@reticlehq/server 3.7.0 → 3.8.1
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 +59 -68
- package/bin/reticle.js +9 -2
- package/dist/command/cli/adhoc-suite.js +1 -1
- package/dist/command/cli/adhoc-verdict.d.ts +12 -0
- package/dist/command/cli/adhoc-verdict.js +62 -4
- package/dist/command/cli/answers/gate-hook-message.d.ts +2 -0
- package/dist/command/cli/answers/gate-hook-message.js +5 -1
- package/dist/command/cli/auth/cloud-session.d.ts +11 -19
- package/dist/command/cli/auth/cloud-session.js +23 -0
- package/dist/command/cli/auth/device-flow.d.ts +3 -37
- package/dist/command/cli/cli-doctor.js +66 -21
- package/dist/command/cli/cli-flow-commands.js +53 -11
- package/dist/command/cli/cli-kill.d.ts +8 -0
- package/dist/command/cli/cli-kill.js +43 -3
- package/dist/command/cli/cli-parse-feedback.d.ts +4 -0
- package/dist/command/cli/cli-parse-feedback.js +13 -1
- package/dist/command/cli/cli-parse-grammar.d.ts +1 -2
- package/dist/command/cli/cli-parse-grammar.js +1 -6
- package/dist/command/cli/cli-parse-serve.d.ts +24 -0
- package/dist/command/cli/cli-parse-serve.js +124 -0
- package/dist/command/cli/cli-parse.d.ts +12 -11
- package/dist/command/cli/cli-parse.js +100 -123
- package/dist/command/cli/cli-usage.d.ts +0 -11
- package/dist/command/cli/cli-usage.js +43 -16
- package/dist/command/cli/cli-verify.d.ts +1 -1
- package/dist/command/cli/cli-verify.js +29 -14
- package/dist/command/cli/cloud-cli.js +27 -9
- package/dist/command/cli/cloud-kit.js +3 -3
- package/dist/command/cli/cloud-link.d.ts +1 -20
- package/dist/command/cli/cloud-link.js +2 -0
- package/dist/command/cli/cloud-login.d.ts +6 -2
- package/dist/command/cli/cloud-login.js +13 -41
- package/dist/command/cli/config/checkout.d.ts +10 -0
- package/dist/command/cli/config/checkout.js +78 -0
- package/dist/command/cli/doctor/doctor-agent-link.d.ts +23 -0
- package/dist/command/cli/doctor/doctor-agent-link.js +28 -0
- package/dist/command/cli/doctor/doctor-coverage-line.js +1 -7
- package/dist/command/cli/doctor/doctor-rows.d.ts +4 -0
- package/dist/command/cli/doctor/doctor-rows.js +4 -0
- package/dist/command/cli/drive/drive-attach.d.ts +5 -0
- package/dist/command/cli/drive/drive-attach.js +21 -1
- package/dist/command/cli/hook/codex-transcript.d.ts +20 -0
- package/dist/command/cli/hook/codex-transcript.js +224 -0
- package/dist/command/cli/hook/episode-structure.d.ts +24 -0
- package/dist/command/cli/hook/episode-structure.js +138 -0
- package/dist/command/cli/hook/hook-command.d.ts +9 -0
- package/dist/command/cli/hook/hook-command.js +211 -0
- package/dist/command/cli/hook/hook-fast.d.ts +31 -0
- package/dist/command/cli/hook/hook-fast.js +136 -0
- package/dist/command/cli/hook/prompt-hook.d.ts +30 -0
- package/dist/command/cli/hook/prompt-hook.js +199 -0
- package/dist/command/cli/hook/tool-hook.d.ts +21 -0
- package/dist/command/cli/hook/tool-hook.js +259 -0
- package/dist/command/cli/launch/cli-launch.d.ts +2 -0
- package/dist/command/cli/launch/cli-launch.js +22 -2
- package/dist/command/cli/lifecycle/daemon-lifecycle.js +28 -2
- package/dist/command/cli/mcp-command.d.ts +9 -0
- package/dist/command/cli/mcp-command.js +127 -41
- package/dist/command/cli/open-navigate.d.ts +43 -0
- package/dist/command/cli/open-navigate.js +85 -0
- package/dist/command/cli/ports/port-holder.d.ts +16 -4
- package/dist/command/cli/ports/port-holder.js +58 -12
- package/dist/command/cli/ports/resolve/cli-port.js +18 -2
- package/dist/command/cli/project-name.d.ts +1 -7
- package/dist/command/cli/project-name.js +1 -0
- package/dist/command/cli/report-command.d.ts +8 -2
- package/dist/command/cli/report-command.js +95 -18
- package/dist/command/cli/status-fields.d.ts +9 -2
- package/dist/command/cli/status-fields.js +148 -4
- package/dist/command/cli/try-command.d.ts +3 -4
- package/dist/command/cli/try-command.js +6 -11
- package/dist/command/cli/verify-results.d.ts +4 -1
- package/dist/command/cli/verify-results.js +3 -1
- package/dist/command/cli.d.ts +1 -7
- package/dist/command/cli.js +79 -160
- package/dist/command/daemon/daemon-resilience.d.ts +6 -1
- package/dist/command/daemon/daemon-resilience.js +31 -18
- package/dist/command/daemon/daemon.d.ts +11 -0
- package/dist/command/daemon/daemon.js +70 -2
- package/dist/command/daemon/lifetime/daemon-usefulness.d.ts +2 -0
- package/dist/command/daemon/lifetime/daemon-usefulness.js +13 -2
- package/dist/command/daemon/wake-decision.js +4 -2
- package/dist/command/daemon/win32-escape.d.ts +32 -0
- package/dist/command/daemon/win32-escape.js +119 -0
- package/dist/command/setup/agent-configs.d.ts +9 -0
- package/dist/command/setup/agent-configs.js +9 -0
- package/dist/command/setup/auto-approve.d.ts +10 -3
- package/dist/command/setup/auto-approve.js +51 -3
- package/dist/command/setup/bringup/dev-server-files.d.ts +1 -9
- package/dist/command/setup/bringup/dev-server-wait.js +5 -1
- package/dist/command/setup/bringup/ensure-daemon.js +4 -7
- package/dist/command/setup/init/init-host.js +6 -0
- package/dist/command/setup/init/init-port.js +5 -4
- package/dist/command/setup/init/init-runtime.js +7 -1
- package/dist/command/setup/node-effects.d.ts +8 -0
- package/dist/command/setup/node-effects.js +36 -4
- package/dist/command/setup/probe/dev-port.d.ts +26 -0
- package/dist/command/setup/probe/dev-port.js +117 -0
- package/dist/command/setup/probe/page-probe.d.ts +1 -1
- package/dist/command/setup/probe/page-probe.js +11 -3
- package/dist/command/setup/remaining-steps.d.ts +0 -7
- package/dist/command/setup/remaining-steps.js +3 -2
- package/dist/command/setup/run-setup.d.ts +11 -0
- package/dist/command/setup/run-setup.js +33 -5
- package/dist/command/setup/setup-command.d.ts +2 -0
- package/dist/command/setup/setup-command.js +22 -4
- package/dist/command/update/updater.d.ts +1 -6
- package/dist/command/update/updater.js +4 -5
- package/dist/command/update/version-seen.d.ts +24 -0
- package/dist/command/update/version-seen.js +65 -0
- package/dist/command/version/peer-announce.d.ts +9 -1
- package/dist/command/version/peer-announce.js +25 -2
- package/dist/command/version/sdk-fix.d.ts +5 -6
- package/dist/command/version/sdk-fix.js +17 -32
- package/dist/command/version/version-skew.d.ts +16 -1
- package/dist/command/version/version-skew.js +84 -10
- package/dist/features/crawl/crawl-tools.js +2 -2
- package/dist/features/crawl/crawl.js +2 -0
- package/dist/features/exhaust/ledger.d.ts +15 -96
- package/dist/features/exhaust/ledger.js +3 -3
- package/dist/features/harness/drive-runs.d.ts +28 -4
- package/dist/features/harness/drive-runs.js +99 -7
- package/dist/features/harness/drivers.d.ts +1 -1
- package/dist/features/harness/drivers.js +1 -1
- package/dist/features/harness/harness.d.ts +5 -0
- package/dist/features/harness/harness.js +24 -12
- package/dist/features/harness/platform/platform-drives.d.ts +7 -1
- package/dist/features/harness/platform/platform-drives.js +12 -7
- package/dist/features/harness/platform/refusal.d.ts +1 -1
- package/dist/features/harness/platform/refusal.js +4 -4
- package/dist/features/harness/platform/remote-drive.js +70 -28
- package/dist/features/harness/platform/server-driver.js +22 -1
- package/dist/features/harness/platform-config.d.ts +1 -10
- package/dist/features/harness/platform-config.js +0 -20
- package/dist/features/license/license.d.ts +2 -14
- package/dist/features/visual/step-shots.d.ts +33 -1
- package/dist/features/visual/step-shots.js +155 -1
- package/dist/features/visual/visual-tools.js +12 -4
- package/dist/hooks/coding-agents.d.ts +6 -0
- package/dist/hooks/coding-agents.js +24 -3
- package/dist/hooks/episode-stamp.d.ts +32 -0
- package/dist/hooks/episode-stamp.js +61 -0
- package/dist/hooks/hook-commands.js +19 -9
- package/dist/index.d.ts +5 -1
- package/dist/index.js +66 -24
- package/dist/judgement/app-graph/journal-steps.d.ts +8 -0
- package/dist/judgement/app-graph/journal-steps.js +92 -0
- package/dist/judgement/capsule/capsule-store.d.ts +2 -39
- package/dist/judgement/domain/domain-model.js +1 -10
- package/dist/judgement/domain/domain-tools.js +4 -2
- package/dist/judgement/runs/artifact/run-store.d.ts +28 -8
- package/dist/judgement/runs/artifact/run-store.js +153 -28
- package/dist/judgement/runs/default-run-id.d.ts +3 -1
- package/dist/judgement/runs/default-run-id.js +15 -3
- package/dist/judgement/runs/drive-run.d.ts +3 -3
- package/dist/judgement/runs/drive-run.js +11 -7
- package/dist/judgement/runs/run-ledger.d.ts +21 -0
- package/dist/judgement/runs/run-ledger.js +143 -0
- package/dist/judgement/runs/runner-port.d.ts +1 -1
- package/dist/judgement/runs/runner-port.js +8 -2
- package/dist/judgement/runs/verification-sync.d.ts +4 -3
- package/dist/judgement/runs/verification-sync.js +27 -5
- package/dist/language/flows/affected-tools.js +2 -1
- package/dist/language/flows/annotate-notes/annotate.js +8 -3
- package/dist/language/flows/annotate-tools.js +1 -1
- package/dist/language/flows/change/affected.d.ts +8 -0
- package/dist/language/flows/change/affected.js +20 -7
- package/dist/language/flows/decision.js +19 -4
- package/dist/language/flows/fields/flow-secret-field.d.ts +9 -0
- package/dist/language/flows/fields/flow-secret-field.js +67 -5
- package/dist/language/flows/flow-anchor.d.ts +5 -0
- package/dist/language/flows/flow-anchor.js +4 -0
- package/dist/language/flows/flow-cross-step.d.ts +7 -1
- package/dist/language/flows/flow-cross-step.js +9 -0
- package/dist/language/flows/flow-expect-grammar.js +15 -10
- package/dist/language/flows/flow-intent.js +6 -1
- package/dist/language/flows/flow-journey.d.ts +8 -0
- package/dist/language/flows/flow-journey.js +13 -0
- package/dist/language/flows/flow-lease.d.ts +27 -0
- package/dist/language/flows/flow-lease.js +59 -0
- package/dist/language/flows/flow-replay-run.d.ts +1 -87
- package/dist/language/flows/flow-replay-run.js +111 -310
- package/dist/language/flows/flow-replay.js +21 -19
- package/dist/language/flows/flow-replayable.d.ts +38 -0
- package/dist/language/flows/flow-replayable.js +179 -0
- package/dist/language/flows/flow-start-path.d.ts +108 -0
- package/dist/language/flows/flow-start-path.js +313 -0
- package/dist/language/flows/flow-step-runners.d.ts +23 -2
- package/dist/language/flows/flow-step-runners.js +191 -32
- package/dist/language/flows/flow-store-for-session.d.ts +8 -1
- package/dist/language/flows/flow-store-for-session.js +6 -0
- package/dist/language/flows/flow-tools.d.ts +2 -23
- package/dist/language/flows/flow-tools.js +63 -113
- package/dist/language/flows/flows.d.ts +4 -6
- package/dist/language/flows/flows.js +90 -15
- package/dist/language/flows/heal-run.d.ts +10 -4
- package/dist/language/flows/heal-run.js +26 -9
- package/dist/language/flows/recording/flake.d.ts +3 -27
- package/dist/language/flows/recording/flake.js +1 -1
- package/dist/language/flows/recording/recording-backtrack.js +1 -4
- package/dist/language/flows/recording/tape/recordings.d.ts +11 -1
- package/dist/language/flows/recording/tape/recordings.js +9 -3
- package/dist/language/flows/replay.d.ts +25 -5
- package/dist/language/flows/replay.js +83 -16
- package/dist/language/flows/stores/assertion-tiers-store.js +1 -1
- package/dist/language/flows/suite/coverage.d.ts +9 -0
- package/dist/language/flows/suite/coverage.js +12 -1
- package/dist/language/flows/suite-selection.d.ts +25 -0
- package/dist/language/flows/suite-selection.js +41 -9
- package/dist/machine/git-tracks.d.ts +6 -0
- package/dist/machine/git-tracks.js +36 -0
- package/dist/memory/cloud/background-sync.d.ts +25 -0
- package/dist/memory/cloud/background-sync.js +79 -0
- package/dist/memory/cloud/cloud-config.d.ts +12 -1
- package/dist/memory/cloud/cloud-config.js +39 -13
- package/dist/memory/cloud/cloud-sync.d.ts +3 -24
- package/dist/memory/cloud/cloud-sync.js +5 -2
- package/dist/memory/cloud/harness-config.d.ts +0 -7
- package/dist/memory/cloud/memory-scope.d.ts +19 -0
- package/dist/memory/cloud/memory-scope.js +48 -0
- package/dist/memory/cloud/sync-answer.d.ts +43 -0
- package/dist/memory/cloud/sync-answer.js +42 -0
- package/dist/memory/cloud/sync-cycle.d.ts +40 -10
- package/dist/memory/cloud/sync-cycle.js +97 -144
- package/dist/memory/cloud/sync-daemon.d.ts +50 -3
- package/dist/memory/cloud/sync-daemon.js +473 -83
- package/dist/memory/cloud/sync-describe.d.ts +28 -0
- package/dist/memory/cloud/sync-describe.js +92 -0
- package/dist/memory/cloud/sync-disk.d.ts +9 -1
- package/dist/memory/cloud/sync-disk.js +137 -33
- package/dist/memory/cloud/sync-flow-versions.d.ts +26 -0
- package/dist/memory/cloud/sync-flow-versions.js +42 -0
- package/dist/memory/impact/impact-store.js +32 -15
- package/dist/memory/intent/intent-shard.d.ts +41 -266
- package/dist/memory/intent/intent-tools.js +20 -61
- package/dist/memory/intent/record-request.d.ts +27 -0
- package/dist/memory/intent/record-request.js +88 -0
- package/dist/memory/intent/settled-words.js +9 -1
- package/dist/memory/journal/drive-flow.d.ts +3 -0
- package/dist/memory/journal/drive-flow.js +11 -41
- package/dist/memory/journal/envelope-store.js +1 -1
- package/dist/memory/journal/envelope.d.ts +6 -154
- package/dist/memory/journal/episode-log.d.ts +107 -0
- package/dist/memory/journal/episode-log.js +302 -0
- package/dist/memory/journal/journal-recorder.d.ts +7 -0
- package/dist/memory/journal/journal-recorder.js +22 -9
- package/dist/memory/journal/on-disk/ambient-file.d.ts +1 -7
- package/dist/memory/journal/on-disk/ambient-file.js +1 -1
- package/dist/memory/journal/on-disk/workspace-gitignore.d.ts +24 -3
- package/dist/memory/journal/on-disk/workspace-gitignore.js +38 -7
- package/dist/memory/journal/on-disk/workspace-tiers.js +7 -0
- package/dist/memory/journal/self-observation.js +3 -1
- package/dist/memory/journal/session-end.js +23 -9
- package/dist/memory/journal/session-journal.js +39 -20
- package/dist/memory/project/artifact-root-resolver.d.ts +14 -1
- package/dist/memory/project/artifact-root-resolver.js +68 -23
- package/dist/memory/project/artifact-root.d.ts +17 -3
- package/dist/memory/project/artifact-root.js +47 -9
- package/dist/memory/project/fs/fs-port.d.ts +5 -0
- package/dist/memory/project/fs/fs-port.js +13 -0
- package/dist/memory/project/learned-routes.d.ts +3 -4
- package/dist/memory/project/learned-routes.js +3 -11
- package/dist/memory/project/link-directory.js +5 -2
- package/dist/memory/project/root-claims.d.ts +3 -1
- package/dist/memory/project/root-claims.js +41 -7
- package/dist/memory/project/session-root.d.ts +1 -1
- package/dist/memory/project/session-root.js +1 -15
- package/dist/memory/project/sync-status.js +5 -6
- package/dist/memory/recall/memory-tools.js +2 -2
- package/dist/memory/recall/platform-memory.d.ts +3 -1
- package/dist/memory/recall/platform-memory.js +9 -1
- package/dist/memory/recall/project-memory.js +15 -19
- package/dist/portal/bridge/auth-failure-reason.d.ts +13 -0
- package/dist/portal/bridge/auth-failure-reason.js +19 -0
- package/dist/portal/bridge/bridge.d.ts +19 -4
- package/dist/portal/bridge/bridge.js +150 -177
- package/dist/portal/bridge/harness-request.d.ts +15 -0
- package/dist/portal/bridge/harness-request.js +19 -0
- package/dist/portal/bridge/origin/origin-follow.d.ts +46 -0
- package/dist/portal/bridge/origin/origin-follow.js +110 -0
- package/dist/portal/bridge/pairing-token.d.ts +6 -0
- package/dist/portal/bridge/pairing-token.js +47 -16
- package/dist/portal/bridge/protocol-skew.d.ts +27 -2
- package/dist/portal/bridge/protocol-skew.js +66 -2
- package/dist/portal/bridge/session-nonces.d.ts +46 -0
- package/dist/portal/bridge/session-nonces.js +72 -0
- package/dist/portal/input/viewport-tools.d.ts +31 -0
- package/dist/portal/input/viewport-tools.js +106 -15
- package/dist/portal/pool/bounded-close.d.ts +23 -0
- package/dist/portal/pool/bounded-close.js +38 -0
- package/dist/portal/pool/browser-pool.d.ts +44 -39
- package/dist/portal/pool/browser-pool.js +247 -95
- package/dist/portal/pool/context-permissions.d.ts +9 -1
- package/dist/portal/pool/context-permissions.js +26 -0
- package/dist/portal/pool/lease-emulation.d.ts +37 -0
- package/dist/portal/pool/lease-emulation.js +29 -0
- package/dist/portal/pool/playwright-launcher.d.ts +6 -0
- package/dist/portal/pool/playwright-launcher.js +74 -7
- package/dist/portal/pool/pool-contract.d.ts +23 -1
- package/dist/portal/pool/pool-lease.d.ts +128 -0
- package/dist/portal/pool/pool-lease.js +49 -0
- package/dist/portal/pool/zero-install.d.ts +8 -1
- package/dist/portal/pool/zero-install.js +24 -2
- package/dist/portal/production/production-activation.d.ts +136 -0
- package/dist/portal/production/production-activation.js +173 -0
- package/dist/portal/production/production-drive.d.ts +52 -0
- package/dist/portal/production/production-drive.js +301 -0
- package/dist/portal/production/production-hello.d.ts +23 -0
- package/dist/portal/production/production-hello.js +23 -0
- package/dist/portal/realm/web-realm.js +42 -15
- package/dist/portal/session/control-envelope.d.ts +1 -1
- package/dist/portal/session/dev-server/served-document.d.ts +0 -5
- package/dist/portal/session/dev-server/served-document.js +6 -8
- package/dist/portal/session/facts/handshake-facts.d.ts +8 -1
- package/dist/portal/session/first-run-wiring.d.ts +3 -36
- package/dist/portal/session/first-run-wiring.js +10 -103
- package/dist/portal/session/live-control-tools.js +61 -19
- package/dist/portal/session/no-session-next-action.d.ts +11 -0
- package/dist/portal/session/no-session-next-action.js +40 -15
- package/dist/portal/session/no-session-watch.d.ts +7 -0
- package/dist/portal/session/no-session-watch.js +67 -23
- package/dist/portal/session/output-budget.d.ts +10 -0
- package/dist/portal/session/output-budget.js +16 -0
- package/dist/portal/session/presence/session-lease.d.ts +2 -0
- package/dist/portal/session/presence/session-lease.js +8 -0
- package/dist/portal/session/recorded-gaps.d.ts +15 -11
- package/dist/portal/session/recorded-gaps.js +39 -18
- package/dist/portal/session/serving-directory.d.ts +24 -2
- package/dist/portal/session/serving-directory.js +93 -5
- package/dist/portal/session/session-info.d.ts +26 -0
- package/dist/portal/session/session-info.js +20 -0
- package/dist/portal/session/session-manager.d.ts +35 -3
- package/dist/portal/session/session-manager.js +69 -14
- package/dist/portal/session/session-successor.js +1 -9
- package/dist/portal/session/session-tools.js +22 -4
- package/dist/portal/session/session.d.ts +10 -10
- package/dist/portal/session/session.js +37 -29
- package/dist/portal/session/zero-install-first-call.d.ts +7 -2
- package/dist/portal/session/zero-install-first-call.js +43 -20
- package/dist/start-wiring.d.ts +2 -2
- package/dist/start-wiring.js +17 -3
- package/dist/status-payload.d.ts +11 -1
- package/dist/status-payload.js +7 -1
- package/dist/surface/agent-presence-grace.d.ts +11 -0
- package/dist/surface/agent-presence-grace.js +34 -0
- package/dist/surface/http-server.d.ts +12 -1
- package/dist/surface/http-server.js +64 -15
- package/dist/surface/mcp/faults/mcp-outage.d.ts +12 -2
- package/dist/surface/mcp/faults/mcp-outage.js +19 -1
- package/dist/surface/mcp/mcp-proxy.d.ts +17 -74
- package/dist/surface/mcp/mcp-proxy.js +194 -267
- package/dist/surface/mcp/mcp.d.ts +20 -3
- package/dist/surface/mcp/mcp.js +88 -25
- package/dist/surface/mcp/proxy/drive-calls.d.ts +44 -0
- package/dist/surface/mcp/proxy/drive-calls.js +114 -5
- package/dist/surface/mcp/proxy/proxy-boot.d.ts +11 -0
- package/dist/surface/mcp/proxy/proxy-boot.js +1 -0
- package/dist/surface/mcp/proxy/proxy-daemon-probe.d.ts +6 -0
- package/dist/surface/mcp/proxy/proxy-daemon-probe.js +14 -1
- package/dist/surface/mcp/proxy/proxy-handshake.d.ts +34 -2
- package/dist/surface/mcp/proxy/proxy-handshake.js +76 -8
- package/dist/surface/mcp/server-instructions.js +35 -16
- package/dist/surface/mcp/shared-params.d.ts +8 -0
- package/dist/surface/mcp/shared-params.js +15 -1
- package/dist/surface/mcp/sse-frame-parser.d.ts +11 -0
- package/dist/surface/mcp/sse-frame-parser.js +18 -0
- package/dist/surface/mcp/surface-vocabulary.d.ts +2 -0
- package/dist/surface/mcp/surface-vocabulary.js +13 -0
- package/dist/surface/mcp/tool-catalog-cache.d.ts +2 -0
- package/dist/surface/mcp/tool-catalog-cache.js +14 -4
- package/dist/surface/tools/account-tool.d.ts +4 -3
- package/dist/surface/tools/account-tool.js +20 -31
- package/dist/surface/tools/act/act-danger.d.ts +2 -0
- package/dist/surface/tools/act/act-danger.js +41 -14
- package/dist/surface/tools/act/act-observation.d.ts +11 -0
- package/dist/surface/tools/act/act-observation.js +33 -0
- package/dist/surface/tools/act/act-preflight.js +10 -3
- package/dist/surface/tools/act/act-sequence-retry.js +2 -1
- package/dist/surface/tools/act/act-target.js +19 -5
- package/dist/surface/tools/act/durable.js +1 -1
- package/dist/surface/tools/act/navigation/navigate-arrival.d.ts +9 -7
- package/dist/surface/tools/act/navigation/navigate-arrival.js +11 -14
- package/dist/surface/tools/act/unsettled-find.d.ts +36 -0
- package/dist/surface/tools/act/unsettled-find.js +71 -0
- package/dist/surface/tools/act-sequence-tool.js +53 -24
- package/dist/surface/tools/act-tools.d.ts +2 -3
- package/dist/surface/tools/act-tools.js +49 -47
- package/dist/surface/tools/agent/compact-envelope.d.ts +2 -2
- package/dist/surface/tools/agent/for-the-agent.js +41 -3
- package/dist/surface/tools/assert/assert-grade.js +8 -3
- package/dist/surface/tools/assert/assert-verdict.js +4 -2
- package/dist/surface/tools/browser-tools.js +7 -4
- package/dist/surface/tools/chat-drives.js +50 -25
- package/dist/surface/tools/coverage-tools.js +1 -1
- package/dist/surface/tools/dynamic-tools.d.ts +8 -0
- package/dist/surface/tools/dynamic-tools.js +89 -34
- package/dist/surface/tools/empty-session-list.d.ts +18 -25
- package/dist/surface/tools/empty-session-list.js +67 -38
- package/dist/surface/tools/error-recovery.d.ts +17 -7
- package/dist/surface/tools/error-recovery.js +53 -20
- package/dist/surface/tools/explore-tools.d.ts +10 -0
- package/dist/surface/tools/explore-tools.js +72 -19
- package/dist/surface/tools/feedback-tools.js +23 -2
- package/dist/surface/tools/gap-novelty.d.ts +6 -0
- package/dist/surface/tools/gap-novelty.js +9 -0
- package/dist/surface/tools/gaps/capability-absences.js +4 -3
- package/dist/surface/tools/harness-explore.d.ts +1 -1
- package/dist/surface/tools/harness-explore.js +6 -4
- package/dist/surface/tools/harness-gate.d.ts +43 -21
- package/dist/surface/tools/harness-gate.js +55 -81
- package/dist/surface/tools/harness-script.d.ts +2 -0
- package/dist/surface/tools/harness-script.js +11 -6
- package/dist/surface/tools/harness-toolset.js +3 -4
- package/dist/surface/tools/invoke-tool.d.ts +0 -8
- package/dist/surface/tools/invoke-tool.js +164 -178
- package/dist/surface/tools/lease-hint.d.ts +9 -0
- package/dist/surface/tools/lease-hint.js +22 -3
- package/dist/surface/tools/lease-permissions.d.ts +1 -1
- package/dist/surface/tools/lease-readiness.d.ts +55 -0
- package/dist/surface/tools/lease-readiness.js +150 -2
- package/dist/surface/tools/lease-tools.d.ts +3 -75
- package/dist/surface/tools/lease-tools.js +124 -188
- package/dist/surface/tools/map-tools.d.ts +20 -0
- package/dist/surface/tools/map-tools.js +145 -0
- package/dist/surface/tools/merge-tools.js +11 -7
- package/dist/surface/tools/next-step.js +6 -3
- package/dist/surface/tools/observe-tools.js +46 -35
- package/dist/surface/tools/platform-moment.d.ts +3 -12
- package/dist/surface/tools/platform-moment.js +12 -24
- package/dist/surface/tools/read/complete-snapshot.d.ts +7 -1
- package/dist/surface/tools/read/complete-snapshot.js +13 -2
- package/dist/surface/tools/read/query-paginate.js +6 -0
- package/dist/surface/tools/read/query-shape.d.ts +9 -0
- package/dist/surface/tools/read/query-shape.js +15 -0
- package/dist/surface/tools/read/snapshot-unmounted-note.d.ts +1 -0
- package/dist/surface/tools/read/snapshot-unmounted-note.js +73 -0
- package/dist/surface/tools/read-tools.js +5 -5
- package/dist/surface/tools/real-input-attempt.d.ts +11 -0
- package/dist/surface/tools/real-input-attempt.js +206 -38
- package/dist/surface/tools/reconcile-tools.js +21 -8
- package/dist/surface/tools/reticle-result.d.ts +3 -0
- package/dist/surface/tools/reticle-result.js +8 -1
- package/dist/surface/tools/run-report.d.ts +22 -0
- package/dist/surface/tools/run-report.js +141 -0
- package/dist/surface/tools/session-ports.d.ts +57 -0
- package/dist/surface/tools/session-ports.js +102 -0
- package/dist/surface/tools/tool-kit.d.ts +58 -4
- package/dist/surface/tools/tool-kit.js +140 -6
- package/dist/surface/tools/tool-surface.d.ts +2 -0
- package/dist/surface/tools/tool-surface.js +45 -0
- package/dist/surface/tools/tools.js +49 -87
- package/dist/telemetry/automation-hint.d.ts +5 -0
- package/dist/telemetry/automation-hint.js +7 -0
- package/dist/telemetry/cli-telemetry.d.ts +22 -0
- package/dist/telemetry/cli-telemetry.js +80 -11
- package/dist/telemetry/daemon-telemetry.d.ts +3 -1
- package/dist/telemetry/daemon-telemetry.js +9 -2
- package/dist/telemetry/feedback-cli.d.ts +1 -1
- package/dist/telemetry/feedback-cli.js +8 -3
- package/dist/telemetry/feedback.d.ts +1 -1
- package/dist/telemetry/feedback.js +51 -4
- package/dist/telemetry/harness-run.d.ts +3 -3
- package/dist/telemetry/harness-run.js +18 -7
- package/dist/telemetry/hud-events.d.ts +1 -1
- package/dist/telemetry/hud-metrics.d.ts +6 -3
- package/dist/telemetry/hud-metrics.js +20 -8
- package/dist/telemetry/install-source.js +1 -1
- package/dist/telemetry/mcp-connection.d.ts +1 -1
- package/dist/telemetry/mcp-connection.js +21 -2
- package/dist/telemetry/onboarding-firsts.d.ts +6 -1
- package/dist/telemetry/onboarding-firsts.js +41 -1
- package/dist/telemetry/proxy-telemetry.d.ts +42 -0
- package/dist/telemetry/proxy-telemetry.js +70 -1
- package/dist/telemetry/session-metrics.d.ts +1 -3
- package/dist/telemetry/session-metrics.js +16 -12
- package/dist/telemetry/telemetry.d.ts +9 -1
- package/dist/telemetry/telemetry.js +16 -1
- package/dist/telemetry/verification-of.d.ts +3 -1
- package/dist/telemetry/verification-of.js +7 -1
- package/dist/wire-journal.js +12 -2
- package/docs/README.md +4 -2
- package/docs/actions.mdx +7 -6
- package/docs/adapters.md +2 -1
- package/docs/agent-cheatsheet.md +19 -5
- package/docs/architecture.md +13 -10
- package/docs/autodrive.md +6 -5
- package/docs/benchmarks.md +2 -2
- package/docs/capabilities.mdx +1 -1
- package/docs/cli/affected.mdx +1 -1
- package/docs/cli/cloud.mdx +6 -6
- package/docs/cli/doctor.mdx +3 -1
- package/docs/cli/feedback.mdx +11 -7
- package/docs/cli/gate.mdx +1 -1
- package/docs/cli/help.mdx +1 -1
- package/docs/cli/init.mdx +20 -16
- package/docs/cli/mcp.mdx +5 -2
- package/docs/cli/open.mdx +5 -2
- package/docs/cli/report.mdx +1 -1
- package/docs/cli/restart.mdx +1 -1
- package/docs/cli/rollback.mdx +4 -4
- package/docs/cli/serve.mdx +7 -5
- package/docs/cli/setup.mdx +1 -1
- package/docs/cli/status.mdx +6 -2
- package/docs/cli/stop.mdx +3 -3
- package/docs/cli/telemetry.mdx +5 -1
- package/docs/cli/try.mdx +8 -8
- package/docs/cli/update.mdx +8 -5
- package/docs/cli/verify.mdx +12 -5
- package/docs/cli/version.mdx +1 -1
- package/docs/cli.mdx +10 -6
- package/docs/debugging.md +1 -1
- package/docs/deploy-checks.md +8 -6
- package/docs/desktop.mdx +14 -18
- package/docs/enterprise.md +6 -6
- package/docs/environment.mdx +5 -3
- package/docs/faq.mdx +9 -6
- package/docs/first-drive.md +19 -9
- package/docs/flows.md +3 -4
- package/docs/for-agents.md +1 -1
- package/docs/frameworks.mdx +34 -11
- package/docs/getting-started.md +46 -29
- package/docs/http-transport.md +2 -2
- package/docs/human-control.md +8 -8
- package/docs/index.mdx +2 -2
- package/docs/install-agentic.mdx +18 -19
- package/docs/install-manual.mdx +8 -4
- package/docs/integration-patterns.md +5 -5
- package/docs/multi-agent-testing.md +7 -5
- package/docs/packages/browser.mdx +34 -2
- package/docs/packages/core.mdx +2 -1
- package/docs/packages/electron.mdx +15 -3
- package/docs/packages/eslint-plugin.mdx +1 -1
- package/docs/packages/next.mdx +17 -5
- package/docs/packages/react.mdx +8 -1
- package/docs/packages/server.mdx +3 -3
- package/docs/packages/tauri.mdx +3 -3
- package/docs/packages/vite-plugin.mdx +1 -1
- package/docs/packages.mdx +19 -6
- package/docs/platform-integration.md +12 -4
- package/docs/predicates.mdx +18 -7
- package/docs/production-mode.md +108 -0
- package/docs/prompt-capture.md +99 -0
- package/docs/quickstart.mdx +14 -12
- package/docs/recipes.mdx +9 -8
- package/docs/required-checks.md +3 -2
- package/docs/skill-file.mdx +4 -3
- package/docs/skill-setup.md +2 -2
- package/docs/skill.md +62 -70
- package/docs/state-files.md +1 -0
- package/docs/state-management.mdx +11 -9
- package/docs/system-map.md +14 -13
- package/docs/telemetry.md +32 -24
- package/docs/testing.md +9 -5
- package/docs/tools/act-and-wait.mdx +17 -13
- package/docs/tools/act-sequence.mdx +40 -66
- package/docs/tools/act.mdx +7 -5
- package/docs/tools/assert.mdx +1 -1
- package/docs/tools/look.mdx +1 -1
- package/docs/tools/navigate.mdx +1 -1
- package/docs/tools/network.mdx +13 -11
- package/docs/tools/overview.mdx +3 -3
- package/docs/tools/query.mdx +3 -3
- package/docs/tools/session-and-feedback.mdx +9 -6
- package/docs/tools/sessions.mdx +7 -0
- package/docs/tools/snapshot.mdx +9 -7
- package/docs/tools/tools-and-run.mdx +11 -10
- package/docs/tools/verify.mdx +1 -1
- package/docs/troubleshooting.mdx +21 -9
- package/docs/usage.md +58 -43
- package/docs/use-cases.mdx +2 -2
- package/docs/vs-chrome-devtools-mcp.mdx +5 -5
- package/docs/vs-playwright-mcp.mdx +5 -4
- package/docs/what-is-recorded.md +12 -7
- package/docs/what-is-reticle.mdx +2 -2
- package/docs/why-reticle.mdx +1 -1
- package/package.json +9 -12
- package/dist/command/dev/stale-issue-guard.d.ts +0 -34
- package/dist/command/dev/stale-issue-guard.js +0 -69
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ActionType, DANGEROUS_ACTION_CONFIRM_ARG, NATIVE_INPUT_ARG, isDangerousActionText, outwardActionOf, outwardRefusal, } from '@reticlehq/core';
|
|
1
|
+
import { ActionType, DANGEROUS_ACTION_CONFIRM_ARG, NATIVE_INPUT_ARG, OutwardAction, isDangerousActionText, isDangerousNavigation, isInertHref, isPaymentProviderUrl, outwardActionOf, outwardRefusal, withoutFilenameTokens, } from '@reticlehq/core';
|
|
2
2
|
import { currentDrivenBy, harnessOutwardAllowed } from '../../../hooks/driven-by.js';
|
|
3
3
|
import { asRecord, asString } from '@reticlehq/core';
|
|
4
4
|
/**
|
|
@@ -14,10 +14,12 @@ import { asRecord, asString } from '@reticlehq/core';
|
|
|
14
14
|
*/
|
|
15
15
|
function descriptorText(value) {
|
|
16
16
|
const descriptor = asRecord(value);
|
|
17
|
+
// Filename tokens are stripped from the name, the text and the value only: an href or a
|
|
18
|
+
// formAction is a target, not words on the control, and its destination must be read whole.
|
|
17
19
|
return [
|
|
18
|
-
asString(descriptor['name']) ?? '',
|
|
19
|
-
asString(descriptor['text']) ?? '',
|
|
20
|
-
asString(descriptor['value']) ?? '',
|
|
20
|
+
withoutFilenameTokens(asString(descriptor['name']) ?? ''),
|
|
21
|
+
withoutFilenameTokens(asString(descriptor['text']) ?? ''),
|
|
22
|
+
withoutFilenameTokens(asString(descriptor['value']) ?? ''),
|
|
21
23
|
asString(descriptor['href']) ?? '',
|
|
22
24
|
asString(descriptor['formAction']) ?? '',
|
|
23
25
|
asString(descriptor['formText']) ?? '',
|
|
@@ -28,27 +30,47 @@ function descriptorRole(value) {
|
|
|
28
30
|
return role !== undefined && role.length > 0 ? role : undefined;
|
|
29
31
|
}
|
|
30
32
|
function isDestructiveDescriptor(value) {
|
|
33
|
+
// A real link is a navigation, judged by where it goes: the same rule as the SDK path.
|
|
34
|
+
const href = asString(asRecord(value)['href']);
|
|
35
|
+
if (href !== undefined && !isInertHref(href)) {
|
|
36
|
+
return isDangerousNavigation(href);
|
|
37
|
+
}
|
|
31
38
|
return isDangerousActionText(descriptorText(value), descriptorRole(value));
|
|
32
39
|
}
|
|
33
40
|
/** A Harness call presses an outward control only when its journey asked (`harnessOutwardAllowed`). */
|
|
34
41
|
function assertOutwardAllowed(...descriptors) {
|
|
35
42
|
const allowed = harnessOutwardAllowed();
|
|
36
|
-
if (allowed === undefined)
|
|
43
|
+
if (allowed === undefined) {
|
|
37
44
|
return;
|
|
45
|
+
}
|
|
38
46
|
for (const descriptor of descriptors) {
|
|
39
47
|
const kind = outwardActionOf(descriptorText(descriptor), descriptorRole(descriptor));
|
|
40
|
-
if (kind !== undefined && !allowed.includes(kind))
|
|
48
|
+
if (kind !== undefined && !allowed.includes(kind)) {
|
|
41
49
|
throw new Error(outwardRefusal(kind));
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
/** A Harness call goes to a payment provider's origin only when its journey asked to pay. */
|
|
54
|
+
export function assertNotPaymentNavigation(url) {
|
|
55
|
+
const allowed = harnessOutwardAllowed();
|
|
56
|
+
if (allowed === undefined || allowed.includes(OutwardAction.PAY)) {
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
if (isPaymentProviderUrl(url)) {
|
|
60
|
+
throw new Error(outwardRefusal(OutwardAction.PAY));
|
|
42
61
|
}
|
|
43
62
|
}
|
|
44
63
|
export function assertNotDestructive(action, innerArgs, inspected) {
|
|
45
|
-
if (action !== ActionType.CLICK && action !== ActionType.DBLCLICK)
|
|
64
|
+
if (action !== ActionType.CLICK && action !== ActionType.DBLCLICK) {
|
|
46
65
|
return;
|
|
66
|
+
}
|
|
47
67
|
assertOutwardAllowed(inspected);
|
|
48
|
-
if (true === innerArgs[DANGEROUS_ACTION_CONFIRM_ARG])
|
|
68
|
+
if (true === innerArgs[DANGEROUS_ACTION_CONFIRM_ARG]) {
|
|
49
69
|
return;
|
|
50
|
-
|
|
70
|
+
}
|
|
71
|
+
if (!isDestructiveDescriptor(inspected)) {
|
|
51
72
|
return;
|
|
73
|
+
}
|
|
52
74
|
throw new Error(`potentially destructive native action blocked; retry with args.${DANGEROUS_ACTION_CONFIRM_ARG}=true`);
|
|
53
75
|
}
|
|
54
76
|
/**
|
|
@@ -58,10 +80,12 @@ export function assertNotDestructive(action, innerArgs, inspected) {
|
|
|
58
80
|
*/
|
|
59
81
|
export function assertDragNotDestructive(innerArgs, from, to) {
|
|
60
82
|
assertOutwardAllowed(from, to);
|
|
61
|
-
if (true === innerArgs[DANGEROUS_ACTION_CONFIRM_ARG])
|
|
83
|
+
if (true === innerArgs[DANGEROUS_ACTION_CONFIRM_ARG]) {
|
|
62
84
|
return;
|
|
63
|
-
|
|
85
|
+
}
|
|
86
|
+
if (!isDestructiveDescriptor(from) && !isDestructiveDescriptor(to)) {
|
|
64
87
|
return;
|
|
88
|
+
}
|
|
65
89
|
throw new Error(`potentially destructive native action blocked; retry with args.${DANGEROUS_ACTION_CONFIRM_ARG}=true`);
|
|
66
90
|
}
|
|
67
91
|
/**
|
|
@@ -78,8 +102,9 @@ export const NATIVE_INPUT_UNSUPPORTED = `reticle_act_and_wait cannot drive nativ
|
|
|
78
102
|
'consequence with reticle_assert / reticle_observe using the `since` cursor it returns.';
|
|
79
103
|
/** Refuse rather than silently drop a native-input request the act-then-wait path cannot honour. */
|
|
80
104
|
export function assertNativeInputSupported(innerArgs) {
|
|
81
|
-
if (true === innerArgs[NATIVE_INPUT_ARG])
|
|
105
|
+
if (true === innerArgs[NATIVE_INPUT_ARG]) {
|
|
82
106
|
throw new Error(NATIVE_INPUT_UNSUPPORTED);
|
|
107
|
+
}
|
|
83
108
|
}
|
|
84
109
|
/**
|
|
85
110
|
* The agent's own declaration counts as the confirmation, for that one control.
|
|
@@ -92,10 +117,12 @@ export function assertNativeInputSupported(innerArgs) {
|
|
|
92
117
|
* guard decides alone.
|
|
93
118
|
*/
|
|
94
119
|
export function confirmedByDeclaration(innerArgs, target, declared) {
|
|
95
|
-
if (!declared || true === innerArgs[DANGEROUS_ACTION_CONFIRM_ARG])
|
|
120
|
+
if (!declared || true === innerArgs[DANGEROUS_ACTION_CONFIRM_ARG]) {
|
|
96
121
|
return innerArgs;
|
|
97
|
-
|
|
122
|
+
}
|
|
123
|
+
if (currentDrivenBy() !== undefined) {
|
|
98
124
|
return innerArgs;
|
|
125
|
+
}
|
|
99
126
|
const named = asRecord(target);
|
|
100
127
|
// The words must themselves be the dangerous ones: naming "Continue" on a button whose form posts
|
|
101
128
|
// to /delete-account consents to nothing, and the guard still reads the whole control.
|
|
@@ -47,6 +47,17 @@ export declare const DISABLED_TARGET_NOTE: string;
|
|
|
47
47
|
* consequence then says nothing about the app, so the verdict is undecided rather than "no".
|
|
48
48
|
*/
|
|
49
49
|
export declare function disabledTargetNote(pass: boolean, actResult: unknown): string | undefined;
|
|
50
|
+
/**
|
|
51
|
+
* Why the click behind a verdict is not one a person could have made, or undefined when it is.
|
|
52
|
+
*
|
|
53
|
+
* Synthetic dispatch reaches a covered, sizeless or off-screen target all the same, so the declared
|
|
54
|
+
* consequence can hold. A "yes" on it says nothing about what the app's users can do: the act
|
|
55
|
+
* result already warned, and the verdict now agrees. Undecided, never a pass and never the app's
|
|
56
|
+
* failure, whichever way the consequence went.
|
|
57
|
+
*/
|
|
58
|
+
export declare function unreachableTargetNote(actResult: unknown): string | undefined;
|
|
59
|
+
/** Why the acted target leaves the verdict undecided: no person could reach it, or it was disabled. */
|
|
60
|
+
export declare function actTargetNote(pass: boolean, actResult: unknown): string | undefined;
|
|
50
61
|
/**
|
|
51
62
|
* The requests of a failed check's window, as its record carries them: method, url, status and the
|
|
52
63
|
* start of the response body (redacted in the page before it was ever sent). Dev tooling is left out.
|
|
@@ -48,6 +48,39 @@ export function disabledTargetNote(pass, actResult) {
|
|
|
48
48
|
return undefined;
|
|
49
49
|
return false === asRecord(actResult)['enabled'] ? DISABLED_TARGET_NOTE : undefined;
|
|
50
50
|
}
|
|
51
|
+
/** The words a verdict carries for a click no person could have made. */
|
|
52
|
+
const UNREACHABLE = {
|
|
53
|
+
covered: (by) => `a person could not have clicked the target: it is covered by ${by}. Dismiss or move what ` +
|
|
54
|
+
'covers it, then act again',
|
|
55
|
+
NO_SIZE: 'a person could not have clicked the target: it has no size (0×0). Give it a size, or act on ' +
|
|
56
|
+
'the control a person actually clicks',
|
|
57
|
+
OFF_VIEWPORT: 'a person could not have clicked the target: it is outside the viewport even after scrolling ' +
|
|
58
|
+
'it into view. Bring it on screen, then act again',
|
|
59
|
+
};
|
|
60
|
+
/**
|
|
61
|
+
* Why the click behind a verdict is not one a person could have made, or undefined when it is.
|
|
62
|
+
*
|
|
63
|
+
* Synthetic dispatch reaches a covered, sizeless or off-screen target all the same, so the declared
|
|
64
|
+
* consequence can hold. A "yes" on it says nothing about what the app's users can do: the act
|
|
65
|
+
* result already warned, and the verdict now agrees. Undecided, never a pass and never the app's
|
|
66
|
+
* failure, whichever way the consequence went.
|
|
67
|
+
*/
|
|
68
|
+
export function unreachableTargetNote(actResult) {
|
|
69
|
+
const effect = asRecord(asRecord(actResult)['effect']);
|
|
70
|
+
if (true === effect['occluded']) {
|
|
71
|
+
const by = asString(effect['occluderName']) ?? asString(effect['occludedBy']);
|
|
72
|
+
return UNREACHABLE.covered(by ?? 'another element');
|
|
73
|
+
}
|
|
74
|
+
if (true === effect['noSize'])
|
|
75
|
+
return UNREACHABLE.NO_SIZE;
|
|
76
|
+
if (true === effect['offViewport'])
|
|
77
|
+
return UNREACHABLE.OFF_VIEWPORT;
|
|
78
|
+
return undefined;
|
|
79
|
+
}
|
|
80
|
+
/** Why the acted target leaves the verdict undecided: no person could reach it, or it was disabled. */
|
|
81
|
+
export function actTargetNote(pass, actResult) {
|
|
82
|
+
return unreachableTargetNote(actResult) ?? disabledTargetNote(pass, actResult);
|
|
83
|
+
}
|
|
51
84
|
/** Calls quoted on a failed check, and how much of each response body. */
|
|
52
85
|
const MAX_NET_CALLS = 5;
|
|
53
86
|
const MAX_BODY_CHARS = 300;
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
*/
|
|
13
13
|
import { PredicateSchema } from '@reticlehq/engine/question/predicate/predicate-schema.js';
|
|
14
14
|
import { SESSION_REF, isGlobalPressCall, unissuedRefRefusal } from '@reticlehq/core';
|
|
15
|
+
import { isDocumentGoneError } from '../../../portal/session/facts/session-replaced.js';
|
|
15
16
|
import { SessionReplacedError } from '../../../portal/session/page-commands/pending-commands.js';
|
|
16
17
|
import { assertNativeInputSupported } from './act-danger.js';
|
|
17
18
|
import { unevaluablePredicateReason, vacuousPredicateReason, } from '@reticlehq/engine/question/predicate/predicate-precheck.js';
|
|
@@ -118,8 +119,14 @@ export function assertSequenceSteps(steps) {
|
|
|
118
119
|
* the very thing it just wrote. Same false green as an unreadable key, through a key this tool
|
|
119
120
|
* does read.
|
|
120
121
|
*/
|
|
121
|
-
|
|
122
|
-
|
|
122
|
+
const parsed = step['expect'] === undefined ? undefined : PredicateSchema.safeParse(step['expect']);
|
|
123
|
+
if (parsed !== undefined && !parsed.success) {
|
|
124
|
+
// The schema's own words, such as the keys it saw when it could not tell the kind.
|
|
125
|
+
const said = parsed.error.issues
|
|
126
|
+
.filter((issue) => 'custom' === issue.code)
|
|
127
|
+
.map((issue) => ` ${issue.message}.`)
|
|
128
|
+
.join('');
|
|
129
|
+
throw new Error(`step ${String(i)} carries an \`expect\` this tool cannot parse.${said} ` +
|
|
123
130
|
'A consequence is a predicate object with a `kind` — e.g. { kind: "signal", name: ' +
|
|
124
131
|
'"order:placed" }, { kind: "element", by: "testid", value: "receipt" }, or ' +
|
|
125
132
|
'{ kind: "settled" } — the same shape reticle_act_and_wait takes as `until`. ' +
|
|
@@ -184,7 +191,7 @@ export async function dispatchAct(send) {
|
|
|
184
191
|
return await send();
|
|
185
192
|
}
|
|
186
193
|
catch (error) {
|
|
187
|
-
if (error instanceof SessionReplacedError)
|
|
194
|
+
if (error instanceof SessionReplacedError || isDocumentGoneError(error))
|
|
188
195
|
return null;
|
|
189
196
|
throw error;
|
|
190
197
|
}
|
|
@@ -50,7 +50,8 @@ export function describeStepResult(step, result) {
|
|
|
50
50
|
settled: result['settled'] ?? null,
|
|
51
51
|
settleReason: result['settleReason'] ?? null,
|
|
52
52
|
};
|
|
53
|
-
|
|
53
|
+
// `reticleUi`: the step hit Reticle's own HUD, so the recorder leaves it out of the app's flow.
|
|
54
|
+
for (const key of ['testid', 'component', 'role', 'name', 'source', 'warning', 'reticleUi']) {
|
|
54
55
|
if (result[key] !== undefined)
|
|
55
56
|
out[key] = result[key];
|
|
56
57
|
}
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* line count. This resolves a TARGET and dispatches only QUERY, so that guard is untouched.
|
|
9
9
|
*/
|
|
10
10
|
import { ReticleCommand, SESSION_REF, isGlobalPressCall, unissuedRefRefusal, } from '@reticlehq/core';
|
|
11
|
-
import { normalizeQueryArgs } from '../read/query-shape.js';
|
|
11
|
+
import { emptyQueryRefusal, normalizeQueryArgs } from '../read/query-shape.js';
|
|
12
12
|
import { resolveTargetRef } from './resolve-target.js';
|
|
13
13
|
import { asRecord, asString, asNumber } from '@reticlehq/core';
|
|
14
14
|
import { appearanceDecision } from '@reticlehq/engine/window/appearance-budget.js';
|
|
@@ -52,17 +52,29 @@ appearanceMs) {
|
|
|
52
52
|
if (ref !== undefined && ref.length > 0) {
|
|
53
53
|
// Refused here, at the boundary, and never re-read as a `target`: guessing what an arbitrary
|
|
54
54
|
// string meant is the silent re-resolution the stale-ref refusal exists to prevent.
|
|
55
|
-
if (!SESSION_REF.test(ref))
|
|
55
|
+
if (!SESSION_REF.test(ref)) {
|
|
56
56
|
return { kind: 'error', message: unissuedRefRefusal(ref) };
|
|
57
|
+
}
|
|
57
58
|
return { kind: 'ref', ref };
|
|
58
59
|
}
|
|
59
60
|
const target = args['target'];
|
|
60
61
|
if (target === undefined) {
|
|
61
|
-
if (isGlobalPressCall(args))
|
|
62
|
+
if (isGlobalPressCall(args)) {
|
|
62
63
|
return { kind: 'global', ref: '' };
|
|
64
|
+
}
|
|
63
65
|
return { kind: 'error', message: MISSING_ACT_TARGET };
|
|
64
66
|
}
|
|
67
|
+
// A ref from a look, given as the target. It is the agent's own explicit ref, not a guess.
|
|
68
|
+
if ('string' === typeof target && SESSION_REF.test(target)) {
|
|
69
|
+
return { kind: 'ref', ref: target };
|
|
70
|
+
}
|
|
65
71
|
const q = normalizeQueryArgs(asRecord(target));
|
|
72
|
+
// A target that names nothing (a CSS string, an empty object) is not sent to the page: there it
|
|
73
|
+
// read as "matched no element", which says the element is gone when nothing was searched.
|
|
74
|
+
const empty = emptyQueryRefusal(q);
|
|
75
|
+
if (empty !== undefined) {
|
|
76
|
+
return { kind: 'error', message: empty.message };
|
|
77
|
+
}
|
|
66
78
|
/*
|
|
67
79
|
* Look again while the step's own budget lasts, instead of once.
|
|
68
80
|
*
|
|
@@ -87,8 +99,9 @@ appearanceMs) {
|
|
|
87
99
|
name: q['name'],
|
|
88
100
|
scope: q['scope'],
|
|
89
101
|
});
|
|
90
|
-
if (!out.ok)
|
|
102
|
+
if (!out.ok) {
|
|
91
103
|
return { kind: 'error', message: out.error ?? 'target query failed' };
|
|
104
|
+
}
|
|
92
105
|
const elements = asRecord(out.result)['elements'];
|
|
93
106
|
const found = Array.isArray(elements) ? elements : [];
|
|
94
107
|
const decision = appearanceDecision({
|
|
@@ -98,8 +111,9 @@ appearanceMs) {
|
|
|
98
111
|
});
|
|
99
112
|
// One match, or an ambiguity: both are answered by the existing resolver, which already ranks
|
|
100
113
|
// candidates inside its refusal so the next turn needs no snapshot.
|
|
101
|
-
if ('wait' !== decision.do)
|
|
114
|
+
if ('wait' !== decision.do) {
|
|
102
115
|
return resolveTargetRef(found, asRecord(out.result)['hint']);
|
|
116
|
+
}
|
|
103
117
|
await new Promise((resolve) => setTimeout(resolve, decision.waitMs));
|
|
104
118
|
}
|
|
105
119
|
}
|
|
@@ -20,7 +20,7 @@ export const durableArg = z
|
|
|
20
20
|
.describe('After a yes, reload and require the element/text/state part of `until` to hold again.');
|
|
21
21
|
// Loose and undescribed on purpose: the output surface is re-sent every turn. `because` carries
|
|
22
22
|
// the answer; this is the detail — { held?, observed?, skipped? }.
|
|
23
|
-
export const durableOutput = z.record(z.unknown()).optional();
|
|
23
|
+
export const durableOutput = z.record(z.string(), z.unknown()).optional();
|
|
24
24
|
const RE_READABLE = new Set([
|
|
25
25
|
PredicateKind.ELEMENT,
|
|
26
26
|
PredicateKind.TEXT,
|
|
@@ -67,17 +67,19 @@ export interface ArrivalScope {
|
|
|
67
67
|
* document identity proves the replacement; `undefined` on both sides proves nothing and waits.
|
|
68
68
|
*/
|
|
69
69
|
navigatedFromDocumentId?: string;
|
|
70
|
-
/**
|
|
70
|
+
/**
|
|
71
|
+
* Sessions connected before dispatch cannot prove this navigation arrived. One already on the
|
|
72
|
+
* target was there before it. One elsewhere, such as a lease on the same app, is another tab: it
|
|
73
|
+
* can reach the target during the wait, but it is not the new document of the navigated tab.
|
|
74
|
+
*/
|
|
71
75
|
priorIds: ReadonlySet<string>;
|
|
72
76
|
}
|
|
73
77
|
/**
|
|
74
|
-
* The sessions
|
|
75
|
-
*
|
|
76
|
-
*
|
|
77
|
-
* Shares `samePage` with the arrival scan on purpose: "was it already there" and "is it there now"
|
|
78
|
-
* are the same question asked at two moments, and two spellings of it would eventually disagree.
|
|
78
|
+
* The sessions connected when the navigation is dispatched: the set `ArrivalScope.priorIds` is
|
|
79
|
+
* built from. The navigated tab's new document is not one of them, so none of the others can be
|
|
80
|
+
* the arrival.
|
|
79
81
|
*/
|
|
80
|
-
export declare function
|
|
82
|
+
export declare function idsOpenAtDispatch(sessions: SessionManager): ReadonlySet<string>;
|
|
81
83
|
export interface ArrivalClock {
|
|
82
84
|
now: () => number;
|
|
83
85
|
sleep: (ms: number) => Promise<void>;
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
* would make the daemon wait. `assert` / `wait_for` / `act_and_wait` all spend the caller's
|
|
18
18
|
* `timeout_ms` (resolve-within.ts); this is the same budget applied to the same wait.
|
|
19
19
|
*/
|
|
20
|
-
import { awaitDocumentSuccessor } from '../../../../portal/session/session-successor.js';
|
|
20
|
+
import { awaitDocumentSuccessor, claimedSessionOf, } from '../../../../portal/session/session-successor.js';
|
|
21
21
|
/**
|
|
22
22
|
* The default when the caller gives no `timeout_ms`: long enough for a dev server to serve a page
|
|
23
23
|
* and the SDK to dial back; short enough to not hang. A caller who knows the app is slower says so.
|
|
@@ -71,19 +71,12 @@ export function absoluteTarget(target, base) {
|
|
|
71
71
|
}
|
|
72
72
|
}
|
|
73
73
|
/**
|
|
74
|
-
* The sessions
|
|
75
|
-
*
|
|
76
|
-
*
|
|
77
|
-
* Shares `samePage` with the arrival scan on purpose: "was it already there" and "is it there now"
|
|
78
|
-
* are the same question asked at two moments, and two spellings of it would eventually disagree.
|
|
74
|
+
* The sessions connected when the navigation is dispatched: the set `ArrivalScope.priorIds` is
|
|
75
|
+
* built from. The navigated tab's new document is not one of them, so none of the others can be
|
|
76
|
+
* the arrival.
|
|
79
77
|
*/
|
|
80
|
-
export function
|
|
81
|
-
|
|
82
|
-
for (const s of sessions.all()) {
|
|
83
|
-
if (samePage(s.url, target))
|
|
84
|
-
ids.add(s.id);
|
|
85
|
-
}
|
|
86
|
-
return ids;
|
|
78
|
+
export function idsOpenAtDispatch(sessions) {
|
|
79
|
+
return new Set(sessions.all().map((s) => s.id));
|
|
87
80
|
}
|
|
88
81
|
/**
|
|
89
82
|
* Whether `current` is a different document from the one the navigation was dispatched on.
|
|
@@ -124,10 +117,14 @@ function findArrival(sessions, target, scope, currentSession) {
|
|
|
124
117
|
// the document has a chance to reach the requested target.
|
|
125
118
|
continue;
|
|
126
119
|
}
|
|
127
|
-
// A different session that was
|
|
120
|
+
// A different session that was connected at dispatch cannot prove this
|
|
128
121
|
// navigation arrived.
|
|
129
122
|
if (scope.priorIds.has(s.id))
|
|
130
123
|
continue;
|
|
124
|
+
// A session that claims another identity (a lease) is another tab, not the new document of
|
|
125
|
+
// the navigated one, even when it reconnects at the target during the wait.
|
|
126
|
+
if (claimedSessionOf(s.url) !== claimedSessionOf(scope.navigatedFrom))
|
|
127
|
+
continue;
|
|
131
128
|
// While the replaced document is still connected, a DIFFERENT session at the target is an
|
|
132
129
|
// unrelated arrival (a second tab, a neighbour app): the replacement this navigation waits
|
|
133
130
|
// for has not reported yet, and letting the newcomer stand in would confirm too early and
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A zero-match `find` read while the last act is still landing says so (#1259).
|
|
3
|
+
*
|
|
4
|
+
* `reticle_act` returns before an async render: a click that opens a modal after a fetch, then an
|
|
5
|
+
* immediate `find` for the modal's combobox, answers 0. A find is a point-in-time read, and an agent
|
|
6
|
+
* reads 0 as "not there" and goes down the wrong path. The read itself stays instant. What changes
|
|
7
|
+
* is that a 0 taken while the page is demonstrably still moving carries `unsettled`, naming why and
|
|
8
|
+
* the call that waits.
|
|
9
|
+
*/
|
|
10
|
+
import { type ReticleEvent } from '@reticlehq/core';
|
|
11
|
+
/** A DOM change this recent means the render the act started may not have landed yet. */
|
|
12
|
+
export declare const UNSETTLED_DOM_QUIET_MS = 500;
|
|
13
|
+
export interface UnsettledFind {
|
|
14
|
+
reason: string;
|
|
15
|
+
inFlight?: string[];
|
|
16
|
+
lastDomChangeMsAgo?: number;
|
|
17
|
+
}
|
|
18
|
+
/** The slice of a session this reads: the last act's window and the clock. */
|
|
19
|
+
export interface UnsettledFindSession {
|
|
20
|
+
lastAct: {
|
|
21
|
+
cursor(): number | undefined;
|
|
22
|
+
};
|
|
23
|
+
eventsSince(cursor: number): readonly ReticleEvent[];
|
|
24
|
+
elapsed(): number;
|
|
25
|
+
url: string;
|
|
26
|
+
background: readonly string[];
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* `unsettled` for a zero-match read taken while the last act's window is still moving, else nothing.
|
|
30
|
+
*
|
|
31
|
+
* Moving means a request that window started has not come back, or the DOM changed within
|
|
32
|
+
* `UNSETTLED_DOM_QUIET_MS`. With no act yet there is no window to judge, so nothing is said.
|
|
33
|
+
*/
|
|
34
|
+
export declare function unsettledFind(session: UnsettledFindSession, result: unknown): UnsettledFind | undefined;
|
|
35
|
+
/** The query result, with `unsettled` added when a zero-match read was taken mid-render. */
|
|
36
|
+
export declare function withUnsettledFind(session: UnsettledFindSession, result: unknown): unknown;
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A zero-match `find` read while the last act is still landing says so (#1259).
|
|
3
|
+
*
|
|
4
|
+
* `reticle_act` returns before an async render: a click that opens a modal after a fetch, then an
|
|
5
|
+
* immediate `find` for the modal's combobox, answers 0. A find is a point-in-time read, and an agent
|
|
6
|
+
* reads 0 as "not there" and goes down the wrong path. The read itself stays instant. What changes
|
|
7
|
+
* is that a 0 taken while the page is demonstrably still moving carries `unsettled`, naming why and
|
|
8
|
+
* the call that waits.
|
|
9
|
+
*/
|
|
10
|
+
import { EventType } from '@reticlehq/core';
|
|
11
|
+
import { inFlightRequestLabels } from './settle-in-flight.js';
|
|
12
|
+
/** A DOM change this recent means the render the act started may not have landed yet. */
|
|
13
|
+
export const UNSETTLED_DOM_QUIET_MS = 500;
|
|
14
|
+
const DOM_CHANGES = new Set([
|
|
15
|
+
EventType.DOM_ADDED,
|
|
16
|
+
EventType.DOM_REMOVED,
|
|
17
|
+
EventType.DOM_ATTR,
|
|
18
|
+
EventType.DOM_TEXT,
|
|
19
|
+
]);
|
|
20
|
+
/** What the next call should be, in the words every unsettled answer uses. */
|
|
21
|
+
const WAIT_INSTEAD = 'a 0 here may only mean it has not rendered yet. Wait for it with reticle_assert { action: "wait", predicate: { kind: "element", query: ... } }, or act with reticle_act_and_wait { until } next time';
|
|
22
|
+
/** How many elements a query result matched, or `undefined` when it is not a query result. */
|
|
23
|
+
function matchedCount(result) {
|
|
24
|
+
if (null === result || 'object' !== typeof result)
|
|
25
|
+
return undefined;
|
|
26
|
+
const rec = result;
|
|
27
|
+
if ('number' === typeof rec['count'])
|
|
28
|
+
return rec['count'];
|
|
29
|
+
return Array.isArray(rec['elements']) ? rec['elements'].length : undefined;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* `unsettled` for a zero-match read taken while the last act's window is still moving, else nothing.
|
|
33
|
+
*
|
|
34
|
+
* Moving means a request that window started has not come back, or the DOM changed within
|
|
35
|
+
* `UNSETTLED_DOM_QUIET_MS`. With no act yet there is no window to judge, so nothing is said.
|
|
36
|
+
*/
|
|
37
|
+
export function unsettledFind(session, result) {
|
|
38
|
+
if (0 !== matchedCount(result))
|
|
39
|
+
return undefined;
|
|
40
|
+
// A test double, or any session that cannot say what its last act was, gets the read as before.
|
|
41
|
+
if (undefined === session.lastAct)
|
|
42
|
+
return undefined;
|
|
43
|
+
const cursor = session.lastAct.cursor();
|
|
44
|
+
if (cursor === undefined)
|
|
45
|
+
return undefined;
|
|
46
|
+
const window = session.eventsSince(cursor);
|
|
47
|
+
const inFlight = inFlightRequestLabels(window, session.url, session.background);
|
|
48
|
+
let lastDom;
|
|
49
|
+
for (const e of window)
|
|
50
|
+
if (DOM_CHANGES.has(e.type))
|
|
51
|
+
lastDom = Math.max(lastDom ?? e.t, e.t);
|
|
52
|
+
const msAgo = lastDom === undefined ? undefined : Math.max(0, session.elapsed() - lastDom);
|
|
53
|
+
const recent = msAgo !== undefined && msAgo < UNSETTLED_DOM_QUIET_MS;
|
|
54
|
+
if (0 === inFlight.length && !recent)
|
|
55
|
+
return undefined;
|
|
56
|
+
const why = 0 < inFlight.length
|
|
57
|
+
? `the last act started ${String(inFlight.length)} request(s) that have not come back`
|
|
58
|
+
: `the page changed ${String(msAgo)} ms ago, after the last act`;
|
|
59
|
+
return {
|
|
60
|
+
reason: `this read found nothing while the page was still changing: ${why}, so ${WAIT_INSTEAD}`,
|
|
61
|
+
...(0 < inFlight.length ? { inFlight } : {}),
|
|
62
|
+
...(msAgo === undefined ? {} : { lastDomChangeMsAgo: msAgo }),
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
/** The query result, with `unsettled` added when a zero-match read was taken mid-render. */
|
|
66
|
+
export function withUnsettledFind(session, result) {
|
|
67
|
+
const unsettled = unsettledFind(session, result);
|
|
68
|
+
if (unsettled === undefined || null === result || 'object' !== typeof result)
|
|
69
|
+
return result;
|
|
70
|
+
return { ...result, unsettled };
|
|
71
|
+
}
|