@reticlehq/server 3.5.0 → 3.7.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/README.md +1 -1
- package/SKILL.md +123 -116
- package/dist/chromium-launch-options.d.ts +3 -1
- package/dist/chromium-launch-options.js +2 -1
- package/dist/command/cli/adhoc-suite.d.ts +14 -0
- package/dist/command/cli/adhoc-suite.js +42 -7
- package/dist/command/cli/adhoc-verdict.d.ts +19 -2
- package/dist/command/cli/adhoc-verdict.js +76 -9
- package/dist/command/cli/answers/gate-exit.d.ts +23 -0
- package/dist/command/cli/answers/gate-exit.js +45 -0
- package/dist/command/cli/answers/gate-hook-message.d.ts +2 -0
- package/dist/command/cli/answers/gate-hook-message.js +3 -1
- package/dist/command/cli/answers/open-note.d.ts +2 -0
- package/dist/command/cli/answers/open-note.js +22 -0
- package/dist/command/cli/auth/device-flow.d.ts +13 -2
- package/dist/command/cli/auth/device-flow.js +17 -0
- package/dist/command/cli/cli-doctor.js +14 -0
- package/dist/command/cli/cli-flow-commands.d.ts +0 -11
- package/dist/command/cli/cli-flow-commands.js +31 -112
- package/dist/command/cli/cli-kill.js +3 -2
- package/dist/command/cli/cli-parse-grammar.d.ts +24 -0
- package/dist/command/cli/cli-parse-grammar.js +75 -0
- package/dist/command/cli/cli-parse-verify.d.ts +2 -0
- package/dist/command/cli/cli-parse-verify.js +18 -0
- package/dist/command/cli/cli-parse.d.ts +19 -28
- package/dist/command/cli/cli-parse.js +82 -182
- package/dist/command/cli/cli-update-commands.d.ts +1 -1
- package/dist/command/cli/cli-update-commands.js +61 -9
- package/dist/command/cli/cli-usage.d.ts +33 -0
- package/dist/command/cli/cli-usage.js +287 -0
- package/dist/command/cli/cli-verify.d.ts +35 -5
- package/dist/command/cli/cli-verify.js +114 -35
- package/dist/command/cli/cloud-cli.d.ts +13 -0
- package/dist/command/cli/cloud-cli.js +192 -341
- package/dist/command/cli/cloud-kit.d.ts +12 -0
- package/dist/command/cli/cloud-kit.js +41 -2
- package/dist/command/cli/cloud-link.d.ts +57 -0
- package/dist/command/cli/cloud-link.js +308 -0
- package/dist/command/cli/cloud-login.d.ts +22 -0
- package/dist/command/cli/cloud-login.js +96 -8
- package/dist/command/cli/context-command.d.ts +1 -0
- package/dist/command/cli/context-command.js +33 -0
- package/dist/command/cli/daemon-start-options.d.ts +3 -0
- package/dist/command/cli/daemon-start-options.js +24 -3
- package/dist/command/cli/doctor/browser/chromium-hint.d.ts +46 -0
- package/dist/command/cli/doctor/browser/chromium-hint.js +99 -1
- package/dist/command/cli/doctor/doctor-coverage-line.d.ts +2 -0
- package/dist/command/cli/doctor/doctor-coverage-line.js +47 -0
- package/dist/command/cli/doctor/doctor-project-line.d.ts +0 -12
- package/dist/command/cli/doctor/doctor-project-line.js +5 -4
- package/dist/command/cli/doctor/doctor-rows.d.ts +6 -0
- package/dist/command/cli/doctor/doctor-rows.js +6 -0
- package/dist/command/cli/doctor/doctor-signing-line.d.ts +38 -0
- package/dist/command/cli/doctor/doctor-signing-line.js +114 -0
- package/dist/command/cli/drive/drive-attach.d.ts +27 -2
- package/dist/command/cli/drive/drive-attach.js +71 -4
- package/dist/command/cli/drive/drive-command.d.ts +2 -1
- package/dist/command/cli/drive/drive-command.js +13 -7
- package/dist/command/cli/known-regression.d.ts +13 -0
- package/dist/command/cli/known-regression.js +34 -0
- package/dist/command/cli/launch/sdk-version-match.d.ts +12 -0
- package/dist/command/cli/launch/sdk-version-match.js +25 -0
- package/dist/command/cli/lifecycle/daemon-lifecycle.js +15 -3
- package/dist/command/cli/mcp-command.d.ts +6 -0
- package/dist/command/cli/mcp-command.js +13 -5
- package/dist/command/cli/ports/port-holder.d.ts +10 -0
- package/dist/command/cli/ports/port-holder.js +25 -1
- package/dist/command/cli/project-name.d.ts +29 -1
- package/dist/command/cli/project-name.js +107 -2
- package/dist/command/cli/setup-mcp-cli.d.ts +17 -1
- package/dist/command/cli/setup-mcp-cli.js +35 -12
- package/dist/command/cli/status/status-lines.d.ts +1 -0
- package/dist/command/cli/status/status-lines.js +47 -2
- package/dist/command/cli/status/workspace-links.d.ts +10 -0
- package/dist/command/cli/status/workspace-links.js +29 -0
- package/dist/command/cli/try-command.d.ts +96 -0
- package/dist/command/cli/try-command.js +362 -0
- package/dist/command/cli/tutorial.d.ts +0 -100
- package/dist/command/cli/tutorial.js +0 -181
- package/dist/command/cli/verify-results.d.ts +19 -0
- package/dist/command/cli/verify-results.js +29 -0
- package/dist/command/cli-onboarding.d.ts +0 -11
- package/dist/command/cli-onboarding.js +0 -15
- package/dist/command/cli.d.ts +20 -0
- package/dist/command/cli.js +130 -104
- package/dist/command/daemon/binding/daemon-status-probe.d.ts +2 -0
- package/dist/command/daemon/binding/daemon-status-probe.js +1 -0
- package/dist/command/daemon/daemon-resilience.js +4 -4
- package/dist/command/daemon/daemon-resolve.d.ts +23 -1
- package/dist/command/daemon/daemon-resolve.js +79 -9
- package/dist/command/setup/agent-writer.d.ts +1 -1
- package/dist/command/setup/agent-writer.js +3 -2
- package/dist/command/setup/bringup/bridge-port.d.ts +3 -1
- package/dist/command/setup/bringup/bridge-port.js +13 -3
- package/dist/command/setup/bringup/connect-lease.d.ts +1 -0
- package/dist/command/setup/bringup/connect-lease.js +1 -0
- package/dist/command/setup/bringup/dev-server-log-cap.js +2 -0
- package/dist/command/setup/bringup/dev-server-wait.d.ts +8 -0
- package/dist/command/setup/bringup/dev-server-wait.js +19 -0
- package/dist/command/setup/bringup/ensure-daemon.js +9 -2
- package/dist/command/setup/init/agent-restart.d.ts +23 -0
- package/dist/command/setup/init/agent-restart.js +28 -0
- package/dist/command/setup/init/init-port.d.ts +14 -1
- package/dist/command/setup/init/init-port.js +32 -2
- package/dist/command/setup/init/init-runtime.d.ts +22 -2
- package/dist/command/setup/init/init-runtime.js +114 -38
- package/dist/command/setup/node-effects.d.ts +2 -0
- package/dist/command/setup/node-effects.js +38 -9
- package/dist/command/setup/probe/existing-app.d.ts +12 -0
- package/dist/command/setup/probe/existing-app.js +14 -0
- package/dist/command/setup/remaining-steps.js +2 -1
- package/dist/command/setup/run-setup.d.ts +34 -9
- package/dist/command/setup/run-setup.js +65 -51
- package/dist/command/setup/setup-command.d.ts +25 -1
- package/dist/command/setup/setup-command.js +59 -4
- package/dist/command/setup/setup-mcp.js +25 -2
- package/dist/command/setup/tauri-signing.d.ts +19 -0
- package/dist/command/setup/tauri-signing.js +79 -0
- package/dist/command/setup/terminal/listeners.d.ts +10 -1
- package/dist/command/setup/terminal/listeners.js +37 -6
- package/dist/command/update/update-nudge.d.ts +9 -0
- package/dist/command/update/update-nudge.js +1 -1
- package/dist/command/update/updater.js +11 -15
- package/dist/command/version/version-nudge.js +3 -0
- package/dist/command/version/version-skew.d.ts +20 -1
- package/dist/command/version/version-skew.js +49 -4
- package/dist/features/crawl/crawl-tools.js +4 -0
- package/dist/features/crawl/crawl.d.ts +6 -0
- package/dist/features/crawl/crawl.js +23 -2
- package/dist/features/exhaust/ledger.d.ts +21 -14
- package/dist/features/exhaust/ledger.js +35 -9
- package/dist/features/harness/app-findings.d.ts +2 -0
- package/dist/features/harness/app-findings.js +52 -0
- package/dist/features/harness/drive-report.d.ts +61 -1
- package/dist/features/harness/drive-report.js +394 -26
- package/dist/features/harness/drive-runs.d.ts +120 -0
- package/dist/features/harness/drive-runs.js +289 -0
- package/dist/features/harness/drivers.d.ts +10 -14
- package/dist/features/harness/drivers.js +10 -14
- package/dist/features/harness/explore/console-pages.d.ts +15 -0
- package/dist/features/harness/explore/console-pages.js +146 -0
- package/dist/features/harness/explore/disparity.d.ts +19 -0
- package/dist/features/harness/explore/disparity.js +71 -0
- package/dist/features/harness/explore/fake-app.d.ts +16 -0
- package/dist/features/harness/explore/fake-app.js +49 -0
- package/dist/features/harness/explore/goal-search.d.ts +26 -0
- package/dist/features/harness/explore/goal-search.js +144 -0
- package/dist/features/harness/explore/page-tree.d.ts +49 -0
- package/dist/features/harness/explore/page-tree.js +148 -0
- package/dist/features/harness/explore/site-map.d.ts +34 -0
- package/dist/features/harness/explore/site-map.js +150 -0
- package/dist/features/harness/fill-values.d.ts +3 -73
- package/dist/features/harness/fill-values.js +3 -169
- package/dist/features/harness/goals.d.ts +82 -0
- package/dist/features/harness/goals.js +330 -0
- package/dist/features/harness/harness.d.ts +51 -1
- package/dist/features/harness/harness.js +207 -6
- package/dist/features/harness/platform/drive-target.d.ts +30 -0
- package/dist/features/harness/platform/drive-target.js +81 -0
- package/dist/features/harness/platform/local-apps.d.ts +127 -0
- package/dist/features/harness/platform/local-apps.js +280 -0
- package/dist/features/harness/platform/persona-credentials.d.ts +20 -0
- package/dist/features/harness/platform/persona-credentials.js +69 -0
- package/dist/features/harness/platform/platform-drives.d.ts +61 -0
- package/dist/features/harness/platform/platform-drives.js +114 -0
- package/dist/features/harness/platform/refusal.d.ts +52 -0
- package/dist/features/harness/platform/refusal.js +71 -0
- package/dist/features/harness/platform/remote-drive.d.ts +186 -0
- package/dist/features/harness/platform/remote-drive.js +378 -0
- package/dist/features/harness/platform/script.d.ts +94 -0
- package/dist/features/harness/platform/script.js +260 -0
- package/dist/features/harness/platform/server-driver.d.ts +54 -0
- package/dist/features/harness/platform/server-driver.js +182 -0
- package/dist/features/harness/platform-config.d.ts +41 -1
- package/dist/features/harness/platform-config.js +106 -9
- package/dist/features/harness/route-guess.d.ts +13 -0
- package/dist/features/harness/route-guess.js +49 -0
- package/dist/features/harness/script/app-controls.d.ts +5 -0
- package/dist/features/harness/script/app-controls.js +40 -0
- package/dist/features/harness/script/lane-ids.d.ts +14 -0
- package/dist/features/harness/script/lane-ids.js +16 -0
- package/dist/features/harness/script/script-run.d.ts +70 -0
- package/dist/features/harness/script/script-run.js +606 -0
- package/dist/features/license/license.d.ts +2 -2
- package/dist/features/visual/step-shots.d.ts +31 -0
- package/dist/features/visual/step-shots.js +231 -0
- package/dist/features/visual/visual-tools.d.ts +10 -1
- package/dist/features/visual/visual-tools.js +62 -17
- package/dist/hooks/client-directory.d.ts +18 -0
- package/dist/hooks/client-directory.js +57 -0
- package/dist/hooks/coding-agents.d.ts +34 -0
- package/dist/hooks/coding-agents.js +117 -0
- package/dist/hooks/driven-by.d.ts +23 -0
- package/dist/hooks/driven-by.js +56 -0
- package/dist/hooks/hook-bus.d.ts +4 -0
- package/dist/hooks/hook-bus.js +18 -0
- package/dist/hooks/hook-commands.js +15 -4
- package/dist/hooks/tool-log.d.ts +9 -0
- package/dist/hooks/tool-log.js +29 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +80 -243
- package/dist/judgement/capsule/capsule-store.d.ts +2 -2
- package/dist/judgement/capsule/causal-summary.d.ts +15 -1
- package/dist/judgement/capsule/causal-summary.js +33 -0
- package/dist/judgement/runs/artifact/build-verification-run.d.ts +1 -1
- package/dist/judgement/runs/artifact/build-verification-run.js +25 -3
- package/dist/judgement/runs/artifact/gap-summary.d.ts +0 -18
- package/dist/judgement/runs/artifact/gap-summary.js +12 -3
- package/dist/judgement/runs/artifact/replay-mapping.d.ts +1 -1
- package/dist/judgement/runs/artifact/replay-mapping.js +37 -11
- package/dist/judgement/runs/artifact/run-store.d.ts +14 -2
- package/dist/judgement/runs/artifact/run-store.js +195 -3
- package/dist/judgement/runs/context-tools.js +59 -1
- package/dist/judgement/runs/default-run-id.d.ts +3 -0
- package/dist/judgement/runs/default-run-id.js +16 -0
- package/dist/judgement/runs/drive-run.d.ts +71 -1
- package/dist/judgement/runs/drive-run.js +317 -5
- package/dist/judgement/runs/repair-prompt.js +1 -1
- package/dist/judgement/runs/resume.d.ts +44 -0
- package/dist/judgement/runs/resume.js +137 -0
- package/dist/judgement/runs/reticle-runner.js +13 -3
- package/dist/judgement/runs/runner-port.d.ts +5 -1
- package/dist/judgement/runs/runner-port.js +8 -2
- package/dist/judgement/runs/verification-sync.d.ts +5 -2
- package/dist/judgement/runs/verification-sync.js +40 -18
- package/dist/language/flows/change/gate.d.ts +10 -0
- package/dist/language/flows/change/gate.js +22 -0
- package/dist/language/flows/decision.js +36 -1
- package/dist/language/flows/fields/flow-secret-field.d.ts +12 -0
- package/dist/language/flows/fields/flow-secret-field.js +25 -2
- package/dist/language/flows/flow-anchor.d.ts +61 -10
- package/dist/language/flows/flow-anchor.js +98 -6
- package/dist/language/flows/flow-cross-step.d.ts +15 -0
- package/dist/language/flows/flow-cross-step.js +21 -0
- package/dist/language/flows/flow-intent.d.ts +1 -0
- package/dist/language/flows/flow-journey.d.ts +6 -0
- package/dist/language/flows/flow-journey.js +20 -0
- package/dist/language/flows/flow-learning.d.ts +4 -0
- package/dist/language/flows/flow-learning.js +45 -14
- package/dist/language/flows/flow-mutate-tools.js +5 -3
- package/dist/language/flows/flow-replay-run.d.ts +23 -9
- package/dist/language/flows/flow-replay-run.js +115 -110
- package/dist/language/flows/flow-replay-types.d.ts +1 -1
- package/dist/language/flows/flow-replay.d.ts +40 -1
- package/dist/language/flows/flow-replay.js +110 -22
- package/dist/language/flows/flow-result.d.ts +22 -1
- package/dist/language/flows/flow-result.js +47 -2
- package/dist/language/flows/flow-scope.js +5 -1
- package/dist/language/flows/flow-step-runners.d.ts +22 -2
- package/dist/language/flows/flow-step-runners.js +247 -47
- package/dist/language/flows/flow-store-for-session.d.ts +2 -2
- package/dist/language/flows/flow-store-for-session.js +7 -3
- package/dist/language/flows/flow-tools.d.ts +10 -0
- package/dist/language/flows/flow-tools.js +112 -89
- package/dist/language/flows/flows.d.ts +16 -1
- package/dist/language/flows/flows.js +74 -12
- package/dist/language/flows/heal-run.js +6 -4
- package/dist/language/flows/narrow-write.d.ts +7 -0
- package/dist/language/flows/narrow-write.js +36 -1
- package/dist/language/flows/recording/flake.d.ts +2 -2
- package/dist/language/flows/recording/recording-backtrack.js +14 -1
- package/dist/language/flows/recording/tape/recordings.d.ts +58 -4
- package/dist/language/flows/recording/tape/recordings.js +95 -13
- package/dist/language/flows/replay-from-hud.d.ts +20 -0
- package/dist/language/flows/replay-from-hud.js +51 -0
- package/dist/language/flows/replay.d.ts +9 -5
- package/dist/language/flows/replay.js +56 -15
- package/dist/language/flows/single-replay.d.ts +7 -0
- package/dist/language/flows/single-replay.js +26 -0
- package/dist/language/flows/suite/suite-flakes.js +2 -0
- package/dist/language/flows/suite-selection.d.ts +2 -15
- package/dist/language/flows/suite-selection.js +4 -3
- package/dist/language/flows/verify-change-tools.d.ts +1 -0
- package/dist/language/flows/verify-change-tools.js +202 -191
- package/dist/launch-chromium.d.ts +27 -5
- package/dist/launch-chromium.js +38 -8
- package/dist/memory/cloud/cloud-config.d.ts +22 -1
- package/dist/memory/cloud/cloud-config.js +34 -5
- package/dist/memory/cloud/cloud-sync.d.ts +17 -14
- package/dist/memory/cloud/cloud-sync.js +15 -4
- package/dist/memory/cloud/harness-config.d.ts +75 -1
- package/dist/memory/cloud/harness-config.js +115 -24
- package/dist/memory/cloud/hud-notices-source.d.ts +21 -0
- package/dist/memory/cloud/hud-notices-source.js +128 -0
- package/dist/memory/cloud/memory-scope.d.ts +161 -0
- package/dist/memory/cloud/memory-scope.js +227 -0
- package/dist/memory/cloud/sync-cycle.d.ts +44 -7
- package/dist/memory/cloud/sync-cycle.js +129 -15
- package/dist/memory/cloud/sync-daemon.d.ts +11 -0
- package/dist/memory/cloud/sync-daemon.js +121 -9
- package/dist/memory/cloud/sync-disk.d.ts +1 -1
- package/dist/memory/cloud/sync-disk.js +31 -10
- package/dist/memory/cloud/sync-screenshots.d.ts +32 -0
- package/dist/memory/cloud/sync-screenshots.js +105 -0
- package/dist/memory/cloud/unsynced-roots.d.ts +47 -0
- package/dist/memory/cloud/unsynced-roots.js +166 -0
- package/dist/memory/impact/account-watch.d.ts +34 -0
- package/dist/memory/impact/account-watch.js +59 -0
- package/dist/memory/impact/impact-recorder.d.ts +8 -0
- package/dist/memory/impact/impact-recorder.js +12 -2
- package/dist/memory/impact/impact-store.d.ts +17 -4
- package/dist/memory/impact/impact-store.js +169 -63
- package/dist/memory/intent/inline-intent.d.ts +1 -0
- package/dist/memory/intent/intent-shard-store.js +16 -4
- package/dist/memory/intent/intent-shard.d.ts +14 -2
- package/dist/memory/intent/intent-store.d.ts +1 -0
- package/dist/memory/intent/intent-tools.js +122 -4
- package/dist/memory/intent/open-intents.d.ts +6 -0
- package/dist/memory/intent/open-intents.js +10 -1
- package/dist/memory/intent/settled-words.d.ts +24 -0
- package/dist/memory/intent/settled-words.js +130 -0
- package/dist/memory/journal/drive-flow.d.ts +16 -0
- package/dist/memory/journal/drive-flow.js +34 -2
- package/dist/memory/journal/drive-run-flush.d.ts +2 -0
- package/dist/memory/journal/drive-run-flush.js +20 -5
- package/dist/memory/journal/envelope.d.ts +8 -8
- package/dist/memory/journal/journal-recorder.js +52 -3
- package/dist/memory/journal/on-disk/retention.d.ts +8 -0
- package/dist/memory/journal/on-disk/retention.js +32 -2
- package/dist/memory/journal/on-disk/startup-maintenance.js +3 -1
- package/dist/memory/journal/on-disk/workspace-tiers.js +9 -4
- package/dist/memory/journal/session-end.d.ts +15 -1
- package/dist/memory/journal/session-end.js +42 -9
- package/dist/memory/project/artifact-root-resolver.d.ts +26 -1
- package/dist/memory/project/artifact-root-resolver.js +125 -16
- package/dist/memory/project/artifact-root.d.ts +46 -8
- package/dist/memory/project/artifact-root.js +89 -10
- package/dist/memory/project/dir/reticle-dir.d.ts +18 -2
- package/dist/memory/project/dir/reticle-dir.js +26 -3
- package/dist/memory/project/link-directory.d.ts +15 -0
- package/dist/memory/project/link-directory.js +44 -0
- package/dist/memory/project/project-tools.js +22 -3
- package/dist/memory/project/root-claims.d.ts +6 -0
- package/dist/memory/project/root-claims.js +39 -0
- package/dist/memory/project/session-root.d.ts +26 -1
- package/dist/memory/project/session-root.js +49 -5
- package/dist/memory/project/sync-status.d.ts +85 -0
- package/dist/memory/project/sync-status.js +224 -0
- package/dist/memory/recall/memory-tools.js +47 -2
- package/dist/memory/recall/platform-memory.d.ts +34 -0
- package/dist/memory/recall/platform-memory.js +139 -0
- package/dist/memory/recall/project-memory.d.ts +19 -0
- package/dist/memory/recall/project-memory.js +80 -13
- package/dist/portal/bridge/bridge.d.ts +9 -3
- package/dist/portal/bridge/bridge.js +82 -22
- package/dist/portal/bridge/harness-request.d.ts +23 -0
- package/dist/portal/bridge/harness-request.js +27 -0
- package/dist/portal/bridge/pairing-token.d.ts +9 -0
- package/dist/portal/bridge/pairing-token.js +17 -0
- package/dist/portal/bridge/wrong-path.d.ts +17 -0
- package/dist/portal/bridge/wrong-path.js +35 -0
- package/dist/portal/input/network-mock-tools.js +11 -2
- package/dist/portal/input/real-input.d.ts +83 -10
- package/dist/portal/input/real-input.js +218 -30
- package/dist/portal/input/viewport-tools.js +3 -3
- package/dist/portal/pool/browser-pool.d.ts +70 -9
- package/dist/portal/pool/browser-pool.js +190 -37
- package/dist/portal/pool/context-permissions.d.ts +33 -0
- package/dist/portal/pool/context-permissions.js +33 -0
- package/dist/portal/pool/lease-marker-stamp.d.ts +23 -0
- package/dist/portal/pool/lease-marker-stamp.js +49 -0
- package/dist/portal/pool/playwright-launcher.d.ts +35 -0
- package/dist/portal/pool/playwright-launcher.js +64 -3
- package/dist/portal/pool/pool-contract.d.ts +28 -5
- package/dist/portal/session/agent-link.d.ts +8 -0
- package/dist/portal/session/agent-link.js +17 -0
- package/dist/portal/session/command-payload.d.ts +8 -0
- package/dist/portal/session/command-payload.js +24 -0
- package/dist/portal/session/daemon-answers.d.ts +3 -3
- package/dist/portal/session/daemon-answers.js +4 -2
- package/dist/portal/session/dev-server/dev-command.d.ts +21 -0
- package/dist/portal/session/dev-server/dev-command.js +87 -12
- package/dist/portal/session/facts/departure-note.d.ts +22 -0
- package/dist/portal/session/facts/departure-note.js +47 -0
- package/dist/portal/session/facts/observed-state.d.ts +16 -18
- package/dist/portal/session/facts/observed-state.js +46 -3
- package/dist/portal/session/facts/session-replaced.d.ts +5 -0
- package/dist/portal/session/facts/session-replaced.js +5 -0
- package/dist/portal/session/first-run-wiring.d.ts +42 -0
- package/dist/portal/session/first-run-wiring.js +132 -0
- package/dist/portal/session/human/live-control.d.ts +9 -2
- package/dist/portal/session/human/live-control.js +12 -3
- package/dist/portal/session/human/notes-ledger.d.ts +20 -0
- package/dist/portal/session/human/notes-ledger.js +55 -0
- package/dist/portal/session/human/review-store.d.ts +12 -0
- package/dist/portal/session/human/review-store.js +18 -10
- package/dist/portal/session/live-control-tools.d.ts +0 -13
- package/dist/portal/session/live-control-tools.js +107 -13
- package/dist/portal/session/narration-args.d.ts +5 -0
- package/dist/portal/session/narration-args.js +17 -0
- package/dist/portal/session/no-session-diagnosis.d.ts +8 -1
- package/dist/portal/session/no-session-diagnosis.js +46 -9
- package/dist/portal/session/no-session-next-action.d.ts +31 -0
- package/dist/portal/session/no-session-next-action.js +159 -60
- package/dist/portal/session/no-session-watch.d.ts +14 -1
- package/dist/portal/session/no-session-watch.js +227 -17
- package/dist/portal/session/presence/session-lease.js +1 -1
- package/dist/portal/session/presence/session-mirror.js +3 -0
- package/dist/portal/session/recorded-gaps.d.ts +97 -0
- package/dist/portal/session/recorded-gaps.js +251 -0
- package/dist/portal/session/serving-directory.d.ts +27 -0
- package/dist/portal/session/serving-directory.js +45 -0
- package/dist/portal/session/session-health.d.ts +18 -0
- package/dist/portal/session/session-health.js +9 -1
- package/dist/portal/session/session-info.d.ts +8 -1
- package/dist/portal/session/session-info.js +8 -1
- package/dist/portal/session/session-manager.d.ts +39 -0
- package/dist/portal/session/session-manager.js +98 -11
- package/dist/portal/session/session-reaper.js +4 -1
- package/dist/portal/session/session-successor.d.ts +13 -0
- package/dist/portal/session/session-successor.js +1 -1
- package/dist/portal/session/session-tools.js +26 -3
- package/dist/portal/session/session.d.ts +22 -30
- package/dist/portal/session/session.js +81 -79
- package/dist/portal/session/timing/command-timeout.js +25 -1
- package/dist/portal/session/timing/wall-clock.d.ts +1 -1
- package/dist/portal/session/timing/wall-clock.js +1 -1
- package/dist/portal/session/zero-install-first-call.d.ts +31 -0
- package/dist/portal/session/zero-install-first-call.js +88 -0
- package/dist/start-options.d.ts +12 -0
- package/dist/start-wiring.d.ts +63 -0
- package/dist/start-wiring.js +169 -0
- package/dist/status-payload.d.ts +23 -1
- package/dist/status-payload.js +36 -1
- package/dist/surface/http-server.js +18 -2
- package/dist/surface/mcp/attach-memory.d.ts +1 -0
- package/dist/surface/mcp/attach-memory.js +12 -1
- package/dist/surface/mcp/mcp-proxy.d.ts +9 -0
- package/dist/surface/mcp/mcp-proxy.js +65 -13
- package/dist/surface/mcp/mcp.d.ts +34 -6
- package/dist/surface/mcp/mcp.js +61 -17
- package/dist/surface/mcp/proxy/drive-calls.d.ts +10 -0
- package/dist/surface/mcp/proxy/drive-calls.js +27 -0
- package/dist/surface/mcp/proxy/mcp-post-transport.js +5 -0
- package/dist/surface/mcp/server-instructions.d.ts +4 -2
- package/dist/surface/mcp/server-instructions.js +32 -14
- package/dist/surface/mcp/shared-params.js +2 -2
- package/dist/surface/mcp/surface-vocabulary.d.ts +2 -0
- package/dist/surface/mcp/surface-vocabulary.js +1 -0
- package/dist/surface/tools/account-tool.d.ts +22 -0
- package/dist/surface/tools/account-tool.js +157 -0
- package/dist/surface/tools/act/act-danger.d.ts +11 -0
- package/dist/surface/tools/act/act-danger.js +38 -1
- package/dist/surface/tools/act/act-observation.d.ts +33 -0
- package/dist/surface/tools/act/act-observation.js +57 -0
- package/dist/surface/tools/act/act-preflight.js +25 -2
- package/dist/surface/tools/act/act-target.js +8 -3
- package/dist/surface/tools/act/navigation/navigate-arrival.d.ts +8 -0
- package/dist/surface/tools/act/navigation/navigate-arrival.js +56 -2
- package/dist/surface/tools/act/resolve-target.d.ts +1 -1
- package/dist/surface/tools/act/resolve-target.js +18 -3
- package/dist/surface/tools/act/screen-request.d.ts +34 -0
- package/dist/surface/tools/act/screen-request.js +113 -0
- package/dist/surface/tools/act/sequence-grade.d.ts +8 -0
- package/dist/surface/tools/act/sequence-grade.js +13 -2
- package/dist/surface/tools/act/settle-in-flight.js +25 -3
- package/dist/surface/tools/act-sequence-tool.js +138 -29
- package/dist/surface/tools/act-tools.d.ts +0 -9
- package/dist/surface/tools/act-tools.js +71 -41
- package/dist/surface/tools/agent/app-notes-learning.d.ts +7 -0
- package/dist/surface/tools/agent/app-notes-learning.js +80 -0
- package/dist/surface/tools/agent/app-notes.d.ts +4 -0
- package/dist/surface/tools/agent/app-notes.js +48 -0
- package/dist/surface/tools/agent/build-staleness.d.ts +7 -0
- package/dist/surface/tools/agent/build-staleness.js +62 -0
- package/dist/surface/tools/agent/compact-envelope.d.ts +80 -0
- package/dist/surface/tools/agent/compact-envelope.js +374 -0
- package/dist/surface/tools/agent/for-the-agent.d.ts +12 -0
- package/dist/surface/tools/agent/for-the-agent.js +44 -0
- package/dist/surface/tools/agent/notices.d.ts +50 -0
- package/dist/surface/tools/agent/notices.js +152 -0
- package/dist/surface/tools/agent/reteach.d.ts +11 -0
- package/dist/surface/tools/agent/reteach.js +50 -0
- package/dist/surface/tools/args/alias-args.d.ts +5 -0
- package/dist/surface/tools/args/alias-args.js +10 -0
- package/dist/surface/tools/args/confirm-dangerous-arg.d.ts +6 -0
- package/dist/surface/tools/args/confirm-dangerous-arg.js +6 -0
- package/dist/surface/tools/assert/assert-source.d.ts +15 -0
- package/dist/surface/tools/assert/assert-source.js +40 -0
- package/dist/surface/tools/assert/assert-verdict.d.ts +1 -1
- package/dist/surface/tools/assert/assert-verdict.js +42 -17
- package/dist/surface/tools/browser-tools.js +51 -2
- package/dist/surface/tools/chat-drives.d.ts +101 -0
- package/dist/surface/tools/chat-drives.js +409 -0
- package/dist/surface/tools/coverage-tools.d.ts +2 -10
- package/dist/surface/tools/coverage-tools.js +2 -53
- package/dist/surface/tools/dynamic-tools.js +29 -1
- package/dist/surface/tools/empty-session-list.d.ts +51 -0
- package/dist/surface/tools/empty-session-list.js +120 -0
- package/dist/surface/tools/error-recovery.d.ts +14 -0
- package/dist/surface/tools/error-recovery.js +105 -8
- package/dist/surface/tools/explore-tools.d.ts +31 -1
- package/dist/surface/tools/explore-tools.js +438 -66
- package/dist/surface/tools/feedback-tools.d.ts +2 -3
- package/dist/surface/tools/feedback-tools.js +18 -3
- package/dist/surface/tools/gap-novelty.d.ts +3 -1
- package/dist/surface/tools/gap-novelty.js +8 -1
- package/dist/surface/tools/harness-explore.d.ts +118 -57
- package/dist/surface/tools/harness-explore.js +344 -292
- package/dist/surface/tools/harness-gate.d.ts +88 -0
- package/dist/surface/tools/harness-gate.js +235 -0
- package/dist/surface/tools/harness-hunt.d.ts +43 -0
- package/dist/surface/tools/harness-hunt.js +215 -0
- package/dist/surface/tools/harness-plan.d.ts +17 -0
- package/dist/surface/tools/harness-plan.js +38 -0
- package/dist/surface/tools/harness-script.d.ts +30 -0
- package/dist/surface/tools/harness-script.js +560 -0
- package/dist/surface/tools/harness-tab-guard.d.ts +5 -0
- package/dist/surface/tools/harness-tab-guard.js +27 -0
- package/dist/surface/tools/harness-toolset.d.ts +22 -1
- package/dist/surface/tools/harness-toolset.js +101 -7
- package/dist/surface/tools/human-notes.d.ts +16 -0
- package/dist/surface/tools/human-notes.js +27 -0
- package/dist/surface/tools/invoke-tool.d.ts +5 -2
- package/dist/surface/tools/invoke-tool.js +263 -85
- package/dist/surface/tools/lease-hint.js +26 -5
- package/dist/surface/tools/lease-permissions.d.ts +33 -0
- package/dist/surface/tools/lease-permissions.js +73 -0
- package/dist/surface/tools/lease-readiness.d.ts +38 -0
- package/dist/surface/tools/lease-readiness.js +57 -0
- package/dist/surface/tools/lease-seed.d.ts +49 -0
- package/dist/surface/tools/lease-seed.js +167 -0
- package/dist/surface/tools/lease-tools.d.ts +13 -24
- package/dist/surface/tools/lease-tools.js +146 -197
- package/dist/surface/tools/live-call-text.js +4 -4
- package/dist/surface/tools/merge-tools.js +42 -2
- package/dist/surface/tools/merged-name-redirect.js +4 -0
- package/dist/surface/tools/next-step.d.ts +29 -0
- package/dist/surface/tools/next-step.js +214 -0
- package/dist/surface/tools/observe-tools.js +45 -9
- package/dist/surface/tools/platform-moment.d.ts +72 -0
- package/dist/surface/tools/platform-moment.js +296 -0
- package/dist/surface/tools/query-hint-schema.d.ts +7 -0
- package/dist/surface/tools/query-hint-schema.js +10 -0
- package/dist/surface/tools/read-tools.js +71 -14
- package/dist/surface/tools/real-input-attempt.js +96 -13
- package/dist/surface/tools/reticle-result.d.ts +120 -0
- package/dist/surface/tools/reticle-result.js +364 -0
- package/dist/surface/tools/tool-kit.d.ts +83 -3
- package/dist/surface/tools/tool-kit.js +77 -7
- package/dist/surface/tools/tools.js +43 -59
- package/dist/telemetry/account-envelope.d.ts +7 -0
- package/dist/telemetry/account-envelope.js +61 -0
- package/dist/telemetry/agent-client.d.ts +15 -0
- package/dist/telemetry/agent-client.js +57 -0
- package/dist/telemetry/app-instrumented.js +9 -2
- package/dist/telemetry/argument-shape.d.ts +7 -0
- package/dist/telemetry/argument-shape.js +86 -1
- package/dist/telemetry/automation-hint.d.ts +2 -3
- package/dist/telemetry/automation-hint.js +33 -8
- package/dist/telemetry/cli-telemetry.js +7 -2
- package/dist/telemetry/daemon-telemetry.js +3 -0
- package/dist/telemetry/error-fingerprint.d.ts +10 -1
- package/dist/telemetry/error-fingerprint.js +61 -5
- package/dist/telemetry/feedback-cli.d.ts +0 -13
- package/dist/telemetry/feedback-cli.js +0 -77
- package/dist/telemetry/feedback.d.ts +13 -0
- package/dist/telemetry/feedback.js +183 -17
- package/dist/telemetry/harness-run.d.ts +18 -0
- package/dist/telemetry/harness-run.js +80 -0
- package/dist/telemetry/hud-events.d.ts +16 -0
- package/dist/telemetry/hud-events.js +27 -0
- package/dist/telemetry/hud-metrics.d.ts +29 -6
- package/dist/telemetry/hud-metrics.js +116 -25
- package/dist/telemetry/init-telemetry.js +2 -2
- package/dist/telemetry/install-source.d.ts +13 -25
- package/dist/telemetry/install-source.js +44 -3
- package/dist/telemetry/mcp-connection.d.ts +0 -14
- package/dist/telemetry/mcp-connection.js +5 -1
- package/dist/telemetry/onboarding-firsts.d.ts +32 -0
- package/dist/telemetry/onboarding-firsts.js +81 -6
- package/dist/telemetry/platform-linked.d.ts +5 -0
- package/dist/telemetry/platform-linked.js +32 -0
- package/dist/telemetry/project-profile.js +5 -3
- package/dist/telemetry/proxy-telemetry.js +4 -1
- package/dist/telemetry/session-metrics.d.ts +15 -4
- package/dist/telemetry/session-metrics.js +88 -52
- package/dist/telemetry/telemetry.d.ts +38 -2
- package/dist/telemetry/telemetry.js +144 -34
- package/dist/telemetry/verification-of.d.ts +3 -1
- package/dist/telemetry/verification-of.js +13 -4
- package/dist/wire-journal.d.ts +2 -2
- package/dist/wire-journal.js +20 -6
- package/docs/README.md +3 -3
- package/docs/actions.mdx +6 -3
- package/docs/adapters.md +1 -1
- package/docs/agent-cheatsheet.md +25 -28
- package/docs/architecture.md +5 -5
- package/docs/autodrive.md +33 -28
- package/docs/benchmarks.md +5 -5
- package/docs/best-practices.mdx +27 -9
- package/docs/capabilities.mdx +14 -16
- package/docs/cli/affected.mdx +1 -1
- package/docs/cli/cloud.mdx +54 -75
- package/docs/cli/doctor.mdx +14 -3
- package/docs/cli/drive.mdx +20 -14
- package/docs/cli/feedback.mdx +3 -3
- package/docs/cli/gate.mdx +7 -2
- package/docs/cli/help.mdx +50 -55
- package/docs/cli/init.mdx +43 -28
- package/docs/cli/license.mdx +12 -8
- package/docs/cli/mcp.mdx +4 -4
- package/docs/cli/open.mdx +3 -3
- package/docs/cli/report.mdx +4 -2
- package/docs/cli/restart.mdx +2 -2
- package/docs/cli/rollback.mdx +14 -8
- package/docs/cli/serve.mdx +4 -4
- package/docs/cli/setup.mdx +23 -0
- package/docs/cli/status.mdx +18 -5
- package/docs/cli/stop.mdx +67 -8
- package/docs/cli/try.mdx +62 -0
- package/docs/cli/update.mdx +4 -3
- package/docs/cli/verify.mdx +17 -6
- package/docs/cli/version.mdx +5 -4
- package/docs/cli.mdx +111 -42
- package/docs/debugging.md +3 -3
- package/docs/deploy-checks.md +1 -1
- package/docs/desktop.mdx +9 -3
- package/docs/enterprise.md +11 -10
- package/docs/environment.mdx +7 -8
- package/docs/faq.mdx +3 -3
- package/docs/first-drive.md +5 -4
- package/docs/flows.md +35 -27
- package/docs/for-agents.md +4 -5
- package/docs/frameworks.mdx +32 -21
- package/docs/getting-started.md +65 -61
- package/docs/human-control.md +16 -16
- package/docs/index.mdx +15 -42
- package/docs/install-agentic.mdx +22 -37
- package/docs/install-manual.mdx +23 -13
- package/docs/instrumentation.mdx +5 -3
- package/docs/integration-patterns.md +7 -7
- package/docs/license-activation.mdx +1 -1
- package/docs/multi-agent-testing.md +24 -6
- package/docs/packages/babel-plugin.mdx +4 -2
- package/docs/packages/browser.mdx +16 -10
- package/docs/packages/core.mdx +12 -5
- package/docs/packages/electron.mdx +3 -2
- package/docs/packages/engine.mdx +1 -1
- package/docs/packages/eslint-plugin.mdx +18 -12
- package/docs/packages/next.mdx +8 -7
- package/docs/packages/open-verification.mdx +1 -1
- package/docs/packages/server.mdx +5 -5
- package/docs/packages/tauri.mdx +9 -9
- package/docs/packages/test.mdx +4 -10
- package/docs/packages/vite-plugin.mdx +32 -4
- package/docs/packages.mdx +11 -15
- package/docs/platform-integration.md +6 -5
- package/docs/predicates.mdx +40 -24
- package/docs/quickstart.mdx +69 -30
- package/docs/required-checks.md +8 -7
- package/docs/reticle-manual.md +15 -5
- package/docs/skill-file.mdx +17 -79
- package/docs/skill-setup.md +9 -9
- package/docs/skill.md +200 -0
- package/docs/system-map.md +7 -7
- package/docs/telemetry.md +23 -25
- package/docs/testing.md +4 -4
- package/docs/token-efficiency.md +12 -12
- package/docs/tools/act-and-wait.mdx +9 -2
- package/docs/tools/act-sequence.mdx +6 -7
- package/docs/tools/act.mdx +2 -2
- package/docs/tools/assert.mdx +18 -17
- package/docs/tools/console.mdx +9 -9
- package/docs/tools/inspect.mdx +16 -7
- package/docs/tools/look.mdx +24 -0
- package/docs/tools/navigate.mdx +5 -3
- package/docs/tools/network.mdx +2 -2
- package/docs/tools/observe.mdx +6 -6
- package/docs/tools/overview.mdx +34 -33
- package/docs/tools/query.mdx +5 -5
- package/docs/tools/session-and-feedback.mdx +22 -13
- package/docs/tools/sessions.mdx +8 -8
- package/docs/tools/snapshot.mdx +6 -5
- package/docs/tools/state.mdx +9 -9
- package/docs/tools/tools-and-run.mdx +26 -24
- package/docs/tools/verify.mdx +28 -0
- package/docs/tools/wait-for.mdx +8 -4
- package/docs/troubleshooting.mdx +21 -6
- package/docs/usage.md +55 -46
- package/docs/use-cases.mdx +3 -3
- package/docs/vs-chrome-devtools-mcp.mdx +9 -6
- package/docs/vs-playwright-mcp.mdx +3 -1
- package/docs/what-is-recorded.md +17 -5
- package/docs/what-is-reticle.mdx +5 -3
- package/docs/why-reticle.mdx +1 -1
- package/package.json +9 -12
- package/dist/command/cli/demo/demo-page.d.ts +0 -78
- package/dist/command/cli/demo/demo-page.js +0 -241
- package/dist/command/cli/demo/demo-run.d.ts +0 -38
- package/dist/command/cli/demo/demo-run.js +0 -138
- package/dist/features/harness/driver.d.ts +0 -50
- package/dist/features/harness/driver.js +0 -236
- package/dist/features/harness/jev-driver.d.ts +0 -188
- package/dist/features/harness/jev-driver.js +0 -678
- package/dist/features/harness/openai-driver.d.ts +0 -58
- package/dist/features/harness/openai-driver.js +0 -206
- package/dist/judgement/hunt/hunt-report.d.ts +0 -49
- package/dist/judgement/hunt/hunt-report.js +0 -84
- package/dist/language/flows/buddy-status.d.ts +0 -25
- package/dist/language/flows/buddy-status.js +0 -32
- package/dist/language/flows/change/watch-batcher.d.ts +0 -18
- package/dist/language/flows/change/watch-batcher.js +0 -19
- package/dist/memory/cloud/harness-offer.d.ts +0 -44
- package/dist/memory/cloud/harness-offer.js +0 -145
- package/dist/memory/project/dir/fill-value-store.d.ts +0 -32
- package/dist/memory/project/dir/fill-value-store.js +0 -88
- package/dist/surface/tools/feature-capture.d.ts +0 -151
- package/dist/surface/tools/feature-capture.js +0 -235
- package/dist/surface/tools/tool-hit-rate.d.ts +0 -87
- package/dist/surface/tools/tool-hit-rate.js +0 -90
- package/dist/telemetry/harness-drive.d.ts +0 -4
- package/dist/telemetry/harness-drive.js +0 -35
- package/dist/telemetry/identify.d.ts +0 -22
- package/dist/telemetry/identify.js +0 -73
- package/docs/cli/capsules.mdx +0 -70
- package/docs/cli/hunt.mdx +0 -73
- package/docs/cli/identify.mdx +0 -76
- package/docs/cli/kill.mdx +0 -91
- package/docs/cli/watch.mdx +0 -62
- package/docs/local-registry.md +0 -143
|
@@ -13,6 +13,7 @@ import { fixturePortFor, seedFromStorageState, } from '../../portal/input/storag
|
|
|
13
13
|
import { mutationPortFor } from '../../portal/input/network-mutation.js';
|
|
14
14
|
import { z } from 'zod';
|
|
15
15
|
import { leaseNotConnectedHint } from './lease-hint.js';
|
|
16
|
+
import { probeLeaseAlive, tabHidden } from './lease-readiness.js';
|
|
16
17
|
import { probeSdkMarker } from './gaps/sdk-marker-probe.js';
|
|
17
18
|
import { observeWebDocument } from '../../portal/session/dev-server/served-document.js';
|
|
18
19
|
import { diagnoseObservedWebCsp } from '@reticlehq/init';
|
|
@@ -20,10 +21,13 @@ import { readProjectFramework, readProjectId } from '../../command/cli/ports/res
|
|
|
20
21
|
import { hasAnyAppConnectedBefore } from '../../memory/recall/prior/connection-memory.js';
|
|
21
22
|
import { AGENT_DRIVING_ELSEWHERE, AGENT_DRIVING_HERE_AGAIN, watchersToNotify, } from '../../portal/session/lease-visibility.js';
|
|
22
23
|
import { reticleStateHome } from '../../command/daemon/daemon.js';
|
|
23
|
-
import {
|
|
24
|
-
import {
|
|
24
|
+
import { claimArtifactRoot, dropArtifactRootClaim } from '../../memory/project/root-claims.js';
|
|
25
|
+
import { LeaseNotReadyReason, RETICLE_URL_PARAM, RETICLE_DEFAULT_PORT, SeedStorageSchema, } from '@reticlehq/core';
|
|
26
|
+
import { HudVisibility, ReticleTool, SESSION_HEALTH } from '@reticlehq/core';
|
|
27
|
+
import { HOST_STUB_NOTE } from './tool-kit.js';
|
|
25
28
|
import { asString } from '@reticlehq/core';
|
|
26
|
-
import {
|
|
29
|
+
import { chromiumPreflightRefusal } from '../../command/cli/doctor/browser/chromium-hint.js';
|
|
30
|
+
import { LEASE_PERMISSIONS_ARG, hintOf, notificationReadBack, parseLeasePermissions, permissionRefusal, refuseRegrant, } from './lease-permissions.js';
|
|
27
31
|
/**
|
|
28
32
|
* Everything the daemon already knows about why a leased tab might not have dialled in.
|
|
29
33
|
*
|
|
@@ -89,19 +93,23 @@ function originOf(url) {
|
|
|
89
93
|
const ALREADY_HELD_LEASE = 'you already hold a lease on this origin';
|
|
90
94
|
function alreadyHeldHint(sessionId, origin) {
|
|
91
95
|
return (`${ALREADY_HELD_LEASE} (${origin}): ${sessionId} — reused it rather than opening a second ` +
|
|
92
|
-
'tab, which would make every later call require sessionId.
|
|
96
|
+
'tab, which would make every later call require sessionId. It is still signed in as whoever ' +
|
|
97
|
+
'used it last (cookies and storage come with it): release it first for a fresh context or ' +
|
|
98
|
+
'another identity.');
|
|
93
99
|
}
|
|
94
100
|
/**
|
|
95
101
|
* Append Reticle identity params (__reticle_session, optional __reticle_project) to a URL so the app's own SDK
|
|
96
102
|
* adopts them on connect. Pure; falls back to plain concatenation if the URL can't be parsed.
|
|
97
103
|
*/
|
|
98
|
-
export function appendReticleParams(url, session, projectId) {
|
|
104
|
+
export function appendReticleParams(url, session, projectId, hud) {
|
|
99
105
|
try {
|
|
100
106
|
const u = new URL(url);
|
|
101
107
|
u.searchParams.set(RETICLE_URL_PARAM.SESSION, session);
|
|
102
108
|
if (projectId !== undefined && projectId.length > 0) {
|
|
103
109
|
u.searchParams.set(RETICLE_URL_PARAM.PROJECT, projectId);
|
|
104
110
|
}
|
|
111
|
+
if (hud !== undefined)
|
|
112
|
+
u.searchParams.set(RETICLE_URL_PARAM.HUD, hud);
|
|
105
113
|
return u.toString();
|
|
106
114
|
}
|
|
107
115
|
catch {
|
|
@@ -112,124 +120,8 @@ export function appendReticleParams(url, session, projectId) {
|
|
|
112
120
|
return `${url}${sep}${RETICLE_URL_PARAM.SESSION}=${encodeURIComponent(session)}${proj}`;
|
|
113
121
|
}
|
|
114
122
|
}
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
return text;
|
|
118
|
-
const escaped = value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
119
|
-
return text.replace(new RegExp(`(^|[^a-zA-Z0-9])${escaped}(?=$|[^a-zA-Z0-9])`, 'g'), `$1${REDACTED_VALUE}`);
|
|
120
|
-
}
|
|
121
|
-
/**
|
|
122
|
-
* Scrub known secret shapes and raw seedStorage values (cookies, localStorage, sessionStorage)
|
|
123
|
-
* from an error string before it reaches daemon logs, metrics, or MCP error responses.
|
|
124
|
-
*/
|
|
125
|
-
export function scrubSeedFromError(text, seed) {
|
|
126
|
-
let out = scrubKnownSecrets(text);
|
|
127
|
-
if (undefined !== seed && null !== seed && 'object' === typeof seed) {
|
|
128
|
-
const s = seed;
|
|
129
|
-
const cookies = s['cookies'];
|
|
130
|
-
if (undefined !== cookies && null !== cookies) {
|
|
131
|
-
if (Array.isArray(cookies)) {
|
|
132
|
-
for (const c of cookies) {
|
|
133
|
-
if (undefined !== c && null !== c && 'object' === typeof c) {
|
|
134
|
-
const val = c['value'];
|
|
135
|
-
if (undefined !== val && 'string' === typeof val) {
|
|
136
|
-
out = redactExactValue(out, val);
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
else if ('object' === typeof cookies) {
|
|
142
|
-
for (const v of Object.values(cookies)) {
|
|
143
|
-
if ('string' === typeof v) {
|
|
144
|
-
out = redactExactValue(out, v);
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
const local = s['local'];
|
|
150
|
-
if (undefined !== local && null !== local && 'object' === typeof local) {
|
|
151
|
-
for (const v of Object.values(local)) {
|
|
152
|
-
if ('string' === typeof v) {
|
|
153
|
-
out = redactExactValue(out, v);
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
const session = s['session'];
|
|
158
|
-
if (undefined !== session && null !== session && 'object' === typeof session) {
|
|
159
|
-
for (const v of Object.values(session)) {
|
|
160
|
-
if ('string' === typeof v) {
|
|
161
|
-
out = redactExactValue(out, v);
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
return out;
|
|
167
|
-
}
|
|
168
|
-
/** True for a Playwright `storageState()` export (`{ origins: [...] }`), not our seed shape. */
|
|
169
|
-
function looksLikeStorageStateExport(seed) {
|
|
170
|
-
return Array.isArray(seed?.origins);
|
|
171
|
-
}
|
|
172
|
-
/**
|
|
173
|
-
* Turn a raw navigation failure (Playwright's `page.goto: net::ERR_… at <url>\nCall log:…`, often
|
|
174
|
-
* with ANSI codes) into a short, clean reason — so the agent/user sees "is the app running?" instead
|
|
175
|
-
* of an internals-leaking wall of text.
|
|
176
|
-
*/
|
|
177
|
-
export function cleanNavError(err, seed) {
|
|
178
|
-
const rawMsg = err instanceof Error ? err.message : String(err);
|
|
179
|
-
const msg = scrubSeedFromError(rawMsg, seed);
|
|
180
|
-
// Strip ANSI color codes (ESC[…m) Playwright emits — built via fromCharCode to keep the
|
|
181
|
-
// control character out of a regex literal (no-control-regex).
|
|
182
|
-
const ansi = new RegExp(`${String.fromCharCode(27)}\\[[0-9;]*m`, 'g');
|
|
183
|
-
const firstLine = (msg.split('\n')[0] ?? msg).replace(ansi, '');
|
|
184
|
-
const netCode = /net::[A-Z_]+/.exec(firstLine);
|
|
185
|
-
if (netCode !== null)
|
|
186
|
-
return netCode[0];
|
|
187
|
-
if (/timeout/i.test(firstLine))
|
|
188
|
-
return 'navigation timed out';
|
|
189
|
-
return firstLine
|
|
190
|
-
.replace(/^page\.goto:\s*/, '')
|
|
191
|
-
.replace(/\s+at\s+https?:\/\/\S+.*$/, '')
|
|
192
|
-
.trim()
|
|
193
|
-
.slice(0, 100);
|
|
194
|
-
}
|
|
195
|
-
/**
|
|
196
|
-
* Determine if a required seedStorage application precondition failed.
|
|
197
|
-
*
|
|
198
|
-
* Checks strong signals:
|
|
199
|
-
* 1. HTTP 401/403 status on the initial navigation.
|
|
200
|
-
* 2. Cross-origin redirect when localStorage or sessionStorage was requested (skipped by origin-scoping).
|
|
201
|
-
* 3. Clear redirect to an authentication/login endpoint when the requested URL was not a login page.
|
|
202
|
-
*
|
|
203
|
-
* Normal app redirects (e.g. / → /dashboard) are valid and return undefined.
|
|
204
|
-
*/
|
|
205
|
-
export function evaluateSeedPrecondition(requestedUrl, actualUrl, seed, navStatus) {
|
|
206
|
-
if (401 === navStatus || 403 === navStatus) {
|
|
207
|
-
return `HTTP ${navStatus} returned on initial seeded navigation to ${requestedUrl}`;
|
|
208
|
-
}
|
|
209
|
-
if (actualUrl === undefined || '' === actualUrl.trim())
|
|
210
|
-
return undefined;
|
|
211
|
-
let reqParsed;
|
|
212
|
-
let actParsed;
|
|
213
|
-
try {
|
|
214
|
-
reqParsed = new URL(requestedUrl);
|
|
215
|
-
actParsed = new URL(actualUrl);
|
|
216
|
-
}
|
|
217
|
-
catch {
|
|
218
|
-
return undefined;
|
|
219
|
-
}
|
|
220
|
-
// Cross-origin redirect when local or session storage was requested
|
|
221
|
-
const hasStorage = (undefined !== seed.local && 0 < Object.keys(seed.local).length) ||
|
|
222
|
-
(undefined !== seed.session && 0 < Object.keys(seed.session).length);
|
|
223
|
-
if (hasStorage && reqParsed.origin !== actParsed.origin) {
|
|
224
|
-
return `seeded storage precondition not established: cross-origin redirect from ${reqParsed.origin} to ${actParsed.origin} skipped origin-scoped storage injection`;
|
|
225
|
-
}
|
|
226
|
-
// Clear redirect to an authentication/login endpoint when the requested URL was not a login page
|
|
227
|
-
const isAuthPath = (pathname) => /(?:^|\/)(?:login|signin|sign-in|auth\/login|auth\/signin|session\/new)(?:$|\/)/i.test(pathname);
|
|
228
|
-
if (!isAuthPath(reqParsed.pathname) && isAuthPath(actParsed.pathname)) {
|
|
229
|
-
return `seeded authentication precondition not established: redirected from ${reqParsed.pathname} to login page (${actParsed.pathname})`;
|
|
230
|
-
}
|
|
231
|
-
return undefined;
|
|
232
|
-
}
|
|
123
|
+
export { cleanNavError, evaluateSeedPrecondition, scrubSeedFromError } from './lease-seed.js';
|
|
124
|
+
import { evaluateSeedPrecondition, looksLikeStorageStateExport, navFailureMessage, scrubSeedFromError, } from './lease-seed.js';
|
|
233
125
|
/** A fresh, collision-resistant lease id. Uses crypto at the I/O boundary (not pure logic). */
|
|
234
126
|
function newLeaseId() {
|
|
235
127
|
const uuid = 'function' === typeof globalThis.crypto?.randomUUID
|
|
@@ -300,46 +192,6 @@ function sessionParamOf(url) {
|
|
|
300
192
|
}
|
|
301
193
|
const LEASE_READY_ATTEMPTS = 100;
|
|
302
194
|
const LEASE_READY_POLL_MS = 100;
|
|
303
|
-
/**
|
|
304
|
-
* How long a liveness probe waits for the tab to say anything at all.
|
|
305
|
-
*
|
|
306
|
-
* Short on purpose. This is not "finish the work", it is "are you there" — a page executing
|
|
307
|
-
* JavaScript answers a no-argument command in single-digit milliseconds, and a wedged one is not
|
|
308
|
-
* going to answer in two seconds either.
|
|
309
|
-
*/
|
|
310
|
-
const LEASE_PROBE_TIMEOUT_MS = 1_500;
|
|
311
|
-
/**
|
|
312
|
-
* Does this tab still answer?
|
|
313
|
-
*
|
|
314
|
-
* PRESENCE IS NOT LIVENESS. The sessions map still holds a tab that is attached, streaming events,
|
|
315
|
-
* and answering nothing, so `ready` read off a row in that map hands back a lease that `snapshot`,
|
|
316
|
-
* `state` and `console` then reject (#692). It has to mean the tab replied.
|
|
317
|
-
*
|
|
318
|
-
* ANY reply counts, including one that reports the command failed. The question is whether the SDK
|
|
319
|
-
* answers at all, not what it says — so an SDK too old to know the command replies
|
|
320
|
-
* `unknown command '…'`, and that is proof. Only the absence of a reply is evidence of absence:
|
|
321
|
-
* `PendingCommands.track` REJECTS on timeout and on a dropped socket, and resolves on every real
|
|
322
|
-
* answer, so the two cases are already separated for us.
|
|
323
|
-
*
|
|
324
|
-
* `CAPABILITIES` is the probe because it takes no arguments and returns a small fixed list. No new
|
|
325
|
-
* wire command is introduced: this rides an existing round trip.
|
|
326
|
-
*
|
|
327
|
-
* Fails OPEN. A registry entry with no `command` is a shape this code did not put there, and
|
|
328
|
-
* turning a lease that works into a refusal over a probe that could not run would be a worse
|
|
329
|
-
* failure than the one being fixed.
|
|
330
|
-
*/
|
|
331
|
-
async function probeLeaseAlive(session, timeoutMs = LEASE_PROBE_TIMEOUT_MS) {
|
|
332
|
-
const send = session?.command;
|
|
333
|
-
if (send === undefined)
|
|
334
|
-
return true;
|
|
335
|
-
try {
|
|
336
|
-
await send.call(session, ReticleCommand.CAPABILITIES, {}, timeoutMs);
|
|
337
|
-
return true;
|
|
338
|
-
}
|
|
339
|
-
catch {
|
|
340
|
-
return false;
|
|
341
|
-
}
|
|
342
|
-
}
|
|
343
195
|
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
344
196
|
/**
|
|
345
197
|
* Poll until the leased tab's SDK has actually registered on the bridge, so the sessionId we return
|
|
@@ -428,7 +280,7 @@ export function hasOriginLock(origin) {
|
|
|
428
280
|
}
|
|
429
281
|
export const LEASE_ACQUIRE_TOOL = {
|
|
430
282
|
name: ReticleTool.LEASE_ACQUIRE,
|
|
431
|
-
description: 'Lease a fresh isolated
|
|
283
|
+
description: 'Lease a fresh isolated browser context from the shared pool (shown or hidden as the daemon was started; `headed: true` forces a window) and navigate it to the app URL (the app must already be running; one with no Reticle SDK gets one supplied, reported as zeroInstall). If this origin is already leased and still connected, this returns THAT session rather than minting a second tab — a second acquire on the same origin poisons default session resolution. Returns the sessionId the leased tab registers — pass it to other tools. The pool keeps all leases in ONE browser and caps concurrency; if at capacity this waits for a free slot. Release with reticle_lease{action:"release"} when the flow is done. PREFER AN ALREADY-OPEN TAB: if reticle_sessions lists a non-leased session for this app, drive THAT instead — a lease is invisible to the person watching the app, whose HUD lives in their own tab, and a tab flagged hidden/throttled is often still driveable. Lease for isolation you actually need (a second identity, a clean context, parallel flows) or when driving the open tab has failed — this call answers with `preferExisting` when a live tab was available.',
|
|
432
284
|
inputSchema: {
|
|
433
285
|
url: z
|
|
434
286
|
.string()
|
|
@@ -437,22 +289,51 @@ export const LEASE_ACQUIRE_TOOL = {
|
|
|
437
289
|
.string()
|
|
438
290
|
.optional()
|
|
439
291
|
.describe('Stable project id to stamp on the leased tab so the agent can scope to it.'),
|
|
440
|
-
seedStorage: SeedStorageSchema.optional().describe('Initial storage state (
|
|
292
|
+
seedStorage: SeedStorageSchema.optional().describe('Initial storage state (local, session and cookies) to seed before the first navigation (e.g. `seedStorage: { local: { token: "..." } }` to start already authenticated).'),
|
|
293
|
+
initScript: z
|
|
294
|
+
.string()
|
|
295
|
+
.optional()
|
|
296
|
+
.describe("JavaScript installed in the tab BEFORE any of the page's own scripts run. Use it for TEST DOUBLES of the host bindings a desktop shell injects — Wails `window.go.*`, Tauri `window.runtime`/`__TAURI_INTERNALS__`, an Electron preload object — so a view that calls them on mount is driven against the stub instead of throwing. It stays on for this lease only, and it is disposed with the lease. Every verdict on this lease carries a note that a stub was installed, so a green is never read as one against the real shell."),
|
|
297
|
+
headed: z
|
|
298
|
+
.boolean()
|
|
299
|
+
.optional()
|
|
300
|
+
.describe('Open it in a browser window somebody can watch, instead of headless.'),
|
|
301
|
+
ignoreHTTPSErrors: z
|
|
302
|
+
.boolean()
|
|
303
|
+
.optional()
|
|
304
|
+
.describe('Accept a self-signed or mkcert certificate on an https dev server, for this lease only. Off by default.'),
|
|
305
|
+
hud: z
|
|
306
|
+
.enum([HudVisibility.SHOWN, HudVisibility.HIDDEN, HudVisibility.REMOVED])
|
|
307
|
+
.optional()
|
|
308
|
+
.describe('How the HUD starts on the page: shown (default), hidden, or removed.'),
|
|
309
|
+
permissions: LEASE_PERMISSIONS_ARG,
|
|
310
|
+
root: z
|
|
311
|
+
.string()
|
|
312
|
+
.optional()
|
|
313
|
+
.describe("Absolute path of the .reticle folder this lease's runs belong in — the caller's project. Without it, the page's project id decides, and a page with none lands in ~/.reticle/unmatched, which nothing syncs."),
|
|
441
314
|
},
|
|
442
315
|
outputSchema: {
|
|
443
316
|
sessionId: z.string(),
|
|
444
317
|
url: z.string(),
|
|
445
318
|
ready: z
|
|
446
319
|
.boolean()
|
|
447
|
-
.describe('Whether the leased tab is connected AND answering.
|
|
320
|
+
.describe('Whether the leased tab is connected AND answering. It is NOT a claim that the app has hydrated, so an act can miss: make the first act reticle_act_and_wait with an `until`, or reticle_assert { action: "wait" }. Empty reads may mean not hydrated. False ⇒ read notReadyReason.'),
|
|
448
321
|
zeroInstall: z
|
|
449
322
|
.boolean()
|
|
450
323
|
.optional()
|
|
451
324
|
.describe('Present when this app ships no Reticle SDK and the lease supplied one. Verdicts work on the DOM, network, console and routes; there is no framework adapter, so no component state and no source file:line. Install with `npx @reticlehq/server init` for those.'),
|
|
325
|
+
hostStub: z
|
|
326
|
+
.string()
|
|
327
|
+
.optional()
|
|
328
|
+
.describe('Present when this leased tab runs an init script stubbing the bindings a desktop shell injects. Verdicts on this lease are about the app with that stub, not about the real shell.'),
|
|
452
329
|
notReadyReason: z
|
|
453
|
-
.enum([
|
|
330
|
+
.enum([
|
|
331
|
+
LeaseNotReadyReason.SDK_NEVER_DIALLED,
|
|
332
|
+
LeaseNotReadyReason.SDK_STOPPED_ANSWERING,
|
|
333
|
+
LeaseNotReadyReason.TAB_HIDDEN,
|
|
334
|
+
])
|
|
454
335
|
.optional()
|
|
455
|
-
.describe('Present only when ready is false. sdk_never_dialled ⇒ nothing connected within the wait, so check the install (the app may not embed @reticlehq/core). sdk_stopped_answering ⇒ an SDK did connect and has stopped replying, so the tab is wedged and needs recovering, not reinstalling.'),
|
|
336
|
+
.describe('Present only when ready is false. sdk_never_dialled ⇒ nothing connected within the wait, so check the install (the app may not embed @reticlehq/core). sdk_stopped_answering ⇒ an SDK did connect and has stopped replying, so the tab is wedged and needs recovering, not reinstalling. tab_hidden ⇒ the SDK answers but its tab is hidden, so timers and animations are throttled and nothing on it verifies; bring the tab to the front, or release and re-acquire.'),
|
|
456
337
|
expiresInMs: z
|
|
457
338
|
.number()
|
|
458
339
|
.describe('Milliseconds until this lease expires if untouched. Each tool call that targets this session resets the clock. Plan your work to finish or re-acquire before this runs out.'),
|
|
@@ -487,12 +368,18 @@ export const LEASE_ACQUIRE_TOOL = {
|
|
|
487
368
|
// fine. Say the real thing at the first refusal instead. The phrasing carries "Chromium is not
|
|
488
369
|
// installed" so error-recovery routes it to the NO_POOL fix (install + drive a human tab).
|
|
489
370
|
if (deps.browserProbe !== undefined) {
|
|
490
|
-
const
|
|
491
|
-
if (
|
|
492
|
-
throw new Error(
|
|
493
|
-
}
|
|
371
|
+
const refusal = chromiumPreflightRefusal(await deps.browserProbe());
|
|
372
|
+
if (refusal !== undefined)
|
|
373
|
+
throw new Error(refusal);
|
|
494
374
|
}
|
|
495
375
|
const projectId = asString(args['projectId']);
|
|
376
|
+
const root = asString(args['root']);
|
|
377
|
+
const headed = true === args['headed'];
|
|
378
|
+
const hud = Object.values(HudVisibility).find((v) => v === args['hud']);
|
|
379
|
+
const permissions = parseLeasePermissions(args['permissions']);
|
|
380
|
+
// The stub of the shell bindings, when the caller supplied one. Installed by the pool before
|
|
381
|
+
// the first navigation, so it is already defined when the app's first module runs.
|
|
382
|
+
const initScript = asString(args['initScript']);
|
|
496
383
|
const seedStorageArg = args['seedStorage'];
|
|
497
384
|
let validatedSeed;
|
|
498
385
|
if (seedStorageArg !== undefined) {
|
|
@@ -526,10 +413,33 @@ export const LEASE_ACQUIRE_TOOL = {
|
|
|
526
413
|
await priorLock.catch(() => undefined);
|
|
527
414
|
}
|
|
528
415
|
try {
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
416
|
+
// Only a lease THIS caller took: another agent's tab is never reused or released (#1226).
|
|
417
|
+
// A window asked for is never answered with the headless tab on that origin, nor the reverse.
|
|
418
|
+
// A held lease that already runs the SAME stub is exactly what the caller asked for, so it is
|
|
419
|
+
// left alone and reused below — releasing it would throw away the tab, and everything loaded
|
|
420
|
+
// in it, for nothing. A lease with no stub, or with a different one, is released FIRST instead:
|
|
421
|
+
// an init script has to exist before the page's own scripts run, which a loaded page cannot
|
|
422
|
+
// do, and the resolve below then finds nothing and mints a fresh context with the stub. A
|
|
423
|
+
// lease of the other kind is left alone, exactly as it is when a window was asked for.
|
|
424
|
+
const heldForStub = origin === undefined ? undefined : pool.leaseIdOnOrigin(origin, deps.attachId);
|
|
425
|
+
if (initScript !== undefined &&
|
|
426
|
+
heldForStub !== undefined &&
|
|
427
|
+
pool.isHeaded(heldForStub) === headed &&
|
|
428
|
+
pool.hostStubScript?.(heldForStub) !== initScript) {
|
|
429
|
+
await pool.release(heldForStub);
|
|
430
|
+
}
|
|
431
|
+
const held = origin === undefined ? undefined : pool.leaseIdOnOrigin(origin, deps.attachId);
|
|
432
|
+
const existing = held !== undefined && pool.isHeaded(held) === headed ? held : undefined;
|
|
433
|
+
// A context's certificate setting is fixed when it is made, so an explicit request for the
|
|
434
|
+
// other one cannot be answered by the held lease: handing it back would keep checks off after
|
|
435
|
+
// `false`, or keep a local certificate refused after `true` (#1255). Omitted keeps the lease.
|
|
436
|
+
const certAsked = args['ignoreHTTPSErrors'];
|
|
437
|
+
const certMismatch = existing !== undefined &&
|
|
438
|
+
'boolean' === typeof certAsked &&
|
|
439
|
+
pool.ignoresHTTPSErrors(existing) !== certAsked;
|
|
440
|
+
if ((validatedSeed !== undefined || certMismatch) && existing !== undefined) {
|
|
441
|
+
// Seeding or a different certificate setting asked for: release its own context so the new
|
|
442
|
+
// lease starts with what was asked.
|
|
533
443
|
await pool.release(existing);
|
|
534
444
|
}
|
|
535
445
|
else if (existing !== undefined && origin !== undefined) {
|
|
@@ -546,23 +456,33 @@ export const LEASE_ACQUIRE_TOOL = {
|
|
|
546
456
|
// A no-op when the id resolved to itself; load-bearing when it did not, because every later
|
|
547
457
|
// touch and release arrives under the id being handed back here.
|
|
548
458
|
pool.alias(resolved, existing);
|
|
459
|
+
refuseRegrant(pool, existing, permissions);
|
|
549
460
|
pool.touch(existing);
|
|
550
461
|
// Probed only HERE, never on the mint path below. There, the readiness wait resolved
|
|
551
462
|
// moments ago and IS the liveness evidence; on reuse the last evidence may be minutes
|
|
552
463
|
// old, or there may be none at all — `unresponsive` is set by past commands failing, and
|
|
553
464
|
// its own contract says absence means "answering, OR NOT ASKED YET". So the happy path of
|
|
554
465
|
// a first acquire pays nothing for this.
|
|
555
|
-
const
|
|
466
|
+
const reusedSession = deps.sessions.get(resolved);
|
|
467
|
+
const alive = await probeLeaseAlive(reusedSession);
|
|
468
|
+
const reuseReason = !alive
|
|
469
|
+
? LeaseNotReadyReason.SDK_STOPPED_ANSWERING
|
|
470
|
+
: tabHidden(reusedSession)
|
|
471
|
+
? LeaseNotReadyReason.TAB_HIDDEN
|
|
472
|
+
: undefined;
|
|
556
473
|
return {
|
|
557
474
|
sessionId: resolved,
|
|
558
475
|
url,
|
|
559
|
-
ready:
|
|
560
|
-
...(
|
|
476
|
+
ready: reuseReason === undefined,
|
|
477
|
+
...(reuseReason === undefined ? {} : { notReadyReason: reuseReason }),
|
|
561
478
|
reused: true,
|
|
562
479
|
expiresInMs: pool.leaseTtlMs(),
|
|
563
480
|
leased: pool.activeCount(),
|
|
564
481
|
queued: pool.queuedCount(),
|
|
565
482
|
hint: alreadyHeldHint(resolved, origin),
|
|
483
|
+
// Asked of the pool, not remembered here: the stub was installed when THIS lease was
|
|
484
|
+
// minted, and the caller reusing it now may be seeing it for the first time.
|
|
485
|
+
...(true === pool.stubInstalled?.(existing) ? { hostStub: HOST_STUB_NOTE } : {}),
|
|
566
486
|
...(alreadyOpen === undefined
|
|
567
487
|
? {}
|
|
568
488
|
: { preferExisting: { sessionId: alreadyOpen, note: PREFER_EXISTING_NOTE } }),
|
|
@@ -574,21 +494,32 @@ export const LEASE_ACQUIRE_TOOL = {
|
|
|
574
494
|
await pool.release(existing);
|
|
575
495
|
}
|
|
576
496
|
const sessionId = newLeaseId();
|
|
577
|
-
|
|
497
|
+
// Before the page can dial in: the session is stamped with its root the moment it registers.
|
|
498
|
+
if (root !== undefined)
|
|
499
|
+
claimArtifactRoot(sessionId, root);
|
|
500
|
+
const navUrl = appendReticleParams(url, sessionId, projectId, hud);
|
|
578
501
|
let lease;
|
|
579
502
|
try {
|
|
580
503
|
lease = await pool.acquire(navUrl, {
|
|
581
504
|
sessionId,
|
|
505
|
+
...(headed ? { headed } : {}),
|
|
506
|
+
...(deps.attachId === undefined ? {} : { owner: deps.attachId }),
|
|
582
507
|
...(validatedSeed !== undefined ? { seedStorage: validatedSeed } : {}),
|
|
508
|
+
...(initScript !== undefined ? { initScript } : {}),
|
|
509
|
+
...(permissions !== undefined ? { permissions } : {}),
|
|
510
|
+
...(true === args['ignoreHTTPSErrors'] ? { ignoreHTTPSErrors: true } : {}),
|
|
583
511
|
});
|
|
584
512
|
}
|
|
585
513
|
catch (err) {
|
|
514
|
+
const refusal = permissionRefusal(err);
|
|
515
|
+
if (refusal !== undefined)
|
|
516
|
+
throw refusal;
|
|
586
517
|
if (err instanceof Error && err.message.startsWith('Storage seeding failed')) {
|
|
587
518
|
throw new Error(scrubSeedFromError(err.message, validatedSeed));
|
|
588
519
|
}
|
|
589
520
|
// A raw page.goto failure is noisy and leaks the internal URL params — surface a clean,
|
|
590
|
-
// actionable message instead.
|
|
591
|
-
throw new Error(
|
|
521
|
+
// actionable message instead, one that tells a slow first compile from a missing app.
|
|
522
|
+
throw new Error(navFailureMessage(url, err, validatedSeed));
|
|
592
523
|
}
|
|
593
524
|
// Wait for the leased tab's SDK to connect so the returned sessionId is usable right away.
|
|
594
525
|
// Resolved rather than assumed: an app that names its own session registers under that name,
|
|
@@ -616,15 +547,21 @@ export const LEASE_ACQUIRE_TOOL = {
|
|
|
616
547
|
tellWatchers(deps, projectId, AGENT_DRIVING_ELSEWHERE);
|
|
617
548
|
// ready means the SDK dialled in — not that contracts match. Carry the skew warning on acquire
|
|
618
549
|
// so the agent does not learn it only after a CDP tool invents a closed page (#688).
|
|
550
|
+
const mintReason = !ready
|
|
551
|
+
? LeaseNotReadyReason.SDK_NEVER_DIALLED
|
|
552
|
+
: tabHidden(session)
|
|
553
|
+
? LeaseNotReadyReason.TAB_HIDDEN
|
|
554
|
+
: undefined;
|
|
619
555
|
const versionSkew = registeredId === undefined ? undefined : deps.sessions.get(registeredId)?.versionSkew;
|
|
620
556
|
return {
|
|
621
557
|
sessionId: registeredId ?? lease.sessionId,
|
|
622
558
|
url,
|
|
623
|
-
ready,
|
|
559
|
+
ready: mintReason === undefined,
|
|
624
560
|
// The other half of the pair. `ready: false` carried two opposite situations under one
|
|
625
561
|
// word: no SDK ever dialled in (look at the install) versus one dialled in and stopped
|
|
626
|
-
// answering (recover the tab). They want different next actions, so they get names
|
|
627
|
-
|
|
562
|
+
// answering (recover the tab). They want different next actions, so they get names — and so
|
|
563
|
+
// does a third: dialled in and answering, but hidden, so nothing on it verifies (#1351).
|
|
564
|
+
...(mintReason === undefined ? {} : { notReadyReason: mintReason }),
|
|
628
565
|
...(zeroInstall ? { zeroInstall: true } : {}),
|
|
629
566
|
expiresInMs: pool.leaseTtlMs(),
|
|
630
567
|
leased: pool.activeCount(),
|
|
@@ -638,9 +575,10 @@ export const LEASE_ACQUIRE_TOOL = {
|
|
|
638
575
|
},
|
|
639
576
|
}),
|
|
640
577
|
...(versionSkew === undefined ? {} : { versionSkew }),
|
|
641
|
-
...(
|
|
642
|
-
|
|
643
|
-
|
|
578
|
+
...(initScript === undefined ? {} : { hostStub: HOST_STUB_NOTE }),
|
|
579
|
+
...hintOf(ready
|
|
580
|
+
? undefined
|
|
581
|
+
: await notConnectedHint(deps, url, pool.dialFailureUrl?.(lease.sessionId)), ready ? await notificationReadBack(pool, lease.sessionId, permissions) : undefined),
|
|
644
582
|
};
|
|
645
583
|
}
|
|
646
584
|
finally {
|
|
@@ -680,17 +618,28 @@ const LEASE_RELEASE_TOOL = {
|
|
|
680
618
|
if (sessionId === undefined || 0 === sessionId.length) {
|
|
681
619
|
throw new Error('reticle_lease{action:"release"} requires a sessionId');
|
|
682
620
|
}
|
|
683
|
-
|
|
684
|
-
// ask which project it belonged to.
|
|
685
|
-
const projectId = deps.sessions.get(sessionId)?.projectId;
|
|
686
|
-
await pool.release(sessionId);
|
|
687
|
-
// Only once the LAST lease is gone. Announcing "live again" while another lease still drives
|
|
688
|
-
// would be a lie, and a HUD that says the wrong thing is worse than one that says nothing.
|
|
689
|
-
if (0 === pool.activeCount())
|
|
690
|
-
tellWatchers(deps, projectId, AGENT_DRIVING_HERE_AGAIN);
|
|
691
|
-
return { released: true, leased: pool.activeCount() };
|
|
621
|
+
return { released: true, leased: await releaseLease(deps, pool, sessionId) };
|
|
692
622
|
},
|
|
693
623
|
};
|
|
624
|
+
/**
|
|
625
|
+
* Release one lease and everything that hangs off it. Returns how many leases are still held.
|
|
626
|
+
*
|
|
627
|
+
* Shared with `reticle_session { action: "end" }`: an ended session that kept its lease stayed
|
|
628
|
+
* connected until the reaper took it, and every id-less call from the next agent was refused as
|
|
629
|
+
* ambiguous in the meantime.
|
|
630
|
+
*/
|
|
631
|
+
export async function releaseLease(deps, pool, sessionId) {
|
|
632
|
+
// Read the project BEFORE releasing: afterwards the session is gone and there is nothing to
|
|
633
|
+
// ask which project it belonged to.
|
|
634
|
+
const projectId = deps.sessions.get(sessionId)?.projectId;
|
|
635
|
+
await pool.release(sessionId);
|
|
636
|
+
dropArtifactRootClaim(sessionId);
|
|
637
|
+
// Only once the LAST lease is gone. Announcing "live again" while another lease still drives
|
|
638
|
+
// would be a lie, and a HUD that says the wrong thing is worse than one that says nothing.
|
|
639
|
+
if (0 === pool.activeCount())
|
|
640
|
+
tellWatchers(deps, projectId, AGENT_DRIVING_HERE_AGAIN);
|
|
641
|
+
return pool.activeCount();
|
|
642
|
+
}
|
|
694
643
|
/**
|
|
695
644
|
* What to say when a lease was taken while a real tab was already open.
|
|
696
645
|
*
|
|
@@ -42,13 +42,13 @@ const NO_TOOL_EQUIVALENT = [
|
|
|
42
42
|
// hint used to put `action` and `url` beside `tool`, which reticle_run refuses, and a `[^}]*\}`
|
|
43
43
|
// body stopped at the inner brace and left ` }` behind once the hint was corrected.
|
|
44
44
|
pattern: /`?reticle_run\s*\{\s*tool:\s*\\?"reticle_lease\\?"(?:[^{}]|\{[^{}]*\})*\}`?(\s*\([^)]*\))?(\s*[-\u2014]+\s*reticle_lease is[^.]*\.)?/g,
|
|
45
|
-
instead: 'the CLI: `
|
|
45
|
+
instead: 'the CLI: `npx @reticlehq/server open <url>` (a human can equivalently run `npx @reticlehq/server drive <url>`)',
|
|
46
46
|
},
|
|
47
47
|
{
|
|
48
48
|
needs: [ReticleTool.LEASE],
|
|
49
49
|
// The bare cross-reference, left behind once the call above is gone.
|
|
50
50
|
pattern: /\breticle_lease\s*\{[^}]*\}/g,
|
|
51
|
-
instead: '`
|
|
51
|
+
instead: '`npx @reticlehq/server open <url>`',
|
|
52
52
|
},
|
|
53
53
|
{
|
|
54
54
|
needs: [ReticleTool.FLOW],
|
|
@@ -80,8 +80,8 @@ const NO_TOOL_EQUIVALENT = [
|
|
|
80
80
|
* every session, and the longer two-route version cost 67 bytes there against a budget measured
|
|
81
81
|
* in whole-session terms — for advice that is read once, on a first run.
|
|
82
82
|
*
|
|
83
|
-
* `explore`
|
|
84
|
-
* the same breath (
|
|
83
|
+
* `explore` runs on the platform and says so itself when it is not linked, naming the fallback in
|
|
84
|
+
* the same breath (drive the journey yourself with the MCP tools). That
|
|
85
85
|
* error is now recognised as ours, so the reader who hits it gets the next step instead of an
|
|
86
86
|
* invitation to file a defect report. One hop, and every hop is honest.
|
|
87
87
|
*/
|
|
@@ -1,6 +1,34 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
+
import { allowParamValues } from '../../telemetry/argument-shape.js';
|
|
2
3
|
/** The field the merged tool dispatches on. A member may not declare one of its own — see below. */
|
|
3
4
|
const DISCRIMINATOR = 'action';
|
|
5
|
+
/**
|
|
6
|
+
* Keys a member may receive without declaring them. `sessionId` is pinned onto the arguments by the
|
|
7
|
+
* dispatch routes (`reticle_run`, the harness toolset) whatever the member, so refusing it would
|
|
8
|
+
* refuse the routes themselves.
|
|
9
|
+
*/
|
|
10
|
+
const SHARED_KEYS = new Set(['sessionId']);
|
|
11
|
+
/**
|
|
12
|
+
* The refusal for keys another action of this tool takes (#1536).
|
|
13
|
+
*
|
|
14
|
+
* The SDK checks unknown keys against the UNION of every action's parameters, so a key that belongs
|
|
15
|
+
* to a sibling action passed, reached a handler that does not read it, and was dropped:
|
|
16
|
+
* `verify { action: "change", names }` replayed every affected flow, and `look { action: "page",
|
|
17
|
+
* limit }` returned the whole tree. Same words as the unknown-key refusal, plus the action that
|
|
18
|
+
* does take each key, which is the correction the caller needs.
|
|
19
|
+
*/
|
|
20
|
+
function strayKeysRefusal(tool, action, stray, actions) {
|
|
21
|
+
const owners = stray.map((key) => {
|
|
22
|
+
const takes = Object.entries(actions)
|
|
23
|
+
.filter(([, member]) => key in member.inputSchema)
|
|
24
|
+
.map(([name]) => `"${name}"`);
|
|
25
|
+
return `\`${key}\` is a parameter of action ${takes.join(' or ')}`;
|
|
26
|
+
});
|
|
27
|
+
const declared = Object.keys(actions[action]?.inputSchema ?? {}).join(', ');
|
|
28
|
+
return (`${tool} { action: "${action}" } does not take ${stray.map((k) => `\`${k}\``).join(', ')}, ` +
|
|
29
|
+
'so it was NOT applied — a result computed without it would look like an answer. ' +
|
|
30
|
+
`${owners.join('; ')}. Action "${action}" takes: ${declared}.`);
|
|
31
|
+
}
|
|
4
32
|
/** The union of member input shapes, every field optional so one schema serves every action. */
|
|
5
33
|
function unionShape(actions) {
|
|
6
34
|
const shape = {};
|
|
@@ -82,6 +110,8 @@ export function mergeTools(spec) {
|
|
|
82
110
|
const actionNames = Object.keys(spec.actions);
|
|
83
111
|
if (0 === actionNames.length)
|
|
84
112
|
throw new Error(`mergeTools(${spec.name}): no actions`);
|
|
113
|
+
// Our own action names: telemetry may report them by value rather than as `other`.
|
|
114
|
+
allowParamValues(DISCRIMINATOR, actionNames);
|
|
85
115
|
refuseDiscriminatorCollision(spec.name, spec.actions);
|
|
86
116
|
if (spec.defaultAction !== undefined && !(spec.defaultAction in spec.actions)) {
|
|
87
117
|
throw new Error(`mergeTools(${spec.name}): defaultAction '${spec.defaultAction}' is not one of its actions`);
|
|
@@ -94,7 +124,7 @@ export function mergeTools(spec) {
|
|
|
94
124
|
[DISCRIMINATOR]: discriminatorSchema(actionNames, spec.defaultAction),
|
|
95
125
|
...unionShape(spec.actions),
|
|
96
126
|
},
|
|
97
|
-
handler: (deps, args) => {
|
|
127
|
+
handler: (deps, args, call) => {
|
|
98
128
|
const named = args[DISCRIMINATOR];
|
|
99
129
|
const action = 'string' === typeof named ? named : spec.defaultAction;
|
|
100
130
|
const chosen = action === undefined ? undefined : spec.actions[action];
|
|
@@ -104,7 +134,17 @@ export function mergeTools(spec) {
|
|
|
104
134
|
expected: actionNames,
|
|
105
135
|
});
|
|
106
136
|
}
|
|
107
|
-
|
|
137
|
+
// A key no action declares is refused before this, against the union; one that another action
|
|
138
|
+
// declares is refused here, against the action that was chosen.
|
|
139
|
+
const stray = Object.keys(args).filter((key) => DISCRIMINATOR !== key &&
|
|
140
|
+
!SHARED_KEYS.has(key) &&
|
|
141
|
+
!(key in chosen.inputSchema) &&
|
|
142
|
+
args[key] !== undefined &&
|
|
143
|
+
Object.values(spec.actions).some((member) => key in member.inputSchema));
|
|
144
|
+
if (0 < stray.length && action !== undefined) {
|
|
145
|
+
return Promise.reject(new Error(strayKeysRefusal(spec.name, action, stray, spec.actions)));
|
|
146
|
+
}
|
|
147
|
+
return chosen.handler(deps, args, call);
|
|
108
148
|
},
|
|
109
149
|
};
|
|
110
150
|
}
|
|
@@ -77,6 +77,10 @@ export function mergedNameRedirect(name) {
|
|
|
77
77
|
export function retiredToolNames() {
|
|
78
78
|
const tombstones = {};
|
|
79
79
|
for (const [old, redirect] of BY_OLD_NAME) {
|
|
80
|
+
// A bare call that redirects to an action on the SAME tool (`reticle_assert` → `{ action: "now" }`)
|
|
81
|
+
// is a live tool, not a retired one. Listing it here told every reader not to use it.
|
|
82
|
+
if (old === redirect.tool)
|
|
83
|
+
continue;
|
|
80
84
|
tombstones[old] =
|
|
81
85
|
redirect.action === undefined
|
|
82
86
|
? `retired; ${redirect.note ?? `use ${redirect.tool}`}`
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export declare const NextText: {
|
|
2
|
+
readonly DECLARE: "Record what the user asked, once per task, verbatim: reticle_run { tool: \"reticle_intent\", args: { action: \"declare\", request: \"<their words>\" } }. It travels with every run.";
|
|
3
|
+
readonly SYNC_PROBLEM: (why: string) => string;
|
|
4
|
+
readonly FINISH_LINKED: "Done driving? reticle_session { action: \"yield\" } hands the tab back; this run syncs to the platform on its own.";
|
|
5
|
+
readonly FINISH: "Done driving? reticle_session { action: \"yield\" } hands the tab back.";
|
|
6
|
+
/**
|
|
7
|
+
* The evidence of this app is landing outside any project, so nothing will send it. A second
|
|
8
|
+
* checkout's runs and flows went to `~/.reticle/unmatched/<id>` and the agent was told nothing.
|
|
9
|
+
*/
|
|
10
|
+
readonly UNMATCHED: (root: string, contenders: readonly string[], serving?: string) => string;
|
|
11
|
+
readonly REPLAY: (flows: number) => string;
|
|
12
|
+
};
|
|
13
|
+
/** Tests only. */
|
|
14
|
+
export declare function resetNextStep(): void;
|
|
15
|
+
export interface NextStepInput {
|
|
16
|
+
tool: string;
|
|
17
|
+
/** Where this app's evidence goes when no project claims it, and the folders that compete for it. */
|
|
18
|
+
unmatched?: {
|
|
19
|
+
root: string;
|
|
20
|
+
contenders: readonly string[];
|
|
21
|
+
serving?: string;
|
|
22
|
+
} | undefined;
|
|
23
|
+
/** Whether this result carries a verdict. */
|
|
24
|
+
verdict: boolean;
|
|
25
|
+
root: string | undefined;
|
|
26
|
+
now: number;
|
|
27
|
+
}
|
|
28
|
+
/** The line, or undefined when there is nothing the agent should be told right now. */
|
|
29
|
+
export declare function nextStep(input: NextStepInput): string | undefined;
|