tabwright 1.0.0 → 1.0.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.
- package/dist/aria-snapshot.d.ts +0 -1
- package/dist/aria-snapshot.js +9 -1
- package/dist/assets/cursors/screen-studio/pointer-macos-tahoe-data-url.d.ts +0 -1
- package/dist/assets/cursors/screen-studio/pointer-macos-tahoe-data-url.js +0 -1
- package/dist/bippy.js +1 -1
- package/dist/browser-config.d.ts +0 -1
- package/dist/browser-config.js +0 -1
- package/dist/browser-install.d.ts +0 -1
- package/dist/browser-install.js +0 -1
- package/dist/browser-launch.d.ts +0 -1
- package/dist/browser-launch.js +0 -1
- package/dist/builtin-capabilities.d.ts +0 -1
- package/dist/builtin-capabilities.js +0 -1
- package/dist/capability-agent-skill.d.ts +0 -1
- package/dist/capability-agent-skill.js +0 -1
- package/dist/capability-auth-state.d.ts +0 -1
- package/dist/capability-auth-state.js +0 -1
- package/dist/capability-auth.d.ts +0 -1
- package/dist/capability-auth.js +0 -1
- package/dist/capability-options.d.ts +0 -1
- package/dist/capability-options.js +0 -1
- package/dist/capability-package.d.ts +0 -1
- package/dist/capability-package.js +0 -1
- package/dist/capability-registry.d.ts +0 -1
- package/dist/capability-registry.js +0 -1
- package/dist/capability-runner.d.ts +0 -1
- package/dist/capability-runner.js +0 -1
- package/dist/capability-studio.d.ts +0 -1
- package/dist/capability-studio.js +0 -1
- package/dist/cdp-log.d.ts +0 -1
- package/dist/cdp-log.js +0 -1
- package/dist/cdp-relay.d.ts +0 -1
- package/dist/cdp-relay.js +0 -1
- package/dist/cdp-session.d.ts +0 -1
- package/dist/cdp-session.js +0 -1
- package/dist/cdp-types.d.ts +0 -1
- package/dist/cdp-types.js +0 -1
- package/dist/chrome-discovery.d.ts +0 -1
- package/dist/chrome-discovery.js +0 -1
- package/dist/clean-html.d.ts +0 -1
- package/dist/clean-html.js +0 -1
- package/dist/cli.d.ts +0 -1
- package/dist/cli.js +9 -2
- package/dist/cloud-client.d.ts +0 -1
- package/dist/cloud-client.js +0 -1
- package/dist/create-logger.d.ts +0 -1
- package/dist/create-logger.js +0 -1
- package/dist/debugger-examples-types.d.ts +0 -1
- package/dist/debugger-examples-types.js +0 -1
- package/dist/debugger-examples.d.ts +0 -1
- package/dist/debugger-examples.js +0 -1
- package/dist/debugger.d.ts +0 -1
- package/dist/debugger.js +0 -1
- package/dist/diff-utils.d.ts +0 -1
- package/dist/diff-utils.js +0 -1
- package/dist/doctor.d.ts +0 -1
- package/dist/doctor.js +5 -7
- package/dist/editor-examples.d.ts +0 -1
- package/dist/editor-examples.js +0 -1
- package/dist/editor.d.ts +0 -1
- package/dist/editor.js +0 -1
- package/dist/env-compat.d.ts +0 -1
- package/dist/env-compat.js +0 -1
- package/dist/executor.d.ts +0 -1
- package/dist/executor.js +1 -2
- package/dist/extension/background.js +7 -3
- package/dist/extension/manifest.json +1 -1
- package/dist/ghost-browser.d.ts +0 -1
- package/dist/ghost-browser.js +0 -1
- package/dist/ghost-cursor-controller.d.ts +0 -1
- package/dist/ghost-cursor-controller.js +0 -1
- package/dist/ghost-cursor.d.ts +0 -1
- package/dist/ghost-cursor.js +0 -1
- package/dist/htmlrewrite.d.ts +0 -1
- package/dist/htmlrewrite.js +0 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.js +0 -1
- package/dist/kill-port.d.ts +0 -1
- package/dist/kill-port.js +0 -1
- package/dist/kitty-graphics.d.ts +0 -1
- package/dist/kitty-graphics.js +0 -1
- package/dist/mcp.d.ts +0 -1
- package/dist/mcp.js +0 -1
- package/dist/package-paths.d.ts +0 -1
- package/dist/package-paths.js +0 -1
- package/dist/page-markdown.d.ts +0 -1
- package/dist/page-markdown.js +0 -1
- package/dist/performance-examples.d.ts +0 -1
- package/dist/performance-examples.js +0 -1
- package/dist/playwright-import.d.ts +0 -1
- package/dist/playwright-import.js +0 -1
- package/dist/product-paths.d.ts +0 -1
- package/dist/product-paths.js +0 -1
- package/dist/protocol.d.ts +0 -1
- package/dist/protocol.js +0 -1
- package/dist/react-source.d.ts +0 -1
- package/dist/react-source.js +0 -1
- package/dist/readability.js +1 -1
- package/dist/relay-client.d.ts +0 -1
- package/dist/relay-client.js +0 -1
- package/dist/relay-state.d.ts +0 -1
- package/dist/relay-state.js +0 -1
- package/dist/replay-ai-index.d.ts +0 -1
- package/dist/replay-ai-index.js +0 -1
- package/dist/replay-eval.d.ts +0 -1
- package/dist/replay-eval.js +0 -1
- package/dist/replay-handoff.d.ts +0 -1
- package/dist/replay-handoff.js +0 -1
- package/dist/replay-workflow-compiler.d.ts +0 -1
- package/dist/replay-workflow-compiler.js +0 -1
- package/dist/rrweb-recording-relay.d.ts +0 -1
- package/dist/rrweb-recording-relay.js +0 -1
- package/dist/rrweb-recording.d.ts +0 -1
- package/dist/rrweb-recording.js +0 -1
- package/dist/scoped-fs.d.ts +0 -1
- package/dist/scoped-fs.js +0 -1
- package/dist/selector-generator.js +1 -1
- package/dist/start-relay-server.d.ts +0 -1
- package/dist/start-relay-server.js +0 -1
- package/dist/styles-examples.d.ts +0 -1
- package/dist/styles-examples.js +0 -1
- package/dist/styles.d.ts +0 -1
- package/dist/styles.js +0 -1
- package/dist/tabwright-agent-skill.d.ts +0 -1
- package/dist/tabwright-agent-skill.js +0 -1
- package/dist/test-declarations.d.ts +0 -1
- package/dist/test-declarations.js +0 -1
- package/dist/utils.d.ts +0 -1
- package/dist/utils.js +2 -2
- package/dist/wait-for-page-load.d.ts +0 -1
- package/dist/wait-for-page-load.js +0 -1
- package/dist/workflow-capability.d.ts +0 -1
- package/dist/workflow-capability.js +0 -1
- package/package.json +9 -4
- package/readme.md +35 -0
- package/dist/aria-snapshot.d.ts.map +0 -1
- package/dist/aria-snapshot.js.map +0 -1
- package/dist/aria-snapshot.test.d.ts +0 -2
- package/dist/aria-snapshot.test.d.ts.map +0 -1
- package/dist/aria-snapshot.test.js +0 -270
- package/dist/aria-snapshot.test.js.map +0 -1
- package/dist/aria-snapshot.unit.test.d.ts +0 -2
- package/dist/aria-snapshot.unit.test.d.ts.map +0 -1
- package/dist/aria-snapshot.unit.test.js +0 -542
- package/dist/aria-snapshot.unit.test.js.map +0 -1
- package/dist/assets/cursors/screen-studio/pointer-macos-tahoe-data-url.d.ts.map +0 -1
- package/dist/assets/cursors/screen-studio/pointer-macos-tahoe-data-url.js.map +0 -1
- package/dist/browser-config.d.ts.map +0 -1
- package/dist/browser-config.js.map +0 -1
- package/dist/browser-install.d.ts.map +0 -1
- package/dist/browser-install.js.map +0 -1
- package/dist/browser-launch.d.ts.map +0 -1
- package/dist/browser-launch.js.map +0 -1
- package/dist/builtin-capabilities.d.ts.map +0 -1
- package/dist/builtin-capabilities.js.map +0 -1
- package/dist/capability-agent-skill.d.ts.map +0 -1
- package/dist/capability-agent-skill.js.map +0 -1
- package/dist/capability-auth-state.d.ts.map +0 -1
- package/dist/capability-auth-state.js.map +0 -1
- package/dist/capability-auth.d.ts.map +0 -1
- package/dist/capability-auth.js.map +0 -1
- package/dist/capability-cli-confirmation.test.d.ts +0 -2
- package/dist/capability-cli-confirmation.test.d.ts.map +0 -1
- package/dist/capability-cli-confirmation.test.js +0 -79
- package/dist/capability-cli-confirmation.test.js.map +0 -1
- package/dist/capability-options.d.ts.map +0 -1
- package/dist/capability-options.js.map +0 -1
- package/dist/capability-options.test.d.ts +0 -2
- package/dist/capability-options.test.d.ts.map +0 -1
- package/dist/capability-options.test.js +0 -81
- package/dist/capability-options.test.js.map +0 -1
- package/dist/capability-package.d.ts.map +0 -1
- package/dist/capability-package.js.map +0 -1
- package/dist/capability-package.test.d.ts +0 -2
- package/dist/capability-package.test.d.ts.map +0 -1
- package/dist/capability-package.test.js +0 -179
- package/dist/capability-package.test.js.map +0 -1
- package/dist/capability-registry.d.ts.map +0 -1
- package/dist/capability-registry.js.map +0 -1
- package/dist/capability-registry.test.d.ts +0 -2
- package/dist/capability-registry.test.d.ts.map +0 -1
- package/dist/capability-registry.test.js +0 -1683
- package/dist/capability-registry.test.js.map +0 -1
- package/dist/capability-runner.d.ts.map +0 -1
- package/dist/capability-runner.js.map +0 -1
- package/dist/capability-search-relevance.test.d.ts +0 -2
- package/dist/capability-search-relevance.test.d.ts.map +0 -1
- package/dist/capability-search-relevance.test.js +0 -67
- package/dist/capability-search-relevance.test.js.map +0 -1
- package/dist/capability-studio.d.ts.map +0 -1
- package/dist/capability-studio.js.map +0 -1
- package/dist/capability-studio.test.d.ts +0 -2
- package/dist/capability-studio.test.d.ts.map +0 -1
- package/dist/capability-studio.test.js +0 -41
- package/dist/capability-studio.test.js.map +0 -1
- package/dist/cdp-log.d.ts.map +0 -1
- package/dist/cdp-log.js.map +0 -1
- package/dist/cdp-log.test.d.ts +0 -2
- package/dist/cdp-log.test.d.ts.map +0 -1
- package/dist/cdp-log.test.js +0 -109
- package/dist/cdp-log.test.js.map +0 -1
- package/dist/cdp-relay.d.ts.map +0 -1
- package/dist/cdp-relay.js.map +0 -1
- package/dist/cdp-session.d.ts.map +0 -1
- package/dist/cdp-session.js.map +0 -1
- package/dist/cdp-types.d.ts.map +0 -1
- package/dist/cdp-types.js.map +0 -1
- package/dist/channel-owner-inspect.test.d.ts +0 -2
- package/dist/channel-owner-inspect.test.d.ts.map +0 -1
- package/dist/channel-owner-inspect.test.js +0 -75
- package/dist/channel-owner-inspect.test.js.map +0 -1
- package/dist/chrome-discovery.d.ts.map +0 -1
- package/dist/chrome-discovery.js.map +0 -1
- package/dist/chrome-discovery.test.d.ts +0 -2
- package/dist/chrome-discovery.test.d.ts.map +0 -1
- package/dist/chrome-discovery.test.js +0 -41
- package/dist/chrome-discovery.test.js.map +0 -1
- package/dist/clean-html.d.ts.map +0 -1
- package/dist/clean-html.js.map +0 -1
- package/dist/cli-help.test.d.ts +0 -2
- package/dist/cli-help.test.d.ts.map +0 -1
- package/dist/cli-help.test.js +0 -98
- package/dist/cli-help.test.js.map +0 -1
- package/dist/cli.d.ts.map +0 -1
- package/dist/cli.js.map +0 -1
- package/dist/cloud-client.d.ts.map +0 -1
- package/dist/cloud-client.js.map +0 -1
- package/dist/create-logger.d.ts.map +0 -1
- package/dist/create-logger.js.map +0 -1
- package/dist/debugger-examples-types.d.ts.map +0 -1
- package/dist/debugger-examples-types.js.map +0 -1
- package/dist/debugger-examples.d.ts.map +0 -1
- package/dist/debugger-examples.js.map +0 -1
- package/dist/debugger.d.ts.map +0 -1
- package/dist/debugger.js.map +0 -1
- package/dist/diff-utils.d.ts.map +0 -1
- package/dist/diff-utils.js.map +0 -1
- package/dist/diff-utils.test.d.ts +0 -2
- package/dist/diff-utils.test.d.ts.map +0 -1
- package/dist/diff-utils.test.js +0 -137
- package/dist/diff-utils.test.js.map +0 -1
- package/dist/doctor.d.ts.map +0 -1
- package/dist/doctor.js.map +0 -1
- package/dist/doctor.test.d.ts +0 -2
- package/dist/doctor.test.d.ts.map +0 -1
- package/dist/doctor.test.js +0 -208
- package/dist/doctor.test.js.map +0 -1
- package/dist/editor-examples.d.ts.map +0 -1
- package/dist/editor-examples.js.map +0 -1
- package/dist/editor.d.ts.map +0 -1
- package/dist/editor.js.map +0 -1
- package/dist/env-compat.d.ts.map +0 -1
- package/dist/env-compat.js.map +0 -1
- package/dist/executor.d.ts.map +0 -1
- package/dist/executor.js.map +0 -1
- package/dist/executor.unit.test.d.ts +0 -2
- package/dist/executor.unit.test.d.ts.map +0 -1
- package/dist/executor.unit.test.js +0 -143
- package/dist/executor.unit.test.js.map +0 -1
- package/dist/extension-connection.test.d.ts +0 -2
- package/dist/extension-connection.test.d.ts.map +0 -1
- package/dist/extension-connection.test.js +0 -708
- package/dist/extension-connection.test.js.map +0 -1
- package/dist/extension-icon-warning.test.d.ts +0 -2
- package/dist/extension-icon-warning.test.d.ts.map +0 -1
- package/dist/extension-icon-warning.test.js +0 -33
- package/dist/extension-icon-warning.test.js.map +0 -1
- package/dist/ghost-browser.d.ts.map +0 -1
- package/dist/ghost-browser.js.map +0 -1
- package/dist/ghost-cursor-controller.d.ts.map +0 -1
- package/dist/ghost-cursor-controller.js.map +0 -1
- package/dist/ghost-cursor.d.ts.map +0 -1
- package/dist/ghost-cursor.js.map +0 -1
- package/dist/htmlrewrite.d.ts.map +0 -1
- package/dist/htmlrewrite.js.map +0 -1
- package/dist/htmlrewrite.test.d.ts +0 -2
- package/dist/htmlrewrite.test.d.ts.map +0 -1
- package/dist/htmlrewrite.test.js +0 -7975
- package/dist/htmlrewrite.test.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/kill-port.d.ts.map +0 -1
- package/dist/kill-port.js.map +0 -1
- package/dist/kitty-graphics.d.ts.map +0 -1
- package/dist/kitty-graphics.js.map +0 -1
- package/dist/kitty-graphics.test.d.ts +0 -2
- package/dist/kitty-graphics.test.d.ts.map +0 -1
- package/dist/kitty-graphics.test.js +0 -125
- package/dist/kitty-graphics.test.js.map +0 -1
- package/dist/locator-selector.test.d.ts +0 -2
- package/dist/locator-selector.test.d.ts.map +0 -1
- package/dist/locator-selector.test.js +0 -98
- package/dist/locator-selector.test.js.map +0 -1
- package/dist/mcp-client.d.ts +0 -20
- package/dist/mcp-client.d.ts.map +0 -1
- package/dist/mcp-client.js +0 -56
- package/dist/mcp-client.js.map +0 -1
- package/dist/mcp.d.ts.map +0 -1
- package/dist/mcp.js.map +0 -1
- package/dist/on-mouse-action.test.d.ts +0 -2
- package/dist/on-mouse-action.test.d.ts.map +0 -1
- package/dist/on-mouse-action.test.js +0 -180
- package/dist/on-mouse-action.test.js.map +0 -1
- package/dist/options-page.test.d.ts +0 -2
- package/dist/options-page.test.d.ts.map +0 -1
- package/dist/options-page.test.js +0 -773
- package/dist/options-page.test.js.map +0 -1
- package/dist/package-paths.d.ts.map +0 -1
- package/dist/package-paths.js.map +0 -1
- package/dist/page-markdown.d.ts.map +0 -1
- package/dist/page-markdown.js.map +0 -1
- package/dist/performance-examples.d.ts.map +0 -1
- package/dist/performance-examples.js.map +0 -1
- package/dist/playwright-import.d.ts.map +0 -1
- package/dist/playwright-import.js.map +0 -1
- package/dist/popup-relocation.test.d.ts +0 -7
- package/dist/popup-relocation.test.d.ts.map +0 -1
- package/dist/popup-relocation.test.js +0 -139
- package/dist/popup-relocation.test.js.map +0 -1
- package/dist/product-paths.d.ts.map +0 -1
- package/dist/product-paths.js.map +0 -1
- package/dist/product-paths.test.d.ts +0 -2
- package/dist/product-paths.test.d.ts.map +0 -1
- package/dist/product-paths.test.js +0 -39
- package/dist/product-paths.test.js.map +0 -1
- package/dist/protocol.d.ts.map +0 -1
- package/dist/protocol.js.map +0 -1
- package/dist/protocol.test.d.ts +0 -2
- package/dist/protocol.test.d.ts.map +0 -1
- package/dist/protocol.test.js +0 -31
- package/dist/protocol.test.js.map +0 -1
- package/dist/react-source.d.ts.map +0 -1
- package/dist/react-source.js.map +0 -1
- package/dist/relay-client.d.ts.map +0 -1
- package/dist/relay-client.js.map +0 -1
- package/dist/relay-client.test.d.ts +0 -2
- package/dist/relay-client.test.d.ts.map +0 -1
- package/dist/relay-client.test.js +0 -305
- package/dist/relay-client.test.js.map +0 -1
- package/dist/relay-core.test.d.ts +0 -2
- package/dist/relay-core.test.d.ts.map +0 -1
- package/dist/relay-core.test.js +0 -1427
- package/dist/relay-core.test.js.map +0 -1
- package/dist/relay-navigation.test.d.ts +0 -2
- package/dist/relay-navigation.test.d.ts.map +0 -1
- package/dist/relay-navigation.test.js +0 -661
- package/dist/relay-navigation.test.js.map +0 -1
- package/dist/relay-session.test.d.ts +0 -2
- package/dist/relay-session.test.d.ts.map +0 -1
- package/dist/relay-session.test.js +0 -1121
- package/dist/relay-session.test.js.map +0 -1
- package/dist/relay-state.d.ts.map +0 -1
- package/dist/relay-state.js.map +0 -1
- package/dist/relay-state.test.d.ts +0 -2
- package/dist/relay-state.test.d.ts.map +0 -1
- package/dist/relay-state.test.js +0 -594
- package/dist/relay-state.test.js.map +0 -1
- package/dist/replay-ai-index.d.ts.map +0 -1
- package/dist/replay-ai-index.js.map +0 -1
- package/dist/replay-ai-index.test.d.ts +0 -2
- package/dist/replay-ai-index.test.d.ts.map +0 -1
- package/dist/replay-ai-index.test.js +0 -255
- package/dist/replay-ai-index.test.js.map +0 -1
- package/dist/replay-cli.test.d.ts +0 -2
- package/dist/replay-cli.test.d.ts.map +0 -1
- package/dist/replay-cli.test.js +0 -275
- package/dist/replay-cli.test.js.map +0 -1
- package/dist/replay-eval.d.ts.map +0 -1
- package/dist/replay-eval.js.map +0 -1
- package/dist/replay-handoff.d.ts.map +0 -1
- package/dist/replay-handoff.js.map +0 -1
- package/dist/replay-handoff.test.d.ts +0 -2
- package/dist/replay-handoff.test.d.ts.map +0 -1
- package/dist/replay-handoff.test.js +0 -123
- package/dist/replay-handoff.test.js.map +0 -1
- package/dist/replay-workflow-compiler.d.ts.map +0 -1
- package/dist/replay-workflow-compiler.js.map +0 -1
- package/dist/replay-workflow-compiler.test.d.ts +0 -2
- package/dist/replay-workflow-compiler.test.d.ts.map +0 -1
- package/dist/replay-workflow-compiler.test.js +0 -223
- package/dist/replay-workflow-compiler.test.js.map +0 -1
- package/dist/rrweb-recording-relay.d.ts.map +0 -1
- package/dist/rrweb-recording-relay.js.map +0 -1
- package/dist/rrweb-recording-relay.test.d.ts +0 -2
- package/dist/rrweb-recording-relay.test.d.ts.map +0 -1
- package/dist/rrweb-recording-relay.test.js +0 -85
- package/dist/rrweb-recording-relay.test.js.map +0 -1
- package/dist/rrweb-recording.d.ts.map +0 -1
- package/dist/rrweb-recording.js.map +0 -1
- package/dist/scoped-fs.d.ts.map +0 -1
- package/dist/scoped-fs.js.map +0 -1
- package/dist/scoped-fs.test.d.ts +0 -5
- package/dist/scoped-fs.test.d.ts.map +0 -1
- package/dist/scoped-fs.test.js +0 -73
- package/dist/scoped-fs.test.js.map +0 -1
- package/dist/skill-stub.test.d.ts +0 -2
- package/dist/skill-stub.test.d.ts.map +0 -1
- package/dist/skill-stub.test.js +0 -22
- package/dist/skill-stub.test.js.map +0 -1
- package/dist/snapshot-tools.test.d.ts +0 -2
- package/dist/snapshot-tools.test.d.ts.map +0 -1
- package/dist/snapshot-tools.test.js +0 -856
- package/dist/snapshot-tools.test.js.map +0 -1
- package/dist/start-relay-server.d.ts.map +0 -1
- package/dist/start-relay-server.js.map +0 -1
- package/dist/styles-examples.d.ts.map +0 -1
- package/dist/styles-examples.js.map +0 -1
- package/dist/styles.d.ts.map +0 -1
- package/dist/styles.js.map +0 -1
- package/dist/tabwright-agent-skill.d.ts.map +0 -1
- package/dist/tabwright-agent-skill.js.map +0 -1
- package/dist/tabwright-agent-skill.test.d.ts +0 -2
- package/dist/tabwright-agent-skill.test.d.ts.map +0 -1
- package/dist/tabwright-agent-skill.test.js +0 -51
- package/dist/tabwright-agent-skill.test.js.map +0 -1
- package/dist/test-declarations.d.ts.map +0 -1
- package/dist/test-declarations.js.map +0 -1
- package/dist/test-utils.d.ts +0 -69
- package/dist/test-utils.d.ts.map +0 -1
- package/dist/test-utils.js +0 -448
- package/dist/test-utils.js.map +0 -1
- package/dist/test-utils.test.d.ts +0 -2
- package/dist/test-utils.test.d.ts.map +0 -1
- package/dist/test-utils.test.js +0 -55
- package/dist/test-utils.test.js.map +0 -1
- package/dist/utils.d.ts.map +0 -1
- package/dist/utils.js.map +0 -1
- package/dist/wait-for-page-load.d.ts.map +0 -1
- package/dist/wait-for-page-load.js.map +0 -1
- package/dist/workflow-capability.d.ts.map +0 -1
- package/dist/workflow-capability.js.map +0 -1
- package/dist/workflow-script-flow.test.d.ts +0 -2
- package/dist/workflow-script-flow.test.d.ts.map +0 -1
- package/dist/workflow-script-flow.test.js +0 -285
- package/dist/workflow-script-flow.test.js.map +0 -1
- package/src/__snapshots__/x.com.processed.html +0 -1003
- package/src/__snapshots__/x.com.processed.withStyles.html +0 -2720
- package/src/a11y-client.ts +0 -241
- package/src/aria-snapshot.test.ts +0 -311
- package/src/aria-snapshot.ts +0 -1681
- package/src/aria-snapshot.unit.test.ts +0 -615
- package/src/aria-snapshots/github-interactive.txt +0 -193
- package/src/aria-snapshots/github-raw.txt +0 -309
- package/src/aria-snapshots/hackernews-interactive.txt +0 -477
- package/src/aria-snapshots/hackernews-raw.txt +0 -428
- package/src/aria-snapshots/prosemirror-interactive.txt +0 -66
- package/src/aria-snapshots/prosemirror-raw.txt +0 -145
- package/src/assets/aria-labels-hacker-news.png +0 -0
- package/src/assets/aria-labels-old-reddit.png +0 -0
- package/src/assets/cursors/screen-studio/pointer-macos-tahoe-data-url.ts +0 -5
- package/src/assets/cursors/screen-studio/pointer-macos-tahoe.svg +0 -18
- package/src/assets/x.com.html +0 -32946
- package/src/browser-config.ts +0 -179
- package/src/browser-install.ts +0 -284
- package/src/browser-launch.ts +0 -75
- package/src/builtin-capabilities.ts +0 -2765
- package/src/capability-agent-skill.ts +0 -305
- package/src/capability-auth-state.ts +0 -197
- package/src/capability-auth.ts +0 -249
- package/src/capability-cli-confirmation.test.ts +0 -90
- package/src/capability-options.test.ts +0 -89
- package/src/capability-options.ts +0 -57
- package/src/capability-package.test.ts +0 -204
- package/src/capability-package.ts +0 -555
- package/src/capability-registry.test.ts +0 -1905
- package/src/capability-registry.ts +0 -1234
- package/src/capability-runner.ts +0 -801
- package/src/capability-search-relevance.test.ts +0 -73
- package/src/capability-studio.test.ts +0 -45
- package/src/capability-studio.ts +0 -641
- package/src/cdp-log.test.ts +0 -131
- package/src/cdp-log.ts +0 -112
- package/src/cdp-relay.ts +0 -2944
- package/src/cdp-session.ts +0 -77
- package/src/cdp-types.ts +0 -158
- package/src/channel-owner-inspect.test.ts +0 -94
- package/src/chrome-discovery.test.ts +0 -50
- package/src/chrome-discovery.ts +0 -220
- package/src/clean-html.ts +0 -141
- package/src/cli-help.test.ts +0 -123
- package/src/cli.ts +0 -3181
- package/src/cloud-client.ts +0 -179
- package/src/create-logger.ts +0 -38
- package/src/debugger-examples-types.ts +0 -16
- package/src/debugger-examples.ts +0 -66
- package/src/debugger.ts +0 -708
- package/src/diff-utils.test.ts +0 -152
- package/src/diff-utils.ts +0 -70
- package/src/doctor.test.ts +0 -244
- package/src/doctor.ts +0 -321
- package/src/editor-examples.ts +0 -158
- package/src/editor.ts +0 -426
- package/src/env-compat.ts +0 -28
- package/src/executor.ts +0 -1824
- package/src/executor.unit.test.ts +0 -168
- package/src/extension-connection.test.ts +0 -855
- package/src/extension-icon-warning.test.ts +0 -45
- package/src/ghost-browser.ts +0 -149
- package/src/ghost-cursor-client.ts +0 -494
- package/src/ghost-cursor-controller.ts +0 -129
- package/src/ghost-cursor.ts +0 -123
- package/src/htmlrewrite.test.ts +0 -8008
- package/src/htmlrewrite.ts +0 -390
- package/src/index.ts +0 -53
- package/src/kill-port.ts +0 -219
- package/src/kitty-graphics.test.ts +0 -139
- package/src/kitty-graphics.ts +0 -79
- package/src/locator-selector.test.ts +0 -119
- package/src/mcp-client.ts +0 -78
- package/src/mcp.ts +0 -629
- package/src/on-mouse-action.test.ts +0 -226
- package/src/options-page.test.ts +0 -839
- package/src/package-paths.ts +0 -38
- package/src/page-markdown.ts +0 -240
- package/src/performance-examples.ts +0 -186
- package/src/playwright-import.ts +0 -59
- package/src/popup-relocation.test.ts +0 -163
- package/src/product-paths.test.ts +0 -47
- package/src/product-paths.ts +0 -28
- package/src/protocol.test.ts +0 -52
- package/src/protocol.ts +0 -351
- package/src/react-source.ts +0 -379
- package/src/relay-client.test.ts +0 -375
- package/src/relay-client.ts +0 -572
- package/src/relay-core.test.ts +0 -1603
- package/src/relay-navigation.test.ts +0 -790
- package/src/relay-session.test.ts +0 -1375
- package/src/relay-state.test.ts +0 -729
- package/src/relay-state.ts +0 -561
- package/src/replay-ai-index.test.ts +0 -278
- package/src/replay-ai-index.ts +0 -872
- package/src/replay-cli.test.ts +0 -325
- package/src/replay-eval.ts +0 -1039
- package/src/replay-handoff.test.ts +0 -163
- package/src/replay-handoff.ts +0 -109
- package/src/replay-workflow-compiler.test.ts +0 -250
- package/src/replay-workflow-compiler.ts +0 -700
- package/src/resource.md +0 -409
- package/src/rrweb-recording-relay.test.ts +0 -99
- package/src/rrweb-recording-relay.ts +0 -400
- package/src/rrweb-recording.ts +0 -322
- package/src/scoped-fs.test.ts +0 -80
- package/src/scoped-fs.ts +0 -420
- package/src/skill-stub.test.ts +0 -24
- package/src/snapshot-tools.test.ts +0 -1017
- package/src/snapshots/hacker-news-accessibility-full.md +0 -81
- package/src/snapshots/hacker-news-accessibility-interactive.md +0 -43
- package/src/snapshots/page-markdown-output.txt +0 -16
- package/src/snapshots/shadcn-ui-accessibility-full.md +0 -201
- package/src/snapshots/shadcn-ui-accessibility-interactive.md +0 -109
- package/src/start-relay-server.ts +0 -69
- package/src/styles-examples.ts +0 -84
- package/src/styles.ts +0 -343
- package/src/tabwright-agent-skill.test.ts +0 -61
- package/src/tabwright-agent-skill.ts +0 -105
- package/src/test-declarations.ts +0 -13
- package/src/test-utils.test.ts +0 -70
- package/src/test-utils.ts +0 -566
- package/src/utils.ts +0 -78
- package/src/wait-for-page-load.ts +0 -198
- package/src/workflow-capability.ts +0 -417
- package/src/workflow-script-flow.test.ts +0 -388
package/src/test-utils.ts
DELETED
|
@@ -1,566 +0,0 @@
|
|
|
1
|
-
import { exec } from 'node:child_process'
|
|
2
|
-
import { promisify } from 'node:util'
|
|
3
|
-
import http from 'node:http'
|
|
4
|
-
import net from 'node:net'
|
|
5
|
-
import { chromium, type BrowserContext } from '@xmorse/playwright-core'
|
|
6
|
-
import path from 'node:path'
|
|
7
|
-
import fs from 'node:fs'
|
|
8
|
-
import os from 'node:os'
|
|
9
|
-
import { startTabwrightCDPRelayServer, type RelayServer } from './cdp-relay.js'
|
|
10
|
-
import { createFileLogger } from './create-logger.js'
|
|
11
|
-
import { killPortProcess } from './kill-port.js'
|
|
12
|
-
|
|
13
|
-
const execAsync = promisify(exec)
|
|
14
|
-
const extensionBuildQueues: Map<string, Promise<void>> = new Map()
|
|
15
|
-
const EXTENSION_SERVICE_WORKER_TIMEOUT_MS = 15_000
|
|
16
|
-
|
|
17
|
-
export function getLocalChromeExecutable(): string | undefined {
|
|
18
|
-
const candidates = [
|
|
19
|
-
process.env.PLAYWRIGHT_CHROME_EXECUTABLE,
|
|
20
|
-
'/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',
|
|
21
|
-
'/Applications/Chromium.app/Contents/MacOS/Chromium',
|
|
22
|
-
'/usr/bin/google-chrome',
|
|
23
|
-
'/usr/bin/google-chrome-stable',
|
|
24
|
-
'/usr/bin/chromium',
|
|
25
|
-
'/usr/bin/chromium-browser',
|
|
26
|
-
'C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe',
|
|
27
|
-
'C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe',
|
|
28
|
-
].filter((candidate): candidate is string => {
|
|
29
|
-
return Boolean(candidate)
|
|
30
|
-
})
|
|
31
|
-
|
|
32
|
-
return candidates.find((candidate) => {
|
|
33
|
-
return fs.existsSync(candidate)
|
|
34
|
-
})
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
export function getLegacyExtensionLaunchArgs({ extensionPaths }: { extensionPaths: string[] }): string[] {
|
|
38
|
-
const resolvedExtensionPaths = extensionPaths.map((extensionPath) => {
|
|
39
|
-
return path.resolve(extensionPath)
|
|
40
|
-
})
|
|
41
|
-
const legacyExtensionPaths = resolvedExtensionPaths.join(',')
|
|
42
|
-
|
|
43
|
-
return [
|
|
44
|
-
`--disable-extensions-except=${legacyExtensionPaths}`,
|
|
45
|
-
`--load-extension=${legacyExtensionPaths}`,
|
|
46
|
-
]
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
export function isExtensionLoadUnavailableError(error: unknown): boolean {
|
|
50
|
-
const message = error instanceof Error ? error.message : String(error)
|
|
51
|
-
return (
|
|
52
|
-
message.includes('Method not found') ||
|
|
53
|
-
message.includes("'Extensions.loadUnpacked' wasn't found") ||
|
|
54
|
-
message.includes('-32601')
|
|
55
|
-
)
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
async function loadUnpackedExtensionsThroughCdp({
|
|
59
|
-
browserContext,
|
|
60
|
-
extensionPaths,
|
|
61
|
-
}: {
|
|
62
|
-
browserContext: BrowserContext
|
|
63
|
-
extensionPaths: string[]
|
|
64
|
-
}): Promise<void> {
|
|
65
|
-
const browser = browserContext.browser()
|
|
66
|
-
if (!browser) {
|
|
67
|
-
throw new Error('Persistent browser context has no browser connection')
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
const session = await browser.newBrowserCDPSession()
|
|
71
|
-
try {
|
|
72
|
-
await Promise.all(
|
|
73
|
-
extensionPaths.map(async (extensionPath) => {
|
|
74
|
-
await session.send('Extensions.loadUnpacked', { path: path.resolve(extensionPath) })
|
|
75
|
-
}),
|
|
76
|
-
)
|
|
77
|
-
} finally {
|
|
78
|
-
await session.detach().catch((error: unknown) => {
|
|
79
|
-
console.error('Failed to detach test extension CDP session:', error)
|
|
80
|
-
})
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
async function launchTestBrowser({
|
|
85
|
-
userDataDir,
|
|
86
|
-
args,
|
|
87
|
-
}: {
|
|
88
|
-
userDataDir: string
|
|
89
|
-
args: string[]
|
|
90
|
-
}): Promise<BrowserContext> {
|
|
91
|
-
const chromeExecutable = getLocalChromeExecutable()
|
|
92
|
-
return await chromium.launchPersistentContext(userDataDir, {
|
|
93
|
-
...(chromeExecutable ? { executablePath: chromeExecutable } : { channel: 'chromium' }),
|
|
94
|
-
headless: !process.env.HEADFUL,
|
|
95
|
-
colorScheme: 'dark',
|
|
96
|
-
ignoreDefaultArgs: ['--disable-extensions'],
|
|
97
|
-
args,
|
|
98
|
-
})
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
export async function launchPersistentContextWithExtensions({
|
|
102
|
-
userDataDir,
|
|
103
|
-
extensionPaths,
|
|
104
|
-
}: {
|
|
105
|
-
userDataDir: string
|
|
106
|
-
extensionPaths: string[]
|
|
107
|
-
}): Promise<BrowserContext> {
|
|
108
|
-
const browserContext = await launchTestBrowser({
|
|
109
|
-
userDataDir,
|
|
110
|
-
// Chrome 137+ ignores --load-extension for branded builds. Its supported
|
|
111
|
-
// Extensions.loadUnpacked replacement requires this opt-in switch.
|
|
112
|
-
args: ['--enable-unsafe-extension-debugging'],
|
|
113
|
-
})
|
|
114
|
-
|
|
115
|
-
try {
|
|
116
|
-
await loadUnpackedExtensionsThroughCdp({ browserContext, extensionPaths })
|
|
117
|
-
return browserContext
|
|
118
|
-
} catch (error: unknown) {
|
|
119
|
-
await browserContext.close()
|
|
120
|
-
if (!isExtensionLoadUnavailableError(error)) {
|
|
121
|
-
throw new Error(`Failed to load unpacked test extensions: ${extensionPaths.join(', ')}`, { cause: error })
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
// Older Chrome/Chromium does not expose Extensions.loadUnpacked. Relaunch
|
|
125
|
-
// the same isolated profile with the legacy flags it still supports.
|
|
126
|
-
return await launchTestBrowser({
|
|
127
|
-
userDataDir,
|
|
128
|
-
args: getLegacyExtensionLaunchArgs({ extensionPaths }),
|
|
129
|
-
})
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
async function buildExtension({ port, distDir }: { port: number; distDir: string }): Promise<void> {
|
|
134
|
-
const previous = extensionBuildQueues.get(distDir) || Promise.resolve()
|
|
135
|
-
const buildPromise = previous
|
|
136
|
-
.catch((error) => {
|
|
137
|
-
console.error('Previous extension build failed:', error)
|
|
138
|
-
})
|
|
139
|
-
.then(async () => {
|
|
140
|
-
// Build into a per-port dist to avoid parallel test runs overwriting each other.
|
|
141
|
-
await execAsync(`TESTING=1 TABWRIGHT_PORT=${port} TABWRIGHT_EXTENSION_DIST=${distDir} pnpm build`, {
|
|
142
|
-
cwd: '../extension',
|
|
143
|
-
})
|
|
144
|
-
})
|
|
145
|
-
|
|
146
|
-
extensionBuildQueues.set(
|
|
147
|
-
distDir,
|
|
148
|
-
buildPromise.finally(() => {}),
|
|
149
|
-
)
|
|
150
|
-
await buildPromise
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
export async function getExtensionServiceWorker(context: BrowserContext) {
|
|
154
|
-
const serviceWorkers = context.serviceWorkers().filter((sw) => sw.url().startsWith('chrome-extension://'))
|
|
155
|
-
if (serviceWorkers.length === 0) {
|
|
156
|
-
await context
|
|
157
|
-
.waitForEvent('serviceworker', {
|
|
158
|
-
predicate: (sw) => sw.url().startsWith('chrome-extension://'),
|
|
159
|
-
timeout: EXTENSION_SERVICE_WORKER_TIMEOUT_MS,
|
|
160
|
-
})
|
|
161
|
-
.catch((error: unknown) => {
|
|
162
|
-
throw new Error(
|
|
163
|
-
`No extension service worker appeared within ${EXTENSION_SERVICE_WORKER_TIMEOUT_MS}ms`,
|
|
164
|
-
{ cause: error },
|
|
165
|
-
)
|
|
166
|
-
})
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
// Check all chrome-extension service workers for the Tabwright one (the one
|
|
170
|
-
// that exposes toggleExtensionForActiveTab). This handles cases where
|
|
171
|
-
// additional test fixture extensions are loaded alongside Tabwright.
|
|
172
|
-
for (let i = 0; i < 50; i++) {
|
|
173
|
-
const allSws = context.serviceWorkers().filter((sw) => sw.url().startsWith('chrome-extension://'))
|
|
174
|
-
for (const sw of allSws) {
|
|
175
|
-
try {
|
|
176
|
-
const isReady = await sw.evaluate(() => {
|
|
177
|
-
// @ts-ignore
|
|
178
|
-
return typeof globalThis.toggleExtensionForActiveTab === 'function'
|
|
179
|
-
})
|
|
180
|
-
if (isReady) {
|
|
181
|
-
return sw
|
|
182
|
-
}
|
|
183
|
-
} catch {
|
|
184
|
-
// Service worker might not be ready yet
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
await new Promise((r) => setTimeout(r, 100))
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
const extensionWorkerUrls = context
|
|
191
|
-
.serviceWorkers()
|
|
192
|
-
.filter((sw) => {
|
|
193
|
-
return sw.url().startsWith('chrome-extension://')
|
|
194
|
-
})
|
|
195
|
-
.map((sw) => {
|
|
196
|
-
return sw.url()
|
|
197
|
-
})
|
|
198
|
-
throw new Error(
|
|
199
|
-
`Tabwright extension service worker did not become ready within ${EXTENSION_SERVICE_WORKER_TIMEOUT_MS}ms. Visible extension workers: ${extensionWorkerUrls.join(', ') || 'none'}`,
|
|
200
|
-
)
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
export interface TestContext {
|
|
204
|
-
browserContext: BrowserContext
|
|
205
|
-
userDataDir: string
|
|
206
|
-
relayServer: RelayServer
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
export async function setupTestContext({
|
|
210
|
-
port,
|
|
211
|
-
tempDirPrefix,
|
|
212
|
-
toggleExtension = false,
|
|
213
|
-
additionalExtensions = [],
|
|
214
|
-
}: {
|
|
215
|
-
port: number
|
|
216
|
-
tempDirPrefix: string
|
|
217
|
-
/** Create initial page and toggle extension on it */
|
|
218
|
-
toggleExtension?: boolean
|
|
219
|
-
/** Additional extension paths to load alongside the main Tabwright extension */
|
|
220
|
-
additionalExtensions?: string[]
|
|
221
|
-
}): Promise<TestContext> {
|
|
222
|
-
await killPortProcess({ port }).catch(() => {})
|
|
223
|
-
|
|
224
|
-
// Use a port-scoped dist folder so parallel tests don't replace each other's extension builds.
|
|
225
|
-
const distDir = `dist-${port}`
|
|
226
|
-
|
|
227
|
-
console.log('Building extension...')
|
|
228
|
-
await buildExtension({ port, distDir })
|
|
229
|
-
console.log('Extension built')
|
|
230
|
-
|
|
231
|
-
const localLogPath = path.join(process.cwd(), 'relay-server.log')
|
|
232
|
-
const logger = createFileLogger({ logFilePath: localLogPath })
|
|
233
|
-
const relayServer = await startTabwrightCDPRelayServer({ port, logger })
|
|
234
|
-
|
|
235
|
-
const userDataDir = fs.mkdtempSync(path.join(os.tmpdir(), tempDirPrefix))
|
|
236
|
-
const extensionPath = path.resolve('../extension', distDir)
|
|
237
|
-
try {
|
|
238
|
-
const browserContext = await launchPersistentContextWithExtensions({
|
|
239
|
-
userDataDir,
|
|
240
|
-
extensionPaths: [extensionPath, ...additionalExtensions],
|
|
241
|
-
})
|
|
242
|
-
|
|
243
|
-
try {
|
|
244
|
-
if (toggleExtension) {
|
|
245
|
-
const serviceWorker = await getExtensionServiceWorker(browserContext)
|
|
246
|
-
const page = await browserContext.newPage()
|
|
247
|
-
await page.goto('about:blank')
|
|
248
|
-
await serviceWorker.evaluate(async () => {
|
|
249
|
-
await (globalThis as any).toggleExtensionForActiveTab()
|
|
250
|
-
})
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
return { browserContext, userDataDir, relayServer }
|
|
254
|
-
} catch (error) {
|
|
255
|
-
await browserContext.close().catch((closeError: unknown) => {
|
|
256
|
-
console.error('Failed to close browser after test setup error:', closeError)
|
|
257
|
-
})
|
|
258
|
-
throw error
|
|
259
|
-
}
|
|
260
|
-
} catch (error) {
|
|
261
|
-
relayServer.close()
|
|
262
|
-
try {
|
|
263
|
-
fs.rmSync(userDataDir, { recursive: true, force: true })
|
|
264
|
-
} catch (cleanupError) {
|
|
265
|
-
console.error('Failed to clean test profile after setup error:', cleanupError)
|
|
266
|
-
}
|
|
267
|
-
throw error
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
export async function cleanupTestContext(
|
|
272
|
-
ctx: TestContext | null,
|
|
273
|
-
cleanup?: (() => Promise<void>) | null,
|
|
274
|
-
): Promise<void> {
|
|
275
|
-
if (ctx?.browserContext) {
|
|
276
|
-
await ctx.browserContext.close()
|
|
277
|
-
}
|
|
278
|
-
if (ctx?.relayServer) {
|
|
279
|
-
ctx.relayServer.close()
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
if (ctx?.userDataDir) {
|
|
283
|
-
try {
|
|
284
|
-
fs.rmSync(ctx.userDataDir, { recursive: true, force: true })
|
|
285
|
-
} catch (e) {
|
|
286
|
-
console.error('Failed to cleanup user data dir:', e)
|
|
287
|
-
}
|
|
288
|
-
}
|
|
289
|
-
if (cleanup) {
|
|
290
|
-
await cleanup()
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
export type SseServerState = {
|
|
295
|
-
connected: boolean
|
|
296
|
-
finished: boolean
|
|
297
|
-
writeCount: number
|
|
298
|
-
closed: boolean
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
export type SseServer = {
|
|
302
|
-
baseUrl: string
|
|
303
|
-
getState: () => SseServerState
|
|
304
|
-
close: () => Promise<void>
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
export async function createSseServer(): Promise<SseServer> {
|
|
308
|
-
let sseResponse: http.ServerResponse | null = null
|
|
309
|
-
let sseFinished = false
|
|
310
|
-
let sseClosed = false
|
|
311
|
-
let sseWriteCount = 0
|
|
312
|
-
let sseInterval: NodeJS.Timeout | null = null
|
|
313
|
-
const openResponses: Set<http.ServerResponse> = new Set()
|
|
314
|
-
const openSockets: Set<net.Socket> = new Set()
|
|
315
|
-
|
|
316
|
-
const server = http.createServer((req, res) => {
|
|
317
|
-
if (req.url === '/') {
|
|
318
|
-
res.writeHead(200, { 'Content-Type': 'text/html' })
|
|
319
|
-
res.end(`<!doctype html>
|
|
320
|
-
<html>
|
|
321
|
-
<head>
|
|
322
|
-
<meta charset="utf-8" />
|
|
323
|
-
<title>SSE Test</title>
|
|
324
|
-
</head>
|
|
325
|
-
<body>
|
|
326
|
-
<script>
|
|
327
|
-
window.__sseMessages = [];
|
|
328
|
-
window.__sseOpen = false;
|
|
329
|
-
window.__sseError = null;
|
|
330
|
-
window.startSse = function () {
|
|
331
|
-
const source = new EventSource('/sse');
|
|
332
|
-
window.__sseSource = source;
|
|
333
|
-
source.onopen = function () {
|
|
334
|
-
window.__sseOpen = true;
|
|
335
|
-
};
|
|
336
|
-
source.onmessage = function (event) {
|
|
337
|
-
window.__sseMessages.push(event.data);
|
|
338
|
-
};
|
|
339
|
-
source.onerror = function () {
|
|
340
|
-
window.__sseError = 'SSE error';
|
|
341
|
-
};
|
|
342
|
-
return true;
|
|
343
|
-
};
|
|
344
|
-
window.stopSse = function () {
|
|
345
|
-
if (window.__sseSource) {
|
|
346
|
-
window.__sseSource.close();
|
|
347
|
-
}
|
|
348
|
-
};
|
|
349
|
-
</script>
|
|
350
|
-
</body>
|
|
351
|
-
</html>`)
|
|
352
|
-
return
|
|
353
|
-
}
|
|
354
|
-
|
|
355
|
-
if (req.url === '/sse') {
|
|
356
|
-
res.writeHead(200, {
|
|
357
|
-
'Content-Type': 'text/event-stream',
|
|
358
|
-
'Cache-Control': 'no-cache, no-transform',
|
|
359
|
-
Connection: 'keep-alive',
|
|
360
|
-
})
|
|
361
|
-
res.write('retry: 1000\n\n')
|
|
362
|
-
res.write('data: hello\n\n')
|
|
363
|
-
sseResponse = res
|
|
364
|
-
sseWriteCount += 1
|
|
365
|
-
openResponses.add(res)
|
|
366
|
-
|
|
367
|
-
res.on('finish', () => {
|
|
368
|
-
sseFinished = true
|
|
369
|
-
})
|
|
370
|
-
res.on('close', () => {
|
|
371
|
-
sseClosed = true
|
|
372
|
-
openResponses.delete(res)
|
|
373
|
-
if (sseInterval) {
|
|
374
|
-
clearInterval(sseInterval)
|
|
375
|
-
sseInterval = null
|
|
376
|
-
}
|
|
377
|
-
})
|
|
378
|
-
|
|
379
|
-
sseInterval = setInterval(() => {
|
|
380
|
-
res.write('data: ping\n\n')
|
|
381
|
-
sseWriteCount += 1
|
|
382
|
-
}, 200)
|
|
383
|
-
return
|
|
384
|
-
}
|
|
385
|
-
|
|
386
|
-
res.writeHead(404)
|
|
387
|
-
res.end('Not found')
|
|
388
|
-
})
|
|
389
|
-
|
|
390
|
-
server.on('connection', (socket) => {
|
|
391
|
-
openSockets.add(socket)
|
|
392
|
-
socket.on('close', () => {
|
|
393
|
-
openSockets.delete(socket)
|
|
394
|
-
})
|
|
395
|
-
})
|
|
396
|
-
|
|
397
|
-
await new Promise<void>((resolve) => {
|
|
398
|
-
server.listen(0, '127.0.0.1', () => {
|
|
399
|
-
resolve()
|
|
400
|
-
})
|
|
401
|
-
})
|
|
402
|
-
|
|
403
|
-
const address = server.address()
|
|
404
|
-
if (!address || typeof address === 'string') {
|
|
405
|
-
throw new Error('Failed to bind SSE server')
|
|
406
|
-
}
|
|
407
|
-
|
|
408
|
-
return {
|
|
409
|
-
baseUrl: `http://127.0.0.1:${address.port}`,
|
|
410
|
-
getState: () => ({
|
|
411
|
-
connected: sseResponse !== null,
|
|
412
|
-
finished: sseFinished,
|
|
413
|
-
closed: sseClosed,
|
|
414
|
-
writeCount: sseWriteCount,
|
|
415
|
-
}),
|
|
416
|
-
close: async () => {
|
|
417
|
-
for (const response of openResponses) {
|
|
418
|
-
response.destroy()
|
|
419
|
-
}
|
|
420
|
-
for (const socket of openSockets) {
|
|
421
|
-
socket.destroy()
|
|
422
|
-
}
|
|
423
|
-
if (sseInterval) {
|
|
424
|
-
clearInterval(sseInterval)
|
|
425
|
-
sseInterval = null
|
|
426
|
-
}
|
|
427
|
-
await new Promise<void>((resolve, reject) => {
|
|
428
|
-
server.close((error) => {
|
|
429
|
-
if (error) {
|
|
430
|
-
reject(error)
|
|
431
|
-
return
|
|
432
|
-
}
|
|
433
|
-
resolve()
|
|
434
|
-
})
|
|
435
|
-
})
|
|
436
|
-
},
|
|
437
|
-
}
|
|
438
|
-
}
|
|
439
|
-
|
|
440
|
-
export async function withTimeout<T>({
|
|
441
|
-
promise,
|
|
442
|
-
timeoutMs,
|
|
443
|
-
errorMessage,
|
|
444
|
-
}: {
|
|
445
|
-
promise: Promise<T>
|
|
446
|
-
timeoutMs: number
|
|
447
|
-
errorMessage: string
|
|
448
|
-
}): Promise<T> {
|
|
449
|
-
return await new Promise<T>((resolve, reject) => {
|
|
450
|
-
const timeoutId = setTimeout(() => {
|
|
451
|
-
reject(new Error(errorMessage))
|
|
452
|
-
}, timeoutMs)
|
|
453
|
-
|
|
454
|
-
promise
|
|
455
|
-
.then((value) => {
|
|
456
|
-
clearTimeout(timeoutId)
|
|
457
|
-
resolve(value)
|
|
458
|
-
})
|
|
459
|
-
.catch((error) => {
|
|
460
|
-
clearTimeout(timeoutId)
|
|
461
|
-
reject(error)
|
|
462
|
-
})
|
|
463
|
-
})
|
|
464
|
-
}
|
|
465
|
-
|
|
466
|
-
/** Tagged template for inline JS code strings used in MCP execute calls */
|
|
467
|
-
export function js(strings: TemplateStringsArray, ...values: unknown[]): string {
|
|
468
|
-
return strings.reduce((result, str, i) => result + str + (values[i] || ''), '')
|
|
469
|
-
}
|
|
470
|
-
|
|
471
|
-
export function tryJsonParse(str: string) {
|
|
472
|
-
try {
|
|
473
|
-
return JSON.parse(str)
|
|
474
|
-
} catch {
|
|
475
|
-
return str
|
|
476
|
-
}
|
|
477
|
-
}
|
|
478
|
-
|
|
479
|
-
/**
|
|
480
|
-
* Safely close a browser connected via connectOverCDP.
|
|
481
|
-
*
|
|
482
|
-
* Playwright's CRConnection uses async message handling (messageWrap) that can cause
|
|
483
|
-
* a race condition where _onClose() runs before all pending _onMessage() handlers complete.
|
|
484
|
-
* This results in "Assertion error" from crConnection.js when a CDP response arrives
|
|
485
|
-
* after callbacks were cleared by dispose().
|
|
486
|
-
*
|
|
487
|
-
* This helper waits for the message queue to drain before closing, avoiding the race.
|
|
488
|
-
*
|
|
489
|
-
* @param browser - Browser instance from chromium.connectOverCDP()
|
|
490
|
-
* @param drainDelayMs - Time to wait for pending messages to be processed (default: 50ms)
|
|
491
|
-
*/
|
|
492
|
-
export async function safeCloseCDPBrowser(
|
|
493
|
-
browser: Awaited<ReturnType<typeof import('@xmorse/playwright-core').chromium.connectOverCDP>>,
|
|
494
|
-
drainDelayMs = 50,
|
|
495
|
-
): Promise<void> {
|
|
496
|
-
// Wait for any queued message handlers to run
|
|
497
|
-
// This gives Playwright's messageWrap time to process pending CDP responses
|
|
498
|
-
await new Promise((r) => setTimeout(r, drainDelayMs))
|
|
499
|
-
await browser.close()
|
|
500
|
-
}
|
|
501
|
-
|
|
502
|
-
export type SimpleServer = {
|
|
503
|
-
baseUrl: string
|
|
504
|
-
close: () => Promise<void>
|
|
505
|
-
}
|
|
506
|
-
|
|
507
|
-
/** Minimal local HTTP server for tests that need cross-origin iframes or custom routes */
|
|
508
|
-
export async function createSimpleServer({ routes }: { routes: Record<string, string> }): Promise<SimpleServer> {
|
|
509
|
-
const openSockets: Set<net.Socket> = new Set()
|
|
510
|
-
const server = http.createServer((req, res) => {
|
|
511
|
-
const url = req.url || '/'
|
|
512
|
-
const body = routes[url]
|
|
513
|
-
if (!body) {
|
|
514
|
-
res.writeHead(404, { 'Content-Type': 'text/plain' })
|
|
515
|
-
res.end('not found')
|
|
516
|
-
return
|
|
517
|
-
}
|
|
518
|
-
res.writeHead(200, { 'Content-Type': 'text/html' })
|
|
519
|
-
res.end(body)
|
|
520
|
-
})
|
|
521
|
-
|
|
522
|
-
server.on('connection', (socket) => {
|
|
523
|
-
openSockets.add(socket)
|
|
524
|
-
socket.on('close', () => {
|
|
525
|
-
openSockets.delete(socket)
|
|
526
|
-
})
|
|
527
|
-
})
|
|
528
|
-
|
|
529
|
-
await new Promise<void>((resolve) => {
|
|
530
|
-
server.listen(0, '127.0.0.1', () => {
|
|
531
|
-
resolve()
|
|
532
|
-
})
|
|
533
|
-
})
|
|
534
|
-
|
|
535
|
-
const address = server.address()
|
|
536
|
-
if (!address || typeof address === 'string') {
|
|
537
|
-
await new Promise<void>((resolve, reject) => {
|
|
538
|
-
server.close((error) => {
|
|
539
|
-
if (error) {
|
|
540
|
-
reject(error)
|
|
541
|
-
return
|
|
542
|
-
}
|
|
543
|
-
resolve()
|
|
544
|
-
})
|
|
545
|
-
})
|
|
546
|
-
throw new Error('Failed to start test server')
|
|
547
|
-
}
|
|
548
|
-
|
|
549
|
-
return {
|
|
550
|
-
baseUrl: `http://127.0.0.1:${address.port}`,
|
|
551
|
-
close: async () => {
|
|
552
|
-
for (const socket of openSockets) {
|
|
553
|
-
socket.destroy()
|
|
554
|
-
}
|
|
555
|
-
await new Promise<void>((resolve, reject) => {
|
|
556
|
-
server.close((error) => {
|
|
557
|
-
if (error) {
|
|
558
|
-
reject(error)
|
|
559
|
-
return
|
|
560
|
-
}
|
|
561
|
-
resolve()
|
|
562
|
-
})
|
|
563
|
-
})
|
|
564
|
-
},
|
|
565
|
-
}
|
|
566
|
-
}
|
package/src/utils.ts
DELETED
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
import fs from 'node:fs'
|
|
2
|
-
import path from 'node:path'
|
|
3
|
-
import { fileURLToPath } from 'node:url'
|
|
4
|
-
import './env-compat.js'
|
|
5
|
-
import { getTabwrightUserDataDir } from './product-paths.js'
|
|
6
|
-
|
|
7
|
-
// Tabwright extension IDs - used for validation and Chrome flag commands
|
|
8
|
-
export const EXTENSION_IDS = [
|
|
9
|
-
'jfeammnjpkecdekppnclgkkffahnhfhe', // Production (Chrome Web Store)
|
|
10
|
-
'pebbngnfojnignonigcnkdilknapkgid', // Dev extension (stable ID from manifest key)
|
|
11
|
-
]
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Parse a relay host string into HTTP and WebSocket base URLs.
|
|
15
|
-
* Supports both plain hostnames (appends port) and full URLs (uses as-is).
|
|
16
|
-
*
|
|
17
|
-
* Examples:
|
|
18
|
-
* "192.168.1.10" → http://192.168.1.10:19988, ws://192.168.1.10:19988
|
|
19
|
-
* "https://my-machine-tunnel.traforo.dev" → https://my-machine-tunnel.traforo.dev, wss://my-machine-tunnel.traforo.dev
|
|
20
|
-
*/
|
|
21
|
-
export function parseRelayHost(host: string, port: number = 19988): { httpBaseUrl: string; wsBaseUrl: string } {
|
|
22
|
-
if (host.startsWith('https://') || host.startsWith('http://')) {
|
|
23
|
-
const url = new URL(host)
|
|
24
|
-
const httpBaseUrl = url.origin
|
|
25
|
-
const wsProtocol = url.protocol === 'https:' ? 'wss:' : 'ws:'
|
|
26
|
-
const wsBaseUrl = `${wsProtocol}//${url.host}`
|
|
27
|
-
return { httpBaseUrl, wsBaseUrl }
|
|
28
|
-
}
|
|
29
|
-
return {
|
|
30
|
-
httpBaseUrl: `http://${host}:${port}`,
|
|
31
|
-
wsBaseUrl: `ws://${host}:${port}`,
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
export function getCdpUrl({
|
|
36
|
-
port = 19988,
|
|
37
|
-
host = '127.0.0.1',
|
|
38
|
-
token,
|
|
39
|
-
extensionId,
|
|
40
|
-
}: {
|
|
41
|
-
port?: number
|
|
42
|
-
host?: string
|
|
43
|
-
token?: string
|
|
44
|
-
extensionId?: string | null
|
|
45
|
-
} = {}) {
|
|
46
|
-
const id = `${Math.random().toString(36).substring(2, 15)}_${Date.now()}`
|
|
47
|
-
const params = new URLSearchParams()
|
|
48
|
-
if (token) {
|
|
49
|
-
params.set('token', token)
|
|
50
|
-
}
|
|
51
|
-
if (extensionId) {
|
|
52
|
-
params.set('extensionId', extensionId)
|
|
53
|
-
}
|
|
54
|
-
const queryString = params.toString()
|
|
55
|
-
const suffix = queryString ? `?${queryString}` : ''
|
|
56
|
-
const { wsBaseUrl } = parseRelayHost(host, port)
|
|
57
|
-
return `${wsBaseUrl}/cdp/${id}${suffix}`
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
export function shouldAutoEnableTabwright(): boolean {
|
|
61
|
-
return (process.env.TABWRIGHT_AUTO_ENABLE || process.env.PLAYWRITER_AUTO_ENABLE)?.toLowerCase() !== 'false'
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
// Existing installations continue using their legacy data directory until users migrate it.
|
|
65
|
-
const LOG_BASE_DIR = getTabwrightUserDataDir()
|
|
66
|
-
export const LOG_FILE_PATH =
|
|
67
|
-
process.env.TABWRIGHT_LOG_FILE_PATH || process.env.PLAYWRITER_LOG_FILE_PATH || path.join(LOG_BASE_DIR, 'relay-server.log')
|
|
68
|
-
export const LOG_CDP_FILE_PATH =
|
|
69
|
-
process.env.TABWRIGHT_CDP_LOG_FILE_PATH ||
|
|
70
|
-
process.env.PLAYWRITER_CDP_LOG_FILE_PATH ||
|
|
71
|
-
path.join(path.dirname(LOG_FILE_PATH), 'cdp.jsonl')
|
|
72
|
-
|
|
73
|
-
const packageJsonPath = path.join(path.dirname(fileURLToPath(import.meta.url)), '..', 'package.json')
|
|
74
|
-
export const VERSION = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8')).version as string
|
|
75
|
-
|
|
76
|
-
export function sleep(ms: number): Promise<void> {
|
|
77
|
-
return new Promise((resolve) => setTimeout(resolve, ms))
|
|
78
|
-
}
|