@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
|
@@ -10,7 +10,9 @@
|
|
|
10
10
|
* the thin Playwright adapter that satisfies these interfaces lives separately.
|
|
11
11
|
*/
|
|
12
12
|
import { unreachableUrlIn } from '@reticlehq/core';
|
|
13
|
-
import { seedStorageInto } from './storage-seed.js';
|
|
13
|
+
import { seedStorageInto, targetOriginOf } from './storage-seed.js';
|
|
14
|
+
import { installLeaseMarker, leaseMarkerOf } from './lease-marker-stamp.js';
|
|
15
|
+
import { grantLeasePermissions, NOTIFICATION_PERMISSION_READ, NOTIFICATION_READ_TIMEOUT_MS, } from './context-permissions.js';
|
|
14
16
|
/** Default lease time-to-live: a lease untouched for this long is presumed orphaned and reclaimed. */
|
|
15
17
|
export const DEFAULT_LEASE_TTL_MS = 5 * 60_000;
|
|
16
18
|
/** Default cap on how long a lease's initial navigation may take before it fails (frees the slot). */
|
|
@@ -22,6 +24,13 @@ const DEFAULT_NAV_TIMEOUT_MS = 30_000;
|
|
|
22
24
|
const MAX_REMEMBERED_REAPED_LEASES = 64;
|
|
23
25
|
/** What a headed lease is refused with where no window can be opened. */
|
|
24
26
|
export const NO_HEADED_BROWSER = 'no headed browser can be opened here';
|
|
27
|
+
/**
|
|
28
|
+
* What an acquire that asked for an init script is refused with when the page cannot run one.
|
|
29
|
+
*
|
|
30
|
+
* A refusal rather than a lease: the caller asked for a stub of the bindings a desktop shell
|
|
31
|
+
* injects, and a tab opened without it would throw in the app's view and read as a broken app.
|
|
32
|
+
*/
|
|
33
|
+
const INIT_SCRIPT_UNSUPPORTED = 'Init script failed: this page does not support init scripts, so the requested stub would not be there';
|
|
25
34
|
/**
|
|
26
35
|
* Owns a headless browser (and, when asked, a headed one) and leases isolated contexts out of them,
|
|
27
36
|
* capped at `maxContexts` across both.
|
|
@@ -181,6 +190,15 @@ export class BrowserPool {
|
|
|
181
190
|
#leaseIdOf(sessionId) {
|
|
182
191
|
return this.#active.has(sessionId) ? sessionId : (this.#aliases.get(sessionId) ?? sessionId);
|
|
183
192
|
}
|
|
193
|
+
/**
|
|
194
|
+
* Whether `sessionId` is a live lease that `owner` may let go of: one it took, or one taken by a
|
|
195
|
+
* caller with no id, which cannot be told apart from it. Another agent's lease is never this
|
|
196
|
+
* caller's to close (#1226).
|
|
197
|
+
*/
|
|
198
|
+
heldBy(sessionId, owner) {
|
|
199
|
+
const lease = this.#active.get(this.#leaseIdOf(sessionId));
|
|
200
|
+
return lease !== undefined && (lease.owner === undefined || lease.owner === owner);
|
|
201
|
+
}
|
|
184
202
|
/** Mark a lease as still in use (called on agent activity) so the reaper doesn't reclaim it. */
|
|
185
203
|
touch(sessionId) {
|
|
186
204
|
const lease = this.#active.get(this.#leaseIdOf(sessionId));
|
|
@@ -215,6 +233,28 @@ export class BrowserPool {
|
|
|
215
233
|
return undefined;
|
|
216
234
|
}
|
|
217
235
|
}
|
|
236
|
+
/** The URL a lease was opened on — the one that carries its Reticle identity. */
|
|
237
|
+
leaseUrl(sessionId) {
|
|
238
|
+
return this.#active.get(this.#leaseIdOf(sessionId))?.url;
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* Navigate a leased page through the browser. For a lease whose page has no SDK to take the
|
|
242
|
+
* command — a navigate to an image left the lease unreachable, and the next navigate answered "no
|
|
243
|
+
* connected session". False when this is not a lease or the page would not go.
|
|
244
|
+
*/
|
|
245
|
+
async gotoLease(sessionId, url, timeoutMs) {
|
|
246
|
+
const lease = this.#active.get(this.#leaseIdOf(sessionId));
|
|
247
|
+
if (lease === undefined)
|
|
248
|
+
return false;
|
|
249
|
+
this.touch(sessionId);
|
|
250
|
+
try {
|
|
251
|
+
await lease.page.goto(url, timeoutMs === undefined ? {} : { timeoutMs });
|
|
252
|
+
return true;
|
|
253
|
+
}
|
|
254
|
+
catch {
|
|
255
|
+
return false;
|
|
256
|
+
}
|
|
257
|
+
}
|
|
218
258
|
/**
|
|
219
259
|
* Move the real pointer on a leased page, or false when this session is not a lease or cannot
|
|
220
260
|
* hover. Same optional-capability contract as screenshotLease: absence must read as "could not
|
|
@@ -275,6 +315,52 @@ export class BrowserPool {
|
|
|
275
315
|
return false;
|
|
276
316
|
}
|
|
277
317
|
}
|
|
318
|
+
/** What a lease was granted when it opened, or undefined for a session that is not a lease. */
|
|
319
|
+
permissionsOf(sessionId) {
|
|
320
|
+
return this.#active.get(this.#leaseIdOf(sessionId))?.permissions;
|
|
321
|
+
}
|
|
322
|
+
/**
|
|
323
|
+
* Whether this lease's page runs a caller-supplied init script — a stub of the bindings a desktop
|
|
324
|
+
* shell injects. Alias-resolved like every agent-facing lookup, and false for any session that is
|
|
325
|
+
* not a lease with a stub, so a verdict can say when it was measured against a fake shell.
|
|
326
|
+
*/
|
|
327
|
+
stubInstalled(sessionId) {
|
|
328
|
+
return this.#active.get(this.#leaseIdOf(sessionId))?.hostStub !== undefined;
|
|
329
|
+
}
|
|
330
|
+
/**
|
|
331
|
+
* The init script this lease installed, or undefined when it runs none. Alias-resolved like
|
|
332
|
+
* `stubInstalled`. The lease tool compares it to the script a caller asks for: the same text means
|
|
333
|
+
* the held tab already is what was asked for, so it is reused rather than released and remade.
|
|
334
|
+
*/
|
|
335
|
+
hostStubScript(sessionId) {
|
|
336
|
+
return this.#active.get(this.#leaseIdOf(sessionId))?.hostStubScript;
|
|
337
|
+
}
|
|
338
|
+
/**
|
|
339
|
+
* What the leased page's `Notification.permission` says, or undefined when it cannot be asked.
|
|
340
|
+
*
|
|
341
|
+
* Read back rather than inferred from the grant, because the headless shell answers `denied`
|
|
342
|
+
* after a notifications grant — see context-permissions.ts. Bounded, so a page that never answers
|
|
343
|
+
* reads as "could not ask" instead of holding the caller.
|
|
344
|
+
*/
|
|
345
|
+
async notificationPermission(sessionId) {
|
|
346
|
+
const lease = this.#active.get(this.#leaseIdOf(sessionId));
|
|
347
|
+
if (lease === undefined || lease.page.evaluate === undefined)
|
|
348
|
+
return undefined;
|
|
349
|
+
let timer;
|
|
350
|
+
const gaveUp = new Promise((resolve) => {
|
|
351
|
+
timer = setTimeout(() => resolve(undefined), NOTIFICATION_READ_TIMEOUT_MS);
|
|
352
|
+
});
|
|
353
|
+
try {
|
|
354
|
+
const value = await Promise.race([lease.page.evaluate(NOTIFICATION_PERMISSION_READ), gaveUp]);
|
|
355
|
+
return 'string' === typeof value ? value : undefined;
|
|
356
|
+
}
|
|
357
|
+
catch {
|
|
358
|
+
return undefined;
|
|
359
|
+
}
|
|
360
|
+
finally {
|
|
361
|
+
clearTimeout(timer);
|
|
362
|
+
}
|
|
363
|
+
}
|
|
278
364
|
async sweepExpired() {
|
|
279
365
|
const now = this.#now();
|
|
280
366
|
const expired = [...this.#active.entries()]
|
|
@@ -336,8 +422,21 @@ export class BrowserPool {
|
|
|
336
422
|
let pendingDialogMessage;
|
|
337
423
|
try {
|
|
338
424
|
const browser = await this.#ensureBrowser(slot);
|
|
339
|
-
context = await browser.newContext();
|
|
425
|
+
context = await browser.newContext(true === opts.ignoreHTTPSErrors ? { ignoreHTTPSErrors: true } : undefined);
|
|
426
|
+
if (opts.permissions !== undefined)
|
|
427
|
+
await grantLeasePermissions(context, opts.permissions, url);
|
|
340
428
|
const page = await context.newPage();
|
|
429
|
+
// A caller-supplied init script is a stub of the bindings a desktop shell injects, and it has
|
|
430
|
+
// to exist before the app's first module runs. Installed here — before goto — so the very
|
|
431
|
+
// first document gets it, and kept for the lease (see hostStub) so a reload keeps it too.
|
|
432
|
+
let hostStub;
|
|
433
|
+
if (opts.initScript !== undefined) {
|
|
434
|
+
const added = await page.addInitScript?.(opts.initScript);
|
|
435
|
+
if (added === undefined || 'function' !== typeof added.dispose) {
|
|
436
|
+
throw new Error(INIT_SCRIPT_UNSUPPORTED);
|
|
437
|
+
}
|
|
438
|
+
hostStub = added;
|
|
439
|
+
}
|
|
341
440
|
// Per-page crash isolation: if THIS renderer dies, reclaim only this lease — the shared browser
|
|
342
441
|
// and every other agent's context keep running. (A full browser death is handled by #onCrash.)
|
|
343
442
|
page.onCrash(() => {
|
|
@@ -367,6 +466,10 @@ export class BrowserPool {
|
|
|
367
466
|
pendingDialogMessage = dialog.message;
|
|
368
467
|
void dialog.dismiss();
|
|
369
468
|
});
|
|
469
|
+
const marker = leaseMarkerOf(url);
|
|
470
|
+
if (marker?.session === sessionId) {
|
|
471
|
+
await installLeaseMarker(page, sessionId, targetOriginOf(url), marker.project);
|
|
472
|
+
}
|
|
370
473
|
let seedHandle;
|
|
371
474
|
let checkSeedError;
|
|
372
475
|
if (opts.seedStorage !== undefined) {
|
|
@@ -390,6 +493,9 @@ export class BrowserPool {
|
|
|
390
493
|
// no longer the live browser, bail — the catch below closes the context and returns the slot.
|
|
391
494
|
if (slot.browser !== browser)
|
|
392
495
|
throw new Error('browser crashed during navigation');
|
|
496
|
+
// Foreground it: a page opened beside other tabs can start hidden (#1351). Best-effort — a tab
|
|
497
|
+
// that stays hidden is reported by name at the lease, which failing here would lose.
|
|
498
|
+
await page.bringToFront?.().catch(() => undefined);
|
|
393
499
|
let navStatus;
|
|
394
500
|
if (null !== navRes && 'object' === typeof navRes && 'status' in navRes) {
|
|
395
501
|
const s = navRes.status;
|
|
@@ -414,8 +520,13 @@ export class BrowserPool {
|
|
|
414
520
|
url,
|
|
415
521
|
...(opts.owner === undefined ? {} : { owner: opts.owner }),
|
|
416
522
|
touchedAt: this.#now(),
|
|
523
|
+
permissions: opts.permissions ?? [],
|
|
524
|
+
ignoresHTTPSErrors: true === opts.ignoreHTTPSErrors,
|
|
417
525
|
...(pending === undefined ? {} : { dialFailureUrl: pending }),
|
|
418
526
|
...(pendingDialogMessage === undefined ? {} : { lastDialogMessage: pendingDialogMessage }),
|
|
527
|
+
...(hostStub === undefined || opts.initScript === undefined
|
|
528
|
+
? {}
|
|
529
|
+
: { hostStub, hostStubScript: opts.initScript }),
|
|
419
530
|
});
|
|
420
531
|
return {
|
|
421
532
|
sessionId,
|
|
@@ -492,6 +603,9 @@ export class BrowserPool {
|
|
|
492
603
|
if (leaseId === sessionId)
|
|
493
604
|
this.#aliases.delete(registered);
|
|
494
605
|
}
|
|
606
|
+
// Disposed with the lease, which is what "for that lease only" means. Best-effort: a context
|
|
607
|
+
// that is already gone (a crash) makes the disposal moot, not a reason to fail the release.
|
|
608
|
+
await lease.hostStub?.dispose().catch(() => undefined);
|
|
495
609
|
await lease.context.close().catch(() => undefined);
|
|
496
610
|
this.#releaseSlot();
|
|
497
611
|
}
|
|
@@ -597,6 +711,10 @@ export class BrowserPool {
|
|
|
597
711
|
for (const waiter of this.#waiters.splice(0))
|
|
598
712
|
waiter(); // let them re-claim + relaunch
|
|
599
713
|
}
|
|
714
|
+
/** Whether this lease's context skips certificate checks. A context cannot change it later. */
|
|
715
|
+
ignoresHTTPSErrors(sessionId) {
|
|
716
|
+
return true === this.#active.get(this.#leaseIdOf(sessionId))?.ignoresHTTPSErrors;
|
|
717
|
+
}
|
|
600
718
|
/** Whether this lease lives in the headed browser. */
|
|
601
719
|
isHeaded(sessionId) {
|
|
602
720
|
return true === this.#active.get(this.#leaseIdOf(sessionId))?.headed;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Browser permissions on a leased context: granted before the first navigation, and read back where
|
|
3
|
+
* the browser can contradict the grant.
|
|
4
|
+
*
|
|
5
|
+
* Never changed on a lease that is already open. Acquire hands an origin's live lease to whoever asks
|
|
6
|
+
* for that origin, so the lease may be another agent's tab mid-flow, and nothing here knows whose it
|
|
7
|
+
* is. A different set means a fresh lease.
|
|
8
|
+
*
|
|
9
|
+
* Each grant is scoped to the origin the lease was opened on, so a third-party frame the app embeds
|
|
10
|
+
* is not handed the same grant as the app.
|
|
11
|
+
*
|
|
12
|
+
* Notifications are why the read-back exists. Playwright's headless shell — what the pool launches
|
|
13
|
+
* when Playwright's own Chromium is installed — has no notification support: after a grant,
|
|
14
|
+
* `navigator.permissions.query` reports `granted` while `Notification.permission` still reads
|
|
15
|
+
* `denied`. A page that gates its UI on the second never sees the grant, so a lease that reported
|
|
16
|
+
* "granted" there would be reporting something the page cannot see.
|
|
17
|
+
*/
|
|
18
|
+
import type { PooledContext } from './pool-contract.js';
|
|
19
|
+
/** The permission whose grant the headless shell does not pass on to `Notification.permission`. */
|
|
20
|
+
export declare const NOTIFICATIONS_PERMISSION = "notifications";
|
|
21
|
+
/** Evaluated in the leased page. A string, because the pool's page surface evaluates scripts. */
|
|
22
|
+
export declare const NOTIFICATION_PERMISSION_READ = "typeof Notification === 'undefined' ? 'unsupported' : Notification.permission";
|
|
23
|
+
/**
|
|
24
|
+
* How long a read-back may take. Bounded because acquire waits on it, and a wedged renderer never
|
|
25
|
+
* answers an evaluation: an unbounded one would turn "this tab is stuck" into "acquire hangs".
|
|
26
|
+
*/
|
|
27
|
+
export declare const NOTIFICATION_READ_TIMEOUT_MS = 1500;
|
|
28
|
+
/** A permission could not be granted or cleared. Its message is written for the agent. */
|
|
29
|
+
export declare class LeasePermissionError extends Error {
|
|
30
|
+
readonly name = "LeasePermissionError";
|
|
31
|
+
}
|
|
32
|
+
/** Grant `permissions` on the origin of `url`. Nothing to grant is a no-op, not a refusal. */
|
|
33
|
+
export declare function grantLeasePermissions(context: PooledContext, permissions: readonly string[], url: string): Promise<void>;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/** The permission whose grant the headless shell does not pass on to `Notification.permission`. */
|
|
2
|
+
export const NOTIFICATIONS_PERMISSION = 'notifications';
|
|
3
|
+
/** Evaluated in the leased page. A string, because the pool's page surface evaluates scripts. */
|
|
4
|
+
export const NOTIFICATION_PERMISSION_READ = "typeof Notification === 'undefined' ? 'unsupported' : Notification.permission";
|
|
5
|
+
/**
|
|
6
|
+
* How long a read-back may take. Bounded because acquire waits on it, and a wedged renderer never
|
|
7
|
+
* answers an evaluation: an unbounded one would turn "this tab is stuck" into "acquire hangs".
|
|
8
|
+
*/
|
|
9
|
+
export const NOTIFICATION_READ_TIMEOUT_MS = 1_500;
|
|
10
|
+
/** Playwright prefixes its errors with the call that failed; the agent needs only the reason. */
|
|
11
|
+
const PLAYWRIGHT_CALL_PREFIX = /^browserContext\.\w+:\s*/;
|
|
12
|
+
/** A permission could not be granted or cleared. Its message is written for the agent. */
|
|
13
|
+
export class LeasePermissionError extends Error {
|
|
14
|
+
name = 'LeasePermissionError';
|
|
15
|
+
}
|
|
16
|
+
function reasonOf(err) {
|
|
17
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
18
|
+
return (message.split('\n')[0] ?? message).replace(PLAYWRIGHT_CALL_PREFIX, '');
|
|
19
|
+
}
|
|
20
|
+
/** Grant `permissions` on the origin of `url`. Nothing to grant is a no-op, not a refusal. */
|
|
21
|
+
export async function grantLeasePermissions(context, permissions, url) {
|
|
22
|
+
if (0 === permissions.length)
|
|
23
|
+
return;
|
|
24
|
+
if (context.grantPermissions === undefined) {
|
|
25
|
+
throw new LeasePermissionError('this browser context cannot grant permissions');
|
|
26
|
+
}
|
|
27
|
+
try {
|
|
28
|
+
await context.grantPermissions([...permissions], { origin: new URL(url).origin });
|
|
29
|
+
}
|
|
30
|
+
catch (err) {
|
|
31
|
+
throw new LeasePermissionError(`could not grant ${permissions.join(', ')}: ${reasonOf(err)}`);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { PooledPage } from './pool-contract.js';
|
|
2
|
+
interface LeaseMarkerArg {
|
|
3
|
+
session: string;
|
|
4
|
+
project?: string | undefined;
|
|
5
|
+
targetOrigin: string;
|
|
6
|
+
sessionParam: string;
|
|
7
|
+
projectParam: string;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Init script restoring the marker a server redirect dropped, so the SDK registers under the lease id.
|
|
11
|
+
* It runs only in pages of the lease's own browser context, so a person's tab at the same URL never
|
|
12
|
+
* carries the marker and is never adopted. It writes only in the top frame, only on the lease's own
|
|
13
|
+
* target origin (never an identity provider's or any third party's URL), and the pool installs it
|
|
14
|
+
* only when the navigated URL's marker matches this lease's id. Must stay self-contained: Playwright
|
|
15
|
+
* serialises the function source into the page.
|
|
16
|
+
*/
|
|
17
|
+
export declare function stampLeaseMarker(arg: LeaseMarkerArg): void;
|
|
18
|
+
export declare function installLeaseMarker(page: PooledPage, leaseId: string, targetOrigin: string | undefined, project: string | undefined): Promise<void>;
|
|
19
|
+
export declare function leaseMarkerOf(url: string): {
|
|
20
|
+
session: string;
|
|
21
|
+
project: string | undefined;
|
|
22
|
+
} | undefined;
|
|
23
|
+
export {};
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { RETICLE_URL_PARAM } from '@reticlehq/core';
|
|
2
|
+
/**
|
|
3
|
+
* Init script restoring the marker a server redirect dropped, so the SDK registers under the lease id.
|
|
4
|
+
* It runs only in pages of the lease's own browser context, so a person's tab at the same URL never
|
|
5
|
+
* carries the marker and is never adopted. It writes only in the top frame, only on the lease's own
|
|
6
|
+
* target origin (never an identity provider's or any third party's URL), and the pool installs it
|
|
7
|
+
* only when the navigated URL's marker matches this lease's id. Must stay self-contained: Playwright
|
|
8
|
+
* serialises the function source into the page.
|
|
9
|
+
*/
|
|
10
|
+
export function stampLeaseMarker(arg) {
|
|
11
|
+
const win = globalThis.window;
|
|
12
|
+
if (win === undefined || win.top !== win || win.location.origin !== arg.targetOrigin)
|
|
13
|
+
return;
|
|
14
|
+
try {
|
|
15
|
+
const url = new URL(win.location.href);
|
|
16
|
+
if (url.searchParams.has(arg.sessionParam))
|
|
17
|
+
return;
|
|
18
|
+
url.searchParams.set(arg.sessionParam, arg.session);
|
|
19
|
+
if (arg.project !== undefined && !url.searchParams.has(arg.projectParam)) {
|
|
20
|
+
url.searchParams.set(arg.projectParam, arg.project);
|
|
21
|
+
}
|
|
22
|
+
win.history.replaceState(null, '', url.toString());
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
export async function installLeaseMarker(page, leaseId, targetOrigin, project) {
|
|
29
|
+
if (page.addInitScript === undefined || targetOrigin === undefined)
|
|
30
|
+
return;
|
|
31
|
+
await page.addInitScript(stampLeaseMarker, {
|
|
32
|
+
session: leaseId,
|
|
33
|
+
project,
|
|
34
|
+
targetOrigin,
|
|
35
|
+
sessionParam: RETICLE_URL_PARAM.SESSION,
|
|
36
|
+
projectParam: RETICLE_URL_PARAM.PROJECT,
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
export function leaseMarkerOf(url) {
|
|
40
|
+
try {
|
|
41
|
+
const params = new URL(url).searchParams;
|
|
42
|
+
const session = params.get(RETICLE_URL_PARAM.SESSION) ?? '';
|
|
43
|
+
const project = params.get(RETICLE_URL_PARAM.PROJECT) ?? '';
|
|
44
|
+
return '' === session ? undefined : { session, project: '' === project ? undefined : project };
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
return undefined;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
@@ -7,18 +7,40 @@
|
|
|
7
7
|
*/
|
|
8
8
|
import type { Launcher } from './browser-pool.js';
|
|
9
9
|
import type { ScreenshotOptions } from './pool-contract.js';
|
|
10
|
-
/** Reticle's own panel, kept out of a picture of the app: it is ours, not what the app shows. */
|
|
11
|
-
export declare const HIDE_RETICLE_CHROME_CSS = "[data-reticle-overlay]{display:none !important}";
|
|
12
10
|
/**
|
|
13
|
-
*
|
|
14
|
-
*
|
|
11
|
+
* Reticle paints its own UI (presenter HUD, glow, annotator marks, tour) into the page. It is
|
|
12
|
+
* time-varying, since the activity log and border state change with every command, so capturing it
|
|
13
|
+
* makes a fresh screenshot of an unchanged page differ from its baseline. Playwright applies `style`
|
|
14
|
+
* for the shot only and then reverts it, so the page under test is never changed. Disabling animations
|
|
15
|
+
* settles any remaining transitions. Shared by every capture path, driven and leased, so both hide
|
|
16
|
+
* the same set: core's `RETICLE_OVERLAY_SELECTOR`.
|
|
17
|
+
*/
|
|
18
|
+
export declare const SCREENSHOT_DETERMINISM: {
|
|
19
|
+
readonly style: "[data-reticle-overlay],[data-reticle-cursor],[data-reticle-hud],[data-reticle-glow],[data-reticle-mark],[data-reticle-blocker],[data-reticle-tour]{display:none !important}";
|
|
20
|
+
readonly animations: "disabled";
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* How Playwright captures a leased tab: a PNG by default, a JPEG for a live picture. Every capture
|
|
24
|
+
* hides Reticle's own UI with `SCREENSHOT_DETERMINISM`, the same as the driven path, so a lease
|
|
25
|
+
* baseline shows the app and not the HUD.
|
|
15
26
|
*/
|
|
16
27
|
export declare function screenshotOptions(opts: ScreenshotOptions): {
|
|
17
28
|
fullPage: boolean;
|
|
29
|
+
style?: string;
|
|
30
|
+
animations?: 'disabled';
|
|
18
31
|
type?: 'jpeg';
|
|
19
32
|
quality?: number;
|
|
20
|
-
|
|
33
|
+
scale?: 'css';
|
|
21
34
|
};
|
|
35
|
+
/**
|
|
36
|
+
* A step screenshot with Reticle's own UI out of it. The step path injects nothing into the page
|
|
37
|
+
* (no stylesheet, no fast-forwarded animation), so the HUD covered a third of every picture. Only
|
|
38
|
+
* our own hosts change, by their own inline `visibility`, for this one capture, and are put back
|
|
39
|
+
* whatever the capture did: the app's DOM, styles and events are not touched.
|
|
40
|
+
*/
|
|
41
|
+
export declare function captureWithChromeHidden(page: {
|
|
42
|
+
evaluate: (script: string) => Promise<unknown>;
|
|
43
|
+
}, capture: () => Promise<Uint8Array>): Promise<Uint8Array>;
|
|
22
44
|
/**
|
|
23
45
|
* How a leased tab navigates. Pure, and exported, because the decision in it is worth a test while
|
|
24
46
|
* the rest of this file needs a real Chromium.
|
|
@@ -6,26 +6,60 @@
|
|
|
6
6
|
* Headless by default — the pool exists for fault-tolerant headless multi-agent testing.
|
|
7
7
|
*/
|
|
8
8
|
import { BrowserLaunchKind } from '@reticlehq/core/telemetry';
|
|
9
|
+
import { HIDE_RETICLE_CHROME_CSS, RETICLE_OVERLAY_SELECTOR } from '@reticlehq/core';
|
|
9
10
|
import { launchChromium } from '../../launch-chromium.js';
|
|
10
11
|
import { getSessionMetrics } from '../../telemetry/session-metrics.js';
|
|
11
12
|
import { classifyConnectFailure } from '../../telemetry/connect-failure.js';
|
|
12
13
|
import { chromiumInstallCommand, chromiumInstallDepsCommand, bundledPlaywrightVersion, } from '../../command/cli/doctor/browser/chromium-hint.js';
|
|
13
14
|
import { installNetworkMocks } from '../input/network-mock.js';
|
|
14
|
-
/** Reticle's own panel, kept out of a picture of the app: it is ours, not what the app shows. */
|
|
15
|
-
export const HIDE_RETICLE_CHROME_CSS = '[data-reticle-overlay]{display:none !important}';
|
|
16
15
|
/**
|
|
17
|
-
*
|
|
18
|
-
*
|
|
16
|
+
* Reticle paints its own UI (presenter HUD, glow, annotator marks, tour) into the page. It is
|
|
17
|
+
* time-varying, since the activity log and border state change with every command, so capturing it
|
|
18
|
+
* makes a fresh screenshot of an unchanged page differ from its baseline. Playwright applies `style`
|
|
19
|
+
* for the shot only and then reverts it, so the page under test is never changed. Disabling animations
|
|
20
|
+
* settles any remaining transitions. Shared by every capture path, driven and leased, so both hide
|
|
21
|
+
* the same set: core's `RETICLE_OVERLAY_SELECTOR`.
|
|
22
|
+
*/
|
|
23
|
+
export const SCREENSHOT_DETERMINISM = {
|
|
24
|
+
style: HIDE_RETICLE_CHROME_CSS,
|
|
25
|
+
animations: 'disabled',
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* How Playwright captures a leased tab: a PNG by default, a JPEG for a live picture. Every capture
|
|
29
|
+
* hides Reticle's own UI with `SCREENSHOT_DETERMINISM`, the same as the driven path, so a lease
|
|
30
|
+
* baseline shows the app and not the HUD.
|
|
19
31
|
*/
|
|
20
32
|
export function screenshotOptions(opts) {
|
|
33
|
+
// A step screenshot is evidence about the page, so it must not change it: `animations: disabled`
|
|
34
|
+
// fast-forwards running animations to their end and fires their events in the app under test.
|
|
35
|
+
if (true === opts.cssScale && opts.jpegQuality !== undefined) {
|
|
36
|
+
return { fullPage: false, type: 'jpeg', quality: opts.jpegQuality, scale: 'css' };
|
|
37
|
+
}
|
|
38
|
+
const base = { ...SCREENSHOT_DETERMINISM, fullPage: true === opts.fullPage };
|
|
21
39
|
return opts.jpegQuality === undefined
|
|
22
|
-
?
|
|
23
|
-
: {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
40
|
+
? base
|
|
41
|
+
: { ...base, type: 'jpeg', quality: opts.jpegQuality };
|
|
42
|
+
}
|
|
43
|
+
/** Where the hidden hosts' own visibility waits to be put back, on the page's window. */
|
|
44
|
+
const SHOT_HIDDEN_KEY = '__reticleShotHidden';
|
|
45
|
+
/** A string literal safe to splice into a script: JSON plus the characters that end one early. */
|
|
46
|
+
const scriptLiteral = (value) => JSON.stringify(value).replace(/[<>/\u2028\u2029]/g, (c) => `\\u${c.charCodeAt(0).toString(16).padStart(4, '0')}`);
|
|
47
|
+
const HIDE_CHROME_SCRIPT = `(() => { const held = []; for (const el of document.querySelectorAll(${scriptLiteral(RETICLE_OVERLAY_SELECTOR)})) { held.push([el, el.style.visibility]); el.style.visibility = 'hidden'; } window.${SHOT_HIDDEN_KEY} = held; })()`;
|
|
48
|
+
const RESTORE_CHROME_SCRIPT = `(() => { for (const [el, was] of window.${SHOT_HIDDEN_KEY} ?? []) el.style.visibility = was; delete window.${SHOT_HIDDEN_KEY}; })()`;
|
|
49
|
+
/**
|
|
50
|
+
* A step screenshot with Reticle's own UI out of it. The step path injects nothing into the page
|
|
51
|
+
* (no stylesheet, no fast-forwarded animation), so the HUD covered a third of every picture. Only
|
|
52
|
+
* our own hosts change, by their own inline `visibility`, for this one capture, and are put back
|
|
53
|
+
* whatever the capture did: the app's DOM, styles and events are not touched.
|
|
54
|
+
*/
|
|
55
|
+
export async function captureWithChromeHidden(page, capture) {
|
|
56
|
+
await page.evaluate(HIDE_CHROME_SCRIPT);
|
|
57
|
+
try {
|
|
58
|
+
return await capture();
|
|
59
|
+
}
|
|
60
|
+
finally {
|
|
61
|
+
await page.evaluate(RESTORE_CHROME_SCRIPT).catch(() => undefined);
|
|
62
|
+
}
|
|
29
63
|
}
|
|
30
64
|
/**
|
|
31
65
|
* How a leased tab navigates. Pure, and exported, because the decision in it is worth a test while
|
|
@@ -49,8 +83,8 @@ export function gotoOptions(timeoutMs) {
|
|
|
49
83
|
function wrapBrowser(browser) {
|
|
50
84
|
return {
|
|
51
85
|
isConnected: () => browser.isConnected(),
|
|
52
|
-
newContext: async () => {
|
|
53
|
-
const context = await browser.newContext();
|
|
86
|
+
newContext: async (opts) => {
|
|
87
|
+
const context = await browser.newContext(true === opts?.ignoreHTTPSErrors ? { ignoreHTTPSErrors: true } : undefined);
|
|
54
88
|
return {
|
|
55
89
|
newPage: async () => {
|
|
56
90
|
const page = await context.newPage();
|
|
@@ -59,7 +93,15 @@ function wrapBrowser(browser) {
|
|
|
59
93
|
close: () => page.close(),
|
|
60
94
|
evaluate: (script) => page.evaluate(script),
|
|
61
95
|
// Playwright returns a Buffer; Uint8Array is what the visual store and differ take.
|
|
62
|
-
|
|
96
|
+
// Same determinism as the driven path's capturePage: without it a lease baseline caught
|
|
97
|
+
// the HUD, its activity log and the toolbar, and a HUD change read as a regression (#1355).
|
|
98
|
+
screenshot: async (opts) => {
|
|
99
|
+
const shoot = async () => new Uint8Array(await page.screenshot(screenshotOptions(opts ?? {})));
|
|
100
|
+
// A step capture injects no stylesheet, so our own hosts are hidden another way.
|
|
101
|
+
return true === opts?.cssScale
|
|
102
|
+
? captureWithChromeHidden({ evaluate: (script) => page.evaluate(script) }, shoot)
|
|
103
|
+
: shoot();
|
|
104
|
+
},
|
|
63
105
|
// Three moves, same as performGesture: a single move to the center can be a no-op if
|
|
64
106
|
// the pointer was already there, and CSS :hover needs a native hit-test to apply.
|
|
65
107
|
hover: async (x, y) => {
|
|
@@ -69,6 +111,7 @@ function wrapBrowser(browser) {
|
|
|
69
111
|
},
|
|
70
112
|
installMocks: (rules) => installNetworkMocks(page, [...rules]),
|
|
71
113
|
setViewport: (size) => page.setViewportSize(size),
|
|
114
|
+
bringToFront: () => page.bringToFront(),
|
|
72
115
|
onCrash: (handler) => page.on('crash', handler),
|
|
73
116
|
onConsole: (handler) => page.on('console', (msg) => handler(msg.text())),
|
|
74
117
|
onDialog: (handler) => page.on('dialog', (dialog) => handler({ message: dialog.message(), dismiss: () => dialog.dismiss() })),
|
|
@@ -83,6 +126,8 @@ function wrapBrowser(browser) {
|
|
|
83
126
|
};
|
|
84
127
|
},
|
|
85
128
|
addCookies: (cookies) => context.addCookies(cookies),
|
|
129
|
+
grantPermissions: (permissions, opts) => context.grantPermissions(permissions, opts),
|
|
130
|
+
clearPermissions: () => context.clearPermissions(),
|
|
86
131
|
close: () => context.close(),
|
|
87
132
|
};
|
|
88
133
|
},
|
|
@@ -64,6 +64,11 @@ export interface PooledPage {
|
|
|
64
64
|
* existed short of restarting the daemon), because nothing in the stack ever answered it.
|
|
65
65
|
*/
|
|
66
66
|
onDialog?(handler: (dialog: PooledDialog) => void): void;
|
|
67
|
+
/**
|
|
68
|
+
* Make this the visible tab. OPTIONAL, like `onDialog`: a page opened beside others can start
|
|
69
|
+
* hidden, and a hidden tab throttles timers and rAF so nothing on it verifies (#1351).
|
|
70
|
+
*/
|
|
71
|
+
bringToFront?(): Promise<void>;
|
|
67
72
|
}
|
|
68
73
|
/** A native dialog the page opened, handed to the pool so it can be dismissed instead of left blocking. */
|
|
69
74
|
export interface PooledDialog {
|
|
@@ -103,11 +108,24 @@ export interface PooledContext {
|
|
|
103
108
|
newPage(): Promise<PooledPage>;
|
|
104
109
|
close(): Promise<void>;
|
|
105
110
|
addCookies?(cookies: PooledCookie[]): Promise<void>;
|
|
111
|
+
/**
|
|
112
|
+
* Grant browser permissions on this context. OPTIONAL, like `addCookies`: a context that cannot
|
|
113
|
+
* grant makes a lease that asked for permissions refuse, rather than open with none granted while
|
|
114
|
+
* the caller believes otherwise.
|
|
115
|
+
*/
|
|
116
|
+
grantPermissions?(permissions: string[], opts?: {
|
|
117
|
+
origin?: string;
|
|
118
|
+
}): Promise<void>;
|
|
119
|
+
/** Drop every permission granted on this context. OPTIONAL, for the same reason. */
|
|
120
|
+
clearPermissions?(): Promise<void>;
|
|
106
121
|
}
|
|
107
122
|
/** The launched browser. Real Playwright `Browser` satisfies this. */
|
|
108
123
|
export interface PooledBrowser {
|
|
109
124
|
isConnected(): boolean;
|
|
110
|
-
|
|
125
|
+
/** `ignoreHTTPSErrors` accepts a self-signed or local-CA certificate for this context only. */
|
|
126
|
+
newContext(opts?: {
|
|
127
|
+
ignoreHTTPSErrors?: boolean;
|
|
128
|
+
}): Promise<PooledContext>;
|
|
111
129
|
close(): Promise<void>;
|
|
112
130
|
/** Fires when the browser process dies/crashes so the pool can relaunch on the next acquire. */
|
|
113
131
|
onDisconnected(handler: () => void): void;
|
|
@@ -118,4 +136,6 @@ export type Launcher = () => Promise<PooledBrowser>;
|
|
|
118
136
|
export interface ScreenshotOptions {
|
|
119
137
|
fullPage?: boolean;
|
|
120
138
|
jpegQuality?: number;
|
|
139
|
+
/** One image pixel per CSS pixel, so a high-density display does not double a step screenshot. */
|
|
140
|
+
cssScale?: boolean;
|
|
121
141
|
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What the HUD shows about the coding agent: who is attached, and this tab's latest notes to it with
|
|
3
|
+
* whether an agent's tool call has taken each one. Read from the session's own inbox history, so
|
|
4
|
+
* "Seen" is shown only for a note that was actually handed to an agent.
|
|
5
|
+
*/
|
|
6
|
+
import { type AgentLink } from '@reticlehq/core';
|
|
7
|
+
import type { InboxMessage } from './human/live-control.js';
|
|
8
|
+
export declare function agentLinkOf(history: readonly InboxMessage[]): AgentLink;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What the HUD shows about the coding agent: who is attached, and this tab's latest notes to it with
|
|
3
|
+
* whether an agent's tool call has taken each one. Read from the session's own inbox history, so
|
|
4
|
+
* "Seen" is shown only for a note that was actually handed to an agent.
|
|
5
|
+
*/
|
|
6
|
+
import { AGENT_NOTE_MAX, AGENT_NOTES_SHOWN } from '@reticlehq/core';
|
|
7
|
+
import { connectedAgents } from '../../hooks/coding-agents.js';
|
|
8
|
+
export function agentLinkOf(history) {
|
|
9
|
+
return {
|
|
10
|
+
agents: connectedAgents(),
|
|
11
|
+
notes: history.slice(-AGENT_NOTES_SHOWN).map((message) => ({
|
|
12
|
+
text: message.text.slice(0, AGENT_NOTE_MAX),
|
|
13
|
+
seen: true === message.seen,
|
|
14
|
+
...(message.by === undefined ? {} : { by: message.by }),
|
|
15
|
+
})),
|
|
16
|
+
};
|
|
17
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { CommandActor, MessageKind } from '@reticlehq/core';
|
|
2
|
-
import { currentDrivenBy } from '../../hooks/driven-by.js';
|
|
2
|
+
import { currentDrivenBy, harnessOutwardAllowed } from '../../hooks/driven-by.js';
|
|
3
3
|
/**
|
|
4
4
|
* The command a session sends its page, as wire JSON.
|
|
5
5
|
*
|
|
@@ -15,5 +15,10 @@ export function commandPayload(id, sessionId, name, args) {
|
|
|
15
15
|
name,
|
|
16
16
|
args,
|
|
17
17
|
...(currentDrivenBy() === undefined ? {} : { by: CommandActor.HARNESS }),
|
|
18
|
+
// The page presses no outward control (invite, send, delete, pay…) the journey did not ask for.
|
|
19
|
+
...outwardField(harnessOutwardAllowed()),
|
|
18
20
|
});
|
|
19
21
|
}
|
|
22
|
+
function outwardField(allowed) {
|
|
23
|
+
return allowed === undefined ? {} : { outward: { allowed } };
|
|
24
|
+
}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { log } from '../../log.js';
|
|
2
|
-
import { bindSpanContext } from '../../trace.js';
|
|
3
2
|
/**
|
|
4
3
|
* What the daemon answers when the rules that decide a verdict ask it for something.
|
|
5
4
|
*
|
|
@@ -15,6 +14,7 @@ import { bindSpanContext } from '../../trace.js';
|
|
|
15
14
|
export declare const noteToDaemonLog: typeof log;
|
|
16
15
|
/**
|
|
17
16
|
* Keep a callback belonging to the call that created it, so a re-check scheduled for later still
|
|
18
|
-
* traces back to the wait that asked for it instead of looking like work starting from nowhere
|
|
17
|
+
* traces back to the wait that asked for it instead of looking like work starting from nowhere, and
|
|
18
|
+
* is still the Harness's when the Harness made the call: the HUD files it by who drove it.
|
|
19
19
|
*/
|
|
20
|
-
export declare const keepCallerContextInDaemon:
|
|
20
|
+
export declare const keepCallerContextInDaemon: <A extends unknown[]>(fn: (...args: A) => void) => ((...args: A) => void);
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { log } from '../../log.js';
|
|
2
2
|
import { bindSpanContext } from '../../trace.js';
|
|
3
|
+
import { bindDrivenBy } from '../../hooks/driven-by.js';
|
|
3
4
|
/**
|
|
4
5
|
* What the daemon answers when the rules that decide a verdict ask it for something.
|
|
5
6
|
*
|
|
@@ -15,6 +16,7 @@ import { bindSpanContext } from '../../trace.js';
|
|
|
15
16
|
export const noteToDaemonLog = log;
|
|
16
17
|
/**
|
|
17
18
|
* Keep a callback belonging to the call that created it, so a re-check scheduled for later still
|
|
18
|
-
* traces back to the wait that asked for it instead of looking like work starting from nowhere
|
|
19
|
+
* traces back to the wait that asked for it instead of looking like work starting from nowhere, and
|
|
20
|
+
* is still the Harness's when the Harness made the call: the HUD files it by who drove it.
|
|
19
21
|
*/
|
|
20
|
-
export const keepCallerContextInDaemon = bindSpanContext;
|
|
22
|
+
export const keepCallerContextInDaemon = (fn) => bindDrivenBy(bindSpanContext(fn));
|
|
@@ -36,3 +36,12 @@ export declare function detectDevCommand(directory: string, read?: (path: string
|
|
|
36
36
|
* package manager, because a workspace package usually has no lockfile of its own.
|
|
37
37
|
*/
|
|
38
38
|
export declare function detectDevCommandInProject(directory: string, read?: (path: string) => string | undefined, listDirs?: (path: string) => readonly string[]): DevCommand | undefined;
|
|
39
|
+
/**
|
|
40
|
+
* The command that wires THIS project for good: `init`, in the app's own folder, through the
|
|
41
|
+
* one-off runner the project's package manager ships.
|
|
42
|
+
*
|
|
43
|
+
* Handed to an agent whose install never ran `init` (an MCP-only route), so it has to be right first
|
|
44
|
+
* time: `init` run in a folder that is not the app stops on a missing package.json, and a runner the
|
|
45
|
+
* machine does not have is "command not found". npx whenever there is doubt — it ships with Node.
|
|
46
|
+
*/
|
|
47
|
+
export declare function initCommandIn(directory: string, read?: (path: string) => string | undefined, listDirs?: (path: string) => readonly string[]): string;
|