@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
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Four checks for the first seconds of `init`, `connect`, `setup` and `verify`: the Node.js version,
|
|
3
|
+
* a browser to drive, `npx.cmd` on the Windows PATH, and the bridge port.
|
|
4
|
+
*
|
|
5
|
+
* Each failed check prints one line: the cause and its one fix. A passed check prints nothing. All
|
|
6
|
+
* are warnings: the command goes on, so a check that is wrong can never block a path that works.
|
|
7
|
+
* The paths that cannot go on still refuse later, in their own words (the lease preflight, the
|
|
8
|
+
* init runtime phase).
|
|
9
|
+
*
|
|
10
|
+
* `reticle doctor --fix` would repair the two that a program can repair: install the Chromium, and
|
|
11
|
+
* move init to a free port. That is a separate change.
|
|
12
|
+
*/
|
|
13
|
+
import { existsSync } from 'node:fs';
|
|
14
|
+
import { dirname, win32 } from 'node:path';
|
|
15
|
+
import { ReticleEnv } from '@reticlehq/core';
|
|
16
|
+
import { PortPresence, probePresence } from '../daemon/binding/port-presence.js';
|
|
17
|
+
import { describePortState } from '../daemon/port-state.js';
|
|
18
|
+
import { fetchStatus } from '../daemon/binding/daemon-status-probe.js';
|
|
19
|
+
import { probeDaemon } from '../../surface/mcp/mcp-proxy.js';
|
|
20
|
+
import { probeChromiumWithFallback } from '../../launch-chromium.js';
|
|
21
|
+
import { compareVersions } from '../version/version-skew.js';
|
|
22
|
+
import { SERVER_NODE_RANGE } from '../version/identity/server-version.js';
|
|
23
|
+
import { ChromiumPathProblem, configuredChromiumRefusal, } from './doctor/browser/chromium-hint.js';
|
|
24
|
+
const WARNING_PREFIX = '⚠ ';
|
|
25
|
+
const NODE_DOWNLOAD_URL = 'https://nodejs.org';
|
|
26
|
+
/** Only a plain floor (`>=20.11`) is read. Any other range is not checked. */
|
|
27
|
+
const NODE_FLOOR = /^>=\s*(\d+(?:\.\d+)*)$/;
|
|
28
|
+
const NPX_WINDOWS = 'npx.cmd';
|
|
29
|
+
const PATH_KEY = 'path';
|
|
30
|
+
const WINDOWS_PATH_SEPARATOR = ';';
|
|
31
|
+
const WINDOWS = 'win32';
|
|
32
|
+
/** The line for a Node.js older than the `engines` floor, or undefined. */
|
|
33
|
+
export function nodeTooOldLine(version, range) {
|
|
34
|
+
const floor = range === undefined ? undefined : NODE_FLOOR.exec(range.trim())?.[1];
|
|
35
|
+
if (floor === undefined) {
|
|
36
|
+
return undefined;
|
|
37
|
+
}
|
|
38
|
+
const order = compareVersions(version, floor);
|
|
39
|
+
if (order === undefined || order >= 0) {
|
|
40
|
+
return undefined;
|
|
41
|
+
}
|
|
42
|
+
return (`Reticle needs Node.js ${floor} or later, and this is Node.js ${version}. ` +
|
|
43
|
+
`Install the current Node.js LTS from ${NODE_DOWNLOAD_URL}, then run the command again.`);
|
|
44
|
+
}
|
|
45
|
+
/** The line for a machine with no browser Reticle can launch, or undefined. */
|
|
46
|
+
export function chromiumMissingLine(probe) {
|
|
47
|
+
if (probe.exists || probe.fallback !== undefined) {
|
|
48
|
+
return undefined;
|
|
49
|
+
}
|
|
50
|
+
if (true === probe.configured && probe.executablePath !== undefined) {
|
|
51
|
+
return configuredChromiumRefusal(probe.executablePath, probe.problem ?? ChromiumPathProblem.MISSING);
|
|
52
|
+
}
|
|
53
|
+
// No playwright at all is a broken install, not a blocked download. `reticle doctor` names it.
|
|
54
|
+
if (probe.executablePath === undefined) {
|
|
55
|
+
return undefined;
|
|
56
|
+
}
|
|
57
|
+
return ('No Chromium, Chrome or Edge is on this machine, so the first browser session downloads ' +
|
|
58
|
+
'Chromium (about 150 MiB). If your network blocks that download, install Google Chrome, or set ' +
|
|
59
|
+
`${ReticleEnv.CHROMIUM_PATH} to a Chromium executable.`);
|
|
60
|
+
}
|
|
61
|
+
/** The line for a Windows PATH with no `npx.cmd` on it, or undefined. */
|
|
62
|
+
export function windowsNpxLine(platform, env, nodeDir, exists) {
|
|
63
|
+
if (WINDOWS !== platform) {
|
|
64
|
+
return undefined;
|
|
65
|
+
}
|
|
66
|
+
// Windows reads environment names without letter case: `Path` and `PATH` are one variable.
|
|
67
|
+
const key = Object.keys(env).find((name) => PATH_KEY === name.toLowerCase());
|
|
68
|
+
const path = key === undefined ? '' : (env[key] ?? '');
|
|
69
|
+
const onPath = path
|
|
70
|
+
.split(WINDOWS_PATH_SEPARATOR)
|
|
71
|
+
.map((dir) => dir.trim().replace(/^"|"$/g, ''))
|
|
72
|
+
.some((dir) => dir.length > 0 && exists(win32.join(dir, NPX_WINDOWS)));
|
|
73
|
+
if (onPath) {
|
|
74
|
+
return undefined;
|
|
75
|
+
}
|
|
76
|
+
return (`${NPX_WINDOWS} is not on PATH, so your agent cannot start the Reticle MCP server with npx. ` +
|
|
77
|
+
`Add ${nodeDir} to PATH, then open a new terminal.`);
|
|
78
|
+
}
|
|
79
|
+
/** Run a probe; a probe that fails gives no line. */
|
|
80
|
+
async function quietly(probe) {
|
|
81
|
+
try {
|
|
82
|
+
return await probe();
|
|
83
|
+
}
|
|
84
|
+
catch {
|
|
85
|
+
return undefined;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
/** The warning lines, in a fixed order. Empty when every check passes. */
|
|
89
|
+
export async function firstUseWarnings(facts) {
|
|
90
|
+
const lines = [
|
|
91
|
+
nodeTooOldLine(facts.nodeVersion, facts.nodeRange),
|
|
92
|
+
windowsNpxLine(facts.platform, facts.env, facts.nodeDir, facts.exists),
|
|
93
|
+
];
|
|
94
|
+
const probe = await quietly(facts.chromium);
|
|
95
|
+
lines.push(probe === undefined ? undefined : chromiumMissingLine(probe));
|
|
96
|
+
const { port, portPresence, describePort } = facts;
|
|
97
|
+
if (port !== undefined && portPresence !== undefined && describePort !== undefined) {
|
|
98
|
+
const presence = await quietly(portPresence);
|
|
99
|
+
lines.push(PortPresence.FOREIGN === presence ? describePort(presence, port) : undefined);
|
|
100
|
+
}
|
|
101
|
+
return lines.flatMap((line) => (line === undefined ? [] : [`${WARNING_PREFIX}${line}`]));
|
|
102
|
+
}
|
|
103
|
+
/** This machine's facts. */
|
|
104
|
+
function thisMachine(port) {
|
|
105
|
+
return {
|
|
106
|
+
nodeVersion: process.versions.node,
|
|
107
|
+
nodeRange: SERVER_NODE_RANGE,
|
|
108
|
+
platform: process.platform,
|
|
109
|
+
env: process.env,
|
|
110
|
+
nodeDir: dirname(process.execPath),
|
|
111
|
+
exists: existsSync,
|
|
112
|
+
chromium: () => probeChromiumWithFallback(),
|
|
113
|
+
...(port === undefined
|
|
114
|
+
? {}
|
|
115
|
+
: {
|
|
116
|
+
port,
|
|
117
|
+
portPresence: () => probePresence(port, { tcpOpen: probeDaemon, status: fetchStatus }),
|
|
118
|
+
describePort: describePortState,
|
|
119
|
+
}),
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
/** Write the warnings for this machine to stderr. `port` adds the bridge port check. */
|
|
123
|
+
export async function writeFirstUseWarnings(port) {
|
|
124
|
+
for (const line of await firstUseWarnings(thisMachine(port))) {
|
|
125
|
+
process.stderr.write(`${line}\n`);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { type FirstVerdictPorts } from './first-verdict.js';
|
|
2
|
+
/** Bare `reticle` in an unwired folder. Returns the exit code. `stop` records an onboarding stop. */
|
|
3
|
+
export declare function cmdFirstVerdict(port: number, headed: boolean, stop: FirstVerdictPorts['stop']): Promise<number>;
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The first verdict, wired to this machine: the dev server, the daemon and the Reticle browser.
|
|
3
|
+
* Every decision is in `first-verdict.ts`; this file only gathers facts and runs effects.
|
|
4
|
+
*/
|
|
5
|
+
import { join } from 'node:path';
|
|
6
|
+
import { EventType, PredicateKind, QueryBy, ReticleTool, SnapshotMode, asRecord, } from '@reticlehq/core';
|
|
7
|
+
import { OnboardingStop } from '@reticlehq/core/telemetry';
|
|
8
|
+
import { RETICLE_VERIFY_DEFAULT_PORT } from '../../index.js';
|
|
9
|
+
import { DEV_SERVER_PORTS } from './ports/resolve/cli-port.js';
|
|
10
|
+
import { WELL_KNOWN_RETICLE_PORTS } from './ports/sibling-ports.js';
|
|
11
|
+
import { probeDevServerStates } from '../../portal/session/dev-server/dev-server-probe.js';
|
|
12
|
+
import { detectDevCommandInProject, } from '../../portal/session/dev-server/dev-command.js';
|
|
13
|
+
import { probePage } from '../setup/node-effects.js';
|
|
14
|
+
import { startDevServerAndWait } from '../setup/start-dev-server.js';
|
|
15
|
+
import { defaultPairingTokenDir, readOrCreatePairingTokenSync, } from '../../portal/bridge/pairing-token.js';
|
|
16
|
+
import { acquireLease, connectOverSse, endpointFor, releaseLease, verdictOf, } from './adhoc-verdict.js';
|
|
17
|
+
import { ensureTryDaemon } from './try-command.js';
|
|
18
|
+
import { writeFirstUseWarnings } from './first-use-checks.js';
|
|
19
|
+
import { AppChoice, MSG_NO_APP, chooseApp, linksToOpen, pageFactsOf, runFirstVerdict, } from './first-verdict.js';
|
|
20
|
+
/** How long a dev server this command started gets to serve its first page. */
|
|
21
|
+
const DEV_START_BUDGET_MS = 120_000;
|
|
22
|
+
/** How long a page gets to come back after a navigation, and to go quiet after it. */
|
|
23
|
+
const PAGE_ARRIVAL_MS = 15_000;
|
|
24
|
+
const PAGE_SETTLE_MS = 5_000;
|
|
25
|
+
const CALL_SLACK_MS = 5_000;
|
|
26
|
+
/** The most events read for one page, and the most links read off the start page. */
|
|
27
|
+
const EVENTS_READ = 500;
|
|
28
|
+
const LINKS_READ = 100;
|
|
29
|
+
const HREF = 'href';
|
|
30
|
+
/** The tool-call fields that carry each answer, for `verdictOf`. */
|
|
31
|
+
const NAV_FIELD = 'ok';
|
|
32
|
+
const EVENTS_FIELD = 'events';
|
|
33
|
+
const ELEMENTS_FIELD = 'elements';
|
|
34
|
+
const STATUS_FIELD = 'status';
|
|
35
|
+
/** `reticle_look` answers the find and the page read that the merged surface no longer names alone. */
|
|
36
|
+
const LOOK_FIND = 'find';
|
|
37
|
+
const LOOK_PAGE = 'page';
|
|
38
|
+
/** The bridge, the bench daemon and the verify endpoint. None of them is an app. */
|
|
39
|
+
const RETICLE_PORTS = new Set([
|
|
40
|
+
...WELL_KNOWN_RETICLE_PORTS,
|
|
41
|
+
RETICLE_VERIFY_DEFAULT_PORT,
|
|
42
|
+
]);
|
|
43
|
+
/** Only these events decide the smoke check. */
|
|
44
|
+
const SMOKE_EVENTS = [EventType.NET_REQUEST, EventType.CONSOLE_ERROR, EventType.ERROR_UNCAUGHT];
|
|
45
|
+
/** Start the folder's dev command and wait until it serves a page, or say why it did not. */
|
|
46
|
+
async function startDevServer(command, cwd) {
|
|
47
|
+
const dir = command.directory === undefined ? cwd : join(cwd, command.directory);
|
|
48
|
+
process.stdout.write(`Starting your dev server: ${command.command}\n`);
|
|
49
|
+
const started = await startDevServerAndWait(command.command, dir, DEV_START_BUDGET_MS);
|
|
50
|
+
return 'failed' in started
|
|
51
|
+
? { lines: [started.failed], stop: OnboardingStop.DEV_SERVER_FAILED }
|
|
52
|
+
: { url: started.url, release: started.stop };
|
|
53
|
+
}
|
|
54
|
+
/** The app in `cwd`, or the one dev server that runs, started when it has to be. */
|
|
55
|
+
async function findApp(cwd) {
|
|
56
|
+
const devCommand = detectDevCommandInProject(cwd);
|
|
57
|
+
const pinned = devCommand?.port;
|
|
58
|
+
const pinnedServing = pinned !== undefined && (await probePage(`http://localhost:${String(pinned)}`)).served;
|
|
59
|
+
// Only outside an app folder: in one, another server is never the app to check.
|
|
60
|
+
const running = devCommand === undefined
|
|
61
|
+
? (await probeDevServerStates([...DEV_SERVER_PORTS].filter((p) => !RETICLE_PORTS.has(p))))
|
|
62
|
+
.serving
|
|
63
|
+
: [];
|
|
64
|
+
const choice = chooseApp({
|
|
65
|
+
...(devCommand === undefined ? {} : { devCommand }),
|
|
66
|
+
pinnedServing,
|
|
67
|
+
running,
|
|
68
|
+
});
|
|
69
|
+
if (AppChoice.USE === choice.action) {
|
|
70
|
+
return { url: choice.url };
|
|
71
|
+
}
|
|
72
|
+
if (AppChoice.NONE === choice.action) {
|
|
73
|
+
return choice;
|
|
74
|
+
}
|
|
75
|
+
// `chooseApp` starts a server only for a folder with a dev command.
|
|
76
|
+
return devCommand === undefined
|
|
77
|
+
? { lines: MSG_NO_APP, stop: OnboardingStop.NO_WEB_APP }
|
|
78
|
+
: startDevServer(devCommand, cwd);
|
|
79
|
+
}
|
|
80
|
+
/** One call through `reticle_run`, the route every tool profile has. */
|
|
81
|
+
function run(caller, tool, args, timeoutMs) {
|
|
82
|
+
return caller.call(ReticleTool.RUN, { tool, args }, timeoutMs);
|
|
83
|
+
}
|
|
84
|
+
/** Wait for the page to go quiet, then read what its document did. */
|
|
85
|
+
async function readPage(caller, sessionId, url, nav) {
|
|
86
|
+
// A page that never goes quiet is still judged on what it did: the wait only bounds the read.
|
|
87
|
+
await run(caller, ReticleTool.WAIT_FOR, { predicate: { kind: PredicateKind.SETTLED }, timeout_ms: PAGE_SETTLE_MS, sessionId }, PAGE_SETTLE_MS + CALL_SLACK_MS).catch(() => undefined);
|
|
88
|
+
const observed = verdictOf(await run(caller, ReticleTool.OBSERVE, {
|
|
89
|
+
sessionId,
|
|
90
|
+
since: 0,
|
|
91
|
+
filters: SMOKE_EVENTS,
|
|
92
|
+
max_events: EVENTS_READ,
|
|
93
|
+
}), EVENTS_FIELD);
|
|
94
|
+
const events = observed?.[EVENTS_FIELD];
|
|
95
|
+
return pageFactsOf(url, Array.isArray(events) ? events : [], nav);
|
|
96
|
+
}
|
|
97
|
+
/** Go to `url` (or reload), and say whether the page came back and where. */
|
|
98
|
+
async function go(caller, sessionId, url) {
|
|
99
|
+
const args = url === undefined
|
|
100
|
+
? { reload: true, timeout_ms: PAGE_ARRIVAL_MS, sessionId }
|
|
101
|
+
: { url, timeout_ms: PAGE_ARRIVAL_MS, sessionId };
|
|
102
|
+
const result = asRecord(verdictOf(await caller.call(ReticleTool.NAVIGATE, args, PAGE_ARRIVAL_MS + CALL_SLACK_MS), NAV_FIELD));
|
|
103
|
+
const landedOn = result['landedOn'];
|
|
104
|
+
const next = result['sessionId'];
|
|
105
|
+
return {
|
|
106
|
+
arrived: true === result['confirmed'],
|
|
107
|
+
...('string' === typeof landedOn ? { landedOn } : {}),
|
|
108
|
+
sessionId: 'string' === typeof next ? next : sessionId,
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
/** The path of the page on screen, from the page's own status. */
|
|
112
|
+
async function currentPath(caller, sessionId) {
|
|
113
|
+
const answer = verdictOf(await run(caller, ReticleTool.LOOK, {
|
|
114
|
+
action: LOOK_PAGE,
|
|
115
|
+
mode: SnapshotMode.STATUS,
|
|
116
|
+
sessionId,
|
|
117
|
+
}).catch(() => undefined), STATUS_FIELD);
|
|
118
|
+
const route = asRecord(answer?.[STATUS_FIELD])['route'];
|
|
119
|
+
return 'string' === typeof route ? route : undefined;
|
|
120
|
+
}
|
|
121
|
+
/** The smoke check, through the daemon on `port`, in a Reticle browser with the zero-install reader. */
|
|
122
|
+
async function smokeThroughDaemon(port, url, headed) {
|
|
123
|
+
const unavailable = await ensureTryDaemon(port);
|
|
124
|
+
if (unavailable !== undefined) {
|
|
125
|
+
return { failed: [unavailable] };
|
|
126
|
+
}
|
|
127
|
+
const caller = await connectOverSse(endpointFor(port, readOrCreatePairingTokenSync(defaultPairingTokenDir())));
|
|
128
|
+
try {
|
|
129
|
+
const opened = await acquireLease(caller, url, headed);
|
|
130
|
+
if ('failed' in opened) {
|
|
131
|
+
return opened;
|
|
132
|
+
}
|
|
133
|
+
try {
|
|
134
|
+
// Reload once: the reader then runs from the start of the document, so it sees what the
|
|
135
|
+
// first load did (a console error during start-up) and not only what came after.
|
|
136
|
+
const back = await go(caller, opened.leased, undefined);
|
|
137
|
+
const path = await currentPath(caller, back.sessionId);
|
|
138
|
+
// The path only: the lease puts its own parameters on the url, and the page is not a link to open.
|
|
139
|
+
const here = path === undefined ? url : new URL(new URL(path, url).pathname, url).href;
|
|
140
|
+
const startNav = {
|
|
141
|
+
arrived: back.arrived,
|
|
142
|
+
...(new URL(here).pathname === new URL(url).pathname ? {} : { landedOn: here }),
|
|
143
|
+
};
|
|
144
|
+
const start = await readPage(caller, back.sessionId, url, startNav);
|
|
145
|
+
const found = verdictOf(await run(caller, ReticleTool.LOOK, {
|
|
146
|
+
action: LOOK_FIND,
|
|
147
|
+
by: QueryBy.ROLE,
|
|
148
|
+
value: 'link',
|
|
149
|
+
attrs: [HREF],
|
|
150
|
+
limit: LINKS_READ,
|
|
151
|
+
sessionId: back.sessionId,
|
|
152
|
+
}), ELEMENTS_FIELD);
|
|
153
|
+
const elements = Array.isArray(found?.[ELEMENTS_FIELD]) ? found[ELEMENTS_FIELD] : [];
|
|
154
|
+
const links = elements.flatMap((item) => {
|
|
155
|
+
const element = asRecord(item);
|
|
156
|
+
const href = asRecord(element['attrs'])[HREF];
|
|
157
|
+
const name = element['name'];
|
|
158
|
+
return 'string' === typeof href
|
|
159
|
+
? [{ name: 'string' === typeof name ? name : '', href }]
|
|
160
|
+
: [];
|
|
161
|
+
});
|
|
162
|
+
const picked = linksToOpen(here, links);
|
|
163
|
+
const visited = [];
|
|
164
|
+
let sessionId = back.sessionId;
|
|
165
|
+
for (const target of picked.open) {
|
|
166
|
+
const nav = await go(caller, sessionId, target);
|
|
167
|
+
sessionId = nav.sessionId;
|
|
168
|
+
visited.push(await readPage(caller, sessionId, target, nav));
|
|
169
|
+
}
|
|
170
|
+
return { start, links: visited, linksFound: picked.found };
|
|
171
|
+
}
|
|
172
|
+
finally {
|
|
173
|
+
await releaseLease(caller, opened.leased);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
finally {
|
|
177
|
+
await caller.close().catch(() => undefined);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
/** Bare `reticle` in an unwired folder. Returns the exit code. `stop` records an onboarding stop. */
|
|
181
|
+
export async function cmdFirstVerdict(port, headed, stop) {
|
|
182
|
+
await writeFirstUseWarnings();
|
|
183
|
+
return runFirstVerdict({
|
|
184
|
+
findApp: () => findApp(process.cwd()),
|
|
185
|
+
smoke: (url) => smokeThroughDaemon(port, url, headed),
|
|
186
|
+
out: (line) => process.stdout.write(`${line}\n`),
|
|
187
|
+
stop,
|
|
188
|
+
});
|
|
189
|
+
}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bare `reticle` in a folder that Reticle has not wired: the first verdict, with no agent, no
|
|
3
|
+
* `init` and no model.
|
|
4
|
+
*
|
|
5
|
+
* It finds the app (the folder's own dev server, or the one dev server that runs on this computer),
|
|
6
|
+
* starts the dev server when it does not run, opens the page in a Reticle browser with the
|
|
7
|
+
* zero-install reader, and runs a smoke check that cannot guess: the page loads, no console error,
|
|
8
|
+
* no failed request, and each same-origin link opens. Then it prints the verdict and the next step.
|
|
9
|
+
*
|
|
10
|
+
* The decisions are here, behind `FirstVerdictPorts`, so each one is a unit test. The browser, the
|
|
11
|
+
* daemon and the dev server are in `first-verdict-node.ts`.
|
|
12
|
+
*/
|
|
13
|
+
import { type ReticleEvent } from '@reticlehq/core';
|
|
14
|
+
import { OnboardingStop } from '@reticlehq/core/telemetry';
|
|
15
|
+
/** Bare `reticle` runs the first verdict only with no arguments, in a folder with no Reticle config. */
|
|
16
|
+
export declare function bareRunsFirstVerdict(argv: readonly string[], wired: boolean): boolean;
|
|
17
|
+
export declare const AppChoice: {
|
|
18
|
+
/** Check this url. */
|
|
19
|
+
readonly USE: "use";
|
|
20
|
+
/** Start the folder's dev command, then check what it serves. */
|
|
21
|
+
readonly START: "start";
|
|
22
|
+
/** Nothing to check: say why. */
|
|
23
|
+
readonly NONE: "none";
|
|
24
|
+
};
|
|
25
|
+
export type AppDecision = {
|
|
26
|
+
action: typeof AppChoice.USE;
|
|
27
|
+
url: string;
|
|
28
|
+
} | {
|
|
29
|
+
action: typeof AppChoice.START;
|
|
30
|
+
} | {
|
|
31
|
+
action: typeof AppChoice.NONE;
|
|
32
|
+
lines: string[];
|
|
33
|
+
stop: OnboardingStop;
|
|
34
|
+
};
|
|
35
|
+
export declare const MSG_NO_APP: string[];
|
|
36
|
+
/**
|
|
37
|
+
* Which app to check. In an app folder, only that app: a server on another port can be another
|
|
38
|
+
* app, and a verdict on the wrong app is worse than none. Outside one, the one server that runs.
|
|
39
|
+
*/
|
|
40
|
+
export declare function chooseApp(facts: {
|
|
41
|
+
/** The folder's dev command, when the folder holds a web app. */
|
|
42
|
+
devCommand?: {
|
|
43
|
+
port?: number;
|
|
44
|
+
};
|
|
45
|
+
/** The dev command pins a port, and that port serves a page now. */
|
|
46
|
+
pinnedServing: boolean;
|
|
47
|
+
/** Dev-server ports that serve a page now, outside Reticle's own. */
|
|
48
|
+
running: readonly number[];
|
|
49
|
+
}): AppDecision;
|
|
50
|
+
/** What one page did, read from its own document's events. */
|
|
51
|
+
export interface PageFacts {
|
|
52
|
+
/** The url the check opened. */
|
|
53
|
+
url: string;
|
|
54
|
+
/** The page came back with Reticle connected, at the url asked for. */
|
|
55
|
+
arrived: boolean;
|
|
56
|
+
/** Where the page went instead, when it went somewhere else. */
|
|
57
|
+
landedOn?: string;
|
|
58
|
+
/** The HTTP status of the document, when the browser reported one. */
|
|
59
|
+
documentStatus?: number;
|
|
60
|
+
consoleErrors: string[];
|
|
61
|
+
failedRequests: string[];
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* The facts of the page now on screen. Events of an earlier document are left out: the check
|
|
65
|
+
* reloads each page, and what the old document did is not this page's fault.
|
|
66
|
+
*/
|
|
67
|
+
export declare function pageFactsOf(url: string, events: readonly ReticleEvent[], nav: {
|
|
68
|
+
arrived: boolean;
|
|
69
|
+
landedOn?: string;
|
|
70
|
+
}): PageFacts;
|
|
71
|
+
/** The most links one check opens. Each one is a page load. */
|
|
72
|
+
export declare const MAX_LINKS_OPENED = 8;
|
|
73
|
+
/**
|
|
74
|
+
* The same-origin pages the links on `pageUrl` lead to, once each, without the page itself and
|
|
75
|
+
* without a link that ends the session. `found` counts them all, so a capped list says so.
|
|
76
|
+
*/
|
|
77
|
+
export declare function linksToOpen(pageUrl: string, links: readonly {
|
|
78
|
+
name: string;
|
|
79
|
+
href: string;
|
|
80
|
+
}[], max?: number): {
|
|
81
|
+
open: string[];
|
|
82
|
+
found: number;
|
|
83
|
+
};
|
|
84
|
+
/** What the smoke check saw: the start page, and each link it opened. */
|
|
85
|
+
export interface SmokeFacts {
|
|
86
|
+
start: PageFacts;
|
|
87
|
+
links: PageFacts[];
|
|
88
|
+
/** Same-origin links found on the start page. More than `links` when the check opened fewer. */
|
|
89
|
+
linksFound: number;
|
|
90
|
+
}
|
|
91
|
+
export interface SmokeVerdict {
|
|
92
|
+
verified: 'yes' | 'no';
|
|
93
|
+
lines: string[];
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* The verdict. "yes" only when the start page loaded with no console error and no failed request,
|
|
97
|
+
* and every link it opened did the same. A page that sends a visitor to sign in is a verdict too:
|
|
98
|
+
* the check is "yes" up to there, and it says what it could not reach.
|
|
99
|
+
*/
|
|
100
|
+
export declare function judgeSmoke(facts: SmokeFacts): SmokeVerdict;
|
|
101
|
+
/** The app to check, or why there is none. `release` stops a dev server this run started. */
|
|
102
|
+
export type FoundApp = {
|
|
103
|
+
url: string;
|
|
104
|
+
release?: () => void;
|
|
105
|
+
} | {
|
|
106
|
+
lines: string[];
|
|
107
|
+
stop: OnboardingStop;
|
|
108
|
+
};
|
|
109
|
+
export interface FirstVerdictPorts {
|
|
110
|
+
findApp: () => Promise<FoundApp>;
|
|
111
|
+
/** Open the page with the zero-install reader and collect the facts, or say why it could not. */
|
|
112
|
+
smoke: (url: string) => Promise<SmokeFacts | {
|
|
113
|
+
failed: string[];
|
|
114
|
+
}>;
|
|
115
|
+
out: (line: string) => void;
|
|
116
|
+
/** Record one onboarding stop. */
|
|
117
|
+
stop: (row: {
|
|
118
|
+
step: string;
|
|
119
|
+
stop: OnboardingStop;
|
|
120
|
+
}) => void;
|
|
121
|
+
}
|
|
122
|
+
export declare const MSG_NEXT_STEP: string[];
|
|
123
|
+
/** Find the app, check it, print the verdict. Returns the exit code: 0 only for "verified: yes". */
|
|
124
|
+
export declare function runFirstVerdict(ports: FirstVerdictPorts): Promise<number>;
|
|
125
|
+
/** The `reason` on a stop this command records, so a reader can tell it from an `init` stop. */
|
|
126
|
+
export declare const FIRST_VERDICT_REASON = "first_verdict";
|