opendevbrowser 0.0.16 → 0.0.18
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 +201 -79
- package/dist/annotate/agent-inbox-store.d.ts +58 -0
- package/dist/annotate/agent-inbox-store.d.ts.map +1 -0
- package/dist/annotate/agent-inbox.d.ts +25 -0
- package/dist/annotate/agent-inbox.d.ts.map +1 -0
- package/dist/annotate/direct-annotator.d.ts.map +1 -1
- package/dist/annotate/timeout-messages.d.ts +4 -0
- package/dist/annotate/timeout-messages.d.ts.map +1 -0
- package/dist/automation/coordinator.d.ts +55 -0
- package/dist/automation/coordinator.d.ts.map +1 -0
- package/dist/browser/annotation-manager.d.ts +7 -1
- package/dist/browser/annotation-manager.d.ts.map +1 -1
- package/dist/browser/browser-manager.d.ts +153 -48
- package/dist/browser/browser-manager.d.ts.map +1 -1
- package/dist/browser/canvas-client.d.ts +54 -0
- package/dist/browser/canvas-client.d.ts.map +1 -0
- package/dist/browser/canvas-code-sync-manager.d.ts +87 -0
- package/dist/browser/canvas-code-sync-manager.d.ts.map +1 -0
- package/dist/browser/canvas-manager.d.ts +122 -0
- package/dist/browser/canvas-manager.d.ts.map +1 -0
- package/dist/browser/canvas-runtime-preview-bridge.d.ts +20 -0
- package/dist/browser/canvas-runtime-preview-bridge.d.ts.map +1 -0
- package/dist/browser/canvas-session-sync-manager.d.ts +21 -0
- package/dist/browser/canvas-session-sync-manager.d.ts.map +1 -0
- package/dist/browser/global-challenge-coordinator.d.ts +27 -0
- package/dist/browser/global-challenge-coordinator.d.ts.map +1 -0
- package/dist/browser/manager-types.d.ts +179 -1
- package/dist/browser/manager-types.d.ts.map +1 -1
- package/dist/browser/ops-browser-manager.d.ts +114 -4
- package/dist/browser/ops-browser-manager.d.ts.map +1 -1
- package/dist/browser/ops-client.d.ts +17 -1
- package/dist/browser/ops-client.d.ts.map +1 -1
- package/dist/browser/playwright-runtime.d.ts +4 -0
- package/dist/browser/playwright-runtime.d.ts.map +1 -0
- package/dist/browser/review-surface.d.ts +9 -0
- package/dist/browser/review-surface.d.ts.map +1 -0
- package/dist/browser/screencast-recorder.d.ts +57 -0
- package/dist/browser/screencast-recorder.d.ts.map +1 -0
- package/dist/browser/session-inspector.d.ts +71 -0
- package/dist/browser/session-inspector.d.ts.map +1 -0
- package/dist/browser/session-store.d.ts +5 -1
- package/dist/browser/session-store.d.ts.map +1 -1
- package/dist/browser/system-chrome-cookies.d.ts +46 -0
- package/dist/browser/system-chrome-cookies.d.ts.map +1 -0
- package/dist/browser/target-manager.d.ts +1 -0
- package/dist/browser/target-manager.d.ts.map +1 -1
- package/dist/cache/chrome-locator.d.ts.map +1 -1
- package/dist/cache/chrome-user-data.d.ts +17 -0
- package/dist/cache/chrome-user-data.d.ts.map +1 -0
- package/dist/canvas/adapter-plugins/loader.d.ts +13 -0
- package/dist/canvas/adapter-plugins/loader.d.ts.map +1 -0
- package/dist/canvas/adapter-plugins/manifest.d.ts +146 -0
- package/dist/canvas/adapter-plugins/manifest.d.ts.map +1 -0
- package/dist/canvas/adapter-plugins/types.d.ts +83 -0
- package/dist/canvas/adapter-plugins/types.d.ts.map +1 -0
- package/dist/canvas/adapter-plugins/validator.d.ts +10 -0
- package/dist/canvas/adapter-plugins/validator.d.ts.map +1 -0
- package/dist/canvas/code-sync/apply-tsx.d.ts +25 -0
- package/dist/canvas/code-sync/apply-tsx.d.ts.map +1 -0
- package/dist/canvas/code-sync/graph.d.ts +5 -0
- package/dist/canvas/code-sync/graph.d.ts.map +1 -0
- package/dist/canvas/code-sync/hash.d.ts +3 -0
- package/dist/canvas/code-sync/hash.d.ts.map +1 -0
- package/dist/canvas/code-sync/import.d.ts +19 -0
- package/dist/canvas/code-sync/import.d.ts.map +1 -0
- package/dist/canvas/code-sync/manifest.d.ts +6 -0
- package/dist/canvas/code-sync/manifest.d.ts.map +1 -0
- package/dist/canvas/code-sync/tsx-adapter.d.ts +8 -0
- package/dist/canvas/code-sync/tsx-adapter.d.ts.map +1 -0
- package/dist/canvas/code-sync/types.d.ts +244 -0
- package/dist/canvas/code-sync/types.d.ts.map +1 -0
- package/dist/canvas/code-sync/write.d.ts +9 -0
- package/dist/canvas/code-sync/write.d.ts.map +1 -0
- package/dist/canvas/document-store.d.ts +91 -0
- package/dist/canvas/document-store.d.ts.map +1 -0
- package/dist/canvas/export.d.ts +12 -0
- package/dist/canvas/export.d.ts.map +1 -0
- package/dist/canvas/framework-adapters/custom-elements-v1.d.ts +3 -0
- package/dist/canvas/framework-adapters/custom-elements-v1.d.ts.map +1 -0
- package/dist/canvas/framework-adapters/html-static-v1.d.ts +3 -0
- package/dist/canvas/framework-adapters/html-static-v1.d.ts.map +1 -0
- package/dist/canvas/framework-adapters/markup.d.ts +9 -0
- package/dist/canvas/framework-adapters/markup.d.ts.map +1 -0
- package/dist/canvas/framework-adapters/react-tsx-v2.d.ts +3 -0
- package/dist/canvas/framework-adapters/react-tsx-v2.d.ts.map +1 -0
- package/dist/canvas/framework-adapters/registry.d.ts +12 -0
- package/dist/canvas/framework-adapters/registry.d.ts.map +1 -0
- package/dist/canvas/framework-adapters/svelte-sfc-v1.d.ts +3 -0
- package/dist/canvas/framework-adapters/svelte-sfc-v1.d.ts.map +1 -0
- package/dist/canvas/framework-adapters/types.d.ts +57 -0
- package/dist/canvas/framework-adapters/types.d.ts.map +1 -0
- package/dist/canvas/framework-adapters/vue-sfc-v1.d.ts +3 -0
- package/dist/canvas/framework-adapters/vue-sfc-v1.d.ts.map +1 -0
- package/dist/canvas/kits/catalog.d.ts +5 -0
- package/dist/canvas/kits/catalog.d.ts.map +1 -0
- package/dist/canvas/library-adapters/react/index.d.ts +3 -0
- package/dist/canvas/library-adapters/react/index.d.ts.map +1 -0
- package/dist/canvas/library-adapters/registry.d.ts +11 -0
- package/dist/canvas/library-adapters/registry.d.ts.map +1 -0
- package/dist/canvas/library-adapters/types.d.ts +43 -0
- package/dist/canvas/library-adapters/types.d.ts.map +1 -0
- package/dist/canvas/repo-store.d.ts +12 -0
- package/dist/canvas/repo-store.d.ts.map +1 -0
- package/dist/canvas/starters/catalog.d.ts +34 -0
- package/dist/canvas/starters/catalog.d.ts.map +1 -0
- package/dist/canvas/surface-palette.d.ts +15 -0
- package/dist/canvas/surface-palette.d.ts.map +1 -0
- package/dist/canvas/token-references.d.ts +22 -0
- package/dist/canvas/token-references.d.ts.map +1 -0
- package/dist/canvas/types.d.ts +594 -0
- package/dist/canvas/types.d.ts.map +1 -0
- package/dist/canvas-runtime-preview-bridge-HBEHXM4T.js +7 -0
- package/dist/canvas-runtime-preview-bridge-HBEHXM4T.js.map +1 -0
- package/dist/challenges/action-loop.d.ts +13 -0
- package/dist/challenges/action-loop.d.ts.map +1 -0
- package/dist/challenges/capability-matrix.d.ts +3 -0
- package/dist/challenges/capability-matrix.d.ts.map +1 -0
- package/dist/challenges/evidence-bundle.d.ts +48 -0
- package/dist/challenges/evidence-bundle.d.ts.map +1 -0
- package/dist/challenges/governed-adapter-gateway.d.ts +4 -0
- package/dist/challenges/governed-adapter-gateway.d.ts.map +1 -0
- package/dist/challenges/human-yield-gate.d.ts +20 -0
- package/dist/challenges/human-yield-gate.d.ts.map +1 -0
- package/dist/challenges/index.d.ts +15 -0
- package/dist/challenges/index.d.ts.map +1 -0
- package/dist/challenges/interpreter.d.ts +3 -0
- package/dist/challenges/interpreter.d.ts.map +1 -0
- package/dist/challenges/optional-computer-use-bridge.d.ts +9 -0
- package/dist/challenges/optional-computer-use-bridge.d.ts.map +1 -0
- package/dist/challenges/orchestrator.d.ts +32 -0
- package/dist/challenges/orchestrator.d.ts.map +1 -0
- package/dist/challenges/outcome-recorder.d.ts +8 -0
- package/dist/challenges/outcome-recorder.d.ts.map +1 -0
- package/dist/challenges/owned-environment-lane.d.ts +3 -0
- package/dist/challenges/owned-environment-lane.d.ts.map +1 -0
- package/dist/challenges/policy-gate.d.ts +9 -0
- package/dist/challenges/policy-gate.d.ts.map +1 -0
- package/dist/challenges/sanctioned-identity-lane.d.ts +3 -0
- package/dist/challenges/sanctioned-identity-lane.d.ts.map +1 -0
- package/dist/challenges/service-adapter-lane.d.ts +3 -0
- package/dist/challenges/service-adapter-lane.d.ts.map +1 -0
- package/dist/challenges/strategy-selector.d.ts +10 -0
- package/dist/challenges/strategy-selector.d.ts.map +1 -0
- package/dist/challenges/types.d.ts +277 -0
- package/dist/challenges/types.d.ts.map +1 -0
- package/dist/challenges/verification-gate.d.ts +15 -0
- package/dist/challenges/verification-gate.d.ts.map +1 -0
- package/dist/chunk-5FZQJRBQ.js +15256 -0
- package/dist/chunk-5FZQJRBQ.js.map +1 -0
- package/dist/{chunk-7W3SPXIB.js → chunk-FUSXMW3G.js} +4 -1
- package/dist/chunk-L57D35TB.js +33513 -0
- package/dist/chunk-L57D35TB.js.map +1 -0
- package/dist/chunk-TBUCZX4A.js +34 -0
- package/dist/chunk-TBUCZX4A.js.map +1 -0
- package/dist/chunk-Y2KL55OG.js +59 -0
- package/dist/chunk-Y2KL55OG.js.map +1 -0
- package/dist/chunk-YBQECXZX.js +409 -0
- package/dist/chunk-YBQECXZX.js.map +1 -0
- package/dist/cli/args.d.ts +4 -4
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/commands/annotate.d.ts +11 -0
- package/dist/cli/commands/annotate.d.ts.map +1 -1
- package/dist/cli/commands/artifacts.d.ts.map +1 -1
- package/dist/cli/commands/canvas.d.ts +45 -0
- package/dist/cli/commands/canvas.d.ts.map +1 -0
- package/dist/cli/commands/daemon.d.ts +7 -0
- package/dist/cli/commands/daemon.d.ts.map +1 -1
- package/dist/cli/commands/desktop/accessibility-snapshot.d.ts +3 -0
- package/dist/cli/commands/desktop/accessibility-snapshot.d.ts.map +1 -0
- package/dist/cli/commands/desktop/active-window.d.ts +3 -0
- package/dist/cli/commands/desktop/active-window.d.ts.map +1 -0
- package/dist/cli/commands/desktop/capture-desktop.d.ts +3 -0
- package/dist/cli/commands/desktop/capture-desktop.d.ts.map +1 -0
- package/dist/cli/commands/desktop/capture-window.d.ts +3 -0
- package/dist/cli/commands/desktop/capture-window.d.ts.map +1 -0
- package/dist/cli/commands/desktop/shared.d.ts +19 -0
- package/dist/cli/commands/desktop/shared.d.ts.map +1 -0
- package/dist/cli/commands/desktop/status.d.ts +3 -0
- package/dist/cli/commands/desktop/status.d.ts.map +1 -0
- package/dist/cli/commands/desktop/windows.d.ts +3 -0
- package/dist/cli/commands/desktop/windows.d.ts.map +1 -0
- package/dist/cli/commands/devtools/dialog.d.ts +19 -0
- package/dist/cli/commands/devtools/dialog.d.ts.map +1 -0
- package/dist/cli/commands/devtools/perf.d.ts.map +1 -1
- package/dist/cli/commands/devtools/screencast-start.d.ts +20 -0
- package/dist/cli/commands/devtools/screencast-start.d.ts.map +1 -0
- package/dist/cli/commands/devtools/screencast-stop.d.ts +17 -0
- package/dist/cli/commands/devtools/screencast-stop.d.ts.map +1 -0
- package/dist/cli/commands/devtools/screenshot.d.ts +3 -0
- package/dist/cli/commands/devtools/screenshot.d.ts.map +1 -1
- package/dist/cli/commands/dom/attr.d.ts.map +1 -1
- package/dist/cli/commands/dom/checked.d.ts.map +1 -1
- package/dist/cli/commands/dom/enabled.d.ts.map +1 -1
- package/dist/cli/commands/dom/html.d.ts.map +1 -1
- package/dist/cli/commands/dom/text.d.ts.map +1 -1
- package/dist/cli/commands/dom/value.d.ts.map +1 -1
- package/dist/cli/commands/dom/visible.d.ts.map +1 -1
- package/dist/cli/commands/export/clone-component.d.ts +9 -0
- package/dist/cli/commands/export/clone-component.d.ts.map +1 -1
- package/dist/cli/commands/export/clone-page.d.ts +8 -0
- package/dist/cli/commands/export/clone-page.d.ts.map +1 -1
- package/dist/cli/commands/interact/check.d.ts.map +1 -1
- package/dist/cli/commands/interact/click.d.ts.map +1 -1
- package/dist/cli/commands/interact/hover.d.ts.map +1 -1
- package/dist/cli/commands/interact/pointer-down.d.ts +7 -0
- package/dist/cli/commands/interact/pointer-down.d.ts.map +1 -0
- package/dist/cli/commands/interact/pointer-drag.d.ts +7 -0
- package/dist/cli/commands/interact/pointer-drag.d.ts.map +1 -0
- package/dist/cli/commands/interact/pointer-move.d.ts +7 -0
- package/dist/cli/commands/interact/pointer-move.d.ts.map +1 -0
- package/dist/cli/commands/interact/pointer-shared.d.ts +6 -0
- package/dist/cli/commands/interact/pointer-shared.d.ts.map +1 -0
- package/dist/cli/commands/interact/pointer-up.d.ts +7 -0
- package/dist/cli/commands/interact/pointer-up.d.ts.map +1 -0
- package/dist/cli/commands/interact/press.d.ts.map +1 -1
- package/dist/cli/commands/interact/scroll-into-view.d.ts.map +1 -1
- package/dist/cli/commands/interact/scroll.d.ts.map +1 -1
- package/dist/cli/commands/interact/select.d.ts.map +1 -1
- package/dist/cli/commands/interact/type.d.ts.map +1 -1
- package/dist/cli/commands/interact/uncheck.d.ts.map +1 -1
- package/dist/cli/commands/interact/upload.d.ts +18 -0
- package/dist/cli/commands/interact/upload.d.ts.map +1 -0
- package/dist/cli/commands/macro-resolve.d.ts +2 -0
- package/dist/cli/commands/macro-resolve.d.ts.map +1 -1
- package/dist/cli/commands/native.d.ts +22 -8
- package/dist/cli/commands/native.d.ts.map +1 -1
- package/dist/cli/commands/nav/goto.d.ts.map +1 -1
- package/dist/cli/commands/nav/review.d.ts +7 -0
- package/dist/cli/commands/nav/review.d.ts.map +1 -0
- package/dist/cli/commands/nav/snapshot.d.ts.map +1 -1
- package/dist/cli/commands/nav/wait.d.ts.map +1 -1
- package/dist/cli/commands/pages/open.d.ts.map +1 -1
- package/dist/cli/commands/product-video.d.ts +2 -0
- package/dist/cli/commands/product-video.d.ts.map +1 -1
- package/dist/cli/commands/research.d.ts +3 -0
- package/dist/cli/commands/research.d.ts.map +1 -1
- package/dist/cli/commands/run.d.ts +14 -0
- package/dist/cli/commands/run.d.ts.map +1 -1
- package/dist/cli/commands/serve.d.ts +1 -21
- package/dist/cli/commands/serve.d.ts.map +1 -1
- package/dist/cli/commands/session/connect.d.ts.map +1 -1
- package/dist/cli/commands/session/disconnect.d.ts.map +1 -1
- package/dist/cli/commands/session/inspector.d.ts +21 -0
- package/dist/cli/commands/session/inspector.d.ts.map +1 -0
- package/dist/cli/commands/session/launch.d.ts.map +1 -1
- package/dist/cli/commands/shopping.d.ts +5 -0
- package/dist/cli/commands/shopping.d.ts.map +1 -1
- package/dist/cli/commands/status.d.ts +2 -9
- package/dist/cli/commands/status.d.ts.map +1 -1
- package/dist/cli/commands/targets/new.d.ts.map +1 -1
- package/dist/cli/daemon-autostart.d.ts +11 -0
- package/dist/cli/daemon-autostart.d.ts.map +1 -1
- package/dist/cli/daemon-client.d.ts +3 -0
- package/dist/cli/daemon-client.d.ts.map +1 -1
- package/dist/cli/daemon-commands.d.ts.map +1 -1
- package/dist/cli/daemon-state.d.ts +16 -0
- package/dist/cli/daemon-state.d.ts.map +1 -1
- package/dist/cli/daemon-status.d.ts +7 -2
- package/dist/cli/daemon-status.d.ts.map +1 -1
- package/dist/cli/daemon.d.ts +1 -0
- package/dist/cli/daemon.d.ts.map +1 -1
- package/dist/cli/help.d.ts +19 -3
- package/dist/cli/help.d.ts.map +1 -1
- package/dist/cli/index.js +2927 -932
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/install-autostart-output.d.ts +6 -0
- package/dist/cli/install-autostart-output.d.ts.map +1 -0
- package/dist/cli/install-autostart-reconciliation.d.ts +23 -0
- package/dist/cli/install-autostart-reconciliation.d.ts.map +1 -0
- package/dist/cli/installers/skills.d.ts +42 -6
- package/dist/cli/installers/skills.d.ts.map +1 -1
- package/dist/cli/output.d.ts +3 -0
- package/dist/cli/output.d.ts.map +1 -1
- package/dist/cli/remote-canvas-manager.d.ts +8 -0
- package/dist/cli/remote-canvas-manager.d.ts.map +1 -0
- package/dist/cli/remote-desktop-runtime.d.ts +15 -0
- package/dist/cli/remote-desktop-runtime.d.ts.map +1 -0
- package/dist/cli/remote-manager.d.ts +27 -3
- package/dist/cli/remote-manager.d.ts.map +1 -1
- package/dist/cli/remote-relay.d.ts +2 -0
- package/dist/cli/remote-relay.d.ts.map +1 -1
- package/dist/cli/transport-timeouts.d.ts +8 -0
- package/dist/cli/transport-timeouts.d.ts.map +1 -0
- package/dist/cli/utils/http.d.ts +9 -0
- package/dist/cli/utils/http.d.ts.map +1 -1
- package/dist/cli/utils/parse.d.ts +3 -0
- package/dist/cli/utils/parse.d.ts.map +1 -1
- package/dist/cli/utils/skills.d.ts +1 -2
- package/dist/cli/utils/skills.d.ts.map +1 -1
- package/dist/cli/utils/workflow-message.d.ts +2 -0
- package/dist/cli/utils/workflow-message.d.ts.map +1 -0
- package/dist/config.d.ts +47 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/core/bootstrap.d.ts.map +1 -1
- package/dist/core/index.d.ts +1 -0
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/logging.d.ts +3 -1
- package/dist/core/logging.d.ts.map +1 -1
- package/dist/core/runtime-assemblies.d.ts +22 -0
- package/dist/core/runtime-assemblies.d.ts.map +1 -0
- package/dist/core/types.d.ts +17 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/desktop/audit.d.ts +37 -0
- package/dist/desktop/audit.d.ts.map +1 -0
- package/dist/desktop/errors.d.ts +7 -0
- package/dist/desktop/errors.d.ts.map +1 -0
- package/dist/desktop/index.d.ts +6 -0
- package/dist/desktop/index.d.ts.map +1 -0
- package/dist/desktop/runtime.d.ts +26 -0
- package/dist/desktop/runtime.d.ts.map +1 -0
- package/dist/desktop/types.d.ts +76 -0
- package/dist/desktop/types.d.ts.map +1 -0
- package/dist/extension-extractor.d.ts +6 -0
- package/dist/extension-extractor.d.ts.map +1 -1
- package/dist/fs-UMRKOBNN.js +7 -0
- package/dist/fs-UMRKOBNN.js.map +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1221 -460
- package/dist/index.js.map +1 -1
- package/dist/integrations/figma/assets.d.ts +13 -0
- package/dist/integrations/figma/assets.d.ts.map +1 -0
- package/dist/integrations/figma/auth.d.ts +3 -0
- package/dist/integrations/figma/auth.d.ts.map +1 -0
- package/dist/integrations/figma/client.d.ts +42 -0
- package/dist/integrations/figma/client.d.ts.map +1 -0
- package/dist/integrations/figma/mappers.d.ts +23 -0
- package/dist/integrations/figma/mappers.d.ts.map +1 -0
- package/dist/integrations/figma/normalize.d.ts +99 -0
- package/dist/integrations/figma/normalize.d.ts.map +1 -0
- package/dist/integrations/figma/url.d.ts +17 -0
- package/dist/integrations/figma/url.d.ts.map +1 -0
- package/dist/integrations/figma/variables.d.ts +21 -0
- package/dist/integrations/figma/variables.d.ts.map +1 -0
- package/dist/macros/execute-runtime.d.ts +19 -0
- package/dist/macros/execute-runtime.d.ts.map +1 -0
- package/dist/macros/execute.d.ts +3 -1
- package/dist/macros/execute.d.ts.map +1 -1
- package/dist/{macros-NUBRM44Y.js → macros-ND2M7LWU.js} +2 -2
- package/dist/opendevbrowser.d.ts.map +1 -1
- package/dist/opendevbrowser.js +1221 -460
- package/dist/opendevbrowser.js.map +1 -1
- package/dist/providers/blocker.d.ts.map +1 -1
- package/dist/providers/browser-fallback.d.ts +30 -0
- package/dist/providers/browser-fallback.d.ts.map +1 -0
- package/dist/providers/constraint.d.ts +45 -0
- package/dist/providers/constraint.d.ts.map +1 -0
- package/dist/providers/index.d.ts +11 -2
- package/dist/providers/index.d.ts.map +1 -1
- package/dist/providers/policy.d.ts.map +1 -1
- package/dist/providers/product-video-compiler.d.ts +92 -0
- package/dist/providers/product-video-compiler.d.ts.map +1 -0
- package/dist/providers/registry.d.ts +37 -1
- package/dist/providers/registry.d.ts.map +1 -1
- package/dist/providers/renderer.d.ts.map +1 -1
- package/dist/providers/research-compiler.d.ts +64 -0
- package/dist/providers/research-compiler.d.ts.map +1 -0
- package/dist/providers/research-executor.d.ts +27 -0
- package/dist/providers/research-executor.d.ts.map +1 -0
- package/dist/providers/runtime-bundle.d.ts +26 -0
- package/dist/providers/runtime-bundle.d.ts.map +1 -0
- package/dist/providers/runtime-factory.d.ts +6 -1
- package/dist/providers/runtime-factory.d.ts.map +1 -1
- package/dist/providers/runtime-policy.d.ts +24 -0
- package/dist/providers/runtime-policy.d.ts.map +1 -0
- package/dist/providers/shared/anti-bot-policy.d.ts +3 -2
- package/dist/providers/shared/anti-bot-policy.d.ts.map +1 -1
- package/dist/providers/shopping/index.d.ts +11 -1
- package/dist/providers/shopping/index.d.ts.map +1 -1
- package/dist/providers/shopping-compiler.d.ts +51 -0
- package/dist/providers/shopping-compiler.d.ts.map +1 -0
- package/dist/providers/shopping-executor.d.ts +18 -0
- package/dist/providers/shopping-executor.d.ts.map +1 -0
- package/dist/providers/shopping-postprocess.d.ts +46 -0
- package/dist/providers/shopping-postprocess.d.ts.map +1 -0
- package/dist/providers/shopping-workflow.d.ts +33 -0
- package/dist/providers/shopping-workflow.d.ts.map +1 -0
- package/dist/providers/social/platform.d.ts +2 -1
- package/dist/providers/social/platform.d.ts.map +1 -1
- package/dist/providers/social/search-quality.d.ts +16 -0
- package/dist/providers/social/search-quality.d.ts.map +1 -0
- package/dist/providers/social/youtube-resolver.d.ts +2 -1
- package/dist/providers/social/youtube-resolver.d.ts.map +1 -1
- package/dist/providers/social/youtube.d.ts.map +1 -1
- package/dist/providers/types.d.ts +116 -4
- package/dist/providers/types.d.ts.map +1 -1
- package/dist/providers/web/crawl-worker.d.ts.map +1 -1
- package/dist/providers/web/extract.d.ts +16 -0
- package/dist/providers/web/extract.d.ts.map +1 -1
- package/dist/providers/web/index.d.ts.map +1 -1
- package/dist/providers/workflow-contracts.d.ts +53 -0
- package/dist/providers/workflow-contracts.d.ts.map +1 -0
- package/dist/providers/workflows.d.ts +30 -6
- package/dist/providers/workflows.d.ts.map +1 -1
- package/dist/providers-G36AM3Z2.js +121 -0
- package/dist/providers-G36AM3Z2.js.map +1 -0
- package/dist/public-surface/generated-manifest.d.ts +1168 -0
- package/dist/public-surface/generated-manifest.d.ts.map +1 -0
- package/dist/public-surface/source.d.ts +437 -0
- package/dist/public-surface/source.d.ts.map +1 -0
- package/dist/relay/protocol.d.ts +108 -4
- package/dist/relay/protocol.d.ts.map +1 -1
- package/dist/relay/relay-endpoints.d.ts +21 -0
- package/dist/relay/relay-endpoints.d.ts.map +1 -1
- package/dist/relay/relay-server.d.ts +32 -1
- package/dist/relay/relay-server.d.ts.map +1 -1
- package/dist/relay/relay-types.d.ts +3 -0
- package/dist/relay/relay-types.d.ts.map +1 -1
- package/dist/skills/bundled-skill-directories.d.ts +8 -0
- package/dist/skills/bundled-skill-directories.d.ts.map +1 -0
- package/dist/skills/skill-loader.d.ts +9 -1
- package/dist/skills/skill-loader.d.ts.map +1 -1
- package/dist/skills/skill-loader.js +7 -0
- package/dist/skills/skill-loader.js.map +1 -0
- package/dist/skills/skill-nudge.d.ts.map +1 -1
- package/dist/skills/types.d.ts +31 -0
- package/dist/skills/types.d.ts.map +1 -1
- package/dist/snapshot/ops-snapshot.d.ts +1 -1
- package/dist/snapshot/ops-snapshot.d.ts.map +1 -1
- package/dist/snapshot/refs.d.ts +6 -1
- package/dist/snapshot/refs.d.ts.map +1 -1
- package/dist/snapshot/snapshotter.d.ts.map +1 -1
- package/dist/tools/annotate.d.ts.map +1 -1
- package/dist/tools/canvas.d.ts +4 -0
- package/dist/tools/canvas.d.ts.map +1 -0
- package/dist/tools/check.d.ts.map +1 -1
- package/dist/tools/click.d.ts.map +1 -1
- package/dist/tools/clone_component.d.ts.map +1 -1
- package/dist/tools/clone_page.d.ts.map +1 -1
- package/dist/tools/connect.d.ts.map +1 -1
- package/dist/tools/deps.d.ts +6 -0
- package/dist/tools/deps.d.ts.map +1 -1
- package/dist/tools/desktop-shared.d.ts +6 -0
- package/dist/tools/desktop-shared.d.ts.map +1 -0
- package/dist/tools/desktop_accessibility_snapshot.d.ts +4 -0
- package/dist/tools/desktop_accessibility_snapshot.d.ts.map +1 -0
- package/dist/tools/desktop_active_window.d.ts +4 -0
- package/dist/tools/desktop_active_window.d.ts.map +1 -0
- package/dist/tools/desktop_capture_desktop.d.ts +4 -0
- package/dist/tools/desktop_capture_desktop.d.ts.map +1 -0
- package/dist/tools/desktop_capture_window.d.ts +4 -0
- package/dist/tools/desktop_capture_window.d.ts.map +1 -0
- package/dist/tools/desktop_status.d.ts +4 -0
- package/dist/tools/desktop_status.d.ts.map +1 -0
- package/dist/tools/desktop_windows.d.ts +4 -0
- package/dist/tools/desktop_windows.d.ts.map +1 -0
- package/dist/tools/dialog.d.ts +4 -0
- package/dist/tools/dialog.d.ts.map +1 -0
- package/dist/tools/dom_get_html.d.ts.map +1 -1
- package/dist/tools/dom_get_text.d.ts.map +1 -1
- package/dist/tools/get_attr.d.ts.map +1 -1
- package/dist/tools/get_value.d.ts.map +1 -1
- package/dist/tools/goto.d.ts.map +1 -1
- package/dist/tools/hover.d.ts.map +1 -1
- package/dist/tools/index.d.ts +3 -0
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/is_checked.d.ts.map +1 -1
- package/dist/tools/is_enabled.d.ts.map +1 -1
- package/dist/tools/is_visible.d.ts.map +1 -1
- package/dist/tools/launch.d.ts.map +1 -1
- package/dist/tools/macro_resolve.d.ts.map +1 -1
- package/dist/tools/perf.d.ts.map +1 -1
- package/dist/tools/pointer_down.d.ts +4 -0
- package/dist/tools/pointer_down.d.ts.map +1 -0
- package/dist/tools/pointer_drag.d.ts +4 -0
- package/dist/tools/pointer_drag.d.ts.map +1 -0
- package/dist/tools/pointer_move.d.ts +4 -0
- package/dist/tools/pointer_move.d.ts.map +1 -0
- package/dist/tools/pointer_up.d.ts +4 -0
- package/dist/tools/pointer_up.d.ts.map +1 -0
- package/dist/tools/press.d.ts.map +1 -1
- package/dist/tools/product_video_run.d.ts.map +1 -1
- package/dist/tools/prompting_guide.d.ts.map +1 -1
- package/dist/tools/research_run.d.ts.map +1 -1
- package/dist/tools/response.d.ts +4 -1
- package/dist/tools/response.d.ts.map +1 -1
- package/dist/tools/review.d.ts +4 -0
- package/dist/tools/review.d.ts.map +1 -0
- package/dist/tools/screencast_start.d.ts +4 -0
- package/dist/tools/screencast_start.d.ts.map +1 -0
- package/dist/tools/screencast_stop.d.ts +4 -0
- package/dist/tools/screencast_stop.d.ts.map +1 -0
- package/dist/tools/screenshot.d.ts.map +1 -1
- package/dist/tools/scroll.d.ts.map +1 -1
- package/dist/tools/scroll_into_view.d.ts.map +1 -1
- package/dist/tools/select.d.ts.map +1 -1
- package/dist/tools/session_inspector.d.ts +4 -0
- package/dist/tools/session_inspector.d.ts.map +1 -0
- package/dist/tools/shopping_run.d.ts.map +1 -1
- package/dist/tools/skill_list.d.ts.map +1 -1
- package/dist/tools/skill_load.d.ts.map +1 -1
- package/dist/tools/snapshot.d.ts.map +1 -1
- package/dist/tools/type.d.ts.map +1 -1
- package/dist/tools/uncheck.d.ts.map +1 -1
- package/dist/tools/upload.d.ts +4 -0
- package/dist/tools/upload.d.ts.map +1 -0
- package/dist/tools/wait.d.ts.map +1 -1
- package/dist/tools/workflow-runtime.d.ts +4 -2
- package/dist/tools/workflow-runtime.d.ts.map +1 -1
- package/dist/utils/package-assets.d.ts +4 -0
- package/dist/utils/package-assets.d.ts.map +1 -0
- package/extension/canvas.html +1006 -0
- package/extension/dist/annotate-content.css +15 -6
- package/extension/dist/annotate-content.js +175 -35
- package/extension/dist/annotation-payload.js +199 -0
- package/extension/dist/background.js +544 -69
- package/extension/dist/canvas/canvas-runtime.js +1490 -0
- package/extension/dist/canvas/model.js +341 -0
- package/extension/dist/canvas/viewport-fit.js +67 -0
- package/extension/dist/canvas-page.js +3609 -0
- package/extension/dist/ops/dom-bridge.js +255 -3
- package/extension/dist/ops/ops-runtime.js +3324 -301
- package/extension/dist/ops/ops-session-store.js +97 -112
- package/extension/dist/ops/snapshot-builder.js +2 -2
- package/extension/dist/ops/snapshot-shared.js +2 -2
- package/extension/dist/ops/target-session-coordinator.js +159 -0
- package/extension/dist/popup.js +201 -42
- package/extension/dist/services/CDPRouter.js +1567 -63
- package/extension/dist/services/ConnectionManager.js +453 -78
- package/extension/dist/services/RelayClient.js +79 -30
- package/extension/dist/services/TabManager.js +118 -22
- package/extension/dist/services/TargetSessionMap.js +127 -3
- package/extension/dist/services/attach-errors.js +20 -0
- package/extension/dist/services/cdp-router-commands.js +135 -8
- package/extension/dist/services/url-restrictions.js +9 -13
- package/extension/dist/types.js +2 -0
- package/extension/manifest.json +2 -2
- package/extension/popup.html +59 -6
- package/package.json +19 -9
- package/skills/AGENTS.md +8 -4
- package/skills/opendevbrowser-best-practices/SKILL.md +183 -6
- package/skills/opendevbrowser-best-practices/artifacts/browser-agent-known-issues-matrix.md +1 -0
- package/skills/opendevbrowser-best-practices/artifacts/canvas-governance-playbook.md +141 -0
- package/skills/opendevbrowser-best-practices/artifacts/command-channel-reference.md +129 -19
- package/skills/opendevbrowser-best-practices/artifacts/parity-gates.md +9 -2
- package/skills/opendevbrowser-best-practices/artifacts/provider-workflows.md +6 -0
- package/skills/opendevbrowser-best-practices/artifacts/skill-runtime-surface-matrix.md +58 -0
- package/skills/opendevbrowser-best-practices/assets/templates/canvas-blocker-checklist.json +70 -0
- package/skills/opendevbrowser-best-practices/assets/templates/canvas-feedback-eval.json +73 -0
- package/skills/opendevbrowser-best-practices/assets/templates/canvas-generation-plan.v1.json +67 -0
- package/skills/opendevbrowser-best-practices/assets/templates/canvas-handshake-example.json +126 -0
- package/skills/opendevbrowser-best-practices/assets/templates/robustness-checklist.json +57 -0
- package/skills/opendevbrowser-best-practices/assets/templates/skill-runtime-pack-matrix.json +674 -0
- package/skills/opendevbrowser-best-practices/assets/templates/surface-audit-checklist.json +12 -3
- package/skills/opendevbrowser-best-practices/scripts/odb-workflow.sh +107 -12
- package/skills/opendevbrowser-best-practices/scripts/resolve-odb-cli.sh +100 -0
- package/skills/opendevbrowser-best-practices/scripts/run-robustness-audit.sh +83 -1
- package/skills/opendevbrowser-best-practices/scripts/validate-skill-assets.sh +365 -84
- package/skills/opendevbrowser-best-practices/scripts/validator-fixture-cli.sh +208 -0
- package/skills/opendevbrowser-continuity-ledger/SKILL.md +14 -1
- package/skills/opendevbrowser-continuity-ledger/scripts/validate-skill-assets.sh +61 -0
- package/skills/opendevbrowser-data-extraction/SKILL.md +6 -0
- package/skills/opendevbrowser-data-extraction/scripts/validate-skill-assets.sh +112 -0
- package/skills/opendevbrowser-design-agent/SKILL.md +275 -0
- package/skills/opendevbrowser-design-agent/artifacts/app-shell-and-state-wiring.md +84 -0
- package/skills/opendevbrowser-design-agent/artifacts/async-search-state-ownership.md +58 -0
- package/skills/opendevbrowser-design-agent/artifacts/component-pattern-index.md +130 -0
- package/skills/opendevbrowser-design-agent/artifacts/design-contract-playbook.md +157 -0
- package/skills/opendevbrowser-design-agent/artifacts/design-release-gate.md +40 -0
- package/skills/opendevbrowser-design-agent/artifacts/design-workflows.md +153 -0
- package/skills/opendevbrowser-design-agent/artifacts/existing-surface-adaptation.md +56 -0
- package/skills/opendevbrowser-design-agent/artifacts/external-pattern-synthesis.md +103 -0
- package/skills/opendevbrowser-design-agent/artifacts/frontend-evaluation-rubric.md +61 -0
- package/skills/opendevbrowser-design-agent/artifacts/implementation-anti-patterns.md +163 -0
- package/skills/opendevbrowser-design-agent/artifacts/isolated-preview-validation.md +68 -0
- package/skills/opendevbrowser-design-agent/artifacts/loading-and-feedback-surfaces.md +56 -0
- package/skills/opendevbrowser-design-agent/artifacts/opendevbrowser-ui-example-map.md +44 -0
- package/skills/opendevbrowser-design-agent/artifacts/performance-audit-playbook.md +70 -0
- package/skills/opendevbrowser-design-agent/artifacts/research-harvest-workflow.md +81 -0
- package/skills/opendevbrowser-design-agent/artifacts/scroll-reveal-surface-planning.md +64 -0
- package/skills/opendevbrowser-design-agent/artifacts/state-ownership-matrix.md +36 -0
- package/skills/opendevbrowser-design-agent/artifacts/theming-and-token-ownership.md +43 -0
- package/skills/opendevbrowser-design-agent/assets/templates/canvas-generation-plan.design.v1.json +58 -0
- package/skills/opendevbrowser-design-agent/assets/templates/design-audit-report.v1.md +34 -0
- package/skills/opendevbrowser-design-agent/assets/templates/design-brief.v1.md +40 -0
- package/skills/opendevbrowser-design-agent/assets/templates/design-contract.v1.json +226 -0
- package/skills/opendevbrowser-design-agent/assets/templates/design-release-gate.v1.json +35 -0
- package/skills/opendevbrowser-design-agent/assets/templates/design-review-checklist.json +57 -0
- package/skills/opendevbrowser-design-agent/assets/templates/real-surface-design-matrix.json +32 -0
- package/skills/opendevbrowser-design-agent/assets/templates/reference-pattern-board.v1.json +31 -0
- package/skills/opendevbrowser-design-agent/scripts/design-workflow.sh +171 -0
- package/skills/opendevbrowser-design-agent/scripts/extract-canvas-plan.sh +56 -0
- package/skills/opendevbrowser-design-agent/scripts/validate-skill-assets.sh +223 -0
- package/skills/opendevbrowser-form-testing/SKILL.md +19 -3
- package/skills/opendevbrowser-form-testing/artifacts/form-workflows.md +5 -4
- package/skills/opendevbrowser-form-testing/assets/templates/challenge-decision-tree.json +2 -0
- package/skills/opendevbrowser-form-testing/scripts/validate-skill-assets.sh +109 -0
- package/skills/opendevbrowser-login-automation/SKILL.md +21 -3
- package/skills/opendevbrowser-login-automation/artifacts/login-workflows.md +5 -4
- package/skills/opendevbrowser-login-automation/assets/templates/auth-signals.json +5 -0
- package/skills/opendevbrowser-login-automation/assets/templates/login-scenario-matrix.json +3 -2
- package/skills/opendevbrowser-login-automation/scripts/run-login-workflow.sh +17 -1
- package/skills/opendevbrowser-login-automation/scripts/validate-skill-assets.sh +133 -0
- package/skills/opendevbrowser-product-presentation-asset/SKILL.md +23 -11
- package/skills/opendevbrowser-product-presentation-asset/artifacts/asset-pack-assembly.md +5 -3
- package/skills/opendevbrowser-product-presentation-asset/assets/templates/shot-list.md +2 -0
- package/skills/opendevbrowser-product-presentation-asset/assets/templates/video-assembly.md +3 -2
- package/skills/opendevbrowser-product-presentation-asset/scripts/capture-screenshots.sh +5 -1
- package/skills/opendevbrowser-product-presentation-asset/scripts/collect-product.sh +6 -2
- package/skills/opendevbrowser-product-presentation-asset/scripts/download-images.sh +5 -1
- package/skills/opendevbrowser-product-presentation-asset/scripts/render-video-brief.sh +20 -7
- package/skills/opendevbrowser-product-presentation-asset/scripts/validate-skill-assets.sh +39 -0
- package/skills/opendevbrowser-product-presentation-asset/scripts/write-manifest.sh +5 -1
- package/skills/opendevbrowser-research/SKILL.md +14 -6
- package/skills/opendevbrowser-research/scripts/render-output.sh +5 -1
- package/skills/opendevbrowser-research/scripts/run-research.sh +5 -1
- package/skills/opendevbrowser-research/scripts/validate-skill-assets.sh +45 -0
- package/skills/opendevbrowser-research/scripts/write-artifacts.sh +5 -1
- package/skills/opendevbrowser-shopping/SKILL.md +20 -1
- package/skills/opendevbrowser-shopping/scripts/normalize-offers.sh +6 -2
- package/skills/opendevbrowser-shopping/scripts/run-deal-hunt.sh +5 -1
- package/skills/opendevbrowser-shopping/scripts/run-shopping.sh +5 -1
- package/skills/opendevbrowser-shopping/scripts/validate-skill-assets.sh +54 -0
- package/dist/chunk-ST7CO5FA.js +0 -18668
- package/dist/chunk-ST7CO5FA.js.map +0 -1
- /package/dist/{chunk-7W3SPXIB.js.map → chunk-FUSXMW3G.js.map} +0 -0
- /package/dist/{macros-NUBRM44Y.js.map → macros-ND2M7LWU.js.map} +0 -0
|
@@ -29,6 +29,20 @@ const logInfo = (message) => {
|
|
|
29
29
|
const logWarn = (message) => {
|
|
30
30
|
console.warn(`[opendevbrowser] ${message}`);
|
|
31
31
|
};
|
|
32
|
+
const getTrackedTabUrl = (tab) => {
|
|
33
|
+
if (!tab) {
|
|
34
|
+
return undefined;
|
|
35
|
+
}
|
|
36
|
+
const pendingUrl = typeof tab.pendingUrl === "string" && tab.pendingUrl.length > 0 ? tab.pendingUrl : undefined;
|
|
37
|
+
const currentUrl = typeof tab.url === "string" && tab.url.length > 0 ? tab.url : undefined;
|
|
38
|
+
return pendingUrl ?? currentUrl;
|
|
39
|
+
};
|
|
40
|
+
const getTrackedTabTitle = (tab) => {
|
|
41
|
+
if (!tab || tab.status === "loading") {
|
|
42
|
+
return undefined;
|
|
43
|
+
}
|
|
44
|
+
return typeof tab.title === "string" && tab.title.length > 0 ? tab.title : undefined;
|
|
45
|
+
};
|
|
32
46
|
const RECONNECT_INITIAL_DELAY_MS = 12_000;
|
|
33
47
|
const RECONNECT_MAX_DELAY_MS = 30_000;
|
|
34
48
|
export class ConnectionManager {
|
|
@@ -55,8 +69,11 @@ export class ConnectionManager {
|
|
|
55
69
|
connectPromise = null;
|
|
56
70
|
annotationHandler = null;
|
|
57
71
|
opsHandler = null;
|
|
72
|
+
canvasHandler = null;
|
|
58
73
|
heartbeatTimer = null;
|
|
59
74
|
heartbeatInFlight = false;
|
|
75
|
+
handshakeRefreshQueued = false;
|
|
76
|
+
handshakeRefreshPromise = null;
|
|
60
77
|
heartbeatIntervalMs = 25_000;
|
|
61
78
|
heartbeatTimeoutMs = 2_000;
|
|
62
79
|
constructor() {
|
|
@@ -91,6 +108,9 @@ export class ConnectionManager {
|
|
|
91
108
|
onOpsMessage(handler) {
|
|
92
109
|
this.opsHandler = handler;
|
|
93
110
|
}
|
|
111
|
+
onCanvasMessage(handler) {
|
|
112
|
+
this.canvasHandler = handler;
|
|
113
|
+
}
|
|
94
114
|
sendAnnotationResponse(response) {
|
|
95
115
|
if (!this.relay)
|
|
96
116
|
return;
|
|
@@ -121,6 +141,16 @@ export class ConnectionManager {
|
|
|
121
141
|
logError("relay.send_ops_message", error, { code: "relay_send_failed" });
|
|
122
142
|
}
|
|
123
143
|
}
|
|
144
|
+
sendCanvasMessage(message) {
|
|
145
|
+
if (!this.relay)
|
|
146
|
+
return;
|
|
147
|
+
try {
|
|
148
|
+
this.relay.sendCanvasMessage(message);
|
|
149
|
+
}
|
|
150
|
+
catch (error) {
|
|
151
|
+
logError("relay.send_canvas_message", error, { code: "relay_send_failed" });
|
|
152
|
+
}
|
|
153
|
+
}
|
|
124
154
|
getCdpRouter() {
|
|
125
155
|
return this.cdp;
|
|
126
156
|
}
|
|
@@ -129,13 +159,82 @@ export class ConnectionManager {
|
|
|
129
159
|
return null;
|
|
130
160
|
}
|
|
131
161
|
try {
|
|
132
|
-
|
|
162
|
+
const health = await this.relay.sendHealthCheck();
|
|
163
|
+
if (health.extensionConnected && !health.extensionHandshakeComplete) {
|
|
164
|
+
this.relayNotice = "Extension websocket is connected but the daemon-extension handshake is unhealthy. Re-establishing a clean handshake.";
|
|
165
|
+
this.refreshHandshake();
|
|
166
|
+
}
|
|
167
|
+
return health;
|
|
133
168
|
}
|
|
134
169
|
catch (error) {
|
|
135
170
|
logError("relay.health_check", error, { code: "relay_health_failed" });
|
|
136
171
|
return null;
|
|
137
172
|
}
|
|
138
173
|
}
|
|
174
|
+
async sendAnnotationCommand(command, timeoutMs = 5000) {
|
|
175
|
+
const socket = new WebSocket(this.buildAnnotationUrl());
|
|
176
|
+
let settled = false;
|
|
177
|
+
return await new Promise((resolve, reject) => {
|
|
178
|
+
const timeoutId = setTimeout(() => {
|
|
179
|
+
finish(() => reject(new Error("Annotation relay request timed out")));
|
|
180
|
+
}, timeoutMs);
|
|
181
|
+
const finish = (callback) => {
|
|
182
|
+
if (settled) {
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
settled = true;
|
|
186
|
+
clearTimeout(timeoutId);
|
|
187
|
+
try {
|
|
188
|
+
if (socket.readyState === WebSocket.OPEN || socket.readyState === WebSocket.CONNECTING) {
|
|
189
|
+
socket.close(1000, "annotation-command-complete");
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
catch {
|
|
193
|
+
// Ignore socket close failures during cleanup.
|
|
194
|
+
}
|
|
195
|
+
callback();
|
|
196
|
+
};
|
|
197
|
+
socket.addEventListener("open", () => {
|
|
198
|
+
try {
|
|
199
|
+
socket.send(JSON.stringify({
|
|
200
|
+
type: "annotationCommand",
|
|
201
|
+
payload: command
|
|
202
|
+
}));
|
|
203
|
+
}
|
|
204
|
+
catch (error) {
|
|
205
|
+
finish(() => reject(error instanceof Error ? error : new Error("Annotation relay send failed")));
|
|
206
|
+
}
|
|
207
|
+
}, { once: true });
|
|
208
|
+
socket.addEventListener("message", (event) => {
|
|
209
|
+
if (typeof event.data !== "string") {
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
try {
|
|
213
|
+
const message = JSON.parse(event.data);
|
|
214
|
+
if (message.type !== "annotationResponse") {
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
217
|
+
const payload = message.payload;
|
|
218
|
+
if (!isAnnotationResponse(payload) || payload.requestId !== command.requestId) {
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
221
|
+
finish(() => resolve(payload));
|
|
222
|
+
}
|
|
223
|
+
catch {
|
|
224
|
+
// Ignore malformed one-off annotation responses.
|
|
225
|
+
}
|
|
226
|
+
});
|
|
227
|
+
socket.addEventListener("error", () => {
|
|
228
|
+
finish(() => reject(new Error("Annotation relay unavailable")));
|
|
229
|
+
}, { once: true });
|
|
230
|
+
socket.addEventListener("close", () => {
|
|
231
|
+
if (settled) {
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
234
|
+
finish(() => reject(new Error("Annotation relay closed")));
|
|
235
|
+
}, { once: true });
|
|
236
|
+
});
|
|
237
|
+
}
|
|
139
238
|
async connect() {
|
|
140
239
|
if (this.connectPromise) {
|
|
141
240
|
return await this.connectPromise;
|
|
@@ -179,6 +278,7 @@ export class ConnectionManager {
|
|
|
179
278
|
this.shouldReconnect = false;
|
|
180
279
|
this.clearReconnectTimer();
|
|
181
280
|
this.stopHeartbeat();
|
|
281
|
+
this.handshakeRefreshQueued = false;
|
|
182
282
|
try {
|
|
183
283
|
if (this.relay) {
|
|
184
284
|
this.relay.disconnect();
|
|
@@ -214,6 +314,38 @@ export class ConnectionManager {
|
|
|
214
314
|
logError(context, error, { code: "relay_send_failed" });
|
|
215
315
|
}
|
|
216
316
|
}
|
|
317
|
+
async getFirstHttpFallbackTab(currentTabId) {
|
|
318
|
+
const fallbackTab = await this.tabs.getFirstAttachableTab(currentTabId);
|
|
319
|
+
if (!fallbackTab || typeof fallbackTab.id !== "number" || !fallbackTab.url) {
|
|
320
|
+
return null;
|
|
321
|
+
}
|
|
322
|
+
logInfo("Falling back to first http(s) tab.");
|
|
323
|
+
return fallbackTab;
|
|
324
|
+
}
|
|
325
|
+
async bootstrapRelayAttachTab() {
|
|
326
|
+
try {
|
|
327
|
+
const fallbackTab = await this.tabs.createTab("about:blank", true);
|
|
328
|
+
if (fallbackTab && typeof fallbackTab.id === "number") {
|
|
329
|
+
logInfo("Bootstrapping a fresh browser tab for relay attach.");
|
|
330
|
+
return fallbackTab;
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
catch {
|
|
334
|
+
// Ignore tab creation failures and let the caller surface the original error.
|
|
335
|
+
}
|
|
336
|
+
return null;
|
|
337
|
+
}
|
|
338
|
+
async resolveRelayAttachFallback(currentTabId) {
|
|
339
|
+
const httpTab = await this.getFirstHttpFallbackTab(currentTabId);
|
|
340
|
+
if (httpTab) {
|
|
341
|
+
return { tab: httpTab, allowBlankRelayFallback: false };
|
|
342
|
+
}
|
|
343
|
+
const blankTab = await this.bootstrapRelayAttachTab();
|
|
344
|
+
if (blankTab) {
|
|
345
|
+
return { tab: blankTab, allowBlankRelayFallback: true };
|
|
346
|
+
}
|
|
347
|
+
return { tab: null, allowBlankRelayFallback: false };
|
|
348
|
+
}
|
|
217
349
|
startHeartbeat() {
|
|
218
350
|
if (this.heartbeatTimer !== null) {
|
|
219
351
|
return;
|
|
@@ -240,7 +372,15 @@ export class ConnectionManager {
|
|
|
240
372
|
}
|
|
241
373
|
this.heartbeatInFlight = true;
|
|
242
374
|
try {
|
|
243
|
-
await this.relay.sendPing(this.heartbeatTimeoutMs);
|
|
375
|
+
const health = await this.relay.sendPing(this.heartbeatTimeoutMs);
|
|
376
|
+
if (health.extensionConnected && !health.extensionHandshakeComplete) {
|
|
377
|
+
this.relayNotice = "Extension websocket is connected but the daemon-extension handshake is incomplete. Re-establishing a clean handshake.";
|
|
378
|
+
this.refreshHandshake();
|
|
379
|
+
return;
|
|
380
|
+
}
|
|
381
|
+
if (health.ok) {
|
|
382
|
+
this.relayNotice = null;
|
|
383
|
+
}
|
|
244
384
|
}
|
|
245
385
|
catch (error) {
|
|
246
386
|
logError("relay.heartbeat", error, { code: "relay_heartbeat_failed" });
|
|
@@ -254,29 +394,35 @@ export class ConnectionManager {
|
|
|
254
394
|
}
|
|
255
395
|
async attachToActiveTab() {
|
|
256
396
|
let tab = await this.tabs.getActiveTab();
|
|
397
|
+
let allowBlankRelayFallback = false;
|
|
398
|
+
let tabUrl = getTrackedTabUrl(tab);
|
|
257
399
|
if (!tab || typeof tab.id !== "number") {
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
400
|
+
const fallback = await this.resolveRelayAttachFallback();
|
|
401
|
+
tab = fallback.tab;
|
|
402
|
+
allowBlankRelayFallback = fallback.allowBlankRelayFallback;
|
|
403
|
+
tabUrl = getTrackedTabUrl(tab);
|
|
404
|
+
if (!tab || typeof tab.id !== "number") {
|
|
405
|
+
this.trackedTab = null;
|
|
406
|
+
this.setStatus("disconnected");
|
|
407
|
+
logWarn("Active tab not found.");
|
|
408
|
+
throw new ConnectionError("no_active_tab", "No active browser page found. Focus the site tab or popup window you want to automate, not the extension popup, and retry.");
|
|
409
|
+
}
|
|
262
410
|
}
|
|
263
|
-
if (!
|
|
411
|
+
if (!tabUrl) {
|
|
264
412
|
logWarn("Active tab URL missing.");
|
|
265
|
-
const
|
|
266
|
-
if (
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
tab = fallbackTab;
|
|
271
|
-
}
|
|
413
|
+
const fallback = await this.resolveRelayAttachFallback(tab.id);
|
|
414
|
+
if (fallback.tab) {
|
|
415
|
+
tab = fallback.tab;
|
|
416
|
+
allowBlankRelayFallback ||= fallback.allowBlankRelayFallback;
|
|
417
|
+
tabUrl = getTrackedTabUrl(tab);
|
|
272
418
|
}
|
|
273
|
-
if (!
|
|
419
|
+
if (!tabUrl) {
|
|
274
420
|
throw new ConnectionError("tab_url_missing", "Active tab URL is unavailable. Reload the tab and retry.");
|
|
275
421
|
}
|
|
276
422
|
}
|
|
277
423
|
let parsedUrl = null;
|
|
278
424
|
try {
|
|
279
|
-
parsedUrl = new URL(
|
|
425
|
+
parsedUrl = tabUrl ? new URL(tabUrl) : null;
|
|
280
426
|
}
|
|
281
427
|
catch (error) {
|
|
282
428
|
logError("connection.parse_tab_url", error, { code: "tab_url_parse_failed" });
|
|
@@ -284,54 +430,48 @@ export class ConnectionManager {
|
|
|
284
430
|
}
|
|
285
431
|
if (!parsedUrl) {
|
|
286
432
|
logWarn("Active tab URL is invalid.");
|
|
287
|
-
const
|
|
288
|
-
if (
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
parsedUrl = null;
|
|
298
|
-
}
|
|
433
|
+
const fallback = await this.resolveRelayAttachFallback(tab.id);
|
|
434
|
+
if (fallback.tab) {
|
|
435
|
+
tab = fallback.tab;
|
|
436
|
+
allowBlankRelayFallback ||= fallback.allowBlankRelayFallback;
|
|
437
|
+
tabUrl = getTrackedTabUrl(tab);
|
|
438
|
+
try {
|
|
439
|
+
parsedUrl = tabUrl ? new URL(tabUrl) : null;
|
|
440
|
+
}
|
|
441
|
+
catch {
|
|
442
|
+
parsedUrl = null;
|
|
299
443
|
}
|
|
300
444
|
}
|
|
301
445
|
if (!parsedUrl) {
|
|
302
|
-
throw new ConnectionError("tab_url_restricted", "Active
|
|
446
|
+
throw new ConnectionError("tab_url_restricted", "Active browser page URL is unsupported. Focus an http(s) page or site popup window, not the extension popup, and retry.");
|
|
303
447
|
}
|
|
304
448
|
}
|
|
305
449
|
const restrictionMessage = getRestrictionMessage(parsedUrl);
|
|
306
450
|
if (restrictionMessage) {
|
|
307
|
-
logWarn(`Active tab blocked: ${summarizeProtocol(
|
|
308
|
-
const
|
|
309
|
-
if (
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
parsedUrl = fallbackUrl;
|
|
319
|
-
}
|
|
320
|
-
}
|
|
321
|
-
catch {
|
|
322
|
-
// Ignore invalid fallback URL.
|
|
323
|
-
}
|
|
451
|
+
logWarn(`Active tab blocked: ${summarizeProtocol(tabUrl)} scheme.`);
|
|
452
|
+
const fallback = await this.resolveRelayAttachFallback(tab.id);
|
|
453
|
+
if (fallback.tab) {
|
|
454
|
+
tab = fallback.tab;
|
|
455
|
+
allowBlankRelayFallback ||= fallback.allowBlankRelayFallback;
|
|
456
|
+
tabUrl = getTrackedTabUrl(tab);
|
|
457
|
+
try {
|
|
458
|
+
parsedUrl = tabUrl ? new URL(tabUrl) : null;
|
|
459
|
+
}
|
|
460
|
+
catch {
|
|
461
|
+
parsedUrl = null;
|
|
324
462
|
}
|
|
325
463
|
}
|
|
326
|
-
if (restrictionMessage && getRestrictionMessage(parsedUrl)) {
|
|
327
|
-
|
|
464
|
+
if (restrictionMessage && (!parsedUrl || getRestrictionMessage(parsedUrl))) {
|
|
465
|
+
if (!allowBlankRelayFallback) {
|
|
466
|
+
throw new ConnectionError("tab_url_restricted", restrictionMessage);
|
|
467
|
+
}
|
|
328
468
|
}
|
|
329
469
|
}
|
|
330
470
|
const tabId = tab.id;
|
|
331
471
|
if (typeof tabId !== "number") {
|
|
332
472
|
this.trackedTab = null;
|
|
333
473
|
this.setStatus("disconnected");
|
|
334
|
-
throw new ConnectionError("no_active_tab", "No active browser
|
|
474
|
+
throw new ConnectionError("no_active_tab", "No active browser page found. Focus the site tab or popup window you want to automate, not the extension popup, and retry.");
|
|
335
475
|
}
|
|
336
476
|
logInfo("Active tab resolved.");
|
|
337
477
|
try {
|
|
@@ -346,12 +486,7 @@ export class ConnectionManager {
|
|
|
346
486
|
: "Debugger attach failed. Close DevTools for the tab and retry.";
|
|
347
487
|
throw new ConnectionError("debugger_attach_failed", message);
|
|
348
488
|
}
|
|
349
|
-
this.trackedTab =
|
|
350
|
-
id: tabId,
|
|
351
|
-
url: tab.url ?? undefined,
|
|
352
|
-
title: tab.title ?? undefined,
|
|
353
|
-
groupId: typeof tab.groupId === "number" ? tab.groupId : undefined
|
|
354
|
-
};
|
|
489
|
+
this.trackedTab = this.toTrackedTab(tab, null);
|
|
355
490
|
}
|
|
356
491
|
async connectRelay() {
|
|
357
492
|
if (!this.trackedTab) {
|
|
@@ -364,12 +499,18 @@ export class ConnectionManager {
|
|
|
364
499
|
this.handleCdpDetach({ reason: "cdp_command_failed" });
|
|
365
500
|
});
|
|
366
501
|
},
|
|
502
|
+
onCdpControl: (message) => {
|
|
503
|
+
this.handleCdpControl(message);
|
|
504
|
+
},
|
|
367
505
|
onAnnotationCommand: (command) => {
|
|
368
506
|
this.annotationHandler?.(command);
|
|
369
507
|
},
|
|
370
508
|
onOpsMessage: (message) => {
|
|
371
509
|
this.opsHandler?.(message);
|
|
372
510
|
},
|
|
511
|
+
onCanvasMessage: (message) => {
|
|
512
|
+
this.canvasHandler?.(message);
|
|
513
|
+
},
|
|
373
514
|
onClose: (detail) => {
|
|
374
515
|
this.handleRelayClose(detail);
|
|
375
516
|
}
|
|
@@ -403,6 +544,10 @@ export class ConnectionManager {
|
|
|
403
544
|
if (!mismatch) {
|
|
404
545
|
this.persistRelayIdentity(ack.payload.relayPort, this.relayInstanceId, this.relayEpoch);
|
|
405
546
|
}
|
|
547
|
+
const handshakeHealthy = await this.verifyHandshakeHealth(relay, "connect");
|
|
548
|
+
if (!handshakeHealthy) {
|
|
549
|
+
return;
|
|
550
|
+
}
|
|
406
551
|
logInfo("Relay WebSocket connected.");
|
|
407
552
|
this.setStatus("connected");
|
|
408
553
|
this.startHeartbeat();
|
|
@@ -421,6 +566,7 @@ export class ConnectionManager {
|
|
|
421
566
|
handleRelayClose(detail) {
|
|
422
567
|
this.stopHeartbeat();
|
|
423
568
|
this.relay = null;
|
|
569
|
+
this.cdp.markClientClosed();
|
|
424
570
|
if (detail && (detail.code === 1008 || detail.reason?.includes("Invalid pairing token"))) {
|
|
425
571
|
this.clearStoredPairingToken();
|
|
426
572
|
}
|
|
@@ -448,6 +594,10 @@ export class ConnectionManager {
|
|
|
448
594
|
if (this.cdp.getAttachedTabIds().length > 0) {
|
|
449
595
|
return;
|
|
450
596
|
}
|
|
597
|
+
if (detail?.reason === "manual_disconnect") {
|
|
598
|
+
void this.recoverFromManualDetach(detail);
|
|
599
|
+
return;
|
|
600
|
+
}
|
|
451
601
|
this.setStatus("disconnected");
|
|
452
602
|
if (this.relay?.isConnected()) {
|
|
453
603
|
this.relay.disconnect();
|
|
@@ -455,12 +605,49 @@ export class ConnectionManager {
|
|
|
455
605
|
}
|
|
456
606
|
this.scheduleReconnect();
|
|
457
607
|
}
|
|
608
|
+
async recoverFromManualDetach(detail) {
|
|
609
|
+
try {
|
|
610
|
+
const preferredTabId = typeof detail?.tabId === "number" ? detail.tabId : this.trackedTab?.id ?? null;
|
|
611
|
+
if (typeof preferredTabId === "number") {
|
|
612
|
+
await this.cdp.attach(preferredTabId);
|
|
613
|
+
const recoveredTabId = this.cdp.getPrimaryTabId() ?? preferredTabId;
|
|
614
|
+
await this.refreshTrackedTab(recoveredTabId, { preserveCurrentOnRestricted: true });
|
|
615
|
+
}
|
|
616
|
+
else {
|
|
617
|
+
await this.attachToActiveTab();
|
|
618
|
+
}
|
|
619
|
+
if (!this.relay?.isConnected()) {
|
|
620
|
+
this.scheduleReconnect();
|
|
621
|
+
return;
|
|
622
|
+
}
|
|
623
|
+
this.setStatus("connected");
|
|
624
|
+
this.refreshHandshake();
|
|
625
|
+
}
|
|
626
|
+
catch (error) {
|
|
627
|
+
logError("connection.manual_detach_recover", error, { code: "tracked_tab_refresh_failed" });
|
|
628
|
+
this.setStatus("disconnected");
|
|
629
|
+
if (this.relay?.isConnected()) {
|
|
630
|
+
this.relay.disconnect();
|
|
631
|
+
return;
|
|
632
|
+
}
|
|
633
|
+
this.scheduleReconnect();
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
handleCdpControl(message) {
|
|
637
|
+
if (message.action !== "client_closed") {
|
|
638
|
+
return;
|
|
639
|
+
}
|
|
640
|
+
this.cdp.markClientClosed();
|
|
641
|
+
}
|
|
458
642
|
scheduleReconnect() {
|
|
459
643
|
if (this.reconnectTimer !== null) {
|
|
460
644
|
return;
|
|
461
645
|
}
|
|
462
646
|
this.reconnectTimer = setTimeout(() => {
|
|
463
647
|
this.reconnectTimer = null;
|
|
648
|
+
if (!this.shouldReconnect || this.status === "connected" || this.relay?.isConnected()) {
|
|
649
|
+
return;
|
|
650
|
+
}
|
|
464
651
|
this.reconnectAttempts += 1;
|
|
465
652
|
this.reconnectDelayMs = Math.min(this.reconnectDelayMs * 2, this.maxReconnectDelayMs);
|
|
466
653
|
this.reconnectRelay().catch((error) => {
|
|
@@ -470,7 +657,7 @@ export class ConnectionManager {
|
|
|
470
657
|
}, this.reconnectDelayMs);
|
|
471
658
|
}
|
|
472
659
|
async reconnectRelay() {
|
|
473
|
-
if (!this.shouldReconnect) {
|
|
660
|
+
if (!this.shouldReconnect || this.status === "connected" || this.relay?.isConnected()) {
|
|
474
661
|
return;
|
|
475
662
|
}
|
|
476
663
|
const primaryId = this.cdp.getPrimaryTabId();
|
|
@@ -527,24 +714,59 @@ export class ConnectionManager {
|
|
|
527
714
|
if (!this.trackedTab || this.trackedTab.id !== tabId) {
|
|
528
715
|
return;
|
|
529
716
|
}
|
|
530
|
-
|
|
717
|
+
const attachedTabIds = this.cdp.getAttachedTabIds().filter((attachedId) => attachedId !== tabId);
|
|
718
|
+
if (attachedTabIds.length === 0) {
|
|
531
719
|
this.disconnect().catch((error) => {
|
|
532
720
|
logError("connection.tab_removed_disconnect", error, { code: "disconnect_failed" });
|
|
533
721
|
});
|
|
722
|
+
return;
|
|
534
723
|
}
|
|
724
|
+
const primaryTabId = this.cdp.getPrimaryTabId();
|
|
725
|
+
const nextTrackedTabId = primaryTabId && primaryTabId !== tabId
|
|
726
|
+
? primaryTabId
|
|
727
|
+
: attachedTabIds[0] ?? null;
|
|
728
|
+
if (!nextTrackedTabId) {
|
|
729
|
+
this.disconnect().catch((error) => {
|
|
730
|
+
logError("connection.tab_removed_disconnect", error, { code: "disconnect_failed" });
|
|
731
|
+
});
|
|
732
|
+
return;
|
|
733
|
+
}
|
|
734
|
+
this.refreshTrackedTab(nextTrackedTabId, { preserveCurrentOnRestricted: true })
|
|
735
|
+
.then(() => {
|
|
736
|
+
this.refreshHandshake();
|
|
737
|
+
})
|
|
738
|
+
.catch((error) => {
|
|
739
|
+
logError("connection.tab_removed_refresh", error, { code: "tracked_tab_refresh_failed" });
|
|
740
|
+
});
|
|
535
741
|
};
|
|
536
742
|
handleTabUpdated = (_tabId, _changeInfo, tab) => {
|
|
537
|
-
|
|
743
|
+
const updatedTabId = typeof tab.id === "number" ? tab.id : null;
|
|
744
|
+
if (updatedTabId === null) {
|
|
538
745
|
return;
|
|
539
746
|
}
|
|
540
|
-
this.trackedTab
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
747
|
+
const trackedTabId = this.trackedTab?.id ?? null;
|
|
748
|
+
const primaryTabId = this.cdp.getPrimaryTabId();
|
|
749
|
+
if (trackedTabId !== updatedTabId && primaryTabId !== updatedTabId) {
|
|
750
|
+
return;
|
|
751
|
+
}
|
|
752
|
+
if (trackedTabId !== updatedTabId) {
|
|
753
|
+
if (!this.isRestrictedTab(tab)) {
|
|
754
|
+
this.setTrackedTab(tab);
|
|
755
|
+
this.refreshHandshake();
|
|
756
|
+
return;
|
|
757
|
+
}
|
|
758
|
+
this.refreshTrackedTab(updatedTabId, { preserveCurrentOnRestricted: true })
|
|
759
|
+
.then(() => {
|
|
760
|
+
this.refreshHandshake();
|
|
761
|
+
})
|
|
762
|
+
.catch((error) => {
|
|
763
|
+
logError("connection.tab_updated_refresh", error, { code: "tracked_tab_refresh_failed" });
|
|
764
|
+
});
|
|
765
|
+
return;
|
|
766
|
+
}
|
|
767
|
+
this.setTrackedTab(tab);
|
|
546
768
|
if (this.relay?.isConnected()) {
|
|
547
|
-
this.
|
|
769
|
+
this.refreshHandshake();
|
|
548
770
|
}
|
|
549
771
|
};
|
|
550
772
|
async loadSettings() {
|
|
@@ -567,7 +789,7 @@ export class ConnectionManager {
|
|
|
567
789
|
}
|
|
568
790
|
return {
|
|
569
791
|
code: "unknown",
|
|
570
|
-
message: "Connection failed. Focus
|
|
792
|
+
message: "Connection failed. Focus the site tab or popup window you want to automate, not the extension popup, and retry."
|
|
571
793
|
};
|
|
572
794
|
}
|
|
573
795
|
updatePairingToken(value) {
|
|
@@ -649,9 +871,9 @@ export class ConnectionManager {
|
|
|
649
871
|
this.clearStoredRelayIdentity();
|
|
650
872
|
this.clearStoredPairingToken(false);
|
|
651
873
|
this.relayNotice = instanceMismatch
|
|
652
|
-
? "Relay instance changed. Re-
|
|
653
|
-
: "Relay restarted. Re-
|
|
654
|
-
this.
|
|
874
|
+
? "Relay instance changed. Re-establishing a clean daemon-extension handshake."
|
|
875
|
+
: "Relay restarted. Re-establishing a clean daemon-extension handshake.";
|
|
876
|
+
this.refreshHandshake();
|
|
655
877
|
return true;
|
|
656
878
|
}
|
|
657
879
|
this.relayNotice = null;
|
|
@@ -665,6 +887,13 @@ export class ConnectionManager {
|
|
|
665
887
|
buildRelayUrl() {
|
|
666
888
|
return `ws://127.0.0.1:${this.relayPort}/extension`;
|
|
667
889
|
}
|
|
890
|
+
buildAnnotationUrl() {
|
|
891
|
+
const port = this.relayConfirmedPort ?? this.relayPort;
|
|
892
|
+
const query = this.pairingEnabled && this.pairingToken
|
|
893
|
+
? `?token=${encodeURIComponent(this.pairingToken)}`
|
|
894
|
+
: "";
|
|
895
|
+
return `ws://127.0.0.1:${port}/annotation${query}`;
|
|
896
|
+
}
|
|
668
897
|
async refreshRelay() {
|
|
669
898
|
if (this.status !== "connected")
|
|
670
899
|
return;
|
|
@@ -673,26 +902,101 @@ export class ConnectionManager {
|
|
|
673
902
|
}
|
|
674
903
|
async handlePrimaryTabChange(tabId) {
|
|
675
904
|
if (!tabId) {
|
|
905
|
+
const trackedTabId = this.trackedTab?.id;
|
|
906
|
+
if (this.shouldReconnect && !this.disconnecting && typeof trackedTabId === "number") {
|
|
907
|
+
const trackedTab = await this.tabs.getTab(trackedTabId);
|
|
908
|
+
if (trackedTab && typeof trackedTab.id === "number") {
|
|
909
|
+
await this.refreshTrackedTab(trackedTab.id, { preserveCurrentOnRestricted: true });
|
|
910
|
+
this.refreshHandshake();
|
|
911
|
+
return;
|
|
912
|
+
}
|
|
913
|
+
}
|
|
676
914
|
this.trackedTab = null;
|
|
677
915
|
if (this.relay?.isConnected()) {
|
|
678
916
|
this.relay.disconnect();
|
|
679
917
|
}
|
|
680
918
|
return;
|
|
681
919
|
}
|
|
682
|
-
await this.refreshTrackedTab(tabId);
|
|
920
|
+
await this.refreshTrackedTab(tabId, { preserveCurrentOnRestricted: true });
|
|
683
921
|
this.refreshHandshake();
|
|
684
922
|
}
|
|
685
|
-
|
|
686
|
-
const
|
|
923
|
+
isRestrictedTab(tab) {
|
|
924
|
+
const rawUrl = getTrackedTabUrl(tab);
|
|
925
|
+
if (!rawUrl) {
|
|
926
|
+
return true;
|
|
927
|
+
}
|
|
928
|
+
try {
|
|
929
|
+
return Boolean(getRestrictionMessage(new URL(rawUrl)));
|
|
930
|
+
}
|
|
931
|
+
catch {
|
|
932
|
+
return true;
|
|
933
|
+
}
|
|
934
|
+
}
|
|
935
|
+
async refreshTrackedTab(tabId, options) {
|
|
936
|
+
const previous = this.trackedTab;
|
|
937
|
+
let tab = await this.tabs.getTab(tabId);
|
|
938
|
+
if ((!tab || typeof tab.id !== "number") && options?.preserveCurrentOnRestricted && previous) {
|
|
939
|
+
this.trackedTab = previous;
|
|
940
|
+
return;
|
|
941
|
+
}
|
|
687
942
|
if (!tab || typeof tab.id !== "number") {
|
|
688
943
|
this.trackedTab = null;
|
|
689
944
|
return;
|
|
690
945
|
}
|
|
691
|
-
this.
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
946
|
+
if (this.isRestrictedTab(tab)) {
|
|
947
|
+
const httpFallback = await this.getFirstHttpFallbackTab(tab.id);
|
|
948
|
+
if (httpFallback) {
|
|
949
|
+
tab = httpFallback;
|
|
950
|
+
}
|
|
951
|
+
else if (options?.preserveCurrentOnRestricted && previous) {
|
|
952
|
+
this.trackedTab = previous;
|
|
953
|
+
return;
|
|
954
|
+
}
|
|
955
|
+
else {
|
|
956
|
+
const blankFallback = await this.bootstrapRelayAttachTab();
|
|
957
|
+
if (blankFallback) {
|
|
958
|
+
tab = blankFallback;
|
|
959
|
+
}
|
|
960
|
+
else {
|
|
961
|
+
this.trackedTab = null;
|
|
962
|
+
return;
|
|
963
|
+
}
|
|
964
|
+
}
|
|
965
|
+
}
|
|
966
|
+
const nextTrackedTabId = tab.id;
|
|
967
|
+
if (typeof nextTrackedTabId !== "number") {
|
|
968
|
+
if (options?.preserveCurrentOnRestricted && previous) {
|
|
969
|
+
this.trackedTab = previous;
|
|
970
|
+
return;
|
|
971
|
+
}
|
|
972
|
+
this.trackedTab = null;
|
|
973
|
+
return;
|
|
974
|
+
}
|
|
975
|
+
this.setTrackedTab(tab);
|
|
976
|
+
}
|
|
977
|
+
setTrackedTab(tab) {
|
|
978
|
+
const tabId = typeof tab.id === "number" ? tab.id : null;
|
|
979
|
+
if (tabId === null) {
|
|
980
|
+
return;
|
|
981
|
+
}
|
|
982
|
+
this.trackedTab = this.toTrackedTab(tab, this.trackedTab);
|
|
983
|
+
}
|
|
984
|
+
toTrackedTab(tab, previous) {
|
|
985
|
+
const tabId = typeof tab.id === "number" ? tab.id : null;
|
|
986
|
+
if (tabId === null) {
|
|
987
|
+
throw new Error("Tracked tab id is missing");
|
|
988
|
+
}
|
|
989
|
+
const sameTab = previous?.id === tabId;
|
|
990
|
+
const url = getTrackedTabUrl(tab) ?? (sameTab ? previous?.url : undefined);
|
|
991
|
+
const title = getTrackedTabTitle(tab) ?? (sameTab ? previous?.title : undefined);
|
|
992
|
+
const groupId = typeof tab.groupId === "number"
|
|
993
|
+
? tab.groupId
|
|
994
|
+
: (sameTab ? previous?.groupId : undefined);
|
|
995
|
+
return {
|
|
996
|
+
id: tabId,
|
|
997
|
+
...(url ? { url } : {}),
|
|
998
|
+
...(title ? { title } : {}),
|
|
999
|
+
...(typeof groupId === "number" ? { groupId } : {})
|
|
696
1000
|
};
|
|
697
1001
|
}
|
|
698
1002
|
clearReconnectTimer() {
|
|
@@ -701,10 +1005,81 @@ export class ConnectionManager {
|
|
|
701
1005
|
this.reconnectTimer = null;
|
|
702
1006
|
}
|
|
703
1007
|
}
|
|
1008
|
+
async verifyHandshakeHealth(relay, source) {
|
|
1009
|
+
try {
|
|
1010
|
+
const health = await relay.sendPing(this.heartbeatTimeoutMs);
|
|
1011
|
+
if (health.extensionConnected && health.extensionHandshakeComplete) {
|
|
1012
|
+
if (this.relay === relay) {
|
|
1013
|
+
this.relayNotice = null;
|
|
1014
|
+
}
|
|
1015
|
+
return true;
|
|
1016
|
+
}
|
|
1017
|
+
if (this.relay === relay) {
|
|
1018
|
+
this.relayNotice = "Extension websocket is connected but the daemon-extension handshake is still incomplete. Retrying a clean handshake.";
|
|
1019
|
+
if (this.shouldReconnect && !this.disconnecting) {
|
|
1020
|
+
relay.disconnect();
|
|
1021
|
+
}
|
|
1022
|
+
}
|
|
1023
|
+
}
|
|
1024
|
+
catch (error) {
|
|
1025
|
+
logError(`relay.${source}_handshake_health`, error, { code: "relay_handshake_health_failed" });
|
|
1026
|
+
if (this.relay === relay) {
|
|
1027
|
+
this.relayNotice = "Failed to verify a clean daemon-extension handshake. Retrying the relay connection.";
|
|
1028
|
+
if (this.shouldReconnect && !this.disconnecting) {
|
|
1029
|
+
relay.disconnect();
|
|
1030
|
+
}
|
|
1031
|
+
}
|
|
1032
|
+
}
|
|
1033
|
+
return false;
|
|
1034
|
+
}
|
|
704
1035
|
refreshHandshake() {
|
|
705
1036
|
if (!this.trackedTab || !this.relay?.isConnected()) {
|
|
706
1037
|
return;
|
|
707
1038
|
}
|
|
708
|
-
this.
|
|
1039
|
+
this.handshakeRefreshQueued = true;
|
|
1040
|
+
if (this.handshakeRefreshPromise) {
|
|
1041
|
+
return;
|
|
1042
|
+
}
|
|
1043
|
+
const run = (async () => {
|
|
1044
|
+
while (this.handshakeRefreshQueued) {
|
|
1045
|
+
this.handshakeRefreshQueued = false;
|
|
1046
|
+
const relay = this.relay;
|
|
1047
|
+
if (!this.trackedTab || !relay || !relay.isConnected()) {
|
|
1048
|
+
return;
|
|
1049
|
+
}
|
|
1050
|
+
try {
|
|
1051
|
+
await relay.sendHandshake(this.buildHandshake());
|
|
1052
|
+
const handshakeHealthy = await this.verifyHandshakeHealth(relay, "refresh");
|
|
1053
|
+
if (!handshakeHealthy) {
|
|
1054
|
+
return;
|
|
1055
|
+
}
|
|
1056
|
+
}
|
|
1057
|
+
catch (error) {
|
|
1058
|
+
logError("relay.refresh_handshake", error, { code: "relay_handshake_refresh_failed" });
|
|
1059
|
+
if (this.relay === relay) {
|
|
1060
|
+
this.relayNotice = "Failed to re-establish a clean daemon-extension handshake. Open the extension popup, click Connect again, confirm `status --daemon` shows ext=on and handshake=on, then retry.";
|
|
1061
|
+
if (this.shouldReconnect && !this.disconnecting) {
|
|
1062
|
+
relay.disconnect();
|
|
1063
|
+
}
|
|
1064
|
+
}
|
|
1065
|
+
return;
|
|
1066
|
+
}
|
|
1067
|
+
}
|
|
1068
|
+
})();
|
|
1069
|
+
const refreshPromise = run.finally(() => {
|
|
1070
|
+
if (this.handshakeRefreshPromise === refreshPromise) {
|
|
1071
|
+
this.handshakeRefreshPromise = null;
|
|
1072
|
+
}
|
|
1073
|
+
});
|
|
1074
|
+
this.handshakeRefreshPromise = refreshPromise;
|
|
709
1075
|
}
|
|
710
1076
|
}
|
|
1077
|
+
const isAnnotationResponse = (value) => {
|
|
1078
|
+
if (!value || typeof value !== "object") {
|
|
1079
|
+
return false;
|
|
1080
|
+
}
|
|
1081
|
+
const record = value;
|
|
1082
|
+
return record.version === 1
|
|
1083
|
+
&& typeof record.requestId === "string"
|
|
1084
|
+
&& (record.status === "ok" || record.status === "cancelled" || record.status === "error");
|
|
1085
|
+
};
|