@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
|
@@ -22,10 +22,28 @@ export declare function within(child: string | undefined, parent: string): boole
|
|
|
22
22
|
export declare function projectAppUrlFinder(io: Pick<FirstCallIo, 'project' | 'serving' | 'servingDirectory'>): () => Promise<string | undefined>;
|
|
23
23
|
/** One lease per project for the daemon's life: a failure is reported once, never retried. */
|
|
24
24
|
export declare function firstCallOpener(io: FirstCallIo): () => Promise<FirstCallOpened | undefined>;
|
|
25
|
+
/**
|
|
26
|
+
* The first-session offer, on the first tool call of each agent connection.
|
|
27
|
+
*
|
|
28
|
+
* The plugin's SessionStart hook says it when a session starts. A plugin installed in an open
|
|
29
|
+
* session and loaded with `/reload-plugins` fires no SessionStart, so the server says it too. Only
|
|
30
|
+
* the first call of a connection looks: an offer on a later call reads as noise.
|
|
31
|
+
*/
|
|
32
|
+
export interface FirstSessionOfferIo {
|
|
33
|
+
/** The unwired web app this call is about; undefined when wired, not a web app, or no project. */
|
|
34
|
+
project: () => string | undefined;
|
|
35
|
+
/** Whether an app is attached now. */
|
|
36
|
+
connected: () => boolean;
|
|
37
|
+
/** Called once for each offer that goes out, with its project. */
|
|
38
|
+
offered: (dir: string) => void;
|
|
39
|
+
}
|
|
40
|
+
/** The offer for this connection's first call, or undefined. Each attach id gets one look. */
|
|
41
|
+
export declare function firstSessionOfferGate(io: FirstSessionOfferIo): (attachId: string) => string | undefined;
|
|
25
42
|
/**
|
|
26
43
|
* The daemon's two answers to an app nobody wired, built together because both ask the same
|
|
27
44
|
* question first — which unwired web app is this caller in. `firstRun` names it when the agent
|
|
28
|
-
* lists sessions; `openUnwiredApp` opens it zero-install on a page-needing call
|
|
45
|
+
* lists sessions; `openUnwiredApp` opens it zero-install on a page-needing call;
|
|
46
|
+
* `firstSessionOffer` says the offer on the first call of each agent connection.
|
|
29
47
|
*/
|
|
30
48
|
export declare function agentWiring(sessions: {
|
|
31
49
|
list(): readonly unknown[];
|
|
@@ -33,4 +51,5 @@ export declare function agentWiring(sessions: {
|
|
|
33
51
|
firstRun: FirstRunWiring;
|
|
34
52
|
openUnwiredApp: () => Promise<FirstCallOpened | undefined>;
|
|
35
53
|
projectAppUrl: () => Promise<string | undefined>;
|
|
54
|
+
firstSessionOffer: (attachId: string) => string | undefined;
|
|
36
55
|
};
|
|
@@ -21,8 +21,11 @@ import { DEV_SERVER_PORTS } from '../../command/cli/ports/resolve/cli-port.js';
|
|
|
21
21
|
import { callingClientDirectory } from '../../hooks/client-directory.js';
|
|
22
22
|
import { detectDevCommandInProject, initCommandIn } from './dev-server/dev-command.js';
|
|
23
23
|
import { probeDevServerStates } from './dev-server/dev-server-probe.js';
|
|
24
|
+
import { NextStepOffered } from '@reticlehq/core';
|
|
25
|
+
import { readProjectId } from '../../command/cli/ports/resolve/cli-port.js';
|
|
26
|
+
import { noteNextStepOffered } from '../../telemetry/onboarding-firsts.js';
|
|
24
27
|
import { firstRunWiring } from './first-run-wiring.js';
|
|
25
|
-
import { wiringConsent } from './no-session-next-action.js';
|
|
28
|
+
import { firstSessionOffer, wiringConsent } from './no-session-next-action.js';
|
|
26
29
|
import { servingDirectoryOf } from './serving-directory.js';
|
|
27
30
|
const LOCALHOST = 'http://localhost';
|
|
28
31
|
/** The path with symlinks resolved when it exists (lsof reports `/private/tmp`, callers `/tmp`). */
|
|
@@ -87,10 +90,32 @@ export function firstCallOpener(io) {
|
|
|
87
90
|
return { url, notice: openedNotice(url, initCommandIn(dir)) };
|
|
88
91
|
};
|
|
89
92
|
}
|
|
93
|
+
/** The offer for this connection's first call, or undefined. Each attach id gets one look. */
|
|
94
|
+
export function firstSessionOfferGate(io) {
|
|
95
|
+
// ponytail: one short id per MCP connection for the daemon's life; bound it if a daemon ever
|
|
96
|
+
// serves connections by the million.
|
|
97
|
+
const looked = new Set();
|
|
98
|
+
return (attachId) => {
|
|
99
|
+
if (looked.has(attachId)) {
|
|
100
|
+
return undefined;
|
|
101
|
+
}
|
|
102
|
+
looked.add(attachId);
|
|
103
|
+
if (io.connected()) {
|
|
104
|
+
return undefined;
|
|
105
|
+
}
|
|
106
|
+
const dir = io.project();
|
|
107
|
+
if (dir === undefined) {
|
|
108
|
+
return undefined;
|
|
109
|
+
}
|
|
110
|
+
io.offered(dir);
|
|
111
|
+
return firstSessionOffer(initCommandIn(dir));
|
|
112
|
+
};
|
|
113
|
+
}
|
|
90
114
|
/**
|
|
91
115
|
* The daemon's two answers to an app nobody wired, built together because both ask the same
|
|
92
116
|
* question first — which unwired web app is this caller in. `firstRun` names it when the agent
|
|
93
|
-
* lists sessions; `openUnwiredApp` opens it zero-install on a page-needing call
|
|
117
|
+
* lists sessions; `openUnwiredApp` opens it zero-install on a page-needing call;
|
|
118
|
+
* `firstSessionOffer` says the offer on the first call of each agent connection.
|
|
94
119
|
*/
|
|
95
120
|
export function agentWiring(sessions, lease) {
|
|
96
121
|
const firstRun = firstRunWiring();
|
|
@@ -107,5 +132,12 @@ export function agentWiring(sessions, lease) {
|
|
|
107
132
|
firstRun,
|
|
108
133
|
openUnwiredApp: firstCallOpener(io),
|
|
109
134
|
projectAppUrl: projectAppUrlFinder({ ...io, project: callerFolder }),
|
|
135
|
+
firstSessionOffer: firstSessionOfferGate({
|
|
136
|
+
...io,
|
|
137
|
+
// The offer leads with the lease, so it is counted as a lease offer.
|
|
138
|
+
offered: (dir) => {
|
|
139
|
+
noteNextStepOffered(NextStepOffered.LEASE, () => readProjectId(dir) !== undefined);
|
|
140
|
+
},
|
|
141
|
+
}),
|
|
110
142
|
};
|
|
111
143
|
}
|
package/dist/start-wiring.d.ts
CHANGED
|
@@ -3,14 +3,40 @@ import type { StartOptions } from './start-options.js';
|
|
|
3
3
|
import type { Bridge } from './portal/bridge/bridge.js';
|
|
4
4
|
import type { RealInputProvider } from './portal/input/real-input.js';
|
|
5
5
|
import { BrowserPool } from './portal/pool/browser-pool.js';
|
|
6
|
+
import { type PageErrorJournal } from './portal/pool/page-error-journal.js';
|
|
7
|
+
import type { PooledPageError } from './portal/pool/pool-contract.js';
|
|
8
|
+
import type { BrowserPoolOptions } from './portal/pool/pool-lease.js';
|
|
6
9
|
import { type InjectedConnect } from './portal/pool/zero-install.js';
|
|
10
|
+
import type { NonceMinter } from './portal/production/production-activation.js';
|
|
7
11
|
/**
|
|
8
12
|
* Build the shared browser pool (one headless Chromium, N capped isolated leased contexts). Lazy —
|
|
9
13
|
* no Chromium launches until the first lease — so creating it is free even when never used.
|
|
10
14
|
*/
|
|
11
15
|
/** Where the zero-install reader connects: this daemon's own bridge, with its pairing token. */
|
|
12
16
|
export declare function readerConnect(port: number, token: string | undefined): InjectedConnect;
|
|
13
|
-
|
|
17
|
+
/**
|
|
18
|
+
* The zero-install script for pages that connect to `reader`, built on first use and kept: the
|
|
19
|
+
* page that needs it is one whose app never connected. Undefined when this install has no reader.
|
|
20
|
+
*
|
|
21
|
+
* A page that is not on loopback gets a nonce minted for its origin in place of the pairing token.
|
|
22
|
+
* The bridge admits a WebSocket from an origin only while a nonce names it, so the reader on a
|
|
23
|
+
* deployed page was refused with a 403 (#2016). The nonce also keeps the machine's pairing token
|
|
24
|
+
* out of a page that somebody else serves.
|
|
25
|
+
*
|
|
26
|
+
* ponytail: the nonce lives for one drive (SESSION_NONCE_TTL_MS). A lease reloaded after that
|
|
27
|
+
* dials with a dead nonce; mint per navigation if that is ever seen.
|
|
28
|
+
*/
|
|
29
|
+
export declare function zeroInstallLoader(reader: InjectedConnect, nonces?: Pick<NonceMinter, 'mint'>): (url?: string) => string | undefined;
|
|
30
|
+
export declare function createBrowserPool(headless: boolean, reader: InjectedConnect, onPageError?: (leaseId: string, error: PooledPageError) => void, onLeaseClosed?: (leaseId: string) => void, nonces?: Pick<NonceMinter, 'mint'>, onDialog?: BrowserPoolOptions['onDialog']): BrowserPool;
|
|
31
|
+
/**
|
|
32
|
+
* Journal the uncaught page errors the pool hears into the session that connects for that lease.
|
|
33
|
+
*
|
|
34
|
+
* The pool sees every throw its pages make from before the first navigation; the SDK only exists
|
|
35
|
+
* afterwards. Without this wiring an import-time crash — a blank page with no error text anywhere
|
|
36
|
+
* (#1966) — was invisible to the agent driving it. Returns the journal so the pool's sink can be
|
|
37
|
+
* handed over; the bridge hook is registered here.
|
|
38
|
+
*/
|
|
39
|
+
export declare function attachPageErrorJournal(bridge: Bridge): PageErrorJournal;
|
|
14
40
|
/**
|
|
15
41
|
* Route CDP-authoritative network detail onto the driven session's journal.
|
|
16
42
|
*
|
|
@@ -26,7 +52,9 @@ export declare function makeNetworkDetailRouter(bridge: Bridge, driveUrl: string
|
|
|
26
52
|
* so a failed launch never leaks a WS port. A past divergence between the two paths let daemon mode
|
|
27
53
|
* run with a different setup — this removes that risk.
|
|
28
54
|
*/
|
|
29
|
-
export declare function resolveRealInput(options: StartOptions, onNavigateError: () => Promise<void>, onNetworkDetail?: (detail: NetworkDetail) => void
|
|
55
|
+
export declare function resolveRealInput(options: StartOptions, onNavigateError: () => Promise<void>, onNetworkDetail?: (detail: NetworkDetail) => void,
|
|
56
|
+
/** Where a driven page with no SDK connects the zero-install reader. Absent: it gets none. */
|
|
57
|
+
reader?: InjectedConnect): Promise<{
|
|
30
58
|
realInput?: RealInputProvider;
|
|
31
59
|
owned?: {
|
|
32
60
|
dispose: () => Promise<void>;
|
package/dist/start-wiring.js
CHANGED
|
@@ -23,7 +23,10 @@ import { SERVER_VERSION } from './command/version/identity/server-version.js';
|
|
|
23
23
|
import { CdpRealInputProvider, LaunchedRealInputProvider } from './portal/input/real-input.js';
|
|
24
24
|
import { BrowserPool } from './portal/pool/browser-pool.js';
|
|
25
25
|
import { playwrightLauncher, resolveMaxContexts } from './portal/pool/playwright-launcher.js';
|
|
26
|
+
import { makePageErrorJournal } from './portal/pool/page-error-journal.js';
|
|
27
|
+
import { resolveLeasedSessionId } from './surface/tools/lease-tools.js';
|
|
26
28
|
import { readReaderBundle, zeroInstallScript as zeroInstallScriptFor, } from './portal/pool/zero-install.js';
|
|
29
|
+
import { offLoopbackOrigin } from './portal/pool/context-permissions.js';
|
|
27
30
|
/**
|
|
28
31
|
* Build the shared browser pool (one headless Chromium, N capped isolated leased contexts). Lazy —
|
|
29
32
|
* no Chromium launches until the first lease — so creating it is free even when never used.
|
|
@@ -32,26 +35,85 @@ import { readReaderBundle, zeroInstallScript as zeroInstallScriptFor, } from './
|
|
|
32
35
|
export function readerConnect(port, token) {
|
|
33
36
|
return { url: bridgeWsUrl(port), ...(token === undefined ? {} : { token }) };
|
|
34
37
|
}
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
38
|
+
/**
|
|
39
|
+
* The zero-install script for pages that connect to `reader`, built on first use and kept: the
|
|
40
|
+
* page that needs it is one whose app never connected. Undefined when this install has no reader.
|
|
41
|
+
*
|
|
42
|
+
* A page that is not on loopback gets a nonce minted for its origin in place of the pairing token.
|
|
43
|
+
* The bridge admits a WebSocket from an origin only while a nonce names it, so the reader on a
|
|
44
|
+
* deployed page was refused with a 403 (#2016). The nonce also keeps the machine's pairing token
|
|
45
|
+
* out of a page that somebody else serves.
|
|
46
|
+
*
|
|
47
|
+
* ponytail: the nonce lives for one drive (SESSION_NONCE_TTL_MS). A lease reloaded after that
|
|
48
|
+
* dials with a dead nonce; mint per navigation if that is ever seen.
|
|
49
|
+
*/
|
|
50
|
+
export function zeroInstallLoader(reader, nonces) {
|
|
41
51
|
let script;
|
|
42
|
-
|
|
52
|
+
return (url) => {
|
|
53
|
+
const origin = offLoopbackOrigin(url);
|
|
54
|
+
if (origin !== undefined && nonces !== undefined) {
|
|
55
|
+
const bundle = readReaderBundle();
|
|
56
|
+
if (bundle === undefined) {
|
|
57
|
+
return undefined;
|
|
58
|
+
}
|
|
59
|
+
return zeroInstallScriptFor(bundle, {
|
|
60
|
+
url: reader.url,
|
|
61
|
+
token: nonces.mint({ origin }).nonce,
|
|
62
|
+
});
|
|
63
|
+
}
|
|
43
64
|
if (script === undefined) {
|
|
44
65
|
const bundle = readReaderBundle();
|
|
45
66
|
script = bundle === undefined ? null : zeroInstallScriptFor(bundle, reader);
|
|
46
67
|
}
|
|
47
68
|
return script ?? undefined;
|
|
48
69
|
};
|
|
70
|
+
}
|
|
71
|
+
export function createBrowserPool(headless, reader, onPageError, onLeaseClosed, nonces, onDialog) {
|
|
72
|
+
const maxContexts = resolveMaxContexts(process.env[ReticleEnv.MAX_CONTEXTS], cpus().length);
|
|
73
|
+
const genSessionId = () => `lease-${'function' === typeof globalThis.crypto?.randomUUID
|
|
74
|
+
? globalThis.crypto.randomUUID()
|
|
75
|
+
: String(Date.now())}`;
|
|
49
76
|
return new BrowserPool(playwrightLauncher({ headless }), {
|
|
50
77
|
maxContexts,
|
|
51
78
|
genSessionId,
|
|
52
|
-
zeroInstallScript,
|
|
79
|
+
zeroInstallScript: zeroInstallLoader(reader, nonces),
|
|
80
|
+
// The reader dials this origin; a lease off loopback adds it to the page CSP (#2016).
|
|
81
|
+
daemonOrigin: new URL(reader.url).origin,
|
|
53
82
|
launchHeaded: playwrightLauncher({ headless: false }),
|
|
83
|
+
...(onPageError === undefined ? {} : { onPageError }),
|
|
84
|
+
...(onLeaseClosed === undefined ? {} : { onLeaseClosed }),
|
|
85
|
+
...(onDialog === undefined ? {} : { onDialog }),
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Journal the uncaught page errors the pool hears into the session that connects for that lease.
|
|
90
|
+
*
|
|
91
|
+
* The pool sees every throw its pages make from before the first navigation; the SDK only exists
|
|
92
|
+
* afterwards. Without this wiring an import-time crash — a blank page with no error text anywhere
|
|
93
|
+
* (#1966) — was invisible to the agent driving it. Returns the journal so the pool's sink can be
|
|
94
|
+
* handed over; the bridge hook is registered here.
|
|
95
|
+
*/
|
|
96
|
+
export function attachPageErrorJournal(bridge) {
|
|
97
|
+
const journal = makePageErrorJournal({
|
|
98
|
+
resolveSession: (leaseId) => {
|
|
99
|
+
// Same resolution the lease tool uses: the lease id, or the id of a session whose URL
|
|
100
|
+
// carries the lease marker — an app that registered under its own name still reaches its lease.
|
|
101
|
+
const id = resolveLeasedSessionId(bridge.sessions, leaseId);
|
|
102
|
+
if (id === undefined) {
|
|
103
|
+
return undefined;
|
|
104
|
+
}
|
|
105
|
+
const session = bridge.sessions.get(id);
|
|
106
|
+
return session === undefined ? undefined : session;
|
|
107
|
+
},
|
|
108
|
+
});
|
|
109
|
+
bridge.attachSessionCreate((session) => journal.onSessionCreate(session));
|
|
110
|
+
// The daemon runs for days; both of the journal's maps are keyed by things that end, so both
|
|
111
|
+
// endings are hooked. The bridge's end hook is additive — the durable journal's teardown runs too.
|
|
112
|
+
bridge.attachSessionEnd((session) => {
|
|
113
|
+
journal.onSessionEnd(session.id);
|
|
114
|
+
return Promise.resolve();
|
|
54
115
|
});
|
|
116
|
+
return journal;
|
|
55
117
|
}
|
|
56
118
|
/**
|
|
57
119
|
* Route CDP-authoritative network detail onto the driven session's journal.
|
|
@@ -98,7 +160,9 @@ export function makeNetworkDetailRouter(bridge, driveUrl) {
|
|
|
98
160
|
* so a failed launch never leaks a WS port. A past divergence between the two paths let daemon mode
|
|
99
161
|
* run with a different setup — this removes that risk.
|
|
100
162
|
*/
|
|
101
|
-
export async function resolveRealInput(options, onNavigateError, onNetworkDetail
|
|
163
|
+
export async function resolveRealInput(options, onNavigateError, onNetworkDetail,
|
|
164
|
+
/** Where a driven page with no SDK connects the zero-install reader. Absent: it gets none. */
|
|
165
|
+
reader) {
|
|
102
166
|
const driveUrl = options.driveUrl;
|
|
103
167
|
if (driveUrl !== undefined && driveUrl.length > 0) {
|
|
104
168
|
const headless = options.headless ?? true;
|
|
@@ -114,6 +178,7 @@ export async function resolveRealInput(options, onNavigateError, onNetworkDetail
|
|
|
114
178
|
...(injectConnect !== undefined ? { injectConnect } : {}),
|
|
115
179
|
...(storageState !== undefined ? { storageState } : {}),
|
|
116
180
|
...(onNetworkDetail !== undefined ? { onNetworkDetail } : {}),
|
|
181
|
+
...(reader !== undefined ? { zeroInstallScript: zeroInstallLoader(reader) } : {}),
|
|
117
182
|
}));
|
|
118
183
|
const launched = factory({ driveUrl, headless });
|
|
119
184
|
try {
|
|
@@ -5,6 +5,8 @@ import { localInitializeResponse, degradedInstructions, isHandshakeLine, drainLi
|
|
|
5
5
|
export { HandshakeReplay, RECONNECT_INITIALIZE_ID } from './proxy/proxy-handshake.js';
|
|
6
6
|
import { isToolCallRequest, isToolsListRequest, ToolCatalogCache } from './tool-catalog-cache.js';
|
|
7
7
|
import { rememberEnumerated, rememberProxyStarted, rememberToolCalled } from './attach-memory.js';
|
|
8
|
+
import { initializeClientName, rememberAgentConnected } from './peer/agents-connected.js';
|
|
9
|
+
import { agentClientOf } from '../../hooks/coding-agents.js';
|
|
8
10
|
import { toolsChangedNotification } from './proxy/proxy-handshake.js';
|
|
9
11
|
import { LOOPBACK_HOST, MCP_SSE_PATH, MCP_SHUTDOWN_EVENT, ReticleEnv, CONTRACT_FINGERPRINT, ProxyExitReason, PROXY_ID_PARAM, } from '@reticlehq/core';
|
|
10
12
|
import { SseFrameParser, buildSessionUrl } from './sse-frame-parser.js';
|
|
@@ -17,7 +19,8 @@ import { hasAnyProjectConnectedBefore } from '../../memory/recall/prior/connecti
|
|
|
17
19
|
import { projectIdsAt } from '../../command/cli/ports/resolve/cli-port.js';
|
|
18
20
|
import { PEER_VERSION_PARAM, PEER_CONTRACT_PARAM, agentSessionQuery, } from '../../command/version/peer-announce.js';
|
|
19
21
|
import { onStreamDrop, onClientRequest, onReconnectBudgetSpent, onQueueExpired, OnDrop, OnRequest, } from './proxy/proxy-lifecycle.js';
|
|
20
|
-
import {
|
|
22
|
+
import { probePresence } from '../../command/daemon/binding/port-presence.js';
|
|
23
|
+
import { describePortState } from '../../command/daemon/port-state.js';
|
|
21
24
|
import { PROXY_ID, flushProxyExit, noteProxyDrop, noteProxyToolCall, } from '../../telemetry/proxy-telemetry.js';
|
|
22
25
|
export { flushProxyExit, reportWakeRefused } from '../../telemetry/proxy-telemetry.js';
|
|
23
26
|
import { detectStack } from '../../telemetry/feedback-context.js';
|
|
@@ -513,7 +516,7 @@ boot) {
|
|
|
513
516
|
// The sentence `doctor` has always been able to say, in the log the agent's own process
|
|
514
517
|
// writes. A FOREIGN holder used to be indistinguishable from a free port here, and the
|
|
515
518
|
// proxy spun against it instead of saying which one it was.
|
|
516
|
-
const sentence =
|
|
519
|
+
const sentence = describePortState(presence, port);
|
|
517
520
|
proxyLog('reticle_mcp_proxy_dormant', { port, presence, note: sentence });
|
|
518
521
|
// Nothing is coming that could answer the client's handshake through this port, and the
|
|
519
522
|
// proxy now knows that rather than merely suspecting it. Waiting out LOCAL_HANDSHAKE_MS
|
|
@@ -792,6 +795,11 @@ boot) {
|
|
|
792
795
|
if (isToolsListRequest(trimmed)) {
|
|
793
796
|
rememberEnumerated(reticleStateHome(), port);
|
|
794
797
|
}
|
|
798
|
+
// WHICH agent connected, so the installer and `status` can say "Connected: Cursor ✓".
|
|
799
|
+
const client = agentClientOf(initializeClientName(trimmed));
|
|
800
|
+
if (client !== undefined) {
|
|
801
|
+
rememberAgentConnected(reticleStateHome(), client);
|
|
802
|
+
}
|
|
795
803
|
// The hop every other check misses. Recorded on the REQUEST rather than a reply, because
|
|
796
804
|
// the question is whether anything ever left the agent — a call that leaves and gets no
|
|
797
805
|
// answer is a different fault from one that was never made, and only this side sees it.
|
package/dist/surface/mcp/mcp.js
CHANGED
|
@@ -7,11 +7,12 @@ import { isToonable, resultToToon, MCP_SERVER_NAME } from '@reticlehq/core';
|
|
|
7
7
|
import { tableForSurface } from '../tools/tools.js';
|
|
8
8
|
import { filterTools, describeToolSurface, TOOL_SURFACE, toolAnnotations, } from '../tools/tool-surface.js';
|
|
9
9
|
import { ReticleTool } from '@reticlehq/core';
|
|
10
|
-
import { sharedParamShort } from './shared-params.js';
|
|
10
|
+
import { refusedKeyRedirect, sharedParamShort } from './shared-params.js';
|
|
11
11
|
import { buildDynamicTools, descriptionOf } from '../tools/dynamic-tools.js';
|
|
12
12
|
import { runTool } from '../tools/invoke-tool.js';
|
|
13
13
|
import { sessionEnvelopeShape, newSnapshotCache } from '../tools/tool-kit.js';
|
|
14
14
|
import { buildErrorPayload, codedRefusalOf } from '../tools/error-recovery.js';
|
|
15
|
+
import { withRepeatHint } from '../tools/repeat-hint.js';
|
|
15
16
|
import { connectionSkew, takeVersionSkewOnto } from '../../command/version/version-nudge.js';
|
|
16
17
|
import { resultIsError } from './faults/mcp-is-error.js';
|
|
17
18
|
import { consumerVerdictRefusal, reservedVerdictKeysIn } from './consumer-verdict-guard.js';
|
|
@@ -131,7 +132,7 @@ const PREDICATE_FIELD_GRAMMAR_HINT = ' Bug-catching options: net.count (exact re
|
|
|
131
132
|
'compare (page text vs server answer, no expected value: { left:{from:"text",scope}, ' +
|
|
132
133
|
'right:{from:"net",urlContains,path}, as:"number" }), ' +
|
|
133
134
|
'console.absent:true (action completed with a CLEAN ' +
|
|
134
|
-
'console), absent:true on element/text (
|
|
135
|
+
'console), absent:true on element/text (gone from the DOM; add visible:true for "not shown"). Call reticle_tools for the full field ' +
|
|
135
136
|
'grammar of a kind.';
|
|
136
137
|
const COMPACT_PREDICATE_DESCRIPTION = `${PREDICATE_KINDS}${PREDICATE_FIELD_GRAMMAR_HINT}`;
|
|
137
138
|
/**
|
|
@@ -149,8 +150,9 @@ function leanZodShape(shape, advertised, predicateAnchor) {
|
|
|
149
150
|
let hintSpent = predicateAnchor !== undefined;
|
|
150
151
|
for (const [key, schema] of Object.entries(shape)) {
|
|
151
152
|
if (isPredicateParam(schema)) {
|
|
152
|
-
// Every tool keeps the kinds; only the navigation hint is anchored.
|
|
153
|
-
|
|
153
|
+
// Every tool keeps the kinds; only the navigation hint is anchored. A bare string is visible
|
|
154
|
+
// text (core's `PredicateSchema`), so the SDK must let it through to that parse.
|
|
155
|
+
const compact = z.union([z.string(), z.record(z.string(), z.unknown())]);
|
|
154
156
|
out[key] = (schema.isOptional() ? compact.optional() : compact).describe(hintSpent ? PREDICATE_KINDS : COMPACT_PREDICATE_DESCRIPTION);
|
|
155
157
|
hintSpent = true;
|
|
156
158
|
continue;
|
|
@@ -365,6 +367,7 @@ export function installFriendlyArgErrors(server, examples, allowedKeys = new Map
|
|
|
365
367
|
const declared = [...(allowedKeys.get(toolName) ?? [])].join(', ');
|
|
366
368
|
throw new McpError(ErrorCode.InvalidParams, `Unknown ${1 === unknown.length ? 'parameter' : 'parameters'} for ${toolName}: ${unknown.join(', ')}. ` +
|
|
367
369
|
`They were NOT applied — a result computed without them would look like an answer. ` +
|
|
370
|
+
refusedKeyRedirect(toolName, unknown) +
|
|
368
371
|
(0 === declared.length ? '' : `${toolName} declares: ${declared}. `) +
|
|
369
372
|
(example === undefined
|
|
370
373
|
? `Call reticle_tools { names: ["${toolName}"] } for its parameters.`
|
|
@@ -769,7 +772,7 @@ tools = tableForSurface(profile)) {
|
|
|
769
772
|
content: [
|
|
770
773
|
{
|
|
771
774
|
type: 'text',
|
|
772
|
-
text: JSON.stringify(liveCallValues(takeVersionSkewOnto(buildErrorPayload(message, codedRefusalOf(error)), deps.peerSkew), advertisedNames)),
|
|
775
|
+
text: JSON.stringify(liveCallValues(takeVersionSkewOnto(withRepeatHint(buildErrorPayload(message, codedRefusalOf(error)), error), deps.peerSkew), advertisedNames)),
|
|
773
776
|
},
|
|
774
777
|
],
|
|
775
778
|
};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/** The `AgentClient` values of every agent that has connected. Empty on a missing or broken file. */
|
|
2
|
+
export declare function connectedAgentClients(stateDir: string): ReadonlySet<string>;
|
|
3
|
+
/** Record that `client` (an `AgentClient` value) connected. Written once per client. */
|
|
4
|
+
export declare function rememberAgentConnected(stateDir: string, client: string): void;
|
|
5
|
+
/** `clientInfo.name` of an MCP `initialize` request line, or undefined for any other line. */
|
|
6
|
+
export declare function initializeClientName(line: string): string | undefined;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Which coding agents have connected to Reticle on this machine, by name.
|
|
3
|
+
*
|
|
4
|
+
* `attach-memory.ts` records that SOME client attached on a port. It cannot say which one, so with
|
|
5
|
+
* two agents a healthy one hides a broken one. This record keeps the client that the MCP
|
|
6
|
+
* `initialize` handshake names, as its closed `AgentClient` value. It is machine wide, because the
|
|
7
|
+
* installer runs before there is a project and therefore before there is a port.
|
|
8
|
+
*
|
|
9
|
+
* The proxy writes it when the request arrives. It records a fact that happened, never an inference
|
|
10
|
+
* from a config file. Best-effort in both directions: a hint never breaks the client path.
|
|
11
|
+
*/
|
|
12
|
+
import { mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
13
|
+
import { join } from 'node:path';
|
|
14
|
+
const RECORD_FILE = 'agents-connected.json';
|
|
15
|
+
const INITIALIZE_METHOD = 'initialize';
|
|
16
|
+
/** The `AgentClient` values of every agent that has connected. Empty on a missing or broken file. */
|
|
17
|
+
export function connectedAgentClients(stateDir) {
|
|
18
|
+
try {
|
|
19
|
+
const parsed = JSON.parse(readFileSync(join(stateDir, RECORD_FILE), 'utf8'));
|
|
20
|
+
return new Set(Array.isArray(parsed) ? parsed.filter((v) => 'string' === typeof v) : []);
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
return new Set();
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
/** Record that `client` (an `AgentClient` value) connected. Written once per client. */
|
|
27
|
+
export function rememberAgentConnected(stateDir, client) {
|
|
28
|
+
const known = connectedAgentClients(stateDir);
|
|
29
|
+
if (known.has(client)) {
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
try {
|
|
33
|
+
mkdirSync(stateDir, { recursive: true });
|
|
34
|
+
writeFileSync(join(stateDir, RECORD_FILE), JSON.stringify([...known, client]), 'utf8');
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
// An unwritable state home is reported elsewhere; it must not break the client path.
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
/** `clientInfo.name` of an MCP `initialize` request line, or undefined for any other line. */
|
|
41
|
+
export function initializeClientName(line) {
|
|
42
|
+
try {
|
|
43
|
+
const msg = JSON.parse(line);
|
|
44
|
+
if ('object' !== typeof msg || null === msg) {
|
|
45
|
+
return undefined;
|
|
46
|
+
}
|
|
47
|
+
const { method, params } = msg;
|
|
48
|
+
if (INITIALIZE_METHOD !== method || 'object' !== typeof params || null === params) {
|
|
49
|
+
return undefined;
|
|
50
|
+
}
|
|
51
|
+
const info = params.clientInfo;
|
|
52
|
+
const name = 'object' === typeof info && null !== info ? info.name : undefined;
|
|
53
|
+
return 'string' === typeof name && 0 < name.length ? name : undefined;
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
return undefined;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as net from 'node:net';
|
|
2
2
|
import { LOOPBACK_HOST } from '@reticlehq/core';
|
|
3
|
-
import {
|
|
3
|
+
import { presenceIsUsable, probePresence, PortPresence, } from '../../../command/daemon/binding/port-presence.js';
|
|
4
|
+
import { describePortState } from '../../../command/daemon/port-state.js';
|
|
4
5
|
import { fetchStatus } from '../../../command/daemon/binding/daemon-status-probe.js';
|
|
5
6
|
import { isAlive, readPid } from '../../../command/daemon/daemon.js';
|
|
6
7
|
const DEFAULT_DAEMON_READY_TIMEOUT_MS = 10_000;
|
|
@@ -21,6 +22,16 @@ function delay(ms) {
|
|
|
21
22
|
export function daemonPollDelayMs(attempt) {
|
|
22
23
|
return Math.min(DAEMON_POLL_INTERVAL_MS * attempt, DAEMON_POLL_MAX_INTERVAL_MS);
|
|
23
24
|
}
|
|
25
|
+
const CONNECTION_RESET = 'ECONNRESET';
|
|
26
|
+
/**
|
|
27
|
+
* A loopback connect to a port with no listener is refused at once. A timeout means a listener
|
|
28
|
+
* whose queue is full because it accepts nothing: a daemon stuck in its exit (#1937). Read as
|
|
29
|
+
* "free", that made `status` say the port was free while a process held it.
|
|
30
|
+
*
|
|
31
|
+
* Not on Windows: it retries a refused loopback connect for about two seconds, so there a timeout
|
|
32
|
+
* is also what a free port gives.
|
|
33
|
+
*/
|
|
34
|
+
const TIMEOUT_MEANS_HELD = 'win32' !== process.platform;
|
|
24
35
|
/**
|
|
25
36
|
* Returns true if something is already listening on the reticle port.
|
|
26
37
|
* Uses a plain TCP probe so we don't create a side-effectful SSE session
|
|
@@ -38,10 +49,11 @@ export function probeDaemon(port, host = LOOPBACK_HOST) {
|
|
|
38
49
|
socket.destroy();
|
|
39
50
|
resolve(true);
|
|
40
51
|
});
|
|
41
|
-
|
|
52
|
+
// A reset is an answer from a listener, not "nothing listens".
|
|
53
|
+
socket.on('error', (err) => resolve(CONNECTION_RESET === err.code));
|
|
42
54
|
socket.on('timeout', () => {
|
|
43
55
|
socket.destroy();
|
|
44
|
-
resolve(
|
|
56
|
+
resolve(TIMEOUT_MEANS_HELD);
|
|
45
57
|
});
|
|
46
58
|
socket.connect(port, host);
|
|
47
59
|
});
|
|
@@ -70,7 +82,7 @@ export async function waitForDaemon(port, probes = { tcpOpen: probeDaemon, statu
|
|
|
70
82
|
return;
|
|
71
83
|
if (false === probes.alive?.()) {
|
|
72
84
|
throw new Error(`the reticle daemon on port ${String(port)} exited before it was ready — ` +
|
|
73
|
-
|
|
85
|
+
describePortState(presence, port));
|
|
74
86
|
}
|
|
75
87
|
attempt++;
|
|
76
88
|
await delay(daemonPollDelayMs(attempt));
|
|
@@ -79,7 +91,7 @@ export async function waitForDaemon(port, probes = { tcpOpen: probeDaemon, statu
|
|
|
79
91
|
// means something is squatting the port. Reporting only the timeout sent readers hunting the
|
|
80
92
|
// wrong one.
|
|
81
93
|
throw new Error(`reticle daemon did not become ready on port ${String(port)} within ` +
|
|
82
|
-
`${String(DAEMON_READY_TIMEOUT_MS)}ms — ${
|
|
94
|
+
`${String(DAEMON_READY_TIMEOUT_MS)}ms — ${describePortState(presence, port)}`);
|
|
83
95
|
}
|
|
84
96
|
/** True while the process in the daemon pid file for `port` runs. */
|
|
85
97
|
export function daemonProcessAlive(port) {
|
|
@@ -33,3 +33,5 @@ export declare const SHARED_PARAM_GUIDANCE: string;
|
|
|
33
33
|
export declare function sharedParamShort(name: string, schema: z.ZodTypeAny): string | undefined;
|
|
34
34
|
/** Is this a parameter whose guidance now lives in the instructions block? */
|
|
35
35
|
export declare function isSharedParam(name: string): boolean;
|
|
36
|
+
/** The sentences that name the tool for each refused key, or an empty string. */
|
|
37
|
+
export declare function refusedKeyRedirect(toolName: string, refused: readonly string[]): string;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ReticleTool } from '@reticlehq/core';
|
|
1
2
|
/**
|
|
2
3
|
* Parameters that mean the same thing on every tool, documented ONCE instead of every turn.
|
|
3
4
|
*
|
|
@@ -48,3 +49,33 @@ export function sharedParamShort(name, schema) {
|
|
|
48
49
|
export function isSharedParam(name) {
|
|
49
50
|
return Object.hasOwn(SHARED_PARAM_SHORT, name);
|
|
50
51
|
}
|
|
52
|
+
/**
|
|
53
|
+
* Where to go when a tool refuses a parameter that another tool takes (#1944).
|
|
54
|
+
*
|
|
55
|
+
* An agent proved a click with `reticle_act_and_wait`, saw a request missing from the act's window,
|
|
56
|
+
* and asked for a wider window with `since`. The refusal listed what the tool declares and stopped
|
|
57
|
+
* there, so the agent did not learn that `reticle_assert` reads any window it is given. The refusal
|
|
58
|
+
* now names that tool.
|
|
59
|
+
*
|
|
60
|
+
* A lookup table, keyed by tool and then by the refused parameter. Add a row only where another
|
|
61
|
+
* tool really does what the refused parameter asked for.
|
|
62
|
+
*/
|
|
63
|
+
const REDIRECTS = {
|
|
64
|
+
[ReticleTool.ACT_AND_WAIT]: {
|
|
65
|
+
since: `${ReticleTool.ACT_AND_WAIT} always reads the window that its own action opens. To check a ` +
|
|
66
|
+
`window that starts earlier, call ${ReticleTool.ASSERT} { predicate, since } with the cursor ` +
|
|
67
|
+
'from an earlier result.',
|
|
68
|
+
},
|
|
69
|
+
};
|
|
70
|
+
/** The sentences that name the tool for each refused key, or an empty string. */
|
|
71
|
+
export function refusedKeyRedirect(toolName, refused) {
|
|
72
|
+
const forTool = REDIRECTS[toolName];
|
|
73
|
+
if (forTool === undefined) {
|
|
74
|
+
return '';
|
|
75
|
+
}
|
|
76
|
+
return refused
|
|
77
|
+
.map((key) => (Object.hasOwn(forTool, key) ? forTool[key] : undefined))
|
|
78
|
+
.filter((line) => line !== undefined)
|
|
79
|
+
.map((line) => `${line} `)
|
|
80
|
+
.join('');
|
|
81
|
+
}
|
|
@@ -10,10 +10,12 @@
|
|
|
10
10
|
* used from the two points where observation can be lost: a write rejected at dispatch, and a wait
|
|
11
11
|
* cut off mid-predicate.
|
|
12
12
|
*/
|
|
13
|
-
import { type ReticleEvent } from '@reticlehq/core';
|
|
13
|
+
import { type Drift, type ReticleEvent } from '@reticlehq/core';
|
|
14
14
|
import type { Session } from '../../../portal/session/session.js';
|
|
15
|
-
import { type SuccessorRegistry } from '../../../portal/session/session-successor.js';
|
|
15
|
+
import { type SuccessorClock, type SuccessorRegistry } from '../../../portal/session/session-successor.js';
|
|
16
16
|
import type { EvalResult } from '@reticlehq/engine/question/predicate/predicate-eval.js';
|
|
17
|
+
/** How long an act whose page navigated away waits for the lease's successor to connect. */
|
|
18
|
+
export declare const NAVIGATION_FOLLOW_GRACE_MS = 8000;
|
|
17
19
|
interface FollowSuccessor {
|
|
18
20
|
sessions: SuccessorRegistry;
|
|
19
21
|
session: Session;
|
|
@@ -24,12 +26,27 @@ interface FollowSuccessor {
|
|
|
24
26
|
predicateStarted: number;
|
|
25
27
|
/** Re-ask the declared consequence on `next`, with whatever budget is left. */
|
|
26
28
|
reevaluate: (next: Session, budgetMs: number) => Promise<EvalResult>;
|
|
29
|
+
/**
|
|
30
|
+
* Grace for the OTHER navigation shape (#2009): a FAILURE graded while the action's own form
|
|
31
|
+
* POST / link navigation was still in flight. The wait spent its budget on the document BEFORE
|
|
32
|
+
* it left, so nothing was "lost" and no successor was looked for — and the verdict then reads
|
|
33
|
+
* "still on /login" for a sign-in that worked. When set, a failed verdict waits this long for
|
|
34
|
+
* the document's successor and re-asks there; when it never connects, the verdict says the page
|
|
35
|
+
* navigated instead of leaving the failure standing. Undefined keeps the old behaviour.
|
|
36
|
+
*/
|
|
37
|
+
failedFollowGraceMs?: number;
|
|
38
|
+
/** The act's own event cursor: the window the departure evidence is read from. */
|
|
39
|
+
since?: number;
|
|
40
|
+
/** Injected so tests do not sleep; defaults to the real clock. */
|
|
41
|
+
clock?: SuccessorClock;
|
|
27
42
|
}
|
|
28
43
|
interface FollowedOutcome {
|
|
29
44
|
session: Session;
|
|
30
45
|
verdict: EvalResult;
|
|
31
46
|
/** True when the wait moved to a new document, so the caller must reset its event cursor. */
|
|
32
47
|
followed: boolean;
|
|
48
|
+
/** The re-ask ran on the caller's grace — a budget extension declared in the result (#2009). */
|
|
49
|
+
budgetExtendedMs?: number;
|
|
33
50
|
}
|
|
34
51
|
/**
|
|
35
52
|
* Follow the unique same-origin successor and re-ask there, or leave the verdict untouched.
|
|
@@ -56,8 +73,29 @@ export declare function disabledTargetNote(pass: boolean, actResult: unknown): s
|
|
|
56
73
|
* failure, whichever way the consequence went.
|
|
57
74
|
*/
|
|
58
75
|
export declare function unreachableTargetNote(actResult: unknown): string | undefined;
|
|
76
|
+
/**
|
|
77
|
+
* The drift for the first sub-step of an `ACT_SEQUENCE` result whose target no person could have
|
|
78
|
+
* clicked, or undefined. The page reports one effect for each sub-step it ran, in order. Synthetic
|
|
79
|
+
* dispatch reaches an unreachable target all the same, so a sequence is read sub-step by sub-step, as
|
|
80
|
+
* a single act is. `labelOf` names the sub-step, by its index in this result.
|
|
81
|
+
*/
|
|
82
|
+
export declare function unreachableSubStepDrift(sequenceResult: unknown, labelOf: (at: number) => string): Drift | undefined;
|
|
59
83
|
/** Why the acted target leaves the verdict undecided: no person could reach it, or it was disabled. */
|
|
60
84
|
export declare function actTargetNote(pass: boolean, actResult: unknown): string | undefined;
|
|
85
|
+
/**
|
|
86
|
+
* The cause and the one fix for a read that came back `unknown`, in place of a bare fact (#1990).
|
|
87
|
+
* A page whose SDK is behind this daemon may not serve `match` at all, so the fix is the same
|
|
88
|
+
* SDK-behind sentence the listing shows. On a current page the read ran out of the assertion's own
|
|
89
|
+
* budget, and the fix is more of it. Any reason that is not a command timeout is returned as it came.
|
|
90
|
+
*/
|
|
91
|
+
export declare function diagnoseTimeout(reason: string | undefined, session: {
|
|
92
|
+
readonly sdkVersion?: string | undefined;
|
|
93
|
+
}): string | undefined;
|
|
94
|
+
/** Why an act's verdict is `unknown`: a read that timed out, else an unreachable or disabled target. */
|
|
95
|
+
export declare const actInconclusive: (verdict: {
|
|
96
|
+
pass: boolean;
|
|
97
|
+
inconclusive?: string | undefined;
|
|
98
|
+
}, actResult: unknown, session: Session) => string | undefined;
|
|
61
99
|
/**
|
|
62
100
|
* The requests of a failed check's window, as its record carries them: method, url, status and the
|
|
63
101
|
* start of the response body (redacted in the page before it was ever sent). Dev tooling is left out.
|