@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
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as z from 'zod';
|
|
2
|
+
import { asRecord, ElementState, NearestTargetSchema } from '@reticlehq/core';
|
|
2
3
|
/**
|
|
3
4
|
* Roles that usually name the control an agent meant, ahead of a wrapping `generic` that
|
|
4
5
|
* happened to inherit the same accessible name (header CTA vs empty-state CTA).
|
|
@@ -17,8 +18,9 @@ const ROLE_RANK = {
|
|
|
17
18
|
searchbox: 10,
|
|
18
19
|
};
|
|
19
20
|
function roleRank(role) {
|
|
20
|
-
if ('string' !== typeof role)
|
|
21
|
+
if ('string' !== typeof role) {
|
|
21
22
|
return 100;
|
|
23
|
+
}
|
|
22
24
|
return ROLE_RANK[role] ?? 50;
|
|
23
25
|
}
|
|
24
26
|
function statesOf(c) {
|
|
@@ -35,8 +37,9 @@ function inViewport(c) {
|
|
|
35
37
|
*/
|
|
36
38
|
function compareCandidates(a, b) {
|
|
37
39
|
const viewport = Number(inViewport(b)) - Number(inViewport(a));
|
|
38
|
-
if (0 !== viewport)
|
|
40
|
+
if (0 !== viewport) {
|
|
39
41
|
return viewport;
|
|
42
|
+
}
|
|
40
43
|
return roleRank(a.role) - roleRank(b.role);
|
|
41
44
|
}
|
|
42
45
|
/**
|
|
@@ -50,14 +53,18 @@ function formatCandidate(c, anyInViewport) {
|
|
|
50
53
|
const ref = 'string' === typeof c.ref ? c.ref : '?';
|
|
51
54
|
const visible = false !== c.visible;
|
|
52
55
|
let where;
|
|
53
|
-
if (!visible)
|
|
56
|
+
if (!visible) {
|
|
54
57
|
where = 'hidden';
|
|
55
|
-
|
|
58
|
+
}
|
|
59
|
+
else if (inViewport(c)) {
|
|
56
60
|
where = 'in-viewport';
|
|
57
|
-
|
|
61
|
+
}
|
|
62
|
+
else if (anyInViewport) {
|
|
58
63
|
where = 'off-screen';
|
|
59
|
-
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
60
66
|
where = 'visible';
|
|
67
|
+
}
|
|
61
68
|
const head = name.length > 0 ? `${ref} (${role} "${name}"` : `${ref} (${role}`;
|
|
62
69
|
return `${head}; ${where})`;
|
|
63
70
|
}
|
|
@@ -76,6 +83,42 @@ function nearNamesClause(hint) {
|
|
|
76
83
|
'Use that name, or — when the name carries a part that changes, like a time — target it by ' +
|
|
77
84
|
'`testid` or by `text` (a contained match).');
|
|
78
85
|
}
|
|
86
|
+
/**
|
|
87
|
+
* What a result says when every match was hidden and the action used the hidden one. It does not
|
|
88
|
+
* say that a person could not reach it: a hidden input with a visible label is reached through the
|
|
89
|
+
* label, and the reach check after the action decides that.
|
|
90
|
+
*/
|
|
91
|
+
export function hiddenTargetNote(ref) {
|
|
92
|
+
return (`every element that matched the target is hidden, so the action used the hidden match ${ref}. ` +
|
|
93
|
+
'If a person reaches it through a visible label, this is correct. If not, target the control ' +
|
|
94
|
+
'a person can see.');
|
|
95
|
+
}
|
|
96
|
+
/** The `hiddenTarget` field for a tool result, or nothing when the action used a visible match. */
|
|
97
|
+
export function hiddenTargetField(resolution) {
|
|
98
|
+
if ('ref' !== resolution.kind || resolution.hiddenTarget === undefined) {
|
|
99
|
+
return {};
|
|
100
|
+
}
|
|
101
|
+
return { hiddenTarget: resolution.hiddenTarget };
|
|
102
|
+
}
|
|
103
|
+
const NearestTargetsSchema = z.array(NearestTargetSchema).min(1);
|
|
104
|
+
/** The words before the nearest-target list in a no_match refusal. The repeat hint reads after it. */
|
|
105
|
+
export const NEAREST_TARGETS_LEAD = ' The nearest targets on the page, most similar first: ';
|
|
106
|
+
/**
|
|
107
|
+
* The browser's `nearest` hint as a sentence: the targets most like the one asked for, with refs,
|
|
108
|
+
* so the retry is one call and not a snapshot loop. Empty when there is no list. It is advice
|
|
109
|
+
* only: the action stays refused, and nothing here picks a target.
|
|
110
|
+
*/
|
|
111
|
+
function nearestClause(hint) {
|
|
112
|
+
const parsed = NearestTargetsSchema.safeParse(asRecord(hint)['nearest']);
|
|
113
|
+
if (!parsed.success) {
|
|
114
|
+
return '';
|
|
115
|
+
}
|
|
116
|
+
const listed = parsed.data
|
|
117
|
+
.map((t) => `${t.ref} (${t.role} "${t.name}${true === t.nameTruncated ? '…' : ''}")`)
|
|
118
|
+
.join(', ');
|
|
119
|
+
return (`${NEAREST_TARGETS_LEAD}${listed}. If one of them is the ` +
|
|
120
|
+
'element you meant, pass its ref as `ref`.');
|
|
121
|
+
}
|
|
79
122
|
/**
|
|
80
123
|
* Turn a target QUERY into the single ref an action can be performed on.
|
|
81
124
|
*
|
|
@@ -91,7 +134,9 @@ function nearNamesClause(hint) {
|
|
|
91
134
|
*
|
|
92
135
|
* Invisible matches are filtered before counting: a hidden duplicate is a common way for a
|
|
93
136
|
* legitimately unambiguous query to look ambiguous, and refusing on it would push callers back to
|
|
94
|
-
* the two-turn path for no gain.
|
|
137
|
+
* the two-turn path for no gain. When every match is hidden, the one hidden match is used and the
|
|
138
|
+
* resolution names it in `hiddenTarget`. It is not refused: a hidden input is often clicked through
|
|
139
|
+
* its visible label.
|
|
95
140
|
*
|
|
96
141
|
* When several remain, they are ranked (in-viewport, then role) inside the refusal only — so the
|
|
97
142
|
* agent can pass the top ref on the next turn without a snapshot. Ranking is never acted on here.
|
|
@@ -104,7 +149,8 @@ export function resolveTargetRef(candidates, hint) {
|
|
|
104
149
|
return {
|
|
105
150
|
kind: 'error',
|
|
106
151
|
message: 'target matched no element. Nothing was acted on and no verdict is possible — ' +
|
|
107
|
-
nearNamesClause(hint)
|
|
152
|
+
nearNamesClause(hint) +
|
|
153
|
+
nearestClause(hint),
|
|
108
154
|
};
|
|
109
155
|
}
|
|
110
156
|
if (usable.length > 1) {
|
|
@@ -126,5 +172,9 @@ export function resolveTargetRef(candidates, hint) {
|
|
|
126
172
|
if ('string' !== typeof ref || 0 === ref.length) {
|
|
127
173
|
return { kind: 'error', message: 'target matched an element with no usable ref.' };
|
|
128
174
|
}
|
|
175
|
+
// Every match was hidden, so the action uses a hidden one. Rule 11: say so, never silently.
|
|
176
|
+
if (0 === visible.length) {
|
|
177
|
+
return { kind: 'ref', ref, hiddenTarget: hiddenTargetNote(ref) };
|
|
178
|
+
}
|
|
129
179
|
return { kind: 'ref', ref };
|
|
130
180
|
}
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
* is verified FOR THOSE THREE and silent about nine, and `because` says so — reporting it as "25%
|
|
15
15
|
* verified" would be the arithmetic that hides the nine.
|
|
16
16
|
*/
|
|
17
|
-
import { Verified } from '@reticlehq/core';
|
|
17
|
+
import { Verified, VerifiedReason } from '@reticlehq/core';
|
|
18
18
|
/**
|
|
19
19
|
* What to do when a step's declared consequence does not hold.
|
|
20
20
|
*
|
|
@@ -46,9 +46,21 @@ export interface StepExpectation {
|
|
|
46
46
|
* step is undecided, never a miss — `unknown`, as act_and_wait says.
|
|
47
47
|
*/
|
|
48
48
|
undecided?: string;
|
|
49
|
+
/** The step's action (`click`, `fill`), so a plan that could not judge a step can name it. */
|
|
50
|
+
action?: string;
|
|
51
|
+
/** A real frame flushed after this step's action, as `settled` on its act result says. */
|
|
52
|
+
settled?: boolean;
|
|
53
|
+
/**
|
|
54
|
+
* Absence-derived contradiction kinds seen in this step's window (a request that never settled,
|
|
55
|
+
* for example). They do not decide a miss, but they stop a plan from claiming no channel saw a
|
|
56
|
+
* problem.
|
|
57
|
+
*/
|
|
58
|
+
doubted?: readonly string[];
|
|
49
59
|
}
|
|
50
60
|
export interface SequenceGrade {
|
|
51
61
|
verified: Verified;
|
|
62
|
+
/** The deciding clause, from core's list, so a sequence verdict is counted by reason like any other. */
|
|
63
|
+
reason: VerifiedReason;
|
|
52
64
|
/** Steps that declared a consequence. */
|
|
53
65
|
declared: number;
|
|
54
66
|
total: number;
|
|
@@ -67,6 +79,8 @@ interface SequencePlan {
|
|
|
67
79
|
readonly planned: number;
|
|
68
80
|
/** Whether anything actually reached the page. */
|
|
69
81
|
readonly dispatched: boolean;
|
|
82
|
+
/** The capture lost events inside the plan's window, so no channel saw all of it. */
|
|
83
|
+
readonly captureLost?: boolean;
|
|
70
84
|
}
|
|
71
85
|
export declare function gradeSequence(steps: readonly StepExpectation[], plan?: SequencePlan): SequenceGrade;
|
|
72
86
|
/**
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
* is verified FOR THOSE THREE and silent about nine, and `because` says so — reporting it as "25%
|
|
15
15
|
* verified" would be the arithmetic that hides the nine.
|
|
16
16
|
*/
|
|
17
|
-
import { Verified } from '@reticlehq/core';
|
|
17
|
+
import { Verified, VerifiedReason } from '@reticlehq/core';
|
|
18
18
|
/**
|
|
19
19
|
* What to do when a step's declared consequence does not hold.
|
|
20
20
|
*
|
|
@@ -23,6 +23,23 @@ import { Verified } from '@reticlehq/core';
|
|
|
23
23
|
* sweep of independent controls, where stopping at the first would hide the other thirteen.
|
|
24
24
|
*/
|
|
25
25
|
export const DeviationMode = { HALT: 'halt', CONTINUE: 'continue' };
|
|
26
|
+
/** The sentence for a plan whose steps declared nothing. */
|
|
27
|
+
function undeclaredBecause(total, dispatched) {
|
|
28
|
+
if (0 === total) {
|
|
29
|
+
return 'the plan had no steps, so nothing was driven and nothing was proved';
|
|
30
|
+
}
|
|
31
|
+
// A step refused before dispatch is a malformed call: telling its author to add an `expect`
|
|
32
|
+
// sends them to the wrong thing.
|
|
33
|
+
if (!dispatched) {
|
|
34
|
+
return `nothing was dispatched, so none of the ${String(total)} step(s) ran — read the per-step \`error\` for the one that was refused, and fix that before adding an \`expect\``;
|
|
35
|
+
}
|
|
36
|
+
return `all ${String(total)} step(s) declared nothing, so the app was driven but not verified — give each step an \`expect\` naming the consequence it causes`;
|
|
37
|
+
}
|
|
38
|
+
/** A step as a sentence names it: its number, counted from 1, and its action when it has one. */
|
|
39
|
+
function stepName(index, action) {
|
|
40
|
+
const number = `step ${String(index + 1)}`;
|
|
41
|
+
return action === undefined ? number : `${number} (${action})`;
|
|
42
|
+
}
|
|
26
43
|
export function gradeSequence(steps, plan = { planned: steps.length, dispatched: true }) {
|
|
27
44
|
const total = Math.max(plan.planned, steps.length);
|
|
28
45
|
const declaring = steps.filter((step) => step.declared);
|
|
@@ -36,6 +53,7 @@ export function gradeSequence(steps, plan = { planned: steps.length, dispatched:
|
|
|
36
53
|
const observed = missed.observed ?? 'nothing that matched';
|
|
37
54
|
return {
|
|
38
55
|
verified: Verified.NO,
|
|
56
|
+
reason: VerifiedReason.ASSERTION_FAILED,
|
|
39
57
|
declared,
|
|
40
58
|
total,
|
|
41
59
|
because: `a declared consequence did not hold — observed ${observed}`,
|
|
@@ -47,47 +65,43 @@ export function gradeSequence(steps, plan = { planned: steps.length, dispatched:
|
|
|
47
65
|
const kinds = (steps[contradictedAt]?.contradicted ?? []).join(', ');
|
|
48
66
|
return {
|
|
49
67
|
verified: Verified.NO,
|
|
68
|
+
reason: VerifiedReason.CONTRADICTED,
|
|
50
69
|
declared,
|
|
51
70
|
total,
|
|
52
71
|
because: `step ${String(contradictedAt + 1)}: channels disagree about this action (${kinds}) even though it went on`,
|
|
53
72
|
};
|
|
54
73
|
}
|
|
55
|
-
// Nothing failed that was seen: a step nobody could judge leaves the plan undecided
|
|
56
|
-
|
|
57
|
-
|
|
74
|
+
// Nothing failed that was seen: a step nobody could judge leaves the plan undecided. The sentence
|
|
75
|
+
// names the step and what was missing, so the agent knows which step to change (#2204).
|
|
76
|
+
const unjudgedAt = steps.findIndex((step) => step.undecided !== undefined);
|
|
77
|
+
if (unjudgedAt >= 0) {
|
|
78
|
+
const unjudged = steps[unjudgedAt];
|
|
58
79
|
return {
|
|
59
80
|
verified: Verified.UNKNOWN,
|
|
81
|
+
reason: VerifiedReason.INCONCLUSIVE,
|
|
60
82
|
declared,
|
|
61
83
|
total,
|
|
62
|
-
because:
|
|
84
|
+
because: `${stepName(unjudgedAt, unjudged?.action)} could not be judged: ${unjudged?.undecided ?? ''}`,
|
|
63
85
|
};
|
|
86
|
+
}
|
|
64
87
|
/*
|
|
65
|
-
*
|
|
66
|
-
*
|
|
67
|
-
*
|
|
68
|
-
*
|
|
69
|
-
*
|
|
70
|
-
* `no-fault` here would claim evidence nobody collected, in the one place this product cannot
|
|
71
|
-
* afford to overclaim.
|
|
72
|
-
*
|
|
73
|
-
* So the enum stays conservative and the SENTENCE carries the whole answer: it names declaring a
|
|
74
|
-
* consequence as the next move, which is what an agent reading `no-fault` would have done.
|
|
75
|
-
* Upgrading means plumbing `settled` from the act results through `SequencePlan`.
|
|
88
|
+
* Nothing declared is `no-fault` over a quiet plan and `unknown` otherwise. This is the rule a
|
|
89
|
+
* single action follows (`engine/src/evidence/verified.ts`): no-fault claims the whole window was
|
|
90
|
+
* observed, so every step must report a settled frame, no step may carry an absence-derived
|
|
91
|
+
* finding, and the capture must be whole. `unknown` sends an agent to look again with better
|
|
92
|
+
* coverage. When the plan was quiet, that cannot help: the fix is to declare a consequence.
|
|
76
93
|
*/
|
|
77
94
|
if (0 === declared) {
|
|
95
|
+
const quiet = plan.dispatched &&
|
|
96
|
+
true !== plan.captureLost &&
|
|
97
|
+
steps.length > 0 &&
|
|
98
|
+
steps.every((step) => true === step.settled && 0 === (step.doubted ?? []).length);
|
|
78
99
|
return {
|
|
79
|
-
verified: Verified.UNKNOWN,
|
|
100
|
+
verified: quiet ? Verified.NO_FAULT : Verified.UNKNOWN,
|
|
101
|
+
reason: VerifiedReason.NOTHING_DECLARED,
|
|
80
102
|
declared,
|
|
81
103
|
total,
|
|
82
|
-
because:
|
|
83
|
-
? 'the plan had no steps, so nothing was driven and nothing was proved'
|
|
84
|
-
: // "the app was driven" was said unconditionally, including on a call whose own
|
|
85
|
-
// `dispatched` was false in the same object. A step refused before dispatch is a
|
|
86
|
-
// malformed call, and telling its author to add an `expect` sends them at the wrong
|
|
87
|
-
// thing entirely.
|
|
88
|
-
plan.dispatched
|
|
89
|
-
? `all ${String(total)} step(s) declared nothing, so the app was driven but not verified — give each step an \`expect\` naming the consequence it causes`
|
|
90
|
-
: `nothing was dispatched, so none of the ${String(total)} step(s) ran — read the per-step \`error\` for the one that was refused, and fix that before adding an \`expect\``,
|
|
104
|
+
because: undeclaredBecause(total, plan.dispatched),
|
|
91
105
|
};
|
|
92
106
|
}
|
|
93
107
|
// A journey is proved at its END. Declaring only early steps checks that it started, and a yes
|
|
@@ -95,6 +109,7 @@ export function gradeSequence(steps, plan = { planned: steps.length, dispatched:
|
|
|
95
109
|
if (steps.length < total) {
|
|
96
110
|
return {
|
|
97
111
|
verified: Verified.UNKNOWN,
|
|
112
|
+
reason: VerifiedReason.EVIDENCE_INCOMPLETE,
|
|
98
113
|
declared,
|
|
99
114
|
total,
|
|
100
115
|
because: `only ${String(steps.length)} of ${String(total)} steps ran, so the journey never reached its end`,
|
|
@@ -103,6 +118,7 @@ export function gradeSequence(steps, plan = { planned: steps.length, dispatched:
|
|
|
103
118
|
if (true !== steps.at(-1)?.declared) {
|
|
104
119
|
return {
|
|
105
120
|
verified: Verified.UNKNOWN,
|
|
121
|
+
reason: VerifiedReason.EVIDENCE_INCOMPLETE,
|
|
106
122
|
declared,
|
|
107
123
|
total,
|
|
108
124
|
because: `the last step, where the journey ends, declared nothing — give it an \`expect\` naming the end state (${String(declared)} of ${String(total)} steps declared one)`,
|
|
@@ -110,6 +126,7 @@ export function gradeSequence(steps, plan = { planned: steps.length, dispatched:
|
|
|
110
126
|
}
|
|
111
127
|
return {
|
|
112
128
|
verified: Verified.YES,
|
|
129
|
+
reason: VerifiedReason.PROVED,
|
|
113
130
|
declared,
|
|
114
131
|
total,
|
|
115
132
|
because: declared === total
|
|
@@ -137,8 +154,9 @@ export function gradeSequence(steps, plan = { planned: steps.length, dispatched:
|
|
|
137
154
|
/** The stopped recording a proved journey is held under, so the `keep` offer can be taken. */
|
|
138
155
|
export const JOURNEY_RECORDING = 'last-journey';
|
|
139
156
|
export function offerToKeep(grade) {
|
|
140
|
-
if (grade.verified !== Verified.YES || 0 === grade.declared)
|
|
157
|
+
if (grade.verified !== Verified.YES || 0 === grade.declared) {
|
|
141
158
|
return undefined;
|
|
159
|
+
}
|
|
142
160
|
return (`this plan proved something (${String(grade.declared)} of ${String(grade.total)} steps declared a ` +
|
|
143
161
|
'consequence and every one held) — keep it as a regression flow with ' +
|
|
144
162
|
`reticle_flow_save { flowName: "${JOURNEY_RECORDING}", saveAs: "<name>" }, and the steps that declared nothing will replay ` +
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
* - still in flight when the budget genuinely runs out → `unsettled`, as before, but now an honest
|
|
28
28
|
* limit instead of an early exit.
|
|
29
29
|
*/
|
|
30
|
-
import { EventType,
|
|
30
|
+
import { EventType, isDevToolingUrl, isForeignTraffic, neverAnswered, urlForMatch, } from '@reticlehq/core';
|
|
31
31
|
/**
|
|
32
32
|
* What a URL is matched against, as opposed to what is shown.
|
|
33
33
|
*
|
|
@@ -81,10 +81,11 @@ const isForeign = (data, appOrigin, background) => isForeignTraffic(matchUrlOf(d
|
|
|
81
81
|
* NET_REQUEST, so counting it as outstanding would mean no page containing an outbound link or a
|
|
82
82
|
* download button ever settles again. See `NetInitiator.NAVIGATION`.
|
|
83
83
|
*
|
|
84
|
-
* The `settled` predicate asks the same question in `evalSettled
|
|
85
|
-
*
|
|
84
|
+
* The `settled` predicate asks the same question in `evalSettled`. Both read core's `neverAnswered`,
|
|
85
|
+
* which keeps the two answers one rule. It also covers a request whose page unloaded before its
|
|
86
|
+
* answer arrived (#1944).
|
|
86
87
|
*/
|
|
87
|
-
const isDeparture =
|
|
88
|
+
const isDeparture = neverAnswered;
|
|
88
89
|
/** How often to re-read the buffer. Short enough to return promptly, long enough not to spin. */
|
|
89
90
|
const POLL_MS = 50;
|
|
90
91
|
const idOf = (data) => 'string' === typeof data['id'] ? data['id'] : undefined;
|
|
@@ -98,21 +99,26 @@ const idOf = (data) => 'string' === typeof data['id'] ? data['id'] : undefined;
|
|
|
98
99
|
export function inFlightRequestIds(events, appOrigin, background = []) {
|
|
99
100
|
const settled = new Set();
|
|
100
101
|
for (const e of events) {
|
|
101
|
-
if (e.type !== EventType.NET_REQUEST)
|
|
102
|
+
if (e.type !== EventType.NET_REQUEST) {
|
|
102
103
|
continue;
|
|
104
|
+
}
|
|
103
105
|
const id = idOf(e.data);
|
|
104
|
-
if (id !== undefined)
|
|
106
|
+
if (id !== undefined) {
|
|
105
107
|
settled.add(id);
|
|
108
|
+
}
|
|
106
109
|
}
|
|
107
110
|
const open = [];
|
|
108
111
|
for (const e of events) {
|
|
109
|
-
if (e.type !== EventType.NET_PENDING || isDevTooling(e.data) || isDeparture(e.data))
|
|
112
|
+
if (e.type !== EventType.NET_PENDING || isDevTooling(e.data) || isDeparture(e.data)) {
|
|
110
113
|
continue;
|
|
111
|
-
|
|
114
|
+
}
|
|
115
|
+
if (isForeign(e.data, appOrigin, background)) {
|
|
112
116
|
continue;
|
|
117
|
+
}
|
|
113
118
|
const id = idOf(e.data);
|
|
114
|
-
if (id !== undefined && !settled.has(id) && !open.includes(id))
|
|
119
|
+
if (id !== undefined && !settled.has(id) && !open.includes(id)) {
|
|
115
120
|
open.push(id);
|
|
121
|
+
}
|
|
116
122
|
}
|
|
117
123
|
return open;
|
|
118
124
|
}
|
|
@@ -128,11 +134,13 @@ export function inFlightRequestLabels(events, appOrigin, background = []) {
|
|
|
128
134
|
const open = new Set(inFlightRequestIds(events, appOrigin, background));
|
|
129
135
|
const labels = [];
|
|
130
136
|
for (const e of events) {
|
|
131
|
-
if (e.type !== EventType.NET_PENDING)
|
|
137
|
+
if (e.type !== EventType.NET_PENDING) {
|
|
132
138
|
continue;
|
|
139
|
+
}
|
|
133
140
|
const id = idOf(e.data);
|
|
134
|
-
if (id === undefined || !open.has(id))
|
|
141
|
+
if (id === undefined || !open.has(id)) {
|
|
135
142
|
continue;
|
|
143
|
+
}
|
|
136
144
|
open.delete(id); // one label per request, however many times its start was recorded
|
|
137
145
|
const method = 'string' === typeof e.data['method'] ? e.data['method'] : 'request';
|
|
138
146
|
const url = 'string' === typeof e.data['url'] ? e.data['url'] : 'an unreported url';
|
|
@@ -158,8 +166,9 @@ const MIN_REPEATS = 2;
|
|
|
158
166
|
export function repeatedRequestLabels(events) {
|
|
159
167
|
const counts = new Map();
|
|
160
168
|
for (const e of events) {
|
|
161
|
-
if (e.type !== EventType.NET_REQUEST || isDevTooling(e.data))
|
|
169
|
+
if (e.type !== EventType.NET_REQUEST || isDevTooling(e.data)) {
|
|
162
170
|
continue;
|
|
171
|
+
}
|
|
163
172
|
const method = 'string' === typeof e.data['method'] ? e.data['method'] : 'request';
|
|
164
173
|
const url = 'string' === typeof e.data['url'] ? e.data['url'] : 'an unreported url';
|
|
165
174
|
const key = `${method} ${url}`;
|
|
@@ -182,17 +191,20 @@ export async function waitForInFlight(session, since, budgetMs, opts) {
|
|
|
182
191
|
// The verdict's own scope: waiting on a request the verdict will not count is latency for nothing.
|
|
183
192
|
const outstanding = () => inFlightRequestIds(session.eventsSince(since), session.url, session.background);
|
|
184
193
|
let open = outstanding();
|
|
185
|
-
if (0 === open.length)
|
|
194
|
+
if (0 === open.length) {
|
|
186
195
|
return { settled: true, stillInFlight: [] };
|
|
187
|
-
|
|
196
|
+
}
|
|
197
|
+
if (budgetMs <= 0) {
|
|
188
198
|
return { settled: false, stillInFlight: open };
|
|
199
|
+
}
|
|
189
200
|
const deadline = session.elapsed() + budgetMs;
|
|
190
201
|
while (session.elapsed() < deadline) {
|
|
191
202
|
// Never overshoot the budget: the last sleep is trimmed to whatever is actually left.
|
|
192
203
|
await opts.sleep(Math.min(POLL_MS, deadline - session.elapsed()));
|
|
193
204
|
open = outstanding();
|
|
194
|
-
if (0 === open.length)
|
|
205
|
+
if (0 === open.length) {
|
|
195
206
|
return { settled: true, stillInFlight: [] };
|
|
207
|
+
}
|
|
196
208
|
}
|
|
197
209
|
return { settled: false, stillInFlight: open };
|
|
198
210
|
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The single dispatch point for every ACT and ACT_SEQUENCE command, extracted from
|
|
3
|
+
* act-tools.ts at the 1000-line cap.
|
|
4
|
+
*
|
|
5
|
+
* Attribution: this dispatch does NOT open its own window — the CALLER wraps it in
|
|
6
|
+
* `session.beginAction` / `finishAction` with the tool it serves (act, act_and_wait, act_sequence
|
|
7
|
+
* pass their own `command`), so the window covers the whole flow around the dispatch, not just
|
|
8
|
+
* the send.
|
|
9
|
+
*/
|
|
10
|
+
import { ReticleCommand } from '@reticlehq/core';
|
|
11
|
+
import type { Session } from '../../portal/session/session.js';
|
|
12
|
+
import type { ToolDeps } from './tool-kit.js';
|
|
13
|
+
/**
|
|
14
|
+
* Single dispatch point for every ACT and ACT_SEQUENCE command.
|
|
15
|
+
*
|
|
16
|
+
* reticle_act, act_and_wait and act_sequence rewrite uploads here, once. The path resolves against
|
|
17
|
+
* the session's project, not the daemon's folder, so a worktree uploads its own fixture (#1769).
|
|
18
|
+
*
|
|
19
|
+
* captureAct is called AFTER this, so the flow-recording captures the pre-rewrite args (the path
|
|
20
|
+
* the agent actually wrote) rather than the base64 blob — replay would otherwise send 750 KiB of
|
|
21
|
+
* base64 to the browser as if it were an inline content call.
|
|
22
|
+
*/
|
|
23
|
+
export declare function actCommand(deps: ToolDeps, session: Session, command: ReticleCommand, rawActArgs: Record<string, unknown>, timeoutMs?: number, realTried?: boolean): Promise<import('@reticlehq/core').CommandResult>;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The single dispatch point for every ACT and ACT_SEQUENCE command, extracted from
|
|
3
|
+
* act-tools.ts at the 1000-line cap.
|
|
4
|
+
*
|
|
5
|
+
* Attribution: this dispatch does NOT open its own window — the CALLER wraps it in
|
|
6
|
+
* `session.beginAction` / `finishAction` with the tool it serves (act, act_and_wait, act_sequence
|
|
7
|
+
* pass their own `command`), so the window covers the whole flow around the dispatch, not just
|
|
8
|
+
* the send.
|
|
9
|
+
*/
|
|
10
|
+
import { ActionType, ReticleCommand, asRecord, asString } from '@reticlehq/core';
|
|
11
|
+
import { rewriteUploadArgs, tryRealInput, HOVER_NEEDS_POINTER_MSG } from './real-input-attempt.js';
|
|
12
|
+
import { sessionRoot } from '../../memory/project/session-root.js';
|
|
13
|
+
import { normalizeTypeSpelling } from './type-spelling.js';
|
|
14
|
+
/**
|
|
15
|
+
* Single dispatch point for every ACT and ACT_SEQUENCE command.
|
|
16
|
+
*
|
|
17
|
+
* reticle_act, act_and_wait and act_sequence rewrite uploads here, once. The path resolves against
|
|
18
|
+
* the session's project, not the daemon's folder, so a worktree uploads its own fixture (#1769).
|
|
19
|
+
*
|
|
20
|
+
* captureAct is called AFTER this, so the flow-recording captures the pre-rewrite args (the path
|
|
21
|
+
* the agent actually wrote) rather than the base64 blob — replay would otherwise send 750 KiB of
|
|
22
|
+
* base64 to the browser as if it were an inline content call.
|
|
23
|
+
*/
|
|
24
|
+
export async function actCommand(deps, session, command, rawActArgs, timeoutMs, realTried = false) {
|
|
25
|
+
const actArgs = normalizeTypeSpelling(rawActArgs);
|
|
26
|
+
const rewritten = await rewriteUploadArgs({ fs: deps.fs, reticleRoot: sessionRoot(deps, session.id) }, 'string' === typeof actArgs['action'] ? actArgs['action'] : '', asRecord(actArgs['args']));
|
|
27
|
+
// Sequence and act_and_wait dispatch through here without the ACT handler's tryRealInput.
|
|
28
|
+
// A synthetic hover reports dispatched/settled while CSS :hover never applies — drive a real
|
|
29
|
+
// pointer when one is available, otherwise refuse rather than lie. A press on a lease takes its
|
|
30
|
+
// real keyboard, as reticle_act does: a synthetic Tab moves no focus.
|
|
31
|
+
const hover = ActionType.HOVER === actArgs['action'];
|
|
32
|
+
if (!realTried && (hover || ActionType.PRESS === actArgs['action'])) {
|
|
33
|
+
const ref = asString(actArgs['ref']);
|
|
34
|
+
if (hover && ref === undefined) {
|
|
35
|
+
throw new Error(HOVER_NEEDS_POINTER_MSG);
|
|
36
|
+
}
|
|
37
|
+
const action = hover ? ActionType.HOVER : ActionType.PRESS;
|
|
38
|
+
const real = await tryRealInput(deps, session, ref ?? '', action, actArgs);
|
|
39
|
+
if (hover && real.result === undefined) {
|
|
40
|
+
throw new Error(HOVER_NEEDS_POINTER_MSG);
|
|
41
|
+
}
|
|
42
|
+
if (real.result !== undefined) {
|
|
43
|
+
const result = { dispatched: true, settled: real.settled, ...asRecord(real.result) };
|
|
44
|
+
return { kind: 'command_result', id: action, ok: true, result };
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
const bridgeArgs = { ...actArgs, args: rewritten };
|
|
48
|
+
// What the acted element shows (test id, source) is noted in `Session.command`, Harness acts too.
|
|
49
|
+
return session.command(command, bridgeArgs, timeoutMs);
|
|
50
|
+
}
|