@reticlehq/server 2.13.1 → 2.14.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 +8 -18
- package/bin/reticle.js +3 -0
- package/dist/bridge/auth-failure-reason.js +12 -1
- package/dist/bridge/bridge-security.d.ts +8 -0
- package/dist/bridge/bridge-security.js +6 -1
- package/dist/bridge/bridge.d.ts +3 -0
- package/dist/bridge/bridge.js +23 -1
- package/dist/bridge/bridge.test-harness.d.ts +10 -1
- package/dist/bridge/bridge.test-harness.js +7 -1
- package/dist/bridge/pairing-token.d.ts +17 -0
- package/dist/bridge/pairing-token.js +26 -0
- package/dist/bridge/token-auth.d.ts +7 -0
- package/dist/bridge/token-auth.js +7 -1
- package/dist/capsule/capsule-store.d.ts +4 -4
- package/dist/capsule/capsule.d.ts +1 -1
- package/dist/capsule/capsule.js +3 -3
- package/dist/capsule/causal-summary.d.ts +21 -1
- package/dist/capsule/causal-summary.js +8 -6
- package/dist/capsule/divergence.d.ts +1 -1
- package/dist/capsule/divergence.js +26 -10
- package/dist/chromium-launch-options.d.ts +2 -1
- package/dist/cli/adhoc-verdict.d.ts +58 -0
- package/dist/cli/adhoc-verdict.js +115 -0
- package/dist/cli/chromium-hint.d.ts +18 -4
- package/dist/cli/chromium-hint.js +54 -6
- package/dist/cli/cli-doctor.js +1 -2
- package/dist/cli/cli-flow-commands.d.ts +16 -2
- package/dist/cli/cli-flow-commands.js +28 -9
- package/dist/cli/cli-parse-feedback.js +1 -1
- package/dist/cli/cli-parse.d.ts +2 -1
- package/dist/cli/cli-parse.js +38 -0
- package/dist/cli/cli-port.d.ts +5 -13
- package/dist/cli/cli-port.js +5 -38
- package/dist/cli/cli-update-commands.js +4 -4
- package/dist/cli/cli-verify.d.ts +24 -7
- package/dist/cli/cli-verify.js +87 -13
- package/dist/cli/cloud-keystore.d.ts +2 -1
- package/dist/cli/cloud-login.d.ts +2 -1
- package/dist/cli/cloud-session.d.ts +2 -1
- package/dist/cli/cloud-session.js +1 -1
- package/dist/cli/daemon-start-options.d.ts +2 -1
- package/dist/cli/device-flow.d.ts +2 -2
- package/dist/cli/doctor-daemon-line.d.ts +2 -1
- package/dist/cli/doctor-project-line.d.ts +2 -1
- package/dist/cli/doctor-rows.d.ts +2 -1
- package/dist/cli/drive-attach.d.ts +4 -3
- package/dist/cli/gate-hook-message.d.ts +2 -1
- package/dist/cli/status-next-action.js +10 -11
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +21 -9
- package/dist/cloud/account-state.d.ts +20 -0
- package/dist/cloud/account-state.js +65 -0
- package/dist/cloud/cloud-sync.d.ts +46 -3
- package/dist/cloud/cloud-sync.js +116 -0
- package/dist/cloud/sync-cycle.d.ts +5 -4
- package/dist/cloud/sync-cycle.js +1 -1
- package/dist/cloud/sync-daemon.d.ts +3 -19
- package/dist/cloud/sync-daemon.js +2 -2
- package/dist/crawl/crawl-tools.js +1 -1
- package/dist/crawl/crawl.d.ts +5 -5
- package/dist/crawl/crawl.js +138 -4
- package/dist/daemon/daemon-resilience.d.ts +3 -2
- package/dist/daemon/daemon-resilience.js +43 -4
- package/dist/daemon/daemon-resolve.d.ts +0 -9
- package/dist/daemon/daemon-resolve.js +2 -2
- package/dist/daemon/dev-servers.d.ts +1 -1
- package/dist/daemon/dev-servers.js +1 -1
- package/dist/daemon/loopback-alias.d.ts +2 -1
- package/dist/daemon/startup-failure.d.ts +11 -0
- package/dist/daemon/startup-failure.js +46 -0
- package/dist/events/contradictions.d.ts +10 -16
- package/dist/events/contradictions.js +149 -17
- package/dist/events/declared.d.ts +13 -1
- package/dist/events/declared.js +59 -3
- package/dist/events/echo-mismatch.js +75 -6
- package/dist/events/lineage.d.ts +52 -0
- package/dist/events/lineage.js +122 -0
- package/dist/events/net-evidence.d.ts +21 -0
- package/dist/events/net-evidence.js +81 -0
- package/dist/events/predicate-console.d.ts +13 -0
- package/dist/events/predicate-console.js +138 -0
- package/dist/events/predicate-element.d.ts +13 -0
- package/dist/events/predicate-element.js +214 -0
- package/dist/events/predicate-eval.d.ts +15 -3
- package/dist/events/predicate-eval.js +128 -110
- package/dist/events/predicate-parse.js +34 -1
- package/dist/events/predicate-request-body.d.ts +50 -0
- package/dist/events/predicate-request-body.js +120 -0
- package/dist/events/predicate-route.d.ts +21 -1
- package/dist/events/predicate-route.js +149 -21
- package/dist/events/predicate-schema.d.ts +8 -1
- package/dist/events/predicate-schema.js +34 -0
- package/dist/events/predicate.d.ts +2 -0
- package/dist/events/predicate.js +52 -159
- package/dist/events/split-text-miss.d.ts +6 -4
- package/dist/events/split-text-miss.js +12 -5
- package/dist/flows/affected-tools.js +22 -9
- package/dist/flows/annotate.d.ts +2 -1
- package/dist/flows/annotate.js +19 -1
- package/dist/flows/coverage.d.ts +2 -2
- package/dist/flows/flake.d.ts +3 -3
- package/dist/flows/flow-expect-grammar.d.ts +33 -0
- package/dist/flows/flow-expect-grammar.js +155 -0
- package/dist/flows/flow-replay-run.d.ts +1 -1
- package/dist/flows/flow-replay-run.js +28 -15
- package/dist/flows/flow-replay.d.ts +10 -0
- package/dist/flows/flow-replay.js +57 -22
- package/dist/flows/flow-secret-field.d.ts +14 -0
- package/dist/flows/flow-secret-field.js +22 -0
- package/dist/flows/flow-step-runners.d.ts +1 -0
- package/dist/flows/flow-step-runners.js +91 -34
- package/dist/flows/flow-success.js +22 -0
- package/dist/flows/flow-tools.js +27 -8
- package/dist/flows/flow-upload-resolve.d.ts +23 -0
- package/dist/flows/flow-upload-resolve.js +46 -0
- package/dist/flows/flows.d.ts +15 -0
- package/dist/flows/flows.js +17 -14
- package/dist/flows/git-changed.d.ts +23 -4
- package/dist/flows/git-changed.js +32 -6
- package/dist/flows/heal-run.js +2 -2
- package/dist/flows/predicate-to-expect.d.ts +3 -2
- package/dist/flows/predicate-to-expect.js +11 -5
- package/dist/flows/recording-backtrack.d.ts +24 -0
- package/dist/flows/recording-backtrack.js +73 -0
- package/dist/flows/recordings.d.ts +6 -0
- package/dist/flows/replay-halt.d.ts +26 -0
- package/dist/flows/replay-halt.js +30 -0
- package/dist/flows/replay.d.ts +0 -8
- package/dist/flows/replay.js +15 -3
- package/dist/flows/suite-flakes.d.ts +2 -1
- package/dist/flows/verify-change-tools.js +16 -4
- package/dist/honesty/already-true.d.ts +14 -0
- package/dist/honesty/already-true.js +47 -4
- package/dist/honesty/blind-spots.d.ts +3 -1
- package/dist/honesty/blind-spots.js +24 -1
- package/dist/honesty/body-capture-remedy.d.ts +42 -0
- package/dist/honesty/body-capture-remedy.js +95 -0
- package/dist/honesty/feature-capture.d.ts +3 -2
- package/dist/honesty/feature-capture.js +1 -1
- package/dist/honesty/gap-ledger.d.ts +1 -1
- package/dist/honesty/gap-ledger.js +1 -1
- package/dist/honesty/instrumentation-gaps.d.ts +8 -1
- package/dist/honesty/instrumentation-gaps.js +12 -2
- package/dist/honesty/observability.d.ts +4 -3
- package/dist/honesty/tool-hit-rate.d.ts +3 -2
- package/dist/honesty/uncaptured-bodies.d.ts +3 -1
- package/dist/honesty/uncaptured-bodies.js +6 -2
- package/dist/honesty/unsettled.d.ts +9 -0
- package/dist/honesty/unsettled.js +45 -0
- package/dist/honesty/verified.d.ts +32 -1
- package/dist/honesty/verified.js +37 -10
- package/dist/impact/impact-store.d.ts +5 -14
- package/dist/impact/impact-store.js +49 -6
- package/dist/index.js +1 -1
- package/dist/input/network-detail.d.ts +26 -1
- package/dist/input/network-detail.js +44 -12
- package/dist/input/network-mock-tools.js +24 -17
- package/dist/input/real-input.js +1 -1
- package/dist/input/viewport-tools.js +25 -13
- package/dist/intent/inline-intent.d.ts +0 -10
- package/dist/intent/inline-intent.js +1 -1
- package/dist/intent/intent-shard-store.d.ts +3 -2
- package/dist/intent/intent-shard-store.js +1 -1
- package/dist/intent/intent-shard.d.ts +14 -14
- package/dist/intent/intent-shard.js +4 -4
- package/dist/intent/intent-store.d.ts +1 -1
- package/dist/intent/intent-store.js +1 -1
- package/dist/intent/intent-subject.d.ts +2 -1
- package/dist/intent/open-intents.d.ts +3 -2
- package/dist/license/license.d.ts +4 -4
- package/dist/license/license.js +1 -1
- package/dist/mcp/attach-memory.d.ts +2 -1
- package/dist/mcp/client-identity.d.ts +2 -1
- package/dist/mcp/mcp-outage.d.ts +1 -1
- package/dist/mcp/mcp-outage.js +1 -1
- package/dist/mcp/mcp-proxy.d.ts +3 -1
- package/dist/mcp/mcp-proxy.js +32 -7
- package/dist/mcp/mcp.js +3 -1
- package/dist/mcp/proxy-handshake.d.ts +2 -1
- package/dist/mcp/proxy-idle-exit.d.ts +45 -0
- package/dist/mcp/proxy-idle-exit.js +94 -0
- package/dist/mcp/server-instructions.d.ts +2 -1
- package/dist/memory/project-memory.d.ts +2 -3
- package/dist/memory/project-memory.js +1 -1
- package/dist/oracles/propose-consequences.js +5 -5
- package/dist/oracles/self-instrument.d.ts +2 -2
- package/dist/oracles/self-instrument.js +1 -1
- package/dist/platform.d.ts +3 -5
- package/dist/platform.js +3 -5
- package/dist/pool/browser-pool.d.ts +92 -0
- package/dist/pool/browser-pool.js +119 -5
- package/dist/pool/playwright-launcher.js +29 -2
- package/dist/pool/storage-seed.d.ts +23 -0
- package/dist/pool/storage-seed.js +198 -0
- package/dist/project/artifact-root.d.ts +2 -1
- package/dist/project/memory-fs.d.ts +2 -1
- package/dist/project/reticle-dir.js +1 -1
- package/dist/project/session-root.d.ts +8 -0
- package/dist/project/session-root.js +9 -2
- package/dist/runs/reticle-runner.d.ts +14 -1
- package/dist/runs/reticle-runner.js +39 -2
- package/dist/session/attachment-history.d.ts +2 -1
- package/dist/session/fake-session.d.ts +37 -0
- package/dist/session/fake-session.js +81 -0
- package/dist/session/lease-visibility.d.ts +2 -1
- package/dist/session/live-control-tools.js +6 -0
- package/dist/session/no-session-diagnosis.d.ts +17 -1
- package/dist/session/no-session-diagnosis.js +32 -6
- package/dist/session/no-session-next-action.d.ts +14 -0
- package/dist/session/no-session-next-action.js +18 -0
- package/dist/session/no-session-watch.js +46 -3
- package/dist/session/registered-projects.d.ts +54 -0
- package/dist/session/registered-projects.js +73 -0
- package/dist/session/review-store.d.ts +2 -1
- package/dist/session/session-health.d.ts +62 -1
- package/dist/session/session-health.js +82 -2
- package/dist/session/session-manager.d.ts +11 -1
- package/dist/session/session-manager.js +18 -3
- package/dist/session/session-replaced.d.ts +24 -0
- package/dist/session/session-replaced.js +29 -0
- package/dist/session/session-successor.js +20 -4
- package/dist/session/session.d.ts +13 -5
- package/dist/session/session.js +31 -23
- package/dist/setup/agent-configs.d.ts +3 -2
- package/dist/setup/agent-writer.d.ts +3 -2
- package/dist/setup/approval-migration.d.ts +2 -1
- package/dist/setup/approval-migration.js +1 -1
- package/dist/setup/auto-approve.d.ts +11 -19
- package/dist/setup/auto-approve.js +15 -12
- package/dist/{init → setup}/confirm.js +1 -1
- package/dist/setup/desktop-shape.d.ts +3 -2
- package/dist/setup/drive-agent.d.ts +2 -3
- package/dist/setup/drive-agent.js +1 -1
- package/dist/setup/drive-plan.d.ts +3 -2
- package/dist/setup/ensure-daemon.d.ts +2 -1
- package/dist/setup/existing-app.d.ts +12 -0
- package/dist/setup/existing-app.js +13 -0
- package/dist/setup/init-host.d.ts +11 -0
- package/dist/setup/init-host.js +26 -0
- package/dist/setup/init-runtime.d.ts +4 -10
- package/dist/setup/init-runtime.js +23 -16
- package/dist/setup/license-key.d.ts +2 -1
- package/dist/setup/listeners.d.ts +2 -1
- package/dist/setup/loopback-probe-urls.d.ts +18 -0
- package/dist/setup/loopback-probe-urls.js +52 -0
- package/dist/setup/node-effects.d.ts +3 -0
- package/dist/setup/node-effects.js +26 -11
- package/dist/setup/page-probe.d.ts +5 -0
- package/dist/setup/relaunch.d.ts +2 -1
- package/dist/setup/run-setup.d.ts +5 -1
- package/dist/setup/run-setup.js +141 -50
- package/dist/setup/setup-command.d.ts +3 -2
- package/dist/setup/setup-command.js +8 -0
- package/dist/setup/setup-options.d.ts +5 -3
- package/dist/setup/setup-options.js +3 -2
- package/dist/setup/wait-progress.d.ts +28 -0
- package/dist/setup/wait-progress.js +43 -0
- package/dist/telemetry/app-instrumented.d.ts +2 -1
- package/dist/telemetry/app-instrumented.js +1 -1
- package/dist/telemetry/automation-hint.d.ts +1 -1
- package/dist/telemetry/automation-hint.js +1 -1
- package/dist/telemetry/cli-telemetry.js +1 -1
- package/dist/telemetry/connect-failure.d.ts +1 -1
- package/dist/telemetry/connect-failure.js +1 -1
- package/dist/telemetry/crash-cause.d.ts +3 -2
- package/dist/telemetry/crash-cause.js +1 -1
- package/dist/telemetry/daemon-telemetry.d.ts +3 -2
- package/dist/telemetry/daemon-telemetry.js +1 -1
- package/dist/telemetry/error-class.d.ts +3 -2
- package/dist/telemetry/error-class.js +1 -1
- package/dist/telemetry/feedback-cli.js +1 -1
- package/dist/telemetry/feedback-context.d.ts +3 -2
- package/dist/telemetry/feedback-context.js +5 -4
- package/dist/telemetry/feedback-local.d.ts +3 -2
- package/dist/telemetry/feedback.d.ts +4 -3
- package/dist/telemetry/feedback.js +1 -1
- package/dist/telemetry/git-facts.d.ts +2 -2
- package/dist/telemetry/git-facts.js +1 -1
- package/dist/telemetry/identify.d.ts +1 -1
- package/dist/telemetry/identify.js +1 -1
- package/dist/telemetry/init-telemetry.d.ts +2 -14
- package/dist/telemetry/init-telemetry.js +4 -13
- package/dist/telemetry/install-source.d.ts +7 -13
- package/dist/telemetry/install-source.js +7 -29
- package/dist/telemetry/license-activation.d.ts +3 -2
- package/dist/telemetry/license-activation.js +1 -1
- package/dist/telemetry/machine-snapshot.d.ts +1 -1
- package/dist/telemetry/mcp-connection.js +1 -1
- package/dist/telemetry/project-profile.d.ts +0 -14
- package/dist/telemetry/project-profile.js +1 -1
- package/dist/telemetry/proxy-telemetry.js +1 -1
- package/dist/telemetry/session-metrics.d.ts +1 -1
- package/dist/telemetry/session-metrics.js +1 -1
- package/dist/telemetry/telemetry.d.ts +1 -17
- package/dist/telemetry/telemetry.js +4 -4
- package/dist/telemetry/tool-refused.d.ts +1 -1
- package/dist/telemetry/tool-refused.js +1 -1
- package/dist/tools/act-observation.d.ts +3 -2
- package/dist/tools/act-preflight.js +8 -3
- package/dist/tools/act-target.d.ts +4 -0
- package/dist/tools/act-target.js +14 -5
- package/dist/tools/act-tools.d.ts +0 -2
- package/dist/tools/act-tools.js +45 -15
- package/dist/tools/assert-source.d.ts +30 -0
- package/dist/tools/assert-source.js +21 -0
- package/dist/tools/assert-verdict.d.ts +1 -1
- package/dist/tools/assert-verdict.js +14 -4
- package/dist/tools/browser-tools.js +28 -8
- package/dist/tools/complete-snapshot.d.ts +3 -2
- package/dist/tools/dynamic-tools.js +8 -0
- package/dist/tools/error-recovery.d.ts +10 -0
- package/dist/tools/error-recovery.js +23 -0
- package/dist/tools/feedback-tools.js +1 -1
- package/dist/tools/invoke-tool.js +2 -0
- package/dist/tools/lease-tools.d.ts +48 -20
- package/dist/tools/lease-tools.js +311 -76
- package/dist/tools/lineage-tools.d.ts +14 -0
- package/dist/tools/lineage-tools.js +64 -0
- package/dist/tools/merge-tools.js +1 -3
- package/dist/tools/navigate-arrival.d.ts +45 -1
- package/dist/tools/navigate-arrival.js +39 -6
- package/dist/tools/navigate-result.d.ts +8 -1
- package/dist/tools/navigate-result.js +14 -4
- package/dist/tools/numeric-bounds.d.ts +0 -11
- package/dist/tools/numeric-bounds.js +4 -4
- package/dist/tools/observe-tools.js +22 -26
- package/dist/tools/observed-nothing.d.ts +9 -0
- package/dist/tools/observed-nothing.js +2 -1
- package/dist/tools/read-tools.js +12 -17
- package/dist/tools/real-input-attempt.d.ts +14 -6
- package/dist/tools/real-input-attempt.js +75 -18
- package/dist/tools/reconcile-tools.js +2 -1
- package/dist/tools/reload-result.d.ts +6 -1
- package/dist/tools/reload-result.js +7 -2
- package/dist/tools/resolve-target.d.ts +7 -1
- package/dist/tools/resolve-target.js +72 -9
- package/dist/tools/settle-in-flight.d.ts +1 -1
- package/dist/tools/settle-in-flight.js +9 -2
- package/dist/tools/snapshot-delta.d.ts +24 -1
- package/dist/tools/snapshot-delta.js +66 -7
- package/dist/tools/tool-names.d.ts +1 -0
- package/dist/tools/tool-names.js +1 -0
- package/dist/tools/tool-surface.js +20 -2
- package/dist/tools/tools.js +120 -11
- package/dist/tools/verify-next-baton.d.ts +2 -1
- package/dist/update/sdk-sync.d.ts +1 -1
- package/dist/update/sdk-sync.js +1 -1
- package/dist/update/updater.js +1 -1
- package/dist/version/sdk-fix.d.ts +2 -1
- package/dist/version/version-skew.d.ts +0 -8
- package/dist/version/version-skew.js +1 -1
- package/docs/README.md +8 -6
- package/docs/actions.mdx +1 -1
- package/docs/agent-cheatsheet.md +4 -2
- package/docs/architecture.md +1 -1
- package/docs/cli/mcp.mdx +3 -1
- package/docs/cli/watch.mdx +1 -1
- package/docs/cli.mdx +1 -1
- package/docs/desktop.mdx +1 -1
- package/docs/docs.json +8 -3
- package/docs/faq.mdx +9 -0
- package/docs/first-drive.md +136 -0
- package/docs/frameworks.mdx +29 -7
- package/docs/gate-plan.md +2 -2
- package/docs/gates.md +19 -11
- package/docs/getting-started.md +7 -1
- package/docs/http-transport.md +164 -0
- package/docs/index.mdx +5 -3
- package/docs/install-manual.mdx +1 -1
- package/docs/packages/tauri.mdx +1 -1
- package/docs/packages.mdx +15 -3
- package/docs/platform-integration.md +1 -1
- package/docs/predicates.mdx +2 -0
- package/docs/system-map.md +2 -2
- package/docs/telemetry-contract.md +4 -4
- package/docs/telemetry-events.mdx +1 -1
- package/docs/telemetry.md +3 -3
- package/docs/tools-navigate.mdx +14 -6
- package/docs/usage.md +4 -4
- package/package.json +7 -4
- package/dist/init/agent-rules.d.ts +0 -116
- package/dist/init/agent-rules.js +0 -279
- package/dist/init/app-choice.d.ts +0 -20
- package/dist/init/app-choice.js +0 -25
- package/dist/init/astro-host.d.ts +0 -21
- package/dist/init/astro-host.js +0 -27
- package/dist/init/astro-patch.d.ts +0 -33
- package/dist/init/astro-patch.js +0 -300
- package/dist/init/capabilities.d.ts +0 -40
- package/dist/init/capabilities.js +0 -150
- package/dist/init/closing-hint.d.ts +0 -36
- package/dist/init/closing-hint.js +0 -120
- package/dist/init/connect-steps.d.ts +0 -2
- package/dist/init/connect-steps.js +0 -50
- package/dist/init/cra.d.ts +0 -79
- package/dist/init/cra.js +0 -178
- package/dist/init/csp-check.d.ts +0 -38
- package/dist/init/csp-check.js +0 -107
- package/dist/init/csp-doctor.d.ts +0 -32
- package/dist/init/csp-doctor.js +0 -54
- package/dist/init/desktop-doctor.d.ts +0 -41
- package/dist/init/desktop-doctor.js +0 -198
- package/dist/init/detect.d.ts +0 -96
- package/dist/init/detect.js +0 -209
- package/dist/init/dev-script.d.ts +0 -50
- package/dist/init/dev-script.js +0 -66
- package/dist/init/format-generated.d.ts +0 -18
- package/dist/init/format-generated.js +0 -39
- package/dist/init/install-hint.d.ts +0 -9
- package/dist/init/install-hint.js +0 -29
- package/dist/init/mcp-clients.d.ts +0 -89
- package/dist/init/mcp-clients.js +0 -299
- package/dist/init/mcp-registered.d.ts +0 -12
- package/dist/init/mcp-registered.js +0 -14
- package/dist/init/mcp.d.ts +0 -89
- package/dist/init/mcp.js +0 -129
- package/dist/init/next-patch.d.ts +0 -39
- package/dist/init/next-patch.js +0 -196
- package/dist/init/node-io.d.ts +0 -7
- package/dist/init/node-io.js +0 -117
- package/dist/init/non-js-project.d.ts +0 -27
- package/dist/init/non-js-project.js +0 -84
- package/dist/init/patch-kind.d.ts +0 -20
- package/dist/init/patch-kind.js +0 -10
- package/dist/init/plan-framework.d.ts +0 -64
- package/dist/init/plan-framework.js +0 -565
- package/dist/init/plan.d.ts +0 -242
- package/dist/init/plan.js +0 -703
- package/dist/init/preflight.d.ts +0 -28
- package/dist/init/preflight.js +0 -38
- package/dist/init/project-id.d.ts +0 -12
- package/dist/init/project-id.js +0 -25
- package/dist/init/refresh-rules.d.ts +0 -39
- package/dist/init/refresh-rules.js +0 -51
- package/dist/init/run.d.ts +0 -117
- package/dist/init/run.js +0 -806
- package/dist/init/slash-command.d.ts +0 -27
- package/dist/init/slash-command.js +0 -132
- package/dist/init/snippets.d.ts +0 -134
- package/dist/init/snippets.js +0 -572
- package/dist/init/vite-config.d.ts +0 -18
- package/dist/init/vite-config.js +0 -114
- package/dist/init/windows-quote.d.ts +0 -38
- package/dist/init/windows-quote.js +0 -70
- package/dist/init/workspace-apps.d.ts +0 -30
- package/dist/init/workspace-apps.js +0 -178
- package/dist/project/remember-project.d.ts +0 -24
- package/dist/project/remember-project.js +0 -40
- /package/dist/{init → setup}/confirm.d.ts +0 -0
package/dist/init/snippets.js
DELETED
|
@@ -1,572 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Generated file contents and copy-paste snippets for `reticle init`. Kept as named constants/builders
|
|
3
|
-
* so the runner never inlines free strings.
|
|
4
|
-
*/
|
|
5
|
-
import { RETICLE_DEFAULT_PORT, ReticleDir, bridgeWsUrl, RETICLE_CLIENT_HOST, RETICLE_WS_PATH, } from '@reticlehq/core';
|
|
6
|
-
import { UiLibrary } from './detect.js';
|
|
7
|
-
import { SERVER_VERSION } from '../version/server-version.js';
|
|
8
|
-
/**
|
|
9
|
-
* The SDK as one import a plain page can actually resolve.
|
|
10
|
-
*
|
|
11
|
-
* `init` used to tell static-HTML users that a page with no build step could not load the SDK, and
|
|
12
|
-
* to go and stand up a bundler. That is true of a BARE specifier and false of a URL, and the
|
|
13
|
-
* difference was the whole road for every server-rendered app we hear from: FastAPI, Flask, Django,
|
|
14
|
-
* Streamlit, Rails. Proven end to end before this shipped, on a page served by `python3 -m
|
|
15
|
-
* http.server`: a session connected, a snapshot returned, and two act_and_wait calls came back
|
|
16
|
-
* `verified: "yes"`.
|
|
17
|
-
*
|
|
18
|
-
* jsDelivr rather than esm.sh, measured: a third of the requests and a third of the bytes for the
|
|
19
|
-
* same result. `/+esm` is what makes it work, and the bare package URL does NOT: every file in
|
|
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
|
-
*
|
|
24
|
-
* PINNED to this server's version on purpose. A floating import upgrades the page SDK underneath a
|
|
25
|
-
* daemon that did not move, which is `version_skew` arriving by a route nothing checks.
|
|
26
|
-
*/
|
|
27
|
-
const CDN_SDK_URL = `https://cdn.jsdelivr.net/npm/@reticlehq/browser@${SERVER_VERSION}/+esm`;
|
|
28
|
-
/**
|
|
29
|
-
* The connect argument literal: a non-default port adds a `url`, and a projectId is always passed
|
|
30
|
-
* (so the app is identifiable across port changes). Empty string only when neither applies.
|
|
31
|
-
*/
|
|
32
|
-
function connectArg(port, projectId) {
|
|
33
|
-
const parts = [];
|
|
34
|
-
if (port !== undefined && port !== RETICLE_DEFAULT_PORT) {
|
|
35
|
-
parts.push(`url: '${bridgeWsUrl(port)}'`);
|
|
36
|
-
}
|
|
37
|
-
if (projectId !== undefined && projectId.length > 0)
|
|
38
|
-
parts.push(`projectId: '${projectId}'`);
|
|
39
|
-
return parts.length > 0 ? `{ ${parts.join(', ')} }` : '';
|
|
40
|
-
}
|
|
41
|
-
/**
|
|
42
|
-
* The same literal, with the pairing token folded in.
|
|
43
|
-
*
|
|
44
|
-
* The token belongs INSIDE the call the user pastes. Every other stack has a build step to inline
|
|
45
|
-
* it (the Vite plugin's `define`, Next's NEXT_PUBLIC_*, Astro's config, CRA's .env); the hand-wired
|
|
46
|
-
* paths have none, so `init` inlines the literal it already read. Without it the bridge closes the
|
|
47
|
-
* socket with AUTH_FAILED and no session ever appears: see Bridge's hello handler.
|
|
48
|
-
*
|
|
49
|
-
* An empty token is omitted rather than emitted as `token: ''`. A daemon that could not write to
|
|
50
|
-
* $HOME runs without auth and trusts loopback, and an empty string would fail the comparison against
|
|
51
|
-
* one that does hold a token.
|
|
52
|
-
*/
|
|
53
|
-
export function connectArgWithToken(port, projectId, pairingToken) {
|
|
54
|
-
const base = connectArg(port, projectId);
|
|
55
|
-
if (pairingToken === undefined || 0 === pairingToken.length)
|
|
56
|
-
return base;
|
|
57
|
-
const inner = base.length > 0 ? base.slice(1, -1).trim() : '';
|
|
58
|
-
return `{ ${[inner, `token: '${pairingToken}'`].filter((p) => p.length > 0).join(', ')} }`;
|
|
59
|
-
}
|
|
60
|
-
/**
|
|
61
|
-
* Which SDK package the GENERATED code should import, and whether `install()` applies.
|
|
62
|
-
*
|
|
63
|
-
* This has to agree with `frameworkPackages`, and it did not. That function was changed so a Vue or
|
|
64
|
-
* Svelte app installs `@reticlehq/browser` instead of the React adapter — correctly — while every
|
|
65
|
-
* generated connect snippet still said `import('@reticlehq/react')`. A SvelteKit app would have
|
|
66
|
-
* installed the sensor and then run a hook importing a package that is not there.
|
|
67
|
-
*
|
|
68
|
-
* `install()` is the React adapter's, not the sensor's: `@reticlehq/browser` exports `reticle` and no
|
|
69
|
-
* `install`, so swapping the specifier alone would trade a missing module for a missing export.
|
|
70
|
-
*/
|
|
71
|
-
export function sdkImport(uiLibrary) {
|
|
72
|
-
const react = uiLibrary !== UiLibrary.VUE && uiLibrary !== UiLibrary.SVELTE;
|
|
73
|
-
return react
|
|
74
|
-
? { specifier: '@reticlehq/react', usesInstall: true }
|
|
75
|
-
: { specifier: '@reticlehq/browser', usesInstall: false };
|
|
76
|
-
}
|
|
77
|
-
/**
|
|
78
|
-
* The framework plugin to show ALONGSIDE reticle() in the example, so the ordering is clear.
|
|
79
|
-
*
|
|
80
|
-
* It used to be `react()` unconditionally, which is what a Vue app was shown — a plugin it does not
|
|
81
|
-
* have, four lines after `init` had correctly detected Vue and said so. The example exists to show
|
|
82
|
-
* that `reticle()` goes last, not to tell anyone which UI framework they are using.
|
|
83
|
-
*/
|
|
84
|
-
function frameworkPluginExample(uiLibrary) {
|
|
85
|
-
switch (uiLibrary) {
|
|
86
|
-
case UiLibrary.VUE:
|
|
87
|
-
return 'vue()';
|
|
88
|
-
case UiLibrary.SVELTE:
|
|
89
|
-
return 'svelte()';
|
|
90
|
-
case UiLibrary.REACT:
|
|
91
|
-
case UiLibrary.PREACT:
|
|
92
|
-
return 'react()';
|
|
93
|
-
default:
|
|
94
|
-
// Nothing detected: name no plugin rather than invent one. The reader keeps whatever they have.
|
|
95
|
-
return '/* your existing plugins */';
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
/** The Vite-config snippet printed when we can't safely auto-patch the config. */
|
|
99
|
-
export function viteManual(port, uiLibrary = UiLibrary.UNKNOWN) {
|
|
100
|
-
const call = port === undefined ? 'reticle()' : `reticle({ port: ${String(port)} })`;
|
|
101
|
-
return `Add the Reticle plugin to your Vite config:
|
|
102
|
-
|
|
103
|
-
import { reticle } from '@reticlehq/vite-plugin';
|
|
104
|
-
|
|
105
|
-
export default defineConfig({
|
|
106
|
-
plugins: [${frameworkPluginExample(uiLibrary)}, ${call}],
|
|
107
|
-
});
|
|
108
|
-
|
|
109
|
-
Keep \`reticle()\` LAST so it sees the output of your other plugins. It only applies during \`vite\`
|
|
110
|
-
(dev) — it is dropped from \`vite build\`.`;
|
|
111
|
-
}
|
|
112
|
-
/** Next.js config wrap — always printed (we never auto-rewrite next.config). */
|
|
113
|
-
export function nextConfigManual(configFile) {
|
|
114
|
-
return `Wrap your ${configFile} export with withReticle (keeps SWC, dev-only):
|
|
115
|
-
|
|
116
|
-
import { withReticle } from '@reticlehq/next';
|
|
117
|
-
|
|
118
|
-
export default withReticle(nextConfig);`;
|
|
119
|
-
}
|
|
120
|
-
/**
|
|
121
|
-
* The dev-only client component that connects Reticle after hydration.
|
|
122
|
-
*
|
|
123
|
-
* The token is not optional. The bridge requires a pairing token even on localhost, and unlike Vite
|
|
124
|
-
* (where the plugin injects it) a Next app has to carry it through `withReticle`, which publishes it
|
|
125
|
-
* as `NEXT_PUBLIC_RETICLE_TOKEN`. This file used to connect with only a projectId, so every Next
|
|
126
|
-
* setup ended at `bridge refused the connection: authentication failed` and no session ever appeared.
|
|
127
|
-
*/
|
|
128
|
-
export function nextReticleDevFile(port, projectId, testids = [], stores = [], found = []) {
|
|
129
|
-
const base = connectArg(port, projectId);
|
|
130
|
-
const fields = '' === base ? '' : `${base.slice(1, -1).trim()}, `;
|
|
131
|
-
const ids = testids.map((t) => `'${t}'`).join(', ');
|
|
132
|
-
// Same rule as the Vite module: a store we found is registered outright, and the commented hint
|
|
133
|
-
// survives only for the libraries we can name but not wire.
|
|
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).
|
|
136
|
-
const storeBlock = found.length > 0
|
|
137
|
-
? found.map((s) => ` registerStore('${s.key}', ${s.ident});`).join('\n')
|
|
138
|
-
: 0 === stores.length
|
|
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.
|
|
144
|
-
return `'use client';
|
|
145
|
-
import { useEffect } from 'react';
|
|
146
|
-
${storeImports.length > 0 ? `${storeImports}\n` : ''}
|
|
147
|
-
/** Dev-only: connect Reticle + install the React adapter, after hydration. */
|
|
148
|
-
export function ReticleDev() {
|
|
149
|
-
useEffect(() => {
|
|
150
|
-
if (process.env.NODE_ENV !== 'development') return;
|
|
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
|
-
});
|
|
166
|
-
|
|
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.
|
|
172
|
-
${storeBlock}
|
|
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
|
-
);
|
|
180
|
-
}, []);
|
|
181
|
-
return null;
|
|
182
|
-
}
|
|
183
|
-
`;
|
|
184
|
-
}
|
|
185
|
-
/**
|
|
186
|
-
* Astro connect instructions.
|
|
187
|
-
*
|
|
188
|
-
* Astro is Vite-based but SSRs its own HTML, so the plugin's index.html injection never fires, and
|
|
189
|
-
* `vite` is not a direct dependency — so this used to fall through to the generic HTML advice, which
|
|
190
|
-
* tells you to add a connect to an "entry module" Astro does not have, or to bundle the SDK with
|
|
191
|
-
* esbuild. Both are wrong for Astro, and following either gets you nothing.
|
|
192
|
-
*
|
|
193
|
-
* Astro bundles a page `<script>`, so the bare import resolves there. The token has to be inlined by
|
|
194
|
-
* the config because there is no plugin in the page's path to inject it, and `build.target` has to be
|
|
195
|
-
* raised or Astro down-levels the modern SDK bundle and dies on a destructuring transform.
|
|
196
|
-
*/
|
|
197
|
-
/**
|
|
198
|
-
* Name the file the connect <script> should go in — the layout when one exists, otherwise the page,
|
|
199
|
-
* because a project with no layout has nowhere else to put it and should not be told otherwise.
|
|
200
|
-
*/
|
|
201
|
-
function layoutHost(layoutPath) {
|
|
202
|
-
return layoutPath === undefined
|
|
203
|
-
? '2. This project has no layout, so put it in the page you want instrumented (e.g.\n src/pages/index.astro) — every page you want a session from needs it — inside <body>:'
|
|
204
|
-
: `2. In ${layoutPath} (or any other page you want instrumented), inside <body>:`;
|
|
205
|
-
}
|
|
206
|
-
export function astroManual(port, projectId,
|
|
207
|
-
/**
|
|
208
|
-
* A layout file that actually exists, when one does.
|
|
209
|
-
*
|
|
210
|
-
* Reported from the field: on `examples/framework-react` — which has no layout at all, only
|
|
211
|
-
* `src/pages/index.astro` — init printed thirty lines telling the user to paste into "your
|
|
212
|
-
* layout". Instructions that name a file the project does not have read as a mistake by the
|
|
213
|
-
* reader, and cost them the time it takes to go and confirm it is missing.
|
|
214
|
-
*/
|
|
215
|
-
layoutPath) {
|
|
216
|
-
const extra = port !== undefined && port !== RETICLE_DEFAULT_PORT
|
|
217
|
-
? `\n url: '${bridgeWsUrl(port)}',`
|
|
218
|
-
: '';
|
|
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 } : {}),` : '';
|
|
260
|
-
return `Astro renders its own HTML, so the connect goes in a page <script> and the pairing token is inlined by the config.
|
|
261
|
-
|
|
262
|
-
1. In astro.config.mjs — inline the daemon's token and raise the build target:
|
|
263
|
-
|
|
264
|
-
import { readFileSync, readdirSync } from 'node:fs';
|
|
265
|
-
import { homedir } from 'node:os';
|
|
266
|
-
import { join } from 'node:path';
|
|
267
|
-
|
|
268
|
-
function reticleToken() {
|
|
269
|
-
const dir = process.env['RETICLE_PAIRING_TOKEN_DIR'] || join(homedir(), '.reticle');
|
|
270
|
-
try { return readFileSync(join(dir, 'pairing-token'), 'utf8').trim(); } catch { return ''; }
|
|
271
|
-
}
|
|
272
|
-
${urlHelper}
|
|
273
|
-
export default defineConfig({
|
|
274
|
-
vite: {
|
|
275
|
-
// Astro's default target down-levels the modern SDK bundle and fails on a destructuring transform.
|
|
276
|
-
build: { target: 'es2022' },
|
|
277
|
-
optimizeDeps: { esbuildOptions: { target: 'es2022' } },
|
|
278
|
-
define: {
|
|
279
|
-
__RETICLE_TOKEN__: JSON.stringify(reticleToken()),${urlDefine}
|
|
280
|
-
// Without this, source pointers come back as absolute paths from YOUR machine — useless in a
|
|
281
|
-
// report. Every other framework gets it from its build plugin; Astro owns its Vite instance.
|
|
282
|
-
__RETICLE_ROOT__: JSON.stringify(process.cwd()),
|
|
283
|
-
},
|
|
284
|
-
},
|
|
285
|
-
});
|
|
286
|
-
|
|
287
|
-
${layoutHost(layoutPath)}
|
|
288
|
-
|
|
289
|
-
<script>
|
|
290
|
-
if (import.meta.env.DEV) {
|
|
291
|
-
const token = typeof __RETICLE_TOKEN__ !== 'undefined' ? __RETICLE_TOKEN__ : '';
|
|
292
|
-
const root = typeof __RETICLE_ROOT__ !== 'undefined' ? __RETICLE_ROOT__ : '';${urlRead}
|
|
293
|
-
const { reticle, install } = await import('@reticlehq/react');
|
|
294
|
-
install();
|
|
295
|
-
reticle.connect({${id}${extra}${urlSpread}
|
|
296
|
-
...(token.length > 0 ? { token } : {}),
|
|
297
|
-
...(root.length > 0 ? { root } : {}),
|
|
298
|
-
});
|
|
299
|
-
}
|
|
300
|
-
</script>
|
|
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
|
-
|
|
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.`;
|
|
309
|
-
}
|
|
310
|
-
/**
|
|
311
|
-
* The app-side dev module the Vite plugin imports by convention.
|
|
312
|
-
*
|
|
313
|
-
* `registerCapabilities` tells the agent what it can drive without guessing; `registerStore` is the
|
|
314
|
-
* one that matters most and the one we cannot write for you — detecting that an app depends on
|
|
315
|
-
* zustand is easy, knowing which module exports the store instance is not, and a wrong import here
|
|
316
|
-
* breaks the module everything else hangs off. So the store lines are generated COMMENTED, naming
|
|
317
|
-
* the libraries actually found in package.json, with the exact call to uncomment.
|
|
318
|
-
*/
|
|
319
|
-
export function viteDevModuleFile(testids, stores, found = [], uiLibrary = UiLibrary.REACT) {
|
|
320
|
-
// The specifier has to be the package `frameworkPackages` installed. This file is the Vite path —
|
|
321
|
-
// the commonest install there is — and it was hardcoded to `@reticlehq/react` while a Vue or
|
|
322
|
-
// Svelte app was being given `@reticlehq/browser`, so the generated file imported something that
|
|
323
|
-
// was not there. Caught by running `init` against a pristine Vue app, not by any gate.
|
|
324
|
-
//
|
|
325
|
-
// The sensor exports `registerCapabilities` and `registerStore` (and the store adapters) just as
|
|
326
|
-
// the React kit does; the only thing it lacks is `install()`, which this file never called.
|
|
327
|
-
const sdk = sdkImport(uiLibrary);
|
|
328
|
-
const ids = testids.map((t) => `'${t}'`).join(', ');
|
|
329
|
-
// A store we FOUND is imported and registered outright — the whole point of the file. The hints
|
|
330
|
-
// stay only for the libraries we can name but not wire (they need an argument we cannot infer).
|
|
331
|
-
const storeImports = found.map((s) => `import { ${s.ident} } from '${s.importPath}';`).join('\n');
|
|
332
|
-
const storeBlock = found.length > 0
|
|
333
|
-
? found.map((s) => ` registerStore('${s.key}', ${s.ident});`).join('\n')
|
|
334
|
-
: 0 === stores.length
|
|
335
|
-
? ' // No state library detected. If you add one, register it here — see node_modules/@reticlehq/server/docs/usage.md.'
|
|
336
|
-
: stores.map((h) => ` // import your store, then: ${h}`).join('\n');
|
|
337
|
-
const registerImport = found.length > 0 ? 'registerCapabilities, registerStore' : 'registerCapabilities';
|
|
338
|
-
return `// Dev-only. Imported automatically by @reticlehq/vite-plugin, so you do not need to import it.
|
|
339
|
-
// Self-guards on import.meta.env.DEV, so it is a no-op in a production build.
|
|
340
|
-
import { ${registerImport} } from '${sdk.specifier}';
|
|
341
|
-
${storeImports.length > 0 ? `${storeImports}\n` : ''}
|
|
342
|
-
if (import.meta.env.DEV) {
|
|
343
|
-
// ── Start with ONE flow. ─────────────────────────────────────────────────────────────────────
|
|
344
|
-
// You do not need to describe the whole app to get value, and trying to is the slow path. Register
|
|
345
|
-
// the store your most important flow reads, and list the testids that flow touches. Add more later,
|
|
346
|
-
// when a flow you actually replay needs them.
|
|
347
|
-
//
|
|
348
|
-
// Registering a store is the highest-value line in this file: it lets the agent check what the app
|
|
349
|
-
// BELIEVES, not just what it rendered — the class of bug a screenshot cannot see. Pass the STORE,
|
|
350
|
-
// not \`() => store.getState()\`: the store form wires \`subscribe\` too, so every mutation emits a
|
|
351
|
-
// state diff; the getter form is read-only and silently produces empty diffs.
|
|
352
|
-
${storeBlock}
|
|
353
|
-
|
|
354
|
-
registerCapabilities({
|
|
355
|
-
testids: [${ids}],${0 === testids.length ? ' // none found; add data-testid to your key elements' : ''}
|
|
356
|
-
signals: [], // names you pass to reticle.signal()
|
|
357
|
-
stores: [${found.map((s) => `'${s.key}'`).join(', ')}], // the keys you registered above
|
|
358
|
-
});
|
|
359
|
-
}
|
|
360
|
-
`;
|
|
361
|
-
}
|
|
362
|
-
/** Where that module goes. Matches @reticlehq/vite-plugin's convention list. */
|
|
363
|
-
export const VITE_DEV_MODULE_PATH = 'src/reticle-dev.ts';
|
|
364
|
-
/** Default root-layout path, used when no layout was found on disk (reporting only). */
|
|
365
|
-
export const NEXT_LAYOUT_PATH = 'app/layout.tsx';
|
|
366
|
-
/** Mount instruction for the root layout. */
|
|
367
|
-
export const NEXT_LAYOUT_MANUAL = `Mount <ReticleDev /> in your root layout (app/layout.tsx), dev-only:
|
|
368
|
-
|
|
369
|
-
import { ReticleDev } from './reticle-dev';
|
|
370
|
-
// inside <body>:
|
|
371
|
-
{process.env.NODE_ENV === 'development' ? <ReticleDev /> : null}`;
|
|
372
|
-
/**
|
|
373
|
-
* Manual connect guidance for projects without a Vite/Next plugin. Most such projects still use a
|
|
374
|
-
* BUNDLER (CRA, webpack, Parcel, Vue/Svelte CLIs) — for those, the connect goes in the entry MODULE,
|
|
375
|
-
* where a bare `@reticlehq/react` import resolves. A bare import in a plain index.html does NOT resolve in
|
|
376
|
-
* the browser, so we never tell a bundled app to do that (the old advice silently failed for CRA).
|
|
377
|
-
*/
|
|
378
|
-
/**
|
|
379
|
-
* The whole install, for a page with no build step, as one block a person can paste.
|
|
380
|
-
*
|
|
381
|
-
* Extracted so the `no package.json` exit can print the SAME snippet `htmlManual` offers. That exit
|
|
382
|
-
* is the one every server-rendered app reaches (FastAPI, Flask, Django, Rails, Streamlit), it is
|
|
383
|
-
* where `init` stops, and until now it stopped with an explanation instead of an answer. A message
|
|
384
|
-
* that says "add the snippet below" and then prints no snippet is the same defect wearing the
|
|
385
|
-
* opposite sign, so the two share a builder rather than a copy.
|
|
386
|
-
*/
|
|
387
|
-
export function staticPageSnippet(connectArgLiteral) {
|
|
388
|
-
return ` <script type="module">
|
|
389
|
-
import { reticle } from '${CDN_SDK_URL}';
|
|
390
|
-
reticle.connect(${connectArgLiteral});
|
|
391
|
-
</script>`;
|
|
392
|
-
}
|
|
393
|
-
export function htmlManual(port, projectId, pairingToken) {
|
|
394
|
-
const withToken = connectArgWithToken(port, projectId, pairingToken);
|
|
395
|
-
const tokenNote = pairingToken === undefined || 0 === pairingToken.length
|
|
396
|
-
? ''
|
|
397
|
-
: `\n\n The \`token\` is this machine's pairing token, read from ~/.reticle/pairing-token. Keep it: the
|
|
398
|
-
bridge REJECTS a connect without it ("authentication failed") and no session appears. It is
|
|
399
|
-
per-machine and local-only, so do not commit it — a teammate's daemon mints their own.`;
|
|
400
|
-
return `No Vite/Next plugin detected — wire the dev-only connect by hand. Pick the form for your setup:
|
|
401
|
-
|
|
402
|
-
• Bundled app (Create React App, webpack, Parcel, Vue/Svelte CLI, etc.) — add to your ENTRY module
|
|
403
|
-
(e.g. src/index.js or src/main.js), where '@reticlehq/react' resolves through your bundler:
|
|
404
|
-
|
|
405
|
-
if (process.env.NODE_ENV !== 'production') {
|
|
406
|
-
void import('@reticlehq/react').then(({ reticle, install }) => {
|
|
407
|
-
install();
|
|
408
|
-
reticle.connect(${withToken});
|
|
409
|
-
});
|
|
410
|
-
}${tokenNote}
|
|
411
|
-
|
|
412
|
-
• Plain HTML with NO build step (FastAPI, Flask, Django, Rails, Streamlit, a hand-written page) —
|
|
413
|
-
paste this into the page, in a template you only serve in development. There is nothing to
|
|
414
|
-
install: no npm, no bundler, no package.json.
|
|
415
|
-
|
|
416
|
-
${staticPageSnippet(withToken)}
|
|
417
|
-
|
|
418
|
-
Serving the app on something other than localhost (a hosts-file alias, a LAN IP, a container, a
|
|
419
|
-
tunnel)? You need TWO things, not one: \`allowNonLocalhost: true\` AND a pairing token, passed as
|
|
420
|
-
\`token\` on the same connect. The flag alone is NOT sufficient — off localhost the SDK refuses
|
|
421
|
-
without a token as well, and that refusal is page-side, so the daemon sees only silence and every
|
|
422
|
-
\`reticle doctor\` check still passes. The token is the one in \`~/.reticle/pairing-token\` (the
|
|
423
|
-
build plugins read the same file). Without both, the SDK says so in the browser console only, so
|
|
424
|
-
from here it looks exactly like nothing happened.`;
|
|
425
|
-
}
|
|
426
|
-
export const NEXT_RETICLE_DEV_PATH = 'app/reticle-dev.tsx';
|
|
427
|
-
export const SVELTEKIT_HOOKS_PATH = 'src/hooks.client.ts';
|
|
428
|
-
/**
|
|
429
|
-
* Said to the user's face rather than discovered later. React, Next, Remix and Astro each have an
|
|
430
|
-
* app and a CI gate; SvelteKit has neither, so "it generated some wiring" is not evidence it works.
|
|
431
|
-
*/
|
|
432
|
-
/**
|
|
433
|
-
* Said out loud when the app does not render through React. The SDK is framework-agnostic — DOM,
|
|
434
|
-
* network, console and routing all still work — but `@reticlehq/react` is a React adapter, so
|
|
435
|
-
* component names and source mapping do not, and no CI gate covers this stack. Reporting all-green
|
|
436
|
-
* here is the one thing this project exists not to do.
|
|
437
|
-
*/
|
|
438
|
-
export function unverifiedUiLibraryNote(library) {
|
|
439
|
-
// Preact is not in the same position as Vue or Svelte and must not be told it is. The React
|
|
440
|
-
// adapter reaches Preact through `preact/compat`, which is what `docs/frameworks.mdx` has always
|
|
441
|
-
// said, so telling a Preact reader they get no component identity contradicts our own docs and
|
|
442
|
-
// talks them out of a package that is the right one for them. It is still ungated, which is the
|
|
443
|
-
// honest caveat, and #129 is the issue for closing that.
|
|
444
|
-
const identity = 'preact' === library
|
|
445
|
-
? 'React component identity — component names and stacks — comes from `@reticlehq/react`, which reaches Preact through `preact/compat`. That path is not covered by a CI gate here, so treat it as expected-to-work rather than proven.'
|
|
446
|
-
: 'What `@reticlehq/react` adds and you will NOT get is React component identity: component names and component stacks.';
|
|
447
|
-
return `Detected a ${library} app. Reticle's DOM, network, console and state tools work here. ${'vue' === library ? 'Source `file:line` does NOT come through: the build plugin stamps JSX and, separately, Svelte components, and a Vue single-file component is neither — measured, a Svelte counter reports `src/lib/Counter.svelte:5` and the same drive on Vue reports no source at all.' : 'Source `file:line` does too — the build plugin stamps it for this library (measured on preact and svelte).'} ${identity} ${'vue' === library ? 'The install gate scaffolds a Vue app from scratch on every change, so this SETUP is proven; no gate drives a Vue app to a verdict, so the drive is not.' : `No CI gate covers ${library}.`} Driven on every change: Vite + React, Next.js, Remix, Astro. If something doesn't work, please open an issue.`;
|
|
448
|
-
}
|
|
449
|
-
export const UNVERIFIED_FRAMEWORK_NOTE = 'Reticle has no SvelteKit app and no CI gate for one, so this wiring is untested — it may work, but nothing proves it and nothing will tell us if it breaks. Supported and gated today: Vite + React, Next.js, Remix and Astro. If the hook does not register a session, please open an issue.';
|
|
450
|
-
/**
|
|
451
|
-
* Dev-only client hook that connects Reticle in a SvelteKit app. SvelteKit renders through app.html and
|
|
452
|
-
* never triggers Vite's index.html injection (verified), so the standard plugin can't auto-connect —
|
|
453
|
-
* a client hook is the reliable path. SvelteKit runs src/hooks.client.ts on the client at startup.
|
|
454
|
-
*/
|
|
455
|
-
export function svelteKitHooksFile(port, projectId, uiLibrary = UiLibrary.SVELTE) {
|
|
456
|
-
// SvelteKit is Svelte, so this defaults to the sensor rather than the React adapter — and the
|
|
457
|
-
// import here MUST match what `frameworkPackages` installed, or the hook loads a package that is
|
|
458
|
-
// not in node_modules. See sdkImport.
|
|
459
|
-
const sdk = sdkImport(uiLibrary);
|
|
460
|
-
const base = connectArg(port, projectId);
|
|
461
|
-
const fields = '' === base ? '' : `${base.slice(1, -1).trim()}, `;
|
|
462
|
-
return `// Dev-only: connect Reticle on the client. SvelteKit renders via app.html, so the Vite-plugin
|
|
463
|
-
// index.html injection doesn't fire — connect from this client hook instead.
|
|
464
|
-
if (import.meta.env.DEV) {
|
|
465
|
-
void import('${sdk.specifier}').then(({ reticle${sdk.usesInstall ? ', install' : ''} }) => {
|
|
466
|
-
${sdk.usesInstall ? 'install();' : '// No React adapter here: the sensor has no install() to call.'}
|
|
467
|
-
// The bridge requires the pairing token even on localhost. Nothing in a browser can read the
|
|
468
|
-
// file it lives in, so @reticlehq/vite-plugin inlines it here at build time. Without it the
|
|
469
|
-
// console reads "bridge refused the connection: authentication failed" and no session appears.
|
|
470
|
-
const token = typeof __RETICLE_TOKEN__ !== 'undefined' ? __RETICLE_TOKEN__ : '';
|
|
471
|
-
const root = typeof __RETICLE_ROOT__ !== 'undefined' ? __RETICLE_ROOT__ : '';
|
|
472
|
-
const sdkVersion = typeof __RETICLE_SDK_VERSION__ !== 'undefined' ? __RETICLE_SDK_VERSION__ : '';
|
|
473
|
-
reticle.connect({
|
|
474
|
-
${fields}...(token.length > 0 ? { token } : {}),
|
|
475
|
-
...(root.length > 0 ? { root } : {}),
|
|
476
|
-
...(sdkVersion.length > 0 ? { sdkVersion } : {}),
|
|
477
|
-
});
|
|
478
|
-
});
|
|
479
|
-
}
|
|
480
|
-
|
|
481
|
-
declare const __RETICLE_TOKEN__: string | undefined;
|
|
482
|
-
declare const __RETICLE_ROOT__: string | undefined;
|
|
483
|
-
declare const __RETICLE_SDK_VERSION__: string | undefined;
|
|
484
|
-
`;
|
|
485
|
-
}
|
|
486
|
-
/** Where a Nuxt dev-only client plugin belongs. `.client` keeps it out of SSR; Nuxt auto-registers it. */
|
|
487
|
-
export const NUXT_PLUGIN_PATH = 'app/plugins/reticle.client.ts';
|
|
488
|
-
/**
|
|
489
|
-
* The Nuxt recipe, written out in full because every trap in it is one somebody actually hit.
|
|
490
|
-
*
|
|
491
|
-
* Reported from the field, in the order they were hit: `init` classified a Nuxt 4 app as `html`, so
|
|
492
|
-
* it installed a package named `@reticlehq/react` (with `react` in its peer dependencies) into a Vue
|
|
493
|
-
* codebase — the reporter only continued after auditing our dist to confirm there are no React
|
|
494
|
-
* imports at runtime, which most people will not do. It then handed over a snippet guarded on
|
|
495
|
-
* `window.location.hostname === 'localhost'`, which fails twice over in Nuxt: `window` does not
|
|
496
|
-
* exist during SSR, and the dev host here was a hosts-file alias (required for the backend's
|
|
497
|
-
* white-label origin detection), so the guard was false and the connect never ran — no error, no log
|
|
498
|
-
* line, nothing to debug. And nothing said a running dev server does not pick up a new plugin.
|
|
499
|
-
*
|
|
500
|
-
* So: `import.meta.dev` (build-time, host-independent) instead of a hostname check, `.client.ts`
|
|
501
|
-
* instead of an SSR guard, the framework-neutral sensor instead of the React kit, the non-localhost
|
|
502
|
-
* flag named up front, and the restart said out loud.
|
|
503
|
-
*/
|
|
504
|
-
export function nuxtManual(port, projectId) {
|
|
505
|
-
const base = connectArg(port, projectId);
|
|
506
|
-
const fields = '' === base ? '' : base.slice(1, -1).trim();
|
|
507
|
-
const connect = '' === fields ? 'reticle.connect()' : `reticle.connect({ ${fields} })`;
|
|
508
|
-
return `Nuxt owns its own Vite instance and renders its own HTML, so there is no vite.config to patch
|
|
509
|
-
and no index.html to inject into. Wire it with a dev-only CLIENT plugin, which is Nuxt's own idiom:
|
|
510
|
-
|
|
511
|
-
1. Create ${NUXT_PLUGIN_PATH}:
|
|
512
|
-
|
|
513
|
-
export default defineNuxtPlugin(() => {
|
|
514
|
-
// import.meta.dev is the correct guard: it is resolved at build time, so it does not care
|
|
515
|
-
// what hostname you develop on. Do NOT guard on window.location.hostname === 'localhost' —
|
|
516
|
-
// that is false on any hosts-file alias or LAN address, and window does not exist in SSR.
|
|
517
|
-
if (!import.meta.dev) return
|
|
518
|
-
void import('@reticlehq/browser').then(({ reticle }) => {
|
|
519
|
-
${connect}
|
|
520
|
-
})
|
|
521
|
-
})
|
|
522
|
-
|
|
523
|
-
The .client.ts suffix is load-bearing: it is what keeps this out of the server bundle.
|
|
524
|
-
|
|
525
|
-
2. Restart the dev server. A dev server that is already running does not pick up a new plugin —
|
|
526
|
-
it will not appear in .nuxt/plugins/client.mjs, and the app will come up with no SDK at all.
|
|
527
|
-
|
|
528
|
-
3. If your dev host is anything other than localhost (a hosts-file alias, a LAN IP, a tunnel), that
|
|
529
|
-
connect call needs TWO additions, not one: allowNonLocalhost: true AND a pairing token passed as
|
|
530
|
-
token. The flag alone is NOT sufficient off localhost. The token is the one in
|
|
531
|
-
~/.reticle/pairing-token. Without both, the SDK loads and then refuses, and the only sign is one
|
|
532
|
-
line in the browser console.
|
|
533
|
-
|
|
534
|
-
4. Add this to nuxt.config, so the dev server does not watch Reticle's own journal:
|
|
535
|
-
|
|
536
|
-
vite: { server: { watch: { ignored: [/(^|[\\\\/])\\.${ReticleDir.ROOT.slice(1)}([\\\\/]|$)/] } } }
|
|
537
|
-
|
|
538
|
-
Reticle journals every session into ${ReticleDir.ROOT}/ in your project root, rewriting one file
|
|
539
|
-
in it continuously while a session is live. Nuxt's dev server watches that root, so without this
|
|
540
|
-
it sees each write as a project file changing and full-reloads the page — which reconnects the
|
|
541
|
-
SDK, which produces the next write. The loop runs several times a second and looks like anything
|
|
542
|
-
except what it is: refs go stale, actions die mid-flight, and the session appears to flap.
|
|
543
|
-
It is a RegExp rather than a glob on purpose — chokidar dropped glob support in v4, so a
|
|
544
|
-
double-star pattern here is accepted and matches nothing.
|
|
545
|
-
|
|
546
|
-
The package is @reticlehq/browser — the framework-neutral sensor. DOM, network, console, routing and
|
|
547
|
-
source file:line all work in Vue. What you do not get is React component identity, which is the only
|
|
548
|
-
thing the React adapter adds. There is no Nuxt app in this project's CI, so this path is UNVERIFIED:
|
|
549
|
-
if something does not work, please open an issue.`;
|
|
550
|
-
}
|
|
551
|
-
/**
|
|
552
|
-
* Root-level project config for Reticle. Written by `reticle init`; read by `reticle mcp` for the port
|
|
553
|
-
* and by tooling for the stable projectId (the app's identity across port changes).
|
|
554
|
-
*/
|
|
555
|
-
export function reticleConfigContent(framework, port, projectId, installSource) {
|
|
556
|
-
const fields = { framework };
|
|
557
|
-
if (projectId !== undefined && projectId.length > 0)
|
|
558
|
-
fields['projectId'] = projectId;
|
|
559
|
-
if (port !== undefined && port !== RETICLE_DEFAULT_PORT)
|
|
560
|
-
fields['port'] = port;
|
|
561
|
-
// How this install arrived, recorded HERE because it is a property of the install and the only
|
|
562
|
-
// moment anything knows it is the moment it happens. It reaches us as an environment variable set
|
|
563
|
-
// by whichever channel ran the install, and an environment variable is gone by the next command,
|
|
564
|
-
// so every event after this one reported `unknown` and the question "which channel actually
|
|
565
|
-
// converts" could not be asked at all. Written once, read for the life of the project.
|
|
566
|
-
//
|
|
567
|
-
// A closed vocabulary, narrowed before it gets here, so this can never carry a path or a URL.
|
|
568
|
-
if (installSource !== undefined && installSource.length > 0) {
|
|
569
|
-
fields['installSource'] = installSource;
|
|
570
|
-
}
|
|
571
|
-
return `${JSON.stringify(fields, null, 2)}\n`;
|
|
572
|
-
}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Pure, conservative patcher for a Vite config: add the `@reticlehq/vite-plugin` import and drop
|
|
3
|
-
* `reticle` into the `plugins` array. Only handles the obvious, common shape — anything ambiguous
|
|
4
|
-
* bails to a `manual` result so we never half-edit a build config (a broken config is worse than a
|
|
5
|
-
* documented manual step).
|
|
6
|
-
*/
|
|
7
|
-
import { PatchKind, type SourcePatch } from './patch-kind.js';
|
|
8
|
-
export declare const VITE_IMPORT = "import { reticle } from '@reticlehq/vite-plugin';";
|
|
9
|
-
/** Alias kept so existing call sites read in Vite terms; the vocabulary is shared (see patch-kind). */
|
|
10
|
-
export declare const VitePatchKind: {
|
|
11
|
-
readonly APPLY: "apply";
|
|
12
|
-
readonly ALREADY: "already";
|
|
13
|
-
readonly MANUAL: "manual";
|
|
14
|
-
};
|
|
15
|
-
export type VitePatchKind = PatchKind;
|
|
16
|
-
type VitePatch = SourcePatch;
|
|
17
|
-
export declare function patchViteConfig(source: string, port?: number, captureBodies?: boolean): VitePatch;
|
|
18
|
-
export {};
|