@reticlehq/server 3.8.2 → 3.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -104
- package/NOTICE +5 -0
- package/README.md +1 -1
- package/SKILL.md +13 -12
- package/bin/launch.js +13 -0
- package/bin/package.json +3 -0
- package/bin/reticle.js +66 -8
- package/dist/chromium-launch-options.d.ts +25 -0
- package/dist/chromium-launch-options.js +21 -1
- package/dist/command/cli/adhoc-suite.js +2 -0
- package/dist/command/cli/adhoc-verdict.d.ts +2 -43
- package/dist/command/cli/adhoc-verdict.js +50 -160
- package/dist/command/cli/answers/gate-exit.d.ts +6 -2
- package/dist/command/cli/answers/gate-exit.js +12 -2
- package/dist/command/cli/answers/mcp-connection-hint.d.ts +2 -0
- package/dist/command/cli/answers/mcp-connection-hint.js +6 -0
- package/dist/command/cli/ci-hint.d.ts +44 -0
- package/dist/command/cli/ci-hint.js +72 -0
- package/dist/command/cli/cli-doctor.d.ts +6 -1
- package/dist/command/cli/cli-doctor.js +46 -5
- package/dist/command/cli/cli-flow-commands.d.ts +7 -1
- package/dist/command/cli/cli-flow-commands.js +39 -24
- package/dist/command/cli/cli-kill.d.ts +21 -0
- package/dist/command/cli/cli-kill.js +47 -4
- package/dist/command/cli/cli-parse-compare.d.ts +22 -0
- package/dist/command/cli/cli-parse-compare.js +75 -0
- package/dist/command/cli/cli-parse-grade.d.ts +36 -0
- package/dist/command/cli/cli-parse-grade.js +75 -0
- package/dist/command/cli/cli-parse-grammar.d.ts +2 -0
- package/dist/command/cli/cli-parse-grammar.js +18 -20
- package/dist/command/cli/cli-parse-verify.d.ts +10 -0
- package/dist/command/cli/cli-parse-verify.js +63 -14
- package/dist/command/cli/cli-parse.d.ts +22 -17
- package/dist/command/cli/cli-parse.js +54 -32
- package/dist/command/cli/cli-update-commands.d.ts +1 -1
- package/dist/command/cli/cli-update-commands.js +29 -20
- package/dist/command/cli/cli-usage.js +61 -31
- package/dist/command/cli/cli-verify.d.ts +17 -3
- package/dist/command/cli/cli-verify.js +59 -21
- package/dist/command/cli/cloud-cli.js +2 -119
- package/dist/command/cli/daemon-link/daemon-client.d.ts +45 -0
- package/dist/command/cli/daemon-link/daemon-client.js +205 -0
- package/dist/command/cli/doctor/browser/chromium-hint.d.ts +6 -1
- package/dist/command/cli/doctor/browser/chromium-hint.js +11 -5
- package/dist/command/cli/doctor/doctor-daemon-line.js +6 -3
- package/dist/command/cli/doctor/doctor-fix.d.ts +44 -0
- package/dist/command/cli/doctor/doctor-fix.js +89 -0
- package/dist/command/cli/doctor/doctor-launcher-line.d.ts +23 -0
- package/dist/command/cli/doctor/doctor-launcher-line.js +60 -0
- package/dist/command/cli/doctor/doctor-rows.d.ts +4 -0
- package/dist/command/cli/doctor/doctor-rows.js +4 -0
- package/dist/command/cli/doctor-repairs.d.ts +64 -0
- package/dist/command/cli/doctor-repairs.js +214 -0
- package/dist/command/cli/drive/drive-command.js +3 -7
- package/dist/command/cli/ensure-daemon.d.ts +26 -0
- package/dist/command/cli/ensure-daemon.js +57 -0
- package/dist/command/cli/finished-run/grade-command.d.ts +23 -0
- package/dist/command/cli/finished-run/grade-command.js +180 -0
- package/dist/command/cli/first-use-checks.d.ts +41 -0
- package/dist/command/cli/first-use-checks.js +127 -0
- package/dist/command/cli/first-verdict-node.d.ts +3 -0
- package/dist/command/cli/first-verdict-node.js +189 -0
- package/dist/command/cli/first-verdict.d.ts +126 -0
- package/dist/command/cli/first-verdict.js +267 -0
- package/dist/command/cli/launch/sdk-version-match.d.ts +3 -2
- package/dist/command/cli/launch/sdk-version-match.js +3 -2
- package/dist/command/cli/lifecycle/daemon-lifecycle.d.ts +1 -1
- package/dist/command/cli/lifecycle/daemon-lifecycle.js +7 -6
- package/dist/command/cli/mcp-command.js +13 -4
- package/dist/command/cli/ports/port-holder.d.ts +11 -0
- package/dist/command/cli/ports/port-holder.js +36 -4
- package/dist/command/cli/setup-mcp-cli.d.ts +27 -1
- package/dist/command/cli/setup-mcp-cli.js +98 -23
- package/dist/command/cli/status/status-lines.d.ts +2 -0
- package/dist/command/cli/status/status-lines.js +72 -17
- package/dist/command/cli/status-fields.d.ts +5 -1
- package/dist/command/cli/status-fields.js +24 -6
- package/dist/command/cli/try-command.d.ts +7 -0
- package/dist/command/cli/try-command.js +11 -3
- package/dist/command/cli/two-builds/compare-command.d.ts +48 -0
- package/dist/command/cli/two-builds/compare-command.js +314 -0
- package/dist/command/cli/verify-against.d.ts +61 -0
- package/dist/command/cli/verify-against.js +187 -0
- package/dist/command/cli/verify-no-session.d.ts +2 -0
- package/dist/command/cli/verify-no-session.js +13 -0
- package/dist/command/cli/verify-results.d.ts +35 -2
- package/dist/command/cli/verify-results.js +76 -10
- package/dist/command/cli.js +112 -70
- package/dist/command/daemon/binding/daemon-status-probe.d.ts +3 -1
- package/dist/command/daemon/binding/daemon-status-probe.js +4 -2
- package/dist/command/daemon/daemon-argv.d.ts +9 -0
- package/dist/command/daemon/daemon-argv.js +11 -0
- package/dist/command/daemon/daemon-resolve.d.ts +8 -1
- package/dist/command/daemon/daemon-resolve.js +27 -1
- package/dist/command/daemon/daemon.d.ts +22 -4
- package/dist/command/daemon/daemon.js +52 -10
- package/dist/command/daemon/lifetime/daemon-exit.d.ts +24 -0
- package/dist/command/daemon/lifetime/daemon-exit.js +39 -0
- package/dist/command/daemon/lifetime/death-cause.d.ts +15 -0
- package/dist/command/daemon/lifetime/death-cause.js +149 -0
- package/dist/command/daemon/lifetime/heartbeat.d.ts +7 -15
- package/dist/command/daemon/lifetime/heartbeat.js +11 -15
- package/dist/command/daemon/lifetime/startup-failure.d.ts +29 -0
- package/dist/command/daemon/lifetime/startup-failure.js +62 -0
- package/dist/command/daemon/port-state.d.ts +14 -0
- package/dist/command/daemon/port-state.js +31 -0
- package/dist/command/setup/agent-configs.d.ts +2 -0
- package/dist/command/setup/agent-configs.js +42 -15
- package/dist/command/setup/agent-next-steps.d.ts +77 -0
- package/dist/command/setup/agent-next-steps.js +284 -0
- package/dist/command/setup/agent-writer.js +11 -6
- package/dist/command/setup/bringup/dev-server-files.d.ts +9 -0
- package/dist/command/setup/bringup/dev-server-files.js +17 -0
- package/dist/command/setup/bringup/static-page-server.d.ts +14 -2
- package/dist/command/setup/bringup/static-page-server.js +43 -9
- package/dist/command/setup/init/init-host.js +2 -0
- package/dist/command/setup/init/init-runtime.d.ts +6 -1
- package/dist/command/setup/init/init-runtime.js +63 -21
- package/dist/command/setup/mcp-launcher.d.ts +3 -0
- package/dist/command/setup/mcp-launcher.js +11 -0
- package/dist/command/setup/node-effects.d.ts +3 -2
- package/dist/command/setup/node-effects.js +9 -3
- package/dist/command/setup/remaining-steps.d.ts +8 -0
- package/dist/command/setup/remaining-steps.js +10 -0
- package/dist/command/setup/run-setup.d.ts +2 -0
- package/dist/command/setup/run-setup.js +9 -1
- package/dist/command/setup/setup-command.js +36 -15
- package/dist/command/setup/setup-mcp.d.ts +8 -0
- package/dist/command/setup/setup-mcp.js +47 -20
- package/dist/command/setup/start-dev-server.d.ts +8 -0
- package/dist/command/setup/start-dev-server.js +43 -0
- package/dist/command/update/updater.js +6 -0
- package/dist/command/version/identity/server-version.d.ts +2 -0
- package/dist/command/version/identity/server-version.js +2 -0
- package/dist/command/version/version-skew.d.ts +7 -0
- package/dist/command/version/version-skew.js +14 -3
- package/dist/features/compare/action-plan.d.ts +260 -0
- package/dist/features/compare/action-plan.js +543 -0
- package/dist/features/compare/behaviour-compare.d.ts +24 -0
- package/dist/features/compare/behaviour-compare.js +85 -0
- package/dist/features/compare/behaviour-diff.d.ts +97 -0
- package/dist/features/compare/behaviour-diff.js +202 -0
- package/dist/features/compare/behaviour-report.d.ts +40 -0
- package/dist/features/compare/behaviour-report.js +128 -0
- package/dist/features/compare/build-readings.d.ts +106 -0
- package/dist/features/compare/build-readings.js +250 -0
- package/dist/features/compare/compare-diff.d.ts +62 -0
- package/dist/features/compare/compare-diff.js +177 -0
- package/dist/features/compare/compare-report-html.d.ts +6 -0
- package/dist/features/compare/compare-report-html.js +102 -0
- package/dist/features/compare/compare-report.d.ts +15 -0
- package/dist/features/compare/compare-report.js +73 -0
- package/dist/features/compare/compare-run.d.ts +60 -0
- package/dist/features/compare/compare-run.js +123 -0
- package/dist/features/compare/outside/effect-lines.d.ts +26 -0
- package/dist/features/compare/outside/effect-lines.js +103 -0
- package/dist/features/compare/outside/state-sources.d.ts +76 -0
- package/dist/features/compare/outside/state-sources.js +164 -0
- package/dist/features/compare/outside/value-dictionary.d.ts +51 -0
- package/dist/features/compare/outside/value-dictionary.js +227 -0
- package/dist/features/compare/visible-content.d.ts +20 -0
- package/dist/features/compare/visible-content.js +125 -0
- package/dist/features/crawl/crawl-empty.js +2 -1
- package/dist/features/crawl/crawl-exhaustive.d.ts +55 -0
- package/dist/features/crawl/crawl-exhaustive.js +138 -0
- package/dist/features/crawl/crawl-tools.d.ts +9 -2
- package/dist/features/crawl/crawl-tools.js +28 -12
- package/dist/features/crawl/crawl.d.ts +8 -9
- package/dist/features/crawl/crawl.js +61 -65
- package/dist/features/exhaust/app-coverage.d.ts +5 -1
- package/dist/features/exhaust/app-coverage.js +3 -1
- package/dist/features/exhaust/code-coverage.js +8 -4
- package/dist/features/exhaust/edge-cases.d.ts +133 -0
- package/dist/features/exhaust/edge-cases.js +310 -0
- package/dist/features/exhaust/edges/edge-drive.d.ts +42 -0
- package/dist/features/exhaust/edges/edge-drive.js +364 -0
- package/dist/features/exhaust/edges/edge-run.d.ts +59 -0
- package/dist/features/exhaust/edges/edge-run.js +169 -0
- package/dist/features/exhaust/explorer.d.ts +87 -14
- package/dist/features/exhaust/explorer.js +159 -25
- package/dist/features/exhaust/failure-branches.d.ts +5 -0
- package/dist/features/exhaust/failure-branches.js +29 -11
- package/dist/features/exhaust/invariants.d.ts +112 -0
- package/dist/features/exhaust/invariants.js +188 -0
- package/dist/features/exhaust/ledger.d.ts +68 -0
- package/dist/features/exhaust/ledger.js +121 -13
- package/dist/features/exhaust/session-fold.d.ts +10 -0
- package/dist/features/exhaust/session-fold.js +46 -3
- package/dist/features/exhaust/session-port.d.ts +3 -1
- package/dist/features/exhaust/session-port.js +97 -28
- package/dist/features/grade/grade-answer.d.ts +99 -0
- package/dist/features/grade/grade-answer.js +112 -0
- package/dist/features/grade/grade-noise.d.ts +27 -0
- package/dist/features/grade/grade-noise.js +55 -0
- package/dist/features/grade/grade-renumber.d.ts +12 -0
- package/dist/features/grade/grade-renumber.js +86 -0
- package/dist/features/grade/grade-state.d.ts +50 -0
- package/dist/features/grade/grade-state.js +93 -0
- package/dist/features/grade/grade-suggest.d.ts +33 -0
- package/dist/features/grade/grade-suggest.js +98 -0
- package/dist/features/license/license.d.ts +11 -71
- package/dist/features/license/license.js +43 -136
- package/dist/features/visual/desktop-capture.d.ts +33 -0
- package/dist/features/visual/desktop-capture.js +94 -0
- package/dist/features/visual/step-shots.js +139 -35
- package/dist/features/visual/visual-tools.d.ts +0 -18
- package/dist/features/visual/visual-tools.js +67 -99
- package/dist/import-graph.js +5 -6
- package/dist/index.d.ts +3 -1
- package/dist/index.js +19 -7
- package/dist/judgement/capsule/causal-summary.js +9 -2
- package/dist/judgement/runs/artifact/replay-mapping.d.ts +13 -1
- package/dist/judgement/runs/artifact/replay-mapping.js +1 -1
- package/dist/judgement/runs/reticle-runner.js +16 -2
- package/dist/judgement/runs/run-ledger.d.ts +7 -5
- package/dist/judgement/runs/run-ledger.js +98 -69
- package/dist/judgement/runs/runner-port.d.ts +2 -0
- package/dist/judgement/runs/runner-port.js +23 -5
- package/dist/judgement/runs/verification-sync.d.ts +6 -3
- package/dist/judgement/runs/verification-sync.js +21 -10
- package/dist/language/flows/affected-tools.d.ts +1 -1
- package/dist/language/flows/affected-tools.js +49 -30
- package/dist/language/flows/change/git-changed.d.ts +2 -1
- package/dist/language/flows/change/git-changed.js +19 -2
- package/dist/language/flows/fields/flow-secret-field.d.ts +1 -13
- package/dist/language/flows/fields/flow-secret-field.js +77 -21
- package/dist/language/flows/flow-anchor.d.ts +60 -2
- package/dist/language/flows/flow-anchor.js +125 -20
- package/dist/language/flows/flow-classify.d.ts +20 -0
- package/dist/language/flows/flow-classify.js +90 -12
- package/dist/language/flows/flow-cross-step.d.ts +7 -1
- package/dist/language/flows/flow-cross-step.js +25 -1
- package/dist/language/flows/flow-journey.d.ts +38 -4
- package/dist/language/flows/flow-journey.js +138 -8
- package/dist/language/flows/flow-replay-run.d.ts +0 -16
- package/dist/language/flows/flow-replay-run.js +76 -14
- package/dist/language/flows/flow-replay-types.d.ts +4 -2
- package/dist/language/flows/flow-replay.d.ts +19 -1
- package/dist/language/flows/flow-replay.js +169 -52
- package/dist/language/flows/flow-replayable.js +7 -1
- package/dist/language/flows/flow-start-path.d.ts +34 -5
- package/dist/language/flows/flow-start-path.js +202 -15
- package/dist/language/flows/flow-step-runners.d.ts +14 -13
- package/dist/language/flows/flow-step-runners.js +184 -109
- package/dist/language/flows/flow-store-for-session.d.ts +26 -25
- package/dist/language/flows/flow-store-for-session.js +51 -5
- package/dist/language/flows/flow-tools.js +46 -33
- package/dist/language/flows/flows.js +176 -76
- package/dist/language/flows/recording/tape/recordings.d.ts +21 -16
- package/dist/language/flows/recording/tape/recordings.js +112 -49
- package/dist/language/flows/replay.d.ts +36 -12
- package/dist/language/flows/replay.js +193 -50
- package/dist/language/flows/steps/page-steps.d.ts +68 -0
- package/dist/language/flows/steps/page-steps.js +198 -0
- package/dist/language/flows/suite/sequential-run.d.ts +68 -0
- package/dist/language/flows/suite/sequential-run.js +96 -0
- package/dist/language/flows/verify-change-tools.js +26 -15
- package/dist/launch-chromium.d.ts +1 -0
- package/dist/launch-chromium.js +49 -12
- package/dist/memory/cloud/background-sync.d.ts +13 -0
- package/dist/memory/cloud/background-sync.js +24 -3
- package/dist/memory/cloud/sync-daemon.js +26 -27
- package/dist/memory/cloud/sync-screenshots.js +6 -1
- package/dist/memory/journal/attach-journal.js +2 -1
- package/dist/memory/journal/drive-flow.d.ts +7 -0
- package/dist/memory/journal/drive-flow.js +44 -13
- package/dist/memory/journal/journal-recorder.d.ts +4 -2
- package/dist/memory/journal/session-journal.d.ts +7 -0
- package/dist/memory/journal/session-journal.js +58 -10
- package/dist/memory/project/root-claims.d.ts +9 -0
- package/dist/memory/project/root-claims.js +9 -4
- package/dist/portal/bridge/bridge.d.ts +13 -4
- package/dist/portal/bridge/bridge.js +10 -9
- package/dist/portal/input/download-capture.d.ts +7 -0
- package/dist/portal/input/download-capture.js +92 -0
- package/dist/portal/input/network-detail.d.ts +6 -0
- package/dist/portal/input/network-detail.js +12 -1
- package/dist/portal/input/network-mock-tools.js +49 -13
- package/dist/portal/input/network-mock.d.ts +8 -0
- package/dist/portal/input/network-mock.js +30 -10
- package/dist/portal/input/page-capture.d.ts +24 -0
- package/dist/portal/input/page-capture.js +33 -0
- package/dist/portal/input/real-input.d.ts +35 -18
- package/dist/portal/input/real-input.js +99 -33
- package/dist/portal/input/viewport-tools.d.ts +8 -0
- package/dist/portal/input/viewport-tools.js +81 -21
- package/dist/portal/pool/browser-pool.d.ts +16 -30
- package/dist/portal/pool/browser-pool.js +64 -52
- package/dist/portal/pool/context-permissions.d.ts +34 -17
- package/dist/portal/pool/context-permissions.js +94 -1
- package/dist/portal/pool/csp-widen.d.ts +62 -0
- package/dist/portal/pool/csp-widen.js +132 -0
- package/dist/portal/pool/determinism.d.ts +52 -0
- package/dist/portal/pool/determinism.js +259 -0
- package/dist/portal/pool/lease-emulation.d.ts +34 -1
- package/dist/portal/pool/lease-emulation.js +18 -0
- package/dist/portal/pool/lease-marker-stamp.d.ts +6 -0
- package/dist/portal/pool/lease-marker-stamp.js +15 -1
- package/dist/portal/pool/lease-page-error.d.ts +56 -0
- package/dist/portal/pool/lease-page-error.js +160 -0
- package/dist/portal/pool/page-error-journal.d.ts +63 -0
- package/dist/portal/pool/page-error-journal.js +208 -0
- package/dist/portal/pool/playwright-launcher.js +71 -15
- package/dist/portal/pool/pool-contract.d.ts +49 -1
- package/dist/portal/pool/pool-lease.d.ts +70 -2
- package/dist/portal/pool/pool-lease.js +23 -0
- package/dist/portal/pool/zero-install.d.ts +8 -0
- package/dist/portal/pool/zero-install.js +91 -1
- package/dist/portal/session/dev-server/dev-command.d.ts +11 -2
- package/dist/portal/session/dev-server/dev-command.js +110 -16
- package/dist/portal/session/dev-server/dev-server-probe.d.ts +7 -0
- package/dist/portal/session/dev-server/dev-server-probe.js +9 -0
- package/dist/portal/session/dev-server/project-ports.d.ts +21 -0
- package/dist/portal/session/dev-server/project-ports.js +62 -0
- package/dist/portal/session/facts/departed-network.d.ts +66 -0
- package/dist/portal/session/facts/departed-network.js +142 -0
- package/dist/portal/session/no-session-diagnosis.d.ts +9 -0
- package/dist/portal/session/no-session-diagnosis.js +76 -27
- package/dist/portal/session/no-session-next-action.d.ts +14 -0
- package/dist/portal/session/no-session-next-action.js +56 -7
- package/dist/portal/session/no-session-watch.d.ts +6 -0
- package/dist/portal/session/no-session-watch.js +41 -4
- package/dist/portal/session/page-commands/undeclared-command.d.ts +9 -3
- package/dist/portal/session/page-commands/undeclared-command.js +16 -7
- package/dist/portal/session/recorded-gaps.d.ts +1 -1
- package/dist/portal/session/recorded-gaps.js +5 -2
- package/dist/portal/session/serving-directory.d.ts +10 -0
- package/dist/portal/session/serving-directory.js +39 -8
- package/dist/portal/session/session-manager.d.ts +10 -0
- package/dist/portal/session/session-manager.js +211 -81
- package/dist/portal/session/session.js +4 -3
- package/dist/portal/session/zero-install-first-call.d.ts +20 -1
- package/dist/portal/session/zero-install-first-call.js +34 -2
- package/dist/start-wiring.d.ts +30 -2
- package/dist/start-wiring.js +74 -9
- package/dist/surface/mcp/mcp-proxy.js +10 -2
- package/dist/surface/mcp/mcp.js +8 -5
- package/dist/surface/mcp/peer/agents-connected.d.ts +6 -0
- package/dist/surface/mcp/peer/agents-connected.js +58 -0
- package/dist/surface/mcp/proxy/proxy-daemon-probe.js +17 -5
- package/dist/surface/mcp/shared-params.d.ts +2 -0
- package/dist/surface/mcp/shared-params.js +31 -0
- package/dist/surface/tools/act/act-observation.d.ts +40 -2
- package/dist/surface/tools/act/act-observation.js +118 -12
- package/dist/surface/tools/act/act-preflight.js +38 -18
- package/dist/surface/tools/act/act-sequence-retry.d.ts +23 -2
- package/dist/surface/tools/act/act-sequence-retry.js +61 -5
- package/dist/surface/tools/act/act-target.js +3 -1
- package/dist/surface/tools/act/after-match.d.ts +10 -0
- package/dist/surface/tools/act/after-match.js +40 -0
- package/dist/surface/tools/act/already-true.js +1 -1
- package/dist/surface/tools/act/navigation/reload-result.d.ts +12 -1
- package/dist/surface/tools/act/navigation/reload-result.js +25 -2
- package/dist/surface/tools/act/resolve-target.d.ts +17 -1
- package/dist/surface/tools/act/resolve-target.js +59 -9
- package/dist/surface/tools/act/sequence-grade.d.ts +15 -1
- package/dist/surface/tools/act/sequence-grade.js +45 -27
- package/dist/surface/tools/act/settle-in-flight.js +27 -15
- package/dist/surface/tools/act-command.d.ts +23 -0
- package/dist/surface/tools/act-command.js +50 -0
- package/dist/surface/tools/act-sequence-tool.js +81 -50
- package/dist/surface/tools/act-tools.d.ts +1 -13
- package/dist/surface/tools/act-tools.js +83 -95
- package/dist/surface/tools/agent/build-staleness.d.ts +1 -1
- package/dist/surface/tools/agent/build-staleness.js +1 -1
- package/dist/surface/tools/assert/assert-verdict.js +18 -12
- package/dist/surface/tools/browser-tools.js +87 -13
- package/dist/surface/tools/compare-tools.d.ts +11 -0
- package/dist/surface/tools/compare-tools.js +94 -0
- package/dist/surface/tools/coverage-tools.js +1 -1
- package/dist/surface/tools/dynamic-tools.js +11 -3
- package/dist/surface/tools/empty-session-list.d.ts +2 -0
- package/dist/surface/tools/empty-session-list.js +4 -2
- package/dist/surface/tools/error-recovery.d.ts +12 -1
- package/dist/surface/tools/error-recovery.js +131 -40
- package/dist/surface/tools/explore-tools.js +1 -1
- package/dist/surface/tools/invoke-tool.js +29 -21
- package/dist/surface/tools/lease-coverage-tools.d.ts +49 -0
- package/dist/surface/tools/lease-coverage-tools.js +128 -0
- package/dist/surface/tools/lease-hint.d.ts +42 -1
- package/dist/surface/tools/lease-hint.js +52 -3
- package/dist/surface/tools/lease-readiness.d.ts +47 -0
- package/dist/surface/tools/lease-readiness.js +126 -0
- package/dist/surface/tools/lease-seed.d.ts +16 -1
- package/dist/surface/tools/lease-seed.js +37 -4
- package/dist/surface/tools/lease-tools.d.ts +3 -41
- package/dist/surface/tools/lease-tools.js +104 -124
- package/dist/surface/tools/lease-url-identity.d.ts +46 -0
- package/dist/surface/tools/lease-url-identity.js +97 -0
- package/dist/surface/tools/merge-tools.js +99 -2
- package/dist/surface/tools/merged-name-redirect.js +5 -1
- package/dist/surface/tools/observe-tools.js +15 -9
- package/dist/surface/tools/read/console-pre-attach.d.ts +19 -0
- package/dist/surface/tools/read/console-pre-attach.js +23 -0
- package/dist/surface/tools/read-tools.js +33 -30
- package/dist/surface/tools/real-input-attempt.d.ts +0 -8
- package/dist/surface/tools/real-input-attempt.js +143 -28
- package/dist/surface/tools/repeat-hint.d.ts +40 -0
- package/dist/surface/tools/repeat-hint.js +171 -0
- package/dist/surface/tools/run-report.d.ts +2 -2
- package/dist/surface/tools/run-report.js +27 -15
- package/dist/surface/tools/session-ports.d.ts +14 -0
- package/dist/surface/tools/session-ports.js +53 -0
- package/dist/surface/tools/tool-kit.d.ts +18 -0
- package/dist/surface/tools/tool-kit.js +9 -3
- package/dist/surface/tools/tool-surface.js +0 -1
- package/dist/surface/tools/tools.js +54 -18
- package/dist/surface/tools/type-spelling.d.ts +13 -0
- package/dist/surface/tools/type-spelling.js +36 -0
- package/dist/telemetry/agent-client.d.ts +6 -0
- package/dist/telemetry/agent-client.js +10 -0
- package/dist/telemetry/argument-shape.js +17 -7
- package/dist/telemetry/cli-telemetry.d.ts +10 -1
- package/dist/telemetry/cli-telemetry.js +15 -0
- package/dist/telemetry/init-telemetry.d.ts +2 -1
- package/dist/telemetry/init-telemetry.js +47 -2
- package/dist/telemetry/install-trace.js +23 -4
- package/dist/telemetry/onboarding-funnel.d.ts +19 -2
- package/dist/telemetry/onboarding-funnel.js +25 -3
- package/dist/telemetry/proxy-telemetry.d.ts +2 -1
- package/dist/telemetry/proxy-telemetry.js +2 -2
- package/dist/telemetry/session-metrics.d.ts +1 -1
- package/dist/telemetry/session-metrics.js +67 -27
- package/dist/telemetry/telemetry.d.ts +3 -1
- package/dist/telemetry/telemetry.js +60 -28
- package/dist/telemetry/tool-refused.d.ts +6 -3
- package/dist/telemetry/tool-refused.js +15 -3
- package/docs/actions.mdx +3 -3
- package/docs/agent-cheatsheet.md +1 -1
- package/docs/architecture.md +3 -6
- package/docs/capabilities.mdx +61 -1
- package/docs/cli/affected.mdx +9 -7
- package/docs/cli/cloud.mdx +3 -3
- package/docs/cli/compare.mdx +94 -0
- package/docs/cli/doctor.mdx +41 -2
- package/docs/cli/grade.mdx +97 -0
- package/docs/cli/help.mdx +4 -2
- package/docs/cli/license.mdx +13 -12
- package/docs/cli/restart.mdx +7 -5
- package/docs/cli/rollback.mdx +5 -5
- package/docs/cli/setup.mdx +13 -2
- package/docs/cli/status.mdx +4 -0
- package/docs/cli/stop.mdx +3 -3
- package/docs/cli/update.mdx +2 -2
- package/docs/cli/verify.mdx +23 -1
- package/docs/cli.mdx +34 -24
- package/docs/deploy-checks.md +25 -0
- package/docs/desktop.mdx +1 -1
- package/docs/enterprise.md +17 -22
- package/docs/environment.mdx +1 -0
- package/docs/first-drive.md +1 -1
- package/docs/flows.md +11 -1
- package/docs/frameworks.mdx +9 -9
- package/docs/getting-started.md +1 -1
- package/docs/install-manual.mdx +16 -1
- package/docs/license-activation.mdx +3 -3
- package/docs/packages/engine.mdx +1 -1
- package/docs/packages/server.mdx +1 -1
- package/docs/packages/tauri.mdx +1 -1
- package/docs/packages/test.mdx +1 -1
- package/docs/packages.mdx +1 -1
- package/docs/platform-integration.md +1 -1
- package/docs/predicates.mdx +1 -1
- package/docs/quickstart.mdx +68 -49
- package/docs/skill-setup.md +1 -1
- package/docs/skill.md +14 -13
- package/docs/telemetry.md +6 -4
- package/docs/tools/navigate.mdx +1 -1
- package/docs/tools/verify.mdx +4 -1
- package/docs/troubleshooting.mdx +1 -1
- package/docs/usage.md +17 -14
- package/package.json +18 -14
- package/LICENSE-ENTERPRISE +0 -37
- package/dist/features/ee/audit-log.d.ts +0 -14
- package/dist/features/ee/audit-log.js +0 -11
- package/dist/features/exhaust/exhaust-run.d.ts +0 -33
- package/dist/features/exhaust/exhaust-run.js +0 -82
|
@@ -10,6 +10,10 @@ export declare const REDUCED_MOTION_ARG: z.ZodOptional<z.ZodEnum<{
|
|
|
10
10
|
reduce: "reduce";
|
|
11
11
|
"no-preference": "no-preference";
|
|
12
12
|
}>>;
|
|
13
|
+
export declare const POINTER_ARG: z.ZodOptional<z.ZodEnum<{
|
|
14
|
+
fine: "fine";
|
|
15
|
+
coarse: "coarse";
|
|
16
|
+
}>>;
|
|
13
17
|
export declare const LEASE_EMULATE_ARG: z.ZodOptional<z.ZodObject<{
|
|
14
18
|
colorScheme: z.ZodOptional<z.ZodEnum<{
|
|
15
19
|
light: "light";
|
|
@@ -22,6 +26,10 @@ export declare const LEASE_EMULATE_ARG: z.ZodOptional<z.ZodObject<{
|
|
|
22
26
|
}>>;
|
|
23
27
|
width: z.ZodOptional<z.ZodNumber>;
|
|
24
28
|
height: z.ZodOptional<z.ZodNumber>;
|
|
29
|
+
pointer: z.ZodOptional<z.ZodEnum<{
|
|
30
|
+
fine: "fine";
|
|
31
|
+
coarse: "coarse";
|
|
32
|
+
}>>;
|
|
25
33
|
}, z.core.$strict>>;
|
|
26
34
|
/** The media part of what a caller asked for, or undefined when it asked for none. */
|
|
27
35
|
export declare function mediaOf(raw: {
|
|
@@ -4,11 +4,12 @@ import { ReticleTool } from '@reticlehq/core';
|
|
|
4
4
|
import { sessionIdShape } from '../../surface/tools/tool-kit.js';
|
|
5
5
|
import { MAX_VIEWPORT_PX, MIN_VIEWPORT_PX, viewportPxSchema, } from '../../surface/tools/args/numeric-bounds.js';
|
|
6
6
|
import { asString } from '@reticlehq/core';
|
|
7
|
-
import {
|
|
7
|
+
import { HEADLESS_VIEWPORT } from '../../chromium-launch-options.js';
|
|
8
|
+
import { ColorScheme, Pointer, ReducedMotion, } from '../pool/lease-emulation.js';
|
|
8
9
|
// ── Media and width, as a tool call names them (reticle_viewport here, reticle_lease acquire) ──
|
|
9
|
-
/**
|
|
10
|
-
const DEFAULT_WIDTH =
|
|
11
|
-
const DEFAULT_HEIGHT =
|
|
10
|
+
/** The side a caller did not name is the page size a headless lease already opens with. */
|
|
11
|
+
const DEFAULT_WIDTH = HEADLESS_VIEWPORT.width;
|
|
12
|
+
const DEFAULT_HEIGHT = HEADLESS_VIEWPORT.height;
|
|
12
13
|
export const COLOR_SCHEME_ARG = z
|
|
13
14
|
.enum([ColorScheme.LIGHT, ColorScheme.DARK, ColorScheme.NO_PREFERENCE])
|
|
14
15
|
.optional()
|
|
@@ -17,16 +18,24 @@ export const REDUCED_MOTION_ARG = z
|
|
|
17
18
|
.enum([ReducedMotion.REDUCE, ReducedMotion.NO_PREFERENCE])
|
|
18
19
|
.optional()
|
|
19
20
|
.describe('prefers-reduced-motion for this page: reduce or no-preference.');
|
|
21
|
+
export const POINTER_ARG = z
|
|
22
|
+
.enum([Pointer.FINE, Pointer.COARSE])
|
|
23
|
+
.optional()
|
|
24
|
+
.describe('The primary pointer this page reports to @media (pointer: ...): fine (a mouse) or coarse (touch). ' +
|
|
25
|
+
'Settable only when the lease opens, because touch support is fixed for a browser context.');
|
|
20
26
|
const EmulateSchema = z
|
|
21
27
|
.object({
|
|
22
28
|
colorScheme: COLOR_SCHEME_ARG,
|
|
23
29
|
reducedMotion: REDUCED_MOTION_ARG,
|
|
24
30
|
width: viewportPxSchema.optional(),
|
|
25
31
|
height: viewportPxSchema.optional(),
|
|
32
|
+
pointer: POINTER_ARG,
|
|
26
33
|
})
|
|
27
34
|
.strict();
|
|
28
|
-
export const LEASE_EMULATE_ARG = EmulateSchema.optional().describe('Open the lease with these set before the first paint: { colorScheme, reducedMotion, width, height }. ' +
|
|
29
|
-
'A side you leave out keeps its default (
|
|
35
|
+
export const LEASE_EMULATE_ARG = EmulateSchema.optional().describe('Open the lease with these set before the first paint: { colorScheme, reducedMotion, width, height, pointer }. ' +
|
|
36
|
+
'A side you leave out keeps its default (1440 by 900). Change the media and the size later with ' +
|
|
37
|
+
'reticle_viewport; `pointer` cannot change on an open lease, so a touch-only rule needs a lease ' +
|
|
38
|
+
'acquired with pointer: "coarse".');
|
|
30
39
|
/** The media part of what a caller asked for, or undefined when it asked for none. */
|
|
31
40
|
export function mediaOf(raw) {
|
|
32
41
|
const parsed = EmulateSchema.pick({ colorScheme: true, reducedMotion: true }).parse({
|
|
@@ -41,21 +50,27 @@ export function mediaOf(raw) {
|
|
|
41
50
|
}
|
|
42
51
|
/** A lease's `emulate` argument, read; a value it does not know is refused by name. */
|
|
43
52
|
export function leaseEmulationOf(raw) {
|
|
44
|
-
if (raw === undefined)
|
|
53
|
+
if (raw === undefined) {
|
|
45
54
|
return undefined;
|
|
55
|
+
}
|
|
46
56
|
const parsed = EmulateSchema.safeParse(raw);
|
|
47
57
|
if (!parsed.success) {
|
|
48
58
|
const field = parsed.error.issues[0]?.path.join('.') ?? 'emulate';
|
|
49
59
|
throw new Error(`emulate.${field}: ${parsed.error.issues[0]?.message ?? 'not valid'}`);
|
|
50
60
|
}
|
|
51
|
-
const { width, height } = parsed.data;
|
|
61
|
+
const { width, height, pointer } = parsed.data;
|
|
52
62
|
const media = mediaOf(parsed.data);
|
|
53
63
|
const viewport = width === undefined && height === undefined
|
|
54
64
|
? undefined
|
|
55
65
|
: { width: width ?? DEFAULT_WIDTH, height: height ?? DEFAULT_HEIGHT };
|
|
56
|
-
if (media === undefined && viewport === undefined)
|
|
66
|
+
if (media === undefined && viewport === undefined && pointer === undefined) {
|
|
57
67
|
return undefined;
|
|
58
|
-
|
|
68
|
+
}
|
|
69
|
+
return {
|
|
70
|
+
...media,
|
|
71
|
+
...(viewport === undefined ? {} : { viewport }),
|
|
72
|
+
...(pointer === undefined ? {} : { pointer }),
|
|
73
|
+
};
|
|
59
74
|
}
|
|
60
75
|
/** Bounds so a viewport request stays sane (and a typo can't ask for a 1px or 100k-px window). */
|
|
61
76
|
const MIN_DIM = MIN_VIEWPORT_PX;
|
|
@@ -66,6 +81,25 @@ function viewportProvider(deps) {
|
|
|
66
81
|
? p
|
|
67
82
|
: undefined;
|
|
68
83
|
}
|
|
84
|
+
/**
|
|
85
|
+
* Whether this caller holds the session as a lease. Another agent's lease is never this caller's
|
|
86
|
+
* to change (#1226).
|
|
87
|
+
*/
|
|
88
|
+
function holdsLease(deps, sessionId) {
|
|
89
|
+
return true === deps.pool?.heldBy(sessionId, deps.attachId);
|
|
90
|
+
}
|
|
91
|
+
/** Whether this call can resize the session: a lease of this caller, or a driven page. */
|
|
92
|
+
async function canResize(deps, session) {
|
|
93
|
+
if (holdsLease(deps, session.id)) {
|
|
94
|
+
return true;
|
|
95
|
+
}
|
|
96
|
+
// A driven browser resizes only a page it has. Having a driven browser is not enough.
|
|
97
|
+
const driven = viewportProvider(deps);
|
|
98
|
+
if (driven === undefined) {
|
|
99
|
+
return false;
|
|
100
|
+
}
|
|
101
|
+
return driven.isAvailableFor(session.url);
|
|
102
|
+
}
|
|
69
103
|
export const VIEWPORT_TOOLS = [
|
|
70
104
|
{
|
|
71
105
|
name: ReticleTool.VIEWPORT,
|
|
@@ -73,37 +107,55 @@ export const VIEWPORT_TOOLS = [
|
|
|
73
107
|
'reproducible across machines — the missing piece of CI-stable visual regression, alongside ' +
|
|
74
108
|
'reticle_visual_diff `masks` and a frozen clock (reticle_clock). Set it once before reticle_screenshot / ' +
|
|
75
109
|
'reticle_visual_diff. On a lease it also sets prefers-color-scheme and prefers-reduced-motion; ' +
|
|
76
|
-
'give only those to change the media and keep the size.
|
|
110
|
+
'give only those to change the media and keep the size. A `pointer` is refused here: touch support is fixed when a lease opens, so ask for it with reticle_lease acquire `emulate.pointer`. ' +
|
|
111
|
+
'Returns { applied, width, height, observed } or the no-provider recommendation; `observed` is the size the leased page reports after the resize.',
|
|
77
112
|
inputSchema: {
|
|
78
113
|
width: viewportPxSchema.optional().describe('Viewport width in CSS px (e.g. 1280).'),
|
|
79
114
|
height: viewportPxSchema.optional().describe('Viewport height in CSS px (e.g. 800).'),
|
|
80
115
|
colorScheme: COLOR_SCHEME_ARG,
|
|
81
116
|
reducedMotion: REDUCED_MOTION_ARG,
|
|
117
|
+
pointer: POINTER_ARG,
|
|
82
118
|
...sessionIdShape,
|
|
83
119
|
},
|
|
84
120
|
outputSchema: {
|
|
85
121
|
applied: z.boolean(),
|
|
86
|
-
width: z.number(),
|
|
87
|
-
height: z.number(),
|
|
122
|
+
width: z.number().optional(),
|
|
123
|
+
height: z.number().optional(),
|
|
88
124
|
observed: z.object({ width: z.number(), height: z.number() }).optional(),
|
|
89
125
|
colorScheme: z.string().optional(),
|
|
90
126
|
reducedMotion: z.string().optional(),
|
|
127
|
+
pointer: z.string().optional(),
|
|
91
128
|
ok: z.boolean().optional(),
|
|
92
129
|
reason: z.string().optional(),
|
|
93
130
|
recommendation: z.string().optional(),
|
|
94
131
|
},
|
|
95
132
|
handler: async (deps, args) => {
|
|
133
|
+
// Touch support is a Playwright context option and a lease is one context, so a pointer can
|
|
134
|
+
// only be chosen when the lease opens. Said out loud instead of dropped: a silently ignored
|
|
135
|
+
// `pointer` would hand back a verdict about a touch-only rule that was taken with a mouse.
|
|
136
|
+
if (args['pointer'] !== undefined) {
|
|
137
|
+
return {
|
|
138
|
+
applied: false,
|
|
139
|
+
ok: false,
|
|
140
|
+
reason: POINTER_IS_FIXED,
|
|
141
|
+
recommendation: POINTER_NEEDS_A_NEW_LEASE,
|
|
142
|
+
};
|
|
143
|
+
}
|
|
96
144
|
const media = mediaOf(args);
|
|
97
145
|
if (media !== undefined && args['width'] === undefined && args['height'] === undefined) {
|
|
98
|
-
|
|
146
|
+
// Only a lease can set the media.
|
|
147
|
+
const session = await deps.sessions.resolveServing(asString(args['sessionId']), (s) => holdsLease(deps, s.id));
|
|
99
148
|
if (true === (await deps.pool?.emulateLease(session.id, media))) {
|
|
100
|
-
|
|
149
|
+
// No size was asked for, so answer the one the lease has; 0 by 0 reads as a broken
|
|
150
|
+
// viewport (#1902). When the page cannot be read, leave the size out.
|
|
151
|
+
const size = await deps.pool?.viewportOfLease(session.id);
|
|
152
|
+
return { applied: true, ...size, ...media };
|
|
101
153
|
}
|
|
102
154
|
return { ...refused(), recommendation: MEDIA_NEEDS_A_LEASE };
|
|
103
155
|
}
|
|
104
156
|
const width = clampDim('width', args['width']);
|
|
105
157
|
const height = clampDim('height', args['height']);
|
|
106
|
-
const session = deps.sessions.
|
|
158
|
+
const session = await deps.sessions.resolveServing(asString(args['sessionId']), (s) => canResize(deps, s));
|
|
107
159
|
// A lease is resized as the lease. The driven provider resizes its own page, whatever
|
|
108
160
|
// session was named, so taking it first resized the wrong tab and said `applied: true`.
|
|
109
161
|
const driven = viewportProvider(deps);
|
|
@@ -111,10 +163,12 @@ export const VIEWPORT_TOOLS = [
|
|
|
111
163
|
if (provider !== undefined) {
|
|
112
164
|
const applied = await provider.setViewport(session.url, { width, height });
|
|
113
165
|
// The driven page takes the size; its media stay as the person's browser has them.
|
|
114
|
-
if (applied && media === undefined)
|
|
166
|
+
if (applied && media === undefined) {
|
|
115
167
|
return { applied: true, width, height };
|
|
116
|
-
|
|
168
|
+
}
|
|
169
|
+
if (applied) {
|
|
117
170
|
return { applied: true, width, height, recommendation: MEDIA_NEEDS_A_LEASE };
|
|
171
|
+
}
|
|
118
172
|
}
|
|
119
173
|
// A lease is a Playwright-owned page, so the resize was always possible — this tool just had
|
|
120
174
|
// no route to it. Tried after the driven provider, on the same rule reticle_network_mock
|
|
@@ -125,16 +179,18 @@ export const VIEWPORT_TOOLS = [
|
|
|
125
179
|
// only mounts under a breakpoint — could not be driven at a desktop viewport at all, and the
|
|
126
180
|
// recommendation printed alongside the refusal asked the reader to install a second browser.
|
|
127
181
|
const leased = await deps.pool?.setViewportLease(session.id, { width, height });
|
|
128
|
-
if (true !== leased)
|
|
182
|
+
if (true !== leased) {
|
|
129
183
|
return refused();
|
|
184
|
+
}
|
|
130
185
|
// What the page reports after the resize, so `applied` is a reading and not a hope.
|
|
131
186
|
const observed = await deps.pool?.viewportOfLease(session.id);
|
|
132
187
|
if (observed !== undefined && (observed.width !== width || observed.height !== height)) {
|
|
133
188
|
return { applied: false, width, height, observed, ok: false, reason: VIEWPORT_NOT_TAKEN };
|
|
134
189
|
}
|
|
135
190
|
const seen = observed === undefined ? {} : { observed };
|
|
136
|
-
if (media === undefined)
|
|
191
|
+
if (media === undefined) {
|
|
137
192
|
return { applied: true, width, height, ...seen };
|
|
193
|
+
}
|
|
138
194
|
if (true === (await deps.pool?.emulateLease(session.id, media))) {
|
|
139
195
|
return { applied: true, width, height, ...seen, ...media };
|
|
140
196
|
}
|
|
@@ -144,6 +200,9 @@ export const VIEWPORT_TOOLS = [
|
|
|
144
200
|
];
|
|
145
201
|
/** The resize went through, but the page still reports another size. */
|
|
146
202
|
const VIEWPORT_NOT_TAKEN = 'the page still reports the size in `observed` after the resize, so the size was not applied';
|
|
203
|
+
/** Touch support rides on the browser context, so an open lease's pointer cannot be changed. */
|
|
204
|
+
const POINTER_IS_FIXED = "a lease's pointer is fixed when its context opens, so it cannot be changed on a live lease";
|
|
205
|
+
const POINTER_NEEDS_A_NEW_LEASE = 'Acquire a new lease with emulate.pointer: reticle_lease { action: "acquire", emulate: { pointer: "coarse" } }, then call this again with its sessionId.';
|
|
147
206
|
/** prefers-color-scheme and prefers-reduced-motion are set on a leased page only. */
|
|
148
207
|
const MEDIA_NEEDS_A_LEASE = 'Media features are set on a leased tab: open one with reticle_lease { action: "acquire", emulate }, then call this again with its sessionId.';
|
|
149
208
|
function refused() {
|
|
@@ -164,8 +223,9 @@ function refused() {
|
|
|
164
223
|
* snapshot, click and screenshot on that page read as broken (#1118).
|
|
165
224
|
*/
|
|
166
225
|
function clampDim(key, value) {
|
|
167
|
-
if (value === undefined)
|
|
226
|
+
if (value === undefined) {
|
|
168
227
|
return MIN_DIM;
|
|
228
|
+
}
|
|
169
229
|
if ('number' !== typeof value || !Number.isFinite(value)) {
|
|
170
230
|
throw new Error(`${ReticleTool.VIEWPORT}: \`${key}\` must be a number of CSS px, got ${JSON.stringify(value)} — NOT applied`);
|
|
171
231
|
}
|
|
@@ -9,12 +9,12 @@
|
|
|
9
9
|
* The browser is injected via a `Launcher` so all lifecycle logic is testable without real Chromium;
|
|
10
10
|
* the thin Playwright adapter that satisfies these interfaces lives separately.
|
|
11
11
|
*/
|
|
12
|
-
import {
|
|
13
|
-
import type { Launcher, PooledMockRule, ScreenshotOptions } from './pool-contract.js';
|
|
12
|
+
import type { Launcher, PooledCoverage, PooledMockRule, ScreenshotOptions } from './pool-contract.js';
|
|
14
13
|
import type { RealInputArgs, RealInputResult } from '../input/real-input.js';
|
|
15
|
-
import { type
|
|
16
|
-
|
|
17
|
-
|
|
14
|
+
import { type LeaseMedia } from './lease-emulation.js';
|
|
15
|
+
import { type DeterminismStep } from './determinism.js';
|
|
16
|
+
export type { InitScriptHandle, Launcher, PooledBrowser, PooledContext, PooledCookie, PooledDialog, PooledMockRule, PooledPage, PooledPageError, } from './pool-contract.js';
|
|
17
|
+
import { type AcquireOptions, type BrowserPoolOptions, type Lease } from './pool-lease.js';
|
|
18
18
|
export { DEFAULT_LEASE_TTL_MS, NO_HEADED_BROWSER, ORPHANED_LEASE_GRACE_MS, PoolAtCapacityError, } from './pool-lease.js';
|
|
19
19
|
export type { Lease } from './pool-lease.js';
|
|
20
20
|
/**
|
|
@@ -101,6 +101,8 @@ export declare class BrowserPool {
|
|
|
101
101
|
* reaper take it out from under a diff.
|
|
102
102
|
*/
|
|
103
103
|
screenshotLease(sessionId: string, opts?: ScreenshotOptions): Promise<Uint8Array | undefined>;
|
|
104
|
+
/** The reason {@link screenshotLease} last failed for this session, if it did. */
|
|
105
|
+
leaseCaptureError(sessionId: string): string | undefined;
|
|
104
106
|
/** The URL a lease was opened on — the one that carries its Reticle identity. */
|
|
105
107
|
leaseUrl(sessionId: string): string | undefined;
|
|
106
108
|
/**
|
|
@@ -117,6 +119,8 @@ export declare class BrowserPool {
|
|
|
117
119
|
* Touches the lease like any other tool call, so hovering keeps it alive.
|
|
118
120
|
*/
|
|
119
121
|
hoverLease(sessionId: string, x: number, y: number): Promise<boolean>;
|
|
122
|
+
/** Reload a lease with the browser cache ignored, or false when this is not a lease or its page cannot. */
|
|
123
|
+
hardReloadLease(sessionId: string): Promise<boolean>;
|
|
120
124
|
/** Set a live lease's media features, or false when this is not a lease or its page cannot. */
|
|
121
125
|
emulateLease(sessionId: string, media: LeaseMedia): Promise<boolean>;
|
|
122
126
|
/** Whether this lease's page is still loading. False for a non-lease, or a page that cannot say. */
|
|
@@ -153,6 +157,10 @@ export declare class BrowserPool {
|
|
|
153
157
|
height: number;
|
|
154
158
|
} | undefined>;
|
|
155
159
|
setMocksLease(sessionId: string, rules: readonly PooledMockRule[]): Promise<boolean>;
|
|
160
|
+
/** Step a deterministic lease's clock by `frames` frames; undefined when it is not one. */
|
|
161
|
+
stepLease(sessionId: string, frames: number): Promise<DeterminismStep | undefined>;
|
|
162
|
+
/** The JS coverage of a lease's page, or undefined when this is not a lease or cannot measure. */
|
|
163
|
+
coverageOf(sessionId: string): PooledCoverage | undefined;
|
|
156
164
|
/** Guard a leased page's requests, or false when this is not a lease or its page cannot. */
|
|
157
165
|
guardLease(sessionId: string, decide: (method: string, url: string) => string | undefined): Promise<boolean>;
|
|
158
166
|
/** What a lease was granted when it opened, or undefined for a session that is not a lease. */
|
|
@@ -205,31 +213,7 @@ export declare class BrowserPool {
|
|
|
205
213
|
* waits FIFO until a slot frees (or until `signal` aborts, if provided), unless `whenFull` is
|
|
206
214
|
* `'refuse'`: then it throws {@link PoolAtCapacityError} at once and claims nothing.
|
|
207
215
|
*/
|
|
208
|
-
acquire(url: string, opts?:
|
|
209
|
-
signal?: AbortSignal;
|
|
210
|
-
/**
|
|
211
|
-
* `'wait'` (the default) queues behind the cap. `'refuse'` is for a caller that has a person
|
|
212
|
-
* or an agent waiting on the answer and no way to see a queue: it is told the pool is full.
|
|
213
|
-
*/
|
|
214
|
-
whenFull?: 'wait' | 'refuse';
|
|
215
|
-
sessionId?: string;
|
|
216
|
-
seedStorage?: SeedStorage;
|
|
217
|
-
owner?: string;
|
|
218
|
-
/** In a browser with a window the person can watch. */
|
|
219
|
-
headed?: boolean;
|
|
220
|
-
/**
|
|
221
|
-
* JavaScript installed before any page script runs, for this lease only. A view built for a
|
|
222
|
-
* desktop shell calls bindings the shell injects (`window.go`, `window.runtime`, a preload
|
|
223
|
-
* object) on mount; a stub here is what lets it reach its data path in a leased tab.
|
|
224
|
-
*/
|
|
225
|
-
initScript?: string;
|
|
226
|
-
/** Granted on the lease's origin before the first navigation, so the first render sees them. */
|
|
227
|
-
permissions?: readonly string[];
|
|
228
|
-
/** Accept a self-signed or local-CA dev certificate for this lease's context only (#1255). */
|
|
229
|
-
ignoreHTTPSErrors?: boolean;
|
|
230
|
-
/** Media and viewport set on the context, so the first paint already has them. */
|
|
231
|
-
emulate?: LeaseEmulation;
|
|
232
|
-
}): Promise<Lease>;
|
|
216
|
+
acquire(url: string, opts?: AcquireOptions): Promise<Lease>;
|
|
233
217
|
/**
|
|
234
218
|
* The websocket address this lease's page reported it could not reach, if it reported one.
|
|
235
219
|
*
|
|
@@ -243,6 +227,8 @@ export declare class BrowserPool {
|
|
|
243
227
|
lastDialogMessage(sessionId: string): string | undefined;
|
|
244
228
|
/** Close every context and the browser. Pending waiters are rejected (the pool is terminal now). */
|
|
245
229
|
shutdown(): Promise<void>;
|
|
230
|
+
/** The origin added to this lease's page CSP `connect-src`, or undefined if none was (#2016). */
|
|
231
|
+
cspWidenedFor(sessionId: string): string | undefined;
|
|
246
232
|
/** Whether this lease's context skips certificate checks. A context cannot change it later. */
|
|
247
233
|
ignoresHTTPSErrors(sessionId: string): boolean;
|
|
248
234
|
/** Whether this lease lives in the headed browser. */
|
|
@@ -14,10 +14,12 @@ import { log } from '../../log.js';
|
|
|
14
14
|
import { closeLeaseTab, LEASE_CLOSE_TIMED_OUT, settledWithin } from './bounded-close.js';
|
|
15
15
|
import { seedStorageInto, targetOriginOf } from './storage-seed.js';
|
|
16
16
|
import { installLeaseMarker, leaseMarkerOf } from './lease-marker-stamp.js';
|
|
17
|
-
import { grantLeasePermissions, readNotificationPermission } from './context-permissions.js';
|
|
17
|
+
import { grantLeasePermissions, grantLocalNetworkAccess, readNotificationPermission, widenLeaseCsp, } from './context-permissions.js';
|
|
18
18
|
import { readViewport } from './lease-emulation.js';
|
|
19
|
-
import {
|
|
20
|
-
import {
|
|
19
|
+
import { injectReaderInto } from './zero-install.js';
|
|
20
|
+
import { stepPage } from './determinism.js';
|
|
21
|
+
import { DEFAULT_LEASE_TTL_MS, DEFAULT_NAV_TIMEOUT_MS, INIT_SCRIPT_UNSUPPORTED, MAX_REMEMBERED_REAPED_LEASES, NO_HEADED_BROWSER, ORPHANED_LEASE_GRACE_MS, navStatusOf, pageLoading, PoolAtCapacityError, } from './pool-lease.js';
|
|
22
|
+
import { listenForPageErrors, reportLeaseClosed, } from './lease-page-error.js';
|
|
21
23
|
export { DEFAULT_LEASE_TTL_MS, NO_HEADED_BROWSER, ORPHANED_LEASE_GRACE_MS, PoolAtCapacityError, } from './pool-lease.js';
|
|
22
24
|
/**
|
|
23
25
|
* Owns a headless browser (and, when asked, a headed one) and leases isolated contexts out of them,
|
|
@@ -30,6 +32,8 @@ export class BrowserPool {
|
|
|
30
32
|
#now;
|
|
31
33
|
#ttl;
|
|
32
34
|
#zeroInstall;
|
|
35
|
+
#daemonOrigin;
|
|
36
|
+
#pageErrorHooks;
|
|
33
37
|
#navTimeout;
|
|
34
38
|
#headless;
|
|
35
39
|
#headed;
|
|
@@ -73,6 +77,8 @@ export class BrowserPool {
|
|
|
73
77
|
this.#ttl = opts.leaseTtlMs ?? DEFAULT_LEASE_TTL_MS;
|
|
74
78
|
this.#navTimeout = opts.navTimeoutMs ?? DEFAULT_NAV_TIMEOUT_MS;
|
|
75
79
|
this.#zeroInstall = opts.zeroInstallScript;
|
|
80
|
+
this.#daemonOrigin = opts.daemonOrigin;
|
|
81
|
+
this.#pageErrorHooks = opts;
|
|
76
82
|
}
|
|
77
83
|
/** The TTL configured for leases — how long an untouched lease lives before the reaper reclaims it. */
|
|
78
84
|
leaseTtlMs() {
|
|
@@ -109,17 +115,9 @@ export class BrowserPool {
|
|
|
109
115
|
return undefined;
|
|
110
116
|
}
|
|
111
117
|
for (const [leaseId, lease] of this.#active) {
|
|
112
|
-
if (lease.owner !== owner
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
let leaseOrigin;
|
|
116
|
-
try {
|
|
117
|
-
leaseOrigin = new URL(lease.url).origin;
|
|
118
|
-
}
|
|
119
|
-
catch {
|
|
120
|
-
continue;
|
|
121
|
-
}
|
|
122
|
-
if (leaseOrigin !== origin) {
|
|
118
|
+
if (lease.owner !== owner ||
|
|
119
|
+
!URL.canParse(lease.url) ||
|
|
120
|
+
new URL(lease.url).origin !== origin) {
|
|
123
121
|
continue;
|
|
124
122
|
}
|
|
125
123
|
for (const [alias, id] of this.#aliases) {
|
|
@@ -247,15 +245,21 @@ export class BrowserPool {
|
|
|
247
245
|
return undefined;
|
|
248
246
|
}
|
|
249
247
|
this.touch(sessionId);
|
|
248
|
+
delete lease.captureError;
|
|
250
249
|
try {
|
|
251
250
|
return await lease.page.screenshot(opts);
|
|
252
251
|
}
|
|
253
|
-
catch {
|
|
254
|
-
// A capture that fails is not a broken lease.
|
|
255
|
-
//
|
|
252
|
+
catch (error) {
|
|
253
|
+
// A capture that fails is not a broken lease. Keep the reason and leave the lease usable,
|
|
254
|
+
// so the screenshot error says why the browser capture failed.
|
|
255
|
+
lease.captureError = error instanceof Error ? error.message : String(error);
|
|
256
256
|
return undefined;
|
|
257
257
|
}
|
|
258
258
|
}
|
|
259
|
+
/** The reason {@link screenshotLease} last failed for this session, if it did. */
|
|
260
|
+
leaseCaptureError(sessionId) {
|
|
261
|
+
return this.#active.get(this.#leaseIdOf(sessionId))?.captureError;
|
|
262
|
+
}
|
|
259
263
|
/** The URL a lease was opened on — the one that carries its Reticle identity. */
|
|
260
264
|
leaseUrl(sessionId) {
|
|
261
265
|
return this.#active.get(this.#leaseIdOf(sessionId))?.url;
|
|
@@ -300,6 +304,21 @@ export class BrowserPool {
|
|
|
300
304
|
return false;
|
|
301
305
|
}
|
|
302
306
|
}
|
|
307
|
+
/** Reload a lease with the browser cache ignored, or false when this is not a lease or its page cannot. */
|
|
308
|
+
async hardReloadLease(sessionId) {
|
|
309
|
+
const lease = this.#active.get(this.#leaseIdOf(sessionId));
|
|
310
|
+
if (lease?.page.reloadIgnoringCache === undefined) {
|
|
311
|
+
return false;
|
|
312
|
+
}
|
|
313
|
+
this.touch(sessionId);
|
|
314
|
+
try {
|
|
315
|
+
await lease.page.reloadIgnoringCache();
|
|
316
|
+
return true;
|
|
317
|
+
}
|
|
318
|
+
catch {
|
|
319
|
+
return false;
|
|
320
|
+
}
|
|
321
|
+
}
|
|
303
322
|
/** Set a live lease's media features, or false when this is not a lease or its page cannot. */
|
|
304
323
|
async emulateLease(sessionId, media) {
|
|
305
324
|
const lease = this.#active.get(this.#leaseIdOf(sessionId));
|
|
@@ -392,6 +411,17 @@ export class BrowserPool {
|
|
|
392
411
|
return false;
|
|
393
412
|
}
|
|
394
413
|
}
|
|
414
|
+
/** Step a deterministic lease's clock by `frames` frames; undefined when it is not one. */
|
|
415
|
+
stepLease(sessionId, frames) {
|
|
416
|
+
const page = this.#active.get(this.#leaseIdOf(sessionId))?.page;
|
|
417
|
+
this.touch(sessionId);
|
|
418
|
+
return page === undefined ? Promise.resolve(undefined) : stepPage(page, frames);
|
|
419
|
+
}
|
|
420
|
+
/** The JS coverage of a lease's page, or undefined when this is not a lease or cannot measure. */
|
|
421
|
+
coverageOf(sessionId) {
|
|
422
|
+
this.touch(sessionId);
|
|
423
|
+
return this.#active.get(this.#leaseIdOf(sessionId))?.page.jsCoverage;
|
|
424
|
+
}
|
|
395
425
|
/** Guard a leased page's requests, or false when this is not a lease or its page cannot. */
|
|
396
426
|
async guardLease(sessionId, decide) {
|
|
397
427
|
const lease = this.#active.get(this.#leaseIdOf(sessionId));
|
|
@@ -510,16 +540,17 @@ export class BrowserPool {
|
|
|
510
540
|
const browser = await this.#ensureBrowser(slot);
|
|
511
541
|
const contextOpts = {
|
|
512
542
|
...(true === opts.ignoreHTTPSErrors ? { ignoreHTTPSErrors: true } : {}),
|
|
543
|
+
...(true === opts.jsCoverage ? { jsCoverage: true } : {}),
|
|
513
544
|
...opts.emulate,
|
|
514
545
|
};
|
|
515
546
|
context = await browser.newContext(0 < Object.keys(contextOpts).length ? contextOpts : undefined);
|
|
516
547
|
if (opts.permissions !== undefined) {
|
|
517
548
|
await grantLeasePermissions(context, opts.permissions, url);
|
|
518
549
|
}
|
|
550
|
+
await grantLocalNetworkAccess(context, url);
|
|
551
|
+
const csp = await widenLeaseCsp(context, url, this.#daemonOrigin);
|
|
519
552
|
const page = await context.newPage();
|
|
520
|
-
// A
|
|
521
|
-
// to exist before the app's first module runs. Installed here — before goto — so the very
|
|
522
|
-
// first document gets it, and kept for the lease (see hostStub) so a reload keeps it too.
|
|
553
|
+
// A desktop-shell stub must exist before the app's first module: added before goto, and kept.
|
|
523
554
|
let hostStub;
|
|
524
555
|
if (opts.initScript !== undefined) {
|
|
525
556
|
const added = await page.addInitScript?.(opts.initScript);
|
|
@@ -549,9 +580,8 @@ export class BrowserPool {
|
|
|
549
580
|
pending = dialled;
|
|
550
581
|
} // logged during goto, before the lease is registered below
|
|
551
582
|
});
|
|
552
|
-
//
|
|
553
|
-
//
|
|
554
|
-
// just ones opened after the lease is registered.
|
|
583
|
+
// Listen before goto, as onConsole does: a dialog in an onload handler is dismissed too. The SDK
|
|
584
|
+
// answers a dialog from its own input first; the hook records this "no" for the verdict (#1350).
|
|
555
585
|
page.onDialog?.((dialog) => {
|
|
556
586
|
const active = this.#active.get(sessionId);
|
|
557
587
|
if (active !== undefined) {
|
|
@@ -561,7 +591,10 @@ export class BrowserPool {
|
|
|
561
591
|
pendingDialogMessage = dialog.message;
|
|
562
592
|
}
|
|
563
593
|
void dialog.dismiss();
|
|
594
|
+
this.#pageErrorHooks?.onDialog?.(sessionId, dialog);
|
|
564
595
|
});
|
|
596
|
+
// Listener on BEFORE goto — an import-time throw lands during it (#1966).
|
|
597
|
+
await listenForPageErrors(page, sessionId, this.#pageErrorHooks);
|
|
565
598
|
const marker = leaseMarkerOf(url);
|
|
566
599
|
if (marker?.session === sessionId) {
|
|
567
600
|
await installLeaseMarker(page, sessionId, targetOriginOf(url), marker.project);
|
|
@@ -593,24 +626,7 @@ export class BrowserPool {
|
|
|
593
626
|
// Foreground it: a page opened beside other tabs can start hidden (#1351). Best-effort — a tab
|
|
594
627
|
// that stays hidden is reported by name at the lease, which failing here would lose.
|
|
595
628
|
await page.bringToFront?.().catch(() => undefined);
|
|
596
|
-
|
|
597
|
-
if (null !== navRes && 'object' === typeof navRes && 'status' in navRes) {
|
|
598
|
-
const s = navRes.status;
|
|
599
|
-
if ('function' === typeof s) {
|
|
600
|
-
try {
|
|
601
|
-
const code = s.call(navRes);
|
|
602
|
-
if ('number' === typeof code) {
|
|
603
|
-
navStatus = code;
|
|
604
|
-
}
|
|
605
|
-
}
|
|
606
|
-
catch {
|
|
607
|
-
// ignore
|
|
608
|
-
}
|
|
609
|
-
}
|
|
610
|
-
else if ('number' === typeof s) {
|
|
611
|
-
navStatus = s;
|
|
612
|
-
}
|
|
613
|
-
}
|
|
629
|
+
const navStatus = navStatusOf(navRes);
|
|
614
630
|
this.#active.set(sessionId, {
|
|
615
631
|
headed: slot.headed,
|
|
616
632
|
context,
|
|
@@ -620,6 +636,7 @@ export class BrowserPool {
|
|
|
620
636
|
touchedAt: this.#now(),
|
|
621
637
|
permissions: opts.permissions ?? [],
|
|
622
638
|
ignoresHTTPSErrors: true === opts.ignoreHTTPSErrors,
|
|
639
|
+
csp,
|
|
623
640
|
...(pending === undefined ? {} : { dialFailureUrl: pending }),
|
|
624
641
|
...(pendingDialogMessage === undefined ? {} : { lastDialogMessage: pendingDialogMessage }),
|
|
625
642
|
...(hostStub === undefined || opts.initScript === undefined
|
|
@@ -631,17 +648,7 @@ export class BrowserPool {
|
|
|
631
648
|
url,
|
|
632
649
|
...(navStatus !== undefined ? { navStatus } : {}),
|
|
633
650
|
release: () => this.#release(sessionId),
|
|
634
|
-
injectReader:
|
|
635
|
-
const script = this.#zeroInstall?.();
|
|
636
|
-
if (script === undefined || page.evaluate === undefined) {
|
|
637
|
-
return false;
|
|
638
|
-
}
|
|
639
|
-
await page.addInitScript?.(script);
|
|
640
|
-
if (READER_NOT_HTML === (await page.evaluate(script))) {
|
|
641
|
-
throw new NotHtmlDocumentError();
|
|
642
|
-
}
|
|
643
|
-
return true;
|
|
644
|
-
},
|
|
651
|
+
injectReader: () => injectReaderInto(page, this.#zeroInstall?.(url)),
|
|
645
652
|
isLoading: () => pageLoading(page),
|
|
646
653
|
};
|
|
647
654
|
}
|
|
@@ -703,6 +710,7 @@ export class BrowserPool {
|
|
|
703
710
|
return;
|
|
704
711
|
} // already released or lost to a crash
|
|
705
712
|
this.#active.delete(sessionId);
|
|
713
|
+
reportLeaseClosed(this.#pageErrorHooks, sessionId);
|
|
706
714
|
// Drop any alias pointing here, or the map grows for the life of the daemon and a later lease
|
|
707
715
|
// reusing that registered name would resolve to a context that is already closed.
|
|
708
716
|
for (const [registered, leaseId] of this.#aliases) {
|
|
@@ -863,6 +871,10 @@ export class BrowserPool {
|
|
|
863
871
|
waiter();
|
|
864
872
|
} // let them re-claim + relaunch
|
|
865
873
|
}
|
|
874
|
+
/** The origin added to this lease's page CSP `connect-src`, or undefined if none was (#2016). */
|
|
875
|
+
cspWidenedFor(sessionId) {
|
|
876
|
+
return this.#active.get(this.#leaseIdOf(sessionId))?.csp.widenedFor;
|
|
877
|
+
}
|
|
866
878
|
/** Whether this lease's context skips certificate checks. A context cannot change it later. */
|
|
867
879
|
ignoresHTTPSErrors(sessionId) {
|
|
868
880
|
return true === this.#active.get(this.#leaseIdOf(sessionId))?.ignoresHTTPSErrors;
|
|
@@ -1,20 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Browser permissions on a leased context: granted before the first navigation, and read back where
|
|
3
|
-
* the browser can contradict the grant.
|
|
4
|
-
*
|
|
5
|
-
* Never changed on a lease that is already open. Acquire hands an origin's live lease to whoever asks
|
|
6
|
-
* for that origin, so the lease may be another agent's tab mid-flow, and nothing here knows whose it
|
|
7
|
-
* is. A different set means a fresh lease.
|
|
8
|
-
*
|
|
9
|
-
* Each grant is scoped to the origin the lease was opened on, so a third-party frame the app embeds
|
|
10
|
-
* is not handed the same grant as the app.
|
|
11
|
-
*
|
|
12
|
-
* Notifications are why the read-back exists. Playwright's headless shell — what the pool launches
|
|
13
|
-
* when Playwright's own Chromium is installed — has no notification support: after a grant,
|
|
14
|
-
* `navigator.permissions.query` reports `granted` while `Notification.permission` still reads
|
|
15
|
-
* `denied`. A page that gates its UI on the second never sees the grant, so a lease that reported
|
|
16
|
-
* "granted" there would be reporting something the page cannot see.
|
|
17
|
-
*/
|
|
18
1
|
import type { PooledContext, PooledPage } from './pool-contract.js';
|
|
19
2
|
/** The permission whose grant the headless shell does not pass on to `Notification.permission`. */
|
|
20
3
|
export declare const NOTIFICATIONS_PERMISSION = "notifications";
|
|
@@ -31,6 +14,19 @@ export declare class LeasePermissionError extends Error {
|
|
|
31
14
|
}
|
|
32
15
|
/** Grant `permissions` on the origin of `url`. Nothing to grant is a no-op, not a refusal. */
|
|
33
16
|
export declare function grantLeasePermissions(context: PooledContext, permissions: readonly string[], url: string): Promise<void>;
|
|
17
|
+
/** The origin of `url` when the page is not on loopback, else undefined (also for no url). */
|
|
18
|
+
export declare function offLoopbackOrigin(url: string | undefined): string | undefined;
|
|
19
|
+
/** Playwright's name for Chrome's Local Network Access grant (local + loopback network). */
|
|
20
|
+
export declare const LOCAL_NETWORK_ACCESS = "local-network-access";
|
|
21
|
+
/**
|
|
22
|
+
* Let a page that is not on loopback dial the bridge on loopback. Chromium blocks that unless a
|
|
23
|
+
* person grants Local Network Access, and a leased browser has no person, so a lease on a hosted
|
|
24
|
+
* preview loaded, signed in, and answered `sdk_never_dialled`. A loopback page needs no grant.
|
|
25
|
+
*
|
|
26
|
+
* ponytail: best effort. A Playwright older than the permission name refuses it; the lease then
|
|
27
|
+
* opens as before, and a page that cannot dial still reports `sdk_never_dialled`.
|
|
28
|
+
*/
|
|
29
|
+
export declare function grantLocalNetworkAccess(context: PooledContext, url: string): Promise<void>;
|
|
34
30
|
/**
|
|
35
31
|
* What the page's `Notification.permission` says, or undefined when it cannot be asked.
|
|
36
32
|
*
|
|
@@ -39,3 +35,24 @@ export declare function grantLeasePermissions(context: PooledContext, permission
|
|
|
39
35
|
* instead of holding the caller.
|
|
40
36
|
*/
|
|
41
37
|
export declare function readNotificationPermission(page: PooledPage): Promise<string | undefined>;
|
|
38
|
+
/** How long the loopback CSP probe may take. Bounded because acquire waits on it. */
|
|
39
|
+
export declare const CSP_PROBE_TIMEOUT_MS = 2000;
|
|
40
|
+
/** The part of `fetch` the probe uses. */
|
|
41
|
+
export type CspProbeFetch = (url: string, init: {
|
|
42
|
+
signal: AbortSignal;
|
|
43
|
+
}) => Promise<Pick<Response, 'headers' | 'text'>>;
|
|
44
|
+
/**
|
|
45
|
+
* Whether the document at `url` sends a CSP (header or meta tag) that would block a dial to
|
|
46
|
+
* `daemonOrigin` (#2163). False when it cannot be asked: the lease then opens as before.
|
|
47
|
+
*/
|
|
48
|
+
export declare function pageCspBlocksDaemon(url: string, daemonOrigin: string, probe?: CspProbeFetch): Promise<boolean>;
|
|
49
|
+
/**
|
|
50
|
+
* On a lease whose page's CSP would block the daemon, add `daemonOrigin` to its `connect-src`
|
|
51
|
+
* (#2016). Off loopback this always installs the route. On loopback it installs it only when a
|
|
52
|
+
* probe of the page finds a CSP that blocks the dial (#2163), because the route sees every request
|
|
53
|
+
* in the context, and a dev server that sends no CSP should not pay for it. The returned record
|
|
54
|
+
* gets `widenedFor` once a response was really widened, so the lease can say so.
|
|
55
|
+
*/
|
|
56
|
+
export declare function widenLeaseCsp(context: PooledContext, url: string, daemonOrigin: string | undefined, probe?: CspProbeFetch): Promise<{
|
|
57
|
+
widenedFor?: string;
|
|
58
|
+
}>;
|