umans-gate 0.1.2 → 0.1.4

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.
Files changed (58) hide show
  1. package/CHANGELOG.md +154 -0
  2. package/README.md +165 -45
  3. package/npm-shim.cjs +71 -0
  4. package/package.json +16 -80
  5. package/dashboard/dist/assets/alert-dialog-DlhAyxD3.js +0 -2
  6. package/dashboard/dist/assets/alert-dialog-DlhAyxD3.js.map +0 -1
  7. package/dashboard/dist/assets/clear-confirm-dialog-BOcl93wD.js +0 -2
  8. package/dashboard/dist/assets/clear-confirm-dialog-BOcl93wD.js.map +0 -1
  9. package/dashboard/dist/assets/config-tab-pnBjiSyC.js +0 -4
  10. package/dashboard/dist/assets/config-tab-pnBjiSyC.js.map +0 -1
  11. package/dashboard/dist/assets/economics-tab-BJXa5ydD.js +0 -2
  12. package/dashboard/dist/assets/economics-tab-BJXa5ydD.js.map +0 -1
  13. package/dashboard/dist/assets/geist-cyrillic-ext-wght-normal-DjL33-gN.woff2 +0 -0
  14. package/dashboard/dist/assets/geist-cyrillic-wght-normal-BEAKL7Jp.woff2 +0 -0
  15. package/dashboard/dist/assets/geist-latin-ext-wght-normal-DC-KSUi6.woff2 +0 -0
  16. package/dashboard/dist/assets/geist-latin-wght-normal-BgDaEnEv.woff2 +0 -0
  17. package/dashboard/dist/assets/geist-vietnamese-wght-normal-6IgcOCM7.woff2 +0 -0
  18. package/dashboard/dist/assets/headers-viewer-C9FKdG-_.js +0 -2
  19. package/dashboard/dist/assets/headers-viewer-C9FKdG-_.js.map +0 -1
  20. package/dashboard/dist/assets/index-72wCsW4_.js +0 -3
  21. package/dashboard/dist/assets/index-72wCsW4_.js.map +0 -1
  22. package/dashboard/dist/assets/index-DFhG4t-C.css +0 -1
  23. package/dashboard/dist/assets/json-viewer-CXkZMoVn.js +0 -2
  24. package/dashboard/dist/assets/json-viewer-CXkZMoVn.js.map +0 -1
  25. package/dashboard/dist/assets/mode-toggle-BxkGFiYG.js +0 -2
  26. package/dashboard/dist/assets/mode-toggle-BxkGFiYG.js.map +0 -1
  27. package/dashboard/dist/assets/models-tab-Deqk3WT3.js +0 -2
  28. package/dashboard/dist/assets/models-tab-Deqk3WT3.js.map +0 -1
  29. package/dashboard/dist/assets/performance-meter-Bd152C4C.js +0 -2
  30. package/dashboard/dist/assets/performance-meter-Bd152C4C.js.map +0 -1
  31. package/dashboard/dist/assets/select-mZPf2BR3.js +0 -2
  32. package/dashboard/dist/assets/select-mZPf2BR3.js.map +0 -1
  33. package/dashboard/dist/assets/sheet-BgQXtbdw.js +0 -2
  34. package/dashboard/dist/assets/sheet-BgQXtbdw.js.map +0 -1
  35. package/dashboard/dist/assets/sonner-DGu1DGeO.js +0 -2
  36. package/dashboard/dist/assets/sonner-DGu1DGeO.js.map +0 -1
  37. package/dashboard/dist/assets/sse-viewer-BHnn3FcY.js +0 -3
  38. package/dashboard/dist/assets/sse-viewer-BHnn3FcY.js.map +0 -1
  39. package/dashboard/dist/assets/use-capture-done-listener-u5RxfYQP.js +0 -2
  40. package/dashboard/dist/assets/use-capture-done-listener-u5RxfYQP.js.map +0 -1
  41. package/dashboard/dist/assets/use-models-B4MLkfpt.js +0 -2
  42. package/dashboard/dist/assets/use-models-B4MLkfpt.js.map +0 -1
  43. package/dashboard/dist/assets/use-polling-resource-D_vWHFwW.js +0 -2
  44. package/dashboard/dist/assets/use-polling-resource-D_vWHFwW.js.map +0 -1
  45. package/dashboard/dist/assets/vendor-CVKsgXJU.js +0 -312
  46. package/dashboard/dist/assets/vendor-CVKsgXJU.js.map +0 -1
  47. package/dashboard/dist/assets/vendor-DtX4s2-2.css +0 -1
  48. package/dashboard/dist/assets/vendor-react-Dtud3GyP.js +0 -41
  49. package/dashboard/dist/assets/vendor-react-Dtud3GyP.js.map +0 -1
  50. package/dashboard/dist/assets/vision-calls-BquNiDzm.js +0 -3
  51. package/dashboard/dist/assets/vision-calls-BquNiDzm.js.map +0 -1
  52. package/dashboard/dist/index.html +0 -34
  53. package/dist/cli.d.ts +0 -1
  54. package/dist/cli.js +0 -6788
  55. package/dist/cli.js.map +0 -1
  56. package/dist/index.d.ts +0 -1094
  57. package/dist/index.js +0 -6443
  58. package/dist/index.js.map +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"mappings":";49EAGO,SAASA,KAAMC,EAAsB,CAC1C,OAAOC,GAAQC,GAAKF,CAAM,CAAC,CAC7B,CCCA,MAAMG,GAAiBC,EACrB,6lBACA,CACE,SAAU,CACR,QAAS,CACP,QAAS,yDACT,QACE,kLACF,UACE,iLACF,MACE,mHACF,YACE,8NACF,KAAM,mDAER,KAAM,CACJ,QACE,uFACF,GAAI,gNACJ,GAAI,0NACJ,GAAI,uFACJ,KAAM,SACN,UACE,0HACF,UACE,qFACF,UAAW,SACb,EAEF,gBAAiB,CACf,QAAS,UACT,KAAM,UACR,CAEJ,EAOMC,EAASC,aACb,CAAC,CAAE,UAAAC,EAAW,QAAAC,EAAU,UAAW,KAAAC,EAAO,UAAW,GAAGC,CAAA,EAASC,IAE7DC,MAACC,GAAA,CACC,IAAAF,EACA,YAAU,SACV,UAAWZ,EAAGI,GAAe,CAAE,QAAAK,EAAS,KAAAC,EAAM,UAAAF,CAAA,CAAW,CAAC,EACzD,GAAGG,CAAA,EAIZ,EAEAL,EAAO,YAAc,SCxDrB,SAASS,GAAM,CAAE,UAAAP,EAAW,KAAAQ,EAAM,GAAGL,GAAwC,CAC3E,OACEE,MAACI,GAAA,CACC,KAAAD,EACA,YAAU,QACV,UAAWhB,EACT,8oBACAQ,CAAA,EAED,GAAGG,CAAA,EAGV,CCZA,SAASO,GAAgB,CAAE,MAAAC,EAAQ,EAAG,GAAGR,GAA0C,CACjF,OAAOE,MAACO,GAAA,CAA0B,YAAU,mBAAmB,MAAAD,EAAe,GAAGR,EAAO,CAC1F,CAEA,SAASU,EAAQ,CAAE,GAAGV,GAAsC,CAC1D,aAAQW,GAAA,CAAsB,YAAU,UAAW,GAAGX,EAAO,CAC/D,CAMA,SAASY,EAAe,CAAE,SAAAC,EAAU,QAAAC,EAAS,GAAGd,GAA8B,CAC5E,OAAIc,GAAWC,iBAAqBF,CAAQ,EACnCX,MAACc,GAAA,CAAyB,YAAU,kBAAkB,OAAQH,EAAW,GAAGb,EAAO,EAG1FE,MAACc,GAAA,CAAyB,YAAU,kBAAmB,GAAGhB,EACvD,SAAAa,EACH,CAEJ,CAEA,SAASI,EAAe,CACtB,UAAApB,EACA,KAAAqB,EAAO,MACP,WAAAC,EAAa,EACb,MAAAC,EAAQ,SACR,YAAAC,EAAc,EACd,SAAAR,EACA,GAAGb,CACL,EAC4F,CAC1F,OACEE,MAACoB,GAAA,CACC,SAAApB,MAACqB,GAAA,CACC,MAAAH,EACA,YAAAC,EACA,KAAAH,EACA,WAAAC,EACA,UAAU,eAEV,SAAAK,OAACC,GAAA,CACC,YAAU,kBACV,UAAWpC,EACT,kwBACAQ,CAAA,EAED,GAAGG,EAEH,UAAAa,EACDX,MAACwB,GAAA,CAAuB,UAAU,2hBAA2hB,IAC/jB,GAEJ,CAEJ,CCjDO,SAASC,GAAc,CAAE,UAAA9B,EAAW,GAAGG,GAAwC,CACpF,KAAM,CAAC4B,EAASC,CAAU,EAAIC,WAAS,EAAK,EAC5C,OACEN,OAAC,OAAI,UAAU,6BACb,UAAAtB,MAACE,GAAA,CAAM,KAAMwB,EAAU,OAAS,WAAY,UAAWvC,EAAG,OAAQQ,CAAS,EAAI,GAAGG,CAAA,CAAO,SACxFU,EAAA,CACC,UAAAR,MAACU,EAAA,CACC,OACEV,MAACP,EAAA,CACC,KAAK,SACL,QAAQ,QACR,KAAK,OACL,UAAU,yEACV,QAAS,IAAMkC,EAAYE,GAAM,CAACA,CAAC,EACnC,aAAYH,EAAU,gBAAkB,gBACxC,SAAU,KAIb,SAAAA,QAAWI,GAAA,CAAO,UAAU,cAAc,EAAK9B,MAAC+B,GAAA,CAAI,UAAU,cAAc,UAE9EhB,EAAA,CAAe,KAAK,MAAO,SAAAW,EAAU,gBAAkB,gBAAgB,GAC1E,GACF,CAEJ,CCrCO,MAAMM,EAAW,iBACXC,EAAkB,GAAGD,CAAQ,UAE7BE,GAAqB,0BC2H3B,SAASC,IAA6B,CAC3C,KAAM,CAACC,EAAQC,CAAS,EAAIT,WAA2B,IAAI,EACrD,CAACU,EAASC,CAAU,EAAIX,WAAS,EAAI,EACrC,CAACY,EAAOC,CAAQ,EAAIb,WAAwB,IAAI,EAEhDc,EAASC,cAAY,SAAY,CACrCJ,EAAW,EAAI,EACfE,EAAS,IAAI,EACb,GAAI,CACF,MAAMG,EAAI,MAAM,MAAMX,CAAe,EACrC,GAAI,CAACW,EAAE,GACL,OAAAH,EAAS,QAAQG,EAAE,MAAM,EAAE,EACpB,KAGT,GAAI,EADOA,EAAE,QAAQ,IAAI,cAAc,GAAK,IACpC,SAAS,kBAAkB,EACjC,OAAAH,EAAS,uBAAuB,EACzB,KAET,MAAMI,EAAQ,MAAMD,EAAE,OACtB,OAAAP,EAAUQ,CAAI,EACPA,CACT,OAASC,EAAG,CACV,OAAAL,EAASK,aAAa,MAAQA,EAAE,QAAU,OAAOA,CAAC,CAAC,EAC5C,IACT,SACEP,EAAW,EAAK,CAClB,CACF,EAAG,EAAE,EAGLQ,YAAU,IAAM,CACTL,EAAA,CACP,EAAG,CAACA,CAAM,CAAC,EAEX,MAAMM,EAAOL,cACX,MAAOM,GAAiD,CACtD,GAAI,CAMF,MAAMJ,EAAQ,MALJ,MAAM,MAAMZ,EAAiB,CACrC,OAAQ,OACR,QAAS,CAAE,eAAgB,oBAC3B,KAAM,KAAK,UAAUgB,CAAK,EAC3B,GACqB,OACtB,OAAIJ,EAAK,IAEP,MAAMH,EAAA,EAEDG,CACT,OAASC,EAAG,CACV,MAAO,CACL,GAAI,GACJ,OAAQ,CAACA,aAAa,MAAQA,EAAE,QAAU,OAAOA,CAAC,CAAC,EACnD,SAAU,GACV,QAASG,CAAA,CAEb,CACF,EACA,CAACP,CAAM,GAGHQ,EAAWP,cAAY,MAAOM,GAAuD,CACzF,GAAI,CACF,MAAML,EAAI,MAAM,MAAM,GAAGX,CAAe,YAAa,CACnD,OAAQ,OACR,QAAS,CAAE,eAAgB,oBAC3B,KAAM,KAAK,UAAUgB,CAAK,EAC3B,EACD,OAAKL,EAAE,GACC,MAAMA,EAAE,OADE,IAEpB,MAAQ,CACN,OAAO,IACT,CACF,EAAG,EAAE,EAECO,EAAiBR,cAAY,SAA0C,CAC3E,GAAI,CACF,MAAMC,EAAI,MAAM,MAAM,GAAGX,CAAe,UAAW,CAAE,OAAQ,OAAQ,EACrE,GAAI,CAACW,EAAE,GAAI,OAAO,KAClB,MAAMC,EAAQ,MAAMD,EAAE,OAEtB,aAAMF,EAAA,EACCG,CACT,MAAQ,CACN,OAAO,IACT,CACF,EAAG,CAACH,CAAM,CAAC,EAELU,EAAoBT,cAAY,SAAiD,CACrF,GAAI,CACF,MAAMC,EAAI,MAAM,MAAM,GAAGZ,CAAQ,wBAAyB,CAAE,OAAQ,OAAQ,EAC5E,GAAI,CAACY,EAAE,GAAI,OAAO,KAClB,MAAMC,EAAQ,MAAMD,EAAE,OACtB,OAAIC,EAAK,IACP,MAAMH,EAAA,EAEDG,CACT,MAAQ,CACN,OAAO,IACT,CACF,EAAG,CAACH,CAAM,CAAC,EAELW,EAAUV,cAAY,SAA2C,CACrE,GAAI,CACF,MAAMC,EAAI,MAAM,MAAM,GAAGZ,CAAQ,WAAY,CAAE,OAAQ,OAAQ,EAC/D,OAAKY,EAAE,GACC,MAAMA,EAAE,OADE,IAEpB,OAASE,EAAG,CACV,MAAO,CACL,GAAI,GACJ,MAAOA,aAAa,MAAQA,EAAE,QAAU,OAAOA,CAAC,EAEpD,CACF,EAAG,EAAE,EAECQ,EAAiBX,cAAY,SAAwC,CACzE,GAAI,CAEF,MAAME,EAAQ,MADJ,MAAM,MAAM,GAAGZ,CAAe,SAAU,CAAE,OAAQ,OAAQ,GAC9C,OACtB,OAAIY,EAAK,IACP,MAAMH,EAAA,EAEDG,CACT,OAASC,EAAG,CACV,MAAO,CACL,GAAI,GACJ,OAAQ,CAACA,aAAa,MAAQA,EAAE,QAAU,OAAOA,CAAC,CAAC,EACnD,SAAU,GACV,QAAS,KAEb,CACF,EAAG,CAACJ,CAAM,CAAC,EAEX,MAAO,CACL,OAAAN,EACA,QAAAE,EACA,MAAAE,EACA,OAAAE,EACA,KAAAM,EACA,SAAAE,EACA,eAAAC,EACA,kBAAAC,EACA,QAAAC,EACA,eAAAC,CAAA,CAEJ,CC3QA,MAAMC,GAAgBC,gBAAsC,IAAI,EAEzD,SAASC,GAAe,CAAE,SAAA9C,GAAqC,CACpE,MAAMyB,EAASD,GAAA,EACf,aAAQoB,GAAc,SAAd,CAAuB,MAAOnB,EAAS,SAAAzB,EAAS,CAC1D,CAEO,SAAS+C,IAAoC,CAClD,MAAMC,EAAMC,aAAWL,EAAa,EACpC,GAAI,CAACI,EACH,MAAM,IAAI,MAAM,uDAAuD,EAEzE,OAAOA,CACT,CCbA,SAASE,GAAK,CACZ,UAAAlE,EACA,KAAAE,EAAO,UACP,GAAGC,CACL,EAA8D,CAC5D,OACEE,MAAC,OACC,YAAU,OACV,YAAWH,EACX,UAAWV,EACT,uZACAQ,CAAA,EAED,GAAGG,CAAA,EAGV,CAEA,SAASgE,GAAW,CAAE,UAAAnE,EAAW,GAAGG,GAAsC,CACxE,OACEE,MAAC,OACC,YAAU,cACV,UAAWb,EACT,yPACAQ,CAAA,EAED,GAAGG,CAAA,EAGV,CAEA,SAASiE,GAAU,CAAE,UAAApE,EAAW,GAAGG,GAAsC,CACvE,OACEE,MAAC,OACC,YAAU,aACV,UAAWb,EACT,oFACAQ,CAAA,EAED,GAAGG,CAAA,EAGV,CAEA,SAASkE,GAAgB,CAAE,UAAArE,EAAW,GAAGG,GAAsC,CAC7E,OACEE,MAAC,OACC,YAAU,mBACV,UAAWb,EAAG,gCAAiCQ,CAAS,EACvD,GAAGG,CAAA,EAGV,CAYA,SAASmE,GAAY,CAAE,UAAAtE,EAAW,GAAGG,GAAsC,CACzE,OACEE,MAAC,OAAI,YAAU,eAAe,UAAWb,EAAG,sBAAuBQ,CAAS,EAAI,GAAGG,CAAA,CAAO,CAE9F,CClEA,SAASoE,GAAM,CAAE,UAAAvE,EAAW,GAAGG,GAAwC,CACrE,OAEEE,MAAC,SACC,YAAU,QACV,UAAWb,EACT,sNACAQ,CAAA,EAED,GAAGG,CAAA,EAGV,CCGA,MAAMqE,GAAOC,GASPC,GAAmBb,gBAAqC,EAA2B,EAEnFc,GAAY,CAGhB,CACA,GAAGxE,CACL,IAEIE,MAACqE,GAAiB,SAAjB,CAA0B,MAAO,CAAE,KAAMvE,EAAM,MAC9C,SAAAE,MAACuE,GAAA,CAAY,GAAGzE,EAAO,EACzB,EAIE0E,EAAe,IAAM,CACzB,MAAMC,EAAeb,aAAWS,EAAgB,EAC1CK,EAAcd,aAAWe,EAAe,EACxC,CAAE,cAAAC,CAAA,EAAkBC,GAAA,EACpBC,EAAYC,GAAa,CAAE,KAAMN,EAAa,KAAM,EACpDO,EAAaJ,EAAcH,EAAa,KAAMK,CAAS,EAE7D,GAAI,CAACL,EACH,MAAM,IAAI,MAAM,gDAAgD,EAGlE,KAAM,CAAE,GAAAQ,GAAOP,EAEf,MAAO,CACL,GAAAO,EACA,KAAMR,EAAa,KACnB,WAAY,GAAGQ,CAAE,aACjB,kBAAmB,GAAGA,CAAE,yBACxB,cAAe,GAAGA,CAAE,qBACpB,GAAGD,CAAA,CAEP,EAMML,GAAkBnB,gBAAoC,EAA0B,EAEtF,SAAS0B,GAAS,CAAE,UAAAvF,EAAW,GAAGG,GAAyC,CACzE,MAAMmF,EAAKE,QAAA,EACX,aACGR,GAAgB,SAAhB,CAAyB,MAAO,CAAE,GAAAM,GACjC,SAAAjF,MAAC,OAAI,YAAU,YAAY,UAAWb,EAAG,aAAcQ,CAAS,EAAI,GAAGG,EAAO,EAChF,CAEJ,CAEA,SAASsF,GAAU,CAAE,UAAAzF,EAAW,GAAGG,GAAiD,CAClF,KAAM,CAAE,MAAA0C,EAAO,WAAA6C,CAAA,EAAeb,EAAA,EAC9B,OACExE,MAACkE,GAAA,CACC,YAAU,aACV,aAAY,CAAC,CAAC1B,EACd,UAAWrD,EAAG,qCAAsCQ,CAAS,EAC7D,QAAS0F,EACR,GAAGvF,CAAA,EAGV,CAEA,SAASwF,GAAY,CAAE,GAAGxF,GAAgD,CACxE,KAAM,CAAE,MAAA0C,EAAO,WAAA6C,EAAY,kBAAAE,EAAmB,cAAAC,CAAA,EAAkBhB,EAAA,EAChE,OACExE,MAACyF,GAAA,CACC,YAAU,eACV,GAAIJ,EACJ,mBAAmB7C,EAAiC,GAAG+C,CAAiB,IAAIC,CAAa,GAA9D,GAAGD,CAAiB,GAC/C,eAAc,CAAC,CAAC/C,EACf,GAAG1C,CAAA,EAGV,CAcA,SAAS4F,GAAY,CAAE,UAAA/F,EAAW,GAAGG,GAA+C,CAClF,KAAM,CAAE,MAAA0C,EAAO,cAAAgD,CAAA,EAAkBhB,EAAA,EAC3BmB,EAAOnD,EAAQ,QAAOA,GAAA,YAAAA,EAAO,UAAW,EAAE,EAAI1C,EAAM,SAC1D,OAAK6F,EAIH3F,MAAC,KACC,YAAU,eACV,GAAIwF,EACJ,UAAWrG,EAAG,2BAA4BQ,CAAS,EAClD,GAAGG,EAEH,SAAA6F,CAAA,GATI,IAYX,CC3HA,MAAMC,GAASC,GAAS,CACtB,cAAeC,GAAE,EAAS,OAAO,IAAI,EAAG,qBAAqB,CAC/D,CAAC,EAIM,SAASC,IAAa,CAC3B,KAAM,CAAE,OAAA3D,EAAQ,QAAAE,EAAS,MAAAE,EAAO,KAAAQ,CAAA,EAASU,GAAA,EAEnCsC,EAAOC,GAAoB,CAC/B,SAAUC,GAAYN,EAAM,EAC5B,cAAe,CAAE,cAAe,GAAG,CACpC,EAEK,CACJ,aAAAO,EACA,UAAW,CAAE,aAAAC,CAAA,CAAa,EACxBJ,EAEEK,EAAYC,SAA0B,IAAI,EAE1CC,EAAWnE,IAAW,MAAQ,CAACE,GAAW,CAACE,GAAS,CAACJ,EAAO,YAelE,GAbAW,YAAU,IAAM,CACVP,GACFgE,EAAM,MAAM,+BAAgC,CAAE,YAAa,OAAOhE,CAAK,EAAG,CAE9E,EAAG,CAACA,CAAK,CAAC,EAEVO,YAAU,IAAM,CACd,MAAM0D,EAASJ,EAAU,QACrBE,GAAYE,GAAU,CAACA,EAAO,MAChCA,EAAO,WAEX,EAAG,CAACF,CAAQ,CAAC,EAET,CAACA,EAAU,OAAO,KAEtB,MAAMG,EAAW,MAAOC,GAAuB,CAC7C,GAAI,CACF,MAAMC,EAAS,MAAM5D,EAAK,CAAE,cAAe2D,EAAO,cAAe,EACjE,GAAI,CAACC,GAAU,CAACA,EAAO,GAAI,CACzBJ,EAAM,MAAM,yBAA0B,CACpC,aAAaI,GAAA,YAAAA,EAAQ,OAAO,KAAK,QAAS,gBAC3C,EACD,MACF,CACAJ,EAAM,QAAQ,yCAAyC,CACzD,OAASK,EAAK,CACZL,EAAM,MAAM,yBAA0B,CACpC,YAAaK,aAAe,MAAQA,EAAI,QAAU,gBACnD,CACH,CACF,EAEA,OACE7G,MAAC,UACC,IAAKqG,EACL,UAAU,6FACV,aAAW,yBAEX,eAAC,OAAI,UAAU,qDACb,SAAA/E,OAACuC,GAAA,CAAK,UAAU,kBACd,UAAAvC,OAACwC,GAAA,CACC,UAAAxC,OAAC,OAAI,UAAU,0BACb,UAAAtB,MAAC8G,GAAA,CAAS,UAAU,+BAA+B,EACnD9G,MAAC+D,IAAU,kCAAsB,GACnC,EACA/D,MAACgE,IAAgB,0JAGjB,GACF,SACCC,GAAA,CACC,UAAAjE,MAACmE,GAAA,CAAM,GAAG6B,EACR,SAAA1E,OAAC,QAAK,SAAU6E,EAAaO,CAAQ,EAAG,UAAU,aAChD,UAAA1G,MAACsE,GAAA,CACC,QAAS0B,EAAK,QACd,KAAK,gBACL,OAAQ,CAAC,CAAE,MAAAe,CAAA,WACR7B,GAAA,CACC,UAAAlF,MAACoF,IAAU,mBAAO,QACjBE,GAAA,CACC,SAAAtF,MAACyB,GAAA,CACC,YAAY,SACZ,aAAa,MACb,UAAS,GACT,SAAU2E,EACT,GAAGW,CAAA,GAER,QACCrB,GAAA,EAAY,GACf,IAGJ1F,MAACP,GAAO,KAAK,SAAS,SAAU2G,EAC7B,SAAAA,EAAe,UAAY,kBAC9B,GACF,EACF,EACA9E,OAAC,KAAE,UAAU,iDAAiD,8BAC1C,IAClBtB,MAAC,KACC,KAAK,uBACL,OAAO,SACP,IAAI,sBACJ,UAAU,kCACX,yBAED,EACF,GACF,GACF,EACF,GAGN,CC/HA,MAAMgH,GAAaC,OAAK,UACtB,OAAO,2BAA0B,8BAAE,KAAMC,IAAO,CAAE,QAASA,EAAE,YAAa,CAC5E,EACMC,GAAYF,OAAK,UACrB,OAAO,0BAAyB,8BAAE,KAAMC,IAAO,CAAE,QAASA,EAAE,WAAY,CAC1E,EAEO,SAASE,GAAa,CAC3B,KAAAzB,EACA,MAAA0B,CACF,EAGG,CACD,GAAI,CAAC1B,EACH,OACErE,OAAC,OAAI,UAAU,yDACb,UAAAtB,MAACsH,GAAA,CAAS,UAAU,cAAc,EAAE,cAEtC,EAIJ,GAAI3B,EAAK,WAAW,SAAS,EAC3B,OACErE,OAAC,OAAI,UAAU,+BAA+B,kCACtBqE,EAAK,OAAS,EAAE,WACxC,EAIJ,GAAI0B,EACF,OAAOrH,MAACmH,IAAU,KAAAxB,EAAY,EAGhC,GAAI,CACF,YAAK,MAAMA,CAAI,EACR3F,MAACgH,IAAW,KAAArB,EAAY,CACjC,MAAQ,CACN,OACE3F,MAAC,OAAI,UAAU,oEACZ,SAAA2F,EACH,CAEJ,CACF,CCvCO,MAAM4B,EACX,sFAGWC,EACX,sFAGWC,GACX,0FAGWC,GACX,kFAGWC,GAAa,iCAGbC,GAAa,iCC5BnB,SAASC,EAAQC,EAAsC,CAC5D,MAAMC,EAAQD,GAAK,EACnB,OAAIC,IAAU,EAAU,MACpBA,EAAQ,KAAa,GAAGA,CAAK,KAC7BA,EAAQ,QAAgB,IAAIA,EAAQ,MAAM,QAAQ,CAAC,CAAC,MACjD,IAAIA,EAAQ,SAAS,QAAQ,CAAC,CAAC,KACxC,CAEO,SAASC,GAAiBF,EAAsC,CACrE,MAAMC,EAAQD,GAAK,EACnB,OAAIC,IAAU,EAAU,IACpBA,EAAQ,IAAa,OAAOA,CAAK,EACjCA,EAAQ,IAAkB,IAAIA,EAAQ,KAAM,QAAQ,CAAC,CAAC,IACtDA,EAAQ,IAAsB,IAAIA,EAAQ,KAAW,QAAQ,CAAC,CAAC,IAC5D,IAAIA,EAAQ,KAAe,QAAQ,CAAC,CAAC,GAC9C,CAEO,SAASE,EAAQC,EAAuC,CAC7D,OAAIA,GAAM,KAAa,GACnBA,EAAK,IAAa,GAAGA,CAAE,MACpB,IAAIA,EAAK,KAAM,QAAQ,CAAC,CAAC,IAClC,CAEO,SAASC,GAAQD,EAAuC,CAC7D,OAAIA,GAAM,KAAa,IACnBA,EAAK,IAAa,GAAG,KAAK,MAAMA,CAAE,CAAC,KAChC,IAAIA,EAAK,KAAM,QAAQ,CAAC,CAAC,GAClC,CAEO,SAASE,GAAOC,EAAwC,CAC7D,OAAIA,GAAO,KAAa,IACjB,GAAGA,EAAI,QAAQ,CAAC,CAAC,EAC1B,CAEO,SAASC,GACdC,EACAC,EACQ,CACR,MAAMC,EAAIF,GAAY,EAChBG,EAAIF,GAAS,EACnB,OAAIE,GAAK,EAAU,IAEZ,IADMD,EAAIC,EAAK,KACR,QAAQ,CAAC,CAAC,GAC1B,CAEO,SAASC,GAAQC,EAAuC,CAC7D,OAAOA,EAAK,IAAI,KAAKA,CAAE,EAAE,mBAAmB,GAAI,CAAE,OAAQ,GAAO,EAAI,EACvE,CAEO,SAASC,GAAYD,EAAuC,CACjE,OAAKA,EACE,IAAI,KAAKA,CAAE,EAAE,eAAe,GAAI,CACrC,MAAO,QACP,IAAK,UACL,KAAM,UACN,OAAQ,UACR,OAAQ,GACT,EAPe,EAQlB,CAEA,SAASE,GAAWC,EAAsC,CACxD,OAAQA,GAAK,IAAI,QAAQ,SAAWN,IAAO,CAAE,IAAK,QAAS,IAAK,OAAQ,IAAK,SAAUA,CAAC,GAAKA,CAAC,CAChG,CAEO,SAASO,GAAYD,EAAmE,CAC7F,OAAKA,EACDA,EAAI,IAAY,KAChBA,EAAI,IAAY,OAChBA,EAAI,IAAY,OACb,MAJQ,EAKjB,CAEO,SAASE,GAAiBC,EAAwD,CACvF,GAAI,CACF,MAAMC,EAAS,KAAK,MAAMD,GAAO,IAAI,EACrC,OAAOC,GAAU,OAAOA,GAAW,UAAY,CAAC,MAAM,QAAQA,CAAM,EAC/DA,EACD,EACN,MAAQ,CACN,MAAO,EACT,CACF,CAEO,SAASC,GAAgBC,EAAsB,CACpD,OAAOP,GAAWO,CAAI,CACxB,CAOO,SAASC,GAAgB3D,EAAsD,CACpF,GAAI,CAACA,EAAM,OAAO,KAClB,IAAIwD,EACJ,GAAI,CACFA,EAAS,KAAK,MAAMxD,CAAI,CAC1B,MAAQ,CACN,OAAO,IACT,CACA,GAAI,CAACwD,GAAU,OAAOA,GAAW,UAAY,MAAM,QAAQA,CAAM,EAAG,OAAO,KAE3E,MAAMI,EAAMJ,EACZ,IAAIK,EAAQ,EACRC,EAAqB,KAEzB,MAAMC,EAAQC,GAAoB,CAChC,GAAK,MAAM,QAAQA,CAAM,EACzB,UAAWC,KAAKD,EAAQ,CACtB,MAAME,EAAMD,GAAA,YAAAA,EAA2D,eACnEC,GAAA,YAAAA,EAAI,QAAS,cACfL,IACIK,EAAG,KAAO,CAACJ,MAAWI,EAAG,KAEjC,CACF,EAEAH,EAAKH,EAAI,MAAM,EACf,UAAWrC,KAAKqC,EAAI,UAAY,GAAIG,EAAKxC,GAAA,YAAAA,EAAG,OAAO,EAEnD,OAAOsC,EAAQ,EAAI,CAAE,MAAAA,EAAO,IAAAC,GAAQ,IACtC,CCnHA,MAAMK,GAAgBtK,EACpB,6eACA,CACE,SAAU,CACR,QAAS,CACP,QAAS,6DACT,UAAW,mEACX,YACE,iKACF,QAAS,mFACT,MAAO,oEACP,KAAM,mDAER,KAAM,CACJ,QAAS,GACT,GAAI,uDACN,EAEF,gBAAiB,CACf,QAAS,UACT,KAAM,UACR,CAEJ,EAEA,SAASuK,EAAM,CACb,UAAApK,EACA,QAAAC,EAAU,UACV,KAAAC,EAAO,UACP,OAAAmK,EACA,GAAGlK,CACL,EAA0E,CACxE,OAAOmK,GAAU,CACf,eAAgB,OAChB,MAAOC,GACL,CACE,UAAW/K,EAAG2K,GAAc,CAAE,QAAAlK,EAAS,KAAAC,CAAA,CAAM,EAAGF,CAAS,GAE3DG,CAAA,EAEF,OAAAkK,EACA,MAAO,CACL,KAAM,QACN,QAAApK,EACA,KAAAC,CAAA,CACF,CACD,CACH,CChDA,MAAMsK,GAGF,CACF,GAAI,CAAE,QAAS,YAAa,UAAW5C,CAAA,EACvC,KAAM,CAAE,QAAS,YAAa,UAAWG,EAAA,EACzC,KAAM,CAAE,QAAS,YAAa,UAAWF,CAAA,EACzC,IAAK,CAAE,QAAS,eAChB,GAAI,CAAE,QAAS,YACjB,EAEM4C,GAAqC,CACzC,GAAI,kBACJ,KAAM,kBACN,KAAM,mBACN,IAAK,mBACL,GAAI,iBACN,EASO,SAASC,GAAY,CAC1B,OAAAC,EACA,aAAAC,EAAe,KACf,WAAAC,EAAa,KACb,KAAA3K,EAAO,SACT,EAAqB,CACnB,MAAM4K,EAAQzB,GAAYsB,CAAM,EAC1BI,EAAMP,GAAYM,CAAK,EACvBE,EAAMP,GAAWK,CAAK,EACtBG,EAASL,IAAiB,OAC1BM,EAAQP,GAAU,KAAO,IAAM,GAAGA,CAAM,GAAGM,EAAS,QAAU,EAAE,GAChEE,EACJF,GAAUJ,EACN,QAAQF,CAAM,wCAAwCE,CAAU,GAChE,QAAQK,CAAK,MAAMF,CAAG,GAE5B,cACGnK,EAAA,CACC,UAAAR,MAACU,GAAe,OAAQV,MAAC,QAAK,UAAU,cAAc,EACpD,SAAAA,MAAC+J,EAAA,CAAM,QAASW,EAAI,QAAS,KAAA7K,EAAY,UAAW6K,EAAI,UACrD,WACH,EACF,EACA1K,MAACe,EAAA,CAAe,KAAK,MAAO,SAAA+J,CAAA,CAAY,GAC1C,CAEJ,CCpDA,SAASC,GAAQ,CAAE,UAAApL,EAAW,GAAGG,GAAsC,CACrE,OACEE,MAACgL,GAAA,CACC,KAAK,MACL,aAAW,UACX,UAAW7L,EAAG,sBAAuBQ,CAAS,EAC7C,GAAGG,CAAA,EAGV,CCXA,SAASmL,EAAO,CAAE,UAAAtL,GAAqC,CACrD,OACEK,MAAC,OAAI,YAAU,SAAS,UAAWb,EAAG,0CAA2CQ,CAAS,EACxF,SAAAK,MAAC+K,GAAA,CAAQ,UAAU,+BAA+B,EACpD,CAEJ,CCFA,SAASG,GAAW,CAClB,UAAAvL,EACA,SAAAgB,EACA,YAAAwK,EACA,GAAGrL,CACL,EAEG,CACD,OACEwB,OAAC8J,GAAA,CACC,YAAU,cACV,UAAWjM,EAAG,WAAYQ,CAAS,EAClC,GAAGG,EAEJ,UAAAE,MAACqL,GAAA,CACC,YAAU,uBACV,IAAKF,EACL,UAAU,qJAET,SAAAxK,CAAA,SAEF2K,GAAA,EAAU,EACXtL,MAACuL,GAAA,EAA2B,IAGlC,CAEA,SAASD,GAAU,CACjB,UAAA3L,EACA,YAAA6L,EAAc,WACd,GAAG1L,CACL,EAAwC,CACtC,OACEE,MAACyL,GAAA,CACC,YAAU,wBACV,mBAAkBD,EAClB,YAAAA,EACA,UAAWrM,EACT,qXACAQ,CAAA,EAED,GAAGG,EAEJ,SAAAE,MAAC0L,GAAA,CACC,YAAU,oBACV,UAAU,oFACZ,EAGN,CCnDA,SAASC,GAAK,CAAE,UAAAhM,EAAW,YAAA6L,EAAc,aAAc,GAAG1L,GAAmC,CAC3F,OACEE,MAAC4L,GAAA,CACC,YAAU,OACV,mBAAkBJ,EAClB,UAAWrM,EAAG,yDAA0DQ,CAAS,EAChF,GAAGG,CAAA,EAGV,CAEA,MAAM+L,GAAmBrM,EACvB,oRACA,CACE,SAAU,CACR,QAAS,CACP,QAAS,WACT,KAAM,uBACR,EAEF,gBAAiB,CACf,QAAS,UACX,CAEJ,EAEA,SAASsM,GAAS,CAChB,UAAAnM,EACA,QAAAC,EAAU,UACV,gBAAAmM,EAAkB,GAClB,GAAGjM,CACL,EAAqE,CACnE,OACEE,MAACgM,GAAA,CACC,YAAU,YACV,eAAcpM,EACd,gBAAAmM,EACA,UAAW5M,EAAG0M,GAAiB,CAAE,QAAAjM,CAAA,CAAS,EAAGD,CAAS,EACrD,GAAGG,CAAA,EAGV,CAEA,SAASmM,GAAY,CAAE,UAAAtM,EAAW,GAAGG,GAAkC,CACrE,OACEE,MAACkM,GAAA,CACC,YAAU,eACV,UAAW/M,EACT,y3BACA,gQACA,oJACA,2dACAQ,CAAA,EAED,GAAGG,CAAA,EAGV,CAEA,SAASqM,EAAY,CAAE,UAAAxM,EAAW,GAAGG,GAAoC,CACvE,OACEE,MAACoM,GAAA,CACC,YAAU,eACV,UAAWjN,EAAG,8BAA+BQ,CAAS,EACrD,GAAGG,CAAA,EAGV,CCxDA,MAAMuM,GAAgBpF,OAAK,UACzB,OAAO,8BAA6B,8BAAE,KAAMC,IAAO,CAAE,QAASA,EAAE,eAAgB,CAClF,EAaMoF,EAAuC,CAC3C,SAAU,gBACV,QAAS,eACT,cAAe,mBACf,cAAe,iBACjB,EAEMC,GAAqC,CACzC,SAAU,oCACV,QAAS,0CACT,cAAe,sCACf,cAAe,uCACjB,EAEO,SAASC,GAAmB,CACjC,QAAAC,EACA,UAAAC,EACA,YAAAC,EACA,OAAAC,EACA,aAAAC,EACA,QAAAC,CACF,EAAuB,CACrB,KAAM,CAACC,EAAWC,CAAY,EAAIpL,WAAmB,UAAU,EACzD,CAACqL,EAAYC,CAAa,EAAItL,WAAuC,MAAM,EAC3EuL,EAAsB7G,SAAO,EAAK,EAElC8G,EAAYC,UAAQ,IACpBJ,IAAe,SAAiB,UAChCA,IAAe,SAAiB,SAC7B,OACN,CAACA,CAAU,CAAC,EAEXJ,GAAgB,CAACM,EAAoB,UACvCA,EAAoB,QAAU,GAC9BN,EAAaO,CAAS,GAGxB,MAAME,EAAYD,UAAQ,IACnBZ,EACE,CACL,SAAUA,EAAQ,cAClB,QAASA,EAAQ,aACjB,cAAeA,EAAQ,iBACvB,cAAeA,EAAQ,iBALJ,GAOpB,CAACA,CAAO,CAAC,EAENc,EAAWF,UACf,IAAOZ,EAAUnD,GAAgBmD,EAAQ,YAAY,EAAI,KACzD,CAACA,CAAO,GAGV,eAAee,GAAa,CAC1B,GAAI,CAACf,EAAS,OACd,MAAMgB,EAAK,MAAMb,EAAOU,EAAUP,CAAS,GAAK,EAAE,EAC5CW,EAAaD,EAAK,SAAW,SAC7BE,EAAYF,EAAK,UAAY,SACnCP,EAAcQ,CAAU,EACxBb,GAAA,MAAAA,EAAec,GACf,WAAW,IAAM,CACfT,EAAc,MAAM,EACpBL,GAAA,MAAAA,EAAe,OACjB,EAAG,IAAI,EACP,MAAMhC,EAAQyB,EAAWS,CAAS,EAC9BU,EACFjH,EAAM,QAAQ,sBAAuB,CAAE,YAAaqE,EAAO,EAE3DrE,EAAM,MAAM,cAAe,CAAE,YAAa,kBAAkBqE,EAAM,aAAa,IAAK,CAExF,CAEA,OAAI6B,EAEA1M,MAAC,QAAK,aAAW,iBAAiB,UAAU,uCAC1C,SAAAA,MAACiL,IAAO,EACV,EAIA,CAACwB,GAAWE,EAEZrL,OAAC,QAAK,UAAU,+GACd,UAAAtB,MAAC4N,GAAA,CAAY,UAAU,6BAA6B,EACpD5N,MAAC,KAAE,UAAU,uCAAuC,gCAAoB,EACxEA,MAAC,KAAE,UAAU,UAAW,SAAA2M,EAAY,SACnCnM,EAAA,CACC,UAAAR,MAACU,EAAA,CAAe,QAAO,GACrB,SAAAY,OAAC7B,EAAA,CAAO,QAAQ,UAAU,KAAK,KAAK,QAASqN,EAC3C,UAAA9M,MAAC6N,GAAA,CAAU,UAAU,qBAAqB,EAAE,SAE9C,EACF,EACA7N,MAACe,EAAA,CAAe,KAAK,MAAM,wCAA4B,GACzD,GACF,EAIC0L,EAaHnL,OAAC,QAAK,UAAU,uCACd,UAAAA,OAAC,UAAO,UAAU,mCAChB,UAAAA,OAAC,OAAI,UAAU,gDACb,UAAAA,OAAC,MAAG,UAAU,8DACX,UAAAmL,EAAQ,OAAO,IAAEA,EAAQ,MAC5B,SACCjM,EAAA,CACC,UAAAR,MAACU,EAAA,CAAe,QAAO,GACrB,SAAAY,OAAC7B,EAAA,CAAO,KAAK,KAAK,QAAQ,UAAU,UAAU,WAAW,QAAS+N,EAChE,UAAAxN,MAAC8N,GAAA,CAAK,UAAU,qBAAqB,EACpCV,CAAA,EACH,EACF,EACApN,MAACe,EAAA,CAAe,KAAK,OAAO,gDAAoC,GAClE,GACF,EACAO,OAAC,OAAI,UAAU,8EACb,UAAAtB,MAACqK,GAAA,CACC,OAAQoC,EAAQ,gBAChB,aAAcA,EAAQ,cACtB,WAAYA,EAAQ,YACpB,KAAK,OAENc,UACE/M,EAAA,CACC,UAAAR,MAACU,EAAA,CAAe,OAAQV,MAAC,QAAK,UAAU,cAAc,EACpD,SAAAsB,OAACyI,EAAA,CAAM,QAAQ,UAAU,KAAK,KAC5B,UAAA/J,MAAC+N,GAAA,CAAM,UAAU,mBAAmB,cAAW,GAAC,EAAE,OAC7CR,EAAS,KAAO,KACvB,EACF,EACAjM,OAACP,EAAA,CAAe,KAAK,MAAM,UAAU,gBAClC,UAAAwM,EAAS,MAAM,SAAOA,EAAS,MAAQ,EAAI,IAAM,GAAG,+BACvD,GACF,EAEDd,EAAQ,QACPnL,OAACd,EAAA,CACC,UAAAR,MAACU,EAAA,CAAe,OAAQV,MAAC,QAAK,UAAU,cAAc,EACpD,SAAAA,MAAC+J,EAAA,CAAM,QAAQ,YAAY,KAAK,KAAK,eAErC,EACF,EACA/J,MAACe,EAAA,CAAe,KAAK,MAAM,8CAAkC,GAC/D,SAEDP,EAAA,CACC,UAAAR,MAACU,EAAA,CAAe,OAAQV,MAAC,QAAK,UAAU,2BAA2B,EACjE,gBAAC,QAAK,cACF6H,EAAQ4E,EAAQ,YAAY,EAAE,KAAG5E,EAAQ4E,EAAQ,aAAa,GAClE,EACF,EACAnL,OAACP,EAAA,CAAe,KAAK,MAAM,eACtB8G,EAAQ4E,EAAQ,YAAY,EAAE,gBAAc5E,EAAQ4E,EAAQ,aAAa,EAAG,IAAI,YAErF,GACF,SACCjM,EAAA,CACC,UAAAR,MAACU,EAAA,CAAe,OAAQV,MAAC,QAAK,UAAU,2BAA2B,EACjE,SAAAA,MAAC,QAAM,SAAAiI,EAAQwE,EAAQ,WAAW,EAAE,EACtC,EACAzM,MAACe,EAAA,CAAe,KAAK,MAAM,wDAA4C,GACzE,EACC0L,EAAQ,mBACPnL,OAACd,EAAA,CACC,UAAAR,MAACU,EAAA,CAAe,OAAQV,MAAC,QAAK,UAAU,cAAc,EACpD,SAAAsB,OAACyI,EAAA,CAAM,QAAQ,UAAU,KAAK,KAAK,gBAC7B0C,EAAQ,mBACd,EACF,EACAzM,MAACe,EAAA,CAAe,KAAK,MAAM,2CAA+B,GAC5D,EAED0L,EAAQ,mBACPnL,OAACd,EAAA,CACC,UAAAR,MAACU,EAAA,CAAe,OAAQV,MAAC,QAAK,UAAU,cAAc,EACpD,SAAAsB,OAACyI,EAAA,CAAM,QAAQ,UAAU,KAAK,KAAK,iBAC5B0C,EAAQ,mBACf,EACF,EACAzM,MAACe,EAAA,CAAe,KAAK,MAAM,+CAAmC,GAChE,SAEDP,EAAA,CACC,UAAAR,MAACU,EAAA,CAAe,OAAQV,MAAC,QAAK,UAAU,qCAAqC,EAC3E,SAAAA,MAAC,QAAM,SAAA2I,GAAQ8D,EAAQ,UAAU,EAAE,EACrC,EACAzM,MAACe,EAAA,CAAe,KAAK,MAClB,SAAA0L,EAAQ,WACL,IAAI,KAAKA,EAAQ,UAAU,EAAE,iBAC7B,mBACN,GACF,EACCA,EAAQ,QAAU,aACjBnL,OAACd,EAAA,CACC,UAAAR,MAACU,GAAe,OAAQV,MAAC,QAAK,UAAU,cAAc,EACpD,SAAAA,MAAC+J,EAAA,CAAM,QAAQ,YAAY,KAAK,KAAK,UAAWxC,EAAc,gBAE9D,EACF,EACAvH,MAACe,EAAA,CAAe,KAAK,MAAM,uCAA2B,GACxD,GAEJ,EACAf,MAAC,OAAI,UAAU,sEACZ,WAAQ,IACX,GACF,EAEAsB,OAACqK,GAAA,CACC,MAAOoB,EACP,cAAgBlL,GAAMmL,EAAanL,CAAa,EAChD,UAAU,uCAEV,UAAA7B,MAAC8L,GAAA,CAAS,UAAU,qBAChB,gBAAO,KAAKQ,CAAU,EAAiB,IAAK0B,GAC5C1M,OAACd,EAAA,CACC,UAAAR,MAACU,EAAA,CAAe,OAAQV,MAAC,SAAK,EAC5B,SAAAA,MAACiM,GAAA,CAAY,MAAO+B,EAAK,SAAA1B,EAAW0B,CAAE,EAAE,EAC1C,EACAhO,MAACe,GAAe,KAAK,SAAS,UAAU,gBACrC,SAAAwL,GAASyB,CAAE,EACd,IANYA,CAOd,CACD,EACH,EAEAhO,MAACiO,WAAA,CAAS,SAAUjO,MAACiL,EAAA,EAAO,EAC1B,SAAAjL,MAACkL,GAAA,CAAW,UAAU,2BACpB,SAAA5J,OAAC,OAAI,UAAU,SACb,UAAAtB,MAACmM,EAAA,CAAY,MAAM,WAAW,UAAU,MACtC,SAAAnM,MAACoH,GAAA,CAAa,KAAMqF,EAAQ,cAAe,MAAOA,EAAQ,OAAQ,EACpE,EACAzM,MAACmM,EAAA,CAAY,MAAM,UAAU,UAAU,MACrC,SAAAnM,MAACoH,GAAA,CAAa,KAAMqF,EAAQ,aAAc,MAAO,GAAO,EAC1D,EACAzM,MAACmM,EAAA,CAAY,MAAM,cAAc,UAAU,MACzC,SAAAnM,MAACqM,GAAA,CAAc,QAASI,EAAQ,iBAAkB,EACpD,EACAzM,MAACmM,EAAA,CAAY,MAAM,cAAc,UAAU,MACzC,SAAAnM,MAACqM,GAAA,CAAc,QAASI,EAAQ,gBAAiB,EACnD,GACF,EACF,EACF,IACF,EACF,EA7JEnL,OAAC,QAAK,UAAU,+GACd,UAAAtB,MAACkO,GAAA,CAAW,UAAU,qCAAqC,EAC3DlO,MAAC,KAAE,UAAU,sBAAsB,uCAA2B,EAC9DA,MAAC,KAAE,UAAU,UAAU,8EAEvB,GACF,CAyJN,CCjQA,SAASmO,GAAWC,EAA0BC,EAAmC,CAC/E,KAAM,CAACC,EAAKC,CAAM,EAAI3M,WAAS,IAAM,KAAK,KAAK,EAM/C,OALAmB,YAAU,IAAM,CACd,GAAI,CAACsL,GAAaD,GAAa,KAAM,OACrC,MAAMnJ,EAAK,YAAY,IAAMsJ,EAAO,KAAK,KAAK,EAAG,GAAI,EACrD,MAAO,IAAM,cAActJ,CAAE,CAC/B,EAAG,CAACoJ,EAAWD,CAAS,CAAC,EACrB,CAACC,GAAaD,GAAa,KAAa,KACrC,KAAK,IAAI,EAAGE,EAAMF,CAAS,CACpC,CAEA,SAASI,GAAOtG,EAAoB,CAClC,MAAM,EAAI,KAAK,MAAMA,EAAK,GAAI,EAC9B,GAAI,EAAI,GAAI,MAAO,GAAG,CAAC,IACvB,MAAMhB,EAAI,KAAK,MAAM,EAAI,EAAE,EACrBuH,EAAM,EAAI,GAChB,MAAO,GAAGvH,CAAC,IAAIuH,CAAG,GACpB,CAMA,SAASC,EAAO,CACd,IAAA/D,EACA,SAAAhK,CACF,EAGG,CACD,cACGH,EAAA,CACC,UAAAR,MAACU,GAAe,OAAQV,MAAC,QAAK,UAAU,cAAc,EAAK,SAAAW,EAAS,QACnEI,EAAA,CAAe,KAAK,MAAM,UAAU,gBAClC,SAAA4J,CAAA,CACH,GACF,CAEJ,CAEO,SAASgE,GAAe,CAC7B,QAASlG,EACT,SAAAmG,EACA,SAAAC,EACA,SAAAC,EACA,WAAAC,CACF,EAAwB,CACtB,MAAMV,EAAY5F,EAAE,QAAU,YAAcA,EAAE,QAAU,YAClDuG,EAAUb,GAAW1F,EAAE,WAAY4F,CAAS,EAElD,OACE/M,OAAC,OAEC,KAAK,SACL,GAAIwN,EACJ,gBAAeF,EACf,SAAU,GACV,QAASG,EACT,UAAYjM,GAAM,EACZA,EAAE,MAAQ,SAAWA,EAAE,MAAQ,OACjCA,EAAE,iBACFiM,EAAA,EAEJ,EACA,UAAW5P,EACT,2GACAyP,GAAY,YACZC,GAAY,CAACD,GAAY,gBAI3B,UAAAtN,OAAC,OAAI,UAAU,4CACb,UAAAtB,MAAC0O,EAAA,CACC,IACEpN,OAAA2N,WAAA,CAAE,oBACOjP,MAAC,QAAK,UAAU,YAAa,WAAE,OAAO,GAC/C,EAGF,SAAAA,MAAC,QAAK,UAAU,oDAAqD,WAAE,OAAO,IAEhFA,MAACqK,GAAA,CACC,OAAQ5B,EAAE,gBACV,aAAcA,EAAE,cAChB,WAAYA,EAAE,YACd,KAAK,OAENA,EAAE,WACDzI,MAAC0O,EAAA,CAAO,IAAI,6CACV,SAAA1O,MAAC,QAAK,UAAU,0DACd,SAAAA,MAAC+B,GAAA,CAAI,UAAU,cAAc,EAC/B,EACF,EAED0G,EAAE,QAAU,YACXzI,MAAC0O,EAAA,CAAO,IAAI,0CACV,SAAA1O,MAAC+J,EAAA,CAAM,QAAQ,YAAY,KAAK,KAAK,UAAWrC,GAAW,kBAE3D,EACF,EAEDe,EAAE,QAAU,aACXzI,MAAC0O,EAAA,CAAO,IAAI,+CACV,SAAA1O,MAAC+J,EAAA,CAAM,QAAQ,YAAY,KAAK,KAAK,UAAWxC,EAAc,mBAE9D,EACF,EAEDkB,EAAE,QACDzI,MAAC0O,EAAA,CAAO,IAAI,sCACV,SAAA1O,MAAC+J,EAAA,CAAM,QAAQ,YAAY,KAAK,KAAK,eAErC,EACF,EAEDtB,EAAE,mBACDzI,MAAC0O,EAAA,CACC,IACEpN,OAAA2N,WAAA,CAAE,2BACcjP,MAAC,QAAK,UAAU,YAAa,WAAE,kBAAkB,GACjE,EAGF,eAAC+J,EAAA,CAAM,QAAQ,UAAU,KAAK,KAC3B,WAAE,kBACL,IAGJzI,OAAC,QAAK,UAAU,oGACd,UAAAtB,MAAC0O,EAAA,CAAO,IAAKpN,OAAA2N,WAAA,CAAE,4BAAgBpH,EAAQY,EAAE,YAAY,GAAE,EACrD,gBAAC,QACC,UAAAzI,MAAC,QAAK,UAAU,2BAA2B,aAAC,EAC3C6H,EAAQY,EAAE,YAAY,GACzB,EACF,EACAzI,MAAC0O,EAAA,CAAO,IAAKpN,OAAA2N,WAAA,CAAE,6BAAiBpH,EAAQY,EAAE,aAAa,GAAE,EACvD,gBAAC,QACC,UAAAzI,MAAC,QAAK,UAAU,2BAA2B,aAAC,EAC3C6H,EAAQY,EAAE,aAAa,GAC1B,EACF,EACAzI,MAAC0O,EAAA,CACC,IACEjG,EAAE,WACE,WAAW,IAAI,KAAKA,EAAE,UAAU,EAAE,gBAAgB,GAChDA,EAAE,YAAc,eAAe,IAAI,KAAKA,EAAE,WAAW,EAAE,gBAAgB,GAAK,EAC9E,GACA,0BAGN,eAAC,QAAK,UAAU,2BAA4B,SAAAE,GAAQF,EAAE,UAAU,EAAE,GACpE,EACF,GACF,EAGAzI,MAAC0O,EAAA,CACC,IACEpN,OAAC,QAAK,UAAU,sBACb,UAAAmH,EAAE,KACFA,EAAE,MAAQ,MAAMA,EAAE,KAAK,GAAK,IAC/B,EAGF,SAAAnH,OAAC,OAAI,UAAU,qDACZ,UAAAmH,EAAE,KACFA,EAAE,OAASnH,OAAC,QAAK,UAAU,wBAAwB,gBAAImH,EAAE,OAAM,GAClE,IAIFnH,OAAC,OAAI,UAAU,gFACZ,UAAA+M,GAAaW,GAAW,KACvBhP,MAAC0O,EAAA,CAAO,IAAI,mDACV,SAAApN,OAAC,QAAK,UAAU,mDACd,UAAAtB,MAAC,QACC,UAAU,iEACV,cAAW,KAEZwO,GAAOQ,CAAO,GACjB,EACF,EAEAhP,MAAC0O,EAAA,CAAO,IAAKpN,OAAA2N,WAAA,CAAE,0BAAchH,EAAQQ,EAAE,WAAW,GAAK,KAAI,EACzD,eAAC,QAAM,SAAAR,EAAQQ,EAAE,WAAW,GAAK,IAAI,EACvC,GAEA,CAAC4F,GAAa5F,EAAE,SAAW,aAC1BiG,EAAA,CAAO,IAAI,0DACV,SAAApN,OAAC,QAAK,kBAAM6G,GAAQM,EAAE,OAAO,GAAE,EACjC,EAEFzI,MAAC0O,EAAA,CACC,IACEjG,EAAE,KAAO,KACLA,EAAE,cACA,6CACAA,EAAE,eAAiB,MAAQA,EAAE,eAAiB,EAC5C,uCACA,mEACJ,6CAGN,gBAAC,QAAM,UAAAL,GAAOK,EAAE,GAAG,EAAE,QAAI,IAE3BzI,MAAC0O,EAAA,CAAO,IAAI,+DACV,gBAAC,QAAK,gBAAI1G,GAAiBS,EAAE,kBAAkB,GAAE,EACnD,EACAzI,MAAC0O,EAAA,CAAO,IAAI,mDACV,gBAAC,QAAK,iBAAK1G,GAAiBS,EAAE,mBAAmB,GAAE,EACrD,EACAzI,MAAC0O,EAAA,CAAO,IAAI,kDACV,gBAAC,QAAK,mBAAOpG,GAAYG,EAAE,kBAAmBA,EAAE,kBAAkB,GAAE,EACtE,GACF,IAGN,CClPA,MAAMyG,GAAgE,CACpE,WAAYzH,GACZ,WAAYC,GACZ,QAAS,MACX,EAEMyH,GAAuC,CAC3C,OAAQ,4CACR,KAAM,oDACN,UAAW,8CACb,EAEMC,GAA2C,CAC/C,KAAM,mBACN,UAAW,wBACX,OAAQ,cACV,EAEMC,GAAkD,CACtD,KAAMC,GACN,UAAWC,GACX,OAAQC,EACV,EAEO,SAASC,GAAW,CAAE,MAAAC,GAAsC,CACjE,GAAI,CAACA,EAAO,OAAO,KAEnB,MAAMC,EAAMD,EAAM,QAAU,EAAKA,EAAM,OAASA,EAAM,QAAW,IAAM,EACjEE,EAAYF,EAAM,OAAS,UAAY,SAAWA,EAAM,KAE9D,OACEpO,OAAC,OAAI,UAAU,2CACb,UAAAA,OAAC,OAAI,UAAU,oCACb,UAAAA,OAAC,OAAI,UAAU,2CACb,UAAAA,OAACd,EAAA,CACC,UAAAR,MAACU,GAAe,OAAQV,MAAC,QAAK,UAAU,cAAc,EACpD,SAAAA,MAAC+J,EAAA,CAAM,QAAQ,YAAY,UAAWmF,GAAeQ,EAAM,IAAI,EAC5D,WACH,EACF,EACA1P,MAACe,EAAA,CAAe,KAAK,SAAS,UAAU,gBACrC,SAAA2O,EAAM,OAAS,WACZ,6CACAA,EAAM,OAAS,WACb,8CACA,kDACR,GACF,SACClP,EAAA,CACC,UAAAc,OAACZ,GAAe,OAAQV,MAAC,QAAK,UAAU,cAAc,EACpD,UAAAsB,OAAC,QAAK,UAAWnC,EAAG,YAAauQ,EAAM,UAAY,QAAU,kBAAkB,EAC5E,UAAAA,EAAM,OAAO,IAAEA,EAAM,SACxB,EACA1P,MAAC,QAAK,UAAU,6BAA6B,oBAAQ,GACvD,EACAsB,OAACP,EAAA,CAAe,KAAK,SAClB,UAAA2O,EAAM,OAAO,aAAWA,EAAM,QAAQ,eAAaA,EAAM,UAAU,eACtE,GACF,EACCA,EAAM,OAAS,GACdpO,OAAA2N,WAAA,CACE,UAAAjP,MAAC,QAAK,UAAU,kCAAmC,SAAA0P,EAAM,OAAO,EAChE1P,MAAC,QAAK,UAAU,wBAAwB,kBAAM,GAChD,EAEFA,MAAC,QAAK,UAAU,wBAAwB,aAAC,SACxCQ,EAAA,CACC,UAAAR,MAACU,EAAA,CACC,OAAQV,MAAC,QAAK,UAAU,6CAA6C,EAEnE,cAAM,CACN,MAAM6P,EAAOR,GAAYK,EAAM,OAAO,GAAKH,GAC3C,OACEvP,MAAC6P,EAAA,CACC,cAAW,GACX,UAAW1Q,EACT,cACAiQ,GAAiBM,EAAM,OAAO,GAAK,wBACrC,EAGN,IAAG,GAEL1P,MAACe,EAAA,CAAe,KAAK,SAAS,UAAU,gBACrC,SAAAoO,GAAaO,EAAM,OAAO,GAAKA,EAAM,QACxC,GACF,EACCA,EAAM,OACLpO,OAACd,EAAA,CACC,UAAAR,MAACU,EAAA,CAAe,OAAQV,MAAC,QAAK,UAAU,cAAc,EACpD,SAAAsB,OAACyI,EAAA,CAAM,QAAQ,cAAc,kBACrB2F,EAAM,YAAc,KAAKA,EAAM,WAAW,GAAK,IACvD,EACF,EACApO,OAACP,EAAA,CAAe,KAAK,SAAS,UAAU,gBAAgB,2CAErD2O,EAAM,YAAc,MAAMA,EAAM,WAAW,GAAK,IACnD,GACF,EAED,CAACA,EAAM,SACNpO,OAACd,EAAA,CACC,UAAAR,MAACU,EAAA,CAAe,OAAQV,MAAC,QAAK,UAAU,cAAc,EACpD,SAAAA,MAAC+J,EAAA,CAAM,QAAQ,YAAY,UAAWvC,EAAc,wBAEpD,EACF,QACCzG,EAAA,CAAe,KAAK,SAAS,UAAU,gBAAgB,2EAExD,GACF,GAEJ,SACCP,EAAA,CACC,UAAAR,MAACU,GAAe,OAAQV,MAAC,QAAK,UAAU,cAAc,EACpD,SAAAA,MAAC+J,EAAA,CACC,QAAS2F,EAAM,aAAe,cAAgB,YAC9C,UACEA,EAAM,aAAe,OAAYA,EAAM,YAAclI,EAAeD,EAGrE,SAAAmI,EAAM,aAAe,UAAYA,EAAM,YAAc,MAAQ,SAElE,EACA1P,MAACe,GAAe,KAAK,SAAS,UAAU,gBACtC,SAAAO,OAAC,OAAI,UAAU,YACb,UAAAA,OAAC,KAAE,uBAAWoO,EAAM,aAAe,UAAYA,EAAM,YAAc,MAAQ,QAAO,EACjFA,EAAM,OAASA,EAAM,aAAe,MACnCpO,OAAC,KAAE,UAAU,wBAAwB,yBAAauH,GAAY6G,EAAM,UAAU,GAAE,EAEjFA,EAAM,eAAiB,MACtBpO,OAAC,KAAE,UAAU,wBAAwB,2BACpBuH,GAAY6G,EAAM,YAAY,GAC/C,GAEJ,EACF,GACF,GACF,EAEA1P,MAAC,OAAI,UAAU,yDACb,SAAAA,MAAC,OACC,UAAWb,EAAG,wBAAyBwQ,GAAO,IAAM,iBAAmB,YAAY,EACnF,MAAO,CAAE,MAAO,GAAG,KAAK,IAAI,IAAKA,CAAG,CAAC,IAAI,GAE7C,EAECD,EAAM,gBAAkB,MACvBpO,OAAC,OAAI,UAAU,qDACb,UAAAA,OAAC,QAAK,uBACOoO,EAAM,iBAChBA,EAAM,cAAgB,MAAMA,EAAM,aAAa,GAAK,IACvD,EACCA,EAAM,oBAAsB,MAAQpO,OAAC,QAAK,cAAEoO,EAAM,kBAAkB,eAAW,EAC/EA,EAAM,eAAiBpO,OAAC,QAAK,eAAG,KAAK,MAAMoO,EAAM,cAAgB,IAAI,EAAE,YAAQ,GAClF,GAEJ,CAEJ,CCrKA,MAAMI,GAAQ7I,OAAK,IAAA8I,EAAA,IAAM,OAAO,qBAAuB,8BAAE,KAAM7I,IAAO,CAAE,QAASA,EAAE,OAAQ,CAAC,EACtF8I,GAAe/I,OAAK,UACxB,OAAO,qBAAuB,8BAAE,KAAMC,IAAO,CAAE,QAASA,EAAE,cAAe,CAC3E,EAQM+I,GAAsBzM,gBAA+C,IAAI,EAEzE0M,GAAwC,CAC5C,WAAY,IAAM,CAAC,EACnB,YAAa,IAAM,CAAC,EACpB,OAAQ,EACV,EAEO,SAASC,IAA4C,CAE1D,OADYvM,aAAWqM,EAAmB,GAC5BC,EAChB,CAMO,SAASE,GAAqB,CAAE,SAAAzP,GAAuC,CAC5E,KAAM,CAAC0P,EAAMC,CAAO,EAAI1O,WAAS,EAAK,EAEhCmG,EAAkC,CACtC,WAAY,IAAMuI,EAAQ,EAAI,EAC9B,YAAa,IAAMA,EAAQ,EAAK,EAChC,OAAQD,CAAA,EAGV,OAAOrQ,MAACiQ,GAAoB,SAApB,CAA6B,MAAAlI,EAAe,SAAApH,CAAA,CAAS,CAC/D,CASO,SAAS4P,GAAmB,CACjC,OAAAC,EACA,OAAAC,EACA,gBAAAC,EACA,gBAAAC,CACF,EAA4B,CAC1B,KAAM,CAAE,OAAAC,EAAQ,YAAAC,CAAA,EAAgBV,GAAA,EAEhC,OACE7O,OAAA2N,WAAA,CACE,UAAA3N,OAAC,OAAI,UAAU,cACb,UAAAtB,MAAC,SAAM,aAAY0Q,EAAiB,UAAU,oCAC3C,SAAAF,EACH,QACC,OAAI,UAAU,sBAAsB,aAAYG,EAC9C,SAAAF,CAAA,CACH,GACF,EACCG,GACC5Q,MAACiO,WAAA,CAAS,SAAU,KAClB,SAAAjO,MAAC8P,GAAA,CACC,KAAMc,EACN,aAAe,GAAM,CACd,GAAGC,EAAA,CACV,EAEA,SAAA7Q,MAACgQ,GAAA,CACC,KAAK,OACL,aAAYU,EACZ,UAAU,gGAET,SAAAF,CAAA,EACH,EACF,CACF,GAEJ,CAEJ,CCvEA,MAAMM,GAAuB,IAEtB,SAASC,GAAkB,CAChC,SAAAC,EACA,WAAAC,EACA,WAAAC,EACA,cAAAC,CACF,EAAsD,CACpD,MAAM3H,EAAQwH,EAAS,OACjB,CAACI,EAAaC,CAAc,EAAIzP,WAAS,CAAC,EAC1C0P,EAAehL,SAGlB,CAAE,MAAO,GAAI,MAAO,OAAW,EAGlCvD,YAAU,IAAM,CACd,GAAIkO,IAAe,MAAQzH,IAAU,EAAG,OACxC,MAAM+H,EAAMP,EAAS,UAAWvI,GAAMA,EAAE,KAAOwI,CAAU,EACrDM,GAAO,GACTF,EAAeE,CAAG,CAEtB,EAAG,CAACN,EAAYzH,EAAOwH,CAAQ,CAAC,EAGhCjO,YAAU,IACD,IAAM,CACPuO,EAAa,QAAQ,OACvB,aAAaA,EAAa,QAAQ,KAAK,CAE3C,EACC,EAAE,EAEL,MAAME,EAAQ7O,cACX4O,GACK/H,IAAU,EAAU,GACjB,KAAK,IAAI,EAAG,KAAK,IAAI+H,EAAK/H,EAAQ,CAAC,CAAC,EAE7C,CAACA,CAAK,GAGFiI,EAAO9O,cACV4O,GAAgB,CACf,MAAMG,EAAUF,EAAMD,CAAG,EACrBG,EAAU,IACdL,EAAeK,CAAO,EACtBP,EAAcO,EAAS,CAAE,MAAO,OAAQ,EAC1C,EACA,CAACF,EAAOL,CAAa,GAGjBQ,EAAgBhP,cACnBG,GAA2B,CAC1B,GAAI0G,IAAU,EACd,OAAQ1G,EAAE,KACR,IAAK,YACHA,EAAE,iBACF2O,EAAKL,EAAc,CAAC,EACpB,MACF,IAAK,UACHtO,EAAE,iBACF2O,EAAKL,EAAc,CAAC,EACpB,MACF,IAAK,OACHtO,EAAE,iBACF2O,EAAK,CAAC,EACN,MACF,IAAK,MACH3O,EAAE,iBACF2O,EAAKjI,EAAQ,CAAC,EACd,MACF,IAAK,QACL,IAAK,IACH1G,EAAE,iBACEsO,GAAe,GAAKA,EAAc5H,GACpC0H,EAAWF,EAASI,CAAW,EAAE,EAAE,EAErC,MACF,QAAS,CAEP,GAAItO,EAAE,IAAI,SAAW,GAAK,eAAe,KAAKA,EAAE,GAAG,EAAG,CACpD,MAAM8O,EAAO9O,EAAE,IAAI,cACb+O,EAAUP,EAAa,QAC7BO,EAAQ,OAASD,EACbC,EAAQ,OAAO,aAAaA,EAAQ,KAAK,EAC7CA,EAAQ,MAAQ,WAAW,IAAM,CAC/BP,EAAa,QAAQ,MAAQ,EAC/B,EAAGR,EAAoB,EAEvB,MAAMgB,EAAYD,EAAQ,MAC1B,QAASE,EAAI,EAAGA,EAAIvI,EAAOuI,IACzB,GAAIf,EAASe,CAAC,EAAE,KAAK,cAAc,WAAWD,CAAS,EAAG,CACxDL,EAAKM,CAAC,EACN,KACF,CAEJ,CACA,KACF,EAEJ,EACA,CAACvI,EAAO4H,EAAaK,EAAMP,EAAYF,CAAQ,GAG3CgB,EAAiBrP,cACpBsP,GAAkB,CACbA,EAAQ,GAAKA,GAASzI,IAC1B6H,EAAeY,CAAK,EACpBf,EAAWF,EAASiB,CAAK,EAAE,EAAE,EAC/B,EACA,CAACf,EAAYF,EAAUxH,CAAK,GAGxB0I,EAAkB1I,IAAU,EAAI,GAAK,KAAK,IAAI4H,EAAa5H,EAAQ,CAAC,EACpE2I,EACJD,GAAmB,EAAI,eAAelB,EAASkB,CAAe,EAAE,EAAE,GAAK,OAEzE,MAAO,CACL,YAAaA,EACb,eAAAC,EACA,cAAAR,EACA,eAAAK,CAAA,CAEJ,CC5HA,MAAMI,GAAqBnL,OAAK,UAC9B,OAAO,oCAAmC,gCAAE,KAAMC,IAAO,CACvD,QAASA,EAAE,oBACX,CACJ,EAmBMmL,GAAa,GAEZ,SAASC,GAAY,CAC1B,SAAAtB,EACA,WAAAC,EACA,QAAAsB,EACA,UAAAC,EACA,UAAAC,EACA,UAAA/F,EACA,SAAAgG,EACA,QAAAC,EACA,QAAA7F,CACF,EAAqB,CACnB,MAAM3B,EAAc7E,SAAuB,IAAI,EACzC,CAAE,YAAAuK,EAAa,OAAAD,CAAA,EAAWT,GAAA,EAC1B,CAACyC,EAAaC,CAAc,EAAIjR,WAAS,EAAK,EAE9CkR,EAAcC,GAAe,CACjC,MAAO/B,EAAS,OAChB,iBAAkB,IAAM7F,EAAY,QACpC,aAAc,IAAMkH,GACpB,SAAU,EACX,EAEKW,EAAcF,EAAY,eAC1BG,EAAQH,EAAY,kBAEpBI,EAAgBjO,GAAe,CACnCyN,EAASzN,CAAE,EACX4L,EAAA,CACF,EAEM,CAAE,YAAAO,EAAa,eAAAe,EAAgB,cAAAR,EAAe,eAAAK,CAAA,EAAmBjB,GAAkB,CACvF,SAAAC,EACA,WAAAC,EACA,WAAYiC,EACZ,cAAeJ,EAAY,cAC5B,EAED,OACExR,OAAC,SAAM,UAAU,qEACf,UAAAA,OAAC,UACC,UAAWnC,EACT,6EACAyR,GAAU,SAGZ,UAAAtP,OAAC,MAAG,UAAU,wBAAwB,sBAC3BA,OAAC,QAAK,UAAU,wBAAwB,cAAE0P,EAAS,OAAO,KAAC,GACtE,EACAhR,MAAC,OAAI,UAAU,0BACb,gBAACQ,EAAA,CACC,UAAAR,MAACU,EAAA,CAAe,QAAO,GACrB,SAAAY,OAAC7B,EAAA,CAAO,QAAQ,UAAU,KAAK,KAAK,QAAS,IAAMoT,EAAe,EAAI,EACpE,UAAA7S,MAACmT,GAAA,CAAO,UAAU,qBAAqB,EAAE,SAE3C,EACF,EACAnT,MAACe,EAAA,CAAe,KAAK,SAAS,wCAA4B,GAC5D,EACF,KAGFf,MAACyP,GAAA,CAAW,MAAO+C,CAAA,CAAW,EAE7BD,IAAY,QAAUvB,EAAS,OAAS,GACvC1P,OAAC,UACC,YAAU,SACV,UAAU,6EAEV,UAAAtB,MAAC,QAAK,UAAU,4DAA4D,cAAW,GAAC,EAAE,uBACrEuS,IAAY,OAAS,eAAiB,kBAI9DvB,EAAS,SAAW,EACnByB,EACEnR,OAAC,WACC,aAAW,WACX,UAAU,+FAEV,UAAAtB,MAAC4N,GAAA,CAAY,UAAU,6BAA6B,EACpD5N,MAAC,KAAE,UAAU,uCAAuC,gCAAoB,EACxEA,MAAC,KAAE,UAAU,UAAW,SAAAyS,EAAU,SACjCjS,EAAA,CACC,UAAAR,MAACU,EAAA,CAAe,QAAO,GACrB,SAAAY,OAAC7B,EAAA,CAAO,QAAQ,UAAU,KAAK,KAAK,QAASqN,EAC3C,UAAA9M,MAAC6N,GAAA,CAAU,UAAU,qBAAqB,EAAE,SAE9C,EACF,EACA7N,MAACe,EAAA,CAAe,KAAK,MAAM,kCAAsB,GACnD,KAEA2L,EACF1M,MAAC,WACC,aAAW,WACX,UAAU,mEAEV,SAAAA,MAACiL,EAAA,CAAO,UAAU,SAAS,IAG7B3J,OAAC,WACC,aAAW,WACX,UAAU,+FAEV,UAAAtB,MAACoT,GAAA,CAAM,UAAU,qCAAqC,EACtDpT,MAAC,KAAE,UAAU,sBAAsB,2BAAe,EAClDA,MAAC,KAAE,UAAU,UAAU,4DAAgD,KAI3EA,MAACkL,GAAA,CACC,UAAU,oHACV,YAAAC,EAEA,KAAK,UACL,aAAW,WACX,wBAAuBgH,EACvB,SAAU,EACV,UAAWR,EAEX,SAAA3R,MAAC,OACC,UAAWb,EAAG,WAAYoT,IAAY,QAAUvB,EAAS,OAAS,GAAK,YAAY,EACnF,MAAO,CAAE,OAAQgC,CAAA,EAEhB,SAAAC,EAAM,IAAKI,GAAe,CACzB,MAAM5K,EAAIuI,EAASqC,EAAW,KAAK,EACnC,OAAK5K,EAEHzI,MAAC,OAEC,aAAYqT,EAAW,MACvB,MAAO,CACL,SAAU,WACV,IAAK,EACL,KAAM,EACN,MAAO,OACP,OAAQA,EAAW,KACnB,UAAW,cAAcA,EAAW,KAAK,OAG3C,SAAArT,MAAC2O,GAAA,CACC,QAASlG,EACT,SAAUA,EAAE,KAAOwI,EACnB,SAAUoC,EAAW,QAAUjC,EAC/B,SAAU,eAAe3I,EAAE,EAAE,GAC7B,WAAY,IAAMuJ,EAAeqB,EAAW,KAAK,GACnD,EAjBK5K,EAAE,IAHI,IAuBjB,CAAC,GACH,GAIHmK,GACC5S,MAACiO,WAAA,CAAS,SAAU,KAClB,SAAAjO,MAACoS,GAAA,CACC,KAAMQ,EACN,MAAO5B,EAAS,OAChB,UAAW,IAAM,CACf6B,EAAe,EAAK,EACpBF,EAAA,CACF,EACA,QAAS,IAAME,EAAe,EAAK,GACrC,CACF,GAEJ,CAEJ,CCxMA,MAAMS,GAAS,CACb,KAAM,CACJ,MAAO,OACP,QAAS,YACT,UAAW/L,EACX,SAAUI,GACV,MAAO,GACP,IAAK,4BAEP,KAAM,CACJ,MAAO,eACP,QAAS,YACT,UAAWH,EACX,SAAUI,GACV,MAAO,GACP,IAAK,mCAEP,YAAa,CACX,MAAO,eACP,QAAS,cACT,UAAW,OACX,SAAU,iBACV,MAAO,GACP,IAAK,uCAET,EAEO,SAAS2L,GAAc,CAAE,QAAAhB,GAA+B,CAC7D,MAAMnQ,EAASkR,GAAOf,CAAO,EAE7B,cACG/R,EAAA,CACC,UAAAR,MAACU,EAAA,CACC,OACEV,MAAC,QACC,UAAU,6FACV,aAAY,cAAcoC,EAAO,KAAK,KAI1C,SAAAd,OAACyI,EAAA,CAAM,QAAS3H,EAAO,QAAS,KAAK,KAAK,UAAWjD,EAAG,QAASiD,EAAO,SAAS,EAC/E,UAAApC,MAAC,QACC,cAAW,GACX,UAAWb,EACT,wCACAiD,EAAO,SACPA,EAAO,OAAS,gBAClB,GAEDA,EAAO,OACV,IAEFpC,MAACe,EAAA,CAAe,KAAK,SAAU,WAAO,IAAI,GAC5C,CAEJ,CCtCO,SAASyS,IAA2C,CACzD,KAAM,CAACvC,EAAYwC,CAAa,EAAI7R,WAAwB,IAAI,EAC1D,CAAC8R,EAAiBC,CAAkB,EAAI/R,WAA+B,IAAI,EAC3E,CAACgS,EAAiBC,CAAkB,EAAIjS,WAAS,EAAK,EACtD,CAAC+K,EAAamH,CAAc,EAAIlS,WAAwB,IAAI,EAE5DmS,EAAqBzN,SAAOoN,CAAe,EACjDK,EAAmB,QAAUL,EAE7B,MAAMM,EAAgB1N,SAAO2K,CAAU,EACvC+C,EAAc,QAAU/C,EAExB,MAAMgD,EAAetR,cAAY,MAAOsC,GAAe,CACrD4O,EAAmB,EAAI,EACvB,GAAI,CACF,MAAMjR,EAAI,MAAM,MAAM,GAAGZ,CAAQ,aAAaiD,CAAE,EAAE,EAClD,GAAI,CAACrC,EAAE,GAAI,CACTkR,EAAe,QAAQlR,EAAE,MAAM,IAAIA,EAAE,UAAU,EAAE,EACjD,MACF,CAEA,GAAI,EADOA,EAAE,QAAQ,IAAI,cAAc,GAAK,IACpC,SAAS,kBAAkB,EAAG,CACpCkR,EAAe,uBAAuB,EACtC,MACF,CACA,MAAMrL,EAAK,MAAM7F,EAAE,OACnB+Q,EAAmBlL,CAAC,EACpBqL,EAAe,IAAI,CACrB,OAAShR,EAAG,CACVgR,EAAe,OAAOhR,CAAC,CAAC,CAC1B,SACE+Q,EAAmB,EAAK,CAC1B,CACF,EAAG,EAAE,EAECK,EAAgBvR,cACnBsC,GAAe,CACdwO,EAAcxO,CAAE,EAChB0O,EAAmB,IAAI,EACvBG,EAAe,IAAI,EACdG,EAAahP,CAAE,CACtB,EACA,CAACgP,CAAY,GAGTE,EAAcxR,cAAY,IAAM,CACpC,MAAMsC,EAAK+O,EAAc,QACrB/O,IAAO,MACJgP,EAAahP,CAAE,CAExB,EAAG,CAACgP,CAAY,CAAC,EAEXG,EAAiBzR,cAAY,IAAM,CACvC8Q,EAAc,IAAI,EAClBE,EAAmB,IAAI,CACzB,EAAG,EAAE,EAEL,MAAO,CACL,gBAAAD,EACA,mBAAAC,EACA,WAAA1C,EACA,cAAA+C,EACA,mBAAAD,EACA,gBAAAH,EACA,YAAAjH,EACA,cAAAuH,EACA,aAAAD,EACA,YAAAE,EACA,eAAAC,CAAA,CAEJ,CCnEO,SAASC,IAAuC,CACrD,KAAM,CAACrD,EAAUsD,CAAW,EAAI1S,WAA2B,EAAE,EACvD,CAAC2S,EAAeC,CAAgB,EAAI5S,WAAS,EAAI,EACjD,CAAC6Q,EAAWgC,CAAY,EAAI7S,WAAwB,IAAI,EACxD,CAAC8S,EAAkBC,CAAmB,EAAI/S,WAAS,EAAK,EAExDgT,EAAWjS,cAAY,SAAY,CACvC,GAAI,CACF,MAAMC,EAAI,MAAM,MAAM,GAAGZ,CAAQ,qBAAqB,EACtD,GAAI,CAACY,EAAE,GAAI,CACT6R,EAAa,QAAQ7R,EAAE,MAAM,IAAIA,EAAE,UAAU,EAAE,EAC/C+R,EAAoB,EAAK,EACzB,MACF,CAEA,GAAI,EADO/R,EAAE,QAAQ,IAAI,cAAc,GAAK,IACpC,SAAS,kBAAkB,EAAG,CACpC+R,EAAoB,EAAK,EACzB,MACF,CACA,MAAME,EAAQ,MAAMjS,EAAE,OACtBiS,EAAK,KAAK,CAACC,EAAGlL,IAAMA,EAAE,GAAKkL,EAAE,EAAE,EAC/BR,EAAYO,CAAI,EAChBJ,EAAa,IAAI,EACjBE,EAAoB,EAAI,CAC1B,OAAS7R,EAAG,CACV2R,EAAa,OAAO3R,CAAC,CAAC,EACtB6R,EAAoB,EAAK,CAC3B,SACEH,EAAiB,EAAK,CACxB,CACF,EAAG,EAAE,EAECO,EAAYpS,cAAY,IAAM,CAC7BiS,EAAA,CACP,EAAG,CAACA,CAAQ,CAAC,EAEb,MAAO,CACL,SAAA5D,EACA,YAAAsD,EACA,cAAAC,EACA,UAAA9B,EACA,iBAAAiC,EACA,SAAAE,EACA,UAAAG,CAAA,CAEJ,CCtEA,MAAMC,GAAS,GAAG,OAAO,SAAS,WAAa,SAAW,MAAQ,IAAI,MAAM,OAAO,SAAS,IAAI,gBAiCzF,SAASC,GAAkB,CAChC,iBAAAP,EACA,WAAAQ,EACA,YAAAC,EACA,eAAAC,EACA,cAAAC,EACA,eAAAC,EACA,YAAAC,EACA,gBAAAC,CACF,EAA4B,CAE1B,MAAMC,EAAiBnP,SAAO6O,CAAW,EACzCM,EAAe,QAAUN,EACzB,MAAMO,EAAoBpP,SAAO8O,CAAc,EAC/CM,EAAkB,QAAUN,EAC5B,MAAMO,EAAmBrP,SAAO+O,CAAa,EAC7CM,EAAiB,QAAUN,EAC3B,MAAMO,EAAoBtP,SAAOgP,CAAc,EAC/CM,EAAkB,QAAUN,EAC5B,MAAMO,EAAiBvP,SAAOiP,CAAW,EACzCM,EAAe,QAAUN,EACzB,MAAMO,EAAqBxP,SAAOkP,CAAe,EACjDM,EAAmB,QAAUN,EAE7BzS,YAAU,IAAM,CACd,GAAI,CAAC2R,EAAkB,CACrBQ,EAAW,aAAa,EACxB,MACF,CAEA,IAAIa,EAAuB,KACvBC,EAAY,GAGhB,MAAMC,EAAyB,CAC7B,MAAO,IAAMP,EAAkB,UAC/B,eAAgB,IAAMC,EAAiB,UACvC,MAAQO,GAAQN,EAAkB,QAAQM,EAAI,UAAWA,EAAI,KAAK,EAClE,KAAOA,GAAQL,EAAe,QAAQK,EAAI,KAAK,EAC/C,IAAMA,GAAQJ,EAAmB,QAAQI,EAAI,QAAS,EAAI,EAC1D,OAASA,GAAQJ,EAAmB,QAAQI,EAAI,QAAS,EAAK,GAGhE,SAASC,GAAU,CACjB,GAAI,CACFJ,EAAK,IAAI,UAAUf,EAAM,CAC3B,MAAQ,CACNE,EAAW,aAAa,EACxB,MACF,CAEAa,EAAG,OAAS,IAAM,CAChBb,EAAW,MAAM,EACZO,EAAe,SACtB,EAEAM,EAAG,UAAaK,GAAgC,CAC9C,GAAI,CACF,MAAMF,EAAM,KAAK,MAAME,EAAM,IAAI,EAI3BC,EAAUJ,EAASC,EAAI,IAAI,EACjCG,EAAQH,CAAG,CACb,OAASpT,EAAG,CACV,QAAQ,MAAMA,CAAC,CACjB,CACF,EAEAiT,EAAG,QAAU,IAAM,CACjBb,EAAW,MAAM,EACZc,GACH,WAAWG,EAAS,GAAI,CAE5B,EAEAJ,EAAG,QAAU,IAAM,CACjBA,GAAA,MAAAA,EAAI,OACN,CACF,CAEA,OAAAI,EAAA,EAEO,IAAM,CACXH,EAAY,GACZD,GAAA,MAAAA,EAAI,OACN,CACF,EAAG,CAACrB,EAAkBQ,CAAU,CAAC,CACnC,CC1GO,SAASoB,IAAmC,CACjD,KAAM,CAAC9D,EAAW+D,CAAY,EAAI3U,WAA2B,IAAI,EAC3D,CAAC4U,EAAWC,CAAY,EAAI7U,WAAwB,IAAI,EAExD8U,EAAW/T,cAAY,SAAY,CACvC,GAAI,CACF,MAAMC,EAAI,MAAM,MAAM,GAAGZ,CAAQ,OAAO,EACxC,GAAI,CAACY,EAAE,GAAI,CACT6T,EAAa,QAAQ7T,EAAE,MAAM,IAAIA,EAAE,UAAU,EAAE,EAC/C,MACF,CAEA,GAAI,EADOA,EAAE,QAAQ,IAAI,cAAc,GAAK,IACpC,SAAS,kBAAkB,EACjC,OAEF2T,EAAc,MAAM3T,EAAE,MAAoB,EAC1C6T,EAAa,IAAI,CACnB,OAAS3T,EAAG,CACV2T,EAAa,OAAO3T,CAAC,CAAC,CACxB,CACF,EAAG,EAAE,EAEC6T,EAAYhU,cAAY,IAAM,CAC7B+T,EAAA,CACP,EAAG,CAACA,CAAQ,CAAC,EAEb,MAAO,CACL,UAAAlE,EACA,aAAA+D,EACA,UAAAC,EACA,SAAAE,EACA,UAAAC,CAAA,CAEJ,CCzBO,SAASC,IAAiC,CAC/C,KAAM,CAAE,SAAA5F,EAAU,YAAAsD,EAAa,cAAAC,EAAe,UAAA9B,EAAW,iBAAAiC,EAAkB,SAAAE,EAAU,UAAAG,CAAA,EACnFV,GAAA,EAEI,CACJ,gBAAAX,EACA,WAAAzC,EACA,cAAA+C,EACA,mBAAAD,EACA,gBAAAH,EACA,YAAAjH,EACA,cAAAuH,EACA,aAAAD,EACA,YAAAE,EACA,eAAAC,CAAA,EACEZ,GAAA,EAEE,CAAE,UAAAhB,EAAW,aAAA+D,EAAc,UAAAC,EAAW,SAAAE,EAAU,UAAAC,CAAA,EAAcL,GAAA,EAE9D,CAAC/D,EAAS2C,CAAU,EAAItT,WAA0C,MAAM,EAG9EmB,YAAU,IAAM,CACT6R,EAAA,EACA8B,EAAA,CACP,EAAG,CAAC9B,EAAU8B,CAAQ,CAAC,EAEvBzB,GAAkB,CAChB,iBAAAP,EACA,WAAAQ,EACA,YAAa,IAAM,CACZN,EAAA,EACA8B,EAAA,CACP,EACA,eAAgB,IAAM,CACpBpC,EAAY,EAAE,CAChB,EACA,cAAe,IAAM,CACnBA,EAAauC,GAASA,EAAK,OAAQpO,GAAM,CAACA,EAAE,SAAS,CAAC,CACxD,EACA,eAAgB,CAACqO,EAAWC,IAAU,CACpCzC,EAAauC,GAAS,CACpB,MAAM9E,EAAI8E,EAAK,UAAWpO,GAAMA,EAAE,KAAOqO,CAAS,EAClD,GAAI/E,EAAI,EAAG,OAAO8E,EAClB,MAAMG,EAAOH,EAAK,QAClB,OAAAG,EAAKjF,CAAC,EAAI,CAAE,GAAGiF,EAAKjF,CAAC,EAAG,MAAAgF,CAAA,EACjBC,CACT,CAAC,CACH,EACA,YAActH,GAAU,CACtB6G,EAAa7G,CAAK,CACpB,EACA,gBAAiB,CAACjD,EAASwK,IAAU,OACnC3C,EAAauC,GAAS,CACpB,MAAM9E,EAAI8E,EAAK,UAAWK,GAAMA,EAAE,KAAOzK,EAAQ,EAAE,EACnD,GAAIsF,GAAK,EAAG,CACV,MAAMiF,EAAOH,EAAK,QAClB,OAAAG,EAAKjF,CAAC,EAAItF,EACHuK,CACT,CAEA,MAAO,CAACvK,EAAS,GAAGoK,CAAI,CAC1B,CAAC,EAEG,CAACI,GAASxK,EAAQ,QAAU,SAC9B,OAAO,cAAc,IAAI,YAAYvK,EAAkB,CAAC,EAGtDuK,EAAQ,KAAOuH,EAAc,WAC7BmD,EAAApD,EAAmB,UAAnB,YAAAoD,EAA4B,SAAU,aAEjClD,EAAaxH,EAAQ,EAAE,EAGlC,EACD,EAED,MAAM2K,GAAgBzU,cAAY,SAAY,CAC5C,GAAI,CACF,MAAM,MAAM,GAAGX,CAAQ,SAAU,CAAE,OAAQ,OAAQ,EACnDsS,EAAY,EAAE,EACdF,EAAA,CACF,OAAStR,EAAG,CACV,QAAQ,MAAMA,CAAC,CACjB,CACF,EAAG,CAACwR,EAAaF,CAAc,CAAC,EAEhC,MAAO,CACL,SAAApD,EACA,gBAAA0C,EACA,gBAAAE,EACA,cAAAW,EACA,QAAAhC,EACA,WAAAtB,EACA,UAAAuB,EACA,UAAAC,EACA,UAAA+D,EACA,YAAA7J,EACA,cAAAuH,EACA,cAAAkD,GACA,UAAArC,EACA,UAAA4B,EACA,YAAAxC,CAAA,CAEJ,CCjIO,SAASkD,IAEd,CA6BA,MAAO,CAAE,SA5BQ1U,cAAY,MAAO2U,GAAmC,CACrE,GAAI,CACF,GAAI,UAAU,WAAa,OAAO,gBAChC,aAAM,UAAU,UAAU,UAAUA,CAAI,EACjC,EAEX,MAAQ,CAER,CAEA,MAAMC,EAAK,SAAS,cAAc,UAAU,EAC5CA,EAAG,MAAQD,EACXC,EAAG,MAAM,SAAW,QACpBA,EAAG,MAAM,IAAM,UACf,SAAS,KAAK,YAAYA,CAAE,EAC5BA,EAAG,QACHA,EAAG,SAEH,IAAI9J,EAAK,GACT,GAAI,CACFA,EAAK,SAAS,YAAY,MAAM,CAClC,MAAQ,CAER,CACA,gBAAS,KAAK,YAAY8J,CAAE,EACrB9J,CACT,EAAG,EAAE,CAEI,CACX,CCbA,MAAM+J,GAAYvQ,OAAK,UACrB,OAAO,0BAAyB,4CAAE,KAAMC,IAAO,CAAE,QAASA,EAAE,WAAY,CAC1E,EACMuQ,GAAYxQ,OAAK,UACrB,OAAO,0BAAyB,wCAAE,KAAMC,IAAO,CAAE,QAASA,EAAE,WAAY,CAC1E,EACMwQ,GAAmBzQ,OAAK,UAC5B,OAAO,iCAAgC,qCAAE,KAAMC,IAAO,CAAE,QAASA,EAAE,kBAAmB,CACxF,EACMyQ,GAAe1Q,OAAK,UACxB,OAAO,6BAA4B,qCAAE,KAAMC,IAAO,CAAE,QAASA,EAAE,cAAe,CAChF,EACM0Q,GAAc3Q,OAAK,UACvB,OAAO,4BAA2B,qCAAE,KAAMC,IAAO,CAAE,QAASA,EAAE,aAAc,CAC9E,EACM2Q,GAAa5Q,OAAK,UACtB,OAAO,2BAA0B,+BAAE,KAAMC,IAAO,CAAE,QAASA,EAAE,YAAa,CAC5E,EACM4Q,GAAU7Q,OAAK,IAAA8I,EAAA,IAAM,OAAO,sBAAwB,+BAAE,KAAM7I,IAAO,CAAE,QAASA,EAAE,SAAU,CAAC,EAEjG,SAAS6Q,GAAmB,CAC1B,aAAQ9M,EAAA,EAAO,CACjB,CASA,SAAS+M,EAAkB,CAAE,MAAAjQ,EAAO,MAAA8C,EAAO,IAAAF,GAAoB,CAC7D,cACGnK,EAAA,CACC,UAAAR,MAACU,EAAA,CAAe,OAAQV,MAAC,SAAK,EAC5B,SAAAA,MAACiM,GAAA,CAAY,MAAAlE,EAAe,SAAA8C,CAAA,CAAM,EACpC,EACA7K,MAACe,EAAA,CAAe,KAAK,SAAU,SAAA4J,CAAA,CAAI,GACrC,CAEJ,CAEO,SAASsN,IAAM,CACpB,KAAM,CACJ,SAAAjH,EACA,gBAAA0C,EACA,gBAAAE,EACA,cAAAW,EACA,QAAAhC,EACA,WAAAtB,EACA,UAAAuB,EACA,UAAAC,EACA,YAAA9F,EACA,cAAAuH,EACA,cAAAkD,EACA,UAAArC,EACA,YAAAZ,CAAA,EACEyC,GAAA,EAEE,CAAE,SAAAsB,CAAA,EAAab,GAAA,EACf,CAACpK,EAAYC,CAAa,EAAItL,WAAS,MAAM,EAEnD,aACG6B,GAAA,CACC,SAAAzD,MAACK,IAAgB,MAAO,IACtB,gBAAC+P,GAAA,CACC,UAAApQ,MAAC+F,GAAA,EAAW,EACZzE,OAAC,OAAI,UAAU,uEACb,UAAAtB,MAAC,KACC,KAAK,QACL,UAAU,2NACX,6BAGDA,MAAC,MAAG,UAAU,UAAU,sBAAU,EAClCsB,OAACqK,GAAA,CAAK,aAAa,WAAW,UAAU,uCACtC,UAAArK,OAAC,UAAO,UAAU,2DAChB,UAAAtB,MAACmY,GAAA,EAAoB,EACrBnY,MAACuT,IAAc,QAAAhB,EAAkB,QAChC,OAAI,UAAU,6EACb,SAAAjR,OAACwK,GAAA,CAAS,UAAU,iCAClB,UAAA9L,MAACgY,EAAA,CACC,MAAM,WACN,MAAM,WACN,IAAI,2CAENhY,MAACgY,EAAA,CACC,MAAM,SACN,MAAM,eACN,IAAI,gDAENhY,MAACgY,EAAA,CACC,MAAM,cACN,MAAM,cACN,IAAI,8CAENhY,MAACgY,EAAA,CACC,MAAM,YACN,MAAM,YACN,IAAI,+CAENhY,MAACgY,EAAA,CACC,MAAM,SACN,MAAM,SACN,IAAI,wCAENhY,MAACgY,EAAA,CACC,MAAM,SACN,MAAM,SACN,IAAI,uCACN,EACF,EACF,QACC/J,WAAA,CAAS,SAAU,KAClB,SAAAjO,MAAC6X,KAAW,EACd,GACF,EACAvW,OAAC,QACC,GAAG,OACH,aAAW,YACX,UAAU,uCAEV,UAAAtB,MAACmM,GAAY,MAAM,WAAW,UAAU,yBAAyB,YAAW,GAC1E,SAAAnM,MAACuQ,GAAA,CACC,OACEvQ,MAACsS,GAAA,CACC,SAAAtB,EACA,WAAAC,EACA,QAAAsB,EACA,UAAAC,EACA,UAAAC,EACA,UAAW8B,EACX,SAAUL,EACV,QAASkD,EACT,QAASrC,CAAA,GAGb,OACE/U,MAACwM,GAAA,CACC,QAASkH,EACT,UAAWE,EACX,YAAAjH,EACA,OAAQuL,EACR,aAAchL,EACd,QAASiH,CAAA,GAGb,gBAAgB,gBAChB,gBAAgB,mBAEpB,QACChI,EAAA,CAAY,MAAM,SAAS,UAAU,iCAAiC,YAAW,GAChF,SAAAnM,MAACiO,WAAA,CAAS,SAAUjO,MAAC+X,EAAA,EAAiB,EACpC,SAAA/X,MAAC4X,GAAA,EAAY,EACf,EACF,EACA5X,MAACmM,EAAA,CACC,MAAM,cACN,UAAU,iCACV,YAAW,GAEX,SAAAnM,MAACiO,YAAS,SAAUjO,MAAC+X,IAAiB,EACpC,SAAA/X,MAAC0X,KAAiB,EACpB,UAEDvL,EAAA,CAAY,MAAM,SAAS,UAAU,iCAAiC,YAAW,GAChF,SAAAnM,MAACiO,WAAA,CAAS,SAAUjO,MAAC+X,EAAA,EAAiB,EACpC,SAAA/X,MAACyX,GAAA,EAAU,EACb,EACF,EACAzX,MAACmM,EAAA,CACC,MAAM,YACN,UAAU,iCACV,YAAW,GAEX,SAAAnM,MAACiO,YAAS,SAAUjO,MAAC+X,IAAiB,EACpC,SAAA/X,MAAC2X,KAAa,EAChB,UAEDxL,EAAA,CAAY,MAAM,SAAS,UAAU,iCAAiC,YAAW,GAChF,SAAAnM,MAACiO,WAAA,CAAS,SAAUjO,MAAC+X,EAAA,EAAiB,EACpC,SAAA/X,MAACwX,GAAA,EAAU,EACb,EACF,IACF,EACF,QACCvJ,WAAA,CAAS,SAAU,KAClB,SAAAjO,MAAC8X,KAAQ,EACX,QACC,UAAO,YAAU,SAAS,UAAU,UAClC,SAAA7K,CAAA,CACH,GACF,GACF,EACF,EACF,CAEJ,CAEA,SAASkL,IAAsB,CAC7B,KAAM,CAAE,WAAAC,CAAA,EAAejI,GAAA,EACvB,cACG3P,EAAA,CACC,UAAAR,MAACU,EAAA,CAAe,QAAO,GACrB,SAAAV,MAACP,EAAA,CACC,QAAQ,QACR,KAAK,OACL,UAAU,YACV,aAAW,gBACX,QAAS2Y,EAET,SAAApY,MAACqY,GAAA,CAAK,UAAU,UAAU,IAE9B,EACArY,MAACe,EAAA,CAAe,KAAK,SAAS,8BAAkB,GAClD,CAEJ,CChOO,MAAMuX,WAAsBC,GAAM,SAAkD,CAApF,kCACLC,GAAA,aAA4B,CAAE,MAAO,OAErC,OAAO,yBAAyBhW,EAAkC,CAChE,MAAO,CAAE,MAAAA,CAAA,CACX,CAEA,QAA0B,CACxB,KAAM,CAAE,MAAAA,GAAU,KAAK,MACvB,OAAKA,EAKH,KAAK,MAAM,UACTlB,OAAC,OAAI,UAAU,wFACb,UAAAtB,MAAC,KAAE,UAAU,uCAAuC,gCAAoB,EACxEA,MAAC,KAAE,UAAU,UAAW,WAAM,QAAQ,SACrCQ,EAAA,CACC,UAAAR,MAACU,EAAA,CACC,OACEV,MAACP,EAAA,CAAO,QAAQ,UAAU,KAAK,KAAK,QAAS,IAAM,OAAO,SAAS,QAAO,CAAG,EAEhF,oBAGDO,MAACe,EAAA,CAAe,KAAK,MAAM,2BAAe,GAC5C,GACF,EAlBK,KAAK,MAAM,QAqBtB,CACF,CC7BA,MAAM0X,GAAuBC,gBAAoD,MAAS,EAE1F,SAASC,IAAgC,CACvC,OAAI,OAAO,OAAW,IACb,QAEF,OAAO,WAAW,8BAA8B,EAAE,QAAU,OAAS,OAC9E,CAEA,SAASC,GAAWC,EAA6B,CAC/C,MAAMC,EAAO,OAAO,SAAS,gBAC7BA,EAAK,UAAU,OAAO,QAAS,MAAM,EAErC,MAAMC,EAA0BF,IAAU,SAAWF,GAAA,EAAmBE,EACxE,OAAAC,EAAK,UAAU,IAAIC,CAAQ,EACpBA,CACT,CAEO,SAASC,GAAc,CAC5B,SAAArY,EACA,aAAAsY,EAAe,SACf,WAAAC,EAAa,kBACf,EAAuB,CACrB,KAAM,CAACL,EAAOM,CAAa,EAAIC,WAAsB,IAC/C,OAAO,OAAW,IACbH,EAEM,OAAO,aAAa,QAAQC,CAAU,GACpCD,CAClB,EAEK,CAACI,EAAeC,CAAgB,EAAIF,WAA8B,IACtEP,IAAU,SAAWF,KAAmBE,CAAA,EAG1CU,YAAgB,IAAM,CACpB,MAAMR,EAAWH,GAAWC,CAAK,EAGjC,GAFAS,EAAiBP,CAAQ,EAErBF,IAAU,SACZ,OAGF,MAAMW,EAAM,OAAO,WAAW,8BAA8B,EACtDC,EAAY3W,GAA2B,CAC3C,MAAMkU,EAAsBlU,EAAE,QAAU,OAAS,QACjD,OAAO,SAAS,gBAAgB,UAAU,OAAO,QAAS,MAAM,EAChE,OAAO,SAAS,gBAAgB,UAAU,IAAIkU,CAAI,EAClDsC,EAAiBtC,CAAI,CACvB,EACA,OAAAwC,EAAI,iBAAiB,SAAUC,CAAQ,EAChC,IAAMD,EAAI,oBAAoB,SAAUC,CAAQ,CACzD,EAAG,CAACZ,CAAK,CAAC,EAEV,MAAM9Q,EAA4B2R,UAChC,KAAO,CACL,MAAAb,EACA,cAAAQ,EACA,SAAWrC,GAAgB,CACzB,OAAO,aAAa,QAAQkC,EAAYlC,CAAI,EAC5CmC,EAAcnC,CAAI,CACpB,IAEF,CAAC6B,EAAOQ,EAAeH,CAAU,GAGnC,OAAOlZ,MAACyY,GAAqB,SAArB,CAA8B,MAAA1Q,EAAe,SAAApH,CAAA,CAAS,CAChE,CAEO,SAASgZ,IAA+B,CAC7C,MAAMC,EAAUC,aAAiBpB,EAAoB,EACrD,GAAImB,IAAY,OACd,MAAM,IAAI,MAAM,8CAA8C,EAEhE,OAAOA,CACT,CC/EA,MAAME,GAAc,SAAS,eAAe,MAAM,EAClD,GAAI,CAACA,GACH,MAAM,IAAI,MAAM,sBAAsB,EAGxCC,cAAWD,EAAW,EAAE,OACtB9Z,MAACga,aAAA,CACC,SAAAha,MAACsY,GAAA,CACC,eAACU,GAAA,CAAc,aAAa,SAAS,WAAW,mBAC9C,SAAAhZ,MAACiY,GAAA,EAAI,EACP,EACF,EACF,CACF","names":["cn","inputs","twMerge","clsx","buttonVariants","cva","Button","forwardRef","className","variant","size","props","ref","jsx","ButtonPrimitive","Input","type","InputPrimitive","TooltipProvider","delay","TooltipPrimitive.Provider","Tooltip","TooltipPrimitive.Root","TooltipTrigger","children","asChild","React.isValidElement","TooltipPrimitive.Trigger","TooltipContent","side","sideOffset","align","alignOffset","TooltipPrimitive.Portal","TooltipPrimitive.Positioner","jsxs","TooltipPrimitive.Popup","TooltipPrimitive.Arrow","PasswordInput","visible","setVisible","useState","v","EyeOff","Eye","API_BASE","CONFIG_API_BASE","CAPTURE_DONE_EVENT","useConfig","config","setConfig","loading","setLoading","error","setError","reload","useCallback","r","data","e","useEffect","save","patch","validate","reloadFromDisk","refreshFromSource","restart","resetToDefault","ConfigContext","createContext","ConfigProvider","useConfigContext","ctx","useContext","Card","CardHeader","CardTitle","CardDescription","CardContent","Label","Form","FormProvider","FormFieldContext","FormField","Controller","useFormField","fieldContext","itemContext","FormItemContext","getFieldState","useFormContext","formState","useFormState","fieldState","id","FormItem","useId","FormLabel","formItemId","FormControl","formDescriptionId","formMessageId","Slot","FormMessage","body","schema","z.object","z.string","ApiKeyGate","form","useForm","zodResolver","handleSubmit","isSubmitting","dialogRef","useRef","showGate","toast","dialog","onSubmit","values","result","err","KeyRound","field","JsonViewer","lazy","m","SseViewer","BodyRenderer","isSse","FileText","badgeSuccess","badgeWarning","badgeGold","badgeInfo","dotSuccess","dotWarning","fmtSize","n","value","fmtTokensCompact","fmtTime","ms","fmtTtft","fmtTps","tps","fmtCachePct","captured","total","c","t","fmtDate","ts","fmtDateTime","escapeHtml","s","statusClass","safeParseHeaders","raw","parsed","syntaxHighlight","json","extractCacheTtl","obj","count","ttl","scan","blocks","b","cc","badgeVariants","Badge","render","useRender","mergeProps","badgeConfig","STATUS_TIP","StatusBadge","status","statusSource","gateReason","klass","cfg","tip","isGate","label","tooltipText","Spinner","LoaderCircle","Loader","ScrollArea","viewportRef","ScrollAreaPrimitive.Root","ScrollAreaPrimitive.Viewport","ScrollBar","ScrollAreaPrimitive.Corner","orientation","ScrollAreaPrimitive.Scrollbar","ScrollAreaPrimitive.Thumb","Tabs","TabsPrimitive.Root","tabsListVariants","TabsList","activateOnFocus","TabsPrimitive.List","TabsTrigger","TabsPrimitive.Tab","TabsContent","TabsPrimitive.Panel","HeadersViewer","TAB_LABELS","TAB_TIPS","CaptureDetailPanel","capture","isLoading","detailError","onCopy","onCopyStatus","onRetry","activeTab","setActiveTab","copyStatus","setCopyStatus","didReportInitialRef","copyLabel","useMemo","sourceMap","cacheTtl","handleCopy","ok","nextStatus","nextLabel","AlertCircle","RotateCcw","Copy","Clock","tv","Suspense","ScanSearch","useLiveAge","startedAt","isRunning","now","setNow","fmtAge","rem","RowTip","CaptureRowItem","selected","isActive","optionId","onActivate","liveAge","Fragment","tierBadgeClass","BREAKER_DESC","breakerIconClass","BreakerIcon","ShieldAlert","ShieldQuestion","ShieldCheck","GateStatus","stats","pct","tierLabel","Icon","Sheet","__vitePreload","SheetContent","MasterDetailContext","noopContext","useMasterDetail","MasterDetailProvider","open","setOpen","MasterDetailLayout","master","detail","masterAriaLabel","detailAriaLabel","isOpen","closeDrawer","TYPEAHEAD_TIMEOUT_MS","useCaptureListbox","captures","selectedId","onSelectId","scrollToIndex","activeIndex","setActiveIndex","typeaheadRef","idx","clamp","move","clamped","handleKeyDown","char","current","searchStr","i","handleRowClick","index","safeActiveIndex","activeOptionId","ClearConfirmDialog","ROW_HEIGHT","CaptureList","wsState","gateStats","listError","onSelect","onClear","confirmOpen","setConfirmOpen","virtualizer","useVirtualizer","totalHeight","items","handleSelect","Trash2","Inbox","virtualRow","CONFIG","WsStatusBadge","useCaptureDetail","setSelectedId","selectedCapture","setSelectedCapture","isLoadingDetail","setIsLoadingDetail","setDetailError","selectedCaptureRef","selectedIdRef","fetchCapture","selectCapture","retryDetail","resetSelection","useCaptureList","setCaptures","isLoadingList","setIsLoadingList","setListError","backendReachable","setBackendReachable","loadList","list","a","retryList","WS_URL","useCapturesSocket","setWsState","onConnected","onCaptureClear","onVisionClear","onCaptureState","onGateStats","onCaptureUpsert","onConnectedRef","onCaptureClearRef","onVisionClearRef","onCaptureStateRef","onGateStatsRef","onCaptureUpsertRef","ws","cancelled","handlers","msg","connect","event","handler","useGateStats","setGateStats","gateError","setGateError","loadGate","retryGate","useCaptures","prev","captureId","state","next","isNew","x","_a","clearCaptures","useClipboard","text","ta","ConfigTab","ModelsTab","PerformanceMeter","EconomicsTab","VisionCalls","ModeToggle","Toaster","TabPanelFallback","TabTriggerWithTip","App","copyText","MobileDrawerTrigger","openDrawer","Menu","ErrorBoundary","React","__publicField","ThemeProviderContext","React.createContext","getSystemTheme","applyTheme","theme","root","resolved","ThemeProvider","defaultTheme","storageKey","setThemeState","React.useState","resolvedTheme","setResolvedTheme","React.useEffect","mql","onChange","React.useMemo","useTheme","context","React.useContext","rootElement","createRoot","StrictMode"],"ignoreList":[],"sources":["../../src/lib/utils.ts","../../src/components/ui/button.tsx","../../src/components/ui/input.tsx","../../src/components/ui/tooltip.tsx","../../src/components/ui/password-input.tsx","../../src/lib/constants.ts","../../src/hooks/use-config.ts","../../src/hooks/use-config-context.tsx","../../src/components/ui/card.tsx","../../src/components/ui/label.tsx","../../src/components/ui/form.tsx","../../src/components/api-key-gate.tsx","../../src/components/body-renderer.tsx","../../src/lib/badge-colors.ts","../../src/lib/format.ts","../../src/components/ui/badge.tsx","../../src/components/status-badge.tsx","../../src/components/ui/spinner.tsx","../../src/components/ui/loader.tsx","../../src/components/ui/scroll-area.tsx","../../src/components/ui/tabs.tsx","../../src/components/capture-detail.tsx","../../src/components/capture-row-item.tsx","../../src/components/gate-status.tsx","../../src/components/layout/master-detail-layout.tsx","../../src/hooks/use-capture-listbox.ts","../../src/components/capture-list.tsx","../../src/components/ws-status-badge.tsx","../../src/hooks/use-capture-detail.ts","../../src/hooks/use-capture-list.ts","../../src/hooks/use-captures-socket.ts","../../src/hooks/use-gate-stats.ts","../../src/hooks/use-captures.ts","../../src/hooks/use-clipboard.ts","../../src/App.tsx","../../src/components/error-boundary.tsx","../../src/components/theme-provider.tsx","../../src/main.tsx"],"sourcesContent":["import { type ClassValue, clsx } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n","import { Button as ButtonPrimitive } from \"@base-ui/react/button\";\nimport { type VariantProps, cva } from \"class-variance-authority\";\nimport { forwardRef } from \"react\";\n\nimport { cn } from \"@/lib/utils\";\n\nconst buttonVariants = cva(\n \"group/button inline-flex shrink-0 items-center justify-center rounded-lg border border-transparent bg-clip-padding text-sm font-medium whitespace-nowrap transition-all outline-none select-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 active:not-aria-[haspopup]:translate-y-px disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n {\n variants: {\n variant: {\n default: \"bg-primary text-primary-foreground hover:bg-primary/80\",\n outline:\n \"border-border bg-background hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:border-input dark:bg-input/30 dark:hover:bg-input/50\",\n secondary:\n \"bg-secondary text-secondary-foreground hover:bg-[color-mix(in_oklch,var(--secondary),var(--foreground)_5%)] aria-expanded:bg-secondary aria-expanded:text-secondary-foreground\",\n ghost:\n \"hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:hover:bg-muted/50\",\n destructive:\n \"bg-destructive/10 text-destructive hover:bg-destructive/20 focus-visible:border-destructive/40 focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:hover:bg-destructive/30 dark:focus-visible:ring-destructive/40\",\n link: \"text-primary underline-offset-4 hover:underline\",\n },\n size: {\n default:\n \"h-8 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2\",\n xs: \"h-6 gap-1 rounded-[min(var(--radius-md),10px)] px-2 text-xs in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3\",\n sm: \"h-7 gap-1 rounded-[min(var(--radius-md),12px)] px-2.5 text-[0.8rem] in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3.5\",\n lg: \"h-9 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2\",\n icon: \"size-8\",\n \"icon-xs\":\n \"size-6 rounded-[min(var(--radius-md),10px)] in-data-[slot=button-group]:rounded-lg [&_svg:not([class*='size-'])]:size-3\",\n \"icon-sm\":\n \"size-7 rounded-[min(var(--radius-md),12px)] in-data-[slot=button-group]:rounded-lg\",\n \"icon-lg\": \"size-9\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n },\n);\n\ntype ButtonProps = ButtonPrimitive.Props &\n VariantProps<typeof buttonVariants> & {\n size?: \"default\" | \"xs\" | \"sm\" | \"lg\" | \"icon\" | \"icon-xs\" | \"icon-sm\" | \"icon-lg\" | null;\n };\n\nconst Button = forwardRef<HTMLElement, ButtonProps>(\n ({ className, variant = \"default\", size = \"default\", ...props }, ref) => {\n return (\n <ButtonPrimitive\n ref={ref}\n data-slot=\"button\"\n className={cn(buttonVariants({ variant, size, className }))}\n {...props}\n />\n );\n },\n);\n\nButton.displayName = \"Button\";\n\nexport { Button, buttonVariants };\n","import { Input as InputPrimitive } from \"@base-ui/react/input\";\nimport type * as React from \"react\";\n\nimport { cn } from \"@/lib/utils\";\n\nfunction Input({ className, type, ...props }: React.ComponentProps<\"input\">) {\n return (\n <InputPrimitive\n type={type}\n data-slot=\"input\"\n className={cn(\n \"h-8 w-full min-w-0 rounded-lg border border-input bg-transparent px-2.5 py-1 text-base transition-colors outline-none file:inline-flex file:h-6 file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:pointer-events-none disabled:cursor-not-allowed disabled:bg-input/50 disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 md:text-sm dark:bg-input/30 dark:disabled:bg-input/80 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40\",\n className,\n )}\n {...props}\n />\n );\n}\n\nexport { Input };\n","import { Tooltip as TooltipPrimitive } from \"@base-ui/react/tooltip\";\nimport * as React from \"react\";\n\nimport { cn } from \"@/lib/utils\";\n\nfunction TooltipProvider({ delay = 0, ...props }: TooltipPrimitive.Provider.Props) {\n return <TooltipPrimitive.Provider data-slot=\"tooltip-provider\" delay={delay} {...props} />;\n}\n\nfunction Tooltip({ ...props }: TooltipPrimitive.Root.Props) {\n return <TooltipPrimitive.Root data-slot=\"tooltip\" {...props} />;\n}\n\ntype TooltipTriggerProps = TooltipPrimitive.Trigger.Props & {\n asChild?: boolean;\n};\n\nfunction TooltipTrigger({ children, asChild, ...props }: TooltipTriggerProps) {\n if (asChild && React.isValidElement(children)) {\n return <TooltipPrimitive.Trigger data-slot=\"tooltip-trigger\" render={children} {...props} />;\n }\n return (\n <TooltipPrimitive.Trigger data-slot=\"tooltip-trigger\" {...props}>\n {children}\n </TooltipPrimitive.Trigger>\n );\n}\n\nfunction TooltipContent({\n className,\n side = \"top\",\n sideOffset = 4,\n align = \"center\",\n alignOffset = 0,\n children,\n ...props\n}: TooltipPrimitive.Popup.Props &\n Pick<TooltipPrimitive.Positioner.Props, \"align\" | \"alignOffset\" | \"side\" | \"sideOffset\">) {\n return (\n <TooltipPrimitive.Portal>\n <TooltipPrimitive.Positioner\n align={align}\n alignOffset={alignOffset}\n side={side}\n sideOffset={sideOffset}\n className=\"isolate z-50\"\n >\n <TooltipPrimitive.Popup\n data-slot=\"tooltip-content\"\n className={cn(\n \"z-50 inline-flex w-fit max-w-xs origin-(--transform-origin) items-center gap-1.5 rounded-md bg-foreground px-3 py-1.5 text-xs text-background has-data-[slot=kbd]:pr-1.5 data-[side=bottom]:slide-in-from-top-2 data-[side=inline-end]:slide-in-from-left-2 data-[side=inline-start]:slide-in-from-right-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 **:data-[slot=kbd]:relative **:data-[slot=kbd]:isolate **:data-[slot=kbd]:z-50 **:data-[slot=kbd]:rounded-sm data-[state=delayed-open]:animate-in data-[state=delayed-open]:fade-in-0 data-[state=delayed-open]:zoom-in-95 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95\",\n className,\n )}\n {...props}\n >\n {children}\n <TooltipPrimitive.Arrow className=\"z-50 size-2.5 translate-y-[calc(-50%-2px)] rotate-45 rounded-[2px] bg-foreground fill-foreground data-[side=bottom]:top-1 data-[side=inline-end]:top-1/2! data-[side=inline-end]:-left-1 data-[side=inline-end]:-translate-y-1/2 data-[side=inline-start]:top-1/2! data-[side=inline-start]:-right-1 data-[side=inline-start]:-translate-y-1/2 data-[side=left]:top-1/2! data-[side=left]:-right-1 data-[side=left]:-translate-y-1/2 data-[side=right]:top-1/2! data-[side=right]:-left-1 data-[side=right]:-translate-y-1/2 data-[side=top]:-bottom-2.5\" />\n </TooltipPrimitive.Popup>\n </TooltipPrimitive.Positioner>\n </TooltipPrimitive.Portal>\n );\n}\n\nexport { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider };\n","import { Eye, EyeOff } from \"lucide-react\";\nimport { useState } from \"react\";\n\nimport { Button } from \"@/components/ui/button\";\nimport { Input } from \"@/components/ui/input\";\nimport { Tooltip, TooltipContent, TooltipTrigger } from \"@/components/ui/tooltip\";\nimport { cn } from \"@/lib/utils\";\n\n/**\n * Password input with show/hide toggle.\n * Renders as a text input with a trailing icon button that toggles visibility.\n */\nexport function PasswordInput({ className, ...props }: React.ComponentProps<\"input\">) {\n const [visible, setVisible] = useState(false);\n return (\n <div className=\"relative flex items-center\">\n <Input type={visible ? \"text\" : \"password\"} className={cn(\"pr-9\", className)} {...props} />\n <Tooltip>\n <TooltipTrigger\n render={\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n className=\"absolute right-0.5 h-7 w-7 text-muted-foreground hover:text-foreground\"\n onClick={() => setVisible((v) => !v)}\n aria-label={visible ? \"Hide password\" : \"Show password\"}\n tabIndex={-1}\n />\n }\n >\n {visible ? <EyeOff className=\"h-3.5 w-3.5\" /> : <Eye className=\"h-3.5 w-3.5\" />}\n </TooltipTrigger>\n <TooltipContent side=\"top\">{visible ? \"Hide password\" : \"Show password\"}</TooltipContent>\n </Tooltip>\n </div>\n );\n}\n","export const API_BASE = \"/dashboard/api\";\nexport const CONFIG_API_BASE = `${API_BASE}/config`;\n\nexport const CAPTURE_DONE_EVENT = \"umans-gate:capture-done\";\n","import { useCallback, useEffect, useState } from \"react\";\n\nimport { API_BASE, CONFIG_API_BASE } from \"@/lib/constants\";\n\nexport interface StampRawConfig {\n stamp_claude_code_enabled?: boolean;\n stamp_reasoning_effort_enabled?: boolean;\n}\n\nexport interface GateRawConfig {\n concurrency_hard_cap?: number;\n concurrency_soft_limit?: number;\n concurrency_main_reservation?: number;\n concurrency_vision_reservation?: number;\n rate_limit_requests?: number;\n queue_timeout_ms?: number;\n max_queue_depth?: number;\n release_cooldown_ms?: number;\n breaker_threshold?: number;\n breaker_window_ms?: number;\n breaker_cooldown_ms?: number;\n}\n\nexport interface VisionRawConfig {\n vision_strategy?: \"never\" | \"catalog\" | \"always\";\n vision_model?: string;\n vision_prompt?: string;\n vision_prompt_version?: number;\n vision_max_images?: number;\n vision_max_description_tokens?: number;\n vision_reasoning_effort?: \"none\" | \"low\" | \"medium\" | \"high\" | null;\n vision_timeout_ms?: number;\n vision_cache_size?: number;\n vision_cache_ttl_ms?: number;\n vision_cache_max_rows?: number;\n vision_persistent_cache?: boolean;\n vision_concurrency?: number;\n vision_max_dimension?: number;\n vision_jpeg_quality?: number;\n vision_image_format?: \"jpeg\" | \"png\";\n vision_image_detail?: \"auto\" | \"low\" | \"high\";\n vision_pending_max_batch?: number;\n}\n\nexport interface ServerRawConfig {\n port?: number;\n max_captures?: number;\n db_path?: string;\n idle_timeout?: number;\n upstream_protocol?: string;\n warmer_enabled?: boolean;\n warmer_interval_ms?: number;\n umans_api_key?: string;\n usage_refresh_ms?: number;\n models_refresh_ms?: number;\n capture_body_max_bytes?: number;\n queue_max_depth?: number;\n ws_backpressure_limit?: number;\n ws_close_on_backpressure_limit?: boolean;\n compression_enabled?: boolean;\n /** Runtime flag: true when the resolved config has an API key (env or file). Read-only — not saved. */\n has_api_key?: boolean;\n}\n\nexport type RawConfig = StampRawConfig & GateRawConfig & VisionRawConfig & ServerRawConfig;\n\nexport interface ValidationResult {\n ok: boolean;\n errors: string[];\n warnings: string[];\n normalized?: RawConfig;\n}\n\nexport interface ReloadResult {\n ok: boolean;\n errors: string[];\n warnings: string[];\n applied: string[];\n restartRequired: string[];\n configPath: string;\n}\n\nexport interface RefreshSourceResult {\n ok: boolean;\n hardCap?: number;\n softLimit?: number;\n requestsLimit?: number | null;\n requestsHardCap?: number | null;\n requestsWindowSeconds?: number | null;\n error?: string;\n}\n\nexport interface RestartResult {\n ok: boolean;\n message?: string;\n error?: string;\n}\n\nexport interface SaveResult {\n ok: boolean;\n errors: string[];\n warnings: string[];\n written: RawConfig;\n}\n\nexport interface ConfigReader {\n config: RawConfig | null;\n loading: boolean;\n error: string | null;\n reload: () => Promise<RawConfig | null>;\n}\n\nexport interface ConfigWriter {\n save: (patch: RawConfig) => Promise<SaveResult | null>;\n validate: (patch: RawConfig) => Promise<ValidationResult | null>;\n}\n\nexport interface ConfigOps {\n reloadFromDisk: () => Promise<ReloadResult | null>;\n refreshFromSource: () => Promise<RefreshSourceResult | null>;\n restart: () => Promise<RestartResult | null>;\n resetToDefault: () => Promise<SaveResult | null>;\n}\n\nexport type UseConfigResult = ConfigReader & ConfigWriter & ConfigOps;\n\nexport function useConfig(): UseConfigResult {\n const [config, setConfig] = useState<RawConfig | null>(null);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n\n const reload = useCallback(async () => {\n setLoading(true);\n setError(null);\n try {\n const r = await fetch(CONFIG_API_BASE);\n if (!r.ok) {\n setError(`HTTP ${r.status}`);\n return null;\n }\n const ct = r.headers.get(\"content-type\") ?? \"\";\n if (!ct.includes(\"application/json\")) {\n setError(\"Backend not reachable\");\n return null;\n }\n const data = (await r.json()) as RawConfig;\n setConfig(data);\n return data;\n } catch (e) {\n setError(e instanceof Error ? e.message : String(e));\n return null;\n } finally {\n setLoading(false);\n }\n }, []);\n\n // Initial fetch.\n useEffect(() => {\n void reload();\n }, [reload]);\n\n const save = useCallback(\n async (patch: RawConfig): Promise<SaveResult | null> => {\n try {\n const r = await fetch(CONFIG_API_BASE, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(patch),\n });\n const data = (await r.json()) as SaveResult;\n if (data.ok) {\n // Refresh local copy from disk-truth.\n await reload();\n }\n return data;\n } catch (e) {\n return {\n ok: false,\n errors: [e instanceof Error ? e.message : String(e)],\n warnings: [],\n written: patch,\n };\n }\n },\n [reload],\n );\n\n const validate = useCallback(async (patch: RawConfig): Promise<ValidationResult | null> => {\n try {\n const r = await fetch(`${CONFIG_API_BASE}/validate`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(patch),\n });\n if (!r.ok) return null;\n return (await r.json()) as ValidationResult;\n } catch {\n return null;\n }\n }, []);\n\n const reloadFromDisk = useCallback(async (): Promise<ReloadResult | null> => {\n try {\n const r = await fetch(`${CONFIG_API_BASE}/reload`, { method: \"POST\" });\n if (!r.ok) return null;\n const data = (await r.json()) as ReloadResult;\n // After reload, refresh local copy too.\n await reload();\n return data;\n } catch {\n return null;\n }\n }, [reload]);\n\n const refreshFromSource = useCallback(async (): Promise<RefreshSourceResult | null> => {\n try {\n const r = await fetch(`${API_BASE}/usage/refresh-source`, { method: \"POST\" });\n if (!r.ok) return null;\n const data = (await r.json()) as RefreshSourceResult;\n if (data.ok) {\n await reload();\n }\n return data;\n } catch {\n return null;\n }\n }, [reload]);\n\n const restart = useCallback(async (): Promise<RestartResult | null> => {\n try {\n const r = await fetch(`${API_BASE}/restart`, { method: \"POST\" });\n if (!r.ok) return null;\n return (await r.json()) as RestartResult;\n } catch (e) {\n return {\n ok: false,\n error: e instanceof Error ? e.message : String(e),\n };\n }\n }, []);\n\n const resetToDefault = useCallback(async (): Promise<SaveResult | null> => {\n try {\n const r = await fetch(`${CONFIG_API_BASE}/reset`, { method: \"POST\" });\n const data = (await r.json()) as SaveResult;\n if (data.ok) {\n await reload();\n }\n return data;\n } catch (e) {\n return {\n ok: false,\n errors: [e instanceof Error ? e.message : String(e)],\n warnings: [],\n written: null as unknown as RawConfig,\n };\n }\n }, [reload]);\n\n return {\n config,\n loading,\n error,\n reload,\n save,\n validate,\n reloadFromDisk,\n refreshFromSource,\n restart,\n resetToDefault,\n };\n}\n","import { type ReactNode, createContext, useContext } from \"react\";\n\nimport { type UseConfigResult, useConfig } from \"@/hooks/use-config\";\n\nconst ConfigContext = createContext<UseConfigResult | null>(null);\n\nexport function ConfigProvider({ children }: { children: ReactNode }) {\n const config = useConfig();\n return <ConfigContext.Provider value={config}>{children}</ConfigContext.Provider>;\n}\n\nexport function useConfigContext(): UseConfigResult {\n const ctx = useContext(ConfigContext);\n if (!ctx) {\n throw new Error(\"useConfigContext must be used within a ConfigProvider\");\n }\n return ctx;\n}\n","import type * as React from \"react\";\n\nimport { cn } from \"@/lib/utils\";\n\nfunction Card({\n className,\n size = \"default\",\n ...props\n}: React.ComponentProps<\"div\"> & { size?: \"default\" | \"sm\" }) {\n return (\n <div\n data-slot=\"card\"\n data-size={size}\n className={cn(\n \"group/card flex flex-col gap-(--card-spacing) overflow-hidden rounded-xl bg-card py-(--card-spacing) text-sm text-card-foreground ring-1 ring-foreground/10 [--card-spacing:--spacing(4)] has-data-[slot=card-footer]:pb-0 has-[>img:first-child]:pt-0 data-[size=sm]:[--card-spacing:--spacing(3)] data-[size=sm]:has-data-[slot=card-footer]:pb-0 *:[img:first-child]:rounded-t-xl *:[img:last-child]:rounded-b-xl\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction CardHeader({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-header\"\n className={cn(\n \"group/card-header @container/card-header grid auto-rows-min items-start gap-1 rounded-t-xl px-(--card-spacing) has-data-[slot=card-action]:grid-cols-[1fr_auto] has-data-[slot=card-description]:grid-rows-[auto_auto] [.border-b]:pb-(--card-spacing)\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction CardTitle({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-title\"\n className={cn(\n \"font-heading text-base leading-snug font-medium group-data-[size=sm]/card:text-sm\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction CardDescription({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-description\"\n className={cn(\"text-sm text-muted-foreground\", className)}\n {...props}\n />\n );\n}\n\nfunction CardAction({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-action\"\n className={cn(\"col-start-2 row-span-2 row-start-1 self-start justify-self-end\", className)}\n {...props}\n />\n );\n}\n\nfunction CardContent({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div data-slot=\"card-content\" className={cn(\"px-(--card-spacing)\", className)} {...props} />\n );\n}\n\nfunction CardFooter({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-footer\"\n className={cn(\n \"flex items-center rounded-b-xl border-t bg-muted/50 p-(--card-spacing)\",\n className,\n )}\n {...props}\n />\n );\n}\n\nexport { Card, CardHeader, CardFooter, CardTitle, CardAction, CardDescription, CardContent };\n","\"use client\";\n\nimport type * as React from \"react\";\n\nimport { cn } from \"@/lib/utils\";\n\nfunction Label({ className, ...props }: React.ComponentProps<\"label\">) {\n return (\n // biome-ignore lint/a11y/noLabelWithoutControl: htmlFor is passed via runtime props\n <label\n data-slot=\"label\"\n className={cn(\n \"flex items-center gap-2 text-sm leading-none font-medium select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50\",\n className,\n )}\n {...props}\n />\n );\n}\n\nexport { Label };\n","import { Slot } from \"@radix-ui/react-slot\";\nimport {\n type ComponentPropsWithoutRef,\n type HTMLAttributes,\n createContext,\n useContext,\n useId,\n} from \"react\";\nimport {\n Controller,\n type ControllerProps,\n type FieldPath,\n type FieldValues,\n FormProvider,\n useFormContext,\n useFormState,\n} from \"react-hook-form\";\n\nimport { Label } from \"@/components/ui/label\";\nimport { cn } from \"@/lib/utils\";\n\nconst Form = FormProvider;\n\ntype FormFieldContextValue<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n> = {\n name: TName;\n};\n\nconst FormFieldContext = createContext<FormFieldContextValue>({} as FormFieldContextValue);\n\nconst FormField = <\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n>({\n ...props\n}: ControllerProps<TFieldValues, TName>) => {\n return (\n <FormFieldContext.Provider value={{ name: props.name }}>\n <Controller {...props} />\n </FormFieldContext.Provider>\n );\n};\n\nconst useFormField = () => {\n const fieldContext = useContext(FormFieldContext);\n const itemContext = useContext(FormItemContext);\n const { getFieldState } = useFormContext();\n const formState = useFormState({ name: fieldContext.name });\n const fieldState = getFieldState(fieldContext.name, formState);\n\n if (!fieldContext) {\n throw new Error(\"useFormField should be used within <FormField>\");\n }\n\n const { id } = itemContext;\n\n return {\n id,\n name: fieldContext.name,\n formItemId: `${id}-form-item`,\n formDescriptionId: `${id}-form-item-description`,\n formMessageId: `${id}-form-item-message`,\n ...fieldState,\n };\n};\n\ntype FormItemContextValue = {\n id: string;\n};\n\nconst FormItemContext = createContext<FormItemContextValue>({} as FormItemContextValue);\n\nfunction FormItem({ className, ...props }: HTMLAttributes<HTMLDivElement>) {\n const id = useId();\n return (\n <FormItemContext.Provider value={{ id }}>\n <div data-slot=\"form-item\" className={cn(\"grid gap-2\", className)} {...props} />\n </FormItemContext.Provider>\n );\n}\n\nfunction FormLabel({ className, ...props }: ComponentPropsWithoutRef<typeof Label>) {\n const { error, formItemId } = useFormField();\n return (\n <Label\n data-slot=\"form-label\"\n data-error={!!error}\n className={cn(\"data-[error=true]:text-destructive\", className)}\n htmlFor={formItemId}\n {...props}\n />\n );\n}\n\nfunction FormControl({ ...props }: ComponentPropsWithoutRef<typeof Slot>) {\n const { error, formItemId, formDescriptionId, formMessageId } = useFormField();\n return (\n <Slot\n data-slot=\"form-control\"\n id={formItemId}\n aria-describedby={!error ? `${formDescriptionId}` : `${formDescriptionId} ${formMessageId}`}\n aria-invalid={!!error}\n {...props}\n />\n );\n}\n\nfunction FormDescription({ className, ...props }: HTMLAttributes<HTMLParagraphElement>) {\n const { formDescriptionId } = useFormField();\n return (\n <p\n data-slot=\"form-description\"\n id={formDescriptionId}\n className={cn(\"text-muted-foreground text-sm\", className)}\n {...props}\n />\n );\n}\n\nfunction FormMessage({ className, ...props }: HTMLAttributes<HTMLParagraphElement>) {\n const { error, formMessageId } = useFormField();\n const body = error ? String(error?.message ?? \"\") : props.children;\n if (!body) {\n return null;\n }\n return (\n <p\n data-slot=\"form-message\"\n id={formMessageId}\n className={cn(\"text-destructive text-sm\", className)}\n {...props}\n >\n {body}\n </p>\n );\n}\n\nexport {\n Form,\n FormControl,\n FormDescription,\n FormField,\n FormItem,\n FormLabel,\n FormMessage,\n useFormField,\n};\n","import { zodResolver } from \"@hookform/resolvers/zod\";\nimport { KeyRound } from \"lucide-react\";\nimport { useEffect, useRef } from \"react\";\nimport { useForm } from \"react-hook-form\";\nimport { toast } from \"sonner\";\nimport { z } from \"zod\";\n\nimport { PasswordInput } from \"@/components/ui/password-input\";\nimport { useConfigContext } from \"@/hooks/use-config-context\";\n\nimport { Button } from \"./ui/button\";\nimport { Card, CardContent, CardDescription, CardHeader, CardTitle } from \"./ui/card\";\nimport { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from \"./ui/form\";\n\nconst schema = z.object({\n umans_api_key: z.string().trim().min(1, \"API key is required\"),\n});\n\ntype FormValues = z.infer<typeof schema>;\n\nexport function ApiKeyGate() {\n const { config, loading, error, save } = useConfigContext();\n\n const form = useForm<FormValues>({\n resolver: zodResolver(schema),\n defaultValues: { umans_api_key: \"\" },\n });\n\n const {\n handleSubmit,\n formState: { isSubmitting },\n } = form;\n\n const dialogRef = useRef<HTMLDialogElement>(null);\n\n const showGate = config !== null && !loading && !error && !config.has_api_key;\n\n useEffect(() => {\n if (error) {\n toast.error(\"Failed to load configuration\", { description: String(error) });\n }\n }, [error]);\n\n useEffect(() => {\n const dialog = dialogRef.current;\n if (showGate && dialog && !dialog.open) {\n dialog.showModal();\n }\n }, [showGate]);\n\n if (!showGate) return null;\n\n const onSubmit = async (values: FormValues) => {\n try {\n const result = await save({ umans_api_key: values.umans_api_key });\n if (!result || !result.ok) {\n toast.error(\"Failed to save API key\", {\n description: result?.errors.join(\"; \") || \"Unknown error\",\n });\n return;\n }\n toast.success(\"API key saved. Reloading configuration…\");\n } catch (err) {\n toast.error(\"Failed to save API key\", {\n description: err instanceof Error ? err.message : \"Unknown error\",\n });\n }\n };\n\n return (\n <dialog\n ref={dialogRef}\n className=\"fixed inset-0 z-[100] m-0 h-screen w-screen bg-background/80 backdrop-blur-sm p-0 border-0\"\n aria-label=\"Umans API key required\"\n >\n <div className=\"flex h-full w-full items-center justify-center p-4\">\n <Card className=\"w-full max-w-md\">\n <CardHeader>\n <div className=\"flex items-center gap-2\">\n <KeyRound className=\"size-5 text-muted-foreground\" />\n <CardTitle>Umans API Key Required</CardTitle>\n </div>\n <CardDescription>\n Enter your Umans API key to start capturing traffic. The key is stored in your local\n config file and can be changed later from the Config tab.\n </CardDescription>\n </CardHeader>\n <CardContent>\n <Form {...form}>\n <form onSubmit={handleSubmit(onSubmit)} className=\"grid gap-4\">\n <FormField\n control={form.control}\n name=\"umans_api_key\"\n render={({ field }) => (\n <FormItem>\n <FormLabel>API Key</FormLabel>\n <FormControl>\n <PasswordInput\n placeholder=\"sk-...\"\n autoComplete=\"off\"\n autoFocus\n disabled={isSubmitting}\n {...field}\n />\n </FormControl>\n <FormMessage />\n </FormItem>\n )}\n />\n <Button type=\"submit\" disabled={isSubmitting}>\n {isSubmitting ? \"Saving…\" : \"Save & Continue\"}\n </Button>\n </form>\n </Form>\n <p className=\"mt-3 text-center text-xs text-muted-foreground\">\n Don't have a key?{\" \"}\n <a\n href=\"https://app.umans.ai\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"underline hover:text-foreground\"\n >\n Get one here\n </a>\n </p>\n </CardContent>\n </Card>\n </div>\n </dialog>\n );\n}\n","import { FileText } from \"lucide-react\";\nimport { lazy } from \"react\";\n\nconst JsonViewer = lazy(() =>\n import(\"@/components/json-viewer\").then((m) => ({ default: m.JsonViewer })),\n);\nconst SseViewer = lazy(() =>\n import(\"@/components/sse-viewer\").then((m) => ({ default: m.SseViewer })),\n);\n\nexport function BodyRenderer({\n body,\n isSse,\n}: {\n body: string | null | undefined;\n isSse: boolean;\n}) {\n if (!body) {\n return (\n <div className=\"flex items-center gap-1.5 text-muted-foreground italic\">\n <FileText className=\"h-3.5 w-3.5\" />\n empty body\n </div>\n );\n }\n\n if (body.startsWith(\"__B64__\")) {\n return (\n <div className=\"text-muted-foreground italic\">\n binary data (base64, {body.length - 6} chars)\n </div>\n );\n }\n\n if (isSse) {\n return <SseViewer body={body} />;\n }\n\n try {\n JSON.parse(body);\n return <JsonViewer body={body} />;\n } catch {\n return (\n <pre className=\"whitespace-pre-wrap break-words font-mono text-xs leading-relaxed\">\n {body}\n </pre>\n );\n }\n}\n","/**\n * Shadcn custom color class strings for semantic Badge usage.\n *\n * Follows the shadcn Badge Custom Colors pattern: Tailwind palette\n * classes applied directly via className, overriding the stock variant.\n * https://ui.shadcn.com/docs/components/base/badge#custom-colors\n */\n\n/** Success — active, healthy, completed states. */\nexport const badgeSuccess =\n \"border-transparent bg-green-50 dark:bg-green-800 text-green-900 dark:text-green-100\";\n\n/** Warning — stale, degraded, reconnecting states. */\nexport const badgeWarning =\n \"border-transparent bg-amber-50 dark:bg-amber-800 text-amber-900 dark:text-amber-100\";\n\n/** Gold — highest/premium tier. */\nexport const badgeGold =\n \"border-transparent bg-yellow-100 dark:bg-yellow-700 text-yellow-900 dark:text-yellow-50\";\n\n/** Info — queued, waiting, informational states. */\nexport const badgeInfo =\n \"border-transparent bg-blue-50 dark:bg-blue-800 text-blue-900 dark:text-blue-100\";\n\n/** Dot color for success indicators (e.g. WebSocket live dot). */\nexport const dotSuccess = \"bg-green-500 dark:bg-green-400\";\n\n/** Dot color for warning indicators (e.g. WebSocket reconnecting dot). */\nexport const dotWarning = \"bg-amber-500 dark:bg-amber-400\";\n","export function fmtSize(n: number | null | undefined): string {\n const value = n ?? 0;\n if (value === 0) return \"0 B\";\n if (value < 1024) return `${value} B`;\n if (value < 1048576) return `${(value / 1024).toFixed(1)} KB`;\n return `${(value / 1048576).toFixed(2)} MB`;\n}\n\nexport function fmtTokensCompact(n: number | null | undefined): string {\n const value = n ?? 0;\n if (value === 0) return \"0\";\n if (value < 1000) return String(value);\n if (value < 1_000_000) return `${(value / 1000).toFixed(1)}K`;\n if (value < 1_000_000_000) return `${(value / 1_000_000).toFixed(2)}M`;\n return `${(value / 1_000_000_000).toFixed(2)}B`;\n}\n\nexport function fmtTime(ms: number | null | undefined): string {\n if (ms == null) return \"\";\n if (ms < 1000) return `${ms} ms`;\n return `${(ms / 1000).toFixed(2)} s`;\n}\n\nexport function fmtTtft(ms: number | null | undefined): string {\n if (ms == null) return \"—\";\n if (ms < 1000) return `${Math.round(ms)}ms`;\n return `${(ms / 1000).toFixed(2)}s`;\n}\n\nexport function fmtTps(tps: number | null | undefined): string {\n if (tps == null) return \"—\";\n return `${tps.toFixed(1)}`;\n}\n\nexport function fmtCachePct(\n captured: number | null | undefined,\n total: number | null | undefined,\n): string {\n const c = captured ?? 0;\n const t = total ?? 0;\n if (t <= 0) return \"—\";\n const pct = (c / t) * 100;\n return `${pct.toFixed(0)}%`;\n}\n\nexport function fmtDate(ts: number | null | undefined): string {\n return ts ? new Date(ts).toLocaleTimeString([], { hour12: false }) : \"\";\n}\n\nexport function fmtDateTime(ts: number | null | undefined): string {\n if (!ts) return \"\";\n return new Date(ts).toLocaleString([], {\n month: \"short\",\n day: \"numeric\",\n hour: \"2-digit\",\n minute: \"2-digit\",\n hour12: false,\n });\n}\n\nfunction escapeHtml(s: string | null | undefined): string {\n return (s ?? \"\").replace(/[&<>]/g, (c) => ({ \"&\": \"&amp;\", \"<\": \"&lt;\", \">\": \"&gt;\" })[c] ?? c);\n}\n\nexport function statusClass(s: number | null | undefined): \"ok\" | \"info\" | \"warn\" | \"err\" | \"\" {\n if (!s) return \"\";\n if (s < 300) return \"ok\";\n if (s < 400) return \"info\";\n if (s < 500) return \"warn\";\n return \"err\";\n}\n\nexport function safeParseHeaders(raw: string | null | undefined): Record<string, string> {\n try {\n const parsed = JSON.parse(raw ?? \"{}\") as unknown;\n return parsed && typeof parsed === \"object\" && !Array.isArray(parsed)\n ? (parsed as Record<string, string>)\n : {};\n } catch {\n return {};\n }\n}\n\nexport function syntaxHighlight(json: string): string {\n return escapeHtml(json);\n}\n\ninterface CacheTtlInfo {\n count: number;\n ttl: string | null;\n}\n\nexport function extractCacheTtl(body: string | null | undefined): CacheTtlInfo | null {\n if (!body) return null;\n let parsed: unknown;\n try {\n parsed = JSON.parse(body);\n } catch {\n return null;\n }\n if (!parsed || typeof parsed !== \"object\" || Array.isArray(parsed)) return null;\n\n const obj = parsed as { system?: unknown; messages?: Array<{ content?: unknown }> };\n let count = 0;\n let ttl: string | null = null;\n\n const scan = (blocks: unknown) => {\n if (!Array.isArray(blocks)) return;\n for (const b of blocks) {\n const cc = (b as { cache_control?: { type?: string; ttl?: string } })?.cache_control;\n if (cc?.type === \"ephemeral\") {\n count++;\n if (cc.ttl && !ttl) ttl = cc.ttl;\n }\n }\n };\n\n scan(obj.system);\n for (const m of obj.messages ?? []) scan(m?.content);\n\n return count > 0 ? { count, ttl } : null;\n}\n","import { mergeProps } from \"@base-ui/react/merge-props\";\nimport { useRender } from \"@base-ui/react/use-render\";\nimport { type VariantProps, cva } from \"class-variance-authority\";\n\nimport { cn } from \"@/lib/utils\";\n\nconst badgeVariants = cva(\n \"group/badge inline-flex h-5 w-fit shrink-0 items-center justify-center gap-1 overflow-hidden rounded-4xl border border-transparent px-2 py-0.5 text-xs font-medium whitespace-nowrap transition-all focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&>svg]:pointer-events-none [&>svg]:size-3!\",\n {\n variants: {\n variant: {\n default: \"bg-primary text-primary-foreground [a]:hover:bg-primary/80\",\n secondary: \"bg-secondary text-secondary-foreground [a]:hover:bg-secondary/80\",\n destructive:\n \"bg-destructive/10 text-destructive focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:focus-visible:ring-destructive/40 [a]:hover:bg-destructive/20\",\n outline: \"border-border text-foreground [a]:hover:bg-muted [a]:hover:text-muted-foreground\",\n ghost: \"hover:bg-muted hover:text-muted-foreground dark:hover:bg-muted/50\",\n link: \"text-primary underline-offset-4 hover:underline\",\n },\n size: {\n default: \"\",\n sm: \"h-4 gap-0.5 px-1.5 text-[0.625rem] [&>svg]:size-2.5!\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n },\n);\n\nfunction Badge({\n className,\n variant = \"default\",\n size = \"default\",\n render,\n ...props\n}: useRender.ComponentProps<\"span\"> & VariantProps<typeof badgeVariants>) {\n return useRender({\n defaultTagName: \"span\",\n props: mergeProps<\"span\">(\n {\n className: cn(badgeVariants({ variant, size }), className),\n },\n props,\n ),\n render,\n state: {\n slot: \"badge\",\n variant,\n size,\n },\n });\n}\n\nexport { Badge, badgeVariants };\n","import { badgeInfo, badgeSuccess, badgeWarning } from \"@/lib/badge-colors\";\nimport { statusClass } from \"@/lib/format\";\nimport { Badge } from \"./ui/badge\";\nimport { Tooltip, TooltipContent, TooltipTrigger } from \"./ui/tooltip\";\n\nconst badgeConfig: Record<\n ReturnType<typeof statusClass>,\n { variant: \"default\" | \"secondary\" | \"outline\" | \"destructive\"; className?: string }\n> = {\n ok: { variant: \"secondary\", className: badgeSuccess },\n info: { variant: \"secondary\", className: badgeInfo },\n warn: { variant: \"secondary\", className: badgeWarning },\n err: { variant: \"destructive\" },\n \"\": { variant: \"secondary\" },\n};\n\nconst STATUS_TIP: Record<string, string> = {\n ok: \"2xx/3xx success\",\n info: \"3xx redirection\",\n warn: \"4xx client error\",\n err: \"5xx server error\",\n \"\": \"No response yet\",\n};\n\ninterface StatusBadgeProps {\n status: number | null;\n statusSource?: \"upstream\" | \"gate\" | null;\n gateReason?: string | null;\n size?: \"default\" | \"sm\";\n}\n\nexport function StatusBadge({\n status,\n statusSource = null,\n gateReason = null,\n size = \"default\",\n}: StatusBadgeProps) {\n const klass = statusClass(status);\n const cfg = badgeConfig[klass];\n const tip = STATUS_TIP[klass];\n const isGate = statusSource === \"gate\";\n const label = status == null ? \"—\" : `${status}${isGate ? \"-gate\" : \"\"}`;\n const tooltipText =\n isGate && gateReason\n ? `HTTP ${status} — generated by gate (not upstream): ${gateReason}`\n : `HTTP ${label} — ${tip}`;\n\n return (\n <Tooltip>\n <TooltipTrigger render={<span className=\"inline-flex\" />}>\n <Badge variant={cfg.variant} size={size} className={cfg.className}>\n {label}\n </Badge>\n </TooltipTrigger>\n <TooltipContent side=\"top\">{tooltipText}</TooltipContent>\n </Tooltip>\n );\n}\n","import { LoaderCircle } from \"lucide-react\";\nimport type * as React from \"react\";\n\nimport { cn } from \"@/lib/utils\";\n\nfunction Spinner({ className, ...props }: React.ComponentProps<\"svg\">) {\n return (\n <LoaderCircle\n role=\"img\"\n aria-label=\"Loading\"\n className={cn(\"animate-spin size-4\", className)}\n {...props}\n />\n );\n}\n\nexport { Spinner };\n","import { Spinner } from \"@/components/ui/spinner\";\nimport { cn } from \"@/lib/utils\";\n\nfunction Loader({ className }: { className?: string }) {\n return (\n <div data-slot=\"loader\" className={cn(\"flex h-full items-center justify-center\", className)}>\n <Spinner className=\"size-8 text-muted-foreground\" />\n </div>\n );\n}\n\nexport { Loader };\n","\"use client\";\n\nimport { ScrollArea as ScrollAreaPrimitive } from \"@base-ui/react/scroll-area\";\nimport type * as React from \"react\";\n\nimport { cn } from \"@/lib/utils\";\n\nfunction ScrollArea({\n className,\n children,\n viewportRef,\n ...props\n}: ScrollAreaPrimitive.Root.Props & {\n viewportRef?: React.Ref<HTMLDivElement>;\n}) {\n return (\n <ScrollAreaPrimitive.Root\n data-slot=\"scroll-area\"\n className={cn(\"relative\", className)}\n {...props}\n >\n <ScrollAreaPrimitive.Viewport\n data-slot=\"scroll-area-viewport\"\n ref={viewportRef}\n className=\"size-full rounded-[inherit] transition-[color,box-shadow] outline-none focus-visible:ring-[3px] focus-visible:ring-ring/50 focus-visible:outline-1\"\n >\n {children}\n </ScrollAreaPrimitive.Viewport>\n <ScrollBar />\n <ScrollAreaPrimitive.Corner />\n </ScrollAreaPrimitive.Root>\n );\n}\n\nfunction ScrollBar({\n className,\n orientation = \"vertical\",\n ...props\n}: ScrollAreaPrimitive.Scrollbar.Props) {\n return (\n <ScrollAreaPrimitive.Scrollbar\n data-slot=\"scroll-area-scrollbar\"\n data-orientation={orientation}\n orientation={orientation}\n className={cn(\n \"flex touch-none p-px transition-colors select-none data-[orientation=horizontal]:h-2.5 data-[orientation=horizontal]:flex-col data-[orientation=horizontal]:border-t data-[orientation=horizontal]:border-t-transparent data-[orientation=vertical]:h-full data-[orientation=vertical]:w-2.5 data-[orientation=vertical]:border-l data-[orientation=vertical]:border-l-transparent\",\n className,\n )}\n {...props}\n >\n <ScrollAreaPrimitive.Thumb\n data-slot=\"scroll-area-thumb\"\n className=\"relative flex-1 rounded-full bg-muted-foreground/40 hover:bg-muted-foreground/60\"\n />\n </ScrollAreaPrimitive.Scrollbar>\n );\n}\n\nexport { ScrollArea, ScrollBar };\n","import { Tabs as TabsPrimitive } from \"@base-ui/react/tabs\";\nimport { type VariantProps, cva } from \"class-variance-authority\";\n\nimport { cn } from \"@/lib/utils\";\n\nfunction Tabs({ className, orientation = \"horizontal\", ...props }: TabsPrimitive.Root.Props) {\n return (\n <TabsPrimitive.Root\n data-slot=\"tabs\"\n data-orientation={orientation}\n className={cn(\"group/tabs flex data-[orientation=horizontal]:flex-col\", className)}\n {...props}\n />\n );\n}\n\nconst tabsListVariants = cva(\n \"group/tabs-list inline-flex w-fit items-center justify-center rounded-lg p-[3px] text-muted-foreground group-data-[orientation=horizontal]/tabs:h-8 group-data-[orientation=vertical]/tabs:h-fit group-data-[orientation=vertical]/tabs:flex-col data-[variant=line]:rounded-none\",\n {\n variants: {\n variant: {\n default: \"bg-muted\",\n line: \"gap-1 bg-transparent\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n },\n },\n);\n\nfunction TabsList({\n className,\n variant = \"default\",\n activateOnFocus = true,\n ...props\n}: TabsPrimitive.List.Props & VariantProps<typeof tabsListVariants>) {\n return (\n <TabsPrimitive.List\n data-slot=\"tabs-list\"\n data-variant={variant}\n activateOnFocus={activateOnFocus}\n className={cn(tabsListVariants({ variant }), className)}\n {...props}\n />\n );\n}\n\nfunction TabsTrigger({ className, ...props }: TabsPrimitive.Tab.Props) {\n return (\n <TabsPrimitive.Tab\n data-slot=\"tabs-trigger\"\n className={cn(\n \"relative inline-flex h-[calc(100%-1px)] flex-1 items-center justify-center gap-1.5 rounded-md border border-transparent px-1.5 py-0.5 text-sm font-medium whitespace-nowrap text-foreground/60 transition-all group-data-[orientation=vertical]/tabs:w-full group-data-[orientation=vertical]/tabs:justify-start hover:text-foreground focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 focus-visible:outline-1 focus-visible:outline-ring disabled:pointer-events-none disabled:opacity-50 has-data-[icon=inline-end]:pr-1 has-data-[icon=inline-start]:pl-1 aria-disabled:pointer-events-none aria-disabled:opacity-50 dark:text-muted-foreground dark:hover:text-foreground group-data-[variant=default]/tabs-list:data-active:shadow-sm group-data-[variant=line]/tabs-list:data-active:shadow-none [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n \"group-data-[variant=line]/tabs-list:bg-transparent group-data-[variant=line]/tabs-list:data-active:bg-transparent dark:group-data-[variant=line]/tabs-list:data-active:border-transparent dark:group-data-[variant=line]/tabs-list:data-active:bg-transparent\",\n \"data-active:bg-background data-active:text-foreground dark:data-active:border-input dark:data-active:bg-input/30 dark:data-active:text-foreground\",\n \"after:absolute after:bg-foreground after:opacity-0 after:transition-opacity group-data-[orientation=horizontal]/tabs:after:inset-x-0 group-data-[orientation=horizontal]/tabs:after:bottom-[-5px] group-data-[orientation=horizontal]/tabs:after:h-0.5 group-data-[orientation=vertical]/tabs:after:inset-y-0 group-data-[orientation=vertical]/tabs:after:-right-1 group-data-[orientation=vertical]/tabs:after:w-0.5 group-data-[variant=line]/tabs-list:data-active:after:opacity-100\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction TabsContent({ className, ...props }: TabsPrimitive.Panel.Props) {\n return (\n <TabsPrimitive.Panel\n data-slot=\"tabs-content\"\n className={cn(\"flex-1 text-sm outline-none\", className)}\n {...props}\n />\n );\n}\n\nexport { Tabs, TabsList, TabsTrigger, TabsContent, tabsListVariants };\n","import { AlertCircle, Clock, Copy, RotateCcw, ScanSearch } from \"lucide-react\";\nimport { Suspense, lazy, useMemo, useRef, useState } from \"react\";\nimport { toast } from \"sonner\";\n\nimport { BodyRenderer } from \"@/components/body-renderer\";\nimport { StatusBadge } from \"@/components/status-badge\";\nimport { Badge } from \"@/components/ui/badge\";\nimport { Button } from \"@/components/ui/button\";\nimport { Loader } from \"@/components/ui/loader\";\nimport { ScrollArea } from \"@/components/ui/scroll-area\";\nimport { Tabs, TabsContent, TabsList, TabsTrigger } from \"@/components/ui/tabs\";\nimport { Tooltip, TooltipContent, TooltipTrigger } from \"@/components/ui/tooltip\";\nimport { badgeSuccess } from \"@/lib/badge-colors\";\nimport { extractCacheTtl, fmtDate, fmtSize, fmtTime } from \"@/lib/format\";\nimport type { CaptureDetail } from \"@/types\";\n\nconst HeadersViewer = lazy(() =>\n import(\"@/components/headers-viewer\").then((m) => ({ default: m.HeadersViewer })),\n);\n\ninterface CaptureDetailProps {\n capture: CaptureDetail | null;\n isLoading: boolean;\n detailError: string | null;\n onCopy: (text: string) => Promise<boolean>;\n onCopyStatus?: (label: string) => void;\n onRetry: () => void;\n}\n\ntype TabValue = \"response\" | \"request\" | \"res-headers\" | \"req-headers\";\n\nconst TAB_LABELS: Record<TabValue, string> = {\n response: \"Response Body\",\n request: \"Request Body\",\n \"res-headers\": \"Response Headers\",\n \"req-headers\": \"Request Headers\",\n};\n\nconst TAB_TIPS: Record<TabValue, string> = {\n response: \"Body returned by the upstream LLM\",\n request: \"Body sent to the upstream — full prompt\",\n \"res-headers\": \"HTTP response headers from upstream\",\n \"req-headers\": \"HTTP request headers sent to upstream\",\n};\n\nexport function CaptureDetailPanel({\n capture,\n isLoading,\n detailError,\n onCopy,\n onCopyStatus,\n onRetry,\n}: CaptureDetailProps) {\n const [activeTab, setActiveTab] = useState<TabValue>(\"response\");\n const [copyStatus, setCopyStatus] = useState<\"idle\" | \"copied\" | \"failed\">(\"idle\");\n const didReportInitialRef = useRef(false);\n\n const copyLabel = useMemo(() => {\n if (copyStatus === \"copied\") return \"Copied!\";\n if (copyStatus === \"failed\") return \"Failed\";\n return \"Copy\";\n }, [copyStatus]);\n\n if (onCopyStatus && !didReportInitialRef.current) {\n didReportInitialRef.current = true;\n onCopyStatus(copyLabel);\n }\n\n const sourceMap = useMemo(() => {\n if (!capture) return {} as Record<TabValue, string>;\n return {\n response: capture.response_body,\n request: capture.request_body,\n \"res-headers\": capture.response_headers,\n \"req-headers\": capture.request_headers,\n };\n }, [capture]);\n\n const cacheTtl = useMemo(\n () => (capture ? extractCacheTtl(capture.request_body) : null),\n [capture],\n );\n\n async function handleCopy() {\n if (!capture) return;\n const ok = await onCopy(sourceMap[activeTab] ?? \"\");\n const nextStatus = ok ? \"copied\" : \"failed\";\n const nextLabel = ok ? \"Copied!\" : \"Failed\";\n setCopyStatus(nextStatus);\n onCopyStatus?.(nextLabel);\n setTimeout(() => {\n setCopyStatus(\"idle\");\n onCopyStatus?.(\"Copy\");\n }, 1200);\n const label = TAB_LABELS[activeTab];\n if (ok) {\n toast.success(\"Copied to clipboard\", { description: label });\n } else {\n toast.error(\"Copy failed\", { description: `Could not copy ${label.toLowerCase()}.` });\n }\n }\n\n if (isLoading) {\n return (\n <main aria-label=\"Capture detail\" className=\"flex flex-1 flex-col overflow-hidden\">\n <Loader />\n </main>\n );\n }\n\n if (!capture && detailError) {\n return (\n <main className=\"flex flex-1 flex-col items-center justify-center gap-3 overflow-y-auto p-8 text-center text-muted-foreground\">\n <AlertCircle className=\"h-12 w-12 text-destructive\" />\n <p className=\"text-sm font-medium text-destructive\">Something went wrong</p>\n <p className=\"text-xs\">{detailError}</p>\n <Tooltip>\n <TooltipTrigger asChild>\n <Button variant=\"outline\" size=\"sm\" onClick={onRetry}>\n <RotateCcw className=\"mr-1.5 h-3.5 w-3.5\" />\n Retry\n </Button>\n </TooltipTrigger>\n <TooltipContent side=\"top\">Retry loading capture detail</TooltipContent>\n </Tooltip>\n </main>\n );\n }\n\n if (!capture) {\n return (\n <main className=\"flex flex-1 flex-col items-center justify-center gap-3 overflow-y-auto p-8 text-center text-muted-foreground\">\n <ScanSearch className=\"h-12 w-12 text-muted-foreground/40\" />\n <p className=\"text-sm font-medium\">Select a capture to inspect</p>\n <p className=\"text-xs\">\n Requests appear here automatically as they flow through the proxy.\n </p>\n </main>\n );\n }\n\n return (\n <main className=\"flex flex-1 flex-col overflow-hidden\">\n <header className=\"border-b border-border px-4 py-3\">\n <div className=\"flex w-full items-start justify-between gap-3\">\n <h2 className=\"break-all font-mono text-[15px] font-semibold leading-tight\">\n {capture.method} {capture.path}\n </h2>\n <Tooltip>\n <TooltipTrigger asChild>\n <Button size=\"sm\" variant=\"outline\" className=\"shrink-0\" onClick={handleCopy}>\n <Copy className=\"mr-1.5 h-3.5 w-3.5\" />\n {copyLabel}\n </Button>\n </TooltipTrigger>\n <TooltipContent side=\"left\">Copy active tab content to clipboard</TooltipContent>\n </Tooltip>\n </div>\n <div className=\"mt-2 flex w-full flex-wrap items-center gap-2 text-xs text-muted-foreground\">\n <StatusBadge\n status={capture.response_status}\n statusSource={capture.status_source}\n gateReason={capture.gate_reason}\n size=\"sm\"\n />\n {cacheTtl && (\n <Tooltip>\n <TooltipTrigger render={<span className=\"inline-flex\" />}>\n <Badge variant=\"outline\" size=\"sm\">\n <Clock className=\"mr-1 h-2.5 w-2.5\" aria-hidden />\n TTL {cacheTtl.ttl ?? \"—\"}\n </Badge>\n </TooltipTrigger>\n <TooltipContent side=\"top\" className=\"max-w-[240px]\">\n {cacheTtl.count} block{cacheTtl.count > 1 ? \"s\" : \"\"} stamped with ephemeral TTL\n </TooltipContent>\n </Tooltip>\n )}\n {capture.is_sse && (\n <Tooltip>\n <TooltipTrigger render={<span className=\"inline-flex\" />}>\n <Badge variant=\"secondary\" size=\"sm\">\n SSE\n </Badge>\n </TooltipTrigger>\n <TooltipContent side=\"top\">Upstream response is an SSE stream</TooltipContent>\n </Tooltip>\n )}\n <Tooltip>\n <TooltipTrigger render={<span className=\"inline-flex tabular-nums\" />}>\n <span>\n ↑{fmtSize(capture.request_size)} ↓{fmtSize(capture.response_size)}\n </span>\n </TooltipTrigger>\n <TooltipContent side=\"top\">\n ↑ {fmtSize(capture.request_size)} request · ↓ {fmtSize(capture.response_size)}{\" \"}\n response\n </TooltipContent>\n </Tooltip>\n <Tooltip>\n <TooltipTrigger render={<span className=\"inline-flex tabular-nums\" />}>\n <span>{fmtTime(capture.duration_ms)}</span>\n </TooltipTrigger>\n <TooltipContent side=\"top\">Wall-clock duration from start to completion</TooltipContent>\n </Tooltip>\n {capture.incoming_protocol && (\n <Tooltip>\n <TooltipTrigger render={<span className=\"inline-flex\" />}>\n <Badge variant=\"outline\" size=\"sm\">\n in {capture.incoming_protocol}\n </Badge>\n </TooltipTrigger>\n <TooltipContent side=\"top\">HTTP version used by the client</TooltipContent>\n </Tooltip>\n )}\n {capture.upstream_protocol && (\n <Tooltip>\n <TooltipTrigger render={<span className=\"inline-flex\" />}>\n <Badge variant=\"outline\" size=\"sm\">\n out {capture.upstream_protocol}\n </Badge>\n </TooltipTrigger>\n <TooltipContent side=\"top\">HTTP version used to reach upstream</TooltipContent>\n </Tooltip>\n )}\n <Tooltip>\n <TooltipTrigger render={<span className=\"inline-flex font-mono tabular-nums\" />}>\n <span>{fmtDate(capture.started_at)}</span>\n </TooltipTrigger>\n <TooltipContent side=\"top\">\n {capture.started_at\n ? new Date(capture.started_at).toLocaleString()\n : \"Not yet recorded\"}\n </TooltipContent>\n </Tooltip>\n {capture.state === \"streaming\" && (\n <Tooltip>\n <TooltipTrigger render={<span className=\"inline-flex\" />}>\n <Badge variant=\"secondary\" size=\"sm\" className={badgeSuccess}>\n live\n </Badge>\n </TooltipTrigger>\n <TooltipContent side=\"top\">Response is still streaming</TooltipContent>\n </Tooltip>\n )}\n </div>\n <div className=\"mt-0.5 w-full break-all font-mono text-[11px] text-muted-foreground\">\n {capture.url}\n </div>\n </header>\n\n <Tabs\n value={activeTab}\n onValueChange={(v) => setActiveTab(v as TabValue)}\n className=\"flex flex-1 flex-col overflow-hidden\"\n >\n <TabsList className=\"mx-auto mt-2 w-fit\">\n {(Object.keys(TAB_LABELS) as TabValue[]).map((tv) => (\n <Tooltip key={tv}>\n <TooltipTrigger render={<span />}>\n <TabsTrigger value={tv}>{TAB_LABELS[tv]}</TabsTrigger>\n </TooltipTrigger>\n <TooltipContent side=\"bottom\" className=\"max-w-[240px]\">\n {TAB_TIPS[tv]}\n </TooltipContent>\n </Tooltip>\n ))}\n </TabsList>\n\n <Suspense fallback={<Loader />}>\n <ScrollArea className=\"flex-1 min-h-0 px-4 py-3\">\n <div className=\"w-full\">\n <TabsContent value=\"response\" className=\"m-0\">\n <BodyRenderer body={capture.response_body} isSse={capture.is_sse} />\n </TabsContent>\n <TabsContent value=\"request\" className=\"m-0\">\n <BodyRenderer body={capture.request_body} isSse={false} />\n </TabsContent>\n <TabsContent value=\"res-headers\" className=\"m-0\">\n <HeadersViewer headers={capture.response_headers} />\n </TabsContent>\n <TabsContent value=\"req-headers\" className=\"m-0\">\n <HeadersViewer headers={capture.request_headers} />\n </TabsContent>\n </div>\n </ScrollArea>\n </Suspense>\n </Tabs>\n </main>\n );\n}\n","import { Eye } from \"lucide-react\";\nimport { useEffect, useState } from \"react\";\nimport type { ReactNode } from \"react\";\n\nimport { Badge } from \"@/components/ui/badge\";\nimport { Tooltip, TooltipContent, TooltipTrigger } from \"@/components/ui/tooltip\";\nimport { badgeInfo, badgeSuccess } from \"@/lib/badge-colors\";\nimport {\n fmtCachePct,\n fmtDate,\n fmtSize,\n fmtTime,\n fmtTokensCompact,\n fmtTps,\n fmtTtft,\n} from \"@/lib/format\";\nimport { cn } from \"@/lib/utils\";\nimport type { CaptureSummary } from \"@/types\";\nimport { StatusBadge } from \"./status-badge\";\n\ninterface CaptureRowItemProps {\n capture: CaptureSummary;\n selected: boolean;\n isActive: boolean;\n optionId: string;\n onActivate: () => void;\n}\n\n/**\n * Live age counter for in-flight captures. Ticks every 1s showing whole\n * seconds elapsed since `started_at`. Sub-second precision is noise while\n * a request is still running.\n */\nfunction useLiveAge(startedAt: number | null, isRunning: boolean): number | null {\n const [now, setNow] = useState(() => Date.now());\n useEffect(() => {\n if (!isRunning || startedAt == null) return;\n const id = setInterval(() => setNow(Date.now()), 1000);\n return () => clearInterval(id);\n }, [isRunning, startedAt]);\n if (!isRunning || startedAt == null) return null;\n return Math.max(0, now - startedAt);\n}\n\nfunction fmtAge(ms: number): string {\n const s = Math.floor(ms / 1000);\n if (s < 60) return `${s}s`;\n const m = Math.floor(s / 60);\n const rem = s % 60;\n return `${m}m${rem}s`;\n}\n\n/**\n * Minimal tooltip wrapper for inline elements in capture rows. Keeps the\n * tooltip content shape consistent: a bold label + optional muted detail.\n */\nfunction RowTip({\n tip,\n children,\n}: {\n tip: ReactNode;\n children: ReactNode;\n}) {\n return (\n <Tooltip>\n <TooltipTrigger render={<span className=\"inline-flex\" />}>{children}</TooltipTrigger>\n <TooltipContent side=\"top\" className=\"max-w-[220px]\">\n {tip}\n </TooltipContent>\n </Tooltip>\n );\n}\n\nexport function CaptureRowItem({\n capture: c,\n selected,\n isActive,\n optionId,\n onActivate,\n}: CaptureRowItemProps) {\n const isRunning = c.state === \"enqueued\" || c.state === \"streaming\";\n const liveAge = useLiveAge(c.started_at, isRunning);\n\n return (\n <div\n // biome-ignore lint/a11y/useSemanticElements: ARIA option role for virtualized listbox pattern\n role=\"option\"\n id={optionId}\n aria-selected={selected}\n tabIndex={-1}\n onClick={onActivate}\n onKeyDown={(e) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n onActivate();\n }\n }}\n className={cn(\n \"cursor-pointer border-b border-border px-4 py-3 w-full transition-colors hover:bg-accent overflow-hidden\",\n selected && \"bg-accent\",\n isActive && !selected && \"bg-accent/50\",\n )}\n >\n {/* Row 1: method + status + protocol + transfer + timestamp */}\n <div className=\"flex items-center gap-1.5 overflow-hidden\">\n <RowTip\n tip={\n <>\n Method <span className=\"font-mono\">{c.method}</span>\n </>\n }\n >\n <span className=\"shrink-0 font-mono text-xs font-bold text-primary\">{c.method}</span>\n </RowTip>\n <StatusBadge\n status={c.response_status}\n statusSource={c.status_source}\n gateReason={c.gate_reason}\n size=\"sm\"\n />\n {c.is_vision && (\n <RowTip tip=\"Vision call — request included image input\">\n <span className=\"inline-flex shrink-0 items-center text-muted-foreground\">\n <Eye className=\"h-3.5 w-3.5\" />\n </span>\n </RowTip>\n )}\n {c.state === \"enqueued\" && (\n <RowTip tip=\"Queued — waiting for a concurrency slot\">\n <Badge variant=\"secondary\" size=\"sm\" className={badgeInfo}>\n queued\n </Badge>\n </RowTip>\n )}\n {c.state === \"streaming\" && (\n <RowTip tip=\"Running — upstream is streaming the response\">\n <Badge variant=\"secondary\" size=\"sm\" className={badgeSuccess}>\n running\n </Badge>\n </RowTip>\n )}\n {c.is_sse && (\n <RowTip tip=\"SSE — upstream response is a stream\">\n <Badge variant=\"secondary\" size=\"sm\">\n SSE\n </Badge>\n </RowTip>\n )}\n {c.upstream_protocol && (\n <RowTip\n tip={\n <>\n Upstream HTTP <span className=\"font-mono\">{c.upstream_protocol}</span>\n </>\n }\n >\n <Badge variant=\"outline\" size=\"sm\">\n {c.upstream_protocol}\n </Badge>\n </RowTip>\n )}\n <span className=\"ml-auto flex shrink-0 items-center gap-2 font-mono text-[11px] tabular-nums text-muted-foreground\">\n <RowTip tip={<>Request size — {fmtSize(c.request_size)}</>}>\n <span>\n <span className=\"text-muted-foreground/70\">↑</span>\n {fmtSize(c.request_size)}\n </span>\n </RowTip>\n <RowTip tip={<>Response size — {fmtSize(c.response_size)}</>}>\n <span>\n <span className=\"text-muted-foreground/70\">↓</span>\n {fmtSize(c.response_size)}\n </span>\n </RowTip>\n <RowTip\n tip={\n c.started_at\n ? `Started ${new Date(c.started_at).toLocaleString()}${\n c.finished_at ? ` · finished ${new Date(c.finished_at).toLocaleString()}` : \"\"\n }`\n : \"Start time not recorded\"\n }\n >\n <span className=\"text-muted-foreground/60\">{fmtDate(c.started_at)}</span>\n </RowTip>\n </span>\n </div>\n\n {/* Row 2: path (mono, truncated) */}\n <RowTip\n tip={\n <span className=\"font-mono break-all\">\n {c.path}\n {c.model ? ` · ${c.model}` : \"\"}\n </span>\n }\n >\n <div className=\"mt-1 truncate font-mono text-xs text-foreground/80\">\n {c.path}\n {c.model && <span className=\"text-muted-foreground\"> · {c.model}</span>}\n </div>\n </RowTip>\n\n {/* Row 3: all metrics in one row */}\n <div className=\"mt-1.5 flex items-center gap-3 text-[11px] tabular-nums text-muted-foreground\">\n {isRunning && liveAge != null ? (\n <RowTip tip=\"Age — time since request started (still running)\">\n <span className=\"flex items-center gap-1 font-medium text-primary\">\n <span\n className=\"inline-block h-1.5 w-1.5 rounded-full bg-primary animate-pulse\"\n aria-hidden\n />\n {fmtAge(liveAge)}\n </span>\n </RowTip>\n ) : (\n <RowTip tip={<>Total time — {fmtTime(c.duration_ms) || \"—\"}</>}>\n <span>{fmtTime(c.duration_ms) || \"—\"}</span>\n </RowTip>\n )}\n {(!isRunning || c.ttft_ms != null) && (\n <RowTip tip=\"Time to first token — delay before first response token\">\n <span>ttft {fmtTtft(c.ttft_ms)}</span>\n </RowTip>\n )}\n <RowTip\n tip={\n c.tps == null\n ? c.usage_missing\n ? \"Tokens per second — usage data unavailable\"\n : c.output_tokens == null || c.output_tokens <= 0\n ? \"Tokens per second — no output tokens\"\n : \"Tokens per second — generation time too short to measure (< 1 s)\"\n : \"Tokens per second — output generation rate\"\n }\n >\n <span>{fmtTps(c.tps)} t/s</span>\n </RowTip>\n <RowTip tip=\"Total input tokens — prompt tokens sent (incl. cache writes)\">\n <span>in {fmtTokensCompact(c.total_input_tokens)}</span>\n </RowTip>\n <RowTip tip=\"Total output tokens — completion tokens received\">\n <span>out {fmtTokensCompact(c.total_output_tokens)}</span>\n </RowTip>\n <RowTip tip=\"Cache read % — share of input from prompt cache\">\n <span>cache {fmtCachePct(c.cache_read_tokens, c.total_input_tokens)}</span>\n </RowTip>\n </div>\n </div>\n );\n}\n","import { Badge } from \"@/components/ui/badge\";\nimport { Tooltip, TooltipContent, TooltipTrigger } from \"@/components/ui/tooltip\";\nimport { badgeGold, badgeInfo, badgeSuccess, badgeWarning } from \"@/lib/badge-colors\";\nimport { fmtDateTime } from \"@/lib/format\";\nimport { cn } from \"@/lib/utils\";\nimport type { GateStats } from \"@/types\";\nimport { ShieldAlert, ShieldCheck, ShieldQuestion } from \"lucide-react\";\n\nconst tierBadgeClass: Record<GateStats[\"tier\"], string | undefined> = {\n \"Code Max\": badgeGold,\n \"Code Pro\": badgeInfo,\n unknown: undefined,\n};\n\nconst BREAKER_DESC: Record<string, string> = {\n closed: \"Upstream healthy — requests flow normally\",\n open: \"Too many 429s — requests fail fast until cooldown\",\n half_open: \"Probe request sent to test upstream recovery\",\n};\n\nconst breakerIconClass: Record<string, string> = {\n open: \"text-destructive\",\n half_open: \"text-muted-foreground\",\n closed: \"text-primary\",\n};\n\nconst BreakerIcon: Record<string, typeof ShieldCheck> = {\n open: ShieldAlert,\n half_open: ShieldQuestion,\n closed: ShieldCheck,\n};\n\nexport function GateStatus({ stats }: { stats: GateStats | null }) {\n if (!stats) return null;\n\n const pct = stats.hardCap > 0 ? (stats.active / stats.hardCap) * 100 : 0;\n const tierLabel = stats.tier === \"unknown\" ? \"no key\" : stats.tier;\n\n return (\n <div className=\"border-b border-border px-4 py-2 text-xs\">\n <div className=\"flex items-center gap-2 flex-wrap\">\n <div className=\"flex items-center gap-2 flex-wrap flex-1\">\n <Tooltip>\n <TooltipTrigger render={<span className=\"inline-flex\" />}>\n <Badge variant=\"secondary\" className={tierBadgeClass[stats.tier]}>\n {tierLabel}\n </Badge>\n </TooltipTrigger>\n <TooltipContent side=\"bottom\" className=\"max-w-[240px]\">\n {stats.tier === \"Code Max\"\n ? \"Highest concurrency — no rate limit gating\"\n : stats.tier === \"Code Pro\"\n ? \"Standard concurrency with rate-limit gating\"\n : \"No API key configured — upstream defaults apply\"}\n </TooltipContent>\n </Tooltip>\n <Tooltip>\n <TooltipTrigger render={<span className=\"cursor-help\" />}>\n <span className={cn(\"font-mono\", stats.breaker === \"open\" && \"text-destructive\")}>\n {stats.active}/{stats.hardCap}\n </span>\n <span className=\"text-muted-foreground ml-1\">hard cap</span>\n </TooltipTrigger>\n <TooltipContent side=\"bottom\">\n {stats.active} active · {stats.hardCap} hard cap · {stats.softLimit} soft limit\n </TooltipContent>\n </Tooltip>\n {stats.queued > 0 && (\n <>\n <span className=\"font-mono text-muted-foreground\">{stats.queued}</span>\n <span className=\"text-muted-foreground\">queued</span>\n </>\n )}\n <span className=\"text-muted-foreground\">·</span>\n <Tooltip>\n <TooltipTrigger\n render={<span className=\"inline-flex items-center gap-1 cursor-help\" />}\n >\n {(() => {\n const Icon = BreakerIcon[stats.breaker] ?? ShieldQuestion;\n return (\n <Icon\n aria-hidden\n className={cn(\n \"h-3.5 w-3.5\",\n breakerIconClass[stats.breaker] ?? \"text-muted-foreground\",\n )}\n />\n );\n })()}\n </TooltipTrigger>\n <TooltipContent side=\"bottom\" className=\"max-w-[260px]\">\n {BREAKER_DESC[stats.breaker] ?? stats.breaker}\n </TooltipContent>\n </Tooltip>\n {stats.boxed && (\n <Tooltip>\n <TooltipTrigger render={<span className=\"inline-flex\" />}>\n <Badge variant=\"destructive\">\n boxed{stats.boxedReason ? `: ${stats.boxedReason}` : \"\"}\n </Badge>\n </TooltipTrigger>\n <TooltipContent side=\"bottom\" className=\"max-w-[260px]\">\n Requests rejected by box guard\n {stats.boxedReason ? ` — ${stats.boxedReason}` : \"\"}\n </TooltipContent>\n </Tooltip>\n )}\n {!stats.usageOk && (\n <Tooltip>\n <TooltipTrigger render={<span className=\"inline-flex\" />}>\n <Badge variant=\"secondary\" className={badgeWarning}>\n usage: stale\n </Badge>\n </TooltipTrigger>\n <TooltipContent side=\"bottom\" className=\"max-w-[240px]\">\n Last usage fetch failed — rate limit counters may be inaccurate\n </TooltipContent>\n </Tooltip>\n )}\n </div>\n <Tooltip>\n <TooltipTrigger render={<span className=\"inline-flex\" />}>\n <Badge\n variant={stats.unitsDemoted ? \"destructive\" : \"secondary\"}\n className={\n stats.unitsDemoted ? undefined : stats.priorityLow ? badgeWarning : badgeSuccess\n }\n >\n {stats.unitsDemoted ? \"demoted\" : stats.priorityLow ? \"low\" : \"high\"}\n </Badge>\n </TooltipTrigger>\n <TooltipContent side=\"bottom\" className=\"max-w-[260px]\">\n <div className=\"space-y-1\">\n <p>Priority: {stats.unitsDemoted ? \"demoted\" : stats.priorityLow ? \"low\" : \"high\"}</p>\n {stats.boxed && stats.boxedUntil !== null && (\n <p className=\"text-muted-foreground\">boxed until {fmtDateTime(stats.boxedUntil)}</p>\n )}\n {stats.demotedUntil !== null && (\n <p className=\"text-muted-foreground\">\n demoted until {fmtDateTime(stats.demotedUntil)}\n </p>\n )}\n </div>\n </TooltipContent>\n </Tooltip>\n </div>\n\n <div className=\"mt-1.5 h-1 w-full overflow-hidden rounded bg-secondary\">\n <div\n className={cn(\"h-full transition-all\", pct >= 100 ? \"bg-destructive\" : \"bg-primary\")}\n style={{ width: `${Math.min(100, pct)}%` }}\n />\n </div>\n\n {stats.requestsLimit !== null && (\n <div className=\"mt-1 flex items-center gap-2 text-muted-foreground\">\n <span>\n requests: {stats.requestsInWindow}\n {stats.requestsLimit ? ` / ${stats.requestsLimit}` : \"\"}\n </span>\n {stats.requestsRemaining !== null && <span>({stats.requestsRemaining} remaining)</span>}\n {stats.windowSeconds && <span>· {Math.round(stats.windowSeconds / 3600)}h window</span>}\n </div>\n )}\n </div>\n );\n}\n","import { type ReactNode, Suspense, createContext, lazy, useContext, useState } from \"react\";\n\nconst Sheet = lazy(() => import(\"@/components/ui/sheet\").then((m) => ({ default: m.Sheet })));\nconst SheetContent = lazy(() =>\n import(\"@/components/ui/sheet\").then((m) => ({ default: m.SheetContent })),\n);\n\ninterface MasterDetailContextValue {\n openDrawer: () => void;\n closeDrawer: () => void;\n isOpen: boolean;\n}\n\nconst MasterDetailContext = createContext<MasterDetailContextValue | null>(null);\n\nconst noopContext: MasterDetailContextValue = {\n openDrawer: () => {},\n closeDrawer: () => {},\n isOpen: false,\n};\n\nexport function useMasterDetail(): MasterDetailContextValue {\n const ctx = useContext(MasterDetailContext);\n return ctx ?? noopContext;\n}\n\ninterface MasterDetailProviderProps {\n children: ReactNode;\n}\n\nexport function MasterDetailProvider({ children }: MasterDetailProviderProps) {\n const [open, setOpen] = useState(false);\n\n const value: MasterDetailContextValue = {\n openDrawer: () => setOpen(true),\n closeDrawer: () => setOpen(false),\n isOpen: open,\n };\n\n return <MasterDetailContext.Provider value={value}>{children}</MasterDetailContext.Provider>;\n}\n\ninterface MasterDetailLayoutProps {\n master: ReactNode;\n detail: ReactNode;\n masterAriaLabel: string;\n detailAriaLabel: string;\n}\n\nexport function MasterDetailLayout({\n master,\n detail,\n masterAriaLabel,\n detailAriaLabel,\n}: MasterDetailLayoutProps) {\n const { isOpen, closeDrawer } = useMasterDetail();\n\n return (\n <>\n <div className=\"flex h-full\">\n <aside aria-label={masterAriaLabel} className=\"hidden w-[380px] shrink-0 md:flex\">\n {master}\n </aside>\n <div className=\"flex flex-1 min-w-0\" aria-label={detailAriaLabel}>\n {detail}\n </div>\n </div>\n {isOpen && (\n <Suspense fallback={null}>\n <Sheet\n open={isOpen}\n onOpenChange={(o) => {\n if (!o) closeDrawer();\n }}\n >\n <SheetContent\n side=\"left\"\n aria-label={masterAriaLabel}\n className=\"p-0 data-[side=left]:w-[85vw] data-[side=left]:sm:w-[380px] data-[side=left]:sm:max-w-[380px]\"\n >\n {master}\n </SheetContent>\n </Sheet>\n </Suspense>\n )}\n </>\n );\n}\n","import { useCallback, useEffect, useRef, useState } from \"react\";\n\ninterface UseCaptureListboxOptions {\n captures: { id: number; path: string }[];\n selectedId: number | null;\n onSelectId: (id: number) => void;\n scrollToIndex: (index: number, options?: { align?: \"start\" | \"center\" | \"end\" | \"auto\" }) => void;\n}\n\ninterface UseCaptureListboxResult {\n activeIndex: number;\n activeOptionId: string | undefined;\n handleKeyDown: (e: React.KeyboardEvent) => void;\n handleRowClick: (index: number) => void;\n}\n\nconst TYPEAHEAD_TIMEOUT_MS = 500;\n\nexport function useCaptureListbox({\n captures,\n selectedId,\n onSelectId,\n scrollToIndex,\n}: UseCaptureListboxOptions): UseCaptureListboxResult {\n const count = captures.length;\n const [activeIndex, setActiveIndex] = useState(0);\n const typeaheadRef = useRef<{\n chars: string;\n timer: ReturnType<typeof setTimeout> | undefined;\n }>({ chars: \"\", timer: undefined });\n\n // Sync activeIndex when selectedId changes to keep focus and selection aligned\n useEffect(() => {\n if (selectedId === null || count === 0) return;\n const idx = captures.findIndex((c) => c.id === selectedId);\n if (idx >= 0) {\n setActiveIndex(idx);\n }\n }, [selectedId, count, captures]);\n\n // Cleanup typeahead timer on unmount\n useEffect(() => {\n return () => {\n if (typeaheadRef.current.timer) {\n clearTimeout(typeaheadRef.current.timer);\n }\n };\n }, []);\n\n const clamp = useCallback(\n (idx: number) => {\n if (count === 0) return -1;\n return Math.max(0, Math.min(idx, count - 1));\n },\n [count],\n );\n\n const move = useCallback(\n (idx: number) => {\n const clamped = clamp(idx);\n if (clamped < 0) return;\n setActiveIndex(clamped);\n scrollToIndex(clamped, { align: \"auto\" });\n },\n [clamp, scrollToIndex],\n );\n\n const handleKeyDown = useCallback(\n (e: React.KeyboardEvent) => {\n if (count === 0) return;\n switch (e.key) {\n case \"ArrowDown\":\n e.preventDefault();\n move(activeIndex + 1);\n break;\n case \"ArrowUp\":\n e.preventDefault();\n move(activeIndex - 1);\n break;\n case \"Home\":\n e.preventDefault();\n move(0);\n break;\n case \"End\":\n e.preventDefault();\n move(count - 1);\n break;\n case \"Enter\":\n case \" \":\n e.preventDefault();\n if (activeIndex >= 0 && activeIndex < count) {\n onSelectId(captures[activeIndex].id);\n }\n break;\n default: {\n // Typeahead: jump to first row whose path starts with typed chars\n if (e.key.length === 1 && /[a-zA-Z0-9/]/.test(e.key)) {\n const char = e.key.toLowerCase();\n const current = typeaheadRef.current;\n current.chars += char;\n if (current.timer) clearTimeout(current.timer);\n current.timer = setTimeout(() => {\n typeaheadRef.current.chars = \"\";\n }, TYPEAHEAD_TIMEOUT_MS);\n\n const searchStr = current.chars;\n for (let i = 0; i < count; i++) {\n if (captures[i].path.toLowerCase().startsWith(searchStr)) {\n move(i);\n break;\n }\n }\n }\n break;\n }\n }\n },\n [count, activeIndex, move, onSelectId, captures],\n );\n\n const handleRowClick = useCallback(\n (index: number) => {\n if (index < 0 || index >= count) return;\n setActiveIndex(index);\n onSelectId(captures[index].id);\n },\n [onSelectId, captures, count],\n );\n\n const safeActiveIndex = count === 0 ? -1 : Math.min(activeIndex, count - 1);\n const activeOptionId =\n safeActiveIndex >= 0 ? `capture-opt-${captures[safeActiveIndex].id}` : undefined;\n\n return {\n activeIndex: safeActiveIndex,\n activeOptionId,\n handleKeyDown,\n handleRowClick,\n };\n}\n","import { useVirtualizer } from \"@tanstack/react-virtual\";\nimport { AlertCircle, Inbox, RotateCcw, Trash2 } from \"lucide-react\";\nimport { Suspense, lazy, useRef, useState } from \"react\";\n\nimport { CaptureRowItem } from \"@/components/capture-row-item\";\nimport { GateStatus } from \"@/components/gate-status\";\nimport { useMasterDetail } from \"@/components/layout/master-detail-layout\";\nimport { Button } from \"@/components/ui/button\";\nimport { Loader } from \"@/components/ui/loader\";\nimport { ScrollArea } from \"@/components/ui/scroll-area\";\nimport { Tooltip, TooltipContent, TooltipTrigger } from \"@/components/ui/tooltip\";\nimport { useCaptureListbox } from \"@/hooks/use-capture-listbox\";\nimport { cn } from \"@/lib/utils\";\nimport type { CaptureSummary, GateStats } from \"@/types\";\n\nconst ClearConfirmDialog = lazy(() =>\n import(\"@/components/clear-confirm-dialog\").then((m) => ({\n default: m.ClearConfirmDialog,\n })),\n);\n\ninterface CaptureListProps {\n captures: CaptureSummary[];\n selectedId: number | null;\n wsState: \"live\" | \"down\" | \"unavailable\";\n gateStats: GateStats | null;\n listError: string | null;\n isLoading: boolean;\n onSelect: (id: number) => void;\n onClear: () => void;\n onRetry: () => void;\n}\n\n/**\n * Fixed row height for the virtualizer. Must be >= actual rendered row\n * height to prevent overlap. Calculated from: py-3 (24) + 3 content rows\n * (~65) + border (1) = ~90px; 2px buffer for font/badge variance.\n */\nconst ROW_HEIGHT = 92;\n\nexport function CaptureList({\n captures,\n selectedId,\n wsState,\n gateStats,\n listError,\n isLoading,\n onSelect,\n onClear,\n onRetry,\n}: CaptureListProps) {\n const viewportRef = useRef<HTMLDivElement>(null);\n const { closeDrawer, isOpen } = useMasterDetail();\n const [confirmOpen, setConfirmOpen] = useState(false);\n\n const virtualizer = useVirtualizer({\n count: captures.length,\n getScrollElement: () => viewportRef.current,\n estimateSize: () => ROW_HEIGHT,\n overscan: 8,\n });\n\n const totalHeight = virtualizer.getTotalSize();\n const items = virtualizer.getVirtualItems();\n\n const handleSelect = (id: number) => {\n onSelect(id);\n closeDrawer();\n };\n\n const { activeIndex, activeOptionId, handleKeyDown, handleRowClick } = useCaptureListbox({\n captures,\n selectedId,\n onSelectId: handleSelect,\n scrollToIndex: virtualizer.scrollToIndex,\n });\n\n return (\n <aside className=\"flex h-full w-full min-w-0 flex-col border-r border-border bg-card\">\n <header\n className={cn(\n \"flex items-center justify-between border-b border-border bg-card px-4 py-3\",\n isOpen && \"pr-12\",\n )}\n >\n <h2 className=\"text-sm font-semibold\">\n Captures <span className=\"text-muted-foreground\">({captures.length})</span>\n </h2>\n <div className=\"flex items-center gap-2\">\n <Tooltip>\n <TooltipTrigger asChild>\n <Button variant=\"outline\" size=\"sm\" onClick={() => setConfirmOpen(true)}>\n <Trash2 className=\"mr-1.5 h-3.5 w-3.5\" />\n Clear\n </Button>\n </TooltipTrigger>\n <TooltipContent side=\"bottom\">Remove all recorded captures</TooltipContent>\n </Tooltip>\n </div>\n </header>\n\n <GateStatus stats={gateStats} />\n\n {wsState !== \"live\" && captures.length > 0 && (\n <output\n aria-live=\"polite\"\n className=\"flex items-center gap-1.5 border-b px-4 py-2 text-xs text-muted-foreground\"\n >\n <span className=\"inline-block h-1.5 w-1.5 rounded-full bg-muted-foreground\" aria-hidden />\n List may be stale — {wsState === \"down\" ? \"reconnecting\" : \"disconnected\"}\n </output>\n )}\n\n {captures.length === 0 ? (\n listError ? (\n <section\n aria-label=\"Captures\"\n className=\"flex flex-1 flex-col items-center justify-center gap-3 p-8 text-center text-muted-foreground\"\n >\n <AlertCircle className=\"h-12 w-12 text-destructive\" />\n <p className=\"text-sm font-medium text-destructive\">Something went wrong</p>\n <p className=\"text-xs\">{listError}</p>\n <Tooltip>\n <TooltipTrigger asChild>\n <Button variant=\"outline\" size=\"sm\" onClick={onRetry}>\n <RotateCcw className=\"mr-1.5 h-3.5 w-3.5\" />\n Retry\n </Button>\n </TooltipTrigger>\n <TooltipContent side=\"top\">Retry loading captures</TooltipContent>\n </Tooltip>\n </section>\n ) : isLoading ? (\n <section\n aria-label=\"Captures\"\n className=\"flex flex-1 flex-col items-center justify-center overflow-hidden\"\n >\n <Loader className=\"h-auto\" />\n </section>\n ) : (\n <section\n aria-label=\"Captures\"\n className=\"flex flex-1 flex-col items-center justify-center gap-3 p-8 text-center text-muted-foreground\"\n >\n <Inbox className=\"h-12 w-12 text-muted-foreground/40\" />\n <p className=\"text-sm font-medium\">No captures yet</p>\n <p className=\"text-xs\">Send a request through the proxy to see it here.</p>\n </section>\n )\n ) : (\n <ScrollArea\n className=\"min-h-0 flex-1 overflow-hidden outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ring\"\n viewportRef={viewportRef}\n // biome-ignore lint/a11y/useSemanticElements: virtualized listbox needs role on scroll container\n role=\"listbox\"\n aria-label=\"Captures\"\n aria-activedescendant={activeOptionId}\n tabIndex={0}\n onKeyDown={handleKeyDown}\n >\n <div\n className={cn(\"relative\", wsState !== \"live\" && captures.length > 0 && \"opacity-60\")}\n style={{ height: totalHeight }}\n >\n {items.map((virtualRow) => {\n const c = captures[virtualRow.index];\n if (!c) return null;\n return (\n <div\n key={c.id}\n data-index={virtualRow.index}\n style={{\n position: \"absolute\",\n top: 0,\n left: 0,\n width: \"100%\",\n height: virtualRow.size,\n transform: `translateY(${virtualRow.start}px)`,\n }}\n >\n <CaptureRowItem\n capture={c}\n selected={c.id === selectedId}\n isActive={virtualRow.index === activeIndex}\n optionId={`capture-opt-${c.id}`}\n onActivate={() => handleRowClick(virtualRow.index)}\n />\n </div>\n );\n })}\n </div>\n </ScrollArea>\n )}\n\n {confirmOpen && (\n <Suspense fallback={null}>\n <ClearConfirmDialog\n open={confirmOpen}\n count={captures.length}\n onConfirm={() => {\n setConfirmOpen(false);\n onClear();\n }}\n onClose={() => setConfirmOpen(false)}\n />\n </Suspense>\n )}\n </aside>\n );\n}\n","import { Badge } from \"@/components/ui/badge\";\nimport { Tooltip, TooltipContent, TooltipTrigger } from \"@/components/ui/tooltip\";\nimport { badgeSuccess, badgeWarning, dotSuccess, dotWarning } from \"@/lib/badge-colors\";\nimport { cn } from \"@/lib/utils\";\n\ninterface WsStatusBadgeProps {\n wsState: \"live\" | \"down\" | \"unavailable\";\n}\n\nconst CONFIG = {\n live: {\n label: \"Live\",\n variant: \"secondary\" as const,\n className: badgeSuccess,\n dotClass: dotSuccess,\n pulse: false,\n tip: \"Real-time updates active\",\n },\n down: {\n label: \"Reconnecting\",\n variant: \"secondary\" as const,\n className: badgeWarning,\n dotClass: dotWarning,\n pulse: true,\n tip: \"Connection lost — auto-retrying\",\n },\n unavailable: {\n label: \"Disconnected\",\n variant: \"destructive\" as const,\n className: undefined,\n dotClass: \"bg-destructive\",\n pulse: false,\n tip: \"WebSocket unavailable — refresh page\",\n },\n} as const;\n\nexport function WsStatusBadge({ wsState }: WsStatusBadgeProps) {\n const config = CONFIG[wsState];\n\n return (\n <Tooltip>\n <TooltipTrigger\n render={\n <span\n className=\"inline-flex items-center outline-none focus-visible:ring-2 focus-visible:ring-ring rounded\"\n aria-label={`WebSocket: ${config.label}`}\n />\n }\n >\n <Badge variant={config.variant} size=\"sm\" className={cn(\"gap-1\", config.className)}>\n <span\n aria-hidden\n className={cn(\n \"inline-block h-1.5 w-1.5 rounded-full\",\n config.dotClass,\n config.pulse && \"animate-pulse\",\n )}\n />\n {config.label}\n </Badge>\n </TooltipTrigger>\n <TooltipContent side=\"bottom\">{config.tip}</TooltipContent>\n </Tooltip>\n );\n}\n","import { useCallback, useRef, useState } from \"react\";\n\nimport { API_BASE } from \"@/lib/constants\";\nimport type { CaptureDetail } from \"@/types\";\n\n/**\n * Manages fetching and retrying the selected capture detail.\n *\n * `selectedIdRef` is a stable ref the orchestrator uses to detect whether a\n * completed-stream capture is the currently-selected one (for auto-refresh),\n * without forcing `fetchCapture` to depend on `selectedId`.\n */\nexport interface UseCaptureDetailResult {\n selectedCapture: CaptureDetail | null;\n setSelectedCapture: React.Dispatch<React.SetStateAction<CaptureDetail | null>>;\n selectedId: number | null;\n selectedIdRef: React.RefObject<number | null>;\n selectedCaptureRef: React.RefObject<CaptureDetail | null>;\n isLoadingDetail: boolean;\n detailError: string | null;\n selectCapture: (id: number) => void;\n fetchCapture: (id: number) => Promise<void>;\n retryDetail: () => void;\n resetSelection: () => void;\n}\n\nexport function useCaptureDetail(): UseCaptureDetailResult {\n const [selectedId, setSelectedId] = useState<number | null>(null);\n const [selectedCapture, setSelectedCapture] = useState<CaptureDetail | null>(null);\n const [isLoadingDetail, setIsLoadingDetail] = useState(false);\n const [detailError, setDetailError] = useState<string | null>(null);\n\n const selectedCaptureRef = useRef(selectedCapture);\n selectedCaptureRef.current = selectedCapture;\n\n const selectedIdRef = useRef(selectedId);\n selectedIdRef.current = selectedId;\n\n const fetchCapture = useCallback(async (id: number) => {\n setIsLoadingDetail(true);\n try {\n const r = await fetch(`${API_BASE}/captures/${id}`);\n if (!r.ok) {\n setDetailError(`HTTP ${r.status} ${r.statusText}`);\n return;\n }\n const ct = r.headers.get(\"content-type\") ?? \"\";\n if (!ct.includes(\"application/json\")) {\n setDetailError(\"Backend not reachable\");\n return;\n }\n const c = (await r.json()) as CaptureDetail;\n setSelectedCapture(c);\n setDetailError(null);\n } catch (e) {\n setDetailError(String(e));\n } finally {\n setIsLoadingDetail(false);\n }\n }, []);\n\n const selectCapture = useCallback(\n (id: number) => {\n setSelectedId(id);\n setSelectedCapture(null);\n setDetailError(null);\n void fetchCapture(id);\n },\n [fetchCapture],\n );\n\n const retryDetail = useCallback(() => {\n const id = selectedIdRef.current;\n if (id !== null) {\n void fetchCapture(id);\n }\n }, [fetchCapture]);\n\n const resetSelection = useCallback(() => {\n setSelectedId(null);\n setSelectedCapture(null);\n }, []);\n\n return {\n selectedCapture,\n setSelectedCapture,\n selectedId,\n selectedIdRef,\n selectedCaptureRef,\n isLoadingDetail,\n detailError,\n selectCapture,\n fetchCapture,\n retryDetail,\n resetSelection,\n };\n}\n","import { useCallback, useState } from \"react\";\n\nimport { API_BASE } from \"@/lib/constants\";\nimport type { CaptureSummary } from \"@/types\";\n\n/**\n * Manages fetching, sorting, clearing, and live-updating the capture list.\n *\n * Exposes:\n * - `captures` / `setCaptures` — list state and a setter for socket-driven upserts,\n * state patches, and clears.\n * - `isLoadingList` / `listError` — load lifecycle.\n * - `loadList` / `retryList` — initial and retry fetchers.\n * - `clearCapturesLocal` — clears the in-memory list (used by the socket clear handler\n * and by the orchestrator's hard-clear flow).\n *\n * `backendReachable` is lifted out so the orchestrator can drive the socket based on\n * whether the backend is actually serving JSON.\n */\nexport interface UseCaptureListResult {\n captures: CaptureSummary[];\n setCaptures: React.Dispatch<React.SetStateAction<CaptureSummary[]>>;\n isLoadingList: boolean;\n listError: string | null;\n backendReachable: boolean;\n loadList: () => Promise<void>;\n retryList: () => void;\n}\n\nexport function useCaptureList(): UseCaptureListResult {\n const [captures, setCaptures] = useState<CaptureSummary[]>([]);\n const [isLoadingList, setIsLoadingList] = useState(true);\n const [listError, setListError] = useState<string | null>(null);\n const [backendReachable, setBackendReachable] = useState(false);\n\n const loadList = useCallback(async () => {\n try {\n const r = await fetch(`${API_BASE}/captures?limit=200`);\n if (!r.ok) {\n setListError(`HTTP ${r.status} ${r.statusText}`);\n setBackendReachable(false);\n return;\n }\n const ct = r.headers.get(\"content-type\") ?? \"\";\n if (!ct.includes(\"application/json\")) {\n setBackendReachable(false);\n return;\n }\n const list = (await r.json()) as CaptureSummary[];\n list.sort((a, b) => b.id - a.id);\n setCaptures(list);\n setListError(null);\n setBackendReachable(true);\n } catch (e) {\n setListError(String(e));\n setBackendReachable(false);\n } finally {\n setIsLoadingList(false);\n }\n }, []);\n\n const retryList = useCallback(() => {\n void loadList();\n }, [loadList]);\n\n return {\n captures,\n setCaptures,\n isLoadingList,\n listError,\n backendReachable,\n loadList,\n retryList,\n };\n}\n","import { useEffect, useRef } from \"react\";\n\nimport type { CaptureState, CaptureSummary, GateStats, WsMessage } from \"@/types\";\n\nconst WS_URL = `${window.location.protocol === \"https:\" ? \"wss\" : \"ws\"}://${window.location.host}/dashboard/ws`;\n\n/** Semantic callbacks for each WS message type the hook handles. */\ninterface UseCapturesSocketParams {\n backendReachable: boolean;\n setWsState: (state: \"live\" | \"down\" | \"unavailable\") => void;\n /** Called when the socket connects (used to refresh list + gate). */\n onConnected: () => void;\n /** WS `clear` — wipe all captures. */\n onCaptureClear: () => void;\n /** WS `vision-clear` — remove only vision captures from the list. */\n onVisionClear: () => void;\n /** WS `state` — patch a single capture's state. */\n onCaptureState: (captureId: number, state: CaptureState) => void;\n /** WS `gate` — replace gate stats. */\n onGateStats: (stats: GateStats) => void;\n /** WS `new` / `update` — upsert a capture; `isNew` distinguishes the two. */\n onCaptureUpsert: (capture: CaptureSummary, isNew: boolean) => void;\n}\n\n/**\n * Maps each WS message type to its handler. Adding a new message type\n * requires only one entry here.\n */\ntype WsHandlerMap = {\n [K in WsMessage[\"type\"]]: (msg: Extract<WsMessage, { type: K }>) => void;\n};\n\n/**\n * WebSocket connection with auto-reconnect.\n * Only attempts when the backend is reachable, to avoid console errors\n * when the dashboard is served statically without the proxy backend.\n */\nexport function useCapturesSocket({\n backendReachable,\n setWsState,\n onConnected,\n onCaptureClear,\n onVisionClear,\n onCaptureState,\n onGateStats,\n onCaptureUpsert,\n}: UseCapturesSocketParams) {\n // Keep latest callbacks in refs so the effect doesn't re-run on every render.\n const onConnectedRef = useRef(onConnected);\n onConnectedRef.current = onConnected;\n const onCaptureClearRef = useRef(onCaptureClear);\n onCaptureClearRef.current = onCaptureClear;\n const onVisionClearRef = useRef(onVisionClear);\n onVisionClearRef.current = onVisionClear;\n const onCaptureStateRef = useRef(onCaptureState);\n onCaptureStateRef.current = onCaptureState;\n const onGateStatsRef = useRef(onGateStats);\n onGateStatsRef.current = onGateStats;\n const onCaptureUpsertRef = useRef(onCaptureUpsert);\n onCaptureUpsertRef.current = onCaptureUpsert;\n\n useEffect(() => {\n if (!backendReachable) {\n setWsState(\"unavailable\");\n return;\n }\n\n let ws: WebSocket | null = null;\n let cancelled = false;\n\n // Dispatch registry: one entry per WS message type.\n const handlers: WsHandlerMap = {\n clear: () => onCaptureClearRef.current(),\n \"vision-clear\": () => onVisionClearRef.current(),\n state: (msg) => onCaptureStateRef.current(msg.captureId, msg.state),\n gate: (msg) => onGateStatsRef.current(msg.stats),\n new: (msg) => onCaptureUpsertRef.current(msg.capture, true),\n update: (msg) => onCaptureUpsertRef.current(msg.capture, false),\n };\n\n function connect() {\n try {\n ws = new WebSocket(WS_URL);\n } catch {\n setWsState(\"unavailable\");\n return;\n }\n\n ws.onopen = () => {\n setWsState(\"live\");\n void onConnectedRef.current();\n };\n\n ws.onmessage = (event: MessageEvent<string>) => {\n try {\n const msg = JSON.parse(event.data) as WsMessage;\n // TypeScript can't prove handlers[msg.type] accepts `msg` (a known\n // limitation of discriminated-union indexed access). The cast is\n // safe: WsHandlerMap guarantees each handler matches its variant.\n const handler = handlers[msg.type] as (m: WsMessage) => void;\n handler(msg);\n } catch (e) {\n console.error(e);\n }\n };\n\n ws.onclose = () => {\n setWsState(\"down\");\n if (!cancelled) {\n setTimeout(connect, 1000);\n }\n };\n\n ws.onerror = () => {\n ws?.close();\n };\n }\n\n connect();\n\n return () => {\n cancelled = true;\n ws?.close();\n };\n }, [backendReachable, setWsState]);\n}\n","import { useCallback, useState } from \"react\";\n\nimport { API_BASE } from \"@/lib/constants\";\nimport type { GateStats } from \"@/types\";\n\n/**\n * Manages fetching and live-updating gate stats.\n *\n * The orchestrator wires `setGateStats` to the socket `gate` handler, and\n * calls `loadGate` on initial mount and on socket reconnect.\n */\nexport interface UseGateStatsResult {\n gateStats: GateStats | null;\n setGateStats: React.Dispatch<React.SetStateAction<GateStats | null>>;\n gateError: string | null;\n loadGate: () => Promise<void>;\n retryGate: () => void;\n}\n\nexport function useGateStats(): UseGateStatsResult {\n const [gateStats, setGateStats] = useState<GateStats | null>(null);\n const [gateError, setGateError] = useState<string | null>(null);\n\n const loadGate = useCallback(async () => {\n try {\n const r = await fetch(`${API_BASE}/gate`);\n if (!r.ok) {\n setGateError(`HTTP ${r.status} ${r.statusText}`);\n return;\n }\n const ct = r.headers.get(\"content-type\") ?? \"\";\n if (!ct.includes(\"application/json\")) {\n return;\n }\n setGateStats((await r.json()) as GateStats);\n setGateError(null);\n } catch (e) {\n setGateError(String(e));\n }\n }, []);\n\n const retryGate = useCallback(() => {\n void loadGate();\n }, [loadGate]);\n\n return {\n gateStats,\n setGateStats,\n gateError,\n loadGate,\n retryGate,\n };\n}\n","import { useCallback, useEffect, useState } from \"react\";\n\nimport { useCaptureDetail } from \"@/hooks/use-capture-detail\";\nimport { useCaptureList } from \"@/hooks/use-capture-list\";\nimport { useCapturesSocket } from \"@/hooks/use-captures-socket\";\nimport { useGateStats } from \"@/hooks/use-gate-stats\";\nimport { API_BASE, CAPTURE_DONE_EVENT } from \"@/lib/constants\";\nimport type { CaptureDetail, CaptureSummary, GateStats } from \"@/types\";\n\nexport interface UseCapturesResult {\n captures: CaptureSummary[];\n selectedCapture: CaptureDetail | null;\n isLoadingDetail: boolean;\n isLoadingList: boolean;\n wsState: \"live\" | \"down\" | \"unavailable\";\n selectedId: number | null;\n gateStats: GateStats | null;\n listError: string | null;\n gateError: string | null;\n detailError: string | null;\n selectCapture: (id: number) => void;\n clearCaptures: () => void;\n retryList: () => void;\n retryGate: () => void;\n retryDetail: () => void;\n}\n\nexport function useCaptures(): UseCapturesResult {\n const { captures, setCaptures, isLoadingList, listError, backendReachable, loadList, retryList } =\n useCaptureList();\n\n const {\n selectedCapture,\n selectedId,\n selectedIdRef,\n selectedCaptureRef,\n isLoadingDetail,\n detailError,\n selectCapture,\n fetchCapture,\n retryDetail,\n resetSelection,\n } = useCaptureDetail();\n\n const { gateStats, setGateStats, gateError, loadGate, retryGate } = useGateStats();\n\n const [wsState, setWsState] = useState<\"live\" | \"down\" | \"unavailable\">(\"down\");\n\n // Initial load.\n useEffect(() => {\n void loadList();\n void loadGate();\n }, [loadList, loadGate]);\n\n useCapturesSocket({\n backendReachable,\n setWsState,\n onConnected: () => {\n void loadList();\n void loadGate();\n },\n onCaptureClear: () => {\n setCaptures([]);\n },\n onVisionClear: () => {\n setCaptures((prev) => prev.filter((c) => !c.is_vision));\n },\n onCaptureState: (captureId, state) => {\n setCaptures((prev) => {\n const i = prev.findIndex((c) => c.id === captureId);\n if (i < 0) return prev;\n const next = prev.slice();\n next[i] = { ...next[i], state };\n return next;\n });\n },\n onGateStats: (stats) => {\n setGateStats(stats);\n },\n onCaptureUpsert: (capture, isNew) => {\n setCaptures((prev) => {\n const i = prev.findIndex((x) => x.id === capture.id);\n if (i >= 0) {\n const next = prev.slice();\n next[i] = capture;\n return next;\n }\n // New capture: prepend (newest id goes to front since ids are monotonic)\n return [capture, ...prev];\n });\n\n if (!isNew && capture.state === \"done\") {\n window.dispatchEvent(new CustomEvent(CAPTURE_DONE_EVENT));\n\n if (\n capture.id === selectedIdRef.current &&\n selectedCaptureRef.current?.state === \"streaming\"\n ) {\n void fetchCapture(capture.id);\n }\n }\n },\n });\n\n const clearCaptures = useCallback(async () => {\n try {\n await fetch(`${API_BASE}/clear`, { method: \"POST\" });\n setCaptures([]);\n resetSelection();\n } catch (e) {\n console.error(e);\n }\n }, [setCaptures, resetSelection]);\n\n return {\n captures,\n selectedCapture,\n isLoadingDetail,\n isLoadingList,\n wsState,\n selectedId,\n gateStats,\n listError,\n gateError,\n detailError,\n selectCapture,\n clearCaptures,\n retryList,\n retryGate,\n retryDetail,\n };\n}\n\nexport type { UseCaptureDetailResult } from \"@/hooks/use-capture-detail\";\nexport type { UseCaptureListResult } from \"@/hooks/use-capture-list\";\nexport type { UseGateStatsResult } from \"@/hooks/use-gate-stats\";\n","import { useCallback } from \"react\";\n\nexport function useClipboard(): {\n copyText: (text: string) => Promise<boolean>;\n} {\n const copyText = useCallback(async (text: string): Promise<boolean> => {\n try {\n if (navigator.clipboard && window.isSecureContext) {\n await navigator.clipboard.writeText(text);\n return true;\n }\n } catch {\n // fall through to textarea fallback\n }\n\n const ta = document.createElement(\"textarea\");\n ta.value = text;\n ta.style.position = \"fixed\";\n ta.style.top = \"-9999px\";\n document.body.appendChild(ta);\n ta.focus();\n ta.select();\n\n let ok = false;\n try {\n ok = document.execCommand(\"copy\");\n } catch {\n // ignore\n }\n document.body.removeChild(ta);\n return ok;\n }, []);\n\n return { copyText };\n}\n","import { Menu } from \"lucide-react\";\nimport { Suspense, lazy, useState } from \"react\";\nimport type { ReactNode } from \"react\";\n\nimport { ApiKeyGate } from \"@/components/api-key-gate\";\nimport { CaptureDetailPanel } from \"@/components/capture-detail\";\nimport { CaptureList } from \"@/components/capture-list\";\nimport {\n MasterDetailLayout,\n MasterDetailProvider,\n useMasterDetail,\n} from \"@/components/layout/master-detail-layout\";\nimport { Button } from \"@/components/ui/button\";\nimport { Loader } from \"@/components/ui/loader\";\nimport { Tabs, TabsContent, TabsList, TabsTrigger } from \"@/components/ui/tabs\";\nimport { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from \"@/components/ui/tooltip\";\nimport { WsStatusBadge } from \"@/components/ws-status-badge\";\nimport { useCaptures } from \"@/hooks/use-captures\";\nimport { useClipboard } from \"@/hooks/use-clipboard\";\nimport { ConfigProvider } from \"@/hooks/use-config-context\";\n\nconst ConfigTab = lazy(() =>\n import(\"@/components/config-tab\").then((m) => ({ default: m.ConfigTab })),\n);\nconst ModelsTab = lazy(() =>\n import(\"@/components/models-tab\").then((m) => ({ default: m.ModelsTab })),\n);\nconst PerformanceMeter = lazy(() =>\n import(\"@/components/performance-meter\").then((m) => ({ default: m.PerformanceMeter })),\n);\nconst EconomicsTab = lazy(() =>\n import(\"@/components/economics-tab\").then((m) => ({ default: m.EconomicsTab })),\n);\nconst VisionCalls = lazy(() =>\n import(\"@/components/vision-calls\").then((m) => ({ default: m.VisionCalls })),\n);\nconst ModeToggle = lazy(() =>\n import(\"@/components/mode-toggle\").then((m) => ({ default: m.ModeToggle })),\n);\nconst Toaster = lazy(() => import(\"@/components/ui/sonner\").then((m) => ({ default: m.Toaster })));\n\nfunction TabPanelFallback() {\n return <Loader />;\n}\n\ninterface TabTipProps {\n value: string;\n label: string;\n tip: string;\n children?: ReactNode;\n}\n\nfunction TabTriggerWithTip({ value, label, tip }: TabTipProps) {\n return (\n <Tooltip>\n <TooltipTrigger render={<span />}>\n <TabsTrigger value={value}>{label}</TabsTrigger>\n </TooltipTrigger>\n <TooltipContent side=\"bottom\">{tip}</TooltipContent>\n </Tooltip>\n );\n}\n\nexport function App() {\n const {\n captures,\n selectedCapture,\n isLoadingDetail,\n isLoadingList,\n wsState,\n selectedId,\n gateStats,\n listError,\n detailError,\n selectCapture,\n clearCaptures,\n retryList,\n retryDetail,\n } = useCaptures();\n\n const { copyText } = useClipboard();\n const [copyStatus, setCopyStatus] = useState(\"Copy\");\n\n return (\n <ConfigProvider>\n <TooltipProvider delay={300}>\n <MasterDetailProvider>\n <ApiKeyGate />\n <div className=\"h-screen flex flex-col overflow-hidden bg-background text-foreground\">\n <a\n href=\"#main\"\n className=\"sr-only focus:not-sr-only focus:absolute focus:z-50 focus:top-2 focus:left-2 focus:rounded-md focus:bg-background focus:px-4 focus:py-2 focus:text-sm focus:font-medium focus:shadow-lg focus:border focus:border-border\"\n >\n Skip to content\n </a>\n <h1 className=\"sr-only\">umans-gate</h1>\n <Tabs defaultValue=\"captures\" className=\"flex flex-1 flex-col overflow-hidden\">\n <header className=\"flex items-center gap-2 px-4 py-2 border-b bg-background\">\n <MobileDrawerTrigger />\n <WsStatusBadge wsState={wsState} />\n <div className=\"tab-scroll flex-1 min-w-0 overflow-x-auto overflow-y-hidden scrollbar-none\">\n <TabsList className=\"flex w-max md:mx-auto md:w-fit\">\n <TabTriggerWithTip\n value=\"captures\"\n label=\"Captures\"\n tip=\"Live log of every intercepted API call\"\n />\n <TabTriggerWithTip\n value=\"vision\"\n label=\"Vision Calls\"\n tip=\"Image-bearing requests with model responses\"\n />\n <TabTriggerWithTip\n value=\"performance\"\n label=\"Performance\"\n tip=\"Per-model TTFT, TPS, and token throughput\"\n />\n <TabTriggerWithTip\n value=\"economics\"\n label=\"Economics\"\n tip=\"Daily usage accumulation and cost tracking\"\n />\n <TabTriggerWithTip\n value=\"models\"\n label=\"Models\"\n tip=\"Upstream model catalog with pricing\"\n />\n <TabTriggerWithTip\n value=\"config\"\n label=\"Config\"\n tip=\"Edit proxy settings and reload live\"\n />\n </TabsList>\n </div>\n <Suspense fallback={null}>\n <ModeToggle />\n </Suspense>\n </header>\n <main\n id=\"main\"\n aria-label=\"Inspector\"\n className=\"flex-1 flex flex-col overflow-hidden\"\n >\n <TabsContent value=\"captures\" className=\"flex-1 overflow-hidden\" keepMounted>\n <MasterDetailLayout\n master={\n <CaptureList\n captures={captures}\n selectedId={selectedId}\n wsState={wsState}\n gateStats={gateStats}\n listError={listError}\n isLoading={isLoadingList}\n onSelect={selectCapture}\n onClear={clearCaptures}\n onRetry={retryList}\n />\n }\n detail={\n <CaptureDetailPanel\n capture={selectedCapture}\n isLoading={isLoadingDetail}\n detailError={detailError}\n onCopy={copyText}\n onCopyStatus={setCopyStatus}\n onRetry={retryDetail}\n />\n }\n masterAriaLabel=\"Captures list\"\n detailAriaLabel=\"Capture detail\"\n />\n </TabsContent>\n <TabsContent value=\"vision\" className=\"min-h-0 flex-1 overflow-hidden\" keepMounted>\n <Suspense fallback={<TabPanelFallback />}>\n <VisionCalls />\n </Suspense>\n </TabsContent>\n <TabsContent\n value=\"performance\"\n className=\"min-h-0 flex-1 overflow-hidden\"\n keepMounted\n >\n <Suspense fallback={<TabPanelFallback />}>\n <PerformanceMeter />\n </Suspense>\n </TabsContent>\n <TabsContent value=\"models\" className=\"min-h-0 flex-1 overflow-hidden\" keepMounted>\n <Suspense fallback={<TabPanelFallback />}>\n <ModelsTab />\n </Suspense>\n </TabsContent>\n <TabsContent\n value=\"economics\"\n className=\"min-h-0 flex-1 overflow-hidden\"\n keepMounted\n >\n <Suspense fallback={<TabPanelFallback />}>\n <EconomicsTab />\n </Suspense>\n </TabsContent>\n <TabsContent value=\"config\" className=\"min-h-0 flex-1 overflow-hidden\" keepMounted>\n <Suspense fallback={<TabPanelFallback />}>\n <ConfigTab />\n </Suspense>\n </TabsContent>\n </main>\n </Tabs>\n <Suspense fallback={null}>\n <Toaster />\n </Suspense>\n <output aria-live=\"polite\" className=\"sr-only\">\n {copyStatus}\n </output>\n </div>\n </MasterDetailProvider>\n </TooltipProvider>\n </ConfigProvider>\n );\n}\n\nfunction MobileDrawerTrigger() {\n const { openDrawer } = useMasterDetail();\n return (\n <Tooltip>\n <TooltipTrigger asChild>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n className=\"md:hidden\"\n aria-label=\"Open captures\"\n onClick={openDrawer}\n >\n <Menu className=\"h-5 w-5\" />\n </Button>\n </TooltipTrigger>\n <TooltipContent side=\"bottom\">Open captures list</TooltipContent>\n </Tooltip>\n );\n}\n\nexport default App;\n","import React from \"react\";\n\nimport { Button } from \"@/components/ui/button\";\nimport { Tooltip, TooltipContent, TooltipTrigger } from \"@/components/ui/tooltip\";\n\ninterface ErrorBoundaryProps {\n children: React.ReactNode;\n fallback?: React.ReactNode;\n}\n\ninterface ErrorBoundaryState {\n error: Error | null;\n}\n\nexport class ErrorBoundary extends React.Component<ErrorBoundaryProps, ErrorBoundaryState> {\n state: ErrorBoundaryState = { error: null };\n\n static getDerivedStateFromError(error: Error): ErrorBoundaryState {\n return { error };\n }\n\n render(): React.ReactNode {\n const { error } = this.state;\n if (!error) {\n return this.props.children;\n }\n\n return (\n this.props.fallback ?? (\n <div className=\"flex flex-col items-center justify-center gap-3 p-8 text-center text-muted-foreground\">\n <p className=\"text-sm font-medium text-destructive\">Something went wrong</p>\n <p className=\"text-xs\">{error.message}</p>\n <Tooltip>\n <TooltipTrigger\n render={\n <Button variant=\"outline\" size=\"sm\" onClick={() => window.location.reload()} />\n }\n >\n Reload\n </TooltipTrigger>\n <TooltipContent side=\"top\">Reload the page</TooltipContent>\n </Tooltip>\n </div>\n )\n );\n }\n}\n","import * as React from \"react\";\n\ntype Theme = \"dark\" | \"light\" | \"system\";\ntype ResolvedTheme = \"dark\" | \"light\";\n\ninterface ThemeProviderProps {\n children: React.ReactNode;\n defaultTheme?: Theme;\n storageKey?: string;\n}\n\ninterface ThemeProviderState {\n theme: Theme;\n resolvedTheme: ResolvedTheme;\n setTheme: (theme: Theme) => void;\n}\n\nconst ThemeProviderContext = React.createContext<ThemeProviderState | undefined>(undefined);\n\nfunction getSystemTheme(): ResolvedTheme {\n if (typeof window === \"undefined\") {\n return \"light\";\n }\n return window.matchMedia(\"(prefers-color-scheme: dark)\").matches ? \"dark\" : \"light\";\n}\n\nfunction applyTheme(theme: Theme): ResolvedTheme {\n const root = window.document.documentElement;\n root.classList.remove(\"light\", \"dark\");\n\n const resolved: ResolvedTheme = theme === \"system\" ? getSystemTheme() : theme;\n root.classList.add(resolved);\n return resolved;\n}\n\nexport function ThemeProvider({\n children,\n defaultTheme = \"system\",\n storageKey = \"umans-gate-theme\",\n}: ThemeProviderProps) {\n const [theme, setThemeState] = React.useState<Theme>(() => {\n if (typeof window === \"undefined\") {\n return defaultTheme;\n }\n const stored = window.localStorage.getItem(storageKey) as Theme | null;\n return stored ?? defaultTheme;\n });\n\n const [resolvedTheme, setResolvedTheme] = React.useState<ResolvedTheme>(() =>\n theme === \"system\" ? getSystemTheme() : theme,\n );\n\n React.useEffect(() => {\n const resolved = applyTheme(theme);\n setResolvedTheme(resolved);\n\n if (theme !== \"system\") {\n return;\n }\n\n const mql = window.matchMedia(\"(prefers-color-scheme: dark)\");\n const onChange = (e: MediaQueryListEvent) => {\n const next: ResolvedTheme = e.matches ? \"dark\" : \"light\";\n window.document.documentElement.classList.remove(\"light\", \"dark\");\n window.document.documentElement.classList.add(next);\n setResolvedTheme(next);\n };\n mql.addEventListener(\"change\", onChange);\n return () => mql.removeEventListener(\"change\", onChange);\n }, [theme]);\n\n const value: ThemeProviderState = React.useMemo(\n () => ({\n theme,\n resolvedTheme,\n setTheme: (next: Theme) => {\n window.localStorage.setItem(storageKey, next);\n setThemeState(next);\n },\n }),\n [theme, resolvedTheme, storageKey],\n );\n\n return <ThemeProviderContext.Provider value={value}>{children}</ThemeProviderContext.Provider>;\n}\n\nexport function useTheme(): ThemeProviderState {\n const context = React.useContext(ThemeProviderContext);\n if (context === undefined) {\n throw new Error(\"useTheme must be used within a ThemeProvider\");\n }\n return context;\n}\n\nexport type { Theme };\n","import { StrictMode } from \"react\";\nimport { createRoot } from \"react-dom/client\";\n\nimport \"@fontsource-variable/geist\";\nimport App from \"./App\";\nimport { ErrorBoundary } from \"./components/error-boundary\";\nimport { ThemeProvider } from \"./components/theme-provider\";\nimport \"./index.css\";\n\nif (import.meta.env.DEV) {\n import(\"./dev-tools\");\n}\n\nconst rootElement = document.getElementById(\"root\");\nif (!rootElement) {\n throw new Error(\"Missing root element\");\n}\n\ncreateRoot(rootElement).render(\n <StrictMode>\n <ErrorBoundary>\n <ThemeProvider defaultTheme=\"system\" storageKey=\"umans-gate-theme\">\n <App />\n </ThemeProvider>\n </ErrorBoundary>\n </StrictMode>,\n);\n"],"file":"assets/index-72wCsW4_.js"}