@reticlehq/server 3.6.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/SKILL.md +122 -123
- 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 +18 -2
- package/dist/command/cli/adhoc-verdict.js +70 -6
- 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/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 +28 -105
- 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 +34 -4
- package/dist/command/cli/cli-verify.js +81 -12
- package/dist/command/cli/cloud-cli.d.ts +13 -0
- package/dist/command/cli/cloud-cli.js +145 -333
- 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 +15 -1
- package/dist/command/cli/cloud-login.js +67 -13
- 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/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/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 +11 -2
- 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.js +1 -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 +29 -8
- 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 -178
- 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 +14 -0
- package/dist/command/cli.js +103 -83
- package/dist/command/daemon/daemon-resilience.js +4 -4
- package/dist/command/daemon/daemon-resolve.d.ts +9 -1
- package/dist/command/daemon/daemon-resolve.js +49 -10
- 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/dev-server-log-cap.js +2 -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 +10 -1
- package/dist/command/setup/init/init-port.js +22 -2
- package/dist/command/setup/init/init-runtime.d.ts +12 -2
- package/dist/command/setup/init/init-runtime.js +96 -37
- package/dist/command/setup/node-effects.d.ts +2 -0
- package/dist/command/setup/node-effects.js +36 -8
- 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 +1 -1
- package/dist/command/setup/run-setup.d.ts +29 -9
- package/dist/command/setup/run-setup.js +34 -28
- package/dist/command/setup/setup-command.d.ts +23 -0
- package/dist/command/setup/setup-command.js +57 -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 +38 -2
- package/dist/features/crawl/crawl.js +14 -1
- package/dist/features/exhaust/ledger.d.ts +14 -14
- package/dist/features/harness/drive-report.d.ts +39 -5
- package/dist/features/harness/drive-report.js +271 -54
- 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 +1 -1
- package/dist/features/harness/drivers.js +1 -1
- 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/goals.d.ts +68 -7
- package/dist/features/harness/goals.js +289 -36
- package/dist/features/harness/harness.d.ts +30 -1
- package/dist/features/harness/harness.js +141 -7
- package/dist/features/harness/platform/local-apps.d.ts +36 -3
- package/dist/features/harness/platform/local-apps.js +81 -5
- 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 +8 -2
- package/dist/features/harness/platform/remote-drive.js +22 -9
- package/dist/features/harness/platform/script.d.ts +57 -11
- package/dist/features/harness/platform/script.js +144 -12
- package/dist/features/harness/platform/server-driver.d.ts +17 -4
- package/dist/features/harness/platform/server-driver.js +29 -26
- package/dist/features/harness/platform-config.d.ts +38 -5
- package/dist/features/harness/platform-config.js +93 -8
- package/dist/features/harness/route-guess.d.ts +13 -0
- package/dist/features/harness/route-guess.js +49 -0
- package/dist/features/harness/script/script-run.d.ts +30 -1
- package/dist/features/harness/script/script-run.js +355 -48
- 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.js +22 -14
- 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 +21 -2
- package/dist/hooks/driven-by.js +42 -2
- package/dist/hooks/hook-bus.d.ts +4 -0
- package/dist/hooks/hook-bus.js +18 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +26 -183
- 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 +20 -4
- 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.js +25 -9
- package/dist/judgement/runs/artifact/run-store.d.ts +13 -1
- package/dist/judgement/runs/artifact/run-store.js +175 -8
- 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 +53 -5
- package/dist/judgement/runs/drive-run.js +234 -20
- package/dist/judgement/runs/resume.d.ts +44 -0
- package/dist/judgement/runs/resume.js +137 -0
- package/dist/judgement/runs/reticle-runner.js +5 -2
- 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 +2 -0
- package/dist/judgement/runs/verification-sync.js +36 -15
- package/dist/language/flows/decision.js +2 -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 +7 -2
- package/dist/language/flows/flow-anchor.js +10 -3
- 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 +37 -3
- package/dist/language/flows/flow-replay-run.js +16 -18
- package/dist/language/flows/flow-replay-types.d.ts +1 -1
- package/dist/language/flows/flow-replay.d.ts +18 -1
- package/dist/language/flows/flow-replay.js +22 -7
- package/dist/language/flows/flow-result.d.ts +22 -1
- package/dist/language/flows/flow-result.js +47 -2
- package/dist/language/flows/flow-step-runners.d.ts +2 -0
- package/dist/language/flows/flow-step-runners.js +12 -6
- package/dist/language/flows/flow-store-for-session.js +5 -1
- package/dist/language/flows/flow-tools.d.ts +10 -0
- package/dist/language/flows/flow-tools.js +61 -62
- package/dist/language/flows/flows.d.ts +16 -1
- package/dist/language/flows/flows.js +69 -10
- package/dist/language/flows/narrow-write.d.ts +7 -0
- package/dist/language/flows/narrow-write.js +36 -1
- package/dist/language/flows/recording/recording-backtrack.js +14 -1
- package/dist/language/flows/recording/tape/recordings.d.ts +29 -1
- package/dist/language/flows/recording/tape/recordings.js +60 -10
- package/dist/language/flows/replay.js +29 -6
- package/dist/language/flows/single-replay.d.ts +7 -0
- package/dist/language/flows/single-replay.js +26 -0
- package/dist/language/flows/verify-change-tools.d.ts +1 -0
- package/dist/language/flows/verify-change-tools.js +200 -193
- package/dist/memory/cloud/cloud-config.d.ts +10 -1
- package/dist/memory/cloud/cloud-config.js +19 -5
- package/dist/memory/cloud/cloud-sync.js +3 -3
- package/dist/memory/cloud/harness-config.d.ts +49 -0
- package/dist/memory/cloud/harness-config.js +16 -20
- package/dist/memory/cloud/memory-scope.d.ts +17 -0
- package/dist/memory/cloud/memory-scope.js +22 -0
- package/dist/memory/cloud/sync-cycle.d.ts +32 -4
- package/dist/memory/cloud/sync-cycle.js +113 -12
- package/dist/memory/cloud/sync-daemon.d.ts +11 -0
- package/dist/memory/cloud/sync-daemon.js +114 -4
- package/dist/memory/cloud/sync-disk.js +26 -2
- 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 +16 -1
- package/dist/memory/impact/account-watch.js +26 -1
- package/dist/memory/impact/impact-store.d.ts +1 -4
- package/dist/memory/impact/impact-store.js +32 -42
- 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 +12 -0
- package/dist/memory/intent/intent-store.d.ts +1 -0
- package/dist/memory/intent/intent-tools.js +42 -2
- 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/journal-recorder.js +46 -3
- package/dist/memory/journal/on-disk/retention.d.ts +5 -0
- package/dist/memory/journal/on-disk/retention.js +27 -2
- package/dist/memory/journal/on-disk/workspace-tiers.js +2 -0
- package/dist/memory/journal/session-end.d.ts +15 -1
- package/dist/memory/journal/session-end.js +38 -7
- package/dist/memory/project/artifact-root-resolver.js +33 -5
- package/dist/memory/project/artifact-root.d.ts +4 -3
- package/dist/memory/project/artifact-root.js +2 -2
- package/dist/memory/project/dir/reticle-dir.d.ts +14 -0
- package/dist/memory/project/dir/reticle-dir.js +23 -2
- package/dist/memory/project/link-directory.d.ts +15 -0
- package/dist/memory/project/link-directory.js +44 -0
- 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 +2 -0
- package/dist/memory/project/session-root.js +9 -1
- package/dist/memory/project/sync-status.d.ts +46 -0
- package/dist/memory/project/sync-status.js +135 -1
- package/dist/memory/recall/memory-tools.js +46 -3
- 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.js +36 -8
- package/dist/portal/bridge/bridge.d.ts +9 -5
- package/dist/portal/bridge/bridge.js +66 -23
- package/dist/portal/bridge/harness-request.d.ts +23 -0
- package/dist/portal/bridge/harness-request.js +27 -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 +2 -0
- package/dist/portal/input/real-input.js +13 -10
- package/dist/portal/pool/browser-pool.d.ts +48 -0
- package/dist/portal/pool/browser-pool.js +120 -2
- 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 +27 -5
- package/dist/portal/pool/playwright-launcher.js +59 -14
- package/dist/portal/pool/pool-contract.d.ts +21 -1
- 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.js +6 -1
- 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 +9 -0
- package/dist/portal/session/dev-server/dev-command.js +27 -1
- 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/human/live-control.d.ts +9 -2
- package/dist/portal/session/human/live-control.js +12 -3
- package/dist/portal/session/live-control-tools.js +82 -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 +1 -1
- package/dist/portal/session/no-session-diagnosis.js +31 -9
- package/dist/portal/session/no-session-next-action.d.ts +20 -0
- package/dist/portal/session/no-session-next-action.js +134 -61
- package/dist/portal/session/no-session-watch.js +179 -22
- package/dist/portal/session/presence/session-lease.js +1 -1
- package/dist/portal/session/recorded-gaps.d.ts +97 -0
- package/dist/portal/session/recorded-gaps.js +251 -0
- package/dist/portal/session/session-health.d.ts +11 -0
- package/dist/portal/session/session-health.js +3 -1
- package/dist/portal/session/session-info.js +2 -1
- package/dist/portal/session/session-manager.d.ts +18 -0
- package/dist/portal/session/session-manager.js +54 -3
- package/dist/portal/session/session-successor.d.ts +8 -0
- package/dist/portal/session/session-successor.js +1 -1
- package/dist/portal/session/session.d.ts +15 -28
- package/dist/portal/session/session.js +60 -61
- 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 +7 -1
- package/dist/start-wiring.d.ts +63 -0
- package/dist/start-wiring.js +169 -0
- package/dist/status-payload.d.ts +13 -1
- package/dist/status-payload.js +13 -1
- package/dist/surface/http-server.js +7 -1
- 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 +4 -0
- package/dist/surface/mcp/mcp-proxy.js +29 -8
- package/dist/surface/mcp/mcp.d.ts +23 -0
- package/dist/surface/mcp/mcp.js +34 -4
- 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.js +22 -14
- package/dist/surface/mcp/shared-params.js +1 -1
- 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/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-sequence-tool.js +136 -27
- package/dist/surface/tools/act-tools.d.ts +0 -9
- package/dist/surface/tools/act-tools.js +48 -34
- 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.js +25 -15
- package/dist/surface/tools/browser-tools.js +43 -1
- package/dist/surface/tools/chat-drives.d.ts +75 -0
- package/dist/surface/tools/chat-drives.js +265 -21
- 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 +10 -0
- package/dist/surface/tools/empty-session-list.js +45 -5
- package/dist/surface/tools/error-recovery.d.ts +8 -0
- package/dist/surface/tools/error-recovery.js +69 -5
- package/dist/surface/tools/explore-tools.d.ts +23 -2
- package/dist/surface/tools/explore-tools.js +377 -74
- package/dist/surface/tools/feedback-tools.d.ts +2 -3
- package/dist/surface/tools/feedback-tools.js +4 -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 +52 -73
- package/dist/surface/tools/harness-explore.js +177 -146
- 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 +5 -0
- package/dist/surface/tools/harness-plan.js +7 -0
- package/dist/surface/tools/harness-script.d.ts +22 -0
- package/dist/surface/tools/harness-script.js +256 -38
- 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 +8 -0
- package/dist/surface/tools/harness-toolset.js +27 -4
- 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 +220 -93
- 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 +20 -0
- package/dist/surface/tools/lease-seed.js +45 -1
- package/dist/surface/tools/lease-tools.d.ts +10 -1
- package/dist/surface/tools/lease-tools.js +119 -69
- package/dist/surface/tools/live-call-text.js +2 -2
- 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 +11 -1
- package/dist/surface/tools/next-step.js +73 -18
- package/dist/surface/tools/observe-tools.js +43 -5
- package/dist/surface/tools/platform-moment.d.ts +60 -0
- package/dist/surface/tools/platform-moment.js +132 -4
- package/dist/surface/tools/read-tools.js +65 -14
- 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 +68 -2
- package/dist/surface/tools/tool-kit.js +73 -1
- package/dist/surface/tools/tools.js +25 -13
- 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 +27 -6
- package/dist/telemetry/hud-metrics.js +99 -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 +26 -2
- package/dist/telemetry/telemetry.js +102 -21
- package/dist/telemetry/verification-of.d.ts +3 -1
- package/dist/telemetry/verification-of.js +12 -4
- package/dist/wire-journal.d.ts +2 -2
- package/dist/wire-journal.js +16 -5
- package/docs/README.md +2 -2
- package/docs/actions.mdx +6 -3
- package/docs/adapters.md +1 -1
- package/docs/agent-cheatsheet.md +24 -27
- package/docs/architecture.md +5 -5
- package/docs/autodrive.md +13 -12
- 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 +8 -3
- package/docs/cli/drive.mdx +12 -12
- 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 +32 -15
- 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 +13 -4
- 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 +3 -2
- package/docs/cli.mdx +110 -41
- package/docs/debugging.md +3 -3
- package/docs/deploy-checks.md +1 -1
- package/docs/desktop.mdx +5 -3
- package/docs/enterprise.md +11 -10
- package/docs/environment.mdx +5 -2
- 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 +66 -64
- package/docs/human-control.md +15 -14
- package/docs/index.mdx +15 -43
- package/docs/install-agentic.mdx +22 -37
- package/docs/install-manual.mdx +22 -12
- 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 +8 -8
- package/docs/packages/test.mdx +4 -10
- package/docs/packages/vite-plugin.mdx +11 -4
- package/docs/packages.mdx +11 -15
- package/docs/platform-integration.md +6 -5
- package/docs/predicates.mdx +40 -24
- package/docs/quickstart.mdx +58 -29
- 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 +22 -24
- 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 +13 -4
- 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 +51 -45
- 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 +7 -5
- package/docs/what-is-reticle.mdx +2 -2
- package/docs/why-reticle.mdx +1 -1
- package/package.json +6 -5
- package/dist/command/cli/demo/demo-page.d.ts +0 -78
- package/dist/command/cli/demo/demo-page.js +0 -249
- package/dist/command/cli/demo/demo-run.d.ts +0 -38
- package/dist/command/cli/demo/demo-run.js +0 -138
- 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/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
|
@@ -8,26 +8,44 @@
|
|
|
8
8
|
*/
|
|
9
9
|
import { randomUUID } from 'node:crypto';
|
|
10
10
|
import { join } from 'node:path';
|
|
11
|
-
import { ReticleCommand, ReticleTool, ScriptStatus, asRecord } from '@reticlehq/core';
|
|
12
|
-
import { PromptContextSchema, checkScript } from '@reticlehq/core/artifacts';
|
|
11
|
+
import { ReticleCommand, ReticleTool, ScriptStatus, asRecord, } from '@reticlehq/core';
|
|
12
|
+
import { JourneyBy, PromptContextSchema, checkScript, } from '@reticlehq/core/artifacts';
|
|
13
13
|
import { runScript, } from '../../features/harness/script/script-run.js';
|
|
14
14
|
import { CUSTOM_DRIVER_NAME } from '../../features/harness/drivers.js';
|
|
15
|
-
import { checkTally, verdictLine } from '../../features/harness/drive-report.js';
|
|
15
|
+
import { actedOnApp, checkTally, pagesReached, typedValues, verdictLine, } from '../../features/harness/drive-report.js';
|
|
16
16
|
import { runHarness, StopReason, } from '../../features/harness/harness.js';
|
|
17
17
|
import { reticleDirPaths } from '../../memory/project/dir/reticle-dir.js';
|
|
18
|
-
import { harnessRunId, noteHarnessGoal } from '../../judgement/runs/drive-run.js';
|
|
18
|
+
import { harnessRunId, noteHarnessDisparity, noteHarnessGoal, noteHarnessSpan, } from '../../judgement/runs/drive-run.js';
|
|
19
19
|
import { openSessionIntents } from '../../memory/intent/open-intents.js';
|
|
20
20
|
import { sessionRoot, sessionTarget } from '../../memory/project/session-root.js';
|
|
21
|
-
import { leasableAppUrl } from '../../language/flows/flow-tools.js';
|
|
22
|
-
import { acquireLeasedSession } from './lease-tools.js';
|
|
21
|
+
import { leasableAppUrl, sessionUrlOf } from '../../language/flows/flow-tools.js';
|
|
22
|
+
import { acquireLeasedSession, suiteFixtureSeed } from './lease-tools.js';
|
|
23
23
|
import { reticleToolset } from './harness-toolset.js';
|
|
24
24
|
import { laneIds } from '../../features/harness/script/lane-ids.js';
|
|
25
25
|
import { appControlsOf } from '../../features/harness/script/app-controls.js';
|
|
26
|
-
import {
|
|
27
|
-
import {
|
|
28
|
-
import {
|
|
29
|
-
import {
|
|
30
|
-
import {
|
|
26
|
+
import { surveyedSince } from '../../features/harness/explore/site-map.js';
|
|
27
|
+
import { PlanStepKind, aboutTheApp, drivingPlan, planAsText, } from './harness-plan.js';
|
|
28
|
+
import { fetchScript, journeyResults, personasIn, proposeScript, reportPlanBlocked, reportPlanResults, } from '../../features/harness/platform/script.js';
|
|
29
|
+
import { endOf, goalOfDrive, parseGoals, readOpening } from '../../features/harness/goals.js';
|
|
30
|
+
import { bestOfLanes, huntAndGrade, knownRoutes, refreshMap, siteMapFor, } from './harness-hunt.js';
|
|
31
|
+
import { serverOptionsFromEnv, } from '../../features/harness/platform/server-driver.js';
|
|
32
|
+
import { MSG_HARNESS_DISABLED, bankOpenRecording, buildDriver, firstLine, flowsThatCheckNothing, maxStepsFromEnv, msgDriveCutOff, narrator, pinned, productRules, readFlows, readPlan, reconcileFlows, recordPersona, refusedByPlatform, steering, withProjectFlows, } from './harness-explore.js';
|
|
33
|
+
/** A saved plan this run was asked for and could not read: said, never swapped for another drive. */
|
|
34
|
+
export const msgSavedPlanUnreadable = (planId) => `The saved plan ${planId} could not be read from the Reticle platform, or it no longer runs as written. Open it on the dashboard, fix it, and run it again.`;
|
|
35
|
+
/** The platform could not plan the run: the drive that follows is the journey alone, unplanned. */
|
|
36
|
+
export const msgNoPlan = (why) => `No plan this time — ${why.replace(/\.$/, '')}. Driving the journey on its own instead.`;
|
|
37
|
+
/** Said when a plan's lanes cannot carry this tab's sign-in into new browsers, so they take turns here. */
|
|
38
|
+
export const MSG_LANES_IN_THIS_TAB = "The plan's lanes take turns in this tab: a new browser would start signed out, and this tab's " +
|
|
39
|
+
'sign-in could not be copied into one.';
|
|
40
|
+
/**
|
|
41
|
+
* The sign-in a plan's lanes start from: what this tab's browser holds, or undefined when it cannot
|
|
42
|
+
* be copied (no browser this daemon drives, nothing to copy), in which case the lanes take turns here.
|
|
43
|
+
*/
|
|
44
|
+
export async function laneSeed(deps, sessionId, appUrl) {
|
|
45
|
+
if (appUrl === undefined)
|
|
46
|
+
return undefined;
|
|
47
|
+
return suiteFixtureSeed(deps.realInput, sessionUrlOf(deps, sessionId) ?? appUrl);
|
|
48
|
+
}
|
|
31
49
|
/** A request older than this is about some earlier task, not the one being driven. */
|
|
32
50
|
const REQUEST_FRESH_MS = 6 * 60 * 60 * 1000;
|
|
33
51
|
const MAX_GOAL_CHARS = 500;
|
|
@@ -52,18 +70,45 @@ export async function exploreScript(deps, env, options, before) {
|
|
|
52
70
|
? plan.steps.filter((s) => PlanStepKind.REPLAY === s.kind).map((s) => s.target)
|
|
53
71
|
: [];
|
|
54
72
|
const goals = focus === undefined ? await memoryGoals(deps, options.sessionId) : [focus];
|
|
55
|
-
const gaps = plan.steps.
|
|
73
|
+
const gaps = drivingPlan(plan, focus).steps.map((s) => s.why);
|
|
56
74
|
const flows = await readFlows(reads);
|
|
57
75
|
const known = await productRules(deps, options.sessionId);
|
|
58
76
|
// The platform plans: personas, order, branches and the product rules each journey proves.
|
|
59
77
|
// A platform that cannot plan leaves the caller to drive the journey through it unplanned.
|
|
60
78
|
const platform = serverOptionsFromEnv(env);
|
|
79
|
+
// A saved plan is the platform's: without it there is nothing to run, and driving something else
|
|
80
|
+
// in its place would answer a question nobody asked.
|
|
81
|
+
if (platform === undefined && options.planId !== undefined)
|
|
82
|
+
throw new Error(msgSavedPlanUnreadable(options.planId));
|
|
61
83
|
if (platform === undefined)
|
|
62
84
|
return undefined;
|
|
85
|
+
if (options.planId !== undefined) {
|
|
86
|
+
const planId = options.planId;
|
|
87
|
+
// Refused or broken before a journey ran is still said to the plan, so its history shows it.
|
|
88
|
+
// ponytail: a throw from inside a running plan is reported as all blocked too; runPlan reports
|
|
89
|
+
// real results itself whenever it returns.
|
|
90
|
+
try {
|
|
91
|
+
const saved = await fetchScript(platform, planId);
|
|
92
|
+
if (saved === undefined)
|
|
93
|
+
throw new Error(msgSavedPlanUnreadable(planId));
|
|
94
|
+
return await runPlan(deps, env, options, before, { platform, plan, script: saved, planId });
|
|
95
|
+
}
|
|
96
|
+
catch (error) {
|
|
97
|
+
const why = error instanceof Error ? error.message : String(error);
|
|
98
|
+
await reportPlanBlocked(platform, planId, firstLine(why));
|
|
99
|
+
throw error;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
// The same persona runs the plan it made last time, as it stands on the platform now (edits and
|
|
103
|
+
// replay-first included): a new plan per HUD run meant a passed journey was never replayed.
|
|
104
|
+
const again = focus === undefined ? undefined : await planMadeFor(deps, options.sessionId, focus);
|
|
105
|
+
const reused = again === undefined ? undefined : await fetchScript(platform, again);
|
|
106
|
+
if (again !== undefined && reused !== undefined)
|
|
107
|
+
return runPlan(deps, env, options, before, { platform, plan, script: reused, planId: again });
|
|
63
108
|
// What the screen offers, for a named journey too. The platform splits a broad request ("test my
|
|
64
109
|
// app, make a plan") into journeys through these controls and leaves a narrow one whole; without
|
|
65
110
|
// them, a chat-requested drive of a desktop app planned one step that restated the request.
|
|
66
|
-
const about = await aboutTheApp(planAsText(plan), (name, args) => reticleToolset(deps, pinned(options)).invoke(name, args), await controlsSeenBefore(deps, options.sessionId));
|
|
111
|
+
const about = await aboutTheApp(planAsText(focus === undefined ? plan : drivingPlan(plan, focus)), (name, args) => reticleToolset(deps, pinned(options)).invoke(name, args), await controlsSeenBefore(deps, options.sessionId));
|
|
67
112
|
const personas = focus === undefined ? personasIn(flows) : [];
|
|
68
113
|
const proposed = await proposeScript(platform, {
|
|
69
114
|
about,
|
|
@@ -74,14 +119,35 @@ export async function exploreScript(deps, env, options, before) {
|
|
|
74
119
|
rules: known,
|
|
75
120
|
personas,
|
|
76
121
|
});
|
|
122
|
+
if (proposed !== undefined && 'refused' in proposed) {
|
|
123
|
+
// Said where the run is watched: the drive goes on without a plan, and that is not what was asked.
|
|
124
|
+
narrator(deps, options)(msgNoPlan(proposed.refused), true);
|
|
125
|
+
return undefined;
|
|
126
|
+
}
|
|
77
127
|
if (proposed === undefined || 0 < checkScript(proposed.script).length)
|
|
78
128
|
return undefined;
|
|
79
|
-
|
|
129
|
+
return runPlan(deps, env, options, before, {
|
|
130
|
+
platform,
|
|
131
|
+
plan,
|
|
132
|
+
script: proposed.script,
|
|
133
|
+
...(proposed.planId === undefined ? {} : { planId: proposed.planId }),
|
|
134
|
+
...(proposed.creditsSpent === undefined ? {} : { planCredits: proposed.creditsSpent }),
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
/** Run a plan the platform wrote (just now, or saved and maybe edited since), and report how it went. */
|
|
138
|
+
async function runPlan(deps, env, options, before, planned) {
|
|
139
|
+
const { platform, plan, script, planId } = planned;
|
|
140
|
+
const reads = withProjectFlows(deps, options.sessionId);
|
|
141
|
+
const focus = options.focus;
|
|
80
142
|
// Saved the moment it exists, so a drive that breaks still leaves its plan behind.
|
|
81
|
-
const planFile = await savePlan(deps, options.sessionId, {
|
|
143
|
+
const planFile = await savePlan(deps, options.sessionId, {
|
|
144
|
+
planId,
|
|
145
|
+
script,
|
|
146
|
+
...(focus === undefined ? {} : { focus }),
|
|
147
|
+
});
|
|
82
148
|
const maxSteps = options.maxSteps ?? maxStepsFromEnv(env);
|
|
83
149
|
// The script replays the saved flows itself; a model handed them too replayed them again per goal.
|
|
84
|
-
const open =
|
|
150
|
+
const open = drivingPlan(plan, focus);
|
|
85
151
|
// The journey itself leads (its rules are already written into it by the platform): a driver
|
|
86
152
|
// with nothing named to prove stopped after its first half.
|
|
87
153
|
const planFor = (goal) => {
|
|
@@ -90,16 +156,26 @@ export async function exploreScript(deps, env, options, before) {
|
|
|
90
156
|
const journey = { kind: PlanStepKind.DRIVE, target: 'this journey, to its end', why: goal };
|
|
91
157
|
return { ...open, steps: [journey, ...open.steps] };
|
|
92
158
|
};
|
|
159
|
+
// Map first: survey the app (no model) unless its map is fresh; every lane's engine looks goals up
|
|
160
|
+
// in it, and the hunt before grading starts from it. The tab is left where it started.
|
|
161
|
+
const mapAsked = deps.now();
|
|
162
|
+
const map = await siteMapFor(deps, options.sessionId, (name, args) => reticleToolset(deps, pinned(options)).invoke(name, args));
|
|
93
163
|
const driverFor = (persona, goal) => options.driver === undefined
|
|
94
|
-
? buildDriver(env, maxSteps, planFor(goal), options.driverName, persona, persona === undefined ? goal : undefined)
|
|
164
|
+
? buildDriver(env, maxSteps, planFor(goal), options.driverName, persona, persona === undefined ? goal : undefined, map)
|
|
95
165
|
: { driver: options.driver, name: CUSTOM_DRIVER_NAME };
|
|
96
166
|
const driverName = driverFor().name;
|
|
97
|
-
const harness = randomUUID();
|
|
167
|
+
const harness = options.harnessId ?? randomUUID();
|
|
98
168
|
const narrate = narrator(deps, options);
|
|
99
169
|
// Lanes run side by side only in leased contexts; without a pool they take turns on this tab.
|
|
100
170
|
const pool = deps.pool;
|
|
101
171
|
const appUrl = leasableAppUrl(deps, options.sessionId);
|
|
102
|
-
const
|
|
172
|
+
const wantsLanes = pool !== undefined && appUrl !== undefined && 1 < script.lanes.length;
|
|
173
|
+
// A new context starts signed out: lanes once spent a whole run (three lanes, twelve credits) on
|
|
174
|
+
// /login, a page that was not the journey. They start from what this tab holds, or take turns here.
|
|
175
|
+
const seed = wantsLanes ? await laneSeed(deps, options.sessionId, appUrl) : undefined;
|
|
176
|
+
const leasing = wantsLanes && seed !== undefined;
|
|
177
|
+
if (wantsLanes && !leasing)
|
|
178
|
+
narrator(deps, options)(MSG_LANES_IN_THIS_TAB);
|
|
103
179
|
const projectId = safeProjectId(deps, options.sessionId);
|
|
104
180
|
let off = false;
|
|
105
181
|
const poll = setInterval(() => {
|
|
@@ -110,15 +186,25 @@ export async function exploreScript(deps, env, options, before) {
|
|
|
110
186
|
}, STOP_POLL_MS);
|
|
111
187
|
poll.unref();
|
|
112
188
|
const lanes = laneIds(harness, leasing);
|
|
189
|
+
const endGoalsAsked = options.goals ?? parseGoals(focus);
|
|
190
|
+
const laneGrades = [];
|
|
113
191
|
// Keyed by the tool list, which the script runner's recording wrapper passes through unchanged.
|
|
114
192
|
const harnessOf = new WeakMap();
|
|
193
|
+
const own = [...(focus === undefined ? [] : [focus]), ...scriptTexts(script)];
|
|
115
194
|
const ports = {
|
|
195
|
+
own,
|
|
116
196
|
parallel: leasing ? Math.max(1, Math.min(script.lanes.length, pool.capacity(), MAX_LANES)) : 1,
|
|
117
|
-
stopped: () => off,
|
|
197
|
+
stopped: () => off || true === options.stopped?.(),
|
|
198
|
+
// A replay-only plan started without the model's gates; a fallback is the model, so it asks now.
|
|
199
|
+
fallbackRefused: async () => {
|
|
200
|
+
const refusal = await refusedByPlatform(env, options);
|
|
201
|
+
return refusal === undefined ? undefined : firstLine(refusal);
|
|
202
|
+
},
|
|
203
|
+
...(true === options.confirmDangerous ? { confirmDangerous: true } : {}),
|
|
118
204
|
lease: async () => {
|
|
119
205
|
if (!leasing)
|
|
120
206
|
return { ...pinned(options), release: () => Promise.resolve() };
|
|
121
|
-
const acquire = () => acquireLeasedSession(pool, deps.sessions, appUrl, projectId);
|
|
207
|
+
const acquire = () => acquireLeasedSession(pool, deps.sessions, appUrl, projectId, seed);
|
|
122
208
|
// A cold dev server can miss the first load while other lanes compile it; the second finds it warm.
|
|
123
209
|
return acquire().catch(acquire);
|
|
124
210
|
},
|
|
@@ -131,6 +217,9 @@ export async function exploreScript(deps, env, options, before) {
|
|
|
131
217
|
driver: driverName,
|
|
132
218
|
...(persona === undefined ? {} : { persona }),
|
|
133
219
|
},
|
|
220
|
+
// The person's request, never the planned journey's text: a planner-invented journey
|
|
221
|
+
// ("press Invite") must not be what allows an invite.
|
|
222
|
+
...(focus === undefined ? {} : { asked: focus }),
|
|
134
223
|
});
|
|
135
224
|
harnessOf.set(toolset.tools, id);
|
|
136
225
|
return toolset;
|
|
@@ -141,16 +230,38 @@ export async function exploreScript(deps, env, options, before) {
|
|
|
141
230
|
? undefined
|
|
142
231
|
: goal);
|
|
143
232
|
const ahead = new Set(await reads.flows.list());
|
|
144
|
-
const
|
|
233
|
+
const driven = await runHarness(driverFor(persona, goal).driver, toolset, {
|
|
234
|
+
...steering(options),
|
|
145
235
|
maxSteps: Math.min(steps, maxSteps),
|
|
236
|
+
routes: knownRoutes(map),
|
|
146
237
|
focus: [planAsText(planFor(goal)), `Focus: ${goal}`].join('\n\n'),
|
|
238
|
+
...((end) => (end === undefined ? {} : { endsAt: { text: end, own } }))(endOf(goal)),
|
|
147
239
|
});
|
|
240
|
+
// The driver's word, unless the lane did nothing: then its goal was not met by it.
|
|
241
|
+
const laneGoal = goalOfDrive(driven.goalMet, [], actedOnApp(driven.toolCalls));
|
|
242
|
+
const result = { ...driven, ...(laneGoal === undefined ? {} : { goalMet: laneGoal }) };
|
|
148
243
|
// Before the lane's session ends and is graded, so its run cannot read "Proved" over a goal
|
|
149
244
|
// the drive did not reach.
|
|
150
245
|
noteHarnessGoal(harnessOf.get(toolset.tools) ?? harness, result.goalMet);
|
|
151
|
-
await bankOpenRecording(toolset, result, persona);
|
|
246
|
+
const banked = await bankOpenRecording(toolset, result, persona, goal);
|
|
247
|
+
// A lane in its own browser is graded where it drove: the caller's tab never saw its pages.
|
|
248
|
+
if (leasing && 0 < endGoalsAsked.length)
|
|
249
|
+
laneGrades.push(await huntAndGrade(deps, (name, args) => toolset.invoke(name, args), {
|
|
250
|
+
sessionId: options.sessionId,
|
|
251
|
+
goals: endGoalsAsked,
|
|
252
|
+
expect: options.expect,
|
|
253
|
+
opening,
|
|
254
|
+
journey: goal,
|
|
255
|
+
map,
|
|
256
|
+
own,
|
|
257
|
+
reached: pagesReached(result.toolCalls),
|
|
258
|
+
typed: typedValues(result.toolCalls),
|
|
259
|
+
}));
|
|
152
260
|
if (persona !== undefined) {
|
|
153
|
-
const saved = reconcileFlows(ahead, await reads.flows.list(),
|
|
261
|
+
const saved = reconcileFlows(ahead, await reads.flows.list(), [
|
|
262
|
+
...result.toolCalls,
|
|
263
|
+
...banked,
|
|
264
|
+
]);
|
|
154
265
|
await recordPersona(reads, [...saved.savedFlows, ...saved.rewroteFlows], persona);
|
|
155
266
|
}
|
|
156
267
|
return result;
|
|
@@ -158,6 +269,10 @@ export async function exploreScript(deps, env, options, before) {
|
|
|
158
269
|
};
|
|
159
270
|
narrate(`Harness plan from the platform · ${String(script.journeys.length)} journeys in ${String(script.lanes.length)} lane(s)` +
|
|
160
271
|
(1 < ports.parallel ? `, ${String(ports.parallel)} at once` : ''));
|
|
272
|
+
// Read before anything is driven: a goal this page already shows proves nothing at the end.
|
|
273
|
+
const endInvoke = (name, args) => ports.toolset(pinned(options).sessionId, focus).invoke(name, args);
|
|
274
|
+
const opening = await readOpening(endInvoke);
|
|
275
|
+
const runStarted = deps.now();
|
|
161
276
|
let run;
|
|
162
277
|
try {
|
|
163
278
|
run = await runScript(script, ports, (view) => {
|
|
@@ -177,23 +292,32 @@ export async function exploreScript(deps, env, options, before) {
|
|
|
177
292
|
// error in the console. On the merchant dashboard eight blank pages went unreported without it.
|
|
178
293
|
// After the journeys, so the lanes start sooner. (Run first, it once left every lane unable to
|
|
179
294
|
// start; that did not reproduce on a clean install, and was the checkout's, not the order's.)
|
|
180
|
-
|
|
295
|
+
// Once per map: a run on a fresh map swept the whole app again, every time.
|
|
296
|
+
const crawled = focus === undefined && !run.stopped && surveyedSince(map, mapAsked)
|
|
181
297
|
? await crawlApp(deps, options, harness, driverName)
|
|
182
298
|
: undefined;
|
|
183
299
|
// How each journey went: kept beside the plan here, and told to the platform, whose next plan
|
|
184
300
|
// drives what failed first.
|
|
185
|
-
const results = journeyResults(run.view);
|
|
186
|
-
await savePlan(deps, options.sessionId, {
|
|
187
|
-
|
|
188
|
-
|
|
301
|
+
const results = journeyResults(run.view, run.journeys);
|
|
302
|
+
await savePlan(deps, options.sessionId, {
|
|
303
|
+
planId,
|
|
304
|
+
script,
|
|
305
|
+
...(focus === undefined ? {} : { focus }),
|
|
306
|
+
results,
|
|
307
|
+
...appControlsOf(run.toolCalls, crawled),
|
|
308
|
+
}, planFile);
|
|
189
309
|
for (const line of run.lines)
|
|
190
310
|
narrate(line);
|
|
311
|
+
const cutOff = run.drives.find((d) => StopReason.BROKEN === d.stopReason);
|
|
191
312
|
narrate(run.stopped
|
|
192
313
|
? 'Autonomous driving switched off — the Harness stopped. What it drove is kept.'
|
|
193
|
-
:
|
|
314
|
+
: cutOff !== undefined
|
|
315
|
+
? msgDriveCutOff(cutOff.error)
|
|
316
|
+
: // One verdict, the journeys': the count of passed journeys is in it, said once.
|
|
317
|
+
`Harness finished the plan${answeredBy(run.journeys)}. ${verdictLine(checkTally(run.toolCalls), undefined, results)}`);
|
|
194
318
|
const sum = (pick) => run.drives.reduce((n, r) => n + pick(r), 0);
|
|
195
319
|
// A model drive that broke breaks the run: "finished" over a platform that answered 500 hid it.
|
|
196
|
-
const broke =
|
|
320
|
+
const broke = cutOff;
|
|
197
321
|
const drive = {
|
|
198
322
|
stopReason: run.stopped
|
|
199
323
|
? StopReason.STOPPED
|
|
@@ -215,7 +339,11 @@ export async function exploreScript(deps, env, options, before) {
|
|
|
215
339
|
},
|
|
216
340
|
proved: run.view.lanes.some((lane) => lane.journeys.some((card) => ScriptStatus.PASSED === card.status)),
|
|
217
341
|
// Unmet if any journey's goal was judged unmet; met only when every judged one was.
|
|
218
|
-
...goalOfRun(run.drives),
|
|
342
|
+
...goalOfRun(run.drives, results),
|
|
343
|
+
// What every lane cost, as the platform said; a planned run dropped it and read as free.
|
|
344
|
+
...(run.drives.some((d) => d.creditsSpent !== undefined) || planned.planCredits !== undefined
|
|
345
|
+
? { creditsSpent: sum((r) => r.creditsSpent ?? 0) + (planned.planCredits ?? 0) }
|
|
346
|
+
: {}),
|
|
219
347
|
};
|
|
220
348
|
const reconciled = reconcileFlows(before, await reads.flows.list(), run.toolCalls);
|
|
221
349
|
const runIds = lanes.all().flatMap((id) => {
|
|
@@ -226,22 +354,86 @@ export async function exploreScript(deps, env, options, before) {
|
|
|
226
354
|
...reconciled.savedFlows,
|
|
227
355
|
...reconciled.rewroteFlows,
|
|
228
356
|
]);
|
|
357
|
+
await refreshMap(deps, options.sessionId, map, run.toolCalls);
|
|
358
|
+
// The texts a named journey quoted must be on the page at the end, hunted for first (a goal the
|
|
359
|
+
// drive walked past or stopped short of is looked for, not graded where it stood), and not counted
|
|
360
|
+
// when the page showed them before the drive began.
|
|
361
|
+
// Lanes in their own browsers were graded where they drove, and a goal any lane proved is proved;
|
|
362
|
+
// lanes taking turns here end on this tab, so it is graded here.
|
|
363
|
+
const graded = 0 < laneGrades.length
|
|
364
|
+
? bestOfLanes(laneGrades)
|
|
365
|
+
: await huntAndGrade(deps, endInvoke, {
|
|
366
|
+
sessionId: options.sessionId,
|
|
367
|
+
goals: endGoalsAsked,
|
|
368
|
+
expect: options.expect,
|
|
369
|
+
opening,
|
|
370
|
+
journey: focus,
|
|
371
|
+
map,
|
|
372
|
+
own,
|
|
373
|
+
reached: pagesReached(run.toolCalls),
|
|
374
|
+
typed: typedValues(run.toolCalls),
|
|
375
|
+
});
|
|
376
|
+
const goals = graded.goals;
|
|
377
|
+
for (const id of lanes.all())
|
|
378
|
+
noteHarnessDisparity(id, graded.disparity);
|
|
379
|
+
const goalMet = goalOfDrive(drive.goalMet, goals, actedOnApp(run.toolCalls));
|
|
380
|
+
if (0 < goals.length)
|
|
381
|
+
for (const id of lanes.all())
|
|
382
|
+
noteHarnessGoal(id, goalMet);
|
|
383
|
+
// After the goals are graded: a journey that "passed" over goals that came back unmet is not.
|
|
384
|
+
// ponytail: one run-wide goalMet on every journey; per-journey once lanes grade their own goals.
|
|
385
|
+
if (planId !== undefined)
|
|
386
|
+
await reportPlanResults(platform, planId, goalMet === undefined ? results : results.map((r) => ({ ...r, goalMet })), runIds);
|
|
387
|
+
// ponytail: every lane is given the run's time; per-lane timing if lanes ever report their own.
|
|
388
|
+
for (const id of lanes.all())
|
|
389
|
+
noteHarnessSpan(id, deps.now() - runStarted);
|
|
229
390
|
return {
|
|
230
|
-
|
|
391
|
+
// The hunt's navigations too, after the goal was decided on what the plan itself drove.
|
|
392
|
+
drive: {
|
|
393
|
+
...drive,
|
|
394
|
+
toolCalls: [...drive.toolCalls, ...graded.moved],
|
|
395
|
+
...(goalMet === undefined ? {} : { goalMet }),
|
|
396
|
+
},
|
|
231
397
|
plan,
|
|
232
398
|
driverName,
|
|
233
399
|
...reconciled,
|
|
234
400
|
unverifiedFlows,
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
goals: await checkGoals((name, args) => ports.toolset(pinned(options).sessionId, focus).invoke(name, args), options.goals ?? goalsIn(focus)),
|
|
401
|
+
goals,
|
|
402
|
+
...(0 === graded.disparity.length ? {} : { disparity: graded.disparity }),
|
|
238
403
|
...(0 === runIds.length ? {} : { runIds }),
|
|
404
|
+
...(planId === undefined ? {} : { planId }),
|
|
405
|
+
journeys: results,
|
|
239
406
|
planLines: [
|
|
240
407
|
`Plan · ${String(script.journeys.length)} journeys in ${String(script.lanes.length)} lane(s)`,
|
|
241
408
|
...run.lines,
|
|
242
409
|
],
|
|
243
410
|
};
|
|
244
411
|
}
|
|
412
|
+
/**
|
|
413
|
+
* How the journeys were answered: replayed with no model, or driven by it and what that cost. Only
|
|
414
|
+
* what was measured; what a replay saved is not, since its journey was not also driven to compare.
|
|
415
|
+
*/
|
|
416
|
+
function answeredBy(journeys) {
|
|
417
|
+
if (0 === journeys.length)
|
|
418
|
+
return '';
|
|
419
|
+
const driven = journeys.filter((j) => JourneyBy.MODEL === j.by);
|
|
420
|
+
const replayed = journeys.filter((j) => JourneyBy.REPLAY === j.by).length;
|
|
421
|
+
const tokens = driven.reduce((n, j) => n + j.tokens, 0);
|
|
422
|
+
return ` (${String(replayed)} replayed with no model, ${String(driven.length)} driven by the model${0 === driven.length ? '' : `, ${String(tokens)} tokens`})`;
|
|
423
|
+
}
|
|
424
|
+
/**
|
|
425
|
+
* Every text the plan writes down that a page could show back: journey titles, open goals, personas.
|
|
426
|
+
* The platform names the saved plan after them, so they are the Harness's words, never evidence.
|
|
427
|
+
*/
|
|
428
|
+
function scriptTexts(script) {
|
|
429
|
+
return [
|
|
430
|
+
...script.journeys.flatMap((j) => [
|
|
431
|
+
j.title,
|
|
432
|
+
...j.steps.flatMap((s) => ('goal' in s && s.goal !== undefined ? [s.goal] : [])),
|
|
433
|
+
]),
|
|
434
|
+
...script.personas.map((p) => p.journey),
|
|
435
|
+
];
|
|
436
|
+
}
|
|
245
437
|
/** What the project still owes, in its own words: the user's recent request, then open intents. */
|
|
246
438
|
async function memoryGoals(deps, sessionId) {
|
|
247
439
|
const goals = [];
|
|
@@ -290,8 +482,14 @@ async function savePlan(deps, sessionId, plan, file) {
|
|
|
290
482
|
return file;
|
|
291
483
|
}
|
|
292
484
|
}
|
|
293
|
-
/**
|
|
294
|
-
|
|
485
|
+
/**
|
|
486
|
+
* The run's goal verdict: false if any drive missed its goal, true if all judged ones reached it.
|
|
487
|
+
* Every journey passed is the page's answer, already graded at each journey's end: a driver's own
|
|
488
|
+
* "not done" (a lane whose model call failed) read "but the goal was not reached" beside it.
|
|
489
|
+
*/
|
|
490
|
+
export function goalOfRun(drives, journeys) {
|
|
491
|
+
if (0 < journeys.length && journeys.every((j) => ScriptStatus.PASSED === j.status))
|
|
492
|
+
return {};
|
|
295
493
|
const judged = drives.flatMap((d) => (d.goalMet === undefined ? [] : [d.goalMet]));
|
|
296
494
|
return 0 === judged.length ? {} : { goalMet: judged.every(Boolean) };
|
|
297
495
|
}
|
|
@@ -316,6 +514,26 @@ async function crawlApp(deps, options, harness, driver) {
|
|
|
316
514
|
return undefined;
|
|
317
515
|
}
|
|
318
516
|
}
|
|
517
|
+
/** The platform plan the newest saved run as `focus` ran, or undefined when none did. */
|
|
518
|
+
async function planMadeFor(deps, sessionId, focus) {
|
|
519
|
+
try {
|
|
520
|
+
const dir = reticleDirPaths(sessionRoot(deps, sessionId)).plans;
|
|
521
|
+
const files = (await deps.fs.readdir(dir))
|
|
522
|
+
.filter((f) => f.endsWith('.json'))
|
|
523
|
+
.sort()
|
|
524
|
+
.reverse();
|
|
525
|
+
for (const file of files) {
|
|
526
|
+
const saved = asRecord(JSON.parse(await deps.fs.readFile(join(dir, file))));
|
|
527
|
+
const planId = saved['planId'];
|
|
528
|
+
if (focus === saved['focus'] && 'string' === typeof planId)
|
|
529
|
+
return planId;
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
catch {
|
|
533
|
+
/* no plans yet: this persona is planned afresh */
|
|
534
|
+
}
|
|
535
|
+
return undefined;
|
|
536
|
+
}
|
|
319
537
|
/**
|
|
320
538
|
* The controls the last crawl saw, from the newest saved plan that kept them. The planner reads the
|
|
321
539
|
* start page only; without these it never learned the refund buttons on another page existed, and
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { ToolDeps } from './tool-kit.js';
|
|
2
|
+
/** Said when the agent acts in a tab the Harness is driving. */
|
|
3
|
+
export declare const msgHarnessHasTheTab: (runId: string) => string;
|
|
4
|
+
/** The Harness run driving the tab this agent call would act on, unless the call is the Harness's. */
|
|
5
|
+
export declare function harnessDriving<Ext>(deps: ToolDeps<Ext>, args: Record<string, unknown>): string | undefined;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One driver per tab. The Harness clicking through a page while the agent clicks too is two hands on
|
|
3
|
+
* one mouse: neither result means anything. While a Harness run drives a tab, the agent's own
|
|
4
|
+
* actions in it are refused with how to wait for the run or stop it; its reads still run.
|
|
5
|
+
*/
|
|
6
|
+
import { ReticleTool } from '@reticlehq/core';
|
|
7
|
+
import { runningDrive, runningDrives } from '../../features/harness/drive-runs.js';
|
|
8
|
+
import { currentDrivenBy } from '../../hooks/driven-by.js';
|
|
9
|
+
import { sessionIdFromArgs } from './tools-helpers.js';
|
|
10
|
+
/** Said when the agent acts in a tab the Harness is driving. */
|
|
11
|
+
export const msgHarnessHasTheTab = (runId) => `Reticle Harness is driving this tab now (run ${runId}), so this action did not run. Wait for ` +
|
|
12
|
+
`its result with ${ReticleTool.VERIFY} { action: "explore", runId: "${runId}" }, or stop it ` +
|
|
13
|
+
`with the same call and stop: true, then act.`;
|
|
14
|
+
/** The Harness run driving the tab this agent call would act on, unless the call is the Harness's. */
|
|
15
|
+
export function harnessDriving(deps, args) {
|
|
16
|
+
// No drive anywhere is the usual case, and it touches nothing: not even which tab this call is.
|
|
17
|
+
if (currentDrivenBy() !== undefined || 0 === runningDrives().length)
|
|
18
|
+
return undefined;
|
|
19
|
+
let sessionId;
|
|
20
|
+
try {
|
|
21
|
+
sessionId = deps.sessions.resolve(sessionIdFromArgs(args)).id;
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
return undefined; // no tab: the action fails on its own, with the no-session answer
|
|
25
|
+
}
|
|
26
|
+
return runningDrive(sessionId)?.harnessRun;
|
|
27
|
+
}
|
|
@@ -17,6 +17,8 @@ export interface ReticleToolsetOptions {
|
|
|
17
17
|
only?: readonly string[];
|
|
18
18
|
/** Stamped on every action this drive journals, so its verdicts fold into a run of their own. */
|
|
19
19
|
drivenBy?: DrivenBy;
|
|
20
|
+
/** The person's own request: the only text that lets the drive press an outward control. */
|
|
21
|
+
asked?: string;
|
|
20
22
|
/** The pinned session wins over any a call names: a remote caller never reaches another tab. */
|
|
21
23
|
locked?: boolean;
|
|
22
24
|
}
|
|
@@ -28,6 +30,12 @@ export interface ReticleToolsetOptions {
|
|
|
28
30
|
* a harness run a measurement of the product rather than of a test harness.
|
|
29
31
|
*/
|
|
30
32
|
export declare function reticleToolset(deps: ToolDeps, options?: ReticleToolsetOptions): HarnessToolset;
|
|
33
|
+
/**
|
|
34
|
+
* A request the Harness declares must succeed (`ok: true`) unless its claim names a status. A net
|
|
35
|
+
* claim with no status is met by any answer, so a sign-in whose `POST /api/login` came back 401 was
|
|
36
|
+
* counted as a check that held. Applied to the top-level claim of a wait or an assert.
|
|
37
|
+
*/
|
|
38
|
+
export declare function requestMustSucceed(args: Record<string, unknown>): Record<string, unknown>;
|
|
31
39
|
/**
|
|
32
40
|
* Stamp the drive's own session onto a call.
|
|
33
41
|
*
|
|
@@ -9,12 +9,13 @@
|
|
|
9
9
|
*/
|
|
10
10
|
import { z } from 'zod';
|
|
11
11
|
import { zodToJsonSchema } from 'zod-to-json-schema';
|
|
12
|
-
import { AppRuntime, ConsequenceKind, NetInitiator, ReticleTool, } from '@reticlehq/core';
|
|
12
|
+
import { AppRuntime, ConsequenceKind, NetInitiator, PredicateKind, ReticleTool, } from '@reticlehq/core';
|
|
13
13
|
import { TOOLS } from './tools.js';
|
|
14
14
|
import { runTool } from './invoke-tool.js';
|
|
15
15
|
import { TOOL_SURFACE, filterTools } from './tool-surface.js';
|
|
16
16
|
import { withTimeout } from '../../features/harness/with-timeout.js';
|
|
17
17
|
import { runDrivenBy } from '../../hooks/driven-by.js';
|
|
18
|
+
import { noteDriveStep } from '../../features/harness/drive-runs.js';
|
|
18
19
|
/**
|
|
19
20
|
* The two tools the harness is given beyond the advertised surface.
|
|
20
21
|
*
|
|
@@ -25,7 +26,7 @@ import { runDrivenBy } from '../../hooks/driven-by.js';
|
|
|
25
26
|
* sometimes skip, which silently turns the cheap path off.
|
|
26
27
|
*/
|
|
27
28
|
/**
|
|
28
|
-
* Beyond the default surface, the
|
|
29
|
+
* Beyond the default surface, the tools a drive cannot do its job without.
|
|
29
30
|
*
|
|
30
31
|
* RECORD and FLOW_SAVE are how a drive keeps what it drove. FLOW_REPLAY is how it avoids driving
|
|
31
32
|
* the same thing twice — it was absent, so a driver handed a plan full of already-recorded journeys
|
|
@@ -35,6 +36,9 @@ const HARNESS_EXTRA_TOOLS = [
|
|
|
35
36
|
ReticleTool.RECORD,
|
|
36
37
|
ReticleTool.FLOW_SAVE,
|
|
37
38
|
ReticleTool.FLOW_REPLAY,
|
|
39
|
+
// A goal below the fold stayed `unknown` on a drive told to scroll to it: nothing it was offered
|
|
40
|
+
// could scroll. This one brings an element into view by the same query a find uses.
|
|
41
|
+
ReticleTool.SCROLL_TO,
|
|
38
42
|
];
|
|
39
43
|
/**
|
|
40
44
|
* The one deliberate subtraction.
|
|
@@ -144,17 +148,36 @@ export function reticleToolset(deps, options = {}) {
|
|
|
144
148
|
// list, and this is the same recovery the MCP surface gives an agent that does the same.
|
|
145
149
|
return { error: `unknown tool ${target ?? name}`, available: [...byName.keys()] };
|
|
146
150
|
}
|
|
147
|
-
const pinned = pinSession(targetArgs, options.sessionId, true === options.locked);
|
|
151
|
+
const pinned = pinSession(options.drivenBy === undefined ? targetArgs : requestMustSucceed(targetArgs), options.sessionId, true === options.locked);
|
|
148
152
|
const scoped = isDesktopSession(deps, pinned['sessionId'])
|
|
149
153
|
? desktopBackendClaims(pinned)
|
|
150
154
|
: pinned;
|
|
151
155
|
const drivenBy = options.drivenBy;
|
|
156
|
+
if (drivenBy !== undefined)
|
|
157
|
+
noteDriveStep(drivenBy.harness, tool.name);
|
|
152
158
|
return withTimeout(drivenBy === undefined
|
|
153
159
|
? runTool(tool, deps, scoped)
|
|
154
|
-
: runDrivenBy(drivenBy, () => runTool(tool, deps, scoped)), TOOL_TIMEOUT_MS, `${tool.name} never returned`);
|
|
160
|
+
: runDrivenBy(drivenBy, () => runTool(tool, deps, scoped), options.asked), TOOL_TIMEOUT_MS, `${tool.name} never returned`);
|
|
155
161
|
},
|
|
156
162
|
};
|
|
157
163
|
}
|
|
164
|
+
/**
|
|
165
|
+
* A request the Harness declares must succeed (`ok: true`) unless its claim names a status. A net
|
|
166
|
+
* claim with no status is met by any answer, so a sign-in whose `POST /api/login` came back 401 was
|
|
167
|
+
* counted as a check that held. Applied to the top-level claim of a wait or an assert.
|
|
168
|
+
*/
|
|
169
|
+
export function requestMustSucceed(args) {
|
|
170
|
+
const out = { ...args };
|
|
171
|
+
for (const key of ['until', 'predicate']) {
|
|
172
|
+
const claim = args[key];
|
|
173
|
+
if ('object' !== typeof claim || null === claim)
|
|
174
|
+
continue;
|
|
175
|
+
const p = claim;
|
|
176
|
+
if (PredicateKind.NET === p['kind'] && undefined === p['status'] && undefined === p['ok'])
|
|
177
|
+
out[key] = { ...p, ok: true };
|
|
178
|
+
}
|
|
179
|
+
return out;
|
|
180
|
+
}
|
|
158
181
|
/**
|
|
159
182
|
* Stamp the drive's own session onto a call.
|
|
160
183
|
*
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The notes a person sent from the HUD, handed to the agent on whatever Reticle call it makes next.
|
|
3
|
+
*
|
|
4
|
+
* Act tools already splice them (`withControl`); every other tool did not, so a note waited until
|
|
5
|
+
* the agent happened to drive the page or poll `messages`. Taken here, once, from the tab the call
|
|
6
|
+
* is about; a call that names no tab and cannot resolve one takes every tab's, since a note held
|
|
7
|
+
* back is a note the person believes was read.
|
|
8
|
+
*/
|
|
9
|
+
import type { Session } from '../../portal/session/session.js';
|
|
10
|
+
import type { SessionManager } from '../../portal/session/session-manager.js';
|
|
11
|
+
import type { SessionState } from '@reticlehq/core';
|
|
12
|
+
export interface HumanNotes {
|
|
13
|
+
state: SessionState;
|
|
14
|
+
guidance: string[];
|
|
15
|
+
}
|
|
16
|
+
export declare function takeHumanNotes(sessions: SessionManager, sessionId: string | undefined, session: Session | undefined): HumanNotes | undefined;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export function takeHumanNotes(sessions, sessionId, session) {
|
|
2
|
+
let target = session;
|
|
3
|
+
if (target === undefined) {
|
|
4
|
+
try {
|
|
5
|
+
target = sessions.resolve(sessionId);
|
|
6
|
+
}
|
|
7
|
+
catch {
|
|
8
|
+
target = undefined;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
// ponytail: an unresolvable call takes every tab's notes; per-agent routing is the upgrade if two
|
|
12
|
+
// agents ever share one daemon on different apps and a note lands with the wrong one.
|
|
13
|
+
try {
|
|
14
|
+
const holding = (target === undefined ? (sessions.all?.() ?? []) : [target]).filter((tab) => 0 < tab.inboxSize());
|
|
15
|
+
const first = holding[0];
|
|
16
|
+
if (first === undefined)
|
|
17
|
+
return undefined;
|
|
18
|
+
return {
|
|
19
|
+
state: first.getState(),
|
|
20
|
+
guidance: holding.flatMap((tab) => tab.drainInbox().map((message) => message.text)),
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
// A courtesy on every call is never the reason a call fails; the notes stay queued.
|
|
25
|
+
return undefined;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { type NoticeFold } from './agent/notices.js';
|
|
2
|
+
import type { ToolCall, ToolDef, ToolDeps } from './tool-kit.js';
|
|
2
3
|
export declare const SESSION_BOUND_TOOLS: ReadonlySet<string>;
|
|
3
4
|
/**
|
|
4
5
|
* Tools that carry a `sessionId` arg but are NOT live-session-health tools — they read/write
|
|
@@ -7,4 +8,6 @@ export declare const SESSION_BOUND_TOOLS: ReadonlySet<string>;
|
|
|
7
8
|
* `sessionId`-bearing tool to be classified into exactly one set (bound XOR exempt).
|
|
8
9
|
*/
|
|
9
10
|
export declare const SESSION_EXEMPT_TOOLS: ReadonlySet<string>;
|
|
10
|
-
export declare function runTool<Ext>(tool: ToolDef<Ext>, deps: ToolDeps<Ext>,
|
|
11
|
+
export declare function runTool<Ext>(tool: ToolDef<Ext>, deps: ToolDeps<Ext>, given: Record<string, unknown>, call?: ToolCall): Promise<unknown>;
|
|
12
|
+
/** Advisories that become once-per-session notice lines. See agent/notices.ts. */
|
|
13
|
+
export declare const NOTICE_FOLD: NoticeFold;
|