surf-cli 2.6.0 → 2.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -1
- package/dist/content/accessibility-tree.js +8 -8
- package/dist/content/accessibility-tree.js.map +1 -1
- package/dist/content/visual-indicator.js +17 -17
- package/dist/content/visual-indicator.js.map +1 -1
- package/dist/manifest.json +1 -1
- package/dist/service-worker/index.js +27 -27
- package/dist/service-worker/index.js.map +1 -1
- package/native/cli.cjs +12 -0
- package/native/gemini-client.cjs +304 -63
- package/native/host.cjs +51 -0
- package/package.json +8 -8
- package/skills/README.md +2 -2
- package/skills/surf/SKILL.md +40 -10
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"mappings":"sxCA8EMA,EAAY,CAChB,IAAK,EACL,KAAM,EACN,QAAS,EACT,KAAM,EACN,IAAK,EACL,QAAS,EACT,IAAK,EACL,QAAS,EACT,MAAO,CACT,EAUMC,GAAiD,CACrD,MAAO,CAAE,IAAK,QAAS,KAAM,QAAS,QAAS,GAAI,KAAM,MACzD,IAAK,CAAE,IAAK,MAAO,KAAM,MAAO,QAAS,GACzC,OAAQ,CAAE,IAAK,SAAU,KAAM,SAAU,QAAS,IAClD,UAAW,CAAE,IAAK,YAAa,KAAM,YAAa,QAAS,GAC3D,OAAQ,CAAE,IAAK,SAAU,KAAM,SAAU,QAAS,IAClD,QAAS,CAAE,IAAK,UAAW,KAAM,UAAW,QAAS,IACrD,UAAW,CAAE,IAAK,YAAa,KAAM,YAAa,QAAS,IAC3D,UAAW,CAAE,IAAK,YAAa,KAAM,YAAa,QAAS,IAC3D,WAAY,CAAE,IAAK,aAAc,KAAM,aAAc,QAAS,IAC9D,KAAM,CAAE,IAAK,OAAQ,KAAM,OAAQ,QAAS,IAC5C,IAAK,CAAE,IAAK,MAAO,KAAM,MAAO,QAAS,IACzC,OAAQ,CAAE,IAAK,SAAU,KAAM,SAAU,QAAS,IAClD,SAAU,CAAE,IAAK,WAAY,KAAM,WAAY,QAAS,IACxD,MAAO,CAAE,IAAK,IAAK,KAAM,QAAS,QAAS,GAAI,KAAM,KACrD,GAAI,CAAE,IAAK,KAAM,KAAM,KAAM,QAAS,KACtC,GAAI,CAAE,IAAK,KAAM,KAAM,KAAM,QAAS,KACtC,GAAI,CAAE,IAAK,KAAM,KAAM,KAAM,QAAS,KACtC,GAAI,CAAE,IAAK,KAAM,KAAM,KAAM,QAAS,KACtC,GAAI,CAAE,IAAK,KAAM,KAAM,KAAM,QAAS,KACtC,GAAI,CAAE,IAAK,KAAM,KAAM,KAAM,QAAS,KACtC,GAAI,CAAE,IAAK,KAAM,KAAM,KAAM,QAAS,KACtC,GAAI,CAAE,IAAK,KAAM,KAAM,KAAM,QAAS,KACtC,GAAI,CAAE,IAAK,KAAM,KAAM,KAAM,QAAS,KACtC,IAAK,CAAE,IAAK,MAAO,KAAM,MAAO,QAAS,KACzC,IAAK,CAAE,IAAK,MAAO,KAAM,MAAO,QAAS,KACzC,IAAK,CAAE,IAAK,MAAO,KAAM,MAAO,QAAS,IAC3C,EAEaC,EAAN,MAAMA,CAAc,CAApB,cACGC,EAAA,mBAAc,KACdA,EAAA,2BAAqD,KACrDA,EAAA,2BAAqD,KACrDA,EAAA,0BAA6D,KAC7DA,EAAA,4BAAuE,KACvEA,EAAA,4BAAuE,KACvEA,EAAA,oCAAoD,KACpDA,EAAA,0BAAiD,KACjDA,EAAA,uBAAkB,GAkB1B,MAAM,OAAOC,EAA8B,CACzC,GAAI,KAAK,QAAQ,IAAIA,CAAK,EAAG,OAE7B,MAAMC,EAAmB,CAAE,MAAAD,CAAA,EAC3B,GAAI,CACF,MAAM,OAAO,SAAS,OAAOC,EAAQ,KAAK,CAC5C,OAASC,EAAK,CACZ,MAAMC,EAAUD,aAAe,MAAQA,EAAI,QAAU,OAAOA,CAAG,EAC/D,MAAIC,EAAQ,SAAS,eAAe,GAAKA,EAAQ,SAAS,eAAe,EACjE,IAAI,MAAM,sGAAsG,EAElH,IAAI,MAAM,8BAA8BA,CAAO,EAAE,CACzD,CACA,KAAK,QAAQ,IAAIH,EAAOC,CAAM,EAE9B,KAAK,qBACL,KAAK,gBAAgB,IAAID,EAAO,EAAE,EAClC,KAAK,gBAAgB,IAAIA,EAAO,EAAE,EAElC,GAAI,CACF,MAAM,KAAK,KAAKA,EAAO,aAAa,CACtC,MAAY,CAAC,CACf,CAEA,MAAM,OAAOA,EAA8B,CACzC,MAAMC,EAAS,KAAK,QAAQ,IAAID,CAAK,EACrC,GAAIC,EAAQ,CACV,GAAI,CACF,MAAM,OAAO,SAAS,OAAOA,CAAM,CACrC,OAASG,EAAG,CACV,QAAQ,KAAK,mCAAoCA,CAAC,CACpD,CACA,KAAK,QAAQ,OAAOJ,CAAK,EACzB,KAAK,gBAAgB,OAAOA,CAAK,EACjC,KAAK,gBAAgB,OAAOA,CAAK,EACjC,KAAK,eAAe,OAAOA,CAAK,EAChC,KAAK,iBAAiB,OAAOA,CAAK,EAClC,KAAK,iBAAiB,OAAOA,CAAK,EAClC,KAAK,eAAe,OAAOA,CAAK,CAClC,CACF,CAEA,MAAM,WAA2B,CAC/B,UAAWA,KAAS,KAAK,QAAQ,OAC/B,MAAM,KAAK,OAAOA,CAAK,CAE3B,CAEQ,oBAA2B,CAC7BF,EAAc,6BAClBA,EAAc,2BAA6B,GAE3C,OAAO,SAAS,QAAQ,YAAY,CAACO,EAAQC,EAAQC,IAAW,CAC9D,MAAMP,EAAQK,EAAO,MACjB,CAACL,GAAS,CAAC,KAAK,QAAQ,IAAIA,CAAK,GAErC,KAAK,eAAeA,EAAOM,EAAQC,CAAM,CAC3C,CAAC,EAED,OAAO,SAAS,SAAS,YAAY,CAACF,EAAQG,IAAW,CACvD,MAAMR,EAAQK,EAAO,MACjBL,GAAS,KAAK,QAAQ,IAAIA,CAAK,IACjC,KAAK,QAAQ,OAAOA,CAAK,EACzB,KAAK,gBAAgB,OAAOA,CAAK,EACjC,KAAK,gBAAgB,OAAOA,CAAK,EACjC,KAAK,eAAe,OAAOA,CAAK,EAChC,KAAK,iBAAiB,OAAOA,CAAK,EAClC,KAAK,iBAAiB,OAAOA,CAAK,EAEtC,CAAC,EACH,CAEQ,eAAeA,EAAeM,EAAgBC,EAAmB,CACvE,OAAQD,EAAA,CACN,IAAK,2BACH,KAAK,qBAAqBN,EAAOO,CAAM,EACvC,MACF,IAAK,0BACH,KAAK,uBAAuBP,EAAOO,CAAM,EACzC,MACF,IAAK,4BACH,KAAK,qBAAqBP,EAAOO,CAAM,EACvC,MACF,IAAK,2BACH,KAAK,sBAAsBP,EAAOO,CAAM,EACxC,MACF,IAAK,wBACH,KAAK,oBAAoBP,EAAOO,CAAM,EACtC,MACF,IAAK,0BACH,KAAK,sBAAsBP,EAAOO,CAAM,EACxC,MACF,IAAK,+BACH,KAAK,oBAAoBP,EAAOO,CAAM,EACtC,MACF,IAAK,8BACH,KAAK,eAAe,OAAOP,CAAK,EAChC,MAEN,CAEQ,qBAAqBA,EAAeO,EAAmB,SAC7D,MAAME,EAAW,KAAK,gBAAgB,IAAIT,CAAK,GAAK,GAG9CU,GAFOH,EAAO,MAAQ,IAGzB,IAAKI,GACAA,EAAE,QAAU,OAAkB,OAAOA,EAAE,KAAK,EAC5CA,EAAE,YAAoBA,EAAE,YACrB,EACR,EACA,KAAK,GAAG,EAELC,GAAYC,GAAAC,EAAAP,EAAO,aAAP,YAAAO,EAAmB,aAAnB,YAAAD,EAAgC,GAE5CE,EAAsB,CAC1B,KAAMR,EAAO,MAAQ,MACrB,KAAAG,EACA,UAAWH,EAAO,WAAa,KAAK,MACpC,IAAKK,GAAA,YAAAA,EAAW,IAChB,KAAMA,GAAA,YAAAA,EAAW,YAGnBH,EAAS,KAAKM,CAAG,EACbN,EAAS,OAAS,KAAMA,EAAS,QACrC,KAAK,gBAAgB,IAAIT,EAAOS,CAAQ,EAExC,MAAMO,EAAY,KAAK,iBAAiB,IAAIhB,CAAK,EACjD,GAAIgB,EACF,UAAWC,KAAMD,EAAU,SACzBC,EAAGF,CAAG,CAGZ,CAEQ,uBAAuBf,EAAeO,EAAmB,OAC/D,MAAME,EAAW,KAAK,gBAAgB,IAAIT,CAAK,GAAK,GAC9CkB,EAAUX,EAAO,iBACvB,GAAI,CAACW,EAAS,OAEd,MAAMH,EAAsB,CAC1B,KAAM,YACN,OAAMD,EAAAI,EAAQ,YAAR,YAAAJ,EAAmB,cAAeI,EAAQ,MAAQ,oBACxD,UAAWA,EAAQ,WAAa,KAAK,MACrC,IAAKA,EAAQ,IACb,KAAMA,EAAQ,YAGhBT,EAAS,KAAKM,CAAG,EACbN,EAAS,OAAS,KAAMA,EAAS,QACrC,KAAK,gBAAgB,IAAIT,EAAOS,CAAQ,EAExC,MAAMO,EAAY,KAAK,iBAAiB,IAAIhB,CAAK,EACjD,GAAIgB,EACF,UAAWC,KAAMD,EAAU,SACzBC,EAAGF,CAAG,CAGZ,CAEQ,qBAAqBf,EAAeO,EAAmB,CAC7D,MAAMY,EAAW,KAAK,gBAAgB,IAAInB,CAAK,GAAK,GAC9CoB,EAAMb,EAAO,QACnB,GAAI,CAACa,EAAK,OAEV,MAAMC,EAAYd,EAAO,UAAYA,EAAO,UAAY,IAAO,KAAK,MACpE,KAAK,yBAAyB,IAAIA,EAAO,UAAWc,CAAS,EAG7D,MAAMC,EAAqC,GAC3C,GAAIF,EAAI,QACN,SAAW,CAACG,EAAKC,CAAK,IAAK,OAAO,QAAQJ,EAAI,OAAO,EACnDE,EAAWC,CAAG,EAAI,OAAOC,CAAK,EAIlCL,EAAS,KAAK,CACZ,UAAWZ,EAAO,UAClB,IAAKa,EAAI,IACT,OAAQA,EAAI,OACZ,KAAMb,EAAO,KACb,UAAAc,EACA,eAAgBC,EAChB,YAAaF,EAAI,SAClB,EAEGD,EAAS,OAAS,KAAKA,EAAS,QACpC,KAAK,gBAAgB,IAAInB,EAAOmB,CAAQ,EAGnC,KAAK,eAAe,IAAInB,CAAK,GAChC,KAAK,eAAe,IAAIA,EAAO,IAAI,GAAK,EAE1C,MAAMyB,EAAa,KAAK,eAAe,IAAIzB,CAAK,EAG1C0B,EAAM,EAAE,KAAK,gBACbC,EAAU,KAAKN,CAAS,IAAIK,CAAG,GAG/BE,EAAyC,GAC/C,GAAIR,EAAI,QACN,SAAW,CAACG,EAAKC,CAAK,IAAK,OAAO,QAAQJ,EAAI,OAAO,EACnDQ,EAAeL,CAAG,EAAI,OAAOC,CAAK,EAKtC,MAAMK,EAAcT,EAAI,SAClBU,EAAkBD,EAAcA,EAAY,OAAS,OAErDE,EAAsB,CAC1B,GAAIJ,EACJ,GAAIN,EACJ,OAAQD,EAAI,OACZ,IAAKA,EAAI,IACT,OAAQ,KAAK,cAAcA,EAAI,GAAG,EAClC,eAAAQ,EACA,YAAAC,EACA,gBAAAC,EACA,MAAA9B,EACA,OAAQO,EAAO,YACf,KAAMA,EAAO,KACb,MAAO,GACP,WAAYA,EAAO,UACnB,kBAAmB,GACnB,iBAAkB,IAIpB,GAAIkB,EAAW,KAAO,IAAK,CACzB,MAAMO,EAAYP,EAAW,OAAO,OAAO,MACvCO,GAAWP,EAAW,OAAOO,CAAS,CAC5C,CAEAP,EAAW,IAAIlB,EAAO,UAAWwB,CAAK,CACxC,CAEQ,sBAAsB/B,EAAeO,EAAmB,iBAE9D,MAAM0B,GADW,KAAK,gBAAgB,IAAIjC,CAAK,GAAK,IAC1B,KAAMkC,GAAMA,EAAE,YAAc3B,EAAO,SAAS,EACtE,GAAI0B,EAAU,CAKZ,GAJAA,EAAS,QAASnB,EAAAP,EAAO,WAAP,YAAAO,EAAiB,OACnCmB,EAAS,UAAWpB,EAAAN,EAAO,WAAP,YAAAM,EAAiB,UAGjCsB,EAAA5B,EAAO,WAAP,MAAA4B,EAAiB,QAAS,CAC5B,MAAMC,EAAsC,GAC5C,SAAW,CAACb,EAAKC,CAAK,IAAK,OAAO,QAAQjB,EAAO,SAAS,OAAO,EAC/D6B,EAAYb,CAAG,EAAI,OAAOC,CAAK,EAEjCS,EAAS,gBAAkBG,CAC7B,CAEA,MAAMpB,EAAY,KAAK,iBAAiB,IAAIhB,CAAK,EACjD,GAAIgB,EAAW,CACb,MAAMqB,EAAY,KAAK,yBAAyB,IAAI9B,EAAO,SAAS,EAC9D+B,EAAM,KAAK,MACXC,EAAWF,EAAY,KAAK,MAAMC,EAAMD,CAAS,EAAI,OAI3D,UAAWpB,KAAMD,EAAU,SACzBC,EAAG,CACD,OAAQgB,EAAS,OACjB,IAAKA,EAAS,IACd,OAAQA,EAAS,OACjB,SAAAM,EACA,UAAWD,CAAA,CACZ,CAEL,CACF,CAGA,MAAMb,EAAa,KAAK,eAAe,IAAIzB,CAAK,EAC1C+B,EAAQN,GAAA,YAAAA,EAAY,IAAIlB,EAAO,WACrC,GAAIwB,GAASxB,EAAO,SAAU,CAC5B,MAAMiC,EAAWjC,EAAO,SAGlB8B,EAAY,KAAK,yBAAyB,IAAI9B,EAAO,SAAS,EAC9D+B,EAAM/B,EAAO,UAAYA,EAAO,UAAY,IAAO,KAAK,MAC1D8B,IACFN,EAAM,KAAO,KAAK,MAAMO,EAAMD,CAAS,GAGzCN,EAAM,OAASS,EAAS,OACxBT,EAAM,WAAaS,EAAS,WAC5BT,EAAM,SAAWS,EAAS,SAG1B,MAAMC,EAA0C,GAChD,GAAID,EAAS,QACX,SAAW,CAACjB,EAAKC,CAAK,IAAK,OAAO,QAAQgB,EAAS,OAAO,EACxDC,EAAgBlB,CAAG,EAAI,OAAOC,CAAK,EAGvCO,EAAM,gBAAkBU,EAGpB,KAAK,aAAaD,EAAS,QAAQ,GACrCT,EAAM,MAAM,KAAK,QAAQ,IAIvBW,EAAAF,EAAS,WAAT,MAAAE,EAAmB,SAAS,cAC5BC,EAAAH,EAAS,WAAT,MAAAG,EAAmB,SAAS,gBAC5BC,EAAAJ,EAAS,WAAT,MAAAI,EAAmB,SAAS,sBAC9Bb,EAAM,MAAM,KAAK,UAAU,EAG7BA,EAAM,kBAAoB,EAC5B,CACF,CAEQ,oBAAoB/B,EAAeO,EAAmB,CAE5D,MAAM0B,GADW,KAAK,gBAAgB,IAAIjC,CAAK,GAAK,IAC1B,KAAMkC,GAAMA,EAAE,YAAc3B,EAAO,SAAS,EACtE,GAAI0B,GAAY,CAACA,EAAS,OAAQ,CAChCA,EAAS,OAAS,EAElB,MAAMjB,EAAY,KAAK,iBAAiB,IAAIhB,CAAK,EACjD,GAAIgB,EAAW,CACb,MAAMqB,EAAY,KAAK,yBAAyB,IAAI9B,EAAO,SAAS,EAC9D+B,EAAM,KAAK,MACXC,EAAWF,EAAY,KAAK,MAAMC,EAAMD,CAAS,EAAI,OAC3D,KAAK,yBAAyB,OAAO9B,EAAO,SAAS,EAErD,UAAWU,KAAMD,EAAU,SACzBC,EAAG,CACD,OAAQgB,EAAS,OACjB,IAAKA,EAAS,IACd,OAAQ,EACR,SAAAM,EACA,UAAWD,CAAA,CACZ,CAEL,CACF,CAGA,MAAMb,EAAa,KAAK,eAAe,IAAIzB,CAAK,EAC1C+B,EAAQN,GAAA,YAAAA,EAAY,IAAIlB,EAAO,WACrC,GAAIwB,EAAO,CACT,MAAMM,EAAY,KAAK,yBAAyB,IAAI9B,EAAO,SAAS,EAC9D+B,EAAM/B,EAAO,UAAYA,EAAO,UAAY,IAAO,KAAK,MAC1D8B,IACFN,EAAM,SAAW,KAAK,MAAMO,EAAMD,CAAS,GAE7C,KAAK,yBAAyB,OAAO9B,EAAO,SAAS,EAErDwB,EAAM,OAAS,EACfA,EAAM,MAAM,KAAK,QAAQ,EACzBA,EAAM,iBAAmB,EAC3B,CACF,CAEQ,oBAAoB/B,EAAeO,EAAmB,CAC5D,KAAK,eAAe,IAAIP,EAAO,CAC7B,KAAMO,EAAO,KACb,QAASA,EAAO,QAChB,cAAeA,EAAO,cACtB,UAAW,KAAK,KAAI,CACrB,CACH,CAEA,MAAc,sBAAsBP,EAAeO,EAA4B,CAG7E,MAAM0B,GADW,KAAK,gBAAgB,IAAIjC,CAAK,GAAK,IAC1B,KAAMkC,GAAMA,EAAE,YAAc3B,EAAO,SAAS,EACtE,GAAI0B,EAAU,CAEZ,MAAMI,EAAY,KAAK,yBAAyB,IAAI9B,EAAO,SAAS,EAC9D+B,EAAM/B,EAAO,UAAYA,EAAO,UAAY,IAAO,KAAK,MAW9D,GAVI8B,IACFJ,EAAS,SAAW,KAAK,MAAMK,EAAMD,CAAS,GAK9C,CAAC,KAAK,cAAcJ,EAAS,QAAQ,GACrC,CAAC,KAAK,aAAaA,EAAS,QAAQ,IACnC1B,EAAO,mBAAqB,IAAMT,EAAc,qBAGjD,GAAI,CACF,MAAM+C,EAAS,MAAM,KAAK,KAAK7C,EAAO,0BAA2B,CAC/D,UAAWO,EAAO,UACnB,EAED,GAAIsC,EAAO,cACT,GAAI,CACFZ,EAAS,aAAe,KAAKY,EAAO,IAAI,CAC1C,MAAQ,CACNZ,EAAS,aAAeY,EAAO,IACjC,MAEAZ,EAAS,aAAeY,EAAO,KAI7BZ,EAAS,cAAgBA,EAAS,aAAa,OAASnC,EAAc,uBACxEmC,EAAS,aAAeA,EAAS,aAAa,MAAM,EAAGnC,EAAc,oBAAoB,EAE7F,MAAY,CAEZ,CAEJ,CAGA,MAAM2B,EAAa,KAAK,eAAe,IAAIzB,CAAK,EAC1C+B,EAAQN,GAAA,YAAAA,EAAY,IAAIlB,EAAO,WACrC,GAAI,CAACwB,EAAO,OAGZ,MAAMM,EAAY,KAAK,yBAAyB,IAAI9B,EAAO,SAAS,EAC9D+B,EAAM/B,EAAO,UAAYA,EAAO,UAAY,IAAO,KAAK,MAgB9D,GAfI8B,IACFN,EAAM,SAAW,KAAK,MAAMO,EAAMD,CAAS,GAE7C,KAAK,yBAAyB,OAAO9B,EAAO,SAAS,EAGrDwB,EAAM,iBAAmBxB,EAAO,kBAChCwB,EAAM,iBAAmB,GAIvB,CAAC,KAAK,cAAcA,EAAM,QAAQ,GAClC,CAAC,KAAK,aAAaA,EAAM,QAAQ,IAChCxB,EAAO,mBAAqB,IAAMT,EAAc,qBAGjD,GAAI,CACF,MAAM+C,EAAS,MAAM,KAAK,KAAK7C,EAAO,0BAA2B,CAC/D,UAAWO,EAAO,UACnB,EAED,GAAIsC,EAAO,cAET,GAAI,CACFd,EAAM,aAAe,KAAKc,EAAO,IAAI,CACvC,MAAQ,CACNd,EAAM,aAAec,EAAO,KAC5Bd,EAAM,MAAM,KAAK,QAAQ,CAC3B,MAEAA,EAAM,aAAec,EAAO,KAI1Bd,EAAM,cAAgBA,EAAM,aAAa,OAASjC,EAAc,uBAClEiC,EAAM,aAAeA,EAAM,aAAa,MAAM,EAAGjC,EAAc,oBAAoB,EACnFiC,EAAM,MAAM,KAAK,WAAW,EAEhC,MAAY,CAGZ,CAEJ,CAGQ,cAAce,EAAqB,CACzC,GAAI,CAEF,OADe,IAAI,IAAIA,CAAG,EACZ,MAChB,MAAQ,CACN,MAAO,EACT,CACF,CAGQ,cAAcC,EAA4B,CAChD,OAAKA,EACEjD,EAAc,mBAAmB,IAAIiD,CAAQ,EAD9B,EAExB,CAGQ,aAAaA,EAA4B,CAC/C,OAAKA,EACEjD,EAAc,aAAa,IAAIiD,CAAQ,EADxB,EAExB,CAEA,MAAM,sBAAsB/C,EAA8B,CACxD,MAAM,KAAK,eAAeA,CAAK,EAC/B,GAAI,CACF,MAAM,KAAK,KAAKA,EAAO,gBAAgB,CACzC,MAAY,CAAC,CACf,CAEA,MAAM,sBAAsBA,EAA8B,CACxD,MAAM,KAAK,eAAeA,CAAK,EAC/B,GAAI,CACF,MAAM,KAAK,KAAKA,EAAO,iBAAkB,CAAE,gBAAiB,MAAO,CACrE,MAAY,CAAC,CACf,CAEA,MAAM,aAAaA,EAAegD,EAAiBC,EAAoE,CACrH,GAAI,CACF,aAAM,KAAK,KAAKjD,EAAO,8BAA+B,CACpD,OAAAgD,EACA,WAAAC,CAAA,CACD,EACD,KAAK,eAAe,OAAOjD,CAAK,EACzB,CAAE,QAAS,GACpB,OAASI,EAAG,CACV,MAAO,CAAE,QAAS,GAAO,MAAOA,aAAa,MAAQA,EAAE,QAAU,OAAOA,CAAC,EAC3E,CACF,CAEA,cAAcJ,EAAqC,CACjD,OAAO,KAAK,eAAe,IAAIA,CAAK,GAAK,IAC3C,CAEA,MAAM,eAAeA,EAAekD,EAA+D,CACjG,MAAM,KAAK,eAAelD,CAAK,EAC/B,MAAMmD,EAAuH,CAC3H,QAAW,CAAE,QAAS,GAAM,QAAS,EAAG,mBAAoB,EAAG,iBAAkB,GACjF,UAAW,CAAE,QAAS,GAAO,QAAS,IAAM,mBAAoB,IAAO,iBAAkB,KACzF,UAAW,CAAE,QAAS,GAAO,QAAS,MAAO,mBAAoB,KAAQ,iBAAkB,OAC3F,KAAM,CAAE,QAAS,GAAO,QAAS,IAAK,mBAAoB,IAAS,iBAAkB,KACrF,MAAS,CAAE,QAAS,GAAO,QAAS,EAAG,mBAAoB,GAAI,iBAAkB,GAAG,EAEhFC,EAASD,EAAQD,EAAO,cAAc,QAAQ,OAAQ,GAAG,CAAC,EAChE,GAAI,CAACE,EACH,MAAO,CAAE,QAAS,GAAO,MAAO,mBAAmBF,CAAM,gBAAgB,OAAO,KAAKC,CAAO,EAAE,KAAK,IAAI,CAAC,IAE1G,GAAI,CACF,aAAM,KAAK,KAAKnD,EAAO,gBAAgB,EACvC,MAAM,KAAK,KAAKA,EAAO,mCAAoCoD,CAAM,EAC1D,CAAE,QAAS,GACpB,OAAShD,EAAG,CACV,MAAO,CAAE,QAAS,GAAO,MAAOA,aAAa,MAAQA,EAAE,QAAU,OAAOA,CAAC,EAC3E,CACF,CAEA,MAAM,WAAWJ,EAAeqD,EAA6D,CAE3F,GADA,MAAM,KAAK,eAAerD,CAAK,EAC3BqD,EAAO,EACT,MAAO,CAAE,QAAS,GAAO,MAAO,qEAElC,GAAI,CACF,aAAM,KAAK,KAAKrD,EAAO,iCAAkC,CAAE,KAAAqD,EAAM,EAC1D,CAAE,QAAS,GACpB,OAASjD,EAAG,CACV,MAAO,CAAE,QAAS,GAAO,MAAOA,aAAa,MAAQA,EAAE,QAAU,OAAOA,CAAC,EAC3E,CACF,CAEA,MAAM,mBAAmBJ,EAAesD,EAAkBC,EAAmBC,EAAkE,CAC7I,MAAM,KAAK,eAAexD,CAAK,EAC/B,GAAI,CACF,aAAM,KAAK,KAAKA,EAAO,mCAAoC,CACzD,SAAAsD,EACA,UAAAC,EACA,SAAUC,GAAY,IACvB,EACM,CAAE,QAAS,GACpB,OAASpD,EAAG,CACV,MAAO,CAAE,QAAS,GAAO,MAAOA,aAAa,MAAQA,EAAE,QAAU,OAAOA,CAAC,EAC3E,CACF,CAEA,MAAM,iBAAiBJ,EAA8D,CACnF,MAAM,KAAK,eAAeA,CAAK,EAC/B,GAAI,CACF,aAAM,KAAK,KAAKA,EAAO,oCAAoC,EACpD,CAAE,QAAS,GACpB,OAAS,EAAG,CACV,MAAO,CAAE,QAAS,GAAO,MAAO,aAAa,MAAQ,EAAE,QAAU,OAAO,CAAC,EAC3E,CACF,CAEA,MAAM,cACJA,EACAyD,EAC+C,CAC/C,MAAM,KAAK,eAAezD,CAAK,EAC/B,GAAI,CAEF,aAAM,KAAK,KAAKA,EAAO,qCAAsC,CAC3D,MAAOyD,EAAO,MACd,OAAQA,EAAO,OACf,kBAAmBA,EAAO,kBAC1B,OAAQA,EAAO,OAChB,EAGGA,EAAO,WACT,MAAM,KAAK,KAAKzD,EAAO,iCAAkC,CACvD,UAAWyD,EAAO,UACnB,EAICA,EAAO,OACT,MAAM,KAAK,KAAKzD,EAAO,qCAAsC,CAC3D,QAAS,GACT,eAAgB,EACjB,EAGI,CAAE,QAAS,GACpB,OAASI,EAAG,CACV,MAAO,CAAE,QAAS,GAAO,MAAOA,aAAa,MAAQA,EAAE,QAAU,OAAOA,CAAC,EAC3E,CACF,CAEA,MAAM,qBAAqBJ,EAA8D,CACvF,MAAM,KAAK,eAAeA,CAAK,EAC/B,GAAI,CACF,aAAM,KAAK,KAAKA,EAAO,sCAAsC,EAC7D,MAAM,KAAK,KAAKA,EAAO,iCAAkC,CAAE,UAAW,GAAI,EAC1E,MAAM,KAAK,KAAKA,EAAO,qCAAsC,CAAE,QAAS,GAAO,EACxE,CAAE,QAAS,GACpB,OAAS,EAAG,CACV,MAAO,CAAE,QAAS,GAAO,MAAO,aAAa,MAAQ,EAAE,QAAU,OAAO,CAAC,EAC3E,CACF,CAEA,MAAM,gBACJA,EACA0D,EAC+C,CAC/C,MAAM,KAAK,eAAe1D,CAAK,EAC/B,GAAI,CAEF,MAAM2D,EAAW,MAAM,KAAK,gBAAgB3D,CAAK,EAEjD,aAAM,KAAK,KAAKA,EAAO,qCAAsC,CAC3D,MAAO0D,EAAQ,OAASC,EAAS,MACjC,OAAQD,EAAQ,QAAUC,EAAS,OACnC,kBAAmBD,EAAQ,mBAAqB,EAChD,OAAQA,EAAQ,QAAU,GAC3B,EAEM,CAAE,QAAS,GACpB,OAAStD,EAAG,CACV,MAAO,CAAE,QAAS,GAAO,MAAOA,aAAa,MAAQA,EAAE,QAAU,OAAOA,CAAC,EAC3E,CACF,CAEA,MAAM,aAAaJ,EAAe4D,EAAiE,CACjG,MAAM,KAAK,eAAe5D,CAAK,EAC/B,GAAI,CACF,aAAM,KAAK,KAAKA,EAAO,qCAAsC,CAC3D,QAAA4D,EACA,eAAgBA,EAAU,EAAI,EAC/B,EACM,CAAE,QAAS,GACpB,OAASxD,EAAG,CACV,MAAO,CAAE,QAAS,GAAO,MAAOA,aAAa,MAAQA,EAAE,QAAU,OAAOA,CAAC,EAC3E,CACF,CAEA,MAAM,sBAAsBJ,EAAe6D,EAAsE,CAC/G,MAAM,KAAK,eAAe7D,CAAK,EAC/B,GAAI,CACF,aAAM,KAAK,KAAKA,EAAO,oBAAoB,EAC3C,MAAM,KAAK,KAAKA,EAAO,gBAAiB,CACtC,YAAY6D,GAAA,YAAAA,EAAY,KAAK,OAAQ,qEACrC,aAAc,iBACf,EACM,CAAE,QAAS,GACpB,OAASzD,EAAG,CACV,MAAO,CAAE,QAAS,GAAO,MAAOA,aAAa,MAAQA,EAAE,QAAU,OAAOA,CAAC,EAC3E,CACF,CAEA,MAAM,qBAAqBJ,EAA6E,CACtG,MAAM,KAAK,eAAeA,CAAK,EAC/B,GAAI,CACF,MAAM,KAAK,KAAKA,EAAO,oBAAoB,EAC3C,MAAM8D,EAAgB,MAAM,KAAK,KAAK9D,EAAO,wBAAwB,EACrE,MAAM,KAAK,KAAKA,EAAO,aAAa,EACpC,MAAM,KAAK,KAAKA,EAAO,qBAAqB,EAC5C,MAAM+D,EAAkC,GACxC,UAAWC,KAAKF,EAAc,SAAW,GACvCC,EAAQC,EAAE,IAAI,EAAIA,EAAE,MAEtB,MAAO,CAAE,QAAS,GAAM,QAAAD,CAAA,CAC1B,OAAS,EAAG,CACV,MAAO,CAAE,QAAS,GAAO,MAAO,aAAa,MAAQ,EAAE,QAAU,OAAO,CAAC,EAC3E,CACF,CAEA,MAAM,sBAAsB/D,EAAgG,CAC1H,MAAM,KAAK,eAAeA,CAAK,EAC/B,GAAI,CACF,MAAM,KAAK,KAAKA,EAAO,oBAAoB,EAC3C,MAAM6C,EAAS,MAAM,KAAK,KAAK7C,EAAO,wBAAwB,EAC9D,MAAM,KAAK,KAAKA,EAAO,qBAAqB,EAC5C,MAAM+D,EAAkC,GACxC,UAAWC,KAAKnB,EAAO,SAAW,GAChCkB,EAAQC,EAAE,IAAI,EAAIA,EAAE,MAEtB,MAAO,CAAE,QAAS,GAAM,QAAAD,CAAA,CAC1B,OAAS,EAAG,CACV,MAAO,CAAE,QAAS,GAAO,MAAO,aAAa,MAAQ,EAAE,QAAU,OAAO,CAAC,EAC3E,CACF,CAEA,MAAM,uBAAuB/D,EAAeiE,EAAkBC,EAAgE,CAC5H,MAAM,KAAK,eAAelE,CAAK,EAC/B,GAAI,CACF,MAAM,KAAK,KAAKA,EAAO,YAAY,EACnC,MAAMmE,EAAM,MAAM,KAAK,KAAKnE,EAAO,iBAAiB,EAC9CoE,EAAc,MAAM,KAAK,KAAKpE,EAAO,oBAAqB,CAC9D,OAAQmE,EAAI,KAAK,OACjB,SAAAF,CAAA,CACD,EACD,OAAKG,EAAY,QAGjB,MAAM,KAAK,KAAKpE,EAAO,wBAAyB,CAC9C,OAAQoE,EAAY,OACpB,MAAAF,CAAA,CACD,EACM,CAAE,QAAS,KANT,CAAE,QAAS,GAAO,MAAO,qCAOpC,OAAS9D,EAAG,CACV,MAAO,CAAE,QAAS,GAAO,MAAOA,aAAa,MAAQA,EAAE,QAAU,OAAOA,CAAC,EAC3E,CACF,CAEA,MAAM,YAAYJ,EAAeqE,EAAkB,IAA2E,OAC5H,MAAM,KAAK,eAAerE,CAAK,EAC/B,MAAMqC,EAAY,KAAK,MACvB,GAAI,CACF,KAAO,KAAK,MAAQA,EAAYgC,GAAS,CAKvC,MAAMC,GAAaxD,GAJJ,MAAM,KAAK,KAAKd,EAAO,mBAAoB,CACxD,WAAY,sBACZ,cAAe,GAChB,GACyB,SAAP,YAAAc,EAAe,MAClC,GAAIwD,IAAe,WACjB,MAAO,CAAE,QAAS,GAAM,WAAAA,CAAA,EAE1B,MAAM,IAAI,QAAQC,GAAW,WAAWA,EAAS,GAAG,CAAC,CACvD,CACA,MAAO,CAAE,QAAS,GAAO,MAAO,kCAAkCF,CAAO,MAC3E,OAASjE,EAAG,CACV,MAAO,CAAE,QAAS,GAAO,MAAOA,aAAa,MAAQA,EAAE,QAAU,OAAOA,CAAC,EAC3E,CACF,CAEA,MAAM,UAAUJ,EAAiJ,CAC/J,MAAM,KAAK,eAAeA,CAAK,EAC/B,GAAI,CACF,MAAM,KAAK,KAAKA,EAAO,aAAa,EACpC,MAAM6C,EAAS,MAAM,KAAK,KAAK7C,EAAO,mBAAmB,EACnDwE,EAAmF,GACnFC,EAAgB,CAACC,EAAYC,IAAsB,CAOvD,GANAH,EAAO,KAAK,CACV,QAASE,EAAM,MAAM,GACrB,IAAKA,EAAM,MAAM,IACjB,KAAMA,EAAM,MAAM,MAAQ,GAC1B,SAAAC,CAAA,CACD,EACGD,EAAM,YACR,UAAWE,KAASF,EAAM,YACxBD,EAAcG,EAAOF,EAAM,MAAM,EAAE,CAGzC,EACA,OAAAD,EAAc5B,EAAO,SAAS,EACvB,CAAE,QAAS,GAAM,OAAA2B,CAAA,CAC1B,OAAS,EAAG,CACV,MAAO,CAAE,QAAS,GAAO,MAAO,aAAa,MAAQ,EAAE,QAAU,OAAO,CAAC,EAC3E,CACF,CAEA,MAAM,gBAAgBxE,EAAe6E,EAAiBC,EAAiF,WACrI,MAAM,KAAK,eAAe9E,CAAK,EAC/B,GAAI,CACF,MAAM+E,EAAgB,MAAM,KAAK,KAAK/E,EAAO,2BAA4B,CACvE,QAAA6E,EACA,UAAW,gBACZ,EACKG,EAAoB,gCAAgCF,CAAU,SAC9DjC,EAAS,MAAM,KAAK,KAAK7C,EAAO,mBAAoB,CACxD,WAAYgF,EACZ,UAAWD,EAAc,mBACzB,cAAe,GACf,aAAc,GACf,EACD,GAAIlC,EAAO,iBACT,MAAO,CAAE,QAAS,GAAO,MAAOA,EAAO,iBAAiB,QAAQ/B,EAAA+B,EAAO,iBAAiB,YAAxB,YAAA/B,EAAmC,cAAe,qBAEpH,GAAI,CACF,MAAO,CAAE,QAAS,GAAM,OAAQ,KAAK,OAAMD,EAAAgC,EAAO,SAAP,YAAAhC,EAAe,KAAK,EACjE,MAAQ,CACN,MAAO,CAAE,QAAS,GAAM,QAAQsB,EAAAU,EAAO,SAAP,YAAAV,EAAe,MACjD,CACF,OAAS/B,EAAG,CACV,MAAO,CAAE,QAAS,GAAO,MAAOA,aAAa,MAAQA,EAAE,QAAU,OAAOA,CAAC,EAC3E,CACF,CAEA,mBACEJ,EACA0D,EAKkB,CAClB,IAAIjD,EAAW,KAAK,gBAAgB,IAAIT,CAAK,GAAK,GAKlD,GAHI0D,GAAA,MAAAA,EAAS,aACXjD,EAAWA,EAAS,OAAQuD,GAAMA,EAAE,OAAS,SAAWA,EAAE,OAAS,WAAW,GAE5EN,GAAA,MAAAA,EAAS,QACX,GAAI,CACF,MAAMuB,EAAQ,IAAI,OAAOvB,EAAQ,QAAS,GAAG,EAC7CjD,EAAWA,EAAS,OAAQuD,GAAMiB,EAAM,KAAKjB,EAAE,IAAI,CAAC,CACtD,MAAY,CACVvD,EAAWA,EAAS,OAAQuD,GAAMA,EAAE,KAAK,SAASN,EAAQ,OAAQ,CAAC,CACrE,CAEF,OAAIA,GAAA,MAAAA,EAAS,QACXjD,EAAWA,EAAS,MAAM,CAACiD,EAAQ,KAAK,GAGnC,CAAC,GAAGjD,CAAQ,CACrB,CAEA,qBAAqBT,EAAqB,CACxC,KAAK,gBAAgB,IAAIA,EAAO,EAAE,CACpC,CAEA,mBACEA,EACA0D,EAIkB,CAClB,IAAIvC,EAAW,KAAK,gBAAgB,IAAInB,CAAK,GAAK,GAElD,OAAI0D,GAAA,MAAAA,EAAS,aACXvC,EAAWA,EAAS,OAAQe,GAAMA,EAAE,IAAI,SAASwB,EAAQ,UAAW,CAAC,GAEnEA,GAAA,MAAAA,EAAS,QACXvC,EAAWA,EAAS,MAAM,CAACuC,EAAQ,KAAK,GAGnC,CAAC,GAAGvC,CAAQ,CACrB,CAEA,qBAAqBnB,EAAqB,CACxC,KAAK,gBAAgB,IAAIA,EAAO,EAAE,EAClC,KAAK,eAAe,IAAIA,EAAO,IAAI,GAAK,CAC1C,CAKA,kBACEA,EACA0D,EAKgB,CAEhB,MAAMjC,EAAa,KAAK,eAAe,IAAIzB,CAAK,EAChD,IAAIkF,EAA0B,GAE9B,OAAIzD,GAAcA,EAAW,KAAO,EAClCyD,EAAU,MAAM,KAAKzD,EAAW,QAAQ,EAIxCyD,GADiB,KAAK,gBAAgB,IAAIlF,CAAK,GAAK,IACjC,IAAI,CAACoB,EAAK+D,KAAS,CACpC,GAAI,KAAK/D,EAAI,SAAS,IAAI+D,CAAG,GAC7B,GAAI/D,EAAI,UACR,OAAQA,EAAI,OACZ,IAAKA,EAAI,IACT,OAAQ,KAAK,cAAcA,EAAI,GAAG,EAClC,eAAgB,GAChB,MAAApB,EACA,KAAMoB,EAAI,KACV,OAAQA,EAAI,OACZ,MAAO,GACP,WAAYA,EAAI,UAChB,kBAAmB,GACnB,iBAAkB,IACF,EAIfsC,GAAA,MAAAA,EAAS,gBACZwB,EAAUA,EAAQ,OAAO9E,GAAK,CAAC,KAAK,cAAcA,EAAE,QAAQ,CAAC,GAG3DsD,GAAA,MAAAA,EAAS,aACXwB,EAAUA,EAAQ,OAAQ9E,GAAMA,EAAE,IAAI,SAASsD,EAAQ,UAAW,CAAC,GAGjEA,GAAA,MAAAA,EAAS,QACXwB,EAAUA,EAAQ,MAAM,CAACxB,EAAQ,KAAK,GAGjCwB,CACT,CAKA,gBAAgBlF,EAAeoF,EAAwC,CACrE,MAAM3D,EAAa,KAAK,eAAe,IAAIzB,CAAK,EAChD,OAAOyB,GAAA,YAAAA,EAAY,IAAI2D,KAAc,IACvC,CAMA,MAAM,gBAAgBpF,EAAeoF,EAKlC,CACD,MAAM,KAAK,eAAepF,CAAK,EAE/B,GAAI,CACF,MAAM6C,EAAS,MAAM,KAAK,KAAK7C,EAAO,0BAA2B,CAC/D,UAAAoF,CAAA,CACD,EAED,MAAO,CACL,QAAS,GACT,KAAMvC,EAAO,KACb,cAAeA,EAAO,cAE1B,OAASzC,EAAG,CACV,MAAO,CACL,QAAS,GACT,MAAOA,aAAa,MAAQA,EAAE,QAAU,OAAOA,CAAC,EAEpD,CACF,CAEA,mBAAmBJ,EAAeqF,EAAkBC,EAAsC,CACnF,KAAK,iBAAiB,IAAItF,CAAK,GAClC,KAAK,iBAAiB,IAAIA,EAAO,IAAI,GAAK,EAE5C,KAAK,iBAAiB,IAAIA,CAAK,EAAG,IAAIqF,EAAUC,CAAQ,CAC1D,CAEA,uBAAuBtF,EAAeqF,EAAwB,CAC5D,MAAMrE,EAAY,KAAK,iBAAiB,IAAIhB,CAAK,EAC7CgB,IACFA,EAAU,OAAOqE,CAAQ,EACrBrE,EAAU,OAAS,GACrB,KAAK,iBAAiB,OAAOhB,CAAK,EAGxC,CAEA,mBAAmBA,EAAeqF,EAAkBC,EAAsC,CACnF,KAAK,iBAAiB,IAAItF,CAAK,GAClC,KAAK,iBAAiB,IAAIA,EAAO,IAAI,GAAK,EAE5C,KAAK,iBAAiB,IAAIA,CAAK,EAAG,IAAIqF,EAAUC,CAAQ,CAC1D,CAEA,uBAAuBtF,EAAeqF,EAAwB,CAC5D,MAAMrE,EAAY,KAAK,iBAAiB,IAAIhB,CAAK,EAC7CgB,IACFA,EAAU,OAAOqE,CAAQ,EACrBrE,EAAU,OAAS,GACrB,KAAK,iBAAiB,OAAOhB,CAAK,EAGxC,CAEA,MAAM,eAAeA,EAAe8E,EAGjC,CACD,MAAM,KAAK,eAAe9E,CAAK,EAC/B,GAAI,CACF,MAAM,KAAK,KAAKA,EAAO,gBAAgB,CACzC,MAAY,CAAC,CAEb,OAAO,KAAK,KAAKA,EAAO,mBAAoB,CAC1C,WAAA8E,EACA,cAAe,GACf,aAAc,GACd,QAAS,IACV,CACH,CAEA,MAAc,KAAK9E,EAAeM,EAAgBC,EAA+B,CAC/E,MAAM,KAAK,eAAeP,CAAK,EAC/B,MAAMC,EAAS,KAAK,QAAQ,IAAID,CAAK,EACrC,OAAO,OAAO,SAAS,YAAYC,EAAQK,EAAQC,CAAM,CAC3D,CAEA,MAAM,YAAYP,EAAeM,EAAgBC,EAA+B,CAC9E,OAAO,KAAK,KAAKP,EAAOM,EAAQC,CAAM,CACxC,CAEA,MAAc,eAAeP,EAA8B,CACpD,KAAK,QAAQ,IAAIA,CAAK,GACzB,MAAM,KAAK,OAAOA,CAAK,CAE3B,CAEA,MAAM,gBAAgBA,EAA2D,CAC/E,MAAMuF,EAAgB,MAAM,KAAK,KAAKvF,EAAO,uBAAuB,EAC9D2D,EAAW4B,EAAc,gBAAkBA,EAAc,eAC/D,MAAO,CACL,MAAO,KAAK,MAAM5B,EAAS,WAAW,EACtC,OAAQ,KAAK,MAAMA,EAAS,YAAY,EAE5C,CAEA,MAAM,kBAAkB3D,EAIrB,CACD,MAAM6C,EAAS,MAAM,KAAK,KAAK7C,EAAO,yBAA0B,CAC9D,OAAQ,MACR,sBAAuB,GACxB,EACK,CAAE,MAAAwF,EAAO,OAAAC,CAAA,EAAW,MAAM,KAAK,gBAAgBzF,CAAK,EAC1D,MAAO,CAAE,OAAQ6C,EAAO,KAAM,MAAA2C,EAAO,OAAAC,CAAA,CACvC,CAEA,MAAM,cAAczF,EAAe0F,EAAWC,EAAWH,EAAeC,EAIrE,CAKD,MAAO,CAAE,QAJM,MAAM,KAAK,KAAKzF,EAAO,yBAA0B,CAC9D,OAAQ,MACR,KAAM,CAAE,EAAA0F,EAAG,EAAAC,EAAG,MAAAH,EAAO,OAAAC,EAAQ,MAAO,EAAE,CACvC,GACuB,KAAM,MAAAD,EAAO,OAAAC,CAAA,CACvC,CAEA,MAAc,mBACZzF,EACA4F,EACAF,EACAC,EACAjC,EAOI,GACW,CACf,MAAMnD,EAA8B,CAClC,KAAAqF,EACA,EAAG,KAAK,MAAMF,CAAC,EACf,EAAG,KAAK,MAAMC,CAAC,EACf,UAAWjC,EAAQ,WAAa,IAG9BkC,IAAS,gBAAkBA,IAAS,iBAAmBA,IAAS,gBAClErF,EAAO,OAASmD,EAAQ,QAAU,QAC9BkC,IAAS,gBAAkBA,IAAS,mBACtCrF,EAAO,WAAamD,EAAQ,YAAc,IAI1CkC,IAAS,eACXrF,EAAO,QAAUmD,EAAQ,SAAW,GAGlCkC,IAAS,eACXrF,EAAO,OAASmD,EAAQ,QAAU,EAClCnD,EAAO,OAASmD,EAAQ,QAAU,GAGpC,MAAM,KAAK,KAAK1D,EAAO,2BAA4BO,CAAM,CAC3D,CAEA,MAAM,MACJP,EACA0F,EACAC,EACAE,EAAsB,OACtBC,EAAa,EACbC,EAAY,EACG,CACf,MAAMC,EAAcH,IAAW,OAAS,EAAIA,IAAW,QAAU,EAAIA,IAAW,SAAW,EAAI,EAE/F,MAAM,KAAK,mBAAmB7F,EAAO,aAAc0F,EAAGC,EAAG,CAAE,OAAQ,OAAQ,QAAS,EAAG,UAAAI,CAAA,CAAW,EAClG,MAAM,IAAI,QAAQxB,GAAW,WAAWA,EAAS,GAAG,CAAC,EAErD,QAAS0B,EAAI,EAAGA,GAAKH,EAAYG,IAC/B,MAAM,KAAK,mBAAmBjG,EAAO,eAAgB0F,EAAGC,EAAG,CACzD,OAAAE,EACA,QAASG,EACT,WAAYC,EACZ,UAAAF,CAAA,CACD,EACD,MAAM,IAAI,QAAQxB,GAAW,WAAWA,EAAS,EAAE,CAAC,EACpD,MAAM,KAAK,mBAAmBvE,EAAO,gBAAiB0F,EAAGC,EAAG,CAC1D,OAAAE,EACA,QAAS,EACT,WAAYI,EACZ,UAAAF,CAAA,CACD,EACGE,EAAIH,GACN,MAAM,IAAI,QAAQvB,GAAW,WAAWA,EAAS,GAAG,CAAC,CAG3D,CAEA,MAAM,WAAWvE,EAAe0F,EAAWC,EAAWI,EAAY,EAAkB,CAClF,MAAM,KAAK,MAAM/F,EAAO0F,EAAGC,EAAG,QAAS,EAAGI,CAAS,CACrD,CAEA,MAAM,YAAY/F,EAAe0F,EAAWC,EAAWI,EAAY,EAAkB,CACnF,MAAM,KAAK,MAAM/F,EAAO0F,EAAGC,EAAG,OAAQ,EAAGI,CAAS,CACpD,CAEA,MAAM,YAAY/F,EAAe0F,EAAWC,EAAWI,EAAY,EAAkB,CACnF,MAAM,KAAK,MAAM/F,EAAO0F,EAAGC,EAAG,OAAQ,EAAGI,CAAS,CACpD,CAEA,MAAM,MAAM/F,EAAe0F,EAAWC,EAA0B,CAC9D,MAAM,KAAK,mBAAmB3F,EAAO,aAAc0F,EAAGC,EAAG,CAAE,OAAQ,OAAQ,QAAS,EAAG,CACzF,CAEA,MAAM,KACJ3F,EACAkG,EACAC,EACAC,EACAC,EACAN,EAAY,EACG,CACf,MAAM,KAAK,mBAAmB/F,EAAO,aAAckG,EAAQC,EAAQ,CAAE,OAAQ,OAAQ,QAAS,EAAG,EACjG,MAAM,IAAI,QAAQ5B,GAAW,WAAWA,EAAS,EAAE,CAAC,EAEpD,MAAM,KAAK,mBAAmBvE,EAAO,eAAgBkG,EAAQC,EAAQ,CACnE,OAAQ,OACR,QAAS,EACT,WAAY,EACZ,UAAAJ,CAAA,CACD,EACD,MAAM,IAAI,QAAQxB,GAAW,WAAWA,EAAS,EAAE,CAAC,EAEpD,MAAM,KAAK,mBAAmBvE,EAAO,aAAcoG,EAAMC,EAAM,CAAE,OAAQ,OAAQ,QAAS,EAAG,UAAAN,CAAA,CAAW,EACxG,MAAM,IAAI,QAAQxB,GAAW,WAAWA,EAAS,EAAE,CAAC,EAEpD,MAAM,KAAK,mBAAmBvE,EAAO,gBAAiBoG,EAAMC,EAAM,CAChE,OAAQ,OACR,QAAS,EACT,WAAY,EACZ,UAAAN,CAAA,CACD,CACH,CAEA,MAAM,OAAO/F,EAAe0F,EAAWC,EAAWW,EAAgBC,EAA+B,CAC/F,MAAM,KAAK,mBAAmBvG,EAAO,aAAc0F,EAAGC,EAAG,CAAE,OAAAW,EAAQ,OAAAC,EAAQ,CAC7E,CAEA,MAAM,KAAKvG,EAAeU,EAA6B,CACrD,UAAW8F,KAAQ9F,EACjB,GAAI8F,IAAS;AAAA,GAAQA,IAAS,KAC5B,MAAM,KAAK,SAASxG,EAAO,OAAO,UAEnB,KAAK,iBAAiBwG,CAAI,EAC7B,CACV,MAAMC,EAAa,KAAK,cAAcD,CAAI,EAC1C,MAAM,KAAK,SAASxG,EAAOwG,EAAMC,EAAa7G,EAAU,MAAQ,CAAC,CACnE,MACE,MAAM,KAAK,KAAKI,EAAO,mBAAoB,CAAE,KAAMwG,EAAM,CAIjE,CAEQ,cAAcA,EAAuB,CAC3C,MAAO,6BAA6B,KAAKA,CAAI,CAC/C,CAEA,MAAc,iBACZxG,EACA4F,EACAc,EACAX,EAAY,EACG,CACf,MAAM,KAAK,KAAK/F,EAAO,yBAA0B,CAC/C,KAAM0G,EAAO,KAAOd,EAAQA,IAAS,UAAY,aAAeA,EAChE,IAAKc,EAAO,IACZ,KAAMA,EAAO,KACb,sBAAuBA,EAAO,QAC9B,UAAAX,EACA,KAAMW,EAAO,MAAQ,GACrB,eAAgBA,EAAO,MAAQ,GAC/B,SAAUA,EAAO,UAAY,EAC9B,CACH,CAEA,MAAM,SAAS1G,EAAeuB,EAAawE,EAAY,EAAkB,CACvE,MAAMW,EAAS,KAAK,iBAAiBnF,CAAG,EACxC,GAAI,CAACmF,EACH,MAAM,IAAI,MAAM,gBAAgBnF,CAAG,EAAE,EAGvC,MAAM,KAAK,iBAAiBvB,EAAO,UAAW0G,EAAQX,CAAS,EAC/D,MAAM,KAAK,iBAAiB/F,EAAO,QAAS0G,EAAQX,CAAS,CAC/D,CAEA,MAAM,cAAc/F,EAAe2G,EAA8B,CAC/D,MAAMC,EAAQD,EAAM,cAAc,MAAM,GAAG,EACrCE,EAAyB,GAC/B,IAAIC,EAAU,GAEd,UAAWC,KAAQH,EACbG,KAAQnH,EACViH,EAAa,KAAKE,CAAI,EAEtBD,EAAUC,EAId,IAAIhB,EAAY,EAChB,UAAWiB,KAAOH,EAChBd,GAAanG,EAAUoH,CAA6B,GAAK,EAGvDF,GACF,MAAM,KAAK,SAAS9G,EAAO8G,EAASf,CAAS,CAEjD,CAEQ,iBAAiBxE,EAAmC,CAC1D,MAAM0F,EAAW1F,EAAI,cAErB,GAAI1B,GAAgBoH,CAAQ,EAC1B,OAAOpH,GAAgBoH,CAAQ,EAGjC,GAAI1F,EAAI,SAAW,EAAG,CACpB,MAAM2F,EAAO3F,EAAI,cAAc,WAAW,CAAC,EAC3C,MAAO,CACL,IAAAA,EACA,KAAM,MAAMA,EAAI,aAAa,GAC7B,QAAS2F,EACT,KAAM3F,CAAA,CAEV,CAEA,OAAO,IACT,CAEA,eAAe4F,EAAiC,CAC9C,GAAI,CAACA,EAAgB,MAAO,GAE5B,IAAItE,EAAS,EACb,MAAM+D,EAAQO,EAAe,cAAc,MAAM,GAAG,EACpD,UAAWJ,KAAQH,EAAO,CACxB,MAAMQ,EAAUL,EAAK,OACjBK,KAAWxH,IACbiD,GAAUjD,EAAUwH,CAAiC,EAEzD,CACA,OAAOvE,CACT,CACF,EA7wCE9C,EAVWD,EAUI,6BAA6B,IAG5CC,EAbWD,EAaa,uBAAuB,GAAK,MACpDC,EAdWD,EAca,qBAAqB,IAAI,IAAI,CACnD,YAAa,aAAc,YAAa,aAAc,gBAAiB,eACvE,YAAa,aAAc,WAAY,WAAY,wBAAyB,yBAC5E,WAAY,yBAA0B,kBAAmB,2BAC1D,GACDC,EAnBWD,EAmBa,eAAe,IAAI,IAAI,CAC7C,YAAa,aAAc,YAAa,aAAc,eACtD,YAAa,aAAc,WAAY,WAAY,wBAAyB,yBAC5E,2BAA4B,kBAAmB,kBAC/C,aAAc,YAAa,YAC3B,YAAa,aAAc,YAC5B,GAzBI,IAAMuH,GAANvH,EC/HHwH,GAAY,GACZC,GAAc,GAClB,MAAMC,GAA2B,GAEjC,OAAO,QAAQ,MAAM,IAAI,WAAW,EAAE,KAAK,CAAC,CAAE,UAAWC,KAAa,CAGpE,GAFAH,GAAY,CAAC,CAACG,EACdF,GAAc,GACVD,GACF,UAAWI,KAAQF,GACjB,QAAQ,IAAI,SAAU,GAAGE,CAAI,EAGjCF,GAAY,OAAS,CACvB,CAAC,EAED,OAAO,QAAQ,UAAU,YAAY,CAACG,EAASC,IAAa,CACtDA,IAAa,SAAWD,EAAQ,YAClCL,GAAY,CAAC,CAACK,EAAQ,UAAU,SAEpC,CAAC,EAEM,SAASE,KAAYH,EAAuB,CACjD,GAAI,CAACH,GAAa,CAChBC,GAAY,KAAKE,CAAI,EACrB,MACF,CACIJ,IACF,QAAQ,IAAI,SAAU,GAAGI,CAAI,CAEjC,CCpBA,MAAMI,OAAsB,IAGrB,SAASC,GAAwBhH,EAAmB,CACzD,KAAM,CAAE,KAAA6E,EAAM,SAAAP,CAAA,EAAatE,EAE3B,GAAI,CAACsE,GAAY,CAACyC,GAAgB,IAAIzC,CAAQ,EAC5C,MAAO,GAGT,MAAMrE,EAAY8G,GAAgB,IAAIzC,CAAQ,EAE9C,OAAQO,EAAA,CACN,IAAK,qBACH,OAAA5E,EAAU,QAAQD,EAAI,OAAQA,EAAI,OAAO,EAClC,GACT,IAAK,qBACH,OAAAC,EAAU,QAAQD,EAAI,KAAK,EACpB,GACT,IAAK,mBACH,OAAAC,EAAU,QACV8G,GAAgB,OAAOzC,CAAQ,EACxB,GACT,IAAK,qBACH,OAAArE,EAAU,QAAQD,EAAI,KAAK,EAC3B+G,GAAgB,OAAOzC,CAAQ,EACxB,GACT,QACE,MAAO,GAEb,CCpCA,IAAI2C,EAAyC,KACzCC,GAAsD,KACtDC,EAAyD,KACzDC,MAA4B,IAC5BC,GAAkB,EAEf,SAASC,GACdC,EACM,CACNL,GAAiBK,EACjBC,GAAA,CACF,CAEO,SAASC,GAAiBzH,EAAwB,CACvD,OAAO,IAAI,QAAQ,CAACwD,EAASkE,IAAW,CACtC,GAAI,CAACT,EAAY,CACfS,EAAO,IAAI,MAAM,2BAA2B,CAAC,EAC7C,MACF,CAEA,GAAI1H,EAAI,OAAS,cAAe,CAC9BiH,EAAW,YAAYjH,CAAG,EAC1BwD,EAAQ,CAAE,KAAM,GAAM,EACtB,MACF,CAEA,MAAMmE,EAAK,EAAEN,GACbD,EAAsB,IAAIO,EAAI,CAAE,QAAAnE,EAAS,OAAAkE,EAAQ,EACjDT,EAAW,YAAY,CAAE,GAAGjH,EAAK,GAAA2H,EAAI,EAErC,WAAW,IAAM,CACXP,EAAsB,IAAIO,CAAE,IAC9BP,EAAsB,OAAOO,CAAE,EAC/BD,EAAO,IAAI,MAAM,6BAA6B,CAAC,EAEnD,EAAG,GAAK,CACV,CAAC,CACH,CAEO,SAASE,EAAiB5H,EAAgB,CAC3CiH,GACFA,EAAW,YAAYjH,CAAG,CAE9B,CAEA,SAASwH,IAAgB,CACnBL,IACF,aAAaA,CAAgB,EAC7BA,EAAmB,MAGrB,GAAI,CACFF,EAAa,OAAO,QAAQ,cAAc,mBAAmB,EAC7DH,EAAS,8BAA8B,EAEvCG,EAAW,UAAU,YAAY,MAAOjH,GAAQ,OAG9C,GAFA8G,EAAS,6BAA8B9G,EAAI,MAAQA,EAAI,EAAE,EAErDA,EAAI,OAAS,aAAc,CAC7B8G,EAAS,mBAAmB,EAC5B,MACF,CAEA,IAAI/G,EAAAC,EAAI,OAAJ,MAAAD,EAAU,WAAW,iBAAkB,CACzCiH,GAAwBhH,CAAG,EAC3B,OAAO,QAAQ,YAAYA,CAAG,EAAE,MAAM,IAAM,CAAC,CAAC,EAC9C,MACF,CAEA,GAAIA,EAAI,IAAMoH,EAAsB,IAAIpH,EAAI,EAAE,EAAG,CAC/C,KAAM,CAAE,QAAAwD,CAAA,EAAY4D,EAAsB,IAAIpH,EAAI,EAAE,EACpDoH,EAAsB,OAAOpH,EAAI,EAAE,EACnCwD,EAAQxD,CAAG,EACX,MACF,CAEA,GAAKkH,GAEL,GAAI,CACF,MAAMpF,EAAS,MAAMoF,GAAelH,CAAG,EACvC,GAAI,CAACiH,EAAY,CACfH,EAAS,mDAAoD9G,EAAI,EAAE,EACnE,MACF,CACAiH,EAAW,YAAY,CAAE,GAAIjH,EAAI,GAAI,GAAG8B,EAAQ,CAClD,OAAS3C,EAAK,CACZ,GAAI,CAAC8H,EAAY,CACfH,EAAS,gDAAiD9G,EAAI,EAAE,EAChE,MACF,CACAiH,EAAW,YAAY,CACrB,GAAIjH,EAAI,GACR,MAAOb,aAAe,MAAQA,EAAI,QAAU,gBAC7C,CACH,CACF,CAAC,EAED8H,EAAW,aAAa,YAAY,IAAM,OACxC,MAAMY,EAAQ,OAAO,QAAQ,UAC7Bf,EACE,6BACAe,GAAA,YAAAA,EAAO,UAAW,kBAEpBZ,EAAa,MAERlH,EAAA8H,GAAA,YAAAA,EAAO,UAAP,MAAA9H,EAAgB,SAAS,eAC5BoH,EAAmB,WAAWK,GAAS,GAAI,EAE/C,CAAC,CACH,OAASrI,EAAK,CACZ2H,EAAS,oCAAqC3H,CAAG,EACjDgI,EAAmB,WAAWK,GAAS,GAAK,CAC9C,CACF,mKChHAV,EAAS,uBAAuB,EAEhC,MAAMgB,EAAM,IAAIxB,GACVyB,MAAuB,IAIvBC,MAAoB,IAG1B,SAASC,EAAiBhJ,EAAuB,CAC/C,OAAO+I,EAAc,IAAI/I,CAAK,GAAK,CACrC,CAEA,MAAMiJ,MAAsB,IAC5B,IAAIC,GAAoB,EAExB,SAASC,IAA+B,CACtC,MAAO,cAAc,EAAED,EAAiB,IAAI,KAAK,KAAK,EACxD,CAEA,SAASE,GAAgBV,EAAYW,EAA+D,CAElG,GADAJ,EAAgB,IAAIP,EAAIW,CAAI,EACxBJ,EAAgB,KAAO,GAAI,CAC7B,MAAMK,EAASL,EAAgB,OAAO,OAAO,MACzCK,GAAQL,EAAgB,OAAOK,CAAM,CAC3C,CACF,CAEA,SAASC,GAAcb,EAAsE,CAC3F,OAAOO,EAAgB,IAAIP,CAAE,GAAK,IACpC,CAEA,MAAMc,GAAyC,CAC7C,OAAQ,UACR,MAAO,UACP,OAAQ,UACR,EAAG,UACH,SAAU,UACV,QAAS,SACX,EAEA,eAAeC,GACbC,EACAC,EACAC,EAC4D,CAC5D,MAAMC,EAAOC,GAAaJ,EAAW,MAAM,EACrCK,EAAS,MAAM,kBAAkBF,CAAI,EAErCG,EAAS,IAAI,gBAAgBD,EAAO,MAAOA,EAAO,MAAM,EACxDE,EAAMD,EAAO,WAAW,IAAI,EAClC,GAAI,CAACC,EAAK,MAAM,IAAI,MAAM,8BAA8B,EAExDA,EAAI,UAAUF,EAAQ,EAAG,CAAC,EAC1BA,EAAO,QAEP,MAAMG,EAAc,KAAK,IAAIN,EAAM,OAAQA,EAAM,MAAM,EAEvD,UAAWO,KAAWR,EAAU,CAC9B,MAAMS,EAAQZ,GAAeW,EAAQ,GAAG,GAAKX,GAAe,QAEtD9D,EAAI,KAAK,MAAMyE,EAAQ,OAAO,EAAID,CAAW,EAC7CvE,EAAI,KAAK,MAAMwE,EAAQ,OAAO,EAAID,CAAW,EAC7CG,EAAI,KAAK,MAAMF,EAAQ,OAAO,MAAQD,CAAW,EACjDI,EAAI,KAAK,MAAMH,EAAQ,OAAO,OAASD,CAAW,EAExD,GAAIG,EAAI,GAAKC,EAAI,EAAG,SAEpBL,EAAI,YAAcG,EAClBH,EAAI,UAAY,EAChBA,EAAI,YAAY,CAAC,EAAG,CAAC,CAAC,EACtBA,EAAI,WAAWvE,EAAGC,EAAG0E,EAAGC,CAAC,EACzBL,EAAI,YAAY,EAAE,EAElB,MAAMM,EAAYJ,EAAQ,IACpBK,EAAW,KAAK,IAAI,GAAI,KAAK,IAAI,GAAI,KAAK,MAAMR,EAAO,MAAQ,GAAI,CAAC,CAAC,EAC3EC,EAAI,KAAO,QAAQO,CAAQ,gBAC3B,MAAMC,EAAYR,EAAI,YAAYM,CAAS,EAAE,MACvCG,EAAU,EACVC,EAAaF,EAAYC,EAAU,EACnCE,EAAcJ,EAAWE,EAAU,EAEzC,IAAIG,EAASnF,EAAI,KAAK,OAAO2E,EAAIM,GAAc,CAAC,EAC5CG,EAASnF,EAAI,GACb0E,EAAI,IAAMC,EAAI,MAChBQ,EAASnF,EAAIiF,EAAc,EAAI,EAAIjF,EAAI2E,EAAI,EAAI3E,EAAIiF,EAAc,GAGnEC,EAAS,KAAK,IAAI,EAAG,KAAK,IAAIb,EAAO,MAAQW,EAAYE,CAAM,CAAC,EAChEC,EAAS,KAAK,IAAI,EAAG,KAAK,IAAId,EAAO,OAASY,EAAaE,CAAM,CAAC,EAElEb,EAAI,UAAYG,EAChBH,EAAI,SAASY,EAAQC,EAAQH,EAAYC,CAAW,EACpDX,EAAI,YAAc,QAClBA,EAAI,UAAY,EAChBA,EAAI,WAAWY,EAAQC,EAAQH,EAAYC,CAAW,EAEtDX,EAAI,UAAY,QAChBA,EAAI,aAAe,MACnBA,EAAI,SAASM,EAAWM,EAASH,EAASI,EAASJ,CAAO,CAC5D,CAEA,MAAMK,EAAa,MAAMf,EAAO,cAAc,CAAE,KAAM,YAAa,EAGnE,MAAO,CAAE,OAFM,MAAMgB,GAAaD,CAAU,EAE3B,MAAOf,EAAO,MAAO,OAAQA,EAAO,OACvD,CAEA,SAASgB,GAAanB,EAA6B,CACjD,OAAO,IAAI,QAAQ,CAACtF,EAASkE,IAAW,CACtC,MAAMwC,EAAS,IAAI,WACnBA,EAAO,OAAS,IAAM,CAEpB,MAAMC,EADUD,EAAO,OACA,MAAM,GAAG,EAAE,CAAC,EACnC1G,EAAQ2G,CAAM,CAChB,EACAD,EAAO,QAAU,IAAMxC,EAAO,IAAI,MAAM,kCAAkC,CAAC,EAC3EwC,EAAO,cAAcpB,CAAI,CAC3B,CAAC,CACH,CAEA,SAASC,GAAaoB,EAAgBnI,EAAW,YAAmB,CAClE,MAAMoI,EAAS,KAAKD,CAAM,EACpBE,EAAQ,IAAI,WAAWD,EAAO,MAAM,EAC1C,QAASlF,EAAI,EAAGA,EAAIkF,EAAO,OAAQlF,IACjCmF,EAAMnF,CAAC,EAAIkF,EAAO,WAAWlF,CAAC,EAEhC,OAAO,IAAI,KAAK,CAACmF,CAAK,EAAG,CAAE,KAAMrI,EAAU,CAC7C,CAEA,eAAesI,GAAgBrL,EAAesL,EAA+E,OAS3H,MAAMC,GAAazK,GARM,MAAM+H,EAAI,eAAe7I,EAAO;AAAA;AAAA,mEAEQsL,CAAS;AAAA;AAAA;AAAA;AAAA,QAIpE,GAE8B,SAAjB,YAAAxK,EAAyB,MAC5C,GAAI,CAACyK,EAAY,MAAM,IAAI,MAAM,+BAA+B,EAEhE,KAAM,CAAE,eAAAC,EAAgB,YAAAC,EAAa,MAAAjG,EAAO,iBAAAkG,EAAkB,gBAAAC,GAAoBJ,EAC5EK,EAAwB,GAC9B,IAAIC,EAAW,EAEf,KAAOA,EAAWJ,GAAa,CAC7B,MAAM5C,EAAI,eAAe7I,EAAO,sBAAsB6L,CAAQ,GAAG,EACjE,MAAM,IAAI,QAAQ,GAAK,WAAW,EAAG,GAAG,CAAC,EAEzC,MAAMC,EAAQ,MAAMjD,EAAI,kBAAkB7I,CAAK,EACzC+L,EAAYjC,GAAagC,EAAM,MAAM,EAC3CF,EAAO,KAAK,MAAM,kBAAkBG,CAAS,CAAC,EAE9CF,GAAYL,CACd,CAEA,MAAM3C,EAAI,eAAe7I,EAAO,sBAAsB2L,CAAe,GAAG,EAExE,MAAMK,EAAc,KAAK,MAAMxG,EAAQkG,CAAgB,EACjDO,EAAe,KAAK,MAAMR,EAAcC,CAAgB,EACxD1B,EAAS,IAAI,gBAAgBgC,EAAaC,CAAY,EACtDhC,EAAMD,EAAO,WAAW,IAAI,EAClC,GAAI,CAACC,EAAK,MAAM,IAAI,MAAM,8BAA8B,EAExD,IAAItE,EAAI,EACR,MAAMuG,EAAc,KAAK,MAAMV,EAAiBE,CAAgB,EAChE,QAASzF,EAAI,EAAGA,EAAI2F,EAAO,OAAQ3F,IAAK,CACtC,MAAM6F,EAAQF,EAAO3F,CAAC,EAChBkG,EAAkBF,EAAetG,EACjCyG,EAAa,KAAK,IAAIF,EAAaC,CAAe,EACxDlC,EAAI,UAAU6B,EAAO,EAAG,EAAGA,EAAM,MAAOM,EAAY,EAAGzG,EAAGmG,EAAM,MAAOM,CAAU,EACjFzG,GAAKyG,EACLN,EAAM,OACR,CAEA,MAAMf,EAAa,MAAMf,EAAO,cAAc,CAAE,KAAM,YAAa,EAGnE,MAAO,CAAE,OAFM,MAAMgB,GAAaD,CAAU,EAE3B,MAAOiB,EAAa,OAAQC,CAAA,CAC/C,CAEA,MAAMI,MAA0B,IAC1BC,MAAsB,IAE5B,OAAO,cAAc,YAAY,YAAapL,GAAY,CACxD,GAAIA,EAAQ,UAAY,EAAG,CAEzB6H,EAAc,OAAO7H,EAAQ,KAAK,EAClC,MAAMqL,EAAWF,EAAoB,IAAInL,EAAQ,KAAK,EAClDqL,IACFA,EAAA,EACAF,EAAoB,OAAOnL,EAAQ,KAAK,EAE5C,CACF,CAAC,EAED,OAAO,cAAc,gBAAgB,YAAaA,GAAY,CAC5D,GAAIA,EAAQ,UAAY,EAAG,CACzB,MAAMqL,EAAWF,EAAoB,IAAInL,EAAQ,KAAK,EAClDqL,IACFA,EAAA,EACAF,EAAoB,OAAOnL,EAAQ,KAAK,EAE5C,CACF,CAAC,EAID,OAAO,KAAK,UAAU,YAAalB,GAAU,CAC3C6I,EAAI,OAAO7I,CAAK,EAChB+I,EAAc,OAAO/I,CAAK,EAC1B,SAAW,CAACwM,EAAM9D,CAAE,IAAK4D,EACnB5D,IAAO1I,GACTsM,EAAgB,OAAOE,CAAI,EAG/B,SAAW,CAACnH,EAAUoH,CAAW,IAAK3D,EAChC2D,IAAgBzM,GAClB8I,EAAiB,OAAOzD,CAAQ,CAGtC,CAAC,EAOD,eAAeqH,GAAoB1M,EAAe2M,EAAY,IAAsB,OAClF,MAAMC,EAAW,KAAK,MAAQD,EACxBE,EAASC,GAAe,IAAI,QAAQ5K,GAAK,WAAWA,EAAG4K,CAAE,CAAC,EAGhE,KAAO,KAAK,MAAQF,GAAU,CAC5B,GAAI,CACF,MAAM/J,EAAS,MAAMgG,EAAI,eAAe7I,EAAO,qBAAqB,EACpE,KAAIc,EAAA+B,GAAA,YAAAA,EAAQ,SAAR,YAAA/B,EAAgB,SAAU,WAAY,CAExC,MAAM+L,EAAM,IAAI,EAChB,MACF,CACF,MAAQ,CAER,CACA,MAAMA,EAAM,GAAG,CACjB,CAGA,QAAQ,KAAK,yCAAyC7M,CAAK,EAAE,CAC/D,CAGA,eAAe+M,GACb/M,EACAgN,EACAC,EACAzL,EACAqH,EACAhE,EAAkB,EACJ,CACd,OAAQoI,EAAA,CACN,IAAK,QAAS,CACZ,MAAMpK,EAAS,MAAM,OAAO,KAAK,YAAY7C,EAAO,CAClD,KAAM,gBACN,IAAAgN,EACA,OAAQ,QACP,CAAE,QAAAnI,CAAA,CAAS,EACd,OAAOhC,EAAO,MAAQA,EAAS,CAAE,QAAS,GAAM,OAAQ,QAAS,IAAAmK,CAAA,CACnE,CACA,IAAK,OAAQ,CACX,GAAI,CAACxL,EAAO,MAAO,CAAE,MAAO,gCAC5B,MAAMqB,EAAS,MAAM,OAAO,KAAK,YAAY7C,EAAO,CAClD,KAAM,aACN,IAAAgN,EACA,MAAAxL,CAAA,EACC,CAAE,QAAAqD,CAAA,CAAS,EACd,OAAOhC,EAAO,MAAQA,EAAS,CAAE,QAAS,GAAM,OAAQ,OAAQ,IAAAmK,EAAK,MAAAxL,CAAA,CACvE,CACA,IAAK,QAAS,CACZ,MAAM0L,EAAS,MAAM,OAAO,KAAK,YAAYlN,EAAO,CAClD,KAAM,0BACN,IAAAgN,CAAA,EACC,CAAE,QAAAnI,CAAA,CAAS,EACd,OAAIqI,EAAO,MAAcA,GACzB,MAAMrE,EAAI,MAAM7I,EAAOkN,EAAO,EAAGA,EAAO,CAAC,EAClC,CAAE,QAAS,GAAM,OAAQ,QAAS,IAAAF,CAAA,EAC3C,CACA,IAAK,OAKH,OAJmB,MAAM,OAAO,KAAK,YAAYhN,EAAO,CACtD,KAAM,mBACN,IAAAgN,CAAA,EACC,CAAE,QAAAnI,CAAA,CAAS,EAGhB,QACE,MAAO,CAAE,MAAO,mBAAmBoI,CAAM,8BAA8B,CAE7E,CAEA,OAAO,QAAQ,UAAU,YAAY,CAAC9M,EAASgN,EAAQC,KACrDC,GAAclN,EAASgN,CAAM,EAC1B,KAAKC,CAAY,EACjB,MAAOlN,GAAQkN,EAAa,CAAE,MAAOlN,EAAI,QAAS,CAAC,EAC/C,GACR,EAED,eAAsBmN,GACpBlN,EACAgN,EACc,2CACd,MAAMnN,EAAQG,EAAQ,MAEtB,OAAQA,EAAQ,MACd,IAAK,qBAAsB,CACzB,KAAM,CAACmN,CAAG,EAAI,MAAM,OAAO,KAAK,MAAM,CAAE,OAAQ,GAAM,cAAe,GAAM,EAC3E,MAAO,CAAE,MAAOA,GAAA,YAAAA,EAAK,GACvB,CAEA,IAAK,qBAAsB,CACzB,GAAI,CAACtN,EAAO,MAAM,IAAI,MAAM,mBAAmB,EAE/C,GAAI,CACF,MAAM,OAAO,KAAK,YAAYA,EAAO,CAAE,KAAM,oBAAqB,CACpE,MAAY,CAAC,CACb,MAAM,IAAI,QAAQuE,GAAW,WAAWA,EAAS,EAAE,CAAC,EAEpD,GAAI,CACF,IAAI1B,EACA0K,EAAY,CAAE,OAAQ,EAAG,OAAQ,GACjCC,EAAe,GAEnB,GAAIrN,EAAQ,SAAU,CACpB0C,EAAS,MAAMwI,GAAgBrL,EAAOG,EAAQ,WAAa,GAAI,EAC/D,GAAI,CACF,MAAMwD,EAAW,MAAMkF,EAAI,gBAAgB7I,CAAK,EAC1CyN,EAAM5K,EAAO,MAAQc,EAAS,MACpC4J,EAAY,CAAE,OAAQE,EAAK,OAAQA,CAAA,CACrC,MAAQ,CAAC,CACX,KACE,IAAI,CACF,MAAMC,EAAY,MAAM7E,EAAI,kBAAkB7I,CAAK,EACnD6C,EAAS6K,EACT,GAAI,CACF,MAAM/J,EAAW,MAAMkF,EAAI,gBAAgB7I,CAAK,EAChDuN,EAAY,CACV,OAAQG,EAAU,MAAQ/J,EAAS,MACnC,OAAQ+J,EAAU,OAAS/J,EAAS,OAExC,MAAQ,CAAC,CACX,OAASgK,EAAU,CACjB,MAAML,EAAM,MAAM,OAAO,KAAK,IAAItN,CAAK,EACvC,GAAI,CAACsN,EAAI,SAAU,MAAMK,EAEzB,MAAMzC,GADU,MAAM,OAAO,KAAK,kBAAkBoC,EAAI,SAAU,CAAE,OAAQ,MAAO,GAC5D,QAAQ,2BAA4B,EAAE,EACvDM,EAAe,KAAK1C,CAAM,EAC1BE,EAAQ,IAAI,WAAWwC,EAAa,MAAM,EAChD,QAAS3H,EAAI,EAAGA,EAAI2H,EAAa,OAAQ3H,IACvCmF,EAAMnF,CAAC,EAAI2H,EAAa,WAAW3H,CAAC,EAEtC,MAAM4D,EAAO,IAAI,KAAK,CAACuB,CAAK,EAAG,CAAE,KAAM,YAAa,EAC9CrB,EAAS,MAAM,kBAAkBF,CAAI,EAC3ChH,EAAS,CAAE,OAAAqI,EAAQ,MAAOnB,EAAO,MAAO,OAAQA,EAAO,QACvDA,EAAO,QACPyD,EAAe,EACjB,CAGF,GAAIrN,EAAQ,UAAY,CAACqN,EACvB,GAAI,CACF,MAAMK,EAAa,MAAM,OAAO,KAAK,YAAY7N,EAAO,CACtD,KAAM,qCACL,CAAE,QAAS,EAAG,EAEb6N,GAAA,MAAAA,EAAY,UAAYA,EAAW,SAAS,OAAS,IACvDhL,EAAS,MAAM4G,GAAmB5G,EAAQgL,EAAW,SAAUN,CAAS,EAE5E,MAAQ,CAAC,CAGX,MAAMO,EAAe3E,GAAA,EACrB,OAAAC,GAAgB0E,EAAcjL,CAAM,EAC7B,CAAE,GAAGA,EAAQ,aAAAiL,CAAA,CACtB,SACE,GAAI,CACF,MAAM,OAAO,KAAK,YAAY9N,EAAO,CAAE,KAAM,sBAAuB,CACtE,MAAY,CAAC,CACf,CACF,CAEA,IAAK,gBAAiB,CACpB,GAAI,CAACA,EAAO,MAAM,IAAI,MAAM,mBAAmB,EAC/C,MAAM+N,EAAO5N,EAAQ,UAAY0I,EAAI,eAAe1I,EAAQ,SAAS,EAAI,EACzE,aAAM0I,EAAI,MAAM7I,EAAOG,EAAQ,EAAGA,EAAQ,EAAG,OAAQ,EAAG4N,CAAI,EACrD,CAAE,QAAS,GACpB,CAEA,IAAK,sBAAuB,CAC1B,GAAI,CAAC/N,EAAO,MAAM,IAAI,MAAM,mBAAmB,EAC/C,MAAM+N,EAAO5N,EAAQ,UAAY0I,EAAI,eAAe1I,EAAQ,SAAS,EAAI,EACzE,aAAM0I,EAAI,WAAW7I,EAAOG,EAAQ,EAAGA,EAAQ,EAAG4N,CAAI,EAC/C,CAAE,QAAS,GACpB,CAEA,IAAK,uBAAwB,CAC3B,GAAI,CAAC/N,EAAO,MAAM,IAAI,MAAM,mBAAmB,EAC/C,MAAM+N,EAAO5N,EAAQ,UAAY0I,EAAI,eAAe1I,EAAQ,SAAS,EAAI,EACzE,aAAM0I,EAAI,YAAY7I,EAAOG,EAAQ,EAAGA,EAAQ,EAAG4N,CAAI,EAChD,CAAE,QAAS,GACpB,CAEA,IAAK,uBAAwB,CAC3B,GAAI,CAAC/N,EAAO,MAAM,IAAI,MAAM,mBAAmB,EAC/C,MAAM+N,EAAO5N,EAAQ,UAAY0I,EAAI,eAAe1I,EAAQ,SAAS,EAAI,EACzE,aAAM0I,EAAI,YAAY7I,EAAOG,EAAQ,EAAGA,EAAQ,EAAG4N,CAAI,EAChD,CAAE,QAAS,GACpB,CAEA,IAAK,eAAgB,CACnB,GAAI,CAAC/N,EAAO,MAAM,IAAI,MAAM,mBAAmB,EAC/C,MAAM+N,EAAO5N,EAAQ,UAAY0I,EAAI,eAAe1I,EAAQ,SAAS,EAAI,EACzE,aAAM0I,EAAI,KAAK7I,EAAOG,EAAQ,OAAQA,EAAQ,OAAQA,EAAQ,KAAMA,EAAQ,KAAM4N,CAAI,EAC/E,CAAE,QAAS,GACpB,CAEA,IAAK,gBAAiB,CACpB,GAAI,CAAC/N,EAAO,MAAM,IAAI,MAAM,mBAAmB,EAC/C,aAAM6I,EAAI,MAAM7I,EAAOG,EAAQ,EAAGA,EAAQ,CAAC,EACpC,CAAE,QAAS,GACpB,CAEA,IAAK,eAAgB,CACnB,GAAI,CAACH,EAAO,MAAM,IAAI,MAAM,mBAAmB,EAC/C,GAAIG,EAAQ,OAAS,QAAaA,EAAQ,OAAS,KAAM,MAAM,IAAI,MAAM,kBAAkB,EAC3F,aAAM0I,EAAI,KAAK7I,EAAOG,EAAQ,IAAI,EAC3B,CAAE,QAAS,GACpB,CAEA,IAAK,cAAe,CAClB,GAAI,CAACH,EAAO,MAAM,IAAI,MAAM,mBAAmB,EAC/C,GAAI,CAACG,EAAQ,KAAM,MAAM,IAAI,MAAM,kBAAkB,EACrD,aAAM0I,EAAI,KAAK7I,EAAOG,EAAQ,IAAI,EAClC,MAAM0I,EAAI,SAAS7I,EAAOG,EAAQ,WAAa,OAAO,EAC/C,CAAE,QAAS,GACpB,CAEA,IAAK,aAAc,CACjB,GAAI,CAACH,EAAO,MAAM,IAAI,MAAM,mBAAmB,EAC/C,GAAI,CAACG,EAAQ,KAAM,MAAM,IAAI,MAAM,kBAAkB,EACrD,MAAM6N,EAAmBhF,EAAiBhJ,CAAK,EAC/C,IAAIiO,EAAU,GACd,GAAI9N,EAAQ,IACV,GAAI,EACa,MAAM,OAAO,KAAK,YAAYH,EAAO,CAAE,KAAM,gBAAiB,IAAKG,EAAQ,IAAK,OAAQ,QAAU,CAAE,QAAS6N,EAAkB,GAClI,QAAOC,EAAU,GAC/B,MAAQ,CAAC,CAMX,GAJI,CAACA,GAAW9N,EAAQ,aACtB,MAAM0I,EAAI,MAAM7I,EAAOG,EAAQ,WAAW,CAAC,EAAGA,EAAQ,WAAW,CAAC,EAAG,OAAQ,EAAG,CAAC,EACjF8N,EAAU,IAER,CAACA,EAAS,CACZ,MAAMpL,EAAS,MAAMgG,EAAI,eAAe7I,EAAO;AAAA;AAAA;AAAA;AAAA;AAAA,aAK1C,GACDc,EAAA+B,EAAO,SAAP,MAAA/B,EAAe,QACjB,MAAM+H,EAAI,MAAM7I,EAAO6C,EAAO,OAAO,MAAM,EAAGA,EAAO,OAAO,MAAM,EAAG,OAAQ,EAAG,CAAC,EACjFoL,EAAU,GAEd,CACA,OAAKA,GACL,MAAMpF,EAAI,KAAK7I,EAAOG,EAAQ,IAAI,EAC3B,CAAE,QAAS,KAFG,CAAE,MAAO,+BAGhC,CAEA,IAAK,oBAAqB,CACxB,GAAI,CAACH,EAAO,MAAM,IAAI,MAAM,mBAAmB,EAC/C,GAAI,CAACG,EAAQ,KAAM,MAAM,IAAI,MAAM,kBAAkB,EACrD,MAAM+N,EAAyBlF,EAAiBhJ,CAAK,EACrD,IAAIiO,EAAU,GACd,GAAI9N,EAAQ,IACV,GAAI,EACa,MAAM,OAAO,KAAK,YAAYH,EAAO,CAAE,KAAM,gBAAiB,IAAKG,EAAQ,IAAK,OAAQ,QAAU,CAAE,QAAS+N,EAAwB,GACxI,QAAOD,EAAU,GAC/B,MAAQ,CAAC,CAMX,GAJI,CAACA,GAAW9N,EAAQ,aACtB,MAAM0I,EAAI,MAAM7I,EAAOG,EAAQ,WAAW,CAAC,EAAGA,EAAQ,WAAW,CAAC,EAAG,OAAQ,EAAG,CAAC,EACjF8N,EAAU,IAER,CAACA,EAAS,CACZ,MAAMpL,EAAS,MAAMgG,EAAI,eAAe7I,EAAO;AAAA;AAAA;AAAA;AAAA;AAAA,aAK1C,GACDa,EAAAgC,EAAO,SAAP,MAAAhC,EAAe,QACjB,MAAMgI,EAAI,MAAM7I,EAAO6C,EAAO,OAAO,MAAM,EAAGA,EAAO,OAAO,MAAM,EAAG,OAAQ,EAAG,CAAC,EACjFoL,EAAU,GAEd,CACA,OAAKA,GACL,MAAMpF,EAAI,KAAK7I,EAAOG,EAAQ,IAAI,EAClC,MAAM0I,EAAI,SAAS7I,EAAOG,EAAQ,WAAa,OAAO,EAC/C,CAAE,QAAS,KAHG,CAAE,MAAO,+BAIhC,CAEA,IAAK,gBAAiB,CACpB,GAAI,CAACH,EAAO,MAAM,IAAI,MAAM,mBAAmB,EAC/C,GAAI,CAACG,EAAQ,KAAM,MAAM,IAAI,MAAM,kBAAkB,EAsBrD,MAAM+M,GAAS/K,GArBI,MAAM0G,EAAI,eAAe7I,EAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,WAoB9C,GACqB,SAAX,YAAAmC,EAAmB,MAClC,OAAK+K,GAAA,MAAAA,EAAQ,OACb,MAAMrE,EAAI,MAAM7I,EAAOkN,EAAO,EAAGA,EAAO,EAAG,OAAQ,EAAG,CAAC,EACvD,MAAMrE,EAAI,KAAK7I,EAAOG,EAAQ,IAAI,EAC9BA,EAAQ,QACV,MAAM0I,EAAI,SAAS7I,EAAOG,EAAQ,WAAa,OAAO,EAEjD,CAAE,QAAS,GAAM,YAAa,CAAE,EAAG+M,EAAO,EAAG,EAAGA,EAAO,EAAE,GANrC,CAAE,MAAO,+BAOtC,CAEA,IAAK,sBAAuB,CAC1B,GAAI,CAAClN,EAAO,MAAM,IAAI,MAAM,mBAAmB,EAC/C,GAAI,CAACG,EAAQ,KAAM,MAAM,IAAI,MAAM,kBAAkB,EACrD,MAAMgO,EAAsBnF,EAAiBhJ,CAAK,EAClD,IAAIiO,EAAU,GACd,GAAI9N,EAAQ,IACV,GAAI,EACa,MAAM,OAAO,KAAK,YAAYH,EAAO,CAAE,KAAM,gBAAiB,IAAKG,EAAQ,IAAK,OAAQ,QAAU,CAAE,QAASgO,EAAqB,GACrI,QAAOF,EAAU,GAC/B,MAAQ,CAAC,CAMX,GAJI,CAACA,GAAW9N,EAAQ,aACtB,MAAM0I,EAAI,MAAM7I,EAAOG,EAAQ,WAAW,CAAC,EAAGA,EAAQ,WAAW,CAAC,EAAG,OAAQ,EAAG,CAAC,EACjF8N,EAAU,IAER,CAACA,EAAS,MAAO,CAAE,MAAO,8BAC9B,MAAM,IAAI,QAAQ/L,GAAK,WAAWA,EAAG,GAAG,CAAC,EACzC,MAAM2G,EAAI,KAAK7I,EAAOG,EAAQ,IAAI,EAClC,MAAMiO,EAASjO,EAAQ,QAAU,IAEjC,GADA,MAAM,IAAI,QAAQ+B,GAAK,WAAWA,EAAGkM,CAAM,CAAC,EACxCjO,EAAQ,OAASA,EAAQ,MAAQ,EACnC,QAAS8F,EAAI,EAAGA,EAAI9F,EAAQ,MAAO8F,IACjC,MAAM4C,EAAI,SAAS7I,EAAO,WAAW,EACrC,MAAM,IAAI,QAAQkC,GAAK,WAAWA,EAAG,EAAE,CAAC,EAG5C,aAAM2G,EAAI,SAAS7I,EAAO,OAAO,EAC1B,CAAE,QAAS,GACpB,CAEA,IAAK,kBAAmB,CACtB,GAAI,CAACA,EAAO,MAAM,IAAI,MAAM,mBAAmB,EAC/C,GAAIG,EAAQ,QAAU,OAAW,MAAM,IAAI,MAAM,mBAAmB,EACpE,MAAM8D,EAAW9D,EAAQ,SACnB6M,EAAM7M,EAAQ,IACpB,GAAI,CAAC8D,GAAY,CAAC+I,EAAK,MAAM,IAAI,MAAM,0BAA0B,EAEjE,MAAMqB,EAASrB,EACX;AAAA,+DACqDA,CAAG;AAAA,yGACuCA,CAAG;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qCAMvE,KAAK,UAAU7M,EAAQ,KAAK,CAAC;AAAA;AAAA,2BAEvC,KAAK,UAAUA,EAAQ,KAAK,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA,gBAM9C;AAAA,gDACsC,KAAK,UAAU8D,CAAQ,CAAC;AAAA,+DACT,KAAK,UAAUA,CAAQ,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA,qCAKlD,KAAK,UAAU9D,EAAQ,KAAK,CAAC;AAAA;AAAA,2BAEvC,KAAK,UAAUA,EAAQ,KAAK,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA,gBAQlD,QAAOuC,GADQ,MAAMmG,EAAI,eAAe7I,EAAOqO,CAAM,GACvC,SAAP,YAAA3L,EAAe,QAAS,CAAE,MAAO,gBAC1C,CAEA,IAAK,aAAc,CACjB,GAAI,CAAC1C,EAAO,MAAM,IAAI,MAAM,mBAAmB,EAC/C,KAAM,CAAE,SAAAiE,EAAU,KAAAvD,EAAM,MAAA4N,EAAQ,GAAM,OAAAC,EAAS,IAAUpO,EACzD,GAAI,CAAC8D,EAAU,MAAM,IAAI,MAAM,mBAAmB,EAClD,GAAIvD,IAAS,OAAW,MAAM,IAAI,MAAM,eAAe,EAEvD,MAAM2N,EAAS;AAAA,4CACuB,KAAK,UAAUpK,CAAQ,CAAC;AAAA,2DACT,KAAK,UAAUA,CAAQ,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,cAWrEqK,CAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,iCASc,KAAK,UAAU5N,CAAI,CAAC;AAAA;AAAA,2BAE1B,KAAK,UAAUA,CAAI,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,cAMjC6N,CAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,YAgBd,QAAO5L,GADQ,MAAMkG,EAAI,eAAe7I,EAAOqO,CAAM,GACvC,SAAP,YAAA1L,EAAe,QAAS,CAAE,MAAO,gBAC1C,CAEA,IAAK,gBAAiB,CACpB,GAAI,CAAC3C,EAAO,MAAM,IAAI,MAAM,mBAAmB,EAC/C,MAAMwO,EAAcrO,EAAQ,aAAe,EAC3C,QAAS8F,EAAI,EAAGA,EAAIuI,EAAavI,IAC/B,MAAM4C,EAAI,SAAS7I,EAAO,QAAQ,EAClC,MAAM,IAAI,QAAQkC,GAAK,WAAWA,EAAG,GAAG,CAAC,EAE3C,MAAO,CAAE,QAAS,GACpB,CAEA,IAAK,aAAc,CACjB,GAAI,CAAClC,EAAO,MAAM,IAAI,MAAM,mBAAmB,EAoC/C,QAAO4C,GADa,MAAMiG,EAAI,eAAe7I,EAlCzB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,WAkC2C,GAC5C,SAAZ,YAAA4C,EAAoB,QAAS,CAAE,MAAO,2BAC/C,CAEA,IAAK,iBAAkB,CACrB,GAAI,CAAC5C,EAAO,MAAM,IAAI,MAAM,mBAAmB,EAC/C,MAAMsG,EAASnG,EAAQ,QAAU,EAC3BoG,EAASpG,EAAQ,QAAU,EAEjC,GAAI,CACF,MAAMwD,EAAW,MAAMkF,EAAI,gBAAgB7I,CAAK,EAC1C0F,EAAIvF,EAAQ,GAAKwD,EAAS,MAAQ,EAClCgC,EAAIxF,EAAQ,GAAKwD,EAAS,OAAS,EACzC,MAAMkF,EAAI,OAAO7I,EAAO0F,EAAGC,EAAGW,EAAQC,CAAM,CAC9C,MAAQ,CACN,GAAI,CACF,MAAMkI,EAAiB,CAACC,EAAYC,KAClC,OAAO,SAASD,EAAIC,CAAE,EACf,CAAE,QAAS,OAAO,QAAS,QAAS,OAAO,UAEpD,MAAM,OAAO,UAAU,cAAc,CACnC,OAAQ,CAAE,MAAA3O,CAAA,EACV,KAAMyO,EACN,KAAM,CAACnI,EAAQC,CAAM,EACtB,CACH,MAAQ,CACN,MAAO,CAAE,MAAO,0CAClB,CACF,CACA,MAAO,CAAE,QAAS,GACpB,CAEA,IAAK,cAAe,CAClB,GAAI,CAACvG,EAAO,MAAM,IAAI,MAAM,mBAAmB,EAC/C,MAAMuB,EAAMpB,EAAQ,IACpB,GAAI,CAACoB,EAAK,MAAM,IAAI,MAAM,iBAAiB,EAC3C,OAAIA,EAAI,SAAS,GAAG,EAClB,MAAMsH,EAAI,cAAc7I,EAAOuB,CAAG,EAElC,MAAMsH,EAAI,SAAS7I,EAAOuB,CAAG,EAExB,CAAE,QAAS,GACpB,CAEA,IAAK,mBAAoB,CACvB,GAAI,CAACvB,EAAO,MAAM,IAAI,MAAM,mBAAmB,EAC/C,GAAI,CAACG,EAAQ,IAAK,MAAM,IAAI,MAAM,iBAAiB,EAEnD,MAAMyO,EAAoB,IAAI,QAAerK,GAAY,CACvD8H,EAAoB,IAAIrM,EAAOuE,CAAO,EACtC,WAAW,IAAM,CACX8H,EAAoB,IAAIrM,CAAK,IAC/BqM,EAAoB,OAAOrM,CAAK,EAChCuE,EAAA,EAEJ,EAAG,GAAK,CACV,CAAC,EAED,aAAM,OAAO,KAAK,OAAOvE,EAAO,CAAE,IAAKG,EAAQ,IAAK,EACpD,MAAMyO,EAEN,MAAM,IAAI,QAAQrK,GAAW,WAAWA,EAAS,GAAG,CAAC,EAE9C,CAAE,QAAS,GACpB,CAEA,IAAK,oBAAqB,CACxB,GAAI,CAACvE,EAAO,MAAM,IAAI,MAAM,mBAAmB,EAC/C,OAAO,MAAM6I,EAAI,gBAAgB7I,CAAK,CACxC,CAEA,IAAK,YAAa,CAChB,GAAI,CAACA,EAAO,MAAM,IAAI,MAAM,mBAAmB,EAC/C,MAAM6O,EAAc7F,EAAiBhJ,CAAK,EAC1C,GAAI,CACF,MAAM,OAAO,KAAK,YAAYA,EAAO,CAAE,KAAM,qBAAuB,CAAE,QAAS,EAAG,CACpF,MAAY,CAAC,CACb,MAAM,IAAI,QAAQuE,GAAW,WAAWA,EAAS,EAAE,CAAC,EAEpD,IAAI1B,EACJ,GAAI,CACFA,EAAS,MAAM,OAAO,KAAK,YAAY7C,EAAO,CAC5C,KAAM,8BACN,QAASG,EAAQ,SAAW,EAAC,EAC5B,CAAE,QAAS0O,EAAa,CAC7B,MAAc,CACZ,MAAO,CACL,MAAO,sDACP,YAAa,GACb,SAAU,CAAE,MAAO,EAAG,OAAQ,EAAE,CAEpC,SACE,GAAI,CACF,MAAM,OAAO,KAAK,YAAY7O,EAAO,CAAE,KAAM,sBAAuB,CACtE,MAAY,CAAC,CACf,CAGA,IAAI8O,EAAA3O,EAAQ,UAAR,MAAA2O,EAAiB,YACnB,GAAI,CACF,MAAMC,EAAa,MAAM,OAAO,KAAK,YAAY/O,EAAO,CAAE,KAAM,iBAAmB,CAAE,QAAS6O,EAAa,EACvGE,GAAA,MAAAA,EAAY,OACdlM,EAAO,KAAOkM,EAAW,KAE7B,MAAc,CAEd,CAGF,IAAIC,EAAA7O,EAAQ,UAAR,MAAA6O,EAAiB,kBACnB,GAAI,CACF,MAAMtF,EAAa,MAAMb,EAAI,kBAAkB7I,CAAK,EACpD,MAAO,CAAE,GAAG6C,EAAQ,WAAA6G,CAAA,CACtB,MAAc,CACZ,MAAO,CAAE,GAAG7G,EAAQ,gBAAiB,+BACvC,CAEF,OAAOA,CACT,CAEA,IAAK,0BAA2B,CAC9B,GAAI,CAAC7C,EAAO,MAAM,IAAI,MAAM,mBAAmB,EAC/C,GAAI,CACF,OAAO,MAAM,OAAO,KAAK,YAAYA,EAAO,CAC1C,KAAM,0BACN,IAAKG,EAAQ,KACZ,CAAE,QAAS6I,EAAiBhJ,CAAK,EAAG,CACzC,MAAc,CACZ,MAAO,CAAE,MAAO,sDAClB,CACF,CAEA,IAAK,aAAc,CACjB,GAAI,CAACA,EAAO,MAAM,IAAI,MAAM,mBAAmB,EAC/C,GAAI,CACF,OAAO,MAAM,OAAO,KAAK,YAAYA,EAAO,CAC1C,KAAM,aACN,IAAKG,EAAQ,IACb,MAAOA,EAAQ,OACd,CAAE,QAAS6I,EAAiBhJ,CAAK,EAAG,CACzC,MAAc,CACZ,MAAO,CAAE,MAAO,sDAClB,CACF,CAEA,IAAK,eAAgB,CACnB,GAAI,CAACA,EAAO,MAAM,IAAI,MAAM,mBAAmB,EAC/C,GAAI,CAACG,EAAQ,KAAM,MAAM,IAAI,MAAM,kBAAkB,EACrD,GAAI,CACF,OAAO,MAAM,OAAO,KAAK,YAAYH,EAAO,CAC1C,KAAM,eACN,KAAMG,EAAQ,MACb,CAAE,QAAS6I,EAAiBhJ,CAAK,EAAG,CACzC,MAAc,CACZ,MAAO,CAAE,MAAO,sDAClB,CACF,CAEA,IAAK,oBAAqB,CACxB,GAAI,CAACA,EAAO,MAAM,IAAI,MAAM,mBAAmB,EAC/C,GAAI,CACF,OAAO,MAAM,OAAO,KAAK,YAAYA,EAAO,CAC1C,KAAM,oBACN,IAAKG,EAAQ,KACZ,CAAE,QAAS6I,EAAiBhJ,CAAK,EAAG,CACzC,MAAc,CACZ,MAAO,CAAE,MAAO,sDAClB,CACF,CAEA,IAAK,qBAAsB,CACzB,GAAI,CAACA,EAAO,MAAM,IAAI,MAAM,mBAAmB,EAC/C,MAAMiP,EAAW9O,EAAQ,SACzB,GAAI8O,IAAa,OAAW,MAAM,IAAI,MAAM,gDAAoD,EAChG,MAAMhL,EAAW9D,EAAQ,SAEnB+O,EAAe,CAACC,EAAsBC,IAAuB,CACjE,MAAMC,EAAiB,IACF,CAAC,GAAG,SAAS,iBAAiB,GAAG,CAAC,EAAE,UACrDC,EAAG,aAAeA,EAAG,cAAgBA,EAAG,aAAe,KACvD,KAAK,CAAC3O,EAAE4O,IAAMA,EAAE,aAAe5O,EAAE,YAAY,EAC7B,CAAC,GAAK,SAAS,gBAG7B6O,EAAYJ,GAAM,SAAS,cAAcA,CAAG,GAAKC,EAAA,EACvD,OAAKG,GAEDL,IAAQ,SACVK,EAAU,UAAYA,EAAU,aACvBL,IAAQ,MACjBK,EAAU,UAAY,EACb,OAAOL,GAAQ,WACxBK,EAAU,UAAYL,GAGjB,CACL,UAAWK,EAAU,UACrB,aAAcA,EAAU,aACxB,aAAcA,EAAU,aACxB,SAAUA,EAAU,UAAYA,EAAU,cAAgBA,EAAU,aAAe,GACnF,MAAOA,EAAU,UAAY,KAfR,CAAE,MAAO,gCAiBlC,EAEA,GAAI,CACF,MAAMnB,EAAS,IAAIa,EAAa,UAAU,KAAK,KAAK,UAAUD,CAAQ,CAAC,KAAK,KAAK,UAAUhL,CAAQ,CAAC,IAEpG,QAAOwL,GADQ,MAAM5G,EAAI,eAAe7I,EAAOqO,CAAM,GACvC,SAAP,YAAAoB,EAAe,QAAS,CAAE,MAAO,gBAC1C,MAAQ,CACN,GAAI,CAMF,QAAOC,GALS,MAAM,OAAO,UAAU,cAAc,CACnD,OAAQ,CAAE,MAAA1P,CAAA,EACV,KAAMkP,EACN,KAAM,CAACD,EAAUhL,CAAQ,EAC1B,GACc,CAAC,IAAT,YAAAyL,EAAY,SAAU,CAAE,MAAO,gBACxC,MAAQ,CACN,MAAO,CAAE,MAAO,0CAClB,CACF,CACF,CAEA,IAAK,kBAAmB,CACtB,GAAI,CAAC1P,EAAO,MAAM,IAAI,MAAM,mBAAmB,EAC/C,MAAMiE,EAAW9D,EAAQ,SAEnBwP,EAAoBP,GAAuB,CAC/C,MAAMC,EAAiB,IACF,CAAC,GAAG,SAAS,iBAAiB,GAAG,CAAC,EAAE,UACrDC,EAAG,aAAeA,EAAG,cAAgBA,EAAG,aAAe,KACvD,KAAK,CAAC3O,EAAE4O,IAAMA,EAAE,aAAe5O,EAAE,YAAY,EAC7B,CAAC,GAAK,SAAS,gBAG7B6O,EAAYJ,GAAM,SAAS,cAAcA,CAAG,GAAKC,EAAA,EACvD,GAAI,CAACG,EAAW,MAAO,CAAE,MAAO,iCAEhC,MAAMI,EAAYJ,EAAU,aAAeA,EAAU,aACrD,MAAO,CACL,UAAWA,EAAU,UACrB,aAAcA,EAAU,aACxB,aAAcA,EAAU,aACxB,SAAUA,EAAU,UAAYA,EAAU,cAAgBA,EAAU,aAAe,GACnF,MAAOA,EAAU,UAAY,GAC7B,iBAAkBI,EAAY,EAAI,KAAK,MAAOJ,EAAU,UAAYI,EAAa,GAAG,EAAI,IAE5F,EAEA,GAAI,CACF,MAAMvB,EAAS,IAAIsB,EAAiB,UAAU,KAAK,KAAK,UAAU1L,CAAQ,CAAC,IAE3E,QAAO4L,GADQ,MAAMhH,EAAI,eAAe7I,EAAOqO,CAAM,GACvC,SAAP,YAAAwB,EAAe,QAAS,CAAE,MAAO,gBAC1C,MAAQ,CACN,GAAI,CAMF,QAAOC,GALS,MAAM,OAAO,UAAU,cAAc,CACnD,OAAQ,CAAE,MAAA9P,CAAA,EACV,KAAM2P,EACN,KAAM,CAAC1L,CAAQ,EAChB,GACc,CAAC,IAAT,YAAA6L,EAAY,SAAU,CAAE,MAAO,gBACxC,MAAQ,CACN,MAAO,CAAE,MAAO,mDAClB,CACF,CACF,CAEA,IAAK,gBAAiB,CACpB,GAAI,CAAC9P,EAAO,MAAM,IAAI,MAAM,mBAAmB,EAC/C,GAAI,CACF,OAAO,MAAM,OAAO,KAAK,YAAYA,EAAO,CAAE,KAAM,iBAAmB,CAAE,QAASgJ,EAAiBhJ,CAAK,EAAG,CAC7G,MAAc,CACZ,MAAO,CAAE,MAAO,sDAClB,CACF,CAEA,IAAK,cAAe,CAClB,GAAI,CAACA,EAAO,MAAM,IAAI,MAAM,mBAAmB,EAC/C,GAAI,CAACG,EAAQ,KAAM,MAAM,IAAI,MAAM,eAAe,EAClD,MAAM4P,EAAgB/G,EAAiBhJ,CAAK,EAE5C,GAAI,CACF,MAAM6C,EAAS,MAAM,OAAO,KAAK,YAAY7C,EAAO,CAClD,KAAM,cACN,KAAMG,EAAQ,KACd,KAAMA,EAAQ,KACd,IAAKA,EAAQ,KACZ,CAAE,QAAS4P,EAAe,EAE7B,OAAIlN,EAAO,MAAcA,EAGrB1C,EAAQ,QAAU0C,EAAO,IACpB,MAAMkK,GAAoB/M,EAAO6C,EAAO,IAAK1C,EAAQ,OAAQA,EAAQ,MAAO0I,EAAKkH,CAAa,EAGhGlN,CACT,MAAc,CACZ,MAAO,CAAE,MAAO,sDAClB,CACF,CAEA,IAAK,cAAe,CAClB,GAAI,CAAC7C,EAAO,MAAM,IAAI,MAAM,mBAAmB,EAC/C,GAAI,CAACG,EAAQ,KAAM,MAAM,IAAI,MAAM,eAAe,EAClD,MAAM6P,EAAchH,EAAiBhJ,CAAK,EAE1C,GAAI,CACF,MAAM6C,EAAS,MAAM,OAAO,KAAK,YAAY7C,EAAO,CAClD,KAAM,cACN,KAAMG,EAAQ,KACd,MAAOA,EAAQ,OACd,CAAE,QAAS6P,EAAa,EAE3B,OAAInN,EAAO,MAAcA,EAGrB1C,EAAQ,QAAU0C,EAAO,IACpB,MAAMkK,GAAoB/M,EAAO6C,EAAO,IAAK1C,EAAQ,OAAQA,EAAQ,MAAO0I,EAAKmH,CAAW,EAG9FnN,CACT,MAAc,CACZ,MAAO,CAAE,MAAO,sDAClB,CACF,CAEA,IAAK,eAAgB,CACnB,GAAI,CAAC7C,EAAO,MAAM,IAAI,MAAM,mBAAmB,EAC/C,GAAI,CAACG,EAAQ,MAAO,MAAM,IAAI,MAAM,gBAAgB,EACpD,MAAM8P,EAAejH,EAAiBhJ,CAAK,EAE3C,GAAI,CACF,MAAM6C,EAAS,MAAM,OAAO,KAAK,YAAY7C,EAAO,CAClD,KAAM,eACN,MAAOG,EAAQ,OACd,CAAE,QAAS8P,EAAc,EAE5B,OAAIpN,EAAO,MAAcA,EAGrB1C,EAAQ,QAAU0C,EAAO,IACpB,MAAMkK,GAAoB/M,EAAO6C,EAAO,IAAK1C,EAAQ,OAAQA,EAAQ,MAAO0I,EAAKoH,CAAY,EAG/FpN,CACT,MAAc,CACZ,MAAO,CAAE,MAAO,sDAClB,CACF,CAEA,IAAK,qBAAsB,CACzB,GAAI,CAAC7C,EAAO,MAAM,IAAI,MAAM,mBAAmB,EAC/C,GAAI,CAACG,EAAQ,SAAU,MAAM,IAAI,MAAM,mBAAmB,EAC1D,MAAM+P,EAAgBlH,EAAiBhJ,CAAK,EAE5C,GAAI,CAMF,OALe,MAAM,OAAO,KAAK,YAAYA,EAAO,CAClD,KAAM,qBACN,SAAUG,EAAQ,UACjB,CAAE,QAAS+P,EAAe,CAG/B,MAAc,CACZ,MAAO,CAAE,MAAO,sDAClB,CACF,CAEA,IAAK,gBAAiB,CACpB,GAAI,CAAClQ,EAAO,MAAM,IAAI,MAAM,mBAAmB,EAC/C,GAAI,CAACG,EAAQ,SAAU,MAAM,IAAI,MAAM,mBAAmB,EAC1D,GAAI,CAACA,EAAQ,OAAQ,MAAM,IAAI,MAAM,iBAAiB,EACtD,MAAMgQ,EAAgBnH,EAAiBhJ,CAAK,EAE5C,GAAI,CAQF,OAPe,MAAM,OAAO,KAAK,YAAYA,EAAO,CAClD,KAAM,gBACN,SAAUG,EAAQ,SAClB,OAAQA,EAAQ,OAChB,GAAIA,EAAQ,IAAM,SACjB,CAAE,QAASgQ,EAAe,CAG/B,MAAc,CACZ,MAAO,CAAE,MAAO,sDAClB,CACF,CAEA,IAAK,wBACL,IAAK,wBACL,IAAK,wBACL,IAAK,wBAAyB,CAC5B,GAAI,CAACnQ,EAAO,MAAM,IAAI,MAAM,mBAAmB,EAC/C,GAAI,CACF,OAAO,MAAM,OAAO,KAAK,YAAYA,EAAO,CAAE,KAAMG,EAAQ,KAAM,CACpE,MAAc,CACZ,MAAO,CAAE,MAAO,sDAClB,CACF,CAEA,IAAK,aAAc,CACjB,MAAMiQ,EAAYjQ,EAAQ,UAC1B,IAAIkQ,EAEJ,OAAID,IAAc,iBAAiBE,EAAAnD,EAAO,MAAP,MAAAmD,EAAY,IAC7CD,EAAclD,EAAO,IAAI,GAChB,OAAOiD,GAAc,WAC9BC,EAAcD,GAGZC,GACF,OAAO,QAAQ,YAAY,CAAE,KAAM,aAAc,YAAAA,EAAa,EAEzD,CAAE,QAAS,GACpB,CAEA,IAAK,2BACH,MAAO,CAAE,QAAS,IAGpB,IAAK,6BACH,MAAO,CAAE,QAAS,IAGpB,IAAK,YAAa,CAChB,GAAI,CAACrQ,EAAO,MAAM,IAAI,MAAM,mBAAmB,EAC/C,GAAI,CACF,MAAM6C,EAAS,MAAM,OAAO,KAAK,YAAY7C,EAAO,CAClD,KAAM,gBACN,IAAKG,EAAQ,IACb,OAAQA,EAAQ,QAAU,QACzB,CAAE,QAAS6I,EAAiBhJ,CAAK,EAAG,EACvC,OAAI6C,EAAO,MAAc,CAAE,MAAOA,EAAO,OAClC,CAAE,QAAS,GACpB,MAAc,CACZ,MAAO,CAAE,MAAO,sDAClB,CACF,CAEA,IAAK,YAAa,CAChB,GAAI,CAAC7C,EAAO,MAAM,IAAI,MAAM,mBAAmB,EAC/C,GAAI,CACF,MAAMkN,EAAS,MAAM,OAAO,KAAK,YAAYlN,EAAO,CAClD,KAAM,0BACN,IAAKG,EAAQ,KACZ,CAAE,QAAS6I,EAAiBhJ,CAAK,EAAG,EACvC,OAAIkN,EAAO,MAAc,CAAE,MAAOA,EAAO,QACzC,MAAMrE,EAAI,MAAM7I,EAAOkN,EAAO,EAAGA,EAAO,CAAC,EAClC,CAAE,QAAS,IACpB,MAAc,CACZ,MAAO,CAAE,MAAO,sDAClB,CACF,CAEA,IAAK,OACH,MAAO,CAAE,QAAS,GAAM,OAAQ,aAGlC,IAAK,mBAAoB,CACvB,GAAI,CAAC/M,EAAQ,IAAK,MAAM,IAAI,MAAM,iBAAiB,EACnD,MAAMkE,EAAUlE,EAAQ,SAAW,IAC7BoQ,EAASpQ,EAAQ,QAAU,IAC3BkC,EAAY,KAAK,MACjBmO,EAAe,IAErB,IAAIC,EAA2B,KAC/B,KAAO,KAAK,MAAQpO,EAAYgC,GAAS,CACvC,GAAI,CACF,MAAM7B,EAAW,MAAM,MAAMrC,EAAQ,IAAK,CAAE,OAAQ,MAAO,EAE3D,GADA,MAAMqC,EAAS,OACXA,EAAS,SAAW+N,EACtB,MAAO,CAAE,QAAS,GAAM,OAAQ/N,EAAS,OAAQ,KAAM,KAAK,MAAQH,CAAA,EAEtEoO,EAAY,cAAcjO,EAAS,MAAM,EAC3C,OAASpC,EAAG,CACVqQ,EAAYrQ,aAAa,MAAQA,EAAE,QAAU,OAAOA,CAAC,CACvD,CACA,MAAM,IAAI,QAAS8B,GAAM,WAAWA,EAAGsO,CAAY,CAAC,CACtD,CACA,MAAO,CACL,MAAO,uBAAuBrQ,EAAQ,GAAG,cAAcoQ,CAAM,GAC7D,UAAAE,EACA,KAAM,KAAK,MAAQpO,CAAA,CAEvB,CAEA,IAAK,aAAc,CACjB,MAAMqO,EAAiBvQ,EAAQ,MAAQ,GACjCwQ,EAA8BxQ,EAAQ,WAAa,OACnDyQ,EAAoBzQ,EAAQ,UAAY,GAE9C,GAAIuQ,EAAK,SAAW,EAClB,MAAO,CAAE,MAAO,mCAGlB,MAAMG,EAOD,GAEL,IAAIC,EAAO,EACPC,EAAO,EAEX,UAAWjO,KAAO4N,EAAM,CACtB,MAAMrO,EAAY,KAAK,MACjB2O,EAAmB,GACzB,IAAIC,EACAC,EACAC,EAEJ,GAAI,CACFD,EAAW,IAAI,IAAIpO,CAAG,EAAE,SAAS,QAAQ,kBAAmB,GAAG,EAC/D,MAAMsO,EAAU,MAAM,OAAO,KAAK,OAAO,CAAE,IAAAtO,EAAK,OAAQ,GAAO,EAC/D,GAAI,CAACsO,EAAQ,GAAI,MAAM,IAAI,MAAM,sBAAsB,EACvDD,EAAYC,EAAQ,GAEpB,GAAI,CACF,MAAMvI,EAAI,sBAAsBsI,CAAS,CAC3C,MAAY,CAAC,CAEb,MAAM,IAAI,QAAe5M,GAAY,CACnC,MAAM8M,EAAcnQ,GAAqE,CACnFA,EAAQ,QAAUiQ,GAAajQ,EAAQ,UAAY,IACrD,OAAO,cAAc,YAAY,eAAemQ,CAAU,EAC1D,OAAO,cAAc,gBAAgB,eAAeC,EAAO,EAC3D/M,EAAA,EAEJ,EACM+M,GAAWpQ,GAA0E,CACrFA,EAAQ,QAAUiQ,GAAajQ,EAAQ,UAAY,IACrD,OAAO,cAAc,YAAY,eAAemQ,CAAU,EAC1D,OAAO,cAAc,gBAAgB,eAAeC,EAAO,EAC3DN,EAAO,KAAK,qBAAqB9P,EAAQ,KAAK,EAAE,EAChDqD,EAAA,EAEJ,EACA,OAAO,cAAc,YAAY,YAAY8M,CAAU,EACvD,OAAO,cAAc,gBAAgB,YAAYC,EAAO,EACxD,WAAW,IAAM,CACf,OAAO,cAAc,YAAY,eAAeD,CAAU,EAC1D,OAAO,cAAc,gBAAgB,eAAeC,EAAO,EAC3DN,EAAO,KAAK,0BAA0B,EACtCzM,EAAA,CACF,EAAG,GAAK,CACV,CAAC,EAED,MAAM,IAAI,QAAQrC,GAAK,WAAWA,EAAG,GAAI,CAAC,EAE1C,MAAMqP,GAAkB1I,EAAI,mBAAmBsI,EAAW,CAAE,WAAY,GAAM,MAAO,GAAI,EACzF,UAAWpQ,KAAOwQ,GAChBP,EAAO,KAAK,IAAIjQ,EAAI,IAAI,KAAKA,EAAI,IAAI,EAAE,EAGzC,GAAI4P,EACF,GAAI,CAEFM,GADmB,MAAMpI,EAAI,kBAAkBsI,CAAS,GAC1B,MAChC,MAAY,CAAC,CAEjB,OAAS/Q,EAAG,CACV4Q,EAAO,KAAK5Q,aAAa,MAAQA,EAAE,QAAU,OAAOA,CAAC,CAAC,CACxD,SACE,GAAI+Q,EACF,GAAI,CAAE,MAAM,OAAO,KAAK,OAAOA,CAAS,CAAG,MAAQ,CAAC,CAExD,CAEA,MAAMK,EAAU,KAAK,MAAQnP,EACvBoP,GAAST,EAAO,SAAW,EAAI,OAAS,OAY9C,GAXIS,KAAW,OAAQX,IAClBC,IAELF,EAAQ,KAAK,CACX,IAAA/N,EACA,OAAA2O,GACA,KAAMD,EACN,OAAAR,EACA,GAAIC,GAAoB,CAAE,iBAAAA,EAAkB,SAAAC,CAAA,CAAS,CACtD,EAEGN,GAAYa,KAAW,OACzB,KAEJ,CAEA,MAAO,CACL,QAAAZ,EACA,QAAS,CAAE,KAAAC,EAAM,KAAAC,EAAM,MAAOF,EAAQ,QACtC,SAAU1Q,EAAQ,SAEtB,CAEA,IAAK,mBAAoB,CACvB,GAAI,CAACH,EAAO,MAAM,IAAI,MAAM,mBAAmB,EAC/C,GAAI,CAACG,EAAQ,SAAU,MAAM,IAAI,MAAM,sBAAsB,EAC7D,MAAMuR,EAAc1I,EAAiBhJ,CAAK,EAE1C,GAAI,CACF,MAAM,OAAO,KAAK,YAAYA,EAAO,CAAE,KAAM,qBAAuB,CAAE,QAAS,EAAG,CACpF,MAAY,CAAC,CACb,MAAM,IAAI,QAAQuE,GAAW,WAAWA,EAAS,EAAE,CAAC,EAEpD,GAAI,CAOF,OANe,MAAM,OAAO,KAAK,YAAYvE,EAAO,CAClD,KAAM,mBACN,SAAUG,EAAQ,SAClB,MAAOA,EAAQ,OAAS,UACxB,QAASA,EAAQ,SAAW,KAC3B,CAAE,QAASuR,EAAa,CAE7B,MAAc,CACZ,MAAO,CACL,MAAO,sDACP,YAAa,GACb,SAAU,CAAE,MAAO,EAAG,OAAQ,EAAE,CAEpC,SACE,GAAI,CACF,MAAM,OAAO,KAAK,YAAY1R,EAAO,CAAE,KAAM,sBAAuB,CACtE,MAAY,CAAC,CACf,CACF,CAEA,IAAK,eAAgB,CACnB,GAAI,CAACA,EAAO,MAAM,IAAI,MAAM,mBAAmB,EAC/C,GAAI,CAACG,EAAQ,QAAS,MAAM,IAAI,MAAM,yBAAyB,EAE/D,GAAI,CACF,MAAM,OAAO,KAAK,YAAYH,EAAO,CAAE,KAAM,qBAAuB,CAAE,QAAS,EAAG,CACpF,MAAY,CAAC,CACb,MAAM,IAAI,QAAQuE,GAAW,WAAWA,EAAS,EAAE,CAAC,EAEpD,GAAI,CAMF,OALe,MAAM,OAAO,KAAK,YAAYvE,EAAO,CAClD,KAAM,eACN,QAASG,EAAQ,QACjB,QAASA,EAAQ,SAAW,KAC3B,CAAE,QAAS,EAAG,CAEnB,MAAc,CACZ,MAAO,CACL,MAAO,sDACP,YAAa,GACb,SAAU,CAAE,MAAO,EAAG,OAAQ,EAAE,CAEpC,SACE,GAAI,CACF,MAAM,OAAO,KAAK,YAAYH,EAAO,CAAE,KAAM,sBAAuB,CACtE,MAAY,CAAC,CACf,CACF,CAEA,IAAK,wBAAyB,CAC5B,GAAI,CAACA,EAAO,MAAM,IAAI,MAAM,mBAAmB,EAE/C,GAAI,CACF,MAAM,OAAO,KAAK,YAAYA,EAAO,CAAE,KAAM,qBAAuB,CAAE,QAAS,EAAG,CACpF,MAAY,CAAC,CACb,MAAM,IAAI,QAAQuE,GAAW,WAAWA,EAAS,EAAE,CAAC,EAEpD,GAAI,CAKF,OAJe,MAAM,OAAO,KAAK,YAAYvE,EAAO,CAClD,KAAM,wBACN,QAASG,EAAQ,SAAW,KAC3B,CAAE,QAAS,EAAG,CAEnB,MAAc,CACZ,MAAO,CACL,MAAO,sDACP,YAAa,GACb,SAAU,CAAE,MAAO,EAAG,OAAQ,EAAE,CAEpC,SACE,GAAI,CACF,MAAM,OAAO,KAAK,YAAYH,EAAO,CAAE,KAAM,sBAAuB,CACtE,MAAY,CAAC,CACf,CACF,CAEA,IAAK,sBAAuB,CAC1B,GAAI,CAACA,EAAO,MAAM,IAAI,MAAM,mBAAmB,EAE/C,GAAI,CACF,MAAM,OAAO,KAAK,YAAYA,EAAO,CAAE,KAAM,qBAAuB,CAAE,QAAS,EAAG,CACpF,MAAY,CAAC,CACb,MAAM,IAAI,QAAQuE,GAAW,WAAWA,EAAS,EAAE,CAAC,EAEpD,GAAI,CAMF,OALe,MAAM,OAAO,KAAK,YAAYvE,EAAO,CAClD,KAAM,sBACN,OAAQG,EAAQ,QAAU,IAC1B,QAASA,EAAQ,SAAW,KAC3B,CAAE,QAAS,EAAG,CAEnB,MAAc,CACZ,MAAO,CACL,MAAO,sDACP,YAAa,GACb,SAAU,CAAE,MAAO,EAAG,OAAQ,EAAE,CAEpC,SACE,GAAI,CACF,MAAM,OAAO,KAAK,YAAYH,EAAO,CAAE,KAAM,uBAAyB,CAAE,QAAS,EAAG,CACtF,MAAY,CAAC,CACf,CACF,CAEA,IAAK,gBAAiB,CACpB,GAAI,CAACA,EAAO,MAAM,IAAI,MAAM,mBAAmB,EAE/C,OADe,MAAM6I,EAAI,aAAa7I,EAAO,GAAMG,EAAQ,IAAI,CAEjE,CAEA,IAAK,iBAAkB,CACrB,GAAI,CAACH,EAAO,MAAM,IAAI,MAAM,mBAAmB,EAE/C,OADe,MAAM6I,EAAI,aAAa7I,EAAO,EAAK,CAEpD,CAEA,IAAK,cAAe,CAClB,GAAI,CAACA,EAAO,MAAM,IAAI,MAAM,mBAAmB,EAC/C,MAAM2R,EAAS9I,EAAI,cAAc7I,CAAK,EACtC,OAAK2R,EAGE,CACL,UAAW,GACX,KAAMA,EAAO,KACb,QAASA,EAAO,QAChB,cAAeA,EAAO,eANf,CAAE,UAAW,GAQxB,CAEA,IAAK,kBAAmB,CACtB,GAAI,CAAC3R,EAAO,MAAM,IAAI,MAAM,mBAAmB,EAC/C,GAAI,CAACG,EAAQ,OAAQ,MAAM,IAAI,MAAM,oBAAoB,EACzD,MAAM0C,EAAS,MAAMgG,EAAI,eAAe7I,EAAOG,EAAQ,MAAM,EAC7D,GAAI,CAAC0C,EAAO,cAAe,IAAI,MAAMA,EAAO,KAAK,EACjD,MAAO,CAAE,QAAS,GAAM,OAAQ1C,EAAQ,OAC1C,CAEA,IAAK,cAAe,CAClB,GAAI,CAACH,EAAO,MAAM,IAAI,MAAM,mBAAmB,EAC/C,GAAIG,EAAQ,OAAS,OAAW,MAAM,IAAI,MAAM,kBAAkB,EAClE,MAAM0C,EAAS,MAAMgG,EAAI,WAAW7I,EAAOG,EAAQ,IAAI,EACvD,GAAI,CAAC0C,EAAO,cAAe,IAAI,MAAMA,EAAO,KAAK,EACjD,MAAO,CAAE,QAAS,GAAM,KAAM1C,EAAQ,KACxC,CAEA,IAAK,cAAe,CAClB,GAAI,CAACH,EAAO,MAAM,IAAI,MAAM,mBAAmB,EAC/C,GAAIG,EAAQ,MAAO,CACjB,MAAM0C,EAAS,MAAMgG,EAAI,iBAAiB7I,CAAK,EAC/C,GAAI,CAAC6C,EAAO,cAAe,IAAI,MAAMA,EAAO,KAAK,EACjD,MAAO,CAAE,QAAS,GAAM,QAAS,GACnC,CACA,GAAI1C,EAAQ,WAAa,QAAaA,EAAQ,YAAc,OAC1D,MAAM,IAAI,MAAM,iCAAiC,EAEnD,MAAM0C,EAAS,MAAMgG,EAAI,mBAAmB7I,EAAOG,EAAQ,SAAUA,EAAQ,UAAWA,EAAQ,QAAQ,EACxG,GAAI,CAAC0C,EAAO,cAAe,IAAI,MAAMA,EAAO,KAAK,EACjD,MAAO,CAAE,QAAS,GAAM,SAAU1C,EAAQ,SAAU,UAAWA,EAAQ,UACzE,CAEA,IAAK,sBASH,MAAO,CAAE,QAPO,CACd,YAAa,YAAa,YAAa,gBAAiB,oBAAqB,YAC7E,OAAQ,WAAY,YACpB,UAAW,UAAW,UAAW,cACjC,aAAc,aAAc,aAAc,gBAC1C,WAAY,eAEL,EAGX,IAAK,iBAAkB,CACrB,GAAI,CAACH,EAAO,MAAM,IAAI,MAAM,mBAAmB,EAC/C,MAAM4R,EAAazR,EAAQ,OAG3B,GAAIyR,EAAW,gBAAkB,QAAS,CACxC,MAAM/O,EAAS,MAAMgG,EAAI,qBAAqB7I,CAAK,EACnD,GAAI,CAAC6C,EAAO,cAAe,IAAI,MAAMA,EAAO,KAAK,EACjD,MAAO,CAAE,QAAS,GAAM,QAAS,yBACnC,CAGA,MAAMM,EAA4I,CAEhJ,YAAa,CAAE,MAAO,IAAK,OAAQ,IAAK,kBAAmB,EAAG,OAAQ,GAAM,MAAO,GAAM,UAAW,2IACpG,YAAa,CAAE,MAAO,IAAK,OAAQ,IAAK,kBAAmB,EAAG,OAAQ,GAAM,MAAO,GAAM,UAAW,2IACpG,YAAa,CAAE,MAAO,IAAK,OAAQ,IAAK,kBAAmB,EAAG,OAAQ,GAAM,MAAO,GAAM,UAAW,2IACpG,gBAAiB,CAAE,MAAO,IAAK,OAAQ,IAAK,kBAAmB,EAAG,OAAQ,GAAM,MAAO,GAAM,UAAW,2IACxG,oBAAqB,CAAE,MAAO,IAAK,OAAQ,IAAK,kBAAmB,EAAG,OAAQ,GAAM,MAAO,GAAM,UAAW,2IAC5G,YAAa,CAAE,MAAO,IAAK,OAAQ,IAAK,kBAAmB,EAAG,OAAQ,GAAM,MAAO,GAAM,UAAW,2IACpG,KAAQ,CAAE,MAAO,IAAK,OAAQ,KAAM,kBAAmB,EAAG,OAAQ,GAAM,MAAO,GAAM,UAAW,kIAChG,WAAY,CAAE,MAAO,KAAM,OAAQ,KAAM,kBAAmB,EAAG,OAAQ,GAAM,MAAO,GAAM,UAAW,kIACrG,YAAa,CAAE,MAAO,IAAK,OAAQ,KAAM,kBAAmB,EAAG,OAAQ,GAAM,MAAO,GAAM,UAAW,kIAErG,UAAW,CAAE,MAAO,IAAK,OAAQ,IAAK,kBAAmB,KAAM,OAAQ,GAAM,MAAO,GAAM,UAAW,4HACrG,UAAW,CAAE,MAAO,IAAK,OAAQ,IAAK,kBAAmB,MAAO,OAAQ,GAAM,MAAO,GAAM,UAAW,4HACtG,UAAW,CAAE,MAAO,IAAK,OAAQ,IAAK,kBAAmB,MAAO,OAAQ,GAAM,MAAO,GAAM,UAAW,yHACtG,cAAe,CAAE,MAAO,IAAK,OAAQ,IAAK,kBAAmB,IAAK,OAAQ,GAAM,MAAO,GAAM,UAAW,6HAExG,aAAc,CAAE,MAAO,IAAK,OAAQ,IAAK,kBAAmB,EAAG,OAAQ,GAAM,MAAO,GAAM,UAAW,8HACrG,aAAc,CAAE,MAAO,IAAK,OAAQ,IAAK,kBAAmB,EAAG,OAAQ,GAAM,MAAO,GAAM,UAAW,+HACrG,aAAc,CAAE,MAAO,IAAK,OAAQ,IAAK,kBAAmB,EAAG,OAAQ,GAAM,MAAO,GAAM,UAAW,0HACrG,gBAAiB,CAAE,MAAO,IAAK,OAAQ,KAAM,kBAAmB,EAAG,OAAQ,GAAM,MAAO,GAAM,UAAW,qHAEzG,WAAY,CAAE,MAAO,KAAM,OAAQ,IAAK,kBAAmB,EAAG,OAAQ,GAAO,MAAO,GAAM,UAAW,4HACrG,eAAgB,CAAE,MAAO,KAAM,OAAQ,IAAK,kBAAmB,EAAG,OAAQ,GAAO,MAAO,GAAM,UAAW,2HAA2H,EAKtO,IAAIM,EAAmCN,EAAQyO,CAAU,EACzD,GAAI,CAACnO,EAAQ,CACX,MAAMoO,EAAYD,EAAW,cAC7B,IAAIE,EAA2D,KAE/D,SAAW,CAACtF,EAAMtJ,CAAM,IAAK,OAAO,QAAQC,CAAO,EAAG,CACpD,MAAM4O,EAAcvF,EAAK,cACnBwF,EAAiBD,EAAY,QAAQ,OAAQ,EAAE,GAGjDA,EAAY,SAASF,CAAS,GAAKA,EAAU,SAASG,CAAc,KAElE,CAACF,GAAatF,EAAK,OAASsF,EAAU,KAAK,UAC7CA,EAAY,CAAE,KAAAtF,EAAM,OAAAtJ,CAAA,EAG1B,CAEI4O,IACFrO,EAASqO,EAAU,OAEvB,CAEA,GAAI,CAACrO,EACH,MAAM,IAAI,MAAM,mBAAmBmO,CAAU,wCAAwC,EAGvF,MAAM/O,EAAS,MAAMgG,EAAI,cAAc7I,EAAOyD,CAAM,EACpD,GAAI,CAACZ,EAAO,cAAe,IAAI,MAAMA,EAAO,KAAK,EACjD,MAAO,CAAE,QAAS,GAAM,OAAQ+O,CAAA,CAClC,CAEA,IAAK,mBAAoB,CACvB,GAAI,CAAC5R,EAAO,MAAM,IAAI,MAAM,mBAAmB,EAC/C,GAAI,CAACG,EAAQ,OAAS,CAACA,EAAQ,OAC7B,MAAM,IAAI,MAAM,8BAA8B,EAEhD,MAAM0C,EAAS,MAAMgG,EAAI,gBAAgB7I,EAAO,CAC9C,MAAOG,EAAQ,MACf,OAAQA,EAAQ,OAChB,kBAAmBA,EAAQ,kBAC3B,OAAQA,EAAQ,OACjB,EACD,GAAI,CAAC0C,EAAO,cAAe,IAAI,MAAMA,EAAO,KAAK,EACjD,MAAO,CAAE,QAAS,GAAM,MAAO1C,EAAQ,MAAO,OAAQA,EAAQ,OAChE,CAEA,IAAK,gBAAiB,CACpB,GAAI,CAACH,EAAO,MAAM,IAAI,MAAM,mBAAmB,EAC/C,MAAM6C,EAAS,MAAMgG,EAAI,aAAa7I,EAAOG,EAAQ,OAAO,EAC5D,GAAI,CAAC0C,EAAO,cAAe,IAAI,MAAMA,EAAO,KAAK,EACjD,MAAO,CAAE,QAAS,GAAM,QAAS1C,EAAQ,QAC3C,CAEA,IAAK,YAAa,CAChB,GAAI,CAACH,EAAO,MAAM,IAAI,MAAM,mBAAmB,EAC/C,GAAI,CAACG,EAAQ,KAAM,MAAM,IAAI,MAAM,kBAAkB,EAKrD,OAJiB,MAAM,OAAO,KAAK,YAAYH,EAAO,CACpD,KAAM,YACN,KAAMG,EAAQ,MACb,CAAE,QAAS6I,EAAiBhJ,CAAK,EAAG,CAEzC,CAEA,IAAK,aAAc,CACjB,GAAI,CAACA,EAAO,MAAM,IAAI,MAAM,mBAAmB,EAC/C,MAAM6C,EAAS,MAAMgG,EAAI,sBAAsB7I,EAAOG,EAAQ,UAAU,EACxE,GAAI,CAAC0C,EAAO,cAAe,IAAI,MAAMA,EAAO,KAAK,EACjD,MAAO,CAAE,QAAS,GAAM,QAAS,8BACnC,CAEA,IAAK,YAAa,CAChB,GAAI,CAAC7C,EAAO,MAAM,IAAI,MAAM,mBAAmB,EAC/C,MAAM6C,EAAS,MAAMgG,EAAI,qBAAqB7I,CAAK,EACnD,GAAI,CAAC6C,EAAO,cAAe,IAAI,MAAMA,EAAO,KAAK,EACjD,MAAO,CAAE,QAAS,GAAM,QAASA,EAAO,QAC1C,CAEA,IAAK,eAAgB,CACnB,GAAI,CAAC7C,EAAO,MAAM,IAAI,MAAM,mBAAmB,EAC/C,MAAM6C,EAAS,MAAMgG,EAAI,sBAAsB7I,CAAK,EACpD,GAAI,CAAC6C,EAAO,cAAe,IAAI,MAAMA,EAAO,KAAK,EACjD,MAAO,CAAE,QAAS,GAAM,QAASA,EAAO,QAC1C,CAEA,IAAK,cAAe,CAClB,GAAI,CAAC7C,EAAO,MAAM,IAAI,MAAM,mBAAmB,EAC/C,GAAI,CAACG,EAAQ,IAAK,MAAM,IAAI,MAAM,iBAAiB,EACnD,GAAI,CAACA,EAAQ,OAAS,CAACA,EAAQ,MAAM,OAAQ,MAAM,IAAI,MAAM,mBAAmB,EAChF,MAAM8R,EAAiB,MAAM,OAAO,KAAK,YAAYjS,EAAO,CAC1D,KAAM,0BACN,IAAKG,EAAQ,KACZ,CAAE,QAAS6I,EAAiBhJ,CAAK,EAAG,EACvC,GAAIiS,EAAe,MAAO,MAAM,IAAI,MAAMA,EAAe,KAAK,EAC9D,MAAMC,EAAY,MAAMrJ,EAAI,uBAAuB7I,EAAOiS,EAAe,SAAU9R,EAAQ,KAAK,EAChG,GAAI,CAAC+R,EAAU,cAAe,IAAI,MAAMA,EAAU,KAAK,EACvD,MAAO,CAAE,QAAS,GAAM,SAAU/R,EAAQ,MAAM,OAClD,CAEA,IAAK,gBAAiB,CACpB,GAAI,CAACH,EAAO,MAAM,IAAI,MAAM,mBAAmB,EAC/C,MAAM6C,EAAS,MAAMgG,EAAI,YAAY7I,EAAOG,EAAQ,SAAW,GAAK,EACpE,GAAI,CAAC0C,EAAO,cAAe,IAAI,MAAMA,EAAO,KAAK,EACjD,MAAO,CAAE,QAAS,GAAM,WAAYA,EAAO,WAC7C,CAEA,IAAK,aAAc,CACjB,GAAI,CAAC7C,EAAO,MAAM,IAAI,MAAM,mBAAmB,EAC/C,MAAM6C,EAAS,MAAMgG,EAAI,UAAU7I,CAAK,EACxC,GAAI,CAAC6C,EAAO,cAAe,IAAI,MAAMA,EAAO,KAAK,EACjD,MAAO,CAAE,QAAS,GAAM,OAAQA,EAAO,OACzC,CAEA,IAAK,eAAgB,CACnB,GAAI,CAAC7C,EAAO,MAAM,IAAI,MAAM,mBAAmB,EAC/C,KAAM,CAAE,SAAAiE,EAAU,KAAAuI,EAAM,MAAA2F,CAAA,EAAUhS,EAElC,GAAI,CAAC8D,GAAY,CAACuI,GAAQ2F,IAAU,OAClC,MAAM,IAAI,MAAM,yCAAyC,EAI3D,MAAMC,EAAe,MAAM,OAAO,cAAc,aAAa,CAAE,MAAApS,EAAO,EACtE,GAAI,CAACoS,GAAgBA,EAAa,SAAW,EAC3C,MAAM,IAAI,MAAM,wBAAwB,EAI1C,MAAMC,EAAcD,EAAa,OAAOE,GAAKA,EAAE,UAAY,CAAC,EAE5D,GAAID,EAAY,SAAW,EACzB,MAAM,IAAI,MAAM,+BAA+B,EAGjD,IAAIE,EAAoE,KAExE,GAAIJ,IAAU,OAAW,CACvB,GAAIA,EAAQ,GAAKA,GAASE,EAAY,OACpC,MAAM,IAAI,MAAM,eAAeF,CAAK,wBAAwBE,EAAY,MAAM,YAAY,EAE5FE,EAAcF,EAAYF,CAAK,CACjC,SAAW3F,EAAM,CAEf,UAAW9H,KAAS2N,EAClB,GAAI,CACF,MAAMxP,EAAS,MAAM,OAAO,KAAK,YAAY7C,EAAO,CAClD,KAAM,kBACL,CAAE,QAAS0E,EAAM,QAAS,EAC7B,IAAI7B,GAAA,YAAAA,EAAQ,QAAS2J,EAAM,CACzB+F,EAAc7N,EACd,KACF,CACF,MAAQ,CAER,CAEF,GAAI,CAAC6N,EACH,MAAM,IAAI,MAAM,oBAAoB/F,CAAI,aAAa,CAEzD,SAAWvI,EAET,GAAI,CACF,MAAMgO,EAAiB,MAAM,OAAO,KAAK,YAAYjS,EAAO,CAC1D,KAAM,wBACN,SAAAiE,CAAA,EACC,CAAE,QAAS,EAAG,EAEjB,GAAIgO,GAAA,MAAAA,EAAgB,MAAO,MAAM,IAAI,MAAMA,EAAe,KAAK,EAG3DA,GAAA,MAAAA,EAAgB,MAClBM,EAAcF,EAAY,KAAKC,GAAKA,EAAE,MAAQL,EAAe,GAAG,GAAK,MAInE,CAACM,GAAeF,EAAY,SAAW,IACzCE,EAAcF,EAAY,CAAC,EAE/B,MAAY,CACV,MAAM,IAAI,MAAM,uCAAuCpO,CAAQ,GAAG,CACpE,CAGF,GAAI,CAACsO,EACH,MAAM,IAAI,MAAM,iBAAiB,EAInC,OAAAxJ,EAAc,IAAI/I,EAAOuS,EAAY,OAAO,EAErC,CACL,QAAS,GACT,QAASA,EAAY,QACrB,IAAKA,EAAY,IAErB,CAEA,IAAK,aAAc,CACjB,GAAI,CAACvS,EAAO,MAAM,IAAI,MAAM,mBAAmB,EAG/C,OAAA+I,EAAc,OAAO/I,CAAK,EAEnB,CAAE,QAAS,GAAM,QAAS,yBACnC,CAEA,IAAK,oBAAqB,CACxB,GAAI,CAACA,EAAO,MAAM,IAAI,MAAM,mBAAmB,EAC/C,GAAI,CAACG,EAAQ,QAAS,MAAM,IAAI,MAAM,qBAAqB,EAC3D,GAAI,CAACA,EAAQ,KAAM,MAAM,IAAI,MAAM,kBAAkB,EACrD,MAAM0C,EAAS,MAAMgG,EAAI,gBAAgB7I,EAAOG,EAAQ,QAASA,EAAQ,IAAI,EAC7E,GAAI,CAAC0C,EAAO,cAAe,IAAI,MAAMA,EAAO,KAAK,EACjD,MAAO,CAAE,MAAOA,EAAO,OACzB,CAEA,IAAK,qBAAsB,CACzB,GAAI,CAAC7C,EAAO,MAAM,IAAI,MAAM,mBAAmB,EAC/C,GAAI,CAACG,EAAQ,KAAM,MAAM,IAAI,MAAM,kBAAkB,EAErD,GAAI,CAEF,MAAM0I,EAAI,eAAe7I,EADH,4mFACuB,EAG7C,MAAM8E,EAAa,gCADH3E,EAAQ,KAAK,QAAQ,KAAM,KAAK,EAAE,QAAQ,MAAO,KAAK,CACZ,QAEpD0C,EAAS,MAAMgG,EAAI,eAAe7I,EAAO8E,CAAU,EAEzD,GAAIjC,EAAO,iBAIT,MAAO,CAAE,QAHG2P,EAAA3P,EAAO,iBAAiB,YAAxB,YAAA2P,EAAmC,cACnC3P,EAAO,iBAAiB,MACxB,yBACI,EAGlB,MAAMrB,GAAQiR,EAAA5P,EAAO,SAAP,YAAA4P,EAAe,MACvBC,EAASlR,IAAU,OAAY,YAAc,KAAK,UAAUA,EAAO,KAAM,CAAC,EAChF,MAAO,CAAE,QAAQkR,GAAA,YAAAA,EAAQ,UAAU,EAAG,OAAU,YAClD,OAASxS,EAAK,CACZ,MAAMa,EAAMb,aAAe,MAAQA,EAAI,QAAU,0BACjD,OAAIa,EAAI,SAAS,eAAe,GAAKA,EAAI,SAAS,eAAe,EACxD,CAAE,MAAO,2DAEX,CAAE,MAAOA,CAAA,CAClB,CACF,CAEA,IAAK,wBAAyB,CAC5B,GAAI,CAACf,EAAO,MAAM,IAAI,MAAM,mBAAmB,EAE/C,GAAI,CACF,MAAM6I,EAAI,sBAAsB7I,CAAK,CACvC,MAAY,CAAC,CAEb,MAAMS,EAAWoI,EAAI,mBAAmB7I,EAAO,CAC7C,WAAYG,EAAQ,WACpB,QAASA,EAAQ,QACjB,MAAOA,EAAQ,OAAS,IACzB,EAED,OAAIA,EAAQ,OACV0I,EAAI,qBAAqB7I,CAAK,EAGzB,CAAE,SAAAS,CAAA,CACX,CAEA,IAAK,yBAA0B,CAC7B,GAAI,CAACT,EAAO,MAAM,IAAI,MAAM,mBAAmB,EAC/C,OAAA6I,EAAI,qBAAqB7I,CAAK,EACvB,CAAE,QAAS,GACpB,CAEA,IAAK,wBAAyB,CAC5B,GAAI,CAACA,EAAO,MAAM,IAAI,MAAM,mBAAmB,EAE/C,GAAI,CACF,MAAM6I,EAAI,sBAAsB7I,CAAK,CACvC,MAAY,CAAC,CAGb,GAAIG,EAAQ,KAAM,CAChB,IAAI+E,EAAU2D,EAAI,kBAAkB7I,EAAO,CACzC,WAAYG,EAAQ,WACrB,EAGGA,EAAQ,SACV+E,EAAUA,EAAQ,OAAO9E,GAAKA,EAAE,SAAWD,EAAQ,MAAM,GAEvDA,EAAQ,SACV+E,EAAUA,EAAQ,OAAO9E,GAAKA,EAAE,SAAWD,EAAQ,MAAM,GAEvDA,EAAQ,cACV+E,EAAUA,EAAQ,OAAO9E,GAAKA,EAAE,OAASD,EAAQ,WAAW,GAG1DA,EAAQ,OACV0I,EAAI,qBAAqB7I,CAAK,EAIhC,MAAM2S,EAAQxS,EAAQ,OAAS,IAC/B,MAAO,CACL,QAAS+E,EAAQ,MAAM,EAAGyN,CAAK,EAC/B,OAAQxS,EAAQ,OAChB,QAASA,EAAQ,QAErB,CAEA,IAAIgB,EAAW0H,EAAI,mBAAmB7I,EAAO,CAC3C,WAAYG,EAAQ,WACpB,MAAOA,EAAQ,OAAS,IACzB,EAGD,OAAIA,EAAQ,SACVgB,EAAWA,EAAS,OAAOe,GAAKA,EAAE,SAAW/B,EAAQ,MAAM,GAEzDA,EAAQ,SACVgB,EAAWA,EAAS,OAAOe,GAAKA,EAAE,SAAW/B,EAAQ,MAAM,GAEzDA,EAAQ,cACVgB,EAAWA,EAAS,OAAOe,GAAKA,EAAE,OAAS/B,EAAQ,WAAW,GAG5DA,EAAQ,OACV0I,EAAI,qBAAqB7I,CAAK,EAGzB,CACL,SAAAmB,EACA,OAAQhB,EAAQ,OAChB,QAASA,EAAQ,QAErB,CAEA,IAAK,yBAA0B,CAC7B,GAAI,CAACH,EAAO,MAAM,IAAI,MAAM,mBAAmB,EAC/C,OAAA6I,EAAI,qBAAqB7I,CAAK,EACvB,CAAE,QAAS,GACpB,CAEA,IAAK,sBAAuB,CAC1B,GAAI,CAACA,EAAO,MAAM,IAAI,MAAM,mBAAmB,EAE/C,GAAI,CACF,MAAM6I,EAAI,sBAAsB7I,CAAK,CACvC,MAAY,CAAC,CAEb,IAAIkF,EAAU2D,EAAI,kBAAkB7I,EAAO,CACzC,WAAYG,EAAQ,WACpB,cAAe,CAACA,EAAQ,cACzB,EAGD,OAAIA,EAAQ,SACV+E,EAAUA,EAAQ,OAAO9E,GAAKA,EAAE,SAAWD,EAAQ,MAAM,GAEvDA,EAAQ,SACV+E,EAAUA,EAAQ,OAAO9E,GAAKA,EAAE,SAAWD,EAAQ,MAAM,GAEvDA,EAAQ,SACV+E,EAAUA,EAAQ,OAAO9E,GAAKA,EAAE,SAAWD,EAAQ,MAAM,GAEvDA,EAAQ,OACV+E,EAAUA,EAAQ,OAAO9E,GAAKA,EAAE,OAASD,EAAQ,IAAI,GAEnDA,EAAQ,QACV+E,EAAUA,EAAQ,OAAO9E,GAAKA,EAAE,IAAMD,EAAQ,KAAK,GAEjDA,EAAQ,UAAY,SACtB+E,EAAUA,EAAQ,OAAO9E,GAAKD,EAAQ,QAAWC,EAAE,kBAAoBA,EAAE,iBAAmB,EAAK,CAACA,EAAE,gBAAgB,GAElHD,EAAQ,OACV+E,EAAUA,EAAQ,MAAM,CAAC/E,EAAQ,IAAI,GAGnCA,EAAQ,OACV0I,EAAI,qBAAqB7I,CAAK,EAGzB,CAAE,QAAAkF,CAAA,CACX,CAEA,IAAK,oBAAqB,CACxB,GAAI,CAAClF,EAAO,MAAM,IAAI,MAAM,mBAAmB,EAC/C,GAAI,CAACG,EAAQ,UAAW,MAAM,IAAI,MAAM,uBAAuB,EAG/D,IAAI4B,EAAQ8G,EAAI,gBAAgB7I,EAAOG,EAAQ,SAAS,EAcxD,OAXK4B,IAEHA,EADgB8G,EAAI,kBAAkB7I,EAAO,EAAE,EAC/B,KAAKI,GAAKA,EAAE,KAAOD,EAAQ,SAAS,GAAK,MAItD4B,IAEHA,EADgB8G,EAAI,kBAAkB7I,EAAO,EAAE,EAC/B,KAAKI,GAAKA,EAAE,aAAeD,EAAQ,SAAS,GAAK,MAG9D4B,EAGE,CAAE,MAAAA,CAAA,EAFA,CAAE,MAAO,oBAAoB5B,EAAQ,SAAS,GAGzD,CAEA,IAAK,oBAAqB,CACxB,GAAI,CAACH,EAAO,MAAM,IAAI,MAAM,mBAAmB,EAC/C,GAAI,CAACG,EAAQ,UAAW,MAAM,IAAI,MAAM,uBAAuB,EAG/D,IAAIyS,EAAezS,EAAQ,UAC3B,GAAIA,EAAQ,UAAU,WAAW,IAAI,EAAG,CAEtC,MAAM4B,EADU8G,EAAI,kBAAkB7I,EAAO,EAAE,EACzB,QAAUI,EAAE,KAAOD,EAAQ,SAAS,EACtD4B,IACF6Q,EAAe7Q,EAAM,WAEzB,CAGA,OADe,MAAM8G,EAAI,gBAAgB7I,EAAO4S,CAAY,CAE9D,CAEA,IAAK,sBAAuB,CAC1B,GAAI,CAAC5S,EAAO,MAAM,IAAI,MAAM,mBAAmB,EAE/C,MAAMkF,EAAU2D,EAAI,kBAAkB7I,EAAO,EAAE,EACzC6S,EAA6E,GAEnF,UAAW9Q,KAASmD,EACb2N,EAAQ9Q,EAAM,MAAM,IACvB8Q,EAAQ9Q,EAAM,MAAM,EAAI,CAAE,MAAO,EAAG,SAAU,EAAG,KAAM,IAEzD8Q,EAAQ9Q,EAAM,MAAM,EAAE,QACtB8Q,EAAQ9Q,EAAM,MAAM,EAAE,SAAW,KAAK,IAAI8Q,EAAQ9Q,EAAM,MAAM,EAAE,SAAUA,EAAM,EAAE,EAClF8Q,EAAQ9Q,EAAM,MAAM,EAAE,MAASA,EAAM,kBAAoB,EAG3D,MAAO,CAAE,QAAA8Q,CAAA,CACX,CAEA,IAAK,oBAAqB,CACxB,GAAI,CAAC7S,EAAO,MAAM,IAAI,MAAM,mBAAmB,EAE/C,MAAMkF,EAAU2D,EAAI,kBAAkB7I,EAAO,EAAE,EACzC6S,EAAkC,GAClCC,EAAmC,GACnCC,EAAmC,GACzC,IAAIC,EAAY,EACZC,EAAc,IACdC,EAAc,EAElB,UAAWnR,KAASmD,EAAS,CAEtB2N,EAAQ9Q,EAAM,MAAM,IACvB8Q,EAAQ9Q,EAAM,MAAM,EAAI,GAE1B8Q,EAAQ9Q,EAAM,MAAM,IAGpB,MAAMzB,EAASyB,EAAM,QAAU,MAI/B,GAHA+Q,EAASxS,CAAM,GAAKwS,EAASxS,CAAM,GAAK,GAAK,EAGzCyB,EAAM,OAAQ,CAChB,MAAMoR,EAAc,GAAG,KAAK,MAAMpR,EAAM,OAAS,GAAG,CAAC,KACrDgR,EAASI,CAAW,GAAKJ,EAASI,CAAW,GAAK,GAAK,CACzD,CAGAH,GAAcjR,EAAM,kBAAoB,EAGpCA,EAAM,GAAKkR,IAAaA,EAAclR,EAAM,IAC5CA,EAAM,GAAKmR,IAAaA,EAAcnR,EAAM,GAClD,CAEA,MAAO,CACL,MAAO,CACL,cAAemD,EAAQ,OACvB,UAAA8N,EACA,cAAe,OAAO,KAAKH,CAAO,EAAE,OACpC,UAAWI,IAAgB,IAAW,KAAOA,EAC7C,SAAWC,GAAeD,IAAgB,IAAYC,EAAcD,EAAc,EAClF,SAAAH,EACA,SAAAC,CAAA,CACF,CAEJ,CAEA,IAAK,gBAAiB,CACpB,GAAI,CAAC/S,EAAO,MAAM,IAAI,MAAM,mBAAmB,EAC/C,GAAI,CAACG,EAAQ,OAAS,CAACA,EAAQ,OAAQ,MAAM,IAAI,MAAM,2BAA2B,EAElF,MAAMmN,EAAM,MAAM,OAAO,KAAK,IAAItN,CAAK,EACvC,GAAI,CAACsN,EAAI,SAAU,MAAM,IAAI,MAAM,mBAAmB,EAEtD,aAAM,OAAO,QAAQ,OAAOA,EAAI,SAAU,CACxC,MAAO,KAAK,MAAMnN,EAAQ,KAAK,EAC/B,OAAQ,KAAK,MAAMA,EAAQ,MAAM,EAClC,EAEM,CAAE,QAAS,GAAM,MAAOA,EAAQ,MAAO,OAAQA,EAAQ,OAChE,CAEA,IAAK,cAAe,CAClB,MAAMiT,EAAYpT,EAAQ,MAAM,OAAO,KAAK,IAAIA,CAAK,EAAI,KAEnDqT,EAAS,MAAM,OAAO,KAAK,OAAO,CACtC,IAAKlT,EAAQ,KAAO,cACpB,OAAQ,GACT,EAED,GAAI,CAACkT,EAAO,GAAI,MAAM,IAAI,MAAM,sBAAsB,EAEtD,OAAID,GAAA,MAAAA,EAAW,SAAWA,EAAU,UAAY,OAAO,UAAU,mBAC/D,MAAM,OAAO,KAAK,MAAM,CAAE,OAAQC,EAAO,GAAI,QAASD,EAAU,QAAS,EAGpE,CACL,QAAS,GACT,MAAOC,EAAO,GACd,IAAKA,EAAO,KAAOlT,EAAQ,KAAO,cAEtC,CAEA,IAAK,eAAgB,CACnB,GAAI,CAACH,EAAO,MAAM,IAAI,MAAM,mBAAmB,EAC/C,GAAI,CAACG,EAAQ,aAAc,MAAM,IAAI,MAAM,uBAAuB,EAClE,GAAI,CAACA,EAAQ,KAAO,CAACA,EAAQ,WAAY,MAAM,IAAI,MAAM,4BAA4B,EAErF,MAAMuJ,EAAaH,GAAcpJ,EAAQ,YAAY,EACrD,GAAI,CAACuJ,EAAY,MAAM,IAAI,MAAM,yBAAyBvJ,EAAQ,YAAY,EAAE,EAEhF,GAAI,CASF,OARe,MAAM,OAAO,KAAK,YAAYH,EAAO,CAClD,KAAM,eACN,OAAQ0J,EAAW,OACnB,IAAKvJ,EAAQ,IACb,WAAYA,EAAQ,WACpB,SAAUA,EAAQ,UAAY,kBAC7B,CAAE,QAAS6I,EAAiBhJ,CAAK,EAAG,CAGzC,MAAc,CACZ,MAAO,CAAE,MAAO,sDAClB,CACF,CAEA,IAAK,WAEH,MAAO,CACL,MAFW,MAAM,OAAO,KAAK,MAAM,EAAE,GAE1B,IAAKsT,IAAO,CAAE,GAAIA,EAAE,GAAI,MAAOA,EAAE,MAAO,IAAKA,EAAE,KAAM,GAIpE,IAAK,YAAa,CAChB,MAAMC,EAAsC,GAE5C,OAAIpT,EAAQ,WACVoT,EAAa,SAAWpT,EAAQ,UAG3B,CACL,MAFW,MAAM,OAAO,KAAK,MAAMoT,CAAY,GAEpC,IAAKD,IAAO,CACrB,GAAIA,EAAE,GACN,MAAOA,EAAE,MACT,IAAKA,EAAE,IACP,OAAQA,EAAE,OACV,SAAUA,EAAE,UACZ,EAEN,CAEA,IAAK,UAAW,CACd,MAAM5C,EAAOvQ,EAAQ,OAASA,EAAQ,IAAM,CAACA,EAAQ,GAAG,EAAI,CAAC,aAAa,GACpEqT,EAAc,GACpB,QAASvN,EAAI,EAAGA,EAAIyK,EAAK,OAAQzK,IAAK,CACpC,MAAMwN,EAA8C,CAClD,IAAK/C,EAAKzK,CAAC,EACX,OAAQA,IAAM,GAGZ9F,EAAQ,WACVsT,EAAc,SAAWtT,EAAQ,UAEnC,MAAMkT,EAAS,MAAM,OAAO,KAAK,OAAOI,CAAa,EACjDJ,EAAO,IAAIG,EAAY,KAAK,CAAE,MAAOH,EAAO,GAAI,IAAK3C,EAAKzK,CAAC,EAAG,CACpE,CACA,OAAIuN,EAAY,SAAW,EAClB,CAAE,QAAS,GAAM,MAAOA,EAAY,CAAC,EAAE,MAAO,IAAKA,EAAY,CAAC,EAAE,KAEpE,CAAE,QAAS,GAAM,KAAMA,CAAA,CAChC,CAEA,IAAK,aAAc,CACjB,MAAMnD,EAAclQ,EAAQ,MAC5B,GAAI,CAACkQ,EAAa,MAAM,IAAI,MAAM,mBAAmB,EACrD,MAAM/C,EAAM,MAAM,OAAO,KAAK,OAAO+C,EAAa,CAAE,OAAQ,GAAM,EAClE,OAAI/C,EAAI,UACN,MAAM,OAAO,QAAQ,OAAOA,EAAI,SAAU,CAAE,QAAS,GAAM,EAEtD,CAAE,QAAS,GAAM,MAAO+C,EAAa,IAAK/C,EAAI,IAAK,MAAOA,EAAI,MACvE,CAEA,IAAK,YAAa,CAChB,MAAMoG,EAASvT,EAAQ,SAAWA,EAAQ,MAAQ,CAACA,EAAQ,KAAK,EAAI,IACpE,GAAIuT,EAAO,SAAW,EAAG,MAAM,IAAI,MAAM,sBAAsB,EAE/D,OADA,MAAM,OAAO,KAAK,OAAOA,CAAM,EAC3BA,EAAO,SAAW,EACb,CAAE,QAAS,GAAM,MAAOA,EAAO,CAAC,GAElC,CAAE,QAAS,GAAM,OAAQA,CAAA,CAClC,CAEA,IAAK,gBAAiB,CACpB,GAAI,CAAC1T,EAAO,MAAM,IAAI,MAAM,mBAAmB,EAC/C,GAAI,CAACG,EAAQ,KAAM,MAAM,IAAI,MAAM,kBAAkB,EACrD,OAAAmM,EAAgB,IAAInM,EAAQ,KAAMH,CAAK,EAChC,CAAE,QAAS,GAAM,KAAMG,EAAQ,KAAM,MAAAH,CAAA,CAC9C,CAEA,IAAK,mBAAoB,CACvB,GAAI,CAACG,EAAQ,KAAM,MAAM,IAAI,MAAM,kBAAkB,EACrD,MAAMwT,EAAkBrH,EAAgB,IAAInM,EAAQ,IAAI,EACxD,GAAI,CAACwT,EACH,MAAO,CAAE,MAAO,gCAAgCxT,EAAQ,IAAI,KAE9D,GAAI,CACF,MAAMmN,EAAM,MAAM,OAAO,KAAK,IAAIqG,CAAe,EACjD,MAAO,CAAE,MAAOA,EAAiB,IAAKrG,EAAI,IAAK,MAAOA,EAAI,MAC5D,MAAY,CACV,OAAAhB,EAAgB,OAAOnM,EAAQ,IAAI,EAC5B,CAAE,MAAO,QAAQA,EAAQ,IAAI,qBACtC,CACF,CAEA,IAAK,kBAAmB,CACtB,MAAMyT,EAA6E,GACnF,SAAW,CAACpH,EAAM9D,CAAE,IAAK4D,EACvB,GAAI,CACF,MAAMgB,EAAM,MAAM,OAAO,KAAK,IAAI5E,CAAE,EACpCkL,EAAU,KAAK,CAAE,KAAApH,EAAM,MAAO9D,EAAI,IAAK4E,EAAI,IAAK,MAAOA,EAAI,MAAO,CACpE,MAAY,CACVhB,EAAgB,OAAOE,CAAI,CAC7B,CAEF,MAAO,CAAE,KAAMoH,CAAA,CACjB,CAEA,IAAK,kBAAmB,CACtB,GAAI,CAACzT,EAAQ,KAAM,MAAM,IAAI,MAAM,kBAAkB,EAErD,OADgBmM,EAAgB,OAAOnM,EAAQ,IAAI,EAI5C,CAAE,QAAS,IAFT,CAAE,QAAS,GAAO,MAAO,gCAAgCA,EAAQ,IAAI,IAGhF,CAEA,IAAK,WAAY,CACf,KAAM,CAAE,iBAAAqI,CAAA,EAAqB,MAAAqL,GAAA,iCAAArL,CAAA,QAAM,2BAAAsL,EAAA,EAA+B,wBAAAtL,CAAA,WAClE,GAAI,CAEF,OADe,MAAMA,EAAiB,CAAE,KAAM,WAAY,CAE5D,MAAc,CACZ,MAAO,CACL,KAAM,KACN,KAAM,sEAEV,CACF,CAEA,IAAK,qBAAsB,CACzB,KAAM,CAAE,iBAAAA,CAAA,EAAqB,MAAAqL,GAAA,iCAAArL,CAAA,QAAM,2BAAAsL,EAAA,EAA+B,wBAAAtL,CAAA,WAClE,GAAI,CACF,aAAMA,EAAiB,CACrB,KAAM,cACN,SAAUrI,EAAQ,SAClB,IAAKA,EAAQ,IACb,OAAQA,EAAQ,OAChB,QAASA,EAAQ,QACjB,KAAMA,EAAQ,KACf,EACM,CAAE,KAAM,GACjB,OAASD,EAAK,CACZ,MAAO,CAAE,MAAOA,aAAe,MAAQA,EAAI,QAAU,gBACvD,CACF,CAEA,IAAK,iBAAkB,CACrB,GAAI,CAACF,EAAO,MAAM,IAAI,MAAM,mBAAmB,EAC/C,MAAMqF,EAAWlF,EAAQ,SAEzB,GAAI,CACF,aAAM0I,EAAI,sBAAsB7I,CAAK,EACrC8I,EAAiB,IAAIzD,EAAUrF,CAAK,EAEpC6I,EAAI,mBAAmB7I,EAAOqF,EAAW0O,GAAU,CACjDpL,EAAiB,CACf,KAAM,eACN,SAAAtD,EACA,MAAO,CACL,KAAM,gBACN,MAAO0O,EAAM,OAAS,YAAc,QAAUA,EAAM,KACpD,KAAMA,EAAM,KACZ,UAAWA,EAAM,UACjB,IAAKA,EAAM,IACX,KAAMA,EAAM,KACd,CACD,CACH,CAAC,EAEM,CAAE,QAAS,GAAM,UAAW,GACrC,OAAS7T,EAAK,CACZ,OAAAyI,EAAiB,CACf,KAAM,eACN,SAAAtD,EACA,MAAOnF,aAAe,MAAQA,EAAI,QAAU,iCAC7C,EACM,CAAE,MAAOA,aAAe,MAAQA,EAAI,QAAU,iCACvD,CACF,CAEA,IAAK,iBAAkB,CACrB,GAAI,CAACF,EAAO,MAAM,IAAI,MAAM,mBAAmB,EAC/C,MAAMqF,EAAWlF,EAAQ,SAEzB,GAAI,CACF,aAAM0I,EAAI,sBAAsB7I,CAAK,EACrC8I,EAAiB,IAAIzD,EAAUrF,CAAK,EAEpC6I,EAAI,mBAAmB7I,EAAOqF,EAAW0O,GAAU,CACjDpL,EAAiB,CACf,KAAM,eACN,SAAAtD,EACA,MAAO,CACL,KAAM,gBACN,OAAQ0O,EAAM,OACd,IAAKA,EAAM,IACX,OAAQA,EAAM,OACd,SAAUA,EAAM,SAChB,UAAWA,EAAM,UACnB,CACD,CACH,CAAC,EAEM,CAAE,QAAS,GAAM,UAAW,GACrC,OAAS7T,EAAK,CACZ,OAAAyI,EAAiB,CACf,KAAM,eACN,SAAAtD,EACA,MAAOnF,aAAe,MAAQA,EAAI,QAAU,iCAC7C,EACM,CAAE,MAAOA,aAAe,MAAQA,EAAI,QAAU,iCACvD,CACF,CAEA,IAAK,cAAe,CAClB,MAAMmF,EAAWlF,EAAQ,SACnBsM,EAAc3D,EAAiB,IAAIzD,CAAQ,EAEjD,OAAIoH,IAAgB,SAClB5D,EAAI,uBAAuB4D,EAAapH,CAAQ,EAChDwD,EAAI,uBAAuB4D,EAAapH,CAAQ,EAChDyD,EAAiB,OAAOzD,CAAQ,GAG3B,CAAE,QAAS,GACpB,CAEA,IAAK,cAAe,CAClB,GAAI,CAACrF,EAAO,MAAM,IAAI,MAAM,mBAAmB,EAC/C,GAAI,CAACG,EAAQ,KAAM,MAAM,IAAI,MAAM,sBAAsB,EACzD,GAAI,CAOF,OANe,MAAM,OAAO,KAAK,YAAYH,EAAO,CAClD,KAAM,cACN,KAAMG,EAAQ,KACd,cAAeA,EAAQ,eAAiB,GACxC,MAAOA,EAAQ,OAAS,IACvB,CAAE,QAAS6I,EAAiBhJ,CAAK,EAAG,CAEzC,MAAQ,CACN,MAAO,CAAE,MAAO,sDAClB,CACF,CAEA,IAAK,mBAAoB,CACvB,MAAM0T,EAAS,CAAC,GAAIvT,EAAQ,QAAU,EAAG,EACnCqM,EAAOrM,EAAQ,MAAQ,OAEvBiK,EADc,CAAC,OAAQ,OAAQ,MAAO,SAAU,QAAS,OAAQ,SAAU,OAAQ,QAAQ,EACvE,SAASjK,EAAQ,KAAK,EAAIA,EAAQ,MAAQ,OAMpE,GAJIuT,EAAO,SAAW,GAAK1T,GACzB0T,EAAO,KAAK1T,CAAK,EAGf0T,EAAO,SAAW,EAAG,MAAM,IAAI,MAAM,mBAAmB,EAE5D,MAAMM,EAAiB,MAAM,OAAO,UAAU,MAAM,CAAE,MAAOxH,EAAM,EACnE,IAAIyH,EAEJ,OAAID,EAAe,OAAS,GAC1BC,EAAUD,EAAe,CAAC,EAAE,GAC5B,MAAM,OAAO,KAAK,MAAM,CAAE,OAAAN,EAAQ,QAAAO,EAAS,IAE3CA,EAAU,MAAM,OAAO,KAAK,MAAM,CAAE,OAAAP,EAAQ,EAC5C,MAAM,OAAO,UAAU,OAAOO,EAAS,CACrC,MAAOzH,EACP,MAAApC,EACA,UAAW,GACZ,GAGI,CAAE,QAAS,GAAM,QAAA6J,EAAS,KAAAzH,EAAM,OAAAkH,CAAA,CACzC,CAEA,IAAK,mBAAoB,CACvB,MAAMA,EAAS,CAAC,GAAIvT,EAAQ,QAAU,EAAG,EAKzC,GAJIuT,EAAO,SAAW,GAAK1T,GACzB0T,EAAO,KAAK1T,CAAK,EAGf0T,EAAO,SAAW,EAAG,MAAM,IAAI,MAAM,mBAAmB,EAE5D,aAAM,OAAO,KAAK,QAAQA,CAAM,EACzB,CAAE,QAAS,GAAM,UAAWA,CAAA,CACrC,CAEA,IAAK,kBAAmB,CACtB,MAAMQ,EAAS,MAAM,OAAO,UAAU,MAAM,EAAE,EACxCrR,EAAS,GAEf,UAAWsR,KAASD,EAAQ,CAC1B,MAAME,EAAO,MAAM,OAAO,KAAK,MAAM,CAAE,QAASD,EAAM,GAAI,EAC1DtR,EAAO,KAAK,CACV,GAAIsR,EAAM,GACV,KAAMA,EAAM,OAAS,YACrB,MAAOA,EAAM,MACb,UAAWA,EAAM,UACjB,KAAMC,EAAK,IAAId,IAAM,CAAE,GAAIA,EAAE,GAAI,MAAOA,EAAE,MAAO,IAAKA,EAAE,KAAM,EAC/D,CACH,CAEA,MAAO,CAAE,OAAQzQ,CAAA,CACnB,CAEA,IAAK,iBAAkB,CACrB,GAAI,CAAC7C,EAAO,MAAM,IAAI,MAAM,mBAAmB,EAC/C,MAAMiE,EAAW9D,EAAQ,SACnBgS,EAAQhS,EAAQ,OAAS,EAEzBkO,EAAS;AAAA,qDACgC,KAAK,UAAUpK,CAAQ,CAAC;AAAA;AAAA,cAE/DkO,CAAK,mDAAmDA,CAAK;AAAA;AAAA,8BAE7CA,CAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,YAUvBjF,GAASmH,GADA,MAAMxL,EAAI,eAAe7I,EAAOqO,CAAM,GAC/B,SAAP,YAAAgG,EAAe,MAE9B,OAAInH,GAAA,MAAAA,EAAQ,MAAc,CAAE,MAAOA,EAAO,OACrCA,GAEL,MAAMrE,EAAI,MAAM7I,EAAOkN,EAAO,EAAGA,EAAO,EAAG,OAAQ,EAAG,CAAC,EAChD,CAAE,QAAS,GAAM,SAAAjJ,EAAU,MAAAkO,EAAO,WAAYjF,EAAO,QAHxC,CAAE,MAAO,oCAI/B,CAEA,IAAK,cAAe,CAClB,GAAI,CAAClN,EAAO,MAAM,IAAI,MAAM,mBAAmB,EAE/C,MAAM8C,GADM,MAAM,OAAO,KAAK,IAAI9C,CAAK,GACvB,IAChB,GAAI,CAAC8C,EAAK,MAAM,IAAI,MAAM,gBAAgB,EAE1C,MAAO,CAAE,QADO,MAAM,OAAO,QAAQ,OAAO,CAAE,IAAAA,EAAK,CAC1C,CACX,CAEA,IAAK,aAAc,CACjB,GAAI,CAAC9C,EAAO,MAAM,IAAI,MAAM,mBAAmB,EAE/C,MAAM8C,GADM,MAAM,OAAO,KAAK,IAAI9C,CAAK,GACvB,IAChB,GAAI,CAAC8C,EAAK,MAAM,IAAI,MAAM,gBAAgB,EAC1C,GAAI,CAAC3C,EAAQ,KAAM,MAAM,IAAI,MAAM,sBAAsB,EACzD,MAAMmU,EAAS,MAAM,OAAO,QAAQ,IAAI,CAAE,IAAAxR,EAAK,KAAM3C,EAAQ,KAAM,EACnE,OAAKmU,EACE,CAAE,OAAAA,CAAA,EADW,CAAE,MAAO,WAAWnU,EAAQ,IAAI,cAEtD,CAEA,IAAK,aAAc,CACjB,GAAI,CAACH,EAAO,MAAM,IAAI,MAAM,mBAAmB,EAE/C,MAAM8C,GADM,MAAM,OAAO,KAAK,IAAI9C,CAAK,GACvB,IAChB,GAAI,CAAC8C,EAAK,MAAM,IAAI,MAAM,gBAAgB,EAC1C,GAAI,CAAC3C,EAAQ,KAAM,MAAM,IAAI,MAAM,sBAAsB,EACzD,GAAIA,EAAQ,QAAU,OAAW,MAAM,IAAI,MAAM,uBAAuB,EAExE,MAAMoU,EAA2C,CAC/C,IAAAzR,EACA,KAAM3C,EAAQ,KACd,MAAOA,EAAQ,OAGjB,GAAIA,EAAQ,QAAS,CACnB,MAAMqU,EAAiB,IAAI,KAAKrU,EAAQ,OAAO,EAAE,UAAY,IAC7D,GAAI,MAAMqU,CAAc,EACtB,MAAM,IAAI,MAAM,4BAA4BrU,EAAQ,OAAO,EAAE,EAE/DoU,EAAc,eAAiBC,CACjC,CAGA,MAAO,CAAE,QAAS,GAAM,OADT,MAAM,OAAO,QAAQ,IAAID,CAAa,CACrB,CAClC,CAEA,IAAK,eAAgB,CACnB,GAAI,CAACvU,EAAO,MAAM,IAAI,MAAM,mBAAmB,EAE/C,MAAM8C,GADM,MAAM,OAAO,KAAK,IAAI9C,CAAK,GACvB,IAChB,GAAI,CAAC8C,EAAK,MAAM,IAAI,MAAM,gBAAgB,EAC1C,GAAI,CAAC3C,EAAQ,KAAM,MAAM,IAAI,MAAM,sBAAsB,EAEzD,aAAM,OAAO,QAAQ,OAAO,CAAE,IAAA2C,EAAK,KAAM3C,EAAQ,KAAM,EAChD,CAAE,QAAS,GAAM,QAASA,EAAQ,KAC3C,CAEA,IAAK,mBAAoB,CACvB,GAAI,CAACH,EAAO,MAAM,IAAI,MAAM,mBAAmB,EAE/C,MAAM8C,GADM,MAAM,OAAO,KAAK,IAAI9C,CAAK,GACvB,IAChB,GAAI,CAAC8C,EAAK,MAAM,IAAI,MAAM,gBAAgB,EAE1C,MAAM2R,EAAU,MAAM,OAAO,QAAQ,OAAO,CAAE,IAAA3R,EAAK,EACnD,UAAWwR,KAAUG,EACnB,MAAM,OAAO,QAAQ,OAAO,CAAE,IAAA3R,EAAK,KAAMwR,EAAO,KAAM,EAExD,MAAO,CAAE,QAAS,GAAM,QAASG,EAAQ,OAC3C,CAEA,IAAK,aAAc,CACjB,GAAI,CAACzU,EAAO,MAAM,IAAI,MAAM,mBAAmB,EAC/C,aAAM,OAAO,KAAK,OAAOA,EAAO,CAAE,YAAaG,EAAQ,MAAQ,GAAO,EAC/D,CAAE,QAAS,GACpB,CAEA,IAAK,WAAY,CACf,GAAI,CAACH,EAAO,MAAM,IAAI,MAAM,mBAAmB,EAE/C,MAAO,CAAE,KADI,MAAM,OAAO,KAAK,QAAQA,CAAK,CACnC,CACX,CAEA,IAAK,WAAY,CACf,GAAI,CAACA,EAAO,MAAM,IAAI,MAAM,mBAAmB,EAC/C,MAAM0U,EAAQvU,EAAQ,MACtB,GAAIuU,EAAQ,KAAQA,EAAQ,EAAG,MAAM,IAAI,MAAM,uCAAuC,EACtF,aAAM,OAAO,KAAK,QAAQ1U,EAAO0U,CAAK,EAC/B,CAAE,QAAS,GAAM,KAAMA,CAAA,CAChC,CAEA,IAAK,aAAc,CACjB,GAAI,CAAC1U,EAAO,MAAM,IAAI,MAAM,mBAAmB,EAC/C,aAAM,OAAO,KAAK,QAAQA,EAAO,CAAC,EAC3B,CAAE,QAAS,GAAM,KAAM,EAChC,CAEA,IAAK,eAAgB,CACnB,GAAI,CAACA,EAAO,MAAM,IAAI,MAAM,mBAAmB,EAC/C,MAAMsN,EAAM,MAAM,OAAO,KAAK,IAAItN,CAAK,EACjC2U,EAAkE,CACtE,MAAOrH,EAAI,OAAS,WACpB,IAAKA,EAAI,KAEX,GAAInN,EAAQ,OAAQ,CAElB,MAAMyU,GADS,MAAM,OAAO,UAAU,OAAO,CAAE,MAAOzU,EAAQ,OAAQ,GAChD,KAAKoP,GAAK,CAACA,EAAE,GAAG,EAClCqF,IACFD,EAAY,SAAWC,EAAO,GAElC,CACA,MAAMC,EAAW,MAAM,OAAO,UAAU,OAAOF,CAAW,EAC1D,MAAO,CAAE,QAAS,GAAM,SAAU,CAAE,GAAIE,EAAS,GAAI,MAAOA,EAAS,MAAO,IAAKA,EAAS,IAAI,CAChG,CAEA,IAAK,kBAAmB,CACtB,GAAI,CAAC7U,EAAO,MAAM,IAAI,MAAM,mBAAmB,EAC/C,MAAMsN,EAAM,MAAM,OAAO,KAAK,IAAItN,CAAK,EACvC,GAAI,CAACsN,EAAI,IAAK,MAAM,IAAI,MAAM,gBAAgB,EAC9C,MAAMwH,EAAY,MAAM,OAAO,UAAU,OAAO,CAAE,IAAKxH,EAAI,IAAK,EAChE,GAAIwH,EAAU,SAAW,EAAG,MAAM,IAAI,MAAM,gCAAgC,EAC5E,aAAM,OAAO,UAAU,OAAOA,EAAU,CAAC,EAAE,EAAE,EACtC,CAAE,QAAS,GACpB,CAEA,IAAK,gBAAiB,CACpB,MAAMnC,EAAQ,OAAOxS,EAAQ,OAAU,SAAWA,EAAQ,MAAQ,GAClE,IAAI2U,EAAiD,GAErD,GAAI3U,EAAQ,OAAQ,CAElB,MAAMyU,GADS,MAAM,OAAO,UAAU,OAAO,CAAE,MAAOzU,EAAQ,OAAQ,GAChD,KAAKoP,GAAK,CAACA,EAAE,GAAG,EAClCqF,IAEFE,GADiB,MAAM,OAAO,UAAU,YAAYF,EAAO,EAAE,GACxC,OAAOrF,GAAKA,EAAE,GAAG,EAAE,MAAM,EAAGoD,CAAK,EAE1D,MAEEmC,EADe,MAAM,OAAO,UAAU,UAAUnC,CAAK,EAIvD,MAAO,CACL,UAAWmC,EAAU,IAAIvF,IAAM,CAC7B,GAAIA,EAAE,GACN,MAAOA,EAAE,MACT,IAAKA,EAAE,IACP,UAAWA,EAAE,WACb,EAEN,CAEA,IAAK,eAAgB,CACnB,MAAMoD,EAAQ,OAAOxS,EAAQ,OAAU,SAAWA,EAAQ,MAAQ,GAMlE,MAAO,CACL,SANY,MAAM,OAAO,QAAQ,OAAO,CACxC,KAAM,GACN,WAAYwS,EACZ,UAAW,EACZ,GAEgB,IAAIrI,IAAM,CACvB,IAAKA,EAAE,IACP,MAAOA,EAAE,MACT,cAAeA,EAAE,cACjB,WAAYA,EAAE,YACd,EAEN,CAEA,IAAK,iBAAkB,CACrB,MAAMyK,EAAQ5U,EAAQ,MAChBwS,EAAQ,OAAOxS,EAAQ,OAAU,SAAWA,EAAQ,MAAQ,GAMlE,MAAO,CACL,SANY,MAAM,OAAO,QAAQ,OAAO,CACxC,KAAM4U,EACN,WAAYpC,EACZ,UAAW,EACZ,GAEgB,IAAI,IAAM,CACvB,IAAK,EAAE,IACP,MAAO,EAAE,MACT,cAAe,EAAE,cACjB,WAAY,EAAE,YACd,EAEN,CAEA,IAAK,sBAAuB,CAC1B,MAAM8B,EAAU,MAAM,OAAO,QAAQ,OAAO,CAAE,OAAQ,eAAgB,EAChEO,EAAgB,MAAM,OAAO,QAAQ,OAAO,CAAE,OAAQ,cAAe,EAC3E,MAAO,CAAE,QAAS,CAAC,GAAGP,EAAS,GAAGO,CAAa,EACjD,CAEA,IAAK,kBAAmB,CACtB,MAAM1H,EAAM,MAAM,OAAO,KAAK,OAAO,CACnC,IAAK,uBACL,OAAQ,GACT,EACD,GAAI,CAACA,EAAI,GAAI,MAAM,IAAI,MAAM,sBAAsB,EAEnD,OADmB,MAAM,OAAO,KAAK,IAAIA,EAAI,EAAE,GAChC,SAAW,YACxB,MAAM,IAAI,QAAe/I,GAAY,CACnC,MAAM0Q,EAAW,CAACjV,EAAekV,IAAoC,CAC/DlV,IAAUsN,EAAI,IAAM4H,EAAK,SAAW,aACtC,OAAO,KAAK,UAAU,eAAeD,CAAQ,EAC7C1Q,EAAA,EAEJ,EACA,OAAO,KAAK,UAAU,YAAY0Q,CAAQ,EAC1C,WAAW,IAAM,CACf,OAAO,KAAK,UAAU,eAAeA,CAAQ,EAC7C1Q,EAAA,CACF,EAAG,GAAK,CACV,CAAC,EAEH,MAAMsE,EAAI,OAAOyE,EAAI,EAAE,EAEvB,MAAMZ,GAAoBY,EAAI,GAAI,GAAK,EAChC,CAAE,MAAOA,EAAI,GACtB,CAEA,IAAK,oBAAqB,CACxB,MAAM6H,EAAYhV,EAAQ,MAC1B,GAAIgV,EAAW,CACb,GAAI,CACF,MAAMtM,EAAI,OAAOsM,CAAS,CAC5B,MAAQ,CAAC,CACT,GAAI,CACF,MAAM,OAAO,KAAK,OAAOA,CAAS,CACpC,MAAQ,CAAC,CACX,CACA,MAAO,CAAE,QAAS,GACpB,CAEA,IAAK,sBAAuB,CAC1B,KAAM,CAAE,OAAA7U,EAAQ,OAAAC,CAAA,EAAWJ,EAE3B,OADe,MAAM0I,EAAI,YAAY1I,EAAQ,MAAOG,EAAQC,GAAU,EAAE,CAE1E,CAEA,IAAK,mBAEH,OADe,MAAMsI,EAAI,eAAe1I,EAAQ,MAAOA,EAAQ,UAAU,EAI3E,IAAK,qBAAsB,CACzB,MAAMmN,EAAM,MAAM,OAAO,KAAK,OAAO,CACnC,IAAK,6BACL,OAAQ,GACT,EACD,GAAI,CAACA,EAAI,GAAI,MAAM,IAAI,MAAM,sBAAsB,EAEnD,OADmB,MAAM,OAAO,KAAK,IAAIA,EAAI,EAAE,GAChC,SAAW,YACxB,MAAM,IAAI,QAAe/I,GAAY,CACnC,MAAM0Q,EAAW,CAACjV,EAAekV,IAAoC,CAC/DlV,IAAUsN,EAAI,IAAM4H,EAAK,SAAW,aACtC,OAAO,KAAK,UAAU,eAAeD,CAAQ,EAC7C1Q,EAAA,EAEJ,EACA,OAAO,KAAK,UAAU,YAAY0Q,CAAQ,EAC1C,WAAW,IAAM,CACf,OAAO,KAAK,UAAU,eAAeA,CAAQ,EAC7C1Q,EAAA,CACF,EAAG,GAAK,CACV,CAAC,EAEH,MAAMsE,EAAI,OAAOyE,EAAI,EAAE,EAEvB,MAAMZ,GAAoBY,EAAI,GAAI,GAAK,EAChC,CAAE,MAAOA,EAAI,GACtB,CAEA,IAAK,uBAAwB,CAC3B,MAAM8H,EAAYjV,EAAQ,MAC1B,GAAIiV,EAAW,CACb,GAAI,CACF,MAAMvM,EAAI,OAAOuM,CAAS,CAC5B,MAAQ,CAAC,CACT,GAAI,CACF,MAAM,OAAO,KAAK,OAAOA,CAAS,CACpC,MAAQ,CAAC,CACX,CACA,MAAO,CAAE,QAAS,GACpB,CAEA,IAAK,yBAA0B,CAC7B,KAAM,CAAE,OAAA9U,EAAQ,OAAAC,CAAA,EAAWJ,EAE3B,OADe,MAAM0I,EAAI,YAAY1I,EAAQ,MAAOG,EAAQC,GAAU,EAAE,CAE1E,CAEA,IAAK,sBAEH,OADe,MAAMsI,EAAI,eAAe1I,EAAQ,MAAOA,EAAQ,UAAU,EAI3E,IAAK,sBAAuB,CAE1B,MAAMkV,EAAU,CAAC,SAAU,eAAgB,QAAS,aAAa,EAC3DC,EAAsC,GAE5C,UAAWC,KAAUF,EACnB,GAAI,CACF,MAAMZ,EAAU,MAAM,OAAO,QAAQ,OAAO,CAAE,OAAAc,EAAQ,EACtDD,EAAW,KAAK,GAAGb,CAAO,CAC5B,MAAQ,CAAC,CAIX,MAAM/D,EAAO,CAAC,gBAAiB,qBAAqB,EACpD,UAAW5N,KAAO4N,EAChB,GAAI,CACF,MAAM+D,EAAU,MAAM,OAAO,QAAQ,OAAO,CAAE,IAAA3R,EAAK,EACnDwS,EAAW,KAAK,GAAGb,CAAO,CAC5B,MAAQ,CAAC,CAIX,MAAMe,MAAW,IACjB,UAAWlB,KAAUgB,GAEf,CADaE,EAAK,IAAIlB,EAAO,IAAI,IACpBmB,EAAAnB,EAAO,SAAP,MAAAmB,EAAe,SAAS,WACvCD,EAAK,IAAIlB,EAAO,KAAMA,CAAM,EAIhC,MAAO,CAAE,QAAS,MAAM,KAAKkB,EAAK,QAAQ,EAC5C,CAEA,IAAK,eAAgB,CACnB,MAAMlI,EAAM,MAAM,OAAO,KAAK,OAAO,CACnC,IAAK,uBACL,OAAQ,GACT,EACD,GAAI,CAACA,EAAI,GAAI,MAAM,IAAI,MAAM,sBAAsB,EAEnD,OADmB,MAAM,OAAO,KAAK,IAAIA,EAAI,EAAE,GAChC,SAAW,YACxB,MAAM,IAAI,QAAe/I,GAAY,CACnC,MAAM0Q,EAAW,CAACjV,EAAekV,IAAoC,CAC/DlV,IAAUsN,EAAI,IAAM4H,EAAK,SAAW,aACtC,OAAO,KAAK,UAAU,eAAeD,CAAQ,EAC7C1Q,EAAA,EAEJ,EACA,OAAO,KAAK,UAAU,YAAY0Q,CAAQ,EAC1C,WAAW,IAAM,CACf,OAAO,KAAK,UAAU,eAAeA,CAAQ,EAC7C1Q,EAAA,CACF,EAAG,GAAK,CACV,CAAC,EAEH,MAAMsE,EAAI,OAAOyE,EAAI,EAAE,EAEvB,MAAMZ,GAAoBY,EAAI,GAAI,GAAK,EAChC,CAAE,MAAOA,EAAI,GACtB,CAEA,IAAK,iBAAkB,CACrB,MAAMoI,EAAYvV,EAAQ,MAC1B,GAAIuV,EAAW,CACb,GAAI,CACF,MAAM7M,EAAI,OAAO6M,CAAS,CAC5B,MAAQ,CAAC,CACT,GAAI,CACF,MAAM,OAAO,KAAK,OAAOA,CAAS,CACpC,MAAQ,CAAC,CACX,CACA,MAAO,CAAE,QAAS,GACpB,CAEA,IAAK,mBAAoB,CACvB,KAAM,CAAE,OAAApV,EAAQ,OAAAC,CAAA,EAAWJ,EAE3B,OADe,MAAM0I,EAAI,YAAY1I,EAAQ,MAAOG,EAAQC,GAAU,EAAE,CAE1E,CAEA,IAAK,gBAEH,OADe,MAAMsI,EAAI,eAAe1I,EAAQ,MAAOA,EAAQ,UAAU,EAI3E,IAAK,mBAAoB,CACvB,MAAM2C,EAAM3C,EAAQ,KAAO,+CACrBmN,EAAM,MAAM,OAAO,KAAK,OAAO,CAAE,IAAAxK,EAAK,OAAQ,GAAM,EAC1D,GAAI,CAACwK,EAAI,GAAI,MAAM,IAAI,MAAM,sBAAsB,EAEnD,OADmB,MAAM,OAAO,KAAK,IAAIA,EAAI,EAAE,GAChC,SAAW,YACxB,MAAM,IAAI,QAAe/I,GAAY,CACnC,MAAM0Q,EAAW,CAACjV,EAAekV,IAAoC,CAC/DlV,IAAUsN,EAAI,IAAM4H,EAAK,SAAW,aACtC,OAAO,KAAK,UAAU,eAAeD,CAAQ,EAC7C1Q,EAAA,EAEJ,EACA,OAAO,KAAK,UAAU,YAAY0Q,CAAQ,EAC1C,WAAW,IAAM,CACf,OAAO,KAAK,UAAU,eAAeA,CAAQ,EAC7C1Q,EAAA,CACF,EAAG,GAAK,CACV,CAAC,EAEH,MAAMsE,EAAI,OAAOyE,EAAI,EAAE,EACvB,MAAMZ,GAAoBY,EAAI,GAAI,GAAK,EAChC,CAAE,MAAOA,EAAI,GACtB,CAEA,IAAK,qBAAsB,CACzB,MAAMqI,EAAgBxV,EAAQ,MAC9B,GAAIwV,EAAe,CACjB,GAAI,CAAE,MAAM9M,EAAI,OAAO8M,CAAa,CAAG,MAAQ,CAAC,CAChD,GAAI,CAAE,MAAM,OAAO,KAAK,OAAOA,CAAa,CAAG,MAAQ,CAAC,CAC1D,CACA,MAAO,CAAE,QAAS,GACpB,CAEA,IAAK,uBAAwB,CAC3B,KAAM,CAAE,OAAArV,EAAQ,OAAAC,CAAA,EAAWJ,EAC3B,OAAO,MAAM0I,EAAI,YAAY1I,EAAQ,MAAOG,EAAQC,GAAU,EAAE,CAClE,CAEA,IAAK,oBACH,OAAO,MAAMsI,EAAI,eAAe1I,EAAQ,MAAOA,EAAQ,UAAU,EAGnE,IAAK,mBAEH,MAAO,CACL,WAFc,MAAM,OAAO,UAAU,OAAOA,EAAQ,cAAgB,EAAE,GAEnD,IAAIyV,IAAM,CAC3B,GAAIA,EAAE,GACN,SAAUA,EAAE,SACZ,MAAOA,EAAE,MACT,MAAOA,EAAE,OACT,GAIN,IAAK,qBAAsB,CAEzB,MAAMP,EAAU,CAAC,cAAe,qBAAsB,sBAAuB,gBAAgB,EACvFC,EAAsC,GAE5C,UAAWC,KAAUF,EACnB,GAAI,CACF,MAAMZ,EAAU,MAAM,OAAO,QAAQ,OAAO,CAAE,OAAAc,EAAQ,EACtDD,EAAW,KAAK,GAAGb,CAAO,CAC5B,MAAQ,CAAC,CAIX,MAAM/D,EAAO,CAAC,4BAA6B,8BAA+B,8BAA+B,wBAAwB,EACjI,UAAW5N,KAAO4N,EAChB,GAAI,CACF,MAAM+D,EAAU,MAAM,OAAO,QAAQ,OAAO,CAAE,IAAA3R,EAAK,EACnDwS,EAAW,KAAK,GAAGb,CAAO,CAC5B,MAAQ,CAAC,CAIX,MAAMe,MAAW,IACjB,UAAWlB,KAAUgB,EAAY,CAC/B,MAAMrT,EAAWuT,EAAK,IAAIlB,EAAO,IAAI,GACjC,CAACrS,GACAqS,EAAO,SAAW,eAAiBA,EAAO,OAAS,KACnD,GAACuB,EAAA5T,EAAS,SAAT,MAAA4T,EAAiB,SAAS,kBAAiBC,EAAAxB,EAAO,SAAP,MAAAwB,EAAe,SAAS,iBACvEN,EAAK,IAAIlB,EAAO,KAAMA,CAAM,CAEhC,CAEA,MAAO,CAAE,QAAS,MAAM,KAAKkB,EAAK,QAAQ,EAC5C,CAEA,IAAK,aAAc,CAEjB,MAAM1S,EAAM3C,EAAQ,KAAO,+RAErBsT,EAA2C,CAC/C,QAAStT,EAAQ,UAAY,GAC7B,KAAM,SACN,IAAA2C,CAAA,EAGE3C,EAAQ,OAASA,EAAQ,SAC3BsT,EAAc,MAAQtT,EAAQ,MAC9BsT,EAAc,OAAStT,EAAQ,QAG7BA,EAAQ,YACVsT,EAAc,UAAY,IAG5B,MAAMsC,EAAS,MAAM,OAAO,QAAQ,OAAOtC,CAAa,EAExD,GAAI,CAACsC,EAAO,GAAI,MAAM,IAAI,MAAM,yBAAyB,EAIzD,MAAMC,GADO,MAAM,OAAO,KAAK,MAAM,CAAE,SAAUD,EAAO,GAAI,GACtC,CAAC,EAGvB,OAAIC,GAAA,MAAAA,EAAU,IACZ,MAAM,IAAI,QAAQ9T,GAAK,WAAWA,EAAG,GAAG,CAAC,EAGpC,CACL,QAAS,GACT,SAAU6T,EAAO,GACjB,MAAOC,GAAA,YAAAA,EAAU,GACjB,KAAM,mBAAmBD,EAAO,EAAE,yBAEtC,CAEA,IAAK,cAGH,MAAO,CACL,SAHc,MAAM,OAAO,QAAQ,OAAO,CAAE,SAAU,GAAM,GAG3C,IAAI1L,GAAA,SAAM,OACzB,GAAIA,EAAE,GACN,QAASA,EAAE,QACX,KAAMA,EAAE,KACR,MAAOA,EAAE,MACT,MAAOA,EAAE,MACT,OAAQA,EAAE,OACV,WAAUvJ,EAAAuJ,EAAE,OAAF,YAAAvJ,EAAQ,SAAU,EAC5B,KAAMX,EAAQ,aAAcU,EAAAwJ,EAAE,OAAF,YAAAxJ,EAAQ,IAAIyS,IAAM,CAC5C,GAAIA,EAAE,GACN,MAAOA,EAAE,MACT,IAAKA,EAAE,IACP,OAAQA,EAAE,UACN,QACN,GAIN,IAAK,eAAgB,CACnB,GAAI,CAACnT,EAAQ,SAAU,MAAM,IAAI,MAAM,sBAAsB,EAE7D,aAAM,OAAO,QAAQ,OAAOA,EAAQ,SAAU,CAAE,QAAS,GAAM,EACxD,CAAE,QAAS,GAAM,SAAUA,EAAQ,SAC5C,CAEA,IAAK,eAAgB,CACnB,GAAI,CAACA,EAAQ,SAAU,MAAM,IAAI,MAAM,sBAAsB,EAE7D,aAAM,OAAO,QAAQ,OAAOA,EAAQ,QAAQ,EACrC,CAAE,QAAS,GAAM,SAAUA,EAAQ,SAC5C,CAEA,IAAK,gBAAiB,CACpB,GAAI,CAACA,EAAQ,SAAU,MAAM,IAAI,MAAM,sBAAsB,EAE7D,MAAM8V,EAAwC,GAC1C9V,EAAQ,QAAO8V,EAAW,MAAQ9V,EAAQ,OAC1CA,EAAQ,SAAQ8V,EAAW,OAAS9V,EAAQ,QAC5CA,EAAQ,OAAS,SAAW8V,EAAW,KAAO9V,EAAQ,MACtDA,EAAQ,MAAQ,SAAW8V,EAAW,IAAM9V,EAAQ,KACpDA,EAAQ,QAAO8V,EAAW,MAAQ9V,EAAQ,OAE9C,MAAM4V,EAAS,MAAM,OAAO,QAAQ,OAAO5V,EAAQ,SAAU8V,CAAU,EACvE,MAAO,CACL,QAAS,GACT,SAAU9V,EAAQ,SAClB,MAAO4V,EAAO,MACd,OAAQA,EAAO,OAEnB,CAEA,QACE,MAAM,IAAI,MAAM,yBAAyB5V,EAAQ,IAAI,EAAE,EAE7D,CAEA,OAAO,QAAQ,YAAY,YAAae,GAAY,CAClD2G,EAAS,+BAAgC3G,EAAQ,MAAM,CACzD,CAAC,EAED,MAAMgV,OAA2B,IAAI,CACnC,YAAa,UAAW,WAAY,aAAc,aAAc,cAChE,gBAAiB,kBAAmB,kBAAmB,mBACvD,mBAAoB,eAAgB,kBAAmB,cAAe,iBACtE,cAAe,aAAc,iBAAkB,gBAAiB,eAChE,kBAAmB,iBAAkB,gBAAiB,cACtD,kBAAmB,oBAAqB,mBAAoB,sBAC5D,sBAAuB,qBAAsB,sBAC7C,qBAAsB,uBAAwB,sBAAuB,yBACrE,eAAgB,iBAAkB,gBAAiB,mBACnD,mBAAoB,qBAAsB,oBAAqB,uBAC/D,mBACA,aAAc,cAAe,eAAgB,eAAgB,gBAC7D,qBACF,CAAC,EAED7N,GAAoB,MAAOtH,GAAQ,aACjC,IAAIf,EAAQe,EAAI,MAChB,MAAMoV,EAAWpV,EAAI,SACfqV,GAAkBtV,EAAAC,EAAI,OAAJ,YAAAD,EAAU,WAAW,WACvCuV,EAAW,CAACH,GAAqB,IAAInV,EAAI,IAAI,EACnD,IAAIuV,EAAiB,GAErB,GAAItW,GAAS,CAACoW,EACZ,GAAI,CACF,MAAM,OAAO,KAAK,IAAIpW,CAAK,CAC7B,MAAQ,CACN,MAAM,IAAI,MAAM,mBAAmBA,CAAK,8CAA8C,CACxF,SACS,CAACA,GAASqW,EAAU,CAC7B,IAAIjC,EACA9G,EAEJ,GAAI6I,EAAU,CAEZ/B,EAAO,MAAM,OAAO,KAAK,MAAM,CAAE,OAAQ,GAAM,SAAA+B,EAAU,EACzD7I,EAAM8G,EAAK,CAAC,EAGZ,MAAMmC,EAAgBzT,GACpB,CAACA,GAAOA,EAAI,WAAW,WAAW,GAAKA,EAAI,WAAW,qBAAqB,GAAKA,IAAQ,cAQ1F,IANI,CAACwK,GAAOiJ,EAAajJ,EAAI,GAAG,KAE9B8G,EAAO,MAAM,OAAO,KAAK,MAAM,CAAE,SAAA+B,EAAU,EAC3C7I,EAAM8G,EAAK,KAAKd,GAAK,CAACiD,EAAajD,EAAE,GAAG,CAAC,GAGvC,EAAChG,GAAA,MAAAA,EAAK,IAAI,CAEZ,MAAM+F,EAAS,MAAM,OAAO,KAAK,OAAO,CACtC,SAAA8C,EACA,IAAK,4EACL,OAAQ,GACT,EACD,GAAI,CAAC9C,EAAO,GACV,MAAM,IAAI,MAAM,kCAAkC8C,CAAQ,EAAE,EAG9D,MAAM,IAAI,QAAQjU,GAAK,WAAWA,EAAG,GAAG,CAAC,EACzCoL,EAAM+F,EACNiD,EAAiB,EACnB,CACF,SAEElC,EAAO,MAAM,OAAO,KAAK,MAAM,CAAE,OAAQ,GAAM,kBAAmB,GAAM,EACxE9G,EAAM8G,EAAK,CAAC,GACR,CAAC9G,IAAOzM,EAAAyM,EAAI,MAAJ,MAAAzM,EAAS,WAAW,0BAC9BuT,EAAO,MAAM,OAAO,KAAK,MAAM,CAAE,OAAQ,GAAM,cAAe,GAAM,EACpE9G,EAAM8G,EAAK,CAAC,IAEV,CAAC9G,IAAOnL,EAAAmL,EAAI,MAAJ,MAAAnL,EAAS,WAAW,yBAA0BO,EAAA4K,EAAI,MAAJ,MAAA5K,EAAS,WAAW,gBAC5E0R,EAAO,MAAM,OAAO,KAAK,MAAM,CAAE,OAAQ,GAAM,EAC/C9G,EAAM8G,EAAK,KAAKd,GAAA,SAAK,SAACxS,EAAAwS,EAAE,MAAF,MAAAxS,EAAO,WAAW,yBAA0B,GAACD,EAAAyS,EAAE,MAAF,MAAAzS,EAAO,WAAW,cAAY,GAE/F,EAACyM,GAAA,MAAAA,EAAK,IACR,MAAM,IAAI,MAAM,wGAAwG,EAG5HtN,EAAQsN,EAAI,EACd,CAEA,MAAMzK,EAAS,MAAMwK,GAAc,CAAE,GAAGtM,EAAK,MAAAf,CAAA,EAAS,EAAkC,EAGlFwW,EAAkB,GACxB,OAAIF,GACFE,EAAM,KAAK,8BAA8BL,CAAQ,yDAAyD,EAGrG,CACL,GAAGtT,EACH,eAAgB7C,EAChB,MAAOwW,EAAM,OAAS,EAAIA,EAAM,KAAK,GAAG,EAAI,OAEhD,CAAC","names":["MODIFIERS","KEY_DEFINITIONS","_CDPController","__publicField","tabId","target","err","message","e","source","method","params","reason","messages","text","a","callFrame","_b","_a","msg","callbacks","cb","details","requests","req","timestamp","reqHeaders","key","value","entriesMap","seq","entryId","requestHeaders","requestBody","requestBodySize","entry","oldestKey","existing","r","_c","respHeaders","startTime","now","duration","response","responseHeaders","_d","_e","_f","result","url","mimeType","accept","promptText","preset","presets","config","rate","latitude","longitude","accuracy","device","options","viewport","enabled","categories","metricsResult","metrics","m","selector","files","doc","queryResult","timeout","readyState","resolve","frames","extractFrames","frame","parentId","child","frameId","expression","contextResult","wrappedExpression","regex","entries","idx","requestId","streamId","callback","layoutMetrics","width","height","x","y","type","button","clickCount","modifiers","buttonValue","i","startX","startY","endX","endY","deltaX","deltaY","char","needsShift","keyDef","chord","parts","modifierKeys","mainKey","part","mod","lowerKey","code","modifierString","trimmed","CDPController","debugMode","initialized","pendingLogs","stored","args","changes","areaName","debugLog","streamCallbacks","handleNativeApiResponse","nativePort","messageHandler","reconnectTimeout","pendingNativeRequests","nativeRequestId","initNativeMessaging","handler","connect","sendToNativeHost","reject","id","postToNativeHost","error","cdp","activeStreamTabs","frameContexts","getFrameIdForTab","screenshotCache","screenshotCounter","generateScreenshotId","cacheScreenshot","data","oldest","getScreenshot","ELEMENT_COLORS","annotateScreenshot","screenshot","elements","scale","blob","base64ToBlob","bitmap","canvas","ctx","scaleFactor","element","color","w","h","labelText","fontSize","textWidth","padding","labelWidth","labelHeight","labelX","labelY","resultBlob","blobToBase64","reader","base64","binary","bytes","captureFullPage","maxHeight","dimensions","viewportHeight","totalHeight","devicePixelRatio","originalScrollY","chunks","currentY","chunk","chunkBlob","canvasWidth","canvasHeight","chunkHeight","remainingHeight","drawHeight","navigationResolvers","tabNameRegistry","resolver","name","streamTabId","waitForRuntimeReady","timeoutMs","deadline","delay","ms","performLocateAction","ref","action","coords","sender","sendResponse","handleMessage","tab","scaleInfo","usedFallback","dpr","rawResult","cdpError","binaryString","treeResult","screenshotId","mods","clickTypeFrameId","clicked","clickTypeSubmitFrameId","autocompleteFrameId","waitMs","script","clear","submit","maxAttempts","scrollFallback","dx","dy","navigationPromise","readFrameId","_g","textResult","_h","position","scrollScript","pos","sel","findScrollable","el","b","container","_i","_j","scrollInfoScript","maxScroll","_k","_l","locateFrameId","textFrameId","labelFrameId","stylesFrameId","selectFrameId","fromTabId","targetTabId","_m","expect","pollInterval","lastError","urls","captureScreenshots","failFast","results","pass","fail","errors","screenshotBase64","hostname","testTabId","testTab","onComplete","onError","consoleMessages","elapsed","status","waitFrameId","dialog","deviceName","lowerName","bestMatch","presetLower","presetNoSpaces","selectorResult","setResult","index","chromeFrames","childFrames","f","targetFrame","_n","_o","output","limit","cdpRequestId","origins","byMethod","byStatus","totalSize","oldestEntry","newestEntry","statusGroup","activeTab","newTab","t","queryOptions","createdTabs","createOptions","tabIds","registeredTabId","namedTabs","__vitePreload","portManager","event","existingGroups","groupId","groups","group","tabs","_p","cookie","cookieDetails","expirationDate","cookies","level","createProps","folder","bookmark","bookmarks","query","openaiCookies","listener","info","chatTabId","pplxTabId","domains","allCookies","domain","seen","_q","grokTabId","aiStudioTabId","d","_r","_s","window","firstTab","updateInfo","COMMANDS_WITHOUT_TAB","windowId","isDialogCommand","needsTab","autoCreatedTab","isRestricted","hints"],"ignoreList":[],"sources":["../../src/cdp/controller.ts","../../src/utils/debug.ts","../../src/native/native-api-transport.ts","../../src/native/port-manager.ts","../../src/service-worker/index.ts"],"sourcesContent":["type Debuggee = chrome.debugger.Debuggee;\ntype MouseButton = \"left\" | \"right\" | \"middle\" | \"none\";\n\ninterface ConsoleMessage {\n type: string;\n text: string;\n timestamp: number;\n url?: string;\n line?: number;\n}\n\ninterface NetworkRequest {\n requestId: string;\n url: string;\n method: string;\n status?: number;\n type?: string;\n timestamp: number;\n requestHeaders?: Record<string, string>;\n requestBody?: string;\n responseHeaders?: Record<string, string>;\n responseBody?: string;\n mimeType?: string;\n duration?: number;\n}\n\nexport interface NetworkEntry {\n id: string; // \"r_<timestamp>_<seq>\"\n ts: number; // Request start timestamp (ms)\n duration?: number; // Total time (ms)\n ttfb?: number; // Time to first byte (ms)\n \n // Request\n method: string;\n url: string;\n origin: string; // Extracted from URL\n requestHeaders: Record<string, string>;\n requestBody?: string; // POST/PUT body\n requestBodySize?: number;\n \n // Response \n status?: number;\n statusText?: string;\n mimeType?: string;\n responseHeaders?: Record<string, string>;\n responseBody?: string; // Will be fetched via getResponseBody\n responseBodySize?: number;\n \n // Metadata\n tabId: number;\n tabUrl?: string; // Page URL that initiated request\n type?: string; // \"xhr\", \"fetch\", \"document\", etc.\n \n // Flags\n flags: string[]; // [\"binary\", \"truncated\", \"protobuf\", \"failed\"]\n \n // Internal tracking\n _requestId: string; // CDP requestId for lazy loading\n _responseReceived: boolean; // Whether response was received\n _loadingFinished: boolean; // Whether loading finished\n}\n\ninterface PendingDialog {\n type: \"alert\" | \"confirm\" | \"prompt\" | \"beforeunload\";\n message: string;\n defaultPrompt?: string;\n timestamp: number;\n}\n\ntype ConsoleEventCallback = (event: ConsoleMessage) => void;\ntype NetworkEventCallback = (event: {\n method: string;\n url: string;\n status?: number;\n duration?: number;\n timestamp: number;\n}) => void;\n\nconst MODIFIERS = {\n alt: 1,\n ctrl: 2,\n control: 2,\n meta: 4,\n cmd: 4,\n command: 4,\n win: 4,\n windows: 4,\n shift: 8,\n} as const;\n\ninterface KeyDefinition {\n key: string;\n code: string;\n keyCode: number;\n text?: string;\n location?: number;\n}\n\nconst KEY_DEFINITIONS: Record<string, KeyDefinition> = {\n enter: { key: \"Enter\", code: \"Enter\", keyCode: 13, text: \"\\r\" },\n tab: { key: \"Tab\", code: \"Tab\", keyCode: 9 },\n escape: { key: \"Escape\", code: \"Escape\", keyCode: 27 },\n backspace: { key: \"Backspace\", code: \"Backspace\", keyCode: 8 },\n delete: { key: \"Delete\", code: \"Delete\", keyCode: 46 },\n arrowup: { key: \"ArrowUp\", code: \"ArrowUp\", keyCode: 38 },\n arrowdown: { key: \"ArrowDown\", code: \"ArrowDown\", keyCode: 40 },\n arrowleft: { key: \"ArrowLeft\", code: \"ArrowLeft\", keyCode: 37 },\n arrowright: { key: \"ArrowRight\", code: \"ArrowRight\", keyCode: 39 },\n home: { key: \"Home\", code: \"Home\", keyCode: 36 },\n end: { key: \"End\", code: \"End\", keyCode: 35 },\n pageup: { key: \"PageUp\", code: \"PageUp\", keyCode: 33 },\n pagedown: { key: \"PageDown\", code: \"PageDown\", keyCode: 34 },\n space: { key: \" \", code: \"Space\", keyCode: 32, text: \" \" },\n f1: { key: \"F1\", code: \"F1\", keyCode: 112 },\n f2: { key: \"F2\", code: \"F2\", keyCode: 113 },\n f3: { key: \"F3\", code: \"F3\", keyCode: 114 },\n f4: { key: \"F4\", code: \"F4\", keyCode: 115 },\n f5: { key: \"F5\", code: \"F5\", keyCode: 116 },\n f6: { key: \"F6\", code: \"F6\", keyCode: 117 },\n f7: { key: \"F7\", code: \"F7\", keyCode: 118 },\n f8: { key: \"F8\", code: \"F8\", keyCode: 119 },\n f9: { key: \"F9\", code: \"F9\", keyCode: 120 },\n f10: { key: \"F10\", code: \"F10\", keyCode: 121 },\n f11: { key: \"F11\", code: \"F11\", keyCode: 122 },\n f12: { key: \"F12\", code: \"F12\", keyCode: 123 },\n};\n\nexport class CDPController {\n private targets = new Map<number, Debuggee>();\n private consoleMessages: Map<number, ConsoleMessage[]> = new Map();\n private networkRequests: Map<number, NetworkRequest[]> = new Map();\n private networkEntries: Map<number, Map<string, NetworkEntry>> = new Map(); // tabId -> requestId -> entry\n private consoleCallbacks: Map<number, Map<number, ConsoleEventCallback>> = new Map();\n private networkCallbacks: Map<number, Map<number, NetworkEventCallback>> = new Map();\n private networkRequestStartTimes: Map<string, number> = new Map();\n private pendingDialogs: Map<number, PendingDialog> = new Map();\n private networkEntrySeq = 0; // Sequence counter for unique IDs\n private static debuggerListenerRegistered = false;\n\n // Body fetch settings\n private static readonly MAX_INLINE_BODY_SIZE = 16 * 1024; // 16KB\n private static readonly STATIC_ASSET_TYPES = new Set([\n 'image/png', 'image/jpeg', 'image/gif', 'image/webp', 'image/svg+xml', 'image/x-icon',\n 'font/woff', 'font/woff2', 'font/ttf', 'font/otf', 'application/font-woff', 'application/font-woff2',\n 'text/css', 'application/javascript', 'text/javascript', 'application/x-javascript',\n ]);\n private static readonly BINARY_TYPES = new Set([\n 'image/png', 'image/jpeg', 'image/gif', 'image/webp', 'image/x-icon',\n 'font/woff', 'font/woff2', 'font/ttf', 'font/otf', 'application/font-woff', 'application/font-woff2',\n 'application/octet-stream', 'application/pdf', 'application/zip',\n 'audio/mpeg', 'audio/wav', 'audio/ogg',\n 'video/mp4', 'video/webm', 'video/ogg',\n ]);\n\n async attach(tabId: number): Promise<void> {\n if (this.targets.has(tabId)) return;\n \n const target: Debuggee = { tabId };\n try {\n await chrome.debugger.attach(target, \"1.3\");\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n if (message.includes(\"Cannot access\") || message.includes(\"Cannot attach\")) {\n throw new Error(`Cannot control this page. Chrome restricts automation on chrome://, extensions, and web store pages.`);\n }\n throw new Error(`Failed to attach debugger: ${message}`);\n }\n this.targets.set(tabId, target);\n\n this.setupEventListener();\n this.consoleMessages.set(tabId, []);\n this.networkRequests.set(tabId, []);\n\n try {\n await this.send(tabId, \"Page.enable\");\n } catch (e) {}\n }\n\n async detach(tabId: number): Promise<void> {\n const target = this.targets.get(tabId);\n if (target) {\n try {\n await chrome.debugger.detach(target);\n } catch (e) {\n console.warn(\"[CDPController] Error detaching:\", e);\n }\n this.targets.delete(tabId);\n this.consoleMessages.delete(tabId);\n this.networkRequests.delete(tabId);\n this.networkEntries.delete(tabId);\n this.consoleCallbacks.delete(tabId);\n this.networkCallbacks.delete(tabId);\n this.pendingDialogs.delete(tabId);\n }\n }\n\n async detachAll(): Promise<void> {\n for (const tabId of this.targets.keys()) {\n await this.detach(tabId);\n }\n }\n\n private setupEventListener(): void {\n if (CDPController.debuggerListenerRegistered) return;\n CDPController.debuggerListenerRegistered = true;\n\n chrome.debugger.onEvent.addListener((source, method, params) => {\n const tabId = source.tabId;\n if (!tabId || !this.targets.has(tabId)) return;\n\n this.handleCDPEvent(tabId, method, params);\n });\n\n chrome.debugger.onDetach.addListener((source, reason) => {\n const tabId = source.tabId;\n if (tabId && this.targets.has(tabId)) {\n this.targets.delete(tabId);\n this.consoleMessages.delete(tabId);\n this.networkRequests.delete(tabId);\n this.networkEntries.delete(tabId);\n this.consoleCallbacks.delete(tabId);\n this.networkCallbacks.delete(tabId);\n }\n });\n }\n\n private handleCDPEvent(tabId: number, method: string, params: any): void {\n switch (method) {\n case \"Runtime.consoleAPICalled\":\n this.handleRuntimeConsole(tabId, params);\n break;\n case \"Runtime.exceptionThrown\":\n this.handleRuntimeException(tabId, params);\n break;\n case \"Network.requestWillBeSent\":\n this.handleNetworkRequest(tabId, params);\n break;\n case \"Network.responseReceived\":\n this.handleNetworkResponse(tabId, params);\n break;\n case \"Network.loadingFailed\":\n this.handleNetworkFailed(tabId, params);\n break;\n case \"Network.loadingFinished\":\n this.handleLoadingFinished(tabId, params);\n break;\n case \"Page.javascriptDialogOpening\":\n this.handleDialogOpening(tabId, params);\n break;\n case \"Page.javascriptDialogClosed\":\n this.pendingDialogs.delete(tabId);\n break;\n }\n }\n\n private handleRuntimeConsole(tabId: number, params: any): void {\n const messages = this.consoleMessages.get(tabId) || [];\n const args = params.args || [];\n\n const text = args\n .map((a: any) => {\n if (a.value !== undefined) return String(a.value);\n if (a.description) return a.description;\n return \"\";\n })\n .join(\" \");\n\n const callFrame = params.stackTrace?.callFrames?.[0];\n\n const msg: ConsoleMessage = {\n type: params.type || \"log\",\n text,\n timestamp: params.timestamp || Date.now(),\n url: callFrame?.url,\n line: callFrame?.lineNumber,\n };\n\n messages.push(msg);\n if (messages.length > 1000) messages.shift();\n this.consoleMessages.set(tabId, messages);\n\n const callbacks = this.consoleCallbacks.get(tabId);\n if (callbacks) {\n for (const cb of callbacks.values()) {\n cb(msg);\n }\n }\n }\n\n private handleRuntimeException(tabId: number, params: any): void {\n const messages = this.consoleMessages.get(tabId) || [];\n const details = params.exceptionDetails;\n if (!details) return;\n\n const msg: ConsoleMessage = {\n type: \"exception\",\n text: details.exception?.description || details.text || \"Unknown exception\",\n timestamp: details.timestamp || Date.now(),\n url: details.url,\n line: details.lineNumber,\n };\n\n messages.push(msg);\n if (messages.length > 1000) messages.shift();\n this.consoleMessages.set(tabId, messages);\n\n const callbacks = this.consoleCallbacks.get(tabId);\n if (callbacks) {\n for (const cb of callbacks.values()) {\n cb(msg);\n }\n }\n }\n\n private handleNetworkRequest(tabId: number, params: any): void {\n const requests = this.networkRequests.get(tabId) || [];\n const req = params.request;\n if (!req) return;\n\n const timestamp = params.timestamp ? params.timestamp * 1000 : Date.now();\n this.networkRequestStartTimes.set(params.requestId, timestamp);\n\n // Legacy format for backward compatibility\n const reqHeaders: Record<string, string> = {};\n if (req.headers) {\n for (const [key, value] of Object.entries(req.headers)) {\n reqHeaders[key] = String(value);\n }\n }\n\n requests.push({\n requestId: params.requestId,\n url: req.url,\n method: req.method,\n type: params.type,\n timestamp,\n requestHeaders: reqHeaders,\n requestBody: req.postData,\n });\n\n if (requests.length > 500) requests.shift();\n this.networkRequests.set(tabId, requests);\n\n // Full NetworkEntry format\n if (!this.networkEntries.has(tabId)) {\n this.networkEntries.set(tabId, new Map());\n }\n const entriesMap = this.networkEntries.get(tabId)!;\n \n // Generate unique ID\n const seq = ++this.networkEntrySeq;\n const entryId = `r_${timestamp}_${seq}`;\n\n // Extract headers as Record\n const requestHeaders: Record<string, string> = {};\n if (req.headers) {\n for (const [key, value] of Object.entries(req.headers)) {\n requestHeaders[key] = String(value);\n }\n }\n\n // Extract request body info\n const requestBody = req.postData;\n const requestBodySize = requestBody ? requestBody.length : undefined;\n\n const entry: NetworkEntry = {\n id: entryId,\n ts: timestamp,\n method: req.method,\n url: req.url,\n origin: this.extractOrigin(req.url),\n requestHeaders,\n requestBody,\n requestBodySize,\n tabId,\n tabUrl: params.documentURL,\n type: params.type,\n flags: [],\n _requestId: params.requestId,\n _responseReceived: false,\n _loadingFinished: false,\n };\n\n // Limit entries per tab\n if (entriesMap.size > 500) {\n const oldestKey = entriesMap.keys().next().value;\n if (oldestKey) entriesMap.delete(oldestKey);\n }\n \n entriesMap.set(params.requestId, entry);\n }\n\n private handleNetworkResponse(tabId: number, params: any): void {\n const requests = this.networkRequests.get(tabId) || [];\n const existing = requests.find((r) => r.requestId === params.requestId);\n if (existing) {\n existing.status = params.response?.status;\n existing.mimeType = params.response?.mimeType;\n\n // Capture response headers\n if (params.response?.headers) {\n const respHeaders: Record<string, string> = {};\n for (const [key, value] of Object.entries(params.response.headers)) {\n respHeaders[key] = String(value);\n }\n existing.responseHeaders = respHeaders;\n }\n\n const callbacks = this.networkCallbacks.get(tabId);\n if (callbacks) {\n const startTime = this.networkRequestStartTimes.get(params.requestId);\n const now = Date.now();\n const duration = startTime ? Math.round(now - startTime) : undefined;\n // Don't delete start time yet - we need it for loadingFinished\n // this.networkRequestStartTimes.delete(params.requestId);\n\n for (const cb of callbacks.values()) {\n cb({\n method: existing.method,\n url: existing.url,\n status: existing.status,\n duration,\n timestamp: now,\n });\n }\n }\n }\n\n // Update full NetworkEntry\n const entriesMap = this.networkEntries.get(tabId);\n const entry = entriesMap?.get(params.requestId);\n if (entry && params.response) {\n const response = params.response;\n \n // Calculate TTFB (time to first byte)\n const startTime = this.networkRequestStartTimes.get(params.requestId);\n const now = params.timestamp ? params.timestamp * 1000 : Date.now();\n if (startTime) {\n entry.ttfb = Math.round(now - startTime);\n }\n \n entry.status = response.status;\n entry.statusText = response.statusText;\n entry.mimeType = response.mimeType;\n \n // Extract response headers\n const responseHeaders: Record<string, string> = {};\n if (response.headers) {\n for (const [key, value] of Object.entries(response.headers)) {\n responseHeaders[key] = String(value);\n }\n }\n entry.responseHeaders = responseHeaders;\n \n // Check if binary type\n if (this.isBinaryType(response.mimeType)) {\n entry.flags.push('binary');\n }\n \n // Check for protobuf\n if (response.mimeType?.includes('protobuf') || \n response.mimeType?.includes('x-protobuf') ||\n response.mimeType?.includes('application/grpc')) {\n entry.flags.push('protobuf');\n }\n \n entry._responseReceived = true;\n }\n }\n\n private handleNetworkFailed(tabId: number, params: any): void {\n const requests = this.networkRequests.get(tabId) || [];\n const existing = requests.find((r) => r.requestId === params.requestId);\n if (existing && !existing.status) {\n existing.status = 0;\n\n const callbacks = this.networkCallbacks.get(tabId);\n if (callbacks) {\n const startTime = this.networkRequestStartTimes.get(params.requestId);\n const now = Date.now();\n const duration = startTime ? Math.round(now - startTime) : undefined;\n this.networkRequestStartTimes.delete(params.requestId);\n\n for (const cb of callbacks.values()) {\n cb({\n method: existing.method,\n url: existing.url,\n status: 0,\n duration,\n timestamp: now,\n });\n }\n }\n }\n\n // Update full NetworkEntry\n const entriesMap = this.networkEntries.get(tabId);\n const entry = entriesMap?.get(params.requestId);\n if (entry) {\n const startTime = this.networkRequestStartTimes.get(params.requestId);\n const now = params.timestamp ? params.timestamp * 1000 : Date.now();\n if (startTime) {\n entry.duration = Math.round(now - startTime);\n }\n this.networkRequestStartTimes.delete(params.requestId);\n \n entry.status = 0;\n entry.flags.push('failed');\n entry._loadingFinished = true;\n }\n }\n\n private handleDialogOpening(tabId: number, params: any): void {\n this.pendingDialogs.set(tabId, {\n type: params.type,\n message: params.message,\n defaultPrompt: params.defaultPrompt,\n timestamp: Date.now(),\n });\n }\n\n private async handleLoadingFinished(tabId: number, params: any): Promise<void> {\n // Update the simple requests array\n const requests = this.networkRequests.get(tabId) || [];\n const existing = requests.find((r) => r.requestId === params.requestId);\n if (existing) {\n // Calculate duration\n const startTime = this.networkRequestStartTimes.get(params.requestId);\n const now = params.timestamp ? params.timestamp * 1000 : Date.now();\n if (startTime) {\n existing.duration = Math.round(now - startTime);\n }\n\n // Fetch response body for small non-static responses (< 16KB)\n const shouldFetchBody = \n !this.isStaticAsset(existing.mimeType) &&\n !this.isBinaryType(existing.mimeType) &&\n (params.encodedDataLength || 0) <= CDPController.MAX_INLINE_BODY_SIZE;\n\n if (shouldFetchBody) {\n try {\n const result = await this.send(tabId, \"Network.getResponseBody\", {\n requestId: params.requestId,\n });\n \n if (result.base64Encoded) {\n try {\n existing.responseBody = atob(result.body);\n } catch {\n existing.responseBody = result.body;\n }\n } else {\n existing.responseBody = result.body;\n }\n \n // Truncate if too large\n if (existing.responseBody && existing.responseBody.length > CDPController.MAX_INLINE_BODY_SIZE) {\n existing.responseBody = existing.responseBody.slice(0, CDPController.MAX_INLINE_BODY_SIZE);\n }\n } catch (e) {\n // Body may not be available (e.g., cached, redirected)\n }\n }\n }\n\n // Update full NetworkEntry format\n const entriesMap = this.networkEntries.get(tabId);\n const entry = entriesMap?.get(params.requestId);\n if (!entry) return;\n\n // Calculate total duration\n const startTime = this.networkRequestStartTimes.get(params.requestId);\n const now = params.timestamp ? params.timestamp * 1000 : Date.now();\n if (startTime) {\n entry.duration = Math.round(now - startTime);\n }\n this.networkRequestStartTimes.delete(params.requestId);\n\n // Set response body size from encoded data length\n entry.responseBodySize = params.encodedDataLength;\n entry._loadingFinished = true;\n\n // Decide whether to fetch body inline\n const shouldFetchBody = \n !this.isStaticAsset(entry.mimeType) &&\n !this.isBinaryType(entry.mimeType) &&\n (params.encodedDataLength || 0) <= CDPController.MAX_INLINE_BODY_SIZE;\n\n if (shouldFetchBody) {\n try {\n const result = await this.send(tabId, \"Network.getResponseBody\", {\n requestId: params.requestId,\n });\n \n if (result.base64Encoded) {\n // Decode base64 for text content\n try {\n entry.responseBody = atob(result.body);\n } catch {\n entry.responseBody = result.body;\n entry.flags.push('binary');\n }\n } else {\n entry.responseBody = result.body;\n }\n \n // Check if truncated\n if (entry.responseBody && entry.responseBody.length > CDPController.MAX_INLINE_BODY_SIZE) {\n entry.responseBody = entry.responseBody.slice(0, CDPController.MAX_INLINE_BODY_SIZE);\n entry.flags.push('truncated');\n }\n } catch (e) {\n // Body may not be available (e.g., cached, redirected)\n // This is not an error - just means no body to capture\n }\n }\n }\n\n // Helper: Extract origin from URL\n private extractOrigin(url: string): string {\n try {\n const parsed = new URL(url);\n return parsed.origin;\n } catch {\n return '';\n }\n }\n\n // Helper: Check if MIME type is a static asset (skip body fetch)\n private isStaticAsset(mimeType?: string): boolean {\n if (!mimeType) return false;\n return CDPController.STATIC_ASSET_TYPES.has(mimeType);\n }\n\n // Helper: Check if MIME type is binary\n private isBinaryType(mimeType?: string): boolean {\n if (!mimeType) return false;\n return CDPController.BINARY_TYPES.has(mimeType);\n }\n\n async enableConsoleTracking(tabId: number): Promise<void> {\n await this.ensureAttached(tabId);\n try {\n await this.send(tabId, \"Runtime.enable\");\n } catch (e) {}\n }\n\n async enableNetworkTracking(tabId: number): Promise<void> {\n await this.ensureAttached(tabId);\n try {\n await this.send(tabId, \"Network.enable\", { maxPostDataSize: 65536 });\n } catch (e) {}\n }\n\n async handleDialog(tabId: number, accept: boolean, promptText?: string): Promise<{ success: boolean; error?: string }> {\n try {\n await this.send(tabId, \"Page.handleJavaScriptDialog\", {\n accept,\n promptText,\n });\n this.pendingDialogs.delete(tabId);\n return { success: true };\n } catch (e) {\n return { success: false, error: e instanceof Error ? e.message : String(e) };\n }\n }\n\n getDialogInfo(tabId: number): PendingDialog | null {\n return this.pendingDialogs.get(tabId) || null;\n }\n\n async emulateNetwork(tabId: number, preset: string): Promise<{ success: boolean; error?: string }> {\n await this.ensureAttached(tabId);\n const presets: Record<string, { offline: boolean; latency: number; downloadThroughput: number; uploadThroughput: number }> = {\n \"offline\": { offline: true, latency: 0, downloadThroughput: 0, uploadThroughput: 0 },\n \"slow-3g\": { offline: false, latency: 2000, downloadThroughput: 50000, uploadThroughput: 50000 },\n \"fast-3g\": { offline: false, latency: 562.5, downloadThroughput: 180000, uploadThroughput: 84375 },\n \"4g\": { offline: false, latency: 100, downloadThroughput: 4000000, uploadThroughput: 3000000 },\n \"reset\": { offline: false, latency: 0, downloadThroughput: -1, uploadThroughput: -1 },\n };\n const config = presets[preset.toLowerCase().replace(/\\s+/g, \"-\")];\n if (!config) {\n return { success: false, error: `Unknown preset: ${preset}. Available: ${Object.keys(presets).join(\", \")}` };\n }\n try {\n await this.send(tabId, \"Network.enable\");\n await this.send(tabId, \"Network.emulateNetworkConditions\", config);\n return { success: true };\n } catch (e) {\n return { success: false, error: e instanceof Error ? e.message : String(e) };\n }\n }\n\n async emulateCPU(tabId: number, rate: number): Promise<{ success: boolean; error?: string }> {\n await this.ensureAttached(tabId);\n if (rate < 1) {\n return { success: false, error: \"CPU throttling rate must be >= 1 (1 = no throttle, 4 = 4x slower)\" };\n }\n try {\n await this.send(tabId, \"Emulation.setCPUThrottlingRate\", { rate });\n return { success: true };\n } catch (e) {\n return { success: false, error: e instanceof Error ? e.message : String(e) };\n }\n }\n\n async emulateGeolocation(tabId: number, latitude: number, longitude: number, accuracy?: number): Promise<{ success: boolean; error?: string }> {\n await this.ensureAttached(tabId);\n try {\n await this.send(tabId, \"Emulation.setGeolocationOverride\", {\n latitude,\n longitude,\n accuracy: accuracy || 100,\n });\n return { success: true };\n } catch (e) {\n return { success: false, error: e instanceof Error ? e.message : String(e) };\n }\n }\n\n async clearGeolocation(tabId: number): Promise<{ success: boolean; error?: string }> {\n await this.ensureAttached(tabId);\n try {\n await this.send(tabId, \"Emulation.clearGeolocationOverride\");\n return { success: true };\n } catch (e) {\n return { success: false, error: e instanceof Error ? e.message : String(e) };\n }\n }\n\n async emulateDevice(\n tabId: number, \n device: { width: number; height: number; deviceScaleFactor: number; mobile: boolean; touch?: boolean; userAgent?: string }\n ): Promise<{ success: boolean; error?: string }> {\n await this.ensureAttached(tabId);\n try {\n // Set device metrics\n await this.send(tabId, \"Emulation.setDeviceMetricsOverride\", {\n width: device.width,\n height: device.height,\n deviceScaleFactor: device.deviceScaleFactor,\n mobile: device.mobile,\n });\n \n // Set user agent if provided\n if (device.userAgent) {\n await this.send(tabId, \"Emulation.setUserAgentOverride\", {\n userAgent: device.userAgent,\n });\n }\n \n // Enable touch if specified\n if (device.touch) {\n await this.send(tabId, \"Emulation.setTouchEmulationEnabled\", {\n enabled: true,\n maxTouchPoints: 5,\n });\n }\n \n return { success: true };\n } catch (e) {\n return { success: false, error: e instanceof Error ? e.message : String(e) };\n }\n }\n\n async clearDeviceEmulation(tabId: number): Promise<{ success: boolean; error?: string }> {\n await this.ensureAttached(tabId);\n try {\n await this.send(tabId, \"Emulation.clearDeviceMetricsOverride\");\n await this.send(tabId, \"Emulation.setUserAgentOverride\", { userAgent: \"\" });\n await this.send(tabId, \"Emulation.setTouchEmulationEnabled\", { enabled: false });\n return { success: true };\n } catch (e) {\n return { success: false, error: e instanceof Error ? e.message : String(e) };\n }\n }\n\n async emulateViewport(\n tabId: number, \n options: { width?: number; height?: number; deviceScaleFactor?: number; mobile?: boolean }\n ): Promise<{ success: boolean; error?: string }> {\n await this.ensureAttached(tabId);\n try {\n // Get current viewport size as defaults\n const viewport = await this.getViewportSize(tabId);\n \n await this.send(tabId, \"Emulation.setDeviceMetricsOverride\", {\n width: options.width || viewport.width,\n height: options.height || viewport.height,\n deviceScaleFactor: options.deviceScaleFactor || 1,\n mobile: options.mobile || false,\n });\n \n return { success: true };\n } catch (e) {\n return { success: false, error: e instanceof Error ? e.message : String(e) };\n }\n }\n\n async emulateTouch(tabId: number, enabled: boolean): Promise<{ success: boolean; error?: string }> {\n await this.ensureAttached(tabId);\n try {\n await this.send(tabId, \"Emulation.setTouchEmulationEnabled\", {\n enabled,\n maxTouchPoints: enabled ? 5 : 0,\n });\n return { success: true };\n } catch (e) {\n return { success: false, error: e instanceof Error ? e.message : String(e) };\n }\n }\n\n async startPerformanceTrace(tabId: number, categories?: string[]): Promise<{ success: boolean; error?: string }> {\n await this.ensureAttached(tabId);\n try {\n await this.send(tabId, \"Performance.enable\");\n await this.send(tabId, \"Tracing.start\", {\n categories: categories?.join(\",\") || \"devtools.timeline,v8.execute,disabled-by-default-devtools.timeline\",\n transferMode: \"ReturnAsStream\",\n });\n return { success: true };\n } catch (e) {\n return { success: false, error: e instanceof Error ? e.message : String(e) };\n }\n }\n\n async stopPerformanceTrace(tabId: number): Promise<{ success: boolean; metrics?: any; error?: string }> {\n await this.ensureAttached(tabId);\n try {\n await this.send(tabId, \"Performance.enable\");\n const metricsResult = await this.send(tabId, \"Performance.getMetrics\");\n await this.send(tabId, \"Tracing.end\");\n await this.send(tabId, \"Performance.disable\");\n const metrics: Record<string, number> = {};\n for (const m of metricsResult.metrics || []) {\n metrics[m.name] = m.value;\n }\n return { success: true, metrics };\n } catch (e) {\n return { success: false, error: e instanceof Error ? e.message : String(e) };\n }\n }\n\n async getPerformanceMetrics(tabId: number): Promise<{ success: boolean; metrics?: Record<string, number>; error?: string }> {\n await this.ensureAttached(tabId);\n try {\n await this.send(tabId, \"Performance.enable\");\n const result = await this.send(tabId, \"Performance.getMetrics\");\n await this.send(tabId, \"Performance.disable\");\n const metrics: Record<string, number> = {};\n for (const m of result.metrics || []) {\n metrics[m.name] = m.value;\n }\n return { success: true, metrics };\n } catch (e) {\n return { success: false, error: e instanceof Error ? e.message : String(e) };\n }\n }\n\n async setFileInputBySelector(tabId: number, selector: string, files: string[]): Promise<{ success: boolean; error?: string }> {\n await this.ensureAttached(tabId);\n try {\n await this.send(tabId, \"DOM.enable\");\n const doc = await this.send(tabId, \"DOM.getDocument\");\n const queryResult = await this.send(tabId, \"DOM.querySelector\", {\n nodeId: doc.root.nodeId,\n selector,\n });\n if (!queryResult.nodeId) {\n return { success: false, error: \"Could not find element by selector\" };\n }\n await this.send(tabId, \"DOM.setFileInputFiles\", {\n nodeId: queryResult.nodeId,\n files,\n });\n return { success: true };\n } catch (e) {\n return { success: false, error: e instanceof Error ? e.message : String(e) };\n }\n }\n\n async waitForLoad(tabId: number, timeout: number = 30000): Promise<{ success: boolean; readyState?: string; error?: string }> {\n await this.ensureAttached(tabId);\n const startTime = Date.now();\n try {\n while (Date.now() - startTime < timeout) {\n const result = await this.send(tabId, \"Runtime.evaluate\", {\n expression: \"document.readyState\",\n returnByValue: true,\n });\n const readyState = result.result?.value;\n if (readyState === \"complete\") {\n return { success: true, readyState };\n }\n await new Promise(resolve => setTimeout(resolve, 100));\n }\n return { success: false, error: `Timeout waiting for page load (${timeout}ms)` };\n } catch (e) {\n return { success: false, error: e instanceof Error ? e.message : String(e) };\n }\n }\n\n async getFrames(tabId: number): Promise<{ success: boolean; frames?: Array<{ frameId: string; url: string; name: string; parentId?: string }>; error?: string }> {\n await this.ensureAttached(tabId);\n try {\n await this.send(tabId, \"Page.enable\");\n const result = await this.send(tabId, \"Page.getFrameTree\");\n const frames: Array<{ frameId: string; url: string; name: string; parentId?: string }> = [];\n const extractFrames = (frame: any, parentId?: string) => {\n frames.push({\n frameId: frame.frame.id,\n url: frame.frame.url,\n name: frame.frame.name || \"\",\n parentId,\n });\n if (frame.childFrames) {\n for (const child of frame.childFrames) {\n extractFrames(child, frame.frame.id);\n }\n }\n };\n extractFrames(result.frameTree);\n return { success: true, frames };\n } catch (e) {\n return { success: false, error: e instanceof Error ? e.message : String(e) };\n }\n }\n\n async evaluateInFrame(tabId: number, frameId: string, expression: string): Promise<{ success: boolean; result?: any; error?: string }> {\n await this.ensureAttached(tabId);\n try {\n const contextResult = await this.send(tabId, \"Page.createIsolatedWorld\", {\n frameId,\n worldName: \"surf-isolated\",\n });\n const wrappedExpression = `JSON.stringify((function() { ${expression} })())`;\n const result = await this.send(tabId, \"Runtime.evaluate\", {\n expression: wrappedExpression,\n contextId: contextResult.executionContextId,\n returnByValue: true,\n awaitPromise: true,\n });\n if (result.exceptionDetails) {\n return { success: false, error: result.exceptionDetails.text || result.exceptionDetails.exception?.description || \"Evaluation failed\" };\n }\n try {\n return { success: true, result: JSON.parse(result.result?.value) };\n } catch {\n return { success: true, result: result.result?.value };\n }\n } catch (e) {\n return { success: false, error: e instanceof Error ? e.message : String(e) };\n }\n }\n\n getConsoleMessages(\n tabId: number,\n options?: {\n onlyErrors?: boolean;\n pattern?: string;\n limit?: number;\n }\n ): ConsoleMessage[] {\n let messages = this.consoleMessages.get(tabId) || [];\n\n if (options?.onlyErrors) {\n messages = messages.filter((m) => m.type === \"error\" || m.type === \"exception\");\n }\n if (options?.pattern) {\n try {\n const regex = new RegExp(options.pattern, \"i\");\n messages = messages.filter((m) => regex.test(m.text));\n } catch (e) {\n messages = messages.filter((m) => m.text.includes(options.pattern!));\n }\n }\n if (options?.limit) {\n messages = messages.slice(-options.limit);\n }\n\n return [...messages];\n }\n\n clearConsoleMessages(tabId: number): void {\n this.consoleMessages.set(tabId, []);\n }\n\n getNetworkRequests(\n tabId: number,\n options?: {\n urlPattern?: string;\n limit?: number;\n }\n ): NetworkRequest[] {\n let requests = this.networkRequests.get(tabId) || [];\n\n if (options?.urlPattern) {\n requests = requests.filter((r) => r.url.includes(options.urlPattern!));\n }\n if (options?.limit) {\n requests = requests.slice(-options.limit);\n }\n\n return [...requests];\n }\n\n clearNetworkRequests(tabId: number): void {\n this.networkRequests.set(tabId, []);\n this.networkEntries.set(tabId, new Map());\n }\n\n /**\n * Get all full network entries for a tab\n */\n getNetworkEntries(\n tabId: number,\n options?: {\n urlPattern?: string;\n limit?: number;\n includeStatic?: boolean;\n }\n ): NetworkEntry[] {\n // First try the full entries map\n const entriesMap = this.networkEntries.get(tabId);\n let entries: NetworkEntry[] = [];\n \n if (entriesMap && entriesMap.size > 0) {\n entries = Array.from(entriesMap.values());\n } else {\n // Fallback to basic networkRequests and convert to NetworkEntry format\n const requests = this.networkRequests.get(tabId) || [];\n entries = requests.map((req, idx) => ({\n id: `r_${req.timestamp}_${idx}`,\n ts: req.timestamp,\n method: req.method,\n url: req.url,\n origin: this.extractOrigin(req.url),\n requestHeaders: {},\n tabId: tabId,\n type: req.type,\n status: req.status,\n flags: [],\n _requestId: req.requestId,\n _responseReceived: true,\n _loadingFinished: true,\n } as NetworkEntry));\n }\n\n // Filter out static assets by default\n if (!options?.includeStatic) {\n entries = entries.filter(e => !this.isStaticAsset(e.mimeType));\n }\n\n if (options?.urlPattern) {\n entries = entries.filter((e) => e.url.includes(options.urlPattern!));\n }\n\n if (options?.limit) {\n entries = entries.slice(-options.limit);\n }\n\n return entries;\n }\n\n /**\n * Get a single network entry by request ID\n */\n getNetworkEntry(tabId: number, requestId: string): NetworkEntry | null {\n const entriesMap = this.networkEntries.get(tabId);\n return entriesMap?.get(requestId) || null;\n }\n\n /**\n * Fetch response body on demand via CDP\n * Use this for bodies that weren't fetched inline (large or binary)\n */\n async getResponseBody(tabId: number, requestId: string): Promise<{\n success: boolean;\n body?: string;\n base64Encoded?: boolean;\n error?: string;\n }> {\n await this.ensureAttached(tabId);\n \n try {\n const result = await this.send(tabId, \"Network.getResponseBody\", {\n requestId,\n });\n \n return {\n success: true,\n body: result.body,\n base64Encoded: result.base64Encoded,\n };\n } catch (e) {\n return {\n success: false,\n error: e instanceof Error ? e.message : String(e),\n };\n }\n }\n\n subscribeToConsole(tabId: number, streamId: number, callback: ConsoleEventCallback): void {\n if (!this.consoleCallbacks.has(tabId)) {\n this.consoleCallbacks.set(tabId, new Map());\n }\n this.consoleCallbacks.get(tabId)!.set(streamId, callback);\n }\n\n unsubscribeFromConsole(tabId: number, streamId: number): void {\n const callbacks = this.consoleCallbacks.get(tabId);\n if (callbacks) {\n callbacks.delete(streamId);\n if (callbacks.size === 0) {\n this.consoleCallbacks.delete(tabId);\n }\n }\n }\n\n subscribeToNetwork(tabId: number, streamId: number, callback: NetworkEventCallback): void {\n if (!this.networkCallbacks.has(tabId)) {\n this.networkCallbacks.set(tabId, new Map());\n }\n this.networkCallbacks.get(tabId)!.set(streamId, callback);\n }\n\n unsubscribeFromNetwork(tabId: number, streamId: number): void {\n const callbacks = this.networkCallbacks.get(tabId);\n if (callbacks) {\n callbacks.delete(streamId);\n if (callbacks.size === 0) {\n this.networkCallbacks.delete(tabId);\n }\n }\n }\n\n async evaluateScript(tabId: number, expression: string): Promise<{\n result?: { value?: any; type?: string; description?: string };\n exceptionDetails?: { text?: string; exception?: { description?: string } };\n }> {\n await this.ensureAttached(tabId);\n try {\n await this.send(tabId, \"Runtime.enable\");\n } catch (e) {}\n \n return this.send(tabId, \"Runtime.evaluate\", {\n expression,\n returnByValue: true,\n awaitPromise: true,\n timeout: 10000,\n });\n }\n\n private async send(tabId: number, method: string, params?: object): Promise<any> {\n await this.ensureAttached(tabId);\n const target = this.targets.get(tabId)!;\n return chrome.debugger.sendCommand(target, method, params);\n }\n\n async sendCommand(tabId: number, method: string, params?: object): Promise<any> {\n return this.send(tabId, method, params);\n }\n\n private async ensureAttached(tabId: number): Promise<void> {\n if (!this.targets.has(tabId)) {\n await this.attach(tabId);\n }\n }\n\n async getViewportSize(tabId: number): Promise<{ width: number; height: number }> {\n const layoutMetrics = await this.send(tabId, \"Page.getLayoutMetrics\");\n const viewport = layoutMetrics.visualViewport || layoutMetrics.layoutViewport;\n return {\n width: Math.round(viewport.clientWidth),\n height: Math.round(viewport.clientHeight),\n };\n }\n\n async captureScreenshot(tabId: number): Promise<{\n base64: string;\n width: number;\n height: number;\n }> {\n const result = await this.send(tabId, \"Page.captureScreenshot\", {\n format: \"png\",\n captureBeyondViewport: false,\n });\n const { width, height } = await this.getViewportSize(tabId);\n return { base64: result.data, width, height };\n }\n\n async captureRegion(tabId: number, x: number, y: number, width: number, height: number): Promise<{\n base64: string;\n width: number;\n height: number;\n }> {\n const result = await this.send(tabId, \"Page.captureScreenshot\", {\n format: \"png\",\n clip: { x, y, width, height, scale: 1 },\n });\n return { base64: result.data, width, height };\n }\n\n private async dispatchMouseEvent(\n tabId: number,\n type: \"mousePressed\" | \"mouseReleased\" | \"mouseMoved\" | \"mouseWheel\",\n x: number,\n y: number,\n options: {\n button?: MouseButton;\n buttons?: number;\n clickCount?: number;\n modifiers?: number;\n deltaX?: number;\n deltaY?: number;\n } = {}\n ): Promise<void> {\n const params: Record<string, any> = {\n type,\n x: Math.round(x),\n y: Math.round(y),\n modifiers: options.modifiers || 0,\n };\n\n if (type === \"mousePressed\" || type === \"mouseReleased\" || type === \"mouseMoved\") {\n params.button = options.button || \"none\";\n if (type === \"mousePressed\" || type === \"mouseReleased\") {\n params.clickCount = options.clickCount || 1;\n }\n }\n\n if (type !== \"mouseWheel\") {\n params.buttons = options.buttons ?? 0;\n }\n\n if (type === \"mouseWheel\") {\n params.deltaX = options.deltaX || 0;\n params.deltaY = options.deltaY || 0;\n }\n\n await this.send(tabId, \"Input.dispatchMouseEvent\", params);\n }\n\n async click(\n tabId: number,\n x: number,\n y: number,\n button: MouseButton = \"left\",\n clickCount = 1,\n modifiers = 0\n ): Promise<void> {\n const buttonValue = button === \"left\" ? 1 : button === \"right\" ? 2 : button === \"middle\" ? 4 : 0;\n\n await this.dispatchMouseEvent(tabId, \"mouseMoved\", x, y, { button: \"none\", buttons: 0, modifiers });\n await new Promise(resolve => setTimeout(resolve, 100));\n\n for (let i = 1; i <= clickCount; i++) {\n await this.dispatchMouseEvent(tabId, \"mousePressed\", x, y, {\n button,\n buttons: buttonValue,\n clickCount: i,\n modifiers,\n });\n await new Promise(resolve => setTimeout(resolve, 12));\n await this.dispatchMouseEvent(tabId, \"mouseReleased\", x, y, {\n button,\n buttons: 0,\n clickCount: i,\n modifiers,\n });\n if (i < clickCount) {\n await new Promise(resolve => setTimeout(resolve, 100));\n }\n }\n }\n\n async rightClick(tabId: number, x: number, y: number, modifiers = 0): Promise<void> {\n await this.click(tabId, x, y, \"right\", 1, modifiers);\n }\n\n async doubleClick(tabId: number, x: number, y: number, modifiers = 0): Promise<void> {\n await this.click(tabId, x, y, \"left\", 2, modifiers);\n }\n\n async tripleClick(tabId: number, x: number, y: number, modifiers = 0): Promise<void> {\n await this.click(tabId, x, y, \"left\", 3, modifiers);\n }\n\n async hover(tabId: number, x: number, y: number): Promise<void> {\n await this.dispatchMouseEvent(tabId, \"mouseMoved\", x, y, { button: \"none\", buttons: 0 });\n }\n\n async drag(\n tabId: number,\n startX: number,\n startY: number,\n endX: number,\n endY: number,\n modifiers = 0\n ): Promise<void> {\n await this.dispatchMouseEvent(tabId, \"mouseMoved\", startX, startY, { button: \"none\", buttons: 0 });\n await new Promise(resolve => setTimeout(resolve, 50));\n\n await this.dispatchMouseEvent(tabId, \"mousePressed\", startX, startY, {\n button: \"left\",\n buttons: 1,\n clickCount: 1,\n modifiers,\n });\n await new Promise(resolve => setTimeout(resolve, 50));\n\n await this.dispatchMouseEvent(tabId, \"mouseMoved\", endX, endY, { button: \"left\", buttons: 1, modifiers });\n await new Promise(resolve => setTimeout(resolve, 50));\n\n await this.dispatchMouseEvent(tabId, \"mouseReleased\", endX, endY, {\n button: \"left\",\n buttons: 0,\n clickCount: 1,\n modifiers,\n });\n }\n\n async scroll(tabId: number, x: number, y: number, deltaX: number, deltaY: number): Promise<void> {\n await this.dispatchMouseEvent(tabId, \"mouseWheel\", x, y, { deltaX, deltaY });\n }\n\n async type(tabId: number, text: string): Promise<void> {\n for (const char of text) {\n if (char === \"\\n\" || char === \"\\r\") {\n await this.pressKey(tabId, \"Enter\");\n } else {\n const keyDef = this.getKeyDefinition(char);\n if (keyDef) {\n const needsShift = this.requiresShift(char);\n await this.pressKey(tabId, char, needsShift ? MODIFIERS.shift : 0);\n } else {\n await this.send(tabId, \"Input.insertText\", { text: char });\n }\n }\n }\n }\n\n private requiresShift(char: string): boolean {\n return /[A-Z!@#$%^&*()_+{}|:\"<>?~]/.test(char);\n }\n\n private async dispatchKeyEvent(\n tabId: number,\n type: \"keyDown\" | \"keyUp\" | \"rawKeyDown\" | \"char\",\n keyDef: KeyDefinition,\n modifiers = 0\n ): Promise<void> {\n await this.send(tabId, \"Input.dispatchKeyEvent\", {\n type: keyDef.text ? type : (type === \"keyDown\" ? \"rawKeyDown\" : type),\n key: keyDef.key,\n code: keyDef.code,\n windowsVirtualKeyCode: keyDef.keyCode,\n modifiers,\n text: keyDef.text ?? \"\",\n unmodifiedText: keyDef.text ?? \"\",\n location: keyDef.location ?? 0,\n });\n }\n\n async pressKey(tabId: number, key: string, modifiers = 0): Promise<void> {\n const keyDef = this.getKeyDefinition(key);\n if (!keyDef) {\n throw new Error(`Unknown key: ${key}`);\n }\n\n await this.dispatchKeyEvent(tabId, \"keyDown\", keyDef, modifiers);\n await this.dispatchKeyEvent(tabId, \"keyUp\", keyDef, modifiers);\n }\n\n async pressKeyChord(tabId: number, chord: string): Promise<void> {\n const parts = chord.toLowerCase().split(\"+\");\n const modifierKeys: string[] = [];\n let mainKey = \"\";\n\n for (const part of parts) {\n if (part in MODIFIERS) {\n modifierKeys.push(part);\n } else {\n mainKey = part;\n }\n }\n\n let modifiers = 0;\n for (const mod of modifierKeys) {\n modifiers |= MODIFIERS[mod as keyof typeof MODIFIERS] || 0;\n }\n\n if (mainKey) {\n await this.pressKey(tabId, mainKey, modifiers);\n }\n }\n\n private getKeyDefinition(key: string): KeyDefinition | null {\n const lowerKey = key.toLowerCase();\n \n if (KEY_DEFINITIONS[lowerKey]) {\n return KEY_DEFINITIONS[lowerKey];\n }\n\n if (key.length === 1) {\n const code = key.toUpperCase().charCodeAt(0);\n return {\n key,\n code: `Key${key.toUpperCase()}`,\n keyCode: code,\n text: key,\n };\n }\n\n return null;\n }\n\n parseModifiers(modifierString?: string): number {\n if (!modifierString) return 0;\n \n let result = 0;\n const parts = modifierString.toLowerCase().split(\"+\");\n for (const part of parts) {\n const trimmed = part.trim();\n if (trimmed in MODIFIERS) {\n result |= MODIFIERS[trimmed as keyof typeof MODIFIERS];\n }\n }\n return result;\n }\n}\n","let debugMode = false;\nlet initialized = false;\nconst pendingLogs: unknown[][] = [];\n\nchrome.storage.local.get(\"debugMode\").then(({ debugMode: stored }) => {\n debugMode = !!stored;\n initialized = true;\n if (debugMode) {\n for (const args of pendingLogs) {\n console.log(\"[Surf]\", ...args);\n }\n }\n pendingLogs.length = 0;\n});\n\nchrome.storage.onChanged.addListener((changes, areaName) => {\n if (areaName === \"local\" && changes.debugMode) {\n debugMode = !!changes.debugMode.newValue;\n }\n});\n\nexport function debugLog(...args: unknown[]): void {\n if (!initialized) {\n pendingLogs.push(args);\n return;\n }\n if (debugMode) {\n console.log(\"[Surf]\", ...args);\n }\n}\n\nexport function isDebugMode(): boolean {\n return debugMode;\n}\n","import { sendToNativeHost } from \"./port-manager\";\n\nexport interface ApiStreamCallbacks {\n onStart: (status: number, headers: Record<string, string>) => void;\n onChunk: (chunk: string) => void;\n onEnd: () => void;\n onError: (error: string) => void;\n}\n\nconst streamCallbacks = new Map<string, ApiStreamCallbacks>();\nlet streamIdCounter = 0;\n\nexport function handleNativeApiResponse(msg: any): boolean {\n const { type, streamId } = msg;\n \n if (!streamId || !streamCallbacks.has(streamId)) {\n return false;\n }\n \n const callbacks = streamCallbacks.get(streamId)!;\n \n switch (type) {\n case \"API_RESPONSE_START\":\n callbacks.onStart(msg.status, msg.headers);\n return true;\n case \"API_RESPONSE_CHUNK\":\n callbacks.onChunk(msg.chunk);\n return true;\n case \"API_RESPONSE_END\":\n callbacks.onEnd();\n streamCallbacks.delete(streamId);\n return true;\n case \"API_RESPONSE_ERROR\":\n callbacks.onError(msg.error);\n streamCallbacks.delete(streamId);\n return true;\n default:\n return false;\n }\n}\n\nexport async function nativeApiFetch(\n url: string,\n options: {\n method?: string;\n headers?: Record<string, string>;\n body?: string;\n },\n callbacks: ApiStreamCallbacks\n): Promise<void> {\n const streamId = `stream_${++streamIdCounter}_${Date.now()}`;\n \n streamCallbacks.set(streamId, callbacks);\n \n try {\n await sendToNativeHost({\n type: \"API_REQUEST\",\n streamId,\n url,\n method: options.method || \"POST\",\n headers: options.headers || {},\n body: options.body,\n });\n } catch (err) {\n streamCallbacks.delete(streamId);\n callbacks.onError(err instanceof Error ? err.message : \"Unknown error\");\n }\n}\n","import { debugLog } from \"../utils/debug\";\nimport { handleNativeApiResponse } from \"./native-api-transport\";\n\nlet nativePort: chrome.runtime.Port | null = null;\nlet messageHandler: ((msg: any) => Promise<any>) | null = null;\nlet reconnectTimeout: ReturnType<typeof setTimeout> | null = null;\nlet pendingNativeRequests = new Map<number, { resolve: (value: any) => void; reject: (err: Error) => void }>();\nlet nativeRequestId = 0;\n\nexport function initNativeMessaging(\n handler: (msg: any) => Promise<any>\n): void {\n messageHandler = handler;\n connect();\n}\n\nexport function sendToNativeHost(msg: any): Promise<any> {\n return new Promise((resolve, reject) => {\n if (!nativePort) {\n reject(new Error(\"Native host not connected\"));\n return;\n }\n \n if (msg.type === \"API_REQUEST\") {\n nativePort.postMessage(msg);\n resolve({ sent: true });\n return;\n }\n \n const id = ++nativeRequestId;\n pendingNativeRequests.set(id, { resolve, reject });\n nativePort.postMessage({ ...msg, id });\n \n setTimeout(() => {\n if (pendingNativeRequests.has(id)) {\n pendingNativeRequests.delete(id);\n reject(new Error(\"Native host request timeout\"));\n }\n }, 10000);\n });\n}\n\nexport function postToNativeHost(msg: any): void {\n if (nativePort) {\n nativePort.postMessage(msg);\n }\n}\n\nfunction connect(): void {\n if (reconnectTimeout) {\n clearTimeout(reconnectTimeout);\n reconnectTimeout = null;\n }\n\n try {\n nativePort = chrome.runtime.connectNative(\"surf.browser.host\");\n debugLog(\"Connecting to native host...\");\n\n nativePort.onMessage.addListener(async (msg) => {\n debugLog(\"Received from native host:\", msg.type || msg.id);\n\n if (msg.type === \"HOST_READY\") {\n debugLog(\"Native host ready\");\n return;\n }\n\n if (msg.type?.startsWith(\"API_RESPONSE_\")) {\n handleNativeApiResponse(msg);\n chrome.runtime.sendMessage(msg).catch(() => {});\n return;\n }\n\n if (msg.id && pendingNativeRequests.has(msg.id)) {\n const { resolve } = pendingNativeRequests.get(msg.id)!;\n pendingNativeRequests.delete(msg.id);\n resolve(msg);\n return;\n }\n\n if (!messageHandler) return;\n\n try {\n const result = await messageHandler(msg);\n if (!nativePort) {\n debugLog(\"Cannot send response - native host disconnected:\", msg.id);\n return;\n }\n nativePort.postMessage({ id: msg.id, ...result });\n } catch (err) {\n if (!nativePort) {\n debugLog(\"Cannot send error - native host disconnected:\", msg.id);\n return;\n }\n nativePort.postMessage({\n id: msg.id,\n error: err instanceof Error ? err.message : \"Unknown error\",\n });\n }\n });\n\n nativePort.onDisconnect.addListener(() => {\n const error = chrome.runtime.lastError;\n debugLog(\n \"Native host disconnected:\",\n error?.message || \"unknown reason\"\n );\n nativePort = null;\n\n if (!error?.message?.includes(\"not found\")) {\n reconnectTimeout = setTimeout(connect, 5000);\n }\n });\n } catch (err) {\n debugLog(\"Failed to connect to native host:\", err);\n reconnectTimeout = setTimeout(connect, 10000);\n }\n}\n","import { CDPController } from \"../cdp/controller\";\nimport { debugLog } from \"../utils/debug\";\nimport { initNativeMessaging, postToNativeHost } from \"../native/port-manager\";\n\ndebugLog(\"Service worker loaded\");\n\nconst cdp = new CDPController();\nconst activeStreamTabs = new Map<number, number>();\n\n// Frame context per tab - stores the active frameId for each tab\n// When frame.switch is called, subsequent content script messages go to that frame\nconst frameContexts = new Map<number, number>();\n\n// Helper to get the frame ID for content script messaging\nfunction getFrameIdForTab(tabId: number): number {\n return frameContexts.get(tabId) ?? 0;\n}\n\nconst screenshotCache = new Map<string, { base64: string; width: number; height: number }>();\nlet screenshotCounter = 0;\n\nfunction generateScreenshotId(): string {\n return `screenshot_${++screenshotCounter}_${Date.now()}`;\n}\n\nfunction cacheScreenshot(id: string, data: { base64: string; width: number; height: number }): void {\n screenshotCache.set(id, data);\n if (screenshotCache.size > 10) {\n const oldest = screenshotCache.keys().next().value;\n if (oldest) screenshotCache.delete(oldest);\n }\n}\n\nfunction getScreenshot(id: string): { base64: string; width: number; height: number } | null {\n return screenshotCache.get(id) || null;\n}\n\nconst ELEMENT_COLORS: Record<string, string> = {\n button: '#FF6B6B',\n input: '#4ECDC4',\n select: '#45B7D1',\n a: '#96CEB4',\n textarea: '#FF8C42',\n default: '#DDA0DD',\n};\n\nasync function annotateScreenshot(\n screenshot: { base64: string; width: number; height: number },\n elements: Array<{ ref: string; tag: string; bounds: { x: number; y: number; width: number; height: number } }>,\n scale: { scaleX: number; scaleY: number }\n): Promise<{ base64: string; width: number; height: number }> {\n const blob = base64ToBlob(screenshot.base64);\n const bitmap = await createImageBitmap(blob);\n \n const canvas = new OffscreenCanvas(bitmap.width, bitmap.height);\n const ctx = canvas.getContext(\"2d\");\n if (!ctx) throw new Error(\"Failed to get canvas context\");\n \n ctx.drawImage(bitmap, 0, 0);\n bitmap.close();\n \n const scaleFactor = Math.min(scale.scaleX, scale.scaleY);\n \n for (const element of elements) {\n const color = ELEMENT_COLORS[element.tag] || ELEMENT_COLORS.default;\n \n const x = Math.round(element.bounds.x * scaleFactor);\n const y = Math.round(element.bounds.y * scaleFactor);\n const w = Math.round(element.bounds.width * scaleFactor);\n const h = Math.round(element.bounds.height * scaleFactor);\n \n if (w < 1 || h < 1) continue;\n \n ctx.strokeStyle = color;\n ctx.lineWidth = 2;\n ctx.setLineDash([4, 4]);\n ctx.strokeRect(x, y, w, h);\n ctx.setLineDash([]);\n \n const labelText = element.ref;\n const fontSize = Math.max(10, Math.min(16, Math.round(canvas.width * 0.01)));\n ctx.font = `bold ${fontSize}px sans-serif`;\n const textWidth = ctx.measureText(labelText).width;\n const padding = 4;\n const labelWidth = textWidth + padding * 2;\n const labelHeight = fontSize + padding * 2;\n \n let labelX = x + Math.floor((w - labelWidth) / 2);\n let labelY = y + 2;\n if (w < 60 || h < 30) {\n labelY = y - labelHeight - 2 < 0 ? y + h + 2 : y - labelHeight - 2;\n }\n \n labelX = Math.max(0, Math.min(canvas.width - labelWidth, labelX));\n labelY = Math.max(0, Math.min(canvas.height - labelHeight, labelY));\n \n ctx.fillStyle = color;\n ctx.fillRect(labelX, labelY, labelWidth, labelHeight);\n ctx.strokeStyle = \"white\";\n ctx.lineWidth = 1;\n ctx.strokeRect(labelX, labelY, labelWidth, labelHeight);\n \n ctx.fillStyle = \"white\";\n ctx.textBaseline = \"top\";\n ctx.fillText(labelText, labelX + padding, labelY + padding);\n }\n \n const resultBlob = await canvas.convertToBlob({ type: \"image/png\" });\n const base64 = await blobToBase64(resultBlob);\n \n return { base64, width: canvas.width, height: canvas.height };\n}\n\nfunction blobToBase64(blob: Blob): Promise<string> {\n return new Promise((resolve, reject) => {\n const reader = new FileReader();\n reader.onload = () => {\n const dataUrl = reader.result as string;\n const base64 = dataUrl.split(\",\")[1];\n resolve(base64);\n };\n reader.onerror = () => reject(new Error(\"Failed to convert blob to base64\"));\n reader.readAsDataURL(blob);\n });\n}\n\nfunction base64ToBlob(base64: string, mimeType = \"image/png\"): Blob {\n const binary = atob(base64);\n const bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++) {\n bytes[i] = binary.charCodeAt(i);\n }\n return new Blob([bytes], { type: mimeType });\n}\n\nasync function captureFullPage(tabId: number, maxHeight: number): Promise<{ base64: string; width: number; height: number }> {\n const dimensionsResult = await cdp.evaluateScript(tabId, `(() => ({\n viewportHeight: window.innerHeight,\n totalHeight: Math.min(document.documentElement.scrollHeight, ${maxHeight}),\n width: window.innerWidth,\n devicePixelRatio: window.devicePixelRatio || 1,\n originalScrollY: window.scrollY,\n }))()`);\n \n const dimensions = dimensionsResult.result?.value;\n if (!dimensions) throw new Error(\"Failed to get page dimensions\");\n \n const { viewportHeight, totalHeight, width, devicePixelRatio, originalScrollY } = dimensions;\n const chunks: ImageBitmap[] = [];\n let currentY = 0;\n \n while (currentY < totalHeight) {\n await cdp.evaluateScript(tabId, `window.scrollTo(0, ${currentY})`);\n await new Promise(r => setTimeout(r, 300));\n \n const chunk = await cdp.captureScreenshot(tabId);\n const chunkBlob = base64ToBlob(chunk.base64);\n chunks.push(await createImageBitmap(chunkBlob));\n \n currentY += viewportHeight;\n }\n \n await cdp.evaluateScript(tabId, `window.scrollTo(0, ${originalScrollY})`);\n \n const canvasWidth = Math.round(width * devicePixelRatio);\n const canvasHeight = Math.round(totalHeight * devicePixelRatio);\n const canvas = new OffscreenCanvas(canvasWidth, canvasHeight);\n const ctx = canvas.getContext(\"2d\");\n if (!ctx) throw new Error(\"Failed to get canvas context\");\n \n let y = 0;\n const chunkHeight = Math.round(viewportHeight * devicePixelRatio);\n for (let i = 0; i < chunks.length; i++) {\n const chunk = chunks[i];\n const remainingHeight = canvasHeight - y;\n const drawHeight = Math.min(chunkHeight, remainingHeight);\n ctx.drawImage(chunk, 0, 0, chunk.width, drawHeight, 0, y, chunk.width, drawHeight);\n y += drawHeight;\n chunk.close();\n }\n \n const resultBlob = await canvas.convertToBlob({ type: \"image/png\" });\n const base64 = await blobToBase64(resultBlob);\n \n return { base64, width: canvasWidth, height: canvasHeight };\n}\n\nconst navigationResolvers = new Map<number, () => void>();\nconst tabNameRegistry = new Map<string, number>();\n\nchrome.webNavigation.onCompleted.addListener((details) => {\n if (details.frameId === 0) {\n // Clear frame context on main frame navigation (iframes may have changed)\n frameContexts.delete(details.tabId);\n const resolver = navigationResolvers.get(details.tabId);\n if (resolver) {\n resolver();\n navigationResolvers.delete(details.tabId);\n }\n }\n});\n\nchrome.webNavigation.onErrorOccurred.addListener((details) => {\n if (details.frameId === 0) {\n const resolver = navigationResolvers.get(details.tabId);\n if (resolver) {\n resolver();\n navigationResolvers.delete(details.tabId);\n }\n }\n});\n\n\n\nchrome.tabs.onRemoved.addListener((tabId) => {\n cdp.detach(tabId);\n frameContexts.delete(tabId);\n for (const [name, id] of tabNameRegistry) {\n if (id === tabId) {\n tabNameRegistry.delete(name);\n }\n }\n for (const [streamId, streamTabId] of activeStreamTabs) {\n if (streamTabId === tabId) {\n activeStreamTabs.delete(streamId);\n }\n }\n});\n\n/**\n * Wait for JavaScript runtime to be ready in a newly created/attached tab.\n * This is needed because document.readyState === 'complete' doesn't mean\n * React/Vue/etc frameworks have finished hydrating.\n */\nasync function waitForRuntimeReady(tabId: number, timeoutMs = 10000): Promise<void> {\n const deadline = Date.now() + timeoutMs;\n const delay = (ms: number) => new Promise(r => setTimeout(r, ms));\n \n // Poll until we can successfully evaluate JS\n while (Date.now() < deadline) {\n try {\n const result = await cdp.evaluateScript(tabId, \"document.readyState\");\n if (result?.result?.value === \"complete\") {\n // Extra delay for framework hydration (React, Vue, etc.)\n await delay(1500);\n return;\n }\n } catch {\n // CDP not ready yet, continue polling\n }\n await delay(200);\n }\n \n // Timeout but proceed anyway - the page might still work\n console.warn(`waitForRuntimeReady timed out for tab ${tabId}`);\n}\n\n// Helper for locate.* commands with actions\nasync function performLocateAction(\n tabId: number, \n ref: string, \n action: string, \n value: string | undefined,\n cdp: CDPController,\n frameId: number = 0\n): Promise<any> {\n switch (action) {\n case \"click\": {\n const result = await chrome.tabs.sendMessage(tabId, {\n type: \"CLICK_ELEMENT\",\n ref,\n button: \"left\",\n }, { frameId });\n return result.error ? result : { success: true, action: \"click\", ref };\n }\n case \"fill\": {\n if (!value) return { error: \"fill action requires --value\" };\n const result = await chrome.tabs.sendMessage(tabId, {\n type: \"FORM_INPUT\",\n ref,\n value,\n }, { frameId });\n return result.error ? result : { success: true, action: \"fill\", ref, value };\n }\n case \"hover\": {\n const coords = await chrome.tabs.sendMessage(tabId, {\n type: \"GET_ELEMENT_COORDINATES\",\n ref,\n }, { frameId });\n if (coords.error) return coords;\n await cdp.hover(tabId, coords.x, coords.y);\n return { success: true, action: \"hover\", ref };\n }\n case \"text\": {\n const textResult = await chrome.tabs.sendMessage(tabId, {\n type: \"GET_ELEMENT_TEXT\",\n ref,\n }, { frameId });\n return textResult;\n }\n default:\n return { error: `Unknown action: ${action}. Use click|fill|hover|text` };\n }\n}\n\nchrome.runtime.onMessage.addListener((message, sender, sendResponse) => {\n handleMessage(message, sender)\n .then(sendResponse)\n .catch((err) => sendResponse({ error: err.message }));\n return true;\n});\n\nexport async function handleMessage(\n message: any,\n sender: chrome.runtime.MessageSender\n): Promise<any> {\n const tabId = message.tabId;\n\n switch (message.type) {\n case \"GET_CURRENT_TAB_ID\": {\n const [tab] = await chrome.tabs.query({ active: true, currentWindow: true });\n return { tabId: tab?.id };\n }\n\n case \"EXECUTE_SCREENSHOT\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n \n try {\n await chrome.tabs.sendMessage(tabId, { type: \"HIDE_FOR_TOOL_USE\" });\n } catch (e) {}\n await new Promise(resolve => setTimeout(resolve, 50));\n \n try {\n let result: { base64: string; width: number; height: number };\n let scaleInfo = { scaleX: 1, scaleY: 1 };\n let usedFallback = false;\n \n if (message.fullpage) {\n result = await captureFullPage(tabId, message.maxHeight || 4000);\n try {\n const viewport = await cdp.getViewportSize(tabId);\n const dpr = result.width / viewport.width;\n scaleInfo = { scaleX: dpr, scaleY: dpr };\n } catch {}\n } else {\n try {\n const rawResult = await cdp.captureScreenshot(tabId);\n result = rawResult;\n try {\n const viewport = await cdp.getViewportSize(tabId);\n scaleInfo = {\n scaleX: rawResult.width / viewport.width,\n scaleY: rawResult.height / viewport.height,\n };\n } catch {}\n } catch (cdpError) {\n const tab = await chrome.tabs.get(tabId);\n if (!tab.windowId) throw cdpError;\n const dataUrl = await chrome.tabs.captureVisibleTab(tab.windowId, { format: \"png\" });\n const base64 = dataUrl.replace(/^data:image\\/png;base64,/, \"\");\n const binaryString = atob(base64);\n const bytes = new Uint8Array(binaryString.length);\n for (let i = 0; i < binaryString.length; i++) {\n bytes[i] = binaryString.charCodeAt(i);\n }\n const blob = new Blob([bytes], { type: \"image/png\" });\n const bitmap = await createImageBitmap(blob);\n result = { base64, width: bitmap.width, height: bitmap.height };\n bitmap.close();\n usedFallback = true;\n }\n }\n \n if (message.annotate && !usedFallback) {\n try {\n const treeResult = await chrome.tabs.sendMessage(tabId, {\n type: \"GET_ELEMENT_BOUNDS_FOR_ANNOTATION\",\n }, { frameId: 0 });\n \n if (treeResult?.elements && treeResult.elements.length > 0) {\n result = await annotateScreenshot(result, treeResult.elements, scaleInfo);\n }\n } catch {}\n }\n \n const screenshotId = generateScreenshotId();\n cacheScreenshot(screenshotId, result);\n return { ...result, screenshotId };\n } finally {\n try {\n await chrome.tabs.sendMessage(tabId, { type: \"SHOW_AFTER_TOOL_USE\" });\n } catch (e) {}\n }\n }\n\n case \"EXECUTE_CLICK\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const mods = message.modifiers ? cdp.parseModifiers(message.modifiers) : 0;\n await cdp.click(tabId, message.x, message.y, \"left\", 1, mods);\n return { success: true };\n }\n\n case \"EXECUTE_RIGHT_CLICK\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const mods = message.modifiers ? cdp.parseModifiers(message.modifiers) : 0;\n await cdp.rightClick(tabId, message.x, message.y, mods);\n return { success: true };\n }\n\n case \"EXECUTE_DOUBLE_CLICK\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const mods = message.modifiers ? cdp.parseModifiers(message.modifiers) : 0;\n await cdp.doubleClick(tabId, message.x, message.y, mods);\n return { success: true };\n }\n\n case \"EXECUTE_TRIPLE_CLICK\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const mods = message.modifiers ? cdp.parseModifiers(message.modifiers) : 0;\n await cdp.tripleClick(tabId, message.x, message.y, mods);\n return { success: true };\n }\n\n case \"EXECUTE_DRAG\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const mods = message.modifiers ? cdp.parseModifiers(message.modifiers) : 0;\n await cdp.drag(tabId, message.startX, message.startY, message.endX, message.endY, mods);\n return { success: true };\n }\n\n case \"EXECUTE_HOVER\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n await cdp.hover(tabId, message.x, message.y);\n return { success: true };\n }\n\n case \"EXECUTE_TYPE\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (message.text === undefined || message.text === null) throw new Error(\"No text provided\");\n await cdp.type(tabId, message.text);\n return { success: true };\n }\n\n case \"TYPE_SUBMIT\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (!message.text) throw new Error(\"No text provided\");\n await cdp.type(tabId, message.text);\n await cdp.pressKey(tabId, message.submitKey || \"Enter\");\n return { success: true };\n }\n\n case \"CLICK_TYPE\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (!message.text) throw new Error(\"No text provided\");\n const clickTypeFrameId = getFrameIdForTab(tabId);\n let clicked = false;\n if (message.ref) {\n try {\n const result = await chrome.tabs.sendMessage(tabId, { type: \"CLICK_ELEMENT\", ref: message.ref, button: \"left\" }, { frameId: clickTypeFrameId });\n if (!result.error) clicked = true;\n } catch {}\n }\n if (!clicked && message.coordinate) {\n await cdp.click(tabId, message.coordinate[0], message.coordinate[1], \"left\", 1, 0);\n clicked = true;\n }\n if (!clicked) {\n const result = await cdp.evaluateScript(tabId, `(() => {\n const el = document.querySelector('textarea, input[type=\"text\"], input[type=\"search\"], input:not([type]), [contenteditable=\"true\"]');\n if (!el) return null;\n const r = el.getBoundingClientRect();\n return { x: r.left + r.width/2, y: r.top + r.height/2 };\n })()`);\n if (result.result?.value) {\n await cdp.click(tabId, result.result.value.x, result.result.value.y, \"left\", 1, 0);\n clicked = true;\n }\n }\n if (!clicked) return { error: \"Could not find input element\" };\n await cdp.type(tabId, message.text);\n return { success: true };\n }\n\n case \"CLICK_TYPE_SUBMIT\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (!message.text) throw new Error(\"No text provided\");\n const clickTypeSubmitFrameId = getFrameIdForTab(tabId);\n let clicked = false;\n if (message.ref) {\n try {\n const result = await chrome.tabs.sendMessage(tabId, { type: \"CLICK_ELEMENT\", ref: message.ref, button: \"left\" }, { frameId: clickTypeSubmitFrameId });\n if (!result.error) clicked = true;\n } catch {}\n }\n if (!clicked && message.coordinate) {\n await cdp.click(tabId, message.coordinate[0], message.coordinate[1], \"left\", 1, 0);\n clicked = true;\n }\n if (!clicked) {\n const result = await cdp.evaluateScript(tabId, `(() => {\n const el = document.querySelector('textarea, input[type=\"text\"], input[type=\"search\"], input:not([type]), [contenteditable=\"true\"]');\n if (!el) return null;\n const r = el.getBoundingClientRect();\n return { x: r.left + r.width/2, y: r.top + r.height/2 };\n })()`);\n if (result.result?.value) {\n await cdp.click(tabId, result.result.value.x, result.result.value.y, \"left\", 1, 0);\n clicked = true;\n }\n }\n if (!clicked) return { error: \"Could not find input element\" };\n await cdp.type(tabId, message.text);\n await cdp.pressKey(tabId, message.submitKey || \"Enter\");\n return { success: true };\n }\n\n case \"FIND_AND_TYPE\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (!message.text) throw new Error(\"No text provided\");\n const findResult = await cdp.evaluateScript(tabId, `(() => {\n const selectors = [\n 'textarea:not([readonly]):not([disabled])',\n 'input[type=\"text\"]:not([readonly]):not([disabled])',\n 'input[type=\"search\"]:not([readonly]):not([disabled])',\n 'input:not([type]):not([readonly]):not([disabled])',\n '[contenteditable=\"true\"]',\n '[role=\"textbox\"]'\n ];\n for (const sel of selectors) {\n const el = document.querySelector(sel);\n if (el) {\n const r = el.getBoundingClientRect();\n if (r.width > 0 && r.height > 0) {\n el.focus();\n return { x: r.left + r.width/2, y: r.top + r.height/2, found: true };\n }\n }\n }\n return { found: false };\n })()`);\n const coords = findResult.result?.value;\n if (!coords?.found) return { error: \"No input field found on page\" };\n await cdp.click(tabId, coords.x, coords.y, \"left\", 1, 0);\n await cdp.type(tabId, message.text);\n if (message.submit) {\n await cdp.pressKey(tabId, message.submitKey || \"Enter\");\n }\n return { success: true, coordinates: { x: coords.x, y: coords.y } };\n }\n\n case \"AUTOCOMPLETE_SELECT\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (!message.text) throw new Error(\"No text provided\");\n const autocompleteFrameId = getFrameIdForTab(tabId);\n let clicked = false;\n if (message.ref) {\n try {\n const result = await chrome.tabs.sendMessage(tabId, { type: \"CLICK_ELEMENT\", ref: message.ref, button: \"left\" }, { frameId: autocompleteFrameId });\n if (!result.error) clicked = true;\n } catch {}\n }\n if (!clicked && message.coordinate) {\n await cdp.click(tabId, message.coordinate[0], message.coordinate[1], \"left\", 1, 0);\n clicked = true;\n }\n if (!clicked) return { error: \"ref or coordinate required\" };\n await new Promise(r => setTimeout(r, 100));\n await cdp.type(tabId, message.text);\n const waitMs = message.waitMs || 500;\n await new Promise(r => setTimeout(r, waitMs));\n if (message.index && message.index > 0) {\n for (let i = 0; i < message.index; i++) {\n await cdp.pressKey(tabId, \"ArrowDown\");\n await new Promise(r => setTimeout(r, 50));\n }\n }\n await cdp.pressKey(tabId, \"Enter\");\n return { success: true };\n }\n\n case \"SET_INPUT_VALUE\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (message.value === undefined) throw new Error(\"No value provided\");\n const selector = message.selector;\n const ref = message.ref;\n if (!selector && !ref) throw new Error(\"selector or ref required\");\n \n const script = ref \n ? `(() => {\n const el = document.querySelector('[data-pi-ref=\"${ref}\"]') || \n [...document.querySelectorAll('*')].find(e => e.getAttribute?.('data-ref') === '${ref}');\n if (!el) return { error: 'Element not found' };\n el.focus();\n const isContentEditable = el.isContentEditable || el.getAttribute('contenteditable') === 'true';\n const target = isContentEditable ? (el.querySelector('p') || el) : el;\n if (isContentEditable) {\n target.textContent = ${JSON.stringify(message.value)};\n } else {\n el.value = ${JSON.stringify(message.value)};\n }\n el.dispatchEvent(new Event('input', { bubbles: true }));\n el.dispatchEvent(new Event('change', { bubbles: true }));\n return { success: true, contentEditable: isContentEditable };\n })()`\n : `(() => {\n const el = document.querySelector(${JSON.stringify(selector)});\n if (!el) return { error: 'Element not found: ' + ${JSON.stringify(selector)} };\n el.focus();\n const isContentEditable = el.isContentEditable || el.getAttribute('contenteditable') === 'true';\n const target = isContentEditable ? (el.querySelector('p') || el) : el;\n if (isContentEditable) {\n target.textContent = ${JSON.stringify(message.value)};\n } else {\n el.value = ${JSON.stringify(message.value)};\n }\n el.dispatchEvent(new Event('input', { bubbles: true }));\n el.dispatchEvent(new Event('change', { bubbles: true }));\n return { success: true, contentEditable: isContentEditable };\n })()`;\n \n const result = await cdp.evaluateScript(tabId, script);\n return result.result?.value || { error: \"Script failed\" };\n }\n\n case \"SMART_TYPE\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const { selector, text, clear = true, submit = false } = message;\n if (!selector) throw new Error(\"selector required\");\n if (text === undefined) throw new Error(\"text required\");\n \n const script = `(() => {\n const el = document.querySelector(${JSON.stringify(selector)});\n if (!el) return { error: 'Element not found: ' + ${JSON.stringify(selector)} };\n \n const isContentEditable = el.isContentEditable || \n el.getAttribute('contenteditable') === 'true';\n const hasContentEditableChild = el.querySelector('[contenteditable=\"true\"]');\n \n const target = hasContentEditableChild || el;\n const useContentEditable = isContentEditable || !!hasContentEditableChild;\n \n target.focus();\n \n if (${clear}) {\n if (useContentEditable) {\n target.textContent = '';\n } else {\n target.value = '';\n }\n }\n \n if (useContentEditable) {\n target.textContent = ${JSON.stringify(text)};\n } else {\n target.value = ${JSON.stringify(text)};\n }\n \n target.dispatchEvent(new Event('input', { bubbles: true }));\n target.dispatchEvent(new Event('change', { bubbles: true }));\n \n if (${submit}) {\n const form = el.closest('form');\n const submitBtn = document.querySelector('button[type=\"submit\"], button[data-testid*=\"send\"], button[aria-label*=\"Send\"]');\n if (submitBtn) {\n submitBtn.click();\n } else if (form) {\n form.dispatchEvent(new Event('submit', { bubbles: true }));\n } else {\n target.dispatchEvent(new KeyboardEvent('keydown', { key: 'Enter', code: 'Enter', keyCode: 13, bubbles: true }));\n }\n }\n \n return { success: true, contentEditable: useContentEditable };\n })()`;\n \n const result = await cdp.evaluateScript(tabId, script);\n return result.result?.value || { error: \"Script failed\" };\n }\n\n case \"CLOSE_DIALOGS\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const maxAttempts = message.maxAttempts || 3;\n for (let i = 0; i < maxAttempts; i++) {\n await cdp.pressKey(tabId, \"Escape\");\n await new Promise(r => setTimeout(r, 100));\n }\n return { success: true };\n }\n\n case \"PAGE_STATE\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const stateScript = `(() => {\n const hasModal = !!(\n document.querySelector('[role=\"dialog\"]') ||\n document.querySelector('[role=\"alertdialog\"]') ||\n document.querySelector('.modal:not([hidden])') ||\n document.querySelector('[aria-modal=\"true\"]') ||\n document.querySelector('.MuiModal-root') ||\n document.querySelector('.MuiDialog-root')\n );\n const hasDropdown = !!(\n document.querySelector('[role=\"listbox\"]') ||\n document.querySelector('[role=\"menu\"]:not([hidden])') ||\n document.querySelector('.dropdown-menu.show') ||\n document.querySelector('[aria-expanded=\"true\"]')\n );\n const hasDatePicker = !!(\n document.querySelector('[role=\"grid\"][aria-label*=\"calendar\" i]') ||\n document.querySelector('.react-datepicker') ||\n document.querySelector('.flatpickr-calendar.open') ||\n document.querySelector('[class*=\"DatePicker\"]')\n );\n const focusedEl = document.activeElement;\n const focusedTag = focusedEl?.tagName?.toLowerCase();\n const focusedType = focusedEl?.getAttribute?.('type');\n return {\n hasModal,\n hasDropdown,\n hasDatePicker,\n hasOverlay: hasModal || hasDropdown || hasDatePicker,\n focusedElement: focusedTag ? { tag: focusedTag, type: focusedType } : null,\n url: location.href,\n title: document.title\n };\n })()`;\n const stateResult = await cdp.evaluateScript(tabId, stateScript);\n return stateResult.result?.value || { error: \"Failed to get page state\" };\n }\n\n case \"EXECUTE_SCROLL\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const deltaX = message.deltaX || 0;\n const deltaY = message.deltaY || 0;\n \n try {\n const viewport = await cdp.getViewportSize(tabId);\n const x = message.x ?? viewport.width / 2;\n const y = message.y ?? viewport.height / 2;\n await cdp.scroll(tabId, x, y, deltaX, deltaY);\n } catch {\n try {\n const scrollFallback = (dx: number, dy: number) => {\n window.scrollBy(dx, dy);\n return { scrollX: window.scrollX, scrollY: window.scrollY };\n };\n await chrome.scripting.executeScript({\n target: { tabId },\n func: scrollFallback,\n args: [deltaX, deltaY],\n });\n } catch {\n return { error: \"Cannot scroll on this page (restricted)\" };\n }\n }\n return { success: true };\n }\n\n case \"EXECUTE_KEY\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const key = message.key;\n if (!key) throw new Error(\"No key provided\");\n if (key.includes(\"+\")) {\n await cdp.pressKeyChord(tabId, key);\n } else {\n await cdp.pressKey(tabId, key);\n }\n return { success: true };\n }\n\n case \"EXECUTE_NAVIGATE\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (!message.url) throw new Error(\"No url provided\");\n \n const navigationPromise = new Promise<void>((resolve) => {\n navigationResolvers.set(tabId, resolve);\n setTimeout(() => {\n if (navigationResolvers.has(tabId)) {\n navigationResolvers.delete(tabId);\n resolve();\n }\n }, 30000);\n });\n \n await chrome.tabs.update(tabId, { url: message.url });\n await navigationPromise;\n \n await new Promise(resolve => setTimeout(resolve, 500));\n \n return { success: true };\n }\n\n case \"GET_VIEWPORT_SIZE\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n return await cdp.getViewportSize(tabId);\n }\n\n case \"READ_PAGE\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const readFrameId = getFrameIdForTab(tabId);\n try {\n await chrome.tabs.sendMessage(tabId, { type: \"HIDE_FOR_TOOL_USE\" }, { frameId: 0 });\n } catch (e) {}\n await new Promise(resolve => setTimeout(resolve, 50));\n \n let result;\n try {\n result = await chrome.tabs.sendMessage(tabId, {\n type: \"GENERATE_ACCESSIBILITY_TREE\",\n options: message.options || {},\n }, { frameId: readFrameId });\n } catch (err) {\n return { \n error: \"Content script not loaded. Try refreshing the page.\",\n pageContent: \"\",\n viewport: { width: 0, height: 0 }\n };\n } finally {\n try {\n await chrome.tabs.sendMessage(tabId, { type: \"SHOW_AFTER_TOOL_USE\" });\n } catch (e) {}\n }\n \n // Include visible text content if requested\n if (message.options?.includeText) {\n try {\n const textResult = await chrome.tabs.sendMessage(tabId, { type: \"GET_PAGE_TEXT\" }, { frameId: readFrameId });\n if (textResult?.text) {\n result.text = textResult.text;\n }\n } catch (err) {\n // Ignore text extraction errors\n }\n }\n \n if (message.options?.includeScreenshot) {\n try {\n const screenshot = await cdp.captureScreenshot(tabId);\n return { ...result, screenshot };\n } catch (err) {\n return { ...result, screenshotError: \"Failed to capture screenshot\" };\n }\n }\n return result;\n }\n\n case \"GET_ELEMENT_COORDINATES\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n try {\n return await chrome.tabs.sendMessage(tabId, {\n type: \"GET_ELEMENT_COORDINATES\",\n ref: message.ref,\n }, { frameId: getFrameIdForTab(tabId) });\n } catch (err) {\n return { error: \"Content script not loaded. Try refreshing the page.\" };\n }\n }\n\n case \"FORM_INPUT\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n try {\n return await chrome.tabs.sendMessage(tabId, {\n type: \"FORM_INPUT\",\n ref: message.ref,\n value: message.value,\n }, { frameId: getFrameIdForTab(tabId) });\n } catch (err) {\n return { error: \"Content script not loaded. Try refreshing the page.\" };\n }\n }\n\n case \"EVAL_IN_PAGE\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (!message.code) throw new Error(\"No code provided\");\n try {\n return await chrome.tabs.sendMessage(tabId, {\n type: \"EVAL_IN_PAGE\",\n code: message.code,\n }, { frameId: getFrameIdForTab(tabId) });\n } catch (err) {\n return { error: \"Content script not loaded. Try refreshing the page.\" };\n }\n }\n\n case \"SCROLL_TO_ELEMENT\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n try {\n return await chrome.tabs.sendMessage(tabId, {\n type: \"SCROLL_TO_ELEMENT\",\n ref: message.ref,\n }, { frameId: getFrameIdForTab(tabId) });\n } catch (err) {\n return { error: \"Content script not loaded. Try refreshing the page.\" };\n }\n }\n\n case \"SCROLL_TO_POSITION\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const position = message.position;\n if (position === undefined) throw new Error(\"position required (\\\"top\\\", \\\"bottom\\\", or number)\");\n const selector = message.selector;\n \n const scrollScript = (pos: string | number, sel: string | null) => {\n const findScrollable = (): Element => {\n const candidates = [...document.querySelectorAll(\"*\")].filter(el => \n el.scrollHeight > el.clientHeight && el.clientHeight > 200\n ).sort((a,b) => b.scrollHeight - a.scrollHeight);\n return candidates[0] || document.documentElement;\n };\n \n const container = sel ? document.querySelector(sel) || findScrollable() : findScrollable();\n if (!container) return { error: \"No scrollable container found\" };\n \n if (pos === \"bottom\") {\n container.scrollTop = container.scrollHeight;\n } else if (pos === \"top\") {\n container.scrollTop = 0;\n } else if (typeof pos === \"number\") {\n container.scrollTop = pos;\n }\n \n return { \n scrollTop: container.scrollTop,\n scrollHeight: container.scrollHeight,\n clientHeight: container.clientHeight,\n atBottom: container.scrollTop + container.clientHeight >= container.scrollHeight - 10,\n atTop: container.scrollTop < 10\n };\n };\n \n try {\n const script = `(${scrollScript.toString()})(${JSON.stringify(position)}, ${JSON.stringify(selector)})`;\n const result = await cdp.evaluateScript(tabId, script);\n return result.result?.value || { error: \"Script failed\" };\n } catch {\n try {\n const results = await chrome.scripting.executeScript({\n target: { tabId },\n func: scrollScript,\n args: [position, selector],\n });\n return results[0]?.result || { error: \"Script failed\" };\n } catch {\n return { error: \"Cannot scroll on this page (restricted)\" };\n }\n }\n }\n\n case \"GET_SCROLL_INFO\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const selector = message.selector;\n \n const scrollInfoScript = (sel: string | null) => {\n const findScrollable = (): Element => {\n const candidates = [...document.querySelectorAll(\"*\")].filter(el => \n el.scrollHeight > el.clientHeight && el.clientHeight > 200\n ).sort((a,b) => b.scrollHeight - a.scrollHeight);\n return candidates[0] || document.documentElement;\n };\n \n const container = sel ? document.querySelector(sel) || findScrollable() : findScrollable();\n if (!container) return { error: \"No scrollable container found\" };\n \n const maxScroll = container.scrollHeight - container.clientHeight;\n return { \n scrollTop: container.scrollTop,\n scrollHeight: container.scrollHeight,\n clientHeight: container.clientHeight,\n atBottom: container.scrollTop + container.clientHeight >= container.scrollHeight - 10,\n atTop: container.scrollTop < 10,\n scrollPercentage: maxScroll > 0 ? Math.round((container.scrollTop / maxScroll) * 100) : 100\n };\n };\n \n try {\n const script = `(${scrollInfoScript.toString()})(${JSON.stringify(selector)})`;\n const result = await cdp.evaluateScript(tabId, script);\n return result.result?.value || { error: \"Script failed\" };\n } catch {\n try {\n const results = await chrome.scripting.executeScript({\n target: { tabId },\n func: scrollInfoScript,\n args: [selector],\n });\n return results[0]?.result || { error: \"Script failed\" };\n } catch {\n return { error: \"Cannot get scroll info on this page (restricted)\" };\n }\n }\n }\n\n case \"GET_PAGE_TEXT\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n try {\n return await chrome.tabs.sendMessage(tabId, { type: \"GET_PAGE_TEXT\" }, { frameId: getFrameIdForTab(tabId) });\n } catch (err) {\n return { error: \"Content script not loaded. Try refreshing the page.\" };\n }\n }\n\n case \"LOCATE_ROLE\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (!message.role) throw new Error(\"role required\");\n const locateFrameId = getFrameIdForTab(tabId);\n \n try {\n const result = await chrome.tabs.sendMessage(tabId, {\n type: \"LOCATE_ROLE\",\n role: message.role,\n name: message.name,\n all: message.all,\n }, { frameId: locateFrameId });\n \n if (result.error) return result;\n \n // Perform action if specified\n if (message.action && result.ref) {\n return await performLocateAction(tabId, result.ref, message.action, message.value, cdp, locateFrameId);\n }\n \n return result;\n } catch (err) {\n return { error: \"Content script not loaded. Try refreshing the page.\" };\n }\n }\n\n case \"LOCATE_TEXT\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (!message.text) throw new Error(\"text required\");\n const textFrameId = getFrameIdForTab(tabId);\n \n try {\n const result = await chrome.tabs.sendMessage(tabId, {\n type: \"LOCATE_TEXT\",\n text: message.text,\n exact: message.exact,\n }, { frameId: textFrameId });\n \n if (result.error) return result;\n \n // Perform action if specified\n if (message.action && result.ref) {\n return await performLocateAction(tabId, result.ref, message.action, message.value, cdp, textFrameId);\n }\n \n return result;\n } catch (err) {\n return { error: \"Content script not loaded. Try refreshing the page.\" };\n }\n }\n\n case \"LOCATE_LABEL\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (!message.label) throw new Error(\"label required\");\n const labelFrameId = getFrameIdForTab(tabId);\n \n try {\n const result = await chrome.tabs.sendMessage(tabId, {\n type: \"LOCATE_LABEL\",\n label: message.label,\n }, { frameId: labelFrameId });\n \n if (result.error) return result;\n \n // Perform action if specified\n if (message.action && result.ref) {\n return await performLocateAction(tabId, result.ref, message.action, message.value, cdp, labelFrameId);\n }\n \n return result;\n } catch (err) {\n return { error: \"Content script not loaded. Try refreshing the page.\" };\n }\n }\n\n case \"GET_ELEMENT_STYLES\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (!message.selector) throw new Error(\"selector required\");\n const stylesFrameId = getFrameIdForTab(tabId);\n \n try {\n const result = await chrome.tabs.sendMessage(tabId, {\n type: \"GET_ELEMENT_STYLES\",\n selector: message.selector,\n }, { frameId: stylesFrameId });\n \n return result;\n } catch (err) {\n return { error: \"Content script not loaded. Try refreshing the page.\" };\n }\n }\n\n case \"SELECT_OPTION\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (!message.selector) throw new Error(\"selector required\");\n if (!message.values) throw new Error(\"values required\");\n const selectFrameId = getFrameIdForTab(tabId);\n \n try {\n const result = await chrome.tabs.sendMessage(tabId, {\n type: \"SELECT_OPTION\",\n selector: message.selector,\n values: message.values,\n by: message.by || \"value\",\n }, { frameId: selectFrameId });\n \n return result;\n } catch (err) {\n return { error: \"Content script not loaded. Try refreshing the page.\" };\n }\n }\n\n case \"SHOW_AGENT_INDICATORS\":\n case \"HIDE_AGENT_INDICATORS\":\n case \"SHOW_STATIC_INDICATOR\":\n case \"HIDE_STATIC_INDICATOR\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n try {\n return await chrome.tabs.sendMessage(tabId, { type: message.type });\n } catch (err) {\n return { error: \"Content script not loaded. Try refreshing the page.\" };\n }\n }\n\n case \"STOP_AGENT\": {\n const fromTabId = message.fromTabId;\n let targetTabId: number | undefined;\n \n if (fromTabId === \"CURRENT_TAB\" && sender.tab?.id) {\n targetTabId = sender.tab.id;\n } else if (typeof fromTabId === \"number\") {\n targetTabId = fromTabId;\n }\n \n if (targetTabId) {\n chrome.runtime.sendMessage({ type: \"STOP_AGENT\", targetTabId });\n }\n return { success: true };\n }\n\n case \"DISMISS_STATIC_INDICATOR\": {\n return { success: true };\n }\n\n case \"STATIC_INDICATOR_HEARTBEAT\": {\n return { success: true };\n }\n\n case \"CLICK_REF\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n try {\n const result = await chrome.tabs.sendMessage(tabId, {\n type: \"CLICK_ELEMENT\",\n ref: message.ref,\n button: message.button || \"left\",\n }, { frameId: getFrameIdForTab(tabId) });\n if (result.error) return { error: result.error };\n return { success: true };\n } catch (err) {\n return { error: \"Content script not loaded. Try refreshing the page.\" };\n }\n }\n\n case \"HOVER_REF\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n try {\n const coords = await chrome.tabs.sendMessage(tabId, {\n type: \"GET_ELEMENT_COORDINATES\",\n ref: message.ref,\n }, { frameId: getFrameIdForTab(tabId) });\n if (coords.error) return { error: coords.error };\n await cdp.hover(tabId, coords.x, coords.y);\n return { success: true };\n } catch (err) {\n return { error: \"Content script not loaded. Try refreshing the page.\" };\n }\n }\n\n case \"PING\": {\n return { success: true, status: \"connected\" };\n }\n\n case \"HEALTH_CHECK_URL\": {\n if (!message.url) throw new Error(\"No url provided\");\n const timeout = message.timeout || 30000;\n const expect = message.expect || 200;\n const startTime = Date.now();\n const pollInterval = 500;\n\n let lastError: string | null = null;\n while (Date.now() - startTime < timeout) {\n try {\n const response = await fetch(message.url, { method: \"GET\" });\n await response.text();\n if (response.status === expect) {\n return { success: true, status: response.status, time: Date.now() - startTime };\n }\n lastError = `Got status ${response.status}`;\n } catch (e) {\n lastError = e instanceof Error ? e.message : String(e);\n }\n await new Promise((r) => setTimeout(r, pollInterval));\n }\n return { \n error: `Timeout waiting for ${message.url} to return ${expect}`, \n lastError,\n time: Date.now() - startTime \n };\n }\n\n case \"SMOKE_TEST\": {\n const urls: string[] = message.urls || [];\n const captureScreenshots: boolean = message.savePath !== undefined;\n const failFast: boolean = message.failFast || false;\n \n if (urls.length === 0) {\n return { error: \"No URLs provided for smoke test\" };\n }\n\n const results: Array<{\n url: string;\n status: \"pass\" | \"fail\";\n time: number;\n errors: string[];\n screenshotBase64?: string;\n hostname?: string;\n }> = [];\n\n let pass = 0;\n let fail = 0;\n\n for (const url of urls) {\n const startTime = Date.now();\n const errors: string[] = [];\n let screenshotBase64: string | undefined;\n let hostname: string | undefined;\n let testTabId: number | undefined;\n\n try {\n hostname = new URL(url).hostname.replace(/[^a-zA-Z0-9.-]/g, \"_\");\n const testTab = await chrome.tabs.create({ url, active: false });\n if (!testTab.id) throw new Error(\"Failed to create tab\");\n testTabId = testTab.id;\n\n try {\n await cdp.enableConsoleTracking(testTabId);\n } catch (e) {}\n\n await new Promise<void>((resolve) => {\n const onComplete = (details: chrome.webNavigation.WebNavigationFramedCallbackDetails) => {\n if (details.tabId === testTabId && details.frameId === 0) {\n chrome.webNavigation.onCompleted.removeListener(onComplete);\n chrome.webNavigation.onErrorOccurred.removeListener(onError);\n resolve();\n }\n };\n const onError = (details: chrome.webNavigation.WebNavigationFramedErrorCallbackDetails) => {\n if (details.tabId === testTabId && details.frameId === 0) {\n chrome.webNavigation.onCompleted.removeListener(onComplete);\n chrome.webNavigation.onErrorOccurred.removeListener(onError);\n errors.push(`Navigation error: ${details.error}`);\n resolve();\n }\n };\n chrome.webNavigation.onCompleted.addListener(onComplete);\n chrome.webNavigation.onErrorOccurred.addListener(onError);\n setTimeout(() => {\n chrome.webNavigation.onCompleted.removeListener(onComplete);\n chrome.webNavigation.onErrorOccurred.removeListener(onError);\n errors.push(\"Navigation timeout (30s)\");\n resolve();\n }, 30000);\n });\n\n await new Promise(r => setTimeout(r, 2000));\n\n const consoleMessages = cdp.getConsoleMessages(testTabId, { onlyErrors: true, limit: 50 });\n for (const msg of consoleMessages) {\n errors.push(`[${msg.type}] ${msg.text}`);\n }\n\n if (captureScreenshots) {\n try {\n const screenshot = await cdp.captureScreenshot(testTabId);\n screenshotBase64 = screenshot.base64;\n } catch (e) {}\n }\n } catch (e) {\n errors.push(e instanceof Error ? e.message : String(e));\n } finally {\n if (testTabId) {\n try { await chrome.tabs.remove(testTabId); } catch {}\n }\n }\n\n const elapsed = Date.now() - startTime;\n const status = errors.length === 0 ? \"pass\" : \"fail\";\n if (status === \"pass\") pass++;\n else fail++;\n\n results.push({\n url,\n status,\n time: elapsed,\n errors,\n ...(screenshotBase64 && { screenshotBase64, hostname }),\n });\n\n if (failFast && status === \"fail\") {\n break;\n }\n }\n\n return {\n results,\n summary: { pass, fail, total: results.length },\n savePath: message.savePath,\n };\n }\n\n case \"WAIT_FOR_ELEMENT\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (!message.selector) throw new Error(\"No selector provided\");\n const waitFrameId = getFrameIdForTab(tabId);\n \n try {\n await chrome.tabs.sendMessage(tabId, { type: \"HIDE_FOR_TOOL_USE\" }, { frameId: 0 });\n } catch (e) {}\n await new Promise(resolve => setTimeout(resolve, 50));\n \n try {\n const result = await chrome.tabs.sendMessage(tabId, {\n type: \"WAIT_FOR_ELEMENT\",\n selector: message.selector,\n state: message.state || \"visible\",\n timeout: message.timeout || 20000,\n }, { frameId: waitFrameId });\n return result;\n } catch (err) {\n return { \n error: \"Content script not loaded. Try refreshing the page.\",\n pageContent: \"\",\n viewport: { width: 0, height: 0 }\n };\n } finally {\n try {\n await chrome.tabs.sendMessage(tabId, { type: \"SHOW_AFTER_TOOL_USE\" });\n } catch (e) {}\n }\n }\n\n case \"WAIT_FOR_URL\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (!message.pattern) throw new Error(\"No URL pattern provided\");\n \n try {\n await chrome.tabs.sendMessage(tabId, { type: \"HIDE_FOR_TOOL_USE\" }, { frameId: 0 });\n } catch (e) {}\n await new Promise(resolve => setTimeout(resolve, 50));\n \n try {\n const result = await chrome.tabs.sendMessage(tabId, {\n type: \"WAIT_FOR_URL\",\n pattern: message.pattern,\n timeout: message.timeout || 20000,\n }, { frameId: 0 });\n return result;\n } catch (err) {\n return { \n error: \"Content script not loaded. Try refreshing the page.\",\n pageContent: \"\",\n viewport: { width: 0, height: 0 }\n };\n } finally {\n try {\n await chrome.tabs.sendMessage(tabId, { type: \"SHOW_AFTER_TOOL_USE\" });\n } catch (e) {}\n }\n }\n\n case \"WAIT_FOR_NETWORK_IDLE\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n \n try {\n await chrome.tabs.sendMessage(tabId, { type: \"HIDE_FOR_TOOL_USE\" }, { frameId: 0 });\n } catch (e) {}\n await new Promise(resolve => setTimeout(resolve, 50));\n \n try {\n const result = await chrome.tabs.sendMessage(tabId, {\n type: \"WAIT_FOR_NETWORK_IDLE\",\n timeout: message.timeout || 10000,\n }, { frameId: 0 });\n return result;\n } catch (err) {\n return { \n error: \"Content script not loaded. Try refreshing the page.\",\n pageContent: \"\",\n viewport: { width: 0, height: 0 }\n };\n } finally {\n try {\n await chrome.tabs.sendMessage(tabId, { type: \"SHOW_AFTER_TOOL_USE\" });\n } catch (e) {}\n }\n }\n\n case \"WAIT_FOR_DOM_STABLE\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n \n try {\n await chrome.tabs.sendMessage(tabId, { type: \"HIDE_FOR_TOOL_USE\" }, { frameId: 0 });\n } catch (e) {}\n await new Promise(resolve => setTimeout(resolve, 50));\n \n try {\n const result = await chrome.tabs.sendMessage(tabId, {\n type: \"WAIT_FOR_DOM_STABLE\",\n stable: message.stable || 100,\n timeout: message.timeout || 5000,\n }, { frameId: 0 });\n return result;\n } catch (err) {\n return { \n error: \"Content script not loaded. Try refreshing the page.\",\n pageContent: \"\",\n viewport: { width: 0, height: 0 }\n };\n } finally {\n try {\n await chrome.tabs.sendMessage(tabId, { type: \"SHOW_AFTER_TOOL_USE\" }, { frameId: 0 });\n } catch (e) {}\n }\n }\n\n case \"DIALOG_ACCEPT\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const result = await cdp.handleDialog(tabId, true, message.text);\n return result;\n }\n\n case \"DIALOG_DISMISS\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const result = await cdp.handleDialog(tabId, false);\n return result;\n }\n\n case \"DIALOG_INFO\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const dialog = cdp.getDialogInfo(tabId);\n if (!dialog) {\n return { hasDialog: false };\n }\n return {\n hasDialog: true,\n type: dialog.type,\n message: dialog.message,\n defaultPrompt: dialog.defaultPrompt,\n };\n }\n\n case \"EMULATE_NETWORK\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (!message.preset) throw new Error(\"No preset provided\");\n const result = await cdp.emulateNetwork(tabId, message.preset);\n if (!result.success) throw new Error(result.error);\n return { success: true, preset: message.preset };\n }\n\n case \"EMULATE_CPU\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (message.rate === undefined) throw new Error(\"No rate provided\");\n const result = await cdp.emulateCPU(tabId, message.rate);\n if (!result.success) throw new Error(result.error);\n return { success: true, rate: message.rate };\n }\n\n case \"EMULATE_GEO\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (message.clear) {\n const result = await cdp.clearGeolocation(tabId);\n if (!result.success) throw new Error(result.error);\n return { success: true, cleared: true };\n }\n if (message.latitude === undefined || message.longitude === undefined) {\n throw new Error(\"Latitude and longitude required\");\n }\n const result = await cdp.emulateGeolocation(tabId, message.latitude, message.longitude, message.accuracy);\n if (!result.success) throw new Error(result.error);\n return { success: true, latitude: message.latitude, longitude: message.longitude };\n }\n\n case \"EMULATE_DEVICE_LIST\": {\n // Return list of available devices - handled in CLI\n const devices = [\n \"iPhone 12\", \"iPhone 13\", \"iPhone 14\", \"iPhone 14 Pro\", \"iPhone 14 Pro Max\", \"iPhone SE\",\n \"iPad\", \"iPad Pro\", \"iPad Mini\",\n \"Pixel 5\", \"Pixel 6\", \"Pixel 7\", \"Pixel 7 Pro\",\n \"Galaxy S21\", \"Galaxy S22\", \"Galaxy S23\", \"Galaxy Tab S7\",\n \"Nest Hub\", \"Nest Hub Max\"\n ];\n return { devices };\n }\n\n case \"EMULATE_DEVICE\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const deviceName = message.device;\n \n // Handle reset\n if (deviceName.toLowerCase() === \"reset\") {\n const result = await cdp.clearDeviceEmulation(tabId);\n if (!result.success) throw new Error(result.error);\n return { success: true, message: \"Device emulation reset\" };\n }\n \n // Device presets (synced with device-presets.cjs)\n const presets: Record<string, { width: number; height: number; deviceScaleFactor: number; mobile: boolean; touch: boolean; userAgent: string }> = {\n // Apple devices\n \"iPhone 12\": { width: 390, height: 844, deviceScaleFactor: 3, mobile: true, touch: true, userAgent: \"Mozilla/5.0 (iPhone; CPU iPhone OS 14_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0 Mobile/15E148 Safari/604.1\" },\n \"iPhone 13\": { width: 390, height: 844, deviceScaleFactor: 3, mobile: true, touch: true, userAgent: \"Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.0 Mobile/15E148 Safari/604.1\" },\n \"iPhone 14\": { width: 390, height: 844, deviceScaleFactor: 3, mobile: true, touch: true, userAgent: \"Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.0 Mobile/15E148 Safari/604.1\" },\n \"iPhone 14 Pro\": { width: 393, height: 852, deviceScaleFactor: 3, mobile: true, touch: true, userAgent: \"Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.0 Mobile/15E148 Safari/604.1\" },\n \"iPhone 14 Pro Max\": { width: 430, height: 932, deviceScaleFactor: 3, mobile: true, touch: true, userAgent: \"Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.0 Mobile/15E148 Safari/604.1\" },\n \"iPhone SE\": { width: 375, height: 667, deviceScaleFactor: 2, mobile: true, touch: true, userAgent: \"Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.0 Mobile/15E148 Safari/604.1\" },\n \"iPad\": { width: 768, height: 1024, deviceScaleFactor: 2, mobile: true, touch: true, userAgent: \"Mozilla/5.0 (iPad; CPU OS 14_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0 Mobile/15E148 Safari/604.1\" },\n \"iPad Pro\": { width: 1024, height: 1366, deviceScaleFactor: 2, mobile: true, touch: true, userAgent: \"Mozilla/5.0 (iPad; CPU OS 14_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0 Mobile/15E148 Safari/604.1\" },\n \"iPad Mini\": { width: 768, height: 1024, deviceScaleFactor: 2, mobile: true, touch: true, userAgent: \"Mozilla/5.0 (iPad; CPU OS 14_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0 Mobile/15E148 Safari/604.1\" },\n // Google devices\n \"Pixel 5\": { width: 393, height: 851, deviceScaleFactor: 2.75, mobile: true, touch: true, userAgent: \"Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.91 Mobile Safari/537.36\" },\n \"Pixel 6\": { width: 412, height: 915, deviceScaleFactor: 2.625, mobile: true, touch: true, userAgent: \"Mozilla/5.0 (Linux; Android 12; Pixel 6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Mobile Safari/537.36\" },\n \"Pixel 7\": { width: 412, height: 915, deviceScaleFactor: 2.625, mobile: true, touch: true, userAgent: \"Mozilla/5.0 (Linux; Android 13; Pixel 7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Mobile Safari/537.36\" },\n \"Pixel 7 Pro\": { width: 412, height: 892, deviceScaleFactor: 3.5, mobile: true, touch: true, userAgent: \"Mozilla/5.0 (Linux; Android 13; Pixel 7 Pro) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Mobile Safari/537.36\" },\n // Samsung devices\n \"Galaxy S21\": { width: 360, height: 800, deviceScaleFactor: 3, mobile: true, touch: true, userAgent: \"Mozilla/5.0 (Linux; Android 11; SM-G991B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.210 Mobile Safari/537.36\" },\n \"Galaxy S22\": { width: 360, height: 780, deviceScaleFactor: 3, mobile: true, touch: true, userAgent: \"Mozilla/5.0 (Linux; Android 12; SM-S901B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Mobile Safari/537.36\" },\n \"Galaxy S23\": { width: 360, height: 780, deviceScaleFactor: 3, mobile: true, touch: true, userAgent: \"Mozilla/5.0 (Linux; Android 13; SM-S911B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Mobile Safari/537.36\" },\n \"Galaxy Tab S7\": { width: 800, height: 1280, deviceScaleFactor: 2, mobile: true, touch: true, userAgent: \"Mozilla/5.0 (Linux; Android 10; SM-T870) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.91 Safari/537.36\" },\n // Other\n \"Nest Hub\": { width: 1024, height: 600, deviceScaleFactor: 2, mobile: false, touch: true, userAgent: \"Mozilla/5.0 (Linux; Android) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.109 Safari/537.36 CrKey/1.54.248666\" },\n \"Nest Hub Max\": { width: 1280, height: 800, deviceScaleFactor: 2, mobile: false, touch: true, userAgent: \"Mozilla/5.0 (Linux; Android) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.109 Safari/537.36 CrKey/1.54.248666\" },\n };\n \n // Find matching device (case-insensitive partial match, prefer longest match)\n type DevicePreset = { width: number; height: number; deviceScaleFactor: number; mobile: boolean; touch: boolean; userAgent: string };\n let device: DevicePreset | undefined = presets[deviceName];\n if (!device) {\n const lowerName = deviceName.toLowerCase();\n let bestMatch: { name: string; preset: DevicePreset } | null = null;\n \n for (const [name, preset] of Object.entries(presets)) {\n const presetLower = name.toLowerCase();\n const presetNoSpaces = presetLower.replace(/\\s+/g, \"\");\n \n // Check if it's a match\n if (presetLower.includes(lowerName) || lowerName.includes(presetNoSpaces)) {\n // Prefer longer matches (more specific devices)\n if (!bestMatch || name.length > bestMatch.name.length) {\n bestMatch = { name, preset };\n }\n }\n }\n \n if (bestMatch) {\n device = bestMatch.preset;\n }\n }\n \n if (!device) {\n throw new Error(`Unknown device: ${deviceName}. Use --list to see available devices.`);\n }\n \n const result = await cdp.emulateDevice(tabId, device);\n if (!result.success) throw new Error(result.error);\n return { success: true, device: deviceName };\n }\n\n case \"EMULATE_VIEWPORT\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (!message.width && !message.height) {\n throw new Error(\"--width or --height required\");\n }\n const result = await cdp.emulateViewport(tabId, {\n width: message.width,\n height: message.height,\n deviceScaleFactor: message.deviceScaleFactor,\n mobile: message.mobile,\n });\n if (!result.success) throw new Error(result.error);\n return { success: true, width: message.width, height: message.height };\n }\n\n case \"EMULATE_TOUCH\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const result = await cdp.emulateTouch(tabId, message.enabled);\n if (!result.success) throw new Error(result.error);\n return { success: true, enabled: message.enabled };\n }\n\n case \"FORM_FILL\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (!message.data) throw new Error(\"No data provided\");\n const response = await chrome.tabs.sendMessage(tabId, {\n type: \"FORM_FILL\",\n data: message.data,\n }, { frameId: getFrameIdForTab(tabId) });\n return response;\n }\n\n case \"PERF_START\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const result = await cdp.startPerformanceTrace(tabId, message.categories);\n if (!result.success) throw new Error(result.error);\n return { success: true, message: \"Performance tracing started\" };\n }\n\n case \"PERF_STOP\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const result = await cdp.stopPerformanceTrace(tabId);\n if (!result.success) throw new Error(result.error);\n return { success: true, metrics: result.metrics };\n }\n\n case \"PERF_METRICS\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const result = await cdp.getPerformanceMetrics(tabId);\n if (!result.success) throw new Error(result.error);\n return { success: true, metrics: result.metrics };\n }\n\n case \"UPLOAD_FILE\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (!message.ref) throw new Error(\"No ref provided\");\n if (!message.files || !message.files.length) throw new Error(\"No files provided\");\n const selectorResult = await chrome.tabs.sendMessage(tabId, {\n type: \"GET_FILE_INPUT_SELECTOR\",\n ref: message.ref,\n }, { frameId: getFrameIdForTab(tabId) });\n if (selectorResult.error) throw new Error(selectorResult.error);\n const setResult = await cdp.setFileInputBySelector(tabId, selectorResult.selector, message.files);\n if (!setResult.success) throw new Error(setResult.error);\n return { success: true, filesSet: message.files.length };\n }\n\n case \"WAIT_FOR_LOAD\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const result = await cdp.waitForLoad(tabId, message.timeout || 30000);\n if (!result.success) throw new Error(result.error);\n return { success: true, readyState: result.readyState };\n }\n\n case \"GET_FRAMES\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const result = await cdp.getFrames(tabId);\n if (!result.success) throw new Error(result.error);\n return { success: true, frames: result.frames };\n }\n\n case \"FRAME_SWITCH\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const { selector, name, index } = message;\n \n if (!selector && !name && index === undefined) {\n throw new Error(\"--selector, --name, or --index required\");\n }\n \n // Get all frames using Chrome's webNavigation API (gives us correct frameIds for messaging)\n const chromeFrames = await chrome.webNavigation.getAllFrames({ tabId });\n if (!chromeFrames || chromeFrames.length === 0) {\n throw new Error(\"No frames found in tab\");\n }\n \n // Filter to child frames only (frameId !== 0)\n const childFrames = chromeFrames.filter(f => f.frameId !== 0);\n \n if (childFrames.length === 0) {\n throw new Error(\"No iframes found on this page\");\n }\n \n let targetFrame: chrome.webNavigation.GetAllFrameResultDetails | null = null;\n \n if (index !== undefined) {\n if (index < 0 || index >= childFrames.length) {\n throw new Error(`Frame index ${index} out of range. Found ${childFrames.length} frame(s).`);\n }\n targetFrame = childFrames[index];\n } else if (name) {\n // Try to find frame by name using content script in each frame\n for (const frame of childFrames) {\n try {\n const result = await chrome.tabs.sendMessage(tabId, {\n type: \"GET_FRAME_NAME\",\n }, { frameId: frame.frameId });\n if (result?.name === name) {\n targetFrame = frame;\n break;\n }\n } catch {\n // Frame may not have content script loaded\n }\n }\n if (!targetFrame) {\n throw new Error(`Frame with name \"${name}\" not found`);\n }\n } else if (selector) {\n // Find frame by selector - ask main frame for iframe element's info\n try {\n const selectorResult = await chrome.tabs.sendMessage(tabId, {\n type: \"GET_FRAME_BY_SELECTOR\",\n selector,\n }, { frameId: 0 });\n \n if (selectorResult?.error) throw new Error(selectorResult.error);\n \n // Match by URL since that's what we can reliably get\n if (selectorResult?.url) {\n targetFrame = childFrames.find(f => f.url === selectorResult.url) || null;\n }\n \n // If no URL match and only one child frame, use it\n if (!targetFrame && childFrames.length === 1) {\n targetFrame = childFrames[0];\n }\n } catch (e) {\n throw new Error(`Could not find frame with selector \"${selector}\"`);\n }\n }\n \n if (!targetFrame) {\n throw new Error(\"Frame not found\");\n }\n \n // Store the Chrome extension frameId (integer) for this tab\n frameContexts.set(tabId, targetFrame.frameId);\n \n return { \n success: true, \n frameId: targetFrame.frameId,\n url: targetFrame.url,\n };\n }\n\n case \"FRAME_MAIN\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n \n // Clear frame context - go back to main frame (frameId 0)\n frameContexts.delete(tabId);\n \n return { success: true, message: \"Returned to main frame\" };\n }\n\n case \"EVALUATE_IN_FRAME\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (!message.frameId) throw new Error(\"No frameId provided\");\n if (!message.code) throw new Error(\"No code provided\");\n const result = await cdp.evaluateInFrame(tabId, message.frameId, message.code);\n if (!result.success) throw new Error(result.error);\n return { value: result.result };\n }\n\n case \"EXECUTE_JAVASCRIPT\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (!message.code) throw new Error(\"No code provided\");\n\n try {\n const piHelpersCode = `if(!window.piHelpers){const piHelpers={wait(ms){return new Promise(r=>setTimeout(r,ms))},async waitForSelector(sel,opts={}){const{state='visible',timeout=20000}=opts;const isVis=el=>el&&getComputedStyle(el).display!=='none'&&getComputedStyle(el).visibility!=='hidden'&&getComputedStyle(el).opacity!=='0'&&el.offsetWidth>0&&el.offsetHeight>0;const chk=()=>{const el=document.querySelector(sel);switch(state){case'attached':return el;case'detached':return el?null:document.body;case'hidden':return(!el||!isVis(el))?(el||document.body):null;default:return isVis(el)?el:null}};return new Promise((res,rej)=>{const r=chk();if(r){res(state==='detached'||state==='hidden'?null:r);return}const obs=new MutationObserver(()=>{const r=chk();if(r){obs.disconnect();clearTimeout(tid);res(state==='detached'||state==='hidden'?null:r)}});const tid=setTimeout(()=>{obs.disconnect();rej(new Error('Timeout'))},timeout);obs.observe(document.documentElement,{childList:true,subtree:true,attributes:true,attributeFilter:['style','class','hidden']})})},async waitForText(text,opts={}){const{selector,timeout=20000}=opts;const chk=()=>{const root=selector?document.querySelector(selector):document.body;if(!root)return null;const w=document.createTreeWalker(root,NodeFilter.SHOW_TEXT);while(w.nextNode())if(w.currentNode.textContent?.includes(text))return w.currentNode.parentElement;return null};return new Promise((res,rej)=>{const r=chk();if(r){res(r);return}const obs=new MutationObserver(()=>{const r=chk();if(r){obs.disconnect();clearTimeout(tid);res(r)}});const tid=setTimeout(()=>{obs.disconnect();rej(new Error('Timeout'))},timeout);obs.observe(document.documentElement,{childList:true,subtree:true,characterData:true})})},async waitForHidden(sel,t=20000){await piHelpers.waitForSelector(sel,{state:'hidden',timeout:t})},getByRole(role,opts={}){const{name}=opts;const roles={button:['button','input[type=button]','input[type=submit]','input[type=reset]'],link:['a[href]'],textbox:['input:not([type])','input[type=text]','input[type=email]','input[type=password]','textarea'],checkbox:['input[type=checkbox]'],radio:['input[type=radio]'],combobox:['select'],heading:['h1','h2','h3','h4','h5','h6']};const cands=[...document.querySelectorAll('[role='+role+']')];if(roles[role])roles[role].forEach(s=>cands.push(...document.querySelectorAll(s+':not([role])')));if(!name)return cands[0]||null;const n=name.toLowerCase().trim();for(const el of cands){const l=el.getAttribute('aria-label')?.toLowerCase().trim();const t=el.textContent?.toLowerCase().trim();if(l===n||t===n||l?.includes(n)||t?.includes(n))return el}return null}};window.__piHelpers=piHelpers;window.piHelpers=piHelpers}`;\n await cdp.evaluateScript(tabId, piHelpersCode);\n \n const escaped = message.code.replace(/`/g, \"\\\\`\").replace(/\\$/g, \"\\\\$\");\n const expression = `(async () => { 'use strict'; ${escaped} })()`;\n \n const result = await cdp.evaluateScript(tabId, expression);\n \n if (result.exceptionDetails) {\n const err = result.exceptionDetails.exception?.description || \n result.exceptionDetails.text || \n \"Script execution failed\";\n return { error: err };\n }\n \n const value = result.result?.value;\n const output = value === undefined ? \"undefined\" : JSON.stringify(value, null, 2);\n return { output: output?.substring(0, 50000) || \"undefined\" };\n } catch (err) {\n const msg = err instanceof Error ? err.message : \"Script execution failed\";\n if (msg.includes(\"Cannot access\") || msg.includes(\"Cannot attach\")) {\n return { error: \"Cannot execute JavaScript on this page (restricted URL)\" };\n }\n return { error: msg };\n }\n }\n\n case \"READ_CONSOLE_MESSAGES\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n\n try {\n await cdp.enableConsoleTracking(tabId);\n } catch (e) {}\n\n const messages = cdp.getConsoleMessages(tabId, {\n onlyErrors: message.onlyErrors,\n pattern: message.pattern,\n limit: message.limit || 100,\n });\n\n if (message.clear) {\n cdp.clearConsoleMessages(tabId);\n }\n\n return { messages };\n }\n\n case \"CLEAR_CONSOLE_MESSAGES\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n cdp.clearConsoleMessages(tabId);\n return { success: true };\n }\n\n case \"READ_NETWORK_REQUESTS\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n\n try {\n await cdp.enableNetworkTracking(tabId);\n } catch (e) {}\n\n // If full flag is passed, use getNetworkEntries for rich data\n if (message.full) {\n let entries = cdp.getNetworkEntries(tabId, {\n urlPattern: message.urlPattern,\n });\n \n // Apply filters\n if (message.method) {\n entries = entries.filter(e => e.method === message.method);\n }\n if (message.status) {\n entries = entries.filter(e => e.status === message.status);\n }\n if (message.contentType) {\n entries = entries.filter(e => e.type === message.contentType);\n }\n \n if (message.clear) {\n cdp.clearNetworkRequests(tabId);\n }\n \n // Return entries sliced to limit\n const limit = message.limit || 100;\n return { \n entries: entries.slice(0, limit),\n format: message.format,\n verbose: message.verbose\n };\n }\n\n let requests = cdp.getNetworkRequests(tabId, {\n urlPattern: message.urlPattern,\n limit: message.limit || 100,\n });\n\n // Apply filters\n if (message.method) {\n requests = requests.filter(r => r.method === message.method);\n }\n if (message.status) {\n requests = requests.filter(r => r.status === message.status);\n }\n if (message.contentType) {\n requests = requests.filter(r => r.type === message.contentType);\n }\n\n if (message.clear) {\n cdp.clearNetworkRequests(tabId);\n }\n\n return { \n requests,\n format: message.format,\n verbose: message.verbose\n };\n }\n\n case \"CLEAR_NETWORK_REQUESTS\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n cdp.clearNetworkRequests(tabId);\n return { success: true };\n }\n\n case \"GET_NETWORK_ENTRIES\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n \n try {\n await cdp.enableNetworkTracking(tabId);\n } catch (e) {}\n \n let entries = cdp.getNetworkEntries(tabId, {\n urlPattern: message.urlPattern,\n includeStatic: !message.excludeStatic,\n });\n \n // Apply additional filters\n if (message.origin) {\n entries = entries.filter(e => e.origin === message.origin);\n }\n if (message.method) {\n entries = entries.filter(e => e.method === message.method);\n }\n if (message.status) {\n entries = entries.filter(e => e.status === message.status);\n }\n if (message.type) {\n entries = entries.filter(e => e.type === message.type);\n }\n if (message.since) {\n entries = entries.filter(e => e.ts >= message.since);\n }\n if (message.hasBody !== undefined) {\n entries = entries.filter(e => message.hasBody ? (e.responseBodySize && e.responseBodySize > 0) : !e.responseBodySize);\n }\n if (message.last) {\n entries = entries.slice(-message.last);\n }\n \n if (message.clear) {\n cdp.clearNetworkRequests(tabId);\n }\n \n return { entries };\n }\n\n case \"GET_NETWORK_ENTRY\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (!message.requestId) throw new Error(\"No requestId provided\");\n \n // First try direct lookup by CDP requestId\n let entry = cdp.getNetworkEntry(tabId, message.requestId);\n \n // If not found, try lookup by entry.id (r_xxx format)\n if (!entry) {\n const entries = cdp.getNetworkEntries(tabId, {});\n entry = entries.find(e => e.id === message.requestId) || null;\n }\n \n // Also try lookup by _requestId for entries that use the generated id\n if (!entry) {\n const entries = cdp.getNetworkEntries(tabId, {});\n entry = entries.find(e => e._requestId === message.requestId) || null;\n }\n \n if (!entry) {\n return { error: `Entry not found: ${message.requestId}` };\n }\n return { entry };\n }\n\n case \"GET_RESPONSE_BODY\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (!message.requestId) throw new Error(\"No requestId provided\");\n \n // If requestId looks like entry.id format (r_xxx), look up the CDP requestId\n let cdpRequestId = message.requestId;\n if (message.requestId.startsWith('r_')) {\n const entries = cdp.getNetworkEntries(tabId, {});\n const entry = entries.find(e => e.id === message.requestId);\n if (entry) {\n cdpRequestId = entry._requestId;\n }\n }\n \n const result = await cdp.getResponseBody(tabId, cdpRequestId);\n return result;\n }\n\n case \"GET_NETWORK_ORIGINS\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n \n const entries = cdp.getNetworkEntries(tabId, {});\n const origins: Record<string, { count: number; lastSeen: number; size: number }> = {};\n \n for (const entry of entries) {\n if (!origins[entry.origin]) {\n origins[entry.origin] = { count: 0, lastSeen: 0, size: 0 };\n }\n origins[entry.origin].count++;\n origins[entry.origin].lastSeen = Math.max(origins[entry.origin].lastSeen, entry.ts);\n origins[entry.origin].size += (entry.responseBodySize || 0);\n }\n \n return { origins };\n }\n\n case \"GET_NETWORK_STATS\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n \n const entries = cdp.getNetworkEntries(tabId, {});\n const origins: Record<string, number> = {};\n const byMethod: Record<string, number> = {};\n const byStatus: Record<string, number> = {};\n let totalSize = 0;\n let oldestEntry = Infinity;\n let newestEntry = 0;\n \n for (const entry of entries) {\n // Count by origin\n if (!origins[entry.origin]) {\n origins[entry.origin] = 0;\n }\n origins[entry.origin]++;\n \n // Count by method\n const method = entry.method || 'GET';\n byMethod[method] = (byMethod[method] || 0) + 1;\n \n // Count by status\n if (entry.status) {\n const statusGroup = `${Math.floor(entry.status / 100)}xx`;\n byStatus[statusGroup] = (byStatus[statusGroup] || 0) + 1;\n }\n \n // Sum size\n totalSize += (entry.responseBodySize || 0);\n \n // Track time range\n if (entry.ts < oldestEntry) oldestEntry = entry.ts;\n if (entry.ts > newestEntry) newestEntry = entry.ts;\n }\n \n return {\n stats: {\n totalRequests: entries.length,\n totalSize,\n uniqueOrigins: Object.keys(origins).length,\n startTime: oldestEntry === Infinity ? null : oldestEntry,\n duration: (newestEntry && oldestEntry !== Infinity) ? newestEntry - oldestEntry : 0,\n byMethod,\n byStatus,\n }\n };\n }\n\n case \"RESIZE_WINDOW\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (!message.width || !message.height) throw new Error(\"width and height required\");\n\n const tab = await chrome.tabs.get(tabId);\n if (!tab.windowId) throw new Error(\"Tab has no window\");\n\n await chrome.windows.update(tab.windowId, {\n width: Math.floor(message.width),\n height: Math.floor(message.height),\n });\n\n return { success: true, width: message.width, height: message.height };\n }\n\n case \"TABS_CREATE\": {\n const activeTab = tabId ? await chrome.tabs.get(tabId) : null;\n\n const newTab = await chrome.tabs.create({\n url: message.url || \"about:blank\",\n active: false,\n });\n\n if (!newTab.id) throw new Error(\"Failed to create tab\");\n\n if (activeTab?.groupId && activeTab.groupId !== chrome.tabGroups.TAB_GROUP_ID_NONE) {\n await chrome.tabs.group({ tabIds: newTab.id, groupId: activeTab.groupId });\n }\n\n return { \n success: true, \n tabId: newTab.id, \n url: newTab.url || message.url || \"about:blank\" \n };\n }\n\n case \"UPLOAD_IMAGE\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (!message.screenshotId) throw new Error(\"screenshotId required\");\n if (!message.ref && !message.coordinate) throw new Error(\"ref or coordinate required\");\n\n const screenshot = getScreenshot(message.screenshotId);\n if (!screenshot) throw new Error(`Screenshot not found: ${message.screenshotId}`);\n\n try {\n const result = await chrome.tabs.sendMessage(tabId, {\n type: \"UPLOAD_IMAGE\",\n base64: screenshot.base64,\n ref: message.ref,\n coordinate: message.coordinate,\n filename: message.filename || \"screenshot.png\",\n }, { frameId: getFrameIdForTab(tabId) });\n\n return result;\n } catch (err) {\n return { error: \"Content script not loaded. Try refreshing the page.\" };\n }\n }\n\n case \"GET_TABS\": {\n const tabs = await chrome.tabs.query({});\n return {\n tabs: tabs.map((t) => ({ id: t.id, title: t.title, url: t.url })),\n };\n }\n\n case \"LIST_TABS\": {\n const queryOptions: chrome.tabs.QueryInfo = {};\n // Support filtering by window\n if (message.windowId) {\n queryOptions.windowId = message.windowId;\n }\n const tabs = await chrome.tabs.query(queryOptions);\n return {\n tabs: tabs.map((t) => ({\n id: t.id,\n title: t.title,\n url: t.url,\n active: t.active,\n windowId: t.windowId,\n })),\n };\n }\n\n case \"NEW_TAB\": {\n const urls = message.urls || (message.url ? [message.url] : [\"about:blank\"]);\n const createdTabs = [];\n for (let i = 0; i < urls.length; i++) {\n const createOptions: chrome.tabs.CreateProperties = {\n url: urls[i],\n active: i === 0,\n };\n // Support creating tab in specific window\n if (message.windowId) {\n createOptions.windowId = message.windowId;\n }\n const newTab = await chrome.tabs.create(createOptions);\n if (newTab.id) createdTabs.push({ tabId: newTab.id, url: urls[i] });\n }\n if (createdTabs.length === 1) {\n return { success: true, tabId: createdTabs[0].tabId, url: createdTabs[0].url };\n }\n return { success: true, tabs: createdTabs };\n }\n\n case \"SWITCH_TAB\": {\n const targetTabId = message.tabId;\n if (!targetTabId) throw new Error(\"No tabId provided\");\n const tab = await chrome.tabs.update(targetTabId, { active: true });\n if (tab.windowId) {\n await chrome.windows.update(tab.windowId, { focused: true });\n }\n return { success: true, tabId: targetTabId, url: tab.url, title: tab.title };\n }\n\n case \"CLOSE_TAB\": {\n const tabIds = message.tabIds || (message.tabId ? [message.tabId] : []);\n if (tabIds.length === 0) throw new Error(\"No tabId(s) provided\");\n await chrome.tabs.remove(tabIds);\n if (tabIds.length === 1) {\n return { success: true, tabId: tabIds[0] };\n }\n return { success: true, closed: tabIds };\n }\n\n case \"TABS_REGISTER\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (!message.name) throw new Error(\"No name provided\");\n tabNameRegistry.set(message.name, tabId);\n return { success: true, name: message.name, tabId };\n }\n\n case \"TABS_GET_BY_NAME\": {\n if (!message.name) throw new Error(\"No name provided\");\n const registeredTabId = tabNameRegistry.get(message.name);\n if (!registeredTabId) {\n return { error: `No tab registered with name \"${message.name}\"` };\n }\n try {\n const tab = await chrome.tabs.get(registeredTabId);\n return { tabId: registeredTabId, url: tab.url, title: tab.title };\n } catch (e) {\n tabNameRegistry.delete(message.name);\n return { error: `Tab \"${message.name}\" no longer exists` };\n }\n }\n\n case \"TABS_LIST_NAMED\": {\n const namedTabs: { name: string; tabId: number; url?: string; title?: string }[] = [];\n for (const [name, id] of tabNameRegistry) {\n try {\n const tab = await chrome.tabs.get(id);\n namedTabs.push({ name, tabId: id, url: tab.url, title: tab.title });\n } catch (e) {\n tabNameRegistry.delete(name);\n }\n }\n return { tabs: namedTabs };\n }\n\n case \"TABS_UNREGISTER\": {\n if (!message.name) throw new Error(\"No name provided\");\n const deleted = tabNameRegistry.delete(message.name);\n if (!deleted) {\n return { success: false, error: `No tab registered with name \"${message.name}\"` };\n }\n return { success: true };\n }\n\n case \"GET_AUTH\": {\n const { sendToNativeHost } = await import(\"../native/port-manager\");\n try {\n const result = await sendToNativeHost({ type: \"GET_AUTH\" });\n return result;\n } catch (err) {\n return { \n auth: null, \n hint: \"Native host not connected. Make sure surf native host is installed.\" \n };\n }\n }\n\n case \"NATIVE_API_REQUEST\": {\n const { sendToNativeHost } = await import(\"../native/port-manager\");\n try {\n await sendToNativeHost({\n type: \"API_REQUEST\",\n streamId: message.streamId,\n url: message.url,\n method: message.method,\n headers: message.headers,\n body: message.body,\n });\n return { sent: true };\n } catch (err) {\n return { error: err instanceof Error ? err.message : \"Unknown error\" };\n }\n }\n\n case \"STREAM_CONSOLE\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const streamId = message.streamId;\n\n try {\n await cdp.enableConsoleTracking(tabId);\n activeStreamTabs.set(streamId, tabId);\n\n cdp.subscribeToConsole(tabId, streamId, (event) => {\n postToNativeHost({\n type: \"STREAM_EVENT\",\n streamId,\n event: {\n type: \"console_event\",\n level: event.type === \"exception\" ? \"error\" : event.type,\n text: event.text,\n timestamp: event.timestamp,\n url: event.url,\n line: event.line,\n },\n });\n });\n\n return { success: true, streaming: true };\n } catch (err) {\n postToNativeHost({\n type: \"STREAM_ERROR\",\n streamId,\n error: err instanceof Error ? err.message : \"Failed to start console stream\",\n });\n return { error: err instanceof Error ? err.message : \"Failed to start console stream\" };\n }\n }\n\n case \"STREAM_NETWORK\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const streamId = message.streamId;\n\n try {\n await cdp.enableNetworkTracking(tabId);\n activeStreamTabs.set(streamId, tabId);\n\n cdp.subscribeToNetwork(tabId, streamId, (event) => {\n postToNativeHost({\n type: \"STREAM_EVENT\",\n streamId,\n event: {\n type: \"network_event\",\n method: event.method,\n url: event.url,\n status: event.status,\n duration: event.duration,\n timestamp: event.timestamp,\n },\n });\n });\n\n return { success: true, streaming: true };\n } catch (err) {\n postToNativeHost({\n type: \"STREAM_ERROR\",\n streamId,\n error: err instanceof Error ? err.message : \"Failed to start network stream\",\n });\n return { error: err instanceof Error ? err.message : \"Failed to start network stream\" };\n }\n }\n\n case \"STREAM_STOP\": {\n const streamId = message.streamId;\n const streamTabId = activeStreamTabs.get(streamId);\n \n if (streamTabId !== undefined) {\n cdp.unsubscribeFromConsole(streamTabId, streamId);\n cdp.unsubscribeFromNetwork(streamTabId, streamId);\n activeStreamTabs.delete(streamId);\n }\n\n return { success: true };\n }\n\n case \"SEARCH_PAGE\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (!message.term) throw new Error(\"Search term required\");\n try {\n const result = await chrome.tabs.sendMessage(tabId, {\n type: \"SEARCH_PAGE\",\n term: message.term,\n caseSensitive: message.caseSensitive || false,\n limit: message.limit || 10,\n }, { frameId: getFrameIdForTab(tabId) });\n return result;\n } catch {\n return { error: \"Content script not loaded. Try refreshing the page.\" };\n }\n }\n\n case \"TAB_GROUP_CREATE\": {\n const tabIds = [...(message.tabIds || [])];\n const name = message.name || \"Surf\";\n const validColors = ['grey', 'blue', 'red', 'yellow', 'green', 'pink', 'purple', 'cyan', 'orange'];\n const color = validColors.includes(message.color) ? message.color : 'blue';\n \n if (tabIds.length === 0 && tabId) {\n tabIds.push(tabId);\n }\n \n if (tabIds.length === 0) throw new Error(\"No tabs specified\");\n \n const existingGroups = await chrome.tabGroups.query({ title: name });\n let groupId: number;\n \n if (existingGroups.length > 0) {\n groupId = existingGroups[0].id;\n await chrome.tabs.group({ tabIds, groupId });\n } else {\n groupId = await chrome.tabs.group({ tabIds });\n await chrome.tabGroups.update(groupId, {\n title: name,\n color: color as chrome.tabGroups.ColorEnum,\n collapsed: false,\n });\n }\n \n return { success: true, groupId, name, tabIds };\n }\n\n case \"TAB_GROUP_REMOVE\": {\n const tabIds = [...(message.tabIds || [])];\n if (tabIds.length === 0 && tabId) {\n tabIds.push(tabId);\n }\n \n if (tabIds.length === 0) throw new Error(\"No tabs specified\");\n \n await chrome.tabs.ungroup(tabIds);\n return { success: true, ungrouped: tabIds };\n }\n\n case \"TAB_GROUPS_LIST\": {\n const groups = await chrome.tabGroups.query({});\n const result = [];\n \n for (const group of groups) {\n const tabs = await chrome.tabs.query({ groupId: group.id });\n result.push({\n id: group.id,\n name: group.title || \"(unnamed)\",\n color: group.color,\n collapsed: group.collapsed,\n tabs: tabs.map(t => ({ id: t.id, title: t.title, url: t.url })),\n });\n }\n \n return { groups: result };\n }\n\n case \"CLICK_SELECTOR\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const selector = message.selector;\n const index = message.index || 0;\n \n const script = `(() => {\n const elements = document.querySelectorAll(${JSON.stringify(selector)});\n if (elements.length === 0) return { error: \"No elements match selector\" };\n if (${index} >= elements.length) return { error: \"Index \" + ${index} + \" out of range (found \" + elements.length + \" elements)\" };\n \n const el = elements[${index}];\n const rect = el.getBoundingClientRect();\n return { \n x: rect.left + rect.width / 2, \n y: rect.top + rect.height / 2,\n count: elements.length\n };\n })()`;\n \n const result = await cdp.evaluateScript(tabId, script);\n const coords = result.result?.value;\n \n if (coords?.error) return { error: coords.error };\n if (!coords) return { error: \"Failed to get element coordinates\" };\n \n await cdp.click(tabId, coords.x, coords.y, \"left\", 1, 0);\n return { success: true, selector, index, matchCount: coords.count };\n }\n\n case \"COOKIE_LIST\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const tab = await chrome.tabs.get(tabId);\n const url = tab.url;\n if (!url) throw new Error(\"Tab has no URL\");\n const cookies = await chrome.cookies.getAll({ url });\n return { cookies };\n }\n\n case \"COOKIE_GET\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const tab = await chrome.tabs.get(tabId);\n const url = tab.url;\n if (!url) throw new Error(\"Tab has no URL\");\n if (!message.name) throw new Error(\"Cookie name required\");\n const cookie = await chrome.cookies.get({ url, name: message.name });\n if (!cookie) return { error: `Cookie \"${message.name}\" not found` };\n return { cookie };\n }\n\n case \"COOKIE_SET\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const tab = await chrome.tabs.get(tabId);\n const url = tab.url;\n if (!url) throw new Error(\"Tab has no URL\");\n if (!message.name) throw new Error(\"Cookie name required\");\n if (message.value === undefined) throw new Error(\"Cookie value required\");\n \n const cookieDetails: chrome.cookies.SetDetails = {\n url,\n name: message.name,\n value: message.value,\n };\n \n if (message.expires) {\n const expirationDate = new Date(message.expires).getTime() / 1000;\n if (isNaN(expirationDate)) {\n throw new Error(`Invalid expiration date: ${message.expires}`);\n }\n cookieDetails.expirationDate = expirationDate;\n }\n \n const result = await chrome.cookies.set(cookieDetails);\n return { success: true, cookie: result };\n }\n\n case \"COOKIE_CLEAR\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const tab = await chrome.tabs.get(tabId);\n const url = tab.url;\n if (!url) throw new Error(\"Tab has no URL\");\n if (!message.name) throw new Error(\"Cookie name required\");\n \n await chrome.cookies.remove({ url, name: message.name });\n return { success: true, cleared: message.name };\n }\n\n case \"COOKIE_CLEAR_ALL\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const tab = await chrome.tabs.get(tabId);\n const url = tab.url;\n if (!url) throw new Error(\"Tab has no URL\");\n \n const cookies = await chrome.cookies.getAll({ url });\n for (const cookie of cookies) {\n await chrome.cookies.remove({ url, name: cookie.name });\n }\n return { success: true, cleared: cookies.length };\n }\n\n case \"TAB_RELOAD\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n await chrome.tabs.reload(tabId, { bypassCache: message.hard || false });\n return { success: true };\n }\n\n case \"ZOOM_GET\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const zoom = await chrome.tabs.getZoom(tabId);\n return { zoom };\n }\n\n case \"ZOOM_SET\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const level = message.level;\n if (level < 0.25 || level > 5) throw new Error(\"Zoom level must be between 0.25 and 5\");\n await chrome.tabs.setZoom(tabId, level);\n return { success: true, zoom: level };\n }\n\n case \"ZOOM_RESET\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n await chrome.tabs.setZoom(tabId, 0);\n return { success: true, zoom: 1.0 };\n }\n\n case \"BOOKMARK_ADD\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const tab = await chrome.tabs.get(tabId);\n const createProps: { title: string; url?: string; parentId?: string } = {\n title: tab.title || \"Untitled\",\n url: tab.url,\n };\n if (message.folder) {\n const search = await chrome.bookmarks.search({ title: message.folder });\n const folder = search.find(b => !b.url);\n if (folder) {\n createProps.parentId = folder.id;\n }\n }\n const bookmark = await chrome.bookmarks.create(createProps);\n return { success: true, bookmark: { id: bookmark.id, title: bookmark.title, url: bookmark.url } };\n }\n\n case \"BOOKMARK_REMOVE\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const tab = await chrome.tabs.get(tabId);\n if (!tab.url) throw new Error(\"Tab has no URL\");\n const bookmarks = await chrome.bookmarks.search({ url: tab.url });\n if (bookmarks.length === 0) throw new Error(\"No bookmark found for this URL\");\n await chrome.bookmarks.remove(bookmarks[0].id);\n return { success: true };\n }\n\n case \"BOOKMARK_LIST\": {\n const limit = typeof message.limit === 'number' ? message.limit : 50;\n let bookmarks: chrome.bookmarks.BookmarkTreeNode[] = [];\n \n if (message.folder) {\n const search = await chrome.bookmarks.search({ title: message.folder });\n const folder = search.find(b => !b.url);\n if (folder) {\n const children = await chrome.bookmarks.getChildren(folder.id);\n bookmarks = children.filter(b => b.url).slice(0, limit);\n }\n } else {\n const recent = await chrome.bookmarks.getRecent(limit);\n bookmarks = recent;\n }\n \n return { \n bookmarks: bookmarks.map(b => ({ \n id: b.id, \n title: b.title, \n url: b.url,\n dateAdded: b.dateAdded\n }))\n };\n }\n\n case \"HISTORY_LIST\": {\n const limit = typeof message.limit === 'number' ? message.limit : 20;\n const items = await chrome.history.search({ \n text: \"\", \n maxResults: limit,\n startTime: 0 \n });\n return { \n history: items.map(h => ({ \n url: h.url, \n title: h.title, \n lastVisitTime: h.lastVisitTime,\n visitCount: h.visitCount\n }))\n };\n }\n\n case \"HISTORY_SEARCH\": {\n const query = message.query;\n const limit = typeof message.limit === 'number' ? message.limit : 20;\n const items = await chrome.history.search({ \n text: query, \n maxResults: limit,\n startTime: 0 \n });\n return { \n history: items.map(h => ({ \n url: h.url, \n title: h.title, \n lastVisitTime: h.lastVisitTime,\n visitCount: h.visitCount\n }))\n };\n }\n\n case \"GET_CHATGPT_COOKIES\": {\n const cookies = await chrome.cookies.getAll({ domain: \".chatgpt.com\" });\n const openaiCookies = await chrome.cookies.getAll({ domain: \".openai.com\" });\n return { cookies: [...cookies, ...openaiCookies] };\n }\n\n case \"CHATGPT_NEW_TAB\": {\n const tab = await chrome.tabs.create({\n url: \"https://chatgpt.com/\",\n active: true,\n });\n if (!tab.id) throw new Error(\"Failed to create tab\");\n const currentTab = await chrome.tabs.get(tab.id);\n if (currentTab.status !== \"complete\") {\n await new Promise<void>((resolve) => {\n const listener = (tabId: number, info: chrome.tabs.TabChangeInfo) => {\n if (tabId === tab.id && info.status === \"complete\") {\n chrome.tabs.onUpdated.removeListener(listener);\n resolve();\n }\n };\n chrome.tabs.onUpdated.addListener(listener);\n setTimeout(() => {\n chrome.tabs.onUpdated.removeListener(listener);\n resolve();\n }, 30000);\n });\n }\n await cdp.attach(tab.id);\n // Wait for JS runtime to be ready after CDP attach\n await waitForRuntimeReady(tab.id, 10000);\n return { tabId: tab.id };\n }\n\n case \"CHATGPT_CLOSE_TAB\": {\n const chatTabId = message.tabId;\n if (chatTabId) {\n try {\n await cdp.detach(chatTabId);\n } catch {}\n try {\n await chrome.tabs.remove(chatTabId);\n } catch {}\n }\n return { success: true };\n }\n\n case \"CHATGPT_CDP_COMMAND\": {\n const { method, params } = message;\n const result = await cdp.sendCommand(message.tabId, method, params || {});\n return result;\n }\n\n case \"CHATGPT_EVALUATE\": {\n const result = await cdp.evaluateScript(message.tabId, message.expression);\n return result;\n }\n\n case \"PERPLEXITY_NEW_TAB\": {\n const tab = await chrome.tabs.create({\n url: \"https://www.perplexity.ai/\",\n active: true,\n });\n if (!tab.id) throw new Error(\"Failed to create tab\");\n const currentTab = await chrome.tabs.get(tab.id);\n if (currentTab.status !== \"complete\") {\n await new Promise<void>((resolve) => {\n const listener = (tabId: number, info: chrome.tabs.TabChangeInfo) => {\n if (tabId === tab.id && info.status === \"complete\") {\n chrome.tabs.onUpdated.removeListener(listener);\n resolve();\n }\n };\n chrome.tabs.onUpdated.addListener(listener);\n setTimeout(() => {\n chrome.tabs.onUpdated.removeListener(listener);\n resolve();\n }, 30000);\n });\n }\n await cdp.attach(tab.id);\n // Wait for JS runtime to be ready after CDP attach\n await waitForRuntimeReady(tab.id, 10000);\n return { tabId: tab.id };\n }\n\n case \"PERPLEXITY_CLOSE_TAB\": {\n const pplxTabId = message.tabId;\n if (pplxTabId) {\n try {\n await cdp.detach(pplxTabId);\n } catch {}\n try {\n await chrome.tabs.remove(pplxTabId);\n } catch {}\n }\n return { success: true };\n }\n\n case \"PERPLEXITY_CDP_COMMAND\": {\n const { method, params } = message;\n const result = await cdp.sendCommand(message.tabId, method, params || {});\n return result;\n }\n\n case \"PERPLEXITY_EVALUATE\": {\n const result = await cdp.evaluateScript(message.tabId, message.expression);\n return result;\n }\n\n case \"GET_TWITTER_COOKIES\": {\n // Grok requires X.com cookies for authentication\n const domains = [\".x.com\", \".twitter.com\", \"x.com\", \"twitter.com\"];\n const allCookies: chrome.cookies.Cookie[] = [];\n \n for (const domain of domains) {\n try {\n const cookies = await chrome.cookies.getAll({ domain });\n allCookies.push(...cookies);\n } catch {}\n }\n \n // Also try by URL\n const urls = [\"https://x.com\", \"https://twitter.com\"];\n for (const url of urls) {\n try {\n const cookies = await chrome.cookies.getAll({ url });\n allCookies.push(...cookies);\n } catch {}\n }\n \n // Dedupe by name\n const seen = new Map<string, chrome.cookies.Cookie>();\n for (const cookie of allCookies) {\n const existing = seen.get(cookie.name);\n if (!existing || cookie.domain?.includes(\"x.com\")) {\n seen.set(cookie.name, cookie);\n }\n }\n \n return { cookies: Array.from(seen.values()) };\n }\n\n case \"GROK_NEW_TAB\": {\n const tab = await chrome.tabs.create({\n url: \"https://x.com/i/grok\",\n active: true,\n });\n if (!tab.id) throw new Error(\"Failed to create tab\");\n const currentTab = await chrome.tabs.get(tab.id);\n if (currentTab.status !== \"complete\") {\n await new Promise<void>((resolve) => {\n const listener = (tabId: number, info: chrome.tabs.TabChangeInfo) => {\n if (tabId === tab.id && info.status === \"complete\") {\n chrome.tabs.onUpdated.removeListener(listener);\n resolve();\n }\n };\n chrome.tabs.onUpdated.addListener(listener);\n setTimeout(() => {\n chrome.tabs.onUpdated.removeListener(listener);\n resolve();\n }, 30000);\n });\n }\n await cdp.attach(tab.id);\n // Wait for JS runtime to be ready after CDP attach\n await waitForRuntimeReady(tab.id, 10000);\n return { tabId: tab.id };\n }\n\n case \"GROK_CLOSE_TAB\": {\n const grokTabId = message.tabId;\n if (grokTabId) {\n try {\n await cdp.detach(grokTabId);\n } catch {}\n try {\n await chrome.tabs.remove(grokTabId);\n } catch {}\n }\n return { success: true };\n }\n\n case \"GROK_CDP_COMMAND\": {\n const { method, params } = message;\n const result = await cdp.sendCommand(message.tabId, method, params || {});\n return result;\n }\n\n case \"GROK_EVALUATE\": {\n const result = await cdp.evaluateScript(message.tabId, message.expression);\n return result;\n }\n\n case \"AISTUDIO_NEW_TAB\": {\n const url = message.url || \"https://aistudio.google.com/prompts/new_chat\";\n const tab = await chrome.tabs.create({ url, active: true });\n if (!tab.id) throw new Error(\"Failed to create tab\");\n const currentTab = await chrome.tabs.get(tab.id);\n if (currentTab.status !== \"complete\") {\n await new Promise<void>((resolve) => {\n const listener = (tabId: number, info: chrome.tabs.TabChangeInfo) => {\n if (tabId === tab.id && info.status === \"complete\") {\n chrome.tabs.onUpdated.removeListener(listener);\n resolve();\n }\n };\n chrome.tabs.onUpdated.addListener(listener);\n setTimeout(() => {\n chrome.tabs.onUpdated.removeListener(listener);\n resolve();\n }, 30000);\n });\n }\n await cdp.attach(tab.id);\n await waitForRuntimeReady(tab.id, 10000);\n return { tabId: tab.id };\n }\n\n case \"AISTUDIO_CLOSE_TAB\": {\n const aiStudioTabId = message.tabId;\n if (aiStudioTabId) {\n try { await cdp.detach(aiStudioTabId); } catch {}\n try { await chrome.tabs.remove(aiStudioTabId); } catch {}\n }\n return { success: true };\n }\n\n case \"AISTUDIO_CDP_COMMAND\": {\n const { method, params } = message;\n return await cdp.sendCommand(message.tabId, method, params || {});\n }\n\n case \"AISTUDIO_EVALUATE\": {\n return await cdp.evaluateScript(message.tabId, message.expression);\n }\n\n case \"DOWNLOADS_SEARCH\": {\n const results = await chrome.downloads.search(message.searchParams || {});\n return {\n downloads: results.map(d => ({\n id: d.id,\n filename: d.filename,\n state: d.state,\n error: d.error,\n }))\n };\n }\n\n case \"GET_GOOGLE_COOKIES\": {\n // Gemini requires cookies from multiple Google domains\n const domains = [\".google.com\", \".gemini.google.com\", \"accounts.google.com\", \"www.google.com\"];\n const allCookies: chrome.cookies.Cookie[] = [];\n \n for (const domain of domains) {\n try {\n const cookies = await chrome.cookies.getAll({ domain });\n allCookies.push(...cookies);\n } catch {}\n }\n \n // Also try by URL for better coverage\n const urls = [\"https://gemini.google.com\", \"https://aistudio.google.com\", \"https://accounts.google.com\", \"https://www.google.com\"];\n for (const url of urls) {\n try {\n const cookies = await chrome.cookies.getAll({ url });\n allCookies.push(...cookies);\n } catch {}\n }\n \n // Dedupe by name, preferring google.com domain with root path\n const seen = new Map<string, chrome.cookies.Cookie>();\n for (const cookie of allCookies) {\n const existing = seen.get(cookie.name);\n if (!existing || \n (cookie.domain === \".google.com\" && cookie.path === \"/\") ||\n (!existing.domain?.includes(\"google.com\") && cookie.domain?.includes(\"google.com\"))) {\n seen.set(cookie.name, cookie);\n }\n }\n \n return { cookies: Array.from(seen.values()) };\n }\n\n case \"WINDOW_NEW\": {\n // Default to a usable blank page if no URL provided\n const url = message.url || 'data:text/html,<html><head><title>Surf Agent</title></head><body style=\"font-family:system-ui;display:flex;align-items:center;justify-content:center;height:100vh;margin:0;color:%23666\"><div style=\"text-align:center\"><h2>Agent Window</h2><p>Ready for automation</p></div></body></html>';\n \n const createOptions: chrome.windows.CreateData = {\n focused: message.focused !== false,\n type: \"normal\",\n url,\n };\n \n if (message.width && message.height) {\n createOptions.width = message.width;\n createOptions.height = message.height;\n }\n \n if (message.incognito) {\n createOptions.incognito = true;\n }\n \n const window = await chrome.windows.create(createOptions);\n \n if (!window.id) throw new Error(\"Failed to create window\");\n \n // Get the tab that was created with the window\n const tabs = await chrome.tabs.query({ windowId: window.id });\n const firstTab = tabs[0];\n \n // Wait for tab to be ready\n if (firstTab?.id) {\n await new Promise(r => setTimeout(r, 150));\n }\n \n return { \n success: true, \n windowId: window.id, \n tabId: firstTab?.id,\n hint: `Use --window-id ${window.id} to target this window`,\n };\n }\n\n case \"WINDOW_LIST\": {\n const windows = await chrome.windows.getAll({ populate: true });\n \n return {\n windows: windows.map(w => ({\n id: w.id,\n focused: w.focused,\n type: w.type,\n state: w.state,\n width: w.width,\n height: w.height,\n tabCount: w.tabs?.length || 0,\n tabs: message.includeTabs ? w.tabs?.map(t => ({\n id: t.id,\n title: t.title,\n url: t.url,\n active: t.active,\n })) : undefined,\n }))\n };\n }\n\n case \"WINDOW_FOCUS\": {\n if (!message.windowId) throw new Error(\"No windowId provided\");\n \n await chrome.windows.update(message.windowId, { focused: true });\n return { success: true, windowId: message.windowId };\n }\n\n case \"WINDOW_CLOSE\": {\n if (!message.windowId) throw new Error(\"No windowId provided\");\n \n await chrome.windows.remove(message.windowId);\n return { success: true, windowId: message.windowId };\n }\n\n case \"WINDOW_RESIZE\": {\n if (!message.windowId) throw new Error(\"No windowId provided\");\n \n const updateInfo: chrome.windows.UpdateInfo = {};\n if (message.width) updateInfo.width = message.width;\n if (message.height) updateInfo.height = message.height;\n if (message.left !== undefined) updateInfo.left = message.left;\n if (message.top !== undefined) updateInfo.top = message.top;\n if (message.state) updateInfo.state = message.state as chrome.windows.windowStateEnum;\n \n const window = await chrome.windows.update(message.windowId, updateInfo);\n return { \n success: true, \n windowId: message.windowId,\n width: window.width,\n height: window.height,\n };\n }\n\n default:\n throw new Error(`Unknown message type: ${message.type}`);\n }\n}\n\nchrome.runtime.onInstalled.addListener((details) => {\n debugLog(\"Extension installed/updated:\", details.reason);\n});\n\nconst COMMANDS_WITHOUT_TAB = new Set([\n \"LIST_TABS\", \"NEW_TAB\", \"TABS_NEW\", \"CLOSE_TABS\", \"SWITCH_TAB\", \"TABS_SWITCH\",\n \"TABS_REGISTER\", \"TABS_UNREGISTER\", \"TABS_LIST_NAMED\", \"TABS_GET_BY_NAME\",\n \"CREATE_TAB_GROUP\", \"UNGROUP_TABS\", \"LIST_TAB_GROUPS\", \"GET_HISTORY\", \"SEARCH_HISTORY\",\n \"GET_COOKIES\", \"SET_COOKIE\", \"DELETE_COOKIES\", \"GET_BOOKMARKS\", \"ADD_BOOKMARK\", \n \"DELETE_BOOKMARK\", \"DIALOG_DISMISS\", \"DIALOG_ACCEPT\", \"DIALOG_INFO\",\n \"CHATGPT_NEW_TAB\", \"CHATGPT_CLOSE_TAB\", \"CHATGPT_EVALUATE\", \"CHATGPT_CDP_COMMAND\",\n \"GET_CHATGPT_COOKIES\", \"GET_GOOGLE_COOKIES\", \"GET_TWITTER_COOKIES\",\n \"PERPLEXITY_NEW_TAB\", \"PERPLEXITY_CLOSE_TAB\", \"PERPLEXITY_EVALUATE\", \"PERPLEXITY_CDP_COMMAND\",\n \"GROK_NEW_TAB\", \"GROK_CLOSE_TAB\", \"GROK_EVALUATE\", \"GROK_CDP_COMMAND\",\n \"AISTUDIO_NEW_TAB\", \"AISTUDIO_CLOSE_TAB\", \"AISTUDIO_EVALUATE\", \"AISTUDIO_CDP_COMMAND\",\n \"DOWNLOADS_SEARCH\",\n \"WINDOW_NEW\", \"WINDOW_LIST\", \"WINDOW_FOCUS\", \"WINDOW_CLOSE\", \"WINDOW_RESIZE\",\n \"EMULATE_DEVICE_LIST\"\n]);\n\ninitNativeMessaging(async (msg) => {\n let tabId = msg.tabId;\n const windowId = msg.windowId;\n const isDialogCommand = msg.type?.startsWith(\"DIALOG_\");\n const needsTab = !COMMANDS_WITHOUT_TAB.has(msg.type);\n let autoCreatedTab = false;\n \n if (tabId && !isDialogCommand) {\n try {\n await chrome.tabs.get(tabId);\n } catch {\n throw new Error(`Invalid tab ID: ${tabId}. Use 'surf tab.list' to see available tabs.`);\n }\n } else if (!tabId && needsTab) {\n let tabs: chrome.tabs.Tab[];\n let tab: chrome.tabs.Tab | undefined;\n \n if (windowId) {\n // If windowId specified, only look in that window\n tabs = await chrome.tabs.query({ active: true, windowId });\n tab = tabs[0];\n \n // Check if active tab is usable (not a restricted URL)\n const isRestricted = (url?: string) => \n !url || url.startsWith('chrome://') || url.startsWith('chrome-extension://') || url === 'about:blank';\n \n if (!tab || isRestricted(tab.url)) {\n // Active tab is restricted, find any usable tab in the window\n tabs = await chrome.tabs.query({ windowId });\n tab = tabs.find(t => !isRestricted(t.url));\n }\n \n if (!tab?.id) {\n // No usable tab - auto-create one with a minimal page\n const newTab = await chrome.tabs.create({ \n windowId, \n url: 'data:text/html,<html><head><title>Surf</title></head><body></body></html>',\n active: true \n });\n if (!newTab.id) {\n throw new Error(`Failed to create tab in window ${windowId}`);\n }\n // Wait briefly for tab to be ready\n await new Promise(r => setTimeout(r, 100));\n tab = newTab;\n autoCreatedTab = true;\n }\n } else {\n // Default behavior: find active tab across windows\n tabs = await chrome.tabs.query({ active: true, lastFocusedWindow: true });\n tab = tabs[0];\n if (!tab || tab.url?.startsWith('chrome-extension://')) {\n tabs = await chrome.tabs.query({ active: true, currentWindow: true });\n tab = tabs[0];\n }\n if (!tab || tab.url?.startsWith('chrome-extension://') || tab.url?.startsWith('chrome://')) {\n tabs = await chrome.tabs.query({ active: true });\n tab = tabs.find(t => !t.url?.startsWith('chrome-extension://') && !t.url?.startsWith('chrome://'));\n }\n if (!tab?.id) {\n throw new Error(\"No active tab found. Use 'surf tab.new <url>' to create one, or 'surf tab.list' to see available tabs.\");\n }\n }\n tabId = tab.id;\n }\n \n const result = await handleMessage({ ...msg, tabId }, {} as chrome.runtime.MessageSender);\n \n // Add helpful hints based on what happened\n const hints: string[] = [];\n if (autoCreatedTab) {\n hints.push(`Auto-created tab in window ${windowId} (no usable tabs existed). Navigate to your target URL.`);\n }\n \n return { \n ...result, \n _resolvedTabId: tabId,\n _hint: hints.length > 0 ? hints.join(' ') : undefined,\n };\n});\n"],"file":"service-worker/index.js"}
|
|
1
|
+
{"version":3,"mappings":"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","names":["MODIFIERS","KEY_DEFINITIONS","CDPController","tabId","target","err","message","source","method","params","reason","messages","text","a","callFrame","msg","callbacks","cb","details","requests","req","timestamp","reqHeaders","key","value","entriesMap","seq","entryId","requestHeaders","requestBody","requestBodySize","entry","oldestKey","existing","r","respHeaders","startTime","now","duration","response","responseHeaders","result","url","mimeType","accept","promptText","e","preset","presets","config","rate","latitude","longitude","accuracy","device","options","viewport","enabled","categories","metricsResult","metrics","m","selector","files","doc","queryResult","timeout","readyState","resolve","frames","extractFrames","frame","parentId","child","frameId","expression","contextResult","wrappedExpression","regex","entries","idx","requestId","streamId","callback","layoutMetrics","width","height","x","y","type","button","clickCount","modifiers","buttonValue","i","startX","startY","endX","endY","deltaX","deltaY","char","needsShift","keyDef","chord","parts","modifierKeys","mainKey","part","mod","lowerKey","code","modifierString","trimmed","debugMode","initialized","pendingLogs","stored","args","changes","areaName","debugLog","streamCallbacks","handleNativeApiResponse","nativePort","messageHandler","reconnectTimeout","pendingNativeRequests","nativeRequestId","initNativeMessaging","handler","connect","sendToNativeHost","reject","id","postToNativeHost","error","cdp","activeStreamTabs","frameContexts","getFrameIdForTab","screenshotCache","screenshotCounter","generateScreenshotId","cacheScreenshot","data","oldest","getScreenshot","ELEMENT_COLORS","annotateScreenshot","screenshot","elements","scale","blob","base64ToBlob","bitmap","canvas","ctx","scaleFactor","element","color","w","h","labelText","fontSize","textWidth","padding","labelWidth","labelHeight","labelX","labelY","resultBlob","blobToBase64","reader","base64","binary","bytes","captureFullPage","maxHeight","dimensions","viewportHeight","totalHeight","devicePixelRatio","originalScrollY","chunks","currentY","chunk","chunkBlob","canvasWidth","canvasHeight","chunkHeight","remainingHeight","drawHeight","navigationResolvers","tabNameRegistry","resolver","name","streamTabId","waitForRuntimeReady","timeoutMs","deadline","delay","ms","performLocateAction","ref","action","coords","sender","sendResponse","handleMessage","tab","scaleInfo","usedFallback","dpr","rawResult","cdpError","binaryString","treeResult","screenshotId","mods","clickTypeFrameId","clicked","clickTypeSubmitFrameId","autocompleteFrameId","waitMs","script","clear","submit","maxAttempts","scrollFallback","dx","dy","navigationPromise","readFrameId","textResult","position","scrollScript","pos","sel","findScrollable","el","b","container","scrollInfoScript","maxScroll","locateFrameId","textFrameId","labelFrameId","stylesFrameId","selectFrameId","fromTabId","targetTabId","expect","pollInterval","lastError","urls","captureScreenshots","failFast","results","pass","fail","errors","screenshotBase64","hostname","testTabId","testTab","onComplete","onError","consoleMessages","elapsed","status","waitFrameId","dialog","deviceName","lowerName","bestMatch","presetLower","presetNoSpaces","selectorResult","setResult","index","chromeFrames","childFrames","f","targetFrame","limit","cdpRequestId","origins","byMethod","byStatus","totalSize","oldestEntry","newestEntry","statusGroup","activeTab","newTab","t","queryOptions","createdTabs","createOptions","tabIds","registeredTabId","namedTabs","__vitePreload","portManager","event","existingGroups","groupId","groups","group","tabs","cookie","cookieDetails","expirationDate","cookies","level","createProps","folder","bookmark","bookmarks","query","openaiCookies","listener","info","chatTabId","pplxTabId","domains","allCookies","domain","seen","grokTabId","geminiTabId","uploadTabId","filePaths","timeoutId","cleanup","attemptFileChooser","attemptNum","clickUploadSequence","timeouts","attempt","fileSetPromise","imageUrl","resp","aiStudioTabId","d","window","firstTab","updateInfo","COMMANDS_WITHOUT_TAB","windowId","isDialogCommand","needsTab","autoCreatedTab","isRestricted","hints"],"ignoreList":[],"sources":["../../src/cdp/controller.ts","../../src/utils/debug.ts","../../src/native/native-api-transport.ts","../../src/native/port-manager.ts","../../src/service-worker/index.ts"],"sourcesContent":["type Debuggee = chrome.debugger.Debuggee;\ntype MouseButton = \"left\" | \"right\" | \"middle\" | \"none\";\n\ninterface ConsoleMessage {\n type: string;\n text: string;\n timestamp: number;\n url?: string;\n line?: number;\n}\n\ninterface NetworkRequest {\n requestId: string;\n url: string;\n method: string;\n status?: number;\n type?: string;\n timestamp: number;\n requestHeaders?: Record<string, string>;\n requestBody?: string;\n responseHeaders?: Record<string, string>;\n responseBody?: string;\n mimeType?: string;\n duration?: number;\n}\n\nexport interface NetworkEntry {\n id: string; // \"r_<timestamp>_<seq>\"\n ts: number; // Request start timestamp (ms)\n duration?: number; // Total time (ms)\n ttfb?: number; // Time to first byte (ms)\n \n // Request\n method: string;\n url: string;\n origin: string; // Extracted from URL\n requestHeaders: Record<string, string>;\n requestBody?: string; // POST/PUT body\n requestBodySize?: number;\n \n // Response \n status?: number;\n statusText?: string;\n mimeType?: string;\n responseHeaders?: Record<string, string>;\n responseBody?: string; // Will be fetched via getResponseBody\n responseBodySize?: number;\n \n // Metadata\n tabId: number;\n tabUrl?: string; // Page URL that initiated request\n type?: string; // \"xhr\", \"fetch\", \"document\", etc.\n \n // Flags\n flags: string[]; // [\"binary\", \"truncated\", \"protobuf\", \"failed\"]\n \n // Internal tracking\n _requestId: string; // CDP requestId for lazy loading\n _responseReceived: boolean; // Whether response was received\n _loadingFinished: boolean; // Whether loading finished\n}\n\ninterface PendingDialog {\n type: \"alert\" | \"confirm\" | \"prompt\" | \"beforeunload\";\n message: string;\n defaultPrompt?: string;\n timestamp: number;\n}\n\ntype ConsoleEventCallback = (event: ConsoleMessage) => void;\ntype NetworkEventCallback = (event: {\n method: string;\n url: string;\n status?: number;\n duration?: number;\n timestamp: number;\n}) => void;\n\nconst MODIFIERS = {\n alt: 1,\n ctrl: 2,\n control: 2,\n meta: 4,\n cmd: 4,\n command: 4,\n win: 4,\n windows: 4,\n shift: 8,\n} as const;\n\ninterface KeyDefinition {\n key: string;\n code: string;\n keyCode: number;\n text?: string;\n location?: number;\n}\n\nconst KEY_DEFINITIONS: Record<string, KeyDefinition> = {\n enter: { key: \"Enter\", code: \"Enter\", keyCode: 13, text: \"\\r\" },\n tab: { key: \"Tab\", code: \"Tab\", keyCode: 9 },\n escape: { key: \"Escape\", code: \"Escape\", keyCode: 27 },\n backspace: { key: \"Backspace\", code: \"Backspace\", keyCode: 8 },\n delete: { key: \"Delete\", code: \"Delete\", keyCode: 46 },\n arrowup: { key: \"ArrowUp\", code: \"ArrowUp\", keyCode: 38 },\n arrowdown: { key: \"ArrowDown\", code: \"ArrowDown\", keyCode: 40 },\n arrowleft: { key: \"ArrowLeft\", code: \"ArrowLeft\", keyCode: 37 },\n arrowright: { key: \"ArrowRight\", code: \"ArrowRight\", keyCode: 39 },\n home: { key: \"Home\", code: \"Home\", keyCode: 36 },\n end: { key: \"End\", code: \"End\", keyCode: 35 },\n pageup: { key: \"PageUp\", code: \"PageUp\", keyCode: 33 },\n pagedown: { key: \"PageDown\", code: \"PageDown\", keyCode: 34 },\n space: { key: \" \", code: \"Space\", keyCode: 32, text: \" \" },\n f1: { key: \"F1\", code: \"F1\", keyCode: 112 },\n f2: { key: \"F2\", code: \"F2\", keyCode: 113 },\n f3: { key: \"F3\", code: \"F3\", keyCode: 114 },\n f4: { key: \"F4\", code: \"F4\", keyCode: 115 },\n f5: { key: \"F5\", code: \"F5\", keyCode: 116 },\n f6: { key: \"F6\", code: \"F6\", keyCode: 117 },\n f7: { key: \"F7\", code: \"F7\", keyCode: 118 },\n f8: { key: \"F8\", code: \"F8\", keyCode: 119 },\n f9: { key: \"F9\", code: \"F9\", keyCode: 120 },\n f10: { key: \"F10\", code: \"F10\", keyCode: 121 },\n f11: { key: \"F11\", code: \"F11\", keyCode: 122 },\n f12: { key: \"F12\", code: \"F12\", keyCode: 123 },\n};\n\nexport class CDPController {\n private targets = new Map<number, Debuggee>();\n private consoleMessages: Map<number, ConsoleMessage[]> = new Map();\n private networkRequests: Map<number, NetworkRequest[]> = new Map();\n private networkEntries: Map<number, Map<string, NetworkEntry>> = new Map(); // tabId -> requestId -> entry\n private consoleCallbacks: Map<number, Map<number, ConsoleEventCallback>> = new Map();\n private networkCallbacks: Map<number, Map<number, NetworkEventCallback>> = new Map();\n private networkRequestStartTimes: Map<string, number> = new Map();\n private pendingDialogs: Map<number, PendingDialog> = new Map();\n private networkEntrySeq = 0; // Sequence counter for unique IDs\n private static debuggerListenerRegistered = false;\n\n // Body fetch settings\n private static readonly MAX_INLINE_BODY_SIZE = 16 * 1024; // 16KB\n private static readonly STATIC_ASSET_TYPES = new Set([\n 'image/png', 'image/jpeg', 'image/gif', 'image/webp', 'image/svg+xml', 'image/x-icon',\n 'font/woff', 'font/woff2', 'font/ttf', 'font/otf', 'application/font-woff', 'application/font-woff2',\n 'text/css', 'application/javascript', 'text/javascript', 'application/x-javascript',\n ]);\n private static readonly BINARY_TYPES = new Set([\n 'image/png', 'image/jpeg', 'image/gif', 'image/webp', 'image/x-icon',\n 'font/woff', 'font/woff2', 'font/ttf', 'font/otf', 'application/font-woff', 'application/font-woff2',\n 'application/octet-stream', 'application/pdf', 'application/zip',\n 'audio/mpeg', 'audio/wav', 'audio/ogg',\n 'video/mp4', 'video/webm', 'video/ogg',\n ]);\n\n async attach(tabId: number): Promise<void> {\n if (this.targets.has(tabId)) return;\n \n const target: Debuggee = { tabId };\n try {\n await chrome.debugger.attach(target, \"1.3\");\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n if (message.includes(\"Already attached\")) {\n this.targets.set(tabId, target);\n return;\n }\n if (message.includes(\"Cannot access\") || message.includes(\"Cannot attach\")) {\n throw new Error(`Cannot control this page. Chrome restricts automation on chrome://, extensions, and web store pages.`);\n }\n throw new Error(`Failed to attach debugger: ${message}`);\n }\n this.targets.set(tabId, target);\n\n this.setupEventListener();\n this.consoleMessages.set(tabId, []);\n this.networkRequests.set(tabId, []);\n\n try {\n await this.send(tabId, \"Page.enable\");\n } catch (e) {}\n }\n\n async detach(tabId: number): Promise<void> {\n const target = this.targets.get(tabId);\n if (target) {\n try {\n await chrome.debugger.detach(target);\n } catch (e) {\n console.warn(\"[CDPController] Error detaching:\", e);\n }\n this.targets.delete(tabId);\n this.consoleMessages.delete(tabId);\n this.networkRequests.delete(tabId);\n this.networkEntries.delete(tabId);\n this.consoleCallbacks.delete(tabId);\n this.networkCallbacks.delete(tabId);\n this.pendingDialogs.delete(tabId);\n }\n }\n\n async detachAll(): Promise<void> {\n for (const tabId of this.targets.keys()) {\n await this.detach(tabId);\n }\n }\n\n private setupEventListener(): void {\n if (CDPController.debuggerListenerRegistered) return;\n CDPController.debuggerListenerRegistered = true;\n\n chrome.debugger.onEvent.addListener((source, method, params) => {\n const tabId = source.tabId;\n if (!tabId || !this.targets.has(tabId)) return;\n\n this.handleCDPEvent(tabId, method, params);\n });\n\n chrome.debugger.onDetach.addListener((source, reason) => {\n const tabId = source.tabId;\n if (tabId && this.targets.has(tabId)) {\n this.targets.delete(tabId);\n this.consoleMessages.delete(tabId);\n this.networkRequests.delete(tabId);\n this.networkEntries.delete(tabId);\n this.consoleCallbacks.delete(tabId);\n this.networkCallbacks.delete(tabId);\n }\n });\n }\n\n private handleCDPEvent(tabId: number, method: string, params: any): void {\n switch (method) {\n case \"Runtime.consoleAPICalled\":\n this.handleRuntimeConsole(tabId, params);\n break;\n case \"Runtime.exceptionThrown\":\n this.handleRuntimeException(tabId, params);\n break;\n case \"Network.requestWillBeSent\":\n this.handleNetworkRequest(tabId, params);\n break;\n case \"Network.responseReceived\":\n this.handleNetworkResponse(tabId, params);\n break;\n case \"Network.loadingFailed\":\n this.handleNetworkFailed(tabId, params);\n break;\n case \"Network.loadingFinished\":\n this.handleLoadingFinished(tabId, params);\n break;\n case \"Page.javascriptDialogOpening\":\n this.handleDialogOpening(tabId, params);\n break;\n case \"Page.javascriptDialogClosed\":\n this.pendingDialogs.delete(tabId);\n break;\n }\n }\n\n private handleRuntimeConsole(tabId: number, params: any): void {\n const messages = this.consoleMessages.get(tabId) || [];\n const args = params.args || [];\n\n const text = args\n .map((a: any) => {\n if (a.value !== undefined) return String(a.value);\n if (a.description) return a.description;\n return \"\";\n })\n .join(\" \");\n\n const callFrame = params.stackTrace?.callFrames?.[0];\n\n const msg: ConsoleMessage = {\n type: params.type || \"log\",\n text,\n timestamp: params.timestamp || Date.now(),\n url: callFrame?.url,\n line: callFrame?.lineNumber,\n };\n\n messages.push(msg);\n if (messages.length > 1000) messages.shift();\n this.consoleMessages.set(tabId, messages);\n\n const callbacks = this.consoleCallbacks.get(tabId);\n if (callbacks) {\n for (const cb of callbacks.values()) {\n cb(msg);\n }\n }\n }\n\n private handleRuntimeException(tabId: number, params: any): void {\n const messages = this.consoleMessages.get(tabId) || [];\n const details = params.exceptionDetails;\n if (!details) return;\n\n const msg: ConsoleMessage = {\n type: \"exception\",\n text: details.exception?.description || details.text || \"Unknown exception\",\n timestamp: details.timestamp || Date.now(),\n url: details.url,\n line: details.lineNumber,\n };\n\n messages.push(msg);\n if (messages.length > 1000) messages.shift();\n this.consoleMessages.set(tabId, messages);\n\n const callbacks = this.consoleCallbacks.get(tabId);\n if (callbacks) {\n for (const cb of callbacks.values()) {\n cb(msg);\n }\n }\n }\n\n private handleNetworkRequest(tabId: number, params: any): void {\n const requests = this.networkRequests.get(tabId) || [];\n const req = params.request;\n if (!req) return;\n\n const timestamp = params.timestamp ? params.timestamp * 1000 : Date.now();\n this.networkRequestStartTimes.set(params.requestId, timestamp);\n\n // Legacy format for backward compatibility\n const reqHeaders: Record<string, string> = {};\n if (req.headers) {\n for (const [key, value] of Object.entries(req.headers)) {\n reqHeaders[key] = String(value);\n }\n }\n\n requests.push({\n requestId: params.requestId,\n url: req.url,\n method: req.method,\n type: params.type,\n timestamp,\n requestHeaders: reqHeaders,\n requestBody: req.postData,\n });\n\n if (requests.length > 500) requests.shift();\n this.networkRequests.set(tabId, requests);\n\n // Full NetworkEntry format\n if (!this.networkEntries.has(tabId)) {\n this.networkEntries.set(tabId, new Map());\n }\n const entriesMap = this.networkEntries.get(tabId)!;\n \n // Generate unique ID\n const seq = ++this.networkEntrySeq;\n const entryId = `r_${timestamp}_${seq}`;\n\n // Extract headers as Record\n const requestHeaders: Record<string, string> = {};\n if (req.headers) {\n for (const [key, value] of Object.entries(req.headers)) {\n requestHeaders[key] = String(value);\n }\n }\n\n // Extract request body info\n const requestBody = req.postData;\n const requestBodySize = requestBody ? requestBody.length : undefined;\n\n const entry: NetworkEntry = {\n id: entryId,\n ts: timestamp,\n method: req.method,\n url: req.url,\n origin: this.extractOrigin(req.url),\n requestHeaders,\n requestBody,\n requestBodySize,\n tabId,\n tabUrl: params.documentURL,\n type: params.type,\n flags: [],\n _requestId: params.requestId,\n _responseReceived: false,\n _loadingFinished: false,\n };\n\n // Limit entries per tab\n if (entriesMap.size > 500) {\n const oldestKey = entriesMap.keys().next().value;\n if (oldestKey) entriesMap.delete(oldestKey);\n }\n \n entriesMap.set(params.requestId, entry);\n }\n\n private handleNetworkResponse(tabId: number, params: any): void {\n const requests = this.networkRequests.get(tabId) || [];\n const existing = requests.find((r) => r.requestId === params.requestId);\n if (existing) {\n existing.status = params.response?.status;\n existing.mimeType = params.response?.mimeType;\n\n // Capture response headers\n if (params.response?.headers) {\n const respHeaders: Record<string, string> = {};\n for (const [key, value] of Object.entries(params.response.headers)) {\n respHeaders[key] = String(value);\n }\n existing.responseHeaders = respHeaders;\n }\n\n const callbacks = this.networkCallbacks.get(tabId);\n if (callbacks) {\n const startTime = this.networkRequestStartTimes.get(params.requestId);\n const now = Date.now();\n const duration = startTime ? Math.round(now - startTime) : undefined;\n // Don't delete start time yet - we need it for loadingFinished\n // this.networkRequestStartTimes.delete(params.requestId);\n\n for (const cb of callbacks.values()) {\n cb({\n method: existing.method,\n url: existing.url,\n status: existing.status,\n duration,\n timestamp: now,\n });\n }\n }\n }\n\n // Update full NetworkEntry\n const entriesMap = this.networkEntries.get(tabId);\n const entry = entriesMap?.get(params.requestId);\n if (entry && params.response) {\n const response = params.response;\n \n // Calculate TTFB (time to first byte)\n const startTime = this.networkRequestStartTimes.get(params.requestId);\n const now = params.timestamp ? params.timestamp * 1000 : Date.now();\n if (startTime) {\n entry.ttfb = Math.round(now - startTime);\n }\n \n entry.status = response.status;\n entry.statusText = response.statusText;\n entry.mimeType = response.mimeType;\n \n // Extract response headers\n const responseHeaders: Record<string, string> = {};\n if (response.headers) {\n for (const [key, value] of Object.entries(response.headers)) {\n responseHeaders[key] = String(value);\n }\n }\n entry.responseHeaders = responseHeaders;\n \n // Check if binary type\n if (this.isBinaryType(response.mimeType)) {\n entry.flags.push('binary');\n }\n \n // Check for protobuf\n if (response.mimeType?.includes('protobuf') || \n response.mimeType?.includes('x-protobuf') ||\n response.mimeType?.includes('application/grpc')) {\n entry.flags.push('protobuf');\n }\n \n entry._responseReceived = true;\n }\n }\n\n private handleNetworkFailed(tabId: number, params: any): void {\n const requests = this.networkRequests.get(tabId) || [];\n const existing = requests.find((r) => r.requestId === params.requestId);\n if (existing && !existing.status) {\n existing.status = 0;\n\n const callbacks = this.networkCallbacks.get(tabId);\n if (callbacks) {\n const startTime = this.networkRequestStartTimes.get(params.requestId);\n const now = Date.now();\n const duration = startTime ? Math.round(now - startTime) : undefined;\n this.networkRequestStartTimes.delete(params.requestId);\n\n for (const cb of callbacks.values()) {\n cb({\n method: existing.method,\n url: existing.url,\n status: 0,\n duration,\n timestamp: now,\n });\n }\n }\n }\n\n // Update full NetworkEntry\n const entriesMap = this.networkEntries.get(tabId);\n const entry = entriesMap?.get(params.requestId);\n if (entry) {\n const startTime = this.networkRequestStartTimes.get(params.requestId);\n const now = params.timestamp ? params.timestamp * 1000 : Date.now();\n if (startTime) {\n entry.duration = Math.round(now - startTime);\n }\n this.networkRequestStartTimes.delete(params.requestId);\n \n entry.status = 0;\n entry.flags.push('failed');\n entry._loadingFinished = true;\n }\n }\n\n private handleDialogOpening(tabId: number, params: any): void {\n this.pendingDialogs.set(tabId, {\n type: params.type,\n message: params.message,\n defaultPrompt: params.defaultPrompt,\n timestamp: Date.now(),\n });\n }\n\n private async handleLoadingFinished(tabId: number, params: any): Promise<void> {\n // Update the simple requests array\n const requests = this.networkRequests.get(tabId) || [];\n const existing = requests.find((r) => r.requestId === params.requestId);\n if (existing) {\n // Calculate duration\n const startTime = this.networkRequestStartTimes.get(params.requestId);\n const now = params.timestamp ? params.timestamp * 1000 : Date.now();\n if (startTime) {\n existing.duration = Math.round(now - startTime);\n }\n\n // Fetch response body for small non-static responses (< 16KB)\n const shouldFetchBody = \n !this.isStaticAsset(existing.mimeType) &&\n !this.isBinaryType(existing.mimeType) &&\n (params.encodedDataLength || 0) <= CDPController.MAX_INLINE_BODY_SIZE;\n\n if (shouldFetchBody) {\n try {\n const result = await this.send(tabId, \"Network.getResponseBody\", {\n requestId: params.requestId,\n });\n \n if (result.base64Encoded) {\n try {\n existing.responseBody = atob(result.body);\n } catch {\n existing.responseBody = result.body;\n }\n } else {\n existing.responseBody = result.body;\n }\n \n // Truncate if too large\n if (existing.responseBody && existing.responseBody.length > CDPController.MAX_INLINE_BODY_SIZE) {\n existing.responseBody = existing.responseBody.slice(0, CDPController.MAX_INLINE_BODY_SIZE);\n }\n } catch (e) {\n // Body may not be available (e.g., cached, redirected)\n }\n }\n }\n\n // Update full NetworkEntry format\n const entriesMap = this.networkEntries.get(tabId);\n const entry = entriesMap?.get(params.requestId);\n if (!entry) return;\n\n // Calculate total duration\n const startTime = this.networkRequestStartTimes.get(params.requestId);\n const now = params.timestamp ? params.timestamp * 1000 : Date.now();\n if (startTime) {\n entry.duration = Math.round(now - startTime);\n }\n this.networkRequestStartTimes.delete(params.requestId);\n\n // Set response body size from encoded data length\n entry.responseBodySize = params.encodedDataLength;\n entry._loadingFinished = true;\n\n // Decide whether to fetch body inline\n const shouldFetchBody = \n !this.isStaticAsset(entry.mimeType) &&\n !this.isBinaryType(entry.mimeType) &&\n (params.encodedDataLength || 0) <= CDPController.MAX_INLINE_BODY_SIZE;\n\n if (shouldFetchBody) {\n try {\n const result = await this.send(tabId, \"Network.getResponseBody\", {\n requestId: params.requestId,\n });\n \n if (result.base64Encoded) {\n // Decode base64 for text content\n try {\n entry.responseBody = atob(result.body);\n } catch {\n entry.responseBody = result.body;\n entry.flags.push('binary');\n }\n } else {\n entry.responseBody = result.body;\n }\n \n // Check if truncated\n if (entry.responseBody && entry.responseBody.length > CDPController.MAX_INLINE_BODY_SIZE) {\n entry.responseBody = entry.responseBody.slice(0, CDPController.MAX_INLINE_BODY_SIZE);\n entry.flags.push('truncated');\n }\n } catch (e) {\n // Body may not be available (e.g., cached, redirected)\n // This is not an error - just means no body to capture\n }\n }\n }\n\n // Helper: Extract origin from URL\n private extractOrigin(url: string): string {\n try {\n const parsed = new URL(url);\n return parsed.origin;\n } catch {\n return '';\n }\n }\n\n // Helper: Check if MIME type is a static asset (skip body fetch)\n private isStaticAsset(mimeType?: string): boolean {\n if (!mimeType) return false;\n return CDPController.STATIC_ASSET_TYPES.has(mimeType);\n }\n\n // Helper: Check if MIME type is binary\n private isBinaryType(mimeType?: string): boolean {\n if (!mimeType) return false;\n return CDPController.BINARY_TYPES.has(mimeType);\n }\n\n async enableConsoleTracking(tabId: number): Promise<void> {\n await this.ensureAttached(tabId);\n try {\n await this.send(tabId, \"Runtime.enable\");\n } catch (e) {}\n }\n\n async enableNetworkTracking(tabId: number): Promise<void> {\n await this.ensureAttached(tabId);\n try {\n await this.send(tabId, \"Network.enable\", { maxPostDataSize: 65536 });\n } catch (e) {}\n }\n\n async handleDialog(tabId: number, accept: boolean, promptText?: string): Promise<{ success: boolean; error?: string }> {\n try {\n await this.send(tabId, \"Page.handleJavaScriptDialog\", {\n accept,\n promptText,\n });\n this.pendingDialogs.delete(tabId);\n return { success: true };\n } catch (e) {\n return { success: false, error: e instanceof Error ? e.message : String(e) };\n }\n }\n\n getDialogInfo(tabId: number): PendingDialog | null {\n return this.pendingDialogs.get(tabId) || null;\n }\n\n async emulateNetwork(tabId: number, preset: string): Promise<{ success: boolean; error?: string }> {\n await this.ensureAttached(tabId);\n const presets: Record<string, { offline: boolean; latency: number; downloadThroughput: number; uploadThroughput: number }> = {\n \"offline\": { offline: true, latency: 0, downloadThroughput: 0, uploadThroughput: 0 },\n \"slow-3g\": { offline: false, latency: 2000, downloadThroughput: 50000, uploadThroughput: 50000 },\n \"fast-3g\": { offline: false, latency: 562.5, downloadThroughput: 180000, uploadThroughput: 84375 },\n \"4g\": { offline: false, latency: 100, downloadThroughput: 4000000, uploadThroughput: 3000000 },\n \"reset\": { offline: false, latency: 0, downloadThroughput: -1, uploadThroughput: -1 },\n };\n const config = presets[preset.toLowerCase().replace(/\\s+/g, \"-\")];\n if (!config) {\n return { success: false, error: `Unknown preset: ${preset}. Available: ${Object.keys(presets).join(\", \")}` };\n }\n try {\n await this.send(tabId, \"Network.enable\");\n await this.send(tabId, \"Network.emulateNetworkConditions\", config);\n return { success: true };\n } catch (e) {\n return { success: false, error: e instanceof Error ? e.message : String(e) };\n }\n }\n\n async emulateCPU(tabId: number, rate: number): Promise<{ success: boolean; error?: string }> {\n await this.ensureAttached(tabId);\n if (rate < 1) {\n return { success: false, error: \"CPU throttling rate must be >= 1 (1 = no throttle, 4 = 4x slower)\" };\n }\n try {\n await this.send(tabId, \"Emulation.setCPUThrottlingRate\", { rate });\n return { success: true };\n } catch (e) {\n return { success: false, error: e instanceof Error ? e.message : String(e) };\n }\n }\n\n async emulateGeolocation(tabId: number, latitude: number, longitude: number, accuracy?: number): Promise<{ success: boolean; error?: string }> {\n await this.ensureAttached(tabId);\n try {\n await this.send(tabId, \"Emulation.setGeolocationOverride\", {\n latitude,\n longitude,\n accuracy: accuracy || 100,\n });\n return { success: true };\n } catch (e) {\n return { success: false, error: e instanceof Error ? e.message : String(e) };\n }\n }\n\n async clearGeolocation(tabId: number): Promise<{ success: boolean; error?: string }> {\n await this.ensureAttached(tabId);\n try {\n await this.send(tabId, \"Emulation.clearGeolocationOverride\");\n return { success: true };\n } catch (e) {\n return { success: false, error: e instanceof Error ? e.message : String(e) };\n }\n }\n\n async emulateDevice(\n tabId: number, \n device: { width: number; height: number; deviceScaleFactor: number; mobile: boolean; touch?: boolean; userAgent?: string }\n ): Promise<{ success: boolean; error?: string }> {\n await this.ensureAttached(tabId);\n try {\n // Set device metrics\n await this.send(tabId, \"Emulation.setDeviceMetricsOverride\", {\n width: device.width,\n height: device.height,\n deviceScaleFactor: device.deviceScaleFactor,\n mobile: device.mobile,\n });\n \n // Set user agent if provided\n if (device.userAgent) {\n await this.send(tabId, \"Emulation.setUserAgentOverride\", {\n userAgent: device.userAgent,\n });\n }\n \n // Enable touch if specified\n if (device.touch) {\n await this.send(tabId, \"Emulation.setTouchEmulationEnabled\", {\n enabled: true,\n maxTouchPoints: 5,\n });\n }\n \n return { success: true };\n } catch (e) {\n return { success: false, error: e instanceof Error ? e.message : String(e) };\n }\n }\n\n async clearDeviceEmulation(tabId: number): Promise<{ success: boolean; error?: string }> {\n await this.ensureAttached(tabId);\n try {\n await this.send(tabId, \"Emulation.clearDeviceMetricsOverride\");\n await this.send(tabId, \"Emulation.setUserAgentOverride\", { userAgent: \"\" });\n await this.send(tabId, \"Emulation.setTouchEmulationEnabled\", { enabled: false });\n return { success: true };\n } catch (e) {\n return { success: false, error: e instanceof Error ? e.message : String(e) };\n }\n }\n\n async emulateViewport(\n tabId: number, \n options: { width?: number; height?: number; deviceScaleFactor?: number; mobile?: boolean }\n ): Promise<{ success: boolean; error?: string }> {\n await this.ensureAttached(tabId);\n try {\n // Get current viewport size as defaults\n const viewport = await this.getViewportSize(tabId);\n \n await this.send(tabId, \"Emulation.setDeviceMetricsOverride\", {\n width: options.width || viewport.width,\n height: options.height || viewport.height,\n deviceScaleFactor: options.deviceScaleFactor || 1,\n mobile: options.mobile || false,\n });\n \n return { success: true };\n } catch (e) {\n return { success: false, error: e instanceof Error ? e.message : String(e) };\n }\n }\n\n async emulateTouch(tabId: number, enabled: boolean): Promise<{ success: boolean; error?: string }> {\n await this.ensureAttached(tabId);\n try {\n await this.send(tabId, \"Emulation.setTouchEmulationEnabled\", {\n enabled,\n maxTouchPoints: enabled ? 5 : 0,\n });\n return { success: true };\n } catch (e) {\n return { success: false, error: e instanceof Error ? e.message : String(e) };\n }\n }\n\n async startPerformanceTrace(tabId: number, categories?: string[]): Promise<{ success: boolean; error?: string }> {\n await this.ensureAttached(tabId);\n try {\n await this.send(tabId, \"Performance.enable\");\n await this.send(tabId, \"Tracing.start\", {\n categories: categories?.join(\",\") || \"devtools.timeline,v8.execute,disabled-by-default-devtools.timeline\",\n transferMode: \"ReturnAsStream\",\n });\n return { success: true };\n } catch (e) {\n return { success: false, error: e instanceof Error ? e.message : String(e) };\n }\n }\n\n async stopPerformanceTrace(tabId: number): Promise<{ success: boolean; metrics?: any; error?: string }> {\n await this.ensureAttached(tabId);\n try {\n await this.send(tabId, \"Performance.enable\");\n const metricsResult = await this.send(tabId, \"Performance.getMetrics\");\n await this.send(tabId, \"Tracing.end\");\n await this.send(tabId, \"Performance.disable\");\n const metrics: Record<string, number> = {};\n for (const m of metricsResult.metrics || []) {\n metrics[m.name] = m.value;\n }\n return { success: true, metrics };\n } catch (e) {\n return { success: false, error: e instanceof Error ? e.message : String(e) };\n }\n }\n\n async getPerformanceMetrics(tabId: number): Promise<{ success: boolean; metrics?: Record<string, number>; error?: string }> {\n await this.ensureAttached(tabId);\n try {\n await this.send(tabId, \"Performance.enable\");\n const result = await this.send(tabId, \"Performance.getMetrics\");\n await this.send(tabId, \"Performance.disable\");\n const metrics: Record<string, number> = {};\n for (const m of result.metrics || []) {\n metrics[m.name] = m.value;\n }\n return { success: true, metrics };\n } catch (e) {\n return { success: false, error: e instanceof Error ? e.message : String(e) };\n }\n }\n\n async setFileInputBySelector(tabId: number, selector: string, files: string[]): Promise<{ success: boolean; error?: string }> {\n await this.ensureAttached(tabId);\n try {\n await this.send(tabId, \"DOM.enable\");\n const doc = await this.send(tabId, \"DOM.getDocument\");\n const queryResult = await this.send(tabId, \"DOM.querySelector\", {\n nodeId: doc.root.nodeId,\n selector,\n });\n if (!queryResult.nodeId) {\n return { success: false, error: \"Could not find element by selector\" };\n }\n await this.send(tabId, \"DOM.setFileInputFiles\", {\n nodeId: queryResult.nodeId,\n files,\n });\n return { success: true };\n } catch (e) {\n return { success: false, error: e instanceof Error ? e.message : String(e) };\n }\n }\n\n async waitForLoad(tabId: number, timeout: number = 30000): Promise<{ success: boolean; readyState?: string; error?: string }> {\n await this.ensureAttached(tabId);\n const startTime = Date.now();\n try {\n while (Date.now() - startTime < timeout) {\n const result = await this.send(tabId, \"Runtime.evaluate\", {\n expression: \"document.readyState\",\n returnByValue: true,\n });\n const readyState = result.result?.value;\n if (readyState === \"complete\") {\n return { success: true, readyState };\n }\n await new Promise(resolve => setTimeout(resolve, 100));\n }\n return { success: false, error: `Timeout waiting for page load (${timeout}ms)` };\n } catch (e) {\n return { success: false, error: e instanceof Error ? e.message : String(e) };\n }\n }\n\n async getFrames(tabId: number): Promise<{ success: boolean; frames?: Array<{ frameId: string; url: string; name: string; parentId?: string }>; error?: string }> {\n await this.ensureAttached(tabId);\n try {\n await this.send(tabId, \"Page.enable\");\n const result = await this.send(tabId, \"Page.getFrameTree\");\n const frames: Array<{ frameId: string; url: string; name: string; parentId?: string }> = [];\n const extractFrames = (frame: any, parentId?: string) => {\n frames.push({\n frameId: frame.frame.id,\n url: frame.frame.url,\n name: frame.frame.name || \"\",\n parentId,\n });\n if (frame.childFrames) {\n for (const child of frame.childFrames) {\n extractFrames(child, frame.frame.id);\n }\n }\n };\n extractFrames(result.frameTree);\n return { success: true, frames };\n } catch (e) {\n return { success: false, error: e instanceof Error ? e.message : String(e) };\n }\n }\n\n async evaluateInFrame(tabId: number, frameId: string, expression: string): Promise<{ success: boolean; result?: any; error?: string }> {\n await this.ensureAttached(tabId);\n try {\n const contextResult = await this.send(tabId, \"Page.createIsolatedWorld\", {\n frameId,\n worldName: \"surf-isolated\",\n });\n const wrappedExpression = `JSON.stringify((function() { ${expression} })())`;\n const result = await this.send(tabId, \"Runtime.evaluate\", {\n expression: wrappedExpression,\n contextId: contextResult.executionContextId,\n returnByValue: true,\n awaitPromise: true,\n });\n if (result.exceptionDetails) {\n return { success: false, error: result.exceptionDetails.text || result.exceptionDetails.exception?.description || \"Evaluation failed\" };\n }\n try {\n return { success: true, result: JSON.parse(result.result?.value) };\n } catch {\n return { success: true, result: result.result?.value };\n }\n } catch (e) {\n return { success: false, error: e instanceof Error ? e.message : String(e) };\n }\n }\n\n getConsoleMessages(\n tabId: number,\n options?: {\n onlyErrors?: boolean;\n pattern?: string;\n limit?: number;\n }\n ): ConsoleMessage[] {\n let messages = this.consoleMessages.get(tabId) || [];\n\n if (options?.onlyErrors) {\n messages = messages.filter((m) => m.type === \"error\" || m.type === \"exception\");\n }\n if (options?.pattern) {\n try {\n const regex = new RegExp(options.pattern, \"i\");\n messages = messages.filter((m) => regex.test(m.text));\n } catch (e) {\n messages = messages.filter((m) => m.text.includes(options.pattern!));\n }\n }\n if (options?.limit) {\n messages = messages.slice(-options.limit);\n }\n\n return [...messages];\n }\n\n clearConsoleMessages(tabId: number): void {\n this.consoleMessages.set(tabId, []);\n }\n\n getNetworkRequests(\n tabId: number,\n options?: {\n urlPattern?: string;\n limit?: number;\n }\n ): NetworkRequest[] {\n let requests = this.networkRequests.get(tabId) || [];\n\n if (options?.urlPattern) {\n requests = requests.filter((r) => r.url.includes(options.urlPattern!));\n }\n if (options?.limit) {\n requests = requests.slice(-options.limit);\n }\n\n return [...requests];\n }\n\n clearNetworkRequests(tabId: number): void {\n this.networkRequests.set(tabId, []);\n this.networkEntries.set(tabId, new Map());\n }\n\n /**\n * Get all full network entries for a tab\n */\n getNetworkEntries(\n tabId: number,\n options?: {\n urlPattern?: string;\n limit?: number;\n includeStatic?: boolean;\n }\n ): NetworkEntry[] {\n // First try the full entries map\n const entriesMap = this.networkEntries.get(tabId);\n let entries: NetworkEntry[] = [];\n \n if (entriesMap && entriesMap.size > 0) {\n entries = Array.from(entriesMap.values());\n } else {\n // Fallback to basic networkRequests and convert to NetworkEntry format\n const requests = this.networkRequests.get(tabId) || [];\n entries = requests.map((req, idx) => ({\n id: `r_${req.timestamp}_${idx}`,\n ts: req.timestamp,\n method: req.method,\n url: req.url,\n origin: this.extractOrigin(req.url),\n requestHeaders: {},\n tabId: tabId,\n type: req.type,\n status: req.status,\n flags: [],\n _requestId: req.requestId,\n _responseReceived: true,\n _loadingFinished: true,\n } as NetworkEntry));\n }\n\n // Filter out static assets by default\n if (!options?.includeStatic) {\n entries = entries.filter(e => !this.isStaticAsset(e.mimeType));\n }\n\n if (options?.urlPattern) {\n entries = entries.filter((e) => e.url.includes(options.urlPattern!));\n }\n\n if (options?.limit) {\n entries = entries.slice(-options.limit);\n }\n\n return entries;\n }\n\n /**\n * Get a single network entry by request ID\n */\n getNetworkEntry(tabId: number, requestId: string): NetworkEntry | null {\n const entriesMap = this.networkEntries.get(tabId);\n return entriesMap?.get(requestId) || null;\n }\n\n /**\n * Fetch response body on demand via CDP\n * Use this for bodies that weren't fetched inline (large or binary)\n */\n async getResponseBody(tabId: number, requestId: string): Promise<{\n success: boolean;\n body?: string;\n base64Encoded?: boolean;\n error?: string;\n }> {\n await this.ensureAttached(tabId);\n \n try {\n const result = await this.send(tabId, \"Network.getResponseBody\", {\n requestId,\n });\n \n return {\n success: true,\n body: result.body,\n base64Encoded: result.base64Encoded,\n };\n } catch (e) {\n return {\n success: false,\n error: e instanceof Error ? e.message : String(e),\n };\n }\n }\n\n subscribeToConsole(tabId: number, streamId: number, callback: ConsoleEventCallback): void {\n if (!this.consoleCallbacks.has(tabId)) {\n this.consoleCallbacks.set(tabId, new Map());\n }\n this.consoleCallbacks.get(tabId)!.set(streamId, callback);\n }\n\n unsubscribeFromConsole(tabId: number, streamId: number): void {\n const callbacks = this.consoleCallbacks.get(tabId);\n if (callbacks) {\n callbacks.delete(streamId);\n if (callbacks.size === 0) {\n this.consoleCallbacks.delete(tabId);\n }\n }\n }\n\n subscribeToNetwork(tabId: number, streamId: number, callback: NetworkEventCallback): void {\n if (!this.networkCallbacks.has(tabId)) {\n this.networkCallbacks.set(tabId, new Map());\n }\n this.networkCallbacks.get(tabId)!.set(streamId, callback);\n }\n\n unsubscribeFromNetwork(tabId: number, streamId: number): void {\n const callbacks = this.networkCallbacks.get(tabId);\n if (callbacks) {\n callbacks.delete(streamId);\n if (callbacks.size === 0) {\n this.networkCallbacks.delete(tabId);\n }\n }\n }\n\n async evaluateScript(tabId: number, expression: string): Promise<{\n result?: { value?: any; type?: string; description?: string };\n exceptionDetails?: { text?: string; exception?: { description?: string } };\n }> {\n await this.ensureAttached(tabId);\n try {\n await this.send(tabId, \"Runtime.enable\");\n } catch (e) {}\n \n return this.send(tabId, \"Runtime.evaluate\", {\n expression,\n returnByValue: true,\n awaitPromise: true,\n timeout: 30000,\n });\n }\n\n private async send(tabId: number, method: string, params?: object): Promise<any> {\n await this.ensureAttached(tabId);\n const target = this.targets.get(tabId)!;\n return chrome.debugger.sendCommand(target, method, params);\n }\n\n async sendCommand(tabId: number, method: string, params?: object): Promise<any> {\n return this.send(tabId, method, params);\n }\n\n private async ensureAttached(tabId: number): Promise<void> {\n if (!this.targets.has(tabId)) {\n await this.attach(tabId);\n }\n }\n\n async getViewportSize(tabId: number): Promise<{ width: number; height: number }> {\n const layoutMetrics = await this.send(tabId, \"Page.getLayoutMetrics\");\n const viewport = layoutMetrics.visualViewport || layoutMetrics.layoutViewport;\n return {\n width: Math.round(viewport.clientWidth),\n height: Math.round(viewport.clientHeight),\n };\n }\n\n async captureScreenshot(tabId: number): Promise<{\n base64: string;\n width: number;\n height: number;\n }> {\n const result = await this.send(tabId, \"Page.captureScreenshot\", {\n format: \"png\",\n captureBeyondViewport: false,\n });\n const { width, height } = await this.getViewportSize(tabId);\n return { base64: result.data, width, height };\n }\n\n async captureRegion(tabId: number, x: number, y: number, width: number, height: number): Promise<{\n base64: string;\n width: number;\n height: number;\n }> {\n const result = await this.send(tabId, \"Page.captureScreenshot\", {\n format: \"png\",\n clip: { x, y, width, height, scale: 1 },\n });\n return { base64: result.data, width, height };\n }\n\n private async dispatchMouseEvent(\n tabId: number,\n type: \"mousePressed\" | \"mouseReleased\" | \"mouseMoved\" | \"mouseWheel\",\n x: number,\n y: number,\n options: {\n button?: MouseButton;\n buttons?: number;\n clickCount?: number;\n modifiers?: number;\n deltaX?: number;\n deltaY?: number;\n } = {}\n ): Promise<void> {\n const params: Record<string, any> = {\n type,\n x: Math.round(x),\n y: Math.round(y),\n modifiers: options.modifiers || 0,\n };\n\n if (type === \"mousePressed\" || type === \"mouseReleased\" || type === \"mouseMoved\") {\n params.button = options.button || \"none\";\n if (type === \"mousePressed\" || type === \"mouseReleased\") {\n params.clickCount = options.clickCount || 1;\n }\n }\n\n if (type !== \"mouseWheel\") {\n params.buttons = options.buttons ?? 0;\n }\n\n if (type === \"mouseWheel\") {\n params.deltaX = options.deltaX || 0;\n params.deltaY = options.deltaY || 0;\n }\n\n await this.send(tabId, \"Input.dispatchMouseEvent\", params);\n }\n\n async click(\n tabId: number,\n x: number,\n y: number,\n button: MouseButton = \"left\",\n clickCount = 1,\n modifiers = 0\n ): Promise<void> {\n const buttonValue = button === \"left\" ? 1 : button === \"right\" ? 2 : button === \"middle\" ? 4 : 0;\n\n await this.dispatchMouseEvent(tabId, \"mouseMoved\", x, y, { button: \"none\", buttons: 0, modifiers });\n await new Promise(resolve => setTimeout(resolve, 100));\n\n for (let i = 1; i <= clickCount; i++) {\n await this.dispatchMouseEvent(tabId, \"mousePressed\", x, y, {\n button,\n buttons: buttonValue,\n clickCount: i,\n modifiers,\n });\n await new Promise(resolve => setTimeout(resolve, 12));\n await this.dispatchMouseEvent(tabId, \"mouseReleased\", x, y, {\n button,\n buttons: 0,\n clickCount: i,\n modifiers,\n });\n if (i < clickCount) {\n await new Promise(resolve => setTimeout(resolve, 100));\n }\n }\n }\n\n async rightClick(tabId: number, x: number, y: number, modifiers = 0): Promise<void> {\n await this.click(tabId, x, y, \"right\", 1, modifiers);\n }\n\n async doubleClick(tabId: number, x: number, y: number, modifiers = 0): Promise<void> {\n await this.click(tabId, x, y, \"left\", 2, modifiers);\n }\n\n async tripleClick(tabId: number, x: number, y: number, modifiers = 0): Promise<void> {\n await this.click(tabId, x, y, \"left\", 3, modifiers);\n }\n\n async hover(tabId: number, x: number, y: number): Promise<void> {\n await this.dispatchMouseEvent(tabId, \"mouseMoved\", x, y, { button: \"none\", buttons: 0 });\n }\n\n async drag(\n tabId: number,\n startX: number,\n startY: number,\n endX: number,\n endY: number,\n modifiers = 0\n ): Promise<void> {\n await this.dispatchMouseEvent(tabId, \"mouseMoved\", startX, startY, { button: \"none\", buttons: 0 });\n await new Promise(resolve => setTimeout(resolve, 50));\n\n await this.dispatchMouseEvent(tabId, \"mousePressed\", startX, startY, {\n button: \"left\",\n buttons: 1,\n clickCount: 1,\n modifiers,\n });\n await new Promise(resolve => setTimeout(resolve, 50));\n\n await this.dispatchMouseEvent(tabId, \"mouseMoved\", endX, endY, { button: \"left\", buttons: 1, modifiers });\n await new Promise(resolve => setTimeout(resolve, 50));\n\n await this.dispatchMouseEvent(tabId, \"mouseReleased\", endX, endY, {\n button: \"left\",\n buttons: 0,\n clickCount: 1,\n modifiers,\n });\n }\n\n async scroll(tabId: number, x: number, y: number, deltaX: number, deltaY: number): Promise<void> {\n await this.dispatchMouseEvent(tabId, \"mouseWheel\", x, y, { deltaX, deltaY });\n }\n\n async type(tabId: number, text: string): Promise<void> {\n for (const char of text) {\n if (char === \"\\n\" || char === \"\\r\") {\n await this.pressKey(tabId, \"Enter\");\n } else {\n const keyDef = this.getKeyDefinition(char);\n if (keyDef) {\n const needsShift = this.requiresShift(char);\n await this.pressKey(tabId, char, needsShift ? MODIFIERS.shift : 0);\n } else {\n await this.send(tabId, \"Input.insertText\", { text: char });\n }\n }\n }\n }\n\n private requiresShift(char: string): boolean {\n return /[A-Z!@#$%^&*()_+{}|:\"<>?~]/.test(char);\n }\n\n private async dispatchKeyEvent(\n tabId: number,\n type: \"keyDown\" | \"keyUp\" | \"rawKeyDown\" | \"char\",\n keyDef: KeyDefinition,\n modifiers = 0\n ): Promise<void> {\n await this.send(tabId, \"Input.dispatchKeyEvent\", {\n type: keyDef.text ? type : (type === \"keyDown\" ? \"rawKeyDown\" : type),\n key: keyDef.key,\n code: keyDef.code,\n windowsVirtualKeyCode: keyDef.keyCode,\n modifiers,\n text: keyDef.text ?? \"\",\n unmodifiedText: keyDef.text ?? \"\",\n location: keyDef.location ?? 0,\n });\n }\n\n async pressKey(tabId: number, key: string, modifiers = 0): Promise<void> {\n const keyDef = this.getKeyDefinition(key);\n if (!keyDef) {\n throw new Error(`Unknown key: ${key}`);\n }\n\n await this.dispatchKeyEvent(tabId, \"keyDown\", keyDef, modifiers);\n await this.dispatchKeyEvent(tabId, \"keyUp\", keyDef, modifiers);\n }\n\n async pressKeyChord(tabId: number, chord: string): Promise<void> {\n const parts = chord.toLowerCase().split(\"+\");\n const modifierKeys: string[] = [];\n let mainKey = \"\";\n\n for (const part of parts) {\n if (part in MODIFIERS) {\n modifierKeys.push(part);\n } else {\n mainKey = part;\n }\n }\n\n let modifiers = 0;\n for (const mod of modifierKeys) {\n modifiers |= MODIFIERS[mod as keyof typeof MODIFIERS] || 0;\n }\n\n if (mainKey) {\n await this.pressKey(tabId, mainKey, modifiers);\n }\n }\n\n private getKeyDefinition(key: string): KeyDefinition | null {\n const lowerKey = key.toLowerCase();\n \n if (KEY_DEFINITIONS[lowerKey]) {\n return KEY_DEFINITIONS[lowerKey];\n }\n\n if (key.length === 1) {\n const code = key.toUpperCase().charCodeAt(0);\n return {\n key,\n code: `Key${key.toUpperCase()}`,\n keyCode: code,\n text: key,\n };\n }\n\n return null;\n }\n\n parseModifiers(modifierString?: string): number {\n if (!modifierString) return 0;\n \n let result = 0;\n const parts = modifierString.toLowerCase().split(\"+\");\n for (const part of parts) {\n const trimmed = part.trim();\n if (trimmed in MODIFIERS) {\n result |= MODIFIERS[trimmed as keyof typeof MODIFIERS];\n }\n }\n return result;\n }\n}\n","let debugMode = false;\nlet initialized = false;\nconst pendingLogs: unknown[][] = [];\n\nchrome.storage.local.get(\"debugMode\").then(({ debugMode: stored }) => {\n debugMode = !!stored;\n initialized = true;\n if (debugMode) {\n for (const args of pendingLogs) {\n console.log(\"[Surf]\", ...args);\n }\n }\n pendingLogs.length = 0;\n});\n\nchrome.storage.onChanged.addListener((changes, areaName) => {\n if (areaName === \"local\" && changes.debugMode) {\n debugMode = !!changes.debugMode.newValue;\n }\n});\n\nexport function debugLog(...args: unknown[]): void {\n if (!initialized) {\n pendingLogs.push(args);\n return;\n }\n if (debugMode) {\n console.log(\"[Surf]\", ...args);\n }\n}\n\nexport function isDebugMode(): boolean {\n return debugMode;\n}\n","import { sendToNativeHost } from \"./port-manager\";\n\nexport interface ApiStreamCallbacks {\n onStart: (status: number, headers: Record<string, string>) => void;\n onChunk: (chunk: string) => void;\n onEnd: () => void;\n onError: (error: string) => void;\n}\n\nconst streamCallbacks = new Map<string, ApiStreamCallbacks>();\nlet streamIdCounter = 0;\n\nexport function handleNativeApiResponse(msg: any): boolean {\n const { type, streamId } = msg;\n \n if (!streamId || !streamCallbacks.has(streamId)) {\n return false;\n }\n \n const callbacks = streamCallbacks.get(streamId)!;\n \n switch (type) {\n case \"API_RESPONSE_START\":\n callbacks.onStart(msg.status, msg.headers);\n return true;\n case \"API_RESPONSE_CHUNK\":\n callbacks.onChunk(msg.chunk);\n return true;\n case \"API_RESPONSE_END\":\n callbacks.onEnd();\n streamCallbacks.delete(streamId);\n return true;\n case \"API_RESPONSE_ERROR\":\n callbacks.onError(msg.error);\n streamCallbacks.delete(streamId);\n return true;\n default:\n return false;\n }\n}\n\nexport async function nativeApiFetch(\n url: string,\n options: {\n method?: string;\n headers?: Record<string, string>;\n body?: string;\n },\n callbacks: ApiStreamCallbacks\n): Promise<void> {\n const streamId = `stream_${++streamIdCounter}_${Date.now()}`;\n \n streamCallbacks.set(streamId, callbacks);\n \n try {\n await sendToNativeHost({\n type: \"API_REQUEST\",\n streamId,\n url,\n method: options.method || \"POST\",\n headers: options.headers || {},\n body: options.body,\n });\n } catch (err) {\n streamCallbacks.delete(streamId);\n callbacks.onError(err instanceof Error ? err.message : \"Unknown error\");\n }\n}\n","import { debugLog } from \"../utils/debug\";\nimport { handleNativeApiResponse } from \"./native-api-transport\";\n\nlet nativePort: chrome.runtime.Port | null = null;\nlet messageHandler: ((msg: any) => Promise<any>) | null = null;\nlet reconnectTimeout: ReturnType<typeof setTimeout> | null = null;\nlet pendingNativeRequests = new Map<number, { resolve: (value: any) => void; reject: (err: Error) => void }>();\nlet nativeRequestId = 0;\n\nexport function initNativeMessaging(\n handler: (msg: any) => Promise<any>\n): void {\n messageHandler = handler;\n connect();\n}\n\nexport function sendToNativeHost(msg: any): Promise<any> {\n return new Promise((resolve, reject) => {\n if (!nativePort) {\n reject(new Error(\"Native host not connected\"));\n return;\n }\n \n if (msg.type === \"API_REQUEST\") {\n nativePort.postMessage(msg);\n resolve({ sent: true });\n return;\n }\n \n const id = ++nativeRequestId;\n pendingNativeRequests.set(id, { resolve, reject });\n nativePort.postMessage({ ...msg, id });\n \n setTimeout(() => {\n if (pendingNativeRequests.has(id)) {\n pendingNativeRequests.delete(id);\n reject(new Error(\"Native host request timeout\"));\n }\n }, 10000);\n });\n}\n\nexport function postToNativeHost(msg: any): void {\n if (nativePort) {\n nativePort.postMessage(msg);\n }\n}\n\nfunction connect(): void {\n if (reconnectTimeout) {\n clearTimeout(reconnectTimeout);\n reconnectTimeout = null;\n }\n\n try {\n nativePort = chrome.runtime.connectNative(\"surf.browser.host\");\n debugLog(\"Connecting to native host...\");\n\n nativePort.onMessage.addListener(async (msg) => {\n debugLog(\"Received from native host:\", msg.type || msg.id);\n\n if (msg.type === \"HOST_READY\") {\n debugLog(\"Native host ready\");\n return;\n }\n\n if (msg.type?.startsWith(\"API_RESPONSE_\")) {\n handleNativeApiResponse(msg);\n chrome.runtime.sendMessage(msg).catch(() => {});\n return;\n }\n\n if (msg.id && pendingNativeRequests.has(msg.id)) {\n const { resolve } = pendingNativeRequests.get(msg.id)!;\n pendingNativeRequests.delete(msg.id);\n resolve(msg);\n return;\n }\n\n if (!messageHandler) return;\n\n try {\n const result = await messageHandler(msg);\n if (!nativePort) {\n debugLog(\"Cannot send response - native host disconnected:\", msg.id);\n return;\n }\n nativePort.postMessage({ id: msg.id, ...result });\n } catch (err) {\n if (!nativePort) {\n debugLog(\"Cannot send error - native host disconnected:\", msg.id);\n return;\n }\n nativePort.postMessage({\n id: msg.id,\n error: err instanceof Error ? err.message : \"Unknown error\",\n });\n }\n });\n\n nativePort.onDisconnect.addListener(() => {\n const error = chrome.runtime.lastError;\n debugLog(\n \"Native host disconnected:\",\n error?.message || \"unknown reason\"\n );\n nativePort = null;\n\n if (!error?.message?.includes(\"not found\")) {\n reconnectTimeout = setTimeout(connect, 5000);\n }\n });\n } catch (err) {\n debugLog(\"Failed to connect to native host:\", err);\n reconnectTimeout = setTimeout(connect, 10000);\n }\n}\n","import { CDPController } from \"../cdp/controller\";\nimport { debugLog } from \"../utils/debug\";\nimport { initNativeMessaging, postToNativeHost } from \"../native/port-manager\";\n\ndebugLog(\"Service worker loaded\");\n\nconst cdp = new CDPController();\nconst activeStreamTabs = new Map<number, number>();\n\n// Frame context per tab - stores the active frameId for each tab\n// When frame.switch is called, subsequent content script messages go to that frame\nconst frameContexts = new Map<number, number>();\n\n// Helper to get the frame ID for content script messaging\nfunction getFrameIdForTab(tabId: number): number {\n return frameContexts.get(tabId) ?? 0;\n}\n\nconst screenshotCache = new Map<string, { base64: string; width: number; height: number }>();\nlet screenshotCounter = 0;\n\nfunction generateScreenshotId(): string {\n return `screenshot_${++screenshotCounter}_${Date.now()}`;\n}\n\nfunction cacheScreenshot(id: string, data: { base64: string; width: number; height: number }): void {\n screenshotCache.set(id, data);\n if (screenshotCache.size > 10) {\n const oldest = screenshotCache.keys().next().value;\n if (oldest) screenshotCache.delete(oldest);\n }\n}\n\nfunction getScreenshot(id: string): { base64: string; width: number; height: number } | null {\n return screenshotCache.get(id) || null;\n}\n\nconst ELEMENT_COLORS: Record<string, string> = {\n button: '#FF6B6B',\n input: '#4ECDC4',\n select: '#45B7D1',\n a: '#96CEB4',\n textarea: '#FF8C42',\n default: '#DDA0DD',\n};\n\nasync function annotateScreenshot(\n screenshot: { base64: string; width: number; height: number },\n elements: Array<{ ref: string; tag: string; bounds: { x: number; y: number; width: number; height: number } }>,\n scale: { scaleX: number; scaleY: number }\n): Promise<{ base64: string; width: number; height: number }> {\n const blob = base64ToBlob(screenshot.base64);\n const bitmap = await createImageBitmap(blob);\n \n const canvas = new OffscreenCanvas(bitmap.width, bitmap.height);\n const ctx = canvas.getContext(\"2d\");\n if (!ctx) throw new Error(\"Failed to get canvas context\");\n \n ctx.drawImage(bitmap, 0, 0);\n bitmap.close();\n \n const scaleFactor = Math.min(scale.scaleX, scale.scaleY);\n \n for (const element of elements) {\n const color = ELEMENT_COLORS[element.tag] || ELEMENT_COLORS.default;\n \n const x = Math.round(element.bounds.x * scaleFactor);\n const y = Math.round(element.bounds.y * scaleFactor);\n const w = Math.round(element.bounds.width * scaleFactor);\n const h = Math.round(element.bounds.height * scaleFactor);\n \n if (w < 1 || h < 1) continue;\n \n ctx.strokeStyle = color;\n ctx.lineWidth = 2;\n ctx.setLineDash([4, 4]);\n ctx.strokeRect(x, y, w, h);\n ctx.setLineDash([]);\n \n const labelText = element.ref;\n const fontSize = Math.max(10, Math.min(16, Math.round(canvas.width * 0.01)));\n ctx.font = `bold ${fontSize}px sans-serif`;\n const textWidth = ctx.measureText(labelText).width;\n const padding = 4;\n const labelWidth = textWidth + padding * 2;\n const labelHeight = fontSize + padding * 2;\n \n let labelX = x + Math.floor((w - labelWidth) / 2);\n let labelY = y + 2;\n if (w < 60 || h < 30) {\n labelY = y - labelHeight - 2 < 0 ? y + h + 2 : y - labelHeight - 2;\n }\n \n labelX = Math.max(0, Math.min(canvas.width - labelWidth, labelX));\n labelY = Math.max(0, Math.min(canvas.height - labelHeight, labelY));\n \n ctx.fillStyle = color;\n ctx.fillRect(labelX, labelY, labelWidth, labelHeight);\n ctx.strokeStyle = \"white\";\n ctx.lineWidth = 1;\n ctx.strokeRect(labelX, labelY, labelWidth, labelHeight);\n \n ctx.fillStyle = \"white\";\n ctx.textBaseline = \"top\";\n ctx.fillText(labelText, labelX + padding, labelY + padding);\n }\n \n const resultBlob = await canvas.convertToBlob({ type: \"image/png\" });\n const base64 = await blobToBase64(resultBlob);\n \n return { base64, width: canvas.width, height: canvas.height };\n}\n\nfunction blobToBase64(blob: Blob): Promise<string> {\n return new Promise((resolve, reject) => {\n const reader = new FileReader();\n reader.onload = () => {\n const dataUrl = reader.result as string;\n const base64 = dataUrl.split(\",\")[1];\n resolve(base64);\n };\n reader.onerror = () => reject(new Error(\"Failed to convert blob to base64\"));\n reader.readAsDataURL(blob);\n });\n}\n\nfunction base64ToBlob(base64: string, mimeType = \"image/png\"): Blob {\n const binary = atob(base64);\n const bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++) {\n bytes[i] = binary.charCodeAt(i);\n }\n return new Blob([bytes], { type: mimeType });\n}\n\nasync function captureFullPage(tabId: number, maxHeight: number): Promise<{ base64: string; width: number; height: number }> {\n const dimensionsResult = await cdp.evaluateScript(tabId, `(() => ({\n viewportHeight: window.innerHeight,\n totalHeight: Math.min(document.documentElement.scrollHeight, ${maxHeight}),\n width: window.innerWidth,\n devicePixelRatio: window.devicePixelRatio || 1,\n originalScrollY: window.scrollY,\n }))()`);\n \n const dimensions = dimensionsResult.result?.value;\n if (!dimensions) throw new Error(\"Failed to get page dimensions\");\n \n const { viewportHeight, totalHeight, width, devicePixelRatio, originalScrollY } = dimensions;\n const chunks: ImageBitmap[] = [];\n let currentY = 0;\n \n while (currentY < totalHeight) {\n await cdp.evaluateScript(tabId, `window.scrollTo(0, ${currentY})`);\n await new Promise(r => setTimeout(r, 300));\n \n const chunk = await cdp.captureScreenshot(tabId);\n const chunkBlob = base64ToBlob(chunk.base64);\n chunks.push(await createImageBitmap(chunkBlob));\n \n currentY += viewportHeight;\n }\n \n await cdp.evaluateScript(tabId, `window.scrollTo(0, ${originalScrollY})`);\n \n const canvasWidth = Math.round(width * devicePixelRatio);\n const canvasHeight = Math.round(totalHeight * devicePixelRatio);\n const canvas = new OffscreenCanvas(canvasWidth, canvasHeight);\n const ctx = canvas.getContext(\"2d\");\n if (!ctx) throw new Error(\"Failed to get canvas context\");\n \n let y = 0;\n const chunkHeight = Math.round(viewportHeight * devicePixelRatio);\n for (let i = 0; i < chunks.length; i++) {\n const chunk = chunks[i];\n const remainingHeight = canvasHeight - y;\n const drawHeight = Math.min(chunkHeight, remainingHeight);\n ctx.drawImage(chunk, 0, 0, chunk.width, drawHeight, 0, y, chunk.width, drawHeight);\n y += drawHeight;\n chunk.close();\n }\n \n const resultBlob = await canvas.convertToBlob({ type: \"image/png\" });\n const base64 = await blobToBase64(resultBlob);\n \n return { base64, width: canvasWidth, height: canvasHeight };\n}\n\nconst navigationResolvers = new Map<number, () => void>();\nconst tabNameRegistry = new Map<string, number>();\n\nchrome.webNavigation.onCompleted.addListener((details) => {\n if (details.frameId === 0) {\n // Clear frame context on main frame navigation (iframes may have changed)\n frameContexts.delete(details.tabId);\n const resolver = navigationResolvers.get(details.tabId);\n if (resolver) {\n resolver();\n navigationResolvers.delete(details.tabId);\n }\n }\n});\n\nchrome.webNavigation.onErrorOccurred.addListener((details) => {\n if (details.frameId === 0) {\n const resolver = navigationResolvers.get(details.tabId);\n if (resolver) {\n resolver();\n navigationResolvers.delete(details.tabId);\n }\n }\n});\n\n\n\nchrome.tabs.onRemoved.addListener((tabId) => {\n cdp.detach(tabId);\n frameContexts.delete(tabId);\n for (const [name, id] of tabNameRegistry) {\n if (id === tabId) {\n tabNameRegistry.delete(name);\n }\n }\n for (const [streamId, streamTabId] of activeStreamTabs) {\n if (streamTabId === tabId) {\n activeStreamTabs.delete(streamId);\n }\n }\n});\n\n/**\n * Wait for JavaScript runtime to be ready in a newly created/attached tab.\n * This is needed because document.readyState === 'complete' doesn't mean\n * React/Vue/etc frameworks have finished hydrating.\n */\nasync function waitForRuntimeReady(tabId: number, timeoutMs = 10000): Promise<void> {\n const deadline = Date.now() + timeoutMs;\n const delay = (ms: number) => new Promise(r => setTimeout(r, ms));\n \n // Poll until we can successfully evaluate JS\n while (Date.now() < deadline) {\n try {\n const result = await cdp.evaluateScript(tabId, \"document.readyState\");\n if (result?.result?.value === \"complete\") {\n // Extra delay for framework hydration (React, Vue, etc.)\n await delay(1500);\n return;\n }\n } catch {\n // CDP not ready yet, continue polling\n }\n await delay(200);\n }\n \n // Timeout but proceed anyway - the page might still work\n console.warn(`waitForRuntimeReady timed out for tab ${tabId}`);\n}\n\n// Helper for locate.* commands with actions\nasync function performLocateAction(\n tabId: number, \n ref: string, \n action: string, \n value: string | undefined,\n cdp: CDPController,\n frameId: number = 0\n): Promise<any> {\n switch (action) {\n case \"click\": {\n const result = await chrome.tabs.sendMessage(tabId, {\n type: \"CLICK_ELEMENT\",\n ref,\n button: \"left\",\n }, { frameId });\n return result.error ? result : { success: true, action: \"click\", ref };\n }\n case \"fill\": {\n if (!value) return { error: \"fill action requires --value\" };\n const result = await chrome.tabs.sendMessage(tabId, {\n type: \"FORM_INPUT\",\n ref,\n value,\n }, { frameId });\n return result.error ? result : { success: true, action: \"fill\", ref, value };\n }\n case \"hover\": {\n const coords = await chrome.tabs.sendMessage(tabId, {\n type: \"GET_ELEMENT_COORDINATES\",\n ref,\n }, { frameId });\n if (coords.error) return coords;\n await cdp.hover(tabId, coords.x, coords.y);\n return { success: true, action: \"hover\", ref };\n }\n case \"text\": {\n const textResult = await chrome.tabs.sendMessage(tabId, {\n type: \"GET_ELEMENT_TEXT\",\n ref,\n }, { frameId });\n return textResult;\n }\n default:\n return { error: `Unknown action: ${action}. Use click|fill|hover|text` };\n }\n}\n\nchrome.runtime.onMessage.addListener((message, sender, sendResponse) => {\n handleMessage(message, sender)\n .then(sendResponse)\n .catch((err) => sendResponse({ error: err.message }));\n return true;\n});\n\nexport async function handleMessage(\n message: any,\n sender: chrome.runtime.MessageSender\n): Promise<any> {\n const tabId = message.tabId;\n\n switch (message.type) {\n case \"GET_CURRENT_TAB_ID\": {\n const [tab] = await chrome.tabs.query({ active: true, currentWindow: true });\n return { tabId: tab?.id };\n }\n\n case \"EXECUTE_SCREENSHOT\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n \n try {\n await chrome.tabs.sendMessage(tabId, { type: \"HIDE_FOR_TOOL_USE\" });\n } catch (e) {}\n await new Promise(resolve => setTimeout(resolve, 50));\n \n try {\n let result: { base64: string; width: number; height: number };\n let scaleInfo = { scaleX: 1, scaleY: 1 };\n let usedFallback = false;\n \n if (message.fullpage) {\n result = await captureFullPage(tabId, message.maxHeight || 4000);\n try {\n const viewport = await cdp.getViewportSize(tabId);\n const dpr = result.width / viewport.width;\n scaleInfo = { scaleX: dpr, scaleY: dpr };\n } catch {}\n } else {\n try {\n const rawResult = await cdp.captureScreenshot(tabId);\n result = rawResult;\n try {\n const viewport = await cdp.getViewportSize(tabId);\n scaleInfo = {\n scaleX: rawResult.width / viewport.width,\n scaleY: rawResult.height / viewport.height,\n };\n } catch {}\n } catch (cdpError) {\n const tab = await chrome.tabs.get(tabId);\n if (!tab.windowId) throw cdpError;\n const dataUrl = await chrome.tabs.captureVisibleTab(tab.windowId, { format: \"png\" });\n const base64 = dataUrl.replace(/^data:image\\/png;base64,/, \"\");\n const binaryString = atob(base64);\n const bytes = new Uint8Array(binaryString.length);\n for (let i = 0; i < binaryString.length; i++) {\n bytes[i] = binaryString.charCodeAt(i);\n }\n const blob = new Blob([bytes], { type: \"image/png\" });\n const bitmap = await createImageBitmap(blob);\n result = { base64, width: bitmap.width, height: bitmap.height };\n bitmap.close();\n usedFallback = true;\n }\n }\n \n if (message.annotate && !usedFallback) {\n try {\n const treeResult = await chrome.tabs.sendMessage(tabId, {\n type: \"GET_ELEMENT_BOUNDS_FOR_ANNOTATION\",\n }, { frameId: 0 });\n \n if (treeResult?.elements && treeResult.elements.length > 0) {\n result = await annotateScreenshot(result, treeResult.elements, scaleInfo);\n }\n } catch {}\n }\n \n const screenshotId = generateScreenshotId();\n cacheScreenshot(screenshotId, result);\n return { ...result, screenshotId };\n } finally {\n try {\n await chrome.tabs.sendMessage(tabId, { type: \"SHOW_AFTER_TOOL_USE\" });\n } catch (e) {}\n }\n }\n\n case \"EXECUTE_CLICK\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const mods = message.modifiers ? cdp.parseModifiers(message.modifiers) : 0;\n await cdp.click(tabId, message.x, message.y, \"left\", 1, mods);\n return { success: true };\n }\n\n case \"EXECUTE_RIGHT_CLICK\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const mods = message.modifiers ? cdp.parseModifiers(message.modifiers) : 0;\n await cdp.rightClick(tabId, message.x, message.y, mods);\n return { success: true };\n }\n\n case \"EXECUTE_DOUBLE_CLICK\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const mods = message.modifiers ? cdp.parseModifiers(message.modifiers) : 0;\n await cdp.doubleClick(tabId, message.x, message.y, mods);\n return { success: true };\n }\n\n case \"EXECUTE_TRIPLE_CLICK\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const mods = message.modifiers ? cdp.parseModifiers(message.modifiers) : 0;\n await cdp.tripleClick(tabId, message.x, message.y, mods);\n return { success: true };\n }\n\n case \"EXECUTE_DRAG\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const mods = message.modifiers ? cdp.parseModifiers(message.modifiers) : 0;\n await cdp.drag(tabId, message.startX, message.startY, message.endX, message.endY, mods);\n return { success: true };\n }\n\n case \"EXECUTE_HOVER\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n await cdp.hover(tabId, message.x, message.y);\n return { success: true };\n }\n\n case \"EXECUTE_TYPE\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (message.text === undefined || message.text === null) throw new Error(\"No text provided\");\n await cdp.type(tabId, message.text);\n return { success: true };\n }\n\n case \"TYPE_SUBMIT\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (!message.text) throw new Error(\"No text provided\");\n await cdp.type(tabId, message.text);\n await cdp.pressKey(tabId, message.submitKey || \"Enter\");\n return { success: true };\n }\n\n case \"CLICK_TYPE\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (!message.text) throw new Error(\"No text provided\");\n const clickTypeFrameId = getFrameIdForTab(tabId);\n let clicked = false;\n if (message.ref) {\n try {\n const result = await chrome.tabs.sendMessage(tabId, { type: \"CLICK_ELEMENT\", ref: message.ref, button: \"left\" }, { frameId: clickTypeFrameId });\n if (!result.error) clicked = true;\n } catch {}\n }\n if (!clicked && message.coordinate) {\n await cdp.click(tabId, message.coordinate[0], message.coordinate[1], \"left\", 1, 0);\n clicked = true;\n }\n if (!clicked) {\n const result = await cdp.evaluateScript(tabId, `(() => {\n const el = document.querySelector('textarea, input[type=\"text\"], input[type=\"search\"], input:not([type]), [contenteditable=\"true\"]');\n if (!el) return null;\n const r = el.getBoundingClientRect();\n return { x: r.left + r.width/2, y: r.top + r.height/2 };\n })()`);\n if (result.result?.value) {\n await cdp.click(tabId, result.result.value.x, result.result.value.y, \"left\", 1, 0);\n clicked = true;\n }\n }\n if (!clicked) return { error: \"Could not find input element\" };\n await cdp.type(tabId, message.text);\n return { success: true };\n }\n\n case \"CLICK_TYPE_SUBMIT\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (!message.text) throw new Error(\"No text provided\");\n const clickTypeSubmitFrameId = getFrameIdForTab(tabId);\n let clicked = false;\n if (message.ref) {\n try {\n const result = await chrome.tabs.sendMessage(tabId, { type: \"CLICK_ELEMENT\", ref: message.ref, button: \"left\" }, { frameId: clickTypeSubmitFrameId });\n if (!result.error) clicked = true;\n } catch {}\n }\n if (!clicked && message.coordinate) {\n await cdp.click(tabId, message.coordinate[0], message.coordinate[1], \"left\", 1, 0);\n clicked = true;\n }\n if (!clicked) {\n const result = await cdp.evaluateScript(tabId, `(() => {\n const el = document.querySelector('textarea, input[type=\"text\"], input[type=\"search\"], input:not([type]), [contenteditable=\"true\"]');\n if (!el) return null;\n const r = el.getBoundingClientRect();\n return { x: r.left + r.width/2, y: r.top + r.height/2 };\n })()`);\n if (result.result?.value) {\n await cdp.click(tabId, result.result.value.x, result.result.value.y, \"left\", 1, 0);\n clicked = true;\n }\n }\n if (!clicked) return { error: \"Could not find input element\" };\n await cdp.type(tabId, message.text);\n await cdp.pressKey(tabId, message.submitKey || \"Enter\");\n return { success: true };\n }\n\n case \"FIND_AND_TYPE\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (!message.text) throw new Error(\"No text provided\");\n const findResult = await cdp.evaluateScript(tabId, `(() => {\n const selectors = [\n 'textarea:not([readonly]):not([disabled])',\n 'input[type=\"text\"]:not([readonly]):not([disabled])',\n 'input[type=\"search\"]:not([readonly]):not([disabled])',\n 'input:not([type]):not([readonly]):not([disabled])',\n '[contenteditable=\"true\"]',\n '[role=\"textbox\"]'\n ];\n for (const sel of selectors) {\n const el = document.querySelector(sel);\n if (el) {\n const r = el.getBoundingClientRect();\n if (r.width > 0 && r.height > 0) {\n el.focus();\n return { x: r.left + r.width/2, y: r.top + r.height/2, found: true };\n }\n }\n }\n return { found: false };\n })()`);\n const coords = findResult.result?.value;\n if (!coords?.found) return { error: \"No input field found on page\" };\n await cdp.click(tabId, coords.x, coords.y, \"left\", 1, 0);\n await cdp.type(tabId, message.text);\n if (message.submit) {\n await cdp.pressKey(tabId, message.submitKey || \"Enter\");\n }\n return { success: true, coordinates: { x: coords.x, y: coords.y } };\n }\n\n case \"AUTOCOMPLETE_SELECT\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (!message.text) throw new Error(\"No text provided\");\n const autocompleteFrameId = getFrameIdForTab(tabId);\n let clicked = false;\n if (message.ref) {\n try {\n const result = await chrome.tabs.sendMessage(tabId, { type: \"CLICK_ELEMENT\", ref: message.ref, button: \"left\" }, { frameId: autocompleteFrameId });\n if (!result.error) clicked = true;\n } catch {}\n }\n if (!clicked && message.coordinate) {\n await cdp.click(tabId, message.coordinate[0], message.coordinate[1], \"left\", 1, 0);\n clicked = true;\n }\n if (!clicked) return { error: \"ref or coordinate required\" };\n await new Promise(r => setTimeout(r, 100));\n await cdp.type(tabId, message.text);\n const waitMs = message.waitMs || 500;\n await new Promise(r => setTimeout(r, waitMs));\n if (message.index && message.index > 0) {\n for (let i = 0; i < message.index; i++) {\n await cdp.pressKey(tabId, \"ArrowDown\");\n await new Promise(r => setTimeout(r, 50));\n }\n }\n await cdp.pressKey(tabId, \"Enter\");\n return { success: true };\n }\n\n case \"SET_INPUT_VALUE\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (message.value === undefined) throw new Error(\"No value provided\");\n const selector = message.selector;\n const ref = message.ref;\n if (!selector && !ref) throw new Error(\"selector or ref required\");\n \n const script = ref \n ? `(() => {\n const el = document.querySelector('[data-pi-ref=\"${ref}\"]') || \n [...document.querySelectorAll('*')].find(e => e.getAttribute?.('data-ref') === '${ref}');\n if (!el) return { error: 'Element not found' };\n el.focus();\n const isContentEditable = el.isContentEditable || el.getAttribute('contenteditable') === 'true';\n const target = isContentEditable ? (el.querySelector('p') || el) : el;\n if (isContentEditable) {\n target.textContent = ${JSON.stringify(message.value)};\n } else {\n el.value = ${JSON.stringify(message.value)};\n }\n el.dispatchEvent(new Event('input', { bubbles: true }));\n el.dispatchEvent(new Event('change', { bubbles: true }));\n return { success: true, contentEditable: isContentEditable };\n })()`\n : `(() => {\n const el = document.querySelector(${JSON.stringify(selector)});\n if (!el) return { error: 'Element not found: ' + ${JSON.stringify(selector)} };\n el.focus();\n const isContentEditable = el.isContentEditable || el.getAttribute('contenteditable') === 'true';\n const target = isContentEditable ? (el.querySelector('p') || el) : el;\n if (isContentEditable) {\n target.textContent = ${JSON.stringify(message.value)};\n } else {\n el.value = ${JSON.stringify(message.value)};\n }\n el.dispatchEvent(new Event('input', { bubbles: true }));\n el.dispatchEvent(new Event('change', { bubbles: true }));\n return { success: true, contentEditable: isContentEditable };\n })()`;\n \n const result = await cdp.evaluateScript(tabId, script);\n return result.result?.value || { error: \"Script failed\" };\n }\n\n case \"SMART_TYPE\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const { selector, text, clear = true, submit = false } = message;\n if (!selector) throw new Error(\"selector required\");\n if (text === undefined) throw new Error(\"text required\");\n \n const script = `(() => {\n const el = document.querySelector(${JSON.stringify(selector)});\n if (!el) return { error: 'Element not found: ' + ${JSON.stringify(selector)} };\n \n const isContentEditable = el.isContentEditable || \n el.getAttribute('contenteditable') === 'true';\n const hasContentEditableChild = el.querySelector('[contenteditable=\"true\"]');\n \n const target = hasContentEditableChild || el;\n const useContentEditable = isContentEditable || !!hasContentEditableChild;\n \n target.focus();\n \n if (${clear}) {\n if (useContentEditable) {\n target.textContent = '';\n } else {\n target.value = '';\n }\n }\n \n if (useContentEditable) {\n target.textContent = ${JSON.stringify(text)};\n } else {\n target.value = ${JSON.stringify(text)};\n }\n \n target.dispatchEvent(new Event('input', { bubbles: true }));\n target.dispatchEvent(new Event('change', { bubbles: true }));\n \n if (${submit}) {\n const form = el.closest('form');\n const submitBtn = document.querySelector('button[type=\"submit\"], button[data-testid*=\"send\"], button[aria-label*=\"Send\"]');\n if (submitBtn) {\n submitBtn.click();\n } else if (form) {\n form.dispatchEvent(new Event('submit', { bubbles: true }));\n } else {\n target.dispatchEvent(new KeyboardEvent('keydown', { key: 'Enter', code: 'Enter', keyCode: 13, bubbles: true }));\n }\n }\n \n return { success: true, contentEditable: useContentEditable };\n })()`;\n \n const result = await cdp.evaluateScript(tabId, script);\n return result.result?.value || { error: \"Script failed\" };\n }\n\n case \"CLOSE_DIALOGS\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const maxAttempts = message.maxAttempts || 3;\n for (let i = 0; i < maxAttempts; i++) {\n await cdp.pressKey(tabId, \"Escape\");\n await new Promise(r => setTimeout(r, 100));\n }\n return { success: true };\n }\n\n case \"PAGE_STATE\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const stateScript = `(() => {\n const hasModal = !!(\n document.querySelector('[role=\"dialog\"]') ||\n document.querySelector('[role=\"alertdialog\"]') ||\n document.querySelector('.modal:not([hidden])') ||\n document.querySelector('[aria-modal=\"true\"]') ||\n document.querySelector('.MuiModal-root') ||\n document.querySelector('.MuiDialog-root')\n );\n const hasDropdown = !!(\n document.querySelector('[role=\"listbox\"]') ||\n document.querySelector('[role=\"menu\"]:not([hidden])') ||\n document.querySelector('.dropdown-menu.show') ||\n document.querySelector('[aria-expanded=\"true\"]')\n );\n const hasDatePicker = !!(\n document.querySelector('[role=\"grid\"][aria-label*=\"calendar\" i]') ||\n document.querySelector('.react-datepicker') ||\n document.querySelector('.flatpickr-calendar.open') ||\n document.querySelector('[class*=\"DatePicker\"]')\n );\n const focusedEl = document.activeElement;\n const focusedTag = focusedEl?.tagName?.toLowerCase();\n const focusedType = focusedEl?.getAttribute?.('type');\n return {\n hasModal,\n hasDropdown,\n hasDatePicker,\n hasOverlay: hasModal || hasDropdown || hasDatePicker,\n focusedElement: focusedTag ? { tag: focusedTag, type: focusedType } : null,\n url: location.href,\n title: document.title\n };\n })()`;\n const stateResult = await cdp.evaluateScript(tabId, stateScript);\n return stateResult.result?.value || { error: \"Failed to get page state\" };\n }\n\n case \"EXECUTE_SCROLL\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const deltaX = message.deltaX || 0;\n const deltaY = message.deltaY || 0;\n \n try {\n const viewport = await cdp.getViewportSize(tabId);\n const x = message.x ?? viewport.width / 2;\n const y = message.y ?? viewport.height / 2;\n await cdp.scroll(tabId, x, y, deltaX, deltaY);\n } catch {\n try {\n const scrollFallback = (dx: number, dy: number) => {\n window.scrollBy(dx, dy);\n return { scrollX: window.scrollX, scrollY: window.scrollY };\n };\n await chrome.scripting.executeScript({\n target: { tabId },\n func: scrollFallback,\n args: [deltaX, deltaY],\n });\n } catch {\n return { error: \"Cannot scroll on this page (restricted)\" };\n }\n }\n return { success: true };\n }\n\n case \"EXECUTE_KEY\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const key = message.key;\n if (!key) throw new Error(\"No key provided\");\n if (key.includes(\"+\")) {\n await cdp.pressKeyChord(tabId, key);\n } else {\n await cdp.pressKey(tabId, key);\n }\n return { success: true };\n }\n\n case \"EXECUTE_NAVIGATE\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (!message.url) throw new Error(\"No url provided\");\n \n const navigationPromise = new Promise<void>((resolve) => {\n navigationResolvers.set(tabId, resolve);\n setTimeout(() => {\n if (navigationResolvers.has(tabId)) {\n navigationResolvers.delete(tabId);\n resolve();\n }\n }, 30000);\n });\n \n await chrome.tabs.update(tabId, { url: message.url });\n await navigationPromise;\n \n await new Promise(resolve => setTimeout(resolve, 500));\n \n return { success: true };\n }\n\n case \"GET_VIEWPORT_SIZE\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n return await cdp.getViewportSize(tabId);\n }\n\n case \"READ_PAGE\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const readFrameId = getFrameIdForTab(tabId);\n try {\n await chrome.tabs.sendMessage(tabId, { type: \"HIDE_FOR_TOOL_USE\" }, { frameId: 0 });\n } catch (e) {}\n await new Promise(resolve => setTimeout(resolve, 50));\n \n let result;\n try {\n result = await chrome.tabs.sendMessage(tabId, {\n type: \"GENERATE_ACCESSIBILITY_TREE\",\n options: message.options || {},\n }, { frameId: readFrameId });\n } catch (err) {\n return { \n error: \"Content script not loaded. Try refreshing the page.\",\n pageContent: \"\",\n viewport: { width: 0, height: 0 }\n };\n } finally {\n try {\n await chrome.tabs.sendMessage(tabId, { type: \"SHOW_AFTER_TOOL_USE\" });\n } catch (e) {}\n }\n \n // Include visible text content if requested\n if (message.options?.includeText) {\n try {\n const textResult = await chrome.tabs.sendMessage(tabId, { type: \"GET_PAGE_TEXT\" }, { frameId: readFrameId });\n if (textResult?.text) {\n result.text = textResult.text;\n }\n } catch (err) {\n // Ignore text extraction errors\n }\n }\n \n if (message.options?.includeScreenshot) {\n try {\n const screenshot = await cdp.captureScreenshot(tabId);\n return { ...result, screenshot };\n } catch (err) {\n return { ...result, screenshotError: \"Failed to capture screenshot\" };\n }\n }\n return result;\n }\n\n case \"GET_ELEMENT_COORDINATES\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n try {\n return await chrome.tabs.sendMessage(tabId, {\n type: \"GET_ELEMENT_COORDINATES\",\n ref: message.ref,\n }, { frameId: getFrameIdForTab(tabId) });\n } catch (err) {\n return { error: \"Content script not loaded. Try refreshing the page.\" };\n }\n }\n\n case \"FORM_INPUT\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n try {\n return await chrome.tabs.sendMessage(tabId, {\n type: \"FORM_INPUT\",\n ref: message.ref,\n value: message.value,\n }, { frameId: getFrameIdForTab(tabId) });\n } catch (err) {\n return { error: \"Content script not loaded. Try refreshing the page.\" };\n }\n }\n\n case \"EVAL_IN_PAGE\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (!message.code) throw new Error(\"No code provided\");\n try {\n return await chrome.tabs.sendMessage(tabId, {\n type: \"EVAL_IN_PAGE\",\n code: message.code,\n }, { frameId: getFrameIdForTab(tabId) });\n } catch (err) {\n return { error: \"Content script not loaded. Try refreshing the page.\" };\n }\n }\n\n case \"SCROLL_TO_ELEMENT\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n try {\n return await chrome.tabs.sendMessage(tabId, {\n type: \"SCROLL_TO_ELEMENT\",\n ref: message.ref,\n }, { frameId: getFrameIdForTab(tabId) });\n } catch (err) {\n return { error: \"Content script not loaded. Try refreshing the page.\" };\n }\n }\n\n case \"SCROLL_TO_POSITION\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const position = message.position;\n if (position === undefined) throw new Error(\"position required (\\\"top\\\", \\\"bottom\\\", or number)\");\n const selector = message.selector;\n \n const scrollScript = (pos: string | number, sel: string | null) => {\n const findScrollable = (): Element => {\n const candidates = [...document.querySelectorAll(\"*\")].filter(el => \n el.scrollHeight > el.clientHeight && el.clientHeight > 200\n ).sort((a,b) => b.scrollHeight - a.scrollHeight);\n return candidates[0] || document.documentElement;\n };\n \n const container = sel ? document.querySelector(sel) || findScrollable() : findScrollable();\n if (!container) return { error: \"No scrollable container found\" };\n \n if (pos === \"bottom\") {\n container.scrollTop = container.scrollHeight;\n } else if (pos === \"top\") {\n container.scrollTop = 0;\n } else if (typeof pos === \"number\") {\n container.scrollTop = pos;\n }\n \n return { \n scrollTop: container.scrollTop,\n scrollHeight: container.scrollHeight,\n clientHeight: container.clientHeight,\n atBottom: container.scrollTop + container.clientHeight >= container.scrollHeight - 10,\n atTop: container.scrollTop < 10\n };\n };\n \n try {\n const script = `(${scrollScript.toString()})(${JSON.stringify(position)}, ${JSON.stringify(selector)})`;\n const result = await cdp.evaluateScript(tabId, script);\n return result.result?.value || { error: \"Script failed\" };\n } catch {\n try {\n const results = await chrome.scripting.executeScript({\n target: { tabId },\n func: scrollScript,\n args: [position, selector],\n });\n return results[0]?.result || { error: \"Script failed\" };\n } catch {\n return { error: \"Cannot scroll on this page (restricted)\" };\n }\n }\n }\n\n case \"GET_SCROLL_INFO\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const selector = message.selector;\n \n const scrollInfoScript = (sel: string | null) => {\n const findScrollable = (): Element => {\n const candidates = [...document.querySelectorAll(\"*\")].filter(el => \n el.scrollHeight > el.clientHeight && el.clientHeight > 200\n ).sort((a,b) => b.scrollHeight - a.scrollHeight);\n return candidates[0] || document.documentElement;\n };\n \n const container = sel ? document.querySelector(sel) || findScrollable() : findScrollable();\n if (!container) return { error: \"No scrollable container found\" };\n \n const maxScroll = container.scrollHeight - container.clientHeight;\n return { \n scrollTop: container.scrollTop,\n scrollHeight: container.scrollHeight,\n clientHeight: container.clientHeight,\n atBottom: container.scrollTop + container.clientHeight >= container.scrollHeight - 10,\n atTop: container.scrollTop < 10,\n scrollPercentage: maxScroll > 0 ? Math.round((container.scrollTop / maxScroll) * 100) : 100\n };\n };\n \n try {\n const script = `(${scrollInfoScript.toString()})(${JSON.stringify(selector)})`;\n const result = await cdp.evaluateScript(tabId, script);\n return result.result?.value || { error: \"Script failed\" };\n } catch {\n try {\n const results = await chrome.scripting.executeScript({\n target: { tabId },\n func: scrollInfoScript,\n args: [selector],\n });\n return results[0]?.result || { error: \"Script failed\" };\n } catch {\n return { error: \"Cannot get scroll info on this page (restricted)\" };\n }\n }\n }\n\n case \"GET_PAGE_TEXT\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n try {\n return await chrome.tabs.sendMessage(tabId, { type: \"GET_PAGE_TEXT\" }, { frameId: getFrameIdForTab(tabId) });\n } catch (err) {\n return { error: \"Content script not loaded. Try refreshing the page.\" };\n }\n }\n\n case \"LOCATE_ROLE\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (!message.role) throw new Error(\"role required\");\n const locateFrameId = getFrameIdForTab(tabId);\n \n try {\n const result = await chrome.tabs.sendMessage(tabId, {\n type: \"LOCATE_ROLE\",\n role: message.role,\n name: message.name,\n all: message.all,\n }, { frameId: locateFrameId });\n \n if (result.error) return result;\n \n // Perform action if specified\n if (message.action && result.ref) {\n return await performLocateAction(tabId, result.ref, message.action, message.value, cdp, locateFrameId);\n }\n \n return result;\n } catch (err) {\n return { error: \"Content script not loaded. Try refreshing the page.\" };\n }\n }\n\n case \"LOCATE_TEXT\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (!message.text) throw new Error(\"text required\");\n const textFrameId = getFrameIdForTab(tabId);\n \n try {\n const result = await chrome.tabs.sendMessage(tabId, {\n type: \"LOCATE_TEXT\",\n text: message.text,\n exact: message.exact,\n }, { frameId: textFrameId });\n \n if (result.error) return result;\n \n // Perform action if specified\n if (message.action && result.ref) {\n return await performLocateAction(tabId, result.ref, message.action, message.value, cdp, textFrameId);\n }\n \n return result;\n } catch (err) {\n return { error: \"Content script not loaded. Try refreshing the page.\" };\n }\n }\n\n case \"LOCATE_LABEL\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (!message.label) throw new Error(\"label required\");\n const labelFrameId = getFrameIdForTab(tabId);\n \n try {\n const result = await chrome.tabs.sendMessage(tabId, {\n type: \"LOCATE_LABEL\",\n label: message.label,\n }, { frameId: labelFrameId });\n \n if (result.error) return result;\n \n // Perform action if specified\n if (message.action && result.ref) {\n return await performLocateAction(tabId, result.ref, message.action, message.value, cdp, labelFrameId);\n }\n \n return result;\n } catch (err) {\n return { error: \"Content script not loaded. Try refreshing the page.\" };\n }\n }\n\n case \"GET_ELEMENT_STYLES\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (!message.selector) throw new Error(\"selector required\");\n const stylesFrameId = getFrameIdForTab(tabId);\n \n try {\n const result = await chrome.tabs.sendMessage(tabId, {\n type: \"GET_ELEMENT_STYLES\",\n selector: message.selector,\n }, { frameId: stylesFrameId });\n \n return result;\n } catch (err) {\n return { error: \"Content script not loaded. Try refreshing the page.\" };\n }\n }\n\n case \"SELECT_OPTION\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (!message.selector) throw new Error(\"selector required\");\n if (!message.values) throw new Error(\"values required\");\n const selectFrameId = getFrameIdForTab(tabId);\n \n try {\n const result = await chrome.tabs.sendMessage(tabId, {\n type: \"SELECT_OPTION\",\n selector: message.selector,\n values: message.values,\n by: message.by || \"value\",\n }, { frameId: selectFrameId });\n \n return result;\n } catch (err) {\n return { error: \"Content script not loaded. Try refreshing the page.\" };\n }\n }\n\n case \"SHOW_AGENT_INDICATORS\":\n case \"HIDE_AGENT_INDICATORS\":\n case \"SHOW_STATIC_INDICATOR\":\n case \"HIDE_STATIC_INDICATOR\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n try {\n return await chrome.tabs.sendMessage(tabId, { type: message.type });\n } catch (err) {\n return { error: \"Content script not loaded. Try refreshing the page.\" };\n }\n }\n\n case \"STOP_AGENT\": {\n const fromTabId = message.fromTabId;\n let targetTabId: number | undefined;\n \n if (fromTabId === \"CURRENT_TAB\" && sender.tab?.id) {\n targetTabId = sender.tab.id;\n } else if (typeof fromTabId === \"number\") {\n targetTabId = fromTabId;\n }\n \n if (targetTabId) {\n chrome.runtime.sendMessage({ type: \"STOP_AGENT\", targetTabId });\n }\n return { success: true };\n }\n\n case \"DISMISS_STATIC_INDICATOR\": {\n return { success: true };\n }\n\n case \"STATIC_INDICATOR_HEARTBEAT\": {\n return { success: true };\n }\n\n case \"CLICK_REF\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n try {\n const result = await chrome.tabs.sendMessage(tabId, {\n type: \"CLICK_ELEMENT\",\n ref: message.ref,\n button: message.button || \"left\",\n }, { frameId: getFrameIdForTab(tabId) });\n if (result.error) return { error: result.error };\n return { success: true };\n } catch (err) {\n return { error: \"Content script not loaded. Try refreshing the page.\" };\n }\n }\n\n case \"HOVER_REF\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n try {\n const coords = await chrome.tabs.sendMessage(tabId, {\n type: \"GET_ELEMENT_COORDINATES\",\n ref: message.ref,\n }, { frameId: getFrameIdForTab(tabId) });\n if (coords.error) return { error: coords.error };\n await cdp.hover(tabId, coords.x, coords.y);\n return { success: true };\n } catch (err) {\n return { error: \"Content script not loaded. Try refreshing the page.\" };\n }\n }\n\n case \"PING\": {\n return { success: true, status: \"connected\" };\n }\n\n case \"HEALTH_CHECK_URL\": {\n if (!message.url) throw new Error(\"No url provided\");\n const timeout = message.timeout || 30000;\n const expect = message.expect || 200;\n const startTime = Date.now();\n const pollInterval = 500;\n\n let lastError: string | null = null;\n while (Date.now() - startTime < timeout) {\n try {\n const response = await fetch(message.url, { method: \"GET\" });\n await response.text();\n if (response.status === expect) {\n return { success: true, status: response.status, time: Date.now() - startTime };\n }\n lastError = `Got status ${response.status}`;\n } catch (e) {\n lastError = e instanceof Error ? e.message : String(e);\n }\n await new Promise((r) => setTimeout(r, pollInterval));\n }\n return { \n error: `Timeout waiting for ${message.url} to return ${expect}`, \n lastError,\n time: Date.now() - startTime \n };\n }\n\n case \"SMOKE_TEST\": {\n const urls: string[] = message.urls || [];\n const captureScreenshots: boolean = message.savePath !== undefined;\n const failFast: boolean = message.failFast || false;\n \n if (urls.length === 0) {\n return { error: \"No URLs provided for smoke test\" };\n }\n\n const results: Array<{\n url: string;\n status: \"pass\" | \"fail\";\n time: number;\n errors: string[];\n screenshotBase64?: string;\n hostname?: string;\n }> = [];\n\n let pass = 0;\n let fail = 0;\n\n for (const url of urls) {\n const startTime = Date.now();\n const errors: string[] = [];\n let screenshotBase64: string | undefined;\n let hostname: string | undefined;\n let testTabId: number | undefined;\n\n try {\n hostname = new URL(url).hostname.replace(/[^a-zA-Z0-9.-]/g, \"_\");\n const testTab = await chrome.tabs.create({ url, active: false });\n if (!testTab.id) throw new Error(\"Failed to create tab\");\n testTabId = testTab.id;\n\n try {\n await cdp.enableConsoleTracking(testTabId);\n } catch (e) {}\n\n await new Promise<void>((resolve) => {\n const onComplete = (details: chrome.webNavigation.WebNavigationFramedCallbackDetails) => {\n if (details.tabId === testTabId && details.frameId === 0) {\n chrome.webNavigation.onCompleted.removeListener(onComplete);\n chrome.webNavigation.onErrorOccurred.removeListener(onError);\n resolve();\n }\n };\n const onError = (details: chrome.webNavigation.WebNavigationFramedErrorCallbackDetails) => {\n if (details.tabId === testTabId && details.frameId === 0) {\n chrome.webNavigation.onCompleted.removeListener(onComplete);\n chrome.webNavigation.onErrorOccurred.removeListener(onError);\n errors.push(`Navigation error: ${details.error}`);\n resolve();\n }\n };\n chrome.webNavigation.onCompleted.addListener(onComplete);\n chrome.webNavigation.onErrorOccurred.addListener(onError);\n setTimeout(() => {\n chrome.webNavigation.onCompleted.removeListener(onComplete);\n chrome.webNavigation.onErrorOccurred.removeListener(onError);\n errors.push(\"Navigation timeout (30s)\");\n resolve();\n }, 30000);\n });\n\n await new Promise(r => setTimeout(r, 2000));\n\n const consoleMessages = cdp.getConsoleMessages(testTabId, { onlyErrors: true, limit: 50 });\n for (const msg of consoleMessages) {\n errors.push(`[${msg.type}] ${msg.text}`);\n }\n\n if (captureScreenshots) {\n try {\n const screenshot = await cdp.captureScreenshot(testTabId);\n screenshotBase64 = screenshot.base64;\n } catch (e) {}\n }\n } catch (e) {\n errors.push(e instanceof Error ? e.message : String(e));\n } finally {\n if (testTabId) {\n try { await chrome.tabs.remove(testTabId); } catch {}\n }\n }\n\n const elapsed = Date.now() - startTime;\n const status = errors.length === 0 ? \"pass\" : \"fail\";\n if (status === \"pass\") pass++;\n else fail++;\n\n results.push({\n url,\n status,\n time: elapsed,\n errors,\n ...(screenshotBase64 && { screenshotBase64, hostname }),\n });\n\n if (failFast && status === \"fail\") {\n break;\n }\n }\n\n return {\n results,\n summary: { pass, fail, total: results.length },\n savePath: message.savePath,\n };\n }\n\n case \"WAIT_FOR_ELEMENT\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (!message.selector) throw new Error(\"No selector provided\");\n const waitFrameId = getFrameIdForTab(tabId);\n \n try {\n await chrome.tabs.sendMessage(tabId, { type: \"HIDE_FOR_TOOL_USE\" }, { frameId: 0 });\n } catch (e) {}\n await new Promise(resolve => setTimeout(resolve, 50));\n \n try {\n const result = await chrome.tabs.sendMessage(tabId, {\n type: \"WAIT_FOR_ELEMENT\",\n selector: message.selector,\n state: message.state || \"visible\",\n timeout: message.timeout || 20000,\n }, { frameId: waitFrameId });\n return result;\n } catch (err) {\n return { \n error: \"Content script not loaded. Try refreshing the page.\",\n pageContent: \"\",\n viewport: { width: 0, height: 0 }\n };\n } finally {\n try {\n await chrome.tabs.sendMessage(tabId, { type: \"SHOW_AFTER_TOOL_USE\" });\n } catch (e) {}\n }\n }\n\n case \"WAIT_FOR_URL\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (!message.pattern) throw new Error(\"No URL pattern provided\");\n \n try {\n await chrome.tabs.sendMessage(tabId, { type: \"HIDE_FOR_TOOL_USE\" }, { frameId: 0 });\n } catch (e) {}\n await new Promise(resolve => setTimeout(resolve, 50));\n \n try {\n const result = await chrome.tabs.sendMessage(tabId, {\n type: \"WAIT_FOR_URL\",\n pattern: message.pattern,\n timeout: message.timeout || 20000,\n }, { frameId: 0 });\n return result;\n } catch (err) {\n return { \n error: \"Content script not loaded. Try refreshing the page.\",\n pageContent: \"\",\n viewport: { width: 0, height: 0 }\n };\n } finally {\n try {\n await chrome.tabs.sendMessage(tabId, { type: \"SHOW_AFTER_TOOL_USE\" });\n } catch (e) {}\n }\n }\n\n case \"WAIT_FOR_NETWORK_IDLE\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n \n try {\n await chrome.tabs.sendMessage(tabId, { type: \"HIDE_FOR_TOOL_USE\" }, { frameId: 0 });\n } catch (e) {}\n await new Promise(resolve => setTimeout(resolve, 50));\n \n try {\n const result = await chrome.tabs.sendMessage(tabId, {\n type: \"WAIT_FOR_NETWORK_IDLE\",\n timeout: message.timeout || 10000,\n }, { frameId: 0 });\n return result;\n } catch (err) {\n return { \n error: \"Content script not loaded. Try refreshing the page.\",\n pageContent: \"\",\n viewport: { width: 0, height: 0 }\n };\n } finally {\n try {\n await chrome.tabs.sendMessage(tabId, { type: \"SHOW_AFTER_TOOL_USE\" });\n } catch (e) {}\n }\n }\n\n case \"WAIT_FOR_DOM_STABLE\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n \n try {\n await chrome.tabs.sendMessage(tabId, { type: \"HIDE_FOR_TOOL_USE\" }, { frameId: 0 });\n } catch (e) {}\n await new Promise(resolve => setTimeout(resolve, 50));\n \n try {\n const result = await chrome.tabs.sendMessage(tabId, {\n type: \"WAIT_FOR_DOM_STABLE\",\n stable: message.stable || 100,\n timeout: message.timeout || 5000,\n }, { frameId: 0 });\n return result;\n } catch (err) {\n return { \n error: \"Content script not loaded. Try refreshing the page.\",\n pageContent: \"\",\n viewport: { width: 0, height: 0 }\n };\n } finally {\n try {\n await chrome.tabs.sendMessage(tabId, { type: \"SHOW_AFTER_TOOL_USE\" }, { frameId: 0 });\n } catch (e) {}\n }\n }\n\n case \"DIALOG_ACCEPT\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const result = await cdp.handleDialog(tabId, true, message.text);\n return result;\n }\n\n case \"DIALOG_DISMISS\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const result = await cdp.handleDialog(tabId, false);\n return result;\n }\n\n case \"DIALOG_INFO\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const dialog = cdp.getDialogInfo(tabId);\n if (!dialog) {\n return { hasDialog: false };\n }\n return {\n hasDialog: true,\n type: dialog.type,\n message: dialog.message,\n defaultPrompt: dialog.defaultPrompt,\n };\n }\n\n case \"EMULATE_NETWORK\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (!message.preset) throw new Error(\"No preset provided\");\n const result = await cdp.emulateNetwork(tabId, message.preset);\n if (!result.success) throw new Error(result.error);\n return { success: true, preset: message.preset };\n }\n\n case \"EMULATE_CPU\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (message.rate === undefined) throw new Error(\"No rate provided\");\n const result = await cdp.emulateCPU(tabId, message.rate);\n if (!result.success) throw new Error(result.error);\n return { success: true, rate: message.rate };\n }\n\n case \"EMULATE_GEO\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (message.clear) {\n const result = await cdp.clearGeolocation(tabId);\n if (!result.success) throw new Error(result.error);\n return { success: true, cleared: true };\n }\n if (message.latitude === undefined || message.longitude === undefined) {\n throw new Error(\"Latitude and longitude required\");\n }\n const result = await cdp.emulateGeolocation(tabId, message.latitude, message.longitude, message.accuracy);\n if (!result.success) throw new Error(result.error);\n return { success: true, latitude: message.latitude, longitude: message.longitude };\n }\n\n case \"EMULATE_DEVICE_LIST\": {\n // Return list of available devices - handled in CLI\n const devices = [\n \"iPhone 12\", \"iPhone 13\", \"iPhone 14\", \"iPhone 14 Pro\", \"iPhone 14 Pro Max\", \"iPhone SE\",\n \"iPad\", \"iPad Pro\", \"iPad Mini\",\n \"Pixel 5\", \"Pixel 6\", \"Pixel 7\", \"Pixel 7 Pro\",\n \"Galaxy S21\", \"Galaxy S22\", \"Galaxy S23\", \"Galaxy Tab S7\",\n \"Nest Hub\", \"Nest Hub Max\"\n ];\n return { devices };\n }\n\n case \"EMULATE_DEVICE\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const deviceName = message.device;\n \n // Handle reset\n if (deviceName.toLowerCase() === \"reset\") {\n const result = await cdp.clearDeviceEmulation(tabId);\n if (!result.success) throw new Error(result.error);\n return { success: true, message: \"Device emulation reset\" };\n }\n \n // Device presets (synced with device-presets.cjs)\n const presets: Record<string, { width: number; height: number; deviceScaleFactor: number; mobile: boolean; touch: boolean; userAgent: string }> = {\n // Apple devices\n \"iPhone 12\": { width: 390, height: 844, deviceScaleFactor: 3, mobile: true, touch: true, userAgent: \"Mozilla/5.0 (iPhone; CPU iPhone OS 14_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0 Mobile/15E148 Safari/604.1\" },\n \"iPhone 13\": { width: 390, height: 844, deviceScaleFactor: 3, mobile: true, touch: true, userAgent: \"Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.0 Mobile/15E148 Safari/604.1\" },\n \"iPhone 14\": { width: 390, height: 844, deviceScaleFactor: 3, mobile: true, touch: true, userAgent: \"Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.0 Mobile/15E148 Safari/604.1\" },\n \"iPhone 14 Pro\": { width: 393, height: 852, deviceScaleFactor: 3, mobile: true, touch: true, userAgent: \"Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.0 Mobile/15E148 Safari/604.1\" },\n \"iPhone 14 Pro Max\": { width: 430, height: 932, deviceScaleFactor: 3, mobile: true, touch: true, userAgent: \"Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.0 Mobile/15E148 Safari/604.1\" },\n \"iPhone SE\": { width: 375, height: 667, deviceScaleFactor: 2, mobile: true, touch: true, userAgent: \"Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.0 Mobile/15E148 Safari/604.1\" },\n \"iPad\": { width: 768, height: 1024, deviceScaleFactor: 2, mobile: true, touch: true, userAgent: \"Mozilla/5.0 (iPad; CPU OS 14_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0 Mobile/15E148 Safari/604.1\" },\n \"iPad Pro\": { width: 1024, height: 1366, deviceScaleFactor: 2, mobile: true, touch: true, userAgent: \"Mozilla/5.0 (iPad; CPU OS 14_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0 Mobile/15E148 Safari/604.1\" },\n \"iPad Mini\": { width: 768, height: 1024, deviceScaleFactor: 2, mobile: true, touch: true, userAgent: \"Mozilla/5.0 (iPad; CPU OS 14_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0 Mobile/15E148 Safari/604.1\" },\n // Google devices\n \"Pixel 5\": { width: 393, height: 851, deviceScaleFactor: 2.75, mobile: true, touch: true, userAgent: \"Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.91 Mobile Safari/537.36\" },\n \"Pixel 6\": { width: 412, height: 915, deviceScaleFactor: 2.625, mobile: true, touch: true, userAgent: \"Mozilla/5.0 (Linux; Android 12; Pixel 6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Mobile Safari/537.36\" },\n \"Pixel 7\": { width: 412, height: 915, deviceScaleFactor: 2.625, mobile: true, touch: true, userAgent: \"Mozilla/5.0 (Linux; Android 13; Pixel 7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Mobile Safari/537.36\" },\n \"Pixel 7 Pro\": { width: 412, height: 892, deviceScaleFactor: 3.5, mobile: true, touch: true, userAgent: \"Mozilla/5.0 (Linux; Android 13; Pixel 7 Pro) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Mobile Safari/537.36\" },\n // Samsung devices\n \"Galaxy S21\": { width: 360, height: 800, deviceScaleFactor: 3, mobile: true, touch: true, userAgent: \"Mozilla/5.0 (Linux; Android 11; SM-G991B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.210 Mobile Safari/537.36\" },\n \"Galaxy S22\": { width: 360, height: 780, deviceScaleFactor: 3, mobile: true, touch: true, userAgent: \"Mozilla/5.0 (Linux; Android 12; SM-S901B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Mobile Safari/537.36\" },\n \"Galaxy S23\": { width: 360, height: 780, deviceScaleFactor: 3, mobile: true, touch: true, userAgent: \"Mozilla/5.0 (Linux; Android 13; SM-S911B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Mobile Safari/537.36\" },\n \"Galaxy Tab S7\": { width: 800, height: 1280, deviceScaleFactor: 2, mobile: true, touch: true, userAgent: \"Mozilla/5.0 (Linux; Android 10; SM-T870) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.91 Safari/537.36\" },\n // Other\n \"Nest Hub\": { width: 1024, height: 600, deviceScaleFactor: 2, mobile: false, touch: true, userAgent: \"Mozilla/5.0 (Linux; Android) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.109 Safari/537.36 CrKey/1.54.248666\" },\n \"Nest Hub Max\": { width: 1280, height: 800, deviceScaleFactor: 2, mobile: false, touch: true, userAgent: \"Mozilla/5.0 (Linux; Android) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.109 Safari/537.36 CrKey/1.54.248666\" },\n };\n \n // Find matching device (case-insensitive partial match, prefer longest match)\n type DevicePreset = { width: number; height: number; deviceScaleFactor: number; mobile: boolean; touch: boolean; userAgent: string };\n let device: DevicePreset | undefined = presets[deviceName];\n if (!device) {\n const lowerName = deviceName.toLowerCase();\n let bestMatch: { name: string; preset: DevicePreset } | null = null;\n \n for (const [name, preset] of Object.entries(presets)) {\n const presetLower = name.toLowerCase();\n const presetNoSpaces = presetLower.replace(/\\s+/g, \"\");\n \n // Check if it's a match\n if (presetLower.includes(lowerName) || lowerName.includes(presetNoSpaces)) {\n // Prefer longer matches (more specific devices)\n if (!bestMatch || name.length > bestMatch.name.length) {\n bestMatch = { name, preset };\n }\n }\n }\n \n if (bestMatch) {\n device = bestMatch.preset;\n }\n }\n \n if (!device) {\n throw new Error(`Unknown device: ${deviceName}. Use --list to see available devices.`);\n }\n \n const result = await cdp.emulateDevice(tabId, device);\n if (!result.success) throw new Error(result.error);\n return { success: true, device: deviceName };\n }\n\n case \"EMULATE_VIEWPORT\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (!message.width && !message.height) {\n throw new Error(\"--width or --height required\");\n }\n const result = await cdp.emulateViewport(tabId, {\n width: message.width,\n height: message.height,\n deviceScaleFactor: message.deviceScaleFactor,\n mobile: message.mobile,\n });\n if (!result.success) throw new Error(result.error);\n return { success: true, width: message.width, height: message.height };\n }\n\n case \"EMULATE_TOUCH\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const result = await cdp.emulateTouch(tabId, message.enabled);\n if (!result.success) throw new Error(result.error);\n return { success: true, enabled: message.enabled };\n }\n\n case \"FORM_FILL\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (!message.data) throw new Error(\"No data provided\");\n const response = await chrome.tabs.sendMessage(tabId, {\n type: \"FORM_FILL\",\n data: message.data,\n }, { frameId: getFrameIdForTab(tabId) });\n return response;\n }\n\n case \"PERF_START\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const result = await cdp.startPerformanceTrace(tabId, message.categories);\n if (!result.success) throw new Error(result.error);\n return { success: true, message: \"Performance tracing started\" };\n }\n\n case \"PERF_STOP\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const result = await cdp.stopPerformanceTrace(tabId);\n if (!result.success) throw new Error(result.error);\n return { success: true, metrics: result.metrics };\n }\n\n case \"PERF_METRICS\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const result = await cdp.getPerformanceMetrics(tabId);\n if (!result.success) throw new Error(result.error);\n return { success: true, metrics: result.metrics };\n }\n\n case \"UPLOAD_FILE\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (!message.ref) throw new Error(\"No ref provided\");\n if (!message.files || !message.files.length) throw new Error(\"No files provided\");\n const selectorResult = await chrome.tabs.sendMessage(tabId, {\n type: \"GET_FILE_INPUT_SELECTOR\",\n ref: message.ref,\n }, { frameId: getFrameIdForTab(tabId) });\n if (selectorResult.error) throw new Error(selectorResult.error);\n const setResult = await cdp.setFileInputBySelector(tabId, selectorResult.selector, message.files);\n if (!setResult.success) throw new Error(setResult.error);\n return { success: true, filesSet: message.files.length };\n }\n\n case \"WAIT_FOR_LOAD\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const result = await cdp.waitForLoad(tabId, message.timeout || 30000);\n if (!result.success) throw new Error(result.error);\n return { success: true, readyState: result.readyState };\n }\n\n case \"GET_FRAMES\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const result = await cdp.getFrames(tabId);\n if (!result.success) throw new Error(result.error);\n return { success: true, frames: result.frames };\n }\n\n case \"FRAME_SWITCH\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const { selector, name, index } = message;\n \n if (!selector && !name && index === undefined) {\n throw new Error(\"--selector, --name, or --index required\");\n }\n \n // Get all frames using Chrome's webNavigation API (gives us correct frameIds for messaging)\n const chromeFrames = await chrome.webNavigation.getAllFrames({ tabId });\n if (!chromeFrames || chromeFrames.length === 0) {\n throw new Error(\"No frames found in tab\");\n }\n \n // Filter to child frames only (frameId !== 0)\n const childFrames = chromeFrames.filter(f => f.frameId !== 0);\n \n if (childFrames.length === 0) {\n throw new Error(\"No iframes found on this page\");\n }\n \n let targetFrame: chrome.webNavigation.GetAllFrameResultDetails | null = null;\n \n if (index !== undefined) {\n if (index < 0 || index >= childFrames.length) {\n throw new Error(`Frame index ${index} out of range. Found ${childFrames.length} frame(s).`);\n }\n targetFrame = childFrames[index];\n } else if (name) {\n // Try to find frame by name using content script in each frame\n for (const frame of childFrames) {\n try {\n const result = await chrome.tabs.sendMessage(tabId, {\n type: \"GET_FRAME_NAME\",\n }, { frameId: frame.frameId });\n if (result?.name === name) {\n targetFrame = frame;\n break;\n }\n } catch {\n // Frame may not have content script loaded\n }\n }\n if (!targetFrame) {\n throw new Error(`Frame with name \"${name}\" not found`);\n }\n } else if (selector) {\n // Find frame by selector - ask main frame for iframe element's info\n try {\n const selectorResult = await chrome.tabs.sendMessage(tabId, {\n type: \"GET_FRAME_BY_SELECTOR\",\n selector,\n }, { frameId: 0 });\n \n if (selectorResult?.error) throw new Error(selectorResult.error);\n \n // Match by URL since that's what we can reliably get\n if (selectorResult?.url) {\n targetFrame = childFrames.find(f => f.url === selectorResult.url) || null;\n }\n \n // If no URL match and only one child frame, use it\n if (!targetFrame && childFrames.length === 1) {\n targetFrame = childFrames[0];\n }\n } catch (e) {\n throw new Error(`Could not find frame with selector \"${selector}\"`);\n }\n }\n \n if (!targetFrame) {\n throw new Error(\"Frame not found\");\n }\n \n // Store the Chrome extension frameId (integer) for this tab\n frameContexts.set(tabId, targetFrame.frameId);\n \n return { \n success: true, \n frameId: targetFrame.frameId,\n url: targetFrame.url,\n };\n }\n\n case \"FRAME_MAIN\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n \n // Clear frame context - go back to main frame (frameId 0)\n frameContexts.delete(tabId);\n \n return { success: true, message: \"Returned to main frame\" };\n }\n\n case \"EVALUATE_IN_FRAME\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (!message.frameId) throw new Error(\"No frameId provided\");\n if (!message.code) throw new Error(\"No code provided\");\n const result = await cdp.evaluateInFrame(tabId, message.frameId, message.code);\n if (!result.success) throw new Error(result.error);\n return { value: result.result };\n }\n\n case \"EXECUTE_JAVASCRIPT\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (!message.code) throw new Error(\"No code provided\");\n\n try {\n const piHelpersCode = `if(!window.piHelpers){const piHelpers={wait(ms){return new Promise(r=>setTimeout(r,ms))},async waitForSelector(sel,opts={}){const{state='visible',timeout=20000}=opts;const isVis=el=>el&&getComputedStyle(el).display!=='none'&&getComputedStyle(el).visibility!=='hidden'&&getComputedStyle(el).opacity!=='0'&&el.offsetWidth>0&&el.offsetHeight>0;const chk=()=>{const el=document.querySelector(sel);switch(state){case'attached':return el;case'detached':return el?null:document.body;case'hidden':return(!el||!isVis(el))?(el||document.body):null;default:return isVis(el)?el:null}};return new Promise((res,rej)=>{const r=chk();if(r){res(state==='detached'||state==='hidden'?null:r);return}const obs=new MutationObserver(()=>{const r=chk();if(r){obs.disconnect();clearTimeout(tid);res(state==='detached'||state==='hidden'?null:r)}});const tid=setTimeout(()=>{obs.disconnect();rej(new Error('Timeout'))},timeout);obs.observe(document.documentElement,{childList:true,subtree:true,attributes:true,attributeFilter:['style','class','hidden']})})},async waitForText(text,opts={}){const{selector,timeout=20000}=opts;const chk=()=>{const root=selector?document.querySelector(selector):document.body;if(!root)return null;const w=document.createTreeWalker(root,NodeFilter.SHOW_TEXT);while(w.nextNode())if(w.currentNode.textContent?.includes(text))return w.currentNode.parentElement;return null};return new Promise((res,rej)=>{const r=chk();if(r){res(r);return}const obs=new MutationObserver(()=>{const r=chk();if(r){obs.disconnect();clearTimeout(tid);res(r)}});const tid=setTimeout(()=>{obs.disconnect();rej(new Error('Timeout'))},timeout);obs.observe(document.documentElement,{childList:true,subtree:true,characterData:true})})},async waitForHidden(sel,t=20000){await piHelpers.waitForSelector(sel,{state:'hidden',timeout:t})},getByRole(role,opts={}){const{name}=opts;const roles={button:['button','input[type=button]','input[type=submit]','input[type=reset]'],link:['a[href]'],textbox:['input:not([type])','input[type=text]','input[type=email]','input[type=password]','textarea'],checkbox:['input[type=checkbox]'],radio:['input[type=radio]'],combobox:['select'],heading:['h1','h2','h3','h4','h5','h6']};const cands=[...document.querySelectorAll('[role='+role+']')];if(roles[role])roles[role].forEach(s=>cands.push(...document.querySelectorAll(s+':not([role])')));if(!name)return cands[0]||null;const n=name.toLowerCase().trim();for(const el of cands){const l=el.getAttribute('aria-label')?.toLowerCase().trim();const t=el.textContent?.toLowerCase().trim();if(l===n||t===n||l?.includes(n)||t?.includes(n))return el}return null}};window.__piHelpers=piHelpers;window.piHelpers=piHelpers}`;\n await cdp.evaluateScript(tabId, piHelpersCode);\n \n const escaped = message.code.replace(/`/g, \"\\\\`\").replace(/\\$/g, \"\\\\$\");\n const expression = `(async () => { 'use strict'; ${escaped} })()`;\n \n const result = await cdp.evaluateScript(tabId, expression);\n \n if (result.exceptionDetails) {\n const err = result.exceptionDetails.exception?.description || \n result.exceptionDetails.text || \n \"Script execution failed\";\n return { error: err };\n }\n \n const value = result.result?.value;\n const output = value === undefined ? \"undefined\" : JSON.stringify(value, null, 2);\n return { output: output?.substring(0, 50000) || \"undefined\" };\n } catch (err) {\n const msg = err instanceof Error ? err.message : \"Script execution failed\";\n if (msg.includes(\"Cannot access\") || msg.includes(\"Cannot attach\")) {\n return { error: \"Cannot execute JavaScript on this page (restricted URL)\" };\n }\n return { error: msg };\n }\n }\n\n case \"READ_CONSOLE_MESSAGES\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n\n try {\n await cdp.enableConsoleTracking(tabId);\n } catch (e) {}\n\n const messages = cdp.getConsoleMessages(tabId, {\n onlyErrors: message.onlyErrors,\n pattern: message.pattern,\n limit: message.limit || 100,\n });\n\n if (message.clear) {\n cdp.clearConsoleMessages(tabId);\n }\n\n return { messages };\n }\n\n case \"CLEAR_CONSOLE_MESSAGES\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n cdp.clearConsoleMessages(tabId);\n return { success: true };\n }\n\n case \"READ_NETWORK_REQUESTS\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n\n try {\n await cdp.enableNetworkTracking(tabId);\n } catch (e) {}\n\n // If full flag is passed, use getNetworkEntries for rich data\n if (message.full) {\n let entries = cdp.getNetworkEntries(tabId, {\n urlPattern: message.urlPattern,\n });\n \n // Apply filters\n if (message.method) {\n entries = entries.filter(e => e.method === message.method);\n }\n if (message.status) {\n entries = entries.filter(e => e.status === message.status);\n }\n if (message.contentType) {\n entries = entries.filter(e => e.type === message.contentType);\n }\n \n if (message.clear) {\n cdp.clearNetworkRequests(tabId);\n }\n \n // Return entries sliced to limit\n const limit = message.limit || 100;\n return { \n entries: entries.slice(0, limit),\n format: message.format,\n verbose: message.verbose\n };\n }\n\n let requests = cdp.getNetworkRequests(tabId, {\n urlPattern: message.urlPattern,\n limit: message.limit || 100,\n });\n\n // Apply filters\n if (message.method) {\n requests = requests.filter(r => r.method === message.method);\n }\n if (message.status) {\n requests = requests.filter(r => r.status === message.status);\n }\n if (message.contentType) {\n requests = requests.filter(r => r.type === message.contentType);\n }\n\n if (message.clear) {\n cdp.clearNetworkRequests(tabId);\n }\n\n return { \n requests,\n format: message.format,\n verbose: message.verbose\n };\n }\n\n case \"CLEAR_NETWORK_REQUESTS\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n cdp.clearNetworkRequests(tabId);\n return { success: true };\n }\n\n case \"GET_NETWORK_ENTRIES\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n \n try {\n await cdp.enableNetworkTracking(tabId);\n } catch (e) {}\n \n let entries = cdp.getNetworkEntries(tabId, {\n urlPattern: message.urlPattern,\n includeStatic: !message.excludeStatic,\n });\n \n // Apply additional filters\n if (message.origin) {\n entries = entries.filter(e => e.origin === message.origin);\n }\n if (message.method) {\n entries = entries.filter(e => e.method === message.method);\n }\n if (message.status) {\n entries = entries.filter(e => e.status === message.status);\n }\n if (message.type) {\n entries = entries.filter(e => e.type === message.type);\n }\n if (message.since) {\n entries = entries.filter(e => e.ts >= message.since);\n }\n if (message.hasBody !== undefined) {\n entries = entries.filter(e => message.hasBody ? (e.responseBodySize && e.responseBodySize > 0) : !e.responseBodySize);\n }\n if (message.last) {\n entries = entries.slice(-message.last);\n }\n \n if (message.clear) {\n cdp.clearNetworkRequests(tabId);\n }\n \n return { entries };\n }\n\n case \"GET_NETWORK_ENTRY\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (!message.requestId) throw new Error(\"No requestId provided\");\n \n // First try direct lookup by CDP requestId\n let entry = cdp.getNetworkEntry(tabId, message.requestId);\n \n // If not found, try lookup by entry.id (r_xxx format)\n if (!entry) {\n const entries = cdp.getNetworkEntries(tabId, {});\n entry = entries.find(e => e.id === message.requestId) || null;\n }\n \n // Also try lookup by _requestId for entries that use the generated id\n if (!entry) {\n const entries = cdp.getNetworkEntries(tabId, {});\n entry = entries.find(e => e._requestId === message.requestId) || null;\n }\n \n if (!entry) {\n return { error: `Entry not found: ${message.requestId}` };\n }\n return { entry };\n }\n\n case \"GET_RESPONSE_BODY\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (!message.requestId) throw new Error(\"No requestId provided\");\n \n // If requestId looks like entry.id format (r_xxx), look up the CDP requestId\n let cdpRequestId = message.requestId;\n if (message.requestId.startsWith('r_')) {\n const entries = cdp.getNetworkEntries(tabId, {});\n const entry = entries.find(e => e.id === message.requestId);\n if (entry) {\n cdpRequestId = entry._requestId;\n }\n }\n \n const result = await cdp.getResponseBody(tabId, cdpRequestId);\n return result;\n }\n\n case \"GET_NETWORK_ORIGINS\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n \n const entries = cdp.getNetworkEntries(tabId, {});\n const origins: Record<string, { count: number; lastSeen: number; size: number }> = {};\n \n for (const entry of entries) {\n if (!origins[entry.origin]) {\n origins[entry.origin] = { count: 0, lastSeen: 0, size: 0 };\n }\n origins[entry.origin].count++;\n origins[entry.origin].lastSeen = Math.max(origins[entry.origin].lastSeen, entry.ts);\n origins[entry.origin].size += (entry.responseBodySize || 0);\n }\n \n return { origins };\n }\n\n case \"GET_NETWORK_STATS\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n \n const entries = cdp.getNetworkEntries(tabId, {});\n const origins: Record<string, number> = {};\n const byMethod: Record<string, number> = {};\n const byStatus: Record<string, number> = {};\n let totalSize = 0;\n let oldestEntry = Infinity;\n let newestEntry = 0;\n \n for (const entry of entries) {\n // Count by origin\n if (!origins[entry.origin]) {\n origins[entry.origin] = 0;\n }\n origins[entry.origin]++;\n \n // Count by method\n const method = entry.method || 'GET';\n byMethod[method] = (byMethod[method] || 0) + 1;\n \n // Count by status\n if (entry.status) {\n const statusGroup = `${Math.floor(entry.status / 100)}xx`;\n byStatus[statusGroup] = (byStatus[statusGroup] || 0) + 1;\n }\n \n // Sum size\n totalSize += (entry.responseBodySize || 0);\n \n // Track time range\n if (entry.ts < oldestEntry) oldestEntry = entry.ts;\n if (entry.ts > newestEntry) newestEntry = entry.ts;\n }\n \n return {\n stats: {\n totalRequests: entries.length,\n totalSize,\n uniqueOrigins: Object.keys(origins).length,\n startTime: oldestEntry === Infinity ? null : oldestEntry,\n duration: (newestEntry && oldestEntry !== Infinity) ? newestEntry - oldestEntry : 0,\n byMethod,\n byStatus,\n }\n };\n }\n\n case \"RESIZE_WINDOW\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (!message.width || !message.height) throw new Error(\"width and height required\");\n\n const tab = await chrome.tabs.get(tabId);\n if (!tab.windowId) throw new Error(\"Tab has no window\");\n\n await chrome.windows.update(tab.windowId, {\n width: Math.floor(message.width),\n height: Math.floor(message.height),\n });\n\n return { success: true, width: message.width, height: message.height };\n }\n\n case \"TABS_CREATE\": {\n const activeTab = tabId ? await chrome.tabs.get(tabId) : null;\n\n const newTab = await chrome.tabs.create({\n url: message.url || \"about:blank\",\n active: false,\n });\n\n if (!newTab.id) throw new Error(\"Failed to create tab\");\n\n if (activeTab?.groupId && activeTab.groupId !== chrome.tabGroups.TAB_GROUP_ID_NONE) {\n await chrome.tabs.group({ tabIds: newTab.id, groupId: activeTab.groupId });\n }\n\n return { \n success: true, \n tabId: newTab.id, \n url: newTab.url || message.url || \"about:blank\" \n };\n }\n\n case \"UPLOAD_IMAGE\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (!message.screenshotId) throw new Error(\"screenshotId required\");\n if (!message.ref && !message.coordinate) throw new Error(\"ref or coordinate required\");\n\n const screenshot = getScreenshot(message.screenshotId);\n if (!screenshot) throw new Error(`Screenshot not found: ${message.screenshotId}`);\n\n try {\n const result = await chrome.tabs.sendMessage(tabId, {\n type: \"UPLOAD_IMAGE\",\n base64: screenshot.base64,\n ref: message.ref,\n coordinate: message.coordinate,\n filename: message.filename || \"screenshot.png\",\n }, { frameId: getFrameIdForTab(tabId) });\n\n return result;\n } catch (err) {\n return { error: \"Content script not loaded. Try refreshing the page.\" };\n }\n }\n\n case \"GET_TABS\": {\n const tabs = await chrome.tabs.query({});\n return {\n tabs: tabs.map((t) => ({ id: t.id, title: t.title, url: t.url })),\n };\n }\n\n case \"LIST_TABS\": {\n const queryOptions: chrome.tabs.QueryInfo = {};\n // Support filtering by window\n if (message.windowId) {\n queryOptions.windowId = message.windowId;\n }\n const tabs = await chrome.tabs.query(queryOptions);\n return {\n tabs: tabs.map((t) => ({\n id: t.id,\n title: t.title,\n url: t.url,\n active: t.active,\n windowId: t.windowId,\n })),\n };\n }\n\n case \"NEW_TAB\": {\n const urls = message.urls || (message.url ? [message.url] : [\"about:blank\"]);\n const createdTabs = [];\n for (let i = 0; i < urls.length; i++) {\n const createOptions: chrome.tabs.CreateProperties = {\n url: urls[i],\n active: i === 0,\n };\n // Support creating tab in specific window\n if (message.windowId) {\n createOptions.windowId = message.windowId;\n }\n const newTab = await chrome.tabs.create(createOptions);\n if (newTab.id) createdTabs.push({ tabId: newTab.id, url: urls[i] });\n }\n if (createdTabs.length === 1) {\n return { success: true, tabId: createdTabs[0].tabId, url: createdTabs[0].url };\n }\n return { success: true, tabs: createdTabs };\n }\n\n case \"SWITCH_TAB\": {\n const targetTabId = message.tabId;\n if (!targetTabId) throw new Error(\"No tabId provided\");\n const tab = await chrome.tabs.update(targetTabId, { active: true });\n if (tab.windowId) {\n await chrome.windows.update(tab.windowId, { focused: true });\n }\n return { success: true, tabId: targetTabId, url: tab.url, title: tab.title };\n }\n\n case \"CLOSE_TAB\": {\n const tabIds = message.tabIds || (message.tabId ? [message.tabId] : []);\n if (tabIds.length === 0) throw new Error(\"No tabId(s) provided\");\n await chrome.tabs.remove(tabIds);\n if (tabIds.length === 1) {\n return { success: true, tabId: tabIds[0] };\n }\n return { success: true, closed: tabIds };\n }\n\n case \"TABS_REGISTER\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (!message.name) throw new Error(\"No name provided\");\n tabNameRegistry.set(message.name, tabId);\n return { success: true, name: message.name, tabId };\n }\n\n case \"TABS_GET_BY_NAME\": {\n if (!message.name) throw new Error(\"No name provided\");\n const registeredTabId = tabNameRegistry.get(message.name);\n if (!registeredTabId) {\n return { error: `No tab registered with name \"${message.name}\"` };\n }\n try {\n const tab = await chrome.tabs.get(registeredTabId);\n return { tabId: registeredTabId, url: tab.url, title: tab.title };\n } catch (e) {\n tabNameRegistry.delete(message.name);\n return { error: `Tab \"${message.name}\" no longer exists` };\n }\n }\n\n case \"TABS_LIST_NAMED\": {\n const namedTabs: { name: string; tabId: number; url?: string; title?: string }[] = [];\n for (const [name, id] of tabNameRegistry) {\n try {\n const tab = await chrome.tabs.get(id);\n namedTabs.push({ name, tabId: id, url: tab.url, title: tab.title });\n } catch (e) {\n tabNameRegistry.delete(name);\n }\n }\n return { tabs: namedTabs };\n }\n\n case \"TABS_UNREGISTER\": {\n if (!message.name) throw new Error(\"No name provided\");\n const deleted = tabNameRegistry.delete(message.name);\n if (!deleted) {\n return { success: false, error: `No tab registered with name \"${message.name}\"` };\n }\n return { success: true };\n }\n\n case \"GET_AUTH\": {\n const { sendToNativeHost } = await import(\"../native/port-manager\");\n try {\n const result = await sendToNativeHost({ type: \"GET_AUTH\" });\n return result;\n } catch (err) {\n return { \n auth: null, \n hint: \"Native host not connected. Make sure surf native host is installed.\" \n };\n }\n }\n\n case \"NATIVE_API_REQUEST\": {\n const { sendToNativeHost } = await import(\"../native/port-manager\");\n try {\n await sendToNativeHost({\n type: \"API_REQUEST\",\n streamId: message.streamId,\n url: message.url,\n method: message.method,\n headers: message.headers,\n body: message.body,\n });\n return { sent: true };\n } catch (err) {\n return { error: err instanceof Error ? err.message : \"Unknown error\" };\n }\n }\n\n case \"STREAM_CONSOLE\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const streamId = message.streamId;\n\n try {\n await cdp.enableConsoleTracking(tabId);\n activeStreamTabs.set(streamId, tabId);\n\n cdp.subscribeToConsole(tabId, streamId, (event) => {\n postToNativeHost({\n type: \"STREAM_EVENT\",\n streamId,\n event: {\n type: \"console_event\",\n level: event.type === \"exception\" ? \"error\" : event.type,\n text: event.text,\n timestamp: event.timestamp,\n url: event.url,\n line: event.line,\n },\n });\n });\n\n return { success: true, streaming: true };\n } catch (err) {\n postToNativeHost({\n type: \"STREAM_ERROR\",\n streamId,\n error: err instanceof Error ? err.message : \"Failed to start console stream\",\n });\n return { error: err instanceof Error ? err.message : \"Failed to start console stream\" };\n }\n }\n\n case \"STREAM_NETWORK\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const streamId = message.streamId;\n\n try {\n await cdp.enableNetworkTracking(tabId);\n activeStreamTabs.set(streamId, tabId);\n\n cdp.subscribeToNetwork(tabId, streamId, (event) => {\n postToNativeHost({\n type: \"STREAM_EVENT\",\n streamId,\n event: {\n type: \"network_event\",\n method: event.method,\n url: event.url,\n status: event.status,\n duration: event.duration,\n timestamp: event.timestamp,\n },\n });\n });\n\n return { success: true, streaming: true };\n } catch (err) {\n postToNativeHost({\n type: \"STREAM_ERROR\",\n streamId,\n error: err instanceof Error ? err.message : \"Failed to start network stream\",\n });\n return { error: err instanceof Error ? err.message : \"Failed to start network stream\" };\n }\n }\n\n case \"STREAM_STOP\": {\n const streamId = message.streamId;\n const streamTabId = activeStreamTabs.get(streamId);\n \n if (streamTabId !== undefined) {\n cdp.unsubscribeFromConsole(streamTabId, streamId);\n cdp.unsubscribeFromNetwork(streamTabId, streamId);\n activeStreamTabs.delete(streamId);\n }\n\n return { success: true };\n }\n\n case \"SEARCH_PAGE\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (!message.term) throw new Error(\"Search term required\");\n try {\n const result = await chrome.tabs.sendMessage(tabId, {\n type: \"SEARCH_PAGE\",\n term: message.term,\n caseSensitive: message.caseSensitive || false,\n limit: message.limit || 10,\n }, { frameId: getFrameIdForTab(tabId) });\n return result;\n } catch {\n return { error: \"Content script not loaded. Try refreshing the page.\" };\n }\n }\n\n case \"TAB_GROUP_CREATE\": {\n const tabIds = [...(message.tabIds || [])];\n const name = message.name || \"Surf\";\n const validColors = ['grey', 'blue', 'red', 'yellow', 'green', 'pink', 'purple', 'cyan', 'orange'];\n const color = validColors.includes(message.color) ? message.color : 'blue';\n \n if (tabIds.length === 0 && tabId) {\n tabIds.push(tabId);\n }\n \n if (tabIds.length === 0) throw new Error(\"No tabs specified\");\n \n const existingGroups = await chrome.tabGroups.query({ title: name });\n let groupId: number;\n \n if (existingGroups.length > 0) {\n groupId = existingGroups[0].id;\n await chrome.tabs.group({ tabIds, groupId });\n } else {\n groupId = await chrome.tabs.group({ tabIds });\n await chrome.tabGroups.update(groupId, {\n title: name,\n color: color as chrome.tabGroups.ColorEnum,\n collapsed: false,\n });\n }\n \n return { success: true, groupId, name, tabIds };\n }\n\n case \"TAB_GROUP_REMOVE\": {\n const tabIds = [...(message.tabIds || [])];\n if (tabIds.length === 0 && tabId) {\n tabIds.push(tabId);\n }\n \n if (tabIds.length === 0) throw new Error(\"No tabs specified\");\n \n await chrome.tabs.ungroup(tabIds);\n return { success: true, ungrouped: tabIds };\n }\n\n case \"TAB_GROUPS_LIST\": {\n const groups = await chrome.tabGroups.query({});\n const result = [];\n \n for (const group of groups) {\n const tabs = await chrome.tabs.query({ groupId: group.id });\n result.push({\n id: group.id,\n name: group.title || \"(unnamed)\",\n color: group.color,\n collapsed: group.collapsed,\n tabs: tabs.map(t => ({ id: t.id, title: t.title, url: t.url })),\n });\n }\n \n return { groups: result };\n }\n\n case \"CLICK_SELECTOR\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const selector = message.selector;\n const index = message.index || 0;\n \n const script = `(() => {\n const elements = document.querySelectorAll(${JSON.stringify(selector)});\n if (elements.length === 0) return { error: \"No elements match selector\" };\n if (${index} >= elements.length) return { error: \"Index \" + ${index} + \" out of range (found \" + elements.length + \" elements)\" };\n \n const el = elements[${index}];\n const rect = el.getBoundingClientRect();\n return { \n x: rect.left + rect.width / 2, \n y: rect.top + rect.height / 2,\n count: elements.length\n };\n })()`;\n \n const result = await cdp.evaluateScript(tabId, script);\n const coords = result.result?.value;\n \n if (coords?.error) return { error: coords.error };\n if (!coords) return { error: \"Failed to get element coordinates\" };\n \n await cdp.click(tabId, coords.x, coords.y, \"left\", 1, 0);\n return { success: true, selector, index, matchCount: coords.count };\n }\n\n case \"COOKIE_LIST\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const tab = await chrome.tabs.get(tabId);\n const url = tab.url;\n if (!url) throw new Error(\"Tab has no URL\");\n const cookies = await chrome.cookies.getAll({ url });\n return { cookies };\n }\n\n case \"COOKIE_GET\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const tab = await chrome.tabs.get(tabId);\n const url = tab.url;\n if (!url) throw new Error(\"Tab has no URL\");\n if (!message.name) throw new Error(\"Cookie name required\");\n const cookie = await chrome.cookies.get({ url, name: message.name });\n if (!cookie) return { error: `Cookie \"${message.name}\" not found` };\n return { cookie };\n }\n\n case \"COOKIE_SET\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const tab = await chrome.tabs.get(tabId);\n const url = tab.url;\n if (!url) throw new Error(\"Tab has no URL\");\n if (!message.name) throw new Error(\"Cookie name required\");\n if (message.value === undefined) throw new Error(\"Cookie value required\");\n \n const cookieDetails: chrome.cookies.SetDetails = {\n url,\n name: message.name,\n value: message.value,\n };\n \n if (message.expires) {\n const expirationDate = new Date(message.expires).getTime() / 1000;\n if (isNaN(expirationDate)) {\n throw new Error(`Invalid expiration date: ${message.expires}`);\n }\n cookieDetails.expirationDate = expirationDate;\n }\n \n const result = await chrome.cookies.set(cookieDetails);\n return { success: true, cookie: result };\n }\n\n case \"COOKIE_CLEAR\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const tab = await chrome.tabs.get(tabId);\n const url = tab.url;\n if (!url) throw new Error(\"Tab has no URL\");\n if (!message.name) throw new Error(\"Cookie name required\");\n \n await chrome.cookies.remove({ url, name: message.name });\n return { success: true, cleared: message.name };\n }\n\n case \"COOKIE_CLEAR_ALL\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const tab = await chrome.tabs.get(tabId);\n const url = tab.url;\n if (!url) throw new Error(\"Tab has no URL\");\n \n const cookies = await chrome.cookies.getAll({ url });\n for (const cookie of cookies) {\n await chrome.cookies.remove({ url, name: cookie.name });\n }\n return { success: true, cleared: cookies.length };\n }\n\n case \"TAB_RELOAD\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n await chrome.tabs.reload(tabId, { bypassCache: message.hard || false });\n return { success: true };\n }\n\n case \"ZOOM_GET\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const zoom = await chrome.tabs.getZoom(tabId);\n return { zoom };\n }\n\n case \"ZOOM_SET\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const level = message.level;\n if (level < 0.25 || level > 5) throw new Error(\"Zoom level must be between 0.25 and 5\");\n await chrome.tabs.setZoom(tabId, level);\n return { success: true, zoom: level };\n }\n\n case \"ZOOM_RESET\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n await chrome.tabs.setZoom(tabId, 0);\n return { success: true, zoom: 1.0 };\n }\n\n case \"BOOKMARK_ADD\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const tab = await chrome.tabs.get(tabId);\n const createProps: { title: string; url?: string; parentId?: string } = {\n title: tab.title || \"Untitled\",\n url: tab.url,\n };\n if (message.folder) {\n const search = await chrome.bookmarks.search({ title: message.folder });\n const folder = search.find(b => !b.url);\n if (folder) {\n createProps.parentId = folder.id;\n }\n }\n const bookmark = await chrome.bookmarks.create(createProps);\n return { success: true, bookmark: { id: bookmark.id, title: bookmark.title, url: bookmark.url } };\n }\n\n case \"BOOKMARK_REMOVE\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const tab = await chrome.tabs.get(tabId);\n if (!tab.url) throw new Error(\"Tab has no URL\");\n const bookmarks = await chrome.bookmarks.search({ url: tab.url });\n if (bookmarks.length === 0) throw new Error(\"No bookmark found for this URL\");\n await chrome.bookmarks.remove(bookmarks[0].id);\n return { success: true };\n }\n\n case \"BOOKMARK_LIST\": {\n const limit = typeof message.limit === 'number' ? message.limit : 50;\n let bookmarks: chrome.bookmarks.BookmarkTreeNode[] = [];\n \n if (message.folder) {\n const search = await chrome.bookmarks.search({ title: message.folder });\n const folder = search.find(b => !b.url);\n if (folder) {\n const children = await chrome.bookmarks.getChildren(folder.id);\n bookmarks = children.filter(b => b.url).slice(0, limit);\n }\n } else {\n const recent = await chrome.bookmarks.getRecent(limit);\n bookmarks = recent;\n }\n \n return { \n bookmarks: bookmarks.map(b => ({ \n id: b.id, \n title: b.title, \n url: b.url,\n dateAdded: b.dateAdded\n }))\n };\n }\n\n case \"HISTORY_LIST\": {\n const limit = typeof message.limit === 'number' ? message.limit : 20;\n const items = await chrome.history.search({ \n text: \"\", \n maxResults: limit,\n startTime: 0 \n });\n return { \n history: items.map(h => ({ \n url: h.url, \n title: h.title, \n lastVisitTime: h.lastVisitTime,\n visitCount: h.visitCount\n }))\n };\n }\n\n case \"HISTORY_SEARCH\": {\n const query = message.query;\n const limit = typeof message.limit === 'number' ? message.limit : 20;\n const items = await chrome.history.search({ \n text: query, \n maxResults: limit,\n startTime: 0 \n });\n return { \n history: items.map(h => ({ \n url: h.url, \n title: h.title, \n lastVisitTime: h.lastVisitTime,\n visitCount: h.visitCount\n }))\n };\n }\n\n case \"GET_CHATGPT_COOKIES\": {\n const cookies = await chrome.cookies.getAll({ domain: \".chatgpt.com\" });\n const openaiCookies = await chrome.cookies.getAll({ domain: \".openai.com\" });\n return { cookies: [...cookies, ...openaiCookies] };\n }\n\n case \"CHATGPT_NEW_TAB\": {\n const tab = await chrome.tabs.create({\n url: \"https://chatgpt.com/\",\n active: true,\n });\n if (!tab.id) throw new Error(\"Failed to create tab\");\n const currentTab = await chrome.tabs.get(tab.id);\n if (currentTab.status !== \"complete\") {\n await new Promise<void>((resolve) => {\n const listener = (tabId: number, info: chrome.tabs.TabChangeInfo) => {\n if (tabId === tab.id && info.status === \"complete\") {\n chrome.tabs.onUpdated.removeListener(listener);\n resolve();\n }\n };\n chrome.tabs.onUpdated.addListener(listener);\n setTimeout(() => {\n chrome.tabs.onUpdated.removeListener(listener);\n resolve();\n }, 30000);\n });\n }\n await cdp.attach(tab.id);\n // Wait for JS runtime to be ready after CDP attach\n await waitForRuntimeReady(tab.id, 10000);\n return { tabId: tab.id };\n }\n\n case \"CHATGPT_CLOSE_TAB\": {\n const chatTabId = message.tabId;\n if (chatTabId) {\n try {\n await cdp.detach(chatTabId);\n } catch {}\n try {\n await chrome.tabs.remove(chatTabId);\n } catch {}\n }\n return { success: true };\n }\n\n case \"CHATGPT_CDP_COMMAND\": {\n const { method, params } = message;\n const result = await cdp.sendCommand(message.tabId, method, params || {});\n return result;\n }\n\n case \"CHATGPT_EVALUATE\": {\n const result = await cdp.evaluateScript(message.tabId, message.expression);\n return result;\n }\n\n case \"PERPLEXITY_NEW_TAB\": {\n const tab = await chrome.tabs.create({\n url: \"https://www.perplexity.ai/\",\n active: true,\n });\n if (!tab.id) throw new Error(\"Failed to create tab\");\n const currentTab = await chrome.tabs.get(tab.id);\n if (currentTab.status !== \"complete\") {\n await new Promise<void>((resolve) => {\n const listener = (tabId: number, info: chrome.tabs.TabChangeInfo) => {\n if (tabId === tab.id && info.status === \"complete\") {\n chrome.tabs.onUpdated.removeListener(listener);\n resolve();\n }\n };\n chrome.tabs.onUpdated.addListener(listener);\n setTimeout(() => {\n chrome.tabs.onUpdated.removeListener(listener);\n resolve();\n }, 30000);\n });\n }\n await cdp.attach(tab.id);\n // Wait for JS runtime to be ready after CDP attach\n await waitForRuntimeReady(tab.id, 10000);\n return { tabId: tab.id };\n }\n\n case \"PERPLEXITY_CLOSE_TAB\": {\n const pplxTabId = message.tabId;\n if (pplxTabId) {\n try {\n await cdp.detach(pplxTabId);\n } catch {}\n try {\n await chrome.tabs.remove(pplxTabId);\n } catch {}\n }\n return { success: true };\n }\n\n case \"PERPLEXITY_CDP_COMMAND\": {\n const { method, params } = message;\n const result = await cdp.sendCommand(message.tabId, method, params || {});\n return result;\n }\n\n case \"PERPLEXITY_EVALUATE\": {\n const result = await cdp.evaluateScript(message.tabId, message.expression);\n return result;\n }\n\n case \"GET_TWITTER_COOKIES\": {\n // Grok requires X.com cookies for authentication\n const domains = [\".x.com\", \".twitter.com\", \"x.com\", \"twitter.com\"];\n const allCookies: chrome.cookies.Cookie[] = [];\n \n for (const domain of domains) {\n try {\n const cookies = await chrome.cookies.getAll({ domain });\n allCookies.push(...cookies);\n } catch {}\n }\n \n // Also try by URL\n const urls = [\"https://x.com\", \"https://twitter.com\"];\n for (const url of urls) {\n try {\n const cookies = await chrome.cookies.getAll({ url });\n allCookies.push(...cookies);\n } catch {}\n }\n \n // Dedupe by name\n const seen = new Map<string, chrome.cookies.Cookie>();\n for (const cookie of allCookies) {\n const existing = seen.get(cookie.name);\n if (!existing || cookie.domain?.includes(\"x.com\")) {\n seen.set(cookie.name, cookie);\n }\n }\n \n return { cookies: Array.from(seen.values()) };\n }\n\n case \"GROK_NEW_TAB\": {\n const tab = await chrome.tabs.create({\n url: \"https://x.com/i/grok\",\n active: true,\n });\n if (!tab.id) throw new Error(\"Failed to create tab\");\n const currentTab = await chrome.tabs.get(tab.id);\n if (currentTab.status !== \"complete\") {\n await new Promise<void>((resolve) => {\n const listener = (tabId: number, info: chrome.tabs.TabChangeInfo) => {\n if (tabId === tab.id && info.status === \"complete\") {\n chrome.tabs.onUpdated.removeListener(listener);\n resolve();\n }\n };\n chrome.tabs.onUpdated.addListener(listener);\n setTimeout(() => {\n chrome.tabs.onUpdated.removeListener(listener);\n resolve();\n }, 30000);\n });\n }\n await cdp.attach(tab.id);\n // Wait for JS runtime to be ready after CDP attach\n await waitForRuntimeReady(tab.id, 10000);\n return { tabId: tab.id };\n }\n\n case \"GROK_CLOSE_TAB\": {\n const grokTabId = message.tabId;\n if (grokTabId) {\n try {\n await cdp.detach(grokTabId);\n } catch {}\n try {\n await chrome.tabs.remove(grokTabId);\n } catch {}\n }\n return { success: true };\n }\n\n case \"GROK_CDP_COMMAND\": {\n const { method, params } = message;\n const result = await cdp.sendCommand(message.tabId, method, params || {});\n return result;\n }\n\n case \"GROK_EVALUATE\": {\n const result = await cdp.evaluateScript(message.tabId, message.expression);\n return result;\n }\n\n case \"GEMINI_NEW_TAB\": {\n const tab = await chrome.tabs.create({\n url: \"https://gemini.google.com/app\",\n active: true,\n });\n if (!tab.id) throw new Error(\"Failed to create tab\");\n return { tabId: tab.id };\n }\n\n case \"GEMINI_CLOSE_TAB\": {\n const geminiTabId = message.tabId;\n if (geminiTabId) {\n try {\n await cdp.detach(geminiTabId);\n } catch {}\n try {\n await chrome.tabs.remove(geminiTabId);\n } catch {}\n }\n return { success: true };\n }\n\n case \"UPLOAD_FILE_TO_TAB\": {\n const { tabId: uploadTabId, filePaths } = message;\n if (!uploadTabId || !filePaths?.length) {\n throw new Error(\"UPLOAD_FILE_TO_TAB requires tabId and filePaths\");\n }\n await cdp.attach(uploadTabId);\n await cdp.sendCommand(uploadTabId, \"DOM.enable\", {});\n await cdp.sendCommand(uploadTabId, \"Page.setInterceptFileChooserDialog\", { enabled: true });\n\n let timeoutId: ReturnType<typeof setTimeout> | null = null;\n let handler: ((source: chrome.debugger.Debuggee, method: string, params: any) => void) | null = null;\n const cleanup = () => {\n if (timeoutId) { clearTimeout(timeoutId); timeoutId = null; }\n if (handler) { chrome.debugger.onEvent.removeListener(handler); handler = null; }\n };\n\n const attemptFileChooser = (attemptNum: number, timeoutMs: number): Promise<void> => {\n return new Promise<void>((resolve, reject) => {\n timeoutId = setTimeout(() => {\n cleanup();\n reject(new Error(`File chooser did not open within ${timeoutMs / 1000}s (attempt ${attemptNum})`));\n }, timeoutMs);\n handler = (source: chrome.debugger.Debuggee, method: string, params: any) => {\n if (source.tabId === uploadTabId && method === \"Page.fileChooserOpened\") {\n cleanup();\n cdp.sendCommand(uploadTabId, \"DOM.setFileInputFiles\", {\n files: filePaths,\n backendNodeId: params.backendNodeId,\n }).then(() => resolve()).catch(reject);\n }\n };\n chrome.debugger.onEvent.addListener(handler);\n });\n };\n\n const clickUploadSequence = async () => {\n // Close menu if already open\n await cdp.sendCommand(uploadTabId, \"Runtime.evaluate\", {\n expression: `document.querySelector('button[aria-label=\"Close upload file menu\"]')?.click()`,\n userGesture: true,\n });\n await new Promise(r => setTimeout(r, 300));\n\n // Open upload menu\n await cdp.sendCommand(uploadTabId, \"Runtime.evaluate\", {\n expression: `document.querySelector('button[aria-label=\"Open upload file menu\"]')?.click()`,\n userGesture: true,\n });\n await new Promise(r => setTimeout(r, 500));\n\n // Click \"Upload files\" button\n await cdp.sendCommand(uploadTabId, \"Runtime.evaluate\", {\n expression: `document.querySelector('[data-test-id=\"local-images-files-uploader-button\"]')?.click()`,\n userGesture: true,\n });\n };\n\n const maxAttempts = 3;\n const timeouts = [10000, 15000, 20000];\n let lastError: Error | null = null;\n\n try {\n for (let attempt = 1; attempt <= maxAttempts; attempt++) {\n try {\n const fileSetPromise = attemptFileChooser(attempt, timeouts[attempt - 1]);\n await clickUploadSequence();\n await fileSetPromise;\n return { success: true };\n } catch (err) {\n lastError = err as Error;\n cleanup();\n if (attempt < maxAttempts) {\n await new Promise(r => setTimeout(r, 1000));\n }\n }\n }\n throw new Error(`File upload failed after ${maxAttempts} attempts: ${lastError?.message}`);\n } finally {\n cleanup();\n try { await cdp.sendCommand(uploadTabId, \"Page.setInterceptFileChooserDialog\", { enabled: false }); } catch {}\n }\n }\n\n case \"GEMINI_FETCH_URL\": {\n const imageUrl = message.url;\n if (!imageUrl) throw new Error(\"No URL provided\");\n const resp = await fetch(imageUrl, { credentials: \"include\" });\n if (!resp.ok) throw new Error(`Fetch failed: ${resp.status}`);\n const blob = await resp.blob();\n const reader = new FileReader();\n const b64: string = await new Promise((resolve, reject) => {\n reader.onload = () => resolve((reader.result as string).split(\",\")[1]);\n reader.onerror = () => reject(new Error(\"FileReader failed\"));\n reader.readAsDataURL(blob);\n });\n return { b64, size: blob.size, type: blob.type };\n }\n\n case \"AISTUDIO_NEW_TAB\": {\n const url = message.url || \"https://aistudio.google.com/prompts/new_chat\";\n const tab = await chrome.tabs.create({ url, active: true });\n if (!tab.id) throw new Error(\"Failed to create tab\");\n const currentTab = await chrome.tabs.get(tab.id);\n if (currentTab.status !== \"complete\") {\n await new Promise<void>((resolve) => {\n const listener = (tabId: number, info: chrome.tabs.TabChangeInfo) => {\n if (tabId === tab.id && info.status === \"complete\") {\n chrome.tabs.onUpdated.removeListener(listener);\n resolve();\n }\n };\n chrome.tabs.onUpdated.addListener(listener);\n setTimeout(() => {\n chrome.tabs.onUpdated.removeListener(listener);\n resolve();\n }, 30000);\n });\n }\n await cdp.attach(tab.id);\n await waitForRuntimeReady(tab.id, 10000);\n return { tabId: tab.id };\n }\n\n case \"AISTUDIO_CLOSE_TAB\": {\n const aiStudioTabId = message.tabId;\n if (aiStudioTabId) {\n try { await cdp.detach(aiStudioTabId); } catch {}\n try { await chrome.tabs.remove(aiStudioTabId); } catch {}\n }\n return { success: true };\n }\n\n case \"AISTUDIO_CDP_COMMAND\": {\n const { method, params } = message;\n return await cdp.sendCommand(message.tabId, method, params || {});\n }\n\n case \"AISTUDIO_EVALUATE\": {\n return await cdp.evaluateScript(message.tabId, message.expression);\n }\n\n case \"DOWNLOADS_SEARCH\": {\n const results = await chrome.downloads.search(message.searchParams || {});\n return {\n downloads: results.map(d => ({\n id: d.id,\n filename: d.filename,\n state: d.state,\n error: d.error,\n }))\n };\n }\n\n case \"GET_GOOGLE_COOKIES\": {\n // Gemini requires cookies from multiple Google domains\n const domains = [\".google.com\", \".gemini.google.com\", \"accounts.google.com\", \"www.google.com\"];\n const allCookies: chrome.cookies.Cookie[] = [];\n \n for (const domain of domains) {\n try {\n const cookies = await chrome.cookies.getAll({ domain });\n allCookies.push(...cookies);\n } catch {}\n }\n \n // Also try by URL for better coverage\n const urls = [\"https://gemini.google.com\", \"https://aistudio.google.com\", \"https://accounts.google.com\", \"https://www.google.com\"];\n for (const url of urls) {\n try {\n const cookies = await chrome.cookies.getAll({ url });\n allCookies.push(...cookies);\n } catch {}\n }\n \n // Dedupe by name, preferring google.com domain with root path\n const seen = new Map<string, chrome.cookies.Cookie>();\n for (const cookie of allCookies) {\n const existing = seen.get(cookie.name);\n if (!existing || \n (cookie.domain === \".google.com\" && cookie.path === \"/\") ||\n (!existing.domain?.includes(\"google.com\") && cookie.domain?.includes(\"google.com\"))) {\n seen.set(cookie.name, cookie);\n }\n }\n \n return { cookies: Array.from(seen.values()) };\n }\n\n case \"WINDOW_NEW\": {\n // Default to a usable blank page if no URL provided\n const url = message.url || 'data:text/html,<html><head><title>Surf Agent</title></head><body style=\"font-family:system-ui;display:flex;align-items:center;justify-content:center;height:100vh;margin:0;color:%23666\"><div style=\"text-align:center\"><h2>Agent Window</h2><p>Ready for automation</p></div></body></html>';\n \n const createOptions: chrome.windows.CreateData = {\n focused: message.focused !== false,\n type: \"normal\",\n url,\n };\n \n if (message.width && message.height) {\n createOptions.width = message.width;\n createOptions.height = message.height;\n }\n \n if (message.incognito) {\n createOptions.incognito = true;\n }\n \n const window = await chrome.windows.create(createOptions);\n \n if (!window.id) throw new Error(\"Failed to create window\");\n \n // Get the tab that was created with the window\n const tabs = await chrome.tabs.query({ windowId: window.id });\n const firstTab = tabs[0];\n \n // Wait for tab to be ready\n if (firstTab?.id) {\n await new Promise(r => setTimeout(r, 150));\n }\n \n return { \n success: true, \n windowId: window.id, \n tabId: firstTab?.id,\n hint: `Use --window-id ${window.id} to target this window`,\n };\n }\n\n case \"WINDOW_LIST\": {\n const windows = await chrome.windows.getAll({ populate: true });\n \n return {\n windows: windows.map(w => ({\n id: w.id,\n focused: w.focused,\n type: w.type,\n state: w.state,\n width: w.width,\n height: w.height,\n tabCount: w.tabs?.length || 0,\n tabs: message.includeTabs ? w.tabs?.map(t => ({\n id: t.id,\n title: t.title,\n url: t.url,\n active: t.active,\n })) : undefined,\n }))\n };\n }\n\n case \"WINDOW_FOCUS\": {\n if (!message.windowId) throw new Error(\"No windowId provided\");\n \n await chrome.windows.update(message.windowId, { focused: true });\n return { success: true, windowId: message.windowId };\n }\n\n case \"WINDOW_CLOSE\": {\n if (!message.windowId) throw new Error(\"No windowId provided\");\n \n await chrome.windows.remove(message.windowId);\n return { success: true, windowId: message.windowId };\n }\n\n case \"WINDOW_RESIZE\": {\n if (!message.windowId) throw new Error(\"No windowId provided\");\n \n const updateInfo: chrome.windows.UpdateInfo = {};\n if (message.width) updateInfo.width = message.width;\n if (message.height) updateInfo.height = message.height;\n if (message.left !== undefined) updateInfo.left = message.left;\n if (message.top !== undefined) updateInfo.top = message.top;\n if (message.state) updateInfo.state = message.state as chrome.windows.windowStateEnum;\n \n const window = await chrome.windows.update(message.windowId, updateInfo);\n return { \n success: true, \n windowId: message.windowId,\n width: window.width,\n height: window.height,\n };\n }\n\n default:\n throw new Error(`Unknown message type: ${message.type}`);\n }\n}\n\nchrome.runtime.onInstalled.addListener((details) => {\n debugLog(\"Extension installed/updated:\", details.reason);\n});\n\nconst COMMANDS_WITHOUT_TAB = new Set([\n \"LIST_TABS\", \"NEW_TAB\", \"TABS_NEW\", \"CLOSE_TABS\", \"SWITCH_TAB\", \"TABS_SWITCH\",\n \"TABS_REGISTER\", \"TABS_UNREGISTER\", \"TABS_LIST_NAMED\", \"TABS_GET_BY_NAME\",\n \"CREATE_TAB_GROUP\", \"UNGROUP_TABS\", \"LIST_TAB_GROUPS\", \"GET_HISTORY\", \"SEARCH_HISTORY\",\n \"GET_COOKIES\", \"SET_COOKIE\", \"DELETE_COOKIES\", \"GET_BOOKMARKS\", \"ADD_BOOKMARK\", \n \"DELETE_BOOKMARK\", \"DIALOG_DISMISS\", \"DIALOG_ACCEPT\", \"DIALOG_INFO\",\n \"CHATGPT_NEW_TAB\", \"CHATGPT_CLOSE_TAB\", \"CHATGPT_EVALUATE\", \"CHATGPT_CDP_COMMAND\",\n \"GET_CHATGPT_COOKIES\", \"GET_GOOGLE_COOKIES\", \"GET_TWITTER_COOKIES\",\n \"PERPLEXITY_NEW_TAB\", \"PERPLEXITY_CLOSE_TAB\", \"PERPLEXITY_EVALUATE\", \"PERPLEXITY_CDP_COMMAND\",\n \"GROK_NEW_TAB\", \"GROK_CLOSE_TAB\", \"GROK_EVALUATE\", \"GROK_CDP_COMMAND\",\n \"GEMINI_NEW_TAB\", \"GEMINI_CLOSE_TAB\", \"GEMINI_FETCH_URL\", \"UPLOAD_FILE_TO_TAB\",\n \"AISTUDIO_NEW_TAB\", \"AISTUDIO_CLOSE_TAB\", \"AISTUDIO_EVALUATE\", \"AISTUDIO_CDP_COMMAND\",\n \"DOWNLOADS_SEARCH\",\n \"WINDOW_NEW\", \"WINDOW_LIST\", \"WINDOW_FOCUS\", \"WINDOW_CLOSE\", \"WINDOW_RESIZE\",\n \"EMULATE_DEVICE_LIST\"\n]);\n\ninitNativeMessaging(async (msg) => {\n let tabId = msg.tabId;\n const windowId = msg.windowId;\n const isDialogCommand = msg.type?.startsWith(\"DIALOG_\");\n const needsTab = !COMMANDS_WITHOUT_TAB.has(msg.type);\n let autoCreatedTab = false;\n \n if (tabId && !isDialogCommand) {\n try {\n await chrome.tabs.get(tabId);\n } catch {\n throw new Error(`Invalid tab ID: ${tabId}. Use 'surf tab.list' to see available tabs.`);\n }\n } else if (!tabId && needsTab) {\n let tabs: chrome.tabs.Tab[];\n let tab: chrome.tabs.Tab | undefined;\n \n if (windowId) {\n // If windowId specified, only look in that window\n tabs = await chrome.tabs.query({ active: true, windowId });\n tab = tabs[0];\n \n // Check if active tab is usable (not a restricted URL)\n const isRestricted = (url?: string) => \n !url || url.startsWith('chrome://') || url.startsWith('chrome-extension://') || url === 'about:blank';\n \n if (!tab || isRestricted(tab.url)) {\n // Active tab is restricted, find any usable tab in the window\n tabs = await chrome.tabs.query({ windowId });\n tab = tabs.find(t => !isRestricted(t.url));\n }\n \n if (!tab?.id) {\n // No usable tab - auto-create one with a minimal page\n const newTab = await chrome.tabs.create({ \n windowId, \n url: 'data:text/html,<html><head><title>Surf</title></head><body></body></html>',\n active: true \n });\n if (!newTab.id) {\n throw new Error(`Failed to create tab in window ${windowId}`);\n }\n // Wait briefly for tab to be ready\n await new Promise(r => setTimeout(r, 100));\n tab = newTab;\n autoCreatedTab = true;\n }\n } else {\n // Default behavior: find active tab across windows\n tabs = await chrome.tabs.query({ active: true, lastFocusedWindow: true });\n tab = tabs[0];\n if (!tab || tab.url?.startsWith('chrome-extension://')) {\n tabs = await chrome.tabs.query({ active: true, currentWindow: true });\n tab = tabs[0];\n }\n if (!tab || tab.url?.startsWith('chrome-extension://') || tab.url?.startsWith('chrome://')) {\n tabs = await chrome.tabs.query({ active: true });\n tab = tabs.find(t => !t.url?.startsWith('chrome-extension://') && !t.url?.startsWith('chrome://'));\n }\n if (!tab?.id) {\n throw new Error(\"No active tab found. Use 'surf tab.new <url>' to create one, or 'surf tab.list' to see available tabs.\");\n }\n }\n tabId = tab.id;\n }\n \n const result = await handleMessage({ ...msg, tabId }, {} as chrome.runtime.MessageSender);\n \n // Add helpful hints based on what happened\n const hints: string[] = [];\n if (autoCreatedTab) {\n hints.push(`Auto-created tab in window ${windowId} (no usable tabs existed). Navigate to your target URL.`);\n }\n \n return { \n ...result, \n _resolvedTabId: tabId,\n _hint: hints.length > 0 ? hints.join(' ') : undefined,\n };\n});\n"],"file":"index.js"}
|