@dtelecom/secure-chat-client 0.1.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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/content/protocol.ts","../src/crypto/olm-adapter.ts","../src/device.ts","../src/device_discovery.ts","../src/key_bundle.ts","../src/message_store.ts","../src/outbox.ts","../src/sessions.ts","../src/status.ts","../src/store/web-adapter.ts","../src/transport/http.ts","../src/transport/ws.ts","../src/typing.ts","../src/crypto/fake-adapter.ts","../src/store/memory-adapter.ts","../src/index.ts"],"names":["vodozemac","Account","plaintext","Session","sessionKey","VERSION","CONTENT_PROTOCOL_VERSION","newText"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AASO,IAAM,wBAAA,GAA2B,CAAA;AA+ExC,IAAM,GAAA,GAAM,IAAI,WAAA,EAAY;AAC5B,IAAM,GAAA,GAAM,IAAI,WAAA,EAAY;AAOrB,SAAS,YAAY,KAAA,EAA6B;AACvD,EAAA,IAAI,KAAA,CAAM,MAAM,wBAAA,EAA0B;AACxC,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,yBAAA,EAA4B,KAAA,CAAM,CAAC,CAAA,CAAE,CAAA;AAAA,EACvD;AACA,EAAA,IAAI,CAAC,KAAA,CAAM,EAAA,IAAM,CAAC,MAAM,IAAA,EAAM;AAC5B,IAAA,MAAM,IAAI,MAAM,iCAAiC,CAAA;AAAA,EACnD;AACA,EAAA,OAAO,IAAA,CAAK,UAAU,KAAK,CAAA;AAC7B;AAUO,SAAS,YAAY,SAAA,EAAwC;AAClE,EAAA,IAAI,GAAA;AACJ,EAAA,IAAI;AACF,IAAA,GAAA,GAAM,IAAA,CAAK,MAAM,SAAS,CAAA;AAAA,EAC5B,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,IAAA;AAAA,EACT;AACA,EAAA,IAAI,OAAO,GAAA,KAAQ,QAAA,IAAY,GAAA,KAAQ,MAAM,OAAO,IAAA;AACpD,EAAA,MAAM,GAAA,GAAM,GAAA;AACZ,EAAA,IAAI,OAAO,GAAA,CAAI,CAAA,KAAM,YAAY,GAAA,CAAI,CAAA,GAAI,0BAA0B,OAAO,IAAA;AAC1E,EAAA,IAAI,OAAO,GAAA,CAAI,EAAA,KAAO,YAAY,CAAC,GAAA,CAAI,IAAI,OAAO,IAAA;AAClD,EAAA,IAAI,OAAO,GAAA,CAAI,IAAA,KAAS,QAAA,EAAU,OAAO,IAAA;AACzC,EAAA,IAAI,OAAO,GAAA,CAAI,YAAA,KAAiB,QAAA,EAAU,OAAO,IAAA;AAEjD,EAAA,QAAQ,IAAI,IAAA;AAAM,IAChB,KAAK,MAAA,EAAQ;AACX,MAAA,IAAI,OAAO,GAAA,CAAI,IAAA,KAAS,QAAA,EAAU,OAAO,IAAA;AACzC,MAAA,MAAM,UAAU,OAAO,GAAA,CAAI,OAAA,KAAY,QAAA,GAAW,IAAI,OAAA,GAAU,MAAA;AAChE,MAAA,OAAO;AAAA,QACL,CAAA,EAAG,CAAA;AAAA,QACH,IAAI,GAAA,CAAI,EAAA;AAAA,QACR,IAAA,EAAM,MAAA;AAAA,QACN,cAAc,GAAA,CAAI,YAAA;AAAA,QAClB,MAAM,GAAA,CAAI,IAAA;AAAA,QACV,GAAI,OAAA,KAAY,MAAA,GAAY,EAAE,OAAA,KAAY;AAAC,OAC7C;AAAA,IACF;AAAA,IACA,KAAK,MAAA,EAAQ;AACX,MAAA,IAAI,OAAO,IAAI,QAAA,KAAa,QAAA,IAAY,OAAO,GAAA,CAAI,IAAA,KAAS,UAAU,OAAO,IAAA;AAC7E,MAAA,OAAO;AAAA,QACL,CAAA,EAAG,CAAA;AAAA,QACH,IAAI,GAAA,CAAI,EAAA;AAAA,QACR,IAAA,EAAM,MAAA;AAAA,QACN,cAAc,GAAA,CAAI,YAAA;AAAA,QAClB,UAAU,GAAA,CAAI,QAAA;AAAA,QACd,MAAM,GAAA,CAAI;AAAA,OACZ;AAAA,IACF;AAAA,IACA,KAAK,QAAA,EAAU;AACb,MAAA,IAAI,OAAO,GAAA,CAAI,QAAA,KAAa,QAAA,EAAU,OAAO,IAAA;AAC7C,MAAA,OAAO;AAAA,QACL,CAAA,EAAG,CAAA;AAAA,QACH,IAAI,GAAA,CAAI,EAAA;AAAA,QACR,IAAA,EAAM,QAAA;AAAA,QACN,cAAc,GAAA,CAAI,YAAA;AAAA,QAClB,UAAU,GAAA,CAAI;AAAA,OAChB;AAAA,IACF;AAAA,IACA,KAAK,MAAA,EAAQ;AACX,MAAA,IAAI,OAAO,GAAA,CAAI,MAAA,KAAW,QAAA,EAAU,OAAO,IAAA;AAC3C,MAAA,OAAO;AAAA,QACL,CAAA,EAAG,CAAA;AAAA,QACH,IAAI,GAAA,CAAI,EAAA;AAAA,QACR,IAAA,EAAM,MAAA;AAAA,QACN,cAAc,GAAA,CAAI,YAAA;AAAA,QAClB,QAAQ,GAAA,CAAI;AAAA,OACd;AAAA,IACF;AAAA,IACA,KAAK,UAAA,EAAY;AACf,MAAA,IAAI,CAAC,KAAA,CAAM,OAAA,CAAQ,GAAA,CAAI,GAAG,KAAK,CAAC,GAAA,CAAI,GAAA,CAAI,KAAA,CAAM,CAAC,CAAA,KAAM,OAAO,CAAA,KAAM,QAAQ,GAAG,OAAO,IAAA;AACpF,MAAA,OAAO;AAAA,QACL,CAAA,EAAG,CAAA;AAAA,QACH,IAAI,GAAA,CAAI,EAAA;AAAA,QACR,IAAA,EAAM,UAAA;AAAA,QACN,cAAc,GAAA,CAAI,YAAA;AAAA,QAClB,KAAK,GAAA,CAAI;AAAA,OACX;AAAA,IACF;AAAA,IACA,KAAK,QAAA,EAAU;AACb,MAAA,IAAI,IAAI,KAAA,KAAU,SAAA,IAAa,GAAA,CAAI,KAAA,KAAU,WAAW,OAAO,IAAA;AAC/D,MAAA,OAAO;AAAA,QACL,CAAA,EAAG,CAAA;AAAA,QACH,IAAI,GAAA,CAAI,EAAA;AAAA,QACR,IAAA,EAAM,QAAA;AAAA,QACN,cAAc,GAAA,CAAI,YAAA;AAAA,QAClB,OAAO,GAAA,CAAI;AAAA,OACb;AAAA,IACF;AAAA,IACA,KAAK,UAAA,EAAY;AACf,MAAA,IAAI,OAAO,GAAA,CAAI,YAAA,KAAiB,YAAY,CAAC,GAAA,CAAI,cAAc,OAAO,IAAA;AACtE,MAAA,IAAI,OAAO,GAAA,CAAI,QAAA,KAAa,YAAY,GAAA,CAAI,QAAA,KAAa,MAAM,OAAO,IAAA;AACtE,MAAA,MAAM,QAAQ,WAAA,CAAY,IAAA,CAAK,SAAA,CAAU,GAAA,CAAI,QAAQ,CAAC,CAAA;AACtD,MAAA,IAAI,KAAA,KAAU,MAAM,OAAO,IAAA;AAC3B,MAAA,IAAI,KAAA,CAAM,IAAA,KAAS,MAAA,IAAU,KAAA,CAAM,IAAA,KAAS,MAAA,IACxC,KAAA,CAAM,IAAA,KAAS,QAAA,IAAY,KAAA,CAAM,IAAA,KAAS,MAAA,EAAQ;AACpD,QAAA,OAAO,IAAA;AAAA,MACT;AACA,MAAA,OAAO;AAAA,QACL,CAAA,EAAG,CAAA;AAAA,QACH,IAAI,GAAA,CAAI,EAAA;AAAA,QACR,IAAA,EAAM,UAAA;AAAA,QACN,cAAc,GAAA,CAAI,YAAA;AAAA,QAClB,cAAc,GAAA,CAAI,YAAA;AAAA,QAClB,QAAA,EAAU;AAAA,OACZ;AAAA,IACF;AAAA,IACA;AACE,MAAA,OAAO,IAAA;AAAA;AAEb;AAGO,SAAS,iBAAiB,KAAA,EAAiC;AAChE,EAAA,OAAO,GAAA,CAAI,MAAA,CAAO,WAAA,CAAY,KAAK,CAAC,CAAA;AACtC;AAEO,SAAS,iBAAiB,KAAA,EAAwC;AACvE,EAAA,OAAO,WAAA,CAAY,GAAA,CAAI,MAAA,CAAO,KAAK,CAAC,CAAA;AACtC;AAIA,SAAS,KAAA,GAAgB;AACvB,EAAA,OAAO,UAAA,CAAW,OAAO,UAAA,EAAW;AACtC;AAEO,SAAS,OAAA,CAAQ,MAAc,OAAA,EAA6B;AACjE,EAAA,OAAO;AAAA,IACL,CAAA,EAAG,CAAA;AAAA,IACH,IAAI,KAAA,EAAM;AAAA,IACV,IAAA,EAAM,MAAA;AAAA,IACN,YAAA,EAAc,KAAK,GAAA,EAAI;AAAA,IACvB,IAAA;AAAA,IACA,GAAI,OAAA,KAAY,MAAA,GAAY,EAAE,OAAA,KAAY;AAAC,GAC7C;AACF;AAEO,SAAS,OAAA,CAAQ,UAAkB,IAAA,EAAyB;AACjE,EAAA,OAAO,EAAE,CAAA,EAAG,CAAA,EAAG,EAAA,EAAI,KAAA,EAAM,EAAG,IAAA,EAAM,MAAA,EAAQ,YAAA,EAAc,IAAA,CAAK,GAAA,EAAI,EAAG,UAAU,IAAA,EAAK;AACrF;AAEO,SAAS,UAAU,QAAA,EAA+B;AACvD,EAAA,OAAO,EAAE,CAAA,EAAG,CAAA,EAAG,EAAA,EAAI,KAAA,EAAM,EAAG,IAAA,EAAM,QAAA,EAAU,YAAA,EAAc,IAAA,CAAK,GAAA,EAAI,EAAG,QAAA,EAAS;AACjF;AAEO,SAAS,QAAQ,MAAA,EAA2B;AACjD,EAAA,OAAO,EAAE,CAAA,EAAG,CAAA,EAAG,EAAA,EAAI,KAAA,EAAM,EAAG,IAAA,EAAM,MAAA,EAAQ,YAAA,EAAc,IAAA,CAAK,GAAA,EAAI,EAAG,MAAA,EAAO;AAC7E;AAEO,SAAS,YAAY,GAAA,EAA8B;AACxD,EAAA,OAAO,EAAE,CAAA,EAAG,CAAA,EAAG,EAAA,EAAI,KAAA,EAAM,EAAG,IAAA,EAAM,UAAA,EAAY,YAAA,EAAc,IAAA,CAAK,GAAA,EAAI,EAAG,GAAA,EAAI;AAC9E;AAEO,SAAS,UAAU,KAAA,EAA2C;AACnE,EAAA,OAAO,EAAE,CAAA,EAAG,CAAA,EAAG,EAAA,EAAI,KAAA,EAAM,EAAG,IAAA,EAAM,QAAA,EAAU,YAAA,EAAc,IAAA,CAAK,GAAA,EAAI,EAAG,KAAA,EAAM;AAC9E;AAEO,SAAS,WAAA,CAAY,cAAsB,QAAA,EAA4C;AAC5F,EAAA,OAAO;AAAA,IACL,CAAA,EAAG,CAAA;AAAA,IACH,IAAI,KAAA,EAAM;AAAA,IACV,IAAA,EAAM,UAAA;AAAA,IACN,YAAA,EAAc,KAAK,GAAA,EAAI;AAAA,IACvB,YAAA;AAAA,IACA;AAAA,GACF;AACF;ACtPA,IAAM,eAAA,GAAkB,aAAA;AACxB,IAAM,kBAAA,GAAqB,cAAA;AAa3B,IAAI,eAAA,GAAwC,IAAA;AAC5C,eAAe,eAAA,GAAiC;AAC9C,EAAA,IAAI,iBAAiB,OAAO,eAAA;AAC5B,EAAA,MAAM,GAAA,GAAMA,oBAAA;AACZ,EAAA,IAAI,OAAO,GAAA,CAAI,OAAA,KAAY,UAAA,EAAY;AAErC,IAAA,eAAA,GAAkB,QAAQ,OAAA,EAAQ;AAClC,IAAA,OAAO,eAAA;AAAA,EACT;AACA,EAAA,eAAA,GAAkB,GAAA,CAAI,OAAA,EAAQ,CAAE,IAAA,CAAK,MAAM,MAAS,CAAA;AACpD,EAAA,OAAO,eAAA;AACT;AAEO,IAAM,mBAAN,MAAgD;AAAA,EAIrD,YAAoB,IAAA,EAAyB;AAAzB,IAAA,IAAA,CAAA,IAAA,GAAA,IAAA;AAAA,EAA0B;AAAA,EAA1B,IAAA;AAAA,EAHZ,OAAA,GAA0B,IAAA;AAAA,EAC1B,QAAA,uBAAe,GAAA,EAAqB;AAAA,EAI5C,MAAM,IAAA,GAAsB;AAC1B,IAAA,MAAM,eAAA,EAAgB;AACtB,IAAA,IAAI,KAAK,OAAA,EAAS;AAClB,IAAA,MAAM,UAAU,MAAM,IAAA,CAAK,IAAA,CAAK,KAAA,CAAM,UAAU,eAAe,CAAA;AAC/D,IAAA,IAAI,OAAA,EAAS;AACX,MAAA,IAAA,CAAK,OAAA,GAAUC,iBAAA,CAAQ,UAAA,CAAW,OAAO,CAAA;AAAA,IAC3C;AAAA,EACF;AAAA,EAEA,MAAM,UAAA,GAA+B;AACnC,IAAA,OAAO,KAAK,OAAA,KAAY,IAAA;AAAA,EAC1B;AAAA,EAEA,MAAM,gBAAgB,QAAA,EAAyC;AAC7D,IAAA,IAAI,IAAA,CAAK,OAAA,EAAS,MAAM,IAAI,MAAM,wBAAwB,CAAA;AAC1D,IAAA,MAAM,GAAA,GAAM,IAAIA,iBAAA,EAAQ;AACxB,IAAA,GAAA,CAAI,oBAAoB,QAAQ,CAAA;AAChC,IAAA,GAAA,CAAI,mBAAA,EAAoB;AACxB,IAAA,IAAA,CAAK,OAAA,GAAU,GAAA;AACf,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,WAAA,CAAY,GAAG,CAAA;AACnC,IAAA,GAAA,CAAI,mBAAA,EAAoB;AACxB,IAAA,MAAM,KAAK,cAAA,EAAe;AAC1B,IAAA,OAAO,MAAA;AAAA,EACT;AAAA,EAEA,MAAM,gBAAA,GAA0C;AAC9C,IAAA,OAAO,IAAA,CAAK,WAAA,CAAY,IAAA,CAAK,cAAA,EAAgB,CAAA;AAAA,EAC/C;AAAA,EAEA,MAAM,oBAAoB,CAAA,EAAsD;AAC9E,IAAA,MAAM,GAAA,GAAM,KAAK,cAAA,EAAe;AAChC,IAAA,GAAA,CAAI,oBAAoB,CAAC,CAAA;AACzB,IAAA,MAAM,IAAA,GAAO,gBAAA,CAAiB,GAAA,CAAI,WAAA,EAAa,CAAA;AAC/C,IAAA,GAAA,CAAI,mBAAA,EAAoB;AACxB,IAAA,MAAM,KAAK,cAAA,EAAe;AAC1B,IAAA,OAAO,IAAA;AAAA,EACT;AAAA,EAEA,MAAM,qBAAA,GAAyC;AAC7C,IAAA,MAAM,GAAA,GAAM,KAAK,cAAA,EAAe;AAChC,IAAA,OAAO,gBAAA,CAAiB,GAAA,CAAI,WAAA,EAAa,CAAA,CAAE,MAAA;AAAA,EAC7C;AAAA,EAEA,MAAM,cAAA,CACJ,UAAA,EACA,YAAA,EACA,YACA,SAAA,EAC2B;AAC3B,IAAA,MAAM,GAAA,GAAM,KAAK,cAAA,EAAe;AAChC,IAAA,IAAI,OAAA,GAAU,MAAM,IAAA,CAAK,WAAA,CAAY,YAAY,YAAY,CAAA;AAC7D,IAAA,IAAI,CAAC,OAAA,EAAS;AAIZ,MAAA,MAAM,SAAA,GAAY,UAAA,CAAW,UAAA,EAAY,MAAA,IAAU,UAAA,CAAW,cAAA;AAC9D,MAAA,OAAA,GAAU,GAAA,CAAI,qBAAA,CAAsB,UAAA,CAAW,gBAAA,EAAkB,SAAS,CAAA;AAC1E,MAAA,IAAA,CAAK,SAAS,GAAA,CAAI,UAAA,CAAW,UAAA,EAAY,YAAY,GAAG,OAAO,CAAA;AAAA,IACjE;AACA,IAAA,MAAM,MAAM,IAAA,CAAK,KAAA,CAAM,OAAA,CAAQ,OAAA,CAAQ,SAAS,CAAC,CAAA;AACjD,IAAA,MAAM,IAAA,CAAK,cAAA,CAAe,UAAA,EAAY,YAAA,EAAc,OAAO,CAAA;AAC3D,IAAA,OAAO;AAAA,MACL,YAAY,GAAA,CAAI,IAAA;AAAA,MAChB,OAAA,EAAS,GAAA,CAAI,IAAA,KAAS,CAAA,GAAI,QAAA,GAAW;AAAA,KACvC;AAAA,EACF;AAAA,EAEA,MAAM,eAAA,CACJ,UAAA,EACA,YAAA,EACA,YACA,OAAA,EACiB;AACjB,IAAA,MAAM,GAAA,GAAM,KAAK,cAAA,EAAe;AAChC,IAAA,IAAI,OAAA,GAAU,MAAM,IAAA,CAAK,WAAA,CAAY,YAAY,YAAY,CAAA;AAC7D,IAAA,MAAM,WAAW,OAAA,KAAY,QAAA;AAE7B,IAAA,IAAI,CAAC,OAAA,EAAS;AACZ,MAAA,IAAI,CAAC,QAAA,EAAU;AACb,QAAA,MAAM,IAAI,KAAA,CAAM,CAAA,2CAAA,EAA8C,UAAU,CAAA,CAAA,EAAI,YAAY,CAAA,CAAE,CAAA;AAAA,MAC5F;AAIA,MAAA,MAAM,OAAA,GAAyB,GAAA,CAAI,oBAAA,CAAqB,UAAU,CAAA;AAClE,MAAA,OAAA,GAAU,QAAQ,WAAA,EAAY;AAC9B,MAAA,MAAMC,aAAY,OAAA,CAAQ,SAAA;AAC1B,MAAA,MAAM,KAAK,cAAA,EAAe;AAC1B,MAAA,IAAA,CAAK,SAAS,GAAA,CAAI,UAAA,CAAW,UAAA,EAAY,YAAY,GAAG,OAAO,CAAA;AAC/D,MAAA,MAAM,IAAA,CAAK,cAAA,CAAe,UAAA,EAAY,YAAA,EAAc,OAAO,CAAA;AAC3D,MAAA,OAAOA,UAAAA;AAAA,IACT;AAEA,IAAA,MAAM,OAAA,GAAU,WAAW,CAAA,GAAI,CAAA;AAC/B,IAAA,MAAM,SAAA,GAAY,OAAA,CAAQ,OAAA,CAAQ,OAAA,EAAS,UAAU,CAAA;AACrD,IAAA,MAAM,IAAA,CAAK,cAAA,CAAe,UAAA,EAAY,YAAA,EAAc,OAAO,CAAA;AAC3D,IAAA,OAAO,SAAA;AAAA,EACT;AAAA,EAEA,MAAM,aAAA,CAAc,UAAA,EAAoB,YAAA,EAAqC;AAC3E,IAAA,MAAM,GAAA,GAAM,UAAA,CAAW,UAAA,EAAY,YAAY,CAAA;AAC/C,IAAA,IAAA,CAAK,QAAA,CAAS,OAAO,GAAG,CAAA;AACxB,IAAA,MAAM,IAAA,CAAK,IAAA,CAAK,KAAA,CAAM,MAAA,CAAO,qBAAqB,GAAG,CAAA;AAAA,EACvD;AAAA,EAEA,MAAM,UAAA,CAAW,UAAA,EAAoB,YAAA,EAAwC;AAC3E,IAAA,IAAI,IAAA,CAAK,SAAS,GAAA,CAAI,UAAA,CAAW,YAAY,YAAY,CAAC,GAAG,OAAO,IAAA;AACpE,IAAA,MAAM,SAAA,GAAY,MAAM,IAAA,CAAK,IAAA,CAAK,KAAA,CAAM,SAAA;AAAA,MACtC,kBAAA,GAAqB,UAAA,CAAW,UAAA,EAAY,YAAY;AAAA,KAC1D;AACA,IAAA,OAAO,SAAA,KAAc,IAAA;AAAA,EACvB;AAAA;AAAA,EAIQ,cAAA,GAA0B;AAChC,IAAA,IAAI,CAAC,IAAA,CAAK,OAAA,EAAS,MAAM,IAAI,MAAM,kDAAkD,CAAA;AACrF,IAAA,OAAO,IAAA,CAAK,OAAA;AAAA,EACd;AAAA,EAEQ,YAAY,GAAA,EAA4B;AAC9C,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,KAAA,CAAM,GAAA,CAAI,cAAc,CAAA;AAC5C,IAAA,MAAM,IAAA,GAAO,gBAAA,CAAiB,GAAA,CAAI,WAAA,EAAa,CAAA;AAE/C,IAAA,MAAM,eAAe,MAAA,CAAO,UAAA;AAC5B,IAAA,MAAM,eAAA,GAAkB,GAAA,CAAI,IAAA,CAAK,YAAY,CAAA;AAC7C,IAAA,MAAM,cAAA,GAAiB,gBAAA,CAAiB,GAAA,CAAI,WAAA,EAAa,CAAA;AACzD,IAAA,MAAM,cAAA,GAAiB,cAAA,CAAe,CAAC,CAAA,EAAG,MAAA,IAAU,YAAA;AACpD,IAAA,MAAM,iBAAA,GAAoB,GAAA,CAAI,IAAA,CAAK,cAAc,CAAA;AACjD,IAAA,OAAO;AAAA,MACL,kBAAkB,MAAA,CAAO,UAAA;AAAA,MACzB,eAAe,MAAA,CAAO,OAAA;AAAA,MACtB,YAAA;AAAA,MACA,eAAA;AAAA,MACA,cAAA;AAAA,MACA,iBAAA;AAAA,MACA,WAAA,EAAa,iBAAA,CAAkB,MAAA,CAAO,OAAO,CAAA;AAAA,MAC7C,WAAA,EAAa;AAAA,KACf;AAAA,EACF;AAAA,EAEA,MAAc,cAAA,GAAgC;AAC5C,IAAA,MAAM,GAAA,GAAM,KAAK,cAAA,EAAe;AAChC,IAAA,MAAM,KAAK,IAAA,CAAK,KAAA,CAAM,UAAU,eAAA,EAAiB,GAAA,CAAI,QAAQ,CAAA;AAAA,EAC/D;AAAA,EAEA,MAAc,WAAA,CAAY,UAAA,EAAoB,YAAA,EAA+C;AAC3F,IAAA,MAAM,GAAA,GAAM,UAAA,CAAW,UAAA,EAAY,YAAY,CAAA;AAC/C,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,QAAA,CAAS,GAAA,CAAI,GAAG,CAAA;AACpC,IAAA,IAAI,QAAQ,OAAO,MAAA;AACnB,IAAA,MAAM,UAAU,MAAM,IAAA,CAAK,KAAK,KAAA,CAAM,SAAA,CAAU,qBAAqB,GAAG,CAAA;AACxE,IAAA,IAAI,CAAC,SAAS,OAAO,IAAA;AACrB,IAAA,MAAM,OAAA,GAAUC,iBAAA,CAAQ,UAAA,CAAW,OAAO,CAAA;AAC1C,IAAA,IAAA,CAAK,QAAA,CAAS,GAAA,CAAI,GAAA,EAAK,OAAO,CAAA;AAC9B,IAAA,OAAO,OAAA;AAAA,EACT;AAAA,EAEA,MAAc,cAAA,CAAe,UAAA,EAAoB,YAAA,EAAsB,OAAA,EAAiC;AACtG,IAAA,MAAM,IAAA,CAAK,KAAK,KAAA,CAAM,SAAA;AAAA,MACpB,kBAAA,GAAqB,UAAA,CAAW,UAAA,EAAY,YAAY,CAAA;AAAA,MACxD,QAAQ,MAAA;AAAO,KACjB;AAAA,EACF;AACF;AAEA,SAAS,UAAA,CAAW,YAAoB,YAAA,EAA8B;AACpE,EAAA,OAAO,CAAA,EAAG,UAAU,CAAA,CAAA,EAAI,YAAY,CAAA,CAAA;AACtC;AAEA,SAAS,iBAAiB,IAAA,EAAgD;AACxE,EAAA,MAAM,MAAA,GAAS,IAAA,CAAK,KAAA,CAAM,IAAI,CAAA;AAC9B,EAAA,MAAM,MAAwC,EAAC;AAC/C,EAAA,KAAA,MAAW,CAAC,EAAA,EAAI,GAAG,CAAA,IAAK,MAAA,CAAO,QAAQ,MAAA,CAAO,UAAA,IAAc,EAAE,CAAA,EAAG;AAC/D,IAAA,GAAA,CAAI,IAAA,CAAK,EAAE,EAAA,EAAI,MAAA,EAAQ,KAAK,CAAA;AAAA,EAC9B;AACA,EAAA,OAAO,GAAA;AACT;AAEA,SAAS,kBAAkB,aAAA,EAA+B;AACxD,EAAA,MAAM,MAAA,GAAA,CAAU,aAAA,CAAc,OAAA,CAAQ,QAAA,EAAU,EAAE,CAAA,CAAE,KAAA,CAAM,SAAS,CAAA,IAAK,EAAC,EAAG,KAAA,CAAM,GAAG,EAAE,CAAA;AACvF,EAAA,OAAO,MAAA,CAAO,KAAK,GAAG,CAAA;AACxB;;;ACxOA,IAAM,aAAA,GAAgB,UAAA;AAEtB,SAAS,YAAA,GAAuB;AAE9B,EAAA,IAAI,OAAO,UAAA,CAAW,MAAA,EAAQ,UAAA,KAAe,UAAA,EAAY;AACvD,IAAA,OAAO,UAAA,CAAW,OAAO,UAAA,EAAW;AAAA,EACtC;AAEA,EAAA,MAAM,KAAA,GAAQ,IAAI,UAAA,CAAW,EAAE,CAAA;AAC/B,EAAA,UAAA,CAAW,MAAA,CAAO,gBAAgB,KAAK,CAAA;AACvC,EAAA,KAAA,CAAM,CAAC,CAAA,GAAK,KAAA,CAAM,CAAC,IAAI,EAAA,GAAQ,EAAA;AAC/B,EAAA,KAAA,CAAM,CAAC,CAAA,GAAK,KAAA,CAAM,CAAC,IAAI,EAAA,GAAQ,GAAA;AAC/B,EAAA,MAAM,MAAM,KAAA,CAAM,IAAA,CAAK,KAAA,EAAO,CAAC,MAAM,CAAA,CAAE,QAAA,CAAS,EAAE,CAAA,CAAE,SAAS,CAAA,EAAG,GAAG,CAAC,CAAA,CAAE,KAAK,EAAE,CAAA;AAC7E,EAAA,OAAO,CAAA,EAAG,GAAA,CAAI,KAAA,CAAM,CAAA,EAAG,CAAC,CAAC,CAAA,CAAA,EAAI,GAAA,CAAI,KAAA,CAAM,CAAA,EAAG,EAAE,CAAC,CAAA,CAAA,EAAI,GAAA,CAAI,KAAA,CAAM,EAAA,EAAI,EAAE,CAAC,CAAA,CAAA,EAAI,GAAA,CAAI,KAAA,CAAM,EAAA,EAAI,EAAE,CAAC,CAAA,CAAA,EAAI,GAAA,CAAI,KAAA,CAAM,EAAE,CAAC,CAAA,CAAA;AAC1G;AAEA,eAAsB,qBAAqB,KAAA,EAAiC;AAC1E,EAAA,MAAM,QAAA,GAAW,MAAM,KAAA,CAAM,SAAA,CAAU,aAAa,CAAA;AACpD,EAAA,IAAI,UAAU,OAAO,QAAA;AACrB,EAAA,MAAM,KAAK,YAAA,EAAa;AACxB,EAAA,MAAM,KAAA,CAAM,SAAA,CAAU,aAAA,EAAe,EAAE,CAAA;AACvC,EAAA,OAAO,EAAA;AACT;;;ACGA,IAAM,sBAAA,GAAyB,IAAI,EAAA,GAAK,GAAA;AAEjC,IAAM,kBAAN,MAAsB;AAAA,EAG3B,YAAoB,IAAA,EAA8B;AAA9B,IAAA,IAAA,CAAA,IAAA,GAAA,IAAA;AAAA,EAA+B;AAAA,EAA/B,IAAA;AAAA,EAFZ,KAAA,uBAAY,GAAA,EAAwB;AAAA;AAAA;AAAA;AAAA;AAAA,EAQ5C,MAAM,eAAe,UAAA,EAA+C;AAClE,IAAA,MAAM,GAAA,GAAM,KAAK,GAAA,EAAI;AACrB,IAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,IAAA,CAAK,YAAA,IAAgB,sBAAA;AACxC,IAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,KAAA,CAAM,GAAA,CAAI,UAAU,CAAA;AACvC,IAAA,IAAI,KAAA,IAAS,GAAA,GAAM,KAAA,CAAM,SAAA,GAAY,KAAA,EAAO;AAC1C,MAAA,OAAO,KAAA,CAAM,OAAA;AAAA,IACf;AACA,IAAA,OAAO,IAAA,CAAK,QAAQ,UAAU,CAAA;AAAA,EAChC;AAAA;AAAA,EAGA,MAAM,QAAQ,UAAA,EAA+C;AAC3D,IAAA,MAAM,GAAA,GAAM,MAAM,IAAA,CAAK,IAAA,CAAK,KAAK,WAAA,CAAY,IAAA,CAAK,IAAA,CAAK,YAAA,EAAc,UAAU,CAAA;AAC/E,IAAA,MAAM,OAAA,GAAU,GAAA,CAAI,OAAA,CAAQ,GAAA,CAAI,CAAC,CAAA,MAAO;AAAA,MACtC,UAAU,CAAA,CAAE,QAAA;AAAA,MACZ,aAAa,CAAA,CAAE,WAAA;AAAA,MACf,cAAc,CAAA,CAAE;AAAA,KAClB,CAAE,CAAA;AACF,IAAA,IAAA,CAAK,KAAA,CAAM,IAAI,UAAA,EAAY,EAAE,SAAS,SAAA,EAAW,IAAA,CAAK,GAAA,EAAI,EAAG,CAAA;AAC7D,IAAA,OAAO,OAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,iBAAA,CAAkB,YAAoB,MAAA,EAA8B;AAClE,IAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,KAAA,CAAM,GAAA,CAAI,UAAU,CAAA;AACvC,IAAA,IAAI,CAAC,KAAA,EAAO;AACV,MAAA,IAAA,CAAK,KAAA,CAAM,GAAA,CAAI,UAAA,EAAY,EAAE,OAAA,EAAS,CAAC,MAAM,CAAA,EAAG,SAAA,EAAW,IAAA,CAAK,GAAA,EAAI,EAAG,CAAA;AACvE,MAAA;AAAA,IACF;AACA,IAAA,IAAI,KAAA,CAAM,QAAQ,IAAA,CAAK,CAAC,MAAM,CAAA,CAAE,QAAA,KAAa,MAAA,CAAO,QAAQ,CAAA,EAAG;AAC/D,IAAA,KAAA,CAAM,OAAA,CAAQ,KAAK,MAAM,CAAA;AAAA,EAC3B;AAAA;AAAA,EAGA,WAAW,UAAA,EAA0B;AACnC,IAAA,IAAA,CAAK,KAAA,CAAM,OAAO,UAAU,CAAA;AAAA,EAC9B;AAAA;AAAA,EAGA,KAAA,GAAc;AACZ,IAAA,IAAA,CAAK,MAAM,KAAA,EAAM;AAAA,EACnB;AACF,CAAA;;;AClFO,IAAM,iBAAA,GAAoB,GAAA;AAC1B,IAAM,mBAAA,GAAsB,EAAA;AAC5B,IAAM,gBAAA,GAAmB,GAAA;AAgBzB,IAAM,mBAAN,MAAuB;AAAA,EAC5B,YAAoB,IAAA,EAA+B;AAA/B,IAAA,IAAA,CAAA,IAAA,GAAA,IAAA;AAAA,EAAgC;AAAA,EAAhC,IAAA;AAAA;AAAA;AAAA,EAIZ,aAAA,GAAwE,IAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOhF,MAAM,eAAA,GAAiC;AACrC,IAAA,MAAM,IAAA,CAAK,IAAA,CAAK,MAAA,CAAO,IAAA,EAAK;AAC5B,IAAA,IAAI,MAAM,IAAA,CAAK,IAAA,CAAK,MAAA,CAAO,YAAW,EAAG;AACvC,MAAA;AAAA,IACF;AACA,IAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,IAAA,CAAK,MAAA,CAAO,eAAA;AAAA,MACpC,IAAA,CAAK,KAAK,eAAA,IAAmB;AAAA,KAC/B;AACA,IAAA,MAAM,KAAK,IAAA,CAAK,IAAA,CAAK,eAAA,CAAgB,IAAA,CAAK,KAAK,QAAA,EAAU;AAAA,MACvD,QAAA,EAAU,KAAK,IAAA,CAAK,QAAA;AAAA,MACpB,kBAAkB,MAAA,CAAO,gBAAA;AAAA,MACzB,eAAe,MAAA,CAAO,aAAA;AAAA,MACtB,cAAc,MAAA,CAAO,YAAA;AAAA,MACrB,iBAAiB,MAAA,CAAO,eAAA;AAAA,MACxB,gBAAgB,MAAA,CAAO,cAAA;AAAA,MACvB,mBAAmB,MAAA,CAAO,iBAAA;AAAA,MAC1B,aAAa,MAAA,CAAO,WAAA;AAAA,MACpB,aAAa,MAAA,CAAO;AAAA,KACrB,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,qBAAA,GAAuC;AAC3C,IAAA,MAAM,IAAA,CAAK,IAAA,CAAK,MAAA,CAAO,IAAA,EAAK;AAC5B,IAAA,IAAI,CAAE,MAAM,IAAA,CAAK,IAAA,CAAK,MAAA,CAAO,YAAW,EAAI;AAC1C,MAAA,MAAM,IAAI,MAAM,+DAA+D,CAAA;AAAA,IACjF;AACA,IAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,IAAA,CAAK,OAAO,gBAAA,EAAiB;AACvD,IAAA,MAAM,KAAK,IAAA,CAAK,IAAA,CAAK,eAAA,CAAgB,IAAA,CAAK,KAAK,QAAA,EAAU;AAAA,MACvD,QAAA,EAAU,KAAK,IAAA,CAAK,QAAA;AAAA,MACpB,kBAAkB,MAAA,CAAO,gBAAA;AAAA,MACzB,eAAe,MAAA,CAAO,aAAA;AAAA,MACtB,cAAc,MAAA,CAAO,YAAA;AAAA,MACrB,iBAAiB,MAAA,CAAO,eAAA;AAAA,MACxB,gBAAgB,MAAA,CAAO,cAAA;AAAA,MACvB,mBAAmB,MAAA,CAAO,iBAAA;AAAA,MAC1B,aAAa,MAAA,CAAO,WAAA;AAAA,MACpB,aAAa,MAAA,CAAO;AAAA,KACrB,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,aAAA,GAAiE;AACrE,IAAA,IAAI,IAAA,CAAK,aAAA,EAAe,OAAO,IAAA,CAAK,aAAA;AACpC,IAAA,MAAM,KAAK,YAAY;AACrB,MAAA,MAAM,EAAE,KAAA,EAAM,GAAI,MAAM,IAAA,CAAK,KAAK,IAAA,CAAK,QAAA,CAAS,IAAA,CAAK,IAAA,CAAK,QAAQ,CAAA;AAClE,MAAA,IAAI,SAAS,mBAAA,EAAqB;AAChC,QAAA,OAAO,EAAE,QAAQ,KAAA,EAAM;AAAA,MACzB;AACA,MAAA,MAAM,OAAO,gBAAA,GAAmB,KAAA;AAChC,MAAA,MAAM,QAAQ,MAAM,IAAA,CAAK,IAAA,CAAK,MAAA,CAAO,oBAAoB,IAAI,CAAA;AAC7D,MAAA,MAAM,GAAA,GAAM,MAAM,IAAA,CAAK,IAAA,CAAK,KAAK,SAAA,CAAU,IAAA,CAAK,IAAA,CAAK,QAAA,EAAU,KAAK,CAAA;AACpE,MAAA,OAAO,EAAE,MAAA,EAAQ,IAAA,EAAe,QAAA,EAAU,IAAI,YAAA,EAAa;AAAA,IAC7D,CAAA,GAAG;AACH,IAAA,IAAA,CAAK,aAAA,GAAgB,CAAA;AACrB,IAAA,IAAI;AACF,MAAA,OAAO,MAAM,CAAA;AAAA,IACf,CAAA,SAAE;AACA,MAAA,IAAA,CAAK,aAAA,GAAgB,IAAA;AAAA,IACvB;AAAA,EACF;AACF,CAAA;;;AC5EO,IAAM,eAAN,MAAmB;AAAA,EAGxB,YAAoB,KAAA,EAAgB;AAAhB,IAAA,IAAA,CAAA,KAAA,GAAA,KAAA;AAAA,EAAiB;AAAA,EAAjB,KAAA;AAAA,EAFZ,KAAA,uBAAY,GAAA,EAA2B;AAAA;AAAA,EAK/C,MAAM,IAAI,GAAA,EAAmC;AAC3C,IAAA,IAAA,CAAK,KAAA,CAAM,GAAA,CAAI,GAAA,CAAI,EAAA,EAAI,GAAG,CAAA;AAC1B,IAAA,MAAM,IAAA,CAAK,KAAA,CAAM,SAAA,CAAU,IAAA,CAAK,KAAA,CAAM,GAAA,CAAI,EAAE,CAAA,EAAG,IAAA,CAAK,SAAA,CAAU,GAAG,CAAC,CAAA;AAAA,EACpE;AAAA,EAEA,MAAM,IAAI,SAAA,EAAkD;AAC1D,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,KAAA,CAAM,GAAA,CAAI,SAAS,CAAA;AACvC,IAAA,IAAI,QAAQ,OAAO,MAAA;AACnB,IAAA,MAAM,GAAA,GAAM,MAAM,IAAA,CAAK,KAAA,CAAM,UAAU,IAAA,CAAK,KAAA,CAAM,SAAS,CAAC,CAAA;AAC5D,IAAA,IAAI,CAAC,KAAK,OAAO,IAAA;AACjB,IAAA,IAAI;AACF,MAAA,MAAM,MAAA,GAAS,IAAA,CAAK,KAAA,CAAM,GAAG,CAAA;AAC7B,MAAA,IAAA,CAAK,KAAA,CAAM,GAAA,CAAI,MAAA,CAAO,EAAA,EAAI,MAAM,CAAA;AAChC,MAAA,OAAO,MAAA;AAAA,IACT,CAAA,CAAA,MAAQ;AACN,MAAA,OAAO,IAAA;AAAA,IACT;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,MAAM,WAAA,CACJ,UAAA,EACA,IAAA,GAAkD,EAAC,EACzB;AAC1B,IAAA,MAAM,IAAA,GAAO,MAAM,IAAA,CAAK,KAAA,CAAM,SAAS,WAAW,CAAA;AAClD,IAAA,MAAM,MAAuB,EAAC;AAC9B,IAAA,KAAA,MAAW,OAAO,IAAA,EAAM;AACtB,MAAA,MAAM,EAAA,GAAK,GAAA,CAAI,KAAA,CAAM,WAAA,CAAY,MAAM,CAAA;AACvC,MAAA,MAAM,MAAA,GAAS,IAAA,CAAK,KAAA,CAAM,GAAA,CAAI,EAAE,CAAA;AAChC,MAAA,IAAI,MAA4B,MAAA,IAAU,IAAA;AAC1C,MAAA,IAAI,CAAC,GAAA,EAAK;AACR,QAAA,MAAM,GAAA,GAAM,MAAM,IAAA,CAAK,KAAA,CAAM,UAAU,GAAG,CAAA;AAC1C,QAAA,IAAI,CAAC,GAAA,EAAK;AACV,QAAA,IAAI;AACF,UAAA,GAAA,GAAM,IAAA,CAAK,MAAM,GAAG,CAAA;AACpB,UAAA,IAAA,CAAK,KAAA,CAAM,GAAA,CAAI,GAAA,CAAI,EAAA,EAAI,GAAG,CAAA;AAAA,QAC5B,CAAA,CAAA,MAAQ;AACN,UAAA;AAAA,QACF;AAAA,MACF;AACA,MAAA,IAAI,GAAA,CAAI,eAAe,UAAA,EAAY;AACnC,MAAA,IAAI,KAAK,YAAA,KAAiB,MAAA,IAAa,GAAA,CAAI,MAAA,IAAU,KAAK,YAAA,EAAc;AACxE,MAAA,GAAA,CAAI,KAAK,GAAG,CAAA;AAAA,IACd;AACA,IAAA,GAAA,CAAI,KAAK,CAAC,CAAA,EAAG,MAAM,CAAA,CAAE,MAAA,GAAS,EAAE,MAAM,CAAA;AACtC,IAAA,IAAI,KAAK,KAAA,KAAU,MAAA,IAAa,GAAA,CAAI,MAAA,GAAS,KAAK,KAAA,EAAO;AACvD,MAAA,OAAO,GAAA,CAAI,KAAA,CAAM,CAAC,IAAA,CAAK,KAAK,CAAA;AAAA,IAC9B;AACA,IAAA,OAAO,GAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,UAAU,IAAA,EAKkB;AAChC,IAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,GAAA,CAAI,KAAK,QAAQ,CAAA;AAC3C,IAAA,IAAI,CAAC,QAAQ,OAAO,IAAA;AACpB,IAAA,IAAI,MAAA,CAAO,SAAA,KAAc,IAAA,EAAM,OAAO,IAAA;AACtC,IAAA,IAAI,MAAA,CAAO,YAAA,KAAiB,IAAA,CAAK,YAAA,EAAc,OAAO,IAAA;AACtD,IAAA,MAAM,OAAA,GAAyB;AAAA,MAC7B,GAAG,MAAA;AAAA,MACH,MAAM,IAAA,CAAK,OAAA;AAAA,MACX,UAAU,IAAA,CAAK;AAAA,KACjB;AACA,IAAA,MAAM,IAAA,CAAK,IAAI,OAAO,CAAA;AACtB,IAAA,OAAO,OAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,YAAY,IAAA,EAIgB;AAChC,IAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,GAAA,CAAI,KAAK,QAAQ,CAAA;AAC3C,IAAA,IAAI,CAAC,QAAQ,OAAO,IAAA;AACpB,IAAA,IAAI,MAAA,CAAO,YAAA,KAAiB,IAAA,CAAK,aAAA,EAAe,OAAO,IAAA;AACvD,IAAA,MAAM,OAAA,GAAyB;AAAA,MAC7B,GAAG,MAAA;AAAA;AAAA,MAEH,IAAA,EAAM,EAAA;AAAA,MACN,WAAW,IAAA,CAAK;AAAA,KAClB;AACA,IAAA,MAAM,IAAA,CAAK,IAAI,OAAO,CAAA;AACtB,IAAA,OAAO,OAAA;AAAA,EACT;AAAA,EAEQ,MAAM,SAAA,EAA2B;AACvC,IAAA,OAAO,YAAY,SAAS,CAAA,CAAA;AAAA,EAC9B;AACF,CAAA;;;ACtHA,IAAM,oBAAA,GAAuB,CAAA;AAC7B,IAAM,oBAAA,GAAuB,GAAA;AAStB,IAAM,SAAN,MAAa;AAAA,EACV,QAAuB,EAAC;AAAA,EACxB,WAAA,uBAAkB,GAAA,EAAY;AAAA,EAC9B,IAAA;AAAA,EAER,WAAA,CAAY,IAAA,GAAsB,EAAC,EAAG;AACpC,IAAA,IAAA,CAAK,IAAA,GAAO;AAAA,MACV,WAAA,EAAa,KAAK,WAAA,IAAe,oBAAA;AAAA,MACjC,aAAA,EAAe,KAAK,aAAA,IAAiB;AAAA,KACvC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,QAAQ,KAAA,EAA4D;AAClE,IAAA,IAAI,IAAA,CAAK,WAAA,CAAY,GAAA,CAAI,KAAA,CAAM,SAAS,CAAA,EAAG;AAC3C,IAAA,IAAA,CAAK,WAAA,CAAY,GAAA,CAAI,KAAA,CAAM,SAAS,CAAA;AACpC,IAAA,IAAA,CAAK,KAAA,CAAM,KAAK,EAAE,GAAG,OAAO,QAAA,EAAU,CAAA,EAAG,WAAA,EAAa,CAAA,EAAG,CAAA;AAAA,EAC3D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,IAAA,GAAwB;AAC5B,IAAA,MAAM,GAAA,GAAM,KAAK,GAAA,EAAI;AACrB,IAAA,IAAI,SAAA,GAAY,CAAA;AAChB,IAAA,MAAM,eAA8B,EAAC;AACrC,IAAA,KAAA,MAAW,KAAA,IAAS,KAAK,KAAA,EAAO;AAC9B,MAAA,IAAI,KAAA,CAAM,cAAc,GAAA,EAAK;AAC3B,QAAA,YAAA,CAAa,KAAK,KAAK,CAAA;AACvB,QAAA;AAAA,MACF;AACA,MAAA,KAAA,CAAM,QAAA,EAAA;AACN,MAAA,IAAI,QAAA;AACJ,MAAA,IAAI;AACF,QAAA,QAAA,GAAW,MAAM,MAAM,OAAA,EAAQ;AAAA,MACjC,CAAA,CAAA,MAAQ;AACN,QAAA,QAAA,uBAAe,GAAA,EAAI;AAAA,MACrB;AAEA,MAAA,MAAM,KAAA,GAAQ,KAAA,CAAM,IAAA,CAAK,QAAA,CAAS,MAAA,EAAQ,CAAA,CAAE,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,KAAM,MAAA,IAAU,MAAM,QAAQ,CAAA;AACtF,MAAA,IAAI,KAAA,EAAO;AACT,QAAA,IAAA,CAAK,WAAA,CAAY,MAAA,CAAO,KAAA,CAAM,SAAS,CAAA;AACvC,QAAA,SAAA,EAAA;AACA,QAAA;AAAA,MACF;AACA,MAAA,IAAI,KAAA,CAAM,QAAA,IAAY,IAAA,CAAK,IAAA,CAAK,WAAA,EAAa;AAC3C,QAAA,IAAA,CAAK,WAAA,CAAY,MAAA,CAAO,KAAA,CAAM,SAAS,CAAA;AACvC,QAAA,SAAA,EAAA;AACA,QAAA;AAAA,MACF;AACA,MAAA,KAAA,CAAM,WAAA,GAAc,GAAA,GAAM,IAAA,CAAK,cAAA,CAAe,MAAM,QAAQ,CAAA;AAC5D,MAAA,YAAA,CAAa,KAAK,KAAK,CAAA;AAAA,IACzB;AACA,IAAA,IAAA,CAAK,KAAA,GAAQ,YAAA;AACb,IAAA,OAAO,SAAA;AAAA,EACT;AAAA,EAEA,IAAA,GAAe;AACb,IAAA,OAAO,KAAK,KAAA,CAAM,MAAA;AAAA,EACpB;AAAA;AAAA,EAGA,IAAI,SAAA,EAA4B;AAC9B,IAAA,OAAO,IAAA,CAAK,WAAA,CAAY,GAAA,CAAI,SAAS,CAAA;AAAA,EACvC;AAAA,EAEQ,eAAe,OAAA,EAAyB;AAC9C,IAAA,MAAM,IAAA,GAAO,IAAA,CAAK,IAAA,CAAK,aAAA,GAAgB,MAAM,OAAA,GAAU,CAAA,CAAA;AACvD,IAAA,MAAM,MAAA,GAAS,IAAA,IAAQ,GAAA,GAAM,IAAA,CAAK,QAAO,GAAI,GAAA,CAAA;AAC7C,IAAA,OAAO,KAAK,GAAA,CAAI,GAAA,EAAK,KAAK,KAAA,CAAM,IAAA,GAAO,MAAM,CAAC,CAAA;AAAA,EAChD;AACF,CAAA;;;AClFO,IAAM,iBAAN,MAAqB;AAAA,EAqB1B,YAAoB,IAAA,EAA6B;AAA7B,IAAA,IAAA,CAAA,IAAA,GAAA,IAAA;AAAA,EAA8B;AAAA,EAA9B,IAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAfZ,KAAA,uBAAY,GAAA,EAA2B;AAAA;AAAA;AAAA,EAIvC,WAAA,uBAAkB,GAAA,EAA6B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAS/C,eAAA,uBAAsB,GAAA,EAAsC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYpE,MAAM,cAAA,CAAe,UAAA,EAAoB,SAAA,EAAgD;AACvF,IAAA,IAAI,OAAA,GAAU,MAAM,IAAA,CAAK,iBAAA,CAAkB,UAAU,CAAA;AAGrD,IAAA,IAAI,KAAK,IAAA,CAAK,UAAA,IAAc,UAAA,KAAe,IAAA,CAAK,KAAK,UAAA,EAAY;AAC/D,MAAA,OAAA,GAAU,OAAA,CAAQ,OAAO,CAAC,CAAA,KAAM,EAAE,QAAA,KAAa,IAAA,CAAK,KAAK,YAAY,CAAA;AAAA,IACvE;AACA,IAAA,IAAI,OAAA,CAAQ,MAAA,KAAW,CAAA,EAAG,OAAO,EAAC;AAElC,IAAA,MAAM,UAA8B,EAAC;AACrC,IAAA,KAAA,MAAW,OAAO,OAAA,EAAS;AACzB,MAAA,MAAM,MAAM,MAAM,IAAA,CAAK,mBAAA,CAAoB,UAAA,EAAY,KAAK,SAAS,CAAA;AACrE,MAAA,OAAA,CAAQ,IAAA,CAAK,EAAE,YAAA,EAAc,GAAA,CAAI,QAAA,EAAU,UAAA,EAAY,GAAA,CAAI,UAAA,EAAY,OAAA,EAAS,GAAA,CAAI,OAAA,EAAS,CAAA;AAAA,IAC/F;AACA,IAAA,OAAO,OAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,OAAA,CACJ,UAAA,EACA,YAAA,EACA,YACA,OAAA,EACiB;AACjB,IAAA,OAAO,KAAK,IAAA,CAAK,MAAA,CAAO,gBAAgB,UAAA,EAAY,YAAA,EAAc,YAAY,OAAO,CAAA;AAAA,EACvF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,gBAAA,CAAiB,UAAA,EAAoB,YAAA,EAAqC;AAC9E,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,WAAA,CAAY,GAAA,CAAI,UAAU,CAAA;AAC9C,IAAA,IAAI,MAAA,EAAQ;AACV,MAAA,IAAA,CAAK,WAAA,CAAY,GAAA;AAAA,QACf,UAAA;AAAA,QACA,OAAO,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,CAAE,aAAa,YAAY;AAAA,OAClD;AAAA,IACF;AACA,IAAA,MAAM,IAAA,CAAK,IAAA,CAAK,MAAA,CAAO,aAAA,CAAc,YAAY,YAAY,CAAA;AAAA,EAC/D;AAAA;AAAA,EAGA,MAAM,UAAA,CAAW,UAAA,EAAoB,YAAA,EAAwC;AAC3E,IAAA,OAAO,IAAA,CAAK,IAAA,CAAK,MAAA,CAAO,UAAA,CAAW,YAAY,YAAY,CAAA;AAAA,EAC7D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,iBAAiB,UAAA,EAAmC;AAClD,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,WAAA,CAAY,GAAA,CAAI,UAAU,CAAA;AAC9C,IAAA,IAAI,CAAC,QAAQ,OAAO,IAAA;AACpB,IAAA,IAAI,KAAK,IAAA,CAAK,UAAA,IAAc,UAAA,KAAe,IAAA,CAAK,KAAK,UAAA,EAAY;AAC/D,MAAA,OAAO,MAAA,CAAO,OAAO,CAAC,CAAA,KAAM,EAAE,QAAA,KAAa,IAAA,CAAK,IAAA,CAAK,YAAY,CAAA,CAAE,MAAA;AAAA,IACrE;AACA,IAAA,OAAO,MAAA,CAAO,MAAA;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,mBAAmB,UAAA,EAA8C;AACrE,IAAA,MAAM,GAAA,GAAM,MAAM,IAAA,CAAK,IAAA,CAAK,KAAK,QAAA,CAAS,IAAA,CAAK,IAAA,CAAK,YAAA,EAAc,UAAU,CAAA;AAC5E,IAAA,IAAA,CAAK,WAAA,CAAY,GAAA,CAAI,UAAA,EAAY,GAAA,CAAI,OAAO,CAAA;AAC5C,IAAA,OAAO,GAAA,CAAI,OAAA;AAAA,EACb;AAAA;AAAA,EAIA,MAAc,kBAAkB,UAAA,EAA8C;AAC5E,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,WAAA,CAAY,GAAA,CAAI,UAAU,CAAA;AAC9C,IAAA,IAAI,QAAQ,OAAO,MAAA;AACnB,IAAA,MAAM,QAAA,GAAW,IAAA,CAAK,eAAA,CAAgB,GAAA,CAAI,UAAU,CAAA;AACpD,IAAA,IAAI,UAAU,OAAO,QAAA;AACrB,IAAA,MAAM,KAAK,YAAY;AACrB,MAAA,IAAI;AACF,QAAA,OAAO,MAAM,IAAA,CAAK,kBAAA,CAAmB,UAAU,CAAA;AAAA,MACjD,CAAA,SAAE;AACA,QAAA,IAAA,CAAK,eAAA,CAAgB,OAAO,UAAU,CAAA;AAAA,MACxC;AAAA,IACF,CAAA,GAAG;AACH,IAAA,IAAA,CAAK,eAAA,CAAgB,GAAA,CAAI,UAAA,EAAY,CAAC,CAAA;AACtC,IAAA,OAAO,CAAA;AAAA,EACT;AAAA,EAEA,MAAc,mBAAA,CACZ,UAAA,EACA,MAAA,EACA,SAAA,EAC2B;AAC3B,IAAA,MAAM,OAAA,GAAUC,WAAAA,CAAW,UAAA,EAAY,MAAA,CAAO,QAAQ,CAAA;AACtD,IAAA,MAAM,OAAO,IAAA,CAAK,KAAA,CAAM,IAAI,OAAO,CAAA,IAAK,QAAQ,OAAA,EAAQ;AACxD,IAAA,IAAI,OAAA;AACJ,IAAA,MAAM,IAAA,GAAO,IAAI,OAAA,CAAc,CAAC,CAAA,KAAM;AAAE,MAAA,OAAA,GAAU,CAAA;AAAA,IAAG,CAAC,CAAA;AACtD,IAAA,IAAA,CAAK,MAAM,GAAA,CAAI,OAAA,EAAS,KAAK,IAAA,CAAK,MAAM,IAAI,CAAC,CAAA;AAC7C,IAAA,MAAM,IAAA;AACN,IAAA,IAAI;AACF,MAAA,OAAO,MAAM,KAAK,IAAA,CAAK,MAAA,CAAO,eAAe,UAAA,EAAY,MAAA,CAAO,QAAA,EAAU,MAAA,EAAQ,SAAS,CAAA;AAAA,IAC7F,CAAA,SAAE;AACA,MAAA,OAAA,EAAQ;AAER,MAAA,IAAI,IAAA,CAAK,MAAM,GAAA,CAAI,OAAO,MAAM,IAAA,CAAK,IAAA,CAAK,MAAM,IAAI,CAAA,EAAG;AACrD,QAAA,IAAA,CAAK,KAAA,CAAM,OAAO,OAAO,CAAA;AAAA,MAC3B;AAAA,IACF;AAAA,EACF;AACF,CAAA;AAEA,SAASA,WAAAA,CAAW,YAAoB,YAAA,EAA8B;AACpE,EAAA,OAAO,CAAA,EAAG,UAAU,CAAA,CAAA,EAAI,YAAY,CAAA,CAAA;AACtC;;;ACjJO,IAAM,gBAAN,MAAoB;AAAA,EACjB,QAAA,uBAAe,GAAA,EAAsB;AAAA;AAAA,EAErC,iBAAA,uBAAwB,GAAA,EAAoB;AAAA;AAAA;AAAA,EAG5C,MAAA,uBAAa,GAAA,EAAsB;AAAA,EAEnC,YAA8B,EAAC;AAAA,EAEvC,GAAG,EAAA,EAAgC;AACjC,IAAA,IAAA,CAAK,SAAA,CAAU,KAAK,EAAE,CAAA;AACtB,IAAA,OAAO,MAAM;AACX,MAAA,MAAM,CAAA,GAAI,IAAA,CAAK,SAAA,CAAU,OAAA,CAAQ,EAAE,CAAA;AACnC,MAAA,IAAI,KAAK,CAAA,EAAG,IAAA,CAAK,SAAA,CAAU,MAAA,CAAO,GAAG,CAAC,CAAA;AAAA,IACxC,CAAA;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,cAAc,IAAA,EAIL;AACP,IAAA,MAAM,cAAc,IAAI,GAAA,CAAI,IAAA,CAAK,gBAAA,CAAiB,QAAQ,CAAA;AAC1D,IAAA,IAAA,CAAK,QAAA,CAAS,GAAA,CAAI,IAAA,CAAK,SAAA,EAAW;AAAA,MAChC,WAAW,IAAA,CAAK,SAAA;AAAA,MAChB,YAAY,IAAA,CAAK,UAAA;AAAA,MACjB,kBAAkB,IAAA,CAAK,gBAAA;AAAA,MACvB,WAAA;AAAA,MACA,YAAA,sBAAkB,GAAA,EAAI;AAAA,MACtB,MAAA,EAAQ;AAAA,KACT,CAAA;AACD,IAAA,KAAA,MAAW,IAAA,IAAQ,IAAA,CAAK,gBAAA,CAAiB,IAAA,EAAK,EAAG;AAC/C,MAAA,IAAA,CAAK,iBAAA,CAAkB,GAAA,CAAI,IAAA,EAAM,IAAA,CAAK,SAAS,CAAA;AAAA,IACjD;AACA,IAAA,MAAM,OAAO,IAAA,CAAK,MAAA,CAAO,IAAI,IAAA,CAAK,UAAU,KAAK,EAAC;AAClD,IAAA,IAAA,CAAK,IAAA,CAAK,KAAK,SAAS,CAAA;AACxB,IAAA,IAAA,CAAK,MAAA,CAAO,GAAA,CAAI,IAAA,CAAK,UAAA,EAAY,IAAI,CAAA;AAAA,EACvC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,YAAA,CAAa,cAAsB,MAAA,EAAuD;AACxF,IAAA,MAAM,SAAA,GAAY,IAAA,CAAK,iBAAA,CAAkB,GAAA,CAAI,YAAY,CAAA;AACzD,IAAA,IAAI,CAAC,SAAA,EAAW;AAChB,IAAA,MAAM,QAAA,GAAW,IAAA,CAAK,QAAA,CAAS,GAAA,CAAI,SAAS,CAAA;AAC5C,IAAA,IAAI,CAAC,QAAA,EAAU;AACf,IAAA,IAAI,MAAA,KAAW,MAAA,IAAU,MAAA,KAAW,QAAA,EAAU;AAC5C,MAAA,IAAA,CAAK,IAAA,CAAK,UAAU,MAAM,CAAA;AAAA,IAC5B;AAAA,EAEF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,WAAW,IAAA,EAIF;AACP,IAAA,KAAA,MAAW,EAAA,IAAM,KAAK,UAAA,EAAY;AAChC,MAAA,MAAM,QAAA,GAAW,IAAA,CAAK,QAAA,CAAS,GAAA,CAAI,EAAE,CAAA;AACrC,MAAA,IAAI,CAAC,QAAA,EAAU;AACf,MAAA,IAAI,QAAA,CAAS,UAAA,KAAe,IAAA,CAAK,UAAA,EAAY;AAC7C,MAAA,IAAI,CAAC,QAAA,CAAS,WAAA,CAAY,GAAA,CAAI,IAAA,CAAK,YAAY,CAAA,EAAG;AAEhD,QAAA,QAAA,CAAS,WAAA,CAAY,GAAA,CAAI,IAAA,CAAK,YAAY,CAAA;AAAA,MAC5C;AACA,MAAA,QAAA,CAAS,YAAA,CAAa,GAAA,CAAI,IAAA,CAAK,YAAY,CAAA;AAC3C,MAAA,MAAM,WAAA,GACJ,SAAS,YAAA,CAAa,IAAA,IAAQ,SAAS,WAAA,CAAY,IAAA,IAAQ,QAAA,CAAS,WAAA,CAAY,IAAA,GAAO,CAAA;AACzF,MAAA,IAAA,CAAK,IAAA,CAAK,QAAA,EAAU,WAAA,GAAc,cAAA,GAAiB,WAAW,CAAA;AAAA,IAChE;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,IAAA,EAAoD;AACzD,IAAA,MAAM,IAAA,GAAO,IAAA,CAAK,MAAA,CAAO,GAAA,CAAI,KAAK,UAAU,CAAA;AAC5C,IAAA,IAAI,CAAC,IAAA,EAAM;AACX,IAAA,MAAM,GAAA,GAAM,IAAA,CAAK,OAAA,CAAQ,IAAA,CAAK,MAAM,CAAA;AACpC,IAAA,IAAI,MAAM,CAAA,EAAG;AACb,IAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,IAAK,GAAA,EAAK,CAAA,EAAA,EAAK;AAC7B,MAAA,MAAM,WAAW,IAAA,CAAK,QAAA,CAAS,GAAA,CAAI,IAAA,CAAK,CAAC,CAAC,CAAA;AAC1C,MAAA,IAAI,CAAC,QAAA,EAAU;AACf,MAAA,IAAA,CAAK,IAAA,CAAK,UAAU,MAAM,CAAA;AAAA,IAC5B;AAAA,EACF;AAAA;AAAA,EAGA,UAAU,SAAA,EAA8C;AACtD,IAAA,OAAO,IAAA,CAAK,QAAA,CAAS,GAAA,CAAI,SAAS,CAAA,EAAG,MAAA;AAAA,EACvC;AAAA;AAAA,EAIQ,IAAA,CAAK,UAAoB,SAAA,EAAgC;AAC/D,IAAA,IAAI,KAAK,SAAS,CAAA,IAAK,IAAA,CAAK,QAAA,CAAS,MAAM,CAAA,EAAG;AAC9C,IAAA,QAAA,CAAS,MAAA,GAAS,SAAA;AAClB,IAAA,KAAA,MAAW,EAAA,IAAM,KAAK,SAAA,EAAW;AAC/B,MAAA,IAAI;AACF,QAAA,EAAA,CAAG,QAAA,CAAS,SAAA,EAAW,SAAA,EAAW,QAAA,CAAS,UAAU,CAAA;AAAA,MACvD,CAAA,CAAA,MAAQ;AAAA,MAER;AAAA,IACF;AAAA,EACF;AACF,CAAA;AAEA,SAAS,KAAK,CAAA,EAA0B;AACtC,EAAA,QAAQ,CAAA;AAAG,IACT,KAAK,SAAA;AACH,MAAA,OAAO,CAAA;AAAA,IACT,KAAK,MAAA;AACH,MAAA,OAAO,CAAA;AAAA,IACT,KAAK,WAAA;AACH,MAAA,OAAO,CAAA;AAAA,IACT,KAAK,cAAA;AACH,MAAA,OAAO,CAAA;AAAA,IACT,KAAK,MAAA;AACH,MAAA,OAAO,CAAA;AAAA;AAEb;;;ACtKA,IAAM,OAAA,GAAU,sBAAA;AAChB,IAAM,KAAA,GAAQ,IAAA;AACd,IAAM,OAAA,GAAU,CAAA;AAOhB,IAAI,SAAA,GAAyC,IAAA;AAE7C,SAAS,MAAA,GAA+B;AACtC,EAAA,IAAI,WAAW,OAAO,SAAA;AACtB,EAAA,SAAA,GAAY,IAAI,OAAA,CAAQ,CAAC,OAAA,EAAS,MAAA,KAAW;AAC3C,IAAA,MAAM,GAAA,GAAM,SAAA,CAAU,IAAA,CAAK,OAAA,EAAS,OAAO,CAAA;AAC3C,IAAA,GAAA,CAAI,kBAAkB,MAAM;AAC1B,MAAA,MAAM,KAAK,GAAA,CAAI,MAAA;AACf,MAAA,IAAI,CAAC,EAAA,CAAG,gBAAA,CAAiB,QAAA,CAAS,KAAK,CAAA,EAAG;AACxC,QAAA,EAAA,CAAG,kBAAkB,KAAK,CAAA;AAAA,MAC5B;AAAA,IACF,CAAA;AACA,IAAA,GAAA,CAAI,SAAA,GAAY,MAAM,OAAA,CAAQ,GAAA,CAAI,MAAM,CAAA;AACxC,IAAA,GAAA,CAAI,OAAA,GAAU,MAAM,MAAA,CAAO,GAAA,CAAI,KAAK,CAAA;AAAA,EACtC,CAAC,CAAA;AACD,EAAA,OAAO,SAAA;AACT;AAEA,eAAe,SAAA,CACb,MACA,EAAA,EACY;AACZ,EAAA,MAAM,EAAA,GAAK,MAAM,MAAA,EAAO;AACxB,EAAA,OAAO,IAAI,OAAA,CAAQ,CAAC,OAAA,EAAS,MAAA,KAAW;AACtC,IAAA,MAAM,EAAA,GAAK,EAAA,CAAG,WAAA,CAAY,KAAA,EAAO,IAAI,CAAA;AACrC,IAAA,MAAM,KAAA,GAAQ,EAAA,CAAG,WAAA,CAAY,KAAK,CAAA;AAClC,IAAA,MAAM,MAAA,GAAS,GAAG,KAAK,CAAA;AACvB,IAAA,EAAA,CAAG,aAAa,MAAM;AAEpB,MAAA,IAAI,MAAA,IAAU,OAAO,MAAA,KAAW,QAAA,IAAY,YAAY,MAAA,EAAQ;AAC9D,QAAA,OAAA,CAAS,OAAyB,MAAM,CAAA;AAAA,MAC1C,CAAA,MAAO;AACL,QAAA,OAAA,CAAQ,MAAW,CAAA;AAAA,MACrB;AAAA,IACF,CAAA;AACA,IAAA,EAAA,CAAG,OAAA,GAAU,MAAM,MAAA,CAAO,EAAA,CAAG,KAAK,CAAA;AAClC,IAAA,EAAA,CAAG,OAAA,GAAU,MAAM,MAAA,CAAO,EAAA,CAAG,KAAK,CAAA;AAAA,EACpC,CAAC,CAAA;AACH;AAEO,IAAM,aAAN,MAAoC;AAAA,EACzC,MAAM,UAAU,GAAA,EAAqC;AACnD,IAAA,MAAM,CAAA,GAAI,MAAM,SAAA,CAAU,UAAA,EAAY,CAAC,CAAA,KAAM,CAAA,CAAE,GAAA,CAAI,GAAG,CAAC,CAAA;AACvD,IAAA,IAAI,CAAC,GAAG,OAAO,IAAA;AACf,IAAA,MAAM,EAAA,GAAK,CAAA;AACX,IAAA,OAAO,EAAA,CAAG,IAAA,KAAS,QAAA,GAAY,EAAA,CAAG,KAAA,GAAmB,IAAA;AAAA,EACvD;AAAA,EAEA,MAAM,SAAA,CAAU,GAAA,EAAa,KAAA,EAA8B;AACzD,IAAA,MAAM,EAAA,GAAkB,EAAE,IAAA,EAAM,QAAA,EAAU,KAAA,EAAM;AAChD,IAAA,MAAM,SAAA,CAAU,aAAa,CAAC,CAAA,KAAM,EAAE,GAAA,CAAI,EAAA,EAAI,GAAG,CAAC,CAAA;AAAA,EACpD;AAAA,EAEA,MAAM,SAAS,GAAA,EAAyC;AACtD,IAAA,MAAM,CAAA,GAAI,MAAM,SAAA,CAAU,UAAA,EAAY,CAAC,CAAA,KAAM,CAAA,CAAE,GAAA,CAAI,GAAG,CAAC,CAAA;AACvD,IAAA,IAAI,CAAC,GAAG,OAAO,IAAA;AACf,IAAA,MAAM,EAAA,GAAK,CAAA;AACX,IAAA,OAAO,EAAA,CAAG,IAAA,KAAS,OAAA,GAAW,EAAA,CAAG,KAAA,GAAuB,IAAA;AAAA,EAC1D;AAAA,EAEA,MAAM,QAAA,CAAS,GAAA,EAAa,KAAA,EAAkC;AAC5D,IAAA,MAAM,EAAA,GAAkB,EAAE,IAAA,EAAM,OAAA,EAAS,KAAA,EAAM;AAC/C,IAAA,MAAM,SAAA,CAAU,aAAa,CAAC,CAAA,KAAM,EAAE,GAAA,CAAI,EAAA,EAAI,GAAG,CAAC,CAAA;AAAA,EACpD;AAAA,EAEA,MAAM,OAAO,GAAA,EAA4B;AACvC,IAAA,MAAM,UAAU,WAAA,EAAa,CAAC,MAAM,CAAA,CAAE,MAAA,CAAO,GAAG,CAAC,CAAA;AAAA,EACnD;AAAA,EAEA,MAAM,SAAS,MAAA,EAAmC;AAChD,IAAA,MAAM,EAAA,GAAK,MAAM,MAAA,EAAO;AACxB,IAAA,OAAO,IAAI,OAAA,CAAQ,CAAC,OAAA,EAAS,MAAA,KAAW;AACtC,MAAA,MAAM,MAAgB,EAAC;AACvB,MAAA,MAAM,EAAA,GAAK,EAAA,CAAG,WAAA,CAAY,KAAA,EAAO,UAAU,CAAA;AAC3C,MAAA,MAAM,SAAA,GAAY,EAAA,CAAG,WAAA,CAAY,KAAK,EAAE,aAAA,EAAc;AACtD,MAAA,SAAA,CAAU,YAAY,MAAM;AAC1B,QAAA,MAAM,SAAS,SAAA,CAAU,MAAA;AACzB,QAAA,IAAI,CAAC,MAAA,EAAQ;AACX,UAAA,OAAA,CAAQ,GAAG,CAAA;AACX,UAAA;AAAA,QACF;AACA,QAAA,MAAM,IAAI,MAAA,CAAO,GAAA;AACjB,QAAA,IAAI,EAAE,UAAA,CAAW,MAAM,CAAA,EAAG,GAAA,CAAI,KAAK,CAAC,CAAA;AACpC,QAAA,MAAA,CAAO,QAAA,EAAS;AAAA,MAClB,CAAA;AACA,MAAA,SAAA,CAAU,OAAA,GAAU,MAAM,MAAA,CAAO,SAAA,CAAU,KAAK,CAAA;AAAA,IAClD,CAAC,CAAA;AAAA,EACH;AACF;;;ACxEO,IAAM,SAAA,GAAN,cAAwB,KAAA,CAAM;AAAA,EACnC,WAAA,CACS,MAAA,EACA,IAAA,EACP,OAAA,EACA;AACA,IAAA,KAAA,CAAM,OAAO,CAAA;AAJN,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA;AACA,IAAA,IAAA,CAAA,IAAA,GAAA,IAAA;AAIP,IAAA,IAAA,CAAK,IAAA,GAAO,WAAA;AAAA,EACd;AAAA,EANS,MAAA;AAAA,EACA,IAAA;AAMX,CAAA;AAEO,IAAM,aAAN,MAAiB;AAAA,EACL,OAAA;AAAA,EACA,UAAA;AAAA,EACA,SAAA;AAAA;AAAA,EAGT,MAAA,GAAmC,IAAA;AAAA,EACnC,cAAA,GAAgC,IAAA;AAAA,EAExC,YAAY,IAAA,EAAyB;AACnC,IAAA,IAAA,CAAK,OAAA,GAAU,IAAA,CAAK,UAAA,CAAW,OAAA,CAAQ,OAAO,EAAE,CAAA;AAChD,IAAA,IAAA,CAAK,aAAa,IAAA,CAAK,cAAA;AACvB,IAAA,IAAA,CAAK,YAAY,IAAA,CAAK,SAAA,IAAa,UAAA,CAAW,KAAA,CAAM,KAAK,UAAU,CAAA;AAAA,EACrE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,QAAQ,QAAA,EAA8C;AAC1D,IAAA,MAAM,MAAM,IAAA,CAAK,KAAA,CAAM,IAAA,CAAK,GAAA,KAAQ,GAAI,CAAA;AACxC,IAAA,IACE,IAAA,CAAK,UACL,IAAA,CAAK,cAAA,KAAmB,YACxB,IAAA,CAAK,MAAA,CAAO,SAAA,GAAY,GAAA,GAAM,EAAA,EAC9B;AACA,MAAA,OAAO,IAAA,CAAK,MAAA;AAAA,IACd;AACA,IAAA,MAAM,IAAA,GAAO,MAAM,IAAA,CAAK,UAAA,CAAW,QAAQ,CAAA;AAC3C,IAAA,IAAI,CAAC,KAAK,SAAA,IAAa,OAAO,KAAK,SAAA,KAAc,QAAA,IAAY,CAAC,IAAA,CAAK,aAAA,EAAe;AAChF,MAAA,MAAM,IAAI,MAAM,oEAAoE,CAAA;AAAA,IACtF;AACA,IAAA,IAAA,CAAK,MAAA,GAAS,IAAA;AACd,IAAA,IAAA,CAAK,cAAA,GAAiB,QAAA;AACtB,IAAA,OAAO,IAAA;AAAA,EACT;AAAA;AAAA,EAGA,MAAM,SAAS,QAAA,EAAmC;AAChD,IAAA,OAAA,CAAQ,MAAM,IAAA,CAAK,OAAA,CAAQ,QAAQ,CAAA,EAAG,SAAA;AAAA,EACxC;AAAA;AAAA,EAGA,MAAM,aAAa,QAAA,EAAmC;AACpD,IAAA,OAAA,CAAQ,MAAM,IAAA,CAAK,OAAA,CAAQ,QAAQ,CAAA,EAAG,aAAA;AAAA,EACxC;AAAA;AAAA,EAIA,MAAc,UAAA,CACZ,MAAA,EACA,IAAA,EACA,UACA,IAAA,EACY;AACZ,IAAA,MAAM,KAAA,GAAQ,MAAM,IAAA,CAAK,QAAA,CAAS,QAAQ,CAAA;AAC1C,IAAA,MAAM,OAAA,GAAkC;AAAA,MACtC,aAAA,EAAe,UAAU,KAAK,CAAA;AAAA,KAChC;AACA,IAAA,IAAI,QAAA;AACJ,IAAA,IAAI,SAAS,MAAA,EAAW;AACtB,MAAA,OAAA,CAAQ,cAAc,CAAA,GAAI,kBAAA;AAC1B,MAAA,QAAA,GAAW,IAAA,CAAK,UAAU,IAAI,CAAA;AAAA,IAChC;AACA,IAAA,MAAM,GAAA,GAAM,MAAM,IAAA,CAAK,SAAA,CAAU,GAAG,IAAA,CAAK,OAAO,CAAA,EAAG,IAAI,CAAA,CAAA,EAAI;AAAA,MACzD,MAAA;AAAA,MACA,OAAA;AAAA,MACA,IAAA,EAAM;AAAA,KACP,CAAA;AACD,IAAA,IAAI,CAAC,IAAI,EAAA,EAAI;AACX,MAAA,IAAI,IAAA,GAAO,YAAA;AACX,MAAA,IAAI,MAAM,CAAA,EAAG,GAAA,CAAI,MAAM,CAAA,CAAA,EAAI,IAAI,UAAU,CAAA,CAAA;AACzC,MAAA,IAAI;AACF,QAAA,MAAM,OAAA,GAAW,MAAM,GAAA,CAAI,IAAA,EAAK;AAChC,QAAA,IAAI,OAAA,CAAQ,KAAA,EAAO,IAAA,GAAO,OAAA,CAAQ,KAAA;AAClC,QAAA,IAAI,OAAA,CAAQ,OAAA,EAAS,GAAA,GAAM,OAAA,CAAQ,OAAA;AAAA,MACrC,CAAA,CAAA,MAAQ;AAAA,MAER;AACA,MAAA,MAAM,IAAI,SAAA,CAAU,GAAA,CAAI,MAAA,EAAQ,MAAM,GAAG,CAAA;AAAA,IAC3C;AACA,IAAA,IAAI,GAAA,CAAI,MAAA,KAAW,GAAA,EAAK,OAAO,MAAA;AAC/B,IAAA,OAAQ,MAAM,IAAI,IAAA,EAAK;AAAA,EACzB;AAAA;AAAA,EAIA,eAAA,CAAgB,UAAkB,IAAA,EAAqD;AACrF,IAAA,OAAO,IAAA,CAAK,UAAA,CAAW,MAAA,EAAQ,uBAAA,EAAyB,UAAU,IAAI,CAAA;AAAA,EACxE;AAAA,EAEA,SAAA,CAAU,UAAkB,IAAA,EAAiE;AAC3F,IAAA,MAAM,IAAA,GAAwB,EAAE,QAAA,EAAoB,WAAA,EAAa,IAAA,EAAK;AACtE,IAAA,OAAO,IAAA,CAAK,UAAA,CAAW,MAAA,EAAQ,sBAAA,EAAwB,UAAU,IAAI,CAAA;AAAA,EACvE;AAAA,EAEA,SAAS,QAAA,EAA6C;AACpD,IAAA,OAAO,IAAA,CAAK,UAAA;AAAA,MACV,KAAA;AAAA,MACA,CAAA,8BAAA,EAAiC,kBAAA,CAAmB,QAAQ,CAAC,CAAA,CAAA;AAAA,MAC7D;AAAA,KACF;AAAA,EACF;AAAA,EAEA,QAAA,CAAS,UAAkB,UAAA,EAA+C;AACxE,IAAA,OAAO,IAAA,CAAK,UAAA,CAAW,MAAA,EAAQ,0BAAA,EAA4B,QAAA,EAAU;AAAA,MACnE;AAAA,KACD,CAAA;AAAA,EACH;AAAA,EAEA,WAAA,CAAY,UAAkB,UAAA,EAAkD;AAC9E,IAAA,OAAO,IAAA,CAAK,UAAA;AAAA,MACV,KAAA;AAAA,MACA,CAAA,uCAAA,EAA0C,kBAAA,CAAmB,UAAU,CAAC,CAAA,CAAA;AAAA,MACxE;AAAA,KACF;AAAA,EACF;AAAA;AAAA,EAIA,OAAA,CAAQ,QAAA,EAAkB,KAAA,GAAQ,GAAA,EAA+B;AAC/D,IAAA,OAAO,IAAA,CAAK,UAAA;AAAA,MACV,KAAA;AAAA,MACA,CAAA,qCAAA,EAAwC,kBAAA,CAAmB,QAAQ,CAAC,UAAU,KAAK,CAAA,CAAA;AAAA,MACnF;AAAA,KACF;AAAA,EACF;AAAA,EAEA,GAAA,CAAI,UAAkB,aAAA,EAAsE;AAC1F,IAAA,MAAM,IAAA,GAAmB,EAAE,QAAA,EAAoB,aAAA,EAA6B;AAC5E,IAAA,OAAO,IAAA,CAAK,UAAA,CAAW,MAAA,EAAQ,yBAAA,EAA2B,UAAU,IAAI,CAAA;AAAA,EAC1E;AAAA;AAAA,EAIA,SAAA,CAAU,UAAkB,UAAA,EAA2C;AACrE,IAAA,OAAO,KAAK,UAAA,CAAW,MAAA,EAAQ,oBAAoB,QAAA,EAAU,EAAE,YAAwB,CAAA;AAAA,EACzF;AAAA,EAEA,WAAA,CAAY,UAAkB,UAAA,EAA2C;AACvE,IAAA,OAAO,IAAA,CAAK,UAAA;AAAA,MACV,QAAA;AAAA,MACA,CAAA,iBAAA,EAAoB,kBAAA,CAAmB,UAAU,CAAC,CAAA,CAAA;AAAA,MAClD;AAAA,KACF;AAAA,EACF;AAAA,EAEA,YAAY,QAAA,EAA+C;AACzD,IAAA,OAAO,IAAA,CAAK,UAAA,CAAW,KAAA,EAAO,kBAAA,EAAoB,QAAQ,CAAA;AAAA,EAC5D;AACF,CAAA;;;ACvKO,IAAM,WAAN,MAAe;AAAA,EACZ,IAAA;AAAA,EAGA,MAAA,GAA2B,IAAA;AAAA,EAC3B,KAAA,GAAiB,QAAA;AAAA,EACjB,OAAA,GAAU,CAAA;AAAA,EACV,SAAA,GAAmD,IAAA;AAAA,EACnD,aAAA,GAAgB,KAAA;AAAA,EAExB,YAAY,IAAA,EAAuB;AACjC,IAAA,IAAA,CAAK,IAAA,GAAO;AAAA,MACV,WAAA,EAAa,IAAA,CAAK,WAAA,CAAY,OAAA,CAAQ,OAAO,EAAE,CAAA;AAAA,MAC/C,UAAU,IAAA,CAAK,QAAA;AAAA,MACf,SAAS,IAAA,CAAK,OAAA;AAAA,MACd,OAAA,EAAS,IAAA,CAAK,OAAA,KAAY,MAAM;AAAA,MAAC,CAAA,CAAA;AAAA,MACjC,aAAA,EAAe,IAAA,CAAK,aAAA,IAAkB,UAAA,CAAW,SAAA;AAAA,MACjD,SAAA,EAAW,KAAK,SAAA,IAAa,IAAA;AAAA,MAC7B,cAAA,EAAgB,KAAK,cAAA,IAAkB;AAAA,KACzC;AAAA,EACF;AAAA,EAEA,QAAA,GAAoB;AAClB,IAAA,OAAO,IAAA,CAAK,KAAA;AAAA,EACd;AAAA;AAAA,EAGA,MAAM,OAAA,GAAyB;AAC7B,IAAA,IAAI,IAAA,CAAK,KAAA,KAAU,MAAA,IAAU,IAAA,CAAK,UAAU,YAAA,EAAc;AAC1D,IAAA,IAAA,CAAK,aAAA,GAAgB,KAAA;AACrB,IAAA,OAAO,KAAK,eAAA,EAAgB;AAAA,EAC9B;AAAA;AAAA,EAGA,KAAK,KAAA,EAA4B;AAC/B,IAAA,IAAI,CAAC,IAAA,CAAK,MAAA,IAAU,IAAA,CAAK,UAAU,MAAA,EAAQ;AACzC,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,mBAAA,EAAsB,IAAA,CAAK,KAAK,CAAA,CAAA,CAAG,CAAA;AAAA,IACrD;AACA,IAAA,IAAA,CAAK,MAAA,CAAO,IAAA,CAAK,IAAA,CAAK,SAAA,CAAU,KAAK,CAAC,CAAA;AAAA,EACxC;AAAA;AAAA,EAGA,SAAS,KAAA,EAA0C;AACjD,IAAA,IAAA,CAAK,KAAK,EAAE,IAAA,EAAM,UAAA,EAAY,GAAG,OAAO,CAAA;AAAA,EAC1C;AAAA;AAAA,EAGA,IAAA,GAAa;AACX,IAAA,MAAM,CAAA,GAAmB,EAAE,IAAA,EAAM,UAAA,EAAW;AAC5C,IAAA,IAAA,CAAK,KAAK,CAAC,CAAA;AAAA,EACb;AAAA;AAAA,EAGA,MAAM,KAAA,GAAuB;AAC3B,IAAA,IAAA,CAAK,aAAA,GAAgB,IAAA;AACrB,IAAA,IAAA,CAAK,SAAS,SAAS,CAAA;AACvB,IAAA,IAAI,KAAK,SAAA,EAAW;AAClB,MAAA,aAAA,CAAc,KAAK,SAAS,CAAA;AAC5B,MAAA,IAAA,CAAK,SAAA,GAAY,IAAA;AAAA,IACnB;AACA,IAAA,IAAI,IAAA,CAAK,UAAU,IAAA,CAAK,MAAA,CAAO,eAAe,IAAA,CAAK,IAAA,CAAK,cAAc,IAAA,EAAM;AAC1E,MAAA,IAAA,CAAK,MAAA,CAAO,KAAA,CAAM,GAAA,EAAM,gBAAgB,CAAA;AAAA,IAC1C;AAAA,EACF;AAAA;AAAA,EAIA,MAAc,eAAA,GAAiC;AAC7C,IAAA,IAAA,CAAK,SAAS,YAAY,CAAA;AAC1B,IAAA,MAAM,KAAA,GAAQ,MAAM,IAAA,CAAK,IAAA,CAAK,QAAA,EAAS;AACvC,IAAA,MAAM,GAAA,GAAM,GAAG,IAAA,CAAK,IAAA,CAAK,WAAW,CAAA,sBAAA,EAAyB,kBAAA,CAAmB,KAAK,CAAC,CAAA,CAAA;AACtF,IAAA,MAAM,IAAA,GAAO,KAAK,IAAA,CAAK,aAAA;AACvB,IAAA,MAAM,IAAA,GAAO,IAAI,IAAA,CAAK,GAAG,CAAA;AACzB,IAAA,IAAA,CAAK,MAAA,GAAS,IAAA;AAEd,IAAA,OAAO,IAAI,OAAA,CAAc,CAAC,OAAA,EAAS,MAAA,KAAW;AAC5C,MAAA,IAAA,CAAK,SAAS,MAAM;AAClB,QAAA,IAAA,CAAK,OAAA,GAAU,CAAA;AACf,QAAA,IAAA,CAAK,SAAS,MAAM,CAAA;AACpB,QAAA,IAAA,CAAK,SAAA,EAAU;AACf,QAAA,OAAA,EAAQ;AAAA,MACV,CAAA;AACA,MAAA,IAAA,CAAK,SAAA,GAAY,CAAC,EAAA,KAAqB;AACrC,QAAA,IAAI,KAAA;AACJ,QAAA,IAAI;AACF,UAAA,KAAA,GAAQ,IAAA,CAAK,MAAM,OAAO,EAAA,CAAG,SAAS,QAAA,GAAW,EAAA,CAAG,OAAO,EAAE,CAAA;AAAA,QAC/D,CAAA,CAAA,MAAQ;AACN,UAAA;AAAA,QACF;AACA,QAAA,IAAI;AACF,UAAA,MAAM,GAAA,GAAM,IAAA,CAAK,IAAA,CAAK,OAAA,CAAQ,KAAK,CAAA;AAKnC,UAAA,IAAI,GAAA,IAAO,OAAQ,GAAA,CAAyB,KAAA,KAAU,UAAA,EAAY;AAChE,YAAC,GAAA,CAAyB,MAAM,MAAM;AAAA,YAAC,CAAC,CAAA;AAAA,UAC1C;AAAA,QACF,CAAA,CAAA,MAAQ;AAAA,QAER;AAAA,MACF,CAAA;AACA,MAAA,IAAA,CAAK,OAAA,GAAU,CAAC,GAAA,KAAe;AAG7B,QAAA,IAAI,KAAK,KAAA,KAAU,YAAA,SAAqB,IAAI,KAAA,CAAM,kBAAkB,CAAC,CAAA;AAAA,MACvE,CAAA;AACA,MAAA,IAAA,CAAK,UAAU,MAAM;AACnB,QAAA,IAAA,CAAK,QAAA,EAAS;AACd,QAAA,IAAA,CAAK,MAAA,GAAS,IAAA;AACd,QAAA,IAAI,IAAA,CAAK,aAAA,IAAiB,CAAC,IAAA,CAAK,KAAK,SAAA,EAAW;AAC9C,UAAA,IAAA,CAAK,SAAS,QAAQ,CAAA;AACtB,UAAA;AAAA,QACF;AACA,QAAA,IAAA,CAAK,SAAS,cAAc,CAAA;AAC5B,QAAA,MAAM,KAAA,GAAQ,SAAA,CAAU,IAAA,CAAK,OAAA,EAAS,CAAA;AACtC,QAAA,UAAA,CAAW,MAAM;AAEf,UAAA,IAAA,CAAK,eAAA,EAAgB,CAAE,KAAA,CAAM,MAAM;AAAA,UAAC,CAAC,CAAA;AAAA,QACvC,GAAG,KAAK,CAAA;AAAA,MACV,CAAA;AAAA,IACF,CAAC,CAAA;AAAA,EACH;AAAA,EAEQ,SAAA,GAAkB;AACxB,IAAA,IAAI,IAAA,CAAK,IAAA,CAAK,cAAA,IAAkB,CAAA,EAAG;AACnC,IAAA,IAAA,CAAK,SAAA,GAAY,YAAY,MAAM;AACjC,MAAA,IAAI;AACF,QAAA,IAAA,CAAK,IAAA,EAAK;AAAA,MACZ,CAAA,CAAA,MAAQ;AAAA,MAER;AAAA,IACF,CAAA,EAAG,IAAA,CAAK,IAAA,CAAK,cAAc,CAAA;AAAA,EAC7B;AAAA,EAEQ,QAAA,GAAiB;AACvB,IAAA,IAAI,KAAK,SAAA,EAAW;AAClB,MAAA,aAAA,CAAc,KAAK,SAAS,CAAA;AAC5B,MAAA,IAAA,CAAK,SAAA,GAAY,IAAA;AAAA,IACnB;AAAA,EACF;AAAA,EAEQ,SAAS,CAAA,EAAkB;AACjC,IAAA,IAAI,IAAA,CAAK,UAAU,CAAA,EAAG;AACtB,IAAA,IAAA,CAAK,KAAA,GAAQ,CAAA;AACb,IAAA,IAAI;AACF,MAAA,IAAA,CAAK,IAAA,CAAK,QAAQ,CAAC,CAAA;AAAA,IACrB,CAAA,CAAA,MAAQ;AAAA,IAER;AAAA,EACF;AACF,CAAA;AAEA,SAAS,UAAU,OAAA,EAAyB;AAE1C,EAAA,MAAM,OAAO,IAAA,CAAK,GAAA,CAAI,GAAA,GAAM,CAAA,IAAK,SAAS,GAAM,CAAA;AAChD,EAAA,MAAM,SAAS,IAAA,IAAQ,GAAA,IAAO,IAAA,CAAK,MAAA,KAAW,GAAA,CAAA,GAAO,CAAA,CAAA;AACrD,EAAA,OAAO,KAAK,GAAA,CAAI,GAAA,EAAK,KAAK,KAAA,CAAM,IAAA,GAAO,MAAM,CAAC,CAAA;AAChD;;;ACnLA,IAAM,kBAAA,GAAqB,GAAA;AAC3B,IAAM,qBAAA,GAAwB,GAAA;AAgBvB,IAAM,gBAAN,MAAoB;AAAA,EAGzB,YAAoB,IAAA,EAAqB;AAArB,IAAA,IAAA,CAAA,IAAA,GAAA,IAAA;AAAA,EAAsB;AAAA,EAAtB,IAAA;AAAA,EAFZ,KAAA,uBAAY,GAAA,EAAuB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAS3C,SAAA,CAAU,YAAoB,QAAA,EAAyB;AACrD,IAAA,MAAM,GAAA,GAAM,KAAK,GAAA,EAAI;AACrB,IAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,KAAA,CAAM,GAAA,CAAI,UAAU,CAAA;AACvC,IAAA,IAAI,CAAC,QAAA,EAAU;AAEb,MAAA,IAAI,OAAO,QAAA,EAAU;AACnB,QAAA,IAAA,CAAK,eAAe,KAAK,CAAA;AACzB,QAAA,KAAA,CAAM,QAAA,GAAW,KAAA;AACjB,QAAA,IAAA,CAAK,IAAA,CAAK,YAAY,SAAS,CAAA;AAAA,MACjC;AACA,MAAA;AAAA,IACF;AAEA,IAAA,IAAI,CAAC,KAAA,EAAO;AACV,MAAA,MAAM,KAAA,GAAmB;AAAA,QACvB,aAAA,EAAe,GAAA;AAAA,QACf,aAAA,EAAe,IAAA;AAAA,QACf,QAAA,EAAU;AAAA,OACZ;AACA,MAAA,IAAA,CAAK,KAAA,CAAM,GAAA,CAAI,UAAA,EAAY,KAAK,CAAA;AAChC,MAAA,IAAA,CAAK,gBAAA,CAAiB,YAAY,KAAK,CAAA;AACvC,MAAA,IAAA,CAAK,IAAA,CAAK,YAAY,SAAS,CAAA;AAC/B,MAAA;AAAA,IACF;AAKA,IAAA,IAAI,CAAC,MAAM,QAAA,EAAU;AACnB,MAAA,KAAA,CAAM,QAAA,GAAW,IAAA;AACjB,MAAA,KAAA,CAAM,aAAA,GAAgB,GAAA;AACtB,MAAA,IAAA,CAAK,gBAAA,CAAiB,YAAY,KAAK,CAAA;AACvC,MAAA,IAAA,CAAK,IAAA,CAAK,YAAY,SAAS,CAAA;AAC/B,MAAA;AAAA,IACF;AAIA,IAAA,IAAA,CAAK,eAAe,KAAK,CAAA;AACzB,IAAA,IAAA,CAAK,gBAAA,CAAiB,YAAY,KAAK,CAAA;AACvC,IAAA,IAAI,GAAA,GAAM,KAAA,CAAM,aAAA,IAAiB,kBAAA,EAAoB;AACnD,MAAA,KAAA,CAAM,aAAA,GAAgB,GAAA;AACtB,MAAA,IAAA,CAAK,IAAA,CAAK,YAAY,SAAS,CAAA;AAAA,IACjC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,YAAY,UAAA,EAA0B;AACpC,IAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,KAAA,CAAM,GAAA,CAAI,UAAU,CAAA;AACvC,IAAA,IAAI,CAAC,KAAA,IAAS,CAAC,KAAA,CAAM,QAAA,EAAU;AAC/B,IAAA,IAAA,CAAK,eAAe,KAAK,CAAA;AACzB,IAAA,KAAA,CAAM,QAAA,GAAW,KAAA;AACjB,IAAA,IAAA,CAAK,IAAA,CAAK,YAAY,SAAS,CAAA;AAAA,EACjC;AAAA;AAAA,EAGA,QAAA,GAAiB;AACf,IAAA,KAAA,MAAW,KAAA,IAAS,IAAA,CAAK,KAAA,CAAM,MAAA,EAAO,EAAG;AACvC,MAAA,IAAA,CAAK,eAAe,KAAK,CAAA;AAAA,IAC3B;AACA,IAAA,IAAA,CAAK,MAAM,KAAA,EAAM;AAAA,EACnB;AAAA;AAAA,EAIQ,gBAAA,CAAiB,YAAoB,KAAA,EAAwB;AACnE,IAAA,KAAA,CAAM,aAAA,GAAgB,WAAW,MAAM;AACrC,MAAA,KAAA,CAAM,aAAA,GAAgB,IAAA;AACtB,MAAA,IAAI,CAAC,MAAM,QAAA,EAAU;AACrB,MAAA,KAAA,CAAM,QAAA,GAAW,KAAA;AACjB,MAAA,IAAA,CAAK,IAAA,CAAK,YAAY,SAAS,CAAA;AAAA,IACjC,GAAG,qBAAqB,CAAA;AAAA,EAC1B;AAAA,EAEQ,eAAe,KAAA,EAAwB;AAC7C,IAAA,IAAI,MAAM,aAAA,EAAe;AACvB,MAAA,YAAA,CAAa,MAAM,aAAa,CAAA;AAChC,MAAA,KAAA,CAAM,aAAA,GAAgB,IAAA;AAAA,IACxB;AAAA,EACF;AACF,CAAA;;;AClGA,IAAM,aAAA,GAAgB,aAAA;AACtB,IAAM,aAAA,GAAgB,aAAA;AAEf,IAAM,oBAAN,MAAiD;AAAA,EAC9C,OAAA,GAAmC,IAAA;AAAA;AAAA,EAEnC,QAAA,uBAAe,GAAA,EAAY;AAAA,EAC3B,UAAA,GAAa,CAAA;AAAA,EAErB,MAAM,IAAA,GAAsB;AAAA,EAE5B;AAAA,EAEA,MAAM,UAAA,GAA+B;AACnC,IAAA,OAAO,KAAK,OAAA,KAAY,IAAA;AAAA,EAC1B;AAAA,EAEA,MAAM,gBAAgB,QAAA,EAAyC;AAC7D,IAAA,IAAI,IAAA,CAAK,OAAA,EAAS,MAAM,IAAI,MAAM,wBAAwB,CAAA;AAC1D,IAAA,MAAM,EAAA,GAAK,UAAU,EAAE,CAAA;AACvB,IAAA,IAAA,CAAK,OAAA,GAAU;AAAA,MACb,gBAAA,EAAkB,EAAA;AAAA,MAClB,aAAA,EAAe,UAAU,EAAE,CAAA;AAAA,MAC3B,YAAA,EAAc,UAAU,EAAE,CAAA;AAAA,MAC1B,eAAA,EAAiB,UAAU,EAAE,CAAA;AAAA,MAC7B,cAAA,EAAgB,UAAU,EAAE,CAAA;AAAA,MAC5B,iBAAA,EAAmB,UAAU,EAAE,CAAA;AAAA,MAC/B,WAAA,EAAa,QAAQ,EAAE,CAAA;AAAA,MACvB,OAAA,EAAS,IAAA,CAAK,QAAA,CAAS,QAAQ;AAAA,KACjC;AACA,IAAA,OAAO,KAAK,QAAA,EAAS;AAAA,EACvB;AAAA,EAEA,MAAM,gBAAA,GAA0C;AAC9C,IAAA,IAAI,CAAC,IAAA,CAAK,OAAA,EAAS,MAAM,IAAI,MAAM,YAAY,CAAA;AAC/C,IAAA,OAAO,KAAK,QAAA,EAAS;AAAA,EACvB;AAAA,EAEA,MAAM,oBAAoB,CAAA,EAAsD;AAC9E,IAAA,IAAI,CAAC,IAAA,CAAK,OAAA,EAAS,MAAM,IAAI,MAAM,YAAY,CAAA;AAC/C,IAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,QAAA,CAAS,CAAC,CAAA;AAC7B,IAAA,IAAA,CAAK,OAAA,CAAQ,OAAA,CAAQ,IAAA,CAAK,GAAG,KAAK,CAAA;AAClC,IAAA,OAAO,KAAA;AAAA,EACT;AAAA,EAEA,MAAM,qBAAA,GAAyC;AAC7C,IAAA,OAAO,IAAA,CAAK,OAAA,EAAS,OAAA,CAAQ,MAAA,IAAU,CAAA;AAAA,EACzC;AAAA,EAEA,MAAM,cAAA,CACJ,UAAA,EACA,YAAA,EACA,aACA,SAAA,EAC2B;AAC3B,IAAA,IAAI,CAAC,IAAA,CAAK,OAAA,EAAS,MAAM,IAAI,MAAM,YAAY,CAAA;AAC/C,IAAA,MAAM,GAAA,GAAMA,WAAAA,CAAW,UAAA,EAAY,YAAY,CAAA;AAC/C,IAAA,MAAM,OAAA,GAAU,CAAC,IAAA,CAAK,QAAA,CAAS,IAAI,GAAG,CAAA;AACtC,IAAA,IAAA,CAAK,QAAA,CAAS,IAAI,GAAG,CAAA;AACrB,IAAA,MAAM,MAAA,GAAS,UAAU,aAAA,GAAgB,aAAA;AACzC,IAAA,MAAM,UAAA,GAAa,IAAA,CAAK,MAAA,GAAS,SAAS,CAAA;AAC1C,IAAA,OAAO,EAAE,UAAA,EAAY,OAAA,EAAS,OAAA,GAAU,WAAW,QAAA,EAAS;AAAA,EAC9D;AAAA,EAEA,MAAM,eAAA,CACJ,UAAA,EACA,YAAA,EACA,YACA,OAAA,EACiB;AACjB,IAAA,IAAI,CAAC,IAAA,CAAK,OAAA,EAAS,MAAM,IAAI,MAAM,YAAY,CAAA;AAC/C,IAAA,MAAM,GAAA,GAAMA,WAAAA,CAAW,UAAA,EAAY,YAAY,CAAA;AAC/C,IAAA,IAAI,YAAY,QAAA,EAAU;AACxB,MAAA,IAAA,CAAK,QAAA,CAAS,IAAI,GAAG,CAAA;AAAA,IACvB,WAAW,CAAC,IAAA,CAAK,QAAA,CAAS,GAAA,CAAI,GAAG,CAAA,EAAG;AAClC,MAAA,MAAM,IAAI,MAAM,uCAAuC,CAAA;AAAA,IACzD;AACA,IAAA,MAAM,OAAA,GAAU,KAAK,UAAU,CAAA;AAC/B,IAAA,MAAM,QAAA,GAAW,OAAA,KAAY,QAAA,GAAW,aAAA,GAAgB,aAAA;AACxD,IAAA,IAAI,CAAC,OAAA,CAAQ,UAAA,CAAW,QAAQ,CAAA,EAAG;AACjC,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,uBAAA,EAA0B,QAAQ,CAAA,aAAA,EAAgB,QAAQ,KAAA,CAAM,CAAA,EAAG,EAAE,CAAC,CAAA,CAAE,CAAA;AAAA,IAC1F;AACA,IAAA,OAAO,OAAA,CAAQ,KAAA,CAAM,QAAA,CAAS,MAAM,CAAA;AAAA,EACtC;AAAA,EAEA,MAAM,aAAA,CAAc,UAAA,EAAoB,YAAA,EAAqC;AAC3E,IAAA,IAAA,CAAK,QAAA,CAAS,MAAA,CAAOA,WAAAA,CAAW,UAAA,EAAY,YAAY,CAAC,CAAA;AAAA,EAC3D;AAAA,EAEA,MAAM,UAAA,CAAW,UAAA,EAAoB,YAAA,EAAwC;AAC3E,IAAA,OAAO,KAAK,QAAA,CAAS,GAAA,CAAIA,WAAAA,CAAW,UAAA,EAAY,YAAY,CAAC,CAAA;AAAA,EAC/D;AAAA;AAAA,EAIQ,QAAA,GAAyB;AAC/B,IAAA,IAAI,CAAC,IAAA,CAAK,OAAA,EAAS,MAAM,IAAI,MAAM,YAAY,CAAA;AAC/C,IAAA,MAAM,EAAE,OAAA,EAAS,GAAG,IAAA,KAAS,IAAA,CAAK,OAAA;AAClC,IAAA,OAAO,EAAE,GAAG,IAAA,EAAM,aAAa,CAAC,GAAG,OAAO,CAAA,EAAE;AAAA,EAC9C;AAAA,EAEQ,SAAS,CAAA,EAA6C;AAC5D,IAAA,MAAM,MAAwC,EAAC;AAC/C,IAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,CAAA,EAAG,CAAA,EAAA,EAAK;AAC1B,MAAA,IAAA,CAAK,UAAA,EAAA;AACL,MAAA,GAAA,CAAI,IAAA,CAAK,EAAE,EAAA,EAAI,CAAA,SAAA,EAAY,IAAA,CAAK,UAAU,CAAA,CAAA,EAAI,MAAA,EAAQ,SAAA,CAAU,EAAE,CAAA,EAAG,CAAA;AAAA,IACvE;AACA,IAAA,OAAO,GAAA;AAAA,EACT;AACF;AAEA,SAASA,WAAAA,CAAW,YAAoB,YAAA,EAA8B;AACpE,EAAA,OAAO,CAAA,EAAG,UAAU,CAAA,CAAA,EAAI,YAAY,CAAA,CAAA;AACtC;AAEA,SAAS,UAAU,KAAA,EAAuB;AACxC,EAAA,MAAM,GAAA,GAAM,IAAI,UAAA,CAAW,KAAK,CAAA;AAChC,EAAA,UAAA,CAAW,MAAA,CAAO,gBAAgB,GAAG,CAAA;AAErC,EAAA,OAAO,KAAK,MAAA,CAAO,YAAA,CAAa,GAAG,GAAG,CAAC,CAAA,CAAE,OAAA,CAAQ,KAAA,EAAO,EAAE,EAAE,OAAA,CAAQ,KAAA,EAAO,GAAG,CAAA,CAAE,OAAA,CAAQ,OAAO,GAAG,CAAA;AACpG;AAEA,SAAS,QAAQ,GAAA,EAAqB;AAGpC,EAAA,MAAM,GAAA,GAAM,GAAA,CAAI,KAAA,CAAM,CAAA,EAAG,EAAE,CAAA;AAC3B,EAAA,OAAO,IAAI,KAAA,CAAM,SAAS,CAAA,EAAG,IAAA,CAAK,GAAG,CAAA,IAAK,GAAA;AAC5C;;;AC1IO,IAAM,gBAAN,MAAuC;AAAA,EACpC,GAAA,uBAAU,GAAA,EAAyB;AAAA,EAE3C,MAAM,UAAU,GAAA,EAAqC;AACnD,IAAA,MAAM,CAAA,GAAI,IAAA,CAAK,GAAA,CAAI,GAAA,CAAI,GAAG,CAAA;AAC1B,IAAA,OAAO,CAAA,EAAG,IAAA,KAAS,QAAA,GAAY,CAAA,CAAE,KAAA,GAAmB,IAAA;AAAA,EACtD;AAAA,EACA,MAAM,SAAA,CAAU,GAAA,EAAa,KAAA,EAA8B;AACzD,IAAA,IAAA,CAAK,IAAI,GAAA,CAAI,GAAA,EAAK,EAAE,IAAA,EAAM,QAAA,EAAU,OAAO,CAAA;AAAA,EAC7C;AAAA,EACA,MAAM,SAAS,GAAA,EAAyC;AACtD,IAAA,MAAM,CAAA,GAAI,IAAA,CAAK,GAAA,CAAI,GAAA,CAAI,GAAG,CAAA;AAC1B,IAAA,OAAO,CAAA,EAAG,IAAA,KAAS,OAAA,GAAW,CAAA,CAAE,KAAA,GAAuB,IAAA;AAAA,EACzD;AAAA,EACA,MAAM,QAAA,CAAS,GAAA,EAAa,KAAA,EAAkC;AAC5D,IAAA,IAAA,CAAK,IAAI,GAAA,CAAI,GAAA,EAAK,EAAE,IAAA,EAAM,OAAA,EAAS,OAAO,CAAA;AAAA,EAC5C;AAAA,EACA,MAAM,OAAO,GAAA,EAA4B;AACvC,IAAA,IAAA,CAAK,GAAA,CAAI,OAAO,GAAG,CAAA;AAAA,EACrB;AAAA,EACA,MAAM,SAAS,MAAA,EAAmC;AAChD,IAAA,MAAM,MAAgB,EAAC;AACvB,IAAA,KAAA,MAAW,CAAA,IAAK,IAAA,CAAK,GAAA,CAAI,IAAA,EAAK,EAAG;AAC/B,MAAA,IAAI,EAAE,UAAA,CAAW,MAAM,CAAA,EAAG,GAAA,CAAI,KAAK,CAAC,CAAA;AAAA,IACtC;AACA,IAAA,OAAO,GAAA;AAAA,EACT;AACF;;;ACJO,IAAMC,QAAAA,GAAU;AAChB,IAAMC,yBAAAA,GAA2B;AA+FxC,IAAM,uBAAA,GAA0B,GAAA;AAChC,IAAM,yBAAA,GAA4B,EAAA;AAClC,IAAM,iBAAA,GAAoB,2BAAA;AAW1B,SAAS,WAAA,CAAY,YAAoB,YAAA,EAA8B;AACrE,EAAA,OAAO,CAAA,eAAA,EAAkB,UAAU,CAAA,CAAA,EAAI,YAAY,CAAA,CAAA;AACrD;AAEO,IAAM,kBAAA,GAAN,MAAM,mBAAA,CAAmB;AAAA,EACtB,QAAA;AAAA,EACA,IAAA;AAAA,EACA,EAAA;AAAA,EACA,MAAA;AAAA,EACA,KAAA;AAAA,EACA,SAAA;AAAA,EACA,QAAA;AAAA,EACA,WAAA;AAAA,EACA,QAAA;AAAA,EACA,MAAA;AAAA,EACA,MAAA,GAAS,IAAI,MAAA,EAAO;AAAA,EACpB,SAAA;AAAA,EACA,SAAA,uBAAgB,GAAA,EAA8C;AAAA;AAAA,EAG9D,eAAA,uBAAsB,GAAA,EAAsB;AAAA,EAC5C,kBAAA,GAA2D,IAAA;AAAA;AAAA,EAE3D,UAAA,GAA4B,IAAA;AAAA;AAAA,EAE5B,mBAAA,uBAA0B,GAAA,EAAY;AAAA;AAAA;AAAA;AAAA,EAItC,uBAAA,GAA0B,KAAA;AAAA;AAAA,EAE1B,iBAAA,GAAoC,IAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAO5C,aAAa,QAAQ,IAAA,EAAmD;AACtE,IAAA,MAAM,IAAA,GAAO,IAAI,mBAAA,EAAmB;AACpC,IAAA,MAAM,IAAA,CAAK,UAAU,IAAI,CAAA;AACzB,IAAA,OAAO,IAAA;AAAA,EACT;AAAA;AAAA,EAGQ,WAAA,GAAc;AAAA,EAAC;AAAA;AAAA,EAGvB,IAAI,eAAA,GAA0B;AAC5B,IAAA,OAAO,IAAA,CAAK,QAAA;AAAA,EACd;AAAA;AAAA,EAIA,MAAM,QAAA,CAAS,UAAA,EAAoB,IAAA,EAAc,IAAA,EAA8C;AAC7F,IAAA,MAAM,KAAA,GAAQ,OAAA,CAAQ,IAAA,EAAM,IAAA,EAAM,OAAO,CAAA;AACzC,IAAA,MAAM,KAAK,WAAA,CAAY,UAAA,EAAY,OAAO,EAAE,SAAA,EAAW,OAAO,CAAA;AAG9D,IAAA,IAAI,KAAK,UAAA,EAAY;AACnB,MAAA,MAAM,IAAA,CAAK,SAAS,GAAA,CAAI;AAAA,QACtB,IAAI,KAAA,CAAM,EAAA;AAAA,QACV,UAAA;AAAA,QACA,cAAc,IAAA,CAAK,UAAA;AAAA,QACnB,MAAM,KAAA,CAAM,IAAA;AAAA,QACZ,QAAQ,KAAA,CAAM,YAAA;AAAA,QACd,QAAA,EAAU,IAAA;AAAA,QACV,SAAA,EAAW,IAAA;AAAA,QACX,GAAI,MAAM,OAAA,KAAY,MAAA,GAAY,EAAE,OAAA,EAAS,KAAA,CAAM,OAAA,EAAQ,GAAI;AAAC,OACjE,CAAA;AAAA,IACH;AACA,IAAA,MAAM,IAAA,CAAK,QAAA,CAAS,UAAA,EAAY,KAAK,CAAA;AACrC,IAAA,IAAA,CAAK,SAAA,CAAU,YAAY,UAAU,CAAA;AACrC,IAAA,OAAO,KAAA,CAAM,EAAA;AAAA,EACf;AAAA,EAEA,MAAM,WAAA,CAAY,UAAA,EAAoB,QAAA,EAAkBC,QAAAA,EAAkC;AACxF,IAAA,MAAM,KAAA,GAAQ,OAAA,CAAQ,QAAA,EAAUA,QAAO,CAAA;AACvC,IAAA,MAAM,KAAK,WAAA,CAAY,UAAA,EAAY,OAAO,EAAE,SAAA,EAAW,OAAO,CAAA;AAC9D,IAAA,IAAI,KAAK,UAAA,EAAY;AACnB,MAAA,MAAM,IAAA,CAAK,SAAS,SAAA,CAAU;AAAA,QAC5B,QAAA;AAAA,QACA,cAAc,IAAA,CAAK,UAAA;AAAA,QACnB,OAAA,EAAAA,QAAAA;AAAA,QACA,UAAU,KAAA,CAAM;AAAA,OACjB,CAAA;AAAA,IACH;AACA,IAAA,MAAM,IAAA,CAAK,QAAA,CAAS,UAAA,EAAY,KAAK,CAAA;AACrC,IAAA,OAAO,KAAA,CAAM,EAAA;AAAA,EACf;AAAA,EAEA,MAAM,aAAA,CAAc,UAAA,EAAoB,QAAA,EAAmC;AACzE,IAAA,MAAM,KAAA,GAAQ,UAAU,QAAQ,CAAA;AAChC,IAAA,MAAM,KAAK,WAAA,CAAY,UAAA,EAAY,OAAO,EAAE,SAAA,EAAW,OAAO,CAAA;AAC9D,IAAA,IAAI,KAAK,UAAA,EAAY;AACnB,MAAA,MAAM,IAAA,CAAK,SAAS,WAAA,CAAY;AAAA,QAC9B,QAAA;AAAA,QACA,eAAe,IAAA,CAAK,UAAA;AAAA,QACpB,WAAW,KAAA,CAAM;AAAA,OAClB,CAAA;AAAA,IACH;AACA,IAAA,MAAM,IAAA,CAAK,QAAA,CAAS,UAAA,EAAY,KAAK,CAAA;AACrC,IAAA,OAAO,KAAA,CAAM,EAAA;AAAA,EACf;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,QAAA,CAAS,UAAA,EAAoB,aAAA,EAAsC;AACvE,IAAA,IAAI,CAAE,MAAM,IAAA,CAAK,sBAAA,EAAuB,EAAI;AAC5C,IAAA,MAAM,KAAA,GAAQ,QAAQ,aAAa,CAAA;AACnC,IAAA,MAAM,KAAK,WAAA,CAAY,UAAA,EAAY,OAAO,EAAE,SAAA,EAAW,OAAO,CAAA;AAC9D,IAAA,MAAM,IAAA,CAAK,QAAA,CAAS,UAAA,EAAY,KAAK,CAAA;AAAA,EACvC;AAAA,EAEA,SAAA,CAAU,YAAoB,QAAA,EAAyB;AACrD,IAAA,IAAA,CAAK,SAAA,CAAU,SAAA,CAAU,UAAA,EAAY,QAAQ,CAAA;AAAA,EAC/C;AAAA;AAAA;AAAA,EAKA,MAAM,uBAAuB,OAAA,EAAiC;AAC5D,IAAA,MAAM,KAAK,KAAA,CAAM,SAAA,CAAU,iBAAA,EAAmB,OAAA,GAAU,MAAM,GAAG,CAAA;AACjE,IAAA,IAAA,CAAK,iBAAA,GAAoB,OAAA;AAAA,EAC3B;AAAA;AAAA,EAGA,MAAM,sBAAA,GAA2C;AAC/C,IAAA,IAAI,IAAA,CAAK,iBAAA,KAAsB,IAAA,EAAM,OAAO,IAAA,CAAK,iBAAA;AACjD,IAAA,MAAM,GAAA,GAAM,MAAM,IAAA,CAAK,KAAA,CAAM,UAAU,iBAAiB,CAAA;AACxD,IAAA,MAAM,OAAA,GAAU,GAAA,KAAQ,IAAA,GAAO,IAAA,GAAO,GAAA,KAAQ,GAAA;AAC9C,IAAA,IAAA,CAAK,iBAAA,GAAoB,OAAA;AACzB,IAAA,OAAO,OAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,oBAAoB,UAAA,EAAgD;AACxE,IAAA,MAAM,OAAA,GAAU,MAAM,IAAA,CAAK,WAAA,CAAY,eAAe,UAAU,CAAA;AAChE,IAAA,MAAM,MAAyB,EAAC;AAChC,IAAA,KAAA,MAAW,KAAK,OAAA,EAAS;AACvB,MAAA,MAAM,WAAW,MAAM,IAAA,CAAK,oBAAA,CAAqB,UAAA,EAAY,EAAE,QAAQ,CAAA;AACvE,MAAA,GAAA,CAAI,IAAA,CAAK;AAAA,QACP,UAAU,CAAA,CAAE,QAAA;AAAA,QACZ,aAAa,CAAA,CAAE,WAAA;AAAA,QACf,cAAc,CAAA,CAAE,YAAA;AAAA,QAChB;AAAA,OACD,CAAA;AAAA,IACH;AACA,IAAA,OAAO,GAAA;AAAA,EACT;AAAA;AAAA,EAGA,MAAM,wBAAA,CACJ,UAAA,EACA,YAAA,EACwB;AACxB,IAAA,MAAM,IAAA,GAAO,MAAM,IAAA,CAAK,WAAA,CAAY,eAAe,UAAU,CAAA;AAC7D,IAAA,OAAO,IAAA,CAAK,KAAK,CAAC,CAAA,KAAM,EAAE,QAAA,KAAa,YAAY,GAAG,WAAA,IAAe,IAAA;AAAA,EACvE;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,sBAAA,CACJ,UAAA,EACA,YAAA,EACA,QAAA,EACe;AACf,IAAA,MAAM,GAAA,GAAM,WAAA,CAAY,UAAA,EAAY,YAAY,CAAA;AAChD,IAAA,IAAI,QAAA,EAAU;AACZ,MAAA,MAAM,IAAA,CAAK,KAAA,CAAM,SAAA,CAAU,GAAA,EAAK,GAAG,CAAA;AAAA,IACrC,CAAA,MAAO;AACL,MAAA,MAAM,IAAA,CAAK,KAAA,CAAM,MAAA,CAAO,GAAG,CAAA;AAAA,IAC7B;AAAA,EACF;AAAA,EAEA,MAAM,oBAAA,CAAqB,UAAA,EAAoB,YAAA,EAAwC;AACrF,IAAA,OAAQ,MAAM,KAAK,KAAA,CAAM,SAAA,CAAU,YAAY,UAAA,EAAY,YAAY,CAAC,CAAA,KAAO,GAAA;AAAA,EACjF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,UAAA,CACE,UAAA,EACA,IAAA,GAAkD,EAAC,EACzB;AAC1B,IAAA,OAAO,IAAA,CAAK,QAAA,CAAS,WAAA,CAAY,UAAA,EAAY,IAAI,CAAA;AAAA,EACnD;AAAA;AAAA,EAIA,UAAU,UAAA,EAA2C;AACnD,IAAA,OAAO,IAAA,CAAK,IAAA,CAAK,SAAA,CAAU,IAAA,CAAK,UAAU,UAAU,CAAA;AAAA,EACtD;AAAA,EACA,YAAY,UAAA,EAA2C;AACrD,IAAA,OAAO,IAAA,CAAK,IAAA,CAAK,WAAA,CAAY,IAAA,CAAK,UAAU,UAAU,CAAA;AAAA,EACxD;AAAA,EACA,MAAM,eAAA,GAAqC;AACzC,IAAA,MAAM,IAAI,MAAM,IAAA,CAAK,IAAA,CAAK,WAAA,CAAY,KAAK,QAAQ,CAAA;AACnD,IAAA,OAAO,CAAA,CAAE,OAAA;AAAA,EACX;AAAA;AAAA,EAIA,EAAA,CAAwB,OAAU,EAAA,EAA6B;AAC7D,IAAA,IAAI,GAAA,GAAM,IAAA,CAAK,SAAA,CAAU,GAAA,CAAI,KAAK,CAAA;AAClC,IAAA,IAAI,CAAC,GAAA,EAAK;AACR,MAAA,GAAA,uBAAU,GAAA,EAAI;AACd,MAAA,IAAA,CAAK,SAAA,CAAU,GAAA,CAAI,KAAA,EAAO,GAAG,CAAA;AAAA,IAC/B;AACA,IAAA,GAAA,CAAI,IAAI,EAA8B,CAAA;AACtC,IAAA,OAAO,MAAM,GAAA,CAAK,MAAA,CAAO,EAA8B,CAAA;AAAA,EACzD;AAAA;AAAA,EAIA,MAAM,UAAA,GAA4B;AAChC,IAAA,IAAA,CAAK,UAAU,QAAA,EAAS;AACxB,IAAA,IAAA,CAAK,kBAAA,EAAmB;AACxB,IAAA,MAAM,IAAA,CAAK,GAAG,KAAA,EAAM;AAAA,EACtB;AAAA;AAAA,EAIA,MAAc,UAAU,IAAA,EAAqC;AAC3D,IAAA,IAAA,CAAK,KAAA,GAAQ,IAAA,CAAK,KAAA,IAAS,IAAI,UAAA,EAAW;AAC1C,IAAA,IAAA,CAAK,MAAA,GAAS,KAAK,MAAA,IAAU,IAAI,iBAAiB,EAAE,KAAA,EAAO,IAAA,CAAK,KAAA,EAAO,CAAA;AACvE,IAAA,MAAM,IAAA,CAAK,OAAO,IAAA,EAAK;AAEvB,IAAA,IAAA,CAAK,QAAA,GAAW,MAAM,oBAAA,CAAqB,IAAA,CAAK,KAAK,CAAA;AAErD,IAAA,IAAA,CAAK,IAAA,GAAO,IAAI,UAAA,CAAW;AAAA,MACzB,YAAY,IAAA,CAAK,UAAA;AAAA,MACjB,gBAAgB,IAAA,CAAK,cAAA;AAAA,MACrB,GAAI,KAAK,SAAA,GAAY,EAAE,WAAW,IAAA,CAAK,SAAA,KAAc;AAAC,KACvD,CAAA;AAGD,IAAA,MAAM,OAAO,MAAM,IAAA,CAAK,IAAA,CAAK,OAAA,CAAQ,KAAK,QAAQ,CAAA;AAClD,IAAA,IAAA,CAAK,UAAA,GAAa,eAAA,CAAgB,IAAA,CAAK,SAAS,CAAA;AAEhD,IAAA,IAAA,CAAK,SAAA,GAAY,IAAI,gBAAA,CAAiB,EAAE,IAAA,EAAM,IAAA,CAAK,IAAA,EAAM,MAAA,EAAQ,IAAA,CAAK,MAAA,EAAQ,QAAA,EAAU,IAAA,CAAK,UAAU,CAAA;AACvG,IAAA,MAAM,IAAA,CAAK,UAAU,eAAA,EAAgB;AAErC,IAAA,IAAA,CAAK,QAAA,GAAW,IAAI,cAAA,CAAe;AAAA,MACjC,MAAM,IAAA,CAAK,IAAA;AAAA,MACX,QAAQ,IAAA,CAAK,MAAA;AAAA,MACb,cAAc,IAAA,CAAK,QAAA;AAAA,MACnB,YAAY,IAAA,CAAK;AAAA,KAClB,CAAA;AACD,IAAA,IAAA,CAAK,WAAA,GAAc,IAAI,eAAA,CAAgB,EAAE,IAAA,EAAM,KAAK,IAAA,EAAM,YAAA,EAAc,IAAA,CAAK,QAAA,EAAU,CAAA;AACvF,IAAA,IAAA,CAAK,QAAA,GAAW,IAAI,YAAA,CAAa,IAAA,CAAK,KAAK,CAAA;AAC3C,IAAA,IAAA,CAAK,MAAA,GAAS,IAAI,aAAA,EAAc;AAChC,IAAA,IAAA,CAAK,MAAA,CAAO,EAAA,CAAG,CAAC,SAAA,EAAW,QAAQ,UAAA,KAAe;AAChD,MAAA,IAAA,CAAK,SAAS,cAAA,EAAgB,EAAE,UAAA,EAAY,SAAA,EAAW,QAAQ,CAAA;AAAA,IACjE,CAAC,CAAA;AAED,IAAA,IAAA,CAAK,SAAA,GAAY,IAAI,aAAA,CAAc,CAAC,YAAY,KAAA,KAAU;AAExD,MAAA,IAAA,CAAK,WAAA,CAAY,UAAA,EAAY,SAAA,CAAU,KAAK,CAAA,EAAG,EAAE,SAAA,EAAW,IAAA,EAAM,CAAA,CAAE,KAAA,CAAM,MAAM;AAAA,MAAC,CAAC,CAAA;AAAA,IACpF,CAAC,CAAA;AAID,IAAA,MAAM,OAAA,GAAU,IAAA,CAAK,aAAA,CAAc,OAAA,CAAQ,kBAAkB,EAAE,CAAA;AAC/D,IAAA,IAAA,CAAK,EAAA,GAAK,IAAI,QAAA,CAAS;AAAA,MACrB,WAAA,EAAa,OAAA;AAAA,MACb,UAAU,MAAM,IAAA,CAAK,IAAA,CAAK,QAAA,CAAS,KAAK,QAAQ,CAAA;AAAA,MAChD,OAAA,EAAS,CAAC,CAAA,KAAM,IAAA,CAAK,QAAQ,CAAC,CAAA;AAAA,MAC9B,OAAA,EAAS,CAAC,CAAA,KAAM,IAAA,CAAK,UAAU,CAAC;AAAA,KACjC,CAAA;AACD,IAAA,MAAM,IAAA,CAAK,GAAG,OAAA,EAAQ;AAGtB,IAAA,MAAM,KAAK,YAAA,EAAa;AAIxB,IAAA,KAAK,IAAA,CAAK,SAAA,CAAU,aAAA,EAAc,CAAE,MAAM,MAAM;AAAA,IAAC,CAAC,CAAA;AAQlD,IAAA,IAAI,KAAK,UAAA,EAAY;AACnB,MAAA,KAAK,KAAK,QAAA,CAAS,kBAAA,CAAmB,KAAK,UAAU,CAAA,CAAE,MAAM,MAAM;AAAA,MAAC,CAAC,CAAA;AAAA,IACvE;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQQ,UAAU,CAAA,EAAiB;AACjC,IAAA,IAAI,MAAM,MAAA,EAAQ;AAClB,IAAA,KAAK,IAAA,CAAK,OAAO,IAAA,EAAK;AACtB,IAAA,KAAK,IAAA,CAAK,YAAA,EAAa,CAAE,KAAA,CAAM,MAAM;AAAA,IAAC,CAAC,CAAA;AAGvC,IAAA,KAAK,IAAA,CAAK,SAAA,CAAU,aAAA,EAAc,CAAE,MAAM,MAAM;AAAA,IAAC,CAAC,CAAA;AAAA,EACpD;AAAA;AAAA;AAAA;AAAA,EAKQ,eAAA,GAAkB,KAAA;AAAA,EAE1B,MAAc,YAAA,GAA8B;AAC1C,IAAA,IAAI,KAAK,eAAA,EAAiB;AAC1B,IAAA,IAAA,CAAK,eAAA,GAAkB,IAAA;AACvB,IAAA,IAAI;AACF,MAAA,OAAO,IAAA,EAAM;AACX,QAAA,MAAM,IAAI,MAAM,IAAA,CAAK,KAAK,OAAA,CAAQ,IAAA,CAAK,UAAU,GAAG,CAAA;AACpD,QAAA,IAAI,CAAA,CAAE,SAAA,CAAU,MAAA,KAAW,CAAA,EAAG;AAC9B,QAAA,MAAM,WAAqB,EAAC;AAC5B,QAAA,KAAA,MAAW,GAAA,IAAO,EAAE,SAAA,EAAW;AAC7B,UAAA,IAAI;AACF,YAAA,MAAM,KAAK,uBAAA,CAAwB;AAAA,cACjC,YAAY,GAAA,CAAI,YAAA;AAAA,cAChB,cAAc,GAAA,CAAI,cAAA;AAAA,cAClB,YAAY,GAAA,CAAI,UAAA;AAAA,cAChB,SAAS,GAAA,CAAI;AAAA,aACd,CAAA;AACD,YAAA,QAAA,CAAS,IAAA,CAAK,IAAI,YAAY,CAAA;AAAA,UAChC,CAAA,CAAA,MAAQ;AAAA,UAER;AAAA,QACF;AACA,QAAA,IAAI,QAAA,CAAS,WAAW,CAAA,EAAG;AAC3B,QAAA,MAAM,IAAA,CAAK,IAAA,CAAK,GAAA,CAAI,IAAA,CAAK,UAAU,QAAQ,CAAA;AAAA,MAC7C;AAAA,IACF,CAAA,SAAE;AACA,MAAA,IAAA,CAAK,eAAA,GAAkB,KAAA;AAAA,IACzB;AAAA,EACF;AAAA,EAEA,MAAc,QAAQ,KAAA,EAAoC;AACxD,IAAA,IAAI,KAAA,CAAM,SAAS,cAAA,EAAgB;AACjC,MAAA,MAAM,KAAK,uBAAA,CAAwB;AAAA,QACjC,YAAY,KAAA,CAAM,YAAA;AAAA,QAClB,cAAc,KAAA,CAAM,cAAA;AAAA,QACpB,YAAY,KAAA,CAAM,UAAA;AAAA,QAClB,SAAS,KAAA,CAAM;AAAA,OAChB,CAAA;AACD,MAAA;AAAA,IACF;AACA,IAAA,IAAI,KAAA,CAAM,SAAS,gBAAA,EAAkB;AACnC,MAAA,KAAA,MAAW,CAAA,IAAK,MAAM,OAAA,EAAS;AAC7B,QAAA,IAAA,CAAK,MAAA,CAAO,YAAA,CAAa,CAAA,CAAE,YAAA,EAAc,EAAE,MAAM,CAAA;AAAA,MACnD;AACA,MAAA;AAAA,IACF;AAAA,EAEF;AAAA,EAEA,MAAc,wBAAwB,IAAA,EAKpB;AAChB,IAAA,IAAI,SAAA;AACJ,IAAA,IAAI;AACF,MAAA,SAAA,GAAY,MAAM,KAAK,QAAA,CAAS,OAAA;AAAA,QAC9B,IAAA,CAAK,UAAA;AAAA,QACL,IAAA,CAAK,YAAA;AAAA,QACL,IAAA,CAAK,UAAA;AAAA,QACL,IAAA,CAAK;AAAA,OACP;AAAA,IACF,SAAS,QAAA,EAAU;AAOjB,MAAA,MAAM,KAAK,QAAA,CAAS,gBAAA,CAAiB,IAAA,CAAK,UAAA,EAAY,KAAK,YAAY,CAAA;AACvE,MAAA,IAAA,CAAK,WAAA,CAAY,UAAA,CAAW,IAAA,CAAK,UAAU,CAAA;AAC3C,MAAA,IAAI;AACF,QAAA,MAAM,IAAA,CAAK,WAAA,CAAY,OAAA,CAAQ,IAAA,CAAK,UAAU,CAAA;AAAA,MAChD,CAAA,CAAA,MAAQ;AAAA,MAER;AACA,MAAA,IAAI;AACF,QAAA,SAAA,GAAY,MAAM,KAAK,QAAA,CAAS,OAAA;AAAA,UAC9B,IAAA,CAAK,UAAA;AAAA,UACL,IAAA,CAAK,YAAA;AAAA,UACL,IAAA,CAAK,UAAA;AAAA,UACL,IAAA,CAAK;AAAA,SACP;AAAA,MACF,CAAA,CAAA,MAAQ;AAEN,QAAA,MAAM,QAAA;AAAA,MACR;AAAA,IACF;AAKA,IAAA,MAAM,IAAA,CAAK,uBAAA,CAAwB,IAAA,CAAK,UAAA,EAAY,KAAK,YAAY,CAAA;AAErE,IAAA,MAAM,QAAQ,gBAAA,CAAiB,IAAI,aAAY,CAAE,MAAA,CAAO,SAAS,CAAC,CAAA;AAClE,IAAA,IAAI,CAAC,KAAA,EAAO;AACZ,IAAA,MAAM,KAAK,oBAAA,CAAqB,IAAA,CAAK,UAAA,EAAY,IAAA,CAAK,cAAc,KAAK,CAAA;AAAA,EAC3E;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAc,uBAAA,CAAwB,UAAA,EAAoB,YAAA,EAAqC;AAC7F,IAAA,MAAM,IAAA,GAAO,CAAA,EAAG,UAAU,CAAA,CAAA,EAAI,YAAY,CAAA,CAAA;AAC1C,IAAA,IAAI,IAAA,CAAK,mBAAA,CAAoB,GAAA,CAAI,IAAI,CAAA,EAAG;AAExC,IAAA,IAAI,OAAA;AACJ,IAAA,IAAI;AACF,MAAA,OAAA,GAAU,MAAM,IAAA,CAAK,WAAA,CAAY,cAAA,CAAe,UAAU,CAAA;AAAA,IAC5D,CAAA,CAAA,MAAQ;AACN,MAAA;AAAA,IACF;AACA,IAAA,IAAI,QAAQ,OAAA,CAAQ,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,aAAa,YAAY,CAAA;AAC3D,IAAA,IAAI,CAAC,KAAA,EAAO;AAEV,MAAA,IAAI,KAAA;AACJ,MAAA,IAAI;AACF,QAAA,KAAA,GAAQ,MAAM,IAAA,CAAK,WAAA,CAAY,OAAA,CAAQ,UAAU,CAAA;AAAA,MACnD,CAAA,CAAA,MAAQ;AACN,QAAA;AAAA,MACF;AACA,MAAA,KAAA,GAAQ,MAAM,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,aAAa,YAAY,CAAA;AACrD,MAAA,IAAI,CAAC,KAAA,EAAO;AAAA,IACd;AAEA,IAAA,IAAA,CAAK,mBAAA,CAAoB,IAAI,IAAI,CAAA;AAOjC,IAAA,IAAI;AACF,MAAA,MAAM,IAAA,CAAK,QAAA,CAAS,kBAAA,CAAmB,UAAU,CAAA;AAAA,IACnD,CAAA,CAAA,MAAQ;AAAA,IAER;AACA,IAAA,IAAA,CAAK,SAAS,eAAA,EAAiB;AAAA,MAC7B,UAAA;AAAA,MACA,YAAA;AAAA,MACA,aAAa,KAAA,CAAM;AAAA,KACpB,CAAA;AAAA,EACH;AAAA,EAEA,MAAc,oBAAA,CACZ,UAAA,EACA,YAAA,EACA,KAAA,EACe;AACf,IAAA,QAAQ,MAAM,IAAA;AAAM,MAClB,KAAK,MAAA,EAAQ;AACX,QAAA,MAAM,IAAA,CAAK,SAAS,GAAA,CAAI;AAAA,UACtB,IAAI,KAAA,CAAM,EAAA;AAAA,UACV,UAAA;AAAA,UACA,YAAA,EAAc,UAAA;AAAA,UACd,MAAM,KAAA,CAAM,IAAA;AAAA,UACZ,QAAQ,KAAA,CAAM,YAAA;AAAA,UACd,QAAA,EAAU,IAAA;AAAA,UACV,SAAA,EAAW,IAAA;AAAA,UACX,GAAI,MAAM,OAAA,KAAY,MAAA,GAAY,EAAE,OAAA,EAAS,KAAA,CAAM,OAAA,EAAQ,GAAI;AAAC,SACjE,CAAA;AACD,QAAA,IAAA,CAAK,SAAS,SAAA,EAAW;AAAA,UACvB,UAAA;AAAA,UACA,YAAA;AAAA,UACA,YAAA,EAAc,UAAA;AAAA,UACd,OAAA,EAAS;AAAA,YACP,IAAI,KAAA,CAAM,EAAA;AAAA,YACV,MAAM,KAAA,CAAM,IAAA;AAAA,YACZ,QAAQ,KAAA,CAAM,YAAA;AAAA,YACd,GAAI,MAAM,OAAA,KAAY,MAAA,GAAY,EAAE,OAAA,EAAS,KAAA,CAAM,OAAA,EAAQ,GAAI;AAAC;AAClE,SACD,CAAA;AACD,QAAA,IAAA,CAAK,gBAAA,CAAiB,UAAA,EAAY,YAAA,EAAc,KAAA,CAAM,EAAE,CAAA;AACxD,QAAA;AAAA,MACF;AAAA,MACA,KAAK,MAAA,EAAQ;AACX,QAAA,MAAM,OAAA,GAAU,MAAM,IAAA,CAAK,QAAA,CAAS,SAAA,CAAU;AAAA,UAC5C,UAAU,KAAA,CAAM,QAAA;AAAA,UAChB,YAAA,EAAc,UAAA;AAAA,UACd,SAAS,KAAA,CAAM,IAAA;AAAA,UACf,UAAU,KAAA,CAAM;AAAA,SACjB,CAAA;AACD,QAAA,IAAI,OAAA,EAAS;AACX,UAAA,IAAA,CAAK,SAAS,eAAA,EAAiB;AAAA,YAC7B,UAAA;AAAA,YACA,YAAA,EAAc,UAAA;AAAA,YACd,UAAU,KAAA,CAAM,QAAA;AAAA,YAChB,SAAS,KAAA,CAAM,IAAA;AAAA,YACf,UAAU,KAAA,CAAM;AAAA,WACjB,CAAA;AAAA,QACH;AACA,QAAA,IAAA,CAAK,gBAAA,CAAiB,UAAA,EAAY,YAAA,EAAc,KAAA,CAAM,EAAE,CAAA;AACxD,QAAA;AAAA,MACF;AAAA,MACA,KAAK,QAAA,EAAU;AACb,QAAA,MAAM,OAAA,GAAU,MAAM,IAAA,CAAK,QAAA,CAAS,WAAA,CAAY;AAAA,UAC9C,UAAU,KAAA,CAAM,QAAA;AAAA,UAChB,aAAA,EAAe,UAAA;AAAA,UACf,WAAW,KAAA,CAAM;AAAA,SAClB,CAAA;AACD,QAAA,IAAI,OAAA,EAAS;AACX,UAAA,IAAA,CAAK,SAAS,gBAAA,EAAkB;AAAA,YAC9B,UAAA;AAAA,YACA,aAAA,EAAe,UAAA;AAAA,YACf,UAAU,KAAA,CAAM,QAAA;AAAA,YAChB,WAAW,KAAA,CAAM;AAAA,WAClB,CAAA;AAAA,QACH;AACA,QAAA,IAAA,CAAK,gBAAA,CAAiB,UAAA,EAAY,YAAA,EAAc,KAAA,CAAM,EAAE,CAAA;AACxD,QAAA;AAAA,MACF;AAAA,MACA,KAAK,MAAA,EAAQ;AACX,QAAA,IAAA,CAAK,OAAO,MAAA,CAAO,EAAE,YAAY,MAAA,EAAQ,KAAA,CAAM,QAAQ,CAAA;AACvD,QAAA,IAAA,CAAK,QAAA,CAAS,eAAe,EAAE,UAAA,EAAY,cAAc,MAAA,EAAQ,KAAA,CAAM,QAAQ,CAAA;AAC/E,QAAA;AAAA,MACF;AAAA,MACA,KAAK,UAAA,EAAY;AACf,QAAA,IAAA,CAAK,MAAA,CAAO,WAAW,EAAE,UAAA,EAAY,cAAc,UAAA,EAAY,KAAA,CAAM,KAAK,CAAA;AAC1E,QAAA;AAAA,MACF;AAAA,MACA,KAAK,QAAA,EAAU;AACb,QAAA,IAAA,CAAK,QAAA,CAAS,UAAU,EAAE,UAAA,EAAY,cAAc,KAAA,EAAO,KAAA,CAAM,OAAO,CAAA;AACxE,QAAA;AAAA,MACF;AAAA,MACA,KAAK,UAAA,EAAY;AAOf,QAAA,IAAI,UAAA,KAAe,KAAK,UAAA,EAAY;AACpC,QAAA,MAAM,QAAQ,KAAA,CAAM,QAAA;AACpB,QAAA,MAAM,eAAe,KAAA,CAAM,YAAA;AAC3B,QAAA,QAAQ,MAAM,IAAA;AAAM,UAClB,KAAK,MAAA,EAAQ;AACX,YAAA,MAAM,IAAA,CAAK,SAAS,GAAA,CAAI;AAAA,cACtB,IAAI,KAAA,CAAM,EAAA;AAAA,cACV,UAAA,EAAY,YAAA;AAAA,cACZ,YAAA,EAAc,UAAA;AAAA,cACd,MAAM,KAAA,CAAM,IAAA;AAAA,cACZ,QAAQ,KAAA,CAAM,YAAA;AAAA,cACd,QAAA,EAAU,IAAA;AAAA,cACV,SAAA,EAAW,IAAA;AAAA,cACX,GAAI,MAAM,OAAA,KAAY,MAAA,GAAY,EAAE,OAAA,EAAS,KAAA,CAAM,OAAA,EAAQ,GAAI;AAAC,aACjE,CAAA;AACD,YAAA,IAAA,CAAK,SAAS,SAAA,EAAW;AAAA,cACvB,UAAA,EAAY,YAAA;AAAA,cACZ,YAAA;AAAA,cACA,YAAA,EAAc,UAAA;AAAA,cACd,OAAA,EAAS;AAAA,gBACP,IAAI,KAAA,CAAM,EAAA;AAAA,gBACV,MAAM,KAAA,CAAM,IAAA;AAAA,gBACZ,QAAQ,KAAA,CAAM,YAAA;AAAA,gBACd,GAAI,MAAM,OAAA,KAAY,MAAA,GAAY,EAAE,OAAA,EAAS,KAAA,CAAM,OAAA,EAAQ,GAAI;AAAC;AAClE,aACD,CAAA;AACD,YAAA;AAAA,UACF;AAAA,UACA,KAAK,MAAA,EAAQ;AACX,YAAA,MAAM,OAAA,GAAU,MAAM,IAAA,CAAK,QAAA,CAAS,SAAA,CAAU;AAAA,cAC5C,UAAU,KAAA,CAAM,QAAA;AAAA,cAChB,YAAA,EAAc,UAAA;AAAA,cACd,SAAS,KAAA,CAAM,IAAA;AAAA,cACf,UAAU,KAAA,CAAM;AAAA,aACjB,CAAA;AACD,YAAA,IAAI,OAAA,EAAS;AACX,cAAA,IAAA,CAAK,SAAS,eAAA,EAAiB;AAAA,gBAC7B,UAAA,EAAY,YAAA;AAAA,gBACZ,YAAA,EAAc,UAAA;AAAA,gBACd,UAAU,KAAA,CAAM,QAAA;AAAA,gBAChB,SAAS,KAAA,CAAM,IAAA;AAAA,gBACf,UAAU,KAAA,CAAM;AAAA,eACjB,CAAA;AAAA,YACH;AACA,YAAA;AAAA,UACF;AAAA,UACA,KAAK,QAAA,EAAU;AACb,YAAA,MAAM,OAAA,GAAU,MAAM,IAAA,CAAK,QAAA,CAAS,WAAA,CAAY;AAAA,cAC9C,UAAU,KAAA,CAAM,QAAA;AAAA,cAChB,aAAA,EAAe,UAAA;AAAA,cACf,WAAW,KAAA,CAAM;AAAA,aAClB,CAAA;AACD,YAAA,IAAI,OAAA,EAAS;AACX,cAAA,IAAA,CAAK,SAAS,gBAAA,EAAkB;AAAA,gBAC9B,UAAA,EAAY,YAAA;AAAA,gBACZ,aAAA,EAAe,UAAA;AAAA,gBACf,UAAU,KAAA,CAAM,QAAA;AAAA,gBAChB,WAAW,KAAA,CAAM;AAAA,eAClB,CAAA;AAAA,YACH;AACA,YAAA;AAAA,UACF;AAAA,UACA,KAAK,MAAA,EAAQ;AAGX,YAAA,IAAA,CAAK,MAAA,CAAO,OAAO,EAAE,UAAA,EAAY,cAAc,MAAA,EAAQ,KAAA,CAAM,QAAQ,CAAA;AACrE,YAAA;AAAA,UACF;AAAA;AAEF,QAAA;AAAA,MACF;AAAA;AACF,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,MAAc,QAAA,CAAS,YAAA,EAAsB,QAAA,EAA4C;AACvF,IAAA,IAAI,CAAC,KAAK,UAAA,EAAY;AACtB,IAAA,IAAI,YAAA,KAAiB,KAAK,UAAA,EAAY;AACtC,IAAA,MAAM,IAAA,GAAO,WAAA,CAAY,YAAA,EAAc,QAAQ,CAAA;AAC/C,IAAA,IAAI;AAKF,MAAA,MAAM,MAAA,GAAS,IAAA,CAAK,QAAA,CAAS,gBAAA,CAAiB,KAAK,UAAU,CAAA;AAC7D,MAAA,IAAI,MAAA,KAAW,IAAA,IAAQ,MAAA,KAAW,CAAA,EAAG;AACnC,QAAA,IAAI;AACF,UAAA,MAAM,IAAA,CAAK,QAAA,CAAS,kBAAA,CAAmB,IAAA,CAAK,UAAU,CAAA;AAAA,QACxD,CAAA,CAAA,MAAQ;AACN,UAAA;AAAA,QACF;AAAA,MACF;AACA,MAAA,MAAM,IAAA,CAAK,YAAY,IAAA,CAAK,UAAA,EAAY,MAAM,EAAE,SAAA,EAAW,OAAO,CAAA;AAAA,IACpE,CAAA,CAAA,MAAQ;AAAA,IAGR;AAAA,EACF;AAAA,EAEA,MAAc,WAAA,CACZ,UAAA,EACA,KAAA,EACA,IAAA,EACe;AACf,IAAA,MAAM,UAAA,GAAa,iBAAiB,KAAK,CAAA;AACzC,IAAA,MAAM,SAAA,GAAY,IAAI,WAAA,EAAY,CAAE,OAAO,UAAU,CAAA;AACrD,IAAA,MAAM,YAAY,MAAM,IAAA,CAAK,QAAA,CAAS,cAAA,CAAe,YAAY,SAAS,CAAA;AAC1E,IAAA,IAAI,SAAA,CAAU,WAAW,CAAA,EAAG;AAO1B,MAAA,IAAI,CAAC,IAAA,CAAK,SAAA,IAAa,CAAC,KAAK,uBAAA,EAAyB;AACpD,QAAA,MAAM,UAAA,GAAA,CACH,MAAM,IAAA,CAAK,QAAA,CAAS,WAAA,CAAY,UAAA,EAAY,EAAE,KAAA,EAAO,CAAA,EAAG,CAAA,EAAG,MAAA,GAAS,CAAA;AACvE,QAAA,IAAI,UAAA,EAAY;AACd,UAAA,IAAA,CAAK,uBAAA,GAA0B,IAAA;AAC/B,UAAA,IAAI;AACF,YAAA,MAAM,IAAA,CAAK,UAAU,qBAAA,EAAsB;AAAA,UAC7C,CAAA,CAAA,MAAQ;AAAA,UAER;AAAA,QACF;AAAA,MACF;AACA,MAAA;AAAA,IACF;AACA,IAAA,MAAM,OAAA,GAA4B,SAAA,CAAU,GAAA,CAAI,CAAC,CAAA,MAAO;AAAA,MACtD,UAAU,CAAA,CAAE,YAAA;AAAA,MACZ,YAAY,CAAA,CAAE,UAAA;AAAA,MACd,YAAA,EAAc,UAAA,CAAW,MAAA,CAAO,UAAA;AAAW,KAC7C,CAAE,CAAA;AAIF,IAAA,IAAI,KAAA,CAAM,SAAS,MAAA,IAAU,KAAA,CAAM,SAAS,MAAA,IAAU,KAAA,CAAM,SAAS,QAAA,EAAU;AAC7E,MAAA,MAAM,GAAA,uBAAU,GAAA,EAAoB;AACpC,MAAA,KAAA,MAAW,KAAK,OAAA,EAAS,GAAA,CAAI,IAAI,CAAA,CAAE,YAAA,EAAc,EAAE,QAAQ,CAAA;AAC3D,MAAA,IAAA,CAAK,MAAA,CAAO,cAAc,EAAE,SAAA,EAAW,MAAM,EAAA,EAAI,UAAA,EAAY,gBAAA,EAAkB,GAAA,EAAK,CAAA;AAAA,IACtF;AAEA,IAAA,MAAM,OAAA,GAAU,SAAA,CAAU,CAAC,CAAA,CAAE,OAAA;AAC7B,IAAA,MAAM,KAAA,GAAQ;AAAA,MACZ,QAAA,EAAU,UAAA;AAAA,MACV,SAAA,EAAW,KAAK,SAAA,IAAa,MAAA;AAAA,MAC7B,OAAA;AAAA,MACA;AAAA,KACF;AAEA,IAAA,IAAI,KAAK,SAAA,EAAW;AAIlB,MAAA,IAAI,IAAA,CAAK,EAAA,CAAG,QAAA,EAAS,KAAM,MAAA,EAAQ;AACjC,QAAA,IAAI;AACF,UAAA,IAAA,CAAK,EAAA,CAAG,SAAS,KAAK,CAAA;AAAA,QACxB,CAAA,CAAA,MAAQ;AAAA,QAER;AAAA,MACF;AACA,MAAA;AAAA,IACF;AAMA,IAAA,IAAA,CAAK,OAAO,OAAA,CAAQ;AAAA,MAClB,WAAW,KAAA,CAAM,EAAA;AAAA,MACjB,UAAA;AAAA,MACA,SAAA,EAAW,KAAA;AAAA,MACX,SAAS,YAAY;AACnB,QAAA,MAAM,QAAA,uBAAe,GAAA,EAAqD;AAC1E,QAAA,IAAI,IAAA,CAAK,EAAA,CAAG,QAAA,EAAS,KAAM,MAAA,EAAQ;AACjC,UAAA,KAAA,MAAW,KAAK,OAAA,EAAS,QAAA,CAAS,GAAA,CAAI,CAAA,CAAE,cAAc,OAAO,CAAA;AAC7D,UAAA,OAAO,QAAA;AAAA,QACT;AACA,QAAA,IAAI;AACF,UAAA,IAAA,CAAK,EAAA,CAAG,SAAS,KAAK,CAAA;AAKtB,UAAA,KAAA,MAAW,KAAK,OAAA,EAAS,QAAA,CAAS,GAAA,CAAI,CAAA,CAAE,cAAc,QAAQ,CAAA;AAAA,QAChE,CAAA,CAAA,MAAQ;AACN,UAAA,KAAA,MAAW,KAAK,OAAA,EAAS,QAAA,CAAS,GAAA,CAAI,CAAA,CAAE,cAAc,OAAO,CAAA;AAAA,QAC/D;AACA,QAAA,OAAO,QAAA;AAAA,MACT;AAAA,KACD,CAAA;AAGD,IAAA,KAAK,IAAA,CAAK,OAAO,IAAA,EAAK;AAEtB,IAAA,KAAK,IAAA,CAAK,WAAA;AAAA,EACZ;AAAA,EAEQ,gBAAA,CAAiB,UAAA,EAAoB,YAAA,EAAsB,OAAA,EAAuB;AACxF,IAAA,MAAM,GAAA,GAAM,CAAA,EAAG,UAAU,CAAA,CAAA,EAAI,YAAY,CAAA,CAAA;AACzC,IAAA,MAAM,OAAO,IAAA,CAAK,eAAA,CAAgB,GAAA,CAAI,GAAG,KAAK,EAAC;AAC/C,IAAA,IAAA,CAAK,KAAK,OAAO,CAAA;AACjB,IAAA,IAAA,CAAK,eAAA,CAAgB,GAAA,CAAI,GAAA,EAAK,IAAI,CAAA;AAClC,IAAA,IAAI,IAAA,CAAK,UAAU,yBAAA,EAA2B;AAC5C,MAAA,IAAA,CAAK,kBAAA,EAAmB;AACxB,MAAA;AAAA,IACF;AACA,IAAA,IAAI,CAAC,KAAK,kBAAA,EAAoB;AAC5B,MAAA,IAAA,CAAK,qBAAqB,UAAA,CAAW,MAAM,IAAA,CAAK,kBAAA,IAAsB,uBAAuB,CAAA;AAAA,IAC/F;AAAA,EACF;AAAA,EAEQ,kBAAA,GAA2B;AACjC,IAAA,IAAI,KAAK,kBAAA,EAAoB;AAC3B,MAAA,YAAA,CAAa,KAAK,kBAAkB,CAAA;AACpC,MAAA,IAAA,CAAK,kBAAA,GAAqB,IAAA;AAAA,IAC5B;AACA,IAAA,IAAI,IAAA,CAAK,eAAA,CAAgB,IAAA,KAAS,CAAA,EAAG;AACrC,IAAA,KAAA,MAAW,CAAC,GAAA,EAAK,GAAG,KAAK,IAAA,CAAK,eAAA,CAAgB,SAAQ,EAAG;AACvD,MAAA,MAAM,CAAC,UAAU,CAAA,GAAI,GAAA,CAAI,MAAM,GAAG,CAAA;AAClC,MAAA,IAAA,CAAK,WAAA,CAAY,UAAA,EAAY,WAAA,CAAY,GAAG,CAAA,EAAG,EAAE,SAAA,EAAW,KAAA,EAAO,CAAA,CAAE,KAAA,CAAM,MAAM;AAAA,MAAC,CAAC,CAAA;AAAA,IACrF;AACA,IAAA,IAAA,CAAK,gBAAgB,KAAA,EAAM;AAAA,EAC7B;AAAA,EAEQ,QAAA,CAA8B,MAAS,KAAA,EAA0B;AACvE,IAAA,MAAM,GAAA,GAAM,IAAA,CAAK,SAAA,CAAU,GAAA,CAAI,IAAI,CAAA;AACnC,IAAA,IAAI,CAAC,GAAA,EAAK;AACV,IAAA,KAAA,MAAW,MAAM,GAAA,EAAK;AACpB,MAAA,IAAI;AACF,QAAC,GAAmB,KAAK,CAAA;AAAA,MAC3B,CAAA,CAAA,MAAQ;AAAA,MAER;AAAA,IACF;AAAA,EACF;AACF;AAIA,SAAS,gBAAgB,GAAA,EAA4B;AACnD,EAAA,IAAI;AACF,IAAA,MAAM,KAAA,GAAQ,GAAA,CAAI,KAAA,CAAM,GAAG,CAAA;AAC3B,IAAA,IAAI,KAAA,CAAM,MAAA,KAAW,CAAA,EAAG,OAAO,IAAA;AAC/B,IAAA,MAAM,UAAU,CAAA,GAAK,KAAA,CAAM,CAAC,CAAA,CAAE,SAAS,CAAA,IAAM,CAAA;AAC7C,IAAA,MAAM,SAAS,KAAA,CAAM,CAAC,CAAA,GAAI,GAAA,CAAI,OAAO,MAAM,CAAA;AAC3C,IAAA,MAAM,GAAA,GAAM,OAAO,OAAA,CAAQ,IAAA,EAAM,GAAG,CAAA,CAAE,OAAA,CAAQ,MAAM,GAAG,CAAA;AACvD,IAAA,MAAM,OAAA,GAAU,KAAK,GAAG,CAAA;AACxB,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,KAAA,CAAM,OAAO,CAAA;AACjC,IAAA,OAAO,OAAO,GAAA,IAAO,IAAA;AAAA,EACvB,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,IAAA;AAAA,EACT;AACF","file":"index.cjs","sourcesContent":["// Content protocol — events that travel inside the Olm ciphertext. Server\n// cannot read or enforce any of this; correctness is enforced\n// cryptographically by the Olm session binding (sender identity is fixed\n// per session and can't be spoofed without the wallet).\n//\n// Forward-compat rule: any unknown `type` or `v` higher than this client\n// understands is silently dropped (logged at debug). Adding new event\n// types is a non-breaking change as long as receivers tolerate them.\n\nexport const CONTENT_PROTOCOL_VERSION = 1;\n\n/** Common header on every content event. */\ninterface BaseEvent {\n v: 1;\n /** Client-generated UUID — referenced later by edit/delete/replyTo. */\n id: string;\n /** Sender wall-clock at compose time, ms epoch. Receivers SHOULD NOT\n * trust for ordering — used for display only. */\n clientSentAt: number;\n}\n\nexport interface TextEvent extends BaseEvent {\n type: \"text\";\n text: string;\n /** id of message this is a reply to; not validated against existence. */\n replyTo?: string;\n}\n\nexport interface EditEvent extends BaseEvent {\n type: \"edit\";\n /** id of the message being edited. Receiver validates the original is\n * from the same sender (Olm-session-bound) before applying. */\n targetId: string;\n text: string;\n}\n\nexport interface DeleteEvent extends BaseEvent {\n type: \"delete\";\n targetId: string;\n}\n\n/** Read-watermark: covers all messages in this conversation up to and\n * including upToId. Cheaper than per-message receipts. */\nexport interface ReadEvent extends BaseEvent {\n type: \"read\";\n upToId: string;\n}\n\n/** Auto-emitted by the receiver after successful decrypt+store. Batched\n * upstream of the SDK boundary (see status tracker). */\nexport interface ReceivedEvent extends BaseEvent {\n type: \"received\";\n ids: string[];\n}\n\n/** Ephemeral typing indicator. Sent with wire-level ephemeral=true so the\n * node drops on offline-fallback — never persisted. */\nexport interface TypingEvent extends BaseEvent {\n type: \"typing\";\n state: \"started\" | \"stopped\";\n}\n\n/** Multi-device self-echo (Signal \"sync messages\"). Sent by the originator\n * to its own user (filtered: not back to the sender's own device) so the\n * user's other devices observe outbound traffic from this device. The\n * receiver validates `peerUserId === selfUserId` before unwrapping —\n * the Olm session binding means only this user's authentic devices can\n * produce a ciphertext that decrypts under our self-keyed inbound state. */\nexport type SelfEchoableEvent = TextEvent | EditEvent | DeleteEvent | ReadEvent;\nexport interface SelfEchoEvent extends BaseEvent {\n type: \"selfEcho\";\n originalPeer: string;\n original: SelfEchoableEvent;\n}\n\nexport type ContentEvent =\n | TextEvent\n | EditEvent\n | DeleteEvent\n | ReadEvent\n | ReceivedEvent\n | TypingEvent\n | SelfEchoEvent;\n\nexport type ContentEventType = ContentEvent[\"type\"];\n\n// ── encode/decode ───────────────────────────────────────────────────────────\n\nconst enc = new TextEncoder();\nconst dec = new TextDecoder();\n\n/**\n * Serialize a content event for encryption. Throws on malformed input —\n * this is a code error, not a runtime decision (event is constructed by\n * the SDK, not received from elsewhere).\n */\nexport function encodeEvent(event: ContentEvent): string {\n if (event.v !== CONTENT_PROTOCOL_VERSION) {\n throw new Error(`encodeEvent: bad version ${event.v}`);\n }\n if (!event.id || !event.type) {\n throw new Error(\"encodeEvent: missing id or type\");\n }\n return JSON.stringify(event);\n}\n\n/**\n * Parse a decrypted plaintext as a content event. Returns null for any\n * unsupported version or unknown type — the SDK should silently drop. The\n * forward-compat contract is \"unknown future events vanish, never crash.\"\n *\n * This is forgiving by design: malformed JSON, missing required fields,\n * etc. all return null with a debug log opportunity for the caller.\n */\nexport function decodeEvent(plaintext: string): ContentEvent | null {\n let raw: unknown;\n try {\n raw = JSON.parse(plaintext);\n } catch {\n return null;\n }\n if (typeof raw !== \"object\" || raw === null) return null;\n const obj = raw as Record<string, unknown>;\n if (typeof obj.v !== \"number\" || obj.v > CONTENT_PROTOCOL_VERSION) return null;\n if (typeof obj.id !== \"string\" || !obj.id) return null;\n if (typeof obj.type !== \"string\") return null;\n if (typeof obj.clientSentAt !== \"number\") return null;\n\n switch (obj.type) {\n case \"text\": {\n if (typeof obj.text !== \"string\") return null;\n const replyTo = typeof obj.replyTo === \"string\" ? obj.replyTo : undefined;\n return {\n v: 1,\n id: obj.id,\n type: \"text\",\n clientSentAt: obj.clientSentAt,\n text: obj.text,\n ...(replyTo !== undefined ? { replyTo } : {}),\n };\n }\n case \"edit\": {\n if (typeof obj.targetId !== \"string\" || typeof obj.text !== \"string\") return null;\n return {\n v: 1,\n id: obj.id,\n type: \"edit\",\n clientSentAt: obj.clientSentAt,\n targetId: obj.targetId,\n text: obj.text,\n };\n }\n case \"delete\": {\n if (typeof obj.targetId !== \"string\") return null;\n return {\n v: 1,\n id: obj.id,\n type: \"delete\",\n clientSentAt: obj.clientSentAt,\n targetId: obj.targetId,\n };\n }\n case \"read\": {\n if (typeof obj.upToId !== \"string\") return null;\n return {\n v: 1,\n id: obj.id,\n type: \"read\",\n clientSentAt: obj.clientSentAt,\n upToId: obj.upToId,\n };\n }\n case \"received\": {\n if (!Array.isArray(obj.ids) || !obj.ids.every((x) => typeof x === \"string\")) return null;\n return {\n v: 1,\n id: obj.id,\n type: \"received\",\n clientSentAt: obj.clientSentAt,\n ids: obj.ids as string[],\n };\n }\n case \"typing\": {\n if (obj.state !== \"started\" && obj.state !== \"stopped\") return null;\n return {\n v: 1,\n id: obj.id,\n type: \"typing\",\n clientSentAt: obj.clientSentAt,\n state: obj.state,\n };\n }\n case \"selfEcho\": {\n if (typeof obj.originalPeer !== \"string\" || !obj.originalPeer) return null;\n if (typeof obj.original !== \"object\" || obj.original === null) return null;\n const inner = decodeEvent(JSON.stringify(obj.original));\n if (inner === null) return null;\n if (inner.type !== \"text\" && inner.type !== \"edit\" &&\n inner.type !== \"delete\" && inner.type !== \"read\") {\n return null;\n }\n return {\n v: 1,\n id: obj.id,\n type: \"selfEcho\",\n clientSentAt: obj.clientSentAt,\n originalPeer: obj.originalPeer,\n original: inner,\n };\n }\n default:\n return null;\n }\n}\n\n/** Convenience: marshal to bytes for the encrypt boundary. */\nexport function encodeEventBytes(event: ContentEvent): Uint8Array {\n return enc.encode(encodeEvent(event));\n}\n\nexport function decodeEventBytes(bytes: Uint8Array): ContentEvent | null {\n return decodeEvent(dec.decode(bytes));\n}\n\n// ── factory helpers (for the SDK send paths) ────────────────────────────────\n\nfunction newId(): string {\n return globalThis.crypto.randomUUID();\n}\n\nexport function newText(text: string, replyTo?: string): TextEvent {\n return {\n v: 1,\n id: newId(),\n type: \"text\",\n clientSentAt: Date.now(),\n text,\n ...(replyTo !== undefined ? { replyTo } : {}),\n };\n}\n\nexport function newEdit(targetId: string, text: string): EditEvent {\n return { v: 1, id: newId(), type: \"edit\", clientSentAt: Date.now(), targetId, text };\n}\n\nexport function newDelete(targetId: string): DeleteEvent {\n return { v: 1, id: newId(), type: \"delete\", clientSentAt: Date.now(), targetId };\n}\n\nexport function newRead(upToId: string): ReadEvent {\n return { v: 1, id: newId(), type: \"read\", clientSentAt: Date.now(), upToId };\n}\n\nexport function newReceived(ids: string[]): ReceivedEvent {\n return { v: 1, id: newId(), type: \"received\", clientSentAt: Date.now(), ids };\n}\n\nexport function newTyping(state: \"started\" | \"stopped\"): TypingEvent {\n return { v: 1, id: newId(), type: \"typing\", clientSentAt: Date.now(), state };\n}\n\nexport function newSelfEcho(originalPeer: string, original: SelfEchoableEvent): SelfEchoEvent {\n return {\n v: 1,\n id: newId(),\n type: \"selfEcho\",\n clientSentAt: Date.now(),\n originalPeer,\n original,\n };\n}\n","// CryptoAdapter wrapping @dtelecom/vodozemac-wasm. State (Olm Account,\n// per-peer-device Sessions) is pickled as JSON strings and persisted via\n// the supplied KVStore.\n//\n// Olm wire format is libolm-compatible (vodozemac defaults to SessionConfig\n// version 1, the libolm format). Bundles produced here interop with libolm\n// peers and vice versa — the wire isn't changing, only the implementation.\n//\n// Olm doesn't natively distinguish \"signed prekey\" from the curve25519\n// identity key the way Signal Protocol does. To match the wire contract's\n// Signal-flavored field set:\n// signedPrekey = identityKeyCurve\n// signedPrekeySig = account.sign(identityKeyCurve)\n// fallbackPrekey = account.fallbackKey().curve25519[<id>]\n// fallbackPrekeySig = account.sign(fallbackPrekey)\n// Outbound session creation uses identityKeyCurve + oneTimeKey (or\n// fallbackPrekey when the OTK is null).\n\nimport * as vodozemac from \"@dtelecom/vodozemac-wasm\";\nimport { Account, Session, type InboundResult } from \"@dtelecom/vodozemac-wasm\";\nimport type { ClaimedDevice } from \"../types.js\";\nimport type { KVStore } from \"../store/interface.js\";\nimport type { CryptoAdapter, OutboundEnvelope, UploadBundle } from \"./interface.js\";\n\nconst OLM_ACCOUNT_KEY = \"olm/account\";\nconst OLM_SESSION_PREFIX = \"olm/session/\";\n\nexport interface OlmAdapterOptions {\n store: KVStore;\n}\n\n// In Node, @dtelecom/vodozemac-wasm's pkg-node target initializes the\n// WASM synchronously at module-load via require('fs'). In a browser\n// the pkg-web target uses fetch+instantiateStreaming; the user must\n// call the package's default export `init()` once. We do it lazily +\n// idempotently inside `OlmCryptoAdapter.init()` so callers don't need\n// to know which environment they're in. Detect \"browser-like\" by the\n// presence of a default export on the module (only pkg-web has one).\nlet wasmInitialized: Promise<void> | null = null;\nasync function ensureWasmReady(): Promise<void> {\n if (wasmInitialized) return wasmInitialized;\n const mod = vodozemac as unknown as { default?: () => Promise<unknown> };\n if (typeof mod.default !== \"function\") {\n // pkg-node — already initialized at import time.\n wasmInitialized = Promise.resolve();\n return wasmInitialized;\n }\n wasmInitialized = mod.default().then(() => undefined);\n return wasmInitialized;\n}\n\nexport class OlmCryptoAdapter implements CryptoAdapter {\n private account: Account | null = null;\n private sessions = new Map<string, Session>();\n\n constructor(private opts: OlmAdapterOptions) {}\n\n async init(): Promise<void> {\n await ensureWasmReady();\n if (this.account) return;\n const pickled = await this.opts.store.getString(OLM_ACCOUNT_KEY);\n if (pickled) {\n this.account = Account.fromPickle(pickled);\n }\n }\n\n async hasAccount(): Promise<boolean> {\n return this.account !== null;\n }\n\n async generateAccount(otkCount: number): Promise<UploadBundle> {\n if (this.account) throw new Error(\"account already exists\");\n const acc = new Account();\n acc.generateOneTimeKeys(otkCount);\n acc.generateFallbackKey();\n this.account = acc;\n const bundle = this.buildBundle(acc);\n acc.markKeysAsPublished();\n await this.persistAccount();\n return bundle;\n }\n\n async getCurrentBundle(): Promise<UploadBundle> {\n return this.buildBundle(this.requireAccount());\n }\n\n async generateOneTimeKeys(n: number): Promise<{ id: string; public: string }[]> {\n const acc = this.requireAccount();\n acc.generateOneTimeKeys(n);\n const otks = parseOneTimeKeys(acc.oneTimeKeys());\n acc.markKeysAsPublished();\n await this.persistAccount();\n return otks;\n }\n\n async unusedOneTimeKeyCount(): Promise<number> {\n const acc = this.requireAccount();\n return parseOneTimeKeys(acc.oneTimeKeys()).length;\n }\n\n async encryptForPeer(\n peerUserId: string,\n peerDeviceId: string,\n peerBundle: ClaimedDevice,\n plaintext: string,\n ): Promise<OutboundEnvelope> {\n const acc = this.requireAccount();\n let session = await this.loadSession(peerUserId, peerDeviceId);\n if (!session) {\n // Olm needs ONE remote curve25519 key to bootstrap; prefer OTK, fall\n // back to the per-device fallback prekey when the server's OTK pool\n // for that device is empty (oneTimeKey === null).\n const remoteOtk = peerBundle.oneTimeKey?.public ?? peerBundle.fallbackPrekey;\n session = acc.createOutboundSession(peerBundle.identityKeyCurve, remoteOtk);\n this.sessions.set(sessionKey(peerUserId, peerDeviceId), session);\n }\n const out = JSON.parse(session.encrypt(plaintext)) as { type: 0 | 1; body: string };\n await this.persistSession(peerUserId, peerDeviceId, session);\n return {\n ciphertext: out.body,\n msgType: out.type === 0 ? \"prekey\" : \"normal\",\n };\n }\n\n async decryptFromPeer(\n peerUserId: string,\n peerDeviceId: string,\n ciphertext: string,\n msgType: \"prekey\" | \"normal\",\n ): Promise<string> {\n const acc = this.requireAccount();\n let session = await this.loadSession(peerUserId, peerDeviceId);\n const isPrekey = msgType === \"prekey\";\n\n if (!session) {\n if (!isPrekey) {\n throw new Error(`no session for normal-type ciphertext from ${peerUserId}/${peerDeviceId}`);\n }\n // Inbound bootstrap: vodozemac extracts the sender's identity key\n // from the prekey message itself; createInboundSession both creates\n // the session AND decrypts the initial message in one call.\n const inbound: InboundResult = acc.createInboundSession(ciphertext);\n session = inbound.takeSession();\n const plaintext = inbound.plaintext;\n await this.persistAccount();\n this.sessions.set(sessionKey(peerUserId, peerDeviceId), session);\n await this.persistSession(peerUserId, peerDeviceId, session);\n return plaintext;\n }\n\n const olmType = isPrekey ? 0 : 1;\n const plaintext = session.decrypt(olmType, ciphertext);\n await this.persistSession(peerUserId, peerDeviceId, session);\n return plaintext;\n }\n\n async forgetSession(peerUserId: string, peerDeviceId: string): Promise<void> {\n const key = sessionKey(peerUserId, peerDeviceId);\n this.sessions.delete(key);\n await this.opts.store.delete(OLM_SESSION_PREFIX + key);\n }\n\n async hasSession(peerUserId: string, peerDeviceId: string): Promise<boolean> {\n if (this.sessions.has(sessionKey(peerUserId, peerDeviceId))) return true;\n const persisted = await this.opts.store.getString(\n OLM_SESSION_PREFIX + sessionKey(peerUserId, peerDeviceId),\n );\n return persisted !== null;\n }\n\n // ── internal ───────────────────────────────────────────────────────────────\n\n private requireAccount(): Account {\n if (!this.account) throw new Error(\"no Olm account; call generateAccount() or init()\");\n return this.account;\n }\n\n private buildBundle(acc: Account): UploadBundle {\n const idKeys = JSON.parse(acc.identityKeys()) as { curve25519: string; ed25519: string };\n const otks = parseOneTimeKeys(acc.oneTimeKeys());\n // No separate signed-prekey in Olm: report identity_key_curve self-signed.\n const signedPrekey = idKeys.curve25519;\n const signedPrekeySig = acc.sign(signedPrekey);\n const fallbackParsed = parseOneTimeKeys(acc.fallbackKey());\n const fallbackPrekey = fallbackParsed[0]?.public ?? signedPrekey;\n const fallbackPrekeySig = acc.sign(fallbackPrekey);\n return {\n identityKeyCurve: idKeys.curve25519,\n identityKeyEd: idKeys.ed25519,\n signedPrekey,\n signedPrekeySig,\n fallbackPrekey,\n fallbackPrekeySig,\n fingerprint: formatFingerprint(idKeys.ed25519),\n oneTimeKeys: otks,\n };\n }\n\n private async persistAccount(): Promise<void> {\n const acc = this.requireAccount();\n await this.opts.store.setString(OLM_ACCOUNT_KEY, acc.pickle());\n }\n\n private async loadSession(peerUserId: string, peerDeviceId: string): Promise<Session | null> {\n const key = sessionKey(peerUserId, peerDeviceId);\n const cached = this.sessions.get(key);\n if (cached) return cached;\n const pickled = await this.opts.store.getString(OLM_SESSION_PREFIX + key);\n if (!pickled) return null;\n const session = Session.fromPickle(pickled);\n this.sessions.set(key, session);\n return session;\n }\n\n private async persistSession(peerUserId: string, peerDeviceId: string, session: Session): Promise<void> {\n await this.opts.store.setString(\n OLM_SESSION_PREFIX + sessionKey(peerUserId, peerDeviceId),\n session.pickle(),\n );\n }\n}\n\nfunction sessionKey(peerUserId: string, peerDeviceId: string): string {\n return `${peerUserId}|${peerDeviceId}`;\n}\n\nfunction parseOneTimeKeys(json: string): { id: string; public: string }[] {\n const parsed = JSON.parse(json) as { curve25519?: Record<string, string> };\n const out: { id: string; public: string }[] = [];\n for (const [id, pub] of Object.entries(parsed.curve25519 ?? {})) {\n out.push({ id, public: pub });\n }\n return out;\n}\n\nfunction formatFingerprint(ed25519PubB64: string): string {\n const groups = (ed25519PubB64.replace(/[+/=]/g, \"\").match(/.{1,4}/g) ?? []).slice(0, 12);\n return groups.join(\"-\");\n}\n\n","// Stable per-install device id, generated once and persisted in the KV store.\n// UUID v4 (16 bytes of randomness). Survives across SDK reconnects; lost only\n// if the underlying storage is wiped.\n\nimport type { KVStore } from \"./store/interface.js\";\n\nconst DEVICE_ID_KEY = \"deviceId\";\n\nfunction generateUUID(): string {\n // Web Crypto + modern Node both expose crypto.randomUUID().\n if (typeof globalThis.crypto?.randomUUID === \"function\") {\n return globalThis.crypto.randomUUID();\n }\n // Defensive fallback: build a UUID v4 from random bytes.\n const bytes = new Uint8Array(16);\n globalThis.crypto.getRandomValues(bytes);\n bytes[6] = (bytes[6] & 0x0f) | 0x40;\n bytes[8] = (bytes[8] & 0x3f) | 0x80;\n const hex = Array.from(bytes, (b) => b.toString(16).padStart(2, \"0\")).join(\"\");\n return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;\n}\n\nexport async function loadOrCreateDeviceId(store: KVStore): Promise<string> {\n const existing = await store.getString(DEVICE_ID_KEY);\n if (existing) return existing;\n const id = generateUUID();\n await store.setString(DEVICE_ID_KEY, id);\n return id;\n}\n\n/** Test-only: forget the persisted device id. Real users never call this. */\nexport async function resetDeviceId(store: KVStore): Promise<void> {\n await store.delete(DEVICE_ID_KEY);\n}\n","// PeerDeviceCache — lightweight cache of peer device metadata, refreshed\n// lazily on chat-open and on-decrypt-failure. Distinct from SessionManager's\n// bundle cache: this just tracks \"which devices does B currently have?\"\n// without consuming OTKs (uses GET /api/chat/keys/list_devices).\n//\n// Refresh triggers (per plan §17):\n// - On first chat-open with a peer (no cache or stale cache)\n// - On inbound prekey-message from a previously-unknown peer device\n// (handled at the SDK boundary; this layer just provides addPeerDevice)\n// - Optional periodic eager refresh (off by default)\n\nimport type { HttpClient } from \"./transport/http.js\";\n\nexport interface PeerDeviceMeta {\n deviceId: string;\n fingerprint: string;\n lastActiveAt: number;\n}\n\nexport interface PeerDeviceCacheOptions {\n http: HttpClient;\n selfDeviceId: string;\n /** Cache freshness window. Default 5 minutes. */\n staleAfterMs?: number;\n}\n\ninterface CacheEntry {\n devices: PeerDeviceMeta[];\n fetchedAt: number;\n}\n\nconst DEFAULT_STALE_AFTER_MS = 5 * 60 * 1000;\n\nexport class PeerDeviceCache {\n private cache = new Map<string, CacheEntry>();\n\n constructor(private opts: PeerDeviceCacheOptions) {}\n\n /**\n * Return peer's known devices, refreshing if cache is missing or older\n * than `staleAfterMs`.\n */\n async getPeerDevices(peerUserId: string): Promise<PeerDeviceMeta[]> {\n const now = Date.now();\n const stale = this.opts.staleAfterMs ?? DEFAULT_STALE_AFTER_MS;\n const entry = this.cache.get(peerUserId);\n if (entry && now - entry.fetchedAt < stale) {\n return entry.devices;\n }\n return this.refresh(peerUserId);\n }\n\n /** Force a fresh fetch regardless of staleness. */\n async refresh(peerUserId: string): Promise<PeerDeviceMeta[]> {\n const res = await this.opts.http.listDevices(this.opts.selfDeviceId, peerUserId);\n const devices = res.devices.map((d) => ({\n deviceId: d.deviceId,\n fingerprint: d.fingerprint,\n lastActiveAt: d.lastActiveAt,\n }));\n this.cache.set(peerUserId, { devices, fetchedAt: Date.now() });\n return devices;\n }\n\n /**\n * Add a peer device discovered through other channels (e.g., an inbound\n * prekey-message from a device the cache doesn't know about). Doesn't\n * hit the network. Caller is responsible for the (deviceId, fingerprint).\n */\n noteNewPeerDevice(peerUserId: string, device: PeerDeviceMeta): void {\n const entry = this.cache.get(peerUserId);\n if (!entry) {\n this.cache.set(peerUserId, { devices: [device], fetchedAt: Date.now() });\n return;\n }\n if (entry.devices.some((d) => d.deviceId === device.deviceId)) return;\n entry.devices.push(device);\n }\n\n /** Drop the cached entry; next getPeerDevices will refetch. */\n invalidate(peerUserId: string): void {\n this.cache.delete(peerUserId);\n }\n\n /** Drop everything. */\n clear(): void {\n this.cache.clear();\n }\n}\n","// Orchestrates account generation + bundle upload + OTK top-up.\n// Stateless wrapper around CryptoAdapter + HttpClient.\n\nimport type { CryptoAdapter } from \"./crypto/interface.js\";\nimport type { HttpClient } from \"./transport/http.js\";\n\nexport const DEFAULT_OTK_COUNT = 100;\nexport const OTK_TOPUP_WATERMARK = 20;\nexport const OTK_TOPUP_TARGET = 100;\n\nexport interface KeyBundleManagerOptions {\n http: HttpClient;\n crypto: CryptoAdapter;\n deviceId: string;\n /** Initial OTK pool size on first generation. Default 100. */\n initialOtkCount?: number;\n}\n\n/**\n * KeyBundleManager handles the device-key lifecycle:\n * first run → generate Olm account + 100 OTKs + upload\n * subsequent → no-op (account persisted; reupload only on demand)\n * periodic → top-up OTKs when server count drops below watermark\n */\nexport class KeyBundleManager {\n constructor(private opts: KeyBundleManagerOptions) {}\n\n /** In-flight topup promise — coalesces concurrent callers so the\n * initial connect + onWsState(\"open\") path doesn't double-upload. */\n private inflightTopup: Promise<{ topped: boolean; newCount?: number }> | null = null;\n\n /**\n * Idempotent. On first call generates a new Olm account and uploads\n * the bundle; on subsequent calls no-ops if the adapter already has\n * an account. Safe to call on every connect.\n */\n async ensureKeyBundle(): Promise<void> {\n await this.opts.crypto.init();\n if (await this.opts.crypto.hasAccount()) {\n return;\n }\n const bundle = await this.opts.crypto.generateAccount(\n this.opts.initialOtkCount ?? DEFAULT_OTK_COUNT,\n );\n await this.opts.http.uploadKeyBundle(this.opts.deviceId, {\n deviceId: this.opts.deviceId,\n identityKeyCurve: bundle.identityKeyCurve,\n identityKeyEd: bundle.identityKeyEd,\n signedPrekey: bundle.signedPrekey,\n signedPrekeySig: bundle.signedPrekeySig,\n fallbackPrekey: bundle.fallbackPrekey,\n fallbackPrekeySig: bundle.fallbackPrekeySig,\n fingerprint: bundle.fingerprint,\n oneTimeKeys: bundle.oneTimeKeys,\n });\n }\n\n /**\n * Re-upload the existing bundle without generating new keys. Used after\n * backend wipes during testing, or when the SDK detects a registry\n * mismatch.\n */\n async reuploadCurrentBundle(): Promise<void> {\n await this.opts.crypto.init();\n if (!(await this.opts.crypto.hasAccount())) {\n throw new Error(\"reuploadCurrentBundle: no account; call ensureKeyBundle first\");\n }\n const bundle = await this.opts.crypto.getCurrentBundle();\n await this.opts.http.uploadKeyBundle(this.opts.deviceId, {\n deviceId: this.opts.deviceId,\n identityKeyCurve: bundle.identityKeyCurve,\n identityKeyEd: bundle.identityKeyEd,\n signedPrekey: bundle.signedPrekey,\n signedPrekeySig: bundle.signedPrekeySig,\n fallbackPrekey: bundle.fallbackPrekey,\n fallbackPrekeySig: bundle.fallbackPrekeySig,\n fingerprint: bundle.fingerprint,\n oneTimeKeys: bundle.oneTimeKeys,\n });\n }\n\n /**\n * Top up if the SERVER's OTK count for this device has dropped below\n * the watermark. Generates fresh OTKs and uploads. Idempotent: a no-op\n * if the count is healthy.\n */\n async topUpIfNeeded(): Promise<{ topped: boolean; newCount?: number }> {\n if (this.inflightTopup) return this.inflightTopup;\n const p = (async () => {\n const { count } = await this.opts.http.otkCount(this.opts.deviceId);\n if (count >= OTK_TOPUP_WATERMARK) {\n return { topped: false } as const;\n }\n const need = OTK_TOPUP_TARGET - count;\n const fresh = await this.opts.crypto.generateOneTimeKeys(need);\n const res = await this.opts.http.topupOtks(this.opts.deviceId, fresh);\n return { topped: true as const, newCount: res.currentCount };\n })();\n this.inflightTopup = p;\n try {\n return await p;\n } finally {\n this.inflightTopup = null;\n }\n }\n}\n","// Local message store. Persists user-facing text messages so the UI has a\n// historical view, applies edits and tombstones from inbound events, and\n// enforces the cryptographic-binding rule for edit/delete (only the\n// original sender can mutate a message).\n//\n// In-memory + KV-backed. Keys are prefixed under \"messages/<peerUserId>/<id>\".\n\nimport type { KVStore } from \"./store/interface.js\";\n\n/**\n * Persisted shape of a message. `senderUserId` is the truth — the SDK\n * sets it to either \"self\" (when the local user sent it) or to the\n * peer's user id (on inbound). Edit/delete authorization compares this\n * field on the stored row to the sender of the inbound mutation event.\n */\nexport interface StoredMessage {\n id: string;\n peerUserId: string;\n senderUserId: string;\n text: string;\n /** Original clientSentAt of the text event; never mutated by edits. */\n sentAt: number;\n /** Set on edit; null otherwise. */\n editedAt: number | null;\n /** Set on delete; the message becomes a tombstone. */\n deletedAt: number | null;\n replyTo?: string;\n}\n\nexport class MessageStore {\n private cache = new Map<string, StoredMessage>();\n\n constructor(private store: KVStore) {}\n\n /** Insert or overwrite. Used for both outbound (self-sent) and inbound. */\n async put(msg: StoredMessage): Promise<void> {\n this.cache.set(msg.id, msg);\n await this.store.setString(this.kvKey(msg.id), JSON.stringify(msg));\n }\n\n async get(messageId: string): Promise<StoredMessage | null> {\n const cached = this.cache.get(messageId);\n if (cached) return cached;\n const raw = await this.store.getString(this.kvKey(messageId));\n if (!raw) return null;\n try {\n const parsed = JSON.parse(raw) as StoredMessage;\n this.cache.set(parsed.id, parsed);\n return parsed;\n } catch {\n return null;\n }\n }\n\n /**\n * Return messages for `peerUserId`, oldest→newest within the page.\n *\n * `beforeSentAt` filters to messages with `sentAt < beforeSentAt`, used by\n * the chat UI to load older history above what's already rendered. `limit`\n * caps the page size; when set, the most-recent matches are returned (i.e.\n * the page sits at the boundary just before `beforeSentAt`).\n *\n * v1 implementation walks every persisted message; secondary indexing is\n * a follow-up. For typical chat volumes (hundreds of messages per peer)\n * this is fine; >10k per peer should add a per-peer KV index.\n */\n async listForPeer(\n peerUserId: string,\n opts: { limit?: number; beforeSentAt?: number } = {},\n ): Promise<StoredMessage[]> {\n const keys = await this.store.listKeys(\"messages/\");\n const out: StoredMessage[] = [];\n for (const key of keys) {\n const id = key.slice(\"messages/\".length);\n const cached = this.cache.get(id);\n let msg: StoredMessage | null = cached ?? null;\n if (!msg) {\n const raw = await this.store.getString(key);\n if (!raw) continue;\n try {\n msg = JSON.parse(raw) as StoredMessage;\n this.cache.set(msg.id, msg);\n } catch {\n continue;\n }\n }\n if (msg.peerUserId !== peerUserId) continue;\n if (opts.beforeSentAt !== undefined && msg.sentAt >= opts.beforeSentAt) continue;\n out.push(msg);\n }\n out.sort((a, b) => a.sentAt - b.sentAt);\n if (opts.limit !== undefined && out.length > opts.limit) {\n return out.slice(-opts.limit);\n }\n return out;\n }\n\n /**\n * Apply an edit if authorized. Returns the resulting message on\n * success, or null if the message doesn't exist, is already deleted,\n * or the editor is not the original sender.\n */\n async applyEdit(opts: {\n targetId: string;\n editorUserId: string;\n newText: string;\n editedAt: number;\n }): Promise<StoredMessage | null> {\n const target = await this.get(opts.targetId);\n if (!target) return null;\n if (target.deletedAt !== null) return null;\n if (target.senderUserId !== opts.editorUserId) return null;\n const updated: StoredMessage = {\n ...target,\n text: opts.newText,\n editedAt: opts.editedAt,\n };\n await this.put(updated);\n return updated;\n }\n\n /**\n * Apply a delete (tombstone) if authorized. Same authorization rule as\n * edit. Returns the tombstoned message or null.\n */\n async applyDelete(opts: {\n targetId: string;\n deleterUserId: string;\n deletedAt: number;\n }): Promise<StoredMessage | null> {\n const target = await this.get(opts.targetId);\n if (!target) return null;\n if (target.senderUserId !== opts.deleterUserId) return null;\n const updated: StoredMessage = {\n ...target,\n // Purge the original text — the contract is \"tombstone, not preserve\".\n text: \"\",\n deletedAt: opts.deletedAt,\n };\n await this.put(updated);\n return updated;\n }\n\n private kvKey(messageId: string): string {\n return `messages/${messageId}`;\n }\n}\n","// Outbox — queues outbound chatSend frames for retry on transient failure.\n// Idempotent at the wire level via envelopeUuid: re-sending the same uuid\n// is harmless because the server-side store dedupes, the receiver's\n// session has Olm replay protection, and the in-flight ACK map keys by\n// uuid so a duplicate just signals once.\n//\n// In-memory only for v1. Survives nothing across reload — that's fine for\n// the typical browser threat model where a tab close means the user is\n// done. KV-backed durability is a future hardening item.\n\nexport interface OutboxEntry {\n messageId: string;\n peerUserId: string;\n ephemeral: boolean;\n /** Function that performs the actual send — returns a per-target outcome\n * set keyed by envelopeUuid. */\n attempt: () => Promise<Map<string, \"live\" | \"stored\" | \"dropped\" | \"error\">>;\n attempts: number;\n nextRetryAt: number;\n}\n\nexport interface OutboxOptions {\n /** Max attempts before giving up (default 5). */\n maxAttempts?: number;\n /** Base backoff (ms) — actual is base * 2^attempts ± 20% jitter. */\n baseBackoffMs?: number;\n}\n\nconst DEFAULT_MAX_ATTEMPTS = 5;\nconst DEFAULT_BASE_BACKOFF = 500;\n\n/**\n * Outbox processes a queue of pending sends with exponential backoff.\n * Caller drives the loop via `enqueue` + the returned per-attempt\n * outcome — Outbox itself doesn't run a goroutine, it's just a state\n * machine. The SDK calls `tick()` opportunistically (on connect, on\n * scheduled timer) and `enqueue()` on each new send.\n */\nexport class Outbox {\n private queue: OutboxEntry[] = [];\n private inflightIds = new Set<string>();\n private opts: Required<OutboxOptions>;\n\n constructor(opts: OutboxOptions = {}) {\n this.opts = {\n maxAttempts: opts.maxAttempts ?? DEFAULT_MAX_ATTEMPTS,\n baseBackoffMs: opts.baseBackoffMs ?? DEFAULT_BASE_BACKOFF,\n };\n }\n\n /**\n * Enqueue a send attempt. Idempotent on messageId — a second enqueue\n * with the same id is a no-op (returns the existing entry's promise).\n */\n enqueue(entry: Omit<OutboxEntry, \"attempts\" | \"nextRetryAt\">): void {\n if (this.inflightIds.has(entry.messageId)) return;\n this.inflightIds.add(entry.messageId);\n this.queue.push({ ...entry, attempts: 0, nextRetryAt: 0 });\n }\n\n /**\n * Process the queue once. Sends due-now entries; reschedules failures\n * with backoff. Returns the number of entries that completed (success\n * or terminal failure) on this tick.\n */\n async tick(): Promise<number> {\n const now = Date.now();\n let completed = 0;\n const stillPending: OutboxEntry[] = [];\n for (const entry of this.queue) {\n if (entry.nextRetryAt > now) {\n stillPending.push(entry);\n continue;\n }\n entry.attempts++;\n let outcomes: Map<string, \"live\" | \"stored\" | \"dropped\" | \"error\">;\n try {\n outcomes = await entry.attempt();\n } catch {\n outcomes = new Map();\n }\n // Success = at least one target stored or live. Errors-only means retry.\n const anyOk = Array.from(outcomes.values()).some((s) => s === \"live\" || s === \"stored\");\n if (anyOk) {\n this.inflightIds.delete(entry.messageId);\n completed++;\n continue;\n }\n if (entry.attempts >= this.opts.maxAttempts) {\n this.inflightIds.delete(entry.messageId);\n completed++;\n continue;\n }\n entry.nextRetryAt = now + this.computeBackoff(entry.attempts);\n stillPending.push(entry);\n }\n this.queue = stillPending;\n return completed;\n }\n\n size(): number {\n return this.queue.length;\n }\n\n /** Test helper. */\n has(messageId: string): boolean {\n return this.inflightIds.has(messageId);\n }\n\n private computeBackoff(attempt: number): number {\n const base = this.opts.baseBackoffMs * 2 ** (attempt - 1);\n const jitter = base * (0.4 * Math.random() - 0.2); // ±20%\n return Math.max(100, Math.floor(base + jitter));\n }\n}\n","// SessionManager — orchestrates outbound and inbound Olm sessions across\n// peer (user, device) pairs. Owns the claim_all flow for outbound, the\n// prekey-message bootstrap for inbound, and serializes session creation\n// per peer device so a burst of sends can't race two outbound sessions.\n//\n// All persistence lives in the underlying CryptoAdapter; this layer is\n// stateless other than its in-memory locking.\n\nimport type { CryptoAdapter, OutboundEnvelope } from \"./crypto/interface.js\";\nimport type { HttpClient } from \"./transport/http.js\";\nimport type { ClaimedDevice } from \"./types.js\";\n\nexport interface SessionManagerOptions {\n http: HttpClient;\n crypto: CryptoAdapter;\n /** This device's id, used to authenticate /api/chat/keys/claim_all. */\n selfDeviceId: string;\n /** This user's id. When sending to self (multi-device echo), used to\n * filter our own device from the fanout. */\n selfUserId?: string | null;\n}\n\n/**\n * EncryptForResult holds per-target encryption output, ready to be put\n * into a chatSend frame's targets[].\n */\nexport interface EncryptForResult {\n peerDeviceId: string;\n ciphertext: string;\n msgType: \"prekey\" | \"normal\";\n}\n\nexport class SessionManager {\n /**\n * Per-peer-device locks to serialize outbound session creation. Without\n * this, two parallel sends to the same fresh peer would each consume an\n * OTK and create two competing sessions.\n */\n private locks = new Map<string, Promise<void>>();\n\n // Cached peer-device bundles. Refreshed by device_discovery; consumed\n // here on send. null = no claim attempted yet for this peer.\n private bundleCache = new Map<string, ClaimedDevice[]>();\n\n // In-flight claim_all promises keyed by peer user. Coalesces parallel\n // first-time sends so they share one claim_all → one OTK consumed → one\n // outbound session per peer device. Without this, two parallel sendText\n // calls both miss the cache, both call claim_all, both consume an OTK,\n // both create outbound sessions, the second persisted session overwrites\n // the first — and subsequent messages encrypt with a session the peer's\n // inbound side never saw.\n private inflightRefresh = new Map<string, Promise<ClaimedDevice[]>>();\n\n constructor(private opts: SessionManagerOptions) {}\n\n /**\n * Encrypt one plaintext for ALL of a peer's currently-known devices.\n * On first contact OR when bundleCache is empty for this peer, calls\n * claim_all to fetch fresh bundles (which atomically pop OTKs).\n *\n * Returns an empty array when the peer has no chat-registered devices\n * (or has blocked the caller — same shape; see contract §2.5).\n */\n async encryptForPeer(peerUserId: string, plaintext: string): Promise<EncryptForResult[]> {\n let devices = await this.ensurePeerBundles(peerUserId);\n // Multi-device self-echo path: filter our own device out of the fanout\n // so we don't try to establish an Olm session with ourselves.\n if (this.opts.selfUserId && peerUserId === this.opts.selfUserId) {\n devices = devices.filter((d) => d.deviceId !== this.opts.selfDeviceId);\n }\n if (devices.length === 0) return [];\n\n const results: EncryptForResult[] = [];\n for (const dev of devices) {\n const env = await this.encryptForOneDevice(peerUserId, dev, plaintext);\n results.push({ peerDeviceId: dev.deviceId, ciphertext: env.ciphertext, msgType: env.msgType });\n }\n return results;\n }\n\n /**\n * Decrypt an inbound ciphertext from (peerUserId, peerDeviceId). On\n * msgType==\"prekey\" with no existing session, creates an inbound\n * session from the prekey message itself — no claim needed.\n */\n async decrypt(\n peerUserId: string,\n peerDeviceId: string,\n ciphertext: string,\n msgType: \"prekey\" | \"normal\",\n ): Promise<string> {\n return this.opts.crypto.decryptFromPeer(peerUserId, peerDeviceId, ciphertext, msgType);\n }\n\n /**\n * Drop the cached bundle list and any session with this peer device.\n * Used on decrypt-failure recovery, before a re-claim.\n */\n async forgetPeerDevice(peerUserId: string, peerDeviceId: string): Promise<void> {\n const cached = this.bundleCache.get(peerUserId);\n if (cached) {\n this.bundleCache.set(\n peerUserId,\n cached.filter((d) => d.deviceId !== peerDeviceId),\n );\n }\n await this.opts.crypto.forgetSession(peerUserId, peerDeviceId);\n }\n\n /** Test/diagnostic helper. */\n async hasSession(peerUserId: string, peerDeviceId: string): Promise<boolean> {\n return this.opts.crypto.hasSession(peerUserId, peerDeviceId);\n }\n\n /**\n * Number of cached devices for `peerUserId` that we'd actually fanout\n * to (excludes selfDeviceId when peerUserId === selfUserId). Returns\n * `null` when no claim has been attempted yet for this peer — caller\n * should treat that as \"unknown, prefer refresh.\"\n */\n cachedFanoutSize(peerUserId: string): number | null {\n const cached = this.bundleCache.get(peerUserId);\n if (!cached) return null;\n if (this.opts.selfUserId && peerUserId === this.opts.selfUserId) {\n return cached.filter((d) => d.deviceId !== this.opts.selfDeviceId).length;\n }\n return cached.length;\n }\n\n /**\n * Force a refresh of peer bundles (e.g., from device_discovery on a\n * detected new peer device). Calls claim_all again; subsequent sends\n * use the new bundles. Pops fresh OTKs server-side.\n */\n async refreshPeerBundles(peerUserId: string): Promise<ClaimedDevice[]> {\n const res = await this.opts.http.claimAll(this.opts.selfDeviceId, peerUserId);\n this.bundleCache.set(peerUserId, res.devices);\n return res.devices;\n }\n\n // ── internal ───────────────────────────────────────────────────────────────\n\n private async ensurePeerBundles(peerUserId: string): Promise<ClaimedDevice[]> {\n const cached = this.bundleCache.get(peerUserId);\n if (cached) return cached;\n const inflight = this.inflightRefresh.get(peerUserId);\n if (inflight) return inflight;\n const p = (async () => {\n try {\n return await this.refreshPeerBundles(peerUserId);\n } finally {\n this.inflightRefresh.delete(peerUserId);\n }\n })();\n this.inflightRefresh.set(peerUserId, p);\n return p;\n }\n\n private async encryptForOneDevice(\n peerUserId: string,\n bundle: ClaimedDevice,\n plaintext: string,\n ): Promise<OutboundEnvelope> {\n const lockKey = sessionKey(peerUserId, bundle.deviceId);\n const prev = this.locks.get(lockKey) ?? Promise.resolve();\n let release!: () => void;\n const next = new Promise<void>((r) => { release = r; });\n this.locks.set(lockKey, prev.then(() => next));\n await prev;\n try {\n return await this.opts.crypto.encryptForPeer(peerUserId, bundle.deviceId, bundle, plaintext);\n } finally {\n release();\n // GC the lock if we're the last waiter.\n if (this.locks.get(lockKey) === prev.then(() => next)) {\n this.locks.delete(lockKey);\n }\n }\n }\n}\n\nfunction sessionKey(peerUserId: string, peerDeviceId: string): string {\n return `${peerUserId}|${peerDeviceId}`;\n}\n","// Sender-side per-message status state machine.\n//\n// sent : the local node accepted at least one target's chatSend\n// (chatSendResult: live | stored).\n// delivered : at least one peer device returned a `received` event.\n// deliveredAll : every peer device the sender knows about returned\n// `received`.\n// read : a `read` event with upToId >= this message arrived.\n//\n// The tracker is in-memory only — status is reconstructable from the\n// store + events on next connect. The SDK emits `statusChange` to the app\n// on every transition.\n\nexport type MessageStatus =\n | \"pending\"\n | \"sent\"\n | \"delivered\"\n | \"deliveredAll\"\n | \"read\";\n\ninterface Outbound {\n messageId: string;\n peerUserId: string;\n /** envelopeUuid → peerDeviceId */\n envelopeToDevice: Map<string, string>;\n /** Peer device ids the sender thinks the recipient has, at send time. */\n peerDevices: Set<string>;\n /** Peer device ids that have returned a `received` for this message. */\n receivedFrom: Set<string>;\n status: MessageStatus;\n}\n\nexport type StatusListener = (\n messageId: string,\n status: MessageStatus,\n peerUserId: string,\n) => void;\n\nexport class StatusTracker {\n private outbound = new Map<string, Outbound>();\n /** Reverse index for quick lookup on chatSendResult. */\n private envelopeToMessage = new Map<string, string>();\n /** Sorted list of (messageId, peerUserId) ordered by send time, used to\n * resolve `read` watermarks against earlier messages. Append-only. */\n private byPeer = new Map<string, string[]>();\n\n private listeners: StatusListener[] = [];\n\n on(fn: StatusListener): () => void {\n this.listeners.push(fn);\n return () => {\n const i = this.listeners.indexOf(fn);\n if (i >= 0) this.listeners.splice(i, 1);\n };\n }\n\n /**\n * Register a freshly-sent message. envelopeToDevice maps each target's\n * envelopeUuid to the peer device it was sent to — fed by the SDK from\n * the chatSend frame's targets[].\n */\n trackOutbound(opts: {\n messageId: string;\n peerUserId: string;\n envelopeToDevice: Map<string, string>;\n }): void {\n const peerDevices = new Set(opts.envelopeToDevice.values());\n this.outbound.set(opts.messageId, {\n messageId: opts.messageId,\n peerUserId: opts.peerUserId,\n envelopeToDevice: opts.envelopeToDevice,\n peerDevices,\n receivedFrom: new Set(),\n status: \"pending\",\n });\n for (const uuid of opts.envelopeToDevice.keys()) {\n this.envelopeToMessage.set(uuid, opts.messageId);\n }\n const list = this.byPeer.get(opts.peerUserId) ?? [];\n list.push(opts.messageId);\n this.byPeer.set(opts.peerUserId, list);\n }\n\n /**\n * Process a chatSendResult outcome. Multiple outcomes per message (one\n * per target). Marks the message at least \"sent\" once any target\n * succeeds.\n */\n onSendResult(envelopeUuid: string, status: \"live\" | \"stored\" | \"dropped\" | \"error\"): void {\n const messageId = this.envelopeToMessage.get(envelopeUuid);\n if (!messageId) return;\n const outbound = this.outbound.get(messageId);\n if (!outbound) return;\n if (status === \"live\" || status === \"stored\") {\n this.bump(outbound, \"sent\");\n }\n // dropped/error: leave status alone — caller might retry from the outbox.\n }\n\n /**\n * Process an inbound `received` event from peer. Marks corresponding\n * outbound messages as delivered (or deliveredAll once all peer\n * devices have acknowledged).\n */\n onReceived(opts: {\n peerUserId: string;\n peerDeviceId: string;\n messageIds: string[];\n }): void {\n for (const id of opts.messageIds) {\n const outbound = this.outbound.get(id);\n if (!outbound) continue;\n if (outbound.peerUserId !== opts.peerUserId) continue;\n if (!outbound.peerDevices.has(opts.peerDeviceId)) {\n // Sender's device list was stale at send time; still count it.\n outbound.peerDevices.add(opts.peerDeviceId);\n }\n outbound.receivedFrom.add(opts.peerDeviceId);\n const allReceived =\n outbound.receivedFrom.size >= outbound.peerDevices.size && outbound.peerDevices.size > 0;\n this.bump(outbound, allReceived ? \"deliveredAll\" : \"delivered\");\n }\n }\n\n /**\n * Process a `read` watermark from the peer. All this peer's outbound\n * messages with sentAt index <= upToId's index move to \"read\".\n * Resolution is by send-order (insertion order in byPeer).\n */\n onRead(opts: { peerUserId: string; upToId: string }): void {\n const list = this.byPeer.get(opts.peerUserId);\n if (!list) return;\n const idx = list.indexOf(opts.upToId);\n if (idx < 0) return;\n for (let i = 0; i <= idx; i++) {\n const outbound = this.outbound.get(list[i]);\n if (!outbound) continue;\n this.bump(outbound, \"read\");\n }\n }\n\n /** Test/diagnostic helper. */\n getStatus(messageId: string): MessageStatus | undefined {\n return this.outbound.get(messageId)?.status;\n }\n\n // ── internal ───────────────────────────────────────────────────────────────\n\n private bump(outbound: Outbound, candidate: MessageStatus): void {\n if (rank(candidate) <= rank(outbound.status)) return;\n outbound.status = candidate;\n for (const fn of this.listeners) {\n try {\n fn(outbound.messageId, candidate, outbound.peerUserId);\n } catch {\n // Listener errors must not break the tracker.\n }\n }\n }\n}\n\nfunction rank(s: MessageStatus): number {\n switch (s) {\n case \"pending\":\n return 0;\n case \"sent\":\n return 1;\n case \"delivered\":\n return 2;\n case \"deliveredAll\":\n return 3;\n case \"read\":\n return 4;\n }\n}\n","// IndexedDB-backed KVStore for browsers. Single object store keyed by string,\n// values are { type: \"string\"|\"bytes\", value }. Async API; the SDK awaits.\n//\n// Tests typically use the in-memory adapter to avoid the IndexedDB dependency\n// in unit tests; real IndexedDB is exercised in browser-mode integration tests.\n\nimport type { KVStore } from \"./interface.js\";\n\nconst DB_NAME = \"dtelecom-secure-chat\";\nconst STORE = \"kv\";\nconst VERSION = 1;\n\ninterface StoredValue {\n type: \"string\" | \"bytes\";\n value: string | Uint8Array;\n}\n\nlet dbPromise: Promise<IDBDatabase> | null = null;\n\nfunction openDB(): Promise<IDBDatabase> {\n if (dbPromise) return dbPromise;\n dbPromise = new Promise((resolve, reject) => {\n const req = indexedDB.open(DB_NAME, VERSION);\n req.onupgradeneeded = () => {\n const db = req.result;\n if (!db.objectStoreNames.contains(STORE)) {\n db.createObjectStore(STORE);\n }\n };\n req.onsuccess = () => resolve(req.result);\n req.onerror = () => reject(req.error);\n });\n return dbPromise;\n}\n\nasync function withStore<T>(\n mode: IDBTransactionMode,\n fn: (store: IDBObjectStore) => IDBRequest<T> | T,\n): Promise<T> {\n const db = await openDB();\n return new Promise((resolve, reject) => {\n const tx = db.transaction(STORE, mode);\n const store = tx.objectStore(STORE);\n const result = fn(store);\n tx.oncomplete = () => {\n // result may be an IDBRequest (success path) or already a value.\n if (result && typeof result === \"object\" && \"result\" in result) {\n resolve((result as IDBRequest<T>).result);\n } else {\n resolve(result as T);\n }\n };\n tx.onerror = () => reject(tx.error);\n tx.onabort = () => reject(tx.error);\n });\n}\n\nexport class WebKVStore implements KVStore {\n async getString(key: string): Promise<string | null> {\n const v = await withStore(\"readonly\", (s) => s.get(key));\n if (!v) return null;\n const sv = v as unknown as StoredValue;\n return sv.type === \"string\" ? (sv.value as string) : null;\n }\n\n async setString(key: string, value: string): Promise<void> {\n const sv: StoredValue = { type: \"string\", value };\n await withStore(\"readwrite\", (s) => s.put(sv, key));\n }\n\n async getBytes(key: string): Promise<Uint8Array | null> {\n const v = await withStore(\"readonly\", (s) => s.get(key));\n if (!v) return null;\n const sv = v as unknown as StoredValue;\n return sv.type === \"bytes\" ? (sv.value as Uint8Array) : null;\n }\n\n async setBytes(key: string, value: Uint8Array): Promise<void> {\n const sv: StoredValue = { type: \"bytes\", value };\n await withStore(\"readwrite\", (s) => s.put(sv, key));\n }\n\n async delete(key: string): Promise<void> {\n await withStore(\"readwrite\", (s) => s.delete(key));\n }\n\n async listKeys(prefix: string): Promise<string[]> {\n const db = await openDB();\n return new Promise((resolve, reject) => {\n const out: string[] = [];\n const tx = db.transaction(STORE, \"readonly\");\n const cursorReq = tx.objectStore(STORE).openKeyCursor();\n cursorReq.onsuccess = () => {\n const cursor = cursorReq.result;\n if (!cursor) {\n resolve(out);\n return;\n }\n const k = cursor.key as string;\n if (k.startsWith(prefix)) out.push(k);\n cursor.continue();\n };\n cursorReq.onerror = () => reject(cursorReq.error);\n });\n }\n}\n","// Typed HTTP client wrapping all /api/chat/* endpoints. Owns no auth state —\n// the caller passes a chat token (or a callback that fetches one). Mirrors\n// chat-wire-contract.md §2 exactly.\n\nimport type {\n AckRequest,\n BlocksListResponse,\n ClaimAllResponse,\n KeyBundleUploadRequest,\n ListDevicesResponse,\n MintTokenResponse,\n OneTimeKey,\n OtkCountResponse,\n OtkTopupRequest,\n PendingResponse,\n} from \"../types.js\";\n\n/**\n * Consumer-supplied callback that mints a chat token via the tenant backend.\n * Must return the full `POST /api/chat/token` response so the SDK can use the\n * server-discovered node URL (chatNodeWsUrl) — no Solana code on the client.\n */\nexport type FetchChatToken = (deviceId: string) => Promise<MintTokenResponse>;\n\nexport interface HttpClientOptions {\n /** Base URL of the dmeet-backend (or mock). e.g. \"http://localhost:8787\" */\n apiBaseURL: string;\n /** Function returning a valid chat token JWT. Called when the SDK needs auth. */\n fetchChatToken: FetchChatToken;\n /** Optional fetch implementation (defaults to globalThis.fetch). */\n fetchImpl?: typeof fetch;\n}\n\nexport class HttpError extends Error {\n constructor(\n public status: number,\n public code: string,\n message: string,\n ) {\n super(message);\n this.name = \"HttpError\";\n }\n}\n\nexport class HttpClient {\n private readonly apiBase: string;\n private readonly fetchToken: FetchChatToken;\n private readonly fetchImpl: typeof fetch;\n\n // Cached MintTokenResponse, keyed by device id. Refreshed when expired.\n private cached: MintTokenResponse | null = null;\n private cachedDeviceId: string | null = null;\n\n constructor(opts: HttpClientOptions) {\n this.apiBase = opts.apiBaseURL.replace(/\\/$/, \"\");\n this.fetchToken = opts.fetchChatToken;\n this.fetchImpl = opts.fetchImpl ?? globalThis.fetch.bind(globalThis);\n }\n\n // ── token + node-url lifecycle ─────────────────────────────────────────────\n\n /**\n * Returns the full mint response (token + chatNodeWsUrl + expiry),\n * fetching afresh if no cached value exists or it expires within 60 seconds.\n * Also re-fetches when the device id changes.\n */\n async getMint(deviceId: string): Promise<MintTokenResponse> {\n const now = Math.floor(Date.now() / 1000);\n if (\n this.cached &&\n this.cachedDeviceId === deviceId &&\n this.cached.expiresAt - now > 60\n ) {\n return this.cached;\n }\n const mint = await this.fetchToken(deviceId);\n if (!mint.chatToken || typeof mint.expiresAt !== \"number\" || !mint.chatNodeWsUrl) {\n throw new Error(\"fetchChatToken must return { chatToken, expiresAt, chatNodeWsUrl }\");\n }\n this.cached = mint;\n this.cachedDeviceId = deviceId;\n return mint;\n }\n\n /** Convenience: just the JWT. Backed by getMint(). */\n async getToken(deviceId: string): Promise<string> {\n return (await this.getMint(deviceId)).chatToken;\n }\n\n /** Convenience: just the discovered node WS URL. Backed by getMint(). */\n async getNodeWsUrl(deviceId: string): Promise<string> {\n return (await this.getMint(deviceId)).chatNodeWsUrl;\n }\n\n // ── authed JSON helpers ────────────────────────────────────────────────────\n\n private async authedJson<T>(\n method: \"GET\" | \"POST\" | \"DELETE\",\n path: string,\n deviceId: string,\n body?: unknown,\n ): Promise<T> {\n const token = await this.getToken(deviceId);\n const headers: Record<string, string> = {\n authorization: `Bearer ${token}`,\n };\n let bodyText: string | undefined;\n if (body !== undefined) {\n headers[\"content-type\"] = \"application/json\";\n bodyText = JSON.stringify(body);\n }\n const res = await this.fetchImpl(`${this.apiBase}${path}`, {\n method,\n headers,\n body: bodyText,\n });\n if (!res.ok) {\n let code = \"http_error\";\n let msg = `${res.status} ${res.statusText}`;\n try {\n const errJson = (await res.json()) as { error?: string; message?: string };\n if (errJson.error) code = errJson.error;\n if (errJson.message) msg = errJson.message;\n } catch {\n // body wasn't JSON\n }\n throw new HttpError(res.status, code, msg);\n }\n if (res.status === 204) return undefined as T;\n return (await res.json()) as T;\n }\n\n // ── /api/chat/keys ─────────────────────────────────────────────────────────\n\n uploadKeyBundle(deviceId: string, body: KeyBundleUploadRequest): Promise<{ ok: true }> {\n return this.authedJson(\"POST\", \"/api/chat/keys/upload\", deviceId, body);\n }\n\n topupOtks(deviceId: string, keys: OneTimeKey[]): Promise<{ ok: true; currentCount: number }> {\n const body: OtkTopupRequest = { deviceId: deviceId, oneTimeKeys: keys };\n return this.authedJson(\"POST\", \"/api/chat/keys/topup\", deviceId, body);\n }\n\n otkCount(deviceId: string): Promise<OtkCountResponse> {\n return this.authedJson(\n \"GET\",\n `/api/chat/keys/count?deviceId=${encodeURIComponent(deviceId)}`,\n deviceId,\n );\n }\n\n claimAll(deviceId: string, peerUserId: string): Promise<ClaimAllResponse> {\n return this.authedJson(\"POST\", \"/api/chat/keys/claim_all\", deviceId, {\n peerUserId: peerUserId,\n });\n }\n\n listDevices(deviceId: string, peerUserId: string): Promise<ListDevicesResponse> {\n return this.authedJson(\n \"GET\",\n `/api/chat/keys/list_devices?peerUserId=${encodeURIComponent(peerUserId)}`,\n deviceId,\n );\n }\n\n // ── /api/chat/envelopes ────────────────────────────────────────────────────\n\n pending(deviceId: string, limit = 100): Promise<PendingResponse> {\n return this.authedJson(\n \"GET\",\n `/api/chat/envelopes/pending?deviceId=${encodeURIComponent(deviceId)}&limit=${limit}`,\n deviceId,\n );\n }\n\n ack(deviceId: string, envelopeUuids: string[]): Promise<{ ok: true; deletedCount: number }> {\n const body: AckRequest = { deviceId: deviceId, envelopeUuids: envelopeUuids };\n return this.authedJson(\"POST\", \"/api/chat/envelopes/ack\", deviceId, body);\n }\n\n // ── /api/chat/blocks ───────────────────────────────────────────────────────\n\n blockUser(deviceId: string, peerUserId: string): Promise<{ ok: true }> {\n return this.authedJson(\"POST\", \"/api/chat/blocks\", deviceId, { peerUserId: peerUserId });\n }\n\n unblockUser(deviceId: string, peerUserId: string): Promise<{ ok: true }> {\n return this.authedJson(\n \"DELETE\",\n `/api/chat/blocks/${encodeURIComponent(peerUserId)}`,\n deviceId,\n );\n }\n\n listBlocked(deviceId: string): Promise<BlocksListResponse> {\n return this.authedJson(\"GET\", \"/api/chat/blocks\", deviceId);\n }\n}\n","// WebSocket client for /chat/ws. JSON frames per chat-wire-contract.md §3.\n// Auto-reconnect with exponential backoff. Token attached via the\n// `?access_token=` query param (browsers can't set headers on WS upgrade).\n\nimport type {\n ChatPingFrame,\n ChatSendFrame,\n InboundFrame,\n OutboundFrame,\n} from \"../types.js\";\n\nexport type WsState = \"connecting\" | \"open\" | \"closing\" | \"closed\" | \"reconnecting\";\n\nexport interface WsClientOptions {\n /** Full WebSocket URL including scheme, e.g. \"wss://node.test.dtelecom.org\" */\n nodeBaseURL: string;\n /** Returns the chat-token JWT to attach as ?access_token=… */\n getToken: () => Promise<string>;\n /** Called for each inbound frame (already JSON-parsed and discriminated). */\n onFrame: (frame: InboundFrame) => void;\n /** Called when the connection state changes. */\n onState?: (state: WsState) => void;\n /** Optional WebSocket constructor (defaults to globalThis.WebSocket). */\n webSocketImpl?: typeof WebSocket;\n /** Auto-reconnect on close (default true). Disable for one-shot tests. */\n reconnect?: boolean;\n /** Send a chatPing every N ms while open (default 25_000; 0 disables). */\n pingIntervalMs?: number;\n}\n\nexport class WsClient {\n private opts: Required<Omit<WsClientOptions, \"webSocketImpl\">> & {\n webSocketImpl: typeof WebSocket;\n };\n private socket: WebSocket | null = null;\n private state: WsState = \"closed\";\n private attempt = 0;\n private pingTimer: ReturnType<typeof setInterval> | null = null;\n private explicitClose = false;\n\n constructor(opts: WsClientOptions) {\n this.opts = {\n nodeBaseURL: opts.nodeBaseURL.replace(/\\/$/, \"\"),\n getToken: opts.getToken,\n onFrame: opts.onFrame,\n onState: opts.onState ?? (() => {}),\n webSocketImpl: opts.webSocketImpl ?? (globalThis.WebSocket as typeof WebSocket),\n reconnect: opts.reconnect ?? true,\n pingIntervalMs: opts.pingIntervalMs ?? 25_000,\n };\n }\n\n getState(): WsState {\n return this.state;\n }\n\n /** Open a connection. Resolves once the WS reaches `open`. */\n async connect(): Promise<void> {\n if (this.state === \"open\" || this.state === \"connecting\") return;\n this.explicitClose = false;\n return this.connectInternal();\n }\n\n /** Send an outbound frame. Throws if not open. */\n send(frame: OutboundFrame): void {\n if (!this.socket || this.state !== \"open\") {\n throw new Error(`ws not open (state=${this.state})`);\n }\n this.socket.send(JSON.stringify(frame));\n }\n\n /** Convenience for a chatSend frame. */\n sendChat(frame: Omit<ChatSendFrame, \"kind\">): void {\n this.send({ kind: \"chatSend\", ...frame });\n }\n\n /** Convenience for a chatPing. */\n ping(): void {\n const f: ChatPingFrame = { kind: \"chatPing\" };\n this.send(f);\n }\n\n /** Close the connection. After this, no auto-reconnect happens. */\n async close(): Promise<void> {\n this.explicitClose = true;\n this.setState(\"closing\");\n if (this.pingTimer) {\n clearInterval(this.pingTimer);\n this.pingTimer = null;\n }\n if (this.socket && this.socket.readyState === this.opts.webSocketImpl.OPEN) {\n this.socket.close(1000, \"client closing\");\n }\n }\n\n // ── internal ───────────────────────────────────────────────────────────────\n\n private async connectInternal(): Promise<void> {\n this.setState(\"connecting\");\n const token = await this.opts.getToken();\n const url = `${this.opts.nodeBaseURL}/chat/ws?access_token=${encodeURIComponent(token)}`;\n const Ctor = this.opts.webSocketImpl;\n const sock = new Ctor(url);\n this.socket = sock;\n\n return new Promise<void>((resolve, reject) => {\n sock.onopen = () => {\n this.attempt = 0;\n this.setState(\"open\");\n this.startPing();\n resolve();\n };\n sock.onmessage = (ev: MessageEvent) => {\n let frame: InboundFrame;\n try {\n frame = JSON.parse(typeof ev.data === \"string\" ? ev.data : \"\") as InboundFrame;\n } catch {\n return; // ignore malformed\n }\n try {\n const ret = this.opts.onFrame(frame);\n // Catch async rejections too — some consumers' onFrame returns a\n // Promise (e.g. SDK's async handler chain). Without this, an\n // inbound message that triggers an internal failure would surface\n // as an UnhandledPromiseRejection on the process.\n if (ret && typeof (ret as Promise<unknown>).catch === \"function\") {\n (ret as Promise<unknown>).catch(() => {});\n }\n } catch {\n // user handler errors must not break the read loop\n }\n };\n sock.onerror = (_ev: Event) => {\n // The error event itself rarely has actionable info — onclose is what\n // we react to. If the connect hasn't resolved yet, surface as reject.\n if (this.state === \"connecting\") reject(new Error(\"ws connect error\"));\n };\n sock.onclose = () => {\n this.stopPing();\n this.socket = null;\n if (this.explicitClose || !this.opts.reconnect) {\n this.setState(\"closed\");\n return;\n }\n this.setState(\"reconnecting\");\n const delay = backoffMs(this.attempt++);\n setTimeout(() => {\n // best-effort; new failure repeats the cycle\n this.connectInternal().catch(() => {});\n }, delay);\n };\n });\n }\n\n private startPing(): void {\n if (this.opts.pingIntervalMs <= 0) return;\n this.pingTimer = setInterval(() => {\n try {\n this.ping();\n } catch {\n // not open; the read loop will reconnect\n }\n }, this.opts.pingIntervalMs);\n }\n\n private stopPing(): void {\n if (this.pingTimer) {\n clearInterval(this.pingTimer);\n this.pingTimer = null;\n }\n }\n\n private setState(s: WsState): void {\n if (this.state === s) return;\n this.state = s;\n try {\n this.opts.onState(s);\n } catch {\n // never let listener errors propagate\n }\n }\n}\n\nfunction backoffMs(attempt: number): number {\n // 0.5s, 1s, 2s, 4s, 8s, capped at 30s. With ±20% jitter.\n const base = Math.min(500 * 2 ** attempt, 30_000);\n const jitter = base * (0.2 * (Math.random() - 0.5) * 2);\n return Math.max(250, Math.floor(base + jitter));\n}\n","// TypingManager — debounces user \"typing\" signals into ephemeral\n// `started`/`stopped` events. The SDK calls `setTyping(peerId, true)`\n// on every keystroke; this layer:\n//\n// - emits `started` at most once per 3s while typing\n// - auto-emits `stopped` after 5s of no further setTyping(true)\n// - emits `stopped` immediately when setTyping is called with false\n// - emits `stopped` on `clearOnSend(peerId)` (the SDK's send path)\n\nconst STARTED_REFRESH_MS = 3_000;\nconst AUTO_STOPPED_AFTER_MS = 5_000;\n\nexport type TypingEmitter = (\n peerUserId: string,\n state: \"started\" | \"stopped\",\n) => void;\n\ninterface PeerState {\n /** When did we last emit a `started`? Used to throttle. */\n lastStartedAt: number;\n /** Pending auto-stop timer id. */\n autoStopTimer: ReturnType<typeof setTimeout> | null;\n /** Are we currently in the \"started\" state from this peer's perspective? */\n isActive: boolean;\n}\n\nexport class TypingManager {\n private peers = new Map<string, PeerState>();\n\n constructor(private emit: TypingEmitter) {}\n\n /**\n * Called by the SDK on every keystroke change.\n * `isTyping=true` means \"user is typing now\"; `false` means \"user\n * explicitly stopped (cleared input or blurred)\".\n */\n setTyping(peerUserId: string, isTyping: boolean): void {\n const now = Date.now();\n const state = this.peers.get(peerUserId);\n if (!isTyping) {\n // Explicit stop. Emit only if we previously emitted started.\n if (state?.isActive) {\n this.cancelAutoStop(state);\n state.isActive = false;\n this.emit(peerUserId, \"stopped\");\n }\n return;\n }\n\n if (!state) {\n const fresh: PeerState = {\n lastStartedAt: now,\n autoStopTimer: null,\n isActive: true,\n };\n this.peers.set(peerUserId, fresh);\n this.scheduleAutoStop(peerUserId, fresh);\n this.emit(peerUserId, \"started\");\n return;\n }\n\n // Coming out of stopped (auto-stop or clearOnSend) — emit a fresh\n // \"started\" unconditionally; the throttle only suppresses while a\n // continuous typing run is in progress.\n if (!state.isActive) {\n state.isActive = true;\n state.lastStartedAt = now;\n this.scheduleAutoStop(peerUserId, state);\n this.emit(peerUserId, \"started\");\n return;\n }\n\n // Continuous typing run — refresh the auto-stop timer; only re-emit\n // started if 3s has elapsed since the last started.\n this.cancelAutoStop(state);\n this.scheduleAutoStop(peerUserId, state);\n if (now - state.lastStartedAt >= STARTED_REFRESH_MS) {\n state.lastStartedAt = now;\n this.emit(peerUserId, \"started\");\n }\n }\n\n /**\n * Called by the SDK when it actually sends a (non-typing) message to\n * this peer — closes any in-progress typing state silently.\n */\n clearOnSend(peerUserId: string): void {\n const state = this.peers.get(peerUserId);\n if (!state || !state.isActive) return;\n this.cancelAutoStop(state);\n state.isActive = false;\n this.emit(peerUserId, \"stopped\");\n }\n\n /** Tear down all timers (called on chat.disconnect()). */\n shutdown(): void {\n for (const state of this.peers.values()) {\n this.cancelAutoStop(state);\n }\n this.peers.clear();\n }\n\n // ── internal ───────────────────────────────────────────────────────────────\n\n private scheduleAutoStop(peerUserId: string, state: PeerState): void {\n state.autoStopTimer = setTimeout(() => {\n state.autoStopTimer = null;\n if (!state.isActive) return;\n state.isActive = false;\n this.emit(peerUserId, \"stopped\");\n }, AUTO_STOPPED_AFTER_MS);\n }\n\n private cancelAutoStop(state: PeerState): void {\n if (state.autoStopTimer) {\n clearTimeout(state.autoStopTimer);\n state.autoStopTimer = null;\n }\n }\n}\n","// In-memory test-only CryptoAdapter that pretends to do Olm but actually\n// just round-trips plaintext (with a marker prefix to verify it went through\n// the encrypt/decrypt path). Lets unit tests exercise sessions.ts and\n// key_bundle.ts without bundling WASM into the test runner.\n//\n// SECURITY: never use this in production. Has zero cryptographic value.\n\nimport type { CryptoAdapter, OutboundEnvelope, UploadBundle } from \"./interface.js\";\nimport type { ClaimedDevice } from \"../types.js\";\n\ninterface FakeAccountState {\n identityKeyCurve: string;\n identityKeyEd: string;\n signedPrekey: string;\n signedPrekeySig: string;\n fallbackPrekey: string;\n fallbackPrekeySig: string;\n fingerprint: string;\n otkPool: { id: string; public: string }[];\n}\n\nconst PREKEY_MARKER = \"FAKEPREKEY:\";\nconst NORMAL_MARKER = \"FAKENORMAL:\";\n\nexport class FakeCryptoAdapter implements CryptoAdapter {\n private account: FakeAccountState | null = null;\n // session existence — keyed \"<peerUser>|<peerDevice>\"; value irrelevant\n private sessions = new Set<string>();\n private otkCounter = 0;\n\n async init(): Promise<void> {\n /* no-op for fake */\n }\n\n async hasAccount(): Promise<boolean> {\n return this.account !== null;\n }\n\n async generateAccount(otkCount: number): Promise<UploadBundle> {\n if (this.account) throw new Error(\"account already exists\");\n const id = randomB64(32);\n this.account = {\n identityKeyCurve: id,\n identityKeyEd: randomB64(32),\n signedPrekey: randomB64(32),\n signedPrekeySig: randomB64(64),\n fallbackPrekey: randomB64(32),\n fallbackPrekeySig: randomB64(64),\n fingerprint: chunked(id),\n otkPool: this.makeOtks(otkCount),\n };\n return this.snapshot();\n }\n\n async getCurrentBundle(): Promise<UploadBundle> {\n if (!this.account) throw new Error(\"no account\");\n return this.snapshot();\n }\n\n async generateOneTimeKeys(n: number): Promise<{ id: string; public: string }[]> {\n if (!this.account) throw new Error(\"no account\");\n const fresh = this.makeOtks(n);\n this.account.otkPool.push(...fresh);\n return fresh;\n }\n\n async unusedOneTimeKeyCount(): Promise<number> {\n return this.account?.otkPool.length ?? 0;\n }\n\n async encryptForPeer(\n peerUserId: string,\n peerDeviceId: string,\n _peerBundle: ClaimedDevice,\n plaintext: string,\n ): Promise<OutboundEnvelope> {\n if (!this.account) throw new Error(\"no account\");\n const key = sessionKey(peerUserId, peerDeviceId);\n const isFirst = !this.sessions.has(key);\n this.sessions.add(key);\n const marker = isFirst ? PREKEY_MARKER : NORMAL_MARKER;\n const ciphertext = btoa(marker + plaintext);\n return { ciphertext, msgType: isFirst ? \"prekey\" : \"normal\" };\n }\n\n async decryptFromPeer(\n peerUserId: string,\n peerDeviceId: string,\n ciphertext: string,\n msgType: \"prekey\" | \"normal\",\n ): Promise<string> {\n if (!this.account) throw new Error(\"no account\");\n const key = sessionKey(peerUserId, peerDeviceId);\n if (msgType === \"prekey\") {\n this.sessions.add(key);\n } else if (!this.sessions.has(key)) {\n throw new Error(\"no session for normal-type ciphertext\");\n }\n const decoded = atob(ciphertext);\n const expected = msgType === \"prekey\" ? PREKEY_MARKER : NORMAL_MARKER;\n if (!decoded.startsWith(expected)) {\n throw new Error(`fake decrypt: expected ${expected} prefix, got ${decoded.slice(0, 16)}`);\n }\n return decoded.slice(expected.length);\n }\n\n async forgetSession(peerUserId: string, peerDeviceId: string): Promise<void> {\n this.sessions.delete(sessionKey(peerUserId, peerDeviceId));\n }\n\n async hasSession(peerUserId: string, peerDeviceId: string): Promise<boolean> {\n return this.sessions.has(sessionKey(peerUserId, peerDeviceId));\n }\n\n // ── helpers ────────────────────────────────────────────────────────────────\n\n private snapshot(): UploadBundle {\n if (!this.account) throw new Error(\"no account\");\n const { otkPool, ...rest } = this.account;\n return { ...rest, oneTimeKeys: [...otkPool] };\n }\n\n private makeOtks(n: number): { id: string; public: string }[] {\n const out: { id: string; public: string }[] = [];\n for (let i = 0; i < n; i++) {\n this.otkCounter++;\n out.push({ id: `fake-otk-${this.otkCounter}`, public: randomB64(32) });\n }\n return out;\n }\n}\n\nfunction sessionKey(peerUserId: string, peerDeviceId: string): string {\n return `${peerUserId}|${peerDeviceId}`;\n}\n\nfunction randomB64(bytes: number): string {\n const buf = new Uint8Array(bytes);\n globalThis.crypto.getRandomValues(buf);\n // base64url, no padding\n return btoa(String.fromCharCode(...buf)).replace(/=+$/, \"\").replace(/\\+/g, \"-\").replace(/\\//g, \"_\");\n}\n\nfunction chunked(b64: string): string {\n // 4-character groups separated by hyphens — visual stand-in for the\n // safety-number fingerprint format the UI eventually displays.\n const hex = b64.slice(0, 32);\n return hex.match(/.{1,4}/g)?.join(\"-\") ?? hex;\n}\n","// In-memory KVStore for unit tests and Node-side smoke tests where we don't\n// want an IndexedDB dependency. Same semantics as WebKVStore.\n\nimport type { KVStore } from \"./interface.js\";\n\ninterface StoredValue {\n type: \"string\" | \"bytes\";\n value: string | Uint8Array;\n}\n\nexport class MemoryKVStore implements KVStore {\n private map = new Map<string, StoredValue>();\n\n async getString(key: string): Promise<string | null> {\n const v = this.map.get(key);\n return v?.type === \"string\" ? (v.value as string) : null;\n }\n async setString(key: string, value: string): Promise<void> {\n this.map.set(key, { type: \"string\", value });\n }\n async getBytes(key: string): Promise<Uint8Array | null> {\n const v = this.map.get(key);\n return v?.type === \"bytes\" ? (v.value as Uint8Array) : null;\n }\n async setBytes(key: string, value: Uint8Array): Promise<void> {\n this.map.set(key, { type: \"bytes\", value });\n }\n async delete(key: string): Promise<void> {\n this.map.delete(key);\n }\n async listKeys(prefix: string): Promise<string[]> {\n const out: string[] = [];\n for (const k of this.map.keys()) {\n if (k.startsWith(prefix)) out.push(k);\n }\n return out;\n }\n}\n","// Public SDK surface. Wires transport + crypto + content protocol behind\n// a small event-emitter API. Most app code will only ever touch this file.\n\nimport { CONTENT_PROTOCOL_VERSION as _CONTENT_VERSION } from \"./content/protocol.js\";\nimport {\n decodeEventBytes,\n encodeEventBytes,\n newDelete,\n newEdit,\n newRead,\n newReceived,\n newSelfEcho,\n newText,\n newTyping,\n type SelfEchoableEvent,\n type ContentEvent,\n} from \"./content/protocol.js\";\nimport type { CryptoAdapter } from \"./crypto/interface.js\";\nimport { OlmCryptoAdapter } from \"./crypto/olm-adapter.js\";\nimport { loadOrCreateDeviceId } from \"./device.js\";\nimport { PeerDeviceCache } from \"./device_discovery.js\";\nimport { KeyBundleManager } from \"./key_bundle.js\";\nimport { MessageStore, type StoredMessage } from \"./message_store.js\";\nimport { Outbox } from \"./outbox.js\";\nimport { SessionManager } from \"./sessions.js\";\nimport { StatusTracker, type MessageStatus } from \"./status.js\";\nimport type { KVStore } from \"./store/interface.js\";\nimport { WebKVStore } from \"./store/web-adapter.js\";\nimport { HttpClient, type FetchChatToken } from \"./transport/http.js\";\nimport { WsClient } from \"./transport/ws.js\";\nimport { TypingManager } from \"./typing.js\";\nimport type { ChatSendResult, ChatSendTarget, InboundFrame } from \"./types.js\";\n\nexport const VERSION = \"0.0.0\";\nexport const CONTENT_PROTOCOL_VERSION = _CONTENT_VERSION;\n\n// ── public option types ─────────────────────────────────────────────────────\n\nexport interface ConnectOptions {\n /** dmeet-backend (or mock) base URL — e.g. https://dmeet.example.com */\n apiBaseURL: string;\n /** Function that mints a chat token. The SDK calls this whenever a fresh\n * token is needed; the consumer's implementation handles their own\n * outer auth (Privy, an internal cookie, etc.). */\n fetchChatToken: FetchChatToken;\n /** Optional. Defaults to WebKVStore (IndexedDB) in browsers. Tests pass\n * MemoryKVStore to avoid the IDB dependency. */\n store?: KVStore;\n /** Optional. Defaults to OlmCryptoAdapter wrapping vodozemac. Tests\n * pass FakeCryptoAdapter to avoid bundling WASM in the test runner. */\n crypto?: CryptoAdapter;\n /** Optional fetch implementation. Defaults to globalThis.fetch. Tests\n * pass a mocked fetch to avoid real network calls. */\n fetchImpl?: typeof fetch;\n}\n\n// ── public event types ──────────────────────────────────────────────────────\n\nexport interface MessageReceived {\n peerUserId: string;\n peerDeviceId: string;\n /** The user that authored this message. Equals selfUserId when the\n * message arrived via self-echo from another own device. */\n senderUserId: string;\n message: { id: string; text: string; replyTo?: string; sentAt: number };\n}\n\nexport interface MessageEdited {\n peerUserId: string;\n /** Author of the edit. Equals selfUserId for self-echoed edits. */\n editorUserId: string;\n targetId: string;\n newText: string;\n editedAt: number;\n}\n\nexport interface MessageDeleted {\n peerUserId: string;\n /** Author of the delete. Equals selfUserId for self-echoed deletes. */\n deleterUserId: string;\n targetId: string;\n deletedAt: number;\n}\n\nexport interface ReadReceiptEvent {\n peerUserId: string;\n peerDeviceId: string;\n upToId: string;\n}\n\nexport interface TypingEvt {\n peerUserId: string;\n peerDeviceId: string;\n state: \"started\" | \"stopped\";\n}\n\nexport interface StatusChangeEvt {\n peerUserId: string;\n messageId: string;\n status: MessageStatus;\n}\n\n/**\n * Emitted the first time the SDK observes a previously-unknown peer device,\n * either via an inbound prekey-message from it OR via a refreshed device\n * list. Apps render this as the \"Bob is using a new device — verify?\"\n * banner per plan §17.\n */\nexport interface PeerNewDeviceEvt {\n peerUserId: string;\n peerDeviceId: string;\n fingerprint: string;\n}\n\ninterface EventMap {\n message: MessageReceived;\n messageEdited: MessageEdited;\n messageDeleted: MessageDeleted;\n readReceipt: ReadReceiptEvent;\n typing: TypingEvt;\n statusChange: StatusChangeEvt;\n peerNewDevice: PeerNewDeviceEvt;\n}\n\ntype EventName = keyof EventMap;\ntype Listener<T extends EventName> = (event: EventMap[T]) => void;\n\n// ── DTelecomSecureChat ──────────────────────────────────────────────────────\n\nconst RECEIVED_BATCH_FLUSH_MS = 500;\nconst RECEIVED_BATCH_FLUSH_SIZE = 50;\nconst READ_RECEIPTS_KEY = \"prefs/readReceiptsEnabled\";\n\n/** Public shape returned by `getKnownPeerDevices()`. */\nexport interface KnownPeerDevice {\n deviceId: string;\n fingerprint: string;\n lastActiveAt: number;\n /** True if the local user has explicitly verified this device. */\n verified: boolean;\n}\n\nfunction verifiedKey(peerUserId: string, peerDeviceId: string): string {\n return `verifiedDevice/${peerUserId}/${peerDeviceId}`;\n}\n\nexport class DTelecomSecureChat {\n private deviceId!: string;\n private http!: HttpClient;\n private ws!: WsClient;\n private crypto!: CryptoAdapter;\n private store!: KVStore;\n private keyBundle!: KeyBundleManager;\n private sessions!: SessionManager;\n private peerDevices!: PeerDeviceCache;\n private messages!: MessageStore;\n private status!: StatusTracker;\n private outbox = new Outbox();\n private typingMgr!: TypingManager;\n private listeners = new Map<EventName, Set<(event: unknown) => void>>();\n\n /** Per-peer-device queue of received-event ids awaiting batch send. */\n private pendingReceived = new Map<string, string[]>();\n private receivedFlushTimer: ReturnType<typeof setTimeout> | null = null;\n /** Self user id derived from chat-token claims after first mint. */\n private selfUserId: string | null = null;\n /** Devices we've already emitted `peerNewDevice` for, to avoid duplicates. */\n private announcedNewDevices = new Set<string>();\n /** True after we've reuploaded the bundle once for this connection — set\n * after a \"peer has zero devices\" outcome that suggests the backend\n * forgot us (registry mismatch / wipe). Don't loop. */\n private bundleReuploadAttempted = false;\n /** Cache of the read-receipts preference (loaded lazily). */\n private readReceiptsCache: boolean | null = null;\n\n /**\n * Connect to the dtelecom mesh. Generates an Olm account on first run,\n * uploads the bundle, opens /chat/ws to the closest discovered node,\n * and pulls any pending offline envelopes.\n */\n static async connect(opts: ConnectOptions): Promise<DTelecomSecureChat> {\n const chat = new DTelecomSecureChat();\n await chat.bootstrap(opts);\n return chat;\n }\n\n // The constructor is private-by-convention — use connect().\n private constructor() {}\n\n /** Stable per-install device id. Useful for app diagnostics. */\n get currentDeviceId(): string {\n return this.deviceId;\n }\n\n // ── public API: messaging ──────────────────────────────────────────────────\n\n async sendText(peerUserId: string, text: string, opts?: { replyTo?: string }): Promise<string> {\n const event = newText(text, opts?.replyTo);\n await this.sendContent(peerUserId, event, { ephemeral: false });\n\n // Persist locally so the UI can show our own sent message.\n if (this.selfUserId) {\n await this.messages.put({\n id: event.id,\n peerUserId,\n senderUserId: this.selfUserId,\n text: event.text,\n sentAt: event.clientSentAt,\n editedAt: null,\n deletedAt: null,\n ...(event.replyTo !== undefined ? { replyTo: event.replyTo } : {}),\n });\n }\n await this.selfEcho(peerUserId, event);\n this.typingMgr.clearOnSend(peerUserId);\n return event.id;\n }\n\n async editMessage(peerUserId: string, targetId: string, newText: string): Promise<string> {\n const event = newEdit(targetId, newText);\n await this.sendContent(peerUserId, event, { ephemeral: false });\n if (this.selfUserId) {\n await this.messages.applyEdit({\n targetId,\n editorUserId: this.selfUserId,\n newText,\n editedAt: event.clientSentAt,\n });\n }\n await this.selfEcho(peerUserId, event);\n return event.id;\n }\n\n async deleteMessage(peerUserId: string, targetId: string): Promise<string> {\n const event = newDelete(targetId);\n await this.sendContent(peerUserId, event, { ephemeral: false });\n if (this.selfUserId) {\n await this.messages.applyDelete({\n targetId,\n deleterUserId: this.selfUserId,\n deletedAt: event.clientSentAt,\n });\n }\n await this.selfEcho(peerUserId, event);\n return event.id;\n }\n\n /**\n * Send a read-watermark to `peerUserId`. No-op when read receipts are\n * disabled by `setReadReceiptsEnabled(false)` — the local user remains\n * invisible to senders, but inbound `read` events from peers are still\n * consumed (the sender's preference is their own call).\n */\n async markRead(peerUserId: string, upToMessageId: string): Promise<void> {\n if (!(await this.areReadReceiptsEnabled())) return;\n const event = newRead(upToMessageId);\n await this.sendContent(peerUserId, event, { ephemeral: false });\n await this.selfEcho(peerUserId, event);\n }\n\n setTyping(peerUserId: string, isTyping: boolean): void {\n this.typingMgr.setTyping(peerUserId, isTyping);\n }\n\n // ── public API: preferences ───────────────────────────────────────────────\n\n /** Enable/disable outbound read receipts. Persisted in the local KV store. */\n async setReadReceiptsEnabled(enabled: boolean): Promise<void> {\n await this.store.setString(READ_RECEIPTS_KEY, enabled ? \"1\" : \"0\");\n this.readReceiptsCache = enabled;\n }\n\n /** Read the current preference. Default true. */\n async areReadReceiptsEnabled(): Promise<boolean> {\n if (this.readReceiptsCache !== null) return this.readReceiptsCache;\n const raw = await this.store.getString(READ_RECEIPTS_KEY);\n const enabled = raw === null ? true : raw === \"1\";\n this.readReceiptsCache = enabled;\n return enabled;\n }\n\n // ── public API: peer device verification ──────────────────────────────────\n\n /**\n * Returns the cached peer-device list for `peerUserId`. Refreshes via\n * `list_devices` if the local cache is empty or stale. Used to render\n * the \"Known Devices\" settings panel. Doesn't consume OTKs.\n */\n async getKnownPeerDevices(peerUserId: string): Promise<KnownPeerDevice[]> {\n const devices = await this.peerDevices.getPeerDevices(peerUserId);\n const out: KnownPeerDevice[] = [];\n for (const d of devices) {\n const verified = await this.isPeerDeviceVerified(peerUserId, d.deviceId);\n out.push({\n deviceId: d.deviceId,\n fingerprint: d.fingerprint,\n lastActiveAt: d.lastActiveAt,\n verified,\n });\n }\n return out;\n }\n\n /** Single-device fingerprint accessor. Returns null if unknown. */\n async getPeerDeviceFingerprint(\n peerUserId: string,\n peerDeviceId: string,\n ): Promise<string | null> {\n const list = await this.peerDevices.getPeerDevices(peerUserId);\n return list.find((d) => d.deviceId === peerDeviceId)?.fingerprint ?? null;\n }\n\n /**\n * Mark a peer device as verified (or unverified). Local-only — doesn't\n * change the protocol's behavior, just exposes a flag the UI can render.\n */\n async markPeerDeviceVerified(\n peerUserId: string,\n peerDeviceId: string,\n verified: boolean,\n ): Promise<void> {\n const key = verifiedKey(peerUserId, peerDeviceId);\n if (verified) {\n await this.store.setString(key, \"1\");\n } else {\n await this.store.delete(key);\n }\n }\n\n async isPeerDeviceVerified(peerUserId: string, peerDeviceId: string): Promise<boolean> {\n return (await this.store.getString(verifiedKey(peerUserId, peerDeviceId))) === \"1\";\n }\n\n /**\n * Read persisted message history with `peerUserId`, oldest→newest within\n * the page. Use `beforeSentAt` + `limit` to paginate older messages.\n * Returns include local-sent messages (sender = self), inbound messages\n * (sender = peer), and tombstoned/edited rows reflecting the latest state.\n */\n getHistory(\n peerUserId: string,\n opts: { limit?: number; beforeSentAt?: number } = {},\n ): Promise<StoredMessage[]> {\n return this.messages.listForPeer(peerUserId, opts);\n }\n\n // ── public API: blocks ─────────────────────────────────────────────────────\n\n blockUser(peerUserId: string): Promise<{ ok: true }> {\n return this.http.blockUser(this.deviceId, peerUserId);\n }\n unblockUser(peerUserId: string): Promise<{ ok: true }> {\n return this.http.unblockUser(this.deviceId, peerUserId);\n }\n async getBlockedUsers(): Promise<string[]> {\n const r = await this.http.listBlocked(this.deviceId);\n return r.blocked;\n }\n\n // ── public API: events ─────────────────────────────────────────────────────\n\n on<T extends EventName>(event: T, fn: Listener<T>): () => void {\n let set = this.listeners.get(event);\n if (!set) {\n set = new Set();\n this.listeners.set(event, set);\n }\n set.add(fn as (event: unknown) => void);\n return () => set!.delete(fn as (event: unknown) => void);\n }\n\n // ── lifecycle ──────────────────────────────────────────────────────────────\n\n async disconnect(): Promise<void> {\n this.typingMgr.shutdown();\n this.flushReceivedBatch();\n await this.ws.close();\n }\n\n // ── internals ──────────────────────────────────────────────────────────────\n\n private async bootstrap(opts: ConnectOptions): Promise<void> {\n this.store = opts.store ?? new WebKVStore();\n this.crypto = opts.crypto ?? new OlmCryptoAdapter({ store: this.store });\n await this.crypto.init();\n\n this.deviceId = await loadOrCreateDeviceId(this.store);\n\n this.http = new HttpClient({\n apiBaseURL: opts.apiBaseURL,\n fetchChatToken: opts.fetchChatToken,\n ...(opts.fetchImpl ? { fetchImpl: opts.fetchImpl } : {}),\n });\n\n // Seed the token cache and capture our self user id from the claims.\n const mint = await this.http.getMint(this.deviceId);\n this.selfUserId = parseSubFromJwt(mint.chatToken);\n\n this.keyBundle = new KeyBundleManager({ http: this.http, crypto: this.crypto, deviceId: this.deviceId });\n await this.keyBundle.ensureKeyBundle();\n\n this.sessions = new SessionManager({\n http: this.http,\n crypto: this.crypto,\n selfDeviceId: this.deviceId,\n selfUserId: this.selfUserId,\n });\n this.peerDevices = new PeerDeviceCache({ http: this.http, selfDeviceId: this.deviceId });\n this.messages = new MessageStore(this.store);\n this.status = new StatusTracker();\n this.status.on((messageId, status, peerUserId) => {\n this.dispatch(\"statusChange\", { peerUserId, messageId, status });\n });\n\n this.typingMgr = new TypingManager((peerUserId, state) => {\n // Fire-and-forget; we don't await typing ephemeral fanout.\n this.sendContent(peerUserId, newTyping(state), { ephemeral: true }).catch(() => {});\n });\n\n // Connect WS to the discovered node URL. Strip a trailing /chat/ws\n // path if the discovery returned one — WsClient appends it.\n const nodeUrl = mint.chatNodeWsUrl.replace(/\\/chat\\/ws\\/?$/, \"\");\n this.ws = new WsClient({\n nodeBaseURL: nodeUrl,\n getToken: () => this.http.getToken(this.deviceId),\n onFrame: (f) => this.onFrame(f),\n onState: (s) => this.onWsState(s),\n });\n await this.ws.connect();\n\n // Drain any offline envelopes that landed while we were away.\n await this.drainPending();\n\n // Refill OTKs if the server-side count has dropped below the\n // watermark. Best-effort — failure here doesn't block bootstrap.\n void this.keyBundle.topUpIfNeeded().catch(() => {});\n\n // Pre-populate the session bundle cache for our OWN user so the\n // first self-echo from this device fanouts to all currently-\n // registered own devices. Without this, the first send-after-\n // boot would self-echo to nobody (cache miss → claim_all on\n // demand only happens at first send to selfUserId, which is\n // also the moment we'd need it).\n if (this.selfUserId) {\n void this.sessions.refreshPeerBundles(this.selfUserId).catch(() => {});\n }\n }\n\n /**\n * State-listener for the underlying WsClient. On every transition to\n * \"open\" (initial connect AND auto-reconnect), drain any queued\n * outbound sends and re-pull pending offline envelopes — closes the\n * gap during disconnect.\n */\n private onWsState(s: string): void {\n if (s !== \"open\") return;\n void this.outbox.tick();\n void this.drainPending().catch(() => {});\n // Reconnect-time topup catches the case where the device sat\n // offline long enough for many incoming sessions to deplete OTKs.\n void this.keyBundle.topUpIfNeeded().catch(() => {});\n }\n\n /** Set true while drainPending is running to avoid overlapping calls\n * (would otherwise hand the same envelope to two concurrent decrypt\n * invocations — Olm rejects the second). */\n private drainingPending = false;\n\n private async drainPending(): Promise<void> {\n if (this.drainingPending) return;\n this.drainingPending = true;\n try {\n while (true) {\n const r = await this.http.pending(this.deviceId, 100);\n if (r.envelopes.length === 0) return;\n const ackUuids: string[] = [];\n for (const env of r.envelopes) {\n try {\n await this.handleInboundCiphertext({\n peerUserId: env.senderUserId,\n peerDeviceId: env.senderDeviceId,\n ciphertext: env.ciphertext,\n msgType: env.msgType,\n });\n ackUuids.push(env.envelopeUuid);\n } catch {\n // decrypt failed — leave on the queue for now.\n }\n }\n if (ackUuids.length === 0) return;\n await this.http.ack(this.deviceId, ackUuids);\n }\n } finally {\n this.drainingPending = false;\n }\n }\n\n private async onFrame(frame: InboundFrame): Promise<void> {\n if (frame.kind === \"chatEnvelope\") {\n await this.handleInboundCiphertext({\n peerUserId: frame.senderUserId,\n peerDeviceId: frame.senderDeviceId,\n ciphertext: frame.ciphertext,\n msgType: frame.msgType,\n });\n return;\n }\n if (frame.kind === \"chatSendResult\") {\n for (const r of frame.results) {\n this.status.onSendResult(r.envelopeUuid, r.status);\n }\n return;\n }\n // chat_pong — ignore; ws.ts already handles ping liveness.\n }\n\n private async handleInboundCiphertext(opts: {\n peerUserId: string;\n peerDeviceId: string;\n ciphertext: string;\n msgType: \"prekey\" | \"normal\";\n }): Promise<void> {\n let plaintext: string;\n try {\n plaintext = await this.sessions.decrypt(\n opts.peerUserId,\n opts.peerDeviceId,\n opts.ciphertext,\n opts.msgType,\n );\n } catch (firstErr) {\n // On-decrypt-failure recovery: drop the broken session, refresh the\n // peer's device list (peer may have a new device whose fingerprint\n // doesn't match our cache), retry decrypt once. For msgType=prekey\n // the retry can succeed by bootstrapping a fresh inbound session;\n // for msgType=normal a forgotten session can't recover this message,\n // but the next inbound from peer arrives as prekey-type and rebuilds.\n await this.sessions.forgetPeerDevice(opts.peerUserId, opts.peerDeviceId);\n this.peerDevices.invalidate(opts.peerUserId);\n try {\n await this.peerDevices.refresh(opts.peerUserId);\n } catch {\n // refresh is best-effort; carry on with retry regardless\n }\n try {\n plaintext = await this.sessions.decrypt(\n opts.peerUserId,\n opts.peerDeviceId,\n opts.ciphertext,\n opts.msgType,\n );\n } catch {\n // Still broken — drop. Future messages from peer will re-bootstrap.\n throw firstErr;\n }\n }\n // Plan §17 prekey-discovery: if this peer device wasn't known to the\n // local cache before, refresh + emit peerNewDevice. Done after a\n // successful decrypt so we only learn about devices that produced\n // valid messages (not random spammers attempting random sessions).\n await this.maybeAnnouncePeerDevice(opts.peerUserId, opts.peerDeviceId);\n\n const event = decodeEventBytes(new TextEncoder().encode(plaintext));\n if (!event) return; // unknown / malformed: drop silently\n await this.dispatchInboundEvent(opts.peerUserId, opts.peerDeviceId, event);\n }\n\n /**\n * If `peerDeviceId` is not in our local cache for `peerUserId`, refresh\n * the peer's device list and emit `peerNewDevice` exactly once. Idempotent\n * across repeated calls — second message from the same new device is a\n * cheap cache hit. Failures (HTTP error fetching the device list) are\n * swallowed; we'll re-attempt on the next inbound from this device.\n */\n private async maybeAnnouncePeerDevice(peerUserId: string, peerDeviceId: string): Promise<void> {\n const flag = `${peerUserId}|${peerDeviceId}`;\n if (this.announcedNewDevices.has(flag)) return;\n\n let devices: Awaited<ReturnType<PeerDeviceCache[\"getPeerDevices\"]>>;\n try {\n devices = await this.peerDevices.getPeerDevices(peerUserId);\n } catch {\n return;\n }\n let entry = devices.find((d) => d.deviceId === peerDeviceId);\n if (!entry) {\n // Stale cache — peer added a device since the last refresh. Force one.\n let fresh: typeof devices;\n try {\n fresh = await this.peerDevices.refresh(peerUserId);\n } catch {\n return;\n }\n entry = fresh.find((d) => d.deviceId === peerDeviceId);\n if (!entry) return; // device truly unknown to backend; defensive\n }\n\n this.announcedNewDevices.add(flag);\n // The peerDevices cache now knows about the new device, but the\n // session-level bundleCache (used by encryptForPeer) was populated\n // before this device existed. Refresh it so the next outbound send\n // fanouts to the new device too. Best-effort — failures here are\n // swallowed and the user can recover by triggering a re-claim\n // through normal traffic.\n try {\n await this.sessions.refreshPeerBundles(peerUserId);\n } catch {\n // ignore\n }\n this.dispatch(\"peerNewDevice\", {\n peerUserId,\n peerDeviceId,\n fingerprint: entry.fingerprint,\n });\n }\n\n private async dispatchInboundEvent(\n peerUserId: string,\n peerDeviceId: string,\n event: ContentEvent,\n ): Promise<void> {\n switch (event.type) {\n case \"text\": {\n await this.messages.put({\n id: event.id,\n peerUserId,\n senderUserId: peerUserId,\n text: event.text,\n sentAt: event.clientSentAt,\n editedAt: null,\n deletedAt: null,\n ...(event.replyTo !== undefined ? { replyTo: event.replyTo } : {}),\n });\n this.dispatch(\"message\", {\n peerUserId,\n peerDeviceId,\n senderUserId: peerUserId,\n message: {\n id: event.id,\n text: event.text,\n sentAt: event.clientSentAt,\n ...(event.replyTo !== undefined ? { replyTo: event.replyTo } : {}),\n },\n });\n this.queueReceivedAck(peerUserId, peerDeviceId, event.id);\n return;\n }\n case \"edit\": {\n const updated = await this.messages.applyEdit({\n targetId: event.targetId,\n editorUserId: peerUserId,\n newText: event.text,\n editedAt: event.clientSentAt,\n });\n if (updated) {\n this.dispatch(\"messageEdited\", {\n peerUserId,\n editorUserId: peerUserId,\n targetId: event.targetId,\n newText: event.text,\n editedAt: event.clientSentAt,\n });\n }\n this.queueReceivedAck(peerUserId, peerDeviceId, event.id);\n return;\n }\n case \"delete\": {\n const updated = await this.messages.applyDelete({\n targetId: event.targetId,\n deleterUserId: peerUserId,\n deletedAt: event.clientSentAt,\n });\n if (updated) {\n this.dispatch(\"messageDeleted\", {\n peerUserId,\n deleterUserId: peerUserId,\n targetId: event.targetId,\n deletedAt: event.clientSentAt,\n });\n }\n this.queueReceivedAck(peerUserId, peerDeviceId, event.id);\n return;\n }\n case \"read\": {\n this.status.onRead({ peerUserId, upToId: event.upToId });\n this.dispatch(\"readReceipt\", { peerUserId, peerDeviceId, upToId: event.upToId });\n return;\n }\n case \"received\": {\n this.status.onReceived({ peerUserId, peerDeviceId, messageIds: event.ids });\n return;\n }\n case \"typing\": {\n this.dispatch(\"typing\", { peerUserId, peerDeviceId, state: event.state });\n return;\n }\n case \"selfEcho\": {\n // Multi-device self-echo. The Olm session binding guarantees the\n // outer ciphertext came from a session keyed under our own user;\n // sender authenticity is therefore cryptographic. Defensive check:\n // the wire layer routes by peerUserId, so an untrusted sender\n // can't fake peerUserId === selfUserId without first establishing\n // an Olm session under our user — which they can't do.\n if (peerUserId !== this.selfUserId) return;\n const inner = event.original;\n const originalPeer = event.originalPeer;\n switch (inner.type) {\n case \"text\": {\n await this.messages.put({\n id: inner.id,\n peerUserId: originalPeer,\n senderUserId: peerUserId,\n text: inner.text,\n sentAt: inner.clientSentAt,\n editedAt: null,\n deletedAt: null,\n ...(inner.replyTo !== undefined ? { replyTo: inner.replyTo } : {}),\n });\n this.dispatch(\"message\", {\n peerUserId: originalPeer,\n peerDeviceId,\n senderUserId: peerUserId,\n message: {\n id: inner.id,\n text: inner.text,\n sentAt: inner.clientSentAt,\n ...(inner.replyTo !== undefined ? { replyTo: inner.replyTo } : {}),\n },\n });\n return;\n }\n case \"edit\": {\n const updated = await this.messages.applyEdit({\n targetId: inner.targetId,\n editorUserId: peerUserId,\n newText: inner.text,\n editedAt: inner.clientSentAt,\n });\n if (updated) {\n this.dispatch(\"messageEdited\", {\n peerUserId: originalPeer,\n editorUserId: peerUserId,\n targetId: inner.targetId,\n newText: inner.text,\n editedAt: inner.clientSentAt,\n });\n }\n return;\n }\n case \"delete\": {\n const updated = await this.messages.applyDelete({\n targetId: inner.targetId,\n deleterUserId: peerUserId,\n deletedAt: inner.clientSentAt,\n });\n if (updated) {\n this.dispatch(\"messageDeleted\", {\n peerUserId: originalPeer,\n deleterUserId: peerUserId,\n targetId: inner.targetId,\n deletedAt: inner.clientSentAt,\n });\n }\n return;\n }\n case \"read\": {\n // Mirror the read watermark so this device's chat ratchets\n // statuses forward the same way the originating device did.\n this.status.onRead({ peerUserId: originalPeer, upToId: inner.upToId });\n return;\n }\n }\n return;\n }\n }\n }\n\n /**\n * Multi-device self-echo. Wraps the original event in a `selfEcho`\n * envelope and ships it to our own user (mesh fanout filters our\n * own device). Other devices belonging to the same user receive,\n * unwrap, and persist the event so their local history mirrors this\n * device's. No-op when:\n * - we don't yet know our own user id\n * - the original was addressed to ourselves (avoids loops)\n * - we have no other devices registered (encryptForPeer returns [])\n * Best-effort: failures here don't surface to the caller.\n */\n private async selfEcho(originalPeer: string, original: SelfEchoableEvent): Promise<void> {\n if (!this.selfUserId) return;\n if (originalPeer === this.selfUserId) return;\n const echo = newSelfEcho(originalPeer, original);\n try {\n // If the cached self-fanout would be empty (first send after\n // boot, or a sibling device just registered), force a refresh\n // before encrypting. In steady state the cache hits the size>0\n // branch and we skip the refresh.\n const cached = this.sessions.cachedFanoutSize(this.selfUserId);\n if (cached === null || cached === 0) {\n try {\n await this.sessions.refreshPeerBundles(this.selfUserId);\n } catch {\n return;\n }\n }\n await this.sendContent(this.selfUserId, echo, { ephemeral: false });\n } catch {\n // ignore — peer-side delivery already succeeded; sync convergence\n // gets a second chance on the next send.\n }\n }\n\n private async sendContent(\n peerUserId: string,\n event: ContentEvent,\n opts: { ephemeral: boolean },\n ): Promise<void> {\n const plainBytes = encodeEventBytes(event);\n const plaintext = new TextDecoder().decode(plainBytes);\n const encrypted = await this.sessions.encryptForPeer(peerUserId, plaintext);\n if (encrypted.length === 0) {\n // Peer has no devices (or has blocked us). Same shape as Signal's\n // \"this user can't be reached.\" If we have message history with\n // this peer, suspect a registry mismatch / backend wipe and trigger\n // a one-shot self-bundle reupload so future sends might recover.\n // Don't loop — bundleReuploadAttempted ensures one attempt per\n // SDK session, and we don't retry the failed encrypt.\n if (!opts.ephemeral && !this.bundleReuploadAttempted) {\n const seenBefore =\n (await this.messages.listForPeer(peerUserId, { limit: 1 })).length > 0;\n if (seenBefore) {\n this.bundleReuploadAttempted = true;\n try {\n await this.keyBundle.reuploadCurrentBundle();\n } catch {\n // best-effort — we'll see future failures via the same path\n }\n }\n }\n return;\n }\n const targets: ChatSendTarget[] = encrypted.map((e) => ({\n deviceId: e.peerDeviceId,\n ciphertext: e.ciphertext,\n envelopeUuid: globalThis.crypto.randomUUID(),\n }));\n\n // For non-typing/non-read events, register with the status tracker\n // so chatSendResult and inbound `received`/`read` can update status.\n if (event.type === \"text\" || event.type === \"edit\" || event.type === \"delete\") {\n const map = new Map<string, string>();\n for (const t of targets) map.set(t.envelopeUuid, t.deviceId);\n this.status.trackOutbound({ messageId: event.id, peerUserId, envelopeToDevice: map });\n }\n\n const msgType = encrypted[0].msgType; // shared across targets in this fanout\n const frame = {\n toUserId: peerUserId,\n ephemeral: opts.ephemeral || undefined,\n msgType,\n targets,\n } as const;\n\n if (opts.ephemeral) {\n // Typing & other ephemerals are fire-and-forget — if the WS isn't\n // open, drop silently. Retrying typing later would deliver a\n // confusing \"X is typing\" hours after the fact.\n if (this.ws.getState() === \"open\") {\n try {\n this.ws.sendChat(frame);\n } catch {\n // ignore\n }\n }\n return;\n }\n\n // Persistent events (text/edit/delete/read/received) go through the\n // outbox — if the WS is closed at send time, the entry queues and\n // drains on the next \"open\" transition. Idempotent on messageId; the\n // outbox keys by it.\n this.outbox.enqueue({\n messageId: event.id,\n peerUserId,\n ephemeral: false,\n attempt: async () => {\n const outcomes = new Map<string, \"live\" | \"stored\" | \"dropped\" | \"error\">();\n if (this.ws.getState() !== \"open\") {\n for (const t of targets) outcomes.set(t.envelopeUuid, \"error\");\n return outcomes;\n }\n try {\n this.ws.sendChat(frame);\n // Synthesize \"stored\" so the outbox treats this as a successful\n // attempt and removes the entry. The real per-target outcome\n // arrives separately as a chatSendResult frame (consumed by\n // StatusTracker). Outbox only cares \"did the send go out at all\".\n for (const t of targets) outcomes.set(t.envelopeUuid, \"stored\");\n } catch {\n for (const t of targets) outcomes.set(t.envelopeUuid, \"error\");\n }\n return outcomes;\n },\n });\n // Best-effort immediate attempt; if the WS is open we'll send right now,\n // otherwise the entry waits for the next \"open\" transition.\n void this.outbox.tick();\n\n void this.peerDevices; // reserved for on-decrypt-failure refresh path\n }\n\n private queueReceivedAck(peerUserId: string, peerDeviceId: string, eventId: string): void {\n const key = `${peerUserId}|${peerDeviceId}`;\n const list = this.pendingReceived.get(key) ?? [];\n list.push(eventId);\n this.pendingReceived.set(key, list);\n if (list.length >= RECEIVED_BATCH_FLUSH_SIZE) {\n this.flushReceivedBatch();\n return;\n }\n if (!this.receivedFlushTimer) {\n this.receivedFlushTimer = setTimeout(() => this.flushReceivedBatch(), RECEIVED_BATCH_FLUSH_MS);\n }\n }\n\n private flushReceivedBatch(): void {\n if (this.receivedFlushTimer) {\n clearTimeout(this.receivedFlushTimer);\n this.receivedFlushTimer = null;\n }\n if (this.pendingReceived.size === 0) return;\n for (const [key, ids] of this.pendingReceived.entries()) {\n const [peerUserId] = key.split(\"|\");\n this.sendContent(peerUserId, newReceived(ids), { ephemeral: false }).catch(() => {});\n }\n this.pendingReceived.clear();\n }\n\n private dispatch<T extends EventName>(name: T, event: EventMap[T]): void {\n const set = this.listeners.get(name);\n if (!set) return;\n for (const fn of set) {\n try {\n (fn as Listener<T>)(event);\n } catch {\n // listener errors must not break the SDK\n }\n }\n }\n}\n\n// ── helpers ─────────────────────────────────────────────────────────────────\n\nfunction parseSubFromJwt(jwt: string): string | null {\n try {\n const parts = jwt.split(\".\");\n if (parts.length !== 3) return null;\n const padLen = (4 - (parts[1].length % 4)) % 4;\n const padded = parts[1] + \"=\".repeat(padLen);\n const std = padded.replace(/-/g, \"+\").replace(/_/g, \"/\");\n const decoded = atob(std);\n const claims = JSON.parse(decoded) as { sub?: string };\n return claims.sub ?? null;\n } catch {\n return null;\n }\n}\n\n// ── re-exports for advanced consumers ───────────────────────────────────────\n\nexport type { CryptoAdapter } from \"./crypto/interface.js\";\nexport { OlmCryptoAdapter } from \"./crypto/olm-adapter.js\";\nexport { FakeCryptoAdapter } from \"./crypto/fake-adapter.js\";\nexport { MemoryKVStore } from \"./store/memory-adapter.js\";\nexport { WebKVStore } from \"./store/web-adapter.js\";\nexport type { KVStore } from \"./store/interface.js\";\nexport type { StoredMessage };\nexport type { MessageStatus } from \"./status.js\";\n"]}