@raingor/pi-web-switch 0.3.1 → 0.3.3

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 (738) hide show
  1. package/.pi/.pi-puppeteer/artifacts/screenshots/session-1-1785132166652.png +0 -0
  2. package/.pi/.pi-puppeteer/artifacts/screenshots/session-1-1785291744290.png +0 -0
  3. package/.pi/.pi-puppeteer/artifacts/screenshots/session-1-1785291756870.png +0 -0
  4. package/.pi/.pi-puppeteer/artifacts/screenshots/session-1-1785293871314.png +0 -0
  5. package/.pi/.pi-puppeteer/artifacts/screenshots/session-10-1785297139944.png +0 -0
  6. package/.pi/.pi-puppeteer/artifacts/screenshots/session-2-1785132240502.png +0 -0
  7. package/.pi/.pi-puppeteer/artifacts/screenshots/session-2-1785132249748.png +0 -0
  8. package/.pi/.pi-puppeteer/artifacts/screenshots/session-2-1785294992352.png +0 -0
  9. package/.pi/.pi-puppeteer/artifacts/screenshots/session-2-1785295104532.png +0 -0
  10. package/.pi/.pi-puppeteer/artifacts/screenshots/session-2-1785295132507.png +0 -0
  11. package/.pi/.pi-puppeteer/artifacts/screenshots/session-3-1785132387218.png +0 -0
  12. package/.pi/.pi-puppeteer/artifacts/screenshots/session-4-1785295319523.png +0 -0
  13. package/.pi/.pi-puppeteer/artifacts/screenshots/session-4-1785295349664.png +0 -0
  14. package/.pi/.pi-puppeteer/artifacts/screenshots/session-4-1785295399600.png +0 -0
  15. package/.pi/.pi-puppeteer/artifacts/screenshots/session-5-1785295450850.png +0 -0
  16. package/.pi/.pi-puppeteer/artifacts/screenshots/session-5-1785295487872.png +0 -0
  17. package/.pi/.pi-puppeteer/artifacts/screenshots/session-5-1785295562600.png +0 -0
  18. package/.pi/.pi-puppeteer/artifacts/screenshots/session-5-1785295761054.png +0 -0
  19. package/.pi/.pi-puppeteer/artifacts/screenshots/session-5-1785295840175.png +0 -0
  20. package/.pi/.pi-puppeteer/artifacts/screenshots/session-6-1785295915007.png +0 -0
  21. package/.pi/.pi-puppeteer/artifacts/screenshots/session-6-1785296069913.png +0 -0
  22. package/.pi/.pi-puppeteer/artifacts/screenshots/session-7-1785296128252.png +0 -0
  23. package/.pi/.pi-puppeteer/artifacts/screenshots/session-9-1785297091531.png +0 -0
  24. package/.pi/.pi-puppeteer/artifacts/screenshots/session-9-1785297116790.png +0 -0
  25. package/.pi/.pi-puppeteer/profiles/chrome/default/ActorSafetyLists/9.5220.3721/_metadata/verified_contents.json +1 -0
  26. package/.pi/.pi-puppeteer/profiles/chrome/default/ActorSafetyLists/9.5220.3721/listdata.json +91946 -0
  27. package/.pi/.pi-puppeteer/profiles/chrome/default/ActorSafetyLists/9.5220.3721/manifest.json +5 -0
  28. package/.pi/.pi-puppeteer/profiles/chrome/default/AmountExtractionHeuristicRegexes/4/_metadata/verified_contents.json +1 -0
  29. package/.pi/.pi-puppeteer/profiles/chrome/default/AmountExtractionHeuristicRegexes/4/heuristic_regexes.binarypb +3 -0
  30. package/.pi/.pi-puppeteer/profiles/chrome/default/AmountExtractionHeuristicRegexes/4/manifest.json +5 -0
  31. package/.pi/.pi-puppeteer/profiles/chrome/default/BrowserMetrics/BrowserMetrics-6A6978EB-A861.pma +0 -0
  32. package/.pi/.pi-puppeteer/profiles/chrome/default/BrowserMetrics-spare.pma +0 -0
  33. package/.pi/.pi-puppeteer/profiles/chrome/default/CaptchaProviders/8.5419.4434/_metadata/verified_contents.json +1 -0
  34. package/.pi/.pi-puppeteer/profiles/chrome/default/CaptchaProviders/8.5419.4434/captcha_providers.json +12 -0
  35. package/.pi/.pi-puppeteer/profiles/chrome/default/CaptchaProviders/8.5419.4434/manifest.json +5 -0
  36. package/.pi/.pi-puppeteer/profiles/chrome/default/CertificateRevocation/10680/LICENSE +27 -0
  37. package/.pi/.pi-puppeteer/profiles/chrome/default/CertificateRevocation/10680/_metadata/verified_contents.json +1 -0
  38. package/.pi/.pi-puppeteer/profiles/chrome/default/CertificateRevocation/10680/crl-set +0 -0
  39. package/.pi/.pi-puppeteer/profiles/chrome/default/CertificateRevocation/10680/manifest.json +5 -0
  40. package/.pi/.pi-puppeteer/profiles/chrome/default/ChromeFeatureState +1 -0
  41. package/.pi/.pi-puppeteer/profiles/chrome/default/Consent To Send Stats +1 -0
  42. package/.pi/.pi-puppeteer/profiles/chrome/default/Crowd Deny/2026.7.27.84/Preload Data +24078 -0
  43. package/.pi/.pi-puppeteer/profiles/chrome/default/Crowd Deny/2026.7.27.84/_metadata/verified_contents.json +1 -0
  44. package/.pi/.pi-puppeteer/profiles/chrome/default/Crowd Deny/2026.7.27.84/manifest.json +6 -0
  45. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/.com.google.Chrome.Hbf1ld +0 -0
  46. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Account Web Data +0 -0
  47. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Account Web Data-journal +0 -0
  48. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Affiliation Database +0 -0
  49. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Affiliation Database-journal +0 -0
  50. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/AutofillAiModelCache/LOCK +0 -0
  51. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/AutofillAiModelCache/LOG +0 -0
  52. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/AutofillAiModelCache/LOG.old +0 -0
  53. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/AutofillStrikeDatabase/LOCK +0 -0
  54. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/AutofillStrikeDatabase/LOG +0 -0
  55. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/AutofillStrikeDatabase/LOG.old +0 -0
  56. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/BookmarkMergedSurfaceOrdering +2 -0
  57. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/BudgetDatabase/LOCK +0 -0
  58. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/BudgetDatabase/LOG +0 -0
  59. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/BudgetDatabase/LOG.old +0 -0
  60. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/003827f5ea5ac9e9_0 +0 -0
  61. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/00473eec8b9b56d5_0 +0 -0
  62. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/05a190c784b641e3_0 +0 -0
  63. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/066df8884be8cf8d_0 +0 -0
  64. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/09627b0809e61f83_0 +0 -0
  65. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/09b27ac23861b1d7_0 +0 -0
  66. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/0fd9412b623e5a66_0 +0 -0
  67. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/118fb0fa2505d3b2_0 +0 -0
  68. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/1194588b7e2b20e9_0 +0 -0
  69. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/135a3004445f6f03_0 +0 -0
  70. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/13f1e7131fe25bc6_0 +0 -0
  71. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/15a2a5dccd304be7_0 +0 -0
  72. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/17893ac60e1e94c2_0 +0 -0
  73. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/19474b63539a4609_0 +0 -0
  74. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/1a1ecc22219568db_0 +0 -0
  75. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/1bb0006133ebefa3_0 +0 -0
  76. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/1cfaeeed4b13a026_0 +0 -0
  77. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/1e3cf5f23a4de58b_0 +0 -0
  78. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/20427e8d33888ba3_0 +0 -0
  79. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/2258d238accf0bfa_0 +0 -0
  80. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/228c3ad9d63adf48_0 +0 -0
  81. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/2437d308abe15ac2_0 +0 -0
  82. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/246f33a252b55bce_0 +0 -0
  83. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/25862298f2999d7d_0 +0 -0
  84. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/262d9bff9f7f64bb_0 +0 -0
  85. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/264aad789515de93_0 +0 -0
  86. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/269ad8897b8e63d0_0 +0 -0
  87. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/2cd2c50a38161cab_0 +0 -0
  88. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/2dd4db1365eeeac8_0 +0 -0
  89. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/2eae0c639fd772df_0 +0 -0
  90. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/30bb21d39b68bd84_0 +0 -0
  91. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/31121aeb5ecffa5f_0 +0 -0
  92. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/32766be1527c8e9a_0 +0 -0
  93. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/328e80b1ed10d28d_0 +0 -0
  94. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/339dcbdde8b8ac4e_0 +0 -0
  95. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/34439c1d4bfc8dad_0 +0 -0
  96. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/381d5603ee3fd8b9_0 +0 -0
  97. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/38fbe92680d28074_0 +0 -0
  98. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/393ce7bb08410970_0 +0 -0
  99. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/3d74b8be0f86614f_0 +0 -0
  100. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/4016e35a2021656d_0 +0 -0
  101. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/409bcaf42c9c09b4_0 +0 -0
  102. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/41888ebeeb475a59_0 +0 -0
  103. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/4714ef11264459f5_0 +0 -0
  104. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/479d2c4f7d4f3b38_0 +0 -0
  105. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/4824ea24720f1a77_0 +0 -0
  106. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/4a73d37e6e4ce922_0 +0 -0
  107. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/4ecdd068adbdf42a_0 +0 -0
  108. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/54e6cc05346dd07c_0 +0 -0
  109. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/5505ea174dc90263_0 +0 -0
  110. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/551679343b836505_0 +0 -0
  111. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/573f6264a77df462_0 +0 -0
  112. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/578926a5c39768ed_0 +0 -0
  113. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/582a8182776d9380_0 +0 -0
  114. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/5f3aa184b329759d_0 +0 -0
  115. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/6351cd107efed247_0 +0 -0
  116. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/637516a46d1d8587_0 +0 -0
  117. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/65e82d9cb58cbd6d_0 +0 -0
  118. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/66d24a1529d6dae0_0 +0 -0
  119. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/6995a7c799490d3d_0 +0 -0
  120. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/6d10426240c5ff67_0 +0 -0
  121. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/6dc325603c897784_0 +0 -0
  122. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/6fbab020dd731222_0 +0 -0
  123. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/70fa542a6974378a_0 +0 -0
  124. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/72a8c452abd1b0e6_0 +0 -0
  125. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/72df48e9888c822b_0 +0 -0
  126. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/73abcb8da3b9f73d_0 +0 -0
  127. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/741e8bcc257a64a9_0 +0 -0
  128. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/75df0820975fcdfa_0 +0 -0
  129. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/7789e307be36811d_0 +0 -0
  130. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/79a161a9b2f4a11e_0 +0 -0
  131. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/7afd0bc7f9852bf0_0 +0 -0
  132. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/7ce691ce1ceb3b8d_0 +0 -0
  133. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/7ef6780a186001ac_0 +0 -0
  134. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/80402f00feb6a222_0 +0 -0
  135. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/85b55ea0ca260643_0 +0 -0
  136. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/86300205c03092e4_0 +0 -0
  137. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/87c94a2eac816ea9_0 +0 -0
  138. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/880c25af3ab59187_0 +0 -0
  139. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/8a7d0881c813aeec_0 +0 -0
  140. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/8bad3b1bccd25517_0 +0 -0
  141. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/8bd9377481fa7d43_0 +0 -0
  142. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/8c1a58ce19e15d16_0 +0 -0
  143. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/8e44e385f5911b07_0 +0 -0
  144. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/90e39d8d065f6ac0_0 +0 -0
  145. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/93d81321f8c35eab_0 +0 -0
  146. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/93e9945beb439414_0 +0 -0
  147. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/944e08f273fccc44_0 +0 -0
  148. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/95edd63493c49660_0 +0 -0
  149. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/9789c4ee76bdb350_0 +0 -0
  150. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/9a5911308e0f26ad_0 +0 -0
  151. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/9a6cdf8f5c03aee5_0 +0 -0
  152. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/9aeb4a3d1a607b07_0 +0 -0
  153. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/9aff0e1ff1742ee0_0 +0 -0
  154. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/9bdabd2703f2e3ba_0 +0 -0
  155. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/9d4d11ac8a8e264f_0 +0 -0
  156. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/9dd169e672e31961_0 +0 -0
  157. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/9e72442bf8821115_0 +0 -0
  158. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/a330965ccf5564ca_0 +0 -0
  159. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/a3a3c6351a3f2f42_0 +0 -0
  160. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/a818977d416f829d_0 +0 -0
  161. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/aa452720fc9d634f_0 +0 -0
  162. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/ac06b722aea9fcb8_0 +0 -0
  163. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/aca3b8cf1f98e0bb_0 +0 -0
  164. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/add439b7aae9334a_0 +0 -0
  165. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/b0113626d8ba968d_0 +0 -0
  166. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/ba97b9d927729aa7_0 +0 -0
  167. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/bfcb9d225e4f11a8_0 +0 -0
  168. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/c364377515d768e0_0 +0 -0
  169. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/c4376485fa897eca_0 +0 -0
  170. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/c5b74f49505d3ecc_0 +0 -0
  171. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/c7e10eb03f6d5cc2_0 +0 -0
  172. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/c91efba145098b4c_0 +0 -0
  173. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/caecbbde37e3c866_0 +0 -0
  174. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/cdddd64b252697fd_0 +0 -0
  175. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/d3efa3ab37db7796_0 +0 -0
  176. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/d6289ab00fe343c0_0 +0 -0
  177. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/d6be42432091d3ae_0 +0 -0
  178. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/d7137f065f39412f_0 +0 -0
  179. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/d83db61c108fa34f_0 +0 -0
  180. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/d86cd6e1d99a8eaf_0 +0 -0
  181. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/d97f1cfcc2edd001_0 +0 -0
  182. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/de620df53673a107_0 +0 -0
  183. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/de86892a6fa4e33b_0 +0 -0
  184. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/deb2cfe585bf96b0_0 +0 -0
  185. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/df93d6767095d5ea_0 +0 -0
  186. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/e1f8d8432edb7ea6_0 +0 -0
  187. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/e2e1058ec6a8e645_0 +0 -0
  188. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/e39ddd81e303f259_0 +0 -0
  189. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/e468a0fb6aa7fd4e_0 +0 -0
  190. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/e46f51470717ac3c_0 +0 -0
  191. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/e4a531774ba47406_0 +0 -0
  192. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/e57a3a1fa60638e1_0 +0 -0
  193. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/e594d414c7f4d6a1_0 +0 -0
  194. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/e771a081db13a5b8_0 +0 -0
  195. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/e78c0ca6dbdafcd0_0 +0 -0
  196. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/e8e671ad5c3fb2a8_0 +0 -0
  197. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/e96e46c4d92b214f_0 +0 -0
  198. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/ea24ade36915d935_0 +0 -0
  199. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/eaa70273ce58d3b3_0 +0 -0
  200. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/eca41bfe04d1680d_0 +0 -0
  201. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/ed551f6d52fa6049_0 +0 -0
  202. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/ee2190fb8068ea31_0 +0 -0
  203. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/ee688f43baa25b4b_0 +0 -0
  204. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/f016dffa17337f95_0 +0 -0
  205. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/f0707f1f113fa72c_0 +0 -0
  206. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/f12650f2be214ec8_0 +0 -0
  207. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/f1887b75d61dbd90_0 +0 -0
  208. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/f28900863f2e45b7_0 +0 -0
  209. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/f4ee911c81881048_0 +0 -0
  210. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/f557a2bca202c132_0 +0 -0
  211. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/f61ed35c6c0b87d8_0 +0 -0
  212. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/f6f1caefb3e18ade_0 +0 -0
  213. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/fd695fa621d42490_0 +0 -0
  214. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/index +0 -0
  215. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/Cache_Data/index-dir/the-real-index +0 -0
  216. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/No_Vary_Search/journal.baj +1 -0
  217. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cache/No_Vary_Search/snapshot.baf +0 -0
  218. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/ClientCertificates/LOCK +0 -0
  219. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/ClientCertificates/LOG +0 -0
  220. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/ClientCertificates/LOG.old +0 -0
  221. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Code Cache/js/02b3a268866a7a0c_0 +0 -0
  222. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Code Cache/js/0edbc65a5e505019_0 +0 -0
  223. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Code Cache/js/1051d2e224b9dd7a_0 +0 -0
  224. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Code Cache/js/13cf7a1704163ded_0 +0 -0
  225. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Code Cache/js/16860cee78cb7179_0 +0 -0
  226. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Code Cache/js/17ea85d6fceb9229_0 +0 -0
  227. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Code Cache/js/1b6c1ba202c59494_0 +0 -0
  228. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Code Cache/js/1ebec9ea59157454_0 +0 -0
  229. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Code Cache/js/1ee2a6b57d251d09_0 +0 -0
  230. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Code Cache/js/2445a9737b996e2a_0 +0 -0
  231. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Code Cache/js/2d10a08da99d6d96_0 +0 -0
  232. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Code Cache/js/325c8b935b677e9d_0 +0 -0
  233. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Code Cache/js/454c49e6be2650e9_0 +0 -0
  234. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Code Cache/js/4a34df5a255ad22e_0 +0 -0
  235. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Code Cache/js/4dfd5beef212627f_0 +0 -0
  236. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Code Cache/js/5fe872a733479fff_0 +0 -0
  237. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Code Cache/js/66943b0755a2799d_0 +0 -0
  238. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Code Cache/js/6a1839253b0d0b0a_0 +0 -0
  239. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Code Cache/js/6e13894af36f3b79_0 +0 -0
  240. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Code Cache/js/786d3f1f49d31154_0 +0 -0
  241. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Code Cache/js/82f67f35254528ab_0 +0 -0
  242. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Code Cache/js/831e5a135cde918e_0 +0 -0
  243. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Code Cache/js/9965b2c8a33ec50d_0 +0 -0
  244. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Code Cache/js/a15b1367fd75ef89_0 +0 -0
  245. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Code Cache/js/a7c7741248aeea07_0 +0 -0
  246. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Code Cache/js/a8e54c52a52541a9_0 +0 -0
  247. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Code Cache/js/afa0d16c75997a6c_0 +0 -0
  248. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Code Cache/js/b35d29b5b3583a88_0 +0 -0
  249. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Code Cache/js/bc55d051b6fd0744_0 +0 -0
  250. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Code Cache/js/bc8566d00f634dfb_0 +0 -0
  251. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Code Cache/js/c0be8aeb35882f7c_0 +0 -0
  252. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Code Cache/js/c771807a395d295c_0 +0 -0
  253. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Code Cache/js/c9058e9015c26dc7_0 +0 -0
  254. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Code Cache/js/d6804628a868f972_0 +0 -0
  255. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Code Cache/js/d7f211a5cec70609_0 +0 -0
  256. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Code Cache/js/d9c03164fc246389_0 +0 -0
  257. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Code Cache/js/e1011bf217f0ad7a_0 +0 -0
  258. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Code Cache/js/efd85d739d006527_0 +0 -0
  259. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Code Cache/js/f5fe496bf55cd561_0 +0 -0
  260. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Code Cache/js/fc52f43646894a73_0 +0 -0
  261. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Code Cache/js/fc8954eb9445852d_0 +0 -0
  262. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Code Cache/js/ff6de2f37189b29f_0 +0 -0
  263. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Code Cache/js/index +0 -0
  264. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Code Cache/js/index-dir/the-real-index +0 -0
  265. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Code Cache/wasm/index +0 -0
  266. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Code Cache/wasm/index-dir/the-real-index +0 -0
  267. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cookies +0 -0
  268. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Cookies-journal +0 -0
  269. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/DIPS +0 -0
  270. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/DawnGraphiteCache/data_0 +0 -0
  271. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/DawnGraphiteCache/data_1 +0 -0
  272. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/DawnGraphiteCache/data_2 +0 -0
  273. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/DawnGraphiteCache/data_3 +0 -0
  274. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/DawnGraphiteCache/index +0 -0
  275. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/DawnWebGPUCache/data_0 +0 -0
  276. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/DawnWebGPUCache/data_1 +0 -0
  277. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/DawnWebGPUCache/data_2 +0 -0
  278. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/DawnWebGPUCache/data_3 +0 -0
  279. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/DawnWebGPUCache/index +0 -0
  280. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Extension Rules/CURRENT +1 -0
  281. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Extension Rules/LOCK +0 -0
  282. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Extension Rules/LOG +2 -0
  283. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Extension Rules/MANIFEST-000001 +0 -0
  284. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Extension Scripts/CURRENT +1 -0
  285. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Extension Scripts/LOCK +0 -0
  286. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Extension Scripts/LOG +2 -0
  287. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Extension Scripts/MANIFEST-000001 +0 -0
  288. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Extension State/CURRENT +1 -0
  289. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Extension State/LOCK +0 -0
  290. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Extension State/LOG +3 -0
  291. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Extension State/LOG.old +3 -0
  292. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Extension State/MANIFEST-000001 +0 -0
  293. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Favicons +0 -0
  294. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Favicons-journal +0 -0
  295. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Feature Engagement Tracker/AvailabilityDB/LOCK +0 -0
  296. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Feature Engagement Tracker/AvailabilityDB/LOG +0 -0
  297. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Feature Engagement Tracker/AvailabilityDB/LOG.old +0 -0
  298. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Feature Engagement Tracker/EventDB/LOCK +0 -0
  299. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Feature Engagement Tracker/EventDB/LOG +0 -0
  300. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Feature Engagement Tracker/EventDB/LOG.old +0 -0
  301. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/GCM Store/CURRENT +1 -0
  302. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/GCM Store/LOCK +0 -0
  303. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/GCM Store/LOG +3 -0
  304. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/GCM Store/LOG.old +3 -0
  305. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/GCM Store/MANIFEST-000001 +0 -0
  306. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/GPUCache/data_0 +0 -0
  307. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/GPUCache/data_1 +0 -0
  308. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/GPUCache/data_2 +0 -0
  309. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/GPUCache/data_3 +0 -0
  310. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/GPUCache/index +0 -0
  311. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/History +0 -0
  312. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/History-journal +0 -0
  313. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/LOCK +0 -0
  314. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/LOG +0 -0
  315. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/LOG.old +0 -0
  316. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Local Storage/leveldb/CURRENT +1 -0
  317. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Local Storage/leveldb/LOCK +0 -0
  318. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Local Storage/leveldb/LOG +3 -0
  319. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Local Storage/leveldb/LOG.old +3 -0
  320. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Local Storage/leveldb/MANIFEST-000001 +0 -0
  321. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Login Data +0 -0
  322. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Login Data For Account +0 -0
  323. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Login Data For Account-journal +0 -0
  324. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Login Data-journal +0 -0
  325. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Network Action Predictor +0 -0
  326. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Network Action Predictor-journal +0 -0
  327. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Network Persistent State +1 -0
  328. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/PersistentOriginTrials/LOCK +0 -0
  329. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/PersistentOriginTrials/LOG +0 -0
  330. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/PersistentOriginTrials/LOG.old +0 -0
  331. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Preferences +1 -0
  332. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/PreferredApps +1 -0
  333. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/README +1 -0
  334. NEL +0 -0
  335. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Reporting and NEL-journal +0 -0
  336. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Safe Browsing Cookies +0 -0
  337. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Safe Browsing Cookies-journal +0 -0
  338. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Secure Preferences +1 -0
  339. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Segmentation Platform/SegmentInfoDB/LOCK +0 -0
  340. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Segmentation Platform/SegmentInfoDB/LOG +0 -0
  341. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Segmentation Platform/SegmentInfoDB/LOG.old +0 -0
  342. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Segmentation Platform/SignalDB/LOCK +0 -0
  343. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Segmentation Platform/SignalDB/LOG +0 -0
  344. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Segmentation Platform/SignalDB/LOG.old +0 -0
  345. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Segmentation Platform/SignalStorageConfigDB/LOCK +0 -0
  346. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Segmentation Platform/SignalStorageConfigDB/LOG +0 -0
  347. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Segmentation Platform/SignalStorageConfigDB/LOG.old +0 -0
  348. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/ServerCertificate +0 -0
  349. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/ServerCertificate-journal +0 -0
  350. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/046fd1ef5e540ebf33332849ed99f4174f5bbafc/56407312-0248-4546-be02-0d16e58a3522/09ed93488198f423_0 +0 -0
  351. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/046fd1ef5e540ebf33332849ed99f4174f5bbafc/56407312-0248-4546-be02-0d16e58a3522/09ed93488198f423_1 +0 -0
  352. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/046fd1ef5e540ebf33332849ed99f4174f5bbafc/56407312-0248-4546-be02-0d16e58a3522/0a30220965d74d1e_0 +0 -0
  353. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/046fd1ef5e540ebf33332849ed99f4174f5bbafc/56407312-0248-4546-be02-0d16e58a3522/1300177f362c3a4a_0 +0 -0
  354. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/046fd1ef5e540ebf33332849ed99f4174f5bbafc/56407312-0248-4546-be02-0d16e58a3522/1300177f362c3a4a_1 +0 -0
  355. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/046fd1ef5e540ebf33332849ed99f4174f5bbafc/56407312-0248-4546-be02-0d16e58a3522/27b9ccf88365ee26_0 +0 -0
  356. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/046fd1ef5e540ebf33332849ed99f4174f5bbafc/56407312-0248-4546-be02-0d16e58a3522/2921673031323747_0 +0 -0
  357. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/046fd1ef5e540ebf33332849ed99f4174f5bbafc/56407312-0248-4546-be02-0d16e58a3522/2921673031323747_1 +0 -0
  358. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/046fd1ef5e540ebf33332849ed99f4174f5bbafc/56407312-0248-4546-be02-0d16e58a3522/35f037f406300022_0 +0 -0
  359. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/046fd1ef5e540ebf33332849ed99f4174f5bbafc/56407312-0248-4546-be02-0d16e58a3522/35f037f406300022_1 +0 -0
  360. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/046fd1ef5e540ebf33332849ed99f4174f5bbafc/56407312-0248-4546-be02-0d16e58a3522/3adbee165bfbf214_0 +0 -0
  361. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/046fd1ef5e540ebf33332849ed99f4174f5bbafc/56407312-0248-4546-be02-0d16e58a3522/3c8f4750e95148d9_0 +0 -0
  362. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/046fd1ef5e540ebf33332849ed99f4174f5bbafc/56407312-0248-4546-be02-0d16e58a3522/3ce96b151d8c7cc1_0 +0 -0
  363. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/046fd1ef5e540ebf33332849ed99f4174f5bbafc/56407312-0248-4546-be02-0d16e58a3522/3ce96b151d8c7cc1_1 +0 -0
  364. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/046fd1ef5e540ebf33332849ed99f4174f5bbafc/56407312-0248-4546-be02-0d16e58a3522/483d56a1df05215a_0 +0 -0
  365. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/046fd1ef5e540ebf33332849ed99f4174f5bbafc/56407312-0248-4546-be02-0d16e58a3522/483d56a1df05215a_1 +0 -0
  366. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/046fd1ef5e540ebf33332849ed99f4174f5bbafc/56407312-0248-4546-be02-0d16e58a3522/4d82f9d0e0941cce_0 +0 -0
  367. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/046fd1ef5e540ebf33332849ed99f4174f5bbafc/56407312-0248-4546-be02-0d16e58a3522/4f42af3671d8c6c6_0 +0 -0
  368. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/046fd1ef5e540ebf33332849ed99f4174f5bbafc/56407312-0248-4546-be02-0d16e58a3522/4f42af3671d8c6c6_1 +0 -0
  369. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/046fd1ef5e540ebf33332849ed99f4174f5bbafc/56407312-0248-4546-be02-0d16e58a3522/5973e266a3773c26_0 +0 -0
  370. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/046fd1ef5e540ebf33332849ed99f4174f5bbafc/56407312-0248-4546-be02-0d16e58a3522/5ad1663b68163b6f_0 +0 -0
  371. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/046fd1ef5e540ebf33332849ed99f4174f5bbafc/56407312-0248-4546-be02-0d16e58a3522/5b4c15b3725d9989_0 +0 -0
  372. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/046fd1ef5e540ebf33332849ed99f4174f5bbafc/56407312-0248-4546-be02-0d16e58a3522/5b4c15b3725d9989_1 +0 -0
  373. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/046fd1ef5e540ebf33332849ed99f4174f5bbafc/56407312-0248-4546-be02-0d16e58a3522/5c619235d9c64bc3_0 +0 -0
  374. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/046fd1ef5e540ebf33332849ed99f4174f5bbafc/56407312-0248-4546-be02-0d16e58a3522/5c619235d9c64bc3_1 +0 -0
  375. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/046fd1ef5e540ebf33332849ed99f4174f5bbafc/56407312-0248-4546-be02-0d16e58a3522/5e3af97b8dccb412_0 +0 -0
  376. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/046fd1ef5e540ebf33332849ed99f4174f5bbafc/56407312-0248-4546-be02-0d16e58a3522/5e3af97b8dccb412_1 +0 -0
  377. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/046fd1ef5e540ebf33332849ed99f4174f5bbafc/56407312-0248-4546-be02-0d16e58a3522/6e068fc05df362b0_0 +0 -0
  378. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/046fd1ef5e540ebf33332849ed99f4174f5bbafc/56407312-0248-4546-be02-0d16e58a3522/6e068fc05df362b0_1 +0 -0
  379. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/046fd1ef5e540ebf33332849ed99f4174f5bbafc/56407312-0248-4546-be02-0d16e58a3522/755a4c7663f8dc02_0 +0 -0
  380. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/046fd1ef5e540ebf33332849ed99f4174f5bbafc/56407312-0248-4546-be02-0d16e58a3522/755a4c7663f8dc02_1 +0 -0
  381. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/046fd1ef5e540ebf33332849ed99f4174f5bbafc/56407312-0248-4546-be02-0d16e58a3522/7969561312c7823f_0 +0 -0
  382. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/046fd1ef5e540ebf33332849ed99f4174f5bbafc/56407312-0248-4546-be02-0d16e58a3522/7969561312c7823f_1 +0 -0
  383. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/046fd1ef5e540ebf33332849ed99f4174f5bbafc/56407312-0248-4546-be02-0d16e58a3522/79ffa2733a735063_0 +0 -0
  384. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/046fd1ef5e540ebf33332849ed99f4174f5bbafc/56407312-0248-4546-be02-0d16e58a3522/7f91cd3066f0019f_0 +0 -0
  385. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/046fd1ef5e540ebf33332849ed99f4174f5bbafc/56407312-0248-4546-be02-0d16e58a3522/7f91cd3066f0019f_1 +0 -0
  386. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/046fd1ef5e540ebf33332849ed99f4174f5bbafc/56407312-0248-4546-be02-0d16e58a3522/7f97d42038a92017_0 +0 -0
  387. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/046fd1ef5e540ebf33332849ed99f4174f5bbafc/56407312-0248-4546-be02-0d16e58a3522/7f97d42038a92017_1 +0 -0
  388. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/046fd1ef5e540ebf33332849ed99f4174f5bbafc/56407312-0248-4546-be02-0d16e58a3522/820d43cc26b882ff_0 +0 -0
  389. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/046fd1ef5e540ebf33332849ed99f4174f5bbafc/56407312-0248-4546-be02-0d16e58a3522/820d43cc26b882ff_1 +0 -0
  390. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/046fd1ef5e540ebf33332849ed99f4174f5bbafc/56407312-0248-4546-be02-0d16e58a3522/88e95753fb6f9ea9_0 +0 -0
  391. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/046fd1ef5e540ebf33332849ed99f4174f5bbafc/56407312-0248-4546-be02-0d16e58a3522/8b469fd8bafad3b3_0 +0 -0
  392. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/046fd1ef5e540ebf33332849ed99f4174f5bbafc/56407312-0248-4546-be02-0d16e58a3522/8b469fd8bafad3b3_1 +0 -0
  393. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/046fd1ef5e540ebf33332849ed99f4174f5bbafc/56407312-0248-4546-be02-0d16e58a3522/900dd661df81967a_0 +0 -0
  394. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/046fd1ef5e540ebf33332849ed99f4174f5bbafc/56407312-0248-4546-be02-0d16e58a3522/9546d2c6dd38203c_0 +0 -0
  395. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/046fd1ef5e540ebf33332849ed99f4174f5bbafc/56407312-0248-4546-be02-0d16e58a3522/9546d2c6dd38203c_1 +0 -0
  396. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/046fd1ef5e540ebf33332849ed99f4174f5bbafc/56407312-0248-4546-be02-0d16e58a3522/96d03a8b051613e1_0 +0 -0
  397. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/046fd1ef5e540ebf33332849ed99f4174f5bbafc/56407312-0248-4546-be02-0d16e58a3522/96d03a8b051613e1_1 +0 -0
  398. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/046fd1ef5e540ebf33332849ed99f4174f5bbafc/56407312-0248-4546-be02-0d16e58a3522/a0222364eb3781e3_0 +0 -0
  399. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/046fd1ef5e540ebf33332849ed99f4174f5bbafc/56407312-0248-4546-be02-0d16e58a3522/a0222364eb3781e3_1 +0 -0
  400. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/046fd1ef5e540ebf33332849ed99f4174f5bbafc/56407312-0248-4546-be02-0d16e58a3522/a524d2c2d64c3660_0 +0 -0
  401. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/046fd1ef5e540ebf33332849ed99f4174f5bbafc/56407312-0248-4546-be02-0d16e58a3522/a524d2c2d64c3660_1 +0 -0
  402. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/046fd1ef5e540ebf33332849ed99f4174f5bbafc/56407312-0248-4546-be02-0d16e58a3522/a78bfbcc1859fb76_0 +0 -0
  403. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/046fd1ef5e540ebf33332849ed99f4174f5bbafc/56407312-0248-4546-be02-0d16e58a3522/a78bfbcc1859fb76_1 +0 -0
  404. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/046fd1ef5e540ebf33332849ed99f4174f5bbafc/56407312-0248-4546-be02-0d16e58a3522/ac56d7aa94c8dd89_0 +0 -0
  405. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/046fd1ef5e540ebf33332849ed99f4174f5bbafc/56407312-0248-4546-be02-0d16e58a3522/ac56d7aa94c8dd89_1 +0 -0
  406. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/046fd1ef5e540ebf33332849ed99f4174f5bbafc/56407312-0248-4546-be02-0d16e58a3522/b5055aa76b1823e0_0 +0 -0
  407. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/046fd1ef5e540ebf33332849ed99f4174f5bbafc/56407312-0248-4546-be02-0d16e58a3522/b5055aa76b1823e0_1 +0 -0
  408. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/046fd1ef5e540ebf33332849ed99f4174f5bbafc/56407312-0248-4546-be02-0d16e58a3522/c0b18bd33c20f43c_0 +0 -0
  409. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/046fd1ef5e540ebf33332849ed99f4174f5bbafc/56407312-0248-4546-be02-0d16e58a3522/c0b18bd33c20f43c_1 +0 -0
  410. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/046fd1ef5e540ebf33332849ed99f4174f5bbafc/56407312-0248-4546-be02-0d16e58a3522/c31100b4d5efc61d_0 +0 -0
  411. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/046fd1ef5e540ebf33332849ed99f4174f5bbafc/56407312-0248-4546-be02-0d16e58a3522/c31100b4d5efc61d_1 +0 -0
  412. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/046fd1ef5e540ebf33332849ed99f4174f5bbafc/56407312-0248-4546-be02-0d16e58a3522/c62331d49f110533_0 +0 -0
  413. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/046fd1ef5e540ebf33332849ed99f4174f5bbafc/56407312-0248-4546-be02-0d16e58a3522/c62331d49f110533_1 +0 -0
  414. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/046fd1ef5e540ebf33332849ed99f4174f5bbafc/56407312-0248-4546-be02-0d16e58a3522/c7bb739419f12b43_0 +0 -0
  415. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/046fd1ef5e540ebf33332849ed99f4174f5bbafc/56407312-0248-4546-be02-0d16e58a3522/cdf6536f6656df3e_0 +0 -0
  416. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/046fd1ef5e540ebf33332849ed99f4174f5bbafc/56407312-0248-4546-be02-0d16e58a3522/cdf6536f6656df3e_1 +0 -0
  417. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/046fd1ef5e540ebf33332849ed99f4174f5bbafc/56407312-0248-4546-be02-0d16e58a3522/d0e2620915e19afb_0 +0 -0
  418. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/046fd1ef5e540ebf33332849ed99f4174f5bbafc/56407312-0248-4546-be02-0d16e58a3522/d0e2620915e19afb_1 +0 -0
  419. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/046fd1ef5e540ebf33332849ed99f4174f5bbafc/56407312-0248-4546-be02-0d16e58a3522/d4313ca21cedf2ad_0 +0 -0
  420. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/046fd1ef5e540ebf33332849ed99f4174f5bbafc/56407312-0248-4546-be02-0d16e58a3522/d4313ca21cedf2ad_1 +0 -0
  421. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/046fd1ef5e540ebf33332849ed99f4174f5bbafc/56407312-0248-4546-be02-0d16e58a3522/d4cbe68232f52d97_0 +0 -0
  422. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/046fd1ef5e540ebf33332849ed99f4174f5bbafc/56407312-0248-4546-be02-0d16e58a3522/d4cbe68232f52d97_1 +0 -0
  423. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/046fd1ef5e540ebf33332849ed99f4174f5bbafc/56407312-0248-4546-be02-0d16e58a3522/d90bf1dbbf713592_0 +0 -0
  424. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/046fd1ef5e540ebf33332849ed99f4174f5bbafc/56407312-0248-4546-be02-0d16e58a3522/d90bf1dbbf713592_1 +0 -0
  425. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/046fd1ef5e540ebf33332849ed99f4174f5bbafc/56407312-0248-4546-be02-0d16e58a3522/df18dfd2a1ad9fb4_0 +0 -0
  426. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/046fd1ef5e540ebf33332849ed99f4174f5bbafc/56407312-0248-4546-be02-0d16e58a3522/df18dfd2a1ad9fb4_1 +0 -0
  427. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/046fd1ef5e540ebf33332849ed99f4174f5bbafc/56407312-0248-4546-be02-0d16e58a3522/e321e1f483bdf8f3_0 +0 -0
  428. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/046fd1ef5e540ebf33332849ed99f4174f5bbafc/56407312-0248-4546-be02-0d16e58a3522/e321e1f483bdf8f3_1 +0 -0
  429. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/046fd1ef5e540ebf33332849ed99f4174f5bbafc/56407312-0248-4546-be02-0d16e58a3522/e3cf32438c59b057_0 +0 -0
  430. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/046fd1ef5e540ebf33332849ed99f4174f5bbafc/56407312-0248-4546-be02-0d16e58a3522/e3cf32438c59b057_1 +0 -0
  431. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/046fd1ef5e540ebf33332849ed99f4174f5bbafc/56407312-0248-4546-be02-0d16e58a3522/e5d70b58b9ad133a_0 +0 -0
  432. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/046fd1ef5e540ebf33332849ed99f4174f5bbafc/56407312-0248-4546-be02-0d16e58a3522/e5d70b58b9ad133a_1 +0 -0
  433. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/046fd1ef5e540ebf33332849ed99f4174f5bbafc/56407312-0248-4546-be02-0d16e58a3522/e6bebc23f041524b_0 +0 -0
  434. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/046fd1ef5e540ebf33332849ed99f4174f5bbafc/56407312-0248-4546-be02-0d16e58a3522/e6bebc23f041524b_1 +0 -0
  435. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/046fd1ef5e540ebf33332849ed99f4174f5bbafc/56407312-0248-4546-be02-0d16e58a3522/ec2dbc36a8a707bf_0 +0 -0
  436. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/046fd1ef5e540ebf33332849ed99f4174f5bbafc/56407312-0248-4546-be02-0d16e58a3522/f0d3846d04ec57fa_0 +0 -0
  437. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/046fd1ef5e540ebf33332849ed99f4174f5bbafc/56407312-0248-4546-be02-0d16e58a3522/f0d3846d04ec57fa_1 +0 -0
  438. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/046fd1ef5e540ebf33332849ed99f4174f5bbafc/56407312-0248-4546-be02-0d16e58a3522/f41ecefc4e8c4d02_0 +0 -0
  439. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/046fd1ef5e540ebf33332849ed99f4174f5bbafc/56407312-0248-4546-be02-0d16e58a3522/f41ecefc4e8c4d02_1 +0 -0
  440. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/046fd1ef5e540ebf33332849ed99f4174f5bbafc/56407312-0248-4546-be02-0d16e58a3522/f641877808e85797_0 +0 -0
  441. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/046fd1ef5e540ebf33332849ed99f4174f5bbafc/56407312-0248-4546-be02-0d16e58a3522/f641877808e85797_1 +0 -0
  442. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/046fd1ef5e540ebf33332849ed99f4174f5bbafc/56407312-0248-4546-be02-0d16e58a3522/f792102a3adfa574_0 +0 -0
  443. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/046fd1ef5e540ebf33332849ed99f4174f5bbafc/56407312-0248-4546-be02-0d16e58a3522/f792102a3adfa574_1 +0 -0
  444. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/046fd1ef5e540ebf33332849ed99f4174f5bbafc/56407312-0248-4546-be02-0d16e58a3522/f87456efb50ead2b_0 +0 -0
  445. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/046fd1ef5e540ebf33332849ed99f4174f5bbafc/56407312-0248-4546-be02-0d16e58a3522/f87456efb50ead2b_1 +0 -0
  446. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/046fd1ef5e540ebf33332849ed99f4174f5bbafc/56407312-0248-4546-be02-0d16e58a3522/f9c75818bcb88359_0 +0 -0
  447. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/046fd1ef5e540ebf33332849ed99f4174f5bbafc/56407312-0248-4546-be02-0d16e58a3522/f9c75818bcb88359_1 +0 -0
  448. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/046fd1ef5e540ebf33332849ed99f4174f5bbafc/56407312-0248-4546-be02-0d16e58a3522/fb21145c8e2675cb_0 +0 -0
  449. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/046fd1ef5e540ebf33332849ed99f4174f5bbafc/56407312-0248-4546-be02-0d16e58a3522/fb21145c8e2675cb_1 +0 -0
  450. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/046fd1ef5e540ebf33332849ed99f4174f5bbafc/56407312-0248-4546-be02-0d16e58a3522/index +0 -0
  451. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/046fd1ef5e540ebf33332849ed99f4174f5bbafc/56407312-0248-4546-be02-0d16e58a3522/index-dir/the-real-index +0 -0
  452. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/046fd1ef5e540ebf33332849ed99f4174f5bbafc/d12381ba-daf3-4f23-9177-0ab3706f83a2/0281c98fa97441e5_0 +0 -0
  453. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/046fd1ef5e540ebf33332849ed99f4174f5bbafc/d12381ba-daf3-4f23-9177-0ab3706f83a2/319cb45fc46cfd93_0 +0 -0
  454. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/046fd1ef5e540ebf33332849ed99f4174f5bbafc/d12381ba-daf3-4f23-9177-0ab3706f83a2/685282d5721939ea_0 +0 -0
  455. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/046fd1ef5e540ebf33332849ed99f4174f5bbafc/d12381ba-daf3-4f23-9177-0ab3706f83a2/8634e8d5eb849493_0 +0 -0
  456. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/046fd1ef5e540ebf33332849ed99f4174f5bbafc/d12381ba-daf3-4f23-9177-0ab3706f83a2/c6ba0abf049dda93_0 +0 -0
  457. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/046fd1ef5e540ebf33332849ed99f4174f5bbafc/d12381ba-daf3-4f23-9177-0ab3706f83a2/ff32d8eaf874a37b_0 +0 -0
  458. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/046fd1ef5e540ebf33332849ed99f4174f5bbafc/d12381ba-daf3-4f23-9177-0ab3706f83a2/index +0 -0
  459. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/046fd1ef5e540ebf33332849ed99f4174f5bbafc/d12381ba-daf3-4f23-9177-0ab3706f83a2/index-dir/the-real-index +0 -0
  460. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/046fd1ef5e540ebf33332849ed99f4174f5bbafc/index.txt +0 -0
  461. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/2f12120e9e05877e5620444e87e1a223bba7f923/3691c090-dad1-4066-a2d5-4462a09e7435/024678dda211fa26_0 +0 -0
  462. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/2f12120e9e05877e5620444e87e1a223bba7f923/3691c090-dad1-4066-a2d5-4462a09e7435/024678dda211fa26_1 +0 -0
  463. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/2f12120e9e05877e5620444e87e1a223bba7f923/3691c090-dad1-4066-a2d5-4462a09e7435/037830b98bc2d51d_0 +0 -0
  464. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/2f12120e9e05877e5620444e87e1a223bba7f923/3691c090-dad1-4066-a2d5-4462a09e7435/037830b98bc2d51d_1 +0 -0
  465. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/2f12120e9e05877e5620444e87e1a223bba7f923/3691c090-dad1-4066-a2d5-4462a09e7435/058b480bfb167f1d_0 +0 -0
  466. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/2f12120e9e05877e5620444e87e1a223bba7f923/3691c090-dad1-4066-a2d5-4462a09e7435/058b480bfb167f1d_1 +0 -0
  467. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/2f12120e9e05877e5620444e87e1a223bba7f923/3691c090-dad1-4066-a2d5-4462a09e7435/0655e9ff0425de79_0 +0 -0
  468. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/2f12120e9e05877e5620444e87e1a223bba7f923/3691c090-dad1-4066-a2d5-4462a09e7435/0a59caba16743dc4_0 +0 -0
  469. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/2f12120e9e05877e5620444e87e1a223bba7f923/3691c090-dad1-4066-a2d5-4462a09e7435/0a59caba16743dc4_1 +0 -0
  470. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/2f12120e9e05877e5620444e87e1a223bba7f923/3691c090-dad1-4066-a2d5-4462a09e7435/136ff5c99b26781c_0 +0 -0
  471. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/2f12120e9e05877e5620444e87e1a223bba7f923/3691c090-dad1-4066-a2d5-4462a09e7435/136ff5c99b26781c_1 +0 -0
  472. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/2f12120e9e05877e5620444e87e1a223bba7f923/3691c090-dad1-4066-a2d5-4462a09e7435/17a566dc27c99ba4_0 +0 -0
  473. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/2f12120e9e05877e5620444e87e1a223bba7f923/3691c090-dad1-4066-a2d5-4462a09e7435/17a566dc27c99ba4_1 +0 -0
  474. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/2f12120e9e05877e5620444e87e1a223bba7f923/3691c090-dad1-4066-a2d5-4462a09e7435/21f0f05b2eceebc6_0 +0 -0
  475. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/2f12120e9e05877e5620444e87e1a223bba7f923/3691c090-dad1-4066-a2d5-4462a09e7435/21f0f05b2eceebc6_1 +0 -0
  476. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/2f12120e9e05877e5620444e87e1a223bba7f923/3691c090-dad1-4066-a2d5-4462a09e7435/258481d12e2d6b56_0 +0 -0
  477. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/2f12120e9e05877e5620444e87e1a223bba7f923/3691c090-dad1-4066-a2d5-4462a09e7435/258481d12e2d6b56_1 +0 -0
  478. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/2f12120e9e05877e5620444e87e1a223bba7f923/3691c090-dad1-4066-a2d5-4462a09e7435/384fffcb0c07b624_0 +0 -0
  479. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/2f12120e9e05877e5620444e87e1a223bba7f923/3691c090-dad1-4066-a2d5-4462a09e7435/4d19946442d4bfbb_0 +0 -0
  480. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/2f12120e9e05877e5620444e87e1a223bba7f923/3691c090-dad1-4066-a2d5-4462a09e7435/4db2b1b4ab66bab9_0 +0 -0
  481. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/2f12120e9e05877e5620444e87e1a223bba7f923/3691c090-dad1-4066-a2d5-4462a09e7435/4db2b1b4ab66bab9_1 +0 -0
  482. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/2f12120e9e05877e5620444e87e1a223bba7f923/3691c090-dad1-4066-a2d5-4462a09e7435/51f125f305445381_0 +0 -0
  483. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/2f12120e9e05877e5620444e87e1a223bba7f923/3691c090-dad1-4066-a2d5-4462a09e7435/51f125f305445381_1 +0 -0
  484. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/2f12120e9e05877e5620444e87e1a223bba7f923/3691c090-dad1-4066-a2d5-4462a09e7435/5a8718d400d2f051_0 +0 -0
  485. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/2f12120e9e05877e5620444e87e1a223bba7f923/3691c090-dad1-4066-a2d5-4462a09e7435/5a8718d400d2f051_1 +0 -0
  486. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/2f12120e9e05877e5620444e87e1a223bba7f923/3691c090-dad1-4066-a2d5-4462a09e7435/61766447abeea15f_0 +0 -0
  487. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/2f12120e9e05877e5620444e87e1a223bba7f923/3691c090-dad1-4066-a2d5-4462a09e7435/61766447abeea15f_1 +0 -0
  488. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/2f12120e9e05877e5620444e87e1a223bba7f923/3691c090-dad1-4066-a2d5-4462a09e7435/62151dfee245ae9b_0 +0 -0
  489. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/2f12120e9e05877e5620444e87e1a223bba7f923/3691c090-dad1-4066-a2d5-4462a09e7435/62151dfee245ae9b_1 +0 -0
  490. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/2f12120e9e05877e5620444e87e1a223bba7f923/3691c090-dad1-4066-a2d5-4462a09e7435/696c1b7392b5c15a_0 +0 -0
  491. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/2f12120e9e05877e5620444e87e1a223bba7f923/3691c090-dad1-4066-a2d5-4462a09e7435/696c1b7392b5c15a_1 +0 -0
  492. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/2f12120e9e05877e5620444e87e1a223bba7f923/3691c090-dad1-4066-a2d5-4462a09e7435/6c82448ab5b28377_0 +0 -0
  493. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/2f12120e9e05877e5620444e87e1a223bba7f923/3691c090-dad1-4066-a2d5-4462a09e7435/6c82448ab5b28377_1 +0 -0
  494. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/2f12120e9e05877e5620444e87e1a223bba7f923/3691c090-dad1-4066-a2d5-4462a09e7435/6d24995ced602e98_0 +0 -0
  495. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/2f12120e9e05877e5620444e87e1a223bba7f923/3691c090-dad1-4066-a2d5-4462a09e7435/722befb3ecafcb3f_0 +0 -0
  496. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/2f12120e9e05877e5620444e87e1a223bba7f923/3691c090-dad1-4066-a2d5-4462a09e7435/78c3660b76e7d93a_0 +0 -0
  497. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/2f12120e9e05877e5620444e87e1a223bba7f923/3691c090-dad1-4066-a2d5-4462a09e7435/78c3660b76e7d93a_1 +0 -0
  498. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/2f12120e9e05877e5620444e87e1a223bba7f923/3691c090-dad1-4066-a2d5-4462a09e7435/798dd4b9b7d9d5c2_0 +0 -0
  499. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/2f12120e9e05877e5620444e87e1a223bba7f923/3691c090-dad1-4066-a2d5-4462a09e7435/8595071248e29ee1_0 +0 -0
  500. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/2f12120e9e05877e5620444e87e1a223bba7f923/3691c090-dad1-4066-a2d5-4462a09e7435/8595071248e29ee1_1 +0 -0
  501. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/2f12120e9e05877e5620444e87e1a223bba7f923/3691c090-dad1-4066-a2d5-4462a09e7435/8b04b7c22f0fd1f9_0 +0 -0
  502. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/2f12120e9e05877e5620444e87e1a223bba7f923/3691c090-dad1-4066-a2d5-4462a09e7435/8b04b7c22f0fd1f9_1 +0 -0
  503. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/2f12120e9e05877e5620444e87e1a223bba7f923/3691c090-dad1-4066-a2d5-4462a09e7435/8f520d5d41ee00bd_0 +0 -0
  504. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/2f12120e9e05877e5620444e87e1a223bba7f923/3691c090-dad1-4066-a2d5-4462a09e7435/8f520d5d41ee00bd_1 +0 -0
  505. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/2f12120e9e05877e5620444e87e1a223bba7f923/3691c090-dad1-4066-a2d5-4462a09e7435/901ff14ab13b28c6_0 +0 -0
  506. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/2f12120e9e05877e5620444e87e1a223bba7f923/3691c090-dad1-4066-a2d5-4462a09e7435/901ff14ab13b28c6_1 +0 -0
  507. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/2f12120e9e05877e5620444e87e1a223bba7f923/3691c090-dad1-4066-a2d5-4462a09e7435/a1d474dd0b6dd558_0 +0 -0
  508. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/2f12120e9e05877e5620444e87e1a223bba7f923/3691c090-dad1-4066-a2d5-4462a09e7435/a1d474dd0b6dd558_1 +0 -0
  509. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/2f12120e9e05877e5620444e87e1a223bba7f923/3691c090-dad1-4066-a2d5-4462a09e7435/a3011f5e2ef033c1_0 +0 -0
  510. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/2f12120e9e05877e5620444e87e1a223bba7f923/3691c090-dad1-4066-a2d5-4462a09e7435/a3011f5e2ef033c1_1 +0 -0
  511. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/2f12120e9e05877e5620444e87e1a223bba7f923/3691c090-dad1-4066-a2d5-4462a09e7435/a8b1cac4bc45ce95_0 +0 -0
  512. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/2f12120e9e05877e5620444e87e1a223bba7f923/3691c090-dad1-4066-a2d5-4462a09e7435/a8b1cac4bc45ce95_1 +0 -0
  513. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/2f12120e9e05877e5620444e87e1a223bba7f923/3691c090-dad1-4066-a2d5-4462a09e7435/ba58c86b9d2825b2_0 +0 -0
  514. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/2f12120e9e05877e5620444e87e1a223bba7f923/3691c090-dad1-4066-a2d5-4462a09e7435/ba58c86b9d2825b2_1 +0 -0
  515. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/2f12120e9e05877e5620444e87e1a223bba7f923/3691c090-dad1-4066-a2d5-4462a09e7435/c5d7b8f405d5e062_0 +0 -0
  516. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/2f12120e9e05877e5620444e87e1a223bba7f923/3691c090-dad1-4066-a2d5-4462a09e7435/ca40ebe1bbd077ac_0 +0 -0
  517. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/2f12120e9e05877e5620444e87e1a223bba7f923/3691c090-dad1-4066-a2d5-4462a09e7435/ca40ebe1bbd077ac_1 +0 -0
  518. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/2f12120e9e05877e5620444e87e1a223bba7f923/3691c090-dad1-4066-a2d5-4462a09e7435/d0ab2b640b0a13e7_0 +0 -0
  519. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/2f12120e9e05877e5620444e87e1a223bba7f923/3691c090-dad1-4066-a2d5-4462a09e7435/d0ab2b640b0a13e7_1 +0 -0
  520. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/2f12120e9e05877e5620444e87e1a223bba7f923/3691c090-dad1-4066-a2d5-4462a09e7435/d0c3865f553ac976_0 +0 -0
  521. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/2f12120e9e05877e5620444e87e1a223bba7f923/3691c090-dad1-4066-a2d5-4462a09e7435/d0c3865f553ac976_1 +0 -0
  522. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/2f12120e9e05877e5620444e87e1a223bba7f923/3691c090-dad1-4066-a2d5-4462a09e7435/da45add0238a285a_0 +0 -0
  523. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/2f12120e9e05877e5620444e87e1a223bba7f923/3691c090-dad1-4066-a2d5-4462a09e7435/da45add0238a285a_1 +0 -0
  524. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/2f12120e9e05877e5620444e87e1a223bba7f923/3691c090-dad1-4066-a2d5-4462a09e7435/e4307c16470799da_0 +0 -0
  525. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/2f12120e9e05877e5620444e87e1a223bba7f923/3691c090-dad1-4066-a2d5-4462a09e7435/e4307c16470799da_1 +0 -0
  526. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/2f12120e9e05877e5620444e87e1a223bba7f923/3691c090-dad1-4066-a2d5-4462a09e7435/e7690ca8c63cad14_0 +0 -0
  527. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/2f12120e9e05877e5620444e87e1a223bba7f923/3691c090-dad1-4066-a2d5-4462a09e7435/e7690ca8c63cad14_1 +0 -0
  528. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/2f12120e9e05877e5620444e87e1a223bba7f923/3691c090-dad1-4066-a2d5-4462a09e7435/e7ba6f4de6562c89_0 +0 -0
  529. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/2f12120e9e05877e5620444e87e1a223bba7f923/3691c090-dad1-4066-a2d5-4462a09e7435/e7ba6f4de6562c89_1 +0 -0
  530. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/2f12120e9e05877e5620444e87e1a223bba7f923/3691c090-dad1-4066-a2d5-4462a09e7435/eb1bcf853b355e13_0 +0 -0
  531. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/2f12120e9e05877e5620444e87e1a223bba7f923/3691c090-dad1-4066-a2d5-4462a09e7435/eb1bcf853b355e13_1 +0 -0
  532. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/2f12120e9e05877e5620444e87e1a223bba7f923/3691c090-dad1-4066-a2d5-4462a09e7435/f32ce7214b1774ba_0 +0 -0
  533. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/2f12120e9e05877e5620444e87e1a223bba7f923/3691c090-dad1-4066-a2d5-4462a09e7435/f32ce7214b1774ba_1 +0 -0
  534. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/2f12120e9e05877e5620444e87e1a223bba7f923/3691c090-dad1-4066-a2d5-4462a09e7435/f62e4b05ee7d99f9_0 +0 -0
  535. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/2f12120e9e05877e5620444e87e1a223bba7f923/3691c090-dad1-4066-a2d5-4462a09e7435/f62e4b05ee7d99f9_1 +0 -0
  536. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/2f12120e9e05877e5620444e87e1a223bba7f923/3691c090-dad1-4066-a2d5-4462a09e7435/fc5ef4b63ae4bb4b_0 +0 -0
  537. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/2f12120e9e05877e5620444e87e1a223bba7f923/3691c090-dad1-4066-a2d5-4462a09e7435/index +0 -0
  538. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/2f12120e9e05877e5620444e87e1a223bba7f923/3691c090-dad1-4066-a2d5-4462a09e7435/index-dir/the-real-index +0 -0
  539. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/2f12120e9e05877e5620444e87e1a223bba7f923/de96e545-808a-4ef3-b7b1-a72521505ad2/52158ab3c1d3fdde_0 +0 -0
  540. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/2f12120e9e05877e5620444e87e1a223bba7f923/de96e545-808a-4ef3-b7b1-a72521505ad2/9c3cfbb43286df23_0 +0 -0
  541. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/2f12120e9e05877e5620444e87e1a223bba7f923/de96e545-808a-4ef3-b7b1-a72521505ad2/b19f1b829e018cf2_0 +0 -0
  542. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/2f12120e9e05877e5620444e87e1a223bba7f923/de96e545-808a-4ef3-b7b1-a72521505ad2/b8ae4f867095f4fd_0 +0 -0
  543. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/2f12120e9e05877e5620444e87e1a223bba7f923/de96e545-808a-4ef3-b7b1-a72521505ad2/bdc920a7c2524c3b_0 +0 -0
  544. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/2f12120e9e05877e5620444e87e1a223bba7f923/de96e545-808a-4ef3-b7b1-a72521505ad2/ea5f9af36eefd38b_0 +0 -0
  545. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/2f12120e9e05877e5620444e87e1a223bba7f923/de96e545-808a-4ef3-b7b1-a72521505ad2/index +0 -0
  546. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/2f12120e9e05877e5620444e87e1a223bba7f923/de96e545-808a-4ef3-b7b1-a72521505ad2/index-dir/the-real-index +0 -0
  547. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/CacheStorage/2f12120e9e05877e5620444e87e1a223bba7f923/index.txt +0 -0
  548. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/Database/CURRENT +1 -0
  549. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/Database/LOCK +0 -0
  550. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/Database/LOG +3 -0
  551. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/Database/LOG.old +3 -0
  552. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/Database/MANIFEST-000001 +0 -0
  553. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/ScriptCache/2cc80dabc69f58b6_0 +0 -0
  554. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/ScriptCache/2cc80dabc69f58b6_1 +0 -0
  555. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/ScriptCache/fa813c9ad67834ac_0 +0 -0
  556. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/ScriptCache/fa813c9ad67834ac_1 +0 -0
  557. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/ScriptCache/index +0 -0
  558. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Service Worker/ScriptCache/index-dir/the-real-index +0 -0
  559. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Session Storage/CURRENT +1 -0
  560. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Session Storage/LOCK +0 -0
  561. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Session Storage/LOG +3 -0
  562. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Session Storage/LOG.old +3 -0
  563. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Session Storage/MANIFEST-000001 +0 -0
  564. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Sessions/Session_13429768577966436 +0 -0
  565. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Sessions/Tabs_13429770684888237 +0 -0
  566. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Sessions/Tabs_13429770734729173 +0 -0
  567. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Shared Dictionary/cache/index +0 -0
  568. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Shared Dictionary/cache/index-dir/the-real-index +0 -0
  569. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Shared Dictionary/db +0 -0
  570. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Shared Dictionary/db-journal +0 -0
  571. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/SharedStorage +0 -0
  572. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Shortcuts +0 -0
  573. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Shortcuts-journal +0 -0
  574. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Site Characteristics Database/CURRENT +1 -0
  575. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Site Characteristics Database/LOCK +0 -0
  576. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Site Characteristics Database/LOG +3 -0
  577. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Site Characteristics Database/LOG.old +3 -0
  578. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Site Characteristics Database/MANIFEST-000001 +0 -0
  579. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Sync Data/LevelDB/CURRENT +1 -0
  580. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Sync Data/LevelDB/LOCK +0 -0
  581. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Sync Data/LevelDB/LOG +3 -0
  582. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Sync Data/LevelDB/LOG.old +3 -0
  583. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Sync Data/LevelDB/MANIFEST-000001 +0 -0
  584. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Top Sites +0 -0
  585. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Top Sites-journal +0 -0
  586. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Translate Ranker Model +0 -0
  587. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/TransportSecurity +1 -0
  588. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Trust Tokens +0 -0
  589. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Trust Tokens-journal +0 -0
  590. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Web Data +0 -0
  591. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/Web Data-journal +0 -0
  592. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/WebStorage/QuotaManager +0 -0
  593. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/WebStorage/QuotaManager-journal +0 -0
  594. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/chrome_cart_db/LOCK +0 -0
  595. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/chrome_cart_db/LOG +0 -0
  596. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/chrome_cart_db/LOG.old +0 -0
  597. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/commerce_subscription_db/LOCK +0 -0
  598. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/commerce_subscription_db/LOG +0 -0
  599. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/commerce_subscription_db/LOG.old +0 -0
  600. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/discount_infos_db/LOCK +0 -0
  601. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/discount_infos_db/LOG +0 -0
  602. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/discount_infos_db/LOG.old +0 -0
  603. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/discounts_db/LOCK +0 -0
  604. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/discounts_db/LOG +0 -0
  605. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/discounts_db/LOG.old +0 -0
  606. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/engine_allowlist.bf +0 -0
  607. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/heavy_ad_intervention_opt_out.db +0 -0
  608. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/heavy_ad_intervention_opt_out.db-journal +0 -0
  609. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/parcel_tracking_db/LOCK +0 -0
  610. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/parcel_tracking_db/LOG +0 -0
  611. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/parcel_tracking_db/LOG.old +0 -0
  612. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/shared_proto_db/CURRENT +1 -0
  613. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/shared_proto_db/LOCK +0 -0
  614. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/shared_proto_db/LOG +3 -0
  615. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/shared_proto_db/LOG.old +3 -0
  616. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/shared_proto_db/MANIFEST-000001 +0 -0
  617. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/shared_proto_db/metadata/CURRENT +1 -0
  618. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/shared_proto_db/metadata/LOCK +0 -0
  619. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/shared_proto_db/metadata/LOG +3 -0
  620. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/shared_proto_db/metadata/LOG.old +3 -0
  621. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/shared_proto_db/metadata/MANIFEST-000001 +0 -0
  622. package/.pi/.pi-puppeteer/profiles/chrome/default/Default/trusted_vault.pb +2 -0
  623. package/.pi/.pi-puppeteer/profiles/chrome/default/DevToolsActivePort +2 -0
  624. package/.pi/.pi-puppeteer/profiles/chrome/default/FileTypePolicies/145.0.7584.0/_metadata/verified_contents.json +1 -0
  625. package/.pi/.pi-puppeteer/profiles/chrome/default/FileTypePolicies/145.0.7584.0/download_file_types.pb +0 -0
  626. package/.pi/.pi-puppeteer/profiles/chrome/default/FileTypePolicies/145.0.7584.0/manifest.json +5 -0
  627. package/.pi/.pi-puppeteer/profiles/chrome/default/FirstPartySetsPreloaded/2025.7.24.0/LICENSE +27 -0
  628. package/.pi/.pi-puppeteer/profiles/chrome/default/FirstPartySetsPreloaded/2025.7.24.0/_metadata/verified_contents.json +1 -0
  629. package/.pi/.pi-puppeteer/profiles/chrome/default/FirstPartySetsPreloaded/2025.7.24.0/manifest.json +5 -0
  630. package/.pi/.pi-puppeteer/profiles/chrome/default/FirstPartySetsPreloaded/2025.7.24.0/sets.json +70 -0
  631. package/.pi/.pi-puppeteer/profiles/chrome/default/GPUPersistentCache/GPUCache/NDJN3PYMYS2VQL44TKFDS34NLSXM6YVU/cache.db +0 -0
  632. package/.pi/.pi-puppeteer/profiles/chrome/default/GPUPersistentCache/GPUCache/NDJN3PYMYS2VQL44TKFDS34NLSXM6YVU/cache.db-wal +0 -0
  633. package/.pi/.pi-puppeteer/profiles/chrome/default/GPUPersistentCache/GPUCache/NDJN3PYMYS2VQL44TKFDS34NLSXM6YVU/cache.journal +0 -0
  634. package/.pi/.pi-puppeteer/profiles/chrome/default/GraphiteDawnCache/data_0 +0 -0
  635. package/.pi/.pi-puppeteer/profiles/chrome/default/GraphiteDawnCache/data_1 +0 -0
  636. package/.pi/.pi-puppeteer/profiles/chrome/default/GraphiteDawnCache/data_2 +0 -0
  637. package/.pi/.pi-puppeteer/profiles/chrome/default/GraphiteDawnCache/data_3 +0 -0
  638. package/.pi/.pi-puppeteer/profiles/chrome/default/GraphiteDawnCache/f_000001 +0 -0
  639. package/.pi/.pi-puppeteer/profiles/chrome/default/GraphiteDawnCache/f_000002 +0 -0
  640. package/.pi/.pi-puppeteer/profiles/chrome/default/GraphiteDawnCache/f_000003 +0 -0
  641. package/.pi/.pi-puppeteer/profiles/chrome/default/GraphiteDawnCache/f_000004 +0 -0
  642. package/.pi/.pi-puppeteer/profiles/chrome/default/GraphiteDawnCache/index +0 -0
  643. package/.pi/.pi-puppeteer/profiles/chrome/default/Last Version +1 -0
  644. package/.pi/.pi-puppeteer/profiles/chrome/default/Local State +1 -0
  645. package/.pi/.pi-puppeteer/profiles/chrome/default/MEIPreload/1.1.0.3/_metadata/verified_contents.json +1 -0
  646. package/.pi/.pi-puppeteer/profiles/chrome/default/MEIPreload/1.1.0.3/manifest.json +7 -0
  647. package/.pi/.pi-puppeteer/profiles/chrome/default/MEIPreload/1.1.0.3/preloaded_data.pb +0 -0
  648. package/.pi/.pi-puppeteer/profiles/chrome/default/PKIMetadata/1728/_metadata/verified_contents.json +1 -0
  649. package/.pi/.pi-puppeteer/profiles/chrome/default/PKIMetadata/1728/crs.pb +0 -0
  650. package/.pi/.pi-puppeteer/profiles/chrome/default/PKIMetadata/1728/ct_config.pb +325 -0
  651. package/.pi/.pi-puppeteer/profiles/chrome/default/PKIMetadata/1728/kp_pinslist.pb +0 -0
  652. package/.pi/.pi-puppeteer/profiles/chrome/default/PKIMetadata/1728/manifest.json +5 -0
  653. package/.pi/.pi-puppeteer/profiles/chrome/default/PKIMetadata/1728/mtc_config.pb +0 -0
  654. package/.pi/.pi-puppeteer/profiles/chrome/default/SSLErrorAssistant/7/_metadata/verified_contents.json +1 -0
  655. package/.pi/.pi-puppeteer/profiles/chrome/default/SSLErrorAssistant/7/manifest.json +5 -0
  656. package/.pi/.pi-puppeteer/profiles/chrome/default/SSLErrorAssistant/7/ssl_error_assistant.pb +54 -0
  657. package/.pi/.pi-puppeteer/profiles/chrome/default/SafetyTips/3091/_metadata/verified_contents.json +1 -0
  658. package/.pi/.pi-puppeteer/profiles/chrome/default/SafetyTips/3091/manifest.json +5 -0
  659. package/.pi/.pi-puppeteer/profiles/chrome/default/SafetyTips/3091/safety_tips.pb +0 -0
  660. package/.pi/.pi-puppeteer/profiles/chrome/default/Subresource Filter/Indexed Rules/38/9.70.0/Ruleset Data +0 -0
  661. package/.pi/.pi-puppeteer/profiles/chrome/default/Subresource Filter/Unindexed Rules/9.70.0/Filtering Rules +6104 -2
  662. package/.pi/.pi-puppeteer/profiles/chrome/default/Subresource Filter/Unindexed Rules/9.70.0/LICENSE.txt +383 -0
  663. package/.pi/.pi-puppeteer/profiles/chrome/default/Subresource Filter/Unindexed Rules/9.70.0/_metadata/verified_contents.json +1 -0
  664. package/.pi/.pi-puppeteer/profiles/chrome/default/Subresource Filter/Unindexed Rules/9.70.0/manifest.json +6 -0
  665. package/.pi/.pi-puppeteer/profiles/chrome/default/TrustTokenKeyCommitments/2026.3.23.1/LICENSE +27 -0
  666. package/.pi/.pi-puppeteer/profiles/chrome/default/TrustTokenKeyCommitments/2026.3.23.1/_metadata/verified_contents.json +1 -0
  667. package/.pi/.pi-puppeteer/profiles/chrome/default/TrustTokenKeyCommitments/2026.3.23.1/keys.json +1 -0
  668. package/.pi/.pi-puppeteer/profiles/chrome/default/TrustTokenKeyCommitments/2026.3.23.1/manifest.json +5 -0
  669. package/.pi/.pi-puppeteer/profiles/chrome/default/Variations +1 -0
  670. package/.pi/.pi-puppeteer/profiles/chrome/default/WasmTtsEngine/20260723.1/_metadata/verified_contents.json +1 -0
  671. package/.pi/.pi-puppeteer/profiles/chrome/default/WasmTtsEngine/20260723.1/background_compiled.js +40 -0
  672. package/.pi/.pi-puppeteer/profiles/chrome/default/WasmTtsEngine/20260723.1/bindings_main.js +6281 -0
  673. package/.pi/.pi-puppeteer/profiles/chrome/default/WasmTtsEngine/20260723.1/bindings_main.wasm +0 -0
  674. package/.pi/.pi-puppeteer/profiles/chrome/default/WasmTtsEngine/20260723.1/manifest.json +5 -0
  675. package/.pi/.pi-puppeteer/profiles/chrome/default/WasmTtsEngine/20260723.1/offscreen.html +2 -0
  676. package/.pi/.pi-puppeteer/profiles/chrome/default/WasmTtsEngine/20260723.1/offscreen_compiled.js +131 -0
  677. package/.pi/.pi-puppeteer/profiles/chrome/default/WasmTtsEngine/20260723.1/streaming_worklet_processor.js +78 -0
  678. package/.pi/.pi-puppeteer/profiles/chrome/default/WasmTtsEngine/20260723.1/voices.json +1779 -0
  679. package/.pi/.pi-puppeteer/profiles/chrome/default/WasmTtsEngine/20260723.1/wasm_tts_manifest_v3.json +43 -0
  680. package/.pi/.pi-puppeteer/profiles/chrome/default/ZxcvbnData/3/_metadata/verified_contents.json +1 -0
  681. package/.pi/.pi-puppeteer/profiles/chrome/default/ZxcvbnData/3/english_wikipedia.txt +30000 -0
  682. package/.pi/.pi-puppeteer/profiles/chrome/default/ZxcvbnData/3/female_names.txt +3712 -0
  683. package/.pi/.pi-puppeteer/profiles/chrome/default/ZxcvbnData/3/male_names.txt +984 -0
  684. package/.pi/.pi-puppeteer/profiles/chrome/default/ZxcvbnData/3/manifest.json +5 -0
  685. package/.pi/.pi-puppeteer/profiles/chrome/default/ZxcvbnData/3/passwords.txt +30000 -0
  686. package/.pi/.pi-puppeteer/profiles/chrome/default/ZxcvbnData/3/ranked_dicts +0 -0
  687. package/.pi/.pi-puppeteer/profiles/chrome/default/ZxcvbnData/3/surnames.txt +10000 -0
  688. package/.pi/.pi-puppeteer/profiles/chrome/default/ZxcvbnData/3/us_tv_and_film.txt +19160 -0
  689. package/.pi/.pi-puppeteer/profiles/chrome/default/component_crx_cache/0d784450fcc5b3ad7ab4efa85b2e1fe56bd5086b69807eab756f62c257ea0d8b +0 -0
  690. package/.pi/.pi-puppeteer/profiles/chrome/default/component_crx_cache/0d994b6c9c5d4b0316bcc7a79f4939a2390c638169ea6dc783198c17286d8255 +0 -0
  691. package/.pi/.pi-puppeteer/profiles/chrome/default/component_crx_cache/3eb16d6c28b502ac4cfee8f4a148df05f4d93229fa36a71db8b08d06329ff18a +0 -0
  692. package/.pi/.pi-puppeteer/profiles/chrome/default/component_crx_cache/4448b37acb13eb51a842a8ebc85ea826729571c7293f2213d855d3a76cb9a4f8 +0 -0
  693. package/.pi/.pi-puppeteer/profiles/chrome/default/component_crx_cache/545666a4efd056351597bb386aea1368105ededc976ed5650d8682daab9f37ff +0 -0
  694. package/.pi/.pi-puppeteer/profiles/chrome/default/component_crx_cache/56c21927faa028be6ce18c931660eec37e41da4bfbfd47cafa48350f828c0dbd +0 -0
  695. package/.pi/.pi-puppeteer/profiles/chrome/default/component_crx_cache/733776833212346a1018b95197c61bed2d107fbb7790a985ef692780e02f31cb +0 -0
  696. package/.pi/.pi-puppeteer/profiles/chrome/default/component_crx_cache/7b05c14dba04ed522210b733f004cb0e74d7679a653b19bd029f9bc0e6b19903 +0 -0
  697. package/.pi/.pi-puppeteer/profiles/chrome/default/component_crx_cache/8f2c0712b6800fa9622a039cb167cc9503d508a271247e445f08a96eded5772f +0 -0
  698. package/.pi/.pi-puppeteer/profiles/chrome/default/component_crx_cache/9bec6c2c0185d3305ac8495047a1aa01e725d58f8f18d219742a2988f07cd93a +0 -0
  699. package/.pi/.pi-puppeteer/profiles/chrome/default/component_crx_cache/9f157bd09a986baa46110a0acb7e3d7407208e58d02250c637902962e5ed2c5e +0 -0
  700. package/.pi/.pi-puppeteer/profiles/chrome/default/component_crx_cache/abd93867c038d4d17c101ace2226d7e21303d984d7097271392bae6be478495b +0 -0
  701. package/.pi/.pi-puppeteer/profiles/chrome/default/component_crx_cache/ae216724654f3e52d3c502328caf83f773e66cc5818c38850165864005a35169 +0 -0
  702. package/.pi/.pi-puppeteer/profiles/chrome/default/component_crx_cache/c8c2fd0acdb7eecaf4f66d5164204c4e8e5ebbabb6398e0ee6ec6d8af71ea672 +0 -0
  703. package/.pi/.pi-puppeteer/profiles/chrome/default/component_crx_cache/fd8fd38c229ab33755ff429ccc9919eba21b566551cbfb17d8e11e35e941ee0e +0 -0
  704. package/.pi/.pi-puppeteer/profiles/chrome/default/component_crx_cache/metadata.json +1 -0
  705. package/.pi/.pi-puppeteer/profiles/chrome/default/extensions_crx_cache/metadata.json +1 -0
  706. package/.pi/.pi-puppeteer/profiles/chrome/default/first_party_sets.db +0 -0
  707. package/.pi/.pi-puppeteer/profiles/chrome/default/first_party_sets.db-journal +0 -0
  708. package/.pi/.pi-puppeteer/profiles/chrome/default/segmentation_platform/ukm_db +0 -0
  709. package/.pi-subagents/artifacts/6d0b4431_custom.vision-agent_0_input.md +54 -0
  710. package/.pi-subagents/artifacts/6d0b4431_custom.vision-agent_0_meta.json +114 -0
  711. package/.pi-subagents/artifacts/6d0b4431_custom.vision-agent_0_output.md +22 -0
  712. package/.pi-subagents/artifacts/6d0b4431_custom.vision-agent_0_transcript.jsonl +7 -0
  713. package/README.md +0 -1
  714. package/README.zh-CN.md +0 -1
  715. package/package.json +2 -1
  716. package/server/pi-reader.ts +1020 -4
  717. package/src/App.tsx +5 -0
  718. package/src/components/dashboard/DashboardPage.tsx +275 -117
  719. package/src/components/layout/Sidebar.tsx +4 -0
  720. package/src/components/providers/ProvidersModelsPage.tsx +1830 -0
  721. package/src/components/sessions/MemoryPage.tsx +480 -85
  722. package/src/components/sessions/SessionsPage.tsx +473 -89
  723. package/src/components/settings/SettingsPage.tsx +555 -243
  724. package/src/components/subagents/SubagentsPage.tsx +502 -0
  725. package/src/data/builtin-providers.ts +8 -12
  726. package/src/data/mock-config.ts +1 -15
  727. package/src/data/mock-usage.ts +0 -2
  728. package/src/lib/translations/en.ts +174 -23
  729. package/src/lib/translations/ja.ts +174 -23
  730. package/src/lib/translations/zh-CN.ts +174 -23
  731. package/src/lib/translations/zh-TW.ts +174 -23
  732. package/src/main.tsx +9 -0
  733. package/src/store/config-store.ts +77 -40
  734. package/src/types/index.ts +66 -0
  735. package/tsconfig.tsbuildinfo +1 -0
  736. package/vite.config.ts +164 -4
  737. package/src/components/models/ModelsPage.tsx +0 -570
  738. package/src/components/providers/ProvidersPage.tsx +0 -466
@@ -0,0 +1,1830 @@
1
+ import { useEffect, useState } from "react";
2
+ import { useConfigStore } from "@/store/config-store";
3
+ import { useTranslation } from "@/lib/i18n";
4
+ import { Badge } from "@/components/ui/Badge";
5
+ import { Modal } from "@/components/ui/Modal";
6
+ import { formatTokens, cn } from "@/lib/utils";
7
+ import type { ApiType, CustomProviderConfig, Model, Provider } from "@/types";
8
+ import {
9
+ Plus,
10
+ Trash2,
11
+ Edit3,
12
+ Eye,
13
+ EyeOff,
14
+ Server,
15
+ Shield,
16
+ Box,
17
+ Brain,
18
+ Image as ImageIcon,
19
+ Search,
20
+ Check,
21
+ X,
22
+ Loader2,
23
+ Zap,
24
+ ClipboardPaste,
25
+ Download,
26
+ SquareCheck,
27
+ Copy,
28
+ } from "lucide-react";
29
+
30
+ const API_TYPES: { value: ApiType; label: string }[] = [
31
+ { value: "openai-completions", label: "Chat Completions (/chat/completions)" },
32
+ { value: "openai-responses", label: "OpenAI Responses" },
33
+ { value: "anthropic-messages", label: "Anthropic Messages" },
34
+ { value: "google-generative-ai", label: "Google Generative AI" },
35
+ { value: "google-vertex", label: "Google Vertex AI" },
36
+ { value: "bedrock-converse-stream", label: "AWS Bedrock" },
37
+ { value: "mistral-conversations", label: "Mistral" },
38
+ ];
39
+
40
+ function isValidHttpUrl(value: string): boolean {
41
+ try {
42
+ const u = new URL(value);
43
+ return u.protocol === "http:" || u.protocol === "https:";
44
+ } catch {
45
+ return false;
46
+ }
47
+ }
48
+
49
+ // Defaults for models without explicit limits: 256K context, 32K output
50
+ // (32K matches the common max-output ceiling of current mainstream models)
51
+ const DEFAULT_CONTEXT_WINDOW = 262144;
52
+ const DEFAULT_MAX_TOKENS = 32768;
53
+
54
+ // Sanitize to a config-safe id: lowercase letters, digits and hyphens only
55
+ function sanitizeProviderId(name: string): string {
56
+ return name
57
+ .trim()
58
+ .toLowerCase()
59
+ .replace(/\s+/g, "-")
60
+ .replace(/[^a-z0-9-]/g, "")
61
+ .replace(/-+/g, "-")
62
+ .replace(/^-|-$/g, "");
63
+ }
64
+
65
+ // Non-ASCII names (e.g. 中文) sanitize to "" — fall back to the endpoint hostname
66
+ // so the provider still gets a valid id while keeping the original display name.
67
+ function deriveProviderId(name: string, baseUrl: string): string {
68
+ const fromName = sanitizeProviderId(name);
69
+ if (fromName || !name.trim()) return fromName;
70
+ try {
71
+ const host = new URL(baseUrl.trim()).hostname;
72
+ const skip = new Set(["api", "www", "app", "gateway", "open", "openapi", "platform"]);
73
+ const part = host.split(".").find((p) => p && !skip.has(p.toLowerCase()));
74
+ return sanitizeProviderId(part ?? "");
75
+ } catch {
76
+ return "";
77
+ }
78
+ }
79
+
80
+ // ─── Freeform Import Parser ───────────────────────────────
81
+ // Recognizes pasted text like:
82
+ // tokenrouter baseurl:https://api.example.com/v1 key:sk-xxxx
83
+ // modelid:vendor/model-a, vendor/model-b
84
+ // Labels accept half/full-width colons; unlabeled tokens fall back to
85
+ // heuristics (URL → baseUrl, sk-… → apiKey, foo/bar → model id).
86
+
87
+ interface ParsedImport {
88
+ name: string;
89
+ baseUrl: string;
90
+ apiKey: string;
91
+ modelIds: string[];
92
+ }
93
+
94
+ const IMPORT_LABEL_RE =
95
+ /(?<![\w/.\-])(apikey|api_key|api-key|key|token|secret|密钥|金鑰|baseurl|base_url|base-url|url|endpoint|地址|接口|provider|name|名称|名稱|供应商|供應商|model_ids?|modelids?|models?|模型)\s*[::](?!\/\/)/gi;
96
+
97
+ function importField(label: string): "name" | "baseUrl" | "apiKey" | "models" {
98
+ const l = label.toLowerCase();
99
+ if (/^(apikey|api_key|api-key|key|token|secret|密钥|金鑰)$/.test(l)) return "apiKey";
100
+ if (/^(baseurl|base_url|base-url|url|endpoint|地址|接口)$/.test(l)) return "baseUrl";
101
+ if (/^(provider|name|名称|名稱|供应商|供應商)$/.test(l)) return "name";
102
+ return "models";
103
+ }
104
+
105
+ function parseProviderImport(raw: string): ParsedImport {
106
+ const out: ParsedImport = { name: "", baseUrl: "", apiKey: "", modelIds: [] };
107
+ const pushModels = (value: string) => {
108
+ for (const part of value.split(/[\s,,;;]+/)) {
109
+ const v = part.trim();
110
+ if (v && !out.modelIds.includes(v)) out.modelIds.push(v);
111
+ }
112
+ };
113
+ const assignFree = (text: string) => {
114
+ for (const token of text.split(/\s+/)) {
115
+ const v = token.replace(/[,,;;]+$/, "");
116
+ if (!v) continue;
117
+ if (/^https?:\/\//i.test(v)) {
118
+ if (!out.baseUrl) out.baseUrl = v;
119
+ } else if (/^sk-\S{8,}$/i.test(v) || /^[A-Za-z0-9_-]{32,}$/.test(v)) {
120
+ if (!out.apiKey) out.apiKey = v;
121
+ } else if (v.includes("/")) {
122
+ pushModels(v);
123
+ } else if (!out.name) {
124
+ // A label line like "百灵:" keeps a trailing colon — strip it
125
+ out.name = v.replace(/[::]\s*$/, "").trim();
126
+ }
127
+ }
128
+ };
129
+ for (const line of raw.split(/\r?\n/)) {
130
+ if (!line.trim()) continue;
131
+ const matches = [...line.matchAll(IMPORT_LABEL_RE)];
132
+ const head = (matches.length ? line.slice(0, matches[0]!.index) : line).trim();
133
+ if (head) assignFree(head);
134
+ matches.forEach((m, i) => {
135
+ const start = m.index! + m[0].length;
136
+ const end = i + 1 < matches.length ? matches[i + 1]!.index! : line.length;
137
+ const value = line.slice(start, end).trim().replace(/[,,;;]+$/, "");
138
+ if (!value) return;
139
+ const field = importField(m[1] ?? "");
140
+ if (field === "models") pushModels(value);
141
+ else if (!out[field]) out[field] = value;
142
+ });
143
+ }
144
+ return out;
145
+ }
146
+
147
+ export function ProvidersModelsPage() {
148
+ const { t } = useTranslation();
149
+ const { allProviders, auth, modelsJson, removeCustomProvider } = useConfigStore();
150
+
151
+ const builtinProviders = allProviders.filter((p) => p.type === "builtin");
152
+ const customProviders = allProviders.filter((p) => p.type === "custom");
153
+
154
+ const [selectedId, setSelectedId] = useState<string | null>(null);
155
+ const [adding, setAdding] = useState(false);
156
+ const [importing, setImporting] = useState(false);
157
+ const [importBump, setImportBump] = useState(0);
158
+ const [deleteConfirm, setDeleteConfirm] = useState<string | null>(null);
159
+ const [deleteError, setDeleteError] = useState(false);
160
+
161
+ // Keep a valid selection (default: first custom, else first builtin)
162
+ const selected = allProviders.find((p) => p.id === selectedId) ?? null;
163
+ useEffect(() => {
164
+ if (!selected && !adding && allProviders.length > 0) {
165
+ setSelectedId(customProviders[0]?.id ?? allProviders[0]?.id ?? null);
166
+ }
167
+ }, [selected, adding, allProviders, customProviders]);
168
+
169
+ const hasKey = (p: Provider) => p.hasAuth || !!p.apiKey || !!auth?.[p.id]?.key;
170
+
171
+ const handleAddProvider = async (id: string, cfg: CustomProviderConfig): Promise<boolean> => {
172
+ const ok = await useConfigStore.getState().addCustomProvider(id, cfg);
173
+ if (ok) {
174
+ setAdding(false);
175
+ setSelectedId(id);
176
+ }
177
+ return ok;
178
+ };
179
+
180
+ const handleDeleteProvider = async () => {
181
+ if (!deleteConfirm) return;
182
+ setDeleteError(false);
183
+ const ok = await removeCustomProvider(deleteConfirm);
184
+ if (ok) {
185
+ if (selectedId === deleteConfirm) setSelectedId(null);
186
+ setDeleteConfirm(null);
187
+ } else {
188
+ setDeleteError(true);
189
+ }
190
+ };
191
+
192
+ const handleDuplicateProvider = async (id: string) => {
193
+ const existing = modelsJson?.providers[id];
194
+ if (!existing) return;
195
+ const suffix = "-copy";
196
+ const newId = sanitizeProviderId(id + suffix);
197
+ // Copy config but clear apiKey, authHeader, and models
198
+ const cfg: CustomProviderConfig = {
199
+ baseUrl: existing.baseUrl,
200
+ api: existing.api,
201
+ headers: existing.headers,
202
+ modelOverrides: existing.modelOverrides,
203
+ };
204
+ const ok = await useConfigStore.getState().addCustomProvider(newId, cfg);
205
+ if (ok) setSelectedId(newId);
206
+ };
207
+
208
+ return (
209
+ <div className="space-y-6">
210
+ <div>
211
+ <h1 className="text-2xl font-bold" style={{ color: "var(--page-text)" }}>
212
+ {t("nav.providers_models")}
213
+ </h1>
214
+ <p className="mt-1 text-sm" style={{ color: "var(--muted-text)" }}>
215
+ {t("providers_models.subtitle")}
216
+ </p>
217
+ </div>
218
+
219
+ <div className="flex overflow-hidden rounded-xl border border-gray-800 bg-gray-900/50">
220
+ {/* ─── Left: Provider List ─────────────────────── */}
221
+ <div className="w-60 shrink-0 border-r border-gray-800 p-3">
222
+ {builtinProviders.length > 0 && (
223
+ <>
224
+ <p className="px-2 pb-2 pt-1 text-xs font-medium uppercase tracking-wider text-gray-500">
225
+ {t("providers.builtin")}
226
+ </p>
227
+ <div className="space-y-0.5">
228
+ {builtinProviders.map((p) => (
229
+ <ProviderListItem
230
+ key={p.id}
231
+ provider={p}
232
+ active={!adding && selectedId === p.id}
233
+ hasKey={hasKey(p)}
234
+ onClick={() => {
235
+ setAdding(false);
236
+ setSelectedId(p.id);
237
+ }}
238
+ />
239
+ ))}
240
+ </div>
241
+ </>
242
+ )}
243
+
244
+ <p className="px-2 pb-2 pt-4 text-xs font-medium uppercase tracking-wider text-gray-500">
245
+ {t("providers_models.custom_providers")}
246
+ </p>
247
+ <div className="space-y-0.5">
248
+ {customProviders.map((p) => (
249
+ <ProviderListItem
250
+ key={p.id}
251
+ provider={p}
252
+ active={!adding && selectedId === p.id}
253
+ hasKey={hasKey(p)}
254
+ onClick={() => {
255
+ setAdding(false);
256
+ setSelectedId(p.id);
257
+ }}
258
+ />
259
+ ))}
260
+ </div>
261
+
262
+ <button
263
+ onClick={() => setAdding(true)}
264
+ className={cn(
265
+ "mt-2 flex w-full items-center gap-2 rounded-lg border px-3 py-2 text-sm font-medium transition-colors",
266
+ adding
267
+ ? "border-gray-600 bg-gray-800 text-white"
268
+ : "border-gray-700 text-gray-300 hover:bg-gray-800 hover:text-white"
269
+ )}
270
+ >
271
+ <Plus className="h-4 w-4" />
272
+ {t("providers.add_provider")}
273
+ </button>
274
+
275
+ <button
276
+ onClick={() => setImporting(true)}
277
+ className="mt-2 flex w-full items-center gap-2 rounded-lg border border-gray-700 px-3 py-2 text-sm font-medium text-gray-300 transition-colors hover:bg-gray-800 hover:text-white"
278
+ >
279
+ <ClipboardPaste className="h-4 w-4" />
280
+ {t("providers_models.import")}
281
+ </button>
282
+ </div>
283
+
284
+ {/* ─── Right: Provider Detail / Add Form ───────── */}
285
+ <div className="min-w-0 flex-1 p-6">
286
+ {adding ? (
287
+ <AddProviderForm onSubmit={handleAddProvider} onCancel={() => setAdding(false)} />
288
+ ) : selected ? (
289
+ <ProviderDetail
290
+ key={`${selected.id}:${importBump}`}
291
+ provider={selected}
292
+ onDelete={() => setDeleteConfirm(selected.id)}
293
+ onDuplicate={() => handleDuplicateProvider(selected.id)}
294
+ />
295
+ ) : (
296
+ <div className="flex h-40 items-center justify-center text-sm text-gray-500">
297
+ {t("providers_models.select_hint")}
298
+ </div>
299
+ )}
300
+ </div>
301
+ </div>
302
+
303
+ {/* Import Provider Modal */}
304
+ <ImportProviderModal
305
+ open={importing}
306
+ onClose={() => setImporting(false)}
307
+ onImported={(id) => {
308
+ setImporting(false);
309
+ setAdding(false);
310
+ setSelectedId(id);
311
+ setImportBump((n) => n + 1);
312
+ }}
313
+ />
314
+
315
+ {/* Delete Provider Confirmation Modal */}
316
+ <Modal
317
+ open={!!deleteConfirm}
318
+ onClose={() => { setDeleteConfirm(null); setDeleteError(false); }}
319
+ title={t("providers.delete_provider")}
320
+ >
321
+ <div className="space-y-4">
322
+ <div className="flex items-start gap-3">
323
+ <Trash2 className="h-5 w-5 shrink-0 mt-0.5 text-red-400" />
324
+ <div>
325
+ <p className="text-sm text-gray-200">
326
+ <strong>{allProviders.find((p) => p.id === deleteConfirm)?.name}</strong>
327
+ {" — "}
328
+ {t("providers.delete_confirm")}
329
+ </p>
330
+ <p className="text-xs mt-2 text-gray-500">
331
+ {t("providers_models.delete_provider_note")}
332
+ </p>
333
+ {deleteError && (
334
+ <p className="text-xs mt-2 text-red-400">{t("providers_models.save_failed")}</p>
335
+ )}
336
+ </div>
337
+ </div>
338
+ <div className="flex justify-end gap-3">
339
+ <button
340
+ onClick={() => { setDeleteConfirm(null); setDeleteError(false); }}
341
+ className="rounded-lg px-4 py-2 text-sm text-gray-400 hover:bg-gray-800"
342
+ >
343
+ {t("models.cancel")}
344
+ </button>
345
+ <button
346
+ onClick={handleDeleteProvider}
347
+ className="flex items-center gap-2 rounded-lg px-4 py-2 text-sm font-medium text-white"
348
+ style={{ backgroundColor: "#dc2626" }}
349
+ >
350
+ <Trash2 className="h-4 w-4" />
351
+ {t("providers.delete_provider")}
352
+ </button>
353
+ </div>
354
+ </div>
355
+ </Modal>
356
+ </div>
357
+ );
358
+ }
359
+
360
+ // ─── Provider List Item ───────────────────────────────────
361
+
362
+ function ProviderListItem({
363
+ provider,
364
+ active,
365
+ hasKey,
366
+ onClick,
367
+ }: {
368
+ provider: Provider;
369
+ active: boolean;
370
+ hasKey: boolean;
371
+ onClick: () => void;
372
+ }) {
373
+ return (
374
+ <button
375
+ onClick={onClick}
376
+ className={cn(
377
+ "flex w-full items-center gap-2 rounded-lg border px-3 py-2 text-left text-sm transition-colors",
378
+ active
379
+ ? "border-gray-600 bg-gray-800 text-white"
380
+ : "border-transparent text-gray-300 hover:bg-gray-800/60"
381
+ )}
382
+ >
383
+ {provider.type === "custom" ? (
384
+ <Server className="h-4 w-4 shrink-0 text-blue-400" />
385
+ ) : (
386
+ <Shield className="h-4 w-4 shrink-0 text-emerald-400" />
387
+ )}
388
+ <span className="min-w-0 flex-1 truncate">{provider.name}</span>
389
+ <span
390
+ className={cn("h-2 w-2 shrink-0 rounded-full", hasKey ? "bg-emerald-400" : "bg-gray-600")}
391
+ />
392
+ </button>
393
+ );
394
+ }
395
+
396
+ // ─── Connection Test Button ───────────────────────────────
397
+
398
+ type TestState =
399
+ | { status: "idle" }
400
+ | { status: "testing" }
401
+ | { status: "ok"; latencyMs: number }
402
+ | { status: "fail"; message: string };
403
+
404
+ function TestConnectionButton({ baseUrl, apiKey }: { baseUrl: string; apiKey?: string }) {
405
+ const { t } = useTranslation();
406
+ const [test, setTest] = useState<TestState>({ status: "idle" });
407
+
408
+ const runTest = async () => {
409
+ setTest({ status: "testing" });
410
+ try {
411
+ const res = await fetch("/api/pi/provider-test", {
412
+ method: "POST",
413
+ headers: { "Content-Type": "application/json" },
414
+ body: JSON.stringify({ baseUrl: baseUrl.trim(), apiKey: apiKey || undefined }),
415
+ });
416
+ const data = await res.json();
417
+ if (data.success) {
418
+ setTest({ status: "ok", latencyMs: data.latencyMs ?? 0 });
419
+ } else {
420
+ setTest({ status: "fail", message: data.message ?? "unknown" });
421
+ }
422
+ } catch {
423
+ setTest({ status: "fail", message: "network error" });
424
+ }
425
+ };
426
+
427
+ const disabled = !baseUrl.trim() || !isValidHttpUrl(baseUrl.trim()) || test.status === "testing";
428
+
429
+ return (
430
+ <div className="flex items-center gap-3">
431
+ <button
432
+ onClick={runTest}
433
+ disabled={disabled}
434
+ className="flex items-center gap-2 rounded-lg border border-gray-700 px-3 py-1.5 text-sm text-gray-300 transition-colors hover:bg-gray-800 disabled:cursor-not-allowed disabled:opacity-50"
435
+ >
436
+ {test.status === "testing" ? (
437
+ <Loader2 className="h-4 w-4 animate-spin" />
438
+ ) : (
439
+ <Zap className="h-4 w-4" />
440
+ )}
441
+ {test.status === "testing" ? t("providers_models.testing") : t("providers_models.test_connection")}
442
+ </button>
443
+ {test.status === "ok" && (
444
+ <span className="flex items-center gap-1 text-sm text-emerald-400">
445
+ <Check className="h-4 w-4" />
446
+ {t("providers_models.test_ok", String(test.latencyMs))}
447
+ </span>
448
+ )}
449
+ {test.status === "fail" && (
450
+ <span className="flex items-center gap-1 text-sm text-red-400">
451
+ <X className="h-4 w-4" />
452
+ {t("providers_models.test_fail", test.message)}
453
+ </span>
454
+ )}
455
+ </div>
456
+ );
457
+ }
458
+
459
+ // ─── Provider Detail Panel ────────────────────────────────
460
+
461
+ function ProviderDetail({ provider, onDelete, onDuplicate }: { provider: Provider; onDelete: () => void; onDuplicate: () => void }) {
462
+ const { t } = useTranslation();
463
+ const {
464
+ auth,
465
+ settings,
466
+ updateSettings,
467
+ updateCustomProvider,
468
+ setProviderAuth,
469
+ removeProviderAuth,
470
+ addModel,
471
+ updateModel,
472
+ removeModel,
473
+ addEnabledModel,
474
+ removeEnabledModel,
475
+ } = useConfigStore();
476
+
477
+ const isCustom = provider.type === "custom";
478
+ const savedKey = provider.apiKey ?? auth?.[provider.id]?.key ?? "";
479
+
480
+ const [providerName, setProviderName] = useState(provider.name ?? "");
481
+ const [baseUrl, setBaseUrl] = useState(provider.baseUrl ?? "");
482
+ const [api, setApi] = useState<ApiType>(provider.api ?? "openai-completions");
483
+ const [apiKey, setApiKey] = useState(savedKey);
484
+ const [showKey, setShowKey] = useState(false);
485
+ const [editModel, setEditModel] = useState<Model | null>(null);
486
+ const [showAddModel, setShowAddModel] = useState(false);
487
+ const [deleteModel, setDeleteModel] = useState<Model | null>(null);
488
+ const [modelQuery, setModelQuery] = useState("");
489
+ const [saveState, setSaveState] = useState<"idle" | "saving" | "saved" | "error">("idle");
490
+
491
+ // ─── Fetch Models State ───
492
+ const [fetchOpen, setFetchOpen] = useState(false);
493
+ const [fetching, setFetching] = useState(false);
494
+ const [fetchError, setFetchError] = useState<string | null>(null);
495
+ const [fetchedModels, setFetchedModels] = useState<{ id: string; contextWindow?: number; maxTokens?: number; vision?: boolean }[]>([]);
496
+ const [fetchSelected, setFetchSelected] = useState<Set<string>>(new Set());
497
+ const [fetchImported, setFetchImported] = useState<number | null>(null);
498
+
499
+ // ─── Per-Model Test State ───
500
+ const [modelTests, setModelTests] = useState<Map<string, TestState>>(new Map());
501
+ const getModelTest = (modelId: string) => modelTests.get(modelId) ?? { status: "idle" };
502
+
503
+ const existingModelIds = new Set(provider.models.map((m) => m.id));
504
+ const availableModels = fetchedModels.filter((m) => !existingModelIds.has(m.id));
505
+ const isSelected = (id: string) => fetchSelected.has(id);
506
+ const allSelected = availableModels.length > 0 && availableModels.every((m) => isSelected(m.id));
507
+
508
+ const toggleSelect = (id: string) => {
509
+ setFetchSelected((prev) => {
510
+ const next = new Set(prev);
511
+ next.has(id) ? next.delete(id) : next.add(id);
512
+ return next;
513
+ });
514
+ };
515
+ const toggleAll = () => {
516
+ setFetchSelected((prev) => {
517
+ if (availableModels.every((m) => isSelected(m.id))) return new Set();
518
+ return new Set(availableModels.map((m) => m.id));
519
+ });
520
+ };
521
+
522
+ const fetchModels = async () => {
523
+ if (!baseUrl.trim() || !isValidHttpUrl(baseUrl.trim())) return;
524
+ setFetchOpen(true);
525
+ setFetching(true);
526
+ setFetchError(null);
527
+ setFetchedModels([]);
528
+ setFetchSelected(new Set());
529
+ setFetchImported(null);
530
+ try {
531
+ const res = await fetch("/api/pi/provider-models", {
532
+ method: "POST",
533
+ headers: { "Content-Type": "application/json" },
534
+ body: JSON.stringify({ baseUrl: baseUrl.trim(), apiKey, providerId: provider.id }),
535
+ });
536
+ const data = await res.json();
537
+ if (data.error) setFetchError(data.error);
538
+ else setFetchedModels(data.models ?? []);
539
+ } catch {
540
+ setFetchError("network error");
541
+ } finally {
542
+ setFetching(false);
543
+ }
544
+ };
545
+
546
+ const handleImportFetched = async () => {
547
+ const selected = availableModels.filter((m) => isSelected(m.id));
548
+ if (selected.length === 0) return;
549
+ selected.forEach((m) => {
550
+ addModel(provider.id, { id: m.id, contextWindow: m.contextWindow ?? DEFAULT_CONTEXT_WINDOW, maxTokens: m.maxTokens ?? DEFAULT_MAX_TOKENS, input: m.vision ? ["text", "image"] : ["text"] } as Model);
551
+ });
552
+ // Enable in a single batched write — per-model addEnabledModel calls race
553
+ // on the same settings snapshot and overwrite each other.
554
+ const list = settings?.enabledModels ?? [];
555
+ const refs = selected.map((m) => `${provider.id}/${m.id}`);
556
+ await updateSettings({ enabledModels: Array.from(new Set([...list, ...refs])) });
557
+ setFetchImported(selected.length);
558
+ setTimeout(() => {
559
+ setFetchOpen(false); setFetchedModels([]); setFetchSelected(new Set());
560
+ setFetchImported(null); setFetchError(null);
561
+ }, 1500);
562
+ };
563
+
564
+ const handleTestModel = async (m: Model) => {
565
+ const modelId = m.id;
566
+ setModelTests((prev) => {
567
+ const next = new Map(prev);
568
+ next.set(modelId, { status: "testing" });
569
+ return next;
570
+ });
571
+ try {
572
+ const res = await fetch("/api/pi/model-test", {
573
+ method: "POST",
574
+ headers: { "Content-Type": "application/json" },
575
+ body: JSON.stringify({ baseUrl: baseUrl.trim(), modelId, apiKey, apiType: api ?? undefined }),
576
+ });
577
+ const data = await res.json();
578
+ setModelTests((prev) => {
579
+ const next = new Map(prev);
580
+ next.set(modelId, data.success
581
+ ? { status: "ok" as const, latencyMs: data.latencyMs ?? 0 }
582
+ : { status: "fail" as const, message: data.message ?? "unknown" });
583
+ return next;
584
+ });
585
+ } catch {
586
+ setModelTests((prev) => {
587
+ const next = new Map(prev);
588
+ next.set(modelId, { status: "fail" as const, message: "network error" });
589
+ return next;
590
+ });
591
+ }
592
+ };
593
+
594
+ const urlInvalid = isCustom && baseUrl.trim() !== "" && !isValidHttpUrl(baseUrl.trim());
595
+
596
+ const dirty =
597
+ (isCustom && (providerName !== (provider.name ?? "") || baseUrl !== (provider.baseUrl ?? "") || api !== (provider.api ?? "openai-completions"))) ||
598
+ apiKey !== savedKey;
599
+
600
+ const handleSave = async () => {
601
+ setSaveState("saving");
602
+ let ok = true;
603
+ if (isCustom) {
604
+ ok = await updateCustomProvider(provider.id, {
605
+ name: providerName || undefined,
606
+ baseUrl: baseUrl || undefined,
607
+ api,
608
+ apiKey: apiKey || undefined,
609
+ });
610
+ } else if (apiKey !== savedKey) {
611
+ ok = apiKey
612
+ ? await setProviderAuth(provider.id, apiKey)
613
+ : await removeProviderAuth(provider.id);
614
+ }
615
+ setSaveState(ok ? "saved" : "error");
616
+ if (ok) setTimeout(() => setSaveState("idle"), 2500);
617
+ };
618
+
619
+ // Enabled state lives in settings.enabledModels ("provider/model" refs) —
620
+ // the same source pi reads, so toggling here matches the CLI behavior.
621
+ const isEnabled = (modelId: string) =>
622
+ settings?.enabledModels?.includes(`${provider.id}/${modelId}`) ?? false;
623
+
624
+ const handleToggle = (modelId: string) => {
625
+ const ref = `${provider.id}/${modelId}`;
626
+ if (isEnabled(modelId)) removeEnabledModel(ref);
627
+ else addEnabledModel(ref);
628
+ };
629
+
630
+ const setAllEnabled = (enable: boolean) => {
631
+ const list = settings?.enabledModels ?? [];
632
+ const refs = provider.models.map((m) => `${provider.id}/${m.id}`);
633
+ const next = enable
634
+ ? Array.from(new Set([...list, ...refs]))
635
+ : list.filter((r) => !refs.includes(r));
636
+ updateSettings({ enabledModels: next });
637
+ };
638
+
639
+ const q = modelQuery.trim().toLowerCase();
640
+ const visibleModels = q
641
+ ? provider.models.filter(
642
+ (m) => m.id.toLowerCase().includes(q) || (m.name ?? "").toLowerCase().includes(q)
643
+ )
644
+ : provider.models;
645
+
646
+ return (
647
+ <div className="space-y-5">
648
+ {/* Header */}
649
+ <div className="flex items-center gap-3">
650
+ <h2 className="text-lg font-semibold text-white">{provider.name}</h2>
651
+ <Badge variant={isCustom ? "default" : "info"}>
652
+ {isCustom ? t("providers.custom") : t("providers.builtin")}
653
+ </Badge>
654
+ {savedKey && <Badge variant="success">{t("providers.configured")}</Badge>}
655
+ {isCustom && (
656
+ <button
657
+ onClick={onDuplicate}
658
+ className="rounded-lg p-2 text-gray-500 transition-colors hover:bg-blue-500/10 hover:text-blue-400"
659
+ title={t("providers.duplicate_provider")}
660
+ >
661
+ <Copy className="h-4 w-4" />
662
+ </button>
663
+ )}
664
+ {isCustom && (
665
+ <button
666
+ onClick={onDelete}
667
+ className="ml-auto rounded-lg p-2 text-gray-500 transition-colors hover:bg-red-500/10 hover:text-red-400"
668
+ title={t("providers.delete_provider")}
669
+ >
670
+ <Trash2 className="h-4 w-4" />
671
+ </button>
672
+ )}
673
+ </div>
674
+
675
+
676
+ {/* Name (custom only) */}
677
+ {isCustom && (
678
+ <div>
679
+ <label className="block text-sm text-gray-400">{t("providers_models.name")}</label>
680
+ <input
681
+ type="text"
682
+ value={providerName}
683
+ onChange={(e) => setProviderName(e.target.value)}
684
+ placeholder="My Provider"
685
+ className="mt-1.5 w-full rounded-lg border border-gray-700 bg-gray-800 px-3 py-2.5 text-sm text-white"
686
+ />
687
+ </div>
688
+ )}
689
+ {/* Base URL */}
690
+ <div>
691
+ <label className="block text-sm text-gray-400">{t("providers.base_url")}</label>
692
+ <input
693
+ type="text"
694
+ value={baseUrl}
695
+ disabled={!isCustom}
696
+ onChange={(e) => setBaseUrl(e.target.value)}
697
+ placeholder="https://api.example.com/v1"
698
+ className={cn(
699
+ "mt-1.5 w-full rounded-lg border bg-gray-800 px-3 py-2.5 text-sm text-white disabled:opacity-50",
700
+ urlInvalid ? "border-red-500" : "border-gray-700"
701
+ )}
702
+ />
703
+ {urlInvalid && (
704
+ <p className="mt-1 text-xs text-red-400">{t("providers_models.invalid_url")}</p>
705
+ )}
706
+ </div>
707
+
708
+ {/* API Type */}
709
+ <div>
710
+ <label className="block text-sm text-gray-400">{t("providers.api_type")}</label>
711
+ <select
712
+ value={api}
713
+ disabled={!isCustom}
714
+ onChange={(e) => setApi(e.target.value as ApiType)}
715
+ className="mt-1.5 w-full rounded-lg border border-gray-700 bg-gray-800 px-3 py-2.5 text-sm text-white disabled:opacity-50"
716
+ >
717
+ {API_TYPES.map((a) => (
718
+ <option key={a.value} value={a.value}>{a.label}</option>
719
+ ))}
720
+ </select>
721
+ </div>
722
+
723
+ {/* API Key */}
724
+ <div>
725
+ <label className="block text-sm text-gray-400">{t("providers.api_key")}</label>
726
+ <div className="relative mt-1.5">
727
+ <input
728
+ type={showKey ? "text" : "password"}
729
+ value={apiKey}
730
+ onChange={(e) => setApiKey(e.target.value)}
731
+ placeholder="sk-... or $MY_API_KEY"
732
+ className="w-full rounded-lg border border-gray-700 bg-gray-800 px-3 py-2.5 pr-10 text-sm text-white"
733
+ />
734
+ <button
735
+ onClick={() => setShowKey(!showKey)}
736
+ className="absolute right-2 top-1/2 -translate-y-1/2 rounded-md p-1.5 text-gray-500 hover:text-gray-300"
737
+ >
738
+ {showKey ? <EyeOff className="h-4 w-4" /> : <Eye className="h-4 w-4" />}
739
+ </button>
740
+ </div>
741
+ </div>
742
+
743
+ {/* Save / Test / Feedback row */}
744
+ <div className="flex flex-wrap items-center gap-3">
745
+ {dirty && (
746
+ <button
747
+ onClick={handleSave}
748
+ disabled={saveState === "saving" || urlInvalid}
749
+ className="flex items-center gap-2 rounded-lg px-4 py-2 text-sm font-medium transition-colors disabled:opacity-50"
750
+ style={{ backgroundColor: "#3b82f6", color: "#ffffff" }}
751
+ >
752
+ {saveState === "saving" && <Loader2 className="h-4 w-4 animate-spin" />}
753
+ {t("models.save")}
754
+ </button>
755
+ )}
756
+ {saveState === "saved" && (
757
+ <span className="flex items-center gap-1 text-sm text-emerald-400">
758
+ <Check className="h-4 w-4" />
759
+ {t("providers_models.saved")}
760
+ </span>
761
+ )}
762
+ {saveState === "error" && (
763
+ <span className="flex items-center gap-1 text-sm text-red-400">
764
+ <X className="h-4 w-4" />
765
+ {t("providers_models.save_failed")}
766
+ </span>
767
+ )}
768
+ {isCustom && baseUrl.trim() !== "" && (
769
+ <TestConnectionButton baseUrl={baseUrl} apiKey={apiKey} />
770
+ )}
771
+ </div>
772
+
773
+ {/* Model List */}
774
+ <div>
775
+ <div className="flex items-center justify-between gap-3">
776
+ <label className="block text-sm text-gray-400">{t("providers_models.model_list")}</label>
777
+ {provider.models.length > 0 && (
778
+ <div className="flex items-center gap-2">
779
+ <button
780
+ onClick={() => setAllEnabled(true)}
781
+ className="rounded-md px-2 py-1 text-xs text-emerald-400 transition-colors hover:bg-emerald-500/10"
782
+ >
783
+ {t("providers_models.enable_all")}
784
+ </button>
785
+ <button
786
+ onClick={() => setAllEnabled(false)}
787
+ className="rounded-md px-2 py-1 text-xs text-gray-400 transition-colors hover:bg-gray-800"
788
+ >
789
+ {t("providers_models.disable_all")}
790
+ </button>
791
+ </div>
792
+ )}
793
+ </div>
794
+
795
+ {provider.models.length > 5 && (
796
+ <div className="relative mt-1.5">
797
+ <Search className="absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-gray-500" />
798
+ <input
799
+ type="text"
800
+ value={modelQuery}
801
+ onChange={(e) => setModelQuery(e.target.value)}
802
+ placeholder={t("models.search_placeholder")}
803
+ className="w-full rounded-lg border border-gray-700 bg-gray-800 py-2 pl-9 pr-3 text-sm text-white"
804
+ />
805
+ </div>
806
+ )}
807
+
808
+ <div className="mt-1.5 space-y-2 rounded-lg border border-gray-800 p-3">
809
+ {provider.models.length === 0 && (
810
+ <p className="px-1 py-2 text-sm text-gray-500">{t("models.no_models")}</p>
811
+ )}
812
+ {provider.models.length > 0 && visibleModels.length === 0 && (
813
+ <p className="px-1 py-2 text-sm text-gray-500">{t("models.no_models")}</p>
814
+ )}
815
+ {visibleModels.map((m) => (
816
+ <div
817
+ key={m.id}
818
+ className={cn(
819
+ "flex items-center gap-2 rounded-lg border border-gray-700 bg-gray-900/70 px-3 py-2.5",
820
+ !isEnabled(m.id) && "opacity-50"
821
+ )}
822
+ >
823
+ <Box className="h-4 w-4 shrink-0 text-gray-500" />
824
+ <span className="min-w-0 flex-1 truncate font-mono text-sm text-gray-200">
825
+ {m.id}
826
+ </span>
827
+ {m.reasoning && (
828
+ <span title={t("models.reasoning")} className="flex shrink-0">
829
+ <Brain className="h-3.5 w-3.5 text-purple-400" />
830
+ </span>
831
+ )}
832
+ {m.input?.includes("image") && (
833
+ <span title={t("models.image_input")} className="flex shrink-0">
834
+ <ImageIcon className="h-3.5 w-3.5 text-blue-400" />
835
+ </span>
836
+ )}
837
+ <span className="rounded-md border border-gray-600 bg-gray-800/50 px-2 py-0.5 text-xs text-gray-400">
838
+ {m.cost && (m.cost.input || m.cost.output)
839
+ ? `$${m.cost.input}/${m.cost.output}`
840
+ : t("models.free")}
841
+ </span>
842
+ <span className="rounded-md border border-gray-600 bg-gray-800/50 px-2 py-0.5 text-xs text-gray-400">
843
+ {m.contextWindow ? formatTokens(m.contextWindow) : "—"}
844
+ </span>
845
+ <button
846
+ onClick={() => handleToggle(m.id)}
847
+ className={cn(
848
+ "rounded-md px-2 py-1 text-xs transition-colors",
849
+ isEnabled(m.id)
850
+ ? "text-emerald-400 hover:bg-emerald-500/10"
851
+ : "text-gray-500 hover:bg-gray-700"
852
+ )}
853
+ >
854
+ {isEnabled(m.id) ? t("models.enabled") : t("models.disabled")}
855
+ </button>
856
+ {/* Test model */}
857
+ {(() => {
858
+ const test = getModelTest(m.id);
859
+ if (test.status === "testing") return null;
860
+ return (
861
+ <button
862
+ onClick={() => handleTestModel(m)}
863
+ className="rounded-md p-1.5 text-gray-500 transition-colors hover:bg-gray-700 hover:text-gray-200"
864
+ title={t("models.test_model")}
865
+ >
866
+ <Zap className="h-3.5 w-3.5" />
867
+ </button>
868
+ );
869
+ })()}
870
+ {/* Model test result */}
871
+ {(() => {
872
+ const test = getModelTest(m.id);
873
+ if (test.status === "ok") return (
874
+ <span className="flex items-center gap-1 text-xs text-emerald-400">
875
+ <Check className="h-3.5 w-3.5" />
876
+ {t("providers_models.test_ok", String(test.latencyMs))}
877
+ </span>
878
+ );
879
+ if (test.status === "fail") return (
880
+ <span className="flex items-center gap-1 text-xs text-red-400">
881
+ <X className="h-3.5 w-3.5" />
882
+ {t("providers_models.test_fail", test.message)}
883
+ </span>
884
+ );
885
+ if (test.status === "testing") return (
886
+ <span className="flex items-center gap-1 text-xs text-gray-400">
887
+ <Loader2 className="h-3.5 w-3.5 animate-spin" />
888
+ {t("providers_models.testing")}
889
+ </span>
890
+ );
891
+ return null;
892
+ })()}
893
+ <button
894
+ onClick={() => setEditModel(m)}
895
+ className="rounded-md p-1.5 text-gray-500 transition-colors hover:bg-gray-700 hover:text-gray-200"
896
+ title={t("models.edit_model")}
897
+ >
898
+ <Edit3 className="h-3.5 w-3.5" />
899
+ </button>
900
+ <button
901
+ onClick={() => setDeleteModel(m)}
902
+ className="rounded-md p-1.5 text-gray-500 transition-colors hover:bg-red-500/10 hover:text-red-400"
903
+ title={t("models.delete_model")}
904
+ >
905
+ <Trash2 className="h-3.5 w-3.5" />
906
+ </button>
907
+ </div>
908
+ ))}
909
+ </div>
910
+ <div className="flex flex-wrap gap-2 mt-3">
911
+ <button
912
+ onClick={fetchModels}
913
+ disabled={!baseUrl.trim() || !isValidHttpUrl(baseUrl.trim()) || fetching}
914
+ title={
915
+ !baseUrl.trim() || !isValidHttpUrl(baseUrl.trim())
916
+ ? t("providers_models.fetch_no_endpoint")
917
+ : t("providers_models.fetch_models")
918
+ }
919
+ className="flex items-center gap-2 rounded-lg border border-gray-700 px-4 py-2 text-sm text-gray-300 transition-colors hover:bg-gray-800 disabled:cursor-not-allowed disabled:opacity-50"
920
+ >
921
+ {fetching ? <Loader2 className="h-4 w-4 animate-spin" /> : <Download className="h-4 w-4" />}
922
+ {fetching ? t("providers_models.fetching") : t("providers_models.fetch_models")}
923
+ </button>
924
+ <button
925
+ onClick={() => setShowAddModel(true)}
926
+ className="flex items-center gap-2 rounded-lg border border-gray-700 px-4 py-2 text-sm text-gray-300 transition-colors hover:bg-gray-800"
927
+ >
928
+ <Plus className="h-4 w-4" />
929
+ {t("models.add_model")}
930
+ </button>
931
+ </div>
932
+ </div>
933
+
934
+
935
+ {/* Fetch Models Modal */}
936
+ <Modal
937
+ open={fetchOpen}
938
+ onClose={() => { setFetchOpen(false); setFetchedModels([]); setFetchSelected(new Set()); setFetchError(null); setFetchImported(null); }}
939
+ title={t("providers_models.fetch_title")}
940
+ size="lg"
941
+ >
942
+ <div className="space-y-4">
943
+ <p className="text-sm text-gray-400">{t("providers_models.fetch_desc", provider.name)}</p>
944
+ {fetching && (
945
+ <div className="flex items-center gap-2 py-6 text-gray-400">
946
+ <Loader2 className="h-5 w-5 animate-spin" />
947
+ <span>{t("providers_models.fetching")}</span>
948
+ </div>
949
+ )}
950
+ {fetchError && !fetching && (
951
+ <div className="flex items-start gap-3 rounded-lg border border-red-500/30 bg-red-500/10 p-4">
952
+ <X className="h-5 w-5 shrink-0 text-red-400 mt-0.5" />
953
+ <p className="text-sm text-red-300">{t("providers_models.fetch_error", fetchError)}</p>
954
+ </div>
955
+ )}
956
+ {!fetching && !fetchError && availableModels.length === 0 && fetchedModels.length === 0 && (
957
+ <p className="text-sm text-gray-500">{t("providers_models.fetch_empty")}</p>
958
+ )}
959
+ {!fetching && !fetchError && availableModels.length > 0 && (
960
+ <>
961
+ <div className="flex items-center justify-between">
962
+ <span className="text-sm text-gray-400">
963
+ {t("providers_models.selected_count", String(fetchSelected.size), String(availableModels.length))}
964
+ </span>
965
+ <button onClick={toggleAll} className="rounded-md px-2 py-1 text-xs">
966
+ {allSelected
967
+ ? <span className="text-amber-400">{t("providers_models.deselect_all")}</span>
968
+ : <span className="text-emerald-400">{t("providers_models.select_all")}</span>
969
+ }
970
+ </button>
971
+ </div>
972
+ <div className="max-h-72 overflow-y-auto space-y-1.5 rounded-lg border border-gray-800 p-3">
973
+ {availableModels.map((m) => (
974
+ <label key={m.id} className="flex items-center gap-3 rounded-lg px-2 py-2 transition-colors hover:bg-gray-800 cursor-pointer">
975
+ <div className="flex h-5 w-5 shrink-0 items-center justify-center rounded border"
976
+ style={{ backgroundColor: isSelected(m.id) ? "#3b82f6" : "transparent", borderColor: isSelected(m.id) ? "#3b82f6" : "#4b5563" }}
977
+ >
978
+ {isSelected(m.id) && <SquareCheck className="h-4 w-4 text-white" />}
979
+ </div>
980
+ <input type="checkbox" checked={isSelected(m.id)} onChange={() => toggleSelect(m.id)} className="sr-only" />
981
+ <span className="min-w-0 flex-1 truncate font-mono text-sm text-gray-200">{m.id}</span>
982
+ <span className={`flex shrink-0 items-center gap-1 rounded border px-1.5 py-0.5 text-xs ${m.vision ? "border-blue-500/40 bg-blue-500/10 text-blue-400" : "border-gray-700 bg-gray-800 text-gray-500"}`}>
983
+ {m.vision && <ImageIcon className="h-3 w-3" />}
984
+ {m.vision ? t("providers_models.modality_vision") : t("providers_models.modality_text")}
985
+ </span>
986
+ {m.contextWindow && <span className="rounded border border-gray-700 bg-gray-800 px-1.5 py-0.5 text-xs text-gray-500 font-mono">{formatTokens(m.contextWindow)}</span>}
987
+ {m.maxTokens && <span className="rounded border border-gray-700 bg-gray-800 px-1.5 py-0.5 text-xs text-gray-500 font-mono">{formatTokens(m.maxTokens)}</span>}
988
+ </label>
989
+ ))}
990
+ </div>
991
+ </>
992
+ )}
993
+ <div className="flex items-center justify-end gap-3 pt-1">
994
+ {fetchImported !== null && (
995
+ <span className="flex items-center gap-1 text-sm text-emerald-400">
996
+ <Check className="h-4 w-4" />
997
+ {t("providers_models.import_done", String(fetchImported))}
998
+ </span>
999
+ )}
1000
+ <button onClick={() => { setFetchOpen(false); setFetchedModels([]); setFetchSelected(new Set()); setFetchError(null); setFetchImported(null); }}
1001
+ className="rounded-lg px-4 py-2 text-sm text-gray-400 hover:bg-gray-800">
1002
+ {t("models.cancel")}
1003
+ </button>
1004
+ <button onClick={handleImportFetched} disabled={fetching || fetchSelected.size === 0}
1005
+ className="flex items-center gap-2 rounded-lg px-4 py-2 text-sm font-medium transition-colors disabled:opacity-50"
1006
+ style={{ backgroundColor: "#3b82f6", color: "#ffffff" }}>
1007
+ {t("providers_models.confirm_import")}
1008
+ </button>
1009
+ </div>
1010
+ </div>
1011
+ </Modal>
1012
+
1013
+ {/* Edit Model Modal */}
1014
+ <Modal
1015
+ open={!!editModel}
1016
+ onClose={() => setEditModel(null)}
1017
+ title={`${t("models.edit_model")}: ${editModel?.name || editModel?.id}`}
1018
+ size="lg"
1019
+ >
1020
+ {editModel && (
1021
+ <ModelForm
1022
+ initial={editModel}
1023
+ onSubmit={(form) => {
1024
+ updateModel(provider.id, editModel.id, form);
1025
+ setEditModel(null);
1026
+ }}
1027
+ onCancel={() => setEditModel(null)}
1028
+ />
1029
+ )}
1030
+ </Modal>
1031
+
1032
+ {/* Add Model Modal */}
1033
+ <Modal
1034
+ open={showAddModel}
1035
+ onClose={() => setShowAddModel(false)}
1036
+ title={`${t("models.add_model")} — ${provider.name}`}
1037
+ size="lg"
1038
+ >
1039
+ <ModelForm
1040
+ onSubmit={(form) => {
1041
+ if (!form.id) return;
1042
+ addModel(provider.id, form as Model);
1043
+ setShowAddModel(false);
1044
+ }}
1045
+ onCancel={() => setShowAddModel(false)}
1046
+ />
1047
+ </Modal>
1048
+
1049
+ {/* Delete Model Confirmation Modal */}
1050
+ <Modal
1051
+ open={!!deleteModel}
1052
+ onClose={() => setDeleteModel(null)}
1053
+ title={t("models.delete_model")}
1054
+ >
1055
+ <div className="space-y-4">
1056
+ <div className="flex items-start gap-3">
1057
+ <Trash2 className="h-5 w-5 shrink-0 mt-0.5 text-red-400" />
1058
+ <p className="text-sm text-gray-200">
1059
+ <strong className="font-mono">{deleteModel?.id}</strong>
1060
+ {" — "}
1061
+ {t("models.delete_confirm")}
1062
+ </p>
1063
+ </div>
1064
+ <div className="flex justify-end gap-3">
1065
+ <button
1066
+ onClick={() => setDeleteModel(null)}
1067
+ className="rounded-lg px-4 py-2 text-sm text-gray-400 hover:bg-gray-800"
1068
+ >
1069
+ {t("models.cancel")}
1070
+ </button>
1071
+ <button
1072
+ onClick={() => {
1073
+ if (deleteModel) {
1074
+ removeModel(provider.id, deleteModel.id);
1075
+ setDeleteModel(null);
1076
+ }
1077
+ }}
1078
+ className="flex items-center gap-2 rounded-lg px-4 py-2 text-sm font-medium text-white"
1079
+ style={{ backgroundColor: "#dc2626" }}
1080
+ >
1081
+ <Trash2 className="h-4 w-4" />
1082
+ {t("models.delete_model")}
1083
+ </button>
1084
+ </div>
1085
+ </div>
1086
+ </Modal>
1087
+ </div>
1088
+ );
1089
+ }
1090
+
1091
+ // ─── Model Form (add & edit) ──────────────────────────────
1092
+
1093
+ function ModelForm({
1094
+ initial,
1095
+ onSubmit,
1096
+ onCancel,
1097
+ }: {
1098
+ initial?: Model;
1099
+ onSubmit: (form: Partial<Model>) => void;
1100
+ onCancel: () => void;
1101
+ }) {
1102
+ const { t } = useTranslation();
1103
+ const [form, setForm] = useState<Partial<Model>>(
1104
+ initial
1105
+ ? { ...initial }
1106
+ : {
1107
+ id: "",
1108
+ name: "",
1109
+ reasoning: false,
1110
+ input: ["text"],
1111
+ contextWindow: DEFAULT_CONTEXT_WINDOW,
1112
+ maxTokens: DEFAULT_MAX_TOKENS,
1113
+ cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
1114
+ }
1115
+ );
1116
+ const isEdit = !!initial;
1117
+
1118
+ return (
1119
+ <div className="space-y-4">
1120
+ <div className="grid grid-cols-2 gap-4">
1121
+ <div>
1122
+ <label className="block text-xs font-medium text-gray-400">{t("models.model_id")} *</label>
1123
+ <input
1124
+ type="text"
1125
+ value={form.id ?? ""}
1126
+ disabled={isEdit}
1127
+ onChange={(e) => setForm({ ...form, id: e.target.value })}
1128
+ placeholder="my-model-id"
1129
+ className="mt-1 w-full rounded-lg border border-gray-700 bg-gray-800 px-3 py-2 text-sm text-white disabled:opacity-50"
1130
+ />
1131
+ </div>
1132
+ <div>
1133
+ <label className="block text-xs font-medium text-gray-400">{t("models.display_name")}</label>
1134
+ <input
1135
+ type="text"
1136
+ value={form.name ?? ""}
1137
+ onChange={(e) => setForm({ ...form, name: e.target.value })}
1138
+ placeholder="My Custom Model"
1139
+ className="mt-1 w-full rounded-lg border border-gray-700 bg-gray-800 px-3 py-2 text-sm text-white"
1140
+ />
1141
+ </div>
1142
+ <div>
1143
+ <label className="block text-xs font-medium text-gray-400">{t("models.context_window")}</label>
1144
+ <input
1145
+ type="number"
1146
+ value={form.contextWindow ?? DEFAULT_CONTEXT_WINDOW}
1147
+ onChange={(e) => setForm({ ...form, contextWindow: parseInt(e.target.value) || DEFAULT_CONTEXT_WINDOW })}
1148
+ className="mt-1 w-full rounded-lg border border-gray-700 bg-gray-800 px-3 py-2 text-sm text-white"
1149
+ />
1150
+ </div>
1151
+ <div>
1152
+ <label className="block text-xs font-medium text-gray-400">{t("models.max_tokens")}</label>
1153
+ <input
1154
+ type="number"
1155
+ value={form.maxTokens ?? DEFAULT_MAX_TOKENS}
1156
+ onChange={(e) => setForm({ ...form, maxTokens: parseInt(e.target.value) || DEFAULT_MAX_TOKENS })}
1157
+ className="mt-1 w-full rounded-lg border border-gray-700 bg-gray-800 px-3 py-2 text-sm text-white"
1158
+ />
1159
+ </div>
1160
+ </div>
1161
+
1162
+ {/* Capabilities */}
1163
+ <div className="flex flex-wrap gap-3">
1164
+ <label className="flex items-center gap-2 text-sm text-gray-300">
1165
+ <input
1166
+ type="checkbox"
1167
+ checked={form.reasoning ?? false}
1168
+ onChange={(e) => setForm({ ...form, reasoning: e.target.checked })}
1169
+ className="rounded border-gray-600 bg-gray-800 text-blue-500"
1170
+ />
1171
+ {t("models.reasoning")}
1172
+ </label>
1173
+ <label className="flex items-center gap-2 text-sm text-gray-300">
1174
+ <input
1175
+ type="checkbox"
1176
+ checked={form.input?.includes("image") ?? false}
1177
+ onChange={(e) =>
1178
+ setForm({ ...form, input: e.target.checked ? ["text", "image"] : ["text"] })
1179
+ }
1180
+ className="rounded border-gray-600 bg-gray-800 text-blue-500"
1181
+ />
1182
+ {t("models.image_input")}
1183
+ </label>
1184
+ </div>
1185
+
1186
+ {/* Cost */}
1187
+ <div className="grid grid-cols-4 gap-3">
1188
+ {(
1189
+ [
1190
+ ["input", "models.cost_input"],
1191
+ ["output", "models.cost_output"],
1192
+ ["cacheRead", "models.cost_cache_read"],
1193
+ ["cacheWrite", "models.cost_cache_write"],
1194
+ ] as const
1195
+ ).map(([field, labelKey]) => (
1196
+ <div key={field}>
1197
+ <label className="block text-xs text-gray-500">{t(labelKey)} $/M</label>
1198
+ <input
1199
+ type="number"
1200
+ step="0.01"
1201
+ value={form.cost?.[field] ?? 0}
1202
+ onChange={(e) =>
1203
+ setForm({
1204
+ ...form,
1205
+ cost: {
1206
+ input: 0, output: 0, cacheRead: 0, cacheWrite: 0,
1207
+ ...form.cost,
1208
+ [field]: parseFloat(e.target.value) || 0,
1209
+ },
1210
+ })
1211
+ }
1212
+ className="mt-1 w-full rounded-lg border border-gray-700 bg-gray-800 px-3 py-2 text-sm text-white"
1213
+ />
1214
+ </div>
1215
+ ))}
1216
+ </div>
1217
+
1218
+ <div className="flex justify-end gap-3 pt-2">
1219
+ <button onClick={onCancel} className="rounded-lg px-4 py-2 text-sm text-gray-400 hover:bg-gray-800">
1220
+ {t("models.cancel")}
1221
+ </button>
1222
+ <button
1223
+ onClick={() => onSubmit(form)}
1224
+ disabled={!form.id}
1225
+ className="rounded-lg px-4 py-2 text-sm font-medium transition-colors disabled:opacity-50"
1226
+ style={{ backgroundColor: "#3b82f6", color: "#ffffff" }}
1227
+ >
1228
+ {isEdit ? t("models.save") : t("models.add_model")}
1229
+ </button>
1230
+ </div>
1231
+ </div>
1232
+ );
1233
+ }
1234
+
1235
+ // ─── Add Provider Form ────────────────────────────────────
1236
+
1237
+ function AddProviderForm({
1238
+ onSubmit,
1239
+ onCancel,
1240
+ }: {
1241
+ onSubmit: (id: string, cfg: CustomProviderConfig) => Promise<boolean>;
1242
+ onCancel: () => void;
1243
+ }) {
1244
+ const { t } = useTranslation();
1245
+ const { allProviders } = useConfigStore();
1246
+ const [name, setName] = useState("");
1247
+ const [baseUrl, setBaseUrl] = useState("");
1248
+ const [apiKey, setApiKey] = useState("");
1249
+ const [api, setApi] = useState<ApiType>("openai-completions");
1250
+ const [models, setModels] = useState<Model[]>([]);
1251
+ const [showAddModel, setShowAddModel] = useState(false);
1252
+ const [submitting, setSubmitting] = useState(false);
1253
+ const [submitError, setSubmitError] = useState(false);
1254
+
1255
+ const id = deriveProviderId(name, baseUrl);
1256
+ const idExists = !!id && allProviders.some((p) => p.id === id);
1257
+ const urlInvalid = baseUrl.trim() !== "" && !isValidHttpUrl(baseUrl.trim());
1258
+
1259
+ const handleSubmit = async () => {
1260
+ if (!id || !baseUrl || idExists || urlInvalid) return;
1261
+ setSubmitting(true);
1262
+ setSubmitError(false);
1263
+ const ok = await onSubmit(id, {
1264
+ name: name.trim() || undefined,
1265
+ baseUrl,
1266
+ api,
1267
+ apiKey: apiKey || undefined,
1268
+ models,
1269
+ });
1270
+ setSubmitting(false);
1271
+ if (!ok) setSubmitError(true);
1272
+ };
1273
+
1274
+ return (
1275
+ <div className="space-y-5">
1276
+ <div>
1277
+ <h2 className="text-lg font-semibold text-white">
1278
+ {t("providers_models.add_provider_title")}
1279
+ </h2>
1280
+ <p className="mt-1 text-sm text-gray-500">{t("providers_models.add_provider_desc")}</p>
1281
+ </div>
1282
+
1283
+ {/* Name */}
1284
+ <div>
1285
+ <label className="block text-sm text-gray-400">{t("providers_models.name")}</label>
1286
+ <input
1287
+ type="text"
1288
+ value={name}
1289
+ onChange={(e) => setName(e.target.value)}
1290
+ placeholder={t("providers_models.name_placeholder")}
1291
+ className={cn(
1292
+ "mt-1.5 w-full rounded-lg border bg-gray-800 px-3 py-2.5 text-sm text-white",
1293
+ idExists ? "border-red-500" : "border-gray-700"
1294
+ )}
1295
+ />
1296
+ {idExists ? (
1297
+ <p className="mt-1 text-xs text-red-400">{t("providers_models.id_exists", id)}</p>
1298
+ ) : id ? (
1299
+ <p className="mt-1 text-xs text-gray-500">{t("providers_models.id_preview", id)}</p>
1300
+ ) : name.trim() ? (
1301
+ <p className="mt-1 text-xs text-red-400">{t("providers_models.id_invalid")}</p>
1302
+ ) : null}
1303
+ </div>
1304
+
1305
+ {/* Base URL */}
1306
+ <div>
1307
+ <label className="block text-sm text-gray-400">{t("providers.base_url")}</label>
1308
+ <input
1309
+ type="text"
1310
+ value={baseUrl}
1311
+ onChange={(e) => setBaseUrl(e.target.value)}
1312
+ placeholder="https://api.example.com/v1"
1313
+ className={cn(
1314
+ "mt-1.5 w-full rounded-lg border bg-gray-800 px-3 py-2.5 text-sm text-white",
1315
+ urlInvalid ? "border-red-500" : "border-gray-700"
1316
+ )}
1317
+ />
1318
+ {urlInvalid && (
1319
+ <p className="mt-1 text-xs text-red-400">{t("providers_models.invalid_url")}</p>
1320
+ )}
1321
+ </div>
1322
+
1323
+ {/* API Key */}
1324
+ <div>
1325
+ <label className="block text-sm text-gray-400">{t("providers.api_key")}</label>
1326
+ <input
1327
+ type="password"
1328
+ value={apiKey}
1329
+ onChange={(e) => setApiKey(e.target.value)}
1330
+ placeholder="sk-... or $MY_API_KEY"
1331
+ className="mt-1.5 w-full rounded-lg border border-gray-700 bg-gray-800 px-3 py-2.5 text-sm text-white"
1332
+ />
1333
+ </div>
1334
+
1335
+ {/* API Type */}
1336
+ <div>
1337
+ <label className="block text-sm text-gray-400">{t("providers.api_type")}</label>
1338
+ <select
1339
+ value={api}
1340
+ onChange={(e) => setApi(e.target.value as ApiType)}
1341
+ className="mt-1.5 w-full rounded-lg border border-gray-700 bg-gray-800 px-3 py-2.5 text-sm text-white"
1342
+ >
1343
+ {API_TYPES.map((a) => (
1344
+ <option key={a.value} value={a.value}>{a.label}</option>
1345
+ ))}
1346
+ </select>
1347
+ </div>
1348
+
1349
+ {/* Connection test with the values entered above */}
1350
+ {baseUrl.trim() !== "" && !urlInvalid && (
1351
+ <TestConnectionButton baseUrl={baseUrl} apiKey={apiKey} />
1352
+ )}
1353
+
1354
+ {/* Initial Model List */}
1355
+ <div>
1356
+ <label className="block text-sm text-gray-400">{t("providers_models.model_list")}</label>
1357
+ {models.length > 0 && (
1358
+ <div className="mt-1.5 space-y-2">
1359
+ {models.map((m) => (
1360
+ <div
1361
+ key={m.id}
1362
+ className="flex items-center gap-2 rounded-lg border border-gray-700 bg-gray-900/70 px-3 py-2.5"
1363
+ >
1364
+ <Box className="h-4 w-4 shrink-0 text-gray-500" />
1365
+ <span className="min-w-0 flex-1 truncate font-mono text-sm text-gray-200">
1366
+ {m.id}
1367
+ </span>
1368
+ <span className="rounded-md border border-gray-600 bg-gray-800/50 px-2 py-0.5 text-xs text-gray-400">
1369
+ {m.contextWindow ? formatTokens(m.contextWindow) : "—"}
1370
+ </span>
1371
+ <button
1372
+ onClick={() => setModels(models.filter((x) => x.id !== m.id))}
1373
+ className="rounded-md p-1.5 text-gray-500 transition-colors hover:bg-red-500/10 hover:text-red-400"
1374
+ title={t("models.delete_model")}
1375
+ >
1376
+ <Trash2 className="h-3.5 w-3.5" />
1377
+ </button>
1378
+ </div>
1379
+ ))}
1380
+ </div>
1381
+ )}
1382
+ <button
1383
+ onClick={() => setShowAddModel(true)}
1384
+ className="mt-2 flex items-center gap-2 rounded-lg border border-gray-700 px-4 py-2 text-sm text-gray-300 transition-colors hover:bg-gray-800"
1385
+ >
1386
+ <Plus className="h-4 w-4" />
1387
+ {t("models.add_model")}
1388
+ </button>
1389
+ </div>
1390
+
1391
+ <div className="flex items-center gap-3">
1392
+ <button
1393
+ onClick={handleSubmit}
1394
+ disabled={!id || !baseUrl || idExists || urlInvalid || submitting}
1395
+ className="flex items-center gap-2 rounded-lg px-4 py-2 text-sm font-medium transition-colors disabled:opacity-50"
1396
+ style={{ backgroundColor: "#3b82f6", color: "#ffffff" }}
1397
+ >
1398
+ {submitting && <Loader2 className="h-4 w-4 animate-spin" />}
1399
+ {t("providers.add_provider")}
1400
+ </button>
1401
+ <button
1402
+ onClick={onCancel}
1403
+ className="rounded-lg px-4 py-2 text-sm text-gray-400 hover:bg-gray-800"
1404
+ >
1405
+ {t("models.cancel")}
1406
+ </button>
1407
+ {submitError && (
1408
+ <span className="flex items-center gap-1 text-sm text-red-400">
1409
+ <X className="h-4 w-4" />
1410
+ {t("providers_models.save_failed")}
1411
+ </span>
1412
+ )}
1413
+ </div>
1414
+
1415
+ {/* Add Initial Model Modal */}
1416
+ <Modal
1417
+ open={showAddModel}
1418
+ onClose={() => setShowAddModel(false)}
1419
+ title={t("models.add_model")}
1420
+ size="lg"
1421
+ >
1422
+ <ModelForm
1423
+ onSubmit={(form) => {
1424
+ if (!form.id) return;
1425
+ setModels([...models.filter((x) => x.id !== form.id), form as Model]);
1426
+ setShowAddModel(false);
1427
+ }}
1428
+ onCancel={() => setShowAddModel(false)}
1429
+ />
1430
+ </Modal>
1431
+ </div>
1432
+ );
1433
+ }
1434
+
1435
+ // ─── Import Provider Modal ─────────────────────────────────
1436
+
1437
+ function ImportProviderModal({
1438
+ open,
1439
+ onClose,
1440
+ onImported,
1441
+ }: {
1442
+ open: boolean;
1443
+ onClose: () => void;
1444
+ onImported: (id: string) => void;
1445
+ }) {
1446
+ const { t } = useTranslation();
1447
+ const { allProviders } = useConfigStore();
1448
+
1449
+ const [text, setText] = useState("");
1450
+ const [name, setName] = useState("");
1451
+ const [baseUrl, setBaseUrl] = useState("");
1452
+ const [apiKey, setApiKey] = useState("");
1453
+ const [api, setApi] = useState<ApiType>("openai-completions");
1454
+ const [modelIds, setModelIds] = useState<string[]>([]);
1455
+ const [submitting, setSubmitting] = useState(false);
1456
+ const [submitError, setSubmitError] = useState(false);
1457
+
1458
+ // ─── Fetch models from the endpoint (one-shot import) ───
1459
+ const [fetching, setFetching] = useState(false);
1460
+ const [fetchErr, setFetchErr] = useState<string | null>(null);
1461
+ const [fetchDone, setFetchDone] = useState(false);
1462
+ const [fetchedModels, setFetchedModels] = useState<{ id: string; contextWindow?: number; maxTokens?: number; vision?: boolean }[]>([]);
1463
+ const [fetchSel, setFetchSel] = useState<Set<string>>(new Set());
1464
+
1465
+ // Re-parse on every paste/edit of the raw text; fields below stay editable
1466
+ const handleText = (value: string) => {
1467
+ setText(value);
1468
+ const parsed = parseProviderImport(value);
1469
+ setName(parsed.name);
1470
+ setBaseUrl(parsed.baseUrl);
1471
+ setApiKey(parsed.apiKey);
1472
+ setModelIds(parsed.modelIds);
1473
+ };
1474
+
1475
+ const reset = () => {
1476
+ setText("");
1477
+ setName("");
1478
+ setBaseUrl("");
1479
+ setApiKey("");
1480
+ setApi("openai-completions");
1481
+ setModelIds([]);
1482
+ setSubmitting(false);
1483
+ setSubmitError(false);
1484
+ setFetching(false);
1485
+ setFetchErr(null);
1486
+ setFetchDone(false);
1487
+ setFetchedModels([]);
1488
+ setFetchSel(new Set());
1489
+ };
1490
+
1491
+ const id = deriveProviderId(name, baseUrl);
1492
+ const existing = allProviders.find((p) => p.id === id);
1493
+ const builtinConflict = existing?.type === "builtin";
1494
+ const mergeTarget = existing?.type === "custom" ? existing : null;
1495
+ const urlInvalid = baseUrl.trim() !== "" && !isValidHttpUrl(baseUrl.trim());
1496
+ const parsedEmpty =
1497
+ text.trim() !== "" && !name && !baseUrl && !apiKey && modelIds.length === 0;
1498
+ const canSubmit =
1499
+ !!id && (!!baseUrl.trim() || !!mergeTarget) && !urlInvalid && !builtinConflict && !submitting;
1500
+
1501
+ // Fetched models not already covered by the parsed model chips
1502
+ const availableFetched = fetchedModels.filter((m) => !modelIds.includes(m.id));
1503
+ const allFetchedSelected =
1504
+ availableFetched.length > 0 && availableFetched.every((m) => fetchSel.has(m.id));
1505
+
1506
+ const handleFetchModels = async () => {
1507
+ if (!isValidHttpUrl(baseUrl.trim()) || fetching) return;
1508
+ setFetching(true);
1509
+ setFetchErr(null);
1510
+ setFetchDone(false);
1511
+ try {
1512
+ const res = await fetch("/api/pi/provider-models", {
1513
+ method: "POST",
1514
+ headers: { "Content-Type": "application/json" },
1515
+ body: JSON.stringify({ baseUrl: baseUrl.trim(), apiKey, providerId: id || undefined }),
1516
+ });
1517
+ const data = await res.json();
1518
+ if (data.error) {
1519
+ setFetchErr(data.error);
1520
+ } else {
1521
+ const models = (data.models ?? []) as { id: string; contextWindow?: number; maxTokens?: number; vision?: boolean }[];
1522
+ setFetchedModels(models);
1523
+ // Select everything by default so import is a single click
1524
+ setFetchSel(new Set(models.map((m) => m.id)));
1525
+ }
1526
+ } catch {
1527
+ setFetchErr("network error");
1528
+ } finally {
1529
+ setFetching(false);
1530
+ setFetchDone(true);
1531
+ }
1532
+ };
1533
+
1534
+ const toggleFetched = (mid: string) => {
1535
+ setFetchSel((prev) => {
1536
+ const next = new Set(prev);
1537
+ next.has(mid) ? next.delete(mid) : next.add(mid);
1538
+ return next;
1539
+ });
1540
+ };
1541
+ const toggleAllFetched = () => {
1542
+ setFetchSel(allFetchedSelected ? new Set() : new Set(availableFetched.map((m) => m.id)));
1543
+ };
1544
+
1545
+ const handleImport = async () => {
1546
+ if (!canSubmit) return;
1547
+ setSubmitting(true);
1548
+ setSubmitError(false);
1549
+ const store = useConfigStore.getState();
1550
+ const defaults = {
1551
+ input: ["text"] as Model["input"],
1552
+ cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
1553
+ };
1554
+ const selectedFetched = availableFetched.filter((m) => fetchSel.has(m.id));
1555
+ const newModels: Model[] = [
1556
+ ...modelIds.map((mid) => ({
1557
+ id: mid,
1558
+ name: mid.split("/").pop() || mid,
1559
+ contextWindow: DEFAULT_CONTEXT_WINDOW,
1560
+ maxTokens: DEFAULT_MAX_TOKENS,
1561
+ ...defaults,
1562
+ })),
1563
+ // Fetched models carry real context/output limits when the endpoint provides them
1564
+ ...selectedFetched.map((m) => ({
1565
+ id: m.id,
1566
+ name: m.id.split("/").pop() || m.id,
1567
+ contextWindow: m.contextWindow ?? DEFAULT_CONTEXT_WINDOW,
1568
+ maxTokens: m.maxTokens ?? DEFAULT_MAX_TOKENS,
1569
+ ...defaults,
1570
+ input: (m.vision ? ["text", "image"] : ["text"]) as Model["input"],
1571
+ })),
1572
+ ];
1573
+ const newIds = newModels.map((m) => m.id);
1574
+
1575
+ let ok: boolean;
1576
+ if (mergeTarget) {
1577
+ // Merge into the existing custom provider (dedupe models by id)
1578
+ const existingCfg = store.modelsJson?.providers[id];
1579
+ const existingModels = existingCfg?.models ?? [];
1580
+ const merged = [
1581
+ ...existingModels,
1582
+ ...newModels.filter((m) => !existingModels.some((e) => e.id === m.id)),
1583
+ ];
1584
+ ok = await store.updateCustomProvider(id, {
1585
+ baseUrl: baseUrl.trim() || existingCfg?.baseUrl,
1586
+ apiKey: apiKey || existingCfg?.apiKey,
1587
+ models: merged,
1588
+ });
1589
+ } else {
1590
+ ok = await store.addCustomProvider(id, {
1591
+ name: name.trim() || undefined,
1592
+ baseUrl: baseUrl.trim(),
1593
+ api,
1594
+ apiKey: apiKey || undefined,
1595
+ models: newModels,
1596
+ });
1597
+ }
1598
+
1599
+ // Imported models are enabled by default (settings.enabledModels refs)
1600
+ if (ok && newIds.length > 0) {
1601
+ const refs = newIds.map((m) => `${id}/${m}`);
1602
+ const list = store.settings?.enabledModels ?? [];
1603
+ await store.updateSettings({ enabledModels: Array.from(new Set([...list, ...refs])) });
1604
+ }
1605
+
1606
+ setSubmitting(false);
1607
+ if (ok) {
1608
+ reset();
1609
+ onImported(id);
1610
+ } else {
1611
+ setSubmitError(true);
1612
+ }
1613
+ };
1614
+
1615
+ return (
1616
+ <Modal
1617
+ open={open}
1618
+ onClose={() => { reset(); onClose(); }}
1619
+ title={t("providers_models.import_title")}
1620
+ size="lg"
1621
+ >
1622
+ <div className="space-y-4">
1623
+ <p className="text-sm text-gray-500">{t("providers_models.import_desc")}</p>
1624
+
1625
+ {/* Paste area */}
1626
+ <textarea
1627
+ value={text}
1628
+ onChange={(e) => handleText(e.target.value)}
1629
+ rows={4}
1630
+ placeholder={t("providers_models.import_placeholder")}
1631
+ className="w-full rounded-lg border border-gray-700 bg-gray-800 px-3 py-2.5 font-mono text-sm text-white placeholder:text-gray-600"
1632
+ />
1633
+ {parsedEmpty && (
1634
+ <p className="text-xs text-amber-400">{t("providers_models.import_empty")}</p>
1635
+ )}
1636
+
1637
+ {/* Parsed preview (editable) */}
1638
+ <div className="grid grid-cols-2 gap-4">
1639
+ <div>
1640
+ <label className="block text-xs font-medium text-gray-400">
1641
+ {t("providers_models.name")}
1642
+ </label>
1643
+ <input
1644
+ type="text"
1645
+ value={name}
1646
+ onChange={(e) => setName(e.target.value)}
1647
+ placeholder={t("providers_models.name_placeholder")}
1648
+ className={cn(
1649
+ "mt-1 w-full rounded-lg border bg-gray-800 px-3 py-2 text-sm text-white",
1650
+ builtinConflict ? "border-red-500" : "border-gray-700"
1651
+ )}
1652
+ />
1653
+ {builtinConflict ? (
1654
+ <p className="mt-1 text-xs text-red-400">
1655
+ {t("providers_models.import_builtin_conflict", id)}
1656
+ </p>
1657
+ ) : mergeTarget ? (
1658
+ <p className="mt-1 text-xs text-amber-400">
1659
+ {t("providers_models.import_merge", id)}
1660
+ </p>
1661
+ ) : id ? (
1662
+ <p className="mt-1 text-xs text-gray-500">{t("providers_models.id_preview", id)}</p>
1663
+ ) : name.trim() ? (
1664
+ <p className="mt-1 text-xs text-red-400">{t("providers_models.id_invalid")}</p>
1665
+ ) : null}
1666
+ </div>
1667
+ <div>
1668
+ <label className="block text-xs font-medium text-gray-400">
1669
+ {t("providers.api_type")}
1670
+ </label>
1671
+ <select
1672
+ value={api}
1673
+ onChange={(e) => setApi(e.target.value as ApiType)}
1674
+ className="mt-1 w-full rounded-lg border border-gray-700 bg-gray-800 px-3 py-2 text-sm text-white"
1675
+ >
1676
+ {API_TYPES.map((a) => (
1677
+ <option key={a.value} value={a.value}>{a.label}</option>
1678
+ ))}
1679
+ </select>
1680
+ </div>
1681
+ <div>
1682
+ <label className="block text-xs font-medium text-gray-400">
1683
+ {t("providers.base_url")}
1684
+ </label>
1685
+ <input
1686
+ type="text"
1687
+ value={baseUrl}
1688
+ onChange={(e) => setBaseUrl(e.target.value)}
1689
+ placeholder="https://api.example.com/v1"
1690
+ className={cn(
1691
+ "mt-1 w-full rounded-lg border bg-gray-800 px-3 py-2 text-sm text-white",
1692
+ urlInvalid ? "border-red-500" : "border-gray-700"
1693
+ )}
1694
+ />
1695
+ {urlInvalid && (
1696
+ <p className="mt-1 text-xs text-red-400">{t("providers_models.invalid_url")}</p>
1697
+ )}
1698
+ </div>
1699
+ <div>
1700
+ <label className="block text-xs font-medium text-gray-400">
1701
+ {t("providers.api_key")}
1702
+ </label>
1703
+ <input
1704
+ type="password"
1705
+ value={apiKey}
1706
+ onChange={(e) => setApiKey(e.target.value)}
1707
+ placeholder="sk-... or $MY_API_KEY"
1708
+ className="mt-1 w-full rounded-lg border border-gray-700 bg-gray-800 px-3 py-2 text-sm text-white"
1709
+ />
1710
+ </div>
1711
+ </div>
1712
+
1713
+ {/* Detected models */}
1714
+ {modelIds.length > 0 && (
1715
+ <div>
1716
+ <label className="block text-xs font-medium text-gray-400">
1717
+ {t("providers_models.model_list")}
1718
+ </label>
1719
+ <div className="mt-1.5 flex flex-wrap gap-2">
1720
+ {modelIds.map((mid) => (
1721
+ <span
1722
+ key={mid}
1723
+ className="flex items-center gap-1.5 rounded-md border border-gray-700 bg-gray-800 px-2 py-1 font-mono text-xs text-gray-200"
1724
+ >
1725
+ <Box className="h-3 w-3 text-gray-500" />
1726
+ {mid}
1727
+ <button
1728
+ onClick={() => setModelIds(modelIds.filter((x) => x !== mid))}
1729
+ className="text-gray-500 hover:text-red-400"
1730
+ >
1731
+ <X className="h-3 w-3" />
1732
+ </button>
1733
+ </span>
1734
+ ))}
1735
+ </div>
1736
+ </div>
1737
+ )}
1738
+
1739
+ {/* Fetch models from the endpoint — one-shot: fetch, tick, import */}
1740
+ <div>
1741
+ <div className="flex flex-wrap items-center gap-3">
1742
+ <button
1743
+ onClick={handleFetchModels}
1744
+ disabled={!isValidHttpUrl(baseUrl.trim()) || fetching}
1745
+ title={
1746
+ !isValidHttpUrl(baseUrl.trim())
1747
+ ? t("providers_models.fetch_no_endpoint")
1748
+ : t("providers_models.fetch_models")
1749
+ }
1750
+ className="flex items-center gap-2 rounded-lg border border-gray-700 px-4 py-2 text-sm text-gray-300 transition-colors hover:bg-gray-800 disabled:cursor-not-allowed disabled:opacity-50"
1751
+ >
1752
+ {fetching ? <Loader2 className="h-4 w-4 animate-spin" /> : <Download className="h-4 w-4" />}
1753
+ {fetching ? t("providers_models.fetching") : t("providers_models.fetch_models")}
1754
+ </button>
1755
+ {fetchErr && (
1756
+ <span className="text-xs text-red-400">{t("providers_models.fetch_error", fetchErr)}</span>
1757
+ )}
1758
+ {fetchDone && !fetchErr && fetchedModels.length === 0 && (
1759
+ <span className="text-xs text-amber-400">{t("providers_models.fetch_empty")}</span>
1760
+ )}
1761
+ </div>
1762
+ {availableFetched.length > 0 && (
1763
+ <div className="mt-2 rounded-lg border border-gray-700">
1764
+ <div className="flex items-center justify-between border-b border-gray-700 px-3 py-2">
1765
+ <span className="text-xs text-gray-400">
1766
+ {t("providers_models.selected_count", String(fetchSel.size), String(availableFetched.length))}
1767
+ </span>
1768
+ <button
1769
+ onClick={toggleAllFetched}
1770
+ className="text-xs text-blue-400 hover:text-blue-300"
1771
+ >
1772
+ {allFetchedSelected ? t("providers_models.deselect_all") : t("providers_models.select_all")}
1773
+ </button>
1774
+ </div>
1775
+ <div className="max-h-44 overflow-y-auto p-1.5">
1776
+ {availableFetched.map((m) => (
1777
+ <label
1778
+ key={m.id}
1779
+ className="flex cursor-pointer items-center gap-2.5 rounded-md px-2 py-1.5 hover:bg-gray-800"
1780
+ >
1781
+ <input
1782
+ type="checkbox"
1783
+ checked={fetchSel.has(m.id)}
1784
+ onChange={() => toggleFetched(m.id)}
1785
+ className="h-3.5 w-3.5 accent-blue-500"
1786
+ />
1787
+ <span className="truncate font-mono text-xs text-gray-200">{m.id}</span>
1788
+ <span className={`ml-auto flex shrink-0 items-center gap-1 rounded border px-1 py-px text-[10px] ${m.vision ? "border-blue-500/40 bg-blue-500/10 text-blue-400" : "border-gray-700 bg-gray-800 text-gray-500"}`}>
1789
+ {m.vision && <ImageIcon className="h-2.5 w-2.5" />}
1790
+ {m.vision ? t("providers_models.modality_vision") : t("providers_models.modality_text")}
1791
+ </span>
1792
+ {m.contextWindow && (
1793
+ <span className="shrink-0 text-[10px] text-gray-500">
1794
+ {formatTokens(m.contextWindow)}
1795
+ </span>
1796
+ )}
1797
+ </label>
1798
+ ))}
1799
+ </div>
1800
+ </div>
1801
+ )}
1802
+ </div>
1803
+
1804
+ <div className="flex items-center justify-end gap-3 pt-1">
1805
+ {submitError && (
1806
+ <span className="flex items-center gap-1 text-sm text-red-400">
1807
+ <X className="h-4 w-4" />
1808
+ {t("providers_models.save_failed")}
1809
+ </span>
1810
+ )}
1811
+ <button
1812
+ onClick={() => { reset(); onClose(); }}
1813
+ className="rounded-lg px-4 py-2 text-sm text-gray-400 hover:bg-gray-800"
1814
+ >
1815
+ {t("models.cancel")}
1816
+ </button>
1817
+ <button
1818
+ onClick={handleImport}
1819
+ disabled={!canSubmit}
1820
+ className="flex items-center gap-2 rounded-lg px-4 py-2 text-sm font-medium transition-colors disabled:opacity-50"
1821
+ style={{ backgroundColor: "#3b82f6", color: "#ffffff" }}
1822
+ >
1823
+ {submitting && <Loader2 className="h-4 w-4 animate-spin" />}
1824
+ {t("providers_models.import")}
1825
+ </button>
1826
+ </div>
1827
+ </div>
1828
+ </Modal>
1829
+ );
1830
+ }