rechrome 1.35.1 → 1.36.1

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 (402) hide show
  1. package/README.md +79 -0
  2. package/extension/lib/background.mjs +28 -1
  3. package/extension/lib/ui/connect.js +29 -19
  4. package/listeners.js +17 -1
  5. package/listeners.ts +7 -2
  6. package/package.json +5 -3
  7. package/rechrome.js +101 -17
  8. package/rechrome.ts +101 -17
  9. package/scoped-upload.js +165 -0
  10. package/scoped-upload.ts +140 -0
  11. package/serve.js +140 -25
  12. package/serve.ts +140 -25
  13. package/vendor/playwright-cli/node_modules/playwright-core/lib/coreBundle.js +360 -256
  14. package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/cli-client/help.json +9 -4
  15. package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/cli-client/program.js +6 -1
  16. package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/cli-client/session.js +10 -12
  17. package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/utils/extension.js +8 -5
  18. package/vendor/playwright-cli/node_modules/playwright-core/lib/androidServerImpl.js +0 -65
  19. package/vendor/playwright-cli/node_modules/playwright-core/lib/browserServerImpl.js +0 -120
  20. package/vendor/playwright-cli/node_modules/playwright-core/lib/cli/driver.js +0 -98
  21. package/vendor/playwright-cli/node_modules/playwright-core/lib/cli/program.js +0 -597
  22. package/vendor/playwright-cli/node_modules/playwright-core/lib/cli/programWithTestStub.js +0 -74
  23. package/vendor/playwright-cli/node_modules/playwright-core/lib/client/android.js +0 -361
  24. package/vendor/playwright-cli/node_modules/playwright-core/lib/client/api.js +0 -137
  25. package/vendor/playwright-cli/node_modules/playwright-core/lib/client/artifact.js +0 -79
  26. package/vendor/playwright-cli/node_modules/playwright-core/lib/client/browser.js +0 -169
  27. package/vendor/playwright-cli/node_modules/playwright-core/lib/client/browserContext.js +0 -583
  28. package/vendor/playwright-cli/node_modules/playwright-core/lib/client/browserType.js +0 -153
  29. package/vendor/playwright-cli/node_modules/playwright-core/lib/client/cdpSession.js +0 -55
  30. package/vendor/playwright-cli/node_modules/playwright-core/lib/client/channelOwner.js +0 -194
  31. package/vendor/playwright-cli/node_modules/playwright-core/lib/client/clientHelper.js +0 -64
  32. package/vendor/playwright-cli/node_modules/playwright-core/lib/client/clientInstrumentation.js +0 -55
  33. package/vendor/playwright-cli/node_modules/playwright-core/lib/client/clientStackTrace.js +0 -69
  34. package/vendor/playwright-cli/node_modules/playwright-core/lib/client/clock.js +0 -68
  35. package/vendor/playwright-cli/node_modules/playwright-core/lib/client/connect.js +0 -143
  36. package/vendor/playwright-cli/node_modules/playwright-core/lib/client/connection.js +0 -322
  37. package/vendor/playwright-cli/node_modules/playwright-core/lib/client/consoleMessage.js +0 -61
  38. package/vendor/playwright-cli/node_modules/playwright-core/lib/client/coverage.js +0 -44
  39. package/vendor/playwright-cli/node_modules/playwright-core/lib/client/debugger.js +0 -57
  40. package/vendor/playwright-cli/node_modules/playwright-core/lib/client/dialog.js +0 -56
  41. package/vendor/playwright-cli/node_modules/playwright-core/lib/client/disposable.js +0 -76
  42. package/vendor/playwright-cli/node_modules/playwright-core/lib/client/download.js +0 -62
  43. package/vendor/playwright-cli/node_modules/playwright-core/lib/client/electron.js +0 -138
  44. package/vendor/playwright-cli/node_modules/playwright-core/lib/client/elementHandle.js +0 -281
  45. package/vendor/playwright-cli/node_modules/playwright-core/lib/client/errors.js +0 -77
  46. package/vendor/playwright-cli/node_modules/playwright-core/lib/client/eventEmitter.js +0 -314
  47. package/vendor/playwright-cli/node_modules/playwright-core/lib/client/events.js +0 -103
  48. package/vendor/playwright-cli/node_modules/playwright-core/lib/client/fetch.js +0 -367
  49. package/vendor/playwright-cli/node_modules/playwright-core/lib/client/fileChooser.js +0 -46
  50. package/vendor/playwright-cli/node_modules/playwright-core/lib/client/fileUtils.js +0 -34
  51. package/vendor/playwright-cli/node_modules/playwright-core/lib/client/frame.js +0 -404
  52. package/vendor/playwright-cli/node_modules/playwright-core/lib/client/harRouter.js +0 -99
  53. package/vendor/playwright-cli/node_modules/playwright-core/lib/client/input.js +0 -84
  54. package/vendor/playwright-cli/node_modules/playwright-core/lib/client/jsHandle.js +0 -105
  55. package/vendor/playwright-cli/node_modules/playwright-core/lib/client/jsonPipe.js +0 -39
  56. package/vendor/playwright-cli/node_modules/playwright-core/lib/client/localUtils.js +0 -60
  57. package/vendor/playwright-cli/node_modules/playwright-core/lib/client/locator.js +0 -367
  58. package/vendor/playwright-cli/node_modules/playwright-core/lib/client/network.js +0 -750
  59. package/vendor/playwright-cli/node_modules/playwright-core/lib/client/page.js +0 -729
  60. package/vendor/playwright-cli/node_modules/playwright-core/lib/client/platform.js +0 -77
  61. package/vendor/playwright-cli/node_modules/playwright-core/lib/client/playwright.js +0 -71
  62. package/vendor/playwright-cli/node_modules/playwright-core/lib/client/screencast.js +0 -48
  63. package/vendor/playwright-cli/node_modules/playwright-core/lib/client/selectors.js +0 -57
  64. package/vendor/playwright-cli/node_modules/playwright-core/lib/client/stream.js +0 -39
  65. package/vendor/playwright-cli/node_modules/playwright-core/lib/client/timeoutSettings.js +0 -79
  66. package/vendor/playwright-cli/node_modules/playwright-core/lib/client/tracing.js +0 -126
  67. package/vendor/playwright-cli/node_modules/playwright-core/lib/client/types.js +0 -28
  68. package/vendor/playwright-cli/node_modules/playwright-core/lib/client/video.js +0 -68
  69. package/vendor/playwright-cli/node_modules/playwright-core/lib/client/waiter.js +0 -142
  70. package/vendor/playwright-cli/node_modules/playwright-core/lib/client/webError.js +0 -39
  71. package/vendor/playwright-cli/node_modules/playwright-core/lib/client/worker.js +0 -85
  72. package/vendor/playwright-cli/node_modules/playwright-core/lib/client/writableStream.js +0 -39
  73. package/vendor/playwright-cli/node_modules/playwright-core/lib/generated/bindingsControllerSource.js +0 -28
  74. package/vendor/playwright-cli/node_modules/playwright-core/lib/generated/clockSource.js +0 -28
  75. package/vendor/playwright-cli/node_modules/playwright-core/lib/generated/injectedScriptSource.js +0 -28
  76. package/vendor/playwright-cli/node_modules/playwright-core/lib/generated/pollingRecorderSource.js +0 -28
  77. package/vendor/playwright-cli/node_modules/playwright-core/lib/generated/storageScriptSource.js +0 -28
  78. package/vendor/playwright-cli/node_modules/playwright-core/lib/generated/utilityScriptSource.js +0 -28
  79. package/vendor/playwright-cli/node_modules/playwright-core/lib/generated/webSocketMockSource.js +0 -336
  80. package/vendor/playwright-cli/node_modules/playwright-core/lib/inProcessFactory.js +0 -60
  81. package/vendor/playwright-cli/node_modules/playwright-core/lib/inprocess.js +0 -3
  82. package/vendor/playwright-cli/node_modules/playwright-core/lib/mcpBundle.js +0 -81
  83. package/vendor/playwright-cli/node_modules/playwright-core/lib/mcpBundleImpl/index.js +0 -91
  84. package/vendor/playwright-cli/node_modules/playwright-core/lib/outofprocess.js +0 -76
  85. package/vendor/playwright-cli/node_modules/playwright-core/lib/protocol/serializers.js +0 -197
  86. package/vendor/playwright-cli/node_modules/playwright-core/lib/protocol/validator.js +0 -3034
  87. package/vendor/playwright-cli/node_modules/playwright-core/lib/protocol/validatorPrimitives.js +0 -193
  88. package/vendor/playwright-cli/node_modules/playwright-core/lib/remote/playwrightConnection.js +0 -131
  89. package/vendor/playwright-cli/node_modules/playwright-core/lib/remote/playwrightPipeServer.js +0 -100
  90. package/vendor/playwright-cli/node_modules/playwright-core/lib/remote/playwrightServer.js +0 -339
  91. package/vendor/playwright-cli/node_modules/playwright-core/lib/remote/playwrightWebSocketServer.js +0 -73
  92. package/vendor/playwright-cli/node_modules/playwright-core/lib/remote/serverTransport.js +0 -96
  93. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/android/android.js +0 -465
  94. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/android/backendAdb.js +0 -177
  95. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/artifact.js +0 -127
  96. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/bidi/bidiBrowser.js +0 -571
  97. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/bidi/bidiChromium.js +0 -162
  98. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/bidi/bidiConnection.js +0 -213
  99. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/bidi/bidiDeserializer.js +0 -116
  100. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/bidi/bidiExecutionContext.js +0 -267
  101. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/bidi/bidiFirefox.js +0 -128
  102. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/bidi/bidiInput.js +0 -146
  103. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/bidi/bidiNetworkManager.js +0 -411
  104. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/bidi/bidiOverCdp.js +0 -102
  105. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/bidi/bidiPage.js +0 -599
  106. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/bidi/bidiPdf.js +0 -106
  107. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/bidi/third_party/bidiCommands.d.js +0 -22
  108. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/bidi/third_party/bidiKeyboard.js +0 -256
  109. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/bidi/third_party/bidiProtocol.js +0 -24
  110. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/bidi/third_party/bidiProtocolCore.js +0 -180
  111. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/bidi/third_party/bidiProtocolPermissions.js +0 -42
  112. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/bidi/third_party/bidiSerializer.js +0 -148
  113. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/bidi/third_party/firefoxPrefs.js +0 -261
  114. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/browser.js +0 -223
  115. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/browserContext.js +0 -703
  116. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/browserType.js +0 -338
  117. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/callLog.js +0 -82
  118. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/chromium/chromium.js +0 -399
  119. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/chromium/chromiumSwitches.js +0 -104
  120. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/chromium/crBrowser.js +0 -532
  121. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/chromium/crConnection.js +0 -197
  122. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/chromium/crCoverage.js +0 -235
  123. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/chromium/crDevTools.js +0 -111
  124. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/chromium/crDragDrop.js +0 -131
  125. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/chromium/crExecutionContext.js +0 -146
  126. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/chromium/crInput.js +0 -187
  127. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/chromium/crNetworkManager.js +0 -708
  128. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/chromium/crPage.js +0 -1004
  129. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/chromium/crPdf.js +0 -121
  130. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/chromium/crProtocolHelper.js +0 -145
  131. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/chromium/crServiceWorker.js +0 -137
  132. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/chromium/defaultFontFamilies.js +0 -162
  133. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/chromium/protocol.d.js +0 -16
  134. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/clock.js +0 -149
  135. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/codegen/csharp.js +0 -327
  136. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/codegen/java.js +0 -274
  137. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/codegen/javascript.js +0 -247
  138. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/codegen/jsonl.js +0 -52
  139. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/codegen/language.js +0 -132
  140. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/codegen/languages.js +0 -68
  141. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/codegen/python.js +0 -279
  142. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/codegen/types.js +0 -16
  143. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/console.js +0 -61
  144. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/cookieStore.js +0 -206
  145. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/debugController.js +0 -197
  146. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/debugger.js +0 -120
  147. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/deviceDescriptors.js +0 -39
  148. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/dialog.js +0 -116
  149. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/dispatchers/androidDispatcher.js +0 -325
  150. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/dispatchers/artifactDispatcher.js +0 -118
  151. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/dispatchers/browserContextDispatcher.js +0 -381
  152. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/dispatchers/browserDispatcher.js +0 -124
  153. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/dispatchers/browserTypeDispatcher.js +0 -71
  154. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/dispatchers/cdpSessionDispatcher.js +0 -47
  155. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/dispatchers/debugControllerDispatcher.js +0 -78
  156. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/dispatchers/debuggerDispatcher.js +0 -80
  157. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/dispatchers/dialogDispatcher.js +0 -47
  158. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/dispatchers/dispatcher.js +0 -364
  159. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/dispatchers/disposableDispatcher.js +0 -39
  160. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/dispatchers/electronDispatcher.js +0 -90
  161. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/dispatchers/elementHandlerDispatcher.js +0 -181
  162. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/dispatchers/frameDispatcher.js +0 -227
  163. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/dispatchers/jsHandleDispatcher.js +0 -85
  164. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/dispatchers/jsonPipeDispatcher.js +0 -58
  165. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/dispatchers/localUtilsDispatcher.js +0 -185
  166. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/dispatchers/networkDispatchers.js +0 -214
  167. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/dispatchers/pageDispatcher.js +0 -434
  168. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/dispatchers/playwrightDispatcher.js +0 -108
  169. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/dispatchers/streamDispatcher.js +0 -67
  170. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/dispatchers/tracingDispatcher.js +0 -68
  171. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/dispatchers/webSocketRouteDispatcher.js +0 -164
  172. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/dispatchers/writableStreamDispatcher.js +0 -79
  173. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/disposable.js +0 -41
  174. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/dom.js +0 -823
  175. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/download.js +0 -71
  176. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/electron/electron.js +0 -272
  177. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/electron/loader.js +0 -115
  178. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/errors.js +0 -69
  179. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/fetch.js +0 -621
  180. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/fileChooser.js +0 -43
  181. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/fileUploadUtils.js +0 -84
  182. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/firefox/ffBrowser.js +0 -415
  183. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/firefox/ffConnection.js +0 -142
  184. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/firefox/ffExecutionContext.js +0 -150
  185. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/firefox/ffInput.js +0 -175
  186. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/firefox/ffNetworkManager.js +0 -256
  187. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/firefox/ffPage.js +0 -495
  188. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/firefox/firefox.js +0 -114
  189. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/firefox/protocol.d.js +0 -16
  190. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/formData.js +0 -147
  191. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/frameSelectors.js +0 -160
  192. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/frames.js +0 -1495
  193. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/har/harRecorder.js +0 -147
  194. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/har/harTracer.js +0 -608
  195. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/harBackend.js +0 -157
  196. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/helper.js +0 -96
  197. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/index.js +0 -58
  198. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/input.js +0 -277
  199. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/instrumentation.js +0 -72
  200. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/javascript.js +0 -291
  201. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/launchApp.js +0 -127
  202. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/localUtils.js +0 -214
  203. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/macEditingCommands.js +0 -143
  204. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/network.js +0 -668
  205. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/page.js +0 -884
  206. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/pipeTransport.js +0 -89
  207. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/playwright.js +0 -69
  208. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/progress.js +0 -136
  209. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/protocolError.js +0 -52
  210. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/recorder/chat.js +0 -161
  211. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/recorder/recorderApp.js +0 -367
  212. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/recorder/recorderRunner.js +0 -138
  213. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/recorder/recorderSignalProcessor.js +0 -83
  214. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/recorder/recorderUtils.js +0 -157
  215. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/recorder/throttledFile.js +0 -57
  216. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/recorder.js +0 -540
  217. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/registry/browserFetcher.js +0 -177
  218. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/registry/dependencies.js +0 -371
  219. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/registry/index.js +0 -1395
  220. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/registry/nativeDeps.js +0 -1281
  221. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/registry/oopDownloadBrowserMain.js +0 -127
  222. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/screencast.js +0 -216
  223. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/screenshotter.js +0 -333
  224. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/selectors.js +0 -112
  225. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/socksClientCertificatesInterceptor.js +0 -383
  226. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/socksInterceptor.js +0 -95
  227. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/trace/recorder/snapshotter.js +0 -147
  228. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/trace/recorder/snapshotterInjected.js +0 -561
  229. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/trace/recorder/tracing.js +0 -607
  230. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/trace/viewer/traceViewer.js +0 -244
  231. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/transport.js +0 -181
  232. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/types.js +0 -28
  233. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/usKeyboardLayout.js +0 -152
  234. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/utils/ascii.js +0 -44
  235. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/utils/comparators.js +0 -139
  236. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/utils/crypto.js +0 -216
  237. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/utils/debug.js +0 -42
  238. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/utils/debugLogger.js +0 -122
  239. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/utils/disposable.js +0 -32
  240. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/utils/env.js +0 -73
  241. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/utils/eventsHelper.js +0 -41
  242. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/utils/expectUtils.js +0 -123
  243. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/utils/fileUtils.js +0 -191
  244. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/utils/happyEyeballs.js +0 -207
  245. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/utils/hostPlatform.js +0 -123
  246. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/utils/httpServer.js +0 -205
  247. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/utils/image_tools/colorUtils.js +0 -89
  248. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/utils/image_tools/compare.js +0 -109
  249. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/utils/image_tools/imageChannel.js +0 -78
  250. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/utils/image_tools/stats.js +0 -102
  251. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/utils/linuxUtils.js +0 -71
  252. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/utils/network.js +0 -244
  253. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/utils/nodePlatform.js +0 -154
  254. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/utils/pipeTransport.js +0 -84
  255. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/utils/processLauncher.js +0 -243
  256. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/utils/profiler.js +0 -65
  257. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/utils/socksProxy.js +0 -511
  258. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/utils/spawnAsync.js +0 -41
  259. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/utils/task.js +0 -51
  260. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/utils/userAgent.js +0 -98
  261. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/utils/wsServer.js +0 -121
  262. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/utils/zipFile.js +0 -74
  263. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/utils/zones.js +0 -57
  264. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/videoRecorder.js +0 -133
  265. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/webkit/protocol.d.js +0 -16
  266. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/webkit/webkit.js +0 -108
  267. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/webkit/wkBrowser.js +0 -331
  268. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/webkit/wkConnection.js +0 -144
  269. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/webkit/wkExecutionContext.js +0 -154
  270. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/webkit/wkInput.js +0 -181
  271. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/webkit/wkInterceptableRequest.js +0 -197
  272. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/webkit/wkPage.js +0 -1164
  273. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/webkit/wkProvisionalPage.js +0 -83
  274. package/vendor/playwright-cli/node_modules/playwright-core/lib/server/webkit/wkWorkers.js +0 -106
  275. package/vendor/playwright-cli/node_modules/playwright-core/lib/third_party/pixelmatch.js +0 -255
  276. package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/backend/browserBackend.js +0 -79
  277. package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/backend/common.js +0 -63
  278. package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/backend/config.js +0 -41
  279. package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/backend/console.js +0 -66
  280. package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/backend/context.js +0 -290
  281. package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/backend/cookies.js +0 -152
  282. package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/backend/devtools.js +0 -69
  283. package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/backend/dialogs.js +0 -59
  284. package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/backend/evaluate.js +0 -64
  285. package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/backend/files.js +0 -60
  286. package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/backend/form.js +0 -64
  287. package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/backend/keyboard.js +0 -155
  288. package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/backend/logFile.js +0 -95
  289. package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/backend/mouse.js +0 -168
  290. package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/backend/navigate.js +0 -106
  291. package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/backend/network.js +0 -135
  292. package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/backend/pdf.js +0 -48
  293. package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/backend/response.js +0 -302
  294. package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/backend/route.js +0 -140
  295. package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/backend/runCode.js +0 -76
  296. package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/backend/screenshot.js +0 -88
  297. package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/backend/sessionLog.js +0 -74
  298. package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/backend/snapshot.js +0 -208
  299. package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/backend/storage.js +0 -67
  300. package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/backend/tab.js +0 -445
  301. package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/backend/tabs.js +0 -67
  302. package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/backend/tool.js +0 -47
  303. package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/backend/tools.js +0 -102
  304. package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/backend/tracing.js +0 -75
  305. package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/backend/utils.js +0 -83
  306. package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/backend/verify.js +0 -151
  307. package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/backend/video.js +0 -89
  308. package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/backend/wait.js +0 -63
  309. package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/backend/webstorage.js +0 -223
  310. package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/cli-daemon/command.js +0 -73
  311. package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/cli-daemon/commands.js +0 -933
  312. package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/cli-daemon/daemon.js +0 -178
  313. package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/cli-daemon/helpGenerator.js +0 -173
  314. package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/cli-daemon/program.js +0 -118
  315. package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/dashboard/dashboardApp.js +0 -286
  316. package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/dashboard/dashboardController.js +0 -296
  317. package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/exports.js +0 -60
  318. package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/mcp/browserFactory.js +0 -233
  319. package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/mcp/cdpRelay.js +0 -356
  320. package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/mcp/cli-stub.js +0 -7
  321. package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/mcp/config.d.js +0 -16
  322. package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/mcp/config.js +0 -401
  323. package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/mcp/configIni.js +0 -189
  324. package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/mcp/extensionContextFactory.js +0 -59
  325. package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/mcp/index.js +0 -62
  326. package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/mcp/log.js +0 -35
  327. package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/mcp/program.js +0 -107
  328. package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/mcp/protocol.js +0 -28
  329. package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/mcp/watchdog.js +0 -44
  330. package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/trace/installSkill.js +0 -48
  331. package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/trace/traceActions.js +0 -142
  332. package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/trace/traceAttachments.js +0 -69
  333. package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/trace/traceCli.js +0 -80
  334. package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/trace/traceConsole.js +0 -97
  335. package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/trace/traceErrors.js +0 -55
  336. package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/trace/traceOpen.js +0 -69
  337. package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/trace/traceParser.js +0 -96
  338. package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/trace/traceRequests.js +0 -158
  339. package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/trace/traceScreenshot.js +0 -68
  340. package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/trace/traceSnapshot.js +0 -149
  341. package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/trace/traceUtils.js +0 -135
  342. package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/utils/connect.js +0 -32
  343. package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/utils/mcp/http.js +0 -152
  344. package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/utils/mcp/server.js +0 -230
  345. package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/utils/mcp/tool.js +0 -47
  346. package/vendor/playwright-cli/node_modules/playwright-core/lib/utils/isomorphic/ariaSnapshot.js +0 -455
  347. package/vendor/playwright-cli/node_modules/playwright-core/lib/utils/isomorphic/assert.js +0 -31
  348. package/vendor/playwright-cli/node_modules/playwright-core/lib/utils/isomorphic/colors.js +0 -72
  349. package/vendor/playwright-cli/node_modules/playwright-core/lib/utils/isomorphic/cssParser.js +0 -245
  350. package/vendor/playwright-cli/node_modules/playwright-core/lib/utils/isomorphic/cssTokenizer.js +0 -1051
  351. package/vendor/playwright-cli/node_modules/playwright-core/lib/utils/isomorphic/formatUtils.js +0 -64
  352. package/vendor/playwright-cli/node_modules/playwright-core/lib/utils/isomorphic/headers.js +0 -53
  353. package/vendor/playwright-cli/node_modules/playwright-core/lib/utils/isomorphic/imageUtils.js +0 -141
  354. package/vendor/playwright-cli/node_modules/playwright-core/lib/utils/isomorphic/locatorGenerators.js +0 -689
  355. package/vendor/playwright-cli/node_modules/playwright-core/lib/utils/isomorphic/locatorParser.js +0 -176
  356. package/vendor/playwright-cli/node_modules/playwright-core/lib/utils/isomorphic/locatorUtils.js +0 -81
  357. package/vendor/playwright-cli/node_modules/playwright-core/lib/utils/isomorphic/lruCache.js +0 -51
  358. package/vendor/playwright-cli/node_modules/playwright-core/lib/utils/isomorphic/manualPromise.js +0 -114
  359. package/vendor/playwright-cli/node_modules/playwright-core/lib/utils/isomorphic/mimeType.js +0 -464
  360. package/vendor/playwright-cli/node_modules/playwright-core/lib/utils/isomorphic/multimap.js +0 -80
  361. package/vendor/playwright-cli/node_modules/playwright-core/lib/utils/isomorphic/protocolFormatter.js +0 -81
  362. package/vendor/playwright-cli/node_modules/playwright-core/lib/utils/isomorphic/protocolMetainfo.js +0 -342
  363. package/vendor/playwright-cli/node_modules/playwright-core/lib/utils/isomorphic/rtti.js +0 -43
  364. package/vendor/playwright-cli/node_modules/playwright-core/lib/utils/isomorphic/selectorParser.js +0 -386
  365. package/vendor/playwright-cli/node_modules/playwright-core/lib/utils/isomorphic/semaphore.js +0 -54
  366. package/vendor/playwright-cli/node_modules/playwright-core/lib/utils/isomorphic/stackTrace.js +0 -158
  367. package/vendor/playwright-cli/node_modules/playwright-core/lib/utils/isomorphic/stringUtils.js +0 -204
  368. package/vendor/playwright-cli/node_modules/playwright-core/lib/utils/isomorphic/time.js +0 -49
  369. package/vendor/playwright-cli/node_modules/playwright-core/lib/utils/isomorphic/timeoutRunner.js +0 -66
  370. package/vendor/playwright-cli/node_modules/playwright-core/lib/utils/isomorphic/trace/entries.js +0 -16
  371. package/vendor/playwright-cli/node_modules/playwright-core/lib/utils/isomorphic/trace/snapshotRenderer.js +0 -502
  372. package/vendor/playwright-cli/node_modules/playwright-core/lib/utils/isomorphic/trace/snapshotServer.js +0 -120
  373. package/vendor/playwright-cli/node_modules/playwright-core/lib/utils/isomorphic/trace/snapshotStorage.js +0 -89
  374. package/vendor/playwright-cli/node_modules/playwright-core/lib/utils/isomorphic/trace/traceLoader.js +0 -131
  375. package/vendor/playwright-cli/node_modules/playwright-core/lib/utils/isomorphic/trace/traceModel.js +0 -366
  376. package/vendor/playwright-cli/node_modules/playwright-core/lib/utils/isomorphic/trace/traceModernizer.js +0 -401
  377. package/vendor/playwright-cli/node_modules/playwright-core/lib/utils/isomorphic/trace/traceUtils.js +0 -58
  378. package/vendor/playwright-cli/node_modules/playwright-core/lib/utils/isomorphic/trace/versions/traceV3.js +0 -16
  379. package/vendor/playwright-cli/node_modules/playwright-core/lib/utils/isomorphic/trace/versions/traceV4.js +0 -16
  380. package/vendor/playwright-cli/node_modules/playwright-core/lib/utils/isomorphic/trace/versions/traceV5.js +0 -16
  381. package/vendor/playwright-cli/node_modules/playwright-core/lib/utils/isomorphic/trace/versions/traceV6.js +0 -16
  382. package/vendor/playwright-cli/node_modules/playwright-core/lib/utils/isomorphic/trace/versions/traceV7.js +0 -16
  383. package/vendor/playwright-cli/node_modules/playwright-core/lib/utils/isomorphic/trace/versions/traceV8.js +0 -16
  384. package/vendor/playwright-cli/node_modules/playwright-core/lib/utils/isomorphic/types.js +0 -16
  385. package/vendor/playwright-cli/node_modules/playwright-core/lib/utils/isomorphic/urlMatch.js +0 -243
  386. package/vendor/playwright-cli/node_modules/playwright-core/lib/utils/isomorphic/utilityScriptSerializers.js +0 -262
  387. package/vendor/playwright-cli/node_modules/playwright-core/lib/utils/isomorphic/yaml.js +0 -84
  388. package/vendor/playwright-cli/node_modules/playwright-core/lib/utils.js +0 -113
  389. package/vendor/playwright-cli/node_modules/playwright-core/lib/utilsBundleImpl/index.js +0 -218
  390. package/vendor/playwright-cli/node_modules/playwright-core/lib/vite/traceViewer/assets/codeMirrorModule-BtGnd8kr.js +0 -32
  391. package/vendor/playwright-cli/node_modules/playwright-core/lib/vite/traceViewer/assets/codeMirrorModule-CnvO0fko.js +0 -32
  392. package/vendor/playwright-cli/node_modules/playwright-core/lib/vite/traceViewer/assets/defaultSettingsView-BkMbME_o.js +0 -262
  393. package/vendor/playwright-cli/node_modules/playwright-core/lib/vite/traceViewer/assets/defaultSettingsView-CN3cwLGD.js +0 -262
  394. package/vendor/playwright-cli/node_modules/playwright-core/lib/vite/traceViewer/defaultSettingsView.B4dS75f0.css +0 -1
  395. package/vendor/playwright-cli/node_modules/playwright-core/lib/vite/traceViewer/defaultSettingsView.DcQiWcKS.css +0 -1
  396. package/vendor/playwright-cli/node_modules/playwright-core/lib/vite/traceViewer/index.B2ffe31o.js +0 -2
  397. package/vendor/playwright-cli/node_modules/playwright-core/lib/vite/traceViewer/index.Df3uWWXm.js +0 -2
  398. package/vendor/playwright-cli/node_modules/playwright-core/lib/vite/traceViewer/uiMode.BZQ54Kgt.css +0 -1
  399. package/vendor/playwright-cli/node_modules/playwright-core/lib/vite/traceViewer/uiMode.CmAqMvmy.js +0 -6
  400. package/vendor/playwright-cli/node_modules/playwright-core/lib/vite/traceViewer/uiMode.u9Eas4CP.js +0 -6
  401. package/vendor/playwright-cli/node_modules/playwright-core/lib/zipBundle.js +0 -34
  402. package/vendor/playwright-cli/node_modules/playwright-core/lib/zipBundleImpl.js +0 -5
package/rechrome.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env bun
2
+ import { prepareStdinUpload, type UploadPayload } from "./scoped-upload.ts";
2
3
  import { readListeners, writeListeners, listenerAddress, isLoopback, normalizePrefix, serviceUrl, allowProfiles, denyProfiles, rotateListenerKey, setPublicUrl, canonicalProfileKeys, planProfileRemoval, type Listener } from "./listeners.ts";
3
4
 
4
5
  import { file } from "bun";
@@ -827,18 +828,53 @@ const CHROME_LOCAL_STATE_PATHS = () => {
827
828
 
828
829
  type ChromeProfileInfo = { user_name?: string; name?: string };
829
830
 
831
+ /**
832
+ * macOS privacy (TCC) blocks a process launched by launchd/oxmgr from Chrome's data folder unless
833
+ * its binary has Full Disk Access; a Terminal or agent session inherits the grant. Turn that EPERM
834
+ * into the fix. Undefined for any other error (or platform).
835
+ */
836
+ export function chromeDataAccessHint(error: unknown, execPath = process.execPath, platform = process.platform): string | undefined {
837
+ const code = (error as { code?: string } | null)?.code;
838
+ const message = error instanceof Error ? error.message : String(error);
839
+ if (platform !== "darwin" || !(code === "EPERM" || code === "EACCES" || /EPERM|operation not permitted/i.test(message))) return undefined;
840
+ return `macOS privacy settings (TCC) block ${execPath} from reading Chrome's profile folder. ` +
841
+ `Grant it Full Disk Access: System Settings → Privacy & Security → Full Disk Access → +, press ⌘⇧G, paste ${execPath}, ` +
842
+ `then restart rech serve. Or run rech serve from Terminal, which already has access (see docs/macos-daemon.md).`;
843
+ }
844
+
845
+ /** Why the last readChromeProfileCache() returned null (undefined when it succeeded). */
846
+ let profileCacheProblem: string | undefined;
847
+
830
848
  export async function readChromeProfileCache(): Promise<Record<string, ChromeProfileInfo> | null> {
849
+ profileCacheProblem = undefined;
850
+ const problems: string[] = [];
831
851
  for (const statePath of CHROME_LOCAL_STATE_PATHS()) {
832
852
  const f = file(statePath);
833
853
  if (!(await f.exists())) continue;
834
854
  try {
835
855
  const data = JSON.parse(await f.text());
836
- return data?.profile?.info_cache ?? null;
837
- } catch {}
856
+ if (data?.profile?.info_cache) return data.profile.info_cache;
857
+ problems.push(`${statePath} has no profile list`);
858
+ } catch (error) {
859
+ const hint = chromeDataAccessHint(error);
860
+ problems.push(`${statePath} is unreadable (${error instanceof Error ? error.message : String(error)})${hint ? `. ${hint}` : ""}`);
861
+ }
838
862
  }
863
+ profileCacheProblem = problems.join("; ") || "Chrome's Local State file was not found";
839
864
  return null;
840
865
  }
841
866
 
867
+ /**
868
+ * Say so (once per process) when profile emails/names are unavailable, so a bare folder name
869
+ * like "Profile 1" is never mistaken for the whole story.
870
+ */
871
+ let warnedProfileCache = false;
872
+ export function warnIfProfileNamesUnavailable(cache: Record<string, ChromeProfileInfo> | null): void {
873
+ if (cache || warnedProfileCache) return;
874
+ warnedProfileCache = true;
875
+ console.error(`[rech] Chrome profile emails and names are unavailable (${profileCacheProblem ?? "Local State not read"}); profiles are shown by folder name only.`);
876
+ }
877
+
842
878
  export function resolveChromeProfileSelector(
843
879
  profiles: Array<[string, ChromeProfileInfo]>,
844
880
  selector: string,
@@ -1306,6 +1342,7 @@ async function listRemoteProfiles(url: string): Promise<void> {
1306
1342
 
1307
1343
  async function listProfiles(): Promise<void> {
1308
1344
  const [cache, registry, root] = await Promise.all([readChromeProfileCache(), readTokenRegistry(), findChromeUserDataDir()]);
1345
+ warnIfProfileNamesUnavailable(cache);
1309
1346
  const profiles = buildProfileRows(cache, registry, root);
1310
1347
  const listeners = await readListeners();
1311
1348
  const url = process.env[ENV_KEY];
@@ -1405,7 +1442,7 @@ export function registeredProfileChoices(registry: Record<string, TokenEntry>, c
1405
1442
  const info = !userDataDir || defaultDirs.includes(userDataDir) ? cache?.[dir] : undefined;
1406
1443
  const names = [info?.name, info?.user_name, key].filter((n): n is string => !!n && n !== dir);
1407
1444
  const shown = [...new Set(names)];
1408
- return { label: shown.length ? `${shown.join(" · ")} [${dir}]` : dir, value: key };
1445
+ return { label: shown.length ? `${shown.join(" · ")} [${dir}]` : `${dir} (no email or name known)`, value: key };
1409
1446
  });
1410
1447
  }
1411
1448
 
@@ -1639,6 +1676,7 @@ async function printProfileUri(selector?: string, listener?: string, opts: { loc
1639
1676
  const interactive = isInteractive();
1640
1677
  const registry = await readTokenRegistry();
1641
1678
  const cache = await readChromeProfileCache();
1679
+ warnIfProfileNamesUnavailable(cache);
1642
1680
  const cancelled = () => new Error("Cancelled; nothing shared.");
1643
1681
  let config = await readListeners();
1644
1682
  const current = resolveEffectiveProfile(url ? parseUrl(url).profileDirectory : undefined);
@@ -1808,6 +1846,7 @@ async function callServe(
1808
1846
  overrideEnv?: Record<string, string>,
1809
1847
  precomputedIdentity?: { key: string; label: string; profile?: string },
1810
1848
  throwOnFailure = false,
1849
+ upload?: UploadPayload,
1811
1850
  ): Promise<{ status: number; stdout: string; stderr: string; files?: string[]; existingSession?: boolean }> {
1812
1851
  const { key, host, port, protocol, extensionId, extensionToken, profileDirectory, userDataDir, loadExtension } = parseUrl(url);
1813
1852
  // Reuse the caller's identity when provided — computing it shells out to `git` several times,
@@ -1826,7 +1865,7 @@ async function callServe(
1826
1865
  method: "POST",
1827
1866
  headers: { "Content-Type": "application/json", Authorization: `Bearer ${key}` },
1828
1867
  // dataDir is a client-local path; the daemon (possibly remote) only needs the session identity.
1829
- body: JSON.stringify({ args, identity: { key: identity.key, label: identity.label, profile: identity.profile }, env }),
1868
+ body: JSON.stringify({ args, identity: { key: identity.key, label: identity.label, profile: identity.profile }, env, ...(upload ? { upload } : {}) }),
1830
1869
  signal: AbortSignal.timeout(70_000),
1831
1870
  }).catch(async (e) => {
1832
1871
  if (throwOnFailure) throw new Error("Cannot reach the rechrome daemon. Check that it is running.");
@@ -1997,7 +2036,16 @@ export function unknownCommandHint(output: string, rechCommands: Iterable<string
1997
2036
  ].join("\n");
1998
2037
  }
1999
2038
 
2000
- async function run(url: string, args: string[], overrideEnv?: Record<string, string>, opts: { verbatim?: boolean } = {}) {
2039
+ /**
2040
+ * An `open` whose extension bridge never connected. Typical right after Chrome restarts: the
2041
+ * relay's connect page reaches no live worker, yet a fresh bridge moments later connects at once
2042
+ * (seen 2026-10-17: a timeout, then `rech setup`'s probe connected in 0.1s). Worth one retry.
2043
+ */
2044
+ export function isBridgeTimeout(args: string[], result: { status: number; stderr?: string }): boolean {
2045
+ return args.find(a => !a.startsWith("-")) === "open" && result.status !== 0 && /Extension connection timeout/i.test(result.stderr ?? "");
2046
+ }
2047
+
2048
+ async function run(url: string, args: string[], overrideEnv?: Record<string, string>, opts: { verbatim?: boolean; bridgeRetried?: boolean } = {}) {
2001
2049
  // Match the underlying CLI's command names while accepting the short forms humans
2002
2050
  // naturally try. Keep this client-side so old and new serve daemons behave alike.
2003
2051
  args = normalizeCommandArgs(args);
@@ -2012,7 +2060,19 @@ async function run(url: string, args: string[], overrideEnv?: Record<string, str
2012
2060
 
2013
2061
  const resolvedEnv = await getClientEnv({ extensionId, extensionToken, profileDirectory: effectiveProfile, userDataDir, loadExtension });
2014
2062
  const effectiveEnv = { ...resolvedEnv, ...overrideEnv };
2015
- const { status, stdout, stderr, files, existingSession } = await callServe(url, args, overrideEnv, identity);
2063
+ let upload: UploadPayload | undefined;
2064
+ if (args.find(a => !/^-s=[a-zA-Z0-9_-]{1,64}$/.test(a)) === "upload") {
2065
+ if (process.stdin.isTTY) throw new Error("upload reads stdin; redirect a PNG/SVG file with < icon.png");
2066
+ ({ args, upload } = await prepareStdinUpload(args, process.stdin));
2067
+ }
2068
+ const { status, stdout, stderr, files, existingSession } = await callServe(url, args, overrideEnv, identity, false, upload);
2069
+ if (!opts.bridgeRetried && isBridgeTimeout(args, { status, stderr })) {
2070
+ // Close the failed session so the retry gets a fresh cliDaemon and relay. callServe re-reads
2071
+ // the extension's live token from the profile, so a re-minted token heals here too.
2072
+ console.error(`[rech] the Chrome extension bridge did not answer (common right after Chrome restarts); retrying once with a fresh connection…`);
2073
+ await callServe(url, [...args.filter(a => /^-s=/.test(a)), "close"], overrideEnv, identity).catch(() => {});
2074
+ return run(url, args, overrideEnv, { ...opts, bridgeRetried: true });
2075
+ }
2016
2076
 
2017
2077
  const isOpenWithUrl = args[0] === "open" && args.length > 1;
2018
2078
  if (existingSession && isOpenWithUrl) {
@@ -2032,9 +2092,12 @@ async function run(url: string, args: string[], overrideEnv?: Record<string, str
2032
2092
  // The daemon resolves registered profiles' bridge tokens itself and then asks for a reload;
2033
2093
  // only blame a missing install when neither side had credentials.
2034
2094
  const hasToken = !!effectiveEnv["PLAYWRIGHT_MCP_EXTENSION_TOKEN"] || /reload the .*extension/i.test(stderr);
2095
+ const profileArg = displayProfile ? ` --profile ${JSON.stringify(displayProfile)}` : "";
2035
2096
  const last = hasToken
2036
- ? ` -x: extension did not connect (reload it at chrome://extensions; then verify its token) -> extension[degraded]`
2037
- : ` -> extension[not installed] (run: rech setup)`;
2097
+ ? ` -x: extension did not connect${opts.bridgeRetried ? " (also after an automatic retry)" : ""} -> extension[degraded]\n` +
2098
+ `[rech] reload "Playwright MCP Bridge" at chrome://extensions${displayProfile ? ` in ${displayProfile}'s window` : ""}, then retry; ` +
2099
+ `or run \`rech setup${profileArg}\`, which re-detects the extension and token and verifies the connection.`
2100
+ : ` -> extension[not installed] (run: rech setup${profileArg})`;
2038
2101
  console.error(`[rech] rech-client -> rech-server[ok] -> playwright[ok]\n${last}`);
2039
2102
  }
2040
2103
  if (stderr.includes("Browser '") && stderr.includes("is not open")) {
@@ -2069,6 +2132,26 @@ async function run(url: string, args: string[], overrideEnv?: Record<string, str
2069
2132
  process.exit(status);
2070
2133
  }
2071
2134
 
2135
+ /** The daemon's Playwright CLI predates `open --wait` (rechrome <= 1.35.1 bundled one). */
2136
+ export function cliRejectsWaitOption(output: string): boolean {
2137
+ return /Unknown options?:?[^\n]*?['"`]?--wait\b/i.test(output);
2138
+ }
2139
+
2140
+ /**
2141
+ * setup's bridge probe: open about:blank without waiting for a load. The daemon owns the CLI and
2142
+ * may be older than this client, so feature-check by behavior: if the CLI rejects `--wait`, probe
2143
+ * again without it rather than reporting a broken bridge.
2144
+ */
2145
+ export async function probeBridgeOpen<T extends { status: number; stdout: string; stderr: string }>(
2146
+ call: (args: string[]) => Promise<T>,
2147
+ note: (message: string) => void = () => {},
2148
+ ): Promise<T> {
2149
+ const probe = await call(["open", "about:blank", "--wait", "none"]);
2150
+ if (probe.status === 0 || !cliRejectsWaitOption(`${probe.stderr}\n${probe.stdout}`)) return probe;
2151
+ note("The daemon's Playwright CLI does not support `open --wait`; probing without it (update rechrome on the daemon host).");
2152
+ return call(["open", "about:blank"]);
2153
+ }
2154
+
2072
2155
  export type SetupPhase = "extension" | "token" | "bridge" | "error" | "save" | "ready";
2073
2156
 
2074
2157
  export function createSetupGuide(extDistDir: string, profileDisplay: string) {
@@ -2529,6 +2612,7 @@ export async function daemonInstall(serveUrl: string): Promise<void> {
2529
2612
  [ENV_KEY]: serveUrl,
2530
2613
  PWMCP_TEST_CONNECTION_TIMEOUT: process.env.PWMCP_TEST_CONNECTION_TIMEOUT || "30000",
2531
2614
  PLAYWRIGHT_CLI: resolvedPlaywrightCli,
2615
+ RECH_SERVE_MANAGED: "1", // the manager restarts it; never idle-self-exit (see serve.ts)
2532
2616
  };
2533
2617
  if (process.env.RECH_HOST) daemonEnv.RECH_HOST = process.env.RECH_HOST;
2534
2618
  if (isReadable(process.env.RECH_TLS_CERT)) daemonEnv.RECH_TLS_CERT = process.env.RECH_TLS_CERT!;
@@ -3287,7 +3371,7 @@ async function setup(opts: SetupOptions = {}): Promise<void> {
3287
3371
  console.log(`✓ [1/5] Local management daemon verified; requested profile access: ${desiredBind}`);
3288
3372
 
3289
3373
  const cache = await readChromeProfileCache();
3290
- if (!cache) { console.error(" Chrome profiles not found"); rl?.close(); process.exit(1); }
3374
+ if (!cache) { console.error(` Chrome profiles not found: ${profileCacheProblem ?? "Local State not read"}`); rl?.close(); process.exit(1); }
3291
3375
  const userDataDir = await findChromeUserDataDir();
3292
3376
 
3293
3377
  async function pickProfile(exclude: Set<string>): Promise<[string, ChromeProfileInfo] | null> {
@@ -3413,12 +3497,9 @@ async function setup(opts: SetupOptions = {}): Promise<void> {
3413
3497
  guide?.takeRetry();
3414
3498
  guide?.update("bridge", "Extension and token detected. Testing the browser connection…");
3415
3499
  try {
3416
- const probe = await callServe(
3417
- rechUrl.toString(),
3418
- [`-s=${probeSession}`, "open", "about:blank", "--wait", "none"],
3419
- probeEnv,
3420
- probeIdentity,
3421
- true,
3500
+ const probe = await probeBridgeOpen(
3501
+ args => callServe(rechUrl.toString(), [`-s=${probeSession}`, ...args], probeEnv, probeIdentity, true),
3502
+ note => console.log(` ${note}`),
3422
3503
  );
3423
3504
  bridgeVerified = probe.status === 0;
3424
3505
  if (bridgeVerified) {
@@ -3574,7 +3655,7 @@ async function status(): Promise<void> {
3574
3655
  ? await fetch(serviceUrl(url, "ping"), { headers: { Authorization: `Bearer ${parsed.key}` }, signal: AbortSignal.timeout(2000) }).catch(() => null)
3575
3656
  : null;
3576
3657
  const pingBody = pingResponse?.ok
3577
- ? await pingResponse.json().catch(() => null) as { bind?: string; listener?: string; profiles?: string[] | "*"; degraded?: boolean; consecutiveTimeouts?: number } | null
3658
+ ? await pingResponse.json().catch(() => null) as { bind?: string; listener?: string; profiles?: string[] | "*"; degraded?: boolean; consecutiveTimeouts?: number; chromeAccessProblem?: string } | null
3578
3659
  : null;
3579
3660
  // Show the URL this client connects to; through a proxy, the daemon's bind is on another port.
3580
3661
  const details = [pingBody?.listener && `listener ${pingBody.listener}`, pingBody?.bind && `bind ${pingBody.bind}`].filter(Boolean).join(", ");
@@ -3595,6 +3676,8 @@ async function status(): Promise<void> {
3595
3676
  // No oxmgr/pm2 on PATH must not take down `rech status`: report it instead of throwing.
3596
3677
  let mgr: DaemonManager | undefined;
3597
3678
  if (isHost) try { mgr = daemonManager(); } catch { /* reported below */ }
3679
+ if (pingBody?.chromeAccessProblem)
3680
+ console.log(`chrome: ⚠ daemon ${pingBody.chromeAccessProblem}`);
3598
3681
  if (pingBody?.degraded)
3599
3682
  console.log(`relay: ⚠ degraded (${pingBody.consecutiveTimeouts} consecutive command timeouts) — if it persists, the daemon self-restarts; ${isHost ? `force it now with \`${mgr?.id ?? "oxmgr"} restart ${PM_PROCESS_NAME}\`` : "the daemon host can restart it"}`);
3600
3683
  if (isHost) {
@@ -3658,6 +3741,7 @@ const HELP_EPILOGUE = `Browser commands (sent to this project's Chrome session):
3658
3741
 
3659
3742
  Environment:
3660
3743
  ${ENV_KEY} connection URL; read from the nearest .rechrome/.env.local or .env.local
3744
+ RECHROME_PROFILE default browser profile selector; --profile overrides it
3661
3745
  RECH_IDENTITY session key: worktree (default) | branch | cwd
3662
3746
  RECH_TOKEN extension token for \`rech setup\` (same as --token)
3663
3747
  RECH_SETUP_AGENT setup hints: codex | claude | none (auto-detected)
@@ -3848,7 +3932,7 @@ if (import.meta.main) {
3848
3932
  if (separator !== -1) args = args.slice(0, separator);
3849
3933
  try {
3850
3934
  const extracted = extractGlobalProfileArg(args);
3851
- profileSelector = extracted.selector;
3935
+ profileSelector = extracted.selector ?? (process.env.RECHROME_PROFILE?.trim() || undefined);
3852
3936
  args = extracted.args;
3853
3937
  } catch (err) {
3854
3938
  console.error(err instanceof Error ? err.message : String(err));
@@ -0,0 +1,165 @@
1
+ // @bun
2
+ // scoped-upload.ts
3
+ import { createHash, randomBytes } from "crypto";
4
+ import { mkdtemp, writeFile, rm } from "fs/promises";
5
+ import { join } from "path";
6
+ import { tmpdir } from "os";
7
+ var MAX_UPLOAD_BYTES = 2 * 1024 * 1024;
8
+ var MAX_REQUEST_BYTES = 3 * 1024 * 1024;
9
+ var UPLOAD_TYPES = ["image/png", "image/svg+xml"];
10
+ function validateUploadPolicy(value) {
11
+ const p = value;
12
+ if (!p || typeof p !== "object" || Array.isArray(p) || Object.keys(p).some((k) => !["maxBytes", "contentTypes"].includes(k)) || p.maxBytes !== undefined && (!Number.isSafeInteger(p.maxBytes) || p.maxBytes < 1 || p.maxBytes > MAX_UPLOAD_BYTES) || p.contentTypes !== undefined && (!Array.isArray(p.contentTypes) || !p.contentTypes.length || p.contentTypes.some((t) => !UPLOAD_TYPES.includes(t))))
13
+ throw new Error("uploads must be an object with optional maxBytes (1..2097152) and contentTypes (image/png, image/svg+xml)");
14
+ }
15
+ function validName(name) {
16
+ return typeof name === "string" && name.length > 0 && name.length <= 128 && name !== "." && name !== ".." && !name.startsWith("-") && !/[\\/:\x00-\x1f\x7f]/.test(name);
17
+ }
18
+ function matchesType(bytes, type) {
19
+ if (type === "image/png")
20
+ return bytes.length >= 33 && bytes.subarray(0, 8).equals(Buffer.from([137, 80, 78, 71, 13, 10, 26, 10])) && bytes.readUInt32BE(8) === 13 && bytes.toString("ascii", 12, 16) === "IHDR";
21
+ if (type === "image/svg+xml") {
22
+ let text;
23
+ try {
24
+ text = new TextDecoder("utf-8", { fatal: true }).decode(bytes);
25
+ } catch {
26
+ return false;
27
+ }
28
+ if (/<!DOCTYPE|<!ENTITY/i.test(text))
29
+ return false;
30
+ text = text.trim().replace(/^<\?xml\s[^?]*\?>\s*/, "").replace(/^(?:<!--[\s\S]*?-->\s*)+/, "");
31
+ return /^<svg(?:\s|\/?>)/.test(text) && /(?:<\/svg\s*>|\/>)\s*$/.test(text);
32
+ }
33
+ return false;
34
+ }
35
+ async function prepareStdinUpload(args, input) {
36
+ const sessions = args.filter((a) => /^-s=[a-zA-Z0-9_-]{1,64}$/.test(a));
37
+ const options = args.filter((a) => !sessions.includes(a));
38
+ if (options.shift() !== "upload")
39
+ throw new Error("Expected upload command");
40
+ const fields = {};
41
+ while (options.length) {
42
+ const option = options.shift();
43
+ const match = option.match(/^--(name|content-type)(?:=(.*))?$/);
44
+ if (!match || fields[match[1]] !== undefined)
45
+ throw new Error("Usage: rech upload --name icon.png [--content-type image/png] < icon.png (stdin only; no path argument)");
46
+ const value = match[2] ?? options.shift();
47
+ if (!value || value.startsWith("--"))
48
+ throw new Error(`Missing value for --${match[1]}`);
49
+ fields[match[1]] = value;
50
+ }
51
+ if (!validName(fields.name))
52
+ throw new Error("upload requires --name with a plain filename (no path)");
53
+ const contentType = fields["content-type"] ?? (fields.name.toLowerCase().endsWith(".png") ? "image/png" : fields.name.toLowerCase().endsWith(".svg") ? "image/svg+xml" : "");
54
+ if (!UPLOAD_TYPES.includes(contentType))
55
+ throw new Error("Upload content type must be image/png or image/svg+xml");
56
+ const chunks = [];
57
+ let size = 0;
58
+ for await (const chunk of input) {
59
+ size += chunk.byteLength;
60
+ if (size > MAX_UPLOAD_BYTES)
61
+ throw new Error("Upload exceeds 2 MiB");
62
+ chunks.push(Buffer.from(chunk));
63
+ }
64
+ const bytes = Buffer.concat(chunks);
65
+ if (!matchesType(bytes, contentType))
66
+ throw new Error("Upload bytes do not match the content type (PNG or UTF-8 SVG without DTD/entities required)");
67
+ return { args: ["upload", ...sessions], upload: { name: fields.name, contentType, data: bytes.toString("base64") } };
68
+ }
69
+ function currentPageOrigin(output) {
70
+ const current = output.split(`
71
+ `).filter((line) => /^- \d+: \(current\) /.test(line));
72
+ const url = current.length === 1 ? current[0].match(/\]\((.*)\)(?: \[crashed\])?$/)?.[1] : undefined;
73
+ if (!url)
74
+ throw new Error("Could not determine the upload page origin");
75
+ const parsed = new URL(url);
76
+ if (!["http:", "https:"].includes(parsed.protocol))
77
+ throw new Error("Uploads require an HTTP(S) page");
78
+ return parsed.origin;
79
+ }
80
+ async function receiveUpload(options) {
81
+ const record = { name: null, size: null, sha256: null, origin: null, result: "rejected" };
82
+ let dir;
83
+ try {
84
+ const p = options.payload;
85
+ if (validName(p?.name))
86
+ record.name = p.name;
87
+ if (options.policy === undefined)
88
+ throw new Error("Uploads are disabled on this listener");
89
+ validateUploadPolicy(options.policy);
90
+ if (options.args.length !== 1 || options.args[0] !== "upload")
91
+ throw new Error("Upload takes stdin bytes, not host paths or CLI options");
92
+ if (!p || !validName(p.name) || typeof p.contentType !== "string" || typeof p.data !== "string" || Object.keys(p).some((k) => !["name", "contentType", "data"].includes(k)))
93
+ throw new Error("Invalid upload payload");
94
+ const limit = options.policy.maxBytes ?? MAX_UPLOAD_BYTES;
95
+ if (p.data.length > 4 * Math.ceil(limit / 3) || /[^A-Za-z0-9+/=]/.test(p.data))
96
+ throw new Error("Upload exceeds maxBytes or has invalid base64");
97
+ const bytes = Buffer.from(p.data, "base64");
98
+ record.size = bytes.length;
99
+ record.sha256 = createHash("sha256").update(bytes).digest("hex");
100
+ if (!bytes.length || bytes.length > limit || bytes.toString("base64") !== p.data)
101
+ throw new Error("Upload is empty, exceeds maxBytes, or is not canonical base64");
102
+ if (!(options.policy.contentTypes ?? UPLOAD_TYPES).includes(p.contentType) || !matchesType(bytes, p.contentType))
103
+ throw new Error("Upload content type is not allowed or does not match the bytes");
104
+ const tabs = await options.run(["tab-list"]);
105
+ if (tabs.status !== 0)
106
+ throw new Error("Could not inspect the upload page");
107
+ record.origin = currentPageOrigin(tabs.stdout);
108
+ dir = await mkdtemp(join(tmpdir(), "rech-upload-"));
109
+ const path = join(dir, randomBytes(16).toString("hex") + (p.contentType === "image/png" ? ".png" : ".svg"));
110
+ await writeFile(path, bytes, { mode: 384, flag: "wx" });
111
+ record.result = "failed";
112
+ const result = await options.run(["upload", path]);
113
+ record.result = result.status === 0 && !/^### Error\b/m.test(result.stdout) ? "completed" : "failed";
114
+ return {
115
+ ...result,
116
+ status: record.result === "completed" ? 0 : 1,
117
+ stdout: result.stdout.replaceAll(path, p.name),
118
+ stderr: result.stderr.replaceAll(path, p.name)
119
+ };
120
+ } catch (error) {
121
+ return { status: 1, stdout: "", stderr: (error instanceof Error ? error.message : "Upload failed") + `
122
+ ` };
123
+ } finally {
124
+ try {
125
+ if (dir)
126
+ await rm(dir, { recursive: true, force: true });
127
+ } finally {
128
+ options.audit(record);
129
+ }
130
+ }
131
+ }
132
+ async function readRequestJson(req) {
133
+ const reader = req.body?.getReader();
134
+ if (!reader)
135
+ throw new Error("Empty request");
136
+ const chunks = [];
137
+ let size = 0;
138
+ try {
139
+ for (;; ) {
140
+ const { done, value } = await reader.read();
141
+ if (done)
142
+ break;
143
+ size += value.byteLength;
144
+ if (size > MAX_REQUEST_BYTES)
145
+ throw new Error("Request exceeds 3 MiB");
146
+ chunks.push(value);
147
+ }
148
+ } catch (error) {
149
+ await reader.cancel().catch(() => {});
150
+ throw error;
151
+ } finally {
152
+ reader.releaseLock();
153
+ }
154
+ return JSON.parse(Buffer.concat(chunks).toString("utf8"));
155
+ }
156
+ export {
157
+ MAX_REQUEST_BYTES,
158
+ MAX_UPLOAD_BYTES,
159
+ UPLOAD_TYPES,
160
+ currentPageOrigin,
161
+ prepareStdinUpload,
162
+ readRequestJson,
163
+ receiveUpload,
164
+ validateUploadPolicy
165
+ };
@@ -0,0 +1,140 @@
1
+ import { createHash, randomBytes } from 'node:crypto';
2
+ import { mkdtemp, writeFile, rm } from 'node:fs/promises';
3
+ import { join } from 'node:path';
4
+ import { tmpdir } from 'node:os';
5
+
6
+ export const MAX_UPLOAD_BYTES = 2 * 1024 * 1024;
7
+ // Base64 plus metadata. Bound JSON input before parsing, not just decoded bytes.
8
+ export const MAX_REQUEST_BYTES = 3 * 1024 * 1024;
9
+ export const UPLOAD_TYPES = ['image/png', 'image/svg+xml'] as const;
10
+ export type UploadPolicy = { maxBytes?: number; contentTypes?: string[] };
11
+ export type UploadPayload = { name: string; contentType: string; data: string };
12
+ export type UploadResult = { status: number; stdout: string; stderr: string };
13
+ export type UploadAudit = { name: string | null; size: number | null; sha256: string | null; origin: string | null; result: string };
14
+
15
+ export function validateUploadPolicy(value: unknown): asserts value is UploadPolicy {
16
+ const p = value as UploadPolicy;
17
+ if (!p || typeof p !== 'object' || Array.isArray(p) || Object.keys(p).some(k => !['maxBytes', 'contentTypes'].includes(k))
18
+ || (p.maxBytes !== undefined && (!Number.isSafeInteger(p.maxBytes) || p.maxBytes < 1 || p.maxBytes > MAX_UPLOAD_BYTES))
19
+ || (p.contentTypes !== undefined && (!Array.isArray(p.contentTypes) || !p.contentTypes.length || p.contentTypes.some(t => !UPLOAD_TYPES.includes(t as any)))))
20
+ throw new Error('uploads must be an object with optional maxBytes (1..2097152) and contentTypes (image/png, image/svg+xml)');
21
+ }
22
+
23
+ function validName(name: unknown): name is string {
24
+ return typeof name === 'string' && name.length > 0 && name.length <= 128
25
+ && name !== '.' && name !== '..' && !name.startsWith('-') && !/[\\/:\x00-\x1f\x7f]/.test(name);
26
+ }
27
+
28
+ function matchesType(bytes: Buffer, type: string): boolean {
29
+ if (type === 'image/png') return bytes.length >= 33 && bytes.subarray(0, 8).equals(Buffer.from([137,80,78,71,13,10,26,10]))
30
+ && bytes.readUInt32BE(8) === 13 && bytes.toString('ascii', 12, 16) === 'IHDR';
31
+ if (type === 'image/svg+xml') {
32
+ let text: string;
33
+ try { text = new TextDecoder('utf-8', { fatal: true }).decode(bytes); } catch { return false; }
34
+ // Sniff only; never parse/render SVG or resolve XML entities on the host.
35
+ if (/<!DOCTYPE|<!ENTITY/i.test(text)) return false;
36
+ text = text.trim().replace(/^<\?xml\s[^?]*\?>\s*/, '').replace(/^(?:<!--[\s\S]*?-->\s*)+/, '');
37
+ return /^<svg(?:\s|\/?>)/.test(text) && /(?:<\/svg\s*>|\/>)\s*$/.test(text);
38
+ }
39
+ return false;
40
+ }
41
+
42
+ export async function prepareStdinUpload(args: string[], input: AsyncIterable<Uint8Array>): Promise<{ args: string[]; upload: UploadPayload }> {
43
+ const sessions = args.filter(a => /^-s=[a-zA-Z0-9_-]{1,64}$/.test(a));
44
+ const options = args.filter(a => !sessions.includes(a));
45
+ if (options.shift() !== 'upload') throw new Error('Expected upload command');
46
+ const fields: Record<string, string> = {};
47
+ while (options.length) {
48
+ const option = options.shift()!;
49
+ const match = option.match(/^--(name|content-type)(?:=(.*))?$/);
50
+ if (!match || fields[match[1]] !== undefined) throw new Error('Usage: rech upload --name icon.png [--content-type image/png] < icon.png (stdin only; no path argument)');
51
+ const value = match[2] ?? options.shift();
52
+ if (!value || value.startsWith('--')) throw new Error(`Missing value for --${match[1]}`);
53
+ fields[match[1]] = value;
54
+ }
55
+ if (!validName(fields.name)) throw new Error('upload requires --name with a plain filename (no path)');
56
+ const contentType = fields['content-type'] ?? (fields.name.toLowerCase().endsWith('.png') ? 'image/png' : fields.name.toLowerCase().endsWith('.svg') ? 'image/svg+xml' : '');
57
+ if (!UPLOAD_TYPES.includes(contentType as any)) throw new Error('Upload content type must be image/png or image/svg+xml');
58
+ const chunks: Buffer[] = [];
59
+ let size = 0;
60
+ for await (const chunk of input) {
61
+ size += chunk.byteLength;
62
+ if (size > MAX_UPLOAD_BYTES) throw new Error('Upload exceeds 2 MiB');
63
+ chunks.push(Buffer.from(chunk));
64
+ }
65
+ const bytes = Buffer.concat(chunks);
66
+ if (!matchesType(bytes, contentType)) throw new Error('Upload bytes do not match the content type (PNG or UTF-8 SVG without DTD/entities required)');
67
+ return { args: ['upload', ...sessions], upload: { name: fields.name, contentType, data: bytes.toString('base64') } };
68
+ }
69
+
70
+ export function currentPageOrigin(output: string): string {
71
+ const current = output.split('\n').filter(line => /^- \d+: \(current\) /.test(line));
72
+ const url = current.length === 1 ? current[0].match(/\]\((.*)\)(?: \[crashed\])?$/)?.[1] : undefined;
73
+ if (!url) throw new Error('Could not determine the upload page origin');
74
+ const parsed = new URL(url);
75
+ if (!['http:', 'https:'].includes(parsed.protocol)) throw new Error('Uploads require an HTTP(S) page');
76
+ return parsed.origin;
77
+ }
78
+
79
+ /** No payload field is ever used as a host path. run() is a server-owned CLI runner,
80
+ * not caller-supplied code. Audit records the selected origin immediately before upload.
81
+ */
82
+ export async function receiveUpload(options: {
83
+ policy: UploadPolicy | undefined; payload: unknown; args: string[];
84
+ run: (args: string[]) => Promise<UploadResult>; audit: (event: UploadAudit) => void;
85
+ }): Promise<UploadResult> {
86
+ const record: UploadAudit = { name: null, size: null, sha256: null, origin: null, result: 'rejected' };
87
+ let dir: string | undefined;
88
+ try {
89
+ const p = options.payload as UploadPayload;
90
+ if (validName(p?.name)) record.name = p.name;
91
+ if (options.policy === undefined) throw new Error('Uploads are disabled on this listener');
92
+ validateUploadPolicy(options.policy);
93
+ if (options.args.length !== 1 || options.args[0] !== 'upload') throw new Error('Upload takes stdin bytes, not host paths or CLI options');
94
+ if (!p || !validName(p.name) || typeof p.contentType !== 'string' || typeof p.data !== 'string'
95
+ || Object.keys(p).some(k => !['name', 'contentType', 'data'].includes(k))) throw new Error('Invalid upload payload');
96
+ const limit = options.policy.maxBytes ?? MAX_UPLOAD_BYTES;
97
+ if (p.data.length > 4 * Math.ceil(limit / 3) || /[^A-Za-z0-9+/=]/.test(p.data))
98
+ throw new Error('Upload exceeds maxBytes or has invalid base64');
99
+ const bytes = Buffer.from(p.data, 'base64');
100
+ record.size = bytes.length;
101
+ record.sha256 = createHash('sha256').update(bytes).digest('hex');
102
+ if (!bytes.length || bytes.length > limit || bytes.toString('base64') !== p.data) throw new Error('Upload is empty, exceeds maxBytes, or is not canonical base64');
103
+ if (!(options.policy.contentTypes ?? UPLOAD_TYPES).includes(p.contentType) || !matchesType(bytes, p.contentType))
104
+ throw new Error('Upload content type is not allowed or does not match the bytes');
105
+ const tabs = await options.run(['tab-list']);
106
+ if (tabs.status !== 0) throw new Error('Could not inspect the upload page');
107
+ record.origin = currentPageOrigin(tabs.stdout);
108
+ dir = await mkdtemp(join(tmpdir(), 'rech-upload-')); // 0700; never served by /files
109
+ const path = join(dir, randomBytes(16).toString('hex') + (p.contentType === 'image/png' ? '.png' : '.svg'));
110
+ await writeFile(path, bytes, { mode: 0o600, flag: 'wx' });
111
+ record.result = 'failed';
112
+ const result = await options.run(['upload', path]);
113
+ record.result = result.status === 0 && !/^### Error\b/m.test(result.stdout) ? 'completed' : 'failed';
114
+ return { ...result, status: record.result === 'completed' ? 0 : 1,
115
+ stdout: result.stdout.replaceAll(path, p.name), stderr: result.stderr.replaceAll(path, p.name) };
116
+ } catch (error) {
117
+ return { status: 1, stdout: '', stderr: (error instanceof Error ? error.message : 'Upload failed') + '\n' };
118
+ } finally {
119
+ try { if (dir) await rm(dir, { recursive: true, force: true }); }
120
+ finally { options.audit(record); }
121
+ }
122
+ }
123
+
124
+ export async function readRequestJson(req: Request): Promise<any> {
125
+ const reader = req.body?.getReader();
126
+ if (!reader) throw new Error('Empty request');
127
+ const chunks: Uint8Array[] = [];
128
+ let size = 0;
129
+ try {
130
+ for (;;) {
131
+ const { done, value } = await reader.read();
132
+ if (done) break;
133
+ size += value.byteLength;
134
+ if (size > MAX_REQUEST_BYTES) throw new Error('Request exceeds 3 MiB');
135
+ chunks.push(value);
136
+ }
137
+ } catch (error) { await reader.cancel().catch(() => {}); throw error; }
138
+ finally { reader.releaseLock(); }
139
+ return JSON.parse(Buffer.concat(chunks).toString('utf8'));
140
+ }