rechrome 1.35.0 → 1.36.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +74 -0
- package/extension/lib/background.mjs +28 -1
- package/extension/lib/ui/connect.js +29 -19
- package/listeners.js +17 -1
- package/listeners.ts +7 -2
- package/package.json +5 -3
- package/rechrome.js +64 -16
- package/rechrome.ts +64 -16
- package/scoped-upload.js +165 -0
- package/scoped-upload.ts +140 -0
- package/serve.js +30 -2
- package/serve.ts +30 -2
- package/vendor/playwright-cli/node_modules/playwright-core/lib/coreBundle.js +360 -256
- package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/cli-client/help.json +9 -4
- package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/cli-client/program.js +6 -1
- package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/cli-client/session.js +10 -12
- package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/utils/extension.js +8 -5
- package/vendor/playwright-cli/node_modules/playwright-core/lib/androidServerImpl.js +0 -65
- package/vendor/playwright-cli/node_modules/playwright-core/lib/browserServerImpl.js +0 -120
- package/vendor/playwright-cli/node_modules/playwright-core/lib/cli/driver.js +0 -98
- package/vendor/playwright-cli/node_modules/playwright-core/lib/cli/program.js +0 -597
- package/vendor/playwright-cli/node_modules/playwright-core/lib/cli/programWithTestStub.js +0 -74
- package/vendor/playwright-cli/node_modules/playwright-core/lib/client/android.js +0 -361
- package/vendor/playwright-cli/node_modules/playwright-core/lib/client/api.js +0 -137
- package/vendor/playwright-cli/node_modules/playwright-core/lib/client/artifact.js +0 -79
- package/vendor/playwright-cli/node_modules/playwright-core/lib/client/browser.js +0 -169
- package/vendor/playwright-cli/node_modules/playwright-core/lib/client/browserContext.js +0 -583
- package/vendor/playwright-cli/node_modules/playwright-core/lib/client/browserType.js +0 -153
- package/vendor/playwright-cli/node_modules/playwright-core/lib/client/cdpSession.js +0 -55
- package/vendor/playwright-cli/node_modules/playwright-core/lib/client/channelOwner.js +0 -194
- package/vendor/playwright-cli/node_modules/playwright-core/lib/client/clientHelper.js +0 -64
- package/vendor/playwright-cli/node_modules/playwright-core/lib/client/clientInstrumentation.js +0 -55
- package/vendor/playwright-cli/node_modules/playwright-core/lib/client/clientStackTrace.js +0 -69
- package/vendor/playwright-cli/node_modules/playwright-core/lib/client/clock.js +0 -68
- package/vendor/playwright-cli/node_modules/playwright-core/lib/client/connect.js +0 -143
- package/vendor/playwright-cli/node_modules/playwright-core/lib/client/connection.js +0 -322
- package/vendor/playwright-cli/node_modules/playwright-core/lib/client/consoleMessage.js +0 -61
- package/vendor/playwright-cli/node_modules/playwright-core/lib/client/coverage.js +0 -44
- package/vendor/playwright-cli/node_modules/playwright-core/lib/client/debugger.js +0 -57
- package/vendor/playwright-cli/node_modules/playwright-core/lib/client/dialog.js +0 -56
- package/vendor/playwright-cli/node_modules/playwright-core/lib/client/disposable.js +0 -76
- package/vendor/playwright-cli/node_modules/playwright-core/lib/client/download.js +0 -62
- package/vendor/playwright-cli/node_modules/playwright-core/lib/client/electron.js +0 -138
- package/vendor/playwright-cli/node_modules/playwright-core/lib/client/elementHandle.js +0 -281
- package/vendor/playwright-cli/node_modules/playwright-core/lib/client/errors.js +0 -77
- package/vendor/playwright-cli/node_modules/playwright-core/lib/client/eventEmitter.js +0 -314
- package/vendor/playwright-cli/node_modules/playwright-core/lib/client/events.js +0 -103
- package/vendor/playwright-cli/node_modules/playwright-core/lib/client/fetch.js +0 -367
- package/vendor/playwright-cli/node_modules/playwright-core/lib/client/fileChooser.js +0 -46
- package/vendor/playwright-cli/node_modules/playwright-core/lib/client/fileUtils.js +0 -34
- package/vendor/playwright-cli/node_modules/playwright-core/lib/client/frame.js +0 -404
- package/vendor/playwright-cli/node_modules/playwright-core/lib/client/harRouter.js +0 -99
- package/vendor/playwright-cli/node_modules/playwright-core/lib/client/input.js +0 -84
- package/vendor/playwright-cli/node_modules/playwright-core/lib/client/jsHandle.js +0 -105
- package/vendor/playwright-cli/node_modules/playwright-core/lib/client/jsonPipe.js +0 -39
- package/vendor/playwright-cli/node_modules/playwright-core/lib/client/localUtils.js +0 -60
- package/vendor/playwright-cli/node_modules/playwright-core/lib/client/locator.js +0 -367
- package/vendor/playwright-cli/node_modules/playwright-core/lib/client/network.js +0 -750
- package/vendor/playwright-cli/node_modules/playwright-core/lib/client/page.js +0 -729
- package/vendor/playwright-cli/node_modules/playwright-core/lib/client/platform.js +0 -77
- package/vendor/playwright-cli/node_modules/playwright-core/lib/client/playwright.js +0 -71
- package/vendor/playwright-cli/node_modules/playwright-core/lib/client/screencast.js +0 -48
- package/vendor/playwright-cli/node_modules/playwright-core/lib/client/selectors.js +0 -57
- package/vendor/playwright-cli/node_modules/playwright-core/lib/client/stream.js +0 -39
- package/vendor/playwright-cli/node_modules/playwright-core/lib/client/timeoutSettings.js +0 -79
- package/vendor/playwright-cli/node_modules/playwright-core/lib/client/tracing.js +0 -126
- package/vendor/playwright-cli/node_modules/playwright-core/lib/client/types.js +0 -28
- package/vendor/playwright-cli/node_modules/playwright-core/lib/client/video.js +0 -68
- package/vendor/playwright-cli/node_modules/playwright-core/lib/client/waiter.js +0 -142
- package/vendor/playwright-cli/node_modules/playwright-core/lib/client/webError.js +0 -39
- package/vendor/playwright-cli/node_modules/playwright-core/lib/client/worker.js +0 -85
- package/vendor/playwright-cli/node_modules/playwright-core/lib/client/writableStream.js +0 -39
- package/vendor/playwright-cli/node_modules/playwright-core/lib/generated/bindingsControllerSource.js +0 -28
- package/vendor/playwright-cli/node_modules/playwright-core/lib/generated/clockSource.js +0 -28
- package/vendor/playwright-cli/node_modules/playwright-core/lib/generated/injectedScriptSource.js +0 -28
- package/vendor/playwright-cli/node_modules/playwright-core/lib/generated/pollingRecorderSource.js +0 -28
- package/vendor/playwright-cli/node_modules/playwright-core/lib/generated/storageScriptSource.js +0 -28
- package/vendor/playwright-cli/node_modules/playwright-core/lib/generated/utilityScriptSource.js +0 -28
- package/vendor/playwright-cli/node_modules/playwright-core/lib/generated/webSocketMockSource.js +0 -336
- package/vendor/playwright-cli/node_modules/playwright-core/lib/inProcessFactory.js +0 -60
- package/vendor/playwright-cli/node_modules/playwright-core/lib/inprocess.js +0 -3
- package/vendor/playwright-cli/node_modules/playwright-core/lib/mcpBundle.js +0 -81
- package/vendor/playwright-cli/node_modules/playwright-core/lib/mcpBundleImpl/index.js +0 -91
- package/vendor/playwright-cli/node_modules/playwright-core/lib/outofprocess.js +0 -76
- package/vendor/playwright-cli/node_modules/playwright-core/lib/protocol/serializers.js +0 -197
- package/vendor/playwright-cli/node_modules/playwright-core/lib/protocol/validator.js +0 -3034
- package/vendor/playwright-cli/node_modules/playwright-core/lib/protocol/validatorPrimitives.js +0 -193
- package/vendor/playwright-cli/node_modules/playwright-core/lib/remote/playwrightConnection.js +0 -131
- package/vendor/playwright-cli/node_modules/playwright-core/lib/remote/playwrightPipeServer.js +0 -100
- package/vendor/playwright-cli/node_modules/playwright-core/lib/remote/playwrightServer.js +0 -339
- package/vendor/playwright-cli/node_modules/playwright-core/lib/remote/playwrightWebSocketServer.js +0 -73
- package/vendor/playwright-cli/node_modules/playwright-core/lib/remote/serverTransport.js +0 -96
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/android/android.js +0 -465
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/android/backendAdb.js +0 -177
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/artifact.js +0 -127
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/bidi/bidiBrowser.js +0 -571
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/bidi/bidiChromium.js +0 -162
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/bidi/bidiConnection.js +0 -213
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/bidi/bidiDeserializer.js +0 -116
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/bidi/bidiExecutionContext.js +0 -267
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/bidi/bidiFirefox.js +0 -128
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/bidi/bidiInput.js +0 -146
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/bidi/bidiNetworkManager.js +0 -411
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/bidi/bidiOverCdp.js +0 -102
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/bidi/bidiPage.js +0 -599
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/bidi/bidiPdf.js +0 -106
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/bidi/third_party/bidiCommands.d.js +0 -22
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/bidi/third_party/bidiKeyboard.js +0 -256
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/bidi/third_party/bidiProtocol.js +0 -24
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/bidi/third_party/bidiProtocolCore.js +0 -180
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/bidi/third_party/bidiProtocolPermissions.js +0 -42
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/bidi/third_party/bidiSerializer.js +0 -148
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/bidi/third_party/firefoxPrefs.js +0 -261
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/browser.js +0 -223
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/browserContext.js +0 -703
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/browserType.js +0 -338
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/callLog.js +0 -82
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/chromium/chromium.js +0 -399
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/chromium/chromiumSwitches.js +0 -104
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/chromium/crBrowser.js +0 -532
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/chromium/crConnection.js +0 -197
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/chromium/crCoverage.js +0 -235
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/chromium/crDevTools.js +0 -111
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/chromium/crDragDrop.js +0 -131
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/chromium/crExecutionContext.js +0 -146
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/chromium/crInput.js +0 -187
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/chromium/crNetworkManager.js +0 -708
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/chromium/crPage.js +0 -1004
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/chromium/crPdf.js +0 -121
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/chromium/crProtocolHelper.js +0 -145
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/chromium/crServiceWorker.js +0 -137
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/chromium/defaultFontFamilies.js +0 -162
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/chromium/protocol.d.js +0 -16
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/clock.js +0 -149
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/codegen/csharp.js +0 -327
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/codegen/java.js +0 -274
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/codegen/javascript.js +0 -247
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/codegen/jsonl.js +0 -52
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/codegen/language.js +0 -132
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/codegen/languages.js +0 -68
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/codegen/python.js +0 -279
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/codegen/types.js +0 -16
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/console.js +0 -61
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/cookieStore.js +0 -206
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/debugController.js +0 -197
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/debugger.js +0 -120
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/deviceDescriptors.js +0 -39
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/dialog.js +0 -116
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/dispatchers/androidDispatcher.js +0 -325
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/dispatchers/artifactDispatcher.js +0 -118
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/dispatchers/browserContextDispatcher.js +0 -381
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/dispatchers/browserDispatcher.js +0 -124
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/dispatchers/browserTypeDispatcher.js +0 -71
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/dispatchers/cdpSessionDispatcher.js +0 -47
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/dispatchers/debugControllerDispatcher.js +0 -78
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/dispatchers/debuggerDispatcher.js +0 -80
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/dispatchers/dialogDispatcher.js +0 -47
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/dispatchers/dispatcher.js +0 -364
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/dispatchers/disposableDispatcher.js +0 -39
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/dispatchers/electronDispatcher.js +0 -90
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/dispatchers/elementHandlerDispatcher.js +0 -181
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/dispatchers/frameDispatcher.js +0 -227
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/dispatchers/jsHandleDispatcher.js +0 -85
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/dispatchers/jsonPipeDispatcher.js +0 -58
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/dispatchers/localUtilsDispatcher.js +0 -185
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/dispatchers/networkDispatchers.js +0 -214
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/dispatchers/pageDispatcher.js +0 -434
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/dispatchers/playwrightDispatcher.js +0 -108
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/dispatchers/streamDispatcher.js +0 -67
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/dispatchers/tracingDispatcher.js +0 -68
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/dispatchers/webSocketRouteDispatcher.js +0 -164
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/dispatchers/writableStreamDispatcher.js +0 -79
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/disposable.js +0 -41
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/dom.js +0 -823
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/download.js +0 -71
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/electron/electron.js +0 -272
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/electron/loader.js +0 -115
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/errors.js +0 -69
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/fetch.js +0 -621
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/fileChooser.js +0 -43
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/fileUploadUtils.js +0 -84
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/firefox/ffBrowser.js +0 -415
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/firefox/ffConnection.js +0 -142
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/firefox/ffExecutionContext.js +0 -150
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/firefox/ffInput.js +0 -175
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/firefox/ffNetworkManager.js +0 -256
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/firefox/ffPage.js +0 -495
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/firefox/firefox.js +0 -114
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/firefox/protocol.d.js +0 -16
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/formData.js +0 -147
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/frameSelectors.js +0 -160
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/frames.js +0 -1495
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/har/harRecorder.js +0 -147
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/har/harTracer.js +0 -608
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/harBackend.js +0 -157
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/helper.js +0 -96
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/index.js +0 -58
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/input.js +0 -277
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/instrumentation.js +0 -72
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/javascript.js +0 -291
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/launchApp.js +0 -127
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/localUtils.js +0 -214
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/macEditingCommands.js +0 -143
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/network.js +0 -668
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/page.js +0 -884
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/pipeTransport.js +0 -89
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/playwright.js +0 -69
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/progress.js +0 -136
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/protocolError.js +0 -52
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/recorder/chat.js +0 -161
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/recorder/recorderApp.js +0 -367
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/recorder/recorderRunner.js +0 -138
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/recorder/recorderSignalProcessor.js +0 -83
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/recorder/recorderUtils.js +0 -157
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/recorder/throttledFile.js +0 -57
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/recorder.js +0 -540
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/registry/browserFetcher.js +0 -177
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/registry/dependencies.js +0 -371
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/registry/index.js +0 -1395
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/registry/nativeDeps.js +0 -1281
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/registry/oopDownloadBrowserMain.js +0 -127
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/screencast.js +0 -216
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/screenshotter.js +0 -333
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/selectors.js +0 -112
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/socksClientCertificatesInterceptor.js +0 -383
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/socksInterceptor.js +0 -95
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/trace/recorder/snapshotter.js +0 -147
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/trace/recorder/snapshotterInjected.js +0 -561
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/trace/recorder/tracing.js +0 -607
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/trace/viewer/traceViewer.js +0 -244
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/transport.js +0 -181
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/types.js +0 -28
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/usKeyboardLayout.js +0 -152
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/utils/ascii.js +0 -44
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/utils/comparators.js +0 -139
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/utils/crypto.js +0 -216
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/utils/debug.js +0 -42
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/utils/debugLogger.js +0 -122
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/utils/disposable.js +0 -32
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/utils/env.js +0 -73
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/utils/eventsHelper.js +0 -41
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/utils/expectUtils.js +0 -123
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/utils/fileUtils.js +0 -191
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/utils/happyEyeballs.js +0 -207
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/utils/hostPlatform.js +0 -123
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/utils/httpServer.js +0 -205
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/utils/image_tools/colorUtils.js +0 -89
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/utils/image_tools/compare.js +0 -109
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/utils/image_tools/imageChannel.js +0 -78
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/utils/image_tools/stats.js +0 -102
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/utils/linuxUtils.js +0 -71
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/utils/network.js +0 -244
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/utils/nodePlatform.js +0 -154
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/utils/pipeTransport.js +0 -84
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/utils/processLauncher.js +0 -243
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/utils/profiler.js +0 -65
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/utils/socksProxy.js +0 -511
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/utils/spawnAsync.js +0 -41
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/utils/task.js +0 -51
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/utils/userAgent.js +0 -98
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/utils/wsServer.js +0 -121
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/utils/zipFile.js +0 -74
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/utils/zones.js +0 -57
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/videoRecorder.js +0 -133
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/webkit/protocol.d.js +0 -16
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/webkit/webkit.js +0 -108
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/webkit/wkBrowser.js +0 -331
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/webkit/wkConnection.js +0 -144
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/webkit/wkExecutionContext.js +0 -154
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/webkit/wkInput.js +0 -181
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/webkit/wkInterceptableRequest.js +0 -197
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/webkit/wkPage.js +0 -1164
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/webkit/wkProvisionalPage.js +0 -83
- package/vendor/playwright-cli/node_modules/playwright-core/lib/server/webkit/wkWorkers.js +0 -106
- package/vendor/playwright-cli/node_modules/playwright-core/lib/third_party/pixelmatch.js +0 -255
- package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/backend/browserBackend.js +0 -79
- package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/backend/common.js +0 -63
- package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/backend/config.js +0 -41
- package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/backend/console.js +0 -66
- package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/backend/context.js +0 -290
- package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/backend/cookies.js +0 -152
- package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/backend/devtools.js +0 -69
- package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/backend/dialogs.js +0 -59
- package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/backend/evaluate.js +0 -64
- package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/backend/files.js +0 -60
- package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/backend/form.js +0 -64
- package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/backend/keyboard.js +0 -155
- package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/backend/logFile.js +0 -95
- package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/backend/mouse.js +0 -168
- package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/backend/navigate.js +0 -106
- package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/backend/network.js +0 -135
- package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/backend/pdf.js +0 -48
- package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/backend/response.js +0 -302
- package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/backend/route.js +0 -140
- package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/backend/runCode.js +0 -76
- package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/backend/screenshot.js +0 -88
- package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/backend/sessionLog.js +0 -74
- package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/backend/snapshot.js +0 -208
- package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/backend/storage.js +0 -67
- package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/backend/tab.js +0 -445
- package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/backend/tabs.js +0 -67
- package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/backend/tool.js +0 -47
- package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/backend/tools.js +0 -102
- package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/backend/tracing.js +0 -75
- package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/backend/utils.js +0 -83
- package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/backend/verify.js +0 -151
- package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/backend/video.js +0 -89
- package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/backend/wait.js +0 -63
- package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/backend/webstorage.js +0 -223
- package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/cli-daemon/command.js +0 -73
- package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/cli-daemon/commands.js +0 -933
- package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/cli-daemon/daemon.js +0 -178
- package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/cli-daemon/helpGenerator.js +0 -173
- package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/cli-daemon/program.js +0 -118
- package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/dashboard/dashboardApp.js +0 -286
- package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/dashboard/dashboardController.js +0 -296
- package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/exports.js +0 -60
- package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/mcp/browserFactory.js +0 -233
- package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/mcp/cdpRelay.js +0 -356
- package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/mcp/cli-stub.js +0 -7
- package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/mcp/config.d.js +0 -16
- package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/mcp/config.js +0 -401
- package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/mcp/configIni.js +0 -189
- package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/mcp/extensionContextFactory.js +0 -59
- package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/mcp/index.js +0 -62
- package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/mcp/log.js +0 -35
- package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/mcp/program.js +0 -107
- package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/mcp/protocol.js +0 -28
- package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/mcp/watchdog.js +0 -44
- package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/trace/installSkill.js +0 -48
- package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/trace/traceActions.js +0 -142
- package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/trace/traceAttachments.js +0 -69
- package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/trace/traceCli.js +0 -80
- package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/trace/traceConsole.js +0 -97
- package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/trace/traceErrors.js +0 -55
- package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/trace/traceOpen.js +0 -69
- package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/trace/traceParser.js +0 -96
- package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/trace/traceRequests.js +0 -158
- package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/trace/traceScreenshot.js +0 -68
- package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/trace/traceSnapshot.js +0 -149
- package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/trace/traceUtils.js +0 -135
- package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/utils/connect.js +0 -32
- package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/utils/mcp/http.js +0 -152
- package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/utils/mcp/server.js +0 -230
- package/vendor/playwright-cli/node_modules/playwright-core/lib/tools/utils/mcp/tool.js +0 -47
- package/vendor/playwright-cli/node_modules/playwright-core/lib/utils/isomorphic/ariaSnapshot.js +0 -455
- package/vendor/playwright-cli/node_modules/playwright-core/lib/utils/isomorphic/assert.js +0 -31
- package/vendor/playwright-cli/node_modules/playwright-core/lib/utils/isomorphic/colors.js +0 -72
- package/vendor/playwright-cli/node_modules/playwright-core/lib/utils/isomorphic/cssParser.js +0 -245
- package/vendor/playwright-cli/node_modules/playwright-core/lib/utils/isomorphic/cssTokenizer.js +0 -1051
- package/vendor/playwright-cli/node_modules/playwright-core/lib/utils/isomorphic/formatUtils.js +0 -64
- package/vendor/playwright-cli/node_modules/playwright-core/lib/utils/isomorphic/headers.js +0 -53
- package/vendor/playwright-cli/node_modules/playwright-core/lib/utils/isomorphic/imageUtils.js +0 -141
- package/vendor/playwright-cli/node_modules/playwright-core/lib/utils/isomorphic/locatorGenerators.js +0 -689
- package/vendor/playwright-cli/node_modules/playwright-core/lib/utils/isomorphic/locatorParser.js +0 -176
- package/vendor/playwright-cli/node_modules/playwright-core/lib/utils/isomorphic/locatorUtils.js +0 -81
- package/vendor/playwright-cli/node_modules/playwright-core/lib/utils/isomorphic/lruCache.js +0 -51
- package/vendor/playwright-cli/node_modules/playwright-core/lib/utils/isomorphic/manualPromise.js +0 -114
- package/vendor/playwright-cli/node_modules/playwright-core/lib/utils/isomorphic/mimeType.js +0 -464
- package/vendor/playwright-cli/node_modules/playwright-core/lib/utils/isomorphic/multimap.js +0 -80
- package/vendor/playwright-cli/node_modules/playwright-core/lib/utils/isomorphic/protocolFormatter.js +0 -81
- package/vendor/playwright-cli/node_modules/playwright-core/lib/utils/isomorphic/protocolMetainfo.js +0 -342
- package/vendor/playwright-cli/node_modules/playwright-core/lib/utils/isomorphic/rtti.js +0 -43
- package/vendor/playwright-cli/node_modules/playwright-core/lib/utils/isomorphic/selectorParser.js +0 -386
- package/vendor/playwright-cli/node_modules/playwright-core/lib/utils/isomorphic/semaphore.js +0 -54
- package/vendor/playwright-cli/node_modules/playwright-core/lib/utils/isomorphic/stackTrace.js +0 -158
- package/vendor/playwright-cli/node_modules/playwright-core/lib/utils/isomorphic/stringUtils.js +0 -204
- package/vendor/playwright-cli/node_modules/playwright-core/lib/utils/isomorphic/time.js +0 -49
- package/vendor/playwright-cli/node_modules/playwright-core/lib/utils/isomorphic/timeoutRunner.js +0 -66
- package/vendor/playwright-cli/node_modules/playwright-core/lib/utils/isomorphic/trace/entries.js +0 -16
- package/vendor/playwright-cli/node_modules/playwright-core/lib/utils/isomorphic/trace/snapshotRenderer.js +0 -502
- package/vendor/playwright-cli/node_modules/playwright-core/lib/utils/isomorphic/trace/snapshotServer.js +0 -120
- package/vendor/playwright-cli/node_modules/playwright-core/lib/utils/isomorphic/trace/snapshotStorage.js +0 -89
- package/vendor/playwright-cli/node_modules/playwright-core/lib/utils/isomorphic/trace/traceLoader.js +0 -131
- package/vendor/playwright-cli/node_modules/playwright-core/lib/utils/isomorphic/trace/traceModel.js +0 -366
- package/vendor/playwright-cli/node_modules/playwright-core/lib/utils/isomorphic/trace/traceModernizer.js +0 -401
- package/vendor/playwright-cli/node_modules/playwright-core/lib/utils/isomorphic/trace/traceUtils.js +0 -58
- package/vendor/playwright-cli/node_modules/playwright-core/lib/utils/isomorphic/trace/versions/traceV3.js +0 -16
- package/vendor/playwright-cli/node_modules/playwright-core/lib/utils/isomorphic/trace/versions/traceV4.js +0 -16
- package/vendor/playwright-cli/node_modules/playwright-core/lib/utils/isomorphic/trace/versions/traceV5.js +0 -16
- package/vendor/playwright-cli/node_modules/playwright-core/lib/utils/isomorphic/trace/versions/traceV6.js +0 -16
- package/vendor/playwright-cli/node_modules/playwright-core/lib/utils/isomorphic/trace/versions/traceV7.js +0 -16
- package/vendor/playwright-cli/node_modules/playwright-core/lib/utils/isomorphic/trace/versions/traceV8.js +0 -16
- package/vendor/playwright-cli/node_modules/playwright-core/lib/utils/isomorphic/types.js +0 -16
- package/vendor/playwright-cli/node_modules/playwright-core/lib/utils/isomorphic/urlMatch.js +0 -243
- package/vendor/playwright-cli/node_modules/playwright-core/lib/utils/isomorphic/utilityScriptSerializers.js +0 -262
- package/vendor/playwright-cli/node_modules/playwright-core/lib/utils/isomorphic/yaml.js +0 -84
- package/vendor/playwright-cli/node_modules/playwright-core/lib/utils.js +0 -113
- package/vendor/playwright-cli/node_modules/playwright-core/lib/utilsBundleImpl/index.js +0 -218
- package/vendor/playwright-cli/node_modules/playwright-core/lib/vite/traceViewer/assets/codeMirrorModule-BtGnd8kr.js +0 -32
- package/vendor/playwright-cli/node_modules/playwright-core/lib/vite/traceViewer/assets/codeMirrorModule-CnvO0fko.js +0 -32
- package/vendor/playwright-cli/node_modules/playwright-core/lib/vite/traceViewer/assets/defaultSettingsView-BkMbME_o.js +0 -262
- package/vendor/playwright-cli/node_modules/playwright-core/lib/vite/traceViewer/assets/defaultSettingsView-CN3cwLGD.js +0 -262
- package/vendor/playwright-cli/node_modules/playwright-core/lib/vite/traceViewer/defaultSettingsView.B4dS75f0.css +0 -1
- package/vendor/playwright-cli/node_modules/playwright-core/lib/vite/traceViewer/defaultSettingsView.DcQiWcKS.css +0 -1
- package/vendor/playwright-cli/node_modules/playwright-core/lib/vite/traceViewer/index.B2ffe31o.js +0 -2
- package/vendor/playwright-cli/node_modules/playwright-core/lib/vite/traceViewer/index.Df3uWWXm.js +0 -2
- package/vendor/playwright-cli/node_modules/playwright-core/lib/vite/traceViewer/uiMode.BZQ54Kgt.css +0 -1
- package/vendor/playwright-cli/node_modules/playwright-core/lib/vite/traceViewer/uiMode.CmAqMvmy.js +0 -6
- package/vendor/playwright-cli/node_modules/playwright-core/lib/vite/traceViewer/uiMode.u9Eas4CP.js +0 -6
- package/vendor/playwright-cli/node_modules/playwright-core/lib/zipBundle.js +0 -34
- package/vendor/playwright-cli/node_modules/playwright-core/lib/zipBundleImpl.js +0 -5
package/README.md
CHANGED
|
@@ -243,6 +243,7 @@ cp .env.example .env.local
|
|
|
243
243
|
| `PLAYWRIGHT_MCP_EXTENSION_ID` | Chrome extension ID (client overrides server) | — |
|
|
244
244
|
| `PLAYWRIGHT_MCP_EXTENSION_TOKEN` | Chrome extension token — profile-specific, get it from the extension's status page (client overrides server) | — |
|
|
245
245
|
| `PLAYWRIGHT_MCP_USER_DATA_DIR` | Chrome user data directory — use to pin connections to a specific Chrome install (client overrides server) | — |
|
|
246
|
+
| `RECHROME_PROFILE` | Default profile selector for browser commands, equivalent to `--profile`. An explicit flag wins; blank values are ignored. Remote listeners still enforce their allowlist. | — |
|
|
246
247
|
| `PLAYWRIGHT_MCP_PROFILE_DIRECTORY` | Chrome profile — accepts directory name (`Profile 2`), display name (`Snowstar`), or **email** (`you@example.com`) (client overrides server) | — |
|
|
247
248
|
|
|
248
249
|
> **Multi-profile tip:** Each project's `.env.local` can specify a different Chrome profile via the `?profile=` query param in `RECHROME_URL`. The server resolves display names and email addresses to the actual Chrome profile directory automatically (reads `~/Library/Application Support/Google/Chrome/Local State`).
|
|
@@ -254,6 +255,57 @@ cp .env.example .env.local
|
|
|
254
255
|
>
|
|
255
256
|
> Shell-set `PLAYWRIGHT_MCP_*` variables take priority over `.env.local`, so you can always override per-command without editing files.
|
|
256
257
|
|
|
258
|
+
### Small icon uploads from stdin
|
|
259
|
+
|
|
260
|
+
Uploads are disabled by default on every listener. The host owner can add an
|
|
261
|
+
`uploads` object to the intended listener entry in `~/.rechrome/listeners.json`:
|
|
262
|
+
|
|
263
|
+
```json
|
|
264
|
+
"uploads": {
|
|
265
|
+
"maxBytes": 2097152,
|
|
266
|
+
"contentTypes": ["image/png", "image/svg+xml"]
|
|
267
|
+
}
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
The object enables uploads; omitting it disables them. `uploads: {}` uses the
|
|
271
|
+
same defaults shown above. The owner can lower the byte limit or narrow the type
|
|
272
|
+
list, but cannot exceed the hard **2 MiB** limit or enable other types. Do not
|
|
273
|
+
replace the listener's other fields or share its key. Install the updated daemon
|
|
274
|
+
code before enabling this policy; configuration changes then use the usual
|
|
275
|
+
listener reload mechanism.
|
|
276
|
+
|
|
277
|
+
On the **client machine**, open the website's file chooser with `rech click`, then
|
|
278
|
+
send the icon through stdin in the same profile/session:
|
|
279
|
+
|
|
280
|
+
```bash
|
|
281
|
+
rech --profile work -s=slack upload --name app-icon.png < ./app-icon.png
|
|
282
|
+
cat ./app-icon.svg | rech --profile work -s=slack upload --name app-icon.svg
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
`--content-type image/png` or `--content-type image/svg+xml` may be specified;
|
|
286
|
+
otherwise the type is inferred from `--name`. This command is stdin-only: there
|
|
287
|
+
is no positional file path. The shell reads the local file; only its bytes and
|
|
288
|
+
metadata are sent to the listener. Client and server both enforce the byte cap.
|
|
289
|
+
The server checks PNG signatures or UTF-8 SVG markup (rejecting DTD/entities),
|
|
290
|
+
and checks the type against the listener policy. These checks identify the file
|
|
291
|
+
format; they do not sanitize SVG or scan for malware. The host never renders the
|
|
292
|
+
file or resolves anything referenced inside it.
|
|
293
|
+
|
|
294
|
+
The receiver writes a random `.png`/`.svg` filename with mode 0600 inside a private
|
|
295
|
+
0700 temporary directory, outside the downloadable output tree. It passes only
|
|
296
|
+
that generated path to the existing file-chooser command and removes the directory
|
|
297
|
+
on success, error, or timeout. Neither filenames nor payload fields can select a
|
|
298
|
+
host file. A crash or forced process kill can interrupt cleanup; the files remain
|
|
299
|
+
private OS temporary files. Permission modes apply on POSIX hosts.
|
|
300
|
+
|
|
301
|
+
Each upload produces one `upload:` JSON audit record with listener, profile,
|
|
302
|
+
original name, byte size, SHA-256, page origin observed immediately before upload,
|
|
303
|
+
and result. It contains no file contents, credentials, page path, query, or fragment.
|
|
304
|
+
Requests rejected before inspection have null values for unavailable fields.
|
|
305
|
+
An HTTP(S) origin must be determined before an upload is attempted. As with other
|
|
306
|
+
browser commands, avoid concurrent tab navigation in the same session. Scoped
|
|
307
|
+
`eval`, `run-code`, host paths, and CLI option overrides remain unavailable.
|
|
308
|
+
|
|
257
309
|
### Remote access
|
|
258
310
|
|
|
259
311
|
`rech setup --profile <profile> --listen tailscale` exposes that profile through a
|
|
@@ -345,3 +397,25 @@ PRs upstream are welcome. Once these features land in the official packages we w
|
|
|
345
397
|
## License
|
|
346
398
|
|
|
347
399
|
MIT
|
|
400
|
+
|
|
401
|
+
### Bridge connection diagnostics and recovery
|
|
402
|
+
|
|
403
|
+
Each connection attempt records fixed phase names (launch, retry, WebSocket
|
|
404
|
+
accepted, initialized, timeout/close) in its own private `.bridge.jsonl` file under
|
|
405
|
+
`~/.cache/ms-playwright/bridge`, or `PLAYWRIGHT_MCP_BRIDGE_LOG_DIR` when configured
|
|
406
|
+
for the Playwright process. Records contain an attempt ID, PID and timing only;
|
|
407
|
+
no URLs, tokens, page text or raw error messages. CLI startup stderr is retained
|
|
408
|
+
separately in a unique `.err` file for each launch and is not the sanitized log.
|
|
409
|
+
|
|
410
|
+
A failed automated connection page retires itself at its deadline only if it
|
|
411
|
+
still shows the original connection URL. The profile's worker can remove an older
|
|
412
|
+
page for the same attempt and relay; it excludes other attempts, attached tabs,
|
|
413
|
+
and tabs that navigated away. Automatic recovery no longer reloads the extension,
|
|
414
|
+
which could disconnect other working lanes. A genuinely unresponsive worker can
|
|
415
|
+
still require an explicit operator-approved extension reload.
|
|
416
|
+
|
|
417
|
+
This source change requires rebuilding the vendored Playwright bundle and
|
|
418
|
+
reloading the updated extension before use. It does not modify a running daemon
|
|
419
|
+
or extension. The draft PR records isolated-browser validation and negative
|
|
420
|
+
controls; passing recovery tests does not establish the original intermittent
|
|
421
|
+
timeout's root cause.
|
|
@@ -566,7 +566,10 @@ class PlaywrightExtension {
|
|
|
566
566
|
_onMessage(message, sender, sendResponse) {
|
|
567
567
|
switch (message.type) {
|
|
568
568
|
case "connectionRequested":
|
|
569
|
-
|
|
569
|
+
(async () => {
|
|
570
|
+
if (message.recoveryAttempt) await this._retireSupersededPages(sender);
|
|
571
|
+
await this._pendingConnections.create(sender.tab.id, message.mcpRelayUrl, message.protocolVersion);
|
|
572
|
+
})().then(
|
|
570
573
|
() => sendResponse({ success: true }),
|
|
571
574
|
(error) => sendResponse({ success: false, error: error.message })
|
|
572
575
|
);
|
|
@@ -606,6 +609,27 @@ class PlaywrightExtension {
|
|
|
606
609
|
return false;
|
|
607
610
|
}
|
|
608
611
|
}
|
|
612
|
+
// The single worker coordinates recovery within this profile. It never reloads
|
|
613
|
+
// itself or touches live groups: only sibling connect pages for the same relay
|
|
614
|
+
// attempt can be retired. A different lane/attempt is outside this ownership.
|
|
615
|
+
async _retireSupersededPages(sender) {
|
|
616
|
+
var _a;
|
|
617
|
+
const current = new URL(sender.url || ((_a = sender.tab) == null ? void 0 : _a.url) || "about:blank");
|
|
618
|
+
const attempt = current.searchParams.get("attempt");
|
|
619
|
+
const relay = current.searchParams.get("mcpRelayUrl");
|
|
620
|
+
if (current.protocol !== "chrome-extension:" || current.host !== chrome.runtime.id || current.pathname !== "/connect.html" || !/^[0-9a-f-]{36}$/.test(attempt || "") || !relay) return;
|
|
621
|
+
const attached = new Set([...this._activeGroups].flatMap((g) => g.connectedTabIds()));
|
|
622
|
+
const tabs = await chrome.tabs.query({});
|
|
623
|
+
await Promise.all(tabs.map(async (tab) => {
|
|
624
|
+
var _a2;
|
|
625
|
+
if (tab.id === void 0 || tab.id === ((_a2 = sender.tab) == null ? void 0 : _a2.id) || attached.has(tab.id) || !tab.url) return;
|
|
626
|
+
const other = new URL(tab.url);
|
|
627
|
+
if (other.protocol !== current.protocol || other.host !== current.host || other.pathname !== current.pathname || other.searchParams.get("attempt") !== attempt || other.searchParams.get("mcpRelayUrl") !== relay) return;
|
|
628
|
+
const latest = await chrome.tabs.get(tab.id).catch(() => void 0);
|
|
629
|
+
if ((latest == null ? void 0 : latest.url) === tab.url) await chrome.tabs.remove(tab.id).catch(() => {
|
|
630
|
+
});
|
|
631
|
+
}));
|
|
632
|
+
}
|
|
609
633
|
async _connectTab(selectorTabId, tab, clientName) {
|
|
610
634
|
try {
|
|
611
635
|
await Promise.race([
|
|
@@ -655,3 +679,6 @@ class PlaywrightExtension {
|
|
|
655
679
|
}
|
|
656
680
|
}
|
|
657
681
|
new PlaywrightExtension();
|
|
682
|
+
export {
|
|
683
|
+
PlaywrightExtension
|
|
684
|
+
};
|
|
@@ -4,18 +4,12 @@
|
|
|
4
4
|
import { c as clientExports, j as jsxRuntimeExports, r as reactExports, A as AuthTokenSection, T as TabItem, B as Button, g as getOrCreateAuthToken } from "./authToken.js";
|
|
5
5
|
const SUPPORTED_PROTOCOL_VERSION = 2;
|
|
6
6
|
const BACKGROUND_RESPONSE_TIMEOUT_MS = 1e4;
|
|
7
|
-
|
|
8
|
-
const
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
const now = Date.now();
|
|
14
|
-
if (now - last < SELF_RELOAD_MIN_INTERVAL_MS)
|
|
15
|
-
return false;
|
|
16
|
-
localStorage.setItem(SELF_RELOAD_GUARD_KEY, String(now));
|
|
17
|
-
chrome.runtime.reload();
|
|
18
|
-
return true;
|
|
7
|
+
async function retireExpiredAttempt(originalUrl) {
|
|
8
|
+
const params = new URL(originalUrl).searchParams;
|
|
9
|
+
if (!/^[0-9a-f-]{36}$/.test(params.get("attempt") || "")) return;
|
|
10
|
+
const tab = await chrome.tabs.getCurrent();
|
|
11
|
+
if ((tab == null ? void 0 : tab.id) !== void 0 && tab.url === originalUrl)
|
|
12
|
+
await chrome.tabs.remove(tab.id);
|
|
19
13
|
}
|
|
20
14
|
async function sendMessageWithTimeout(message, simulateHang = false) {
|
|
21
15
|
let timer;
|
|
@@ -41,6 +35,17 @@ const ConnectApp = () => {
|
|
|
41
35
|
setStatus({ type: "error", message });
|
|
42
36
|
}, []);
|
|
43
37
|
reactExports.useEffect(() => {
|
|
38
|
+
const originalUrl = window.location.href;
|
|
39
|
+
const expiry = Number(new URL(originalUrl).searchParams.get("expires"));
|
|
40
|
+
let connected = false;
|
|
41
|
+
const onConnected = () => {
|
|
42
|
+
connected = true;
|
|
43
|
+
};
|
|
44
|
+
window.addEventListener("bridge-connected", onConnected);
|
|
45
|
+
const expiryTimer = Number.isFinite(expiry) && expiry > 0 ? setTimeout(() => {
|
|
46
|
+
if (!connected) void retireExpiredAttempt(originalUrl).catch(() => {
|
|
47
|
+
});
|
|
48
|
+
}, Math.max(0, Math.min(expiry - Date.now(), 2147483647))) : void 0;
|
|
44
49
|
const runAsync = async () => {
|
|
45
50
|
const params = new URLSearchParams(window.location.search);
|
|
46
51
|
const relayUrl = params.get("mcpRelayUrl");
|
|
@@ -89,13 +94,12 @@ const ConnectApp = () => {
|
|
|
89
94
|
let response;
|
|
90
95
|
try {
|
|
91
96
|
response = await sendMessageWithTimeout(
|
|
92
|
-
{ type: "connectionRequested", mcpRelayUrl: relayUrl, protocolVersion: requestedVersion },
|
|
97
|
+
{ type: "connectionRequested", mcpRelayUrl: relayUrl, protocolVersion: requestedVersion, recoveryAttempt },
|
|
93
98
|
params.get("testHangOnce") === "1" && !recoveryAttempt
|
|
94
99
|
);
|
|
95
100
|
} catch (error) {
|
|
96
101
|
if (hasAutomationToken && !recoveryAttempt) {
|
|
97
|
-
|
|
98
|
-
setError(reloading ? "Extension service worker is not responding. Reloading extension and retrying…" : "Extension service worker is not responding. Retrying once…");
|
|
102
|
+
setError("Extension service worker is not responding. Retrying once…");
|
|
99
103
|
return;
|
|
100
104
|
}
|
|
101
105
|
setError(`Extension service worker did not recover: ${error.message}`);
|
|
@@ -108,7 +112,7 @@ const ConnectApp = () => {
|
|
|
108
112
|
const expectedToken = getOrCreateAuthToken();
|
|
109
113
|
const token = params.get("token");
|
|
110
114
|
if (token === expectedToken) {
|
|
111
|
-
await handleConnectToTab(void 0, info);
|
|
115
|
+
connected = !!await handleConnectToTab(void 0, info);
|
|
112
116
|
return;
|
|
113
117
|
}
|
|
114
118
|
if (token) {
|
|
@@ -125,7 +129,11 @@ const ConnectApp = () => {
|
|
|
125
129
|
chrome.runtime.sendMessage({ type: "keepalive" }).catch(() => {
|
|
126
130
|
});
|
|
127
131
|
}, 2e4);
|
|
128
|
-
return () =>
|
|
132
|
+
return () => {
|
|
133
|
+
clearInterval(keepalive);
|
|
134
|
+
clearTimeout(expiryTimer);
|
|
135
|
+
window.removeEventListener("bridge-connected", onConnected);
|
|
136
|
+
};
|
|
129
137
|
}, []);
|
|
130
138
|
const loadTabs = reactExports.useCallback(async () => {
|
|
131
139
|
const response = await chrome.runtime.sendMessage({ type: "getTabs" });
|
|
@@ -144,6 +152,8 @@ const ConnectApp = () => {
|
|
|
144
152
|
});
|
|
145
153
|
if (response == null ? void 0 : response.success) {
|
|
146
154
|
setStatus({ type: "connected", message: `"${clientName}" connected.` });
|
|
155
|
+
window.dispatchEvent(new Event("bridge-connected"));
|
|
156
|
+
return true;
|
|
147
157
|
} else {
|
|
148
158
|
setStatus({
|
|
149
159
|
type: "error",
|
|
@@ -154,8 +164,7 @@ const ConnectApp = () => {
|
|
|
154
164
|
const recoveryAttempt = new URLSearchParams(window.location.search).get("recoveryAttempt") === "1";
|
|
155
165
|
const hasAutomationToken = !!new URLSearchParams(window.location.search).get("token");
|
|
156
166
|
if (hasAutomationToken && !recoveryAttempt) {
|
|
157
|
-
|
|
158
|
-
setError(reloading ? "Extension service worker stopped during connection. Reloading extension and retrying…" : "Extension service worker stopped during connection. Retrying once…");
|
|
167
|
+
setError("Extension service worker stopped during connection. Retrying once…");
|
|
159
168
|
return;
|
|
160
169
|
}
|
|
161
170
|
setStatus({
|
|
@@ -163,6 +172,7 @@ const ConnectApp = () => {
|
|
|
163
172
|
message: `"${clientName}" failed to connect: ${e}`
|
|
164
173
|
});
|
|
165
174
|
}
|
|
175
|
+
return false;
|
|
166
176
|
}, [clientInfo, setError]);
|
|
167
177
|
reactExports.useEffect(() => {
|
|
168
178
|
const listener = (message) => {
|
package/listeners.js
CHANGED
|
@@ -1,4 +1,14 @@
|
|
|
1
1
|
// @bun
|
|
2
|
+
// scoped-upload.ts
|
|
3
|
+
var MAX_UPLOAD_BYTES = 2 * 1024 * 1024;
|
|
4
|
+
var MAX_REQUEST_BYTES = 3 * 1024 * 1024;
|
|
5
|
+
var UPLOAD_TYPES = ["image/png", "image/svg+xml"];
|
|
6
|
+
function validateUploadPolicy(value) {
|
|
7
|
+
const p = value;
|
|
8
|
+
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))))
|
|
9
|
+
throw new Error("uploads must be an object with optional maxBytes (1..2097152) and contentTypes (image/png, image/svg+xml)");
|
|
10
|
+
}
|
|
11
|
+
|
|
2
12
|
// listeners.ts
|
|
3
13
|
import { isIP } from "net";
|
|
4
14
|
import { createHash, randomBytes } from "crypto";
|
|
@@ -54,6 +64,8 @@ function validateListeners(value) {
|
|
|
54
64
|
} else if (!Array.isArray(l.profiles) || !l.profiles.length || l.profiles.some((p) => typeof p !== "string" || !p.trim() || p.includes("\x00") || p === "*")) {
|
|
55
65
|
throw new Error("Listener profiles must be a nonempty list of registered profile keys");
|
|
56
66
|
}
|
|
67
|
+
if (l.uploads !== undefined)
|
|
68
|
+
validateUploadPolicy(l.uploads);
|
|
57
69
|
const address = listenerAddress(l);
|
|
58
70
|
if (names.has(l.name) || addresses.has(address) || keys.has(l.key))
|
|
59
71
|
throw new Error("Listener names, addresses, and credentials must be unique");
|
|
@@ -92,12 +104,16 @@ function authorizeProfileRequest(listener, body) {
|
|
|
92
104
|
if (body.env?.PLAYWRIGHT_MCP_PROFILE_DIRECTORY && body.env.PLAYWRIGHT_MCP_PROFILE_DIRECTORY !== profile)
|
|
93
105
|
throw new Error("Profile override does not match request identity");
|
|
94
106
|
const args = body.args.filter((a) => /^-s=[a-zA-Z0-9_-]{1,64}$/.test(a) === false);
|
|
95
|
-
if (!SCOPED_COMMANDS.has(args[0]))
|
|
107
|
+
if (!(args[0] === "upload" && listener.uploads !== undefined) && !SCOPED_COMMANDS.has(args[0]))
|
|
96
108
|
throw new Error("Command is unavailable on profile-scoped listeners; use the local management listener for arbitrary code or host access");
|
|
97
109
|
if (body.args.filter((a) => a.startsWith("-s=")).length > 1 || args.slice(1).some((a) => a.startsWith("-") && !(args[0] === "screenshot" && a === "--full-page")))
|
|
98
110
|
throw new Error("CLI option overrides are unavailable on profile-scoped listeners");
|
|
99
111
|
if (["open", "goto", "tab-new"].includes(args[0]) && args[1] && !/^https?:\/\//i.test(args[1]) && args[1] !== "about:blank")
|
|
100
112
|
throw new Error("Scoped navigation accepts only HTTP(S) or about:blank");
|
|
113
|
+
if (args[0] === "upload" && (args.length !== 1 || !body.upload))
|
|
114
|
+
throw new Error("Upload requires stdin bytes; host paths are unavailable");
|
|
115
|
+
if (args[0] !== "upload" && body.upload !== undefined)
|
|
116
|
+
throw new Error("Unexpected upload payload");
|
|
101
117
|
return profile;
|
|
102
118
|
}
|
|
103
119
|
function canReadProfileFile(listener, path) {
|
package/listeners.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { validateUploadPolicy, type UploadPolicy } from "./scoped-upload.ts";
|
|
1
2
|
import { isIP } from "net";
|
|
2
3
|
import { createHash, randomBytes } from "crypto";
|
|
3
4
|
import { homedir } from "os";
|
|
@@ -5,7 +6,7 @@ import { join } from "path";
|
|
|
5
6
|
import { mkdir, readFile, rename, writeFile } from "fs/promises";
|
|
6
7
|
|
|
7
8
|
// publicUrl: where a reverse proxy (Tailscale Serve, Caddy, nginx, ...) exposes this listener.
|
|
8
|
-
export type Listener = { name: string; host: string; port: number; key: string; profiles: string[] | "*"; prefix?: string; publicUrl?: string };
|
|
9
|
+
export type Listener = { name: string; host: string; port: number; key: string; profiles: string[] | "*"; prefix?: string; publicUrl?: string; uploads?: UploadPolicy };
|
|
9
10
|
export type ListenerConfig = { version: 1; listeners: Listener[] };
|
|
10
11
|
export const LISTENERS_FILE = join(homedir(), ".rechrome", "listeners.json");
|
|
11
12
|
export const isLoopback = (host: string) => host === "::1" || /^127\./.test(host);
|
|
@@ -54,6 +55,7 @@ export function validateListeners(value: unknown): ListenerConfig {
|
|
|
54
55
|
} else if (!Array.isArray(l.profiles) || !l.profiles.length || l.profiles.some(p => typeof p !== "string" || !p.trim() || p.includes("\0") || p === "*")) {
|
|
55
56
|
throw new Error("Listener profiles must be a nonempty list of registered profile keys");
|
|
56
57
|
}
|
|
58
|
+
if (l.uploads !== undefined) validateUploadPolicy(l.uploads);
|
|
57
59
|
const address = listenerAddress(l);
|
|
58
60
|
if (names.has(l.name) || addresses.has(address) || keys.has(l.key)) throw new Error("Listener names, addresses, and credentials must be unique");
|
|
59
61
|
names.add(l.name); addresses.add(address); keys.add(l.key);
|
|
@@ -85,9 +87,12 @@ export function authorizeProfileRequest(listener: Listener, body: any): string {
|
|
|
85
87
|
if (typeof profile !== "string" || listener.profiles === "*" || !listener.profiles.includes(profile)) throw new Error("Profile is not allowed on this listener");
|
|
86
88
|
if (body.env?.PLAYWRIGHT_MCP_PROFILE_DIRECTORY && body.env.PLAYWRIGHT_MCP_PROFILE_DIRECTORY !== profile) throw new Error("Profile override does not match request identity");
|
|
87
89
|
const args = body.args.filter((a: string) => /^-s=[a-zA-Z0-9_-]{1,64}$/.test(a) === false);
|
|
88
|
-
if (!SCOPED_COMMANDS.has(args[0])) throw new Error("Command is unavailable on profile-scoped listeners; use the local management listener for arbitrary code or host access");
|
|
90
|
+
if (!(args[0] === "upload" && listener.uploads !== undefined) && !SCOPED_COMMANDS.has(args[0])) throw new Error("Command is unavailable on profile-scoped listeners; use the local management listener for arbitrary code or host access");
|
|
89
91
|
if (body.args.filter((a: string) => a.startsWith("-s=")).length > 1 || args.slice(1).some((a: string) => a.startsWith("-") && !(args[0] === "screenshot" && a === "--full-page"))) throw new Error("CLI option overrides are unavailable on profile-scoped listeners");
|
|
90
92
|
if (["open", "goto", "tab-new"].includes(args[0]) && args[1] && !/^https?:\/\//i.test(args[1]) && args[1] !== "about:blank") throw new Error("Scoped navigation accepts only HTTP(S) or about:blank");
|
|
93
|
+
// Upload is handled by the byte-only receiver; the caller cannot supply host paths.
|
|
94
|
+
if (args[0] === "upload" && (args.length !== 1 || !body.upload)) throw new Error("Upload requires stdin bytes; host paths are unavailable");
|
|
95
|
+
if (args[0] !== "upload" && body.upload !== undefined) throw new Error("Unexpected upload payload");
|
|
91
96
|
return profile;
|
|
92
97
|
}
|
|
93
98
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "rechrome",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.36.0",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "https://github.com/snomiao/rechrome.git"
|
|
@@ -25,7 +25,9 @@
|
|
|
25
25
|
"rechrome.ts",
|
|
26
26
|
"serve.js",
|
|
27
27
|
"serve.ts",
|
|
28
|
-
"vendor"
|
|
28
|
+
"vendor",
|
|
29
|
+
"scoped-upload.ts",
|
|
30
|
+
"scoped-upload.js"
|
|
29
31
|
],
|
|
30
32
|
"type": "module",
|
|
31
33
|
"scripts": {
|
|
@@ -34,7 +36,7 @@
|
|
|
34
36
|
"vendor-cli": "bash scripts/vendor-cli.sh",
|
|
35
37
|
"prepare": "bash scripts/vendor-cli.sh --prepare",
|
|
36
38
|
"check-pack": "bash scripts/check-pack.sh",
|
|
37
|
-
"prepublishOnly": "bash scripts/vendor-cli.sh && sed 's/\\.ts/\\.js/g' rechrome.ts > rechrome.js && sed 's/\\.ts/\\.js/g' serve.ts > serve.js && bun build extension-token.ts --target=bun --outfile=extension-token.js && bun build daemon-manager.ts --target=bun --outfile=daemon-manager.js && bun build listeners.ts --target=bun --outfile=listeners.js && bash scripts/check-pack.sh"
|
|
39
|
+
"prepublishOnly": "bash scripts/vendor-cli.sh && sed 's/\\.ts/\\.js/g' rechrome.ts > rechrome.js && sed 's/\\.ts/\\.js/g' serve.ts > serve.js && bun build extension-token.ts --target=bun --outfile=extension-token.js && bun build daemon-manager.ts --target=bun --outfile=daemon-manager.js && bun build listeners.ts --target=bun --outfile=listeners.js && bun build scoped-upload.ts --target=bun --outfile=scoped-upload.js && bash scripts/check-pack.sh"
|
|
38
40
|
},
|
|
39
41
|
"devDependencies": {
|
|
40
42
|
"@types/bun": "latest",
|
package/rechrome.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
|
+
import { prepareStdinUpload, type UploadPayload } from "./scoped-upload.js";
|
|
2
3
|
import { readListeners, writeListeners, listenerAddress, isLoopback, normalizePrefix, serviceUrl, allowProfiles, denyProfiles, rotateListenerKey, setPublicUrl, canonicalProfileKeys, planProfileRemoval, type Listener } from "./listeners.js";
|
|
3
4
|
|
|
4
5
|
import { file } from "bun";
|
|
@@ -1509,11 +1510,7 @@ async function shareSet(snapshot: string[], opts: { listener?: string; local?: b
|
|
|
1509
1510
|
// A one-profile link names its profile, so the other machine needs no --profile.
|
|
1510
1511
|
const only = snapshot.length === 1 ? `?profile=${encodeURIComponent(snapshot[0])}` : "";
|
|
1511
1512
|
const local = `http://${listener.key}@${listenerAddress(listener)}${normalizePrefix(listener.prefix)}${only}`;
|
|
1512
|
-
|
|
1513
|
-
for (let i = 0; i < 20 && !ready; i++) {
|
|
1514
|
-
ready = await fetch(serviceUrl(local, "ping"), { headers: { Authorization: `Bearer ${listener.key}` }, signal: AbortSignal.timeout(1000) }).then(r => r.ok).catch(() => false);
|
|
1515
|
-
if (!ready) await Bun.sleep(250);
|
|
1516
|
-
}
|
|
1513
|
+
const ready = await waitForListener(listener);
|
|
1517
1514
|
if (!ready) console.error(`[rech] warning: listener "${name}" is not answering yet; check the daemon with rech status.`);
|
|
1518
1515
|
if (opts.tailscaleServe && !listener.publicUrl) {
|
|
1519
1516
|
const publicUrl = await exposeWithTailscaleServe(listener);
|
|
@@ -1570,6 +1567,32 @@ async function exposeWithTailscaleServe(listener: Listener): Promise<string | nu
|
|
|
1570
1567
|
return (await detectTailscaleServe(listener.port, prefix)).routeUrl;
|
|
1571
1568
|
}
|
|
1572
1569
|
|
|
1570
|
+
/** The daemon reloads listeners.json about every second: wait (up to ~5s) until this listener answers. */
|
|
1571
|
+
async function waitForListener(listener: Listener): Promise<boolean> {
|
|
1572
|
+
const url = `http://${listener.key}@${listenerAddress(listener)}${normalizePrefix(listener.prefix)}`;
|
|
1573
|
+
for (let i = 0; i < 20; i++) {
|
|
1574
|
+
if (await fetch(serviceUrl(url, "ping"), { headers: { Authorization: `Bearer ${listener.key}` }, signal: AbortSignal.timeout(1000) }).then(r => r.ok).catch(() => false)) return true;
|
|
1575
|
+
await Bun.sleep(250);
|
|
1576
|
+
}
|
|
1577
|
+
return false;
|
|
1578
|
+
}
|
|
1579
|
+
|
|
1580
|
+
/**
|
|
1581
|
+
* Ask how other machines will reach a link: "tailscale-serve", a detected network address
|
|
1582
|
+
* (plain HTTP), "127.0.0.1" for the user's own proxy, or `extra` choices; null when cancelled.
|
|
1583
|
+
*/
|
|
1584
|
+
async function askReachability(question: string, extra: { label: string; value: string }[] = []): Promise<string | null> {
|
|
1585
|
+
const serve = !!tailscaleBinary();
|
|
1586
|
+
// With Tailscale Serve on offer, a plain-HTTP Tailscale IP would only be a worse duplicate.
|
|
1587
|
+
const networks = (await detectListenChoices()).filter(c => c.kind !== "local" && !(serve && c.kind === "tailscale"));
|
|
1588
|
+
return promptChoice(question, [
|
|
1589
|
+
...(serve ? [{ label: "Tailscale: HTTPS, only your tailnet", value: "tailscale-serve" }] : []),
|
|
1590
|
+
...networks.map(c => ({ label: `${c.label.split(" — ")[0]} network: http://${c.address}, plain HTTP`, value: c.address })),
|
|
1591
|
+
{ label: "My own reverse proxy", value: "127.0.0.1" },
|
|
1592
|
+
...extra,
|
|
1593
|
+
], 0);
|
|
1594
|
+
}
|
|
1595
|
+
|
|
1573
1596
|
/**
|
|
1574
1597
|
* Give one profile its own link. In a terminal, ask how the other machines will reach it
|
|
1575
1598
|
* (Tailscale Serve, a detected network, or the user's own proxy); without one, create a
|
|
@@ -1580,14 +1603,7 @@ async function shareNewLink(profile: string, opts: { local?: boolean; save?: boo
|
|
|
1580
1603
|
const name = uniqueShareName(profileSlug(profile), (await requireListeners()).listeners, served);
|
|
1581
1604
|
let host = "127.0.0.1", tailscaleServe = false;
|
|
1582
1605
|
if (isInteractive()) {
|
|
1583
|
-
const
|
|
1584
|
-
// With Tailscale Serve on offer, a plain-HTTP Tailscale IP would only be a worse duplicate.
|
|
1585
|
-
const networks = (await detectListenChoices()).filter(c => c.kind !== "local" && !(serve && c.kind === "tailscale"));
|
|
1586
|
-
const how = await promptChoice(`How will your other machines reach it?`, [
|
|
1587
|
-
...(serve ? [{ label: "Tailscale: HTTPS, only your tailnet", value: "tailscale-serve" }] : []),
|
|
1588
|
-
...networks.map(c => ({ label: `${c.label.split(" — ")[0]} network: http://${c.address}, plain HTTP`, value: c.address })),
|
|
1589
|
-
{ label: "My own reverse proxy", value: "127.0.0.1" },
|
|
1590
|
-
], 0);
|
|
1606
|
+
const how = await askReachability(`How will your other machines reach it?`);
|
|
1591
1607
|
if (!how) throw new Error("Cancelled; nothing shared.");
|
|
1592
1608
|
tailscaleServe = how === "tailscale-serve";
|
|
1593
1609
|
host = tailscaleServe ? "127.0.0.1" : how;
|
|
@@ -1726,6 +1742,31 @@ async function printProfileUri(selector?: string, listener?: string, opts: { loc
|
|
|
1726
1742
|
const serve = await detectTailscaleServe(pending.port, normalizePrefix(pending.prefix));
|
|
1727
1743
|
if (serve.routeUrl && !serve.funnel) { pending.publicUrl = serve.routeUrl; await writeListeners(config); }
|
|
1728
1744
|
}
|
|
1745
|
+
// Still only reachable from this machine (no proxy recorded or detected): a link like that is
|
|
1746
|
+
// useless to hand out, so ask how other machines reach it, or say how to expose it.
|
|
1747
|
+
if (config && pending && pending.profiles !== "*" && !pending.publicUrl && isLoopback(pending.host) && !opts.local) {
|
|
1748
|
+
const steps = () => { for (const line of listenerNextSteps(pending, profile)) console.error(line); };
|
|
1749
|
+
if (!interactive) {
|
|
1750
|
+
console.error(`[rech] this link only works on this machine: listener "${pending.name}" is on ${listenerAddress(pending)} and no proxy is recorded.`);
|
|
1751
|
+
steps();
|
|
1752
|
+
} else {
|
|
1753
|
+
const KEEP = "\0keep";
|
|
1754
|
+
const how = await askReachability(`Link "${pending.name}" only works on this machine (${listenerAddress(pending)}). How will your other machines reach it?`,
|
|
1755
|
+
[{ label: "Nothing: keep it on this machine", value: KEEP }]);
|
|
1756
|
+
if (!how) throw cancelled();
|
|
1757
|
+
if (how === "tailscale-serve") {
|
|
1758
|
+
const routeUrl = await exposeWithTailscaleServe(pending);
|
|
1759
|
+
if (routeUrl) { pending.publicUrl = routeUrl; await writeListeners(config); }
|
|
1760
|
+
} else if (how === "127.0.0.1") steps();
|
|
1761
|
+
else if (how !== KEEP) {
|
|
1762
|
+
// Same key and prefix, now bound on that network; links already handed out change host.
|
|
1763
|
+
pending.host = how;
|
|
1764
|
+
await writeListeners(config);
|
|
1765
|
+
if (!(await waitForListener(pending))) console.error(`[rech] warning: listener "${pending.name}" is not answering on ${listenerAddress(pending)} yet; check the daemon with rech status.`);
|
|
1766
|
+
uri = profileConnectionUri(profile, undefined, config.listeners, pending.name);
|
|
1767
|
+
}
|
|
1768
|
+
}
|
|
1769
|
+
}
|
|
1729
1770
|
const publicUrl = pending?.publicUrl;
|
|
1730
1771
|
if (publicUrl && !opts.local) uri = rebaseConnectionUrl(publicUrl, uri);
|
|
1731
1772
|
console.log(uri);
|
|
@@ -1768,6 +1809,7 @@ async function callServe(
|
|
|
1768
1809
|
overrideEnv?: Record<string, string>,
|
|
1769
1810
|
precomputedIdentity?: { key: string; label: string; profile?: string },
|
|
1770
1811
|
throwOnFailure = false,
|
|
1812
|
+
upload?: UploadPayload,
|
|
1771
1813
|
): Promise<{ status: number; stdout: string; stderr: string; files?: string[]; existingSession?: boolean }> {
|
|
1772
1814
|
const { key, host, port, protocol, extensionId, extensionToken, profileDirectory, userDataDir, loadExtension } = parseUrl(url);
|
|
1773
1815
|
// Reuse the caller's identity when provided — computing it shells out to `git` several times,
|
|
@@ -1786,7 +1828,7 @@ async function callServe(
|
|
|
1786
1828
|
method: "POST",
|
|
1787
1829
|
headers: { "Content-Type": "application/json", Authorization: `Bearer ${key}` },
|
|
1788
1830
|
// dataDir is a client-local path; the daemon (possibly remote) only needs the session identity.
|
|
1789
|
-
body: JSON.stringify({ args, identity: { key: identity.key, label: identity.label, profile: identity.profile }, env }),
|
|
1831
|
+
body: JSON.stringify({ args, identity: { key: identity.key, label: identity.label, profile: identity.profile }, env, ...(upload ? { upload } : {}) }),
|
|
1790
1832
|
signal: AbortSignal.timeout(70_000),
|
|
1791
1833
|
}).catch(async (e) => {
|
|
1792
1834
|
if (throwOnFailure) throw new Error("Cannot reach the rechrome daemon. Check that it is running.");
|
|
@@ -1972,7 +2014,12 @@ async function run(url: string, args: string[], overrideEnv?: Record<string, str
|
|
|
1972
2014
|
|
|
1973
2015
|
const resolvedEnv = await getClientEnv({ extensionId, extensionToken, profileDirectory: effectiveProfile, userDataDir, loadExtension });
|
|
1974
2016
|
const effectiveEnv = { ...resolvedEnv, ...overrideEnv };
|
|
1975
|
-
|
|
2017
|
+
let upload: UploadPayload | undefined;
|
|
2018
|
+
if (args.find(a => !/^-s=[a-zA-Z0-9_-]{1,64}$/.test(a)) === "upload") {
|
|
2019
|
+
if (process.stdin.isTTY) throw new Error("upload reads stdin; redirect a PNG/SVG file with < icon.png");
|
|
2020
|
+
({ args, upload } = await prepareStdinUpload(args, process.stdin));
|
|
2021
|
+
}
|
|
2022
|
+
const { status, stdout, stderr, files, existingSession } = await callServe(url, args, overrideEnv, identity, false, upload);
|
|
1976
2023
|
|
|
1977
2024
|
const isOpenWithUrl = args[0] === "open" && args.length > 1;
|
|
1978
2025
|
if (existingSession && isOpenWithUrl) {
|
|
@@ -3618,6 +3665,7 @@ const HELP_EPILOGUE = `Browser commands (sent to this project's Chrome session):
|
|
|
3618
3665
|
|
|
3619
3666
|
Environment:
|
|
3620
3667
|
${ENV_KEY} connection URL; read from the nearest .rechrome/.env.local or .env.local
|
|
3668
|
+
RECHROME_PROFILE default browser profile selector; --profile overrides it
|
|
3621
3669
|
RECH_IDENTITY session key: worktree (default) | branch | cwd
|
|
3622
3670
|
RECH_TOKEN extension token for \`rech setup\` (same as --token)
|
|
3623
3671
|
RECH_SETUP_AGENT setup hints: codex | claude | none (auto-detected)
|
|
@@ -3808,7 +3856,7 @@ if (import.meta.main) {
|
|
|
3808
3856
|
if (separator !== -1) args = args.slice(0, separator);
|
|
3809
3857
|
try {
|
|
3810
3858
|
const extracted = extractGlobalProfileArg(args);
|
|
3811
|
-
profileSelector = extracted.selector;
|
|
3859
|
+
profileSelector = extracted.selector ?? (process.env.RECHROME_PROFILE?.trim() || undefined);
|
|
3812
3860
|
args = extracted.args;
|
|
3813
3861
|
} catch (err) {
|
|
3814
3862
|
console.error(err instanceof Error ? err.message : String(err));
|
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";
|
|
@@ -1509,11 +1510,7 @@ async function shareSet(snapshot: string[], opts: { listener?: string; local?: b
|
|
|
1509
1510
|
// A one-profile link names its profile, so the other machine needs no --profile.
|
|
1510
1511
|
const only = snapshot.length === 1 ? `?profile=${encodeURIComponent(snapshot[0])}` : "";
|
|
1511
1512
|
const local = `http://${listener.key}@${listenerAddress(listener)}${normalizePrefix(listener.prefix)}${only}`;
|
|
1512
|
-
|
|
1513
|
-
for (let i = 0; i < 20 && !ready; i++) {
|
|
1514
|
-
ready = await fetch(serviceUrl(local, "ping"), { headers: { Authorization: `Bearer ${listener.key}` }, signal: AbortSignal.timeout(1000) }).then(r => r.ok).catch(() => false);
|
|
1515
|
-
if (!ready) await Bun.sleep(250);
|
|
1516
|
-
}
|
|
1513
|
+
const ready = await waitForListener(listener);
|
|
1517
1514
|
if (!ready) console.error(`[rech] warning: listener "${name}" is not answering yet; check the daemon with rech status.`);
|
|
1518
1515
|
if (opts.tailscaleServe && !listener.publicUrl) {
|
|
1519
1516
|
const publicUrl = await exposeWithTailscaleServe(listener);
|
|
@@ -1570,6 +1567,32 @@ async function exposeWithTailscaleServe(listener: Listener): Promise<string | nu
|
|
|
1570
1567
|
return (await detectTailscaleServe(listener.port, prefix)).routeUrl;
|
|
1571
1568
|
}
|
|
1572
1569
|
|
|
1570
|
+
/** The daemon reloads listeners.json about every second: wait (up to ~5s) until this listener answers. */
|
|
1571
|
+
async function waitForListener(listener: Listener): Promise<boolean> {
|
|
1572
|
+
const url = `http://${listener.key}@${listenerAddress(listener)}${normalizePrefix(listener.prefix)}`;
|
|
1573
|
+
for (let i = 0; i < 20; i++) {
|
|
1574
|
+
if (await fetch(serviceUrl(url, "ping"), { headers: { Authorization: `Bearer ${listener.key}` }, signal: AbortSignal.timeout(1000) }).then(r => r.ok).catch(() => false)) return true;
|
|
1575
|
+
await Bun.sleep(250);
|
|
1576
|
+
}
|
|
1577
|
+
return false;
|
|
1578
|
+
}
|
|
1579
|
+
|
|
1580
|
+
/**
|
|
1581
|
+
* Ask how other machines will reach a link: "tailscale-serve", a detected network address
|
|
1582
|
+
* (plain HTTP), "127.0.0.1" for the user's own proxy, or `extra` choices; null when cancelled.
|
|
1583
|
+
*/
|
|
1584
|
+
async function askReachability(question: string, extra: { label: string; value: string }[] = []): Promise<string | null> {
|
|
1585
|
+
const serve = !!tailscaleBinary();
|
|
1586
|
+
// With Tailscale Serve on offer, a plain-HTTP Tailscale IP would only be a worse duplicate.
|
|
1587
|
+
const networks = (await detectListenChoices()).filter(c => c.kind !== "local" && !(serve && c.kind === "tailscale"));
|
|
1588
|
+
return promptChoice(question, [
|
|
1589
|
+
...(serve ? [{ label: "Tailscale: HTTPS, only your tailnet", value: "tailscale-serve" }] : []),
|
|
1590
|
+
...networks.map(c => ({ label: `${c.label.split(" — ")[0]} network: http://${c.address}, plain HTTP`, value: c.address })),
|
|
1591
|
+
{ label: "My own reverse proxy", value: "127.0.0.1" },
|
|
1592
|
+
...extra,
|
|
1593
|
+
], 0);
|
|
1594
|
+
}
|
|
1595
|
+
|
|
1573
1596
|
/**
|
|
1574
1597
|
* Give one profile its own link. In a terminal, ask how the other machines will reach it
|
|
1575
1598
|
* (Tailscale Serve, a detected network, or the user's own proxy); without one, create a
|
|
@@ -1580,14 +1603,7 @@ async function shareNewLink(profile: string, opts: { local?: boolean; save?: boo
|
|
|
1580
1603
|
const name = uniqueShareName(profileSlug(profile), (await requireListeners()).listeners, served);
|
|
1581
1604
|
let host = "127.0.0.1", tailscaleServe = false;
|
|
1582
1605
|
if (isInteractive()) {
|
|
1583
|
-
const
|
|
1584
|
-
// With Tailscale Serve on offer, a plain-HTTP Tailscale IP would only be a worse duplicate.
|
|
1585
|
-
const networks = (await detectListenChoices()).filter(c => c.kind !== "local" && !(serve && c.kind === "tailscale"));
|
|
1586
|
-
const how = await promptChoice(`How will your other machines reach it?`, [
|
|
1587
|
-
...(serve ? [{ label: "Tailscale: HTTPS, only your tailnet", value: "tailscale-serve" }] : []),
|
|
1588
|
-
...networks.map(c => ({ label: `${c.label.split(" — ")[0]} network: http://${c.address}, plain HTTP`, value: c.address })),
|
|
1589
|
-
{ label: "My own reverse proxy", value: "127.0.0.1" },
|
|
1590
|
-
], 0);
|
|
1606
|
+
const how = await askReachability(`How will your other machines reach it?`);
|
|
1591
1607
|
if (!how) throw new Error("Cancelled; nothing shared.");
|
|
1592
1608
|
tailscaleServe = how === "tailscale-serve";
|
|
1593
1609
|
host = tailscaleServe ? "127.0.0.1" : how;
|
|
@@ -1726,6 +1742,31 @@ async function printProfileUri(selector?: string, listener?: string, opts: { loc
|
|
|
1726
1742
|
const serve = await detectTailscaleServe(pending.port, normalizePrefix(pending.prefix));
|
|
1727
1743
|
if (serve.routeUrl && !serve.funnel) { pending.publicUrl = serve.routeUrl; await writeListeners(config); }
|
|
1728
1744
|
}
|
|
1745
|
+
// Still only reachable from this machine (no proxy recorded or detected): a link like that is
|
|
1746
|
+
// useless to hand out, so ask how other machines reach it, or say how to expose it.
|
|
1747
|
+
if (config && pending && pending.profiles !== "*" && !pending.publicUrl && isLoopback(pending.host) && !opts.local) {
|
|
1748
|
+
const steps = () => { for (const line of listenerNextSteps(pending, profile)) console.error(line); };
|
|
1749
|
+
if (!interactive) {
|
|
1750
|
+
console.error(`[rech] this link only works on this machine: listener "${pending.name}" is on ${listenerAddress(pending)} and no proxy is recorded.`);
|
|
1751
|
+
steps();
|
|
1752
|
+
} else {
|
|
1753
|
+
const KEEP = "\0keep";
|
|
1754
|
+
const how = await askReachability(`Link "${pending.name}" only works on this machine (${listenerAddress(pending)}). How will your other machines reach it?`,
|
|
1755
|
+
[{ label: "Nothing: keep it on this machine", value: KEEP }]);
|
|
1756
|
+
if (!how) throw cancelled();
|
|
1757
|
+
if (how === "tailscale-serve") {
|
|
1758
|
+
const routeUrl = await exposeWithTailscaleServe(pending);
|
|
1759
|
+
if (routeUrl) { pending.publicUrl = routeUrl; await writeListeners(config); }
|
|
1760
|
+
} else if (how === "127.0.0.1") steps();
|
|
1761
|
+
else if (how !== KEEP) {
|
|
1762
|
+
// Same key and prefix, now bound on that network; links already handed out change host.
|
|
1763
|
+
pending.host = how;
|
|
1764
|
+
await writeListeners(config);
|
|
1765
|
+
if (!(await waitForListener(pending))) console.error(`[rech] warning: listener "${pending.name}" is not answering on ${listenerAddress(pending)} yet; check the daemon with rech status.`);
|
|
1766
|
+
uri = profileConnectionUri(profile, undefined, config.listeners, pending.name);
|
|
1767
|
+
}
|
|
1768
|
+
}
|
|
1769
|
+
}
|
|
1729
1770
|
const publicUrl = pending?.publicUrl;
|
|
1730
1771
|
if (publicUrl && !opts.local) uri = rebaseConnectionUrl(publicUrl, uri);
|
|
1731
1772
|
console.log(uri);
|
|
@@ -1768,6 +1809,7 @@ async function callServe(
|
|
|
1768
1809
|
overrideEnv?: Record<string, string>,
|
|
1769
1810
|
precomputedIdentity?: { key: string; label: string; profile?: string },
|
|
1770
1811
|
throwOnFailure = false,
|
|
1812
|
+
upload?: UploadPayload,
|
|
1771
1813
|
): Promise<{ status: number; stdout: string; stderr: string; files?: string[]; existingSession?: boolean }> {
|
|
1772
1814
|
const { key, host, port, protocol, extensionId, extensionToken, profileDirectory, userDataDir, loadExtension } = parseUrl(url);
|
|
1773
1815
|
// Reuse the caller's identity when provided — computing it shells out to `git` several times,
|
|
@@ -1786,7 +1828,7 @@ async function callServe(
|
|
|
1786
1828
|
method: "POST",
|
|
1787
1829
|
headers: { "Content-Type": "application/json", Authorization: `Bearer ${key}` },
|
|
1788
1830
|
// dataDir is a client-local path; the daemon (possibly remote) only needs the session identity.
|
|
1789
|
-
body: JSON.stringify({ args, identity: { key: identity.key, label: identity.label, profile: identity.profile }, env }),
|
|
1831
|
+
body: JSON.stringify({ args, identity: { key: identity.key, label: identity.label, profile: identity.profile }, env, ...(upload ? { upload } : {}) }),
|
|
1790
1832
|
signal: AbortSignal.timeout(70_000),
|
|
1791
1833
|
}).catch(async (e) => {
|
|
1792
1834
|
if (throwOnFailure) throw new Error("Cannot reach the rechrome daemon. Check that it is running.");
|
|
@@ -1972,7 +2014,12 @@ async function run(url: string, args: string[], overrideEnv?: Record<string, str
|
|
|
1972
2014
|
|
|
1973
2015
|
const resolvedEnv = await getClientEnv({ extensionId, extensionToken, profileDirectory: effectiveProfile, userDataDir, loadExtension });
|
|
1974
2016
|
const effectiveEnv = { ...resolvedEnv, ...overrideEnv };
|
|
1975
|
-
|
|
2017
|
+
let upload: UploadPayload | undefined;
|
|
2018
|
+
if (args.find(a => !/^-s=[a-zA-Z0-9_-]{1,64}$/.test(a)) === "upload") {
|
|
2019
|
+
if (process.stdin.isTTY) throw new Error("upload reads stdin; redirect a PNG/SVG file with < icon.png");
|
|
2020
|
+
({ args, upload } = await prepareStdinUpload(args, process.stdin));
|
|
2021
|
+
}
|
|
2022
|
+
const { status, stdout, stderr, files, existingSession } = await callServe(url, args, overrideEnv, identity, false, upload);
|
|
1976
2023
|
|
|
1977
2024
|
const isOpenWithUrl = args[0] === "open" && args.length > 1;
|
|
1978
2025
|
if (existingSession && isOpenWithUrl) {
|
|
@@ -3618,6 +3665,7 @@ const HELP_EPILOGUE = `Browser commands (sent to this project's Chrome session):
|
|
|
3618
3665
|
|
|
3619
3666
|
Environment:
|
|
3620
3667
|
${ENV_KEY} connection URL; read from the nearest .rechrome/.env.local or .env.local
|
|
3668
|
+
RECHROME_PROFILE default browser profile selector; --profile overrides it
|
|
3621
3669
|
RECH_IDENTITY session key: worktree (default) | branch | cwd
|
|
3622
3670
|
RECH_TOKEN extension token for \`rech setup\` (same as --token)
|
|
3623
3671
|
RECH_SETUP_AGENT setup hints: codex | claude | none (auto-detected)
|
|
@@ -3808,7 +3856,7 @@ if (import.meta.main) {
|
|
|
3808
3856
|
if (separator !== -1) args = args.slice(0, separator);
|
|
3809
3857
|
try {
|
|
3810
3858
|
const extracted = extractGlobalProfileArg(args);
|
|
3811
|
-
profileSelector = extracted.selector;
|
|
3859
|
+
profileSelector = extracted.selector ?? (process.env.RECHROME_PROFILE?.trim() || undefined);
|
|
3812
3860
|
args = extracted.args;
|
|
3813
3861
|
} catch (err) {
|
|
3814
3862
|
console.error(err instanceof Error ? err.message : String(err));
|