@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,10 +1,10 @@
|
|
|
1
|
-
import { carryReticleIdentity } from './lease-tools.js';
|
|
1
|
+
import { carryReticleIdentity, LEASE_ACQUIRE_TOOL } from './lease-tools.js';
|
|
2
2
|
import { z } from 'zod';
|
|
3
3
|
import { navigateResult } from './act/navigation/navigate-result.js';
|
|
4
4
|
import { absoluteTarget, awaitArrival, idsOpenAtDispatch, ARRIVAL_TIMEOUT_MS, } from './act/navigation/navigate-arrival.js';
|
|
5
|
-
import { reloadResult } from './act/navigation/reload-result.js';
|
|
5
|
+
import { HardReload, hardReloadOf, reloadResult } from './act/navigation/reload-result.js';
|
|
6
6
|
import { waitForReconnect, RELOAD_RECONNECT_TIMEOUT_MS, } from '../../portal/session/session-reconnect.js';
|
|
7
|
-
import { ReticleCommand } from '@reticlehq/core';
|
|
7
|
+
import { NO_SESSION_CONNECTED_ERROR, ReticleCommand, SESSION_STARTED_NOTE, SessionStartedVia, relativeUrlNoSession, } from '@reticlehq/core';
|
|
8
8
|
import { ReticleTool } from '@reticlehq/core';
|
|
9
9
|
import { asNumber, asString } from '@reticlehq/core';
|
|
10
10
|
import { sessionIdShape, commandOrThrow } from './tool-kit.js';
|
|
@@ -17,8 +17,9 @@ const MSG_LEASE_WITHOUT_SDK = 'This page has no Reticle SDK, so only browser-lev
|
|
|
17
17
|
async function navigateLease(deps, sessionId, url, args) {
|
|
18
18
|
const timeoutMs = asNumber(args['timeout_ms']) ?? ARRIVAL_TIMEOUT_MS;
|
|
19
19
|
const went = (await deps.pool?.gotoLease(sessionId, url, timeoutMs)) ?? false;
|
|
20
|
-
if (!went)
|
|
20
|
+
if (!went) {
|
|
21
21
|
return { ok: false, url, reason: 'the leased page did not navigate' };
|
|
22
|
+
}
|
|
22
23
|
const back = await waitForSession(deps, sessionId, timeoutMs);
|
|
23
24
|
return back
|
|
24
25
|
? { ok: true, url, confirmed: true, sessionId }
|
|
@@ -28,19 +29,74 @@ async function navigateLease(deps, sessionId, url, args) {
|
|
|
28
29
|
async function waitForSession(deps, sessionId, timeoutMs) {
|
|
29
30
|
const start = deps.now();
|
|
30
31
|
for (;;) {
|
|
31
|
-
if (deps.sessions.get(sessionId) !== undefined)
|
|
32
|
+
if (deps.sessions.get(sessionId) !== undefined) {
|
|
32
33
|
return true;
|
|
33
|
-
|
|
34
|
+
}
|
|
35
|
+
if (deps.now() - start >= timeoutMs) {
|
|
34
36
|
return false;
|
|
37
|
+
}
|
|
35
38
|
await new Promise((resolve) => setTimeout(resolve, LEASE_POLL_MS));
|
|
36
39
|
}
|
|
37
40
|
}
|
|
38
41
|
const LEASE_POLL_MS = 100;
|
|
42
|
+
/** `sessionStarted` on the result. See `SessionStarted` in core. */
|
|
43
|
+
const SessionStartedSchema = z.object({
|
|
44
|
+
sessionId: z.string(),
|
|
45
|
+
via: z.nativeEnum(SessionStartedVia),
|
|
46
|
+
zeroInstall: z.boolean().optional(),
|
|
47
|
+
});
|
|
48
|
+
/** The origin a relative-URL refusal names when the project app cannot be found. */
|
|
49
|
+
const EXAMPLE_ORIGIN = 'http://localhost:3000';
|
|
50
|
+
function isHttpUrl(url) {
|
|
51
|
+
try {
|
|
52
|
+
const { protocol } = new URL(url);
|
|
53
|
+
return 'http:' === protocol || 'https:' === protocol;
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* No session, and an absolute URL: open a lease on it through the lease tool itself, so the same
|
|
61
|
+
* owner, browser preflight and production rules apply as on an explicit `reticle_lease` acquire.
|
|
62
|
+
*/
|
|
63
|
+
async function startSessionOn(deps, url) {
|
|
64
|
+
const leased = (await LEASE_ACQUIRE_TOOL.handler(deps, { url }));
|
|
65
|
+
const sessionStarted = {
|
|
66
|
+
sessionId: leased.sessionId,
|
|
67
|
+
via: SessionStartedVia.LEASE,
|
|
68
|
+
...(true === leased.zeroInstall ? { zeroInstall: true } : {}),
|
|
69
|
+
};
|
|
70
|
+
const note = leased.hint === undefined ? SESSION_STARTED_NOTE : `${SESSION_STARTED_NOTE} ${leased.hint}`;
|
|
71
|
+
return {
|
|
72
|
+
ok: true,
|
|
73
|
+
url,
|
|
74
|
+
confirmed: leased.ready,
|
|
75
|
+
sessionId: leased.sessionId,
|
|
76
|
+
sessionStarted,
|
|
77
|
+
note,
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* No session, and a relative URL: nothing names the app. Keep the no-session refusal (and its
|
|
82
|
+
* diagnosis), and add the absolute form of the same path.
|
|
83
|
+
*/
|
|
84
|
+
async function refuseRelativeWithoutSession(deps, path) {
|
|
85
|
+
let message = NO_SESSION_CONNECTED_ERROR;
|
|
86
|
+
try {
|
|
87
|
+
deps.sessions.resolve();
|
|
88
|
+
}
|
|
89
|
+
catch (err) {
|
|
90
|
+
message = err instanceof Error ? err.message : String(err);
|
|
91
|
+
}
|
|
92
|
+
const origin = (await deps.projectAppUrl?.().catch(() => undefined)) ?? EXAMPLE_ORIGIN;
|
|
93
|
+
throw new Error(`${message}${relativeUrlNoSession(path, origin)}`);
|
|
94
|
+
}
|
|
39
95
|
export const BROWSER_TOOLS = [
|
|
40
96
|
{
|
|
41
97
|
name: ReticleTool.NAVIGATE,
|
|
42
98
|
example: { url: '/settings' },
|
|
43
|
-
description: 'Navigate the connected browser tab to a URL, or reload it in place with { reload: true } (add { hard: true } to bypass the cache). `ok` means the navigation was DISPATCHED — the SDK is torn down by the navigation, so the old page cannot report on it. The daemon then waits up to `timeout_ms` (default 5000) for the SDK to reconnect. `confirmed:true` with a `sessionId` means the requested page arrived and you can act immediately. `confirmed:false` with `landedOn` means the navigation arrived but the app landed at another URL, such as an authentication or route-guard redirect; use `landedOn` to understand where the browser actually ended up. `confirmed:false` without `landedOn` means the target was not observed within the wait window; a slow app may still be on its way, so increase `timeout_ms` when appropriate.',
|
|
99
|
+
description: 'Navigate the connected browser tab to a URL, or reload it in place with { reload: true } (add { hard: true } to bypass the cache). `ok` means the navigation was DISPATCHED — the SDK is torn down by the navigation, so the old page cannot report on it. The daemon then waits up to `timeout_ms` (default 5000) for the SDK to reconnect. `confirmed:true` with a `sessionId` means the requested page arrived and you can act immediately. `confirmed:false` with `landedOn` means the navigation arrived but the app landed at another URL, such as an authentication or route-guard redirect; use `landedOn` to understand where the browser actually ended up. `confirmed:false` without `landedOn` means the target was not observed within the wait window; a slow app may still be on its way, so increase `timeout_ms` when appropriate. With no session connected, an absolute URL opens a leased tab on it and the result carries `sessionStarted`.',
|
|
44
100
|
inputSchema: {
|
|
45
101
|
url: z.string().optional().describe('The URL to navigate to. Omit when using reload.'),
|
|
46
102
|
reload: z
|
|
@@ -50,7 +106,7 @@ export const BROWSER_TOOLS = [
|
|
|
50
106
|
hard: z
|
|
51
107
|
.boolean()
|
|
52
108
|
.optional()
|
|
53
|
-
.describe('With reload:true, bypass the browser cache (Cmd+Shift+R). Default: false.'),
|
|
109
|
+
.describe('With reload:true, bypass the browser cache (Cmd+Shift+R) on a leased tab. On a tab Reticle does not drive, only the document is fetched again; scripts and modules can still come from the cache. Default: false.'),
|
|
54
110
|
timeout_ms: timeoutMsSchema
|
|
55
111
|
.optional()
|
|
56
112
|
.describe('How long to wait for the page to come back (the SDK reconnecting at the new URL, or under the same id on a reload) before answering confirmed:false. Default 5000. 0 looks once without waiting. An SPA reattaching under HMR has been measured at 30-60s — say so here instead of polling reticle_sessions.'),
|
|
@@ -74,7 +130,11 @@ export const BROWSER_TOOLS = [
|
|
|
74
130
|
* of "Reticle stopped waiting" and "the page never came back" you are looking at.
|
|
75
131
|
*/
|
|
76
132
|
waitedMs: z.number().optional(),
|
|
133
|
+
/** Present only when no session was connected and this call opened one on the URL. */
|
|
134
|
+
sessionStarted: SessionStartedSchema.optional(),
|
|
77
135
|
note: z.string().optional(),
|
|
136
|
+
/** On a `hard` reload: whether the browser ignored its cache, or only the document was fetched again. */
|
|
137
|
+
hardReload: z.nativeEnum(HardReload).optional(),
|
|
78
138
|
},
|
|
79
139
|
handler: async (deps, args) => {
|
|
80
140
|
// reload:true is the absorbed reticle_refresh — same command, one fewer advertised tool.
|
|
@@ -90,9 +150,13 @@ export const BROWSER_TOOLS = [
|
|
|
90
150
|
// coming back `contradicted` by hundreds of 500s against resources that were already gone.
|
|
91
151
|
before.lastAct.markNavigated(before.elapsed());
|
|
92
152
|
deps.recordings.markNavigated();
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
153
|
+
const hard = true === args['hard'];
|
|
154
|
+
// A leased tab reloads through the browser with the cache ignored. The page itself can only
|
|
155
|
+
// re-fetch its document: scripts and modules still come from the cache (#1785).
|
|
156
|
+
const throughBrowser = hard && true === (await deps.pool?.hardReloadLease(before.id));
|
|
157
|
+
if (!throughBrowser) {
|
|
158
|
+
await commandOrThrow(deps, asString(args['sessionId']), ReticleCommand.REFRESH, { hard });
|
|
159
|
+
}
|
|
96
160
|
// WAIT for the page to come back, rather than telling the agent to. The id survives the
|
|
97
161
|
// reload, but the seconds between dispatch and the new HELLO are seconds in which every call
|
|
98
162
|
// lands in the old, disconnected session — measured as reticle_run failing 5 of 5 on a page
|
|
@@ -107,11 +171,12 @@ export const BROWSER_TOOLS = [
|
|
|
107
171
|
// Not a bare `{ ok: true }`. The URL branch below already discloses that `ok` means
|
|
108
172
|
// DISPATCHED — the reload branch had identical semantics and said nothing, on the path most
|
|
109
173
|
// likely to need it. See reload-result.
|
|
110
|
-
return reloadResult(back, timeoutMs);
|
|
174
|
+
return reloadResult(back, timeoutMs, hardReloadOf(hard, throughBrowser));
|
|
111
175
|
}
|
|
112
176
|
const requested = asString(args['url']);
|
|
113
|
-
if (requested === undefined || 0 === requested.length)
|
|
177
|
+
if (requested === undefined || 0 === requested.length) {
|
|
114
178
|
return { ok: false, reason: 'url required' };
|
|
179
|
+
}
|
|
115
180
|
assertNotPaymentNavigation(requested);
|
|
116
181
|
const named = asString(args['sessionId']);
|
|
117
182
|
// A lease whose page has no SDK right now (it was navigated to an image, a PDF, another site):
|
|
@@ -123,6 +188,15 @@ export const BROWSER_TOOLS = [
|
|
|
123
188
|
return navigateLease(deps, named, carryReticleIdentity(leaseUrl, requested), args);
|
|
124
189
|
}
|
|
125
190
|
}
|
|
191
|
+
// Nothing is connected at all, and the call named no tab. An absolute URL names the app, so
|
|
192
|
+
// open a lease on it instead of refusing. Several sessions, or one in another project, keep
|
|
193
|
+
// the refusal that resolve gives below: a lease there would guess.
|
|
194
|
+
if (named === undefined && 0 === deps.sessions.count()) {
|
|
195
|
+
if (isHttpUrl(requested)) {
|
|
196
|
+
return startSessionOn(deps, requested);
|
|
197
|
+
}
|
|
198
|
+
return refuseRelativeWithoutSession(deps, requested);
|
|
199
|
+
}
|
|
126
200
|
// Record navigate as an action. Its window is usually empty (the page unloads and the SDK
|
|
127
201
|
// reconnects), but the action record itself — "navigated to X" — is the causal fact worth keeping.
|
|
128
202
|
const session = deps.sessions.resolve(asString(args['sessionId']));
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { type CompareCommandOptions } from '../../command/cli/two-builds/compare-command.js';
|
|
2
|
+
import type { ToolDef } from './tool-kit.js';
|
|
3
|
+
type RunCompare = (options: CompareCommandOptions) => Promise<{
|
|
4
|
+
code: number;
|
|
5
|
+
lines: string[];
|
|
6
|
+
}>;
|
|
7
|
+
type Sleep = (ms: number) => Promise<void>;
|
|
8
|
+
/** The compare tool. `run` and `sleep` are injected so a test needs no daemon. */
|
|
9
|
+
export declare function compareTool(run?: RunCompare, sleep?: Sleep): ToolDef;
|
|
10
|
+
export declare const COMPARE_TOOLS: ToolDef[];
|
|
11
|
+
export {};
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `reticle_verify { action: "compare" }`: `reticle compare` for an agent whose tools are loaded.
|
|
3
|
+
*
|
|
4
|
+
* It runs the CLI's own compare (`runCompareCommand`) against this daemon, over the same loopback
|
|
5
|
+
* transport the CLI uses, so the answer is the `--json` object of `reticle compare` and nothing
|
|
6
|
+
* else. The leased tabs resolve their own project from the page, as every lease does. A compare takes minutes, longer than one tool call may wait, so within `wait` seconds it
|
|
7
|
+
* answers the result, or `{ status: "running", runId }` to poll with `runId`, as `explore` does.
|
|
8
|
+
*/
|
|
9
|
+
import { randomUUID } from 'node:crypto';
|
|
10
|
+
import { z } from 'zod';
|
|
11
|
+
import { RETICLE_DEFAULT_PORT, ReticleTool } from '@reticlehq/core';
|
|
12
|
+
import { pairingToken, runCompareCommand, } from '../../command/cli/two-builds/compare-command.js';
|
|
13
|
+
const RUN_PREFIX = 'compare-';
|
|
14
|
+
const COMPARE_ACTION = 'compare';
|
|
15
|
+
const RUNNING = 'running';
|
|
16
|
+
/** Seconds one call waits for the result before it answers with a run id. */
|
|
17
|
+
const DEFAULT_WAIT_S = 50;
|
|
18
|
+
const MAX_WAIT_S = 240;
|
|
19
|
+
const MS_PER_S = 1000;
|
|
20
|
+
/** The most finished runs kept for polling. A run is read back once or twice, not for ever. */
|
|
21
|
+
const KEPT_RUNS = 8;
|
|
22
|
+
const MSG_NEEDS_URLS = 'compare needs `reference` and `candidate`, the urls of two running builds';
|
|
23
|
+
const MSG_UNKNOWN_RUN = 'no compare run has the id';
|
|
24
|
+
const asText = (value) => 'string' === typeof value && value.length > 0 ? value : undefined;
|
|
25
|
+
/** The JSON object the CLI printed, or the line itself when it is not one. */
|
|
26
|
+
function parsed(lines) {
|
|
27
|
+
const line = lines[0] ?? '';
|
|
28
|
+
try {
|
|
29
|
+
return JSON.parse(line);
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
return { error: line };
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
/** The compare tool. `run` and `sleep` are injected so a test needs no daemon. */
|
|
36
|
+
export function compareTool(run = runCompareCommand, sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms))) {
|
|
37
|
+
const runs = new Map();
|
|
38
|
+
const answer = async (runId, result, waitS) => {
|
|
39
|
+
const timedOut = Symbol(RUNNING);
|
|
40
|
+
const first = await Promise.race([result, sleep(waitS * MS_PER_S).then(() => timedOut)]);
|
|
41
|
+
if (first !== timedOut) {
|
|
42
|
+
return first;
|
|
43
|
+
}
|
|
44
|
+
return { status: RUNNING, runId, next: { action: COMPARE_ACTION, runId } };
|
|
45
|
+
};
|
|
46
|
+
return {
|
|
47
|
+
name: ReticleTool.VERIFY_COMPARE,
|
|
48
|
+
description: 'Drive two running builds of one app the same way (for example main and a pull request preview) and list each difference in what users see and in the requests and console errors the app made. Nothing is installed in the app. One opinionated recipe: plan every action on the reference, drive it on the reference two times and the candidate one time, and ignore what changes between the two reference runs. With `base`, each difference is tagged regression, target-missed or changed, with a score. Answers the JSON of `reticle compare --json`: `verified` yes (same), no (different) or unknown (the run proves nothing). Within `wait` seconds the result, or { status: "running", runId } to poll with `runId`. DESTRUCTIVE: it presses every button it finds.',
|
|
49
|
+
inputSchema: {
|
|
50
|
+
reference: z.string().optional().describe('URL of the build that is right, e.g. main.'),
|
|
51
|
+
candidate: z.string().optional().describe('URL of the build to check.'),
|
|
52
|
+
base: z.string().optional().describe('URL of the build before the change.'),
|
|
53
|
+
runId: z
|
|
54
|
+
.string()
|
|
55
|
+
.optional()
|
|
56
|
+
.describe('The run id a compare call answered with; pass it to poll that run.'),
|
|
57
|
+
wait: z.number().min(0).max(MAX_WAIT_S).optional().describe('Seconds; default 50.'),
|
|
58
|
+
},
|
|
59
|
+
handler: async (deps, args) => {
|
|
60
|
+
const waitS = 'number' === typeof args['wait'] ? args['wait'] : DEFAULT_WAIT_S;
|
|
61
|
+
const polled = asText(args['runId']);
|
|
62
|
+
if (polled !== undefined) {
|
|
63
|
+
const result = runs.get(polled);
|
|
64
|
+
if (result === undefined) {
|
|
65
|
+
return { error: `${MSG_UNKNOWN_RUN} ${polled}` };
|
|
66
|
+
}
|
|
67
|
+
return answer(polled, result, waitS);
|
|
68
|
+
}
|
|
69
|
+
const reference = asText(args['reference']);
|
|
70
|
+
const candidate = asText(args['candidate']);
|
|
71
|
+
if (reference === undefined || candidate === undefined) {
|
|
72
|
+
return { error: MSG_NEEDS_URLS };
|
|
73
|
+
}
|
|
74
|
+
const base = asText(args['base']);
|
|
75
|
+
const token = pairingToken();
|
|
76
|
+
const runId = `${RUN_PREFIX}${randomUUID()}`;
|
|
77
|
+
const result = run({
|
|
78
|
+
reference,
|
|
79
|
+
candidate,
|
|
80
|
+
...(base === undefined ? {} : { base }),
|
|
81
|
+
json: true,
|
|
82
|
+
port: deps.bridgePort ?? RETICLE_DEFAULT_PORT,
|
|
83
|
+
...(token === undefined ? {} : { token }),
|
|
84
|
+
}).then((out) => parsed(out.lines));
|
|
85
|
+
runs.set(runId, result);
|
|
86
|
+
// ponytail: the oldest runs are dropped by count. Drop by age if a session polls very late.
|
|
87
|
+
for (const old of [...runs.keys()].slice(0, Math.max(0, runs.size - KEPT_RUNS))) {
|
|
88
|
+
runs.delete(old);
|
|
89
|
+
}
|
|
90
|
+
return answer(runId, result, waitS);
|
|
91
|
+
},
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
export const COMPARE_TOOLS = [compareTool()];
|
|
@@ -63,7 +63,7 @@ export function buildCoverageTools() {
|
|
|
63
63
|
app: z
|
|
64
64
|
.boolean()
|
|
65
65
|
.optional()
|
|
66
|
-
.describe('Also fold into the app-wide ledger; returns `app.levels`.'),
|
|
66
|
+
.describe('Also fold into the app-wide ledger; returns `app.levels`, `app.holes` and `app.findings`.'),
|
|
67
67
|
...sessionIdShape,
|
|
68
68
|
},
|
|
69
69
|
outputSchema: {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import { runTool } from './invoke-tool.js';
|
|
3
3
|
import { buildErrorPayload, codedRefusalOf } from './error-recovery.js';
|
|
4
|
+
import { withRepeatHint } from './repeat-hint.js';
|
|
4
5
|
import { mergedNameRedirect, mergedNameMessage, retiredToolNames } from './merged-name-redirect.js';
|
|
5
6
|
import { CATALOGUE_SUMMARY_LENGTH, firstSentence } from './first-sentence.js';
|
|
6
7
|
import { takeVersionSkewOnto } from '../../command/version/version-nudge.js';
|
|
@@ -309,10 +310,17 @@ callable) {
|
|
|
309
310
|
hint: `pass them inside args: reticle_run { tool, args: { ${strayTop.join(', ')}: … } } if the target tool declares them`,
|
|
310
311
|
};
|
|
311
312
|
}
|
|
312
|
-
const
|
|
313
|
-
const
|
|
313
|
+
const asked = 'string' === typeof args['tool'] ? args['tool'] : '';
|
|
314
|
+
const passed = 'object' === typeof args['args'] && args['args'] !== null
|
|
314
315
|
? args['args']
|
|
315
316
|
: {};
|
|
317
|
+
// A merged name is CALLED, as the MCP layer does (mcp.ts). Explaining it here left
|
|
318
|
+
// `reticle verify --expect` unable to wait, so it could never give a verdict. The old name is
|
|
319
|
+
// the action, so it wins over an `action` in the arguments.
|
|
320
|
+
const moved = byName.has(asked) ? undefined : mergedNameRedirect(asked);
|
|
321
|
+
const routed = moved?.action !== undefined && byName.has(moved.tool);
|
|
322
|
+
const name = routed ? moved.tool : asked;
|
|
323
|
+
const given = routed ? { ...passed, action: moved.action } : passed;
|
|
316
324
|
const aimed = args['sessionId'];
|
|
317
325
|
const target = byName.get(name);
|
|
318
326
|
if (target === undefined) {
|
|
@@ -381,7 +389,7 @@ callable) {
|
|
|
381
389
|
// is reached through here: a stale ref, a paused session, a missing pairing token all came
|
|
382
390
|
// back as the agent's arguments being wrong, which is advice that spends the retry.
|
|
383
391
|
const message = error instanceof Error ? error.message : String(error);
|
|
384
|
-
const payload = buildErrorPayload(message, codedRefusalOf(error));
|
|
392
|
+
const payload = withRepeatHint(buildErrorPayload(message, codedRefusalOf(error)), error);
|
|
385
393
|
return { ...takeVersionSkewOnto(payload, deps.peerSkew), tool: name };
|
|
386
394
|
}
|
|
387
395
|
},
|
|
@@ -2,6 +2,8 @@ import { z } from 'zod';
|
|
|
2
2
|
import { wiringConsent } from '../../portal/session/no-session-next-action.js';
|
|
3
3
|
export { wiringConsent };
|
|
4
4
|
import type { ToolDeps } from './tool-kit.js';
|
|
5
|
+
/** The field that carries the next step for an unwired project. */
|
|
6
|
+
export declare const NEXT_STEP_FIELD = "next_step";
|
|
5
7
|
/** The fields only an empty list carries, declared so a schema-aware client does not strip them. */
|
|
6
8
|
export declare const EMPTY_SESSION_LIST_OUTPUT: {
|
|
7
9
|
why: z.ZodOptional<z.ZodString>;
|
|
@@ -32,6 +32,8 @@ const LEASABLE_ACTIONS = new Set([
|
|
|
32
32
|
NoSessionAction.OPEN_APP,
|
|
33
33
|
]);
|
|
34
34
|
const LOCALHOST = 'http://localhost';
|
|
35
|
+
/** The field that carries the next step for an unwired project. */
|
|
36
|
+
export const NEXT_STEP_FIELD = 'next_step';
|
|
35
37
|
/** The fields only an empty list carries, declared so a schema-aware client does not strip them. */
|
|
36
38
|
export const EMPTY_SESSION_LIST_OUTPUT = {
|
|
37
39
|
why: z
|
|
@@ -51,7 +53,7 @@ export const EMPTY_SESSION_LIST_OUTPUT = {
|
|
|
51
53
|
.string()
|
|
52
54
|
.optional()
|
|
53
55
|
.describe('Present ONLY when `sessions` is empty: a call with the founder for the person you are working with. Offer it; never act on it.'),
|
|
54
|
-
|
|
56
|
+
[NEXT_STEP_FIELD]: z
|
|
55
57
|
.object({
|
|
56
58
|
offered: z.nativeEnum(NextStepOffered),
|
|
57
59
|
lease: z.string().optional(),
|
|
@@ -141,7 +143,7 @@ export function emptySessionList(deps, sessions) {
|
|
|
141
143
|
sessions,
|
|
142
144
|
...(why === undefined ? {} : { why }),
|
|
143
145
|
...(next === undefined ? {} : { next_action: next }),
|
|
144
|
-
...(nextStep === undefined ? {} : {
|
|
146
|
+
...(nextStep === undefined ? {} : { [NEXT_STEP_FIELD]: nextStep }),
|
|
145
147
|
...(undefined === lastKnown ? {} : { lastKnown }),
|
|
146
148
|
// Setup that never connects is where most people give up; it is the talk worth having.
|
|
147
149
|
talk_to_us: DiscoveryInvite.AGENT,
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* on stable, human-authored substrings of the thrown messages (see session-manager.ts, the flow/
|
|
9
9
|
* baseline stores). No clock, no IO — unit-testable in isolation.
|
|
10
10
|
*/
|
|
11
|
-
import { RefusalReason, type CodedRefusal } from '@reticlehq/core';
|
|
11
|
+
import { RefusalDetail, RefusalReason, type CodedRefusal } from '@reticlehq/core';
|
|
12
12
|
/** The recovery hints, named so they are not free strings and can be asserted in tests. */
|
|
13
13
|
export declare const RECOVERY: {
|
|
14
14
|
readonly NO_SESSION: string;
|
|
@@ -97,6 +97,11 @@ export declare const RECOVERY: {
|
|
|
97
97
|
* saying a server is running and the recovery saying to go start one.
|
|
98
98
|
*/
|
|
99
99
|
export declare function recoveryFor(message: string): string | undefined;
|
|
100
|
+
/** A refusal's bucket, and the cause inside it when the recovery table can tell. */
|
|
101
|
+
export interface RefusalClass {
|
|
102
|
+
readonly reason: RefusalReason;
|
|
103
|
+
readonly detail?: RefusalDetail;
|
|
104
|
+
}
|
|
100
105
|
/**
|
|
101
106
|
* WHY a tool refused, as one of the six buckets in core's `RefusalReason`.
|
|
102
107
|
*
|
|
@@ -106,6 +111,12 @@ export declare function recoveryFor(message: string): string | undefined;
|
|
|
106
111
|
* this table rather than about anybody's app.
|
|
107
112
|
*/
|
|
108
113
|
export declare function refusalReasonFor(rawMessage: string, coded?: CodedRefusal): RefusalReason;
|
|
114
|
+
/**
|
|
115
|
+
* The bucket and, when the recovery table names one, the cause inside it. The cause comes from the
|
|
116
|
+
* same rule that chose the agent's advice, so the two cannot disagree. No detail means no rule
|
|
117
|
+
* matched, or the message diagnosed itself (`noSessionReason` carries that cause).
|
|
118
|
+
*/
|
|
119
|
+
export declare function classifyRefusal(rawMessage: string, coded?: CodedRefusal): RefusalClass;
|
|
109
120
|
/**
|
|
110
121
|
* The ask attached to errors we do NOT recognize. An unrecognized error is, by definition, the case
|
|
111
122
|
* where Reticle failed in a way nobody anticipated — the single highest-value moment to hear from the
|