@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
package/dist/init/snippets.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Generated file contents and copy-paste snippets for `reticle init`. Kept as named constants/builders
|
|
3
3
|
* so the runner never inlines free strings.
|
|
4
4
|
*/
|
|
5
|
-
import { RETICLE_DEFAULT_PORT, ReticleDir, bridgeWsUrl } from '@reticlehq/core';
|
|
5
|
+
import { RETICLE_DEFAULT_PORT, ReticleDir, bridgeWsUrl, RETICLE_CLIENT_HOST, RETICLE_WS_PATH, } from '@reticlehq/core';
|
|
6
6
|
import { UiLibrary } from './detect.js';
|
|
7
7
|
import { SERVER_VERSION } from '../version/server-version.js';
|
|
8
8
|
/**
|
|
@@ -17,9 +17,9 @@ import { SERVER_VERSION } from '../version/server-version.js';
|
|
|
17
17
|
*
|
|
18
18
|
* jsDelivr rather than esm.sh, measured: a third of the requests and a third of the bytes for the
|
|
19
19
|
* same result. `/+esm` is what makes it work, and the bare package URL does NOT: every file in
|
|
20
|
-
* `dist` carries bare specifiers
|
|
21
|
-
*
|
|
22
|
-
*
|
|
20
|
+
* `dist` still carries bare workspace specifiers such as `@reticlehq/core`, so an unbundled entry
|
|
21
|
+
* point dies on the first import. That is also why adding `unpkg`/`jsdelivr` fields to package.json
|
|
22
|
+
* would not help.
|
|
23
23
|
*
|
|
24
24
|
* PINNED to this server's version on purpose. A floating import upgrades the page SDK underneath a
|
|
25
25
|
* daemon that did not move, which is `version_skew` arriving by a route nothing checks.
|
|
@@ -132,38 +132,51 @@ export function nextReticleDevFile(port, projectId, testids = [], stores = [], f
|
|
|
132
132
|
// Same rule as the Vite module: a store we found is registered outright, and the commented hint
|
|
133
133
|
// survives only for the libraries we can name but not wire.
|
|
134
134
|
const storeImports = found.map((s) => `import { ${s.ident} } from '${s.importPath}';`).join('\n');
|
|
135
|
+
// Eight spaces: nested inside useEffect → .then callback (see multiline shape below for #684).
|
|
135
136
|
const storeBlock = found.length > 0
|
|
136
|
-
? found.map((s) => `
|
|
137
|
+
? found.map((s) => ` registerStore('${s.key}', ${s.ident});`).join('\n')
|
|
137
138
|
: 0 === stores.length
|
|
138
|
-
? '
|
|
139
|
-
: stores.map((h) => `
|
|
139
|
+
? ' // No state library detected. If you add one, register it here — see node_modules/@reticlehq/server/docs/usage.md.'
|
|
140
|
+
: stores.map((h) => ` // import your store, then: ${h}`).join('\n');
|
|
141
|
+
const registerNames = found.length > 0 ? ', registerStore' : '';
|
|
142
|
+
// Multiline connect + single blank after imports (#684): the one-line connect and the double blank
|
|
143
|
+
// both fail Prettier on a clean Next install.
|
|
140
144
|
return `'use client';
|
|
141
145
|
import { useEffect } from 'react';
|
|
142
|
-
${storeImports.length > 0 ? storeImports : ''}
|
|
143
|
-
|
|
146
|
+
${storeImports.length > 0 ? `${storeImports}\n` : ''}
|
|
144
147
|
/** Dev-only: connect Reticle + install the React adapter, after hydration. */
|
|
145
148
|
export function ReticleDev() {
|
|
146
149
|
useEffect(() => {
|
|
147
150
|
if (process.env.NODE_ENV !== 'development') return;
|
|
148
|
-
void import('@reticlehq/react').then(
|
|
149
|
-
install
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
151
|
+
void import('@reticlehq/react').then(
|
|
152
|
+
({ reticle, install, registerCapabilities${registerNames} }) => {
|
|
153
|
+
install();
|
|
154
|
+
// Both provided by withReticle() in next.config. The bridge rejects a connect with no token;
|
|
155
|
+
// the root makes source paths repo-relative instead of absolute.
|
|
156
|
+
const token = process.env.NEXT_PUBLIC_RETICLE_TOKEN;
|
|
157
|
+
const root = process.env.NEXT_PUBLIC_RETICLE_ROOT;
|
|
158
|
+
// withReticle() finds the daemon serving this project on every dev-server start. It wins over
|
|
159
|
+
// any port written into this file at install time, so moving the daemon needs no edit here.
|
|
160
|
+
const url = process.env.NEXT_PUBLIC_RETICLE_URL;
|
|
161
|
+
reticle.connect({
|
|
162
|
+
${fields}...(url ? { url } : {}),
|
|
163
|
+
...(token ? { token } : {}),
|
|
164
|
+
...(root ? { root } : {}),
|
|
165
|
+
});
|
|
155
166
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
167
|
+
// ── Start with ONE flow. ────────────────────────────────────────────────────────────────
|
|
168
|
+
// Registering a store is the highest-value line here: it lets the agent check what the app
|
|
169
|
+
// BELIEVES, not just what it rendered. Pass the STORE, not \`() => store.getState()\` — the
|
|
170
|
+
// store form wires \`subscribe\` too, so every mutation emits a diff; the getter form is
|
|
171
|
+
// read-only.
|
|
160
172
|
${storeBlock}
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
173
|
+
registerCapabilities({
|
|
174
|
+
testids: [${ids}],${0 === testids.length ? ' // none found; add data-testid to your key elements' : ''}
|
|
175
|
+
signals: [], // names you pass to reticle.signal()
|
|
176
|
+
stores: [${found.map((s) => `'${s.key}'`).join(', ')}], // the keys you registered above
|
|
177
|
+
});
|
|
178
|
+
},
|
|
179
|
+
);
|
|
167
180
|
}, []);
|
|
168
181
|
return null;
|
|
169
182
|
}
|
|
@@ -204,11 +217,51 @@ layoutPath) {
|
|
|
204
217
|
? `\n url: '${bridgeWsUrl(port)}',`
|
|
205
218
|
: '';
|
|
206
219
|
const id = projectId !== undefined && projectId.length > 0 ? `\n projectId: '${projectId}',` : '';
|
|
220
|
+
// Astro owns its Vite instance, so it has a build-time channel of its own: the same `define` that
|
|
221
|
+
// already inlines the token can inline the daemon URL, resolved every time the config is read —
|
|
222
|
+
// that is, on every `astro dev`. The port above is written once at install time and goes stale the
|
|
223
|
+
// moment the daemon moves; this does not.
|
|
224
|
+
//
|
|
225
|
+
// Needs the projectId to know WHICH daemon is ours. Without one there is nothing to match on, and
|
|
226
|
+
// adopting a daemon serving another project would report its state as this app's, so the whole
|
|
227
|
+
// block is omitted rather than made to guess.
|
|
228
|
+
const canDiscover = projectId !== undefined && projectId.length > 0;
|
|
229
|
+
// Interpolated from core rather than typed into the template: this is the same wire string
|
|
230
|
+
// `bridgeWsUrl` builds, and a generator that spells it out by hand is exactly how the four call
|
|
231
|
+
// sites that constant exists to unify drifted apart in the first place.
|
|
232
|
+
const RETICLE_CLIENT_HOST_LITERAL = `ws://${RETICLE_CLIENT_HOST}:`;
|
|
233
|
+
const urlHelper = canDiscover
|
|
234
|
+
? `
|
|
235
|
+
// The live daemon serving THIS project, re-read on every \`astro dev\`. Same rule as the Vite and
|
|
236
|
+
// Next plugins: skip dead daemons, match on projectId, lowest port wins, '' when none matches.
|
|
237
|
+
function reticleUrl() {
|
|
238
|
+
const dir = process.env['RETICLE_PAIRING_TOKEN_DIR'] || join(homedir(), '.reticle');
|
|
239
|
+
let best;
|
|
240
|
+
try {
|
|
241
|
+
for (const file of readdirSync(dir)) {
|
|
242
|
+
if (!file.startsWith('daemon-') || !file.endsWith('.json')) continue;
|
|
243
|
+
let entry;
|
|
244
|
+
try { entry = JSON.parse(readFileSync(join(dir, file), 'utf8')); } catch { continue; }
|
|
245
|
+
if (entry.projectId !== '${projectId}') continue;
|
|
246
|
+
try { process.kill(entry.pid, 0); } catch { continue; }
|
|
247
|
+
if (best === undefined || entry.port < best) best = entry.port;
|
|
248
|
+
}
|
|
249
|
+
} catch { return ''; }
|
|
250
|
+
return best === undefined ? '' : '${RETICLE_CLIENT_HOST_LITERAL}' + best + '${RETICLE_WS_PATH}';
|
|
251
|
+
}
|
|
252
|
+
`
|
|
253
|
+
: '';
|
|
254
|
+
const urlDefine = canDiscover ? `\n __RETICLE_URL__: JSON.stringify(reticleUrl()),` : '';
|
|
255
|
+
const urlRead = canDiscover
|
|
256
|
+
? `\n const url = typeof __RETICLE_URL__ !== 'undefined' ? __RETICLE_URL__ : '';`
|
|
257
|
+
: '';
|
|
258
|
+
// After the baked port, so the discovered one wins: later key in an object literal.
|
|
259
|
+
const urlSpread = canDiscover ? `\n ...(url.length > 0 ? { url } : {}),` : '';
|
|
207
260
|
return `Astro renders its own HTML, so the connect goes in a page <script> and the pairing token is inlined by the config.
|
|
208
261
|
|
|
209
262
|
1. In astro.config.mjs — inline the daemon's token and raise the build target:
|
|
210
263
|
|
|
211
|
-
import { readFileSync } from 'node:fs';
|
|
264
|
+
import { readFileSync, readdirSync } from 'node:fs';
|
|
212
265
|
import { homedir } from 'node:os';
|
|
213
266
|
import { join } from 'node:path';
|
|
214
267
|
|
|
@@ -216,14 +269,14 @@ layoutPath) {
|
|
|
216
269
|
const dir = process.env['RETICLE_PAIRING_TOKEN_DIR'] || join(homedir(), '.reticle');
|
|
217
270
|
try { return readFileSync(join(dir, 'pairing-token'), 'utf8').trim(); } catch { return ''; }
|
|
218
271
|
}
|
|
219
|
-
|
|
272
|
+
${urlHelper}
|
|
220
273
|
export default defineConfig({
|
|
221
274
|
vite: {
|
|
222
275
|
// Astro's default target down-levels the modern SDK bundle and fails on a destructuring transform.
|
|
223
276
|
build: { target: 'es2022' },
|
|
224
277
|
optimizeDeps: { esbuildOptions: { target: 'es2022' } },
|
|
225
278
|
define: {
|
|
226
|
-
__RETICLE_TOKEN__: JSON.stringify(reticleToken())
|
|
279
|
+
__RETICLE_TOKEN__: JSON.stringify(reticleToken()),${urlDefine}
|
|
227
280
|
// Without this, source pointers come back as absolute paths from YOUR machine — useless in a
|
|
228
281
|
// report. Every other framework gets it from its build plugin; Astro owns its Vite instance.
|
|
229
282
|
__RETICLE_ROOT__: JSON.stringify(process.cwd()),
|
|
@@ -236,16 +289,22 @@ ${layoutHost(layoutPath)}
|
|
|
236
289
|
<script>
|
|
237
290
|
if (import.meta.env.DEV) {
|
|
238
291
|
const token = typeof __RETICLE_TOKEN__ !== 'undefined' ? __RETICLE_TOKEN__ : '';
|
|
239
|
-
const root = typeof __RETICLE_ROOT__ !== 'undefined' ? __RETICLE_ROOT__ : ''
|
|
292
|
+
const root = typeof __RETICLE_ROOT__ !== 'undefined' ? __RETICLE_ROOT__ : '';${urlRead}
|
|
240
293
|
const { reticle, install } = await import('@reticlehq/react');
|
|
241
294
|
install();
|
|
242
|
-
reticle.connect({${id}${extra}
|
|
295
|
+
reticle.connect({${id}${extra}${urlSpread}
|
|
243
296
|
...(token.length > 0 ? { token } : {}),
|
|
244
297
|
...(root.length > 0 ? { root } : {}),
|
|
245
298
|
});
|
|
246
299
|
}
|
|
247
300
|
</script>
|
|
248
301
|
|
|
302
|
+
3. In src/env.d.ts — declare the Vite define names so \`astro check\` can see them (create-astro's
|
|
303
|
+
default build runs check first, and without this it fails with Cannot find name '__RETICLE_TOKEN__'):
|
|
304
|
+
|
|
305
|
+
declare const __RETICLE_TOKEN__: string | undefined;
|
|
306
|
+
declare const __RETICLE_ROOT__: string | undefined;
|
|
307
|
+
|
|
249
308
|
Start the daemon BEFORE \`astro dev\`, so the token file exists when the config is read. Until it does the token is empty and the page reloads once the daemon is up.`;
|
|
250
309
|
}
|
|
251
310
|
/**
|
|
@@ -14,5 +14,5 @@ export declare const VitePatchKind: {
|
|
|
14
14
|
};
|
|
15
15
|
export type VitePatchKind = PatchKind;
|
|
16
16
|
type VitePatch = SourcePatch;
|
|
17
|
-
export declare function patchViteConfig(source: string, port?: number): VitePatch;
|
|
17
|
+
export declare function patchViteConfig(source: string, port?: number, captureBodies?: boolean): VitePatch;
|
|
18
18
|
export {};
|
package/dist/init/vite-config.js
CHANGED
|
@@ -8,30 +8,38 @@ import { PatchKind } from './patch-kind.js';
|
|
|
8
8
|
export const VITE_IMPORT = "import { reticle } from '@reticlehq/vite-plugin';";
|
|
9
9
|
const RETICLE_MARKER = '@reticlehq/vite-plugin';
|
|
10
10
|
/**
|
|
11
|
-
* The `reticle(...)` call — the bridge port so the injected connect targets it
|
|
11
|
+
* The `reticle(...)` call — the bridge port so the injected connect targets it.
|
|
12
12
|
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
* describes the transport and not the result
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
* the user had typed rather than the amount that came back, and every DOM-level check passed. An agent
|
|
19
|
-
* asked to verify that flow had to edit the app's own vite config mid-task to see the payload, and
|
|
20
|
-
* then tell its human to undo the edit.
|
|
13
|
+
* **`captureNetworkBodies` is OPT-IN.** It was written in by default, and the argument for that was
|
|
14
|
+
* a good one: without a body, a write that answers 2xx grades `unknown / outcome_unread`, because a
|
|
15
|
+
* 200 describes the transport and not the result. Measured on a real payments UI — a refund posted
|
|
16
|
+
* rupees into a paise field, the server answered 200 having refunded a hundredth of it, the page
|
|
17
|
+
* rendered the amount the user had typed, and every DOM-level check passed.
|
|
21
18
|
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
19
|
+
* That argument justifies the CAPABILITY. It does not justify the default, and the distinction is
|
|
20
|
+
* what #705 is about. A healthcare workspace proxying authenticated API traffic through Vite ran
|
|
21
|
+
* `init`, and on the first drive their login tokens and patient payloads were in the daemon's
|
|
22
|
+
* buffer. The old comment here conceded the exact gap — "the credential classes are redacted ... but
|
|
23
|
+
* an address or an email is not, and nothing here should decide that for someone silently" — and
|
|
24
|
+
* then decided it for them, because writing the line into their config IS deciding. `init` is run
|
|
25
|
+
* unattended by an agent; the person who knows the data is sensitive is not in the room.
|
|
26
|
+
*
|
|
27
|
+
* So the default is off and the ways in are all deliberate:
|
|
28
|
+
* - `reticle init --capture-bodies` writes the line, for someone who has decided
|
|
29
|
+
* - `VITE_RETICLE_CAPTURE_BODIES=1` turns it on for ONE dev-server run, no config edit
|
|
30
|
+
* - adding the option by hand, which is what the tools tell you to do
|
|
31
|
+
*
|
|
32
|
+
* Nothing goes quiet in exchange. Every tool that needs a body already says so when it is missing
|
|
33
|
+
* and names the option — see honesty/uncaptured-bodies.ts, honesty/verified.ts, predicate-eval.ts
|
|
34
|
+
* and reconcile-tools.ts — so the capability is discovered at the moment it is wanted, by the person
|
|
35
|
+
* who wanted it, instead of being switched on before anyone has asked.
|
|
28
36
|
*/
|
|
29
|
-
function reticlePluginCall(port) {
|
|
37
|
+
function reticlePluginCall(port, captureBodies) {
|
|
30
38
|
const options = [
|
|
31
39
|
...(port === undefined ? [] : [`port: ${String(port)}`]),
|
|
32
|
-
'captureNetworkBodies: true',
|
|
40
|
+
...(captureBodies ? ['captureNetworkBodies: true'] : []),
|
|
33
41
|
];
|
|
34
|
-
return `reticle({ ${options.join(', ')} })`;
|
|
42
|
+
return 0 === options.length ? 'reticle()' : `reticle({ ${options.join(', ')} })`;
|
|
35
43
|
}
|
|
36
44
|
/** Matches the start of a `plugins: [` array literal. */
|
|
37
45
|
const PLUGINS_ARRAY = /plugins\s*:\s*\[/;
|
|
@@ -66,35 +74,41 @@ function insertImport(source) {
|
|
|
66
74
|
* what a formatter rewrites, turning a one-line install into a diff against the user's own style. A
|
|
67
75
|
* single-line array needs the space, or the result reads `[reticle(),react()]`.
|
|
68
76
|
*/
|
|
69
|
-
function insertPlugin(source, port) {
|
|
77
|
+
function insertPlugin(source, port, captureBodies) {
|
|
70
78
|
return source.replace(PLUGINS_ARRAY, (match, _g, offset) => {
|
|
71
79
|
const next = source[offset + match.length] ?? '';
|
|
72
80
|
const separator = '' === next || /\s/.test(next) ? '' : ' ';
|
|
73
|
-
return `${match}${reticlePluginCall(port)},${separator}`;
|
|
81
|
+
return `${match}${reticlePluginCall(port, captureBodies)},${separator}`;
|
|
74
82
|
});
|
|
75
83
|
}
|
|
76
84
|
/**
|
|
77
85
|
* Add a whole `plugins: [reticle()]` key to a config object that has none, matching the layout of
|
|
78
86
|
* the object it lands in: a multi-line object gets its own indented line, a one-liner stays inline.
|
|
79
87
|
*/
|
|
80
|
-
function insertPluginsKey(source, port) {
|
|
88
|
+
function insertPluginsKey(source, port, captureBodies) {
|
|
81
89
|
return source.replace(CONFIG_OBJECT, (_match, prefix, offset) => {
|
|
82
90
|
const rest = source.slice(offset + _match.length);
|
|
83
91
|
const multiline = /^\s*\n/.test(rest);
|
|
84
92
|
const indent = /^\s*\n(\s*)\S/.exec(rest)?.[1] ?? ' ';
|
|
85
|
-
const key = `plugins: [${reticlePluginCall(port)}],`;
|
|
93
|
+
const key = `plugins: [${reticlePluginCall(port, captureBodies)}],`;
|
|
86
94
|
return multiline ? `${prefix}{\n${indent}${key}` : `${prefix}{ ${key}`;
|
|
87
95
|
});
|
|
88
96
|
}
|
|
89
|
-
export function patchViteConfig(source, port) {
|
|
97
|
+
export function patchViteConfig(source, port, captureBodies = false) {
|
|
90
98
|
if (source.includes(RETICLE_MARKER)) {
|
|
91
99
|
return { kind: VitePatchKind.ALREADY };
|
|
92
100
|
}
|
|
93
101
|
if (PLUGINS_ARRAY.test(source)) {
|
|
94
|
-
return {
|
|
102
|
+
return {
|
|
103
|
+
kind: VitePatchKind.APPLY,
|
|
104
|
+
code: insertImport(insertPlugin(source, port, captureBodies)),
|
|
105
|
+
};
|
|
95
106
|
}
|
|
96
107
|
if (CONFIG_OBJECT.test(source)) {
|
|
97
|
-
return {
|
|
108
|
+
return {
|
|
109
|
+
kind: VitePatchKind.APPLY,
|
|
110
|
+
code: insertImport(insertPluginsKey(source, port, captureBodies)),
|
|
111
|
+
};
|
|
98
112
|
}
|
|
99
113
|
return { kind: VitePatchKind.MANUAL, reason: NO_PLUGINS_REASON };
|
|
100
114
|
}
|
|
@@ -1,16 +1,14 @@
|
|
|
1
|
+
import type { InitIo } from './run.js';
|
|
1
2
|
/**
|
|
2
|
-
*
|
|
3
|
+
* The file names that say what a directory IS, shared by everything that has to ask.
|
|
3
4
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* against the root, and it reported ✓ for writing `app/reticle-dev.tsx` into a directory Next never
|
|
7
|
-
* compiles. A ⚠ tells a human to act; a ✓ tells them it is handled.
|
|
8
|
-
*
|
|
9
|
-
* A workspace DECLARES its packages, so that declaration is used first and directory names are not
|
|
10
|
-
* guessed at all. Where nothing is declared, every top-level directory is a better candidate than two
|
|
11
|
-
* hardcoded ones — filtered by the usual non-source suspects, and still subject to the `looksLikeApp`
|
|
12
|
-
* check that follows, so a wrong guess here costs a `package.json` read.
|
|
5
|
+
* They lived in run.ts and are read from here now because `findWorkspaceApps` moved and needs them —
|
|
6
|
+
* one definition, imported in both directions of the question ("is this an app?" and "which app?").
|
|
13
7
|
*/
|
|
8
|
+
export declare const PACKAGE_JSON = "package.json";
|
|
9
|
+
export declare const PNPM_WORKSPACE = "pnpm-workspace.yaml";
|
|
10
|
+
export declare const VITE_CONFIG_CANDIDATES: string[];
|
|
11
|
+
export declare const NEXT_CONFIG_CANDIDATES: string[];
|
|
14
12
|
interface WorkspaceSources {
|
|
15
13
|
/** Raw contents of pnpm-workspace.yaml, when present. */
|
|
16
14
|
pnpmWorkspace?: string;
|
|
@@ -20,4 +18,13 @@ interface WorkspaceSources {
|
|
|
20
18
|
topLevelDirs?: readonly string[];
|
|
21
19
|
}
|
|
22
20
|
export declare function workspaceParents(sources: WorkspaceSources): string[];
|
|
21
|
+
/**
|
|
22
|
+
* App directories under a workspace root.
|
|
23
|
+
*
|
|
24
|
+
* Running `reticle init` at the repo root is what people actually do, and in a monorepo the app is a
|
|
25
|
+
* directory down — so init detected "no framework", printed a wall of manual HTML instructions, and
|
|
26
|
+
* would have installed the SDK into the ROOT package.json. It already walks UP for the lockfile, so
|
|
27
|
+
* it knows it is in a workspace; this is the matching walk DOWN.
|
|
28
|
+
*/
|
|
29
|
+
export declare function findWorkspaceApps(io: Pick<InitIo, 'exists' | 'readFile' | 'listDirs'>): string[];
|
|
23
30
|
export {};
|
|
@@ -1,3 +1,24 @@
|
|
|
1
|
+
import { DEV_SCRIPT_NAMES } from './dev-script.js';
|
|
2
|
+
/**
|
|
3
|
+
* The file names that say what a directory IS, shared by everything that has to ask.
|
|
4
|
+
*
|
|
5
|
+
* They lived in run.ts and are read from here now because `findWorkspaceApps` moved and needs them —
|
|
6
|
+
* one definition, imported in both directions of the question ("is this an app?" and "which app?").
|
|
7
|
+
*/
|
|
8
|
+
export const PACKAGE_JSON = 'package.json';
|
|
9
|
+
export const PNPM_WORKSPACE = 'pnpm-workspace.yaml';
|
|
10
|
+
export const VITE_CONFIG_CANDIDATES = [
|
|
11
|
+
'vite.config.ts',
|
|
12
|
+
'vite.config.js',
|
|
13
|
+
'vite.config.mjs',
|
|
14
|
+
'vite.config.mts',
|
|
15
|
+
];
|
|
16
|
+
export const NEXT_CONFIG_CANDIDATES = [
|
|
17
|
+
'next.config.mjs',
|
|
18
|
+
'next.config.js',
|
|
19
|
+
'next.config.ts',
|
|
20
|
+
'next.config.cjs',
|
|
21
|
+
];
|
|
1
22
|
/**
|
|
2
23
|
* Which directories to look in for the app, when `reticle init` runs at a monorepo root.
|
|
3
24
|
*
|
|
@@ -66,3 +87,92 @@ export function workspaceParents(sources) {
|
|
|
66
87
|
: (sources.topLevelDirs ?? []).filter((d) => !d.startsWith('.') && !NEVER_A_PACKAGE.has(d));
|
|
67
88
|
return [...new Set(candidates)];
|
|
68
89
|
}
|
|
90
|
+
/**
|
|
91
|
+
* Which directories under this workspace are runnable apps.
|
|
92
|
+
*
|
|
93
|
+
* Moved here from run.ts, which was over the 1000-line cap and had carried a note saying it was at
|
|
94
|
+
* its cohesion limit. `library-path-boundary.test.ts` had already written down that this function
|
|
95
|
+
* "squats in init/ for historical reasons" — it is a general-purpose question about a repository's
|
|
96
|
+
* shape, next to `workspaceParents`, which answers the other half of it.
|
|
97
|
+
*/
|
|
98
|
+
/** Deps that mark a directory as a runnable web app even when it has no bundler config file. */
|
|
99
|
+
const APP_DEPS = ['next', 'vite'];
|
|
100
|
+
function hasDevScript(pkgRaw) {
|
|
101
|
+
try {
|
|
102
|
+
const parsed = JSON.parse(pkgRaw);
|
|
103
|
+
const scripts = 'object' === typeof parsed && parsed !== null
|
|
104
|
+
? parsed.scripts
|
|
105
|
+
: undefined;
|
|
106
|
+
if ('object' !== typeof scripts || null === scripts)
|
|
107
|
+
return false;
|
|
108
|
+
const named = scripts;
|
|
109
|
+
return DEV_SCRIPT_NAMES.some((n) => 'string' === typeof named[n] && '' !== named[n]);
|
|
110
|
+
}
|
|
111
|
+
catch {
|
|
112
|
+
// A manifest that will not parse says nothing either way, and this is a filter, not a verdict.
|
|
113
|
+
return false;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
function looksLikeApp(dir, io) {
|
|
117
|
+
const pkgRaw = io.readFile(`${dir}/${PACKAGE_JSON}`);
|
|
118
|
+
if (null === pkgRaw)
|
|
119
|
+
return false;
|
|
120
|
+
const configs = [...VITE_CONFIG_CANDIDATES, ...NEXT_CONFIG_CANDIDATES];
|
|
121
|
+
if (configs.some((c) => io.exists(`${dir}/${c}`)))
|
|
122
|
+
return true;
|
|
123
|
+
// `next.config` is optional in Next, so the dependency list is the other half of the signal.
|
|
124
|
+
if (APP_DEPS.some((d) => pkgRaw.includes(`"${d}"`)))
|
|
125
|
+
return true;
|
|
126
|
+
// And the honest third: an app somebody can SERVE. Asking only for a bundler missed every app
|
|
127
|
+
// built on anything else — Remix, Astro, a plain node server — and in a monorepo missing it means
|
|
128
|
+
// init never redirects, wires the ROOT, and reports ✓ for files nothing compiles.
|
|
129
|
+
//
|
|
130
|
+
// A monorepo root has no dev script by design, and a package that can only be BUILT is not the app
|
|
131
|
+
// somebody is working in, so this stays a filter rather than matching every directory.
|
|
132
|
+
return hasDevScript(pkgRaw);
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* App directories under a workspace root.
|
|
136
|
+
*
|
|
137
|
+
* Running `reticle init` at the repo root is what people actually do, and in a monorepo the app is a
|
|
138
|
+
* directory down — so init detected "no framework", printed a wall of manual HTML instructions, and
|
|
139
|
+
* would have installed the SDK into the ROOT package.json. It already walks UP for the lockfile, so
|
|
140
|
+
* it knows it is in a workspace; this is the matching walk DOWN.
|
|
141
|
+
*/
|
|
142
|
+
export function findWorkspaceApps(io) {
|
|
143
|
+
const found = [];
|
|
144
|
+
// A workspace DECLARES its packages; `['apps','packages']` was a guess that missed a real repo
|
|
145
|
+
// with three Next apps at web/, admin/ and space/ — and missing them meant init ran against the
|
|
146
|
+
// root and reported ✓ for a file Next never compiles. See workspace-apps.
|
|
147
|
+
const pkgRaw = io.readFile(PACKAGE_JSON);
|
|
148
|
+
let pkgWorkspaces;
|
|
149
|
+
try {
|
|
150
|
+
const parsed = null === pkgRaw ? undefined : JSON.parse(pkgRaw);
|
|
151
|
+
pkgWorkspaces =
|
|
152
|
+
'object' === typeof parsed && parsed !== null
|
|
153
|
+
? parsed.workspaces
|
|
154
|
+
: undefined;
|
|
155
|
+
}
|
|
156
|
+
catch {
|
|
157
|
+
pkgWorkspaces = undefined;
|
|
158
|
+
}
|
|
159
|
+
const parents = workspaceParents({
|
|
160
|
+
...(null === io.readFile(PNPM_WORKSPACE)
|
|
161
|
+
? {}
|
|
162
|
+
: { pnpmWorkspace: io.readFile(PNPM_WORKSPACE) ?? '' }),
|
|
163
|
+
...(pkgWorkspaces === undefined ? {} : { pkgWorkspaces }),
|
|
164
|
+
topLevelDirs: io.listDirs('.'),
|
|
165
|
+
});
|
|
166
|
+
// A declared parent can itself BE the app (`workspaces: ["web"]`), so check both the directory and
|
|
167
|
+
// its children rather than assuming one level of nesting.
|
|
168
|
+
for (const parent of parents) {
|
|
169
|
+
if (looksLikeApp(parent, io))
|
|
170
|
+
found.push(parent);
|
|
171
|
+
for (const name of io.listDirs(parent)) {
|
|
172
|
+
const dir = `${parent}/${name}`;
|
|
173
|
+
if (looksLikeApp(dir, io))
|
|
174
|
+
found.push(dir);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
return [...new Set(found)];
|
|
178
|
+
}
|
|
@@ -2,6 +2,7 @@ import { z } from 'zod';
|
|
|
2
2
|
import { CDP_NO_PROVIDER_REASON, CDP_NO_PROVIDER_RECOMMENDATION } from '@reticlehq/core';
|
|
3
3
|
import { ReticleTool } from '../tools/tool-names.js';
|
|
4
4
|
import { sessionIdShape } from '../tools/tool-kit.js';
|
|
5
|
+
import { delayMsSchema, httpStatusSchema } from '../tools/numeric-bounds.js';
|
|
5
6
|
import { asString } from '../tools/tools-helpers.js';
|
|
6
7
|
function mockProvider(deps) {
|
|
7
8
|
const p = deps.realInput;
|
|
@@ -13,14 +14,10 @@ const ruleShape = z.object({
|
|
|
13
14
|
.min(1)
|
|
14
15
|
.describe('Substring the request URL must contain, e.g. "/api/pay".'),
|
|
15
16
|
method: z.string().optional().describe('Optional method filter (GET/POST/…), case-insensitive.'),
|
|
16
|
-
status:
|
|
17
|
+
status: httpStatusSchema.optional().describe('Fulfill with this HTTP status (default 200).'),
|
|
17
18
|
body: z.string().optional().describe('Response body to fulfill with.'),
|
|
18
19
|
contentType: z.string().optional().describe('Response content type (default application/json).'),
|
|
19
|
-
delayMs:
|
|
20
|
-
.number()
|
|
21
|
-
.int()
|
|
22
|
-
.optional()
|
|
23
|
-
.describe('Delay (ms) before fulfilling — simulate a slow API.'),
|
|
20
|
+
delayMs: delayMsSchema.optional().describe('Delay (ms) before fulfilling — simulate a slow API.'),
|
|
24
21
|
abort: z
|
|
25
22
|
.boolean()
|
|
26
23
|
.optional()
|
|
@@ -171,6 +171,8 @@ export interface LaunchedProviderOptions {
|
|
|
171
171
|
*/
|
|
172
172
|
onNetworkDetail?: (detail: NetworkDetail) => void;
|
|
173
173
|
}
|
|
174
|
+
/** The only place the dynamic value import of Playwright lives for the launched (drive) path. */
|
|
175
|
+
export declare const launchedChromium: LaunchFn;
|
|
174
176
|
/**
|
|
175
177
|
* Launches and OWNS a Playwright Chromium, navigates it to `driveUrl`, then drives native
|
|
176
178
|
* input on that page. Headless-capable so @reticlehq/test / CI can run hover/drag unattended.
|
package/dist/input/real-input.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { chromiumLaunchOptions } from '../chromium-launch-options.js';
|
|
1
2
|
import { gotoOptions } from '../pool/playwright-launcher.js';
|
|
2
3
|
import { BrowserLaunchKind } from '@reticlehq/core';
|
|
3
4
|
import { getSessionMetrics } from '../telemetry/session-metrics.js';
|
|
@@ -220,7 +221,7 @@ export class CdpRealInputProvider {
|
|
|
220
221
|
}
|
|
221
222
|
const INJECT_CONNECT_WAIT_MS = 8_000;
|
|
222
223
|
/** The only place the dynamic value import of Playwright lives for the launched (drive) path. */
|
|
223
|
-
const launchedChromium = async (headless) => {
|
|
224
|
+
export const launchedChromium = async (headless) => {
|
|
224
225
|
let mod;
|
|
225
226
|
try {
|
|
226
227
|
mod = await import('playwright');
|
|
@@ -230,7 +231,7 @@ const launchedChromium = async (headless) => {
|
|
|
230
231
|
}
|
|
231
232
|
const settle = getSessionMetrics().recordConnectAttempt(BrowserLaunchKind.LAUNCHED);
|
|
232
233
|
try {
|
|
233
|
-
const browser = await mod.chromium.launch(
|
|
234
|
+
const browser = await mod.chromium.launch(chromiumLaunchOptions(headless));
|
|
234
235
|
settle();
|
|
235
236
|
return browser;
|
|
236
237
|
}
|
|
@@ -301,8 +302,28 @@ export class LaunchedRealInputProvider {
|
|
|
301
302
|
// No SDK on the page (or it connected already) — the no-session guard in verify reports it.
|
|
302
303
|
}
|
|
303
304
|
}
|
|
304
|
-
|
|
305
|
+
/**
|
|
306
|
+
* The page we own, or undefined once it is gone.
|
|
307
|
+
*
|
|
308
|
+
* The handle is cached for the life of the provider and Playwright keeps answering `url()` after
|
|
309
|
+
* the page has closed, so a closed window read as AVAILABLE and every method below threw
|
|
310
|
+
* "Target page, context or browser has been closed" — the raw Playwright message, surfaced to the
|
|
311
|
+
* agent as a tool error, on every call for the rest of the run. A dead page is the same fact as no
|
|
312
|
+
* page, and every caller already handles that. Only an EXPLICIT `true` drops it, matching
|
|
313
|
+
* `CdpRealInputProvider`'s `isConnected` check: a test fake without the method is assumed live.
|
|
314
|
+
*/
|
|
315
|
+
#livePage() {
|
|
305
316
|
const page = this.#page;
|
|
317
|
+
if (page === undefined)
|
|
318
|
+
return undefined;
|
|
319
|
+
if (true === page.isClosed?.()) {
|
|
320
|
+
this.#page = undefined; // never ask a corpse twice
|
|
321
|
+
return undefined;
|
|
322
|
+
}
|
|
323
|
+
return page;
|
|
324
|
+
}
|
|
325
|
+
isAvailableFor(sessionUrl) {
|
|
326
|
+
const page = this.#livePage();
|
|
306
327
|
if (page === undefined)
|
|
307
328
|
return Promise.resolve(false);
|
|
308
329
|
if (page.url() === sessionUrl)
|
|
@@ -310,14 +331,14 @@ export class LaunchedRealInputProvider {
|
|
|
310
331
|
return Promise.resolve(stripVolatile(page.url()) === stripVolatile(sessionUrl));
|
|
311
332
|
}
|
|
312
333
|
perform(_sessionUrl, action, box, args) {
|
|
313
|
-
const page = this.#
|
|
334
|
+
const page = this.#livePage();
|
|
314
335
|
if (page === undefined)
|
|
315
336
|
return Promise.resolve({ performed: false, center: boxCenter(box) });
|
|
316
337
|
return performGesture(page, action, box, args, this.#sleep);
|
|
317
338
|
}
|
|
318
339
|
/** PNG of the owned page, or undefined before navigate / after dispose. */
|
|
319
340
|
screenshot(_sessionUrl, opts) {
|
|
320
|
-
const page = this.#
|
|
341
|
+
const page = this.#livePage();
|
|
321
342
|
if (page === undefined)
|
|
322
343
|
return Promise.resolve(undefined);
|
|
323
344
|
return capturePage(page, opts);
|
|
@@ -331,7 +352,7 @@ export class LaunchedRealInputProvider {
|
|
|
331
352
|
* screenshots the whole time; only these two methods were missing.
|
|
332
353
|
*/
|
|
333
354
|
async setViewport(_sessionUrl, size) {
|
|
334
|
-
const page = this.#
|
|
355
|
+
const page = this.#livePage();
|
|
335
356
|
if (page === undefined)
|
|
336
357
|
return false;
|
|
337
358
|
await page.setViewportSize({ width: size.width, height: size.height });
|
|
@@ -339,7 +360,7 @@ export class LaunchedRealInputProvider {
|
|
|
339
360
|
}
|
|
340
361
|
/** Apply network-mock rules to the owned page; false before navigate / after dispose. */
|
|
341
362
|
async setMocks(_sessionUrl, rules) {
|
|
342
|
-
const page = this.#
|
|
363
|
+
const page = this.#livePage();
|
|
343
364
|
if (page === undefined)
|
|
344
365
|
return false;
|
|
345
366
|
await installNetworkMocks(page, rules);
|
|
@@ -36,10 +36,13 @@ export interface ScrollFindResult {
|
|
|
36
36
|
note?: string;
|
|
37
37
|
}
|
|
38
38
|
/**
|
|
39
|
-
* Reveal an element that a windowed/virtualized list has not mounted yet. Queries
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
39
|
+
* Reveal an element that a windowed/virtualized list has not mounted yet. Queries once (it may
|
|
40
|
+
* already be visible), optionally jumps straight to a bisection estimate, then walks the container
|
|
41
|
+
* a viewport at a time re-querying after each step. Downward first; when the bottom is reached the
|
|
42
|
+
* walk TURNS AROUND and continues upward, because a list that is already scrolled to its end keeps
|
|
43
|
+
* its earlier rows mounted above the viewport and a downward-only search answered "exhausted" on
|
|
44
|
+
* its first step (#505). `exhausted` therefore means BOTH directions are spent, not "the bottom is
|
|
45
|
+
* here". Pure orchestration over the session command seam — fully unit-testable with a fake.
|
|
43
46
|
*/
|
|
44
47
|
export declare function scrollToFind(session: ScrollFindSession, q: ScrollFindQuery, opts?: {
|
|
45
48
|
maxScrolls?: number;
|