@reticlehq/server 2.11.0 → 2.13.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 +93 -111
- package/dist/bridge/auth-failure-reason.d.ts +6 -2
- package/dist/bridge/auth-failure-reason.js +15 -8
- package/dist/bridge/bridge.d.ts +18 -14
- package/dist/bridge/bridge.js +248 -165
- package/dist/bridge/bridge.test-harness.d.ts +2 -0
- package/dist/bridge/bridge.test-harness.js +8 -1
- package/dist/bridge/pairing-token.d.ts +5 -0
- package/dist/bridge/pairing-token.js +28 -0
- package/dist/bridge/protocol-skew.d.ts +37 -0
- package/dist/bridge/protocol-skew.js +45 -0
- package/dist/capsule/capsule-store.d.ts +8 -7
- package/dist/capsule/capsule-store.js +1 -1
- package/dist/capsule/causal-summary.d.ts +2 -2
- package/dist/capsule/causal-summary.js +7 -2
- package/dist/chromium-launch-options.d.ts +28 -0
- package/dist/chromium-launch-options.js +29 -0
- package/dist/cli/cli-doctor.js +39 -1
- package/dist/cli/cli-flow-commands.d.ts +3 -1
- package/dist/cli/cli-flow-commands.js +34 -4
- package/dist/cli/cli-kill.d.ts +2 -1
- package/dist/cli/cli-launch.d.ts +11 -1
- package/dist/cli/cli-launch.js +59 -10
- package/dist/cli/cli-parse.d.ts +17 -1
- package/dist/cli/cli-parse.js +238 -12
- package/dist/cli/cli-update-commands.js +20 -1
- package/dist/cli/cli-verify.d.ts +2 -1
- package/dist/cli/cli-verify.js +5 -4
- package/dist/cli/cloud-cli.js +428 -253
- package/dist/cli/cloud-keystore.d.ts +37 -0
- package/dist/cli/cloud-keystore.js +97 -0
- package/dist/cli/cloud-kit.d.ts +37 -0
- package/dist/cli/cloud-kit.js +121 -0
- package/dist/cli/cloud-login.d.ts +17 -0
- package/dist/cli/cloud-login.js +183 -0
- package/dist/cli/cloud-session.d.ts +48 -0
- package/dist/cli/cloud-session.js +53 -0
- package/dist/cli/config-discovery.d.ts +2 -1
- package/dist/cli/config-discovery.js +1 -0
- package/dist/cli/daemon-start-options.d.ts +32 -0
- package/dist/cli/daemon-start-options.js +38 -0
- package/dist/cli/device-flow.d.ts +76 -0
- package/dist/cli/device-flow.js +56 -0
- package/dist/cli/doctor-rows.d.ts +12 -1
- package/dist/cli/doctor-rows.js +12 -1
- package/dist/cli/drive-attach.d.ts +13 -0
- package/dist/cli/drive-attach.js +18 -0
- package/dist/cli/drive-command.js +7 -3
- package/dist/cli/gate-exit.d.ts +21 -0
- package/dist/cli/gate-exit.js +21 -0
- package/dist/cli/gate-hook-message.d.ts +33 -0
- package/dist/cli/gate-hook-message.js +46 -0
- package/dist/cli/mcp-command.d.ts +25 -0
- package/dist/cli/mcp-command.js +174 -0
- package/dist/cli/project-name.d.ts +30 -0
- package/dist/cli/project-name.js +44 -0
- package/dist/cli/sibling-ports.d.ts +37 -0
- package/dist/cli/sibling-ports.js +56 -0
- package/dist/cli/status-next-action.d.ts +14 -0
- package/dist/cli/status-next-action.js +4 -4
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +167 -186
- package/dist/cloud/cloud-config.d.ts +24 -2
- package/dist/cloud/cloud-config.js +64 -5
- package/dist/cloud/cloud-sync.d.ts +16 -5
- package/dist/cloud/cloud-sync.js +64 -1
- package/dist/cloud/sync-cycle.d.ts +110 -0
- package/dist/cloud/sync-cycle.js +270 -0
- package/dist/cloud/sync-daemon.d.ts +69 -0
- package/dist/cloud/sync-daemon.js +260 -0
- package/dist/cloud/sync-disk.d.ts +9 -0
- package/dist/cloud/sync-disk.js +191 -0
- package/dist/cloud/sync-hash.d.ts +2 -0
- package/dist/cloud/sync-hash.js +35 -0
- package/dist/crawl/crawl-tools.js +5 -3
- package/dist/crawl/crawl.d.ts +12 -13
- package/dist/crawl/crawl.js +25 -3
- package/dist/daemon/daemon-resolve.d.ts +122 -0
- package/dist/daemon/daemon-resolve.js +187 -0
- package/dist/daemon/dev-servers.d.ts +15 -0
- package/dist/daemon/dev-servers.js +68 -0
- package/dist/daemon/free-port.d.ts +29 -0
- package/dist/daemon/free-port.js +55 -0
- package/dist/daemon/heartbeat.d.ts +0 -4
- package/dist/daemon/heartbeat.js +2 -2
- package/dist/daemon/wake-decision.d.ts +32 -0
- package/dist/daemon/wake-decision.js +38 -0
- package/dist/dev/stale-issue-guard.d.ts +0 -2
- package/dist/dev/stale-issue-guard.js +1 -1
- package/dist/domain/domain-tools.js +2 -2
- package/dist/events/contradictions.d.ts +59 -0
- package/dist/events/contradictions.js +253 -27
- package/dist/events/declared.d.ts +17 -0
- package/dist/events/declared.js +43 -1
- package/dist/events/echo-mismatch.js +65 -1
- package/dist/events/event-filters.d.ts +8 -0
- package/dist/events/event-filters.js +19 -2
- package/dist/events/observed-in-window.d.ts +12 -0
- package/dist/events/observed-in-window.js +17 -0
- package/dist/events/predicate-asks.d.ts +13 -0
- package/dist/events/predicate-asks.js +22 -0
- package/dist/events/predicate-eval.js +117 -27
- package/dist/events/predicate-parse.d.ts +0 -6
- package/dist/events/predicate-parse.js +43 -3
- package/dist/events/predicate-precheck.d.ts +8 -0
- package/dist/events/predicate-precheck.js +41 -0
- package/dist/events/predicate-route.d.ts +14 -0
- package/dist/events/predicate-route.js +36 -8
- package/dist/events/predicate-schema.d.ts +44 -0
- package/dist/events/predicate-schema.js +126 -23
- package/dist/events/predicate.d.ts +20 -0
- package/dist/events/predicate.js +77 -6
- package/dist/events/split-text-miss.d.ts +30 -0
- package/dist/events/split-text-miss.js +44 -0
- package/dist/flows/coverage.d.ts +0 -8
- package/dist/flows/coverage.js +1 -1
- package/dist/flows/decision.d.ts +5 -1
- package/dist/flows/decision.js +33 -7
- package/dist/flows/flake.d.ts +6 -8
- package/dist/flows/flake.js +1 -1
- package/dist/flows/flow-intent.d.ts +52 -0
- package/dist/flows/flow-intent.js +123 -0
- package/dist/flows/flow-memory-consult.d.ts +55 -0
- package/dist/flows/flow-memory-consult.js +38 -0
- package/dist/flows/flow-replay-run.d.ts +18 -7
- package/dist/flows/flow-replay-run.js +263 -23
- package/dist/flows/flow-replay.js +11 -2
- package/dist/flows/flow-step-runners.d.ts +8 -0
- package/dist/flows/flow-step-runners.js +8 -2
- package/dist/flows/flow-store-for-session.d.ts +31 -0
- package/dist/flows/flow-store-for-session.js +33 -0
- package/dist/flows/flow-success.js +15 -3
- package/dist/flows/flow-tools.js +87 -33
- package/dist/flows/flows.d.ts +14 -1
- package/dist/flows/flows.js +502 -24
- package/dist/flows/heal-run.js +5 -2
- package/dist/flows/predicate-to-expect.d.ts +17 -12
- package/dist/flows/predicate-to-expect.js +36 -15
- package/dist/flows/recordings.d.ts +13 -1
- package/dist/flows/recordings.js +17 -2
- package/dist/flows/replay.d.ts +22 -2
- package/dist/flows/replay.js +28 -2
- package/dist/flows/server-verify.js +16 -2
- package/dist/flows/verify-change-tools.js +9 -3
- package/dist/honesty/blind-spots.d.ts +51 -15
- package/dist/honesty/blind-spots.js +64 -4
- package/dist/honesty/feature-capture.d.ts +150 -0
- package/dist/honesty/feature-capture.js +233 -0
- package/dist/honesty/honesty.d.ts +24 -0
- package/dist/honesty/honesty.js +25 -1
- package/dist/honesty/instrumentation-gaps.d.ts +39 -6
- package/dist/honesty/instrumentation-gaps.js +88 -5
- package/dist/honesty/tool-hit-rate.d.ts +86 -0
- package/dist/honesty/tool-hit-rate.js +90 -0
- package/dist/honesty/undeclared-change.d.ts +51 -0
- package/dist/honesty/undeclared-change.js +56 -0
- package/dist/honesty/verified.d.ts +16 -0
- package/dist/honesty/verified.js +84 -5
- package/dist/http-server.d.ts +0 -1
- package/dist/http-server.js +13 -1
- package/dist/hunt/hunt-report.d.ts +0 -2
- package/dist/hunt/hunt-report.js +1 -1
- package/dist/impact/impact-recorder.d.ts +31 -8
- package/dist/impact/impact-recorder.js +104 -21
- package/dist/impact/impact-store.d.ts +13 -4
- package/dist/impact/impact-store.js +44 -3
- package/dist/index.d.ts +4 -1
- package/dist/index.js +113 -7
- package/dist/init/agent-rules.d.ts +30 -6
- package/dist/init/agent-rules.js +54 -13
- package/dist/init/astro-patch.d.ts +16 -0
- package/dist/init/astro-patch.js +28 -0
- package/dist/init/capabilities.d.ts +4 -3
- package/dist/init/capabilities.js +23 -3
- package/dist/init/closing-hint.d.ts +36 -0
- package/dist/init/closing-hint.js +120 -0
- package/dist/init/confirm.d.ts +27 -28
- package/dist/init/confirm.js +51 -11
- package/dist/init/cra.d.ts +34 -5
- package/dist/init/cra.js +96 -25
- package/dist/init/csp-check.js +17 -2
- package/dist/init/csp-doctor.d.ts +8 -1
- package/dist/init/csp-doctor.js +8 -3
- package/dist/init/dev-script.d.ts +50 -0
- package/dist/init/dev-script.js +66 -0
- package/dist/init/format-generated.d.ts +18 -0
- package/dist/init/format-generated.js +39 -0
- package/dist/init/install-hint.d.ts +9 -0
- package/dist/init/install-hint.js +29 -0
- package/dist/init/mcp-clients.d.ts +7 -0
- package/dist/init/mcp-clients.js +7 -0
- package/dist/init/mcp.d.ts +17 -6
- package/dist/init/mcp.js +27 -11
- package/dist/init/node-io.js +11 -1
- package/dist/init/plan-framework.d.ts +0 -5
- package/dist/init/plan-framework.js +147 -37
- package/dist/init/plan.d.ts +30 -37
- package/dist/init/plan.js +50 -60
- package/dist/init/preflight.d.ts +28 -0
- package/dist/init/preflight.js +38 -0
- package/dist/init/refresh-rules.d.ts +39 -0
- package/dist/init/refresh-rules.js +51 -0
- package/dist/init/run.d.ts +32 -35
- package/dist/init/run.js +151 -202
- package/dist/init/slash-command.d.ts +1 -1
- package/dist/init/snippets.js +90 -31
- package/dist/init/vite-config.d.ts +1 -1
- package/dist/init/vite-config.js +39 -25
- package/dist/init/workspace-apps.d.ts +17 -10
- package/dist/init/workspace-apps.js +110 -0
- package/dist/input/network-mock-tools.js +3 -6
- package/dist/input/real-input.d.ts +2 -0
- package/dist/input/real-input.js +28 -7
- package/dist/input/scroll-find.d.ts +7 -4
- package/dist/input/scroll-find.js +63 -25
- package/dist/input/scroll-tools.js +4 -6
- package/dist/input/viewport-tools.js +5 -4
- package/dist/intent/inline-intent.d.ts +37 -0
- package/dist/intent/inline-intent.js +193 -0
- package/dist/intent/intent-shard-store.d.ts +72 -0
- package/dist/intent/intent-shard-store.js +203 -0
- package/dist/intent/intent-shard.d.ts +411 -0
- package/dist/intent/intent-shard.js +176 -0
- package/dist/intent/intent-store.d.ts +49 -0
- package/dist/intent/intent-store.js +133 -0
- package/dist/intent/intent-subject.d.ts +45 -0
- package/dist/intent/intent-subject.js +177 -0
- package/dist/intent/intent-tools.d.ts +2 -0
- package/dist/intent/intent-tools.js +143 -0
- package/dist/intent/open-intents.d.ts +42 -0
- package/dist/intent/open-intents.js +40 -0
- package/dist/journal/envelope.d.ts +26 -26
- package/dist/journal/journal-recorder.d.ts +23 -0
- package/dist/journal/journal-recorder.js +35 -0
- package/dist/license/license-env.d.ts +29 -0
- package/dist/license/license-env.js +148 -0
- package/dist/loopback-agent.d.ts +31 -0
- package/dist/loopback-agent.js +57 -0
- package/dist/mcp/attach-memory.d.ts +83 -0
- package/dist/mcp/attach-memory.js +185 -0
- package/dist/mcp/client-identity.d.ts +31 -0
- package/dist/mcp/client-identity.js +51 -0
- package/dist/mcp/mcp-post-transport.d.ts +26 -0
- package/dist/mcp/mcp-post-transport.js +109 -0
- package/dist/mcp/mcp-proxy.d.ts +2 -8
- package/dist/mcp/mcp-proxy.js +64 -62
- package/dist/mcp/mcp.d.ts +2 -0
- package/dist/mcp/mcp.js +52 -24
- package/dist/mcp/proxy-backoff.d.ts +11 -0
- package/dist/mcp/proxy-backoff.js +13 -0
- package/dist/mcp/proxy-daemon-probe.d.ts +1 -0
- package/dist/mcp/proxy-daemon-probe.js +7 -1
- package/dist/mcp/proxy-handshake.d.ts +23 -0
- package/dist/mcp/proxy-handshake.js +31 -0
- package/dist/mcp/server-instructions.js +45 -3
- package/dist/mcp/tool-catalog-cache.d.ts +16 -0
- package/dist/mcp/tool-catalog-cache.js +22 -0
- package/dist/memory/memory-tools.d.ts +2 -0
- package/dist/memory/memory-tools.js +82 -0
- package/dist/memory/project-memory.d.ts +34 -0
- package/dist/memory/project-memory.js +96 -0
- package/dist/oracles/flow-instrument-gaps.d.ts +4 -4
- package/dist/oracles/flow-instrument-gaps.js +4 -5
- package/dist/oracles/propose-consequences.js +12 -3
- package/dist/oracles/self-instrument.d.ts +9 -9
- package/dist/oracles/self-instrument.js +19 -13
- package/dist/pool/browser-pool.d.ts +75 -5
- package/dist/pool/browser-pool.js +144 -5
- package/dist/pool/playwright-launcher.js +12 -1
- package/dist/project/fs-port.d.ts +3 -0
- package/dist/project/fs-port.js +3 -2
- package/dist/project/memory-fs.js +6 -1
- package/dist/project/project-tools.js +6 -35
- package/dist/project/reticle-dir.d.ts +17 -2
- package/dist/project/reticle-dir.js +22 -4
- package/dist/runs/context-tools.d.ts +2 -0
- package/dist/runs/context-tools.js +89 -0
- package/dist/runs/run-context.d.ts +40 -0
- package/dist/runs/run-context.js +158 -0
- package/dist/runs/run-diff.d.ts +2 -1
- package/dist/runs/run-store.d.ts +10 -0
- package/dist/runs/run-store.js +10 -0
- package/dist/runs/verification-sync.d.ts +0 -11
- package/dist/runs/verification-sync.js +24 -3
- package/dist/runs/verify-server.d.ts +8 -1
- package/dist/runs/verify-server.js +14 -2
- package/dist/session/command-timeout.d.ts +5 -2
- package/dist/session/command-timeout.js +5 -4
- package/dist/session/dev-server-probe.d.ts +0 -8
- package/dist/session/dev-server-probe.js +1 -1
- package/dist/session/last-act.d.ts +7 -1
- package/dist/session/last-act.js +2 -2
- package/dist/session/lease-visibility.d.ts +67 -0
- package/dist/session/lease-visibility.js +76 -0
- package/dist/session/live-control-tools.js +1 -42
- package/dist/session/no-session-diagnosis.d.ts +33 -0
- package/dist/session/no-session-diagnosis.js +82 -24
- package/dist/session/no-session-next-action.d.ts +12 -0
- package/dist/session/no-session-next-action.js +77 -6
- package/dist/session/no-session-watch.d.ts +18 -6
- package/dist/session/no-session-watch.js +125 -75
- package/dist/session/output-budget.js +4 -1
- package/dist/session/pending-commands.d.ts +11 -1
- package/dist/session/pending-commands.js +12 -2
- package/dist/session/resolve-within.d.ts +34 -0
- package/dist/session/resolve-within.js +53 -0
- package/dist/session/session-health.d.ts +9 -0
- package/dist/session/session-health.js +23 -0
- package/dist/session/session-info.d.ts +18 -0
- package/dist/session/session-info.js +11 -0
- package/dist/session/session-manager.d.ts +14 -0
- package/dist/session/session-manager.js +111 -4
- package/dist/session/session-mirror.d.ts +16 -0
- package/dist/session/session-mirror.js +22 -0
- package/dist/session/session-recommendation.d.ts +19 -5
- package/dist/session/session-recommendation.js +25 -9
- package/dist/session/session-successor.d.ts +37 -0
- package/dist/session/session-successor.js +113 -0
- package/dist/session/session-tools.js +2 -2
- package/dist/session/session.d.ts +53 -3
- package/dist/session/session.js +162 -9
- package/dist/session/wall-clock.d.ts +12 -0
- package/dist/session/wall-clock.js +14 -0
- package/dist/setup/agent-configs.d.ts +96 -0
- package/dist/setup/agent-configs.js +333 -0
- package/dist/setup/agent-io.d.ts +9 -0
- package/dist/setup/agent-io.js +16 -0
- package/dist/setup/agent-writer.d.ts +51 -0
- package/dist/setup/agent-writer.js +115 -0
- package/dist/setup/approval-migration.d.ts +47 -0
- package/dist/setup/approval-migration.js +68 -0
- package/dist/setup/auto-approve.d.ts +85 -0
- package/dist/setup/auto-approve.js +150 -0
- package/dist/setup/bridge-port.d.ts +15 -0
- package/dist/setup/bridge-port.js +24 -0
- package/dist/setup/desktop-shape.d.ts +57 -0
- package/dist/setup/desktop-shape.js +63 -0
- package/dist/setup/dev-server-wait.d.ts +60 -0
- package/dist/setup/dev-server-wait.js +65 -0
- package/dist/setup/drive-agent.d.ts +71 -0
- package/dist/setup/drive-agent.js +171 -0
- package/dist/setup/drive-plan.d.ts +68 -0
- package/dist/setup/drive-plan.js +130 -0
- package/dist/setup/ensure-daemon.d.ts +29 -0
- package/dist/setup/ensure-daemon.js +58 -0
- package/dist/setup/init-runtime.d.ts +47 -0
- package/dist/setup/init-runtime.js +160 -0
- package/dist/setup/interrupt.d.ts +25 -0
- package/dist/setup/interrupt.js +40 -0
- package/dist/setup/license-key.d.ts +39 -0
- package/dist/setup/license-key.js +72 -0
- package/dist/setup/listeners.d.ts +37 -0
- package/dist/setup/listeners.js +85 -0
- package/dist/setup/node-effects.d.ts +60 -0
- package/dist/setup/node-effects.js +210 -0
- package/dist/setup/page-probe.d.ts +39 -0
- package/dist/setup/page-probe.js +49 -0
- package/dist/setup/relaunch.d.ts +36 -0
- package/dist/setup/relaunch.js +57 -0
- package/dist/setup/remaining-steps.d.ts +19 -0
- package/dist/setup/remaining-steps.js +31 -0
- package/dist/setup/run-setup.d.ts +99 -0
- package/dist/setup/run-setup.js +187 -0
- package/dist/setup/session-pick.d.ts +47 -0
- package/dist/setup/session-pick.js +51 -0
- package/dist/setup/setup-command.d.ts +45 -0
- package/dist/setup/setup-command.js +199 -0
- package/dist/setup/setup-options.d.ts +74 -0
- package/dist/setup/setup-options.js +67 -0
- package/dist/setup/transcripts.d.ts +16 -0
- package/dist/setup/transcripts.js +43 -0
- package/dist/status-payload.d.ts +14 -1
- package/dist/status-payload.js +23 -1
- package/dist/telemetry/automation-hint.d.ts +2 -1
- package/dist/telemetry/daemon-telemetry.d.ts +8 -1
- package/dist/telemetry/daemon-telemetry.js +52 -5
- package/dist/telemetry/error-class.js +1 -1
- package/dist/telemetry/feedback-context.d.ts +9 -1
- package/dist/telemetry/feedback-context.js +60 -29
- package/dist/telemetry/feedback-local.d.ts +15 -0
- package/dist/telemetry/feedback-local.js +56 -0
- package/dist/telemetry/feedback-outbox.d.ts +2 -1
- package/dist/telemetry/feedback.d.ts +11 -0
- package/dist/telemetry/feedback.js +19 -6
- package/dist/telemetry/init-telemetry.d.ts +2 -0
- package/dist/telemetry/init-telemetry.js +2 -0
- package/dist/telemetry/install-source.d.ts +14 -0
- package/dist/telemetry/install-source.js +30 -0
- package/dist/telemetry/license-activation.d.ts +7 -1
- package/dist/telemetry/license-activation.js +9 -5
- package/dist/telemetry/mcp-connection.js +7 -0
- package/dist/telemetry/project-profile.d.ts +12 -9
- package/dist/telemetry/project-profile.js +12 -7
- package/dist/telemetry/proxy-telemetry.d.ts +3 -0
- package/dist/telemetry/proxy-telemetry.js +21 -0
- package/dist/telemetry/run-telemetry.d.ts +0 -2
- package/dist/telemetry/run-telemetry.js +1 -1
- package/dist/telemetry/session-metrics.d.ts +12 -0
- package/dist/telemetry/session-metrics.js +35 -1
- package/dist/telemetry/telemetry.js +17 -2
- package/dist/telemetry/tool-refused.d.ts +3 -1
- package/dist/telemetry/tool-refused.js +34 -2
- package/dist/telemetry/verification-of.js +2 -2
- package/dist/tools/act-capsule.d.ts +10 -0
- package/dist/tools/act-capsule.js +8 -2
- package/dist/tools/act-danger.d.ts +2 -1
- package/dist/tools/act-danger.js +11 -3
- package/dist/tools/act-observation.d.ts +41 -0
- package/dist/tools/act-observation.js +36 -0
- package/dist/tools/act-preflight.d.ts +20 -0
- package/dist/tools/act-preflight.js +98 -0
- package/dist/tools/act-sequence-retry.d.ts +45 -0
- package/dist/tools/act-sequence-retry.js +58 -0
- package/dist/tools/act-sequence-tool.d.ts +13 -0
- package/dist/tools/act-sequence-tool.js +135 -0
- package/dist/tools/act-target.d.ts +14 -0
- package/dist/tools/act-target.js +47 -0
- package/dist/tools/act-tools.d.ts +21 -1
- package/dist/tools/act-tools.js +196 -204
- package/dist/tools/assert-source.d.ts +22 -0
- package/dist/tools/assert-source.js +53 -0
- package/dist/tools/assert-verdict.d.ts +20 -3
- package/dist/tools/assert-verdict.js +58 -20
- package/dist/tools/browser-tools.js +6 -22
- package/dist/tools/complete-snapshot.d.ts +48 -0
- package/dist/tools/complete-snapshot.js +75 -0
- package/dist/tools/coverage-tools.d.ts +10 -1
- package/dist/tools/coverage-tools.js +123 -69
- package/dist/tools/dynamic-tools.js +53 -13
- package/dist/tools/error-recovery.d.ts +25 -14
- package/dist/tools/error-recovery.js +78 -9
- package/dist/tools/feedback-tools.d.ts +1 -1
- package/dist/tools/feedback-tools.js +2 -2
- package/dist/tools/invoke-tool.js +121 -11
- package/dist/tools/lease-hint.d.ts +10 -0
- package/dist/tools/lease-hint.js +53 -4
- package/dist/tools/lease-tools.d.ts +35 -5
- package/dist/tools/lease-tools.js +191 -13
- package/dist/tools/merged-name-redirect.d.ts +13 -0
- package/dist/tools/merged-name-redirect.js +22 -0
- package/dist/tools/navigate-arrival.d.ts +0 -2
- package/dist/tools/navigate-arrival.js +1 -1
- package/dist/tools/numeric-bounds.d.ts +100 -0
- package/dist/tools/numeric-bounds.js +125 -0
- package/dist/tools/observe-tools.js +109 -65
- package/dist/tools/read-tools.js +31 -8
- package/dist/tools/real-input-attempt.d.ts +32 -0
- package/dist/tools/real-input-attempt.js +212 -2
- package/dist/tools/reconcile-tools.js +22 -8
- package/dist/tools/resolve-target.d.ts +0 -7
- package/dist/tools/sdk-marker-probe.d.ts +29 -0
- package/dist/tools/sdk-marker-probe.js +57 -0
- package/dist/tools/snapshot-delta.d.ts +1 -1
- package/dist/tools/tool-kit.d.ts +24 -0
- package/dist/tools/tool-kit.js +21 -0
- package/dist/tools/tool-names.d.ts +5 -0
- package/dist/tools/tool-names.js +5 -0
- package/dist/tools/tool-surface.d.ts +85 -6
- package/dist/tools/tool-surface.js +122 -2
- package/dist/tools/tools-helpers.d.ts +19 -0
- package/dist/tools/tools-helpers.js +46 -0
- package/dist/tools/tools.d.ts +2 -0
- package/dist/tools/tools.js +78 -12
- package/dist/tools/unadvertised-help.js +4 -4
- package/dist/tools/verify-next-baton.d.ts +53 -0
- package/dist/tools/verify-next-baton.js +52 -0
- package/dist/update/reticle-deps.d.ts +9 -0
- package/dist/update/reticle-deps.js +27 -0
- package/dist/update/sdk-sync.d.ts +1 -2
- package/dist/update/sdk-sync.js +1 -21
- package/dist/update/update-nudge.d.ts +25 -10
- package/dist/update/update-nudge.js +32 -3
- package/dist/update/updater.d.ts +1 -1
- package/dist/version/peer-announce.js +4 -2
- package/dist/version/sdk-fix.d.ts +47 -0
- package/dist/version/sdk-fix.js +127 -0
- package/dist/version/version-nudge.d.ts +14 -0
- package/dist/version/version-nudge.js +21 -0
- package/dist/version/version-skew.d.ts +38 -3
- package/dist/version/version-skew.js +83 -7
- package/dist/visual/visual-store.d.ts +6 -6
- package/dist/visual/visual-store.js +18 -16
- package/dist/visual/visual-tools.js +57 -12
- package/docs/README.md +2 -1
- package/docs/cli/cloud.mdx +1 -1
- package/docs/cli/doctor.mdx +2 -0
- package/docs/cli/serve.mdx +4 -2
- package/docs/cli/verify.mdx +4 -5
- package/docs/cli.mdx +7 -3
- package/docs/desktop.mdx +1 -1
- package/docs/docs.json +2 -2
- package/docs/gates.md +1 -1
- package/docs/getting-started.md +19 -3
- package/docs/index.mdx +9 -6
- package/docs/install-agentic.mdx +38 -12
- package/docs/install-manual.mdx +1 -1
- package/docs/packages/browser.mdx +2 -2
- package/docs/packages/server.mdx +1 -1
- package/docs/packages.mdx +8 -6
- package/docs/platform-integration.md +17 -0
- package/docs/predicates.mdx +8 -0
- package/docs/reticle-manual.md +106 -0
- package/docs/skill-file.mdx +3 -3
- package/docs/telemetry-contract.md +108 -4
- package/docs/tools-act-sequence.mdx +16 -0
- package/docs/tools-tools-and-run.mdx +2 -4
- package/docs/troubleshooting.mdx +9 -0
- package/docs/usage.md +4 -3
- package/package.json +4 -3
- package/dist/init/cursor.d.ts +0 -24
- package/dist/init/cursor.js +0 -80
- package/dist/session/session-readiness.d.ts +0 -34
- package/dist/session/session-readiness.js +0 -36
|
@@ -1,17 +1,20 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Lease tools — the agent-facing surface of the BrowserPool.
|
|
3
3
|
*
|
|
4
|
-
* `reticle_lease_acquire` opens
|
|
5
|
-
* the sessionId the app's SDK will register
|
|
6
|
-
*
|
|
7
|
-
*
|
|
4
|
+
* `reticle_lease_acquire` opens an isolated headless context navigated to the app URL and returns
|
|
5
|
+
* the sessionId the app's SDK will register. A second acquire on the same origin reuses the live
|
|
6
|
+
* lease rather than minting another tab — that second tab used to poison default session resolution
|
|
7
|
+
* for the rest of the run. The parallel suite still mints via `acquireLeasedSession`, because ten
|
|
8
|
+
* flows on one origin need isolation on purpose.
|
|
8
9
|
*
|
|
9
10
|
* Attach-only: the pool drives a browser against an already-running dev server — it never starts one.
|
|
10
11
|
*/
|
|
11
12
|
import { z } from 'zod';
|
|
12
13
|
import { leaseNotConnectedHint } from './lease-hint.js';
|
|
14
|
+
import { probeSdkMarker } from './sdk-marker-probe.js';
|
|
13
15
|
import { readProjectFramework, readProjectId } from '../cli/cli-port.js';
|
|
14
16
|
import { hasConnectedBefore } from '../session/connection-memory.js';
|
|
17
|
+
import { AGENT_DRIVING_ELSEWHERE, AGENT_DRIVING_HERE_AGAIN, watchersToNotify, } from '../session/lease-visibility.js';
|
|
15
18
|
import { reticleStateHome } from '../daemon/daemon.js';
|
|
16
19
|
import { RETICLE_URL_PARAM, RETICLE_DEFAULT_PORT } from '@reticlehq/core';
|
|
17
20
|
import { ReticleTool } from './tool-names.js';
|
|
@@ -24,19 +27,42 @@ import { chromiumHint } from '../cli/chromium-hint.js';
|
|
|
24
27
|
* printed a static differential over the top of it — telling one agent in `reticle_sessions` that
|
|
25
28
|
* the wiring was proven correct and telling it seconds later that the port was probably wrong.
|
|
26
29
|
*/
|
|
27
|
-
|
|
30
|
+
/**
|
|
31
|
+
* Async only for the marker probe, which is the piece that decides whether this app ships an SDK at
|
|
32
|
+
* all — the difference between the diagnosis a new user needs and four causes that all assume the
|
|
33
|
+
* install already happened. It is one localhost GET on a path that has already failed and is about
|
|
34
|
+
* to print a paragraph, and it can only ever add a sentence: the probe returns `undefined` on any
|
|
35
|
+
* doubt and the hint then says nothing about markers.
|
|
36
|
+
*/
|
|
37
|
+
async function leaseEvidence(deps, port, url) {
|
|
28
38
|
const cwd = process.cwd();
|
|
29
39
|
const projectId = readProjectId(cwd);
|
|
30
40
|
const refusal = deps.sessions.lastClosure()?.reason;
|
|
31
41
|
const framework = readProjectFramework(cwd);
|
|
42
|
+
const sdkMarker = await probeSdkMarker(url);
|
|
32
43
|
return {
|
|
33
44
|
...(refusal === undefined ? {} : { refusal }),
|
|
34
45
|
...(framework === undefined ? {} : { framework }),
|
|
46
|
+
...(sdkMarker === undefined ? {} : { sdkMarker }),
|
|
35
47
|
previouslyConnected: hasConnectedBefore(reticleStateHome(), port, projectId),
|
|
36
48
|
initialized: projectId !== undefined,
|
|
37
49
|
};
|
|
38
50
|
}
|
|
39
51
|
const POOL_UNAVAILABLE = 'browser pool unavailable — the lease tools need the daemon-managed pool (start Reticle via `reticle mcp`).';
|
|
52
|
+
/** The origin of a URL, or undefined when it does not parse. */
|
|
53
|
+
export function originOf(url) {
|
|
54
|
+
try {
|
|
55
|
+
return new URL(url).origin;
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
return undefined;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
const ALREADY_HELD_LEASE = 'you already hold a lease on this origin';
|
|
62
|
+
function alreadyHeldHint(sessionId, origin) {
|
|
63
|
+
return (`${ALREADY_HELD_LEASE} (${origin}): ${sessionId} — reused it rather than opening a second ` +
|
|
64
|
+
'tab, which would make every later call require sessionId. Release first if you want a fresh one.');
|
|
65
|
+
}
|
|
40
66
|
/**
|
|
41
67
|
* Append Reticle identity params (__reticle_session, optional __reticle_project) to a URL so the app's own SDK
|
|
42
68
|
* adopts them on connect. Pure; falls back to plain concatenation if the URL can't be parsed.
|
|
@@ -105,6 +131,39 @@ export function resolveLeasedSessionId(sessions, leaseId) {
|
|
|
105
131
|
return leaseId;
|
|
106
132
|
return sessions.all().find((s) => sessionParamOf(s.url) === leaseId)?.id;
|
|
107
133
|
}
|
|
134
|
+
/**
|
|
135
|
+
* Carry a claimed identity across a navigation.
|
|
136
|
+
*
|
|
137
|
+
* A LEASED tab is addressed by `__reticle_session` in its URL: that param is how the pool finds the
|
|
138
|
+
* context it opened, and — since succession was tightened — it is also the ONLY thing that lets the
|
|
139
|
+
* reconnecting document inherit the lease. `reticle_navigate` sent the caller's raw URL, so the very
|
|
140
|
+
* first navigation stripped the marker, the tab re-announced as an ordinary anonymous session, and
|
|
141
|
+
* the lease was orphaned: "no sessions are connected at all", with a browser window still open on
|
|
142
|
+
* screen. A leased browser that cannot survive being navigated is not a usable one.
|
|
143
|
+
*
|
|
144
|
+
* A tab that claims nothing is left exactly as it was — this must never bolt Reticle's params onto
|
|
145
|
+
* a human's own URL.
|
|
146
|
+
*/
|
|
147
|
+
export function carryReticleIdentity(fromUrl, toUrl) {
|
|
148
|
+
const session = sessionParamOf(fromUrl);
|
|
149
|
+
if (session === undefined)
|
|
150
|
+
return toUrl;
|
|
151
|
+
// Already addressed (a caller passing the stamped URL back) — appending would be a no-op at best.
|
|
152
|
+
if (sessionParamOf(toUrl) !== undefined)
|
|
153
|
+
return toUrl;
|
|
154
|
+
const projectId = projectParamOf(fromUrl);
|
|
155
|
+
return appendReticleParams(toUrl, session, projectId);
|
|
156
|
+
}
|
|
157
|
+
function projectParamOf(url) {
|
|
158
|
+
if (url === undefined)
|
|
159
|
+
return undefined;
|
|
160
|
+
try {
|
|
161
|
+
return new URL(url).searchParams.get(RETICLE_URL_PARAM.PROJECT) ?? undefined;
|
|
162
|
+
}
|
|
163
|
+
catch {
|
|
164
|
+
return undefined;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
108
167
|
function sessionParamOf(url) {
|
|
109
168
|
if (url === undefined)
|
|
110
169
|
return undefined;
|
|
@@ -163,7 +222,7 @@ export async function waitForLeasedSession(isConnected, sleeper = sleep, attempt
|
|
|
163
222
|
*/
|
|
164
223
|
export const LEASE_ACQUIRE_TOOL = {
|
|
165
224
|
name: ReticleTool.LEASE_ACQUIRE,
|
|
166
|
-
description: 'Lease a fresh isolated headless browser context from the shared pool and navigate it to the app URL (the app must already be running and embed @reticlehq/core). Returns the sessionId the leased tab registers — pass it to other tools. The pool keeps all leases in ONE browser and caps concurrency; if at capacity this waits for a free slot. Release with reticle_lease{action:"release"} when the flow is done.',
|
|
225
|
+
description: 'Lease a fresh isolated headless browser context from the shared pool and navigate it to the app URL (the app must already be running and embed @reticlehq/core). If this origin is already leased and still connected, this returns THAT session rather than minting a second tab — a second acquire on the same origin poisons default session resolution. Returns the sessionId the leased tab registers — pass it to other tools. The pool keeps all leases in ONE browser and caps concurrency; if at capacity this waits for a free slot. Release with reticle_lease{action:"release"} when the flow is done. PREFER AN ALREADY-OPEN TAB: if reticle_sessions lists a non-leased session for this app, drive THAT instead — a lease is invisible to the person watching the app, whose HUD lives in their own tab, and a tab flagged hidden/throttled is often still driveable. Lease for isolation you actually need (a second identity, a clean context, parallel flows) or when driving the open tab has failed — this call answers with `preferExisting` when a live tab was available.',
|
|
167
226
|
inputSchema: {
|
|
168
227
|
url: z
|
|
169
228
|
.string()
|
|
@@ -184,7 +243,21 @@ export const LEASE_ACQUIRE_TOOL = {
|
|
|
184
243
|
.describe('Milliseconds until this lease expires if untouched. Each tool call that targets this session resets the clock. Plan your work to finish or re-acquire before this runs out.'),
|
|
185
244
|
leased: z.number().describe('How many contexts are currently leased from the pool.'),
|
|
186
245
|
queued: z.number().describe('How many acquires are waiting for a free slot.'),
|
|
246
|
+
preferExisting: z
|
|
247
|
+
.object({ sessionId: z.string(), note: z.string() })
|
|
248
|
+
.optional()
|
|
249
|
+
.describe('Present when a live NON-leased tab for this app was already connected. That tab is the one a human can see; this lease is not. Release this lease and drive that sessionId unless you specifically need an isolated context.'),
|
|
250
|
+
reused: z
|
|
251
|
+
.boolean()
|
|
252
|
+
.optional()
|
|
253
|
+
.describe('True when this acquire returned an existing live lease on the same origin rather than minting a second context.'),
|
|
187
254
|
hint: z.string().optional(),
|
|
255
|
+
versionSkew: z
|
|
256
|
+
.string()
|
|
257
|
+
.optional()
|
|
258
|
+
.describe("Present when the leased tab's SDK disagrees with this daemon. ready is still true — the " +
|
|
259
|
+
'page dialled in — but CDP-backed tools (screenshot, viewport, real input, network_mock) ' +
|
|
260
|
+
'will fail until the versions match. Same sentence as reticle_sessions.versionSkew.'),
|
|
188
261
|
},
|
|
189
262
|
handler: async (deps, args) => {
|
|
190
263
|
const pool = deps.pool;
|
|
@@ -205,6 +278,33 @@ export const LEASE_ACQUIRE_TOOL = {
|
|
|
205
278
|
}
|
|
206
279
|
}
|
|
207
280
|
const projectId = asString(args['projectId']);
|
|
281
|
+
// Sampled BEFORE acquiring: afterwards this lease is itself a session, and the point is to name
|
|
282
|
+
// a tab that already existed. A human's open tab is the one they can watch, so if one is here
|
|
283
|
+
// the agent should be told at the moment it is choosing — not after it has gone dark on them.
|
|
284
|
+
const alreadyOpen = liveTabFor(deps, projectId);
|
|
285
|
+
const origin = originOf(url);
|
|
286
|
+
const existing = origin === undefined ? undefined : pool.leaseIdOnOrigin?.(origin);
|
|
287
|
+
if (existing !== undefined && origin !== undefined) {
|
|
288
|
+
if (deps.sessions.get(existing) !== undefined) {
|
|
289
|
+
pool.touch(existing);
|
|
290
|
+
return {
|
|
291
|
+
sessionId: existing,
|
|
292
|
+
url,
|
|
293
|
+
ready: true,
|
|
294
|
+
reused: true,
|
|
295
|
+
expiresInMs: pool.leaseTtlMs(),
|
|
296
|
+
leased: pool.activeCount(),
|
|
297
|
+
queued: pool.queuedCount(),
|
|
298
|
+
hint: alreadyHeldHint(existing, origin),
|
|
299
|
+
...(alreadyOpen === undefined
|
|
300
|
+
? {}
|
|
301
|
+
: { preferExisting: { sessionId: alreadyOpen, note: PREFER_EXISTING_NOTE } }),
|
|
302
|
+
};
|
|
303
|
+
}
|
|
304
|
+
// The lease is still held but the tab has gone — a reload dropped the session. Free the
|
|
305
|
+
// slot and mint, rather than handing back a dead id or leaving both contexts occupied.
|
|
306
|
+
await pool.release(existing);
|
|
307
|
+
}
|
|
208
308
|
const sessionId = newLeaseId();
|
|
209
309
|
const navUrl = appendReticleParams(url, sessionId, projectId);
|
|
210
310
|
let lease;
|
|
@@ -230,6 +330,11 @@ export const LEASE_ACQUIRE_TOOL = {
|
|
|
230
330
|
// reaper closes the context mid-flow. See BrowserPool.alias and #157.
|
|
231
331
|
if (registeredId !== undefined)
|
|
232
332
|
pool.alias(registeredId, lease.sessionId);
|
|
333
|
+
// The lease now exists, so any HUD a human is watching has just gone dark. Say so.
|
|
334
|
+
tellWatchers(deps, projectId, AGENT_DRIVING_ELSEWHERE);
|
|
335
|
+
// ready means the SDK dialled in — not that contracts match. Carry the skew warning on acquire
|
|
336
|
+
// so the agent does not learn it only after a CDP tool invents a closed page (#688).
|
|
337
|
+
const versionSkew = registeredId === undefined ? undefined : deps.sessions.get(registeredId)?.versionSkew;
|
|
233
338
|
return {
|
|
234
339
|
sessionId: registeredId ?? lease.sessionId,
|
|
235
340
|
url,
|
|
@@ -237,18 +342,31 @@ export const LEASE_ACQUIRE_TOOL = {
|
|
|
237
342
|
expiresInMs: pool.leaseTtlMs(),
|
|
238
343
|
leased: pool.activeCount(),
|
|
239
344
|
queued: pool.queuedCount(),
|
|
345
|
+
...(alreadyOpen === undefined
|
|
346
|
+
? {}
|
|
347
|
+
: {
|
|
348
|
+
preferExisting: {
|
|
349
|
+
sessionId: alreadyOpen,
|
|
350
|
+
note: PREFER_EXISTING_NOTE,
|
|
351
|
+
},
|
|
352
|
+
}),
|
|
353
|
+
...(versionSkew === undefined ? {} : { versionSkew }),
|
|
240
354
|
...(ready
|
|
241
355
|
? {}
|
|
242
|
-
: (()
|
|
243
|
-
const bridgePort = deps.bridgePort ?? RETICLE_DEFAULT_PORT;
|
|
244
|
-
return {
|
|
245
|
-
hint: leaseNotConnectedHint(url, bridgePort, leaseEvidence(deps, bridgePort)),
|
|
246
|
-
};
|
|
247
|
-
})()),
|
|
356
|
+
: { hint: await notConnectedHint(deps, url, pool.dialFailureUrl?.(lease.sessionId)) }),
|
|
248
357
|
};
|
|
249
358
|
},
|
|
250
359
|
};
|
|
251
|
-
|
|
360
|
+
/** The whole not-connected diagnosis, gathered and worded. Split out so the acquire path stays flat. */
|
|
361
|
+
async function notConnectedHint(deps, url, dialledUrl) {
|
|
362
|
+
const bridgePort = deps.bridgePort ?? RETICLE_DEFAULT_PORT;
|
|
363
|
+
const evidence = await leaseEvidence(deps, bridgePort, url);
|
|
364
|
+
return leaseNotConnectedHint(url, bridgePort, {
|
|
365
|
+
...evidence,
|
|
366
|
+
...(dialledUrl === undefined ? {} : { dialledUrl }),
|
|
367
|
+
});
|
|
368
|
+
}
|
|
369
|
+
const LEASE_RELEASE_TOOL = {
|
|
252
370
|
name: ReticleTool.LEASE_RELEASE,
|
|
253
371
|
description: 'Release a leased browser context by sessionId, closing it and freeing the pool slot for a queued acquire. Call this when a flow finishes so the pool stays within its concurrency cap.',
|
|
254
372
|
inputSchema: {
|
|
@@ -268,8 +386,68 @@ export const LEASE_RELEASE_TOOL = {
|
|
|
268
386
|
if (sessionId === undefined || 0 === sessionId.length) {
|
|
269
387
|
throw new Error('reticle_lease{action:"release"} requires a sessionId');
|
|
270
388
|
}
|
|
389
|
+
// Read the project BEFORE releasing: afterwards the session is gone and there is nothing to
|
|
390
|
+
// ask which project it belonged to.
|
|
391
|
+
const projectId = deps.sessions.get(sessionId)?.projectId;
|
|
271
392
|
await pool.release(sessionId);
|
|
393
|
+
// Only once the LAST lease is gone. Announcing "live again" while another lease still drives
|
|
394
|
+
// would be a lie, and a HUD that says the wrong thing is worse than one that says nothing.
|
|
395
|
+
if (0 === pool.activeCount())
|
|
396
|
+
tellWatchers(deps, projectId, AGENT_DRIVING_HERE_AGAIN);
|
|
272
397
|
return { released: true, leased: pool.activeCount() };
|
|
273
398
|
},
|
|
274
399
|
};
|
|
400
|
+
/**
|
|
401
|
+
* What to say when a lease was taken while a real tab was already open.
|
|
402
|
+
*
|
|
403
|
+
* Not a refusal. Leases are the highest-value path for autonomous work and an agent that genuinely
|
|
404
|
+
* needs isolation must still get one — but a human watching their own tab cannot see a lease, so
|
|
405
|
+
* when both exist the visible one is the better default and the agent should hear that here, where
|
|
406
|
+
* it is choosing, rather than discover it when somebody asks why nothing is happening.
|
|
407
|
+
*/
|
|
408
|
+
export const PREFER_EXISTING_NOTE = 'a non-leased tab for this app was already connected — that is the one a human can see, and this lease is not. Unless you need an isolated context (a second identity, a clean profile, parallel flows), release this lease and drive that sessionId instead.';
|
|
409
|
+
/**
|
|
410
|
+
* The first live non-leased session for this project, if any.
|
|
411
|
+
*
|
|
412
|
+
* Reuses the watcher selector rather than re-deriving "which sessions belong to a human": one rule
|
|
413
|
+
* for one question, so the tab we announce to and the tab we recommend can never disagree.
|
|
414
|
+
*/
|
|
415
|
+
function liveTabFor(deps, projectId) {
|
|
416
|
+
const pool = deps.pool;
|
|
417
|
+
if (pool === undefined)
|
|
418
|
+
return undefined;
|
|
419
|
+
try {
|
|
420
|
+
const candidates = deps.sessions
|
|
421
|
+
.all()
|
|
422
|
+
.map((session) => ({ id: session.id, projectId: session.projectId }));
|
|
423
|
+
return watchersToNotify(candidates, pool.leasedSessionIds(), projectId)[0];
|
|
424
|
+
}
|
|
425
|
+
catch {
|
|
426
|
+
return undefined;
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
/**
|
|
430
|
+
* Tell the tabs a human is watching that the agent has gone somewhere they cannot see.
|
|
431
|
+
*
|
|
432
|
+
* Fire-and-forget, and deliberately never able to fail the tool: this is a courtesy to a person, and
|
|
433
|
+
* a lease that succeeded must not be reported as failed because a narration could not be posted to
|
|
434
|
+
* some unrelated tab. `pushNarration` is already fire-and-forget; the try/catch covers a session
|
|
435
|
+
* that disconnects between listing it and posting to it.
|
|
436
|
+
*/
|
|
437
|
+
function tellWatchers(deps, projectId, text) {
|
|
438
|
+
const pool = deps.pool;
|
|
439
|
+
if (pool === undefined)
|
|
440
|
+
return;
|
|
441
|
+
try {
|
|
442
|
+
const candidates = deps.sessions
|
|
443
|
+
.all()
|
|
444
|
+
.map((session) => ({ id: session.id, projectId: session.projectId }));
|
|
445
|
+
for (const id of watchersToNotify(candidates, pool.leasedSessionIds(), projectId)) {
|
|
446
|
+
deps.sessions.get(id)?.pushNarration(text);
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
catch {
|
|
450
|
+
// A HUD that missed one line is a smaller problem than a lease reported as broken.
|
|
451
|
+
}
|
|
452
|
+
}
|
|
275
453
|
export const LEASE_TOOLS = [LEASE_ACQUIRE_TOOL, LEASE_RELEASE_TOOL];
|
|
@@ -8,6 +8,19 @@ interface MergedNameRedirect {
|
|
|
8
8
|
}
|
|
9
9
|
/** Where `name` went, or undefined when it is a live tool or not ours. */
|
|
10
10
|
export declare function mergedNameRedirect(name: string): MergedNameRedirect | undefined;
|
|
11
|
+
/**
|
|
12
|
+
* Every retired name against the call that replaces it — the tombstones, as one block.
|
|
13
|
+
*
|
|
14
|
+
* The redirect above answers an agent that already guessed the old name. This answers the one that
|
|
15
|
+
* is reading the surface to find out what exists, and is the case a redirect cannot reach: nothing
|
|
16
|
+
* in the catalogue says `reticle_crawl` became `reticle_verify { action: "crawl" }`, so instructions
|
|
17
|
+
* written against an earlier release lead either to an error string or to nothing at all.
|
|
18
|
+
*
|
|
19
|
+
* Derived from the same two declarations as `BY_OLD_NAME`, for the same reason: a hand-written
|
|
20
|
+
* migration list is one merge away from being wrong, and wrong is worse than absent here — the agent
|
|
21
|
+
* retries into it.
|
|
22
|
+
*/
|
|
23
|
+
export declare function retiredToolNames(): Readonly<Record<string, string>>;
|
|
11
24
|
/** The sentence handed to an agent that called `name`. */
|
|
12
25
|
export declare function mergedNameMessage(name: string, redirect: MergedNameRedirect): string;
|
|
13
26
|
export {};
|
|
@@ -46,6 +46,28 @@ const BY_OLD_NAME = (() => {
|
|
|
46
46
|
export function mergedNameRedirect(name) {
|
|
47
47
|
return BY_OLD_NAME.get(name);
|
|
48
48
|
}
|
|
49
|
+
/**
|
|
50
|
+
* Every retired name against the call that replaces it — the tombstones, as one block.
|
|
51
|
+
*
|
|
52
|
+
* The redirect above answers an agent that already guessed the old name. This answers the one that
|
|
53
|
+
* is reading the surface to find out what exists, and is the case a redirect cannot reach: nothing
|
|
54
|
+
* in the catalogue says `reticle_crawl` became `reticle_verify { action: "crawl" }`, so instructions
|
|
55
|
+
* written against an earlier release lead either to an error string or to nothing at all.
|
|
56
|
+
*
|
|
57
|
+
* Derived from the same two declarations as `BY_OLD_NAME`, for the same reason: a hand-written
|
|
58
|
+
* migration list is one merge away from being wrong, and wrong is worse than absent here — the agent
|
|
59
|
+
* retries into it.
|
|
60
|
+
*/
|
|
61
|
+
export function retiredToolNames() {
|
|
62
|
+
const tombstones = {};
|
|
63
|
+
for (const [old, redirect] of BY_OLD_NAME) {
|
|
64
|
+
tombstones[old] =
|
|
65
|
+
redirect.action === undefined
|
|
66
|
+
? `retired; ${redirect.note ?? `use ${redirect.tool}`}`
|
|
67
|
+
: `retired; use ${redirect.tool} { action: "${redirect.action}" }`;
|
|
68
|
+
}
|
|
69
|
+
return tombstones;
|
|
70
|
+
}
|
|
49
71
|
/** The sentence handed to an agent that called `name`. */
|
|
50
72
|
export function mergedNameMessage(name, redirect) {
|
|
51
73
|
return redirect.action === undefined
|
|
@@ -13,8 +13,6 @@
|
|
|
13
13
|
*/
|
|
14
14
|
import type { SessionManager } from '../session/session-manager.js';
|
|
15
15
|
import type { NavigateArrival } from './navigate-result.js';
|
|
16
|
-
/** Long enough for a dev server to serve a page and the SDK to dial back; short enough to not hang. */
|
|
17
|
-
export declare const ARRIVAL_TIMEOUT_MS = 5000;
|
|
18
16
|
export interface ArrivalClock {
|
|
19
17
|
now: () => number;
|
|
20
18
|
sleep: (ms: number) => Promise<void>;
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
* the sleep are injected so this is testable without waiting on a real one.
|
|
13
13
|
*/
|
|
14
14
|
/** Long enough for a dev server to serve a page and the SDK to dial back; short enough to not hang. */
|
|
15
|
-
|
|
15
|
+
const ARRIVAL_TIMEOUT_MS = 5_000;
|
|
16
16
|
const POLL_MS = 100;
|
|
17
17
|
/**
|
|
18
18
|
* Compare only origin + pathname.
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared bounds for numeric TOOL INPUTS.
|
|
3
|
+
*
|
|
4
|
+
* An unknown parameter is refused with "They were NOT applied — a result computed without them
|
|
5
|
+
* would look like an answer." A known parameter carrying a value the code cannot honour is the
|
|
6
|
+
* same failure: `reticle_state { depth: -5 }` used to return the full unscoped store, because
|
|
7
|
+
* `capDepth` treats a negative budget as "no cap". The agent cannot tell a bound it asked for
|
|
8
|
+
* from a bound that was dropped.
|
|
9
|
+
*
|
|
10
|
+
* A single rule for every number would be wrong (`since: 0` is a real cursor; `timeout_ms: 0`
|
|
11
|
+
* on assert means evaluate now; `threshold` is a 0–1 ratio). Each helper below is one policy,
|
|
12
|
+
* with the sentence for why that bound and not another.
|
|
13
|
+
*/
|
|
14
|
+
import { z } from 'zod';
|
|
15
|
+
/**
|
|
16
|
+
* Hard cap on "return the first N". The ring buffer holds this many events; asking for a billion
|
|
17
|
+
* cannot be honoured from memory we do not keep, and would look like a complete listing.
|
|
18
|
+
*/
|
|
19
|
+
export declare const MAX_RESULT_COUNT: 2000;
|
|
20
|
+
/**
|
|
21
|
+
* Hard cap on a numeric millisecond argument that does NOT block the caller's request.
|
|
22
|
+
* `timeout_ms: 0` stays legal — it means evaluate once, do not wait.
|
|
23
|
+
*/
|
|
24
|
+
export declare const MAX_TIMEOUT_MS = 120000;
|
|
25
|
+
export declare const MAX_BLOCKING_WAIT_MS: number;
|
|
26
|
+
/**
|
|
27
|
+
* `capDepth` at this many levels is already past any store an agent can read.
|
|
28
|
+
*
|
|
29
|
+
* Not lower: `numeric-args-are-bounded.test.ts` pins depth 50 as legal, because a large depth is a
|
|
30
|
+
* SCOPE choice and not an error. A ceiling that refuses it would turn a working call into a refusal
|
|
31
|
+
* in the name of bounding one that never worked.
|
|
32
|
+
*/
|
|
33
|
+
export declare const MAX_STATE_DEPTH = 256;
|
|
34
|
+
/** A crawl that clicks forever is not a bound. */
|
|
35
|
+
export declare const MAX_CRAWL_STEPS = 500;
|
|
36
|
+
/** Scroll-to-find steps. Default is 20; hundreds is searching, thousands is a hang. */
|
|
37
|
+
export declare const MAX_SCROLLS = 200;
|
|
38
|
+
/** Fake-clock jump. One day of timers is a test; a billion ms is not. */
|
|
39
|
+
export declare const MAX_ADVANCE_MS = 86400000;
|
|
40
|
+
/** Presenter idle window. One hour is a slow app; larger values never fire. */
|
|
41
|
+
export declare const MAX_IDLE_MS = 3600000;
|
|
42
|
+
/** Viewport CSS px — matches the clamp the handler already applied, now as a refusal. */
|
|
43
|
+
export declare const MIN_VIEWPORT_PX = 64;
|
|
44
|
+
export declare const MAX_VIEWPORT_PX = 10000;
|
|
45
|
+
/**
|
|
46
|
+
* A page cursor. 0 is the start of the buffer, so `.positive()` would refuse a legitimate first
|
|
47
|
+
* page. Negative is not a cursor.
|
|
48
|
+
*/
|
|
49
|
+
export declare const cursorSchema: z.ZodNumber;
|
|
50
|
+
/**
|
|
51
|
+
* A wait budget in ms. 0 means evaluate now (documented on assert). Negative cannot be honoured.
|
|
52
|
+
*/
|
|
53
|
+
export declare const timeoutMsSchema: z.ZodNumber;
|
|
54
|
+
/**
|
|
55
|
+
* A count / cap. 0 means "return none", which is a real request. Negative is not.
|
|
56
|
+
* Capped at the ring-buffer size so a `limit: 1e9` cannot pretend the buffer is larger than it is.
|
|
57
|
+
*/
|
|
58
|
+
export declare const countSchema: z.ZodNumber;
|
|
59
|
+
/**
|
|
60
|
+
* Store projection depth. Negative used to mean "no cap" inside `capDepth`, which is how
|
|
61
|
+
* `depth: -5` silently returned the full store — that is the defect this bound closes.
|
|
62
|
+
*
|
|
63
|
+
* 0 stays REFUSED, which is the policy already on the surface (a zero-level read is not a read).
|
|
64
|
+
* `capDepth(v, 0)` does return a size marker, so accepting it would be defensible — but that is a
|
|
65
|
+
* change to what the tool answers, not a bound on what it cannot honour, and it belongs in its own
|
|
66
|
+
* change with its own reason.
|
|
67
|
+
*/
|
|
68
|
+
export declare const depthSchema: z.ZodNumber;
|
|
69
|
+
/**
|
|
70
|
+
* Pixel-diff ratios (`threshold`, `maxRatio`). pixelmatch's threshold and our pass ratio are both
|
|
71
|
+
* 0..1; `.int()` would refuse 0.01.
|
|
72
|
+
*/
|
|
73
|
+
export declare const ratioSchema: z.ZodNumber;
|
|
74
|
+
/** HTTP status on a mock or a filter. */
|
|
75
|
+
export declare const httpStatusSchema: z.ZodNumber;
|
|
76
|
+
/** Viewport CSS px. `.int()` alone still accepted 5 and 999999, then the handler silently clamped. */
|
|
77
|
+
export declare const viewportPxSchema: z.ZodNumber;
|
|
78
|
+
/** Crawl / scroll step budgets. 0 is a documented no-op on crawl ("raise it to crawl at all"). */
|
|
79
|
+
export declare const stepCountSchema: z.ZodNumber;
|
|
80
|
+
export declare const scrollCountSchema: z.ZodNumber;
|
|
81
|
+
export declare const advanceMsSchema: z.ZodNumber;
|
|
82
|
+
export declare const idleMsSchema: z.ZodNumber;
|
|
83
|
+
/** Delay before a mocked response. 0 is immediate. */
|
|
84
|
+
export declare const delayMsSchema: z.ZodNumber;
|
|
85
|
+
/**
|
|
86
|
+
* Observe lookback. Must be > 0 — a non-positive window used to mint a FUTURE cursor, so the
|
|
87
|
+
* tool returned zero events and looked like a quiet page. Capped so `window_ms: 1e12` cannot hang.
|
|
88
|
+
*/
|
|
89
|
+
export declare const windowMsSchema: z.ZodNumber;
|
|
90
|
+
/**
|
|
91
|
+
* Parallelism for suite replay. 0 (and omit) means sequential. Capped at the session/pool ceiling;
|
|
92
|
+
* asking for a thousand workers cannot be honoured.
|
|
93
|
+
*/
|
|
94
|
+
export declare const workerCountSchema: z.ZodNumber;
|
|
95
|
+
/**
|
|
96
|
+
* A row index / list length in a virtualized table. Those lists are large on purpose; the ring
|
|
97
|
+
* buffer's 2000 is the wrong ceiling. A billion-row claim is not a list, it is a hang.
|
|
98
|
+
*/
|
|
99
|
+
export declare const MAX_LIST_INDEX = 1000000;
|
|
100
|
+
export declare const listIndexSchema: z.ZodNumber;
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared bounds for numeric TOOL INPUTS.
|
|
3
|
+
*
|
|
4
|
+
* An unknown parameter is refused with "They were NOT applied — a result computed without them
|
|
5
|
+
* would look like an answer." A known parameter carrying a value the code cannot honour is the
|
|
6
|
+
* same failure: `reticle_state { depth: -5 }` used to return the full unscoped store, because
|
|
7
|
+
* `capDepth` treats a negative budget as "no cap". The agent cannot tell a bound it asked for
|
|
8
|
+
* from a bound that was dropped.
|
|
9
|
+
*
|
|
10
|
+
* A single rule for every number would be wrong (`since: 0` is a real cursor; `timeout_ms: 0`
|
|
11
|
+
* on assert means evaluate now; `threshold` is a 0–1 ratio). Each helper below is one policy,
|
|
12
|
+
* with the sentence for why that bound and not another.
|
|
13
|
+
*/
|
|
14
|
+
import { z } from 'zod';
|
|
15
|
+
import { RING_BUFFER_DEFAULTS, TRANSPORT_LIMITS } from '@reticlehq/core';
|
|
16
|
+
/**
|
|
17
|
+
* Hard cap on "return the first N". The ring buffer holds this many events; asking for a billion
|
|
18
|
+
* cannot be honoured from memory we do not keep, and would look like a complete listing.
|
|
19
|
+
*/
|
|
20
|
+
export const MAX_RESULT_COUNT = RING_BUFFER_DEFAULTS.MAX_EVENTS;
|
|
21
|
+
/**
|
|
22
|
+
* Hard cap on a numeric millisecond argument that does NOT block the caller's request.
|
|
23
|
+
* `timeout_ms: 0` stays legal — it means evaluate once, do not wait.
|
|
24
|
+
*/
|
|
25
|
+
export const MAX_TIMEOUT_MS = 120_000;
|
|
26
|
+
/**
|
|
27
|
+
* Hard cap on a wait the CALLER BLOCKS ON, which is a different ceiling from the one above.
|
|
28
|
+
*
|
|
29
|
+
* A blocking wait is bounded by the client's patience, not by ours. The MCP SDK's default request
|
|
30
|
+
* timeout is 60s and clients configure it lower; we advertised 120s. A caller who believed the
|
|
31
|
+
* advertised bound and asked for 90s got a TRANSPORT error at 60s — not a Reticle verdict, not a
|
|
32
|
+
* near-miss diagnosis, nothing to act on. The wait was honoured right up to the point where the
|
|
33
|
+
* only thing that could report it had gone.
|
|
34
|
+
*
|
|
35
|
+
* So the ceiling is set below the SDK default rather than at it: the margin is what lets Reticle's
|
|
36
|
+
* own "timed out, here is the near miss" answer beat the client's abort. A refused argument is a
|
|
37
|
+
* bad ceiling costing one round trip; an accepted one that cannot be delivered costs the drive.
|
|
38
|
+
*
|
|
39
|
+
* This does not make long waits possible, and is not meant to — it makes the ADVERTISED bound one
|
|
40
|
+
* that can actually be honoured. A caller that genuinely needs to outlast this polls: several short
|
|
41
|
+
* waits, each of which returns a verdict. See #601 for the bounded-wait cursor that would let one
|
|
42
|
+
* call do it properly.
|
|
43
|
+
*/
|
|
44
|
+
const MCP_SDK_DEFAULT_REQUEST_TIMEOUT_MS = 60_000;
|
|
45
|
+
export const MAX_BLOCKING_WAIT_MS = MCP_SDK_DEFAULT_REQUEST_TIMEOUT_MS - 5_000;
|
|
46
|
+
/**
|
|
47
|
+
* `capDepth` at this many levels is already past any store an agent can read.
|
|
48
|
+
*
|
|
49
|
+
* Not lower: `numeric-args-are-bounded.test.ts` pins depth 50 as legal, because a large depth is a
|
|
50
|
+
* SCOPE choice and not an error. A ceiling that refuses it would turn a working call into a refusal
|
|
51
|
+
* in the name of bounding one that never worked.
|
|
52
|
+
*/
|
|
53
|
+
export const MAX_STATE_DEPTH = 256;
|
|
54
|
+
/** A crawl that clicks forever is not a bound. */
|
|
55
|
+
export const MAX_CRAWL_STEPS = 500;
|
|
56
|
+
/** Scroll-to-find steps. Default is 20; hundreds is searching, thousands is a hang. */
|
|
57
|
+
export const MAX_SCROLLS = 200;
|
|
58
|
+
/** Fake-clock jump. One day of timers is a test; a billion ms is not. */
|
|
59
|
+
export const MAX_ADVANCE_MS = 86_400_000;
|
|
60
|
+
/** Presenter idle window. One hour is a slow app; larger values never fire. */
|
|
61
|
+
export const MAX_IDLE_MS = 3_600_000;
|
|
62
|
+
/** Viewport CSS px — matches the clamp the handler already applied, now as a refusal. */
|
|
63
|
+
export const MIN_VIEWPORT_PX = 64;
|
|
64
|
+
export const MAX_VIEWPORT_PX = 10_000;
|
|
65
|
+
/**
|
|
66
|
+
* A page cursor. 0 is the start of the buffer, so `.positive()` would refuse a legitimate first
|
|
67
|
+
* page. Negative is not a cursor.
|
|
68
|
+
*/
|
|
69
|
+
export const cursorSchema = z.number().finite().int().nonnegative();
|
|
70
|
+
/**
|
|
71
|
+
* A wait budget in ms. 0 means evaluate now (documented on assert). Negative cannot be honoured.
|
|
72
|
+
*/
|
|
73
|
+
export const timeoutMsSchema = z.number().finite().int().nonnegative().max(MAX_BLOCKING_WAIT_MS);
|
|
74
|
+
/**
|
|
75
|
+
* A count / cap. 0 means "return none", which is a real request. Negative is not.
|
|
76
|
+
* Capped at the ring-buffer size so a `limit: 1e9` cannot pretend the buffer is larger than it is.
|
|
77
|
+
*/
|
|
78
|
+
export const countSchema = z.number().finite().int().nonnegative().max(MAX_RESULT_COUNT);
|
|
79
|
+
/**
|
|
80
|
+
* Store projection depth. Negative used to mean "no cap" inside `capDepth`, which is how
|
|
81
|
+
* `depth: -5` silently returned the full store — that is the defect this bound closes.
|
|
82
|
+
*
|
|
83
|
+
* 0 stays REFUSED, which is the policy already on the surface (a zero-level read is not a read).
|
|
84
|
+
* `capDepth(v, 0)` does return a size marker, so accepting it would be defensible — but that is a
|
|
85
|
+
* change to what the tool answers, not a bound on what it cannot honour, and it belongs in its own
|
|
86
|
+
* change with its own reason.
|
|
87
|
+
*/
|
|
88
|
+
export const depthSchema = z.number().finite().int().positive().max(MAX_STATE_DEPTH);
|
|
89
|
+
/**
|
|
90
|
+
* Pixel-diff ratios (`threshold`, `maxRatio`). pixelmatch's threshold and our pass ratio are both
|
|
91
|
+
* 0..1; `.int()` would refuse 0.01.
|
|
92
|
+
*/
|
|
93
|
+
export const ratioSchema = z.number().finite().min(0).max(1);
|
|
94
|
+
/** HTTP status on a mock or a filter. */
|
|
95
|
+
export const httpStatusSchema = z.number().finite().int().min(100).max(599);
|
|
96
|
+
/** Viewport CSS px. `.int()` alone still accepted 5 and 999999, then the handler silently clamped. */
|
|
97
|
+
export const viewportPxSchema = z.number().finite().int().min(MIN_VIEWPORT_PX).max(MAX_VIEWPORT_PX);
|
|
98
|
+
/** Crawl / scroll step budgets. 0 is a documented no-op on crawl ("raise it to crawl at all"). */
|
|
99
|
+
export const stepCountSchema = z.number().finite().int().nonnegative().max(MAX_CRAWL_STEPS);
|
|
100
|
+
export const scrollCountSchema = z.number().finite().int().nonnegative().max(MAX_SCROLLS);
|
|
101
|
+
export const advanceMsSchema = z.number().finite().int().nonnegative().max(MAX_ADVANCE_MS);
|
|
102
|
+
export const idleMsSchema = z.number().finite().int().nonnegative().max(MAX_IDLE_MS);
|
|
103
|
+
/** Delay before a mocked response. 0 is immediate. */
|
|
104
|
+
export const delayMsSchema = z.number().finite().int().nonnegative().max(MAX_TIMEOUT_MS);
|
|
105
|
+
/**
|
|
106
|
+
* Observe lookback. Must be > 0 — a non-positive window used to mint a FUTURE cursor, so the
|
|
107
|
+
* tool returned zero events and looked like a quiet page. Capped so `window_ms: 1e12` cannot hang.
|
|
108
|
+
*/
|
|
109
|
+
export const windowMsSchema = z.number().finite().int().positive().max(MAX_TIMEOUT_MS);
|
|
110
|
+
/**
|
|
111
|
+
* Parallelism for suite replay. 0 (and omit) means sequential. Capped at the session/pool ceiling;
|
|
112
|
+
* asking for a thousand workers cannot be honoured.
|
|
113
|
+
*/
|
|
114
|
+
export const workerCountSchema = z
|
|
115
|
+
.number()
|
|
116
|
+
.finite()
|
|
117
|
+
.int()
|
|
118
|
+
.nonnegative()
|
|
119
|
+
.max(TRANSPORT_LIMITS.MAX_SESSIONS);
|
|
120
|
+
/**
|
|
121
|
+
* A row index / list length in a virtualized table. Those lists are large on purpose; the ring
|
|
122
|
+
* buffer's 2000 is the wrong ceiling. A billion-row claim is not a list, it is a hang.
|
|
123
|
+
*/
|
|
124
|
+
export const MAX_LIST_INDEX = 1_000_000;
|
|
125
|
+
export const listIndexSchema = z.number().finite().int().nonnegative().max(MAX_LIST_INDEX);
|