@reticlehq/server 2.4.0 → 2.5.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 +702 -0
- package/dist/bridge/auth-failure-reason.d.ts +19 -0
- package/dist/bridge/auth-failure-reason.js +29 -0
- package/dist/{bridge-security.d.ts → bridge/bridge-security.d.ts} +1 -1
- package/dist/{bridge-security.js → bridge/bridge-security.js} +1 -1
- package/dist/{bridge.d.ts → bridge/bridge.d.ts} +1 -1
- package/dist/{bridge.js → bridge/bridge.js} +63 -13
- package/dist/{bridge.test-harness.d.ts → bridge/bridge.test-harness.d.ts} +1 -11
- package/dist/{bridge.test-harness.js → bridge/bridge.test-harness.js} +9 -9
- package/dist/{pairing-token.js → bridge/pairing-token.js} +1 -1
- package/dist/capsule/capsule-store.d.ts +8 -3
- package/dist/capsule/capsule-store.js +7 -2
- package/dist/capsule/capsule.js +3 -3
- package/dist/capsule/causal-summary.d.ts +8 -0
- package/dist/capsule/causal-summary.js +22 -12
- package/dist/capsule/divergence.d.ts +9 -4
- package/dist/capsule/divergence.js +8 -8
- package/dist/capsule/predicate-to-links.js +11 -8
- package/dist/{cli-doctor.js → cli/cli-doctor.js} +9 -2
- package/dist/{cli-flow-commands.d.ts → cli/cli-flow-commands.d.ts} +2 -2
- package/dist/{cli-flow-commands.js → cli/cli-flow-commands.js} +15 -15
- package/dist/{cli-launch.d.ts → cli/cli-launch.d.ts} +32 -3
- package/dist/cli/cli-launch.js +171 -0
- package/dist/{cli-parse.d.ts → cli/cli-parse.d.ts} +2 -11
- package/dist/{cli-parse.js → cli/cli-parse.js} +113 -60
- package/dist/{cli-port.d.ts → cli/cli-port.d.ts} +12 -0
- package/dist/{cli-port.js → cli/cli-port.js} +9 -9
- package/dist/cli/cli-update-commands.d.ts +4 -0
- package/dist/cli/cli-update-commands.js +93 -0
- package/dist/{cli-verify.js → cli/cli-verify.js} +14 -14
- package/dist/{cloud-cli.js → cli/cloud-cli.js} +29 -24
- package/dist/cli.d.ts +2 -2
- package/dist/cli.js +174 -92
- package/dist/cloud/cloud-config.d.ts +0 -1
- package/dist/cloud/cloud-config.js +9 -9
- package/dist/cloud/cloud-sync.d.ts +1 -7
- package/dist/cloud/cloud-sync.js +12 -12
- package/dist/crawl/crawl-empty.d.ts +16 -0
- package/dist/crawl/crawl-empty.js +24 -0
- package/dist/crawl/crawl-tools.js +4 -1
- package/dist/crawl/crawl.js +26 -7
- package/dist/daemon/daemon-resilience.d.ts +49 -0
- package/dist/daemon/daemon-resilience.js +191 -0
- package/dist/daemon/daemon-usefulness.d.ts +61 -0
- package/dist/daemon/daemon-usefulness.js +62 -0
- package/dist/{daemon.d.ts → daemon/daemon.d.ts} +33 -8
- package/dist/{daemon.js → daemon/daemon.js} +80 -48
- package/dist/daemon/idle-grace.d.ts +32 -0
- package/dist/daemon/idle-grace.js +41 -0
- package/dist/{idle-shutdown.d.ts → daemon/idle-shutdown.d.ts} +13 -0
- package/dist/{idle-shutdown.js → daemon/idle-shutdown.js} +27 -4
- package/dist/domain/domain-model.js +2 -2
- package/dist/events/body-failures.js +8 -8
- package/dist/events/contradictions.d.ts +1 -1
- package/dist/events/contradictions.js +60 -10
- package/dist/events/echo-mismatch.js +10 -10
- package/dist/events/event-filters.js +6 -6
- package/dist/events/json-salvage.d.ts +2 -1
- package/dist/events/json-salvage.js +6 -6
- package/dist/events/observed-in-window.d.ts +12 -0
- package/dist/events/observed-in-window.js +21 -0
- package/dist/events/predicate-eval.d.ts +43 -20
- package/dist/events/predicate-eval.js +159 -55
- package/dist/events/predicate.d.ts +2 -2
- package/dist/events/predicate.js +112 -35
- package/dist/events/reconcile.js +5 -5
- package/dist/events/ring-buffer.js +1 -1
- package/dist/events/stale-response.js +6 -6
- package/dist/events/testid-near-miss.d.ts +22 -0
- package/dist/events/testid-near-miss.js +33 -0
- package/dist/events/unit-mismatch.js +8 -8
- package/dist/flows/affected-tools.js +19 -4
- package/dist/flows/affected.js +1 -1
- package/dist/flows/annotate-target.d.ts +1 -0
- package/dist/flows/annotate-target.js +20 -0
- package/dist/flows/annotate-tools.js +25 -3
- package/dist/flows/annotate.js +17 -4
- package/dist/flows/assertion-integrity.d.ts +2 -1
- package/dist/flows/assertion-tiers-store.d.ts +3 -66
- package/dist/flows/assertion-tiers-store.js +2 -2
- package/dist/flows/attributed-failure.d.ts +17 -0
- package/dist/flows/attributed-failure.js +20 -0
- package/dist/flows/buddy-status.d.ts +2 -1
- package/dist/flows/buddy-status.js +2 -2
- package/dist/flows/coverage.d.ts +3 -2
- package/dist/flows/coverage.js +2 -2
- package/dist/flows/decision.js +24 -9
- package/dist/flows/empty-flow.d.ts +6 -0
- package/dist/flows/empty-flow.js +24 -0
- package/dist/flows/flake-store.d.ts +0 -1
- package/dist/flows/flake-store.js +1 -1
- package/dist/flows/flake.d.ts +2 -1
- package/dist/flows/flake.js +2 -2
- package/dist/flows/flow-classify.js +12 -0
- package/dist/flows/flow-replay-run.js +4 -4
- package/dist/flows/flow-replay.d.ts +5 -7
- package/dist/flows/flow-replay.js +114 -47
- package/dist/flows/flow-report.js +1 -1
- package/dist/flows/flow-scope.d.ts +1 -6
- package/dist/flows/flow-step-runners.d.ts +26 -6
- package/dist/flows/flow-step-runners.js +157 -6
- package/dist/flows/flow-success.js +20 -15
- package/dist/flows/flow-tools.js +53 -7
- package/dist/flows/flows.js +15 -11
- package/dist/flows/gate.d.ts +4 -3
- package/dist/flows/gate.js +1 -1
- package/dist/flows/heal-run.d.ts +0 -8
- package/dist/flows/heal-run.js +5 -5
- package/dist/flows/heal.js +3 -3
- package/dist/flows/predicate-to-expect.d.ts +38 -0
- package/dist/flows/predicate-to-expect.js +95 -0
- package/dist/flows/replay.d.ts +16 -1
- package/dist/flows/replay.js +58 -22
- package/dist/flows/role-anchor-nearest.d.ts +6 -0
- package/dist/flows/role-anchor-nearest.js +45 -0
- package/dist/flows/server-verify.d.ts +1 -1
- package/dist/flows/server-verify.js +5 -5
- package/dist/flows/verify-change-tools.js +32 -10
- package/dist/flows/verify-change-verdict.d.ts +15 -0
- package/dist/flows/verify-change-verdict.js +25 -0
- package/dist/flows/watch-batcher.d.ts +3 -2
- package/dist/honesty/already-true.d.ts +2 -0
- package/dist/honesty/already-true.js +31 -0
- package/dist/honesty/blind-spots.d.ts +16 -3
- package/dist/honesty/blind-spots.js +24 -12
- package/dist/honesty/honesty.d.ts +3 -2
- package/dist/honesty/honesty.js +4 -4
- package/dist/honesty/uncaptured-bodies.js +1 -1
- package/dist/honesty/unread-outcome.js +2 -2
- package/dist/honesty/verified.d.ts +22 -3
- package/dist/honesty/verified.js +48 -8
- package/dist/http-server.js +14 -7
- package/dist/hunt/hunt-report.d.ts +2 -1
- package/dist/hunt/hunt-report.js +2 -2
- package/dist/index.d.ts +8 -6
- package/dist/index.js +32 -25
- package/dist/init/agent-rules.d.ts +2 -1
- package/dist/init/agent-rules.js +45 -7
- package/dist/init/app-choice.d.ts +20 -0
- package/dist/init/app-choice.js +25 -0
- package/dist/init/astro-host.d.ts +21 -0
- package/dist/init/astro-host.js +27 -0
- package/dist/init/astro-patch.d.ts +16 -0
- package/dist/init/astro-patch.js +240 -0
- package/dist/init/capabilities.js +4 -1
- package/dist/init/cra.d.ts +37 -0
- package/dist/init/cra.js +90 -0
- package/dist/init/cursor.js +39 -4
- package/dist/init/desktop-doctor.d.ts +3 -2
- package/dist/init/desktop-doctor.js +4 -4
- package/dist/init/detect.d.ts +3 -2
- package/dist/init/detect.js +16 -5
- package/dist/init/mcp-registered.d.ts +12 -0
- package/dist/init/mcp-registered.js +14 -0
- package/dist/init/mcp.d.ts +27 -2
- package/dist/init/mcp.js +40 -4
- package/dist/init/next-patch.d.ts +2 -4
- package/dist/init/next-patch.js +109 -19
- package/dist/init/node-io.js +23 -6
- package/dist/init/plan-framework.d.ts +16 -1
- package/dist/init/plan-framework.js +132 -8
- package/dist/init/plan.d.ts +73 -8
- package/dist/init/plan.js +133 -34
- package/dist/init/project-id.d.ts +5 -9
- package/dist/init/project-id.js +10 -22
- package/dist/init/run.d.ts +5 -0
- package/dist/init/run.js +210 -36
- package/dist/init/slash-command.d.ts +9 -0
- package/dist/init/slash-command.js +10 -1
- package/dist/init/snippets.d.ts +7 -10
- package/dist/init/snippets.js +44 -15
- package/dist/init/vite-config.js +1 -1
- package/dist/init/workspace-apps.d.ts +23 -0
- package/dist/init/workspace-apps.js +68 -0
- package/dist/input/driven-redaction.js +1 -1
- package/dist/input/network-detail.js +8 -8
- package/dist/input/network-mock-tools.js +2 -2
- package/dist/input/network-mock.js +4 -4
- package/dist/input/real-input.js +8 -3
- package/dist/input/scroll-find.js +2 -2
- package/dist/input/scroll-tools.d.ts +0 -5
- package/dist/input/scroll-tools.js +11 -4
- package/dist/input/viewport-tools.js +2 -2
- package/dist/journal/ambient-store.d.ts +0 -2
- package/dist/journal/ambient-store.js +1 -1
- package/dist/journal/ambient.js +1 -1
- package/dist/journal/attach-journal.d.ts +2 -1
- package/dist/journal/deviation-report.js +6 -6
- package/dist/journal/deviation-service.js +1 -1
- package/dist/journal/envelope-store.d.ts +0 -2
- package/dist/journal/envelope-store.js +1 -1
- package/dist/journal/envelope.d.ts +2 -3
- package/dist/journal/envelope.js +3 -3
- package/dist/journal/journal-query.js +1 -1
- package/dist/journal/journal-recorder.d.ts +2 -1
- package/dist/journal/journal-recorder.js +2 -2
- package/dist/journal/rollups.js +9 -9
- package/dist/journal/session-end.d.ts +2 -1
- package/dist/journal/session-journal.js +4 -4
- package/dist/license/license.d.ts +0 -14
- package/dist/license/license.js +8 -8
- package/dist/log.d.ts +10 -0
- package/dist/log.js +11 -1
- package/dist/mcp/mcp-is-error.d.ts +13 -0
- package/dist/mcp/mcp-is-error.js +18 -0
- package/dist/mcp/mcp-outage.d.ts +31 -0
- package/dist/mcp/mcp-outage.js +48 -0
- package/dist/mcp/mcp-proxy.d.ts +124 -0
- package/dist/mcp/mcp-proxy.js +697 -0
- package/dist/{mcp.d.ts → mcp/mcp.d.ts} +13 -10
- package/dist/{mcp.js → mcp/mcp.js} +110 -35
- package/dist/mcp/proxy-handshake.d.ts +3 -0
- package/dist/mcp/proxy-handshake.js +54 -0
- package/dist/mcp/proxy-lifecycle.d.ts +64 -0
- package/dist/mcp/proxy-lifecycle.js +70 -0
- package/dist/mcp/tool-catalog-cache.d.ts +29 -0
- package/dist/mcp/tool-catalog-cache.js +55 -0
- package/dist/oracles/propose-consequences.d.ts +2 -1
- package/dist/oracles/propose-consequences.js +16 -11
- package/dist/oracles/self-instrument.d.ts +2 -1
- package/dist/oracles/self-instrument.js +1 -1
- package/dist/phenomena/phenomena.js +3 -3
- package/dist/platform.d.ts +16 -0
- package/dist/platform.js +16 -0
- package/dist/pool/playwright-launcher.d.ts +15 -2
- package/dist/pool/playwright-launcher.js +21 -2
- package/dist/project/fs-port.js +1 -1
- package/dist/project/project-tools.js +2 -2
- package/dist/runs/build-verification-run.js +1 -1
- package/dist/runs/repair-prompt.d.ts +0 -6
- package/dist/runs/repair-prompt.js +3 -3
- package/dist/runs/risk-classify.js +1 -1
- package/dist/runs/run-diff.d.ts +0 -2
- package/dist/runs/run-diff.js +3 -3
- package/dist/runs/run-tools.js +2 -2
- package/dist/runs/verification-sync.js +2 -2
- package/dist/runs/verify-http.js +1 -1
- package/dist/runs/verify-server.js +1 -1
- package/dist/session/command-timeout.d.ts +11 -3
- package/dist/session/command-timeout.js +2 -2
- package/dist/session/control-envelope.d.ts +6 -0
- package/dist/session/control-envelope.js +7 -1
- package/dist/session/dev-server-probe.d.ts +13 -0
- package/dist/session/dev-server-probe.js +52 -0
- package/dist/session/last-act.d.ts +17 -3
- package/dist/session/last-act.js +16 -4
- package/dist/session/live-control-tools.js +7 -2
- package/dist/session/live-control.js +1 -1
- package/dist/session/looks-like-dev-server.d.ts +14 -0
- package/dist/session/looks-like-dev-server.js +25 -0
- package/dist/session/no-session-diagnosis.d.ts +38 -0
- package/dist/session/no-session-diagnosis.js +70 -0
- package/dist/session/no-session-watch.d.ts +19 -0
- package/dist/session/no-session-watch.js +61 -0
- package/dist/session/observed-state.d.ts +4 -0
- package/dist/session/observed-state.js +19 -1
- package/dist/session/output-budget.js +1 -1
- package/dist/session/session-health.d.ts +8 -1
- package/dist/session/session-health.js +8 -7
- package/dist/session/session-info.d.ts +26 -7
- package/dist/session/session-info.js +42 -1
- package/dist/session/session-lease.d.ts +0 -11
- package/dist/session/session-lease.js +1 -1
- package/dist/session/session-manager.d.ts +3 -0
- package/dist/session/session-manager.js +52 -9
- package/dist/session/session-readiness.d.ts +1 -1
- package/dist/session/session-readiness.js +6 -1
- package/dist/session/session-reaper.js +1 -1
- package/dist/session/session-reconnect.d.ts +32 -0
- package/dist/session/session-reconnect.js +42 -0
- package/dist/session/session.d.ts +14 -2
- package/dist/session/session.js +69 -26
- package/dist/session/state-select.d.ts +1 -1
- package/dist/session/state-select.js +1 -1
- package/dist/status-payload.d.ts +19 -0
- package/dist/status-payload.js +11 -0
- package/dist/telemetry/argument-shape.js +10 -1
- package/dist/telemetry/browser-mode.d.ts +27 -0
- package/dist/telemetry/browser-mode.js +33 -0
- package/dist/telemetry/bug-found.d.ts +17 -21
- package/dist/telemetry/bug-found.js +120 -8
- package/dist/telemetry/cli-telemetry.d.ts +2 -12
- package/dist/telemetry/cli-telemetry.js +27 -4
- package/dist/telemetry/daemon-telemetry.d.ts +19 -0
- package/dist/telemetry/daemon-telemetry.js +12 -2
- package/dist/telemetry/dev-repo.js +4 -4
- package/dist/telemetry/error-fingerprint.js +21 -2
- package/dist/telemetry/feedback-cli.d.ts +1 -1
- package/dist/telemetry/feedback-cli.js +4 -4
- package/dist/telemetry/feedback-context.d.ts +22 -0
- package/dist/telemetry/feedback-context.js +41 -1
- package/dist/telemetry/feedback-delivery.d.ts +20 -0
- package/dist/telemetry/feedback-delivery.js +30 -0
- package/dist/telemetry/feedback-outbox.d.ts +22 -0
- package/dist/telemetry/feedback-outbox.js +87 -0
- package/dist/telemetry/feedback.d.ts +22 -1
- package/dist/telemetry/feedback.js +67 -8
- package/dist/telemetry/git-facts.js +1 -1
- package/dist/telemetry/session-metrics.d.ts +2 -0
- package/dist/telemetry/session-metrics.js +68 -6
- package/dist/telemetry/telemetry.d.ts +27 -2
- package/dist/telemetry/telemetry.js +119 -29
- package/dist/telemetry/verification-of.d.ts +22 -0
- package/dist/telemetry/verification-of.js +84 -0
- package/dist/tools/act-capsule.js +2 -2
- package/dist/tools/act-danger.d.ts +12 -0
- package/dist/tools/act-danger.js +20 -3
- package/dist/tools/act-helpers.js +4 -4
- package/dist/tools/act-tools.d.ts +0 -8
- package/dist/tools/act-tools.js +84 -115
- package/dist/tools/act-view.js +7 -7
- package/dist/tools/alias-args.d.ts +17 -0
- package/dist/tools/alias-args.js +25 -0
- package/dist/tools/assert-grade.js +9 -9
- package/dist/tools/assert-verdict.d.ts +3 -1
- package/dist/tools/assert-verdict.js +8 -5
- package/dist/tools/browser-tools.js +30 -11
- package/dist/tools/contract-tools.js +1 -1
- package/dist/tools/coverage-identity.d.ts +34 -0
- package/dist/tools/coverage-identity.js +46 -0
- package/dist/tools/coverage-tools.js +10 -14
- package/dist/tools/dynamic-tools.d.ts +2 -1
- package/dist/tools/dynamic-tools.js +90 -18
- package/dist/tools/error-recovery.d.ts +20 -2
- package/dist/tools/error-recovery.js +179 -4
- package/dist/tools/feedback-tools.d.ts +12 -1
- package/dist/tools/feedback-tools.js +28 -5
- package/dist/tools/invoke-tool.d.ts +0 -6
- package/dist/tools/invoke-tool.js +57 -32
- package/dist/tools/lease-hint.d.ts +17 -0
- package/dist/tools/lease-hint.js +24 -0
- package/dist/tools/lease-tools.js +6 -5
- package/dist/tools/merge-tools.d.ts +10 -1
- package/dist/tools/merge-tools.js +9 -3
- package/dist/tools/merged-name-redirect.d.ts +13 -0
- package/dist/tools/merged-name-redirect.js +55 -0
- package/dist/tools/navigate-result.d.ts +17 -0
- package/dist/tools/navigate-result.js +31 -0
- package/dist/tools/observe-tools.js +54 -20
- package/dist/tools/observed-nothing.d.ts +25 -0
- package/dist/tools/observed-nothing.js +33 -0
- package/dist/tools/query-paginate.js +2 -2
- package/dist/tools/query-shape.d.ts +18 -0
- package/dist/tools/query-shape.js +39 -0
- package/dist/tools/read-tools.js +81 -20
- package/dist/tools/real-input-attempt.d.ts +28 -0
- package/dist/tools/real-input-attempt.js +88 -0
- package/dist/tools/reconcile-tools.js +7 -7
- package/dist/tools/reload-result.d.ts +14 -0
- package/dist/tools/reload-result.js +29 -0
- package/dist/tools/snapshot-delta.d.ts +4 -5
- package/dist/tools/snapshot-delta.js +0 -0
- package/dist/tools/tool-kit.d.ts +8 -0
- package/dist/tools/tool-surface.d.ts +83 -0
- package/dist/tools/tool-surface.js +204 -0
- package/dist/tools/tools-helpers.js +6 -6
- package/dist/tools/tools.d.ts +15 -0
- package/dist/tools/tools.js +53 -17
- package/dist/tools/unadvertised-help.d.ts +5 -0
- package/dist/tools/unadvertised-help.js +39 -0
- package/dist/trace.d.ts +69 -0
- package/dist/trace.js +150 -0
- package/dist/update/nudge-credit.d.ts +4 -0
- package/dist/update/nudge-credit.js +53 -0
- package/dist/update/sdk-sync.d.ts +21 -0
- package/dist/update/sdk-sync.js +42 -0
- package/dist/update/update-checker.js +3 -3
- package/dist/update/update-nudge.d.ts +63 -6
- package/dist/update/update-nudge.js +128 -15
- package/dist/update/updater.d.ts +1 -9
- package/dist/update/updater.js +13 -8
- package/dist/version/peer-announce.d.ts +4 -0
- package/dist/version/peer-announce.js +30 -0
- package/dist/{server-version.js → version/server-version.js} +5 -1
- package/dist/version/version-nudge.d.ts +28 -0
- package/dist/version/version-nudge.js +40 -0
- package/dist/version/version-skew.d.ts +66 -0
- package/dist/version/version-skew.js +71 -0
- package/dist/visual/visual-diff.js +2 -2
- package/dist/visual/visual-tools.js +4 -4
- package/docs/agent-cheatsheet.md +85 -0
- package/docs/architecture.md +113 -0
- package/docs/benchmarks.md +255 -0
- package/docs/debugging.md +102 -0
- package/docs/deploy-checks.md +69 -0
- package/docs/desktop-apps.md +256 -0
- package/docs/enterprise.md +62 -0
- package/docs/fixtures.md +28 -0
- package/docs/flows.md +166 -0
- package/docs/getting-started.md +469 -0
- package/docs/human-control.md +63 -0
- package/docs/integration-patterns.md +171 -0
- package/docs/local-registry.md +126 -0
- package/docs/mint.json +61 -0
- package/docs/multi-agent-testing.md +55 -0
- package/docs/platform-integration.md +122 -0
- package/docs/telemetry-contract.md +214 -0
- package/docs/telemetry.md +184 -0
- package/docs/testing.md +82 -0
- package/docs/token-efficiency.md +80 -0
- package/docs/usage.md +1046 -0
- package/package.json +8 -5
- package/dist/cli-launch.js +0 -112
- package/dist/daemon-resilience.d.ts +0 -22
- package/dist/daemon-resilience.js +0 -85
- package/dist/mcp-proxy.d.ts +0 -67
- package/dist/mcp-proxy.js +0 -337
- package/dist/tools/profiles.d.ts +0 -37
- package/dist/tools/profiles.js +0 -139
- /package/dist/{pairing-token.d.ts → bridge/pairing-token.d.ts} +0 -0
- /package/dist/{token-auth.d.ts → bridge/token-auth.d.ts} +0 -0
- /package/dist/{token-auth.js → bridge/token-auth.js} +0 -0
- /package/dist/{cli-doctor.d.ts → cli/cli-doctor.d.ts} +0 -0
- /package/dist/{cli-verify.d.ts → cli/cli-verify.d.ts} +0 -0
- /package/dist/{cloud-cli.d.ts → cli/cloud-cli.d.ts} +0 -0
- /package/dist/{server-version.d.ts → version/server-version.d.ts} +0 -0
package/dist/init/next-patch.js
CHANGED
|
@@ -7,14 +7,14 @@
|
|
|
7
7
|
*/
|
|
8
8
|
import { PatchKind } from './patch-kind.js';
|
|
9
9
|
const RETICLE_NEXT_PACKAGE = '@reticlehq/next';
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
const NEXT_CONFIG_IMPORT = `import { withReticle } from '${RETICLE_NEXT_PACKAGE}';`;
|
|
11
|
+
const NEXT_CONFIG_REQUIRE = `const { withReticle } = require('${RETICLE_NEXT_PACKAGE}');`;
|
|
12
12
|
const RETICLE_DEV_COMPONENT = 'ReticleDev';
|
|
13
13
|
const RETICLE_DEV_BASENAME = 'reticle-dev';
|
|
14
14
|
/** Default import specifier: the component sits beside the file importing it (App Router). */
|
|
15
15
|
const RETICLE_DEV_SIBLING = `./${RETICLE_DEV_BASENAME}`;
|
|
16
16
|
const reticleDevImport = (specifier) => `import { ${RETICLE_DEV_COMPONENT} } from '${specifier}';`;
|
|
17
|
-
|
|
17
|
+
const RETICLE_DEV_IMPORT = reticleDevImport(RETICLE_DEV_SIBLING);
|
|
18
18
|
/**
|
|
19
19
|
* Decide where the connect component lives, from the file that will mount it.
|
|
20
20
|
*
|
|
@@ -31,11 +31,11 @@ export const RETICLE_DEV_IMPORT = reticleDevImport(RETICLE_DEV_SIBLING);
|
|
|
31
31
|
export function reticleDevLocation(mountPath, typescript) {
|
|
32
32
|
const ext = typescript ? '.tsx' : '.jsx';
|
|
33
33
|
const slash = mountPath.lastIndexOf('/');
|
|
34
|
-
const dir =
|
|
34
|
+
const dir = -1 === slash ? '' : mountPath.slice(0, slash);
|
|
35
35
|
const isPagesRouter = /(^|\/)pages$/.test(dir);
|
|
36
36
|
if (!isPagesRouter) {
|
|
37
37
|
return {
|
|
38
|
-
path: `${
|
|
38
|
+
path: `${'' === dir ? '' : `${dir}/`}${RETICLE_DEV_BASENAME}${ext}`,
|
|
39
39
|
importSpecifier: RETICLE_DEV_SIBLING,
|
|
40
40
|
};
|
|
41
41
|
}
|
|
@@ -48,26 +48,116 @@ export function reticleDevLocation(mountPath, typescript) {
|
|
|
48
48
|
}
|
|
49
49
|
/** The dev-guarded mount. Production strips it — `process.env.NODE_ENV` is inlined at build time. */
|
|
50
50
|
const RETICLE_DEV_MOUNT = `{process.env.NODE_ENV === 'development' ? <${RETICLE_DEV_COMPONENT} /> : null}`;
|
|
51
|
-
/**
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
51
|
+
/**
|
|
52
|
+
* `export default ` / `module.exports = ` at the START of a line — the head of the assignment, not
|
|
53
|
+
* the whole statement. Where the exported expression ENDS is decided by `expressionEnd` below.
|
|
54
|
+
*
|
|
55
|
+
* These used to be `/…([\s\S]+?);?\s*$/`, which reads as "the expression, lazily". It is not: with
|
|
56
|
+
* no `m` flag the `$` is end-of-FILE and the trailing `;?\s*` is satisfiable only there, so the
|
|
57
|
+
* capture always ran to the last non-blank character of the file. Every config whose export was not
|
|
58
|
+
* the final statement got everything after it swallowed into the wrap. On a config exporting
|
|
59
|
+
* conditionally that produced an unbalanced paren — a syntax error, so `next dev` exited 1 while
|
|
60
|
+
* `init` reported the step as ✓ and the only symptom was "dev server never served".
|
|
61
|
+
*/
|
|
62
|
+
const ESM_DEFAULT_HEAD = /^[ \t]*export[ \t]+default[ \t]+/gm;
|
|
63
|
+
const CJS_EXPORT_HEAD = /^[ \t]*module\.exports[ \t]*=[ \t]*/gm;
|
|
55
64
|
/** The opening `<body ...>` tag, whose first child is where the mount goes. */
|
|
56
65
|
const BODY_OPEN_TAG = /<body(\s[^>]*)?>/g;
|
|
57
66
|
const NO_EXPORT_REASON = "couldn't find an `export default` or `module.exports` to wrap";
|
|
58
67
|
const NO_BODY_REASON = "couldn't find a single <body> tag to mount <ReticleDev /> inside";
|
|
68
|
+
/** Bracket pairs that keep an expression open. A `;` at depth 0 is what ends it. */
|
|
69
|
+
const OPENERS = '([{';
|
|
70
|
+
const CLOSERS = ')]}';
|
|
71
|
+
const LINE_COMMENT = '//';
|
|
72
|
+
const BLOCK_COMMENT_OPEN = '/*';
|
|
73
|
+
const BLOCK_COMMENT_CLOSE = '*/';
|
|
74
|
+
const QUOTES = '\'"`';
|
|
75
|
+
/**
|
|
76
|
+
* Index just past the exported expression that starts at `from` — the `;` that closes it, or end of
|
|
77
|
+
* file. Tracks bracket depth so a multi-line object or a nested call ends in the right place, and
|
|
78
|
+
* skips strings and comments so a `;` or a brace inside one cannot end it early.
|
|
79
|
+
*
|
|
80
|
+
* Deliberately a scanner and not a parser: `next.config.*` is arbitrary JS and this file's contract
|
|
81
|
+
* is to recognise the obvious shape or bail. It only has to be right about where ONE expression
|
|
82
|
+
* stops, and wrong is caught by the caller bailing to manual, never by a half-edit.
|
|
83
|
+
*/
|
|
84
|
+
function expressionEnd(source, from) {
|
|
85
|
+
let depth = 0;
|
|
86
|
+
for (let i = from; i < source.length; i++) {
|
|
87
|
+
const ch = source[i] ?? '';
|
|
88
|
+
const pair = source.slice(i, i + 2);
|
|
89
|
+
if (pair === LINE_COMMENT) {
|
|
90
|
+
const nl = source.indexOf('\n', i);
|
|
91
|
+
if (-1 === nl)
|
|
92
|
+
return source.length;
|
|
93
|
+
i = nl;
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
if (pair === BLOCK_COMMENT_OPEN) {
|
|
97
|
+
const close = source.indexOf(BLOCK_COMMENT_CLOSE, i + 2);
|
|
98
|
+
i = -1 === close ? source.length : close + 1;
|
|
99
|
+
continue;
|
|
100
|
+
}
|
|
101
|
+
if (QUOTES.includes(ch)) {
|
|
102
|
+
for (i++; i < source.length; i++) {
|
|
103
|
+
if ('\\' === source[i])
|
|
104
|
+
i++;
|
|
105
|
+
else if (source[i] === ch)
|
|
106
|
+
break;
|
|
107
|
+
}
|
|
108
|
+
continue;
|
|
109
|
+
}
|
|
110
|
+
if (OPENERS.includes(ch))
|
|
111
|
+
depth++;
|
|
112
|
+
else if (CLOSERS.includes(ch)) {
|
|
113
|
+
// A closer at depth 0 belongs to an enclosing block, so the expression ended before it.
|
|
114
|
+
if (0 === depth)
|
|
115
|
+
return i;
|
|
116
|
+
depth--;
|
|
117
|
+
}
|
|
118
|
+
else if (';' === ch && 0 === depth)
|
|
119
|
+
return i;
|
|
120
|
+
}
|
|
121
|
+
return source.length;
|
|
122
|
+
}
|
|
123
|
+
/** Every top-level export assignment in the file, in source order. */
|
|
124
|
+
function exportSites(source, head) {
|
|
125
|
+
const sites = [];
|
|
126
|
+
for (const match of source.matchAll(head)) {
|
|
127
|
+
if (match.index === undefined)
|
|
128
|
+
continue;
|
|
129
|
+
const start = match.index + match[0].length;
|
|
130
|
+
sites.push({ start, end: expressionEnd(source, start) });
|
|
131
|
+
}
|
|
132
|
+
return sites;
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Wrap every listed expression in `withReticle(...)`, leaving every other byte of the file alone.
|
|
136
|
+
*
|
|
137
|
+
* All of them, not just the first: a config can export CONDITIONALLY — Sentry-wrapped in one branch,
|
|
138
|
+
* plain in the other — and which branch runs is an environment variable's business, not ours.
|
|
139
|
+
* Wrapping each assignment is correct whichever one executes, and it is what turns that shape from a
|
|
140
|
+
* manual step (an app that boots and never connects) into a working install.
|
|
141
|
+
*
|
|
142
|
+
* Applied back-to-front so each splice leaves the earlier offsets valid.
|
|
143
|
+
*/
|
|
144
|
+
function wrapAll(source, sites) {
|
|
145
|
+
let out = source;
|
|
146
|
+
for (const site of [...sites].sort((a, b) => b.start - a.start)) {
|
|
147
|
+
out = `${out.slice(0, site.start)}withReticle(${out.slice(site.start, site.end)})${out.slice(site.end)}`;
|
|
148
|
+
}
|
|
149
|
+
return out;
|
|
150
|
+
}
|
|
59
151
|
export function patchNextConfig(source) {
|
|
60
152
|
if (source.includes(RETICLE_NEXT_PACKAGE))
|
|
61
153
|
return { kind: PatchKind.ALREADY };
|
|
62
|
-
const esm =
|
|
63
|
-
if (esm
|
|
64
|
-
|
|
65
|
-
return { kind: PatchKind.APPLY, code: `${NEXT_CONFIG_IMPORT}\n${wrapped}` };
|
|
154
|
+
const esm = exportSites(source, ESM_DEFAULT_HEAD);
|
|
155
|
+
if (esm.length > 0) {
|
|
156
|
+
return { kind: PatchKind.APPLY, code: `${NEXT_CONFIG_IMPORT}\n${wrapAll(source, esm)}` };
|
|
66
157
|
}
|
|
67
|
-
const cjs =
|
|
68
|
-
if (cjs
|
|
69
|
-
|
|
70
|
-
return { kind: PatchKind.APPLY, code: `${NEXT_CONFIG_REQUIRE}\n${wrapped}` };
|
|
158
|
+
const cjs = exportSites(source, CJS_EXPORT_HEAD);
|
|
159
|
+
if (cjs.length > 0) {
|
|
160
|
+
return { kind: PatchKind.APPLY, code: `${NEXT_CONFIG_REQUIRE}\n${wrapAll(source, cjs)}` };
|
|
71
161
|
}
|
|
72
162
|
return { kind: PatchKind.MANUAL, reason: NO_EXPORT_REASON };
|
|
73
163
|
}
|
|
@@ -84,7 +174,7 @@ export function patchPagesApp(source, importSpecifier = RETICLE_DEV_SIBLING) {
|
|
|
84
174
|
if (source.includes(RETICLE_DEV_COMPONENT))
|
|
85
175
|
return { kind: PatchKind.ALREADY };
|
|
86
176
|
const matches = [...source.matchAll(PAGES_APP_COMPONENT)];
|
|
87
|
-
const match = matches.length
|
|
177
|
+
const match = 1 === matches.length ? matches[0] : undefined;
|
|
88
178
|
if (match?.index === undefined)
|
|
89
179
|
return { kind: PatchKind.MANUAL, reason: NO_PAGES_COMPONENT_REASON };
|
|
90
180
|
const wrapped = `<>${RETICLE_DEV_MOUNT}${match[0]}</>`;
|
|
@@ -97,7 +187,7 @@ export function patchRootLayout(source) {
|
|
|
97
187
|
const tags = [...source.matchAll(BODY_OPEN_TAG)];
|
|
98
188
|
// Exactly one <body> or we cannot tell which one actually renders — and mounting into the wrong
|
|
99
189
|
// one is the same silent no-connect as not mounting at all.
|
|
100
|
-
const tag = tags.length
|
|
190
|
+
const tag = 1 === tags.length ? tags[0] : undefined;
|
|
101
191
|
if (tag?.index === undefined)
|
|
102
192
|
return { kind: PatchKind.MANUAL, reason: NO_BODY_REASON };
|
|
103
193
|
const insertAt = tag.index + tag[0].length;
|
package/dist/init/node-io.js
CHANGED
|
@@ -4,9 +4,27 @@
|
|
|
4
4
|
* command, not the MCP stdio transport.
|
|
5
5
|
*/
|
|
6
6
|
import { readFileSync, writeFileSync, existsSync, mkdirSync, readdirSync, statSync } from 'node:fs';
|
|
7
|
+
import { NodePlatform } from '../platform.js';
|
|
7
8
|
import { join, dirname, isAbsolute } from 'node:path';
|
|
8
9
|
import { homedir } from 'node:os';
|
|
9
10
|
import { spawnSync } from 'node:child_process';
|
|
11
|
+
/**
|
|
12
|
+
* `shell: true` ONLY where it earns its keep.
|
|
13
|
+
*
|
|
14
|
+
* It exists so package-manager shims (`pnpm.cmd`, `npx.cmd`) resolve on Windows. On POSIX it buys
|
|
15
|
+
* nothing and costs correctness: under a shell, arguments are re-parsed, so a path containing a
|
|
16
|
+
* space — `/Users/ada/My Projects/app` — silently becomes two arguments and registration fails with
|
|
17
|
+
* no error anyone can read.
|
|
18
|
+
*/
|
|
19
|
+
function shellOpt() {
|
|
20
|
+
return NodePlatform.WINDOWS === process.platform ? { shell: true } : {};
|
|
21
|
+
}
|
|
22
|
+
/** Under a shell, quote what the shell would otherwise split. Windows only, where shell is required. */
|
|
23
|
+
function shellSafe(args) {
|
|
24
|
+
if (process.platform !== NodePlatform.WINDOWS)
|
|
25
|
+
return [...args];
|
|
26
|
+
return args.map((arg) => (/[\s"]/.test(arg) ? `"${arg.replace(/"/g, '\\"')}"` : arg));
|
|
27
|
+
}
|
|
10
28
|
export function buildNodeIo(cwd) {
|
|
11
29
|
// Project-relative by default; absolute paths (e.g. ~/.cursor/mcp.json) pass through unchanged.
|
|
12
30
|
const abs = (rel) => (isAbsolute(rel) ? rel : join(cwd, rel));
|
|
@@ -64,15 +82,14 @@ export function buildNodeIo(cwd) {
|
|
|
64
82
|
return buildNodeIo(abs(rel));
|
|
65
83
|
},
|
|
66
84
|
exec(command, args) {
|
|
67
|
-
//
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
return result.status === 0;
|
|
85
|
+
// Inherit stdio so the install's own progress is visible to the user.
|
|
86
|
+
const result = spawnSync(command, shellSafe(args), { cwd, stdio: 'inherit', ...shellOpt() });
|
|
87
|
+
return 0 === result.status;
|
|
71
88
|
},
|
|
72
89
|
probe(command, args) {
|
|
73
90
|
// Quiet yes/no check (CLI availability, existing registration). Never throws.
|
|
74
|
-
const result = spawnSync(command,
|
|
75
|
-
return result.status
|
|
91
|
+
const result = spawnSync(command, shellSafe(args), { cwd, stdio: 'ignore', ...shellOpt() });
|
|
92
|
+
return 0 === result.status;
|
|
76
93
|
},
|
|
77
94
|
print(line) {
|
|
78
95
|
process.stdout.write(`${line}\n`);
|
|
@@ -16,7 +16,6 @@ export declare const VITE_PLUGIN_DETAIL: {
|
|
|
16
16
|
*/
|
|
17
17
|
readonly SVELTEKIT: "add reticle() to plugins (stamps data-reticle-source in .svelte components)";
|
|
18
18
|
};
|
|
19
|
-
export declare const CAPABILITIES_TITLE = "Capabilities + store";
|
|
20
19
|
export declare function viteSteps(input: PlanInput, detail?: string): Step[];
|
|
21
20
|
/**
|
|
22
21
|
* Next used to be the ONLY stack with hand edits left over — and both of them fail silently when
|
|
@@ -32,4 +31,20 @@ export declare function nextSteps(input: PlanInput): Step[];
|
|
|
32
31
|
* wiring is real and may well work; what is missing is anything that would tell us when it stops.
|
|
33
32
|
* Silently emitting it reads as a support claim, which is the thing this project exists to not do.
|
|
34
33
|
*/
|
|
34
|
+
/**
|
|
35
|
+
* Create React App: the connect goes in `src/index.tsx`, the token in `.env.development.local`.
|
|
36
|
+
*
|
|
37
|
+
* The previous plan pointed at `index.html`, which cannot work — CRA's is a static template the
|
|
38
|
+
* bundler never processes for modules. Reported from a real cra-redux-saga app.
|
|
39
|
+
*/
|
|
40
|
+
export declare function craSteps(input: PlanInput): Step[];
|
|
35
41
|
export declare function svelteKitSteps(input: PlanInput): Step[];
|
|
42
|
+
/**
|
|
43
|
+
* Astro: the config define + build target, and the connect script in ONE layout.
|
|
44
|
+
*
|
|
45
|
+
* Astro was the last gated stack left printing a recipe it did not apply. It still falls back to the
|
|
46
|
+
* printed one whenever the choice is not obvious — no config, no single layout, or a shape the
|
|
47
|
+
* patchers do not fully recognise — because which page or layout to instrument is a real decision
|
|
48
|
+
* and a half-edited build config is worse than a documented manual step.
|
|
49
|
+
*/
|
|
50
|
+
export declare function astroSteps(input: PlanInput): Step[];
|
|
@@ -5,8 +5,10 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import { patchViteConfig, VitePatchKind } from './vite-config.js';
|
|
7
7
|
import { patchNextConfig, patchRootLayout, patchPagesApp } from './next-patch.js';
|
|
8
|
+
import { patchAstroConfig, patchAstroLayout } from './astro-patch.js';
|
|
9
|
+
import { CRA_DEV_MODULE_IMPORT, CRA_DEV_MODULE_PATH, CRA_ENV_PATH, TOKEN_VAR, craDevModuleFile, craEnvPatch, craImportPatch, } from './cra.js';
|
|
8
10
|
import { PatchKind } from './patch-kind.js';
|
|
9
|
-
import { viteManual, NEXT_LAYOUT_MANUAL, NEXT_LAYOUT_PATH, viteDevModuleFile, VITE_DEV_MODULE_PATH, nextReticleDevFile, NEXT_RETICLE_DEV_PATH, nextConfigManual, svelteKitHooksFile, SVELTEKIT_HOOKS_PATH, UNVERIFIED_FRAMEWORK_NOTE, } from './snippets.js';
|
|
11
|
+
import { viteManual, NEXT_LAYOUT_MANUAL, NEXT_LAYOUT_PATH, viteDevModuleFile, VITE_DEV_MODULE_PATH, nextReticleDevFile, NEXT_RETICLE_DEV_PATH, nextConfigManual, svelteKitHooksFile, SVELTEKIT_HOOKS_PATH, UNVERIFIED_FRAMEWORK_NOTE, astroManual, } from './snippets.js';
|
|
10
12
|
import { StepStatus } from './plan.js';
|
|
11
13
|
/** What adding `reticle()` to a Vite config buys, which differs by framework. */
|
|
12
14
|
export const VITE_PLUGIN_DETAIL = {
|
|
@@ -20,7 +22,7 @@ export const VITE_PLUGIN_DETAIL = {
|
|
|
20
22
|
*/
|
|
21
23
|
SVELTEKIT: 'add reticle() to plugins (stamps data-reticle-source in .svelte components)',
|
|
22
24
|
};
|
|
23
|
-
|
|
25
|
+
const CAPABILITIES_TITLE = 'Capabilities + store';
|
|
24
26
|
/**
|
|
25
27
|
* The dev module carrying `registerCapabilities` / `registerStore`.
|
|
26
28
|
*
|
|
@@ -29,7 +31,7 @@ export const CAPABILITIES_TITLE = 'Capabilities + store';
|
|
|
29
31
|
* only when absent, because it is the one generated file a user is expected to EDIT.
|
|
30
32
|
*/
|
|
31
33
|
function capabilitiesStep(input) {
|
|
32
|
-
if (input.viteDevModuleExists
|
|
34
|
+
if (true === input.viteDevModuleExists) {
|
|
33
35
|
return [
|
|
34
36
|
{
|
|
35
37
|
title: CAPABILITIES_TITLE,
|
|
@@ -41,7 +43,9 @@ function capabilitiesStep(input) {
|
|
|
41
43
|
}
|
|
42
44
|
const testids = input.testids ?? [];
|
|
43
45
|
const stores = input.storeHints ?? [];
|
|
44
|
-
const found = testids.length > 0
|
|
46
|
+
const found = testids.length > 0
|
|
47
|
+
? `${String(testids.length)} data-testid values`
|
|
48
|
+
: 'no data-testid values yet';
|
|
45
49
|
return [
|
|
46
50
|
{
|
|
47
51
|
title: CAPABILITIES_TITLE,
|
|
@@ -61,7 +65,7 @@ export function viteSteps(input, detail = VITE_PLUGIN_DETAIL.VITE) {
|
|
|
61
65
|
function viteConfigSteps(input, detail) {
|
|
62
66
|
const cfg = input.viteConfig;
|
|
63
67
|
const port = input.options.port;
|
|
64
|
-
if (
|
|
68
|
+
if (null === cfg) {
|
|
65
69
|
return [
|
|
66
70
|
{
|
|
67
71
|
title: 'Vite plugin',
|
|
@@ -154,14 +158,14 @@ export function nextSteps(input) {
|
|
|
154
158
|
},
|
|
155
159
|
dependsOnInstall: true,
|
|
156
160
|
};
|
|
157
|
-
const configPatch = input.nextConfigSource
|
|
161
|
+
const configPatch = null === input.nextConfigSource || input.nextConfigSource === undefined
|
|
158
162
|
? { kind: PatchKind.MANUAL, reason: `no ${configFile} found` }
|
|
159
163
|
: patchNextConfig(input.nextConfigSource);
|
|
160
164
|
const layout = input.nextLayout ?? null;
|
|
161
165
|
// Pages Router mounts through pages/_app, App Router through the root layout — different edits,
|
|
162
166
|
// and picking by path is what stops a Pages app being handed the layout patch that cannot apply.
|
|
163
167
|
const isPagesRouter = layout !== null && /(^|\/)pages\/_app\.[jt]sx?$/.test(layout.path);
|
|
164
|
-
const layoutPatch =
|
|
168
|
+
const layoutPatch = null === layout
|
|
165
169
|
? { kind: PatchKind.MANUAL, reason: 'no root layout (app/layout.tsx) or pages/_app found' }
|
|
166
170
|
: isPagesRouter
|
|
167
171
|
? patchPagesApp(layout.source, input.nextReticleDevImport)
|
|
@@ -180,6 +184,79 @@ export function nextSteps(input) {
|
|
|
180
184
|
* wiring is real and may well work; what is missing is anything that would tell us when it stops.
|
|
181
185
|
* Silently emitting it reads as a support claim, which is the thing this project exists to not do.
|
|
182
186
|
*/
|
|
187
|
+
/**
|
|
188
|
+
* Create React App: the connect goes in `src/index.tsx`, the token in `.env.development.local`.
|
|
189
|
+
*
|
|
190
|
+
* The previous plan pointed at `index.html`, which cannot work — CRA's is a static template the
|
|
191
|
+
* bundler never processes for modules. Reported from a real cra-redux-saga app.
|
|
192
|
+
*/
|
|
193
|
+
export function craSteps(input) {
|
|
194
|
+
const entry = input.craEntry ?? null;
|
|
195
|
+
const steps = [
|
|
196
|
+
{
|
|
197
|
+
title: 'Reticle connect module',
|
|
198
|
+
target: CRA_DEV_MODULE_PATH,
|
|
199
|
+
status: StepStatus.APPLY,
|
|
200
|
+
detail: 'create the dev-only connect (CRA cannot inject through public/index.html)',
|
|
201
|
+
write: {
|
|
202
|
+
path: CRA_DEV_MODULE_PATH,
|
|
203
|
+
content: craDevModuleFile(input.options.port, input.options.projectId),
|
|
204
|
+
},
|
|
205
|
+
dependsOnInstall: true,
|
|
206
|
+
},
|
|
207
|
+
];
|
|
208
|
+
const token = input.pairingToken ?? '';
|
|
209
|
+
const env = craEnvPatch(input.craEnv ?? null, token);
|
|
210
|
+
if (env !== null) {
|
|
211
|
+
steps.push({
|
|
212
|
+
title: 'Pairing token',
|
|
213
|
+
target: CRA_ENV_PATH,
|
|
214
|
+
status: StepStatus.APPLY,
|
|
215
|
+
// REACT_APP_* is the only thing CRA inlines into browser code; without the token the bridge
|
|
216
|
+
// refuses the connection and no session appears. Say the file is gitignored HERE, at the one
|
|
217
|
+
// moment someone is looking: the token is per-machine and cannot travel, so every teammate
|
|
218
|
+
// has to run init once or their clone is dead with no explanation.
|
|
219
|
+
detail: `set ${TOKEN_VAR} (the only channel CRA inlines) — ${CRA_ENV_PATH} is gitignored, so each teammate must run \`reticle init\` on their own machine`,
|
|
220
|
+
write: { path: CRA_ENV_PATH, content: env },
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
else if ('' === token) {
|
|
224
|
+
// No daemon has ever run here, so there is no token to inline. Omitting the step entirely made
|
|
225
|
+
// init report all-green for an app that could never pair.
|
|
226
|
+
steps.push({
|
|
227
|
+
title: 'Pairing token',
|
|
228
|
+
target: CRA_ENV_PATH,
|
|
229
|
+
status: StepStatus.MANUAL,
|
|
230
|
+
detail: `no pairing token yet — run \`reticle start\`, then \`reticle init\` again to write ${TOKEN_VAR}`,
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
if (null === entry) {
|
|
234
|
+
steps.push({
|
|
235
|
+
title: 'Connect snippet (CRA)',
|
|
236
|
+
target: 'src/index.tsx',
|
|
237
|
+
status: StepStatus.MANUAL,
|
|
238
|
+
detail: `Add \`${CRA_DEV_MODULE_IMPORT}\` to your app entry (src/index.tsx or src/index.js), after the existing imports.`,
|
|
239
|
+
});
|
|
240
|
+
return steps;
|
|
241
|
+
}
|
|
242
|
+
const patched = craImportPatch(entry.source);
|
|
243
|
+
steps.push(null === patched
|
|
244
|
+
? {
|
|
245
|
+
title: 'Connect snippet (CRA)',
|
|
246
|
+
target: entry.path,
|
|
247
|
+
status: StepStatus.ALREADY,
|
|
248
|
+
detail: 'already imported',
|
|
249
|
+
}
|
|
250
|
+
: {
|
|
251
|
+
title: 'Connect snippet (CRA)',
|
|
252
|
+
target: entry.path,
|
|
253
|
+
status: StepStatus.APPLY,
|
|
254
|
+
detail: 'import the dev-only connect module',
|
|
255
|
+
write: { path: entry.path, content: patched },
|
|
256
|
+
dependsOnInstall: true,
|
|
257
|
+
});
|
|
258
|
+
return steps;
|
|
259
|
+
}
|
|
183
260
|
export function svelteKitSteps(input) {
|
|
184
261
|
const unverified = {
|
|
185
262
|
title: 'SvelteKit is UNVERIFIED',
|
|
@@ -189,7 +266,7 @@ export function svelteKitSteps(input) {
|
|
|
189
266
|
};
|
|
190
267
|
// SvelteKit can't use the Vite-plugin injection (it renders via app.html) — wire a client hook
|
|
191
268
|
// that SvelteKit runs on startup, which is the path that can register a session at all.
|
|
192
|
-
if (input.svelteKitHooksExists
|
|
269
|
+
if (true === input.svelteKitHooksExists) {
|
|
193
270
|
return [
|
|
194
271
|
unverified,
|
|
195
272
|
{
|
|
@@ -215,3 +292,50 @@ export function svelteKitSteps(input) {
|
|
|
215
292
|
},
|
|
216
293
|
];
|
|
217
294
|
}
|
|
295
|
+
/**
|
|
296
|
+
* Astro: the config define + build target, and the connect script in ONE layout.
|
|
297
|
+
*
|
|
298
|
+
* Astro was the last gated stack left printing a recipe it did not apply. It still falls back to the
|
|
299
|
+
* printed one whenever the choice is not obvious — no config, no single layout, or a shape the
|
|
300
|
+
* patchers do not fully recognise — because which page or layout to instrument is a real decision
|
|
301
|
+
* and a half-edited build config is worse than a documented manual step.
|
|
302
|
+
*/
|
|
303
|
+
export function astroSteps(input) {
|
|
304
|
+
const config = input.astroConfig ?? null;
|
|
305
|
+
const layout = input.astroLayout ?? null;
|
|
306
|
+
const manual = astroManual(input.options.port, input.options.projectId, layout?.path);
|
|
307
|
+
if (null === config || null === layout) {
|
|
308
|
+
return [
|
|
309
|
+
{
|
|
310
|
+
title: 'Connect snippet (Astro)',
|
|
311
|
+
// Name what is actually there. `astro.config + layout` pointed at a layout this project may
|
|
312
|
+
// not have — reported on a fixture with only src/pages/index.astro.
|
|
313
|
+
target: null === layout ? 'astro.config + a page (no layout found)' : 'astro.config + layout',
|
|
314
|
+
status: StepStatus.MANUAL,
|
|
315
|
+
detail: manual,
|
|
316
|
+
},
|
|
317
|
+
];
|
|
318
|
+
}
|
|
319
|
+
// ATOMIC. The connect snippet is useless without the config: the token is inlined by the config,
|
|
320
|
+
// so a layout patched on its own gives an app that dials the bridge and is refused. Measured on a
|
|
321
|
+
// real fixture — config ⚠, layout ✓ — which reads as one step done and one caveat when it is
|
|
322
|
+
// actually a guaranteed non-connection. If either half cannot be applied, BOTH go manual with the
|
|
323
|
+
// single recipe that does the whole job.
|
|
324
|
+
const manualWithLayout = astroManual(input.options.port, input.options.projectId, layout.path);
|
|
325
|
+
const configPatch = patchAstroConfig(config.source);
|
|
326
|
+
const layoutPatch = patchAstroLayout(layout.source, input.options.port, input.options.projectId);
|
|
327
|
+
if (configPatch.kind === PatchKind.MANUAL || layoutPatch.kind === PatchKind.MANUAL) {
|
|
328
|
+
return [
|
|
329
|
+
{
|
|
330
|
+
title: 'Connect snippet (Astro)',
|
|
331
|
+
target: `${config.path} + ${layout.path}`,
|
|
332
|
+
status: StepStatus.MANUAL,
|
|
333
|
+
detail: manualWithLayout,
|
|
334
|
+
},
|
|
335
|
+
];
|
|
336
|
+
}
|
|
337
|
+
return [
|
|
338
|
+
patchStep('Astro config (token + build target)', config.path, configPatch, 'inline the pairing token and raise build.target to es2022', manualWithLayout),
|
|
339
|
+
patchStep('Connect snippet (Astro)', layout.path, layoutPatch, 'add the dev-only connect <script> before </body>', manualWithLayout),
|
|
340
|
+
];
|
|
341
|
+
}
|
package/dist/init/plan.d.ts
CHANGED
|
@@ -14,10 +14,10 @@ import { Framework, type Detection } from './detect.js';
|
|
|
14
14
|
* irrelevant, and a skewed pair impossible to install by accident.
|
|
15
15
|
*/
|
|
16
16
|
export declare function pinnedPackages(packages: readonly string[], version: string | undefined): readonly string[];
|
|
17
|
-
/** The dev-dependencies `reticle init` installs for a given framework — kit first, build plugin next. */
|
|
18
|
-
export declare function frameworkPackages(framework: Framework): readonly string[];
|
|
19
17
|
/** Exported so the init telemetry can tell an MCP-registration failure from a dependency install. */
|
|
20
18
|
export declare const MCP_TARGET = "global (claude user scope)";
|
|
19
|
+
/** True when this step is what makes the app dial the daemon. */
|
|
20
|
+
export declare function isConnectStep(title: string): boolean;
|
|
21
21
|
/** The step that runs the package manager — the other thing that commonly fails on a user's machine. */
|
|
22
22
|
export declare const DEPS_TARGET = "package.json";
|
|
23
23
|
export declare const StepStatus: {
|
|
@@ -50,6 +50,20 @@ export interface Step {
|
|
|
50
50
|
args: string[];
|
|
51
51
|
fallback: string;
|
|
52
52
|
};
|
|
53
|
+
/**
|
|
54
|
+
* A second, weaker attempt to run when `exec` fails, with what to tell the user if it succeeds.
|
|
55
|
+
*
|
|
56
|
+
* The pinned install is refused outright by pnpm's `minimumReleaseAge` for as long as its window
|
|
57
|
+
* lasts — so for ~48 hours after every release, a project with that setting could not install
|
|
58
|
+
* Reticle at all. An unpinned install still works there (it resolves the newest MATURE version), so
|
|
59
|
+
* the fallback trades an exact version for a working install and says which it did. It must never
|
|
60
|
+
* be silent: an older SDK against a newer daemon is the skew this pin exists to prevent.
|
|
61
|
+
*/
|
|
62
|
+
retry?: {
|
|
63
|
+
command: string;
|
|
64
|
+
args: string[];
|
|
65
|
+
note: string;
|
|
66
|
+
};
|
|
53
67
|
/**
|
|
54
68
|
* This step wires the app to a package the install step provides. If that install fails, applying
|
|
55
69
|
* it anyway leaves the app importing a module that is not there — `next.config.ts` importing
|
|
@@ -81,6 +95,22 @@ export interface PlanInput {
|
|
|
81
95
|
path: string;
|
|
82
96
|
source: string;
|
|
83
97
|
} | null;
|
|
98
|
+
/** Discovered Astro config: its path + source, or null if none found. */
|
|
99
|
+
astroConfig?: {
|
|
100
|
+
path: string;
|
|
101
|
+
source: string;
|
|
102
|
+
} | null | undefined;
|
|
103
|
+
/**
|
|
104
|
+
* The single layout to instrument, or null when the choice is not obvious.
|
|
105
|
+
*
|
|
106
|
+
* WHICH page or layout to instrument is a real decision — so `init` only makes it when there is
|
|
107
|
+
* exactly one candidate. Zero or several falls back to the printed recipe rather than guessing at
|
|
108
|
+
* the file every page of the user's site inherits from.
|
|
109
|
+
*/
|
|
110
|
+
astroLayout?: {
|
|
111
|
+
path: string;
|
|
112
|
+
source: string;
|
|
113
|
+
} | null | undefined;
|
|
84
114
|
/** Discovered Next config filename (e.g. 'next.config.mjs'), or null. */
|
|
85
115
|
nextConfigFile: string | null;
|
|
86
116
|
/** Source of that Next config, so the export can be wrapped in withReticle. */
|
|
@@ -104,18 +134,33 @@ export interface PlanInput {
|
|
|
104
134
|
viteDevModuleExists?: boolean | undefined;
|
|
105
135
|
/** Whether src/hooks.client.ts already exists (SvelteKit idempotency). */
|
|
106
136
|
svelteKitHooksExists?: boolean;
|
|
137
|
+
/** CRA's bundled entry (src/index.tsx or .js) — where the connect import has to go. */
|
|
138
|
+
craEntry?: {
|
|
139
|
+
path: string;
|
|
140
|
+
source: string;
|
|
141
|
+
} | null;
|
|
142
|
+
/** Existing .env.development.local, so an unrelated variable in it survives. */
|
|
143
|
+
craEnv?: string | null;
|
|
144
|
+
/** The daemon's pairing token, inlined for CRA through the one channel it supports. */
|
|
145
|
+
pairingToken?: string;
|
|
107
146
|
/** Whether .reticle.json already exists in the project root (idempotency). */
|
|
108
147
|
reticleConfigExists?: boolean;
|
|
109
148
|
/** Current project-root CLAUDE.md content (for the idempotent agent-rule merge), or null/undefined. */
|
|
110
149
|
claudeMdContent?: string | null | undefined;
|
|
111
150
|
/** Current project-root AGENTS.md content (cross-agent fallback rule), or null/undefined. */
|
|
112
151
|
agentsMdContent?: string | null | undefined;
|
|
113
|
-
/**
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
152
|
+
/**
|
|
153
|
+
* Current .cursor/rules/reticle.mdc content, or null when absent.
|
|
154
|
+
*
|
|
155
|
+
* CONTENT, not existence. Gating on the file merely being there froze a Cursor project's rule at
|
|
156
|
+
* whatever release wrote it — so the CLAUDE.md path refreshed itself while the Cursor one never
|
|
157
|
+
* could, and a rule added later (`version_skew`) never reached a Cursor-only project at all.
|
|
158
|
+
*/
|
|
159
|
+
cursorRuleContent?: string | null | undefined;
|
|
160
|
+
/** Current .claude/commands/reticle.md content, or null when absent (slash-command idempotency). */
|
|
161
|
+
claudeCommandContent?: string | null | undefined;
|
|
162
|
+
/** Current .cursor/commands/reticle.md content, or null when absent. */
|
|
163
|
+
cursorCommandContent?: string | null | undefined;
|
|
119
164
|
options: {
|
|
120
165
|
port: number | undefined;
|
|
121
166
|
mcp: boolean;
|
|
@@ -126,4 +171,24 @@ export interface PlanInput {
|
|
|
126
171
|
sdkVersion?: string;
|
|
127
172
|
};
|
|
128
173
|
}
|
|
174
|
+
/**
|
|
175
|
+
* Every coding agent `reticle init` knows how to wire itself into, and the three surfaces it wires:
|
|
176
|
+
* the global MCP registration, the project rule file that makes the agent USE Reticle, and the
|
|
177
|
+
* `/reticle` command.
|
|
178
|
+
*
|
|
179
|
+
* One list, because those three surfaces used to enumerate Claude and Cursor separately in three
|
|
180
|
+
* places — so supporting a fourth agent meant finding all three and getting each right. Adding one
|
|
181
|
+
* is now an entry here plus its builders; each builder answers null when that agent is not present
|
|
182
|
+
* for this user or this project, which is also how "no agent detected" falls through to the
|
|
183
|
+
* cross-agent AGENTS.md.
|
|
184
|
+
*
|
|
185
|
+
* Deliberately functions rather than data: registering with Claude runs its CLI while Cursor merges
|
|
186
|
+
* a JSON file, and pretending those are the same shape would cost more than it saves.
|
|
187
|
+
*/
|
|
188
|
+
declare const AgentId: {
|
|
189
|
+
readonly CLAUDE: "claude";
|
|
190
|
+
readonly CURSOR: "cursor";
|
|
191
|
+
};
|
|
192
|
+
export type AgentId = (typeof AgentId)[keyof typeof AgentId];
|
|
129
193
|
export declare function buildPlan(input: PlanInput): Plan;
|
|
194
|
+
export {};
|