@agentproto/runtime 0.1.0 → 0.3.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.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/agentproto-dir.ts","../src/command-tools.ts","../src/conversations.ts","../src/events.ts","../src/fs-tools.ts","../src/workspaces-config.ts","../src/mcp-discovery.ts","../src/mcp-imports.ts","../src/session-tools.ts","../src/heartbeat.ts","../src/http-server.ts","../src/resume-strategies.ts","../src/sessions.ts","../src/mcp-proxy.ts","../src/remote-providers/quick.ts","../src/remote-controller.ts","../src/remote-tools.ts","../src/workspace-fs.ts","../src/index.ts"],"names":["stat","readFile","join","text","mkdir","existsSync","writeFile","resolve","isAbsolute","normalize","relative","z","readdir","fs","homedir","resolvePath","dirname","server","id","spawn","EventEmitter","rt","rm","randomBytes","fsReadFile","fsWriteFile","randomUUID"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AA4DA,eAAsB,gBAAA,CACpB,WACA,IAAA,EACe;AACf,EAAA,MAAM,GAAA,GAAM,IAAA,CAAK,SAAA,EAAW,aAAa,CAAA;AACzC,EAAA,IAAI;AACF,IAAA,MAAM,KAAA,CAAM,GAAA,EAAK,EAAE,SAAA,EAAW,MAAM,CAAA;AAEpC,IAAA,MAAM,SAAA;AAAA,MACJ,IAAA,CAAK,KAAK,cAAc,CAAA;AAAA,MACxB,IAAA,CAAK,SAAA,CAAU,IAAA,EAAM,IAAA,EAAM,CAAC,CAAA,GAAI,IAAA;AAAA,MAChC,EAAE,QAAA,EAAU,MAAA,EAAQ,IAAA,EAAM,GAAA;AAAM,KAClC;AAAA,EACF,SAAS,GAAA,EAAK;AACZ,IAAA,OAAA,CAAQ,KAAA,CAAM,uDAAuD,GAAG,CAAA;AAAA,EAC1E;AACF;AAQA,eAAsB,kBAAkB,SAAA,EAAkC;AACxE,EAAA,IAAI;AACF,IAAA,MAAM,MAAA,CAAO,IAAA,CAAK,SAAA,EAAW,aAAA,EAAe,cAAc,CAAC,CAAA;AAAA,EAC7D,CAAA,CAAA,MAAQ;AAAA,EAER;AACF;AAOA,eAAsB,gBAAgB,SAAA,EAG5B;AACR,EAAA,MAAM,IAAA,GAAO,IAAA,CAAK,SAAA,EAAW,aAAA,EAAe,cAAc,CAAA;AAC1D,EAAA,IAAI;AACF,IAAA,MAAM,CAAC,GAAA,EAAK,EAAE,CAAA,GAAI,MAAM,OAAA,CAAQ,GAAA,CAAI,CAAC,QAAA,CAAS,MAAM,MAAM,CAAA,EAAG,IAAA,CAAK,IAAI,CAAC,CAAC,CAAA;AACxE,IAAA,MAAM,IAAA,GAAO,IAAA,CAAK,KAAA,CAAM,GAAG,CAAA;AAC3B,IAAA,OAAO,EAAE,IAAA,EAAM,KAAA,EAAO,EAAA,CAAG,KAAA,EAAM;AAAA,EACjC,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,IAAA;AAAA,EACT;AACF;AAaA,eAAsB,sBAAA,CACpB,YACA,gBAAA,EACmB;AACnB,EAAA,MAAM,UAAoB,EAAC;AAC3B,EAAA,KAAA,MAAW,MAAM,UAAA,EAAY;AAC3B,IAAA,IAAI,OAAO,gBAAA,EAAkB;AAC7B,IAAA,MAAM,IAAA,GAAO,MAAM,eAAA,CAAgB,EAAE,CAAA;AACrC,IAAA,IAAI,CAAC,IAAA,EAAM;AACX,IAAA,MAAM,GAAA,GAAM,KAAK,IAAA,CAAK,GAAA;AACtB,IAAA,IAAI,OAAO,GAAA,KAAQ,QAAA,IAAY,CAAC,UAAA,CAAW,GAAG,CAAA,EAAG;AAC/C,MAAA,IAAI;AACF,QAAA,MAAM,MAAA,CAAO,IAAA,CAAK,EAAA,EAAI,aAAA,EAAe,cAAc,CAAC,CAAA;AACpD,QAAA,OAAA,CAAQ,IAAA,CAAK,IAAA,CAAK,EAAA,EAAI,aAAA,EAAe,cAAc,CAAC,CAAA;AAAA,MACtD,CAAA,CAAA,MAAQ;AAAA,MAER;AAAA,IACF;AAAA,EACF;AACA,EAAA,OAAO,OAAA;AACT;AAEA,SAAS,WAAW,GAAA,EAAsB;AACxC,EAAA,IAAI;AACF,IAAA,OAAA,CAAQ,IAAA,CAAK,KAAK,CAAC,CAAA;AACnB,IAAA,OAAO,IAAA;AAAA,EACT,SAAS,GAAA,EAAK;AACZ,IAAA,MAAM,OAAQ,GAAA,CAA8B,IAAA;AAC5C,IAAA,IAAI,IAAA,KAAS,SAAS,OAAO,IAAA;AAC7B,IAAA,OAAO,KAAA;AAAA,EACT;AACF;ACvGA,IAAM,kBAAA,GAAqB,GAAA;AAC3B,IAAM,cAAA,GAAiB,GAAA;AACvB,IAAM,aAAA,GAAgB,mCAAA;AAgBtB,IAAI,cAAA,GAAsE,IAAA;AAE1E,eAAe,cAAc,SAAA,EAAyC;AACpE,EAAA,MAAM,IAAA,GAAO,OAAA,CAAQ,SAAA,EAAW,aAAa,CAAA;AAC7C,EAAA,IAAI,CAAC,UAAA,CAAW,IAAI,CAAA,EAAG;AACrB,IAAA,cAAA,GAAiB,IAAA;AACjB,IAAA,2BAAW,GAAA,EAAI;AAAA,EACjB;AACA,EAAA,IAAI;AACF,IAAA,MAAM,CAAA,GAAI,MAAMA,IAAAA,CAAK,IAAI,CAAA;AACzB,IAAA,IACE,cAAA,IACA,eAAe,IAAA,KAAS,IAAA,IACxB,eAAe,KAAA,CAAM,OAAA,KAAY,EAAE,OAAA,EACnC;AACA,MAAA,OAAO,eAAe,KAAA,CAAM,QAAA;AAAA,IAC9B;AACA,IAAA,MAAM,GAAA,GAAM,MAAMC,QAAAA,CAAS,IAAA,EAAM,MAAM,CAAA;AACvC,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,KAAA,CAAM,GAAG,CAAA;AAC7B,IAAA,MAAM,IAAA,GAAO,MAAM,OAAA,CAAQ,MAAA,CAAO,QAAQ,CAAA,GAAI,MAAA,CAAO,WAAW,EAAC;AACjE,IAAA,MAAM,WAAW,IAAI,GAAA;AAAA,MACnB,IAAA,CACG,MAAA,CAAO,CAAC,CAAA,KAAmB,OAAO,CAAA,KAAM,QAAA,IAAY,CAAA,CAAE,MAAA,GAAS,CAAC,CAAA,CAChE,GAAA,CAAI,CAAA,CAAA,KAAK,CAAA,CAAE,MAAM;AAAA,KACtB;AACA,IAAA,cAAA,GAAiB,EAAE,MAAM,KAAA,EAAO,EAAE,SAAS,CAAA,CAAE,OAAA,EAAS,UAAS,EAAE;AACjE,IAAA,OAAO,QAAA;AAAA,EACT,SAAS,GAAA,EAAK;AAGZ,IAAA,OAAA,CAAQ,KAAA;AAAA,MACN,4BAA4B,aAAa,CAAA,iBAAA,CAAA;AAAA,MACzC;AAAA,KACF;AACA,IAAA,cAAA,GAAiB,IAAA;AACjB,IAAA,2BAAW,GAAA,EAAI;AAAA,EACjB;AACF;AAEA,SAAS,cAAc,SAAA,EAA0D;AAC/E,EAAA,MAAM,IAAA,GAAO,QAAQ,SAAS,CAAA;AAC9B,EAAA,OAAO,CAAC,KAAA,KAAmB;AACzB,IAAA,IAAI,CAAC,KAAA,IAAS,KAAA,CAAM,MAAA,KAAW,GAAG,OAAO,IAAA;AACzC,IAAA,MAAM,SAAA,GAAY,UAAA,CAAW,KAAK,CAAA,GAC9B,SAAA,CAAU,KAAK,CAAA,GACf,SAAA,CAAUC,IAAAA,CAAK,IAAA,EAAM,KAAK,CAAC,CAAA;AAC/B,IAAA,MAAM,GAAA,GAAM,QAAA,CAAS,IAAA,EAAM,SAAS,CAAA;AACpC,IAAA,IAAI,IAAI,UAAA,CAAW,IAAI,CAAA,IAAK,UAAA,CAAW,GAAG,CAAA,EAAG;AAC3C,MAAA,MAAM,IAAI,KAAA;AAAA,QACR,CAAA,4BAAA,EAA+B,KAAK,CAAA,aAAA,EAAgB,IAAI,CAAA,CAAA;AAAA,OAC1D;AAAA,IACF;AACA,IAAA,OAAO,SAAA;AAAA,EACT,CAAA;AACF;AAmBO,SAAS,oBAAA,CACd,QACA,IAAA,EACM;AACN,EAAA,MAAM,SAAA,GAAY,aAAA,CAAc,IAAA,CAAK,SAAS,CAAA;AAE9C,EAAA,MAAA,CAAO,IAAA;AAAA,IACL,iBAAA;AAAA,IACA,gTAAA;AAAA,IACA;AAAA,MACE,SAAS,CAAA,CACN,MAAA,EAAO,CACP,GAAA,CAAI,CAAC,CAAA,CACL,QAAA;AAAA,QACC;AAAA,OACF;AAAA,MACF,IAAA,EAAM,EACH,KAAA,CAAM,CAAA,CAAE,QAAQ,CAAA,CAChB,UAAS,CACT,QAAA;AAAA,QACC;AAAA,OACF;AAAA,MACF,GAAA,EAAK,CAAA,CACF,MAAA,EAAO,CACP,UAAS,CACT,QAAA;AAAA,QACC;AAAA,OACF;AAAA,MACF,OAAO,CAAA,CACJ,MAAA,GACA,QAAA,EAAS,CACT,SAAS,8CAA8C,CAAA;AAAA,MAC1D,SAAA,EAAW,CAAA,CACR,MAAA,EAAO,CACP,GAAA,EAAI,CACJ,QAAA,EAAS,CACT,GAAA,CAAI,cAAc,CAAA,CAClB,QAAA,EAAS,CACT,QAAA;AAAA,QACC,CAAA,0CAAA,EAA6C,kBAAkB,CAAA,YAAA,EAAe,cAAc,CAAA,CAAA;AAAA;AAC9F,KACJ;AAAA,IACA,OAAO,EAAE,OAAA,EAAS,MAAM,GAAA,EAAK,KAAA,EAAO,WAAU,KAAM;AAClD,MAAA,MAAM,SAAA,GAAY,MAAM,aAAA,CAAc,IAAA,CAAK,SAAS,CAAA;AACpD,MAAA,MAAM,QAAA,GAAW,SAAS,OAAO,CAAA;AACjC,MAAA,IAAI,CAAC,SAAA,CAAU,GAAA,CAAI,QAAQ,CAAA,EAAG;AAC5B,QAAA,MAAM,OAAA,GAAU,CAAC,GAAG,SAAS,EAAE,IAAA,EAAK,CAAE,IAAA,CAAK,IAAI,CAAA,IAAK,SAAA;AACpD,QAAA,MAAM,IAAI,KAAA;AAAA,UACR,CAAA,SAAA,EAAY,QAAQ,CAAA,qCAAA,EACLA,IAAAA,CAAK,KAAK,SAAA,EAAW,aAAa,CAAC,CAAA,6CAAA,EACD,OAAO,CAAA,CAAA;AAAA,SAC1D;AAAA,MACF;AACA,MAAA,MAAM,WAAA,GAAc,UAAU,GAAG,CAAA;AACjC,MAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,GAAA,CAAI,SAAA,IAAa,oBAAoB,cAAc,CAAA;AACtE,MAAA,MAAM,MAAA,GAAS,MAAM,UAAA,CAAW;AAAA,QAC9B,OAAA;AAAA,QACA,IAAA,EAAM,QAAQ,EAAC;AAAA,QACf,GAAA,EAAK,WAAA;AAAA,QACL,KAAA;AAAA,QACA,SAAA,EAAW;AAAA,OACZ,CAAA;AACD,MAAA,OAAO;AAAA,QACL,OAAA,EAAS,CAAC,EAAE,IAAA,EAAM,MAAA,EAAiB,MAAM,IAAA,CAAK,SAAA,CAAU,MAAM,CAAA,EAAG;AAAA,OACnE;AAAA,IACF;AAAA,GACF;AACF;AAUA,IAAM,iBAAA,GAAoB,OAAA;AAE1B,eAAe,WAAW,KAAA,EAAgD;AACxE,EAAA,OAAO,IAAI,QAAuB,CAAA,cAAA,KAAkB;AAClD,IAAA,MAAM,SAAA,GAAY,KAAK,GAAA,EAAI;AAC3B,IAAA,MAAM,KAAA,GAAQ,KAAA,CAAM,KAAA,CAAM,OAAA,EAAS,MAAM,IAAA,EAAM;AAAA,MAC7C,KAAK,KAAA,CAAM,GAAA;AAAA,MACX,KAAA,EAAO,KAAA;AAAA;AAAA,MAEP,KAAK,OAAA,CAAQ,GAAA;AAAA,MACb,KAAA,EAAO,CAAC,MAAA,EAAQ,MAAA,EAAQ,MAAM;AAAA,KAC/B,CAAA;AAED,IAAA,IAAI,MAAA,GAAS,EAAA;AACb,IAAA,IAAI,MAAA,GAAS,EAAA;AACb,IAAA,IAAI,SAAA,GAAY,KAAA;AAChB,IAAA,IAAI,QAAA,GAAW,KAAA;AAEf,IAAA,SAAS,YAAA,CAAa,KAAa,KAAA,EAAuB;AACxD,MAAA,IAAI,GAAA,CAAI,UAAU,iBAAA,EAAmB;AACnC,QAAA,SAAA,GAAY,IAAA;AACZ,QAAA,OAAO,GAAA;AAAA,MACT;AACA,MAAA,MAAM,IAAA,GAAO,oBAAoB,GAAA,CAAI,MAAA;AACrC,MAAA,MAAMC,KAAAA,GAAO,KAAA,CAAM,QAAA,CAAS,MAAM,CAAA;AAClC,MAAA,IAAIA,KAAAA,CAAK,SAAS,IAAA,EAAM;AACtB,QAAA,SAAA,GAAY,IAAA;AACZ,QAAA,OAAO,GAAA,GAAMA,KAAAA,CAAK,KAAA,CAAM,CAAA,EAAG,IAAI,CAAA;AAAA,MACjC;AACA,MAAA,OAAO,GAAA,GAAMA,KAAAA;AAAA,IACf;AACA,IAAA,KAAA,CAAM,MAAA,EAAQ,EAAA,CAAG,MAAA,EAAQ,CAAA,CAAA,KAAK;AAC5B,MAAA,MAAA,GAAS,YAAA,CAAa,QAAQ,CAAC,CAAA;AAAA,IACjC,CAAC,CAAA;AACD,IAAA,KAAA,CAAM,MAAA,EAAQ,EAAA,CAAG,MAAA,EAAQ,CAAA,CAAA,KAAK;AAC5B,MAAA,MAAA,GAAS,YAAA,CAAa,QAAQ,CAAC,CAAA;AAAA,IACjC,CAAC,CAAA;AAED,IAAA,IAAI,MAAM,KAAA,EAAO;AACf,MAAA,KAAA,CAAM,KAAA,EAAO,KAAA,CAAM,KAAA,CAAM,KAAK,CAAA;AAAA,IAChC;AACA,IAAA,KAAA,CAAM,OAAO,GAAA,EAAI;AAEjB,IAAA,MAAM,KAAA,GAAQ,WAAW,MAAM;AAC7B,MAAA,QAAA,GAAW,IAAA;AAGX,MAAA,IAAI;AACF,QAAA,KAAA,CAAM,KAAK,SAAS,CAAA;AAAA,MACtB,CAAA,CAAA,MAAQ;AAAA,MAER;AAEA,MAAA,UAAA,CAAW,MAAM;AACf,QAAA,IAAI;AACF,UAAA,KAAA,CAAM,KAAK,SAAS,CAAA;AAAA,QACtB,CAAA,CAAA,MAAQ;AAAA,QAER;AAAA,MACF,CAAA,EAAG,GAAK,CAAA,CAAE,KAAA,EAAM;AAAA,IAClB,CAAA,EAAG,MAAM,SAAS,CAAA;AAClB,IAAA,KAAA,CAAM,KAAA,EAAM;AAEZ,IAAA,KAAA,CAAM,EAAA,CAAG,SAAS,CAAA,GAAA,KAAO;AACvB,MAAA,YAAA,CAAa,KAAK,CAAA;AAGlB,MAAA,cAAA,CAAe;AAAA,QACb,QAAA,EAAU,EAAA;AAAA,QACV,MAAA,EAAQ,IAAA;AAAA,QACR,MAAA;AAAA,QACA,MAAA,EAAQ,MAAA,IAAU,MAAA,GAAS,IAAA,GAAO,MAAO,GAAA,CAAc,OAAA;AAAA,QACvD,SAAA;AAAA,QACA,UAAA,EAAY,IAAA,CAAK,GAAA,EAAI,GAAI;AAAA,OAC1B,CAAA;AAAA,IACH,CAAC,CAAA;AACD,IAAA,KAAA,CAAM,EAAA,CAAG,OAAA,EAAS,CAAC,IAAA,EAAM,MAAA,KAAW;AAClC,MAAA,YAAA,CAAa,KAAK,CAAA;AAClB,MAAA,cAAA,CAAe;AAAA,QACb,QAAA,EAAU,OAAO,IAAA,KAAS,QAAA,GAAW,IAAA,GAAO,EAAA;AAAA,QAC5C,MAAA,EAAQ,MAAA,KAAW,QAAA,GAAW,iBAAA,GAAoB,IAAA,CAAA;AAAA,QAClD,MAAA;AAAA,QACA,MAAA;AAAA,QACA,SAAA;AAAA,QACA,UAAA,EAAY,IAAA,CAAK,GAAA,EAAI,GAAI;AAAA,OAC1B,CAAA;AAAA,IACH,CAAC,CAAA;AAAA,EACH,CAAC,CAAA;AACH;AC/RA,IAAM,cAAA,GAAiB,yBAAA;AA8ChB,SAAS,sBACd,IAAA,EACmB;AACnB,EAAA,MAAM,MAAM,IAAA,CAAK,GAAA,IAAOD,IAAAA,CAAK,IAAA,CAAK,WAAW,eAAe,CAAA;AAE5D,EAAA,MAAM,WAAW,CAAC,EAAA,KAAeA,KAAK,GAAA,EAAK,CAAA,EAAG,EAAE,CAAA,GAAA,CAAK,CAAA;AAErD,EAAA,OAAO;AAAA,IACL,OAAA,EAAS,QAAA;AAAA,IAET,MAAM,IAAA,CAAK,EAAA,EAAI,IAAA,EAAM;AACnB,MAAA,MAAME,KAAAA,CAAM,GAAA,EAAK,EAAE,SAAA,EAAW,MAAM,CAAA;AACpC,MAAA,MAAM,IAAA,GAAO,SAAS,EAAE,CAAA;AACxB,MAAA,IAAIC,UAAAA,CAAW,IAAI,CAAA,EAAG;AACtB,MAAA,MAAM,SAAS,YAAA,CAAa;AAAA,QAC1B,EAAA;AAAA,QACA,OAAO,IAAA,CAAK,KAAA;AAAA,QACZ,OAAA,EAAA,iBAAS,IAAI,IAAA,EAAK,EAAE,WAAA,EAAY;AAAA,QAChC,MAAA,EAAQ;AAAA,OACT,CAAA;AACD,MAAA,MAAMC,SAAAA,CAAU,IAAA,EAAM,MAAA,EAAQ,MAAM,CAAA;AAAA,IACtC,CAAA;AAAA,IAEA,MAAM,UAAA,CAAW,EAAA,EAAI,IAAA,EAAM,SAAS,OAAA,EAAS;AAC3C,MAAA,MAAM,IAAA,GAAO,SAAS,EAAE,CAAA;AAGxB,MAAA,IAAI,CAACD,UAAAA,CAAW,IAAI,CAAA,EAAG;AACrB,QAAA,MAAM,IAAA,CAAK,KAAK,EAAA,EAAI,EAAE,OAAO,OAAA,EAAS,WAAA,IAAe,WAAW,CAAA;AAAA,MAClE;AACA,MAAA,MAAM,QAAQ,UAAA,CAAW;AAAA,QACvB,IAAA;AAAA,QACA,IAAI,OAAA,EAAS,EAAA,IAAA,iBAAM,IAAI,IAAA,IAAO,WAAA,EAAY;AAAA,QAC1C,aAAa,OAAA,EAAS,WAAA;AAAA,QACtB;AAAA,OACD,CAAA;AAGD,MAAA,MAAMC,SAAAA,CAAU,MAAM,KAAA,EAAO,EAAE,UAAU,MAAA,EAAQ,IAAA,EAAM,KAAK,CAAA;AAAA,IAC9D,CAAA;AAAA,IAEA,MAAM,KAAK,EAAA,EAAI;AACb,MAAA,MAAM,IAAA,GAAO,SAAS,EAAE,CAAA;AACxB,MAAA,MAAM,MAAA,GAAS,MAAML,QAAAA,CAAS,IAAA,EAAM,MAAM,CAAA;AAC1C,MAAA,OAAO,iBAAA,CAAkB,QAAQ,EAAE,CAAA;AAAA,IACrC,CAAA;AAAA,IAEA,MAAM,IAAA,GAAO;AACX,MAAA,IAAI,CAACI,UAAAA,CAAW,GAAG,CAAA,SAAU,EAAC;AAC9B,MAAA,MAAM,UAAU,MAAM,OAAA,CAAQ,KAAK,EAAE,aAAA,EAAe,MAAM,CAAA;AAC1D,MAAA,MAAM,MAAqD,EAAC;AAC5D,MAAA,KAAA,MAAW,SAAS,OAAA,EAAS;AAC3B,QAAA,IAAI,CAAC,MAAM,MAAA,EAAO,IAAK,CAAC,KAAA,CAAM,IAAA,CAAK,QAAA,CAAS,KAAK,CAAA,EAAG;AACpD,QAAA,MAAM,EAAA,GAAK,KAAA,CAAM,IAAA,CAAK,KAAA,CAAM,GAAG,EAAE,CAAA;AACjC,QAAA,IAAI;AACF,UAAA,MAAM,MAAA,GAAS,MAAMJ,QAAAA,CAASC,IAAAA,CAAK,KAAK,KAAA,CAAM,IAAI,GAAG,MAAM,CAAA;AAC3D,UAAA,MAAM,EAAE,IAAA,EAAK,GAAI,iBAAA,CAAkB,QAAQ,EAAE,CAAA;AAC7C,UAAA,GAAA,CAAI,IAAA,CAAK,EAAE,EAAA,EAAI,IAAA,EAAM,CAAA;AAAA,QACvB,CAAA,CAAA,MAAQ;AAAA,QAER;AAAA,MACF;AACA,MAAA,OAAO,GAAA;AAAA,IACT;AAAA,GACF;AACF;AAIA,SAAS,aAAa,IAAA,EAAgC;AACpD,EAAA,OAAO;AAAA,IACL,KAAA;AAAA,IACA,CAAA,uBAAA,CAAA;AAAA,IACA,CAAA,IAAA,EAAO,KAAK,EAAE,CAAA,CAAA;AAAA,IACd,CAAA,OAAA,EAAU,KAAK,KAAK,CAAA,CAAA;AAAA,IACpB,CAAA,SAAA,EAAY,KAAK,OAAO,CAAA,CAAA;AAAA,IACxB,CAAA,QAAA,EAAW,KAAK,MAAM,CAAA,CAAA;AAAA,IACtB,KAAA;AAAA,IACA,EAAA;AAAA,IACA;AAAA,GACF,CAAE,KAAK,IAAI,CAAA;AACb;AAEA,SAAS,WAAW,IAAA,EAAgC;AAClD,EAAA,MAAM,UAAU,IAAA,CAAK,WAAA,GACjB,MAAM,IAAA,CAAK,IAAI,WAAM,IAAA,CAAK,EAAE,CAAA,EAAA,EAAK,IAAA,CAAK,WAAW,CAAA,CAAA,CAAA,GACjD,CAAA,GAAA,EAAM,KAAK,IAAI,CAAA,QAAA,EAAM,KAAK,EAAE,CAAA,CAAA;AAChC,EAAA,OAAO,GAAG,OAAO;;AAAA,EAAO,IAAA,CAAK,OAAA,CAAQ,OAAA,EAAS;;AAAA,CAAA;AAChD;AASA,SAAS,iBAAA,CAAkB,QAAgB,UAAA,EAAwC;AACjF,EAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,KAAA,CAAM,cAAc,CAAA;AACzC,EAAA,IAAI,IAAA,GAAyB;AAAA,IAC3B,EAAA,EAAI,UAAA;AAAA,IACJ,KAAA,EAAO,SAAA;AAAA,IACP,OAAA,EAAS,EAAA;AAAA,IACT,MAAA,EAAQ;AAAA,GACV;AACA,EAAA,IAAI,IAAA,GAAO,MAAA;AACX,EAAA,IAAI,KAAA,EAAO;AACT,IAAA,IAAA,GAAO,gBAAA,CAAiB,KAAA,CAAM,CAAC,CAAA,IAAK,IAAI,UAAU,CAAA;AAClD,IAAA,IAAA,GAAO,MAAA,CAAO,KAAA,CAAM,KAAA,CAAM,CAAC,EAAE,MAAM,CAAA;AAAA,EACrC;AAEA,EAAA,MAAM,QAA4B,EAAC;AAGnC,EAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,KAAA,CAAM,IAAI,CAAA;AAC7B,EAAA,IAAI,OAAA,GAAmC,IAAA;AACvC,EAAA,IAAI,SAAmB,EAAC;AAExB,EAAA,MAAM,QAAQ,MAAM;AAClB,IAAA,IAAI,CAAC,OAAA,EAAS;AACd,IAAA,OAAA,CAAQ,OAAA,GAAU,MAAA,CAAO,IAAA,CAAK,IAAI,EAAE,IAAA,EAAK;AACzC,IAAA,KAAA,CAAM,KAAK,OAAO,CAAA;AAClB,IAAA,OAAA,GAAU,IAAA;AACV,IAAA,MAAA,GAAS,EAAC;AAAA,EACZ,CAAA;AAEA,EAAA,MAAM,SAAA,GACJ,kEAAA;AAEF,EAAA,KAAA,MAAW,QAAQ,KAAA,EAAO;AACxB,IAAA,MAAM,CAAA,GAAI,IAAA,CAAK,KAAA,CAAM,SAAS,CAAA;AAC9B,IAAA,IAAI,CAAA,EAAG;AACL,MAAA,KAAA,EAAM;AACN,MAAA,OAAA,GAAU;AAAA,QACR,IAAA,EAAM,EAAE,CAAC,CAAA;AAAA,QACT,EAAA,EAAI,CAAA,CAAE,CAAC,CAAA,IAAK,EAAA;AAAA,QACZ,WAAA,EAAa,EAAE,CAAC,CAAA;AAAA,QAChB,OAAA,EAAS;AAAA,OACX;AACA,MAAA;AAAA,IACF;AACA,IAAA,IAAI,OAAA,EAAS,MAAA,CAAO,IAAA,CAAK,IAAI,CAAA;AAAA,EAC/B;AACA,EAAA,KAAA,EAAM;AAEN,EAAA,OAAO,EAAE,MAAM,KAAA,EAAM;AACvB;AAEA,SAAS,gBAAA,CACP,KACA,UAAA,EACkB;AAClB,EAAA,MAAM,MAA8B,EAAC;AACrC,EAAA,KAAA,MAAW,IAAA,IAAQ,GAAA,CAAI,KAAA,CAAM,IAAI,CAAA,EAAG;AAClC,IAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,OAAA,CAAQ,GAAG,CAAA;AAC9B,IAAA,IAAI,QAAQ,CAAA,EAAG;AACf,IAAA,MAAM,MAAM,IAAA,CAAK,KAAA,CAAM,CAAA,EAAG,KAAK,EAAE,IAAA,EAAK;AACtC,IAAA,MAAM,QAAQ,IAAA,CAAK,KAAA,CAAM,KAAA,GAAQ,CAAC,EAAE,IAAA,EAAK;AACzC,IAAA,GAAA,CAAI,GAAG,CAAA,GAAI,KAAA;AAAA,EACb;AACA,EAAA,OAAO;AAAA,IACL,EAAA,EAAI,IAAI,EAAA,IAAM,UAAA;AAAA,IACd,KAAA,EAAO,IAAI,KAAA,IAAS,SAAA;AAAA,IACpB,OAAA,EAAS,IAAI,OAAA,IAAW,EAAA;AAAA,IACxB,MAAA,EAAS,GAAA,CAAI,MAAA,KAAW,QAAA,GAAW,QAAA,GAAW;AAAA,GAChD;AACF;AChKO,SAAS,mBAAA,GAAqC;AACnD,EAAA,MAAM,EAAA,GAAK,IAAI,YAAA,EAAa;AAC5B,EAAA,EAAA,CAAG,gBAAgB,EAAE,CAAA;AAErB,EAAA,OAAO;AAAA,IACL,EAAA,CAAG,MAAM,OAAA,EAAS;AAChB,MAAA,MAAM,OAAA,GAAU,CAAC,EAAA,KAAqB;AACpC,QAAA,IAAI,EAAA,CAAG,IAAA,KAAS,IAAA,EAAM,OAAA,CAAQ,EAAkD,CAAA;AAAA,MAClF,CAAA;AACA,MAAA,EAAA,CAAG,EAAA,CAAG,SAAS,OAAO,CAAA;AACtB,MAAA,OAAO,MAAM,EAAA,CAAG,GAAA,CAAI,OAAA,EAAS,OAAO,CAAA;AAAA,IACtC,CAAA;AAAA,IACA,MAAM,OAAA,EAAS;AACb,MAAA,EAAA,CAAG,EAAA,CAAG,SAAS,OAAO,CAAA;AACtB,MAAA,OAAO,MAAM,EAAA,CAAG,GAAA,CAAI,OAAA,EAAS,OAAO,CAAA;AAAA,IACtC,CAAA;AAAA,IACA,KAAK,EAAA,EAAI;AACP,MAAA,EAAA,CAAG,IAAA,CAAK,SAAS,EAAE,CAAA;AAAA,IACrB;AAAA,GACF;AACF;ACpDA,IAAM,WAAA,GAAN,cAA0B,KAAA,CAAM;AAAA,EAC9B,YAAY,OAAA,EAAiB;AAC3B,IAAA,KAAA,CAAM,OAAO,CAAA;AACb,IAAA,IAAA,CAAK,IAAA,GAAO,aAAA;AAAA,EACd;AACF,CAAA;AAEA,SAAS,WAAW,SAAA,EAA8C;AAChE,EAAA,MAAM,IAAA,GAAOK,QAAQ,SAAS,CAAA;AAC9B,EAAA,OAAO,CAAC,KAAA,KAAkB;AACxB,IAAA,IAAI,OAAO,KAAA,KAAU,QAAA,IAAY,KAAA,CAAM,WAAW,CAAA,EAAG;AACnD,MAAA,MAAM,IAAI,YAAY,iCAAiC,CAAA;AAAA,IACzD;AACA,IAAA,MAAM,SAAA,GAAYC,UAAAA,CAAW,KAAK,CAAA,GAC9BC,SAAAA,CAAU,KAAK,CAAA,GACfA,SAAAA,CAAUP,IAAAA,CAAK,IAAA,EAAM,KAAK,CAAC,CAAA;AAC/B,IAAA,MAAM,GAAA,GAAMQ,QAAAA,CAAS,IAAA,EAAM,SAAS,CAAA;AACpC,IAAA,IAAI,IAAI,UAAA,CAAW,IAAI,CAAA,IAAKF,UAAAA,CAAW,GAAG,CAAA,EAAG;AAC3C,MAAA,MAAM,IAAI,WAAA,CAAY,CAAA,6BAAA,EAAgC,KAAK,CAAA,CAAA,CAAG,CAAA;AAAA,IAChE;AACA,IAAA,OAAO,SAAA;AAAA,EACT,CAAA;AACF;AAEA,SAAS,KAAK,KAAA,EAEZ;AACA,EAAA,OAAO;AAAA,IACL,OAAA,EAAS;AAAA,MACP;AAAA,QACE,IAAA,EAAM,MAAA;AAAA,QACN,MAAM,OAAO,KAAA,KAAU,WAAW,KAAA,GAAQ,IAAA,CAAK,UAAU,KAAK;AAAA;AAChE;AACF,GACF;AACF;AAEO,SAAS,eAAA,CACd,QACA,IAAA,EACM;AACN,EAAA,MAAM,MAAA,GAAS,UAAA,CAAW,IAAA,CAAK,SAAS,CAAA;AAExC,EAAA,MAAA,CAAO,IAAA;AAAA,IACL,WAAA;AAAA,IACA,uCAAA;AAAA,IACA,EAAE,IAAA,EAAMG,CAAAA,CAAE,QAAO,CAAE,QAAA,CAAS,sCAAsC,CAAA,EAAE;AAAA,IACpE,OAAO,EAAE,IAAA,EAAK,KAAM;AAClB,MAAA,MAAM,GAAA,GAAM,OAAO,IAAI,CAAA;AACvB,MAAA,MAAM,GAAA,GAAM,MAAMV,QAAAA,CAAS,GAAG,CAAA;AAC9B,MAAA,OAAO,IAAA,CAAK,GAAA,CAAI,QAAA,CAAS,MAAM,CAAC,CAAA;AAAA,IAClC;AAAA,GACF;AAEA,EAAA,MAAA,CAAO,IAAA;AAAA,IACL,YAAA;AAAA,IACA,0EAAA;AAAA,IACA;AAAA,MACE,IAAA,EAAMU,CAAAA,CAAE,MAAA,EAAO,CAAE,SAAS,sCAAsC,CAAA;AAAA,MAChE,OAAA,EAASA,CAAAA,CAAE,MAAA,EAAO,CAAE,SAAS,oBAAoB;AAAA,KACnD;AAAA,IACA,OAAO,EAAE,IAAA,EAAM,OAAA,EAAQ,KAAM;AAC3B,MAAA,MAAM,GAAA,GAAM,OAAO,IAAI,CAAA;AACvB,MAAA,MAAMP,MAAM,OAAA,CAAQ,GAAG,GAAG,EAAE,SAAA,EAAW,MAAM,CAAA;AAC7C,MAAA,MAAME,SAAAA,CAAU,GAAA,EAAK,OAAA,EAAS,MAAM,CAAA;AACpC,MAAA,OAAO,KAAK,IAAI,CAAA;AAAA,IAClB;AAAA,GACF;AAEA,EAAA,MAAA,CAAO,IAAA;AAAA,IACL,gBAAA;AAAA,IACA,oJAAA;AAAA,IACA;AAAA,MACE,MAAMK,CAAAA,CACH,MAAA,GACA,QAAA,EAAS,CACT,SAAS,4DAA4D;AAAA,KAC1E;AAAA,IACA,OAAO,EAAE,IAAA,EAAK,KAAM;AAClB,MAAA,MAAM,MAAM,MAAA,CAAO,IAAA,IAAQ,KAAK,MAAA,GAAS,CAAA,GAAI,OAAO,GAAG,CAAA;AACvD,MAAA,MAAM,UAAU,MAAMC,OAAAA,CAAQ,KAAK,EAAE,aAAA,EAAe,MAAM,CAAA;AAC1D,MAAA,MAAM,QAAQ,OAAA,CAAQ,GAAA;AAAA,QAAI,CAAA,CAAA,KACxB,CAAA,CAAE,WAAA,EAAY,GAAI,CAAA,OAAA,EAAU,EAAE,IAAI,CAAA,CAAA,GAAK,CAAA,OAAA,EAAU,CAAA,CAAE,IAAI,CAAA;AAAA,OACzD;AACA,MAAA,OAAO,IAAA,CAAK,KAAA,CAAM,IAAA,CAAK,IAAI,CAAC,CAAA;AAAA,IAC9B;AAAA,GACF;AAEA,EAAA,MAAA,CAAO,IAAA;AAAA,IACL,eAAA;AAAA,IACA,4CAAA;AAAA,IACA,EAAE,IAAA,EAAMD,CAAAA,CAAE,QAAO,CAAE,QAAA,CAAS,0BAA0B,CAAA,EAAE;AAAA,IACxD,OAAO,EAAE,IAAA,EAAK,KAAM;AAClB,MAAA,MAAM,GAAA,GAAM,OAAO,IAAI,CAAA;AACvB,MAAA,MAAM,IAAA,GAAO,MAAMX,IAAAA,CAAK,GAAG,CAAA;AAC3B,MAAA,OAAO,IAAA,CAAK;AAAA,QACV,MAAM,GAAA,CAAI,KAAA,CAAM,GAAG,CAAA,CAAE,KAAI,IAAK,IAAA;AAAA,QAC9B,IAAA;AAAA,QACA,IAAA,EAAM,IAAA,CAAK,WAAA,EAAY,GAAI,WAAA,GAAc,MAAA;AAAA,QACzC,MAAM,IAAA,CAAK,IAAA;AAAA,QACX,QAAA,EAAU,IAAA,CAAK,KAAA,CAAM,WAAA,EAAY;AAAA,QACjC,OAAA,EAAS,IAAA,CAAK,SAAA,CAAU,WAAA;AAAY,OACrC,CAAA;AAAA,IACH;AAAA,GACF;AAEA,EAAA,MAAA,CAAO,IAAA;AAAA,IACL,kBAAA;AAAA,IACA,kDAAA;AAAA,IACA,EAAE,IAAA,EAAMW,CAAAA,CAAE,QAAO,CAAE,QAAA,CAAS,oCAAoC,CAAA,EAAE;AAAA,IAClE,OAAO,EAAE,IAAA,EAAK,KAAM;AAClB,MAAA,MAAM,GAAA,GAAM,OAAO,IAAI,CAAA;AACvB,MAAA,MAAMP,KAAAA,CAAM,GAAA,EAAK,EAAE,SAAA,EAAW,MAAM,CAAA;AACpC,MAAA,OAAO,KAAK,IAAI,CAAA;AAAA,IAClB;AAAA,GACF;AAEA,EAAA,MAAA,CAAO,IAAA;AAAA,IACL,aAAA;AAAA,IACA,oDAAA;AAAA,IACA,EAAE,IAAA,EAAMO,CAAAA,CAAE,QAAO,CAAE,QAAA,CAAS,0BAA0B,CAAA,EAAE;AAAA,IACxD,OAAO,EAAE,IAAA,EAAK,KAAM;AAClB,MAAA,MAAM,GAAA,GAAM,OAAO,IAAI,CAAA;AACvB,MAAA,MAAM,GAAG,GAAA,EAAK,EAAE,WAAW,IAAA,EAAM,KAAA,EAAO,MAAM,CAAA;AAC9C,MAAA,OAAO,KAAK,IAAI,CAAA;AAAA,IAClB;AAAA,GACF;AACF;AC5IO,IAAM,yBAAA,GAA4B,CAAA;AA8BlC,IAAM,kBAAA,GAAqB,MAChCJ,OAAAA,CAAQ,OAAA,IAAW,aAAa,CAAA;AAC3B,IAAM,mBAAA,GAAsB,MACjCA,OAAAA,CAAQ,kBAAA,IAAsB,iBAAiB,CAAA;AAK1C,SAAS,aAAa,KAAA,EAAuB;AAClD,EAAA,MAAM,OAAA,GAAU,KAAA,CAAM,IAAA,EAAK,CAAE,WAAA,EAAY;AACzC,EAAA,MAAM,OAAA,GAAU,OAAA,CACb,OAAA,CAAQ,eAAA,EAAiB,GAAG,CAAA,CAC5B,OAAA,CAAQ,UAAA,EAAY,EAAE,CAAA,CACtB,KAAA,CAAM,CAAA,EAAG,EAAE,CAAA;AAGd,EAAA,OAAO,OAAA,IAAW,WAAA;AACpB;AAKA,eAAsB,oBAAA,CACpB,IAAA,GAAe,mBAAA,EAAoB,EACR;AAC3B,EAAA,IAAI,GAAA;AACJ,EAAA,IAAI;AACF,IAAA,GAAA,GAAM,MAAMM,QAAA,CAAG,QAAA,CAAS,IAAA,EAAM,MAAM,CAAA;AAAA,EACtC,SAAS,GAAA,EAAK;AACZ,IAAA,IAAK,GAAA,CAA8B,SAAS,QAAA,EAAU;AACpD,MAAA,OAAO,EAAE,OAAA,EAAS,yBAAA,EAA2B,UAAA,EAAY,EAAC,EAAE;AAAA,IAC9D;AACA,IAAA,MAAM,GAAA;AAAA,EACR;AACA,EAAA,IAAI,MAAA;AACJ,EAAA,IAAI;AACF,IAAA,MAAA,GAAS,IAAA,CAAK,MAAM,GAAG,CAAA;AAAA,EACzB,SAAS,GAAA,EAAK;AACZ,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,CAAA,YAAA,EAAe,IAAI,CAAA,oBAAA,EACjB,GAAA,YAAe,QAAQ,GAAA,CAAI,OAAA,GAAU,MAAA,CAAO,GAAG,CACjD,CAAA,sCAAA;AAAA,KACF;AAAA,EACF;AACA,EAAA,OAAO,gBAAgB,MAAM,CAAA;AAC/B;AA0FO,SAAS,aAAA,CACd,QACA,IAAA,EAC4B;AAC5B,EAAA,OAAO,MAAA,CAAO,WAAW,IAAA,CAAK,CAAA,CAAA,KAAK,EAAE,IAAA,KAAS,YAAA,CAAa,IAAI,CAAC,CAAA;AAClE;AAIO,SAAS,mBACd,MAAA,EAC4B;AAC5B,EAAA,IAAI,CAAC,MAAA,CAAO,MAAA,EAAQ,OAAO,MAAA,CAAO,WAAW,CAAC,CAAA;AAC9C,EAAA,OAAO,cAAc,MAAA,EAAQ,MAAA,CAAO,MAAM,CAAA,IAAK,MAAA,CAAO,WAAW,CAAC,CAAA;AACpE;AASA,SAAS,gBAAgB,MAAA,EAAmC;AAC1D,EAAA,IAAI,CAAC,MAAA,IAAU,OAAO,MAAA,KAAW,QAAA,EAAU;AACzC,IAAA,OAAO,EAAE,OAAA,EAAS,yBAAA,EAA2B,UAAA,EAAY,EAAC,EAAE;AAAA,EAC9D;AACA,EAAA,MAAM,GAAA,GAAM,MAAA;AACZ,EAAA,MAAM,aAA+B,EAAC;AACtC,EAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,GAAA,CAAI,UAAU,CAAA,EAAG;AACjC,IAAA,KAAA,MAAW,KAAA,IAAS,IAAI,UAAA,EAAY;AAClC,MAAA,IAAI,CAAC,KAAA,IAAS,OAAO,KAAA,KAAU,QAAA,EAAU;AACzC,MAAA,MAAM,CAAA,GAAI,KAAA;AACV,MAAA,MAAM,IAAA,GAAO,OAAO,CAAA,CAAE,IAAA,KAAS,WAAW,YAAA,CAAa,CAAA,CAAE,IAAI,CAAA,GAAI,EAAA;AACjE,MAAA,MAAM,OAAO,OAAO,CAAA,CAAE,IAAA,KAAS,QAAA,GAAW,EAAE,IAAA,GAAO,EAAA;AACnD,MAAA,IAAI,CAAC,IAAA,IAAQ,CAAC,IAAA,EAAM;AACpB,MAAA,MAAM,OAAA,GACJ,OAAO,CAAA,CAAE,OAAA,KAAY,QAAA,GAAW,EAAE,OAAA,GAAA,iBAAU,IAAI,IAAA,EAAK,EAAE,WAAA,EAAY;AACrE,MAAA,MAAM,YAAY,OAAO,CAAA,CAAE,SAAA,KAAc,QAAA,GAAW,EAAE,SAAA,GAAY,OAAA;AAClE,MAAA,MAAM,EAAA,GAAqB,EAAE,IAAA,EAAM,IAAA,EAAM,SAAS,SAAA,EAAU;AAC5D,MAAA,IAAI,OAAO,CAAA,CAAE,KAAA,KAAU,YAAY,CAAA,CAAE,KAAA,CAAM,MAAK,EAAG;AACjD,QAAA,EAAA,CAAG,KAAA,GAAQ,CAAA,CAAE,KAAA,CAAM,IAAA,EAAK;AAAA,MAC1B;AACA,MAAA,UAAA,CAAW,KAAK,EAAE,CAAA;AAAA,IACpB;AAAA,EACF;AAGA,EAAA,MAAM,KAAA,uBAAY,GAAA,EAA4B;AAC9C,EAAA,KAAA,MAAW,KAAK,UAAA,EAAY,KAAA,CAAM,GAAA,CAAI,CAAA,CAAE,MAAM,CAAC,CAAA;AAC/C,EAAA,MAAM,SAAA,GAAY,KAAA,CAAM,IAAA,CAAK,KAAA,CAAM,QAAQ,CAAA;AAC3C,EAAA,MAAM,SACJ,OAAO,GAAA,CAAI,MAAA,KAAW,QAAA,IAAY,UAAU,IAAA,CAAK,CAAA,CAAA,KAAK,CAAA,CAAE,IAAA,KAAS,IAAI,MAAM,CAAA,GACtE,IAAI,MAAA,GACL,SAAA,CAAU,CAAC,CAAA,EAAG,IAAA;AACpB,EAAA,MAAM,GAAA,GAAwB;AAAA,IAC5B,OAAA,EAAS,yBAAA;AAAA,IACT,UAAA,EAAY;AAAA,GACd;AACA,EAAA,IAAI,MAAA,KAAW,MAAA,EAAW,GAAA,CAAI,MAAA,GAAS,MAAA;AACvC,EAAA,OAAO,GAAA;AACT;ACpLA,eAAsB,YAAA,CACpB,IAAA,GAA4B,EAAC,EACH;AAC1B,EAAA,MAAM,IAAA,GAAO,IAAA,CAAK,IAAA,IAAQC,OAAAA,EAAQ;AAClC,EAAA,MAAM,MAAuB,EAAC;AAC9B,EAAA,MAAM,SAAmB,EAAC;AAC1B,EAAA,MAAM,QAAQ,GAAA,CAAI;AAAA,IAChB,cAAA,CAAe,IAAA,EAAM,GAAA,EAAK,MAAM,CAAA;AAAA,IAChC,UAAA,CAAW,IAAA,EAAM,GAAA,EAAK,MAAM,CAAA;AAAA,IAC5B,SAAA,CAAU,IAAA,EAAM,GAAW,CAAA;AAAA,IAC3B,wBAAA,CAAyB,KAAK,MAAM;AAAA,GACrC,CAAA;AAID,EAAA,MAAM,IAAA,uBAAW,GAAA,EAAY;AAC7B,EAAA,MAAM,QAAyB,EAAC;AAChC,EAAA,KAAA,MAAW,KAAK,GAAA,EAAK;AACnB,IAAA,MAAM,GAAA,GAAM,GAAG,CAAA,CAAE,MAAM,IAAI,CAAA,CAAE,KAAK,CAAA,CAAA,EAAI,CAAA,CAAE,IAAI,CAAA,CAAA;AAC5C,IAAA,IAAI,IAAA,CAAK,GAAA,CAAI,GAAG,CAAA,EAAG;AACnB,IAAA,IAAA,CAAK,IAAI,GAAG,CAAA;AACZ,IAAA,KAAA,CAAM,KAAK,CAAC,CAAA;AAAA,EACd;AACA,EAAA,IAAI,MAAA,CAAO,SAAS,CAAA,EAAG;AAGrB,IAAA,KAAA,MAAW,KAAK,MAAA,EAAQ,OAAA,CAAQ,IAAA,CAAK,CAAA,gBAAA,EAAmB,CAAC,CAAA,CAAE,CAAA;AAAA,EAC7D;AACA,EAAA,OAAO,KAAA,CAAM,IAAA,CAAK,CAAC,CAAA,EAAG,CAAA,KAAM;AAC1B,IAAA,IAAI,CAAA,CAAE,WAAW,CAAA,CAAE,MAAA,SAAe,CAAA,CAAE,MAAA,CAAO,aAAA,CAAc,CAAA,CAAE,MAAM,CAAA;AACjE,IAAA,IAAI,CAAA,CAAE,UAAU,CAAA,CAAE,KAAA,SAAc,CAAA,CAAE,KAAA,CAAM,aAAA,CAAc,CAAA,CAAE,KAAK,CAAA;AAC7D,IAAA,OAAO,CAAA,CAAE,IAAA,CAAK,aAAA,CAAc,CAAA,CAAE,IAAI,CAAA;AAAA,EACpC,CAAC,CAAA;AACH;AAcA,eAAe,cAAA,CACb,IAAA,EACA,GAAA,EACA,MAAA,EACe;AACf,EAAA,MAAM,IAAA,GAAOC,OAAA,CAAY,IAAA,EAAM,cAAc,CAAA;AAC7C,EAAA,IAAI,GAAA;AACJ,EAAA,IAAI;AACF,IAAA,GAAA,GAAM,MAAMF,QAAAA,CAAG,QAAA,CAAS,IAAA,EAAM,MAAM,CAAA;AAAA,EACtC,SAAS,GAAA,EAAK;AACZ,IAAA,IAAK,GAAA,CAA8B,SAAS,QAAA,EAAU;AACtD,IAAA,MAAA,CAAO,KAAK,CAAA,kBAAA,EAAqB,IAAI,CAAA,QAAA,EAAO,GAAA,CAAc,OAAO,CAAA,CAAE,CAAA;AACnE,IAAA;AAAA,EACF;AACA,EAAA,IAAI,MAAA;AACJ,EAAA,IAAI;AACF,IAAA,MAAA,GAAS,IAAA,CAAK,MAAM,GAAG,CAAA;AAAA,EACzB,SAAS,GAAA,EAAK;AACZ,IAAA,MAAA,CAAO,KAAK,CAAA,wBAAA,EAA2B,IAAI,CAAA,QAAA,EAAO,GAAA,CAAc,OAAO,CAAA,CAAE,CAAA;AACzE,IAAA;AAAA,EACF;AACA,EAAA,IAAI,CAAC,MAAA,IAAU,OAAO,MAAA,KAAW,QAAA,EAAU;AAC3C,EAAA,MAAM,IAAA,GAAO,MAAA;AACb,EAAA,MAAM,MAAM,IAAA,CAAK,UAAA;AACjB,EAAA,IAAI,GAAA,IAAO,OAAO,GAAA,KAAQ,QAAA,EAAU;AAClC,IAAA,UAAA,CAAW;AAAA,MACT,GAAA;AAAA,MACA,MAAA,EAAQ,aAAA;AAAA,MACR,KAAA,EAAO,QAAA;AAAA,MACP,GAAA,EAAK;AAAA,KACN,CAAA;AAAA,EACH;AACA,EAAA,MAAM,WAAW,IAAA,CAAK,QAAA;AACtB,EAAA,IAAI,QAAA,IAAY,OAAO,QAAA,KAAa,QAAA,EAAU;AAC5C,IAAA,KAAA,MAAW,CAAC,QAAA,EAAU,IAAI,CAAA,IAAK,MAAA,CAAO,OAAA;AAAA,MACpC;AAAA,KACF,EAAG;AACD,MAAA,IAAI,CAAC,IAAA,IAAQ,OAAO,IAAA,KAAS,QAAA,EAAU;AACvC,MAAA,MAAM,WAAY,IAAA,CAAiC,UAAA;AACnD,MAAA,IAAI,CAAC,QAAA,IAAY,OAAO,QAAA,KAAa,QAAA,EAAU;AAC/C,MAAA,UAAA,CAAW;AAAA,QACT,GAAA;AAAA,QACA,MAAA,EAAQ,aAAA;AAAA,QACR,KAAA,EAAO,WAAW,QAAQ,CAAA,CAAA;AAAA,QAC1B,GAAA,EAAK;AAAA,OACN,CAAA;AAAA,IACH;AAAA,EACF;AACF;AAKA,eAAe,UAAA,CACb,IAAA,EACA,GAAA,EACA,MAAA,EACe;AACf,EAAA,MAAM,IAAA,GAAOE,OAAA,CAAY,IAAA,EAAM,SAAA,EAAW,UAAU,CAAA;AACpD,EAAA,IAAI,GAAA;AACJ,EAAA,IAAI;AACF,IAAA,GAAA,GAAM,MAAMF,QAAAA,CAAG,QAAA,CAAS,IAAA,EAAM,MAAM,CAAA;AAAA,EACtC,SAAS,GAAA,EAAK;AACZ,IAAA,IAAK,GAAA,CAA8B,SAAS,QAAA,EAAU;AACtD,IAAA,MAAA,CAAO,KAAK,CAAA,aAAA,EAAgB,IAAI,CAAA,QAAA,EAAO,GAAA,CAAc,OAAO,CAAA,CAAE,CAAA;AAC9D,IAAA;AAAA,EACF;AACA,EAAA,IAAI,MAAA;AACJ,EAAA,IAAI;AACF,IAAA,MAAA,GAAS,IAAA,CAAK,MAAM,GAAG,CAAA;AAAA,EACzB,SAAS,GAAA,EAAK;AACZ,IAAA,MAAA,CAAO,KAAK,CAAA,mBAAA,EAAsB,IAAI,CAAA,QAAA,EAAO,GAAA,CAAc,OAAO,CAAA,CAAE,CAAA;AACpE,IAAA;AAAA,EACF;AACA,EAAA,IAAI,CAAC,MAAA,IAAU,OAAO,MAAA,KAAW,QAAA,EAAU;AAC3C,EAAA,MAAM,IAAA,GAAO,MAAA;AACb,EAAA,MAAM,MAAM,IAAA,CAAK,UAAA;AACjB,EAAA,IAAI,GAAA,IAAO,OAAO,GAAA,KAAQ,QAAA,EAAU;AAClC,IAAA,UAAA,CAAW;AAAA,MACT,GAAA;AAAA,MACA,MAAA,EAAQ,QAAA;AAAA,MACR,KAAA,EAAO,QAAA;AAAA,MACP;AAAA,KACD,CAAA;AAAA,EACH;AACF;AAOA,eAAe,SAAA,CACb,IAAA,EACA,GAAA,EACA,MAAA,EACe;AAEf,EAAA,MAAM,IAAA,GAAOE,OAAA,CAAY,IAAA,EAAM,SAAA,EAAW,SAAS,aAAa,CAAA;AAChE,EAAA,IAAI;AACF,IAAA,MAAMF,QAAAA,CAAG,OAAO,IAAI,CAAA;AAAA,EACtB,CAAA,CAAA,MAAQ;AACN,IAAA;AAAA,EACF;AAKA,EAAA,GAAA,CAAI,IAAA,CAAK;AAAA,IACP,EAAA,EAAI,wBAAA;AAAA,IACJ,MAAA,EAAQ,OAAA;AAAA,IACR,KAAA,EAAO,QAAA;AAAA,IACP,IAAA,EAAM,yBAAA;AAAA,IACN,IAAA,EAAM,SAAA;AAAA,IACN,SAAA,EACE;AAAA,GAEH,CAAA;AACH;AASA,eAAe,wBAAA,CACb,KACA,MAAA,EACe;AACf,EAAA,IAAI,aAA+B,EAAC;AACpC,EAAA,IAAI;AACF,IAAA,MAAM,GAAA,GAAM,MAAM,oBAAA,EAAqB;AACvC,IAAA,UAAA,GAAa,GAAA,CAAI,UAAA;AAAA,EACnB,SAAS,GAAA,EAAK;AACZ,IAAA,MAAA,CAAO,IAAA,CAAK,CAAA,+BAAA,EAA8B,GAAA,CAAc,OAAO,CAAA,CAAE,CAAA;AACjE,IAAA;AAAA,EACF;AAIA,EAAA,MAAM,OAAA,CAAQ,GAAA;AAAA,IACZ,UAAA,CAAW,GAAA,CAAI,OAAM,EAAA,KAAM;AACzB,MAAA,MAAM,UAAA,GAAa;AAAA,QACjBE,OAAA,CAAY,EAAA,CAAG,IAAA,EAAM,WAAW,CAAA;AAAA,QAChCA,OAAA,CAAY,EAAA,CAAG,IAAA,EAAM,SAAA,EAAW,UAAU,CAAA;AAAA,QAC1CA,OAAA,CAAY,EAAA,CAAG,IAAA,EAAM,SAAA,EAAW,UAAU;AAAA,OAC5C;AACA,MAAA,KAAA,MAAW,QAAQ,UAAA,EAAY;AAC7B,QAAA,IAAI,GAAA;AACJ,QAAA,IAAI;AACF,UAAA,GAAA,GAAM,MAAMF,QAAAA,CAAG,QAAA,CAAS,IAAA,EAAM,MAAM,CAAA;AAAA,QACtC,SAAS,GAAA,EAAK;AACZ,UAAA,IAAK,GAAA,CAA8B,SAAS,QAAA,EAAU;AACtD,UAAA,MAAA,CAAO,IAAA;AAAA,YACL,aAAa,EAAA,CAAG,IAAI,UAAU,IAAI,CAAA,QAAA,EAAO,IAAc,OAAO,CAAA;AAAA,WAChE;AACA,UAAA;AAAA,QACF;AACA,QAAA,IAAI,MAAA;AACJ,QAAA,IAAI;AACF,UAAA,MAAA,GAAS,IAAA,CAAK,MAAM,GAAG,CAAA;AAAA,QACzB,SAAS,GAAA,EAAK;AACZ,UAAA,MAAA,CAAO,IAAA;AAAA,YACL,aAAa,EAAA,CAAG,IAAI,gBAAgB,IAAI,CAAA,QAAA,EAAO,IAAc,OAAO,CAAA;AAAA,WACtE;AACA,UAAA;AAAA,QACF;AACA,QAAA,IAAI,CAAC,MAAA,IAAU,OAAO,MAAA,KAAW,QAAA,EAAU;AAC3C,QAAA,MAAM,MAAO,MAAA,CAAmC,UAAA;AAChD,QAAA,IAAI,CAAC,GAAA,IAAO,OAAO,GAAA,KAAQ,QAAA,EAAU;AACrC,QAAA,UAAA,CAAW;AAAA,UACT,GAAA;AAAA,UACA,MAAA,EAAQ,WAAA;AAAA,UACR,KAAA,EAAO,CAAA,UAAA,EAAa,EAAA,CAAG,IAAI,CAAA,CAAA;AAAA,UAC3B;AAAA,SACD,CAAA;AAAA,MACH;AAAA,IACF,CAAC;AAAA,GACH;AACF;AAEA,SAAS,WAAW,IAAA,EAKX;AACP,EAAA,KAAA,MAAW,CAAC,MAAM,GAAG,CAAA,IAAK,OAAO,OAAA,CAAQ,IAAA,CAAK,GAAG,CAAA,EAAG;AAClD,IAAA,IAAI,CAAC,GAAA,IAAO,OAAO,GAAA,KAAQ,QAAA,EAAU;AACrC,IAAA,MAAM,KAAA,GAAQ,GAAA;AACd,IAAA,MAAM,EAAA,GAAK,GAAG,IAAA,CAAK,MAAM,IAAI,IAAA,CAAK,KAAK,IAAI,IAAI,CAAA,CAAA;AAC/C,IAAA,MAAM,WAAW,OAAO,KAAA,CAAM,IAAA,KAAS,QAAA,GAAW,MAAM,IAAA,GAAO,IAAA;AAC/D,IAAA,MAAM,MAAM,OAAO,KAAA,CAAM,GAAA,KAAQ,QAAA,GAAW,MAAM,GAAA,GAAM,MAAA;AACxD,IAAA,MAAM,UAAU,OAAO,KAAA,CAAM,OAAA,KAAY,QAAA,GAAW,MAAM,OAAA,GAAU,MAAA;AACpE,IAAA,IAAI,IAAA;AACJ,IAAA,IAAI,QAAA,KAAa,MAAA,IAAU,QAAA,KAAa,KAAA,IAAS,aAAa,OAAA,EAAS;AACrE,MAAA,IAAA,GAAO,QAAA;AAAA,IACT,WAAW,GAAA,EAAK;AACd,MAAA,IAAA,GAAO,MAAA;AAAA,IACT,WAAW,OAAA,EAAS;AAClB,MAAA,IAAA,GAAO,OAAA;AAAA,IACT,CAAA,MAAO;AACL,MAAA,IAAA,GAAO,SAAA;AAAA,IACT;AACA,IAAA,MAAM,CAAA,GAAmB;AAAA,MACvB,EAAA;AAAA,MACA,QAAQ,IAAA,CAAK,MAAA;AAAA,MACb,OAAO,IAAA,CAAK,KAAA;AAAA,MACZ,IAAA;AAAA,MACA;AAAA,KACF;AACA,IAAA,IAAI,OAAA,KAAY,MAAA,EAAW,CAAA,CAAE,OAAA,GAAU,OAAA;AACvC,IAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,KAAA,CAAM,IAAI,CAAA,EAAG;AAC7B,MAAA,CAAA,CAAE,IAAA,GAAO,MAAM,IAAA,CAAK,MAAA,CAAO,CAAC,CAAA,KAAmB,OAAO,MAAM,QAAQ,CAAA;AAAA,IACtE;AACA,IAAA,IAAI,KAAA,CAAM,GAAA,IAAO,OAAO,KAAA,CAAM,QAAQ,QAAA,EAAU;AAC9C,MAAA,CAAA,CAAE,GAAA,GAAM,eAAA,CAAgB,KAAA,CAAM,GAAG,CAAA;AAAA,IACnC;AACA,IAAA,IAAI,GAAA,KAAQ,MAAA,EAAW,CAAA,CAAE,GAAA,GAAM,GAAA;AAC/B,IAAA,IAAI,KAAA,CAAM,OAAA,IAAW,OAAO,KAAA,CAAM,YAAY,QAAA,EAAU;AACtD,MAAA,CAAA,CAAE,OAAA,GAAU,eAAA,CAAgB,KAAA,CAAM,OAAO,CAAA;AAAA,IAC3C;AACA,IAAA,IAAI,SAAS,SAAA,EAAW;AACtB,MAAA,CAAA,CAAE,SAAA,GACA,2EAAA;AAAA,IACJ;AACA,IAAA,IAAA,CAAK,GAAA,CAAI,KAAK,CAAC,CAAA;AAAA,EACjB;AACF;AAEA,SAAS,gBACP,GAAA,EACwB;AACxB,EAAA,MAAM,MAA8B,EAAC;AACrC,EAAA,KAAA,MAAW,CAAC,CAAA,EAAG,CAAC,KAAK,MAAA,CAAO,OAAA,CAAQ,GAAG,CAAA,EAAG;AACxC,IAAA,IAAI,OAAO,CAAA,KAAM,QAAA,EAAU,GAAA,CAAI,CAAC,CAAA,GAAI,CAAA;AAAA,SAAA,IAC3B,KAAK,IAAA,EAAM,GAAA,CAAI,CAAC,CAAA,GAAI,OAAO,CAAC,CAAA;AAAA,EACvC;AACA,EAAA,OAAO,GAAA;AACT;ACnUO,IAAM,qBAAqB,MAChCE,OAAAA,CAAYD,OAAAA,EAAQ,EAAG,eAAe,oBAAoB,CAAA;AAErD,IAAM,qBAAA,GAAwB,CAAA;AAcrC,IAAM,KAAA,GAA4B;AAAA,EAChC,OAAA,EAAS,qBAAA;AAAA,EACT,SAAS;AACX,CAAA;AAEA,eAAsB,gBAAA,CACpB,IAAA,GAAe,kBAAA,EAAmB,EACL;AAC7B,EAAA,IAAI,GAAA;AACJ,EAAA,IAAI;AACF,IAAA,GAAA,GAAM,MAAMD,QAAAA,CAAG,QAAA,CAAS,IAAA,EAAM,MAAM,CAAA;AAAA,EACtC,SAAS,GAAA,EAAK;AACZ,IAAA,IAAK,GAAA,CAA8B,IAAA,KAAS,QAAA,EAAU,OAAO,KAAA;AAC7D,IAAA,MAAM,GAAA;AAAA,EACR;AACA,EAAA,IAAI,MAAA;AACJ,EAAA,IAAI;AACF,IAAA,MAAA,GAAS,IAAA,CAAK,MAAM,GAAG,CAAA;AAAA,EACzB,SAAS,GAAA,EAAK;AACZ,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,CAAA,YAAA,EAAe,IAAI,CAAA,oBAAA,EACjB,GAAA,YAAe,QAAQ,GAAA,CAAI,OAAA,GAAU,MAAA,CAAO,GAAG,CACjD,CAAA,0BAAA;AAAA,KACF;AAAA,EACF;AACA,EAAA,OAAOJ,WAAU,MAAM,CAAA;AACzB;AAEA,eAAsB,gBAAA,CACpB,MAAA,EACA,IAAA,GAAe,kBAAA,EAAmB,EACnB;AACf,EAAA,MAAMI,QAAAA,CAAG,MAAMG,OAAAA,CAAQ,IAAI,GAAG,EAAE,SAAA,EAAW,MAAM,CAAA;AACjD,EAAA,MAAM,GAAA,GAAM,CAAA,EAAG,IAAI,CAAA,KAAA,EAAQ,QAAQ,GAAG,CAAA,CAAA;AACtC,EAAA,MAAMH,QAAAA,CAAG,SAAA,CAAU,GAAA,EAAK,IAAA,CAAK,SAAA,CAAU,QAAQ,IAAA,EAAM,CAAC,CAAA,GAAI,IAAA,EAAM,MAAM,CAAA;AACtE,EAAA,MAAMA,QAAAA,CAAG,MAAA,CAAO,GAAA,EAAK,IAAI,CAAA;AAC3B;AAOO,SAAS,SAAA,CACd,QACA,KAAA,EACoB;AACpB,EAAA,MAAM,SAAS,KAAA,CAAM,KAAA,IAAS,KAAA,CAAM,QAAA,CAAS,MAAM,IAAA,EAAK;AACxD,EAAA,IAAI,CAAC,KAAA,EAAO;AACV,IAAA,MAAM,IAAI,MAAM,2CAA2C,CAAA;AAAA,EAC7D;AACA,EAAA,MAAM,OAAA,GAAA,iBAAU,IAAI,IAAA,EAAK,EAAE,WAAA,EAAY;AACvC,EAAA,MAAM,IAAA,GAAyB;AAAA,IAC7B,EAAA,EAAI,MAAM,QAAA,CAAS,EAAA;AAAA,IACnB,KAAA;AAAA,IACA,OAAA;AAAA,IACA,UAAU,KAAA,CAAM;AAAA,GAClB;AACA,EAAA,MAAM,MAAA,GAAS,OAAO,OAAA,CAAQ,MAAA,CAAO,OAAK,CAAA,CAAE,EAAA,KAAO,KAAA,CAAM,QAAA,CAAS,EAAE,CAAA;AACpE,EAAA,OAAO,EAAE,GAAG,MAAA,EAAQ,OAAA,EAAS,CAAC,GAAG,MAAA,EAAQ,IAAI,CAAA,EAAE;AACjD;AAEO,SAAS,YAAA,CACd,QACA,EAAA,EACoB;AACpB,EAAA,OAAO,EAAE,GAAG,MAAA,EAAQ,OAAA,EAAS,MAAA,CAAO,OAAA,CAAQ,MAAA,CAAO,CAAA,CAAA,KAAK,CAAA,CAAE,EAAA,KAAO,EAAE,CAAA,EAAE;AACvE;AASA,SAASJ,WAAU,MAAA,EAAqC;AACtD,EAAA,IAAI,CAAC,MAAA,IAAU,OAAO,MAAA,KAAW,UAAU,OAAO,KAAA;AAClD,EAAA,MAAM,GAAA,GAAM,MAAA;AACZ,EAAA,MAAM,UAA8B,EAAC;AACrC,EAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,GAAA,CAAI,OAAO,CAAA,EAAG;AAC9B,IAAA,KAAA,MAAW,KAAA,IAAS,IAAI,OAAA,EAAS;AAC/B,MAAA,IAAI,CAAC,KAAA,IAAS,OAAO,KAAA,KAAU,QAAA,EAAU;AACzC,MAAA,MAAM,CAAA,GAAI,KAAA;AACV,MAAA,MAAM,KAAK,OAAO,CAAA,CAAE,EAAA,KAAO,QAAA,GAAW,EAAE,EAAA,GAAK,EAAA;AAC7C,MAAA,MAAM,QAAQ,OAAO,CAAA,CAAE,KAAA,KAAU,QAAA,GAAW,EAAE,KAAA,GAAQ,EAAA;AACtD,MAAA,MAAM,OAAA,GACJ,OAAO,CAAA,CAAE,OAAA,KAAY,QAAA,GAAW,EAAE,OAAA,GAAA,iBAAU,IAAI,IAAA,EAAK,EAAE,WAAA,EAAY;AACrE,MAAA,MAAM,WAAW,CAAA,CAAE,QAAA;AACnB,MAAA,IAAI,CAAC,EAAA,IAAM,CAAC,QAAA,EAAU;AACtB,MAAA,OAAA,CAAQ,KAAK,EAAE,EAAA,EAAI,KAAA,EAAO,OAAA,EAAS,UAAU,CAAA;AAAA,IAC/C;AAAA,EACF;AACA,EAAA,OAAO,EAAE,OAAA,EAAS,qBAAA,EAAuB,OAAA,EAAQ;AACnD;;;ACzFO,SAAS,oBAAA,CACd,QACA,IAAA,EACM;AACN,EAAA,MAAM,EAAE,QAAA,EAAU,mBAAA,EAAqB,iBAAA,EAAmB,UAAS,GAAI,IAAA;AACvE,EAAA,MAAM,UAAA,GAAa,KAAK,UAAA,KAAe,IAAA;AAGvC,EAAA,MAAA,CAAO,IAAA;AAAA,IACL,qBAAA;AAAA,IACA,gYAAA;AAAA,IAMA;AAAA,MACE,SAASE,CAAAA,CACN,MAAA,EAAO,CACP,GAAA,CAAI,CAAC,CAAA,CACL,QAAA;AAAA,QACC;AAAA,OAEF;AAAA,MACF,aAAA,EAAeA,CAAAA,CACZ,MAAA,EAAO,CACP,UAAS,CACT,QAAA;AAAA,QACC;AAAA,OAEF;AAAA,MACF,GAAA,EAAKA,CAAAA,CACF,MAAA,EAAO,CACP,UAAS,CACT,QAAA;AAAA,QACC;AAAA,OACF;AAAA,MACF,MAAA,EAAQA,CAAAA,CACL,MAAA,EAAO,CACP,UAAS,CACT,QAAA;AAAA,QACC;AAAA,OAEF;AAAA,MACF,KAAA,EAAOA,CAAAA,CACJ,MAAA,EAAO,CACP,UAAS,CACT,QAAA;AAAA,QACC;AAAA;AAEF,KACJ;AAAA,IACA,OAAM,KAAA,KAAS;AACb,MAAA,IAAI,CAAC,mBAAA,EAAqB;AACxB,QAAA,OAAO;AAAA,UACL,OAAA,EAAS;AAAA,YACP;AAAA,cACE,IAAA,EAAM,MAAA;AAAA,cACN,IAAA,EACE;AAAA;AAGJ,WACF;AAAA,UACA,OAAA,EAAS;AAAA,SACX;AAAA,MACF;AAIA,MAAA,IAAI,MAAM,KAAA,CAAM,GAAA;AAChB,MAAA,IAAI,YAAA,GAAe,MAAM,aAAA,IAAiB,SAAA;AAC1C,MAAA,IAAI,CAAC,GAAA,EAAK;AACR,QAAA,IAAI;AACF,UAAA,MAAM,MAAA,GAAS,MAAM,oBAAA,EAAqB;AAC1C,UAAA,MAAM,EAAA,GAAK,MAAM,aAAA,GACb,aAAA,CAAc,QAAQ,KAAA,CAAM,aAAa,CAAA,GACzC,kBAAA,CAAmB,MAAM,CAAA;AAC7B,UAAA,IAAI,EAAA,EAAI;AACN,YAAA,GAAA,GAAM,EAAA,CAAG,IAAA;AACT,YAAA,YAAA,GAAe,EAAA,CAAG,IAAA;AAAA,UACpB;AAAA,QACF,CAAA,CAAA,MAAQ;AAAA,QAER;AAAA,MACF;AACA,MAAA,IAAI,CAAC,GAAA,EAAK;AACR,QAAA,OAAO;AAAA,UACL,OAAA,EAAS;AAAA,YACP;AAAA,cACE,IAAA,EAAM,MAAA;AAAA,cACN,IAAA,EACE;AAAA;AAGJ,WACF;AAAA,UACA,OAAA,EAAS;AAAA,SACX;AAAA,MACF;AACA,MAAA,MAAM,QAAA,GAAW,MAAM,mBAAA,CAAoB,KAAA,CAAM,OAAO,CAAA;AACxD,MAAA,IAAI,CAAC,QAAA,EAAU;AACb,QAAA,OAAO;AAAA,UACL,OAAA,EAAS;AAAA,YACP;AAAA,cACE,IAAA,EAAM,MAAA;AAAA,cACN,IAAA,EAAM,CAAA,8BAAA,EAAiC,KAAA,CAAM,OAAO,CAAA,qDAAA;AAAA;AACtD,WACF;AAAA,UACA,OAAA,EAAS;AAAA,SACX;AAAA,MACF;AACA,MAAA,IAAI;AACF,QAAA,MAAM,eAAe,MAAM,QAAA,CAAS,YAAA,CAAa,EAAE,KAAK,CAAA;AACxD,QAAA,MAAM,IAAA,GAAO,SAAS,UAAA,CAAW;AAAA,UAC/B,aAAA,EAAe,YAAA;AAAA,UACf,GAAA;AAAA,UACA,YAAA;AAAA,UACA,aAAa,KAAA,CAAM,OAAA;AAAA,UACnB,GAAI,MAAM,MAAA,GAAS,EAAE,eAAe,KAAA,CAAM,MAAA,KAAW,EAAC;AAAA,UACtD,GAAI,MAAM,KAAA,GAAQ,EAAE,OAAO,KAAA,CAAM,KAAA,KAAU,EAAC;AAAA,UAC5C,GAAI,SAAS,cAAA,GACT,EAAE,gBAAgB,QAAA,CAAS,cAAA,KAC3B;AAAC,SACN,CAAA;AACD,QAAA,OAAO;AAAA,UACL,OAAA,EAAS,CAAC,EAAE,IAAA,EAAM,MAAA,EAAQ,IAAA,EAAM,IAAA,CAAK,SAAA,CAAU,IAAA,EAAM,IAAA,EAAM,CAAC,CAAA,EAAG;AAAA,SACjE;AAAA,MACF,SAAS,GAAA,EAAK;AACZ,QAAA,OAAO;AAAA,UACL,OAAA,EAAS;AAAA,YACP;AAAA,cACE,IAAA,EAAM,MAAA;AAAA,cACN,IAAA,EAAM,4CACJ,GAAA,YAAe,KAAA,GAAQ,IAAI,OAAA,GAAU,MAAA,CAAO,GAAG,CACjD,CAAA;AAAA;AACF,WACF;AAAA,UACA,OAAA,EAAS;AAAA,SACX;AAAA,MACF;AAAA,IACF;AAAA,GACF;AAGA,EAAA,MAAA,CAAO,IAAA;AAAA,IACL,sBAAA;AAAA,IACA,yRAAA;AAAA,IAIA;AAAA,MACE,SAAA,EAAWA,CAAAA,CAAE,MAAA,EAAO,CAAE,SAAS,6CAA6C,CAAA;AAAA,MAC5E,MAAA,EAAQA,EAAE,MAAA,EAAO,CAAE,IAAI,CAAC,CAAA,CAAE,SAAS,kCAAkC;AAAA,KACvE;AAAA,IACA,OAAM,KAAA,KAAS;AACb,MAAA,IAAI;AAMF,QAAA,KAAK,QAAA,CAAS,WAAW,KAAA,CAAM,SAAA,EAAW,MAAM,MAAM,CAAA,CAAE,MAAM,MAAM;AAAA,QAEpE,CAAC,CAAA;AACD,QAAA,OAAO;AAAA,UACL,OAAA,EAAS;AAAA,YACP;AAAA,cACE,IAAA,EAAM,MAAA;AAAA,cACN,MAAM,IAAA,CAAK,SAAA;AAAA,gBACT,EAAE,EAAA,EAAI,IAAA,EAAM,WAAW,KAAA,CAAM,SAAA,EAAW,QAAQ,IAAA,EAAK;AAAA,gBACrD,IAAA;AAAA,gBACA;AAAA;AACF;AACF;AACF,SACF;AAAA,MACF,SAAS,GAAA,EAAK;AACZ,QAAA,OAAO;AAAA,UACL,OAAA,EAAS;AAAA,YACP;AAAA,cACE,IAAA,EAAM,MAAA;AAAA,cACN,IAAA,EAAM,yBAAyB,GAAA,YAAe,KAAA,GAAQ,IAAI,OAAA,GAAU,MAAA,CAAO,GAAG,CAAC,CAAA;AAAA;AACjF,WACF;AAAA,UACA,OAAA,EAAS;AAAA,SACX;AAAA,MACF;AAAA,IACF;AAAA,GACF;AAGA,EAAA,MAAA,CAAO,IAAA;AAAA,IACL,eAAA;AAAA,IACA,qZAAA;AAAA,IAMA;AAAA,MACE,IAAA,EAAMA,CAAAA,CACH,IAAA,CAAK,CAAC,UAAA,EAAY,WAAA,EAAa,SAAA,EAAW,KAAK,CAAC,CAAA,CAChD,QAAA,EAAS,CACT,QAAA;AAAA,QACC;AAAA,OAGF;AAAA,MACF,WAAWA,CAAAA,CACR,OAAA,GACA,QAAA,EAAS,CACT,SAAS,2DAA2D,CAAA;AAAA,MACvE,MAAA,EAAQA,CAAAA,CACL,IAAA,CAAK,CAAC,YAAY,SAAA,EAAW,QAAA,EAAU,QAAA,EAAU,OAAO,CAAC,CAAA,CACzD,QAAA,EAAS,CACT,SAAS,+CAA+C;AAAA,KAC7D;AAAA,IACA,OAAM,KAAA,KAAS;AACb,MAAA,IAAI,IAAA,GAAO,SAAS,IAAA,EAAK;AACzB,MAAA,IAAI,KAAA,CAAM,IAAA,IAAQ,KAAA,CAAM,IAAA,KAAS,KAAA,EAAO;AACtC,QAAA,IAAA,GAAO,KAAK,MAAA,CAAO,CAAA,CAAA,KAAK,CAAA,CAAE,IAAA,KAAS,MAAM,IAAI,CAAA;AAAA,MAC/C;AACA,MAAA,IAAI,MAAM,MAAA,EAAQ;AAChB,QAAA,IAAA,GAAO,KAAK,MAAA,CAAO,CAAA,CAAA,KAAK,CAAA,CAAE,MAAA,KAAW,MAAM,MAAM,CAAA;AAAA,MACnD,CAAA,MAAA,IAAW,MAAM,SAAA,EAAW;AAC1B,QAAA,IAAA,GAAO,IAAA,CAAK,MAAA;AAAA,UACV,CAAA,CAAA,KAAK,CAAA,CAAE,MAAA,KAAW,SAAA,IAAa,EAAE,MAAA,KAAW;AAAA,SAC9C;AAAA,MACF;AACA,MAAA,OAAO;AAAA,QACL,OAAA,EAAS;AAAA,UACP,EAAE,IAAA,EAAM,MAAA,EAAQ,IAAA,EAAM,IAAA,CAAK,SAAA,CAAU,EAAE,QAAA,EAAU,IAAA,EAAK,EAAG,IAAA,EAAM,CAAC,CAAA;AAAE;AACpE,OACF;AAAA,IACF;AAAA,GACF;AAGA,EAAA,MAAA,CAAO,IAAA;AAAA,IACL,qBAAA;AAAA,IACA,kNAAA;AAAA,IAGA;AAAA,MACE,WAAWA,CAAAA,CACR,OAAA,GACA,QAAA,EAAS,CACT,SAAS,wDAAwD;AAAA,KACtE;AAAA,IACA,OAAM,KAAA,KAAS;AACb,MAAA,MAAM,GAAA,GAAM,SAAS,IAAA,EAAK;AAC1B,MAAA,MAAM,QAAA,GAAW,KAAA,CAAM,SAAA,GACnB,GAAA,CAAI,MAAA,CAAO,CAAA,CAAA,KAAK,CAAA,CAAE,MAAA,KAAW,SAAA,IAAa,CAAA,CAAE,MAAA,KAAW,UAAU,CAAA,GACjE,GAAA;AACJ,MAAA,OAAO;AAAA,QACL,OAAA,EAAS;AAAA,UACP;AAAA,YACE,IAAA,EAAM,MAAA;AAAA,YACN,IAAA,EAAM,KAAK,SAAA,CAAU,EAAE,UAAU,QAAA,EAAS,EAAG,MAAM,CAAC;AAAA;AACtD;AACF,OACF;AAAA,IACF;AAAA,GACF;AAGA,EAAA,MAAA,CAAO,IAAA;AAAA,IACL,0BAAA;AAAA,IACA,+LAAA;AAAA,IAGA;AAAA,MACE,SAAA,EAAWA,CAAAA,CAAE,MAAA,EAAO,CAAE,SAAS,aAAa,CAAA;AAAA,MAC5C,KAAA,EAAOA,CAAAA,CACJ,MAAA,EAAO,CACP,KAAI,CACJ,GAAA,CAAI,CAAC,CAAA,CACL,IAAI,GAAG,CAAA,CACP,QAAA,EAAS,CACT,SAAS,2CAA2C;AAAA,KACzD;AAAA,IACA,OAAM,KAAA,KAAS;AACb,MAAA,MAAM,IAAA,GAAO,QAAA,CAAS,GAAA,CAAI,KAAA,CAAM,SAAS,CAAA;AACzC,MAAA,IAAI,CAAC,IAAA,EAAM;AACT,QAAA,OAAO;AAAA,UACL,OAAA,EAAS;AAAA,YACP,EAAE,IAAA,EAAM,MAAA,EAAQ,MAAM,CAAA,sCAAA,EAAyC,KAAA,CAAM,SAAS,CAAA,CAAA,CAAA;AAAI,WACpF;AAAA,UACA,OAAA,EAAS;AAAA,SACX;AAAA,MACF;AAGA,MAAA,MAAM,KAAA,GAAQ,MAAM,KAAA,IAAS,EAAA;AAC7B,MAAA,MAAM,QAAkB,EAAC;AACzB,MAAA,MAAM,QAAQ,QAAA,CAAS,MAAA,CAAO,MAAM,SAAA,EAAW,CAAC,MAAM,OAAA,KAAY;AAChE,QAAA,KAAA,CAAM,KAAK,IAAI,CAAA;AAAA,MACjB,CAAC,CAAA;AACD,MAAA,IAAI,OAAO,KAAA,EAAM;AACjB,MAAA,MAAM,IAAA,GAAO,KAAA,CAAM,KAAA,CAAM,CAAC,KAAK,CAAA;AAC/B,MAAA,OAAO;AAAA,QACL,OAAA,EAAS;AAAA,UACP;AAAA,YACE,IAAA,EAAM,MAAA;AAAA,YACN,MAAM,IAAA,CAAK,SAAA;AAAA,cACT;AAAA,gBACE,WAAW,KAAA,CAAM,SAAA;AAAA,gBACjB,QAAQ,IAAA,CAAK,MAAA;AAAA,gBACb,cAAc,IAAA,CAAK,YAAA;AAAA,gBACnB,KAAA,EAAO;AAAA,eACT;AAAA,cACA,IAAA;AAAA,cACA;AAAA;AACF;AACF;AACF,OACF;AAAA,IACF;AAAA,GACF;AAGA,EAAA,MAAA,CAAO,IAAA;AAAA,IACL,eAAA;AAAA,IACA,iTAAA;AAAA,IAKA,EAAC;AAAA,IACD,YAAY;AACV,MAAA,IAAI,CAAC,iBAAA,EAAmB;AACtB,QAAA,OAAO;AAAA,UACL,OAAA,EAAS;AAAA,YACP;AAAA,cACE,IAAA,EAAM,MAAA;AAAA,cACN,IAAA,EACE;AAAA;AAGJ,WACF;AAAA,UACA,OAAA,EAAS;AAAA,SACX;AAAA,MACF;AACA,MAAA,IAAI;AACF,QAAA,MAAM,QAAA,GAAW,MAAM,iBAAA,EAAkB;AACzC,QAAA,OAAO;AAAA,UACL,OAAA,EAAS,CAAC,EAAE,IAAA,EAAM,QAAQ,IAAA,EAAM,IAAA,CAAK,SAAA,CAAU,EAAE,QAAA,EAAS,EAAG,IAAA,EAAM,CAAC,GAAG;AAAA,SACzE;AAAA,MACF,SAAS,GAAA,EAAK;AACZ,QAAA,OAAO;AAAA,UACL,OAAA,EAAS;AAAA,YACP;AAAA,cACE,IAAA,EAAM,MAAA;AAAA,cACN,IAAA,EAAM,yBAAyB,GAAA,YAAe,KAAA,GAAQ,IAAI,OAAA,GAAU,MAAA,CAAO,GAAG,CAAC,CAAA;AAAA;AACjF,WACF;AAAA,UACA,OAAA,EAAS;AAAA,SACX;AAAA,MACF;AAAA,IACF;AAAA,GACF;AAGA,EAAA,MAAA,CAAO,IAAA;AAAA,IACL,sBAAA;AAAA,IACA,iWAAA;AAAA,IAKA,EAAC;AAAA,IACD,YAAY;AACV,MAAA,IAAI;AACF,QAAA,MAAM,IAAA,GAAO,MAAM,YAAA,EAAa;AAChC,QAAA,OAAO;AAAA,UACL,OAAA,EAAS,CAAC,EAAE,IAAA,EAAM,QAAQ,IAAA,EAAM,IAAA,CAAK,SAAA,CAAU,EAAE,IAAA,EAAK,EAAG,IAAA,EAAM,CAAC,GAAG;AAAA,SACrE;AAAA,MACF,SAAS,GAAA,EAAK;AACZ,QAAA,OAAO;AAAA,UACL,OAAA,EAAS;AAAA,YACP;AAAA,cACE,IAAA,EAAM,MAAA;AAAA,cACN,IAAA,EAAM,gCAAgC,GAAA,YAAe,KAAA,GAAQ,IAAI,OAAA,GAAU,MAAA,CAAO,GAAG,CAAC,CAAA;AAAA;AACxF,WACF;AAAA,UACA,OAAA,EAAS;AAAA,SACX;AAAA,MACF;AAAA,IACF;AAAA,GACF;AAGA,EAAA,MAAA,CAAO,IAAA;AAAA,IACL,oBAAA;AAAA,IACA,iRAAA;AAAA,IAIA,EAAC;AAAA,IACD,YAAY;AACV,MAAA,IAAI;AACF,QAAA,MAAM,MAAA,GAAS,MAAM,gBAAA,EAAiB;AACtC,QAAA,OAAO;AAAA,UACL,OAAA,EAAS;AAAA,YACP,EAAE,MAAM,MAAA,EAAQ,IAAA,EAAM,KAAK,SAAA,CAAU,MAAA,EAAQ,IAAA,EAAM,CAAC,CAAA;AAAE;AACxD,SACF;AAAA,MACF,SAAS,GAAA,EAAK;AACZ,QAAA,OAAO;AAAA,UACL,OAAA,EAAS;AAAA,YACP;AAAA,cACE,IAAA,EAAM,MAAA;AAAA,cACN,IAAA,EAAM,8BAA8B,GAAA,YAAe,KAAA,GAAQ,IAAI,OAAA,GAAU,MAAA,CAAO,GAAG,CAAC,CAAA;AAAA;AACtF,WACF;AAAA,UACA,OAAA,EAAS;AAAA,SACX;AAAA,MACF;AAAA,IACF;AAAA,GACF;AAGA,EAAA,MAAA,CAAO,IAAA;AAAA,IACL,YAAA;AAAA,IACA,qRAAA;AAAA,IAKA;AAAA,MACE,aAAaA,CAAAA,CACV,MAAA,EAAO,CACP,GAAA,CAAI,CAAC,CAAA,CACL,QAAA;AAAA,QACC;AAAA,OAEF;AAAA,MACF,KAAA,EAAOA,CAAAA,CACJ,MAAA,EAAO,CACP,UAAS,CACT,QAAA;AAAA,QACC;AAAA;AACF,KACJ;AAAA,IACA,OAAM,KAAA,KAAS;AACb,MAAA,IAAI;AACF,QAAA,MAAM,UAAA,GAAa,MAAM,YAAA,EAAa;AACtC,QAAA,MAAM,WAAW,UAAA,CAAW,IAAA,CAAK,OAAK,CAAA,CAAE,EAAA,KAAO,MAAM,WAAW,CAAA;AAChE,QAAA,IAAI,CAAC,QAAA,EAAU;AACb,UAAA,OAAO;AAAA,YACL,OAAA,EAAS;AAAA,cACP;AAAA,gBACE,IAAA,EAAM,MAAA;AAAA,gBACN,IAAA,EAAM,CAAA,4BAAA,EAA+B,KAAA,CAAM,WAAW,CAAA,4DAAA;AAAA;AACxD,aACF;AAAA,YACA,OAAA,EAAS;AAAA,WACX;AAAA,QACF;AACA,QAAA,MAAM,GAAA,GAAM,MAAM,gBAAA,EAAiB;AACnC,QAAA,MAAM,IAAA,GAAO,UAAU,GAAA,EAAK;AAAA,UAC1B,QAAA;AAAA,UACA,GAAI,MAAM,KAAA,GAAQ,EAAE,OAAO,KAAA,CAAM,KAAA,KAAU;AAAC,SAC7C,CAAA;AACD,QAAA,MAAM,iBAAiB,IAAI,CAAA;AAC3B,QAAA,MAAM,KAAA,GAAQ,KAAK,OAAA,CAAQ,IAAA,CAAK,OAAK,CAAA,CAAE,EAAA,KAAO,SAAS,EAAE,CAAA;AACzD,QAAA,OAAO;AAAA,UACL,OAAA,EAAS,CAAC,EAAE,IAAA,EAAM,MAAA,EAAQ,IAAA,EAAM,IAAA,CAAK,SAAA,CAAU,KAAA,EAAO,IAAA,EAAM,CAAC,CAAA,EAAG;AAAA,SAClE;AAAA,MACF,SAAS,GAAA,EAAK;AACZ,QAAA,OAAO;AAAA,UACL,OAAA,EAAS;AAAA,YACP;AAAA,cACE,IAAA,EAAM,MAAA;AAAA,cACN,IAAA,EAAM,sBAAsB,GAAA,YAAe,KAAA,GAAQ,IAAI,OAAA,GAAU,MAAA,CAAO,GAAG,CAAC,CAAA;AAAA;AAC9E,WACF;AAAA,UACA,OAAA,EAAS;AAAA,SACX;AAAA,MACF;AAAA,IACF;AAAA,GACF;AAGA,EAAA,MAAA,CAAO,IAAA;AAAA,IACL,qBAAA;AAAA,IACA,gIAAA;AAAA,IAEA;AAAA,MACE,IAAIA,CAAAA,CACD,MAAA,EAAO,CACP,GAAA,CAAI,CAAC,CAAA,CACL,QAAA;AAAA,QACC;AAAA;AACF,KACJ;AAAA,IACA,OAAM,KAAA,KAAS;AACb,MAAA,IAAI;AACF,QAAA,MAAM,GAAA,GAAM,MAAM,gBAAA,EAAiB;AACnC,QAAA,IAAI,CAAC,IAAI,OAAA,CAAQ,IAAA,CAAK,OAAK,CAAA,CAAE,EAAA,KAAO,KAAA,CAAM,EAAE,CAAA,EAAG;AAC7C,UAAA,OAAO;AAAA,YACL,OAAA,EAAS;AAAA,cACP;AAAA,gBACE,IAAA,EAAM,MAAA;AAAA,gBACN,IAAA,EAAM,CAAA,yBAAA,EAA4B,KAAA,CAAM,EAAE,CAAA,gEAAA;AAAA;AAC5C,aACF;AAAA,YACA,OAAA,EAAS;AAAA,WACX;AAAA,QACF;AACA,QAAA,MAAM,gBAAA,CAAiB,YAAA,CAAa,GAAA,EAAK,KAAA,CAAM,EAAE,CAAC,CAAA;AAClD,QAAA,OAAO;AAAA,UACL,OAAA,EAAS;AAAA,YACP,EAAE,IAAA,EAAM,MAAA,EAAQ,IAAA,EAAM,KAAK,SAAA,CAAU,EAAE,EAAA,EAAI,IAAA,EAAM,IAAI,KAAA,CAAM,EAAA,EAAG,EAAG,IAAA,EAAM,CAAC,CAAA;AAAE;AAC5E,SACF;AAAA,MACF,SAAS,GAAA,EAAK;AACZ,QAAA,OAAO;AAAA,UACL,OAAA,EAAS;AAAA,YACP;AAAA,cACE,IAAA,EAAM,MAAA;AAAA,cACN,IAAA,EAAM,+BAA+B,GAAA,YAAe,KAAA,GAAQ,IAAI,OAAA,GAAU,MAAA,CAAO,GAAG,CAAC,CAAA;AAAA;AACvF,WACF;AAAA,UACA,OAAA,EAAS;AAAA,SACX;AAAA,MACF;AAAA,IACF;AAAA,GACF;AAOA,EAAA,MAAA,CAAO,IAAA;AAAA,IACL,qBAAA;AAAA,IACA,uUAAA;AAAA,IAKA,EAAC;AAAA,IACD,YAAY;AACV,MAAA,IAAI,CAAC,QAAA,EAAU;AACb,QAAA,OAAO;AAAA,UACL,OAAA,EAAS;AAAA,YACP;AAAA,cACE,IAAA,EAAM,MAAA;AAAA,cACN,IAAA,EACE;AAAA;AAEJ,WACF;AAAA,UACA,OAAA,EAAS;AAAA,SACX;AAAA,MACF;AACA,MAAA,IAAI;AACF,QAAA,MAAM,OAAA,GAAU,MAAM,QAAA,CAAS,WAAA,EAAY;AAC3C,QAAA,OAAO;AAAA,UACL,OAAA,EAAS;AAAA,YACP,EAAE,IAAA,EAAM,MAAA,EAAQ,IAAA,EAAM,IAAA,CAAK,SAAA,CAAU,EAAE,OAAA,EAAS,OAAA,EAAQ,EAAG,IAAA,EAAM,CAAC,CAAA;AAAE;AACtE,SACF;AAAA,MACF,SAAS,GAAA,EAAK;AACZ,QAAA,OAAO;AAAA,UACL,OAAA,EAAS;AAAA,YACP;AAAA,cACE,IAAA,EAAM,MAAA;AAAA,cACN,IAAA,EAAM,+BAA+B,GAAA,YAAe,KAAA,GAAQ,IAAI,OAAA,GAAU,MAAA,CAAO,GAAG,CAAC,CAAA;AAAA;AACvF,WACF;AAAA,UACA,OAAA,EAAS;AAAA,SACX;AAAA,MACF;AAAA,IACF;AAAA,GACF;AAGA,EAAA,MAAA,CAAO,IAAA;AAAA,IACL,yBAAA;AAAA,IACA,iXAAA;AAAA,IAMA;AAAA,MACE,OAAOA,CAAAA,CACJ,MAAA,EAAO,CACP,GAAA,CAAI,CAAC,CAAA,CACL,QAAA;AAAA,QACC;AAAA;AAEF,KACJ;AAAA,IACA,OAAM,KAAA,KAAS;AACb,MAAA,IAAI,CAAC,QAAA,EAAU;AACb,QAAA,OAAO;AAAA,UACL,OAAA,EAAS;AAAA,YACP;AAAA,cACE,IAAA,EAAM,MAAA;AAAA,cACN,IAAA,EAAM;AAAA;AACR,WACF;AAAA,UACA,OAAA,EAAS;AAAA,SACX;AAAA,MACF;AACA,MAAA,MAAM,GAAA,GAAM,MAAM,QAAA,CAAS,SAAA,CAAU,MAAM,KAAK,CAAA;AAChD,MAAA,IAAI,CAAC,IAAI,EAAA,EAAI;AACX,QAAA,OAAO;AAAA,UACL,OAAA,EAAS;AAAA,YACP;AAAA,cACE,IAAA,EAAM,MAAA;AAAA,cACN,MAAM,CAAA,yBAAA,EAA4B,KAAA,CAAM,KAAK,CAAA,GAAA,EAAM,IAAI,KAAK,CAAA;AAAA;AAC9D,WACF;AAAA,UACA,OAAA,EAAS;AAAA,SACX;AAAA,MACF;AACA,MAAA,OAAO;AAAA,QACL,OAAA,EAAS;AAAA,UACP,EAAE,IAAA,EAAM,MAAA,EAAQ,IAAA,EAAM,IAAA,CAAK,UAAU,EAAE,KAAA,EAAO,KAAA,CAAM,KAAA,EAAO,OAAO,GAAA,CAAI,KAAA,EAAM,EAAG,IAAA,EAAM,CAAC,CAAA;AAAE;AAC1F,OACF;AAAA,IACF;AAAA,GACF;AAGA,EAAA,MAAA,CAAO,IAAA;AAAA,IACL,mBAAA;AAAA,IACA,sWAAA;AAAA,IAMA;AAAA,MACE,KAAA,EAAOA,EAAE,MAAA,EAAO,CAAE,IAAI,CAAC,CAAA,CAAE,SAAS,qBAAqB,CAAA;AAAA,MACvD,UAAUA,CAAAA,CACP,MAAA,EAAO,CACP,GAAA,CAAI,CAAC,CAAA,CACL,QAAA;AAAA,QACC;AAAA,OAEF;AAAA,MACF,IAAA,EAAMA,CAAAA,CACH,MAAA,CAAOA,CAAAA,CAAE,MAAA,EAAO,EAAGA,CAAAA,CAAE,OAAA,EAAS,CAAA,CAC9B,QAAA,EAAS,CACT,QAAA;AAAA,QACC;AAAA;AAEF,KACJ;AAAA,IACA,OAAM,KAAA,KAAS;AACb,MAAA,IAAI,CAAC,QAAA,EAAU;AACb,QAAA,OAAO;AAAA,UACL,OAAA,EAAS;AAAA,YACP;AAAA,cACE,IAAA,EAAM,MAAA;AAAA,cACN,IAAA,EAAM;AAAA;AACR,WACF;AAAA,UACA,OAAA,EAAS;AAAA,SACX;AAAA,MACF;AACA,MAAA,MAAM,GAAA,GAAM,MAAM,QAAA,CAAS,QAAA;AAAA,QACzB,KAAA,CAAM,KAAA;AAAA,QACN,KAAA,CAAM,QAAA;AAAA,QACN,KAAA,CAAM,QAAQ;AAAC,OACjB;AACA,MAAA,IAAI,CAAC,IAAI,EAAA,EAAI;AACX,QAAA,OAAO;AAAA,UACL,OAAA,EAAS;AAAA,YACP;AAAA,cACE,IAAA,EAAM,MAAA;AAAA,cACN,IAAA,EAAM,sBAAsB,KAAA,CAAM,KAAK,KAAK,KAAA,CAAM,QAAQ,CAAA,EAAA,EAAK,GAAA,CAAI,KAAK,CAAA;AAAA;AAC1E,WACF;AAAA,UACA,OAAA,EAAS;AAAA,SACX;AAAA,MACF;AAIA,MAAA,OAAO,GAAA,CAAI,MAAA;AAAA,IAIb;AAAA,GACF;AAGA,EAAA,MAAA,CAAO,IAAA;AAAA,IACL,oBAAA;AAAA,IACA,uKAAA;AAAA,IAGA;AAAA,MACE,SAAA,EAAWA,CAAAA,CAAE,MAAA,EAAO,CAAE,SAAS,aAAa;AAAA,KAC9C;AAAA,IACA,OAAM,KAAA,KAAS;AACb,MAAA,MAAM,EAAA,GAAK,QAAA,CAAS,IAAA,CAAK,KAAA,CAAM,SAAS,CAAA;AACxC,MAAA,OAAO;AAAA,QACL,OAAA,EAAS;AAAA,UACP;AAAA,YACE,IAAA,EAAM,MAAA;AAAA,YACN,IAAA,EAAM,IAAA,CAAK,SAAA,CAAU,EAAE,EAAA,EAAI,WAAW,KAAA,CAAM,SAAA,EAAU,EAAG,IAAA,EAAM,CAAC;AAAA;AAClE;AACF,OACF;AAAA,IACF;AAAA,GACF;AAUA,EAAA,MAAM,gBAAA,GAAmB,CAAC,QAAA,MAGpB;AAAA,IACJ,OAAA,EAAS;AAAA,MACP;AAAA,QACE,IAAA,EAAM,MAAA;AAAA,QACN,IAAA,EACE,GAAG,QAAQ,CAAA,+LAAA;AAAA;AAGf,KACF;AAAA,IACA,OAAA,EAAS;AAAA,GACX,CAAA;AAEA,EAAA,MAAA,CAAO,IAAA;AAAA,IACL,wBAAA;AAAA,IACA,yUAAA;AAAA,IAKA;AAAA,MACE,IAAA,EAAMA,EACH,KAAA,CAAMA,CAAAA,CAAE,QAAQ,CAAA,CAChB,GAAA,CAAI,CAAC,CAAA,CACL,QAAA;AAAA,QACC;AAAA,OAEF;AAAA,MACF,aAAA,EAAeA,CAAAA,CACZ,MAAA,EAAO,CACP,UAAS,CACT,QAAA;AAAA,QACC;AAAA,OAEF;AAAA,MACF,KAAKA,CAAAA,CACF,MAAA,GACA,QAAA,EAAS,CACT,SAAS,sDAAsD,CAAA;AAAA,MAClE,IAAA,EAAMA,CAAAA,CAAE,MAAA,EAAO,CAAE,KAAI,CAAE,GAAA,CAAI,CAAC,CAAA,CAAE,IAAI,GAAG,CAAA,CAAE,QAAA,EAAS,CAAE,SAAS,2BAA2B,CAAA;AAAA,MACtF,IAAA,EAAMA,CAAAA,CAAE,MAAA,EAAO,CAAE,KAAI,CAAE,GAAA,CAAI,CAAC,CAAA,CAAE,IAAI,GAAG,CAAA,CAAE,QAAA,EAAS,CAAE,SAAS,2BAA2B,CAAA;AAAA,MACtF,IAAA,EAAMA,CAAAA,CACH,MAAA,EAAO,CACP,UAAS,CACT,QAAA;AAAA,QACC;AAAA,OAEF;AAAA,MACF,KAAA,EAAOA,CAAAA,CACJ,MAAA,EAAO,CACP,UAAS,CACT,QAAA;AAAA,QACC;AAAA;AACF,KACJ;AAAA,IACA,OAAM,KAAA,KAAS;AACb,MAAA,IAAI,CAAC,UAAA,EAAY,OAAO,gBAAA,CAAiB,wBAAwB,CAAA;AACjE,MAAA,IAAI,MAAM,KAAA,CAAM,GAAA;AAChB,MAAA,IAAI,YAAA,GAAe,MAAM,aAAA,IAAiB,SAAA;AAC1C,MAAA,IAAI,CAAC,GAAA,EAAK;AACR,QAAA,IAAI;AACF,UAAA,MAAM,MAAA,GAAS,MAAM,oBAAA,EAAqB;AAC1C,UAAA,MAAM,EAAA,GAAK,MAAM,aAAA,GACb,aAAA,CAAc,QAAQ,KAAA,CAAM,aAAa,CAAA,GACzC,kBAAA,CAAmB,MAAM,CAAA;AAC7B,UAAA,IAAI,EAAA,EAAI;AACN,YAAA,GAAA,GAAM,EAAA,CAAG,IAAA;AACT,YAAA,YAAA,GAAe,EAAA,CAAG,IAAA;AAAA,UACpB;AAAA,QACF,CAAA,CAAA,MAAQ;AAAA,QAER;AAAA,MACF;AACA,MAAA,IAAI,CAAC,GAAA,EAAK;AACR,QAAA,OAAO;AAAA,UACL,OAAA,EAAS;AAAA,YACP;AAAA,cACE,IAAA,EAAM,MAAA;AAAA,cACN,IAAA,EACE;AAAA;AAEJ,WACF;AAAA,UACA,OAAA,EAAS;AAAA,SACX;AAAA,MACF;AACA,MAAA,IAAI;AACF,QAAA,MAAM,IAAA,GAAO,SAAS,QAAA,CAAS;AAAA,UAC7B,MAAM,KAAA,CAAM,IAAA;AAAA,UACZ,GAAA;AAAA,UACA,aAAA,EAAe,YAAA;AAAA,UACf,IAAA,EAAM,MAAM,IAAA,IAAQ,EAAA;AAAA,UACpB,IAAA,EAAM,MAAM,IAAA,IAAQ,EAAA;AAAA,UACpB,GAAI,MAAM,IAAA,GAAO,EAAE,MAAM,KAAA,CAAM,IAAA,KAAS,EAAC;AAAA,UACzC,GAAI,MAAM,KAAA,GAAQ,EAAE,OAAO,KAAA,CAAM,KAAA,KAAU;AAAC,SAC7C,CAAA;AACD,QAAA,OAAO;AAAA,UACL,OAAA,EAAS,CAAC,EAAE,IAAA,EAAM,MAAA,EAAQ,IAAA,EAAM,IAAA,CAAK,SAAA,CAAU,IAAA,EAAM,IAAA,EAAM,CAAC,CAAA,EAAG;AAAA,SACjE;AAAA,MACF,SAAS,GAAA,EAAK;AACZ,QAAA,OAAO;AAAA,UACL,OAAA,EAAS;AAAA,YACP;AAAA,cACE,IAAA,EAAM,MAAA;AAAA,cACN,IAAA,EAAM,2BAA2B,GAAA,YAAe,KAAA,GAAQ,IAAI,OAAA,GAAU,MAAA,CAAO,GAAG,CAAC,CAAA;AAAA;AACnF,WACF;AAAA,UACA,OAAA,EAAS;AAAA,SACX;AAAA,MACF;AAAA,IACF;AAAA,GACF;AAEA,EAAA,MAAA,CAAO,IAAA;AAAA,IACL,sBAAA;AAAA,IACA,2NAAA;AAAA,IAGA;AAAA,MACE,SAAA,EAAWA,CAAAA,CACR,MAAA,EAAO,CACP,SAAS,iDAAiD,CAAA;AAAA,MAC7D,IAAA,EAAMA,CAAAA,CAAE,MAAA,EAAO,CAAE,SAAS,+CAA+C;AAAA,KAC3E;AAAA,IACA,OAAM,KAAA,KAAS;AACb,MAAA,IAAI,CAAC,UAAA,EAAY,OAAO,gBAAA,CAAiB,sBAAsB,CAAA;AAC/D,MAAA,MAAM,IAAA,GAAO,QAAA,CAAS,cAAA,CAAe,KAAA,CAAM,SAAS,CAAA;AACpD,MAAA,IAAI,CAAC,IAAA,EAAM;AACT,QAAA,OAAO;AAAA,UACL,OAAA,EAAS;AAAA,YACP;AAAA,cACE,IAAA,EAAM,MAAA;AAAA,cACN,IAAA,EAAM,CAAA,kCAAA,EAAqC,KAAA,CAAM,SAAS,CAAA,CAAA;AAAA;AAC5D,WACF;AAAA,UACA,OAAA,EAAS;AAAA,SACX;AAAA,MACF;AACA,MAAA,MAAM,KAAK,QAAA,CAAS,kBAAA,CAAmB,IAAA,CAAK,EAAA,EAAI,MAAM,IAAI,CAAA;AAC1D,MAAA,OAAO;AAAA,QACL,OAAA,EAAS;AAAA,UACP;AAAA,YACE,IAAA,EAAM,MAAA;AAAA,YACN,IAAA,EAAM,IAAA,CAAK,SAAA,CAAU,EAAE,EAAA,EAAI,WAAW,IAAA,CAAK,EAAA,EAAG,EAAG,IAAA,EAAM,CAAC;AAAA;AAC1D,SACF;AAAA,QACA,GAAI,EAAA,GAAK,EAAC,GAAI,EAAE,SAAS,IAAA;AAAc,OACzC;AAAA,IACF;AAAA,GACF;AAEA,EAAA,MAAA,CAAO,IAAA;AAAA,IACL,sBAAA;AAAA,IACA,sNAAA;AAAA,IAGA;AAAA,MACE,SAAA,EAAWA,CAAAA,CACR,MAAA,EAAO,CACP,SAAS,iDAAiD,CAAA;AAAA,MAC7D,WAAWA,CAAAA,CACR,MAAA,EAAO,CACP,GAAA,GACA,GAAA,CAAI,CAAC,CAAA,CACL,GAAA,CAAI,KAAK,IAAI,CAAA,CACb,QAAA,EAAS,CACT,SAAS,+DAA+D;AAAA,KAC7E;AAAA,IACA,OAAM,KAAA,KAAS;AACb,MAAA,IAAI,CAAC,UAAA,EAAY,OAAO,gBAAA,CAAiB,sBAAsB,CAAA;AAC/D,MAAA,MAAM,IAAA,GAAO,QAAA,CAAS,cAAA,CAAe,KAAA,CAAM,SAAS,CAAA;AACpD,MAAA,IAAI,CAAC,IAAA,EAAM;AACT,QAAA,OAAO;AAAA,UACL,OAAA,EAAS;AAAA,YACP;AAAA,cACE,IAAA,EAAM,MAAA;AAAA,cACN,IAAA,EAAM,CAAA,kCAAA,EAAqC,KAAA,CAAM,SAAS,CAAA,CAAA;AAAA;AAC5D,WACF;AAAA,UACA,OAAA,EAAS;AAAA,SACX;AAAA,MACF;AACA,MAAA,MAAM,MAAM,QAAA,CAAS,kBAAA;AAAA,QACnB,IAAA,CAAK,EAAA;AAAA,QACL,KAAA,CAAM;AAAA,OACR;AACA,MAAA,IAAI,CAAC,GAAA,EAAK;AACR,QAAA,OAAO;AAAA,UACL,OAAA,EAAS;AAAA,YACP;AAAA,cACE,IAAA,EAAM,MAAA;AAAA,cACN,IAAA,EAAM,CAAA,+BAAA,EAAkC,IAAA,CAAK,EAAE,CAAA,cAAA;AAAA;AACjD,WACF;AAAA,UACA,OAAA,EAAS;AAAA,SACX;AAAA,MACF;AACA,MAAA,OAAO;AAAA,QACL,OAAA,EAAS;AAAA,UACP;AAAA,YACE,IAAA,EAAM,MAAA;AAAA,YACN,MAAM,IAAA,CAAK,SAAA;AAAA,cACT;AAAA,gBACE,WAAW,IAAA,CAAK,EAAA;AAAA,gBAChB,QAAQ,IAAA,CAAK,MAAA;AAAA,gBACb,OAAO,GAAA,CAAI,UAAA;AAAA,gBACX,GAAA,EAAK,GAAA,CAAI,QAAA,CAAS,QAAQ;AAAA,eAC5B;AAAA,cACA,IAAA;AAAA,cACA;AAAA;AACF;AACF;AACF,OACF;AAAA,IACF;AAAA,GACF;AAEA,EAAA,MAAA,CAAO,IAAA;AAAA,IACL,uBAAA;AAAA,IACA,yKAAA;AAAA,IAGA;AAAA,MACE,SAAA,EAAWA,CAAAA,CACR,MAAA,EAAO,CACP,SAAS,iDAAiD;AAAA,KAC/D;AAAA,IACA,OAAM,KAAA,KAAS;AACb,MAAA,IAAI,CAAC,UAAA,EAAY,OAAO,gBAAA,CAAiB,uBAAuB,CAAA;AAChE,MAAA,MAAM,IAAA,GAAO,QAAA,CAAS,cAAA,CAAe,KAAA,CAAM,SAAS,CAAA;AACpD,MAAA,IAAI,CAAC,IAAA,EAAM;AACT,QAAA,OAAO;AAAA,UACL,OAAA,EAAS;AAAA,YACP;AAAA,cACE,IAAA,EAAM,MAAA;AAAA,cACN,IAAA,EAAM,CAAA,mCAAA,EAAsC,KAAA,CAAM,SAAS,CAAA,CAAA;AAAA;AAC7D,WACF;AAAA,UACA,OAAA,EAAS;AAAA,SACX;AAAA,MACF;AACA,MAAA,MAAM,EAAA,GAAK,QAAA,CAAS,IAAA,CAAK,IAAA,CAAK,EAAE,CAAA;AAChC,MAAA,OAAO;AAAA,QACL,OAAA,EAAS;AAAA,UACP;AAAA,YACE,IAAA,EAAM,MAAA;AAAA,YACN,IAAA,EAAM,IAAA,CAAK,SAAA,CAAU,EAAE,EAAA,EAAI,WAAW,IAAA,CAAK,EAAA,EAAG,EAAG,IAAA,EAAM,CAAC;AAAA;AAC1D;AACF,OACF;AAAA,IACF;AAAA,GACF;AACF;ACx8BO,SAAS,eAAe,IAAA,EAA+C;AAC5E,EAAA,MAAM,QAAA,GAAW,KAAK,QAAA,IAAY,cAAA;AAClC,EAAA,MAAM,IAAA,GAAOT,IAAAA,CAAK,IAAA,CAAK,SAAA,EAAW,QAAQ,CAAA;AAC1C,EAAA,MAAM,GAAA,GAAM,IAAA,CAAK,GAAA,KAAQ,0BAAU,IAAA,EAAK,CAAA;AAExC,EAAA,IAAI,KAAA,GAA+B,IAAA;AACnC,EAAA,IAAI,cAAA,GAAgC,IAAA;AACpC,EAAA,IAAI,MAAA,GAAS,KAAA;AAEb,EAAA,eAAe,IAAA,GAAwC;AACrD,IAAA,IAAI,CAACG,UAAAA,CAAW,IAAI,CAAA,EAAG,OAAO,IAAA;AAC9B,IAAA,IAAI,MAAA;AACJ,IAAA,IAAI;AACF,MAAA,MAAA,GAAS,MAAMJ,QAAAA,CAAS,IAAA,EAAM,MAAM,CAAA;AAAA,IACtC,CAAA,CAAA,MAAQ;AACN,MAAA,OAAO,IAAA;AAAA,IACT;AACA,IAAA,MAAM,MAAA,GAAS,OAAO,MAAM,CAAA;AAC5B,IAAA,MAAM,KAAK,MAAA,CAAO,IAAA;AAClB,IAAA,MAAM,QAAQ,OAAO,EAAA,CAAG,KAAA,KAAU,QAAA,GAAW,GAAG,KAAA,GAAQ,IAAA;AACxD,IAAA,IAAI,CAAC,OAAO,OAAO,IAAA;AACnB,IAAA,MAAM,UAAU,EAAA,CAAG,OAAA,KAAY,SAAY,IAAA,GAAO,OAAA,CAAQ,GAAG,OAAO,CAAA;AACpE,IAAA,MAAM,WAAW,OAAO,EAAA,CAAG,KAAA,KAAU,QAAA,GAAW,GAAG,KAAA,GAAQ,KAAA;AAC3D,IAAA,MAAM,OAAA,GAAU,cAAc,QAAQ,CAAA;AACtC,IAAA,IAAI,CAAC,SAAS,OAAO,IAAA;AACrB,IAAA,MAAM,uBACJ,OAAO,EAAA,CAAG,YAAA,KAAiB,QAAA,GACvB,GAAG,YAAA,GACH,kBAAA;AACN,IAAA,OAAO;AAAA,MACL,KAAA;AAAA,MACA,OAAA;AAAA,MACA,OAAA;AAAA,MACA,oBAAA;AAAA,MACA,IAAA,EAAM,MAAA,CAAO,OAAA,CAAQ,IAAA;AAAK,KAC5B;AAAA,EACF;AAEA,EAAA,eAAe,IAAA,GAAsB;AACnC,IAAA,IAAI,MAAA,EAAQ;AACZ,IAAA,IAAI,IAAA,CAAK,UAAA,IAAc,CAAC,IAAA,CAAK,YAAW,EAAG;AAC3C,IAAA,MAAA,GAAS,IAAA;AACT,IAAA,IAAI,OAAA;AACJ,IAAA,IAAI;AACF,MAAA,MAAM,EAAA,GAAK,MAAM,IAAA,EAAK;AACtB,MAAA,IAAI,CAAC,EAAA,IAAM,CAAC,EAAA,CAAG,OAAA,EAAS;AACxB,MAAA,OAAA,GAAU,EAAA,CAAG,KAAA;AACb,MAAA,MAAM,KAAA,GAAQ,MAAM,IAAA,CAAK,UAAA,CAAW,GAAG,KAAK,CAAA;AAC5C,MAAA,IAAI,CAAC,KAAA,EAAO;AACV,QAAA,IAAA,CAAK,OAAO,IAAA,CAAK;AAAA,UACf,IAAA,EAAM,iBAAA;AAAA,UACN,EAAA,EAAI,GAAA,EAAI,CAAE,WAAA,EAAY;AAAA,UACtB,OAAO,EAAA,CAAG,KAAA;AAAA,UACV,KAAA,EAAO,CAAA,YAAA,EAAe,EAAA,CAAG,KAAK,CAAA,gBAAA;AAAA,SAC/B,CAAA;AACD,QAAA;AAAA,MACF;AACA,MAAA,IAAI,CAAC,GAAG,IAAA,EAAM;AACZ,QAAA,IAAA,CAAK,OAAO,IAAA,CAAK;AAAA,UACf,IAAA,EAAM,iBAAA;AAAA,UACN,EAAA,EAAI,GAAA,EAAI,CAAE,WAAA,EAAY;AAAA,UACtB,OAAO,EAAA,CAAG,KAAA;AAAA,UACV,KAAA,EAAO;AAAA,SACR,CAAA;AACD,QAAA;AAAA,MACF;AAEA,MAAA,MAAM,cAAA,GAAiB,cAAA,CAAe,EAAA,CAAG,oBAAA,EAAsB,KAAK,CAAA;AACpE,MAAA,MAAM,IAAA,CAAK,cAAc,IAAA,CAAK,cAAA,EAAgB,EAAE,KAAA,EAAO,EAAA,CAAG,OAAO,CAAA;AAEjE,MAAA,MAAM,YAAY,GAAA,EAAI;AACtB,MAAA,MAAM,KAAK,aAAA,CAAc,UAAA;AAAA,QACvB,cAAA;AAAA,QACA,MAAA;AAAA,QACA,EAAA,CAAG,IAAA;AAAA,QACH,EAAE,EAAA,EAAI,SAAA,CAAU,WAAA,EAAY,EAAG,aAAa,WAAA;AAAY,OAC1D;AACA,MAAA,IAAA,CAAK,OAAO,IAAA,CAAK;AAAA,QACf,IAAA,EAAM,oBAAA;AAAA,QACN,EAAA,EAAI,UAAU,WAAA,EAAY;AAAA,QAC1B,cAAA;AAAA,QACA,IAAA,EAAM,MAAA;AAAA,QACN,cAAA,EAAgB,OAAA,CAAQ,EAAA,CAAG,IAAI;AAAA,OAChC,CAAA;AAED,MAAA,MAAM,EAAA,GAAK,KAAK,GAAA,EAAI;AACpB,MAAA,MAAM,KAAA,GAAQ,MAAM,KAAA,CAAM,QAAA,CAAS,GAAG,IAAI,CAAA;AAC1C,MAAA,MAAM,UAAA,GAAa,IAAA,CAAK,GAAA,EAAI,GAAI,EAAA;AAEhC,MAAA,MAAM,aAAa,GAAA,EAAI;AACvB,MAAA,MAAM,KAAK,aAAA,CAAc,UAAA;AAAA,QACvB,cAAA;AAAA,QACA,WAAA;AAAA,QACA,KAAA,CAAM,IAAA;AAAA,QACN,EAAE,EAAA,EAAI,UAAA,CAAW,aAAY,EAAG,WAAA,EAAa,GAAG,KAAA;AAAM,OACxD;AACA,MAAA,IAAA,CAAK,OAAO,IAAA,CAAK;AAAA,QACf,IAAA,EAAM,oBAAA;AAAA,QACN,EAAA,EAAI,WAAW,WAAA,EAAY;AAAA,QAC3B,cAAA;AAAA,QACA,IAAA,EAAM,WAAA;AAAA,QACN,cAAA,EAAgB,OAAA,CAAQ,KAAA,CAAM,IAAI;AAAA,OACnC,CAAA;AACD,MAAA,IAAA,CAAK,OAAO,IAAA,CAAK;AAAA,QACf,IAAA,EAAM,iBAAA;AAAA,QACN,EAAA,EAAI,WAAW,WAAA,EAAY;AAAA,QAC3B,OAAO,EAAA,CAAG,KAAA;AAAA,QACV,cAAA;AAAA,QACA,QAAQ,EAAA,CAAG,IAAA;AAAA,QACX,OAAO,KAAA,CAAM,IAAA;AAAA,QACb;AAAA,OACD,CAAA;AAGD,MAAA,IAAI,cAAA,KAAmB,IAAA,IAAQ,cAAA,KAAmB,EAAA,CAAG,OAAA,EAAS;AAC5D,QAAA,UAAA,CAAW,GAAG,OAAO,CAAA;AAAA,MACvB;AAAA,IACF,SAAS,GAAA,EAAK;AACZ,MAAA,IAAA,CAAK,OAAO,IAAA,CAAK;AAAA,QACf,IAAA,EAAM,iBAAA;AAAA,QACN,EAAA,EAAI,GAAA,EAAI,CAAE,WAAA,EAAY;AAAA,QACtB,KAAA,EAAO,OAAA;AAAA,QACP,OAAO,GAAA,YAAe,KAAA,GAAQ,GAAA,CAAI,OAAA,GAAU,OAAO,GAAG;AAAA,OACvD,CAAA;AAAA,IACH,CAAA,SAAE;AACA,MAAA,MAAA,GAAS,KAAA;AAAA,IACX;AAAA,EACF;AAEA,EAAA,SAAS,WAAW,OAAA,EAAuB;AACzC,IAAA,IAAI,KAAA,gBAAqB,KAAK,CAAA;AAC9B,IAAA,cAAA,GAAiB,OAAA;AACjB,IAAA,KAAA,GAAQ,YAAY,MAAM;AACxB,MAAA,KAAK,IAAA,EAAK;AAAA,IACZ,GAAG,OAAO,CAAA;AAAA,EACZ;AAEA,EAAA,OAAO;AAAA,IACL,KAAA,GAAQ;AACN,MAAA,IAAI,KAAA,EAAO;AAGX,MAAA,KAAK,IAAA,EAAK,CAAE,IAAA,CAAK,CAAC,EAAA,KAAO;AACvB,QAAA,MAAM,OAAA,GAAU,IAAI,OAAA,IAAW,GAAA;AAC/B,QAAA,UAAA,CAAW,OAAO,CAAA;AAAA,MACpB,CAAC,CAAA;AAAA,IACH,CAAA;AAAA,IACA,IAAA,GAAO;AACL,MAAA,IAAI,KAAA,EAAO;AACT,QAAA,aAAA,CAAc,KAAK,CAAA;AACnB,QAAA,KAAA,GAAQ,IAAA;AACR,QAAA,cAAA,GAAiB,IAAA;AAAA,MACnB;AAAA,IACF,CAAA;AAAA,IACA,MAAM,OAAA,GAAU;AACd,MAAA,MAAM,IAAA,EAAK;AAAA,IACb;AAAA,GACF;AACF;AAIA,IAAM,WAAA,GAAc,qBAAA;AAOb,SAAS,cAAc,KAAA,EAA8B;AAC1D,EAAA,MAAM,OAAA,GAAU,MAAM,IAAA,EAAK;AAC3B,EAAA,MAAM,KAAA,GAAQ,OAAA,CAAQ,KAAA,CAAM,WAAW,CAAA;AACvC,EAAA,IAAI,CAAC,OAAO,OAAO,IAAA;AACnB,EAAA,MAAM,CAAA,GAAI,MAAA,CAAO,KAAA,CAAM,CAAC,CAAC,CAAA;AACzB,EAAA,IAAI,CAAC,MAAA,CAAO,QAAA,CAAS,CAAC,CAAA,IAAK,CAAA,IAAK,GAAG,OAAO,IAAA;AAC1C,EAAA,QAAQ,KAAA,CAAM,CAAC,CAAA;AAAG,IAChB,KAAK,GAAA;AACH,MAAA,OAAO,CAAA,GAAI,GAAA;AAAA,IACb,KAAK,GAAA;AACH,MAAA,OAAO,CAAA,GAAI,GAAA;AAAA,IACb,KAAK,GAAA;AACH,MAAA,OAAO,CAAA,GAAI,IAAA;AAAA,IACb,KAAK,GAAA;AACH,MAAA,OAAO,CAAA,GAAI,KAAA;AAAA,IACb;AACE,MAAA,OAAO,IAAA;AAAA;AAEb;AAMA,SAAS,cAAA,CAAe,UAAkB,IAAA,EAAoB;AAC5D,EAAA,MAAM,OAAO,IAAA,CAAK,WAAA,EAAY,CAAE,KAAA,CAAM,GAAG,EAAE,CAAA;AAC3C,EAAA,OAAO,QAAA,CAAS,OAAA,CAAQ,WAAA,EAAa,IAAI,CAAA;AAC3C;AAEA,SAAS,OAAA,CAAQE,KAAAA,EAAc,GAAA,GAAM,GAAA,EAAa;AAChD,EAAA,MAAM,OAAOA,KAAAA,CAAK,OAAA,CAAQ,MAAA,EAAQ,GAAG,EAAE,IAAA,EAAK;AAC5C,EAAA,OAAO,IAAA,CAAK,MAAA,GAAS,GAAA,GAAM,CAAA,EAAG,IAAA,CAAK,MAAM,CAAA,EAAG,GAAA,GAAM,CAAC,CAAC,CAAA,MAAA,CAAA,GAAM,IAAA;AAC5D;ACzNA,IAAM,uBAAA,GAA6C;AAAA,EACjD,oBAAA;AAAA,EACA,oBAAA;AAAA,EACA;AACF,CAAA;AAwJA,eAAsB,gBACpB,IAAA,EACkC;AAClC,EAAA,MAAM,SAAA,GAAY,KAAK,GAAA,EAAI;AAC3B,EAAA,MAAM,UAAA,GAAyB,IAAA,CAAK,IAAA,IAAQ,EAAE,MAAM,MAAA,EAAO;AAC3D,EAAA,MAAM,WAAW,MACf,OAAO,UAAA,KAAe,UAAA,GAAa,YAAW,GAAI,UAAA;AA6BpD,EAAA,SAAS,WAAW,GAAA,EAA+B;AACjD,IAAA,MAAM,IAAA,GAAO,GAAA,CAAI,MAAA,CAAO,aAAA,IAAiB,EAAA;AACzC,IAAA,MAAM,WAAA,GACJ,IAAA,KAAS,WAAA,IAAe,IAAA,KAAS,SAAS,IAAA,KAAS,kBAAA;AACrD,IAAA,IAAI,CAAC,aAAa,OAAO,KAAA;AAGzB,IAAA,IAAI,GAAA,CAAI,OAAA,CAAQ,iBAAiB,CAAA,EAAG,OAAO,KAAA;AAC3C,IAAA,OAAO,IAAA;AAAA,EACT;AAEA,EAAA,SAAS,SAAA,CAAU,KAAsB,GAAA,EAA8B;AACrE,IAAA,MAAM,OAAO,QAAA,EAAS;AACtB,IAAA,IAAI,IAAA,CAAK,IAAA,KAAS,MAAA,EAAQ,OAAO,IAAA;AACjC,IAAA,IAAI,UAAA,CAAW,GAAG,CAAA,EAAG,OAAO,IAAA;AAC5B,IAAA,MAAM,MAAA,GAAS,IAAI,OAAA,CAAQ,aAAA;AAC3B,IAAA,MAAM,QAAA,GAAW,CAAA,OAAA,EAAU,IAAA,CAAK,KAAK,CAAA,CAAA;AACrC,IAAA,IAAI,WAAW,QAAA,EAAU;AACvB,MAAA,GAAA,CAAI,SAAA,CAAU,GAAA,EAAK,EAAE,cAAA,EAAgB,oBAAoB,CAAA;AACzD,MAAA,GAAA,CAAI,IAAI,IAAA,CAAK,SAAA,CAAU,EAAE,KAAA,EAAO,cAAA,EAAgB,CAAC,CAAA;AACjD,MAAA,OAAO,KAAA;AAAA,IACT;AACA,IAAA,OAAO,IAAA;AAAA,EACT;AAuBA,EAAA,SAAS,mBAAmB,GAAA,EAAgD;AAC1E,IAAA,IAAI,CAAC,IAAA,CAAK,KAAA,EAAO,OAAO,IAAA;AAGxB,IAAA,MAAM,MAAA,GAAS,IAAI,OAAA,CAAQ,aAAA;AAC3B,IAAA,MAAM,QAAA,GAAW,CAAA,OAAA,EAAU,IAAA,CAAK,KAAK,CAAA,CAAA;AACrC,IAAA,IAAI,MAAA,KAAW,UAAU,OAAO,IAAA;AAGhC,IAAA,MAAM,MAAA,GAAS,IAAI,GAAA,IAAO,EAAA;AAC1B,IAAA,IAAI,MAAA,CAAO,QAAA,CAAS,GAAG,CAAA,EAAG;AACxB,MAAA,MAAM,EAAA,GAAK,IAAI,eAAA,CAAgB,MAAA,CAAO,KAAA,CAAM,OAAO,OAAA,CAAQ,GAAG,CAAA,GAAI,CAAC,CAAC,CAAA;AACpE,MAAA,MAAM,OAAA,GAAU,EAAA,CAAG,GAAA,CAAI,OAAO,CAAA;AAC9B,MAAA,IAAI,OAAA,IAAW,OAAA,KAAY,IAAA,CAAK,KAAA,EAAO,OAAO,IAAA;AAAA,IAChD;AAGA,IAAA,MAAM,MAAA,GAAS,IAAI,OAAA,CAAQ,MAAA;AAC3B,IAAA,IAAI,OAAO,MAAA,KAAW,QAAA,IAAY,aAAA,CAAc,MAAM,GAAG,OAAO,IAAA;AAEhE,IAAA,OAAO,SAAS,KAAA,GAAQ,SAAA;AAAA,EAC1B;AAEA,EAAA,SAAS,cAAc,MAAA,EAAyB;AAO9C,IAAA,MAAM,IAAA,GAAO,IAAA,CAAK,aAAA,GACb,IAAA,CAAK,kBAAkB,EAAC,GACzB,CAAC,GAAG,uBAAA,EAAyB,GAAI,IAAA,CAAK,cAAA,IAAkB,EAAG,CAAA;AAC/D,IAAA,KAAA,MAAW,WAAW,IAAA,EAAM;AAC1B,MAAA,IAAI,OAAA,KAAY,QAAQ,OAAO,IAAA;AAE/B,MAAA,IAAI,OAAA,CAAQ,QAAA,CAAS,IAAI,CAAA,EAAG;AAC1B,QAAA,MAAM,MAAA,GAAS,OAAA,CAAQ,KAAA,CAAM,CAAA,EAAG,EAAE,CAAA;AAClC,QAAA,IAAI,WAAW,MAAA,IAAU,MAAA,CAAO,WAAW,MAAA,GAAS,GAAG,GAAG,OAAO,IAAA;AAAA,MACnE;AAAA,IACF;AACA,IAAA,OAAO,KAAA;AAAA,EACT;AAEA,EAAA,SAAS,yBAAA,CACP,GAAA,EACA,GAAA,EACA,IAAA,EACM;AACN,IAAA,MAAM,MAAA,GAAS,GAAA,CAAI,OAAA,CAAQ,MAAA,IAAU,IAAA;AACrC,IAAA,MAAM,SAAA,GAAY,IAAA,CAAK,aAAA,GAClB,IAAA,CAAK,kBAAkB,EAAC,GACzB,CAAC,GAAG,uBAAA,EAAyB,GAAI,IAAA,CAAK,cAAA,IAAkB,EAAG,CAAA;AAC/D,IAAA,GAAA,CAAI,SAAA,CAAU,GAAA,EAAK,EAAE,cAAA,EAAgB,oBAAoB,CAAA;AACzD,IAAA,MAAM,OAAA,GACJ,SAAS,SAAA,GACL,MAAA,GACE,WAAW,MAAM,CAAA,wHAAA,EAC+C,MAAM,CAAA,kHAAA,CAAA,GAEtE,CAAA,8LAAA,CAAA,GAGF,CAAA,4HAAA,CAAA;AAEN,IAAA,GAAA,CAAI,GAAA;AAAA,MACF,KAAK,SAAA,CAAU;AAAA,QACb,KAAA,EAAO,uBAAA;AAAA,QACP,OAAA;AAAA;AAAA;AAAA,QAGA,cAAA,EAAgB,MAAA;AAAA,QAChB,cAAA,EAAgB,SAAA;AAAA;AAAA,QAEhB,kBAAA,EAAoB,OAAO,GAAA,CAAI,OAAA,CAAQ,aAAA,KAAkB;AAAA,OAC1D;AAAA,KACH;AAAA,EACF;AAQA,EAAA,SAAS,uBAAA,CAAwB,QAAgB,IAAA,EAAuB;AACtE,IAAA,IAAI,CAAC,IAAA,CAAK,UAAA,CAAW,WAAW,GAAG,OAAO,KAAA;AAC1C,IAAA,IAAI,WAAW,MAAA,IAAU,MAAA,KAAW,YAAY,MAAA,KAAW,KAAA,IAAS,WAAW,OAAA,EAAS;AACtF,MAAA,OAAO,IAAA;AAAA,IACT;AACA,IAAA,OAAO,KAAA;AAAA,EACT;AAEA,EAAA,eAAe,SAAA,CAAU,KAAsB,GAAA,EAAoC;AACjF,IAAA,IAAI,CAAC,SAAA,CAAU,GAAA,EAAK,GAAG,CAAA,EAAG;AAI1B,IAAA,MAAMc,OAAAA,GAAS,MAAM,IAAA,CAAK,gBAAA,EAAiB;AAC3C,IAAA,MAAM,SAAA,GAAY,IAAI,6BAAA,CAA8B;AAAA,MAClD,kBAAA,EAAoB;AAAA,KACrB,CAAA;AAGD,IAAA,MAAM,iBAAA,GAAoB,SAAA;AAC1B,IAAA,IAAI,aAAc,SAAA,EAAsB;AACtC,MAAA,iBAAA,CAAkB,SAAS,CAAA,GAAI,CAAC,GAAA,KAAiB;AAC/C,QAAA,OAAA,CAAQ,KAAA,CAAM,2BAA2B,GAAG,CAAA;AAAA,MAC9C,CAAA;AAAA,IACF;AAEA,IAAA,GAAA,CAAI,EAAA,CAAG,SAAS,MAAM;AACpB,MAAA,KAAK,UAAU,KAAA,EAAM;AACrB,MAAA,KAAKA,QAAO,KAAA,EAAM;AAAA,IACpB,CAAC,CAAA;AAED,IAAA,IAAI;AACF,MAAA,MAAMA,OAAAA,CAAO,QAAQ,SAAS,CAAA;AAC9B,MAAA,MAAM,SAAA,CAAU,aAAA,CAAc,GAAA,EAAK,GAAG,CAAA;AAAA,IACxC,SAAS,GAAA,EAAK;AACZ,MAAA,OAAA,CAAQ,KAAA,CAAM,8BAA8B,GAAG,CAAA;AAC/C,MAAA,IAAI,CAAC,IAAI,WAAA,EAAa;AACpB,QAAA,GAAA,CAAI,SAAA,CAAU,GAAA,EAAK,EAAE,cAAA,EAAgB,oBAAoB,CAAA;AACzD,QAAA,GAAA,CAAI,GAAA;AAAA,UACF,KAAK,SAAA,CAAU;AAAA,YACb,KAAA,EAAO,sBAAA;AAAA,YACP,SAAS,GAAA,YAAe,KAAA,GAAQ,GAAA,CAAI,OAAA,GAAU,OAAO,GAAG;AAAA,WACzD;AAAA,SACH;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,EAAA,SAAS,YAAA,CAAa,MAAuB,GAAA,EAA2B;AACtE,IAAA,GAAA,CAAI,SAAA,CAAU,GAAA,EAAK,EAAE,cAAA,EAAgB,oBAAoB,CAAA;AACzD,IAAA,GAAA,CAAI,GAAA;AAAA,MACF,KAAK,SAAA,CAAU;AAAA,QACb,MAAA,EAAQ,IAAA;AAAA,QACR,SAAA,EAAW,KAAK,IAAA,CAAK,SAAA;AAAA,QACrB,UAAA,EAAY,KAAK,IAAA,CAAK,UAAA;AAAA,QACtB,QAAA,EAAU,IAAA,CAAK,GAAA,EAAI,GAAI;AAAA,OACxB;AAAA,KACH;AAAA,EACF;AAEA,EAAA,SAAS,YAAA,CAAa,KAAsB,GAAA,EAA2B;AACrE,IAAA,IAAI,CAAC,SAAA,CAAU,GAAA,EAAK,GAAG,CAAA,EAAG;AAC1B,IAAA,GAAA,CAAI,UAAU,GAAA,EAAK;AAAA,MACjB,cAAA,EAAgB,mBAAA;AAAA,MAChB,eAAA,EAAiB,wBAAA;AAAA,MACjB,UAAA,EAAY;AAAA,KACb,CAAA;AACD,IAAA,GAAA,CAAI,KAAA,CAAM,CAAA;;AAAA,CAAiB,CAAA;AAC3B,IAAA,MAAM,GAAA,GAAM,IAAA,CAAK,MAAA,CAAO,KAAA,CAAM,CAAC,EAAA,KAAqB;AAClD,MAAA,GAAA,CAAI,KAAA,CAAM,CAAA,MAAA,EAAS,IAAA,CAAK,SAAA,CAAU,EAAE,CAAC;;AAAA,CAAM,CAAA;AAAA,IAC7C,CAAC,CAAA;AACD,IAAA,GAAA,CAAI,EAAA,CAAG,SAAS,GAAG,CAAA;AAAA,EACrB;AAEA,EAAA,eAAe,uBAAA,CACb,KACA,GAAA,EACe;AACf,IAAA,IAAI,CAAC,SAAA,CAAU,GAAA,EAAK,GAAG,CAAA,EAAG;AAC1B,IAAA,MAAM,IAAA,GAAO,MAAM,IAAA,CAAK,aAAA,CAAc,IAAA,EAAK;AAC3C,IAAA,GAAA,CAAI,SAAA,CAAU,GAAA,EAAK,EAAE,cAAA,EAAgB,oBAAoB,CAAA;AACzD,IAAA,GAAA,CAAI,GAAA,CAAI,IAAA,CAAK,SAAA,CAAU,IAAI,CAAC,CAAA;AAAA,EAC9B;AAEA,EAAA,eAAe,qBAAA,CACb,GAAA,EACA,GAAA,EACA,EAAA,EACe;AACf,IAAA,IAAI,CAAC,SAAA,CAAU,GAAA,EAAK,GAAG,CAAA,EAAG;AAC1B,IAAA,IAAI;AACF,MAAA,MAAM,IAAA,GAAO,MAAM,IAAA,CAAK,aAAA,CAAc,KAAK,EAAE,CAAA;AAC7C,MAAA,GAAA,CAAI,SAAA,CAAU,GAAA,EAAK,EAAE,cAAA,EAAgB,oBAAoB,CAAA;AACzD,MAAA,GAAA,CAAI,GAAA,CAAI,IAAA,CAAK,SAAA,CAAU,IAAI,CAAC,CAAA;AAAA,IAC9B,SAAS,GAAA,EAAK;AACZ,MAAA,GAAA,CAAI,SAAA,CAAU,GAAA,EAAK,EAAE,cAAA,EAAgB,oBAAoB,CAAA;AACzD,MAAA,GAAA,CAAI,GAAA;AAAA,QACF,KAAK,SAAA,CAAU;AAAA,UACb,KAAA,EAAO,WAAA;AAAA,UACP,SAAS,GAAA,YAAe,KAAA,GAAQ,GAAA,CAAI,OAAA,GAAU,OAAO,GAAG;AAAA,SACzD;AAAA,OACH;AAAA,IACF;AAAA,EACF;AAEA,EAAA,eAAe,mBAAA,CACb,KACA,GAAA,EACe;AACf,IAAA,IAAI,CAAC,SAAA,CAAU,GAAA,EAAK,GAAG,CAAA,EAAG;AAC1B,IAAA,MAAM,IAAA,CAAK,UAAU,OAAA,EAAQ;AAC7B,IAAA,GAAA,CAAI,SAAA,CAAU,GAAA,EAAK,EAAE,cAAA,EAAgB,oBAAoB,CAAA;AACzD,IAAA,GAAA,CAAI,IAAI,IAAA,CAAK,SAAA,CAAU,EAAE,MAAA,EAAQ,OAAA,EAAS,CAAC,CAAA;AAAA,EAC7C;AA2BA,EAAA,eAAe,gBAAA,CACb,GAAA,EACA,GAAA,EACA,GAAA,EACe;AACf,IAAA,MAAM,KAAA,GAAQ,CAAC,MAAA,EAAgB,IAAA,KAAwB;AACrD,MAAA,GAAA,CAAI,SAAA,CAAU,MAAA,EAAQ,EAAE,cAAA,EAAgB,oBAAoB,CAAA;AAC5D,MAAA,GAAA,CAAI,GAAA,CAAI,IAAA,CAAK,SAAA,CAAU,IAAI,CAAC,CAAA;AAAA,IAC9B,CAAA;AACA,IAAA,MAAM,EAAA,GAAK,IAAI,eAAA,CAAgB,GAAA,CAAI,SAAS,GAAG,CAAA,GAAI,GAAA,CAAI,KAAA,CAAM,IAAI,OAAA,CAAQ,GAAG,CAAA,GAAI,CAAC,IAAI,EAAE,CAAA;AACvF,IAAA,MAAM,GAAA,GAAM,EAAA,CAAG,GAAA,CAAI,KAAK,CAAA;AACxB,IAAA,MAAM,OAAA,GAAU,EAAA,CAAG,GAAA,CAAI,MAAM,CAAA;AAC7B,IAAA,IAAI,CAAC,GAAA,IAAO,CAAC,OAAA,EAAS;AACpB,MAAA,KAAA,CAAM,GAAA,EAAK,EAAE,KAAA,EAAO,qBAAA,EAAuB,CAAA;AAC3C,MAAA;AAAA,IACF;AACA,IAAA,IAAI,CAACT,UAAAA,CAAW,GAAG,CAAA,EAAG;AACpB,MAAA,KAAA,CAAM,GAAA,EAAK,EAAE,KAAA,EAAO,kBAAA,EAAoB,CAAA;AACxC,MAAA;AAAA,IACF;AAIA,IAAA,MAAM,WAAW,OAAA,CACd,OAAA,CAAQ,SAAA,EAAW,GAAG,EACtB,OAAA,CAAQ,QAAA,EAAU,GAAG,CAAA,CACrB,QAAQ,MAAA,EAAQ,EAAE,CAAA,CAClB,KAAA,CAAM,GAAG,GAAG,CAAA;AACf,IAAA,IAAI,QAAA,CAAS,WAAW,CAAA,EAAG;AACzB,MAAA,KAAA,CAAM,GAAA,EAAK,EAAE,KAAA,EAAO,cAAA,EAAgB,CAAA;AACpC,MAAA;AAAA,IACF;AACA,IAAA,IAAI;AACF,MAAA,MAAM,EAAA,GAAK,MAAMR,IAAAA,CAAK,GAAG,CAAA;AACzB,MAAA,IAAI,CAAC,EAAA,CAAG,WAAA,EAAY,EAAG;AACrB,QAAA,KAAA,CAAM,GAAA,EAAK,EAAE,KAAA,EAAO,qBAAA,EAAuB,CAAA;AAC3C,QAAA;AAAA,MACF;AAAA,IACF,CAAA,CAAA,MAAQ;AACN,MAAA,KAAA,CAAM,GAAA,EAAK,EAAE,KAAA,EAAO,eAAA,EAAiB,CAAA;AACrC,MAAA;AAAA,IACF;AACA,IAAA,MAAM,GAAA,GAAME,IAAAA,CAAK,GAAA,EAAK,yBAAyB,CAAA;AAC/C,IAAA,MAAM,MAAA,GAASa,OAAAA,CAAY,GAAA,EAAK,QAAQ,CAAA;AAGxC,IAAA,IAAI,CAAC,MAAA,CAAO,UAAA,CAAWA,OAAAA,CAAY,GAAG,CAAA,IAAK,GAAA,CAAI,QAAA,CAAS,GAAG,CAAA,GAAI,EAAA,GAAK,GAAA,CAAI,CAAA,EAAG;AACzE,MAAA,KAAA,CAAM,GAAA,EAAK,EAAE,KAAA,EAAO,wBAAA,EAA0B,CAAA;AAC9C,MAAA;AAAA,IACF;AACA,IAAA,MAAM,SAAA,GAAY,KAAK,IAAA,GAAO,IAAA;AAC9B,IAAA,MAAM,SAAmB,EAAC;AAC1B,IAAA,IAAI,KAAA,GAAQ,CAAA;AACZ,IAAA,IAAI,OAAA,GAAU,KAAA;AACd,IAAA,MAAM,IAAI,OAAA,CAAc,CAAC,WAAA,EAAa,UAAA,KAAe;AACnD,MAAA,GAAA,CAAI,EAAA,CAAG,QAAQ,CAAA,KAAA,KAAS;AACtB,QAAA,IAAI,OAAA,EAAS;AACb,QAAA,MAAM,GAAA,GAAM,KAAA;AACZ,QAAA,KAAA,IAAS,GAAA,CAAI,MAAA;AACb,QAAA,IAAI,QAAQ,SAAA,EAAW;AACrB,UAAA,OAAA,GAAU,IAAA;AACV,UAAA,KAAA,CAAM,KAAK,EAAE,KAAA,EAAO,gBAAA,EAAkB,QAAA,EAAU,WAAW,CAAA;AAC3D,UAAA,UAAA,CAAW,IAAI,KAAA,CAAM,WAAW,CAAC,CAAA;AACjC,UAAA;AAAA,QACF;AACA,QAAA,MAAA,CAAO,KAAK,GAAG,CAAA;AAAA,MACjB,CAAC,CAAA;AACD,MAAA,GAAA,CAAI,EAAA,CAAG,OAAO,MAAM;AAClB,QAAA,IAAI,CAAC,SAAS,WAAA,EAAY;AAAA,MAC5B,CAAC,CAAA;AACD,MAAA,GAAA,CAAI,EAAA,CAAG,OAAA,EAAS,CAAA,GAAA,KAAO,UAAA,CAAW,GAAG,CAAC,CAAA;AAAA,IACxC,CAAC,CAAA,CAAE,KAAA,CAAM,MAAM,MAAS,CAAA;AACxB,IAAA,IAAI,OAAA,EAAS;AACb,IAAA,IAAI;AACF,MAAA,MAAMX,KAAAA,CAAM,GAAA,EAAK,EAAE,SAAA,EAAW,MAAM,CAAA;AACpC,MAAA,MAAME,SAAAA,CAAU,MAAA,EAAQ,MAAA,CAAO,MAAA,CAAO,MAAM,CAAC,CAAA;AAC7C,MAAA,KAAA,CAAM,KAAK,EAAE,IAAA,EAAM,MAAA,EAAQ,KAAA,EAAO,OAAO,CAAA;AAAA,IAC3C,SAAS,GAAA,EAAK;AACZ,MAAA,KAAA,CAAM,GAAA,EAAK;AAAA,QACT,KAAA,EAAO,cAAA;AAAA,QACP,SAAS,GAAA,YAAe,KAAA,GAAQ,GAAA,CAAI,OAAA,GAAU,OAAO,GAAG;AAAA,OACzD,CAAA;AAAA,IACH;AAAA,EACF;AAcA,EAAA,SAAS,SAAA,CAAU,KAAsB,GAAA,EAA2B;AAClE,IAAA,MAAM,MAAA,GAAU,GAAA,CAAI,OAAA,CAAQ,MAAA,IAAiC,GAAA;AAC7D,IAAA,GAAA,CAAI,SAAA,CAAU,+BAA+B,MAAM,CAAA;AACnD,IAAA,GAAA,CAAI,SAAA,CAAU,QAAQ,QAAQ,CAAA;AAC9B,IAAA,GAAA,CAAI,SAAA,CAAU,oCAAoC,MAAM,CAAA;AACxD,IAAA,GAAA,CAAI,SAAA;AAAA,MACF,8BAAA;AAAA,MACA,GAAA,CAAI,OAAA,CAAQ,gCAAgC,CAAA,IAC1C;AAAA,KACJ;AACA,IAAA,GAAA,CAAI,SAAA;AAAA,MACF,8BAAA;AAAA,MACA;AAAA,KACF;AACA,IAAA,IAAI,GAAA,CAAI,OAAA,CAAQ,wCAAwC,CAAA,KAAM,MAAA,EAAQ;AACpE,MAAA,GAAA,CAAI,SAAA,CAAU,wCAAwC,MAAM,CAAA;AAAA,IAC9D;AAAA,EACF;AAEA,EAAA,MAAM,MAAA,GAAiB,YAAA,CAAa,CAAC,GAAA,EAAK,GAAA,KAAQ;AAChD,IAAA,KAAA,CAAM,YAAY;AAChB,MAAA,IAAI;AACF,QAAA,MAAM,GAAA,GAAM,IAAI,GAAA,IAAO,GAAA;AACvB,QAAA,MAAM,OAAO,GAAA,CAAI,KAAA,CAAM,GAAG,CAAA,CAAE,CAAC,CAAA,IAAK,GAAA;AAKlC,QAAA,IAAI,GAAA,CAAI,OAAA,CAAQ,iBAAiB,CAAA,EAAG;AAClC,UAAA,IAAA,CAAK,OAAO,IAAA,CAAK;AAAA,YACf,IAAA,EAAM,YAAA;AAAA,YACN,EAAA,EAAA,iBAAI,IAAI,IAAA,EAAK,EAAE,WAAA,EAAY;AAAA,YAC3B,MAAM,CAAA,UAAA,EAAa,GAAA,CAAI,MAAM,CAAA,CAAA,EAAI,GAAG,CAAA,MAAA,EAAS,GAAA,CAAI,OAAA,CAAQ,IAAA,IAAQ,GAAG,CAAA,KAAA,EAAQ,MAAA,CAAO,IAAI,OAAA,CAAQ,iBAAiB,CAAC,CAAC,CAAA;AAAA,WACnH,CAAA;AAAA,QACH;AAEA,QAAA,SAAA,CAAU,KAAK,GAAG,CAAA;AAClB,QAAA,IAAI,GAAA,CAAI,WAAW,SAAA,EAAW;AAC5B,UAAA,GAAA,CAAI,UAAU,GAAG,CAAA;AACjB,UAAA,GAAA,CAAI,GAAA,EAAI;AACR,UAAA;AAAA,QACF;AAEA,QAAA,IAAI,IAAA,KAAS,SAAA,IAAa,GAAA,CAAI,MAAA,KAAW,KAAA,EAAO;AAC9C,UAAA,YAAA,CAAa,KAAK,GAAG,CAAA;AACrB,UAAA;AAAA,QACF;AACA,QAAA,IAAI,IAAA,KAAS,SAAA,IAAa,GAAA,CAAI,MAAA,KAAW,KAAA,EAAO;AAC9C,UAAA,YAAA,CAAa,KAAK,GAAG,CAAA;AACrB,UAAA;AAAA,QACF;AACA,QAAA,IAAI,SAAS,MAAA,EAAQ;AACnB,UAAA,MAAM,SAAA,CAAU,KAAK,GAAG,CAAA;AACxB,UAAA;AAAA,QACF;AACA,QAAA,IAAI,IAAA,KAAS,gBAAA,IAAoB,GAAA,CAAI,MAAA,KAAW,KAAA,EAAO;AACrD,UAAA,MAAM,uBAAA,CAAwB,KAAK,GAAG,CAAA;AACtC,UAAA;AAAA,QACF;AACA,QAAA,IAAI,KAAK,UAAA,CAAW,iBAAiB,CAAA,IAAK,GAAA,CAAI,WAAW,KAAA,EAAO;AAC9D,UAAA,MAAM,EAAA,GAAK,IAAA,CAAK,KAAA,CAAM,iBAAA,CAAkB,MAAM,CAAA;AAC9C,UAAA,MAAM,qBAAA,CAAsB,GAAA,EAAK,GAAA,EAAK,EAAE,CAAA;AACxC,UAAA;AAAA,QACF;AACA,QAAA,IAAI,IAAA,KAAS,iBAAA,IAAqB,GAAA,CAAI,MAAA,KAAW,MAAA,EAAQ;AACvD,UAAA,MAAM,mBAAA,CAAoB,KAAK,GAAG,CAAA;AAClC,UAAA;AAAA,QACF;AAEA,QAAA,IAAI,IAAA,KAAS,eAAA,IAAmB,GAAA,CAAI,MAAA,KAAW,MAAA,EAAQ;AAGrD,UAAA,MAAM,IAAA,GAAO,mBAAmB,GAAG,CAAA;AACnC,UAAA,IAAI,SAAS,IAAA,EAAM;AACjB,YAAA,yBAAA,CAA0B,GAAA,EAAK,KAAK,IAAI,CAAA;AACxC,YAAA;AAAA,UACF;AACA,UAAA,MAAM,gBAAA,CAAiB,GAAA,EAAK,GAAA,EAAK,GAAG,CAAA;AACpC,UAAA;AAAA,QACF;AAMA,QAAA,IAAI,IAAA,CAAK,QAAA,IAAY,IAAA,CAAK,UAAA,CAAW,WAAW,CAAA,EAAG;AACjD,UAAA,IAAI,uBAAA,CAAwB,GAAA,CAAI,MAAA,IAAU,KAAA,EAAO,IAAI,CAAA,EAAG;AACtD,YAAA,MAAM,IAAA,GAAO,mBAAmB,GAAG,CAAA;AACnC,YAAA,IAAI,SAAS,IAAA,EAAM;AACjB,cAAA,yBAAA,CAA0B,GAAA,EAAK,KAAK,IAAI,CAAA;AACxC,cAAA;AAAA,YACF;AAAA,UACF;AACA,UAAA,MAAM,UAAU,MAAM,cAAA;AAAA,YACpB,GAAA;AAAA,YACA,GAAA;AAAA,YACA,IAAA;AAAA,YACA,IAAA,CAAK,QAAA;AAAA,YACL,IAAA,CAAK,mBAAA;AAAA,YACL,KAAK,UAAA,KAAe;AAAA,WACtB;AACA,UAAA,IAAI,OAAA,EAAS;AAAA,QACf;AAEA,QAAA,IAAI,IAAA,KAAS,aAAA,IAAiB,GAAA,CAAI,MAAA,KAAW,KAAA,EAAO;AAKlD,UAAA,IAAI;AACF,YAAA,MAAM,MAAA,GAAS,MAAM,oBAAA,EAAqB;AAC1C,YAAA,GAAA,CAAI,SAAA,CAAU,GAAA,EAAK,EAAE,cAAA,EAAgB,oBAAoB,CAAA;AACzD,YAAA,GAAA,CAAI,GAAA,CAAI,IAAA,CAAK,SAAA,CAAU,MAAM,CAAC,CAAA;AAAA,UAChC,SAAS,GAAA,EAAK;AACZ,YAAA,GAAA,CAAI,SAAA,CAAU,GAAA,EAAK,EAAE,cAAA,EAAgB,oBAAoB,CAAA;AACzD,YAAA,GAAA,CAAI,GAAA;AAAA,cACF,KAAK,SAAA,CAAU;AAAA,gBACb,KAAA,EAAO,wBAAA;AAAA,gBACP,SAAS,GAAA,YAAe,KAAA,GAAQ,GAAA,CAAI,OAAA,GAAU,OAAO,GAAG;AAAA,eACzD;AAAA,aACH;AAAA,UACF;AACA,UAAA;AAAA,QACF;AAEA,QAAA,IAAI,IAAA,KAAS,eAAA,IAAmB,GAAA,CAAI,MAAA,KAAW,KAAA,EAAO;AACpD,UAAA,MAAM,MAAA,GAAS,MAAM,gBAAA,EAAiB;AACtC,UAAA,GAAA,CAAI,SAAA,CAAU,GAAA,EAAK,EAAE,cAAA,EAAgB,oBAAoB,CAAA;AACzD,UAAA,GAAA,CAAI,GAAA,CAAI,IAAA,CAAK,SAAA,CAAU,MAAM,CAAC,CAAA;AAC9B,UAAA;AAAA,QACF;AACA,QAAA,IAAI,IAAA,KAAS,eAAA,IAAmB,GAAA,CAAI,MAAA,KAAW,MAAA,EAAQ;AACrD,UAAA,MAAM,IAAA,GAAQ,MAAM,YAAA,CAAa,GAAG,CAAA;AAIpC,UAAA,IAAI,CAAC,IAAA,IAAQ,OAAO,IAAA,CAAK,gBAAgB,QAAA,EAAU;AACjD,YAAA,GAAA,CAAI,SAAA,CAAU,GAAA,EAAK,EAAE,cAAA,EAAgB,oBAAoB,CAAA;AACzD,YAAA,GAAA,CAAI,IAAI,IAAA,CAAK,SAAA,CAAU,EAAE,KAAA,EAAO,qBAAA,EAAuB,CAAC,CAAA;AACxD,YAAA;AAAA,UACF;AACA,UAAA,MAAM,UAAA,GAAa,MAAM,YAAA,EAAa;AACtC,UAAA,MAAM,WAAW,UAAA,CAAW,IAAA,CAAK,OAAK,CAAA,CAAE,EAAA,KAAO,KAAK,WAAW,CAAA;AAC/D,UAAA,IAAI,CAAC,QAAA,EAAU;AACb,YAAA,GAAA,CAAI,SAAA,CAAU,GAAA,EAAK,EAAE,cAAA,EAAgB,oBAAoB,CAAA;AACzD,YAAA,GAAA,CAAI,GAAA;AAAA,cACF,KAAK,SAAA,CAAU;AAAA,gBACb,KAAA,EAAO,0BAAA;AAAA,gBACP,aAAa,IAAA,CAAK;AAAA,eACnB;AAAA,aACH;AACA,YAAA;AAAA,UACF;AACA,UAAA,MAAM,GAAA,GAAM,MAAM,gBAAA,EAAiB;AACnC,UAAA,MAAM,IAAA,GAAO,UAAU,GAAA,EAAK;AAAA,YAC1B,QAAA;AAAA,YACA,GAAI,KAAK,KAAA,GAAQ,EAAE,OAAO,IAAA,CAAK,KAAA,KAAU;AAAC,WAC3C,CAAA;AACD,UAAA,MAAM,iBAAiB,IAAI,CAAA;AAC3B,UAAA,GAAA,CAAI,SAAA,CAAU,GAAA,EAAK,EAAE,cAAA,EAAgB,oBAAoB,CAAA;AACzD,UAAA,GAAA,CAAI,GAAA,CAAI,IAAA,CAAK,SAAA,CAAU,IAAA,CAAK,OAAA,CAAQ,IAAA,CAAK,CAAA,CAAA,KAAK,CAAA,CAAE,EAAA,KAAO,QAAA,CAAS,EAAE,CAAC,CAAC,CAAA;AACpE,UAAA;AAAA,QACF;AACA,QAAA,MAAM,WAAA,GAAc,IAAA,CAAK,KAAA,CAAM,yBAAyB,CAAA;AACxD,QAAA,IAAI,WAAA,IAAe,GAAA,CAAI,MAAA,KAAW,QAAA,EAAU;AAG1C,UAAA,MAAM,EAAA,GAAK,kBAAA,CAAmB,WAAA,CAAY,CAAC,KAAK,EAAE,CAAA;AAClD,UAAA,MAAM,GAAA,GAAM,MAAM,gBAAA,EAAiB;AACnC,UAAA,IAAI,CAAC,IAAI,OAAA,CAAQ,IAAA,CAAK,OAAK,CAAA,CAAE,EAAA,KAAO,EAAE,CAAA,EAAG;AACvC,YAAA,GAAA,CAAI,SAAA,CAAU,GAAA,EAAK,EAAE,cAAA,EAAgB,oBAAoB,CAAA;AACzD,YAAA,GAAA,CAAI,GAAA,CAAI,KAAK,SAAA,CAAU,EAAE,OAAO,kBAAA,EAAoB,EAAA,EAAI,CAAC,CAAA;AACzD,YAAA;AAAA,UACF;AACA,UAAA,MAAM,gBAAA,CAAiB,YAAA,CAAa,GAAA,EAAK,EAAE,CAAC,CAAA;AAC5C,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,EAAA,EAAI,CAAC,CAAA;AACxC,UAAA;AAAA,QACF;AAEA,QAAA,IAAI,IAAA,KAAS,kBAAA,IAAsB,GAAA,CAAI,MAAA,KAAW,KAAA,EAAO;AAIvD,UAAA,IAAI;AACF,YAAA,MAAM,IAAA,GAAO,MAAM,YAAA,EAAa;AAChC,YAAA,GAAA,CAAI,SAAA,CAAU,GAAA,EAAK,EAAE,cAAA,EAAgB,oBAAoB,CAAA;AACzD,YAAA,GAAA,CAAI,IAAI,IAAA,CAAK,SAAA,CAAU,EAAE,IAAA,EAAM,CAAC,CAAA;AAAA,UAClC,SAAS,GAAA,EAAK;AACZ,YAAA,GAAA,CAAI,SAAA,CAAU,GAAA,EAAK,EAAE,cAAA,EAAgB,oBAAoB,CAAA;AACzD,YAAA,GAAA,CAAI,GAAA;AAAA,cACF,KAAK,SAAA,CAAU;AAAA,gBACb,KAAA,EAAO,kBAAA;AAAA,gBACP,SAAS,GAAA,YAAe,KAAA,GAAQ,GAAA,CAAI,OAAA,GAAU,OAAO,GAAG;AAAA,eACzD;AAAA,aACH;AAAA,UACF;AACA,UAAA;AAAA,QACF;AAMA,QAAA,IAAI,IAAA,KAAS,oBAAA,IAAwB,GAAA,CAAI,MAAA,KAAW,KAAA,EAAO;AACzD,UAAA,IAAI,CAAC,KAAK,QAAA,EAAU;AAClB,YAAA,GAAA,CAAI,SAAA,CAAU,GAAA,EAAK,EAAE,cAAA,EAAgB,oBAAoB,CAAA;AACzD,YAAA,GAAA,CAAI,IAAI,IAAA,CAAK,SAAA,CAAU,EAAE,KAAA,EAAO,0BAAA,EAA4B,CAAC,CAAA;AAC7D,YAAA;AAAA,UACF;AACA,UAAA,IAAI;AACF,YAAA,MAAM,OAAA,GAAU,MAAM,IAAA,CAAK,QAAA,CAAS,WAAA,EAAY;AAChD,YAAA,GAAA,CAAI,SAAA,CAAU,GAAA,EAAK,EAAE,cAAA,EAAgB,oBAAoB,CAAA;AACzD,YAAA,GAAA,CAAI,IAAI,IAAA,CAAK,SAAA,CAAU,EAAE,OAAA,EAAS,CAAC,CAAA;AAAA,UACrC,SAAS,GAAA,EAAK;AACZ,YAAA,GAAA,CAAI,SAAA,CAAU,GAAA,EAAK,EAAE,cAAA,EAAgB,oBAAoB,CAAA;AACzD,YAAA,GAAA,CAAI,GAAA;AAAA,cACF,KAAK,SAAA,CAAU;AAAA,gBACb,KAAA,EAAO,qBAAA;AAAA,gBACP,SAAS,GAAA,YAAe,KAAA,GAAQ,GAAA,CAAI,OAAA,GAAU,OAAO,GAAG;AAAA,eACzD;AAAA,aACH;AAAA,UACF;AACA,UAAA;AAAA,QACF;AACA,QAAA,MAAM,eAAA,GAAkB,IAAA,CAAK,KAAA,CAAM,8BAA8B,CAAA;AACjE,QAAA,IAAI,eAAA,IAAmB,GAAA,CAAI,MAAA,KAAW,KAAA,EAAO;AAC3C,UAAA,IAAI,CAAC,KAAK,QAAA,EAAU;AAClB,YAAA,GAAA,CAAI,SAAA,CAAU,GAAA,EAAK,EAAE,cAAA,EAAgB,oBAAoB,CAAA;AACzD,YAAA,GAAA,CAAI,IAAI,IAAA,CAAK,SAAA,CAAU,EAAE,KAAA,EAAO,0BAAA,EAA4B,CAAC,CAAA;AAC7D,YAAA;AAAA,UACF;AACA,UAAA,MAAM,KAAA,GAAQ,kBAAA,CAAmB,eAAA,CAAgB,CAAC,KAAK,EAAE,CAAA;AACzD,UAAA,MAAM,GAAA,GAAM,MAAM,IAAA,CAAK,QAAA,CAAS,UAAU,KAAK,CAAA;AAC/C,UAAA,GAAA,CAAI,SAAA,CAAU,GAAA,CAAI,EAAA,GAAK,GAAA,GAAM,GAAA,EAAK;AAAA,YAChC,cAAA,EAAgB;AAAA,WACjB,CAAA;AACD,UAAA,GAAA,CAAI,GAAA,CAAI,IAAA,CAAK,SAAA,CAAU,GAAG,CAAC,CAAA;AAC3B,UAAA;AAAA,QACF;AACA,QAAA,IAAI,IAAA,KAAS,kBAAA,IAAsB,GAAA,CAAI,MAAA,KAAW,MAAA,EAAQ;AACxD,UAAA,IAAI,CAAC,KAAK,QAAA,EAAU;AAClB,YAAA,GAAA,CAAI,SAAA,CAAU,GAAA,EAAK,EAAE,cAAA,EAAgB,oBAAoB,CAAA;AACzD,YAAA,GAAA,CAAI,IAAI,IAAA,CAAK,SAAA,CAAU,EAAE,KAAA,EAAO,0BAAA,EAA4B,CAAC,CAAA;AAC7D,YAAA;AAAA,UACF;AACA,UAAA,MAAM,IAAA,GAAQ,MAAM,YAAA,CAAa,GAAG,CAAA;AAKpC,UAAA,IACE,CAAC,QACD,OAAO,IAAA,CAAK,UAAU,QAAA,IACtB,OAAO,IAAA,CAAK,QAAA,KAAa,QAAA,EACzB;AACA,YAAA,GAAA,CAAI,SAAA,CAAU,GAAA,EAAK,EAAE,cAAA,EAAgB,oBAAoB,CAAA;AACzD,YAAA,GAAA,CAAI,GAAA;AAAA,cACF,KAAK,SAAA,CAAU;AAAA,gBACb,KAAA,EAAO,cAAA;AAAA,gBACP,OAAA,EAAS;AAAA,eACV;AAAA,aACH;AACA,YAAA;AAAA,UACF;AACA,UAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,QAAA,CAAS,QAAA;AAAA,YACjC,IAAA,CAAK,KAAA;AAAA,YACL,IAAA,CAAK,QAAA;AAAA,YACL,IAAA,CAAK,QAAQ;AAAC,WAChB;AACA,UAAA,GAAA,CAAI,SAAA,CAAU,MAAA,CAAO,EAAA,GAAK,GAAA,GAAM,GAAA,EAAK;AAAA,YACnC,cAAA,EAAgB;AAAA,WACjB,CAAA;AACD,UAAA,GAAA,CAAI,GAAA,CAAI,IAAA,CAAK,SAAA,CAAU,MAAM,CAAC,CAAA;AAC9B,UAAA;AAAA,QACF;AAEA,QAAA,IAAI,IAAA,KAAS,WAAA,IAAe,GAAA,CAAI,MAAA,KAAW,KAAA,EAAO;AAChD,UAAA,IAAI,CAAC,KAAK,iBAAA,EAAmB;AAC3B,YAAA,GAAA,CAAI,SAAA,CAAU,GAAA,EAAK,EAAE,cAAA,EAAgB,oBAAoB,CAAA;AACzD,YAAA,GAAA,CAAI,GAAA;AAAA,cACF,KAAK,SAAA,CAAU;AAAA,gBACb,KAAA,EAAO,uBAAA;AAAA,gBACP,OAAA,EACE;AAAA,eAEH;AAAA,aACH;AACA,YAAA;AAAA,UACF;AACA,UAAA,IAAI;AACF,YAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,iBAAA,EAAkB;AAC9C,YAAA,GAAA,CAAI,SAAA,CAAU,GAAA,EAAK,EAAE,cAAA,EAAgB,oBAAoB,CAAA;AACzD,YAAA,GAAA,CAAI,IAAI,IAAA,CAAK,SAAA,CAAU,EAAE,QAAA,EAAU,CAAC,CAAA;AAAA,UACtC,SAAS,GAAA,EAAK;AACZ,YAAA,GAAA,CAAI,SAAA,CAAU,GAAA,EAAK,EAAE,cAAA,EAAgB,oBAAoB,CAAA;AACzD,YAAA,GAAA,CAAI,GAAA;AAAA,cACF,KAAK,SAAA,CAAU;AAAA,gBACb,KAAA,EAAO,aAAA;AAAA,gBACP,SAAS,GAAA,YAAe,KAAA,GAAQ,GAAA,CAAI,OAAA,GAAU,OAAO,GAAG;AAAA,eACzD;AAAA,aACH;AAAA,UACF;AACA,UAAA;AAAA,QACF;AAEA,QAAA,GAAA,CAAI,SAAA,CAAU,GAAA,EAAK,EAAE,cAAA,EAAgB,oBAAoB,CAAA;AACzD,QAAA,GAAA,CAAI,GAAA,CAAI,KAAK,SAAA,CAAU,EAAE,OAAO,WAAA,EAAa,IAAA,EAAM,CAAC,CAAA;AAAA,MACtD,SAAS,GAAA,EAAK;AACZ,QAAA,IAAI,CAAC,IAAI,WAAA,EAAa;AACpB,UAAA,GAAA,CAAI,SAAA,CAAU,GAAA,EAAK,EAAE,cAAA,EAAgB,oBAAoB,CAAA;AACzD,UAAA,GAAA,CAAI,GAAA;AAAA,YACF,KAAK,SAAA,CAAU;AAAA,cACb,KAAA,EAAO,gBAAA;AAAA,cACP,SAAS,GAAA,YAAe,KAAA,GAAQ,GAAA,CAAI,OAAA,GAAU,OAAO,GAAG;AAAA,aACzD;AAAA,WACH;AAAA,QACF;AAAA,MACF;AAAA,IACF,CAAA,GAAG;AAAA,EACL,CAAC,CAAA;AAaD,EAAA,MAAM,MAAM,IAAI,eAAA,CAAgB,EAAE,QAAA,EAAU,MAAM,CAAA;AAClD,EAAA,MAAA,CAAO,EAAA,CAAG,SAAA,EAAW,CAAC,GAAA,EAAK,QAAQ,IAAA,KAAS;AAC1C,IAAA,MAAM,GAAA,GAAM,IAAI,GAAA,IAAO,GAAA;AACvB,IAAA,MAAM,OAAO,GAAA,CAAI,KAAA,CAAM,GAAG,CAAA,CAAE,CAAC,CAAA,IAAK,GAAA;AAClC,IAAA,MAAM,QAAA,GAAW,IAAA,CAAK,KAAA,CAAM,4BAA4B,CAAA;AACxD,IAAA,IAAI,CAAC,QAAA,EAAU;AACb,MAAA,MAAA,CAAO,OAAA,EAAQ;AACf,MAAA;AAAA,IACF;AACA,IAAA,IAAI,CAAC,IAAA,CAAK,QAAA,IAAY,IAAA,CAAK,eAAe,IAAA,EAAM;AAC9C,MAAA,aAAA,CAAc,MAAA,EAAQ,KAAK,oBAAoB,CAAA;AAC/C,MAAA;AAAA,IACF;AAGA,IAAA,MAAM,IAAA,GAAO,mBAAmB,GAAG,CAAA;AACnC,IAAA,IAAI,SAAS,IAAA,EAAM;AACjB,MAAA,aAAA,CAAc,MAAA,EAAQ,GAAA,EAAK,IAAA,KAAS,SAAA,GAAY,kBAAkB,WAAW,CAAA;AAC7E,MAAA;AAAA,IACF;AACA,IAAA,MAAM,EAAA,GAAK,SAAS,CAAC,CAAA;AACrB,IAAA,IAAI,CAAC,EAAA,EAAI;AACP,MAAA,aAAA,CAAc,MAAA,EAAQ,KAAK,YAAY,CAAA;AACvC,MAAA;AAAA,IACF;AAGA,IAAA,MAAM,IAAA,GAAO,IAAA,CAAK,QAAA,CAAS,cAAA,CAAe,EAAE,CAAA;AAC5C,IAAA,IAAI,CAAC,IAAA,EAAM;AACT,MAAA,aAAA,CAAc,MAAA,EAAQ,KAAK,mBAAmB,CAAA;AAC9C,MAAA;AAAA,IACF;AACA,IAAA,IAAI,IAAA,CAAK,QAAQ,IAAA,EAAM;AACrB,MAAA,aAAA,CAAc,MAAA,EAAQ,KAAK,iBAAiB,CAAA;AAC5C,MAAA;AAAA,IACF;AAKA,IAAA,IACE,IAAA,CAAK,WAAW,QAAA,IAChB,IAAA,CAAK,WAAW,QAAA,IAChB,IAAA,CAAK,WAAW,OAAA,EAChB;AACA,MAAA,aAAA;AAAA,QACE,MAAA;AAAA,QACA,GAAA;AAAA,QACA,CAAA,QAAA,EAAW,KAAK,MAAM,CAAA,CAAA;AAAA,QACtB,WAAW,IAAA,CAAK,EAAE,GAAG,IAAA,CAAK,IAAA,GAAO,KAAK,IAAA,CAAK,IAAI,CAAA,CAAA,CAAA,GAAM,EAAE,QAAQ,IAAA,CAAK,MAAM,yDACjB,IAAA,CAAK,IAAA,IAAQ,KAAK,EAAE,CAAA;AAAA,OAC/E;AACA,MAAA;AAAA,IACF;AACA,IAAA,GAAA,CAAI,aAAA,CAAc,GAAA,EAAK,MAAA,EAAQ,IAAA,EAAM,CAAA,EAAA,KAAM;AACzC,MAAA,kBAAA,CAAmB,EAAA,EAAI,GAAA,EAAK,IAAA,CAAK,EAAA,EAAI,KAAK,QAAS,CAAA;AAAA,IACrD,CAAC,CAAA;AAAA,EACH,CAAC,CAAA;AAED,EAAA,MAAM,IAAA,GAAO,KAAK,IAAA,IAAQ,WAAA;AAC1B,EAAA,MAAM,IAAI,OAAA,CAAc,CAACC,QAAAA,EAAS,MAAA,KAAW;AAC3C,IAAA,MAAA,CAAO,IAAA,CAAK,SAAS,MAAM,CAAA;AAC3B,IAAA,MAAA,CAAO,OAAO,IAAA,CAAK,IAAA,EAAM,IAAA,EAAM,MAAMA,UAAS,CAAA;AAAA,EAChD,CAAC,CAAA;AAED,EAAA,OAAO;AAAA,IACL,GAAA,EAAK,CAAA,OAAA,EAAU,IAAI,CAAA,CAAA,EAAI,KAAK,IAAI,CAAA,CAAA;AAAA,IAChC,MAAM,IAAA,GAAO;AAMX,MAAA,GAAA,CAAI,KAAA,EAAM;AACV,MAAA,MAAM,IAAI,QAAc,CAACA,QAAAA,KAAY,OAAO,KAAA,CAAM,MAAMA,QAAAA,EAAS,CAAC,CAAA;AAAA,IACpE;AAAA,GACF;AACF;AAQA,SAAS,aAAA,CACP,MAAA,EACA,MAAA,EACA,MAAA,EACA,OAAA,EACM;AACN,EAAA,MAAM,UAAA,GAAa,CAAA,EAAG,MAAM,CAAA,CAAA,EAAI,MAAM,CAAA,CAAA;AACtC,EAAA,MAAM,IAAA,GAA4C,EAAE,KAAA,EAAO,MAAA,EAAO;AAClE,EAAA,IAAI,OAAA,OAAc,OAAA,GAAU,OAAA;AAC5B,EAAA,IAAI;AACF,IAAA,MAAA,CAAO,KAAA;AAAA,MACL,YAAY,UAAU,CAAA;AAAA;AAAA;AAAA;AAAA,CAAA,GAGpB,IAAA,CAAK,SAAA,CAAU,IAAI,CAAA,GACnB;AAAA;AAAA,KACJ;AAAA,EACF,CAAA,CAAA,MAAQ;AAAA,EAER;AACA,EAAA,MAAA,CAAO,OAAA,EAAQ;AACjB;AASA,SAAS,kBAAA,CACP,EAAA,EACA,GAAA,EACA,SAAA,EACA,QAAA,EACM;AAKN,EAAA,MAAM,QAAQ,IAAI,eAAA;AAAA,IAAA,CACf,GAAA,CAAI,GAAA,IAAO,EAAA,EAAI,QAAA,CAAS,GAAG,CAAA,GAAA,CAAK,GAAA,CAAI,GAAA,IAAO,EAAA,EAAI,KAAA,CAAM,GAAG,CAAA,CAAE,CAAC,CAAA,GAAI;AAAA,GAClE;AACA,EAAA,MAAM,OAAO,gBAAA,CAAiB,KAAA,CAAM,GAAA,CAAI,MAAM,GAAG,EAAE,CAAA;AACnD,EAAA,MAAM,OAAO,gBAAA,CAAiB,KAAA,CAAM,GAAA,CAAI,MAAM,GAAG,EAAE,CAAA;AAKnD,EAAA,MAAM,qBAAqB,GAAA,GAAM,IAAA;AAEjC,EAAA,MAAM,SAAS,QAAA,CAAS,SAAA;AAAA,IACtB,SAAA;AAAA,IACA,EAAE,MAAM,IAAA,EAAK;AAAA,IACb,CAAA,KAAA,KAAS;AACP,MAAA,IAAI,EAAA,CAAG,UAAA,KAAe,EAAA,CAAG,IAAA,EAAM;AAC/B,MAAA,IAAI,EAAA,CAAG,iBAAiB,kBAAA,EAAoB;AAC5C,MAAA,EAAA,CAAG,IAAA;AAAA,QACD,IAAA,CAAK,SAAA,CAAU,EAAE,IAAA,EAAM,MAAA,EAAQ,KAAK,KAAA,CAAM,QAAA,CAAS,QAAQ,CAAA,EAAG;AAAA,OAChE;AAAA,IACF,CAAA;AAAA,IACA,CAAA,GAAA,KAAO;AACL,MAAA,IAAI,EAAA,CAAG,UAAA,KAAe,EAAA,CAAG,IAAA,EAAM;AAC/B,MAAA,EAAA,CAAG,IAAA;AAAA,QACD,KAAK,SAAA,CAAU;AAAA,UACb,IAAA,EAAM,MAAA;AAAA,UACN,UAAU,GAAA,CAAI,QAAA;AAAA,UACd,GAAI,IAAI,MAAA,IAAU,IAAA,GAAO,EAAE,MAAA,EAAQ,GAAA,CAAI,MAAA,EAAO,GAAI;AAAC,SACpD;AAAA,OACH;AAGA,MAAA,IAAI;AACF,QAAA,EAAA,CAAG,KAAA,CAAM,KAAM,gBAAgB,CAAA;AAAA,MACjC,CAAA,CAAA,MAAQ;AAAA,MAER;AAAA,IACF;AAAA,GACF;AAEA,EAAA,IAAI,CAAC,MAAA,EAAQ;AAGX,IAAA,IAAI;AACF,MAAA,EAAA,CAAG,KAAA,CAAM,MAAM,wBAAwB,CAAA;AAAA,IACzC,CAAA,CAAA,MAAQ;AAAA,IAER;AACA,IAAA;AAAA,EACF;AAEA,EAAA,EAAA,CAAG,EAAA,CAAG,SAAA,EAAW,CAAC,GAAA,EAAK,QAAA,KAAa;AAClC,IAAA,IAAI,QAAA,EAAU;AAEZ,MAAA;AAAA,IACF;AACA,IAAA,IAAI,KAAA;AACJ,IAAA,IAAI;AACF,MAAA,KAAA,GAAQ,IAAA,CAAK,KAAA,CAAM,GAAA,CAAI,QAAA,CAAS,MAAM,CAAC,CAAA;AAAA,IACzC,CAAA,CAAA,MAAQ;AACN,MAAA;AAAA,IACF;AACA,IAAA,IAAI,CAAC,KAAA,IAAS,OAAO,KAAA,KAAU,QAAA,EAAU;AACzC,IAAA,MAAM,CAAA,GAAI,KAAA;AACV,IAAA,QAAQ,EAAE,IAAA;AAAM,MACd,KAAK,OAAA,EAAS;AAGZ,QAAA,IAAI,OAAO,CAAA,CAAE,IAAA,KAAS,QAAA,EAAU;AAC9B,UAAA,MAAA,CAAO,KAAA,CAAM,EAAE,IAAI,CAAA;AAAA,QACrB,CAAA,MAAA,IAAW,OAAO,CAAA,CAAE,GAAA,KAAQ,QAAA,EAAU;AACpC,UAAA,IAAI;AACF,YAAA,MAAA,CAAO,KAAA,CAAM,OAAO,IAAA,CAAK,CAAA,CAAE,KAAK,QAAQ,CAAA,CAAE,QAAA,CAAS,MAAM,CAAC,CAAA;AAAA,UAC5D,CAAA,CAAA,MAAQ;AAAA,UAER;AAAA,QACF;AACA,QAAA;AAAA,MACF;AAAA,MACA,KAAK,QAAA,EAAU;AACb,QAAA,MAAM,CAAA,GACJ,OAAO,CAAA,CAAE,IAAA,KAAS,QAAA,IAAY,CAAA,CAAE,IAAA,GAAO,CAAA,GAAI,IAAA,CAAK,KAAA,CAAM,CAAA,CAAE,IAAI,CAAA,GAAI,IAAA;AAClE,QAAA,MAAM,CAAA,GACJ,OAAO,CAAA,CAAE,IAAA,KAAS,QAAA,IAAY,CAAA,CAAE,IAAA,GAAO,CAAA,GAAI,IAAA,CAAK,KAAA,CAAM,CAAA,CAAE,IAAI,CAAA,GAAI,IAAA;AAClE,QAAA,IAAI,CAAA,IAAK,CAAA,EAAG,MAAA,CAAO,MAAA,CAAO,GAAG,CAAC,CAAA;AAC9B,QAAA;AAAA,MACF;AAAA,MACA,KAAK,MAAA;AAEH,QAAA,IAAI;AACF,UAAA,EAAA,CAAG,KAAK,IAAA,CAAK,SAAA,CAAU,EAAE,IAAA,EAAM,MAAA,EAAQ,CAAC,CAAA;AAAA,QAC1C,CAAA,CAAA,MAAQ;AAAA,QAER;AACA,QAAA;AAAA;AAEJ,EACF,CAAC,CAAA;AAED,EAAA,EAAA,CAAG,EAAA,CAAG,SAAS,MAAM;AACnB,IAAA,MAAA,CAAO,MAAA,EAAO;AAAA,EAChB,CAAC,CAAA;AACD,EAAA,EAAA,CAAG,EAAA,CAAG,SAAS,MAAM;AACnB,IAAA,MAAA,CAAO,MAAA,EAAO;AAAA,EAChB,CAAC,CAAA;AACH;AAEA,SAAS,gBAAA,CAAiB,KAAoB,QAAA,EAA0B;AACtE,EAAA,IAAI,CAAC,KAAK,OAAO,QAAA;AACjB,EAAA,MAAM,CAAA,GAAI,MAAA,CAAO,QAAA,CAAS,GAAA,EAAK,EAAE,CAAA;AACjC,EAAA,OAAO,OAAO,QAAA,CAAS,CAAC,CAAA,IAAK,CAAA,GAAI,IAAI,CAAA,GAAI,QAAA;AAC3C;AAEA,SAAS,QAAA,CACP,GAAA,EACA,QAAA,EACA,GAAA,EACA,GAAA,EACQ;AACR,EAAA,IAAI,CAAC,KAAK,OAAO,QAAA;AACjB,EAAA,MAAM,CAAA,GAAI,MAAA,CAAO,QAAA,CAAS,GAAA,EAAK,EAAE,CAAA;AACjC,EAAA,IAAI,CAAC,MAAA,CAAO,QAAA,CAAS,CAAC,GAAG,OAAO,QAAA;AAChC,EAAA,IAAI,CAAA,GAAI,KAAK,OAAO,GAAA;AACpB,EAAA,IAAI,CAAA,GAAI,KAAK,OAAO,GAAA;AACpB,EAAA,OAAO,CAAA;AACT;AAcA,eAAe,eACb,GAAA,EACA,GAAA,EACA,MACA,QAAA,EACA,mBAAA,EACA,aAAa,KAAA,EACK;AAClB,EAAA,MAAM,IAAA,GAAO,CAAC,MAAA,EAAgB,IAAA,KAAwB;AACpD,IAAA,GAAA,CAAI,SAAA,CAAU,MAAA,EAAQ,EAAE,cAAA,EAAgB,oBAAoB,CAAA;AAC5D,IAAA,GAAA,CAAI,GAAA,CAAI,IAAA,CAAK,SAAA,CAAU,IAAI,CAAC,CAAA;AAAA,EAC9B,CAAA;AAEA,EAAA,IAAI,IAAA,KAAS,WAAA,IAAe,GAAA,CAAI,MAAA,KAAW,KAAA,EAAO;AAChD,IAAA,IAAA,CAAK,KAAK,EAAE,QAAA,EAAU,QAAA,CAAS,IAAA,IAAQ,CAAA;AACvC,IAAA,OAAO,IAAA;AAAA,EACT;AAMA,EAAA,IAAI,IAAA,KAAS,iBAAA,IAAqB,GAAA,CAAI,MAAA,KAAW,MAAA,EAAQ;AACvD,IAAA,IAAI,CAAC,mBAAA,EAAqB;AACxB,MAAA,IAAA,CAAK,GAAA,EAAK;AAAA,QACR,KAAA,EAAO,+BAAA;AAAA,QACP,OAAA,EACE;AAAA,OAEH,CAAA;AACD,MAAA,OAAO,IAAA;AAAA,IACT;AACA,IAAA,MAAM,IAAA,GAAO,MAAM,YAAA,CAAa,GAAG,CAAA;AACnC,IAAA,IAAI,CAAC,IAAA,IAAQ,OAAO,IAAA,KAAS,QAAA,EAAU;AACrC,MAAA,IAAA,CAAK,GAAA,EAAK,EAAE,KAAA,EAAO,cAAA,EAAgB,CAAA;AACnC,MAAA,OAAO,IAAA;AAAA,IACT;AACA,IAAA,MAAM,CAAA,GAAI,IAAA;AACV,IAAA,MAAM,UAAU,OAAO,CAAA,CAAE,OAAA,KAAY,QAAA,GAAW,EAAE,OAAA,GAAU,EAAA;AAC5D,IAAA,IAAI,CAAC,OAAA,EAAS;AACZ,MAAA,IAAA,CAAK,GAAA,EAAK,EAAE,KAAA,EAAO,iBAAA,EAAmB,CAAA;AACtC,MAAA,OAAO,IAAA;AAAA,IACT;AAOA,IAAA,IAAI,GAAA,GACF,OAAO,CAAA,CAAE,GAAA,KAAQ,QAAA,IAAY,EAAE,GAAA,CAAI,MAAA,GAAS,CAAA,GAAI,CAAA,CAAE,GAAA,GAAM,IAAA;AAC1D,IAAA,IAAI,gBACF,OAAO,CAAA,CAAE,aAAA,KAAkB,QAAA,GAAW,EAAE,aAAA,GAAgB,EAAA;AAC1D,IAAA,IAAI,CAAC,GAAA,EAAK;AACR,MAAA,IAAI;AACF,QAAA,MAAM,MAAA,GAAS,MAAM,oBAAA,EAAqB;AAC1C,QAAA,MAAM,KAAK,aAAA,GACP,aAAA,CAAc,QAAQ,aAAa,CAAA,GACnC,mBAAmB,MAAM,CAAA;AAC7B,QAAA,IAAI,EAAA,EAAI;AACN,UAAA,GAAA,GAAM,EAAA,CAAG,IAAA;AACT,UAAA,aAAA,GAAgB,EAAA,CAAG,IAAA;AAAA,QACrB;AAAA,MACF,CAAA,CAAA,MAAQ;AAAA,MAER;AAAA,IACF;AACA,IAAA,IAAI,CAAC,GAAA,EAAK;AACR,MAAA,GAAA,GAAM,QAAQ,GAAA,EAAI;AAClB,MAAA,OAAA,CAAQ,IAAA;AAAA,QACN,CAAA,gDAAA,EAAmD,OAAO,CAAA,iIAAA,EAED,GAAG,CAAA;AAAA,OAC9D;AAAA,IACF;AACA,IAAA,IAAI,CAAC,eAAe,aAAA,GAAgB,SAAA;AACpC,IAAA,MAAM,QAAA,GAAW,MAAM,mBAAA,CAAoB,OAAO,CAAA;AAClD,IAAA,IAAI,CAAC,QAAA,EAAU;AACb,MAAA,IAAA,CAAK,GAAA,EAAK,EAAE,KAAA,EAAO,mBAAA,EAAqB,SAAS,CAAA;AACjD,MAAA,OAAO,IAAA;AAAA,IACT;AACA,IAAA,IAAI;AACF,MAAA,MAAM,eAAA,GACJ,OAAO,CAAA,CAAE,eAAA,KAAoB,QAAA,IAAY,EAAE,eAAA,CAAgB,MAAA,GAAS,CAAA,GAChE,CAAA,CAAE,eAAA,GACF,KAAA,CAAA;AACN,MAAA,MAAM,YAAA,GAAe,MAAM,QAAA,CAAS,YAAA,CAAa;AAAA,QAC/C,GAAA;AAAA,QACA,GAAI,eAAA,GAAkB,EAAE,eAAA,KAAoB;AAAC,OAC9C,CAAA;AACD,MAAA,MAAM,IAAA,GAAO,SAAS,UAAA,CAAW;AAAA,QAC/B,aAAA;AAAA,QACA,GAAA;AAAA,QACA,YAAA;AAAA,QACA,WAAA,EAAa,OAAA;AAAA,QACb,GAAI,OAAO,CAAA,CAAE,MAAA,KAAW,QAAA,GAAW,EAAE,aAAA,EAAe,CAAA,CAAE,MAAA,EAAO,GAAI,EAAC;AAAA,QAClE,GAAI,OAAO,CAAA,CAAE,KAAA,KAAU,QAAA,GAAW,EAAE,KAAA,EAAO,CAAA,CAAE,KAAA,EAAM,GAAI,EAAC;AAAA,QACxD,GAAI,SAAS,cAAA,GACT,EAAE,gBAAgB,QAAA,CAAS,cAAA,KAC3B;AAAC,OACN,CAAA;AACD,MAAA,IAAA,CAAK,KAAK,IAAI,CAAA;AAAA,IAChB,SAAS,GAAA,EAAK;AACZ,MAAA,IAAA,CAAK,GAAA,EAAK;AAAA,QACR,KAAA,EAAO,oBAAA;AAAA,QACP,SAAS,GAAA,YAAe,KAAA,GAAQ,GAAA,CAAI,OAAA,GAAU,OAAO,GAAG;AAAA,OACzD,CAAA;AAAA,IACH;AACA,IAAA,OAAO,IAAA;AAAA,EACT;AAMA,EAAA,IAAI,IAAA,KAAS,oBAAA,IAAwB,GAAA,CAAI,MAAA,KAAW,MAAA,EAAQ;AAC1D,IAAA,IAAI,CAAC,UAAA,EAAY;AACf,MAAA,IAAA,CAAK,GAAA,EAAK;AAAA,QACR,KAAA,EAAO,oBAAA;AAAA,QACP,OAAA,EACE;AAAA,OAEH,CAAA;AACD,MAAA,OAAO,IAAA;AAAA,IACT;AACA,IAAA,MAAM,IAAA,GAAO,MAAM,YAAA,CAAa,GAAG,CAAA;AACnC,IAAA,IAAI,CAAC,IAAA,IAAQ,OAAO,IAAA,KAAS,QAAA,EAAU;AACrC,MAAA,IAAA,CAAK,GAAA,EAAK,EAAE,KAAA,EAAO,cAAA,EAAgB,CAAA;AACnC,MAAA,OAAO,IAAA;AAAA,IACT;AACA,IAAA,MAAM,CAAA,GAAI,IAAA;AACV,IAAA,MAAM,IAAA,GAAO,KAAA,CAAM,OAAA,CAAQ,CAAA,CAAE,IAAI,CAAA,GAC5B,CAAA,CAAE,IAAA,CAAmB,MAAA,CAAO,CAAC,CAAA,KAAmB,OAAO,CAAA,KAAM,QAAQ,IACtE,EAAC;AACL,IAAA,IAAI,IAAA,CAAK,WAAW,CAAA,EAAG;AACrB,MAAA,IAAA,CAAK,GAAA,EAAK,EAAE,KAAA,EAAO,cAAA,EAAgB,CAAA;AACnC,MAAA,OAAO,IAAA;AAAA,IACT;AACA,IAAA,MAAM,IAAA,GAAO,OAAO,CAAA,CAAE,IAAA,KAAS,QAAA,IAAY,CAAA,CAAE,IAAA,GAAO,CAAA,GAAI,IAAA,CAAK,KAAA,CAAM,CAAA,CAAE,IAAI,CAAA,GAAI,EAAA;AAC7E,IAAA,MAAM,IAAA,GAAO,OAAO,CAAA,CAAE,IAAA,KAAS,QAAA,IAAY,CAAA,CAAE,IAAA,GAAO,CAAA,GAAI,IAAA,CAAK,KAAA,CAAM,CAAA,CAAE,IAAI,CAAA,GAAI,EAAA;AAE7E,IAAA,IAAI,GAAA,GACF,OAAO,CAAA,CAAE,GAAA,KAAQ,QAAA,IAAY,EAAE,GAAA,CAAI,MAAA,GAAS,CAAA,GAAI,CAAA,CAAE,GAAA,GAAM,IAAA;AAC1D,IAAA,IAAI,gBACF,OAAO,CAAA,CAAE,aAAA,KAAkB,QAAA,GAAW,EAAE,aAAA,GAAgB,EAAA;AAC1D,IAAA,IAAI,CAAC,GAAA,EAAK;AACR,MAAA,IAAI;AACF,QAAA,MAAM,MAAA,GAAS,MAAM,oBAAA,EAAqB;AAC1C,QAAA,MAAM,KAAK,aAAA,GACP,aAAA,CAAc,QAAQ,aAAa,CAAA,GACnC,mBAAmB,MAAM,CAAA;AAC7B,QAAA,IAAI,EAAA,EAAI;AACN,UAAA,GAAA,GAAM,EAAA,CAAG,IAAA;AACT,UAAA,aAAA,GAAgB,EAAA,CAAG,IAAA;AAAA,QACrB;AAAA,MACF,CAAA,CAAA,MAAQ;AAAA,MAER;AAAA,IACF;AACA,IAAA,IAAI,CAAC,GAAA,EAAK;AACR,MAAA,GAAA,GAAM,QAAQ,GAAA,EAAI;AAClB,MAAA,OAAA,CAAQ,IAAA;AAAA,QACN,mDAAmD,IAAA,CAAK,IAAA,CAAK,GAAG,CAAC,wCAC7B,GAAG,CAAA;AAAA,OACzC;AAAA,IACF;AACA,IAAA,IAAI,CAAC,eAAe,aAAA,GAAgB,SAAA;AACpC,IAAA,IAAI;AACF,MAAA,MAAM,IAAA,GAAO,SAAS,QAAA,CAAS;AAAA,QAC7B,IAAA;AAAA,QACA,GAAA;AAAA,QACA,aAAA;AAAA,QACA,IAAA;AAAA,QACA,IAAA;AAAA,QACA,GAAI,CAAA,CAAE,GAAA,IAAO,OAAO,CAAA,CAAE,GAAA,KAAQ,QAAA,GAC1B,EAAE,GAAA,EAAK,CAAA,CAAE,GAAA,EAA8B,GACvC,EAAC;AAAA,QACL,GAAI,OAAO,CAAA,CAAE,IAAA,KAAS,QAAA,GAAW,EAAE,IAAA,EAAM,CAAA,CAAE,IAAA,EAAK,GAAI,EAAC;AAAA,QACrD,GAAI,OAAO,CAAA,CAAE,KAAA,KAAU,QAAA,GAAW,EAAE,KAAA,EAAO,CAAA,CAAE,KAAA,EAAM,GAAI;AAAC,OACzD,CAAA;AACD,MAAA,IAAA,CAAK,KAAK,IAAI,CAAA;AAAA,IAChB,SAAS,GAAA,EAAK;AACZ,MAAA,MAAM,MAAM,GAAA,YAAe,KAAA,GAAQ,GAAA,CAAI,OAAA,GAAU,OAAO,GAAG,CAAA;AAC3D,MAAA,MAAM,MAAA,GAAS,GAAA,CAAI,QAAA,CAAS,gBAAgB,CAAA,GACxC,MACA,GAAA,CAAI,QAAA,CAAS,gBAAgB,CAAA,GAC3B,GAAA,GACA,GAAA;AACN,MAAA,IAAA,CAAK,QAAQ,EAAE,KAAA,EAAO,kBAAA,EAAoB,OAAA,EAAS,KAAK,CAAA;AAAA,IAC1D;AACA,IAAA,OAAO,IAAA;AAAA,EACT;AAqBA,EAAA,MAAM,WAAA,GAAc,IAAA,CAAK,KAAA,CAAM,+BAA+B,CAAA;AAC9D,EAAA,IAAI,WAAA,IAAe,GAAA,CAAI,MAAA,KAAW,MAAA,EAAQ;AACxC,IAAA,MAAMW,GAAAA,GAAK,YAAY,CAAC,CAAA;AACxB,IAAA,IAAI,CAACA,KAAI,OAAO,KAAA;AAChB,IAAA,MAAM,IAAA,GAAO,MAAM,YAAA,CAAa,GAAG,CAAA;AACnC,IAAA,MAAM,SAAU,IAAA,EAAsC,MAAA;AACtD,IAAA,MAAM,WAAA,GACH,OAAO,MAAA,KAAW,QAAA,IAAY,MAAA,CAAO,MAAA,GAAS,CAAA,IAC9C,KAAA,CAAM,OAAA,CAAQ,MAAM,CAAA,IACnB,MAAA,CAAO,SAAS,CAAA,IAChB,MAAA,CAAO,KAAA,CAAM,CAAA,CAAA,KAAK,CAAA,KAAM,IAAA,IAAQ,OAAO,CAAA,KAAM,QAAQ,CAAA,IACtD,MAAA,KAAW,IAAA,IAAQ,OAAO,MAAA,KAAW,QAAA,IAAY,CAAC,KAAA,CAAM,QAAQ,MAAM,CAAA;AACzE,IAAA,IAAI,CAAC,WAAA,EAAa;AAChB,MAAA,IAAA,CAAK,GAAA,EAAK;AAAA,QACR,KAAA,EAAO,gBAAA;AAAA,QACP,OAAA,EACE;AAAA,OACH,CAAA;AACD,MAAA,OAAO,IAAA;AAAA,IACT;AACA,IAAA,MAAM,MAAA,GAAS,IAAI,GAAA,IAAO,EAAA;AAC1B,IAAA,MAAM,WAAA,GAAc,MAAA,CAAO,QAAA,CAAS,GAAG,CAAA,GACnC,MAAA,CAAO,KAAA,CAAM,MAAA,CAAO,OAAA,CAAQ,GAAG,CAAA,GAAI,CAAC,CAAA,GACpC,EAAA;AACJ,IAAA,MAAM,OAAO,IAAI,eAAA,CAAgB,WAAW,CAAA,CAAE,IAAI,MAAM,CAAA;AACxD,IAAA,MAAM,aAAA,GAAgB,IAAA,KAAS,OAAA,IAAW,IAAA,KAAS,GAAA;AACnD,IAAA,IAAI;AACF,MAAA,IAAI,aAAA,EAAe;AACjB,QAAA,QAAA,CAAS,aAAA,CAAcA,KAAI,MAAM,CAAA;AACjC,QAAA,IAAA,CAAK,GAAA,EAAK,EAAE,EAAA,EAAI,IAAA,EAAM,IAAAA,GAAAA,EAAI,MAAA,EAAQ,MAAM,CAAA;AAAA,MAC1C,CAAA,MAAO;AACL,QAAA,MAAM,QAAA,CAAS,UAAA,CAAWA,GAAAA,EAAI,MAAM,CAAA;AACpC,QAAA,IAAA,CAAK,KAAK,EAAE,EAAA,EAAI,IAAA,EAAM,EAAA,EAAAA,KAAI,CAAA;AAAA,MAC5B;AAAA,IACF,SAAS,GAAA,EAAK;AACZ,MAAA,MAAM,MAAM,GAAA,YAAe,KAAA,GAAQ,GAAA,CAAI,OAAA,GAAU,OAAO,GAAG,CAAA;AAG3D,MAAA,MAAM,MAAA,GAAS,GAAA,CAAI,QAAA,CAAS,YAAY,IACpC,GAAA,GACA,GAAA,CAAI,QAAA,CAAS,cAAc,IACzB,GAAA,GACA,GAAA,CAAI,QAAA,CAAS,UAAU,IACrB,GAAA,GACA,GAAA;AACR,MAAA,IAAA,CAAK,QAAQ,EAAE,KAAA,EAAO,oBAAA,EAAsB,OAAA,EAAS,KAAK,CAAA;AAAA,IAC5D;AACA,IAAA,OAAO,IAAA;AAAA,EACT;AAEA,EAAA,IAAI,IAAA,KAAS,WAAA,IAAe,GAAA,CAAI,MAAA,KAAW,MAAA,EAAQ;AACjD,IAAA,MAAM,IAAA,GAAO,MAAM,YAAA,CAAa,GAAG,CAAA;AACnC,IAAA,IAAI,CAAC,IAAA,IAAQ,OAAO,IAAA,KAAS,QAAA,EAAU;AACrC,MAAA,IAAA,CAAK,GAAA,EAAK,EAAE,KAAA,EAAO,cAAA,EAAgB,CAAA;AACnC,MAAA,OAAO,IAAA;AAAA,IACT;AACA,IAAA,MAAM,CAAA,GAAI,IAAA;AACV,IAAA,MAAM,IAAA,GAAO,KAAA,CAAM,OAAA,CAAQ,CAAA,CAAE,IAAI,CAAA,GAC5B,CAAA,CAAE,IAAA,CAAmB,MAAA,CAAO,CAAC,CAAA,KAAmB,OAAO,CAAA,KAAM,QAAQ,IACtE,EAAC;AACL,IAAA,IAAI,IAAA,CAAK,WAAW,CAAA,EAAG;AACrB,MAAA,IAAA,CAAK,GAAA,EAAK,EAAE,KAAA,EAAO,cAAA,EAAgB,CAAA;AACnC,MAAA,OAAO,IAAA;AAAA,IACT;AACA,IAAA,IAAI;AACF,MAAA,MAAM,IAAA,GAAO,SAAS,KAAA,CAAM;AAAA,QAC1B,IAAA,EACE,CAAA,CAAE,IAAA,KAAS,UAAA,IAAc,CAAA,CAAE,IAAA,KAAS,WAAA,IAAe,CAAA,CAAE,IAAA,KAAS,SAAA,GAC1D,CAAA,CAAE,IAAA,GACF,SAAA;AAAA,QACN,eACE,OAAO,CAAA,CAAE,aAAA,KAAkB,QAAA,GAAW,EAAE,aAAA,GAAgB,SAAA;AAAA,QAC1D,GAAA,EAAK,OAAO,CAAA,CAAE,GAAA,KAAQ,WAAW,CAAA,CAAE,GAAA,GAAM,QAAQ,GAAA,EAAI;AAAA,QACrD,IAAA;AAAA,QACA,GAAA,EACE,EAAE,GAAA,IAAO,OAAO,EAAE,GAAA,KAAQ,QAAA,GACrB,EAAE,GAAA,GACH,KAAA,CAAA;AAAA,QACN,OAAO,OAAO,CAAA,CAAE,KAAA,KAAU,QAAA,GAAW,EAAE,KAAA,GAAQ,KAAA;AAAA,OAChD,CAAA;AACD,MAAA,IAAA,CAAK,KAAK,IAAI,CAAA;AAAA,IAChB,SAAS,GAAA,EAAK;AACZ,MAAA,IAAA,CAAK,GAAA,EAAK;AAAA,QACR,KAAA,EAAO,cAAA;AAAA,QACP,SAAS,GAAA,YAAe,KAAA,GAAQ,GAAA,CAAI,OAAA,GAAU,OAAO,GAAG;AAAA,OACzD,CAAA;AAAA,IACH;AACA,IAAA,OAAO,IAAA;AAAA,EACT;AAKA,EAAA,MAAM,UAAU,IAAA,CAAK,KAAA;AAAA,IACnB;AAAA,GACF;AACA,EAAA,IAAI,CAAC,SAAS,OAAO,KAAA;AACrB,EAAA,MAAM,GAAG,WAAA,EAAa,MAAM,CAAA,GAAI,OAAA;AAChC,EAAA,IAAI,CAAC,aAAa,OAAO,KAAA;AACzB,EAAA,MAAM,YAAA,GAAe,QAAA,CAAS,cAAA,CAAe,WAAW,CAAA;AACxD,EAAA,MAAM,EAAA,GAAK,cAAc,EAAA,IAAM,WAAA;AAE/B,EAAA,IAAI,MAAA,KAAW,UAAA,IAAc,GAAA,CAAI,MAAA,KAAW,KAAA,EAAO;AAMjD,IAAA,IAAI,CAAC,YAAA,EAAc;AACjB,MAAA,IAAA,CAAK,KAAK,EAAE,KAAA,EAAO,mBAAA,EAAqB,EAAA,EAAI,aAAa,CAAA;AACzD,MAAA,OAAO,IAAA;AAAA,IACT;AACA,IAAA,MAAM,MAAA,GAAS,IAAI,GAAA,IAAO,EAAA;AAC1B,IAAA,MAAM,KAAK,IAAI,eAAA;AAAA,MACb,MAAA,CAAO,QAAA,CAAS,GAAG,CAAA,GAAI,MAAA,CAAO,KAAA,CAAM,MAAA,CAAO,OAAA,CAAQ,GAAG,CAAA,GAAI,CAAC,CAAA,GAAI;AAAA,KACjE;AACA,IAAA,MAAM,OAAA,GAAU,SAAS,EAAA,CAAG,GAAA,CAAI,OAAO,CAAA,EAAG,EAAA,EAAI,GAAG,GAAG,CAAA;AACpD,IAAA,MAAM,OAAA,GAAU,QAAA,CAAS,EAAA,CAAG,GAAA,CAAI,OAAO,GAAG,EAAA,GAAK,IAAA,EAAM,GAAA,EAAK,EAAA,GAAK,IAAI,CAAA;AAKnE,IAAA,MAAM,QAAkB,EAAC;AACzB,IAAA,IAAI,YAAA,CAAa,QAAQ,IAAA,EAAM;AAC7B,MAAA,MAAM,KAAA,GAAQ,QAAA,CAAS,MAAA,CAAO,EAAA,EAAI,CAAA,IAAA,KAAQ;AACxC,QAAA,KAAA,CAAM,KAAK,IAAI,CAAA;AAAA,MACjB,CAAC,CAAA;AACD,MAAA,IAAI,OAAO,KAAA,EAAM;AAAA,IACnB;AACA,IAAA,MAAM,QAAA,GAAW,QAAA,CAAS,kBAAA,CAAmB,EAAA,EAAI,OAAO,CAAA;AACxD,IAAA,IAAA,CAAK,GAAA,EAAK;AAAA,MACR,IAAI,YAAA,CAAa,EAAA;AAAA,MACjB,KAAA,EAAO,KAAA,CAAM,KAAA,CAAM,CAAC,OAAO,CAAA;AAAA,MAC3B,KAAA,EAAO,QAAA,GAAW,QAAA,CAAS,QAAA,CAAS,QAAQ,CAAA,GAAI;AAAA,KACjD,CAAA;AACD,IAAA,OAAO,IAAA;AAAA,EACT;AAEA,EAAA,IAAI,MAAA,KAAW,SAAA,IAAa,GAAA,CAAI,MAAA,KAAW,KAAA,EAAO;AAChD,IAAA,IAAI,CAAC,YAAA,EAAc;AACjB,MAAA,IAAA,CAAK,KAAK,EAAE,KAAA,EAAO,mBAAA,EAAqB,EAAA,EAAI,aAAa,CAAA;AACzD,MAAA,OAAO,IAAA;AAAA,IACT;AACA,IAAA,GAAA,CAAI,UAAU,GAAA,EAAK;AAAA,MACjB,cAAA,EAAgB,mBAAA;AAAA,MAChB,eAAA,EAAiB,UAAA;AAAA,MACjB,UAAA,EAAY;AAAA,KACb,CAAA;AAKD,IAAA,MAAM,IAAA,GAAO,YAAY,MAAM;AAC7B,MAAA,IAAI;AACF,QAAA,GAAA,CAAI,KAAA,CAAM,CAAA;;AAAA,CAAkB,CAAA;AAAA,MAC9B,CAAA,CAAA,MAAQ;AACN,QAAA,aAAA,CAAc,IAAI,CAAA;AAAA,MACpB;AAAA,IACF,GAAG,IAAM,CAAA;AACT,IAAA,MAAM,QAAQ,QAAA,CAAS,MAAA,CAAO,EAAA,EAAI,CAAC,MAAM,MAAA,KAAW;AAClD,MAAA,IAAI;AACF,QAAA,GAAA,CAAI,KAAA;AAAA,UACF,SAAS,IAAA,CAAK,SAAA,CAAU,EAAE,IAAA,EAAM,MAAA,EAAQ,CAAC;;AAAA;AAAA,SAC3C;AAAA,MACF,CAAA,CAAA,MAAQ;AAAA,MAER;AAAA,IACF,CAAC,CAAA;AACD,IAAA,IAAI,CAAC,KAAA,EAAO;AACV,MAAA,aAAA,CAAc,IAAI,CAAA;AAClB,MAAA,GAAA,CAAI,GAAA,EAAI;AACR,MAAA,OAAO,IAAA;AAAA,IACT;AACA,IAAA,GAAA,CAAI,IAAA,CAAK,SAAS,MAAM;AACtB,MAAA,KAAA,EAAM;AACN,MAAA,aAAA,CAAc,IAAI,CAAA;AAAA,IACpB,CAAC,CAAA;AACD,IAAA,OAAO,IAAA;AAAA,EACT;AAEA,EAAA,IAAI,MAAA,KAAW,OAAA,IAAW,GAAA,CAAI,MAAA,KAAW,MAAA,EAAQ;AAC/C,IAAA,MAAM,EAAA,GAAK,QAAA,CAAS,IAAA,CAAK,EAAE,CAAA;AAC3B,IAAA,IAAA,CAAK,KAAK,GAAA,GAAM,GAAA,EAAK,EAAE,EAAA,EAAI,IAAI,CAAA;AAC/B,IAAA,OAAO,IAAA;AAAA,EACT;AAEA,EAAA,IAAI,CAAC,MAAA,IAAU,GAAA,CAAI,MAAA,KAAW,KAAA,EAAO;AACnC,IAAA,IAAI,CAAC,YAAA,EAAc;AACjB,MAAA,IAAA,CAAK,KAAK,EAAE,KAAA,EAAO,mBAAA,EAAqB,EAAA,EAAI,aAAa,CAAA;AACzD,MAAA,OAAO,IAAA;AAAA,IACT;AACA,IAAA,IAAA,CAAK,KAAK,YAAY,CAAA;AACtB,IAAA,OAAO,IAAA;AAAA,EACT;AAEA,EAAA,IAAI,CAAC,MAAA,IAAU,GAAA,CAAI,MAAA,KAAW,QAAA,EAAU;AACtC,IAAA,MAAM,EAAA,GAAK,QAAA,CAAS,MAAA,CAAO,EAAE,CAAA;AAC7B,IAAA,IAAA,CAAK,KAAK,GAAA,GAAM,GAAA,EAAK,EAAE,EAAA,EAAI,IAAI,CAAA;AAC/B,IAAA,OAAO,IAAA;AAAA,EACT;AAEA,EAAA,OAAO,KAAA;AACT;AAEA,eAAe,aAAa,GAAA,EAAwC;AAClE,EAAA,MAAM,SAAmB,EAAC;AAC1B,EAAA,WAAA,MAAiB,SAAS,GAAA,EAAK;AAC7B,IAAA,MAAA,CAAO,IAAA,CAAK,OAAO,KAAA,KAAU,QAAA,GAAW,OAAO,IAAA,CAAK,KAAK,IAAI,KAAK,CAAA;AAAA,EACpE;AACA,EAAA,IAAI,MAAA,CAAO,MAAA,KAAW,CAAA,EAAG,OAAO,IAAA;AAChC,EAAA,IAAI;AACF,IAAA,OAAO,IAAA,CAAK,MAAM,MAAA,CAAO,MAAA,CAAO,MAAM,CAAA,CAAE,QAAA,CAAS,MAAM,CAAC,CAAA;AAAA,EAC1D,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,IAAA;AAAA,EACT;AACF;ACjiDO,IAAM,iBAAA,GAAoD;AAAA,EAC/D,aAAA,EAAe;AAAA;AAAA;AAAA,IAGb,UAAA,EAAY,sCAAA;AAAA,IACZ,OAAA,EAAS,gBAAA;AAAA,IACT,OAAA,EAAS,sBAAsB,kBAAkB,CAAA;AAAA,IACjD,SAAA,EAAW,CAAA,EAAA,KAAM,CAAC,QAAA,EAAU,YAAY,EAAE;AAAA;AAC5C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAUF,CAAA;AASA,SAAS,sBACP,QAAA,EACgE;AAChE,EAAA,OAAO,OAAO,KAAK,aAAA,KAAkB;AACnC,IAAA,MAAM,OAAA,GAAU,GAAA,CAAI,OAAA,CAAQ,KAAA,EAAO,GAAG,CAAA;AACtC,IAAA,MAAM,GAAA,GAAMX,OAAAA,CAAQO,OAAAA,EAAQ,EAAG,UAAU,OAAO,CAAA;AAChD,IAAA,IAAI,OAAA;AACJ,IAAA,IAAI;AACF,MAAA,OAAA,GAAU,MAAMD,QAAAA,CAAG,OAAA,CAAQ,GAAG,CAAA;AAAA,IAChC,CAAA,CAAA,MAAQ;AACN,MAAA,OAAO,IAAA;AAAA,IACT;AACA,IAAA,MAAM,QAAQ,OAAA,CAAQ,MAAA,CAAO,OAAK,CAAA,CAAE,QAAA,CAAS,QAAQ,CAAC,CAAA;AACtD,IAAA,IAAI,KAAA,CAAM,MAAA,KAAW,CAAA,EAAG,OAAO,IAAA;AAC/B,IAAA,MAAM,WAAA,GAAc,IAAA,CAAK,KAAA,CAAM,aAAa,CAAA;AAC5C,IAAA,MAAM,aAAgD,EAAC;AACvD,IAAA,KAAA,MAAW,KAAK,KAAA,EAAO;AACrB,MAAA,IAAI;AACF,QAAA,MAAM,KAAK,MAAMA,QAAAA,CAAG,KAAKX,IAAAA,CAAK,GAAA,EAAK,CAAC,CAAC,CAAA;AACrC,QAAA,IAAI,CAAC,OAAO,QAAA,CAAS,WAAW,KAAK,EAAA,CAAG,OAAA,IAAW,cAAc,GAAA,EAAM;AACrE,UAAA,UAAA,CAAW,KAAK,EAAE,IAAA,EAAM,GAAG,KAAA,EAAO,EAAA,CAAG,SAAS,CAAA;AAAA,QAChD;AAAA,MACF,CAAA,CAAA,MAAQ;AAAA,MAER;AAAA,IACF;AACA,IAAA,IAAI,UAAA,CAAW,MAAA,KAAW,CAAA,EAAG,OAAO,IAAA;AACpC,IAAA,UAAA,CAAW,KAAK,CAAC,CAAA,EAAG,MAAM,CAAA,CAAE,KAAA,GAAQ,EAAE,KAAK,CAAA;AAC3C,IAAA,OAAO,WAAW,CAAC,CAAA,CAAG,IAAA,CAAK,OAAA,CAAQ,YAAY,EAAE,CAAA;AAAA,EACnD,CAAA;AACF;AC/CO,IAAM,qBAAqB,MAChCK,OAAAA,CAAQO,OAAAA,EAAQ,EAAG,eAAe,eAAe,CAAA;AAiHnD,IAAM,gBAAA,GAAmB,GAAA;AACzB,IAAM,mBAAmB,EAAA,GAAK,IAAA;AAC9B,IAAM,mBAAA,GAAsB,IAAA;AAM5B,IAAM,WAAA,GAAc,GAAA;AAKpB,SAAS,eAAe,CAAA,EAAmB;AACzC,EAAA,OAAO,CAAA,CAAE,OAAA,CAAQ,yBAAA,EAA2B,EAAE,CAAA;AAChD;AAmLO,SAAS,uBAAuB,IAAA,EAgBlB;AACnB,EAAA,MAAM,WAAA,GAAc,IAAA,EAAM,WAAA,IAAe,kBAAA,EAAmB;AAC5D,EAAA,MAAM,OAAA,GAAU,MAAM,OAAA,IAAW,IAAA;AACjC,EAAA,MAAM,aAAa,IAAA,EAAM,QAAA;AACzB,EAAA,MAAM,cAAc,IAAA,EAAM,WAAA;AAC1B,EAAA,MAAM,QAAA,uBAAe,GAAA,EAA4B;AACjD,EAAA,IAAI,YAAA,GAAqD,IAAA;AAIzD,EAAA,IAAI,SAAA,GAAY,CAAA;AAIhB,EAAA,IAAI,YAAA,GAAe,KAAA;AAgBnB,EAAA,IAAI,OAAA,EAAS;AACX,IAAA,mBAAA,CAAoB,aAAa,QAAQ,CAAA;AAAA,EAC3C;AASA,EAAA,MAAM,gBAAgB,MAAY;AAChC,IAAA,YAAA,EAAa;AAAA,EACf,CAAA;AACA,EAAA,IAAI,OAAA,EAAS;AACX,IAAA,OAAA,CAAQ,EAAA,CAAG,QAAQ,aAAa,CAAA;AAAA,EAClC;AAEA,EAAA,MAAM,kBAAkB,MAAY;AAClC,IAAA,IAAI,CAAC,OAAA,EAAS;AACd,IAAA,IAAI,YAAA,eAA2B,YAAY,CAAA;AAC3C,IAAA,YAAA,GAAe,WAAW,MAAM;AAC9B,MAAA,KAAK,eAAA,EAAgB;AAAA,IACvB,GAAG,mBAAmB,CAAA;AAAA,EACxB,CAAA;AAEA,EAAA,MAAM,kBAAkB,YAA2B;AACjD,IAAA,IAAI;AACF,MAAA,MAAM,QAAA,GAAW;AAAA,QACf,OAAA,EAAA,iBAAS,IAAI,IAAA,EAAK,EAAE,WAAA,EAAY;AAAA,QAChC,QAAA,EAAU,KAAA,CAAM,IAAA,CAAK,QAAA,CAAS,MAAA,EAAQ,CAAA,CAAE,GAAA,CAAI,CAAA,CAAA,KAAK,CAAA,CAAE,IAAI;AAAA,OACzD;AACA,MAAA,MAAMD,QAAAA,CAAG,MAAMG,OAAAA,CAAQ,WAAW,GAAG,EAAE,SAAA,EAAW,MAAM,CAAA;AACxD,MAAA,MAAMH,QAAAA,CAAG,UAAU,WAAA,EAAa,IAAA,CAAK,UAAU,QAAA,EAAU,IAAA,EAAM,CAAC,CAAA,GAAI,IAAI,CAAA;AAAA,IAC1E,SAAS,GAAA,EAAK;AAEZ,MAAA,OAAA,CAAQ,IAAA;AAAA,QACN,8BACE,GAAA,YAAe,KAAA,GAAQ,IAAI,OAAA,GAAU,MAAA,CAAO,GAAG,CACjD,CAAA;AAAA,OACF;AAAA,IACF;AAAA,EACF,CAAA;AAEA,EAAA,MAAM,UAAA,GAAa,CACjB,EAAA,EACA,IAAA,EACA,MAAA,KACS;AACT,IAAA,EAAA,CAAG,WAAA,CAAY,KAAK,IAAI,CAAA;AACxB,IAAA,IAAI,EAAA,CAAG,WAAA,CAAY,MAAA,GAAS,gBAAA,EAAkB;AAC5C,MAAA,EAAA,CAAG,YAAY,MAAA,CAAO,CAAA,EAAG,EAAA,CAAG,WAAA,CAAY,SAAS,gBAAgB,CAAA;AAAA,IACnE;AACA,IAAA,EAAA,CAAG,IAAA,CAAK,YAAA,GAAA,iBAAe,IAAI,IAAA,IAAO,WAAA,EAAY;AAC9C,IAAA,gBAAA,CAAiB,IAAI,IAAI,CAAA;AACzB,IAAA,EAAA,CAAG,QAAQ,IAAA,CAAK,MAAA,EAAQ,EAAE,IAAA,EAAM,QAAQ,CAAA;AAAA,EAC1C,CAAA;AAYA,EAAA,MAAM,gBAAA,GAAmB,CAAC,EAAA,EAAoB,IAAA,KAAuB;AACnE,IAAA,IAAI,EAAA,CAAG,IAAA,CAAK,IAAA,KAAS,WAAA,EAAa;AAClC,IAAA,MAAM,QAAA,GAAW,GAAG,IAAA,CAAK,WAAA,GACrB,kBAAkB,EAAA,CAAG,IAAA,CAAK,WAAW,CAAA,GACrC,MAAA;AACJ,IAAA,IAAI,CAAC,UAAU,UAAA,EAAY;AAC3B,IAAA,MAAM,KAAA,GAAQ,eAAe,IAAI,CAAA;AACjC,IAAA,MAAM,CAAA,GAAI,KAAA,CAAM,KAAA,CAAM,QAAA,CAAS,UAAU,CAAA;AACzC,IAAA,IAAI,CAAA,IAAK,CAAA,CAAE,CAAC,CAAA,EAAG;AACb,MAAA,EAAA,CAAG,KAAK,cAAA,GAAiB;AAAA,QACvB,GAAI,EAAA,CAAG,IAAA,CAAK,cAAA,IAAkB,EAAC;AAAA,QAC/B,CAAC,QAAA,CAAS,OAAO,GAAG,EAAE,CAAC;AAAA,OACzB;AACA,MAAA,eAAA,EAAgB;AAAA,IAClB;AAAA,EACF,CAAA;AAUA,EAAA,MAAM,WAAA,GAAc,CAAC,EAAA,EAAoB,KAAA,KAAwB;AAC/D,IAAA,EAAA,CAAG,WAAA,CAAY,KAAK,KAAK,CAAA;AACzB,IAAA,EAAA,CAAG,mBAAmB,KAAA,CAAM,UAAA;AAC5B,IAAA,OACE,GAAG,eAAA,GAAkB,gBAAA,IACrB,EAAA,CAAG,WAAA,CAAY,SAAS,CAAA,EACxB;AACA,MAAA,MAAM,OAAA,GAAU,EAAA,CAAG,WAAA,CAAY,KAAA,EAAM;AACrC,MAAA,IAAI,OAAA,EAAS,EAAA,CAAG,eAAA,IAAmB,OAAA,CAAQ,UAAA;AAAA,IAC7C;AACA,IAAA,EAAA,CAAG,IAAA,CAAK,YAAA,GAAA,iBAAe,IAAI,IAAA,IAAO,WAAA,EAAY;AAC9C,IAAA,EAAA,CAAG,OAAA,CAAQ,IAAA,CAAK,MAAA,EAAQ,KAAK,CAAA;AAAA,EAC/B,CAAA;AAOA,EAAA,MAAM,gBAAA,GAAmB,CAAC,EAAA,KAA6B;AACrD,IAAA,IAAI,CAAC,GAAG,GAAA,IAAO,CAAC,GAAG,cAAA,IAAkB,EAAA,CAAG,cAAA,CAAe,IAAA,KAAS,CAAA,EAAG;AACnE,IAAA,IAAI,IAAA,GAAO,QAAA;AACX,IAAA,IAAI,IAAA,GAAO,QAAA;AACX,IAAA,KAAA,MAAW,GAAA,IAAO,EAAA,CAAG,cAAA,CAAe,MAAA,EAAO,EAAG;AAC5C,MAAA,IAAI,GAAA,CAAI,IAAA,GAAO,IAAA,EAAM,IAAA,GAAO,GAAA,CAAI,IAAA;AAChC,MAAA,IAAI,GAAA,CAAI,IAAA,GAAO,IAAA,EAAM,IAAA,GAAO,GAAA,CAAI,IAAA;AAAA,IAClC;AACA,IAAA,IAAI,CAAC,OAAO,QAAA,CAAS,IAAI,KAAK,CAAC,MAAA,CAAO,QAAA,CAAS,IAAI,CAAA,EAAG;AACtD,IAAA,IAAI;AACF,MAAA,EAAA,CAAG,GAAA,CAAI,MAAA,CAAO,IAAA,EAAM,IAAI,CAAA;AAAA,IAC1B,CAAA,CAAA,MAAQ;AAAA,IAER;AAAA,EACF,CAAA;AAOA,EAAA,MAAM,YAAA,GAAe,CAAC,EAAA,EAAoB,GAAA,KAAgC;AACxE,IAAA,QAAQ,IAAI,IAAA;AAAM,MAChB,KAAK,YAAA;AACH,QAAA,IAAI,IAAI,IAAA,EAAM;AAIZ,UAAA,MAAM,QAAA,GAAW,EAAA,CAAG,OAAA,GAAU,GAAA,CAAI,IAAA;AAClC,UAAA,MAAM,KAAA,GAAQ,QAAA,CAAS,KAAA,CAAM,OAAO,CAAA;AACpC,UAAA,EAAA,CAAG,OAAA,GAAU,KAAA,CAAM,GAAA,EAAI,IAAK,EAAA;AAC5B,UAAA,KAAA,MAAW,IAAA,IAAQ,KAAA,EAAO,UAAA,CAAW,EAAA,EAAI,MAAM,QAAQ,CAAA;AAAA,QACzD;AACA,QAAA;AAAA,MACF,KAAK,SAAA;AACH,QAAA,IAAI,IAAI,IAAA,EAAM;AAIZ,UAAA,MAAM,QAAA,GAAW,EAAA,CAAG,UAAA,GAAa,GAAA,CAAI,IAAA;AACrC,UAAA,MAAM,KAAA,GAAQ,QAAA,CAAS,KAAA,CAAM,OAAO,CAAA;AACpC,UAAA,EAAA,CAAG,UAAA,GAAa,KAAA,CAAM,GAAA,EAAI,IAAK,EAAA;AAC/B,UAAA,KAAA,MAAW,QAAQ,KAAA,EAAO;AACxB,YAAA,IAAI,IAAA,CAAK,MAAK,EAAG;AACf,cAAA,UAAA,CAAW,EAAA,EAAI,CAAA,iBAAA,EAAoB,IAAI,CAAA,OAAA,CAAA,EAAW,QAAQ,CAAA;AAAA,YAC5D;AAAA,UACF;AAAA,QACF;AACA,QAAA;AAAA,MACF,KAAK,WAAA;AACH,QAAA,UAAA;AAAA,UACE,EAAA;AAAA,UACA,CAAA,eAAA,EAAkB,GAAA,CAAI,QAAA,IAAY,GAAG,CAAA,OAAA,CAAA;AAAA,UACrC;AAAA,SACF;AACA,QAAA;AAAA,MACF,KAAK,aAAA;AACH,QAAA,IAAI,GAAA,CAAI,OAAA;AACN,UAAA,UAAA,CAAW,EAAA,EAAI,+BAA+B,QAAQ,CAAA;AACxD,QAAA;AAAA,MACF,KAAK,cAAA;AACH,QAAA,UAAA,CAAW,EAAA,EAAI,mCAAmC,QAAQ,CAAA;AAC1D,QAAA;AAAA,MACF,KAAK,UAAA,EAAY;AAEf,QAAA,IAAI,EAAA,CAAG,UAAA,CAAW,IAAA,EAAK,EAAG;AACxB,UAAA,UAAA;AAAA,YACE,EAAA;AAAA,YACA,CAAA,iBAAA,EAAoB,GAAG,UAAU,CAAA,OAAA,CAAA;AAAA,YACjC;AAAA,WACF;AAAA,QACF;AACA,QAAA,EAAA,CAAG,UAAA,GAAa,EAAA;AAChB,QAAA,IAAI,GAAG,OAAA,EAAS;AACd,UAAA,UAAA,CAAW,EAAA,EAAI,EAAA,CAAG,OAAA,EAAS,QAAQ,CAAA;AACnC,UAAA,EAAA,CAAG,OAAA,GAAU,EAAA;AAAA,QACf;AACA,QAAA,UAAA;AAAA,UACE,EAAA;AAAA,UACA,CAAA,8BAAA,EAAuB,GAAA,CAAI,MAAA,IAAU,WAAW,CAAA,qBAAA,CAAA;AAAA,UAChD;AAAA,SACF;AACA,QAAA;AAAA,MACF;AAAA,MACA,KAAK,OAAA,EAAS;AACZ,QAAA,MAAM,IAAA,GACJ,OAAO,GAAA,CAAI,KAAA,EAAO,IAAA,KAAS,WAAW,CAAA,OAAA,EAAU,GAAA,CAAI,KAAA,CAAM,IAAI,CAAA,CAAA,CAAA,GAAM,EAAA;AACtE,QAAA,UAAA;AAAA,UACE,EAAA;AAAA,UACA,kBAAkB,IAAI,CAAA,CAAA,EAAI,GAAA,CAAI,KAAA,EAAO,WAAW,SAAS,CAAA,OAAA,CAAA;AAAA,UACzD;AAAA,SACF;AAIA,QAAA,MAAM,IAAA,GAAO,IAAI,KAAA,EAAO,IAAA;AAIxB,QAAA,IAAI,QAAQ,OAAO,IAAA,KAAS,YAAY,OAAO,IAAA,CAAK,WAAW,QAAA,EAAU;AACvE,UAAA,KAAA,MAAW,IAAA,IAAQ,IAAA,CAAK,MAAA,CAAO,KAAA,CAAM,OAAO,CAAA,EAAG;AAC7C,YAAA,IAAI,MAAM,UAAA,CAAW,EAAA,EAAI,CAAA,SAAA,EAAY,IAAI,WAAW,QAAQ,CAAA;AAAA,UAC9D;AAAA,QACF;AACA,QAAA;AAAA,MACF;AAAA;AACF,EACF,CAAA;AAcA,EAAA,MAAM,iBAAA,GAAoB,CAAC,EAAA,EAAY,MAAA,KAAmC;AACxE,IAAA,MAAM,EAAA,GAAK,QAAA,CAAS,GAAA,CAAI,EAAE,CAAA;AAC1B,IAAA,IAAI,CAAC,IAAI,MAAM,IAAI,MAAM,CAAA,EAAG,MAAM,CAAA,cAAA,EAAiB,EAAE,CAAA,CAAA,CAAG,CAAA;AACxD,IAAA,IAAI,CAAC,GAAG,YAAA,EAAc;AACpB,MAAA,MAAM,IAAI,KAAA;AAAA,QACR,GAAG,MAAM,CAAA,WAAA,EAAc,EAAE,CAAA,gCAAA,EAAmC,EAAA,CAAG,KAAK,IAAI,CAAA,CAAA;AAAA,OAC1E;AAAA,IACF;AACA,IAAA,IAAI,GAAG,IAAA,EAAM;AACX,MAAA,MAAM,IAAI,KAAA;AAAA,QACR,CAAA,EAAG,MAAM,CAAA,WAAA,EAAc,EAAE,CAAA,oDAAA;AAAA,OAC3B;AAAA,IACF;AACA,IAAA,OAAO,EAAA;AAAA,EACT,CAAA;AAmBA,EAAA,MAAM,gBAAA,GAAmB,OAAO,EAAA,KAAsC;AACpE,IAAA,IAAI,GAAG,YAAA,EAAc;AACrB,IAAA,IAAI,CAAC,WAAA,EAAa;AAClB,IAAA,IAAI,EAAA,CAAG,IAAA,CAAK,IAAA,KAAS,WAAA,EAAa;AAClC,IAAA,MAAM,WAAA,GAAc,EAAA,CAAG,IAAA,CAAK,WAAA,IAAe,EAAA,CAAG,WAAA;AAC9C,IAAA,MAAM,gBAAA,GAAmB,GAAG,IAAA,CAAK,gBAAA;AACjC,IAAA,MAAM,GAAA,GAAM,GAAG,IAAA,CAAK,GAAA;AACpB,IAAA,IAAI,CAAC,WAAA,IAAe,CAAC,gBAAA,IAAoB,CAAC,GAAA,EAAK;AAC/C,IAAA,IAAI,GAAG,aAAA,EAAe;AACpB,MAAA,MAAM,EAAA,CAAG,aAAA;AACT,MAAA;AAAA,IACF;AACA,IAAA,EAAA,CAAG,iBAAiB,YAAY;AAC9B,MAAA,UAAA;AAAA,QACE,EAAA;AAAA,QACA,CAAA,sBAAA,EAAe,WAAW,CAAA,SAAA,EAAY,gBAAgB,CAAA,aAAA,CAAA;AAAA,QACtD;AAAA,OACF;AACA,MAAA,IAAI;AACF,QAAA,MAAM,KAAA,GAAQ,MAAM,WAAA,CAAY;AAAA,UAC9B,WAAA;AAAA,UACA,GAAA;AAAA,UACA,eAAA,EAAiB;AAAA,SAClB,CAAA;AACD,QAAA,IAAI,CAAC,KAAA,EAAO;AACV,UAAA,UAAA;AAAA,YACE,EAAA;AAAA,YACA,mCAAmC,WAAW,CAAA,eAAA,CAAA;AAAA,YAC9C;AAAA,WACF;AACA,UAAA;AAAA,QACF;AACA,QAAA,EAAA,CAAG,YAAA,GAAe,KAAA;AAClB,QAAA,EAAA,CAAG,WAAA,GAAc,WAAA;AACjB,QAAA,EAAA,CAAG,IAAA,CAAK,mBAAmB,KAAA,CAAM,SAAA;AACjC,QAAA,IAAI,EAAA,CAAG,IAAA,CAAK,MAAA,KAAW,SAAA,EAAW;AAChC,UAAA,EAAA,CAAG,KAAK,MAAA,GAAS,SAAA;AACjB,UAAA,OAAO,GAAG,IAAA,CAAK,OAAA;AACf,UAAA,OAAO,GAAG,IAAA,CAAK,QAAA;AACf,UAAA,EAAA,CAAG,OAAA,CAAQ,IAAA,CAAK,QAAA,EAAU,EAAA,CAAG,KAAK,MAAM,CAAA;AAAA,QAC1C;AACA,QAAA,eAAA,EAAgB;AAAA,MAClB,SAAS,GAAA,EAAK;AACZ,QAAA,MAAM,MAAM,GAAA,YAAe,KAAA,GAAQ,GAAA,CAAI,OAAA,GAAU,OAAO,GAAG,CAAA;AAC3D,QAAA,UAAA,CAAW,EAAA,EAAI,CAAA,uBAAA,EAA0B,GAAG,CAAA,CAAA,EAAI,QAAQ,CAAA;AAAA,MAC1D;AAAA,IACF,CAAA,GAAG;AACH,IAAA,IAAI;AACF,MAAA,MAAM,EAAA,CAAG,aAAA;AAAA,IACX,CAAA,SAAE;AACA,MAAA,EAAA,CAAG,aAAA,GAAgB,MAAA;AAAA,IACrB;AAAA,EACF,CAAA;AAEA,EAAA,MAAM,YAAA,GAAe,OACnB,EAAA,EACA,OAAA,KACkB;AAClB,IAAA,IAAI,CAAC,GAAG,YAAA,EAAc;AACpB,MAAA,MAAM,IAAI,MAAM,2CAA2C,CAAA;AAAA,IAC7D;AACA,IAAA,EAAA,CAAG,IAAA,GAAO,IAAA;AACV,IAAA,IAAI;AACF,MAAA,UAAA;AAAA,QACE,EAAA;AAAA,QACA,CAAA,2BAAA,EAAe,OAAO,OAAA,KAAY,QAAA,GAAW,UAAU,IAAA,CAAK,SAAA,CAAU,OAAO,CAAC,CAAA,oBAAA,CAAA;AAAA,QAC9E;AAAA,OACF;AAKA,MAAA,MAAM,OAAA,GACJ,OAAO,OAAA,KAAY,QAAA,GAAW,EAAE,IAAA,EAAM,MAAA,EAAQ,IAAA,EAAM,OAAA,EAAQ,GAAI,OAAA;AAClE,MAAA,WAAA,MAAiB,GAAA,IAAO,EAAA,CAAG,YAAA,CAAa,IAAA,CAAK,OAAO,CAAA,EAAG;AACrD,QAAA,YAAA,CAAa,IAAI,GAAG,CAAA;AAAA,MACtB;AAAA,IACF,SAAS,GAAA,EAAK;AACZ,MAAA,EAAA,CAAG,KAAK,MAAA,GAAS,OAAA;AACjB,MAAA,EAAA,CAAG,IAAA,CAAK,OAAA,GAAA,iBAAU,IAAI,IAAA,IAAO,WAAA,EAAY;AACzC,MAAA,UAAA;AAAA,QACE,EAAA;AAAA,QACA,gBAAgB,GAAA,YAAe,KAAA,GAAQ,IAAI,OAAA,GAAU,MAAA,CAAO,GAAG,CAAC,CAAA,CAAA;AAAA,QAChE;AAAA,OACF;AACA,MAAA,eAAA,EAAgB;AAAA,IAClB,CAAA,SAAE;AACA,MAAA,EAAA,CAAG,IAAA,GAAO,KAAA;AAAA,IACZ;AAAA,EACF,CAAA;AAEA,EAAA,MAAM,iBAAA,GAAoB,CAAC,EAAA,KAA6B;AACtD,IAAA,MAAM,OAAA,GACJ,CAAC,MAAA,KACD,CAAC,KAAA,KAAiC;AAChC,MAAA,MAAMV,QAAO,OAAO,KAAA,KAAU,WAAW,KAAA,GAAQ,KAAA,CAAM,SAAS,MAAM,CAAA;AACtE,MAAA,KAAA,MAAW,IAAA,IAAQA,KAAAA,CAAK,KAAA,CAAM,OAAO,CAAA,EAAG;AACtC,QAAA,IAAI,KAAK,MAAA,GAAS,CAAA,EAAG,UAAA,CAAW,EAAA,EAAI,MAAM,MAAM,CAAA;AAAA,MAClD;AAAA,IACF,CAAA;AAGF,IAAA,IAAI,CAAC,GAAG,KAAA,EAAO;AACf,IAAA,EAAA,CAAG,MAAM,MAAA,EAAQ,EAAA,CAAG,MAAA,EAAQ,OAAA,CAAQ,QAAQ,CAAC,CAAA;AAC7C,IAAA,EAAA,CAAG,MAAM,MAAA,EAAQ,EAAA,CAAG,MAAA,EAAQ,OAAA,CAAQ,QAAQ,CAAC,CAAA;AAAA,EAC/C,CAAA;AAEA,EAAA,OAAO;AAAA,IACL,MAAM,KAAA,EAAO;AACX,MAAA,MAAM,EAAA,GAAK,MAAM,EAAA,IAAM,CAAA,KAAA,EAAQ,YAAW,CAAE,KAAA,CAAM,CAAA,EAAG,CAAC,CAAC,CAAA,CAAA;AACvD,MAAA,IAAI,QAAA,CAAS,GAAA,CAAI,EAAE,CAAA,EAAG;AACpB,QAAA,MAAM,IAAI,KAAA,CAAM,CAAA,oBAAA,EAAuB,EAAE,CAAA,gBAAA,CAAkB,CAAA;AAAA,MAC7D;AACA,MAAA,MAAM,GAAA,GAAM,EAAE,GAAG,OAAA,CAAQ,KAAK,GAAI,KAAA,CAAM,GAAA,IAAO,EAAC,EAAG;AAEnD,MAAA,OAAO,GAAA,CAAI,YAAA;AACX,MAAA,MAAM,CAAC,GAAA,EAAK,GAAG,IAAI,IAAI,KAAA,CAAM,IAAA;AAC7B,MAAA,IAAI,CAAC,GAAA,EAAK,MAAM,IAAI,MAAM,4CAA4C,CAAA;AAKtE,MAAA,MAAM,SAAA,GAAY,KAAA,CAAM,SAAA,GAAY,MAAA,GAAS,QAAA;AAC7C,MAAA,MAAM,KAAA,GAAQgB,KAAAA,CAAM,GAAA,EAAK,IAAA,EAAM;AAAA,QAC7B,KAAK,KAAA,CAAM,GAAA;AAAA,QACX,GAAA;AAAA,QACA,KAAA,EAAO,CAAC,SAAA,EAAW,MAAA,EAAQ,MAAM;AAAA,OAClC,CAAA;AACD,MAAA,MAAM,IAAA,GAA0B;AAAA,QAC9B,EAAA;AAAA,QACA,MAAM,KAAA,CAAM,IAAA;AAAA,QACZ,eAAe,KAAA,CAAM,aAAA;AAAA,QACrB,OAAA,EAAS,CAAC,GAAA,EAAK,GAAG,IAAI,EAAE,GAAA,CAAI,QAAQ,CAAA,CAAE,IAAA,CAAK,GAAG,CAAA;AAAA,QAC9C,GAAA,EAAK,MAAM,GAAA,IAAO,IAAA;AAAA,QAClB,MAAA,EAAQ,UAAA;AAAA,QACR,SAAA,EAAA,iBAAW,IAAI,IAAA,EAAK,EAAE,WAAA,EAAY;AAAA,QAClC,MAAM,KAAA,CAAM,IAAA;AAAA,QACZ,KAAK,KAAA,CAAM,GAAA;AAAA,QACX,GAAI,MAAM,KAAA,GAAQ,EAAE,OAAO,KAAA,CAAM,KAAA,KAAU;AAAC,OAC9C;AACA,MAAA,MAAM,EAAA,GAAqB;AAAA,QACzB,IAAA;AAAA,QACA,KAAA;AAAA,QACA,aAAa,EAAC;AAAA,QACd,aAAa,EAAC;AAAA,QACd,eAAA,EAAiB,CAAA;AAAA,QACjB,OAAA,EAAS,IAAIC,YAAAA,EAAa;AAAA,QAC1B,IAAA,EAAM,KAAA;AAAA,QACN,OAAA,EAAS,EAAA;AAAA,QACT,UAAA,EAAY;AAAA,OACd;AAGA,MAAA,EAAA,CAAG,OAAA,CAAQ,gBAAgB,EAAE,CAAA;AAE7B,MAAA,QAAA,CAAS,GAAA,CAAI,IAAI,EAAE,CAAA;AACnB,MAAA,iBAAA,CAAkB,EAAE,CAAA;AAEpB,MAAA,KAAA,CAAM,IAAA,CAAK,SAAS,MAAM;AACxB,QAAA,IAAA,CAAK,MAAA,GAAS,SAAA;AACd,QAAA,EAAA,CAAG,OAAA,CAAQ,IAAA,CAAK,QAAA,EAAU,IAAA,CAAK,MAAM,CAAA;AACrC,QAAA,eAAA,EAAgB;AAAA,MAClB,CAAC,CAAA;AACD,MAAA,KAAA,CAAM,IAAA,CAAK,SAAS,CAAA,GAAA,KAAO;AACzB,QAAA,IAAA,CAAK,MAAA,GAAS,OAAA;AACd,QAAA,IAAA,CAAK,OAAA,GAAA,iBAAU,IAAI,IAAA,EAAK,EAAE,WAAA,EAAY;AACtC,QAAA,UAAA,CAAW,EAAA,EAAI,CAAA,cAAA,EAAiB,GAAA,CAAI,OAAO,IAAI,QAAQ,CAAA;AACvD,QAAA,EAAA,CAAG,OAAA,CAAQ,IAAA,CAAK,QAAA,EAAU,IAAA,CAAK,MAAM,CAAA;AACrC,QAAA,eAAA,EAAgB;AAAA,MAClB,CAAC,CAAA;AACD,MAAA,KAAA,CAAM,IAAA,CAAK,MAAA,EAAQ,CAAC,IAAA,EAAM,MAAA,KAAW;AACnC,QAAA,IAAI,MAAA,IAAU,IAAA,CAAK,MAAA,KAAW,QAAA,OAAe,MAAA,GAAS,QAAA;AAAA,aAAA,IAC7C,IAAA,CAAK,MAAA,KAAW,SAAA,IAAa,IAAA,CAAK,WAAW,UAAA,EAAY;AAChE,UAAA,IAAA,CAAK,MAAA,GAAS,QAAA;AAAA,QAChB;AACA,QAAA,IAAA,CAAK,OAAA,GAAA,iBAAU,IAAI,IAAA,EAAK,EAAE,WAAA,EAAY;AACtC,QAAA,IAAI,OAAO,IAAA,KAAS,QAAA,EAAU,IAAA,CAAK,QAAA,GAAW,IAAA;AAC9C,QAAA,EAAA,CAAG,OAAA,CAAQ,IAAA,CAAK,QAAA,EAAU,IAAA,CAAK,MAAM,CAAA;AACrC,QAAA,eAAA,EAAgB;AAAA,MAClB,CAAC,CAAA;AACD,MAAA,eAAA,EAAgB;AAChB,MAAA,OAAO,IAAA;AAAA,IACT,CAAA;AAAA,IACA,SAAS,KAAA,EAAO;AACd,MAAA,IAAI,QAAA,CAAS,GAAA,CAAI,KAAA,CAAM,EAAE,CAAA,EAAG;AAG1B,QAAA,MAAM,QAAA,GAAW,QAAA,CAAS,GAAA,CAAI,KAAA,CAAM,EAAE,CAAA;AACtC,QAAA,IAAI,QAAA,SAAiB,QAAA,CAAS,IAAA;AAAA,MAChC;AACA,MAAA,MAAM,IAAA,GAA0B;AAAA,QAC9B,IAAI,KAAA,CAAM,EAAA;AAAA,QACV,IAAA,EAAM,MAAM,IAAA,IAAQ,SAAA;AAAA,QACpB,eAAe,KAAA,CAAM,aAAA;AAAA,QACrB,SAAS,KAAA,CAAM,OAAA;AAAA,QACf,GAAA,EAAK,KAAA,CAAM,KAAA,CAAM,GAAA,IAAO,IAAA;AAAA,QACxB,MAAA,EAAQ,KAAA,CAAM,KAAA,CAAM,MAAA,GAAS,QAAA,GAAW,SAAA;AAAA,QACxC,SAAA,EAAA,iBAAW,IAAI,IAAA,EAAK,EAAE,WAAA,EAAY;AAAA,QAClC,GAAI,MAAM,KAAA,GAAQ,EAAE,OAAO,KAAA,CAAM,KAAA,KAAU;AAAC,OAC9C;AACA,MAAA,MAAM,EAAA,GAAqB;AAAA,QACzB,IAAA;AAAA,QACA,OAAO,KAAA,CAAM,KAAA;AAAA,QACb,aAAa,EAAC;AAAA,QACd,aAAa,EAAC;AAAA,QACd,eAAA,EAAiB,CAAA;AAAA,QACjB,OAAA,EAAS,IAAIA,YAAAA,EAAa;AAAA,QAC1B,IAAA,EAAM,KAAA;AAAA,QACN,OAAA,EAAS,EAAA;AAAA,QACT,UAAA,EAAY;AAAA,OACd;AACA,MAAA,EAAA,CAAG,OAAA,CAAQ,gBAAgB,EAAE,CAAA;AAC7B,MAAA,QAAA,CAAS,GAAA,CAAI,KAAA,CAAM,EAAA,EAAI,EAAE,CAAA;AACzB,MAAA,iBAAA,CAAkB,EAAE,CAAA;AAIpB,MAAA,KAAA,CAAM,KAAA,CAAM,IAAA,CAAK,MAAA,EAAQ,CAAC,MAAM,MAAA,KAAW;AACzC,QAAA,IAAI,MAAA,IAAU,IAAA,CAAK,MAAA,KAAW,QAAA,OAAe,MAAA,GAAS,QAAA;AAAA,aAAA,IAC7C,IAAA,CAAK,MAAA,KAAW,SAAA,EAAW,IAAA,CAAK,MAAA,GAAS,QAAA;AAClD,QAAA,IAAA,CAAK,OAAA,GAAA,iBAAU,IAAI,IAAA,EAAK,EAAE,WAAA,EAAY;AACtC,QAAA,IAAI,OAAO,IAAA,KAAS,QAAA,EAAU,IAAA,CAAK,QAAA,GAAW,IAAA;AAC9C,QAAA,EAAA,CAAG,OAAA,CAAQ,IAAA,CAAK,QAAA,EAAU,IAAA,CAAK,MAAM,CAAA;AACrC,QAAA,eAAA,EAAgB;AAAA,MAClB,CAAC,CAAA;AACD,MAAA,KAAA,CAAM,KAAA,CAAM,IAAA,CAAK,OAAA,EAAS,CAAA,GAAA,KAAO;AAC/B,QAAA,IAAA,CAAK,MAAA,GAAS,OAAA;AACd,QAAA,IAAA,CAAK,OAAA,GAAA,iBAAU,IAAI,IAAA,EAAK,EAAE,WAAA,EAAY;AACtC,QAAA,UAAA,CAAW,EAAA,EAAI,CAAA,cAAA,EAAiB,GAAA,CAAI,OAAO,IAAI,QAAQ,CAAA;AACvD,QAAA,EAAA,CAAG,OAAA,CAAQ,IAAA,CAAK,QAAA,EAAU,IAAA,CAAK,MAAM,CAAA;AACrC,QAAA,eAAA,EAAgB;AAAA,MAClB,CAAC,CAAA;AACD,MAAA,eAAA,EAAgB;AAChB,MAAA,OAAO,IAAA;AAAA,IACT,CAAA;AAAA,IACA,WAAW,KAAA,EAAO;AAChB,MAAA,MAAM,KAAK,CAAA,KAAA,EAAQ,UAAA,GAAa,KAAA,CAAM,CAAA,EAAG,CAAC,CAAC,CAAA,CAAA;AAC3C,MAAA,MAAM,IAAA,GAA0B;AAAA,QAC9B,EAAA;AAAA,QACA,IAAA,EAAM,WAAA;AAAA,QACN,eAAe,KAAA,CAAM,aAAA;AAAA,QACrB,OAAA,EAAS,KAAA,CAAM,cAAA,IAAkB,CAAA,EAAG,MAAM,WAAW,CAAA,QAAA,CAAA;AAAA,QACrD,GAAA,EAAK,IAAA;AAAA,QACL,MAAA,EAAQ,SAAA;AAAA;AAAA,QACR,SAAA,EAAA,iBAAW,IAAI,IAAA,EAAK,EAAE,WAAA,EAAY;AAAA,QAClC,KAAK,KAAA,CAAM,GAAA;AAAA,QACX,aAAa,KAAA,CAAM,WAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAKnB,gBAAA,EAAkB,MAAM,YAAA,CAAa,SAAA;AAAA,QACrC,GAAI,MAAM,KAAA,GAAQ,EAAE,OAAO,KAAA,CAAM,KAAA,KAAU;AAAC,OAC9C;AACA,MAAA,MAAM,EAAA,GAAqB;AAAA,QACzB,IAAA;AAAA,QACA,cAAc,KAAA,CAAM,YAAA;AAAA,QACpB,aAAa,KAAA,CAAM,WAAA;AAAA,QACnB,aAAa,EAAC;AAAA,QACd,aAAa,EAAC;AAAA,QACd,eAAA,EAAiB,CAAA;AAAA,QACjB,OAAA,EAAS,IAAIA,YAAAA,EAAa;AAAA,QAC1B,IAAA,EAAM,KAAA;AAAA,QACN,OAAA,EAAS,EAAA;AAAA,QACT,UAAA,EAAY;AAAA,OACd;AACA,MAAA,EAAA,CAAG,OAAA,CAAQ,gBAAgB,EAAE,CAAA;AAC7B,MAAA,QAAA,CAAS,GAAA,CAAI,IAAI,EAAE,CAAA;AACnB,MAAA,UAAA;AAAA,QACE,EAAA;AAAA,QACA,CAAA,aAAA,EAAM,MAAM,WAAW,CAAA,eAAA,EAAkB,MAAM,YAAA,CAAa,SAAS,CAAA,MAAA,EAAS,KAAA,CAAM,GAAG,CAAA,cAAA,CAAA;AAAA,QACvF;AAAA,OACF;AACA,MAAA,eAAA,EAAgB;AAIhB,MAAA,IAAI,MAAM,aAAA,EAAe;AACvB,QAAA,KAAK,aAAa,EAAA,EAAI,KAAA,CAAM,aAAa,CAAA,CAAE,MAAM,CAAA,GAAA,KAAO;AACtD,UAAA,UAAA;AAAA,YACE,EAAA;AAAA,YACA,gBAAgB,GAAA,YAAe,KAAA,GAAQ,IAAI,OAAA,GAAU,MAAA,CAAO,GAAG,CAAC,CAAA,CAAA;AAAA,YAChE;AAAA,WACF;AAAA,QACF,CAAC,CAAA;AAAA,MACH;AACA,MAAA,OAAO,IAAA;AAAA,IACT,CAAA;AAAA,IACA,SAAS,KAAA,EAAO;AACd,MAAA,IAAI,CAAC,UAAA,EAAY;AACf,QAAA,MAAM,IAAI,KAAA;AAAA,UACR;AAAA,SACF;AAAA,MACF;AACA,MAAA,MAAM,KAAK,CAAA,KAAA,EAAQ,UAAA,GAAa,KAAA,CAAM,CAAA,EAAG,CAAC,CAAC,CAAA,CAAA;AAK3C,MAAA,IAAI,MAAM,IAAA,EAAM;AACd,QAAA,KAAA,MAAWC,GAAAA,IAAM,QAAA,CAAS,MAAA,EAAO,EAAG;AAClC,UAAA,IAAIA,GAAAA,CAAG,IAAA,CAAK,IAAA,KAAS,KAAA,CAAM,IAAA,EAAM;AACjC,UAAA,MAAM,MAAA,GAASA,IAAG,IAAA,CAAK,MAAA;AACvB,UAAA,IAAI,MAAA,KAAW,SAAA,IAAa,MAAA,KAAW,UAAA,EAAY;AACjD,YAAA,MAAM,IAAI,KAAA;AAAA,cACR,CAAA,yBAAA,EAA4B,MAAM,IAAI,CAAA,oBAAA,EAAuBA,IAAG,IAAA,CAAK,EAAE,YAAY,MAAM,CAAA,CAAA;AAAA,aAC3F;AAAA,UACF;AAIA,UAAAA,GAAAA,CAAG,KAAK,IAAA,GAAO,MAAA;AAAA,QACjB;AAAA,MACF;AACA,MAAA,MAAM,CAAC,GAAA,EAAK,GAAG,IAAI,IAAI,KAAA,CAAM,IAAA;AAC7B,MAAA,IAAI,CAAC,GAAA,EAAK;AACR,QAAA,MAAM,IAAI,MAAM,+CAA+C,CAAA;AAAA,MACjE;AAIA,MAAA,MAAM,GAAA,GAAM,EAAE,GAAI,OAAA,CAAQ,KAAgC,GAAI,KAAA,CAAM,GAAA,IAAO,EAAC,EAAG;AAC/E,MAAA,OAAO,GAAA,CAAI,YAAA;AACX,MAAA,MAAM,MAAkB,UAAA,CAAW;AAAA,QACjC,OAAA,EAAS,GAAA;AAAA,QACT,IAAA;AAAA,QACA,KAAK,KAAA,CAAM,GAAA;AAAA,QACX,GAAA;AAAA,QACA,MAAM,KAAA,CAAM,IAAA;AAAA,QACZ,MAAM,KAAA,CAAM;AAAA,OACb,CAAA;AACD,MAAA,MAAM,IAAA,GAA0B;AAAA,QAC9B,EAAA;AAAA,QACA,IAAA,EAAM,UAAA;AAAA,QACN,eAAe,KAAA,CAAM,aAAA;AAAA,QACrB,OAAA,EAAS,CAAC,GAAA,EAAK,GAAG,IAAI,EAAE,GAAA,CAAI,QAAQ,CAAA,CAAE,IAAA,CAAK,GAAG,CAAA;AAAA,QAC9C,KAAK,GAAA,CAAI,GAAA;AAAA,QACT,MAAA,EAAQ,SAAA;AAAA,QACR,SAAA,EAAA,iBAAW,IAAI,IAAA,EAAK,EAAE,WAAA,EAAY;AAAA,QAClC,GAAA,EAAK,IAAA;AAAA,QACL,MAAM,KAAA,CAAM,IAAA;AAAA,QACZ,KAAK,KAAA,CAAM,GAAA;AAAA,QACX,GAAI,MAAM,IAAA,GAAO,EAAE,MAAM,KAAA,CAAM,IAAA,KAAS,EAAC;AAAA,QACzC,GAAI,MAAM,KAAA,GAAQ,EAAE,OAAO,KAAA,CAAM,KAAA,KAAU;AAAC,OAC9C;AACA,MAAA,MAAM,EAAA,GAAqB;AAAA,QACzB,IAAA;AAAA,QACA,GAAA;AAAA,QACA,cAAA,sBAAoB,GAAA,EAAI;AAAA,QACxB,aAAa,EAAC;AAAA,QACd,aAAa,EAAC;AAAA,QACd,eAAA,EAAiB,CAAA;AAAA,QACjB,OAAA,EAAS,IAAID,YAAAA,EAAa;AAAA,QAC1B,IAAA,EAAM,KAAA;AAAA,QACN,OAAA,EAAS,EAAA;AAAA,QACT,UAAA,EAAY;AAAA,OACd;AACA,MAAA,EAAA,CAAG,OAAA,CAAQ,gBAAgB,EAAE,CAAA;AAC7B,MAAA,QAAA,CAAS,GAAA,CAAI,IAAI,EAAE,CAAA;AACnB,MAAA,GAAA,CAAI,MAAA,CAAO,CAAC,KAAA,KAAkB;AAG5B,QAAA,WAAA,CAAY,EAAA,EAAI,MAAA,CAAO,IAAA,CAAK,KAAA,EAAO,MAAM,CAAC,CAAA;AAAA,MAC5C,CAAC,CAAA;AACD,MAAA,GAAA,CAAI,OAAO,CAAA,GAAA,KAAO;AAChB,QAAA,IAAI,EAAA,CAAG,IAAA,CAAK,MAAA,KAAW,QAAA,EAAU;AAC/B,UAAA,EAAA,CAAG,KAAK,MAAA,GAAS,QAAA;AAAA,QACnB;AACA,QAAA,EAAA,CAAG,IAAA,CAAK,OAAA,GAAA,iBAAU,IAAI,IAAA,IAAO,WAAA,EAAY;AACzC,QAAA,IAAI,OAAO,GAAA,CAAI,QAAA,KAAa,UAAU,EAAA,CAAG,IAAA,CAAK,WAAW,GAAA,CAAI,QAAA;AAC7D,QAAA,EAAA,CAAG,OAAA,CAAQ,IAAA,CAAK,MAAA,EAAQ,GAAG,CAAA;AAC3B,QAAA,EAAA,CAAG,OAAA,CAAQ,IAAA,CAAK,QAAA,EAAU,EAAA,CAAG,KAAK,MAAM,CAAA;AACxC,QAAA,eAAA,EAAgB;AAAA,MAClB,CAAC,CAAA;AACD,MAAA,eAAA,EAAgB;AAChB,MAAA,OAAO,IAAA;AAAA,IACT,CAAA;AAAA,IACA,MAAM,UAAA,CAAW,EAAA,EAAI,OAAA,EAAS;AAC5B,MAAA,MAAM,KAAA,GAAQ,QAAA,CAAS,GAAA,CAAI,EAAE,CAAA;AAC7B,MAAA,IAAI,KAAA,EAAO,MAAM,gBAAA,CAAiB,KAAK,CAAA;AACvC,MAAA,MAAM,EAAA,GAAK,iBAAA,CAAkB,EAAA,EAAI,YAAY,CAAA;AAC7C,MAAA,MAAM,YAAA,CAAa,IAAI,OAAO,CAAA;AAAA,IAChC,CAAA;AAAA,IACA,aAAA,CAAc,IAAI,OAAA,EAAS;AAQzB,MAAA,MAAM,KAAA,GAAQ,QAAA,CAAS,GAAA,CAAI,EAAE,CAAA;AAC7B,MAAA,IAAI,CAAC,KAAA,EAAO;AACV,QAAA,MAAM,IAAI,KAAA,CAAM,CAAA,2BAAA,EAA8B,EAAE,CAAA,CAAA,CAAG,CAAA;AAAA,MACrD;AACA,MAAA,IAAI,KAAA,CAAM,IAAA,CAAK,IAAA,KAAS,WAAA,EAAa;AACnC,QAAA,MAAM,IAAI,KAAA;AAAA,UACR,CAAA,wBAAA,EAA2B,EAAE,CAAA,gCAAA,EAAmC,KAAA,CAAM,KAAK,IAAI,CAAA,CAAA;AAAA,SACjF;AAAA,MACF;AACA,MAAA,IAAI,MAAM,IAAA,EAAM;AACd,QAAA,MAAM,IAAI,KAAA;AAAA,UACR,2BAA2B,EAAE,CAAA,oDAAA;AAAA,SAC/B;AAAA,MACF;AAIA,MAAA,KAAA,CAAM,YAAY;AAChB,QAAA,IAAI;AACF,UAAA,MAAM,iBAAiB,KAAK,CAAA;AAC5B,UAAA,MAAM,EAAA,GAAK,iBAAA,CAAkB,EAAA,EAAI,eAAe,CAAA;AAChD,UAAA,MAAM,YAAA,CAAa,IAAI,OAAO,CAAA;AAAA,QAChC,SAAS,GAAA,EAAK;AACZ,UAAA,UAAA;AAAA,YACE,KAAA;AAAA,YACA,WAAW,GAAA,YAAe,KAAA,GAAQ,IAAI,OAAA,GAAU,MAAA,CAAO,GAAG,CAAC,CAAA,CAAA;AAAA,YAC3D;AAAA,WACF;AAAA,QACF;AAAA,MACF,CAAA,GAAG;AAAA,IACL,CAAA;AAAA,IACA,IAAA,GAAO;AACL,MAAA,OAAO,KAAA,CAAM,KAAK,QAAA,CAAS,MAAA,EAAQ,CAAA,CAChC,GAAA,CAAI,OAAK,CAAA,CAAE,IAAI,EACf,IAAA,CAAK,CAAC,GAAG,CAAA,KAAM,CAAA,CAAE,UAAU,aAAA,CAAc,CAAA,CAAE,SAAS,CAAC,CAAA;AAAA,IAC1D,CAAA;AAAA,IACA,IAAI,EAAA,EAAI;AACN,MAAA,OAAO,QAAA,CAAS,GAAA,CAAI,EAAE,CAAA,EAAG,IAAA;AAAA,IAC3B,CAAA;AAAA,IACA,MAAA,CAAO,IAAI,MAAA,EAAQ;AACjB,MAAA,MAAM,EAAA,GAAK,QAAA,CAAS,GAAA,CAAI,EAAE,CAAA;AAC1B,MAAA,IAAI,CAAC,IAAI,OAAO,IAAA;AAGhB,MAAA,KAAA,MAAW,IAAA,IAAQ,EAAA,CAAG,WAAA,EAAa,MAAA,CAAO,MAAM,QAAQ,CAAA;AACxD,MAAA,MAAM,UAAU,CAAC,GAAA,KAGL,OAAO,GAAA,CAAI,IAAA,EAAM,IAAI,MAAM,CAAA;AACvC,MAAA,EAAA,CAAG,OAAA,CAAQ,EAAA,CAAG,MAAA,EAAQ,OAAO,CAAA;AAC7B,MAAA,OAAO,MAAM,EAAA,CAAG,OAAA,CAAQ,GAAA,CAAI,QAAQ,OAAO,CAAA;AAAA,IAC7C,CAAA;AAAA,IACA,SAAA,CAAU,EAAA,EAAI,OAAA,EAAS,MAAA,EAAQ,MAAA,EAAQ;AACrC,MAAA,MAAM,EAAA,GAAK,QAAA,CAAS,GAAA,CAAI,EAAE,CAAA;AAC1B,MAAA,IAAI,CAAC,MAAM,CAAC,EAAA,CAAG,OAAO,CAAC,EAAA,CAAG,gBAAgB,OAAO,IAAA;AAIjD,MAAA,KAAA,MAAW,KAAA,IAAS,EAAA,CAAG,WAAA,EAAa,MAAA,CAAO,KAAK,CAAA;AAGhD,MAAA,MAAM,KAAA,GAAQ,SAAA,EAAA;AACd,MAAA,EAAA,CAAG,cAAA,CAAe,GAAA,CAAI,KAAA,EAAO,EAAE,IAAA,EAAM,QAAQ,IAAA,EAAM,IAAA,EAAM,OAAA,CAAQ,IAAA,EAAM,CAAA;AACvE,MAAA,gBAAA,CAAiB,EAAE,CAAA;AACnB,MAAA,MAAM,WAAA,GAAc,CAAC,KAAA,KAAwB,MAAA,CAAO,KAAK,CAAA;AACzD,MAAA,MAAM,WAAA,GAAc,CAAC,GAAA,KAGT,MAAA,CAAO,GAAG,CAAA;AACtB,MAAA,EAAA,CAAG,OAAA,CAAQ,EAAA,CAAG,MAAA,EAAQ,WAAW,CAAA;AACjC,MAAA,EAAA,CAAG,OAAA,CAAQ,IAAA,CAAK,MAAA,EAAQ,WAAW,CAAA;AACnC,MAAA,OAAO;AAAA,QACL,MAAM,IAAA,EAAoB;AACxB,UAAA,IAAI,CAAC,GAAG,GAAA,EAAK;AACb,UAAA,IAAI;AACF,YAAA,EAAA,CAAG,GAAA,CAAI,MAAM,IAAI,CAAA;AAAA,UACnB,CAAA,CAAA,MAAQ;AAAA,UAER;AAAA,QACF,CAAA;AAAA,QACA,MAAA,CAAO,MAAc,IAAA,EAAoB;AACvC,UAAA,IAAI,CAAC,GAAG,cAAA,EAAgB;AACxB,UAAA,EAAA,CAAG,eAAe,GAAA,CAAI,KAAA,EAAO,EAAE,IAAA,EAAM,MAAM,CAAA;AAC3C,UAAA,gBAAA,CAAiB,EAAE,CAAA;AAAA,QACrB,CAAA;AAAA,QACA,MAAA,GAAe;AACb,UAAA,EAAA,CAAG,OAAA,CAAQ,GAAA,CAAI,MAAA,EAAQ,WAAW,CAAA;AAClC,UAAA,EAAA,CAAG,OAAA,CAAQ,GAAA,CAAI,MAAA,EAAQ,WAAW,CAAA;AAClC,UAAA,EAAA,CAAG,cAAA,EAAgB,OAAO,KAAK,CAAA;AAC/B,UAAA,gBAAA,CAAiB,EAAE,CAAA;AAAA,QACrB;AAAA,OACF;AAAA,IACF,CAAA;AAAA,IACA,eAAe,KAAA,EAAO;AACpB,MAAA,MAAM,MAAA,GAAS,QAAA,CAAS,GAAA,CAAI,KAAK,CAAA;AACjC,MAAA,IAAI,MAAA,SAAe,MAAA,CAAO,IAAA;AAC1B,MAAA,KAAA,MAAW,EAAA,IAAM,QAAA,CAAS,MAAA,EAAO,EAAG;AAClC,QAAA,IAAI,EAAA,CAAG,IAAA,CAAK,IAAA,KAAS,KAAA,SAAc,EAAA,CAAG,IAAA;AAAA,MACxC;AACA,MAAA,OAAO,MAAA;AAAA,IACT,CAAA;AAAA,IACA,kBAAA,CAAmB,IAAI,IAAA,EAAM;AAC3B,MAAA,MAAM,EAAA,GAAK,QAAA,CAAS,GAAA,CAAI,EAAE,CAAA;AAC1B,MAAA,IAAI,CAAC,EAAA,IAAM,CAAC,EAAA,CAAG,KAAK,OAAO,KAAA;AAC3B,MAAA,IAAI;AACF,QAAA,EAAA,CAAG,GAAA,CAAI,MAAM,IAAI,CAAA;AACjB,QAAA,OAAO,IAAA;AAAA,MACT,CAAA,CAAA,MAAQ;AACN,QAAA,OAAO,KAAA;AAAA,MACT;AAAA,IACF,CAAA;AAAA,IACA,kBAAA,CAAmB,IAAI,SAAA,EAAW;AAChC,MAAA,MAAM,EAAA,GAAK,QAAA,CAAS,GAAA,CAAI,EAAE,CAAA;AAC1B,MAAA,IAAI,CAAC,EAAA,IAAM,CAAC,EAAA,CAAG,KAAK,OAAO,IAAA;AAC3B,MAAA,MAAM,SAAS,MAAA,CAAO,MAAA,CAAO,EAAA,CAAG,WAAA,EAAa,GAAG,eAAe,CAAA;AAC/D,MAAA,IAAI,OAAO,SAAA,KAAc,QAAA,IAAY,YAAY,CAAA,IAAK,MAAA,CAAO,aAAa,SAAA,EAAW;AACnF,QAAA,OAAO,MAAA,CAAO,QAAA,CAAS,MAAA,CAAO,UAAA,GAAa,SAAS,CAAA;AAAA,MACtD;AACA,MAAA,OAAO,MAAA;AAAA,IACT,CAAA;AAAA,IACA,IAAA,CAAK,EAAA,EAAI,MAAA,GAAS,SAAA,EAAW;AAC3B,MAAA,MAAM,EAAA,GAAK,QAAA,CAAS,GAAA,CAAI,EAAE,CAAA;AAC1B,MAAA,IAAI,CAAC,IAAI,OAAO,KAAA;AAChB,MAAA,IACE,EAAA,CAAG,IAAA,CAAK,MAAA,KAAW,QAAA,IACnB,EAAA,CAAG,IAAA,CAAK,MAAA,KAAW,QAAA,IACnB,EAAA,CAAG,IAAA,CAAK,MAAA,KAAW,OAAA,EACnB;AACA,QAAA,OAAO,KAAA;AAAA,MACT;AACA,MAAA,EAAA,CAAG,KAAK,MAAA,GAAS,QAAA;AACjB,MAAA,EAAA,CAAG,IAAA,CAAK,OAAA,GAAA,iBAAU,IAAI,IAAA,IAAO,WAAA,EAAY;AAIzC,MAAA,IAAI,GAAG,YAAA,EAAc;AACnB,QAAA,KAAK,GAAG,YAAA,CAAa,KAAA,EAAM,CAAE,KAAA,CAAM,MAAM,MAAS,CAAA;AAAA,MACpD;AACA,MAAA,IAAI,GAAG,GAAA,EAAK;AACV,QAAA,IAAI;AACF,UAAA,EAAA,CAAG,GAAA,CAAI,KAAK,MAAM,CAAA;AAAA,QACpB,CAAA,CAAA,MAAQ;AAAA,QAER;AAAA,MACF;AACA,MAAA,EAAA,CAAG,KAAA,EAAO,KAAK,MAAM,CAAA;AACrB,MAAA,eAAA,EAAgB;AAChB,MAAA,OAAO,IAAA;AAAA,IACT,CAAA;AAAA,IACA,OAAO,EAAA,EAAI;AACT,MAAA,MAAM,EAAA,GAAK,QAAA,CAAS,GAAA,CAAI,EAAE,CAAA;AAC1B,MAAA,IAAI,CAAC,IAAI,OAAO,KAAA;AAEhB,MAAA,EAAA,CAAG,QAAQ,kBAAA,EAAmB;AAC9B,MAAA,QAAA,CAAS,OAAO,EAAE,CAAA;AAClB,MAAA,eAAA,EAAgB;AAChB,MAAA,OAAO,IAAA;AAAA,IACT,CAAA;AAAA,IACA,QAAA,GAAW;AACT,MAAA,YAAA,EAAa;AAAA,IACf;AAAA,GACF;AAeA,EAAA,SAAS,YAAA,GAAqB;AAC5B,IAAA,IAAI,YAAA,EAAc;AAClB,IAAA,YAAA,GAAe,IAAA;AACf,IAAA,IAAI,YAAA,eAA2B,YAAY,CAAA;AAC3C,IAAA,IAAI,OAAA,EAAS;AACX,MAAA,IAAI;AACF,QAAA,OAAA,CAAQ,GAAA,CAAI,QAAQ,aAAa,CAAA;AAAA,MACnC,CAAA,CAAA,MAAQ;AAAA,MAER;AAAA,IACF;AAKA,IAAA,MAAM,MAAA,GAAA,iBAAS,IAAI,IAAA,EAAK,EAAE,WAAA,EAAY;AACtC,IAAA,KAAA,MAAW,EAAA,IAAM,QAAA,CAAS,MAAA,EAAO,EAAG;AAClC,MAAA,EAAA,CAAG,QAAQ,kBAAA,EAAmB;AAC9B,MAAA,IACE,GAAG,IAAA,CAAK,MAAA,KAAW,aACnB,EAAA,CAAG,IAAA,CAAK,WAAW,UAAA,EACnB;AACA,QAAA,EAAA,CAAG,KAAK,MAAA,GAAS,QAAA;AACjB,QAAA,EAAA,CAAG,KAAK,OAAA,GAAU,MAAA;AAClB,QAAA,IAAI,GAAG,YAAA,EAAc;AACnB,UAAA,KAAK,GAAG,YAAA,CAAa,KAAA,EAAM,CAAE,KAAA,CAAM,MAAM,MAAS,CAAA;AAAA,QACpD;AACA,QAAA,IAAI,GAAG,GAAA,EAAK;AACV,UAAA,IAAI;AACF,YAAA,EAAA,CAAG,GAAA,CAAI,KAAK,SAAS,CAAA;AAAA,UACvB,CAAA,CAAA,MAAQ;AAAA,UAER;AAAA,QACF;AACA,QAAA,EAAA,CAAG,KAAA,EAAO,KAAK,SAAS,CAAA;AAAA,MAC1B;AAAA,IACF;AAKA,IAAA,IAAI,OAAA,EAAS;AACX,MAAA,IAAI;AACF,QAAA,MAAM,QAAA,GAAW;AAAA,UACf,OAAA,EAAS,MAAA;AAAA,UACT,QAAA,EAAU,KAAA,CAAM,IAAA,CAAK,QAAA,CAAS,MAAA,EAAQ,CAAA,CAAE,GAAA,CAAI,CAAA,CAAA,KAAK,CAAA,CAAE,IAAI;AAAA,SACzD;AACA,QAAA,SAAA,CAAUJ,QAAQ,WAAW,CAAA,EAAG,EAAE,SAAA,EAAW,MAAM,CAAA;AACnD,QAAA,aAAA,CAAc,aAAa,IAAA,CAAK,SAAA,CAAU,UAAU,IAAA,EAAM,CAAC,IAAI,IAAI,CAAA;AAAA,MACrE,CAAA,CAAA,MAAQ;AAAA,MAER;AAAA,IACF;AACA,IAAA,QAAA,CAAS,KAAA,EAAM;AAAA,EACjB;AACF;AAqBA,SAAS,mBAAA,CACP,aACA,QAAA,EACM;AACN,EAAA,IAAI,GAAA;AACJ,EAAA,IAAI;AACF,IAAA,GAAA,GAAM,YAAA,CAAa,aAAa,MAAM,CAAA;AAAA,EACxC,CAAA,CAAA,MAAQ;AACN,IAAA;AAAA,EACF;AACA,EAAA,IAAI,MAAA;AACJ,EAAA,IAAI;AACF,IAAA,MAAA,GAAS,IAAA,CAAK,MAAM,GAAG,CAAA;AAAA,EACzB,CAAA,CAAA,MAAQ;AACN,IAAA,OAAA,CAAQ,IAAA;AAAA,MACN,2BAA2B,WAAW,CAAA,6BAAA;AAAA,KACxC;AACA,IAAA;AAAA,EACF;AACA,EAAA,IAAI,CAAC,KAAA,CAAM,OAAA,CAAQ,MAAA,CAAO,QAAQ,CAAA,EAAG;AAErC,EAAA,MAAM,MAAA,GAAS,MAAA,CAAO,QAAA,CACnB,MAAA,CAAO,CAAC,CAAA,KAA8B,CAAC,CAAC,CAAA,IAAK,OAAO,CAAA,CAAE,EAAA,KAAO,QAAQ,CAAA,CACrE,IAAA,CAAK,CAAC,CAAA,EAAG,CAAA,KAAM,CAAA,CAAE,SAAA,CAAU,aAAA,CAAc,CAAA,CAAE,SAAS,CAAC,CAAA,CACrD,KAAA,CAAM,CAAA,EAAG,WAAW,CAAA;AACvB,EAAA,MAAM,GAAA,GAAA,iBAAM,IAAI,IAAA,EAAK,EAAE,WAAA,EAAY;AACnC,EAAA,KAAA,MAAW,QAAQ,MAAA,EAAQ;AACzB,IAAA,IAAI,QAAA,CAAS,GAAA,CAAI,IAAA,CAAK,EAAE,CAAA,EAAG;AAC3B,IAAA,MAAM,QAAA,GAAW,IAAA,CAAK,MAAA,KAAW,SAAA,IAAa,KAAK,MAAA,KAAW,UAAA;AAC9D,IAAA,MAAM,eAAkC,QAAA,GACpC;AAAA,MACE,GAAG,IAAA;AAAA,MACH,MAAA,EAAQ,QAAA;AAAA,MACR,OAAA,EAAS,KAAK,OAAA,IAAW;AAAA,KAC3B,GACA,IAAA;AACJ,IAAA,MAAM,EAAA,GAAqB;AAAA,MACzB,IAAA,EAAM,YAAA;AAAA,MACN,aAAa,EAAC;AAAA,MACd,aAAa,EAAC;AAAA,MACd,eAAA,EAAiB,CAAA;AAAA,MACjB,OAAA,EAAS,IAAII,YAAAA,EAAa;AAAA,MAC1B,IAAA,EAAM,KAAA;AAAA,MACN,OAAA,EAAS,EAAA;AAAA,MACT,UAAA,EAAY;AAAA,KACd;AACA,IAAA,EAAA,CAAG,OAAA,CAAQ,gBAAgB,EAAE,CAAA;AAC7B,IAAA,QAAA,CAAS,GAAA,CAAI,IAAA,CAAK,EAAA,EAAI,EAAE,CAAA;AAAA,EAC1B;AACF;AAIA,SAAS,SAAS,GAAA,EAAqB;AACrC,EAAA,IAAI,GAAA,KAAQ,IAAI,OAAO,IAAA;AACvB,EAAA,IAAI,yBAAA,CAA0B,IAAA,CAAK,GAAG,CAAA,EAAG,OAAO,GAAA;AAChD,EAAA,OAAO,CAAA,CAAA,EAAI,GAAA,CAAI,OAAA,CAAQ,YAAA,EAAc,MAAM,CAAC,CAAA,CAAA,CAAA;AAC9C;AChyCO,IAAM,mBAAN,MAAuB;AAAA,EACpB,OAAA,uBAAc,GAAA,EAAyB;AAAA,EACvC,WAAA,GAAc,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAKd,WAAA,GAAc,KAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQtB,MAAM,aAAA,GAA+B;AACnC,IAAA,IAAI,OAAA,GAAU,CAAA;AACd,IAAA,IAAI;AACF,MAAA,MAAM,EAAA,GAAK,MAAMP,QAAAA,CAAG,IAAA,CAAK,oBAAoB,CAAA;AAC7C,MAAA,OAAA,GAAU,EAAA,CAAG,OAAA;AAAA,IACf,CAAA,CAAA,MAAQ;AAGN,MAAA,OAAA,GAAU,CAAA;AAAA,IACZ;AACA,IAAA,IAAI,IAAA,CAAK,WAAA,IAAe,OAAA,KAAY,IAAA,CAAK,WAAA,EAAa;AAEtD,IAAA,MAAM,MAAA,GAAS,MAAM,gBAAA,EAAiB,CAAE,MAAM,OAAO;AAAA,MACnD,OAAA,EAAS,CAAA;AAAA,MACT,SAAS;AAAC,KACZ,CAAE,CAAA;AACF,IAAA,MAAM,SAAA,GAAY,IAAI,GAAA,CAAI,MAAA,CAAO,QAAQ,GAAA,CAAI,CAAA,CAAA,KAAK,CAAA,CAAE,EAAE,CAAC,CAAA;AAGvD,IAAA,KAAA,MAAW,CAAC,EAAA,EAAI,CAAC,KAAK,IAAA,CAAK,OAAA,CAAQ,SAAQ,EAAG;AAC5C,MAAA,IAAI,CAAC,SAAA,CAAU,GAAA,CAAI,EAAE,CAAA,EAAG;AACtB,QAAA,MAAM,SAAA,CAAU,EAAE,MAAM,CAAA;AACxB,QAAA,IAAA,CAAK,OAAA,CAAQ,OAAO,EAAE,CAAA;AAAA,MACxB;AAAA,IACF;AAEA,IAAA,KAAA,MAAW,KAAA,IAAS,OAAO,OAAA,EAAS;AAClC,MAAA,MAAM,QAAA,GAAW,IAAA,CAAK,OAAA,CAAQ,GAAA,CAAI,MAAM,EAAE,CAAA;AAC1C,MAAA,IAAI,QAAA,EAAU;AAIZ,QAAA,IACE,IAAA,CAAK,SAAA,CAAU,QAAA,CAAS,KAAA,CAAM,QAAQ,MACtC,IAAA,CAAK,SAAA,CAAU,KAAA,CAAM,QAAQ,CAAA,EAC7B;AACA,UAAA,MAAM,SAAA,CAAU,SAAS,MAAM,CAAA;AAC/B,UAAA,IAAA,CAAK,QAAQ,GAAA,CAAI,KAAA,CAAM,EAAA,EAAI,gBAAA,CAAiB,KAAK,CAAC,CAAA;AAAA,QACpD,CAAA,MAAO;AACL,UAAA,QAAA,CAAS,KAAA,GAAQ,KAAA;AAAA,QACnB;AAAA,MACF,CAAA,MAAO;AACL,QAAA,IAAA,CAAK,QAAQ,GAAA,CAAI,KAAA,CAAM,EAAA,EAAI,gBAAA,CAAiB,KAAK,CAAC,CAAA;AAAA,MACpD;AAAA,IACF;AACA,IAAA,IAAA,CAAK,WAAA,GAAc,OAAA;AACnB,IAAA,IAAA,CAAK,WAAA,GAAc,IAAA;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAc,gBAAgB,KAAA,EAA4C;AACxE,IAAA,MAAM,KAAK,aAAA,EAAc;AACzB,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,WAAA,CAAY,KAAK,CAAA;AACrC,IAAA,IAAI,CAAC,QAAQ,OAAO,IAAA;AACpB,IAAA,IAAI,MAAA,CAAO,QAAQ,OAAO,MAAA;AAC1B,IAAA,IAAI;AACF,MAAA,MAAM,MAAA,GAAS,MAAM,UAAA,CAAW,MAAA,CAAO,KAAK,CAAA;AAC5C,MAAA,MAAA,CAAO,MAAA,GAAS,MAAA;AAChB,MAAA,MAAA,CAAO,SAAA,GAAY,IAAA;AAGnB,MAAA,MAAM,CAAA,GAAI,MAAM,MAAA,CAAO,SAAA,EAAU;AACjC,MAAA,MAAA,CAAO,KAAA,GAAQ,CAAA,CAAE,KAAA,CAAM,GAAA,CAAI,YAAY,CAAA;AACvC,MAAA,OAAO,MAAA;AAAA,IACT,SAAS,GAAA,EAAK;AACZ,MAAA,MAAA,CAAO,MAAA,GAAS,IAAA;AAChB,MAAA,MAAA,CAAO,KAAA,GAAQ,IAAA;AACf,MAAA,MAAA,CAAO,YAAY,GAAA,YAAe,KAAA,GAAQ,GAAA,CAAI,OAAA,GAAU,OAAO,GAAG,CAAA;AAClE,MAAA,OAAO,MAAA;AAAA,IACT;AAAA,EACF;AAAA;AAAA;AAAA,EAIQ,YAAY,SAAA,EAA4C;AAC9D,IAAA,KAAA,MAAW,CAAA,IAAK,IAAA,CAAK,OAAA,CAAQ,MAAA,EAAO,EAAG;AACrC,MAAA,IAAI,CAAA,CAAE,KAAA,CAAM,KAAA,KAAU,SAAA,EAAW,OAAO,CAAA;AACxC,MAAA,IAAI,CAAA,CAAE,KAAA,CAAM,EAAA,KAAO,SAAA,EAAW,OAAO,CAAA;AAAA,IACvC;AACA,IAAA,OAAO,MAAA;AAAA,EACT;AAAA,EAEA,MAAM,WAAA,GAA4C;AAChD,IAAA,MAAM,KAAK,aAAA,EAAc;AACzB,IAAA,OAAO,KAAA,CAAM,KAAK,IAAA,CAAK,OAAA,CAAQ,QAAQ,CAAA,CAAE,IAAI,CAAA,CAAA,MAAM;AAAA,MACjD,KAAA,EAAO,EAAE,KAAA,CAAM,KAAA;AAAA,MACf,QAAA,EAAU,EAAE,KAAA,CAAM,EAAA;AAAA,MAClB,MAAA,EAAQ,CAAA,CAAE,KAAA,CAAM,QAAA,CAAS,MAAA;AAAA,MACzB,IAAA,EAAM,CAAA,CAAE,KAAA,CAAM,QAAA,CAAS,IAAA;AAAA,MACvB,QAAQ,CAAA,CAAE,MAAA,GACN,WAAA,GACA,CAAA,CAAE,YACA,OAAA,GACA,SAAA;AAAA,MACN,SAAA,EAAW,CAAA,CAAE,KAAA,EAAO,MAAA,IAAU,CAAA;AAAA,MAC9B,GAAI,EAAE,SAAA,GAAY,EAAE,WAAW,CAAA,CAAE,SAAA,KAAc;AAAC,KAClD,CAAE,CAAA;AAAA,EACJ;AAAA,EAEA,MAAM,UACJ,KAAA,EACoF;AACpF,IAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,eAAA,CAAgB,KAAK,CAAA;AAC/C,IAAA,IAAI,CAAC,QAAQ,OAAO,EAAE,IAAI,KAAA,EAAO,KAAA,EAAO,CAAA,eAAA,EAAkB,KAAK,CAAA,CAAA,CAAA,EAAI;AACnE,IAAA,IAAI,CAAC,MAAA,CAAO,MAAA,IAAU,CAAC,OAAO,KAAA,EAAO;AACnC,MAAA,OAAO;AAAA,QACL,EAAA,EAAI,KAAA;AAAA,QACJ,KAAA,EAAO,OAAO,SAAA,IAAa;AAAA,OAC7B;AAAA,IACF;AACA,IAAA,OAAO,EAAE,EAAA,EAAI,IAAA,EAAM,KAAA,EAAO,OAAO,KAAA,EAAM;AAAA,EACzC;AAAA,EAEA,MAAM,QAAA,CACJ,KAAA,EACA,QAAA,EACA,IAAA,EAC2B;AAC3B,IAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,eAAA,CAAgB,KAAK,CAAA;AAC/C,IAAA,IAAI,CAAC,QAAQ,OAAO,EAAE,IAAI,KAAA,EAAO,KAAA,EAAO,CAAA,eAAA,EAAkB,KAAK,CAAA,CAAA,CAAA,EAAI;AACnE,IAAA,IAAI,CAAC,OAAO,MAAA,EAAQ;AAClB,MAAA,OAAO;AAAA,QACL,EAAA,EAAI,KAAA;AAAA,QACJ,KAAA,EAAO,OAAO,SAAA,IAAa;AAAA,OAC7B;AAAA,IACF;AACA,IAAA,IAAI;AACF,MAAA,MAAM,MAAA,GAAS,MAAM,MAAA,CAAO,MAAA,CAAO,QAAA,CAAS;AAAA,QAC1C,IAAA,EAAM,QAAA;AAAA,QACN,WACE,IAAA,IAAQ,OAAO,IAAA,KAAS,QAAA,GACnB,OACD;AAAC,OACR,CAAA;AACD,MAAA,OAAO,EAAE,EAAA,EAAI,IAAA,EAAM,MAAA,EAAO;AAAA,IAC5B,SAAS,GAAA,EAAK;AAIZ,MAAA,MAAM,MAAM,GAAA,YAAe,KAAA,GAAQ,GAAA,CAAI,OAAA,GAAU,OAAO,GAAG,CAAA;AAC3D,MAAA,IAAI,qCAAA,CAAsC,IAAA,CAAK,GAAG,CAAA,EAAG;AACnD,QAAA,MAAM,SAAA,CAAU,OAAO,MAAM,CAAA;AAC7B,QAAA,MAAA,CAAO,MAAA,GAAS,IAAA;AAChB,QAAA,MAAA,CAAO,KAAA,GAAQ,IAAA;AACf,QAAA,MAAA,CAAO,SAAA,GAAY,GAAA;AAAA,MACrB;AACA,MAAA,OAAO,EAAE,EAAA,EAAI,KAAA,EAAO,KAAA,EAAO,GAAA,EAAI;AAAA,IACjC;AAAA,EACF;AAAA,EAEA,MAAM,QAAA,GAA0B;AAC9B,IAAA,MAAM,OAAA,CAAQ,GAAA;AAAA,MACZ,KAAA,CAAM,IAAA,CAAK,IAAA,CAAK,OAAA,CAAQ,MAAA,EAAQ,CAAA,CAAE,GAAA,CAAI,CAAA,CAAA,KAAK,SAAA,CAAU,CAAA,CAAE,MAAM,CAAC;AAAA,KAChE;AACA,IAAA,IAAA,CAAK,QAAQ,KAAA,EAAM;AAAA,EACrB;AACF,CAAA;AAEA,SAAS,iBAAiB,KAAA,EAAsC;AAC9D,EAAA,OAAO,EAAE,KAAA,EAAO,MAAA,EAAQ,MAAM,KAAA,EAAO,IAAA,EAAM,WAAW,IAAA,EAAK;AAC7D;AAEA,SAAS,aAAa,IAAA,EAIE;AACtB,EAAA,OAAO;AAAA,IACL,MAAM,IAAA,CAAK,IAAA;AAAA,IACX,GAAI,KAAK,WAAA,GAAc,EAAE,aAAa,IAAA,CAAK,WAAA,KAAgB,EAAC;AAAA,IAC5D,GAAI,KAAK,WAAA,GAAc,EAAE,aAAa,IAAA,CAAK,WAAA,KAAgB;AAAC,GAC9D;AACF;AAWA,SAAS,sBACP,GAAA,EACwB;AACxB,EAAA,MAAM,MAA8B,EAAC;AACrC,EAAA,KAAA,MAAW,CAAC,CAAA,EAAG,CAAC,KAAK,MAAA,CAAO,OAAA,CAAQ,GAAG,CAAA,EAAG;AACxC,IAAA,MAAM,WAAW,CAAA,CAAE,OAAA;AAAA,MACjB,0CAAA;AAAA,MACA,CAAC,MAAA,EAAQ,IAAA,EAAc,QAAA,KAAiC;AACtD,QAAA,MAAM,OAAA,GAAU,OAAA,CAAQ,GAAA,CAAI,IAAI,CAAA;AAChC,QAAA,IAAI,OAAA,KAAY,QAAW,OAAO,OAAA;AAClC,QAAA,IAAI,QAAA,KAAa,QAAW,OAAO,QAAA;AACnC,QAAA,OAAO,EAAA;AAAA,MACT;AAAA,KACF;AAIA,IAAA,IAAI,QAAA,CAAS,WAAW,CAAA,EAAG;AAC3B,IAAA,GAAA,CAAI,CAAC,CAAA,GAAI,QAAA;AAAA,EACX;AACA,EAAA,OAAO,GAAA;AACT;AAEA,eAAe,UAAU,MAAA,EAAsC;AAC7D,EAAA,IAAI,CAAC,MAAA,EAAQ;AACb,EAAA,IAAI;AACF,IAAA,MAAM,OAAO,KAAA,EAAM;AAAA,EACrB,CAAA,CAAA,MAAQ;AAAA,EAER;AACF;AAOA,eAAe,WAAW,KAAA,EAA0C;AAClE,EAAA,MAAM,OAAO,KAAA,CAAM,QAAA;AACnB,EAAA,MAAM,SAAS,IAAI,MAAA;AAAA,IACjB,EAAE,IAAA,EAAM,yBAAA,EAA2B,OAAA,EAAS,OAAA,EAAQ;AAAA,IACpD,EAAE,YAAA,EAAc,EAAC;AAAE,GACrB;AACA,EAAA,IAAI,IAAA,CAAK,SAAS,OAAA,EAAS;AACzB,IAAA,IAAI,CAAC,KAAK,OAAA,EAAS;AACjB,MAAA,MAAM,IAAI,KAAA;AAAA,QACR,CAAA,QAAA,EAAW,MAAM,KAAK,CAAA,mCAAA;AAAA,OACxB;AAAA,IACF;AAOA,IAAA,MAAM,WAAA,GAAc,qBAAA,CAAsB,IAAA,CAAK,GAAA,IAAO,EAAE,CAAA;AACxD,IAAA,MAAM,SAAA,GAAY,IAAI,oBAAA,CAAqB;AAAA,MACzC,SAAS,IAAA,CAAK,OAAA;AAAA,MACd,IAAA,EAAM,IAAA,CAAK,IAAA,IAAQ,EAAC;AAAA,MACpB,KAAK,EAAE,GAAG,OAAA,CAAQ,GAAA,EAAK,GAAG,WAAA,EAAY;AAAA;AAAA;AAAA,MAGtC,MAAA,EAAQ;AAAA,KACT,CAAA;AACD,IAAA,MAAM,YAAsB,EAAC;AAC7B,IAAA,SAAA,CAAU,MAAA,EAAQ,EAAA,CAAG,MAAA,EAAQ,CAAC,KAAA,KAA2B;AACvD,MAAA,SAAA,CAAU,IAAA,CAAK,OAAO,KAAA,KAAU,QAAA,GAAW,QAAQ,KAAA,CAAM,QAAA,CAAS,MAAM,CAAC,CAAA;AACzE,MAAA,IAAI,SAAA,CAAU,MAAA,GAAS,EAAA,EAAI,SAAA,CAAU,KAAA,EAAM;AAAA,IAC7C,CAAC,CAAA;AACD,IAAA,IAAI;AACF,MAAA,MAAM,MAAA,CAAO,QAAQ,SAAS,CAAA;AAAA,IAChC,SAAS,GAAA,EAAK;AACZ,MAAA,MAAM,UAAA,GAAa,SAAA,CAAU,IAAA,CAAK,EAAE,EAAE,IAAA,EAAK;AAC3C,MAAA,MAAM,MAAM,GAAA,YAAe,KAAA,GAAQ,GAAA,CAAI,OAAA,GAAU,OAAO,GAAG,CAAA;AAC3D,MAAA,MAAM,IAAI,KAAA,CAAM,UAAA,GAAa,CAAA,EAAG,GAAG;AAAA,QAAA,EAAa,UAAA,CAAW,KAAA,CAAM,IAAI,CAAC,KAAK,GAAG,CAAA;AAAA,IAChF;AACA,IAAA,OAAO,MAAA;AAAA,EACT;AACA,EAAA,IAAI,IAAA,CAAK,SAAS,MAAA,EAAQ;AACxB,IAAA,IAAI,CAAC,KAAK,GAAA,EAAK,MAAM,IAAI,KAAA,CAAM,CAAA,QAAA,EAAW,KAAA,CAAM,KAAK,CAAA,YAAA,CAAc,CAAA;AACnE,IAAA,MAAM,YAAY,IAAI,6BAAA,CAA8B,IAAI,GAAA,CAAI,IAAA,CAAK,GAAG,CAAA,EAAG;AAAA,MACrE,WAAA,EAAa;AAAA,QACX,OAAA,EAAS,IAAA,CAAK,OAAA,IAAW;AAAC;AAC5B,KACD,CAAA;AACD,IAAA,MAAM,MAAA,CAAO,QAAQ,SAAS,CAAA;AAC9B,IAAA,OAAO,MAAA;AAAA,EACT;AACA,EAAA,IAAI,IAAA,CAAK,SAAS,KAAA,EAAO;AACvB,IAAA,IAAI,CAAC,KAAK,GAAA,EAAK,MAAM,IAAI,KAAA,CAAM,CAAA,QAAA,EAAW,KAAA,CAAM,KAAK,CAAA,YAAA,CAAc,CAAA;AACnE,IAAA,MAAM,YAAY,IAAI,kBAAA,CAAmB,IAAI,GAAA,CAAI,IAAA,CAAK,GAAG,CAAA,EAAG;AAAA,MAC1D,WAAA,EAAa;AAAA,QACX,OAAA,EAAS,IAAA,CAAK,OAAA,IAAW;AAAC;AAC5B,KACD,CAAA;AACD,IAAA,MAAM,MAAA,CAAO,QAAQ,SAAS,CAAA;AAC9B,IAAA,OAAO,MAAA;AAAA,EACT;AACA,EAAA,MAAM,IAAI,KAAA;AAAA,IACR,CAAA,QAAA,EAAW,KAAA,CAAM,KAAK,CAAA,kCAAA,EAAqC,KAAK,IAAI,CAAA,CAAA;AAAA,GACtE;AACF;ACnVA,IAAM,aAAA,GAAgB,UAAU,QAAQ,CAAA;AAExC,IAAM,SAAA,GAAY,2CAAA;AAElB,IAAM,kBAAA,GAAqB,GAAA;AAEpB,SAAS,mBAAA,GAAsC;AACpD,EAAA,IAAI,KAAA,GAA6B,IAAA;AACjC,EAAA,IAAI,UAAA,GAA4B,IAAA;AAEhC,EAAA,OAAO;AAAA,IACL,EAAA,EAAI,OAAA;AAAA,IACJ,MAAM,MAAM,IAAA,EAA0D;AACpE,MAAA,MAAM,uBAAA,EAAwB;AAC9B,MAAA,MAAM,SAAA,GAAY,UAAU,IAAA,CAAK,MAAA,CAAO,IAAI,CAAA,CAAA,EAAI,IAAA,CAAK,OAAO,IAAI,CAAA,CAAA;AAShE,MAAA,MAAM,EAAA,GAAK,WAAA,CAAY,CAAC,CAAA,CAAE,SAAS,KAAK,CAAA;AACxC,MAAA,MAAM,GAAA,GAAMX,IAAAA,CAAK,IAAA,CAAK,SAAA,EAAW,aAAa,CAAA;AAC9C,MAAA,MAAME,KAAAA,CAAM,GAAA,EAAK,EAAE,SAAA,EAAW,MAAM,CAAA;AACpC,MAAA,UAAA,GAAaF,IAAAA,CAAK,GAAA,EAAK,CAAA,YAAA,EAAe,EAAE,CAAA,IAAA,CAAM,CAAA;AAC9C,MAAA,MAAM,UAAA,GAAa;AAAA,QACjB,CAAA,sDAAA,CAAA;AAAA,QACA,CAAA,0DAAA,CAAA;AAAA,QACA,CAAA,6DAAA,CAAA;AAAA,QACA,CAAA,iBAAA,CAAA;AAAA,QACA,CAAA,mBAAA,CAAA;AAAA,QACA,CAAA,eAAA,CAAA;AAAA,QACA,CAAA;AAAA,OACF,CAAE,KAAK,IAAI,CAAA;AACX,MAAA,MAAMI,SAAAA,CAAU,UAAA,EAAY,UAAA,EAAY,MAAM,CAAA;AAC9C,MAAA,MAAM,IAAA,GAAOa,KAAAA;AAAA,QACX,aAAA;AAAA,QACA,CAAC,QAAA,EAAU,UAAA,EAAY,UAAA,EAAY,SAAS,SAAS,CAAA;AAAA,QACrD,EAAE,OAAO,CAAC,QAAA,EAAU,QAAQ,MAAM,CAAA,EAAG,OAAO,KAAA;AAAM,OACpD;AACA,MAAA,KAAA,GAAQ,IAAA;AAER,MAAA,MAAM,MAAM,MAAM,IAAI,OAAA,CAAgB,CAACZ,UAAS,MAAA,KAAW;AACzD,QAAA,IAAI,OAAA,GAAU,KAAA;AACd,QAAA,MAAM,KAAA,GAAQ,WAAW,MAAM;AAC7B,UAAA,IAAI,OAAA,EAAS;AACb,UAAA,OAAA,GAAU,IAAA;AACV,UAAA,IAAI;AACF,YAAA,IAAA,CAAK,KAAK,SAAS,CAAA;AAAA,UACrB,CAAA,CAAA,MAAQ;AAAA,UAER;AACA,UAAA,MAAA;AAAA,YACE,IAAI,KAAA;AAAA,cACF,CAAA,6CAAA,EAAgD,qBAAqB,GAAI,CAAA,CAAA;AAAA;AAC3E,WACF;AAAA,QACF,GAAG,kBAAkB,CAAA;AAErB,QAAA,MAAM,MAAA,GAAS,CAAC,KAAA,KAAkB;AAChC,UAAA,MAAMJ,KAAAA,GAAO,KAAA,CAAM,QAAA,CAAS,MAAM,CAAA;AAClC,UAAA,KAAA,MAAW,IAAA,IAAQA,KAAAA,CAAK,KAAA,CAAM,OAAO,CAAA,EAAG;AACtC,YAAA,IAAI,KAAK,MAAA,GAAS,CAAA,OAAQ,KAAA,GAAQ,CAAA,cAAA,EAAiB,IAAI,CAAA,CAAE,CAAA;AAAA,UAC3D;AACA,UAAA,IAAI,OAAA,EAAS;AACb,UAAA,MAAM,KAAA,GAAQA,KAAAA,CAAK,KAAA,CAAM,SAAS,CAAA;AAClC,UAAA,IAAI,KAAA,EAAO;AACT,YAAA,OAAA,GAAU,IAAA;AACV,YAAA,YAAA,CAAa,KAAK,CAAA;AAClB,YAAAI,QAAAA,CAAQ,KAAA,CAAM,CAAC,CAAC,CAAA;AAAA,UAClB;AAAA,QACF,CAAA;AAIA,QAAA,IAAA,CAAK,MAAA,EAAQ,EAAA,CAAG,MAAA,EAAQ,MAAM,CAAA;AAC9B,QAAA,IAAA,CAAK,MAAA,EAAQ,EAAA,CAAG,MAAA,EAAQ,MAAM,CAAA;AAE9B,QAAA,IAAA,CAAK,IAAA,CAAK,SAAS,CAAA,GAAA,KAAO;AACxB,UAAA,IAAI,OAAA,EAAS;AACb,UAAA,OAAA,GAAU,IAAA;AACV,UAAA,YAAA,CAAa,KAAK,CAAA;AAClB,UAAA,MAAA,CAAO,GAAG,CAAA;AAAA,QACZ,CAAC,CAAA;AACD,QAAA,IAAA,CAAK,IAAA,CAAK,MAAA,EAAQ,CAAC,IAAA,EAAM,MAAA,KAAW;AAClC,UAAA,IAAI,OAAA,EAAS;AACb,UAAA,OAAA,GAAU,IAAA;AACV,UAAA,YAAA,CAAa,KAAK,CAAA;AAClB,UAAA,MAAA;AAAA,YACE,IAAI,KAAA;AAAA,cACF,CAAA,+CAAA,EAAkD,IAAI,CAAA,SAAA,EAAY,MAAM,CAAA,CAAA;AAAA;AAC1E,WACF;AAAA,QACF,CAAC,CAAA;AAAA,MACH,CAAC,CAAA;AAKD,MAAA,IAAA,CAAK,IAAA,CAAK,MAAA,EAAQ,CAAC,IAAA,EAAM,MAAA,KAAW;AAClC,QAAA,IAAA,CAAK,KAAA;AAAA,UACH,CAAA,2BAAA,EAA8B,IAAA,IAAQ,GAAG,CAAA,QAAA,EAAW,UAAU,GAAG,CAAA,CAAA;AAAA,SACnE;AAAA,MACF,CAAC,CAAA;AAED,MAAA,OAAO,EAAE,SAAA,EAAW,GAAA,EAAK,GAAA,EAAK,IAAA,CAAK,OAAO,IAAA,EAAK;AAAA,IACjD,CAAA;AAAA,IAEA,MAAM,IAAA,GAAsB;AAC1B,MAAA,MAAM,IAAA,GAAO,KAAA;AACb,MAAA,MAAM,GAAA,GAAM,UAAA;AACZ,MAAA,KAAA,GAAQ,IAAA;AACR,MAAA,UAAA,GAAa,IAAA;AAIb,MAAA,IAAI,GAAA,EAAK;AACP,QAAA,IAAI;AACF,UAAA,MAAMe,EAAAA,CAAG,GAAA,EAAK,EAAE,KAAA,EAAO,MAAM,CAAA;AAAA,QAC/B,CAAA,CAAA,MAAQ;AAAA,QAER;AAAA,MACF;AACA,MAAA,IAAI,CAAC,IAAA,IAAQ,IAAA,CAAK,QAAA,KAAa,IAAA,EAAM;AACrC,MAAA,IAAA,CAAK,KAAK,SAAS,CAAA;AAEnB,MAAA,MAAM,KAAA,GAAQ,WAAW,MAAM;AAC7B,QAAA,IAAI;AACF,UAAA,IAAA,CAAK,KAAK,SAAS,CAAA;AAAA,QACrB,CAAA,CAAA,MAAQ;AAAA,QAER;AAAA,MACF,GAAG,GAAK,CAAA;AACR,MAAA,KAAA,CAAM,KAAA,EAAM;AACZ,MAAA,MAAM,IAAI,OAAA,CAAc,CAAAf,QAAAA,KAAW;AACjC,QAAA,IAAI,IAAA,CAAK,aAAa,IAAA,EAAM;AAC1B,UAAA,YAAA,CAAa,KAAK,CAAA;AAClB,UAAAA,QAAAA,EAAQ;AACR,UAAA;AAAA,QACF;AACA,QAAA,IAAA,CAAK,IAAA,CAAK,QAAQ,MAAM;AACtB,UAAA,YAAA,CAAa,KAAK,CAAA;AAClB,UAAAA,QAAAA,EAAQ;AAAA,QACV,CAAC,CAAA;AAAA,MACH,CAAC,CAAA;AAAA,IACH;AAAA,GACF;AACF;AAEA,eAAe,uBAAA,GAAyC;AACtD,EAAA,IAAI;AACF,IAAA,MAAM,aAAA,CAAc,eAAe,CAAC,WAAW,GAAG,EAAE,OAAA,EAAS,KAAO,CAAA;AAAA,EACtE,CAAA,CAAA,MAAQ;AACN,IAAA,MAAM,IAAI,KAAA;AAAA,MACR;AAAA,KAKF;AAAA,EACF;AACF;;;AC9DO,IAAM,mBAAN,MAAuB;AAAA,EACpB,KAAA,GAA4B,IAAA;AAAA,EAC5B,WAAA,GAA6B,IAAA;AAAA,EAC7B,QAAA,GAAkC,IAAA;AAAA,EAClC,SAAA;AAAA,EACS,IAAA;AAAA,EAEjB,YAAY,IAAA,EAA+B;AACzC,IAAA,IAAA,CAAK,IAAA,GAAO,IAAA;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOS,WAAW,MAAmB;AACrC,IAAA,IAAI,KAAK,WAAA,KAAgB,IAAA,EAAM,OAAO,EAAE,MAAM,MAAA,EAAO;AACrD,IAAA,OAAO,EAAE,IAAA,EAAM,QAAA,EAAU,KAAA,EAAO,KAAK,WAAA,EAAY;AAAA,EACnD,CAAA;AAAA,EAEA,MAAA,GAAuB;AACrB,IAAA,IAAI,CAAC,KAAK,KAAA,EAAO;AACf,MAAA,OAAO,EAAE,OAAA,EAAS,KAAA,EAAO,SAAA,EAAW,KAAK,SAAA,EAAU;AAAA,IACrD;AACA,IAAA,OAAO;AAAA,MACL,OAAA,EAAS,IAAA;AAAA,MACT,QAAA,EAAU,KAAK,KAAA,CAAM,QAAA;AAAA,MACrB,SAAA,EAAW,KAAK,KAAA,CAAM,SAAA;AAAA,MACtB,GAAA,EAAK,KAAK,KAAA,CAAM,GAAA;AAAA,MAChB,SAAA,EAAW,KAAK,KAAA,CAAM,SAAA;AAAA,MACtB,MAAA,EAAQ,KAAK,KAAA,CAAM,MAAA;AAAA,MACnB,cAAA,EAAgB,KAAK,KAAA,CAAM,cAAA;AAAA,MAC3B,WAAW,IAAA,CAAK;AAAA,KAClB;AAAA,EACF;AAAA,EAEA,MAAM,OAAO,KAAA,EAA2C;AACtD,IAAA,IAAI,KAAK,KAAA,EAAO;AAId,MAAA,MAAM,IAAI,KAAA;AAAA,QACR;AAAA,OACF;AAAA,IACF;AACA,IAAA,MAAM,UAAA,GAAa,MAAM,QAAA,IAAY,OAAA;AACrC,IAAA,MAAM,QAAA,GAAW,aAAa,UAAU,CAAA;AACxC,IAAA,IAAA,CAAK,SAAA,GAAY,MAAA;AAEjB,IAAA,MAAM,MAAA,GAAS;AAAA,MACb,IAAA,EAAM,MAAM,UAAA,IAAc,WAAA;AAAA,MAC1B,IAAA,EAAM,KAAA,CAAM,UAAA,IAAc,IAAA,CAAK,IAAA,CAAK;AAAA,KACtC;AACA,IAAA,MAAM,iBACJ,MAAA,CAAO,IAAA,KAAS,eAAe,MAAA,CAAO,IAAA,KAAS,KAAK,IAAA,CAAK,IAAA;AAE3D,IAAA,IAAI,OAAA;AACJ,IAAA,IAAI;AACF,MAAA,OAAA,GAAU,MAAM,SAAS,KAAA,CAAM;AAAA,QAC7B,MAAA;AAAA,QACA,SAAA,EAAW,KAAK,IAAA,CAAK,SAAA;AAAA,QACrB,OAAO,CAAA,IAAA,KAAQ;AACb,UAAA,IAAA,CAAK,IAAA,CAAK,QAAQ,IAAI,CAAA;AAAA,QACxB;AAAA,OACD,CAAA;AAAA,IACH,SAAS,GAAA,EAAK;AACZ,MAAA,IAAA,CAAK,SAAA,GAAY,aAAa,GAAG,CAAA;AACjC,MAAA,MAAM,GAAA;AAAA,IACR;AAMA,IAAA,IAAI,WAAA,GAA6B,IAAA;AACjC,IAAA,IAAI,eAAA,GAAkB,EAAA;AACtB,IAAA,IAAI,cAAA,EAAgB;AAClB,MAAA,WAAA,GAAcgB,WAAAA,CAAY,EAAE,CAAA,CAAE,QAAA,CAAS,WAAW,CAAA;AAClD,MAAA,eAAA,GAAkB,OAAO,WAAW,CAAA;AAAA,IACtC;AAEA,IAAA,MAAM,KAAA,GAAqB;AAAA,MACzB,QAAA,EAAU,UAAA;AAAA,MACV,WAAW,OAAA,CAAQ,SAAA;AAAA,MACnB,eAAA;AAAA,MACA,SAAA,EAAA,iBAAW,IAAI,IAAA,EAAK,EAAE,WAAA,EAAY;AAAA,MAClC,KAAK,OAAA,CAAQ,GAAA;AAAA,MACb,MAAA;AAAA,MACA;AAAA,KACF;AAEA,IAAA,IAAA,CAAK,KAAA,GAAQ,KAAA;AACb,IAAA,IAAA,CAAK,WAAA,GAAc,WAAA;AACnB,IAAA,IAAA,CAAK,QAAA,GAAW,QAAA;AAEhB,IAAA,MAAM,YAAA,CAAa,IAAA,CAAK,IAAA,CAAK,SAAA,EAAW,KAAK,CAAA;AAE7C,IAAA,MAAM,MAAA,GAAuB;AAAA,MAC3B,QAAA,EAAU,UAAA;AAAA,MACV,WAAW,OAAA,CAAQ,SAAA;AAAA,MACnB,MAAA;AAAA,MACA;AAAA,KACF;AACA,IAAA,IAAI,kBAAkB,WAAA,EAAa;AACjC,MAAA,MAAM,WAAA,GAAc,CAAA,EAAG,OAAA,CAAQ,SAAS,CAAA,IAAA,CAAA;AACxC,MAAA,MAAA,CAAO,WAAA,GAAc,WAAA;AACrB,MAAA,MAAA,CAAO,WAAA,GAAc,WAAA;AACrB,MAAA,MAAA,CAAO,gBAAA,GAAmB,qBAAA,CAAsB,WAAA,EAAa,WAAW,CAAA;AAAA,IAC1E;AACA,IAAA,OAAO,MAAA;AAAA,EACT;AAAA,EAEA,MAAM,OAAA,GAA0C;AAC9C,IAAA,IAAI,CAAC,IAAA,CAAK,KAAA,EAAO,OAAO,EAAE,UAAU,KAAA,EAAM;AAC1C,IAAA,MAAM,WAAW,IAAA,CAAK,QAAA;AACtB,IAAA,IAAA,CAAK,KAAA,GAAQ,IAAA;AACb,IAAA,IAAA,CAAK,WAAA,GAAc,IAAA;AACnB,IAAA,IAAA,CAAK,QAAA,GAAW,IAAA;AAChB,IAAA,IAAI,QAAA,EAAU;AACZ,MAAA,IAAI;AACF,QAAA,MAAM,SAAS,IAAA,EAAK;AAAA,MACtB,SAAS,GAAA,EAAK;AACZ,QAAA,IAAA,CAAK,SAAA,GAAY,aAAa,GAAG,CAAA;AAAA,MACnC;AAAA,IACF;AACA,IAAA,MAAM,UAAA,CAAW,IAAA,CAAK,IAAA,CAAK,SAAS,CAAA;AACpC,IAAA,OAAO,EAAE,UAAU,IAAA,EAAK;AAAA,EAC1B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,QAAA,GAA0B;AAC9B,IAAA,IAAI,KAAK,QAAA,EAAU;AACjB,MAAA,IAAI;AACF,QAAA,MAAM,IAAA,CAAK,SAAS,IAAA,EAAK;AAAA,MAC3B,CAAA,CAAA,MAAQ;AAAA,MAER;AAAA,IACF;AAAA,EACF;AACF,CAAA;AAIA,SAAS,aAAa,EAAA,EAA6B;AACjD,EAAA,IAAI,EAAA,KAAO,OAAA,EAAS,OAAO,mBAAA,EAAoB;AAG/C,EAAA,MAAM,WAAA,GAAqB,EAAA;AAC3B,EAAA,MAAM,IAAI,KAAA,CAAM,CAAA,yBAAA,EAA4B,MAAA,CAAO,WAAW,CAAC,CAAA,CAAE,CAAA;AACnE;AAEA,SAAS,OAAO,KAAA,EAAuB;AACrC,EAAA,OAAO,WAAW,QAAQ,CAAA,CAAE,OAAO,KAAK,CAAA,CAAE,OAAO,KAAK,CAAA;AACxD;AAEA,SAAS,aAAa,GAAA,EAAsB;AAC1C,EAAA,OAAO,GAAA,YAAe,KAAA,GAAQ,GAAA,CAAI,OAAA,GAAU,OAAO,GAAG,CAAA;AACxD;AAEA,eAAe,YAAA,CAAa,WAAmB,KAAA,EAAmC;AAChF,EAAA,MAAM,GAAA,GAAMrB,IAAAA,CAAK,SAAA,EAAW,aAAa,CAAA;AACzC,EAAA,MAAME,KAAAA,CAAM,GAAA,EAAK,EAAE,SAAA,EAAW,MAAM,CAAA;AACpC,EAAA,MAAM,IAAA,GAAOF,IAAAA,CAAK,GAAA,EAAK,aAAa,CAAA;AACpC,EAAA,MAAMI,SAAAA,CAAU,MAAM,IAAA,CAAK,SAAA,CAAU,OAAO,IAAA,EAAM,CAAC,CAAA,GAAI,IAAA,EAAM,MAAM,CAAA;AAGnE,EAAA,IAAI;AACF,IAAA,MAAM,KAAA,CAAM,MAAM,GAAK,CAAA;AAAA,EACzB,CAAA,CAAA,MAAQ;AAAA,EAER;AACF;AAEA,eAAe,WAAW,SAAA,EAAkC;AAC1D,EAAA,MAAM,IAAA,GAAOJ,IAAAA,CAAK,SAAA,EAAW,yBAAyB,CAAA;AACtD,EAAA,IAAI,CAACG,UAAAA,CAAW,IAAI,CAAA,EAAG;AACvB,EAAA,MAAMiB,EAAAA,CAAG,IAAA,EAAM,EAAE,KAAA,EAAO,MAAM,CAAA;AAChC;AAuBA,SAAS,qBAAA,CAAsB,UAAkB,KAAA,EAAuB;AACtE,EAAA,OAAO,IAAA,CAAK,SAAA;AAAA,IACV;AAAA,MACE,UAAA,EAAY;AAAA,QACV,mBAAA,EAAqB;AAAA,UACnB,SAAA,EAAW,MAAA;AAAA,UACX,GAAA,EAAK,QAAA;AAAA,UACL,OAAA,EAAS,EAAE,aAAA,EAAe,CAAA,OAAA,EAAU,KAAK,CAAA,CAAA;AAAG;AAC9C;AACF,KACF;AAAA,IACA,IAAA;AAAA,IACA;AAAA,GACF;AACF;ACvVA,SAASnB,MAAK,KAAA,EAEZ;AACA,EAAA,OAAO;AAAA,IACL,OAAA,EAAS;AAAA,MACP;AAAA,QACE,IAAA,EAAM,MAAA;AAAA,QACN,IAAA,EAAM,OAAO,KAAA,KAAU,QAAA,GAAW,QAAQ,IAAA,CAAK,SAAA,CAAU,KAAA,EAAO,IAAA,EAAM,CAAC;AAAA;AACzE;AACF,GACF;AACF;AAEO,SAAS,mBAAA,CACd,QACA,IAAA,EACM;AACN,EAAA,MAAM,EAAE,YAAW,GAAI,IAAA;AAEvB,EAAA,MAAA,CAAO,IAAA;AAAA,IACL,eAAA;AAAA,IACA,gjBAAA;AAAA,IAQA;AAAA,MACE,QAAA,EAAUQ,EACP,IAAA,CAAK,CAAC,OAAO,CAAC,CAAA,CACd,UAAS,CACT,QAAA;AAAA,QACC;AAAA,OACF;AAAA,MACF,UAAA,EAAYA,CAAAA,CACT,MAAA,EAAO,CACP,GAAA,EAAI,CACJ,GAAA,CAAI,CAAC,CAAA,CACL,GAAA,CAAI,KAAK,CAAA,CACT,UAAS,CACT,QAAA;AAAA,QACC;AAAA,OACF;AAAA,MACF,UAAA,EAAYA,CAAAA,CACT,MAAA,EAAO,CACP,UAAS,CACT,QAAA;AAAA,QACC;AAAA;AACF,KACJ;AAAA,IACA,OAAO,EAAE,QAAA,EAAU,UAAA,EAAY,YAAW,KAAM;AAC9C,MAAA,MAAM,MAAA,GAAS,MAAM,UAAA,CAAW,MAAA,CAAO,EAAE,QAAA,EAAU,UAAA,EAAY,YAAY,CAAA;AAC3E,MAAA,OAAOR,MAAK,MAAM,CAAA;AAAA,IACpB;AAAA,GACF;AAEA,EAAA,MAAA,CAAO,IAAA;AAAA,IACL,gBAAA;AAAA,IACA,+IAAA;AAAA,IAEA,EAAC;AAAA,IACD,YAAY;AACV,MAAA,MAAM,MAAA,GAAS,MAAM,UAAA,CAAW,OAAA,EAAQ;AACxC,MAAA,OAAOA,MAAK,MAAM,CAAA;AAAA,IACpB;AAAA,GACF;AAEA,EAAA,MAAA,CAAO,IAAA;AAAA,IACL,eAAA;AAAA,IACA,iMAAA;AAAA,IAGA,EAAC;AAAA,IACD,YAAY;AACV,MAAA,OAAOA,KAAAA,CAAK,UAAA,CAAW,MAAA,EAAQ,CAAA;AAAA,IACjC;AAAA,GACF;AACF;AChFO,IAAM,kBAAA,GAAN,cAAiC,KAAA,CAAM;AAAA,EAC5C,YAAY,OAAA,EAAiB;AAC3B,IAAA,KAAA,CAAM,OAAO,CAAA;AACb,IAAA,IAAA,CAAK,IAAA,GAAO,oBAAA;AAAA,EACd;AACF,CAAA;AAEO,SAAS,kBAAkB,IAAA,EAA6C;AAC7E,EAAA,MAAM,IAAA,GAAOI,OAAAA,CAAQ,IAAA,CAAK,SAAS,CAAA;AAEnC,EAAA,SAASQ,aAAY,IAAA,EAAsB;AACzC,IAAA,IAAI,OAAO,IAAA,KAAS,QAAA,IAAY,IAAA,CAAK,WAAW,CAAA,EAAG;AACjD,MAAA,MAAM,IAAI,mBAAmB,iCAAiC,CAAA;AAAA,IAChE;AACA,IAAA,IAAIP,UAAAA,CAAW,IAAI,CAAA,EAAG;AACpB,MAAA,MAAM,IAAI,kBAAA;AAAA,QACR;AAAA,OACF;AAAA,IACF;AACA,IAAA,MAAM,MAAA,GAASC,SAAAA,CAAUP,IAAAA,CAAK,IAAA,EAAM,IAAI,CAAC,CAAA;AACzC,IAAA,MAAM,GAAA,GAAMQ,QAAAA,CAAS,IAAA,EAAM,MAAM,CAAA;AACjC,IAAA,IAAI,IAAI,UAAA,CAAW,IAAI,CAAA,IAAKF,UAAAA,CAAW,GAAG,CAAA,EAAG;AAC3C,MAAA,MAAM,IAAI,kBAAA;AAAA,QACR,gCAAgC,IAAI,CAAA,CAAA;AAAA,OACtC;AAAA,IACF;AACA,IAAA,OAAO,MAAA;AAAA,EACT;AAEA,EAAA,OAAO;AAAA,IACL,MAAM,SAAS,IAAA,EAAM;AACnB,MAAA,MAAM,GAAA,GAAMO,aAAY,IAAI,CAAA;AAC5B,MAAA,MAAM,GAAA,GAAM,MAAMS,QAAA,CAAW,GAAG,CAAA;AAChC,MAAA,OAAO,GAAA,CAAI,SAAS,MAAM,CAAA;AAAA,IAC5B,CAAA;AAAA,IACA,MAAM,SAAA,CAAU,IAAA,EAAM,OAAA,EAAS;AAC7B,MAAA,MAAM,GAAA,GAAMT,aAAY,IAAI,CAAA;AAC5B,MAAA,MAAMX,MAAMY,OAAAA,CAAQ,GAAG,GAAG,EAAE,SAAA,EAAW,MAAM,CAAA;AAC7C,MAAA,MAAMS,SAAA,CAAY,KAAK,OAAO,CAAA;AAAA,IAChC,CAAA;AAAA,IACA,MAAM,OAAO,IAAA,EAAM;AACjB,MAAA,IAAI;AACF,QAAA,MAAM,GAAA,GAAMV,aAAY,IAAI,CAAA;AAC5B,QAAA,OAAOV,WAAW,GAAG,CAAA;AAAA,MACvB,CAAA,CAAA,MAAQ;AACN,QAAA,OAAO,KAAA;AAAA,MACT;AAAA,IACF;AAAA,GACF;AACF;;;AC8FA,eAAsB,cACpB,IAAA,EACwB;AACxB,EAAA,MAAM,SAAA,GAAYE,OAAAA,CAAQ,IAAA,CAAK,SAAS,CAAA;AACxC,EAAA,IAAI,CAACF,UAAAA,CAAW,SAAS,CAAA,EAAG;AAC1B,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,uCAAA,EAA0C,SAAS,CAAA,CAAE,CAAA;AAAA,EACvE;AACA,EAAA,MAAM,IAAA,GAAO,KAAK,IAAA,IAAQ,KAAA;AAE1B,EAAA,MAAM,SAAS,mBAAA,EAAoB;AACnC,EAAA,MAAM,aAAA,GAAgB,qBAAA,CAAsB,EAAE,SAAA,EAAW,CAAA;AACzD,EAAA,MAAM,WAAA,GAAc,iBAAA,CAAkB,EAAE,SAAA,EAAW,CAAA;AAMnD,EAAA,MAAM,MAAA,GAAS,IAAI,gBAAA,CAAiB;AAAA,IAClC,SAAA;AAAA,IACA,IAAA;AAAA,IACA,KAAA,EAAO,CAAA,IAAA,KACL,MAAA,CAAO,IAAA,CAAK;AAAA,MACV,IAAA,EAAM,YAAA;AAAA,MACN,EAAA,EAAA,iBAAI,IAAI,IAAA,EAAK,EAAE,WAAA,EAAY;AAAA,MAC3B;AAAA,KACD;AAAA,GACJ,CAAA;AAOD,EAAA,MAAM,EAAE,UAAA,EAAW,GAAI,MAAM,eAAA,CAAgB;AAAA,IAC3C,OAAO,IAAA,CAAK,KAAA;AAAA,IACZ,SAAA;AAAA,IACA,IAAA,EAAM,KAAK,IAAA,IAAQ,oBAAA;AAAA,IACnB,OAAA,EAAS,KAAK,OAAA,IAAW;AAAA,GAC1B,CAAA;AAOD,EAAA,MAAM,WAAW,sBAAA,CAAuB;AAAA,IACtC,GAAI,KAAK,QAAA,GAAW,EAAE,UAAU,IAAA,CAAK,QAAA,KAAa,EAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAQnD,GAAI,KAAK,mBAAA,GACL;AAAA,MACE,aAAa,OAAO,EAAE,WAAA,EAAa,GAAA,EAAK,iBAAgB,KAAM;AAC5D,QAAA,MAAM,OAAA,GAAU,MAAM,IAAA,CAAK,mBAAA,CAAqB,WAAW,CAAA;AAC3D,QAAA,IAAI,CAAC,SAAS,OAAO,IAAA;AACrB,QAAA,IAAI;AACF,UAAA,OAAO,MAAM,OAAA,CAAQ,YAAA,CAAa,EAAE,GAAA,EAAK,iBAAiB,CAAA;AAAA,QAC5D,SAAS,GAAA,EAAK;AACZ,UAAA,OAAA,CAAQ,IAAA;AAAA,YACN,CAAA,0BAAA,EAA6B,WAAW,CAAA,GAAA,EAAM,eAAe,CAAA,UAAA,EAC3D,GAAA,YAAe,KAAA,GAAQ,GAAA,CAAI,OAAA,GAAU,MAAA,CAAO,GAAG,CACjD,CAAA;AAAA,WACF;AACA,UAAA,OAAO,IAAA;AAAA,QACT;AAAA,MACF;AAAA,QAEF;AAAC,GACN,CAAA;AAMD,EAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,KAAA,IAASqB,UAAAA,EAAW;AAMvC,EAAA,MAAM,QAAA,GAAW,IAAI,gBAAA,EAAiB;AAEtC,EAAA,MAAM,mBAAmB,YAAY;AACnC,IAAA,MAAM,EAAE,MAAA,EAAO,GAAI,MAAM,eAAA,CAAgB;AAAA,MACvC,OAAO,IAAA,CAAK,KAAA;AAAA,MACZ,SAAA;AAAA,MACA,IAAA,EAAM,KAAK,IAAA,IAAQ,oBAAA;AAAA,MACnB,OAAA,EAAS,KAAK,OAAA,IAAW;AAAA,KAC1B,CAAA;AAKD,IAAA,eAAA,CAAgB,MAAA,EAAQ,EAAE,SAAA,EAAW,CAAA;AAKrC,IAAA,oBAAA,CAAqB,MAAA,EAAQ,EAAE,SAAA,EAAW,CAAA;AAI1C,IAAA,mBAAA,CAAoB,MAAA,EAAQ,EAAE,UAAA,EAAY,MAAA,EAAQ,CAAA;AAMlD,IAAA,oBAAA,CAAqB,MAAA,EAAQ;AAAA,MAC3B,QAAA,EAAU,QAAA;AAAA,MACV,QAAA;AAAA,MACA,UAAA,EAAY,KAAK,QAAA,IAAY,IAAA;AAAA,MAC7B,GAAI,KAAK,mBAAA,GACL,EAAE,qBAAqB,IAAA,CAAK,mBAAA,KAC5B,EAAC;AAAA,MACL,GAAI,KAAK,iBAAA,GACL,EAAE,mBAAmB,IAAA,CAAK,iBAAA,KAC1B;AAAC,KACN,CAAA;AACD,IAAA,OAAO,MAAA;AAAA,EACT,CAAA;AAGA,EAAA,IAAI,IAAA,CAAK,SAAS,KAAA,EAAO;AACvB,IAAA,MAAM,OAAA,CAAQ,WAAW,IAAA,EAAM,aAAA,EAAe,MAAM,CAAA,CAAE,KAAA,CAAM,CAAC,GAAA,KAAQ;AACnE,MAAA,MAAA,CAAO,IAAA,CAAK;AAAA,QACV,IAAA,EAAM,iBAAA;AAAA,QACN,EAAA,EAAA,iBAAI,IAAI,IAAA,EAAK,EAAE,WAAA,EAAY;AAAA,QAC3B,OAAO,IAAA,CAAK,gBAAA;AAAA,QACZ,KAAA,EAAO,mBAAmB,GAAA,YAAe,KAAA,GAAQ,IAAI,OAAA,GAAU,MAAA,CAAO,GAAG,CAAC,CAAA;AAAA,OAC3E,CAAA;AAAA,IACH,CAAC,CAAA;AAAA,EACH;AAEA,EAAA,MAAM,YAAY,cAAA,CAAe;AAAA,IAC/B,SAAA;AAAA,IACA,aAAA;AAAA,IACA,MAAA;AAAA,IACA,UAAA,EAAY,KAAK,UAAA,IAAc;AAAA,GAChC,CAAA;AAED,EAAA,MAAM,IAAA,GAAO,MAAM,eAAA,CAAgB;AAAA,IACjC,IAAA;AAAA,IACA,MAAM,IAAA,CAAK,IAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAOX,MAAM,MAAM;AACV,MAAA,MAAM,UAAA,GAAa,OAAO,QAAA,EAAS;AACnC,MAAA,IAAI,UAAA,CAAW,IAAA,KAAS,QAAA,EAAU,OAAO,UAAA;AACzC,MAAA,OAAO,IAAA,CAAK,IAAA,IAAQ,EAAE,IAAA,EAAM,MAAA,EAAO;AAAA,IACrC,CAAA;AAAA,IACA,gBAAA;AAAA,IACA,aAAA;AAAA,IACA,MAAA;AAAA,IACA,SAAA;AAAA,IACA,QAAA;AAAA,IACA,QAAA;AAAA,IACA,KAAA;AAAA,IACA,UAAA,EAAY,KAAK,QAAA,IAAY,IAAA;AAAA,IAC7B,GAAI,KAAK,cAAA,GAAiB,EAAE,gBAAgB,IAAA,CAAK,cAAA,KAAmB,EAAC;AAAA,IACrE,GAAI,IAAA,CAAK,aAAA,GAAgB,EAAE,aAAA,EAAe,IAAA,KAAS,EAAC;AAAA,IACpD,GAAI,KAAK,mBAAA,GACL,EAAE,qBAAqB,IAAA,CAAK,mBAAA,KAC5B,EAAC;AAAA,IACL,GAAI,KAAK,iBAAA,GACL,EAAE,mBAAmB,IAAA,CAAK,iBAAA,KAC1B,EAAC;AAAA,IACL,IAAA,EAAM,EAAE,SAAA,EAAW,UAAA;AAAW,GAC/B,CAAA;AAED,EAAA,SAAA,CAAU,KAAA,EAAM;AAChB,EAAA,MAAA,CAAO,IAAA,CAAK;AAAA,IACV,IAAA,EAAM,MAAA;AAAA,IACN,EAAA,EAAA,iBAAI,IAAI,IAAA,EAAK,EAAE,WAAA,EAAY;AAAA,IAC3B,SAAA;AAAA,IACA;AAAA,GACD,CAAA;AAMD,EAAA,KAAK,iBAAiB,SAAA,EAAW;AAAA,IAC/B,SAAA;AAAA,IACA,IAAA;AAAA,IACA,IAAA,EAAM,KAAK,IAAA,IAAQ,WAAA;AAAA,IACnB,KAAK,OAAA,CAAQ,GAAA;AAAA,IACb,SAAA,EAAA,iBAAW,IAAI,IAAA,EAAK,EAAE,WAAA,EAAY;AAAA,IAClC,IAAA,EAAM,KAAK,IAAA,IAAQ,oBAAA;AAAA,IACnB,UAAA;AAAA,IACA;AAAA,GACD,CAAA;AAED,EAAA,OAAO;AAAA,IACL,KAAK,IAAA,CAAK,GAAA;AAAA,IACV,SAAA;AAAA,IACA,WAAA;AAAA,IACA,UAAA;AAAA,IACA,QAAA;AAAA,IACA,KAAA;AAAA,IACA,MAAM,IAAA,GAAO;AACX,MAAA,SAAA,CAAU,IAAA,EAAK;AAIf,MAAA,QAAA,CAAS,QAAA,EAAS;AAGlB,MAAA,MAAM,SAAS,QAAA,EAAS;AAIxB,MAAA,MAAM,OAAO,QAAA,EAAS;AACtB,MAAA,MAAM,KAAK,IAAA,EAAK;AAAA,IAClB;AAAA,GACF;AACF;AAIA,IAAM,iBAAsC,YAAY,IAAA;AAExD,eAAe,OAAA,CACb,SAAA,EACA,IAAA,EACA,aAAA,EACA,MAAA,EACe;AACf,EAAA,MAAM,IAAA,GAAOxB,IAAAA,CAAK,SAAA,EAAW,SAAS,CAAA;AACtC,EAAA,IAAI,CAACG,UAAAA,CAAW,IAAI,CAAA,EAAG;AACvB,EAAA,MAAM,QAAQ,MAAMJ,QAAAA,CAAS,IAAA,EAAM,MAAM,GAAG,IAAA,EAAK;AACjD,EAAA,IAAI,CAAC,IAAA,EAAM;AACX,EAAA,IAAI,CAAC,IAAA,CAAK,UAAA,IAAc,CAAC,KAAK,gBAAA,EAAkB;AAEhD,EAAA,MAAM,KAAA,GAAQ,MAAM,IAAA,CAAK,UAAA,CAAW,KAAK,gBAAgB,CAAA;AACzD,EAAA,IAAI,CAAC,KAAA,EAAO;AAEZ,EAAA,MAAM,cAAA,GAAiB,CAAA,KAAA,EAAA,iBAAQ,IAAI,IAAA,IAAO,WAAA,EAAY,CAAE,KAAA,CAAM,CAAA,EAAG,EAAE,CAAA,CAAE,OAAA,CAAQ,OAAA,EAAS,GAAG,CAAC,CAAA,CAAA;AAC1F,EAAA,MAAM,cAAc,IAAA,CAAK,cAAA,EAAgB,EAAE,KAAA,EAAO,IAAA,CAAK,kBAAkB,CAAA;AACzE,EAAA,MAAM,aAAA,CAAc,UAAA,CAAW,cAAA,EAAgB,MAAA,EAAQ,IAAA,EAAM;AAAA,IAC3D,WAAA,EAAa;AAAA,GACd,CAAA;AACD,EAAA,MAAM,KAAA,GAAQ,MAAM,KAAA,CAAM,QAAA,CAAS,IAAI,CAAA;AACvC,EAAA,MAAM,aAAA,CAAc,UAAA,CAAW,cAAA,EAAgB,WAAA,EAAa,MAAM,IAAA,EAAM;AAAA,IACtE,aAAa,IAAA,CAAK;AAAA,GACnB,CAAA;AACD,EAAA,MAAA,CAAO,IAAA,CAAK;AAAA,IACV,IAAA,EAAM,iBAAA;AAAA,IACN,EAAA,EAAA,iBAAI,IAAI,IAAA,EAAK,EAAE,WAAA,EAAY;AAAA,IAC3B,OAAO,IAAA,CAAK,gBAAA;AAAA,IACZ,cAAA;AAAA,IACA,MAAA,EAAQ,IAAA;AAAA,IACR,OAAO,KAAA,CAAM,IAAA;AAAA,IACb,UAAA,EAAY;AAAA,GACb,CAAA;AACH","file":"index.mjs","sourcesContent":["/**\n * `.agentproto/` config dir — runtime-managed state at the root of\n * every workspace. Mirrors the `.git/` model: user-content stays at\n * the workspace root (HEARTBEAT.md, conversations/, .agents/) while\n * everything the runtime owns lives in `<workspace>/.agentproto/`.\n *\n * What goes here today:\n * - `runtime.json` — boot-time snapshot of the live config (PID,\n * port, resolved workspace, MCP server name, startedAt). Useful\n * for `cat .agentproto/runtime.json` diagnostics + future tooling\n * that wants to discover a running gateway from disk.\n *\n * What does NOT go here:\n * - HEARTBEAT.md — user-edited content\n * - conversations/ — user-readable chat history\n * - .agents/ — user-authored manifests\n *\n * The `.agentproto/` dir is safe to gitignore. The `runtime.json`\n * file contains a per-boot bearer token used to gate mutating HTTP\n * routes (POST /sessions/*, WS /sessions/:id/pty). The token lives\n * in RAM + on disk only — never logged. File mode 0600 below; only\n * processes running as the workspace user (and the daemon itself)\n * can read it. A browser-loaded localhost page CAN'T read this file,\n * which is what defends against the localhost-DNS-rebinding drive-by\n * spawn vector.\n */\n\nimport { mkdir, readFile, stat, unlink, writeFile } from \"node:fs/promises\"\nimport { join } from \"node:path\"\n\nexport interface RuntimeMeta {\n /** Absolute path to the workspace root the gateway is bound to. */\n workspace: string\n /** HTTP listener port. */\n port: number\n /** HTTP bind address (loopback or `0.0.0.0`). */\n bind: string\n /** Process id of the running gateway. */\n pid: number\n /** Wall-clock ISO timestamp at boot. */\n startedAt: string\n /** MCP server name advertised in the initialize handshake. */\n name: string\n /** AIP doctype names + extensions registered as MCP CRUD tools. */\n registered: readonly string[]\n /**\n * Per-boot bearer token. Required on mutating routes (POST\n * /sessions/*, POST /sessions/:id/kill, DELETE /sessions/:id, and\n * WS upgrade to /sessions/:id/pty). Random uuid generated at boot\n * by createGateway; regenerated each restart.\n */\n token: string\n}\n\n/**\n * Create `<workspace>/.agentproto/` (idempotent) and write the\n * `runtime.json` snapshot. Errors are logged but non-fatal — losing\n * the meta file shouldn't crash the gateway, the runtime is still\n * fully functional without it.\n */\nexport async function writeRuntimeMeta(\n workspace: string,\n meta: RuntimeMeta,\n): Promise<void> {\n const dir = join(workspace, \".agentproto\")\n try {\n await mkdir(dir, { recursive: true })\n // mode 0600 so other local users can't read the bearer token.\n await writeFile(\n join(dir, \"runtime.json\"),\n JSON.stringify(meta, null, 2) + \"\\n\",\n { encoding: \"utf8\", mode: 0o600 },\n )\n } catch (err) {\n console.error(\"[runtime] failed to write .agentproto/runtime.json:\", err)\n }\n}\n\n/**\n * Delete `<workspace>/.agentproto/runtime.json`. Best-effort — called\n * from the daemon's graceful shutdown path so a CLI looking for the\n * live daemon doesn't pick up a stale token after this process exits.\n * Missing file is a no-op (the daemon may never have written one).\n */\nexport async function unlinkRuntimeMeta(workspace: string): Promise<void> {\n try {\n await unlink(join(workspace, \".agentproto\", \"runtime.json\"))\n } catch {\n // ENOENT / permission — not worth surfacing on shutdown.\n }\n}\n\n/**\n * Read a runtime.json from `<workspace>/.agentproto/`. Returns the\n * parsed object (no validation) plus the on-disk mtime, or null when\n * the file is missing / unreadable / malformed.\n */\nexport async function readRuntimeMeta(workspace: string): Promise<{\n meta: Partial<RuntimeMeta> & Record<string, unknown>\n mtime: Date\n} | null> {\n const path = join(workspace, \".agentproto\", \"runtime.json\")\n try {\n const [raw, st] = await Promise.all([readFile(path, \"utf8\"), stat(path)])\n const meta = JSON.parse(raw) as Record<string, unknown>\n return { meta, mtime: st.mtime }\n } catch {\n return null\n }\n}\n\n/**\n * For each `workspace` path, check whether its runtime.json points\n * at a now-dead PID; if so, delete it. Returns the list of paths\n * that were cleaned. Called by `agentproto serve` at boot to keep\n * the discovery layer's view of \"live daemons\" honest — a stale\n * file with the same port as the new daemon is the classic source\n * of `sessions_unauthorized` 401s.\n *\n * Skips the running daemon's own workspace (passed in as\n * `currentWorkspace`) since that file is OURS to write.\n */\nexport async function sweepStaleRuntimeMetas(\n workspaces: readonly string[],\n currentWorkspace: string,\n): Promise<string[]> {\n const cleaned: string[] = []\n for (const ws of workspaces) {\n if (ws === currentWorkspace) continue\n const meta = await readRuntimeMeta(ws)\n if (!meta) continue\n const pid = meta.meta.pid\n if (typeof pid === \"number\" && !isPidAlive(pid)) {\n try {\n await unlink(join(ws, \".agentproto\", \"runtime.json\"))\n cleaned.push(join(ws, \".agentproto\", \"runtime.json\"))\n } catch {\n // ignore — best-effort\n }\n }\n }\n return cleaned\n}\n\nfunction isPidAlive(pid: number): boolean {\n try {\n process.kill(pid, 0)\n return true\n } catch (err) {\n const code = (err as NodeJS.ErrnoException).code\n if (code === \"EPERM\") return true // exists, foreign user\n return false\n }\n}\n","/**\n * Shell-execution MCP tools for the runtime.\n *\n * The runtime is a remote shell as far as cloud agents are concerned —\n * the workspace lives on the user's machine, so the only place a\n * `claude -p`, `gh pr view`, `pnpm test` etc. can actually run *is*\n * the user's machine. This module exposes one MCP tool,\n * `execute_command`, that any MCP client (cloud Guilde Blake,\n * Claude Code as a sub-agent, …) can call to spawn a subprocess.\n *\n * ## Allowlist\n *\n * Default-deny. The runtime reads\n * `<workspace>/.agentproto/allowed-commands.json` on every call (cheap\n * stat; cached for 1s) for the list of allowed command basenames.\n * Missing / empty file ⇒ no commands run. The error message points the\n * user at the file path so they know exactly where to opt in.\n *\n * Allowlist file shape:\n * { \"version\": 1, \"commands\": [\"claude\", \"gh\", \"pnpm\", \"node\"] }\n *\n * Match is by command BASENAME (`/usr/local/bin/claude` → `claude`)\n * to keep the allowlist short and not break when users have multiple\n * binaries on their PATH.\n *\n * ## Safety notes\n *\n * - We use `spawn()` with `shell: false` so arguments are passed\n * verbatim — no shell interpolation surprises.\n * - `cwd` is anchored to the workspace root via the same path-escape\n * guard used by `fs-tools.ts`. Callers can't run a subprocess in\n * `/etc` unless they also bind-mounted it inside the workspace.\n * - Every spawn has a `timeoutMs` cap (default 60s, max 600s). Hung\n * subprocesses can't pin the runtime forever.\n */\n\nimport { spawn } from \"node:child_process\"\nimport { existsSync } from \"node:fs\"\nimport { readFile, stat } from \"node:fs/promises\"\nimport {\n basename,\n isAbsolute,\n join,\n normalize,\n relative,\n resolve,\n} from \"node:path\"\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\"\nimport { z } from \"zod\"\n\nconst DEFAULT_TIMEOUT_MS = 60_000\nconst MAX_TIMEOUT_MS = 600_000\nconst ALLOWLIST_REL = \".agentproto/allowed-commands.json\"\n\nexport interface RegisterCommandToolsOptions {\n workspace: string\n}\n\ninterface AllowlistFile {\n version?: number\n commands?: string[]\n}\n\ninterface AllowlistCacheEntry {\n mtimeMs: number\n commands: Set<string>\n}\n\nlet allowlistCache: { path: string; entry: AllowlistCacheEntry } | null = null\n\nasync function loadAllowlist(workspace: string): Promise<Set<string>> {\n const path = resolve(workspace, ALLOWLIST_REL)\n if (!existsSync(path)) {\n allowlistCache = null\n return new Set()\n }\n try {\n const s = await stat(path)\n if (\n allowlistCache &&\n allowlistCache.path === path &&\n allowlistCache.entry.mtimeMs === s.mtimeMs\n ) {\n return allowlistCache.entry.commands\n }\n const raw = await readFile(path, \"utf8\")\n const parsed = JSON.parse(raw) as AllowlistFile\n const list = Array.isArray(parsed.commands) ? parsed.commands : []\n const commands = new Set(\n list\n .filter((x): x is string => typeof x === \"string\" && x.length > 0)\n .map(x => x.trim()),\n )\n allowlistCache = { path, entry: { mtimeMs: s.mtimeMs, commands } }\n return commands\n } catch (err) {\n // Bad JSON / unreadable file ⇒ deny all and surface in the error\n // the next caller gets. Don't poison the cache.\n console.error(\n `[runtime] failed to load ${ALLOWLIST_REL} (will deny all):`,\n err,\n )\n allowlistCache = null\n return new Set()\n }\n}\n\nfunction makeCwdAnchor(workspace: string): (input: string | undefined) => string {\n const root = resolve(workspace)\n return (input?: string) => {\n if (!input || input.length === 0) return root\n const candidate = isAbsolute(input)\n ? normalize(input)\n : normalize(join(root, input))\n const rel = relative(root, candidate)\n if (rel.startsWith(\"..\") || isAbsolute(rel)) {\n throw new Error(\n `cwd escapes the workspace: '${input}' (workspace=${root})`,\n )\n }\n return candidate\n }\n}\n\nexport interface ExecuteResult {\n exitCode: number\n signal: string | null\n stdout: string\n stderr: string\n truncated?: boolean\n durationMs: number\n}\n\n/**\n * Register `execute_command` on the given MCP server. The tool returns\n * a JSON-encoded `ExecuteResult` as a single text content item — that\n * matches the response shape `@modelcontextprotocol/server-filesystem`\n * uses for `read_file` and friends, so the existing\n * `parseReadFileResponse`-style parsers in workspace-providers can\n * decode it without bespoke logic.\n */\nexport function registerCommandTools(\n server: McpServer,\n opts: RegisterCommandToolsOptions,\n): void {\n const anchorCwd = makeCwdAnchor(opts.workspace)\n\n server.tool(\n \"execute_command\",\n \"Run a shell command on the host running the runtime. The command basename must be in `<workspace>/.agentproto/allowed-commands.json`; default-deny otherwise. Captures stdout / stderr / exit code and returns them as JSON. Use this to drive local CLIs (Claude Code, gh, pnpm, …) from a remote agent.\",\n {\n command: z\n .string()\n .min(1)\n .describe(\n \"Executable name or absolute path. Must be allowlisted by basename in the workspace's allowed-commands.json.\",\n ),\n args: z\n .array(z.string())\n .optional()\n .describe(\n \"Argv array. Passed verbatim — no shell expansion (we spawn with shell:false so quoting doesn't bite).\",\n ),\n cwd: z\n .string()\n .optional()\n .describe(\n \"Working directory, workspace-relative or an absolute path inside the workspace. Defaults to the workspace root.\",\n ),\n stdin: z\n .string()\n .optional()\n .describe(\"Optional input piped to the process's stdin.\"),\n timeoutMs: z\n .number()\n .int()\n .positive()\n .max(MAX_TIMEOUT_MS)\n .optional()\n .describe(\n `Hard kill after this many ms. Defaults to ${DEFAULT_TIMEOUT_MS}; capped at ${MAX_TIMEOUT_MS}.`,\n ),\n },\n async ({ command, args, cwd, stdin, timeoutMs }) => {\n const allowlist = await loadAllowlist(opts.workspace)\n const baseName = basename(command)\n if (!allowlist.has(baseName)) {\n const allowed = [...allowlist].sort().join(\", \") || \"(empty)\"\n throw new Error(\n `command '${baseName}' is not in the allowlist. ` +\n `Add it to ${join(opts.workspace, ALLOWLIST_REL)} ` +\n `under \"commands\": [...]. Currently allowed: ${allowed}.`,\n )\n }\n const resolvedCwd = anchorCwd(cwd)\n const limit = Math.min(timeoutMs ?? DEFAULT_TIMEOUT_MS, MAX_TIMEOUT_MS)\n const result = await runCommand({\n command,\n args: args ?? [],\n cwd: resolvedCwd,\n stdin,\n timeoutMs: limit,\n })\n return {\n content: [{ type: \"text\" as const, text: JSON.stringify(result) }],\n }\n },\n )\n}\n\ninterface RunCommandInput {\n command: string\n args: string[]\n cwd: string\n stdin?: string\n timeoutMs: number\n}\n\nconst STREAM_BUFFER_CAP = 1_048_576 // 1 MiB per stream\n\nasync function runCommand(input: RunCommandInput): Promise<ExecuteResult> {\n return new Promise<ExecuteResult>(resolvePromise => {\n const startedAt = Date.now()\n const child = spawn(input.command, input.args, {\n cwd: input.cwd,\n shell: false,\n // Inherit user env so PATH lookups for `claude`, `gh`, etc. work.\n env: process.env,\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n })\n\n let stdout = \"\"\n let stderr = \"\"\n let truncated = false\n let timedOut = false\n\n function appendCapped(buf: string, chunk: Buffer): string {\n if (buf.length >= STREAM_BUFFER_CAP) {\n truncated = true\n return buf\n }\n const room = STREAM_BUFFER_CAP - buf.length\n const text = chunk.toString(\"utf8\")\n if (text.length > room) {\n truncated = true\n return buf + text.slice(0, room)\n }\n return buf + text\n }\n child.stdout?.on(\"data\", d => {\n stdout = appendCapped(stdout, d)\n })\n child.stderr?.on(\"data\", d => {\n stderr = appendCapped(stderr, d)\n })\n\n if (input.stdin) {\n child.stdin?.write(input.stdin)\n }\n child.stdin?.end()\n\n const timer = setTimeout(() => {\n timedOut = true\n // SIGTERM first; the close handler resolves either way. Ignore\n // EPERM if the child is already gone.\n try {\n child.kill(\"SIGTERM\")\n } catch {\n /* noop */\n }\n // Hard kill 2s later if it hasn't exited.\n setTimeout(() => {\n try {\n child.kill(\"SIGKILL\")\n } catch {\n /* noop */\n }\n }, 2_000).unref()\n }, input.timeoutMs)\n timer.unref()\n\n child.on(\"error\", err => {\n clearTimeout(timer)\n // spawn errors (ENOENT, EACCES) become exitCode -1 with the\n // message in stderr — the JSON shape stays consistent.\n resolvePromise({\n exitCode: -1,\n signal: null,\n stdout,\n stderr: stderr + (stderr ? \"\\n\" : \"\") + (err as Error).message,\n truncated,\n durationMs: Date.now() - startedAt,\n })\n })\n child.on(\"close\", (code, signal) => {\n clearTimeout(timer)\n resolvePromise({\n exitCode: typeof code === \"number\" ? code : -1,\n signal: signal ?? (timedOut ? \"SIGTERM-timeout\" : null),\n stdout,\n stderr,\n truncated,\n durationMs: Date.now() - startedAt,\n })\n })\n })\n}\n","/**\n * Append-only conversation persistence as plain markdown.\n *\n * Each conversation is a file at `<workspace>/conversations/<id>.md`\n * with a frontmatter header (`schema: conversation/v1`, `id`, `agent`,\n * `started`, `status`) and a body composed of `## <role> — <iso>`\n * blocks. Append-only: turns are concatenated to the body, never\n * rewritten in place. Readers tolerant to clock skew use the timestamp\n * in each block, not file mtime.\n *\n * The format is intentionally trivial — git-diffable, human-editable,\n * survives `cat`. Designed to converge with the AIP runtime/v1 spec\n * (TBD) once it lands.\n */\n\nimport { existsSync } from \"node:fs\"\nimport { mkdir, readFile, readdir, writeFile } from \"node:fs/promises\"\nimport { join } from \"node:path\"\n\nconst FRONTMATTER_RE = /^---\\n([\\s\\S]*?)\\n---\\n/\n\nexport type ConvRole = \"user\" | \"assistant\" | \"system\"\n\nexport interface ConversationMeta {\n id: string\n agent: string\n started: string\n status: \"open\" | \"closed\"\n}\n\nexport interface ConversationTurn {\n role: ConvRole\n at: string\n /** Optional sub-attribution after the role (e.g. agent id). */\n attribution?: string\n content: string\n}\n\nexport interface ConversationStore {\n /**\n * Open a conversation. If the file doesn't exist, it's created with\n * a frontmatter header. If it exists, no-op (idempotent).\n */\n open(id: string, meta: { agent: string }): Promise<void>\n appendTurn(\n id: string,\n role: ConvRole,\n content: string,\n opts?: { attribution?: string; at?: string },\n ): Promise<void>\n read(\n id: string,\n ): Promise<{ meta: ConversationMeta; turns: ConversationTurn[] }>\n list(): Promise<Array<{ id: string; meta: ConversationMeta }>>\n /** Workspace-relative path to the conv file, for tooling. */\n pathFor(id: string): string\n}\n\nexport interface FileConversationStoreOptions {\n /** Absolute workspace root. */\n workspace: string\n /** Override `<workspace>/conversations`. */\n dir?: string\n}\n\nexport function fileConversationStore(\n opts: FileConversationStoreOptions,\n): ConversationStore {\n const dir = opts.dir ?? join(opts.workspace, \"conversations\")\n\n const filePath = (id: string) => join(dir, `${id}.md`)\n\n return {\n pathFor: filePath,\n\n async open(id, meta) {\n await mkdir(dir, { recursive: true })\n const path = filePath(id)\n if (existsSync(path)) return\n const header = renderHeader({\n id,\n agent: meta.agent,\n started: new Date().toISOString(),\n status: \"open\",\n })\n await writeFile(path, header, \"utf8\")\n },\n\n async appendTurn(id, role, content, options) {\n const path = filePath(id)\n // Lazy-open: if a caller appends without opening, create the\n // file so the operation never silently drops a turn.\n if (!existsSync(path)) {\n await this.open(id, { agent: options?.attribution ?? \"unknown\" })\n }\n const block = renderTurn({\n role,\n at: options?.at ?? new Date().toISOString(),\n attribution: options?.attribution,\n content,\n })\n // Append a leading blank line so the new block is always\n // separated from whatever's above (header or prev turn).\n await writeFile(path, block, { encoding: \"utf8\", flag: \"a\" })\n },\n\n async read(id) {\n const path = filePath(id)\n const source = await readFile(path, \"utf8\")\n return parseConversation(source, id)\n },\n\n async list() {\n if (!existsSync(dir)) return []\n const entries = await readdir(dir, { withFileTypes: true })\n const out: Array<{ id: string; meta: ConversationMeta }> = []\n for (const entry of entries) {\n if (!entry.isFile() || !entry.name.endsWith(\".md\")) continue\n const id = entry.name.slice(0, -3)\n try {\n const source = await readFile(join(dir, entry.name), \"utf8\")\n const { meta } = parseConversation(source, id)\n out.push({ id, meta })\n } catch {\n // Skip malformed conv files rather than crash list().\n }\n }\n return out\n },\n }\n}\n\n// ── render ───────────────────────────────────────────────────────────\n\nfunction renderHeader(meta: ConversationMeta): string {\n return [\n \"---\",\n `schema: conversation/v1`,\n `id: ${meta.id}`,\n `agent: ${meta.agent}`,\n `started: ${meta.started}`,\n `status: ${meta.status}`,\n \"---\",\n \"\",\n \"\",\n ].join(\"\\n\")\n}\n\nfunction renderTurn(turn: ConversationTurn): string {\n const heading = turn.attribution\n ? `## ${turn.role} — ${turn.at} (${turn.attribution})`\n : `## ${turn.role} — ${turn.at}`\n return `${heading}\\n\\n${turn.content.trimEnd()}\\n\\n`\n}\n\n// ── parse ────────────────────────────────────────────────────────────\n\ninterface ParsedConversation {\n meta: ConversationMeta\n turns: ConversationTurn[]\n}\n\nfunction parseConversation(source: string, fallbackId: string): ParsedConversation {\n const match = source.match(FRONTMATTER_RE)\n let meta: ConversationMeta = {\n id: fallbackId,\n agent: \"unknown\",\n started: \"\",\n status: \"open\",\n }\n let body = source\n if (match) {\n meta = parseFrontmatter(match[1] ?? \"\", fallbackId)\n body = source.slice(match[0].length)\n }\n\n const turns: ConversationTurn[] = []\n // Split on `## <role> — <iso>` headings. Conservative — anything\n // that doesn't match is treated as continuation of the prior turn.\n const lines = body.split(\"\\n\")\n let current: ConversationTurn | null = null\n let buffer: string[] = []\n\n const flush = () => {\n if (!current) return\n current.content = buffer.join(\"\\n\").trim()\n turns.push(current)\n current = null\n buffer = []\n }\n\n const headingRe =\n /^##\\s+(user|assistant|system)\\s+—\\s+(\\S+)(?:\\s+\\(([^)]+)\\))?\\s*$/\n\n for (const line of lines) {\n const m = line.match(headingRe)\n if (m) {\n flush()\n current = {\n role: m[1] as ConvRole,\n at: m[2] ?? \"\",\n attribution: m[3],\n content: \"\",\n }\n continue\n }\n if (current) buffer.push(line)\n }\n flush()\n\n return { meta, turns }\n}\n\nfunction parseFrontmatter(\n raw: string,\n fallbackId: string,\n): ConversationMeta {\n const out: Record<string, string> = {}\n for (const line of raw.split(\"\\n\")) {\n const colon = line.indexOf(\":\")\n if (colon < 1) continue\n const key = line.slice(0, colon).trim()\n const value = line.slice(colon + 1).trim()\n out[key] = value\n }\n return {\n id: out.id ?? fallbackId,\n agent: out.agent ?? \"unknown\",\n started: out.started ?? \"\",\n status: (out.status === \"closed\" ? \"closed\" : \"open\"),\n }\n}\n","/**\n * In-process event bus for the runtime gateway. Anything the daemon\n * does that an external observer might want to watch (heartbeat fired,\n * conversation turn appended, boot completed, …) flows through here.\n *\n * The HTTP server's `/events` SSE stream subscribes to it and forwards\n * each event as a `data: <json>\\n\\n` frame. Tests and embedded usage\n * subscribe directly via `events.on()`.\n */\n\nimport { EventEmitter } from \"node:events\"\n\nexport interface BootEvent {\n type: \"boot\"\n at: string\n workspace: string\n registered: readonly string[]\n}\n\nexport interface HeartbeatFiredEvent {\n type: \"heartbeat-fired\"\n at: string\n agent: string\n conversationId: string\n prompt: string\n reply: string\n durationMs: number\n}\n\nexport interface HeartbeatErrorEvent {\n type: \"heartbeat-error\"\n at: string\n agent?: string\n error: string\n}\n\nexport interface ConvTurnEvent {\n type: \"conv-turn-appended\"\n at: string\n conversationId: string\n role: \"user\" | \"assistant\"\n contentPreview: string\n}\n\n/**\n * One log line from a supervised tunnel provider (cloudflared today).\n * Surfaced verbatim so users can debug \"why didn't my remote URL come\n * up\" by tailing /events.\n */\nexport interface RemoteLogEvent {\n type: \"remote-log\"\n at: string\n line: string\n}\n\nexport type RuntimeEvent =\n | BootEvent\n | HeartbeatFiredEvent\n | HeartbeatErrorEvent\n | ConvTurnEvent\n | RemoteLogEvent\n\nexport interface RuntimeEvents {\n on<E extends RuntimeEvent[\"type\"]>(\n type: E,\n handler: (ev: Extract<RuntimeEvent, { type: E }>) => void,\n ): () => void\n onAny(handler: (ev: RuntimeEvent) => void): () => void\n emit(ev: RuntimeEvent): void\n}\n\nexport function createRuntimeEvents(): RuntimeEvents {\n const ee = new EventEmitter()\n ee.setMaxListeners(50)\n\n return {\n on(type, handler) {\n const wrapped = (ev: RuntimeEvent) => {\n if (ev.type === type) handler(ev as Extract<RuntimeEvent, { type: typeof type }>)\n }\n ee.on(\"event\", wrapped)\n return () => ee.off(\"event\", wrapped)\n },\n onAny(handler) {\n ee.on(\"event\", handler)\n return () => ee.off(\"event\", handler)\n },\n emit(ev) {\n ee.emit(\"event\", ev)\n },\n }\n}\n","/**\n * Filesystem MCP tools registered on the runtime's MCP server.\n *\n * The runtime already exposes AIP CRUD verbs (create_tool, load_agent, …)\n * via @agentproto/mcp-server. To make the workspace genuinely reachable\n * to remote MCP clients (Guilde cloud agents through a tunnel, IDEs,\n * etc.), we also register canonical filesystem tools that match the\n * shape used by `@modelcontextprotocol/server-filesystem` so existing\n * MCP-fs proxy clients can target the runtime without bespoke logic:\n *\n * read_file ({ path }) → string\n * write_file ({ path, content }) → \"ok\"\n * list_directory ({ path? }) → \"[FILE] x\\n[DIR] y\" lines\n * get_file_info ({ path }) → { name, type, size, modified }\n * create_directory ({ path }) → \"ok\"\n * delete_file ({ path }) → \"ok\"\n *\n * All paths are resolved relative to the workspace root via the same\n * escape guard used by `WorkspaceFs`. Absolute paths inside the root\n * are accepted (so callers that prefix `basePath` with the absolute\n * workspace path keep working).\n */\n\nimport {\n mkdir,\n readFile,\n readdir,\n rm,\n stat,\n writeFile,\n} from \"node:fs/promises\"\nimport { dirname, isAbsolute, join, normalize, relative, resolve } from \"node:path\"\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\"\nimport { z } from \"zod\"\n\nexport interface RegisterFsToolsOptions {\n workspace: string\n}\n\nclass FsPathError extends Error {\n constructor(message: string) {\n super(message)\n this.name = \"FsPathError\"\n }\n}\n\nfunction makeAnchor(workspace: string): (input: string) => string {\n const root = resolve(workspace)\n return (input: string) => {\n if (typeof input !== \"string\" || input.length === 0) {\n throw new FsPathError(\"path must be a non-empty string\")\n }\n const candidate = isAbsolute(input)\n ? normalize(input)\n : normalize(join(root, input))\n const rel = relative(root, candidate)\n if (rel.startsWith(\"..\") || isAbsolute(rel)) {\n throw new FsPathError(`path escapes the workspace: '${input}'`)\n }\n return candidate\n }\n}\n\nfunction text(value: string | object): {\n content: Array<{ type: \"text\"; text: string }>\n} {\n return {\n content: [\n {\n type: \"text\",\n text: typeof value === \"string\" ? value : JSON.stringify(value),\n },\n ],\n }\n}\n\nexport function registerFsTools(\n server: McpServer,\n opts: RegisterFsToolsOptions,\n): void {\n const anchor = makeAnchor(opts.workspace)\n\n server.tool(\n \"read_file\",\n \"Read a UTF-8 file from the workspace.\",\n { path: z.string().describe(\"Workspace-relative path to the file.\") },\n async ({ path }) => {\n const abs = anchor(path)\n const buf = await readFile(abs)\n return text(buf.toString(\"utf8\"))\n },\n )\n\n server.tool(\n \"write_file\",\n \"Write a file to the workspace. Parent directories are created on demand.\",\n {\n path: z.string().describe(\"Workspace-relative path to the file.\"),\n content: z.string().describe(\"File body (UTF-8).\"),\n },\n async ({ path, content }) => {\n const abs = anchor(path)\n await mkdir(dirname(abs), { recursive: true })\n await writeFile(abs, content, \"utf8\")\n return text(\"ok\")\n },\n )\n\n server.tool(\n \"list_directory\",\n \"List entries of a directory in the workspace. Returns one '[FILE]' or '[DIR]' line per entry, mirroring `@modelcontextprotocol/server-filesystem`.\",\n {\n path: z\n .string()\n .optional()\n .describe(\"Workspace-relative directory (defaults to workspace root).\"),\n },\n async ({ path }) => {\n const abs = anchor(path && path.length > 0 ? path : \".\")\n const entries = await readdir(abs, { withFileTypes: true })\n const lines = entries.map(e =>\n e.isDirectory() ? `[DIR] ${e.name}` : `[FILE] ${e.name}`,\n )\n return text(lines.join(\"\\n\"))\n },\n )\n\n server.tool(\n \"get_file_info\",\n \"Stat a file or directory in the workspace.\",\n { path: z.string().describe(\"Workspace-relative path.\") },\n async ({ path }) => {\n const abs = anchor(path)\n const info = await stat(abs)\n return text({\n name: abs.split(\"/\").pop() ?? path,\n path,\n type: info.isDirectory() ? \"directory\" : \"file\",\n size: info.size,\n modified: info.mtime.toISOString(),\n created: info.birthtime.toISOString(),\n })\n },\n )\n\n server.tool(\n \"create_directory\",\n \"Create a directory (recursive) in the workspace.\",\n { path: z.string().describe(\"Workspace-relative directory path.\") },\n async ({ path }) => {\n const abs = anchor(path)\n await mkdir(abs, { recursive: true })\n return text(\"ok\")\n },\n )\n\n server.tool(\n \"delete_file\",\n \"Delete a file or empty directory in the workspace.\",\n { path: z.string().describe(\"Workspace-relative path.\") },\n async ({ path }) => {\n const abs = anchor(path)\n await rm(abs, { recursive: true, force: true })\n return text(\"ok\")\n },\n )\n}\n","/**\n * `~/.agentproto/workspaces.json` — single source of truth for the\n * local agentproto control plane. Tracks which directories the user\n * has opted into as agentproto workspaces, plus which one is \"active\"\n * (the daemon's default working set when no workspace is named in\n * a tool call).\n *\n * Why a config file instead of recreating an MCP entry per workspace:\n * - One daemon = one MCP entry in the user's IDE (clean to read in\n * `claude mcp list`, no `dapper_willow` / `noble_lantern` spam).\n * - The daemon walks `workspaces[]` at boot and exposes them all;\n * tools that need a target take an optional `workspace` arg and\n * fall back to `active` when omitted.\n * - The CLI (`agentproto workspace add/list/remove/use`), the daemon,\n * and the guilde-web onboarding dialog all read+write the same\n * file, so changes from one surface are immediately visible to\n * the others.\n *\n * File layout is intentionally boring (small, hand-editable JSON) —\n * future fields go on top, never break v1 readers.\n */\n\nimport { promises as fs } from \"node:fs\"\nimport { homedir } from \"node:os\"\nimport { dirname, isAbsolute, resolve } from \"node:path\"\n\nexport const WORKSPACES_CONFIG_VERSION = 1 as const\n\nexport interface WorkspaceEntry {\n /** Stable handle — what tools accept as `workspace`. Lowercase\n * ASCII, hyphen-only. The CLI sanitises arbitrary names down to\n * this shape so paste-from-finder Just Works. */\n slug: string\n /** Absolute filesystem path. Required absolute so the daemon can\n * serve the workspace regardless of its own cwd. */\n path: string\n /** ISO-8601 — first time the entry was added. Pure metadata, no\n * behavioural impact. */\n addedAt: string\n /** Last time the entry was touched (renamed, path edited, used as\n * active). Lets the CLI sort by recency without an N+1 stat. */\n updatedAt: string\n /** Free-text label the user can attach so workspaces with similar\n * slugs stay distinguishable in `agentproto workspace list`. */\n label?: string\n}\n\nexport interface WorkspacesConfig {\n version: typeof WORKSPACES_CONFIG_VERSION\n /** Active workspace slug — daemon defaults to this when no\n * `workspace` arg is passed. May be undefined when no workspaces\n * are registered yet. */\n active?: string\n workspaces: WorkspaceEntry[]\n}\n\nexport const DEFAULT_CONFIG_DIR = (): string =>\n resolve(homedir(), \".agentproto\")\nexport const DEFAULT_CONFIG_PATH = (): string =>\n resolve(DEFAULT_CONFIG_DIR(), \"workspaces.json\")\n\n/** Reduce arbitrary user input to a safe slug. Aligns with what most\n * tooling validates against (`/^[a-z0-9][a-z0-9-]{0,63}$/`) so the\n * daemon never has to encode it for URLs or filesystem paths. */\nexport function sanitizeSlug(input: string): string {\n const trimmed = input.trim().toLowerCase()\n const cleaned = trimmed\n .replace(/[^a-z0-9_-]+/g, \"-\")\n .replace(/^-+|-+$/g, \"\")\n .slice(0, 64)\n // Edge case: input was entirely non-conforming — fall back to a\n // generic so we never return an empty string.\n return cleaned || \"workspace\"\n}\n\n/** Read the config from disk. Returns an empty config (no workspaces,\n * no active) when the file is missing — this is the legitimate\n * first-boot state, not an error. */\nexport async function loadWorkspacesConfig(\n path: string = DEFAULT_CONFIG_PATH()\n): Promise<WorkspacesConfig> {\n let raw: string\n try {\n raw = await fs.readFile(path, \"utf8\")\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === \"ENOENT\") {\n return { version: WORKSPACES_CONFIG_VERSION, workspaces: [] }\n }\n throw err\n }\n let parsed: unknown\n try {\n parsed = JSON.parse(raw)\n } catch (err) {\n throw new Error(\n `agentproto: ${path} is not valid JSON (${\n err instanceof Error ? err.message : String(err)\n }). Delete the file or fix it manually.`\n )\n }\n return normalizeConfig(parsed)\n}\n\n/** Write the config back. Creates the parent directory if missing.\n * Atomic-ish: writes to a temp file first, then renames over the\n * target — avoids the partial-write window where a concurrent reader\n * sees half a JSON object. */\nexport async function saveWorkspacesConfig(\n config: WorkspacesConfig,\n path: string = DEFAULT_CONFIG_PATH()\n): Promise<void> {\n const normalized = normalizeConfig(config)\n await fs.mkdir(dirname(path), { recursive: true })\n const tmp = `${path}.tmp.${process.pid}`\n await fs.writeFile(tmp, JSON.stringify(normalized, null, 2) + \"\\n\", \"utf8\")\n await fs.rename(tmp, path)\n}\n\n/**\n * Pure helpers — caller manages persistence. Returns a NEW config\n * (never mutates) so callers can compose multiple updates before\n * a single save.\n */\nexport function addWorkspace(\n config: WorkspacesConfig,\n input: { slug: string; path: string; label?: string }\n): WorkspacesConfig {\n if (!isAbsolute(input.path)) {\n throw new Error(\n `addWorkspace: path must be absolute, got \"${input.path}\".`\n )\n }\n const slug = sanitizeSlug(input.slug)\n const now = new Date().toISOString()\n const existingIdx = config.workspaces.findIndex(w => w.slug === slug)\n const next: WorkspaceEntry = existingIdx >= 0\n ? {\n ...config.workspaces[existingIdx]!,\n path: input.path,\n ...(input.label !== undefined ? { label: input.label } : {}),\n updatedAt: now,\n }\n : {\n slug,\n path: input.path,\n ...(input.label ? { label: input.label } : {}),\n addedAt: now,\n updatedAt: now,\n }\n const workspaces = [...config.workspaces]\n if (existingIdx >= 0) workspaces[existingIdx] = next\n else workspaces.push(next)\n // First-add becomes active automatically — saves the user a\n // separate `workspace use` call right after a fresh `add`.\n const active = config.active ?? slug\n return { ...config, workspaces, active }\n}\n\nexport function removeWorkspace(\n config: WorkspacesConfig,\n slug: string\n): WorkspacesConfig {\n const sanitised = sanitizeSlug(slug)\n const workspaces = config.workspaces.filter(w => w.slug !== sanitised)\n // If the removed workspace was active, hand off to whatever's\n // first — predictable and avoids leaving the daemon in an\n // unreachable state when the user removes the only one.\n let active = config.active\n if (active === sanitised) {\n active = workspaces[0]?.slug\n }\n const next: WorkspacesConfig = { ...config, workspaces }\n if (active !== undefined) next.active = active\n else delete next.active\n return next\n}\n\nexport function setActiveWorkspace(\n config: WorkspacesConfig,\n slug: string\n): WorkspacesConfig {\n const sanitised = sanitizeSlug(slug)\n if (!config.workspaces.some(w => w.slug === sanitised)) {\n throw new Error(\n `setActiveWorkspace: no workspace registered with slug \"${sanitised}\". ` +\n `Run \\`agentproto workspace add <path> --slug ${sanitised}\\` first.`\n )\n }\n return { ...config, active: sanitised }\n}\n\nexport function findWorkspace(\n config: WorkspacesConfig,\n slug: string\n): WorkspaceEntry | undefined {\n return config.workspaces.find(w => w.slug === sanitizeSlug(slug))\n}\n\n/** The active workspace, or undefined when none is registered. Pure\n * convenience to avoid re-implementing the lookup at every caller. */\nexport function getActiveWorkspace(\n config: WorkspacesConfig\n): WorkspaceEntry | undefined {\n if (!config.active) return config.workspaces[0]\n return findWorkspace(config, config.active) ?? config.workspaces[0]\n}\n\n/**\n * Coerce arbitrary parsed JSON into a valid config. Skips entries\n * with missing required fields rather than throwing — partial recovery\n * is friendlier than \"your config file is corrupted, here's a stack\n * trace\". Logs nothing here; the CLI shells that consume this should\n * decide whether to surface a warning.\n */\nfunction normalizeConfig(parsed: unknown): WorkspacesConfig {\n if (!parsed || typeof parsed !== \"object\") {\n return { version: WORKSPACES_CONFIG_VERSION, workspaces: [] }\n }\n const obj = parsed as Record<string, unknown>\n const workspaces: WorkspaceEntry[] = []\n if (Array.isArray(obj.workspaces)) {\n for (const entry of obj.workspaces) {\n if (!entry || typeof entry !== \"object\") continue\n const e = entry as Record<string, unknown>\n const slug = typeof e.slug === \"string\" ? sanitizeSlug(e.slug) : \"\"\n const path = typeof e.path === \"string\" ? e.path : \"\"\n if (!slug || !path) continue\n const addedAt =\n typeof e.addedAt === \"string\" ? e.addedAt : new Date().toISOString()\n const updatedAt = typeof e.updatedAt === \"string\" ? e.updatedAt : addedAt\n const we: WorkspaceEntry = { slug, path, addedAt, updatedAt }\n if (typeof e.label === \"string\" && e.label.trim()) {\n we.label = e.label.trim()\n }\n workspaces.push(we)\n }\n }\n // De-dupe by slug (last wins) — the file is hand-editable so a\n // typo could have produced two entries with the same slug.\n const dedup = new Map<string, WorkspaceEntry>()\n for (const w of workspaces) dedup.set(w.slug, w)\n const finalList = Array.from(dedup.values())\n const active =\n typeof obj.active === \"string\" && finalList.some(w => w.slug === obj.active)\n ? (obj.active as string)\n : finalList[0]?.slug\n const out: WorkspacesConfig = {\n version: WORKSPACES_CONFIG_VERSION,\n workspaces: finalList,\n }\n if (active !== undefined) out.active = active\n return out\n}\n","/**\n * Discover MCP servers already configured in the user's local agent\n * tooling — claude-code, cursor, goose, etc. — so the daemon can\n * surface them in the UI without making the user re-enter the same\n * credentials and URLs they already painstakingly configured for\n * one host.\n *\n * v1 is read-only discovery: we report what's there with source\n * attribution. Future v1.1 ships an \"import to daemon\" verb that\n * proxies the discovered server through the daemon's own /mcp\n * endpoint so every operator (cloud Guilde, local agents) sees a\n * unified set without per-host config drift.\n *\n * Sources scanned (in priority order):\n * - ~/.claude.json (claude-code) — `mcpServers` top-level + nested\n * under `projects[<path>].mcpServers`. Most users land here.\n * - ~/.cursor/mcp.json (cursor) — flat `mcpServers` map.\n * - ~/.config/goose/config.yaml (goose) — TOML/YAML hybrid; we\n * only handle the YAML form for now.\n * - any `.mcp.json` under the user's home that follows the\n * standard mcpServers shape.\n *\n * Each source contributes 0..N entries. Errors are caught + logged\n * (broken JSON, missing files, permission denied) — partial\n * discovery beats failing the whole listing on one bad file.\n */\n\nimport { promises as fs } from \"node:fs\"\nimport { homedir } from \"node:os\"\nimport { resolve as resolvePath } from \"node:path\"\nimport {\n loadWorkspacesConfig,\n type WorkspaceEntry,\n} from \"./workspaces-config.js\"\n\nexport interface DiscoveredMcp {\n /** Stable id within (source, scope, name) — for de-dupe and\n * cross-call identity (UI treat as React key). */\n id: string\n /** Where we found it. Lets the UI render a source badge. */\n source: \"claude-code\" | \"cursor\" | \"goose\" | \"workspace\"\n /** \"global\" when the entry sits at the top level of the host's\n * config; \"project:<path>\" when it's scoped to a single\n * workspace. claude-code in particular nests per-project. */\n scope: string\n /** The host's name for the entry (key in the mcpServers map). */\n name: string\n /** Wire transport — `stdio` (command + args) or `http` / `sse` (url). */\n type: \"stdio\" | \"http\" | \"sse\" | \"unknown\"\n /** stdio entries: argv to spawn. */\n command?: string\n args?: string[]\n /** stdio entries: env injected into the child. */\n env?: Record<string, string>\n /** http/sse entries: target URL. */\n url?: string\n /** http/sse entries: extra headers (Authorization, etc.). */\n headers?: Record<string, string>\n /** Free-form tags from the source config — claude-code's project\n * scope is the most common. */\n tags?: string[]\n /** Reason field when `type === \"unknown\"` — surfaces why the\n * parser couldn't classify the entry (e.g. neither command nor\n * url present). */\n parseNote?: string\n}\n\nexport interface DiscoverMcpsOptions {\n /** Override the home dir — handy for tests that pin a tmpdir. */\n home?: string\n}\n\nexport async function discoverMcps(\n opts: DiscoverMcpsOptions = {}\n): Promise<DiscoveredMcp[]> {\n const home = opts.home ?? homedir()\n const out: DiscoveredMcp[] = []\n const errors: string[] = []\n await Promise.all([\n scanClaudeCode(home, out, errors),\n scanCursor(home, out, errors),\n scanGoose(home, out, errors),\n scanRegisteredWorkspaces(out, errors),\n ])\n // De-dupe identical entries that show up in multiple scopes\n // (e.g. user copied a project entry to global) — keep the first\n // occurrence so the source attribution stays meaningful.\n const seen = new Set<string>()\n const dedup: DiscoveredMcp[] = []\n for (const m of out) {\n const key = `${m.source}:${m.scope}:${m.name}`\n if (seen.has(key)) continue\n seen.add(key)\n dedup.push(m)\n }\n if (errors.length > 0) {\n // One log line per error — operators can trace which file\n // failed without us bubbling the whole stack into the response.\n for (const e of errors) console.warn(`[mcp-discovery] ${e}`)\n }\n return dedup.sort((a, b) => {\n if (a.source !== b.source) return a.source.localeCompare(b.source)\n if (a.scope !== b.scope) return a.scope.localeCompare(b.scope)\n return a.name.localeCompare(b.name)\n })\n}\n\ninterface RawMcpEntry {\n type?: string\n command?: string\n args?: string[]\n env?: Record<string, string>\n url?: string\n headers?: Record<string, string>\n}\n\n/** claude-code stores entries either at top-level `mcpServers` OR\n * per-project under `projects[<absolute-path>].mcpServers`. We\n * surface both with `scope` set so the UI can group by project. */\nasync function scanClaudeCode(\n home: string,\n out: DiscoveredMcp[],\n errors: string[]\n): Promise<void> {\n const path = resolvePath(home, \".claude.json\")\n let raw: string\n try {\n raw = await fs.readFile(path, \"utf8\")\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === \"ENOENT\") return\n errors.push(`claude-code: read ${path} — ${(err as Error).message}`)\n return\n }\n let parsed: unknown\n try {\n parsed = JSON.parse(raw)\n } catch (err) {\n errors.push(`claude-code: JSON parse ${path} — ${(err as Error).message}`)\n return\n }\n if (!parsed || typeof parsed !== \"object\") return\n const root = parsed as Record<string, unknown>\n const top = root.mcpServers\n if (top && typeof top === \"object\") {\n pushMcpMap({\n out,\n source: \"claude-code\",\n scope: \"global\",\n map: top as Record<string, unknown>,\n })\n }\n const projects = root.projects\n if (projects && typeof projects === \"object\") {\n for (const [projPath, proj] of Object.entries(\n projects as Record<string, unknown>\n )) {\n if (!proj || typeof proj !== \"object\") continue\n const projMcps = (proj as Record<string, unknown>).mcpServers\n if (!projMcps || typeof projMcps !== \"object\") continue\n pushMcpMap({\n out,\n source: \"claude-code\",\n scope: `project:${projPath}`,\n map: projMcps as Record<string, unknown>,\n })\n }\n }\n}\n\n/** cursor uses ~/.cursor/mcp.json (standard mcpServers shape).\n * Also supports per-workspace `.cursor/mcp.json` but those need\n * the user's project paths — out of scope for v1. */\nasync function scanCursor(\n home: string,\n out: DiscoveredMcp[],\n errors: string[]\n): Promise<void> {\n const path = resolvePath(home, \".cursor\", \"mcp.json\")\n let raw: string\n try {\n raw = await fs.readFile(path, \"utf8\")\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === \"ENOENT\") return\n errors.push(`cursor: read ${path} — ${(err as Error).message}`)\n return\n }\n let parsed: unknown\n try {\n parsed = JSON.parse(raw)\n } catch (err) {\n errors.push(`cursor: JSON parse ${path} — ${(err as Error).message}`)\n return\n }\n if (!parsed || typeof parsed !== \"object\") return\n const root = parsed as Record<string, unknown>\n const map = root.mcpServers\n if (map && typeof map === \"object\") {\n pushMcpMap({\n out,\n source: \"cursor\",\n scope: \"global\",\n map: map as Record<string, unknown>,\n })\n }\n}\n\n/** goose stores config in ~/.config/goose/config.yaml. The full\n * parser is non-trivial (yaml + extension manifests); v1 looks for\n * the simple `extensions:` block with `mcp_servers` declarations\n * and emits a parseNote so the user knows we found goose but\n * punted on the details. */\nasync function scanGoose(\n home: string,\n out: DiscoveredMcp[],\n errors: string[]\n): Promise<void> {\n // ~/.config on macOS / Linux; goose hasn't shipped Windows-native yet.\n const path = resolvePath(home, \".config\", \"goose\", \"config.yaml\")\n try {\n await fs.access(path)\n } catch {\n return\n }\n // We don't ship a yaml parser as a runtime dep — record presence\n // but punt on parsing. The user sees \"goose detected — open\n // ~/.config/goose/config.yaml to inspect entries\" which is enough\n // signal to drive a v2 enhancement.\n out.push({\n id: \"goose:global:_detected\",\n source: \"goose\",\n scope: \"global\",\n name: \"(goose config detected)\",\n type: \"unknown\",\n parseNote:\n \"Goose config found but YAML parsing is not yet implemented. \" +\n \"Open ~/.config/goose/config.yaml to inspect MCP entries.\",\n })\n}\n\n/**\n * Per-workspace scan — for each registered workspace, look at the\n * common per-project MCP locations (.mcp.json, .cursor/mcp.json,\n * .vscode/mcp.json). Lets the UI surface \"this workspace ships\n * its own chrome-devtools MCP\" instead of only\n * showing what the user configured globally in claude/cursor.\n */\nasync function scanRegisteredWorkspaces(\n out: DiscoveredMcp[],\n errors: string[]\n): Promise<void> {\n let workspaces: WorkspaceEntry[] = []\n try {\n const cfg = await loadWorkspacesConfig()\n workspaces = cfg.workspaces\n } catch (err) {\n errors.push(`workspaces: load failed — ${(err as Error).message}`)\n return\n }\n // Walk each workspace + each candidate path. We don't recurse —\n // these are conventional top-level files. Errors per-file are\n // collected; one bad file doesn't fail the rest.\n await Promise.all(\n workspaces.map(async ws => {\n const candidates = [\n resolvePath(ws.path, \".mcp.json\"),\n resolvePath(ws.path, \".cursor\", \"mcp.json\"),\n resolvePath(ws.path, \".vscode\", \"mcp.json\"),\n ]\n for (const path of candidates) {\n let raw: string\n try {\n raw = await fs.readFile(path, \"utf8\")\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === \"ENOENT\") continue\n errors.push(\n `workspace ${ws.slug}: read ${path} — ${(err as Error).message}`\n )\n continue\n }\n let parsed: unknown\n try {\n parsed = JSON.parse(raw)\n } catch (err) {\n errors.push(\n `workspace ${ws.slug}: JSON parse ${path} — ${(err as Error).message}`\n )\n continue\n }\n if (!parsed || typeof parsed !== \"object\") continue\n const map = (parsed as Record<string, unknown>).mcpServers\n if (!map || typeof map !== \"object\") continue\n pushMcpMap({\n out,\n source: \"workspace\",\n scope: `workspace:${ws.slug}`,\n map: map as Record<string, unknown>,\n })\n }\n })\n )\n}\n\nfunction pushMcpMap(args: {\n out: DiscoveredMcp[]\n source: DiscoveredMcp[\"source\"]\n scope: string\n map: Record<string, unknown>\n}): void {\n for (const [name, raw] of Object.entries(args.map)) {\n if (!raw || typeof raw !== \"object\") continue\n const entry = raw as RawMcpEntry\n const id = `${args.source}:${args.scope}:${name}`\n const declared = typeof entry.type === \"string\" ? entry.type : null\n const url = typeof entry.url === \"string\" ? entry.url : undefined\n const command = typeof entry.command === \"string\" ? entry.command : undefined\n let type: DiscoveredMcp[\"type\"]\n if (declared === \"http\" || declared === \"sse\" || declared === \"stdio\") {\n type = declared\n } else if (url) {\n type = \"http\"\n } else if (command) {\n type = \"stdio\"\n } else {\n type = \"unknown\"\n }\n const m: DiscoveredMcp = {\n id,\n source: args.source,\n scope: args.scope,\n name,\n type,\n }\n if (command !== undefined) m.command = command\n if (Array.isArray(entry.args)) {\n m.args = entry.args.filter((a): a is string => typeof a === \"string\")\n }\n if (entry.env && typeof entry.env === \"object\") {\n m.env = stringifyValues(entry.env)\n }\n if (url !== undefined) m.url = url\n if (entry.headers && typeof entry.headers === \"object\") {\n m.headers = stringifyValues(entry.headers)\n }\n if (type === \"unknown\") {\n m.parseNote =\n \"Entry has neither `command` nor `url` — couldn't classify transport.\"\n }\n args.out.push(m)\n }\n}\n\nfunction stringifyValues(\n raw: Record<string, unknown>\n): Record<string, string> {\n const out: Record<string, string> = {}\n for (const [k, v] of Object.entries(raw)) {\n if (typeof v === \"string\") out[k] = v\n else if (v != null) out[k] = String(v)\n }\n return out\n}\n","/**\n * `~/.agentproto/imported-mcps.json` — the user's curated set of\n * discovered MCPs they want the daemon to know about. v1 is just\n * persistence + read-side; the actual MCP-proxy implementation\n * (where the daemon's /mcp endpoint aggregates the imported\n * servers' tools under namespace prefixes) is v2 work.\n *\n * Purpose: today, \"I see you have chrome-devtools in claude\" is\n * read-only. Once a user imports it, the operator agent can refer\n * to it (\"the user said it's enabled — call it\") and a future\n * proxy layer can actually expose it. We persist the choice now so\n * the data is in place when the proxy lands.\n *\n * File shape:\n * {\n * \"version\": 1,\n * \"imports\": [\n * {\n * \"id\": \"claude-code:project:/path:chrome-devtools\",\n * \"alias\": \"chrome-devtools\",\n * \"addedAt\": \"2026-05-10T...\",\n * \"snapshot\": { ...the DiscoveredMcp at import time }\n * }\n * ]\n * }\n *\n * Snapshotting at import time keeps the daemon resilient to the\n * source config getting deleted (user runs `claude mcp remove ...`).\n * The imported entry stays usable; only the next discovery pass\n * stops listing it as \"available to import.\"\n */\n\nimport { promises as fs } from \"node:fs\"\nimport { homedir } from \"node:os\"\nimport { dirname, resolve as resolvePath } from \"node:path\"\nimport type { DiscoveredMcp } from \"./mcp-discovery.js\"\n\nexport const IMPORTED_MCPS_PATH = (): string =>\n resolvePath(homedir(), \".agentproto\", \"imported-mcps.json\")\n\nexport const IMPORTED_MCPS_VERSION = 1 as const\n\nexport interface ImportedMcpEntry {\n id: string\n alias: string\n addedAt: string\n snapshot: DiscoveredMcp\n}\n\nexport interface ImportedMcpsConfig {\n version: typeof IMPORTED_MCPS_VERSION\n imports: ImportedMcpEntry[]\n}\n\nconst EMPTY: ImportedMcpsConfig = {\n version: IMPORTED_MCPS_VERSION,\n imports: [],\n}\n\nexport async function loadImportedMcps(\n path: string = IMPORTED_MCPS_PATH()\n): Promise<ImportedMcpsConfig> {\n let raw: string\n try {\n raw = await fs.readFile(path, \"utf8\")\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === \"ENOENT\") return EMPTY\n throw err\n }\n let parsed: unknown\n try {\n parsed = JSON.parse(raw)\n } catch (err) {\n throw new Error(\n `agentproto: ${path} is not valid JSON (${\n err instanceof Error ? err.message : String(err)\n }). Delete or fix manually.`\n )\n }\n return normalize(parsed)\n}\n\nexport async function saveImportedMcps(\n config: ImportedMcpsConfig,\n path: string = IMPORTED_MCPS_PATH()\n): Promise<void> {\n await fs.mkdir(dirname(path), { recursive: true })\n const tmp = `${path}.tmp.${process.pid}`\n await fs.writeFile(tmp, JSON.stringify(config, null, 2) + \"\\n\", \"utf8\")\n await fs.rename(tmp, path)\n}\n\n/**\n * Add (or replace) an import. Snapshots the discovered MCP at\n * import time so the entry stays usable when the source config\n * disappears.\n */\nexport function addImport(\n config: ImportedMcpsConfig,\n input: { snapshot: DiscoveredMcp; alias?: string }\n): ImportedMcpsConfig {\n const alias = (input.alias ?? input.snapshot.name).trim()\n if (!alias) {\n throw new Error(\"addImport: alias resolves to empty string\")\n }\n const addedAt = new Date().toISOString()\n const next: ImportedMcpEntry = {\n id: input.snapshot.id,\n alias,\n addedAt,\n snapshot: input.snapshot,\n }\n const others = config.imports.filter(e => e.id !== input.snapshot.id)\n return { ...config, imports: [...others, next] }\n}\n\nexport function removeImport(\n config: ImportedMcpsConfig,\n id: string\n): ImportedMcpsConfig {\n return { ...config, imports: config.imports.filter(e => e.id !== id) }\n}\n\nexport function findImport(\n config: ImportedMcpsConfig,\n id: string\n): ImportedMcpEntry | undefined {\n return config.imports.find(e => e.id === id)\n}\n\nfunction normalize(parsed: unknown): ImportedMcpsConfig {\n if (!parsed || typeof parsed !== \"object\") return EMPTY\n const obj = parsed as Record<string, unknown>\n const imports: ImportedMcpEntry[] = []\n if (Array.isArray(obj.imports)) {\n for (const entry of obj.imports) {\n if (!entry || typeof entry !== \"object\") continue\n const e = entry as Record<string, unknown>\n const id = typeof e.id === \"string\" ? e.id : \"\"\n const alias = typeof e.alias === \"string\" ? e.alias : id\n const addedAt =\n typeof e.addedAt === \"string\" ? e.addedAt : new Date().toISOString()\n const snapshot = e.snapshot as DiscoveredMcp | undefined\n if (!id || !snapshot) continue\n imports.push({ id, alias, addedAt, snapshot })\n }\n }\n return { version: IMPORTED_MCPS_VERSION, imports }\n}\n","/**\n * MCP tools that expose the sessions registry to agents connected to\n * the daemon. Lets a remote operator (Mastra agent in cloud Guilde,\n * Claude Code as a sub-agent, …) spawn + drive agent CLIs on the\n * user's machine through the same MCP connection they already use\n * for fs/exec.\n *\n * Five tools:\n * start_agent_session spawn a long-running agent (claude / hermes / …)\n * prompt_agent_session send a follow-up turn to a live session\n * list_agent_sessions browse alive + recent sessions\n * get_agent_session_output tail the ring buffer\n * kill_agent_session SIGTERM the session\n *\n * Auth: same as every other daemon tool — gated by the gateway's\n * auth source (loopback bypass when no tunnel is up).\n */\n\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\"\nimport { z } from \"zod\"\nimport type { SessionsRegistry } from \"./sessions.js\"\nimport type {\n AgentAdapterResolver,\n AgentAdapterLister,\n} from \"./http-server.js\"\nimport {\n loadWorkspacesConfig,\n findWorkspace,\n getActiveWorkspace,\n} from \"./workspaces-config.js\"\nimport { discoverMcps } from \"./mcp-discovery.js\"\nimport {\n loadImportedMcps,\n saveImportedMcps,\n addImport,\n removeImport,\n} from \"./mcp-imports.js\"\nimport type { McpProxyRegistry } from \"./mcp-proxy.js\"\n\ninterface RegisterSessionToolsOptions {\n registry: SessionsRegistry\n /** Optional adapter resolver — required for `start_agent_session`\n * (the others work with raw spawn sessions too). When unset the\n * start tool returns a clear error pointing at the host wiring. */\n resolveAgentAdapter?: AgentAdapterResolver\n /** Optional adapter lister — when wired, exposes `list_adapters`\n * MCP tool. Without it the tool returns a clear \"not configured\"\n * error pointing at the host wiring. */\n listAgentAdapters?: AgentAdapterLister\n /** Optional MCP proxy registry — when wired, exposes 3 tools that\n * let the operator drive imported MCPs (chrome-devtools, goose-bridge,\n * …) through the daemon as a single MCP entry point. */\n mcpProxy?: McpProxyRegistry\n /** Whether the registry was constructed with a PTY factory — when\n * true, expose the four terminal session tools. When false, the\n * tools return a clear \"not configured\" error. */\n ptyEnabled?: boolean\n}\n\nexport function registerSessionTools(\n server: McpServer,\n opts: RegisterSessionToolsOptions\n): void {\n const { registry, resolveAgentAdapter, listAgentAdapters, mcpProxy } = opts\n const ptyEnabled = opts.ptyEnabled === true\n\n // ── start_agent_session ────────────────────────────────────────\n server.tool(\n \"start_agent_session\",\n \"Spawn a long-running agent CLI (claude-code, hermes, …) on the host. \" +\n \"The session stays alive across multiple turns — call `prompt_agent_session` \" +\n \"to continue the conversation. Returns the session id + initial descriptor. \" +\n \"When `workspaceSlug` is set, resolves the cwd via \" +\n \"`~/.agentproto/workspaces.json`; otherwise pass `cwd` explicitly or \" +\n \"fall back to the active workspace.\",\n {\n adapter: z\n .string()\n .min(1)\n .describe(\n \"Adapter slug — one of the installed `@agentproto/adapter-*` packages \" +\n \"(e.g. 'claude-code', 'hermes', 'aider').\"\n ),\n workspaceSlug: z\n .string()\n .optional()\n .describe(\n \"Workspace slug from `agentproto workspace list`. The daemon resolves it \" +\n \"to an absolute path. Omit to use the `cwd` field or the active workspace.\"\n ),\n cwd: z\n .string()\n .optional()\n .describe(\n \"Absolute path to spawn the agent in. Wins over `workspaceSlug` when both are set.\"\n ),\n prompt: z\n .string()\n .optional()\n .describe(\n \"Optional initial prompt. The session is spawned and the prompt dispatched \" +\n \"in one shot — equivalent to `start` then `prompt` back-to-back. Skip to spawn idle.\"\n ),\n label: z\n .string()\n .optional()\n .describe(\n \"Free-text label that surfaces in `list_agent_sessions` and the UI — useful \" +\n \"for tagging sessions with a conversation id or operator name.\"\n ),\n },\n async input => {\n if (!resolveAgentAdapter) {\n return {\n content: [\n {\n type: \"text\",\n text:\n \"start_agent_session is not enabled — the daemon was started without \" +\n \"an adapter resolver. Re-run the daemon with the `@agentproto/cli` \" +\n \"shim wired (see playground/scripts/gateway.ts).\",\n },\n ],\n isError: true,\n }\n }\n // cwd resolution mirrors the HTTP route: explicit cwd wins,\n // then workspaceSlug lookup, then active workspace, then a\n // hard error (the operator probably forgot a step).\n let cwd = input.cwd\n let resolvedSlug = input.workspaceSlug ?? \"default\"\n if (!cwd) {\n try {\n const config = await loadWorkspacesConfig()\n const ws = input.workspaceSlug\n ? findWorkspace(config, input.workspaceSlug)\n : getActiveWorkspace(config)\n if (ws) {\n cwd = ws.path\n resolvedSlug = ws.slug\n }\n } catch {\n // fall through to error below\n }\n }\n if (!cwd) {\n return {\n content: [\n {\n type: \"text\",\n text:\n \"start_agent_session: no cwd resolvable. Pass `cwd` explicitly, \" +\n \"or pass `workspaceSlug` matching `agentproto workspace list`, \" +\n \"or set an active workspace via `agentproto workspace use <slug>`.\",\n },\n ],\n isError: true,\n }\n }\n const resolved = await resolveAgentAdapter(input.adapter)\n if (!resolved) {\n return {\n content: [\n {\n type: \"text\",\n text: `start_agent_session: adapter \"${input.adapter}\" not found. Try \\`agentproto install <slug>\\` first.`,\n },\n ],\n isError: true,\n }\n }\n try {\n const agentSession = await resolved.startSession({ cwd })\n const desc = registry.spawnAgent({\n workspaceSlug: resolvedSlug,\n cwd,\n agentSession,\n adapterSlug: input.adapter,\n ...(input.prompt ? { initialPrompt: input.prompt } : {}),\n ...(input.label ? { label: input.label } : {}),\n ...(resolved.commandPreview\n ? { commandPreview: resolved.commandPreview }\n : {}),\n })\n return {\n content: [{ type: \"text\", text: JSON.stringify(desc, null, 2) }],\n }\n } catch (err) {\n return {\n content: [\n {\n type: \"text\",\n text: `start_agent_session: spawn failed — ${\n err instanceof Error ? err.message : String(err)\n }`,\n },\n ],\n isError: true,\n }\n }\n }\n )\n\n // ── prompt_agent_session ───────────────────────────────────────\n server.tool(\n \"prompt_agent_session\",\n \"Send a follow-up prompt to a live agent session — multi-turn continuity \" +\n \"without re-spawning. The session id comes from `start_agent_session` \" +\n \"(or `list_agent_sessions`). Returns immediately; tail output via \" +\n \"`get_agent_session_output` or the SSE /sessions/:id/stream endpoint.\",\n {\n sessionId: z.string().describe(\"Session id returned by start_agent_session.\"),\n prompt: z.string().min(1).describe(\"The next user turn (plain text).\"),\n },\n async input => {\n try {\n // Note: sendPrompt awaits the full turn (drains the event\n // stream into the ring buffer). For long turns the operator\n // would prefer fire-and-forget — kick the promise without\n // awaiting and report \"queued\". The caller polls\n // get_agent_session_output for completion.\n void registry.sendPrompt(input.sessionId, input.prompt).catch(() => {\n // Errors land in the ring buffer; nothing to do here.\n })\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(\n { ok: true, sessionId: input.sessionId, queued: true },\n null,\n 2\n ),\n },\n ],\n }\n } catch (err) {\n return {\n content: [\n {\n type: \"text\",\n text: `prompt_agent_session: ${err instanceof Error ? err.message : String(err)}`,\n },\n ],\n isError: true,\n }\n }\n }\n )\n\n // ── list_sessions (canonical lister) ──────────────────────────\n server.tool(\n \"list_sessions\",\n \"List sessions tracked by the daemon — agent-CLI sessions (claude-code, \" +\n \"hermes, …), terminal/PTY sessions (claude TUI, bash, …), and raw \" +\n \"commands. Each entry includes `kind`, `pty` (true for real PTYs), \" +\n \"`name` (when set at spawn), `status`, `command`, age + exit code. Use \" +\n \"this when you need to know what's already running before spawning \" +\n \"anything new, or to discover a session id by name.\",\n {\n kind: z\n .enum([\"terminal\", \"agent-cli\", \"command\", \"all\"])\n .optional()\n .describe(\n \"Filter by session kind. `all` (default) returns every kind. \" +\n \"Use `terminal` to list only PTY sessions, `agent-cli` for \" +\n \"structured ACP agents.\",\n ),\n onlyAlive: z\n .boolean()\n .optional()\n .describe(\"When true, only running/starting sessions. Default false.\"),\n status: z\n .enum([\"starting\", \"running\", \"exited\", \"killed\", \"error\"])\n .optional()\n .describe(\"Filter by exact status (overrides onlyAlive).\"),\n },\n async input => {\n let rows = registry.list()\n if (input.kind && input.kind !== \"all\") {\n rows = rows.filter(s => s.kind === input.kind)\n }\n if (input.status) {\n rows = rows.filter(s => s.status === input.status)\n } else if (input.onlyAlive) {\n rows = rows.filter(\n s => s.status === \"running\" || s.status === \"starting\",\n )\n }\n return {\n content: [\n { type: \"text\", text: JSON.stringify({ sessions: rows }, null, 2) },\n ],\n }\n },\n )\n\n // ── list_agent_sessions (kept for backwards compatibility) ─────\n server.tool(\n \"list_agent_sessions\",\n \"DEPRECATED — prefer `list_sessions` which returns ALL kinds + filters. \" +\n \"Despite the name this tool already returns every kind, not just \" +\n \"agent-cli sessions; the new tool's name reflects the actual surface.\",\n {\n onlyAlive: z\n .boolean()\n .optional()\n .describe(\"Filter to status running/starting only. Default false.\"),\n },\n async input => {\n const all = registry.list()\n const filtered = input.onlyAlive\n ? all.filter(s => s.status === \"running\" || s.status === \"starting\")\n : all\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify({ sessions: filtered }, null, 2),\n },\n ],\n }\n }\n )\n\n // ── get_agent_session_output ───────────────────────────────────\n server.tool(\n \"get_agent_session_output\",\n \"Tail the recent output of a session. Returns the last N lines of the \" +\n \"ring buffer (stdout + stderr inter-leaved, newest last). Use this to read \" +\n \"an agent's reply after `prompt_agent_session`.\",\n {\n sessionId: z.string().describe(\"Session id.\"),\n lastN: z\n .number()\n .int()\n .min(1)\n .max(500)\n .optional()\n .describe(\"Max lines to return. Default 80, max 500.\"),\n },\n async input => {\n const desc = registry.get(input.sessionId)\n if (!desc) {\n return {\n content: [\n { type: \"text\", text: `get_agent_session_output: no session \"${input.sessionId}\"` },\n ],\n isError: true,\n }\n }\n // Best-effort tail — re-attach with a temp listener, capture\n // backfill (which is the recent ring buffer), unsubscribe.\n const limit = input.lastN ?? 80\n const lines: string[] = []\n const unsub = registry.attach(input.sessionId, (line, _stream) => {\n lines.push(line)\n })\n if (unsub) unsub()\n const tail = lines.slice(-limit)\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(\n {\n sessionId: input.sessionId,\n status: desc.status,\n lastOutputAt: desc.lastOutputAt,\n lines: tail,\n },\n null,\n 2\n ),\n },\n ],\n }\n }\n )\n\n // ── list_adapters ──────────────────────────────────────────────\n server.tool(\n \"list_adapters\",\n \"Enumerate every agent CLI adapter installed on the host (claude-code, \" +\n \"hermes, aider, …). Returns slug + display name + version + protocol so \" +\n \"callers can let users pick from the installed set instead of guessing. \" +\n \"Use before `start_agent_session` when the model doesn't already know \" +\n \"what's available.\",\n {},\n async () => {\n if (!listAgentAdapters) {\n return {\n content: [\n {\n type: \"text\",\n text:\n \"list_adapters is not enabled — the daemon was started without \" +\n \"an adapter lister. Wire `@agentproto/cli`'s \" +\n \"`listInstalledAdapters` via `createGateway({ listAgentAdapters })`.\",\n },\n ],\n isError: true,\n }\n }\n try {\n const adapters = await listAgentAdapters()\n return {\n content: [{ type: \"text\", text: JSON.stringify({ adapters }, null, 2) }],\n }\n } catch (err) {\n return {\n content: [\n {\n type: \"text\",\n text: `list_adapters failed: ${err instanceof Error ? err.message : String(err)}`,\n },\n ],\n isError: true,\n }\n }\n }\n )\n\n // ── list_discovered_mcps ───────────────────────────────────────\n server.tool(\n \"list_discovered_mcps\",\n \"Discover MCP servers already configured in the user's other agent \" +\n \"tooling (claude-code, cursor, goose). Returns the union with source \" +\n \"attribution so the operator can suggest 'I see you have a chrome-devtools \" +\n \"MCP set up in claude — want me to use it?' instead of asking the user \" +\n \"to re-configure. Read-only — does not modify any host's config.\",\n {},\n async () => {\n try {\n const mcps = await discoverMcps()\n return {\n content: [{ type: \"text\", text: JSON.stringify({ mcps }, null, 2) }],\n }\n } catch (err) {\n return {\n content: [\n {\n type: \"text\",\n text: `list_discovered_mcps failed: ${err instanceof Error ? err.message : String(err)}`,\n },\n ],\n isError: true,\n }\n }\n }\n )\n\n // ── list_imported_mcps ─────────────────────────────────────────\n server.tool(\n \"list_imported_mcps\",\n \"Return the user's curated set of MCP servers — the ones they've \" +\n \"imported from claude / cursor / workspace configs into the daemon. \" +\n \"Use to know which MCPs the operator may freely call vs. ones still \" +\n \"showing up in `list_discovered_mcps` waiting on the user's blessing.\",\n {},\n async () => {\n try {\n const config = await loadImportedMcps()\n return {\n content: [\n { type: \"text\", text: JSON.stringify(config, null, 2) },\n ],\n }\n } catch (err) {\n return {\n content: [\n {\n type: \"text\",\n text: `list_imported_mcps failed: ${err instanceof Error ? err.message : String(err)}`,\n },\n ],\n isError: true,\n }\n }\n }\n )\n\n // ── import_mcp ─────────────────────────────────────────────────\n server.tool(\n \"import_mcp\",\n \"Import a discovered MCP into the daemon's curated set. The agent \" +\n \"calls `list_discovered_mcps` first, asks the user, then commits the \" +\n \"choice via this tool. The snapshot is captured at import time so \" +\n \"the entry stays usable if the source config (claude/cursor) is \" +\n \"later removed.\",\n {\n sourceMcpId: z\n .string()\n .min(1)\n .describe(\n \"The discovered MCP id from `list_discovered_mcps` \" +\n \"(e.g. 'claude-code:project:/path:chrome-devtools').\"\n ),\n alias: z\n .string()\n .optional()\n .describe(\n \"Optional friendly name to display. Defaults to the source MCP's name.\"\n ),\n },\n async input => {\n try {\n const discovered = await discoverMcps()\n const snapshot = discovered.find(d => d.id === input.sourceMcpId)\n if (!snapshot) {\n return {\n content: [\n {\n type: \"text\",\n text: `import_mcp: discovered MCP \"${input.sourceMcpId}\" not found. Re-run list_discovered_mcps to get current ids.`,\n },\n ],\n isError: true,\n }\n }\n const cfg = await loadImportedMcps()\n const next = addImport(cfg, {\n snapshot,\n ...(input.alias ? { alias: input.alias } : {}),\n })\n await saveImportedMcps(next)\n const entry = next.imports.find(e => e.id === snapshot.id)\n return {\n content: [{ type: \"text\", text: JSON.stringify(entry, null, 2) }],\n }\n } catch (err) {\n return {\n content: [\n {\n type: \"text\",\n text: `import_mcp failed: ${err instanceof Error ? err.message : String(err)}`,\n },\n ],\n isError: true,\n }\n }\n }\n )\n\n // ── remove_imported_mcp ────────────────────────────────────────\n server.tool(\n \"remove_imported_mcp\",\n \"Remove a previously-imported MCP from the daemon's curated set. \" +\n \"Use when the user no longer wants the operator referencing it.\",\n {\n id: z\n .string()\n .min(1)\n .describe(\n \"The imported MCP id (matches the discovered MCP id at import time).\"\n ),\n },\n async input => {\n try {\n const cfg = await loadImportedMcps()\n if (!cfg.imports.some(e => e.id === input.id)) {\n return {\n content: [\n {\n type: \"text\",\n text: `remove_imported_mcp: id \"${input.id}\" not in imports. Use list_imported_mcps to see current entries.`,\n },\n ],\n isError: true,\n }\n }\n await saveImportedMcps(removeImport(cfg, input.id))\n return {\n content: [\n { type: \"text\", text: JSON.stringify({ ok: true, id: input.id }, null, 2) },\n ],\n }\n } catch (err) {\n return {\n content: [\n {\n type: \"text\",\n text: `remove_imported_mcp failed: ${err instanceof Error ? err.message : String(err)}`,\n },\n ],\n isError: true,\n }\n }\n }\n )\n\n // ── mcp_imported_status ────────────────────────────────────────\n // The 3 proxy tools share the same wiring guard — register them\n // only when the host injected a proxy registry, otherwise emit a\n // clear \"not enabled\" error so the agent doesn't think the daemon\n // silently dropped the call.\n server.tool(\n \"mcp_imported_status\",\n \"Snapshot every imported MCP server with its connection status, \" +\n \"transport type, and tool count. Use this first when an operator \" +\n \"wonders 'what MCPs do I actually have access to right now?' — the \" +\n \"answer covers both 'imported but not yet connected' and 'connected \" +\n \"with N tools'. Errors during connect surface in `lastError`.\",\n {},\n async () => {\n if (!mcpProxy) {\n return {\n content: [\n {\n type: \"text\",\n text:\n \"mcp_imported_status is not enabled — daemon was started without \" +\n \"an MCP proxy. The host must wire `mcpProxy` in createGateway.\",\n },\n ],\n isError: true,\n }\n }\n try {\n const aliases = await mcpProxy.listAliases()\n return {\n content: [\n { type: \"text\", text: JSON.stringify({ imports: aliases }, null, 2) },\n ],\n }\n } catch (err) {\n return {\n content: [\n {\n type: \"text\",\n text: `mcp_imported_status failed: ${err instanceof Error ? err.message : String(err)}`,\n },\n ],\n isError: true,\n }\n }\n }\n )\n\n // ── mcp_imported_list_tools ────────────────────────────────────\n server.tool(\n \"mcp_imported_list_tools\",\n \"List the tools exposed by one imported MCP server. The proxy \" +\n \"lazily connects on first call — first-use latency includes the \" +\n \"transport handshake (stdio: ~1-2s for npx-spawned servers; \" +\n \"http/sse: <100ms). Returns the upstream `inputSchema` (JSON \" +\n \"Schema) verbatim so the operator can build a valid `arguments` \" +\n \"object for the follow-up `mcp_imported_call` invocation.\",\n {\n alias: z\n .string()\n .min(1)\n .describe(\n \"Alias from `list_imported_mcps` / `mcp_imported_status` \" +\n \"(typically the original MCP name, e.g. 'chrome-devtools').\"\n ),\n },\n async input => {\n if (!mcpProxy) {\n return {\n content: [\n {\n type: \"text\",\n text: \"mcp_imported_list_tools is not enabled — see mcp_imported_status.\",\n },\n ],\n isError: true,\n }\n }\n const out = await mcpProxy.listTools(input.alias)\n if (!out.ok) {\n return {\n content: [\n {\n type: \"text\",\n text: `mcp_imported_list_tools \"${input.alias}\": ${out.error}`,\n },\n ],\n isError: true,\n }\n }\n return {\n content: [\n { type: \"text\", text: JSON.stringify({ alias: input.alias, tools: out.tools }, null, 2) },\n ],\n }\n }\n )\n\n // ── mcp_imported_call ──────────────────────────────────────────\n server.tool(\n \"mcp_imported_call\",\n \"Invoke a tool on an imported MCP server. The daemon proxies the \" +\n \"call through the live client connection — the upstream server \" +\n \"validates `arguments` against its own input schema (which you \" +\n \"can fetch via `mcp_imported_list_tools`). The full upstream \" +\n \"result is returned verbatim, including `isError` flags so the \" +\n \"operator sees the original failure shape.\",\n {\n alias: z.string().min(1).describe(\"Imported MCP alias.\"),\n toolName: z\n .string()\n .min(1)\n .describe(\n \"Tool name as it appears in `mcp_imported_list_tools` \" +\n \"(NOT a namespaced version — pass the upstream's own name).\"\n ),\n args: z\n .record(z.string(), z.unknown())\n .optional()\n .describe(\n \"Tool arguments as a JSON object. Schema is the upstream's \" +\n \"— the proxy doesn't validate, only forwards. Default: empty object.\"\n ),\n },\n async input => {\n if (!mcpProxy) {\n return {\n content: [\n {\n type: \"text\",\n text: \"mcp_imported_call is not enabled — see mcp_imported_status.\",\n },\n ],\n isError: true,\n }\n }\n const out = await mcpProxy.callTool(\n input.alias,\n input.toolName,\n input.args ?? {}\n )\n if (!out.ok) {\n return {\n content: [\n {\n type: \"text\",\n text: `mcp_imported_call \"${input.alias}\".${input.toolName}: ${out.error}`,\n },\n ],\n isError: true,\n }\n }\n // Forward the upstream result. The MCP SDK's CallToolResult is\n // already in the {content, isError?} shape we return — pass it\n // through with a note that it came from the proxy.\n return out.result as {\n content: Array<{ type: \"text\"; text: string }>\n isError?: boolean\n }\n }\n )\n\n // ── kill_agent_session ─────────────────────────────────────────\n server.tool(\n \"kill_agent_session\",\n \"Stop a session — SIGTERM the underlying child + close the agent protocol \" +\n \"session. Use to free resources after the operator is done, or when a \" +\n \"session is wedged.\",\n {\n sessionId: z.string().describe(\"Session id.\"),\n },\n async input => {\n const ok = registry.kill(input.sessionId)\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify({ ok, sessionId: input.sessionId }, null, 2),\n },\n ],\n }\n }\n )\n\n // ── Terminal session tools ─────────────────────────────────────\n // Four tools that mirror the agent-session set but operate on raw\n // PTY sessions (real terminal, ANSI bytes, multi-subscriber). Use\n // these to drive interactive CLIs like `claude` in TUI mode, or\n // for one agent to orchestrate other shells. Read/write/exit\n // happen over the byte ring buffer; the WS at /sessions/:id/pty\n // is the streaming alternative.\n\n const ptyNotConfigured = (toolName: string): {\n content: Array<{ type: \"text\"; text: string }>\n isError: true\n } => ({\n content: [\n {\n type: \"text\",\n text:\n `${toolName}: PTY support not enabled — the daemon was started without ` +\n \"a node-pty factory. Re-run `agentproto serve` from a build that ships \" +\n \"node-pty (the optional dep ships with @agentproto/cli).\",\n },\n ],\n isError: true,\n })\n\n server.tool(\n \"start_terminal_session\",\n \"Spawn a process under a real PTY (node-pty) on the host. Bytes (including \" +\n \"ANSI escapes, alt-screen sequences) flow through the daemon's byte ring \" +\n \"buffer; subscribers attach via the WS at /sessions/:id/pty. Use for \" +\n \"interactive TUIs (claude, vim, htop) or to orchestrate shells from another \" +\n \"agent. Returns the session descriptor.\",\n {\n argv: z\n .array(z.string())\n .min(1)\n .describe(\n \"Argv array. First element is the binary, rest are arguments. \" +\n \"e.g. ['claude'] or ['bash', '-l'].\"\n ),\n workspaceSlug: z\n .string()\n .optional()\n .describe(\n \"Workspace slug from `agentproto workspace list`. Resolves cwd. Omit \" +\n \"to use `cwd` explicitly or the active workspace.\"\n ),\n cwd: z\n .string()\n .optional()\n .describe(\"Absolute cwd. Wins over workspaceSlug when both set.\"),\n cols: z.number().int().min(1).max(500).optional().describe(\"Initial cols. Default 80.\"),\n rows: z.number().int().min(1).max(200).optional().describe(\"Initial rows. Default 24.\"),\n name: z\n .string()\n .optional()\n .describe(\n \"User-friendly slug. Becomes an alias for the session id in \" +\n \"subsequent tool calls (read/write/kill accept either).\"\n ),\n label: z\n .string()\n .optional()\n .describe(\n \"Free-text label surfaced in list_agent_sessions and the UI.\"\n ),\n },\n async input => {\n if (!ptyEnabled) return ptyNotConfigured(\"start_terminal_session\")\n let cwd = input.cwd\n let resolvedSlug = input.workspaceSlug ?? \"default\"\n if (!cwd) {\n try {\n const config = await loadWorkspacesConfig()\n const ws = input.workspaceSlug\n ? findWorkspace(config, input.workspaceSlug)\n : getActiveWorkspace(config)\n if (ws) {\n cwd = ws.path\n resolvedSlug = ws.slug\n }\n } catch {\n // fall through to error\n }\n }\n if (!cwd) {\n return {\n content: [\n {\n type: \"text\",\n text:\n \"start_terminal_session: no cwd resolvable. Pass `cwd` explicitly \" +\n \"or `workspaceSlug` matching `agentproto workspace list`.\",\n },\n ],\n isError: true,\n }\n }\n try {\n const desc = registry.spawnPty({\n argv: input.argv,\n cwd,\n workspaceSlug: resolvedSlug,\n cols: input.cols ?? 80,\n rows: input.rows ?? 24,\n ...(input.name ? { name: input.name } : {}),\n ...(input.label ? { label: input.label } : {}),\n })\n return {\n content: [{ type: \"text\", text: JSON.stringify(desc, null, 2) }],\n }\n } catch (err) {\n return {\n content: [\n {\n type: \"text\",\n text: `start_terminal_session: ${err instanceof Error ? err.message : String(err)}`,\n },\n ],\n isError: true,\n }\n }\n }\n )\n\n server.tool(\n \"write_terminal_input\",\n \"Send keystrokes to a PTY session's stdin. The text is forwarded verbatim — \" +\n \"include trailing newlines if the target needs them (e.g. shell commands). \" +\n \"Use after `start_terminal_session` to drive an interactive CLI.\",\n {\n sessionId: z\n .string()\n .describe(\"Session id OR name from start_terminal_session.\"),\n text: z.string().describe(\"Text to write. Sent as-is to the PTY's stdin.\"),\n },\n async input => {\n if (!ptyEnabled) return ptyNotConfigured(\"write_terminal_input\")\n const desc = registry.findByIdOrName(input.sessionId)\n if (!desc) {\n return {\n content: [\n {\n type: \"text\",\n text: `write_terminal_input: no session \"${input.sessionId}\"`,\n },\n ],\n isError: true,\n }\n }\n const ok = registry.writeTerminalInput(desc.id, input.text)\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify({ ok, sessionId: desc.id }, null, 2),\n },\n ],\n ...(ok ? {} : { isError: true as const }),\n }\n }\n )\n\n server.tool(\n \"read_terminal_output\",\n \"Snapshot the recent byte buffer of a PTY session. Returns base64-encoded \" +\n \"bytes (the buffer is RAW including ANSI escapes — strip with a regex if \" +\n \"you want plain text). `lastBytes` caps the read from the tail.\",\n {\n sessionId: z\n .string()\n .describe(\"Session id OR name from start_terminal_session.\"),\n lastBytes: z\n .number()\n .int()\n .min(1)\n .max(64 * 1024)\n .optional()\n .describe(\"Max bytes from the tail. Default: full ring buffer (~64 KiB).\"),\n },\n async input => {\n if (!ptyEnabled) return ptyNotConfigured(\"read_terminal_output\")\n const desc = registry.findByIdOrName(input.sessionId)\n if (!desc) {\n return {\n content: [\n {\n type: \"text\",\n text: `read_terminal_output: no session \"${input.sessionId}\"`,\n },\n ],\n isError: true,\n }\n }\n const buf = registry.readTerminalOutput(\n desc.id,\n input.lastBytes,\n )\n if (!buf) {\n return {\n content: [\n {\n type: \"text\",\n text: `read_terminal_output: session \"${desc.id}\" is not a PTY`,\n },\n ],\n isError: true,\n }\n }\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(\n {\n sessionId: desc.id,\n status: desc.status,\n bytes: buf.byteLength,\n b64: buf.toString(\"base64\"),\n },\n null,\n 2,\n ),\n },\n ],\n }\n }\n )\n\n server.tool(\n \"kill_terminal_session\",\n \"SIGTERM a PTY session and drop it from the alive set. Same effect as \" +\n \"`kill_agent_session` for the PTY family — separate name so it's obvious \" +\n \"what's being stopped.\",\n {\n sessionId: z\n .string()\n .describe(\"Session id OR name from start_terminal_session.\"),\n },\n async input => {\n if (!ptyEnabled) return ptyNotConfigured(\"kill_terminal_session\")\n const desc = registry.findByIdOrName(input.sessionId)\n if (!desc) {\n return {\n content: [\n {\n type: \"text\",\n text: `kill_terminal_session: no session \"${input.sessionId}\"`,\n },\n ],\n isError: true,\n }\n }\n const ok = registry.kill(desc.id)\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify({ ok, sessionId: desc.id }, null, 2),\n },\n ],\n }\n }\n )\n}\n","/**\n * HEARTBEAT.md autonomy loop.\n *\n * A workspace can ship a `HEARTBEAT.md` at its root. Frontmatter:\n *\n * schema: heartbeat/v1\n * agent: <id> (matches `<workspace>/.agents/<id>/AGENT.md`)\n * every: \"60s\" (Ns | Nm | Nh | Nd; cron support TODO)\n * enabled: true (default true; set false to register-but-skip)\n * conversation: heartbeat-{date} (templated id; defaults to per-day)\n *\n * Body = the prompt body the agent receives each tick. Reread fresh\n * on every tick so editing HEARTBEAT.md takes effect without restart.\n *\n * Ticks resolve the agent via the injected `buildAgent` callback,\n * call `agent.generate(prompt)`, and append the prompt + reply to a\n * conversation (default: daily-rolling `heartbeat-YYYY-MM-DD`).\n *\n * When the file is missing, frontmatter is invalid, `enabled: false`,\n * or the resolved agent has no usable model — the runner skips the\n * tick silently and emits a `heartbeat-error` event. The daemon\n * stays up.\n */\n\nimport matter from \"gray-matter\"\nimport { existsSync } from \"node:fs\"\nimport { readFile } from \"node:fs/promises\"\nimport { join } from \"node:path\"\nimport type { ConversationStore } from \"./conversations.js\"\nimport type { RuntimeEvents } from \"./events.js\"\n\nexport interface HeartbeatAgent {\n generate(prompt: string): Promise<{ text: string }>\n}\n\nexport interface BuildHeartbeatAgent {\n (id: string): Promise<HeartbeatAgent | null>\n}\n\nexport interface HeartbeatRunnerOptions {\n workspace: string\n conversations: ConversationStore\n events: RuntimeEvents\n /** Resolves a heartbeat-runnable agent from its workspace id. */\n buildAgent: BuildHeartbeatAgent\n /** Filename inside the workspace root. Default `HEARTBEAT.md`. */\n filename?: string\n /** Skip ticks while this returns false. Default: always true. */\n shouldFire?: () => boolean\n /** Override clock for tests. */\n now?: () => Date\n}\n\nexport interface HeartbeatRunner {\n /** Start the timer loop. Idempotent. */\n start(): void\n /** Stop the timer loop. Pending ticks finish out. */\n stop(): void\n /** Force-fire one tick now (used by `POST /heartbeat/tick`). */\n fireNow(): Promise<void>\n}\n\ninterface ParsedHeartbeat {\n agent: string\n everyMs: number\n enabled: boolean\n conversationTemplate: string\n body: string\n}\n\nexport function startHeartbeat(opts: HeartbeatRunnerOptions): HeartbeatRunner {\n const filename = opts.filename ?? \"HEARTBEAT.md\"\n const path = join(opts.workspace, filename)\n const now = opts.now ?? (() => new Date())\n\n let timer: NodeJS.Timeout | null = null\n let currentEveryMs: number | null = null\n let firing = false\n\n async function load(): Promise<ParsedHeartbeat | null> {\n if (!existsSync(path)) return null\n let source: string\n try {\n source = await readFile(path, \"utf8\")\n } catch {\n return null\n }\n const parsed = matter(source)\n const fm = parsed.data as Record<string, unknown>\n const agent = typeof fm.agent === \"string\" ? fm.agent : null\n if (!agent) return null\n const enabled = fm.enabled === undefined ? true : Boolean(fm.enabled)\n const everyRaw = typeof fm.every === \"string\" ? fm.every : \"60s\"\n const everyMs = parseDuration(everyRaw)\n if (!everyMs) return null\n const conversationTemplate =\n typeof fm.conversation === \"string\"\n ? fm.conversation\n : \"heartbeat-{date}\"\n return {\n agent,\n everyMs,\n enabled,\n conversationTemplate,\n body: parsed.content.trim(),\n }\n }\n\n async function tick(): Promise<void> {\n if (firing) return\n if (opts.shouldFire && !opts.shouldFire()) return\n firing = true\n let agentId: string | undefined\n try {\n const hb = await load()\n if (!hb || !hb.enabled) return\n agentId = hb.agent\n const agent = await opts.buildAgent(hb.agent)\n if (!agent) {\n opts.events.emit({\n type: \"heartbeat-error\",\n at: now().toISOString(),\n agent: hb.agent,\n error: `buildAgent('${hb.agent}') returned null`,\n })\n return\n }\n if (!hb.body) {\n opts.events.emit({\n type: \"heartbeat-error\",\n at: now().toISOString(),\n agent: hb.agent,\n error: \"HEARTBEAT.md body is empty\",\n })\n return\n }\n\n const conversationId = expandTemplate(hb.conversationTemplate, now())\n await opts.conversations.open(conversationId, { agent: hb.agent })\n\n const startedAt = now()\n await opts.conversations.appendTurn(\n conversationId,\n \"user\",\n hb.body,\n { at: startedAt.toISOString(), attribution: \"heartbeat\" },\n )\n opts.events.emit({\n type: \"conv-turn-appended\",\n at: startedAt.toISOString(),\n conversationId,\n role: \"user\",\n contentPreview: preview(hb.body),\n })\n\n const t0 = Date.now()\n const reply = await agent.generate(hb.body)\n const durationMs = Date.now() - t0\n\n const finishedAt = now()\n await opts.conversations.appendTurn(\n conversationId,\n \"assistant\",\n reply.text,\n { at: finishedAt.toISOString(), attribution: hb.agent },\n )\n opts.events.emit({\n type: \"conv-turn-appended\",\n at: finishedAt.toISOString(),\n conversationId,\n role: \"assistant\",\n contentPreview: preview(reply.text),\n })\n opts.events.emit({\n type: \"heartbeat-fired\",\n at: finishedAt.toISOString(),\n agent: hb.agent,\n conversationId,\n prompt: hb.body,\n reply: reply.text,\n durationMs,\n })\n\n // Adapt the timer if `every` changed since we started.\n if (currentEveryMs !== null && currentEveryMs !== hb.everyMs) {\n reschedule(hb.everyMs)\n }\n } catch (err) {\n opts.events.emit({\n type: \"heartbeat-error\",\n at: now().toISOString(),\n agent: agentId,\n error: err instanceof Error ? err.message : String(err),\n })\n } finally {\n firing = false\n }\n }\n\n function reschedule(everyMs: number): void {\n if (timer) clearInterval(timer)\n currentEveryMs = everyMs\n timer = setInterval(() => {\n void tick()\n }, everyMs)\n }\n\n return {\n start() {\n if (timer) return\n // Bootstrap interval from the file (or fall back to 60s if\n // unreadable — first real tick will refresh from disk).\n void load().then((hb) => {\n const everyMs = hb?.everyMs ?? 60_000\n reschedule(everyMs)\n })\n },\n stop() {\n if (timer) {\n clearInterval(timer)\n timer = null\n currentEveryMs = null\n }\n },\n async fireNow() {\n await tick()\n },\n }\n}\n\n// ── helpers ──────────────────────────────────────────────────────────\n\nconst DURATION_RE = /^(\\d+)\\s*(s|m|h|d)$/\n\n/**\n * Parse `Ns | Nm | Nh | Nd` into milliseconds. Returns `null` if the\n * string doesn't match. (AIP-41 supports more units, but the daemon's\n * heartbeat sticks to coarse durations to keep ticks observable.)\n */\nexport function parseDuration(input: string): number | null {\n const trimmed = input.trim()\n const match = trimmed.match(DURATION_RE)\n if (!match) return null\n const n = Number(match[1])\n if (!Number.isFinite(n) || n <= 0) return null\n switch (match[2]) {\n case \"s\":\n return n * 1_000\n case \"m\":\n return n * 60_000\n case \"h\":\n return n * 3_600_000\n case \"d\":\n return n * 86_400_000\n default:\n return null\n }\n}\n\n/**\n * Replace `{date}` with `YYYY-MM-DD` (UTC) in conversation templates.\n * Other tokens pass through unchanged — extend later if needed.\n */\nfunction expandTemplate(template: string, when: Date): string {\n const date = when.toISOString().slice(0, 10)\n return template.replace(/\\{date\\}/g, date)\n}\n\nfunction preview(text: string, max = 120): string {\n const flat = text.replace(/\\s+/g, \" \").trim()\n return flat.length > max ? `${flat.slice(0, max - 1)}…` : flat\n}\n","/**\n * Tiny node:http server that fronts the runtime gateway.\n *\n * Routes:\n * GET /health — { status, workspace, registered, uptime }\n * GET /events — SSE stream of RuntimeEvent\n * POST /mcp — MCP Streamable HTTP transport (POST)\n * GET /mcp — MCP SSE response stream (GET)\n * DELETE /mcp — close MCP session\n * GET /conversations — JSON list of conversation summaries\n * GET /conversations/<id> — markdown body of one conversation\n * POST /heartbeat/tick — force-fire one heartbeat tick\n *\n * No auth in `mode: \"none\"` (loopback default). `mode: \"bearer\"`\n * checks `Authorization: Bearer <token>` against the configured\n * token. Health is always public so external monitors can probe.\n *\n * MCP transport: stateless mode for v1 — each request is independent.\n * Stateful session pinning can come later when long-running streaming\n * tool calls become a real use case.\n */\n\nimport { createServer, type IncomingMessage, type Server, type ServerResponse } from \"node:http\"\nimport type { Duplex } from \"node:stream\"\nimport { mkdir, stat, writeFile } from \"node:fs/promises\"\nimport { isAbsolute, join, resolve as resolvePath } from \"node:path\"\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\"\nimport { StreamableHTTPServerTransport } from \"@modelcontextprotocol/sdk/server/streamableHttp.js\"\nimport { WebSocketServer, type WebSocket } from \"ws\"\nimport type { ConversationStore } from \"./conversations.js\"\nimport type { HeartbeatRunner } from \"./heartbeat.js\"\nimport type { RuntimeEvents, RuntimeEvent } from \"./events.js\"\nimport type { SessionsRegistry, AgentSessionLike } from \"./sessions.js\"\nimport {\n loadWorkspacesConfig,\n findWorkspace,\n getActiveWorkspace,\n} from \"./workspaces-config.js\"\nimport { discoverMcps } from \"./mcp-discovery.js\"\nimport type { McpProxyRegistry } from \"./mcp-proxy.js\"\nimport {\n loadImportedMcps,\n saveImportedMcps,\n addImport,\n removeImport,\n} from \"./mcp-imports.js\"\n\n/**\n * Default Origin allowlist used when `RuntimeHttpServerOptions.allowedOrigins`\n * is undefined. Localhost on any port covers the user's own dev environments\n * (Guilde web dev server, playground demos, embedded panels). Production\n * origins (https://guilde.work, …) are NOT included by default — those are\n * opt-in via `agentproto serve --allow-origin <url>`.\n */\nconst DEFAULT_ALLOWED_ORIGINS: readonly string[] = [\n \"http://localhost:*\",\n \"http://127.0.0.1:*\",\n \"https://localhost:*\",\n]\n\n/**\n * Pluggable adapter resolver — keeps the runtime package free of any\n * @agentproto/cli dep. The host (cli `serve`, playground, embedding\n * apps) builds the resolver and hands it in. Returning null means\n * \"adapter not found\" → 404.\n */\nexport type AgentAdapterResolver = (slug: string) => Promise<{\n /** Build a fresh AgentSessionLike for the given cwd. The driver\n * spawns the adapter binary, opens the protocol, and the\n * registry holds the result.\n *\n * When `resumeSessionId` is set, the driver reattaches to that\n * pre-existing adapter session (claude-code's conversation id,\n * hermes' chat handle, …) rather than starting blank. Same\n * mechanism as `agentproto run --resume <id>` — exposed over\n * HTTP so `agentproto sessions restart` works on agent-cli\n * sessions, not just PTY ones. */\n startSession(opts: {\n cwd: string\n resumeSessionId?: string\n /** Model identifier forwarded from `start_agent_session`. Adapters\n * that support model selection (e.g. via a `--model` CLI flag) may\n * honour this; others silently ignore it. */\n model?: string\n }): Promise<AgentSessionLike>\n /** Display label for the descriptor's `command` field. */\n commandPreview?: string\n} | null>\n\n/**\n * Compact adapter metadata for the discovery endpoints. Independent\n * of the resolver function above — hosts that can list installed\n * adapters wire this; hosts that can only resolve by-slug skip it\n * (the routes 501).\n */\nexport interface AdapterListEntry {\n slug: string\n name: string\n version: string\n description: string\n protocol: string\n streaming: boolean\n packageName: string\n}\n\nexport type AgentAdapterLister = () => Promise<AdapterListEntry[]>\n\nexport interface AuthOptions {\n mode: \"none\" | \"bearer\"\n token?: string\n}\n\n/**\n * Auth can be a fixed value (set at startup) or a getter (re-read on\n * every request). The getter form lets `remote_enable` flip bearer on\n * at runtime without restarting the gateway.\n */\nexport type AuthSource = AuthOptions | (() => AuthOptions)\n\nexport interface RuntimeHttpServerOptions {\n port: number\n bind?: string\n auth?: AuthSource\n /**\n * Per-request McpServer factory.\n *\n * The SDK's `StreamableHTTPServerTransport` is single-use — once a\n * transport has handled one request, the underlying `Protocol`\n * cannot be reattached, so subsequent requests on a shared transport\n * 500. The official stateless pattern (see SDK\n * `examples/server/simpleStatelessStreamableHttp.js`) builds a\n * fresh `McpServer` and `StreamableHTTPServerTransport` per request,\n * connects them, and tears both down on `res.close`. We follow that.\n *\n * The factory is invoked once per `/mcp` POST. It must register\n * tools / resources / prompts on the returned server before\n * resolving — by the time the transport's `handleRequest` fires,\n * the server is locked in.\n */\n mcpServerFactory: () => Promise<McpServer>\n conversations: ConversationStore\n events: RuntimeEvents\n heartbeat: HeartbeatRunner\n /** Optional — when wired, exposes /sessions routes for the CLI\n * TUI and the guilde-web Active tab to navigate live child\n * processes. Daemons that don't spawn anything (pure MCP servers)\n * can omit this and the routes 404. */\n sessions?: SessionsRegistry\n /** Optional — when wired alongside `sessions`, enables\n * `POST /sessions/agent` and `POST /sessions/:id/prompt` routes.\n * Hosts that ship adapters (`agentproto serve`, playground)\n * pass the cli's `resolveAdapter` via a thin shim. */\n resolveAgentAdapter?: AgentAdapterResolver\n /** Optional — when wired, enables `GET /adapters` route + the\n * MCP `list_adapters` tool so UIs can discover what's installed\n * without trial-and-error against the resolver. Hosts ship the\n * cli's `listInstalledAdapters` via a thin shim. */\n listAgentAdapters?: AgentAdapterLister\n /** Optional — MCP proxy registry. When wired, exposes\n * `/mcps/proxy/*` routes that let the browser drive imported MCPs\n * without going through the MCP wire protocol (useful for the\n * /providers/mcp page's \"Local\" tab). */\n mcpProxy?: McpProxyRegistry\n /** Per-boot bearer token. When set, mutating /sessions/* routes\n * + the /sessions/:id/pty WebSocket upgrade require either\n * `Authorization: Bearer <token>` or an `Origin` header that\n * matches `allowedOrigins`. Read-only routes (GET, SSE stream)\n * stay open since the CORS surface already restricts origins\n * enough for them. */\n token?: string\n /** Trusted browser origins. When a mutating request carries an\n * `Origin: <url>` header (browser-set, JS can't forge), and that\n * url is in this list, the request is allowed without a Bearer\n * token. Browsers can't read the daemon's runtime.json (mode 0600)\n * so they can't send the token — Origin-based auth lets a trusted\n * page (Guilde web UI, local dev) drive the daemon. Non-browser\n * callers (curl, the CLI) still use the token.\n *\n * Match policy: exact origin (`https://guilde.work`) OR prefix\n * with `:*` for any-port match (`http://localhost:*` matches\n * `http://localhost:3000`).\n *\n * Default (when undefined): localhost on any port is allowed via\n * `DEFAULT_ALLOWED_ORIGINS`. Production origins are opt-in via\n * `agentproto serve --allow-origin <url>`. Pair with `strictOrigins`\n * to remove the localhost defaults entirely. */\n allowedOrigins?: readonly string[]\n /** When true, skip the localhost-wildcard defaults — only the\n * explicit `allowedOrigins` list is honoured. Useful for daemons\n * on shared hosts or when the user wants to lock dev to a\n * specific port. Default false (current behaviour — any browser\n * on `localhost` is trusted). */\n strictOrigins?: boolean\n /** Whether `POST /sessions/terminal` + WS upgrade are advertised.\n * Reflects whether the host injected a PTY factory into the\n * SessionsRegistry. When false, the terminal HTTP route returns\n * 501 and the WS upgrade rejects. */\n ptyEnabled?: boolean\n /** Static fields surfaced via `/health`. */\n meta: {\n workspace: string\n registered: readonly string[]\n }\n}\n\nexport interface RuntimeHttpServerHandle {\n url: string\n stop(): Promise<void>\n}\n\nexport async function startHttpServer(\n opts: RuntimeHttpServerOptions,\n): Promise<RuntimeHttpServerHandle> {\n const startedAt = Date.now()\n const authSource: AuthSource = opts.auth ?? { mode: \"none\" }\n const readAuth = (): AuthOptions =>\n typeof authSource === \"function\" ? authSource() : authSource\n\n /**\n * Loopback bypass — requests originating from 127.0.0.1 / ::1 with\n * no `X-Forwarded-For` header skip the bearer check even when one is\n * configured. Rationale:\n *\n * 1. The bearer is meant to gate the *public tunnel*, not the\n * loopback socket. Without this, calling `remote_enable` from a\n * local MCP client immediately 401s that same local client —\n * the user locks themselves out and the only recovery is a\n * gateway restart. Hit this in real use; not a theoretical edge.\n *\n * 2. Cloudflared (and any reasonable tunnel) sets X-Forwarded-For\n * when forwarding a public request to the loopback origin. So\n * \"loopback AND no XFF\" is a tight characterisation of \"this\n * request never left the machine.\"\n *\n * 3. Local FS access already trumps bearer (the user can read\n * runtime.json, kill -9 the daemon, etc.). Adding another check\n * here doesn't raise the bar for someone with shell on the box.\n *\n * If your threat model is \"untrusted users on the same loopback\n * interface\" (unusual — usually a multi-tenant container scenario),\n * pass `auth: { mode: \"bearer\", … }` at startup instead of relying\n * on the controller's runtime flip; the auth getter will return the\n * stricter of the two and the bypass still applies (intentional —\n * the operator opted in to bearer with full knowledge of the trade).\n */\n function isLoopback(req: IncomingMessage): boolean {\n const addr = req.socket.remoteAddress ?? \"\"\n const isLocalAddr =\n addr === \"127.0.0.1\" || addr === \"::1\" || addr === \"::ffff:127.0.0.1\"\n if (!isLocalAddr) return false\n // X-Forwarded-For present ⇒ a tunnel is in front of us; the\n // request crossed the public internet to reach this socket.\n if (req.headers[\"x-forwarded-for\"]) return false\n return true\n }\n\n function authorize(req: IncomingMessage, res: ServerResponse): boolean {\n const auth = readAuth()\n if (auth.mode === \"none\") return true\n if (isLoopback(req)) return true\n const header = req.headers.authorization\n const expected = `Bearer ${auth.token}`\n if (header !== expected) {\n res.writeHead(401, { \"content-type\": \"application/json\" })\n res.end(JSON.stringify({ error: \"unauthorized\" }))\n return false\n }\n return true\n }\n\n /**\n * Per-boot auth gate for mutating /sessions/* routes and the WS\n * upgrade for /sessions/:id/pty. Accepts EITHER:\n *\n * 1. `Authorization: Bearer <token>` matching the per-boot token\n * (the CLI path — reads runtime.json mode 0600).\n * 2. A WS-upgrade query-string `?token=<token>` (browser\n * WebSocket can't set headers; some non-browser clients use\n * this too).\n * 3. An `Origin: <url>` header matching `allowedOrigins` — the\n * browser path. Origin is browser-set, JS can't forge.\n *\n * UNLIKE `authorize()`, this does NOT have a loopback bypass: the\n * threat we're defending against (browser drive-by spawning shells\n * via fetch to 127.0.0.1) IS loopback. Browsers can't read\n * runtime.json (mode 0600); a same-origin trusted page can rely on\n * its Origin instead.\n *\n * When `opts.token` is unset (older host integrations), this is a\n * no-op so existing call sites keep working.\n */\n function checkSessionsToken(req: IncomingMessage): \"ok\" | \"missing\" | \"bad\" {\n if (!opts.token) return \"ok\"\n\n // 1. Header bearer token.\n const header = req.headers.authorization\n const expected = `Bearer ${opts.token}`\n if (header === expected) return \"ok\"\n\n // 2. ?token=<token> in the URL (WS upgrade convenience).\n const urlStr = req.url ?? \"\"\n if (urlStr.includes(\"?\")) {\n const qs = new URLSearchParams(urlStr.slice(urlStr.indexOf(\"?\") + 1))\n const qsToken = qs.get(\"token\")\n if (qsToken && qsToken === opts.token) return \"ok\"\n }\n\n // 3. Origin allowlist (browser path).\n const origin = req.headers.origin\n if (typeof origin === \"string\" && originAllowed(origin)) return \"ok\"\n\n return header ? \"bad\" : \"missing\"\n }\n\n function originAllowed(origin: string): boolean {\n // Defaults are normally in effect — `opts.allowedOrigins` extends\n // them rather than replacing. Otherwise setting one production\n // origin via config silently locks out `http://localhost:*`,\n // breaking local dev. Users who genuinely want a curated list\n // (shared host, paranoid local-only ports) set `strictOrigins:true`\n // which drops the defaults entirely.\n const list = opts.strictOrigins\n ? (opts.allowedOrigins ?? [])\n : [...DEFAULT_ALLOWED_ORIGINS, ...(opts.allowedOrigins ?? [])]\n for (const pattern of list) {\n if (pattern === origin) return true\n // `http://localhost:*` style: match the host prefix, any port.\n if (pattern.endsWith(\":*\")) {\n const prefix = pattern.slice(0, -2) // drop \":*\"\n if (origin === prefix || origin.startsWith(prefix + \":\")) return true\n }\n }\n return false\n }\n\n function rejectUnauthorizedSession(\n req: IncomingMessage,\n res: ServerResponse,\n kind: \"missing\" | \"bad\",\n ): void {\n const origin = req.headers.origin ?? null\n const allowList = opts.strictOrigins\n ? (opts.allowedOrigins ?? [])\n : [...DEFAULT_ALLOWED_ORIGINS, ...(opts.allowedOrigins ?? [])]\n res.writeHead(401, { \"content-type\": \"application/json\" })\n const message =\n kind === \"missing\"\n ? origin\n ? `Origin \"${origin}\" not in the daemon's allowlist, and no Bearer token sent. ` +\n `Either add it (\\`agentproto config set daemon.allowedOrigins ${origin}\\` then restart the daemon), ` +\n `or send Authorization: Bearer <token> read from <workspace>/.agentproto/runtime.json.`\n : `Authorization: Bearer <token> required on mutating /sessions/* routes. ` +\n `Read the token from <workspace>/.agentproto/runtime.json. ` +\n `(Browser callers can use an Origin in the allowlist instead.)`\n : `Invalid bearer token. The daemon regenerated its token on its last boot — ` +\n `re-read <workspace>/.agentproto/runtime.json.`\n res.end(\n JSON.stringify({\n error: \"sessions_unauthorized\",\n message,\n // Debug data so a UI / network-tab inspection points the user\n // straight at the fix without needing the daemon's stderr.\n rejectedOrigin: origin,\n allowedOrigins: allowList,\n // We never echo the token; only the absence-or-presence flag.\n receivedAuthHeader: typeof req.headers.authorization === \"string\",\n }),\n )\n }\n\n /**\n * Returns true when this `path` + `method` is a mutating /sessions/*\n * route that should require the per-boot token. Kept narrow: GETs\n * (list, get, SSE stream) stay open for read-only telemetry from\n * existing tools that haven't learned about the token yet.\n */\n function isMutatingSessionsRoute(method: string, path: string): boolean {\n if (!path.startsWith(\"/sessions\")) return false\n if (method === \"POST\" || method === \"DELETE\" || method === \"PUT\" || method === \"PATCH\") {\n return true\n }\n return false\n }\n\n async function handleMcp(req: IncomingMessage, res: ServerResponse): Promise<void> {\n if (!authorize(req, res)) return\n // Per-request server + transport, per the SDK's stateless pattern.\n // Sharing either across requests breaks after the first one because\n // `Protocol.connect` rejects re-attachment.\n const server = await opts.mcpServerFactory()\n const transport = new StreamableHTTPServerTransport({\n sessionIdGenerator: undefined,\n })\n // `onerror` is an unofficial SDK hook — guard before assigning so\n // a future SDK rename doesn't silently drop transport error logs.\n const transportInternal = transport as unknown as Record<string, unknown>\n if (\"onerror\" in (transport as object)) {\n transportInternal[\"onerror\"] = (err: unknown) => {\n console.error(\"[mcp transport.onerror]\", err)\n }\n }\n\n res.on(\"close\", () => {\n void transport.close()\n void server.close()\n })\n\n try {\n await server.connect(transport)\n await transport.handleRequest(req, res)\n } catch (err) {\n console.error(\"[mcp] handleRequest threw:\", err)\n if (!res.headersSent) {\n res.writeHead(500, { \"content-type\": \"application/json\" })\n res.end(\n JSON.stringify({\n error: \"mcp_transport_failed\",\n message: err instanceof Error ? err.message : String(err),\n }),\n )\n }\n }\n }\n\n function handleHealth(_req: IncomingMessage, res: ServerResponse): void {\n res.writeHead(200, { \"content-type\": \"application/json\" })\n res.end(\n JSON.stringify({\n status: \"ok\",\n workspace: opts.meta.workspace,\n registered: opts.meta.registered,\n uptimeMs: Date.now() - startedAt,\n }),\n )\n }\n\n function handleEvents(req: IncomingMessage, res: ServerResponse): void {\n if (!authorize(req, res)) return\n res.writeHead(200, {\n \"content-type\": \"text/event-stream\",\n \"cache-control\": \"no-cache, no-transform\",\n connection: \"keep-alive\",\n })\n res.write(`: connected\\n\\n`)\n const off = opts.events.onAny((ev: RuntimeEvent) => {\n res.write(`data: ${JSON.stringify(ev)}\\n\\n`)\n })\n req.on(\"close\", off)\n }\n\n async function handleListConversations(\n req: IncomingMessage,\n res: ServerResponse,\n ): Promise<void> {\n if (!authorize(req, res)) return\n const list = await opts.conversations.list()\n res.writeHead(200, { \"content-type\": \"application/json\" })\n res.end(JSON.stringify(list))\n }\n\n async function handleGetConversation(\n req: IncomingMessage,\n res: ServerResponse,\n id: string,\n ): Promise<void> {\n if (!authorize(req, res)) return\n try {\n const data = await opts.conversations.read(id)\n res.writeHead(200, { \"content-type\": \"application/json\" })\n res.end(JSON.stringify(data))\n } catch (err) {\n res.writeHead(404, { \"content-type\": \"application/json\" })\n res.end(\n JSON.stringify({\n error: \"not_found\",\n message: err instanceof Error ? err.message : String(err),\n }),\n )\n }\n }\n\n async function handleHeartbeatTick(\n req: IncomingMessage,\n res: ServerResponse,\n ): Promise<void> {\n if (!authorize(req, res)) return\n await opts.heartbeat.fireNow()\n res.writeHead(202, { \"content-type\": \"application/json\" })\n res.end(JSON.stringify({ status: \"fired\" }))\n }\n\n /**\n * POST /files/upload?cwd=<abs-dir>&name=<filename>\n *\n * Writes the raw request body bytes to\n * `{cwd}/.agentproto-attachments/{safe-name}`, creating the\n * subdirectory on demand, and returns `{path}` with the absolute\n * path the agent CLI can read. Used by the host UI's terminal\n * drag-drop: the browser can't read the dragged file's source path\n * (security), so we copy the bytes to a known location and tell the\n * UI to paste THAT path into the terminal — claude-code (and any\n * CLI with a Read tool) picks it up natively.\n *\n * Gated by `checkSessionsToken` so a drive-by HTTP request can't\n * write arbitrary files: only sessions-authorized callers (CLI or\n * an allow-listed browser origin) can hit it.\n *\n * Hardening:\n * - `cwd` must be absolute and exist as a directory.\n * - `name` is basename-sanitized (no `/`, `..`, NULs).\n * - The resolved write target must stay within\n * `{cwd}/.agentproto-attachments/` (defense-in-depth in case the\n * name sanitizer ever drifts).\n * - Body capped at 32 MiB. Larger uploads error 413 instead of\n * filling the daemon's disk.\n */\n async function handleFileUpload(\n req: IncomingMessage,\n res: ServerResponse,\n url: string,\n ): Promise<void> {\n const reply = (status: number, body: unknown): void => {\n res.writeHead(status, { \"content-type\": \"application/json\" })\n res.end(JSON.stringify(body))\n }\n const qs = new URLSearchParams(url.includes(\"?\") ? url.slice(url.indexOf(\"?\") + 1) : \"\")\n const cwd = qs.get(\"cwd\")\n const rawName = qs.get(\"name\")\n if (!cwd || !rawName) {\n reply(400, { error: \"missing_cwd_or_name\" })\n return\n }\n if (!isAbsolute(cwd)) {\n reply(400, { error: \"cwd_not_absolute\" })\n return\n }\n // basename-style sanitize: strip path separators + parent refs +\n // NUL bytes; collapse leading dots so the file is visible. The\n // resolvePath check below catches anything this misses.\n const safeName = rawName\n .replace(/[\u0000/\\\\]/g, \"_\")\n .replace(/\\.\\.+/g, \".\")\n .replace(/^\\.+/, \"\")\n .slice(0, 200)\n if (safeName.length === 0) {\n reply(400, { error: \"invalid_name\" })\n return\n }\n try {\n const st = await stat(cwd)\n if (!st.isDirectory()) {\n reply(400, { error: \"cwd_not_a_directory\" })\n return\n }\n } catch {\n reply(400, { error: \"cwd_not_found\" })\n return\n }\n const dir = join(cwd, \".agentproto-attachments\")\n const target = resolvePath(dir, safeName)\n // Defense-in-depth: the sanitized name should never escape `dir`,\n // but if the sanitizer ever drifts, this catches the escape.\n if (!target.startsWith(resolvePath(dir) + (dir.endsWith(\"/\") ? \"\" : \"/\"))) {\n reply(400, { error: \"path_traversal_blocked\" })\n return\n }\n const MAX_BYTES = 32 * 1024 * 1024 // 32 MiB\n const chunks: Buffer[] = []\n let total = 0\n let aborted = false\n await new Promise<void>((resolveBody, rejectBody) => {\n req.on(\"data\", chunk => {\n if (aborted) return\n const buf = chunk as Buffer\n total += buf.length\n if (total > MAX_BYTES) {\n aborted = true\n reply(413, { error: \"file_too_large\", maxBytes: MAX_BYTES })\n rejectBody(new Error(\"too_large\"))\n return\n }\n chunks.push(buf)\n })\n req.on(\"end\", () => {\n if (!aborted) resolveBody()\n })\n req.on(\"error\", err => rejectBody(err))\n }).catch(() => undefined)\n if (aborted) return\n try {\n await mkdir(dir, { recursive: true })\n await writeFile(target, Buffer.concat(chunks))\n reply(200, { path: target, bytes: total })\n } catch (err) {\n reply(500, {\n error: \"write_failed\",\n message: err instanceof Error ? err.message : String(err),\n })\n }\n }\n\n // Permissive CORS for the loopback gateway. The Guilde web app\n // (localhost:3041) probes /health from the browser; without these\n // headers the browser blocks the response and the panel says\n // \"not reachable\" even though curl works. Auth still gates the\n // sensitive routes — this just lifts the cross-origin block.\n //\n // Private Network Access (Chrome 105+): when an HTTPS page like\n // https://guilde.work fetches a loopback URL, Chrome sends a\n // preflight with `Access-Control-Request-Private-Network: true`.\n // Without `Access-Control-Allow-Private-Network: true` in the\n // response, the browser blocks the actual GET. Mirror the flag\n // when the request asked for it.\n function applyCors(req: IncomingMessage, res: ServerResponse): void {\n const origin = (req.headers.origin as string | undefined) ?? \"*\"\n res.setHeader(\"Access-Control-Allow-Origin\", origin)\n res.setHeader(\"Vary\", \"Origin\")\n res.setHeader(\"Access-Control-Allow-Credentials\", \"true\")\n res.setHeader(\n \"Access-Control-Allow-Headers\",\n req.headers[\"access-control-request-headers\"] ??\n \"authorization,content-type,mcp-session-id\",\n )\n res.setHeader(\n \"Access-Control-Allow-Methods\",\n \"GET,POST,PUT,PATCH,DELETE,OPTIONS\",\n )\n if (req.headers[\"access-control-request-private-network\"] === \"true\") {\n res.setHeader(\"Access-Control-Allow-Private-Network\", \"true\")\n }\n }\n\n const server: Server = createServer((req, res) => {\n void (async () => {\n try {\n const url = req.url ?? \"/\"\n const path = url.split(\"?\")[0] ?? \"/\"\n // Diagnostic: emit forwarded requests (those carrying XFF) onto\n // the events stream so /events tailers can see what cloudflared\n // actually sends. Loopback-only traffic stays quiet to avoid\n // flooding subscribers during normal local use.\n if (req.headers[\"x-forwarded-for\"]) {\n opts.events.emit({\n type: \"remote-log\",\n at: new Date().toISOString(),\n line: `[http-in] ${req.method} ${url} host=${req.headers.host ?? \"?\"} xff=${String(req.headers[\"x-forwarded-for\"])}`,\n })\n }\n\n applyCors(req, res)\n if (req.method === \"OPTIONS\") {\n res.writeHead(204)\n res.end()\n return\n }\n\n if (path === \"/health\" && req.method === \"GET\") {\n handleHealth(req, res)\n return\n }\n if (path === \"/events\" && req.method === \"GET\") {\n handleEvents(req, res)\n return\n }\n if (path === \"/mcp\") {\n await handleMcp(req, res)\n return\n }\n if (path === \"/conversations\" && req.method === \"GET\") {\n await handleListConversations(req, res)\n return\n }\n if (path.startsWith(\"/conversations/\") && req.method === \"GET\") {\n const id = path.slice(\"/conversations/\".length)\n await handleGetConversation(req, res, id)\n return\n }\n if (path === \"/heartbeat/tick\" && req.method === \"POST\") {\n await handleHeartbeatTick(req, res)\n return\n }\n\n if (path === \"/files/upload\" && req.method === \"POST\") {\n // Same auth gate as the mutating /sessions/* routes — drive-by\n // HTTP shouldn't be able to write arbitrary files to disk.\n const gate = checkSessionsToken(req)\n if (gate !== \"ok\") {\n rejectUnauthorizedSession(req, res, gate)\n return\n }\n await handleFileUpload(req, res, url)\n return\n }\n\n // Sessions routes — only registered when the gateway was\n // built with a SessionsRegistry. /sessions, /sessions/:id,\n // /sessions/:id/stream (SSE), POST /sessions/:id/kill,\n // DELETE /sessions/:id (forget after exit).\n if (opts.sessions && path.startsWith(\"/sessions\")) {\n if (isMutatingSessionsRoute(req.method ?? \"GET\", path)) {\n const gate = checkSessionsToken(req)\n if (gate !== \"ok\") {\n rejectUnauthorizedSession(req, res, gate)\n return\n }\n }\n const handled = await handleSessions(\n req,\n res,\n path,\n opts.sessions,\n opts.resolveAgentAdapter,\n opts.ptyEnabled === true,\n )\n if (handled) return\n }\n\n if (path === \"/workspaces\" && req.method === \"GET\") {\n // Surface ~/.agentproto/workspaces.json for UIs that\n // want a workspace dropdown (spawn dialog, MCP discovery\n // grouping, etc.). Read-only; mutate via the CLI's\n // `agentproto workspace add/remove/use` verbs.\n try {\n const config = await loadWorkspacesConfig()\n res.writeHead(200, { \"content-type\": \"application/json\" })\n res.end(JSON.stringify(config))\n } catch (err) {\n res.writeHead(500, { \"content-type\": \"application/json\" })\n res.end(\n JSON.stringify({\n error: \"workspaces_load_failed\",\n message: err instanceof Error ? err.message : String(err),\n })\n )\n }\n return\n }\n\n if (path === \"/mcps/imports\" && req.method === \"GET\") {\n const config = await loadImportedMcps()\n res.writeHead(200, { \"content-type\": \"application/json\" })\n res.end(JSON.stringify(config))\n return\n }\n if (path === \"/mcps/imports\" && req.method === \"POST\") {\n const body = (await readJsonBody(req)) as {\n sourceMcpId?: string\n alias?: string\n } | null\n if (!body || typeof body.sourceMcpId !== \"string\") {\n res.writeHead(400, { \"content-type\": \"application/json\" })\n res.end(JSON.stringify({ error: \"missing_sourceMcpId\" }))\n return\n }\n const discovered = await discoverMcps()\n const snapshot = discovered.find(d => d.id === body.sourceMcpId)\n if (!snapshot) {\n res.writeHead(404, { \"content-type\": \"application/json\" })\n res.end(\n JSON.stringify({\n error: \"discovered_mcp_not_found\",\n sourceMcpId: body.sourceMcpId,\n })\n )\n return\n }\n const cfg = await loadImportedMcps()\n const next = addImport(cfg, {\n snapshot,\n ...(body.alias ? { alias: body.alias } : {}),\n })\n await saveImportedMcps(next)\n res.writeHead(201, { \"content-type\": \"application/json\" })\n res.end(JSON.stringify(next.imports.find(e => e.id === snapshot.id)))\n return\n }\n const importMatch = path.match(/^\\/mcps\\/imports\\/(.+)$/)\n if (importMatch && req.method === \"DELETE\") {\n // The id is URL-encoded since it contains colons + slashes\n // (e.g. claude-code:project:/path:name).\n const id = decodeURIComponent(importMatch[1] ?? \"\")\n const cfg = await loadImportedMcps()\n if (!cfg.imports.some(e => e.id === id)) {\n res.writeHead(404, { \"content-type\": \"application/json\" })\n res.end(JSON.stringify({ error: \"import_not_found\", id }))\n return\n }\n await saveImportedMcps(removeImport(cfg, id))\n res.writeHead(200, { \"content-type\": \"application/json\" })\n res.end(JSON.stringify({ ok: true, id }))\n return\n }\n\n if (path === \"/mcps/discovered\" && req.method === \"GET\") {\n // No host wiring needed — the scanner reads\n // ~/.claude.json + ~/.cursor/mcp.json + goose config\n // directly. Always available; cheap (~5ms typical).\n try {\n const mcps = await discoverMcps()\n res.writeHead(200, { \"content-type\": \"application/json\" })\n res.end(JSON.stringify({ mcps }))\n } catch (err) {\n res.writeHead(500, { \"content-type\": \"application/json\" })\n res.end(\n JSON.stringify({\n error: \"discovery_failed\",\n message: err instanceof Error ? err.message : String(err),\n })\n )\n }\n return\n }\n\n // Browser-friendly proxy surface — same operations the MCP\n // tools expose (mcp_imported_status / list_tools / call) but\n // over plain HTTP so the /providers/mcp page can render them\n // without embedding an MCP client.\n if (path === \"/mcps/proxy/status\" && req.method === \"GET\") {\n if (!opts.mcpProxy) {\n res.writeHead(501, { \"content-type\": \"application/json\" })\n res.end(JSON.stringify({ error: \"mcp_proxy_not_configured\" }))\n return\n }\n try {\n const imports = await opts.mcpProxy.listAliases()\n res.writeHead(200, { \"content-type\": \"application/json\" })\n res.end(JSON.stringify({ imports }))\n } catch (err) {\n res.writeHead(500, { \"content-type\": \"application/json\" })\n res.end(\n JSON.stringify({\n error: \"proxy_status_failed\",\n message: err instanceof Error ? err.message : String(err),\n })\n )\n }\n return\n }\n const proxyToolsMatch = path.match(/^\\/mcps\\/proxy\\/tools\\/(.+)$/)\n if (proxyToolsMatch && req.method === \"GET\") {\n if (!opts.mcpProxy) {\n res.writeHead(501, { \"content-type\": \"application/json\" })\n res.end(JSON.stringify({ error: \"mcp_proxy_not_configured\" }))\n return\n }\n const alias = decodeURIComponent(proxyToolsMatch[1] ?? \"\")\n const out = await opts.mcpProxy.listTools(alias)\n res.writeHead(out.ok ? 200 : 502, {\n \"content-type\": \"application/json\",\n })\n res.end(JSON.stringify(out))\n return\n }\n if (path === \"/mcps/proxy/call\" && req.method === \"POST\") {\n if (!opts.mcpProxy) {\n res.writeHead(501, { \"content-type\": \"application/json\" })\n res.end(JSON.stringify({ error: \"mcp_proxy_not_configured\" }))\n return\n }\n const body = (await readJsonBody(req)) as {\n alias?: unknown\n toolName?: unknown\n args?: unknown\n } | null\n if (\n !body ||\n typeof body.alias !== \"string\" ||\n typeof body.toolName !== \"string\"\n ) {\n res.writeHead(400, { \"content-type\": \"application/json\" })\n res.end(\n JSON.stringify({\n error: \"invalid_body\",\n message: \"expected { alias, toolName, args? }\",\n })\n )\n return\n }\n const result = await opts.mcpProxy.callTool(\n body.alias,\n body.toolName,\n body.args ?? {}\n )\n res.writeHead(result.ok ? 200 : 502, {\n \"content-type\": \"application/json\",\n })\n res.end(JSON.stringify(result))\n return\n }\n\n if (path === \"/adapters\" && req.method === \"GET\") {\n if (!opts.listAgentAdapters) {\n res.writeHead(501, { \"content-type\": \"application/json\" })\n res.end(\n JSON.stringify({\n error: \"lister_not_configured\",\n message:\n \"Daemon was started without `listAgentAdapters` — see \" +\n \"@agentproto/cli's `listInstalledAdapters` for the canonical impl.\",\n })\n )\n return\n }\n try {\n const adapters = await opts.listAgentAdapters()\n res.writeHead(200, { \"content-type\": \"application/json\" })\n res.end(JSON.stringify({ adapters }))\n } catch (err) {\n res.writeHead(500, { \"content-type\": \"application/json\" })\n res.end(\n JSON.stringify({\n error: \"list_failed\",\n message: err instanceof Error ? err.message : String(err),\n })\n )\n }\n return\n }\n\n res.writeHead(404, { \"content-type\": \"application/json\" })\n res.end(JSON.stringify({ error: \"not_found\", path }))\n } catch (err) {\n if (!res.headersSent) {\n res.writeHead(500, { \"content-type\": \"application/json\" })\n res.end(\n JSON.stringify({\n error: \"internal_error\",\n message: err instanceof Error ? err.message : String(err),\n }),\n )\n }\n }\n })()\n })\n\n // ── WebSocket upgrade: /sessions/:id/pty ──\n // Single WSS bound to the HTTP server's `upgrade` event. Connections\n // are accepted only when the SessionsRegistry is wired AND PTY\n // support is advertised. Frames are JSON-encoded over text WS\n // messages (binary mode is a future optimization — JSON keeps\n // wireshark/devtools debuggable):\n // server → client: {kind:\"data\", b64:\"...\"}\n // server → client: {kind:\"exit\", exitCode:0, signal?:1}\n // client → server: {kind:\"input\", b64:\"...\"} (or {kind:\"input\", text:\"...\"})\n // client → server: {kind:\"resize\", cols:80, rows:24}\n // client → server: {kind:\"ping\"} (no-op keepalive)\n const wss = new WebSocketServer({ noServer: true })\n server.on(\"upgrade\", (req, socket, head) => {\n const url = req.url ?? \"/\"\n const path = url.split(\"?\")[0] ?? \"/\"\n const ptyMatch = path.match(/^\\/sessions\\/([^/]+)\\/pty$/)\n if (!ptyMatch) {\n socket.destroy()\n return\n }\n if (!opts.sessions || opts.ptyEnabled !== true) {\n rejectUpgrade(socket, 501, \"pty_not_configured\")\n return\n }\n // Per-boot token gate, no loopback bypass — see comment on\n // checkSessionsToken for why.\n const gate = checkSessionsToken(req)\n if (gate !== \"ok\") {\n rejectUpgrade(socket, 401, gate === \"missing\" ? \"missing_token\" : \"bad_token\")\n return\n }\n const id = ptyMatch[1]\n if (!id) {\n rejectUpgrade(socket, 400, \"missing_id\")\n return\n }\n // Resolve id-or-name BEFORE upgrading so a typo returns a clean\n // 404 instead of a successful WS that immediately closes.\n const desc = opts.sessions.findByIdOrName(id)\n if (!desc) {\n rejectUpgrade(socket, 404, \"session_not_found\")\n return\n }\n if (desc.pty !== true) {\n rejectUpgrade(socket, 400, \"session_not_pty\")\n return\n }\n // A descriptor for an exited/killed/error session lives on as\n // history — its PTY child is gone. Reject the upgrade with a\n // clear reason so the CLI/web client can suggest `restart`\n // instead of letting the user see a generic 1011 mid-attach.\n if (\n desc.status === \"exited\" ||\n desc.status === \"killed\" ||\n desc.status === \"error\"\n ) {\n rejectUpgrade(\n socket,\n 410,\n `session_${desc.status}`,\n `Session ${desc.id}${desc.name ? ` (${desc.name})` : \"\"} has ${desc.status}. ` +\n `Spawn a fresh one with: agentproto sessions restart ${desc.name ?? desc.id}`,\n )\n return\n }\n wss.handleUpgrade(req, socket, head, ws => {\n handlePtyWebSocket(ws, req, desc.id, opts.sessions!)\n })\n })\n\n const bind = opts.bind ?? \"127.0.0.1\"\n await new Promise<void>((resolve, reject) => {\n server.once(\"error\", reject)\n server.listen(opts.port, bind, () => resolve())\n })\n\n return {\n url: `http://${bind}:${opts.port}`,\n async stop() {\n // Per-request transports/servers are torn down on `res.close`,\n // so we only need to stop the HTTP listener here. The WSS is\n // bound `noServer:true` so closing the HTTP server also tears\n // down its underlying TCP socket; live WS connections receive\n // a close frame from the kernel.\n wss.close()\n await new Promise<void>((resolve) => server.close(() => resolve()))\n },\n }\n}\n\n/**\n * Reject an HTTP upgrade attempt with a structured plaintext body.\n * `ws.handleUpgrade` is meant to be the success path — if we can't\n * accept the upgrade we write a minimal HTTP response and destroy\n * the socket, matching ws's own internal error path.\n */\nfunction rejectUpgrade(\n socket: Duplex,\n status: number,\n reason: string,\n message?: string,\n): void {\n const reasonText = `${status} ${reason}`\n const body: { error: string; message?: string } = { error: reason }\n if (message) body.message = message\n try {\n socket.write(\n `HTTP/1.1 ${reasonText}\\r\\n` +\n `Content-Type: application/json\\r\\n` +\n `Connection: close\\r\\n\\r\\n` +\n JSON.stringify(body) +\n `\\n`,\n )\n } catch {\n // socket already gone — fall through\n }\n socket.destroy()\n}\n\n/**\n * Per-connection WS handler for /sessions/:id/pty. Attaches as a\n * subscriber to the SessionsRegistry; bridges JSON frames in both\n * directions. Per-subscriber backpressure: if the WS's `bufferedAmount`\n * exceeds a threshold, the next chunk is dropped (slow client must\n * not stall the daemon's fan-out to other subscribers).\n */\nfunction handlePtyWebSocket(\n ws: WebSocket,\n req: IncomingMessage,\n sessionId: string,\n registry: SessionsRegistry,\n): void {\n // Parse cols/rows from the query string for the initial dimension\n // hint. Real clients will send a {kind:\"resize\"} immediately after\n // connecting; this seeds the registry's min-size calculation so the\n // first replay frames render at a sensible width if no resize comes.\n const query = new URLSearchParams(\n (req.url ?? \"\").includes(\"?\") ? (req.url ?? \"\").split(\"?\")[1] : \"\",\n )\n const cols = clampPositiveInt(query.get(\"cols\"), 80)\n const rows = clampPositiveInt(query.get(\"rows\"), 24)\n\n // Backpressure threshold — when the socket has more than 256 KiB\n // queued, drop the next data frame for THIS subscriber rather than\n // letting the registry block on send. Other subscribers stay live.\n const BACKPRESSURE_BYTES = 256 * 1024\n\n const handle = registry.attachPty(\n sessionId,\n { cols, rows },\n chunk => {\n if (ws.readyState !== ws.OPEN) return\n if (ws.bufferedAmount > BACKPRESSURE_BYTES) return // drop\n ws.send(\n JSON.stringify({ kind: \"data\", b64: chunk.toString(\"base64\") }),\n )\n },\n evt => {\n if (ws.readyState !== ws.OPEN) return\n ws.send(\n JSON.stringify({\n kind: \"exit\",\n exitCode: evt.exitCode,\n ...(evt.signal != null ? { signal: evt.signal } : {}),\n }),\n )\n // Close ourselves once we've emitted exit — the session can be\n // reattached for a buffer replay but this socket is done.\n try {\n ws.close(1000, \"session exited\")\n } catch {\n // ignore\n }\n },\n )\n\n if (!handle) {\n // Race: the session may have vanished between the upgrade and\n // attach. Close politely.\n try {\n ws.close(1011, \"session not attachable\")\n } catch {\n // ignore\n }\n return\n }\n\n ws.on(\"message\", (raw, isBinary) => {\n if (isBinary) {\n // Binary frames not supported yet — wire format is JSON-only.\n return\n }\n let frame: unknown\n try {\n frame = JSON.parse(raw.toString(\"utf8\"))\n } catch {\n return // malformed\n }\n if (!frame || typeof frame !== \"object\") return\n const f = frame as Record<string, unknown>\n switch (f.kind) {\n case \"input\": {\n // Accept either {text} (UTF-8) or {b64} (arbitrary bytes,\n // useful for clients sending raw key sequences).\n if (typeof f.text === \"string\") {\n handle.write(f.text)\n } else if (typeof f.b64 === \"string\") {\n try {\n handle.write(Buffer.from(f.b64, \"base64\").toString(\"utf8\"))\n } catch {\n // ignore malformed base64\n }\n }\n break\n }\n case \"resize\": {\n const c =\n typeof f.cols === \"number\" && f.cols > 0 ? Math.floor(f.cols) : null\n const r =\n typeof f.rows === \"number\" && f.rows > 0 ? Math.floor(f.rows) : null\n if (c && r) handle.resize(c, r)\n break\n }\n case \"ping\":\n // Reply with pong so client keepalive logic works. Optional.\n try {\n ws.send(JSON.stringify({ kind: \"pong\" }))\n } catch {\n // ignore\n }\n break\n // Unknown kinds silently dropped; reserved for forward compat.\n }\n })\n\n ws.on(\"close\", () => {\n handle.detach()\n })\n ws.on(\"error\", () => {\n handle.detach()\n })\n}\n\nfunction clampPositiveInt(raw: string | null, fallback: number): number {\n if (!raw) return fallback\n const n = Number.parseInt(raw, 10)\n return Number.isFinite(n) && n > 0 ? n : fallback\n}\n\nfunction clampInt(\n raw: string | null,\n fallback: number,\n min: number,\n max: number,\n): number {\n if (!raw) return fallback\n const n = Number.parseInt(raw, 10)\n if (!Number.isFinite(n)) return fallback\n if (n < min) return min\n if (n > max) return max\n return n\n}\n\n/**\n * /sessions routes — split out of the main switch so the surface\n * stays scannable. Returns `true` when it handled the request, so\n * the dispatcher knows to skip the 404 path.\n *\n * GET /sessions → list of SessionDescriptor[]\n * GET /sessions/:id → one SessionDescriptor\n * GET /sessions/:id/stream → SSE stream {line,stream} events\n * POST /sessions/:id/kill → SIGTERM, returns {ok}\n * DELETE /sessions/:id → forget (drop from registry; only\n * valid for exited/killed/error)\n */\nasync function handleSessions(\n req: IncomingMessage,\n res: ServerResponse,\n path: string,\n registry: SessionsRegistry,\n resolveAgentAdapter?: AgentAdapterResolver,\n ptyEnabled = false,\n): Promise<boolean> {\n const json = (status: number, body: unknown): void => {\n res.writeHead(status, { \"content-type\": \"application/json\" })\n res.end(JSON.stringify(body))\n }\n\n if (path === \"/sessions\" && req.method === \"GET\") {\n json(200, { sessions: registry.list() })\n return true\n }\n\n // Long-running agent session — spawn via the cli's adapter\n // resolver, hold across multiple turns. Body shape:\n // {adapter: \"claude-code\"|\"hermes\"|...,\n // workspaceSlug, cwd, prompt?, label?}\n if (path === \"/sessions/agent\" && req.method === \"POST\") {\n if (!resolveAgentAdapter) {\n json(501, {\n error: \"agent_resolver_not_configured\",\n message:\n \"POST /sessions/agent needs the host to inject `resolveAgentAdapter` \" +\n \"(e.g. via @agentproto/cli's resolveAdapter shim).\",\n })\n return true\n }\n const body = await readJsonBody(req)\n if (!body || typeof body !== \"object\") {\n json(400, { error: \"invalid_body\" })\n return true\n }\n const b = body as Record<string, unknown>\n const adapter = typeof b.adapter === \"string\" ? b.adapter : \"\"\n if (!adapter) {\n json(400, { error: \"missing_adapter\" })\n return true\n }\n // cwd resolution priority:\n // 1. explicit `cwd` in the body\n // 2. lookup `workspaceSlug` in ~/.agentproto/workspaces.json\n // 3. active workspace from the same config\n // 4. process.cwd() (last resort, almost certainly not what\n // the user wants — log it so the operator notices)\n let cwd: string | null =\n typeof b.cwd === \"string\" && b.cwd.length > 0 ? b.cwd : null\n let workspaceSlug =\n typeof b.workspaceSlug === \"string\" ? b.workspaceSlug : \"\"\n if (!cwd) {\n try {\n const config = await loadWorkspacesConfig()\n const ws = workspaceSlug\n ? findWorkspace(config, workspaceSlug)\n : getActiveWorkspace(config)\n if (ws) {\n cwd = ws.path\n workspaceSlug = ws.slug\n }\n } catch {\n // Config missing / unreadable — fall through to process.cwd()\n }\n }\n if (!cwd) {\n cwd = process.cwd()\n console.warn(\n `[/sessions/agent] no cwd resolvable for adapter=${adapter} ` +\n `(no body.cwd, no workspaceSlug match in ~/.agentproto/workspaces.json, ` +\n `no active workspace) — falling back to daemon's cwd ${cwd}`\n )\n }\n if (!workspaceSlug) workspaceSlug = \"default\"\n const resolved = await resolveAgentAdapter(adapter)\n if (!resolved) {\n json(404, { error: \"adapter_not_found\", adapter })\n return true\n }\n try {\n const resumeSessionId =\n typeof b.resumeSessionId === \"string\" && b.resumeSessionId.length > 0\n ? b.resumeSessionId\n : undefined\n const agentSession = await resolved.startSession({\n cwd,\n ...(resumeSessionId ? { resumeSessionId } : {}),\n })\n const desc = registry.spawnAgent({\n workspaceSlug,\n cwd,\n agentSession,\n adapterSlug: adapter,\n ...(typeof b.prompt === \"string\" ? { initialPrompt: b.prompt } : {}),\n ...(typeof b.label === \"string\" ? { label: b.label } : {}),\n ...(resolved.commandPreview\n ? { commandPreview: resolved.commandPreview }\n : {}),\n })\n json(201, desc)\n } catch (err) {\n json(500, {\n error: \"agent_spawn_failed\",\n message: err instanceof Error ? err.message : String(err),\n })\n }\n return true\n }\n\n // Long-running PTY session — spawn argv under node-pty. Bytes flow\n // through the registry's byte ring buffer; attach via the WebSocket\n // upgrade at /sessions/:id/pty. Body shape:\n // {argv: string[], cwd?, workspaceSlug?, cols, rows, env?, name?, label?}\n if (path === \"/sessions/terminal\" && req.method === \"POST\") {\n if (!ptyEnabled) {\n json(501, {\n error: \"pty_not_configured\",\n message:\n \"POST /sessions/terminal needs the host to inject `spawnPty` into createGateway \" +\n \"(node-pty optional dep — install in @agentproto/cli).\",\n })\n return true\n }\n const body = await readJsonBody(req)\n if (!body || typeof body !== \"object\") {\n json(400, { error: \"invalid_body\" })\n return true\n }\n const b = body as Record<string, unknown>\n const argv = Array.isArray(b.argv)\n ? (b.argv as unknown[]).filter((v): v is string => typeof v === \"string\")\n : []\n if (argv.length === 0) {\n json(400, { error: \"missing_argv\" })\n return true\n }\n const cols = typeof b.cols === \"number\" && b.cols > 0 ? Math.floor(b.cols) : 80\n const rows = typeof b.rows === \"number\" && b.rows > 0 ? Math.floor(b.rows) : 24\n // cwd resolution mirrors /sessions/agent exactly.\n let cwd: string | null =\n typeof b.cwd === \"string\" && b.cwd.length > 0 ? b.cwd : null\n let workspaceSlug =\n typeof b.workspaceSlug === \"string\" ? b.workspaceSlug : \"\"\n if (!cwd) {\n try {\n const config = await loadWorkspacesConfig()\n const ws = workspaceSlug\n ? findWorkspace(config, workspaceSlug)\n : getActiveWorkspace(config)\n if (ws) {\n cwd = ws.path\n workspaceSlug = ws.slug\n }\n } catch {\n // fall through to process.cwd()\n }\n }\n if (!cwd) {\n cwd = process.cwd()\n console.warn(\n `[/sessions/terminal] no cwd resolvable for argv=${argv.join(\" \")} ` +\n `— falling back to daemon's cwd ${cwd}`\n )\n }\n if (!workspaceSlug) workspaceSlug = \"default\"\n try {\n const desc = registry.spawnPty({\n argv,\n cwd,\n workspaceSlug,\n cols,\n rows,\n ...(b.env && typeof b.env === \"object\"\n ? { env: b.env as Record<string, string> }\n : {}),\n ...(typeof b.name === \"string\" ? { name: b.name } : {}),\n ...(typeof b.label === \"string\" ? { label: b.label } : {}),\n })\n json(201, desc)\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err)\n const status = msg.includes(\"already in use\")\n ? 409\n : msg.includes(\"no PTY factory\")\n ? 501\n : 500\n json(status, { error: \"pty_spawn_failed\", message: msg })\n }\n return true\n }\n\n // Send a follow-up turn to a live agent session.\n // Body: { prompt: string | ContentBlock | ContentBlock[] }\n // - string → auto-wrapped to a single text block by\n // the registry (legacy / convenience).\n // - ContentBlock → e.g. `{type:\"image\", source:{...}}`\n // - ContentBlock[] → text + image mix for multimodal turns.\n // Forwarded as-is to `agentSession.send`\n // so the adapter (claude-agent-acp, …)\n // negotiates its own content shape.\n //\n // Validation is intentionally loose — we accept anything object-\n // shaped + non-empty arrays + non-empty strings. The adapter will\n // reject ill-formed blocks with a clear error projected into the\n // session's ring buffer; throwing here would just duplicate that.\n //\n // Query: ?wait=false → fire-and-forget (return 202 after sync\n // validation; output streams via /sessions/:id/stream). Default\n // wait=true keeps the call blocking until the turn drains, which\n // is what curl scripts + the MCP bridge expect.\n const promptMatch = path.match(/^\\/sessions\\/([^/]+)\\/prompt$/)\n if (promptMatch && req.method === \"POST\") {\n const id = promptMatch[1]\n if (!id) return false\n const body = await readJsonBody(req)\n const prompt = (body as { prompt?: unknown } | null)?.prompt\n const validPrompt =\n (typeof prompt === \"string\" && prompt.length > 0) ||\n (Array.isArray(prompt) &&\n prompt.length > 0 &&\n prompt.every(b => b !== null && typeof b === \"object\")) ||\n (prompt !== null && typeof prompt === \"object\" && !Array.isArray(prompt))\n if (!validPrompt) {\n json(400, {\n error: \"missing_prompt\",\n message:\n \"Body `prompt` must be a non-empty string, a content block object, or an array of content blocks.\",\n })\n return true\n }\n const reqUrl = req.url ?? \"\"\n const queryString = reqUrl.includes(\"?\")\n ? reqUrl.slice(reqUrl.indexOf(\"?\") + 1)\n : \"\"\n const wait = new URLSearchParams(queryString).get(\"wait\")\n const fireAndForget = wait === \"false\" || wait === \"0\"\n try {\n if (fireAndForget) {\n registry.enqueuePrompt(id, prompt)\n json(202, { ok: true, id, queued: true })\n } else {\n await registry.sendPrompt(id, prompt)\n json(200, { ok: true, id })\n }\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err)\n // Differentiate \"not found\" / \"wrong kind\" / \"busy\" — they\n // surface as readable thrown messages from the registry.\n const status = msg.includes(\"no session\")\n ? 404\n : msg.includes(\"not an agent\")\n ? 400\n : msg.includes(\"mid-turn\")\n ? 409\n : 500\n json(status, { error: \"send_prompt_failed\", message: msg })\n }\n return true\n }\n\n if (path === \"/sessions\" && req.method === \"POST\") {\n const body = await readJsonBody(req)\n if (!body || typeof body !== \"object\") {\n json(400, { error: \"invalid_body\" })\n return true\n }\n const b = body as Record<string, unknown>\n const argv = Array.isArray(b.argv)\n ? (b.argv as unknown[]).filter((v): v is string => typeof v === \"string\")\n : []\n if (argv.length === 0) {\n json(400, { error: \"missing_argv\" })\n return true\n }\n try {\n const desc = registry.spawn({\n kind:\n b.kind === \"terminal\" || b.kind === \"agent-cli\" || b.kind === \"command\"\n ? b.kind\n : \"command\",\n workspaceSlug:\n typeof b.workspaceSlug === \"string\" ? b.workspaceSlug : \"default\",\n cwd: typeof b.cwd === \"string\" ? b.cwd : process.cwd(),\n argv,\n env:\n b.env && typeof b.env === \"object\"\n ? (b.env as Record<string, string>)\n : undefined,\n label: typeof b.label === \"string\" ? b.label : undefined,\n })\n json(201, desc)\n } catch (err) {\n json(500, {\n error: \"spawn_failed\",\n message: err instanceof Error ? err.message : String(err),\n })\n }\n return true\n }\n\n // Per-id routes. The `:id` slot also accepts a session's `name`\n // when one was set at spawn time — `findByIdOrName` resolves both\n // and the rest of the handler operates on the canonical id.\n const idMatch = path.match(\n /^\\/sessions\\/([^/]+)(\\/stream|\\/kill|\\/preview)?$/,\n )\n if (!idMatch) return false\n const [, rawIdOrName, suffix] = idMatch\n if (!rawIdOrName) return false\n const resolvedDesc = registry.findByIdOrName(rawIdOrName)\n const id = resolvedDesc?.id ?? rawIdOrName\n\n if (suffix === \"/preview\" && req.method === \"GET\") {\n // Read-only snapshot of the recent ring buffer — used by the\n // dashboard's detail pane so the user sees what the session was\n // doing without committing to an attach. Returns BOTH lines\n // (for agent-cli/command sessions) and recent-bytes (for PTY).\n // Caller picks whichever is populated.\n if (!resolvedDesc) {\n json(404, { error: \"session_not_found\", id: rawIdOrName })\n return true\n }\n const reqUrl = req.url ?? \"\"\n const qs = new URLSearchParams(\n reqUrl.includes(\"?\") ? reqUrl.slice(reqUrl.indexOf(\"?\") + 1) : \"\",\n )\n const lineCap = clampInt(qs.get(\"lines\"), 10, 1, 200)\n const byteCap = clampInt(qs.get(\"bytes\"), 16 * 1024, 256, 64 * 1024)\n // No registry method exists for \"give me the recent buffer\n // snapshot\" — readTerminalOutput is the closest. For non-PTY\n // sessions, attach with a no-op subscriber, read backfill,\n // detach. Cheap; the backfill is synchronous on attach.\n const lines: string[] = []\n if (resolvedDesc.pty !== true) {\n const unsub = registry.attach(id, line => {\n lines.push(line)\n })\n if (unsub) unsub()\n }\n const bufBytes = registry.readTerminalOutput(id, byteCap)\n json(200, {\n id: resolvedDesc.id,\n lines: lines.slice(-lineCap),\n bytes: bufBytes ? bufBytes.toString(\"base64\") : null,\n })\n return true\n }\n\n if (suffix === \"/stream\" && req.method === \"GET\") {\n if (!resolvedDesc) {\n json(404, { error: \"session_not_found\", id: rawIdOrName })\n return true\n }\n res.writeHead(200, {\n \"content-type\": \"text/event-stream\",\n \"cache-control\": \"no-cache\",\n connection: \"keep-alive\",\n })\n // Keep-alive ping every 25s — proxies / browsers eventually\n // close idle SSE connections; the comment line keeps the pipe\n // warm without confusing the EventSource parser (it ignores\n // anything starting with `:`).\n const ping = setInterval(() => {\n try {\n res.write(`: keep-alive\\n\\n`)\n } catch {\n clearInterval(ping)\n }\n }, 25_000)\n const unsub = registry.attach(id, (line, stream) => {\n try {\n res.write(\n `data: ${JSON.stringify({ line, stream })}\\n\\n`\n )\n } catch {\n // Client gone — cleanup happens on `close`.\n }\n })\n if (!unsub) {\n clearInterval(ping)\n res.end()\n return true\n }\n req.once(\"close\", () => {\n unsub()\n clearInterval(ping)\n })\n return true\n }\n\n if (suffix === \"/kill\" && req.method === \"POST\") {\n const ok = registry.kill(id)\n json(ok ? 200 : 404, { ok, id })\n return true\n }\n\n if (!suffix && req.method === \"GET\") {\n if (!resolvedDesc) {\n json(404, { error: \"session_not_found\", id: rawIdOrName })\n return true\n }\n json(200, resolvedDesc)\n return true\n }\n\n if (!suffix && req.method === \"DELETE\") {\n const ok = registry.forget(id)\n json(ok ? 200 : 404, { ok, id })\n return true\n }\n\n return false\n}\n\nasync function readJsonBody(req: IncomingMessage): Promise<unknown> {\n const chunks: Buffer[] = []\n for await (const chunk of req) {\n chunks.push(typeof chunk === \"string\" ? Buffer.from(chunk) : chunk)\n }\n if (chunks.length === 0) return null\n try {\n return JSON.parse(Buffer.concat(chunks).toString(\"utf8\"))\n } catch {\n return null\n }\n}\n","/**\n * Per-adapter resume strategies — the daemon's view of \"how do I\n * continue a previous session for THIS adapter?\".\n *\n * The driver already has an `AgentCliContinuation` declaration in\n * the adapter manifest (AIP-45). That covers strategy NAMES\n * (`native-resume`, `pinned-session`, `transcript`, `none`) but is\n * silent on the mechanics that live OUTSIDE the runtime — like\n * \"where on disk does this adapter store its conversations?\" or\n * \"what argv do I pass to resume into PTY mode?\".\n *\n * This table is that practical bridge. Each entry declares three\n * optional hooks:\n *\n * outputHint regex matched against each output line; group 1 is\n * the resume id. Stored as `desc.resumeMetadata[storeAs]`.\n * fsProbe async function that probes a per-adapter directory\n * for a stored session id, scoped to a workspace cwd.\n * Used when `outputHint` never matched.\n * spawnArgs given a captured id, returns the argv to spawn a\n * PTY that resumes the session. agentproto then\n * bypasses ACP/agent-cli and runs the provider\n * directly — the most reliable resume path because\n * it leans on the provider's native UX.\n *\n * Adapters that don't declare anything here fall back to:\n * 1. ACP-level resume via `resumeSessionId` on POST /sessions/agent\n * 2. Fresh spawn (same shape, no continuity)\n *\n * Eventually each adapter should ship its own strategy on\n * `AgentCliHandle.resumeStrategy` (driver-side). This central table\n * is the bootstrap: it lets a new adapter become resume-capable\n * without bumping its npm package; once that lands, entries\n * graduate into the adapter packages.\n */\n\nimport { promises as fs } from \"node:fs\"\nimport { homedir } from \"node:os\"\nimport { join, resolve } from \"node:path\"\n\n/** Where on disk the resume id ends up on the session descriptor. */\nexport type ResumeMetadataKey =\n | \"claudeResumeId\"\n | \"hermesResumeId\"\n | \"codexResumeId\"\n | \"openClawResumeId\"\n | \"openCodeResumeId\"\n\nexport interface ResumeStrategy {\n /** When set, run on every output line for this adapter. Group 1\n * captures the resume id. The match is saved on the descriptor\n * as `resumeMetadata[storeAs]`. */\n outputHint?: RegExp\n /** Where the matched id is recorded on the descriptor. */\n storeAs: ResumeMetadataKey\n /** Probe the adapter's on-disk session store for the most-recently\n * modified session in the given workspace. Returns the resume id\n * or null when nothing eligible. Files older than `prevStartedAt`\n * are ignored (avoids resuming an unrelated prior conversation).\n *\n * Skip when the adapter doesn't persist sessions externally. */\n fsProbe?(cwd: string, prevStartedAt: string): Promise<string | null>\n /** Return the argv to spawn a PTY that resumes into the given id.\n * When omitted, the daemon falls back to ACP-level resume via\n * the agent-cli protocol instead of the provider's native CLI. */\n spawnArgs?(id: string): string[]\n}\n\nexport const RESUME_STRATEGIES: Record<string, ResumeStrategy> = {\n \"claude-code\": {\n // Printed by claude on graceful exit when session persistence\n // is on (default). Example: `claude --resume 0e483f81-1a44-4bec-9667-b37158450296`\n outputHint: /claude\\s+--resume\\s+([0-9a-f-]{8,})/i,\n storeAs: \"claudeResumeId\",\n fsProbe: probeMtimeLatestJsonl(\".claude/projects\"),\n spawnArgs: id => [\"claude\", \"--resume\", id],\n },\n\n // Stubs for other shipped adapters — fill in as we learn each\n // provider's resume mechanism. Today they fall back to ACP-level\n // resume (whatever the agent-cli runtime supports) or fresh spawn.\n //\n // hermes: { storeAs: \"hermesResumeId\", ... }\n // codex: { storeAs: \"codexResumeId\", ... }\n // openclaw: { storeAs: \"openClawResumeId\", ... }\n // opencode: { storeAs: \"openCodeResumeId\", ... }\n}\n\n/**\n * Build an `fsProbe` for adapters that store one `.jsonl` per session\n * inside `~/<storeRel>/<cwd-encoded>/`. The encoded cwd is the\n * absolute path with `/` → `-` (claude's convention; others tend to\n * use the same scheme). Returns the UUID of the most-recently\n * modified `.jsonl`, filtered to files at-or-after `prevStartedAt`.\n */\nfunction probeMtimeLatestJsonl(\n storeRel: string,\n): (cwd: string, prevStartedAt: string) => Promise<string | null> {\n return async (cwd, prevStartedAt) => {\n const encoded = cwd.replace(/\\//g, \"-\")\n const dir = resolve(homedir(), storeRel, encoded)\n let entries: string[]\n try {\n entries = await fs.readdir(dir)\n } catch {\n return null\n }\n const jsonl = entries.filter(e => e.endsWith(\".jsonl\"))\n if (jsonl.length === 0) return null\n const startedAtMs = Date.parse(prevStartedAt)\n const candidates: { name: string; mtime: number }[] = []\n for (const f of jsonl) {\n try {\n const st = await fs.stat(join(dir, f))\n if (!Number.isFinite(startedAtMs) || st.mtimeMs >= startedAtMs - 1000) {\n candidates.push({ name: f, mtime: st.mtimeMs })\n }\n } catch {\n // ignore unreadable entry\n }\n }\n if (candidates.length === 0) return null\n candidates.sort((a, b) => b.mtime - a.mtime)\n return candidates[0]!.name.replace(/\\.jsonl$/, \"\")\n }\n}\n\n/**\n * Helper: which adapters declare any resume capability? Used by\n * `agentproto sessions restart` to print a helpful \"this adapter\n * doesn't support resume; falling back to fresh spawn\" hint when\n * applicable.\n */\nexport function hasResumeStrategy(adapterSlug: string | undefined): boolean {\n if (!adapterSlug) return false\n const s = RESUME_STRATEGIES[adapterSlug]\n return !!(s && (s.outputHint || s.fsProbe || s.spawnArgs))\n}\n","/**\n * Sessions registry — tracks long-lived child processes spawned by\n * the agentproto daemon (terminals, agent CLIs, custom commands).\n *\n * The registry lives in-memory for the daemon's lifetime; a recent\n * snapshot also persists to `~/.agentproto/sessions.json` so a fresh\n * daemon restart can show \"you had these running before\" instead of\n * losing all visibility on a crash.\n *\n * Each session owns:\n * - identity: id, kind, workspace slug, command + args, started time\n * - lifecycle: status (starting/running/exited/killed/error)\n * - output: last N lines (ring buffer) for instant attach + a\n * Node EventEmitter for live streaming consumers\n *\n * Consumers:\n * - HTTP routes (GET /sessions, /sessions/:id, /sessions/:id/stream,\n * POST /sessions/:id/kill)\n * - CLI `agentproto sessions` (TUI navigation + attach)\n * - guilde-web Active tab (session cards + terminal viewer)\n */\n\nimport { spawn, type ChildProcess } from \"node:child_process\"\nimport { EventEmitter } from \"node:events\"\nimport { mkdirSync, writeFileSync, promises as fs, readFileSync } from \"node:fs\"\nimport { RESUME_STRATEGIES } from \"./resume-strategies.js\"\nimport { dirname, resolve } from \"node:path\"\nimport { homedir } from \"node:os\"\nimport { randomUUID } from \"node:crypto\"\n\n/**\n * Minimal shape we need from a driver-agent-cli session — kept as a\n * structural type so the runtime package doesn't take a hard\n * dependency on @agentproto/driver-agent-cli (the http-server route\n * imports it and passes the constructed session in).\n */\nexport interface AgentSessionLike {\n sessionId: string\n send(message: unknown): AsyncIterable<AgentStreamEvent>\n cancel(): Promise<void>\n close(): Promise<void>\n}\n\n/**\n * Minimal PTY surface — structurally compatible with\n * @agentproto/acp/tunnel's PtyProcess (node-pty's IPty wrapper). The\n * runtime declares its own so this package stays native-free; the\n * cli's pty-factory util constructs values that satisfy both.\n */\nexport interface PtyProcess {\n readonly pid: number\n write(data: string): void\n resize(cols: number, rows: number): void\n kill(signal?: string): void\n onData(handler: (data: string) => void): void\n onExit(handler: (event: { exitCode: number; signal?: number }) => void): void\n}\n\nexport interface PtyFactoryOptions {\n command: string\n args: string[]\n cwd?: string\n env?: Record<string, string>\n cols: number\n rows: number\n}\n\nexport type PtyFactory = (opts: PtyFactoryOptions) => PtyProcess\n\nexport interface AgentStreamEvent {\n kind: string\n text?: string\n toolName?: string\n isError?: boolean\n reason?: string\n error?: { message: string; code?: number; data?: unknown }\n}\n\nexport const SESSIONS_FILE_PATH = (): string =>\n resolve(homedir(), \".agentproto\", \"sessions.json\")\n\nexport type SessionKind = \"terminal\" | \"agent-cli\" | \"command\"\nexport type SessionStatus =\n | \"starting\"\n | \"running\"\n | \"exited\"\n | \"killed\"\n | \"error\"\n\nexport interface SessionDescriptor {\n id: string\n kind: SessionKind\n workspaceSlug: string\n /** What was actually run — quoted joined for display purposes\n * (`bash -lc \"claude --resume xyz\"`). */\n command: string\n pid: number | null\n status: SessionStatus\n startedAt: string\n endedAt?: string\n exitCode?: number\n /** Last time anything was written to stdout/stderr. Lets the UI\n * spot stuck sessions (\"running for 2h, last output 12min ago\"). */\n lastOutputAt?: string\n /** Free-text label the spawner can attach (e.g. conversation id,\n * operator name) so the UI can group/filter. */\n label?: string\n /** True when the session was spawned under a real PTY (node-pty)\n * instead of `child_process.spawn`. PTY sessions carry raw ANSI\n * bytes (alt-screen, key bindings, colors); attach goes through\n * WS /sessions/:id/pty rather than SSE /sessions/:id/stream. */\n pty?: boolean\n /** User-friendly slug supplied at spawn time. Optional; when set,\n * attach/stop/kill commands accept it as an alias for the id. */\n name?: string\n /** Argv that was spawned. Persisted so `agentproto sessions restart`\n * can clone the original shape without re-tokenizing the display\n * `command` string. Empty for agent-cli sessions (we record\n * `adapterSlug` separately). */\n argv?: readonly string[]\n /** Working directory the session was spawned in. Cloned by restart. */\n cwd?: string\n /** Adapter slug for agent-cli sessions — restart uses this with\n * `/sessions/agent` to spin up a fresh ACP runtime. Undefined for\n * pty/command kinds. */\n adapterSlug?: string\n /** ACP-level session id (the adapter's own handle — claude-code's\n * conversation id, hermes' chat id, …). Set at spawnAgent time\n * from `agentSession.sessionId`. Survives across daemon restarts\n * via sessions.json so `restart` can pass it as `resumeSessionId`\n * and reattach to the prior conversation history. */\n adapterSessionId?: string\n /** Provider-specific resume hints sniffed from the session's\n * output. claude-code prints `claude --resume <uuid>` on exit;\n * we capture that uuid as `claudeResumeId`. On `restart`, when a\n * hint is present, agentproto prefers a PTY spawn with the\n * provider's native resume command (`claude --resume <id>`) over\n * the ACP-level resume — works wherever the provider persisted\n * the session, not just when the ACP wrapper did.\n *\n * Keys are adapter-specific so future adapters can add their own\n * (\"hermesResumeId\", etc.) without changing this type. */\n resumeMetadata?: Record<string, string>\n}\n\ninterface SessionRuntime {\n desc: SessionDescriptor\n /** Set when the session is a raw spawn (`kind: \"command\"|\"terminal\"`).\n * Agent sessions don't expose the underlying process — the\n * driver-agent-cli runtime owns it. */\n child?: ChildProcess\n /** Set when the session is an agent-cli (multi-turn). The registry\n * keeps it alive across turns; sendPrompt(id, prompt) re-uses it. */\n agentSession?: AgentSessionLike\n /** Adapter slug — only set for agent sessions, helps the UI render\n * \"claude-code\" / \"hermes\" badges. */\n adapterSlug?: string\n /** Set when the session is a PTY (spawnPty). Bytes flow through\n * pty.onData → recentBytes ring + emitter \"data\" event. */\n pty?: PtyProcess\n /** Per-subscriber size requests for the PTY. Min cols/rows\n * across the live set is what we actually call pty.resize with\n * (mirrors tmux's \"smallest attached client wins\" rule). */\n ptySubscribers?: Map<number, { cols: number; rows: number }>\n /** Ring buffer of recent stdout+stderr lines. Capped so a runaway\n * child can't blow the daemon's heap. */\n recentLines: string[]\n /** Ring buffer of recent PTY bytes for replay-on-attach. Total\n * size capped at RECENT_BYTES_CAP — oldest chunks dropped first. */\n recentBytes: Buffer[]\n recentBytesSize: number\n emitter: EventEmitter\n /** True while a turn is in flight. POST /sessions/:id/prompt rejects\n * with 409 when busy — the agent can only handle one turn at a\n * time per session. */\n busy: boolean\n /** Buffer for partial text-delta fragments — agent text events\n * arrive as chunks, we coalesce them across deltas and split on\n * newlines so each line lands as a discrete ring-buffer entry. */\n textBuf: string\n /** Same as textBuf but for `thought` events. Some agents (hermes)\n * stream chain-of-thought as one delta per token, which made the\n * ring buffer unreadable when each token got its own\n * `[thought]` line — coalesce the same way text-delta does. */\n thoughtBuf: string\n /** In-flight resume promise. Deduplicates concurrent prompt\n * attempts on a dead agent session — only one resume call hits\n * the adapter, the rest await this promise. Cleared once\n * resolved (success or failure). */\n resumePromise?: Promise<void>\n}\n\nconst RECENT_LINES_CAP = 500\nconst RECENT_BYTES_CAP = 64 * 1024\nconst PERSIST_DEBOUNCE_MS = 1_500\n/** Cap on the number of historical descriptors loaded from\n * sessions.json at boot. Older entries (by startedAt) are dropped\n * on overflow — newest history wins. Adjust upward if the file\n * starts feeling sparse; downward if the dashboard takes too long\n * to render. */\nconst HISTORY_CAP = 200\n\n/** Strip CSI / SGR ANSI sequences so resume-pattern matching works\n * on dim/coloured output. Liberal regex covering most cases — we\n * don't need byte-perfect parsing here. */\nfunction stripAnsiCodes(s: string): string {\n return s.replace(/\\x1b\\[[0-9;?]*[A-Za-z]/g, \"\")\n}\n\nexport interface SessionsRegistry {\n spawn(input: SpawnSessionInput): SessionDescriptor\n /** Adopt a ChildProcess that was spawned outside the registry —\n * e.g. by the tunnel server when the host dispatches a spawn\n * frame. The registry attaches its stdout/stderr listeners and\n * tracks the descriptor so the child shows up in /sessions and\n * the LocalDaemonSessionsCard. The caller keeps lifecycle\n * ownership (kill / wait); this is purely for observability.\n * Returns the descriptor for the registered session. */\n register(input: RegisterSessionInput): SessionDescriptor\n /** Register an already-built agent session (caller resolves the\n * adapter + builds the runtime). Sets kind=\"agent-cli\", consumes\n * the optional initial prompt synchronously, returns the\n * descriptor. The agent stays alive — call `sendPrompt(id, ...)`\n * for follow-up turns until `kill(id)` closes it. */\n spawnAgent(input: SpawnAgentInput): SessionDescriptor\n /** Spawn a process under a real PTY (node-pty). Bytes flow through\n * the registry's byte ring buffer + emitter; attach with\n * `attachPty(id, ...)`. Throws when the registry was constructed\n * without a `spawnPty` factory (node-pty optional dep missing). */\n spawnPty(input: SpawnPtyInput): SessionDescriptor\n /** Send a follow-up turn to a live agent session. Throws when the\n * session is missing, not an agent-cli kind, or busy. The events\n * stream into the existing ring buffer + line emitter so /stream\n * consumers see them as they arrive. */\n sendPrompt(id: string, message: unknown): Promise<void>\n /** Fire-and-forget variant of `sendPrompt`. Validates the same\n * preconditions synchronously — throws on missing session / wrong\n * kind / busy — but returns immediately after the turn is started,\n * letting the caller stream output via the SSE endpoint instead of\n * blocking on the full turn. Async errors during the turn are\n * pushed into the ring buffer as `[error]` lines so `/stream`\n * subscribers see them. Used by the web UI's chat input where a\n * long turn would otherwise freeze the textbox. */\n enqueuePrompt(id: string, message: unknown): void\n list(): SessionDescriptor[]\n get(id: string): SessionDescriptor | undefined\n /** Subscribe to a session's output. Returns an unsubscribe fn.\n * Initial backfill: synchronously invokes `onLine` once for each\n * line currently in the ring buffer so attaches show context. */\n attach(\n id: string,\n onLine: (line: string, stream: \"stdout\" | \"stderr\") => void\n ): (() => void) | null\n /** Subscribe to a PTY session's byte stream. Returns a control\n * handle (write/resize/detach) and null when the session is\n * missing or not a PTY kind. Replays the ring buffer\n * synchronously before live frames start. Initial `cols`/`rows`\n * are required so the registry can compute min-size across\n * subscribers; recompute on every `resize` call. */\n attachPty(\n id: string,\n initial: { cols: number; rows: number },\n onData: (chunk: Buffer) => void,\n onExit: (event: { exitCode: number; signal?: number }) => void\n ): {\n write(data: string): void\n resize(cols: number, rows: number): void\n detach(): void\n } | null\n /** Find a session by exact id OR exact name match. Returns the\n * descriptor or undefined. Used by HTTP/MCP routes so callers\n * can refer to \"claude-main\" instead of \"sess_a3f8c1b2\". */\n findByIdOrName(query: string): SessionDescriptor | undefined\n /** Write a chunk of text to a PTY session's stdin. Returns true\n * on success, false when the session is missing or not a PTY.\n * Single-shot variant of attachPty().write — useful for MCP\n * tools that drive a session through tool calls. */\n writeTerminalInput(id: string, data: string): boolean\n /** Snapshot the recent PTY byte buffer as one Buffer. Newest\n * bytes at the end; `lastBytes` caps the returned size from the\n * tail. Returns null when the session is missing or not a PTY. */\n readTerminalOutput(id: string, lastBytes?: number): Buffer | null\n kill(id: string, signal?: NodeJS.Signals): boolean\n /** Stop tracking a session (after it exited and the user clicked\n * \"clear\"). Doesn't kill — use `kill` first. */\n forget(id: string): boolean\n /** Stop persisting + close all sessions. Killed children are not\n * awaited — the daemon shutdown loop handles process tree teardown. */\n shutdown(): void\n}\n\nexport interface RegisterSessionInput {\n /** Pre-existing child process to adopt (e.g. from a tunnel spawn). */\n child: ChildProcess\n /** Stable id — typically the tunnel's execId so callers cross-ref. */\n id: string\n workspaceSlug: string\n /** Display label for the descriptor's `command` field. */\n command: string\n kind?: SessionKind\n label?: string\n}\n\nexport interface SpawnAgentInput {\n workspaceSlug: string\n cwd: string\n /** Driver-built session ready to receive turns. Caller resolves\n * the adapter, calls createAgentCliRuntime(handle).start({cwd}),\n * and hands the result here. */\n agentSession: AgentSessionLike\n /** Adapter slug for the descriptor (display only). */\n adapterSlug: string\n /** Optional initial prompt to dispatch immediately. The promise\n * the registry returns resolves AFTER the spawn — the prompt\n * runs in the background, projecting events into the ring\n * buffer. Skip to spawn idle. */\n initialPrompt?: string\n label?: string\n /** Pretty command for the descriptor (display only). */\n commandPreview?: string\n}\n\nexport interface SpawnSessionInput {\n kind: SessionKind\n workspaceSlug: string\n /** Path of the workspace root (for the child's cwd). The registry\n * doesn't validate it against the workspaces config — caller has\n * already resolved this. */\n cwd: string\n /** Argv. First element is the binary; rest are passed verbatim. */\n argv: string[]\n /** Extra env on top of the daemon's process.env. */\n env?: Record<string, string>\n /** Optional pre-set id (lets the spawner reference the session\n * before the spawn returns — useful for telemetry). */\n id?: string\n label?: string\n /** Keep the child's stdin open (default: closed). Most spawned\n * agents are non-interactive and emit a warning when stdin is a\n * pipe with no writer (claude-code prints \"no stdin data\n * received in 3s, proceeding without it\"). Closing stdin lets\n * them skip the wait. PTY/terminal kinds that genuinely need\n * bidirectional IO should opt in via `keepStdin: true` and the\n * caller is then responsible for writing to `child.stdin`. */\n keepStdin?: boolean\n}\n\nexport interface SpawnPtyInput {\n workspaceSlug: string\n cwd: string\n argv: string[]\n /** Initial PTY dimensions. The registry uses min(cols, rows) across\n * active subscribers thereafter — these are the seed values used\n * before anyone attaches. */\n cols: number\n rows: number\n /** Extra env on top of process.env. TERM/LANG/PATH are forced by\n * the factory layer (node-pty.spawn options); don't try to clear\n * them here. */\n env?: Record<string, string>\n /** User-friendly slug. Used by `findByIdOrName(query)`. Must not\n * collide with an existing session's name. */\n name?: string\n label?: string\n}\n\n/**\n * Hook the registry uses to rebuild a dead agent session on demand.\n * Invoked when a prompt arrives for an agent-cli session whose\n * `agentSession` was lost (typically daemon restart). Returns a fresh\n * `AgentSessionLike` bound to the same upstream conversation via\n * `resumeSessionId`, OR null if resume isn't possible (adapter gone,\n * upstream rejected). When null, the prompt path surfaces the same\n * \"not an agent session\" error as before — caller knows the row is a\n * ghost.\n *\n * The CLI wires this into the registry by passing in a closure that\n * calls `resolveAgentAdapter(slug)?.startSession({cwd, resumeSessionId})`,\n * which is the same path the gateway's POST /sessions/agent uses.\n */\nexport type AgentSessionResumer = (input: {\n adapterSlug: string\n cwd: string\n resumeSessionId: string\n}) => Promise<AgentSessionLike | null>\n\nexport function createSessionsRegistry(opts?: {\n /** Override the persistence path — tests pin a tmpdir. */\n persistPath?: string\n /** Disable persistence entirely. */\n persist?: boolean\n /** PTY factory (node-pty wrapper). When omitted, `spawnPty()`\n * throws — the daemon advertises PTY support only when the cli\n * layer resolved node-pty successfully. */\n spawnPty?: PtyFactory\n /** Hook called when a prompt arrives for an agent-cli session whose\n * agentSession binding is gone (daemon restart). When provided,\n * the registry transparently resumes the session via the adapter's\n * resumeSessionId before dispatching the turn. When omitted,\n * killed agent-cli sessions surface the legacy \"not an agent\n * session\" error and the user must spawn fresh. */\n resumeAgent?: AgentSessionResumer\n}): SessionsRegistry {\n const persistPath = opts?.persistPath ?? SESSIONS_FILE_PATH()\n const persist = opts?.persist ?? true\n const ptyFactory = opts?.spawnPty\n const resumeAgent = opts?.resumeAgent\n const sessions = new Map<string, SessionRuntime>()\n let persistTimer: ReturnType<typeof setTimeout> | null = null\n // Monotonically-growing PTY-subscriber id. Detach is O(1) on\n // Map.delete(subId), so we never reuse — overflow at Number.MAX_-\n // SAFE_INTEGER would take ~285 years at 1M attaches/sec.\n let nextSubId = 1\n // Guards `shutdown()` from running twice — double-stop happens in\n // serve --interactive's Ctrl-C race; without this, the second\n // call writes an empty snapshot over the real one.\n let shutdownDone = false\n\n // ── boot-time history load ──\n // Read sessions.json synchronously at construction so the dashboard\n // shows historical sessions immediately on daemon restart. Anything\n // that was \"running\" or \"starting\" when the daemon last died gets\n // marked \"killed\" — we have no way to know if the orphan child\n // survived the daemon's exit, and pretending it's still alive would\n // make attach calls fail mysteriously.\n //\n // Historical entries are GHOSTS: descriptor only, no child / no\n // agentSession / no pty. Calls like kill(id) / attach(id) work on\n // them but degrade to no-ops (the underlying process is gone). The\n // session's `endedAt` is set to now when we infer a kill, so the\n // dashboard ages them from this boot rather than the daemon's last\n // life.\n if (persist) {\n loadHistorySnapshot(persistPath, sessions)\n }\n\n // Belt-and-suspenders: `process.on(\"exit\")` runs even on uncaught\n // throws, terminal-close (SIGHUP), and any termination path that\n // bypassed the regular SIGINT/SIGTERM cleanup. The handler must be\n // sync (Node won't await async there); we already use sync IO in\n // `shutdown()` so this is safe. Idempotency guard inside shutdown\n // prevents a double-write when both this handler and the explicit\n // SIGINT path fire.\n const onProcessExit = (): void => {\n shutdownImpl()\n }\n if (persist) {\n process.on(\"exit\", onProcessExit)\n }\n\n const schedulePersist = (): void => {\n if (!persist) return\n if (persistTimer) clearTimeout(persistTimer)\n persistTimer = setTimeout(() => {\n void persistSnapshot()\n }, PERSIST_DEBOUNCE_MS)\n }\n\n const persistSnapshot = async (): Promise<void> => {\n try {\n const snapshot = {\n savedAt: new Date().toISOString(),\n sessions: Array.from(sessions.values()).map(s => s.desc),\n }\n await fs.mkdir(dirname(persistPath), { recursive: true })\n await fs.writeFile(persistPath, JSON.stringify(snapshot, null, 2) + \"\\n\")\n } catch (err) {\n // Persistence is best-effort — log only, never throw.\n console.warn(\n `[sessions] persist failed: ${\n err instanceof Error ? err.message : String(err)\n }`\n )\n }\n }\n\n const appendLine = (\n rt: SessionRuntime,\n line: string,\n stream: \"stdout\" | \"stderr\"\n ): void => {\n rt.recentLines.push(line)\n if (rt.recentLines.length > RECENT_LINES_CAP) {\n rt.recentLines.splice(0, rt.recentLines.length - RECENT_LINES_CAP)\n }\n rt.desc.lastOutputAt = new Date().toISOString()\n sniffResumeHints(rt, line)\n rt.emitter.emit(\"line\", { line, stream })\n }\n\n /**\n * Provider-specific resume-hint sniffer. Looks up the adapter's\n * strategy in `RESUME_STRATEGIES` and runs its `outputHint` regex\n * against each agent-cli line. The captured id is recorded on the\n * descriptor so `agentproto sessions restart` can use it.\n *\n * ANSI-stripped before matching so dim/color codes don't break the\n * pattern. Adapters without a strategy entry (or without an\n * outputHint) are skipped — they fall back to ACP-level resume.\n */\n const sniffResumeHints = (rt: SessionRuntime, line: string): void => {\n if (rt.desc.kind !== \"agent-cli\") return\n const strategy = rt.desc.adapterSlug\n ? RESUME_STRATEGIES[rt.desc.adapterSlug]\n : undefined\n if (!strategy?.outputHint) return\n const plain = stripAnsiCodes(line)\n const m = plain.match(strategy.outputHint)\n if (m && m[1]) {\n rt.desc.resumeMetadata = {\n ...(rt.desc.resumeMetadata ?? {}),\n [strategy.storeAs]: m[1],\n }\n schedulePersist()\n }\n }\n\n /**\n * PTY byte ring buffer. Keeps the last ~64 KiB of raw bytes so a\n * fresh attacher sees the current screenful (alt-screen apps like\n * Claude TUI / vim repaint on next interaction but a snapshot is\n * still better than blank). Drops oldest chunks when over cap;\n * never splits within a chunk — Buffer arithmetic on UTF-8 mid-\n * sequence would corrupt multi-byte glyphs.\n */\n const appendBytes = (rt: SessionRuntime, chunk: Buffer): void => {\n rt.recentBytes.push(chunk)\n rt.recentBytesSize += chunk.byteLength\n while (\n rt.recentBytesSize > RECENT_BYTES_CAP &&\n rt.recentBytes.length > 1\n ) {\n const dropped = rt.recentBytes.shift()\n if (dropped) rt.recentBytesSize -= dropped.byteLength\n }\n rt.desc.lastOutputAt = new Date().toISOString()\n rt.emitter.emit(\"data\", chunk)\n }\n\n /**\n * Recompute the smallest cols/rows across the active subscriber\n * set and resize the PTY accordingly (tmux's \"smallest attached\n * client wins\" rule). No-op when the subscriber map is empty.\n */\n const reconcilePtySize = (rt: SessionRuntime): void => {\n if (!rt.pty || !rt.ptySubscribers || rt.ptySubscribers.size === 0) return\n let cols = Infinity\n let rows = Infinity\n for (const dim of rt.ptySubscribers.values()) {\n if (dim.cols < cols) cols = dim.cols\n if (dim.rows < rows) rows = dim.rows\n }\n if (!Number.isFinite(cols) || !Number.isFinite(rows)) return\n try {\n rt.pty.resize(cols, rows)\n } catch {\n // pty may have exited between the emit and the resize — swallow.\n }\n }\n\n /**\n * Project ACP-style stream events into ring-buffer lines. Keeps\n * the line shape simple so the existing /stream SSE consumer\n * (and the xterm panel) just renders them as-is.\n */\n const projectEvent = (rt: SessionRuntime, evt: AgentStreamEvent): void => {\n switch (evt.kind) {\n case \"text-delta\":\n if (evt.text) {\n // text-delta is a stream of chunks — split on newlines so\n // each line lands in the ring buffer separately. Coalesce\n // a trailing fragment via rt.textBuf.\n const combined = rt.textBuf + evt.text\n const lines = combined.split(/\\r?\\n/)\n rt.textBuf = lines.pop() ?? \"\"\n for (const line of lines) appendLine(rt, line, \"stdout\")\n }\n break\n case \"thought\":\n if (evt.text) {\n // Same coalescing as text-delta — some adapters stream\n // chain-of-thought one token at a time, which would\n // otherwise produce ~100 [thought] lines per turn.\n const combined = rt.thoughtBuf + evt.text\n const lines = combined.split(/\\r?\\n/)\n rt.thoughtBuf = lines.pop() ?? \"\"\n for (const line of lines) {\n if (line.trim()) {\n appendLine(rt, `\\x1b[2m[thought] ${line}\\x1b[0m`, \"stdout\")\n }\n }\n }\n break\n case \"tool-call\":\n appendLine(\n rt,\n `\\x1b[36m[tool] ${evt.toolName ?? \"?\"}\\x1b[0m`,\n \"stdout\"\n )\n break\n case \"tool-result\":\n if (evt.isError)\n appendLine(rt, `\\x1b[31m[tool-error]\\x1b[0m`, \"stderr\")\n break\n case \"agent-prompt\":\n appendLine(rt, `\\x1b[33m[awaiting input]\\x1b[0m`, \"stdout\")\n break\n case \"turn-end\": {\n // Flush any buffered text/thought fragments as final lines.\n if (rt.thoughtBuf.trim()) {\n appendLine(\n rt,\n `\\x1b[2m[thought] ${rt.thoughtBuf}\\x1b[0m`,\n \"stdout\"\n )\n }\n rt.thoughtBuf = \"\"\n if (rt.textBuf) {\n appendLine(rt, rt.textBuf, \"stdout\")\n rt.textBuf = \"\"\n }\n appendLine(\n rt,\n `\\x1b[2m── turn-end (${evt.reason ?? \"completed\"}) ──\\x1b[0m`,\n \"stdout\"\n )\n break\n }\n case \"error\": {\n const code =\n typeof evt.error?.code === \"number\" ? ` (code ${evt.error.code})` : \"\"\n appendLine(\n rt,\n `\\x1b[31m[error]${code} ${evt.error?.message ?? \"unknown\"}\\x1b[0m`,\n \"stderr\"\n )\n // Project the child's stderr tail when define-agent-cli\n // attached it — otherwise the user sees only \"Invalid\n // params\" and has to dig into the daemon log for context.\n const data = evt.error?.data as\n | { stderr?: unknown }\n | null\n | undefined\n if (data && typeof data === \"object\" && typeof data.stderr === \"string\") {\n for (const line of data.stderr.split(/\\r?\\n/)) {\n if (line) appendLine(rt, `\\x1b[2m ${line}\\x1b[0m`, \"stderr\")\n }\n }\n break\n }\n }\n }\n\n /**\n * Drive one agent turn. Sets busy=true, drains the event stream\n * into the ring buffer, clears busy on completion. Bumps the\n * descriptor status to \"error\" if the iteration throws (network\n * drop, child died mid-turn).\n */\n /**\n * Shared sync validation for sendPrompt + enqueuePrompt. Throws on\n * missing session / wrong kind / busy so both code paths surface\n * the exact same error messages — the only difference is whether\n * the caller awaits the turn.\n */\n const validateAgentTurn = (id: string, caller: string): SessionRuntime => {\n const rt = sessions.get(id)\n if (!rt) throw new Error(`${caller}: no session \"${id}\"`)\n if (!rt.agentSession) {\n throw new Error(\n `${caller}: session \"${id}\" is not an agent session (kind=${rt.desc.kind})`\n )\n }\n if (rt.busy) {\n throw new Error(\n `${caller}: session \"${id}\" is mid-turn — wait for it to finish or cancel`\n )\n }\n return rt\n }\n\n /**\n * Attempt to resume a dead agent-cli session by re-spawning the\n * adapter with the persisted `adapterSessionId`. The conversation\n * continues from where it left off — ACP's `resumeSessionId`\n * contract guarantees the adapter rehydrates state from the\n * upstream provider (Anthropic / OpenAI / etc.) when supported.\n *\n * Returns silently when:\n * - resumeAgent hook wasn't provided (older daemon embedding)\n * - session is already alive (binding present)\n * - session is a non-agent kind (terminal/command can't resume)\n * - descriptor lacks adapterSessionId or adapterSlug (legacy row\n * persisted before resume metadata was tracked)\n *\n * Concurrent prompt arrivals share one resume attempt via\n * `rt.resumePromise`.\n */\n const maybeResumeAgent = async (rt: SessionRuntime): Promise<void> => {\n if (rt.agentSession) return\n if (!resumeAgent) return\n if (rt.desc.kind !== \"agent-cli\") return\n const adapterSlug = rt.desc.adapterSlug ?? rt.adapterSlug\n const adapterSessionId = rt.desc.adapterSessionId\n const cwd = rt.desc.cwd\n if (!adapterSlug || !adapterSessionId || !cwd) return\n if (rt.resumePromise) {\n await rt.resumePromise\n return\n }\n rt.resumePromise = (async () => {\n appendLine(\n rt,\n `── resuming ${adapterSlug} session ${adapterSessionId} ──`,\n \"stdout\"\n )\n try {\n const fresh = await resumeAgent({\n adapterSlug,\n cwd,\n resumeSessionId: adapterSessionId,\n })\n if (!fresh) {\n appendLine(\n rt,\n `[error] resume failed: adapter '${adapterSlug}' returned null`,\n \"stderr\"\n )\n return\n }\n rt.agentSession = fresh\n rt.adapterSlug = adapterSlug\n rt.desc.adapterSessionId = fresh.sessionId\n if (rt.desc.status !== \"running\") {\n rt.desc.status = \"running\"\n delete rt.desc.endedAt\n delete rt.desc.exitCode\n rt.emitter.emit(\"status\", rt.desc.status)\n }\n schedulePersist()\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err)\n appendLine(rt, `[error] resume failed: ${msg}`, \"stderr\")\n }\n })()\n try {\n await rt.resumePromise\n } finally {\n rt.resumePromise = undefined\n }\n }\n\n const runAgentTurn = async (\n rt: SessionRuntime,\n message: unknown\n ): Promise<void> => {\n if (!rt.agentSession) {\n throw new Error(\"runAgentTurn: session has no agentSession\")\n }\n rt.busy = true\n try {\n appendLine(\n rt,\n `\\x1b[2m── ▶ ${typeof message === \"string\" ? message : JSON.stringify(message)} ──\\x1b[0m`,\n \"stdout\"\n )\n // ACP's `prompt` field expects ContentBlock[] (or a single\n // block). Hosts that send a raw string get auto-wrapped into\n // `{type: \"text\", text: \"...\"}` so callers can hand us\n // human-friendly prompts without shaping the wire format.\n const wrapped =\n typeof message === \"string\" ? { type: \"text\", text: message } : message\n for await (const evt of rt.agentSession.send(wrapped)) {\n projectEvent(rt, evt)\n }\n } catch (err) {\n rt.desc.status = \"error\"\n rt.desc.endedAt = new Date().toISOString()\n appendLine(\n rt,\n `[turn error] ${err instanceof Error ? err.message : String(err)}`,\n \"stderr\"\n )\n schedulePersist()\n } finally {\n rt.busy = false\n }\n }\n\n const wireOutputStreams = (rt: SessionRuntime): void => {\n const onChunk =\n (stream: \"stdout\" | \"stderr\") =>\n (chunk: Buffer | string): void => {\n const text = typeof chunk === \"string\" ? chunk : chunk.toString(\"utf8\")\n for (const line of text.split(/\\r?\\n/)) {\n if (line.length > 0) appendLine(rt, line, stream)\n }\n }\n // Only called from spawn() which always sets rt.child — narrow\n // here so the stream listeners don't trip the optional-chain.\n if (!rt.child) return\n rt.child.stdout?.on(\"data\", onChunk(\"stdout\"))\n rt.child.stderr?.on(\"data\", onChunk(\"stderr\"))\n }\n\n return {\n spawn(input) {\n const id = input.id ?? `sess_${randomUUID().slice(0, 8)}`\n if (sessions.has(id)) {\n throw new Error(`sessions.spawn: id \"${id}\" already in use`)\n }\n const env = { ...process.env, ...(input.env ?? {}) }\n // Filter out Node bookkeeping that confuses subprocesses.\n delete env.NODE_OPTIONS\n const [bin, ...args] = input.argv\n if (!bin) throw new Error(\"sessions.spawn: argv must include a binary\")\n // Close stdin by default — most agent CLIs spawn-and-prompt\n // (claude/codex/aider/etc.) read argv for the prompt and will\n // otherwise sit waiting for piped input. Caller opts in to a\n // writeable stdin via `keepStdin: true` (terminal/PTY kinds).\n const stdinMode = input.keepStdin ? \"pipe\" : \"ignore\"\n const child = spawn(bin, args, {\n cwd: input.cwd,\n env: env as NodeJS.ProcessEnv,\n stdio: [stdinMode, \"pipe\", \"pipe\"],\n })\n const desc: SessionDescriptor = {\n id,\n kind: input.kind,\n workspaceSlug: input.workspaceSlug,\n command: [bin, ...args].map(quoteArg).join(\" \"),\n pid: child.pid ?? null,\n status: \"starting\",\n startedAt: new Date().toISOString(),\n argv: input.argv,\n cwd: input.cwd,\n ...(input.label ? { label: input.label } : {}),\n }\n const rt: SessionRuntime = {\n desc,\n child,\n recentLines: [],\n recentBytes: [],\n recentBytesSize: 0,\n emitter: new EventEmitter(),\n busy: false,\n textBuf: \"\",\n thoughtBuf: \"\",\n }\n // Don't crash the daemon when no listener is attached — the\n // emitter's \"error\" event would otherwise propagate.\n rt.emitter.setMaxListeners(50)\n\n sessions.set(id, rt)\n wireOutputStreams(rt)\n\n child.once(\"spawn\", () => {\n desc.status = \"running\"\n rt.emitter.emit(\"status\", desc.status)\n schedulePersist()\n })\n child.once(\"error\", err => {\n desc.status = \"error\"\n desc.endedAt = new Date().toISOString()\n appendLine(rt, `[spawn error] ${err.message}`, \"stderr\")\n rt.emitter.emit(\"status\", desc.status)\n schedulePersist()\n })\n child.once(\"exit\", (code, signal) => {\n if (signal && desc.status !== \"killed\") desc.status = \"killed\"\n else if (desc.status === \"running\" || desc.status === \"starting\") {\n desc.status = \"exited\"\n }\n desc.endedAt = new Date().toISOString()\n if (typeof code === \"number\") desc.exitCode = code\n rt.emitter.emit(\"status\", desc.status)\n schedulePersist()\n })\n schedulePersist()\n return desc\n },\n register(input) {\n if (sessions.has(input.id)) {\n // Already adopted (re-tracking is a noop). Return the\n // existing descriptor so callers don't have to special-case.\n const existing = sessions.get(input.id)\n if (existing) return existing.desc\n }\n const desc: SessionDescriptor = {\n id: input.id,\n kind: input.kind ?? \"command\",\n workspaceSlug: input.workspaceSlug,\n command: input.command,\n pid: input.child.pid ?? null,\n status: input.child.killed ? \"killed\" : \"running\",\n startedAt: new Date().toISOString(),\n ...(input.label ? { label: input.label } : {}),\n }\n const rt: SessionRuntime = {\n desc,\n child: input.child,\n recentLines: [],\n recentBytes: [],\n recentBytesSize: 0,\n emitter: new EventEmitter(),\n busy: false,\n textBuf: \"\",\n thoughtBuf: \"\",\n }\n rt.emitter.setMaxListeners(50)\n sessions.set(input.id, rt)\n wireOutputStreams(rt)\n // Wire exit so the descriptor flips when the adopted child\n // dies — same handlers as spawn() but registered post-hoc\n // because the child is already alive.\n input.child.once(\"exit\", (code, signal) => {\n if (signal && desc.status !== \"killed\") desc.status = \"killed\"\n else if (desc.status === \"running\") desc.status = \"exited\"\n desc.endedAt = new Date().toISOString()\n if (typeof code === \"number\") desc.exitCode = code\n rt.emitter.emit(\"status\", desc.status)\n schedulePersist()\n })\n input.child.once(\"error\", err => {\n desc.status = \"error\"\n desc.endedAt = new Date().toISOString()\n appendLine(rt, `[child error] ${err.message}`, \"stderr\")\n rt.emitter.emit(\"status\", desc.status)\n schedulePersist()\n })\n schedulePersist()\n return desc\n },\n spawnAgent(input) {\n const id = `sess_${randomUUID().slice(0, 8)}`\n const desc: SessionDescriptor = {\n id,\n kind: \"agent-cli\",\n workspaceSlug: input.workspaceSlug,\n command: input.commandPreview ?? `${input.adapterSlug} (agent)`,\n pid: null,\n status: \"running\", // driver already started the session\n startedAt: new Date().toISOString(),\n cwd: input.cwd,\n adapterSlug: input.adapterSlug,\n // ACP-level session id — sticks across daemon restart so\n // `agentproto sessions restart <id>` can pass it as\n // `resumeSessionId` and the adapter reattaches to the prior\n // conversation rather than starting blank.\n adapterSessionId: input.agentSession.sessionId,\n ...(input.label ? { label: input.label } : {}),\n }\n const rt: SessionRuntime = {\n desc,\n agentSession: input.agentSession,\n adapterSlug: input.adapterSlug,\n recentLines: [],\n recentBytes: [],\n recentBytesSize: 0,\n emitter: new EventEmitter(),\n busy: false,\n textBuf: \"\",\n thoughtBuf: \"\",\n }\n rt.emitter.setMaxListeners(50)\n sessions.set(id, rt)\n appendLine(\n rt,\n `── ${input.adapterSlug} agent session ${input.agentSession.sessionId} (cwd ${input.cwd}) ──`,\n \"stdout\"\n )\n schedulePersist()\n // Fire-and-forget the initial prompt (if any). Errors land in\n // the ring buffer + bump status to \"error\" but don't reject\n // the spawn — the descriptor was already returned.\n if (input.initialPrompt) {\n void runAgentTurn(rt, input.initialPrompt).catch(err => {\n appendLine(\n rt,\n `[turn error] ${err instanceof Error ? err.message : String(err)}`,\n \"stderr\"\n )\n })\n }\n return desc\n },\n spawnPty(input) {\n if (!ptyFactory) {\n throw new Error(\n \"sessions.spawnPty: no PTY factory configured (node-pty optional dep missing in the daemon)\"\n )\n }\n const id = `sess_${randomUUID().slice(0, 8)}`\n // Reject the name only when the prior holder is still alive —\n // killed/exited/error sessions keep their descriptor in the\n // registry for history, but their name is free to reuse so\n // `stop X && terminal --name X` round-trips cleanly.\n if (input.name) {\n for (const rt of sessions.values()) {\n if (rt.desc.name !== input.name) continue\n const status = rt.desc.status\n if (status === \"running\" || status === \"starting\") {\n throw new Error(\n `sessions.spawnPty: name \"${input.name}\" already in use by ${rt.desc.id} (status=${status})`,\n )\n }\n // Free the name on the dead session so id-or-name lookup\n // resolves to the NEW one. The old descriptor stays in the\n // registry (you can still find it by id in the list).\n rt.desc.name = undefined\n }\n }\n const [bin, ...args] = input.argv\n if (!bin) {\n throw new Error(\"sessions.spawnPty: argv must include a binary\")\n }\n // node-pty forces its own minimal env unless we forward — pass\n // process.env merged with caller overrides. The factory layer\n // also forces TERM=xterm-256color so alt-screen apps render.\n const env = { ...(process.env as Record<string, string>), ...(input.env ?? {}) }\n delete env.NODE_OPTIONS\n const pty: PtyProcess = ptyFactory({\n command: bin,\n args,\n cwd: input.cwd,\n env,\n cols: input.cols,\n rows: input.rows,\n })\n const desc: SessionDescriptor = {\n id,\n kind: \"terminal\",\n workspaceSlug: input.workspaceSlug,\n command: [bin, ...args].map(quoteArg).join(\" \"),\n pid: pty.pid,\n status: \"running\",\n startedAt: new Date().toISOString(),\n pty: true,\n argv: input.argv,\n cwd: input.cwd,\n ...(input.name ? { name: input.name } : {}),\n ...(input.label ? { label: input.label } : {}),\n }\n const rt: SessionRuntime = {\n desc,\n pty,\n ptySubscribers: new Map(),\n recentLines: [],\n recentBytes: [],\n recentBytesSize: 0,\n emitter: new EventEmitter(),\n busy: false,\n textBuf: \"\",\n thoughtBuf: \"\",\n }\n rt.emitter.setMaxListeners(50)\n sessions.set(id, rt)\n pty.onData((chunk: string) => {\n // node-pty emits utf-8 strings. Convert once at the boundary\n // so the ring buffer + emitter consumers all see Buffer.\n appendBytes(rt, Buffer.from(chunk, \"utf8\"))\n })\n pty.onExit(evt => {\n if (rt.desc.status !== \"killed\") {\n rt.desc.status = \"exited\"\n }\n rt.desc.endedAt = new Date().toISOString()\n if (typeof evt.exitCode === \"number\") rt.desc.exitCode = evt.exitCode\n rt.emitter.emit(\"exit\", evt)\n rt.emitter.emit(\"status\", rt.desc.status)\n schedulePersist()\n })\n schedulePersist()\n return desc\n },\n async sendPrompt(id, message) {\n const rtPre = sessions.get(id)\n if (rtPre) await maybeResumeAgent(rtPre)\n const rt = validateAgentTurn(id, \"sendPrompt\")\n await runAgentTurn(rt, message)\n },\n enqueuePrompt(id, message) {\n // For sync `enqueuePrompt`, we need to surface an immediate\n // error when the session is missing OR when it's a non-agent\n // kind that can't be resumed at all. But when the session IS\n // an agent-cli with resume metadata, defer validation until\n // after the resume attempt so a dead-but-resumable row Just\n // Works for the caller (no \"not an agent session\" error after\n // a daemon restart).\n const rtPre = sessions.get(id)\n if (!rtPre) {\n throw new Error(`enqueuePrompt: no session \"${id}\"`)\n }\n if (rtPre.desc.kind !== \"agent-cli\") {\n throw new Error(\n `enqueuePrompt: session \"${id}\" is not an agent session (kind=${rtPre.desc.kind})`\n )\n }\n if (rtPre.busy) {\n throw new Error(\n `enqueuePrompt: session \"${id}\" is mid-turn — wait for it to finish or cancel`\n )\n }\n // Fire-and-forget: resume (if needed) then dispatch. Errors\n // during either step land in the ring buffer as `[error]`\n // lines so the SSE consumer sees them.\n void (async () => {\n try {\n await maybeResumeAgent(rtPre)\n const rt = validateAgentTurn(id, \"enqueuePrompt\")\n await runAgentTurn(rt, message)\n } catch (err) {\n appendLine(\n rtPre,\n `[error] ${err instanceof Error ? err.message : String(err)}`,\n \"stderr\"\n )\n }\n })()\n },\n list() {\n return Array.from(sessions.values())\n .map(s => s.desc)\n .sort((a, b) => b.startedAt.localeCompare(a.startedAt))\n },\n get(id) {\n return sessions.get(id)?.desc\n },\n attach(id, onLine) {\n const rt = sessions.get(id)\n if (!rt) return null\n // Backfill: synchronously replay the ring buffer so attaches\n // see the recent context, then subscribe for new lines.\n for (const line of rt.recentLines) onLine(line, \"stdout\")\n const handler = (evt: {\n line: string\n stream: \"stdout\" | \"stderr\"\n }): void => onLine(evt.line, evt.stream)\n rt.emitter.on(\"line\", handler)\n return () => rt.emitter.off(\"line\", handler)\n },\n attachPty(id, initial, onData, onExit) {\n const rt = sessions.get(id)\n if (!rt || !rt.pty || !rt.ptySubscribers) return null\n // Backfill: flush the byte ring buffer so a fresh attach lands\n // on the recent screenful. Alt-screen apps repaint on next\n // input but a snapshot is still better than blank.\n for (const chunk of rt.recentBytes) onData(chunk)\n // Subscriber registration: a monotonically-growing key so the\n // size map can hold the per-subscriber dims and detach is O(1).\n const subId = nextSubId++\n rt.ptySubscribers.set(subId, { cols: initial.cols, rows: initial.rows })\n reconcilePtySize(rt)\n const dataHandler = (chunk: Buffer): void => onData(chunk)\n const exitHandler = (evt: {\n exitCode: number\n signal?: number\n }): void => onExit(evt)\n rt.emitter.on(\"data\", dataHandler)\n rt.emitter.once(\"exit\", exitHandler)\n return {\n write(data: string): void {\n if (!rt.pty) return\n try {\n rt.pty.write(data)\n } catch {\n // PTY already exited — drop the input silently.\n }\n },\n resize(cols: number, rows: number): void {\n if (!rt.ptySubscribers) return\n rt.ptySubscribers.set(subId, { cols, rows })\n reconcilePtySize(rt)\n },\n detach(): void {\n rt.emitter.off(\"data\", dataHandler)\n rt.emitter.off(\"exit\", exitHandler)\n rt.ptySubscribers?.delete(subId)\n reconcilePtySize(rt)\n },\n }\n },\n findByIdOrName(query) {\n const direct = sessions.get(query)\n if (direct) return direct.desc\n for (const rt of sessions.values()) {\n if (rt.desc.name === query) return rt.desc\n }\n return undefined\n },\n writeTerminalInput(id, data) {\n const rt = sessions.get(id)\n if (!rt || !rt.pty) return false\n try {\n rt.pty.write(data)\n return true\n } catch {\n return false\n }\n },\n readTerminalOutput(id, lastBytes) {\n const rt = sessions.get(id)\n if (!rt || !rt.pty) return null\n const joined = Buffer.concat(rt.recentBytes, rt.recentBytesSize)\n if (typeof lastBytes === \"number\" && lastBytes > 0 && joined.byteLength > lastBytes) {\n return joined.subarray(joined.byteLength - lastBytes)\n }\n return joined\n },\n kill(id, signal = \"SIGTERM\") {\n const rt = sessions.get(id)\n if (!rt) return false\n if (\n rt.desc.status === \"exited\" ||\n rt.desc.status === \"killed\" ||\n rt.desc.status === \"error\"\n ) {\n return false\n }\n rt.desc.status = \"killed\"\n rt.desc.endedAt = new Date().toISOString()\n // Close agent session first (graceful protocol shutdown), then\n // SIGTERM the underlying child/pty if any. Either branch is a\n // best-effort — the descriptor flip is what the UI surfaces.\n if (rt.agentSession) {\n void rt.agentSession.close().catch(() => undefined)\n }\n if (rt.pty) {\n try {\n rt.pty.kill(signal)\n } catch {\n // pty already gone — fall through\n }\n }\n rt.child?.kill(signal)\n schedulePersist()\n return true\n },\n forget(id) {\n const rt = sessions.get(id)\n if (!rt) return false\n // Don't leak: tear down the emitter so backfill listeners stop.\n rt.emitter.removeAllListeners()\n sessions.delete(id)\n schedulePersist()\n return true\n },\n shutdown() {\n shutdownImpl()\n },\n }\n\n /**\n * The actual shutdown logic, hoisted so both the explicit\n * `shutdown()` method AND the `process.on(\"exit\")` safety net\n * can call it. Sync (no awaits) so it works in the `exit` event\n * handler.\n *\n * Idempotent — `serve --interactive` calls gateway.stop() twice in\n * some Ctrl-C race paths (parent SIGINT handler + the child-exit\n * promise both fire), and `process.on(\"exit\")` ALSO fires at the\n * end of every termination path. Without the guard, the second\n * call clears the already-empty sessions Map and writes an empty\n * snapshot back to sessions.json, wiping history.\n */\n function shutdownImpl(): void {\n if (shutdownDone) return\n shutdownDone = true\n if (persistTimer) clearTimeout(persistTimer)\n if (persist) {\n try {\n process.off(\"exit\", onProcessExit)\n } catch {\n // ignore — handler may not be installed\n }\n }\n // Mark any still-alive sessions as killed BEFORE the final\n // flush so the snapshot accurately reflects what happened. On\n // the next boot, load reads these and we won't have to guess\n // (\"was running last time → assume killed\" is then a no-op).\n const nowIso = new Date().toISOString()\n for (const rt of sessions.values()) {\n rt.emitter.removeAllListeners()\n if (\n rt.desc.status === \"running\" ||\n rt.desc.status === \"starting\"\n ) {\n rt.desc.status = \"killed\"\n rt.desc.endedAt = nowIso\n if (rt.agentSession) {\n void rt.agentSession.close().catch(() => undefined)\n }\n if (rt.pty) {\n try {\n rt.pty.kill(\"SIGTERM\")\n } catch {\n // already exited\n }\n }\n rt.child?.kill(\"SIGTERM\")\n }\n }\n // Sync flush so quick sessions (spawned + ended in less than\n // PERSIST_DEBOUNCE_MS) aren't lost. The debounced async write\n // may have been cancelled by clearTimeout above, but a 200-byte\n // sync write at shutdown is cheap and the data needs to land.\n if (persist) {\n try {\n const snapshot = {\n savedAt: nowIso,\n sessions: Array.from(sessions.values()).map(s => s.desc),\n }\n mkdirSync(dirname(persistPath), { recursive: true })\n writeFileSync(persistPath, JSON.stringify(snapshot, null, 2) + \"\\n\")\n } catch {\n // best-effort — same policy as the async path\n }\n }\n sessions.clear()\n }\n}\n\n/**\n * Read the persisted snapshot at boot and reinflate session\n * descriptors as historical \"ghost\" entries. Sync-read because this\n * runs once at construction, the file is small (~200 entries), and\n * keeping it sync avoids making createSessionsRegistry async (would\n * cascade through createGateway + every embedding host).\n *\n * Anything that was \"running\"/\"starting\" when the daemon last died\n * gets re-classified as \"killed\" with endedAt=now — we can't tell\n * if the orphan PID survived the daemon's exit, and pretending it's\n * still alive would make attach/kill calls fail mysteriously. The\n * descriptor stays in the registry for history; the dashboard sees\n * it under SESSIONS, the user can `d` to forget.\n *\n * Ghosts carry NO live child / agentSession / pty — calls that\n * would interact with the underlying process degrade to no-ops.\n * Output ring buffers (lines + bytes) are empty: we don't persist\n * those, only the descriptor metadata.\n */\nfunction loadHistorySnapshot(\n persistPath: string,\n sessions: Map<string, SessionRuntime>,\n): void {\n let raw: string\n try {\n raw = readFileSync(persistPath, \"utf8\")\n } catch {\n return // ENOENT etc. — first boot, no history.\n }\n let parsed: { sessions?: SessionDescriptor[] }\n try {\n parsed = JSON.parse(raw)\n } catch {\n console.warn(\n `[sessions] history file ${persistPath} is malformed — ignoring`,\n )\n return\n }\n if (!Array.isArray(parsed.sessions)) return\n // Newest first so the FIFO cap drops oldest.\n const sorted = parsed.sessions\n .filter((s): s is SessionDescriptor => !!s && typeof s.id === \"string\")\n .sort((a, b) => b.startedAt.localeCompare(a.startedAt))\n .slice(0, HISTORY_CAP)\n const now = new Date().toISOString()\n for (const desc of sorted) {\n if (sessions.has(desc.id)) continue // collision with a live entry — keep live\n const wasAlive = desc.status === \"running\" || desc.status === \"starting\"\n const reclassified: SessionDescriptor = wasAlive\n ? {\n ...desc,\n status: \"killed\",\n endedAt: desc.endedAt ?? now,\n }\n : desc\n const rt: SessionRuntime = {\n desc: reclassified,\n recentLines: [],\n recentBytes: [],\n recentBytesSize: 0,\n emitter: new EventEmitter(),\n busy: false,\n textBuf: \"\",\n thoughtBuf: \"\",\n }\n rt.emitter.setMaxListeners(50)\n sessions.set(desc.id, rt)\n }\n}\n\n/** Minimal shell-quote — wraps args containing whitespace or quotes\n * so the rendered `command` field is copy-pasteable. */\nfunction quoteArg(arg: string): string {\n if (arg === \"\") return '\"\"'\n if (/^[a-zA-Z0-9._/=:@,+-]+$/.test(arg)) return arg\n return `\"${arg.replace(/([\"\\\\$`])/g, \"\\\\$1\")}\"`\n}\n","/**\n * mcp-proxy — connect the daemon as an MCP *client* to every server\n * the user imported via `~/.agentproto/imported-mcps.json`, and\n * surface their tools through dedicated MCP tools on the daemon's\n * own server. The chain looks like:\n *\n * operator (cloud Guilde) ──MCP──▶ agentproto-daemon (this proxy)\n * │\n * ├──stdio──▶ chrome-devtools-mcp\n * └──http───▶ goose-bridge\n *\n * v1 design choice: instead of re-registering each upstream tool\n * under a namespaced name (which requires JSON-Schema↔Zod conversion\n * for every exotic shape — recursive refs, oneOf, etc.), the proxy\n * exposes two indirection tools:\n * - `mcp_list_imported_tools(alias?)` lets the operator discover\n * what's available\n * - `mcp_call_imported(alias, toolName, args)` invokes a specific\n * tool, forwarding the JSON args verbatim\n *\n * Trade-off: agents do a 2-step (list → call) instead of seeing the\n * imports directly in their tool palette. We keep tool inputs\n * unconstrained at the MCP layer; validation is the upstream\n * server's job. v2 can re-expose namespaced tools once we ship a\n * solid JSON-Schema → Zod converter.\n *\n * Lifecycle: clients are connected lazily on the first call that\n * touches them and held open until daemon shutdown. The registry\n * notices new/removed imports by stat'ing the imports file's mtime\n * before each call — cheap, avoids forcing the HTTP routes to push.\n */\n\nimport { promises as fs } from \"node:fs\"\nimport { Client } from \"@modelcontextprotocol/sdk/client/index.js\"\nimport { StdioClientTransport } from \"@modelcontextprotocol/sdk/client/stdio.js\"\nimport { StreamableHTTPClientTransport } from \"@modelcontextprotocol/sdk/client/streamableHttp.js\"\nimport { SSEClientTransport } from \"@modelcontextprotocol/sdk/client/sse.js\"\nimport {\n loadImportedMcps,\n IMPORTED_MCPS_PATH,\n type ImportedMcpEntry,\n} from \"./mcp-imports.js\"\nimport type { DiscoveredMcp } from \"./mcp-discovery.js\"\n\ninterface ProxyClient {\n entry: ImportedMcpEntry\n /** Live MCP client. Null while a connect is in-flight or after a\n * connection error — the next call retries. */\n client: Client | null\n /** Tools list cached after the first successful fetch. Cleared on\n * disconnect so stale tool names don't survive a reconnect. */\n tools: ProxyToolDescriptor[] | null\n /** Last connection error message, kept so listAliases can surface\n * diagnostics to the operator without re-throwing on every list. */\n lastError: string | null\n}\n\nexport interface ProxyToolDescriptor {\n name: string\n description?: string\n /** JSON Schema as published by the upstream server. Forwarded to\n * the operator verbatim — they read it to figure out args. */\n inputSchema?: unknown\n}\n\nexport interface ProxyAliasSummary {\n alias: string\n importId: string\n source: DiscoveredMcp[\"source\"]\n type: DiscoveredMcp[\"type\"]\n /** \"connected\" | \"error\" | \"pending\" — pending = never tried yet. */\n status: \"connected\" | \"error\" | \"pending\"\n toolCount: number\n lastError?: string\n}\n\nexport interface CallResult {\n ok: true\n result: unknown\n}\nexport interface CallError {\n ok: false\n error: string\n}\nexport type ProxyCallOutcome = CallResult | CallError\n\nexport class McpProxyRegistry {\n private clients = new Map<string, ProxyClient>()\n private lastMtimeMs = 0\n /** Sentinel so we know whether the file has *ever* been read.\n * Distinguishes \"file missing on first call\" (legit empty state)\n * from \"we've read it before and it's gone\" (treat as empty too,\n * but only after closing live clients). */\n private hasReadOnce = false\n\n /**\n * Reload the imports file when its mtime has advanced. Avoids\n * repeated parsing when nothing changed — most calls are no-ops.\n * Disconnects clients whose import was removed; connects the new\n * set lazily (the first call that touches them).\n */\n async ensureCurrent(): Promise<void> {\n let mtimeMs = 0\n try {\n const st = await fs.stat(IMPORTED_MCPS_PATH())\n mtimeMs = st.mtimeMs\n } catch {\n // ENOENT — empty imports state. If we'd previously loaded\n // some, close them.\n mtimeMs = 0\n }\n if (this.hasReadOnce && mtimeMs === this.lastMtimeMs) return\n\n const config = await loadImportedMcps().catch(() => ({\n version: 1 as const,\n imports: [] as ImportedMcpEntry[],\n }))\n const wantedIds = new Set(config.imports.map(e => e.id))\n\n // Drop clients for imports the user removed.\n for (const [id, c] of this.clients.entries()) {\n if (!wantedIds.has(id)) {\n await safeClose(c.client)\n this.clients.delete(id)\n }\n }\n // Add placeholders for new imports — connect lazily.\n for (const entry of config.imports) {\n const existing = this.clients.get(entry.id)\n if (existing) {\n // Snapshot may have changed (user re-imported same id with\n // different command). Detect by comparing serialised\n // snapshots; on mismatch, force reconnect.\n if (\n JSON.stringify(existing.entry.snapshot) !==\n JSON.stringify(entry.snapshot)\n ) {\n await safeClose(existing.client)\n this.clients.set(entry.id, freshPlaceholder(entry))\n } else {\n existing.entry = entry\n }\n } else {\n this.clients.set(entry.id, freshPlaceholder(entry))\n }\n }\n this.lastMtimeMs = mtimeMs\n this.hasReadOnce = true\n }\n\n /**\n * Lazy connect: the first call to `connectIfNeeded(alias)`\n * actually opens the transport + handshakes. Subsequent calls\n * reuse the live client.\n */\n private async connectIfNeeded(alias: string): Promise<ProxyClient | null> {\n await this.ensureCurrent()\n const handle = this.findByAlias(alias)\n if (!handle) return null\n if (handle.client) return handle\n try {\n const client = await openClient(handle.entry)\n handle.client = client\n handle.lastError = null\n // Eagerly fetch tools so listTools doesn't pay the round-trip\n // on next call. Cheap (single tools/list request).\n const t = await client.listTools()\n handle.tools = t.tools.map(toDescriptor)\n return handle\n } catch (err) {\n handle.client = null\n handle.tools = null\n handle.lastError = err instanceof Error ? err.message : String(err)\n return handle\n }\n }\n\n /** Find a client handle by alias *or* import id (defensive — agents\n * sometimes pass the id from `list_imported_mcps`). */\n private findByAlias(aliasOrId: string): ProxyClient | undefined {\n for (const c of this.clients.values()) {\n if (c.entry.alias === aliasOrId) return c\n if (c.entry.id === aliasOrId) return c\n }\n return undefined\n }\n\n async listAliases(): Promise<ProxyAliasSummary[]> {\n await this.ensureCurrent()\n return Array.from(this.clients.values()).map(c => ({\n alias: c.entry.alias,\n importId: c.entry.id,\n source: c.entry.snapshot.source,\n type: c.entry.snapshot.type,\n status: c.client\n ? \"connected\"\n : c.lastError\n ? \"error\"\n : \"pending\",\n toolCount: c.tools?.length ?? 0,\n ...(c.lastError ? { lastError: c.lastError } : {}),\n }))\n }\n\n async listTools(\n alias: string\n ): Promise<{ ok: true; tools: ProxyToolDescriptor[] } | { ok: false; error: string }> {\n const handle = await this.connectIfNeeded(alias)\n if (!handle) return { ok: false, error: `unknown alias \"${alias}\"` }\n if (!handle.client || !handle.tools) {\n return {\n ok: false,\n error: handle.lastError ?? \"client not connected\",\n }\n }\n return { ok: true, tools: handle.tools }\n }\n\n async callTool(\n alias: string,\n toolName: string,\n args: unknown\n ): Promise<ProxyCallOutcome> {\n const handle = await this.connectIfNeeded(alias)\n if (!handle) return { ok: false, error: `unknown alias \"${alias}\"` }\n if (!handle.client) {\n return {\n ok: false,\n error: handle.lastError ?? \"client not connected\",\n }\n }\n try {\n const result = await handle.client.callTool({\n name: toolName,\n arguments:\n args && typeof args === \"object\"\n ? (args as Record<string, unknown>)\n : {},\n })\n return { ok: true, result }\n } catch (err) {\n // Mark the client as dirty — the connection may have died\n // mid-call (process crash, http server restart). The next call\n // re-opens via connectIfNeeded.\n const msg = err instanceof Error ? err.message : String(err)\n if (/closed|disconnect|EPIPE|ECONNRESET/i.test(msg)) {\n await safeClose(handle.client)\n handle.client = null\n handle.tools = null\n handle.lastError = msg\n }\n return { ok: false, error: msg }\n }\n }\n\n async closeAll(): Promise<void> {\n await Promise.all(\n Array.from(this.clients.values()).map(c => safeClose(c.client))\n )\n this.clients.clear()\n }\n}\n\nfunction freshPlaceholder(entry: ImportedMcpEntry): ProxyClient {\n return { entry, client: null, tools: null, lastError: null }\n}\n\nfunction toDescriptor(tool: {\n name: string\n description?: string\n inputSchema?: unknown\n}): ProxyToolDescriptor {\n return {\n name: tool.name,\n ...(tool.description ? { description: tool.description } : {}),\n ...(tool.inputSchema ? { inputSchema: tool.inputSchema } : {}),\n }\n}\n\n/**\n * Replace `${VAR}` and `${VAR:-default}` placeholders in env values\n * with the corresponding `process.env` entry (or default), the same\n * way claude-code / cursor expand mcp-server env. When the variable\n * is unset and no default is given, the placeholder is dropped — the\n * upstream then sees the env var as absent rather than as the\n * literal `${MISSING_VAR}`, which it usually treats as \"use default\n * config\" rather than \"explicit empty token\".\n */\nfunction expandEnvPlaceholders(\n raw: Record<string, string>\n): Record<string, string> {\n const out: Record<string, string> = {}\n for (const [k, v] of Object.entries(raw)) {\n const expanded = v.replace(\n /\\$\\{([A-Z_][A-Z0-9_]*)(?::-([^}]*))?\\}/gi,\n (_match, name: string, fallback: string | undefined) => {\n const fromEnv = process.env[name]\n if (fromEnv !== undefined) return fromEnv\n if (fallback !== undefined) return fallback\n return \"\"\n }\n )\n // Drop the var entirely if it expanded to empty — keeps the\n // upstream from receiving an empty-string token + treating it as\n // a real (but invalid) credential.\n if (expanded.length === 0) continue\n out[k] = expanded\n }\n return out\n}\n\nasync function safeClose(client: Client | null): Promise<void> {\n if (!client) return\n try {\n await client.close()\n } catch {\n // best-effort\n }\n}\n\n/**\n * Open a transport for a discovered MCP. stdio spawns the command;\n * http/sse open over the network. Returns a connected `Client` on\n * success; throws with a useful message on failure.\n */\nasync function openClient(entry: ImportedMcpEntry): Promise<Client> {\n const snap = entry.snapshot\n const client = new Client(\n { name: \"agentproto-daemon-proxy\", version: \"0.1.0\" },\n { capabilities: {} }\n )\n if (snap.type === \"stdio\") {\n if (!snap.command) {\n throw new Error(\n `import \"${entry.alias}\" is stdio but has no command field`\n )\n }\n // claude-code / cursor / vscode all support `${VAR}` placeholders\n // in the env map (and the more permissive `${VAR:-default}`\n // form). Our scanner stores the snapshot verbatim — expand at\n // spawn time so live env changes work without a re-import, and\n // tokens like REPLICATE_API_TOKEN don't end up forwarded as the\n // literal string `${REPLICATE_API_TOKEN}`.\n const expandedEnv = expandEnvPlaceholders(snap.env ?? {})\n const transport = new StdioClientTransport({\n command: snap.command,\n args: snap.args ?? [],\n env: { ...process.env, ...expandedEnv } as Record<string, string>,\n // Pipe stderr so we can include it in the error message instead of\n // surfacing the opaque \"Connection closed\" MCP error code.\n stderr: \"pipe\",\n })\n const stderrBuf: string[] = []\n transport.stderr?.on(\"data\", (chunk: Buffer | string) => {\n stderrBuf.push(typeof chunk === \"string\" ? chunk : chunk.toString(\"utf8\"))\n if (stderrBuf.length > 40) stderrBuf.shift()\n })\n try {\n await client.connect(transport)\n } catch (err) {\n const stderrText = stderrBuf.join(\"\").trim()\n const msg = err instanceof Error ? err.message : String(err)\n throw new Error(stderrText ? `${msg}\\nstderr: ${stderrText.slice(-600)}` : msg)\n }\n return client\n }\n if (snap.type === \"http\") {\n if (!snap.url) throw new Error(`import \"${entry.alias}\" has no url`)\n const transport = new StreamableHTTPClientTransport(new URL(snap.url), {\n requestInit: {\n headers: snap.headers ?? {},\n },\n })\n await client.connect(transport)\n return client\n }\n if (snap.type === \"sse\") {\n if (!snap.url) throw new Error(`import \"${entry.alias}\" has no url`)\n const transport = new SSEClientTransport(new URL(snap.url), {\n requestInit: {\n headers: snap.headers ?? {},\n },\n })\n await client.connect(transport)\n return client\n }\n throw new Error(\n `import \"${entry.alias}\" has unsupported transport type \"${snap.type}\"`\n )\n}\n","/**\n * Quick Cloudflare Tunnel provider — zero-credential variant.\n *\n * Spawns `cloudflared tunnel --config <ours>` against an isolated\n * config file we write per-tunnel into the workspace, parses the\n * assigned `*.trycloudflare.com` URL out of cloudflared's stderr.\n * No CF account, no API token, no DNS records. Trade-off: URL is\n * ephemeral (different each run) and there's no Cloudflare Access\n * gating — auth happens at the upstream (gateway bearer token, or\n * whatever the tunneled service does for itself).\n *\n * ## Why we don't use `--url`\n *\n * `cloudflared --url http://...` synthesises an inline ingress block\n * but ALSO merges anything from `~/.cloudflared/config.yml`. If a user\n * has prior named-tunnel config there, hostname-specific rules can\n * shadow the inline rule and every request falls through to the\n * built-in `http_status:404` catch-all (the symptom: cloudflared logs\n * `ingressRule=2 originService=http_status:404` for every request,\n * origin never sees traffic). Writing our own config and passing it\n * via `--config` is hermetic — `~/.cloudflared/config.yml` is ignored\n * entirely, so the URL-forward rule always wins.\n *\n * Use this for: ad-hoc demos, \"let me try this from another machine\n * for 10 minutes\", iterating on the remote-MCP UX before committing\n * to a domain.\n *\n * For: persistent URLs / SSO gating, use the named-CF provider (TBD).\n *\n * ## cloudflared discovery\n *\n * Detected on PATH at start time. Missing → throw with a pointer to\n * the install instructions. We deliberately don't bundle binaries —\n * keeps the OSS package free of platform-specific blobs and defers the\n * \"which version\" maintenance tax.\n */\n\nimport { spawn, type ChildProcess } from \"node:child_process\"\nimport { promisify } from \"node:util\"\nimport { execFile } from \"node:child_process\"\nimport { mkdir, writeFile, rm } from \"node:fs/promises\"\nimport { join } from \"node:path\"\nimport { randomBytes } from \"node:crypto\"\n\nimport type {\n ProviderStartOptions,\n ProviderStartResult,\n RemoteProvider,\n} from \"../remote-controller.js\"\n\nconst execFileAsync = promisify(execFile)\n\nconst URL_REGEX = /https:\\/\\/[a-z0-9-]+\\.trycloudflare\\.com/i\n\nconst STARTUP_TIMEOUT_MS = 30_000\n\nexport function quickTunnelProvider(): RemoteProvider {\n let child: ChildProcess | null = null\n let configPath: string | null = null\n\n return {\n id: \"quick\",\n async start(opts: ProviderStartOptions): Promise<ProviderStartResult> {\n await assertCloudflaredOnPath()\n const targetUrl = `http://${opts.target.host}:${opts.target.port}`\n\n // Per-tunnel sentinel config — the only reason it exists is to\n // override `~/.cloudflared/config.yml` so its ingress rules can't\n // shadow our inline `--url` rule. We deliberately do NOT include\n // an `ingress:` block here: quick-tunnel mode treats `--url` as\n // the routing source of truth, and a stray top-level `ingress:`\n // would fight it. Random suffix avoids collisions when dev\n // restarts overlap.\n const id = randomBytes(4).toString(\"hex\")\n const dir = join(opts.workspace, \".agentproto\")\n await mkdir(dir, { recursive: true })\n configPath = join(dir, `cloudflared-${id}.yml`)\n const configBody = [\n `# generated by agentproto-runtime — sentinel only`,\n `# overrides ~/.cloudflared/config.yml so its ingress rules`,\n `# don't shadow the inline --url rule. Safe to delete when the`,\n `# tunnel is down.`,\n `no-autoupdate: true`,\n `loglevel: debug`,\n ``,\n ].join(\"\\n\")\n await writeFile(configPath, configBody, \"utf8\")\n const proc = spawn(\n \"cloudflared\",\n [\"tunnel\", \"--config\", configPath, \"--url\", targetUrl],\n { stdio: [\"ignore\", \"pipe\", \"pipe\"], shell: false },\n )\n child = proc\n\n const url = await new Promise<string>((resolve, reject) => {\n let settled = false\n const timer = setTimeout(() => {\n if (settled) return\n settled = true\n try {\n proc.kill(\"SIGTERM\")\n } catch {\n /* noop */\n }\n reject(\n new Error(\n `cloudflared did not emit a public URL within ${STARTUP_TIMEOUT_MS / 1000}s`,\n ),\n )\n }, STARTUP_TIMEOUT_MS)\n\n const onData = (chunk: Buffer) => {\n const text = chunk.toString(\"utf8\")\n for (const line of text.split(/\\r?\\n/)) {\n if (line.length > 0) opts.onLog?.(`[cloudflared] ${line}`)\n }\n if (settled) return\n const match = text.match(URL_REGEX)\n if (match) {\n settled = true\n clearTimeout(timer)\n resolve(match[0])\n }\n }\n // cloudflared writes the URL to stderr (it reserves stdout for\n // proxied traffic / structured output in some modes). Watch\n // both for safety.\n proc.stderr?.on(\"data\", onData)\n proc.stdout?.on(\"data\", onData)\n\n proc.once(\"error\", err => {\n if (settled) return\n settled = true\n clearTimeout(timer)\n reject(err)\n })\n proc.once(\"exit\", (code, signal) => {\n if (settled) return\n settled = true\n clearTimeout(timer)\n reject(\n new Error(\n `cloudflared exited before emitting a URL (code=${code}, signal=${signal})`,\n ),\n )\n })\n })\n\n // Detach the resolver listener (we already captured the URL); leave\n // the log-forwarder attached so the gateway's RuntimeEvents stream\n // sees ongoing tunnel chatter.\n proc.once(\"exit\", (code, signal) => {\n opts.onLog?.(\n `[cloudflared] exited (code=${code ?? \"?\"} signal=${signal ?? \"-\"})`,\n )\n })\n\n return { publicUrl: url, pid: proc.pid ?? null }\n },\n\n async stop(): Promise<void> {\n const proc = child\n const cfg = configPath\n child = null\n configPath = null\n // Best-effort cleanup of the sentinel config — losing it means a\n // stale `.agentproto/cloudflared-<id>.yml` file, no functional\n // impact. We do this even if the proc never started.\n if (cfg) {\n try {\n await rm(cfg, { force: true })\n } catch {\n /* noop */\n }\n }\n if (!proc || proc.exitCode !== null) return\n proc.kill(\"SIGTERM\")\n // Hard-kill backstop after 3s if cloudflared ignores SIGTERM.\n const timer = setTimeout(() => {\n try {\n proc.kill(\"SIGKILL\")\n } catch {\n /* noop */\n }\n }, 3_000)\n timer.unref()\n await new Promise<void>(resolve => {\n if (proc.exitCode !== null) {\n clearTimeout(timer)\n resolve()\n return\n }\n proc.once(\"exit\", () => {\n clearTimeout(timer)\n resolve()\n })\n })\n },\n }\n}\n\nasync function assertCloudflaredOnPath(): Promise<void> {\n try {\n await execFileAsync(\"cloudflared\", [\"--version\"], { timeout: 3_000 })\n } catch {\n throw new Error(\n \"cloudflared not found on PATH. Install it first:\\n\" +\n \" macOS: brew install cloudflared\\n\" +\n \" Linux: https://pkg.cloudflare.com/index.html\\n\" +\n \" Windows: winget install --id Cloudflare.cloudflared\\n\" +\n \"Or download a prebuilt binary from https://github.com/cloudflare/cloudflared/releases.\",\n )\n }\n}\n","/**\n * RemoteController — owns the gateway's \"publish to the internet\" state.\n *\n * One singleton per gateway. Holds:\n * - the current tunnel provider's child process (cloudflared, …)\n * - the bearer token gating /mcp once the tunnel is up\n * - persisted state in `<workspace>/.agentproto/remote.json`\n *\n * The controller is the *only* component that mutates auth at runtime.\n * The HTTP server reads auth via a getter (see `AuthSource` in\n * http-server.ts), so flipping `enable() / disable()` here takes effect\n * on the next request — no restart, no race.\n *\n * ## Provider model\n *\n * Each provider implements `RemoteProvider` (start / stop / status).\n * v1 ships only `quick` (Cloudflare Quick Tunnel — no API key, no DNS,\n * ephemeral `*.trycloudflare.com` URL). Named CF Tunnel and Tailscale\n * land as additional implementations.\n *\n * ## Token model\n *\n * On enable we generate a 32-byte random bearer token, return it once\n * to the caller, and persist only its sha256 hash to disk. Same model\n * as a Stripe API key — losing the plaintext means rotating, not\n * recovering. This keeps `.agentproto/remote.json` safe to commit by\n * accident (it leaks the URL, not the credential).\n *\n * ## Security note\n *\n * The CF API token (when used by named-tunnel provider) is *never*\n * accepted as MCP tool input. The controller reads it from\n * `~/.config/agentproto/cloudflare.json` or `$CLOUDFLARE_API_TOKEN`.\n * Otherwise a remote agent could exfiltrate it through `remote_enable`.\n */\n\nimport { randomBytes, createHash } from \"node:crypto\"\nimport { mkdir, writeFile, readFile, chmod, rm } from \"node:fs/promises\"\nimport { existsSync } from \"node:fs\"\nimport { join } from \"node:path\"\n\nimport type { AuthOptions } from \"./http-server.js\"\nimport { quickTunnelProvider } from \"./remote-providers/quick.js\"\n\nexport interface RemoteState {\n provider: \"quick\"\n publicUrl: string\n bearerTokenHash: string\n createdAt: string\n /** PID of the supervised tunnel child process, if any. */\n pid: number | null\n /** Local target the tunnel forwards to (host + port). */\n target: { host: string; port: number }\n /**\n * Whether the tunnel exposes the gateway itself (true) or some other\n * local service (false). Bearer auth + loopback bypass only matter\n * for the gateway path; arbitrary-target tunnels are pure passthrough\n * and the daemon does not gate them.\n */\n exposesGateway: boolean\n}\n\nexport interface EnableInput {\n provider?: \"quick\"\n /**\n * Local port to expose. Defaults to the gateway's own port — i.e.\n * \"publish this MCP server.\" Pass any other port to expose a\n * different local service (Supabase 54371, a Vite dev server, …)\n * without spinning up a separate tunnel manager.\n */\n targetPort?: number\n /**\n * Host the tunnel forwards to. Defaults to `127.0.0.1`. Setting it\n * to `localhost` resolves through DNS (IPv6 first on most systems);\n * keep `127.0.0.1` unless the target is explicitly IPv6-bound.\n */\n targetHost?: string\n}\n\nexport interface EnableResult {\n publicUrl: string\n /**\n * Bearer token issued by this gateway. Only meaningful when the\n * tunnel exposes the gateway itself (default). For arbitrary-target\n * tunnels (`targetPort != gateway.port`) the daemon does not gate\n * the proxied service, and this is omitted.\n */\n bearerToken?: string\n /**\n * `<publicUrl>/mcp`. Only emitted when exposing the gateway.\n */\n mcpEndpoint?: string\n /**\n * Paste-ready `.mcp.json` snippet. Only emitted when exposing the\n * gateway.\n */\n mcpConfigSnippet?: string\n provider: \"quick\"\n target: { host: string; port: number }\n exposesGateway: boolean\n}\n\nexport interface RemoteStatus {\n enabled: boolean\n provider?: \"quick\"\n publicUrl?: string\n pid?: number | null\n createdAt?: string\n target?: { host: string; port: number }\n exposesGateway?: boolean\n /** Last error from the provider, if any (since last enable). */\n lastError?: string\n}\n\n/**\n * A pluggable tunnel provider.\n *\n * `start` returns the public URL once the upstream tunnel is ready\n * (e.g. for cloudflared, after parsing the trycloudflare.com URL out of\n * its stderr). `stop` is idempotent — calling it twice or on an\n * already-dead child must not throw.\n */\nexport interface RemoteProvider {\n readonly id: \"quick\"\n start(opts: ProviderStartOptions): Promise<ProviderStartResult>\n stop(): Promise<void>\n}\n\nexport interface ProviderStartOptions {\n /** Local target the tunnel forwards to. */\n target: { host: string; port: number }\n /** Workspace path — for log / state files. */\n workspace: string\n /** Called whenever the provider has a status update worth logging. */\n onLog?: (line: string) => void\n}\n\nexport interface ProviderStartResult {\n publicUrl: string\n pid: number | null\n}\n\nexport interface RemoteControllerOptions {\n workspace: string\n port: number\n /** Hook for surfacing provider logs through RuntimeEvents. */\n onLog?: (line: string) => void\n}\n\nconst STATE_FILE_REL = \".agentproto/remote.json\"\n\nexport class RemoteController {\n private state: RemoteState | null = null\n private bearerToken: string | null = null\n private provider: RemoteProvider | null = null\n private lastError: string | undefined\n private readonly opts: RemoteControllerOptions\n\n constructor(opts: RemoteControllerOptions) {\n this.opts = opts\n }\n\n /**\n * Auth getter handed to startHttpServer. The HTTP server calls this\n * on every request so flipping enable/disable is effective without\n * a restart.\n */\n readonly readAuth = (): AuthOptions => {\n if (this.bearerToken === null) return { mode: \"none\" }\n return { mode: \"bearer\", token: this.bearerToken }\n }\n\n status(): RemoteStatus {\n if (!this.state) {\n return { enabled: false, lastError: this.lastError }\n }\n return {\n enabled: true,\n provider: this.state.provider,\n publicUrl: this.state.publicUrl,\n pid: this.state.pid,\n createdAt: this.state.createdAt,\n target: this.state.target,\n exposesGateway: this.state.exposesGateway,\n lastError: this.lastError,\n }\n }\n\n async enable(input: EnableInput): Promise<EnableResult> {\n if (this.state) {\n // Idempotent: returning the existing config would leak the\n // bearer token (we only have the hash). Force teardown first so\n // re-enable always rotates the token. Surface this in the docs.\n throw new Error(\n \"remote tunnel already active — call remote_disable first to rotate\",\n )\n }\n const providerId = input.provider ?? \"quick\"\n const provider = pickProvider(providerId)\n this.lastError = undefined\n\n const target = {\n host: input.targetHost ?? \"127.0.0.1\",\n port: input.targetPort ?? this.opts.port,\n }\n const exposesGateway =\n target.host === \"127.0.0.1\" && target.port === this.opts.port\n\n let started: ProviderStartResult\n try {\n started = await provider.start({\n target,\n workspace: this.opts.workspace,\n onLog: line => {\n this.opts.onLog?.(line)\n },\n })\n } catch (err) {\n this.lastError = errToMessage(err)\n throw err\n }\n\n // Bearer auth + token issuance only matter when the tunnel exposes\n // *this* gateway. For arbitrary-target tunnels (e.g. Supabase on\n // 54371) the daemon is just provisioning a public passthrough; the\n // proxied service does its own authn.\n let bearerToken: string | null = null\n let bearerTokenHash = \"\"\n if (exposesGateway) {\n bearerToken = randomBytes(32).toString(\"base64url\")\n bearerTokenHash = sha256(bearerToken)\n }\n\n const state: RemoteState = {\n provider: providerId,\n publicUrl: started.publicUrl,\n bearerTokenHash,\n createdAt: new Date().toISOString(),\n pid: started.pid,\n target,\n exposesGateway,\n }\n\n this.state = state\n this.bearerToken = bearerToken\n this.provider = provider\n\n await persistState(this.opts.workspace, state)\n\n const result: EnableResult = {\n provider: providerId,\n publicUrl: started.publicUrl,\n target,\n exposesGateway,\n }\n if (exposesGateway && bearerToken) {\n const mcpEndpoint = `${started.publicUrl}/mcp`\n result.bearerToken = bearerToken\n result.mcpEndpoint = mcpEndpoint\n result.mcpConfigSnippet = buildMcpConfigSnippet(mcpEndpoint, bearerToken)\n }\n return result\n }\n\n async disable(): Promise<{ disabled: boolean }> {\n if (!this.state) return { disabled: false }\n const provider = this.provider\n this.state = null\n this.bearerToken = null\n this.provider = null\n if (provider) {\n try {\n await provider.stop()\n } catch (err) {\n this.lastError = errToMessage(err)\n }\n }\n await clearState(this.opts.workspace)\n return { disabled: true }\n }\n\n /**\n * Stop the provider on gateway shutdown. Does NOT clear persisted\n * state — that survives across restarts so the user can `remote_status`\n * after rebooting and see \"stale state, run remote_enable to refresh\".\n * (Stale-recovery semantics land in v2; today we just leave the file.)\n */\n async shutdown(): Promise<void> {\n if (this.provider) {\n try {\n await this.provider.stop()\n } catch {\n /* swallow — gateway is shutting down anyway */\n }\n }\n }\n}\n\n// ── helpers ────────────────────────────────────────────────────────────\n\nfunction pickProvider(id: \"quick\"): RemoteProvider {\n if (id === \"quick\") return quickTunnelProvider()\n // Exhaustive guard — adding \"named-cf\" / \"tailscale\" later forces this\n // switch to be updated, otherwise TS will yell.\n const _exhaustive: never = id\n throw new Error(`unknown remote provider: ${String(_exhaustive)}`)\n}\n\nfunction sha256(input: string): string {\n return createHash(\"sha256\").update(input).digest(\"hex\")\n}\n\nfunction errToMessage(err: unknown): string {\n return err instanceof Error ? err.message : String(err)\n}\n\nasync function persistState(workspace: string, state: RemoteState): Promise<void> {\n const dir = join(workspace, \".agentproto\")\n await mkdir(dir, { recursive: true })\n const file = join(dir, \"remote.json\")\n await writeFile(file, JSON.stringify(state, null, 2) + \"\\n\", \"utf8\")\n // mode 0600 — even though we only persist the hash, the URL itself\n // is sensitive (knowing it lets an attacker brute-force the token).\n try {\n await chmod(file, 0o600)\n } catch {\n /* best-effort on platforms where chmod is a noop */\n }\n}\n\nasync function clearState(workspace: string): Promise<void> {\n const file = join(workspace, \".agentproto/remote.json\")\n if (!existsSync(file)) return\n await rm(file, { force: true })\n}\n\n/**\n * Best-effort load of persisted state on boot. We don't restore the\n * bearer token from this — the hash is one-way — so a rebooted gateway\n * that finds a stale `remote.json` will surface it via `remote_status`\n * and require a fresh `remote_enable` to mint a new token.\n *\n * Exposed mostly for diagnostics; not used by the controller today.\n */\nexport async function loadPersistedState(\n workspace: string,\n): Promise<RemoteState | null> {\n const file = join(workspace, STATE_FILE_REL)\n if (!existsSync(file)) return null\n try {\n const raw = await readFile(file, \"utf8\")\n return JSON.parse(raw) as RemoteState\n } catch {\n return null\n }\n}\n\nfunction buildMcpConfigSnippet(endpoint: string, token: string): string {\n return JSON.stringify(\n {\n mcpServers: {\n \"agentproto-remote\": {\n transport: \"http\",\n url: endpoint,\n headers: { Authorization: `Bearer ${token}` },\n },\n },\n },\n null,\n 2,\n )\n}\n","/**\n * MCP tools that drive RemoteController — the gateway's \"publish to\n * the internet\" surface.\n *\n * Three tools, mirroring the controller's lifecycle:\n *\n * remote_enable — bring up a tunnel, mint bearer token, return the\n * public /mcp URL + a paste-ready .mcp.json snippet\n * remote_disable — tear down tunnel, revoke token, drop bearer auth\n * remote_status — read-only — provider, URL, pid, lastError\n *\n * Why this lives on the MCP surface (not a separate CLI):\n * - The user already has an MCP client connected (that's how they\n * started talking to the gateway in the first place). One tool call\n * replaces an entire CLI install + auth dance.\n * - The bearer token comes back as part of the MCP response, so it\n * doesn't have to land on the user's clipboard.\n */\n\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\"\nimport { z } from \"zod\"\n\nimport type { RemoteController } from \"./remote-controller.js\"\n\nexport interface RegisterRemoteToolsOptions {\n controller: RemoteController\n}\n\nfunction text(value: string | object): {\n content: Array<{ type: \"text\"; text: string }>\n} {\n return {\n content: [\n {\n type: \"text\",\n text: typeof value === \"string\" ? value : JSON.stringify(value, null, 2),\n },\n ],\n }\n}\n\nexport function registerRemoteTools(\n server: McpServer,\n opts: RegisterRemoteToolsOptions,\n): void {\n const { controller } = opts\n\n server.tool(\n \"remote_enable\",\n \"Publish a local port to the internet via Cloudflare. By default exposes \" +\n \"this gateway and gates it with a bearer token (returned ONCE in the \" +\n \"response — store it; only its hash is persisted). Pass `targetPort` to \" +\n \"tunnel a different local service (Supabase, dev server, …); in that mode \" +\n \"the daemon does not gate the proxied traffic — the upstream service \" +\n \"handles its own auth. Returns the public URL plus a paste-ready \" +\n \"`.mcp.json` snippet (gateway mode only). Re-running while a tunnel is \" +\n \"already up errors; call `remote_disable` first to rotate.\",\n {\n provider: z\n .enum([\"quick\"])\n .optional()\n .describe(\n \"Tunnel backend. `quick` = Cloudflare Quick Tunnel (no API key, ephemeral *.trycloudflare.com URL). Defaults to `quick`. Named-CF / Tailscale providers TBD.\",\n ),\n targetPort: z\n .number()\n .int()\n .min(1)\n .max(65535)\n .optional()\n .describe(\n \"Local port to expose. Defaults to this gateway's own port (= publish the MCP server). Pass another port to tunnel a different local service (e.g. 54371 for Supabase) — in that mode bearer auth is OFF since the upstream handles its own gating.\",\n ),\n targetHost: z\n .string()\n .optional()\n .describe(\n \"Host the tunnel forwards to. Defaults to `127.0.0.1`. Use `localhost` only if the target is explicitly IPv6-bound; cloudflared resolves DNS and IPv6-first lookups can break IPv4-only origins.\",\n ),\n },\n async ({ provider, targetPort, targetHost }) => {\n const result = await controller.enable({ provider, targetPort, targetHost })\n return text(result)\n },\n )\n\n server.tool(\n \"remote_disable\",\n \"Tear down the active remote tunnel and drop bearer auth back to \" +\n \"loopback-only. Idempotent — calling when no tunnel is active is a no-op.\",\n {},\n async () => {\n const result = await controller.disable()\n return text(result)\n },\n )\n\n server.tool(\n \"remote_status\",\n \"Report whether a remote tunnel is active. When active: provider, \" +\n \"public URL, supervised PID, createdAt. The bearer token itself is \" +\n \"never returned by status — it was shown once at enable.\",\n {},\n async () => {\n return text(controller.status())\n },\n )\n}\n","/**\n * `WorkspaceFs` — minimal `readFile` / `writeFile` adapter over a\n * workspace directory. Mirrors the `McpWorkspace.filesystem` shape\n * used by `@guilde/mcp` so the daemon can be plugged in as the\n * workspace backend for a Guilde MCP server (via its\n * `loadGuildWorkspace` injection point) without re-shimming.\n *\n * All paths are workspace-relative. Absolute paths are rejected to\n * keep the surface predictable when the daemon binds to a public\n * port.\n */\n\nimport { existsSync } from \"node:fs\"\nimport { mkdir, readFile as fsReadFile, writeFile as fsWriteFile } from \"node:fs/promises\"\nimport { dirname, isAbsolute, join, normalize, relative, resolve } from \"node:path\"\n\nexport interface WorkspaceFs {\n readFile(path: string): Promise<string>\n writeFile(path: string, content: string | Uint8Array): Promise<void>\n exists(path: string): Promise<boolean>\n}\n\nexport interface CreateWorkspaceFsOptions {\n /** Absolute path to the workspace root. */\n workspace: string\n}\n\nexport class WorkspacePathError extends Error {\n constructor(message: string) {\n super(message)\n this.name = \"WorkspacePathError\"\n }\n}\n\nexport function createWorkspaceFs(opts: CreateWorkspaceFsOptions): WorkspaceFs {\n const root = resolve(opts.workspace)\n\n function resolvePath(path: string): string {\n if (typeof path !== \"string\" || path.length === 0) {\n throw new WorkspacePathError(\"path must be a non-empty string\")\n }\n if (isAbsolute(path)) {\n throw new WorkspacePathError(\n \"absolute paths are not allowed; use a workspace-relative path\",\n )\n }\n const joined = normalize(join(root, path))\n const rel = relative(root, joined)\n if (rel.startsWith(\"..\") || isAbsolute(rel)) {\n throw new WorkspacePathError(\n `path escapes the workspace: '${path}'`,\n )\n }\n return joined\n }\n\n return {\n async readFile(path) {\n const abs = resolvePath(path)\n const buf = await fsReadFile(abs)\n return buf.toString(\"utf8\")\n },\n async writeFile(path, content) {\n const abs = resolvePath(path)\n await mkdir(dirname(abs), { recursive: true })\n await fsWriteFile(abs, content)\n },\n async exists(path) {\n try {\n const abs = resolvePath(path)\n return existsSync(abs)\n } catch {\n return false\n }\n },\n }\n}\n","/**\n * @agentproto/runtime — long-running gateway around an agentproto\n * workspace dir.\n *\n * Composes:\n * - `@agentproto/mcp-server` (CRUD verbs over registered specs)\n * - HTTP transport (Streamable HTTP) on a configurable port\n * - HEARTBEAT.md autonomy loop\n * - Append-only conversation persistence (`conversations/<id>.md`)\n * - Workspace filesystem adapter (compatible with the\n * `McpWorkspace.filesystem` shape used by `@guilde/mcp`)\n *\n * Single entry point: `createGateway(opts)`. Returns a handle with\n * `url` and `stop()` — the rest of the surface lives on the HTTP\n * server.\n */\n\nimport { randomUUID } from \"node:crypto\"\nimport { existsSync } from \"node:fs\"\nimport { readFile } from \"node:fs/promises\"\nimport { join, resolve } from \"node:path\"\nimport { createMcpServer } from \"@agentproto/mcp-server\"\nimport type { DoctypeSpec } from \"@agentproto/manifest\"\n\nimport { writeRuntimeMeta } from \"./agentproto-dir.js\"\nimport { registerCommandTools } from \"./command-tools.js\"\nimport { fileConversationStore } from \"./conversations.js\"\nimport { createRuntimeEvents } from \"./events.js\"\nimport { registerFsTools } from \"./fs-tools.js\"\nimport { registerSessionTools } from \"./session-tools.js\"\nimport { startHeartbeat, type BuildHeartbeatAgent } from \"./heartbeat.js\"\nimport {\n startHttpServer,\n type AuthOptions,\n type AgentAdapterResolver,\n type AgentAdapterLister,\n} from \"./http-server.js\"\nimport {\n createSessionsRegistry,\n type SessionsRegistry,\n type PtyFactory,\n} from \"./sessions.js\"\nimport { McpProxyRegistry } from \"./mcp-proxy.js\"\n\nexport type {\n AgentAdapterResolver,\n AgentAdapterLister,\n AdapterListEntry,\n} from \"./http-server.js\"\nexport type {\n AgentSessionLike,\n AgentStreamEvent,\n SessionDescriptor,\n SessionKind,\n SessionStatus,\n SpawnSessionInput,\n SpawnAgentInput,\n SessionsRegistry,\n} from \"./sessions.js\"\nimport { RemoteController } from \"./remote-controller.js\"\nimport { registerRemoteTools } from \"./remote-tools.js\"\nimport { createWorkspaceFs, type WorkspaceFs } from \"./workspace-fs.js\"\n\nexport type { ConversationStore, ConversationMeta, ConversationTurn } from \"./conversations.js\"\nexport type { HeartbeatRunner, BuildHeartbeatAgent, HeartbeatAgent } from \"./heartbeat.js\"\nexport type { RuntimeEvent, RuntimeEvents } from \"./events.js\"\nexport type { WorkspaceFs } from \"./workspace-fs.js\"\nexport { parseDuration } from \"./heartbeat.js\"\nexport { createWorkspaceFs } from \"./workspace-fs.js\"\nexport {\n sweepStaleRuntimeMetas,\n unlinkRuntimeMeta,\n readRuntimeMeta,\n type RuntimeMeta,\n} from \"./agentproto-dir.js\"\nexport { fileConversationStore } from \"./conversations.js\"\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype AnySpec = DoctypeSpec<any, any>\n\nexport interface CreateGatewayOptions {\n /** Absolute path to the workspace dir. */\n workspace: string\n /** AIP doctype specs to expose as MCP CRUD verbs. */\n specs: readonly AnySpec[]\n /** Port to bind. Default 18790. */\n port?: number\n /** Bind host. Default `127.0.0.1` (loopback). Set `0.0.0.0` for LAN. */\n bind?: string\n /** Auth mode. Default `none` (safe only on loopback). */\n auth?: AuthOptions\n /**\n * Resolves a heartbeat-runnable agent from its workspace id.\n * Required for HEARTBEAT.md to do anything; without it ticks emit\n * `heartbeat-error` events instead of generating.\n */\n buildAgent?: BuildHeartbeatAgent\n /** Server name advertised over MCP. */\n name?: string\n /** Server version advertised over MCP. */\n version?: string\n /**\n * Run BOOT.md once at startup. Pass `false` to disable. Defaults to\n * `true`. The boot file is plain markdown — frontmatter-free; the\n * agent named in `defaultBootAgent` (or skipped if unset) gets the\n * body as a single prompt and the reply is appended to a `boot-<iso>`\n * conversation.\n */\n boot?: boolean\n /** Agent id used for BOOT.md if no per-file frontmatter. */\n defaultBootAgent?: string\n /** Optional adapter resolver — when provided, enables\n * `POST /sessions/agent` (long-running agent CLIs like\n * claude-code / hermes via the @agentproto/cli adapter system).\n * Without this, /sessions still works for raw `argv` spawns. */\n resolveAgentAdapter?: AgentAdapterResolver\n /** Optional adapter lister — when provided, enables\n * `GET /adapters` HTTP route + `list_adapters` MCP tool so UIs\n * can discover what's installed on the host. */\n listAgentAdapters?: AgentAdapterLister\n /** Optional PTY factory (node-pty wrapper, typically from the cli\n * layer's `loadNodePtyFactory()`). When provided, enables\n * `POST /sessions/terminal`, the `start_terminal_session` MCP\n * tool family, and the `/sessions/:id/pty` WebSocket. Without it,\n * those routes return 501 / the MCP tools aren't registered. */\n spawnPty?: PtyFactory\n /** Override the per-boot bearer token. Default: `randomUUID()`.\n * Tests can pin a known value; production should always let\n * the gateway generate fresh. The token is written into\n * `<workspace>/.agentproto/runtime.json` (mode 0600) and required\n * on mutating `/sessions/*` routes + the PTY WS upgrade. */\n token?: string\n /** Trusted browser origins allowed to drive mutating routes\n * without a bearer token. See `RuntimeHttpServerOptions.allowedOrigins`\n * for match semantics. Default: localhost on any port. */\n allowedOrigins?: readonly string[]\n /** When true, drop the localhost-wildcard defaults — only the\n * explicit `allowedOrigins` list is honoured. */\n strictOrigins?: boolean\n}\n\nexport interface GatewayHandle {\n url: string\n workspace: string\n workspaceFs: WorkspaceFs\n registered: readonly string[]\n /** Sessions registry — exposed so MCP tools / external spawners\n * inside the same process can register their child processes for\n * visibility through /sessions and the CLI TUI. */\n sessions: SessionsRegistry\n /** Per-boot bearer token required on mutating /sessions/* routes\n * + WS PTY upgrades. Exposed so an embedding host (e.g. the CLI\n * shell that hosts the gateway in-process) can pass it to child\n * tools without re-reading the runtime.json file. */\n token: string\n stop(): Promise<void>\n}\n\n/**\n * Spin up the gateway. Order:\n * 1. Build MCP server + load AIP-40 extensions\n * 2. Build conversation store + workspace fs adapter\n * 3. (optional) Run BOOT.md once\n * 4. Start HTTP server\n * 5. Start heartbeat ticker\n *\n * `stop()` reverses 4–5 (heartbeat first, then HTTP). The MCP server\n * is owned by the HTTP server's per-session transports and is closed\n * implicitly when those close.\n */\nexport async function createGateway(\n opts: CreateGatewayOptions,\n): Promise<GatewayHandle> {\n const workspace = resolve(opts.workspace)\n if (!existsSync(workspace)) {\n throw new Error(`runtime: workspace dir does not exist: ${workspace}`)\n }\n const port = opts.port ?? 18790\n\n const events = createRuntimeEvents()\n const conversations = fileConversationStore({ workspace })\n const workspaceFs = createWorkspaceFs({ workspace })\n\n // Singleton controller for \"publish to the internet\" state. Created\n // disabled — auth stays `mode: \"none\"` until `remote_enable` is\n // called. Tunnel logs flow through the events stream so `/events`\n // subscribers see cloudflared chatter.\n const remote = new RemoteController({\n workspace,\n port,\n onLog: line =>\n events.emit({\n type: \"remote-log\",\n at: new Date().toISOString(),\n line,\n }),\n })\n\n // Build a server once eagerly so we can capture `registered` for\n // `/health`. The server is NOT used for serving — every `/mcp`\n // request gets its own freshly-constructed pair, mirroring the\n // SDK's official stateless pattern. See the comment on\n // `RuntimeHttpServerOptions.mcpServerFactory` for why.\n const { registered } = await createMcpServer({\n specs: opts.specs,\n workspace,\n name: opts.name ?? \"agentproto-runtime\",\n version: opts.version ?? \"0.1.0-alpha\",\n })\n\n // Sessions registry — single instance per gateway, captured by\n // the per-request mcpServerFactory closure below + handed to\n // startHttpServer for the /sessions HTTP routes. Declared here\n // (above the factory) so its identifier is visible at closure-\n // build time, even though the factory only invokes later.\n const sessions = createSessionsRegistry({\n ...(opts.spawnPty ? { spawnPty: opts.spawnPty } : {}),\n // Resume hook: when a prompt arrives for a dead agent-cli row\n // (typical after daemon restart), the registry calls back into\n // the adapter resolver to re-create the AgentSession with\n // `resumeSessionId = adapterSessionId`. ACP semantics: the\n // upstream provider reattaches to the prior conversation.\n // Unwired (no resolveAgentAdapter) → legacy \"not an agent\n // session\" error, user must spawn fresh.\n ...(opts.resolveAgentAdapter\n ? {\n resumeAgent: async ({ adapterSlug, cwd, resumeSessionId }) => {\n const adapter = await opts.resolveAgentAdapter!(adapterSlug)\n if (!adapter) return null\n try {\n return await adapter.startSession({ cwd, resumeSessionId })\n } catch (err) {\n console.warn(\n `[agentproto] resumeAgent('${adapterSlug}', ${resumeSessionId}) failed: ${\n err instanceof Error ? err.message : String(err)\n }`\n )\n return null\n }\n },\n }\n : {}),\n })\n\n // Per-boot bearer token. Required on mutating /sessions/* routes\n // and on the WS upgrade for /sessions/:id/pty. Persisted to\n // runtime.json (mode 0600) so the same-user CLI can read it; a\n // browser-loaded localhost page can't.\n const token = opts.token ?? randomUUID()\n\n // MCP proxy — single registry that holds open Client connections\n // to every imported MCP server. The per-request mcpServerFactory\n // captures it so each /mcp request reuses the same upstream\n // sessions instead of re-spawning stdio children.\n const mcpProxy = new McpProxyRegistry()\n\n const mcpServerFactory = async () => {\n const { server } = await createMcpServer({\n specs: opts.specs,\n workspace,\n name: opts.name ?? \"agentproto-runtime\",\n version: opts.version ?? \"0.1.0-alpha\",\n })\n // Canonical filesystem tools so remote MCP clients (cloud\n // workspace-providers, IDEs, ad-hoc tooling) can read/write the\n // workspace without each implementing AIP-aware glue. Names match\n // `@modelcontextprotocol/server-filesystem` for drop-in compat.\n registerFsTools(server, { workspace })\n // Subprocess execution — the runtime's superpower for cloud\n // agents. Any allowlisted CLI on the user's machine (claude, gh,\n // pnpm, …) is reachable via `execute_command`. Allowlist lives at\n // `.agentproto/allowed-commands.json`; default-deny.\n registerCommandTools(server, { workspace })\n // Remote-tunnel lifecycle. The controller is a singleton on the\n // gateway, so registering its tools per-request is just rebinding\n // the same closures — the underlying state lives in `remote`.\n registerRemoteTools(server, { controller: remote })\n // Agent-session orchestration — operators (Mastra agents in\n // cloud Guilde, Claude Code as a sub-agent, …) drive long-running\n // claude/hermes/aider sessions on the user's machine through\n // these MCP tools. The registry + adapter resolver are\n // singletons on the gateway, same closure-rebind pattern.\n registerSessionTools(server, {\n registry: sessions,\n mcpProxy,\n ptyEnabled: opts.spawnPty != null,\n ...(opts.resolveAgentAdapter\n ? { resolveAgentAdapter: opts.resolveAgentAdapter }\n : {}),\n ...(opts.listAgentAdapters\n ? { listAgentAdapters: opts.listAgentAdapters }\n : {}),\n })\n return server\n }\n\n // ── boot ─────────────────────────────────────────────────────────\n if (opts.boot !== false) {\n await runBoot(workspace, opts, conversations, events).catch((err) => {\n events.emit({\n type: \"heartbeat-error\",\n at: new Date().toISOString(),\n agent: opts.defaultBootAgent,\n error: `BOOT.md failed: ${err instanceof Error ? err.message : String(err)}`,\n })\n })\n }\n\n const heartbeat = startHeartbeat({\n workspace,\n conversations,\n events,\n buildAgent: opts.buildAgent ?? noopBuildAgent,\n })\n\n const http = await startHttpServer({\n port,\n bind: opts.bind,\n // Auth is read on every request via this getter. `opts.auth`\n // (when provided) is the startup default and represents the\n // operator's intent — bearer-only deployments stay bearer-only\n // even when no remote tunnel is up. The controller's auth wins\n // once a tunnel is enabled (it issues a fresh token); on disable\n // we fall back to `opts.auth` if set, otherwise `mode: \"none\"`.\n auth: () => {\n const remoteAuth = remote.readAuth()\n if (remoteAuth.mode === \"bearer\") return remoteAuth\n return opts.auth ?? { mode: \"none\" }\n },\n mcpServerFactory,\n conversations,\n events,\n heartbeat,\n sessions,\n mcpProxy,\n token,\n ptyEnabled: opts.spawnPty != null,\n ...(opts.allowedOrigins ? { allowedOrigins: opts.allowedOrigins } : {}),\n ...(opts.strictOrigins ? { strictOrigins: true } : {}),\n ...(opts.resolveAgentAdapter\n ? { resolveAgentAdapter: opts.resolveAgentAdapter }\n : {}),\n ...(opts.listAgentAdapters\n ? { listAgentAdapters: opts.listAgentAdapters }\n : {}),\n meta: { workspace, registered },\n })\n\n heartbeat.start()\n events.emit({\n type: \"boot\",\n at: new Date().toISOString(),\n workspace,\n registered,\n })\n\n // Record a snapshot of the running config so external tooling /\n // shell users can introspect a live gateway via\n // `cat <workspace>/.agentproto/runtime.json`. Best-effort — failure\n // here doesn't gate the gateway being functional.\n void writeRuntimeMeta(workspace, {\n workspace,\n port,\n bind: opts.bind ?? \"127.0.0.1\",\n pid: process.pid,\n startedAt: new Date().toISOString(),\n name: opts.name ?? \"agentproto-runtime\",\n registered,\n token,\n })\n\n return {\n url: http.url,\n workspace,\n workspaceFs,\n registered,\n sessions,\n token,\n async stop() {\n heartbeat.stop()\n // Kill all live sessions before tearing down HTTP — otherwise\n // long-running children inherit the daemon's listening socket\n // and stay around as zombies after the parent exits.\n sessions.shutdown()\n // Close upstream MCP clients (their stdio children would\n // otherwise leak the same way).\n await mcpProxy.closeAll()\n // Tear the tunnel before the HTTP listener — otherwise cloudflared\n // briefly proxies to a dead port and surfaces 502s to any in-flight\n // remote client.\n await remote.shutdown()\n await http.stop()\n },\n }\n}\n\n// ── helpers ──────────────────────────────────────────────────────────\n\nconst noopBuildAgent: BuildHeartbeatAgent = async () => null\n\nasync function runBoot(\n workspace: string,\n opts: CreateGatewayOptions,\n conversations: import(\"./conversations.js\").ConversationStore,\n events: import(\"./events.js\").RuntimeEvents,\n): Promise<void> {\n const path = join(workspace, \"BOOT.md\")\n if (!existsSync(path)) return\n const body = (await readFile(path, \"utf8\")).trim()\n if (!body) return\n if (!opts.buildAgent || !opts.defaultBootAgent) return\n\n const agent = await opts.buildAgent(opts.defaultBootAgent)\n if (!agent) return\n\n const conversationId = `boot-${new Date().toISOString().slice(0, 19).replace(/[:.]/g, \"-\")}`\n await conversations.open(conversationId, { agent: opts.defaultBootAgent })\n await conversations.appendTurn(conversationId, \"user\", body, {\n attribution: \"boot\",\n })\n const reply = await agent.generate(body)\n await conversations.appendTurn(conversationId, \"assistant\", reply.text, {\n attribution: opts.defaultBootAgent,\n })\n events.emit({\n type: \"heartbeat-fired\",\n at: new Date().toISOString(),\n agent: opts.defaultBootAgent,\n conversationId,\n prompt: body,\n reply: reply.text,\n durationMs: 0,\n })\n}\n"]}
1
+ {"version":3,"sources":["../src/agentproto-dir.ts","../src/command-tools.ts","../src/conversations.ts","../src/events.ts","../src/fs-tools.ts","../src/transcript-export.ts","../src/workspaces-config.ts","../src/mcp-discovery.ts","../src/mcp-imports.ts","../src/tool-subset.ts","../src/json-tolerant.ts","../src/session-tools.ts","../src/browser-tools.ts","../src/mcp-apps-adapter.ts","../src/sessions-panel.ts","../src/sessions-panel-app.ts","../src/agents-overview-app.ts","../src/bureau-sessions-app.ts","../src/heartbeat.ts","../src/http-server.ts","../src/resume-strategies.ts","../src/sessions.ts","../src/mcp-proxy.ts","../src/orchestration-tools.ts","../src/session-event-bus.ts","../src/event-ring.ts","../src/webhook-notifier.ts","../src/routine-runner.ts","../src/supervisor.ts","../src/inbound-watcher.ts","../src/orchestrator-gateway.ts","../src/browser-adapters.ts","../src/remote-providers/quick.ts","../src/remote-controller.ts","../src/remote-tools.ts","../src/remote-providers/named.ts","../src/remote-providers/ngrok.ts","../src/remote-providers/registry.ts","../src/tunnel-registry.ts","../src/tunnel-tools.ts","../src/tunnel-adapters.ts","../src/workspace-fs.ts","../src/providers-store.ts","../src/index.ts"],"names":["resolve","stat","readFile","join","text","mkdir","existsSync","writeFile","readdir","isAbsolute","normalize","relative","z","homedir","spawn","fs","resolvePath","dirname","adapters","server","id","EventEmitter","rt","state","readFileSync","mkdirSync","writeFileSync","randomUUID","ANSI_RE","PERSIST_DEBOUNCE_MS","fsp","basename","entry","toDescriptor","randomBytes","rm","execFileAsync","promisify","execFile","STARTUP_TIMEOUT_MS","cloudflaredOnPath","assertCloudflaredOnPath","opts","HISTORY_CAP","makeAdapterLister","fields","fsReadFile","fsWriteFile","createMcpServer"],"mappings":"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","file":"index.mjs","sourcesContent":["/**\n * `.agentproto/` config dir — runtime-managed state at the root of\n * every workspace. Mirrors the `.git/` model: user-content stays at\n * the workspace root (HEARTBEAT.md, conversations/, .agents/) while\n * everything the runtime owns lives in `<workspace>/.agentproto/`.\n *\n * What goes here today:\n * - `runtime.json` — boot-time snapshot of the live config (PID,\n * port, resolved workspace, MCP server name, startedAt). Useful\n * for `cat .agentproto/runtime.json` diagnostics + future tooling\n * that wants to discover a running gateway from disk.\n *\n * The same snapshot is ALSO mirrored to the central, workspace-\n * independent daemon registry at `~/.agentproto/daemons/<port>.json`\n * (see daemonRegistryDir / writeDaemonRegistryEntry below). The\n * per-workspace file only helps `cat`-style local diagnostics and\n * discovery for REGISTERED workspaces; a daemon launched from an\n * arbitrary cwd (tunnel mode, a repo checkout) writes its workspace\n * file somewhere discovery never walks. The central entry is what\n * makes `agentproto chat` / `sessions` find such a daemon.\n *\n * What does NOT go here:\n * - HEARTBEAT.md — user-edited content\n * - conversations/ — user-readable chat history\n * - .agents/ — user-authored manifests\n *\n * The `.agentproto/` dir is safe to gitignore. The `runtime.json`\n * file contains a per-boot bearer token used to gate mutating HTTP\n * routes (POST /sessions/*, WS /sessions/:id/pty). The token lives\n * in RAM + on disk only — never logged. File mode 0600 below; only\n * processes running as the workspace user (and the daemon itself)\n * can read it. A browser-loaded localhost page CAN'T read this file,\n * which is what defends against the localhost-DNS-rebinding drive-by\n * spawn vector.\n */\n\nimport { mkdir, readdir, readFile, stat, unlink, writeFile } from \"node:fs/promises\"\nimport { homedir } from \"node:os\"\nimport { join, resolve } from \"node:path\"\n\nexport interface RuntimeMeta {\n /** Absolute path to the workspace root the gateway is bound to. */\n workspace: string\n /** HTTP listener port. */\n port: number\n /** HTTP bind address (loopback or `0.0.0.0`). */\n bind: string\n /** Process id of the running gateway. */\n pid: number\n /** Wall-clock ISO timestamp at boot. */\n startedAt: string\n /** MCP server name advertised in the initialize handshake. */\n name: string\n /** AIP doctype names + extensions registered as MCP CRUD tools. */\n registered: readonly string[]\n /**\n * Per-boot bearer token. Required on mutating routes (POST\n * /sessions/*, POST /sessions/:id/kill, DELETE /sessions/:id, and\n * WS upgrade to /sessions/:id/pty). Random uuid generated at boot\n * by createGateway; regenerated each restart.\n */\n token: string\n}\n\n/**\n * Create `<workspace>/.agentproto/` (idempotent) and write the\n * `runtime.json` snapshot. Errors are logged but non-fatal — losing\n * the meta file shouldn't crash the gateway, the runtime is still\n * fully functional without it.\n */\nexport async function writeRuntimeMeta(\n workspace: string,\n meta: RuntimeMeta,\n): Promise<void> {\n const dir = join(workspace, \".agentproto\")\n try {\n await mkdir(dir, { recursive: true })\n // mode 0600 so other local users can't read the bearer token.\n await writeFile(\n join(dir, \"runtime.json\"),\n JSON.stringify(meta, null, 2) + \"\\n\",\n { encoding: \"utf8\", mode: 0o600 },\n )\n } catch (err) {\n console.error(\"[runtime] failed to write .agentproto/runtime.json:\", err)\n }\n // Also publish to the central daemon registry so the CLI can discover\n // this daemon WITHOUT its workspace being registered in\n // workspaces.json. A daemon launched from an arbitrary cwd (the common\n // case: `agentproto serve` from a repo checkout, or tunnel mode) lands\n // its workspace runtime.json somewhere discovery never walks; the\n // central entry closes that gap. Keyed by port so multiple daemons\n // coexist. Best-effort — the workspace file above is the source of\n // truth; this is purely an additional discovery hint.\n await writeDaemonRegistryEntry(meta)\n}\n\n/** `~/.agentproto/daemons/` — the central, workspace-independent daemon\n * registry. Each live daemon owns one `<port>.json` here. */\nexport function daemonRegistryDir(): string {\n return resolve(homedir(), \".agentproto\", \"daemons\")\n}\n\nfunction daemonRegistryPath(port: number): string {\n return join(daemonRegistryDir(), `${port}.json`)\n}\n\n/**\n * Write `<registry>/<port>.json` (mode 0600 — holds the bearer token).\n * Best-effort; failure here never gates the gateway. Mirrors the\n * per-workspace runtime.json so the same `RuntimeMeta` shape is readable\n * from either location.\n */\nexport async function writeDaemonRegistryEntry(meta: RuntimeMeta): Promise<void> {\n try {\n await mkdir(daemonRegistryDir(), { recursive: true })\n await writeFile(\n daemonRegistryPath(meta.port),\n JSON.stringify(meta, null, 2) + \"\\n\",\n { encoding: \"utf8\", mode: 0o600 },\n )\n } catch (err) {\n console.error(\"[runtime] failed to write daemons/<port>.json:\", err)\n }\n}\n\n/** Remove a daemon's central registry entry. Best-effort; missing is a\n * no-op. Called from graceful shutdown alongside unlinkRuntimeMeta. */\nexport async function unlinkDaemonRegistryEntry(port: number): Promise<void> {\n try {\n await unlink(daemonRegistryPath(port))\n } catch {\n // ENOENT / permission — not worth surfacing on shutdown.\n }\n}\n\n/**\n * Read every entry in the central daemon registry, newest-first by\n * `startedAt`. No liveness filtering here — callers decide (discovery\n * skips dead PIDs; the sweep deletes them). Malformed / unreadable\n * entries are skipped silently.\n */\nexport async function readDaemonRegistry(): Promise<\n Array<{ meta: Partial<RuntimeMeta> & Record<string, unknown>; path: string; mtime: Date }>\n> {\n let names: string[]\n try {\n names = await readdir(daemonRegistryDir())\n } catch {\n return [] // registry dir doesn't exist yet — no daemons published.\n }\n const out: Array<{\n meta: Partial<RuntimeMeta> & Record<string, unknown>\n path: string\n mtime: Date\n }> = []\n for (const name of names) {\n if (!name.endsWith(\".json\")) continue\n const path = join(daemonRegistryDir(), name)\n try {\n const [raw, st] = await Promise.all([readFile(path, \"utf8\"), stat(path)])\n out.push({ meta: JSON.parse(raw) as Record<string, unknown>, path, mtime: st.mtime })\n } catch {\n // skip malformed / unreadable\n }\n }\n // Newest daemon first — discovery prefers the most recently booted.\n return out.sort((a, b) => b.mtime.getTime() - a.mtime.getTime())\n}\n\n/**\n * Delete central registry entries whose PID is dead (kill -9, crash,\n * reboot). Returns the paths cleaned. Called at `serve` boot — the same\n * footgun the per-workspace sweep guards against, applied to the central\n * registry. Skips `currentPort` (the booting daemon's own entry).\n */\nexport async function sweepStaleDaemonRegistry(currentPort: number): Promise<string[]> {\n const cleaned: string[] = []\n for (const entry of await readDaemonRegistry()) {\n if (entry.meta.port === currentPort) continue\n const pid = entry.meta.pid\n if (typeof pid === \"number\" && !isPidAlive(pid)) {\n try {\n await unlink(entry.path)\n cleaned.push(entry.path)\n } catch {\n // ignore — best-effort\n }\n }\n }\n return cleaned\n}\n\n/**\n * Delete `<workspace>/.agentproto/runtime.json`. Best-effort — called\n * from the daemon's graceful shutdown path so a CLI looking for the\n * live daemon doesn't pick up a stale token after this process exits.\n * Missing file is a no-op (the daemon may never have written one).\n */\nexport async function unlinkRuntimeMeta(\n workspace: string,\n port?: number,\n): Promise<void> {\n try {\n await unlink(join(workspace, \".agentproto\", \"runtime.json\"))\n } catch {\n // ENOENT / permission — not worth surfacing on shutdown.\n }\n // Tear down the matching central registry entry too (when the caller\n // knows the port) so discovery doesn't pick up a dead daemon.\n if (typeof port === \"number\") await unlinkDaemonRegistryEntry(port)\n}\n\n/**\n * Read a runtime.json from `<workspace>/.agentproto/`. Returns the\n * parsed object (no validation) plus the on-disk mtime, or null when\n * the file is missing / unreadable / malformed.\n */\nexport async function readRuntimeMeta(workspace: string): Promise<{\n meta: Partial<RuntimeMeta> & Record<string, unknown>\n mtime: Date\n} | null> {\n const path = join(workspace, \".agentproto\", \"runtime.json\")\n try {\n const [raw, st] = await Promise.all([readFile(path, \"utf8\"), stat(path)])\n const meta = JSON.parse(raw) as Record<string, unknown>\n return { meta, mtime: st.mtime }\n } catch {\n return null\n }\n}\n\n/**\n * For each `workspace` path, check whether its runtime.json points\n * at a now-dead PID; if so, delete it. Returns the list of paths\n * that were cleaned. Called by `agentproto serve` at boot to keep\n * the discovery layer's view of \"live daemons\" honest — a stale\n * file with the same port as the new daemon is the classic source\n * of `sessions_unauthorized` 401s.\n *\n * Skips the running daemon's own workspace (passed in as\n * `currentWorkspace`) since that file is OURS to write.\n */\nexport async function sweepStaleRuntimeMetas(\n workspaces: readonly string[],\n currentWorkspace: string,\n): Promise<string[]> {\n const cleaned: string[] = []\n for (const ws of workspaces) {\n if (ws === currentWorkspace) continue\n const meta = await readRuntimeMeta(ws)\n if (!meta) continue\n const pid = meta.meta.pid\n if (typeof pid === \"number\" && !isPidAlive(pid)) {\n try {\n await unlink(join(ws, \".agentproto\", \"runtime.json\"))\n cleaned.push(join(ws, \".agentproto\", \"runtime.json\"))\n } catch {\n // ignore — best-effort\n }\n }\n }\n return cleaned\n}\n\nfunction isPidAlive(pid: number): boolean {\n try {\n process.kill(pid, 0)\n return true\n } catch (err) {\n const code = (err as NodeJS.ErrnoException).code\n if (code === \"EPERM\") return true // exists, foreign user\n return false\n }\n}\n","/**\n * Shell-execution MCP tools for the runtime.\n *\n * The runtime is a remote shell as far as cloud agents are concerned —\n * the workspace lives on the user's machine, so the only place a\n * `claude -p`, `gh pr view`, `pnpm test` etc. can actually run *is*\n * the user's machine. This module exposes one MCP tool,\n * `execute_command`, that any MCP client (cloud Guilde Blake,\n * Claude Code as a sub-agent, …) can call to spawn a subprocess.\n *\n * ## Allowlist\n *\n * Default-deny. The runtime reads\n * `<workspace>/.agentproto/allowed-commands.json` on every call (cheap\n * stat; cached for 1s) for the list of allowed command basenames.\n * Missing / empty file ⇒ no commands run. The error message points the\n * user at the file path so they know exactly where to opt in.\n *\n * Allowlist file shape:\n * { \"version\": 1, \"commands\": [\"claude\", \"gh\", \"pnpm\", \"node\"] }\n *\n * Match is by command BASENAME (`/usr/local/bin/claude` → `claude`)\n * to keep the allowlist short and not break when users have multiple\n * binaries on their PATH.\n *\n * ## Safety notes\n *\n * - We use `spawn()` with `shell: false` so arguments are passed\n * verbatim — no shell interpolation surprises.\n * - `cwd` is anchored to the workspace root via the same path-escape\n * guard used by `fs-tools.ts`. Callers can't run a subprocess in\n * `/etc` unless they also bind-mounted it inside the workspace.\n * - Every spawn has a `timeoutMs` cap (default 60s, max 600s). Hung\n * subprocesses can't pin the runtime forever.\n */\n\nimport { spawn } from \"node:child_process\"\nimport { existsSync } from \"node:fs\"\nimport { readFile, stat } from \"node:fs/promises\"\nimport {\n basename,\n isAbsolute,\n join,\n normalize,\n relative,\n resolve,\n} from \"node:path\"\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\"\nimport { z } from \"zod\"\n\nconst DEFAULT_TIMEOUT_MS = 60_000\nconst MAX_TIMEOUT_MS = 600_000\nconst ALLOWLIST_REL = \".agentproto/allowed-commands.json\"\n\nexport interface RegisterCommandToolsOptions {\n workspace: string\n}\n\ninterface AllowlistFile {\n version?: number\n commands?: string[]\n}\n\ninterface AllowlistCacheEntry {\n mtimeMs: number\n commands: Set<string>\n}\n\nlet allowlistCache: { path: string; entry: AllowlistCacheEntry } | null = null\n\nexport async function loadAllowlist(workspace: string): Promise<Set<string>> {\n const path = resolve(workspace, ALLOWLIST_REL)\n if (!existsSync(path)) {\n allowlistCache = null\n return new Set()\n }\n try {\n const s = await stat(path)\n if (\n allowlistCache &&\n allowlistCache.path === path &&\n allowlistCache.entry.mtimeMs === s.mtimeMs\n ) {\n return allowlistCache.entry.commands\n }\n const raw = await readFile(path, \"utf8\")\n const parsed = JSON.parse(raw) as AllowlistFile\n const list = Array.isArray(parsed.commands) ? parsed.commands : []\n const commands = new Set(\n list\n .filter((x): x is string => typeof x === \"string\" && x.length > 0)\n .map(x => x.trim()),\n )\n allowlistCache = { path, entry: { mtimeMs: s.mtimeMs, commands } }\n return commands\n } catch (err) {\n // Bad JSON / unreadable file ⇒ deny all and surface in the error\n // the next caller gets. Don't poison the cache.\n console.error(\n `[runtime] failed to load ${ALLOWLIST_REL} (will deny all):`,\n err,\n )\n allowlistCache = null\n return new Set()\n }\n}\n\nexport function makeCwdAnchor(workspace: string): (input: string | undefined) => string {\n const root = resolve(workspace)\n return (input?: string) => {\n if (!input || input.length === 0) return root\n const candidate = isAbsolute(input)\n ? normalize(input)\n : normalize(join(root, input))\n const rel = relative(root, candidate)\n if (rel.startsWith(\"..\") || isAbsolute(rel)) {\n throw new Error(\n `cwd escapes the workspace: '${input}' (workspace=${root})`,\n )\n }\n return candidate\n }\n}\n\nexport interface ExecuteResult {\n exitCode: number\n signal: string | null\n stdout: string\n stderr: string\n truncated?: boolean\n durationMs: number\n}\n\n/**\n * Register `execute_command` on the given MCP server. The tool returns\n * a JSON-encoded `ExecuteResult` as a single text content item — that\n * matches the response shape `@modelcontextprotocol/server-filesystem`\n * uses for `read_file` and friends, so the existing\n * `parseReadFileResponse`-style parsers in workspace-providers can\n * decode it without bespoke logic.\n */\nexport function registerCommandTools(\n server: McpServer,\n opts: RegisterCommandToolsOptions,\n): void {\n const anchorCwd = makeCwdAnchor(opts.workspace)\n\n server.tool(\n \"execute_command\",\n \"Run a shell command on the host running the runtime. The command basename must be in `<workspace>/.agentproto/allowed-commands.json`; default-deny otherwise. Captures stdout / stderr / exit code and returns them as JSON. Use this to drive local CLIs (Claude Code, gh, pnpm, …) from a remote agent.\",\n {\n command: z\n .string()\n .min(1)\n .describe(\n \"Executable name or absolute path. Must be allowlisted by basename in the workspace's allowed-commands.json.\",\n ),\n args: z\n .array(z.string())\n .optional()\n .describe(\n \"Argv array. Passed verbatim — no shell expansion (we spawn with shell:false so quoting doesn't bite).\",\n ),\n cwd: z\n .string()\n .optional()\n .describe(\n \"Working directory, workspace-relative or an absolute path inside the workspace. Defaults to the workspace root.\",\n ),\n stdin: z\n .string()\n .optional()\n .describe(\"Optional input piped to the process's stdin.\"),\n timeoutMs: z\n .number()\n .int()\n .positive()\n .max(MAX_TIMEOUT_MS)\n .optional()\n .describe(\n `Hard kill after this many ms. Defaults to ${DEFAULT_TIMEOUT_MS}; capped at ${MAX_TIMEOUT_MS}.`,\n ),\n },\n async ({ command, args, cwd, stdin, timeoutMs }) => {\n const allowlist = await loadAllowlist(opts.workspace)\n const baseName = basename(command)\n if (!allowlist.has(baseName)) {\n const allowed = [...allowlist].sort().join(\", \") || \"(empty)\"\n throw new Error(\n `command '${baseName}' is not in the allowlist. ` +\n `Add it to ${join(opts.workspace, ALLOWLIST_REL)} ` +\n `under \"commands\": [...]. Currently allowed: ${allowed}.`,\n )\n }\n const resolvedCwd = anchorCwd(cwd)\n const limit = Math.min(timeoutMs ?? DEFAULT_TIMEOUT_MS, MAX_TIMEOUT_MS)\n const result = await runCommand({\n command,\n args: args ?? [],\n cwd: resolvedCwd,\n stdin,\n timeoutMs: limit,\n })\n return {\n content: [{ type: \"text\" as const, text: JSON.stringify(result) }],\n }\n },\n )\n}\n\nexport interface RunCommandInput {\n command: string\n args: string[]\n cwd: string\n stdin?: string\n timeoutMs: number\n}\n\nconst STREAM_BUFFER_CAP = 1_048_576 // 1 MiB per stream\n\nexport async function runCommand(input: RunCommandInput): Promise<ExecuteResult> {\n return new Promise<ExecuteResult>(resolvePromise => {\n const startedAt = Date.now()\n const child = spawn(input.command, input.args, {\n cwd: input.cwd,\n shell: false,\n // Inherit user env so PATH lookups for `claude`, `gh`, etc. work.\n env: process.env,\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n })\n\n let stdout = \"\"\n let stderr = \"\"\n let truncated = false\n let timedOut = false\n\n function appendCapped(buf: string, chunk: Buffer): string {\n if (buf.length >= STREAM_BUFFER_CAP) {\n truncated = true\n return buf\n }\n const room = STREAM_BUFFER_CAP - buf.length\n const text = chunk.toString(\"utf8\")\n if (text.length > room) {\n truncated = true\n return buf + text.slice(0, room)\n }\n return buf + text\n }\n child.stdout?.on(\"data\", d => {\n stdout = appendCapped(stdout, d)\n })\n child.stderr?.on(\"data\", d => {\n stderr = appendCapped(stderr, d)\n })\n\n if (input.stdin) {\n child.stdin?.write(input.stdin)\n }\n child.stdin?.end()\n\n const timer = setTimeout(() => {\n timedOut = true\n // SIGTERM first; the close handler resolves either way. Ignore\n // EPERM if the child is already gone.\n try {\n child.kill(\"SIGTERM\")\n } catch {\n /* noop */\n }\n // Hard kill 2s later if it hasn't exited.\n setTimeout(() => {\n try {\n child.kill(\"SIGKILL\")\n } catch {\n /* noop */\n }\n }, 2_000).unref()\n }, input.timeoutMs)\n timer.unref()\n\n child.on(\"error\", err => {\n clearTimeout(timer)\n // spawn errors (ENOENT, EACCES) become exitCode -1 with the\n // message in stderr — the JSON shape stays consistent.\n resolvePromise({\n exitCode: -1,\n signal: null,\n stdout,\n stderr: stderr + (stderr ? \"\\n\" : \"\") + (err as Error).message,\n truncated,\n durationMs: Date.now() - startedAt,\n })\n })\n child.on(\"close\", (code, signal) => {\n clearTimeout(timer)\n resolvePromise({\n exitCode: typeof code === \"number\" ? code : -1,\n signal: signal ?? (timedOut ? \"SIGTERM-timeout\" : null),\n stdout,\n stderr,\n truncated,\n durationMs: Date.now() - startedAt,\n })\n })\n })\n}\n","/**\n * Append-only conversation persistence as plain markdown.\n *\n * Each conversation is a file at `<workspace>/conversations/<id>.md`\n * with a frontmatter header (`schema: conversation/v1`, `id`, `agent`,\n * `started`, `status`) and a body composed of `## <role> — <iso>`\n * blocks. Append-only: turns are concatenated to the body, never\n * rewritten in place. Readers tolerant to clock skew use the timestamp\n * in each block, not file mtime.\n *\n * The format is intentionally trivial — git-diffable, human-editable,\n * survives `cat`. Designed to converge with the AIP runtime/v1 spec\n * (TBD) once it lands.\n */\n\nimport { existsSync } from \"node:fs\"\nimport { mkdir, readFile, readdir, writeFile } from \"node:fs/promises\"\nimport { join } from \"node:path\"\n\nconst FRONTMATTER_RE = /^---\\n([\\s\\S]*?)\\n---\\n/\n\nexport type ConvRole = \"user\" | \"assistant\" | \"system\"\n\nexport interface ConversationMeta {\n id: string\n agent: string\n started: string\n status: \"open\" | \"closed\"\n}\n\nexport interface ConversationTurn {\n role: ConvRole\n at: string\n /** Optional sub-attribution after the role (e.g. agent id). */\n attribution?: string\n content: string\n}\n\nexport interface ConversationStore {\n /**\n * Open a conversation. If the file doesn't exist, it's created with\n * a frontmatter header. If it exists, no-op (idempotent).\n */\n open(id: string, meta: { agent: string }): Promise<void>\n appendTurn(\n id: string,\n role: ConvRole,\n content: string,\n opts?: { attribution?: string; at?: string },\n ): Promise<void>\n read(\n id: string,\n ): Promise<{ meta: ConversationMeta; turns: ConversationTurn[] }>\n list(): Promise<Array<{ id: string; meta: ConversationMeta }>>\n /** Workspace-relative path to the conv file, for tooling. */\n pathFor(id: string): string\n}\n\nexport interface FileConversationStoreOptions {\n /** Absolute workspace root. */\n workspace: string\n /** Override `<workspace>/conversations`. */\n dir?: string\n}\n\nexport function fileConversationStore(\n opts: FileConversationStoreOptions,\n): ConversationStore {\n const dir = opts.dir ?? join(opts.workspace, \"conversations\")\n\n const filePath = (id: string) => join(dir, `${id}.md`)\n\n return {\n pathFor: filePath,\n\n async open(id, meta) {\n await mkdir(dir, { recursive: true })\n const path = filePath(id)\n if (existsSync(path)) return\n const header = renderHeader({\n id,\n agent: meta.agent,\n started: new Date().toISOString(),\n status: \"open\",\n })\n await writeFile(path, header, \"utf8\")\n },\n\n async appendTurn(id, role, content, options) {\n const path = filePath(id)\n // Lazy-open: if a caller appends without opening, create the\n // file so the operation never silently drops a turn.\n if (!existsSync(path)) {\n await this.open(id, { agent: options?.attribution ?? \"unknown\" })\n }\n const block = renderTurn({\n role,\n at: options?.at ?? new Date().toISOString(),\n attribution: options?.attribution,\n content,\n })\n // Append a leading blank line so the new block is always\n // separated from whatever's above (header or prev turn).\n await writeFile(path, block, { encoding: \"utf8\", flag: \"a\" })\n },\n\n async read(id) {\n const path = filePath(id)\n const source = await readFile(path, \"utf8\")\n return parseConversation(source, id)\n },\n\n async list() {\n if (!existsSync(dir)) return []\n const entries = await readdir(dir, { withFileTypes: true })\n const out: Array<{ id: string; meta: ConversationMeta }> = []\n for (const entry of entries) {\n if (!entry.isFile() || !entry.name.endsWith(\".md\")) continue\n const id = entry.name.slice(0, -3)\n try {\n const source = await readFile(join(dir, entry.name), \"utf8\")\n const { meta } = parseConversation(source, id)\n out.push({ id, meta })\n } catch {\n // Skip malformed conv files rather than crash list().\n }\n }\n return out\n },\n }\n}\n\n// ── render ───────────────────────────────────────────────────────────\n\nfunction renderHeader(meta: ConversationMeta): string {\n return [\n \"---\",\n `schema: conversation/v1`,\n `id: ${meta.id}`,\n `agent: ${meta.agent}`,\n `started: ${meta.started}`,\n `status: ${meta.status}`,\n \"---\",\n \"\",\n \"\",\n ].join(\"\\n\")\n}\n\nfunction renderTurn(turn: ConversationTurn): string {\n const heading = turn.attribution\n ? `## ${turn.role} — ${turn.at} (${turn.attribution})`\n : `## ${turn.role} — ${turn.at}`\n return `${heading}\\n\\n${turn.content.trimEnd()}\\n\\n`\n}\n\n// ── parse ────────────────────────────────────────────────────────────\n\ninterface ParsedConversation {\n meta: ConversationMeta\n turns: ConversationTurn[]\n}\n\nfunction parseConversation(source: string, fallbackId: string): ParsedConversation {\n const match = source.match(FRONTMATTER_RE)\n let meta: ConversationMeta = {\n id: fallbackId,\n agent: \"unknown\",\n started: \"\",\n status: \"open\",\n }\n let body = source\n if (match) {\n meta = parseFrontmatter(match[1] ?? \"\", fallbackId)\n body = source.slice(match[0].length)\n }\n\n const turns: ConversationTurn[] = []\n // Split on `## <role> — <iso>` headings. Conservative — anything\n // that doesn't match is treated as continuation of the prior turn.\n const lines = body.split(\"\\n\")\n let current: ConversationTurn | null = null\n let buffer: string[] = []\n\n const flush = () => {\n if (!current) return\n current.content = buffer.join(\"\\n\").trim()\n turns.push(current)\n current = null\n buffer = []\n }\n\n const headingRe =\n /^##\\s+(user|assistant|system)\\s+—\\s+(\\S+)(?:\\s+\\(([^)]+)\\))?\\s*$/\n\n for (const line of lines) {\n const m = line.match(headingRe)\n if (m) {\n flush()\n current = {\n role: m[1] as ConvRole,\n at: m[2] ?? \"\",\n attribution: m[3],\n content: \"\",\n }\n continue\n }\n if (current) buffer.push(line)\n }\n flush()\n\n return { meta, turns }\n}\n\nfunction parseFrontmatter(\n raw: string,\n fallbackId: string,\n): ConversationMeta {\n const out: Record<string, string> = {}\n for (const line of raw.split(\"\\n\")) {\n const colon = line.indexOf(\":\")\n if (colon < 1) continue\n const key = line.slice(0, colon).trim()\n const value = line.slice(colon + 1).trim()\n out[key] = value\n }\n return {\n id: out.id ?? fallbackId,\n agent: out.agent ?? \"unknown\",\n started: out.started ?? \"\",\n status: (out.status === \"closed\" ? \"closed\" : \"open\"),\n }\n}\n","/**\n * In-process event bus for the runtime gateway. Anything the daemon\n * does that an external observer might want to watch (heartbeat fired,\n * conversation turn appended, boot completed, …) flows through here.\n *\n * The HTTP server's `/events` SSE stream subscribes to it and forwards\n * each event as a `data: <json>\\n\\n` frame. Tests and embedded usage\n * subscribe directly via `events.on()`.\n */\n\nimport { EventEmitter } from \"node:events\"\n\nexport interface BootEvent {\n type: \"boot\"\n at: string\n workspace: string\n registered: readonly string[]\n}\n\nexport interface HeartbeatFiredEvent {\n type: \"heartbeat-fired\"\n at: string\n agent: string\n conversationId: string\n prompt: string\n reply: string\n durationMs: number\n}\n\nexport interface HeartbeatErrorEvent {\n type: \"heartbeat-error\"\n at: string\n agent?: string\n error: string\n}\n\nexport interface ConvTurnEvent {\n type: \"conv-turn-appended\"\n at: string\n conversationId: string\n role: \"user\" | \"assistant\"\n contentPreview: string\n}\n\n/**\n * One log line from a supervised tunnel provider (cloudflared today).\n * Surfaced verbatim so users can debug \"why didn't my remote URL come\n * up\" by tailing /events.\n */\nexport interface RemoteLogEvent {\n type: \"remote-log\"\n at: string\n line: string\n}\n\nexport type RuntimeEvent =\n | BootEvent\n | HeartbeatFiredEvent\n | HeartbeatErrorEvent\n | ConvTurnEvent\n | RemoteLogEvent\n\nexport interface RuntimeEvents {\n on<E extends RuntimeEvent[\"type\"]>(\n type: E,\n handler: (ev: Extract<RuntimeEvent, { type: E }>) => void,\n ): () => void\n onAny(handler: (ev: RuntimeEvent) => void): () => void\n emit(ev: RuntimeEvent): void\n}\n\nexport function createRuntimeEvents(): RuntimeEvents {\n const ee = new EventEmitter()\n ee.setMaxListeners(50)\n\n return {\n on(type, handler) {\n const wrapped = (ev: RuntimeEvent) => {\n if (ev.type === type) handler(ev as Extract<RuntimeEvent, { type: typeof type }>)\n }\n ee.on(\"event\", wrapped)\n return () => ee.off(\"event\", wrapped)\n },\n onAny(handler) {\n ee.on(\"event\", handler)\n return () => ee.off(\"event\", handler)\n },\n emit(ev) {\n ee.emit(\"event\", ev)\n },\n }\n}\n","/**\n * Filesystem MCP tools registered on the runtime's MCP server.\n *\n * The runtime already exposes AIP CRUD verbs (create_tool, load_agent, …)\n * via @agentproto/mcp-server. To make the workspace genuinely reachable\n * to remote MCP clients (Guilde cloud agents through a tunnel, IDEs,\n * etc.), we also register canonical filesystem tools that match the\n * shape used by `@modelcontextprotocol/server-filesystem` so existing\n * MCP-fs proxy clients can target the runtime without bespoke logic:\n *\n * read_file ({ path }) → string\n * write_file ({ path, content }) → \"ok\"\n * list_directory ({ path? }) → \"[FILE] x\\n[DIR] y\" lines\n * get_file_info ({ path }) → { name, type, size, modified }\n * create_directory ({ path }) → \"ok\"\n * delete_file ({ path }) → \"ok\"\n *\n * All paths are resolved relative to the workspace root via the same\n * escape guard used by `WorkspaceFs`. Absolute paths inside the root\n * are accepted (so callers that prefix `basePath` with the absolute\n * workspace path keep working).\n */\n\nimport {\n mkdir,\n readFile,\n readdir,\n rm,\n stat,\n writeFile,\n} from \"node:fs/promises\"\nimport { dirname, isAbsolute, join, normalize, relative, resolve } from \"node:path\"\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\"\nimport { z } from \"zod\"\n\nexport interface RegisterFsToolsOptions {\n workspace: string\n}\n\nclass FsPathError extends Error {\n constructor(message: string) {\n super(message)\n this.name = \"FsPathError\"\n }\n}\n\nfunction makeAnchor(workspace: string): (input: string) => string {\n const root = resolve(workspace)\n return (input: string) => {\n if (typeof input !== \"string\" || input.length === 0) {\n throw new FsPathError(\"path must be a non-empty string\")\n }\n const candidate = isAbsolute(input)\n ? normalize(input)\n : normalize(join(root, input))\n const rel = relative(root, candidate)\n if (rel.startsWith(\"..\") || isAbsolute(rel)) {\n throw new FsPathError(`path escapes the workspace: '${input}'`)\n }\n return candidate\n }\n}\n\nfunction text(value: string | object): {\n content: Array<{ type: \"text\"; text: string }>\n} {\n return {\n content: [\n {\n type: \"text\",\n text: typeof value === \"string\" ? value : JSON.stringify(value),\n },\n ],\n }\n}\n\nexport function registerFsTools(\n server: McpServer,\n opts: RegisterFsToolsOptions,\n): void {\n const anchor = makeAnchor(opts.workspace)\n\n server.tool(\n \"read_file\",\n \"Read a UTF-8 file from the workspace.\",\n { path: z.string().describe(\"Workspace-relative path to the file.\") },\n async ({ path }) => {\n const abs = anchor(path)\n const buf = await readFile(abs)\n return text(buf.toString(\"utf8\"))\n },\n )\n\n server.tool(\n \"write_file\",\n \"Write a file to the workspace. Parent directories are created on demand.\",\n {\n path: z.string().describe(\"Workspace-relative path to the file.\"),\n content: z.string().describe(\"File body (UTF-8).\"),\n },\n async ({ path, content }) => {\n const abs = anchor(path)\n await mkdir(dirname(abs), { recursive: true })\n await writeFile(abs, content, \"utf8\")\n return text(\"ok\")\n },\n )\n\n server.tool(\n \"list_directory\",\n \"List entries of a directory in the workspace. Returns one '[FILE]' or '[DIR]' line per entry, mirroring `@modelcontextprotocol/server-filesystem`.\",\n {\n path: z\n .string()\n .optional()\n .describe(\"Workspace-relative directory (defaults to workspace root).\"),\n },\n async ({ path }) => {\n const abs = anchor(path && path.length > 0 ? path : \".\")\n const entries = await readdir(abs, { withFileTypes: true })\n const lines = entries.map(e =>\n e.isDirectory() ? `[DIR] ${e.name}` : `[FILE] ${e.name}`,\n )\n return text(lines.join(\"\\n\"))\n },\n )\n\n server.tool(\n \"get_file_info\",\n \"Stat a file or directory in the workspace.\",\n { path: z.string().describe(\"Workspace-relative path.\") },\n async ({ path }) => {\n const abs = anchor(path)\n const info = await stat(abs)\n return text({\n name: abs.split(\"/\").pop() ?? path,\n path,\n type: info.isDirectory() ? \"directory\" : \"file\",\n size: info.size,\n modified: info.mtime.toISOString(),\n created: info.birthtime.toISOString(),\n })\n },\n )\n\n server.tool(\n \"create_directory\",\n \"Create a directory (recursive) in the workspace.\",\n { path: z.string().describe(\"Workspace-relative directory path.\") },\n async ({ path }) => {\n const abs = anchor(path)\n await mkdir(abs, { recursive: true })\n return text(\"ok\")\n },\n )\n\n server.tool(\n \"delete_file\",\n \"Delete a file or empty directory in the workspace.\",\n { path: z.string().describe(\"Workspace-relative path.\") },\n async ({ path }) => {\n const abs = anchor(path)\n await rm(abs, { recursive: true, force: true })\n return text(\"ok\")\n },\n )\n}\n","/**\n * Export a clean, readable transcript from the source an adapter already\n * persists — instead of parsing the noisy ANSI/ACP ring buffer.\n *\n * Two backends, dispatched by adapter slug:\n * claude-code — reads ~/.claude/projects/<cwd-encoded>/<sessionId>.jsonl\n * hermes — reads ~/.hermes/state.db via node:sqlite (read-only)\n *\n * Output: Markdown (default) or JSON, built from a shared ExportedSession\n * model so both adapters produce identical rendering logic.\n */\n\nimport { createReadStream } from \"node:fs\"\nimport { homedir } from \"node:os\"\nimport { join } from \"node:path\"\nimport { createInterface } from \"node:readline\"\nimport type { SessionsRegistry } from \"./sessions.js\"\n\n// ── Common model ──────────────────────────────────────────────────────\n\nexport interface ExportedMessage {\n role: \"user\" | \"assistant\" | \"tool\" | \"system\"\n text?: string\n reasoning?: string\n toolName?: string\n toolCalls?: { name: string; args: string }[]\n ts?: number\n}\n\nexport interface ExportedSessionMeta {\n title?: string\n model?: string\n startedAt?: string\n endedAt?: string\n messageCount?: number\n toolCallCount?: number\n tokens?: {\n input?: number\n output?: number\n cacheRead?: number\n cacheWrite?: number\n reasoning?: number\n }\n costUsd?: number\n source?: string\n}\n\nexport interface ExportedSession {\n meta: ExportedSessionMeta\n messages: ExportedMessage[]\n}\n\n// ── Render ────────────────────────────────────────────────────────────\n\nconst ROLE_ICON: Record<string, string> = {\n user: \"🧑 User\",\n assistant: \"🤖 Assistant\",\n tool: \"🔧 Tool\",\n system: \"⚙️ System\",\n}\n\nfunction trunc(text: string, n: number): string {\n if (text.length <= n) return text\n return text.slice(0, n) + `\\n… [${text.length - n} chars truncated]`\n}\n\nexport function renderMarkdown(\n session: ExportedSession,\n opts: { maxToolChars?: number } = {},\n): string {\n const { meta, messages } = session\n const maxToolChars = opts.maxToolChars ?? 1200\n const out: string[] = []\n\n out.push(`# ${meta.title ?? \"(untitled)\"}`)\n out.push(\"\")\n\n const sourceNote = meta.source ? ` · source \\`${meta.source}\\`` : \"\"\n out.push(`> Session${sourceNote}`)\n out.push(\"\")\n out.push(\"| | |\")\n out.push(\"|---|---|\")\n if (meta.model) out.push(`| Model | \\`${meta.model}\\` |`)\n if (meta.startedAt || meta.endedAt) {\n out.push(`| Start → end | ${meta.startedAt ?? \"?\"} → ${meta.endedAt ?? \"?\"} |`)\n }\n if (meta.messageCount !== undefined || meta.toolCallCount !== undefined) {\n const parts: string[] = []\n if (meta.messageCount !== undefined) parts.push(`${meta.messageCount} messages`)\n if (meta.toolCallCount !== undefined) parts.push(`${meta.toolCallCount} tool calls`)\n out.push(`| Count | ${parts.join(\" · \")} |`)\n }\n if (meta.tokens && Object.keys(meta.tokens).length) {\n const t = meta.tokens\n const parts: string[] = []\n if (t.input !== undefined) parts.push(`in ${t.input.toLocaleString(\"en-US\")}`)\n if (t.output !== undefined) parts.push(`out ${t.output.toLocaleString(\"en-US\")}`)\n if (t.cacheRead !== undefined || t.cacheWrite !== undefined) {\n parts.push(\n `cache r/w ${(t.cacheRead ?? 0).toLocaleString(\"en-US\")}/${(t.cacheWrite ?? 0).toLocaleString(\"en-US\")}`,\n )\n }\n if (t.reasoning !== undefined) parts.push(`reason. ${t.reasoning.toLocaleString(\"en-US\")}`)\n if (parts.length) out.push(`| Tokens | ${parts.join(\" · \")} |`)\n }\n if (meta.costUsd !== undefined) {\n out.push(`| Cost | $${meta.costUsd.toFixed(4)} |`)\n }\n out.push(\"\")\n out.push(\"---\")\n out.push(\"\")\n\n for (const m of messages) {\n const icon = ROLE_ICON[m.role] ?? m.role\n const nameSuffix = m.toolName ? ` · \\`${m.toolName}\\`` : \"\"\n out.push(`### ${icon}${nameSuffix}`)\n\n if (m.reasoning?.trim()) {\n out.push(\"\")\n out.push(\"<details><summary>💭 reasoning</summary>\")\n out.push(\"\")\n out.push(trunc(m.reasoning, 4000))\n out.push(\"\")\n out.push(\"</details>\")\n }\n\n if (m.text?.trim()) {\n out.push(\"\")\n if (m.role === \"tool\") {\n out.push(\"```\")\n out.push(trunc(m.text, maxToolChars))\n out.push(\"```\")\n } else {\n out.push(m.text.trim())\n }\n }\n\n if (m.toolCalls?.length) {\n out.push(\"\")\n for (const tc of m.toolCalls) {\n const argsDisplay = trunc(tc.args, 300).replace(/\\n/g, \" \")\n out.push(`> 📞 **${tc.name}**(\\`${argsDisplay}\\`)`)\n }\n }\n\n out.push(\"\")\n }\n\n return out.join(\"\\n\")\n}\n\nexport function renderJson(session: ExportedSession): string {\n return JSON.stringify(session, null, 2)\n}\n\n// ── Exporter interface ────────────────────────────────────────────────\n\ninterface ExportStrategy {\n exportSession(adapterSessionId: string, cwd?: string): Promise<ExportedSession>\n}\n\n// ── claude-code exporter (JSONL) ──────────────────────────────────────\n\ninterface ClaudeTextBlock {\n type: \"text\"\n text: string\n}\ninterface ClaudeThinkingBlock {\n type: \"thinking\"\n thinking: string\n}\ninterface ClaudeToolUseBlock {\n type: \"tool_use\"\n name: string\n input?: unknown\n}\ninterface ClaudeToolResultBlock {\n type: \"tool_result\"\n tool_use_id?: string\n content?: unknown\n}\ntype ClaudeContentBlock =\n | ClaudeTextBlock\n | ClaudeThinkingBlock\n | ClaudeToolUseBlock\n | ClaudeToolResultBlock\n | { type: string }\n\ninterface ClaudeCodeJsonlLine {\n type: string\n message?: {\n role?: string\n content?: string | ClaudeContentBlock[]\n }\n}\n\nconst IGNORED_CLAUDE_TYPES = new Set([\n \"queue-operation\",\n \"attachment\",\n \"file-history-snapshot\",\n \"ai-title\",\n \"last-prompt\",\n])\n\nasync function exportClaudeCodeSession(\n adapterSessionId: string,\n cwd?: string,\n): Promise<ExportedSession> {\n if (!cwd) {\n throw new Error(\n \"claude-code exporter: cwd is required to locate the JSONL file.\\n\" +\n \"Pass cwd explicitly or use a session id that is in the registry.\",\n )\n }\n const encoded = cwd.replace(/\\//g, \"-\")\n const filePath = join(homedir(), \".claude\", \"projects\", encoded, `${adapterSessionId}.jsonl`)\n\n let stream: ReturnType<typeof createReadStream>\n try {\n stream = createReadStream(filePath, { encoding: \"utf8\" })\n // Trigger ENOENT eagerly before readline wraps it.\n await new Promise<void>((resolve, reject) => {\n stream.once(\"error\", reject)\n stream.once(\"open\", resolve)\n })\n } catch (err) {\n const code = (err as NodeJS.ErrnoException).code\n if (code === \"ENOENT\") {\n throw new Error(\n `claude-code: JSONL file not found: ${filePath}\\n` +\n `Verify cwd=\"${cwd}\" and adapterSessionId=\"${adapterSessionId}\".`,\n )\n }\n throw err\n }\n\n const messages: ExportedMessage[] = []\n const rl = createInterface({ input: stream, crlfDelay: Infinity })\n\n for await (const line of rl) {\n const trimmed = line.trim()\n if (!trimmed) continue\n let entry: ClaudeCodeJsonlLine\n try {\n entry = JSON.parse(trimmed) as ClaudeCodeJsonlLine\n } catch {\n continue\n }\n if (IGNORED_CLAUDE_TYPES.has(entry.type)) continue\n if (entry.type !== \"user\" && entry.type !== \"assistant\") continue\n const msg = entry.message\n if (!msg) continue\n\n const role: ExportedMessage[\"role\"] =\n msg.role === \"assistant\" ? \"assistant\" : \"user\"\n const content = msg.content\n\n if (typeof content === \"string\") {\n if (content.trim()) messages.push({ role, text: content.trim() })\n continue\n }\n if (!Array.isArray(content)) continue\n\n // Collect all block types from this message event\n let textAcc = \"\"\n let reasoningAcc = \"\"\n const toolCalls: { name: string; args: string }[] = []\n const toolResults: { text: string }[] = []\n\n for (const block of content) {\n switch (block.type) {\n case \"text\": {\n textAcc += (block as ClaudeTextBlock).text\n break\n }\n case \"thinking\": {\n reasoningAcc += (block as ClaudeThinkingBlock).thinking\n break\n }\n case \"tool_use\": {\n const tb = block as ClaudeToolUseBlock\n const args =\n typeof tb.input === \"string\"\n ? tb.input\n : JSON.stringify(tb.input ?? {})\n toolCalls.push({ name: tb.name, args })\n break\n }\n case \"tool_result\": {\n const tb = block as ClaudeToolResultBlock\n let resultText = \"\"\n if (typeof tb.content === \"string\") {\n resultText = tb.content\n } else if (Array.isArray(tb.content)) {\n for (const c of tb.content as ClaudeContentBlock[]) {\n if (c.type === \"text\") resultText += (c as ClaudeTextBlock).text\n }\n }\n toolResults.push({ text: resultText })\n break\n }\n }\n }\n\n // Emit the main message (user text or assistant with optional tool calls)\n if (textAcc.trim() || toolCalls.length || reasoningAcc) {\n const m: ExportedMessage = { role }\n if (textAcc.trim()) m.text = textAcc.trim()\n if (reasoningAcc) m.reasoning = reasoningAcc\n if (toolCalls.length) m.toolCalls = toolCalls\n messages.push(m)\n }\n\n // Emit each tool result as its own role=tool message\n for (const tr of toolResults) {\n messages.push({ role: \"tool\", text: tr.text })\n }\n }\n\n return { meta: { source: \"claude-code\" }, messages }\n}\n\n// ── hermes exporter (SQLite) ──────────────────────────────────────────\n// node:sqlite is experimental in Node 22.x but functional.\n// Isolated here so a future stable import replaces only this function.\n\ninterface HermesSessionRow {\n id: string\n title?: string\n model?: string\n started_at?: number\n ended_at?: number\n message_count?: number\n tool_call_count?: number\n api_call_count?: number\n input_tokens?: number\n output_tokens?: number\n cache_read_tokens?: number\n cache_write_tokens?: number\n reasoning_tokens?: number\n actual_cost_usd?: number\n estimated_cost_usd?: number\n source?: string\n end_reason?: string\n}\n\ninterface HermesMessageRow {\n id: number\n session_id: string\n role: string\n content?: string\n tool_calls?: string\n tool_name?: string\n reasoning?: string\n reasoning_content?: string\n timestamp?: number\n}\n\nasync function exportHermesSession(adapterSessionId: string): Promise<ExportedSession> {\n const dbPath = join(homedir(), \".hermes\", \"state.db\")\n\n // Dynamic import isolates the experimental module warning and lets\n // callers on older Node get a clear error instead of a crash at load time.\n let DatabaseSync: (typeof import(\"node:sqlite\"))[\"DatabaseSync\"]\n try {\n const sqlite = await import(\"node:sqlite\")\n DatabaseSync = sqlite.DatabaseSync\n } catch {\n throw new Error(\n \"hermes exporter: node:sqlite unavailable. Requires Node.js ≥22.5.0.\",\n )\n }\n\n let db: InstanceType<typeof DatabaseSync>\n try {\n db = new DatabaseSync(dbPath, { readOnly: true })\n } catch (err) {\n const msg = String(err)\n if (\n (err as NodeJS.ErrnoException).code === \"ENOENT\" ||\n msg.includes(\"unable to open database file\")\n ) {\n throw new Error(\n `hermes: state.db not found at ${dbPath}. ` +\n `Has hermes been run at least once?`,\n )\n }\n if (msg.includes(\"SQLITE_BUSY\") || msg.includes(\"database is locked\")) {\n throw new Error(\n `hermes: database is locked (SQLITE_BUSY). ` +\n `Hermes may be writing. Try again in a moment.`,\n )\n }\n throw err\n }\n\n const withRetryOnBusy = <T>(fn: () => T): T => {\n try {\n return fn()\n } catch (err) {\n const msg = String(err)\n if (msg.includes(\"SQLITE_BUSY\") || msg.includes(\"database is locked\")) {\n // One brief retry — the lock is usually transient\n try {\n return fn()\n } catch {\n throw new Error(\n `hermes: database is locked. Hermes may be actively writing. Try again.`,\n )\n }\n }\n throw err\n }\n }\n\n const session = withRetryOnBusy(\n () =>\n db\n .prepare(\"SELECT * FROM sessions WHERE id = ?\")\n .get(adapterSessionId) as unknown as HermesSessionRow | undefined,\n )\n\n if (!session) {\n db.close()\n throw new Error(\n `hermes: session \"${adapterSessionId}\" not found in ${dbPath}. ` +\n `ACP sessions are indexed by the agentproto UUID passed as resumeSessionId.`,\n )\n }\n\n const rows = withRetryOnBusy(\n () =>\n db\n .prepare(\n \"SELECT * FROM messages WHERE session_id = ? ORDER BY id ASC\",\n )\n .all(adapterSessionId) as unknown as HermesMessageRow[],\n )\n\n db.close()\n\n const cost =\n session.actual_cost_usd != null\n ? session.actual_cost_usd\n : session.estimated_cost_usd\n\n const startedAt = session.started_at\n ? new Date(session.started_at * 1000).toISOString().replace(\"T\", \" \").slice(0, 19)\n : undefined\n const endedAt = session.ended_at\n ? new Date(session.ended_at * 1000).toISOString().replace(\"T\", \" \").slice(0, 19)\n : undefined\n\n const meta: ExportedSessionMeta = {\n ...(session.title ? { title: session.title } : {}),\n ...(session.model ? { model: session.model } : {}),\n ...(startedAt ? { startedAt } : {}),\n ...(endedAt ? { endedAt } : {}),\n ...(session.message_count !== undefined ? { messageCount: session.message_count } : {}),\n ...(session.tool_call_count !== undefined\n ? { toolCallCount: session.tool_call_count }\n : {}),\n ...(cost != null ? { costUsd: Number(cost) } : {}),\n ...(session.source ? { source: session.source } : {}),\n }\n\n // Only include tokens sub-object when at least one field is present\n const tokensInput = session.input_tokens\n const tokensOutput = session.output_tokens\n const tokensCacheRead = session.cache_read_tokens\n const tokensCacheWrite = session.cache_write_tokens\n const tokensReasoning = session.reasoning_tokens\n if (\n tokensInput !== undefined ||\n tokensOutput !== undefined ||\n tokensCacheRead !== undefined ||\n tokensCacheWrite !== undefined ||\n tokensReasoning !== undefined\n ) {\n meta.tokens = {\n ...(tokensInput !== undefined ? { input: tokensInput } : {}),\n ...(tokensOutput !== undefined ? { output: tokensOutput } : {}),\n ...(tokensCacheRead !== undefined ? { cacheRead: tokensCacheRead } : {}),\n ...(tokensCacheWrite !== undefined ? { cacheWrite: tokensCacheWrite } : {}),\n ...(tokensReasoning !== undefined ? { reasoning: tokensReasoning } : {}),\n }\n }\n\n const messages: ExportedMessage[] = rows.map(row => {\n const validRoles = new Set([\"user\", \"assistant\", \"tool\", \"system\"])\n const role = (\n validRoles.has(row.role) ? row.role : \"user\"\n ) as ExportedMessage[\"role\"]\n\n const reasoning = row.reasoning ?? row.reasoning_content\n\n let toolCalls: { name: string; args: string }[] | undefined\n if (row.tool_calls) {\n try {\n const tc = JSON.parse(row.tool_calls) as unknown[]\n if (Array.isArray(tc) && tc.length) {\n toolCalls = tc.map(c => {\n const entry = c as Record<string, unknown>\n const fn =\n entry.function != null\n ? (entry.function as Record<string, unknown>)\n : entry\n const name = String(fn.name ?? entry.name ?? \"tool\")\n const args =\n typeof fn.arguments === \"string\"\n ? fn.arguments\n : JSON.stringify(fn.arguments ?? {})\n return { name, args }\n })\n }\n } catch {\n // malformed tool_calls — skip\n }\n }\n\n const m: ExportedMessage = { role }\n if (row.content?.trim()) m.text = row.content.trim()\n if (reasoning && String(reasoning).trim()) m.reasoning = String(reasoning)\n if (row.tool_name) m.toolName = row.tool_name\n if (toolCalls) m.toolCalls = toolCalls\n if (row.timestamp) m.ts = row.timestamp\n return m\n })\n\n // Fire-and-forget: cross-check our row count against the binary's export.\n // Non-blocking — a mismatch only logs a warning, it never fails the call.\n void crossValidateHermesExport(adapterSessionId, messages.length).catch(() => {})\n\n return { meta, messages }\n}\n\n// ── Hermes cross-validation via native CLI ────────────────────────────\n//\n// `hermes sessions export --session-id <id> -` emits a stable JSONL\n// transcript on stdout. We use it as a non-blocking sanity-check:\n// if the message count from state.db differs from the binary's output,\n// something in the SQLite schema likely changed and the reader needs\n// updating. The check is fire-and-forget — a mismatch logs a warning but\n// does NOT affect the returned ExportedSession (SQLite stays primary).\n//\n// The export JSONL has one JSON object per message line; lines with a\n// `role` key are treated as messages (other metadata lines are ignored).\n\nexport interface HermesCrossValidationResult {\n sqliteCount: number\n binaryCount: number\n matched: boolean\n /** True when the hermes binary was not found on PATH */\n binaryUnavailable?: boolean\n}\n\n/** Default subprocess runner: spawns `hermes sessions export --session-id <id> -`\n * and returns stdout. Throws with `.code=\"ENOENT\"` when the binary isn't on PATH. */\nasync function defaultHermesRunner(adapterSessionId: string): Promise<string> {\n const { spawn } = await import(\"node:child_process\")\n return new Promise<string>((resolve, reject) => {\n const chunks: Buffer[] = []\n const errChunks: Buffer[] = []\n const proc = spawn(\n \"hermes\",\n [\"sessions\", \"export\", \"--session-id\", adapterSessionId, \"-\"],\n { stdio: [\"ignore\", \"pipe\", \"pipe\"] },\n )\n proc.stdout.on(\"data\", (chunk: Buffer) => chunks.push(chunk))\n proc.stderr.on(\"data\", (chunk: Buffer) => errChunks.push(chunk))\n proc.on(\"error\", reject)\n proc.on(\"close\", code => {\n if (code !== 0) {\n reject(\n new Error(\n `hermes exited with code ${code}: ${Buffer.concat(errChunks).toString()}`,\n ),\n )\n } else {\n resolve(Buffer.concat(chunks).toString(\"utf8\"))\n }\n })\n })\n}\n\n/** Run `hermes sessions export` and compare its message count with\n * what our SQLite reader produced. Returns null on any subprocess\n * error (binary missing, timeout, parse failure).\n *\n * The optional `_runner` parameter lets tests inject a mock that returns stdout\n * directly, avoiding subprocess mocking complexity (promisify + child_process). */\nexport async function crossValidateHermesExport(\n adapterSessionId: string,\n sqliteCount: number,\n _runner: (id: string) => Promise<string> = defaultHermesRunner,\n): Promise<HermesCrossValidationResult | null> {\n let stdout: string\n try {\n stdout = await _runner(adapterSessionId)\n } catch (err) {\n const msg = String(err)\n // ENOENT = binary not on PATH — expected when hermes isn't installed\n if (\n (err as NodeJS.ErrnoException).code === \"ENOENT\" ||\n msg.includes(\"ENOENT\") ||\n msg.includes(\"not found\")\n ) {\n return { sqliteCount, binaryCount: -1, matched: true, binaryUnavailable: true }\n }\n // Any other error (timeout, non-zero exit, etc.) — skip validation\n return null\n }\n\n // Count lines that look like message objects (have a `role` field)\n const binaryCount = stdout\n .split(\"\\n\")\n .filter(l => l.trim())\n .filter(l => {\n try {\n const obj = JSON.parse(l) as Record<string, unknown>\n return typeof obj.role === \"string\"\n } catch {\n return false\n }\n }).length\n\n const matched = binaryCount === sqliteCount\n if (!matched) {\n console.warn(\n `[hermes export] cross-validation mismatch for session ${adapterSessionId}: ` +\n `SQLite=${sqliteCount} messages, binary=${binaryCount} messages. ` +\n `The state.db schema may have changed — check the SQLite reader in transcript-export.ts.`,\n )\n }\n return { sqliteCount, binaryCount, matched }\n}\n\n// ── Strategy registry ─────────────────────────────────────────────────\n\nconst EXPORT_STRATEGIES: Record<string, ExportStrategy> = {\n \"claude-code\": {\n exportSession: exportClaudeCodeSession,\n },\n hermes: {\n exportSession: (id: string) => exportHermesSession(id),\n },\n}\n\n// ── Public API ────────────────────────────────────────────────────────\n\nexport interface ExportAgentSessionInput {\n /** agentproto session id (sess_xxx) or an adapter-native id */\n sessionId: string\n registry: SessionsRegistry\n format?: \"markdown\" | \"json\"\n maxToolChars?: number\n /** Override adapter slug when sessionId is an adapter-native id */\n adapter?: string\n /** Override cwd when sessionId is an adapter-native id (claude-code only) */\n cwd?: string\n}\n\nexport interface ExportAgentSessionResult {\n sessionId: string\n adapter: string\n format: string\n meta: ExportedSessionMeta\n content: string\n}\n\nexport async function exportAgentSession(\n input: ExportAgentSessionInput,\n): Promise<ExportAgentSessionResult> {\n const { sessionId, registry, format = \"markdown\", maxToolChars = 1200 } = input\n\n // Resolve via registry first. `err` closes over `adapterSlug` so it\n // returns the resolved slug (not the raw input) after registry lookup.\n let adapterSlug = input.adapter\n let cwd = input.cwd\n let adapterSessionId = sessionId\n\n const err = (msg: string): ExportAgentSessionResult => ({\n sessionId,\n adapter: adapterSlug ?? \"unknown\",\n format,\n meta: {},\n content: `Error: ${msg}`,\n })\n\n const desc = registry.findByIdOrName(sessionId)\n if (desc) {\n adapterSlug = adapterSlug ?? desc.adapterSlug\n cwd = cwd ?? desc.cwd\n // prefer the adapter-native id over the agentproto id\n if (desc.adapterSessionId) adapterSessionId = desc.adapterSessionId\n }\n\n if (!adapterSlug) {\n return err(\n `session \"${sessionId}\" not found in registry and no adapter override supplied.\\n` +\n `Pass adapter explicitly or use a known session id (sess_xxx or name).`,\n )\n }\n\n const exporter = EXPORT_STRATEGIES[adapterSlug]\n if (!exporter) {\n const supported = Object.keys(EXPORT_STRATEGIES).join(\", \")\n return err(\n `no exporter for adapter \"${adapterSlug}\". Supported: ${supported}.\\n` +\n `Only sessions spawned via claude-code or hermes can be exported.`,\n )\n }\n\n let session: ExportedSession\n try {\n session = await exporter.exportSession(adapterSessionId, cwd)\n } catch (e) {\n return err(e instanceof Error ? e.message : String(e))\n }\n\n const content =\n format === \"json\"\n ? renderJson(session)\n : renderMarkdown(session, { maxToolChars })\n\n return {\n sessionId,\n adapter: adapterSlug,\n format,\n meta: session.meta,\n content,\n }\n}\n","/**\n * `~/.agentproto/workspaces.json` — single source of truth for the\n * local agentproto control plane. Tracks which directories the user\n * has opted into as agentproto workspaces, plus which one is \"active\"\n * (the daemon's default working set when no workspace is named in\n * a tool call).\n *\n * Why a config file instead of recreating an MCP entry per workspace:\n * - One daemon = one MCP entry in the user's IDE (clean to read in\n * `claude mcp list`, no `dapper_willow` / `noble_lantern` spam).\n * - The daemon walks `workspaces[]` at boot and exposes them all;\n * tools that need a target take an optional `workspace` arg and\n * fall back to `active` when omitted.\n * - The CLI (`agentproto workspace add/list/remove/use`), the daemon,\n * and the guilde-web onboarding dialog all read+write the same\n * file, so changes from one surface are immediately visible to\n * the others.\n *\n * File layout is intentionally boring (small, hand-editable JSON) —\n * future fields go on top, never break v1 readers.\n */\n\nimport { promises as fs } from \"node:fs\"\nimport { homedir } from \"node:os\"\nimport { dirname, isAbsolute, resolve } from \"node:path\"\n\nexport const WORKSPACES_CONFIG_VERSION = 1 as const\n\nexport interface WorkspaceEntry {\n /** Stable handle — what tools accept as `workspace`. Lowercase\n * ASCII, hyphen-only. The CLI sanitises arbitrary names down to\n * this shape so paste-from-finder Just Works. */\n slug: string\n /** Absolute filesystem path. Required absolute so the daemon can\n * serve the workspace regardless of its own cwd. */\n path: string\n /** ISO-8601 — first time the entry was added. Pure metadata, no\n * behavioural impact. */\n addedAt: string\n /** Last time the entry was touched (renamed, path edited, used as\n * active). Lets the CLI sort by recency without an N+1 stat. */\n updatedAt: string\n /** Free-text label the user can attach so workspaces with similar\n * slugs stay distinguishable in `agentproto workspace list`. */\n label?: string\n}\n\nexport interface WorkspacesConfig {\n version: typeof WORKSPACES_CONFIG_VERSION\n /** Active workspace slug — daemon defaults to this when no\n * `workspace` arg is passed. May be undefined when no workspaces\n * are registered yet. */\n active?: string\n workspaces: WorkspaceEntry[]\n}\n\nexport const DEFAULT_CONFIG_DIR = (): string =>\n resolve(homedir(), \".agentproto\")\nexport const DEFAULT_CONFIG_PATH = (): string =>\n resolve(DEFAULT_CONFIG_DIR(), \"workspaces.json\")\n\n/** Reduce arbitrary user input to a safe slug. Aligns with what most\n * tooling validates against (`/^[a-z0-9][a-z0-9-]{0,63}$/`) so the\n * daemon never has to encode it for URLs or filesystem paths. */\nexport function sanitizeSlug(input: string): string {\n const trimmed = input.trim().toLowerCase()\n const cleaned = trimmed\n .replace(/[^a-z0-9_-]+/g, \"-\")\n .replace(/^-+|-+$/g, \"\")\n .slice(0, 64)\n // Edge case: input was entirely non-conforming — fall back to a\n // generic so we never return an empty string.\n return cleaned || \"workspace\"\n}\n\n/** Read the config from disk. Returns an empty config (no workspaces,\n * no active) when the file is missing — this is the legitimate\n * first-boot state, not an error. */\nexport async function loadWorkspacesConfig(\n path: string = DEFAULT_CONFIG_PATH()\n): Promise<WorkspacesConfig> {\n let raw: string\n try {\n raw = await fs.readFile(path, \"utf8\")\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === \"ENOENT\") {\n return { version: WORKSPACES_CONFIG_VERSION, workspaces: [] }\n }\n throw err\n }\n let parsed: unknown\n try {\n parsed = JSON.parse(raw)\n } catch (err) {\n throw new Error(\n `agentproto: ${path} is not valid JSON (${\n err instanceof Error ? err.message : String(err)\n }). Delete the file or fix it manually.`\n )\n }\n return normalizeConfig(parsed)\n}\n\n/** Write the config back. Creates the parent directory if missing.\n * Atomic-ish: writes to a temp file first, then renames over the\n * target — avoids the partial-write window where a concurrent reader\n * sees half a JSON object. */\nexport async function saveWorkspacesConfig(\n config: WorkspacesConfig,\n path: string = DEFAULT_CONFIG_PATH()\n): Promise<void> {\n const normalized = normalizeConfig(config)\n await fs.mkdir(dirname(path), { recursive: true })\n const tmp = `${path}.tmp.${process.pid}`\n await fs.writeFile(tmp, JSON.stringify(normalized, null, 2) + \"\\n\", \"utf8\")\n await fs.rename(tmp, path)\n}\n\n/**\n * Pure helpers — caller manages persistence. Returns a NEW config\n * (never mutates) so callers can compose multiple updates before\n * a single save.\n */\nexport function addWorkspace(\n config: WorkspacesConfig,\n input: { slug: string; path: string; label?: string }\n): WorkspacesConfig {\n if (!isAbsolute(input.path)) {\n throw new Error(\n `addWorkspace: path must be absolute, got \"${input.path}\".`\n )\n }\n const slug = sanitizeSlug(input.slug)\n const now = new Date().toISOString()\n const existingIdx = config.workspaces.findIndex(w => w.slug === slug)\n const next: WorkspaceEntry = existingIdx >= 0\n ? {\n ...config.workspaces[existingIdx]!,\n path: input.path,\n ...(input.label !== undefined ? { label: input.label } : {}),\n updatedAt: now,\n }\n : {\n slug,\n path: input.path,\n ...(input.label ? { label: input.label } : {}),\n addedAt: now,\n updatedAt: now,\n }\n const workspaces = [...config.workspaces]\n if (existingIdx >= 0) workspaces[existingIdx] = next\n else workspaces.push(next)\n // First-add becomes active automatically — saves the user a\n // separate `workspace use` call right after a fresh `add`.\n const active = config.active ?? slug\n return { ...config, workspaces, active }\n}\n\nexport function removeWorkspace(\n config: WorkspacesConfig,\n slug: string\n): WorkspacesConfig {\n const sanitised = sanitizeSlug(slug)\n const workspaces = config.workspaces.filter(w => w.slug !== sanitised)\n // If the removed workspace was active, hand off to whatever's\n // first — predictable and avoids leaving the daemon in an\n // unreachable state when the user removes the only one.\n let active = config.active\n if (active === sanitised) {\n active = workspaces[0]?.slug\n }\n const next: WorkspacesConfig = { ...config, workspaces }\n if (active !== undefined) next.active = active\n else delete next.active\n return next\n}\n\nexport function setActiveWorkspace(\n config: WorkspacesConfig,\n slug: string\n): WorkspacesConfig {\n const sanitised = sanitizeSlug(slug)\n if (!config.workspaces.some(w => w.slug === sanitised)) {\n throw new Error(\n `setActiveWorkspace: no workspace registered with slug \"${sanitised}\". ` +\n `Run \\`agentproto workspace add <path> --slug ${sanitised}\\` first.`\n )\n }\n return { ...config, active: sanitised }\n}\n\nexport function findWorkspace(\n config: WorkspacesConfig,\n slug: string\n): WorkspaceEntry | undefined {\n return config.workspaces.find(w => w.slug === sanitizeSlug(slug))\n}\n\n/** The active workspace, or undefined when none is registered. Pure\n * convenience to avoid re-implementing the lookup at every caller. */\nexport function getActiveWorkspace(\n config: WorkspacesConfig\n): WorkspaceEntry | undefined {\n if (!config.active) return config.workspaces[0]\n return findWorkspace(config, config.active) ?? config.workspaces[0]\n}\n\n/**\n * Coerce arbitrary parsed JSON into a valid config. Skips entries\n * with missing required fields rather than throwing — partial recovery\n * is friendlier than \"your config file is corrupted, here's a stack\n * trace\". Logs nothing here; the CLI shells that consume this should\n * decide whether to surface a warning.\n */\nfunction normalizeConfig(parsed: unknown): WorkspacesConfig {\n if (!parsed || typeof parsed !== \"object\") {\n return { version: WORKSPACES_CONFIG_VERSION, workspaces: [] }\n }\n const obj = parsed as Record<string, unknown>\n const workspaces: WorkspaceEntry[] = []\n if (Array.isArray(obj.workspaces)) {\n for (const entry of obj.workspaces) {\n if (!entry || typeof entry !== \"object\") continue\n const e = entry as Record<string, unknown>\n const slug = typeof e.slug === \"string\" ? sanitizeSlug(e.slug) : \"\"\n const path = typeof e.path === \"string\" ? e.path : \"\"\n if (!slug || !path) continue\n const addedAt =\n typeof e.addedAt === \"string\" ? e.addedAt : new Date().toISOString()\n const updatedAt = typeof e.updatedAt === \"string\" ? e.updatedAt : addedAt\n const we: WorkspaceEntry = { slug, path, addedAt, updatedAt }\n if (typeof e.label === \"string\" && e.label.trim()) {\n we.label = e.label.trim()\n }\n workspaces.push(we)\n }\n }\n // De-dupe by slug (last wins) — the file is hand-editable so a\n // typo could have produced two entries with the same slug.\n const dedup = new Map<string, WorkspaceEntry>()\n for (const w of workspaces) dedup.set(w.slug, w)\n const finalList = Array.from(dedup.values())\n const active =\n typeof obj.active === \"string\" && finalList.some(w => w.slug === obj.active)\n ? (obj.active as string)\n : finalList[0]?.slug\n const out: WorkspacesConfig = {\n version: WORKSPACES_CONFIG_VERSION,\n workspaces: finalList,\n }\n if (active !== undefined) out.active = active\n return out\n}\n","/**\n * Discover MCP servers already configured in the user's local agent\n * tooling — claude-code, cursor, goose, etc. — so the daemon can\n * surface them in the UI without making the user re-enter the same\n * credentials and URLs they already painstakingly configured for\n * one host.\n *\n * v1 is read-only discovery: we report what's there with source\n * attribution. Future v1.1 ships an \"import to daemon\" verb that\n * proxies the discovered server through the daemon's own /mcp\n * endpoint so every operator (cloud Guilde, local agents) sees a\n * unified set without per-host config drift.\n *\n * Sources scanned (in priority order):\n * - ~/.claude.json (claude-code) — `mcpServers` top-level + nested\n * under `projects[<path>].mcpServers`. Most users land here.\n * - ~/.cursor/mcp.json (cursor) — flat `mcpServers` map.\n * - ~/.config/goose/config.yaml (goose) — TOML/YAML hybrid; we\n * only handle the YAML form for now.\n * - any `.mcp.json` under the user's home that follows the\n * standard mcpServers shape.\n *\n * Each source contributes 0..N entries. Errors are caught + logged\n * (broken JSON, missing files, permission denied) — partial\n * discovery beats failing the whole listing on one bad file.\n */\n\nimport { promises as fs } from \"node:fs\"\nimport { homedir } from \"node:os\"\nimport { resolve as resolvePath } from \"node:path\"\nimport {\n loadWorkspacesConfig,\n type WorkspaceEntry,\n} from \"./workspaces-config.js\"\n\nexport interface DiscoveredMcp {\n /** Stable id within (source, scope, name) — for de-dupe and\n * cross-call identity (UI treat as React key). */\n id: string\n /** Where we found it. Lets the UI render a source badge. */\n source: \"claude-code\" | \"cursor\" | \"goose\" | \"workspace\"\n /** \"global\" when the entry sits at the top level of the host's\n * config; \"project:<path>\" when it's scoped to a single\n * workspace. claude-code in particular nests per-project. */\n scope: string\n /** The host's name for the entry (key in the mcpServers map). */\n name: string\n /** Wire transport — `stdio` (command + args) or `http` / `sse` (url). */\n type: \"stdio\" | \"http\" | \"sse\" | \"unknown\"\n /** stdio entries: argv to spawn. */\n command?: string\n args?: string[]\n /** stdio entries: env injected into the child. */\n env?: Record<string, string>\n /** http/sse entries: target URL. */\n url?: string\n /** http/sse entries: extra headers (Authorization, etc.). */\n headers?: Record<string, string>\n /** Free-form tags from the source config — claude-code's project\n * scope is the most common. */\n tags?: string[]\n /** Reason field when `type === \"unknown\"` — surfaces why the\n * parser couldn't classify the entry (e.g. neither command nor\n * url present). */\n parseNote?: string\n}\n\nexport interface DiscoverMcpsOptions {\n /** Override the home dir — handy for tests that pin a tmpdir. */\n home?: string\n}\n\nexport async function discoverMcps(\n opts: DiscoverMcpsOptions = {}\n): Promise<DiscoveredMcp[]> {\n const home = opts.home ?? homedir()\n const out: DiscoveredMcp[] = []\n const errors: string[] = []\n await Promise.all([\n scanClaudeCode(home, out, errors),\n scanCursor(home, out, errors),\n scanGoose(home, out, errors),\n scanRegisteredWorkspaces(out, errors),\n ])\n // De-dupe identical entries that show up in multiple scopes\n // (e.g. user copied a project entry to global) — keep the first\n // occurrence so the source attribution stays meaningful.\n const seen = new Set<string>()\n const dedup: DiscoveredMcp[] = []\n for (const m of out) {\n const key = `${m.source}:${m.scope}:${m.name}`\n if (seen.has(key)) continue\n seen.add(key)\n dedup.push(m)\n }\n if (errors.length > 0) {\n // One log line per error — operators can trace which file\n // failed without us bubbling the whole stack into the response.\n for (const e of errors) console.warn(`[mcp-discovery] ${e}`)\n }\n return dedup.sort((a, b) => {\n if (a.source !== b.source) return a.source.localeCompare(b.source)\n if (a.scope !== b.scope) return a.scope.localeCompare(b.scope)\n return a.name.localeCompare(b.name)\n })\n}\n\ninterface RawMcpEntry {\n type?: string\n command?: string\n args?: string[]\n env?: Record<string, string>\n url?: string\n headers?: Record<string, string>\n}\n\n/** claude-code stores entries either at top-level `mcpServers` OR\n * per-project under `projects[<absolute-path>].mcpServers`. We\n * surface both with `scope` set so the UI can group by project. */\nasync function scanClaudeCode(\n home: string,\n out: DiscoveredMcp[],\n errors: string[]\n): Promise<void> {\n const path = resolvePath(home, \".claude.json\")\n let raw: string\n try {\n raw = await fs.readFile(path, \"utf8\")\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === \"ENOENT\") return\n errors.push(`claude-code: read ${path} — ${(err as Error).message}`)\n return\n }\n let parsed: unknown\n try {\n parsed = JSON.parse(raw)\n } catch (err) {\n errors.push(`claude-code: JSON parse ${path} — ${(err as Error).message}`)\n return\n }\n if (!parsed || typeof parsed !== \"object\") return\n const root = parsed as Record<string, unknown>\n const top = root.mcpServers\n if (top && typeof top === \"object\") {\n pushMcpMap({\n out,\n source: \"claude-code\",\n scope: \"global\",\n map: top as Record<string, unknown>,\n })\n }\n const projects = root.projects\n if (projects && typeof projects === \"object\") {\n for (const [projPath, proj] of Object.entries(\n projects as Record<string, unknown>\n )) {\n if (!proj || typeof proj !== \"object\") continue\n const projMcps = (proj as Record<string, unknown>).mcpServers\n if (!projMcps || typeof projMcps !== \"object\") continue\n pushMcpMap({\n out,\n source: \"claude-code\",\n scope: `project:${projPath}`,\n map: projMcps as Record<string, unknown>,\n })\n }\n }\n}\n\n/** cursor uses ~/.cursor/mcp.json (standard mcpServers shape).\n * Also supports per-workspace `.cursor/mcp.json` but those need\n * the user's project paths — out of scope for v1. */\nasync function scanCursor(\n home: string,\n out: DiscoveredMcp[],\n errors: string[]\n): Promise<void> {\n const path = resolvePath(home, \".cursor\", \"mcp.json\")\n let raw: string\n try {\n raw = await fs.readFile(path, \"utf8\")\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === \"ENOENT\") return\n errors.push(`cursor: read ${path} — ${(err as Error).message}`)\n return\n }\n let parsed: unknown\n try {\n parsed = JSON.parse(raw)\n } catch (err) {\n errors.push(`cursor: JSON parse ${path} — ${(err as Error).message}`)\n return\n }\n if (!parsed || typeof parsed !== \"object\") return\n const root = parsed as Record<string, unknown>\n const map = root.mcpServers\n if (map && typeof map === \"object\") {\n pushMcpMap({\n out,\n source: \"cursor\",\n scope: \"global\",\n map: map as Record<string, unknown>,\n })\n }\n}\n\n/** goose stores config in ~/.config/goose/config.yaml. The full\n * parser is non-trivial (yaml + extension manifests); v1 looks for\n * the simple `extensions:` block with `mcp_servers` declarations\n * and emits a parseNote so the user knows we found goose but\n * punted on the details. */\nasync function scanGoose(\n home: string,\n out: DiscoveredMcp[],\n errors: string[]\n): Promise<void> {\n // ~/.config on macOS / Linux; goose hasn't shipped Windows-native yet.\n const path = resolvePath(home, \".config\", \"goose\", \"config.yaml\")\n try {\n await fs.access(path)\n } catch {\n return\n }\n // We don't ship a yaml parser as a runtime dep — record presence\n // but punt on parsing. The user sees \"goose detected — open\n // ~/.config/goose/config.yaml to inspect entries\" which is enough\n // signal to drive a v2 enhancement.\n out.push({\n id: \"goose:global:_detected\",\n source: \"goose\",\n scope: \"global\",\n name: \"(goose config detected)\",\n type: \"unknown\",\n parseNote:\n \"Goose config found but YAML parsing is not yet implemented. \" +\n \"Open ~/.config/goose/config.yaml to inspect MCP entries.\",\n })\n}\n\n/**\n * Per-workspace scan — for each registered workspace, look at the\n * common per-project MCP locations (.mcp.json, .cursor/mcp.json,\n * .vscode/mcp.json). Lets the UI surface \"this workspace ships\n * its own chrome-devtools MCP\" instead of only\n * showing what the user configured globally in claude/cursor.\n */\nasync function scanRegisteredWorkspaces(\n out: DiscoveredMcp[],\n errors: string[]\n): Promise<void> {\n let workspaces: WorkspaceEntry[] = []\n try {\n const cfg = await loadWorkspacesConfig()\n workspaces = cfg.workspaces\n } catch (err) {\n errors.push(`workspaces: load failed — ${(err as Error).message}`)\n return\n }\n // Walk each workspace + each candidate path. We don't recurse —\n // these are conventional top-level files. Errors per-file are\n // collected; one bad file doesn't fail the rest.\n await Promise.all(\n workspaces.map(async ws => {\n const candidates = [\n resolvePath(ws.path, \".mcp.json\"),\n resolvePath(ws.path, \".cursor\", \"mcp.json\"),\n resolvePath(ws.path, \".vscode\", \"mcp.json\"),\n ]\n for (const path of candidates) {\n let raw: string\n try {\n raw = await fs.readFile(path, \"utf8\")\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === \"ENOENT\") continue\n errors.push(\n `workspace ${ws.slug}: read ${path} — ${(err as Error).message}`\n )\n continue\n }\n let parsed: unknown\n try {\n parsed = JSON.parse(raw)\n } catch (err) {\n errors.push(\n `workspace ${ws.slug}: JSON parse ${path} — ${(err as Error).message}`\n )\n continue\n }\n if (!parsed || typeof parsed !== \"object\") continue\n const map = (parsed as Record<string, unknown>).mcpServers\n if (!map || typeof map !== \"object\") continue\n pushMcpMap({\n out,\n source: \"workspace\",\n scope: `workspace:${ws.slug}`,\n map: map as Record<string, unknown>,\n })\n }\n })\n )\n}\n\nfunction pushMcpMap(args: {\n out: DiscoveredMcp[]\n source: DiscoveredMcp[\"source\"]\n scope: string\n map: Record<string, unknown>\n}): void {\n for (const [name, raw] of Object.entries(args.map)) {\n if (!raw || typeof raw !== \"object\") continue\n const entry = raw as RawMcpEntry\n const id = `${args.source}:${args.scope}:${name}`\n const declared = typeof entry.type === \"string\" ? entry.type : null\n const url = typeof entry.url === \"string\" ? entry.url : undefined\n const command = typeof entry.command === \"string\" ? entry.command : undefined\n let type: DiscoveredMcp[\"type\"]\n if (declared === \"http\" || declared === \"sse\" || declared === \"stdio\") {\n type = declared\n } else if (url) {\n type = \"http\"\n } else if (command) {\n type = \"stdio\"\n } else {\n type = \"unknown\"\n }\n const m: DiscoveredMcp = {\n id,\n source: args.source,\n scope: args.scope,\n name,\n type,\n }\n if (command !== undefined) m.command = command\n if (Array.isArray(entry.args)) {\n m.args = entry.args.filter((a): a is string => typeof a === \"string\")\n }\n if (entry.env && typeof entry.env === \"object\") {\n m.env = stringifyValues(entry.env)\n }\n if (url !== undefined) m.url = url\n if (entry.headers && typeof entry.headers === \"object\") {\n m.headers = stringifyValues(entry.headers)\n }\n if (type === \"unknown\") {\n m.parseNote =\n \"Entry has neither `command` nor `url` — couldn't classify transport.\"\n }\n args.out.push(m)\n }\n}\n\nfunction stringifyValues(\n raw: Record<string, unknown>\n): Record<string, string> {\n const out: Record<string, string> = {}\n for (const [k, v] of Object.entries(raw)) {\n if (typeof v === \"string\") out[k] = v\n else if (v != null) out[k] = String(v)\n }\n return out\n}\n","/**\n * `~/.agentproto/imported-mcps.json` — the user's curated set of\n * discovered MCPs they want the daemon to know about. v1 is just\n * persistence + read-side; the actual MCP-proxy implementation\n * (where the daemon's /mcp endpoint aggregates the imported\n * servers' tools under namespace prefixes) is v2 work.\n *\n * Purpose: today, \"I see you have chrome-devtools in claude\" is\n * read-only. Once a user imports it, the operator agent can refer\n * to it (\"the user said it's enabled — call it\") and a future\n * proxy layer can actually expose it. We persist the choice now so\n * the data is in place when the proxy lands.\n *\n * File shape:\n * {\n * \"version\": 1,\n * \"imports\": [\n * {\n * \"id\": \"claude-code:project:/path:chrome-devtools\",\n * \"alias\": \"chrome-devtools\",\n * \"addedAt\": \"2026-05-10T...\",\n * \"snapshot\": { ...the DiscoveredMcp at import time }\n * }\n * ]\n * }\n *\n * Snapshotting at import time keeps the daemon resilient to the\n * source config getting deleted (user runs `claude mcp remove ...`).\n * The imported entry stays usable; only the next discovery pass\n * stops listing it as \"available to import.\"\n */\n\nimport { promises as fs } from \"node:fs\"\nimport { homedir } from \"node:os\"\nimport { dirname, resolve as resolvePath } from \"node:path\"\nimport type { DiscoveredMcp } from \"./mcp-discovery.js\"\n\nexport const IMPORTED_MCPS_PATH = (): string =>\n resolvePath(homedir(), \".agentproto\", \"imported-mcps.json\")\n\nexport const IMPORTED_MCPS_VERSION = 1 as const\n\nexport interface ImportedMcpEntry {\n id: string\n alias: string\n addedAt: string\n snapshot: DiscoveredMcp\n}\n\nexport interface ImportedMcpsConfig {\n version: typeof IMPORTED_MCPS_VERSION\n imports: ImportedMcpEntry[]\n}\n\nconst EMPTY: ImportedMcpsConfig = {\n version: IMPORTED_MCPS_VERSION,\n imports: [],\n}\n\nexport async function loadImportedMcps(\n path: string = IMPORTED_MCPS_PATH()\n): Promise<ImportedMcpsConfig> {\n let raw: string\n try {\n raw = await fs.readFile(path, \"utf8\")\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === \"ENOENT\") return EMPTY\n throw err\n }\n let parsed: unknown\n try {\n parsed = JSON.parse(raw)\n } catch (err) {\n throw new Error(\n `agentproto: ${path} is not valid JSON (${\n err instanceof Error ? err.message : String(err)\n }). Delete or fix manually.`\n )\n }\n return normalize(parsed)\n}\n\nexport async function saveImportedMcps(\n config: ImportedMcpsConfig,\n path: string = IMPORTED_MCPS_PATH()\n): Promise<void> {\n await fs.mkdir(dirname(path), { recursive: true })\n const tmp = `${path}.tmp.${process.pid}`\n await fs.writeFile(tmp, JSON.stringify(config, null, 2) + \"\\n\", \"utf8\")\n await fs.rename(tmp, path)\n}\n\n/**\n * Add (or replace) an import. Snapshots the discovered MCP at\n * import time so the entry stays usable when the source config\n * disappears.\n */\nexport function addImport(\n config: ImportedMcpsConfig,\n input: { snapshot: DiscoveredMcp; alias?: string }\n): ImportedMcpsConfig {\n const alias = (input.alias ?? input.snapshot.name).trim()\n if (!alias) {\n throw new Error(\"addImport: alias resolves to empty string\")\n }\n const addedAt = new Date().toISOString()\n const next: ImportedMcpEntry = {\n id: input.snapshot.id,\n alias,\n addedAt,\n snapshot: input.snapshot,\n }\n const others = config.imports.filter(e => e.id !== input.snapshot.id)\n return { ...config, imports: [...others, next] }\n}\n\nexport function removeImport(\n config: ImportedMcpsConfig,\n id: string\n): ImportedMcpsConfig {\n return { ...config, imports: config.imports.filter(e => e.id !== id) }\n}\n\nexport function findImport(\n config: ImportedMcpsConfig,\n id: string\n): ImportedMcpEntry | undefined {\n return config.imports.find(e => e.id === id)\n}\n\nfunction normalize(parsed: unknown): ImportedMcpsConfig {\n if (!parsed || typeof parsed !== \"object\") return EMPTY\n const obj = parsed as Record<string, unknown>\n const imports: ImportedMcpEntry[] = []\n if (Array.isArray(obj.imports)) {\n for (const entry of obj.imports) {\n if (!entry || typeof entry !== \"object\") continue\n const e = entry as Record<string, unknown>\n const id = typeof e.id === \"string\" ? e.id : \"\"\n const alias = typeof e.alias === \"string\" ? e.alias : id\n const addedAt =\n typeof e.addedAt === \"string\" ? e.addedAt : new Date().toISOString()\n const snapshot = e.snapshot as DiscoveredMcp | undefined\n if (!id || !snapshot) continue\n imports.push({ id, alias, addedAt, snapshot })\n }\n }\n return { version: IMPORTED_MCPS_VERSION, imports }\n}\n","/**\n * Tool-subset guard — the single mechanism that scopes which MCP tools\n * a `register*` pass actually exposes on a server.\n *\n * `withToolSubset(server, subset)` returns a Proxy where\n * `server.tool(name, …)` is a no-op when `name ∉ subset`; every other\n * call delegates to the underlying server unchanged. The orchestrator\n * sub-gateway (ADR §4.2 / WP2) wraps its per-request server with this\n * before running the normal `registerSessionTools` /\n * `registerOrchestrationTools` passes, so a scoped child orchestrator\n * only ever sees the curated allowlist (spawn / prompt / wait / poll /\n * output / list / kill) — never `execute_command`, fs, remote, import,\n * or terminal tools.\n *\n * Backward-compatible by construction: callers that don't pass a subset\n * use the raw server and register everything, exactly as before.\n */\n\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\"\n\nexport function withToolSubset(\n server: McpServer,\n subset: ReadonlySet<string>,\n): McpServer {\n return new Proxy(server, {\n get(target, prop, receiver) {\n if (prop === \"tool\") {\n // One guard for every `server.tool(name, …)` call: drop the\n // registration entirely when the name is outside the allowlist.\n return (name: string, ...rest: unknown[]): unknown => {\n if (!subset.has(name)) return undefined\n return (\n target.tool as unknown as (n: string, ...r: unknown[]) => unknown\n )(name, ...rest)\n }\n }\n const value = Reflect.get(target, prop, receiver)\n // Bind methods to the real server so SDK internals that touch\n // private fields keep working through the proxy.\n return typeof value === \"function\" ? value.bind(target) : value\n },\n })\n}\n","/**\n * `jsonTolerant` — wrap a zod schema so it also accepts a JSON-stringified\n * form of its value.\n *\n * Why: some MCP clients (notably the cowork client) stringify parameters\n * whose declared type is a UNION or an OBJECT/ARRAY before sending them\n * over the wire. A field declared `z.union([z.boolean(), z.object({…})])`\n * then receives the literal string `\"true\"` or `\"{\\\"tools\\\":[…]}\"`, and the\n * daemon's strict zod rejects it (`invalid_union: … received string`).\n * Plain scalars (a bare `onlyAlive: true`) survive because the client\n * doesn't stringify them; only composite types break.\n *\n * What: `jsonTolerant(schema)` returns `z.preprocess(…, schema)` that, when\n * it sees a string, tries `JSON.parse` and feeds the parsed result to the\n * inner schema. If the string is NOT valid JSON, it is passed through\n * untouched so the inner schema produces its normal, readable validation\n * error (we never swallow the failure into a crash or a silent default).\n *\n * Semantics are unchanged for well-behaved clients: a value that already\n * has the right type is never a string, so `tryParse` is never invoked and\n * the inner schema sees it verbatim.\n */\n\nimport { z } from \"zod\"\n\n/**\n * Attempt to JSON-parse a string. Returns the parsed value on success, or\n * the original string on failure (so the inner schema reports the real\n * type error instead of us masking it). Only objects/arrays/primitives\n * that JSON can express are produced — exactly the shapes a client would\n * have stringified.\n */\nexport function tryParseJson(value: string): unknown {\n try {\n return JSON.parse(value)\n } catch {\n return value\n }\n}\n\n/**\n * Wrap `schema` so a JSON-stringified value is coerced back to its parsed\n * form before validation. Non-string inputs flow straight through.\n */\nexport function jsonTolerant<T extends z.ZodTypeAny>(schema: T) {\n return z.preprocess(\n v => (typeof v === \"string\" ? tryParseJson(v) : v),\n schema,\n )\n}\n","/**\n * MCP tools that expose the sessions registry to agents connected to\n * the daemon. Lets a remote operator (Mastra agent in cloud Guilde,\n * Claude Code as a sub-agent, …) spawn + drive agent CLIs on the\n * user's machine through the same MCP connection they already use\n * for fs/exec.\n *\n * Five tools:\n * start_agent_session spawn a long-running agent (claude / hermes / …)\n * prompt_agent_session send a follow-up turn to a live session\n * list_agent_sessions browse alive + recent sessions\n * get_agent_session_output tail the ring buffer\n * kill_agent_session SIGTERM the session\n *\n * Auth: same as every other daemon tool — gated by the gateway's\n * auth source (loopback bypass when no tunnel is up).\n */\n\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\"\nimport { z } from \"zod\"\nimport type { AcpMcpServer } from \"@agentproto/acp\"\nimport type { SessionsRegistry } from \"./sessions.js\"\nimport {\n exportAgentSession,\n type ExportAgentSessionInput,\n type ExportAgentSessionResult,\n} from \"./transcript-export.js\"\nimport type {\n AgentAdapterResolver,\n AgentAdapterLister,\n} from \"./http-server.js\"\nimport {\n loadWorkspacesConfig,\n findWorkspace,\n getActiveWorkspace,\n} from \"./workspaces-config.js\"\nimport { discoverMcps } from \"./mcp-discovery.js\"\nimport {\n loadImportedMcps,\n saveImportedMcps,\n addImport,\n removeImport,\n} from \"./mcp-imports.js\"\nimport type { McpProxyRegistry } from \"./mcp-proxy.js\"\nimport { withToolSubset } from \"./tool-subset.js\"\nimport { jsonTolerant } from \"./json-tolerant.js\"\nimport type { OrchestratorScope } from \"./orchestrator-gateway.js\"\nimport type { SessionDescriptor } from \"./sessions.js\"\nimport type { WebhookNotifier } from \"./webhook-notifier.js\"\n\n/** Strip CSI/SGR ANSI escape sequences. Exported for test access. */\nexport function stripAnsi(s: string): string {\n return s.replace(/\\x1b\\[[0-9;?]*[A-Za-z]/g, \"\")\n}\n\n/**\n * One node in the session-tree output (WP5). Mirrors the descriptor\n * fields most useful for observability + recursion, plus a `children`\n * array so consumers can walk the tree without building the index\n * themselves, and an `isOrchestrator` flag that's true when the\n * session spawned at least one child (i.e. any session carries its id\n * as `parentSessionId`).\n */\nexport interface SessionTreeNode {\n id: string\n label?: string\n status: string\n depth: number\n adapterSlug?: string\n parentSessionId?: string\n isOrchestrator: boolean\n children: SessionTreeNode[]\n}\n\n/**\n * Build a nested session tree from a (scoped) flat list. Roots are\n * sessions whose `parentSessionId` is absent or points outside the\n * provided list (the list is already scoped when called from the\n * tool handler). Each root carries its descendants as nested\n * `children`, breadth-first insertion, depth-sorted within siblings.\n *\n * Exported for testing.\n */\nexport function buildSessionTree(\n sessions: readonly SessionDescriptor[],\n): SessionTreeNode[] {\n const idSet = new Set(sessions.map(s => s.id))\n // Build parent→children index.\n const childrenOf = new Map<string, SessionDescriptor[]>()\n for (const s of sessions) {\n if (s.parentSessionId && idSet.has(s.parentSessionId)) {\n const arr = childrenOf.get(s.parentSessionId)\n if (arr) arr.push(s)\n else childrenOf.set(s.parentSessionId, [s])\n }\n }\n // Identify nodes that spawned at least one child (isOrchestrator).\n const orchestratorIds = new Set(childrenOf.keys())\n\n const toNode = (s: SessionDescriptor): SessionTreeNode => ({\n id: s.id,\n ...(s.label ? { label: s.label } : {}),\n status: s.status,\n depth: s.depth ?? 0,\n ...(s.adapterSlug ? { adapterSlug: s.adapterSlug } : {}),\n ...(s.parentSessionId ? { parentSessionId: s.parentSessionId } : {}),\n isOrchestrator: orchestratorIds.has(s.id),\n children: (childrenOf.get(s.id) ?? [])\n .sort((a, b) => (a.depth ?? 0) - (b.depth ?? 0))\n .map(toNode),\n })\n\n // Roots: no parentSessionId, or parent is outside the scoped list.\n return sessions\n .filter(s => !s.parentSessionId || !idSet.has(s.parentSessionId))\n .sort((a, b) => a.startedAt.localeCompare(b.startedAt))\n .map(toNode)\n}\n\n/**\n * Compute the set of session ids in the subtree rooted at `rootId` —\n * the root itself plus every descendant reachable through the\n * `parentSessionId` chain (orchestrator WP4). Used to scope\n * `list`/`kill` on the scoped sub-gateway so a child orchestrator only\n * ever sees/affects the sessions it (transitively) spawned, never the\n * whole daemon. Returns an empty set when `rootId` is undefined (an\n * unbound scope sees nothing — safe default).\n */\nexport function collectSubtree(\n rootId: string | undefined,\n all: readonly SessionDescriptor[],\n): Set<string> {\n const result = new Set<string>()\n if (!rootId) return result\n const childrenOf = new Map<string, string[]>()\n for (const s of all) {\n if (!s.parentSessionId) continue\n const arr = childrenOf.get(s.parentSessionId)\n if (arr) arr.push(s.id)\n else childrenOf.set(s.parentSessionId, [s.id])\n }\n const queue = [rootId]\n result.add(rootId)\n while (queue.length > 0) {\n const id = queue.shift() as string\n for (const child of childrenOf.get(id) ?? []) {\n if (!result.has(child)) {\n result.add(child)\n queue.push(child)\n }\n }\n }\n return result\n}\n\ninterface RegisterSessionToolsOptions {\n registry: SessionsRegistry\n /** Optional adapter resolver — required for `start_agent_session`\n * (the others work with raw spawn sessions too). When unset the\n * start tool returns a clear error pointing at the host wiring. */\n resolveAgentAdapter?: AgentAdapterResolver\n /** Optional adapter lister — when wired, exposes `list_adapters`\n * MCP tool. Without it the tool returns a clear \"not configured\"\n * error pointing at the host wiring. */\n listAgentAdapters?: AgentAdapterLister\n /** Optional MCP proxy registry — when wired, exposes 3 tools that\n * let the operator drive imported MCPs (chrome-devtools, goose-bridge,\n * …) through the daemon as a single MCP entry point. */\n mcpProxy?: McpProxyRegistry\n /** Whether the registry was constructed with a PTY factory — when\n * true, expose the four terminal session tools. When false, the\n * tools return a clear \"not configured\" error. */\n ptyEnabled?: boolean\n /** Optional allowlist — when set, only tools whose name is in the\n * set are registered (the scoped orchestrator sub-gateway, WP2).\n * Omitted → register everything, today's behaviour. */\n toolSubset?: ReadonlySet<string>\n /** Optional orchestrator-injection builder (WP3). When wired, the\n * `orchestrator` field on `start_agent_session` mints a scoped\n * sub-gateway token, builds the `mcpServers` entry pointing the\n * child at `/mcp/orchestrator?scope=<token>`, and returns a\n * `bindLifecycle` hook the handler calls (with the spawned session\n * id) so the token is revoked when that session exits. Closed over\n * the gateway's scope-token registry + HTTP port + session-event\n * bus in `createGateway`. Omitted → `orchestrator` is rejected with\n * a clear \"not enabled\" error. */\n buildOrchestratorMcp?: (opts: {\n tools?: readonly string[]\n /** Caller orchestrator scope (WP4) — when a child orchestrator\n * spawns its OWN sub-orchestrator, the new token inherits depth+1\n * and is bounded by the caller's tools (non-re-grant). */\n caller?: OrchestratorScope\n /** Override max depth for the minted child scope (clamped to the\n * caller's, then HARD_MAX_DEPTH). */\n maxDepth?: number\n /** Override the child quota for the minted child scope (clamped to\n * the caller's). */\n maxChildren?: number\n }) => {\n entry: AcpMcpServer\n bindLifecycle: (sessionId: string) => () => void\n }\n /** Calling orchestrator's scope (orchestrator WP4). Present ONLY on\n * the scoped sub-gateway server (built per-request from a verified\n * scope-token), absent on the root `/mcp` server. When present it is\n * the identity of the orchestrator driving these tools, so:\n * - spawns are attributed (`parentSessionId = ownerSessionId`,\n * `depth = depth + 1`) and gated by the depth cap + child quota;\n * - `list_sessions`/`list_agent_sessions`/`kill_agent_session` are\n * restricted to the caller's subtree.\n * Absent → full visibility, depth-0 spawns, no parent (today's root\n * behaviour). */\n callerScope?: OrchestratorScope\n /** Optional webhook notifier — when provided, per-session `notifyUrl`\n * values from `start_agent_session` are registered on spawn and\n * unregistered on exit via the session-event bus. */\n webhookNotifier?: WebhookNotifier\n}\n\n/** MCP clients commonly stringify scalar arguments (\"true\"/\"false\"/\"42\").\n * These coercers let a flag work whether the client sends a real JSON\n * boolean/number or its string form — avoids opaque \"expected boolean,\n * received string\" validation errors over the wire. */\nconst mcpBool = z.preprocess(\n v => (v === \"true\" ? true : v === \"false\" ? false : v),\n z.boolean(),\n)\nconst mcpPositiveNumber = z.preprocess(\n v => (typeof v === \"string\" && v.trim() !== \"\" ? Number(v) : v),\n z.number().positive(),\n)\n\n/** Strip ANSI escapes and drop the ACP framing/marker noise (`── … ──`\n * turn frames + `[thought]` / `[tool]` lines) so the lines read as plain,\n * human-friendly text. Used by `get_agent_session_output({clean})` and the\n * `start_agent_session({wait})` one-shot output. */\nfunction cleanAgentLines(lines: string[]): string[] {\n return lines\n .map(l => l.replace(/\\x1b\\[[0-9;]*m/g, \"\"))\n .filter(l => {\n const t = l.trim()\n return !t.startsWith(\"──\") && !/^\\[(thought|tool)\\b/.test(t)\n })\n}\n\nexport function registerSessionTools(\n rawServer: McpServer,\n opts: RegisterSessionToolsOptions\n): void {\n // When a subset is requested, every `server.tool(...)` below is\n // filtered through this one guard (ADR §4.2). No subset → raw server.\n const server = opts.toolSubset\n ? withToolSubset(rawServer, opts.toolSubset)\n : rawServer\n const {\n registry,\n resolveAgentAdapter,\n listAgentAdapters,\n mcpProxy,\n buildOrchestratorMcp,\n callerScope,\n webhookNotifier,\n } = opts\n const ptyEnabled = opts.ptyEnabled === true\n\n // ── start_agent_session ────────────────────────────────────────\n server.tool(\n \"start_agent_session\",\n \"Spawn a long-running agent CLI (claude-code, hermes, …) on the host. \" +\n \"The session stays alive across multiple turns — call `prompt_agent_session` \" +\n \"to continue the conversation. Returns the session id + initial descriptor. \" +\n \"When `workspaceSlug` is set, resolves the cwd via \" +\n \"`~/.agentproto/workspaces.json`; otherwise pass `cwd` explicitly or \" +\n \"fall back to the active workspace.\",\n {\n adapter: z\n .string()\n .min(1)\n .describe(\n \"Adapter slug — one of the installed `@agentproto/adapter-*` packages \" +\n \"(e.g. 'claude-code', 'hermes', 'aider').\"\n ),\n workspaceSlug: z\n .string()\n .optional()\n .describe(\n \"Workspace slug from `agentproto workspace list`. The daemon resolves it \" +\n \"to an absolute path. Omit to use the `cwd` field or the active workspace.\"\n ),\n cwd: z\n .string()\n .optional()\n .describe(\n \"Absolute path to spawn the agent in. Wins over `workspaceSlug` when both are set.\"\n ),\n prompt: z\n .string()\n .optional()\n .describe(\n \"Optional initial prompt. The session is spawned and the prompt dispatched \" +\n \"in one shot — equivalent to `start` then `prompt` back-to-back. Skip to spawn idle.\"\n ),\n label: z\n .string()\n .optional()\n .describe(\n \"Free-text label that surfaces in `list_agent_sessions` and the UI — useful \" +\n \"for tagging sessions with a conversation id or operator name.\"\n ),\n model: z\n .string()\n .optional()\n .describe(\n \"Model identifier to pass to the adapter (e.g. 'claude-opus-4-8'). \" +\n \"For ACP adapters (claude-code) applied via session/set_config_option \" +\n \"after newSession — NOT via a CLI flag. Others may ignore it.\"\n ),\n effort: z\n .string()\n .optional()\n .describe(\n \"Reasoning effort level (e.g. 'low', 'medium', 'high', 'xhigh', 'max', 'ultracode'). \" +\n \"IMPORTANT: effort is calibrated per model — the same label maps to different \" +\n \"compute budgets across models, and defaults differ by model \" +\n \"(Sonnet 4.6 / Opus 4.8 default 'high'; Opus 4.7 default 'xhigh'). \" +\n \"'max' and 'ultracode' are session-only. Omit to keep the model's own default.\"\n ),\n mcpServers: jsonTolerant(\n z.array(\n z.object({\n name: z.string(),\n transport: z.enum([\"stdio\", \"http\", \"sse\"]),\n ref: z.string().optional(),\n })\n )\n )\n .optional()\n .describe(\n \"MCP servers to mount into the spawned agent's session at spawn time. \" +\n \"Forwarded verbatim to `session/new.mcpServers` on the ACP arm — gives \" +\n \"the child agent a host-chosen scoped toolset (e.g. the daemon's own \" +\n \"orchestration gateway so it can spawn + supervise sub-agents). \" +\n \"Adapters that don't model MCP mounting ignore it.\"\n ),\n orchestrator: jsonTolerant(\n z.union([\n z.boolean(),\n z.object({\n tools: z\n .array(z.string())\n .optional()\n .describe(\n \"Explicit allowlist — narrows the orchestration toolset to ⊆ the \" +\n \"default subset. Names outside the default are dropped (a child \" +\n \"can never widen its own scope). Omit for the full default subset.\"\n ),\n maxDepth: z\n .number()\n .int()\n .min(1)\n .max(8)\n .optional()\n .describe(\n \"Max recursion depth reachable through this child (default 3, hard \" +\n \"ceiling 8). A spawn that would exceed it is rejected. For a \" +\n \"recursive spawn it can only LOWER the inherited cap, never raise it.\"\n ),\n maxChildren: z\n .number()\n .int()\n .min(1)\n .optional()\n .describe(\n \"Max concurrently-alive sub-agents this child may spawn (default 8). \" +\n \"For a recursive spawn it can only lower the inherited quota.\"\n ),\n }),\n ])\n )\n .optional()\n .describe(\n \"Make this child a SCOPED orchestrator — auto-mount the daemon's own \" +\n \"orchestration MCP tools (start/prompt/wait/poll/output + subtree \" +\n \"list/kill) so it can spawn and supervise its OWN sub-agents. \" +\n \"`true` = the default curated subset; `{ tools: [...] }` narrows it. \" +\n \"The daemon mints a per-child scope-token, injects the scoped \" +\n \"sub-gateway URL into the child's session (alongside any `mcpServers` \" +\n \"you pass), and revokes the token when the session exits. Shell/fs/\" +\n \"remote/import/terminal tools are NEVER exposed this way.\"\n ),\n notifyUrl: z\n .string()\n .url()\n .optional()\n .describe(\n \"Optional per-session webhook URL. POSTed (fire-and-forget) on this \" +\n \"session's turn-end / awaiting-input / exited events, in addition to \" +\n \"any global notify URL.\"\n ),\n wait: mcpBool\n .optional()\n .describe(\n \"Block until the spawned session's first turn completes and include the cleaned output in the response. Default false = return the descriptor immediately.\"\n ),\n maxCostUsd: mcpPositiveNumber\n .optional()\n .describe(\n \"Hard ceiling on cumulative session cost (USD). The session is stopped at a turn-end once exceeded.\"\n ),\n },\n async input => {\n if (!resolveAgentAdapter) {\n return {\n content: [\n {\n type: \"text\",\n text:\n \"start_agent_session is not enabled — the daemon was started without \" +\n \"an adapter resolver. Re-run the daemon with the `@agentproto/cli` \" +\n \"shim wired (see playground/scripts/gateway.ts).\",\n },\n ],\n isError: true,\n }\n }\n // cwd resolution mirrors the HTTP route: explicit cwd wins,\n // then workspaceSlug lookup, then active workspace, then a\n // hard error (the operator probably forgot a step).\n let cwd = input.cwd\n let resolvedSlug = input.workspaceSlug ?? \"default\"\n if (!cwd) {\n try {\n const config = await loadWorkspacesConfig()\n const ws = input.workspaceSlug\n ? findWorkspace(config, input.workspaceSlug)\n : getActiveWorkspace(config)\n if (ws) {\n cwd = ws.path\n resolvedSlug = ws.slug\n }\n } catch {\n // fall through to error below\n }\n }\n if (!cwd) {\n return {\n content: [\n {\n type: \"text\",\n text:\n \"start_agent_session: no cwd resolvable. Pass `cwd` explicitly, \" +\n \"or pass `workspaceSlug` matching `agentproto workspace list`, \" +\n \"or set an active workspace via `agentproto workspace use <slug>`.\",\n },\n ],\n isError: true,\n }\n }\n const resolved = await resolveAgentAdapter(input.adapter)\n if (!resolved) {\n return {\n content: [\n {\n type: \"text\",\n text: `start_agent_session: adapter \"${input.adapter}\" not found. Try \\`agentproto install <slug>\\` first.`,\n },\n ],\n isError: true,\n }\n }\n // ── Recursion guardrails (WP4) ──────────────────────────────\n // When this call arrives through the scoped sub-gateway,\n // `callerScope` is the spawning orchestrator's identity. Enforce\n // the depth cap and per-parent child quota BEFORE spawning, and\n // compute the new session's parent attribution. A direct `/mcp`\n // spawn (no callerScope) is a root: depth 0, no parent, no caps.\n const childDepth = callerScope ? callerScope.depth + 1 : 0\n const parentSessionId = callerScope?.ownerSessionId\n if (callerScope) {\n if (childDepth > callerScope.maxDepth) {\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(\n {\n error: \"orchestrator_max_depth_exceeded\",\n message:\n `Spawn rejected: this orchestrator is at depth ${callerScope.depth}; ` +\n `a child would be depth ${childDepth}, exceeding the max depth ` +\n `${callerScope.maxDepth}. No session was created.`,\n depth: callerScope.depth,\n childDepth,\n maxDepth: callerScope.maxDepth,\n },\n null,\n 2,\n ),\n },\n ],\n isError: true,\n }\n }\n // Count this orchestrator's currently-alive children. Killed/\n // exited children free a slot (the cap bounds concurrent load,\n // not lifetime spawns).\n const aliveChildren = parentSessionId\n ? registry.list().filter(\n s =>\n s.parentSessionId === parentSessionId &&\n (s.status === \"running\" || s.status === \"starting\"),\n ).length\n : 0\n if (aliveChildren >= callerScope.maxChildren) {\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(\n {\n error: \"orchestrator_child_quota_exceeded\",\n message:\n `Spawn rejected: this orchestrator already has ${aliveChildren} ` +\n `alive children, at the max of ${callerScope.maxChildren}. ` +\n `Kill one before spawning another. No session was created.`,\n aliveChildren,\n maxChildren: callerScope.maxChildren,\n },\n null,\n 2,\n ),\n },\n ],\n isError: true,\n }\n }\n }\n // Orchestrator role (WP3): when requested, mint a scoped\n // sub-gateway token and MERGE its `mcpServers` entry with any\n // caller-provided ones (WP1) — both coexist on the child's\n // session. The child thus receives the curated orchestration\n // toolset and can spawn + supervise its own sub-agents. The\n // token is revoked when the session exits (bindLifecycle below).\n // When the spawn is itself recursive (callerScope present), the\n // child's token inherits depth+1 and is bounded by the caller's\n // tools (non-re-grant — a child can't widen past its parent).\n let mcpServers = input.mcpServers\n let bindOrchestratorLifecycle:\n | ((sessionId: string) => () => void)\n | undefined\n if (input.orchestrator !== undefined && input.orchestrator !== false) {\n if (!buildOrchestratorMcp) {\n return {\n content: [\n {\n type: \"text\",\n text:\n \"start_agent_session: `orchestrator` is not enabled — the daemon \" +\n \"was started without the scoped orchestrator sub-gateway. Wire \" +\n \"`buildOrchestratorMcp` in createGateway (it needs the scope-token \" +\n \"registry + HTTP port + session-event bus).\",\n },\n ],\n isError: true,\n }\n }\n const orchestratorOpts =\n typeof input.orchestrator === \"object\"\n ? input.orchestrator\n : undefined\n const requestedTools = orchestratorOpts?.tools\n const injection = buildOrchestratorMcp({\n ...(requestedTools ? { tools: requestedTools } : {}),\n ...(callerScope ? { caller: callerScope } : {}),\n ...(orchestratorOpts?.maxDepth !== undefined\n ? { maxDepth: orchestratorOpts.maxDepth }\n : {}),\n ...(orchestratorOpts?.maxChildren !== undefined\n ? { maxChildren: orchestratorOpts.maxChildren }\n : {}),\n })\n mcpServers = [...(input.mcpServers ?? []), injection.entry]\n bindOrchestratorLifecycle = injection.bindLifecycle\n }\n try {\n const agentSession = await resolved.startSession({\n cwd,\n ...(input.model ? { model: input.model } : {}),\n ...(input.effort ? { effort: input.effort } : {}),\n ...(mcpServers ? { mcpServers } : {}),\n })\n const desc = registry.spawnAgent({\n workspaceSlug: resolvedSlug,\n cwd,\n agentSession,\n adapterSlug: input.adapter,\n ...(input.model ? { model: input.model } : {}),\n ...(input.wait && input.prompt ? {} : input.prompt ? { initialPrompt: input.prompt } : {}),\n ...(input.label ? { label: input.label } : {}),\n ...(mcpServers ? { mcpServers } : {}),\n // Parent attribution + depth (WP4) — only set for spawns that\n // arrived via the scoped sub-gateway; root spawns stay\n // parentless at depth 0.\n ...(parentSessionId ? { parentSessionId } : {}),\n depth: childDepth,\n ...(resolved.commandPreview\n ? { commandPreview: resolved.commandPreview }\n : {}),\n ...(input.maxCostUsd !== undefined ? { maxCostUsd: input.maxCostUsd } : {}),\n ...(resolved.readUsage ? { readUsage: () => resolved.readUsage!(agentSession.sessionId) } : {}),\n })\n // Bind the scope-token's lifetime to the child session — once\n // it exits, the token is revoked so it can't outlive its child.\n bindOrchestratorLifecycle?.(desc.id)\n // Per-session webhook: register if notifyUrl was supplied and\n // the notifier is wired. Unregistered on session:exited by the\n // gateway's session-event bus handler.\n if (input.notifyUrl && webhookNotifier) {\n webhookNotifier.register(desc.id, input.notifyUrl)\n }\n // wait mode: block until the first turn completes, then return\n // the descriptor with cleaned output appended.\n if (input.wait && input.prompt) {\n await registry.sendPrompt(desc.id, input.prompt)\n const waitLines: string[] = []\n const waitUnsub = registry.attach(desc.id, (line: string) => {\n waitLines.push(line)\n })\n if (waitUnsub) waitUnsub()\n const waitTail = waitLines.slice(-80)\n const output = cleanAgentLines(waitTail)\n return {\n content: [\n { type: \"text\", text: JSON.stringify({ ...desc, output }, null, 2) },\n ],\n }\n }\n return {\n content: [{ type: \"text\", text: JSON.stringify(desc, null, 2) }],\n }\n } catch (err) {\n return {\n content: [\n {\n type: \"text\",\n text: `start_agent_session: spawn failed — ${\n err instanceof Error ? err.message : String(err)\n }`,\n },\n ],\n isError: true,\n }\n }\n }\n )\n\n // ── prompt_agent_session ───────────────────────────────────────\n server.tool(\n \"prompt_agent_session\",\n \"Send a follow-up prompt to a live agent session — multi-turn continuity \" +\n \"without re-spawning. The session id comes from `start_agent_session` \" +\n \"(or `list_agent_sessions`). Returns immediately; tail output via \" +\n \"`get_agent_session_output` or the SSE /sessions/:id/stream endpoint.\",\n {\n sessionId: z.string().describe(\"Session id returned by start_agent_session.\"),\n prompt: z.string().min(1).describe(\"The next user turn (plain text).\"),\n },\n async input => {\n try {\n // Note: sendPrompt awaits the full turn (drains the event\n // stream into the ring buffer). For long turns the operator\n // would prefer fire-and-forget — kick the promise without\n // awaiting and report \"queued\". The caller polls\n // get_agent_session_output for completion.\n void registry.sendPrompt(input.sessionId, input.prompt).catch(() => {\n // Errors land in the ring buffer; nothing to do here.\n })\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(\n { ok: true, sessionId: input.sessionId, queued: true },\n null,\n 2\n ),\n },\n ],\n }\n } catch (err) {\n return {\n content: [\n {\n type: \"text\",\n text: `prompt_agent_session: ${err instanceof Error ? err.message : String(err)}`,\n },\n ],\n isError: true,\n }\n }\n }\n )\n\n // ── list_sessions (canonical lister) ──────────────────────────\n server.tool(\n \"list_sessions\",\n \"List sessions tracked by the daemon — agent-CLI sessions (claude-code, \" +\n \"hermes, …), terminal/PTY sessions (claude TUI, bash, …), and raw \" +\n \"commands. Each entry includes `kind`, `pty` (true for real PTYs), \" +\n \"`name` (when set at spawn), `status`, `command`, age + exit code. Use \" +\n \"this when you need to know what's already running before spawning \" +\n \"anything new, or to discover a session id by name.\",\n {\n kind: z\n .enum([\"terminal\", \"agent-cli\", \"command\", \"all\"])\n .optional()\n .describe(\n \"Filter by session kind. `all` (default) returns every kind. \" +\n \"Use `terminal` to list only PTY sessions, `agent-cli` for \" +\n \"structured ACP agents.\",\n ),\n onlyAlive: z\n .boolean()\n .optional()\n .describe(\"When true, only running/starting sessions. Default false.\"),\n status: z\n .enum([\"starting\", \"running\", \"exited\", \"killed\", \"error\"])\n .optional()\n .describe(\"Filter by exact status (overrides onlyAlive).\"),\n },\n async input => {\n let rows = registry.list()\n // Subtree scoping (WP4): on the scoped sub-gateway a child\n // orchestrator only sees the sessions in its own subtree, never\n // the whole daemon.\n if (callerScope) {\n const subtree = collectSubtree(callerScope.ownerSessionId, rows)\n rows = rows.filter(s => subtree.has(s.id))\n }\n if (input.kind && input.kind !== \"all\") {\n rows = rows.filter(s => s.kind === input.kind)\n }\n if (input.status) {\n rows = rows.filter(s => s.status === input.status)\n } else if (input.onlyAlive) {\n rows = rows.filter(\n s => s.status === \"running\" || s.status === \"starting\",\n )\n }\n return {\n content: [\n { type: \"text\", text: JSON.stringify({ sessions: rows }, null, 2) },\n ],\n }\n },\n )\n\n // ── list_agent_sessions (kept for backwards compatibility) ─────\n server.tool(\n \"list_agent_sessions\",\n \"DEPRECATED — prefer `list_sessions` which returns ALL kinds + filters. \" +\n \"Despite the name this tool already returns every kind, not just \" +\n \"agent-cli sessions; the new tool's name reflects the actual surface.\",\n {\n onlyAlive: z\n .boolean()\n .optional()\n .describe(\"Filter to status running/starting only. Default false.\"),\n },\n async input => {\n let all = registry.list()\n // Subtree scoping (WP4) — same as list_sessions.\n if (callerScope) {\n const subtree = collectSubtree(callerScope.ownerSessionId, all)\n all = all.filter(s => subtree.has(s.id))\n }\n const filtered = input.onlyAlive\n ? all.filter(s => s.status === \"running\" || s.status === \"starting\")\n : all\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify({ sessions: filtered }, null, 2),\n },\n ],\n }\n }\n )\n\n // ── get_agent_session_output ───────────────────────────────────\n server.tool(\n \"get_agent_session_output\",\n \"Tail the recent output of a session. Returns the last N lines of the \" +\n \"ring buffer (stdout + stderr inter-leaved, newest last). Use this to read \" +\n \"an agent's reply after `prompt_agent_session`.\",\n {\n sessionId: z.string().describe(\"Session id.\"),\n lastN: z\n .number()\n .int()\n .min(1)\n .max(500)\n .optional()\n .describe(\"Max lines to return. Default 80, max 500.\"),\n clean: mcpBool\n .optional()\n .describe(\n \"Strip ANSI codes and drop framing/decoration lines, returning human-readable text.\"\n ),\n },\n async input => {\n const desc = registry.get(input.sessionId)\n if (!desc) {\n return {\n content: [\n { type: \"text\", text: `get_agent_session_output: no session \"${input.sessionId}\"` },\n ],\n isError: true,\n }\n }\n // Best-effort tail — re-attach with a temp listener, capture\n // backfill (which is the recent ring buffer), unsubscribe.\n const limit = input.lastN ?? 80\n const lines: string[] = []\n const unsub = registry.attach(input.sessionId, (line, _stream) => {\n lines.push(line)\n })\n if (unsub) unsub()\n const tail = lines.slice(-limit)\n const output = input.clean ? cleanAgentLines(tail) : tail\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(\n {\n sessionId: input.sessionId,\n status: desc.status,\n lastOutputAt: desc.lastOutputAt,\n lines: output,\n },\n null,\n 2\n ),\n },\n ],\n }\n }\n )\n\n // ── list_adapters ──────────────────────────────────────────────\n server.tool(\n \"list_adapters\",\n \"Enumerate every agent CLI adapter installed on the host (claude-code, \" +\n \"hermes, aider, …). Returns slug + display name + version + protocol so \" +\n \"callers can let users pick from the installed set instead of guessing. \" +\n \"Use before `start_agent_session` when the model doesn't already know \" +\n \"what's available.\",\n {},\n async () => {\n if (!listAgentAdapters) {\n return {\n content: [\n {\n type: \"text\",\n text:\n \"list_adapters is not enabled — the daemon was started without \" +\n \"an adapter lister. Wire `@agentproto/cli`'s \" +\n \"`listInstalledAdapters` via `createGateway({ listAgentAdapters })`.\",\n },\n ],\n isError: true,\n }\n }\n try {\n const adapters = await listAgentAdapters()\n return {\n content: [{ type: \"text\", text: JSON.stringify({ adapters }, null, 2) }],\n }\n } catch (err) {\n return {\n content: [\n {\n type: \"text\",\n text: `list_adapters failed: ${err instanceof Error ? err.message : String(err)}`,\n },\n ],\n isError: true,\n }\n }\n }\n )\n\n // ── list_discovered_mcps ───────────────────────────────────────\n server.tool(\n \"list_discovered_mcps\",\n \"Discover MCP servers already configured in the user's other agent \" +\n \"tooling (claude-code, cursor, goose). Returns the union with source \" +\n \"attribution so the operator can suggest 'I see you have a chrome-devtools \" +\n \"MCP set up in claude — want me to use it?' instead of asking the user \" +\n \"to re-configure. Read-only — does not modify any host's config.\",\n {},\n async () => {\n try {\n const mcps = await discoverMcps()\n return {\n content: [{ type: \"text\", text: JSON.stringify({ mcps }, null, 2) }],\n }\n } catch (err) {\n return {\n content: [\n {\n type: \"text\",\n text: `list_discovered_mcps failed: ${err instanceof Error ? err.message : String(err)}`,\n },\n ],\n isError: true,\n }\n }\n }\n )\n\n // ── list_imported_mcps ─────────────────────────────────────────\n server.tool(\n \"list_imported_mcps\",\n \"Return the user's curated set of MCP servers — the ones they've \" +\n \"imported from claude / cursor / workspace configs into the daemon. \" +\n \"Use to know which MCPs the operator may freely call vs. ones still \" +\n \"showing up in `list_discovered_mcps` waiting on the user's blessing.\",\n {},\n async () => {\n try {\n const config = await loadImportedMcps()\n return {\n content: [\n { type: \"text\", text: JSON.stringify(config, null, 2) },\n ],\n }\n } catch (err) {\n return {\n content: [\n {\n type: \"text\",\n text: `list_imported_mcps failed: ${err instanceof Error ? err.message : String(err)}`,\n },\n ],\n isError: true,\n }\n }\n }\n )\n\n // ── import_mcp ─────────────────────────────────────────────────\n server.tool(\n \"import_mcp\",\n \"Import a discovered MCP into the daemon's curated set. The agent \" +\n \"calls `list_discovered_mcps` first, asks the user, then commits the \" +\n \"choice via this tool. The snapshot is captured at import time so \" +\n \"the entry stays usable if the source config (claude/cursor) is \" +\n \"later removed.\",\n {\n sourceMcpId: z\n .string()\n .min(1)\n .describe(\n \"The discovered MCP id from `list_discovered_mcps` \" +\n \"(e.g. 'claude-code:project:/path:chrome-devtools').\"\n ),\n alias: z\n .string()\n .optional()\n .describe(\n \"Optional friendly name to display. Defaults to the source MCP's name.\"\n ),\n },\n async input => {\n try {\n const discovered = await discoverMcps()\n const snapshot = discovered.find(d => d.id === input.sourceMcpId)\n if (!snapshot) {\n return {\n content: [\n {\n type: \"text\",\n text: `import_mcp: discovered MCP \"${input.sourceMcpId}\" not found. Re-run list_discovered_mcps to get current ids.`,\n },\n ],\n isError: true,\n }\n }\n const cfg = await loadImportedMcps()\n const next = addImport(cfg, {\n snapshot,\n ...(input.alias ? { alias: input.alias } : {}),\n })\n await saveImportedMcps(next)\n const entry = next.imports.find(e => e.id === snapshot.id)\n return {\n content: [{ type: \"text\", text: JSON.stringify(entry, null, 2) }],\n }\n } catch (err) {\n return {\n content: [\n {\n type: \"text\",\n text: `import_mcp failed: ${err instanceof Error ? err.message : String(err)}`,\n },\n ],\n isError: true,\n }\n }\n }\n )\n\n // ── remove_imported_mcp ────────────────────────────────────────\n server.tool(\n \"remove_imported_mcp\",\n \"Remove a previously-imported MCP from the daemon's curated set. \" +\n \"Use when the user no longer wants the operator referencing it.\",\n {\n id: z\n .string()\n .min(1)\n .describe(\n \"The imported MCP id (matches the discovered MCP id at import time).\"\n ),\n },\n async input => {\n try {\n const cfg = await loadImportedMcps()\n if (!cfg.imports.some(e => e.id === input.id)) {\n return {\n content: [\n {\n type: \"text\",\n text: `remove_imported_mcp: id \"${input.id}\" not in imports. Use list_imported_mcps to see current entries.`,\n },\n ],\n isError: true,\n }\n }\n await saveImportedMcps(removeImport(cfg, input.id))\n return {\n content: [\n { type: \"text\", text: JSON.stringify({ ok: true, id: input.id }, null, 2) },\n ],\n }\n } catch (err) {\n return {\n content: [\n {\n type: \"text\",\n text: `remove_imported_mcp failed: ${err instanceof Error ? err.message : String(err)}`,\n },\n ],\n isError: true,\n }\n }\n }\n )\n\n // ── mcp_imported_status ────────────────────────────────────────\n // The 3 proxy tools share the same wiring guard — register them\n // only when the host injected a proxy registry, otherwise emit a\n // clear \"not enabled\" error so the agent doesn't think the daemon\n // silently dropped the call.\n server.tool(\n \"mcp_imported_status\",\n \"Snapshot every imported MCP server with its connection status, \" +\n \"transport type, and tool count. Use this first when an operator \" +\n \"wonders 'what MCPs do I actually have access to right now?' — the \" +\n \"answer covers both 'imported but not yet connected' and 'connected \" +\n \"with N tools'. Errors during connect surface in `lastError`.\",\n {},\n async () => {\n if (!mcpProxy) {\n return {\n content: [\n {\n type: \"text\",\n text:\n \"mcp_imported_status is not enabled — daemon was started without \" +\n \"an MCP proxy. The host must wire `mcpProxy` in createGateway.\",\n },\n ],\n isError: true,\n }\n }\n try {\n const aliases = await mcpProxy.listAliases()\n return {\n content: [\n { type: \"text\", text: JSON.stringify({ imports: aliases }, null, 2) },\n ],\n }\n } catch (err) {\n return {\n content: [\n {\n type: \"text\",\n text: `mcp_imported_status failed: ${err instanceof Error ? err.message : String(err)}`,\n },\n ],\n isError: true,\n }\n }\n }\n )\n\n // ── mcp_imported_list_tools ────────────────────────────────────\n server.tool(\n \"mcp_imported_list_tools\",\n \"List the tools exposed by one imported MCP server. The proxy \" +\n \"lazily connects on first call — first-use latency includes the \" +\n \"transport handshake (stdio: ~1-2s for npx-spawned servers; \" +\n \"http/sse: <100ms). Returns the upstream `inputSchema` (JSON \" +\n \"Schema) verbatim so the operator can build a valid `arguments` \" +\n \"object for the follow-up `mcp_imported_call` invocation.\",\n {\n alias: z\n .string()\n .min(1)\n .describe(\n \"Alias from `list_imported_mcps` / `mcp_imported_status` \" +\n \"(typically the original MCP name, e.g. 'chrome-devtools').\"\n ),\n },\n async input => {\n if (!mcpProxy) {\n return {\n content: [\n {\n type: \"text\",\n text: \"mcp_imported_list_tools is not enabled — see mcp_imported_status.\",\n },\n ],\n isError: true,\n }\n }\n const out = await mcpProxy.listTools(input.alias)\n if (!out.ok) {\n return {\n content: [\n {\n type: \"text\",\n text: `mcp_imported_list_tools \"${input.alias}\": ${out.error}`,\n },\n ],\n isError: true,\n }\n }\n return {\n content: [\n { type: \"text\", text: JSON.stringify({ alias: input.alias, tools: out.tools }, null, 2) },\n ],\n }\n }\n )\n\n // ── mcp_imported_call ──────────────────────────────────────────\n server.tool(\n \"mcp_imported_call\",\n \"Invoke a tool on an imported MCP server. The daemon proxies the \" +\n \"call through the live client connection — the upstream server \" +\n \"validates `arguments` against its own input schema (which you \" +\n \"can fetch via `mcp_imported_list_tools`). The full upstream \" +\n \"result is returned verbatim, including `isError` flags so the \" +\n \"operator sees the original failure shape.\",\n {\n alias: z.string().min(1).describe(\"Imported MCP alias.\"),\n toolName: z\n .string()\n .min(1)\n .describe(\n \"Tool name as it appears in `mcp_imported_list_tools` \" +\n \"(NOT a namespaced version — pass the upstream's own name).\"\n ),\n args: z\n .record(z.string(), z.unknown())\n .optional()\n .describe(\n \"Tool arguments as a JSON object. Schema is the upstream's \" +\n \"— the proxy doesn't validate, only forwards. Default: empty object.\"\n ),\n },\n async input => {\n if (!mcpProxy) {\n return {\n content: [\n {\n type: \"text\",\n text: \"mcp_imported_call is not enabled — see mcp_imported_status.\",\n },\n ],\n isError: true,\n }\n }\n const out = await mcpProxy.callTool(\n input.alias,\n input.toolName,\n input.args ?? {}\n )\n if (!out.ok) {\n return {\n content: [\n {\n type: \"text\",\n text: `mcp_imported_call \"${input.alias}\".${input.toolName}: ${out.error}`,\n },\n ],\n isError: true,\n }\n }\n // Forward the upstream result. The MCP SDK's CallToolResult is\n // already in the {content, isError?} shape we return — pass it\n // through with a note that it came from the proxy.\n return out.result as {\n content: Array<{ type: \"text\"; text: string }>\n isError?: boolean\n }\n }\n )\n\n // ── session_tree (WP5) ────────────────────────────────────────\n server.tool(\n \"session_tree\",\n \"Return the orchestrator session hierarchy as a nested tree. Each root \" +\n \"is a session with no parent (or whose parent is outside the visible scope); \" +\n \"its `children` array holds direct sub-sessions, recursively. Each node \" +\n \"carries `id`, `label`, `status`, `depth`, `adapterSlug`, `parentSessionId`, \" +\n \"and `isOrchestrator` (true when the session itself spawned sub-agents). \" +\n \"Via a scoped orchestrator token only the caller's subtree is returned; \" +\n \"from the root `/mcp` endpoint the full daemon tree is visible.\",\n {\n onlyAlive: z\n .boolean()\n .optional()\n .describe(\n \"When true, only include sessions with status running/starting. \" +\n \"Pruned nodes also hide their subtree. Default false.\",\n ),\n },\n async input => {\n let rows = registry.list()\n // Subtree scoping (WP5 / WP4): same gate as list_sessions.\n if (callerScope) {\n const subtree = collectSubtree(callerScope.ownerSessionId, rows)\n rows = rows.filter(s => subtree.has(s.id))\n }\n if (input.onlyAlive) {\n rows = rows.filter(\n s => s.status === \"running\" || s.status === \"starting\",\n )\n }\n const tree = buildSessionTree(rows)\n return {\n content: [\n { type: \"text\", text: JSON.stringify({ tree }, null, 2) },\n ],\n }\n },\n )\n\n // ── kill_agent_session ─────────────────────────────────────────\n server.tool(\n \"kill_agent_session\",\n \"Stop a session — SIGTERM the underlying child + close the agent protocol \" +\n \"session. Use to free resources after the operator is done, or when a \" +\n \"session is wedged.\",\n {\n sessionId: z.string().describe(\"Session id.\"),\n },\n async input => {\n // Subtree scoping (WP4): on the scoped sub-gateway a child\n // orchestrator may only kill sessions in its own subtree — never\n // an arbitrary id (e.g. a sibling's, or the root operator's).\n if (callerScope) {\n const subtree = collectSubtree(\n callerScope.ownerSessionId,\n registry.list(),\n )\n if (!subtree.has(input.sessionId)) {\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(\n {\n error: \"orchestrator_session_out_of_scope\",\n message:\n `kill_agent_session: session \"${input.sessionId}\" is not in ` +\n `your subtree — a scoped orchestrator can only kill sessions ` +\n `it (transitively) spawned. No action taken.`,\n ok: false,\n sessionId: input.sessionId,\n },\n null,\n 2,\n ),\n },\n ],\n isError: true,\n }\n }\n }\n const ok = registry.kill(input.sessionId)\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify({ ok, sessionId: input.sessionId }, null, 2),\n },\n ],\n }\n }\n )\n\n // ── Terminal session tools ─────────────────────────────────────\n // Four tools that mirror the agent-session set but operate on raw\n // PTY sessions (real terminal, ANSI bytes, multi-subscriber). Use\n // these to drive interactive CLIs like `claude` in TUI mode, or\n // for one agent to orchestrate other shells. Read/write/exit\n // happen over the byte ring buffer; the WS at /sessions/:id/pty\n // is the streaming alternative.\n\n const ptyNotConfigured = (toolName: string): {\n content: Array<{ type: \"text\"; text: string }>\n isError: true\n } => ({\n content: [\n {\n type: \"text\",\n text:\n `${toolName}: PTY support not enabled — the daemon was started without ` +\n \"a node-pty factory. Re-run `agentproto serve` from a build that ships \" +\n \"node-pty (the optional dep ships with @agentproto/cli).\",\n },\n ],\n isError: true,\n })\n\n server.tool(\n \"start_terminal_session\",\n \"Spawn a process under a real PTY (node-pty) on the host. Bytes (including \" +\n \"ANSI escapes, alt-screen sequences) flow through the daemon's byte ring \" +\n \"buffer; subscribers attach via the WS at /sessions/:id/pty. Use for \" +\n \"interactive TUIs (claude, vim, htop) or to orchestrate shells from another \" +\n \"agent. Returns the session descriptor.\",\n {\n argv: z\n .array(z.string())\n .min(1)\n .describe(\n \"Argv array. First element is the binary, rest are arguments. \" +\n \"e.g. ['claude'] or ['bash', '-l'].\"\n ),\n workspaceSlug: z\n .string()\n .optional()\n .describe(\n \"Workspace slug from `agentproto workspace list`. Resolves cwd. Omit \" +\n \"to use `cwd` explicitly or the active workspace.\"\n ),\n cwd: z\n .string()\n .optional()\n .describe(\"Absolute cwd. Wins over workspaceSlug when both set.\"),\n cols: z.number().int().min(1).max(500).optional().describe(\"Initial cols. Default 80.\"),\n rows: z.number().int().min(1).max(200).optional().describe(\"Initial rows. Default 24.\"),\n name: z\n .string()\n .optional()\n .describe(\n \"User-friendly slug. Becomes an alias for the session id in \" +\n \"subsequent tool calls (read/write/kill accept either).\"\n ),\n label: z\n .string()\n .optional()\n .describe(\n \"Free-text label surfaced in list_agent_sessions and the UI.\"\n ),\n },\n async input => {\n if (!ptyEnabled) return ptyNotConfigured(\"start_terminal_session\")\n let cwd = input.cwd\n let resolvedSlug = input.workspaceSlug ?? \"default\"\n if (!cwd) {\n try {\n const config = await loadWorkspacesConfig()\n const ws = input.workspaceSlug\n ? findWorkspace(config, input.workspaceSlug)\n : getActiveWorkspace(config)\n if (ws) {\n cwd = ws.path\n resolvedSlug = ws.slug\n }\n } catch {\n // fall through to error\n }\n }\n if (!cwd) {\n return {\n content: [\n {\n type: \"text\",\n text:\n \"start_terminal_session: no cwd resolvable. Pass `cwd` explicitly \" +\n \"or `workspaceSlug` matching `agentproto workspace list`.\",\n },\n ],\n isError: true,\n }\n }\n try {\n const desc = registry.spawnPty({\n argv: input.argv,\n cwd,\n workspaceSlug: resolvedSlug,\n cols: input.cols ?? 80,\n rows: input.rows ?? 24,\n ...(input.name ? { name: input.name } : {}),\n ...(input.label ? { label: input.label } : {}),\n })\n return {\n content: [{ type: \"text\", text: JSON.stringify(desc, null, 2) }],\n }\n } catch (err) {\n return {\n content: [\n {\n type: \"text\",\n text: `start_terminal_session: ${err instanceof Error ? err.message : String(err)}`,\n },\n ],\n isError: true,\n }\n }\n }\n )\n\n server.tool(\n \"write_terminal_input\",\n \"Send keystrokes to a PTY session's stdin. The text is forwarded verbatim — \" +\n \"include trailing newlines if the target needs them (e.g. shell commands). \" +\n \"Use after `start_terminal_session` to drive an interactive CLI.\",\n {\n sessionId: z\n .string()\n .describe(\"Session id OR name from start_terminal_session.\"),\n text: z.string().describe(\"Text to write. Sent as-is to the PTY's stdin.\"),\n },\n async input => {\n if (!ptyEnabled) return ptyNotConfigured(\"write_terminal_input\")\n const desc = registry.findByIdOrName(input.sessionId)\n if (!desc) {\n return {\n content: [\n {\n type: \"text\",\n text: `write_terminal_input: no session \"${input.sessionId}\"`,\n },\n ],\n isError: true,\n }\n }\n const ok = registry.writeTerminalInput(desc.id, input.text)\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify({ ok, sessionId: desc.id }, null, 2),\n },\n ],\n ...(ok ? {} : { isError: true as const }),\n }\n }\n )\n\n server.tool(\n \"read_terminal_output\",\n \"Snapshot the recent byte buffer of a PTY session. Returns base64-encoded \" +\n \"bytes (the buffer is RAW including ANSI escapes — strip with a regex if \" +\n \"you want plain text). `lastBytes` caps the read from the tail.\",\n {\n sessionId: z\n .string()\n .describe(\"Session id OR name from start_terminal_session.\"),\n lastBytes: z\n .number()\n .int()\n .min(1)\n .max(64 * 1024)\n .optional()\n .describe(\"Max bytes from the tail. Default: full ring buffer (~64 KiB).\"),\n },\n async input => {\n if (!ptyEnabled) return ptyNotConfigured(\"read_terminal_output\")\n const desc = registry.findByIdOrName(input.sessionId)\n if (!desc) {\n return {\n content: [\n {\n type: \"text\",\n text: `read_terminal_output: no session \"${input.sessionId}\"`,\n },\n ],\n isError: true,\n }\n }\n const buf = registry.readTerminalOutput(\n desc.id,\n input.lastBytes,\n )\n if (!buf) {\n return {\n content: [\n {\n type: \"text\",\n text: `read_terminal_output: session \"${desc.id}\" is not a PTY`,\n },\n ],\n isError: true,\n }\n }\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(\n {\n sessionId: desc.id,\n status: desc.status,\n bytes: buf.byteLength,\n b64: buf.toString(\"base64\"),\n },\n null,\n 2,\n ),\n },\n ],\n }\n }\n )\n\n server.tool(\n \"kill_terminal_session\",\n \"SIGTERM a PTY session and drop it from the alive set. Same effect as \" +\n \"`kill_agent_session` for the PTY family — separate name so it's obvious \" +\n \"what's being stopped.\",\n {\n sessionId: z\n .string()\n .describe(\"Session id OR name from start_terminal_session.\"),\n },\n async input => {\n if (!ptyEnabled) return ptyNotConfigured(\"kill_terminal_session\")\n const desc = registry.findByIdOrName(input.sessionId)\n if (!desc) {\n return {\n content: [\n {\n type: \"text\",\n text: `kill_terminal_session: no session \"${input.sessionId}\"`,\n },\n ],\n isError: true,\n }\n }\n const ok = registry.kill(desc.id)\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify({ ok, sessionId: desc.id }, null, 2),\n },\n ],\n }\n }\n )\n}\n\n// ── export_agent_session tool ─────────────────────────────────────────────────\n\nexport interface ExportSessionOps {\n registry: SessionsRegistry\n /**\n * Override the export function — primarily for testing so callers can inject\n * a stub without needing real JSONL / SQLite fixtures.\n */\n exportFn?: (input: ExportAgentSessionInput) => Promise<ExportAgentSessionResult>\n}\n\n/**\n * Register the `export_agent_session` MCP tool.\n *\n * Wraps `exportAgentSession` from transcript-export.ts. Resolves the session\n * descriptor via the registry (same registry-access pattern as `summarize_session`)\n * then delegates to the per-adapter exporter (claude-code JSONL / hermes SQLite).\n * Returns the rendered transcript as a text content block.\n */\nexport function registerExportSessionTool(server: McpServer, ops: ExportSessionOps): void {\n const doExport = ops.exportFn ?? exportAgentSession\n server.tool(\n \"export_agent_session\",\n \"Export a clean, human-readable transcript of an agent session. \" +\n \"Reads the source the adapter already persists (claude-code: JSONL in \" +\n \"~/.claude/projects/; hermes: state.db in ~/.hermes/). Returns markdown \" +\n \"(default) or JSON. Works on stopped and running sessions alike. Use \" +\n \"after a long agent run to review the full conversation without the \" +\n \"ANSI noise of the ring buffer.\",\n {\n sessionId: z.string().describe(\n \"agentproto session id (sess_xxx), adapter-native id, or session name.\"\n ),\n adapter: z.string().optional().describe(\n \"Override adapter slug (e.g. 'claude-code', 'hermes') when the session \" +\n \"is not in the registry. Required when passing a raw adapter-native id.\"\n ),\n cwd: z.string().optional().describe(\n \"Override cwd (absolute path) — required for claude-code when the session \" +\n \"is not in the registry (used to locate the JSONL file).\"\n ),\n format: z.enum([\"markdown\", \"json\"]).optional().describe(\n \"Output format. `markdown` (default) renders a human-friendly transcript \" +\n \"with a metadata table and role-labelled messages; `json` returns the raw \" +\n \"ExportedSession object for programmatic processing.\"\n ),\n },\n async input => {\n const result = await doExport({\n sessionId: input.sessionId,\n registry: ops.registry,\n ...(input.adapter ? { adapter: input.adapter } : {}),\n ...(input.cwd ? { cwd: input.cwd } : {}),\n ...(input.format ? { format: input.format } : {}),\n })\n const isError = result.content.startsWith(\"Error:\")\n return {\n content: [{ type: \"text\" as const, text: result.content }],\n ...(isError ? { isError: true as const } : {}),\n }\n },\n )\n}\n","/**\n * MCP tools that expose browser service adapters (Camofox, Bureau, …) to\n * agents connected to the daemon. Lets a remote operator start, stop, and\n * inspect browser service sessions through the same MCP connection it uses\n * for fs/exec/agent-cli.\n *\n * Five tools:\n * list_adapter_browsers discover available browser adapter ids + metadata\n * start_browser ensure a browser adapter is up, register as a session\n * stop_browser kill a running browser session\n * list_browsers browse alive/recent browser sessions\n * browser_status descriptor + live health probe for one session\n *\n * Auth: same as every other daemon tool — gated by the gateway's auth source.\n *\n * Injection pattern: `resolveBrowserAdapter` is passed in, not imported.\n * This keeps the runtime package free of a hard dep on @agentproto/adapter-browser.\n * The types below are minimal structural shapes — equivalent to `AgentSessionLike`\n * in sessions.ts.\n */\n\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\"\nimport { z } from \"zod\"\nimport type { AdapterLister } from \"@agentproto/adapter-kit\"\nimport type { SessionsRegistry } from \"./sessions.js\"\n\n// ── Minimal structural types (no dep on @agentproto/adapter-browser) ──────────\n\n/**\n * Minimal shape of a BrowserAdapterInstance — structurally compatible with\n * @agentproto/adapter-browser's BrowserAdapterInstance. Kept local so the\n * runtime package stays free of a hard dependency on the adapter package.\n */\ninterface BrowserInstanceLike {\n id: string\n port: number\n baseUrl: string\n pid?: number\n wasAlreadyRunning: boolean\n /** False when a non-blocking cold start returned before the service\n * finished converging (background health-wait still running). */\n healthy: boolean\n stop(): Promise<void>\n}\n\n/**\n * Minimal shape of a BrowserAdapterHandle — structurally compatible with\n * @agentproto/adapter-browser's BrowserAdapterHandle.\n */\ninterface BrowserAdapterLike {\n id: string\n name: string\n description: string\n defaultPort: number\n healthPath: string\n /** Where this adapter runs — \"local\" (default) or \"cloud\". */\n location?: \"local\" | \"cloud\"\n ensure(opts: {\n port?: number\n /** forwarded to dependent adapters (e.g. bureau→camofox) */\n camofoxPort?: number\n launchCmd?: string\n env?: Record<string, string>\n timeoutMs?: number\n /** Opt-in non-blocking cold start: wait only this long for a freshly\n * spawned service before returning `healthy:false` and converging\n * in the background. */\n initialWaitMs?: number\n log?: (s: string) => void\n /** Override execution location (\"local\" or \"cloud\"). */\n location?: \"local\" | \"cloud\"\n /** Base URL of the remote service when location=\"cloud\". */\n baseUrl?: string\n /** Override the binary path for a local spawn. */\n binPath?: string\n }): Promise<BrowserInstanceLike>\n}\n\n/**\n * Bounded window `start_browser` waits for a freshly-spawned service to become\n * healthy before returning `starting`. Heavy services (chromium, bureau) take\n * >60s to boot (pnpm + Chrome launch) and would otherwise time out the MCP\n * request; we return promptly and let health converge in the background.\n */\nconst START_BROWSER_INITIAL_WAIT_MS = 6_000\n\nexport type BrowserAdapterResolver = (id: string) => BrowserAdapterLike | undefined\nexport type BrowserAdapterLister = () => {\n id: string\n name: string\n description: string\n defaultPort: number\n /** Where this adapter runs — \"local\" (default) or \"cloud\". */\n location?: \"local\" | \"cloud\"\n /** Install methods — informational metadata from the adapter manifest. */\n install?: unknown[]\n /** Config prompts — informational metadata from the adapter manifest. */\n config?: unknown[]\n}[]\n\n/**\n * Family-specific descriptor surfaced in the kit-path `list_adapter_browsers`\n * response. Fields match the legacy lister shape so the tool output is\n * unchanged regardless of which path is active.\n */\nexport interface BrowserAdapterInfo {\n id: string\n name: string\n description: string\n defaultPort: number\n}\n\n// ── Shared result helpers ─────────────────────────────────────────────────────\n\nconst okResult = (r: Record<string, unknown>) => ({\n content: [{ type: \"text\" as const, text: JSON.stringify(r, null, 2) }],\n structuredContent: r,\n})\n\nconst errResult = (text: string) => ({\n content: [{ type: \"text\" as const, text }],\n isError: true as const,\n})\n\n// ── Registration ──────────────────────────────────────────────────────────────\n\ninterface RegisterBrowserToolsOptions {\n registry: SessionsRegistry\n /** Resolver for browser adapters — injected by the serve/CLI layer (P6).\n * Required for `start_browser`; the tool returns a clear error when unset. */\n resolveBrowserAdapter?: BrowserAdapterResolver\n /** Lister for available browser adapters — when unset, `list_adapter_browsers`\n * returns a \"not configured\" message. */\n listBrowserAdapters?: BrowserAdapterLister\n /**\n * Kit-path lister (Phase 3). When provided, `list_adapter_browsers` calls\n * this async lister and extracts `AdapterEntry.info` fields for the response,\n * preserving the existing `{ id, name, description, defaultPort }[]` shape.\n * When absent, the legacy `listBrowserAdapters` path is used.\n */\n lister?: AdapterLister<BrowserAdapterInfo>\n log?: (msg: string) => void\n}\n\nexport function registerBrowserTools(\n server: McpServer,\n opts: RegisterBrowserToolsOptions\n): void {\n const { registry, resolveBrowserAdapter, listBrowserAdapters, lister, log } = opts\n\n // ── list_adapter_browsers ────────────────────────────────────────────────────\n server.tool(\n \"list_adapter_browsers\",\n \"List available browser adapter ids and their metadata (name, description, default port). \" +\n \"Use the `id` field to reference an adapter in `start_browser`.\",\n {},\n async () => {\n // Kit path: async lister supplied — extract info fields to preserve the\n // existing { id, name, description, defaultPort }[] response shape.\n if (lister) {\n const entries = await lister()\n const adapters = entries.flatMap(e => (e.info ? [e.info] : []))\n return {\n content: [{ type: \"text\" as const, text: JSON.stringify(adapters, null, 2) }],\n }\n }\n // Legacy path: synchronous injected lister.\n if (!listBrowserAdapters) {\n return {\n content: [\n {\n type: \"text\" as const,\n text:\n \"list_adapter_browsers is not enabled — the daemon was started without \" +\n \"a browser adapter lister. Re-run with `listBrowserAdapters` wired.\",\n },\n ],\n isError: true,\n }\n }\n const adapters = listBrowserAdapters()\n return {\n content: [{ type: \"text\" as const, text: JSON.stringify(adapters, null, 2) }],\n }\n }\n )\n\n // ── start_browser ────────────────────────────────────────────────────────────\n server.tool(\n \"start_browser\",\n \"Ensure a browser adapter service is running, then register it as a tracked session. \" +\n \"Idempotent: if the service is already healthy, returns wasAlreadyRunning=true without spawning. \" +\n \"Returns the session descriptor (sessionId, browserBaseUrl, …) for subsequent calls.\",\n {\n adapter: z\n .string()\n .min(1)\n .describe(\n \"Browser adapter id — one of the ids returned by `list_adapter_browsers` \" +\n \"(e.g. 'camofox', 'bureau').\"\n ),\n port: z\n .number()\n .int()\n .optional()\n .describe(\"Override the adapter's default port.\"),\n camofoxPort: z\n .number()\n .int()\n .optional()\n .describe(\n \"For adapters that depend on Camofox (e.g. 'bureau'): override the Camofox port (default 9377).\"\n ),\n label: z\n .string()\n .optional()\n .describe(\"Free-text label surfaced in `list_browsers` and the UI.\"),\n location: z\n .enum([\"local\", \"cloud\"])\n .optional()\n .describe(\n \"Override execution location. 'local' spawns the adapter process on this machine (default). \" +\n \"'cloud' health-checks a remote endpoint at `baseUrl` without spawning anything.\"\n ),\n baseUrl: z\n .string()\n .optional()\n .describe(\n \"Base URL of the remote service when location='cloud' \" +\n \"(e.g. 'https://browser-service.example.com'). Required when location='cloud'.\"\n ),\n binPath: z\n .string()\n .optional()\n .describe(\n \"Override the binary path used for the local spawn. \" +\n \"When unset, the adapter resolves its own default binary.\"\n ),\n },\n async input => {\n if (!resolveBrowserAdapter) {\n return {\n content: [\n {\n type: \"text\" as const,\n text:\n \"start_browser is not enabled — the daemon was started without \" +\n \"a browser adapter resolver. Re-run with `resolveBrowserAdapter` wired.\",\n },\n ],\n isError: true,\n }\n }\n const adapter = resolveBrowserAdapter(input.adapter)\n if (!adapter) {\n const available = listBrowserAdapters\n ? listBrowserAdapters()\n .map(a => a.id)\n .join(\", \")\n : \"camofox, bureau\"\n return {\n content: [\n {\n type: \"text\" as const,\n text: `start_browser: adapter \"${input.adapter}\" not found. Available adapters: ${available}.`,\n },\n ],\n isError: true,\n }\n }\n try {\n const instance = await adapter.ensure({\n port: input.port,\n camofoxPort: input.camofoxPort,\n location: input.location,\n baseUrl: input.baseUrl,\n binPath: input.binPath,\n // Non-blocking cold start: if the freshly spawned service isn't\n // healthy within this bounded window, register it as `starting`\n // and let health converge in the background instead of blocking\n // the MCP request until the full health timeout.\n initialWaitMs: START_BROWSER_INITIAL_WAIT_MS,\n log: msg => log?.(`[start_browser:${input.adapter}] ${msg}`),\n })\n const desc = registry.registerBrowser({\n adapterId: instance.id,\n port: instance.port,\n baseUrl: instance.baseUrl,\n location: input.location ?? adapter.location,\n pid: instance.pid,\n wasAlreadyRunning: instance.wasAlreadyRunning,\n status: instance.healthy ? \"running\" : \"starting\",\n stop: instance.stop.bind(instance),\n label: input.label,\n })\n const stillStarting = !instance.healthy\n return {\n content: [\n {\n type: \"text\" as const,\n text: JSON.stringify(\n {\n sessionId: desc.id,\n browserAdapterId: desc.browserAdapterId,\n browserPort: desc.browserPort,\n browserBaseUrl: desc.browserBaseUrl,\n wasAlreadyRunning: instance.wasAlreadyRunning,\n status: desc.status,\n ...(stillStarting\n ? {\n hint:\n `Service is still booting (cold start). It was spawned successfully ` +\n `and is converging to healthy in the background — poll ` +\n `\\`browser_status\\` with sessionId \"${desc.id}\" until status is \"running\".`,\n }\n : {}),\n },\n null,\n 2\n ),\n },\n ],\n }\n } catch (err) {\n return {\n content: [\n {\n type: \"text\" as const,\n text: `start_browser: ${err instanceof Error ? err.message : String(err)}`,\n },\n ],\n isError: true,\n }\n }\n }\n )\n\n // ── stop_browser ─────────────────────────────────────────────────────────────\n server.tool(\n \"stop_browser\",\n \"Stop a browser session registered by `start_browser`. \" +\n \"Calls the adapter's stop() (best-effort SIGTERM) and marks the session as killed.\",\n {\n sessionId: z\n .string()\n .min(1)\n .describe(\"Session id returned by `start_browser` or `list_browsers`.\"),\n },\n async input => {\n const desc = registry.get(input.sessionId)\n if (!desc) {\n return {\n content: [\n {\n type: \"text\" as const,\n text: `stop_browser: session \"${input.sessionId}\" not found.`,\n },\n ],\n isError: true,\n }\n }\n if (desc.kind !== \"browser\") {\n return {\n content: [\n {\n type: \"text\" as const,\n text: `stop_browser: session \"${input.sessionId}\" is not a browser session (kind=${desc.kind}).`,\n },\n ],\n isError: true,\n }\n }\n const ok = registry.kill(input.sessionId)\n return {\n content: [\n {\n type: \"text\" as const,\n text: JSON.stringify({ ok, sessionId: input.sessionId }, null, 2),\n },\n ],\n }\n }\n )\n\n // ── list_browsers ────────────────────────────────────────────────────────────\n server.tool(\n \"list_browsers\",\n \"List browser sessions tracked by the daemon (all or alive-only).\",\n {\n onlyAlive: z\n .boolean()\n .optional()\n .describe(\n \"When true, return only sessions with status='running'. Default false (all including killed/exited).\"\n ),\n },\n async input => {\n const all = registry\n .list()\n .filter(d => d.kind === \"browser\")\n const result = input.onlyAlive\n ? all.filter(d => d.status === \"running\")\n : all\n return {\n content: [{ type: \"text\" as const, text: JSON.stringify(result, null, 2) }],\n }\n }\n )\n\n // ── browser_status ───────────────────────────────────────────────────────────\n server.tool(\n \"browser_status\",\n \"Get the descriptor and live health status for a specific browser session. \" +\n \"Probes the service's /health endpoint to confirm it is still responding.\",\n {\n sessionId: z\n .string()\n .min(1)\n .describe(\"Session id returned by `start_browser` or `list_browsers`.\"),\n },\n async input => {\n const desc = registry.get(input.sessionId)\n if (!desc) {\n return {\n content: [\n {\n type: \"text\" as const,\n text: `browser_status: session \"${input.sessionId}\" not found.`,\n },\n ],\n isError: true,\n }\n }\n if (desc.kind !== \"browser\") {\n return {\n content: [\n {\n type: \"text\" as const,\n text: `browser_status: session \"${input.sessionId}\" is not a browser session (kind=${desc.kind}).`,\n },\n ],\n isError: true,\n }\n }\n\n let healthy: boolean | null = null\n let healthBody: unknown = null\n if (desc.browserBaseUrl) {\n const healthUrl = `${desc.browserBaseUrl}/health`\n const ac = new AbortController()\n const t = setTimeout(() => ac.abort(), 3000)\n try {\n const r = await fetch(healthUrl, { signal: ac.signal })\n healthy = r.ok\n if (r.ok) {\n try { healthBody = await r.json() } catch { /* non-JSON health */ }\n }\n } catch {\n healthy = false\n } finally {\n clearTimeout(t)\n }\n }\n\n return {\n content: [\n {\n type: \"text\" as const,\n text: JSON.stringify({ descriptor: desc, healthy, healthBody }, null, 2),\n },\n ],\n }\n }\n )\n\n // ── browser_screenshot ───────────────────────────────────────────────────────\n server.tool(\n \"browser_screenshot\",\n \"Capture a base64-encoded screenshot of what an agent's browser session is currently showing. \" +\n \"Dispatches to the correct backend by the session's browserAdapterId: \" +\n \"camofox → GET /tabs/:tabId/screenshot, \" +\n \"bureau → POST /mcp browser_screenshot, \" +\n \"chromium → POST /sessions/:id/screenshot. \" +\n \"Returns { data (base64, no data: prefix), format, width?, height? } in both text and structuredContent.\",\n {\n sessionId: z\n .string()\n .min(1)\n .describe(\"Browser session id returned by `start_browser` or `list_browsers`.\"),\n tabId: z\n .string()\n .optional()\n .describe(\n \"Camofox: tabId to screenshot (default: first active tab). \" +\n \"Chromium: service-internal session id (default: first listed session). \" +\n \"Bureau: ignored (bureau screenshots its current tab).\"\n ),\n },\n async input => {\n const desc = registry.get(input.sessionId)\n if (!desc)\n return errResult(`browser_screenshot: session \"${input.sessionId}\" not found.`)\n if (desc.kind !== \"browser\")\n return errResult(\n `browser_screenshot: session \"${input.sessionId}\" is not a browser session (kind=${desc.kind}).`\n )\n if (!desc.browserBaseUrl)\n return errResult(`browser_screenshot: session \"${input.sessionId}\" has no browserBaseUrl.`)\n\n // Normalise to IPv4 — node/undici resolves localhost→::1 first but these\n // services bind IPv4 only.\n const rawUrl = new URL(desc.browserBaseUrl)\n if (rawUrl.hostname === \"localhost\") rawUrl.hostname = \"127.0.0.1\"\n const base = rawUrl.href.replace(/\\/$/, \"\")\n const adapterId = desc.browserAdapterId ?? \"\"\n\n // AbortController created after all guard-returns so the finally block\n // below covers every path that reaches the network.\n const ac = new AbortController()\n const timer = setTimeout(() => ac.abort(), 15_000)\n\n try {\n // ── camofox (port 9377): GET /tabs/:tabId/screenshot ────────────────────\n if (adapterId === \"camofox\") {\n let tabId = input.tabId\n if (!tabId) {\n const tabsRes = await fetch(`${base}/tabs?userId=main`, { signal: ac.signal })\n if (!tabsRes.ok) throw new Error(`camofox /tabs: HTTP ${tabsRes.status}`)\n const tabsBody = (await tabsRes.json()) as { tabs?: { tabId: string }[] }\n tabId = tabsBody.tabs?.[0]?.tabId\n if (!tabId) throw new Error(\"camofox: no active tabs found\")\n }\n const shotRes = await fetch(\n `${base}/tabs/${encodeURIComponent(tabId)}/screenshot?userId=main&format=png`,\n { signal: ac.signal }\n )\n if (!shotRes.ok) throw new Error(`camofox screenshot: HTTP ${shotRes.status}`)\n const data = Buffer.from(await shotRes.arrayBuffer()).toString(\"base64\")\n return okResult({ data, format: \"png\" as const })\n }\n\n // ── bureau (port 8830): POST /mcp → browser_screenshot MCP tool ─────────\n if (adapterId === \"bureau\") {\n const mcpBody = {\n jsonrpc: \"2.0\",\n id: 1,\n method: \"tools/call\",\n params: { name: \"browser_screenshot\", arguments: { format: \"png\" } },\n }\n const mcpRes = await fetch(`${base}/mcp`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\", accept: \"application/json, text/event-stream\" },\n body: JSON.stringify(mcpBody),\n signal: ac.signal,\n })\n if (!mcpRes.ok) throw new Error(`bureau /mcp: HTTP ${mcpRes.status}`)\n const envelope = (await mcpRes.json()) as {\n result?: { content?: { type: string; text?: string }[] }\n error?: { message?: string }\n }\n if (envelope.error)\n throw new Error(`bureau MCP error: ${envelope.error.message ?? \"unknown\"}`)\n const textBlock = envelope.result?.content?.find(c => c.type === \"text\")\n if (!textBlock?.text) throw new Error(\"bureau MCP: no text content block in response\")\n const shot = JSON.parse(textBlock.text) as {\n base64?: string\n format?: string\n width?: number\n height?: number\n }\n if (!shot.base64) throw new Error(\"bureau MCP: screenshot result missing base64 field\")\n return okResult({\n data: shot.base64,\n format: (shot.format ?? \"png\") as \"png\" | \"jpeg\",\n ...(shot.width != null ? { width: shot.width } : {}),\n ...(shot.height != null ? { height: shot.height } : {}),\n })\n }\n\n // ── chromium (port 3200): POST /sessions/:id/screenshot ─────────────────\n if (adapterId === \"chromium\") {\n let chromiumSessionId = input.tabId\n if (!chromiumSessionId) {\n const listRes = await fetch(`${base}/sessions`, { signal: ac.signal })\n if (!listRes.ok) throw new Error(`chromium /sessions: HTTP ${listRes.status}`)\n const listBody = (await listRes.json()) as { sessions?: { id: string }[] }\n chromiumSessionId = listBody.sessions?.[0]?.id\n if (!chromiumSessionId) throw new Error(\"chromium: no active sessions found\")\n }\n const shotRes = await fetch(\n `${base}/sessions/${encodeURIComponent(chromiumSessionId)}/screenshot`,\n {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify({ format: \"png\" }),\n signal: ac.signal,\n }\n )\n if (!shotRes.ok) throw new Error(`chromium screenshot: HTTP ${shotRes.status}`)\n const data = Buffer.from(await shotRes.arrayBuffer()).toString(\"base64\")\n return okResult({ data, format: \"png\" as const })\n }\n\n return errResult(\n `browser_screenshot: adapter \"${adapterId}\" is not supported. ` +\n \"Supported adapters: camofox, bureau, chromium.\"\n )\n } catch (err) {\n return errResult(\n `browser_screenshot: ${err instanceof Error ? err.message : String(err)}`\n )\n } finally {\n clearTimeout(timer)\n }\n }\n )\n}\n","/**\n * Adapter: registers AgnoMcpApp[] on a @modelcontextprotocol/sdk McpServer.\n *\n * Mirrors the @agstudio/mcp-apps platform pattern but without the Mastra\n * dependency (agentproto is a standalone pnpm workspace that cannot import\n * @agstudio/* packages). Both sides follow the same invariant:\n *\n * _meta.ui.resourceUri lives at the TOOL DEFINITION level (registerTool\n * config), NOT in the handler return value. This is because the SDK\n * serialises the handler result as MCP content, and any _meta returned\n * there would be buried inside the text payload and invisible to the host.\n *\n * Usage:\n * import { registerMcpApps } from \"./mcp-apps-adapter.js\"\n * import { makeSessionsPanelApp } from \"./sessions-panel-app.js\"\n *\n * registerMcpApps(server, [\n * makeSessionsPanelApp({ listSessions: () => sessions.list() }),\n * ])\n */\n\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\"\nimport type { AgnoMcpApp } from \"./sessions-panel-app.js\"\n\nconst MIME_TYPE = \"text/html;profile=mcp-app\"\n\n/**\n * Register every AgnoMcpApp on the MCP server:\n * • A resource at ui://<id>/view serving the HTML panel.\n * • A tool named <id> that links to the resource via _meta.ui.resourceUri\n * and optionally returns a JSON snapshot from execute().\n */\nexport function registerMcpApps(\n server: McpServer,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n apps: AgnoMcpApp<any, any>[],\n): void {\n for (const app of apps) {\n const resourceUri = `ui://${app.id}/view`\n const html =\n typeof app.html === \"string\" ? app.html : app.html({} as never)\n\n // 1. Resource — HTML panel served at ui://<id>/view\n server.registerResource(\n app.id,\n resourceUri,\n {\n mimeType: MIME_TYPE,\n description: app.description,\n _meta: { ui: { prefersBorder: true } },\n },\n async () => ({\n contents: [\n {\n uri: resourceUri,\n mimeType: MIME_TYPE,\n text: html,\n },\n ],\n }),\n )\n\n // 2. Tool — _meta.ui.resourceUri at definition level so the host\n // can pre-associate the panel before the handler even runs.\n server.registerTool(\n app.id,\n {\n description: app.description ?? app.title,\n inputSchema: app.inputSchema.shape,\n annotations: {\n readOnlyHint: true,\n openWorldHint: false,\n },\n _meta: {\n ui: {\n resourceUri,\n visibility: [\"model\", \"app\"],\n },\n },\n },\n async (args) => {\n const initData = app.execute ? await app.execute(args) : {}\n return {\n content: [\n {\n type: \"text\" as const,\n text: JSON.stringify(initData, null, 2),\n },\n ],\n }\n },\n )\n }\n}\n","/**\n * MCP App resource: agentproto sessions panel.\n *\n * Declares a `ui://agentproto/sessions-panel` resource (mimeType\n * `text/html;profile=mcp-app`) and an `open_sessions_panel` tool that\n * links to it via `_meta.ui.resourceUri`.\n *\n * Protocol: MCP Apps ext spec 2026-01-26\n * – Bridge: JSON-RPC 2.0 over window.parent.postMessage\n * – Handshake: ui/initialize → host result → ui/notifications/initialized\n * – Data: tools/call → list_sessions + get_agent_session_output (3 s poll)\n * – Kill action: tools/call → kill_agent_session | kill_terminal_session\n * (goes through Claude's normal tool approval flow)\n *\n * The HTML bundle is fully autonomous (zero CDN, zero external deps).\n * ANSI-to-HTML renderer handles SGR codes (colors 0-15, bold, dim,\n * italic, underline, reset). CR-overwrite sequences are stripped so\n * progress bars don't corrupt the output.\n */\n\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\"\n\nconst RESOURCE_URI = \"ui://agentproto/sessions-panel\"\nconst MIME_TYPE = \"text/html;profile=mcp-app\"\n\n// ── HTML bundle ─────────────────────────────────────────────────────────────\n\nexport const PANEL_HTML = `<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"UTF-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<title>agentproto sessions</title>\n<style>\n*{box-sizing:border-box;margin:0;padding:0}\n:root{\n --bg:#0d1117;--bg2:#161b22;--bg3:#21262d;--border:#30363d;\n --text:#e6edf3;--text2:#8b949e;\n --green:#3fb950;--yellow:#d29922;--red:#f85149;--blue:#58a6ff;--purple:#bc8cff;\n}\nhtml,body{height:100%;font-family:Menlo,Monaco,'Courier New',monospace;font-size:13px;background:var(--bg);color:var(--text);overflow:hidden}\n#app{display:flex;height:100%}\n#sidebar{width:220px;min-width:180px;background:var(--bg2);border-right:1px solid var(--border);display:flex;flex-direction:column;flex-shrink:0}\n#sidebar-hdr{padding:10px 12px;border-bottom:1px solid var(--border);display:flex;align-items:center;justify-content:space-between}\n#sidebar-hdr h1{font-size:11px;font-weight:600;color:var(--text2);text-transform:uppercase;letter-spacing:.06em}\n#refresh-btn{background:none;border:none;cursor:pointer;color:var(--text2);font-size:15px;line-height:1;padding:2px 4px;border-radius:4px;font-family:inherit}\n#refresh-btn:hover{color:var(--text);background:var(--bg3)}\n#session-list{flex:1;overflow-y:auto;padding:4px 0}\n.si{padding:8px 12px;cursor:pointer;border-left:2px solid transparent}\n.si:hover{background:var(--bg3)}\n.si.active{background:var(--bg3);border-left-color:var(--blue)}\n.sn{font-size:12px;font-weight:500;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n.sm{font-size:11px;color:var(--text2);margin-top:2px;display:flex;gap:6px;align-items:center}\n.badge{display:inline-block;padding:1px 5px;border-radius:10px;font-size:10px;font-weight:600}\n.br{background:rgba(63,185,80,.15);color:var(--green)}\n.bs{background:rgba(88,166,255,.15);color:var(--blue)}\n.be{background:rgba(139,148,158,.1);color:var(--text2)}\n.bk{background:rgba(248,81,73,.1);color:var(--red)}\n.berr{background:rgba(248,81,73,.2);color:var(--red)}\n#main{flex:1;display:flex;flex-direction:column;overflow:hidden;min-width:0}\n#toolbar{padding:8px 12px;border-bottom:1px solid var(--border);display:flex;align-items:center;gap:8px;background:var(--bg2)}\n#session-title{font-size:12px;font-weight:500;flex:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n.abtn{background:var(--bg3);border:1px solid var(--border);color:var(--text);padding:4px 10px;border-radius:4px;cursor:pointer;font-size:12px;font-family:inherit}\n.abtn:hover{background:var(--border)}\n.abtn:disabled{opacity:.4;cursor:default}\n.abtn.danger{border-color:var(--red);color:var(--red)}\n.abtn.danger:hover{background:rgba(248,81,73,.1)}\n#output{flex:1;overflow-y:auto;padding:8px 12px;background:var(--bg);font-size:12px;line-height:1.6}\n.line{white-space:pre-wrap;word-break:break-all}\n#empty{display:flex;flex-direction:column;align-items:center;justify-content:center;height:100%;color:var(--text2);gap:8px;text-align:center;padding:24px}\n#empty .ico{font-size:32px}\n#statusbar{padding:4px 12px;font-size:11px;color:var(--text2);border-top:1px solid var(--border);background:var(--bg2);flex-shrink:0}\n.errmsg{color:var(--red);padding:12px}\n/* ANSI SGR */\n.ab{font-weight:bold}.ad{opacity:.6}.ai{font-style:italic}.au{text-decoration:underline}\n.f0{color:#21262d}.f1{color:#f85149}.f2{color:#3fb950}.f3{color:#d29922}\n.f4{color:#58a6ff}.f5{color:#bc8cff}.f6{color:#39d353}.f7{color:#e6edf3}\n.f8{color:#8b949e}.f9{color:#ff7b72}.f10{color:#56d364}.f11{color:#e3b341}\n.f12{color:#79c0ff}.f13{color:#d2a8ff}.f14{color:#56d364}.f15{color:#f0f6fc}\n</style>\n</head>\n<body>\n<div id=\"app\">\n <div id=\"sidebar\">\n <div id=\"sidebar-hdr\">\n <h1>Sessions</h1>\n <button id=\"refresh-btn\" title=\"Refresh\" onclick=\"doRefresh()\">&#8635;</button>\n </div>\n <div id=\"session-list\"></div>\n </div>\n <div id=\"main\">\n <div id=\"toolbar\" style=\"display:none\">\n <span id=\"session-title\"></span>\n <button class=\"abtn danger\" id=\"kill-btn\" onclick=\"doKill()\">Kill</button>\n </div>\n <div id=\"output\">\n <div id=\"empty\"><div class=\"ico\">&#9889;</div><div>Select a session</div></div>\n </div>\n <div id=\"statusbar\">Connecting to bridge&#8230;</div>\n </div>\n</div>\n<script>\n// ============================================================\n// MCP Apps bridge — JSON-RPC 2.0 over window.parent.postMessage\n// Spec: io.modelcontextprotocol/ui 2026-01-26\n// ============================================================\n\nvar _nextId = 1;\nvar _pending = {}; // id -> {resolve, reject}\n\nfunction post(msg) {\n window.parent.postMessage(msg, '*');\n}\n\nfunction rpcRequest(method, params) {\n return new Promise(function(resolve, reject) {\n var id = _nextId++;\n _pending[id] = {resolve: resolve, reject: reject};\n post({jsonrpc: '2.0', id: id, method: method, params: params || {}});\n });\n}\n\nfunction rpcNotify(method, params) {\n post({jsonrpc: '2.0', method: method, params: params || {}});\n}\n\nwindow.addEventListener('message', function(evt) {\n var msg = evt.data;\n if (!msg || typeof msg !== 'object' || msg.jsonrpc !== '2.0') return;\n // Responses have an id and are not requests (no method)\n if (msg.id != null && msg.method == null) {\n var p = _pending[msg.id];\n if (!p) return;\n delete _pending[msg.id];\n if (msg.error) {\n p.reject(new Error(msg.error.message || 'rpc error ' + msg.error.code));\n } else {\n p.resolve(msg.result);\n }\n }\n // Host notifications (ui/notifications/tool-input, ui/resource-teardown, etc.)\n // — ignored for now; panel drives via poll\n});\n\n// Initialize bridge per spec 2026-01-26\nfunction initBridge() {\n return rpcRequest('ui/initialize', {\n capabilities: {},\n clientInfo: {name: 'agentproto-sessions-panel', version: '0.1.0'},\n protocolVersion: '2026-01-26',\n appCapabilities: {\n tools: {listChanged: false},\n availableDisplayModes: ['inline', 'fullscreen']\n }\n }).then(function() {\n rpcNotify('ui/notifications/initialized', {});\n });\n}\n\n// Call an MCP tool through the bridge and parse the JSON result text\nfunction callTool(name, args) {\n return rpcRequest('tools/call', {name: name, arguments: args || {}}).then(function(result) {\n if (result.isError) {\n var errText = (result.content && result.content[0] && result.content[0].text) || 'tool error';\n throw new Error(errText);\n }\n var text = (result.content && result.content[0] && result.content[0].text) || '{}';\n return JSON.parse(text);\n });\n}\n\n// ============================================================\n// ANSI-to-HTML renderer (SGR codes: colors 0-15, bold/dim/italic/underline)\n// ============================================================\n\nfunction escHtml(s) {\n return s.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');\n}\n\nfunction ansiToHtml(raw) {\n // Strip CR overwrite sequences (progress bars: \\r without \\n)\n var text = raw.replace(/[^\\n]*\\r([^\\n])/g, '$1').replace(/\\r/g, '');\n var bold = false, dim = false, italic = false, underline = false, fg = -1;\n var out = '';\n // Split on ESC [ ... m (SGR) sequences; keep delimiters\n var ESC = '\u001b';\n var parts = text.split(/([\u001b]\\[[0-9;]*m)/);\n for (var pi = 0; pi < parts.length; pi++) {\n var part = parts[pi];\n if (part.length === 0) continue;\n if (part.charCodeAt(0) === 0x1b && part[1] === '[') {\n // Parse SGR parameters\n var inner = part.slice(2, part.length - 1); // strip ESC[ and m\n var codes = inner === '' ? [0] : inner.split(';').map(Number);\n for (var ci = 0; ci < codes.length; ci++) {\n var c = codes[ci];\n if (c === 0) { bold = false; dim = false; italic = false; underline = false; fg = -1; }\n else if (c === 1) bold = true;\n else if (c === 2) dim = true;\n else if (c === 3) italic = true;\n else if (c === 4) underline = true;\n else if (c === 22) { bold = false; dim = false; }\n else if (c === 23) italic = false;\n else if (c === 24) underline = false;\n else if (c >= 30 && c <= 37) fg = c - 30;\n else if (c === 39) fg = -1;\n else if (c >= 90 && c <= 97) fg = c - 90 + 8;\n }\n } else {\n // Text segment — strip any remaining non-printable ESC sequences\n var safe = escHtml(part).replace(/\u001b\\[[^m]*[A-Za-z]/g, '');\n if (safe === '') continue;\n var cls = '';\n if (bold) cls += ' ab';\n if (dim) cls += ' ad';\n if (italic) cls += ' ai';\n if (underline) cls += ' au';\n if (fg >= 0 && fg <= 15) cls += ' f' + fg;\n cls = cls.trim();\n out += cls ? '<span class=\"' + cls + '\">' + safe + '</span>' : safe;\n }\n }\n return out;\n}\n\n// ============================================================\n// App state\n// ============================================================\n\nvar sessions = [];\nvar activeId = null;\nvar outputLines = [];\nvar nextCursor = 0;\nvar pollTimer = null;\nvar pollActive = false;\n\nfunction setStatus(msg) {\n document.getElementById('statusbar').textContent = msg;\n}\n\n// ============================================================\n// Session list\n// ============================================================\n\nfunction badgeClass(status) {\n if (status === 'running') return 'br';\n if (status === 'starting') return 'bs';\n if (status === 'killed') return 'bk';\n if (status === 'error') return 'berr';\n return 'be'; // exited\n}\n\nfunction renderSidebar() {\n var el = document.getElementById('session-list');\n if (sessions.length === 0) {\n el.innerHTML = '<div style=\"padding:12px;color:var(--text2);font-size:11px\">No sessions</div>';\n return;\n }\n var html = '';\n for (var i = 0; i < sessions.length; i++) {\n var s = sessions[i];\n var label = s.label || s.name || (s.command ? s.command.split('/').pop() : null) || s.id.slice(0, 8);\n var bc = badgeClass(s.status);\n var active = s.id === activeId ? ' active' : '';\n html += '<div class=\"si' + active + '\" onclick=\"selectSession(\\'' + s.id + '\\')\">'\n + '<div class=\"sn\">' + escHtml(label) + '</div>'\n + '<div class=\"sm\">'\n + '<span class=\"badge ' + bc + '\">' + s.status + '</span>'\n + '<span>' + escHtml(s.kind || '') + '</span>'\n + '</div></div>';\n }\n el.innerHTML = html;\n}\n\nfunction loadSessions() {\n return callTool('list_sessions', {kind: 'all'}).then(function(data) {\n sessions = data.sessions || [];\n renderSidebar();\n setStatus(sessions.length + ' session' + (sessions.length === 1 ? '' : 's') + ' · ' + new Date().toLocaleTimeString());\n }).catch(function(e) {\n setStatus('Error: ' + e.message);\n });\n}\n\n// ============================================================\n// Output panel\n// ============================================================\n\nfunction renderOutputFull() {\n var el = document.getElementById('output');\n if (outputLines.length === 0) {\n el.innerHTML = '<div id=\"empty\"><div class=\"ico\">&#9889;</div><div>No output yet</div></div>';\n return;\n }\n var html = '';\n for (var i = 0; i < outputLines.length; i++) {\n html += '<div class=\"line\">' + ansiToHtml(outputLines[i]) + '</div>';\n }\n el.innerHTML = html;\n el.scrollTop = el.scrollHeight;\n}\n\nfunction appendLines(lines) {\n var el = document.getElementById('output');\n // Remove empty-state placeholder if present\n var empty = el.querySelector('#empty');\n if (empty) empty.parentNode.removeChild(empty);\n var frag = document.createDocumentFragment();\n for (var i = 0; i < lines.length; i++) {\n var div = document.createElement('div');\n div.className = 'line';\n div.innerHTML = ansiToHtml(lines[i]);\n frag.appendChild(div);\n }\n el.appendChild(frag);\n el.scrollTop = el.scrollHeight;\n}\n\nfunction selectSession(id) {\n activeId = id;\n outputLines = [];\n nextCursor = 0;\n renderSidebar();\n\n var s = null;\n for (var i = 0; i < sessions.length; i++) {\n if (sessions[i].id === id) { s = sessions[i]; break; }\n }\n\n var toolbar = document.getElementById('toolbar');\n toolbar.style.display = 'flex';\n document.getElementById('session-title').textContent = (s && (s.label || s.name)) || id.slice(0, 12);\n\n var killBtn = document.getElementById('kill-btn');\n killBtn.disabled = !s || (s.status !== 'running' && s.status !== 'starting');\n\n document.getElementById('output').innerHTML = '<div style=\"padding:12px;color:var(--text2)\">Loading&#8230;</div>';\n\n // Initial load\n callTool('get_agent_session_output', {sessionId: id, lastN: 200}).then(function(data) {\n outputLines = data.lines || [];\n nextCursor = data.nextCursor || 0;\n renderOutputFull();\n }).catch(function(e) {\n document.getElementById('output').innerHTML = '<div class=\"errmsg\">Error: ' + escHtml(e.message) + '</div>';\n });\n}\n\n// ============================================================\n// Kill\n// ============================================================\n\nfunction doKill() {\n if (!activeId) return;\n var s = null;\n for (var i = 0; i < sessions.length; i++) {\n if (sessions[i].id === activeId) { s = sessions[i]; break; }\n }\n var toolName = (s && s.pty) ? 'kill_terminal_session' : 'kill_agent_session';\n callTool(toolName, {sessionId: activeId}).then(function() {\n return doRefresh();\n }).catch(function(e) {\n setStatus('Kill failed: ' + e.message);\n });\n}\n\n// ============================================================\n// Poll\n// ============================================================\n\nfunction doPoll() {\n if (pollActive) return;\n pollActive = true;\n var p = loadSessions();\n if (activeId) {\n var capturedId = activeId;\n var capturedCursor = nextCursor;\n p = p.then(function() {\n return callTool('get_agent_session_output', {sessionId: capturedId, since: capturedCursor});\n }).then(function(data) {\n if (capturedId !== activeId) return; // user switched sessions\n var newLines = data.lines || [];\n if (newLines.length > 0) {\n outputLines = outputLines.concat(newLines);\n if (outputLines.length > 2000) outputLines = outputLines.slice(-2000);\n nextCursor = data.nextCursor || nextCursor;\n appendLines(newLines);\n }\n }).catch(function() {});\n }\n p.then(function() {\n pollActive = false;\n pollTimer = setTimeout(doPoll, 3000);\n }).catch(function() {\n pollActive = false;\n pollTimer = setTimeout(doPoll, 3000);\n });\n}\n\nfunction doRefresh() {\n return loadSessions().then(function() {\n if (activeId) {\n return callTool('get_agent_session_output', {sessionId: activeId, lastN: 200}).then(function(data) {\n outputLines = data.lines || [];\n nextCursor = data.nextCursor || 0;\n renderOutputFull();\n });\n }\n });\n}\n\n// ============================================================\n// Boot\n// ============================================================\n\ninitBridge().then(function() {\n return loadSessions();\n}).then(function() {\n pollTimer = setTimeout(doPoll, 3000);\n}).catch(function(e) {\n setStatus('Bridge error: ' + e.message);\n document.getElementById('output').innerHTML = '<div class=\"errmsg\">Failed to connect to MCP bridge: ' + escHtml(e.message) + '</div>';\n});\n</script>\n</body>\n</html>`\n\n// ── MCP registration ─────────────────────────────────────────────────────────\n\nexport function registerSessionsPanelResource(server: McpServer): void {\n // Resource — MCP Apps host (Claude) reads this and renders the HTML\n // in a sandboxed iframe.\n server.registerResource(\n \"sessions-panel\",\n RESOURCE_URI,\n {\n mimeType: MIME_TYPE,\n description:\n \"Interactive sessions panel — browse, inspect output, and kill \" +\n \"agentproto daemon sessions. Rendered as an MCP App in the host UI.\",\n _meta: {\n ui: {\n // No external CSP domains needed — fully autonomous bundle.\n prefersBorder: true,\n },\n },\n },\n async () => ({\n contents: [\n {\n uri: RESOURCE_URI,\n mimeType: MIME_TYPE,\n text: PANEL_HTML,\n },\n ],\n }),\n )\n\n // Tool — links to the panel resource via _meta.ui.resourceUri so the\n // host pre-associates the panel with this tool call and can show it\n // immediately when the tool is invoked.\n server.registerTool(\n \"open_sessions_panel\",\n {\n description:\n \"Open the agentproto sessions panel — an interactive UI that shows all \" +\n \"running and recent sessions (agent-CLI, terminal/PTY, commands). \" +\n \"The panel polls live data and lets you inspect output or kill sessions. \" +\n \"Rendered as an MCP App in the host interface.\",\n inputSchema: undefined,\n annotations: {\n readOnlyHint: true,\n openWorldHint: false,\n },\n _meta: {\n ui: {\n resourceUri: RESOURCE_URI,\n visibility: [\"model\", \"app\"],\n },\n },\n },\n async () => ({\n content: [\n {\n type: \"text\" as const,\n text: JSON.stringify(\n {\n ok: true,\n panel: RESOURCE_URI,\n message: \"Sessions panel available. The host should render it as an MCP App.\",\n },\n null,\n 2,\n ),\n },\n ],\n }),\n )\n}\n","/**\n * McpApp definition for the agentproto sessions panel.\n *\n * Uses the AgnoMcpApp contract (a local McpApp-compatible shape that does\n * NOT depend on @agstudio/mcp-apps or Mastra — agentproto is a separate\n * pnpm workspace). Wire via `registerMcpApps` from mcp-apps-adapter.ts.\n *\n * Protocol flow:\n * 1. Tool `agentproto_sessions` is called by the host.\n * 2. execute() returns a sessions snapshot → injected into the HTML as\n * window.__APP_INIT__ (static initial render, no bridge needed).\n * 3. The HTML panel opens a JSON-RPC bridge (postMessage) and polls\n * `list_sessions` + `get_agent_session_output` every 3 s for live data.\n */\n\nimport { z } from \"zod\"\nimport { PANEL_HTML } from \"./sessions-panel.js\"\nimport type { SessionDescriptor } from \"./sessions.js\"\n\nexport const sessionsPanelInputSchema = z.object({\n filter: z\n .enum([\"running\", \"all\"])\n .optional()\n .describe(\n \"Which sessions to return. `running` = only alive; `all` = running + recent (default).\",\n ),\n})\n\nexport type SessionsInput = z.infer<typeof sessionsPanelInputSchema>\nexport type SessionsOutput = { sessions: SessionDescriptor[] }\n\nexport interface SessionsPanelOps {\n listSessions(filter?: \"running\" | \"all\"): SessionDescriptor[]\n}\n\n/**\n * Local McpApp-compatible shape — mirrors @agstudio/mcp-apps McpApp<TIn,TOut>\n * without importing it (cross-workspace isolation).\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport interface AgnoMcpApp<TInput = unknown, TOutput = unknown> {\n id: string\n title: string\n description?: string\n /** Must be a z.object({...}) so registerMcpApps can extract .shape. */\n inputSchema: z.ZodObject<z.ZodRawShape>\n execute?: (input: TInput) => Promise<TOutput>\n html: string | ((initData: TOutput) => string)\n}\n\n/**\n * Factory: close over the sessions registry so execute() doesn't need\n * an AppContext (agentproto has no userId/guildId concept).\n */\nexport function makeSessionsPanelApp(\n ops: SessionsPanelOps,\n): AgnoMcpApp<SessionsInput, SessionsOutput> {\n return {\n id: \"agentproto_sessions\",\n title: \"Agent Sessions\",\n description:\n \"Open the agentproto sessions panel — an interactive UI that shows all \" +\n \"running and recent sessions (agent-CLI, terminal/PTY, commands). \" +\n \"The panel polls live data and lets you inspect output or kill sessions.\",\n inputSchema: sessionsPanelInputSchema,\n execute: async (input) => ({\n sessions: ops.listSessions(input.filter),\n }),\n html: PANEL_HTML,\n }\n}\n","/**\n * McpApp definition for the agentproto \"agents — vue claire\" panel.\n *\n * A plain-language overview of agent-cli sessions: one card per session\n * with a single human sentence (what the agent is doing/last said) plus a\n * coarse state — `à traiter` / `au travail` / `en attente` / `terminé`.\n *\n * Uses the same AgnoMcpApp contract as sessions-panel-app.ts (a local\n * McpApp-compatible shape that does NOT depend on @agstudio/mcp-apps —\n * agentproto is a separate pnpm workspace). Wire via `registerMcpApps`.\n *\n * Protocol flow:\n * 1. Tool `agentproto_agents_overview` is called by the host.\n * 2. execute() returns the agent-session snapshot → injected into the\n * HTML as the initial render via the tool result JSON.\n * 3. The HTML panel opens a JSON-RPC bridge (postMessage) and polls\n * `list_sessions` every ~12 s, then calls `summarize_session` for\n * each visible session to fetch the plain sentence + state.\n *\n * The per-session summary is generated SERVER-SIDE by the\n * `summarize_session` tool (see registerSummarizeSessionTool below).\n * Today it is HEURISTIC — last meaningful output line + a state derived\n * from lifecycle/awaitingInput/recency. There is no LLM client wired into\n * @agentproto/runtime (egress/providers.ts is a proxy allowlist, not an\n * inference client; driver-agent-cli's `ModelLike.complete` would spawn a\n * fresh agent session per call — too heavy, and it would pollute the very\n * session list we render). When a real summarizer is wanted, swap the body\n * of `summarizeSession` for a `ModelLike.complete({system, prompt})` call;\n * the tool contract (1 sentence + state) stays the same.\n */\n\nimport { z } from \"zod\"\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\"\nimport type { SessionDescriptor } from \"./sessions.js\"\nimport type { AgnoMcpApp } from \"./sessions-panel-app.js\"\n\n// ── Heuristic summary (pure, server-side) ────────────────────────────────────\n\nexport type SessionState = \"à traiter\" | \"au travail\" | \"en attente\" | \"terminé\"\n\nconst ANSI_RE = /\\x1b\\[[0-9;?]*[A-Za-z]/g\n/** Chrome-only lines we never want as a summary (spinners, box-drawing,\n * bare prompts, separators). */\nconst CHROME_RE = /^[\\s>$#*✻✶✳·•.\\-=_|~╭╰╮╯│─├┤┌┐└┘]+$/u\n\nfunction strip(s: string): string {\n return s.replace(ANSI_RE, \"\").replace(/\\r/g, \"\")\n}\n\n/**\n * Pick the last meaningful output line as a one-sentence summary.\n * Falls back to the session label/command when there's no usable output.\n */\nexport function summarizeLines(\n lines: readonly string[],\n desc: Pick<SessionDescriptor, \"command\" | \"label\" | \"name\">,\n): string {\n for (let i = lines.length - 1; i >= 0; i--) {\n const t = strip(lines[i] ?? \"\").trim()\n if (t.length < 3) continue\n if (CHROME_RE.test(t)) continue\n return t.length > 160 ? `${t.slice(0, 157)}…` : t\n }\n return desc.label || desc.name || desc.command || \"Aucune sortie pour le moment.\"\n}\n\n/**\n * Coarse state from lifecycle + recency. Heuristic, no LLM:\n * terminé — exited / killed / error\n * à traiter — alive and the agent flagged awaiting-input (your turn)\n * au travail — alive and produced output recently (< staleMs)\n * en attente — alive but idle (no recent output, not awaiting input)\n */\nexport function deriveSessionState(\n desc: Pick<SessionDescriptor, \"status\" | \"awaitingInput\" | \"lastOutputAt\">,\n nowMs: number,\n staleMs = 30_000,\n): SessionState {\n if (desc.status === \"exited\" || desc.status === \"killed\" || desc.status === \"error\") {\n return \"terminé\"\n }\n if (desc.awaitingInput) return \"à traiter\"\n const last = desc.lastOutputAt ? Date.parse(desc.lastOutputAt) : Number.NaN\n if (!Number.isNaN(last) && nowMs - last < staleMs) return \"au travail\"\n return \"en attente\"\n}\n\nexport interface SessionSummary {\n sessionId: string\n summary: string\n state: SessionState\n status: SessionDescriptor[\"status\"]\n label?: string\n lastOutputAt?: string\n}\n\n/** Build the full per-session summary from a descriptor + recent lines. */\nexport function summarizeSession(\n desc: SessionDescriptor,\n lines: readonly string[],\n nowMs: number,\n): SessionSummary {\n return {\n sessionId: desc.id,\n summary: summarizeLines(lines, desc),\n state: deriveSessionState(desc, nowMs),\n status: desc.status,\n ...(desc.label ? { label: desc.label } : {}),\n ...(desc.lastOutputAt ? { lastOutputAt: desc.lastOutputAt } : {}),\n }\n}\n\n// ── summarize_session tool ───────────────────────────────────────────────────\n\nexport interface SummarizeOps {\n getSession(id: string): SessionDescriptor | undefined\n /** Tail the recent ring buffer for a session (same source as\n * get_agent_session_output). Returns [] for unknown sessions. */\n tailLines(id: string, lastN: number): string[]\n /** Current epoch-ms, injectable for tests. Defaults to Date.now. */\n now?: () => number\n}\n\n/**\n * Register the server-side `summarize_session` tool. The agents-overview\n * panel calls this via the bridge (callTool) for each visible session.\n */\nexport function registerSummarizeSessionTool(server: McpServer, ops: SummarizeOps): void {\n server.tool(\n \"summarize_session\",\n \"Summarise a session in one plain sentence plus a coarse state \" +\n \"(à traiter / au travail / en attente / terminé). Heuristic today \" +\n \"(last meaningful output line + lifecycle/recency) — no LLM. Used by \" +\n \"the agents overview panel.\",\n {\n sessionId: z.string().describe(\"Session id to summarise.\"),\n lastN: z\n .number()\n .int()\n .min(1)\n .max(500)\n .optional()\n .describe(\"Max recent lines to scan. Default 120.\"),\n },\n async input => {\n const desc = ops.getSession(input.sessionId)\n if (!desc) {\n return {\n content: [\n { type: \"text\" as const, text: `summarize_session: no session \"${input.sessionId}\"` },\n ],\n isError: true,\n }\n }\n const lines = ops.tailLines(input.sessionId, input.lastN ?? 120)\n const nowMs = (ops.now ?? Date.now)()\n return {\n content: [\n { type: \"text\" as const, text: JSON.stringify(summarizeSession(desc, lines, nowMs), null, 2) },\n ],\n }\n },\n )\n}\n\n// ── McpApp factory ───────────────────────────────────────────────────────────\n\nexport const agentsOverviewInputSchema = z.object({\n filter: z\n .enum([\"running\", \"all\"])\n .optional()\n .describe(\"`running` = only alive agent sessions; `all` = running + recent (default).\"),\n})\n\nexport type AgentsOverviewInput = z.infer<typeof agentsOverviewInputSchema>\nexport type AgentsOverviewOutput = { sessions: SessionDescriptor[] }\n\nexport interface AgentsOverviewOps {\n listSessions(filter?: \"running\" | \"all\"): SessionDescriptor[]\n}\n\nexport function makeAgentsOverviewApp(\n ops: AgentsOverviewOps,\n): AgnoMcpApp<AgentsOverviewInput, AgentsOverviewOutput> {\n return {\n id: \"agentproto_agents_overview\",\n title: \"Agents — vue claire\",\n description:\n \"Open the agents overview — a plain-language card per agent session \" +\n \"with one human sentence (what it's doing / last said) and a coarse \" +\n \"state (à traiter / au travail / en attente / terminé). Polls live and \" +\n \"asks the server to summarise each session.\",\n inputSchema: agentsOverviewInputSchema,\n execute: async input => ({ sessions: ops.listSessions(input.filter) }),\n html: AGENTS_OVERVIEW_HTML,\n }\n}\n\n// ── HTML bundle (zero CDN, CSP-safe inline) ──────────────────────────────────\n\nexport const AGENTS_OVERVIEW_HTML = `<!DOCTYPE html>\n<html lang=\"fr\">\n<head>\n<meta charset=\"UTF-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<title>agents — vue claire</title>\n<style>\n*{box-sizing:border-box;margin:0;padding:0}\n:root{\n --bg:#0d1117;--bg2:#161b22;--bg3:#21262d;--border:#30363d;\n --text:#e6edf3;--text2:#8b949e;\n --green:#3fb950;--yellow:#d29922;--red:#f85149;--blue:#58a6ff;--purple:#bc8cff;\n}\nhtml,body{height:100%;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Helvetica,Arial,sans-serif;font-size:13px;background:var(--bg);color:var(--text);overflow:hidden}\n#app{display:flex;flex-direction:column;height:100%}\n#hdr{padding:12px 16px;border-bottom:1px solid var(--border);display:flex;align-items:center;justify-content:space-between;background:var(--bg2);flex-shrink:0}\n#hdr h1{font-size:13px;font-weight:600;letter-spacing:.02em}\n#hdr .sub{font-size:11px;color:var(--text2);margin-top:2px}\n#refresh-btn{background:none;border:none;cursor:pointer;color:var(--text2);font-size:16px;line-height:1;padding:4px 6px;border-radius:6px}\n#refresh-btn:hover{color:var(--text);background:var(--bg3)}\n#grid{flex:1;overflow-y:auto;padding:14px 16px;display:grid;grid-template-columns:repeat(auto-fill,minmax(280px,1fr));gap:12px;align-content:start}\n.card{background:var(--bg2);border:1px solid var(--border);border-left:3px solid var(--border);border-radius:8px;padding:12px 14px;display:flex;flex-direction:column;gap:8px;min-height:96px}\n.card.s-todo{border-left-color:var(--purple)}\n.card.s-work{border-left-color:var(--green)}\n.card.s-wait{border-left-color:var(--yellow)}\n.card.s-done{border-left-color:var(--text2)}\n.card-top{display:flex;align-items:center;justify-content:space-between;gap:8px}\n.title{font-size:12px;font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;flex:1}\n.state{font-size:10px;font-weight:700;padding:2px 8px;border-radius:11px;white-space:nowrap;letter-spacing:.02em}\n.state.s-todo{background:rgba(188,140,255,.16);color:var(--purple)}\n.state.s-work{background:rgba(63,185,80,.16);color:var(--green)}\n.state.s-wait{background:rgba(210,153,34,.16);color:var(--yellow)}\n.state.s-done{background:rgba(139,148,158,.14);color:var(--text2)}\n.summary{font-size:12.5px;line-height:1.5;color:var(--text);word-break:break-word}\n.summary.muted{color:var(--text2);font-style:italic}\n.meta{font-size:10.5px;color:var(--text2);display:flex;gap:8px;align-items:center;flex-wrap:wrap;margin-top:auto}\n.dot{width:5px;height:5px;border-radius:50%;background:var(--text2);display:inline-block}\n#empty{grid-column:1/-1;display:flex;flex-direction:column;align-items:center;justify-content:center;color:var(--text2);gap:8px;padding:48px;text-align:center}\n#empty .ico{font-size:30px}\n#statusbar{padding:5px 16px;font-size:11px;color:var(--text2);border-top:1px solid var(--border);background:var(--bg2);flex-shrink:0}\n</style>\n</head>\n<body>\n<div id=\"app\">\n <div id=\"hdr\">\n <div>\n <h1>Agents — vue claire</h1>\n <div class=\"sub\">une carte par agent · résumé + état</div>\n </div>\n <button id=\"refresh-btn\" title=\"Rafraîchir\" onclick=\"doRefresh()\">&#8635;</button>\n </div>\n <div id=\"grid\"><div id=\"empty\"><div class=\"ico\">&#9889;</div><div>Connexion au bridge&#8230;</div></div></div>\n <div id=\"statusbar\">Connexion&#8230;</div>\n</div>\n<script>\n// ── MCP Apps bridge — JSON-RPC 2.0 over window.parent.postMessage ──\n// Spec: io.modelcontextprotocol/ui 2026-01-26\nvar _nextId = 1, _pending = {};\nfunction post(msg){ window.parent.postMessage(msg, '*'); }\nfunction rpcRequest(method, params){\n return new Promise(function(resolve, reject){\n var id = _nextId++;\n _pending[id] = {resolve: resolve, reject: reject};\n post({jsonrpc:'2.0', id:id, method:method, params:params||{}});\n });\n}\nfunction rpcNotify(method, params){ post({jsonrpc:'2.0', method:method, params:params||{}}); }\nwindow.addEventListener('message', function(evt){\n var msg = evt.data;\n if (!msg || typeof msg !== 'object' || msg.jsonrpc !== '2.0') return;\n if (msg.id != null && msg.method == null){\n var p = _pending[msg.id];\n if (!p) return;\n delete _pending[msg.id];\n if (msg.error) p.reject(new Error(msg.error.message || ('rpc error ' + msg.error.code)));\n else p.resolve(msg.result);\n }\n});\nfunction initBridge(){\n return rpcRequest('ui/initialize', {\n capabilities: {},\n clientInfo: {name:'agentproto-agents-overview', version:'0.1.0'},\n protocolVersion: '2026-01-26',\n appCapabilities: {tools:{listChanged:false}, availableDisplayModes:['inline','fullscreen']}\n }).then(function(){ rpcNotify('ui/notifications/initialized', {}); });\n}\nfunction callTool(name, args){\n return rpcRequest('tools/call', {name:name, arguments:args||{}}).then(function(result){\n if (result.isError){\n var e = (result.content && result.content[0] && result.content[0].text) || 'tool error';\n throw new Error(e);\n }\n var text = (result.content && result.content[0] && result.content[0].text) || '{}';\n return JSON.parse(text);\n });\n}\n\n// ── State ──\nvar REFRESH_MS = 12000;\nvar pollTimer = null, polling = false;\nfunction esc(s){ return String(s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;'); }\nfunction setStatus(m){ document.getElementById('statusbar').textContent = m; }\n\nvar STATE_CLASS = {\n 'à traiter':'s-todo', 'au travail':'s-work', 'en attente':'s-wait', 'terminé':'s-done'\n};\nfunction stateClass(st){ return STATE_CLASS[st] || 's-wait'; }\n\nfunction fmtAgo(iso){\n if (!iso) return '';\n var t = Date.parse(iso);\n if (isNaN(t)) return '';\n var s = Math.max(0, Math.round((Date.now() - t) / 1000));\n if (s < 60) return 'il y a ' + s + 's';\n var m = Math.round(s/60);\n if (m < 60) return 'il y a ' + m + 'min';\n var h = Math.round(m/60);\n return 'il y a ' + h + 'h';\n}\n\nfunction titleOf(s){\n return s.label || s.name || (s.command ? s.command.split(/\\\\s+/)[0].split('/').pop() : null) || s.id.slice(0,8);\n}\n\nfunction render(sessions, summaries){\n var grid = document.getElementById('grid');\n if (!sessions.length){\n grid.innerHTML = '<div id=\"empty\"><div class=\"ico\">&#128564;</div><div>Aucune session d\\\\'agent</div></div>';\n return;\n }\n var html = '';\n for (var i=0;i<sessions.length;i++){\n var s = sessions[i];\n var sum = summaries[s.id] || {};\n var st = sum.state || 'en attente';\n var cls = stateClass(st);\n var summary = sum.summary || 'Résumé indisponible.';\n var muted = !sum.summary ? ' muted' : '';\n html += '<div class=\"card ' + cls + '\">'\n + '<div class=\"card-top\">'\n + '<span class=\"title\">' + esc(titleOf(s)) + '</span>'\n + '<span class=\"state ' + cls + '\">' + esc(st) + '</span>'\n + '</div>'\n + '<div class=\"summary' + muted + '\">' + esc(summary) + '</div>'\n + '<div class=\"meta\">'\n + '<span>' + esc(s.kind || '') + '</span><span class=\"dot\"></span>'\n + '<span>' + esc(s.status || '') + '</span>'\n + (s.lastOutputAt ? '<span class=\"dot\"></span><span>' + esc(fmtAgo(s.lastOutputAt)) + '</span>' : '')\n + '</div>'\n + '</div>';\n }\n grid.innerHTML = html;\n}\n\nfunction loadAndRender(){\n return callTool('list_sessions', {kind:'all'}).then(function(data){\n var all = data.sessions || [];\n var agents = all.filter(function(s){ return s.kind === 'agent-cli'; });\n // Render shells immediately, then fill summaries as they arrive.\n var summaries = {};\n render(agents, summaries);\n setStatus(agents.length + ' agent' + (agents.length===1?'':'s') + ' · ' + new Date().toLocaleTimeString('fr-FR'));\n return Promise.all(agents.map(function(s){\n return callTool('summarize_session', {sessionId: s.id}).then(function(sum){\n summaries[s.id] = sum;\n }).catch(function(){ /* leave shell */ });\n })).then(function(){ render(agents, summaries); });\n }).catch(function(e){ setStatus('Erreur : ' + e.message); });\n}\n\nfunction doPoll(){\n if (polling) return;\n polling = true;\n loadAndRender().then(function(){\n polling = false;\n pollTimer = setTimeout(doPoll, REFRESH_MS);\n }).catch(function(){\n polling = false;\n pollTimer = setTimeout(doPoll, REFRESH_MS);\n });\n}\nfunction doRefresh(){ if (pollTimer) clearTimeout(pollTimer); return loadAndRender().then(function(){ pollTimer = setTimeout(doPoll, REFRESH_MS); }); }\n\ninitBridge().then(loadAndRender).then(function(){\n pollTimer = setTimeout(doPoll, REFRESH_MS);\n}).catch(function(e){\n setStatus('Bridge : ' + e.message);\n document.getElementById('grid').innerHTML = '<div id=\"empty\"><div class=\"ico\">&#9888;</div><div>Échec connexion bridge : ' + esc(e.message) + '</div></div>';\n});\n</script>\n</body>\n</html>`\n","/**\n * McpApp definition for the agentproto \"bureau — sessions navigateur\" panel.\n *\n * Shows the browser sessions (kind === \"browser\"): adapter, base URL, port,\n * status and uptime. One row per live/recent browser service so you can see\n * what's bound where at a glance.\n *\n * Uses the same AgnoMcpApp contract as sessions-panel-app.ts (no\n * @agstudio/mcp-apps dependency — agentproto is a standalone workspace).\n * Wire via `registerMcpApps`.\n *\n * Protocol flow:\n * 1. Tool `agentproto_bureau_sessions` is called by the host.\n * 2. execute() returns the browser-session snapshot.\n * 3. The HTML panel opens a JSON-RPC bridge (postMessage) and polls\n * `list_sessions {kind:'all'}` every ~5 s, filtering to kind===\"browser\".\n *\n * Data only — no server LLM. The whole bundle is inline (zero CDN).\n */\n\nimport { z } from \"zod\"\nimport type { SessionDescriptor } from \"./sessions.js\"\nimport type { AgnoMcpApp } from \"./sessions-panel-app.js\"\n\nexport const bureauSessionsInputSchema = z.object({\n filter: z\n .enum([\"running\", \"all\"])\n .optional()\n .describe(\"`running` = only alive browser sessions; `all` = running + recent (default).\"),\n})\n\nexport type BureauSessionsInput = z.infer<typeof bureauSessionsInputSchema>\nexport type BureauSessionsOutput = { sessions: SessionDescriptor[] }\n\nexport interface BureauSessionsOps {\n listSessions(filter?: \"running\" | \"all\"): SessionDescriptor[]\n}\n\nexport function makeBureauSessionsApp(\n ops: BureauSessionsOps,\n): AgnoMcpApp<BureauSessionsInput, BureauSessionsOutput> {\n return {\n id: \"agentproto_bureau_sessions\",\n title: \"Bureau — sessions navigateur\",\n description:\n \"Open the browser-sessions panel — one row per browser service \" +\n \"(adapter, base URL, port, status, uptime). Polls live every ~5 s.\",\n inputSchema: bureauSessionsInputSchema,\n execute: async input => ({\n sessions: ops.listSessions(input.filter).filter(s => s.kind === \"browser\"),\n }),\n html: BUREAU_SESSIONS_HTML,\n }\n}\n\n// ── HTML bundle (zero CDN, CSP-safe inline) ──────────────────────────────────\n\nexport const BUREAU_SESSIONS_HTML = `<!DOCTYPE html>\n<html lang=\"fr\">\n<head>\n<meta charset=\"UTF-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<title>bureau — sessions navigateur</title>\n<style>\n*{box-sizing:border-box;margin:0;padding:0}\n:root{\n --bg:#0d1117;--bg2:#161b22;--bg3:#21262d;--border:#30363d;\n --text:#e6edf3;--text2:#8b949e;\n --green:#3fb950;--yellow:#d29922;--red:#f85149;--blue:#58a6ff;--purple:#bc8cff;\n}\n*{box-sizing:border-box}\nhtml,body{height:100%;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Helvetica,Arial,sans-serif;font-size:13px;background:var(--bg);color:var(--text);overflow:hidden}\n#app{display:flex;flex-direction:column;height:100%}\n#hdr{padding:12px 16px;border-bottom:1px solid var(--border);display:flex;align-items:center;justify-content:space-between;background:var(--bg2);flex-shrink:0}\n#hdr h1{font-size:13px;font-weight:600}\n#hdr .sub{font-size:11px;color:var(--text2);margin-top:2px}\n#refresh-btn{background:none;border:none;cursor:pointer;color:var(--text2);font-size:16px;line-height:1;padding:4px 6px;border-radius:6px}\n#refresh-btn:hover{color:var(--text);background:var(--bg3)}\n#list{flex:1;overflow-y:auto;padding:14px 16px;display:flex;flex-direction:column;gap:10px}\n.row{background:var(--bg2);border:1px solid var(--border);border-radius:8px;padding:11px 14px;display:flex;align-items:center;gap:14px}\n.icon{font-size:20px;flex-shrink:0}\n.body{flex:1;min-width:0}\n.r1{display:flex;align-items:center;gap:8px}\n.adapter{font-size:12.5px;font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n.url{font-family:Menlo,Monaco,'Courier New',monospace;font-size:11.5px;color:var(--blue);margin-top:3px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n.meta{font-size:10.5px;color:var(--text2);margin-top:3px;display:flex;gap:8px;align-items:center;flex-wrap:wrap}\n.dot{width:5px;height:5px;border-radius:50%;background:var(--text2);display:inline-block}\n.badge{font-size:10px;font-weight:700;padding:2px 8px;border-radius:11px;white-space:nowrap}\n.br{background:rgba(63,185,80,.16);color:var(--green)}\n.bs{background:rgba(88,166,255,.16);color:var(--blue)}\n.bk{background:rgba(248,81,73,.14);color:var(--red)}\n.be{background:rgba(139,148,158,.14);color:var(--text2)}\n.berr{background:rgba(248,81,73,.22);color:var(--red)}\n.port{font-family:Menlo,Monaco,'Courier New',monospace}\n#empty{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;color:var(--text2);gap:8px;padding:48px;text-align:center}\n#empty .ico{font-size:30px}\n#statusbar{padding:5px 16px;font-size:11px;color:var(--text2);border-top:1px solid var(--border);background:var(--bg2);flex-shrink:0}\n</style>\n</head>\n<body>\n<div id=\"app\">\n <div id=\"hdr\">\n <div>\n <h1>Bureau — sessions navigateur</h1>\n <div class=\"sub\">services navigateur actifs · URL / port / statut</div>\n </div>\n <button id=\"refresh-btn\" title=\"Rafraîchir\" onclick=\"doRefresh()\">&#8635;</button>\n </div>\n <div id=\"list\"><div id=\"empty\"><div class=\"ico\">&#127760;</div><div>Connexion au bridge&#8230;</div></div></div>\n <div id=\"statusbar\">Connexion&#8230;</div>\n</div>\n<script>\n// ── MCP Apps bridge — JSON-RPC 2.0 over window.parent.postMessage ──\n// Spec: io.modelcontextprotocol/ui 2026-01-26\nvar _nextId = 1, _pending = {};\nfunction post(msg){ window.parent.postMessage(msg, '*'); }\nfunction rpcRequest(method, params){\n return new Promise(function(resolve, reject){\n var id = _nextId++;\n _pending[id] = {resolve: resolve, reject: reject};\n post({jsonrpc:'2.0', id:id, method:method, params:params||{}});\n });\n}\nfunction rpcNotify(method, params){ post({jsonrpc:'2.0', method:method, params:params||{}}); }\nwindow.addEventListener('message', function(evt){\n var msg = evt.data;\n if (!msg || typeof msg !== 'object' || msg.jsonrpc !== '2.0') return;\n if (msg.id != null && msg.method == null){\n var p = _pending[msg.id];\n if (!p) return;\n delete _pending[msg.id];\n if (msg.error) p.reject(new Error(msg.error.message || ('rpc error ' + msg.error.code)));\n else p.resolve(msg.result);\n }\n});\nfunction initBridge(){\n return rpcRequest('ui/initialize', {\n capabilities: {},\n clientInfo: {name:'agentproto-bureau-sessions', version:'0.1.0'},\n protocolVersion: '2026-01-26',\n appCapabilities: {tools:{listChanged:false}, availableDisplayModes:['inline','fullscreen']}\n }).then(function(){ rpcNotify('ui/notifications/initialized', {}); });\n}\nfunction callTool(name, args){\n return rpcRequest('tools/call', {name:name, arguments:args||{}}).then(function(result){\n if (result.isError){\n var e = (result.content && result.content[0] && result.content[0].text) || 'tool error';\n throw new Error(e);\n }\n var text = (result.content && result.content[0] && result.content[0].text) || '{}';\n return JSON.parse(text);\n });\n}\n\n// ── State ──\nvar REFRESH_MS = 5000;\nvar pollTimer = null, polling = false;\nfunction esc(s){ return String(s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;'); }\nfunction setStatus(m){ document.getElementById('statusbar').textContent = m; }\n\nfunction badgeClass(st){\n if (st === 'running') return 'br';\n if (st === 'starting') return 'bs';\n if (st === 'killed') return 'bk';\n if (st === 'error') return 'berr';\n return 'be';\n}\nfunction fmtUptime(iso, end){\n if (!iso) return '';\n var start = Date.parse(iso);\n if (isNaN(start)) return '';\n var ref = end ? Date.parse(end) : Date.now();\n var s = Math.max(0, Math.round((ref - start) / 1000));\n if (s < 60) return s + 's';\n var m = Math.floor(s/60), rs = s%60;\n if (m < 60) return m + 'm ' + rs + 's';\n var h = Math.floor(m/60), rm = m%60;\n return h + 'h ' + rm + 'm';\n}\n\nfunction render(rows){\n var list = document.getElementById('list');\n if (!rows.length){\n list.innerHTML = '<div id=\"empty\"><div class=\"ico\">&#127760;</div><div>Aucune session navigateur</div></div>';\n return;\n }\n var html = '';\n for (var i=0;i<rows.length;i++){\n var s = rows[i];\n var bc = badgeClass(s.status);\n var url = s.browserBaseUrl || (s.browserPort ? ('http://127.0.0.1:' + s.browserPort) : '');\n var adapter = s.browserAdapterId || s.label || s.name || 'navigateur';\n var up = fmtUptime(s.startedAt, s.endedAt);\n html += '<div class=\"row\">'\n + '<div class=\"icon\">&#127760;</div>'\n + '<div class=\"body\">'\n + '<div class=\"r1\"><span class=\"adapter\">' + esc(adapter) + '</span>'\n + '<span class=\"badge ' + bc + '\">' + esc(s.status || '') + '</span></div>'\n + (url ? '<div class=\"url\">' + esc(url) + '</div>' : '')\n + '<div class=\"meta\">'\n + (s.browserPort ? '<span>port <span class=\"port\">' + esc(s.browserPort) + '</span></span><span class=\"dot\"></span>' : '')\n + '<span>' + (up ? 'uptime ' + esc(up) : '') + '</span>'\n + '</div>'\n + '</div>'\n + '</div>';\n }\n list.innerHTML = html;\n}\n\nfunction loadAndRender(){\n return callTool('list_sessions', {kind:'all'}).then(function(data){\n var all = data.sessions || [];\n var browsers = all.filter(function(s){ return s.kind === 'browser'; });\n render(browsers);\n setStatus(browsers.length + ' session' + (browsers.length===1?'':'s') + ' · ' + new Date().toLocaleTimeString('fr-FR'));\n }).catch(function(e){ setStatus('Erreur : ' + e.message); });\n}\n\nfunction doPoll(){\n if (polling) return;\n polling = true;\n loadAndRender().then(function(){\n polling = false;\n pollTimer = setTimeout(doPoll, REFRESH_MS);\n }).catch(function(){\n polling = false;\n pollTimer = setTimeout(doPoll, REFRESH_MS);\n });\n}\nfunction doRefresh(){ if (pollTimer) clearTimeout(pollTimer); return loadAndRender().then(function(){ pollTimer = setTimeout(doPoll, REFRESH_MS); }); }\n\ninitBridge().then(loadAndRender).then(function(){\n pollTimer = setTimeout(doPoll, REFRESH_MS);\n}).catch(function(e){\n setStatus('Bridge : ' + e.message);\n document.getElementById('list').innerHTML = '<div id=\"empty\"><div class=\"ico\">&#9888;</div><div>Échec connexion bridge : ' + esc(e.message) + '</div></div>';\n});\n</script>\n</body>\n</html>`\n","/**\n * HEARTBEAT.md autonomy loop.\n *\n * A workspace can ship a `HEARTBEAT.md` at its root. Frontmatter:\n *\n * schema: heartbeat/v1\n * agent: <id> (matches `<workspace>/.agents/<id>/AGENT.md`)\n * every: \"60s\" (Ns | Nm | Nh | Nd; cron support TODO)\n * enabled: true (default true; set false to register-but-skip)\n * conversation: heartbeat-{date} (templated id; defaults to per-day)\n *\n * Body = the prompt body the agent receives each tick. Reread fresh\n * on every tick so editing HEARTBEAT.md takes effect without restart.\n *\n * Ticks resolve the agent via the injected `buildAgent` callback,\n * call `agent.generate(prompt)`, and append the prompt + reply to a\n * conversation (default: daily-rolling `heartbeat-YYYY-MM-DD`).\n *\n * When the file is missing, frontmatter is invalid, `enabled: false`,\n * or the resolved agent has no usable model — the runner skips the\n * tick silently and emits a `heartbeat-error` event. The daemon\n * stays up.\n */\n\nimport matter from \"gray-matter\"\nimport { existsSync } from \"node:fs\"\nimport { readFile } from \"node:fs/promises\"\nimport { join } from \"node:path\"\nimport type { ConversationStore } from \"./conversations.js\"\nimport type { RuntimeEvents } from \"./events.js\"\n\nexport interface HeartbeatAgent {\n generate(prompt: string): Promise<{ text: string }>\n}\n\nexport interface BuildHeartbeatAgent {\n (id: string): Promise<HeartbeatAgent | null>\n}\n\nexport interface HeartbeatRunnerOptions {\n workspace: string\n conversations: ConversationStore\n events: RuntimeEvents\n /** Resolves a heartbeat-runnable agent from its workspace id. */\n buildAgent: BuildHeartbeatAgent\n /** Filename inside the workspace root. Default `HEARTBEAT.md`. */\n filename?: string\n /** Skip ticks while this returns false. Default: always true. */\n shouldFire?: () => boolean\n /** Override clock for tests. */\n now?: () => Date\n}\n\nexport interface HeartbeatRunner {\n /** Start the timer loop. Idempotent. */\n start(): void\n /** Stop the timer loop. Pending ticks finish out. */\n stop(): void\n /** Force-fire one tick now (used by `POST /heartbeat/tick`). */\n fireNow(): Promise<void>\n}\n\ninterface ParsedHeartbeat {\n agent: string\n everyMs: number\n enabled: boolean\n conversationTemplate: string\n body: string\n}\n\nexport function startHeartbeat(opts: HeartbeatRunnerOptions): HeartbeatRunner {\n const filename = opts.filename ?? \"HEARTBEAT.md\"\n const path = join(opts.workspace, filename)\n const now = opts.now ?? (() => new Date())\n\n let timer: NodeJS.Timeout | null = null\n let currentEveryMs: number | null = null\n let firing = false\n\n async function load(): Promise<ParsedHeartbeat | null> {\n if (!existsSync(path)) return null\n let source: string\n try {\n source = await readFile(path, \"utf8\")\n } catch {\n return null\n }\n const parsed = matter(source)\n const fm = parsed.data as Record<string, unknown>\n const agent = typeof fm.agent === \"string\" ? fm.agent : null\n if (!agent) return null\n const enabled = fm.enabled === undefined ? true : Boolean(fm.enabled)\n const everyRaw = typeof fm.every === \"string\" ? fm.every : \"60s\"\n const everyMs = parseDuration(everyRaw)\n if (!everyMs) return null\n const conversationTemplate =\n typeof fm.conversation === \"string\"\n ? fm.conversation\n : \"heartbeat-{date}\"\n return {\n agent,\n everyMs,\n enabled,\n conversationTemplate,\n body: parsed.content.trim(),\n }\n }\n\n async function tick(): Promise<void> {\n if (firing) return\n if (opts.shouldFire && !opts.shouldFire()) return\n firing = true\n let agentId: string | undefined\n try {\n const hb = await load()\n if (!hb || !hb.enabled) return\n agentId = hb.agent\n const agent = await opts.buildAgent(hb.agent)\n if (!agent) {\n opts.events.emit({\n type: \"heartbeat-error\",\n at: now().toISOString(),\n agent: hb.agent,\n error: `buildAgent('${hb.agent}') returned null`,\n })\n return\n }\n if (!hb.body) {\n opts.events.emit({\n type: \"heartbeat-error\",\n at: now().toISOString(),\n agent: hb.agent,\n error: \"HEARTBEAT.md body is empty\",\n })\n return\n }\n\n const conversationId = expandTemplate(hb.conversationTemplate, now())\n await opts.conversations.open(conversationId, { agent: hb.agent })\n\n const startedAt = now()\n await opts.conversations.appendTurn(\n conversationId,\n \"user\",\n hb.body,\n { at: startedAt.toISOString(), attribution: \"heartbeat\" },\n )\n opts.events.emit({\n type: \"conv-turn-appended\",\n at: startedAt.toISOString(),\n conversationId,\n role: \"user\",\n contentPreview: preview(hb.body),\n })\n\n const t0 = Date.now()\n const reply = await agent.generate(hb.body)\n const durationMs = Date.now() - t0\n\n const finishedAt = now()\n await opts.conversations.appendTurn(\n conversationId,\n \"assistant\",\n reply.text,\n { at: finishedAt.toISOString(), attribution: hb.agent },\n )\n opts.events.emit({\n type: \"conv-turn-appended\",\n at: finishedAt.toISOString(),\n conversationId,\n role: \"assistant\",\n contentPreview: preview(reply.text),\n })\n opts.events.emit({\n type: \"heartbeat-fired\",\n at: finishedAt.toISOString(),\n agent: hb.agent,\n conversationId,\n prompt: hb.body,\n reply: reply.text,\n durationMs,\n })\n\n // Adapt the timer if `every` changed since we started.\n if (currentEveryMs !== null && currentEveryMs !== hb.everyMs) {\n reschedule(hb.everyMs)\n }\n } catch (err) {\n opts.events.emit({\n type: \"heartbeat-error\",\n at: now().toISOString(),\n agent: agentId,\n error: err instanceof Error ? err.message : String(err),\n })\n } finally {\n firing = false\n }\n }\n\n function reschedule(everyMs: number): void {\n if (timer) clearInterval(timer)\n currentEveryMs = everyMs\n timer = setInterval(() => {\n void tick()\n }, everyMs)\n }\n\n return {\n start() {\n if (timer) return\n // Bootstrap interval from the file (or fall back to 60s if\n // unreadable — first real tick will refresh from disk).\n void load().then((hb) => {\n const everyMs = hb?.everyMs ?? 60_000\n reschedule(everyMs)\n })\n },\n stop() {\n if (timer) {\n clearInterval(timer)\n timer = null\n currentEveryMs = null\n }\n },\n async fireNow() {\n await tick()\n },\n }\n}\n\n// ── helpers ──────────────────────────────────────────────────────────\n\nconst DURATION_RE = /^(\\d+)\\s*(s|m|h|d)$/\n\n/**\n * Parse `Ns | Nm | Nh | Nd` into milliseconds. Returns `null` if the\n * string doesn't match. (AIP-41 supports more units, but the daemon's\n * heartbeat sticks to coarse durations to keep ticks observable.)\n */\nexport function parseDuration(input: string): number | null {\n const trimmed = input.trim()\n const match = trimmed.match(DURATION_RE)\n if (!match) return null\n const n = Number(match[1])\n if (!Number.isFinite(n) || n <= 0) return null\n switch (match[2]) {\n case \"s\":\n return n * 1_000\n case \"m\":\n return n * 60_000\n case \"h\":\n return n * 3_600_000\n case \"d\":\n return n * 86_400_000\n default:\n return null\n }\n}\n\n/**\n * Replace `{date}` with `YYYY-MM-DD` (UTC) in conversation templates.\n * Other tokens pass through unchanged — extend later if needed.\n */\nfunction expandTemplate(template: string, when: Date): string {\n const date = when.toISOString().slice(0, 10)\n return template.replace(/\\{date\\}/g, date)\n}\n\nfunction preview(text: string, max = 120): string {\n const flat = text.replace(/\\s+/g, \" \").trim()\n return flat.length > max ? `${flat.slice(0, max - 1)}…` : flat\n}\n","/**\n * Tiny node:http server that fronts the runtime gateway.\n *\n * Routes:\n * GET /health — { status, workspace, registered, uptime }\n * GET /events — SSE stream of RuntimeEvent\n * POST /mcp — MCP Streamable HTTP transport (POST)\n * GET /mcp — MCP SSE response stream (GET)\n * DELETE /mcp — close MCP session\n * GET /conversations — JSON list of conversation summaries\n * GET /conversations/<id> — markdown body of one conversation\n * POST /heartbeat/tick — force-fire one heartbeat tick\n *\n * No auth in `mode: \"none\"` (loopback default). `mode: \"bearer\"`\n * checks `Authorization: Bearer <token>` against the configured\n * token. Health is always public so external monitors can probe.\n *\n * MCP transport: stateless mode for v1 — each request is independent.\n * Stateful session pinning can come later when long-running streaming\n * tool calls become a real use case.\n */\n\nimport { createServer, type IncomingMessage, type Server, type ServerResponse } from \"node:http\"\nimport type { Duplex } from \"node:stream\"\nimport { mkdir, stat, writeFile } from \"node:fs/promises\"\nimport { isAbsolute, join, resolve as resolvePath } from \"node:path\"\nimport type { AcpMcpServer } from \"@agentproto/acp\"\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\"\nimport { StreamableHTTPServerTransport } from \"@modelcontextprotocol/sdk/server/streamableHttp.js\"\nimport { WebSocketServer, type WebSocket } from \"ws\"\nimport type { ConversationStore } from \"./conversations.js\"\nimport type { HeartbeatRunner } from \"./heartbeat.js\"\nimport type { RuntimeEvents, RuntimeEvent } from \"./events.js\"\nimport type { SessionsRegistry, AgentSessionLike } from \"./sessions.js\"\nimport type { TunnelRegistry } from \"./tunnel-registry.js\"\nimport {\n loadWorkspacesConfig,\n findWorkspace,\n getActiveWorkspace,\n} from \"./workspaces-config.js\"\nimport { discoverMcps } from \"./mcp-discovery.js\"\nimport type { McpProxyRegistry } from \"./mcp-proxy.js\"\nimport type {\n BrowserAdapterResolver,\n BrowserAdapterLister,\n} from \"./browser-tools.js\"\nimport type {\n OrchestratorScope,\n OrchestratorMcpServerFactory,\n} from \"./orchestrator-gateway.js\"\nimport {\n loadImportedMcps,\n saveImportedMcps,\n addImport,\n removeImport,\n} from \"./mcp-imports.js\"\nimport { exportAgentSession } from \"./transcript-export.js\"\n\n/**\n * Default Origin allowlist used when `RuntimeHttpServerOptions.allowedOrigins`\n * is undefined. Localhost on any port covers the user's own dev environments\n * (Guilde web dev server, playground demos, embedded panels). Production\n * origins (https://guilde.work, …) are NOT included by default — those are\n * opt-in via `agentproto serve --allow-origin <url>`.\n */\nconst DEFAULT_ALLOWED_ORIGINS: readonly string[] = [\n \"http://localhost:*\",\n \"http://127.0.0.1:*\",\n \"https://localhost:*\",\n]\n\n/**\n * Pluggable adapter resolver — keeps the runtime package free of any\n * @agentproto/cli dep. The host (cli `serve`, playground, embedding\n * apps) builds the resolver and hands it in. Returning null means\n * \"adapter not found\" → 404.\n */\nexport type AgentAdapterResolver = (slug: string) => Promise<{\n /** Build a fresh AgentSessionLike for the given cwd. The driver\n * spawns the adapter binary, opens the protocol, and the\n * registry holds the result.\n *\n * When `resumeSessionId` is set, the driver reattaches to that\n * pre-existing adapter session (claude-code's conversation id,\n * hermes' chat handle, …) rather than starting blank. Same\n * mechanism as `agentproto run --resume <id>` — exposed over\n * HTTP so `agentproto sessions restart` works on agent-cli\n * sessions, not just PTY ones. */\n startSession(opts: {\n cwd: string\n resumeSessionId?: string\n /** Model identifier forwarded from `start_agent_session`. For ACP\n * adapters this is applied via session/set_config_option after\n * newSession (the ACP wrapper does not forward CLI args to claude).\n * Adapters that don't support model selection ignore it. */\n model?: string\n /** Effort level forwarded from `start_agent_session`. Effort is\n * model-dependent — same label ≠ same budget across models; defaults\n * differ by model. Omit to keep the model's own default. Applied\n * via session/set_config_option on ACP adapters; others ignore it. */\n effort?: string\n /** MCP servers to mount into the spawned agent's session at spawn\n * time. Forwarded verbatim to the driver's `start({ mcpServers })`\n * → the ACP arm's `session/new.mcpServers`, giving the child agent\n * a host-chosen scoped toolset (e.g. the daemon's own orchestration\n * gateway). Adapters that don't model MCP mounting ignore it. */\n mcpServers?: AcpMcpServer[]\n }): Promise<AgentSessionLike>\n /** Display label for the descriptor's `command` field. */\n commandPreview?: string\n /** Best-effort per-session usage reader (adapter-specific, e.g. hermes state.db). */\n readUsage?: (adapterSessionId: string) => Promise<{ costUsd?: number; tokensIn?: number; tokensOut?: number } | null>\n} | null>\n\n/**\n * Compact adapter metadata for the discovery endpoints. Independent\n * of the resolver function above — hosts that can list installed\n * adapters wire this; hosts that can only resolve by-slug skip it\n * (the routes 501).\n */\nexport interface AdapterListEntry {\n slug: string\n name: string\n version: string\n description: string\n protocol: string\n streaming: boolean\n packageName: string\n}\n\nexport type AgentAdapterLister = () => Promise<AdapterListEntry[]>\n\nexport interface AuthOptions {\n mode: \"none\" | \"bearer\"\n token?: string\n}\n\n/**\n * Auth can be a fixed value (set at startup) or a getter (re-read on\n * every request). The getter form lets `remote_enable` flip bearer on\n * at runtime without restarting the gateway.\n */\nexport type AuthSource = AuthOptions | (() => AuthOptions)\n\nexport interface RuntimeHttpServerOptions {\n port: number\n bind?: string\n auth?: AuthSource\n /**\n * Per-request McpServer factory.\n *\n * The SDK's `StreamableHTTPServerTransport` is single-use — once a\n * transport has handled one request, the underlying `Protocol`\n * cannot be reattached, so subsequent requests on a shared transport\n * 500. The official stateless pattern (see SDK\n * `examples/server/simpleStatelessStreamableHttp.js`) builds a\n * fresh `McpServer` and `StreamableHTTPServerTransport` per request,\n * connects them, and tears both down on `res.close`. We follow that.\n *\n * The factory is invoked once per `/mcp` POST. It must register\n * tools / resources / prompts on the returned server before\n * resolving — by the time the transport's `handleRequest` fires,\n * the server is locked in.\n */\n mcpServerFactory: () => Promise<McpServer>\n /**\n * Optional scoped orchestrator sub-gateway (WP2). When BOTH this and\n * `verifyOrchestratorScope` are wired, the server mounts a second MCP\n * endpoint at `/mcp/orchestrator` that — unlike `/mcp` — has NO\n * loopback auth bypass: every request must present a valid scope-token\n * (`?scope=<token>` query or `X-Orchestrator-Scope` header). The token\n * resolves to a scope, and the factory builds a server exposing only\n * that scope's curated tool subset. This is what makes it safe to\n * point a child agent at the daemon (WP3 auto-injects the URL).\n */\n orchestratorMcpServerFactory?: OrchestratorMcpServerFactory\n /** Resolve a presented scope-token to its scope, or null when\n * unknown/missing. Paired with `orchestratorMcpServerFactory`. */\n verifyOrchestratorScope?: (\n token: string | null | undefined,\n ) => OrchestratorScope | null\n conversations: ConversationStore\n events: RuntimeEvents\n heartbeat: HeartbeatRunner\n /** Optional — when wired, exposes /sessions routes for the CLI\n * TUI and the guilde-web Active tab to navigate live child\n * processes. Daemons that don't spawn anything (pure MCP servers)\n * can omit this and the routes 404. */\n sessions?: SessionsRegistry\n /** Optional — when wired alongside `sessions`, enables\n * `POST /sessions/agent` and `POST /sessions/:id/prompt` routes.\n * Hosts that ship adapters (`agentproto serve`, playground)\n * pass the cli's `resolveAdapter` via a thin shim. */\n resolveAgentAdapter?: AgentAdapterResolver\n /** Optional — when wired, enables `GET /adapters` route + the\n * MCP `list_adapters` tool so UIs can discover what's installed\n * without trial-and-error against the resolver. Hosts ship the\n * cli's `listInstalledAdapters` via a thin shim. */\n listAgentAdapters?: AgentAdapterLister\n /** Optional — when wired alongside `sessions`, enables\n * `POST /sessions/browser` (same operation as MCP `start_browser`,\n * exposed as an HTTP route for the CLI surface). */\n resolveBrowserAdapter?: BrowserAdapterResolver\n /** Optional — passed to error messages on `POST /sessions/browser`\n * to list available adapter ids when the requested one isn't found. */\n listBrowserAdapters?: BrowserAdapterLister\n /** Optional — MCP proxy registry. When wired, exposes\n * `/mcps/proxy/*` routes that let the browser drive imported MCPs\n * without going through the MCP wire protocol (useful for the\n * /providers/mcp page's \"Local\" tab). */\n mcpProxy?: McpProxyRegistry\n /** Per-boot bearer token. When set, mutating /sessions/* routes\n * + the /sessions/:id/pty WebSocket upgrade require either\n * `Authorization: Bearer <token>` or an `Origin` header that\n * matches `allowedOrigins`. Read-only routes (GET, SSE stream)\n * stay open since the CORS surface already restricts origins\n * enough for them. */\n token?: string\n /** Trusted browser origins. When a mutating request carries an\n * `Origin: <url>` header (browser-set, JS can't forge), and that\n * url is in this list, the request is allowed without a Bearer\n * token. Browsers can't read the daemon's runtime.json (mode 0600)\n * so they can't send the token — Origin-based auth lets a trusted\n * page (Guilde web UI, local dev) drive the daemon. Non-browser\n * callers (curl, the CLI) still use the token.\n *\n * Match policy: exact origin (`https://guilde.work`) OR prefix\n * with `:*` for any-port match (`http://localhost:*` matches\n * `http://localhost:3000`).\n *\n * Default (when undefined): localhost on any port is allowed via\n * `DEFAULT_ALLOWED_ORIGINS`. Production origins are opt-in via\n * `agentproto serve --allow-origin <url>`. Pair with `strictOrigins`\n * to remove the localhost defaults entirely. */\n allowedOrigins?: readonly string[]\n /** When true, skip the localhost-wildcard defaults — only the\n * explicit `allowedOrigins` list is honoured. Useful for daemons\n * on shared hosts or when the user wants to lock dev to a\n * specific port. Default false (current behaviour — any browser\n * on `localhost` is trusted). */\n strictOrigins?: boolean\n /** Whether `POST /sessions/terminal` + WS upgrade are advertised.\n * Reflects whether the host injected a PTY factory into the\n * SessionsRegistry. When false, the terminal HTTP route returns\n * 501 and the WS upgrade rejects. */\n ptyEnabled?: boolean\n /** Optional — when wired, exposes /tunnels/* routes for creating and\n * managing public tunnels for local ports. Without it the routes 404. */\n tunnels?: TunnelRegistry\n /** Static fields surfaced via `/health`. */\n meta: {\n workspace: string\n registered: readonly string[]\n }\n}\n\nexport interface RuntimeHttpServerHandle {\n url: string\n stop(): Promise<void>\n}\n\nexport async function startHttpServer(\n opts: RuntimeHttpServerOptions,\n): Promise<RuntimeHttpServerHandle> {\n const startedAt = Date.now()\n const authSource: AuthSource = opts.auth ?? { mode: \"none\" }\n const readAuth = (): AuthOptions =>\n typeof authSource === \"function\" ? authSource() : authSource\n\n /**\n * Loopback bypass — requests originating from 127.0.0.1 / ::1 with\n * no `X-Forwarded-For` header skip the bearer check even when one is\n * configured. Rationale:\n *\n * 1. The bearer is meant to gate the *public tunnel*, not the\n * loopback socket. Without this, calling `remote_enable` from a\n * local MCP client immediately 401s that same local client —\n * the user locks themselves out and the only recovery is a\n * gateway restart. Hit this in real use; not a theoretical edge.\n *\n * 2. Cloudflared (and any reasonable tunnel) sets X-Forwarded-For\n * when forwarding a public request to the loopback origin. So\n * \"loopback AND no XFF\" is a tight characterisation of \"this\n * request never left the machine.\"\n *\n * 3. Local FS access already trumps bearer (the user can read\n * runtime.json, kill -9 the daemon, etc.). Adding another check\n * here doesn't raise the bar for someone with shell on the box.\n *\n * If your threat model is \"untrusted users on the same loopback\n * interface\" (unusual — usually a multi-tenant container scenario),\n * pass `auth: { mode: \"bearer\", … }` at startup instead of relying\n * on the controller's runtime flip; the auth getter will return the\n * stricter of the two and the bypass still applies (intentional —\n * the operator opted in to bearer with full knowledge of the trade).\n */\n function isLoopback(req: IncomingMessage): boolean {\n const addr = req.socket.remoteAddress ?? \"\"\n const isLocalAddr =\n addr === \"127.0.0.1\" || addr === \"::1\" || addr === \"::ffff:127.0.0.1\"\n if (!isLocalAddr) return false\n // X-Forwarded-For present ⇒ a tunnel is in front of us; the\n // request crossed the public internet to reach this socket.\n if (req.headers[\"x-forwarded-for\"]) return false\n return true\n }\n\n function authorize(req: IncomingMessage, res: ServerResponse): boolean {\n const auth = readAuth()\n if (auth.mode === \"none\") return true\n if (isLoopback(req)) return true\n const header = req.headers.authorization\n const expected = `Bearer ${auth.token}`\n if (header !== expected) {\n res.writeHead(401, { \"content-type\": \"application/json\" })\n res.end(JSON.stringify({ error: \"unauthorized\" }))\n return false\n }\n return true\n }\n\n /**\n * Per-boot auth gate for mutating /sessions/* routes and the WS\n * upgrade for /sessions/:id/pty. Accepts EITHER:\n *\n * 1. `Authorization: Bearer <token>` matching the per-boot token\n * (the CLI path — reads runtime.json mode 0600).\n * 2. A WS-upgrade query-string `?token=<token>` (browser\n * WebSocket can't set headers; some non-browser clients use\n * this too).\n * 3. An `Origin: <url>` header matching `allowedOrigins` — the\n * browser path. Origin is browser-set, JS can't forge.\n *\n * UNLIKE `authorize()`, this does NOT have a loopback bypass: the\n * threat we're defending against (browser drive-by spawning shells\n * via fetch to 127.0.0.1) IS loopback. Browsers can't read\n * runtime.json (mode 0600); a same-origin trusted page can rely on\n * its Origin instead.\n *\n * When `opts.token` is unset (older host integrations), this is a\n * no-op so existing call sites keep working.\n */\n function checkSessionsToken(req: IncomingMessage): \"ok\" | \"missing\" | \"bad\" {\n if (!opts.token) return \"ok\"\n\n // 1. Header bearer token.\n const header = req.headers.authorization\n const expected = `Bearer ${opts.token}`\n if (header === expected) return \"ok\"\n\n // 2. ?token=<token> in the URL (WS upgrade convenience).\n const urlStr = req.url ?? \"\"\n if (urlStr.includes(\"?\")) {\n const qs = new URLSearchParams(urlStr.slice(urlStr.indexOf(\"?\") + 1))\n const qsToken = qs.get(\"token\")\n if (qsToken && qsToken === opts.token) return \"ok\"\n }\n\n // 3. Origin allowlist (browser path).\n const origin = req.headers.origin\n if (typeof origin === \"string\" && originAllowed(origin)) return \"ok\"\n\n return header ? \"bad\" : \"missing\"\n }\n\n function originAllowed(origin: string): boolean {\n // Defaults are normally in effect — `opts.allowedOrigins` extends\n // them rather than replacing. Otherwise setting one production\n // origin via config silently locks out `http://localhost:*`,\n // breaking local dev. Users who genuinely want a curated list\n // (shared host, paranoid local-only ports) set `strictOrigins:true`\n // which drops the defaults entirely.\n const list = opts.strictOrigins\n ? (opts.allowedOrigins ?? [])\n : [...DEFAULT_ALLOWED_ORIGINS, ...(opts.allowedOrigins ?? [])]\n for (const pattern of list) {\n if (pattern === origin) return true\n // `http://localhost:*` style: match the host prefix, any port.\n if (pattern.endsWith(\":*\")) {\n const prefix = pattern.slice(0, -2) // drop \":*\"\n if (origin === prefix || origin.startsWith(prefix + \":\")) return true\n }\n }\n return false\n }\n\n function rejectUnauthorizedSession(\n req: IncomingMessage,\n res: ServerResponse,\n kind: \"missing\" | \"bad\",\n ): void {\n const origin = req.headers.origin ?? null\n const allowList = opts.strictOrigins\n ? (opts.allowedOrigins ?? [])\n : [...DEFAULT_ALLOWED_ORIGINS, ...(opts.allowedOrigins ?? [])]\n res.writeHead(401, { \"content-type\": \"application/json\" })\n const message =\n kind === \"missing\"\n ? origin\n ? `Origin \"${origin}\" not in the daemon's allowlist, and no Bearer token sent. ` +\n `Either add it (\\`agentproto config set daemon.allowedOrigins ${origin}\\` then restart the daemon), ` +\n `or send Authorization: Bearer <token> read from <workspace>/.agentproto/runtime.json.`\n : `Authorization: Bearer <token> required on mutating /sessions/* routes. ` +\n `Read the token from <workspace>/.agentproto/runtime.json. ` +\n `(Browser callers can use an Origin in the allowlist instead.)`\n : `Invalid bearer token. The daemon regenerated its token on its last boot — ` +\n `re-read <workspace>/.agentproto/runtime.json.`\n res.end(\n JSON.stringify({\n error: \"sessions_unauthorized\",\n message,\n // Debug data so a UI / network-tab inspection points the user\n // straight at the fix without needing the daemon's stderr.\n rejectedOrigin: origin,\n allowedOrigins: allowList,\n // We never echo the token; only the absence-or-presence flag.\n receivedAuthHeader: typeof req.headers.authorization === \"string\",\n }),\n )\n }\n\n /**\n * Returns true when this `path` + `method` is a mutating /sessions/*\n * route that should require the per-boot token. Kept narrow: GETs\n * (list, get, SSE stream) stay open for read-only telemetry from\n * existing tools that haven't learned about the token yet.\n */\n function isMutatingSessionsRoute(method: string, path: string): boolean {\n if (!path.startsWith(\"/sessions\")) return false\n if (method === \"POST\" || method === \"DELETE\" || method === \"PUT\" || method === \"PATCH\") {\n return true\n }\n return false\n }\n\n /**\n * Drive one MCP request over a fresh server+transport pair, per the\n * SDK's stateless pattern. Sharing either across requests breaks after\n * the first one because `Protocol.connect` rejects re-attachment.\n * Shared by `/mcp` and the scoped `/mcp/orchestrator` endpoint.\n */\n async function serveMcp(\n req: IncomingMessage,\n res: ServerResponse,\n server: McpServer,\n ): Promise<void> {\n const transport = new StreamableHTTPServerTransport({\n sessionIdGenerator: undefined,\n })\n // `onerror` is an unofficial SDK hook — guard before assigning so\n // a future SDK rename doesn't silently drop transport error logs.\n const transportInternal = transport as unknown as Record<string, unknown>\n if (\"onerror\" in (transport as object)) {\n transportInternal[\"onerror\"] = (err: unknown) => {\n console.error(\"[mcp transport.onerror]\", err)\n }\n }\n\n res.on(\"close\", () => {\n void transport.close()\n void server.close()\n })\n\n try {\n await server.connect(transport)\n await transport.handleRequest(req, res)\n } catch (err) {\n console.error(\"[mcp] handleRequest threw:\", err)\n if (!res.headersSent) {\n res.writeHead(500, { \"content-type\": \"application/json\" })\n res.end(\n JSON.stringify({\n error: \"mcp_transport_failed\",\n message: err instanceof Error ? err.message : String(err),\n }),\n )\n }\n }\n }\n\n async function handleMcp(req: IncomingMessage, res: ServerResponse): Promise<void> {\n if (!authorize(req, res)) return\n const server = await opts.mcpServerFactory()\n await serveMcp(req, res, server)\n }\n\n /**\n * Scoped orchestrator sub-gateway (WP2). Mounted at\n * `/mcp/orchestrator`. CRITICALLY this does NOT call `authorize()`:\n * the loopback bypass that makes `/mcp` open to any local process is\n * exactly what we must not inherit here — a child gets the\n * orchestration subset ONLY by presenting a valid scope-token. The\n * token arrives via `?scope=<token>` (the injected URL form) or the\n * `X-Orchestrator-Scope` header.\n */\n async function handleOrchestratorMcp(\n req: IncomingMessage,\n res: ServerResponse,\n ): Promise<void> {\n if (!opts.orchestratorMcpServerFactory || !opts.verifyOrchestratorScope) {\n res.writeHead(501, { \"content-type\": \"application/json\" })\n res.end(\n JSON.stringify({\n error: \"orchestrator_gateway_not_configured\",\n message:\n \"The daemon was started without the scoped orchestrator \" +\n \"sub-gateway. Wire `orchestratorMcpServerFactory` + \" +\n \"`verifyOrchestratorScope` in createGateway.\",\n }),\n )\n return\n }\n const urlStr = req.url ?? \"\"\n let token: string | null = null\n if (urlStr.includes(\"?\")) {\n token = new URLSearchParams(urlStr.slice(urlStr.indexOf(\"?\") + 1)).get(\n \"scope\",\n )\n }\n if (!token) {\n const headerTok = req.headers[\"x-orchestrator-scope\"]\n if (typeof headerTok === \"string\") token = headerTok\n }\n const scope = opts.verifyOrchestratorScope(token)\n if (!scope) {\n res.writeHead(401, { \"content-type\": \"application/json\" })\n res.end(\n JSON.stringify({\n error: \"orchestrator_scope_required\",\n message:\n \"A valid scope-token is required on /mcp/orchestrator \" +\n \"(pass `?scope=<token>` or the `X-Orchestrator-Scope` header). \" +\n \"Unlike /mcp, this endpoint has no loopback bypass.\",\n }),\n )\n return\n }\n const server = await opts.orchestratorMcpServerFactory(scope)\n await serveMcp(req, res, server)\n }\n\n function handleHealth(_req: IncomingMessage, res: ServerResponse): void {\n res.writeHead(200, { \"content-type\": \"application/json\" })\n res.end(\n JSON.stringify({\n status: \"ok\",\n workspace: opts.meta.workspace,\n registered: opts.meta.registered,\n uptimeMs: Date.now() - startedAt,\n }),\n )\n }\n\n function handleEvents(req: IncomingMessage, res: ServerResponse): void {\n if (!authorize(req, res)) return\n res.writeHead(200, {\n \"content-type\": \"text/event-stream\",\n \"cache-control\": \"no-cache, no-transform\",\n connection: \"keep-alive\",\n })\n res.write(`: connected\\n\\n`)\n const off = opts.events.onAny((ev: RuntimeEvent) => {\n res.write(`data: ${JSON.stringify(ev)}\\n\\n`)\n })\n req.on(\"close\", off)\n }\n\n async function handleListConversations(\n req: IncomingMessage,\n res: ServerResponse,\n ): Promise<void> {\n if (!authorize(req, res)) return\n const list = await opts.conversations.list()\n res.writeHead(200, { \"content-type\": \"application/json\" })\n res.end(JSON.stringify(list))\n }\n\n async function handleGetConversation(\n req: IncomingMessage,\n res: ServerResponse,\n id: string,\n ): Promise<void> {\n if (!authorize(req, res)) return\n try {\n const data = await opts.conversations.read(id)\n res.writeHead(200, { \"content-type\": \"application/json\" })\n res.end(JSON.stringify(data))\n } catch (err) {\n res.writeHead(404, { \"content-type\": \"application/json\" })\n res.end(\n JSON.stringify({\n error: \"not_found\",\n message: err instanceof Error ? err.message : String(err),\n }),\n )\n }\n }\n\n async function handleHeartbeatTick(\n req: IncomingMessage,\n res: ServerResponse,\n ): Promise<void> {\n if (!authorize(req, res)) return\n await opts.heartbeat.fireNow()\n res.writeHead(202, { \"content-type\": \"application/json\" })\n res.end(JSON.stringify({ status: \"fired\" }))\n }\n\n /**\n * POST /files/upload?cwd=<abs-dir>&name=<filename>\n *\n * Writes the raw request body bytes to\n * `{cwd}/.agentproto-attachments/{safe-name}`, creating the\n * subdirectory on demand, and returns `{path}` with the absolute\n * path the agent CLI can read. Used by the host UI's terminal\n * drag-drop: the browser can't read the dragged file's source path\n * (security), so we copy the bytes to a known location and tell the\n * UI to paste THAT path into the terminal — claude-code (and any\n * CLI with a Read tool) picks it up natively.\n *\n * Gated by `checkSessionsToken` so a drive-by HTTP request can't\n * write arbitrary files: only sessions-authorized callers (CLI or\n * an allow-listed browser origin) can hit it.\n *\n * Hardening:\n * - `cwd` must be absolute and exist as a directory.\n * - `name` is basename-sanitized (no `/`, `..`, NULs).\n * - The resolved write target must stay within\n * `{cwd}/.agentproto-attachments/` (defense-in-depth in case the\n * name sanitizer ever drifts).\n * - Body capped at 32 MiB. Larger uploads error 413 instead of\n * filling the daemon's disk.\n */\n async function handleFileUpload(\n req: IncomingMessage,\n res: ServerResponse,\n url: string,\n ): Promise<void> {\n const reply = (status: number, body: unknown): void => {\n res.writeHead(status, { \"content-type\": \"application/json\" })\n res.end(JSON.stringify(body))\n }\n const qs = new URLSearchParams(url.includes(\"?\") ? url.slice(url.indexOf(\"?\") + 1) : \"\")\n const cwd = qs.get(\"cwd\")\n const rawName = qs.get(\"name\")\n if (!cwd || !rawName) {\n reply(400, { error: \"missing_cwd_or_name\" })\n return\n }\n if (!isAbsolute(cwd)) {\n reply(400, { error: \"cwd_not_absolute\" })\n return\n }\n // basename-style sanitize: strip path separators + parent refs +\n // NUL bytes; collapse leading dots so the file is visible. The\n // resolvePath check below catches anything this misses.\n const safeName = rawName\n .replace(/[\\x00/\\\\]/g, \"_\")\n .replace(/\\.\\.+/g, \".\")\n .replace(/^\\.+/, \"\")\n .slice(0, 200)\n if (safeName.length === 0) {\n reply(400, { error: \"invalid_name\" })\n return\n }\n try {\n const st = await stat(cwd)\n if (!st.isDirectory()) {\n reply(400, { error: \"cwd_not_a_directory\" })\n return\n }\n } catch {\n reply(400, { error: \"cwd_not_found\" })\n return\n }\n const dir = join(cwd, \".agentproto-attachments\")\n const target = resolvePath(dir, safeName)\n // Defense-in-depth: the sanitized name should never escape `dir`,\n // but if the sanitizer ever drifts, this catches the escape.\n if (!target.startsWith(resolvePath(dir) + (dir.endsWith(\"/\") ? \"\" : \"/\"))) {\n reply(400, { error: \"path_traversal_blocked\" })\n return\n }\n const MAX_BYTES = 32 * 1024 * 1024 // 32 MiB\n const chunks: Buffer[] = []\n let total = 0\n let aborted = false\n await new Promise<void>((resolveBody, rejectBody) => {\n req.on(\"data\", chunk => {\n if (aborted) return\n const buf = chunk as Buffer\n total += buf.length\n if (total > MAX_BYTES) {\n aborted = true\n reply(413, { error: \"file_too_large\", maxBytes: MAX_BYTES })\n rejectBody(new Error(\"too_large\"))\n return\n }\n chunks.push(buf)\n })\n req.on(\"end\", () => {\n if (!aborted) resolveBody()\n })\n req.on(\"error\", err => rejectBody(err))\n }).catch(() => undefined)\n if (aborted) return\n try {\n await mkdir(dir, { recursive: true })\n await writeFile(target, Buffer.concat(chunks))\n reply(200, { path: target, bytes: total })\n } catch (err) {\n reply(500, {\n error: \"write_failed\",\n message: err instanceof Error ? err.message : String(err),\n })\n }\n }\n\n // Permissive CORS for the loopback gateway. The Guilde web app\n // (localhost:3041) probes /health from the browser; without these\n // headers the browser blocks the response and the panel says\n // \"not reachable\" even though curl works. Auth still gates the\n // sensitive routes — this just lifts the cross-origin block.\n //\n // Private Network Access (Chrome 105+): when an HTTPS page like\n // https://guilde.work fetches a loopback URL, Chrome sends a\n // preflight with `Access-Control-Request-Private-Network: true`.\n // Without `Access-Control-Allow-Private-Network: true` in the\n // response, the browser blocks the actual GET. Mirror the flag\n // when the request asked for it.\n function applyCors(req: IncomingMessage, res: ServerResponse): void {\n const origin = (req.headers.origin as string | undefined) ?? \"*\"\n res.setHeader(\"Access-Control-Allow-Origin\", origin)\n res.setHeader(\"Vary\", \"Origin\")\n res.setHeader(\"Access-Control-Allow-Credentials\", \"true\")\n res.setHeader(\n \"Access-Control-Allow-Headers\",\n req.headers[\"access-control-request-headers\"] ??\n \"authorization,content-type,mcp-session-id\",\n )\n res.setHeader(\n \"Access-Control-Allow-Methods\",\n \"GET,POST,PUT,PATCH,DELETE,OPTIONS\",\n )\n if (req.headers[\"access-control-request-private-network\"] === \"true\") {\n res.setHeader(\"Access-Control-Allow-Private-Network\", \"true\")\n }\n }\n\n const server: Server = createServer((req, res) => {\n void (async () => {\n try {\n const url = req.url ?? \"/\"\n const path = url.split(\"?\")[0] ?? \"/\"\n // Diagnostic: emit forwarded requests (those carrying XFF) onto\n // the events stream so /events tailers can see what cloudflared\n // actually sends. Loopback-only traffic stays quiet to avoid\n // flooding subscribers during normal local use.\n if (req.headers[\"x-forwarded-for\"]) {\n opts.events.emit({\n type: \"remote-log\",\n at: new Date().toISOString(),\n line: `[http-in] ${req.method} ${url} host=${req.headers.host ?? \"?\"} xff=${String(req.headers[\"x-forwarded-for\"])}`,\n })\n }\n\n applyCors(req, res)\n if (req.method === \"OPTIONS\") {\n res.writeHead(204)\n res.end()\n return\n }\n\n if (path === \"/health\" && req.method === \"GET\") {\n handleHealth(req, res)\n return\n }\n if (path === \"/events\" && req.method === \"GET\") {\n handleEvents(req, res)\n return\n }\n if (path === \"/mcp/orchestrator\") {\n await handleOrchestratorMcp(req, res)\n return\n }\n if (path === \"/mcp\") {\n await handleMcp(req, res)\n return\n }\n if (path === \"/conversations\" && req.method === \"GET\") {\n await handleListConversations(req, res)\n return\n }\n if (path.startsWith(\"/conversations/\") && req.method === \"GET\") {\n const id = path.slice(\"/conversations/\".length)\n await handleGetConversation(req, res, id)\n return\n }\n if (path === \"/heartbeat/tick\" && req.method === \"POST\") {\n await handleHeartbeatTick(req, res)\n return\n }\n\n if (path === \"/files/upload\" && req.method === \"POST\") {\n // Same auth gate as the mutating /sessions/* routes — drive-by\n // HTTP shouldn't be able to write arbitrary files to disk.\n const gate = checkSessionsToken(req)\n if (gate !== \"ok\") {\n rejectUnauthorizedSession(req, res, gate)\n return\n }\n await handleFileUpload(req, res, url)\n return\n }\n\n // Sessions routes — only registered when the gateway was\n // built with a SessionsRegistry. /sessions, /sessions/:id,\n // /sessions/:id/stream (SSE), POST /sessions/:id/kill,\n // DELETE /sessions/:id (forget after exit).\n if (opts.sessions && path.startsWith(\"/sessions\")) {\n if (isMutatingSessionsRoute(req.method ?? \"GET\", path)) {\n const gate = checkSessionsToken(req)\n if (gate !== \"ok\") {\n rejectUnauthorizedSession(req, res, gate)\n return\n }\n }\n const handled = await handleSessions(\n req,\n res,\n path,\n opts.sessions,\n opts.resolveAgentAdapter,\n opts.ptyEnabled === true,\n opts.resolveBrowserAdapter,\n opts.listBrowserAdapters,\n )\n if (handled) return\n }\n\n if (path === \"/workspaces\" && req.method === \"GET\") {\n // Surface ~/.agentproto/workspaces.json for UIs that\n // want a workspace dropdown (spawn dialog, MCP discovery\n // grouping, etc.). Read-only; mutate via the CLI's\n // `agentproto workspace add/remove/use` verbs.\n try {\n const config = await loadWorkspacesConfig()\n res.writeHead(200, { \"content-type\": \"application/json\" })\n res.end(JSON.stringify(config))\n } catch (err) {\n res.writeHead(500, { \"content-type\": \"application/json\" })\n res.end(\n JSON.stringify({\n error: \"workspaces_load_failed\",\n message: err instanceof Error ? err.message : String(err),\n })\n )\n }\n return\n }\n\n if (path === \"/mcps/imports\" && req.method === \"GET\") {\n const config = await loadImportedMcps()\n res.writeHead(200, { \"content-type\": \"application/json\" })\n res.end(JSON.stringify(config))\n return\n }\n if (path === \"/mcps/imports\" && req.method === \"POST\") {\n const body = (await readJsonBody(req)) as {\n sourceMcpId?: string\n alias?: string\n } | null\n if (!body || typeof body.sourceMcpId !== \"string\") {\n res.writeHead(400, { \"content-type\": \"application/json\" })\n res.end(JSON.stringify({ error: \"missing_sourceMcpId\" }))\n return\n }\n const discovered = await discoverMcps()\n const snapshot = discovered.find(d => d.id === body.sourceMcpId)\n if (!snapshot) {\n res.writeHead(404, { \"content-type\": \"application/json\" })\n res.end(\n JSON.stringify({\n error: \"discovered_mcp_not_found\",\n sourceMcpId: body.sourceMcpId,\n })\n )\n return\n }\n const cfg = await loadImportedMcps()\n const next = addImport(cfg, {\n snapshot,\n ...(body.alias ? { alias: body.alias } : {}),\n })\n await saveImportedMcps(next)\n res.writeHead(201, { \"content-type\": \"application/json\" })\n res.end(JSON.stringify(next.imports.find(e => e.id === snapshot.id)))\n return\n }\n const importMatch = path.match(/^\\/mcps\\/imports\\/(.+)$/)\n if (importMatch && req.method === \"DELETE\") {\n // The id is URL-encoded since it contains colons + slashes\n // (e.g. claude-code:project:/path:name).\n const id = decodeURIComponent(importMatch[1] ?? \"\")\n const cfg = await loadImportedMcps()\n if (!cfg.imports.some(e => e.id === id)) {\n res.writeHead(404, { \"content-type\": \"application/json\" })\n res.end(JSON.stringify({ error: \"import_not_found\", id }))\n return\n }\n await saveImportedMcps(removeImport(cfg, id))\n res.writeHead(200, { \"content-type\": \"application/json\" })\n res.end(JSON.stringify({ ok: true, id }))\n return\n }\n\n if (path === \"/mcps/discovered\" && req.method === \"GET\") {\n // No host wiring needed — the scanner reads\n // ~/.claude.json + ~/.cursor/mcp.json + goose config\n // directly. Always available; cheap (~5ms typical).\n try {\n const mcps = await discoverMcps()\n res.writeHead(200, { \"content-type\": \"application/json\" })\n res.end(JSON.stringify({ mcps }))\n } catch (err) {\n res.writeHead(500, { \"content-type\": \"application/json\" })\n res.end(\n JSON.stringify({\n error: \"discovery_failed\",\n message: err instanceof Error ? err.message : String(err),\n })\n )\n }\n return\n }\n\n // Browser-friendly proxy surface — same operations the MCP\n // tools expose (mcp_imported_status / list_tools / call) but\n // over plain HTTP so the /providers/mcp page can render them\n // without embedding an MCP client.\n if (path === \"/mcps/proxy/status\" && req.method === \"GET\") {\n if (!opts.mcpProxy) {\n res.writeHead(501, { \"content-type\": \"application/json\" })\n res.end(JSON.stringify({ error: \"mcp_proxy_not_configured\" }))\n return\n }\n try {\n const imports = await opts.mcpProxy.listAliases()\n res.writeHead(200, { \"content-type\": \"application/json\" })\n res.end(JSON.stringify({ imports }))\n } catch (err) {\n res.writeHead(500, { \"content-type\": \"application/json\" })\n res.end(\n JSON.stringify({\n error: \"proxy_status_failed\",\n message: err instanceof Error ? err.message : String(err),\n })\n )\n }\n return\n }\n const proxyToolsMatch = path.match(/^\\/mcps\\/proxy\\/tools\\/(.+)$/)\n if (proxyToolsMatch && req.method === \"GET\") {\n if (!opts.mcpProxy) {\n res.writeHead(501, { \"content-type\": \"application/json\" })\n res.end(JSON.stringify({ error: \"mcp_proxy_not_configured\" }))\n return\n }\n const alias = decodeURIComponent(proxyToolsMatch[1] ?? \"\")\n const out = await opts.mcpProxy.listTools(alias)\n res.writeHead(out.ok ? 200 : 502, {\n \"content-type\": \"application/json\",\n })\n res.end(JSON.stringify(out))\n return\n }\n if (path === \"/mcps/proxy/call\" && req.method === \"POST\") {\n if (!opts.mcpProxy) {\n res.writeHead(501, { \"content-type\": \"application/json\" })\n res.end(JSON.stringify({ error: \"mcp_proxy_not_configured\" }))\n return\n }\n const body = (await readJsonBody(req)) as {\n alias?: unknown\n toolName?: unknown\n args?: unknown\n } | null\n if (\n !body ||\n typeof body.alias !== \"string\" ||\n typeof body.toolName !== \"string\"\n ) {\n res.writeHead(400, { \"content-type\": \"application/json\" })\n res.end(\n JSON.stringify({\n error: \"invalid_body\",\n message: \"expected { alias, toolName, args? }\",\n })\n )\n return\n }\n const result = await opts.mcpProxy.callTool(\n body.alias,\n body.toolName,\n body.args ?? {}\n )\n res.writeHead(result.ok ? 200 : 502, {\n \"content-type\": \"application/json\",\n })\n res.end(JSON.stringify(result))\n return\n }\n\n if (path === \"/adapters\" && req.method === \"GET\") {\n if (!opts.listAgentAdapters) {\n res.writeHead(501, { \"content-type\": \"application/json\" })\n res.end(\n JSON.stringify({\n error: \"lister_not_configured\",\n message:\n \"Daemon was started without `listAgentAdapters` — see \" +\n \"@agentproto/cli's `listInstalledAdapters` for the canonical impl.\",\n })\n )\n return\n }\n try {\n const adapters = await opts.listAgentAdapters()\n res.writeHead(200, { \"content-type\": \"application/json\" })\n res.end(JSON.stringify({ adapters }))\n } catch (err) {\n res.writeHead(500, { \"content-type\": \"application/json\" })\n res.end(\n JSON.stringify({\n error: \"list_failed\",\n message: err instanceof Error ? err.message : String(err),\n })\n )\n }\n return\n }\n\n // Tunnel routes — only registered when the gateway was built with\n // a TunnelRegistry. /tunnels, /tunnels/:id.\n if (opts.tunnels && path.startsWith(\"/tunnels\")) {\n const handled = await handleTunnels(req, res, path, opts.tunnels)\n if (handled) return\n }\n\n res.writeHead(404, { \"content-type\": \"application/json\" })\n res.end(JSON.stringify({ error: \"not_found\", path }))\n } catch (err) {\n if (!res.headersSent) {\n res.writeHead(500, { \"content-type\": \"application/json\" })\n res.end(\n JSON.stringify({\n error: \"internal_error\",\n message: err instanceof Error ? err.message : String(err),\n }),\n )\n }\n }\n })()\n })\n\n // ── WebSocket upgrade: /sessions/:id/pty ──\n // Single WSS bound to the HTTP server's `upgrade` event. Connections\n // are accepted only when the SessionsRegistry is wired AND PTY\n // support is advertised. Frames are JSON-encoded over text WS\n // messages (binary mode is a future optimization — JSON keeps\n // wireshark/devtools debuggable):\n // server → client: {kind:\"data\", b64:\"...\"}\n // server → client: {kind:\"exit\", exitCode:0, signal?:1}\n // client → server: {kind:\"input\", b64:\"...\"} (or {kind:\"input\", text:\"...\"})\n // client → server: {kind:\"resize\", cols:80, rows:24}\n // client → server: {kind:\"ping\"} (no-op keepalive)\n const wss = new WebSocketServer({ noServer: true })\n server.on(\"upgrade\", (req, socket, head) => {\n const url = req.url ?? \"/\"\n const path = url.split(\"?\")[0] ?? \"/\"\n const ptyMatch = path.match(/^\\/sessions\\/([^/]+)\\/pty$/)\n if (!ptyMatch) {\n socket.destroy()\n return\n }\n if (!opts.sessions || opts.ptyEnabled !== true) {\n rejectUpgrade(socket, 501, \"pty_not_configured\")\n return\n }\n // Per-boot token gate, no loopback bypass — see comment on\n // checkSessionsToken for why.\n const gate = checkSessionsToken(req)\n if (gate !== \"ok\") {\n rejectUpgrade(socket, 401, gate === \"missing\" ? \"missing_token\" : \"bad_token\")\n return\n }\n const id = ptyMatch[1]\n if (!id) {\n rejectUpgrade(socket, 400, \"missing_id\")\n return\n }\n // Resolve id-or-name BEFORE upgrading so a typo returns a clean\n // 404 instead of a successful WS that immediately closes.\n const desc = opts.sessions.findByIdOrName(id)\n if (!desc) {\n rejectUpgrade(socket, 404, \"session_not_found\")\n return\n }\n if (desc.pty !== true) {\n rejectUpgrade(socket, 400, \"session_not_pty\")\n return\n }\n // A descriptor for an exited/killed/error session lives on as\n // history — its PTY child is gone. Reject the upgrade with a\n // clear reason so the CLI/web client can suggest `restart`\n // instead of letting the user see a generic 1011 mid-attach.\n if (\n desc.status === \"exited\" ||\n desc.status === \"killed\" ||\n desc.status === \"error\"\n ) {\n rejectUpgrade(\n socket,\n 410,\n `session_${desc.status}`,\n `Session ${desc.id}${desc.name ? ` (${desc.name})` : \"\"} has ${desc.status}. ` +\n `Spawn a fresh one with: agentproto sessions restart ${desc.name ?? desc.id}`,\n )\n return\n }\n wss.handleUpgrade(req, socket, head, ws => {\n handlePtyWebSocket(ws, req, desc.id, opts.sessions!)\n })\n })\n\n const bind = opts.bind ?? \"127.0.0.1\"\n await new Promise<void>((resolve, reject) => {\n server.once(\"error\", reject)\n server.listen(opts.port, bind, () => resolve())\n })\n\n return {\n url: `http://${bind}:${opts.port}`,\n async stop() {\n // Per-request transports/servers are torn down on `res.close`,\n // so we only need to stop the HTTP listener here. The WSS is\n // bound `noServer:true` so closing the HTTP server also tears\n // down its underlying TCP socket; live WS connections receive\n // a close frame from the kernel.\n wss.close()\n await new Promise<void>((resolve) => server.close(() => resolve()))\n },\n }\n}\n\n/**\n * Reject an HTTP upgrade attempt with a structured plaintext body.\n * `ws.handleUpgrade` is meant to be the success path — if we can't\n * accept the upgrade we write a minimal HTTP response and destroy\n * the socket, matching ws's own internal error path.\n */\nfunction rejectUpgrade(\n socket: Duplex,\n status: number,\n reason: string,\n message?: string,\n): void {\n const reasonText = `${status} ${reason}`\n const body: { error: string; message?: string } = { error: reason }\n if (message) body.message = message\n try {\n socket.write(\n `HTTP/1.1 ${reasonText}\\r\\n` +\n `Content-Type: application/json\\r\\n` +\n `Connection: close\\r\\n\\r\\n` +\n JSON.stringify(body) +\n `\\n`,\n )\n } catch {\n // socket already gone — fall through\n }\n socket.destroy()\n}\n\n/**\n * Per-connection WS handler for /sessions/:id/pty. Attaches as a\n * subscriber to the SessionsRegistry; bridges JSON frames in both\n * directions. Per-subscriber backpressure: if the WS's `bufferedAmount`\n * exceeds a threshold, the next chunk is dropped (slow client must\n * not stall the daemon's fan-out to other subscribers).\n */\nfunction handlePtyWebSocket(\n ws: WebSocket,\n req: IncomingMessage,\n sessionId: string,\n registry: SessionsRegistry,\n): void {\n // Parse cols/rows from the query string for the initial dimension\n // hint. Real clients will send a {kind:\"resize\"} immediately after\n // connecting; this seeds the registry's min-size calculation so the\n // first replay frames render at a sensible width if no resize comes.\n const query = new URLSearchParams(\n (req.url ?? \"\").includes(\"?\") ? (req.url ?? \"\").split(\"?\")[1] : \"\",\n )\n const cols = clampPositiveInt(query.get(\"cols\"), 80)\n const rows = clampPositiveInt(query.get(\"rows\"), 24)\n\n // Backpressure threshold — when the socket has more than 256 KiB\n // queued, drop the next data frame for THIS subscriber rather than\n // letting the registry block on send. Other subscribers stay live.\n const BACKPRESSURE_BYTES = 256 * 1024\n\n const handle = registry.attachPty(\n sessionId,\n { cols, rows },\n chunk => {\n if (ws.readyState !== ws.OPEN) return\n if (ws.bufferedAmount > BACKPRESSURE_BYTES) return // drop\n ws.send(\n JSON.stringify({ kind: \"data\", b64: chunk.toString(\"base64\") }),\n )\n },\n evt => {\n if (ws.readyState !== ws.OPEN) return\n ws.send(\n JSON.stringify({\n kind: \"exit\",\n exitCode: evt.exitCode,\n ...(evt.signal != null ? { signal: evt.signal } : {}),\n }),\n )\n // Close ourselves once we've emitted exit — the session can be\n // reattached for a buffer replay but this socket is done.\n try {\n ws.close(1000, \"session exited\")\n } catch {\n // ignore\n }\n },\n )\n\n if (!handle) {\n // Race: the session may have vanished between the upgrade and\n // attach. Close politely.\n try {\n ws.close(1011, \"session not attachable\")\n } catch {\n // ignore\n }\n return\n }\n\n ws.on(\"message\", (raw, isBinary) => {\n if (isBinary) {\n // Binary frames not supported yet — wire format is JSON-only.\n return\n }\n let frame: unknown\n try {\n frame = JSON.parse(raw.toString(\"utf8\"))\n } catch {\n return // malformed\n }\n if (!frame || typeof frame !== \"object\") return\n const f = frame as Record<string, unknown>\n switch (f.kind) {\n case \"input\": {\n // Accept either {text} (UTF-8) or {b64} (arbitrary bytes,\n // useful for clients sending raw key sequences).\n if (typeof f.text === \"string\") {\n handle.write(f.text)\n } else if (typeof f.b64 === \"string\") {\n try {\n handle.write(Buffer.from(f.b64, \"base64\").toString(\"utf8\"))\n } catch {\n // ignore malformed base64\n }\n }\n break\n }\n case \"resize\": {\n const c =\n typeof f.cols === \"number\" && f.cols > 0 ? Math.floor(f.cols) : null\n const r =\n typeof f.rows === \"number\" && f.rows > 0 ? Math.floor(f.rows) : null\n if (c && r) handle.resize(c, r)\n break\n }\n case \"ping\":\n // Reply with pong so client keepalive logic works. Optional.\n try {\n ws.send(JSON.stringify({ kind: \"pong\" }))\n } catch {\n // ignore\n }\n break\n // Unknown kinds silently dropped; reserved for forward compat.\n }\n })\n\n ws.on(\"close\", () => {\n handle.detach()\n })\n ws.on(\"error\", () => {\n handle.detach()\n })\n}\n\nfunction clampPositiveInt(raw: string | null, fallback: number): number {\n if (!raw) return fallback\n const n = Number.parseInt(raw, 10)\n return Number.isFinite(n) && n > 0 ? n : fallback\n}\n\nfunction clampInt(\n raw: string | null,\n fallback: number,\n min: number,\n max: number,\n): number {\n if (!raw) return fallback\n const n = Number.parseInt(raw, 10)\n if (!Number.isFinite(n)) return fallback\n if (n < min) return min\n if (n > max) return max\n return n\n}\n\n/**\n * /sessions routes — split out of the main switch so the surface\n * stays scannable. Returns `true` when it handled the request, so\n * the dispatcher knows to skip the 404 path.\n *\n * GET /sessions → list of SessionDescriptor[]\n * GET /sessions/:id → one SessionDescriptor\n * GET /sessions/:id/stream → SSE stream {line,stream} events\n * GET /sessions/:id/export → ExportAgentSessionResult (transcript as markdown or JSON)\n * POST /sessions/:id/kill → SIGTERM, returns {ok}\n * DELETE /sessions/:id → forget (drop from registry; only\n * valid for exited/killed/error)\n * POST /sessions/browser → start a browser adapter and register\n * as a tracked session; body:\n * { adapter, port?, camofoxPort?, label?,\n * location?, baseUrl?, binPath? }\n * (requires `resolveBrowserAdapter` wired)\n */\nasync function handleSessions(\n req: IncomingMessage,\n res: ServerResponse,\n path: string,\n registry: SessionsRegistry,\n resolveAgentAdapter?: AgentAdapterResolver,\n ptyEnabled = false,\n resolveBrowserAdapter?: BrowserAdapterResolver,\n listBrowserAdapters?: BrowserAdapterLister,\n): Promise<boolean> {\n const json = (status: number, body: unknown): void => {\n res.writeHead(status, { \"content-type\": \"application/json\" })\n res.end(JSON.stringify(body))\n }\n\n if (path === \"/sessions\" && req.method === \"GET\") {\n json(200, { sessions: registry.list() })\n return true\n }\n\n // Long-running agent session — spawn via the cli's adapter\n // resolver, hold across multiple turns. Body shape:\n // {adapter: \"claude-code\"|\"hermes\"|...,\n // workspaceSlug, cwd, prompt?, label?}\n if (path === \"/sessions/agent\" && req.method === \"POST\") {\n if (!resolveAgentAdapter) {\n json(501, {\n error: \"agent_resolver_not_configured\",\n message:\n \"POST /sessions/agent needs the host to inject `resolveAgentAdapter` \" +\n \"(e.g. via @agentproto/cli's resolveAdapter shim).\",\n })\n return true\n }\n const body = await readJsonBody(req)\n if (!body || typeof body !== \"object\") {\n json(400, { error: \"invalid_body\" })\n return true\n }\n const b = body as Record<string, unknown>\n const adapter = typeof b.adapter === \"string\" ? b.adapter : \"\"\n if (!adapter) {\n json(400, { error: \"missing_adapter\" })\n return true\n }\n // cwd resolution priority:\n // 1. explicit `cwd` in the body\n // 2. lookup `workspaceSlug` in ~/.agentproto/workspaces.json\n // 3. active workspace from the same config\n // 4. process.cwd() (last resort, almost certainly not what\n // the user wants — log it so the operator notices)\n let cwd: string | null =\n typeof b.cwd === \"string\" && b.cwd.length > 0 ? b.cwd : null\n let workspaceSlug =\n typeof b.workspaceSlug === \"string\" ? b.workspaceSlug : \"\"\n if (!cwd) {\n try {\n const config = await loadWorkspacesConfig()\n const ws = workspaceSlug\n ? findWorkspace(config, workspaceSlug)\n : getActiveWorkspace(config)\n if (ws) {\n cwd = ws.path\n workspaceSlug = ws.slug\n }\n } catch {\n // Config missing / unreadable — fall through to process.cwd()\n }\n }\n if (!cwd) {\n cwd = process.cwd()\n console.warn(\n `[/sessions/agent] no cwd resolvable for adapter=${adapter} ` +\n `(no body.cwd, no workspaceSlug match in ~/.agentproto/workspaces.json, ` +\n `no active workspace) — falling back to daemon's cwd ${cwd}`\n )\n }\n if (!workspaceSlug) workspaceSlug = \"default\"\n const resolved = await resolveAgentAdapter(adapter)\n if (!resolved) {\n json(404, { error: \"adapter_not_found\", adapter })\n return true\n }\n try {\n const resumeSessionId =\n typeof b.resumeSessionId === \"string\" && b.resumeSessionId.length > 0\n ? b.resumeSessionId\n : undefined\n const bodyModel = typeof b.model === \"string\" && b.model.length > 0\n ? b.model\n : undefined\n const bodyEffort = typeof b.effort === \"string\" && b.effort.length > 0\n ? b.effort\n : undefined\n const agentSession = await resolved.startSession({\n cwd,\n ...(resumeSessionId ? { resumeSessionId } : {}),\n ...(bodyModel ? { model: bodyModel } : {}),\n ...(bodyEffort ? { effort: bodyEffort } : {}),\n })\n const desc = registry.spawnAgent({\n workspaceSlug,\n cwd,\n agentSession,\n adapterSlug: adapter,\n ...(typeof b.prompt === \"string\" ? { initialPrompt: b.prompt } : {}),\n ...(typeof b.label === \"string\" ? { label: b.label } : {}),\n ...(resolved.commandPreview\n ? { commandPreview: resolved.commandPreview }\n : {}),\n })\n json(201, desc)\n } catch (err) {\n json(500, {\n error: \"agent_spawn_failed\",\n message: err instanceof Error ? err.message : String(err),\n })\n }\n return true\n }\n\n // Browser service session — start the adapter and register as a tracked\n // session. HTTP equivalent of the MCP `start_browser` tool.\n // Body: { adapter: string, port?: number, camofoxPort?: number, label?: string,\n // location?: \"local\"|\"cloud\", baseUrl?: string, binPath?: string }\n if (path === \"/sessions/browser\" && req.method === \"POST\") {\n if (!resolveBrowserAdapter) {\n json(501, {\n error: \"browser_resolver_not_configured\",\n message:\n \"POST /sessions/browser needs the host to inject `resolveBrowserAdapter` \" +\n \"(e.g. via `agentproto serve`).\",\n })\n return true\n }\n const body = await readJsonBody(req)\n if (!body || typeof body !== \"object\") {\n json(400, { error: \"invalid_body\" })\n return true\n }\n const b = body as Record<string, unknown>\n const adapterId = typeof b.adapter === \"string\" ? b.adapter : \"\"\n if (!adapterId) {\n json(400, { error: \"missing_adapter\" })\n return true\n }\n const rawPort = b.port\n if (rawPort !== undefined) {\n const p = typeof rawPort === \"number\" ? rawPort : Number(rawPort)\n if (!Number.isInteger(p) || p < 1 || p > 65535) {\n json(400, {\n error: \"invalid_port\",\n message: `port must be an integer in range 1–65535 (got ${JSON.stringify(rawPort)})`,\n })\n return true\n }\n }\n const rawCamofoxPort = b.camofoxPort\n if (rawCamofoxPort !== undefined) {\n const p = typeof rawCamofoxPort === \"number\" ? rawCamofoxPort : Number(rawCamofoxPort)\n if (!Number.isInteger(p) || p < 1 || p > 65535) {\n json(400, {\n error: \"invalid_camofox_port\",\n message: `camofoxPort must be an integer in range 1–65535 (got ${JSON.stringify(rawCamofoxPort)})`,\n })\n return true\n }\n }\n const adapter = resolveBrowserAdapter(adapterId)\n if (!adapter) {\n const available = listBrowserAdapters\n ? listBrowserAdapters()\n .map(a => a.id)\n .join(\", \")\n : \"camofox, bureau\"\n json(404, {\n error: \"adapter_not_found\",\n adapter: adapterId,\n message: `Browser adapter \"${adapterId}\" not found. Available: ${available}.`,\n })\n return true\n }\n const rawLocation = b.location\n if (rawLocation !== undefined && rawLocation !== \"local\" && rawLocation !== \"cloud\") {\n json(400, {\n error: \"invalid_location\",\n message: `location must be \"local\" or \"cloud\" (got ${JSON.stringify(rawLocation)})`,\n })\n return true\n }\n const location = rawLocation as \"local\" | \"cloud\" | undefined\n const baseUrl = typeof b.baseUrl === \"string\" ? b.baseUrl : undefined\n const binPath = typeof b.binPath === \"string\" ? b.binPath : undefined\n try {\n const instance = await adapter.ensure({\n port: typeof b.port === \"number\" ? b.port : undefined,\n camofoxPort: typeof b.camofoxPort === \"number\" ? b.camofoxPort : undefined,\n location,\n baseUrl,\n binPath,\n initialWaitMs: 6_000,\n })\n const desc = registry.registerBrowser({\n adapterId: instance.id,\n port: instance.port,\n baseUrl: instance.baseUrl,\n location: location ?? adapter.location,\n pid: instance.pid,\n wasAlreadyRunning: instance.wasAlreadyRunning,\n status: instance.healthy ? \"running\" : \"starting\",\n stop: instance.stop.bind(instance),\n label: typeof b.label === \"string\" ? b.label : undefined,\n })\n json(201, desc)\n } catch (err) {\n json(500, {\n error: \"browser_start_failed\",\n message: err instanceof Error ? err.message : String(err),\n })\n }\n return true\n }\n\n // Long-running PTY session — spawn argv under node-pty. Bytes flow\n // through the registry's byte ring buffer; attach via the WebSocket\n // upgrade at /sessions/:id/pty. Body shape:\n // {argv: string[], cwd?, workspaceSlug?, cols, rows, env?, name?, label?}\n if (path === \"/sessions/terminal\" && req.method === \"POST\") {\n if (!ptyEnabled) {\n json(501, {\n error: \"pty_not_configured\",\n message:\n \"POST /sessions/terminal needs the host to inject `spawnPty` into createGateway \" +\n \"(node-pty optional dep — install in @agentproto/cli).\",\n })\n return true\n }\n const body = await readJsonBody(req)\n if (!body || typeof body !== \"object\") {\n json(400, { error: \"invalid_body\" })\n return true\n }\n const b = body as Record<string, unknown>\n const argv = Array.isArray(b.argv)\n ? (b.argv as unknown[]).filter((v): v is string => typeof v === \"string\")\n : []\n if (argv.length === 0) {\n json(400, { error: \"missing_argv\" })\n return true\n }\n const cols = typeof b.cols === \"number\" && b.cols > 0 ? Math.floor(b.cols) : 80\n const rows = typeof b.rows === \"number\" && b.rows > 0 ? Math.floor(b.rows) : 24\n // cwd resolution mirrors /sessions/agent exactly.\n let cwd: string | null =\n typeof b.cwd === \"string\" && b.cwd.length > 0 ? b.cwd : null\n let workspaceSlug =\n typeof b.workspaceSlug === \"string\" ? b.workspaceSlug : \"\"\n if (!cwd) {\n try {\n const config = await loadWorkspacesConfig()\n const ws = workspaceSlug\n ? findWorkspace(config, workspaceSlug)\n : getActiveWorkspace(config)\n if (ws) {\n cwd = ws.path\n workspaceSlug = ws.slug\n }\n } catch {\n // fall through to process.cwd()\n }\n }\n if (!cwd) {\n cwd = process.cwd()\n console.warn(\n `[/sessions/terminal] no cwd resolvable for argv=${argv.join(\" \")} ` +\n `— falling back to daemon's cwd ${cwd}`\n )\n }\n if (!workspaceSlug) workspaceSlug = \"default\"\n try {\n const desc = registry.spawnPty({\n argv,\n cwd,\n workspaceSlug,\n cols,\n rows,\n ...(b.env && typeof b.env === \"object\"\n ? { env: b.env as Record<string, string> }\n : {}),\n ...(typeof b.name === \"string\" ? { name: b.name } : {}),\n ...(typeof b.label === \"string\" ? { label: b.label } : {}),\n })\n json(201, desc)\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err)\n const status = msg.includes(\"already in use\")\n ? 409\n : msg.includes(\"no PTY factory\")\n ? 501\n : 500\n json(status, { error: \"pty_spawn_failed\", message: msg })\n }\n return true\n }\n\n // Send a follow-up turn to a live agent session.\n // Body: { prompt: string | ContentBlock | ContentBlock[] }\n // - string → auto-wrapped to a single text block by\n // the registry (legacy / convenience).\n // - ContentBlock → e.g. `{type:\"image\", source:{...}}`\n // - ContentBlock[] → text + image mix for multimodal turns.\n // Forwarded as-is to `agentSession.send`\n // so the adapter (claude-agent-acp, …)\n // negotiates its own content shape.\n //\n // Validation is intentionally loose — we accept anything object-\n // shaped + non-empty arrays + non-empty strings. The adapter will\n // reject ill-formed blocks with a clear error projected into the\n // session's ring buffer; throwing here would just duplicate that.\n //\n // Query: ?wait=false → fire-and-forget (return 202 after sync\n // validation; output streams via /sessions/:id/stream). Default\n // wait=true keeps the call blocking until the turn drains, which\n // is what curl scripts + the MCP bridge expect.\n const promptMatch = path.match(/^\\/sessions\\/([^/]+)\\/prompt$/)\n if (promptMatch && req.method === \"POST\") {\n const id = promptMatch[1]\n if (!id) return false\n const body = await readJsonBody(req)\n const prompt = (body as { prompt?: unknown } | null)?.prompt\n const validPrompt =\n (typeof prompt === \"string\" && prompt.length > 0) ||\n (Array.isArray(prompt) &&\n prompt.length > 0 &&\n prompt.every(b => b !== null && typeof b === \"object\")) ||\n (prompt !== null && typeof prompt === \"object\" && !Array.isArray(prompt))\n if (!validPrompt) {\n json(400, {\n error: \"missing_prompt\",\n message:\n \"Body `prompt` must be a non-empty string, a content block object, or an array of content blocks.\",\n })\n return true\n }\n const reqUrl = req.url ?? \"\"\n const queryString = reqUrl.includes(\"?\")\n ? reqUrl.slice(reqUrl.indexOf(\"?\") + 1)\n : \"\"\n const wait = new URLSearchParams(queryString).get(\"wait\")\n const fireAndForget = wait === \"false\" || wait === \"0\"\n try {\n if (fireAndForget) {\n registry.enqueuePrompt(id, prompt)\n json(202, { ok: true, id, queued: true })\n } else {\n await registry.sendPrompt(id, prompt)\n json(200, { ok: true, id })\n }\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err)\n // Differentiate \"not found\" / \"wrong kind\" / \"busy\" — they\n // surface as readable thrown messages from the registry.\n const status = msg.includes(\"no session\")\n ? 404\n : msg.includes(\"not an agent\")\n ? 400\n : msg.includes(\"mid-turn\")\n ? 409\n : 500\n json(status, { error: \"send_prompt_failed\", message: msg })\n }\n return true\n }\n\n if (path === \"/sessions\" && req.method === \"POST\") {\n const body = await readJsonBody(req)\n if (!body || typeof body !== \"object\") {\n json(400, { error: \"invalid_body\" })\n return true\n }\n const b = body as Record<string, unknown>\n const argv = Array.isArray(b.argv)\n ? (b.argv as unknown[]).filter((v): v is string => typeof v === \"string\")\n : []\n if (argv.length === 0) {\n json(400, { error: \"missing_argv\" })\n return true\n }\n try {\n const desc = registry.spawn({\n kind:\n b.kind === \"terminal\" || b.kind === \"agent-cli\" || b.kind === \"command\"\n ? b.kind\n : \"command\",\n workspaceSlug:\n typeof b.workspaceSlug === \"string\" ? b.workspaceSlug : \"default\",\n cwd: typeof b.cwd === \"string\" ? b.cwd : process.cwd(),\n argv,\n env:\n b.env && typeof b.env === \"object\"\n ? (b.env as Record<string, string>)\n : undefined,\n label: typeof b.label === \"string\" ? b.label : undefined,\n })\n json(201, desc)\n } catch (err) {\n json(500, {\n error: \"spawn_failed\",\n message: err instanceof Error ? err.message : String(err),\n })\n }\n return true\n }\n\n // Per-id routes. The `:id` slot also accepts a session's `name`\n // when one was set at spawn time — `findByIdOrName` resolves both\n // and the rest of the handler operates on the canonical id.\n const idMatch = path.match(\n /^\\/sessions\\/([^/]+)(\\/stream|\\/kill|\\/preview|\\/export)?$/,\n )\n if (!idMatch) return false\n const [, rawIdOrName, suffix] = idMatch\n if (!rawIdOrName) return false\n const resolvedDesc = registry.findByIdOrName(rawIdOrName)\n const id = resolvedDesc?.id ?? rawIdOrName\n\n if (suffix === \"/export\" && req.method === \"GET\") {\n // Transcript export — reads the adapter's native persistence layer\n // (claude-code JSONL / hermes SQLite) and returns a rendered\n // transcript. Query params: format (markdown|json), adapter, cwd.\n // Read-only GET, no auth gate (same policy as /preview).\n const reqUrl = req.url ?? \"\"\n const qs = new URLSearchParams(\n reqUrl.includes(\"?\") ? reqUrl.slice(reqUrl.indexOf(\"?\") + 1) : \"\",\n )\n const fmt = qs.get(\"format\") === \"json\" ? \"json\" as const : \"markdown\" as const\n const adapterOverride = qs.get(\"adapter\") ?? undefined\n const cwdOverride = qs.get(\"cwd\") ?? undefined\n const result = await exportAgentSession({\n sessionId: rawIdOrName,\n registry,\n format: fmt,\n ...(adapterOverride ? { adapter: adapterOverride } : {}),\n ...(cwdOverride ? { cwd: cwdOverride } : {}),\n })\n if (result.content.startsWith(\"Error:\")) {\n const isNotFound =\n result.content.includes(\"not found in registry\") ||\n result.content.includes(\"not found\") ||\n result.content.includes(\"not found\")\n json(isNotFound ? 404 : 422, {\n error: \"export_failed\",\n message: result.content,\n sessionId: rawIdOrName,\n adapter: result.adapter,\n })\n } else {\n json(200, result)\n }\n return true\n }\n\n if (suffix === \"/preview\" && req.method === \"GET\") {\n // Read-only snapshot of the recent ring buffer — used by the\n // dashboard's detail pane so the user sees what the session was\n // doing without committing to an attach. Returns BOTH lines\n // (for agent-cli/command sessions) and recent-bytes (for PTY).\n // Caller picks whichever is populated.\n if (!resolvedDesc) {\n json(404, { error: \"session_not_found\", id: rawIdOrName })\n return true\n }\n const reqUrl = req.url ?? \"\"\n const qs = new URLSearchParams(\n reqUrl.includes(\"?\") ? reqUrl.slice(reqUrl.indexOf(\"?\") + 1) : \"\",\n )\n const lineCap = clampInt(qs.get(\"lines\"), 10, 1, 200)\n const byteCap = clampInt(qs.get(\"bytes\"), 16 * 1024, 256, 64 * 1024)\n // No registry method exists for \"give me the recent buffer\n // snapshot\" — readTerminalOutput is the closest. For non-PTY\n // sessions, attach with a no-op subscriber, read backfill,\n // detach. Cheap; the backfill is synchronous on attach.\n const lines: string[] = []\n if (resolvedDesc.pty !== true) {\n const unsub = registry.attach(id, line => {\n lines.push(line)\n })\n if (unsub) unsub()\n }\n const bufBytes = registry.readTerminalOutput(id, byteCap)\n json(200, {\n id: resolvedDesc.id,\n lines: lines.slice(-lineCap),\n bytes: bufBytes ? bufBytes.toString(\"base64\") : null,\n })\n return true\n }\n\n if (suffix === \"/stream\" && req.method === \"GET\") {\n if (!resolvedDesc) {\n json(404, { error: \"session_not_found\", id: rawIdOrName })\n return true\n }\n res.writeHead(200, {\n \"content-type\": \"text/event-stream\",\n \"cache-control\": \"no-cache\",\n connection: \"keep-alive\",\n })\n // Keep-alive ping every 25s — proxies / browsers eventually\n // close idle SSE connections; the comment line keeps the pipe\n // warm without confusing the EventSource parser (it ignores\n // anything starting with `:`).\n const ping = setInterval(() => {\n try {\n res.write(`: keep-alive\\n\\n`)\n } catch {\n clearInterval(ping)\n }\n }, 25_000)\n const unsub = registry.attach(id, (line, stream) => {\n try {\n res.write(\n `data: ${JSON.stringify({ line, stream })}\\n\\n`\n )\n } catch {\n // Client gone — cleanup happens on `close`.\n }\n })\n if (!unsub) {\n clearInterval(ping)\n res.end()\n return true\n }\n req.once(\"close\", () => {\n unsub()\n clearInterval(ping)\n })\n return true\n }\n\n if (suffix === \"/kill\" && req.method === \"POST\") {\n const ok = registry.kill(id)\n json(ok ? 200 : 404, { ok, sessionId: id })\n return true\n }\n\n if (!suffix && req.method === \"GET\") {\n if (!resolvedDesc) {\n json(404, { error: \"session_not_found\", id: rawIdOrName })\n return true\n }\n json(200, resolvedDesc)\n return true\n }\n\n if (!suffix && req.method === \"DELETE\") {\n const ok = registry.forget(id)\n json(ok ? 200 : 404, { ok, id })\n return true\n }\n\n return false\n}\n\n/**\n * /tunnels routes — create, list, get, and stop public tunnels.\n * Returns `true` when it handled the request so the dispatcher\n * skips the 404 path.\n *\n * GET /tunnels → { tunnels: TunnelDescriptor[] }\n * POST /tunnels → TunnelDescriptor (creates a new tunnel)\n * GET /tunnels/:id → TunnelDescriptor\n * DELETE /tunnels/:id → { ok, tunnelId }\n */\nasync function handleTunnels(\n req: IncomingMessage,\n res: ServerResponse,\n path: string,\n registry: TunnelRegistry,\n): Promise<boolean> {\n const json = (status: number, body: unknown): void => {\n res.writeHead(status, { \"content-type\": \"application/json\" })\n res.end(JSON.stringify(body))\n }\n\n if (path === \"/tunnels\" && req.method === \"GET\") {\n const urlStr = req.url ?? \"\"\n const qs = urlStr.includes(\"?\")\n ? new URLSearchParams(urlStr.slice(urlStr.indexOf(\"?\") + 1))\n : new URLSearchParams()\n const onlyActive = qs.get(\"onlyActive\") === \"true\"\n let tunnels = registry.list()\n if (onlyActive) {\n tunnels = tunnels.filter(\n t => t.status === \"starting\" || t.status === \"active\",\n )\n }\n json(200, { tunnels })\n return true\n }\n\n if (path === \"/tunnels\" && req.method === \"POST\") {\n const body = await readJsonBody(req)\n if (!body || typeof body !== \"object\") {\n json(400, { error: \"invalid_body\" })\n return true\n }\n const b = body as Record<string, unknown>\n const targetPort =\n typeof b.targetPort === \"number\" && b.targetPort > 0\n ? Math.floor(b.targetPort)\n : null\n if (!targetPort) {\n json(400, {\n error: \"missing_targetPort\",\n message: \"body must include `targetPort` (integer 1-65535)\",\n })\n return true\n }\n try {\n const desc = await registry.create({\n targetPort,\n // Any provider slug (built-in, legacy alias, or third-party) — the\n // registry resolves/validates it and surfaces an unknown slug as a\n // create_failed error below.\n ...(typeof b.provider === \"string\" ? { provider: b.provider } : {}),\n ...(typeof b.name === \"string\" ? { name: b.name } : {}),\n ...(typeof b.label === \"string\" ? { label: b.label } : {}),\n ...(typeof b.targetHost === \"string\" ? { targetHost: b.targetHost } : {}),\n ...(b.autostart === true ? { autostart: true } : {}),\n ...(typeof b.hostname === \"string\" ? { hostname: b.hostname } : {}),\n ...(typeof b.tunnelId === \"string\" ? { tunnelId: b.tunnelId } : {}),\n ...(typeof b.credentialsFile === \"string\"\n ? { credentialsFile: b.credentialsFile }\n : {}),\n })\n json(201, desc)\n } catch (err) {\n json(500, {\n error: \"create_failed\",\n message: err instanceof Error ? err.message : String(err),\n })\n }\n return true\n }\n\n const tunnelMatch = path.match(/^\\/tunnels\\/([^/]+)$/)\n if (!tunnelMatch) return false\n const rawIdOrName = decodeURIComponent(tunnelMatch[1] ?? \"\")\n\n if (req.method === \"GET\") {\n const desc = registry.findByIdOrName(rawIdOrName)\n if (!desc) {\n json(404, { error: \"tunnel_not_found\", id: rawIdOrName })\n return true\n }\n json(200, desc)\n return true\n }\n\n if (req.method === \"DELETE\") {\n const ok = await registry.stop(rawIdOrName)\n if (!ok) {\n json(404, { error: \"tunnel_not_found\", id: rawIdOrName })\n return true\n }\n json(200, { ok, tunnelId: rawIdOrName })\n return true\n }\n\n return false\n}\n\nasync function readJsonBody(req: IncomingMessage): Promise<unknown> {\n const chunks: Buffer[] = []\n for await (const chunk of req) {\n chunks.push(typeof chunk === \"string\" ? Buffer.from(chunk) : chunk)\n }\n if (chunks.length === 0) return null\n try {\n return JSON.parse(Buffer.concat(chunks).toString(\"utf8\"))\n } catch {\n return null\n }\n}\n","/**\n * Per-adapter resume strategies — the daemon's view of \"how do I\n * continue a previous session for THIS adapter?\".\n *\n * The driver already has an `AgentCliContinuation` declaration in\n * the adapter manifest (AIP-45). That covers strategy NAMES\n * (`native-resume`, `pinned-session`, `transcript`, `none`) but is\n * silent on the mechanics that live OUTSIDE the runtime — like\n * \"where on disk does this adapter store its conversations?\" or\n * \"what argv do I pass to resume into PTY mode?\".\n *\n * This table is that practical bridge. Each entry declares three\n * optional hooks:\n *\n * outputHint regex matched against each output line; group 1 is\n * the resume id. Stored as `desc.resumeMetadata[storeAs]`.\n * fsProbe async function that probes a per-adapter directory\n * for a stored session id, scoped to a workspace cwd.\n * Used when `outputHint` never matched.\n * spawnArgs given a captured id, returns the argv to spawn a\n * PTY that resumes the session. agentproto then\n * bypasses ACP/agent-cli and runs the provider\n * directly — the most reliable resume path because\n * it leans on the provider's native UX.\n *\n * Adapters that don't declare anything here fall back to:\n * 1. ACP-level resume via `resumeSessionId` on POST /sessions/agent\n * 2. Fresh spawn (same shape, no continuity)\n *\n * Eventually each adapter should ship its own strategy on\n * `AgentCliHandle.resumeStrategy` (driver-side). This central table\n * is the bootstrap: it lets a new adapter become resume-capable\n * without bumping its npm package; once that lands, entries\n * graduate into the adapter packages.\n */\n\nimport { promises as fs } from \"node:fs\"\nimport { homedir } from \"node:os\"\nimport { join, resolve } from \"node:path\"\n\n/** Where on disk the resume id ends up on the session descriptor. */\nexport type ResumeMetadataKey =\n | \"claudeResumeId\"\n | \"hermesResumeId\"\n | \"codexResumeId\"\n | \"openClawResumeId\"\n | \"openCodeResumeId\"\n\nexport interface ResumeStrategy {\n /** When set, run on every output line for this adapter. Group 1\n * captures the resume id. The match is saved on the descriptor\n * as `resumeMetadata[storeAs]`. */\n outputHint?: RegExp\n /** Where the matched id is recorded on the descriptor. */\n storeAs: ResumeMetadataKey\n /** Probe the adapter's on-disk session store for the most-recently\n * modified session in the given workspace. Returns the resume id\n * or null when nothing eligible. Files older than `prevStartedAt`\n * are ignored (avoids resuming an unrelated prior conversation).\n *\n * Skip when the adapter doesn't persist sessions externally. */\n fsProbe?(cwd: string, prevStartedAt: string): Promise<string | null>\n /** Return the argv to spawn a PTY that resumes into the given id.\n * When omitted, the daemon falls back to ACP-level resume via\n * the agent-cli protocol instead of the provider's native CLI. */\n spawnArgs?(id: string): string[]\n}\n\nexport const RESUME_STRATEGIES: Record<string, ResumeStrategy> = {\n \"claude-code\": {\n // Printed by claude on graceful exit when session persistence\n // is on (default). Example: `claude --resume 0e483f81-1a44-4bec-9667-b37158450296`\n outputHint: /claude\\s+--resume\\s+([0-9a-f-]{8,})/i,\n storeAs: \"claudeResumeId\",\n fsProbe: probeMtimeLatestJsonl(\".claude/projects\"),\n spawnArgs: id => [\"claude\", \"--resume\", id],\n },\n\n // Stubs for other shipped adapters — fill in as we learn each\n // provider's resume mechanism. Today they fall back to ACP-level\n // resume (whatever the agent-cli runtime supports) or fresh spawn.\n //\n // hermes: { storeAs: \"hermesResumeId\", ... }\n // codex: { storeAs: \"codexResumeId\", ... }\n // openclaw: { storeAs: \"openClawResumeId\", ... }\n // opencode: { storeAs: \"openCodeResumeId\", ... }\n}\n\n/**\n * Build an `fsProbe` for adapters that store one `.jsonl` per session\n * inside `~/<storeRel>/<cwd-encoded>/`. The encoded cwd is the\n * absolute path with `/` → `-` (claude's convention; others tend to\n * use the same scheme). Returns the UUID of the most-recently\n * modified `.jsonl`, filtered to files at-or-after `prevStartedAt`.\n */\nfunction probeMtimeLatestJsonl(\n storeRel: string,\n): (cwd: string, prevStartedAt: string) => Promise<string | null> {\n return async (cwd, prevStartedAt) => {\n const encoded = cwd.replace(/\\//g, \"-\")\n const dir = resolve(homedir(), storeRel, encoded)\n let entries: string[]\n try {\n entries = await fs.readdir(dir)\n } catch {\n return null\n }\n const jsonl = entries.filter(e => e.endsWith(\".jsonl\"))\n if (jsonl.length === 0) return null\n const startedAtMs = Date.parse(prevStartedAt)\n const candidates: { name: string; mtime: number }[] = []\n for (const f of jsonl) {\n try {\n const st = await fs.stat(join(dir, f))\n if (!Number.isFinite(startedAtMs) || st.mtimeMs >= startedAtMs - 1000) {\n candidates.push({ name: f, mtime: st.mtimeMs })\n }\n } catch {\n // ignore unreadable entry\n }\n }\n if (candidates.length === 0) return null\n candidates.sort((a, b) => b.mtime - a.mtime)\n return candidates[0]!.name.replace(/\\.jsonl$/, \"\")\n }\n}\n\n/**\n * Helper: which adapters declare any resume capability? Used by\n * `agentproto sessions restart` to print a helpful \"this adapter\n * doesn't support resume; falling back to fresh spawn\" hint when\n * applicable.\n */\nexport function hasResumeStrategy(adapterSlug: string | undefined): boolean {\n if (!adapterSlug) return false\n const s = RESUME_STRATEGIES[adapterSlug]\n return !!(s && (s.outputHint || s.fsProbe || s.spawnArgs))\n}\n","/**\n * Sessions registry — tracks long-lived child processes spawned by\n * the agentproto daemon (terminals, agent CLIs, custom commands).\n *\n * The registry lives in-memory for the daemon's lifetime; a recent\n * snapshot also persists to `~/.agentproto/sessions.json` so a fresh\n * daemon restart can show \"you had these running before\" instead of\n * losing all visibility on a crash.\n *\n * Each session owns:\n * - identity: id, kind, workspace slug, command + args, started time\n * - lifecycle: status (starting/running/exited/killed/error)\n * - output: last N lines (ring buffer) for instant attach + a\n * Node EventEmitter for live streaming consumers\n *\n * Consumers:\n * - HTTP routes (GET /sessions, /sessions/:id, /sessions/:id/stream,\n * POST /sessions/:id/kill)\n * - CLI `agentproto sessions` (TUI navigation + attach)\n * - guilde-web Active tab (session cards + terminal viewer)\n */\n\nimport type { AcpMcpServer } from \"@agentproto/acp\"\nimport { spawn, type ChildProcess } from \"node:child_process\"\nimport { EventEmitter } from \"node:events\"\nimport { mkdirSync, writeFileSync, promises as fs, readFileSync } from \"node:fs\"\nimport { RESUME_STRATEGIES } from \"./resume-strategies.js\"\nimport type { SessionEventBus } from \"./session-event-bus.js\"\nimport { dirname, resolve } from \"node:path\"\nimport { homedir } from \"node:os\"\nimport { randomUUID } from \"node:crypto\"\n\n/**\n * Minimal shape we need from a driver-agent-cli session — kept as a\n * structural type so the runtime package doesn't take a hard\n * dependency on @agentproto/driver-agent-cli (the http-server route\n * imports it and passes the constructed session in).\n */\nexport interface AgentSessionLike {\n sessionId: string\n send(message: unknown): AsyncIterable<AgentStreamEvent>\n cancel(): Promise<void>\n close(): Promise<void>\n}\n\n/**\n * Minimal PTY surface — structurally compatible with\n * @agentproto/acp/tunnel's PtyProcess (node-pty's IPty wrapper). The\n * runtime declares its own so this package stays native-free; the\n * cli's pty-factory util constructs values that satisfy both.\n */\nexport interface PtyProcess {\n readonly pid: number\n write(data: string): void\n resize(cols: number, rows: number): void\n kill(signal?: string): void\n onData(handler: (data: string) => void): void\n onExit(handler: (event: { exitCode: number; signal?: number }) => void): void\n}\n\nexport interface PtyFactoryOptions {\n command: string\n args: string[]\n cwd?: string\n env?: Record<string, string>\n cols: number\n rows: number\n}\n\nexport type PtyFactory = (opts: PtyFactoryOptions) => PtyProcess\n\nexport interface AgentStreamEvent {\n kind: string\n text?: string\n toolName?: string\n isError?: boolean\n reason?: string\n error?: { message: string; code?: number; data?: unknown }\n}\n\nexport const SESSIONS_FILE_PATH = (): string =>\n resolve(homedir(), \".agentproto\", \"sessions.json\")\n\nexport type SessionKind = \"terminal\" | \"agent-cli\" | \"command\" | \"browser\"\nexport type SessionStatus =\n | \"starting\"\n | \"running\"\n | \"exited\"\n | \"killed\"\n | \"error\"\n\nexport interface SessionDescriptor {\n id: string\n kind: SessionKind\n workspaceSlug: string\n /** What was actually run — quoted joined for display purposes\n * (`bash -lc \"claude --resume xyz\"`). */\n command: string\n pid: number | null\n status: SessionStatus\n startedAt: string\n endedAt?: string\n exitCode?: number\n /** Last time anything was written to stdout/stderr. Lets the UI\n * spot stuck sessions (\"running for 2h, last output 12min ago\"). */\n lastOutputAt?: string\n /** Free-text label the spawner can attach (e.g. conversation id,\n * operator name) so the UI can group/filter. */\n label?: string\n /** True when the session was spawned under a real PTY (node-pty)\n * instead of `child_process.spawn`. PTY sessions carry raw ANSI\n * bytes (alt-screen, key bindings, colors); attach goes through\n * WS /sessions/:id/pty rather than SSE /sessions/:id/stream. */\n pty?: boolean\n /** User-friendly slug supplied at spawn time. Optional; when set,\n * attach/stop/kill commands accept it as an alias for the id. */\n name?: string\n /** Argv that was spawned. Persisted so `agentproto sessions restart`\n * can clone the original shape without re-tokenizing the display\n * `command` string. Empty for agent-cli sessions (we record\n * `adapterSlug` separately). */\n argv?: readonly string[]\n /** Working directory the session was spawned in. Cloned by restart. */\n cwd?: string\n /** Adapter slug for agent-cli sessions — restart uses this with\n * `/sessions/agent` to spin up a fresh ACP runtime. Undefined for\n * pty/command kinds. */\n adapterSlug?: string\n /** The model the session was requested to run (echoed back at spawn). */\n model?: string\n /** Cumulative estimated USD cost of the session — best-effort, refreshed\n * on each turn-end from the adapter's usage reader (e.g. hermes reads its\n * state.db). Absent for adapters with no usage source. */\n costUsd?: number\n /** Cumulative input / output token counts (same source + cadence as costUsd). */\n tokensIn?: number\n tokensOut?: number\n /** ACP-level session id (the adapter's own handle — claude-code's\n * conversation id, hermes' chat id, …). Set at spawnAgent time\n * from `agentSession.sessionId`. Survives across daemon restarts\n * via sessions.json so `restart` can pass it as `resumeSessionId`\n * and reattach to the prior conversation history. */\n adapterSessionId?: string\n /** MCP servers mounted into the agent's session at spawn time\n * (orchestrator WP1). Persisted so the resume/re-spawn path can\n * re-mount the same host-chosen toolset instead of resuming a\n * capability-stripped agent. The current `AcpMcpServer` shape is\n * `{ name, transport, ref? }` — a reference, NOT inline credentials\n * — so this carries no secrets today. Should the shape ever grow\n * headers/tokens, NEVER log this field's contents. */\n mcpServers?: AcpMcpServer[]\n /** Provider-specific resume hints sniffed from the session's\n * output. claude-code prints `claude --resume <uuid>` on exit;\n * we capture that uuid as `claudeResumeId`. On `restart`, when a\n * hint is present, agentproto prefers a PTY spawn with the\n * provider's native resume command (`claude --resume <id>`) over\n * the ACP-level resume — works wherever the provider persisted\n * the session, not just when the ACP wrapper did.\n *\n * Keys are adapter-specific so future adapters can add their own\n * (\"hermesResumeId\", etc.) without changing this type. */\n resumeMetadata?: Record<string, string>\n /** Set by the orchestration layer when the agent emits an\n * \"awaiting-input\" turn-end. Cleared on the next turn start.\n * Used by `wait_for_any` to fast-return without subscribing. */\n awaitingInput?: boolean\n /** Count of turns that have fully completed (turn-end emitted) on this\n * session. Lets `wait_for_any` fast-return for a session that already\n * finished its turn before the wait subscribed — a fast turn that ends\n * in \"completed\" (not \"awaiting-input\") leaves no other persisted\n * signal (status stays \"running\", busy clears). 0 = never ran a turn,\n * so a freshly-spawned idle session is NOT mistaken for done. */\n turnsCompleted?: number\n /** True while a turn is actively running (mirror of the internal\n * runtime `busy` flag). Lets `wait_for_any` distinguish \"idle after a\n * finished turn\" from \"mid-turn\" so it doesn't fast-return a stale\n * turn-end while the NEXT turn is still generating. */\n busy?: boolean\n /** Session id of the orchestrator that spawned this session, set when\n * the spawn arrived via the scoped orchestrator sub-gateway (the\n * token carried the spawner's identity). Absent for direct `/mcp`\n * spawns (the root operator). Powers the subtree scoping of\n * list/kill and the per-parent child quota (orchestrator WP4).\n * Persisted so the tree survives a daemon restart. */\n parentSessionId?: string\n /** Recursion depth in the orchestrator tree: a direct (root) spawn is\n * depth 0; a session spawned by a depth-d orchestrator is d+1. Used\n * by the depth-cap guard. Persisted alongside `parentSessionId`.\n * Treated as 0 when absent (legacy rows / direct spawns that predate\n * WP4). */\n depth?: number\n // ── Browser-session fields (kind=\"browser\") ──────────────────────────────\n /** Adapter id that drives this session (e.g. \"camofox\", \"bureau\"). */\n browserAdapterId?: string\n /** Port the browser service listens on. */\n browserPort?: number\n /** Base URL of the browser service (e.g. \"http://127.0.0.1:9377\"). */\n browserBaseUrl?: string\n /** Execution location — \"local\" (default) or \"cloud\". */\n browserLocation?: \"local\" | \"cloud\"\n}\n\ninterface SessionRuntime {\n desc: SessionDescriptor\n /** Set when the session is a raw spawn (`kind: \"command\"|\"terminal\"`).\n * Agent sessions don't expose the underlying process — the\n * driver-agent-cli runtime owns it. */\n child?: ChildProcess\n /** Set when the session is an agent-cli (multi-turn). The registry\n * keeps it alive across turns; sendPrompt(id, prompt) re-uses it. */\n agentSession?: AgentSessionLike\n /** Adapter slug — only set for agent sessions, helps the UI render\n * \"claude-code\" / \"hermes\" badges. */\n adapterSlug?: string\n /** Set when the session is a PTY (spawnPty). Bytes flow through\n * pty.onData → recentBytes ring + emitter \"data\" event. */\n pty?: PtyProcess\n /** Per-subscriber size requests for the PTY. Min cols/rows\n * across the live set is what we actually call pty.resize with\n * (mirrors tmux's \"smallest attached client wins\" rule). */\n ptySubscribers?: Map<number, { cols: number; rows: number }>\n /** Ring buffer of recent stdout+stderr lines. Capped so a runaway\n * child can't blow the daemon's heap. */\n recentLines: string[]\n /** Ring buffer of recent PTY bytes for replay-on-attach. Total\n * size capped at RECENT_BYTES_CAP — oldest chunks dropped first. */\n recentBytes: Buffer[]\n recentBytesSize: number\n emitter: EventEmitter\n /** True while a turn is in flight. POST /sessions/:id/prompt rejects\n * with 409 when busy — the agent can only handle one turn at a\n * time per session. */\n busy: boolean\n /** Buffer for partial text-delta fragments — agent text events\n * arrive as chunks, we coalesce them across deltas and split on\n * newlines so each line lands as a discrete ring-buffer entry. */\n textBuf: string\n /** Same as textBuf but for `thought` events. Some agents (hermes)\n * stream chain-of-thought as one delta per token, which made the\n * ring buffer unreadable when each token got its own\n * `[thought]` line — coalesce the same way text-delta does. */\n thoughtBuf: string\n /** In-flight resume promise. Deduplicates concurrent prompt\n * attempts on a dead agent session — only one resume call hits\n * the adapter, the rest await this promise. Cleared once\n * resolved (success or failure). */\n resumePromise?: Promise<void>\n /** Async stop callback for browser sessions (kind=\"browser\").\n * Called by kill() best-effort — the descriptor is already flipped\n * to \"killed\" before this fires. */\n browserStop?: () => Promise<void>\n /** Guard: true once session:exited has been emitted to sessionEvents.\n * Prevents duplicate emissions when both kill() and an OS exit event fire. */\n exitedEmitted?: boolean\n /** Per-session cost cap. When set, the turn-end finally block checks\n * the accumulated costUsd against this ceiling and kills the session\n * if exceeded. */\n maxCostUsd?: number\n /** Best-effort usage reader called after each turn. The adapter returns\n * accumulated cost/token counts which are mirrored onto the descriptor. */\n readUsage?: () => Promise<{ costUsd?: number; tokensIn?: number; tokensOut?: number } | null>\n}\n\nconst RECENT_LINES_CAP = 500\nconst RECENT_BYTES_CAP = 64 * 1024\nconst PERSIST_DEBOUNCE_MS = 1_500\n/** Cap on the number of historical descriptors loaded from\n * sessions.json at boot. Older entries (by startedAt) are dropped\n * on overflow — newest history wins. Adjust upward if the file\n * starts feeling sparse; downward if the dashboard takes too long\n * to render. */\nconst HISTORY_CAP = 200\n\n/** Strip CSI / SGR ANSI sequences so resume-pattern matching works\n * on dim/coloured output. Liberal regex covering most cases — we\n * don't need byte-perfect parsing here. */\nfunction stripAnsiCodes(s: string): string {\n return s.replace(/\\x1b\\[[0-9;?]*[A-Za-z]/g, \"\")\n}\n\nexport interface SessionsRegistry {\n spawn(input: SpawnSessionInput): SessionDescriptor\n /** Adopt a ChildProcess that was spawned outside the registry —\n * e.g. by the tunnel server when the host dispatches a spawn\n * frame. The registry attaches its stdout/stderr listeners and\n * tracks the descriptor so the child shows up in /sessions and\n * the LocalDaemonSessionsCard. The caller keeps lifecycle\n * ownership (kill / wait); this is purely for observability.\n * Returns the descriptor for the registered session. */\n register(input: RegisterSessionInput): SessionDescriptor\n /** Register an already-built agent session (caller resolves the\n * adapter + builds the runtime). Sets kind=\"agent-cli\", consumes\n * the optional initial prompt synchronously, returns the\n * descriptor. The agent stays alive — call `sendPrompt(id, ...)`\n * for follow-up turns until `kill(id)` closes it. */\n spawnAgent(input: SpawnAgentInput): SessionDescriptor\n /** Spawn a process under a real PTY (node-pty). Bytes flow through\n * the registry's byte ring buffer + emitter; attach with\n * `attachPty(id, ...)`. Throws when the registry was constructed\n * without a `spawnPty` factory (node-pty optional dep missing). */\n spawnPty(input: SpawnPtyInput): SessionDescriptor\n /** Register an already-running browser service adapter as a tracked\n * session (kind=\"browser\"). Idempotent by identity — each call\n * mints a fresh session id. The `stop` callback is invoked by\n * `kill()` best-effort. */\n registerBrowser(input: RegisterBrowserInput): SessionDescriptor\n /** Send a follow-up turn to a live agent session. Throws when the\n * session is missing, not an agent-cli kind, or busy. The events\n * stream into the existing ring buffer + line emitter so /stream\n * consumers see them as they arrive. */\n sendPrompt(id: string, message: unknown): Promise<void>\n /** Fire-and-forget variant of `sendPrompt`. Validates the same\n * preconditions synchronously — throws on missing session / wrong\n * kind / busy — but returns immediately after the turn is started,\n * letting the caller stream output via the SSE endpoint instead of\n * blocking on the full turn. Async errors during the turn are\n * pushed into the ring buffer as `[error]` lines so `/stream`\n * subscribers see them. Used by the web UI's chat input where a\n * long turn would otherwise freeze the textbox. */\n enqueuePrompt(id: string, message: unknown): void\n list(): SessionDescriptor[]\n get(id: string): SessionDescriptor | undefined\n /** Subscribe to a session's output. Returns an unsubscribe fn.\n * Initial backfill: synchronously invokes `onLine` once for each\n * line currently in the ring buffer so attaches show context. */\n attach(\n id: string,\n onLine: (line: string, stream: \"stdout\" | \"stderr\") => void\n ): (() => void) | null\n /** Subscribe to a PTY session's byte stream. Returns a control\n * handle (write/resize/detach) and null when the session is\n * missing or not a PTY kind. Replays the ring buffer\n * synchronously before live frames start. Initial `cols`/`rows`\n * are required so the registry can compute min-size across\n * subscribers; recompute on every `resize` call. */\n attachPty(\n id: string,\n initial: { cols: number; rows: number },\n onData: (chunk: Buffer) => void,\n onExit: (event: { exitCode: number; signal?: number }) => void\n ): {\n write(data: string): void\n resize(cols: number, rows: number): void\n detach(): void\n } | null\n /** Find a session by exact id OR exact name match. Returns the\n * descriptor or undefined. Used by HTTP/MCP routes so callers\n * can refer to \"claude-main\" instead of \"sess_a3f8c1b2\". */\n findByIdOrName(query: string): SessionDescriptor | undefined\n /** Write a chunk of text to a PTY session's stdin. Returns true\n * on success, false when the session is missing or not a PTY.\n * Single-shot variant of attachPty().write — useful for MCP\n * tools that drive a session through tool calls. */\n writeTerminalInput(id: string, data: string): boolean\n /** Snapshot the recent PTY byte buffer as one Buffer. Newest\n * bytes at the end; `lastBytes` caps the returned size from the\n * tail. Returns null when the session is missing or not a PTY. */\n readTerminalOutput(id: string, lastBytes?: number): Buffer | null\n kill(id: string, signal?: NodeJS.Signals): boolean\n /** Stop tracking a session (after it exited and the user clicked\n * \"clear\"). Doesn't kill — use `kill` first. */\n forget(id: string): boolean\n /** Stop persisting + close all sessions. Killed children are not\n * awaited — the daemon shutdown loop handles process tree teardown. */\n shutdown(): void\n}\n\nexport interface RegisterBrowserInput {\n /** Adapter id (e.g. \"camofox\", \"bureau\", \"chromium\"). */\n adapterId: string\n /** Port the browser service listens on. */\n port: number\n /** Base URL of the browser service (e.g. \"http://127.0.0.1:9377\"). */\n baseUrl: string\n /** Execution location — \"local\" (default) or \"cloud\". Included in the\n * dedup key so a cloud call never returns a pre-existing local session. */\n location?: \"local\" | \"cloud\"\n /** PID of the service process — undefined when managed by launchd/systemd. */\n pid?: number\n /** True when the service was already healthy before this call (idempotent start). */\n wasAlreadyRunning: boolean\n /** Initial lifecycle status. \"running\" when the service is confirmed\n * healthy; \"starting\" when a non-blocking cold start returned before the\n * service finished converging (health-wait continues in the background and\n * `browser_status` / `list_browsers` flip it to running once up).\n * Defaults to \"running\" when omitted. */\n status?: Extract<SessionStatus, \"running\" | \"starting\">\n /** Async shutdown callback — called by kill() best-effort. */\n stop: () => Promise<void>\n label?: string\n}\n\nexport interface RegisterSessionInput {\n /** Pre-existing child process to adopt (e.g. from a tunnel spawn). */\n child: ChildProcess\n /** Stable id — typically the tunnel's execId so callers cross-ref. */\n id: string\n workspaceSlug: string\n /** Display label for the descriptor's `command` field. */\n command: string\n kind?: SessionKind\n label?: string\n}\n\nexport interface SpawnAgentInput {\n workspaceSlug: string\n cwd: string\n /** Driver-built session ready to receive turns. Caller resolves\n * the adapter, calls createAgentCliRuntime(handle).start({cwd}),\n * and hands the result here. */\n agentSession: AgentSessionLike\n /** Adapter slug for the descriptor (display only). */\n adapterSlug: string\n /** Optional initial prompt to dispatch immediately. The promise\n * the registry returns resolves AFTER the spawn — the prompt\n * runs in the background, projecting events into the ring\n * buffer. Skip to spawn idle. */\n initialPrompt?: string\n label?: string\n /** Pretty command for the descriptor (display only). */\n commandPreview?: string\n /** MCP servers mounted at spawn time. Persisted on the descriptor so\n * the resume/re-spawn path can re-mount the same toolset (orchestrator\n * WP1). */\n mcpServers?: AcpMcpServer[]\n /** Spawning orchestrator's session id — set when the spawn arrived\n * through the scoped sub-gateway (orchestrator WP4). Recorded on the\n * descriptor for subtree scoping + quota accounting. */\n parentSessionId?: string\n /** Recursion depth for the new session (orchestrator WP4). Defaults to\n * 0 when omitted (direct/root spawn). */\n depth?: number\n /** Requested model id — recorded on the descriptor for display + echo. */\n model?: string\n /** Hard ceiling on cumulative session cost (USD). When set and the\n * adapter's usage reader reports a higher cost at a turn-end, the session\n * is stopped (best-effort, turn-granular — caps continuation, can't abort\n * a turn mid-flight). */\n maxCostUsd?: number\n /** Best-effort usage reader, called on each turn-end to refresh the\n * cost/token fields on the descriptor. Adapter-specific (e.g. hermes\n * reads its state.db keyed by the adapter session id). Omit for adapters\n * with no usage source. */\n readUsage?: () => Promise<{ costUsd?: number; tokensIn?: number; tokensOut?: number } | null>\n}\n\nexport interface SpawnSessionInput {\n kind: SessionKind\n workspaceSlug: string\n /** Path of the workspace root (for the child's cwd). The registry\n * doesn't validate it against the workspaces config — caller has\n * already resolved this. */\n cwd: string\n /** Argv. First element is the binary; rest are passed verbatim. */\n argv: string[]\n /** Extra env on top of the daemon's process.env. */\n env?: Record<string, string>\n /** Optional pre-set id (lets the spawner reference the session\n * before the spawn returns — useful for telemetry). */\n id?: string\n label?: string\n /** Keep the child's stdin open (default: closed). Most spawned\n * agents are non-interactive and emit a warning when stdin is a\n * pipe with no writer (claude-code prints \"no stdin data\n * received in 3s, proceeding without it\"). Closing stdin lets\n * them skip the wait. PTY/terminal kinds that genuinely need\n * bidirectional IO should opt in via `keepStdin: true` and the\n * caller is then responsible for writing to `child.stdin`. */\n keepStdin?: boolean\n}\n\nexport interface SpawnPtyInput {\n workspaceSlug: string\n cwd: string\n argv: string[]\n /** Initial PTY dimensions. The registry uses min(cols, rows) across\n * active subscribers thereafter — these are the seed values used\n * before anyone attaches. */\n cols: number\n rows: number\n /** Extra env on top of process.env. TERM/LANG/PATH are forced by\n * the factory layer (node-pty.spawn options); don't try to clear\n * them here. */\n env?: Record<string, string>\n /** User-friendly slug. Used by `findByIdOrName(query)`. Must not\n * collide with an existing session's name. */\n name?: string\n label?: string\n}\n\n/**\n * Hook the registry uses to rebuild a dead agent session on demand.\n * Invoked when a prompt arrives for an agent-cli session whose\n * `agentSession` was lost (typically daemon restart). Returns a fresh\n * `AgentSessionLike` bound to the same upstream conversation via\n * `resumeSessionId`, OR null if resume isn't possible (adapter gone,\n * upstream rejected). When null, the prompt path surfaces the same\n * \"not an agent session\" error as before — caller knows the row is a\n * ghost.\n *\n * The CLI wires this into the registry by passing in a closure that\n * calls `resolveAgentAdapter(slug)?.startSession({cwd, resumeSessionId})`,\n * which is the same path the gateway's POST /sessions/agent uses.\n */\nexport type AgentSessionResumer = (input: {\n adapterSlug: string\n cwd: string\n resumeSessionId: string\n /** MCP servers to re-mount on the resumed session — threaded from the\n * descriptor's persisted `mcpServers` so the re-spawned agent keeps the\n * same host-chosen toolset it had on the initial spawn (orchestrator\n * WP1). Omitted for legacy rows spawned before this was persisted. */\n mcpServers?: AcpMcpServer[]\n}) => Promise<AgentSessionLike | null>\n\nexport function createSessionsRegistry(opts?: {\n /** Override the persistence path — tests pin a tmpdir. */\n persistPath?: string\n /** Disable persistence entirely. */\n persist?: boolean\n /** PTY factory (node-pty wrapper). When omitted, `spawnPty()`\n * throws — the daemon advertises PTY support only when the cli\n * layer resolved node-pty successfully. */\n spawnPty?: PtyFactory\n /** Hook called when a prompt arrives for an agent-cli session whose\n * agentSession binding is gone (daemon restart). When provided,\n * the registry transparently resumes the session via the adapter's\n * resumeSessionId before dispatching the turn. When omitted,\n * killed agent-cli sessions surface the legacy \"not an agent\n * session\" error and the user must spawn fresh. */\n resumeAgent?: AgentSessionResumer\n /** When provided, the registry translates internal lifecycle transitions\n * (turn-end, awaiting-input, exit) into SessionEvents on this bus. */\n sessionEvents?: SessionEventBus\n}): SessionsRegistry {\n const persistPath = opts?.persistPath ?? SESSIONS_FILE_PATH()\n const persist = opts?.persist ?? true\n const ptyFactory = opts?.spawnPty\n const resumeAgent = opts?.resumeAgent\n const sessionEvents = opts?.sessionEvents\n const sessions = new Map<string, SessionRuntime>()\n let persistTimer: ReturnType<typeof setTimeout> | null = null\n // Monotonically-growing PTY-subscriber id. Detach is O(1) on\n // Map.delete(subId), so we never reuse — overflow at Number.MAX_-\n // SAFE_INTEGER would take ~285 years at 1M attaches/sec.\n let nextSubId = 1\n // Guards `shutdown()` from running twice — double-stop happens in\n // serve --interactive's Ctrl-C race; without this, the second\n // call writes an empty snapshot over the real one.\n let shutdownDone = false\n\n // ── boot-time history load ──\n // Read sessions.json synchronously at construction so the dashboard\n // shows historical sessions immediately on daemon restart. Anything\n // that was \"running\" or \"starting\" when the daemon last died gets\n // marked \"killed\" — we have no way to know if the orphan child\n // survived the daemon's exit, and pretending it's still alive would\n // make attach calls fail mysteriously.\n //\n // Historical entries are GHOSTS: descriptor only, no child / no\n // agentSession / no pty. Calls like kill(id) / attach(id) work on\n // them but degrade to no-ops (the underlying process is gone). The\n // session's `endedAt` is set to now when we infer a kill, so the\n // dashboard ages them from this boot rather than the daemon's last\n // life.\n if (persist) {\n loadHistorySnapshot(persistPath, sessions)\n }\n\n // Belt-and-suspenders: `process.on(\"exit\")` runs even on uncaught\n // throws, terminal-close (SIGHUP), and any termination path that\n // bypassed the regular SIGINT/SIGTERM cleanup. The handler must be\n // sync (Node won't await async there); we already use sync IO in\n // `shutdown()` so this is safe. Idempotency guard inside shutdown\n // prevents a double-write when both this handler and the explicit\n // SIGINT path fire.\n const onProcessExit = (): void => {\n shutdownImpl()\n }\n if (persist) {\n process.on(\"exit\", onProcessExit)\n }\n\n // Emit session:exited once per session, deduplicated via exitedEmitted flag.\n const emitExited = (rt: SessionRuntime): void => {\n if (!sessionEvents || rt.exitedEmitted) return\n rt.exitedEmitted = true\n sessionEvents.emit({\n type: \"session:exited\",\n sessionId: rt.desc.id,\n exitCode: rt.desc.exitCode,\n status: rt.desc.status as \"exited\" | \"killed\" | \"error\",\n label: rt.desc.label,\n ts: new Date().toISOString(),\n })\n }\n\n const schedulePersist = (): void => {\n if (!persist) return\n if (persistTimer) clearTimeout(persistTimer)\n persistTimer = setTimeout(() => {\n void persistSnapshot()\n }, PERSIST_DEBOUNCE_MS)\n }\n\n const persistSnapshot = async (): Promise<void> => {\n try {\n const snapshot = {\n savedAt: new Date().toISOString(),\n sessions: Array.from(sessions.values()).map(s => s.desc),\n }\n await fs.mkdir(dirname(persistPath), { recursive: true })\n await fs.writeFile(persistPath, JSON.stringify(snapshot, null, 2) + \"\\n\")\n } catch (err) {\n // Persistence is best-effort — log only, never throw.\n console.warn(\n `[sessions] persist failed: ${\n err instanceof Error ? err.message : String(err)\n }`\n )\n }\n }\n\n const appendLine = (\n rt: SessionRuntime,\n line: string,\n stream: \"stdout\" | \"stderr\"\n ): void => {\n rt.recentLines.push(line)\n if (rt.recentLines.length > RECENT_LINES_CAP) {\n rt.recentLines.splice(0, rt.recentLines.length - RECENT_LINES_CAP)\n }\n rt.desc.lastOutputAt = new Date().toISOString()\n sniffResumeHints(rt, line)\n rt.emitter.emit(\"line\", { line, stream })\n }\n\n /**\n * Provider-specific resume-hint sniffer. Looks up the adapter's\n * strategy in `RESUME_STRATEGIES` and runs its `outputHint` regex\n * against each agent-cli line. The captured id is recorded on the\n * descriptor so `agentproto sessions restart` can use it.\n *\n * ANSI-stripped before matching so dim/color codes don't break the\n * pattern. Adapters without a strategy entry (or without an\n * outputHint) are skipped — they fall back to ACP-level resume.\n */\n const sniffResumeHints = (rt: SessionRuntime, line: string): void => {\n if (rt.desc.kind !== \"agent-cli\") return\n const strategy = rt.desc.adapterSlug\n ? RESUME_STRATEGIES[rt.desc.adapterSlug]\n : undefined\n if (!strategy?.outputHint) return\n const plain = stripAnsiCodes(line)\n const m = plain.match(strategy.outputHint)\n if (m && m[1]) {\n rt.desc.resumeMetadata = {\n ...(rt.desc.resumeMetadata ?? {}),\n [strategy.storeAs]: m[1],\n }\n schedulePersist()\n }\n }\n\n /**\n * PTY byte ring buffer. Keeps the last ~64 KiB of raw bytes so a\n * fresh attacher sees the current screenful (alt-screen apps like\n * Claude TUI / vim repaint on next interaction but a snapshot is\n * still better than blank). Drops oldest chunks when over cap;\n * never splits within a chunk — Buffer arithmetic on UTF-8 mid-\n * sequence would corrupt multi-byte glyphs.\n */\n const appendBytes = (rt: SessionRuntime, chunk: Buffer): void => {\n rt.recentBytes.push(chunk)\n rt.recentBytesSize += chunk.byteLength\n while (\n rt.recentBytesSize > RECENT_BYTES_CAP &&\n rt.recentBytes.length > 1\n ) {\n const dropped = rt.recentBytes.shift()\n if (dropped) rt.recentBytesSize -= dropped.byteLength\n }\n rt.desc.lastOutputAt = new Date().toISOString()\n rt.emitter.emit(\"data\", chunk)\n }\n\n /**\n * Recompute the smallest cols/rows across the active subscriber\n * set and resize the PTY accordingly (tmux's \"smallest attached\n * client wins\" rule). No-op when the subscriber map is empty.\n */\n const reconcilePtySize = (rt: SessionRuntime): void => {\n if (!rt.pty || !rt.ptySubscribers || rt.ptySubscribers.size === 0) return\n let cols = Infinity\n let rows = Infinity\n for (const dim of rt.ptySubscribers.values()) {\n if (dim.cols < cols) cols = dim.cols\n if (dim.rows < rows) rows = dim.rows\n }\n if (!Number.isFinite(cols) || !Number.isFinite(rows)) return\n try {\n rt.pty.resize(cols, rows)\n } catch {\n // pty may have exited between the emit and the resize — swallow.\n }\n }\n\n /**\n * Project ACP-style stream events into ring-buffer lines. Keeps\n * the line shape simple so the existing /stream SSE consumer\n * (and the xterm panel) just renders them as-is.\n */\n const projectEvent = (rt: SessionRuntime, evt: AgentStreamEvent): void => {\n switch (evt.kind) {\n case \"text-delta\":\n if (evt.text) {\n // text-delta is a stream of chunks — split on newlines so\n // each line lands in the ring buffer separately. Coalesce\n // a trailing fragment via rt.textBuf.\n const combined = rt.textBuf + evt.text\n const lines = combined.split(/\\r?\\n/)\n rt.textBuf = lines.pop() ?? \"\"\n for (const line of lines) appendLine(rt, line, \"stdout\")\n }\n break\n case \"thought\":\n if (evt.text) {\n // Same coalescing as text-delta — some adapters stream\n // chain-of-thought one token at a time, which would\n // otherwise produce ~100 [thought] lines per turn.\n const combined = rt.thoughtBuf + evt.text\n const lines = combined.split(/\\r?\\n/)\n rt.thoughtBuf = lines.pop() ?? \"\"\n for (const line of lines) {\n if (line.trim()) {\n appendLine(rt, `\\x1b[2m[thought] ${line}\\x1b[0m`, \"stdout\")\n }\n }\n }\n break\n case \"tool-call\":\n appendLine(\n rt,\n `\\x1b[36m[tool] ${evt.toolName ?? \"?\"}\\x1b[0m`,\n \"stdout\"\n )\n break\n case \"tool-result\":\n if (evt.isError)\n appendLine(rt, `\\x1b[31m[tool-error]\\x1b[0m`, \"stderr\")\n break\n case \"agent-prompt\":\n rt.desc.awaitingInput = true\n appendLine(rt, `\\x1b[33m[awaiting input]\\x1b[0m`, \"stdout\")\n break\n case \"turn-end\": {\n if (evt.reason === \"awaiting-input\") rt.desc.awaitingInput = true\n // Flush any buffered text/thought fragments as final lines.\n if (rt.thoughtBuf.trim()) {\n appendLine(\n rt,\n `\\x1b[2m[thought] ${rt.thoughtBuf}\\x1b[0m`,\n \"stdout\"\n )\n }\n rt.thoughtBuf = \"\"\n if (rt.textBuf) {\n appendLine(rt, rt.textBuf, \"stdout\")\n rt.textBuf = \"\"\n }\n appendLine(\n rt,\n `\\x1b[2m── turn-end (${evt.reason ?? \"completed\"}) ──\\x1b[0m`,\n \"stdout\"\n )\n break\n }\n case \"error\": {\n const code =\n typeof evt.error?.code === \"number\" ? ` (code ${evt.error.code})` : \"\"\n appendLine(\n rt,\n `\\x1b[31m[error]${code} ${evt.error?.message ?? \"unknown\"}\\x1b[0m`,\n \"stderr\"\n )\n // Project the child's stderr tail when define-agent-cli\n // attached it — otherwise the user sees only \"Invalid\n // params\" and has to dig into the daemon log for context.\n const data = evt.error?.data as\n | { stderr?: unknown }\n | null\n | undefined\n if (data && typeof data === \"object\" && typeof data.stderr === \"string\") {\n for (const line of data.stderr.split(/\\r?\\n/)) {\n if (line) appendLine(rt, `\\x1b[2m ${line}\\x1b[0m`, \"stderr\")\n }\n }\n break\n }\n }\n }\n\n /**\n * Drive one agent turn. Sets busy=true, drains the event stream\n * into the ring buffer, clears busy on completion. Bumps the\n * descriptor status to \"error\" if the iteration throws (network\n * drop, child died mid-turn).\n */\n /**\n * Shared sync validation for sendPrompt + enqueuePrompt. Throws on\n * missing session / wrong kind / busy so both code paths surface\n * the exact same error messages — the only difference is whether\n * the caller awaits the turn.\n */\n const validateAgentTurn = (id: string, caller: string): SessionRuntime => {\n const rt = sessions.get(id)\n if (!rt) throw new Error(`${caller}: no session \"${id}\"`)\n if (!rt.agentSession) {\n throw new Error(\n `${caller}: session \"${id}\" is not an agent session (kind=${rt.desc.kind})`\n )\n }\n if (rt.busy) {\n throw new Error(\n `${caller}: session \"${id}\" is mid-turn — wait for it to finish or cancel`\n )\n }\n return rt\n }\n\n /**\n * Attempt to resume a dead agent-cli session by re-spawning the\n * adapter with the persisted `adapterSessionId`. The conversation\n * continues from where it left off — ACP's `resumeSessionId`\n * contract guarantees the adapter rehydrates state from the\n * upstream provider (Anthropic / OpenAI / etc.) when supported.\n *\n * Returns silently when:\n * - resumeAgent hook wasn't provided (older daemon embedding)\n * - session is already alive (binding present)\n * - session is a non-agent kind (terminal/command can't resume)\n * - descriptor lacks adapterSessionId or adapterSlug (legacy row\n * persisted before resume metadata was tracked)\n *\n * Concurrent prompt arrivals share one resume attempt via\n * `rt.resumePromise`.\n */\n const maybeResumeAgent = async (rt: SessionRuntime): Promise<void> => {\n if (rt.agentSession) return\n if (!resumeAgent) return\n if (rt.desc.kind !== \"agent-cli\") return\n const adapterSlug = rt.desc.adapterSlug ?? rt.adapterSlug\n const adapterSessionId = rt.desc.adapterSessionId\n const cwd = rt.desc.cwd\n if (!adapterSlug || !adapterSessionId || !cwd) return\n if (rt.resumePromise) {\n await rt.resumePromise\n return\n }\n rt.resumePromise = (async () => {\n appendLine(\n rt,\n `── resuming ${adapterSlug} session ${adapterSessionId} ──`,\n \"stdout\"\n )\n try {\n const fresh = await resumeAgent({\n adapterSlug,\n cwd,\n resumeSessionId: adapterSessionId,\n // Re-mount the persisted spawn-time toolset (orchestrator WP1).\n ...(rt.desc.mcpServers ? { mcpServers: rt.desc.mcpServers } : {}),\n })\n if (!fresh) {\n appendLine(\n rt,\n `[error] resume failed: adapter '${adapterSlug}' returned null`,\n \"stderr\"\n )\n return\n }\n rt.agentSession = fresh\n rt.adapterSlug = adapterSlug\n rt.desc.adapterSessionId = fresh.sessionId\n if (rt.desc.status !== \"running\") {\n rt.desc.status = \"running\"\n delete rt.desc.endedAt\n delete rt.desc.exitCode\n rt.emitter.emit(\"status\", rt.desc.status)\n }\n schedulePersist()\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err)\n appendLine(rt, `[error] resume failed: ${msg}`, \"stderr\")\n }\n })()\n try {\n await rt.resumePromise\n } finally {\n rt.resumePromise = undefined\n }\n }\n\n const runAgentTurn = async (\n rt: SessionRuntime,\n message: unknown\n ): Promise<void> => {\n if (!rt.agentSession) {\n throw new Error(\"runAgentTurn: session has no agentSession\")\n }\n rt.busy = true\n rt.desc.busy = true // mirror onto the public descriptor for wait_for_any\n rt.desc.awaitingInput = false // clear stale awaiting-input flag from prior turn\n let turnCompleted = false\n try {\n appendLine(\n rt,\n `\\x1b[2m── ▶ ${typeof message === \"string\" ? message : JSON.stringify(message)} ──\\x1b[0m`,\n \"stdout\"\n )\n // ACP's `prompt` field expects ContentBlock[] (or a single\n // block). Hosts that send a raw string get auto-wrapped into\n // `{type: \"text\", text: \"...\"}` so callers can hand us\n // human-friendly prompts without shaping the wire format.\n const wrapped =\n typeof message === \"string\" ? { type: \"text\", text: message } : message\n for await (const evt of rt.agentSession.send(wrapped)) {\n projectEvent(rt, evt)\n }\n turnCompleted = true\n } catch (err) {\n rt.desc.status = \"error\"\n rt.desc.endedAt = new Date().toISOString()\n appendLine(\n rt,\n `[turn error] ${err instanceof Error ? err.message : String(err)}`,\n \"stderr\"\n )\n schedulePersist()\n emitExited(rt)\n } finally {\n rt.busy = false\n rt.desc.busy = false // mirror onto the public descriptor for wait_for_any\n if (turnCompleted && sessionEvents) {\n // Record that a turn finished so a late `wait_for_any` (subscribed\n // after a fast turn already ended) can still fast-return.\n rt.desc.turnsCompleted = (rt.desc.turnsCompleted ?? 0) + 1\n\n // ── Cost refresh + cap (best-effort) ─────────────────────────\n if (rt.readUsage) {\n try {\n const usage = await rt.readUsage()\n if (usage) {\n if (usage.costUsd !== undefined) rt.desc.costUsd = usage.costUsd\n if (usage.tokensIn !== undefined) rt.desc.tokensIn = usage.tokensIn\n if (usage.tokensOut !== undefined) rt.desc.tokensOut = usage.tokensOut\n }\n } catch {\n // best-effort — swallow\n }\n }\n const overBudget =\n rt.maxCostUsd !== undefined &&\n rt.desc.costUsd !== undefined &&\n rt.desc.costUsd > rt.maxCostUsd\n if (overBudget) {\n appendLine(\n rt,\n `[cost-cap] cost $${rt.desc.costUsd} exceeds max $${rt.maxCostUsd} — killing session`,\n \"stderr\",\n )\n rt.desc.status = \"killed\"\n rt.desc.endedAt = new Date().toISOString()\n void rt.agentSession?.close().catch(() => undefined)\n }\n\n const ts = new Date().toISOString()\n sessionEvents.emit({\n type: \"session:turn-end\",\n sessionId: rt.desc.id,\n awaitingInput: rt.desc.awaitingInput ?? false,\n label: rt.desc.label,\n ts,\n })\n if (rt.desc.awaitingInput) {\n sessionEvents.emit({\n type: \"session:awaiting-input\",\n sessionId: rt.desc.id,\n label: rt.desc.label,\n ts,\n })\n }\n if (overBudget) emitExited(rt)\n }\n }\n }\n\n const wireOutputStreams = (rt: SessionRuntime): void => {\n const onChunk =\n (stream: \"stdout\" | \"stderr\") =>\n (chunk: Buffer | string): void => {\n const text = typeof chunk === \"string\" ? chunk : chunk.toString(\"utf8\")\n for (const line of text.split(/\\r?\\n/)) {\n if (line.length > 0) appendLine(rt, line, stream)\n }\n }\n // Only called from spawn() which always sets rt.child — narrow\n // here so the stream listeners don't trip the optional-chain.\n if (!rt.child) return\n rt.child.stdout?.on(\"data\", onChunk(\"stdout\"))\n rt.child.stderr?.on(\"data\", onChunk(\"stderr\"))\n }\n\n return {\n spawn(input) {\n const id = input.id ?? `sess_${randomUUID().slice(0, 8)}`\n if (sessions.has(id)) {\n throw new Error(`sessions.spawn: id \"${id}\" already in use`)\n }\n const env = { ...process.env, ...(input.env ?? {}) }\n // Filter out Node bookkeeping that confuses subprocesses.\n delete env.NODE_OPTIONS\n const [bin, ...args] = input.argv\n if (!bin) throw new Error(\"sessions.spawn: argv must include a binary\")\n // Close stdin by default — most agent CLIs spawn-and-prompt\n // (claude/codex/aider/etc.) read argv for the prompt and will\n // otherwise sit waiting for piped input. Caller opts in to a\n // writeable stdin via `keepStdin: true` (terminal/PTY kinds).\n const stdinMode = input.keepStdin ? \"pipe\" : \"ignore\"\n const child = spawn(bin, args, {\n cwd: input.cwd,\n env: env as NodeJS.ProcessEnv,\n stdio: [stdinMode, \"pipe\", \"pipe\"],\n })\n const desc: SessionDescriptor = {\n id,\n kind: input.kind,\n workspaceSlug: input.workspaceSlug,\n command: [bin, ...args].map(quoteArg).join(\" \"),\n pid: child.pid ?? null,\n status: \"starting\",\n startedAt: new Date().toISOString(),\n argv: input.argv,\n cwd: input.cwd,\n ...(input.label ? { label: input.label } : {}),\n }\n const rt: SessionRuntime = {\n desc,\n child,\n recentLines: [],\n recentBytes: [],\n recentBytesSize: 0,\n emitter: new EventEmitter(),\n busy: false,\n textBuf: \"\",\n thoughtBuf: \"\",\n }\n // Don't crash the daemon when no listener is attached — the\n // emitter's \"error\" event would otherwise propagate.\n rt.emitter.setMaxListeners(50)\n\n sessions.set(id, rt)\n wireOutputStreams(rt)\n\n child.once(\"spawn\", () => {\n desc.status = \"running\"\n rt.emitter.emit(\"status\", desc.status)\n schedulePersist()\n })\n child.once(\"error\", err => {\n desc.status = \"error\"\n desc.endedAt = new Date().toISOString()\n appendLine(rt, `[spawn error] ${err.message}`, \"stderr\")\n rt.emitter.emit(\"status\", desc.status)\n schedulePersist()\n emitExited(rt)\n })\n child.once(\"exit\", (code, signal) => {\n if (signal && desc.status !== \"killed\") desc.status = \"killed\"\n else if (desc.status === \"running\" || desc.status === \"starting\") {\n desc.status = \"exited\"\n }\n desc.endedAt = new Date().toISOString()\n if (typeof code === \"number\") desc.exitCode = code\n rt.emitter.emit(\"status\", desc.status)\n schedulePersist()\n emitExited(rt)\n })\n schedulePersist()\n return desc\n },\n register(input) {\n if (sessions.has(input.id)) {\n // Already adopted (re-tracking is a noop). Return the\n // existing descriptor so callers don't have to special-case.\n const existing = sessions.get(input.id)\n if (existing) return existing.desc\n }\n const desc: SessionDescriptor = {\n id: input.id,\n kind: input.kind ?? \"command\",\n workspaceSlug: input.workspaceSlug,\n command: input.command,\n pid: input.child.pid ?? null,\n status: input.child.killed ? \"killed\" : \"running\",\n startedAt: new Date().toISOString(),\n ...(input.label ? { label: input.label } : {}),\n }\n const rt: SessionRuntime = {\n desc,\n child: input.child,\n recentLines: [],\n recentBytes: [],\n recentBytesSize: 0,\n emitter: new EventEmitter(),\n busy: false,\n textBuf: \"\",\n thoughtBuf: \"\",\n }\n rt.emitter.setMaxListeners(50)\n sessions.set(input.id, rt)\n wireOutputStreams(rt)\n // Wire exit so the descriptor flips when the adopted child\n // dies — same handlers as spawn() but registered post-hoc\n // because the child is already alive.\n input.child.once(\"exit\", (code, signal) => {\n if (signal && desc.status !== \"killed\") desc.status = \"killed\"\n else if (desc.status === \"running\") desc.status = \"exited\"\n desc.endedAt = new Date().toISOString()\n if (typeof code === \"number\") desc.exitCode = code\n rt.emitter.emit(\"status\", desc.status)\n schedulePersist()\n emitExited(rt)\n })\n input.child.once(\"error\", err => {\n desc.status = \"error\"\n desc.endedAt = new Date().toISOString()\n appendLine(rt, `[child error] ${err.message}`, \"stderr\")\n rt.emitter.emit(\"status\", desc.status)\n schedulePersist()\n emitExited(rt)\n })\n schedulePersist()\n return desc\n },\n spawnAgent(input) {\n const id = `sess_${randomUUID().slice(0, 8)}`\n const desc: SessionDescriptor = {\n id,\n kind: \"agent-cli\",\n workspaceSlug: input.workspaceSlug,\n command: input.commandPreview ?? `${input.adapterSlug} (agent)`,\n pid: null,\n status: \"running\", // driver already started the session\n startedAt: new Date().toISOString(),\n cwd: input.cwd,\n adapterSlug: input.adapterSlug,\n // ACP-level session id — sticks across daemon restart so\n // `agentproto sessions restart <id>` can pass it as\n // `resumeSessionId` and the adapter reattaches to the prior\n // conversation rather than starting blank.\n adapterSessionId: input.agentSession.sessionId,\n ...(input.label ? { label: input.label } : {}),\n // Persist the spawn-time MCP mounts so resume re-mounts the same\n // toolset (orchestrator WP1). Reference-only shape — no secrets.\n ...(input.mcpServers ? { mcpServers: input.mcpServers } : {}),\n // Parent attribution + depth (orchestrator WP4). Depth is always\n // recorded (defaults to 0) so subtree/depth logic never has to\n // distinguish \"absent\" from \"root\".\n ...(input.parentSessionId\n ? { parentSessionId: input.parentSessionId }\n : {}),\n depth: input.depth ?? 0,\n ...(input.model ? { model: input.model } : {}),\n }\n const rt: SessionRuntime = {\n desc,\n agentSession: input.agentSession,\n adapterSlug: input.adapterSlug,\n recentLines: [],\n recentBytes: [],\n recentBytesSize: 0,\n emitter: new EventEmitter(),\n busy: false,\n textBuf: \"\",\n thoughtBuf: \"\",\n maxCostUsd: input.maxCostUsd,\n readUsage: input.readUsage,\n }\n rt.emitter.setMaxListeners(50)\n sessions.set(id, rt)\n appendLine(\n rt,\n `── ${input.adapterSlug} agent session ${input.agentSession.sessionId} (cwd ${input.cwd}) ──`,\n \"stdout\"\n )\n schedulePersist()\n // Fire-and-forget the initial prompt (if any). Errors land in\n // the ring buffer + bump status to \"error\" but don't reject\n // the spawn — the descriptor was already returned.\n if (input.initialPrompt) {\n void runAgentTurn(rt, input.initialPrompt).catch(err => {\n appendLine(\n rt,\n `[turn error] ${err instanceof Error ? err.message : String(err)}`,\n \"stderr\"\n )\n })\n }\n return desc\n },\n spawnPty(input) {\n if (!ptyFactory) {\n throw new Error(\n \"sessions.spawnPty: no PTY factory configured (node-pty optional dep missing in the daemon)\"\n )\n }\n const id = `sess_${randomUUID().slice(0, 8)}`\n // Reject the name only when the prior holder is still alive —\n // killed/exited/error sessions keep their descriptor in the\n // registry for history, but their name is free to reuse so\n // `stop X && terminal --name X` round-trips cleanly.\n if (input.name) {\n for (const rt of sessions.values()) {\n if (rt.desc.name !== input.name) continue\n const status = rt.desc.status\n if (status === \"running\" || status === \"starting\") {\n throw new Error(\n `sessions.spawnPty: name \"${input.name}\" already in use by ${rt.desc.id} (status=${status})`,\n )\n }\n // Free the name on the dead session so id-or-name lookup\n // resolves to the NEW one. The old descriptor stays in the\n // registry (you can still find it by id in the list).\n rt.desc.name = undefined\n }\n }\n const [bin, ...args] = input.argv\n if (!bin) {\n throw new Error(\"sessions.spawnPty: argv must include a binary\")\n }\n // node-pty forces its own minimal env unless we forward — pass\n // process.env merged with caller overrides. The factory layer\n // also forces TERM=xterm-256color so alt-screen apps render.\n const env = { ...(process.env as Record<string, string>), ...(input.env ?? {}) }\n delete env.NODE_OPTIONS\n const pty: PtyProcess = ptyFactory({\n command: bin,\n args,\n cwd: input.cwd,\n env,\n cols: input.cols,\n rows: input.rows,\n })\n const desc: SessionDescriptor = {\n id,\n kind: \"terminal\",\n workspaceSlug: input.workspaceSlug,\n command: [bin, ...args].map(quoteArg).join(\" \"),\n pid: pty.pid,\n status: \"running\",\n startedAt: new Date().toISOString(),\n pty: true,\n argv: input.argv,\n cwd: input.cwd,\n ...(input.name ? { name: input.name } : {}),\n ...(input.label ? { label: input.label } : {}),\n }\n const rt: SessionRuntime = {\n desc,\n pty,\n ptySubscribers: new Map(),\n recentLines: [],\n recentBytes: [],\n recentBytesSize: 0,\n emitter: new EventEmitter(),\n busy: false,\n textBuf: \"\",\n thoughtBuf: \"\",\n }\n rt.emitter.setMaxListeners(50)\n sessions.set(id, rt)\n pty.onData((chunk: string) => {\n // node-pty emits utf-8 strings. Convert once at the boundary\n // so the ring buffer + emitter consumers all see Buffer.\n appendBytes(rt, Buffer.from(chunk, \"utf8\"))\n })\n pty.onExit(evt => {\n if (rt.desc.status !== \"killed\") {\n rt.desc.status = \"exited\"\n }\n rt.desc.endedAt = new Date().toISOString()\n if (typeof evt.exitCode === \"number\") rt.desc.exitCode = evt.exitCode\n rt.emitter.emit(\"exit\", evt)\n rt.emitter.emit(\"status\", rt.desc.status)\n schedulePersist()\n emitExited(rt)\n })\n schedulePersist()\n return desc\n },\n registerBrowser(input) {\n const inputLocation = input.location ?? \"local\"\n // Idempotent: reuse an alive session for the same (adapterId, port, location).\n // Location is part of the key so a cloud call never returns a local session.\n for (const rt of sessions.values()) {\n if (\n rt.desc.kind === \"browser\" &&\n rt.desc.browserAdapterId === input.adapterId &&\n rt.desc.browserPort === input.port &&\n (rt.desc.browserLocation ?? \"local\") === inputLocation &&\n (rt.desc.status === \"running\" || rt.desc.status === \"starting\")\n ) {\n // Update label on idempotent hit so callers can stamp correlation\n // context (guild/op/workItem) onto a long-lived browser session.\n if (input.label !== undefined) {\n rt.desc.label = input.label\n schedulePersist()\n }\n return rt.desc\n }\n }\n const id = `sess_${randomUUID().slice(0, 8)}`\n const desc: SessionDescriptor = {\n id,\n kind: \"browser\",\n workspaceSlug: \"\",\n command: `${input.adapterId} (browser)`,\n pid: input.pid ?? null,\n status: input.status ?? \"running\",\n startedAt: new Date().toISOString(),\n browserAdapterId: input.adapterId,\n browserPort: input.port,\n browserBaseUrl: input.baseUrl,\n browserLocation: inputLocation,\n ...(input.label ? { label: input.label } : {}),\n }\n const rt: SessionRuntime = {\n desc,\n browserStop: input.stop,\n recentLines: [],\n recentBytes: [],\n recentBytesSize: 0,\n emitter: new EventEmitter(),\n busy: false,\n textBuf: \"\",\n thoughtBuf: \"\",\n }\n rt.emitter.setMaxListeners(50)\n sessions.set(id, rt)\n schedulePersist()\n return desc\n },\n async sendPrompt(id, message) {\n const rtPre = sessions.get(id)\n if (rtPre) await maybeResumeAgent(rtPre)\n const rt = validateAgentTurn(id, \"sendPrompt\")\n await runAgentTurn(rt, message)\n },\n enqueuePrompt(id, message) {\n // For sync `enqueuePrompt`, we need to surface an immediate\n // error when the session is missing OR when it's a non-agent\n // kind that can't be resumed at all. But when the session IS\n // an agent-cli with resume metadata, defer validation until\n // after the resume attempt so a dead-but-resumable row Just\n // Works for the caller (no \"not an agent session\" error after\n // a daemon restart).\n const rtPre = sessions.get(id)\n if (!rtPre) {\n throw new Error(`enqueuePrompt: no session \"${id}\"`)\n }\n if (rtPre.desc.kind !== \"agent-cli\") {\n throw new Error(\n `enqueuePrompt: session \"${id}\" is not an agent session (kind=${rtPre.desc.kind})`\n )\n }\n if (rtPre.busy) {\n throw new Error(\n `enqueuePrompt: session \"${id}\" is mid-turn — wait for it to finish or cancel`\n )\n }\n // Fire-and-forget: resume (if needed) then dispatch. Errors\n // during either step land in the ring buffer as `[error]`\n // lines so the SSE consumer sees them.\n void (async () => {\n try {\n await maybeResumeAgent(rtPre)\n const rt = validateAgentTurn(id, \"enqueuePrompt\")\n await runAgentTurn(rt, message)\n } catch (err) {\n appendLine(\n rtPre,\n `[error] ${err instanceof Error ? err.message : String(err)}`,\n \"stderr\"\n )\n }\n })()\n },\n list() {\n return Array.from(sessions.values())\n .map(s => s.desc)\n .sort((a, b) => b.startedAt.localeCompare(a.startedAt))\n },\n get(id) {\n return sessions.get(id)?.desc\n },\n attach(id, onLine) {\n const rt = sessions.get(id)\n if (!rt) return null\n // Backfill: synchronously replay the ring buffer so attaches\n // see the recent context, then subscribe for new lines.\n for (const line of rt.recentLines) onLine(line, \"stdout\")\n const handler = (evt: {\n line: string\n stream: \"stdout\" | \"stderr\"\n }): void => onLine(evt.line, evt.stream)\n rt.emitter.on(\"line\", handler)\n return () => rt.emitter.off(\"line\", handler)\n },\n attachPty(id, initial, onData, onExit) {\n const rt = sessions.get(id)\n if (!rt || !rt.pty || !rt.ptySubscribers) return null\n // Backfill: flush the byte ring buffer so a fresh attach lands\n // on the recent screenful. Alt-screen apps repaint on next\n // input but a snapshot is still better than blank.\n for (const chunk of rt.recentBytes) onData(chunk)\n // Subscriber registration: a monotonically-growing key so the\n // size map can hold the per-subscriber dims and detach is O(1).\n const subId = nextSubId++\n rt.ptySubscribers.set(subId, { cols: initial.cols, rows: initial.rows })\n reconcilePtySize(rt)\n const dataHandler = (chunk: Buffer): void => onData(chunk)\n const exitHandler = (evt: {\n exitCode: number\n signal?: number\n }): void => onExit(evt)\n rt.emitter.on(\"data\", dataHandler)\n rt.emitter.once(\"exit\", exitHandler)\n return {\n write(data: string): void {\n if (!rt.pty) return\n try {\n rt.pty.write(data)\n } catch {\n // PTY already exited — drop the input silently.\n }\n },\n resize(cols: number, rows: number): void {\n if (!rt.ptySubscribers) return\n rt.ptySubscribers.set(subId, { cols, rows })\n reconcilePtySize(rt)\n },\n detach(): void {\n rt.emitter.off(\"data\", dataHandler)\n rt.emitter.off(\"exit\", exitHandler)\n rt.ptySubscribers?.delete(subId)\n reconcilePtySize(rt)\n },\n }\n },\n findByIdOrName(query) {\n const direct = sessions.get(query)\n if (direct) return direct.desc\n for (const rt of sessions.values()) {\n if (rt.desc.name === query) return rt.desc\n }\n return undefined\n },\n writeTerminalInput(id, data) {\n const rt = sessions.get(id)\n if (!rt || !rt.pty) return false\n try {\n rt.pty.write(data)\n return true\n } catch {\n return false\n }\n },\n readTerminalOutput(id, lastBytes) {\n const rt = sessions.get(id)\n if (!rt || !rt.pty) return null\n const joined = Buffer.concat(rt.recentBytes, rt.recentBytesSize)\n if (typeof lastBytes === \"number\" && lastBytes > 0 && joined.byteLength > lastBytes) {\n return joined.subarray(joined.byteLength - lastBytes)\n }\n return joined\n },\n kill(id, signal = \"SIGTERM\") {\n const rt = sessions.get(id)\n if (!rt) return false\n if (\n rt.desc.status === \"exited\" ||\n rt.desc.status === \"killed\" ||\n rt.desc.status === \"error\"\n ) {\n return false\n }\n rt.desc.status = \"killed\"\n rt.desc.endedAt = new Date().toISOString()\n // Close agent session first (graceful protocol shutdown), then\n // SIGTERM the underlying child/pty if any. Either branch is a\n // best-effort — the descriptor flip is what the UI surfaces.\n if (rt.agentSession) {\n void rt.agentSession.close().catch(() => undefined)\n }\n if (rt.pty) {\n try {\n rt.pty.kill(signal)\n } catch {\n // pty already gone — fall through\n }\n }\n rt.child?.kill(signal)\n if (rt.browserStop) {\n void rt.browserStop().catch(() => undefined)\n }\n schedulePersist()\n // Agent-cli sessions have no OS exit event — emit here.\n // Child/PTY sessions emit from their exit handlers; the\n // exitedEmitted guard prevents a duplicate from kill() AND exit.\n emitExited(rt)\n return true\n },\n forget(id) {\n const rt = sessions.get(id)\n if (!rt) return false\n // Don't leak: tear down the emitter so backfill listeners stop.\n rt.emitter.removeAllListeners()\n sessions.delete(id)\n schedulePersist()\n return true\n },\n shutdown() {\n shutdownImpl()\n },\n }\n\n /**\n * The actual shutdown logic, hoisted so both the explicit\n * `shutdown()` method AND the `process.on(\"exit\")` safety net\n * can call it. Sync (no awaits) so it works in the `exit` event\n * handler.\n *\n * Idempotent — `serve --interactive` calls gateway.stop() twice in\n * some Ctrl-C race paths (parent SIGINT handler + the child-exit\n * promise both fire), and `process.on(\"exit\")` ALSO fires at the\n * end of every termination path. Without the guard, the second\n * call clears the already-empty sessions Map and writes an empty\n * snapshot back to sessions.json, wiping history.\n */\n function shutdownImpl(): void {\n if (shutdownDone) return\n shutdownDone = true\n if (persistTimer) clearTimeout(persistTimer)\n if (persist) {\n try {\n process.off(\"exit\", onProcessExit)\n } catch {\n // ignore — handler may not be installed\n }\n }\n // Mark any still-alive sessions as killed BEFORE the final\n // flush so the snapshot accurately reflects what happened. On\n // the next boot, load reads these and we won't have to guess\n // (\"was running last time → assume killed\" is then a no-op).\n const nowIso = new Date().toISOString()\n for (const rt of sessions.values()) {\n rt.emitter.removeAllListeners()\n if (\n rt.desc.status === \"running\" ||\n rt.desc.status === \"starting\"\n ) {\n rt.desc.status = \"killed\"\n rt.desc.endedAt = nowIso\n if (rt.agentSession) {\n void rt.agentSession.close().catch(() => undefined)\n }\n if (rt.pty) {\n try {\n rt.pty.kill(\"SIGTERM\")\n } catch {\n // already exited\n }\n }\n rt.child?.kill(\"SIGTERM\")\n }\n }\n // Sync flush so quick sessions (spawned + ended in less than\n // PERSIST_DEBOUNCE_MS) aren't lost. The debounced async write\n // may have been cancelled by clearTimeout above, but a 200-byte\n // sync write at shutdown is cheap and the data needs to land.\n if (persist) {\n try {\n const snapshot = {\n savedAt: nowIso,\n sessions: Array.from(sessions.values()).map(s => s.desc),\n }\n mkdirSync(dirname(persistPath), { recursive: true })\n writeFileSync(persistPath, JSON.stringify(snapshot, null, 2) + \"\\n\")\n } catch {\n // best-effort — same policy as the async path\n }\n }\n sessions.clear()\n }\n}\n\n/**\n * Read the persisted snapshot at boot and reinflate session\n * descriptors as historical \"ghost\" entries. Sync-read because this\n * runs once at construction, the file is small (~200 entries), and\n * keeping it sync avoids making createSessionsRegistry async (would\n * cascade through createGateway + every embedding host).\n *\n * Anything that was \"running\"/\"starting\" when the daemon last died\n * gets re-classified as \"killed\" with endedAt=now — we can't tell\n * if the orphan PID survived the daemon's exit, and pretending it's\n * still alive would make attach/kill calls fail mysteriously. The\n * descriptor stays in the registry for history; the dashboard sees\n * it under SESSIONS, the user can `d` to forget.\n *\n * Ghosts carry NO live child / agentSession / pty — calls that\n * would interact with the underlying process degrade to no-ops.\n * Output ring buffers (lines + bytes) are empty: we don't persist\n * those, only the descriptor metadata.\n */\nfunction loadHistorySnapshot(\n persistPath: string,\n sessions: Map<string, SessionRuntime>,\n): void {\n let raw: string\n try {\n raw = readFileSync(persistPath, \"utf8\")\n } catch {\n return // ENOENT etc. — first boot, no history.\n }\n let parsed: { sessions?: SessionDescriptor[] }\n try {\n parsed = JSON.parse(raw)\n } catch {\n console.warn(\n `[sessions] history file ${persistPath} is malformed — ignoring`,\n )\n return\n }\n if (!Array.isArray(parsed.sessions)) return\n // Newest first so the FIFO cap drops oldest.\n const sorted = parsed.sessions\n .filter((s): s is SessionDescriptor => !!s && typeof s.id === \"string\")\n .sort((a, b) => b.startedAt.localeCompare(a.startedAt))\n .slice(0, HISTORY_CAP)\n const now = new Date().toISOString()\n for (const desc of sorted) {\n if (sessions.has(desc.id)) continue // collision with a live entry — keep live\n const wasAlive = desc.status === \"running\" || desc.status === \"starting\"\n const reclassified: SessionDescriptor = wasAlive\n ? {\n ...desc,\n status: \"killed\",\n endedAt: desc.endedAt ?? now,\n }\n : desc\n const rt: SessionRuntime = {\n desc: reclassified,\n recentLines: [],\n recentBytes: [],\n recentBytesSize: 0,\n emitter: new EventEmitter(),\n busy: false,\n textBuf: \"\",\n thoughtBuf: \"\",\n }\n rt.emitter.setMaxListeners(50)\n sessions.set(desc.id, rt)\n }\n}\n\n/** Minimal shell-quote — wraps args containing whitespace or quotes\n * so the rendered `command` field is copy-pasteable. */\nfunction quoteArg(arg: string): string {\n if (arg === \"\") return '\"\"'\n if (/^[a-zA-Z0-9._/=:@,+-]+$/.test(arg)) return arg\n return `\"${arg.replace(/([\"\\\\$`])/g, \"\\\\$1\")}\"`\n}\n","/**\n * mcp-proxy — connect the daemon as an MCP *client* to every server\n * the user imported via `~/.agentproto/imported-mcps.json`, and\n * surface their tools through dedicated MCP tools on the daemon's\n * own server. The chain looks like:\n *\n * operator (cloud Guilde) ──MCP──▶ agentproto-daemon (this proxy)\n * │\n * ├──stdio──▶ chrome-devtools-mcp\n * └──http───▶ goose-bridge\n *\n * v1 design choice: instead of re-registering each upstream tool\n * under a namespaced name (which requires JSON-Schema↔Zod conversion\n * for every exotic shape — recursive refs, oneOf, etc.), the proxy\n * exposes two indirection tools:\n * - `mcp_list_imported_tools(alias?)` lets the operator discover\n * what's available\n * - `mcp_call_imported(alias, toolName, args)` invokes a specific\n * tool, forwarding the JSON args verbatim\n *\n * Trade-off: agents do a 2-step (list → call) instead of seeing the\n * imports directly in their tool palette. We keep tool inputs\n * unconstrained at the MCP layer; validation is the upstream\n * server's job. v2 can re-expose namespaced tools once we ship a\n * solid JSON-Schema → Zod converter.\n *\n * Lifecycle: clients are connected lazily on the first call that\n * touches them and held open until daemon shutdown. The registry\n * notices new/removed imports by stat'ing the imports file's mtime\n * before each call — cheap, avoids forcing the HTTP routes to push.\n */\n\nimport { promises as fs } from \"node:fs\"\nimport { Client } from \"@modelcontextprotocol/sdk/client/index.js\"\nimport { StdioClientTransport } from \"@modelcontextprotocol/sdk/client/stdio.js\"\nimport { StreamableHTTPClientTransport } from \"@modelcontextprotocol/sdk/client/streamableHttp.js\"\nimport { SSEClientTransport } from \"@modelcontextprotocol/sdk/client/sse.js\"\nimport {\n loadImportedMcps,\n IMPORTED_MCPS_PATH,\n type ImportedMcpEntry,\n} from \"./mcp-imports.js\"\nimport type { DiscoveredMcp } from \"./mcp-discovery.js\"\n\ninterface ProxyClient {\n entry: ImportedMcpEntry\n /** Live MCP client. Null while a connect is in-flight or after a\n * connection error — the next call retries. */\n client: Client | null\n /** Tools list cached after the first successful fetch. Cleared on\n * disconnect so stale tool names don't survive a reconnect. */\n tools: ProxyToolDescriptor[] | null\n /** Last connection error message, kept so listAliases can surface\n * diagnostics to the operator without re-throwing on every list. */\n lastError: string | null\n}\n\nexport interface ProxyToolDescriptor {\n name: string\n description?: string\n /** JSON Schema as published by the upstream server. Forwarded to\n * the operator verbatim — they read it to figure out args. */\n inputSchema?: unknown\n}\n\nexport interface ProxyAliasSummary {\n alias: string\n importId: string\n source: DiscoveredMcp[\"source\"]\n type: DiscoveredMcp[\"type\"]\n /** \"connected\" | \"error\" | \"pending\" — pending = never tried yet. */\n status: \"connected\" | \"error\" | \"pending\"\n toolCount: number\n lastError?: string\n}\n\nexport interface CallResult {\n ok: true\n result: unknown\n}\nexport interface CallError {\n ok: false\n error: string\n}\nexport type ProxyCallOutcome = CallResult | CallError\n\nexport class McpProxyRegistry {\n private clients = new Map<string, ProxyClient>()\n private lastMtimeMs = 0\n /** Sentinel so we know whether the file has *ever* been read.\n * Distinguishes \"file missing on first call\" (legit empty state)\n * from \"we've read it before and it's gone\" (treat as empty too,\n * but only after closing live clients). */\n private hasReadOnce = false\n\n /**\n * Reload the imports file when its mtime has advanced. Avoids\n * repeated parsing when nothing changed — most calls are no-ops.\n * Disconnects clients whose import was removed; connects the new\n * set lazily (the first call that touches them).\n */\n async ensureCurrent(): Promise<void> {\n let mtimeMs = 0\n try {\n const st = await fs.stat(IMPORTED_MCPS_PATH())\n mtimeMs = st.mtimeMs\n } catch {\n // ENOENT — empty imports state. If we'd previously loaded\n // some, close them.\n mtimeMs = 0\n }\n if (this.hasReadOnce && mtimeMs === this.lastMtimeMs) return\n\n const config = await loadImportedMcps().catch(() => ({\n version: 1 as const,\n imports: [] as ImportedMcpEntry[],\n }))\n const wantedIds = new Set(config.imports.map(e => e.id))\n\n // Drop clients for imports the user removed.\n for (const [id, c] of this.clients.entries()) {\n if (!wantedIds.has(id)) {\n await safeClose(c.client)\n this.clients.delete(id)\n }\n }\n // Add placeholders for new imports — connect lazily.\n for (const entry of config.imports) {\n const existing = this.clients.get(entry.id)\n if (existing) {\n // Snapshot may have changed (user re-imported same id with\n // different command). Detect by comparing serialised\n // snapshots; on mismatch, force reconnect.\n if (\n JSON.stringify(existing.entry.snapshot) !==\n JSON.stringify(entry.snapshot)\n ) {\n await safeClose(existing.client)\n this.clients.set(entry.id, freshPlaceholder(entry))\n } else {\n existing.entry = entry\n }\n } else {\n this.clients.set(entry.id, freshPlaceholder(entry))\n }\n }\n this.lastMtimeMs = mtimeMs\n this.hasReadOnce = true\n }\n\n /**\n * Lazy connect: the first call to `connectIfNeeded(alias)`\n * actually opens the transport + handshakes. Subsequent calls\n * reuse the live client.\n */\n private async connectIfNeeded(alias: string): Promise<ProxyClient | null> {\n await this.ensureCurrent()\n const handle = this.findByAlias(alias)\n if (!handle) return null\n if (handle.client) return handle\n try {\n const client = await openClient(handle.entry)\n handle.client = client\n handle.lastError = null\n // Eagerly fetch tools so listTools doesn't pay the round-trip\n // on next call. Cheap (single tools/list request).\n const t = await client.listTools()\n handle.tools = t.tools.map(toDescriptor)\n return handle\n } catch (err) {\n handle.client = null\n handle.tools = null\n handle.lastError = err instanceof Error ? err.message : String(err)\n return handle\n }\n }\n\n /** Find a client handle by alias *or* import id (defensive — agents\n * sometimes pass the id from `list_imported_mcps`). */\n private findByAlias(aliasOrId: string): ProxyClient | undefined {\n for (const c of this.clients.values()) {\n if (c.entry.alias === aliasOrId) return c\n if (c.entry.id === aliasOrId) return c\n }\n return undefined\n }\n\n async listAliases(): Promise<ProxyAliasSummary[]> {\n await this.ensureCurrent()\n return Array.from(this.clients.values()).map(c => ({\n alias: c.entry.alias,\n importId: c.entry.id,\n source: c.entry.snapshot.source,\n type: c.entry.snapshot.type,\n status: c.client\n ? \"connected\"\n : c.lastError\n ? \"error\"\n : \"pending\",\n toolCount: c.tools?.length ?? 0,\n ...(c.lastError ? { lastError: c.lastError } : {}),\n }))\n }\n\n async listTools(\n alias: string\n ): Promise<{ ok: true; tools: ProxyToolDescriptor[] } | { ok: false; error: string }> {\n const handle = await this.connectIfNeeded(alias)\n if (!handle) return { ok: false, error: `unknown alias \"${alias}\"` }\n if (!handle.client || !handle.tools) {\n return {\n ok: false,\n error: handle.lastError ?? \"client not connected\",\n }\n }\n return { ok: true, tools: handle.tools }\n }\n\n async callTool(\n alias: string,\n toolName: string,\n args: unknown\n ): Promise<ProxyCallOutcome> {\n const handle = await this.connectIfNeeded(alias)\n if (!handle) return { ok: false, error: `unknown alias \"${alias}\"` }\n if (!handle.client) {\n return {\n ok: false,\n error: handle.lastError ?? \"client not connected\",\n }\n }\n try {\n const result = await handle.client.callTool({\n name: toolName,\n arguments:\n args && typeof args === \"object\"\n ? (args as Record<string, unknown>)\n : {},\n })\n return { ok: true, result }\n } catch (err) {\n // Mark the client as dirty — the connection may have died\n // mid-call (process crash, http server restart). The next call\n // re-opens via connectIfNeeded.\n const msg = err instanceof Error ? err.message : String(err)\n if (/closed|disconnect|EPIPE|ECONNRESET/i.test(msg)) {\n await safeClose(handle.client)\n handle.client = null\n handle.tools = null\n handle.lastError = msg\n }\n return { ok: false, error: msg }\n }\n }\n\n async closeAll(): Promise<void> {\n await Promise.all(\n Array.from(this.clients.values()).map(c => safeClose(c.client))\n )\n this.clients.clear()\n }\n}\n\nfunction freshPlaceholder(entry: ImportedMcpEntry): ProxyClient {\n return { entry, client: null, tools: null, lastError: null }\n}\n\nfunction toDescriptor(tool: {\n name: string\n description?: string\n inputSchema?: unknown\n}): ProxyToolDescriptor {\n return {\n name: tool.name,\n ...(tool.description ? { description: tool.description } : {}),\n ...(tool.inputSchema ? { inputSchema: tool.inputSchema } : {}),\n }\n}\n\n/**\n * Replace `${VAR}` and `${VAR:-default}` placeholders in env values\n * with the corresponding `process.env` entry (or default), the same\n * way claude-code / cursor expand mcp-server env. When the variable\n * is unset and no default is given, the placeholder is dropped — the\n * upstream then sees the env var as absent rather than as the\n * literal `${MISSING_VAR}`, which it usually treats as \"use default\n * config\" rather than \"explicit empty token\".\n */\nfunction expandEnvPlaceholders(\n raw: Record<string, string>\n): Record<string, string> {\n const out: Record<string, string> = {}\n for (const [k, v] of Object.entries(raw)) {\n const expanded = v.replace(\n /\\$\\{([A-Z_][A-Z0-9_]*)(?::-([^}]*))?\\}/gi,\n (_match, name: string, fallback: string | undefined) => {\n const fromEnv = process.env[name]\n if (fromEnv !== undefined) return fromEnv\n if (fallback !== undefined) return fallback\n return \"\"\n }\n )\n // Drop the var entirely if it expanded to empty — keeps the\n // upstream from receiving an empty-string token + treating it as\n // a real (but invalid) credential.\n if (expanded.length === 0) continue\n out[k] = expanded\n }\n return out\n}\n\nasync function safeClose(client: Client | null): Promise<void> {\n if (!client) return\n try {\n await client.close()\n } catch {\n // best-effort\n }\n}\n\n/**\n * Open a transport for a discovered MCP. stdio spawns the command;\n * http/sse open over the network. Returns a connected `Client` on\n * success; throws with a useful message on failure.\n */\nasync function openClient(entry: ImportedMcpEntry): Promise<Client> {\n const snap = entry.snapshot\n const client = new Client(\n { name: \"agentproto-daemon-proxy\", version: \"0.1.0\" },\n { capabilities: {} }\n )\n if (snap.type === \"stdio\") {\n if (!snap.command) {\n throw new Error(\n `import \"${entry.alias}\" is stdio but has no command field`\n )\n }\n // claude-code / cursor / vscode all support `${VAR}` placeholders\n // in the env map (and the more permissive `${VAR:-default}`\n // form). Our scanner stores the snapshot verbatim — expand at\n // spawn time so live env changes work without a re-import, and\n // tokens like REPLICATE_API_TOKEN don't end up forwarded as the\n // literal string `${REPLICATE_API_TOKEN}`.\n const expandedEnv = expandEnvPlaceholders(snap.env ?? {})\n const transport = new StdioClientTransport({\n command: snap.command,\n args: snap.args ?? [],\n env: { ...process.env, ...expandedEnv } as Record<string, string>,\n // Pipe stderr so we can include it in the error message instead of\n // surfacing the opaque \"Connection closed\" MCP error code.\n stderr: \"pipe\",\n })\n const stderrBuf: string[] = []\n transport.stderr?.on(\"data\", (chunk: Buffer | string) => {\n stderrBuf.push(typeof chunk === \"string\" ? chunk : chunk.toString(\"utf8\"))\n if (stderrBuf.length > 40) stderrBuf.shift()\n })\n try {\n await client.connect(transport)\n } catch (err) {\n const stderrText = stderrBuf.join(\"\").trim()\n const msg = err instanceof Error ? err.message : String(err)\n throw new Error(stderrText ? `${msg}\\nstderr: ${stderrText.slice(-600)}` : msg)\n }\n return client\n }\n if (snap.type === \"http\") {\n if (!snap.url) throw new Error(`import \"${entry.alias}\" has no url`)\n const transport = new StreamableHTTPClientTransport(new URL(snap.url), {\n requestInit: {\n headers: snap.headers ?? {},\n },\n })\n await client.connect(transport)\n return client\n }\n if (snap.type === \"sse\") {\n if (!snap.url) throw new Error(`import \"${entry.alias}\" has no url`)\n const transport = new SSEClientTransport(new URL(snap.url), {\n requestInit: {\n headers: snap.headers ?? {},\n },\n })\n await client.connect(transport)\n return client\n }\n throw new Error(\n `import \"${entry.alias}\" has unsupported transport type \"${snap.type}\"`\n )\n}\n","/**\n * MCP tools for event-driven orchestration:\n * - poll_events — cheap cursor-based snapshot of session events\n * - wait_for_any — multiplexed long-poll (1 call for N sessions)\n *\n * These complement the existing per-session waitForTurnEnd inside\n * get_agent_session_output. The new tools handle multi-session fan-in\n * and external-client retrigger without burning polling tokens.\n */\n\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\"\nimport { z } from \"zod\"\nimport type { SessionsRegistry } from \"./sessions.js\"\nimport type { SessionEventBus, SessionEventType } from \"./session-event-bus.js\"\nimport type { EventRing } from \"./event-ring.js\"\nimport type { RoutineRunner } from \"./routine-runner.js\"\nimport type { CompletionPolicySupervisor, AttachPolicyInput } from \"./supervisor.js\"\nimport { withToolSubset } from \"./tool-subset.js\"\nimport { jsonTolerant } from \"./json-tolerant.js\"\nimport { collectSubtree } from \"./session-tools.js\"\nimport type { PolicyRunState } from \"./supervisor.js\"\nimport type { InboundWatcher } from \"./inbound-watcher.js\"\n\n/**\n * Zod schema for the `gate` field of `attach_policy`.\n * Exported so tests can validate the schema directly.\n *\n * Union of two variants:\n * • shell — `{ command, args?, cwd?, timeoutMs? }`\n * • judge — `{ judge: { adapter, model?, prompt, timeoutMs? } }` (WP7)\n */\nexport const gateInputSchema = z.union([\n z.object({\n command: z.string().min(1).describe(\"Gate command basename (must be allowlisted).\"),\n args: z.array(z.string()).optional().describe(\"Argv passed verbatim.\"),\n cwd: z.string().optional().describe(\"Working directory for the gate. Defaults to the session's cwd.\"),\n timeoutMs: z.number().int().positive().optional().describe(\"Gate timeout in ms. Default 60 000.\"),\n }),\n z.object({\n judge: z.object({\n adapter: z.string().min(1).describe(\"Agent adapter slug to spawn (e.g. \\\"claude-code\\\").\"),\n model: z.string().optional().describe(\"Optional model identifier forwarded to the adapter.\"),\n prompt: z.string().min(1).describe(\"Rubric / instructions for the judge. The supervisor appends a VERDICT instruction.\"),\n timeoutMs: z.number().int().positive().optional().describe(\"Max wall-clock for the judge before kill + FAIL. Default 120 000.\"),\n }),\n }),\n])\n\nexport interface RegisterOrchestrationToolsOptions {\n registry: SessionsRegistry\n sessionEvents: SessionEventBus\n eventRing: EventRing\n routineRunner?: RoutineRunner\n supervisor?: CompletionPolicySupervisor\n /** When wired, exposes start/stop/list_inbound_watcher tools. */\n inboundWatcher?: InboundWatcher\n /** Optional allowlist — when set, only tools whose name is in the\n * set are registered (the scoped orchestrator sub-gateway, WP2).\n * Omitted → register everything, today's behaviour. */\n toolSubset?: ReadonlySet<string>\n /**\n * When set, this is the calling orchestrator's scope (WP6 supervisor\n * composition). Enables subtree-scoped policy operations:\n * - attach_policy may only target sessions in the caller's subtree\n * - then:\"commit\" is refused (host commit is an operator gesture)\n * - get_policy_status / list_policies / cancel_policy only see\n * policies whose watched sessions are all within the caller's subtree\n * Absent → operator/root context, no additional restrictions.\n */\n callerScope?: { ownerSessionId?: string }\n}\n\nexport function registerOrchestrationTools(\n rawServer: McpServer,\n opts: RegisterOrchestrationToolsOptions,\n): void {\n // When a subset is requested, every `server.tool(...)` below is\n // filtered through this one guard (ADR §4.2). No subset → raw server.\n const server = opts.toolSubset\n ? withToolSubset(rawServer, opts.toolSubset)\n : rawServer\n const { registry, sessionEvents, eventRing, callerScope, inboundWatcher } = opts\n\n /**\n * WP6: check whether ALL watched sessions of a policy fall within the\n * subtree rooted at `ownerId`. Rebuilds the subtree from the live\n * registry on each call so newly-spawned children are visible without\n * any explicit invalidation. The subtree is tiny and the build is O(n)\n * over all sessions — cheap relative to any surrounding I/O.\n */\n const isPolicyInSubtree = (policy: PolicyRunState, ownerId: string): boolean => {\n const subtree = collectSubtree(ownerId, registry.list())\n const ids = policy.sessionIds.length > 0 ? policy.sessionIds : [policy.sessionId]\n return ids.every(id => subtree.has(id))\n }\n\n // ── poll_events ──────────────────────────────────────────────────\n server.tool(\n \"poll_events\",\n \"Lightweight cursor-based snapshot of session lifecycle events \" +\n \"(turn-end, awaiting-input, exited). Returns only what changed since \" +\n \"the last call — cheap, no transcript. Use `wait_for_any` to block \" +\n \"efficiently; use this for a quick status sweep between other work.\",\n {\n since: z\n .number()\n .int()\n .min(0)\n .optional()\n .describe(\n \"Opaque cursor from a prior call's `nextCursor`. Omit (or pass 0) \" +\n \"to start from the current tail — returns events emitted after this call.\",\n ),\n sessionIds: z\n .array(z.string())\n .optional()\n .describe(\"Filter to these session ids. Omit → all sessions.\"),\n types: z\n .array(z.enum([\"turn-end\", \"awaiting-input\", \"exited\", \"command-done\", \"policy:passed\", \"policy:failed\", \"policy:commit-ready\", \"policy:committed\"]))\n .optional()\n .describe(\"Filter to these event types. Omit → all types.\"),\n limit: z\n .number()\n .int()\n .min(1)\n .max(200)\n .optional()\n .describe(\"Max events to return. Default 50.\"),\n },\n async input => {\n const cursor = input.since ?? eventRing.since(0).nextCursor\n const { events, nextCursor } = eventRing.since(cursor, {\n sessionIds: input.sessionIds,\n types: input.types as SessionEventType[] | undefined,\n limit: input.limit,\n })\n return {\n content: [\n { type: \"text\", text: JSON.stringify({ events, nextCursor }, null, 2) },\n ],\n }\n },\n )\n\n // ── Routine tools (optional — only registered when routineRunner is provided) ─\n const { routineRunner } = opts\n if (routineRunner) {\n server.tool(\n \"start_routine\",\n \"Start a routine — a named sequence of steps that spawn agent sessions \" +\n \"and fan-in on their turn-end events. Returns a runId immediately; \" +\n \"the routine executes in the background. Poll with `get_routine_status`.\",\n {\n routineId: z.string().describe(\"Arbitrary label for this routine type (e.g. 'daily-brief').\"),\n steps: z\n .array(\n z.object({\n label: z.string(),\n adapter: z.string().optional().describe(\"Agent adapter slug to spawn.\"),\n prompt: z.string().optional().describe(\"Prompt to send after spawning.\"),\n waitFor: z\n .array(z.string())\n .optional()\n .describe(\"Session ids that must fire turn-end before this step runs.\"),\n policy: z\n .discriminatedUnion(\"awaiting\", [\n z.object({\n awaiting: z.literal(\"auto-allow\"),\n prompt: z.string(),\n }),\n z.object({\n awaiting: z.literal(\"escalate\"),\n webhookUrl: z.string().url().optional(),\n timeoutMs: z.number().int().positive().optional(),\n }),\n z.object({ awaiting: z.literal(\"fail\") }),\n ])\n .optional()\n .describe(\"What to do when a session asks for input mid-step.\"),\n }),\n )\n .min(1)\n .max(50)\n .describe(\"Ordered list of steps. Steps with `waitFor` block until those sessions finish.\"),\n workspaceSlug: z\n .string()\n .optional()\n .describe(\"Workspace slug passed to each spawned session.\"),\n cwd: z.string().optional().describe(\"Working directory for spawned sessions.\"),\n notifyUrl: z\n .string()\n .url()\n .optional()\n .describe(\"Webhook URL to call on run completion or escalation.\"),\n },\n async input => {\n const run = await routineRunner.start(input)\n return {\n content: [{ type: \"text\", text: JSON.stringify({ runId: run.runId, status: run.status }, null, 2) }],\n }\n },\n )\n\n server.tool(\n \"get_routine_status\",\n \"Poll the status of a background routine run started with `start_routine`.\",\n {\n runId: z.string().describe(\"Run id returned by `start_routine`.\"),\n },\n async input => {\n const run = routineRunner.status(input.runId)\n if (!run) {\n return {\n content: [{ type: \"text\", text: JSON.stringify({ error: \"run not found\", runId: input.runId }) }],\n }\n }\n return { content: [{ type: \"text\", text: JSON.stringify(run, null, 2) }] }\n },\n )\n\n server.tool(\n \"cancel_routine\",\n \"Cancel a running routine. Steps already in flight will finish, but no \" +\n \"new steps will be started.\",\n {\n runId: z.string().describe(\"Run id to cancel.\"),\n },\n async input => {\n routineRunner.cancel(input.runId)\n const run = routineRunner.status(input.runId)\n return { content: [{ type: \"text\", text: JSON.stringify({ runId: input.runId, status: run?.status ?? \"not_found\" }) }] }\n },\n )\n\n server.tool(\n \"resolve_routine_escalation\",\n \"Provide an external answer to a routine step that escalated because a \" +\n \"session asked for human input (policy=escalate).\",\n {\n runId: z.string().describe(\"Run id.\"),\n stepIndex: z.number().int().min(0).describe(\"Step index to resolve (0-based).\"),\n response: z.string().describe(\"The answer to inject into the awaiting session.\"),\n },\n async input => {\n routineRunner.resolve(input.runId, input.stepIndex, input.response)\n return { content: [{ type: \"text\", text: JSON.stringify({ ok: true }) }] }\n },\n )\n\n server.tool(\n \"list_routines\",\n \"List all routine runs (running, done, failed, cancelled).\",\n {},\n async () => {\n const runs = routineRunner.list()\n return { content: [{ type: \"text\", text: JSON.stringify(runs, null, 2) }] }\n },\n )\n }\n\n // ── Supervisor tools ─────────────────────────────────────────────────────────\n // attach_policy / get_policy_status / list_policies / cancel_policy are\n // registered UNCONDITIONALLY because they appear in DEFAULT_ORCHESTRATOR_TOOLS\n // and therefore in every scoped subset. A tool declared in the subset but not\n // registered on the server causes the MCP handshake to hang indefinitely\n // (empirically verified). When no supervisor is wired the handlers return a\n // structured error instead of a live result — clean fail, no hang.\n const { supervisor } = opts\n\n // Base shape of a completion policy (shared by attach_policy and, via\n // z.lazy, the recursive `next` DAG chain — WP6).\n {\n const policyShapeBase = {\n sessionId: z\n .string()\n .optional()\n .describe(\n \"Session id to watch (single-session form). Provide this OR \" +\n \"`sessionIds`. Equivalent to `sessionIds: [sessionId]`.\",\n ),\n sessionIds: jsonTolerant(\n z.array(z.string()).min(1),\n )\n .optional()\n .describe(\n \"Fan-in group: the gate runs once, only after EVERY listed session \" +\n \"has finished its turn (turn-end or exit). Supersedes `sessionId`.\",\n ),\n gate: jsonTolerant(gateInputSchema)\n .optional()\n .describe(\n \"Gate: shell (exit 0 = pass) or judge-agent (WP7 — `{ judge: { adapter, prompt } }`). \" +\n \"Absent → always passes immediately after turn-end.\",\n ),\n then: z\n .enum([\"emit\", \"commit\"])\n .describe(\n \"Action on a GREEN gate. 'emit' → emits policy:passed. 'commit' → \" +\n \"stages the explicit `commit.paths` and commits on the host \" +\n \"(requires `commit`; git must be allowlisted).\",\n ),\n commit: jsonTolerant(\n z.object({\n paths: z\n .array(z.string().min(1))\n .min(1)\n .describe(\n \"Explicit literal paths to stage (workspace-relative). Staged \" +\n \"via `git add -- <paths>` — never `-A`, never a glob.\",\n ),\n message: z.string().min(1).describe(\"Commit message (passed as argv, no shell).\"),\n requireHumanAck: z\n .boolean()\n .optional()\n .describe(\n \"Default TRUE. When true, the green gate parks in awaiting-ack \" +\n \"and emits policy:commit-ready; the commit runs only on \" +\n \"ack_policy(approve:true). When false, commits directly. \" +\n \"Never pushes, never --force.\",\n ),\n }),\n )\n .optional()\n .describe(\"Required when then === 'commit' (WP5).\"),\n onFail: jsonTolerant(\n z.object({\n nudge: z\n .string()\n .optional()\n .describe(\n \"Message sent to the session when the gate fails. \" +\n \"Use {code} as a placeholder for the exit code. \" +\n \"Default: built-in message in French.\",\n ),\n maxRetries: z\n .number()\n .int()\n .min(1)\n .max(10)\n .optional()\n .describe(\n \"Maximum consecutive gate failures before blocking. Default: 2.\",\n ),\n }),\n )\n .optional()\n .describe(\n \"What to do when the gate fails (WP2). Absent → immediately blocked. \" +\n \"Present → re-prompt the session up to maxRetries times then block. \" +\n \"The session must still be running to receive a nudge.\",\n ),\n }\n\n // WP6: a policy may declare `next` — a full (recursive) completion policy\n // attached automatically when this policy reaches `done`. Chains over\n // already-running sessions named in the child's own spec.\n const policyInputSchema: z.ZodTypeAny = z.lazy(() =>\n z.object({\n ...policyShapeBase,\n next: jsonTolerant(policyInputSchema).optional(),\n }),\n )\n const nextField = {\n next: jsonTolerant(policyInputSchema)\n .optional()\n .describe(\n \"DAG chaining (WP6): a full completion policy (recursive) attached \" +\n \"automatically when THIS policy reaches done. It watches the \" +\n \"session(s) named in its own spec. Chains policies over existing \" +\n \"sessions — does not spawn new sessions.\",\n ),\n }\n\n server.tool(\n \"attach_policy\",\n \"Attach a completion policy to a running session (or a fan-in group). When \" +\n \"the watched session emits turn-end — or, for a group, once EVERY member \" +\n \"has finished its turn — an optional shell gate runs (exit 0 = pass). The \" +\n \"result is emitted as `policy:passed` or `policy:failed` on the event bus \" +\n \"(readable via poll_events). A policy may declare `next` to chain another \" +\n \"policy when it completes (WP6 DAG). Returns the policyId immediately.\",\n {\n ...policyShapeBase,\n ...nextField,\n },\n async input => {\n if (!supervisor) {\n return { content: [{ type: \"text\", text: JSON.stringify({ error: \"supervisor not available\" }) }] }\n }\n if (!input.sessionId && !(input.sessionIds && input.sessionIds.length > 0)) {\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify({ error: \"attach_policy requires sessionId or a non-empty sessionIds\" }),\n },\n ],\n }\n }\n if (input.then === \"commit\" && !input.commit) {\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify({ error: 'then:\"commit\" requires a commit spec' }),\n },\n ],\n }\n }\n // WP6 scoping: a child orchestrator may only attach policies on\n // sessions within its own subtree, and may not request a commit\n // action (host commits are an operator/human gesture).\n if (callerScope) {\n if (input.then === \"commit\") {\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify({\n error: 'then:\"commit\" is not permitted from a child orchestrator scope; use then:\"emit\" and let the operator or human ack the commit',\n }),\n },\n ],\n }\n }\n if (!callerScope.ownerSessionId) {\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify({ error: \"scope is not yet bound to a session; cannot attach policy\" }),\n },\n ],\n }\n }\n const targetIds =\n input.sessionIds && input.sessionIds.length > 0\n ? input.sessionIds\n : input.sessionId\n ? [input.sessionId]\n : []\n const subtree = collectSubtree(callerScope.ownerSessionId, registry.list())\n const outside = targetIds.filter(id => !subtree.has(id))\n if (outside.length > 0) {\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify({\n error: `attach_policy denied: sessions not in caller subtree: ${outside.join(\", \")}`,\n forbidden: outside,\n }),\n },\n ],\n }\n }\n }\n try {\n const state = supervisor.attach({\n sessionId: input.sessionId,\n sessionIds: input.sessionIds,\n gate: input.gate,\n then: input.then,\n commit: input.commit,\n onFail: input.onFail,\n next: input.next as AttachPolicyInput[\"next\"],\n })\n return {\n content: [{ type: \"text\", text: JSON.stringify({ policyId: state.policyId, status: state.status }, null, 2) }],\n }\n } catch (err) {\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify({ error: err instanceof Error ? err.message : String(err) }),\n },\n ],\n }\n }\n },\n )\n\n server.tool(\n \"get_policy_status\",\n \"Get the current status of a completion policy attached with `attach_policy`.\",\n {\n policyId: z.string().describe(\"Policy id returned by `attach_policy`.\"),\n },\n async input => {\n if (!supervisor) {\n return { content: [{ type: \"text\", text: JSON.stringify({ error: \"supervisor not available\" }) }] }\n }\n const state = supervisor.getStatus(input.policyId)\n if (!state) {\n return {\n content: [{ type: \"text\", text: JSON.stringify({ error: \"policy not found\", policyId: input.policyId }) }],\n }\n }\n // WP6 scoping: only reveal policies whose watched sessions are all\n // within the caller's subtree. Return \"not found\" for out-of-scope\n // policies (no information leak about existence).\n if (callerScope) {\n if (!callerScope.ownerSessionId || !isPolicyInSubtree(state, callerScope.ownerSessionId)) {\n return {\n content: [{ type: \"text\", text: JSON.stringify({ error: \"policy not found\", policyId: input.policyId }) }],\n }\n }\n }\n return { content: [{ type: \"text\", text: JSON.stringify(state, null, 2) }] }\n },\n )\n\n server.tool(\n \"cancel_policy\",\n \"Cancel a watching or gating completion policy. No-op on done/blocked policies.\",\n {\n policyId: z.string().describe(\"Policy id to cancel.\"),\n },\n async input => {\n if (!supervisor) {\n return { content: [{ type: \"text\", text: JSON.stringify({ error: \"supervisor not available\" }) }] }\n }\n // WP6 scoping: a child may only cancel policies on its own subtree.\n if (callerScope) {\n const state = supervisor.getStatus(input.policyId)\n if (!state || !callerScope.ownerSessionId || !isPolicyInSubtree(state, callerScope.ownerSessionId)) {\n return {\n content: [{ type: \"text\", text: JSON.stringify({ error: \"cancel denied: policy not found or outside caller subtree\", policyId: input.policyId }) }],\n }\n }\n }\n supervisor.cancel(input.policyId)\n const state = supervisor.getStatus(input.policyId)\n return {\n content: [{ type: \"text\", text: JSON.stringify({ policyId: input.policyId, status: state?.status ?? \"not_found\" }) }],\n }\n },\n )\n\n // ack_policy is intentionally absent from DEFAULT_ORCHESTRATOR_TOOLS (host\n // commits are an operator gesture, not a child-orchestrator one — WP6).\n // Register it only when a supervisor is present, consistent with the\n // declared ≡ registered invariant.\n if (supervisor) {\n server.tool(\n \"ack_policy\",\n \"Acknowledge a `then:\\\"commit\\\"` policy parked in `awaiting-ack` (WP5). \" +\n \"`approve:true` runs the prepared host commit (git add <paths> + git \" +\n \"commit; never -A/push/--force) → emits policy:committed (+sha) → done. \" +\n \"`approve:false` cancels it (no commit). No-op on any other state.\",\n {\n policyId: z.string().describe(\"Policy id returned by `attach_policy`.\"),\n approve: z\n .boolean()\n .describe(\"true → run the commit; false → cancel without committing.\"),\n },\n async input => {\n const state = await supervisor.ack(input.policyId, input.approve)\n if (!state) {\n return {\n content: [{ type: \"text\", text: JSON.stringify({ error: \"policy not found\", policyId: input.policyId }) }],\n }\n }\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(\n {\n policyId: state.policyId,\n status: state.status,\n ...(state.commitSha ? { sha: state.commitSha } : {}),\n ...(state.error ? { error: state.error } : {}),\n },\n null,\n 2,\n ),\n },\n ],\n }\n },\n )\n } // end if (supervisor) for ack_policy\n\n server.tool(\n \"list_policies\",\n \"List all completion policies (watching, gating, done, blocked, cancelled).\",\n {},\n async () => {\n if (!supervisor) {\n return { content: [{ type: \"text\", text: JSON.stringify({ error: \"supervisor not available\" }) }] }\n }\n let policies = supervisor.list()\n // WP6 scoping: a child orchestrator only sees policies whose watched\n // sessions are all within its own subtree. An unbound scope (no\n // ownerSessionId yet) sees nothing — safe default.\n if (callerScope) {\n if (!callerScope.ownerSessionId) {\n policies = []\n } else {\n const ownerId = callerScope.ownerSessionId\n policies = policies.filter(p => isPolicyInSubtree(p, ownerId))\n }\n }\n return { content: [{ type: \"text\", text: JSON.stringify(policies, null, 2) }] }\n },\n )\n }\n\n // ── wait_for_any ─────────────────────────────────────────────────\n server.tool(\n \"wait_for_any\",\n \"Multiplexed long-poll: block until ANY of the listed sessions fires a \" +\n \"lifecycle event. Returns immediately when a session is already in the \" +\n \"target state. Eliminates polling in multi-session fan-in orchestration — \" +\n \"one call replaces N concurrent waitForTurnEnd calls.\",\n {\n sessionIds: z\n .array(z.string())\n .min(1)\n .max(20)\n .describe(\"Session ids (or names) to watch. Returns on the first hit.\"),\n timeoutMs: z\n .number()\n .int()\n .min(1_000)\n .max(49_000)\n .optional()\n .describe(\"Max wait in ms. Default 25 000. Stays under MCP request timeout.\"),\n event: z\n .enum([\"turn-end\", \"awaiting-input\", \"exited\", \"any\"])\n .optional()\n .describe(\n \"Event type to wait for. Default 'any'. 'turn-end' also matches \" +\n \"'awaiting-input' (both signal end-of-turn).\",\n ),\n since: z\n .number()\n .int()\n .min(0)\n .optional()\n .describe(\n \"Event-ring cursor (from a prior poll_events nextCursor). When set, an already-emitted matching event for a watched session is returned immediately — race-free — before long-polling.\"\n ),\n },\n async input => {\n const timeout = input.timeoutMs ?? 25_000\n const targetEvent = input.event ?? \"any\"\n\n // Resolve id-or-name → canonical id\n const resolvedIds = input.sessionIds.map(q => {\n const desc = registry.findByIdOrName(q)\n return desc?.id ?? q\n })\n\n // Race-free replay: if a cursor is provided, check the event ring\n // for already-emitted matching events before descriptor checks.\n if (input.since !== undefined) {\n const ringResult = eventRing.since(input.since, {\n sessionIds: resolvedIds,\n })\n const matchTypes: Set<string> =\n targetEvent === \"any\"\n ? new Set([\"session:turn-end\", \"session:awaiting-input\", \"session:exited\"])\n : targetEvent === \"turn-end\"\n ? new Set([\"session:turn-end\", \"session:awaiting-input\"])\n : targetEvent === \"awaiting-input\"\n ? new Set([\"session:awaiting-input\"])\n : new Set([\"session:exited\"])\n for (const ev of ringResult.events) {\n if (!matchTypes.has(ev.type)) continue\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify({\n sessionId: ev.sessionId,\n event: ev.type.replace(\"session:\", \"\"),\n source: \"ring\",\n since: input.since,\n }),\n },\n ],\n }\n }\n }\n\n // Synchronous check: return immediately if a session is already done\n for (const sid of resolvedIds) {\n const desc = registry.get(sid)\n if (!desc) continue\n if (\n desc.awaitingInput &&\n (targetEvent === \"any\" || targetEvent === \"turn-end\" || targetEvent === \"awaiting-input\")\n ) {\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify({\n sessionId: sid,\n event: \"awaiting-input\",\n awaitingInput: true,\n status: desc.status,\n }),\n },\n ],\n }\n }\n // Already-finished turn: a fast session can complete its turn\n // (\"completed\", not \"awaiting-input\") BEFORE this wait subscribes —\n // turn-end is a transient event with no persisted flag, so without\n // this check the wait would block until the NEXT turn and time out.\n // `turnsCompleted > 0 && !busy && running` = idle after ≥1 finished\n // turn (a freshly-spawned never-run session has turnsCompleted 0, so\n // it is NOT mistaken for done).\n if (\n (desc.turnsCompleted ?? 0) > 0 &&\n !desc.busy &&\n desc.status === \"running\" &&\n (targetEvent === \"any\" || targetEvent === \"turn-end\")\n ) {\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify({\n sessionId: sid,\n event: \"turn-end\",\n awaitingInput: false,\n status: desc.status,\n turnsCompleted: desc.turnsCompleted,\n }),\n },\n ],\n }\n }\n const terminal = desc.status === \"exited\" || desc.status === \"killed\" || desc.status === \"error\"\n if (terminal && (targetEvent === \"any\" || targetEvent === \"exited\")) {\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify({\n sessionId: sid,\n event: \"exited\",\n awaitingInput: false,\n status: desc.status,\n }),\n },\n ],\n }\n }\n }\n\n // Long-poll: subscribe to bus, resolve on first matching event\n return new Promise(resolve => {\n const unsubs: Array<() => void> = []\n let settled = false\n\n const finish = (result: unknown): void => {\n if (settled) return\n settled = true\n clearTimeout(timer)\n for (const u of unsubs) u()\n resolve({\n content: [{ type: \"text\", text: JSON.stringify(result) }],\n })\n }\n\n // Which event types to watch\n const relevantTypes: SessionEventType[] =\n targetEvent === \"any\"\n ? [\"session:turn-end\", \"session:awaiting-input\", \"session:exited\"]\n : targetEvent === \"turn-end\"\n ? [\"session:turn-end\", \"session:awaiting-input\"]\n : targetEvent === \"awaiting-input\"\n ? [\"session:awaiting-input\"]\n : [\"session:exited\"]\n\n const idSet = new Set(resolvedIds)\n\n for (const evType of relevantTypes) {\n unsubs.push(\n sessionEvents.on(evType, ev => {\n if (!idSet.has(ev.sessionId)) return\n const desc = registry.get(ev.sessionId)\n finish({\n sessionId: ev.sessionId,\n event: ev.type.replace(\"session:\", \"\"),\n awaitingInput: desc?.awaitingInput ?? false,\n status: desc?.status ?? \"unknown\",\n })\n }),\n )\n }\n\n const timer = setTimeout(() => {\n finish({ timedOut: true, sessionIds: resolvedIds })\n }, timeout)\n })\n },\n )\n\n // ── start_inbound_watcher ────────────────────────────────────────\n if (inboundWatcher) {\n server.tool(\n \"start_inbound_watcher\",\n \"Start a background poller that watches an agentpush source for new inbound \" +\n \"messages and spawns one agent per contact_ref. The agent receives the \" +\n \"inbound events inline via the prompt template. Returns a watcherId you \" +\n \"can pass to stop_inbound_watcher or list_inbound_watchers.\",\n {\n alias: z\n .string()\n .min(1)\n .describe(\n \"Imported MCP alias for the agentpush server (e.g. 'agentpush'). \" +\n \"Import it first with import_mcp.\",\n ),\n source: z\n .string()\n .min(1)\n .describe(\n \"Contact ref / channel to poll — forwarded as `source` to poll_inbound \" +\n \"(e.g. a phone number '+33612345678' or a webhook channel name).\",\n ),\n adapter: z\n .string()\n .min(1)\n .describe(\n \"Agent adapter slug to spawn when new messages arrive (e.g. 'claude-code').\",\n ),\n promptTemplate: z\n .string()\n .min(1)\n .describe(\n \"Prompt sent to the spawned agent. Placeholders: \" +\n \"{{source}} (watched source), {{contact_ref}} (sender), \" +\n \"{{messages_json}} (JSON array of new events), {{count}} (message count).\",\n ),\n pollIntervalMs: z\n .number()\n .int()\n .min(1_000)\n .max(60_000)\n .optional()\n .describe(\"Poll interval in ms. Default 5 000.\"),\n cwd: z\n .string()\n .optional()\n .describe(\n \"Working directory for spawned agents. Defaults to the daemon's cwd.\",\n ),\n label: z\n .string()\n .optional()\n .describe(\"Optional label suffix on spawned session names.\"),\n mcpServersForChild: jsonTolerant(\n z.array(\n z.object({\n name: z.string(),\n transport: z.enum([\"stdio\", \"http\", \"sse\"]),\n ref: z.string().optional(),\n }),\n ),\n )\n .optional()\n .describe(\n \"MCP servers to mount in each spawned agent. Pass the agentpush entry \" +\n \"here (e.g. [{name:'agentpush',transport:'http',ref:'http://localhost:8080/mcp'}]) \" +\n \"so the agent can call dispatch_request to reply.\",\n ),\n },\n async input => {\n const desc = inboundWatcher.start(input)\n return { content: [{ type: \"text\", text: JSON.stringify(desc, null, 2) }] }\n },\n )\n\n server.tool(\n \"stop_inbound_watcher\",\n \"Stop a running inbound watcher. The watcher's cursor position is preserved \" +\n \"in memory (and flushed to disk on daemon shutdown) so a new watcher \" +\n \"started later can pick up where it left off.\",\n {\n watcherId: z\n .string()\n .min(1)\n .describe(\"Watcher id returned by start_inbound_watcher.\"),\n },\n async input => {\n const ok = inboundWatcher.stop(input.watcherId)\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(\n ok\n ? { ok: true, watcherId: input.watcherId, status: \"stopped\" }\n : {\n ok: false,\n error: `watcher \"${input.watcherId}\" not found`,\n },\n null,\n 2,\n ),\n },\n ],\n ...(ok ? {} : { isError: true }),\n }\n },\n )\n\n server.tool(\n \"list_inbound_watchers\",\n \"List all inbound watchers (running and stopped) with their cursor position, \" +\n \"last poll time, last fire time, and total spawned session count.\",\n {},\n async () => {\n const watchers = inboundWatcher.list()\n return { content: [{ type: \"text\", text: JSON.stringify(watchers, null, 2) }] }\n },\n )\n }\n}\n","/**\n * In-process pub/sub bus for session lifecycle events. Separate from\n * RuntimeEvents (global daemon bus) — session events are scoped to\n * individual sessions and fire at turn-level granularity.\n *\n * Consumers: EventRing (poll_events cursor), WebhookNotifier\n * (fire-and-forget HTTP), RoutineRunner (state machine fan-in),\n * and wait_for_any MCP tool (long-poll multiplexed).\n */\n\nimport { EventEmitter } from \"node:events\"\n\nexport type SessionEventType =\n | \"session:turn-end\"\n | \"session:awaiting-input\"\n | \"session:exited\"\n | \"session:command-done\"\n | \"policy:passed\"\n | \"policy:failed\"\n | \"policy:commit-ready\"\n | \"policy:committed\"\n\nexport interface SessionTurnEndEvent {\n type: \"session:turn-end\"\n sessionId: string\n awaitingInput: boolean\n label?: string\n ts: string\n}\n\nexport interface SessionAwaitingInputEvent {\n type: \"session:awaiting-input\"\n sessionId: string\n label?: string\n ts: string\n}\n\nexport interface SessionExitedEvent {\n type: \"session:exited\"\n sessionId: string\n exitCode?: number\n status: \"exited\" | \"killed\" | \"error\"\n label?: string\n ts: string\n}\n\n/** Emitted when execute_command finishes. commandId matches the id\n * returned by the execute_command MCP tool. */\nexport interface SessionCommandDoneEvent {\n type: \"session:command-done\"\n sessionId: string\n commandId: string\n exitCode: number\n ts: string\n}\n\n/** Emitted by the supervisor when a completion policy's gate passes. */\nexport interface PolicyPassedEvent {\n type: \"policy:passed\"\n policyId: string\n sessionId: string\n ts: string\n}\n\n/** Emitted by the supervisor when a completion policy's gate fails. */\nexport interface PolicyFailedEvent {\n type: \"policy:failed\"\n policyId: string\n sessionId: string\n exitCode?: number\n ts: string\n}\n\n/**\n * Emitted by the supervisor (WP5) when a `then:\"commit\"` policy's gate passes\n * but `requireHumanAck` is set: the commit is staged-and-ready but NOT yet\n * executed. Carries the exact paths + message that `ack_policy(approve:true)`\n * will commit. The policy sits in `awaiting-ack` until acked.\n */\nexport interface PolicyCommitReadyEvent {\n type: \"policy:commit-ready\"\n policyId: string\n sessionId: string\n paths: string[]\n message: string\n ts: string\n}\n\n/** Emitted by the supervisor (WP5) when a `then:\"commit\"` policy has actually\n * committed — either directly (requireHumanAck:false) or after an approving\n * `ack_policy`. Carries the resulting commit sha. */\nexport interface PolicyCommittedEvent {\n type: \"policy:committed\"\n policyId: string\n sessionId: string\n sha: string\n paths: string[]\n message: string\n ts: string\n}\n\nexport type SessionEvent =\n | SessionTurnEndEvent\n | SessionAwaitingInputEvent\n | SessionExitedEvent\n | SessionCommandDoneEvent\n | PolicyPassedEvent\n | PolicyFailedEvent\n | PolicyCommitReadyEvent\n | PolicyCommittedEvent\n\nexport interface SessionEventBus {\n emit(ev: SessionEvent): void\n /** Subscribe to a specific event type. Returns an unsubscribe fn. */\n on<E extends SessionEventType>(\n type: E,\n handler: (ev: Extract<SessionEvent, { type: E }>) => void,\n ): () => void\n /** Subscribe to all event types. Returns an unsubscribe fn. */\n onAny(handler: (ev: SessionEvent) => void): () => void\n}\n\nexport function createSessionEventBus(): SessionEventBus {\n const ee = new EventEmitter()\n ee.setMaxListeners(100)\n\n return {\n emit(ev) {\n ee.emit(\"event\", ev)\n },\n on(type, handler) {\n const wrapped = (ev: SessionEvent) => {\n if (ev.type === type) handler(ev as Extract<SessionEvent, { type: typeof type }>)\n }\n ee.on(\"event\", wrapped)\n return () => ee.off(\"event\", wrapped)\n },\n onAny(handler) {\n ee.on(\"event\", handler)\n return () => ee.off(\"event\", handler)\n },\n }\n}\n","/**\n * Cursor-based ring buffer for session events. Bridges the in-process\n * SessionEventBus (push) to the poll_events MCP tool (pull).\n *\n * Capacity default: 1 000 events. Oldest entry dropped on overflow —\n * callers that lag beyond the cap see a gap in their cursor but never\n * a block. `since()` returns `nextCursor = totalEmitted` so a fresh\n * call with that value always starts just past the current tail.\n */\n\nimport type { SessionEvent, SessionEventBus, SessionEventType } from \"./session-event-bus.js\"\n\nconst DEFAULT_CAP = 1_000\n\nexport interface EventRingSnapshot {\n events: SessionEvent[]\n nextCursor: number\n}\n\nexport interface EventRingQueryOpts {\n sessionIds?: string[]\n types?: SessionEventType[]\n /** Default 50. */\n limit?: number\n}\n\nexport interface EventRing {\n /**\n * Return events whose ring-index >= `cursor`. Pass 0 to get all\n * retained events; pass the previously returned `nextCursor` for an\n * incremental read. The returned `nextCursor` is always equal to\n * `totalEmitted` — use it as the next `cursor` argument.\n *\n * Negative or below-base cursors are clamped to the oldest retained\n * event (no error, just a potential replay of a partial window).\n */\n since(cursor: number, opts?: EventRingQueryOpts): EventRingSnapshot\n /** Wire the ring to a SessionEventBus. Returns an unsubscribe fn. */\n wire(bus: SessionEventBus): () => void\n}\n\nexport function createEventRing(cap = DEFAULT_CAP): EventRing {\n /** Circular store — oldest entry at index 0, newest at the tail. */\n const ring: SessionEvent[] = []\n /** Total events ever pushed. ring[0] has absolute index base = totalEmitted - ring.length. */\n let totalEmitted = 0\n\n return {\n since(cursor, opts = {}) {\n const limit = opts.limit ?? 50\n // Absolute index of ring[0]\n const base = totalEmitted - ring.length\n // Clamp cursor into the valid window\n const clampedStart = Math.max(0, cursor - base)\n let slice = ring.slice(clampedStart)\n\n if (opts.sessionIds && opts.sessionIds.length > 0) {\n const ids = new Set(opts.sessionIds)\n slice = slice.filter(e => ids.has(e.sessionId))\n }\n if (opts.types && opts.types.length > 0) {\n const types = new Set<string>(opts.types)\n slice = slice.filter(e => types.has(e.type))\n }\n\n return {\n events: slice.slice(0, limit),\n nextCursor: totalEmitted,\n }\n },\n\n wire(bus) {\n return bus.onAny(ev => {\n ring.push(ev)\n totalEmitted++\n if (ring.length > cap) ring.shift()\n })\n },\n }\n}\n","/**\n * Fire-and-forget webhook notifier for session lifecycle events.\n *\n * Each session can register its own `notifyUrl` (via `start_agent_session`).\n * A global URL can be set via `AGENTPROTO_NOTIFY_URL` env var or\n * `~/.agentproto/notify.json` (env wins). Both are POSTed when an event\n * fires — the union of per-session + global URLs, deduplicated.\n *\n * Retry policy: one retry after 2 s on network error. No retry on 4xx/5xx.\n * Timeout: 10 s per attempt. All errors are swallowed — the notifier never\n * throws into the session's hot path.\n */\n\nimport { readFileSync } from \"node:fs\"\nimport { homedir } from \"node:os\"\nimport { join } from \"node:path\"\nimport type { SessionEvent } from \"./session-event-bus.js\"\n\nexport interface WebhookNotifier {\n /** Register a per-session URL (called from start_agent_session). */\n register(sessionId: string, url: string): void\n unregister(sessionId: string): void\n /** Handler to wire into SessionEventBus.onAny. Fire-and-forget. */\n onSessionEvent(ev: SessionEvent): void\n}\n\ninterface NotifyPayload {\n sessionId: string\n label?: string\n event: string\n awaitingInput: boolean\n ts: string\n exitCode?: number\n status?: string\n}\n\nexport function createWebhookNotifier(opts?: {\n /** Pre-resolved global URL — overridden at call time by env var or file. */\n globalUrl?: string\n}): WebhookNotifier {\n const perSession = new Map<string, string>()\n\n const resolveGlobalUrl = (): string | undefined => {\n if (process.env.AGENTPROTO_NOTIFY_URL) return process.env.AGENTPROTO_NOTIFY_URL\n try {\n const path = join(homedir(), \".agentproto\", \"notify.json\")\n const parsed = JSON.parse(readFileSync(path, \"utf8\")) as unknown\n if (parsed && typeof parsed === \"object\" && \"url\" in parsed) {\n const { url } = parsed as { url: unknown }\n if (typeof url === \"string\" && url) return url\n }\n } catch {\n // file absent or malformed — not an error\n }\n return opts?.globalUrl\n }\n\n const post = async (url: string, payload: NotifyPayload): Promise<void> => {\n const body = JSON.stringify(payload)\n const headers = { \"Content-Type\": \"application/json\" }\n try {\n const resp = await fetch(url, {\n method: \"POST\",\n headers,\n body,\n signal: AbortSignal.timeout(10_000),\n })\n if (resp.ok) return\n // 4xx/5xx — no retry\n } catch {\n // Network error — one retry after 2 s\n await new Promise<void>(res => setTimeout(res, 2_000))\n try {\n await fetch(url, {\n method: \"POST\",\n headers,\n body,\n signal: AbortSignal.timeout(10_000),\n })\n } catch {\n // Give up silently\n }\n }\n }\n\n return {\n register(sessionId, url) {\n perSession.set(sessionId, url)\n },\n unregister(sessionId) {\n perSession.delete(sessionId)\n },\n onSessionEvent(ev) {\n // Only fire on meaningful lifecycle events (not command-done, which\n // goes through the command-tools layer)\n if (\n ev.type !== \"session:turn-end\" &&\n ev.type !== \"session:awaiting-input\" &&\n ev.type !== \"session:exited\"\n ) {\n return\n }\n\n const targets = new Set<string>()\n const sessionUrl = perSession.get(ev.sessionId)\n if (sessionUrl) targets.add(sessionUrl)\n const globalUrl = resolveGlobalUrl()\n if (globalUrl) targets.add(globalUrl)\n if (targets.size === 0) return\n\n const payload: NotifyPayload = {\n sessionId: ev.sessionId,\n label: ev.label,\n event: ev.type.replace(\"session:\", \"\"),\n awaitingInput:\n ev.type === \"session:awaiting-input\" ||\n (ev.type === \"session:turn-end\" && ev.awaitingInput),\n ts: ev.ts,\n }\n if (ev.type === \"session:exited\") {\n payload.exitCode = ev.exitCode\n payload.status = ev.status\n }\n\n for (const url of targets) {\n void post(url, payload)\n }\n },\n }\n}\n","/**\n * In-process routine runner — executes a sequence of RoutineStep[]\n * by reacting to SessionEventBus events instead of polling.\n *\n * State machine per run:\n * idle → running → (per step) → done | failed | cancelled\n *\n * Fan-in: a step with `waitFor: string[]` waits for ALL listed\n * sessions to fire turn-end/exited before executing its own prompt.\n *\n * Awaiting-input policy:\n * auto-allow → send the configured prompt and continue\n * escalate → POST webhook, wait for external `resolve()` call\n * fail → mark step/run as failed\n *\n * Persistence: runs are serialised to ~/.agentproto/routine-runs.json\n * (write-tmp + rename atomic swap) on every state mutation so they\n * survive daemon restarts. On load, any run with status \"running\" or\n * \"awaiting-input\" is immediately marked \"failed\" with reason\n * \"interrupted by daemon restart\" — these runs have no live sessions\n * to resume, so marking them failed is the only safe choice (an\n * in-flight run cannot be replayed without re-executing its steps,\n * which could trigger unintended side-effects).\n *\n * Persistence opt-in: persistence is DISABLED by default (persist defaults to\n * false when no persistPath is supplied) so that unit tests calling\n * createRoutineRunner() without a persistPath never touch ~/.agentproto/.\n * Pass persist:true (or supply a persistPath) to enable durable storage — the\n * production createGateway() call does both.\n */\n\nimport { randomUUID } from \"node:crypto\"\nimport { homedir } from \"node:os\"\nimport { join, dirname } from \"node:path\"\nimport { mkdirSync, readFileSync, existsSync, writeFileSync, renameSync } from \"node:fs\"\nimport type { SessionsRegistry } from \"./sessions.js\"\nimport type { SessionEventBus } from \"./session-event-bus.js\"\nimport type { AgentAdapterResolver } from \"./http-server.js\"\nimport type { WebhookNotifier } from \"./webhook-notifier.js\"\n\n// ── Public types ─────────────────────────────────────────────────────\n\nexport type RoutinePolicy =\n | { awaiting: \"auto-allow\"; prompt: string }\n | { awaiting: \"escalate\"; webhookUrl?: string; timeoutMs?: number }\n | { awaiting: \"fail\" }\n\nexport interface RoutineStep {\n label: string\n /** Prompt to send to the agent. Omit to just wait without prompting. */\n prompt?: string\n /** Adapter slug for spawning a NEW session. Omit to reuse the current\n * run's last session. */\n adapter?: string\n /** Fan-in: wait for ALL these session ids to finish before executing. */\n waitFor?: string[]\n policy?: RoutinePolicy\n}\n\nexport type RoutineRunStatus =\n | \"idle\"\n | \"running\"\n | \"awaiting-input\"\n | \"done\"\n | \"failed\"\n | \"cancelled\"\n\nexport interface RoutineStepState {\n index: number\n label: string\n status: \"pending\" | \"running\" | \"done\" | \"failed\" | \"skipped\"\n sessionId?: string\n startedAt?: string\n endedAt?: string\n error?: string\n}\n\nexport interface RoutineRun {\n runId: string\n routineId: string\n status: RoutineRunStatus\n startedAt: string\n endedAt?: string\n steps: RoutineStepState[]\n notifyUrl?: string\n error?: string\n result?: { sessionIds: string[] }\n}\n\nexport interface RoutineRunner {\n /**\n * Start a routine. Returns immediately with the run descriptor\n * (status \"running\"). Steps execute in the background; subscribe\n * to the webhook or poll `status(runId)` for completion.\n */\n start(input: {\n routineId: string\n steps: RoutineStep[]\n workspaceSlug?: string\n cwd?: string\n notifyUrl?: string\n }): Promise<RoutineRun>\n\n status(runId: string): RoutineRun | undefined\n list(): RoutineRun[]\n\n /**\n * Provide an external answer to a step stuck in \"escalate\" awaiting-input.\n * The step's escalate timeout is cleared and the response is sent as the\n * next prompt.\n */\n resolve(runId: string, stepIndex: number, response: string): void\n\n cancel(runId: string): void\n}\n\n// ── Internal state per run ───────────────────────────────────────────\n\ninterface RunState {\n run: RoutineRun\n cancelled: boolean\n /** cwd passed to start() — used as the CWD for all spawned sessions. */\n cwd?: string\n /** workspaceSlug passed to start() — forwarded to spawnAgent. */\n workspaceSlug?: string\n /** Filled by resolve() when a step is in \"escalate\" mode. */\n pendingResolve?: { stepIndex: number; resolver: (response: string) => void }\n}\n\n// ── Factory ──────────────────────────────────────────────────────────\n\nconst DEFAULT_PERSIST_PATH = (): string =>\n join(homedir(), \".agentproto\", \"routine-runs.json\")\n\n// ── Persistence helpers ──────────────────────────────────────────────\n\nfunction loadRuns(persistPath: string): Map<string, RunState> {\n const result = new Map<string, RunState>()\n if (!existsSync(persistPath)) return result\n let raw: string\n try {\n raw = readFileSync(persistPath, \"utf8\")\n } catch {\n return result\n }\n let parsed: unknown\n try {\n parsed = JSON.parse(raw)\n } catch {\n // Malformed file — start empty (documented: not an error)\n return result\n }\n if (!Array.isArray(parsed)) return result\n for (const item of parsed) {\n if (!item || typeof item !== \"object\" || typeof (item as RoutineRun).runId !== \"string\") continue\n // item passes only a minimal shape check (runId: string); remaining fields\n // are trusted as-written. Malformed entries are skipped above — this matches\n // the \"malformed = ignored\" recovery policy used by tunnel-registry and\n // supervisor for the same class of loader.\n const run = item as RoutineRun\n // Any run that was mid-flight cannot be resumed: mark it failed.\n // Reason: the in-process state machine and its live sessions are gone;\n // replaying steps would trigger unintended side-effects, so the safest\n // invariant is \"interrupted = failed\". Callers can re-start a new run.\n if (run.status === \"running\" || run.status === \"awaiting-input\") {\n run.status = \"failed\"\n run.error = \"interrupted by daemon restart\"\n run.endedAt = run.endedAt ?? new Date().toISOString()\n }\n result.set(run.runId, { run, cancelled: false })\n }\n return result\n}\n\nfunction saveRuns(runs: Map<string, RunState>, persistPath: string): void {\n try {\n mkdirSync(dirname(persistPath), { recursive: true })\n const payload = JSON.stringify(\n Array.from(runs.values()).map(s => s.run),\n null,\n 2,\n ) + \"\\n\"\n const tmp = `${persistPath}.tmp.${process.pid}`\n writeFileSync(tmp, payload, \"utf8\")\n renameSync(tmp, persistPath)\n } catch {\n // Best-effort — a write failure must not crash the daemon.\n }\n}\n\nexport function createRoutineRunner(opts: {\n registry: SessionsRegistry\n sessionEvents: SessionEventBus\n resolveAgentAdapter: AgentAdapterResolver\n webhookNotifier?: WebhookNotifier\n /** Absolute path for the persistence file. Defaults to ~/.agentproto/routine-runs.json */\n persistPath?: string\n /**\n * Enable filesystem persistence. Defaults to `true` when `persistPath` is\n * explicitly supplied, `false` otherwise. This mirrors the supervisor pattern\n * so that unit tests calling createRoutineRunner() without a persistPath never\n * write to ~/.agentproto/ — only the production createGateway() call (which\n * passes persist:true) opts in to durable storage.\n */\n persist?: boolean\n}): RoutineRunner {\n const { registry, sessionEvents, resolveAgentAdapter, webhookNotifier } = opts\n const persistPath = opts.persistPath ?? DEFAULT_PERSIST_PATH()\n const shouldPersist = opts.persist ?? (opts.persistPath !== undefined)\n\n // Default false: tests (no opts.persist, no opts.persistPath)\n // don't touch ~/.agentproto. Set opts.persist:true in production\n // (createGateway does this), or supply a persistPath (which also opts in).\n\n // Load persisted runs on init only when persistence is enabled;\n // interrupted runs are marked failed.\n const runs = shouldPersist ? loadRuns(persistPath) : new Map<string, RunState>()\n\n /** Flush the in-memory run map to disk atomically. Call on every mutation. */\n const persist = (): void => {\n if (shouldPersist) saveRuns(runs, persistPath)\n }\n\n // ── Helpers ────────────────────────────────────────────────────────\n\n /** Wait for a session to emit turn-end, awaiting-input, or exited.\n *\n * Subscribes synchronously so the caller can create this promise BEFORE\n * sending a prompt — preventing a race where a fast session fires turn-end\n * between sendPrompt() resolving and the subscription being set up.\n *\n * Belt-and-suspenders: after subscribing, checks whether the session is\n * already in a terminal state (exited/killed/error or awaitingInput) and\n * resolves immediately if so, covering the gap between session spawn and\n * this function being called.\n */\n const waitTurnEnd = (sessionId: string): Promise<void> =>\n new Promise(resolve => {\n const unsubs: Array<() => void> = []\n const done = (): void => {\n for (const u of unsubs) u()\n resolve()\n }\n unsubs.push(\n sessionEvents.on(\"session:turn-end\", ev => {\n if (ev.sessionId === sessionId) done()\n }),\n )\n unsubs.push(\n sessionEvents.on(\"session:awaiting-input\", ev => {\n if (ev.sessionId === sessionId) done()\n }),\n )\n unsubs.push(\n sessionEvents.on(\"session:exited\", ev => {\n if (ev.sessionId === sessionId) done()\n }),\n )\n // Belt-and-suspenders: resolve immediately if the session is already done.\n // Covers the window between session spawn and this subscription being set up.\n const desc = registry.get(sessionId)\n const isTerminal =\n desc?.status === \"exited\" ||\n desc?.status === \"killed\" ||\n desc?.status === \"error\" ||\n desc?.awaitingInput === true\n if (isTerminal) done()\n })\n\n /** Spawn a new agent session for the given step. */\n const spawnSession = async (\n step: RoutineStep,\n state: RunState,\n ): Promise<string | null> => {\n if (!step.adapter) return null\n const resolved = await resolveAgentAdapter(step.adapter)\n if (!resolved) return null\n const lastSessionId = state.run.result?.sessionIds.at(-1)\n // state.cwd wins (explicit caller intent); fall back to last session's cwd;\n // last resort: daemon's process.cwd().\n const cwd =\n state.cwd ??\n (lastSessionId ? registry.get(lastSessionId)?.cwd : undefined) ??\n process.cwd()\n try {\n const agentSession = await resolved.startSession({ cwd })\n const desc = registry.spawnAgent({\n workspaceSlug: state.workspaceSlug ?? \"default\",\n cwd,\n agentSession,\n adapterSlug: step.adapter,\n label: `routine:${state.run.routineId}:${step.label}`,\n ...(resolved.commandPreview ? { commandPreview: resolved.commandPreview } : {}),\n })\n state.run.result ??= { sessionIds: [] }\n state.run.result.sessionIds.push(desc.id)\n return desc.id\n } catch {\n return null\n }\n }\n\n // ── Step executor ──────────────────────────────────────────────────\n\n const executeStep = async (\n stepDef: RoutineStep,\n stepState: RoutineStepState,\n state: RunState,\n ): Promise<void> => {\n stepState.status = \"running\"\n stepState.startedAt = new Date().toISOString()\n persist()\n\n try {\n // Fan-in: wait for all listed sessions\n if (stepDef.waitFor?.length) {\n await Promise.all(stepDef.waitFor.map(id => waitTurnEnd(id)))\n }\n\n if (state.cancelled) {\n stepState.status = \"skipped\"\n return\n }\n\n // Spawn / reuse session\n let sessionId: string | null = null\n if (stepDef.adapter) {\n sessionId = await spawnSession(stepDef, state)\n if (sessionId) stepState.sessionId = sessionId\n } else if (state.run.result?.sessionIds.length) {\n sessionId = state.run.result.sessionIds.at(-1) ?? null\n if (sessionId) stepState.sessionId = sessionId\n }\n\n if (state.cancelled) {\n stepState.status = \"skipped\"\n return\n }\n\n // Subscribe to turn-end BEFORE sending the prompt so a fast session\n // cannot fire the event in the window between sendPrompt() resolving\n // and a later waitTurnEnd() call setting up its listeners.\n if (sessionId) {\n const turnEnded = waitTurnEnd(sessionId)\n if (stepDef.prompt) {\n await registry.sendPrompt(sessionId, stepDef.prompt)\n }\n await turnEnded\n }\n\n if (state.cancelled) {\n stepState.status = \"skipped\"\n return\n }\n\n // Check awaiting-input\n const desc = sessionId ? registry.get(sessionId) : undefined\n if (desc && (desc as { awaitingInput?: boolean }).awaitingInput) {\n const policy = stepDef.policy ?? { awaiting: \"fail\" }\n if (policy.awaiting === \"auto-allow\") {\n const turnEnded = waitTurnEnd(sessionId!)\n await registry.sendPrompt(sessionId!, policy.prompt)\n await turnEnded\n } else if (policy.awaiting === \"escalate\") {\n const escalateUrl = policy.webhookUrl ?? state.run.notifyUrl\n if (escalateUrl) {\n void fetch(escalateUrl, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n type: \"routine:awaiting-input\",\n runId: state.run.runId,\n routineId: state.run.routineId,\n stepIndex: stepState.index,\n stepLabel: stepDef.label,\n }),\n signal: AbortSignal.timeout(10_000),\n }).catch(() => undefined)\n }\n state.run.status = \"awaiting-input\"\n persist()\n // Wait for external resolve()\n const response = await new Promise<string>((res, rej) => {\n const timeoutMs = policy.timeoutMs ?? 300_000\n const timer = setTimeout(() => {\n state.pendingResolve = undefined\n rej(new Error(\"escalate timeout\"))\n }, timeoutMs)\n state.pendingResolve = {\n stepIndex: stepState.index,\n resolver: (r: string) => {\n clearTimeout(timer)\n state.pendingResolve = undefined\n res(r)\n },\n }\n })\n state.run.status = \"running\"\n persist()\n if (sessionId) {\n const turnEnded = waitTurnEnd(sessionId)\n await registry.sendPrompt(sessionId, response)\n await turnEnded\n }\n } else {\n // policy.awaiting === \"fail\"\n throw new Error(\"step failed: session awaiting input\")\n }\n }\n\n stepState.status = \"done\"\n stepState.endedAt = new Date().toISOString()\n persist()\n } catch (err) {\n stepState.status = \"failed\"\n stepState.endedAt = new Date().toISOString()\n stepState.error = err instanceof Error ? err.message : String(err)\n persist()\n throw err\n }\n }\n\n // ── Run executor ───────────────────────────────────────────────────\n\n const executeRun = async (state: RunState, steps: RoutineStep[]): Promise<void> => {\n try {\n for (let i = 0; i < steps.length; i++) {\n if (state.cancelled) break\n const stepState = state.run.steps[i]!\n await executeStep(steps[i]!, stepState, state)\n if (stepState.status === \"failed\") {\n state.run.status = \"failed\"\n state.run.error = stepState.error\n state.run.endedAt = new Date().toISOString()\n persist()\n return\n }\n }\n if (state.cancelled) {\n state.run.status = \"cancelled\"\n } else {\n state.run.status = \"done\"\n }\n state.run.endedAt = new Date().toISOString()\n persist()\n\n // Fire webhook if requested\n if (state.run.notifyUrl) {\n void fetch(state.run.notifyUrl, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n type: state.cancelled ? \"routine:cancelled\" : \"routine:done\",\n runId: state.run.runId,\n result: state.run.result,\n }),\n signal: AbortSignal.timeout(10_000),\n }).catch(() => undefined)\n }\n } catch {\n state.run.status = \"failed\"\n state.run.endedAt = new Date().toISOString()\n persist()\n }\n }\n\n // ── Public interface ───────────────────────────────────────────────\n\n return {\n start: async (input) => {\n const runId = `run_${randomUUID()}`\n const run: RoutineRun = {\n runId,\n routineId: input.routineId,\n status: \"running\",\n startedAt: new Date().toISOString(),\n steps: input.steps.map((s, i) => ({\n index: i,\n label: s.label,\n status: \"pending\",\n })),\n ...(input.notifyUrl ? { notifyUrl: input.notifyUrl } : {}),\n }\n const state: RunState = {\n run,\n cancelled: false,\n ...(input.cwd !== undefined ? { cwd: input.cwd } : {}),\n ...(input.workspaceSlug !== undefined ? { workspaceSlug: input.workspaceSlug } : {}),\n }\n runs.set(runId, state)\n persist()\n // Fire-and-forget: run steps in background\n void executeRun(state, input.steps)\n return run\n },\n\n status: (runId) => runs.get(runId)?.run,\n\n list: () => Array.from(runs.values()).map(s => s.run),\n\n resolve: (runId, stepIndex, response) => {\n const state = runs.get(runId)\n if (!state) return\n const pr = state.pendingResolve\n if (pr && pr.stepIndex === stepIndex) {\n pr.resolver(response)\n }\n },\n\n cancel: (runId) => {\n const state = runs.get(runId)\n if (!state) return\n state.cancelled = true\n // If the run is already terminal, leave it; otherwise mark cancelled\n if (state.run.status === \"running\" || state.run.status === \"awaiting-input\") {\n state.run.status = \"cancelled\"\n state.run.endedAt = new Date().toISOString()\n persist()\n }\n },\n }\n}\n","/**\n * Completion-policy supervisor — WP1 + WP2 + WP3 + WP4 + WP5 + WP6 + WP7.\n *\n * WP7 (judge-gate): a gate may be a judge AGENT instead of a shell command —\n * `gate: { judge: { adapter, model?, prompt, timeoutMs? } }`. When the trigger\n * fires the supervisor spawns a short-lived agent (resolveAgentAdapter →\n * spawnAgent), prompts it with the rubric (+ a minimal context tail of the\n * watched session output), waits for its turn-end on the bus, reads the final\n * reply and parses the LAST `VERDICT: PASS|FAIL` line (case-insensitive). PASS\n * = gate pass (then-action), FAIL = gate fail (existing nudge/escalate path).\n * Fail-safe: no resolver / spawn fail / timeout (default 120s) / unparseable\n * verdict → FAIL (+ reason on state.error). The judge session is ALWAYS killed\n * when the gate settles. The judge runs while the policy holds its `gating`\n * slot, so it is accounted for in the WP6 concurrency cap. Persistence: a judge\n * gate left in `gating` at crash is re-armed to `watching` like any active\n * policy and simply re-runs the judge — no in-flight judge is persisted.\n *\n *\n * State machine per attached policy:\n * watching → gating → acting → done\n * ↘ nudging (retries < maxRetries) → watching (gate failed, nudge sent)\n * ↘ blocked (gate failed, retries exhausted)\n * ↘ awaiting-ack → done (then:\"commit\" + requireHumanAck, ack approve)\n * ↘ cancelled (ack reject)\n * watching → cancelled (watched session exited before turn-end)\n *\n * Trigger: session:turn-end on the watched session(s).\n * Gate: optional shell command via the same allowlist + cwd-anchor as\n * execute_command. exit 0 = pass.\n * Action (then:\"emit\"): emits policy:passed / policy:failed on the bus\n * (readable via poll_events).\n *\n * WP5 (then:\"commit\"): on a GREEN gate, prepare a host-side git commit in the\n * watched session's cwd — `git add -- <explicit paths>` then `git commit -m\n * <message>` via the same allowlisted runCommand path (argv array, shell:false).\n * GUARDRAILS: never `git add -A`/glob, never `git push`, never `--force`, never\n * a branch the policy didn't ask for (commits the cwd's current branch), message\n * passed as argv (no shell injection), empty paths → error (no commit). A `--`\n * separator precedes the paths so a path can never be parsed as a git flag.\n * \"nothing to commit\" is treated as SUCCESS (idempotent re-commit after a\n * restart). `requireHumanAck` defaults to TRUE: the gate-green transition goes\n * to `awaiting-ack` and emits `policy:commit-ready` (paths + message) instead of\n * committing; the commit runs only on `ack_policy(approve:true)` →\n * `policy:committed` (+ sha) → done; `approve:false` → cancelled. With\n * `requireHumanAck:false` the commit runs directly at the green gate.\n * onFail (WP2): when gate fails, re-prompts the session(s) (sendPrompt) up to\n * maxRetries times, then transitions to blocked + emits policy:failed.\n *\n * WP3: persists PolicyRunState + input to ~/.agentproto/policies.json (or an\n * injected persistPath). Debounced async write on every transition; sync flush\n * at shutdown(). On boot, active policies (watching/gating/nudging/acting) are\n * re-armed to \"watching\" and re-subscribed to the bus. Terminal states (done/\n * blocked/cancelled) are kept for history. Session absent at reload → cancelled.\n *\n * WP6 (DAG + concurrency cap):\n * - CHAINING: a policy may declare `next` — a recursive AttachPolicyInput.\n * When the policy reaches `done` (emit-passed or commit-committed), the\n * supervisor automatically attaches `next` as a fresh completion policy on\n * the session(s) named in its own spec (chaining policies over EXISTING\n * sessions — this WP does NOT spawn new sessions). The child's policyId is\n * recorded on the parent as `nextPolicyId`. Chaining is idempotent (a parent\n * already carrying a `nextPolicyId` never re-chains, so a re-armed/re-acked\n * parent after a restart won't double-attach). `next` persists as part of the\n * parent's `input`, so the whole chain survives a restart.\n * - CONCURRENCY CAP: a daemon-wide cap (`concurrencyCap`, default 8) on how\n * many policies may be in `gating`/`acting` at once. When a trigger fires\n * and the cap is already saturated, the policy parks in `queued` (a FIFO\n * gate queue) instead of gating. As each active policy settles (done /\n * blocked / awaiting-ack / back-to-watching after a nudge), the queue is\n * pumped and the oldest queued policy proceeds to gate. Queued policies hold\n * NO slot, so a chained DAG can't deadlock behind the cap. The queued state\n * persists and is re-armed to `watching` on reload (then re-evaluated).\n *\n * WP4 (fan-in): a policy may watch a GROUP of sessions (`sessionIds`). The gate\n * runs ONCE, only after EVERY member of the group has finished its turn. Members\n * are tracked in an idempotent `pending` set: a member is removed on its first\n * `session:turn-end`; a repeated turn-end for an already-removed member is a\n * no-op (no double-count). When the set empties → gating.\n *\n * A member that emits `session:exited` is treated as \"this member is done\": it\n * is removed from the pending set exactly like a turn-end (a dead session will\n * never emit one), so a partially-crashed group can still complete. If every\n * member exits, the set empties and the gate runs once. The one exception is the\n * degenerate group of size 1 (the legacy single-`sessionId` form): a lone\n * watched session that exits has nothing left to gate on, so the policy is\n * cancelled — preserving the original single-session contract.\n *\n * Back-compat: the legacy `sessionId` (single) form is a group of one. `state.\n * sessionId` is retained as the group's representative (group[0]) and is the id\n * carried on policy:passed / policy:failed events.\n */\n\nimport { randomUUID } from \"node:crypto\"\nimport { basename, dirname } from \"node:path\"\nimport { homedir } from \"node:os\"\nimport { resolve } from \"node:path\"\nimport {\n mkdirSync,\n writeFileSync,\n readFileSync,\n promises as fsp,\n} from \"node:fs\"\nimport type { SessionsRegistry } from \"./sessions.js\"\nimport type { SessionEventBus } from \"./session-event-bus.js\"\nimport type { AgentAdapterResolver } from \"./http-server.js\"\nimport {\n runCommand as defaultRunCommand,\n loadAllowlist,\n makeCwdAnchor,\n} from \"./command-tools.js\"\nimport type { RunCommandInput, ExecuteResult } from \"./command-tools.js\"\n\n// ── Public types ─────────────────────────────────────────────────────\n\nexport interface ShellGateSpec {\n command: string\n args?: string[]\n /** Working directory for the gate command. Defaults to the watched\n * session's cwd, anchored to the workspace. */\n cwd?: string\n timeoutMs?: number\n}\n\n/**\n * Judge-agent gate (WP7). Instead of a shell command, the gate spawns a\n * short-lived LLM agent (via the daemon's `resolveAgentAdapter`), prompts it\n * with `prompt` (+ a minimal context tail of the watched session output, if\n * readable), waits for its turn to end, reads the final reply and parses a\n * verdict line (`VERDICT: PASS` / `VERDICT: FAIL`, last occurrence,\n * case-insensitive). PASS = gate pass (exit 0 equivalent), FAIL = gate fail\n * (→ the existing nudge/escalate path). Fail-safe: a judge timeout OR an\n * unparseable reply is treated as FAIL. The judge session is always killed\n * when the gate settles (success or failure).\n */\nexport interface JudgeGateSpec {\n judge: {\n /** Agent CLI adapter slug used to spawn the judge (e.g. \"claude-code\"). */\n adapter: string\n /** Optional model identifier forwarded to the adapter. */\n model?: string\n /** The rubric / instructions for the judge. The supervisor appends a\n * fixed instruction to end the reply with `VERDICT: PASS` or\n * `VERDICT: FAIL`. */\n prompt: string\n /** Max wall-clock for the judge turn before it is killed + FAIL.\n * Default 120_000ms. */\n timeoutMs?: number\n }\n}\n\n/** A gate is either a shell command (exit 0 = pass) or a judge agent. */\nexport type GateSpec = ShellGateSpec | JudgeGateSpec\n\n/** Narrow a gate spec to the judge variant. */\nfunction isJudgeGate(gate: GateSpec): gate is JudgeGateSpec {\n return typeof (gate as JudgeGateSpec).judge === \"object\"\n}\n\nexport interface OnFailSpec {\n /**\n * Message sent to the watched session via sendPrompt when the gate fails.\n * Use the placeholder {code} to embed the actual exit code.\n * Default: \"Le gate a échoué (exit {code}). Corrige et termine jusqu'à ce qu'il passe.\"\n */\n nudge?: string\n /**\n * Maximum number of consecutive gate failures before transitioning to\n * blocked. Must be >= 1. Default: 2.\n */\n maxRetries?: number\n}\n\nexport interface CommitSpec {\n /**\n * Explicit, literal paths to stage — workspace/cwd-relative. NEVER a glob,\n * NEVER `-A`/`--all`. Staged via `git add -- <paths>` (the `--` guards each\n * path from being parsed as a flag). An empty array is rejected at attach.\n */\n paths: string[]\n /** Commit message. Passed as a single `-m` argv value — no shell. */\n message: string\n /**\n * Human-in-the-loop gate before the commit actually runs. Default TRUE:\n * the green gate transitions to `awaiting-ack` + emits `policy:commit-ready`\n * and waits for `ack_policy`. Set false to commit directly at the green gate.\n */\n requireHumanAck?: boolean\n}\n\nexport interface AttachPolicyInput {\n /**\n * Session id whose turn-end triggers the policy (single-session / legacy\n * form). Equivalent to `sessionIds: [sessionId]`. Provide this OR\n * `sessionIds`; if both are given, `sessionIds` wins.\n */\n sessionId?: string\n /**\n * Fan-in group (WP4): the gate runs once, only after EVERY listed session\n * has finished its turn (turn-end or exit). Supersedes `sessionId` when\n * present and non-empty. A single-element array behaves like `sessionId`.\n */\n sessionIds?: string[]\n /**\n * Optional gate. Absent → always pass immediately. Either a shell gate\n * (exit 0 = pass) or a judge-agent gate (WP7: `{ judge: {...} }`).\n */\n gate?: GateSpec\n /**\n * Action on a GREEN gate. \"emit\" (WP1) emits policy:passed. \"commit\" (WP5)\n * stages explicit paths and commits on the host — see `commit`.\n */\n then: \"emit\" | \"commit\"\n /** Required when then === \"commit\". Ignored otherwise. */\n commit?: CommitSpec\n /**\n * What to do when the gate fails (WP2). Absent → immediately blocked\n * (WP1 behaviour). Present → re-prompt the session up to maxRetries\n * times before blocking; the session must still be running to nudge.\n */\n onFail?: OnFailSpec\n /**\n * DAG chaining (WP6). When this policy reaches `done`, the supervisor\n * automatically attaches `next` as a fresh completion policy. `next` is a\n * full AttachPolicyInput (recursive — it may declare its own `next`), and it\n * carries the session(s) it watches in its own spec. Chaining only attaches\n * policies onto already-running sessions; it never spawns new sessions.\n */\n next?: AttachPolicyInput\n}\n\nexport type PolicyRunStatus =\n | \"watching\"\n | \"queued\"\n | \"gating\"\n | \"acting\"\n | \"nudging\"\n | \"awaiting-ack\"\n | \"done\"\n | \"blocked\"\n | \"cancelled\"\n\nexport interface PolicyRunState {\n policyId: string\n /** Representative session id (the fan-in group's first member, group[0]).\n * Carried on policy:passed / policy:failed events. */\n sessionId: string\n /** The full fan-in group being watched. Always present; a length-1 group is\n * the legacy single-session form. */\n sessionIds: string[]\n /** Sessions in the group that have NOT yet finished their turn. The gate\n * fires once this set empties. Idempotent: a member is removed on its first\n * turn-end/exit; repeats are no-ops. Reset to the full group on each nudge. */\n pending: string[]\n status: PolicyRunStatus\n /** Number of nudges sent so far (incremented after each nudge round). */\n retries: number\n startedAt: string\n endedAt?: string\n lastGate?: { exitCode: number; at: string }\n /**\n * The exact commit prepared at the green gate (WP5). Set when entering\n * `awaiting-ack` (or just before a direct commit) so that an ack arriving\n * after a daemon restart commits the same paths/message in the same cwd,\n * independent of whether the watched session still exists.\n */\n commitPlan?: { paths: string[]; message: string; cwd: string }\n /** The resulting commit sha once `then:\"commit\"` has committed. */\n commitSha?: string\n /**\n * DAG chaining (WP6): the policyId of the child policy attached when this\n * policy reached `done`. Set exactly once (idempotent chaining guard).\n */\n nextPolicyId?: string\n error?: string\n}\n\nexport interface CompletionPolicySupervisor {\n /**\n * Attach a completion policy to an already-running session.\n * Returns immediately with the initial (watching) state.\n * The state machine runs in the background.\n */\n attach(input: AttachPolicyInput): PolicyRunState\n getStatus(policyId: string): PolicyRunState | undefined\n cancel(policyId: string): void\n /**\n * Human acknowledgement for a `then:\"commit\"` policy parked in\n * `awaiting-ack` (WP5). `approve:true` runs the prepared commit (→ done,\n * emits policy:committed); `approve:false` cancels it (no commit). No-op on\n * any other state. Returns the (possibly updated) state.\n */\n ack(policyId: string, approve: boolean): Promise<PolicyRunState | undefined>\n list(): PolicyRunState[]\n /**\n * Sync flush of the policy snapshot to disk. Call from the daemon\n * stop() path — mirrors sessions.shutdown().\n */\n shutdown(): void\n}\n\n// ── Internal ─────────────────────────────────────────────────────────\n\ninterface RunEntry {\n input: AttachPolicyInput\n /** Resolved fan-in group (deduped, order-preserved). group[0] is the repr. */\n group: string[]\n /** Live idempotent set of sessions still awaited. Mirrored to state.pending. */\n pending: Set<string>\n state: PolicyRunState\n unsubscribes: Array<() => void>\n cancelled: boolean\n /** Per-entry gate runner, set by armEntry; invoked by the concurrency-cap\n * queue pump (WP6) when a slot frees. */\n runGate?: () => Promise<void>\n}\n\n/**\n * Resolve the watched group from an attach input. `sessionIds` (when present\n * and non-empty) wins over the legacy `sessionId`. Deduped, order-preserved.\n * Throws if neither yields a session id.\n */\nfunction resolveGroup(input: AttachPolicyInput): string[] {\n const raw =\n input.sessionIds && input.sessionIds.length > 0\n ? input.sessionIds\n : input.sessionId\n ? [input.sessionId]\n : []\n const group = Array.from(new Set(raw))\n if (group.length === 0) {\n throw new Error(\"attach_policy requires sessionId or a non-empty sessionIds\")\n }\n return group\n}\n\n/** Persisted envelope written to policies.json. */\ninterface PolicySnapshot {\n savedAt: string\n policies: Array<{ input: AttachPolicyInput; state: PolicyRunState }>\n}\n\nconst DEFAULT_NUDGE_TEMPLATE =\n \"Le gate a échoué (exit {code}). Corrige et termine jusqu'à ce qu'il passe.\"\nconst DEFAULT_MAX_RETRIES = 2\n/** Judge-gate (WP7) wall-clock default before timeout → kill + FAIL. */\nconst DEFAULT_JUDGE_TIMEOUT_MS = 120_000\n/** Fixed instruction appended to the judge prompt so its verdict is parseable. */\nconst JUDGE_VERDICT_INSTRUCTION =\n \"\\n\\nWhen you are done, end your reply with a single line containing exactly \" +\n \"`VERDICT: PASS` (if the criteria are met) or `VERDICT: FAIL` (if not). \" +\n \"Do not write anything after that line.\"\n/** Strip ANSI escape sequences (mirrors session-tools.stripAnsi). */\n// eslint-disable-next-line no-control-regex\nconst ANSI_RE = /\\x1b\\[[0-9;?]*[A-Za-z]/g\nfunction stripAnsi(s: string): string {\n return s.replace(ANSI_RE, \"\")\n}\n/**\n * Parse the judge verdict from its final reply. Scans for `VERDICT: PASS|FAIL`\n * (case-insensitive) and returns the LAST occurrence. Returns null when no\n * verdict line is present → caller treats as FAIL (fail-safe).\n */\nfunction parseVerdict(text: string): \"PASS\" | \"FAIL\" | null {\n const re = /VERDICT:\\s*(PASS|FAIL)/gi\n let last: \"PASS\" | \"FAIL\" | null = null\n let m: RegExpExecArray | null\n while ((m = re.exec(text)) !== null) {\n last = m[1]!.toUpperCase() as \"PASS\" | \"FAIL\"\n }\n return last\n}\nconst PERSIST_DEBOUNCE_MS = 1_500\n/** Daemon-wide default cap on policies concurrently in gating/acting (WP6). */\nconst DEFAULT_CONCURRENCY_CAP = 8\n\nexport const POLICIES_FILE_PATH = (): string =>\n resolve(homedir(), \".agentproto\", \"policies.json\")\n\n// ── Factory ──────────────────────────────────────────────────────────\n\nexport function createCompletionPolicySupervisor(opts: {\n registry: SessionsRegistry\n sessionEvents: SessionEventBus\n workspace: string\n /** Override the persist path — used in tests to avoid touching ~/.agentproto. */\n persistPath?: string\n /** Disable persistence entirely (e.g. for unit tests that don't need it). */\n persist?: boolean\n /**\n * Inject the command runner — used by tests to mock git (gate + commit) so\n * no real subprocess/commit runs. Defaults to the host runCommand.\n */\n runCommand?: (input: RunCommandInput) => Promise<ExecuteResult>\n /**\n * Daemon-wide cap on policies concurrently in gating/acting (WP6). Excess\n * triggered policies queue (FIFO) until a slot frees. Default 8. Values < 1\n * are clamped to 1.\n */\n concurrencyCap?: number\n /**\n * Adapter resolver used to spawn a judge agent for a judge-gate (WP7).\n * Same resolver the daemon passes to `start_agent_session`. When absent, a\n * judge-gate fails fail-safe (FAIL) with a clear reason — shell gates are\n * unaffected.\n */\n resolveAgentAdapter?: AgentAdapterResolver\n}): CompletionPolicySupervisor {\n const { registry, sessionEvents, workspace, resolveAgentAdapter } = opts\n const exec = opts.runCommand ?? defaultRunCommand\n const persistPath = opts.persistPath ?? POLICIES_FILE_PATH()\n const cap = Math.max(1, opts.concurrencyCap ?? DEFAULT_CONCURRENCY_CAP)\n /** FIFO queue of entries whose trigger fired while the cap was saturated. */\n const gateQueue: RunEntry[] = []\n // Default false: WP1/WP2 tests (no opts.persist, no opts.persistPath)\n // don't touch ~/.agentproto. Set opts.persist:true in production\n // (createGateway) or supply persistPath to implicitly enable it.\n const persist = opts.persist ?? (opts.persistPath !== undefined)\n const anchorCwd = makeCwdAnchor(workspace)\n const runs = new Map<string, RunEntry>()\n let persistTimer: ReturnType<typeof setTimeout> | null = null\n let shutdownDone = false\n\n // ── persistence helpers ──────────────────────────────────────────\n\n const buildSnapshot = (): PolicySnapshot => ({\n savedAt: new Date().toISOString(),\n policies: Array.from(runs.values()).map(e => ({\n input: e.input,\n state: e.state,\n })),\n })\n\n const schedulePersist = (): void => {\n if (!persist) return\n if (persistTimer) clearTimeout(persistTimer)\n persistTimer = setTimeout(() => {\n void (async () => {\n try {\n const snap = buildSnapshot()\n await fsp.mkdir(dirname(persistPath), { recursive: true })\n await fsp.writeFile(\n persistPath,\n JSON.stringify(snap, null, 2) + \"\\n\",\n )\n } catch (err) {\n console.warn(\n `[supervisor] persist failed: ${err instanceof Error ? err.message : String(err)}`,\n )\n }\n })()\n }, PERSIST_DEBOUNCE_MS)\n }\n\n // ── concurrency cap (WP6) ────────────────────────────────────────\n\n /** Policies currently holding a slot — i.e. in gating or acting. */\n const countActive = (): number => {\n let n = 0\n for (const e of runs.values()) {\n if (e.state.status === \"gating\" || e.state.status === \"acting\") n++\n }\n return n\n }\n\n /**\n * Release-time pump: while there is a free slot, dequeue the oldest queued\n * entry and run its gate. A dequeued entry is flipped back to `watching` so\n * its runGate() guard passes; runGate() then synchronously sets `gating`\n * (before its first await), so the loop's next countActive() sees the slot\n * taken — no over-admission. Cancelled / no-longer-queued entries are skipped.\n */\n const pumpQueue = (): void => {\n while (gateQueue.length > 0 && countActive() < cap) {\n const entry = gateQueue.shift()!\n if (entry.cancelled || entry.state.status !== \"queued\") continue\n entry.state.status = \"watching\"\n schedulePersist()\n void entry.runGate?.()\n }\n }\n\n // ── DAG chaining (WP6) ───────────────────────────────────────────\n\n /**\n * When `entry` reaches `done`, attach its `next` policy (if any) onto the\n * session(s) named in the `next` spec. Idempotent: a parent that already\n * carries a `nextPolicyId` never re-chains, so a re-armed or re-acked parent\n * after a restart won't double-attach the child.\n */\n const maybeChain = (entry: RunEntry): void => {\n const next = entry.input.next\n if (!next) return\n if (entry.state.nextPolicyId) return\n try {\n const child = attachPolicy(next)\n entry.state.nextPolicyId = child.policyId\n schedulePersist()\n } catch (err) {\n entry.state.error = `next chain failed: ${err instanceof Error ? err.message : String(err)}`\n schedulePersist()\n }\n }\n\n // ── commit action (WP5) ──────────────────────────────────────────\n\n /**\n * Stage explicit paths and commit on the host. Fixed argv, shell:false:\n * git add -- <paths...> (the `--` guards paths from flag-parsing)\n * git commit -m <message> (message is one argv value, never a shell str)\n * git rev-parse HEAD (read back the sha)\n * No `-A`, no glob, no push, no --force, no branch switch — the commit lands\n * on whatever branch the cwd is already on. \"nothing to commit\" → success.\n */\n async function performCommit(plan: {\n paths: string[]\n message: string\n cwd: string\n }): Promise<{ sha: string } | { error: string }> {\n if (plan.paths.length === 0) {\n return { error: \"commit requires a non-empty paths[]\" }\n }\n // Defensive: argv-only, but still refuse blatantly unsafe path entries.\n if (plan.paths.some(p => typeof p !== \"string\" || p.length === 0)) {\n return { error: \"commit paths must be non-empty strings\" }\n }\n\n const allowlist = await loadAllowlist(workspace)\n if (!allowlist.has(\"git\")) {\n return { error: \"commit command 'git' not in allowlist\" }\n }\n\n const add = await exec({\n command: \"git\",\n args: [\"add\", \"--\", ...plan.paths],\n cwd: plan.cwd,\n timeoutMs: 60_000,\n })\n if (add.exitCode !== 0) {\n return { error: `git add failed (exit ${add.exitCode}): ${add.stderr.trim()}` }\n }\n\n const commit = await exec({\n command: \"git\",\n args: [\"commit\", \"-m\", plan.message],\n cwd: plan.cwd,\n timeoutMs: 60_000,\n })\n // \"nothing to commit\" is success — a re-armed policy after a crash may find\n // the tree already committed (design §5.4).\n const out = `${commit.stdout}\\n${commit.stderr}`\n const nothingToCommit = /nothing to commit|no changes added|nothing added to commit/i.test(out)\n if (commit.exitCode !== 0 && !nothingToCommit) {\n return { error: `git commit failed (exit ${commit.exitCode}): ${commit.stderr.trim()}` }\n }\n\n const head = await exec({\n command: \"git\",\n args: [\"rev-parse\", \"HEAD\"],\n cwd: plan.cwd,\n timeoutMs: 30_000,\n })\n if (head.exitCode !== 0) {\n return { error: `git rev-parse HEAD failed (exit ${head.exitCode}): ${head.stderr.trim()}` }\n }\n return { sha: head.stdout.trim() }\n }\n\n /**\n * Run the prepared commit for `entry` and settle its state. Does NOT touch\n * bus subscriptions (callers handle that). Used by both the direct-commit\n * path and the ack-approve path.\n */\n async function finishCommit(entry: RunEntry): Promise<void> {\n const state = entry.state\n const repr = entry.group[0]!\n const plan = state.commitPlan\n if (!plan) {\n state.status = \"blocked\"\n state.error = \"no commit plan\"\n state.endedAt = new Date().toISOString()\n sessionEvents.emit({\n type: \"policy:failed\",\n policyId: state.policyId,\n sessionId: repr,\n ts: new Date().toISOString(),\n })\n schedulePersist()\n return\n }\n\n const result = await performCommit(plan)\n if (\"error\" in result) {\n state.status = \"blocked\"\n state.error = result.error\n state.endedAt = new Date().toISOString()\n sessionEvents.emit({\n type: \"policy:failed\",\n policyId: state.policyId,\n sessionId: repr,\n ts: new Date().toISOString(),\n })\n schedulePersist()\n pumpQueue() // WP6: release the slot this commit held\n return\n }\n\n state.commitSha = result.sha\n state.status = \"done\"\n state.endedAt = new Date().toISOString()\n sessionEvents.emit({\n type: \"policy:committed\",\n policyId: state.policyId,\n sessionId: repr,\n sha: result.sha,\n paths: plan.paths,\n message: plan.message,\n ts: new Date().toISOString(),\n })\n schedulePersist()\n maybeChain(entry) // WP6: attach `next` now that this policy is done\n pumpQueue() // WP6: release the slot this commit held\n }\n\n // ── arm logic (shared by attach() and reload) ────────────────────\n\n /**\n * Set up bus subscriptions for a run entry. Called both when\n * attaching a fresh policy and when re-arming after reload.\n * The caller is responsible for inserting the entry into `runs`.\n */\n function armEntry(entry: RunEntry): void {\n const { input, state, unsubscribes } = entry\n const group = entry.group\n // Representative session id used for cwd resolution and event payloads.\n // group is guaranteed non-empty by resolveGroup.\n const repr = group[0]!\n\n // Keep the serializable mirror (state.pending) in sync with the live set.\n const syncPending = () => {\n state.pending = Array.from(entry.pending)\n }\n\n let settled = false\n const cleanup = () => {\n if (settled) return\n settled = true\n for (const u of unsubscribes) u()\n unsubscribes.length = 0\n }\n\n const emitFailed = (exitCode: number | undefined, error?: string) => {\n if (error) state.error = error\n state.status = \"blocked\"\n state.endedAt = new Date().toISOString()\n sessionEvents.emit({\n type: \"policy:failed\",\n policyId: state.policyId,\n sessionId: repr,\n ...(exitCode !== undefined ? { exitCode } : {}),\n ts: new Date().toISOString(),\n })\n schedulePersist()\n cleanup()\n pumpQueue() // WP6: release the slot (if any) this run held\n }\n\n const act = async (passed: boolean, exitCode: number) => {\n if (entry.cancelled) return\n state.status = \"acting\"\n schedulePersist()\n\n if (passed) {\n // WP5: commit action. Prepare the plan in the watched session's cwd.\n if (input.then === \"commit\") {\n const commit = input.commit!\n const cwd = anchorCwd(registry.get(repr)?.cwd ?? workspace)\n state.commitPlan = {\n paths: commit.paths,\n message: commit.message,\n cwd,\n }\n const requireAck = commit.requireHumanAck !== false // default true\n if (requireAck) {\n // Don't commit yet — park in awaiting-ack and surface the plan.\n state.status = \"awaiting-ack\"\n schedulePersist()\n sessionEvents.emit({\n type: \"policy:commit-ready\",\n policyId: state.policyId,\n sessionId: repr,\n paths: commit.paths,\n message: commit.message,\n ts: new Date().toISOString(),\n })\n // Stop watching the bus; ack_policy drives the rest. The entry\n // stays in `runs` so ack() can find it.\n cleanup()\n pumpQueue() // WP6: parked awaiting ack — release the slot\n return\n }\n // Unattended commit — run it directly at the green gate.\n // finishCommit handles maybeChain + pumpQueue on settle.\n await finishCommit(entry)\n cleanup()\n return\n }\n\n // then === \"emit\" (WP1)\n sessionEvents.emit({\n type: \"policy:passed\",\n policyId: state.policyId,\n sessionId: repr,\n ts: new Date().toISOString(),\n })\n state.status = \"done\"\n state.endedAt = new Date().toISOString()\n schedulePersist()\n cleanup()\n maybeChain(entry) // WP6: attach `next` now that this policy is done\n pumpQueue() // WP6: release the slot this run held\n return\n }\n\n // Gate failed — attempt bounded nudge if configured (WP2).\n if (input.onFail !== undefined) {\n const maxRetries = input.onFail.maxRetries ?? DEFAULT_MAX_RETRIES\n if (state.retries < maxRetries) {\n // Nudge every still-running member of the group (fan-in: WP4).\n const running = group.filter(\n id => registry.get(id)?.status === \"running\",\n )\n if (running.length > 0) {\n const template = input.onFail.nudge ?? DEFAULT_NUDGE_TEMPLATE\n const nudgeMsg = template.replace(\"{code}\", String(exitCode))\n state.status = \"nudging\"\n schedulePersist()\n try {\n for (const id of running) {\n await registry.sendPrompt(id, nudgeMsg)\n }\n } catch {\n emitFailed(exitCode, \"nudge prompt delivery failed\")\n return\n }\n state.retries++\n // Reset the fan-in set to the full group and return to watching —\n // bus subscriptions remain active; the gate fires again only once\n // every member has finished another turn.\n entry.pending = new Set(group)\n syncPending()\n state.status = \"watching\"\n schedulePersist()\n pumpQueue() // WP6: nudged back to watching — release the slot\n return\n }\n }\n }\n\n // No nudge configured, no running member, or retries exhausted → block\n emitFailed(exitCode)\n }\n\n /**\n * Read the recent ring-buffer tail of a session (best-effort) — used to\n * give the judge a minimal context of the watched session's output. Mirrors\n * get_agent_session_output: attach captures the backfill synchronously, then\n * unsubscribe. Returns \"\" when the session/attach is unavailable.\n */\n const readTail = (sessionId: string, lastN: number): string => {\n const lines: string[] = []\n let unsub: (() => void) | null = null\n try {\n unsub = registry.attach(sessionId, line => {\n lines.push(line)\n })\n } catch {\n return \"\"\n }\n if (unsub) unsub()\n return lines.slice(-lastN).map(stripAnsi).join(\"\\n\").trim()\n }\n\n /**\n * WP7: run a judge-agent gate. Spawns a short-lived agent via\n * resolveAgentAdapter, prompts it with the rubric (+ a minimal context tail),\n * waits for its turn-end (or a timeout), parses VERDICT: PASS/FAIL from the\n * final reply, and ALWAYS kills the judge session before returning.\n * Fail-safe: no resolver / spawn failure / timeout / unparseable → FAIL.\n * The judge runs while this policy holds its `gating` slot, so it is already\n * accounted for in the WP6 concurrency cap.\n */\n const runJudge = async (\n spec: JudgeGateSpec[\"judge\"],\n ): Promise<{ passed: boolean; exitCode: number; reason?: string }> => {\n if (!resolveAgentAdapter) {\n return { passed: false, exitCode: 1, reason: \"judge gate not enabled (no adapter resolver)\" }\n }\n let resolved\n try {\n resolved = await resolveAgentAdapter(spec.adapter)\n } catch (err) {\n return { passed: false, exitCode: 1, reason: `judge adapter resolve failed: ${err instanceof Error ? err.message : String(err)}` }\n }\n if (!resolved) {\n return { passed: false, exitCode: 1, reason: `judge adapter '${spec.adapter}' not found` }\n }\n\n const cwd = anchorCwd(registry.get(repr)?.cwd ?? workspace)\n const timeoutMs = spec.timeoutMs ?? DEFAULT_JUDGE_TIMEOUT_MS\n\n // Minimal context: the tail of each watched session's output, if readable.\n const contextBlocks = group\n .map(id => {\n const tail = readTail(id, 60)\n return tail ? `--- output of session ${id} ---\\n${tail}` : \"\"\n })\n .filter(Boolean)\n const context = contextBlocks.length > 0\n ? `\\n\\nContext — recent output of the watched session(s):\\n${contextBlocks.join(\"\\n\\n\")}`\n : \"\"\n const fullPrompt = `${spec.prompt}${context}${JUDGE_VERDICT_INSTRUCTION}`\n\n // Spawn the judge agent.\n let judgeId: string\n try {\n const agentSession = await resolved.startSession({\n cwd,\n ...(spec.model ? { model: spec.model } : {}),\n })\n const desc = registry.spawnAgent({\n workspaceSlug: \"default\",\n cwd,\n agentSession,\n adapterSlug: spec.adapter,\n label: `judge:${state.policyId}`,\n ...(resolved.commandPreview ? { commandPreview: resolved.commandPreview } : {}),\n })\n judgeId = desc.id\n } catch (err) {\n return { passed: false, exitCode: 1, reason: `judge spawn failed: ${err instanceof Error ? err.message : String(err)}` }\n }\n\n try {\n // Subscribe to the judge's turn-end BEFORE prompting so we never miss it.\n const ended = new Promise<\"ended\" | \"timeout\">(resolveEnd => {\n const unsubs: Array<() => void> = []\n let done = false\n const finish = (r: \"ended\" | \"timeout\") => {\n if (done) return\n done = true\n clearTimeout(timer)\n for (const u of unsubs) u()\n resolveEnd(r)\n }\n const timer = setTimeout(() => finish(\"timeout\"), timeoutMs)\n const onEnd = (ev: { sessionId: string }) => {\n if (ev.sessionId === judgeId) finish(\"ended\")\n }\n unsubs.push(sessionEvents.on(\"session:turn-end\", onEnd))\n unsubs.push(sessionEvents.on(\"session:awaiting-input\", onEnd))\n unsubs.push(sessionEvents.on(\"session:exited\", onEnd))\n })\n\n try {\n await registry.sendPrompt(judgeId, fullPrompt)\n } catch (err) {\n return { passed: false, exitCode: 1, reason: `judge prompt failed: ${err instanceof Error ? err.message : String(err)}` }\n }\n\n const outcome = await ended\n if (outcome === \"timeout\") {\n return { passed: false, exitCode: 1, reason: `judge timed out after ${timeoutMs}ms` }\n }\n\n const reply = readTail(judgeId, 200)\n const verdict = parseVerdict(reply)\n if (verdict === null) {\n return { passed: false, exitCode: 1, reason: \"judge reply had no parseable VERDICT line\" }\n }\n return verdict === \"PASS\"\n ? { passed: true, exitCode: 0 }\n : { passed: false, exitCode: 1, reason: \"judge verdict: FAIL\" }\n } finally {\n // Always kill the judge session — success or failure.\n try {\n registry.kill(judgeId)\n } catch {\n // best-effort\n }\n }\n }\n\n const runGate = async () => {\n if (entry.cancelled || state.status !== \"watching\") return\n state.status = \"gating\"\n schedulePersist()\n\n if (!input.gate) {\n await act(true, 0)\n return\n }\n\n // WP7: judge-agent gate.\n if (isJudgeGate(input.gate)) {\n const { passed, exitCode, reason } = await runJudge(input.gate.judge)\n state.lastGate = { exitCode, at: new Date().toISOString() }\n if (!passed && reason) state.error = reason\n schedulePersist()\n await act(passed, exitCode)\n return\n }\n\n try {\n const allowlist = await loadAllowlist(workspace)\n const baseName = basename(input.gate.command)\n if (!allowlist.has(baseName)) {\n emitFailed(-1, `gate command '${baseName}' not in allowlist`)\n return\n }\n\n const sessionCwd = registry.get(repr)?.cwd ?? workspace\n const resolvedCwd = anchorCwd(input.gate.cwd ?? sessionCwd)\n\n const result = await exec({\n command: input.gate.command,\n args: input.gate.args ?? [],\n cwd: resolvedCwd,\n timeoutMs: input.gate.timeoutMs ?? 60_000,\n })\n\n state.lastGate = {\n exitCode: result.exitCode,\n at: new Date().toISOString(),\n }\n schedulePersist()\n await act(result.exitCode === 0, result.exitCode)\n } catch (err) {\n emitFailed(-1, err instanceof Error ? err.message : String(err))\n }\n }\n entry.runGate = runGate\n\n /**\n * WP6: gate-entry through the daemon-wide concurrency cap. If a slot is\n * free, run the gate now; otherwise park in `queued` (FIFO) and let\n * pumpQueue() admit this entry when a slot frees. Holds no slot while queued.\n */\n const requestGate = () => {\n if (entry.cancelled || state.status !== \"watching\") return\n if (countActive() >= cap) {\n state.status = \"queued\"\n if (!gateQueue.includes(entry)) gateQueue.push(entry)\n schedulePersist()\n return\n }\n void runGate()\n }\n\n /** Remove a member from the pending set (idempotent); gate once empty. */\n const markMemberDone = (sessionId: string) => {\n if (state.status !== \"watching\") return\n if (!entry.pending.has(sessionId)) return // idempotent — no double-count\n entry.pending.delete(sessionId)\n syncPending()\n schedulePersist()\n if (entry.pending.size === 0) requestGate()\n }\n\n // Fan-in: a member's first turn-end removes it from the pending set; the\n // gate runs once the set empties.\n unsubscribes.push(\n sessionEvents.on(\"session:turn-end\", ev => {\n if (!group.includes(ev.sessionId)) return\n markMemberDone(ev.sessionId)\n }),\n )\n\n // Member exit handling:\n // - group of 1 (legacy single-session form): a lone watched session that\n // exits before turn-end has nothing to gate on → cancel (unchanged).\n // - fan-in group (>1): the exited member is treated as \"done\" and removed\n // from the pending set, exactly like a turn-end. If every member exits,\n // the set empties and the gate runs once.\n unsubscribes.push(\n sessionEvents.on(\"session:exited\", ev => {\n if (!group.includes(ev.sessionId)) return\n if (group.length === 1) {\n if (\n state.status === \"watching\" ||\n state.status === \"gating\" ||\n state.status === \"nudging\"\n ) {\n entry.cancelled = true\n state.status = \"cancelled\"\n state.endedAt = new Date().toISOString()\n schedulePersist()\n cleanup()\n }\n return\n }\n markMemberDone(ev.sessionId)\n }),\n )\n\n // If the pending set was already empty at arm time (e.g. re-armed after a\n // reload where every still-awaited member had exited), gate immediately.\n if (!entry.cancelled && state.status === \"watching\" && entry.pending.size === 0) {\n requestGate()\n }\n }\n\n // ── boot-time reload ─────────────────────────────────────────────\n\n if (persist) {\n let raw: string\n try {\n raw = readFileSync(persistPath, \"utf8\")\n } catch {\n raw = \"\"\n }\n if (raw) {\n let parsed: PolicySnapshot | null = null\n try {\n parsed = JSON.parse(raw) as PolicySnapshot\n } catch {\n // corrupt file — ignore\n }\n if (parsed?.policies) {\n for (const { input, state } of parsed.policies) {\n const isTerminal =\n state.status === \"done\" ||\n state.status === \"blocked\" ||\n state.status === \"cancelled\"\n\n // Reconstruct the fan-in group + pending set defensively (older\n // snapshots predate sessionIds/pending and carry only sessionId).\n const group =\n state.sessionIds && state.sessionIds.length > 0\n ? Array.from(new Set(state.sessionIds))\n : resolveGroup(input)\n const persistedPending =\n state.pending && state.pending.length >= 0\n ? state.pending\n : [...group]\n\n // WP5: a commit parked awaiting human ack stays awaiting-ack across a\n // restart — re-armed neither to watching nor to a terminal state. No\n // bus subscription (it's past gating); ack_policy drives it. The\n // commitPlan persisted with it carries the exact paths/message/cwd.\n if (state.status === \"awaiting-ack\") {\n runs.set(state.policyId, {\n input,\n group,\n pending: new Set(persistedPending),\n state: { ...state, sessionIds: group },\n unsubscribes: [],\n cancelled: false,\n })\n continue\n }\n\n if (isTerminal) {\n // Keep for history, no re-arm needed.\n const entry: RunEntry = {\n input,\n group,\n pending: new Set(persistedPending),\n state,\n unsubscribes: [],\n cancelled: true,\n }\n runs.set(state.policyId, entry)\n continue\n }\n\n // Active state at crash time. A member still counts as alive only if\n // the registry still reports it running/starting.\n const isAlive = (id: string): boolean => {\n const s = registry.get(id)\n return !!s && (s.status === \"running\" || s.status === \"starting\")\n }\n const aliveGroup = group.filter(isAlive)\n\n if (aliveGroup.length === 0) {\n // No member survived the restart — cancel instead of hanging.\n const cancelledState: PolicyRunState = {\n ...state,\n sessionIds: group,\n pending: [],\n status: \"cancelled\",\n endedAt: state.endedAt ?? new Date().toISOString(),\n error: \"session absent at reload\",\n }\n runs.set(state.policyId, {\n input,\n group,\n pending: new Set(),\n state: cancelledState,\n unsubscribes: [],\n cancelled: true,\n })\n continue\n }\n\n // Re-arm to watching. Re-subscribe only to members still awaited AND\n // still alive: a pending member that died while the daemon was down\n // counts as \"done\" (same rule as a live exit), so it drops out of the\n // pending set rather than wedging the fan-in forever.\n const rearmedPending = persistedPending.filter(\n id => group.includes(id) && isAlive(id),\n )\n const rearmedState: PolicyRunState = {\n ...state,\n sessionIds: group,\n pending: rearmedPending,\n status: \"watching\",\n }\n const entry: RunEntry = {\n input,\n group,\n pending: new Set(rearmedPending),\n state: rearmedState,\n unsubscribes: [],\n cancelled: false,\n }\n runs.set(state.policyId, entry)\n armEntry(entry)\n }\n }\n }\n }\n\n // ── attach core (shared by public attach() + WP6 chaining) ───────\n\n /**\n * Validate + register + arm a fresh policy. Used both by the public\n * `attach()` and by `maybeChain()` when a parent policy reaches `done`.\n * Hoisted (function declaration) so maybeChain can reference it.\n */\n function attachPolicy(input: AttachPolicyInput): PolicyRunState {\n const group = resolveGroup(input)\n if (input.gate && isJudgeGate(input.gate)) {\n const j = input.gate.judge\n if (typeof j.adapter !== \"string\" || j.adapter.length === 0) {\n throw new Error(\"judge gate requires a non-empty adapter\")\n }\n if (typeof j.prompt !== \"string\" || j.prompt.length === 0) {\n throw new Error(\"judge gate requires a non-empty prompt\")\n }\n }\n if (input.then === \"commit\") {\n if (!input.commit) {\n throw new Error('then:\"commit\" requires a commit spec')\n }\n if (!Array.isArray(input.commit.paths) || input.commit.paths.length === 0) {\n throw new Error('then:\"commit\" requires a non-empty paths[]')\n }\n if (input.commit.paths.some(p => typeof p !== \"string\" || p.length === 0)) {\n throw new Error(\"commit paths must be non-empty strings\")\n }\n if (typeof input.commit.message !== \"string\" || input.commit.message.length === 0) {\n throw new Error('then:\"commit\" requires a non-empty message')\n }\n }\n const policyId = `policy_${randomUUID().slice(0, 8)}`\n const state: PolicyRunState = {\n policyId,\n sessionId: group[0]!,\n sessionIds: group,\n pending: [...group],\n status: \"watching\",\n retries: 0,\n startedAt: new Date().toISOString(),\n }\n const entry: RunEntry = {\n input,\n group,\n pending: new Set(group),\n state,\n unsubscribes: [],\n cancelled: false,\n }\n runs.set(policyId, entry)\n schedulePersist()\n armEntry(entry)\n return state\n }\n\n // ── public interface ─────────────────────────────────────────────\n\n return {\n attach(input) {\n return attachPolicy(input)\n },\n\n getStatus(policyId) {\n return runs.get(policyId)?.state\n },\n\n cancel(policyId) {\n const entry = runs.get(policyId)\n if (!entry) return\n entry.cancelled = true\n if (\n entry.state.status === \"watching\" ||\n entry.state.status === \"queued\" ||\n entry.state.status === \"gating\" ||\n entry.state.status === \"nudging\"\n ) {\n const wasActive =\n entry.state.status === \"gating\" || entry.state.status === \"queued\"\n entry.state.status = \"cancelled\"\n entry.state.endedAt = new Date().toISOString()\n for (const u of entry.unsubscribes) u()\n entry.unsubscribes.length = 0\n // WP6: drop from the gate queue and release any held slot.\n const qi = gateQueue.indexOf(entry)\n if (qi >= 0) gateQueue.splice(qi, 1)\n schedulePersist()\n if (wasActive) pumpQueue()\n }\n },\n\n async ack(policyId, approve) {\n const entry = runs.get(policyId)\n if (!entry) return undefined\n // Only meaningful while parked awaiting a human ack.\n if (entry.state.status !== \"awaiting-ack\") return entry.state\n\n if (!approve) {\n entry.cancelled = true\n entry.state.status = \"cancelled\"\n entry.state.endedAt = new Date().toISOString()\n schedulePersist()\n return entry.state\n }\n\n await finishCommit(entry)\n return entry.state\n },\n\n list() {\n return Array.from(runs.values()).map(e => e.state)\n },\n\n shutdown() {\n if (shutdownDone) return\n shutdownDone = true\n if (persistTimer) {\n clearTimeout(persistTimer)\n persistTimer = null\n }\n if (!persist) return\n try {\n const snap = buildSnapshot()\n mkdirSync(dirname(persistPath), { recursive: true })\n writeFileSync(persistPath, JSON.stringify(snap, null, 2) + \"\\n\")\n } catch {\n // best-effort\n }\n },\n }\n}\n","/**\n * InboundWatcher — polls agentpush `poll_inbound` on a timer and\n * spawns one agent per contact_ref that has unread inbound messages.\n *\n * Flow per tick:\n * mcp_imported_call(alias, \"poll_inbound\", {source, since:cursor})\n * → group events by contact_ref\n * → spawn one agent per contact with prompt from promptTemplate\n * → advance + persist cursor to ~/.agentproto/agentpush-cursors.json\n *\n * Cursor key = \"${alias}:${source}\" — stable across daemon restarts so\n * cursor resume actually works (a random watcherId would break it).\n *\n * Prompt template variables: {{source}}, {{contact_ref}},\n * {{messages_json}}, {{count}}.\n *\n * The mcpServersForChild array is forwarded to the spawned agent's\n * startSession + spawnAgent so the child can call dispatch_request\n * directly on the mounted agentpush MCP server.\n *\n * State is in-memory; cursors persist to disk (debounced async write\n * + sync flush at shutdown), matching the supervisor.ts pattern.\n */\n\nimport { randomUUID } from \"node:crypto\"\nimport { resolve, dirname } from \"node:path\"\nimport { homedir } from \"node:os\"\nimport { mkdirSync, writeFileSync, readFileSync, promises as fsp } from \"node:fs\"\nimport type { McpProxyRegistry } from \"./mcp-proxy.js\"\nimport type { SessionsRegistry } from \"./sessions.js\"\nimport type { AgentAdapterResolver } from \"./http-server.js\"\n\n// ── Types ─────────────────────────────────────────────────────────────\n\nexport interface WatcherStartInput {\n /** Imported MCP alias (e.g. \"agentpush\"). */\n alias: string\n /** Contact ref / channel to watch — forwarded as `source` to poll_inbound. */\n source: string\n /** Agent adapter slug (e.g. \"claude-code\"). */\n adapter: string\n /**\n * Prompt template with placeholders:\n * {{source}} — the watched source\n * {{contact_ref}} — the sender's contact_ref\n * {{messages_json}} — JSON array of the new events\n * {{count}} — number of new messages\n */\n promptTemplate: string\n /** Poll interval in ms. Default 5 000. */\n pollIntervalMs?: number\n /** Working directory for spawned agents. Default process.cwd(). */\n cwd?: string\n /** Optional label suffix on spawned sessions. */\n label?: string\n /**\n * MCP servers to mount in the child agent at spawn time.\n * Pass agentpush here so the child can call dispatch_request.\n */\n mcpServersForChild?: Array<{\n name: string\n transport: \"stdio\" | \"http\" | \"sse\"\n ref?: string\n }>\n}\n\nexport interface WatcherDescriptor {\n watcherId: string\n alias: string\n source: string\n adapter: string\n pollIntervalMs: number\n status: \"running\" | \"stopped\"\n /** Next `since` value for poll_inbound (exclusive lower bound). */\n cursor: number\n lastPollAt?: string\n lastFireAt?: string\n /** Total agent sessions spawned since the watcher started. */\n spawned: number\n}\n\nexport interface InboundWatcher {\n start(input: WatcherStartInput): WatcherDescriptor\n /** Returns false when watcherId is unknown. */\n stop(watcherId: string): boolean\n list(): WatcherDescriptor[]\n /** Stops all watchers and flushes cursor state to disk synchronously. */\n shutdown(): void\n}\n\n// ── Internal ─────────────────────────────────────────────────────────\n\ninterface InboundEvent {\n timestamp?: number\n contact_ref?: string\n [key: string]: unknown\n}\n\ninterface WatcherState {\n readonly watcherId: string\n readonly input: {\n alias: string\n source: string\n adapter: string\n promptTemplate: string\n pollIntervalMs: number\n cwd: string\n label?: string\n mcpServersForChild?: WatcherStartInput[\"mcpServersForChild\"]\n }\n status: \"running\" | \"stopped\"\n cursor: number\n /** True while a poll tick is still in-flight — prevents overlap. */\n inFlight: boolean\n lastPollAt?: string\n lastFireAt?: string\n spawned: number\n timer: ReturnType<typeof setInterval> | null\n}\n\nexport const CURSORS_FILE_PATH = (): string =>\n resolve(homedir(), \".agentproto\", \"agentpush-cursors.json\")\n\nconst PERSIST_DEBOUNCE_MS = 1_500\n\n// ── Factory ───────────────────────────────────────────────────────────\n\nexport function createInboundWatcher(opts: {\n mcpProxy: McpProxyRegistry\n registry: SessionsRegistry\n resolveAgentAdapter: AgentAdapterResolver\n /** Override persist path (tests). Implies persist:true unless set explicitly. */\n persistPath?: string\n /** Disable disk persistence entirely (unit tests). Default false. */\n persist?: boolean\n}): InboundWatcher {\n const { mcpProxy, registry, resolveAgentAdapter } = opts\n const persistPath = opts.persistPath ?? CURSORS_FILE_PATH()\n const persist = opts.persist ?? opts.persistPath !== undefined\n const watchers = new Map<string, WatcherState>()\n let persistTimer: ReturnType<typeof setTimeout> | null = null\n\n // ── Cursor persistence (mirrors supervisor.ts pattern) ────────────\n\n const loadCursors = (): Record<string, number> => {\n try {\n const raw = readFileSync(persistPath, \"utf8\")\n return JSON.parse(raw) as Record<string, number>\n } catch {\n return {}\n }\n }\n\n // Cursor key uses alias + source — stable identity that survives\n // daemon restarts (unlike watcherId which is a new UUID per start()).\n const buildSnapshot = (): Record<string, number> => {\n const out: Record<string, number> = {}\n for (const state of watchers.values()) {\n out[`${state.input.alias}:${state.input.source}`] = state.cursor\n }\n return out\n }\n\n // Merge current in-memory snapshot with the existing file so cursors\n // for alias:source pairs that are NOT active in this session are never\n // erased on shutdown. Current in-memory values win on conflict.\n const mergedSnapshot = (): Record<string, number> => ({\n ...loadCursors(),\n ...buildSnapshot(),\n })\n\n const schedulePersist = (): void => {\n if (!persist) return\n if (persistTimer) clearTimeout(persistTimer)\n persistTimer = setTimeout(() => {\n void (async () => {\n try {\n const snap = mergedSnapshot()\n await fsp.mkdir(dirname(persistPath), { recursive: true })\n await fsp.writeFile(persistPath, JSON.stringify(snap, null, 2) + \"\\n\")\n } catch (err) {\n console.warn(\n `[inbound-watcher] persist failed: ${err instanceof Error ? err.message : String(err)}`,\n )\n }\n })()\n }, PERSIST_DEBOUNCE_MS)\n }\n\n const flushSync = (): void => {\n if (!persist) return\n try {\n const snap = mergedSnapshot()\n mkdirSync(dirname(persistPath), { recursive: true })\n writeFileSync(persistPath, JSON.stringify(snap, null, 2) + \"\\n\")\n } catch {\n // best-effort — never throw in shutdown path\n }\n }\n\n // ── Helpers ───────────────────────────────────────────────────────\n\n const renderPrompt = (\n template: string,\n vars: {\n source: string\n contact_ref: string\n messages_json: string\n count: number\n },\n ): string =>\n template\n .replaceAll(\"{{source}}\", vars.source)\n .replaceAll(\"{{contact_ref}}\", vars.contact_ref)\n .replaceAll(\"{{messages_json}}\", vars.messages_json)\n .replaceAll(\"{{count}}\", String(vars.count))\n\n // ── Agent spawn ───────────────────────────────────────────────────\n\n const spawnForContact = async (\n state: WatcherState,\n contactRef: string,\n events: InboundEvent[],\n resolved: NonNullable<Awaited<ReturnType<AgentAdapterResolver>>>,\n ): Promise<void> => {\n const prompt = renderPrompt(state.input.promptTemplate, {\n source: state.input.source,\n contact_ref: contactRef,\n messages_json: JSON.stringify(events),\n count: events.length,\n })\n\n const mcpServers = state.input.mcpServersForChild\n\n try {\n const agentSession = await resolved.startSession({\n cwd: state.input.cwd,\n ...(mcpServers ? { mcpServers } : {}),\n })\n\n const labelParts = [\"inbound\", state.watcherId, contactRef]\n if (state.input.label) labelParts.push(state.input.label)\n\n registry.spawnAgent({\n workspaceSlug: \"default\",\n cwd: state.input.cwd,\n agentSession,\n adapterSlug: state.input.adapter,\n initialPrompt: prompt,\n label: labelParts.join(\":\"),\n ...(mcpServers ? { mcpServers } : {}),\n ...(resolved.commandPreview\n ? { commandPreview: resolved.commandPreview }\n : {}),\n })\n\n state.spawned++\n state.lastFireAt = new Date().toISOString()\n } catch (err) {\n console.warn(\n `[inbound-watcher:${state.watcherId}] spawn failed: ${err instanceof Error ? err.message : String(err)}`,\n )\n }\n }\n\n // ── Poll ──────────────────────────────────────────────────────────\n\n const doPoll = async (state: WatcherState): Promise<void> => {\n if (state.status !== \"running\") return\n // Anti-race: skip this tick if the previous one hasn't finished yet.\n if (state.inFlight) return\n state.inFlight = true\n state.lastPollAt = new Date().toISOString()\n\n try {\n const out = await mcpProxy.callTool(state.input.alias, \"poll_inbound\", {\n source: state.input.source,\n ...(state.cursor > 0 ? { since: state.cursor } : {}),\n })\n\n if (!out.ok) {\n console.warn(\n `[inbound-watcher:${state.watcherId}] poll_inbound error: ${out.error}`,\n )\n return\n }\n\n // Unwrap MCP content envelope: { content: [{type:\"text\", text:\"...json...\"}] }\n const raw = out.result as {\n content?: Array<{ type: string; text?: string }>\n }\n const text = raw?.content?.find(c => c.type === \"text\")?.text\n if (!text) return\n\n let data: { events?: InboundEvent[] }\n try {\n data = JSON.parse(text) as { events?: InboundEvent[] }\n } catch {\n return\n }\n\n const events = data.events ?? []\n if (events.length === 0) return\n\n // Compute the new cursor value (max timestamp + 1). Guard against\n // NaN/non-finite values from malformed events.\n // If NO event carries a valid timestamp, fall back to Date.now() so\n // the cursor still advances and the same events are not re-delivered\n // on the next tick (infinite-loop guard).\n const maxTs = events.reduce((m, e) => {\n const ts = typeof e.timestamp === \"number\" ? e.timestamp : -Infinity\n return Number.isFinite(ts) ? Math.max(m, ts) : m\n }, -Infinity)\n const nextCursor = Number.isFinite(maxTs) && maxTs >= state.cursor\n ? maxTs + 1\n : Date.now()\n\n // Resolve adapter once per tick — shared across all contact spawns\n // so N contacts don't fan out N identical adapter-resolution calls.\n const resolved = await resolveAgentAdapter(state.input.adapter).catch(\n () => null,\n )\n if (!resolved) {\n console.warn(\n `[inbound-watcher:${state.watcherId}] adapter \"${state.input.adapter}\" not found — events not consumed`,\n )\n // Do NOT advance cursor: if the adapter is missing the events\n // should be re-delivered on the next tick once it's installed.\n return\n }\n\n // Group by contact_ref, spawn one agent per contact\n const byContact = new Map<string, InboundEvent[]>()\n for (const ev of events) {\n const ref = typeof ev.contact_ref === \"string\" ? ev.contact_ref : \"unknown\"\n const bucket = byContact.get(ref) ?? []\n bucket.push(ev)\n byContact.set(ref, bucket)\n }\n\n await Promise.all(\n Array.from(byContact.entries()).map(([ref, evs]) =>\n spawnForContact(state, ref, evs, resolved),\n ),\n )\n\n // Advance cursor AFTER spawn attempts complete.\n // Delivery contract: at-most-once within a session. If a spawn throws\n // unexpectedly the event is not re-delivered. Across daemon restarts\n // delivery is at-least-once: a tick in-flight at shutdown advances the\n // cursor as a microtask after flushSync() returns, so the new cursor\n // value is not persisted and those events may be re-fetched on restart.\n state.cursor = nextCursor\n schedulePersist()\n } finally {\n state.inFlight = false\n }\n }\n\n // ── Public interface ──────────────────────────────────────────────\n\n return {\n start(input: WatcherStartInput): WatcherDescriptor {\n const watcherId = randomUUID()\n const pollIntervalMs = input.pollIntervalMs ?? 5_000\n const cwd = input.cwd ?? process.cwd()\n\n // Restore persisted cursor using the stable alias:source key so\n // a restarted daemon picks up where it left off.\n const savedCursors = loadCursors()\n\n const state: WatcherState = {\n watcherId,\n input: {\n alias: input.alias,\n source: input.source,\n adapter: input.adapter,\n promptTemplate: input.promptTemplate,\n pollIntervalMs,\n cwd,\n label: input.label,\n mcpServersForChild: input.mcpServersForChild,\n },\n status: \"running\",\n cursor: savedCursors[`${input.alias}:${input.source}`] ?? 0,\n inFlight: false,\n spawned: 0,\n timer: null,\n }\n\n state.timer = setInterval(() => {\n void doPoll(state).catch(err => {\n console.warn(\n `[inbound-watcher:${watcherId}] unhandled poll error: ${err instanceof Error ? err.message : String(err)}`,\n )\n })\n }, pollIntervalMs)\n\n watchers.set(watcherId, state)\n return toDescriptor(state)\n },\n\n stop(watcherId: string): boolean {\n const state = watchers.get(watcherId)\n if (!state) return false\n if (state.timer) clearInterval(state.timer)\n state.timer = null\n state.status = \"stopped\"\n return true\n },\n\n list(): WatcherDescriptor[] {\n return Array.from(watchers.values()).map(toDescriptor)\n },\n\n shutdown(): void {\n for (const state of watchers.values()) {\n if (state.timer) clearInterval(state.timer)\n state.timer = null\n state.status = \"stopped\"\n }\n if (persistTimer) {\n clearTimeout(persistTimer)\n persistTimer = null\n }\n flushSync()\n },\n }\n}\n\nfunction toDescriptor(state: WatcherState): WatcherDescriptor {\n return {\n watcherId: state.watcherId,\n alias: state.input.alias,\n source: state.input.source,\n adapter: state.input.adapter,\n pollIntervalMs: state.input.pollIntervalMs,\n status: state.status,\n cursor: state.cursor,\n lastPollAt: state.lastPollAt,\n lastFireAt: state.lastFireAt,\n spawned: state.spawned,\n }\n}\n","/**\n * Orchestrator sub-gateway (ADR §4.2 / WP2) — the security primitive\n * that lets a spawned agent become a *scoped* orchestrator without\n * handing it the daemon's full toolset.\n *\n * The plain `/mcp` endpoint registers EVERY tool (execute_command,\n * fs_*, remote_*, import_mcp, terminals, driver CRUD) and bypasses auth\n * on loopback — pointing a child at it would be a privilege handout.\n * This module builds a second, scoped MCP server that registers ONLY a\n * curated orchestration allowlist, gated by an unguessable per-child\n * scope-token. The HTTP layer mounts it at `/mcp/orchestrator`\n * (`http-server.ts`); WP3 will auto-mint a token and inject the URL at\n * spawn time. WP2 only builds the primitive.\n *\n * Three pieces:\n * - DEFAULT_ORCHESTRATOR_TOOLS — the curated allowlist.\n * - createScopeTokenRegistry() — mint / verify / revoke scope-tokens.\n * - createOrchestratorMcpServerFactory() — build a scoped server for\n * a verified scope.\n */\n\nimport { randomBytes } from \"node:crypto\"\nimport { createMcpServer } from \"@agentproto/mcp-server\"\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\"\nimport type { AcpMcpServer } from \"@agentproto/acp\"\n\nimport { registerSessionTools } from \"./session-tools.js\"\nimport { registerOrchestrationTools } from \"./orchestration-tools.js\"\nimport { withToolSubset } from \"./tool-subset.js\"\nimport type { SessionsRegistry } from \"./sessions.js\"\nimport type { SessionEventBus } from \"./session-event-bus.js\"\nimport type { EventRing } from \"./event-ring.js\"\nimport type { CompletionPolicySupervisor } from \"./supervisor.js\"\nimport type {\n AgentAdapterResolver,\n AgentAdapterLister,\n} from \"./http-server.js\"\nimport type { WebhookNotifier } from \"./webhook-notifier.js\"\n\n/**\n * The curated set of tools a scoped child orchestrator may call.\n *\n * INCLUDED — the orchestration primitives:\n * start_agent_session, prompt_agent_session, get_agent_session_output,\n * wait_for_any, poll_events (spawn + drive + fan-in)\n * list_sessions, list_agent_sessions, kill_agent_session (observe +\n * halt). NB: list/kill are NOT yet scoped to the child's own\n * subtree — that subtree filter is WP4 (parentSessionId/depth). For\n * WP2 they are exposed daemon-wide; documented debt.\n *\n * EXCLUDED — the danger surface (each a separate trust boundary):\n * execute_command, terminal/PTY tools (raw shell), fs tools\n * (read/write/delete file, create_directory, …), remote_* (publish\n * the daemon to the internet), import_mcp / mcp_imported_* /\n * list_discovered_mcps / remove_imported_mcp (widen the daemon's own\n * MCP surface), and driver CRUD (create_/delete_/update_driver — these\n * never register here because the scoped server is built with no\n * doctype specs).\n */\nexport const DEFAULT_ORCHESTRATOR_TOOLS: readonly string[] = [\n \"start_agent_session\",\n \"prompt_agent_session\",\n \"get_agent_session_output\",\n \"wait_for_any\",\n \"poll_events\",\n \"list_sessions\",\n \"list_agent_sessions\",\n \"session_tree\",\n \"kill_agent_session\",\n // WP6 — supervisor composition: a child orchestrator may attach /\n // inspect / cancel completion policies on sessions within its own\n // subtree. `ack_policy` is intentionally absent: triggering a host\n // commit is an operator-or-human gesture, not a child-orchestrator one.\n \"attach_policy\",\n \"get_policy_status\",\n \"list_policies\",\n \"cancel_policy\",\n]\n\n/**\n * Recursion guardrail defaults (ADR §4.5 / WP4).\n * DEFAULT_MAX_DEPTH — how deep the orchestrator tree may grow by\n * default (root spawns at depth 0; a session\n * spawned by a depth-d orchestrator is d+1, so\n * depth 3 means at most 4 levels: 0,1,2,3).\n * HARD_MAX_DEPTH — an unconditional ceiling the schema bound +\n * mint both clamp to, so no caller can lift the\n * cap past this even with an explicit request.\n * DEFAULT_MAX_CHILDREN — per-orchestrator alive-child quota.\n */\nexport const DEFAULT_MAX_DEPTH = 3\nexport const HARD_MAX_DEPTH = 8\nexport const DEFAULT_MAX_CHILDREN = 8\n\nexport interface OrchestratorScope {\n /** The opaque scope-token handed to (and presented by) the child. */\n token: string\n /** The effective tool allowlist for this scope (⊆ the default and,\n * for a recursively-spawned child, ⊆ its parent's allowlist). */\n tools: ReadonlySet<string>\n /**\n * Session id of the orchestrator that OWNS this token — i.e. the\n * child session that presents it back on `/mcp/orchestrator`. The\n * token is minted *before* the child session exists (the injector\n * needs the URL to compose the spawn), so this is bound late, after\n * `spawnAgent` returns the id, via `bindOwner`. Until bound, spawns\n * through this scope are attributed to no parent and its subtree is\n * empty (safe degradation). (ADR §4.5 / WP4) */\n ownerSessionId?: string\n /** Recursion depth of the owning orchestrator session. A spawn made\n * *through* this scope produces a child at `depth + 1`. Root scopes\n * (minted for a direct `/mcp` spawn) are depth 0. */\n depth: number\n /** Max recursion depth reachable through this scope. A spawn whose\n * child depth (`depth + 1`) would exceed this is rejected. Clamped\n * to `HARD_MAX_DEPTH`. */\n maxDepth: number\n /** Max concurrently-alive children the owning orchestrator may spawn\n * before further spawns are rejected. */\n maxChildren: number\n}\n\n/**\n * Narrow a caller-requested tool list to ⊆ a ceiling subset.\n *\n * The `ceiling` is the maximum a caller may end up with — the global\n * `DEFAULT_ORCHESTRATOR_TOOLS` for a root scope, or the *parent's*\n * effective tools for a recursively-spawned child (non-re-grant: a\n * child can never widen beyond what its parent holds — ADR §4.5 #5).\n * The `{ tools: [...] }` form can only REMOVE from the ceiling, never\n * add: any name outside it is dropped. Omitting `requested` yields the\n * full ceiling. Omitting `ceiling` defaults to the global default.\n */\nexport function narrowOrchestratorTools(\n requested?: readonly string[],\n ceiling?: ReadonlySet<string>,\n): Set<string> {\n const cap = ceiling ?? new Set(DEFAULT_ORCHESTRATOR_TOOLS)\n if (!requested) return new Set(cap)\n return new Set(requested.filter(t => cap.has(t)))\n}\n\nexport interface MintScopeOptions {\n /** Caller-requested allowlist — narrowed ⊆ `ceiling` (or the default\n * when no ceiling is given). */\n tools?: readonly string[]\n /** Upper bound on the minted tools (the parent's effective tools for\n * a recursive child). Omit for a root scope (defaults to the global\n * default subset). */\n ceiling?: ReadonlySet<string>\n /** Depth of the owning orchestrator (default 0). */\n depth?: number\n /** Max depth reachable through this scope (default DEFAULT_MAX_DEPTH,\n * clamped to HARD_MAX_DEPTH). */\n maxDepth?: number\n /** Per-orchestrator alive-child quota (default DEFAULT_MAX_CHILDREN). */\n maxChildren?: number\n}\n\nexport interface ScopeTokenRegistry {\n /** Mint a fresh scope-token. See `MintScopeOptions`. */\n mint(opts?: MintScopeOptions): OrchestratorScope\n /** Resolve a presented token to its scope, or null when unknown. */\n verify(token: string | null | undefined): OrchestratorScope | null\n /** Late-bind the owning child session id onto a minted scope (the\n * token is minted before the child exists). No-op when the token is\n * unknown. Mutates the live scope object so `verify` reflects it. */\n bindOwner(token: string, sessionId: string): void\n /** Drop a token (e.g. when the child session ends). */\n revoke(token: string): void\n}\n\n/**\n * In-memory registry of live scope-tokens. Tokens are random 256-bit\n * hex (unguessable, never persisted) — see ADR §5.3. Single-user-host\n * trust assumption mirrors the loopback auth bypass on `/mcp`.\n */\nexport function createScopeTokenRegistry(): ScopeTokenRegistry {\n const scopes = new Map<string, OrchestratorScope>()\n return {\n mint(opts) {\n const token = randomBytes(32).toString(\"hex\")\n const scope: OrchestratorScope = {\n token,\n tools: narrowOrchestratorTools(opts?.tools, opts?.ceiling),\n depth: opts?.depth ?? 0,\n maxDepth: Math.min(opts?.maxDepth ?? DEFAULT_MAX_DEPTH, HARD_MAX_DEPTH),\n maxChildren: opts?.maxChildren ?? DEFAULT_MAX_CHILDREN,\n }\n scopes.set(token, scope)\n return scope\n },\n verify(token) {\n if (!token) return null\n return scopes.get(token) ?? null\n },\n bindOwner(token, sessionId) {\n const scope = scopes.get(token)\n if (scope) scope.ownerSessionId = sessionId\n },\n revoke(token) {\n scopes.delete(token)\n },\n }\n}\n\nexport interface OrchestratorGatewayDeps {\n workspace: string\n name?: string\n version?: string\n registry: SessionsRegistry\n sessionEvents: SessionEventBus\n eventRing: EventRing\n supervisor?: CompletionPolicySupervisor\n resolveAgentAdapter?: AgentAdapterResolver\n listAgentAdapters?: AgentAdapterLister\n /** Orchestrator injector (WP3/WP4). When wired, a child orchestrator\n * driving the scoped server can itself spawn sub-orchestrators\n * (`orchestrator: true` on its `start_agent_session`) — the new\n * token inherits depth+1 and is bounded by the caller's tools\n * (non-re-grant). Omitted → recursion injection is unavailable on\n * the scoped surface (a child can still spawn plain sub-agents). */\n orchestratorInjector?: OrchestratorInjector\n /** Optional webhook notifier — same singleton as the root /mcp server.\n * When provided, per-session notifyUrl values from start_agent_session\n * are registered on spawn and unregistered on exit, so child\n * orchestrators spawning through this scoped gateway also fire webhooks. */\n webhookNotifier?: WebhookNotifier\n}\n\nexport type OrchestratorMcpServerFactory = (\n scope: OrchestratorScope,\n) => Promise<McpServer>\n\n/**\n * Build a factory that produces a scoped MCP server for a verified\n * scope. The server is created with NO doctype specs and NO workspace\n * (so no CRUD verbs, no `self_inspect`, no driver tools leak in), then\n * the orchestration passes run against a `withToolSubset` wrapper so\n * only `scope.tools` survive. Critically, `mcpProxy` and the PTY\n * factory are never wired here — import + terminal tools stay unwired\n * AND are excluded from the subset (defense in depth).\n */\nexport function createOrchestratorMcpServerFactory(\n deps: OrchestratorGatewayDeps,\n): OrchestratorMcpServerFactory {\n return async (scope: OrchestratorScope): Promise<McpServer> => {\n const { server } = await createMcpServer({\n specs: [],\n name: `${deps.name ?? \"agentproto-runtime\"}-orchestrator`,\n version: deps.version ?? \"0.1.0-alpha\",\n })\n registerSessionTools(server, {\n registry: deps.registry,\n toolSubset: scope.tools,\n // The verified scope IS the calling orchestrator's identity:\n // spawns through this server are attributed to `scope.ownerSessionId`\n // at `scope.depth + 1`, depth/quota guards fire against it, and\n // list/kill are filtered to its subtree (WP4).\n callerScope: scope,\n ...(deps.orchestratorInjector\n ? { buildOrchestratorMcp: deps.orchestratorInjector }\n : {}),\n ...(deps.resolveAgentAdapter\n ? { resolveAgentAdapter: deps.resolveAgentAdapter }\n : {}),\n ...(deps.listAgentAdapters\n ? { listAgentAdapters: deps.listAgentAdapters }\n : {}),\n ...(deps.webhookNotifier\n ? { webhookNotifier: deps.webhookNotifier }\n : {}),\n })\n registerOrchestrationTools(server, {\n registry: deps.registry,\n sessionEvents: deps.sessionEvents,\n eventRing: deps.eventRing,\n toolSubset: scope.tools,\n // WP6: pass the caller's scope so supervisor tools can enforce\n // subtree-scoped access (attach only to own sub-agents; list/cancel\n // only policies on own sub-agents; commit refused).\n callerScope: scope,\n ...(deps.supervisor ? { supervisor: deps.supervisor } : {}),\n })\n return server\n }\n}\n\n/**\n * The auto-injection assembly (ADR §4.4 / WP3) — turns the \"make this\n * child an orchestrator\" intent into the concrete `mcpServers` entry\n * the ACP `session/new` call mounts, plus the token lifecycle.\n *\n * One call (`inject`) does three things:\n * 1. mint a scope-token (narrowed ⊆ default when `tools` is given);\n * 2. build the `mcpServers` entry pointing the child at the daemon's\n * own scoped sub-gateway (`/mcp/orchestrator?scope=<token>`);\n * 3. hand back `bindLifecycle(sessionId)` so the caller can revoke\n * the token the moment that child session exits — no token leaks\n * past the life of the session it was minted for.\n *\n * Assembled in `createGateway` (not the CLI resolver) because it needs\n * the gateway's scope-token registry, the session-event bus, and the\n * HTTP listener's port — all of which live there.\n */\nexport interface OrchestratorInjection {\n /** The `mcpServers` entry to merge into the child's `session/new`. */\n entry: AcpMcpServer\n /** The minted scope — `token` gates the endpoint, `tools` is the\n * effective (narrowed) allowlist. */\n scope: OrchestratorScope\n /**\n * Revoke the scope-token once `sessionId` exits. Subscribes to the\n * session-event bus for that one session's `session:exited` and\n * self-unsubscribes on fire. Returns an unsubscribe in case the\n * caller wants to drop the binding early (rarely needed).\n */\n bindLifecycle(sessionId: string): () => void\n}\n\nexport interface OrchestratorInjectorDeps {\n scopeTokens: ScopeTokenRegistry\n sessionEvents: SessionEventBus\n /** Port the daemon's HTTP listener (and thus `/mcp/orchestrator`)\n * binds. The child reaches it over loopback. */\n port: number\n /** Loopback host for the injected `ref`. Always loopback — the child\n * is co-located on the host. Default `127.0.0.1`. */\n host?: string\n /** `name` advertised on the injected `mcpServers` entry. The child\n * sees its orchestration tools namespaced under this. Default\n * `agentproto`. */\n entryName?: string\n}\n\nexport type OrchestratorInjector = (opts?: {\n tools?: readonly string[]\n /** The calling orchestrator's scope, when this spawn arrives via the\n * scoped sub-gateway (recursive spawn). The minted child token then\n * inherits `depth = caller.depth + 1`, its tools are bounded by the\n * caller's tools (non-re-grant — ADR §4.5 #5), and its depth/child\n * limits never exceed the caller's. Omit for a root spawn (direct\n * `/mcp`) → depth 0, full default subset, default limits. */\n caller?: OrchestratorScope\n /** Override the max depth reachable through the minted scope (clamped\n * to the caller's, then to HARD_MAX_DEPTH). Root-only knob. */\n maxDepth?: number\n /** Override the per-orchestrator child quota for the minted scope\n * (clamped to the caller's). Root-only knob. */\n maxChildren?: number\n}) => OrchestratorInjection\n\n/**\n * Build the orchestrator injector. Closed over the gateway's\n * scope-token registry + session-event bus + HTTP port. Returns a\n * function that the `start_agent_session` handler calls when its\n * `orchestrator` field is set.\n */\nexport function createOrchestratorInjector(\n deps: OrchestratorInjectorDeps,\n): OrchestratorInjector {\n const host = deps.host ?? \"127.0.0.1\"\n const name = deps.entryName ?? \"agentproto\"\n return (opts) => {\n const caller = opts?.caller\n // A recursive child lands one level below its caller; a root spawn\n // (no caller) is depth 0. Limits never escalate past the caller's.\n const depth = caller ? caller.depth + 1 : 0\n const maxDepth = caller\n ? Math.min(opts?.maxDepth ?? caller.maxDepth, caller.maxDepth)\n : (opts?.maxDepth ?? DEFAULT_MAX_DEPTH)\n const maxChildren = caller\n ? Math.min(opts?.maxChildren ?? caller.maxChildren, caller.maxChildren)\n : (opts?.maxChildren ?? DEFAULT_MAX_CHILDREN)\n const scope = deps.scopeTokens.mint({\n ...(opts?.tools ? { tools: opts.tools } : {}),\n // Non-re-grant: bound the child's tools by the caller's effective\n // tools (not just the global default) — a child can never widen\n // beyond what its parent holds.\n ...(caller ? { ceiling: caller.tools } : {}),\n depth,\n maxDepth,\n maxChildren,\n })\n const entry: AcpMcpServer = {\n name,\n transport: \"http\",\n ref: `http://${host}:${deps.port}/mcp/orchestrator?scope=${scope.token}`,\n }\n const bindLifecycle = (sessionId: string): (() => void) => {\n // Late-bind the owner: the token was minted before this child\n // session existed; now that we have its id, attribute the scope to\n // it so its own spawns inherit `parentSessionId = sessionId` and\n // its subtree filters resolve.\n deps.scopeTokens.bindOwner(scope.token, sessionId)\n const off = deps.sessionEvents.on(\"session:exited\", ev => {\n if (ev.sessionId !== sessionId) return\n deps.scopeTokens.revoke(scope.token)\n off()\n })\n return off\n }\n return { entry, scope, bindLifecycle }\n }\n}\n","/**\n * Browser family on top of `@agentproto/adapter-kit` — Phase 3 (lightest\n * adoption: no creds, no wizard, no catalog file).\n *\n * Provides the kit-compatible types (`BrowserAdapterHandle`) and the\n * `makeBrowserAdapterLister` factory that wraps the existing injected\n * `listBrowserAdapters` / `resolveBrowserAdapter` functions in a standard\n * `AdapterLister<BrowserAdapterInfo>`.\n *\n * The resulting lister is passed as the `lister` option to\n * `registerBrowserTools`, which uses it to produce the same\n * `{ id, name, description, defaultPort }[]` JSON the legacy path emits\n * (output shape is unchanged — only the internal flow changes).\n *\n * Kit invariants honoured:\n * - `check()` is NEVER called by the lister (OQ-5).\n * - `BrowserAdapterInfo` carries no cred values (Appendix B).\n * - `requiresSetup = false` → status is always \"ready\" without a ledger.\n */\n\nimport {\n makeAdapterLister,\n type AdapterHandle,\n type AdapterLister,\n} from \"@agentproto/adapter-kit\"\nimport type {\n BrowserAdapterInfo,\n BrowserAdapterLister,\n BrowserAdapterResolver,\n} from \"./browser-tools.js\"\n\n// ── Handle ────────────────────────────────────────────────────────────────────\n\n/**\n * Kit-compatible handle for a single in-process browser adapter.\n * `requiresSetup` is always `false` — browser adapters need no creds or\n * setup wizard, so the kit classifies them as \"ready\" on first resolution.\n */\nexport interface BrowserAdapterHandle extends AdapterHandle {\n readonly requiresSetup: false\n readonly defaultPort: number\n}\n\nfunction makeBrowserHandle(\n entry: { id: string; name: string; description: string; defaultPort: number },\n resolve?: BrowserAdapterResolver,\n): BrowserAdapterHandle {\n return {\n slug: entry.id,\n name: entry.name,\n version: \"built-in\",\n description: entry.description,\n requiresSetup: false,\n defaultPort: entry.defaultPort,\n // check() is available for on-demand health probes but is never called\n // by the lister (kit invariant OQ-5). Returns true when the adapter\n // is present in the injected resolver map, false otherwise.\n check: async () => (resolve ? resolve(entry.id) != null : true),\n }\n}\n\n// ── Noop ledger ───────────────────────────────────────────────────────────────\n\n// Browser adapters have requiresSetup=false, so the ledger result is\n// irrelevant to status classification. A lightweight noop avoids any\n// filesystem side-effects.\nconst noopLedger = {\n exists: async (_slug: string): Promise<boolean> => false,\n write: async (): Promise<void> => {},\n read: async (_slug: string) => null,\n}\n\n// ── Lister factory ────────────────────────────────────────────────────────────\n\n/**\n * Build a kit-compatible `AdapterLister<BrowserAdapterInfo>` from the\n * existing injected browser adapter functions. The returned lister uses an\n * empty catalog and `discoverExtras` to surface the injected adapters, then\n * maps each resolved handle's fields into a `BrowserAdapterInfo` descriptor.\n *\n * The caller should pass the result as the `lister` option to\n * `registerBrowserTools`, which extracts `AdapterEntry.info` to preserve the\n * existing tool response shape.\n */\nexport function makeBrowserAdapterLister(opts: {\n listBrowserAdapters: BrowserAdapterLister\n resolveBrowserAdapter?: BrowserAdapterResolver\n}): AdapterLister<BrowserAdapterInfo> {\n const { listBrowserAdapters, resolveBrowserAdapter } = opts\n\n return makeAdapterLister<BrowserAdapterHandle, BrowserAdapterInfo>({\n // Empty catalog — all adapters are discovered via discoverExtras below.\n catalog: [],\n // Resolver is never called with an empty catalog; noop is safe.\n resolver: async () => null,\n ledger: noopLedger,\n toInfo: (handle): BrowserAdapterInfo => ({\n id: handle.slug,\n name: handle.name,\n description: handle.description,\n defaultPort: handle.defaultPort,\n }),\n // Surface every injected adapter as a discovered extra. The kit will\n // call entryFor() on each, which reads ledger (returns false) and\n // computes status as \"ready\" because requiresSetup=false.\n discoverExtras: async () => {\n const entries = listBrowserAdapters()\n return entries.map(entry => makeBrowserHandle(entry, resolveBrowserAdapter))\n },\n })\n}\n","/**\n * Quick Cloudflare Tunnel provider — zero-credential variant.\n *\n * Spawns `cloudflared tunnel --config <ours>` against an isolated\n * config file we write per-tunnel into the workspace, parses the\n * assigned `*.trycloudflare.com` URL out of cloudflared's stderr.\n * No CF account, no API token, no DNS records. Trade-off: URL is\n * ephemeral (different each run) and there's no Cloudflare Access\n * gating — auth happens at the upstream (gateway bearer token, or\n * whatever the tunneled service does for itself).\n *\n * ## Why we don't use `--url`\n *\n * `cloudflared --url http://...` synthesises an inline ingress block\n * but ALSO merges anything from `~/.cloudflared/config.yml`. If a user\n * has prior named-tunnel config there, hostname-specific rules can\n * shadow the inline rule and every request falls through to the\n * built-in `http_status:404` catch-all (the symptom: cloudflared logs\n * `ingressRule=2 originService=http_status:404` for every request,\n * origin never sees traffic). Writing our own config and passing it\n * via `--config` is hermetic — `~/.cloudflared/config.yml` is ignored\n * entirely, so the URL-forward rule always wins.\n *\n * Use this for: ad-hoc demos, \"let me try this from another machine\n * for 10 minutes\", iterating on the remote-MCP UX before committing\n * to a domain.\n *\n * For: persistent URLs / SSO gating, use the named-CF provider (TBD).\n *\n * ## cloudflared discovery\n *\n * Detected on PATH at start time. Missing → throw with a pointer to\n * the install instructions. We deliberately don't bundle binaries —\n * keeps the OSS package free of platform-specific blobs and defers the\n * \"which version\" maintenance tax.\n */\n\nimport { spawn, type ChildProcess } from \"node:child_process\"\nimport { promisify } from \"node:util\"\nimport { execFile } from \"node:child_process\"\nimport { mkdir, writeFile, rm } from \"node:fs/promises\"\nimport { join } from \"node:path\"\nimport { randomBytes } from \"node:crypto\"\n\nimport type {\n ProviderStartOptions,\n ProviderStartResult,\n RemoteProvider,\n TunnelProviderHandle,\n} from \"./types.js\"\n\nconst execFileAsync = promisify(execFile)\n\nconst URL_REGEX = /https:\\/\\/[a-z0-9-]+\\.trycloudflare\\.com/i\n\nconst STARTUP_TIMEOUT_MS = 30_000\n\n/** Adapter-kit slug for the quick provider (catalog key). */\nexport const CLOUDFLARE_QUICK_SLUG = \"cloudflare-quick\"\n\n/** Quick tunnels need no credentials and offer no stability guarantees. */\nexport const QUICK_CAPABILITIES = {\n stableUrl: false,\n autostart: false,\n customDomain: false,\n requiresAuth: false,\n hasApi: false,\n} as const\n\nexport function quickTunnelProvider(): RemoteProvider & TunnelProviderHandle {\n let child: ChildProcess | null = null\n let configPath: string | null = null\n\n return {\n id: \"quick\",\n // ── adapter-kit handle surface ──────────────────────────────────\n slug: CLOUDFLARE_QUICK_SLUG,\n name: \"Cloudflare Quick Tunnel\",\n // In-process provider — no npm package version to report.\n version: \"builtin\",\n description:\n \"Zero-credential Cloudflare tunnel. Ephemeral *.trycloudflare.com URL, fresh each run.\",\n requiresSetup: false,\n capabilities: { ...QUICK_CAPABILITIES },\n async check(): Promise<boolean> {\n return cloudflaredOnPath()\n },\n async start(opts: ProviderStartOptions): Promise<ProviderStartResult> {\n await assertCloudflaredOnPath()\n const targetUrl = `http://${opts.target.host}:${opts.target.port}`\n\n // Per-tunnel sentinel config — the only reason it exists is to\n // override `~/.cloudflared/config.yml` so its ingress rules can't\n // shadow our inline `--url` rule. We deliberately do NOT include\n // an `ingress:` block here: quick-tunnel mode treats `--url` as\n // the routing source of truth, and a stray top-level `ingress:`\n // would fight it. Random suffix avoids collisions when dev\n // restarts overlap.\n const id = randomBytes(4).toString(\"hex\")\n const dir = join(opts.workspace, \".agentproto\")\n await mkdir(dir, { recursive: true })\n configPath = join(dir, `cloudflared-${id}.yml`)\n const configBody = [\n `# generated by agentproto-runtime — sentinel only`,\n `# overrides ~/.cloudflared/config.yml so its ingress rules`,\n `# don't shadow the inline --url rule. Safe to delete when the`,\n `# tunnel is down.`,\n `no-autoupdate: true`,\n `loglevel: debug`,\n ``,\n ].join(\"\\n\")\n await writeFile(configPath, configBody, \"utf8\")\n const proc = spawn(\n \"cloudflared\",\n [\"tunnel\", \"--config\", configPath, \"--url\", targetUrl],\n { stdio: [\"ignore\", \"pipe\", \"pipe\"], shell: false },\n )\n child = proc\n\n const url = await new Promise<string>((resolve, reject) => {\n let settled = false\n const timer = setTimeout(() => {\n if (settled) return\n settled = true\n try {\n proc.kill(\"SIGTERM\")\n } catch {\n /* noop */\n }\n reject(\n new Error(\n `cloudflared did not emit a public URL within ${STARTUP_TIMEOUT_MS / 1000}s`,\n ),\n )\n }, STARTUP_TIMEOUT_MS)\n\n const onData = (chunk: Buffer) => {\n const text = chunk.toString(\"utf8\")\n for (const line of text.split(/\\r?\\n/)) {\n if (line.length > 0) opts.onLog?.(`[cloudflared] ${line}`)\n }\n if (settled) return\n const match = text.match(URL_REGEX)\n if (match) {\n settled = true\n clearTimeout(timer)\n resolve(match[0])\n }\n }\n // cloudflared writes the URL to stderr (it reserves stdout for\n // proxied traffic / structured output in some modes). Watch\n // both for safety.\n proc.stderr?.on(\"data\", onData)\n proc.stdout?.on(\"data\", onData)\n\n proc.once(\"error\", err => {\n if (settled) return\n settled = true\n clearTimeout(timer)\n reject(err)\n })\n proc.once(\"exit\", (code, signal) => {\n if (settled) return\n settled = true\n clearTimeout(timer)\n reject(\n new Error(\n `cloudflared exited before emitting a URL (code=${code}, signal=${signal})`,\n ),\n )\n })\n })\n\n // Detach the resolver listener (we already captured the URL); leave\n // the log-forwarder attached so the gateway's RuntimeEvents stream\n // sees ongoing tunnel chatter.\n proc.once(\"exit\", (code, signal) => {\n opts.onLog?.(\n `[cloudflared] exited (code=${code ?? \"?\"} signal=${signal ?? \"-\"})`,\n )\n })\n\n return { publicUrl: url, pid: proc.pid ?? null }\n },\n\n async stop(): Promise<void> {\n const proc = child\n const cfg = configPath\n child = null\n configPath = null\n // Best-effort cleanup of the sentinel config — losing it means a\n // stale `.agentproto/cloudflared-<id>.yml` file, no functional\n // impact. We do this even if the proc never started.\n if (cfg) {\n try {\n await rm(cfg, { force: true })\n } catch {\n /* noop */\n }\n }\n if (!proc || proc.exitCode !== null) return\n proc.kill(\"SIGTERM\")\n // Hard-kill backstop after 3s if cloudflared ignores SIGTERM.\n const timer = setTimeout(() => {\n try {\n proc.kill(\"SIGKILL\")\n } catch {\n /* noop */\n }\n }, 3_000)\n timer.unref()\n await new Promise<void>(resolve => {\n if (proc.exitCode !== null) {\n clearTimeout(timer)\n resolve()\n return\n }\n proc.once(\"exit\", () => {\n clearTimeout(timer)\n resolve()\n })\n })\n },\n }\n}\n\n/**\n * Non-throwing variant for the adapter-kit `check()` health probe — true\n * when `cloudflared` is reachable on PATH. NOT called during listing (the\n * kit derives status from resolvability + creds, per OQ-5); reserved for\n * on-demand health checks.\n */\nasync function cloudflaredOnPath(): Promise<boolean> {\n try {\n await execFileAsync(\"cloudflared\", [\"--version\"], { timeout: 3_000 })\n return true\n } catch {\n return false\n }\n}\n\nasync function assertCloudflaredOnPath(): Promise<void> {\n try {\n await execFileAsync(\"cloudflared\", [\"--version\"], { timeout: 3_000 })\n } catch {\n throw new Error(\n \"cloudflared not found on PATH. Install it first:\\n\" +\n \" macOS: brew install cloudflared\\n\" +\n \" Linux: https://pkg.cloudflare.com/index.html\\n\" +\n \" Windows: winget install --id Cloudflare.cloudflared\\n\" +\n \"Or download a prebuilt binary from https://github.com/cloudflare/cloudflared/releases.\",\n )\n }\n}\n","/**\n * RemoteController — owns the gateway's \"publish to the internet\" state.\n *\n * One singleton per gateway. Holds:\n * - the current tunnel provider's child process (cloudflared, …)\n * - the bearer token gating /mcp once the tunnel is up\n * - persisted state in `<workspace>/.agentproto/remote.json`\n *\n * The controller is the *only* component that mutates auth at runtime.\n * The HTTP server reads auth via a getter (see `AuthSource` in\n * http-server.ts), so flipping `enable() / disable()` here takes effect\n * on the next request — no restart, no race.\n *\n * ## Provider model\n *\n * Each provider implements `RemoteProvider` (start / stop / status).\n * v1 ships only `quick` (Cloudflare Quick Tunnel — no API key, no DNS,\n * ephemeral `*.trycloudflare.com` URL). Named CF Tunnel and Tailscale\n * land as additional implementations.\n *\n * ## Token model\n *\n * On enable we generate a 32-byte random bearer token, return it once\n * to the caller, and persist only its sha256 hash to disk. Same model\n * as a Stripe API key — losing the plaintext means rotating, not\n * recovering. This keeps `.agentproto/remote.json` safe to commit by\n * accident (it leaks the URL, not the credential).\n *\n * ## Security note\n *\n * The CF API token (when used by named-tunnel provider) is *never*\n * accepted as MCP tool input. The controller reads it from\n * `~/.config/agentproto/cloudflare.json` or `$CLOUDFLARE_API_TOKEN`.\n * Otherwise a remote agent could exfiltrate it through `remote_enable`.\n */\n\nimport { randomBytes, createHash } from \"node:crypto\"\nimport { mkdir, writeFile, readFile, chmod, rm } from \"node:fs/promises\"\nimport { existsSync } from \"node:fs\"\nimport { join } from \"node:path\"\n\nimport type { AuthOptions } from \"./http-server.js\"\nimport { quickTunnelProvider } from \"./remote-providers/quick.js\"\nimport type {\n ProviderStartOptions,\n ProviderStartResult,\n RemoteProvider,\n} from \"./remote-providers/types.js\"\n\nexport type { ProviderStartOptions, ProviderStartResult, RemoteProvider }\n\nexport interface RemoteState {\n provider: \"quick\"\n publicUrl: string\n bearerTokenHash: string\n createdAt: string\n /** PID of the supervised tunnel child process, if any. */\n pid: number | null\n /** Local target the tunnel forwards to (host + port). */\n target: { host: string; port: number }\n /**\n * Whether the tunnel exposes the gateway itself (true) or some other\n * local service (false). Bearer auth + loopback bypass only matter\n * for the gateway path; arbitrary-target tunnels are pure passthrough\n * and the daemon does not gate them.\n */\n exposesGateway: boolean\n}\n\nexport interface EnableInput {\n provider?: \"quick\"\n /**\n * Local port to expose. Defaults to the gateway's own port — i.e.\n * \"publish this MCP server.\" Pass any other port to expose a\n * different local service (Supabase 54371, a Vite dev server, …)\n * without spinning up a separate tunnel manager.\n */\n targetPort?: number\n /**\n * Host the tunnel forwards to. Defaults to `127.0.0.1`. Setting it\n * to `localhost` resolves through DNS (IPv6 first on most systems);\n * keep `127.0.0.1` unless the target is explicitly IPv6-bound.\n */\n targetHost?: string\n}\n\nexport interface EnableResult {\n publicUrl: string\n /**\n * Bearer token issued by this gateway. Only meaningful when the\n * tunnel exposes the gateway itself (default). For arbitrary-target\n * tunnels (`targetPort != gateway.port`) the daemon does not gate\n * the proxied service, and this is omitted.\n */\n bearerToken?: string\n /**\n * `<publicUrl>/mcp`. Only emitted when exposing the gateway.\n */\n mcpEndpoint?: string\n /**\n * Paste-ready `.mcp.json` snippet. Only emitted when exposing the\n * gateway.\n */\n mcpConfigSnippet?: string\n provider: \"quick\"\n target: { host: string; port: number }\n exposesGateway: boolean\n}\n\nexport interface RemoteStatus {\n enabled: boolean\n provider?: \"quick\"\n publicUrl?: string\n pid?: number | null\n createdAt?: string\n target?: { host: string; port: number }\n exposesGateway?: boolean\n /** Last error from the provider, if any (since last enable). */\n lastError?: string\n}\n\nexport interface RemoteControllerOptions {\n workspace: string\n port: number\n /** Hook for surfacing provider logs through RuntimeEvents. */\n onLog?: (line: string) => void\n}\n\nconst STATE_FILE_REL = \".agentproto/remote.json\"\n\nexport class RemoteController {\n private state: RemoteState | null = null\n private bearerToken: string | null = null\n private provider: RemoteProvider | null = null\n private lastError: string | undefined\n private readonly opts: RemoteControllerOptions\n\n constructor(opts: RemoteControllerOptions) {\n this.opts = opts\n }\n\n /**\n * Auth getter handed to startHttpServer. The HTTP server calls this\n * on every request so flipping enable/disable is effective without\n * a restart.\n */\n readonly readAuth = (): AuthOptions => {\n if (this.bearerToken === null) return { mode: \"none\" }\n return { mode: \"bearer\", token: this.bearerToken }\n }\n\n status(): RemoteStatus {\n if (!this.state) {\n return { enabled: false, lastError: this.lastError }\n }\n return {\n enabled: true,\n provider: this.state.provider,\n publicUrl: this.state.publicUrl,\n pid: this.state.pid,\n createdAt: this.state.createdAt,\n target: this.state.target,\n exposesGateway: this.state.exposesGateway,\n lastError: this.lastError,\n }\n }\n\n async enable(input: EnableInput): Promise<EnableResult> {\n if (this.state) {\n // Idempotent: returning the existing config would leak the\n // bearer token (we only have the hash). Force teardown first so\n // re-enable always rotates the token. Surface this in the docs.\n throw new Error(\n \"remote tunnel already active — call remote_disable first to rotate\",\n )\n }\n const providerId = input.provider ?? \"quick\"\n const provider = pickProvider(providerId)\n this.lastError = undefined\n\n const target = {\n host: input.targetHost ?? \"127.0.0.1\",\n port: input.targetPort ?? this.opts.port,\n }\n const exposesGateway =\n target.host === \"127.0.0.1\" && target.port === this.opts.port\n\n let started: ProviderStartResult\n try {\n started = await provider.start({\n target,\n workspace: this.opts.workspace,\n onLog: line => {\n this.opts.onLog?.(line)\n },\n })\n } catch (err) {\n this.lastError = errToMessage(err)\n throw err\n }\n\n // Bearer auth + token issuance only matter when the tunnel exposes\n // *this* gateway. For arbitrary-target tunnels (e.g. Supabase on\n // 54371) the daemon is just provisioning a public passthrough; the\n // proxied service does its own authn.\n let bearerToken: string | null = null\n let bearerTokenHash = \"\"\n if (exposesGateway) {\n bearerToken = randomBytes(32).toString(\"base64url\")\n bearerTokenHash = sha256(bearerToken)\n }\n\n const state: RemoteState = {\n provider: providerId,\n publicUrl: started.publicUrl,\n bearerTokenHash,\n createdAt: new Date().toISOString(),\n pid: started.pid,\n target,\n exposesGateway,\n }\n\n this.state = state\n this.bearerToken = bearerToken\n this.provider = provider\n\n await persistState(this.opts.workspace, state)\n\n const result: EnableResult = {\n provider: providerId,\n publicUrl: started.publicUrl,\n target,\n exposesGateway,\n }\n if (exposesGateway && bearerToken) {\n const mcpEndpoint = `${started.publicUrl}/mcp`\n result.bearerToken = bearerToken\n result.mcpEndpoint = mcpEndpoint\n result.mcpConfigSnippet = buildMcpConfigSnippet(mcpEndpoint, bearerToken)\n }\n return result\n }\n\n async disable(): Promise<{ disabled: boolean }> {\n if (!this.state) return { disabled: false }\n const provider = this.provider\n this.state = null\n this.bearerToken = null\n this.provider = null\n if (provider) {\n try {\n await provider.stop()\n } catch (err) {\n this.lastError = errToMessage(err)\n }\n }\n await clearState(this.opts.workspace)\n return { disabled: true }\n }\n\n /**\n * Stop the provider on gateway shutdown. Does NOT clear persisted\n * state — that survives across restarts so the user can `remote_status`\n * after rebooting and see \"stale state, run remote_enable to refresh\".\n * (Stale-recovery semantics land in v2; today we just leave the file.)\n */\n async shutdown(): Promise<void> {\n if (this.provider) {\n try {\n await this.provider.stop()\n } catch {\n /* swallow — gateway is shutting down anyway */\n }\n }\n }\n}\n\n// ── helpers ────────────────────────────────────────────────────────────\n\nfunction pickProvider(id: \"quick\"): RemoteProvider {\n if (id === \"quick\") return quickTunnelProvider()\n // Exhaustive guard — adding \"named-cf\" / \"tailscale\" later forces this\n // switch to be updated, otherwise TS will yell.\n const _exhaustive: never = id\n throw new Error(`unknown remote provider: ${String(_exhaustive)}`)\n}\n\nfunction sha256(input: string): string {\n return createHash(\"sha256\").update(input).digest(\"hex\")\n}\n\nfunction errToMessage(err: unknown): string {\n return err instanceof Error ? err.message : String(err)\n}\n\nasync function persistState(workspace: string, state: RemoteState): Promise<void> {\n const dir = join(workspace, \".agentproto\")\n await mkdir(dir, { recursive: true })\n const file = join(dir, \"remote.json\")\n await writeFile(file, JSON.stringify(state, null, 2) + \"\\n\", \"utf8\")\n // mode 0600 — even though we only persist the hash, the URL itself\n // is sensitive (knowing it lets an attacker brute-force the token).\n try {\n await chmod(file, 0o600)\n } catch {\n /* best-effort on platforms where chmod is a noop */\n }\n}\n\nasync function clearState(workspace: string): Promise<void> {\n const file = join(workspace, \".agentproto/remote.json\")\n if (!existsSync(file)) return\n await rm(file, { force: true })\n}\n\n/**\n * Best-effort load of persisted state on boot. We don't restore the\n * bearer token from this — the hash is one-way — so a rebooted gateway\n * that finds a stale `remote.json` will surface it via `remote_status`\n * and require a fresh `remote_enable` to mint a new token.\n *\n * Exposed mostly for diagnostics; not used by the controller today.\n */\nexport async function loadPersistedState(\n workspace: string,\n): Promise<RemoteState | null> {\n const file = join(workspace, STATE_FILE_REL)\n if (!existsSync(file)) return null\n try {\n const raw = await readFile(file, \"utf8\")\n return JSON.parse(raw) as RemoteState\n } catch {\n return null\n }\n}\n\nfunction buildMcpConfigSnippet(endpoint: string, token: string): string {\n return JSON.stringify(\n {\n mcpServers: {\n \"agentproto-remote\": {\n transport: \"http\",\n url: endpoint,\n headers: { Authorization: `Bearer ${token}` },\n },\n },\n },\n null,\n 2,\n )\n}\n","/**\n * MCP tools that drive RemoteController — the gateway's \"publish to\n * the internet\" surface.\n *\n * Three tools, mirroring the controller's lifecycle:\n *\n * remote_enable — bring up a tunnel, mint bearer token, return the\n * public /mcp URL + a paste-ready .mcp.json snippet\n * remote_disable — tear down tunnel, revoke token, drop bearer auth\n * remote_status — read-only — provider, URL, pid, lastError\n *\n * Why this lives on the MCP surface (not a separate CLI):\n * - The user already has an MCP client connected (that's how they\n * started talking to the gateway in the first place). One tool call\n * replaces an entire CLI install + auth dance.\n * - The bearer token comes back as part of the MCP response, so it\n * doesn't have to land on the user's clipboard.\n */\n\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\"\nimport { z } from \"zod\"\n\nimport type { RemoteController } from \"./remote-controller.js\"\n\nexport interface RegisterRemoteToolsOptions {\n controller: RemoteController\n}\n\nfunction text(value: string | object): {\n content: Array<{ type: \"text\"; text: string }>\n} {\n return {\n content: [\n {\n type: \"text\",\n text: typeof value === \"string\" ? value : JSON.stringify(value, null, 2),\n },\n ],\n }\n}\n\nexport function registerRemoteTools(\n server: McpServer,\n opts: RegisterRemoteToolsOptions,\n): void {\n const { controller } = opts\n\n server.tool(\n \"remote_enable\",\n \"Publish a local port to the internet via Cloudflare. By default exposes \" +\n \"this gateway and gates it with a bearer token (returned ONCE in the \" +\n \"response — store it; only its hash is persisted). Pass `targetPort` to \" +\n \"tunnel a different local service (Supabase, dev server, …); in that mode \" +\n \"the daemon does not gate the proxied traffic — the upstream service \" +\n \"handles its own auth. Returns the public URL plus a paste-ready \" +\n \"`.mcp.json` snippet (gateway mode only). Re-running while a tunnel is \" +\n \"already up errors; call `remote_disable` first to rotate.\",\n {\n provider: z\n .enum([\"quick\"])\n .optional()\n .describe(\n \"Tunnel backend. `quick` = Cloudflare Quick Tunnel (no API key, ephemeral *.trycloudflare.com URL). Defaults to `quick`. Named-CF / Tailscale providers TBD.\",\n ),\n targetPort: z\n .number()\n .int()\n .min(1)\n .max(65535)\n .optional()\n .describe(\n \"Local port to expose. Defaults to this gateway's own port (= publish the MCP server). Pass another port to tunnel a different local service (e.g. 54371 for Supabase) — in that mode bearer auth is OFF since the upstream handles its own gating.\",\n ),\n targetHost: z\n .string()\n .optional()\n .describe(\n \"Host the tunnel forwards to. Defaults to `127.0.0.1`. Use `localhost` only if the target is explicitly IPv6-bound; cloudflared resolves DNS and IPv6-first lookups can break IPv4-only origins.\",\n ),\n },\n async ({ provider, targetPort, targetHost }) => {\n const result = await controller.enable({ provider, targetPort, targetHost })\n return text(result)\n },\n )\n\n server.tool(\n \"remote_disable\",\n \"Tear down the active remote tunnel and drop bearer auth back to \" +\n \"loopback-only. Idempotent — calling when no tunnel is active is a no-op.\",\n {},\n async () => {\n const result = await controller.disable()\n return text(result)\n },\n )\n\n server.tool(\n \"remote_status\",\n \"Report whether a remote tunnel is active. When active: provider, \" +\n \"public URL, supervised PID, createdAt. The bearer token itself is \" +\n \"never returned by status — it was shown once at enable.\",\n {},\n async () => {\n return text(controller.status())\n },\n )\n}\n","/**\n * Named Cloudflare Tunnel provider — persistent-URL variant.\n *\n * Unlike the quick provider (ephemeral `*.trycloudflare.com`, fresh each\n * run), this runs a *named* cloudflared tunnel bound to a stable hostname\n * you control (e.g. `guilde-local.example.com`). The URL never changes —\n * which is what makes a tunnel survivable across restarts and safe to bake\n * into a client config (MCP server URL, webhook, …).\n *\n * ## BYO (bring-your-own) model\n *\n * This provider does NOT create the tunnel or its DNS record — it *runs* a\n * tunnel you've already provisioned once via the cloudflared CLI:\n *\n * cloudflared tunnel create <name> # → tunnel id + creds json\n * cloudflared tunnel route dns <id> <host> # → CNAME host → tunnel\n *\n * After that one-time setup, agentproto owns the lifecycle: it writes a\n * hermetic `--config` (tunnel id + credentials-file + a single ingress\n * rule `hostname → http://localhost:<port>`) and spawns\n * `cloudflared tunnel --config <ours> run <id>`. Because we pass our own\n * config, `~/.cloudflared/config.yml` is ignored entirely (same hermetic\n * reasoning as the quick provider) so the ingress rule always wins.\n *\n * Managed mode (provider auto-runs `create` + `route dns` via a CF API\n * token) is a future addition; BYO covers the common case without storing\n * an account-wide token.\n *\n * ## Why publicUrl is deterministic\n *\n * The hostname is known up front, so — unlike quick — we don't parse a URL\n * out of cloudflared's stderr. We instead wait for the connection-ready\n * marker (`Registered tunnel connection`) before reporting `active`, so a\n * tunnel that can't reach the edge surfaces as a start failure rather than\n * a dead \"active\" entry.\n *\n * ## credentials-file discovery\n *\n * If `credentialsFile` is omitted we default to\n * `~/.cloudflared/<tunnelId>.json` — exactly where `cloudflared tunnel\n * create` writes it. Pass an explicit path only if you relocated it.\n */\n\nimport { spawn, type ChildProcess } from \"node:child_process\"\nimport { promisify } from \"node:util\"\nimport { execFile } from \"node:child_process\"\nimport { mkdir, writeFile, rm, access } from \"node:fs/promises\"\nimport { join } from \"node:path\"\nimport { homedir } from \"node:os\"\nimport { randomBytes } from \"node:crypto\"\n\nimport type {\n ProviderStartOptions,\n ProviderStartResult,\n RemoteProvider,\n TunnelProviderHandle,\n} from \"./types.js\"\n\nconst execFileAsync = promisify(execFile)\n\n/** Cloudflared logs this once each edge connection is registered. */\nconst READY_REGEX = /Registered tunnel connection/i\n\nconst STARTUP_TIMEOUT_MS = 30_000\n\n/** Adapter-kit slug for the named provider (catalog key). */\nexport const CLOUDFLARE_NAMED_SLUG = \"cloudflare-named\"\n\n/** Named tunnels are stable, autostart-able, and require BYO credentials. */\nexport const NAMED_CAPABILITIES = {\n stableUrl: true,\n autostart: true,\n customDomain: true,\n requiresAuth: true,\n hasApi: false,\n} as const\n\n/** Creds fields the named provider accepts via `setup_tunnel_provider`. */\nexport const NAMED_SETUP_FIELDS = [\n {\n name: \"hostname\",\n description: \"Cloudflare tunnel hostname (e.g. agent.example.com)\",\n required: true,\n sensitive: true,\n },\n {\n name: \"tunnelId\",\n description:\n \"Cloudflare tunnel UUID (e.g. 11111111-2222-3333-4444-555555555555)\",\n required: true,\n sensitive: true,\n },\n {\n name: \"credentialsFile\",\n description: \"Optional path to cloudflared credentials JSON file\",\n required: false,\n sensitive: true,\n },\n] as const\n\nexport interface NamedTunnelConfig {\n /** Stable public hostname routed to this tunnel (e.g. app.example.com). */\n hostname: string\n /** Cloudflare tunnel id or name (the `run` target). */\n tunnelId: string\n /**\n * Path to the tunnel credentials JSON. Defaults to\n * `~/.cloudflared/<tunnelId>.json`.\n */\n credentialsFile?: string\n}\n\nexport function namedTunnelProvider(\n cfg: NamedTunnelConfig,\n): RemoteProvider & TunnelProviderHandle {\n let child: ChildProcess | null = null\n let configPath: string | null = null\n\n const credentialsFile =\n cfg.credentialsFile ??\n join(homedir(), \".cloudflared\", `${cfg.tunnelId}.json`)\n\n return {\n id: \"named\",\n // ── adapter-kit handle surface ──────────────────────────────────\n slug: CLOUDFLARE_NAMED_SLUG,\n name: \"Cloudflare Named Tunnel\",\n // In-process provider — no npm package version to report.\n version: \"builtin\",\n description:\n \"Persistent Cloudflare tunnel bound to a stable hostname you control (BYO credentials).\",\n requiresSetup: true,\n capabilities: { ...NAMED_CAPABILITIES },\n setupFields: NAMED_SETUP_FIELDS,\n async check(): Promise<boolean> {\n // Reachable = cloudflared on PATH AND the tunnel credentials file\n // exists. NOT called during listing (kit derives status from creds\n // existence); reserved for on-demand health probes.\n const [bin, creds] = await Promise.all([\n cloudflaredOnPath(),\n fileExists(credentialsFile),\n ])\n return bin && creds\n },\n async start(opts: ProviderStartOptions): Promise<ProviderStartResult> {\n await assertCloudflaredOnPath()\n await assertCredentialsExist(credentialsFile)\n\n const targetUrl = `http://${opts.target.host}:${opts.target.port}`\n\n // Hermetic per-run config. A named tunnel needs a real `ingress:`\n // block (the quick provider deliberately omits it because `--url`\n // is its routing source of truth; here `run <id>` has no `--url`,\n // so ingress IS the routing). Random suffix avoids collisions when\n // restarts overlap.\n const id = randomBytes(4).toString(\"hex\")\n const dir = join(opts.workspace, \".agentproto\")\n await mkdir(dir, { recursive: true })\n configPath = join(dir, `cloudflared-named-${id}.yml`)\n const configBody = [\n `# generated by agentproto-runtime — named tunnel run config`,\n `# hermetic: overrides ~/.cloudflared/config.yml. Safe to delete`,\n `# when the tunnel is down.`,\n `tunnel: ${cfg.tunnelId}`,\n `credentials-file: ${credentialsFile}`,\n `no-autoupdate: true`,\n ``,\n `ingress:`,\n ` - hostname: ${cfg.hostname}`,\n ` service: ${targetUrl}`,\n ` - service: http_status:404`,\n ``,\n ].join(\"\\n\")\n await writeFile(configPath, configBody, \"utf8\")\n\n const proc = spawn(\n \"cloudflared\",\n [\"tunnel\", \"--config\", configPath, \"run\", cfg.tunnelId],\n { stdio: [\"ignore\", \"pipe\", \"pipe\"], shell: false },\n )\n child = proc\n\n await new Promise<void>((resolve, reject) => {\n let settled = false\n const timer = setTimeout(() => {\n if (settled) return\n settled = true\n try {\n proc.kill(\"SIGTERM\")\n } catch {\n /* noop */\n }\n reject(\n new Error(\n `cloudflared did not register a tunnel connection within ${STARTUP_TIMEOUT_MS / 1000}s`,\n ),\n )\n }, STARTUP_TIMEOUT_MS)\n\n const onData = (chunk: Buffer) => {\n const text = chunk.toString(\"utf8\")\n for (const line of text.split(/\\r?\\n/)) {\n if (line.length > 0) opts.onLog?.(`[cloudflared] ${line}`)\n }\n if (settled) return\n if (READY_REGEX.test(text)) {\n settled = true\n clearTimeout(timer)\n resolve()\n }\n }\n proc.stderr?.on(\"data\", onData)\n proc.stdout?.on(\"data\", onData)\n\n proc.once(\"error\", err => {\n if (settled) return\n settled = true\n clearTimeout(timer)\n reject(err)\n })\n proc.once(\"exit\", (code, signal) => {\n if (settled) return\n settled = true\n clearTimeout(timer)\n reject(\n new Error(\n `cloudflared exited before connecting (code=${code}, signal=${signal})`,\n ),\n )\n })\n })\n\n proc.once(\"exit\", (code, signal) => {\n opts.onLog?.(\n `[cloudflared] exited (code=${code ?? \"?\"} signal=${signal ?? \"-\"})`,\n )\n })\n\n return { publicUrl: `https://${cfg.hostname}`, pid: proc.pid ?? null }\n },\n\n async stop(): Promise<void> {\n const proc = child\n const cfg2 = configPath\n child = null\n configPath = null\n if (cfg2) {\n try {\n await rm(cfg2, { force: true })\n } catch {\n /* noop */\n }\n }\n if (!proc || proc.exitCode !== null) return\n proc.kill(\"SIGTERM\")\n const timer = setTimeout(() => {\n try {\n proc.kill(\"SIGKILL\")\n } catch {\n /* noop */\n }\n }, 3_000)\n timer.unref()\n await new Promise<void>(resolve => {\n if (proc.exitCode !== null) {\n clearTimeout(timer)\n resolve()\n return\n }\n proc.once(\"exit\", () => {\n clearTimeout(timer)\n resolve()\n })\n })\n },\n }\n}\n\n/** Non-throwing PATH probe for the adapter-kit `check()` health surface. */\nasync function cloudflaredOnPath(): Promise<boolean> {\n try {\n await execFileAsync(\"cloudflared\", [\"--version\"], { timeout: 3_000 })\n return true\n } catch {\n return false\n }\n}\n\n/** Non-throwing existence check (no value read — purely a boolean probe). */\nasync function fileExists(path: string): Promise<boolean> {\n try {\n await access(path)\n return true\n } catch {\n return false\n }\n}\n\nasync function assertCloudflaredOnPath(): Promise<void> {\n try {\n await execFileAsync(\"cloudflared\", [\"--version\"], { timeout: 3_000 })\n } catch {\n throw new Error(\n \"cloudflared not found on PATH. Install it first:\\n\" +\n \" macOS: brew install cloudflared\\n\" +\n \" Linux: https://pkg.cloudflare.com/index.html\\n\" +\n \" Windows: winget install --id Cloudflare.cloudflared\\n\" +\n \"Or download a prebuilt binary from https://github.com/cloudflare/cloudflared/releases.\",\n )\n }\n}\n\nasync function assertCredentialsExist(path: string): Promise<void> {\n try {\n await access(path)\n } catch {\n throw new Error(\n `named tunnel credentials not found at ${path}.\\n` +\n \"Provision the tunnel once, then retry:\\n\" +\n \" cloudflared tunnel create <name>\\n\" +\n \" cloudflared tunnel route dns <id-or-name> <hostname>\\n\" +\n \"Or pass an explicit credentialsFile if you relocated the JSON.\",\n )\n }\n}\n","/**\n * Ngrok tunnel provider — static-domain variant.\n *\n * Spawns `ngrok http <port>` (with optional `--domain=<domain>` when a\n * reserved domain is configured), authenticates via the stored authtoken,\n * and extracts the public URL from the local ngrok agent API\n * (`http://127.0.0.1:4040/api/tunnels`) with a fallback to parsing stdout\n * JSON lines.\n *\n * ## Creds model\n *\n * Ngrok needs an authtoken (free tier ok). An optional reserved domain\n * (`--domain`) enables stable URLs (paid plan). Both are stored via the\n * adapter-kit creds store under the tunnel family.\n *\n * ## local agent API (port 4040)\n *\n * Ngrok exposes `http://127.0.0.1:4040/api/tunnels` while running — the\n * canonical source of the public URL. We poll this after spawn (with a\n * short grace period) before falling back to stdout JSON-line parsing.\n *\n * ## Why we don't use `@ngrok/ngrok` npm package\n *\n * The npm package embeds the ngrok binary and manages its own lifecycle,\n * which fights with our explicit spawn/stop model. The binary-on-PATH\n * approach mirrors the cloudflared providers and keeps the dependency\n * surface small.\n *\n * ## ngrok discovery\n *\n * Detected on PATH at check/start time. Missing → `check()` returns false\n * and `start()` throws with install instructions. We deliberately don't\n * bundle binaries.\n */\n\nimport { spawn, type ChildProcess } from \"node:child_process\"\nimport { promisify } from \"node:util\"\nimport { execFile } from \"node:child_process\"\n\nimport type {\n ProviderStartOptions,\n ProviderStartResult,\n RemoteProvider,\n TunnelProviderHandle,\n} from \"./types.js\"\n\nconst execFileAsync = promisify(execFile)\n\n/** JSON line from ngrok's `--log-format=json` stdout: `{\"url\":\"...\",...}`. */\nconst URL_JSON_REGEX = /\"url\"\\s*:\\s*\"(https:\\/\\/[^\"]+)\"/i\n\n/** Ngrok local agent API base. */\nconst AGENT_API = \"http://127.0.0.1:4040\"\n\nconst STARTUP_TIMEOUT_MS = 30_000\nconst API_POLL_INTERVAL_MS = 500\nconst API_GRACE_MS = 2_000\n\n/** Adapter-kit slug for the ngrok provider (catalog key). */\nexport const NGROK_SLUG = \"ngrok\"\n\n/**\n * Ngrok capabilities. `stableUrl` is true only when a reserved domain is\n * configured; without one the URL is fixed in format but not guaranteed\n * across restarts without a paid plan.\n */\nexport const NGROK_CAPABILITIES = {\n stableUrl: false, // overridden at instance level when domain is set\n autostart: true,\n customDomain: true,\n requiresAuth: true,\n hasApi: true,\n} as const\n\n/** Creds fields the ngrok provider accepts via `setup_tunnel_provider`. */\nexport const NGROK_SETUP_FIELDS = [\n {\n name: \"authToken\",\n description:\n \"Ngrok authtoken (from dashboard.ngrok.com/get-started/your-authtoken)\",\n required: true,\n sensitive: true,\n },\n {\n name: \"domain\",\n description: \"Optional reserved ngrok static domain (requires paid plan)\",\n required: false,\n sensitive: true,\n },\n] as const\n\n/** Structured credentials for the ngrok provider. */\nexport interface TunnelNgrokCreds {\n /** Ngrok authtoken from dashboard.ngrok.com/get-started/your-authtoken. */\n authToken: string\n /** Optional reserved static domain (requires ngrok paid plan). */\n domain?: string\n}\n\n/** Factory options for building an ngrok tunnel provider. */\nexport interface NgrokProviderOpts {\n /** Ngrok authtoken. Pass undefined for descriptor-only handles. */\n authToken?: string\n /** Optional reserved static domain. */\n domain?: string\n /**\n * Binary presence probe. Default: real `ngrok version` PATH check.\n * Injectable so tests can control binary-presence deterministically\n * without a global `node:child_process` mock.\n */\n probeBinary?: () => Promise<boolean>\n}\n\n/**\n * Factory: build an ngrok tunnel provider.\n *\n * When called with no config (descriptor-only, for listing), `start()` and\n * `check()` will fail gracefully — the adapter-kit lister never calls those\n * methods; it only inspects handle metadata.\n */\nexport function ngrokTunnelProvider(\n opts?: NgrokProviderOpts,\n): RemoteProvider & TunnelProviderHandle {\n let child: ChildProcess | null = null\n\n const authToken = opts?.authToken ?? null\n const domain = opts?.domain ?? null\n const hasDomain = domain != null && domain.length > 0\n const probeBinary = opts?.probeBinary ?? ngrokOnPath\n\n return {\n id: \"ngrok\",\n // ── adapter-kit handle surface ──────────────────────────────────\n slug: NGROK_SLUG,\n name: \"Ngrok Tunnel\",\n version: \"builtin\",\n description:\n \"Ngrok tunnel with optional static domain support. Requires a free authtoken.\",\n requiresSetup: true,\n setupFields: NGROK_SETUP_FIELDS,\n capabilities: {\n ...NGROK_CAPABILITIES,\n stableUrl: hasDomain,\n },\n async check(): Promise<boolean> {\n // Reachable = ngrok binary on PATH AND an authtoken is available.\n const [bin] = await Promise.all([probeBinary()])\n return bin && authToken != null\n },\n async start(opts: ProviderStartOptions): Promise<ProviderStartResult> {\n await assertNgrokOnPath(probeBinary)\n if (!authToken) {\n throw new Error(\n \"ngrok authtoken not configured. Run setup first:\\n\" +\n \" agentproto tunnel setup ngrok\\n\" +\n \"Or set NGROK_AUTHTOKEN in your environment.\",\n )\n }\n\n const args = [\n \"http\",\n String(opts.target.port),\n \"--log=stdout\",\n \"--log-format=json\",\n ]\n if (hasDomain) args.push(`--domain=${domain}`)\n\n const proc = spawn(\"ngrok\", args, {\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n env: { ...process.env, NGROK_AUTHTOKEN: authToken },\n shell: false,\n })\n child = proc\n\n // Forward logs.\n const forwardLogs = (chunk: Buffer) => {\n const text = chunk.toString(\"utf8\")\n for (const line of text.split(/\\r?\\n/)) {\n if (line.length > 0) opts.onLog?.(`[ngrok] ${line}`)\n }\n }\n proc.stderr?.on(\"data\", forwardLogs)\n proc.stdout?.on(\"data\", forwardLogs)\n\n const url = await new Promise<string>((resolve, reject) => {\n let settled = false\n const timer = setTimeout(() => {\n if (settled) return\n settled = true\n try {\n proc.kill(\"SIGTERM\")\n } catch {\n /* noop */\n }\n reject(\n new Error(\n `ngrok did not emit a public URL within ${STARTUP_TIMEOUT_MS / 1000}s`,\n ),\n )\n }, STARTUP_TIMEOUT_MS)\n\n // Strategy 1: poll the local agent API (preferred — canonical).\n let apiPollHandle: ReturnType<typeof setInterval> | null = null\n const startApiPoll = () => {\n apiPollHandle = setInterval(async () => {\n if (settled) return\n try {\n const res = await fetch(`${AGENT_API}/api/tunnels`)\n if (!res.ok) return\n const data = (await res.json()) as {\n tunnels?: { public_url?: string }[]\n }\n const pubUrl = data.tunnels?.[0]?.public_url\n if (pubUrl) {\n settled = true\n clearTimeout(timer)\n if (apiPollHandle) clearInterval(apiPollHandle)\n resolve(pubUrl)\n }\n } catch {\n // API not ready yet — keep polling.\n }\n }, API_POLL_INTERVAL_MS)\n if (apiPollHandle.unref) apiPollHandle.unref()\n }\n\n // Strategy 2: fallback — parse JSON lines from stdout.\n const onStdout = (chunk: Buffer) => {\n if (settled) return\n const text = chunk.toString(\"utf8\")\n // Try the regex first (fast path).\n const reMatch = text.match(URL_JSON_REGEX)\n if (reMatch) {\n settled = true\n clearTimeout(timer)\n if (apiPollHandle) clearInterval(apiPollHandle)\n resolve(reMatch[1]!)\n return\n }\n // Try line-by-line JSON parse.\n for (const line of text.split(/\\r?\\n/)) {\n if (line.length === 0) continue\n try {\n const parsed = JSON.parse(line) as { url?: string }\n if (parsed.url) {\n settled = true\n clearTimeout(timer)\n if (apiPollHandle) clearInterval(apiPollHandle)\n resolve(parsed.url)\n return\n }\n } catch {\n // Not a JSON line — keep waiting.\n }\n }\n }\n\n // Start API polling after a short grace period (ngrok takes ~1-2s\n // to start the agent API).\n setTimeout(startApiPoll, API_GRACE_MS)\n\n // Also listen on stdout for JSON-line fallback.\n proc.stdout?.on(\"data\", onStdout)\n\n proc.once(\"error\", err => {\n if (settled) return\n settled = true\n clearTimeout(timer)\n if (apiPollHandle) clearInterval(apiPollHandle)\n reject(err)\n })\n proc.once(\"exit\", (code, signal) => {\n if (settled) return\n settled = true\n clearTimeout(timer)\n if (apiPollHandle) clearInterval(apiPollHandle)\n reject(\n new Error(\n `ngrok exited before emitting a URL (code=${code}, signal=${signal})`,\n ),\n )\n })\n })\n\n proc.once(\"exit\", (code, signal) => {\n opts.onLog?.(\n `[ngrok] exited (code=${code ?? \"?\"} signal=${signal ?? \"-\"})`,\n )\n })\n\n return { publicUrl: url, pid: proc.pid ?? null }\n },\n\n async stop(): Promise<void> {\n const proc = child\n child = null\n if (!proc || proc.exitCode !== null) return\n proc.kill(\"SIGTERM\")\n const timer = setTimeout(() => {\n try {\n proc.kill(\"SIGKILL\")\n } catch {\n /* noop */\n }\n }, 3_000)\n timer.unref()\n await new Promise<void>(resolve => {\n if (proc.exitCode !== null) {\n clearTimeout(timer)\n resolve()\n return\n }\n proc.once(\"exit\", () => {\n clearTimeout(timer)\n resolve()\n })\n })\n },\n }\n}\n\n// ── helpers ────────────────────────────────────────────────────────────\n\n/** Non-throwing PATH probe for the adapter-kit `check()` health surface. */\nasync function ngrokOnPath(): Promise<boolean> {\n try {\n await execFileAsync(\"ngrok\", [\"version\"], { timeout: 3_000 })\n return true\n } catch {\n return false\n }\n}\n\nasync function assertNgrokOnPath(probe?: () => Promise<boolean>): Promise<void> {\n const ok = await (probe ?? ngrokOnPath)()\n if (!ok) {\n throw new Error(\n \"ngrok not found on PATH. Install it first:\\n\" +\n \" macOS: brew install ngrok/ngrok/ngrok\\n\" +\n \" Linux: https://ngrok.com/download\\n\" +\n \" Windows: winget install ngrok\\n\" +\n \"Or download a prebuilt binary from https://ngrok.com/download.\",\n )\n }\n}","/**\n * Slug-keyed tunnel provider registry — the single source of truth that both\n * halves of the tunnel family consult:\n *\n * - the adapter-kit listing path (`list_tunnel_adapters` / `setup_tunnel_provider`)\n * - the lifecycle path (`TunnelRegistry`: create / restore / start / stop)\n *\n * Before this module those two halves spoke different languages — the\n * lifecycle engine only knew the short discriminators `\"quick\"`/`\"named\"` and\n * had no ngrok case at all, while the adapter half spoke slugs. They never\n * reconciled, so ngrok was listable-but-not-creatable. Routing everything\n * through one registry collapses that: a built-in OR a third-party\n * `@agentproto/adapter-<slug>` / `@<scope>/agentproto-adapter-<slug>` provider\n * resolves the same way and works end to end.\n */\n\nimport { discoverAdapterPackages } from \"@agentproto/adapter-kit\"\n\nimport {\n quickTunnelProvider,\n CLOUDFLARE_QUICK_SLUG,\n} from \"./quick.js\"\nimport {\n namedTunnelProvider,\n CLOUDFLARE_NAMED_SLUG,\n} from \"./named.js\"\nimport { ngrokTunnelProvider, NGROK_SLUG } from \"./ngrok.js\"\nimport type {\n RemoteProvider,\n TunnelProviderHandle,\n TunnelProviderCapabilities,\n} from \"./types.js\"\n\n/** A resolved provider — the lifecycle + adapter-kit handle surface combined. */\nexport type TunnelProvider = RemoteProvider & TunnelProviderHandle\n\n/** Per-slug credentials, as stored by the creds store / setup tool. */\nexport type TunnelCreds = Record<string, string>\n\n/**\n * Factory for a tunnel provider. Built-ins and third-party packages both\n * expose this shape: given the slug's stored creds (or null for a\n * descriptor-only handle used in listing), return a ready provider.\n */\nexport type TunnelProviderFactory = (creds?: TunnelCreds | null) => TunnelProvider\n\n/**\n * Built-in providers keyed by canonical slug. This replaces BOTH the old\n * `pickProvider()` switch (lifecycle) and the `makeTunnelResolver()` switch\n * (listing) — one map, two consumers.\n */\nexport const BUILTIN_TUNNEL_PROVIDERS: Record<string, TunnelProviderFactory> = {\n [CLOUDFLARE_QUICK_SLUG]: () => quickTunnelProvider(),\n [CLOUDFLARE_NAMED_SLUG]: (creds) =>\n namedTunnelProvider({\n hostname: creds?.hostname ?? \"\",\n tunnelId: creds?.tunnelId ?? \"\",\n ...(creds?.credentialsFile\n ? { credentialsFile: creds.credentialsFile }\n : {}),\n }),\n [NGROK_SLUG]: (creds) =>\n ngrokTunnelProvider(\n creds?.authToken\n ? {\n authToken: creds.authToken,\n ...(creds.domain ? { domain: creds.domain } : {}),\n }\n : undefined,\n ),\n}\n\n/** The canonical built-in slugs, in catalog order. */\nexport const BUILTIN_TUNNEL_SLUGS = [\n CLOUDFLARE_QUICK_SLUG,\n CLOUDFLARE_NAMED_SLUG,\n NGROK_SLUG,\n] as const\n\n/**\n * Legacy short discriminators → canonical slugs. Persisted `tunnels.json`\n * descriptors and existing automations create tunnels with `\"quick\"` /\n * `\"named\"`; we normalize those to slugs everywhere so old state restores and\n * old callers keep working.\n */\nexport const LEGACY_PROVIDER_ALIAS: Record<string, string> = {\n quick: CLOUDFLARE_QUICK_SLUG,\n named: CLOUDFLARE_NAMED_SLUG,\n}\n\n/** Map a raw provider string (slug OR legacy short name) to a canonical slug. */\nexport function normalizeProviderSlug(raw: string): string {\n return LEGACY_PROVIDER_ALIAS[raw] ?? raw\n}\n\n/**\n * Capabilities for a BUILT-IN provider slug (or legacy short name), read\n * synchronously from a descriptor-only handle. Returns null for third-party\n * slugs (their capabilities need an async import — `resolveTunnelProvider`).\n * Used by the lifecycle engine to decide autostart eligibility by data\n * (`stableUrl`) rather than a hardcoded slug literal.\n */\nexport function builtinProviderCapabilities(\n raw: string,\n): TunnelProviderCapabilities | null {\n const factory = BUILTIN_TUNNEL_PROVIDERS[normalizeProviderSlug(raw)]\n return factory ? factory(null).capabilities : null\n}\n\nconst slugToCamel = (slug: string): string =>\n slug.replace(/-([a-z0-9])/g, (_, c: string) => c.toUpperCase())\n\n/** Duck-type a value as a tunnel provider handle (no secrets touched). */\nfunction isTunnelProvider(x: unknown): x is TunnelProvider {\n if (!x || typeof x !== \"object\") return false\n const h = x as Record<string, unknown>\n const caps = h.capabilities\n return (\n typeof h.start === \"function\" &&\n typeof h.stop === \"function\" &&\n typeof caps === \"object\" &&\n caps !== null &&\n \"stableUrl\" in (caps as Record<string, unknown>)\n )\n}\n\n/**\n * Import a third-party tunnel provider package and build its handle. The\n * package may export either a factory `(creds) => handle` or a ready static\n * handle, under `<camelSlug>TunnelProvider`, `<camelSlug>`, `default`, or\n * `handle`. Returns null on any failure (not importable / wrong shape) —\n * partial discovery beats failing the whole listing on one bad package.\n */\nasync function importThirdPartyProvider(\n packageName: string,\n slug: string,\n creds: TunnelCreds | null,\n): Promise<TunnelProvider | null> {\n let mod: Record<string, unknown>\n try {\n mod = (await import(packageName)) as Record<string, unknown>\n } catch {\n return null\n }\n const camel = slugToCamel(slug)\n const candidate =\n mod[`${camel}TunnelProvider`] ??\n mod[camel] ??\n mod.default ??\n mod.handle\n const built =\n typeof candidate === \"function\"\n ? (candidate as TunnelProviderFactory)(creds)\n : candidate\n return isTunnelProvider(built) ? built : null\n}\n\nexport interface ResolveTunnelProviderOpts {\n /** Stored creds for the slug (descriptor-only listing passes null). */\n creds?: TunnelCreds | null\n}\n\n/**\n * Resolve a slug (or legacy short name) to a concrete provider. Built-ins\n * first (no import), then a third-party package discovered on disk across\n * both naming conventions. Returns null when the slug is unknown / not\n * installed — the kit's \"supported but unavailable\" signal.\n */\nexport async function resolveTunnelProvider(\n raw: string,\n opts?: ResolveTunnelProviderOpts,\n): Promise<TunnelProvider | null> {\n const slug = normalizeProviderSlug(raw)\n const builtin = BUILTIN_TUNNEL_PROVIDERS[slug]\n if (builtin) return builtin(opts?.creds ?? null)\n\n const pkgs = await discoverAdapterPackages()\n const match = pkgs.find((p) => p.slug === slug)\n if (!match) return null\n return importThirdPartyProvider(match.packageName, slug, opts?.creds ?? null)\n}\n\n/**\n * Discover installed third-party tunnel providers NOT already in the catalog\n * (built-ins) — the `discoverExtras` source for the kit's lister so\n * locally-installed custom providers appear in `list_tunnel_adapters`.\n */\nexport async function discoverTunnelHandles(\n catalogSlugs: Set<string>,\n): Promise<TunnelProvider[]> {\n const pkgs = await discoverAdapterPackages()\n const out: TunnelProvider[] = []\n for (const pkg of pkgs) {\n if (catalogSlugs.has(pkg.slug)) continue\n if (BUILTIN_TUNNEL_PROVIDERS[pkg.slug]) continue\n const handle = await importThirdPartyProvider(pkg.packageName, pkg.slug, null)\n if (handle) out.push(handle)\n }\n return out.sort((a, b) => a.slug.localeCompare(b.slug))\n}\n","/**\n * TunnelRegistry — multi-tunnel public-URL manager.\n *\n * Manages a named set of cloudflared (or future provider) tunnels,\n * each forwarding a local port to a public URL. Independent from\n * RemoteController which handles the single \"expose this gateway\"\n * use-case with bearer-token gating. This registry is for the general\n * \"create a public endpoint for any local port\" surface.\n *\n * Lifecycle:\n * create(input) → spawns provider, waits for URL, stores descriptor\n * list() → TunnelDescriptor[]\n * get(id) → TunnelDescriptor | undefined\n * stop(id) → SIGTERM provider, mark stopped\n * shutdown() → stop all active tunnels (called on daemon exit)\n *\n * Persistence: `~/.agentproto/tunnels.json` — descriptors survive\n * daemon restarts; active entries are marked \"stopped\" on next boot\n * since their child processes are gone (same GHOST pattern as\n * sessions.ts).\n */\n\nimport { randomUUID } from \"node:crypto\"\nimport { mkdirSync, readFileSync, writeFileSync, existsSync } from \"node:fs\"\nimport { mkdir } from \"node:fs/promises\"\nimport { dirname, join, resolve } from \"node:path\"\nimport { homedir } from \"node:os\"\nimport { CLOUDFLARE_NAMED_SLUG } from \"./remote-providers/named.js\"\nimport {\n resolveTunnelProvider,\n normalizeProviderSlug,\n builtinProviderCapabilities,\n type TunnelCreds,\n} from \"./remote-providers/registry.js\"\nimport type { RemoteProvider } from \"./remote-providers/types.js\"\n\nexport type TunnelStatus = \"starting\" | \"active\" | \"stopped\" | \"error\"\n\n/**\n * Provider identifier — an open set of slugs (built-in `cloudflare-quick` /\n * `cloudflare-named` / `ngrok`, legacy short names `quick` / `named`, or any\n * third-party `@scope/agentproto-adapter-<slug>`). Normalized to a canonical\n * slug only at resolve time, so persisted descriptors keep their original\n * value and need no migration.\n */\nexport type TunnelProvider = string\n\nexport interface TunnelDescriptor {\n id: string\n /** Optional user-friendly slug. Accepts id-or-name in stop/status calls. */\n name?: string\n /** Free-text label surfaced in list / CLI table. */\n label?: string\n provider: TunnelProvider\n targetHost: string\n targetPort: number\n publicUrl: string\n status: TunnelStatus\n pid: number | null\n createdAt: string\n stoppedAt?: string\n lastError?: string\n /**\n * When true, the tunnel is relaunched on daemon boot (see\n * `restoreOnBoot`). Only meaningful for `named` tunnels — a relaunched\n * `quick` tunnel gets a fresh random URL, so autostart for it merely\n * keeps *a* tunnel up, not a stable URL.\n */\n autostart?: boolean\n // ── named-provider fields (unset for quick) ──────────────────────\n /** Stable public hostname routed to this tunnel. */\n hostname?: string\n /** Cloudflare tunnel id or name (the `run` target). */\n tunnelId?: string\n /** Path to the tunnel credentials JSON (defaults under ~/.cloudflared). */\n credentialsFile?: string\n}\n\ninterface TunnelEntry {\n desc: TunnelDescriptor\n provider: RemoteProvider\n}\n\nexport interface CreateTunnelInput {\n targetPort: number\n provider?: TunnelProvider\n name?: string\n label?: string\n targetHost?: string\n /** Relaunch this tunnel on daemon boot. See `TunnelDescriptor.autostart`. */\n autostart?: boolean\n // ── required when provider === \"named\" ───────────────────────────\n /** Stable public hostname (e.g. app.example.com). */\n hostname?: string\n /** Cloudflare tunnel id or name to `run`. */\n tunnelId?: string\n /** Path to the credentials JSON (defaults to ~/.cloudflared/<tunnelId>.json). */\n credentialsFile?: string\n}\n\nexport interface TunnelRegistryOptions {\n /** Absolute path for persistence file. Defaults to ~/.agentproto/tunnels.json */\n persistPath?: string\n /** Absolute path to workspace — used as scratch dir for provider config files. */\n workspace?: string\n /** Hook for surfacing provider log lines. */\n onLog?: (line: string) => void\n /**\n * Read stored credentials for a provider slug. Lets the lifecycle build a\n * provider that keeps its secrets in the creds store (e.g. ngrok's authtoken,\n * or any third-party provider) rather than on the descriptor. Injected by the\n * daemon (index.ts); descriptor-carried config (named's hostname/tunnelId)\n * still takes precedence.\n */\n readCreds?: (slug: string) => Promise<TunnelCreds | null>\n}\n\nconst TUNNELS_FILE_PATH = (): string =>\n resolve(homedir(), \".agentproto\", \"tunnels.json\")\n\nconst HISTORY_CAP = 50\n\ninterface PersistedTunnels {\n savedAt: string\n tunnels: TunnelDescriptor[]\n}\n\nexport class TunnelRegistry {\n private readonly tunnels = new Map<string, TunnelEntry>()\n private readonly persistPath: string\n private readonly workspace: string\n private readonly onLog: ((line: string) => void) | undefined\n private readonly readCreds:\n | ((slug: string) => Promise<TunnelCreds | null>)\n | undefined\n private persistTimer: ReturnType<typeof setTimeout> | null = null\n\n constructor(opts: TunnelRegistryOptions = {}) {\n this.persistPath = opts.persistPath ?? TUNNELS_FILE_PATH()\n this.workspace = opts.workspace ?? homedir()\n this.onLog = opts.onLog\n this.readCreds = opts.readCreds\n\n this.loadFromDisk()\n }\n\n async create(input: CreateTunnelInput): Promise<TunnelDescriptor> {\n const id = randomUUID()\n const provider = input.provider ?? \"quick\"\n const targetHost = input.targetHost ?? \"127.0.0.1\"\n\n // Named tunnels need a stable hostname + a tunnel id to `run`. Fail\n // fast here rather than letting cloudflared error out cryptically.\n if (normalizeProviderSlug(provider) === CLOUDFLARE_NAMED_SLUG) {\n if (!input.hostname || !input.tunnelId) {\n throw new Error(\n 'named tunnel requires both \"hostname\" and \"tunnelId\" ' +\n \"(the cloudflared tunnel you provisioned with `cloudflared tunnel create`).\",\n )\n }\n }\n\n if (input.name) {\n const conflict = this.findByIdOrName(input.name)\n if (conflict && (conflict.status === \"starting\" || conflict.status === \"active\")) {\n throw new Error(\n `tunnel name \"${input.name}\" already in use by active tunnel ${conflict.id}`,\n )\n }\n }\n\n const desc: TunnelDescriptor = {\n id,\n provider,\n targetHost,\n targetPort: input.targetPort,\n publicUrl: \"\",\n status: \"starting\",\n pid: null,\n createdAt: new Date().toISOString(),\n ...(input.name ? { name: input.name } : {}),\n ...(input.label ? { label: input.label } : {}),\n ...(input.autostart ? { autostart: true } : {}),\n ...(input.hostname ? { hostname: input.hostname } : {}),\n ...(input.tunnelId ? { tunnelId: input.tunnelId } : {}),\n ...(input.credentialsFile ? { credentialsFile: input.credentialsFile } : {}),\n }\n\n const prov = await this.pickProviderForTest(provider, desc)\n const entry: TunnelEntry = { desc, provider: prov }\n this.tunnels.set(id, entry)\n this.schedulePersist()\n\n await this.startEntry(entry)\n return { ...desc }\n }\n\n /**\n * Drive an entry's provider through start and fold the result back into\n * its descriptor. On failure the descriptor is marked `error` and the\n * error re-thrown (callers that want best-effort — e.g. boot restore —\n * catch it). Shared by `create` and `restoreOnBoot`.\n */\n private async startEntry(entry: TunnelEntry): Promise<void> {\n const { desc, provider } = entry\n desc.status = \"starting\"\n delete desc.lastError\n this.schedulePersist()\n\n const workspaceDir = this.workspace\n await mkdir(join(workspaceDir, \".agentproto\"), { recursive: true }).catch(() => {\n // ignore if already exists or not writable\n })\n\n let result: { publicUrl: string; pid: number | null }\n try {\n result = await provider.start({\n target: { host: desc.targetHost, port: desc.targetPort },\n workspace: workspaceDir,\n onLog: line => this.onLog?.(line),\n })\n } catch (err) {\n desc.status = \"error\"\n desc.lastError = err instanceof Error ? err.message : String(err)\n this.schedulePersist()\n throw err\n }\n\n desc.publicUrl = result.publicUrl\n desc.pid = result.pid\n desc.status = \"active\"\n delete desc.stoppedAt\n this.schedulePersist()\n }\n\n /**\n * Relaunch every `autostart` tunnel that isn't currently running. Called\n * once on daemon boot — `loadFromDisk` has already ghosted formerly-live\n * entries to `stopped` and given autostart ones a real provider. Quick\n * tunnels are skipped (a relaunch yields a fresh random URL, defeating\n * the point); named tunnels come back on their stable hostname.\n *\n * Best-effort: a provider that fails to start leaves its descriptor in\n * `error` and the others still come up.\n */\n async restoreOnBoot(): Promise<void> {\n const toStart = Array.from(this.tunnels.values()).filter(\n e => e.desc.autostart === true && e.desc.status === \"stopped\",\n )\n for (const entry of toStart) {\n // Autostart eligibility is data-driven: a provider whose public URL is\n // NOT stable across restarts (e.g. cloudflare-quick) gets a fresh URL on\n // relaunch, defeating the point — skip it. Read by slug so it holds even\n // for a test-injected mock that carries no capabilities. Third-party\n // providers (caps unknown here) are attempted.\n const caps = builtinProviderCapabilities(entry.desc.provider)\n if (caps && caps.stableUrl === false) {\n this.onLog?.(\n `[tunnel] skipping autostart for ephemeral-URL tunnel ${entry.desc.name ?? entry.desc.id} ` +\n `(URL would change on relaunch — use a stable-URL provider)`,\n )\n continue\n }\n this.onLog?.(\n `[tunnel] autostart: relaunching ${entry.desc.name ?? entry.desc.id} → ${entry.desc.hostname ?? \"?\"}`,\n )\n try {\n // loadFromDisk left a stub here; build the real provider now (async —\n // may dynamic-import a third-party package or read creds).\n entry.provider = await this.pickProviderForTest(entry.desc.provider, entry.desc)\n await this.startEntry(entry)\n } catch (err) {\n this.onLog?.(\n `[tunnel] autostart failed for ${entry.desc.name ?? entry.desc.id}: ` +\n `${err instanceof Error ? err.message : String(err)}`,\n )\n }\n }\n }\n\n list(): TunnelDescriptor[] {\n return Array.from(this.tunnels.values()).map(e => ({ ...e.desc }))\n }\n\n get(id: string): TunnelDescriptor | undefined {\n const entry = this.tunnels.get(id)\n return entry ? { ...entry.desc } : undefined\n }\n\n findByIdOrName(idOrName: string): TunnelDescriptor | undefined {\n const byId = this.tunnels.get(idOrName)\n if (byId) return { ...byId.desc }\n for (const entry of this.tunnels.values()) {\n if (entry.desc.name === idOrName) return { ...entry.desc }\n }\n return undefined\n }\n\n async stop(idOrName: string): Promise<boolean> {\n const entry = this.findEntryByIdOrName(idOrName)\n if (!entry) return false\n if (entry.desc.status === \"stopped\") return true\n\n try {\n await entry.provider.stop()\n } catch {\n // swallow — provider may already be dead\n }\n\n entry.desc.status = \"stopped\"\n entry.desc.stoppedAt = new Date().toISOString()\n this.schedulePersist()\n return true\n }\n\n async shutdown(): Promise<void> {\n const active = Array.from(this.tunnels.values()).filter(\n e => e.desc.status === \"starting\" || e.desc.status === \"active\",\n )\n await Promise.allSettled(\n active.map(async e => {\n try {\n await e.provider.stop()\n } catch {\n // swallow\n }\n e.desc.status = \"stopped\"\n e.desc.stoppedAt = new Date().toISOString()\n }),\n )\n // Flush persist timer if scheduled\n if (this.persistTimer !== null) {\n clearTimeout(this.persistTimer)\n this.persistTimer = null\n this.persistNow()\n }\n }\n\n // ── test seam ─────────────────────────────────────────────────────\n // Subclasses (tests) override this to inject a mock provider. The\n // descriptor is passed so a real provider can be built with its\n // hostname / tunnelId / credentials. Async because the default path may\n // dynamic-import a third-party provider package.\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n protected async pickProviderForTest(\n _provider: TunnelProvider,\n desc: TunnelDescriptor,\n ): Promise<RemoteProvider> {\n const slug = normalizeProviderSlug(desc.provider)\n const creds = await this.credsForDescriptor(desc)\n const provider = await resolveTunnelProvider(slug, { creds })\n if (!provider) {\n throw new Error(`unknown tunnel provider: ${desc.provider}`)\n }\n return provider\n }\n\n /**\n * Build the creds passed to a provider: stored creds (ngrok authtoken,\n * third-party secrets) merged with descriptor-carried config (named's\n * hostname/tunnelId/credentialsFile), descriptor taking precedence.\n */\n private async credsForDescriptor(\n desc: TunnelDescriptor,\n ): Promise<TunnelCreds> {\n const slug = normalizeProviderSlug(desc.provider)\n const stored = this.readCreds ? (await this.readCreds(slug)) ?? {} : {}\n const creds: TunnelCreds = { ...stored }\n if (desc.hostname) creds.hostname = desc.hostname\n if (desc.tunnelId) creds.tunnelId = desc.tunnelId\n if (desc.credentialsFile) creds.credentialsFile = desc.credentialsFile\n return creds\n }\n\n // ── private ──────────────────────────────────────────────────────\n\n private findEntryByIdOrName(idOrName: string): TunnelEntry | undefined {\n const byId = this.tunnels.get(idOrName)\n if (byId) return byId\n for (const entry of this.tunnels.values()) {\n if (entry.desc.name === idOrName) return entry\n }\n return undefined\n }\n\n private schedulePersist(): void {\n if (this.persistTimer !== null) return\n this.persistTimer = setTimeout(() => {\n this.persistTimer = null\n this.persistNow()\n }, 1_500)\n // Don't keep the process alive just for a persist flush.\n if (this.persistTimer.unref) this.persistTimer.unref()\n }\n\n private persistNow(): void {\n try {\n const all = Array.from(this.tunnels.values()).map(e => e.desc)\n // Newest first, capped to HISTORY_CAP.\n const sliced = all.slice(-HISTORY_CAP)\n const payload: PersistedTunnels = {\n savedAt: new Date().toISOString(),\n tunnels: sliced,\n }\n mkdirSync(dirname(this.persistPath), { recursive: true })\n writeFileSync(this.persistPath, JSON.stringify(payload, null, 2) + \"\\n\", \"utf8\")\n } catch {\n // Best-effort persistence — a write failure must not crash the daemon.\n }\n }\n\n private loadFromDisk(): void {\n if (!existsSync(this.persistPath)) return\n let raw: string\n try {\n raw = readFileSync(this.persistPath, \"utf8\")\n } catch {\n return\n }\n let parsed: PersistedTunnels\n try {\n parsed = JSON.parse(raw) as PersistedTunnels\n } catch {\n return\n }\n if (!Array.isArray(parsed.tunnels)) return\n\n for (const desc of parsed.tunnels) {\n if (!desc.id) continue\n // Tunnels that were \"starting\" or \"active\" at last save are dead\n // now — the child process is gone. Mark them stopped (GHOST pattern).\n const ghosted: TunnelDescriptor = {\n ...desc,\n status:\n desc.status === \"starting\" || desc.status === \"active\"\n ? \"stopped\"\n : desc.status,\n pid: null,\n ...((desc.status === \"starting\" || desc.status === \"active\")\n ? { stoppedAt: new Date().toISOString() }\n : {}),\n }\n // Every loaded entry starts stubbed — its child process is gone. The\n // real provider is built lazily (async) by `restoreOnBoot` for autostart\n // entries; non-autostart entries are kept only for history and never\n // start, so the stub (which throws on start) is correct for them.\n this.tunnels.set(desc.id, { desc: ghosted, provider: makeStubProvider() })\n }\n }\n}\n\n// ── module-level helpers ───────────────────────────────────────────\n\nfunction makeStubProvider(): RemoteProvider {\n return {\n id: \"stub\",\n async start() {\n throw new Error(\"stub provider: cannot start a ghost tunnel entry\")\n },\n async stop() {\n // no-op — nothing to kill\n },\n }\n}\n","/**\n * MCP tools that expose the TunnelRegistry to agents connected to the\n * daemon. Lets a remote operator create, list, stop, and inspect\n * public tunnels for any local port without touching the terminal.\n *\n * Four tools:\n * create_tunnel spawn a public URL for a local port (cloudflared quick tunnel)\n * list_tunnels browse active + historical tunnels\n * stop_tunnel SIGTERM the tunnel provider + mark stopped\n * tunnel_status read-only descriptor for one tunnel\n *\n * Designed parallel to session-tools.ts — same error-shape, same style.\n */\n\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\"\nimport { z } from \"zod\"\nimport type { TunnelRegistry } from \"./tunnel-registry.js\"\n\nexport interface RegisterTunnelToolsOptions {\n registry: TunnelRegistry\n}\n\nfunction text(value: string | object): {\n content: Array<{ type: \"text\"; text: string }>\n} {\n return {\n content: [\n {\n type: \"text\",\n text: typeof value === \"string\" ? value : JSON.stringify(value, null, 2),\n },\n ],\n }\n}\n\nfunction errText(\n toolName: string,\n err: unknown,\n): { content: Array<{ type: \"text\"; text: string }>; isError: true } {\n return {\n content: [\n {\n type: \"text\",\n text: `${toolName}: ${err instanceof Error ? err.message : String(err)}`,\n },\n ],\n isError: true,\n }\n}\n\nexport function registerTunnelTools(\n server: McpServer,\n opts: RegisterTunnelToolsOptions,\n): void {\n const { registry } = opts\n\n // ── create_tunnel ──────────────────────────────────────────────\n server.tool(\n \"create_tunnel\",\n \"Spawn a public HTTPS URL for a local port. Built-in backends: \" +\n \"`cloudflare-quick` (default, alias `quick`) = Cloudflare Quick Tunnel, \" +\n \"no API key, ephemeral *.trycloudflare.com URL; `cloudflare-named` \" +\n \"(alias `named`) = a cloudflared tunnel you provisioned once \" +\n \"(`cloudflared tunnel create` + `route dns`), bound to a STABLE \" +\n \"hostname — pass `hostname` + `tunnelId`, set `autostart:true` to \" +\n \"relaunch on boot; `ngrok` = ngrok tunnel (configure its authtoken via \" +\n \"`setup_tunnel_provider` first). Any installed third-party provider \" +\n \"(`@scope/agentproto-adapter-<slug>`) also works — see \" +\n \"`list_tunnel_adapters` for the full set. Returns the TunnelDescriptor \" +\n \"once ready (typically <10s). Use `list_tunnels` before opening a \" +\n \"duplicate. Unlike `remote_enable`, this does NOT gate auth — pure \" +\n \"passthrough; the proxied service handles its own authn.\",\n {\n targetPort: z\n .number()\n .int()\n .min(1)\n .max(65535)\n .describe(\"Local port to expose publicly (e.g. 3000 for a dev server).\"),\n provider: z\n .string()\n .optional()\n .describe(\n \"Tunnel provider slug. Built-ins: `cloudflare-quick` (default), \" +\n \"`cloudflare-named`, `ngrok` (legacy aliases `quick`/`named` \" +\n \"accepted). Or any installed third-party provider slug — list via \" +\n \"`list_tunnel_adapters`. `cloudflare-named` requires `hostname` + \" +\n \"`tunnelId`.\",\n ),\n name: z\n .string()\n .optional()\n .describe(\n \"Optional friendly slug (e.g. 'vite-preview'). Accepted as an \" +\n \"alias for the tunnel id in `stop_tunnel` and `tunnel_status`.\",\n ),\n label: z\n .string()\n .optional()\n .describe(\"Free-text label shown in `list_tunnels` output.\"),\n targetHost: z\n .string()\n .optional()\n .describe(\n \"Host the tunnel forwards to. Defaults to `127.0.0.1`. Use \" +\n \"`localhost` only if the target is explicitly IPv6-bound.\",\n ),\n autostart: z\n .boolean()\n .optional()\n .describe(\n \"Relaunch this tunnel automatically on daemon boot. Only useful \" +\n \"for `named` tunnels (a relaunched quick tunnel gets a new URL).\",\n ),\n hostname: z\n .string()\n .optional()\n .describe(\n \"REQUIRED for `named`: the stable public hostname routed to the \" +\n \"tunnel (e.g. app.example.com).\",\n ),\n tunnelId: z\n .string()\n .optional()\n .describe(\n \"REQUIRED for `named`: the cloudflared tunnel id or name to run \" +\n \"(from `cloudflared tunnel create`).\",\n ),\n credentialsFile: z\n .string()\n .optional()\n .describe(\n \"Optional for `named`: path to the tunnel credentials JSON. \" +\n \"Defaults to ~/.cloudflared/<tunnelId>.json.\",\n ),\n },\n async input => {\n try {\n const desc = await registry.create({\n targetPort: input.targetPort,\n ...(input.provider ? { provider: input.provider } : {}),\n ...(input.name ? { name: input.name } : {}),\n ...(input.label ? { label: input.label } : {}),\n ...(input.targetHost ? { targetHost: input.targetHost } : {}),\n ...(input.autostart ? { autostart: true } : {}),\n ...(input.hostname ? { hostname: input.hostname } : {}),\n ...(input.tunnelId ? { tunnelId: input.tunnelId } : {}),\n ...(input.credentialsFile ? { credentialsFile: input.credentialsFile } : {}),\n })\n return text(desc)\n } catch (err) {\n return errText(\"create_tunnel\", err)\n }\n },\n )\n\n // ── list_tunnels ───────────────────────────────────────────────\n server.tool(\n \"list_tunnels\",\n \"List all tunnels tracked by the daemon — active, stopped, and errored. \" +\n \"Each entry includes provider, target port, public URL, status, pid, \" +\n \"and age. Use before `create_tunnel` to avoid spawning duplicates \" +\n \"for the same port.\",\n {\n onlyActive: z\n .boolean()\n .optional()\n .describe(\n \"When true, return only tunnels with status `starting` or `active`. \" +\n \"Default false (return all).\",\n ),\n },\n async input => {\n let tunnels = registry.list()\n if (input.onlyActive) {\n tunnels = tunnels.filter(\n t => t.status === \"starting\" || t.status === \"active\",\n )\n }\n return text({ tunnels })\n },\n )\n\n // ── stop_tunnel ────────────────────────────────────────────────\n server.tool(\n \"stop_tunnel\",\n \"Stop an active tunnel — SIGTERM cloudflared and mark the tunnel stopped. \" +\n \"Accepts either the tunnel id or the friendly name set at create time. \" +\n \"Idempotent on an already-stopped tunnel.\",\n {\n tunnelId: z\n .string()\n .min(1)\n .describe(\n \"Tunnel id (UUID from `create_tunnel`) or the name slug \" +\n \"(e.g. 'vite-preview').\",\n ),\n },\n async input => {\n try {\n const ok = await registry.stop(input.tunnelId)\n if (!ok) {\n return {\n content: [\n {\n type: \"text\",\n text: `stop_tunnel: no tunnel \"${input.tunnelId}\" — use list_tunnels to see current ids`,\n },\n ],\n isError: true,\n }\n }\n return text({ ok, tunnelId: input.tunnelId })\n } catch (err) {\n return errText(\"stop_tunnel\", err)\n }\n },\n )\n\n // ── tunnel_status ──────────────────────────────────────────────\n server.tool(\n \"tunnel_status\",\n \"Return the current descriptor for one tunnel. Accepts either the \" +\n \"tunnel id or the friendly name set at create time.\",\n {\n tunnelId: z\n .string()\n .min(1)\n .describe(\n \"Tunnel id (UUID from `create_tunnel`) or the name slug.\",\n ),\n },\n async input => {\n const desc = registry.findByIdOrName(input.tunnelId)\n if (!desc) {\n return {\n content: [\n {\n type: \"text\",\n text: `tunnel_status: no tunnel \"${input.tunnelId}\" — use list_tunnels to see current ids`,\n },\n ],\n isError: true,\n }\n }\n return text(desc)\n },\n )\n}\n","/**\n * Tunnel family on top of `@agentproto/adapter-kit` — the PILOT consumer.\n *\n * This module is the entire bridge between the generic kit and the two\n * concrete Cloudflare tunnel providers. It contributes nothing the kit\n * already owns (catalog/status/creds/ledger/list/MCP-tool plumbing); it\n * only supplies the tunnel-family `TInfo` (`TunnelAdapterInfo`), the\n * static `TUNNEL_CATALOG`, and the resolver that maps a catalog slug to a\n * concrete {@link TunnelProviderHandle}.\n *\n * Kit primitives used:\n * - `makeCredsStore` → per-slug 0600 creds under `~/.agentproto/tunnel-creds/`\n * - `makeSetupLedger` → `~/.agentproto/setup/<slug>.json`\n * - `makeAdapterResolver` → wraps the throwing `load` into null-on-miss\n * - `makeAdapterLister` → catalog → status-classified `AdapterEntry[]`\n * - `makeListTool` → registers `list_tunnel_adapters`\n * - `makeSetupTool` → registers `setup_tunnel_provider` (multi-field form:\n * hostname + tunnelId + credentialsFile?, all sensitive)\n *\n * Security: `toTunnelInfo` exposes only `capabilities` — never a cred value\n * (Appendix B). The setup tool's fields are marked SENSITIVE and the result\n * NEVER echoes any field value back.\n */\n\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\"\nimport {\n makeCredsStore,\n makeSetupLedger,\n makeAdapterResolver,\n makeAdapterLister,\n makeListTool,\n makeSetupTool,\n type AdapterCatalog,\n type AdapterLister,\n type CredsStore,\n type SetupField,\n type SetupLedger,\n} from \"@agentproto/adapter-kit\"\n\nimport { CLOUDFLARE_QUICK_SLUG } from \"./remote-providers/quick.js\"\nimport { CLOUDFLARE_NAMED_SLUG } from \"./remote-providers/named.js\"\nimport { NGROK_SLUG, type TunnelNgrokCreds } from \"./remote-providers/ngrok.js\"\nimport {\n resolveTunnelProvider,\n discoverTunnelHandles,\n BUILTIN_TUNNEL_PROVIDERS,\n BUILTIN_TUNNEL_SLUGS,\n type TunnelCreds,\n} from \"./remote-providers/registry.js\"\nimport type {\n TunnelProviderHandle,\n TunnelProviderCapabilities,\n} from \"./remote-providers/types.js\"\n\n/** Creds-store / ledger family key → `~/.agentproto/tunnel-creds/`. */\nexport const TUNNEL_FAMILY = \"tunnel\"\n\n/**\n * Family descriptor (`TInfo`). Pure metadata surfaced in\n * `list_tunnel_adapters`. The kit's `AdapterEntry` already carries\n * slug/name/description/status/version, so the only tunnel-specific field\n * is the declared capability set. NEVER carries a cred value.\n */\nexport interface TunnelAdapterInfo {\n capabilities: TunnelProviderCapabilities\n}\n\n/**\n * Structured credentials for `cloudflare-named`. Collected from the\n * multi-field setup tool (hostname + tunnelId + credentialsFile?).\n */\nexport interface TunnelNamedCreds {\n hostname: string\n tunnelId: string\n credentialsFile?: string\n}\n\n/** Union of all tunnel-family credential shapes (per-slug). */\nexport type TunnelProviderCreds = TunnelNamedCreds | TunnelNgrokCreds\n\n/** Static catalog of the three providers. */\nexport const TUNNEL_CATALOG: AdapterCatalog = [\n {\n slug: CLOUDFLARE_QUICK_SLUG,\n name: \"Cloudflare Quick Tunnel\",\n description:\n \"Zero-credential Cloudflare tunnel. Ephemeral *.trycloudflare.com URL, fresh each run.\",\n packageName: \"@agentproto/runtime\",\n hint: \"cloudflare · ephemeral\",\n },\n {\n slug: CLOUDFLARE_NAMED_SLUG,\n name: \"Cloudflare Named Tunnel\",\n description:\n \"Persistent Cloudflare tunnel bound to a stable hostname you control (BYO credentials).\",\n packageName: \"@agentproto/runtime\",\n hint: \"cloudflare · stable\",\n },\n {\n slug: NGROK_SLUG,\n name: \"Ngrok Tunnel\",\n description:\n \"Ngrok tunnel with optional static domain support. Requires a free authtoken.\",\n packageName: \"@agentproto/runtime\",\n hint: \"ngrok · stable\",\n },\n]\n\n/** Extract the safe descriptor from a resolved handle. No secrets. */\nexport function toTunnelInfo(handle: TunnelProviderHandle): TunnelAdapterInfo {\n return { capabilities: handle.capabilities }\n}\n\n/**\n * Build the tunnel-family creds store (per-slug, 0600). Stored as a plain\n * string map — the structured {@link TunnelNamedCreds}/{@link TunnelNgrokCreds}\n * shapes are typed *views* used by callers that read specific providers; the\n * generic store accepts any provider's declared fields (incl. third-party),\n * which is what makes setup pluggable.\n */\nexport function makeTunnelCredsStore(home?: string): CredsStore<TunnelCreds> {\n return makeCredsStore<TunnelCreds>({\n family: TUNNEL_FAMILY,\n ...(home ? { home } : {}),\n })\n}\n\n/**\n * Resolve a catalog slug to a concrete handle via the provider registry —\n * built-ins in-process, third-party packages dynamic-imported. Reads stored\n * creds first so `named`/`ngrok` (and any third-party provider) are built\n * configured when possible; unconfigured slugs resolve to a descriptor-only\n * handle (listing never calls `start()`/`check()` — per OQ-5). Throws on an\n * unknown slug so the kit's resolver wraps it to `null` (\"supported but not\n * installed\").\n */\nexport function makeTunnelResolver(credsStore: CredsStore<TunnelCreds>) {\n return makeAdapterResolver<TunnelProviderHandle>({\n load: async (slug: string): Promise<TunnelProviderHandle> => {\n const creds = await credsStore.read(slug)\n const handle = await resolveTunnelProvider(slug, { creds })\n if (!handle) throw new Error(`unknown tunnel adapter slug: ${slug}`)\n return handle\n },\n })\n}\n\n/** Build the family lister: catalog → status-classified entries, plus any\n * third-party providers discovered on disk (both naming conventions). */\nexport function makeTunnelLister(opts: {\n credsStore: CredsStore<TunnelCreds>\n ledger: SetupLedger\n}): AdapterLister<TunnelAdapterInfo> {\n return makeAdapterLister<TunnelProviderHandle, TunnelAdapterInfo>({\n catalog: TUNNEL_CATALOG,\n resolver: makeTunnelResolver(opts.credsStore),\n ledger: opts.ledger,\n credsStore: opts.credsStore,\n toInfo: toTunnelInfo,\n discoverExtras: () =>\n discoverTunnelHandles(new Set(TUNNEL_CATALOG.map((c) => c.slug))),\n })\n}\n\n/**\n * Resolve every provider that declares creds (built-in + third-party) and\n * union their `setupFields` for the `setup_tunnel_provider` tool. Because one\n * tool spans many providers with disjoint fields, the unioned shape is relaxed\n * to all-optional at the zod layer (`required: false`); the genuine per-provider\n * required-ness is enforced in `onSetup` against the chosen provider's handle.\n */\nasync function collectSetupSchema(): Promise<{\n validSlugs: string[]\n fields: SetupField[]\n}> {\n const builtinHandles = Object.values(BUILTIN_TUNNEL_PROVIDERS).map((f) =>\n f(null),\n )\n const extraHandles = await discoverTunnelHandles(new Set(BUILTIN_TUNNEL_SLUGS))\n const setupHandles = [...builtinHandles, ...extraHandles].filter(\n (h) => h.setupFields && h.setupFields.length > 0,\n )\n\n const validSlugs = setupHandles.map((h) => h.slug)\n const fieldByName = new Map<string, SetupField>()\n for (const h of setupHandles) {\n for (const f of h.setupFields ?? []) {\n // First declaration wins; relax to optional for the cross-provider tool.\n if (!fieldByName.has(f.name)) {\n fieldByName.set(f.name, { ...f, required: false })\n }\n }\n }\n return { validSlugs, fields: [...fieldByName.values()] }\n}\n\nexport interface RegisterTunnelAdapterToolsOptions {\n /** Home dir override (tests). Defaults to `AGENTPROTO_HOME ?? ~/.agentproto`. */\n home?: string\n}\n\n/**\n * Register the tunnel family's adapter-kit MCP tools on the server:\n * - `list_tunnel_adapters` (parameterless; status + capabilities, no creds)\n * - `setup_tunnel_provider` (multi-field; fields are union of every\n * configurable provider's declared `setupFields`, all SENSITIVE and never\n * echoed). Async because the field schema is derived from resolved handles\n * (incl. third-party providers discovered on disk).\n */\nexport async function registerTunnelAdapterTools(\n server: McpServer,\n opts: RegisterTunnelAdapterToolsOptions = {},\n): Promise<void> {\n const credsStore = makeTunnelCredsStore(opts.home)\n const ledger = makeSetupLedger(opts.home ? { home: opts.home } : {})\n\n makeListTool<TunnelAdapterInfo>({\n server,\n toolName: \"list_tunnel_adapters\",\n description:\n \"List known tunnel providers with their status (supported/available/\" +\n \"ready), version, and declared capabilities (stableUrl, autostart, \" +\n \"customDomain, requiresAuth, hasApi). Credentials are never returned. \" +\n \"Use `setup_tunnel_provider` to configure a provider that needs creds.\",\n lister: makeTunnelLister({ credsStore, ledger }),\n })\n\n const { validSlugs, fields } = await collectSetupSchema()\n\n makeSetupTool({\n server,\n toolName: \"setup_tunnel_provider\",\n description:\n \"Configure a tunnel provider that requires credentials (e.g. \" +\n \"cloudflare-named or ngrok). Each field is SENSITIVE — stored 0600 and \" +\n \"never echoed back in tool results. Only the fields a given provider \" +\n \"declares are stored.\",\n validSlugs,\n fields,\n onSetup: async (slug: string, fields: Record<string, string>) => {\n // Resolve the chosen provider so its OWN setupFields drive validation —\n // works for built-ins and third-party providers alike.\n const handle = await resolveTunnelProvider(slug)\n const declared = handle?.setupFields\n if (!handle || !declared || declared.length === 0) {\n return { ok: false, hint: `provider '${slug}' is not configurable` }\n }\n\n const missing = declared\n .filter((f) => f.required === true)\n .map((f) => f.name)\n .filter((name) => {\n const v = fields[name]\n return v === undefined || v.length === 0\n })\n if (missing.length > 0) {\n return {\n ok: false,\n hint: `missing required field(s): ${missing.join(\", \")}`,\n }\n }\n\n // Persist only the provider's declared, non-empty fields.\n const creds: TunnelCreds = {}\n for (const f of declared) {\n const v = fields[f.name]\n if (v !== undefined && v.length > 0) creds[f.name] = v\n }\n await credsStore.write(slug, creds)\n\n const now = new Date().toISOString()\n await ledger.write(slug, {\n slug,\n completedAt: now,\n steps: [{ id: \"creds\", completedAt: now }],\n })\n return { ok: true, hint: `${slug} configured — status is now ready` }\n },\n })\n}","/**\n * `WorkspaceFs` — minimal `readFile` / `writeFile` adapter over a\n * workspace directory. Mirrors the `McpWorkspace.filesystem` shape\n * used by `@guilde/mcp` so the daemon can be plugged in as the\n * workspace backend for a Guilde MCP server (via its\n * `loadGuildWorkspace` injection point) without re-shimming.\n *\n * All paths are workspace-relative. Absolute paths are rejected to\n * keep the surface predictable when the daemon binds to a public\n * port.\n */\n\nimport { existsSync } from \"node:fs\"\nimport { mkdir, readFile as fsReadFile, writeFile as fsWriteFile } from \"node:fs/promises\"\nimport { dirname, isAbsolute, join, normalize, relative, resolve } from \"node:path\"\n\nexport interface WorkspaceFs {\n readFile(path: string): Promise<string>\n writeFile(path: string, content: string | Uint8Array): Promise<void>\n exists(path: string): Promise<boolean>\n}\n\nexport interface CreateWorkspaceFsOptions {\n /** Absolute path to the workspace root. */\n workspace: string\n}\n\nexport class WorkspacePathError extends Error {\n constructor(message: string) {\n super(message)\n this.name = \"WorkspacePathError\"\n }\n}\n\nexport function createWorkspaceFs(opts: CreateWorkspaceFsOptions): WorkspaceFs {\n const root = resolve(opts.workspace)\n\n function resolvePath(path: string): string {\n if (typeof path !== \"string\" || path.length === 0) {\n throw new WorkspacePathError(\"path must be a non-empty string\")\n }\n if (isAbsolute(path)) {\n throw new WorkspacePathError(\n \"absolute paths are not allowed; use a workspace-relative path\",\n )\n }\n const joined = normalize(join(root, path))\n const rel = relative(root, joined)\n if (rel.startsWith(\"..\") || isAbsolute(rel)) {\n throw new WorkspacePathError(\n `path escapes the workspace: '${path}'`,\n )\n }\n return joined\n }\n\n return {\n async readFile(path) {\n const abs = resolvePath(path)\n const buf = await fsReadFile(abs)\n return buf.toString(\"utf8\")\n },\n async writeFile(path, content) {\n const abs = resolvePath(path)\n await mkdir(dirname(abs), { recursive: true })\n await fsWriteFile(abs, content)\n },\n async exists(path) {\n try {\n const abs = resolvePath(path)\n return existsSync(abs)\n } catch {\n return false\n }\n },\n }\n}\n","/**\n * `~/.agentproto/providers.json` — the provider API-key store (mode 0600).\n *\n * Distinct from `credentials.json` (host-binding OAuth tokens for\n * `serve --connect`) and from per-adapter `setup[]` tokens. This file holds\n * the LLM/model **provider** keys (anthropic, openrouter, openai, …) that the\n * model gateways in spawned agents read from the environment.\n *\n * Why a store at all: before this, the only way to give the daemon a provider\n * key was an ambient `export FOO_API_KEY=…` in whatever shell launched\n * `serve`. That's invisible, easy to forget, and per-shell. Storing the keys\n * here (0600, same-user-only) lets `serve` inject them at boot — set once,\n * works for every daemon. Explicit env still wins (see injectProviderKeysIntoEnv).\n *\n * Keys never leave this file except into the daemon's own process env; they\n * are never logged. A browser-loaded localhost page can't read a 0600 file —\n * the same defence the runtime.json bearer token relies on.\n */\n\nimport { mkdir, readFile, writeFile } from \"node:fs/promises\"\nimport { homedir } from \"node:os\"\nimport { join, resolve } from \"node:path\"\n\n/**\n * Canonical provider → environment-variable name. The spawned model gateways\n * (Mastra in mastra-agent, hermes/opencode's routers) read the provider key\n * from these env names. Aligned with the adapter manifests' `models.env`\n * maps + the common SDK conventions.\n */\nexport const PROVIDER_ENV_VARS: Readonly<Record<string, string>> = {\n anthropic: \"ANTHROPIC_API_KEY\",\n openrouter: \"OPENROUTER_API_KEY\",\n openai: \"OPENAI_API_KEY\",\n google: \"GOOGLE_GENERATIVE_AI_API_KEY\",\n groq: \"GROQ_API_KEY\",\n mistral: \"MISTRAL_API_KEY\",\n // Vercel AI Gateway — a gateway provider, like openrouter, that fronts many\n // upstream model families behind one key.\n \"vercel-ai-gateway\": \"AI_GATEWAY_API_KEY\",\n}\n\nexport type KnownProvider = keyof typeof PROVIDER_ENV_VARS\n\nexport interface ProviderEntry {\n /** The provider API key (or gateway key). */\n apiKey: string\n /** Optional custom base URL (self-hosted / proxy). */\n baseUrl?: string\n /** Wall-clock ISO timestamp the key was last set. */\n updatedAt: string\n}\n\nexport interface ProvidersFile {\n version: 1\n providers: Record<string, ProviderEntry>\n}\n\n/** Fresh empty file each call — never share the `providers` object, or a\n * later `setProviderKey` mutation leaks into every other load in-process. */\nfunction emptyFile(): ProvidersFile {\n return { version: 1, providers: {} }\n}\n\nexport function providersPath(): string {\n return resolve(homedir(), \".agentproto\", \"providers.json\")\n}\n\n/** Resolve the env-var name for a provider (canonical map, else\n * `<PROVIDER>_API_KEY` upper-snake fallback so new providers still work). */\nexport function providerEnvVar(provider: string): string {\n return (\n PROVIDER_ENV_VARS[provider] ??\n `${provider.toUpperCase().replace(/[^A-Z0-9]+/g, \"_\")}_API_KEY`\n )\n}\n\nexport async function loadProviders(): Promise<ProvidersFile> {\n try {\n const raw = await readFile(providersPath(), \"utf8\")\n const parsed = JSON.parse(raw) as unknown\n if (\n !parsed ||\n typeof parsed !== \"object\" ||\n !(\"providers\" in parsed) ||\n typeof (parsed as Record<string, unknown>).providers !== \"object\" ||\n (parsed as Record<string, unknown>).providers === null\n ) {\n return emptyFile()\n }\n return {\n version: 1,\n providers: (parsed as ProvidersFile).providers,\n }\n } catch {\n return emptyFile() // ENOENT / malformed → empty\n }\n}\n\nasync function writeProviders(file: ProvidersFile): Promise<void> {\n const dir = join(homedir(), \".agentproto\")\n await mkdir(dir, { recursive: true })\n // mode 0600 so other local users can't read the keys.\n await writeFile(providersPath(), JSON.stringify(file, null, 2) + \"\\n\", {\n encoding: \"utf8\",\n mode: 0o600,\n })\n}\n\n/** Set (or replace) a provider's key. Returns the env-var it maps to. */\nexport async function setProviderKey(\n provider: string,\n apiKey: string,\n baseUrl?: string,\n): Promise<string> {\n const file = await loadProviders()\n file.providers[provider] = {\n apiKey,\n ...(baseUrl ? { baseUrl } : {}),\n updatedAt: new Date().toISOString(),\n }\n await writeProviders(file)\n return providerEnvVar(provider)\n}\n\n/** Remove a provider's key. Returns true if it existed. */\nexport async function removeProviderKey(provider: string): Promise<boolean> {\n const file = await loadProviders()\n if (!(provider in file.providers)) return false\n delete file.providers[provider]\n await writeProviders(file)\n return true\n}\n\n/**\n * Inject stored provider keys into a target env (default `process.env`).\n * **Explicit env always wins** — a var already set is never overwritten, so a\n * one-off `FOO_API_KEY=… serve` or a CI secret takes precedence over the\n * store. Returns the list of provider names actually injected (for a boot log\n * that names providers, never values).\n */\nexport async function injectProviderKeysIntoEnv(\n env: NodeJS.ProcessEnv = process.env,\n): Promise<string[]> {\n const file = await loadProviders()\n const injected: string[] = []\n for (const [provider, entry] of Object.entries(file.providers)) {\n if (!entry?.apiKey) continue\n const name = providerEnvVar(provider)\n if (env[name]) continue // explicit env wins\n env[name] = entry.apiKey\n if (entry.baseUrl) env[`${provider.toUpperCase().replace(/[^A-Z0-9]+/g, \"_\")}_BASE_URL`] = entry.baseUrl\n injected.push(provider)\n }\n return injected\n}\n","/**\n * @agentproto/runtime — long-running gateway around an agentproto\n * workspace dir.\n *\n * Composes:\n * - `@agentproto/mcp-server` (CRUD verbs over registered specs)\n * - HTTP transport (Streamable HTTP) on a configurable port\n * - HEARTBEAT.md autonomy loop\n * - Append-only conversation persistence (`conversations/<id>.md`)\n * - Workspace filesystem adapter (compatible with the\n * `McpWorkspace.filesystem` shape used by `@guilde/mcp`)\n *\n * Single entry point: `createGateway(opts)`. Returns a handle with\n * `url` and `stop()` — the rest of the surface lives on the HTTP\n * server.\n */\n\nimport { randomUUID } from \"node:crypto\"\nimport { existsSync } from \"node:fs\"\nimport { readFile } from \"node:fs/promises\"\nimport { join, resolve } from \"node:path\"\nimport { createMcpServer } from \"@agentproto/mcp-server\"\nimport type { DoctypeSpec } from \"@agentproto/manifest\"\n\nimport { writeRuntimeMeta } from \"./agentproto-dir.js\"\nimport { registerCommandTools } from \"./command-tools.js\"\nimport { fileConversationStore } from \"./conversations.js\"\nimport { createRuntimeEvents } from \"./events.js\"\nimport { registerFsTools } from \"./fs-tools.js\"\nimport { registerSessionTools, registerExportSessionTool } from \"./session-tools.js\"\nimport {\n registerBrowserTools,\n type BrowserAdapterResolver,\n type BrowserAdapterLister,\n} from \"./browser-tools.js\"\nimport { registerMcpApps } from \"./mcp-apps-adapter.js\"\nimport { makeSessionsPanelApp } from \"./sessions-panel-app.js\"\nimport {\n makeAgentsOverviewApp,\n registerSummarizeSessionTool,\n} from \"./agents-overview-app.js\"\nimport { makeBureauSessionsApp } from \"./bureau-sessions-app.js\"\nimport { startHeartbeat, type BuildHeartbeatAgent } from \"./heartbeat.js\"\nimport {\n startHttpServer,\n type AuthOptions,\n type AgentAdapterResolver,\n type AgentAdapterLister,\n} from \"./http-server.js\"\nimport {\n createSessionsRegistry,\n type SessionsRegistry,\n type PtyFactory,\n} from \"./sessions.js\"\nimport { McpProxyRegistry } from \"./mcp-proxy.js\"\nimport { registerOrchestrationTools } from \"./orchestration-tools.js\"\nimport { createSessionEventBus } from \"./session-event-bus.js\"\nimport { createEventRing } from \"./event-ring.js\"\nimport { createWebhookNotifier } from \"./webhook-notifier.js\"\nimport { createRoutineRunner } from \"./routine-runner.js\"\nimport { createCompletionPolicySupervisor } from \"./supervisor.js\"\nimport { createInboundWatcher } from \"./inbound-watcher.js\"\nexport type {\n WatcherStartInput,\n WatcherDescriptor,\n InboundWatcher,\n} from \"./inbound-watcher.js\"\nimport {\n createScopeTokenRegistry,\n createOrchestratorMcpServerFactory,\n createOrchestratorInjector,\n type OrchestratorScope,\n} from \"./orchestrator-gateway.js\"\n\nexport type {\n AgentAdapterResolver,\n AgentAdapterLister,\n AdapterListEntry,\n} from \"./http-server.js\"\nexport type { BrowserAdapterResolver, BrowserAdapterLister, BrowserAdapterInfo } from \"./browser-tools.js\"\nexport { makeBrowserAdapterLister } from \"./browser-adapters.js\"\nexport type { BrowserAdapterHandle } from \"./browser-adapters.js\"\nexport type {\n AgentSessionLike,\n AgentStreamEvent,\n SessionDescriptor,\n SessionKind,\n SessionStatus,\n SpawnSessionInput,\n SpawnAgentInput,\n SessionsRegistry,\n RegisterBrowserInput,\n RegisterSessionInput,\n} from \"./sessions.js\"\nimport { RemoteController } from \"./remote-controller.js\"\nimport { registerRemoteTools } from \"./remote-tools.js\"\nimport { TunnelRegistry } from \"./tunnel-registry.js\"\nimport { registerTunnelTools } from \"./tunnel-tools.js\"\nimport {\n registerTunnelAdapterTools,\n makeTunnelCredsStore,\n} from \"./tunnel-adapters.js\"\nimport { createWorkspaceFs, type WorkspaceFs } from \"./workspace-fs.js\"\n\nexport type { ConversationStore, ConversationMeta, ConversationTurn } from \"./conversations.js\"\nexport type { HeartbeatRunner, BuildHeartbeatAgent, HeartbeatAgent } from \"./heartbeat.js\"\nexport type { RuntimeEvent, RuntimeEvents } from \"./events.js\"\nexport type { WorkspaceFs } from \"./workspace-fs.js\"\nexport type { TunnelDescriptor, TunnelStatus, TunnelProvider } from \"./tunnel-registry.js\"\nexport { parseDuration } from \"./heartbeat.js\"\nexport { createWorkspaceFs } from \"./workspace-fs.js\"\nexport {\n sweepStaleRuntimeMetas,\n unlinkRuntimeMeta,\n readRuntimeMeta,\n daemonRegistryDir,\n readDaemonRegistry,\n sweepStaleDaemonRegistry,\n writeDaemonRegistryEntry,\n unlinkDaemonRegistryEntry,\n type RuntimeMeta,\n} from \"./agentproto-dir.js\"\nexport { fileConversationStore } from \"./conversations.js\"\nexport {\n loadProviders,\n setProviderKey,\n removeProviderKey,\n injectProviderKeysIntoEnv,\n providerEnvVar,\n providersPath,\n PROVIDER_ENV_VARS,\n type ProviderEntry,\n type ProvidersFile,\n} from \"./providers-store.js\"\nexport {\n DEFAULT_ORCHESTRATOR_TOOLS,\n narrowOrchestratorTools,\n createScopeTokenRegistry,\n createOrchestratorMcpServerFactory,\n createOrchestratorInjector,\n type OrchestratorScope,\n type ScopeTokenRegistry,\n type OrchestratorMcpServerFactory,\n type OrchestratorGatewayDeps,\n type OrchestratorInjector,\n type OrchestratorInjection,\n type OrchestratorInjectorDeps,\n} from \"./orchestrator-gateway.js\"\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype AnySpec = DoctypeSpec<any, any>\n\nexport interface CreateGatewayOptions {\n /** Absolute path to the workspace dir. */\n workspace: string\n /** AIP doctype specs to expose as MCP CRUD verbs. */\n specs: readonly AnySpec[]\n /** Port to bind. Default 18790. */\n port?: number\n /** Bind host. Default `127.0.0.1` (loopback). Set `0.0.0.0` for LAN. */\n bind?: string\n /** Auth mode. Default `none` (safe only on loopback). */\n auth?: AuthOptions\n /**\n * Resolves a heartbeat-runnable agent from its workspace id.\n * Required for HEARTBEAT.md to do anything; without it ticks emit\n * `heartbeat-error` events instead of generating.\n */\n buildAgent?: BuildHeartbeatAgent\n /** Server name advertised over MCP. */\n name?: string\n /** Server version advertised over MCP. */\n version?: string\n /**\n * Run BOOT.md once at startup. Pass `false` to disable. Defaults to\n * `true`. The boot file is plain markdown — frontmatter-free; the\n * agent named in `defaultBootAgent` (or skipped if unset) gets the\n * body as a single prompt and the reply is appended to a `boot-<iso>`\n * conversation.\n */\n boot?: boolean\n /** Agent id used for BOOT.md if no per-file frontmatter. */\n defaultBootAgent?: string\n /** Optional adapter resolver — when provided, enables\n * `POST /sessions/agent` (long-running agent CLIs like\n * claude-code / hermes via the @agentproto/cli adapter system).\n * Without this, /sessions still works for raw `argv` spawns. */\n resolveAgentAdapter?: AgentAdapterResolver\n /** Optional adapter lister — when provided, enables\n * `GET /adapters` HTTP route + `list_adapters` MCP tool so UIs\n * can discover what's installed on the host. */\n listAgentAdapters?: AgentAdapterLister\n /** Optional browser adapter resolver — when provided, enables the\n * `start_browser` MCP tool (launches Camofox / Bureau / Chromium). */\n resolveBrowserAdapter?: BrowserAdapterResolver\n /** Optional browser adapter lister — when provided, enables the\n * `list_adapter_browsers` MCP tool. */\n listBrowserAdapters?: BrowserAdapterLister\n /** Optional PTY factory (node-pty wrapper, typically from the cli\n * layer's `loadNodePtyFactory()`). When provided, enables\n * `POST /sessions/terminal`, the `start_terminal_session` MCP\n * tool family, and the `/sessions/:id/pty` WebSocket. Without it,\n * those routes return 501 / the MCP tools aren't registered. */\n spawnPty?: PtyFactory\n /** Override the per-boot bearer token. Default: `randomUUID()`.\n * Tests can pin a known value; production should always let\n * the gateway generate fresh. The token is written into\n * `<workspace>/.agentproto/runtime.json` (mode 0600) and required\n * on mutating `/sessions/*` routes + the PTY WS upgrade. */\n token?: string\n /** Trusted browser origins allowed to drive mutating routes\n * without a bearer token. See `RuntimeHttpServerOptions.allowedOrigins`\n * for match semantics. Default: localhost on any port. */\n allowedOrigins?: readonly string[]\n /** When true, drop the localhost-wildcard defaults — only the\n * explicit `allowedOrigins` list is honoured. */\n strictOrigins?: boolean\n}\n\nexport interface GatewayHandle {\n url: string\n workspace: string\n workspaceFs: WorkspaceFs\n registered: readonly string[]\n /** Sessions registry — exposed so MCP tools / external spawners\n * inside the same process can register their child processes for\n * visibility through /sessions and the CLI TUI. */\n sessions: SessionsRegistry\n /** Tunnel registry — manages public cloudflared tunnels for any\n * local port. Exposed so embedding hosts can open tunnels\n * programmatically without going through the HTTP/MCP surface. */\n tunnels: TunnelRegistry\n /** Per-boot bearer token required on mutating /sessions/* routes\n * + WS PTY upgrades. Exposed so an embedding host (e.g. the CLI\n * shell that hosts the gateway in-process) can pass it to child\n * tools without re-reading the runtime.json file. */\n token: string\n /** Mint a scope-token for the scoped orchestrator sub-gateway\n * (`/mcp/orchestrator`). The returned `token` gates that endpoint\n * and `tools` is the effective allowlist (⊆ the default orchestrator\n * subset). WP3 will call this at spawn time and inject the URL into\n * the child's `mcpServers`; for WP2 it's the internal primitive. */\n mintOrchestratorScope(opts?: {\n tools?: readonly string[]\n }): OrchestratorScope\n stop(): Promise<void>\n}\n\n/**\n * Spin up the gateway. Order:\n * 1. Build MCP server + load AIP-40 extensions\n * 2. Build conversation store + workspace fs adapter\n * 3. (optional) Run BOOT.md once\n * 4. Start HTTP server\n * 5. Start heartbeat ticker\n *\n * `stop()` reverses 4–5 (heartbeat first, then HTTP). The MCP server\n * is owned by the HTTP server's per-session transports and is closed\n * implicitly when those close.\n */\nexport async function createGateway(\n opts: CreateGatewayOptions,\n): Promise<GatewayHandle> {\n const workspace = resolve(opts.workspace)\n if (!existsSync(workspace)) {\n throw new Error(`runtime: workspace dir does not exist: ${workspace}`)\n }\n const port = opts.port ?? 18790\n\n const events = createRuntimeEvents()\n const conversations = fileConversationStore({ workspace })\n const workspaceFs = createWorkspaceFs({ workspace })\n\n // Singleton controller for \"publish to the internet\" state. Created\n // disabled — auth stays `mode: \"none\"` until `remote_enable` is\n // called. Tunnel logs flow through the events stream so `/events`\n // subscribers see cloudflared chatter.\n const remote = new RemoteController({\n workspace,\n port,\n onLog: line =>\n events.emit({\n type: \"remote-log\",\n at: new Date().toISOString(),\n line,\n }),\n })\n\n // Multi-tunnel registry — independent from RemoteController. Manages\n // the general \"create a public URL for any local port\" surface\n // (create_tunnel / list_tunnels / stop_tunnel MCP tools + /tunnels HTTP\n // routes). Logs flow through the same events stream.\n // Shared tunnel creds store (~/.agentproto/tunnel-creds/, 0600) — lets the\n // registry rebuild a provider that keeps its secrets off the descriptor\n // (ngrok authtoken, third-party creds) when restoring on boot / creating.\n const tunnelCredsStore = makeTunnelCredsStore()\n const tunnels = new TunnelRegistry({\n workspace,\n onLog: line =>\n events.emit({\n type: \"remote-log\",\n at: new Date().toISOString(),\n line,\n }),\n readCreds: slug => tunnelCredsStore.read(slug),\n })\n // Relaunch any `autostart` (named) tunnels that were live before this\n // daemon restarted. Non-blocking — boot must not wait on cloudflared,\n // and a failed restore leaves that one tunnel `error` without gating\n // the rest of the gateway.\n void tunnels.restoreOnBoot().catch(() => {\n // restoreOnBoot already logs per-tunnel failures via onLog.\n })\n\n // Build a server once eagerly so we can capture `registered` for\n // `/health`. The server is NOT used for serving — every `/mcp`\n // request gets its own freshly-constructed pair, mirroring the\n // SDK's official stateless pattern. See the comment on\n // `RuntimeHttpServerOptions.mcpServerFactory` for why.\n const { registered } = await createMcpServer({\n specs: opts.specs,\n workspace,\n name: opts.name ?? \"agentproto-runtime\",\n version: opts.version ?? \"0.1.0-alpha\",\n })\n\n // Event bus + ring for orchestration tools (poll_events / wait_for_any).\n // Declared before the sessions registry so we can pass the bus into it.\n const sessionEvents = createSessionEventBus()\n const eventRing = createEventRing()\n // Wire the ring so every session:* event is buffered for poll_events.\n eventRing.wire(sessionEvents)\n // Wire the webhook notifier so per-session and global URLs are\n // notified on turn-end / awaiting-input / exited events.\n const webhookNotifier = createWebhookNotifier()\n sessionEvents.onAny(ev => webhookNotifier.onSessionEvent(ev))\n // Unregister per-session URLs on exit so the notifier map doesn't\n // leak memory across sessions.\n sessionEvents.on(\"session:exited\", ev => {\n webhookNotifier.unregister(ev.sessionId)\n })\n\n // Sessions registry — single instance per gateway, captured by\n // the per-request mcpServerFactory closure below + handed to\n // startHttpServer for the /sessions HTTP routes. Declared here\n // (above the factory) so its identifier is visible at closure-\n // build time, even though the factory only invokes later.\n const sessions = createSessionsRegistry({\n sessionEvents,\n ...(opts.spawnPty ? { spawnPty: opts.spawnPty } : {}),\n // Resume hook: when a prompt arrives for a dead agent-cli row\n // (typical after daemon restart), the registry calls back into\n // the adapter resolver to re-create the AgentSession with\n // `resumeSessionId = adapterSessionId`. ACP semantics: the\n // upstream provider reattaches to the prior conversation.\n // Unwired (no resolveAgentAdapter) → legacy \"not an agent\n // session\" error, user must spawn fresh.\n ...(opts.resolveAgentAdapter\n ? {\n resumeAgent: async ({\n adapterSlug,\n cwd,\n resumeSessionId,\n mcpServers,\n }) => {\n const adapter = await opts.resolveAgentAdapter!(adapterSlug)\n if (!adapter) return null\n try {\n return await adapter.startSession({\n cwd,\n resumeSessionId,\n // Re-mount the persisted spawn-time toolset on resume\n // (orchestrator WP1) — closes the gap where re-spawn\n // dropped mcpServers.\n ...(mcpServers ? { mcpServers } : {}),\n })\n } catch (err) {\n console.warn(\n `[agentproto] resumeAgent('${adapterSlug}', ${resumeSessionId}) failed: ${\n err instanceof Error ? err.message : String(err)\n }`\n )\n return null\n }\n },\n }\n : {}),\n })\n\n // Completion-policy supervisor — watches sessions and runs shell gates.\n // Declared after `sessions` so it can resolve session cwd at gate time.\n const supervisor = createCompletionPolicySupervisor({\n registry: sessions,\n sessionEvents,\n workspace,\n persist: true,\n // WP6: daemon-wide cap on policies concurrently gating/acting. Excess\n // queue (FIFO) until a slot frees. Override via AGENTPROTO_POLICY_CONCURRENCY.\n concurrencyCap: (() => {\n const raw = process.env.AGENTPROTO_POLICY_CONCURRENCY\n const n = raw ? Number.parseInt(raw, 10) : NaN\n return Number.isFinite(n) && n > 0 ? n : undefined\n })(),\n // WP7: judge-agent gate spawns a short-lived agent via the same resolver\n // start_agent_session uses. Absent → judge gates fail-safe (FAIL).\n ...(opts.resolveAgentAdapter\n ? { resolveAgentAdapter: opts.resolveAgentAdapter }\n : {}),\n })\n\n // Routine runner — singleton per daemon, shared across all MCP connections.\n // Persists run state to ~/.agentproto/routine-runs.json so runs survive\n // daemon restarts (interrupted runs are marked \"failed\" on load).\n // Declared after `sessions` and `supervisor` so it shares the same\n // registry + event bus. Only wired when `resolveAgentAdapter` is\n // available (routine steps need to spawn agent sessions).\n const routineRunner = opts.resolveAgentAdapter\n ? createRoutineRunner({\n registry: sessions,\n sessionEvents,\n resolveAgentAdapter: opts.resolveAgentAdapter,\n webhookNotifier,\n persist: true,\n })\n : undefined\n\n // Per-boot bearer token. Required on mutating /sessions/* routes\n // and on the WS upgrade for /sessions/:id/pty. Persisted to\n // runtime.json (mode 0600) so the same-user CLI can read it; a\n // browser-loaded localhost page can't.\n const token = opts.token ?? randomUUID()\n\n // MCP proxy — single registry that holds open Client connections\n // to every imported MCP server. The per-request mcpServerFactory\n // captures it so each /mcp request reuses the same upstream\n // sessions instead of re-spawning stdio children.\n const mcpProxy = new McpProxyRegistry()\n\n // Inbound watcher — polls an agentpush source on a timer and spawns\n // one agent per new contact_ref. Wired when an adapter resolver is\n // available (otherwise the watcher would have nowhere to spawn).\n const inboundWatcher =\n opts.resolveAgentAdapter\n ? createInboundWatcher({\n mcpProxy,\n registry: sessions,\n resolveAgentAdapter: opts.resolveAgentAdapter,\n persist: true,\n })\n : undefined\n\n // Scope-token registry (WP2) — mints/validates the per-child tokens\n // that gate `/mcp/orchestrator` and carry each orchestrator's identity\n // (owner session, depth, tools, limits — WP4). The injector + scoped\n // factory below both close over it.\n const scopeTokens = createScopeTokenRegistry()\n\n // Orchestrator auto-injection (WP3). Closed over the scope-token\n // registry + the session-event bus + the HTTP port: when\n // `start_agent_session` is called with `orchestrator`, this mints a\n // scoped token, builds the `mcpServers` entry pointing the child at\n // `/mcp/orchestrator?scope=<token>` on the daemon's own loopback\n // port, and revokes the token on the child's `session:exited`. The\n // port is the daemon's configured listener port (`startHttpServer`\n // binds `opts.port` directly), reachable by the co-located child\n // over loopback.\n // The injected entry is named \"agentproto\" (the default) so the\n // child's orchestration tools surface under a stable namespace,\n // independent of the daemon's advertised server name.\n // Defined BEFORE the scoped factory so the factory can hand it to the\n // scoped server's `start_agent_session` — that's what lets a child\n // orchestrator recursively spawn its OWN sub-orchestrators (WP4),\n // bounded by depth/quota/tools inheritance.\n const orchestratorInjector = createOrchestratorInjector({\n scopeTokens,\n sessionEvents,\n port,\n })\n\n // Scoped orchestrator sub-gateway (WP2). The scope-token registry\n // mints/validates per-child tokens; the factory builds a scoped MCP\n // server exposing only the curated orchestration subset for a verified\n // scope. Mounted by the HTTP server at `/mcp/orchestrator` (no\n // loopback bypass — token required). The verified scope is also the\n // calling orchestrator's identity, so the scoped server enforces the\n // WP4 depth/quota guards + subtree scoping against it.\n const orchestratorMcpServerFactory = createOrchestratorMcpServerFactory({\n workspace,\n name: opts.name ?? \"agentproto-runtime\",\n version: opts.version ?? \"0.1.0-alpha\",\n registry: sessions,\n sessionEvents,\n eventRing,\n supervisor,\n orchestratorInjector,\n webhookNotifier,\n ...(opts.resolveAgentAdapter\n ? { resolveAgentAdapter: opts.resolveAgentAdapter }\n : {}),\n ...(opts.listAgentAdapters\n ? { listAgentAdapters: opts.listAgentAdapters }\n : {}),\n })\n\n const mcpServerFactory = async () => {\n const { server } = await createMcpServer({\n specs: opts.specs,\n workspace,\n name: opts.name ?? \"agentproto-runtime\",\n version: opts.version ?? \"0.1.0-alpha\",\n })\n // Canonical filesystem tools so remote MCP clients (cloud\n // workspace-providers, IDEs, ad-hoc tooling) can read/write the\n // workspace without each implementing AIP-aware glue. Names match\n // `@modelcontextprotocol/server-filesystem` for drop-in compat.\n registerFsTools(server, { workspace })\n // Subprocess execution — the runtime's superpower for cloud\n // agents. Any allowlisted CLI on the user's machine (claude, gh,\n // pnpm, …) is reachable via `execute_command`. Allowlist lives at\n // `.agentproto/allowed-commands.json`; default-deny.\n registerCommandTools(server, { workspace })\n // Remote-tunnel lifecycle. The controller is a singleton on the\n // gateway, so registering its tools per-request is just rebinding\n // the same closures — the underlying state lives in `remote`.\n registerRemoteTools(server, { controller: remote })\n // Agent-session orchestration — operators (Mastra agents in\n // cloud Guilde, Claude Code as a sub-agent, …) drive long-running\n // claude/hermes/aider sessions on the user's machine through\n // these MCP tools. The registry + adapter resolver are\n // singletons on the gateway, same closure-rebind pattern.\n registerSessionTools(server, {\n registry: sessions,\n mcpProxy,\n ptyEnabled: opts.spawnPty != null,\n buildOrchestratorMcp: orchestratorInjector,\n webhookNotifier,\n ...(opts.resolveAgentAdapter\n ? { resolveAgentAdapter: opts.resolveAgentAdapter }\n : {}),\n ...(opts.listAgentAdapters\n ? { listAgentAdapters: opts.listAgentAdapters }\n : {}),\n })\n registerBrowserTools(server, {\n registry: sessions,\n ...(opts.resolveBrowserAdapter\n ? { resolveBrowserAdapter: opts.resolveBrowserAdapter }\n : {}),\n ...(opts.listBrowserAdapters\n ? { listBrowserAdapters: opts.listBrowserAdapters }\n : {}),\n })\n registerOrchestrationTools(server, {\n registry: sessions,\n sessionEvents,\n eventRing,\n supervisor,\n ...(routineRunner ? { routineRunner } : {}),\n ...(inboundWatcher ? { inboundWatcher } : {}),\n })\n // MCP Apps — agentproto_sessions panel via the AgnoMcpApp adapter.\n // Tool: agentproto_sessions Resource: ui://agentproto_sessions/view\n const listSessionsFiltered = (filter?: \"running\" | \"all\") => {\n let rows = sessions.list()\n if (filter === \"running\") {\n rows = rows.filter(s => s.status === \"running\" || s.status === \"starting\")\n }\n return rows\n }\n registerMcpApps(server, [\n makeSessionsPanelApp({ listSessions: listSessionsFiltered }),\n makeAgentsOverviewApp({ listSessions: listSessionsFiltered }),\n makeBureauSessionsApp({ listSessions: listSessionsFiltered }),\n ])\n // Server-side per-session summariser backing the agents-overview panel.\n // Heuristic today (no LLM in @agentproto/runtime) — see agents-overview-app.ts.\n registerSummarizeSessionTool(server, {\n getSession: (id) => sessions.get(id),\n tailLines: (id, lastN) => {\n // Same source as get_agent_session_output: attach replays the ring\n // buffer synchronously, then we unsubscribe immediately.\n const lines: string[] = []\n const unsub = sessions.attach(id, (line) => { lines.push(line) })\n if (unsub) unsub()\n return lines.slice(-lastN)\n },\n })\n // Transcript exporter — reads the adapter's native persistence\n // (claude-code JSONL / hermes SQLite) and renders a clean markdown or\n // JSON transcript. Co-located with the session tools; registry access\n // mirrors the summarise_session pattern above.\n registerExportSessionTool(server, { registry: sessions })\n // Multi-tunnel tools — same closure-rebind pattern.\n registerTunnelTools(server, { registry: tunnels })\n // Tunnel adapter introspection/setup, riding on @agentproto/adapter-kit\n // (list_tunnel_adapters + setup_tunnel_provider). Stateless wrt the\n // gateway — creds/ledger live under ~/.agentproto.\n await registerTunnelAdapterTools(server, {})\n return server\n }\n\n // ── boot ─────────────────────────────────────────────────────────\n if (opts.boot !== false) {\n await runBoot(workspace, opts, conversations, events).catch((err) => {\n events.emit({\n type: \"heartbeat-error\",\n at: new Date().toISOString(),\n agent: opts.defaultBootAgent,\n error: `BOOT.md failed: ${err instanceof Error ? err.message : String(err)}`,\n })\n })\n }\n\n const heartbeat = startHeartbeat({\n workspace,\n conversations,\n events,\n buildAgent: opts.buildAgent ?? noopBuildAgent,\n })\n\n const http = await startHttpServer({\n port,\n bind: opts.bind,\n // Auth is read on every request via this getter. `opts.auth`\n // (when provided) is the startup default and represents the\n // operator's intent — bearer-only deployments stay bearer-only\n // even when no remote tunnel is up. The controller's auth wins\n // once a tunnel is enabled (it issues a fresh token); on disable\n // we fall back to `opts.auth` if set, otherwise `mode: \"none\"`.\n auth: () => {\n const remoteAuth = remote.readAuth()\n if (remoteAuth.mode === \"bearer\") return remoteAuth\n return opts.auth ?? { mode: \"none\" }\n },\n mcpServerFactory,\n orchestratorMcpServerFactory,\n verifyOrchestratorScope: scopeTokens.verify,\n conversations,\n events,\n heartbeat,\n sessions,\n mcpProxy,\n token,\n ptyEnabled: opts.spawnPty != null,\n tunnels,\n ...(opts.allowedOrigins ? { allowedOrigins: opts.allowedOrigins } : {}),\n ...(opts.strictOrigins ? { strictOrigins: true } : {}),\n ...(opts.resolveAgentAdapter\n ? { resolveAgentAdapter: opts.resolveAgentAdapter }\n : {}),\n ...(opts.listAgentAdapters\n ? { listAgentAdapters: opts.listAgentAdapters }\n : {}),\n ...(opts.resolveBrowserAdapter\n ? { resolveBrowserAdapter: opts.resolveBrowserAdapter }\n : {}),\n ...(opts.listBrowserAdapters\n ? { listBrowserAdapters: opts.listBrowserAdapters }\n : {}),\n meta: { workspace, registered },\n })\n\n heartbeat.start()\n events.emit({\n type: \"boot\",\n at: new Date().toISOString(),\n workspace,\n registered,\n })\n\n // Record a snapshot of the running config so external tooling /\n // shell users can introspect a live gateway via\n // `cat <workspace>/.agentproto/runtime.json`. Best-effort — failure\n // here doesn't gate the gateway being functional.\n void writeRuntimeMeta(workspace, {\n workspace,\n port,\n bind: opts.bind ?? \"127.0.0.1\",\n pid: process.pid,\n startedAt: new Date().toISOString(),\n name: opts.name ?? \"agentproto-runtime\",\n registered,\n token,\n })\n\n return {\n url: http.url,\n workspace,\n workspaceFs,\n registered,\n sessions,\n tunnels,\n token,\n mintOrchestratorScope: scopeTokens.mint,\n async stop() {\n heartbeat.stop()\n // Flush inbound-watcher cursor state before sessions shut down.\n inboundWatcher?.shutdown()\n // Flush completion-policy state before sessions shut down so\n // policies referencing live sessions are persisted with their\n // current status (not \"killed\" sessions).\n supervisor.shutdown()\n // Kill all live sessions before tearing down HTTP — otherwise\n // long-running children inherit the daemon's listening socket\n // and stay around as zombies after the parent exits.\n sessions.shutdown()\n // Close upstream MCP clients (their stdio children would\n // otherwise leak the same way).\n await mcpProxy.closeAll()\n // Stop all active tunnels (TunnelRegistry) then the remote\n // controller's single-gateway tunnel. Both before HTTP so\n // cloudflared doesn't briefly proxy to a dead port.\n await tunnels.shutdown()\n await remote.shutdown()\n await http.stop()\n },\n }\n}\n\n// ── helpers ──────────────────────────────────────────────────────────\n\nconst noopBuildAgent: BuildHeartbeatAgent = async () => null\n\nasync function runBoot(\n workspace: string,\n opts: CreateGatewayOptions,\n conversations: import(\"./conversations.js\").ConversationStore,\n events: import(\"./events.js\").RuntimeEvents,\n): Promise<void> {\n const path = join(workspace, \"BOOT.md\")\n if (!existsSync(path)) return\n const body = (await readFile(path, \"utf8\")).trim()\n if (!body) return\n if (!opts.buildAgent || !opts.defaultBootAgent) return\n\n const agent = await opts.buildAgent(opts.defaultBootAgent)\n if (!agent) return\n\n const conversationId = `boot-${new Date().toISOString().slice(0, 19).replace(/[:.]/g, \"-\")}`\n await conversations.open(conversationId, { agent: opts.defaultBootAgent })\n await conversations.appendTurn(conversationId, \"user\", body, {\n attribution: \"boot\",\n })\n const reply = await agent.generate(body)\n await conversations.appendTurn(conversationId, \"assistant\", reply.text, {\n attribution: opts.defaultBootAgent,\n })\n events.emit({\n type: \"heartbeat-fired\",\n at: new Date().toISOString(),\n agent: opts.defaultBootAgent,\n conversationId,\n prompt: body,\n reply: reply.text,\n durationMs: 0,\n })\n}\n"]}