codexui-android 0.1.91 → 0.1.93
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 +10 -1
- package/dist/assets/{ReviewPane-gbhCGpfh.js → ReviewPane-D1nOf7-W.js} +1 -2
- package/dist/assets/{ReviewPane-CyugWwTM.css → ReviewPane-DuPX5OZA.css} +1 -1
- package/dist/assets/{SkillsHub-xXcF9J80.js → SkillsHub-BpqR2Yu5.js} +2 -3
- package/dist/assets/{SkillsHub-Bg1Le103.css → SkillsHub-CTnWejwn.css} +1 -1
- package/dist/assets/ThreadConversation-3WaRKicR.css +1 -0
- package/dist/assets/ThreadConversation-DgJc2aJG.js +39 -0
- package/dist/assets/ThreadTerminalPanel-CGTJQ1BI.css +32 -0
- package/dist/assets/ThreadTerminalPanel-Dy-oA46U.js +38 -0
- package/dist/assets/common-BeuopZEI.js +0 -1
- package/dist/assets/index-Dj8HigAf.css +1 -0
- package/dist/assets/index-HcEz2bUL.js +64 -0
- package/dist/assets/{index.esm-DtVW_dfU.js → index.esm-Bi-9KxvS.js} +2 -3
- package/dist/assets/{index.esm-mbv_PYjX.js → index.esm-DECIu6Fp.js} +1 -2
- package/dist/assets/{index.esm-BilMXo9u.js → index.esm-DPq88-QA.js} +2 -3
- package/dist/index.html +2 -2
- package/dist-cli/index.js +2372 -1058
- package/dist-cli/index.js.map +1 -1
- package/package.json +17 -15
- package/scripts/dev.cjs +58 -0
- package/scripts/fix-pty-native-build.cjs +62 -0
- package/dist/assets/ReviewPane-gbhCGpfh.js.map +0 -1
- package/dist/assets/SkillsHub-xXcF9J80.js.map +0 -1
- package/dist/assets/ThreadConversation-BsN7bN3q.css +0 -1
- package/dist/assets/ThreadConversation-Dr0u8WbA.js +0 -40
- package/dist/assets/ThreadConversation-Dr0u8WbA.js.map +0 -1
- package/dist/assets/common-BeuopZEI.js.map +0 -1
- package/dist/assets/index-B81KnkV8.js +0 -92
- package/dist/assets/index-B81KnkV8.js.map +0 -1
- package/dist/assets/index-C_knKlTI.css +0 -1
- package/dist/assets/index.esm-BilMXo9u.js.map +0 -1
- package/dist/assets/index.esm-DtVW_dfU.js.map +0 -1
- package/dist/assets/index.esm-mbv_PYjX.js.map +0 -1
- package/dist-cli/chunk-PUR7OUAG.js +0 -127
- package/dist-cli/chunk-PUR7OUAG.js.map +0 -1
- package/dist-cli/instrument.js +0 -8
- package/dist-cli/instrument.js.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"mappings":"oRACO,MAAM,6BAA6B,MAAM,MAAM,OAAO,MAAM,QAAQ,YAAY,cAAY,yBAAjG,OAAAA,EAAA,EAAAC,EASM,MATNC,GASM,IAAAC,EAAA,KAAAA,EAAA,IARJC,EAOE,QANA,KAAK,OACL,OAAO,eACP,iBAAe,QACf,kBAAgB,QAChB,eAAa,IACb,EAAE,gGCPD,MAAM,6BAA6B,MAAM,MAAM,OAAO,MAAM,QAAQ,YAAY,cAAY,yBAAjG,OAAAJ,EAAA,EAAAC,EASM,MATNC,GASM,IAAAC,EAAA,KAAAA,EAAA,IARJC,EAOE,QANA,KAAK,OACL,OAAO,eACP,iBAAe,QACf,kBAAgB,QAChB,eAAa,IACb,EAAE,2hLCqqCFC,GAAsB,GAuDtBC,GAAqB,GACrBC,GAAkB,GAClBC,GAAgC,4QAzZtC,MAAMC,GAAqBC,EAAiB,IAAI,GAAK,EAC/CC,EAA0BD,EAAiB,IAAI,GAAK,EACpDE,GAA0BF,EAAiB,IAAI,GAAK,EACpDG,GAAoBH,EAAiB,IAAI,GAAK,EAC9CI,GAA+BJ,EAAiB,IAAI,GAAK,EACzDK,GAA0BL,EAAkC,IAAI,EAChEM,GAA4BN,EAAI,EAAE,EAClCO,EAA2BP,EAAI,EAAK,EACpCQ,GAAyBR,EAAwB,IAAI,EACrDS,GAA+BT,EAAI,EAAK,EACxCU,GAAuBV,EAAI,CAAC,EAC5BW,GAAuBX,EAAI,CAAC,EAC5BY,GAA2BZ,EAAI,EAAE,EACjCa,GAAyBb,EAAI,EAAE,EAC/B,CAAE,SAAAc,EAAA,EAAaC,GAAA,EAErB,SAASC,GAAyBC,EAAmE,OACnG,MAAMC,EAAaD,EAAK,QAAQ,QAAS;AAAA,CAAI,EAAE,OAC/C,GAAI,CAACC,EAAY,OAAO,KAExB,MAAMC,EAAsB,GACtBC,EAA6B,GAEnC,UAAWC,KAAQH,EAAW,MAAM;AAAA,CAAI,EAAG,CACzC,MAAMI,EAAUD,EAAK,OACrB,GAAI,CAACC,EAAS,CACRH,EAAM,SAAW,GAAGC,EAAiB,KAAK,EAAE,EAChD,QACF,CAEA,MAAMG,EAAQD,EAAQ,MAAM,iCAAiC,EAC7D,GAAIC,EAAO,CACT,MAAMC,GAAUD,EAAM,CAAC,GAAK,KAAK,cACjC,IAAIE,EAA+B,UAC/BD,IAAW,MAAKC,EAAS,cACzBD,IAAW,KAAOA,IAAW,KAAOA,IAAW,OAAKC,EAAS,cACjEN,EAAM,KAAK,CACT,OAAMO,EAAAH,EAAM,CAAC,IAAP,YAAAG,EAAU,SAAU,GAC1B,OAAAD,CAAA,CACD,EACD,QACF,CAEAL,EAAiB,KAAKE,CAAO,CAC/B,CAEA,OAAIH,EAAM,SAAW,EAAU,KACxB,CACL,YAAaC,EAAiB,KAAK;AAAA,CAAI,EAAE,OACzC,MAAOD,EAAM,OAAQQ,GAASA,EAAK,KAAK,OAAS,CAAC,EAEtD,CAEA,SAASC,GAAaC,EAAyE,OAC7F,OAAIA,EAAQ,MAAQA,EAAQ,KAAK,MAAM,OAAS,EACvC,CACL,cAAaH,EAAAG,EAAQ,KAAK,cAAb,YAAAH,EAA0B,SAAU,GACjD,MAAOG,EAAQ,KAAK,OAGjBb,GAAyBa,EAAQ,IAAI,CAC9C,CAEA,SAASC,EAAiBD,EAA6B,CACrD,OAAOA,EAAQ,cAAgB,oBAAsB,CAAC,CAACA,EAAQ,gBACjE,CAEA,SAASE,GAAcF,EAA6B,CAClD,OAAOA,EAAQ,cAAgB,QAAUA,EAAQ,cAAgB,WACnE,CAEA,SAASG,GAAoBH,EAA6B,CACxD,OAAOA,EAAQ,cAAgB,cAC1BA,EAAQ,mBAAqB,aAC7B,MAAM,QAAQA,EAAQ,WAAW,GACjCA,EAAQ,YAAY,OAAS,CACpC,CAEA,SAASI,GAA2BJ,EAA6B,CAC/D,OAAOA,EAAQ,OAAS,aACnB,CAACC,EAAiBD,CAAO,GACzBA,EAAQ,cAAgB,UACxB,EAAEA,EAAQ,aAAe,IAAI,SAAS,OAAO,CACpD,CAEA,MAAMK,GAAyBC,EAAS,IAAM,OAC5C,QAASC,EAAQC,EAAM,SAAS,OAAS,EAAGD,GAAS,EAAGA,GAAS,EAAG,CAClE,MAAMP,EAAUQ,EAAM,SAASD,CAAK,EACpC,GAAIP,EAAQ,cAAgB,sBAAsBH,EAAAG,EAAQ,mBAAR,YAAAH,EAA0B,UAAW,aACrF,OAAOG,EAAQ,EAEnB,CACA,MAAO,EACT,CAAC,EAEKS,GAAuBH,EAAS,IACpCE,EAAM,SAAS,KAAMR,GACnBA,EAAQ,OAAS,aACjBA,EAAQ,cAAgB,qBACxBA,EAAQ,KAAK,OAAO,OAAS,EAC/B,EAGIU,GAAoBJ,EAAS,IACjC,EAAQE,EAAM,aAAgBH,GAAuB,MAAM,OAAS,GAAKI,GAAqB,OAG1FE,GAA4BL,EAAsC,IAAM,CAC5E,MAAMM,EAAoC,GAC1C,QAASL,EAAQ,EAAGA,EAAQC,EAAM,SAAS,QAAS,CAClD,MAAMR,EAAUQ,EAAM,SAASD,CAAK,EACpC,GAAI,CAACN,EAAiBD,CAAO,EAAG,CAC9BO,GAAS,EACT,QACF,CAEA,MAAMM,EAAqB,GAC3B,KAAON,EAAQC,EAAM,SAAS,QAAUP,EAAiBO,EAAM,SAASD,CAAK,CAAC,GAC5EM,EAAM,KAAKL,EAAM,SAASD,CAAK,CAAC,EAChCA,GAAS,EAGX,GAAIM,EAAM,QAAU,EAAG,SACvB,MAAMC,EAASD,EAAMA,EAAM,OAAS,CAAC,EACrCD,EAAKE,EAAO,EAAE,EAAID,EAAM,MAAM,EAAG,EAAE,CACrC,CACA,OAAOD,CACT,CAAC,EAEKG,GAA0BT,EAAS,IAAM,CAC7C,MAAMM,MAAW,IACjB,UAAWI,KAAY,OAAO,OAAOL,GAA0B,KAAK,EAClE,UAAWM,KAAWD,EACpBJ,EAAK,IAAIK,EAAQ,EAAE,EAGvB,OAAOL,CACT,CAAC,EAED,SAASM,GAAoBlB,EAA4B,OACvD,QAAOH,EAAAE,GAAaC,CAAO,IAApB,YAAAH,EAAuB,cAAe,EAC/C,CAEA,SAASsB,GAAcnB,EAAkC,OACvD,QAAOH,EAAAE,GAAaC,CAAO,IAApB,YAAAH,EAAuB,QAAS,EACzC,CAEA,SAASuB,GAAmBxB,EAAsC,CAChE,OAAQA,EAAA,CACN,IAAK,YACH,MAAO,IACT,IAAK,aACH,MAAO,IACT,QACE,MAAO,IAEb,CAEA,SAASyB,GAAsBrB,EAA6B,CAC1D,MAAO,CAACS,GAAqB,OAAST,EAAQ,KAAOK,GAAuB,KAC9E,CAEA,SAASiB,EAAkBtB,EAA6B,CACtD,OAAKC,EAAiBD,CAAO,EACtB9B,GAAmB,MAAM,IAAI8B,EAAQ,EAAE,GACxC,CAAC5B,EAAwB,MAAM,IAAI4B,EAAQ,EAAE,GAAKqB,GAAsBrB,CAAO,EAF9C,EAGzC,CAEA,SAASuB,GAAiBvB,EAA6B,CACrD,OAAOC,EAAiBD,CAAO,GAAKU,GAAkB,KACxD,CAEA,SAASc,GAAyBxB,EAA6B,OAC7D,OAAOC,EAAiBD,CAAO,IAAMU,GAAkB,SAASb,EAAAG,EAAQ,mBAAR,YAAAH,EAA0B,UAAW,aACvG,CAEA,SAAS4B,GAAoBzB,EAA0B,CACrD,GAAI,CAACC,EAAiBD,CAAO,EAAG,OAEhC,MAAM0B,EAAe,IAAI,IAAIxD,GAAmB,KAAK,EAC/CyD,EAAoB,IAAI,IAAIvD,EAAwB,KAAK,EACzDwD,EAAiBP,GAAsBrB,CAAO,EACzB0B,EAAa,IAAI1B,EAAQ,EAAE,GAGpD0B,EAAa,OAAO1B,EAAQ,EAAE,EAC1B4B,GAAgBD,EAAkB,IAAI3B,EAAQ,EAAE,GAC3C4B,GAAkB,CAACD,EAAkB,IAAI3B,EAAQ,EAAE,EAC5D2B,EAAkB,IAAI3B,EAAQ,EAAE,GAEhC0B,EAAa,IAAI1B,EAAQ,EAAE,EAC3B2B,EAAkB,OAAO3B,EAAQ,EAAE,GAGrC9B,GAAmB,MAAQwD,EAC3BtD,EAAwB,MAAQuD,CAClC,CAEA,SAASE,GAA4B7B,EAAiC,CACpE,OAAOW,GAA0B,MAAMX,EAAQ,EAAE,GAAK,EACxD,CAEA,SAAS8B,GAAyB9B,EAAiC,CACjE,OAAKC,EAAiBD,CAAO,EACtB,CAAC,GAAG6B,GAA4B7B,CAAO,EAAGA,CAAO,EADjB,EAEzC,CAEA,SAAS+B,GAAmB/B,EAA0B,CAEpD,GADwB6B,GAA4B7B,CAAO,EACvC,SAAW,EAAG,OAClC,MAAMY,EAAO,IAAI,IAAIvC,GAAwB,KAAK,EAC9CuC,EAAK,IAAIZ,EAAQ,EAAE,EAAGY,EAAK,OAAOZ,EAAQ,EAAE,EAC3CY,EAAK,IAAIZ,EAAQ,EAAE,EACxB3B,GAAwB,MAAQuC,CAClC,CAEA,SAASoB,GAAuBhC,EAA6B,CAC3D,OAAO3B,GAAwB,MAAM,IAAI2B,EAAQ,EAAE,CACrD,CAEA,SAASiC,GAAyBjC,EAA4B,SAE5D,MAAMkC,EADWJ,GAAyB9B,CAAO,EAC1B,OACjBmC,IAAgBC,GAAAvC,EAAAG,EAAQ,mBAAR,YAAAH,EAA0B,UAA1B,YAAAuC,EAAmC,SAAU,YAEnE,MAAO,GADYF,IAAU,EAAI,YAAc,GAAGA,CAAK,WACnC,cAAcC,CAAa,EACjD,CAEA,SAASE,GAA0BrC,EAA4B,CAC7D,OAAOsC,GAAmBtC,CAAO,CACnC,CAEA,SAASuC,GAAmBvC,EAA0B,CACpD,MAAMY,EAAO,IAAI,IAAItC,GAAkB,KAAK,EACxCsC,EAAK,IAAIZ,EAAQ,EAAE,EAAGY,EAAK,OAAOZ,EAAQ,EAAE,EAC3CY,EAAK,IAAIZ,EAAQ,EAAE,EACxB1B,GAAkB,MAAQsC,CAC5B,CAEA,SAAS4B,GAAiBxC,EAA6B,CACrD,OAAO1B,GAAkB,MAAM,IAAI0B,EAAQ,EAAE,CAC/C,CAEA,SAASyC,GAAwBzC,EAA0B,CACzD,MAAMY,EAAO,IAAI,IAAIrC,GAA6B,KAAK,EACnDqC,EAAK,IAAIZ,EAAQ,EAAE,EAAGY,EAAK,OAAOZ,EAAQ,EAAE,EAC3CY,EAAK,IAAIZ,EAAQ,EAAE,EACxBzB,GAA6B,MAAQqC,CACvC,CAEA,SAAS8B,GAA4B1C,EAA6B,CAChE,OAAOzB,GAA6B,MAAM,IAAIyB,EAAQ,EAAE,CAC1D,CAEA,SAAS2C,EAAcC,EAA8B,CACnD,MAAO,GAAGA,EAAO,IAAI,KAASA,EAAO,aAAe,EAAE,EACxD,CAEA,SAASC,GAAeC,EAAuCF,EAA4B,CACpFE,IACLtE,GAAwB,MAAQsE,EAChCrE,GAA0B,MAAQkE,EAAcC,CAAM,EACtDlE,EAAyB,MAAQ,GACnC,CAEA,SAASqE,IAAwB,CAC/BvE,GAAwB,MAAQ,KAChCC,GAA0B,MAAQ,GAClCC,EAAyB,MAAQ,EACnC,CAEA,SAASsE,IAAiC,CACxCtE,EAAyB,MAAQ,CAACA,EAAyB,KAC7D,CAEA,SAASuE,IAAgC,CACvCvE,EAAyB,MAAQ,EACnC,CAEA,SAASwE,GAAuBN,EAA4B,CAC1DnE,GAA0B,MAAQkE,EAAcC,CAAM,EAClD3D,GAAS,QACXP,EAAyB,MAAQ,GAErC,CAEA,SAAS4D,GAAmBtC,EAA4B,CACtD,MAAMmD,EAAKnD,EAAQ,iBACnB,GAAI,CAACmD,EAAI,MAAO,GAChB,MAAMC,EAAU7B,GAAiBvB,CAAO,EACxC,OAAQmD,EAAG,QACT,IAAK,aAAc,OAAOC,EAAU,UAAY,YAChD,IAAK,YAAa,OAAOD,EAAG,WAAa,EAAKC,EAAU,OAAS,cAAiB,QAAQD,EAAG,UAAY,GAAG,GAC5G,IAAK,SAAU,OAAOC,EAAU,SAAW,WAC3C,IAAK,WAAY,OAAOA,EAAU,WAAa,aAC/C,IAAK,cAAe,OAAOA,EAAU,UAAY,gBACjD,QAAS,MAAO,GAEpB,CAEA,SAASC,GAAmBrD,EAA4B,SACtD,MAAMsD,GAAIzD,EAAAG,EAAQ,mBAAR,YAAAH,EAA0B,OACpC,OAAIyD,IAAM,aAAqB,qBAC3BA,IAAM,eAAelB,EAAApC,EAAQ,mBAAR,YAAAoC,EAA0B,YAAa,EAAU,gBACnE,kBACT,CAEA,SAASmB,GAAkBC,EAAqBC,EAAoC,CAClF,GAAID,EAAO,OAAS,EAAG,OAAOA,EAC9B,MAAM5C,MAAW,IACjB,UAAW8C,KAAMF,EACXC,EAAS,IAAIC,CAAE,GAAG9C,EAAK,IAAI8C,CAAE,EAEnC,OAAO9C,EAAK,OAAS4C,EAAO,KAAOA,EAAS5C,CAC9C,CAEA,SAAS+C,GAAqBC,EAAuBC,EAAkC,CACrF,MAAMC,EAAsB,GAC5B,QAASC,EAAIF,EAAc,EAAGE,GAAK,EAAGA,IAAK,CACzC,MAAMC,EAAIJ,EAASG,CAAC,EACpB,GAAIC,EAAE,cAAgB,mBAAoBF,EAAO,QAAQE,CAAC,UACjDA,EAAE,OAAS,QAAUA,EAAE,cAAgB,SAAU,KAC5D,CACA,OAAOF,CACT,CAEA,MAAMtD,EAAQyD,EAURC,GAAOC,GAOPC,EAAsBjG,EAAwB,IAAI,EAClDkG,GAAkBlG,EAAwB,IAAI,EAC9CmG,GAAgBnG,EAAI,EAAE,EACtBoG,EAAyBpG,EAAI,EAAE,EAI/BqG,GAAmBrG,EAA8B,IAAI,EACrDsG,EAAmBtG,IAAI0B,GAAAW,EAAM,cAAN,YAAAX,GAAmB,cAAe,EAAK,EAE9D6E,GAAgD,CACpD,GAAI,aACJ,IAAK,MACL,GAAI,aACJ,IAAK,MACL,GAAI,SACJ,GAAI,OACJ,GAAI,OACJ,MAAO,OACP,IAAK,OACL,IAAK,OACL,GAAI,WACJ,MAAO,MACP,KAAM,SACN,IAAK,cA+BP,IAAIC,GAAqB,EACrBC,EAAkB,EAClBC,GAAuB,EACvBC,GAAgE,KACpE,MAAMC,OAA2B,QAE3BC,GAAoB7G,EAA8B,IAAI,EAC5D,IAAI8G,GAA0C,KAM9C,MAAMC,EAAoB/G,EAAI,CAAC,EACzBgH,EAAgBhH,EAAI,EAAK,EAEzBiH,GAAkB9E,EAAS,IAAME,EAAM,SAAS,MAAM0E,EAAkB,KAAK,CAAC,EAC9EG,GAAe/E,EAAS,IAAM4E,EAAkB,MAAQ,CAAC,EAEzDI,GAAyBhF,EAC7B,IAAM,CAACmE,EAAiB,QAAUjE,EAAM,SAAS,OAAS,GAAKA,EAAM,gBAAgB,OAAS,GAAK,EAAQA,EAAM,YAAW,EAG9H,SAAS+E,IAAyC,CAChD,OAAIP,GAAkB,MAAc,QAAQ,WACvCC,KACHA,GAAAO,GAAA,IAAoB,OAAO,sBAAyB,MACjD,KAAMC,GAAW,CAChBT,GAAkB,MAAQS,EAAO,OACnC,CAAC,EACA,QAAQ,IAAM,CACbR,GAAoB,IACtB,CAAC,GAEEA,GACT,CAsCA,SAASS,GAAWC,EAAwB,CAG1C,GAFI,CAACA,GAAS,UAAU,KAAKA,CAAK,GAC9BA,EAAM,SAAS,GAAG,GAAKA,EAAM,SAAS,IAAI,GAC1C,iCAAiC,KAAKA,CAAK,EAAG,MAAO,GAEzD,MAAMC,EAAwBD,EAAM,WAAW,GAAG,EAC5CE,EAA2B,mBAAmB,KAAKF,CAAK,EACxDG,EAAoBH,EAAM,WAAW,IAAI,GAAKA,EAAM,WAAW,KAAK,GAAKA,EAAM,WAAW,IAAI,EACpG,OAAIC,GAAyBC,GAA4BC,EAA0B,GAG5E,sDAAsD,KAAKH,CAAK,CACzE,CAEA,SAASI,GAAYC,EAA2B,CAG9C,OAFmBA,EAAU,QAAQ,OAAQ,GAAG,EACxB,MAAM,GAAG,EAAE,OAAO,OAAO,EAAE,OACpCA,CACjB,CAEA,SAASC,GAAwBD,EAA2B,CAC1D,OAAOA,EAAU,QAAQ,OAAQ,GAAG,CACtC,CAEA,SAASE,GAAuBF,EAA2B,CACzD,GAAI,CAACA,EAAU,WAAW,SAAS,EAAG,OAAOA,EAC7C,IAAIG,EAAWH,EAAU,QAAQ,cAAe,EAAE,EAClD,GAAI,CACFG,EAAW,mBAAmBA,CAAQ,CACxC,MAAQ,CAER,CACA,MAAI,kBAAkB,KAAKA,CAAQ,IACjCA,EAAWA,EAAS,MAAM,CAAC,GAEtBA,CACT,CAEA,SAASC,GAAiBC,EAAqB,CAC7C,MAAMhH,EAAa4G,GAAwBI,CAAG,EACxCC,EAAYjH,EAAW,MAAM,oBAAoB,EACvD,GAAIiH,EAAW,MAAO,UAAUA,EAAU,CAAC,CAAC,GAC5C,MAAMC,EAAYlH,EAAW,MAAM,mBAAmB,EACtD,OAAIkH,EAAkB,SAASA,EAAU,CAAC,CAAC,GACpC,EACT,CAEA,SAASC,GAAkBR,EAA2B,CACpD,MAAM3G,EAAa4G,GAAwBD,CAAS,EACpD,GAAI,CAAC3G,EAAY,OAAOA,EAExB,IAAIoH,EAAO,GACPC,EAAOrH,EACX,MAAMsH,EAAaD,EAAK,MAAM,uBAAuB,EACjDC,GACFF,EAAO,GAAGE,EAAW,CAAC,CAAC,IACvBD,GAAQC,EAAW,CAAC,GAAK,IAAI,QAAQ,QAAS,EAAE,GACvCD,EAAK,WAAW,GAAG,IAC5BD,EAAO,IACPC,EAAOA,EAAK,MAAM,CAAC,GAGrB,MAAME,EAAQF,EAAK,MAAM,GAAG,EAAE,OAAO,OAAO,EACtCG,EAAkB,GACxB,UAAWC,KAAQF,EACjB,GAAIE,IAAS,IACb,IAAIA,IAAS,KAAM,CACbD,EAAM,OAAS,GAAGA,EAAM,MAC5B,QACF,CACAA,EAAM,KAAKC,CAAI,EAGjB,MAAMC,EAASF,EAAM,KAAK,GAAG,EAC7B,OAAIJ,EAAa,GAAGA,CAAI,GAAGM,CAAM,GAAG,QAAQ,QAAS,EAAE,GAAKN,EACrDM,GAAU1H,CACnB,CAEA,SAAS2H,GAAoBhB,EAAmBK,EAAqB,CACnE,MAAMY,EAAiBhB,GAAwBC,GAAuBF,EAAU,MAAM,CAAC,EACvF,GAAI,CAACiB,EAAgB,MAAO,GAG5B,GAD0BA,EAAe,WAAW,GAAG,GAAK,gBAAgB,KAAKA,CAAc,EACxE,OAAOT,GAAkBS,CAAc,EAE9D,GAAIA,EAAe,WAAW,IAAI,EAAG,CACnC,MAAMC,EAAWd,GAAiBC,CAAG,EACrC,GAAIa,EACF,OAAOV,GAAkB,GAAGU,CAAQ,IAAID,EAAe,MAAM,CAAC,CAAC,EAAE,CAErE,CAEA,MAAME,EAAOlB,GAAwBI,EAAI,MAAM,EAC/C,OACOG,GADFW,EACoB,GAAGA,EAAK,QAAQ,QAAS,EAAE,CAAC,IAAIF,CAAc,GADnCA,CACqC,CAC3E,CAEA,SAASG,GAAmBzB,EAA6D,CACvF,GAAI,CAACA,EAAO,OAAO,KAEnB,IAAIK,EAAYL,EAAM,OAEtBK,EADgBqB,GAAiBrB,CAAS,EACtB,KAAK,OACzB,IAAIxG,EAAsB,KAE1B,MAAM8H,EAAgBtB,EAAU,MAAM,yBAAyB,EAC/D,GAAIsB,EACFtB,EAAYsB,EAAc,CAAC,EAC3B9H,EAAO,OAAO8H,EAAc,CAAC,CAAC,MACzB,CACL,MAAMC,EAAiBvB,EAAU,MAAM,wBAAwB,EAC3DuB,IACFvB,EAAYuB,EAAe,CAAC,EAC5B/H,EAAO,OAAO+H,EAAe,CAAC,CAAC,EAEnC,CAGA,OADAvB,EAAYE,GAAuBF,CAAS,EACvCN,GAAWM,CAAS,EAClB,CAAE,KAAMA,EAAW,KAAAxG,CAAA,EADS,IAErC,CAEA,SAAS6H,GAAiB1B,EAAoE,CAC5F,IAAI6B,EAAO7B,EACP8B,EAAU,GACVC,EAAW,GAEf,KAAO,gBAAgB,KAAKF,CAAI,GAC9BC,GAAWD,EAAK,CAAC,EACjBA,EAAOA,EAAK,MAAM,CAAC,EAErB,KAAO,iBAAiB,KAAKA,CAAI,GAC/BE,EAAWF,EAAK,MAAM,EAAE,EAAIE,EAC5BF,EAAOA,EAAK,MAAM,EAAG,EAAE,EAGzB,MAAO,CAAE,KAAAA,EAAM,QAAAC,EAAS,SAAAC,CAAA,CAC1B,CAEA,SAASC,GAAuBhC,EAAyD,CACvF,MAAMlG,EAAUkG,EAAM,OACtB,GAAI,CAAClG,EAAQ,WAAW,GAAG,GAAK,CAACA,EAAQ,SAAS,GAAG,EAAG,OAAO,KAC/D,MAAMmI,EAAkBnI,EAAQ,QAAQ,GAAG,EAE3C,GADImI,GAAmB,GACnBnI,EAAQmI,EAAkB,CAAC,IAAM,IAAK,OAAO,KACjD,MAAMC,EAAWpI,EAAQ,MAAM,EAAGmI,CAAe,EAAE,OAC7CE,EAAYrI,EAAQ,MAAMmI,EAAkB,EAAG,EAAE,EAAE,OACzD,GAAIC,EAAS,SAAS;AAAA,CAAI,GAAKC,EAAU,SAAS;AAAA,CAAI,EAAG,OAAO,KAChE,MAAMC,EAAQV,GAAiBQ,CAAQ,EAAE,KAAK,QAAUA,EAClDG,EAASX,GAAiBS,CAAS,EAAE,KAAK,OAChD,OAAKE,EACE,CAAE,MAAAD,EAAO,OAAAC,CAAA,EADI,IAEtB,CAEA,SAASC,GAAWC,EAAuB,CACzC,MAAMC,EAAkB,KAAK,IAAI,EAAG,KAAK,IAAI,EAAG,KAAK,MAAMD,CAAK,CAAC,CAAC,EAClE,MAAO,IAAI,OAAOC,CAAe,CAAC,EACpC,CAEA,SAASC,GAAaF,EAAuB,CAC3C,OAAQ,KAAK,IAAI,EAAG,KAAK,IAAI,EAAG,KAAK,MAAMA,CAAK,CAAC,CAAC,GAChD,IAAK,GACH,MAAO,qBACT,IAAK,GACH,MAAO,qBACT,IAAK,GACH,MAAO,qBACT,IAAK,GACH,MAAO,qBACT,IAAK,GACH,MAAO,qBACT,QACE,MAAO,qBAEb,CAEA,SAASG,GAAmBzI,EAAsC,CAChE,OAAQA,EAAA,CACN,IAAK,YACH,MAAO,MACT,IAAK,aACH,MAAO,MACT,QACE,MAAO,MAEb,CAEA,SAAS0I,GAAkBtI,EAA4B,OACrD,MAAMuI,EAAWxI,GAAaC,CAAO,EACrC,GAAI,CAACuI,EAAU,MAAO,GAEtB,MAAMC,EAAqB,GAC3B,OAAI3I,EAAA0I,EAAS,cAAT,MAAA1I,EAAsB,QACxB2I,EAAS,KAAKD,EAAS,YAAY,MAAM,EAGvCA,EAAS,MAAM,OAAS,GAC1BC,EAAS,KAAKD,EAAS,MAAM,IAAKzI,GAAS,KAAKuI,GAAmBvI,EAAK,MAAM,CAAC,IAAIA,EAAK,IAAI,GAAG,MAAM,EAAE,KAAK;AAAA,CAAI,CAAC,EAG5G0I,EAAS,KAAK;;AAAA,CAAM,EAAE,MAC/B,CAEA,SAASC,GAA4BzI,EAA4B,CAC/D,MAAMwI,EAAqB,GACrBE,EAAiB1I,EAAQ,KAAK,QAAUsI,GAAkBtI,CAAO,EACjE2I,EAAczI,GAAcF,CAAO,GAAK0I,EAC1C;AAAA,EAASA,CAAc,GACvBA,EACAC,GACFH,EAAS,KAAKG,CAAW,EAG3B,MAAMC,GAAmB5I,EAAQ,iBAAmB,IACjD,IAAK6I,GAAeA,EAAW,KAAK,MAAM,EAC1C,OAAQ7C,GAAcA,EAAU,OAAS,CAAC,EACzC4C,EAAgB,OAAS,GAC3BJ,EAAS,KAAK;AAAA,EAAWI,EAAgB,KAAK;AAAA,CAAI,CAAC,EAAE,EAGvD,MAAME,GAAc9I,EAAQ,QAAU,IACnC,IAAK+I,GAAaA,EAAS,MAAM,EACjC,OAAQA,GAAaA,EAAS,OAAS,CAAC,EAC3C,OAAID,EAAW,OAAS,GACtBN,EAAS,KAAK;AAAA,EAAYM,EAAW,KAAK;AAAA,CAAI,CAAC,EAAE,EAG5CN,EAAS,KAAK;;AAAA,CAAM,EAAE,MAC/B,CAEA,MAAMQ,GAAoC1I,EAAiC,IAAM,OAC/E,MAAM2I,MAAuB,IAE7B,UAAWjJ,KAAWQ,EAAM,SAAU,CACpC,GAAI,CAACJ,GAA2BJ,CAAO,EAAG,SAE1C,MAAMkJ,EAAUT,GAA4BzI,CAAO,EACnD,GAAI,CAACkJ,EAAS,SAEd,MAAMC,EAAc,OAAOnJ,EAAQ,WAAc,SAC7C,QAAQA,EAAQ,SAAS,GACzB,WAAWA,EAAQ,EAAE,GACnBoJ,EAAWH,EAAiB,IAAIE,CAAW,EACjD,GAAIC,EAAU,CACZA,EAAS,gBAAkBpJ,EAAQ,GACnCoJ,EAAS,MAAM,KAAKF,CAAO,EAC3B,QACF,CAEAD,EAAiB,IAAIE,EAAa,CAChC,gBAAiBnJ,EAAQ,GACzB,MAAO,CAACkJ,CAAO,EAChB,CACH,CAEA,MAAMtI,EAA+B,GACrC,UAAWyI,KAAYJ,EAAiB,SAAU,CAChD,MAAMC,EAAUG,EAAS,MAAM,KAAK;;AAAA,CAAM,EAAE,OACvCH,IACLtI,EAAKyI,EAAS,eAAe,EAAIH,EACnC,CAEA,SAAW,CAACI,EAAiBxG,CAAO,IAAK,OAAO,QAAQyG,GAAoC,KAAK,EAAG,CAClG,GAAIzG,EAAQ,SAAW,WAAY,SACnC,MAAM0G,EAAiBC,GAAwB3G,CAAO,EACtD,GAAI,CAAC0G,EAAgB,SACrB,MAAMJ,GAAWvJ,EAAAe,EAAK0I,CAAe,IAApB,YAAAzJ,EAAuB,OACxCe,EAAK0I,CAAe,EAAIF,EAAW,GAAGA,CAAQ;;AAAA,EAAOI,CAAc,GAAKA,CAC1E,CACA,OAAO5I,CACT,CAAC,EAEK8I,GAA8BpJ,EAAiC,IAAM,CACzE,MAAMqJ,MAAmB,IAEzB,UAAW3J,KAAWQ,EAAM,SAAU,CACpC,GAAI,CAACJ,GAA2BJ,CAAO,GAAK,OAAOA,EAAQ,WAAc,SAAU,SAEnF,MAAMmJ,EAAc,QAAQnJ,EAAQ,SAAS,GACvCoJ,EAAWO,EAAa,IAAIR,CAAW,EAC7C,GAAIC,EAAU,CACZA,EAAS,gBAAkBpJ,EAAQ,GACnCoJ,EAAS,UAAYpJ,EAAQ,UAC7B,QACF,CAEA2J,EAAa,IAAIR,EAAa,CAC5B,gBAAiBnJ,EAAQ,GACzB,UAAWA,EAAQ,UACpB,CACH,CAEA,MAAMY,EAA+B,GACrC,UAAWgJ,KAAeD,EAAa,SACrC/I,EAAKgJ,EAAY,eAAe,EAAIA,EAAY,UAElD,OAAOhJ,CACT,CAAC,EAED,SAASiJ,GAAuB7J,EAA6B,CAC3D,OAAO,OAAOgJ,GAAkC,MAAMhJ,EAAQ,EAAE,GAAM,QACxE,CAEA,SAAS8J,GAAuB9J,EAA6B,CAC3D,OAAO,OAAO0J,GAA4B,MAAM1J,EAAQ,EAAE,GAAM,QAClE,CAEA,SAAS+J,GAAoBC,EAAeC,EAAwB,CAClE,OAAKD,EACD,CAACC,GAAUD,IAAUC,EAAeD,EACjC,GAAGA,CAAK;AAAA,EAAKC,CAAM,GAAG,OAFVA,CAGrB,CAEA,SAASC,GAAqBF,EAAqBC,EAAoC,CACrF,MAAME,EAAYH,EAAM,YAAc,OAASC,EAAO,YAAc,MAChE,MACAD,EAAM,YAAc,UAAYC,EAAO,YAAc,SACnD,SACA,SACN,MAAO,CACL,KAAMA,EAAO,MAAQD,EAAM,KAC3B,UAAAG,EACA,YAAaF,EAAO,aAAeD,EAAM,aAAe,KACxD,KAAMD,GAAoBC,EAAM,KAAMC,EAAO,IAAI,EACjD,eAAgBD,EAAM,eAAiBC,EAAO,eAC9C,iBAAkBD,EAAM,iBAAmBC,EAAO,iBAEtD,CAEA,SAASG,GAAmBJ,EAAqBC,EAA8B,CAC7E,MAAMI,EAAYL,EAAM,YAAc,MAAQ,EAAIA,EAAM,YAAc,SAAW,EAAI,EAC/EM,EAAaL,EAAO,YAAc,MAAQ,EAAIA,EAAO,YAAc,SAAW,EAAI,EACxF,GAAII,IAAcC,EAAY,OAAOD,EAAYC,EACjD,MAAMC,EAAY,GAAGP,EAAM,IAAI,KAASA,EAAM,aAAe,EAAE,GACzDQ,EAAa,GAAGP,EAAO,IAAI,KAASA,EAAO,aAAe,EAAE,GAClE,OAAOM,EAAU,cAAcC,CAAU,CAC3C,CAEA,SAASC,GAAqBC,EAAyC,CACrE,MAAMC,MAAa,IACnB,UAAW/H,KAAU8H,EAAS,CAC5B,MAAME,EAAM,GAAGhI,EAAO,IAAI,KAASA,EAAO,aAAe,EAAE,GACrDiI,EAAWF,EAAO,IAAIC,CAAG,EAC/BD,EAAO,IAAIC,EAAKC,EAAWX,GAAqBW,EAAUjI,CAAM,EAAI,CAAE,GAAGA,EAAQ,CACnF,CACA,OAAO,MAAM,KAAK+H,EAAO,QAAQ,EAAE,KAAKP,EAAkB,CAC5D,CAEA,MAAMb,GAAsCjJ,EAAgD,IAAM,CAChG,MAAMwK,MAAiC,IACjCC,MAAiC,IACjCC,MAAkC,IAExC,UAAWhL,KAAWQ,EAAM,SAAU,CAYpC,GAXIJ,GAA2BJ,CAAO,GAAK,OAAOA,EAAQ,WAAc,WACtE8K,EAA2B,IAAI,QAAQ9K,EAAQ,SAAS,GAAIA,EAAQ,EAAE,EAClE,MAAM,QAAQA,EAAQ,WAAW,GAAKA,EAAQ,YAAY,OAAS,GACrE+K,EAA2B,IAAI/K,EAAQ,GAAI,CACzC,QAASyK,GAAqBzK,EAAQ,WAAW,EACjD,iBAAkB,GAClB,OAAQ,YACT,GAID,CAACG,GAAoBH,CAAO,EAAG,SACnC,MAAMiL,EAAU,OAAOjL,EAAQ,WAAc,SAAW,QAAQA,EAAQ,SAAS,GAAK,WAAWA,EAAQ,EAAE,GACrGkL,EAAUF,EAA4B,IAAIC,CAAO,EACnDC,EAASA,EAAQ,KAAKlL,CAAO,EAC5BgL,EAA4B,IAAIC,EAAS,CAACjL,CAAO,CAAC,CACzD,CAEA,MAAMmL,EAAmD,GACzD,SAAW,CAACF,EAASrH,CAAQ,IAAKoH,EAA4B,UAAW,CACvE,MAAMI,EAAWN,EAA2B,IAAIG,CAAO,EAClDG,IACLD,EAAUC,CAAQ,EAAI,CACpB,QAASX,GAAqB7G,EAAS,QAAS5D,GAAYA,EAAQ,aAAe,EAAE,CAAC,EACtF,iBAAkB4D,EAAS,IAAK5D,GAAYA,EAAQ,EAAE,EACtD,OAAQ,YAEZ,CAEA,SAAW,CAACoL,EAAUtI,CAAO,IAAKiI,EAA2B,UACtDI,EAAUC,CAAQ,IACrBD,EAAUC,CAAQ,EAAItI,GAI1B,OAAOqI,CACT,CAAC,EAEKE,GAAyC/K,EAAgD,IAAM,CACnG,MAAMwK,MAAiC,IACjCE,MAAkC,IAExC,UAAWhL,KAAWQ,EAAM,SAAU,CAKpC,GAJIJ,GAA2BJ,CAAO,GAAK,OAAOA,EAAQ,WAAc,UACtE8K,EAA2B,IAAI,QAAQ9K,EAAQ,SAAS,GAAIA,EAAQ,EAAE,EAGpE,CAACG,GAAoBH,CAAO,EAAG,SACnC,MAAMiL,EAAU,OAAOjL,EAAQ,WAAc,SAAW,QAAQA,EAAQ,SAAS,GAAK,WAAWA,EAAQ,EAAE,GACrGkL,EAAUF,EAA4B,IAAIC,CAAO,EACnDC,EAASA,EAAQ,KAAKlL,CAAO,EAC5BgL,EAA4B,IAAIC,EAAS,CAACjL,CAAO,CAAC,CACzD,CAEA,MAAMmL,EAAmD,GACzD,SAAW,CAACF,EAASrH,CAAQ,IAAKoH,EAA4B,UAAW,CACvE,GAAIF,EAA2B,IAAIG,CAAO,EAAG,SAC7C,MAAMK,EAAiB1H,EAASA,EAAS,OAAS,CAAC,EAC9C0H,IACLH,EAAUG,EAAe,EAAE,EAAI,CAC7B,QAASb,GAAqB7G,EAAS,QAAS5D,GAAYA,EAAQ,aAAe,EAAE,CAAC,EACtF,iBAAkB4D,EAAS,IAAK5D,GAAYA,EAAQ,EAAE,EACtD,OAAQ,YAEZ,CAEA,OAAOmL,CACT,CAAC,EAEKI,GAA6BjL,EAAS,IAAM,CAChD,MAAMM,MAAW,IACjB,UAAWkC,KAAW,OAAO,OAAOyG,GAAoC,KAAK,EAC3E,UAAWiC,KAAa1I,EAAQ,iBAC9BlC,EAAK,IAAI4K,CAAS,EAGtB,SAAW,CAACA,EAAW1I,CAAO,IAAK,OAAO,QAAQuI,GAAuC,KAAK,EAC5F,UAAWI,KAAmB3I,EAAQ,iBAChC2I,IAAoBD,GACtB5K,EAAK,IAAI6K,CAAe,EAI9B,OAAO7K,CACT,CAAC,EAED,SAAS8K,GAA8B1L,EAAkD,CACvF,OAAOuJ,GAAoC,MAAMvJ,EAAQ,EAAE,GAAK,IAClE,CAEA,SAAS2L,GAAgC3L,EAAkD,CACzF,OAAOqL,GAAuC,MAAMrL,EAAQ,EAAE,GAAK,IACrE,CAEA,SAAS4L,GAAyBhJ,EAA8B,CAC9D,OAAIA,EAAO,YAAc,UAAYA,EAAO,YACnCA,EAAO,eAAiB,GAAKA,EAAO,iBAAmB,EAAI,iBAAmB,QAEnFA,EAAO,YAAc,MAAc,QACnCA,EAAO,YAAc,SAAiB,UACnC,QACT,CAEA,SAASiJ,GAAwBjJ,EAA4D,CAC3F,OAAIA,EAAO,YAAc,UAAYA,EAAO,YAAoB,OACzDA,EAAO,SAChB,CAEA,SAASkJ,EAAsBlJ,EAA8B,CAC3D,MAAMgE,EAAkB,GACxB,OAAIhE,EAAO,eAAiB,GAAGgE,EAAM,KAAK,IAAIhE,EAAO,cAAc,EAAE,EACjEA,EAAO,iBAAmB,GAAGgE,EAAM,KAAK,IAAIhE,EAAO,gBAAgB,EAAE,EAClEgE,EAAM,KAAK,GAAG,CACvB,CASA,SAASmF,GAA0BC,EAAoBC,EAAsBC,EAAgB,GAA2B,CACtH,MAAMtF,EAA+B,GAGrC,OAFIoF,EAAa,GAAGpF,EAAM,KAAK,CAAE,KAAM,MAAO,MAAO,IAAIoF,CAAU,GAAI,EACnEC,EAAe,GAAGrF,EAAM,KAAK,CAAE,KAAM,SAAU,MAAO,IAAIqF,CAAY,GAAI,EAC1ErF,EAAM,OAAS,EAAUA,EACtBsF,EAAgB,CAAC,CAAE,KAAM,UAAW,MAAOA,CAAA,CAAe,EAAI,EACvE,CAEA,SAASC,GAAqBvJ,EAA6C,CACzE,OAAOmJ,GAA0BnJ,EAAO,eAAgBA,EAAO,gBAAgB,CACjF,CAEA,SAASwJ,GAA2BlK,EAAuB,CACzD,OAAOA,IAAU,EAAI,iBAAmB,GAAGA,CAAK,gBAClD,CAEA,SAASmK,GAAyBvJ,EAA+C,CAC/E,GAAI,CAACA,GAAWA,EAAQ,QAAQ,SAAW,EAAG,MAAO,GACrD,IAAIwJ,EAAQ,EACRC,EAAU,EACVC,EAAS,EACTC,EAAQ,EAEZ,UAAW7J,KAAUE,EAAQ,QAAS,CACpC,GAAIF,EAAO,YAAc,MAAO,CAC9B0J,GAAS,EACT,QACF,CACA,GAAI1J,EAAO,YAAc,SAAU,CACjC2J,GAAW,EACX,QACF,CACA,GAAI3J,EAAO,YAAa,CACtB6J,GAAS,EACT,QACF,CACAD,GAAU,CACZ,CAEA,MAAM5F,EAAkB,GACxB,OAAI4F,EAAS,GAAG5F,EAAM,KAAK,GAAG4F,CAAM,SAAS,EACzCF,EAAQ,GAAG1F,EAAM,KAAK,GAAG0F,CAAK,QAAQ,EACtCC,EAAU,GAAG3F,EAAM,KAAK,GAAG2F,CAAO,UAAU,EAC5CE,EAAQ,GAAG7F,EAAM,KAAK,GAAG6F,CAAK,QAAQ,EACnC7F,EAAM,KAAK,IAAI,CACxB,CAEA,SAAS8F,GAAuB5J,EAA+C,CAC7E,GAAI,CAACA,GAAWA,EAAQ,QAAQ,SAAW,EAAG,MAAO,iBACrD,MAAM6J,EAAaP,GAA2BtJ,EAAQ,QAAQ,MAAM,EAC9D8J,EAAcP,GAAyBvJ,CAAO,EACpD,OAAO8J,EAAc,GAAGD,CAAU,MAAMC,CAAW,GAAKD,CAC1D,CAEA,SAASE,GAA6B/J,EAA8D,CAClG,GAAI,CAACA,GAAWA,EAAQ,QAAQ,SAAW,QAAU,GACrD,MAAMgK,EAAahK,EAAQ,QAAQ,OAAO,CAACiK,EAAKnK,IAAWmK,EAAMnK,EAAO,eAAgB,CAAC,EACnFoK,EAAelK,EAAQ,QAAQ,OAAO,CAACiK,EAAKnK,IAAWmK,EAAMnK,EAAO,iBAAkB,CAAC,EACvFsJ,EAAgBpJ,EAAQ,QAAQ,KAAMF,GAAWA,EAAO,WAAW,EAAI,QAAU,QACvF,OAAOmJ,GAA0Be,EAAYE,EAAcd,CAAa,CAC1E,CAEA,SAASe,EAAsBjH,EAA2B,CACxD,MAAMkH,EAAWlG,GAAoBhB,EAAWxF,EAAM,GAAG,EACnD2M,EAAgB3G,GAAkBP,GAAwBzF,EAAM,IAAI,MAAM,CAAC,EAC3E4M,EAAqB5G,GAAkBP,GAAwBiH,CAAQ,CAAC,EAC9E,OAAIC,GAAiBC,EAAmB,WAAW,GAAGD,CAAa,GAAG,EAC7DC,EAAmB,MAAMD,EAAc,OAAS,CAAC,EAEnDnH,CACT,CAEA,SAASyD,GAAwB3G,EAA+C,CAC9E,MAAI,CAACA,GAAWA,EAAQ,QAAQ,SAAW,EAAU,GAO9C;AAAA,EANOA,EAAQ,QAAQ,IAAKF,GAAW,CAC5C,MAAMyK,EAAYJ,EAAsBrK,EAAO,IAAI,EAC7C0K,EAAa1K,EAAO,YAAc,OAAOqK,EAAsBrK,EAAO,WAAW,CAAC,GAAK,GACvF2K,EAAQzB,EAAsBlJ,CAAM,EAC1C,MAAO,KAAKgJ,GAAyBhJ,CAAM,CAAC,KAAKyK,CAAS,GAAGC,CAAU,GAAGC,EAAQ,KAAKA,CAAK,IAAM,EAAE,EACtG,CAAC,EACgC,KAAK;AAAA,CAAI,CAAC,GAAG,MAChD,CAEA,MAAMC,GAAoBlN,EAAyB,WAAM,QAAAT,EAAArB,GAAwB,QAAxB,YAAAqB,EAA+B,UAAW,GAAE,EAE/F4N,EAAyBnN,EAA8B,IAAM,CACjE,MAAMoK,EAAU8C,GAAkB,MAClC,OAAI9C,EAAQ,SAAW,EAAU,KAC1BA,EAAQ,KAAM9H,GAAWD,EAAcC,CAAM,IAAMnE,GAA0B,KAAK,GAAKiM,EAAQ,CAAC,CACzG,CAAC,EAED,SAASgD,GAAwB9K,EAA8B,OAE7D,MAAM+K,IAAY9N,GADC+C,EAAO,aAAeA,EAAO,MACnB,MAAM,GAAG,EAAE,QAAtB,YAAA/C,EAA6B,gBAAiB,GAChE,OAAO6E,GAAsBiJ,CAAS,GAAKA,GAAa,EAC1D,CAEA,SAASC,GAAyBhL,EAA+B,CAC/D,OAAOA,EAAO,YAAc,UAAY,2EAA2E,KAAKA,EAAO,IAAI,CACrI,CAEA,SAASiL,GAAwBjL,EAAwC,CACvE,MAAMvD,EAAauD,EAAO,KAAK,QAAQ,QAAS;AAAA,CAAI,EAC9CkL,EAAQzO,EAAW,OAAS,EAAIA,EAAW,MAAM;AAAA,CAAI,EAAI,GAC/D,OAAIyO,EAAM,OAAS,GAAKA,EAAMA,EAAM,OAAS,CAAC,IAAM,IAClDA,EAAM,MAEDA,EAAM,IAAI,CAACtO,EAAMe,KAAW,CACjC,IAAK,GAAGoC,EAAcC,CAAM,CAAC,cAAcrC,CAAK,GAChD,KAAMqC,EAAO,YAAc,SAAW,SAAW,MACjD,QAASA,EAAO,YAAc,SAAWrC,EAAQ,EAAI,KACrD,QAASqC,EAAO,YAAc,SAAW,KAAOrC,EAAQ,EACxD,KAAMf,CAAA,EACN,CACJ,CAEA,SAASuO,GAAsBnL,EAAwC,CACrE,MAAMvD,EAAauD,EAAO,KAAK,QAAQ,QAAS;AAAA,CAAI,EAC9CkL,EAAQzO,EAAW,OAAS,EAAIA,EAAW,MAAM;AAAA,CAAI,EAAI,GAC3DyO,EAAM,OAAS,GAAKA,EAAMA,EAAM,OAAS,CAAC,IAAM,IAClDA,EAAM,MAGR,MAAME,EAA2B,GACjC,IAAIC,EAAU,EACVC,EAAU,EAEd,SAAW,CAAC3N,EAAOf,CAAI,IAAKsO,EAAM,UAAW,CAC3C,MAAMK,EAAY3O,EAAK,MAAM,gDAAgD,EAC7E,GAAI2O,EAAW,CACbF,EAAU,OAAOE,EAAU,CAAC,CAAC,EAC7BD,EAAU,OAAOC,EAAU,CAAC,CAAC,EAC7BH,EAAO,KAAK,CACV,IAAK,GAAGrL,EAAcC,CAAM,CAAC,SAASrC,CAAK,GAC3C,KAAM,OACN,QAAS,KACT,QAAS,KACT,KAAMf,CAAA,CACP,EACD,QACF,CAEA,GAAIA,EAAK,WAAW,GAAG,GAAK,CAACA,EAAK,WAAW,KAAK,EAAG,CACnDwO,EAAO,KAAK,CACV,IAAK,GAAGrL,EAAcC,CAAM,CAAC,QAAQrC,CAAK,GAC1C,KAAM,MACN,QAAS,KACT,QAAA2N,EACA,KAAM1O,EAAK,MAAM,CAAC,EACnB,EACD0O,GAAW,EACX,QACF,CAEA,GAAI1O,EAAK,WAAW,GAAG,GAAK,CAACA,EAAK,WAAW,KAAK,EAAG,CACnDwO,EAAO,KAAK,CACV,IAAK,GAAGrL,EAAcC,CAAM,CAAC,WAAWrC,CAAK,GAC7C,KAAM,SACN,QAAA0N,EACA,QAAS,KACT,KAAMzO,EAAK,MAAM,CAAC,EACnB,EACDyO,GAAW,EACX,QACF,CAEA,GAAIzO,EAAK,WAAW,GAAG,EAAG,CACxBwO,EAAO,KAAK,CACV,IAAK,GAAGrL,EAAcC,CAAM,CAAC,YAAYrC,CAAK,GAC9C,KAAM,UACN,QAAA0N,EACA,QAAAC,EACA,KAAM1O,EAAK,MAAM,CAAC,EACnB,EACDyO,GAAW,EACXC,GAAW,EACX,QACF,CAEAF,EAAO,KAAK,CACV,IAAK,GAAGrL,EAAcC,CAAM,CAAC,SAASrC,CAAK,GAC3C,KAAM,OACN,QAAS,KACT,QAAS,KACT,KAAMf,CAAA,CACP,CACH,CAEA,OAAOwO,CACT,CAEA,SAASI,GAAqBxL,EAA+C,CAC3E,MAAI,CAACA,GAAU,CAACA,EAAO,KAAK,OAAe,GACvCgL,GAAyBhL,CAAM,EAC1BmL,GAAsBnL,CAAM,EAE9BiL,GAAwBjL,CAAM,CACvC,CAEA,MAAMyL,GAAwB/N,EAA2B,IAAM8N,GAAqBX,EAAuB,KAAK,CAAC,EAEjH,SAASa,GAAqB1L,EAAsC,CAClE,MAAO,GAAQA,GAAA,MAAAA,EAAQ,KAAK,OAC9B,CAEA,SAAS2L,GAAiB/O,EAA8B,CACtD,OAAIA,EAAK,OAAS,MAAc,IAC5BA,EAAK,OAAS,SAAiB,IAC/BA,EAAK,OAAS,OAAe,KAC1B,EACT,CAEA,SAASgP,GAA8BpP,EAAuB,CAC5D,GAAI,OAAO,SAAa,IAAa,MAAO,GAE5C,MAAMqP,EAAW,SAAS,cAAc,UAAU,EAClDA,EAAS,MAAQrP,EACjBqP,EAAS,aAAa,WAAY,MAAM,EACxCA,EAAS,MAAM,SAAW,QAC1BA,EAAS,MAAM,KAAO,UACtBA,EAAS,MAAM,QAAU,IACzBA,EAAS,MAAM,cAAgB,OAC/B,SAAS,KAAK,YAAYA,CAAQ,EAClCA,EAAS,QACTA,EAAS,SACTA,EAAS,kBAAkB,EAAGrP,EAAK,MAAM,EAEzC,GAAI,CACF,OAAO,SAAS,YAAY,MAAM,CACpC,MAAQ,CACN,MAAO,EACT,SACE,SAAS,KAAK,YAAYqP,CAAQ,CACpC,CACF,CAEA,eAAeC,GAAapF,EAAwC,OAClE,MAAMJ,EAAUF,GAAkC,MAAMM,CAAe,GAAK,GAC5E,GAAI,CAACJ,EAAS,OAEd,IAAIyF,EAAS,GACb,GAAI,OAAO,UAAc,OAAe9O,EAAA,UAAU,YAAV,MAAAA,EAAqB,WAC3D,GAAI,CACF,MAAM,UAAU,UAAU,UAAUqJ,CAAO,EAC3CyF,EAAS,EACX,MAAQ,CACNA,EAAS,EACX,CAGGA,IACHA,EAASH,GAA8BtF,CAAO,GAG3CyF,IAELpK,EAAuB,MAAQ+E,EAC3BxE,IACF,aAAaA,EAAuB,EAEtCA,GAA0B,WAAW,IAAM,CACrCP,EAAuB,QAAU+E,IACnC/E,EAAuB,MAAQ,IAEjCO,GAA0B,IAC5B,EAAG,IAAI,EACT,CAEA,SAAS8J,GAAatF,EAA+B,CACnD,MAAMuF,EAAYnF,GAA4B,MAAMJ,CAAe,EAC/D,OAAOuF,GAAc,UACpBrO,EAAM,gBACX0D,GAAK,aAAc,CACjB,SAAU1D,EAAM,eAChB,UAAAqO,CAAA,CACD,CACH,CAEA,MAAMC,GAA2BxO,EAAiC,IAAM,CACtE,MAAMqJ,MAAmB,IAEzB,UAAW3J,KAAWQ,EAAM,SAAU,CACpC,GAAI,CAACJ,GAA2BJ,CAAO,GAAK,OAAOA,EAAQ,WAAc,SAAU,SACnF,MAAM+O,EAAS,OAAO/O,EAAQ,QAAW,UAAYA,EAAQ,OAAO,OAAS,EAAIA,EAAQ,OAAS,GAClG,GAAI,CAAC+O,EAAQ,SAEb,MAAM5F,EAAc,QAAQnJ,EAAQ,SAAS,GACvCoJ,EAAWO,EAAa,IAAIR,CAAW,EAC7C,GAAIC,EAAU,CACZA,EAAS,gBAAkBpJ,EAAQ,GACnCoJ,EAAS,OAAS2F,EAClB,QACF,CACApF,EAAa,IAAIR,EAAa,CAAE,gBAAiBnJ,EAAQ,GAAI,OAAA+O,EAAQ,CACvE,CAEA,MAAMnO,EAA+B,GACrC,UAAWoO,KAASrF,EAAa,SAC/B/I,EAAKoO,EAAM,eAAe,EAAIA,EAAM,OAEtC,OAAOpO,CACT,CAAC,EAED,SAASqO,GAAmBjP,EAA6B,CACvD,OAAO,OAAO8O,GAAyB,MAAM9O,EAAQ,EAAE,GAAM,QAC/D,CAEA,SAASkP,GAAiB5F,EAA+B,CACvD,MAAMyF,EAASD,GAAyB,MAAMxF,CAAe,EACxDyF,GACL7K,GAAK,WAAY,CAAE,OAAA6K,EAAQ,CAC7B,CAEA,SAASI,GAAsB/P,EAA+B,CAC5D,MAAMgQ,EAA4B,GAC5BC,EAAU,sUAChB,IAAIC,EAAS,EAEb,UAAW5P,KAASN,EAAK,SAASiQ,CAAO,EAAG,CAC1C,GAAI,OAAO3P,EAAM,OAAU,SAAU,SACrC,MAAM6P,EAAQ7P,EAAM,MACd8P,EAAMD,EAAQ7P,EAAM,CAAC,EAAE,OAEzB6P,EAAQD,GACVF,EAAS,KAAK,CAAE,KAAM,OAAQ,MAAOhQ,EAAK,MAAMkQ,EAAQC,CAAK,EAAG,EAGlE,IAAIE,EAAQ/P,EAAM,CAAC,EACfgQ,EAAsB,GAC1B,KAAO,oBAAoB,KAAKD,CAAK,GACnCC,EAAsBD,EAAM,MAAM,EAAE,EAAIC,EACxCD,EAAQA,EAAM,MAAM,EAAG,EAAE,EAE3B,MAAME,EAAUtI,GAAiBoI,CAAK,EACtCA,EAAQE,EAAQ,KAChB,MAAMlI,EAAUkI,EAAQ,QAClBjI,EAAWiI,EAAQ,SAAWD,EAMpC,GAJIjI,GACF2H,EAAS,KAAK,CAAE,KAAM,OAAQ,MAAO3H,EAAS,EAG5CgI,EAAM,WAAW,IAAI,GAAKA,EAAM,SAAS,IAAI,GAAKA,EAAM,OAAS,EACnEL,EAAS,KAAK,CAAE,KAAM,OAAQ,MAAOK,EAAM,MAAM,EAAG,EAAE,EAAG,EACrD/H,GACF0H,EAAS,KAAK,CAAE,KAAM,OAAQ,MAAO1H,EAAU,UAExC,gBAAgB,KAAK+H,CAAK,EACnCL,EAAS,KAAK,CAAE,KAAM,MAAO,MAAOK,EAAO,KAAMA,EAAO,EACpD/H,GACF0H,EAAS,KAAK,CAAE,KAAM,OAAQ,MAAO1H,EAAU,MAE5C,CACL,MAAMvJ,EAAMiJ,GAAmBqI,CAAK,EAChCtR,GACFiR,EAAS,KAAK,CACZ,KAAM,OACN,MAAOK,EACP,KAAMtR,EAAI,KACV,YAAasR,EACb,aAAc1J,GAAY5H,EAAI,IAAI,EACnC,EACGuJ,GACF0H,EAAS,KAAK,CAAE,KAAM,OAAQ,MAAO1H,EAAU,GAGjD0H,EAAS,KAAK,CAAE,KAAM,OAAQ,MAAO1P,EAAM,CAAC,EAAG,CAEnD,CAEA4P,EAASE,CACX,CAEA,OAAIF,EAASlQ,EAAK,QAChBgQ,EAAS,KAAK,CAAE,KAAM,OAAQ,MAAOhQ,EAAK,MAAMkQ,CAAM,EAAG,EAGpDM,GAA2BR,CAAQ,CAC5C,CAEA,SAASS,GACPT,EACAU,EAKiB,CACjB,MAAM9B,EAA0B,GAChC,IAAI+B,EAAS,GACTC,EAAS,GAEb,MAAMC,EAAYtK,GAAwB,CACnCA,GACLqI,EAAO,KAAK,CAAE,KAAM,OAAQ,MAAArI,EAAO,CACrC,EAEA,UAAWuK,KAAWd,EAAU,CAC9B,GAAIc,EAAQ,OAAS,OAAQ,CACvBH,IACFE,EAAS,GAAGH,EAAQ,MAAM,GAAGE,CAAM,EAAE,EACrCD,EAAS,GACTC,EAAS,IAEXhC,EAAO,KAAKkC,CAAO,EACnB,QACF,CAEA,IAAIC,EAAYD,EAAQ,MACxB,KAAOC,EAAU,OAAS,GAAG,CAC3B,MAAMC,EAAcD,EAAU,QAAQL,EAAQ,MAAM,EACpD,GAAIM,EAAc,EAAG,CACfL,EAAQC,GAAUG,IACRA,CAAS,EACvB,KACF,CAEA,MAAME,EAASF,EAAU,MAAM,EAAGC,CAAW,EAK7C,GAJIL,EAAQC,GAAUK,IACRA,CAAM,EAEpBF,EAAYA,EAAU,MAAMC,EAAcN,EAAQ,OAAO,MAAM,EAC3DC,EAAQ,CACV,MAAM7G,EAAU8G,EAEd9G,EAAQ,OAAS,IAChB,CAAA4G,EAAQ,gBAAiBA,EAAQ,eAAe5G,CAAO,GAExD8E,EAAO,KAAK,CAAE,KAAM8B,EAAQ,KAAM,MAAO5G,EAAS,EAElD+G,EAAS,GAAGH,EAAQ,MAAM,GAAG5G,CAAO,GAAG4G,EAAQ,MAAM,EAAE,EAEzDE,EAAS,GACTD,EAAS,EACX,MACEA,EAAS,EAEb,CACF,CAEA,OAAIA,GACFE,EAAS,GAAGH,EAAQ,MAAM,GAAGE,CAAM,EAAE,EAGhChC,CACT,CAEA,SAAS4B,GAA2BR,EAA4C,CAC9E,MAAMkB,EAAwB3K,GAC5BA,EAAM,OAAO,OAAS,GACtB,CAAC,OAAO,KAAKA,CAAK,GAClB,CAAC,OAAO,KAAKA,CAAK,EAGpB,IAAI/E,EAAOiP,GAAwCT,EAAU,CAC3D,OAAQ,KACR,KAAM,OACN,eAAgBkB,CAAA,CACjB,EAED,OAAA1P,EAAOiP,GAAwCjP,EAAM,CACnD,OAAQ,KACR,KAAM,gBACN,eAAgB0P,CAAA,CACjB,EAED1P,EAAOiP,GAAwCjP,EAAM,CACnD,OAAQ,IACR,KAAM,SACN,eAAgB0P,CAAA,CACjB,EAEM1P,CACT,CAEA,SAAS2P,GAAoBnR,EAA+B,CAC1D,MAAMgQ,EAA4B,GAClC,IAAIE,EAAS,EACTkB,EAAW,EAEf,MAAMC,EAAuB,CAC3BjN,EACAkN,IACyD,CACzD,IAAIC,EAAYnN,EAAO,QAAQ,IAAKkN,CAAS,EAC7C,KAAOC,GAAa,GAAG,CACrB,MAAMC,EAAWpN,EAAO,QAAQ,IAAKmN,EAAY,CAAC,EAClD,GAAIC,EAAW,EAAG,OAAO,KACzB,GAAIpN,EAAOoN,EAAW,CAAC,IAAM,IAAK,CAChCD,EAAYnN,EAAO,QAAQ,IAAKmN,EAAY,CAAC,EAC7C,QACF,CAEA,IAAIE,EAAQ,EACRtQ,EAAQqQ,EAAW,EACnBE,EAAa,GACjB,KAAOvQ,EAAQiD,EAAO,QAAQ,CAC5B,MAAMuN,EAAOvN,EAAOjD,CAAK,EACzB,GAAIwQ,IAAS;AAAA,EAAM,CACjBD,EAAa,GACb,KACF,CAEA,GADIC,IAAS,MAAKF,GAAS,GACvBE,IAAS,MACXF,GAAS,EACLA,IAAU,GAAG,CACf,MAAMpB,EAAQjM,EAAO,MAAMmN,EAAWpQ,EAAQ,CAAC,EAC/C,GAAIoH,GAAuB8H,CAAK,EAC9B,MAAO,CAAE,MAAOkB,EAAW,IAAKpQ,EAAQ,EAAG,MAAAkP,CAAA,EAE7C,KACF,CAEFlP,GAAS,CACX,CAEA,GAAIuQ,EAAY,CACdH,EAAYnN,EAAO,QAAQ,IAAKmN,EAAY,CAAC,EAC7C,QACF,CACAA,EAAYnN,EAAO,QAAQ,IAAKmN,EAAY,CAAC,CAC/C,CACA,OAAO,IACT,EAEA,KAAOH,EAAWpR,EAAK,QAAQ,CAC7B,MAAMM,EAAQ+Q,EAAqBrR,EAAMoR,CAAQ,EACjD,GAAI,CAAC9Q,EAAO,MACZ,KAAM,CAAE,MAAA6P,EAAO,IAAAC,EAAK,MAAAC,CAAA,EAAU/P,EAE1B6P,EAAQD,GACVF,EAAS,KAAK,GAAGD,GAAsB/P,EAAK,MAAMkQ,EAAQC,CAAK,CAAC,CAAC,EAGnE,MAAMyB,EAAgBrJ,GAAuB8H,CAAK,EAClD,GAAI,CAACuB,EAAe,CAClB5B,EAAS,KAAK,GAAGD,GAAsB/P,EAAK,MAAMmQ,EAAOC,CAAG,CAAC,CAAC,EAC9DF,EAASE,EACTgB,EAAWhB,EACX,QACF,CACA,MAAMzH,EAAQiJ,EAAc,MACtBhJ,EAASgJ,EAAc,OAE7B,GAAI,gBAAgB,KAAKhJ,CAAM,EAC7BoH,EAAS,KAAK,CAAE,KAAM,MAAO,MAAOrH,GAASC,EAAQ,KAAMA,EAAQ,MAC9D,CACL,MAAM7J,EAAMiJ,GAAmBY,CAAM,EACjC7J,EACFiR,EAAS,KAAK,CACZ,KAAM,OACN,MAAOpH,EACP,KAAM7J,EAAI,KACV,YAAa4J,GAASC,EACtB,aAAcjC,GAAY5H,EAAI,IAAI,EACnC,EAEDiR,EAAS,KAAK,CAAE,KAAM,OAAQ,MAAOK,EAAO,CAEhD,CAEAH,EAASE,EACTgB,EAAWhB,CACb,CAEA,OAAIF,EAASlQ,EAAK,QAChBgQ,EAAS,KAAK,GAAGD,GAAsB/P,EAAK,MAAMkQ,CAAM,CAAC,CAAC,EAGrDF,CACT,CAEA,SAAS6B,EAAoB7R,EAA+B,CAC1D,GAAIA,EAAK,SAAS,IAAI,EAAG,CACvB,MAAM8R,EAAoBX,GAAoBnR,CAAI,EAClD,GAAI8R,EAAkB,KAAMhB,GAAYA,EAAQ,OAAS,QAAUA,EAAQ,OAAS,KAAK,EACvF,OAAOgB,CAEX,CAEA,GAAI,CAAC9R,EAAK,SAAS,GAAG,EAAG,OAAOmR,GAAoBnR,CAAI,EAExD,MAAMgQ,EAA4B,GAClC,IAAIE,EAAS,EACT6B,EAAY,EAEhB,KAAO7B,EAASlQ,EAAK,QAAQ,CAC3B,GAAIA,EAAKkQ,CAAM,IAAM,IAAK,CACxBA,GAAU,EACV,QACF,CAEA,IAAI8B,EAAa,EACjB,KAAO9B,EAAS8B,EAAahS,EAAK,QAAUA,EAAKkQ,EAAS8B,CAAU,IAAM,KACxEA,GAAc,EAEhB,MAAMC,EAAY,IAAI,OAAOD,CAAU,EAEvC,IAAIE,EAAahC,EAAS8B,EACtBG,EAAe,GACnB,KAAOD,EAAalS,EAAK,QAAQ,CAC/B,MAAMoS,EAAYpS,EAAK,QAAQiS,EAAWC,CAAU,EACpD,GAAIE,EAAY,EAAG,MAEnB,MAAMC,EAAoBD,EAAY,GAAKpS,EAAKoS,EAAY,CAAC,IAAM,IAC7DE,EACJF,EAAYJ,EAAahS,EAAK,QAAUA,EAAKoS,EAAYJ,CAAU,IAAM,IACrEO,EAAmBvS,EAAK,MAAMkQ,EAAS8B,EAAYI,CAAS,EAAE,SAAS;AAAA,CAAI,EAEjF,GAAI,CAACC,GAAqB,CAACC,GAAoB,CAACC,EAAkB,CAChEJ,EAAeC,EACf,KACF,CACAF,EAAaE,EAAY,CAC3B,CAEA,GAAID,EAAe,EAAG,CACpBjC,GAAU8B,EACV,QACF,CAEI9B,EAAS6B,GACX/B,EAAS,KAAK,GAAGmB,GAAoBnR,EAAK,MAAM+R,EAAW7B,CAAM,CAAC,CAAC,EAGrE,MAAMG,EAAQrQ,EAAK,MAAMkQ,EAAS8B,EAAYG,CAAY,EAC1D,GAAI9B,EAAM,OAAS,EAAG,CACpB,MAAMmC,EAAejK,GAAuB8H,CAAK,EACjD,GAAImC,EACF,GAAI,gBAAgB,KAAKA,EAAa,MAAM,EAC1CxC,EAAS,KAAK,CACZ,KAAM,MACN,MAAOwC,EAAa,OAASA,EAAa,OAC1C,KAAMA,EAAa,OACpB,MACI,CACL,MAAMC,EAAwBzK,GAAmBwK,EAAa,MAAM,EAChEC,EACFzC,EAAS,KAAK,CACZ,KAAM,OACN,MAAOwC,EAAa,OACpB,KAAMC,EAAsB,KAC5B,YAAaD,EAAa,OAASA,EAAa,OAChD,aAAc7L,GAAY8L,EAAsB,IAAI,EACrD,EAEDzC,EAAS,KAAK,CAAE,KAAM,OAAQ,MAAOK,EAAO,CAEhD,SACS,uBAAuB,KAAKA,CAAK,EAC1CL,EAAS,KAAK,CACZ,KAAM,MACN,MAAOK,EACP,KAAMA,CAAA,CACP,MACI,CACL,MAAMqC,EAAgB1K,GAAmBqI,CAAK,EAC9C,GAAIqC,EAAe,CACjB,MAAMC,EAAcD,EAAc,KAC9B,GAAGA,EAAc,IAAI,IAAI,OAAOA,EAAc,IAAI,CAAC,GACnDA,EAAc,KAClB1C,EAAS,KAAK,CACZ,KAAM,OACN,MAAOK,EACP,KAAMqC,EAAc,KACpB,YAAAC,EACA,aAAchM,GAAY+L,EAAc,IAAI,EAC7C,CACH,MACE1C,EAAS,KAAK,CAAE,KAAM,OAAQ,MAAOK,EAAO,CAEhD,CACF,MACEL,EAAS,KAAK,CAAE,KAAM,OAAQ,MAAO,GAAGiC,CAAS,GAAGA,CAAS,GAAI,EAGnE/B,EAASiC,EAAeH,EACxBD,EAAY7B,CACd,CAEA,OAAI6B,EAAY/R,EAAK,QACnBgQ,EAAS,KAAK,GAAGmB,GAAoBnR,EAAK,MAAM+R,CAAS,CAAC,CAAC,EAGtD/B,CACT,CAEA,SAAS4C,GAAqBrM,EAAuB,CACnD,MAAMtG,EAAasG,EAAM,OACzB,GAAI,CAACtG,EAAY,MAAO,GACxB,GACEA,EAAW,WAAW,OAAO,GAC7BA,EAAW,WAAW,OAAO,GAC7BA,EAAW,WAAW,SAAS,GAC/BA,EAAW,WAAW,UAAU,GAChCA,EAAW,WAAW,qBAAqB,EAE3C,OAAOA,EAGT,GAAIA,EAAW,WAAW,SAAS,EACjC,MAAO,2BAA2B,mBAAmBA,CAAU,CAAC,GAGlE,MAAMuG,EAAwBvG,EAAW,WAAW,GAAG,EACjDwG,EAA2B,mBAAmB,KAAKxG,CAAU,EACnE,OAAIuG,GAAyBC,EACpB,2BAA2B,mBAAmBxG,CAAU,CAAC,GAG3DA,CACT,CAEA,SAAS4S,EAAYjM,EAA2B,CAC9C,MAAM3G,EAAa2G,EAAU,OAC7B,GAAI,CAAC3G,EAAY,MAAO,IACxB,MAAM6S,EAAyBV,GAC7BA,EAAU,WAAW,GAAG,GAAK,mBAAmB,KAAKA,CAAS,EAG1DW,EAAS/K,GAAmB/H,CAAU,EACtC+S,GAAgBD,GAAA,YAAAA,EAAQ,OAAQ9S,EAChC6N,EAAWlG,GAAoBoL,EAAe5R,EAAM,GAAG,EAE7D,GAAI0R,EAAsBhF,CAAQ,EAAG,CACnC,MAAME,EAAqBF,EAAS,WAAW,GAAG,EAAIA,EAAW,IAAIA,CAAQ,GAC7E,MAAO,sBAAsB,UAAUE,CAAkB,CAAC,EAC5D,CAEA,MAAO,GACT,CAEA,MAAMiF,GAA2B/R,EAAS,KAAO,CAC/C,KAAM,GAAG,OAAOzB,GAAqB,KAAK,CAAC,KAC3C,IAAK,GAAG,OAAOC,GAAqB,KAAK,CAAC,MAC1C,EAEF,SAASwT,GAAwBC,EAAsB,CACrD,MAAMC,EAAiBD,EAAK,OAC5B,GAAI,CAACC,EAAgB,MAAO,GAC5B,GAAI,CACF,MAAMtF,EAAW,IAAI,IAAIsF,EAAgB,OAAO,SAAS,IAAI,EAC7D,OAAKtF,EAAS,SAAS,WAAW,qBAAqB,EAEhD,GADU,oBAAoBA,EAAS,SAAS,MAAM,EAA4B,CAAC,EACxE,GAAGA,EAAS,MAAM,GAAGA,EAAS,IAAI,GAFa,EAGnE,MAAQ,CACN,MAAO,EACT,CACF,CAEA,SAASuF,GAA0BC,EAAyB,CAC1D,MAAM1K,EAAS0K,EAAM,OACrB,GAAI,EAAE1K,aAAkB,SAAU,OAElC,MAAM2K,EAAS3K,EAAO,QAAQ,qBAAqB,EACnD,GAAI,EAAE2K,aAAkB,mBAAoB,OAE5C,MAAMJ,GAAQI,EAAO,aAAa,MAAM,GAAK,IAAI,OAC7C,CAACJ,GAAQA,IAAS,MAEtBG,EAAM,iBACNA,EAAM,kBAEN3T,GAAyB,MAAQwT,EACjCvT,GAAuB,MAAQsT,GAAwBC,CAAI,EAC3D1T,GAAqB,MAAQ6T,EAAM,QACnC5T,GAAqB,MAAQ4T,EAAM,QACnC9T,GAA6B,MAAQ,GACvC,CAEA,SAASgU,GAAiC,CACnChU,GAA6B,QAClCA,GAA6B,MAAQ,GACvC,CAEA,SAASiU,IAAkC,CACzC,MAAMN,EAAOxT,GAAyB,MACtC6T,EAAA,EACI,GAACL,GAAQA,IAAS,MACtB,OAAO,KAAKA,EAAM,SAAU,qBAAqB,CACnD,CAEA,SAASO,IAAgC,CACvC,MAAMP,EAAOvT,GAAuB,MACpC4T,EAAA,EACI,GAACL,GAAQA,IAAS,MACtB,OAAO,KAAKA,EAAM,SAAU,qBAAqB,CACnD,CAEA,eAAeQ,IAAyC,CACtD,MAAMR,EAAOxT,GAAyB,MAEtC,GADA6T,EAAA,EACI,GAACL,GAAQA,IAAS,KAEtB,GAAI,CACF,MAAM,UAAU,UAAU,UAAUA,CAAI,CAC1C,MAAQ,CACN,MAAM9D,EAAW,SAAS,cAAc,UAAU,EAClDA,EAAS,MAAQ8D,EACjB9D,EAAS,aAAa,WAAY,MAAM,EACxCA,EAAS,MAAM,SAAW,QAC1BA,EAAS,MAAM,QAAU,IACzB,SAAS,KAAK,YAAYA,CAAQ,EAClCA,EAAS,SACT,SAAS,YAAY,MAAM,EAC3B,SAAS,KAAK,YAAYA,CAAQ,CACpC,CACF,CAEA,SAASuE,GAA0CN,EAA2B,CAC5E,GAAI,CAAC9T,GAA6B,MAAO,OACzC,MAAMqU,EAAOtU,GAAuB,MACpC,GAAI,CAACsU,EAAM,CACTL,EAAA,EACA,MACF,CACA,MAAM5K,EAAS0K,EAAM,OACjB1K,aAAkB,MAAQiL,EAAK,SAASjL,CAAM,GAClD4K,EAAA,CACF,CAEA,SAASM,IAA2C,CAClDN,EAAA,CACF,CAEA,SAASO,GAAsCT,EAA4B,CACrEA,EAAM,MAAQ,UAClBE,EAAA,CACF,CAEA,SAASQ,GAAsBhU,EAAsB,CACnD,OAAOA,EAAK,QAAQ,SAAU;AAAA,CAAI,CACpC,CAEA,SAASiU,EAAmB7T,EAAsB,OAEhD,SAD0BK,EAAAL,EAAK,MAAM,OAAO,IAAlB,YAAAK,EAAsB,KAAM,IAC7B,QAAQ,OAAQ,MAAM,EAAE,MACnD,CAEA,SAASyT,GAAqB9T,EAAc+T,EAA4B,CACtE,GAAIA,GAAc,EAAG,OAAO/T,EAAK,YAEjC,IAAIe,EAAQ,EACRiT,EAAQ,EACZ,KAAOjT,EAAQf,EAAK,QAAUgU,EAAQD,GAAY,CAChD,MAAME,EAAYjU,EAAKe,CAAK,EAC5BiT,GAASC,IAAc,IAAO,EAAI,EAClClT,GAAS,CACX,CAEA,OAAOf,EAAK,MAAMe,CAAK,CACzB,CAEA,SAASmT,EAAoBlU,EAAuB,CAClD,OAAOA,EAAK,OAAO,SAAW,CAChC,CAEA,SAASmU,GAAYnU,EAAuD,CAC1E,MAAME,EAAQF,EAAK,MAAM,2BAA2B,EACpD,OAAKE,EACE,CACL,MAAOA,EAAM,CAAC,EAAE,OAChB,MAAOA,EAAM,CAAC,EAAE,MAAK,EAHJ,IAKrB,CAEA,SAASkU,GAAmBpU,EAA6B,CACvD,MAAME,EAAQF,EAAK,MAAM,oBAAoB,EAC7C,OAAKE,EACEA,EAAM,CAAC,GAAK,GADA,IAErB,CAEA,SAASmU,GAAsBrU,EAA6B,OAC1D,MAAME,EAAQF,EAAK,MAAM,oBAAoB,EAC7C,QAAOK,EAAAH,GAAA,YAAAA,EAAQ,KAAR,YAAAG,EAAY,SAAU,IAC/B,CAEA,SAASiU,GAA2BtU,EAAuD,OACzF,MAAME,EAAQF,EAAK,MAAM,sBAAsB,EAC/C,OAAKE,EACE,CACL,OAAQ2T,EAAmB3T,EAAM,CAAC,GAAK,EAAE,EACzC,OAAMG,EAAAH,EAAM,CAAC,IAAP,YAAAG,EAAU,SAAU,IAHT,IAKrB,CAEA,SAASkU,GAAiBvU,EAAmC,OAC3D,MAAME,EAAQF,EAAK,MAAM,kCAAkC,EAC3D,OAAKE,EACE,CACL,SAAUA,EAAM,CAAC,GAAK,KAAK,gBAAkB,IAC7C,OAAMG,EAAAH,EAAM,CAAC,IAAP,YAAAG,EAAU,SAAU,IAHT,IAKrB,CAEA,SAASmU,GAAsBxU,EAA6D,OAC1F,MAAME,EAAQF,EAAK,MAAM,oCAAoC,EAC7D,OAAKE,EACE,CACL,OAAQ2T,EAAmB3T,EAAM,CAAC,GAAK,EAAE,EACzC,KAAM,CACJ,SAAUA,EAAM,CAAC,GAAK,KAAK,gBAAkB,IAC7C,OAAMG,EAAAH,EAAM,CAAC,IAAP,YAAAG,EAAU,SAAU,GAC5B,EANiB,IAQrB,CAEA,SAASoU,GAAwBzU,EAAsE,OACrG,MAAME,EAAQF,EAAK,MAAM,0BAA0B,EACnD,OAAKE,EACE,CACL,OAAQ2T,EAAmB3T,EAAM,CAAC,GAAK,EAAE,EACzC,MAAO,OAAO,SAASA,EAAM,CAAC,GAAK,IAAK,EAAE,GAAK,EAC/C,OAAMG,EAAAH,EAAM,CAAC,IAAP,YAAAG,EAAU,SAAU,IAJT,IAMrB,CAEA,SAASqU,GAAoB1U,EAA6B,OACxD,QAAOK,EAAAoU,GAAwBzU,CAAI,IAA5B,YAAAK,EAA+B,OAAQ,IAChD,CAEA,SAASsU,GAAyB3U,EAAsE,CACtG,OAAOyU,GAAwBzU,CAAI,CACrC,CAEA,SAAS4U,GAAsB5U,EAA+B,CAC5D,MAAMC,EAAUD,EAAK,OACrB,GAAI,CAACC,EAAQ,SAAS,GAAG,EAAG,OAAO,KAEnC,IAAIyJ,EAAUzJ,EACVyJ,EAAQ,WAAW,GAAG,IAAGA,EAAUA,EAAQ,MAAM,CAAC,GAClDA,EAAQ,SAAS,GAAG,MAAaA,EAAQ,MAAM,EAAG,EAAE,GAExD,MAAMmL,EAAkB,GACxB,IAAInJ,EAAU,GACVoJ,EAAkB,EAEtB,QAAS/T,EAAQ,EAAGA,EAAQ2I,EAAQ,OAAQ3I,GAAS,EAAG,CACtD,MAAMkT,EAAYvK,EAAQ3I,CAAK,EAE/B,GAAIkT,IAAc,MAAQvK,EAAQ3I,EAAQ,CAAC,IAAM,IAAK,CACpD2K,GAAW,IACX3K,GAAS,EACT,QACF,CAEA,GAAIkT,IAAc,IAAK,CACrB,IAAIc,EAAY,EAChB,KAAOrL,EAAQ3I,EAAQgU,CAAS,IAAM,KAAKA,GAAa,EACxDrJ,GAAWhC,EAAQ,MAAM3I,EAAOA,EAAQgU,CAAS,EAC7CD,IAAoB,EAAGA,EAAkBC,EACpCD,IAAoBC,IAAWD,EAAkB,GAC1D/T,GAASgU,EAAY,EACrB,QACF,CAEA,GAAId,IAAc,KAAOa,IAAoB,EAAG,CAC9CD,EAAM,KAAKnJ,EAAQ,MAAM,EACzBA,EAAU,GACV,QACF,CAEAA,GAAWuI,CACb,CAEA,OAAAY,EAAM,KAAKnJ,EAAQ,MAAM,EAClBmJ,EAAM,KAAMG,GAASA,EAAK,OAAS,CAAC,EAAIH,EAAQ,IACzD,CAEA,SAASI,GAAsBjV,EAAuC,CACpE,MAAM6U,EAAQD,GAAsB5U,CAAI,EACxC,GAAI,CAAC6U,GAASA,EAAM,SAAW,EAAG,OAAO,KAEzC,MAAMK,EAAaL,EAAM,IAAKG,GAAS,CACrC,MAAM/U,EAAU+U,EAAK,QAAQ,QAAS,EAAE,EACxC,GAAI,CAAC,eAAe,KAAK/U,CAAO,EAAG,OAAO,KAC1C,MAAMkV,EAAkBlV,EAAQ,WAAW,GAAG,EACxCmV,EAAgBnV,EAAQ,SAAS,GAAG,EAC1C,OAAIkV,GAAmBC,EAAsB,SACzCA,EAAsB,QACtBD,EAAwB,OACrB,IACT,CAAC,EAED,OAAOD,EAAW,MAAM,CAACG,EAAWtU,IAAUsU,IAAc,MAAQ,QAAQ,KAAKR,EAAM9T,CAAK,EAAE,QAAQ,QAAS,EAAE,CAAC,CAAC,EAC/GmU,EACA,IACN,CAEA,SAASI,GAAoBT,EAAiBb,EAAyB,CACrE,OAAIa,EAAM,SAAWb,EAAca,EAC/BA,EAAM,OAASb,EAAca,EAAM,MAAM,EAAGb,CAAK,EAC9C,CAAC,GAAGa,EAAO,GAAG,MAAM,KAAK,CAAE,OAAQb,EAAQa,EAAM,QAAU,IAAM,EAAE,CAAC,CAC7E,CAEA,SAASU,GAAejH,EAAiBkH,EAAqE,OAC5G,GAAIA,EAAa,GAAKlH,EAAM,OAAQ,OAAO,KAE3C,MAAMmH,EAAanH,EAAMkH,CAAU,EAC7BE,EAAgBpH,EAAMkH,EAAa,CAAC,EACpCG,EAAUf,GAAsBa,CAAU,EAC1CP,EAAaD,GAAsBS,CAAa,EAEtD,GADI,CAACC,GAAW,CAACT,GACbS,EAAQ,SAAWT,EAAW,OAAQ,OAAO,KAEjD,MAAMU,EAAgBH,EAAW,OACjC,GAAI,CAACG,EAAc,WAAW,GAAG,MAAMvV,EAAAuV,EAAc,MAAM,MAAM,IAA1B,YAAAvV,EAA6B,SAAU,GAAK,EAAG,OAAO,KAE7F,MAAM2T,EAAQ2B,EAAQ,OAChBE,EAAmB,GACzB,IAAI9U,EAAQyU,EAAa,EACzB,KAAOzU,EAAQuN,EAAM,QACf,CAAA4F,EAAoB5F,EAAMvN,CAAK,CAAC,GADT,CAE3B,MAAM+U,EAAMlB,GAAsBtG,EAAMvN,CAAK,CAAC,EAC9C,GAAI,CAAC+U,EAAK,MACVD,EAAK,KAAKP,GAAoBQ,EAAK9B,CAAK,CAAC,EACzCjT,GAAS,CACX,CAEA,MAAO,CACL,KAAM,QACN,QAASuU,GAAoBK,EAAS3B,CAAK,EAC3C,KAAA6B,EACA,WAAAX,CAAA,CAEJ,CAEA,SAASa,GAAwB/V,EAAuB,CACtD,OACEkU,EAAoBlU,CAAI,GACxBgW,GAAehW,CAAI,IAAM,MACzBiW,GAAoBjW,CAAI,GACxBmU,GAAYnU,CAAI,IAAM,MACtBoU,GAAmBpU,CAAI,IAAM,MAC7BuU,GAAiBvU,CAAI,IAAM,MAC3BqU,GAAsBrU,CAAI,IAAM,MAChC0U,GAAoB1U,CAAI,IAAM,IAElC,CAEA,SAASkW,GACP5H,EACAkH,EACAzB,EAAa,GACgC,CAC7C,MAAMoC,EAA2B,GACjC,IAAIpV,EAAQyU,EAEZ,KAAOzU,EAAQuN,EAAM,QACf,EAAAyH,GAAwBzH,EAAMvN,CAAK,CAAC,GACpCgT,GAAc,GAAKF,EAAmBvF,EAAMvN,CAAK,CAAC,GAAKgT,IAE3DoC,EAAe,KAAKpC,GAAc,EAAID,GAAqBxF,EAAMvN,CAAK,EAAGgT,EAAa,CAAC,EAAIzF,EAAMvN,CAAK,CAAC,EACvGA,GAAS,EAGX,MAAMoF,EAAQgQ,EAAe,KAAK;AAAA,CAAI,EAAE,OACxC,OAAOhQ,EAAQ,CAAE,MAAAA,EAAO,UAAWpF,GAAU,IAC/C,CAEA,SAASqV,GAA0B9H,EAAiBkH,EAA4B,CAC9E,QAASzU,EAAQyU,EAAYzU,EAAQuN,EAAM,OAAQvN,GAAS,EAC1D,GAAI,CAACmT,EAAoB5F,EAAMvN,CAAK,CAAC,EAAG,OAAOA,EAEjD,MAAO,EACT,CAEA,SAASsV,GACP/H,EACAkH,EACAc,EACAC,EAAiF,KACjFC,EAAuB,GAC+B,CACtD,MAAMC,EAAwB,GAC9B,IAAI1V,EAAQyU,EAEZ,KAAOzU,EAAQuN,EAAM,QAAQ,CAC3B,MAAMtO,EAAOsO,EAAMvN,CAAK,EACxB,GAAImT,EAAoBlU,CAAI,EAAG,CAC7B,MAAM0W,EAAoBN,GAA0B9H,EAAOvN,EAAQ,CAAC,EACpE,GAAI2V,IAAsB,GAAI,CAC5BD,EAAY,KAAK,EAAE,EACnB1V,EAAQuN,EAAM,OACd,KACF,CACA,MAAMqI,EAAeJ,GAAA,YAAAA,EAAajI,EAAMoI,CAAiB,GAEzD,GADIC,GAAgBA,EAAa,SAAWL,GACxCzC,EAAmBvF,EAAMoI,CAAiB,CAAC,GAAKJ,EAAc,MAClEG,EAAY,KAAK,EAAE,EACnB1V,GAAS,EACT,QACF,CAEA,MAAM6V,EAAWL,GAAA,YAAAA,EAAavW,GAC9B,GAAI4W,GAAYA,EAAS,SAAWN,EAAc,MAElD,MAAMO,EAAahD,EAAmB7T,CAAI,EACpC8W,EAAmBN,IACvBjC,GAAiBvU,CAAI,IAAM,MAC3BqU,GAAsBrU,CAAI,IAAM,MAElC,GAAI6W,GAAcP,GAAgB,CAACQ,EAAkB,MAErDL,EAAY,KACVI,EAAaP,EACTxC,GAAqB9T,EAAMsW,EAAe,CAAC,EAC3CtW,EAAK,WAAU,EAErBe,GAAS,CACX,CAEA,KAAO0V,EAAY,OAAS,GAAKvC,EAAoBuC,EAAY,CAAC,CAAC,GAAGA,EAAY,QAClF,KAAOA,EAAY,OAAS,GAAKvC,EAAoBuC,EAAYA,EAAY,OAAS,CAAC,CAAC,GAAGA,EAAY,MAEvG,OAAIA,EAAY,SAAW,EAAU,KAE9B,CACL,OAAQM,GAAgBN,EAAY,KAAK;AAAA,CAAI,CAAC,EAC9C,UAAW1V,CAAA,CAEf,CAEA,SAASiW,GACP1I,EACAkH,EACAyB,EACAT,EAAuB,GAC0B,CACjD,MAAMU,EAAoB,GAC1B,IAAInW,EAAQyU,EACZ,MAAM2B,EAAYF,EAAS3I,EAAMkH,CAAU,CAAC,EAC5C,GAAI,CAAC2B,EAAW,OAAO,KACvB,MAAMpD,EAAaoD,EAAU,OAE7B,KAAOpW,EAAQuN,EAAM,QAAQ,CAC3B,MAAM8I,EAAYH,EAAS3I,EAAMvN,CAAK,CAAC,EACvC,GAAIqW,IAAc,MAAQA,EAAU,SAAWrD,EAAY,MAE3D,MAAMsD,EAAa,CAACD,EAAU,IAAI,EAC5BE,EAA2B,GAGjC,IAFAvW,GAAS,EAEFA,EAAQuN,EAAM,QAAQ,CAC3B,GAAI4F,EAAoB5F,EAAMvN,CAAK,CAAC,EAAG,CACrC,MAAM2V,EAAoBN,GAA0B9H,EAAOvN,EAAQ,CAAC,EACpE,GAAI2V,IAAsB,GAAI,CAC5B3V,EAAQuN,EAAM,OACd,KACF,CACA,MAAMiJ,EAAoBN,EAAS3I,EAAMoI,CAAiB,CAAC,EAC3D,GAAIa,GAAqBA,EAAkB,SAAWxD,EAAY,CAChEhT,EAAQ2V,EACR,KACF,CACA,GAAI7C,EAAmBvF,EAAMoI,CAAiB,CAAC,GAAK3C,EAAY,CAC9DhT,EAAQ2V,EACR,KACF,CACA3V,GAAS,EACT,QACF,CAEA,MAAMwW,EAAoBN,EAAS3I,EAAMvN,CAAK,CAAC,EAC/C,GAAIwW,GAAqBA,EAAkB,SAAWxD,EAAY,MAElE,MAAMyD,EAAsB3D,EAAmBvF,EAAMvN,CAAK,CAAC,EAAIgT,EACzD0D,EAAoBjB,IACxBjC,GAAiBjG,EAAMvN,CAAK,CAAC,IAAM,MACnCsT,GAAsB/F,EAAMvN,CAAK,CAAC,IAAM,MAE1C,GAAIyW,GAAuBC,EAAmB,CAC5C,MAAMC,EAAerB,GAAqB/H,EAAOvN,EAAOgT,EAAYkD,EAAUT,CAAoB,EAClG,GAAIkB,EAAc,CAChBJ,EAAS,KAAK,GAAGI,EAAa,MAAM,EACpC3W,EAAQ2W,EAAa,UACrB,QACF,CACF,CAEA,GAAI7D,EAAmBvF,EAAMvN,CAAK,CAAC,GAAKgT,EAAY,MAEpD,MAAM4D,EAAezB,GAAkB5H,EAAOvN,EAAOgT,CAAU,EAC/D,GAAI,CAAC4D,EAAc,MACnBN,EAAW,KAAKM,EAAa,KAAK,EAClC5W,EAAQ4W,EAAa,SACvB,CAEAT,EAAM,KAAKI,EAAS,OAAS,EAAI,CAAE,WAAAD,EAAY,SAAAC,CAAA,EAAa,CAAE,WAAAD,EAAY,CAC5E,CAEA,OAAOH,EAAM,OAAS,EAAI,CAAE,MAAAA,EAAO,UAAWnW,GAAU,IAC1D,CAEA,SAASkV,GAAoBjW,EAAuB,CAClD,MAAO,sCAAsC,KAAKA,EAAK,MAAM,CAC/D,CAEA,SAASgW,GAAehW,EAA2D,CACjF,MAAME,EAAQF,EAAK,MAAM,4CAA4C,EACrE,OAAKE,EACE,CACL,OAAQA,EAAM,CAAC,EACf,UAAWA,EAAM,CAAC,GAAK,IAAI,MAAK,EAHf,IAKrB,CAEA,SAAS6W,GAAgBnX,EAA8B,OAErD,MAAM0O,EADiBsF,GAAsBhU,CAAI,EACpB,MAAM;AAAA,CAAI,EACjCgY,EAAyB,GAC/B,IAAI7W,EAAQ,EAEZ,KAAOA,EAAQuN,EAAM,QAAQ,CAC3B,GAAI4F,EAAoB5F,EAAMvN,CAAK,CAAC,EAAG,CACrCA,GAAS,EACT,QACF,CAEA,MAAM8W,EAAQ7B,GAAe1H,EAAMvN,CAAK,CAAC,EACzC,GAAI8W,EAAO,CACT9W,GAAS,EACT,MAAM+W,EAAsB,GAC5B,KAAO/W,EAAQuN,EAAM,QAAQ,CAC3B,GAAIA,EAAMvN,CAAK,EAAE,SAAW8W,EAAM,OAAQ,CACxC9W,GAAS,EACT,KACF,CACA+W,EAAU,KAAKxJ,EAAMvN,CAAK,CAAC,EAC3BA,GAAS,CACX,CACA6W,EAAO,KAAK,CACV,KAAM,YACN,SAAUC,EAAM,SAChB,MAAOC,EAAU,KAAK;AAAA,CAAI,EAC3B,EACD,QACF,CAEA,GAAI7B,GAAoB3H,EAAMvN,CAAK,CAAC,EAAG,CACrC6W,EAAO,KAAK,CAAE,KAAM,gBAAiB,EACrC7W,GAAS,EACT,QACF,CAEA,MAAMgX,EAAU5D,GAAY7F,EAAMvN,CAAK,CAAC,EACxC,GAAIgX,EAAS,CACXH,EAAO,KAAK,CAAE,KAAM,UAAW,MAAOG,EAAQ,MAAO,MAAOA,EAAQ,MAAO,EAC3EhX,GAAS,EACT,QACF,CAGA,GADkBqT,GAAmB9F,EAAMvN,CAAK,CAAC,IAC/B,KAAM,CACtB,MAAMiX,EAAuB,GAC7B,KAAOjX,EAAQuN,EAAM,QAAQ,CAC3B,MAAM2J,EAAgB7D,GAAmB9F,EAAMvN,CAAK,CAAC,EACrD,GAAIkX,IAAkB,KAAM,MAC5BD,EAAW,KAAKC,CAAa,EAC7BlX,GAAS,CACX,CACA6W,EAAO,KAAK,CAAE,KAAM,aAAc,MAAOI,EAAW,KAAK;AAAA,CAAI,EAAE,MAAK,CAAG,EACvE,QACF,CAEA,MAAME,EAAQ3C,GAAejH,EAAOvN,CAAK,EACzC,GAAImX,EAAO,CACTN,EAAO,KAAKM,CAAK,EACjBnX,GAAS,EAAImX,EAAM,KAAK,OACxB,QACF,CAGA,GADiB3D,GAAiBjG,EAAMvN,CAAK,CAAC,IAC7B,KAAM,CACrB,MAAMmW,EAAwB,GACxBnD,IAAa1T,EAAAmU,GAAsBlG,EAAMvN,CAAK,CAAC,IAAlC,YAAAV,EAAqC,SAAU,EAClE,KAAOU,EAAQuN,EAAM,QAAQ,CAC3B,MAAM6J,GAAW3D,GAAsBlG,EAAMvN,CAAK,CAAC,EACnD,GAAIoX,KAAa,MAAQA,GAAS,SAAWpE,EAAY,MACzDmD,EAAM,KAAKiB,GAAS,IAAI,EACxBpX,GAAS,CACX,CACA,GAAImW,EAAM,OAAS,EAAG,CACpBU,EAAO,KAAK,CAAE,KAAM,WAAY,MAAAV,EAAO,EACvC,QACF,CACF,CAEA,MAAMkB,EAAgB/D,GAAsB/F,EAAMvN,CAAK,CAAC,EACxD,GAAIqX,IAAkB,KAAM,CAC1B,MAAMC,EAAarB,GAAc1I,EAAOvN,EAAOuT,EAA0B,EACzE,GAAI+D,EAAY,CACdT,EAAO,KAAK,CAAE,KAAM,gBAAiB,MAAOS,EAAW,MAAO,EAC9DtX,EAAQsX,EAAW,UACnB,QACF,CACA,GAAID,EAAc,OAAS,EAAG,CAC5BR,EAAO,KAAK,CAAE,KAAM,gBAAiB,MAAO,CAAC,CAAE,WAAY,CAACQ,CAAa,EAAG,EAAG,EAC/ErX,GAAS,EACT,QACF,CACF,CAEA,MAAMuX,EAAc5D,GAAoBpG,EAAMvN,CAAK,CAAC,EACpD,GAAIuX,IAAgB,KAAM,CACxB,MAAMC,EAAmB5D,GAAyBrG,EAAMvN,CAAK,CAAC,EACxDsX,EAAarB,GAAc1I,EAAOvN,EAAO4T,GAA0B,EAAI,EAC7E,GAAI0D,EAAY,CACdT,EAAO,KAAK,CACV,KAAM,cACN,MAAOS,EAAW,MAClB,OAAOE,GAAA,YAAAA,EAAkB,QAAS,EACnC,EACDxX,EAAQsX,EAAW,UACnB,QACF,CACA,GAAIC,EAAY,OAAS,EAAG,CAC1BV,EAAO,KAAK,CACV,KAAM,cACN,MAAO,CAAC,CAAE,WAAY,CAACU,CAAW,EAAG,EACrC,OAAOC,GAAA,YAAAA,EAAkB,QAAS,EACnC,EACDxX,GAAS,EACT,QACF,CACF,CAEA,MAAMoV,EAA2B,GACjC,KAAOpV,EAAQuN,EAAM,QACf,EAAA4F,EAAoB5F,EAAMvN,CAAK,CAAC,GAElCiV,GAAe1H,EAAMvN,CAAK,CAAC,GAC3BkV,GAAoB3H,EAAMvN,CAAK,CAAC,GAChCoT,GAAY7F,EAAMvN,CAAK,CAAC,GACxBwU,GAAejH,EAAOvN,CAAK,GAC3BqT,GAAmB9F,EAAMvN,CAAK,CAAC,IAAM,MACrCwT,GAAiBjG,EAAMvN,CAAK,CAAC,IAAM,MACnCsT,GAAsB/F,EAAMvN,CAAK,CAAC,IAAM,MACxC2T,GAAoBpG,EAAMvN,CAAK,CAAC,IAAM,OAExCoV,EAAe,KAAK7H,EAAMvN,CAAK,CAAC,EAChCA,GAAS,EAGX,MAAMoF,EAAQgQ,EAAe,KAAK;AAAA,CAAI,EAAE,OACpChQ,GACFyR,EAAO,KAAK,CAAE,KAAM,YAAa,MAAAzR,EAAO,CAE5C,CAEA,OAAOyR,CACT,CAEA,SAASY,GAA0B5Y,EAA8B,CAC/D,GAAI,CAACA,EAAK,SAAS,IAAI,GAAK,CAACA,EAAK,SAAS,IAAI,EAC7C,OAAOmX,GAAgBnX,CAAI,EAG7B,MAAMgY,EAAyB,GACzBa,EAAe,+BACrB,IAAI3I,EAAS,EAEb,UAAW5P,KAASN,EAAK,SAAS6Y,CAAY,EAAG,CAC/C,KAAM,CAACC,EAAWC,EAAQC,CAAM,EAAI1Y,EACpC,GAAI,OAAOA,EAAM,OAAU,SAAU,SAErC,MAAM6P,EAAQ7P,EAAM,MACd8P,EAAMD,EAAQ2I,EAAU,OACxBnP,EAAWiJ,GAAqBoG,EAAO,MAAM,EAC9CrP,IAEDwG,EAAQD,GACV8H,EAAO,KAAK,GAAGb,GAAgBnX,EAAK,MAAMkQ,EAAQC,CAAK,CAAC,CAAC,EAG3D6H,EAAO,KAAK,CAAE,KAAM,QAAS,IAAKrO,EAAU,IAAKoP,EAAO,OAAQ,SAAUD,CAAA,CAAW,EACrF5I,EAASE,EACX,CAEA,OAAIF,EAASlQ,EAAK,QAChBgY,EAAO,KAAK,GAAGb,GAAgBnX,EAAK,MAAMkQ,CAAM,CAAC,CAAC,EAG7C8H,CACT,CAEA,SAASiB,GAAmBjZ,EAA8B,CAExD,MAAM0O,EADiBsF,GAAsBhU,CAAI,EACpB,MAAM;AAAA,CAAI,EACjCgY,EAAyB,GAC/B,IAAI7W,EAAQ,EACR+X,EAAa,EAEjB,MAAMC,EAAcC,GAA+B,CACjD,GAAIA,GAAgBF,EAAY,OAChC,MAAMG,EAAQ3K,EAAM,MAAMwK,EAAYE,CAAY,EAAE,KAAK;AAAA,CAAI,EAC7DpB,EAAO,KAAK,GAAGY,GAA0BS,CAAK,CAAC,CACjD,EAEA,KAAOlY,EAAQuN,EAAM,QAAQ,CAC3B,MAAMuJ,EAAQ7B,GAAe1H,EAAMvN,CAAK,CAAC,EACzC,GAAI,CAAC8W,EAAO,CACV9W,GAAS,EACT,QACF,CAEAgY,EAAWhY,CAAK,EAEhBA,GAAS,EACT,MAAM+W,EAAsB,GAC5B,KAAO/W,EAAQuN,EAAM,QAAQ,CAC3B,GAAIA,EAAMvN,CAAK,EAAE,SAAW8W,EAAM,OAAQ,CACxC9W,GAAS,EACT,KACF,CACA+W,EAAU,KAAKxJ,EAAMvN,CAAK,CAAC,EAC3BA,GAAS,CACX,CAEA6W,EAAO,KAAK,CACV,KAAM,YACN,SAAUC,EAAM,SAChB,MAAOC,EAAU,KAAK;AAAA,CAAI,EAC3B,EACDgB,EAAa/X,CACf,CAEA,OAAAgY,EAAWzK,EAAM,MAAM,EAChBsJ,EAAO,OAAS,EAAIA,EAAS,CAAC,CAAE,KAAM,YAAa,MAAOhY,EAAM,CACzE,CAEA,SAASsZ,EAAW/S,EAAuB,CACzC,OAAOA,EACJ,QAAQ,MAAO,OAAO,EACtB,QAAQ,MAAO,MAAM,EACrB,QAAQ,MAAO,MAAM,EACrB,QAAQ,MAAO,QAAQ,EACvB,QAAQ,MAAO,OAAO,CAC3B,CAEA,SAASgT,GAAsBC,EAA0B,OACvD,MAAMnJ,IAAQ5P,EAAA+Y,EAAS,OAAO,MAAM,MAAM,EAAE,CAAC,IAA/B,YAAA/Y,EAAkC,gBAAiB,GACjE,OAAK4P,EACE/K,GAAsB+K,CAAK,GAAKA,EADpB,EAErB,CAEA,SAASoJ,GAA4BD,EAAkBjT,EAAuB,CAC5E,MAAMmT,EAAqBH,GAAsBC,CAAQ,EACzD,GAAI,CAACE,EAAoB,OAAOJ,EAAW/S,CAAK,EAChD,MAAMoT,EAAc/T,GAAkB,MACtC,GAAI,CAAC+T,EAAa,OAAOL,EAAW/S,CAAK,EAEzC,GAAI,CACF,GAAIoT,EAAY,YAAYD,CAAkB,EAC5C,OAAOC,EAAY,UAAUpT,EAAO,CAClC,SAAUmT,EACV,eAAgB,GACjB,EAAE,KAEP,MAAQ,CAER,CAEA,OAAOJ,EAAW/S,CAAK,CACzB,CAEA,SAASqT,EAA2B5Z,EAAsB,CACxD,OAAO6R,EAAoB7R,CAAI,EAC5B,IAAK8Q,GACAA,EAAQ,OAAS,OACZwI,EAAWxI,EAAQ,KAAK,EAE7BA,EAAQ,OAAS,OACZ,qCAAqCwI,EAAWxI,EAAQ,KAAK,CAAC,YAEnEA,EAAQ,OAAS,SACZ,mCAAmCwI,EAAWxI,EAAQ,KAAK,CAAC,QAEjEA,EAAQ,OAAS,gBACZ,yCAAyCwI,EAAWxI,EAAQ,KAAK,CAAC,OAEvEA,EAAQ,OAAS,OACZ,sCAAsCwI,EAAWzG,EAAY/B,EAAQ,IAAI,CAAC,CAAC,sDAAsDwI,EAAWxI,EAAQ,IAAI,CAAC,KAAKwI,EAAWxI,EAAQ,WAAW,CAAC,OAElMA,EAAQ,OAAS,MACZ,sCAAsCwI,EAAWxI,EAAQ,IAAI,CAAC,sDAAsDwI,EAAWxI,EAAQ,IAAI,CAAC,KAAKwI,EAAWxI,EAAQ,KAAK,CAAC,OAE5K,qCAAqCwI,EAAWxI,EAAQ,KAAK,CAAC,SACtE,EACA,KAAK,EAAE,CACZ,CAEA,SAAS+I,GAA+BC,EAAwB,CAC9D,OAAOA,EAAK,WACT,IAAKC,GAAc,mEAAmEH,EAA2BG,CAAS,CAAC,QAAQ,EACnI,KAAK,EAAE,CACZ,CAEA,SAASC,GAA4BF,EAAwB,OAC3D,MAAMG,EAAiBJ,GAA+BC,CAAI,EACpDI,IAAezZ,EAAAqZ,EAAK,WAAL,YAAArZ,EAAe,IAAKgB,GAAU0Y,GAAyB1Y,CAAK,GAAG,KAAK,MAAO,GAChG,OAAOwY,EAAiBC,CAC1B,CAEA,SAASE,GAAwB3E,EAAmC,CAClE,OAAKA,EACE,sBAAsBA,CAAS,IADf,EAEzB,CAEA,SAAS0E,GAAyB1Y,EAA6B,CAC7D,GAAIA,EAAM,OAAS,YACjB,MAAO,2BAA2BmY,EAA2BnY,EAAM,KAAK,CAAC,OAE3E,GAAIA,EAAM,OAAS,UAAW,CAC5B,MAAMqH,EAAQ,KAAK,IAAI,EAAG,KAAK,IAAI,EAAG,KAAK,MAAMrH,EAAM,KAAK,CAAC,CAAC,EACxD4Y,EAAMxR,GAAWC,CAAK,EACtBwR,EAAU,mBAAmBtR,GAAaF,CAAK,CAAC,GACtD,MAAO,IAAIuR,CAAG,WAAWC,CAAO,KAAKV,EAA2BnY,EAAM,KAAK,CAAC,KAAK4Y,CAAG,GACtF,CACA,GAAI5Y,EAAM,OAAS,aACjB,MAAO,0CAA0CmY,EAA2BnY,EAAM,KAAK,CAAC,gBAE1F,GAAIA,EAAM,OAAS,gBAIjB,MAAO,mDAHOA,EAAM,MACjB,IAAKqY,GAAS,wEAAwEE,GAA4BF,CAAI,CAAC,aAAa,EACpI,KAAK,EAAE,CACqD,QAEjE,GAAIrY,EAAM,OAAS,WASjB,MAAO,8CAROA,EAAM,MACjB,IAAKqY,GACJ,mFACqDA,EAAK,QAAU,OAAS,OAAO,KAAKA,EAAK,QAAU,IAAM,GAAG,8CAC1EF,EAA2BE,EAAK,IAAI,CAAC,aAE7E,EACA,KAAK,EAAE,CACgD,QAE5D,GAAIrY,EAAM,OAAS,cAAe,CAChC,MAAM6V,EAAQ7V,EAAM,MACjB,IAAKqY,GAAS,wEAAwEE,GAA4BF,CAAI,CAAC,aAAa,EACpI,KAAK,EAAE,EACV,MAAO,wDAAwDrY,EAAM,KAAK,KAAK6V,CAAK,OACtF,CACA,GAAI7V,EAAM,OAAS,QAAS,CAC1B,MAAM8Y,EAAc9Y,EAAM,QACvB,IAAI,CAAC2T,EAAMjU,IAAU,sCAAsCiZ,GAAwB3Y,EAAM,WAAWN,CAAK,GAAK,IAAI,CAAC,IAAIyY,EAA2BxE,CAAI,CAAC,OAAO,EAC9J,KAAK,EAAE,EACJa,EAAOxU,EAAM,KAChB,IAAKyU,GACJ,sCACAA,EAAI,IAAI,CAACd,EAAMjU,IAAU,iCAAiCiZ,GAAwB3Y,EAAM,WAAWN,CAAK,GAAK,IAAI,CAAC,IAAIyY,EAA2BxE,CAAI,CAAC,OAAO,EAAE,KAAK,EAAE,EACtK,OACD,EACA,KAAK,EAAE,EACJoF,EAAOvE,EAAO,UAAUA,CAAI,WAAa,GAC/C,MAAO,2EAA2EsE,CAAW,gBAAgBC,CAAI,gBACnH,CACA,OAAI/Y,EAAM,OAAS,YAIV,mCAHUA,EAAM,SACnB,sCAAsC6X,EAAW7X,EAAM,QAAQ,CAAC,SAChE,EAC8C,oDAAoDgY,GAA4BhY,EAAM,SAAUA,EAAM,KAAK,CAAC,sBAE5JA,EAAM,OAAS,gBACV,+BAEF,kEAAkE6X,EAAW7X,EAAM,GAAG,CAAC,UAAU6X,EAAW7X,EAAM,KAAO,wBAAwB,CAAC,mBAC3J,CAEA,SAASgZ,GAA2Bza,EAAsB,CACxD,OAAOiZ,GAAmBjZ,CAAI,EAC3B,IAAKyB,GAAU0Y,GAAyB1Y,CAAK,CAAC,EAC9C,KAAK,EAAE,CACZ,CAyZA,SAASiZ,IAAuB,CAC9B,MAAMC,EAAY3V,EAAoB,MAChCuO,EAAStO,GAAgB,MAC3B,CAAC0V,GAAa,CAACpH,IACnBoH,EAAU,UAAYA,EAAU,aAChCpH,EAAO,eAAe,CAAE,MAAO,MAAO,EACxC,CAEA,SAASqH,GAAWD,EAAiC,CAEnD,OADiBA,EAAU,cAAgBA,EAAU,UAAYA,EAAU,eACxDjc,EACrB,CAEA,SAASmc,GAAgBF,EAA8B,CACrD,GAAI,CAACvZ,EAAM,eAAgB,OAC3B,MAAM0Z,EAAe,KAAK,IAAIH,EAAU,aAAeA,EAAU,aAAc,CAAC,EAC1EI,EAAcD,EAAe,EAAI,KAAK,IAAI,KAAK,IAAIH,EAAU,UAAYG,EAAc,CAAC,EAAG,CAAC,EAAI,EACtGhW,GAAK,oBAAqB,CACxB,SAAU1D,EAAM,eAChB,MAAO,CACL,UAAWuZ,EAAU,UACrB,WAAYC,GAAWD,CAAS,EAChC,YAAAI,CAAA,CACF,CACD,CACH,CAEA,SAASC,IAA8B,CACrC,MAAML,EAAY3V,EAAoB,MACtC,GAAI,CAAC2V,EAAW,OAEhB,GAAItV,EAAiB,MAAO,CAC1B4V,GAAA,EACA,MACF,CAEA,MAAMC,EAAa9Z,EAAM,YACzB,GAAI,CAAC8Z,GAAcA,EAAW,WAAY,CACxCL,GAAgBF,CAAS,EACzB,MACF,CAEA,MAAMG,EAAe,KAAK,IAAIH,EAAU,aAAeA,EAAU,aAAc,CAAC,EAC1EQ,EAAkBD,EAAW,UACnCP,EAAU,UAAY,KAAK,IAAI,KAAK,IAAIQ,EAAiB,CAAC,EAAGL,CAAY,EACzED,GAAgBF,CAAS,CAC3B,CAEA,SAASM,IAA2B,CAClC,MAAMN,EAAY3V,EAAoB,MACjC2V,IACLD,GAAA,EACAG,GAAgBF,CAAS,EAC3B,CAEA,SAASS,IAA8B,CACrC,OAAO/V,EAAiB,KAC1B,CAEA,SAASgW,IAA2B,CAClC,GAAI,CAACD,KAAsB,CACzB3V,GAAuB,EACvBD,EAAkB,EAClB,MACF,CAIA,GAFAyV,GAAA,EACAxV,IAAwB,EACpBA,IAAwB,EAAG,CAC7BD,EAAkB,EAClB,MACF,CACAA,EAAkB,sBAAsB6V,EAAkB,CAC5D,CAEA,SAASC,GAAmBC,EAAS,EAAS,CACvCH,OACD5V,IACF,qBAAqBA,CAAe,EACpCA,EAAkB,GAEpBC,GAAuB,KAAK,IAAI8V,EAAQ,CAAC,EACzC/V,EAAkB,sBAAsB6V,EAAkB,EAC5D,CAEA,SAASG,IAA8B,CACrCF,GAAmB,CAAC,CACtB,CAEA,SAASG,IAAqB,CAC5BpW,EAAiB,MAAQ,GACzB4V,GAAA,EACAK,GAAmB,CAAC,CACtB,CAEA,eAAeI,IAA+B,CAC5C,MAAMf,EAAY3V,EAAoB,MACtC,GAAI,CAAC2V,GAAa,CAAC1U,GAAa,OAASF,EAAc,MAAO,OAE9DA,EAAc,MAAQ,GACtB,MAAM4V,EAAkBva,EAAM,eAExBwa,EAAmBjB,EAAU,aAC7BkB,EAAgBlB,EAAU,UAEhC7U,EAAkB,MAAQ,KAAK,IAAI,EAAGA,EAAkB,MAAQlH,EAAe,EAE/E,MAAMkd,GAAA,EAGF1a,EAAM,iBAAmBua,IAC3BhB,EAAU,UAAYkB,GAAiBlB,EAAU,aAAeiB,GAChE7V,EAAc,MAAQ,GAE1B,CAEAgW,EAAa,CACX,aAAAN,EAAA,CACD,EAED,SAASO,IAAiC,CACxC,GAAI,CAACZ,KAAsB,OAC3B,MAAMT,EAAY3V,EAAoB,MACtC,GAAI,CAAC2V,EAAW,OAEhB,MAAMsB,EAAStB,EAAU,iBAAmC,2BAA2B,EACvF,UAAWuB,KAASD,EACdC,EAAM,UAAYvW,GAAqB,IAAIuW,CAAK,IACpDvW,GAAqB,IAAIuW,CAAK,EAC9BA,EAAM,iBAAiB,OAAQV,GAAuB,CAAE,KAAM,GAAM,EACpEU,EAAM,iBAAiB,QAASV,GAAuB,CAAE,KAAM,GAAM,EAEzE,CAEA,eAAeW,IAAuC,CACpD,MAAML,GAAA,EACFvW,IACF,qBAAqBA,EAAkB,EAEzCA,GAAqB,sBAAsB,IAAM,CAC/CA,GAAqB,EACrByV,GAAA,EACAgB,GAAA,EACAV,GAAA,CACF,CAAC,CACH,CAEAc,EACE,IAAMhb,EAAM,SACZ,MAAOI,GAAS,CACd,GAAIJ,EAAM,UAAW,OAErB,MAAMib,EAAa,IAAI,IACrB7a,EACG,OAAQZ,GAAYA,EAAQ,cAAgB,oBAAsBA,EAAQ,gBAAgB,EAC1F,IAAKA,GAAYA,EAAQ,EAAE,GAEhC9B,GAAmB,MAAQqF,GAAkBrF,GAAmB,MAAOud,CAAU,EACjFrd,EAAwB,MAAQmF,GAAkBnF,EAAwB,MAAOqd,CAAU,EAC3Fpd,GAAwB,MAAQkF,GAC9BlF,GAAwB,MACxB,IAAI,IAAI,OAAO,KAAKsC,GAA0B,KAAK,CAAC,GAEtDpC,GAA6B,MAAQgF,GACnChF,GAA6B,UACzB,IAAI,CACN,GAAG,OAAO,KAAKgL,GAAoC,KAAK,EACxD,GAAG,OAAO,KAAK8B,GAAuC,KAAK,EAC5D,GAQC5G,EAAiB,MACnBS,EAAkB,MAAQ,KAAK,IAAI,EAAGtE,EAAK,OAAS7C,EAAkB,EAEtEmH,EAAkB,MAAQ,KAAK,IAAIA,EAAkB,MAAO,KAAK,IAAI,EAAGtE,EAAK,OAAS,CAAC,CAAC,EAG1F,MAAM2a,GAAA,CACR,GAGFC,EACE,IAAMhb,EAAM,SAAS,KAAMR,GAAYA,EAAQ,KAAK,SAAS,KAAK,CAAC,EAClE0b,GAAkB,CACb,CAACA,GAAiB1W,GAAkB,OACnCO,GAAA,CACP,EACA,CAAE,UAAW,GAAK,EAGpBiW,EACEnb,GACA,CAACsb,EAAQC,IAAW,CAElB,GADI,CAACA,GAAUA,IAAWD,GACtB,CAACvd,EAAwB,MAAM,IAAIwd,CAAM,EAAG,OAChD,MAAMja,EAAoB,IAAI,IAAIvD,EAAwB,KAAK,EAC/DuD,EAAkB,OAAOia,CAAM,EAC/Bxd,EAAwB,MAAQuD,CAClC,GAGF6Z,EACE,IAAMhb,EAAM,gBACZ,SAAY,CACNA,EAAM,WACV,MAAM+a,GAAA,CACR,EACA,CAAE,KAAM,GAAK,EAGfC,EACE,IAAMhb,EAAM,YACZ,MAAOqb,GAAY,CACZA,GACApX,EAAiB,QACtB,MAAMyW,GAAA,EACNb,GAAA,EACAK,GAAmB,CAAC,EACtB,EACA,CAAE,KAAM,GAAK,EAGfc,EACE,IAAMhb,EAAM,UACZ,MAAOsb,GAAY,CACbA,IACJ5W,EAAkB,MAAQ,KAAK,IAAI,EAAG1E,EAAM,SAAS,OAASzC,EAAkB,EAChF,MAAMwd,GAAA,EACR,GAGFC,EACE,IAAMhb,EAAM,eACZ,IAAM,CACJgE,GAAiB,MAAQ,KACzBC,EAAiB,MAAQ,GACzBH,GAAc,MAAQ,GACtBa,EAAc,MAAQ,GAEtBD,EAAkB,MAAQ,KAAK,IAAI,EAAG1E,EAAM,SAAS,OAASzC,EAAkB,CAClF,EACA,CAAE,MAAO,OAAO,EAGlB,SAASge,IAA6B,CACpC,MAAMhC,EAAY3V,EAAoB,MAClC,CAAC2V,GAAavZ,EAAM,YACxBiE,EAAiB,MAAQuV,GAAWD,CAAS,EAC7CE,GAAgBF,CAAS,EACrB1U,GAAa,OAAS,CAACF,EAAc,OAAS4U,EAAU,UAAY9b,IACjE6c,GAAA,EAET,CAEA,MAAMkB,GAAuB7d,EAAI,IAAI,GAAa,EAElD,SAAS8d,GAAiBzQ,EAAmB0Q,EAA4B,CACvE,MAAO,GAAG1Q,CAAS,IAAI0Q,CAAU,EACnC,CAEA,SAASC,GAAsB3Q,EAAmB0Q,EAA6B,CAC7E,OAAOF,GAAqB,MAAM,IAAIC,GAAiBzQ,EAAW0Q,CAAU,CAAC,CAC/E,CAEA,SAASE,GAAqB5Q,EAAmB0Q,EAA0B,CACzEF,GAAqB,MAAM,IAAIC,GAAiBzQ,EAAW0Q,CAAU,CAAC,CACxE,CAEA,SAASG,GAAetT,EAAwB,CAC9CzE,GAAc,MAAQyE,CACxB,CAEA,SAASuT,IAAwB,CAC/BhY,GAAc,MAAQ,EACxB,CAEA,OAAAiY,GAAU,IAAM,CACd,OAAO,iBAAiB,cAAevJ,EAAyC,EAChF,OAAO,iBAAiB,OAAQE,EAAkC,EAClE,OAAO,iBAAiB,UAAWC,EAAqC,CAC1E,CAAC,EAEDqJ,GAAgB,IAAM,CAChB7X,IACF,qBAAqBA,EAAkB,EAErCC,GACF,qBAAqBA,CAAe,EAElCE,IACF,aAAaA,EAAuB,EAEtC,OAAO,oBAAoB,cAAekO,EAAyC,EACnF,OAAO,oBAAoB,OAAQE,EAAkC,EACrE,OAAO,oBAAoB,UAAWC,EAAqC,CAC7E,CAAC,cA3+HCzV,EA4zBU,WA5zBD,MAAM,yCAA0C+U,EAAA,GAC9CxO,EAAA,eAATvG,EAAwE,IAAxEC,GAAiD,qBAAmB,GAGvDsG,EAAA,SAAS,SAAM,GAAUA,kBAAgB,aAAiBA,EAAA,iBADvEvG,EAKI,IALJ+e,GAGC,mCAED,QAEA/e,EAipBK,oBAjpBU,sBAAJ,IAAI0G,EAAsB,MAAM,oBAAqB,SAAQ2X,EAAA,GAC5D1W,GAAA,OAAV5H,EAAA,EAAAC,EASK,KATLgf,GASK,CARH7e,EAOS,UANP,KAAK,SACL,MAAM,mBACL,SAAUsH,EAAA,MACV,QAAO2V,EAAA,IAEL3V,EAAA,MAAa,sCAAAwX,EAAA,qBAGpBjf,EAonBWkf,EAAA,KAAAC,EApnBiBzX,GAAA,MAAXpF,GAAO,6BAA2B,IAAAA,EAAQ,KAElD,CAAAe,GAAA,MAAwB,IAAIf,EAAQ,EAAE,IAAMuL,GAAA,MAA2B,IAAIvL,EAAQ,EAAE,OAD9FtC,EAknBK,YAhnBH,MAAM,oBACL,YAAWsC,EAAQ,KACnB,oBAAmBA,EAAQ,aAAW,KAE5BC,EAAiBD,CAAO,GAAnCvC,IAAAC,EAsFM,MAtFNof,GAsFM,CArFJjf,EAoFM,MApFNkf,GAoFM,CAlFIlb,GAA4B7B,CAAO,EAAE,OAAM,OADnDtC,EAUS,gBARP,KAAK,SACL,MAAKsf,EAAA,CAAC,oCAAmC,CAChC3Z,GAAmBrD,CAAO,kBAAqBgC,GAAuBhC,CAAO,MACrF,QAAKid,GAAElb,GAAmB/B,CAAO,IAElCnC,EAAmG,QAA7F,MAAKmf,EAAA,CAAC,cAAa,oBAA+Bhb,GAAuBhC,CAAO,MAAK,IAAC,GAC5FnC,EAA4E,OAA5Eqf,GAA4EC,EAA3Clb,GAAyBjC,CAAO,MACjEnC,EAAwE,OAAxEuf,GAAwED,EAA5C9a,GAA0BrC,CAAO,wBAGvD6B,GAA4B7B,CAAO,EAAE,OAAM,OADnDtC,EAyCM,aAvCJ,MAAKsf,EAAA,CAAC,iBAAgB,qBACShb,GAAuBhC,CAAO,OAE7DnC,EAmCM,MAnCNwf,GAmCM,EAlCJ5f,EAAA,IAAAC,EAiCMkf,EAAA,KAAAC,EAhCU/a,GAAyB9B,CAAO,EAAvCsd,GAAG,oBADZ5f,EAiCM,OA/BH,IAAG,eAAiB4f,EAAI,EAAE,GAC3B,MAAM,oBAENzf,EAeS,UAdP,KAAK,SACL,SAAM,UAAS,CACiBwF,GAAmBia,CAAG,GAAmE,eAAAhc,EAAkBgc,CAAG,uBAO7I,QAAKL,GAAExb,GAAoB6b,CAAG,IAE/Bzf,EAA0F,QAApF,MAAKmf,EAAA,CAAC,cAAa,oBAA+B1b,EAAkBgc,CAAG,MAAK,IAAC,GACnFzf,EAAiF,OAAjF0f,GAAiFJ,IAAtDtd,EAAAyd,EAAI,mBAAJ,YAAAzd,EAAsB,UAAO,gBACxDhC,EAA6D,OAA7D2f,GAA6DL,EAAjC7a,GAAmBgb,CAAG,cAEpDzf,EAWM,OAVJ,MAAKmf,EAAA,CAAC,kBAAiB,sBACS1b,EAAkBgc,CAAG,OAErDzf,EAMM,MANN4f,GAMM,CALJ5f,EAIO,OAHL,MAAKmf,EAAA,CAAC,aAAY,wBACgBxb,GAAyB8b,CAAG,KAC9D,YAAAH,IAAQ/a,EAAAkb,EAAI,mBAAJ,YAAAlb,EAAsB,mBAAgB,wDAO1D1E,EA6BWkf,EAAA,SA5BT/e,EAeS,UAdP,KAAK,SACL,SAAM,UAAS,CACawF,GAAmBrD,CAAO,GAA2D,eAAAsB,EAAkBtB,CAAO,EAAsC,cAAAuB,GAAiBvB,CAAO,MAOvM,QAAKid,GAAExb,GAAoBzB,CAAO,IAEnCnC,EAA8F,QAAxF,MAAKmf,EAAA,CAAC,cAAa,oBAA+B1b,EAAkBtB,CAAO,MAAK,IAAC,GACvFnC,EAAqF,OAArF6f,GAAqFP,IAA1Dtd,EAAAG,EAAQ,mBAAR,YAAAH,EAA0B,UAAO,gBAC5DhC,EAAiE,OAAjE8f,GAAiER,EAArC7a,GAAmBtC,CAAO,cAExDnC,EAWM,OAVJ,MAAKmf,EAAA,CAAC,kBAAiB,sBACS1b,EAAkBtB,CAAO,OAEzDnC,EAMM,MANN+f,GAMM,CALJ/f,EAIO,OAHL,MAAKmf,EAAA,CAAC,aAAY,wBACgBxb,GAAyBxB,CAAO,KAClE,YAAAmd,IAAQ/a,EAAApC,EAAQ,mBAAR,YAAAoC,EAA0B,mBAAgB,6CASjDjC,GAAoBH,CAAO,OADxCtC,EA4EM,aA1EJ,MAAM,cACL,YAAWsC,EAAQ,KACnB,oBAAmBA,EAAQ,aAAW,KAEvCnC,EAqEM,OArED,MAAM,gBAAiB,YAAWmC,EAAQ,OAC7CnC,EAmEU,WAnED,MAAM,eAAgB,YAAWmC,EAAQ,OACjC2L,GAAgC3L,CAAO,GAAtDvC,IAAAC,EAiEU,UAjEVmgB,GAiEU,CAhERhgB,EAoBS,UAnBP,KAAK,SACL,MAAKmf,EAAA,CAAC,4DAA2D,gBACvCta,GAA4B1C,CAAO,KAC5D,QAAKid,GAAExa,GAAwBzC,CAAO,IAEvCnC,EAAwG,QAAlG,MAAKmf,EAAA,CAAC,cAAa,oBAA+Bta,GAA4B1C,CAAO,MAAK,IAAC,GACjGnC,EAEO,OAFPigB,GAEOX,EADFzQ,GAAuBf,GAAgC3L,CAAO,OAEnEnC,EASO,OATPkgB,GASO,EARLtgB,EAAA,IAAAC,EAOOkf,SANU/P,GAA6BlB,GAAgC3L,CAAO,GAA5E8G,QADTpJ,EAOO,QALJ,IAAG,kBAAoBsC,EAAQ,EAAE,IAAI8G,EAAK,IAAI,IAAIA,EAAK,KAAK,GAC7D,MAAM,2BACL,YAAWA,EAAK,MAEdqW,EAAArW,EAAK,KAAK,IAAAkX,EAAA,oBAInBngB,EA0CM,OA1CD,MAAKmf,EAAA,CAAC,iBAAgB,qBAAgCta,GAA4B1C,CAAO,OAC5FnC,EAwCM,MAxCNogB,GAwCM,CAvCJpgB,EAsCK,KAtCLqgB,GAsCK,EArCHzgB,EAAA,IAAAC,EAoCKkf,WAnCcuB,EAAAxS,GAAgC3L,CAAO,IAAvC,YAAAme,EAA0C,aAApDvb,QADTlF,EAoCK,MAlCF,IAAG,eAAiBsC,EAAQ,EAAE,IAAI4C,EAAO,IAAI,IAAIA,EAAO,aAAW,KACpE,MAAM,qBAEN/E,EAEO,QAFD,MAAM,oBAAqB,iBAAgBgO,GAAwBjJ,CAAM,GAC1Eua,EAAAvR,GAAyBhJ,CAAM,KAAAwb,EAAA,EAEpCvgB,EAOS,UANP,KAAK,SACL,MAAM,0BACL,MAAO+E,EAAO,KACd,WAAOC,GAAe8I,GAAgC3L,CAAO,EAAG4C,CAAM,KAEpEqK,EAAsBrK,EAAO,IAAI,KAAAyb,EAAA,EAE1Bzb,EAAO,iBAAnBlF,EAAkE,OAAlE4gB,GAA0D,GAAC,YAEnD1b,EAAO,iBADflF,EAQS,gBANP,KAAK,SACL,MAAM,0BACL,MAAOkF,EAAO,YACd,WAAOC,GAAe8I,GAAgC3L,CAAO,EAAG4C,CAAM,KAEpEqK,EAAsBrK,EAAO,WAAW,KAAA2b,EAAA,YAEjC3b,EAAO,eAAc,GAAQA,EAAO,iBAAgB,GAAhEnF,IAAAC,EASO,OATP8gB,GASO,EARL/gB,EAAA,IAAAC,EAOOkf,EAAA,KAAAC,EANU1Q,GAAqBvJ,CAAM,EAAnCkE,QADTpJ,EAOO,QALJ,IAAG,gBAAkBsC,EAAQ,EAAE,IAAI4C,EAAO,IAAI,IAAIkE,EAAK,IAAI,IAAIA,EAAK,KAAK,GAC1E,MAAM,2BACL,YAAWA,EAAK,MAEdqW,EAAArW,EAAK,KAAK,IAAA2X,EAAA,+EAYjC/gB,EAqcM,aArcM,MAAM,cAAe,YAAWsC,EAAQ,KAAO,oBAAmBA,EAAQ,aAAW,KAC/FnC,EAmcM,OAncD,MAAM,gBAAiB,YAAWmC,EAAQ,OAC7CnC,EAicU,WAjcD,MAAM,eAAgB,YAAWmC,EAAQ,OAExCA,EAAQ,QAAUA,EAAQ,OAAO,OAAM,OAD/CtC,EAUK,YARH,MAAM,qBACL,YAAWsC,EAAQ,QAEpBvC,EAAA,IAAAC,EAIKkf,EAAA,KAAAC,EAJkB7c,EAAQ,OAApB+I,QAAXrL,EAIK,MAJmC,IAAKqL,EAAU,MAAM,uBAC3DlL,EAES,UAFD,MAAM,uBAAuB,KAAK,SAAU,QAAKof,GAAEZ,GAAetT,CAAQ,IAChFlL,EAAgG,OAA3F,MAAM,wBAAyB,IAAKkL,EAAU,IAAI,wBAAwB,QAAQ,qDAKlF/I,EAAQ,iBAAmBA,EAAQ,gBAAgB,OAAM,GAApEvC,IAAAC,EAaM,MAbNghB,GAaM,EAZJjhB,EAAA,IAAAC,EAWOkf,EAAA,KAAAC,EAXa7c,EAAQ,gBAAf2e,QAAbjhB,EAWO,QAXuC,OAAQsC,EAAQ,EAAE,IAAI2e,EAAI,IAAI,GAAI,MAAM,sBACpF/gB,EAAA,KAAAA,EAAA,GAAAC,EAA8C,QAAxC,MAAM,0BAAyB,KAAE,KACvCA,EAQI,KAPF,MAAM,2CACL,KAAMoU,EAAY0M,EAAI,IAAI,EAC3B,OAAO,SACP,IAAI,sBACH,MAAOA,EAAI,MAETxB,EAAAwB,EAAI,KAAK,IAAAC,EAAA,wBAKH5e,EAAQ,KAAK,OAAM,OAAlCtC,EAwTU,iBAxT8B,MAAM,eAAgB,YAAWsC,EAAQ,OACpEA,EAAQ,cAAW,UAA9BvC,IAAAC,EA2CM,MA3CNmhB,GA2CM,CA1CJhhB,EAKS,UALD,KAAK,SAAS,MAAM,mBAAoB,QAAKof,GAAE1a,GAAmBvC,CAAO,gBAC/EnC,EAAyD,QAAnD,MAAM,wBAAwB,cAAY,kBAChDA,EAAmG,QAA7F,MAAKmf,EAAA,CAAC,iBAAgB,uBAAkCxa,GAAiBxC,CAAO,MAAK,IAAC,GAC5FnC,EAAuD,IAAvDihB,GAAuD3B,EAAnBnd,EAAQ,IAAI,iBAChDnC,EAAyD,QAAnD,MAAM,wBAAwB,cAAY,yBAEvC2E,GAAiBxC,CAAO,GAAnCvC,IAAAC,EAmCM,MAnCNqhB,GAmCM,QAlCJrhB,EAiCMkf,EAAA,KAAAC,EAhCUlZ,GAAqBM,EAAA,SAAUA,EAAA,SAAS,QAAQjE,CAAO,GAA9Dsd,GAAG,oBADZ5f,EAiCM,OA/BH,IAAG,cAAgB4f,EAAI,EAAE,GAC1B,MAAM,oBAENzf,EAeS,UAdP,KAAK,SACL,SAAM,UAAS,CACqBwF,GAAmBia,CAAG,GAA2E,eAAAhc,EAAkBgc,CAAG,EAA8C,cAAA/b,GAAiB+b,CAAG,MAO3N,QAAKL,GAAExb,GAAoB6b,CAAG,IAE/Bzf,EAA0F,QAApF,MAAKmf,EAAA,CAAC,cAAa,oBAA+B1b,EAAkBgc,CAAG,MAAK,IAAC,GACnFzf,EAAiF,OAAjFmhB,GAAiF7B,IAAtDtd,EAAAyd,EAAI,mBAAJ,YAAAzd,EAAsB,UAAO,gBACxDhC,EAA6D,OAA7DohB,GAA6D9B,EAAjC7a,GAAmBgb,CAAG,cAEpDzf,EAWM,OAVJ,MAAKmf,EAAA,CAAC,kBAAiB,sBACS1b,EAAkBgc,CAAG,OAErDzf,EAMM,MANNqhB,GAMM,CALJrhB,EAIO,OAHL,MAAKmf,EAAA,CAAC,aAAY,wBACgBxb,GAAyB8b,CAAG,KAC9D,YAAAH,IAAQ/a,EAAAkb,EAAI,mBAAJ,YAAAlb,EAAsB,mBAAgB,2DAO1ClC,GAAcF,CAAO,OAArCtC,EAsBM,aAtBkC,MAAM,YAAa,iBAAgBsC,EAAQ,cAAW,cAC5FnC,EAGM,MAHNshB,GAGM,CAFJvhB,EAAA,KAAAA,EAAA,GAAAC,EAAmC,KAAhC,MAAM,mBAAkB,OAAI,KACnBmC,EAAQ,cAAW,iBAA/BtC,EAAwF,OAAxF0hB,GAAyE,UAAQ,cAG3Ele,GAAoBlB,CAAO,OADnCtC,EAIE,aAFA,MAAM,2CACN,UAAQmc,GAA2B3Y,GAAoBlB,CAAO,yBAEtDmB,GAAcnB,CAAO,EAAE,OAAM,GAAvCvC,IAAAC,EAUK,KAVL2hB,GAUK,EATH5hB,EAAA,IAAAC,EAQKkf,SAPyBzb,GAAcnB,CAAO,GAAzCF,EAAMwf,SADhB5hB,EAQK,MANF,IAAG,GAAKsC,EAAQ,EAAE,cAAcsf,CAAS,GAC1C,MAAM,iBACL,cAAaxf,EAAK,SAEnBjC,EAAsG,QAAhG,MAAM,mBAAoB,cAAaiC,EAAK,UAAWsB,GAAmBtB,EAAK,MAAM,KAAAyf,EAAA,EAC3F1hB,EAAgG,OAA3F,MAAM,oCAAoC,UAAQgc,GAA2B/Z,EAAK,IAAI,qCAG/FpC,EAA2F,aAA/E,MAAM,qBAAqB,UAAQmc,GAA2B7Z,EAAQ,IAAI,wBAExFvC,IAAAC,EAmPM,MAnPN8hB,GAmPM,QAlPJ9hB,EAiPWkf,EAAA,KAAAC,EAjP6BxE,GAAmBrY,EAAQ,IAAI,GAArDa,EAAOqb,2BAAgEA,CAAU,KACxFrb,EAAM,OAAI,aAAnBpD,IAAAC,EA4BI,IA5BJ+hB,GA4BI,QA3BF/hB,EA0BWkf,EAAA,KAAAC,EA1BiC5L,EAAoBpQ,EAAM,KAAK,GAAzDqP,EAASwP,cAAgE,WAAAxD,CAAU,IAAIwD,CAAY,KACvGxP,EAAQ,OAAI,YAAxBxS,EAA+D,OAAAiiB,GAAAxC,EAAvBjN,EAAQ,KAAK,MAClCA,EAAQ,OAAI,QAA/BzS,EAAA,EAAAC,EAAkG,SAAlGkiB,GAAkGzC,EAAzBjN,EAAQ,KAAK,MACvEA,EAAQ,OAAI,UAA3BzS,EAAA,EAAAC,EAA8F,KAA9FmiB,GAA8F1C,EAArBjN,EAAQ,KAAK,MACxEA,EAAQ,OAAI,iBAA1BzS,EAAA,EAAAC,EAA0G,IAA1GoiB,GAA0G3C,EAApBjN,EAAQ,KAAK,MAEtFA,EAAQ,OAAI,YADzBxS,EASI,WAPF,MAAM,oBACL,KAAMuU,EAAY/B,EAAQ,IAAI,EAC/B,OAAO,SACP,IAAI,sBACH,MAAOA,EAAQ,MAEbiN,EAAAjN,EAAQ,WAAW,IAAA6P,EAAA,GAGX7P,EAAQ,OAAI,WADzBxS,EASI,WAPF,MAAM,oBACL,KAAMwS,EAAQ,KACf,OAAO,SACP,IAAI,sBACH,MAAOA,EAAQ,MAEbiN,EAAAjN,EAAQ,KAAK,IAAA8P,EAAA,IAElBviB,EAAA,EAAAC,EAAmE,OAAnEuiB,GAAmE9C,EAAvBjN,EAAQ,KAAK,sBAKhDrP,EAAM,OAAI,WAFvBpD,EAAA,EAAAyiB,GAiCYC,GAhCLlY,GAAWpH,EAAM,KAAK,UAE3B,SAAM,kBACEuH,GAAavH,EAAM,KAAK,iBAEtB,IAAmE,QAA7EnD,EA0BWkf,EAAA,KAAAC,EA1BiC5L,EAAoBpQ,EAAM,KAAK,GAAzDqP,EAASwP,cAAwE,mBAAAxD,CAAU,IAAIwD,CAAY,KAC/GxP,EAAQ,OAAI,YAAxBxS,EAA+D,OAAA0iB,GAAAjD,EAAvBjN,EAAQ,KAAK,MAClCA,EAAQ,OAAI,QAA/BzS,EAAA,EAAAC,EAAkG,SAAlG2iB,GAAkGlD,EAAzBjN,EAAQ,KAAK,MACvEA,EAAQ,OAAI,UAA3BzS,EAAA,EAAAC,EAA8F,KAA9F4iB,GAA8FnD,EAArBjN,EAAQ,KAAK,MACxEA,EAAQ,OAAI,iBAA1BzS,EAAA,EAAAC,EAA0G,IAA1G6iB,GAA0GpD,EAApBjN,EAAQ,KAAK,MAEtFA,EAAQ,OAAI,YADzBxS,EASI,WAPF,MAAM,oBACL,KAAMuU,EAAY/B,EAAQ,IAAI,EAC/B,OAAO,SACP,IAAI,sBACH,MAAOA,EAAQ,MAEbiN,EAAAjN,EAAQ,WAAW,IAAAsQ,EAAA,GAGXtQ,EAAQ,OAAI,WADzBxS,EASI,WAPF,MAAM,oBACL,KAAMwS,EAAQ,KACf,OAAO,SACP,IAAI,sBACH,MAAOA,EAAQ,MAEbiN,EAAAjN,EAAQ,KAAK,IAAAuQ,EAAA,IAElBhjB,EAAA,EAAAC,EAAmE,OAAnEgjB,GAAmEvD,EAAvBjN,EAAQ,KAAK,2CAGtCrP,EAAM,OAAI,cAAjCpD,EAAA,EAAAC,EA4Ba,aA5BbijB,GA4Ba,QA3BXjjB,EA0BWkf,EAAA,KAAAC,EA1BiC5L,EAAoBpQ,EAAM,KAAK,GAAzDqP,EAASwP,cAAsE,iBAAAxD,CAAU,IAAIwD,CAAY,KAC7GxP,EAAQ,OAAI,YAAxBxS,EAA+D,OAAAkjB,GAAAzD,EAAvBjN,EAAQ,KAAK,MAClCA,EAAQ,OAAI,QAA/BzS,EAAA,EAAAC,EAAkG,SAAlGmjB,GAAkG1D,EAAzBjN,EAAQ,KAAK,MACvEA,EAAQ,OAAI,UAA3BzS,EAAA,EAAAC,EAA8F,KAA9FojB,GAA8F3D,EAArBjN,EAAQ,KAAK,MACxEA,EAAQ,OAAI,iBAA1BzS,EAAA,EAAAC,EAA0G,IAA1GqjB,GAA0G5D,EAApBjN,EAAQ,KAAK,MAEtFA,EAAQ,OAAI,YADzBxS,EASI,WAPF,MAAM,oBACL,KAAMuU,EAAY/B,EAAQ,IAAI,EAC/B,OAAO,SACP,IAAI,sBACH,MAAOA,EAAQ,MAEbiN,EAAAjN,EAAQ,WAAW,IAAA8Q,EAAA,GAGX9Q,EAAQ,OAAI,WADzBxS,EASI,WAPF,MAAM,oBACL,KAAMwS,EAAQ,KACf,OAAO,SACP,IAAI,sBACH,MAAOA,EAAQ,MAEbiN,EAAAjN,EAAQ,KAAK,IAAA+Q,EAAA,IAElBxjB,EAAA,EAAAC,EAAmE,OAAnEwjB,GAAmE/D,EAAvBjN,EAAQ,KAAK,sBAG9CrP,EAAM,OAAI,iBAAzBpD,EAAA,EAAAC,EAIK,KAJLyjB,GAIK,EAHH1jB,EAAA,IAAAC,EAEKkf,SAF2B/b,EAAM,MAAK,CAA/BqY,EAAMkI,SAAlB1jB,EAEK,MAFyC,IAAG,MAAQwe,CAAU,IAAIkF,CAAS,GAAI,MAAM,sBACxFvjB,EAAoF,OAA/E,MAAM,4BAA4B,UAAQub,GAA4BF,CAAI,2BAGpErY,EAAM,OAAI,YAAzBpD,EAAA,EAAAC,EAiCK,KAjCL2jB,GAiCK,EAhCH5jB,EAAA,IAAAC,EA+BKkf,SA/B2B/b,EAAM,MAAK,CAA/BqY,EAAMkI,SAAlB1jB,EA+BK,MA/ByC,IAAG,QAAUwe,CAAU,IAAIkF,CAAS,GAAI,MAAM,sBAC1FvjB,EAAsG,QAAhG,MAAM,wBAAyB,eAAcqb,EAAK,SAAYiE,EAAAjE,EAAK,QAAO,WAAAoI,EAAA,EAChFzjB,EA4BM,MA5BN0jB,GA4BM,QA3BJ7jB,EA0BWkf,EAAA,KAAAC,EA1BiC5L,EAAoBiI,EAAK,IAAI,GAAvDhJ,EAASwP,8BAAmExD,CAAU,IAAIkF,CAAS,IAAI1B,CAAY,KACvHxP,EAAQ,OAAI,YAAxBxS,EAA+D,OAAA8jB,GAAArE,EAAvBjN,EAAQ,KAAK,MAClCA,EAAQ,OAAI,QAA/BzS,EAAA,EAAAC,EAAkG,SAAlG+jB,GAAkGtE,EAAzBjN,EAAQ,KAAK,MACvEA,EAAQ,OAAI,UAA3BzS,EAAA,EAAAC,EAA8F,KAA9FgkB,GAA8FvE,EAArBjN,EAAQ,KAAK,MACxEA,EAAQ,OAAI,iBAA1BzS,EAAA,EAAAC,EAA0G,IAA1GikB,GAA0GxE,EAApBjN,EAAQ,KAAK,MAEtFA,EAAQ,OAAI,YADzBxS,EASI,WAPF,MAAM,oBACL,KAAMuU,EAAY/B,EAAQ,IAAI,EAC/B,OAAO,SACP,IAAI,sBACH,MAAOA,EAAQ,MAEbiN,EAAAjN,EAAQ,WAAW,IAAA0R,EAAA,GAGX1R,EAAQ,OAAI,WADzBxS,EASI,WAPF,MAAM,oBACL,KAAMwS,EAAQ,KACf,OAAO,SACP,IAAI,sBACH,MAAOA,EAAQ,MAEbiN,EAAAjN,EAAQ,KAAK,IAAA2R,EAAA,IAElBpkB,EAAA,EAAAC,EAAmE,OAAnEokB,GAAmE3E,EAAvBjN,EAAQ,KAAK,kCAMpDrP,EAAM,OAAI,mBADvBnD,EAQK,YANH,MAAM,oCACL,MAAOmD,EAAM,SAEdpD,EAAA,IAAAC,EAEKkf,SAF2B/b,EAAM,MAAK,CAA/BqY,EAAMkI,SAAlB1jB,EAEK,MAFyC,IAAG,MAAQwe,CAAU,IAAIkF,CAAS,GAAI,MAAM,sBACxFvjB,EAAoF,OAA/E,MAAM,4BAA4B,UAAQub,GAA4BF,CAAI,gCAGnErY,EAAM,OAAI,SAA1BpD,IAAAC,EA+EM,MA/ENqkB,GA+EM,CA9EJlkB,EA6EQ,QA7ERmkB,GA6EQ,CA5ENnkB,EAqCQ,cApCNA,EAmCK,YAlCHJ,EAAA,IAAAC,EAiCKkf,SAhCyB/b,EAAM,QAAO,CAAjC2T,EAAMyN,SADhBvkB,EAiCK,MA/BF,IAAG,MAAQwe,CAAU,IAAI+F,CAAS,GACnC,MAAM,0BACL,MAAKC,GAAA,WAAerhB,EAAM,WAAWohB,CAAS,eAE/CxkB,EAAA,IAAAC,EA0BWkf,SA1BiC3L,EAAoBuD,CAAI,GAAlDtE,EAASwP,4BAA4DxD,CAAU,IAAI+F,CAAS,IAAIvC,CAAY,KAChHxP,EAAQ,OAAI,YAAxBxS,EAA+D,OAAAykB,GAAAhF,EAAvBjN,EAAQ,KAAK,MAClCA,EAAQ,OAAI,QAA/BzS,EAAA,EAAAC,EAAkG,SAAlG0kB,GAAkGjF,EAAzBjN,EAAQ,KAAK,MACvEA,EAAQ,OAAI,UAA3BzS,EAAA,EAAAC,EAA8F,KAA9F2kB,GAA8FlF,EAArBjN,EAAQ,KAAK,MACxEA,EAAQ,OAAI,iBAA1BzS,EAAA,EAAAC,EAA0G,IAA1G4kB,GAA0GnF,EAApBjN,EAAQ,KAAK,MAEtFA,EAAQ,OAAI,YADzBxS,EASI,WAPF,MAAM,oBACL,KAAMuU,EAAY/B,EAAQ,IAAI,EAC/B,OAAO,SACP,IAAI,sBACH,MAAOA,EAAQ,MAEbiN,EAAAjN,EAAQ,WAAW,IAAAqS,EAAA,GAGXrS,EAAQ,OAAI,WADzBxS,EASI,WAPF,MAAM,oBACL,KAAMwS,EAAQ,KACf,OAAO,SACP,IAAI,sBACH,MAAOA,EAAQ,MAEbiN,EAAAjN,EAAQ,KAAK,IAAAsS,EAAA,IAElB/kB,EAAA,EAAAC,EAAmE,OAAnE+kB,GAAmEtF,EAAvBjN,EAAQ,KAAK,mCAKpDrP,EAAM,KAAK,OAAM,OAA9BnD,EAqCQ,QAAAglB,GAAA,EApCNjlB,EAAA,IAAAC,EAmCKkf,SAnCyB/b,EAAM,KAAI,CAA5ByU,EAAKqN,SAAjBjlB,EAmCK,MAnCsC,IAAG,MAAQwe,CAAU,IAAIyG,CAAQ,GAAI,MAAM,4BACpFllB,EAAA,IAAAC,EAiCKkf,EAAA,KAAAC,EAhCyBvH,EAAG,CAAvBd,EAAMyN,SADhBvkB,EAiCK,MA/BF,IAAG,MAAQwe,CAAU,IAAIyG,CAAQ,IAAIV,CAAS,GAC/C,MAAM,qBACL,MAAKC,GAAA,WAAerhB,EAAM,WAAWohB,CAAS,eAE/CxkB,EAAA,IAAAC,EA0BWkf,SA1BiC3L,EAAoBuD,CAAI,GAAlDtE,EAASwP,cAA4D,cAAAxD,CAAU,IAAIyG,CAAQ,IAAIV,CAAS,IAAIvC,CAAY,KAC5HxP,EAAQ,OAAI,YAAxBxS,EAA+D,OAAAklB,GAAAzF,EAAvBjN,EAAQ,KAAK,MAClCA,EAAQ,OAAI,QAA/BzS,EAAA,EAAAC,EAAkG,SAAlGmlB,GAAkG1F,EAAzBjN,EAAQ,KAAK,MACvEA,EAAQ,OAAI,UAA3BzS,EAAA,EAAAC,EAA8F,KAA9FolB,GAA8F3F,EAArBjN,EAAQ,KAAK,MACxEA,EAAQ,OAAI,iBAA1BzS,EAAA,EAAAC,EAA0G,IAA1GqlB,GAA0G5F,EAApBjN,EAAQ,KAAK,MAEtFA,EAAQ,OAAI,YADzBxS,EASI,WAPF,MAAM,oBACL,KAAMuU,EAAY/B,EAAQ,IAAI,EAC/B,OAAO,SACP,IAAI,sBACH,MAAOA,EAAQ,MAEbiN,EAAAjN,EAAQ,WAAW,IAAA8S,EAAA,GAGX9S,EAAQ,OAAI,WADzBxS,EASI,WAPF,MAAM,oBACL,KAAMwS,EAAQ,KACf,OAAO,SACP,IAAI,sBACH,MAAOA,EAAQ,MAEbiN,EAAAjN,EAAQ,KAAK,IAAA+S,EAAA,IAElBxlB,EAAA,EAAAC,EAAmE,OAAnEwlB,GAAmE/F,EAAvBjN,EAAQ,KAAK,0DAOrDrP,EAAM,OAAI,aAA1BpD,EAAA,EAAAC,EAGM,MAHNylB,GAGM,CAFOtiB,EAAM,UAAjBpD,EAAA,EAAAC,EAAmF,MAAnF0lB,GAAmFjG,EAAvBtc,EAAM,QAAQ,eAC1EhD,EAAgI,MAAhIwlB,GAAgI,CAAlGxlB,EAA4F,QAAtF,MAAM,OAAO,UAAQgb,GAA4BhY,EAAM,SAAUA,EAAM,KAAK,mBAEnGA,EAAM,OAAI,iBAAzBpD,EAAA,EAAAC,EAAyE,KAAzE4lB,EAAyE,GAC3DnH,GAAsBnc,EAAQ,GAAIkc,CAAU,GAA1Dze,EAAA,EAAAC,EAA0G,IAA1G6lB,GAA0GpG,EAArBtc,EAAM,QAAQ,WACnGnD,EAaS,iBAXP,MAAM,uBACN,KAAK,SACJ,QAAKuf,GAAEZ,GAAexb,EAAM,GAAG,IAEhChD,EAME,OALA,MAAM,+CACL,IAAKgD,EAAM,IACX,IAAKA,EAAM,KAAG,yBACf,QAAQ,OACP,WAAOub,GAAqBpc,EAAQ,GAAIkc,CAAU,wDAO9CxQ,GAA8B1L,CAAO,GAApDvC,IAAAC,EAiEU,UAjEV8lB,GAiEU,CAhER3lB,EAoBS,UAnBP,KAAK,SACL,MAAKmf,EAAA,CAAC,4DAA2D,gBACvCta,GAA4B1C,CAAO,KAC5D,QAAKid,GAAExa,GAAwBzC,CAAO,IAEvCnC,EAAwG,QAAlG,MAAKmf,EAAA,CAAC,cAAa,oBAA+Bta,GAA4B1C,CAAO,MAAK,IAAC,GACjGnC,EAEO,OAFP4lB,GAEOtG,EADFzQ,GAAuBhB,GAA8B1L,CAAO,OAEjEnC,EASO,OATP6lB,GASO,EARLjmB,EAAA,IAAAC,EAOOkf,SANU/P,GAA6BnB,GAA8B1L,CAAO,GAA1E8G,QADTpJ,EAOO,QALJ,IAAG,kBAAoBsC,EAAQ,EAAE,IAAI8G,EAAK,IAAI,IAAIA,EAAK,KAAK,GAC7D,MAAM,2BACL,YAAWA,EAAK,MAEdqW,EAAArW,EAAK,KAAK,IAAA6c,EAAA,oBAInB9lB,EA0CM,OA1CD,MAAKmf,EAAA,CAAC,iBAAgB,qBAAgCta,GAA4B1C,CAAO,OAC5FnC,EAwCM,MAxCN+lB,GAwCM,CAvCJ/lB,EAsCK,KAtCLgmB,GAsCK,EArCHpmB,EAAA,IAAAC,EAoCKkf,WAnCckH,EAAApY,GAA8B1L,CAAO,IAArC,YAAA8jB,EAAwC,aAAlDlhB,QADTlF,EAoCK,MAlCF,IAAG,sBAAwBsC,EAAQ,EAAE,IAAI4C,EAAO,IAAI,IAAIA,EAAO,aAAW,KAC3E,MAAM,qBAEN/E,EAEO,QAFD,MAAM,oBAAqB,iBAAgBgO,GAAwBjJ,CAAM,GAC1Eua,EAAAvR,GAAyBhJ,CAAM,KAAAmhB,EAAA,EAEpClmB,EAOS,UANP,KAAK,SACL,MAAM,0BACL,MAAO+E,EAAO,KACd,WAAOC,GAAe6I,GAA8B1L,CAAO,EAAG4C,CAAM,KAElEqK,EAAsBrK,EAAO,IAAI,KAAAohB,EAAA,EAE1BphB,EAAO,iBAAnBlF,EAAkE,OAAlEumB,GAA0D,GAAC,YAEnDrhB,EAAO,iBADflF,EAQS,gBANP,KAAK,SACL,MAAM,0BACL,MAAOkF,EAAO,YACd,WAAOC,GAAe6I,GAA8B1L,CAAO,EAAG4C,CAAM,KAElEqK,EAAsBrK,EAAO,WAAW,KAAAshB,EAAA,YAEjCthB,EAAO,eAAc,GAAQA,EAAO,iBAAgB,GAAhEnF,IAAAC,EASO,OATPymB,GASO,EARL1mB,EAAA,IAAAC,EAOOkf,EAAA,KAAAC,EANU1Q,GAAqBvJ,CAAM,EAAnCkE,QADTpJ,EAOO,QALJ,IAAG,uBAAyBsC,EAAQ,EAAE,IAAI4C,EAAO,IAAI,IAAIkE,EAAK,IAAI,IAAIA,EAAK,KAAK,GACjF,MAAM,2BACL,YAAWA,EAAK,MAEdqW,EAAArW,EAAK,KAAK,IAAAsd,EAAA,oDAUnBva,GAAuB7J,CAAO,GAAKiP,GAAmBjP,CAAO,OADrEtC,EAuCM,aArCJ,MAAM,kBACL,YAAWsC,EAAQ,OAGZiP,GAAmBjP,CAAO,OADlCtC,EAUS,gBARP,KAAK,SACL,MAAM,0BACN,aAAW,4BACX,MAAM,4BACL,QAAKuf,GAAE/N,GAAiBlP,EAAQ,EAAE,IAEnCqkB,EAAgEC,GAAA,CAAzC,MAAM,iCAAgC,EAC7D1mB,EAAA,KAAAA,EAAA,GAAAC,EAAoD,QAA9C,MAAM,0BAAyB,WAAQ,sBAGvCiM,GAAuB9J,CAAO,OADtCtC,EAUS,gBARP,KAAK,SACL,MAAM,sBACN,aAAW,iCACX,MAAM,iCACL,QAAKuf,GAAErO,GAAa5O,EAAQ,EAAE,IAE/BqkB,EAAwDE,GAAA,CAArC,MAAM,6BAA4B,EACrD3mB,EAAA,KAAAA,EAAA,GAAAC,EAA4C,QAAtC,MAAM,sBAAqB,OAAI,sBAG/BgM,GAAuB7J,CAAO,OADtCtC,EAWS,gBATP,KAAK,SACL,MAAM,sBACL,cAAa6G,EAAA,QAA2BvE,EAAQ,GAChD,aAAYuE,EAAA,QAA2BvE,EAAQ,GAAE,kCACjD,MAAOuE,EAAA,QAA2BvE,EAAQ,GAAE,kCAC5C,QAAKid,GAAEvO,GAAa1O,EAAQ,EAAE,IAE/BqkB,EAAqDG,GAAA,CAArC,MAAM,6BAA4B,EAClD3mB,EAAuG,OAAvG4mB,GAAuGtH,EAAnE5Y,UAA2BvE,EAAQ,GAAE,0GAQ3EiE,EAAA,aAAVxG,EAAA,EAAAC,EAeK,KAfLgnB,GAeK,CAdH7mB,EAaM,MAbN8mB,GAaM,CAZJ9mB,EAWM,MAXN+mB,GAWM,CAVJ/mB,EASU,UATVgnB,GASU,CARRhnB,EAAiE,IAAjEinB,GAAiE3H,EAAhClZ,EAAA,YAAY,aAAa,KAElDA,EAAA,YAAY,eADpBxG,EAAA,EAAAC,EAKI,IALJqnB,GAKI5H,EADClZ,EAAA,YAAY,aAAa,eAErBA,EAAA,YAAY,WAArBxG,EAAA,EAAAC,EAA0F,IAA1FsnB,GAA0F7H,EAA5BlZ,EAAA,YAAY,SAAS,iCAK3FpG,EAA+D,cAAvD,kBAAJ,IAAIwG,GAAkB,MAAM,+CAI1BiB,GAAA,WADR5H,EASS,gBAPP,KAAK,SACL,MAAM,wBACN,MAAM,iBACN,aAAW,wBACV,QAAOmd,EAAA,GAERwJ,EAA0DY,GAAA,CAAvC,MAAM,+BAA8B,cAG9C3gB,GAAA,MAAc,OAAM,OAA/B5G,EAOM,aAP+B,MAAM,uBAAwB,QAAO4e,EAAA,GACxEze,EAKM,OALD,MAAM,sBAAuB,uBAAD,OAAW,aAC1CA,EAES,UAFD,MAAM,oBAAoB,KAAK,SAAS,aAAW,sBAAuB,QAAOye,EAAA,GACvF+H,EAAgCa,GAAA,CAAnB,MAAM,WAAU,IAE/BrnB,EAAmF,OAA9E,MAAM,oBAAqB,IAAKyG,GAAA,MAAe,IAAI,mDAKpD1F,GAAA,WADRlB,EAqBM,qBAnBA,yBAAJ,IAAIiB,GACJ,MAAM,yBACL,SAAO0T,GAAA,KAAwB,EAC/B,uBAAD,OAAW,aAEXxU,EAES,UAFD,KAAK,SAAS,MAAM,8BAA+B,QAAOgV,EAAA,EAA2B,aAE7F,EACAhV,EAES,UAFD,KAAK,SAAS,MAAM,8BAA+B,QAAOkV,EAAA,EAAyB,aAE3F,EAEQ/T,GAAA,WADRtB,EAOS,gBALP,KAAK,SACL,MAAM,8BACL,QAAOoV,EAAA,EACT,aAED,0BAGSrF,EAAA,WAAX/P,EAmHM,aAnH6B,MAAM,uBAAwB,QAAOqF,EAAA,GACtElF,EAiHM,OAjHD,MAAM,oBAAqB,uBAAD,OAAW,aAC1BsnB,GAAAlmB,EAAA,YAAdxB,IAAAC,EAwBQ,QAxBR0nB,GAwBQ,CAvBNvnB,EAGM,MAHNwnB,GAGM,CAFJznB,EAAA,MAAAA,EAAA,IAAAC,EAAsD,KAAnD,MAAM,6BAA4B,gBAAa,KAClDA,EAAmG,IAAnGynB,GAAmGnI,EAA3D/Q,GAA2BoB,GAAA,MAAkB,MAAM,QAE7F3P,EAkBM,MAlBN0nB,GAkBM,QAjBJ7nB,EAgBSkf,EAAA,KAAAC,EAfUrP,GAAA,MAAV5K,QADTlF,EAgBS,UAdN,IAAG,eAAiBiF,EAAcC,CAAM,IACzC,KAAK,SACL,MAAM,0BACL,cAAaD,EAAcC,CAAM,IAAMD,EAAc8K,EAAA,KAAsB,EAC3E,QAAKwP,GAAE/Z,GAAuBN,CAAM,IAErC/E,EAEO,QAFD,MAAM,oBAAqB,iBAAgBgO,GAAwBjJ,CAAM,GAC1Eua,EAAAvR,GAAyBhJ,CAAM,KAAA4iB,EAAA,EAEpC3nB,EAGO,OAHP4nB,GAGO,CAFFC,EAAAvI,EAAAlQ,EAAsBrK,EAAO,IAAI,GAAI,IACxC,GAAgBA,EAAO,iBAAvBlF,EAAiGkf,EAAA,SAA7D8I,EAAA,MAAGvI,EAAGlQ,EAAsBrK,EAAO,WAAW,uBAExEkJ,EAAsBlJ,CAAM,GAAxCnF,EAAA,EAAAC,EAAoH,OAApHioB,GAAoHxI,EAAvCrR,EAAsBlJ,CAAM,oCAK/G/E,EAkDU,UAlDV+nB,GAkDU,CAjDR/nB,EAwBM,MAxBNgoB,GAwBM,CAvBJhoB,EASM,MATNioB,GASM,CARJjoB,EAGI,IAHJkoB,GAGI,CAFCL,EAAAvI,EAAAlQ,EAAsBQ,EAAA,MAAuB,IAAI,GAAI,IACxD,GAAgBA,EAAA,MAAuB,iBAAvC/P,EAAiIkf,EAAA,SAA7E8I,EAAA,MAAGvI,EAAGlQ,EAAsBQ,EAAA,MAAuB,WAAW,uBAEpH5P,EAGI,IAHJmoB,GAGI,KAFCpa,GAAyB6B,EAAA,KAAsB,GAAI,IACtD,GAAY3B,EAAsB2B,EAAA,KAAsB,GAAxDhQ,IAAAC,EAAwH,OAAAuoB,GAA7D,MAAG9I,EAAGrR,EAAsB2B,EAAA,KAAsB,oBAGjH5P,EAYM,MAZNqoB,GAYM,CAVIf,GAAAlmB,EAAA,OADRvB,EAOS,gBALP,KAAK,SACL,MAAM,kCACL,QAAOsF,EAAA,IAELoJ,GAA2BoB,GAAA,MAAkB,MAAM,gBAExD3P,EAES,UAFD,MAAM,sCAAsC,KAAK,SAAS,aAAW,oBAAqB,QAAOkF,EAAA,GACvGshB,EAAgCa,GAAA,CAAnB,MAAM,WAAU,QAKvB5W,GAAqBb,EAAA,KAAsB,GAKvDhQ,IAAAC,EAiBM,MAjBNyoB,GAiBM,CAhBJtoB,EAEM,MAFNuoB,GAEM,CADJvoB,EAAyG,OAAzGwoB,GAAyGlJ,EAAnEzP,GAAwBD,EAAA,KAAsB,gBAEtF5P,EAYM,MAZNyoB,GAYM,QAXJ5oB,EAUMkf,EAAA,KAAAC,EATWxO,GAAA,MAAR7O,QADT9B,EAUM,OARH,IAAK8B,EAAK,IACX,MAAM,mBACL,YAAWA,EAAK,OAEjB3B,EAAqE,OAArE0oB,GAAqEpJ,EAA5B3d,EAAK,SAAO,OACrD3B,EAAqE,OAArE2oB,GAAqErJ,EAA5B3d,EAAK,SAAO,OACrD3B,EAAyE,OAAzE4oB,GAAyEtJ,EAAhC5O,GAAiB/O,CAAI,MAC9D3B,EAAsF,QAAhF,MAAM,wBAAwB,UAAQ6a,EAAWlZ,EAAK,IAAI,wCAnBtE/B,IAAAC,EAGM,MAHNgpB,GAGM,IAAA9oB,EAAA,MAAAA,EAAA,KAFJC,EAAwD,KAArD,MAAM,2BAA0B,oBAAiB,IACpDA,EAAqK,KAAlK,MAAM,0BAAyB,kIAA+H,WAuBrKwmB,EAiCasC,GAAA,CAjCD,KAAK,qBAAmB,YAClC,IA+BM,CA9BExB,GAAAlmB,EAAA,GAAYP,EAAA,WADpBhB,EA+BM,aA7BJ,MAAM,oCACL,QAAOuF,EAAA,GAERpF,EAyBM,OAzBD,MAAM,2BAA4B,uBAAD,OAAW,2BAC/CA,EAAsE,OAAjE,MAAM,kCAAkC,cAAY,kBACzDA,EAGM,MAHN+oB,GAGM,CAFJhpB,EAAA,MAAAA,EAAA,IAAAC,EAAsD,KAAnD,MAAM,6BAA4B,gBAAa,KAClDA,EAAmG,IAAnGgpB,GAAmG1J,EAA3D/Q,GAA2BoB,GAAA,MAAkB,MAAM,QAE7F3P,EAkBM,MAlBNipB,GAkBM,QAjBJppB,EAgBSkf,EAAA,KAAAC,EAfUrP,GAAA,MAAV5K,QADTlF,EAgBS,UAdN,IAAG,qBAAuBiF,EAAcC,CAAM,IAC/C,KAAK,SACL,MAAM,0BACL,cAAaD,EAAcC,CAAM,IAAMD,EAAc8K,EAAA,KAAsB,EAC3E,QAAKwP,GAAE/Z,GAAuBN,CAAM,IAErC/E,EAEO,QAFD,MAAM,oBAAqB,iBAAgBgO,GAAwBjJ,CAAM,GAC1Eua,EAAAvR,GAAyBhJ,CAAM,KAAAmkB,EAAA,EAEpClpB,EAGO,OAHPmpB,GAGO,CAFFtB,EAAAvI,EAAAlQ,EAAsBrK,EAAO,IAAI,GAAI,IACxC,GAAgBA,EAAO,iBAAvBlF,EAAiGkf,EAAA,SAA7D8I,EAAA,MAAGvI,EAAGlQ,EAAsBrK,EAAO,WAAW,uBAExEkJ,EAAsBlJ,CAAM,GAAxCnF,EAAA,EAAAC,EAAoH,OAApHupB,GAAoH9J,EAAvCrR,EAAsBlJ,CAAM","names":["_openBlock","_createElementBlock","_hoisted_1","_cache","_createElementVNode","BOTTOM_THRESHOLD_PX","RENDER_WINDOW_SIZE","LOAD_MORE_CHUNK","LOAD_MORE_SCROLL_THRESHOLD_PX","expandedCommandIds","ref","collapsedAutoCommandIds","expandedCommandGroupIds","expandedWorkedIds","expandedFileChangeSummaryIds","activeDiffViewerSummary","activeDiffViewerChangeKey","isDiffViewerFileListOpen","fileLinkContextMenuRef","isFileLinkContextMenuVisible","fileLinkContextMenuX","fileLinkContextMenuY","fileLinkContextBrowseUrl","fileLinkContextEditUrl","isMobile","useMobile","parsePlanFromMessageText","text","normalized","steps","explanationLines","line","trimmed","match","marker","status","_a","step","readPlanData","message","isCommandMessage","isPlanMessage","isFileChangeMessage","isCopyableAssistantMessage","activeCommandMessageId","computed","index","props","hasLiveAssistantText","isLiveTurnRuntime","groupedCommandsByLatestId","next","block","latest","hiddenGroupedCommandIds","commands","command","readPlanExplanation","readPlanSteps","planStepStatusIcon","isCommandAutoExpanded","isCommandExpanded","isCommandCompact","isCommandOutputCondensed","toggleCommandExpand","nextExpanded","nextCollapsedAuto","isAutoExpanded","getGroupedCommandsForLatest","getCommandBlockForLatest","toggleCommandGroup","isCommandGroupExpanded","commandGroupSummaryLabel","count","latestCommand","_b","commandGroupSummaryStatus","commandStatusLabel","toggleWorkedExpand","isWorkedExpanded","toggleFileChangeSummary","isFileChangeSummaryExpanded","fileChangeKey","change","openDiffViewer","summary","closeDiffViewer","toggleDiffViewerFileList","closeDiffViewerFileList","selectDiffViewerChange","ce","compact","commandStatusClass","s","pruneCommandIdSet","source","validIds","id","getCommandsForWorked","messages","workedIndex","result","i","m","__props","emit","__emit","conversationListRef","bottomAnchorRef","modalImageUrl","copiedResponseAnchorId","localScrollState","autoFollowOutput","CODE_LANGUAGE_ALIASES","scrollRestoreFrame","bottomLockFrame","bottomLockFramesLeft","copiedMessageResetTimer","trackedPendingImages","highlightJsModule","highlightJsLoader","renderWindowStart","isLoadingMore","visibleMessages","hasMoreAbove","showJumpToLatestButton","ensureHighlightJsLoaded","__vitePreload","module","isFilePath","value","looksLikeUnixAbsolute","looksLikeWindowsAbsolute","looksLikeRelative","getBasename","pathValue","normalizePathSeparators","normalizeFileUrlToPath","stripped","inferHomeFromCwd","cwd","userMatch","homeMatch","normalizePathDots","root","rest","driveMatch","parts","stack","part","joined","resolveRelativePath","normalizedPath","homeBase","base","parseFileReference","trimLinkWrappers","hashLineMatch","colonLineMatch","core","leading","trailing","parseMarkdownLinkToken","labelCloseIndex","labelRaw","targetRaw","label","target","headingTag","level","normalizedLevel","headingClass","planStepCopyMarker","buildPlanCopyText","planData","sections","buildCopyableMessageContent","rawTextContent","textContent","attachmentLines","attachment","imageLines","imageUrl","copyableResponseContentByAnchorId","groupedResponses","content","responseKey","existing","response","anchorMessageId","anchoredFileChangeSummaryByAnchorId","fileChangeCopy","buildFileChangeCopyText","forkableTurnIndexByAnchorId","groupedTurns","groupedTurn","showCopyResponseButton","showForkResponseButton","mergeFileChangeDiff","first","second","mergeFileChangeEntry","operation","compareFileChanges","firstRank","secondRank","firstPath","secondPath","aggregateFileChanges","changes","byPath","key","previous","assistantAnchorIdByTurnKey","assistantSummaryByAnchorId","fileChangeMessagesByTurnKey","turnKey","current","summaries","anchorId","standaloneFileChangeSummaryByMessageId","visibleMessage","hiddenFileChangeMessageIds","messageId","sourceMessageId","readAnchoredFileChangeSummary","readStandaloneFileChangeSummary","fileChangeOperationLabel","fileChangeOperationTone","formatFileChangeDelta","buildFileChangeDeltaParts","addedCount","removedCount","fallbackLabel","fileChangeDeltaParts","formatFileChangeCountLabel","summarizeFileChangeKinds","added","deleted","edited","moved","fileChangeSummaryLabel","countLabel","kindSummary","fileChangeSummaryStatusParts","totalAdded","sum","totalRemoved","displayFileChangePath","resolved","normalizedCwd","normalizedResolved","pathLabel","movedLabel","delta","diffViewerChanges","activeDiffViewerChange","inferDiffViewerLanguage","extension","hasStructuredUnifiedDiff","buildSyntheticDiffLines","lines","buildUnifiedDiffLines","output","oldLine","newLine","hunkMatch","buildDiffViewerLines","activeDiffViewerLines","hasDiffViewerContent","diffViewerMarker","copyTextWithSelectionFallback","textarea","copyResponse","copied","forkResponse","turnIndex","rollbackTurnIdByAnchorId","turnId","entry","showRollbackButton","rollbackResponse","splitPlainTextByLinks","segments","pattern","cursor","start","end","token","trailingPunctuation","wrapped","applyInlineMarkdownMarkers","applyDelimitedMarkersAcrossTextSegments","options","isOpen","buffer","pushText","segment","remaining","markerIndex","before","nonWhitespaceWrapped","splitTextByFileUrls","scanFrom","findNextMarkdownLink","fromIndex","linkStart","labelEnd","depth","hasNewLine","char","markdownToken","parseInlineSegments","linkFirstSegments","textStart","openLength","delimiter","searchFrom","closingStart","candidate","hasBacktickBefore","hasBacktickAfter","hasNewLineInside","markdownLink","markdownFileReference","fileReference","displayPath","toRenderableImageUrl","toBrowseUrl","looksLikeAbsolutePath","parsed","candidatePath","fileLinkContextMenuStyle","toEditUrlFromBrowseHref","href","normalizedHref","onConversationContextMenu","event","anchor","closeFileLinkContextMenu","openFileLinkContextBrowse","openFileLinkContextEdit","copyFileLinkContextLink","onWindowPointerDownForFileLinkContextMenu","menu","onWindowBlurForFileLinkContextMenu","onWindowKeydownForFileLinkContextMenu","normalizeMarkdownText","leadingIndentWidth","stripIndentedContent","baseIndent","width","character","isBlankMarkdownLine","readHeading","readBlockquoteLine","readUnorderedListItem","readUnorderedListItemMatch","readTaskListItem","readTaskListItemMatch","readOrderedListItemData","readOrderedListItem","readOrderedListItemMatch","splitMarkdownTableRow","cells","codeFenceLength","runLength","cell","readTableAlignmentRow","alignments","startsWithColon","endsWithColon","alignment","normalizeTableCells","readTableBlock","startIndex","headerLine","separatorLine","headers","trimmedHeader","rows","row","isParagraphBreakingLine","readFenceStart","isThematicBreakLine","readListParagraph","paragraphLines","findNextNonBlankLineIndex","readNestedListBlocks","parentIndent","stopAtItem","allowLooseChildLists","nestedLines","nextNonBlankIndex","nextStopItem","stopItem","lineIndent","isLooseChildList","parseTextBlocks","readListItems","readItem","items","firstItem","itemValue","paragraphs","children","nextSameLevelItem","hasIndentedChildren","hasLooseChildList","nestedBlocks","continuation","blocks","fence","codeLines","heading","quoteLines","nextQuoteLine","table","nextItem","unorderedItem","parsedList","orderedItem","orderedItemMatch","parseNonCodeMessageBlocks","imagePattern","fullMatch","altRaw","urlRaw","parseMessageBlocks","chunkStart","flushChunk","endExclusive","chunk","escapeHtml","normalizeCodeLanguage","language","renderHighlightedCodeAsHtml","normalizedLanguage","highlighter","renderInlineSegmentsAsHtml","renderListItemParagraphsAsHtml","item","paragraph","renderListItemContentAsHtml","paragraphsHtml","childrenHtml","renderMessageBlockAsHtml","tableCellAlignmentStyle","tag","classes","headerCells","body","renderMarkdownBlocksAsHtml","scrollToBottom","container","isAtBottom","emitScrollState","maxScrollTop","scrollRatio","applySavedScrollState","enforceBottomState","savedState","targetScrollTop","shouldLockToBottom","runBottomLockFrame","scheduleBottomLock","frames","onPendingImageSettled","jumpToLatest","loadMoreAbove","threadIdAtStart","prevScrollHeight","prevScrollTop","nextTick","__expose","bindPendingImageHandlers","images","image","scheduleScrollRestore","watch","commandIds","hasCodeBlocks","nextId","prevId","overlay","loading","onConversationScroll","failedMarkdownImages","markdownImageKey","blockIndex","isMarkdownImageFailed","onMarkdownImageError","openImageModal","closeImageModal","onMounted","onBeforeUnmount","_hoisted_2","_hoisted_3","_hoisted_4","_Fragment","_renderList","_hoisted_6","_hoisted_7","_normalizeClass","$event","_hoisted_9","_toDisplayString","_hoisted_10","_hoisted_11","cmd","_hoisted_13","_hoisted_14","_hoisted_15","_hoisted_18","_hoisted_19","_hoisted_20","_hoisted_25","_hoisted_27","_hoisted_28","_hoisted_29","_hoisted_30","_hoisted_31","_c","_hoisted_32","_hoisted_33","_hoisted_34","_hoisted_35","_hoisted_36","_hoisted_37","_hoisted_44","att","_hoisted_45","_hoisted_47","_hoisted_49","_hoisted_50","_hoisted_52","_hoisted_53","_hoisted_54","_hoisted_57","_hoisted_58","_hoisted_60","stepIndex","_hoisted_62","_hoisted_65","_hoisted_66","segmentIndex","_hoisted_67","_hoisted_68","_hoisted_69","_hoisted_70","_hoisted_71","_hoisted_72","_hoisted_73","_createBlock","_resolveDynamicComponent","_hoisted_74","_hoisted_75","_hoisted_76","_hoisted_77","_hoisted_78","_hoisted_79","_hoisted_80","_hoisted_81","_hoisted_82","_hoisted_83","_hoisted_84","_hoisted_85","_hoisted_86","_hoisted_87","_hoisted_88","_hoisted_89","itemIndex","_hoisted_91","_hoisted_92","_hoisted_93","_hoisted_94","_hoisted_95","_hoisted_96","_hoisted_97","_hoisted_98","_hoisted_99","_hoisted_100","_hoisted_103","_hoisted_104","cellIndex","_normalizeStyle","_hoisted_105","_hoisted_106","_hoisted_107","_hoisted_108","_hoisted_109","_hoisted_110","_hoisted_111","_hoisted_112","rowIndex","_hoisted_113","_hoisted_114","_hoisted_115","_hoisted_116","_hoisted_117","_hoisted_118","_hoisted_119","_hoisted_120","_hoisted_121","_hoisted_122","_hoisted_124","_hoisted_125","_hoisted_128","_hoisted_130","_hoisted_131","_hoisted_132","_hoisted_133","_hoisted_134","_d","_hoisted_135","_hoisted_136","_hoisted_137","_hoisted_138","_hoisted_139","_hoisted_140","_createVNode","IconTablerArrowBackUp","IconTablerGitFork","IconTablerCopy","_hoisted_145","_hoisted_146","_hoisted_147","_hoisted_148","_hoisted_149","_hoisted_150","_hoisted_151","_hoisted_152","IconTablerArrowUp","IconTablerX","_unref","_hoisted_154","_hoisted_155","_hoisted_156","_hoisted_157","_hoisted_159","_hoisted_160","_createTextVNode","_hoisted_161","_hoisted_162","_hoisted_163","_hoisted_164","_hoisted_165","_hoisted_166","_hoisted_167","_hoisted_168","_hoisted_170","_hoisted_171","_hoisted_172","_hoisted_173","_hoisted_175","_hoisted_176","_hoisted_177","_hoisted_169","_Transition","_hoisted_179","_hoisted_180","_hoisted_181","_hoisted_183","_hoisted_184","_hoisted_185"],"ignoreList":[],"sources":["../../src/components/icons/IconTablerArrowBackUp.vue","../../src/components/icons/IconTablerCopy.vue","../../src/components/content/ThreadConversation.vue"],"sourcesContent":["<template>\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"1em\" height=\"1em\" viewBox=\"0 0 24 24\" aria-hidden=\"true\">\n <path\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n stroke-width=\"2\"\n d=\"M9 14L4 9l5-5m-5 5h11a4 4 0 0 1 0 8H4\"\n />\n </svg>\n</template>\n","<template>\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"1em\" height=\"1em\" viewBox=\"0 0 24 24\" aria-hidden=\"true\">\n <path\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n stroke-width=\"2\"\n d=\"M8 16a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2zm-4 4a2 2 0 0 1-2-2V8m4 8h10\"\n />\n </svg>\n</template>\n","<template>\n <section class=\"conversation-root\" @contextmenu.capture=\"onConversationContextMenu\">\n <p v-if=\"isLoading\" class=\"conversation-loading\">Loading messages...</p>\n\n <p\n v-else-if=\"messages.length === 0 && pendingRequests.length === 0 && !liveOverlay\"\n class=\"conversation-empty\"\n >\n No messages in this thread yet.\n </p>\n\n <ul v-else ref=\"conversationListRef\" class=\"conversation-list\" @scroll=\"onConversationScroll\">\n <li v-if=\"hasMoreAbove\" class=\"conversation-load-more\">\n <button\n type=\"button\"\n class=\"load-more-button\"\n :disabled=\"isLoadingMore\"\n @click=\"loadMoreAbove\"\n >\n {{ isLoadingMore ? 'Loading…' : 'Load earlier messages' }}\n </button>\n </li>\n <template v-for=\"message in visibleMessages\" :key=\"message.id\">\n <li\n v-if=\"!hiddenGroupedCommandIds.has(message.id) && !hiddenFileChangeMessageIds.has(message.id)\"\n class=\"conversation-item\"\n :data-role=\"message.role\"\n :data-message-type=\"message.messageType || ''\"\n >\n <div v-if=\"isCommandMessage(message)\" class=\"message-row\" data-role=\"system\">\n <div class=\"message-stack\" data-role=\"system\">\n <button\n v-if=\"getGroupedCommandsForLatest(message).length > 0\"\n type=\"button\"\n class=\"cmd-row cmd-row-group cmd-compact\"\n :class=\"[commandStatusClass(message), { 'cmd-expanded': isCommandGroupExpanded(message) }]\"\n @click=\"toggleCommandGroup(message)\"\n >\n <span class=\"cmd-chevron\" :class=\"{ 'cmd-chevron-open': isCommandGroupExpanded(message) }\">▶</span>\n <span class=\"cmd-group-label\">{{ commandGroupSummaryLabel(message) }}</span>\n <span class=\"cmd-status\">{{ commandGroupSummaryStatus(message) }}</span>\n </button>\n <div\n v-if=\"getGroupedCommandsForLatest(message).length > 0\"\n class=\"cmd-group-wrap\"\n :class=\"{ 'cmd-group-visible': isCommandGroupExpanded(message) }\"\n >\n <div class=\"cmd-group-inner\">\n <div\n v-for=\"cmd in getCommandBlockForLatest(message)\"\n :key=\"`grouped-cmd-${cmd.id}`\"\n class=\"worked-cmd-item\"\n >\n <button\n type=\"button\"\n class=\"cmd-row\"\n :class=\"[\n commandStatusClass(cmd),\n {\n 'cmd-expanded': isCommandExpanded(cmd),\n 'cmd-compact': true,\n },\n ]\"\n @click=\"toggleCommandExpand(cmd)\"\n >\n <span class=\"cmd-chevron\" :class=\"{ 'cmd-chevron-open': isCommandExpanded(cmd) }\">▶</span>\n <code class=\"cmd-label\">{{ cmd.commandExecution?.command || '(command)' }}</code>\n <span class=\"cmd-status\">{{ commandStatusLabel(cmd) }}</span>\n </button>\n <div\n class=\"cmd-output-wrap\"\n :class=\"{ 'cmd-output-visible': isCommandExpanded(cmd) }\"\n >\n <div class=\"cmd-output-inner\">\n <pre\n class=\"cmd-output\"\n :class=\"{ 'cmd-output-condensed': isCommandOutputCondensed(cmd) }\"\n v-text=\"cmd.commandExecution?.aggregatedOutput || '(no output)'\"\n ></pre>\n </div>\n </div>\n </div>\n </div>\n </div>\n <template v-else>\n <button\n type=\"button\"\n class=\"cmd-row\"\n :class=\"[\n commandStatusClass(message),\n {\n 'cmd-expanded': isCommandExpanded(message),\n 'cmd-compact': isCommandCompact(message),\n },\n ]\"\n @click=\"toggleCommandExpand(message)\"\n >\n <span class=\"cmd-chevron\" :class=\"{ 'cmd-chevron-open': isCommandExpanded(message) }\">▶</span>\n <code class=\"cmd-label\">{{ message.commandExecution?.command || '(command)' }}</code>\n <span class=\"cmd-status\">{{ commandStatusLabel(message) }}</span>\n </button>\n <div\n class=\"cmd-output-wrap\"\n :class=\"{ 'cmd-output-visible': isCommandExpanded(message) }\"\n >\n <div class=\"cmd-output-inner\">\n <pre\n class=\"cmd-output\"\n :class=\"{ 'cmd-output-condensed': isCommandOutputCondensed(message) }\"\n v-text=\"message.commandExecution?.aggregatedOutput || '(no output)'\"\n ></pre>\n </div>\n </div>\n </template>\n </div>\n </div>\n\n <div\n v-else-if=\"isFileChangeMessage(message)\"\n class=\"message-row\"\n :data-role=\"message.role\"\n :data-message-type=\"message.messageType || ''\"\n >\n <div class=\"message-stack\" :data-role=\"message.role\">\n <article class=\"message-body\" :data-role=\"message.role\">\n <section v-if=\"readStandaloneFileChangeSummary(message)\" class=\"file-change-summary-block\">\n <button\n type=\"button\"\n class=\"cmd-row cmd-row-group cmd-compact file-change-summary-row\"\n :class=\"{ 'cmd-expanded': isFileChangeSummaryExpanded(message) }\"\n @click=\"toggleFileChangeSummary(message)\"\n >\n <span class=\"cmd-chevron\" :class=\"{ 'cmd-chevron-open': isFileChangeSummaryExpanded(message) }\">▶</span>\n <span class=\"file-change-summary-label\">\n {{ fileChangeSummaryLabel(readStandaloneFileChangeSummary(message)) }}\n </span>\n <span class=\"file-change-summary-status\">\n <span\n v-for=\"part in fileChangeSummaryStatusParts(readStandaloneFileChangeSummary(message))\"\n :key=\"`summary-status:${message.id}:${part.tone}:${part.label}`\"\n class=\"file-change-signed-count\"\n :data-tone=\"part.tone\"\n >\n {{ part.label }}\n </span>\n </span>\n </button>\n <div class=\"cmd-group-wrap\" :class=\"{ 'cmd-group-visible': isFileChangeSummaryExpanded(message) }\">\n <div class=\"file-change-panel-inner\">\n <ul class=\"file-change-list\">\n <li\n v-for=\"change in readStandaloneFileChangeSummary(message)?.changes ?? []\"\n :key=\"`file-change:${message.id}:${change.path}:${change.movedToPath || ''}`\"\n class=\"file-change-item\"\n >\n <span class=\"file-change-badge\" :data-operation=\"fileChangeOperationTone(change)\">\n {{ fileChangeOperationLabel(change) }}\n </span>\n <button\n type=\"button\"\n class=\"file-change-path-button\"\n :title=\"change.path\"\n @click=\"openDiffViewer(readStandaloneFileChangeSummary(message), change)\"\n >\n {{ displayFileChangePath(change.path) }}\n </button>\n <span v-if=\"change.movedToPath\" class=\"file-change-arrow\">→</span>\n <button\n v-if=\"change.movedToPath\"\n type=\"button\"\n class=\"file-change-path-button\"\n :title=\"change.movedToPath\"\n @click=\"openDiffViewer(readStandaloneFileChangeSummary(message), change)\"\n >\n {{ displayFileChangePath(change.movedToPath) }}\n </button>\n <span v-if=\"change.addedLineCount > 0 || change.removedLineCount > 0\" class=\"file-change-delta\">\n <span\n v-for=\"part in fileChangeDeltaParts(change)\"\n :key=\"`change-delta:${message.id}:${change.path}:${part.tone}:${part.label}`\"\n class=\"file-change-signed-count\"\n :data-tone=\"part.tone\"\n >\n {{ part.label }}\n </span>\n </span>\n </li>\n </ul>\n </div>\n </div>\n </section>\n </article>\n </div>\n </div>\n\n <div v-else class=\"message-row\" :data-role=\"message.role\" :data-message-type=\"message.messageType || ''\">\n <div class=\"message-stack\" :data-role=\"message.role\">\n <article class=\"message-body\" :data-role=\"message.role\">\n <ul\n v-if=\"message.images && message.images.length > 0\"\n class=\"message-image-list\"\n :data-role=\"message.role\"\n >\n <li v-for=\"imageUrl in message.images\" :key=\"imageUrl\" class=\"message-image-item\">\n <button class=\"message-image-button\" type=\"button\" @click=\"openImageModal(imageUrl)\">\n <img class=\"message-image-preview\" :src=\"imageUrl\" alt=\"Message image preview\" loading=\"lazy\" />\n </button>\n </li>\n </ul>\n\n <div v-if=\"message.fileAttachments && message.fileAttachments.length > 0\" class=\"message-file-attachments\">\n <span v-for=\"att in message.fileAttachments\" :key=\"`${message.id}:${att.path}`\" class=\"message-file-chip\">\n <span class=\"message-file-chip-icon\">📄</span>\n <a\n class=\"message-file-link message-file-chip-name\"\n :href=\"toBrowseUrl(att.path)\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n :title=\"att.path\"\n >\n {{ att.label }}\n </a>\n </span>\n </div>\n\n <article v-if=\"message.text.length > 0\" class=\"message-card\" :data-role=\"message.role\">\n <div v-if=\"message.messageType === 'worked'\" class=\"worked-separator-wrap\" aria-live=\"polite\">\n <button type=\"button\" class=\"worked-separator\" @click=\"toggleWorkedExpand(message)\">\n <span class=\"worked-separator-line\" aria-hidden=\"true\" />\n <span class=\"worked-chevron\" :class=\"{ 'worked-chevron-open': isWorkedExpanded(message) }\">▶</span>\n <p class=\"worked-separator-text\">{{ message.text }}</p>\n <span class=\"worked-separator-line\" aria-hidden=\"true\" />\n </button>\n <div v-if=\"isWorkedExpanded(message)\" class=\"worked-details\">\n <div\n v-for=\"cmd in getCommandsForWorked(messages, messages.indexOf(message))\"\n :key=\"`worked-cmd-${cmd.id}`\"\n class=\"worked-cmd-item\"\n >\n <button\n type=\"button\"\n class=\"cmd-row\"\n :class=\"[\n commandStatusClass(cmd),\n {\n 'cmd-expanded': isCommandExpanded(cmd),\n 'cmd-compact': isCommandCompact(cmd),\n },\n ]\"\n @click=\"toggleCommandExpand(cmd)\"\n >\n <span class=\"cmd-chevron\" :class=\"{ 'cmd-chevron-open': isCommandExpanded(cmd) }\">▶</span>\n <code class=\"cmd-label\">{{ cmd.commandExecution?.command || '(command)' }}</code>\n <span class=\"cmd-status\">{{ commandStatusLabel(cmd) }}</span>\n </button>\n <div\n class=\"cmd-output-wrap\"\n :class=\"{ 'cmd-output-visible': isCommandExpanded(cmd) }\"\n >\n <div class=\"cmd-output-inner\">\n <pre\n class=\"cmd-output\"\n :class=\"{ 'cmd-output-condensed': isCommandOutputCondensed(cmd) }\"\n v-text=\"cmd.commandExecution?.aggregatedOutput || '(no output)'\"\n ></pre>\n </div>\n </div>\n </div>\n </div>\n </div>\n <div v-else-if=\"isPlanMessage(message)\" class=\"plan-card\" :data-streaming=\"message.messageType === 'plan.live'\">\n <div class=\"plan-card-header\">\n <p class=\"plan-card-title\">Plan</p>\n <span v-if=\"message.messageType === 'plan.live'\" class=\"plan-card-badge\">Updating</span>\n </div>\n <div\n v-if=\"readPlanExplanation(message)\"\n class=\"plan-card-explanation plan-card-markdown\"\n v-html=\"renderMarkdownBlocksAsHtml(readPlanExplanation(message))\"\n />\n <ol v-if=\"readPlanSteps(message).length > 0\" class=\"plan-step-list\">\n <li\n v-for=\"(step, stepIndex) in readPlanSteps(message)\"\n :key=\"`${message.id}:plan-step:${stepIndex}`\"\n class=\"plan-step-item\"\n :data-status=\"step.status\"\n >\n <span class=\"plan-step-status\" :data-status=\"step.status\">{{ planStepStatusIcon(step.status) }}</span>\n <div class=\"plan-step-text plan-card-markdown\" v-html=\"renderMarkdownBlocksAsHtml(step.step)\" />\n </li>\n </ol>\n <div v-else class=\"plan-card-markdown\" v-html=\"renderMarkdownBlocksAsHtml(message.text)\" />\n </div>\n <div v-else class=\"message-text-flow\">\n <template v-for=\"(block, blockIndex) in parseMessageBlocks(message.text)\" :key=\"`block-${blockIndex}`\">\n <p v-if=\"block.kind === 'paragraph'\" class=\"message-text\">\n <template v-for=\"(segment, segmentIndex) in parseInlineSegments(block.value)\" :key=\"`seg-${blockIndex}-${segmentIndex}`\">\n <span v-if=\"segment.kind === 'text'\">{{ segment.value }}</span>\n <strong v-else-if=\"segment.kind === 'bold'\" class=\"message-bold-text\">{{ segment.value }}</strong>\n <em v-else-if=\"segment.kind === 'italic'\" class=\"message-italic-text\">{{ segment.value }}</em>\n <s v-else-if=\"segment.kind === 'strikethrough'\" class=\"message-strikethrough-text\">{{ segment.value }}</s>\n <a\n v-else-if=\"segment.kind === 'file'\"\n class=\"message-file-link\"\n :href=\"toBrowseUrl(segment.path)\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n :title=\"segment.path\"\n >\n {{ segment.displayPath }}\n </a>\n <a\n v-else-if=\"segment.kind === 'url'\"\n class=\"message-file-link\"\n :href=\"segment.href\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n :title=\"segment.href\"\n >\n {{ segment.value }}\n </a>\n <code v-else class=\"message-inline-code\">{{ segment.value }}</code>\n </template>\n </p>\n <component\n :is=\"headingTag(block.level)\"\n v-else-if=\"block.kind === 'heading'\"\n class=\"message-heading\"\n :class=\"headingClass(block.level)\"\n >\n <template v-for=\"(segment, segmentIndex) in parseInlineSegments(block.value)\" :key=\"`heading-seg-${blockIndex}-${segmentIndex}`\">\n <span v-if=\"segment.kind === 'text'\">{{ segment.value }}</span>\n <strong v-else-if=\"segment.kind === 'bold'\" class=\"message-bold-text\">{{ segment.value }}</strong>\n <em v-else-if=\"segment.kind === 'italic'\" class=\"message-italic-text\">{{ segment.value }}</em>\n <s v-else-if=\"segment.kind === 'strikethrough'\" class=\"message-strikethrough-text\">{{ segment.value }}</s>\n <a\n v-else-if=\"segment.kind === 'file'\"\n class=\"message-file-link\"\n :href=\"toBrowseUrl(segment.path)\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n :title=\"segment.path\"\n >\n {{ segment.displayPath }}\n </a>\n <a\n v-else-if=\"segment.kind === 'url'\"\n class=\"message-file-link\"\n :href=\"segment.href\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n :title=\"segment.href\"\n >\n {{ segment.value }}\n </a>\n <code v-else class=\"message-inline-code\">{{ segment.value }}</code>\n </template>\n </component>\n <blockquote v-else-if=\"block.kind === 'blockquote'\" class=\"message-blockquote\">\n <template v-for=\"(segment, segmentIndex) in parseInlineSegments(block.value)\" :key=\"`quote-seg-${blockIndex}-${segmentIndex}`\">\n <span v-if=\"segment.kind === 'text'\">{{ segment.value }}</span>\n <strong v-else-if=\"segment.kind === 'bold'\" class=\"message-bold-text\">{{ segment.value }}</strong>\n <em v-else-if=\"segment.kind === 'italic'\" class=\"message-italic-text\">{{ segment.value }}</em>\n <s v-else-if=\"segment.kind === 'strikethrough'\" class=\"message-strikethrough-text\">{{ segment.value }}</s>\n <a\n v-else-if=\"segment.kind === 'file'\"\n class=\"message-file-link\"\n :href=\"toBrowseUrl(segment.path)\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n :title=\"segment.path\"\n >\n {{ segment.displayPath }}\n </a>\n <a\n v-else-if=\"segment.kind === 'url'\"\n class=\"message-file-link\"\n :href=\"segment.href\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n :title=\"segment.href\"\n >\n {{ segment.value }}\n </a>\n <code v-else class=\"message-inline-code\">{{ segment.value }}</code>\n </template>\n </blockquote>\n <ul v-else-if=\"block.kind === 'unorderedList'\" class=\"message-list message-list-unordered\">\n <li v-for=\"(item, itemIndex) in block.items\" :key=\"`ul-${blockIndex}-${itemIndex}`\" class=\"message-list-item\">\n <div class=\"message-list-item-content\" v-html=\"renderListItemContentAsHtml(item)\" />\n </li>\n </ul>\n <ul v-else-if=\"block.kind === 'taskList'\" class=\"message-list message-task-list\">\n <li v-for=\"(item, itemIndex) in block.items\" :key=\"`task-${blockIndex}-${itemIndex}`\" class=\"message-task-item\">\n <span class=\"message-task-checkbox\" :data-checked=\"item.checked\">{{ item.checked ? '☑' : '☐' }}</span>\n <div class=\"message-list-item-text\">\n <template v-for=\"(segment, segmentIndex) in parseInlineSegments(item.text)\" :key=\"`task-seg-${blockIndex}-${itemIndex}-${segmentIndex}`\">\n <span v-if=\"segment.kind === 'text'\">{{ segment.value }}</span>\n <strong v-else-if=\"segment.kind === 'bold'\" class=\"message-bold-text\">{{ segment.value }}</strong>\n <em v-else-if=\"segment.kind === 'italic'\" class=\"message-italic-text\">{{ segment.value }}</em>\n <s v-else-if=\"segment.kind === 'strikethrough'\" class=\"message-strikethrough-text\">{{ segment.value }}</s>\n <a\n v-else-if=\"segment.kind === 'file'\"\n class=\"message-file-link\"\n :href=\"toBrowseUrl(segment.path)\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n :title=\"segment.path\"\n >\n {{ segment.displayPath }}\n </a>\n <a\n v-else-if=\"segment.kind === 'url'\"\n class=\"message-file-link\"\n :href=\"segment.href\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n :title=\"segment.href\"\n >\n {{ segment.value }}\n </a>\n <code v-else class=\"message-inline-code\">{{ segment.value }}</code>\n </template>\n </div>\n </li>\n </ul>\n <ol\n v-else-if=\"block.kind === 'orderedList'\"\n class=\"message-list message-list-ordered\"\n :start=\"block.start\"\n >\n <li v-for=\"(item, itemIndex) in block.items\" :key=\"`ol-${blockIndex}-${itemIndex}`\" class=\"message-list-item\">\n <div class=\"message-list-item-content\" v-html=\"renderListItemContentAsHtml(item)\" />\n </li>\n </ol>\n <div v-else-if=\"block.kind === 'table'\" class=\"message-table-wrap\">\n <table class=\"message-table\">\n <thead>\n <tr>\n <th\n v-for=\"(cell, cellIndex) in block.headers\"\n :key=\"`th-${blockIndex}-${cellIndex}`\"\n class=\"message-table-head-cell\"\n :style=\"{ textAlign: block.alignments[cellIndex] ?? 'left' }\"\n >\n <template v-for=\"(segment, segmentIndex) in parseInlineSegments(cell)\" :key=\"`th-seg-${blockIndex}-${cellIndex}-${segmentIndex}`\">\n <span v-if=\"segment.kind === 'text'\">{{ segment.value }}</span>\n <strong v-else-if=\"segment.kind === 'bold'\" class=\"message-bold-text\">{{ segment.value }}</strong>\n <em v-else-if=\"segment.kind === 'italic'\" class=\"message-italic-text\">{{ segment.value }}</em>\n <s v-else-if=\"segment.kind === 'strikethrough'\" class=\"message-strikethrough-text\">{{ segment.value }}</s>\n <a\n v-else-if=\"segment.kind === 'file'\"\n class=\"message-file-link\"\n :href=\"toBrowseUrl(segment.path)\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n :title=\"segment.path\"\n >\n {{ segment.displayPath }}\n </a>\n <a\n v-else-if=\"segment.kind === 'url'\"\n class=\"message-file-link\"\n :href=\"segment.href\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n :title=\"segment.href\"\n >\n {{ segment.value }}\n </a>\n <code v-else class=\"message-inline-code\">{{ segment.value }}</code>\n </template>\n </th>\n </tr>\n </thead>\n <tbody v-if=\"block.rows.length > 0\">\n <tr v-for=\"(row, rowIndex) in block.rows\" :key=\"`tr-${blockIndex}-${rowIndex}`\" class=\"message-table-body-row\">\n <td\n v-for=\"(cell, cellIndex) in row\"\n :key=\"`td-${blockIndex}-${rowIndex}-${cellIndex}`\"\n class=\"message-table-cell\"\n :style=\"{ textAlign: block.alignments[cellIndex] ?? 'left' }\"\n >\n <template v-for=\"(segment, segmentIndex) in parseInlineSegments(cell)\" :key=\"`td-seg-${blockIndex}-${rowIndex}-${cellIndex}-${segmentIndex}`\">\n <span v-if=\"segment.kind === 'text'\">{{ segment.value }}</span>\n <strong v-else-if=\"segment.kind === 'bold'\" class=\"message-bold-text\">{{ segment.value }}</strong>\n <em v-else-if=\"segment.kind === 'italic'\" class=\"message-italic-text\">{{ segment.value }}</em>\n <s v-else-if=\"segment.kind === 'strikethrough'\" class=\"message-strikethrough-text\">{{ segment.value }}</s>\n <a\n v-else-if=\"segment.kind === 'file'\"\n class=\"message-file-link\"\n :href=\"toBrowseUrl(segment.path)\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n :title=\"segment.path\"\n >\n {{ segment.displayPath }}\n </a>\n <a\n v-else-if=\"segment.kind === 'url'\"\n class=\"message-file-link\"\n :href=\"segment.href\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n :title=\"segment.href\"\n >\n {{ segment.value }}\n </a>\n <code v-else class=\"message-inline-code\">{{ segment.value }}</code>\n </template>\n </td>\n </tr>\n </tbody>\n </table>\n </div>\n <div v-else-if=\"block.kind === 'codeBlock'\" class=\"message-code-block\">\n <div v-if=\"block.language\" class=\"message-code-language\">{{ block.language }}</div>\n <pre class=\"message-code-pre\"><code class=\"hljs\" v-html=\"renderHighlightedCodeAsHtml(block.language, block.value)\"></code></pre>\n </div>\n <hr v-else-if=\"block.kind === 'thematicBreak'\" class=\"message-divider\" />\n <p v-else-if=\"isMarkdownImageFailed(message.id, blockIndex)\" class=\"message-text\">{{ block.markdown }}</p>\n <button\n v-else\n class=\"message-image-button\"\n type=\"button\"\n @click=\"openImageModal(block.url)\"\n >\n <img\n class=\"message-image-preview message-markdown-image\"\n :src=\"block.url\"\n :alt=\"block.alt || 'Embedded message image'\"\n loading=\"lazy\"\n @error=\"onMarkdownImageError(message.id, blockIndex)\"\n />\n </button>\n </template>\n </div>\n </article>\n\n <section v-if=\"readAnchoredFileChangeSummary(message)\" class=\"file-change-summary-block file-change-summary-block-inline\">\n <button\n type=\"button\"\n class=\"cmd-row cmd-row-group cmd-compact file-change-summary-row\"\n :class=\"{ 'cmd-expanded': isFileChangeSummaryExpanded(message) }\"\n @click=\"toggleFileChangeSummary(message)\"\n >\n <span class=\"cmd-chevron\" :class=\"{ 'cmd-chevron-open': isFileChangeSummaryExpanded(message) }\">▶</span>\n <span class=\"file-change-summary-label\">\n {{ fileChangeSummaryLabel(readAnchoredFileChangeSummary(message)) }}\n </span>\n <span class=\"file-change-summary-status\">\n <span\n v-for=\"part in fileChangeSummaryStatusParts(readAnchoredFileChangeSummary(message))\"\n :key=\"`summary-status:${message.id}:${part.tone}:${part.label}`\"\n class=\"file-change-signed-count\"\n :data-tone=\"part.tone\"\n >\n {{ part.label }}\n </span>\n </span>\n </button>\n <div class=\"cmd-group-wrap\" :class=\"{ 'cmd-group-visible': isFileChangeSummaryExpanded(message) }\">\n <div class=\"file-change-panel-inner\">\n <ul class=\"file-change-list\">\n <li\n v-for=\"change in readAnchoredFileChangeSummary(message)?.changes ?? []\"\n :key=\"`file-change:inline:${message.id}:${change.path}:${change.movedToPath || ''}`\"\n class=\"file-change-item\"\n >\n <span class=\"file-change-badge\" :data-operation=\"fileChangeOperationTone(change)\">\n {{ fileChangeOperationLabel(change) }}\n </span>\n <button\n type=\"button\"\n class=\"file-change-path-button\"\n :title=\"change.path\"\n @click=\"openDiffViewer(readAnchoredFileChangeSummary(message), change)\"\n >\n {{ displayFileChangePath(change.path) }}\n </button>\n <span v-if=\"change.movedToPath\" class=\"file-change-arrow\">→</span>\n <button\n v-if=\"change.movedToPath\"\n type=\"button\"\n class=\"file-change-path-button\"\n :title=\"change.movedToPath\"\n @click=\"openDiffViewer(readAnchoredFileChangeSummary(message), change)\"\n >\n {{ displayFileChangePath(change.movedToPath) }}\n </button>\n <span v-if=\"change.addedLineCount > 0 || change.removedLineCount > 0\" class=\"file-change-delta\">\n <span\n v-for=\"part in fileChangeDeltaParts(change)\"\n :key=\"`change-delta:inline:${message.id}:${change.path}:${part.tone}:${part.label}`\"\n class=\"file-change-signed-count\"\n :data-tone=\"part.tone\"\n >\n {{ part.label }}\n </span>\n </span>\n </li>\n </ul>\n </div>\n </div>\n </section>\n\n <div\n v-if=\"showCopyResponseButton(message) || showRollbackButton(message)\"\n class=\"message-toolbar\"\n :data-role=\"message.role\"\n >\n <button\n v-if=\"showRollbackButton(message)\"\n type=\"button\"\n class=\"message-rollback-button\"\n aria-label=\"Rollback to this response\"\n title=\"Rollback to this response\"\n @click=\"rollbackResponse(message.id)\"\n >\n <IconTablerArrowBackUp class=\"icon-svg message-rollback-icon\" />\n <span class=\"message-rollback-label\">Rollback</span>\n </button>\n <button\n v-if=\"showForkResponseButton(message)\"\n type=\"button\"\n class=\"message-fork-button\"\n aria-label=\"Fork thread from this response\"\n title=\"Fork thread from this response\"\n @click=\"forkResponse(message.id)\"\n >\n <IconTablerGitFork class=\"icon-svg message-fork-icon\" />\n <span class=\"message-fork-label\">Fork</span>\n </button>\n <button\n v-if=\"showCopyResponseButton(message)\"\n type=\"button\"\n class=\"message-copy-button\"\n :data-copied=\"copiedResponseAnchorId === message.id\"\n :aria-label=\"copiedResponseAnchorId === message.id ? 'Response copied' : 'Copy response'\"\n :title=\"copiedResponseAnchorId === message.id ? 'Response copied' : 'Copy response'\"\n @click=\"copyResponse(message.id)\"\n >\n <IconTablerCopy class=\"icon-svg message-copy-icon\" />\n <span class=\"message-copy-label\">{{ copiedResponseAnchorId === message.id ? 'Copied' : 'Copy' }}</span>\n </button>\n </div>\n </article>\n </div>\n </div>\n </li>\n </template>\n <li v-if=\"liveOverlay\" class=\"conversation-item conversation-item-overlay\">\n <div class=\"message-row\">\n <div class=\"message-stack\">\n <article class=\"live-overlay-inline\" aria-live=\"polite\">\n <p class=\"live-overlay-label\">{{ liveOverlay.activityLabel }}</p>\n <p\n v-if=\"liveOverlay.reasoningText\"\n class=\"live-overlay-reasoning\"\n >\n {{ liveOverlay.reasoningText }}\n </p>\n <p v-if=\"liveOverlay.errorText\" class=\"live-overlay-error\">{{ liveOverlay.errorText }}</p>\n </article>\n </div>\n </div>\n </li>\n <li ref=\"bottomAnchorRef\" class=\"conversation-bottom-anchor\" />\n </ul>\n\n <button\n v-if=\"showJumpToLatestButton\"\n type=\"button\"\n class=\"jump-to-latest-button\"\n title=\"Jump to latest\"\n aria-label=\"Jump to latest output\"\n @click=\"jumpToLatest\"\n >\n <IconTablerArrowUp class=\"icon-svg jump-to-latest-icon\" />\n </button>\n\n <div v-if=\"modalImageUrl.length > 0\" class=\"image-modal-backdrop\" @click=\"closeImageModal\">\n <div class=\"image-modal-content\" @click.stop>\n <button class=\"image-modal-close\" type=\"button\" aria-label=\"Close image preview\" @click=\"closeImageModal\">\n <IconTablerX class=\"icon-svg\" />\n </button>\n <img class=\"image-modal-image\" :src=\"modalImageUrl\" alt=\"Expanded message image\" />\n </div>\n </div>\n\n <div\n v-if=\"isFileLinkContextMenuVisible\"\n ref=\"fileLinkContextMenuRef\"\n class=\"file-link-context-menu\"\n :style=\"fileLinkContextMenuStyle\"\n @click.stop\n >\n <button type=\"button\" class=\"file-link-context-menu-item\" @click=\"openFileLinkContextBrowse\">\n Open link\n </button>\n <button type=\"button\" class=\"file-link-context-menu-item\" @click=\"copyFileLinkContextLink\">\n Copy link\n </button>\n <button\n v-if=\"fileLinkContextEditUrl\"\n type=\"button\"\n class=\"file-link-context-menu-item\"\n @click=\"openFileLinkContextEdit\"\n >\n Edit file\n </button>\n </div>\n\n <div v-if=\"activeDiffViewerChange\" class=\"diff-viewer-backdrop\" @click=\"closeDiffViewer\">\n <div class=\"diff-viewer-shell\" @click.stop>\n <aside v-if=\"!isMobile\" class=\"diff-viewer-sidebar\">\n <div class=\"diff-viewer-sidebar-header\">\n <p class=\"diff-viewer-sidebar-title\">Changed files</p>\n <p class=\"diff-viewer-sidebar-count\">{{ formatFileChangeCountLabel(diffViewerChanges.length) }}</p>\n </div>\n <div class=\"diff-viewer-sidebar-list\">\n <button\n v-for=\"change in diffViewerChanges\"\n :key=\"`diff-viewer:${fileChangeKey(change)}`\"\n type=\"button\"\n class=\"diff-viewer-file-button\"\n :data-active=\"fileChangeKey(change) === fileChangeKey(activeDiffViewerChange)\"\n @click=\"selectDiffViewerChange(change)\"\n >\n <span class=\"file-change-badge\" :data-operation=\"fileChangeOperationTone(change)\">\n {{ fileChangeOperationLabel(change) }}\n </span>\n <span class=\"diff-viewer-file-label\">\n {{ displayFileChangePath(change.path) }}\n <template v-if=\"change.movedToPath\"> → {{ displayFileChangePath(change.movedToPath) }}</template>\n </span>\n <span v-if=\"formatFileChangeDelta(change)\" class=\"diff-viewer-file-delta\">{{ formatFileChangeDelta(change) }}</span>\n </button>\n </div>\n </aside>\n\n <section class=\"diff-viewer-main\">\n <div class=\"diff-viewer-toolbar\">\n <div class=\"diff-viewer-title-wrap\">\n <p class=\"diff-viewer-title\">\n {{ displayFileChangePath(activeDiffViewerChange.path) }}\n <template v-if=\"activeDiffViewerChange.movedToPath\"> → {{ displayFileChangePath(activeDiffViewerChange.movedToPath) }}</template>\n </p>\n <p class=\"diff-viewer-subtitle\">\n {{ fileChangeOperationLabel(activeDiffViewerChange) }}\n <span v-if=\"formatFileChangeDelta(activeDiffViewerChange)\"> · {{ formatFileChangeDelta(activeDiffViewerChange) }}</span>\n </p>\n </div>\n <div class=\"diff-viewer-toolbar-actions\">\n <button\n v-if=\"isMobile\"\n type=\"button\"\n class=\"diff-viewer-mobile-files-button\"\n @click=\"toggleDiffViewerFileList\"\n >\n {{ formatFileChangeCountLabel(diffViewerChanges.length) }}\n </button>\n <button class=\"image-modal-close diff-viewer-close\" type=\"button\" aria-label=\"Close diff viewer\" @click=\"closeDiffViewer\">\n <IconTablerX class=\"icon-svg\" />\n </button>\n </div>\n </div>\n\n <div v-if=\"!hasDiffViewerContent(activeDiffViewerChange)\" class=\"diff-viewer-empty\">\n <p class=\"diff-viewer-empty-title\">No diff available</p>\n <p class=\"diff-viewer-empty-text\">This summary was restored from the final answer text, but the thread history does not include patch diff content for this file.</p>\n </div>\n\n <div v-else class=\"diff-viewer-panel\">\n <div class=\"diff-viewer-meta\">\n <span class=\"diff-viewer-language\">{{ inferDiffViewerLanguage(activeDiffViewerChange) || 'diff' }}</span>\n </div>\n <div class=\"diff-viewer-lines\">\n <div\n v-for=\"line in activeDiffViewerLines\"\n :key=\"line.key\"\n class=\"diff-viewer-line\"\n :data-kind=\"line.kind\"\n >\n <span class=\"diff-viewer-line-number\">{{ line.oldLine ?? '' }}</span>\n <span class=\"diff-viewer-line-number\">{{ line.newLine ?? '' }}</span>\n <span class=\"diff-viewer-line-marker\">{{ diffViewerMarker(line) }}</span>\n <code class=\"diff-viewer-line-code\" v-html=\"escapeHtml(line.text) || ' '\"></code>\n </div>\n </div>\n </div>\n </section>\n\n <Transition name=\"diff-viewer-sheet\">\n <div\n v-if=\"isMobile && isDiffViewerFileListOpen\"\n class=\"diff-viewer-mobile-sheet-backdrop\"\n @click=\"closeDiffViewerFileList\"\n >\n <div class=\"diff-viewer-mobile-sheet\" @click.stop>\n <div class=\"diff-viewer-mobile-sheet-handle\" aria-hidden=\"true\"></div>\n <div class=\"diff-viewer-mobile-sheet-header\">\n <p class=\"diff-viewer-sidebar-title\">Changed files</p>\n <p class=\"diff-viewer-sidebar-count\">{{ formatFileChangeCountLabel(diffViewerChanges.length) }}</p>\n </div>\n <div class=\"diff-viewer-mobile-sheet-list\">\n <button\n v-for=\"change in diffViewerChanges\"\n :key=\"`diff-viewer-sheet:${fileChangeKey(change)}`\"\n type=\"button\"\n class=\"diff-viewer-file-button\"\n :data-active=\"fileChangeKey(change) === fileChangeKey(activeDiffViewerChange)\"\n @click=\"selectDiffViewerChange(change)\"\n >\n <span class=\"file-change-badge\" :data-operation=\"fileChangeOperationTone(change)\">\n {{ fileChangeOperationLabel(change) }}\n </span>\n <span class=\"diff-viewer-file-label\">\n {{ displayFileChangePath(change.path) }}\n <template v-if=\"change.movedToPath\"> → {{ displayFileChangePath(change.movedToPath) }}</template>\n </span>\n <span v-if=\"formatFileChangeDelta(change)\" class=\"diff-viewer-file-delta\">{{ formatFileChangeDelta(change) }}</span>\n </button>\n </div>\n </div>\n </div>\n </Transition>\n </div>\n </div>\n </section>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed, nextTick, onBeforeUnmount, onMounted, ref, watch } from 'vue'\nimport type { ThreadScrollState, UiFileChange, UiLiveOverlay, UiMessage, UiPlanStep, UiServerRequest } from '../../types/codex'\nimport { useMobile } from '../../composables/useMobile'\n\nimport IconTablerArrowBackUp from '../icons/IconTablerArrowBackUp.vue'\nimport IconTablerArrowUp from '../icons/IconTablerArrowUp.vue'\nimport IconTablerCopy from '../icons/IconTablerCopy.vue'\nimport IconTablerGitFork from '../icons/IconTablerGitFork.vue'\nimport IconTablerX from '../icons/IconTablerX.vue'\n\ntype HighlightJsModule = (typeof import('highlight.js/lib/common'))['default']\n\nconst expandedCommandIds = ref<Set<string>>(new Set())\nconst collapsedAutoCommandIds = ref<Set<string>>(new Set())\nconst expandedCommandGroupIds = ref<Set<string>>(new Set())\nconst expandedWorkedIds = ref<Set<string>>(new Set())\nconst expandedFileChangeSummaryIds = ref<Set<string>>(new Set())\nconst activeDiffViewerSummary = ref<TurnFileChangeSummary | null>(null)\nconst activeDiffViewerChangeKey = ref('')\nconst isDiffViewerFileListOpen = ref(false)\nconst fileLinkContextMenuRef = ref<HTMLElement | null>(null)\nconst isFileLinkContextMenuVisible = ref(false)\nconst fileLinkContextMenuX = ref(0)\nconst fileLinkContextMenuY = ref(0)\nconst fileLinkContextBrowseUrl = ref('')\nconst fileLinkContextEditUrl = ref('')\nconst { isMobile } = useMobile()\n\nfunction parsePlanFromMessageText(text: string): { explanation: string; steps: UiPlanStep[] } | null {\n const normalized = text.replace(/\\r\\n/g, '\\n').trim()\n if (!normalized) return null\n\n const steps: UiPlanStep[] = []\n const explanationLines: string[] = []\n\n for (const line of normalized.split('\\n')) {\n const trimmed = line.trim()\n if (!trimmed) {\n if (steps.length === 0) explanationLines.push('')\n continue\n }\n\n const match = trimmed.match(/^[-*]\\s+\\[([ xX~>|-])\\]\\s+(.+)$/)\n if (match) {\n const marker = (match[1] ?? ' ').toLowerCase()\n let status: UiPlanStep['status'] = 'pending'\n if (marker === 'x') status = 'completed'\n if (marker === '~' || marker === '>' || marker === '-') status = 'inProgress'\n steps.push({\n step: match[2]?.trim() ?? '',\n status,\n })\n continue\n }\n\n explanationLines.push(trimmed)\n }\n\n if (steps.length === 0) return null\n return {\n explanation: explanationLines.join('\\n').trim(),\n steps: steps.filter((step) => step.step.length > 0),\n }\n}\n\nfunction readPlanData(message: UiMessage): { explanation: string; steps: UiPlanStep[] } | null {\n if (message.plan && message.plan.steps.length > 0) {\n return {\n explanation: message.plan.explanation?.trim() ?? '',\n steps: message.plan.steps,\n }\n }\n return parsePlanFromMessageText(message.text)\n}\n\nfunction isCommandMessage(message: UiMessage): boolean {\n return message.messageType === 'commandExecution' && !!message.commandExecution\n}\n\nfunction isPlanMessage(message: UiMessage): boolean {\n return message.messageType === 'plan' || message.messageType === 'plan.live'\n}\n\nfunction isFileChangeMessage(message: UiMessage): boolean {\n return message.messageType === 'fileChange'\n && message.fileChangeStatus === 'completed'\n && Array.isArray(message.fileChanges)\n && message.fileChanges.length > 0\n}\n\nfunction isCopyableAssistantMessage(message: UiMessage): boolean {\n return message.role === 'assistant'\n && !isCommandMessage(message)\n && message.messageType !== 'worked'\n && !(message.messageType ?? '').endsWith('.live')\n}\n\nconst activeCommandMessageId = computed(() => {\n for (let index = props.messages.length - 1; index >= 0; index -= 1) {\n const message = props.messages[index]\n if (message.messageType === 'commandExecution' && message.commandExecution?.status === 'inProgress') {\n return message.id\n }\n }\n return ''\n})\n\nconst hasLiveAssistantText = computed(() =>\n props.messages.some((message) =>\n message.role === 'assistant' &&\n message.messageType === 'agentMessage.live' &&\n message.text.trim().length > 0,\n ),\n)\n\nconst isLiveTurnRuntime = computed(() =>\n Boolean(props.liveOverlay) || activeCommandMessageId.value.length > 0 || hasLiveAssistantText.value,\n)\n\nconst groupedCommandsByLatestId = computed<Record<string, UiMessage[]>>(() => {\n const next: Record<string, UiMessage[]> = {}\n for (let index = 0; index < props.messages.length;) {\n const message = props.messages[index]\n if (!isCommandMessage(message)) {\n index += 1\n continue\n }\n\n const block: UiMessage[] = []\n while (index < props.messages.length && isCommandMessage(props.messages[index])) {\n block.push(props.messages[index])\n index += 1\n }\n\n if (block.length <= 1) continue\n const latest = block[block.length - 1]\n next[latest.id] = block.slice(0, -1)\n }\n return next\n})\n\nconst hiddenGroupedCommandIds = computed(() => {\n const next = new Set<string>()\n for (const commands of Object.values(groupedCommandsByLatestId.value)) {\n for (const command of commands) {\n next.add(command.id)\n }\n }\n return next\n})\n\nfunction readPlanExplanation(message: UiMessage): string {\n return readPlanData(message)?.explanation ?? ''\n}\n\nfunction readPlanSteps(message: UiMessage): UiPlanStep[] {\n return readPlanData(message)?.steps ?? []\n}\n\nfunction planStepStatusIcon(status: UiPlanStep['status']): string {\n switch (status) {\n case 'completed':\n return '✓'\n case 'inProgress':\n return '•'\n default:\n return '○'\n }\n}\n\nfunction isCommandAutoExpanded(message: UiMessage): boolean {\n return !hasLiveAssistantText.value && message.id === activeCommandMessageId.value\n}\n\nfunction isCommandExpanded(message: UiMessage): boolean {\n if (!isCommandMessage(message)) return false\n return expandedCommandIds.value.has(message.id)\n || (!collapsedAutoCommandIds.value.has(message.id) && isCommandAutoExpanded(message))\n}\n\nfunction isCommandCompact(message: UiMessage): boolean {\n return isCommandMessage(message) && isLiveTurnRuntime.value\n}\n\nfunction isCommandOutputCondensed(message: UiMessage): boolean {\n return isCommandMessage(message) && (isLiveTurnRuntime.value || message.commandExecution?.status === 'inProgress')\n}\n\nfunction toggleCommandExpand(message: UiMessage): void {\n if (!isCommandMessage(message)) return\n\n const nextExpanded = new Set(expandedCommandIds.value)\n const nextCollapsedAuto = new Set(collapsedAutoCommandIds.value)\n const isAutoExpanded = isCommandAutoExpanded(message)\n const isManuallyExpanded = nextExpanded.has(message.id)\n\n if (isManuallyExpanded) {\n nextExpanded.delete(message.id)\n if (isAutoExpanded) nextCollapsedAuto.add(message.id)\n } else if (isAutoExpanded && !nextCollapsedAuto.has(message.id)) {\n nextCollapsedAuto.add(message.id)\n } else {\n nextExpanded.add(message.id)\n nextCollapsedAuto.delete(message.id)\n }\n\n expandedCommandIds.value = nextExpanded\n collapsedAutoCommandIds.value = nextCollapsedAuto\n}\n\nfunction getGroupedCommandsForLatest(message: UiMessage): UiMessage[] {\n return groupedCommandsByLatestId.value[message.id] ?? []\n}\n\nfunction getCommandBlockForLatest(message: UiMessage): UiMessage[] {\n if (!isCommandMessage(message)) return []\n return [...getGroupedCommandsForLatest(message), message]\n}\n\nfunction toggleCommandGroup(message: UiMessage): void {\n const groupedCommands = getGroupedCommandsForLatest(message)\n if (groupedCommands.length === 0) return\n const next = new Set(expandedCommandGroupIds.value)\n if (next.has(message.id)) next.delete(message.id)\n else next.add(message.id)\n expandedCommandGroupIds.value = next\n}\n\nfunction isCommandGroupExpanded(message: UiMessage): boolean {\n return expandedCommandGroupIds.value.has(message.id)\n}\n\nfunction commandGroupSummaryLabel(message: UiMessage): string {\n const commands = getCommandBlockForLatest(message)\n const count = commands.length\n const latestCommand = message.commandExecution?.command?.trim() || '(command)'\n const countLabel = count === 1 ? '1 command' : `${count} commands`\n return `${countLabel} · latest: ${latestCommand}`\n}\n\nfunction commandGroupSummaryStatus(message: UiMessage): string {\n return commandStatusLabel(message)\n}\n\nfunction toggleWorkedExpand(message: UiMessage): void {\n const next = new Set(expandedWorkedIds.value)\n if (next.has(message.id)) next.delete(message.id)\n else next.add(message.id)\n expandedWorkedIds.value = next\n}\n\nfunction isWorkedExpanded(message: UiMessage): boolean {\n return expandedWorkedIds.value.has(message.id)\n}\n\nfunction toggleFileChangeSummary(message: UiMessage): void {\n const next = new Set(expandedFileChangeSummaryIds.value)\n if (next.has(message.id)) next.delete(message.id)\n else next.add(message.id)\n expandedFileChangeSummaryIds.value = next\n}\n\nfunction isFileChangeSummaryExpanded(message: UiMessage): boolean {\n return expandedFileChangeSummaryIds.value.has(message.id)\n}\n\nfunction fileChangeKey(change: UiFileChange): string {\n return `${change.path}\\u0000${change.movedToPath ?? ''}`\n}\n\nfunction openDiffViewer(summary: TurnFileChangeSummary | null, change: UiFileChange): void {\n if (!summary) return\n activeDiffViewerSummary.value = summary\n activeDiffViewerChangeKey.value = fileChangeKey(change)\n isDiffViewerFileListOpen.value = false\n}\n\nfunction closeDiffViewer(): void {\n activeDiffViewerSummary.value = null\n activeDiffViewerChangeKey.value = ''\n isDiffViewerFileListOpen.value = false\n}\n\nfunction toggleDiffViewerFileList(): void {\n isDiffViewerFileListOpen.value = !isDiffViewerFileListOpen.value\n}\n\nfunction closeDiffViewerFileList(): void {\n isDiffViewerFileListOpen.value = false\n}\n\nfunction selectDiffViewerChange(change: UiFileChange): void {\n activeDiffViewerChangeKey.value = fileChangeKey(change)\n if (isMobile.value) {\n isDiffViewerFileListOpen.value = false\n }\n}\n\nfunction commandStatusLabel(message: UiMessage): string {\n const ce = message.commandExecution\n if (!ce) return ''\n const compact = isCommandCompact(message)\n switch (ce.status) {\n case 'inProgress': return compact ? 'Running' : '⟳ Running'\n case 'completed': return ce.exitCode === 0 ? (compact ? 'Done' : '✓ Completed') : `Exit ${ce.exitCode ?? '?'}`\n case 'failed': return compact ? 'Failed' : '✗ Failed'\n case 'declined': return compact ? 'Declined' : '⊘ Declined'\n case 'interrupted': return compact ? 'Stopped' : '⊘ Interrupted'\n default: return ''\n }\n}\n\nfunction commandStatusClass(message: UiMessage): string {\n const s = message.commandExecution?.status\n if (s === 'inProgress') return 'cmd-status-running'\n if (s === 'completed' && message.commandExecution?.exitCode === 0) return 'cmd-status-ok'\n return 'cmd-status-error'\n}\n\nfunction pruneCommandIdSet(source: Set<string>, validIds: Set<string>): Set<string> {\n if (source.size === 0) return source\n const next = new Set<string>()\n for (const id of source) {\n if (validIds.has(id)) next.add(id)\n }\n return next.size === source.size ? source : next\n}\n\nfunction getCommandsForWorked(messages: UiMessage[], workedIndex: number): UiMessage[] {\n const result: UiMessage[] = []\n for (let i = workedIndex - 1; i >= 0; i--) {\n const m = messages[i]\n if (m.messageType === 'commandExecution') result.unshift(m)\n else if (m.role === 'user' || m.messageType === 'worked') break\n }\n return result\n}\n\nconst props = defineProps<{\n messages: UiMessage[]\n pendingRequests: UiServerRequest[]\n liveOverlay: UiLiveOverlay | null\n isLoading: boolean\n activeThreadId: string\n cwd: string\n scrollState: ThreadScrollState | null\n}>()\n\nconst emit = defineEmits<{\n updateScrollState: [payload: { threadId: string; state: ThreadScrollState }]\n forkThread: [payload: { threadId: string; turnIndex: number }]\n rollback: [payload: { turnId: string }]\n respondServerRequest: [payload: { id: number; result?: unknown; error?: { code?: number; message: string } }]\n}>()\n\nconst conversationListRef = ref<HTMLElement | null>(null)\nconst bottomAnchorRef = ref<HTMLElement | null>(null)\nconst modalImageUrl = ref('')\nconst copiedResponseAnchorId = ref('')\nconst toolQuestionAnswers = ref<Record<string, string>>({})\nconst toolQuestionOtherAnswers = ref<Record<string, string>>({})\nconst mcpElicitationAnswers = ref<Record<string, string | number | boolean | string[]>>({})\nconst localScrollState = ref<ThreadScrollState | null>(null)\nconst autoFollowOutput = ref(props.scrollState?.isAtBottom !== false)\nconst BOTTOM_THRESHOLD_PX = 16\nconst CODE_LANGUAGE_ALIASES: Record<string, string> = {\n js: 'javascript',\n jsx: 'jsx',\n ts: 'typescript',\n tsx: 'tsx',\n py: 'python',\n rb: 'ruby',\n sh: 'bash',\n shell: 'bash',\n zsh: 'bash',\n yml: 'yaml',\n md: 'markdown',\n 'c++': 'cpp',\n 'c#': 'csharp',\n ps1: 'powershell',\n}\ntype InlineSegment =\n | { kind: 'text'; value: string }\n | { kind: 'bold'; value: string }\n | { kind: 'italic'; value: string }\n | { kind: 'strikethrough'; value: string }\n | { kind: 'code'; value: string }\n | { kind: 'url'; value: string; href: string }\n | { kind: 'file'; value: string; path: string; displayPath: string; downloadName: string }\ntype TaskListItem = {\n text: string\n checked: boolean\n}\ntype TableAlignment = 'left' | 'center' | 'right' | null\ntype ListItem = {\n paragraphs: string[]\n children?: MessageBlock[]\n}\ntype MessageBlock =\n | { kind: 'paragraph'; value: string }\n | { kind: 'heading'; level: number; value: string }\n | { kind: 'blockquote'; value: string }\n | { kind: 'unorderedList'; items: ListItem[] }\n | { kind: 'taskList'; items: TaskListItem[] }\n | { kind: 'orderedList'; items: ListItem[]; start: number }\n | { kind: 'table'; headers: string[]; rows: string[][]; alignments: TableAlignment[] }\n | { kind: 'codeBlock'; language: string; value: string }\n | { kind: 'thematicBreak' }\n | { kind: 'image'; url: string; alt: string; markdown: string }\n\nlet scrollRestoreFrame = 0\nlet bottomLockFrame = 0\nlet bottomLockFramesLeft = 0\nlet copiedMessageResetTimer: ReturnType<typeof setTimeout> | null = null\nconst trackedPendingImages = new WeakSet<HTMLImageElement>()\nconst failedMarkdownImageKeys = ref<Set<string>>(new Set())\nconst highlightJsModule = ref<HighlightJsModule | null>(null)\nlet highlightJsLoader: Promise<void> | null = null\n\nconst RENDER_WINDOW_SIZE = 50\nconst LOAD_MORE_CHUNK = 30\nconst LOAD_MORE_SCROLL_THRESHOLD_PX = 200\n\nconst renderWindowStart = ref(0)\nconst isLoadingMore = ref(false)\n\nconst visibleMessages = computed(() => props.messages.slice(renderWindowStart.value))\nconst hasMoreAbove = computed(() => renderWindowStart.value > 0)\n\nconst showJumpToLatestButton = computed(\n () => !autoFollowOutput.value && (props.messages.length > 0 || props.pendingRequests.length > 0 || Boolean(props.liveOverlay)),\n)\n\nfunction ensureHighlightJsLoaded(): Promise<void> {\n if (highlightJsModule.value) return Promise.resolve()\n if (!highlightJsLoader) {\n highlightJsLoader = import('highlight.js/lib/common')\n .then((module) => {\n highlightJsModule.value = module.default\n })\n .finally(() => {\n highlightJsLoader = null\n })\n }\n return highlightJsLoader\n}\n\ntype ParsedToolQuestion = {\n id: string\n header: string\n question: string\n isSecret: boolean\n isOther: boolean\n options: Array<{ label: string; description: string }>\n}\ntype McpElicitationFieldOption = {\n value: string\n label: string\n}\ntype McpElicitationField = {\n key: string\n label: string\n description: string\n required: boolean\n kind: 'string' | 'number' | 'boolean' | 'singleEnum' | 'multiEnum'\n inputType: string\n options: McpElicitationFieldOption[]\n defaultValue: string | number | boolean | string[]\n}\ntype TurnFileChangeSummary = {\n changes: UiFileChange[]\n sourceMessageIds: string[]\n source: 'assistant' | 'metadata'\n}\ntype DiffViewerLineKind = 'meta' | 'hunk' | 'add' | 'remove' | 'context'\ntype DiffViewerLine = {\n key: string\n kind: DiffViewerLineKind\n oldLine: number | null\n newLine: number | null\n text: string\n}\n\nfunction isFilePath(value: string): boolean {\n if (!value || /[\\r\\n]/u.test(value)) return false\n if (value.endsWith('/') || value.endsWith('\\\\')) return false\n if (/^[A-Za-z][A-Za-z0-9+.-]*:\\/\\//u.test(value)) return false\n\n const looksLikeUnixAbsolute = value.startsWith('/')\n const looksLikeWindowsAbsolute = /^[A-Za-z]:[\\\\/]/u.test(value)\n const looksLikeRelative = value.startsWith('./') || value.startsWith('../') || value.startsWith('~/')\n if (looksLikeUnixAbsolute || looksLikeWindowsAbsolute || looksLikeRelative) return true\n\n // Bare relative paths should look like actual path segments, not arbitrary prose containing \"/\".\n return /^[A-Za-z0-9._@() -]+(?:[\\\\/][A-Za-z0-9._@() -]+)+$/u.test(value)\n}\n\nfunction getBasename(pathValue: string): string {\n const normalized = pathValue.replace(/\\\\/gu, '/')\n const name = normalized.split('/').filter(Boolean).pop()\n return name || pathValue\n}\n\nfunction normalizePathSeparators(pathValue: string): string {\n return pathValue.replace(/\\\\/gu, '/')\n}\n\nfunction normalizeFileUrlToPath(pathValue: string): string {\n if (!pathValue.startsWith('file://')) return pathValue\n let stripped = pathValue.replace(/^file:\\/\\//u, '')\n try {\n stripped = decodeURIComponent(stripped)\n } catch {\n // Keep best-effort path if decoding fails.\n }\n if (/^\\/[A-Za-z]:\\//u.test(stripped)) {\n stripped = stripped.slice(1)\n }\n return stripped\n}\n\nfunction inferHomeFromCwd(cwd: string): string {\n const normalized = normalizePathSeparators(cwd)\n const userMatch = normalized.match(/^\\/Users\\/([^/]+)/u)\n if (userMatch) return `/Users/${userMatch[1]}`\n const homeMatch = normalized.match(/^\\/home\\/([^/]+)/u)\n if (homeMatch) return `/home/${homeMatch[1]}`\n return ''\n}\n\nfunction normalizePathDots(pathValue: string): string {\n const normalized = normalizePathSeparators(pathValue)\n if (!normalized) return normalized\n\n let root = ''\n let rest = normalized\n const driveMatch = rest.match(/^([A-Za-z]:)(\\/.*)?$/u)\n if (driveMatch) {\n root = `${driveMatch[1]}/`\n rest = (driveMatch[2] ?? '').replace(/^\\/+/u, '')\n } else if (rest.startsWith('/')) {\n root = '/'\n rest = rest.slice(1)\n }\n\n const parts = rest.split('/').filter(Boolean)\n const stack: string[] = []\n for (const part of parts) {\n if (part === '.') continue\n if (part === '..') {\n if (stack.length > 0) stack.pop()\n continue\n }\n stack.push(part)\n }\n\n const joined = stack.join('/')\n if (root) return `${root}${joined}`.replace(/\\/+$/u, '') || root\n return joined || normalized\n}\n\nfunction resolveRelativePath(pathValue: string, cwd: string): string {\n const normalizedPath = normalizePathSeparators(normalizeFileUrlToPath(pathValue.trim()))\n if (!normalizedPath) return ''\n\n const looksLikeAbsolute = normalizedPath.startsWith('/') || /^[A-Za-z]:\\//u.test(normalizedPath)\n if (looksLikeAbsolute) return normalizePathDots(normalizedPath)\n\n if (normalizedPath.startsWith('~/')) {\n const homeBase = inferHomeFromCwd(cwd)\n if (homeBase) {\n return normalizePathDots(`${homeBase}/${normalizedPath.slice(2)}`)\n }\n }\n\n const base = normalizePathSeparators(cwd.trim())\n if (!base) return normalizePathDots(normalizedPath)\n return normalizePathDots(`${base.replace(/\\/+$/u, '')}/${normalizedPath}`)\n}\n\nfunction parseFileReference(value: string): { path: string; line: number | null } | null {\n if (!value) return null\n\n let pathValue = value.trim()\n const wrapped = trimLinkWrappers(pathValue)\n pathValue = wrapped.core.trim()\n let line: number | null = null\n\n const hashLineMatch = pathValue.match(/^(.*)#L(\\d+)(?:C\\d+)?$/u)\n if (hashLineMatch) {\n pathValue = hashLineMatch[1]\n line = Number(hashLineMatch[2])\n } else {\n const colonLineMatch = pathValue.match(/^(.*):(\\d+)(?::\\d+)?$/u)\n if (colonLineMatch) {\n pathValue = colonLineMatch[1]\n line = Number(colonLineMatch[2])\n }\n }\n\n pathValue = normalizeFileUrlToPath(pathValue)\n if (!isFilePath(pathValue)) return null\n return { path: pathValue, line }\n}\n\nfunction trimLinkWrappers(value: string): { core: string; leading: string; trailing: string } {\n let core = value\n let leading = ''\n let trailing = ''\n\n while (/^[('\"`[{<“‘]/u.test(core)) {\n leading += core[0]\n core = core.slice(1)\n }\n while (/[)\"'`\\]}>”’]$/u.test(core)) {\n trailing = core.slice(-1) + trailing\n core = core.slice(0, -1)\n }\n\n return { core, leading, trailing }\n}\n\nfunction parseMarkdownLinkToken(value: string): { label: string; target: string } | null {\n const trimmed = value.trim()\n if (!trimmed.startsWith('[') || !trimmed.endsWith(')')) return null\n const labelCloseIndex = trimmed.indexOf(']')\n if (labelCloseIndex <= 1) return null\n if (trimmed[labelCloseIndex + 1] !== '(') return null\n const labelRaw = trimmed.slice(1, labelCloseIndex).trim()\n const targetRaw = trimmed.slice(labelCloseIndex + 2, -1).trim()\n if (labelRaw.includes('\\n') || targetRaw.includes('\\n')) return null\n const label = trimLinkWrappers(labelRaw).core.trim() || labelRaw\n const target = trimLinkWrappers(targetRaw).core.trim()\n if (!target) return null\n return { label, target }\n}\n\nfunction headingTag(level: number): string {\n const normalizedLevel = Math.min(6, Math.max(1, Math.trunc(level)))\n return `h${String(normalizedLevel)}`\n}\n\nfunction headingClass(level: number): string {\n switch (Math.min(6, Math.max(1, Math.trunc(level)))) {\n case 1:\n return 'message-heading-h1'\n case 2:\n return 'message-heading-h2'\n case 3:\n return 'message-heading-h3'\n case 4:\n return 'message-heading-h4'\n case 5:\n return 'message-heading-h5'\n default:\n return 'message-heading-h6'\n }\n}\n\nfunction planStepCopyMarker(status: UiPlanStep['status']): string {\n switch (status) {\n case 'completed':\n return '[x]'\n case 'inProgress':\n return '[~]'\n default:\n return '[ ]'\n }\n}\n\nfunction buildPlanCopyText(message: UiMessage): string {\n const planData = readPlanData(message)\n if (!planData) return ''\n\n const sections: string[] = []\n if (planData.explanation?.trim()) {\n sections.push(planData.explanation.trim())\n }\n\n if (planData.steps.length > 0) {\n sections.push(planData.steps.map((step) => `- ${planStepCopyMarker(step.status)} ${step.step}`.trim()).join('\\n'))\n }\n\n return sections.join('\\n\\n').trim()\n}\n\nfunction buildCopyableMessageContent(message: UiMessage): string {\n const sections: string[] = []\n const rawTextContent = message.text.trim() || buildPlanCopyText(message)\n const textContent = isPlanMessage(message) && rawTextContent\n ? `Plan\\n${rawTextContent}`\n : rawTextContent\n if (textContent) {\n sections.push(textContent)\n }\n\n const attachmentLines = (message.fileAttachments ?? [])\n .map((attachment) => attachment.path.trim())\n .filter((pathValue) => pathValue.length > 0)\n if (attachmentLines.length > 0) {\n sections.push(`Files:\\n${attachmentLines.join('\\n')}`)\n }\n\n const imageLines = (message.images ?? [])\n .map((imageUrl) => imageUrl.trim())\n .filter((imageUrl) => imageUrl.length > 0)\n if (imageLines.length > 0) {\n sections.push(`Images:\\n${imageLines.join('\\n')}`)\n }\n\n return sections.join('\\n\\n').trim()\n}\n\nconst copyableResponseContentByAnchorId = computed<Record<string, string>>(() => {\n const groupedResponses = new Map<string, { anchorMessageId: string; parts: string[] }>()\n\n for (const message of props.messages) {\n if (!isCopyableAssistantMessage(message)) continue\n\n const content = buildCopyableMessageContent(message)\n if (!content) continue\n\n const responseKey = typeof message.turnIndex === 'number'\n ? `turn:${message.turnIndex}`\n : `message:${message.id}`\n const existing = groupedResponses.get(responseKey)\n if (existing) {\n existing.anchorMessageId = message.id\n existing.parts.push(content)\n continue\n }\n\n groupedResponses.set(responseKey, {\n anchorMessageId: message.id,\n parts: [content],\n })\n }\n\n const next: Record<string, string> = {}\n for (const response of groupedResponses.values()) {\n const content = response.parts.join('\\n\\n').trim()\n if (!content) continue\n next[response.anchorMessageId] = content\n }\n\n for (const [anchorMessageId, summary] of Object.entries(anchoredFileChangeSummaryByAnchorId.value)) {\n if (summary.source !== 'metadata') continue\n const fileChangeCopy = buildFileChangeCopyText(summary)\n if (!fileChangeCopy) continue\n const existing = next[anchorMessageId]?.trim()\n next[anchorMessageId] = existing ? `${existing}\\n\\n${fileChangeCopy}` : fileChangeCopy\n }\n return next\n})\n\nconst forkableTurnIndexByAnchorId = computed<Record<string, number>>(() => {\n const groupedTurns = new Map<string, { anchorMessageId: string; turnIndex: number }>()\n\n for (const message of props.messages) {\n if (!isCopyableAssistantMessage(message) || typeof message.turnIndex !== 'number') continue\n\n const responseKey = `turn:${message.turnIndex}`\n const existing = groupedTurns.get(responseKey)\n if (existing) {\n existing.anchorMessageId = message.id\n existing.turnIndex = message.turnIndex\n continue\n }\n\n groupedTurns.set(responseKey, {\n anchorMessageId: message.id,\n turnIndex: message.turnIndex,\n })\n }\n\n const next: Record<string, number> = {}\n for (const groupedTurn of groupedTurns.values()) {\n next[groupedTurn.anchorMessageId] = groupedTurn.turnIndex\n }\n return next\n})\n\nfunction showCopyResponseButton(message: UiMessage): boolean {\n return typeof copyableResponseContentByAnchorId.value[message.id] === 'string'\n}\n\nfunction showForkResponseButton(message: UiMessage): boolean {\n return typeof forkableTurnIndexByAnchorId.value[message.id] === 'number'\n}\n\nfunction mergeFileChangeDiff(first: string, second: string): string {\n if (!first) return second\n if (!second || first === second) return first\n return `${first}\\n${second}`.trim()\n}\n\nfunction mergeFileChangeEntry(first: UiFileChange, second: UiFileChange): UiFileChange {\n const operation = first.operation === 'add' || second.operation === 'add'\n ? 'add'\n : first.operation === 'delete' || second.operation === 'delete'\n ? 'delete'\n : 'update'\n return {\n path: second.path || first.path,\n operation,\n movedToPath: second.movedToPath ?? first.movedToPath ?? null,\n diff: mergeFileChangeDiff(first.diff, second.diff),\n addedLineCount: first.addedLineCount + second.addedLineCount,\n removedLineCount: first.removedLineCount + second.removedLineCount,\n }\n}\n\nfunction compareFileChanges(first: UiFileChange, second: UiFileChange): number {\n const firstRank = first.operation === 'add' ? 0 : first.operation === 'update' ? 1 : 2\n const secondRank = second.operation === 'add' ? 0 : second.operation === 'update' ? 1 : 2\n if (firstRank !== secondRank) return firstRank - secondRank\n const firstPath = `${first.path}\\u0000${first.movedToPath ?? ''}`\n const secondPath = `${second.path}\\u0000${second.movedToPath ?? ''}`\n return firstPath.localeCompare(secondPath)\n}\n\nfunction aggregateFileChanges(changes: UiFileChange[]): UiFileChange[] {\n const byPath = new Map<string, UiFileChange>()\n for (const change of changes) {\n const key = `${change.path}\\u0000${change.movedToPath ?? ''}`\n const previous = byPath.get(key)\n byPath.set(key, previous ? mergeFileChangeEntry(previous, change) : { ...change })\n }\n return Array.from(byPath.values()).sort(compareFileChanges)\n}\n\nconst anchoredFileChangeSummaryByAnchorId = computed<Record<string, TurnFileChangeSummary>>(() => {\n const assistantAnchorIdByTurnKey = new Map<string, string>()\n const assistantSummaryByAnchorId = new Map<string, TurnFileChangeSummary>()\n const fileChangeMessagesByTurnKey = new Map<string, UiMessage[]>()\n\n for (const message of props.messages) {\n if (isCopyableAssistantMessage(message) && typeof message.turnIndex === 'number') {\n assistantAnchorIdByTurnKey.set(`turn:${message.turnIndex}`, message.id)\n if (Array.isArray(message.fileChanges) && message.fileChanges.length > 0) {\n assistantSummaryByAnchorId.set(message.id, {\n changes: aggregateFileChanges(message.fileChanges),\n sourceMessageIds: [],\n source: 'assistant',\n })\n }\n }\n\n if (!isFileChangeMessage(message)) continue\n const turnKey = typeof message.turnIndex === 'number' ? `turn:${message.turnIndex}` : `message:${message.id}`\n const current = fileChangeMessagesByTurnKey.get(turnKey)\n if (current) current.push(message)\n else fileChangeMessagesByTurnKey.set(turnKey, [message])\n }\n\n const summaries: Record<string, TurnFileChangeSummary> = {}\n for (const [turnKey, messages] of fileChangeMessagesByTurnKey.entries()) {\n const anchorId = assistantAnchorIdByTurnKey.get(turnKey)\n if (!anchorId) continue\n summaries[anchorId] = {\n changes: aggregateFileChanges(messages.flatMap((message) => message.fileChanges ?? [])),\n sourceMessageIds: messages.map((message) => message.id),\n source: 'metadata',\n }\n }\n\n for (const [anchorId, summary] of assistantSummaryByAnchorId.entries()) {\n if (!summaries[anchorId]) {\n summaries[anchorId] = summary\n }\n }\n\n return summaries\n})\n\nconst standaloneFileChangeSummaryByMessageId = computed<Record<string, TurnFileChangeSummary>>(() => {\n const assistantAnchorIdByTurnKey = new Map<string, string>()\n const fileChangeMessagesByTurnKey = new Map<string, UiMessage[]>()\n\n for (const message of props.messages) {\n if (isCopyableAssistantMessage(message) && typeof message.turnIndex === 'number') {\n assistantAnchorIdByTurnKey.set(`turn:${message.turnIndex}`, message.id)\n }\n\n if (!isFileChangeMessage(message)) continue\n const turnKey = typeof message.turnIndex === 'number' ? `turn:${message.turnIndex}` : `message:${message.id}`\n const current = fileChangeMessagesByTurnKey.get(turnKey)\n if (current) current.push(message)\n else fileChangeMessagesByTurnKey.set(turnKey, [message])\n }\n\n const summaries: Record<string, TurnFileChangeSummary> = {}\n for (const [turnKey, messages] of fileChangeMessagesByTurnKey.entries()) {\n if (assistantAnchorIdByTurnKey.has(turnKey)) continue\n const visibleMessage = messages[messages.length - 1]\n if (!visibleMessage) continue\n summaries[visibleMessage.id] = {\n changes: aggregateFileChanges(messages.flatMap((message) => message.fileChanges ?? [])),\n sourceMessageIds: messages.map((message) => message.id),\n source: 'metadata',\n }\n }\n\n return summaries\n})\n\nconst hiddenFileChangeMessageIds = computed(() => {\n const next = new Set<string>()\n for (const summary of Object.values(anchoredFileChangeSummaryByAnchorId.value)) {\n for (const messageId of summary.sourceMessageIds) {\n next.add(messageId)\n }\n }\n for (const [messageId, summary] of Object.entries(standaloneFileChangeSummaryByMessageId.value)) {\n for (const sourceMessageId of summary.sourceMessageIds) {\n if (sourceMessageId !== messageId) {\n next.add(sourceMessageId)\n }\n }\n }\n return next\n})\n\nfunction readAnchoredFileChangeSummary(message: UiMessage): TurnFileChangeSummary | null {\n return anchoredFileChangeSummaryByAnchorId.value[message.id] ?? null\n}\n\nfunction readStandaloneFileChangeSummary(message: UiMessage): TurnFileChangeSummary | null {\n return standaloneFileChangeSummaryByMessageId.value[message.id] ?? null\n}\n\nfunction fileChangeOperationLabel(change: UiFileChange): string {\n if (change.operation === 'update' && change.movedToPath) {\n return change.addedLineCount > 0 || change.removedLineCount > 0 ? 'Moved + edited' : 'Moved'\n }\n if (change.operation === 'add') return 'Added'\n if (change.operation === 'delete') return 'Deleted'\n return 'Edited'\n}\n\nfunction fileChangeOperationTone(change: UiFileChange): 'add' | 'delete' | 'update' | 'move' {\n if (change.operation === 'update' && change.movedToPath) return 'move'\n return change.operation\n}\n\nfunction formatFileChangeDelta(change: UiFileChange): string {\n const parts: string[] = []\n if (change.addedLineCount > 0) parts.push(`+${change.addedLineCount}`)\n if (change.removedLineCount > 0) parts.push(`-${change.removedLineCount}`)\n return parts.join(' ')\n}\n\ntype FileChangeDeltaTone = 'add' | 'remove' | 'neutral'\n\ntype FileChangeDeltaPart = {\n tone: FileChangeDeltaTone\n label: string\n}\n\nfunction buildFileChangeDeltaParts(addedCount: number, removedCount: number, fallbackLabel = ''): FileChangeDeltaPart[] {\n const parts: FileChangeDeltaPart[] = []\n if (addedCount > 0) parts.push({ tone: 'add', label: `+${addedCount}` })\n if (removedCount > 0) parts.push({ tone: 'remove', label: `-${removedCount}` })\n if (parts.length > 0) return parts\n return fallbackLabel ? [{ tone: 'neutral', label: fallbackLabel }] : []\n}\n\nfunction fileChangeDeltaParts(change: UiFileChange): FileChangeDeltaPart[] {\n return buildFileChangeDeltaParts(change.addedLineCount, change.removedLineCount)\n}\n\nfunction formatFileChangeCountLabel(count: number): string {\n return count === 1 ? '1 file changed' : `${count} files changed`\n}\n\nfunction summarizeFileChangeKinds(summary: TurnFileChangeSummary | null): string {\n if (!summary || summary.changes.length === 0) return ''\n let added = 0\n let deleted = 0\n let edited = 0\n let moved = 0\n\n for (const change of summary.changes) {\n if (change.operation === 'add') {\n added += 1\n continue\n }\n if (change.operation === 'delete') {\n deleted += 1\n continue\n }\n if (change.movedToPath) {\n moved += 1\n continue\n }\n edited += 1\n }\n\n const parts: string[] = []\n if (edited > 0) parts.push(`${edited} edited`)\n if (added > 0) parts.push(`${added} added`)\n if (deleted > 0) parts.push(`${deleted} deleted`)\n if (moved > 0) parts.push(`${moved} moved`)\n return parts.join(', ')\n}\n\nfunction fileChangeSummaryLabel(summary: TurnFileChangeSummary | null): string {\n if (!summary || summary.changes.length === 0) return 'Modified files'\n const countLabel = formatFileChangeCountLabel(summary.changes.length)\n const kindSummary = summarizeFileChangeKinds(summary)\n return kindSummary ? `${countLabel} · ${kindSummary}` : countLabel\n}\n\nfunction fileChangeSummaryStatusParts(summary: TurnFileChangeSummary | null): FileChangeDeltaPart[] {\n if (!summary || summary.changes.length === 0) return []\n const totalAdded = summary.changes.reduce((sum, change) => sum + change.addedLineCount, 0)\n const totalRemoved = summary.changes.reduce((sum, change) => sum + change.removedLineCount, 0)\n const fallbackLabel = summary.changes.some((change) => change.movedToPath) ? 'Moved' : 'Ready'\n return buildFileChangeDeltaParts(totalAdded, totalRemoved, fallbackLabel)\n}\n\nfunction displayFileChangePath(pathValue: string): string {\n const resolved = resolveRelativePath(pathValue, props.cwd)\n const normalizedCwd = normalizePathDots(normalizePathSeparators(props.cwd.trim()))\n const normalizedResolved = normalizePathDots(normalizePathSeparators(resolved))\n if (normalizedCwd && normalizedResolved.startsWith(`${normalizedCwd}/`)) {\n return normalizedResolved.slice(normalizedCwd.length + 1)\n }\n return pathValue\n}\n\nfunction buildFileChangeCopyText(summary: TurnFileChangeSummary | null): string {\n if (!summary || summary.changes.length === 0) return ''\n const lines = summary.changes.map((change) => {\n const pathLabel = displayFileChangePath(change.path)\n const movedLabel = change.movedToPath ? ` -> ${displayFileChangePath(change.movedToPath)}` : ''\n const delta = formatFileChangeDelta(change)\n return `- ${fileChangeOperationLabel(change)}: ${pathLabel}${movedLabel}${delta ? ` (${delta})` : ''}`\n })\n return `Modified files:\\n${lines.join('\\n')}`.trim()\n}\n\nconst diffViewerChanges = computed<UiFileChange[]>(() => activeDiffViewerSummary.value?.changes ?? [])\n\nconst activeDiffViewerChange = computed<UiFileChange | null>(() => {\n const changes = diffViewerChanges.value\n if (changes.length === 0) return null\n return changes.find((change) => fileChangeKey(change) === activeDiffViewerChangeKey.value) ?? changes[0]\n})\n\nfunction inferDiffViewerLanguage(change: UiFileChange): string {\n const targetPath = change.movedToPath || change.path\n const extension = targetPath.split('.').pop()?.toLowerCase() ?? ''\n return CODE_LANGUAGE_ALIASES[extension] ?? extension ?? ''\n}\n\nfunction hasStructuredUnifiedDiff(change: UiFileChange): boolean {\n return change.operation === 'update' && /^diff --git |^@@ |^--- |^\\+\\+\\+ |^[ +-]|^\\*\\*\\* (Move to:|End of File)/mu.test(change.diff)\n}\n\nfunction buildSyntheticDiffLines(change: UiFileChange): DiffViewerLine[] {\n const normalized = change.diff.replace(/\\r\\n/g, '\\n')\n const lines = normalized.length > 0 ? normalized.split('\\n') : []\n if (lines.length > 0 && lines[lines.length - 1] === '') {\n lines.pop()\n }\n return lines.map((line, index) => ({\n key: `${fileChangeKey(change)}:synthetic:${index}`,\n kind: change.operation === 'delete' ? 'remove' : 'add',\n oldLine: change.operation === 'delete' ? index + 1 : null,\n newLine: change.operation === 'delete' ? null : index + 1,\n text: line,\n }))\n}\n\nfunction buildUnifiedDiffLines(change: UiFileChange): DiffViewerLine[] {\n const normalized = change.diff.replace(/\\r\\n/g, '\\n')\n const lines = normalized.length > 0 ? normalized.split('\\n') : []\n if (lines.length > 0 && lines[lines.length - 1] === '') {\n lines.pop()\n }\n\n const output: DiffViewerLine[] = []\n let oldLine = 0\n let newLine = 0\n\n for (const [index, line] of lines.entries()) {\n const hunkMatch = line.match(/^@@\\s+-(\\d+)(?:,\\d+)?\\s+\\+(\\d+)(?:,\\d+)?\\s+@@/u)\n if (hunkMatch) {\n oldLine = Number(hunkMatch[1])\n newLine = Number(hunkMatch[2])\n output.push({\n key: `${fileChangeKey(change)}:hunk:${index}`,\n kind: 'hunk',\n oldLine: null,\n newLine: null,\n text: line,\n })\n continue\n }\n\n if (line.startsWith('+') && !line.startsWith('+++')) {\n output.push({\n key: `${fileChangeKey(change)}:add:${index}`,\n kind: 'add',\n oldLine: null,\n newLine,\n text: line.slice(1),\n })\n newLine += 1\n continue\n }\n\n if (line.startsWith('-') && !line.startsWith('---')) {\n output.push({\n key: `${fileChangeKey(change)}:remove:${index}`,\n kind: 'remove',\n oldLine,\n newLine: null,\n text: line.slice(1),\n })\n oldLine += 1\n continue\n }\n\n if (line.startsWith(' ')) {\n output.push({\n key: `${fileChangeKey(change)}:context:${index}`,\n kind: 'context',\n oldLine,\n newLine,\n text: line.slice(1),\n })\n oldLine += 1\n newLine += 1\n continue\n }\n\n output.push({\n key: `${fileChangeKey(change)}:meta:${index}`,\n kind: 'meta',\n oldLine: null,\n newLine: null,\n text: line,\n })\n }\n\n return output\n}\n\nfunction buildDiffViewerLines(change: UiFileChange | null): DiffViewerLine[] {\n if (!change || !change.diff.trim()) return []\n if (hasStructuredUnifiedDiff(change)) {\n return buildUnifiedDiffLines(change)\n }\n return buildSyntheticDiffLines(change)\n}\n\nconst activeDiffViewerLines = computed<DiffViewerLine[]>(() => buildDiffViewerLines(activeDiffViewerChange.value))\n\nfunction hasDiffViewerContent(change: UiFileChange | null): boolean {\n return Boolean(change?.diff.trim())\n}\n\nfunction diffViewerMarker(line: DiffViewerLine): string {\n if (line.kind === 'add') return '+'\n if (line.kind === 'remove') return '-'\n if (line.kind === 'hunk') return '@@'\n return ''\n}\n\nfunction copyTextWithSelectionFallback(text: string): boolean {\n if (typeof document === 'undefined') return false\n\n const textarea = document.createElement('textarea')\n textarea.value = text\n textarea.setAttribute('readonly', 'true')\n textarea.style.position = 'fixed'\n textarea.style.left = '-9999px'\n textarea.style.opacity = '0'\n textarea.style.pointerEvents = 'none'\n document.body.appendChild(textarea)\n textarea.focus()\n textarea.select()\n textarea.setSelectionRange(0, text.length)\n\n try {\n return document.execCommand('copy')\n } catch {\n return false\n } finally {\n document.body.removeChild(textarea)\n }\n}\n\nasync function copyResponse(anchorMessageId: string): Promise<void> {\n const content = copyableResponseContentByAnchorId.value[anchorMessageId] ?? ''\n if (!content) return\n\n let copied = false\n if (typeof navigator !== 'undefined' && navigator.clipboard?.writeText) {\n try {\n await navigator.clipboard.writeText(content)\n copied = true\n } catch {\n copied = false\n }\n }\n\n if (!copied) {\n copied = copyTextWithSelectionFallback(content)\n }\n\n if (!copied) return\n\n copiedResponseAnchorId.value = anchorMessageId\n if (copiedMessageResetTimer) {\n clearTimeout(copiedMessageResetTimer)\n }\n copiedMessageResetTimer = setTimeout(() => {\n if (copiedResponseAnchorId.value === anchorMessageId) {\n copiedResponseAnchorId.value = ''\n }\n copiedMessageResetTimer = null\n }, 1800)\n}\n\nfunction forkResponse(anchorMessageId: string): void {\n const turnIndex = forkableTurnIndexByAnchorId.value[anchorMessageId]\n if (typeof turnIndex !== 'number') return\n if (!props.activeThreadId) return\n emit('forkThread', {\n threadId: props.activeThreadId,\n turnIndex,\n })\n}\n\nconst rollbackTurnIdByAnchorId = computed<Record<string, string>>(() => {\n const groupedTurns = new Map<string, { anchorMessageId: string; turnId: string }>()\n\n for (const message of props.messages) {\n if (!isCopyableAssistantMessage(message) || typeof message.turnIndex !== 'number') continue\n const turnId = typeof message.turnId === 'string' && message.turnId.length > 0 ? message.turnId : ''\n if (!turnId) continue\n\n const responseKey = `turn:${message.turnIndex}`\n const existing = groupedTurns.get(responseKey)\n if (existing) {\n existing.anchorMessageId = message.id\n existing.turnId = turnId\n continue\n }\n groupedTurns.set(responseKey, { anchorMessageId: message.id, turnId })\n }\n\n const next: Record<string, string> = {}\n for (const entry of groupedTurns.values()) {\n next[entry.anchorMessageId] = entry.turnId\n }\n return next\n})\n\nfunction showRollbackButton(message: UiMessage): boolean {\n return typeof rollbackTurnIdByAnchorId.value[message.id] === 'string'\n}\n\nfunction rollbackResponse(anchorMessageId: string): void {\n const turnId = rollbackTurnIdByAnchorId.value[anchorMessageId]\n if (!turnId) return\n emit('rollback', { turnId })\n}\n\nfunction splitPlainTextByLinks(text: string): InlineSegment[] {\n const segments: InlineSegment[] = []\n const pattern = /https?:\\/\\/[^\\s<>\"'`,。;:!?、()[\\]{}「」『』《》]+|file:\\/\\/[^\\n<>\"'`,。;:!?、[\\]{}「」『』《》]+|(?:[A-Za-z]:[\\\\/]|~\\/|\\.{1,2}\\/)[^\\n<>\"'`,。;:!?、[\\]{}「」『』《》]+|(?<![\\p{L}\\p{N}_-])\\/[^\\n<>\"'`,。;:!?、[\\]{}「」『』《》]+|[A-Za-z0-9._@() -]+(?:[\\\\/][A-Za-z0-9._@() -]+)+(?:#L\\d+(?:C\\d+)?|:\\d+(?::\\d+)?)?/gu\n let cursor = 0\n\n for (const match of text.matchAll(pattern)) {\n if (typeof match.index !== 'number') continue\n const start = match.index\n const end = start + match[0].length\n\n if (start > cursor) {\n segments.push({ kind: 'text', value: text.slice(cursor, start) })\n }\n\n let token = match[0]\n let trailingPunctuation = ''\n while (/[.,;:!?,。;:!?、]$/u.test(token)) {\n trailingPunctuation = token.slice(-1) + trailingPunctuation\n token = token.slice(0, -1)\n }\n const wrapped = trimLinkWrappers(token)\n token = wrapped.core\n const leading = wrapped.leading\n const trailing = wrapped.trailing + trailingPunctuation\n\n if (leading) {\n segments.push({ kind: 'text', value: leading })\n }\n\n if (token.startsWith('**') && token.endsWith('**') && token.length > 4) {\n segments.push({ kind: 'bold', value: token.slice(2, -2) })\n if (trailing) {\n segments.push({ kind: 'text', value: trailing })\n }\n } else if (/^https?:\\/\\//u.test(token)) {\n segments.push({ kind: 'url', value: token, href: token })\n if (trailing) {\n segments.push({ kind: 'text', value: trailing })\n }\n } else {\n const ref = parseFileReference(token)\n if (ref) {\n segments.push({\n kind: 'file',\n value: token,\n path: ref.path,\n displayPath: token,\n downloadName: getBasename(ref.path),\n })\n if (trailing) {\n segments.push({ kind: 'text', value: trailing })\n }\n } else {\n segments.push({ kind: 'text', value: match[0] })\n }\n }\n\n cursor = end\n }\n\n if (cursor < text.length) {\n segments.push({ kind: 'text', value: text.slice(cursor) })\n }\n\n return applyInlineMarkdownMarkers(segments)\n}\n\nfunction applyDelimitedMarkersAcrossTextSegments(\n segments: InlineSegment[],\n options: {\n marker: string\n kind: Extract<InlineSegment['kind'], 'bold' | 'italic' | 'strikethrough'>\n isValidContent?: (value: string) => boolean\n },\n): InlineSegment[] {\n const output: InlineSegment[] = []\n let isOpen = false\n let buffer = ''\n\n const pushText = (value: string): void => {\n if (!value) return\n output.push({ kind: 'text', value })\n }\n\n for (const segment of segments) {\n if (segment.kind !== 'text') {\n if (isOpen) {\n pushText(`${options.marker}${buffer}`)\n isOpen = false\n buffer = ''\n }\n output.push(segment)\n continue\n }\n\n let remaining = segment.value\n while (remaining.length > 0) {\n const markerIndex = remaining.indexOf(options.marker)\n if (markerIndex < 0) {\n if (isOpen) buffer += remaining\n else pushText(remaining)\n break\n }\n\n const before = remaining.slice(0, markerIndex)\n if (isOpen) buffer += before\n else pushText(before)\n\n remaining = remaining.slice(markerIndex + options.marker.length)\n if (isOpen) {\n const content = buffer\n if (\n content.length > 0 &&\n (options.isValidContent ? options.isValidContent(content) : true)\n ) {\n output.push({ kind: options.kind, value: content })\n } else {\n pushText(`${options.marker}${content}${options.marker}`)\n }\n buffer = ''\n isOpen = false\n } else {\n isOpen = true\n }\n }\n }\n\n if (isOpen) {\n pushText(`${options.marker}${buffer}`)\n }\n\n return output\n}\n\nfunction applyInlineMarkdownMarkers(segments: InlineSegment[]): InlineSegment[] {\n const nonWhitespaceWrapped = (value: string): boolean => (\n value.trim().length > 0 &&\n !/^\\s/u.test(value) &&\n !/\\s$/u.test(value)\n )\n\n let next = applyDelimitedMarkersAcrossTextSegments(segments, {\n marker: '**',\n kind: 'bold',\n isValidContent: nonWhitespaceWrapped,\n })\n\n next = applyDelimitedMarkersAcrossTextSegments(next, {\n marker: '~~',\n kind: 'strikethrough',\n isValidContent: nonWhitespaceWrapped,\n })\n\n next = applyDelimitedMarkersAcrossTextSegments(next, {\n marker: '*',\n kind: 'italic',\n isValidContent: nonWhitespaceWrapped,\n })\n\n return next\n}\n\nfunction splitTextByFileUrls(text: string): InlineSegment[] {\n const segments: InlineSegment[] = []\n let cursor = 0\n let scanFrom = 0\n\n const findNextMarkdownLink = (\n source: string,\n fromIndex: number,\n ): { start: number; end: number; token: string } | null => {\n let linkStart = source.indexOf('[', fromIndex)\n while (linkStart >= 0) {\n const labelEnd = source.indexOf(']', linkStart + 1)\n if (labelEnd < 0) return null\n if (source[labelEnd + 1] !== '(') {\n linkStart = source.indexOf('[', linkStart + 1)\n continue\n }\n\n let depth = 1\n let index = labelEnd + 2\n let hasNewLine = false\n while (index < source.length) {\n const char = source[index]\n if (char === '\\n') {\n hasNewLine = true\n break\n }\n if (char === '(') depth += 1\n if (char === ')') {\n depth -= 1\n if (depth === 0) {\n const token = source.slice(linkStart, index + 1)\n if (parseMarkdownLinkToken(token)) {\n return { start: linkStart, end: index + 1, token }\n }\n break\n }\n }\n index += 1\n }\n\n if (hasNewLine) {\n linkStart = source.indexOf('[', linkStart + 1)\n continue\n }\n linkStart = source.indexOf('[', linkStart + 1)\n }\n return null\n }\n\n while (scanFrom < text.length) {\n const match = findNextMarkdownLink(text, scanFrom)\n if (!match) break\n const { start, end, token } = match\n\n if (start > cursor) {\n segments.push(...splitPlainTextByLinks(text.slice(cursor, start)))\n }\n\n const markdownToken = parseMarkdownLinkToken(token)\n if (!markdownToken) {\n segments.push(...splitPlainTextByLinks(text.slice(start, end)))\n cursor = end\n scanFrom = end\n continue\n }\n const label = markdownToken.label\n const target = markdownToken.target\n\n if (/^https?:\\/\\//u.test(target)) {\n segments.push({ kind: 'url', value: label || target, href: target })\n } else {\n const ref = parseFileReference(target)\n if (ref) {\n segments.push({\n kind: 'file',\n value: target,\n path: ref.path,\n displayPath: label || target,\n downloadName: getBasename(ref.path),\n })\n } else {\n segments.push({ kind: 'text', value: token })\n }\n }\n\n cursor = end\n scanFrom = end\n }\n\n if (cursor < text.length) {\n segments.push(...splitPlainTextByLinks(text.slice(cursor)))\n }\n\n return segments\n}\n\nfunction parseInlineSegments(text: string): InlineSegment[] {\n if (text.includes('](')) {\n const linkFirstSegments = splitTextByFileUrls(text)\n if (linkFirstSegments.some((segment) => segment.kind === 'file' || segment.kind === 'url')) {\n return linkFirstSegments\n }\n }\n\n if (!text.includes('`')) return splitTextByFileUrls(text)\n\n const segments: InlineSegment[] = []\n let cursor = 0\n let textStart = 0\n\n while (cursor < text.length) {\n if (text[cursor] !== '`') {\n cursor += 1\n continue\n }\n\n let openLength = 1\n while (cursor + openLength < text.length && text[cursor + openLength] === '`') {\n openLength += 1\n }\n const delimiter = '`'.repeat(openLength)\n\n let searchFrom = cursor + openLength\n let closingStart = -1\n while (searchFrom < text.length) {\n const candidate = text.indexOf(delimiter, searchFrom)\n if (candidate < 0) break\n\n const hasBacktickBefore = candidate > 0 && text[candidate - 1] === '`'\n const hasBacktickAfter =\n candidate + openLength < text.length && text[candidate + openLength] === '`'\n const hasNewLineInside = text.slice(cursor + openLength, candidate).includes('\\n')\n\n if (!hasBacktickBefore && !hasBacktickAfter && !hasNewLineInside) {\n closingStart = candidate\n break\n }\n searchFrom = candidate + 1\n }\n\n if (closingStart < 0) {\n cursor += openLength\n continue\n }\n\n if (cursor > textStart) {\n segments.push(...splitTextByFileUrls(text.slice(textStart, cursor)))\n }\n\n const token = text.slice(cursor + openLength, closingStart)\n if (token.length > 0) {\n const markdownLink = parseMarkdownLinkToken(token)\n if (markdownLink) {\n if (/^https?:\\/\\//u.test(markdownLink.target)) {\n segments.push({\n kind: 'url',\n value: markdownLink.label || markdownLink.target,\n href: markdownLink.target,\n })\n } else {\n const markdownFileReference = parseFileReference(markdownLink.target)\n if (markdownFileReference) {\n segments.push({\n kind: 'file',\n value: markdownLink.target,\n path: markdownFileReference.path,\n displayPath: markdownLink.label || markdownLink.target,\n downloadName: getBasename(markdownFileReference.path),\n })\n } else {\n segments.push({ kind: 'code', value: token })\n }\n }\n } else if (/^https?:\\/\\/[^\\s]+$/u.test(token)) {\n segments.push({\n kind: 'url',\n value: token,\n href: token,\n })\n } else {\n const fileReference = parseFileReference(token)\n if (fileReference) {\n const displayPath = fileReference.line\n ? `${fileReference.path}:${String(fileReference.line)}`\n : fileReference.path\n segments.push({\n kind: 'file',\n value: token,\n path: fileReference.path,\n displayPath,\n downloadName: getBasename(fileReference.path),\n })\n } else {\n segments.push({ kind: 'code', value: token })\n }\n }\n } else {\n segments.push({ kind: 'text', value: `${delimiter}${delimiter}` })\n }\n\n cursor = closingStart + openLength\n textStart = cursor\n }\n\n if (textStart < text.length) {\n segments.push(...splitTextByFileUrls(text.slice(textStart)))\n }\n\n return segments\n}\n\nfunction toRenderableImageUrl(value: string): string {\n const normalized = value.trim()\n if (!normalized) return ''\n if (\n normalized.startsWith('data:') ||\n normalized.startsWith('blob:') ||\n normalized.startsWith('http://') ||\n normalized.startsWith('https://') ||\n normalized.startsWith('/codex-local-image?')\n ) {\n return normalized\n }\n\n if (normalized.startsWith('file://')) {\n return `/codex-local-image?path=${encodeURIComponent(normalized)}`\n }\n\n const looksLikeUnixAbsolute = normalized.startsWith('/')\n const looksLikeWindowsAbsolute = /^[A-Za-z]:[\\\\/]/u.test(normalized)\n if (looksLikeUnixAbsolute || looksLikeWindowsAbsolute) {\n return `/codex-local-image?path=${encodeURIComponent(normalized)}`\n }\n\n return normalized\n}\n\nfunction toBrowseUrl(pathValue: string): string {\n const normalized = pathValue.trim()\n if (!normalized) return '#'\n const looksLikeAbsolutePath = (candidate: string): boolean => (\n candidate.startsWith('/') || /^[A-Za-z]:[\\\\/]/u.test(candidate)\n )\n\n const parsed = parseFileReference(normalized)\n const candidatePath = parsed?.path ?? normalized\n const resolved = resolveRelativePath(candidatePath, props.cwd)\n\n if (looksLikeAbsolutePath(resolved)) {\n const normalizedResolved = resolved.startsWith('/') ? resolved : `/${resolved}`\n return `/codex-local-browse${encodeURI(normalizedResolved)}`\n }\n\n return '#'\n}\n\nconst fileLinkContextMenuStyle = computed(() => ({\n left: `${String(fileLinkContextMenuX.value)}px`,\n top: `${String(fileLinkContextMenuY.value)}px`,\n}))\n\nfunction toEditUrlFromBrowseHref(href: string): string {\n const normalizedHref = href.trim()\n if (!normalizedHref) return ''\n try {\n const resolved = new URL(normalizedHref, window.location.href)\n if (!resolved.pathname.startsWith('/codex-local-browse')) return ''\n const editPath = `/codex-local-edit${resolved.pathname.slice('/codex-local-browse'.length)}`\n return `${editPath}${resolved.search}${resolved.hash}`\n } catch {\n return ''\n }\n}\n\nfunction onConversationContextMenu(event: MouseEvent): void {\n const target = event.target\n if (!(target instanceof Element)) return\n\n const anchor = target.closest('a.message-file-link')\n if (!(anchor instanceof HTMLAnchorElement)) return\n\n const href = (anchor.getAttribute('href') ?? '').trim()\n if (!href || href === '#') return\n\n event.preventDefault()\n event.stopPropagation()\n\n fileLinkContextBrowseUrl.value = href\n fileLinkContextEditUrl.value = toEditUrlFromBrowseHref(href)\n fileLinkContextMenuX.value = event.clientX\n fileLinkContextMenuY.value = event.clientY\n isFileLinkContextMenuVisible.value = true\n}\n\nfunction closeFileLinkContextMenu(): void {\n if (!isFileLinkContextMenuVisible.value) return\n isFileLinkContextMenuVisible.value = false\n}\n\nfunction openFileLinkContextBrowse(): void {\n const href = fileLinkContextBrowseUrl.value\n closeFileLinkContextMenu()\n if (!href || href === '#') return\n window.open(href, '_blank', 'noopener,noreferrer')\n}\n\nfunction openFileLinkContextEdit(): void {\n const href = fileLinkContextEditUrl.value\n closeFileLinkContextMenu()\n if (!href || href === '#') return\n window.open(href, '_blank', 'noopener,noreferrer')\n}\n\nasync function copyFileLinkContextLink(): Promise<void> {\n const href = fileLinkContextBrowseUrl.value\n closeFileLinkContextMenu()\n if (!href || href === '#') return\n\n try {\n await navigator.clipboard.writeText(href)\n } catch {\n const textarea = document.createElement('textarea')\n textarea.value = href\n textarea.setAttribute('readonly', 'true')\n textarea.style.position = 'fixed'\n textarea.style.opacity = '0'\n document.body.appendChild(textarea)\n textarea.select()\n document.execCommand('copy')\n document.body.removeChild(textarea)\n }\n}\n\nfunction onWindowPointerDownForFileLinkContextMenu(event: PointerEvent): void {\n if (!isFileLinkContextMenuVisible.value) return\n const menu = fileLinkContextMenuRef.value\n if (!menu) {\n closeFileLinkContextMenu()\n return\n }\n const target = event.target\n if (target instanceof Node && menu.contains(target)) return\n closeFileLinkContextMenu()\n}\n\nfunction onWindowBlurForFileLinkContextMenu(): void {\n closeFileLinkContextMenu()\n}\n\nfunction onWindowKeydownForFileLinkContextMenu(event: KeyboardEvent): void {\n if (event.key !== 'Escape') return\n closeFileLinkContextMenu()\n}\n\nfunction normalizeMarkdownText(text: string): string {\n return text.replace(/\\r\\n/gu, '\\n')\n}\n\nfunction leadingIndentWidth(line: string): number {\n const leadingWhitespace = line.match(/^\\s*/u)?.[0] ?? ''\n return leadingWhitespace.replace(/\\t/gu, ' ').length\n}\n\nfunction stripIndentedContent(line: string, baseIndent: number): string {\n if (baseIndent <= 0) return line.trimStart()\n\n let index = 0\n let width = 0\n while (index < line.length && width < baseIndent) {\n const character = line[index]\n width += character === '\\t' ? 4 : 1\n index += 1\n }\n\n return line.slice(index)\n}\n\nfunction isBlankMarkdownLine(line: string): boolean {\n return line.trim().length === 0\n}\n\nfunction readHeading(line: string): { level: number; value: string } | null {\n const match = line.match(/^\\s{0,3}(#{1,6})\\s+(.+)$/u)\n if (!match) return null\n return {\n level: match[1].length,\n value: match[2].trim(),\n }\n}\n\nfunction readBlockquoteLine(line: string): string | null {\n const match = line.match(/^\\s{0,3}>\\s?(.*)$/u)\n if (!match) return null\n return match[1] ?? ''\n}\n\nfunction readUnorderedListItem(line: string): string | null {\n const match = line.match(/^\\s*[-*+]\\s+(.+)$/u)\n return match?.[1]?.trim() ?? null\n}\n\nfunction readUnorderedListItemMatch(line: string): { indent: number; text: string } | null {\n const match = line.match(/^(\\s*)[-*+]\\s+(.+)$/u)\n if (!match) return null\n return {\n indent: leadingIndentWidth(match[1] ?? ''),\n text: match[2]?.trim() ?? '',\n }\n}\n\nfunction readTaskListItem(line: string): TaskListItem | null {\n const match = line.match(/^\\s*[-*+]\\s+\\[([ xX])\\]\\s+(.+)$/u)\n if (!match) return null\n return {\n checked: (match[1] ?? ' ').toLowerCase() === 'x',\n text: match[2]?.trim() ?? '',\n }\n}\n\nfunction readTaskListItemMatch(line: string): { indent: number; item: TaskListItem } | null {\n const match = line.match(/^(\\s*)[-*+]\\s+\\[([ xX])\\]\\s+(.+)$/u)\n if (!match) return null\n return {\n indent: leadingIndentWidth(match[1] ?? ''),\n item: {\n checked: (match[2] ?? ' ').toLowerCase() === 'x',\n text: match[3]?.trim() ?? '',\n },\n }\n}\n\nfunction readOrderedListItemData(line: string): { indent: number; text: string; start: number } | null {\n const match = line.match(/^(\\s*)(\\d+)[.)]\\s+(.+)$/u)\n if (!match) return null\n return {\n indent: leadingIndentWidth(match[1] ?? ''),\n start: Number.parseInt(match[2] ?? '1', 10) || 1,\n text: match[3]?.trim() ?? '',\n }\n}\n\nfunction readOrderedListItem(line: string): string | null {\n return readOrderedListItemData(line)?.text ?? null\n}\n\nfunction readOrderedListItemMatch(line: string): { indent: number; text: string; start: number } | null {\n return readOrderedListItemData(line)\n}\n\nfunction splitMarkdownTableRow(line: string): string[] | null {\n const trimmed = line.trim()\n if (!trimmed.includes('|')) return null\n\n let content = trimmed\n if (content.startsWith('|')) content = content.slice(1)\n if (content.endsWith('|')) content = content.slice(0, -1)\n\n const cells: string[] = []\n let current = ''\n let codeFenceLength = 0\n\n for (let index = 0; index < content.length; index += 1) {\n const character = content[index]\n\n if (character === '\\\\' && content[index + 1] === '|') {\n current += '|'\n index += 1\n continue\n }\n\n if (character === '`') {\n let runLength = 1\n while (content[index + runLength] === '`') runLength += 1\n current += content.slice(index, index + runLength)\n if (codeFenceLength === 0) codeFenceLength = runLength\n else if (codeFenceLength === runLength) codeFenceLength = 0\n index += runLength - 1\n continue\n }\n\n if (character === '|' && codeFenceLength === 0) {\n cells.push(current.trim())\n current = ''\n continue\n }\n\n current += character\n }\n\n cells.push(current.trim())\n return cells.some((cell) => cell.length > 0) ? cells : null\n}\n\nfunction readTableAlignmentRow(line: string): TableAlignment[] | null {\n const cells = splitMarkdownTableRow(line)\n if (!cells || cells.length === 0) return null\n\n const alignments = cells.map((cell) => {\n const trimmed = cell.replace(/\\s+/gu, '')\n if (!/^:?-{3,}:?$/u.test(trimmed)) return null\n const startsWithColon = trimmed.startsWith(':')\n const endsWithColon = trimmed.endsWith(':')\n if (startsWithColon && endsWithColon) return 'center'\n if (endsWithColon) return 'right'\n if (startsWithColon) return 'left'\n return null\n })\n\n return alignments.every((alignment, index) => alignment !== null || /^-+$/u.test(cells[index].replace(/\\s+/gu, '')))\n ? alignments\n : null\n}\n\nfunction normalizeTableCells(cells: string[], width: number): string[] {\n if (cells.length === width) return cells\n if (cells.length > width) return cells.slice(0, width)\n return [...cells, ...Array.from({ length: width - cells.length }, () => '')]\n}\n\nfunction readTableBlock(lines: string[], startIndex: number): Extract<MessageBlock, { kind: 'table' }> | null {\n if (startIndex + 1 >= lines.length) return null\n\n const headerLine = lines[startIndex]\n const separatorLine = lines[startIndex + 1]\n const headers = splitMarkdownTableRow(headerLine)\n const alignments = readTableAlignmentRow(separatorLine)\n if (!headers || !alignments) return null\n if (headers.length !== alignments.length) return null\n\n const trimmedHeader = headerLine.trim()\n if (!trimmedHeader.startsWith('|') && (trimmedHeader.match(/\\|/gu)?.length ?? 0) < 2) return null\n\n const width = headers.length\n const rows: string[][] = []\n let index = startIndex + 2\n while (index < lines.length) {\n if (isBlankMarkdownLine(lines[index])) break\n const row = splitMarkdownTableRow(lines[index])\n if (!row) break\n rows.push(normalizeTableCells(row, width))\n index += 1\n }\n\n return {\n kind: 'table',\n headers: normalizeTableCells(headers, width),\n rows,\n alignments,\n }\n}\n\nfunction isParagraphBreakingLine(line: string): boolean {\n return (\n isBlankMarkdownLine(line) ||\n readFenceStart(line) !== null ||\n isThematicBreakLine(line) ||\n readHeading(line) !== null ||\n readBlockquoteLine(line) !== null ||\n readTaskListItem(line) !== null ||\n readUnorderedListItem(line) !== null ||\n readOrderedListItem(line) !== null\n )\n}\n\nfunction readListParagraph(\n lines: string[],\n startIndex: number,\n baseIndent = -1,\n): { value: string; nextIndex: number } | null {\n const paragraphLines: string[] = []\n let index = startIndex\n\n while (index < lines.length) {\n if (isParagraphBreakingLine(lines[index])) break\n if (baseIndent >= 0 && leadingIndentWidth(lines[index]) <= baseIndent) break\n\n paragraphLines.push(baseIndent >= 0 ? stripIndentedContent(lines[index], baseIndent + 1) : lines[index])\n index += 1\n }\n\n const value = paragraphLines.join('\\n').trim()\n return value ? { value, nextIndex: index } : null\n}\n\nfunction findNextNonBlankLineIndex(lines: string[], startIndex: number): number {\n for (let index = startIndex; index < lines.length; index += 1) {\n if (!isBlankMarkdownLine(lines[index])) return index\n }\n return -1\n}\n\nfunction readNestedListBlocks(\n lines: string[],\n startIndex: number,\n parentIndent: number,\n stopAtItem: ((line: string) => { indent: number; text: string } | null) | null = null,\n allowLooseChildLists = false,\n): { blocks: MessageBlock[]; nextIndex: number } | null {\n const nestedLines: string[] = []\n let index = startIndex\n\n while (index < lines.length) {\n const line = lines[index]\n if (isBlankMarkdownLine(line)) {\n const nextNonBlankIndex = findNextNonBlankLineIndex(lines, index + 1)\n if (nextNonBlankIndex === -1) {\n nestedLines.push('')\n index = lines.length\n break\n }\n const nextStopItem = stopAtItem?.(lines[nextNonBlankIndex])\n if (nextStopItem && nextStopItem.indent === parentIndent) break\n if (leadingIndentWidth(lines[nextNonBlankIndex]) <= parentIndent) break\n nestedLines.push('')\n index += 1\n continue\n }\n\n const stopItem = stopAtItem?.(line)\n if (stopItem && stopItem.indent === parentIndent) break\n\n const lineIndent = leadingIndentWidth(line)\n const isLooseChildList = allowLooseChildLists && (\n readTaskListItem(line) !== null ||\n readUnorderedListItem(line) !== null\n )\n if (lineIndent <= parentIndent && !isLooseChildList) break\n\n nestedLines.push(\n lineIndent > parentIndent\n ? stripIndentedContent(line, parentIndent + 1)\n : line.trimStart(),\n )\n index += 1\n }\n\n while (nestedLines.length > 0 && isBlankMarkdownLine(nestedLines[0])) nestedLines.shift()\n while (nestedLines.length > 0 && isBlankMarkdownLine(nestedLines[nestedLines.length - 1])) nestedLines.pop()\n\n if (nestedLines.length === 0) return null\n\n return {\n blocks: parseTextBlocks(nestedLines.join('\\n')),\n nextIndex: index,\n }\n}\n\nfunction readListItems(\n lines: string[],\n startIndex: number,\n readItem: (line: string) => { indent: number; text: string } | null,\n allowLooseChildLists = false,\n): { items: ListItem[]; nextIndex: number } | null {\n const items: ListItem[] = []\n let index = startIndex\n const firstItem = readItem(lines[startIndex])\n if (!firstItem) return null\n const baseIndent = firstItem.indent\n\n while (index < lines.length) {\n const itemValue = readItem(lines[index])\n if (itemValue === null || itemValue.indent !== baseIndent) break\n\n const paragraphs = [itemValue.text]\n const children: MessageBlock[] = []\n index += 1\n\n while (index < lines.length) {\n if (isBlankMarkdownLine(lines[index])) {\n const nextNonBlankIndex = findNextNonBlankLineIndex(lines, index + 1)\n if (nextNonBlankIndex === -1) {\n index = lines.length\n break\n }\n const nextSameLevelItem = readItem(lines[nextNonBlankIndex])\n if (nextSameLevelItem && nextSameLevelItem.indent === baseIndent) {\n index = nextNonBlankIndex\n break\n }\n if (leadingIndentWidth(lines[nextNonBlankIndex]) <= baseIndent) {\n index = nextNonBlankIndex\n break\n }\n index += 1\n continue\n }\n\n const nextSameLevelItem = readItem(lines[index])\n if (nextSameLevelItem && nextSameLevelItem.indent === baseIndent) break\n\n const hasIndentedChildren = leadingIndentWidth(lines[index]) > baseIndent\n const hasLooseChildList = allowLooseChildLists && (\n readTaskListItem(lines[index]) !== null ||\n readUnorderedListItem(lines[index]) !== null\n )\n if (hasIndentedChildren || hasLooseChildList) {\n const nestedBlocks = readNestedListBlocks(lines, index, baseIndent, readItem, allowLooseChildLists)\n if (nestedBlocks) {\n children.push(...nestedBlocks.blocks)\n index = nestedBlocks.nextIndex\n continue\n }\n }\n\n if (leadingIndentWidth(lines[index]) <= baseIndent) break\n\n const continuation = readListParagraph(lines, index, baseIndent)\n if (!continuation) break\n paragraphs.push(continuation.value)\n index = continuation.nextIndex\n }\n\n items.push(children.length > 0 ? { paragraphs, children } : { paragraphs })\n }\n\n return items.length > 0 ? { items, nextIndex: index } : null\n}\n\nfunction isThematicBreakLine(line: string): boolean {\n return /^\\s{0,3}(?:-{3,}|\\*{3,}|_{3,})\\s*$/u.test(line.trim())\n}\n\nfunction readFenceStart(line: string): { marker: string; language: string } | null {\n const match = line.match(/^\\s{0,3}(```+|~~~+)\\s*([^\\s`~][^`]*)?\\s*$/u)\n if (!match) return null\n return {\n marker: match[1],\n language: (match[2] ?? '').trim(),\n }\n}\n\nfunction parseTextBlocks(text: string): MessageBlock[] {\n const normalizedText = normalizeMarkdownText(text)\n const lines = normalizedText.split('\\n')\n const blocks: MessageBlock[] = []\n let index = 0\n\n while (index < lines.length) {\n if (isBlankMarkdownLine(lines[index])) {\n index += 1\n continue\n }\n\n const fence = readFenceStart(lines[index])\n if (fence) {\n index += 1\n const codeLines: string[] = []\n while (index < lines.length) {\n if (lines[index].trim() === fence.marker) {\n index += 1\n break\n }\n codeLines.push(lines[index])\n index += 1\n }\n blocks.push({\n kind: 'codeBlock',\n language: fence.language,\n value: codeLines.join('\\n'),\n })\n continue\n }\n\n if (isThematicBreakLine(lines[index])) {\n blocks.push({ kind: 'thematicBreak' })\n index += 1\n continue\n }\n\n const heading = readHeading(lines[index])\n if (heading) {\n blocks.push({ kind: 'heading', level: heading.level, value: heading.value })\n index += 1\n continue\n }\n\n const quoteLine = readBlockquoteLine(lines[index])\n if (quoteLine !== null) {\n const quoteLines: string[] = []\n while (index < lines.length) {\n const nextQuoteLine = readBlockquoteLine(lines[index])\n if (nextQuoteLine === null) break\n quoteLines.push(nextQuoteLine)\n index += 1\n }\n blocks.push({ kind: 'blockquote', value: quoteLines.join('\\n').trim() })\n continue\n }\n\n const table = readTableBlock(lines, index)\n if (table) {\n blocks.push(table)\n index += 2 + table.rows.length\n continue\n }\n\n const taskItem = readTaskListItem(lines[index])\n if (taskItem !== null) {\n const items: TaskListItem[] = []\n const baseIndent = readTaskListItemMatch(lines[index])?.indent ?? 0\n while (index < lines.length) {\n const nextItem = readTaskListItemMatch(lines[index])\n if (nextItem === null || nextItem.indent !== baseIndent) break\n items.push(nextItem.item)\n index += 1\n }\n if (items.length > 0) {\n blocks.push({ kind: 'taskList', items })\n continue\n }\n }\n\n const unorderedItem = readUnorderedListItem(lines[index])\n if (unorderedItem !== null) {\n const parsedList = readListItems(lines, index, readUnorderedListItemMatch)\n if (parsedList) {\n blocks.push({ kind: 'unorderedList', items: parsedList.items })\n index = parsedList.nextIndex\n continue\n }\n if (unorderedItem.length > 0) {\n blocks.push({ kind: 'unorderedList', items: [{ paragraphs: [unorderedItem] }] })\n index += 1\n continue\n }\n }\n\n const orderedItem = readOrderedListItem(lines[index])\n if (orderedItem !== null) {\n const orderedItemMatch = readOrderedListItemMatch(lines[index])\n const parsedList = readListItems(lines, index, readOrderedListItemMatch, true)\n if (parsedList) {\n blocks.push({\n kind: 'orderedList',\n items: parsedList.items,\n start: orderedItemMatch?.start ?? 1,\n })\n index = parsedList.nextIndex\n continue\n }\n if (orderedItem.length > 0) {\n blocks.push({\n kind: 'orderedList',\n items: [{ paragraphs: [orderedItem] }],\n start: orderedItemMatch?.start ?? 1,\n })\n index += 1\n continue\n }\n }\n\n const paragraphLines: string[] = []\n while (index < lines.length) {\n if (isBlankMarkdownLine(lines[index])) break\n if (\n readFenceStart(lines[index]) ||\n isThematicBreakLine(lines[index]) ||\n readHeading(lines[index]) ||\n readTableBlock(lines, index) ||\n readBlockquoteLine(lines[index]) !== null ||\n readTaskListItem(lines[index]) !== null ||\n readUnorderedListItem(lines[index]) !== null ||\n readOrderedListItem(lines[index]) !== null\n ) break\n paragraphLines.push(lines[index])\n index += 1\n }\n\n const value = paragraphLines.join('\\n').trim()\n if (value) {\n blocks.push({ kind: 'paragraph', value })\n }\n }\n\n return blocks\n}\n\nfunction parseNonCodeMessageBlocks(text: string): MessageBlock[] {\n if (!text.includes(') {\n return parseTextBlocks(text)\n }\n\n const blocks: MessageBlock[] = []\n const imagePattern = /!\\[([^\\]]*)\\]\\(([^)\\n]+)\\)/gu\n let cursor = 0\n\n for (const match of text.matchAll(imagePattern)) {\n const [fullMatch, altRaw, urlRaw] = match\n if (typeof match.index !== 'number') continue\n\n const start = match.index\n const end = start + fullMatch.length\n const imageUrl = toRenderableImageUrl(urlRaw.trim())\n if (!imageUrl) continue\n\n if (start > cursor) {\n blocks.push(...parseTextBlocks(text.slice(cursor, start)))\n }\n\n blocks.push({ kind: 'image', url: imageUrl, alt: altRaw.trim(), markdown: fullMatch })\n cursor = end\n }\n\n if (cursor < text.length) {\n blocks.push(...parseTextBlocks(text.slice(cursor)))\n }\n\n return blocks\n}\n\nfunction parseMessageBlocks(text: string): MessageBlock[] {\n const normalizedText = normalizeMarkdownText(text)\n const lines = normalizedText.split('\\n')\n const blocks: MessageBlock[] = []\n let index = 0\n let chunkStart = 0\n\n const flushChunk = (endExclusive: number): void => {\n if (endExclusive <= chunkStart) return\n const chunk = lines.slice(chunkStart, endExclusive).join('\\n')\n blocks.push(...parseNonCodeMessageBlocks(chunk))\n }\n\n while (index < lines.length) {\n const fence = readFenceStart(lines[index])\n if (!fence) {\n index += 1\n continue\n }\n\n flushChunk(index)\n\n index += 1\n const codeLines: string[] = []\n while (index < lines.length) {\n if (lines[index].trim() === fence.marker) {\n index += 1\n break\n }\n codeLines.push(lines[index])\n index += 1\n }\n\n blocks.push({\n kind: 'codeBlock',\n language: fence.language,\n value: codeLines.join('\\n'),\n })\n chunkStart = index\n }\n\n flushChunk(lines.length)\n return blocks.length > 0 ? blocks : [{ kind: 'paragraph', value: text }]\n}\n\nfunction escapeHtml(value: string): string {\n return value\n .replace(/&/gu, '&')\n .replace(/</gu, '<')\n .replace(/>/gu, '>')\n .replace(/\"/gu, '"')\n .replace(/'/gu, ''')\n}\n\nfunction normalizeCodeLanguage(language: string): string {\n const token = language.trim().split(/\\s+/u)[0]?.toLowerCase() ?? ''\n if (!token) return ''\n return CODE_LANGUAGE_ALIASES[token] ?? token\n}\n\nfunction renderHighlightedCodeAsHtml(language: string, value: string): string {\n const normalizedLanguage = normalizeCodeLanguage(language)\n if (!normalizedLanguage) return escapeHtml(value)\n const highlighter = highlightJsModule.value\n if (!highlighter) return escapeHtml(value)\n\n try {\n if (highlighter.getLanguage(normalizedLanguage)) {\n return highlighter.highlight(value, {\n language: normalizedLanguage,\n ignoreIllegals: true,\n }).value\n }\n } catch {\n // Fall back to plain escaped code when highlighting fails.\n }\n\n return escapeHtml(value)\n}\n\nfunction renderInlineSegmentsAsHtml(text: string): string {\n return parseInlineSegments(text)\n .map((segment) => {\n if (segment.kind === 'text') {\n return escapeHtml(segment.value)\n }\n if (segment.kind === 'bold') {\n return `<strong class=\"message-bold-text\">${escapeHtml(segment.value)}</strong>`\n }\n if (segment.kind === 'italic') {\n return `<em class=\"message-italic-text\">${escapeHtml(segment.value)}</em>`\n }\n if (segment.kind === 'strikethrough') {\n return `<s class=\"message-strikethrough-text\">${escapeHtml(segment.value)}</s>`\n }\n if (segment.kind === 'file') {\n return `<a class=\"message-file-link\" href=\"${escapeHtml(toBrowseUrl(segment.path))}\" target=\"_blank\" rel=\"noopener noreferrer\" title=\"${escapeHtml(segment.path)}\">${escapeHtml(segment.displayPath)}</a>`\n }\n if (segment.kind === 'url') {\n return `<a class=\"message-file-link\" href=\"${escapeHtml(segment.href)}\" target=\"_blank\" rel=\"noopener noreferrer\" title=\"${escapeHtml(segment.href)}\">${escapeHtml(segment.value)}</a>`\n }\n return `<code class=\"message-inline-code\">${escapeHtml(segment.value)}</code>`\n })\n .join('')\n}\n\nfunction renderListItemParagraphsAsHtml(item: ListItem): string {\n return item.paragraphs\n .map((paragraph) => `<div class=\"message-list-item-text message-list-item-paragraph\">${renderInlineSegmentsAsHtml(paragraph)}</div>`)\n .join('')\n}\n\nfunction renderListItemContentAsHtml(item: ListItem): string {\n const paragraphsHtml = renderListItemParagraphsAsHtml(item)\n const childrenHtml = item.children?.map((block) => renderMessageBlockAsHtml(block)).join('') ?? ''\n return paragraphsHtml + childrenHtml\n}\n\nfunction tableCellAlignmentStyle(alignment: TableAlignment): string {\n if (!alignment) return ''\n return ` style=\"text-align:${alignment}\"`\n}\n\nfunction renderMessageBlockAsHtml(block: MessageBlock): string {\n if (block.kind === 'paragraph') {\n return `<p class=\"message-text\">${renderInlineSegmentsAsHtml(block.value)}</p>`\n }\n if (block.kind === 'heading') {\n const level = Math.min(6, Math.max(1, Math.trunc(block.level)))\n const tag = headingTag(level)\n const classes = `message-heading ${headingClass(level)}`\n return `<${tag} class=\"${classes}\">${renderInlineSegmentsAsHtml(block.value)}</${tag}>`\n }\n if (block.kind === 'blockquote') {\n return `<blockquote class=\"message-blockquote\">${renderInlineSegmentsAsHtml(block.value)}</blockquote>`\n }\n if (block.kind === 'unorderedList') {\n const items = block.items\n .map((item) => `<li class=\"message-list-item\"><div class=\"message-list-item-content\">${renderListItemContentAsHtml(item)}</div></li>`)\n .join('')\n return `<ul class=\"message-list message-list-unordered\">${items}</ul>`\n }\n if (block.kind === 'taskList') {\n const items = block.items\n .map((item) => (\n `<li class=\"message-task-item\">` +\n `<span class=\"message-task-checkbox\" data-checked=\"${item.checked ? 'true' : 'false'}\">${item.checked ? '☑' : '☐'}</span>` +\n `<div class=\"message-list-item-text\">${renderInlineSegmentsAsHtml(item.text)}</div>` +\n `</li>`\n ))\n .join('')\n return `<ul class=\"message-list message-task-list\">${items}</ul>`\n }\n if (block.kind === 'orderedList') {\n const items = block.items\n .map((item) => `<li class=\"message-list-item\"><div class=\"message-list-item-content\">${renderListItemContentAsHtml(item)}</div></li>`)\n .join('')\n return `<ol class=\"message-list message-list-ordered\" start=\"${block.start}\">${items}</ol>`\n }\n if (block.kind === 'table') {\n const headerCells = block.headers\n .map((cell, index) => `<th class=\"message-table-head-cell\"${tableCellAlignmentStyle(block.alignments[index] ?? null)}>${renderInlineSegmentsAsHtml(cell)}</th>`)\n .join('')\n const rows = block.rows\n .map((row) => (\n `<tr class=\"message-table-body-row\">` +\n row.map((cell, index) => `<td class=\"message-table-cell\"${tableCellAlignmentStyle(block.alignments[index] ?? null)}>${renderInlineSegmentsAsHtml(cell)}</td>`).join('') +\n `</tr>`\n ))\n .join('')\n const body = rows ? `<tbody>${rows}</tbody>` : ''\n return `<div class=\"message-table-wrap\"><table class=\"message-table\"><thead><tr>${headerCells}</tr></thead>${body}</table></div>`\n }\n if (block.kind === 'codeBlock') {\n const language = block.language\n ? `<div class=\"message-code-language\">${escapeHtml(block.language)}</div>`\n : ''\n return `<div class=\"message-code-block\">${language}<pre class=\"message-code-pre\"><code class=\"hljs\">${renderHighlightedCodeAsHtml(block.language, block.value)}</code></pre></div>`\n }\n if (block.kind === 'thematicBreak') {\n return '<hr class=\"message-divider\">'\n }\n return `<img class=\"message-image-preview message-markdown-image\" src=\"${escapeHtml(block.url)}\" alt=\"${escapeHtml(block.alt || 'Embedded message image')}\" loading=\"lazy\">`\n}\n\nfunction renderMarkdownBlocksAsHtml(text: string): string {\n return parseMessageBlocks(text)\n .map((block) => renderMessageBlockAsHtml(block))\n .join('')\n}\n\nfunction asRecord(value: unknown): Record<string, unknown> | null {\n return value !== null && typeof value === 'object' && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : null\n}\n\nfunction formatIsoTime(value: string): string {\n const date = new Date(value)\n if (Number.isNaN(date.getTime())) return value\n return date.toLocaleTimeString()\n}\n\nfunction readRequestReason(request: UiServerRequest): string {\n const params = asRecord(request.params)\n const reason = typeof params?.reason === 'string' ? params.reason.trim() : ''\n if (reason) return reason\n const message = typeof params?.message === 'string' ? params.message.trim() : ''\n if (message) return message\n return typeof params?.prompt === 'string' ? params.prompt.trim() : ''\n}\n\nfunction requestDisplayTitle(request: UiServerRequest): string {\n if (request.method === 'item/commandExecution/requestApproval') return 'Command approval required'\n if (request.method === 'item/fileChange/requestApproval') return 'File change approval required'\n if (request.method === 'item/permissions/requestApproval') return 'Permissions approval required'\n if (request.method === 'mcpServer/elicitation/request') return 'MCP server input required'\n if (request.method === 'item/tool/requestUserInput') return 'Input required'\n if (request.method === 'item/tool/call') return 'Tool call waiting for response'\n return request.method\n}\n\nfunction readMcpElicitationServerName(request: UiServerRequest): string {\n const params = asRecord(request.params)\n return typeof params?.serverName === 'string' ? params.serverName.trim() : ''\n}\n\nfunction readMcpElicitationUrl(request: UiServerRequest): string {\n const params = asRecord(request.params)\n return typeof params?.url === 'string' ? params.url.trim() : ''\n}\n\nfunction mcpElicitationAnswerKey(requestId: number, fieldKey: string): string {\n return `${String(requestId)}:${fieldKey}`\n}\n\nfunction readMcpElicitationFields(request: UiServerRequest): McpElicitationField[] {\n const params = asRecord(request.params)\n const requestedSchema = asRecord(params?.requestedSchema)\n const properties = asRecord(requestedSchema?.properties)\n if (!properties) return []\n\n const required = new Set(\n Array.isArray(requestedSchema?.required)\n ? requestedSchema.required.filter((entry): entry is string => typeof entry === 'string')\n : [],\n )\n\n return Object.entries(properties)\n .map(([key, value]) => parseMcpElicitationField(key, asRecord(value), required.has(key)))\n .filter((field): field is McpElicitationField => field !== null)\n}\n\nfunction parseMcpElicitationField(\n key: string,\n schema: Record<string, unknown> | null,\n required: boolean,\n): McpElicitationField | null {\n if (!schema) return null\n\n const label = typeof schema.title === 'string' && schema.title.trim().length > 0 ? schema.title.trim() : key\n const description = typeof schema.description === 'string' ? schema.description.trim() : ''\n const type = typeof schema.type === 'string' ? schema.type.trim() : ''\n\n if (type === 'boolean') {\n return { key, label, description, required, kind: 'boolean', inputType: 'checkbox', options: [], defaultValue: schema.default === true }\n }\n\n if (type === 'number' || type === 'integer') {\n return {\n key,\n label,\n description,\n required,\n kind: 'number',\n inputType: 'number',\n options: [],\n defaultValue: typeof schema.default === 'number' ? schema.default : '',\n }\n }\n\n const options = readMcpElicitationOptions(schema)\n if (type === 'array') {\n return {\n key,\n label,\n description,\n required,\n kind: 'multiEnum',\n inputType: 'checkbox',\n options,\n defaultValue: Array.isArray(schema.default)\n ? schema.default.filter((entry): entry is string => typeof entry === 'string')\n : [],\n }\n }\n\n if (options.length > 0) {\n return {\n key,\n label,\n description,\n required,\n kind: 'singleEnum',\n inputType: 'select',\n options,\n defaultValue: (typeof schema.default === 'string' ? schema.default : '') || options[0]?.value || '',\n }\n }\n\n return {\n key,\n label,\n description,\n required,\n kind: 'string',\n inputType: readMcpElicitationInputType(schema),\n options: [],\n defaultValue: typeof schema.default === 'string' ? schema.default : '',\n }\n}\n\nfunction readMcpElicitationOptions(schema: Record<string, unknown>): McpElicitationFieldOption[] {\n const titledSource = Array.isArray(schema.oneOf) ? schema.oneOf : Array.isArray(schema.anyOf) ? schema.anyOf : []\n const titledOptions = titledSource\n .map((option) => asRecord(option))\n .map((option) => ({\n value: typeof option?.const === 'string' ? option.const : '',\n label: typeof option?.title === 'string' && option.title.trim().length > 0 ? option.title : (typeof option?.const === 'string' ? option.const : ''),\n }))\n .filter((option) => option.value.length > 0)\n if (titledOptions.length > 0) return titledOptions\n\n const items = asRecord(schema.items)\n if (items) {\n const nestedOptions = readMcpElicitationOptions(items)\n if (nestedOptions.length > 0) return nestedOptions\n }\n\n const values = Array.isArray(schema.enum) ? schema.enum.filter((entry): entry is string => typeof entry === 'string') : []\n const names = Array.isArray(schema.enumNames) ? schema.enumNames.filter((entry): entry is string => typeof entry === 'string') : []\n return values.map((value, index) => ({ value, label: names[index] || value }))\n}\n\nfunction readMcpElicitationInputType(schema: Record<string, unknown>): string {\n const format = typeof schema.format === 'string' ? schema.format.trim() : ''\n if (format === 'email') return 'email'\n if (format === 'uri') return 'url'\n if (format === 'date') return 'date'\n if (format === 'date-time') return 'datetime-local'\n return 'text'\n}\n\nfunction readMcpElicitationFieldValue(requestId: number, field: McpElicitationField): string | number | boolean | string[] {\n const saved = mcpElicitationAnswers.value[mcpElicitationAnswerKey(requestId, field.key)]\n return saved === undefined ? field.defaultValue : saved\n}\n\nfunction readMcpElicitationMultiValue(requestId: number, field: McpElicitationField): string[] {\n const value = readMcpElicitationFieldValue(requestId, field)\n return Array.isArray(value) ? value.filter((entry): entry is string => typeof entry === 'string') : []\n}\n\nfunction toolQuestionKey(requestId: number, questionId: string): string {\n return `${String(requestId)}:${questionId}`\n}\n\nfunction readToolQuestions(request: UiServerRequest): ParsedToolQuestion[] {\n const params = asRecord(request.params)\n const questions = Array.isArray(params?.questions) ? params.questions : []\n const parsed: ParsedToolQuestion[] = []\n\n for (const row of questions) {\n const question = asRecord(row)\n if (!question) continue\n const id = typeof question.id === 'string' ? question.id : ''\n if (!id) continue\n\n const options = Array.isArray(question.options)\n ? question.options\n .map((option) => asRecord(option))\n .map((option) => ({\n label: typeof option?.label === 'string' ? option.label : '',\n description: typeof option?.description === 'string' ? option.description : '',\n }))\n .filter((option) => option.label.length > 0)\n : []\n\n parsed.push({\n id,\n header: typeof question.header === 'string' ? question.header : '',\n question: typeof question.question === 'string' ? question.question : '',\n isSecret: question.isSecret === true,\n isOther: question.isOther === true,\n options,\n })\n }\n\n return parsed\n}\n\nfunction readQuestionAnswer(requestId: number, questionId: string, fallback: string): string {\n const key = toolQuestionKey(requestId, questionId)\n const saved = toolQuestionAnswers.value[key]\n if (typeof saved === 'string' && saved.length > 0) return saved\n return fallback\n}\n\nfunction onQuestionAnswerInput(requestId: number, questionId: string, event: Event): void {\n const target = event.target\n if (!(target instanceof HTMLInputElement)) return\n const key = toolQuestionKey(requestId, questionId)\n toolQuestionAnswers.value = {\n ...toolQuestionAnswers.value,\n [key]: target.value,\n }\n}\n\nfunction readQuestionOptionDescription(requestId: number, question: ParsedToolQuestion): string {\n const selected = readQuestionAnswer(requestId, question.id, question.options[0]?.label || '')\n const match = question.options.find((option) => option.label === selected)\n return match?.description ?? ''\n}\n\nfunction readQuestionOtherAnswer(requestId: number, questionId: string): string {\n const key = toolQuestionKey(requestId, questionId)\n return toolQuestionOtherAnswers.value[key] ?? ''\n}\n\nfunction onQuestionAnswerChange(requestId: number, questionId: string, event: Event): void {\n const target = event.target\n if (!(target instanceof HTMLSelectElement)) return\n const key = toolQuestionKey(requestId, questionId)\n toolQuestionAnswers.value = {\n ...toolQuestionAnswers.value,\n [key]: target.value,\n }\n}\n\nfunction onQuestionOtherAnswerInput(requestId: number, questionId: string, event: Event): void {\n const target = event.target\n if (!(target instanceof HTMLInputElement)) return\n const key = toolQuestionKey(requestId, questionId)\n toolQuestionOtherAnswers.value = {\n ...toolQuestionOtherAnswers.value,\n [key]: target.value,\n }\n}\n\nfunction onMcpElicitationFieldInput(requestId: number, field: McpElicitationField, event: Event): void {\n const target = event.target\n if (!(target instanceof HTMLInputElement) && !(target instanceof HTMLSelectElement)) return\n mcpElicitationAnswers.value = {\n ...mcpElicitationAnswers.value,\n [mcpElicitationAnswerKey(requestId, field.key)]: target.value,\n }\n}\n\nfunction onMcpElicitationBooleanToggle(requestId: number, field: McpElicitationField, event: Event): void {\n const target = event.target\n if (!(target instanceof HTMLInputElement)) return\n mcpElicitationAnswers.value = {\n ...mcpElicitationAnswers.value,\n [mcpElicitationAnswerKey(requestId, field.key)]: target.checked,\n }\n}\n\nfunction onMcpElicitationMultiToggle(\n requestId: number,\n field: McpElicitationField,\n optionValue: string,\n event: Event,\n): void {\n const target = event.target\n if (!(target instanceof HTMLInputElement)) return\n const next = new Set(readMcpElicitationMultiValue(requestId, field))\n if (target.checked) next.add(optionValue)\n else next.delete(optionValue)\n mcpElicitationAnswers.value = {\n ...mcpElicitationAnswers.value,\n [mcpElicitationAnswerKey(requestId, field.key)]: Array.from(next),\n }\n}\n\nfunction onRespondApproval(requestId: number, decision: 'accept' | 'acceptForSession' | 'decline' | 'cancel'): void {\n emit('respondServerRequest', {\n id: requestId,\n result: { decision },\n })\n}\n\nfunction onRespondPermissionsApproval(request: UiServerRequest, scope: 'turn' | 'session'): void {\n const params = asRecord(request.params)\n const permissions = asRecord(params?.permissions) ?? {}\n emit('respondServerRequest', {\n id: request.id,\n result: {\n permissions,\n scope,\n },\n })\n}\n\nfunction buildMcpElicitationContent(request: UiServerRequest): Record<string, unknown> {\n const content: Record<string, unknown> = {}\n for (const field of readMcpElicitationFields(request)) {\n const value = readMcpElicitationFieldValue(request.id, field)\n if (field.kind === 'multiEnum') {\n const arrayValue = Array.isArray(value) ? value : []\n if (arrayValue.length > 0 || field.required) content[field.key] = arrayValue\n continue\n }\n if (field.kind === 'boolean') {\n content[field.key] = Boolean(value)\n continue\n }\n if (field.kind === 'number') {\n const numberValue = typeof value === 'number' ? value : Number(String(value).trim())\n if (!Number.isNaN(numberValue)) content[field.key] = numberValue\n continue\n }\n const textValue = String(value ?? '').trim()\n if (textValue.length > 0 || field.required) content[field.key] = textValue\n }\n return content\n}\n\nfunction onRespondMcpElicitation(request: UiServerRequest, action: 'accept' | 'decline' | 'cancel'): void {\n const params = asRecord(request.params)\n const result: Record<string, unknown> = { action }\n if (action === 'accept' && typeof params?.mode === 'string' && params.mode === 'form') {\n result.content = buildMcpElicitationContent(request)\n }\n emit('respondServerRequest', {\n id: request.id,\n result,\n })\n}\n\nfunction onRespondToolRequestUserInput(request: UiServerRequest): void {\n const questions = readToolQuestions(request)\n const answers: Record<string, { answers: string[] }> = {}\n\n for (const question of questions) {\n const selected = readQuestionAnswer(request.id, question.id, question.options[0]?.label || '')\n const other = readQuestionOtherAnswer(request.id, question.id).trim()\n const values = [selected, other].map((value) => value.trim()).filter((value) => value.length > 0)\n answers[question.id] = { answers: values }\n }\n\n emit('respondServerRequest', {\n id: request.id,\n result: { answers },\n })\n}\n\nfunction onRespondToolCallFailure(requestId: number): void {\n emit('respondServerRequest', {\n id: requestId,\n result: {\n success: false,\n contentItems: [\n {\n type: 'inputText',\n text: 'Tool call rejected from codex-web-local UI.',\n },\n ],\n },\n })\n}\n\nfunction onRespondToolCallSuccess(requestId: number): void {\n emit('respondServerRequest', {\n id: requestId,\n result: {\n success: true,\n contentItems: [],\n },\n })\n}\n\nfunction onRespondEmptyResult(requestId: number): void {\n emit('respondServerRequest', {\n id: requestId,\n result: {},\n })\n}\n\nfunction onRejectUnknownRequest(requestId: number): void {\n emit('respondServerRequest', {\n id: requestId,\n error: {\n code: -32000,\n message: 'Rejected from codex-web-local UI.',\n },\n })\n}\n\nfunction scrollToBottom(): void {\n const container = conversationListRef.value\n const anchor = bottomAnchorRef.value\n if (!container || !anchor) return\n container.scrollTop = container.scrollHeight\n anchor.scrollIntoView({ block: 'end' })\n}\n\nfunction isAtBottom(container: HTMLElement): boolean {\n const distance = container.scrollHeight - (container.scrollTop + container.clientHeight)\n return distance <= BOTTOM_THRESHOLD_PX\n}\n\nfunction emitScrollState(container: HTMLElement): void {\n if (!props.activeThreadId) return\n const maxScrollTop = Math.max(container.scrollHeight - container.clientHeight, 0)\n const scrollRatio = maxScrollTop > 0 ? Math.min(Math.max(container.scrollTop / maxScrollTop, 0), 1) : 1\n emit('updateScrollState', {\n threadId: props.activeThreadId,\n state: {\n scrollTop: container.scrollTop,\n isAtBottom: isAtBottom(container),\n scrollRatio,\n },\n })\n}\n\nfunction applySavedScrollState(): void {\n const container = conversationListRef.value\n if (!container) return\n\n if (autoFollowOutput.value) {\n enforceBottomState()\n return\n }\n\n const savedState = props.scrollState\n if (!savedState || savedState.isAtBottom) {\n emitScrollState(container)\n return\n }\n\n const maxScrollTop = Math.max(container.scrollHeight - container.clientHeight, 0)\n const targetScrollTop = savedState.scrollTop\n container.scrollTop = Math.min(Math.max(targetScrollTop, 0), maxScrollTop)\n emitScrollState(container)\n}\n\nfunction enforceBottomState(): void {\n const container = conversationListRef.value\n if (!container) return\n scrollToBottom()\n emitScrollState(container)\n}\n\nfunction shouldLockToBottom(): boolean {\n return autoFollowOutput.value\n}\n\nfunction runBottomLockFrame(): void {\n if (!shouldLockToBottom()) {\n bottomLockFramesLeft = 0\n bottomLockFrame = 0\n return\n }\n\n enforceBottomState()\n bottomLockFramesLeft -= 1\n if (bottomLockFramesLeft <= 0) {\n bottomLockFrame = 0\n return\n }\n bottomLockFrame = requestAnimationFrame(runBottomLockFrame)\n}\n\nfunction scheduleBottomLock(frames = 6): void {\n if (!shouldLockToBottom()) return\n if (bottomLockFrame) {\n cancelAnimationFrame(bottomLockFrame)\n bottomLockFrame = 0\n }\n bottomLockFramesLeft = Math.max(frames, 1)\n bottomLockFrame = requestAnimationFrame(runBottomLockFrame)\n}\n\nfunction onPendingImageSettled(): void {\n scheduleBottomLock(3)\n}\n\nfunction jumpToLatest(): void {\n autoFollowOutput.value = true\n enforceBottomState()\n scheduleBottomLock(4)\n}\n\nasync function loadMoreAbove(): Promise<void> {\n const container = conversationListRef.value\n if (!container || !hasMoreAbove.value || isLoadingMore.value) return\n\n isLoadingMore.value = true\n const threadIdAtStart = props.activeThreadId\n\n const prevScrollHeight = container.scrollHeight\n const prevScrollTop = container.scrollTop\n\n renderWindowStart.value = Math.max(0, renderWindowStart.value - LOAD_MORE_CHUNK)\n\n await nextTick()\n\n // Discard scroll restoration if the thread changed while we were awaiting.\n if (props.activeThreadId === threadIdAtStart) {\n container.scrollTop = prevScrollTop + (container.scrollHeight - prevScrollHeight)\n isLoadingMore.value = false\n }\n}\n\ndefineExpose({\n jumpToLatest,\n})\n\nfunction bindPendingImageHandlers(): void {\n if (!shouldLockToBottom()) return\n const container = conversationListRef.value\n if (!container) return\n\n const images = container.querySelectorAll<HTMLImageElement>('img.message-image-preview')\n for (const image of images) {\n if (image.complete || trackedPendingImages.has(image)) continue\n trackedPendingImages.add(image)\n image.addEventListener('load', onPendingImageSettled, { once: true })\n image.addEventListener('error', onPendingImageSettled, { once: true })\n }\n}\n\nasync function scheduleScrollRestore(): Promise<void> {\n await nextTick()\n if (scrollRestoreFrame) {\n cancelAnimationFrame(scrollRestoreFrame)\n }\n scrollRestoreFrame = requestAnimationFrame(() => {\n scrollRestoreFrame = 0\n applySavedScrollState()\n bindPendingImageHandlers()\n scheduleBottomLock()\n })\n}\n\nwatch(\n () => props.messages,\n async (next) => {\n if (props.isLoading) return\n\n const commandIds = new Set(\n next\n .filter((message) => message.messageType === 'commandExecution' && message.commandExecution)\n .map((message) => message.id),\n )\n expandedCommandIds.value = pruneCommandIdSet(expandedCommandIds.value, commandIds)\n collapsedAutoCommandIds.value = pruneCommandIdSet(collapsedAutoCommandIds.value, commandIds)\n expandedCommandGroupIds.value = pruneCommandIdSet(\n expandedCommandGroupIds.value,\n new Set(Object.keys(groupedCommandsByLatestId.value)),\n )\n expandedFileChangeSummaryIds.value = pruneCommandIdSet(\n expandedFileChangeSummaryIds.value,\n new Set([\n ...Object.keys(anchoredFileChangeSummaryByAnchorId.value),\n ...Object.keys(standaloneFileChangeSummaryByMessageId.value),\n ]),\n )\n\n // Keep renderWindowStart in bounds whenever the message list changes length.\n // Following output: always pin the window to the last RENDER_WINDOW_SIZE messages so\n // the rendered count stays bounded (handles both growth and shrink/rollback).\n // Scrolled up: only clamp downward so renderWindowStart never exceeds the list length\n // (prevents visibleMessages from becoming empty after a rollback).\n if (autoFollowOutput.value) {\n renderWindowStart.value = Math.max(0, next.length - RENDER_WINDOW_SIZE)\n } else {\n renderWindowStart.value = Math.min(renderWindowStart.value, Math.max(0, next.length - 1))\n }\n\n await scheduleScrollRestore()\n },\n)\n\nwatch(\n () => props.messages.some((message) => message.text.includes('```')),\n (hasCodeBlocks) => {\n if (!hasCodeBlocks || highlightJsModule.value) return\n void ensureHighlightJsLoaded()\n },\n { immediate: true },\n)\n\nwatch(\n activeCommandMessageId,\n (nextId, prevId) => {\n if (!prevId || prevId === nextId) return\n if (!collapsedAutoCommandIds.value.has(prevId)) return\n const nextCollapsedAuto = new Set(collapsedAutoCommandIds.value)\n nextCollapsedAuto.delete(prevId)\n collapsedAutoCommandIds.value = nextCollapsedAuto\n },\n)\n\nwatch(\n () => props.pendingRequests,\n async () => {\n if (props.isLoading) return\n await scheduleScrollRestore()\n },\n { deep: true },\n)\n\nwatch(\n () => props.liveOverlay,\n async (overlay) => {\n if (!overlay) return\n if (!autoFollowOutput.value) return\n await nextTick()\n enforceBottomState()\n scheduleBottomLock(8)\n },\n { deep: true },\n)\n\nwatch(\n () => props.isLoading,\n async (loading) => {\n if (loading) return\n renderWindowStart.value = Math.max(0, props.messages.length - RENDER_WINDOW_SIZE)\n await scheduleScrollRestore()\n },\n)\n\nwatch(\n () => props.activeThreadId,\n () => {\n localScrollState.value = null\n autoFollowOutput.value = true\n modalImageUrl.value = ''\n isLoadingMore.value = false\n // Apply immediately for cached threads where isLoading never toggles.\n renderWindowStart.value = Math.max(0, props.messages.length - RENDER_WINDOW_SIZE)\n },\n { flush: 'post' },\n)\n\nfunction onConversationScroll(): void {\n const container = conversationListRef.value\n if (!container || props.isLoading) return\n autoFollowOutput.value = isAtBottom(container)\n emitScrollState(container)\n if (hasMoreAbove.value && !isLoadingMore.value && container.scrollTop < LOAD_MORE_SCROLL_THRESHOLD_PX) {\n void loadMoreAbove()\n }\n}\n\nconst failedMarkdownImages = ref(new Set<string>())\n\nfunction markdownImageKey(messageId: string, blockIndex: number): string {\n return `${messageId}:${blockIndex}`\n}\n\nfunction isMarkdownImageFailed(messageId: string, blockIndex: number): boolean {\n return failedMarkdownImages.value.has(markdownImageKey(messageId, blockIndex))\n}\n\nfunction onMarkdownImageError(messageId: string, blockIndex: number): void {\n failedMarkdownImages.value.add(markdownImageKey(messageId, blockIndex))\n}\n\nfunction openImageModal(imageUrl: string): void {\n modalImageUrl.value = imageUrl\n}\n\nfunction closeImageModal(): void {\n modalImageUrl.value = ''\n}\n\nonMounted(() => {\n window.addEventListener('pointerdown', onWindowPointerDownForFileLinkContextMenu)\n window.addEventListener('blur', onWindowBlurForFileLinkContextMenu)\n window.addEventListener('keydown', onWindowKeydownForFileLinkContextMenu)\n})\n\nonBeforeUnmount(() => {\n if (scrollRestoreFrame) {\n cancelAnimationFrame(scrollRestoreFrame)\n }\n if (bottomLockFrame) {\n cancelAnimationFrame(bottomLockFrame)\n }\n if (copiedMessageResetTimer) {\n clearTimeout(copiedMessageResetTimer)\n }\n window.removeEventListener('pointerdown', onWindowPointerDownForFileLinkContextMenu)\n window.removeEventListener('blur', onWindowBlurForFileLinkContextMenu)\n window.removeEventListener('keydown', onWindowKeydownForFileLinkContextMenu)\n})\n</script>\n\n<style scoped>\n@reference \"tailwindcss\";\n\n.conversation-root {\n @apply relative h-full min-h-0 min-w-0 p-0 flex flex-col overflow-y-hidden overflow-x-hidden bg-transparent border-none rounded-none;\n}\n\n.conversation-loading {\n @apply m-0 px-6 text-sm text-slate-500;\n}\n\n.conversation-empty {\n @apply m-0 px-6 text-sm text-slate-500;\n}\n\n.conversation-list {\n @apply h-full min-h-0 list-none m-0 px-2 sm:px-6 py-0 overflow-y-auto overflow-x-visible flex flex-col gap-2 sm:gap-3;\n}\n\n.conversation-load-more {\n @apply flex justify-center py-3 m-0;\n}\n\n.load-more-button {\n @apply px-4 py-1.5 text-xs rounded-full border border-slate-300 dark:border-slate-600\n text-slate-500 dark:text-slate-400 bg-transparent\n hover:bg-slate-100 dark:hover:bg-slate-800\n disabled:opacity-40 disabled:cursor-not-allowed\n transition-colors cursor-pointer;\n}\n\n.conversation-item {\n @apply m-0 w-full min-w-0 flex;\n}\n\n.conversation-item-request {\n @apply justify-center;\n}\n\n.conversation-item-overlay {\n @apply justify-center;\n}\n\n.message-row {\n @apply relative w-full min-w-0 max-w-[min(var(--chat-column-max,45rem),100%)] mx-auto flex;\n}\n\n.message-row[data-role='user'] {\n @apply justify-end;\n}\n\n.message-row[data-role='assistant'],\n.message-row[data-role='system'] {\n @apply justify-start;\n}\n\n.conversation-bottom-anchor {\n @apply h-px;\n}\n\n.jump-to-latest-button {\n @apply absolute left-1/2 bottom-4 z-20 inline-flex h-11 w-11 -translate-x-1/2 items-center justify-center rounded-full border border-slate-300 bg-white/96 text-slate-700 shadow-lg shadow-slate-900/10 transition hover:-translate-x-1/2 hover:-translate-y-0.5 hover:bg-white hover:text-slate-900;\n}\n\n.jump-to-latest-icon {\n transform: rotate(180deg);\n}\n\n.message-stack {\n @apply flex flex-col w-full min-w-0;\n}\n\n.request-card {\n @apply w-full max-w-[min(var(--chat-column-max,45rem),100%)] rounded-xl border border-amber-300 bg-amber-50 px-4 py-3 flex flex-col gap-2;\n}\n\n.request-title {\n @apply m-0 text-sm leading-5 font-semibold text-amber-900;\n}\n\n.request-meta {\n @apply m-0 text-xs leading-4 text-amber-700;\n}\n\n.request-reason {\n @apply m-0 text-sm leading-5 text-amber-900 whitespace-pre-wrap break-words;\n overflow-wrap: anywhere;\n}\n\n.request-actions {\n @apply flex flex-wrap gap-2;\n}\n\n.request-button {\n @apply rounded-md border border-amber-300 bg-white px-3 py-1.5 text-xs text-amber-900 hover:bg-amber-100 transition;\n}\n\n.request-button-primary {\n @apply border-amber-500 bg-amber-500 text-white hover:bg-amber-600;\n}\n\n.request-user-input {\n @apply flex flex-col gap-3;\n}\n\n.request-question {\n @apply flex flex-col gap-1;\n}\n\n.request-question-title {\n @apply m-0 text-sm leading-5 font-medium text-amber-900;\n}\n\n.request-question-text {\n @apply m-0 text-xs leading-4 text-amber-800;\n}\n\n.request-question-option-description {\n @apply m-0 text-xs leading-4 text-amber-700;\n}\n\n.request-link {\n @apply inline-flex w-fit rounded-md border border-amber-300 bg-white px-3 py-1.5 text-xs text-amber-900 hover:bg-amber-100 transition;\n}\n\n.request-select {\n @apply h-8 rounded-md border border-amber-300 bg-white px-2 text-sm text-amber-900;\n}\n\n.request-input {\n @apply h-8 rounded-md border border-amber-300 bg-white px-2 text-sm text-amber-900 placeholder:text-amber-500;\n}\n\n.request-checkbox-list {\n @apply flex flex-col gap-1.5;\n}\n\n.request-checkbox-row {\n @apply flex items-center gap-2 text-sm text-amber-900;\n}\n\n.live-overlay-inline {\n @apply w-full max-w-[min(var(--chat-column-max,45rem),100%)] px-0 py-1 flex flex-col gap-1;\n}\n\n.live-overlay-label {\n @apply m-0 text-sm leading-5 font-medium text-zinc-600;\n}\n\n.live-overlay-reasoning {\n @apply m-0 text-sm leading-5 text-zinc-500 whitespace-pre-wrap break-words;\n display: block;\n max-height: calc(1.25rem * 5);\n overflow: auto;\n overflow-wrap: anywhere;\n scrollbar-width: none;\n mask-image: linear-gradient(to top, black 75%, transparent 100%);\n -webkit-mask-image: linear-gradient(to top, black 75%, transparent 100%);\n}\n\n.live-overlay-reasoning::-webkit-scrollbar {\n display: none;\n}\n\n.live-overlay-error {\n @apply m-0 text-sm leading-5 text-rose-600 whitespace-pre-wrap;\n}\n\n.message-body {\n @apply flex flex-col min-w-0 max-w-full;\n width: fit-content;\n}\n\n.message-body[data-role='user'] {\n @apply ml-auto items-end;\n align-self: flex-end;\n}\n\n.message-toolbar {\n @apply mt-1 self-start flex items-center gap-1 opacity-[0.01] transition-opacity duration-200;\n}\n\n.message-row:hover .message-toolbar {\n @apply opacity-100;\n}\n\n.message-copy-button {\n @apply inline-flex items-center gap-0.5 rounded-full border border-slate-200 bg-white/90 px-1.25 py-0.5 text-[9px] font-medium leading-none text-slate-500 transition hover:border-slate-300 hover:bg-white hover:text-slate-900;\n}\n\n.message-fork-button {\n @apply inline-flex items-center gap-0.5 px-0.5 py-0 text-[9px] font-medium leading-none text-slate-500 transition hover:text-slate-900;\n}\n\n\n.message-copy-button[data-copied='true'] {\n @apply border-emerald-200 bg-emerald-50 text-emerald-700;\n}\n\n.message-rollback-button {\n @apply inline-flex items-center gap-0.5 px-0.5 py-0 text-[9px] font-medium leading-none text-amber-600/70 transition hover:text-amber-700;\n}\n\n.message-fork-icon,\n.message-copy-icon,\n.message-rollback-icon {\n @apply text-[10px];\n}\n\n.message-fork-label,\n.message-copy-label,\n.message-rollback-label {\n @apply leading-none;\n}\n\n.message-image-list {\n @apply list-none m-0 mb-2 p-0 flex flex-wrap gap-2;\n}\n\n.message-image-list[data-role='user'] {\n @apply ml-auto justify-end;\n}\n\n.message-image-item {\n @apply m-0;\n}\n\n.message-image-button {\n @apply block rounded-xl overflow-hidden border border-slate-300 bg-white p-0 transition hover:border-slate-400;\n}\n\n.message-image-preview {\n @apply block w-16 h-16 object-cover;\n}\n\n.message-file-attachments {\n @apply mb-2 flex flex-wrap gap-1.5;\n}\n\n.message-file-chip {\n @apply inline-flex items-center gap-1 rounded-md border border-zinc-200 bg-zinc-50 px-2 py-0.5 text-xs text-zinc-700;\n}\n\n.message-file-chip-icon {\n @apply text-[10px] leading-none;\n}\n\n.message-file-chip-name {\n @apply truncate max-w-48 font-mono;\n}\n\n.message-card {\n @apply max-w-[min(var(--chat-card-max,76ch),100%)] px-0 py-0 bg-transparent border-none rounded-none;\n}\n\n.message-text-flow {\n @apply flex flex-col gap-2;\n}\n\n.plan-card {\n @apply flex max-w-[min(var(--chat-card-max,76ch),100%)] flex-col gap-3 rounded-2xl border border-sky-200 bg-sky-50 px-4 py-3 text-slate-900;\n}\n\n.plan-card-header {\n @apply flex items-center justify-between gap-3;\n}\n\n.plan-card-title {\n @apply m-0 text-sm font-semibold leading-5 text-sky-900;\n}\n\n.plan-card-badge {\n @apply inline-flex items-center rounded-full bg-sky-200 px-2 py-0.5 text-[11px] font-medium leading-4 text-sky-900;\n}\n\n.plan-card-explanation {\n @apply text-slate-700;\n}\n\n.plan-card-markdown {\n @apply flex flex-col gap-2;\n}\n\n.plan-card-markdown :deep(.message-text),\n.plan-card-markdown :deep(.message-heading),\n.plan-card-markdown :deep(.message-blockquote),\n.plan-card-markdown :deep(.message-list),\n.plan-card-markdown :deep(.message-table-wrap),\n.plan-card-markdown :deep(.message-code-block),\n.plan-card-markdown :deep(.message-divider) {\n @apply m-0;\n}\n\n.plan-card-markdown :deep(.message-text) {\n @apply text-sm leading-relaxed whitespace-pre-wrap text-slate-800;\n}\n\n.plan-card-markdown :deep(.message-heading) {\n @apply text-slate-900 tracking-tight;\n}\n\n.plan-card-markdown :deep(.message-heading-h1) {\n @apply text-2xl font-semibold leading-tight;\n}\n\n.plan-card-markdown :deep(.message-heading-h2) {\n @apply text-xl font-semibold leading-tight;\n}\n\n.plan-card-markdown :deep(.message-heading-h3) {\n @apply text-lg font-semibold leading-snug;\n}\n\n.plan-card-markdown :deep(.message-heading-h4) {\n @apply text-base font-semibold leading-snug;\n}\n\n.plan-card-markdown :deep(.message-heading-h5) {\n @apply text-sm font-semibold leading-snug uppercase tracking-[0.02em];\n}\n\n.plan-card-markdown :deep(.message-heading-h6) {\n @apply text-xs font-semibold leading-snug uppercase tracking-[0.04em] text-slate-600;\n}\n\n.plan-card-markdown :deep(.message-blockquote) {\n @apply border-l-4 border-slate-300 pl-4 py-1 text-sm leading-relaxed whitespace-pre-wrap text-slate-700 bg-slate-50/70 rounded-r-lg;\n}\n\n.plan-card-markdown :deep(.message-list) {\n @apply pl-5 text-sm leading-relaxed text-slate-800 flex flex-col gap-1.5;\n}\n\n.plan-card-markdown :deep(.message-list-unordered) {\n @apply list-disc;\n}\n\n.plan-card-markdown :deep(.message-list-ordered) {\n @apply list-decimal;\n}\n\n.plan-card-markdown :deep(.message-list-item) {\n @apply pl-1;\n}\n\n.plan-card-markdown :deep(.message-list-item-text) {\n @apply whitespace-pre-wrap;\n}\n\n.plan-card-markdown :deep(.message-list-item-paragraph + .message-list-item-paragraph) {\n @apply mt-2;\n}\n\n.plan-card-markdown :deep(.message-task-list) {\n @apply list-none pl-0;\n}\n\n.plan-card-markdown :deep(.message-task-item) {\n @apply flex items-start gap-2;\n}\n\n.plan-card-markdown :deep(.message-task-checkbox) {\n @apply mt-0.5 text-sm leading-none text-slate-500 select-none;\n}\n\n.plan-card-markdown :deep(.message-code-block) {\n @apply overflow-hidden rounded-xl border border-slate-200 bg-slate-950/95 text-slate-100;\n}\n\n.plan-card-markdown :deep(.message-code-language) {\n @apply border-b border-slate-800 bg-slate-900/90 px-3 py-2 text-[11px] font-medium uppercase tracking-[0.08em] text-slate-400;\n}\n\n.plan-card-markdown :deep(.message-code-pre) {\n @apply m-0 overflow-x-auto px-3 py-3 text-[13px] leading-6;\n}\n\n.plan-card-markdown :deep(.message-inline-code) {\n @apply rounded-md bg-slate-200/80 px-1.5 py-0.5 font-mono text-[0.9em] text-slate-900;\n}\n\n.plan-card-markdown :deep(.message-file-link) {\n @apply text-sky-700 underline decoration-sky-300 underline-offset-2;\n}\n\n.plan-card-markdown :deep(.message-table) {\n @apply bg-white/90;\n}\n\n.plan-step-list {\n @apply m-0 flex list-none flex-col gap-2 p-0;\n}\n\n.plan-step-item {\n @apply flex items-start gap-2 rounded-xl border border-white/70 bg-white/80 px-3 py-2 text-sm leading-relaxed text-slate-800;\n}\n\n.plan-step-item[data-status='completed'] {\n @apply border-emerald-200 bg-emerald-50/80;\n}\n\n.plan-step-item[data-status='inProgress'] {\n @apply border-amber-200 bg-amber-50/80;\n}\n\n.plan-step-status {\n @apply mt-0.5 inline-flex h-5 w-5 shrink-0 items-center justify-center rounded-full bg-slate-200 text-xs font-semibold text-slate-700;\n}\n\n.plan-step-status[data-status='completed'] {\n @apply bg-emerald-200 text-emerald-900;\n}\n\n.plan-step-status[data-status='inProgress'] {\n @apply bg-amber-200 text-amber-900;\n}\n\n.plan-step-text {\n @apply min-w-0 flex-1;\n}\n\n.message-text {\n @apply m-0 text-sm leading-relaxed whitespace-pre-wrap break-words text-slate-800;\n overflow-wrap: anywhere;\n}\n\n.message-heading {\n @apply m-0 text-slate-900 tracking-tight;\n}\n\n.message-heading-h1 {\n @apply text-2xl font-semibold leading-tight;\n}\n\n.message-heading-h2 {\n @apply text-xl font-semibold leading-tight;\n}\n\n.message-heading-h3 {\n @apply text-lg font-semibold leading-snug;\n}\n\n.message-heading-h4 {\n @apply text-base font-semibold leading-snug;\n}\n\n.message-heading-h5 {\n @apply text-sm font-semibold leading-snug uppercase tracking-[0.02em];\n}\n\n.message-heading-h6 {\n @apply text-xs font-semibold leading-snug uppercase tracking-[0.04em] text-slate-600;\n}\n\n.message-blockquote {\n @apply m-0 border-l-4 border-slate-300 pl-4 py-1 text-sm leading-relaxed whitespace-pre-wrap break-words text-slate-700 bg-slate-50/70 rounded-r-lg;\n overflow-wrap: anywhere;\n}\n\n.message-list {\n @apply m-0 pl-5 text-sm leading-relaxed text-slate-800 flex flex-col gap-1.5;\n}\n\n.message-list-unordered {\n @apply list-disc;\n}\n\n.message-list-ordered {\n @apply list-decimal;\n}\n\n.message-list-item {\n @apply pl-1;\n}\n\n.message-list-item-content {\n @apply flex flex-col gap-1.5;\n}\n\n.message-list-item-text {\n @apply whitespace-pre-wrap break-words;\n overflow-wrap: anywhere;\n}\n\n.message-list-item-paragraph + .message-list-item-paragraph {\n @apply mt-2;\n}\n\n.message-task-list {\n @apply list-none pl-0;\n}\n\n.message-task-item {\n @apply flex items-start gap-2;\n}\n\n.message-task-checkbox {\n @apply mt-0.5 text-sm leading-none text-slate-500 select-none;\n}\n\n.message-table-wrap {\n @apply w-full overflow-x-auto;\n}\n\n.message-table {\n @apply min-w-full border-separate border-spacing-0 overflow-hidden rounded-xl border border-slate-200 bg-white text-sm text-slate-800;\n}\n\n.message-table-head-cell,\n.message-table-cell {\n @apply border-b border-l border-slate-200 px-3 py-2 align-top whitespace-pre-wrap break-words;\n overflow-wrap: anywhere;\n}\n\n.message-table-head-cell:first-child,\n.message-table-cell:first-child {\n @apply border-l-0;\n}\n\n.message-table-head-cell {\n @apply bg-slate-100 font-semibold text-slate-900;\n}\n\n.message-table-body-row:last-child .message-table-cell {\n @apply border-b-0;\n}\n\n.message-bold-text {\n @apply font-semibold text-slate-900;\n}\n\n.message-italic-text {\n @apply italic;\n}\n\n.message-strikethrough-text {\n @apply line-through text-slate-500;\n}\n\n.message-markdown-image {\n @apply w-auto h-auto max-w-[min(560px,85vw)] max-h-[min(460px,62vh)] object-contain bg-white;\n}\n\n.message-inline-code {\n @apply rounded-md border border-slate-200 bg-slate-100/60 px-1.5 py-0.5 text-[0.875em] leading-[1.4] text-slate-900 font-mono;\n}\n\n.message-code-block {\n @apply overflow-hidden rounded-xl border border-slate-200 bg-slate-950 text-slate-100;\n}\n\n.message-code-language {\n @apply border-b border-slate-800 px-3 py-2 text-[11px] font-mono uppercase tracking-[0.08em] text-slate-400;\n}\n\n.message-code-pre {\n @apply m-0 overflow-x-auto px-3 py-3 text-[13px] leading-relaxed font-mono whitespace-pre;\n}\n\n.message-code-pre :deep(.hljs) {\n @apply block bg-transparent p-0 text-inherit;\n}\n\n.message-file-link {\n @apply text-sm leading-relaxed text-[#0969da] no-underline hover:text-[#1f6feb] hover:underline underline-offset-2;\n}\n\n.file-link-context-menu {\n @apply fixed z-50 min-w-36 rounded-lg border border-zinc-200 bg-white p-1 shadow-xl;\n}\n\n.file-link-context-menu-item {\n @apply block w-full rounded-md px-2 py-1.5 text-left text-xs text-zinc-700 hover:bg-zinc-100;\n}\n\n.message-divider {\n @apply m-0 border-0 h-px bg-slate-300/80;\n}\n\n.message-stack[data-role='user'] {\n @apply items-end;\n}\n\n.message-stack[data-role='assistant'],\n.message-stack[data-role='system'] {\n @apply items-start;\n}\n\n.message-card[data-role='user'] {\n @apply rounded-2xl bg-slate-200 px-4 py-3 max-w-[min(560px,100%)];\n width: fit-content;\n margin-left: auto;\n align-self: flex-end;\n}\n\n.message-card[data-role='assistant'],\n.message-card[data-role='system'] {\n @apply px-0 py-0 bg-transparent border-none rounded-none;\n}\n\n.conversation-item[data-message-type='worked'] .message-stack,\n.conversation-item[data-message-type='worked'] .message-body,\n.conversation-item[data-message-type='worked'] .message-card {\n @apply w-full max-w-full;\n}\n\n.worked-separator-wrap {\n @apply w-full flex flex-col gap-0;\n}\n\n.worked-separator {\n @apply w-full flex items-center gap-3 bg-transparent border-none cursor-pointer p-0;\n}\n\n.worked-chevron {\n @apply text-[9px] text-zinc-400 transition-transform duration-200 flex-shrink-0;\n}\n\n.worked-chevron-open {\n transform: rotate(90deg);\n}\n\n.worked-separator-line {\n @apply h-px bg-zinc-300/80 flex-1;\n}\n\n.worked-separator-text {\n @apply m-0 text-sm leading-relaxed font-normal text-slate-800;\n}\n\n.worked-details {\n @apply flex flex-col gap-1.5 pt-2;\n}\n\n.worked-cmd-item {\n @apply flex flex-col;\n}\n\n.image-modal-backdrop {\n @apply fixed inset-0 z-50 bg-black/40 p-6 flex items-center justify-center;\n}\n\n.image-modal-content {\n @apply relative max-w-[min(92vw,1100px)] max-h-[92vh];\n}\n\n.image-modal-close {\n @apply absolute top-2 right-2 z-10 w-10 h-10 rounded-full bg-white/90 text-slate-900 border border-slate-300 flex items-center justify-center;\n}\n\n.image-modal-image {\n @apply block max-w-full max-h-[90vh] rounded-2xl shadow-2xl bg-white;\n}\n\n.icon-svg {\n @apply w-5 h-5;\n}\n\n.cmd-row {\n @apply w-full flex items-center gap-2 px-3 py-1.5 rounded-lg border border-zinc-200 bg-zinc-50 cursor-pointer transition text-left hover:bg-zinc-100;\n}\n\n.cmd-row.cmd-row-group {\n @apply border-dashed border-zinc-300 bg-zinc-100/90 text-zinc-600;\n}\n\n.cmd-row.cmd-compact {\n gap: 0.375rem;\n padding: 0.375rem 0.625rem;\n border-radius: 0.625rem;\n}\n\n.cmd-row.cmd-compact .cmd-chevron {\n font-size: 9px;\n}\n\n.cmd-row.cmd-compact .cmd-label {\n font-size: 0.75rem;\n}\n\n.cmd-row.cmd-compact .cmd-status {\n max-width: 4.5rem;\n font-size: 0.75rem;\n}\n\n.cmd-row.cmd-expanded {\n @apply rounded-b-none;\n}\n\n.cmd-chevron {\n @apply text-[10px] text-zinc-400 transition-transform duration-150 flex-shrink-0;\n}\n\n.cmd-chevron-open {\n transform: rotate(90deg);\n}\n\n.cmd-label {\n @apply flex-1 min-w-0 truncate text-xs font-mono text-zinc-700;\n}\n\n.cmd-group-label {\n @apply flex-1 min-w-0 truncate text-xs font-medium text-zinc-600;\n}\n\n.cmd-status {\n @apply max-w-24 truncate text-right text-[11px] font-medium flex-shrink-0;\n}\n\n.cmd-status-running .cmd-status {\n @apply text-amber-600;\n}\n\n.cmd-status-ok .cmd-status {\n @apply text-emerald-600;\n}\n\n.cmd-status-error .cmd-status {\n @apply text-rose-600;\n}\n\n.cmd-output-wrap {\n @apply rounded-b-lg bg-zinc-900;\n display: grid;\n grid-template-rows: 0fr;\n transition: grid-template-rows 300ms ease-out, border-color 300ms ease-out;\n border: 1px solid transparent;\n border-top: none;\n}\n\n.cmd-output-wrap.cmd-output-visible {\n grid-template-rows: 1fr;\n border-color: #e4e4e7;\n}\n\n.cmd-group-wrap {\n display: grid;\n grid-template-rows: 0fr;\n transition: grid-template-rows 220ms ease-out;\n}\n\n.cmd-group-wrap.cmd-group-visible {\n grid-template-rows: 1fr;\n}\n\n.cmd-group-inner {\n @apply mb-1 flex min-h-0 flex-col gap-1 overflow-hidden pl-2;\n}\n\n.cmd-output-inner {\n overflow: hidden;\n min-height: 0;\n}\n\n.cmd-output {\n @apply m-0 px-3 py-2 text-xs font-mono text-zinc-200 whitespace-pre-wrap break-words max-h-60 overflow-y-auto;\n}\n\n.cmd-output.cmd-output-condensed {\n max-height: 9rem;\n}\n\n.file-change-summary-block {\n @apply mt-3 flex flex-col gap-0;\n}\n\n.file-change-summary-block-inline {\n @apply mt-4;\n}\n\n.file-change-summary-row {\n @apply border-dashed;\n}\n\n.file-change-summary-label {\n @apply flex-1 min-w-0 truncate text-xs font-medium text-zinc-700;\n}\n\n.file-change-summary-status {\n @apply inline-flex max-w-28 items-center justify-end gap-1.5 text-right text-[11px] font-semibold text-zinc-500 flex-shrink-0;\n}\n\n.file-change-panel-inner {\n @apply mb-1 min-h-0 overflow-hidden pl-2;\n}\n\n.file-change-list {\n @apply m-0 flex list-none flex-col gap-0.5 rounded-xl border border-zinc-200 bg-white/80 p-1.5;\n}\n\n.file-change-item {\n @apply flex flex-wrap items-center gap-1.5 rounded-lg px-2 py-1 text-sm text-zinc-700;\n}\n\n.file-change-badge {\n @apply inline-flex items-center rounded-full px-2.5 py-1 text-[11px] font-semibold uppercase tracking-[0.08em];\n}\n\n.file-change-badge[data-operation='add'] {\n @apply bg-emerald-50 text-emerald-700;\n}\n\n.file-change-badge[data-operation='update'] {\n @apply bg-sky-50 text-sky-700;\n}\n\n.file-change-badge[data-operation='delete'] {\n @apply bg-rose-50 text-rose-700;\n}\n\n.file-change-badge[data-operation='move'] {\n @apply bg-amber-50 text-amber-700;\n}\n\n.file-change-path {\n @apply min-w-0 break-all font-mono text-[13px];\n}\n\n.file-change-path-button {\n @apply min-w-0 border-0 bg-transparent p-0 text-left font-mono text-[13px] text-[#0969da] hover:text-[#1f6feb] hover:underline underline-offset-2;\n}\n\n.file-change-arrow {\n @apply text-zinc-400;\n}\n\n.file-change-delta {\n @apply ml-auto inline-flex items-center gap-1.5 rounded-full bg-zinc-100 px-2 py-1 text-[11px] font-semibold text-zinc-600;\n}\n\n.file-change-signed-count {\n @apply inline-flex items-center whitespace-nowrap;\n}\n\n.file-change-signed-count[data-tone='add'] {\n @apply text-emerald-600;\n}\n\n.file-change-signed-count[data-tone='remove'] {\n @apply text-rose-600;\n}\n\n.diff-viewer-backdrop {\n @apply fixed inset-0 z-50 bg-black/45 p-3 sm:p-6 flex items-center justify-center;\n}\n\n.diff-viewer-shell {\n @apply relative grid h-[min(88vh,920px)] w-[min(96vw,1320px)] grid-cols-1 overflow-hidden rounded-3xl border border-zinc-200 bg-white shadow-2xl lg:grid-cols-[320px_minmax(0,1fr)];\n}\n\n.diff-viewer-sidebar {\n @apply flex min-h-0 flex-col border-b border-zinc-200 bg-zinc-50 lg:border-b-0 lg:border-r;\n}\n\n.diff-viewer-sidebar-header {\n @apply flex items-center justify-between gap-3 border-b border-zinc-200 px-4 py-4;\n}\n\n.diff-viewer-sidebar-title {\n @apply m-0 text-sm font-semibold text-zinc-900;\n}\n\n.diff-viewer-sidebar-count {\n @apply m-0 text-xs font-medium text-zinc-500;\n}\n\n.diff-viewer-sidebar-list {\n @apply flex min-h-0 flex-col gap-2 overflow-y-auto p-3;\n}\n\n.diff-viewer-file-button {\n @apply flex w-full flex-col items-start gap-2 rounded-2xl border border-transparent bg-transparent px-3 py-3 text-left transition hover:border-zinc-200 hover:bg-white;\n}\n\n.diff-viewer-file-button[data-active='true'] {\n @apply border-sky-200 bg-white shadow-sm;\n}\n\n.diff-viewer-file-label {\n @apply break-all font-mono text-[13px] text-zinc-700;\n}\n\n.diff-viewer-file-delta {\n @apply inline-flex items-center rounded-full bg-zinc-100 px-2.5 py-1 text-[11px] font-medium text-zinc-600;\n}\n\n.diff-viewer-main {\n @apply flex min-h-0 flex-col bg-white;\n}\n\n.diff-viewer-toolbar {\n @apply flex items-start justify-between gap-4 border-b border-zinc-200 px-5 py-4;\n}\n\n.diff-viewer-toolbar-actions {\n @apply flex items-center gap-2 shrink-0;\n}\n\n.diff-viewer-title-wrap {\n @apply min-w-0;\n}\n\n.diff-viewer-title {\n @apply m-0 break-all text-base font-semibold text-zinc-900;\n}\n\n.diff-viewer-subtitle {\n @apply mt-1 mb-0 text-sm text-zinc-500;\n}\n\n.diff-viewer-close {\n @apply static shrink-0 border-zinc-200 bg-zinc-100 text-zinc-700;\n}\n\n.diff-viewer-mobile-files-button {\n @apply inline-flex items-center rounded-full border border-zinc-200 bg-zinc-100 px-3 py-1.5 text-xs font-medium text-zinc-700;\n}\n\n.diff-viewer-empty {\n @apply flex min-h-0 flex-1 flex-col items-center justify-center px-6 text-center;\n}\n\n.diff-viewer-empty-title {\n @apply m-0 text-base font-semibold text-zinc-900;\n}\n\n.diff-viewer-empty-text {\n @apply mt-2 max-w-2xl text-sm leading-relaxed text-zinc-500;\n}\n\n.diff-viewer-panel {\n @apply flex min-h-0 flex-1 flex-col;\n}\n\n.diff-viewer-meta {\n @apply border-b border-zinc-200 bg-zinc-50 px-5 py-2;\n}\n\n.diff-viewer-language {\n @apply inline-flex items-center rounded-full bg-zinc-200 px-2.5 py-1 text-[11px] font-semibold uppercase tracking-[0.08em] text-zinc-700;\n}\n\n.diff-viewer-lines {\n @apply min-h-0 flex-1 overflow-auto bg-zinc-950;\n}\n\n.diff-viewer-line {\n display: grid;\n grid-template-columns: 4rem 4rem 2rem minmax(0, 1fr);\n align-items: stretch;\n min-width: fit-content;\n}\n\n.diff-viewer-line-number {\n @apply border-r border-zinc-800 px-3 py-1.5 text-right font-mono text-xs text-zinc-500 select-none;\n}\n\n.diff-viewer-line-marker {\n @apply border-r border-zinc-800 px-2 py-1.5 text-center font-mono text-xs text-zinc-500 select-none;\n}\n\n.diff-viewer-line-code {\n @apply block whitespace-pre px-3 py-1.5 font-mono text-[12px] leading-5 text-zinc-100;\n}\n\n.diff-viewer-line[data-kind='meta'] {\n @apply bg-zinc-900;\n}\n\n.diff-viewer-line[data-kind='meta'] .diff-viewer-line-code,\n.diff-viewer-line[data-kind='meta'] .diff-viewer-line-marker {\n @apply text-sky-300;\n}\n\n.diff-viewer-line[data-kind='hunk'] {\n @apply bg-sky-950/40;\n}\n\n.diff-viewer-line[data-kind='hunk'] .diff-viewer-line-code,\n.diff-viewer-line[data-kind='hunk'] .diff-viewer-line-marker {\n @apply text-sky-300;\n}\n\n.diff-viewer-line[data-kind='add'] {\n background: rgba(20, 83, 45, 0.38);\n}\n\n.diff-viewer-line[data-kind='add'] .diff-viewer-line-marker,\n.diff-viewer-line[data-kind='add'] .diff-viewer-line-code {\n @apply text-emerald-200;\n}\n\n.diff-viewer-line[data-kind='remove'] {\n background: rgba(127, 29, 29, 0.32);\n}\n\n.diff-viewer-line[data-kind='remove'] .diff-viewer-line-marker,\n.diff-viewer-line[data-kind='remove'] .diff-viewer-line-code {\n @apply text-rose-200;\n}\n\n.diff-viewer-line[data-kind='context'] {\n @apply bg-zinc-950;\n}\n\n.diff-viewer-line[data-kind='context'] .diff-viewer-line-code {\n @apply text-zinc-100;\n}\n\n.diff-viewer-mobile-sheet-backdrop {\n @apply absolute inset-0 z-20 bg-black/35 flex items-end;\n}\n\n.diff-viewer-mobile-sheet {\n @apply w-full max-h-[70vh] rounded-t-3xl bg-white shadow-2xl border-t border-zinc-200 flex flex-col overflow-hidden;\n}\n\n.diff-viewer-mobile-sheet-handle {\n @apply mx-auto mt-3 h-1.5 w-12 rounded-full bg-zinc-300;\n}\n\n.diff-viewer-mobile-sheet-header {\n @apply flex items-center justify-between gap-3 px-4 pt-3 pb-2 border-b border-zinc-200;\n}\n\n.diff-viewer-mobile-sheet-list {\n @apply flex min-h-0 flex-col gap-2 overflow-y-auto px-3 py-3;\n}\n\n.diff-viewer-sheet-enter-active,\n.diff-viewer-sheet-leave-active {\n @apply transition-opacity duration-200;\n}\n\n.diff-viewer-sheet-enter-active .diff-viewer-mobile-sheet,\n.diff-viewer-sheet-leave-active .diff-viewer-mobile-sheet {\n transition: transform 200ms ease;\n}\n\n.diff-viewer-sheet-enter-from,\n.diff-viewer-sheet-leave-to {\n @apply opacity-0;\n}\n\n.diff-viewer-sheet-enter-from .diff-viewer-mobile-sheet,\n.diff-viewer-sheet-leave-to .diff-viewer-mobile-sheet {\n transform: translateY(100%);\n}\n\n@media (max-width: 767px) {\n .diff-viewer-backdrop {\n @apply p-0 items-stretch;\n }\n\n .diff-viewer-shell {\n @apply h-[100dvh] w-screen rounded-none border-0 shadow-none;\n }\n\n .diff-viewer-main {\n @apply min-w-0;\n }\n\n .diff-viewer-toolbar {\n @apply sticky top-0 z-10 bg-white px-3 py-3;\n }\n\n .diff-viewer-title {\n @apply text-sm leading-5;\n }\n\n .diff-viewer-subtitle {\n @apply text-xs;\n }\n\n .diff-viewer-meta {\n @apply px-3 py-2;\n }\n\n .diff-viewer-language {\n @apply text-[10px];\n }\n\n .diff-viewer-line {\n grid-template-columns: 2.75rem 2.75rem 1.5rem minmax(0, 1fr);\n }\n\n .diff-viewer-line-number {\n @apply px-1.5 py-1 text-[10px];\n }\n\n .diff-viewer-line-marker {\n @apply px-1 py-1 text-[10px];\n }\n\n .diff-viewer-line-code {\n @apply px-2 py-1 text-[11px] leading-5;\n }\n}\n</style>\n"],"file":"assets/ThreadConversation-Dr0u8WbA.js"}
|