@reticlehq/server 2.12.0 → 2.13.1
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 +67 -109
- package/dist/bridge/auth-failure-reason.d.ts +6 -2
- package/dist/bridge/auth-failure-reason.js +15 -8
- package/dist/bridge/bridge.d.ts +18 -1
- package/dist/bridge/bridge.js +247 -164
- package/dist/bridge/pairing-token.d.ts +5 -0
- package/dist/bridge/pairing-token.js +28 -0
- package/dist/bridge/protocol-skew.d.ts +37 -0
- package/dist/bridge/protocol-skew.js +45 -0
- package/dist/capsule/capsule-store.d.ts +6 -6
- package/dist/capsule/causal-summary.js +7 -2
- package/dist/cli/cli-doctor.js +31 -1
- package/dist/cli/cli-launch.d.ts +11 -1
- package/dist/cli/cli-launch.js +59 -10
- package/dist/cli/cli-parse.d.ts +15 -1
- package/dist/cli/cli-parse.js +212 -8
- package/dist/cli/cli-verify.d.ts +1 -0
- package/dist/cli/cli-verify.js +3 -2
- package/dist/cli/cloud-cli.js +428 -259
- package/dist/cli/cloud-keystore.d.ts +37 -0
- package/dist/cli/cloud-keystore.js +97 -0
- package/dist/cli/cloud-kit.d.ts +37 -0
- package/dist/cli/cloud-kit.js +121 -0
- package/dist/cli/cloud-login.d.ts +17 -0
- package/dist/cli/cloud-login.js +183 -0
- package/dist/cli/cloud-session.d.ts +48 -0
- package/dist/cli/cloud-session.js +53 -0
- package/dist/cli/config-discovery.js +1 -0
- package/dist/cli/daemon-start-options.d.ts +32 -0
- package/dist/cli/daemon-start-options.js +38 -0
- package/dist/cli/device-flow.d.ts +76 -0
- package/dist/cli/device-flow.js +56 -0
- package/dist/cli/doctor-rows.d.ts +9 -0
- package/dist/cli/doctor-rows.js +9 -0
- package/dist/cli/drive-attach.d.ts +13 -0
- package/dist/cli/drive-attach.js +18 -0
- package/dist/cli/drive-command.js +7 -3
- package/dist/cli/mcp-command.js +51 -20
- package/dist/cli/project-name.d.ts +30 -0
- package/dist/cli/project-name.js +44 -0
- package/dist/cli/status-next-action.d.ts +14 -0
- package/dist/cli/status-next-action.js +4 -4
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +134 -80
- package/dist/cloud/cloud-config.d.ts +22 -1
- package/dist/cloud/cloud-config.js +64 -5
- package/dist/cloud/cloud-sync.d.ts +5 -5
- package/dist/cloud/cloud-sync.js +33 -2
- package/dist/cloud/sync-cycle.d.ts +110 -0
- package/dist/cloud/sync-cycle.js +270 -0
- package/dist/cloud/sync-daemon.d.ts +69 -0
- package/dist/cloud/sync-daemon.js +260 -0
- package/dist/cloud/sync-disk.d.ts +9 -0
- package/dist/cloud/sync-disk.js +191 -0
- package/dist/cloud/sync-hash.d.ts +2 -0
- package/dist/cloud/sync-hash.js +35 -0
- package/dist/crawl/crawl-tools.js +5 -3
- package/dist/crawl/crawl.d.ts +3 -0
- package/dist/crawl/crawl.js +5 -0
- package/dist/daemon/daemon-resolve.d.ts +43 -0
- package/dist/daemon/daemon-resolve.js +69 -0
- package/dist/daemon/dev-servers.d.ts +15 -0
- package/dist/daemon/dev-servers.js +68 -0
- package/dist/daemon/wake-decision.d.ts +32 -0
- package/dist/daemon/wake-decision.js +38 -0
- package/dist/domain/domain-tools.js +2 -2
- package/dist/events/contradictions.d.ts +18 -0
- package/dist/events/contradictions.js +134 -21
- package/dist/events/declared.d.ts +7 -4
- package/dist/events/declared.js +15 -6
- package/dist/events/echo-mismatch.js +64 -14
- package/dist/events/event-filters.d.ts +8 -0
- package/dist/events/event-filters.js +19 -2
- package/dist/events/predicate-eval.js +53 -5
- package/dist/events/predicate-precheck.d.ts +8 -0
- package/dist/events/predicate-precheck.js +41 -0
- package/dist/events/predicate-route.d.ts +14 -0
- package/dist/events/predicate-route.js +36 -8
- package/dist/events/predicate.d.ts +5 -0
- package/dist/events/predicate.js +37 -5
- package/dist/events/split-text-miss.d.ts +30 -0
- package/dist/events/split-text-miss.js +44 -0
- package/dist/flows/flake.d.ts +6 -6
- package/dist/flows/flow-memory-consult.d.ts +55 -0
- package/dist/flows/flow-memory-consult.js +38 -0
- package/dist/flows/flow-replay-run.d.ts +18 -7
- package/dist/flows/flow-replay-run.js +239 -22
- package/dist/flows/flow-replay.js +11 -2
- package/dist/flows/flow-step-runners.d.ts +8 -0
- package/dist/flows/flow-step-runners.js +8 -2
- package/dist/flows/flow-store-for-session.d.ts +31 -0
- package/dist/flows/flow-store-for-session.js +33 -0
- package/dist/flows/flow-tools.js +58 -32
- package/dist/flows/flows.d.ts +8 -0
- package/dist/flows/flows.js +468 -2
- package/dist/flows/heal-run.js +5 -2
- package/dist/flows/predicate-to-expect.d.ts +17 -12
- package/dist/flows/predicate-to-expect.js +30 -12
- package/dist/flows/recordings.d.ts +13 -1
- package/dist/flows/recordings.js +17 -2
- package/dist/flows/replay.d.ts +22 -2
- package/dist/flows/replay.js +28 -2
- package/dist/flows/verify-change-tools.js +5 -2
- package/dist/honesty/blind-spots.d.ts +55 -2
- package/dist/honesty/blind-spots.js +63 -3
- package/dist/honesty/honesty.d.ts +24 -0
- package/dist/honesty/honesty.js +25 -1
- package/dist/honesty/instrumentation-gaps.d.ts +9 -0
- package/dist/honesty/instrumentation-gaps.js +29 -2
- package/dist/honesty/verified.d.ts +2 -1
- package/dist/honesty/verified.js +16 -1
- package/dist/http-server.js +12 -0
- package/dist/impact/impact-recorder.d.ts +31 -8
- package/dist/impact/impact-recorder.js +104 -21
- package/dist/impact/impact-store.d.ts +15 -1
- package/dist/impact/impact-store.js +43 -2
- package/dist/index.js +113 -7
- package/dist/init/agent-rules.d.ts +13 -6
- package/dist/init/agent-rules.js +23 -12
- package/dist/init/astro-patch.d.ts +16 -0
- package/dist/init/astro-patch.js +28 -0
- package/dist/init/capabilities.d.ts +4 -1
- package/dist/init/capabilities.js +22 -2
- package/dist/init/confirm.d.ts +31 -7
- package/dist/init/confirm.js +48 -8
- package/dist/init/cra.d.ts +20 -4
- package/dist/init/cra.js +57 -17
- package/dist/init/csp-check.js +17 -2
- package/dist/init/csp-doctor.d.ts +8 -1
- package/dist/init/csp-doctor.js +8 -3
- package/dist/init/dev-script.d.ts +3 -1
- package/dist/init/dev-script.js +8 -5
- package/dist/init/format-generated.d.ts +18 -0
- package/dist/init/format-generated.js +39 -0
- package/dist/init/install-hint.d.ts +9 -0
- package/dist/init/install-hint.js +29 -0
- package/dist/init/mcp-clients.d.ts +7 -0
- package/dist/init/mcp-clients.js +7 -0
- package/dist/init/mcp.d.ts +1 -1
- package/dist/init/mcp.js +1 -1
- package/dist/init/node-io.js +11 -1
- package/dist/init/plan-framework.js +81 -45
- package/dist/init/plan.d.ts +20 -7
- package/dist/init/plan.js +20 -45
- package/dist/init/preflight.d.ts +28 -0
- package/dist/init/preflight.js +38 -0
- package/dist/init/run.d.ts +32 -9
- package/dist/init/run.js +141 -119
- package/dist/init/slash-command.d.ts +1 -1
- package/dist/init/snippets.js +41 -25
- package/dist/init/vite-config.d.ts +1 -1
- package/dist/init/vite-config.js +39 -25
- package/dist/init/workspace-apps.d.ts +17 -10
- package/dist/init/workspace-apps.js +110 -0
- package/dist/input/network-mock-tools.js +3 -6
- package/dist/input/real-input.js +25 -5
- package/dist/input/scroll-tools.js +4 -6
- package/dist/input/viewport-tools.js +5 -4
- package/dist/intent/inline-intent.d.ts +10 -19
- package/dist/intent/inline-intent.js +91 -1
- package/dist/intent/intent-shard-store.d.ts +72 -0
- package/dist/intent/intent-shard-store.js +203 -0
- package/dist/intent/intent-shard.d.ts +411 -0
- package/dist/intent/intent-shard.js +176 -0
- package/dist/intent/intent-store.d.ts +12 -0
- package/dist/intent/intent-store.js +21 -0
- package/dist/intent/intent-subject.d.ts +45 -0
- package/dist/intent/intent-subject.js +177 -0
- package/dist/intent/intent-tools.js +65 -2
- package/dist/intent/open-intents.d.ts +21 -0
- package/dist/intent/open-intents.js +15 -0
- package/dist/license/license-env.d.ts +29 -0
- package/dist/license/license-env.js +148 -0
- package/dist/loopback-agent.d.ts +31 -0
- package/dist/loopback-agent.js +57 -0
- package/dist/mcp/attach-memory.d.ts +18 -2
- package/dist/mcp/attach-memory.js +50 -7
- package/dist/mcp/client-identity.d.ts +31 -0
- package/dist/mcp/client-identity.js +51 -0
- package/dist/mcp/mcp-post-transport.d.ts +26 -0
- package/dist/mcp/mcp-post-transport.js +109 -0
- package/dist/mcp/mcp-proxy.d.ts +2 -1
- package/dist/mcp/mcp-proxy.js +52 -62
- package/dist/mcp/mcp.js +7 -1
- package/dist/mcp/proxy-backoff.d.ts +11 -0
- package/dist/mcp/proxy-backoff.js +13 -0
- package/dist/mcp/proxy-daemon-probe.d.ts +1 -0
- package/dist/mcp/proxy-daemon-probe.js +7 -1
- package/dist/mcp/proxy-handshake.d.ts +23 -0
- package/dist/mcp/proxy-handshake.js +31 -0
- package/dist/mcp/tool-catalog-cache.d.ts +8 -0
- package/dist/mcp/tool-catalog-cache.js +12 -0
- package/dist/memory/memory-tools.d.ts +2 -0
- package/dist/memory/memory-tools.js +82 -0
- package/dist/memory/project-memory.d.ts +34 -0
- package/dist/memory/project-memory.js +96 -0
- package/dist/oracles/propose-consequences.js +12 -3
- package/dist/pool/browser-pool.d.ts +63 -4
- package/dist/pool/browser-pool.js +113 -4
- package/dist/pool/playwright-launcher.js +9 -0
- package/dist/project/project-tools.js +3 -3
- package/dist/project/reticle-dir.d.ts +15 -2
- package/dist/project/reticle-dir.js +21 -4
- package/dist/runs/run-store.d.ts +10 -0
- package/dist/runs/run-store.js +10 -0
- package/dist/runs/verification-sync.d.ts +0 -11
- package/dist/runs/verification-sync.js +22 -1
- package/dist/runs/verify-server.d.ts +8 -1
- package/dist/runs/verify-server.js +14 -2
- package/dist/session/command-timeout.d.ts +5 -2
- package/dist/session/command-timeout.js +5 -4
- package/dist/session/lease-visibility.d.ts +67 -0
- package/dist/session/lease-visibility.js +76 -0
- package/dist/session/no-session-diagnosis.d.ts +23 -0
- package/dist/session/no-session-diagnosis.js +58 -17
- package/dist/session/no-session-next-action.d.ts +7 -0
- package/dist/session/no-session-next-action.js +42 -3
- package/dist/session/no-session-watch.d.ts +10 -6
- package/dist/session/no-session-watch.js +51 -19
- package/dist/session/pending-commands.d.ts +11 -1
- package/dist/session/pending-commands.js +12 -2
- package/dist/session/resolve-within.d.ts +34 -0
- package/dist/session/resolve-within.js +53 -0
- package/dist/session/session-info.d.ts +18 -0
- package/dist/session/session-info.js +11 -0
- package/dist/session/session-manager.d.ts +14 -0
- package/dist/session/session-manager.js +61 -3
- package/dist/session/session-mirror.d.ts +16 -0
- package/dist/session/session-mirror.js +22 -0
- package/dist/session/session-recommendation.d.ts +19 -5
- package/dist/session/session-recommendation.js +25 -9
- package/dist/session/session-successor.js +36 -1
- package/dist/session/session-tools.js +2 -2
- package/dist/session/session.d.ts +22 -2
- package/dist/session/session.js +87 -7
- package/dist/session/wall-clock.d.ts +12 -0
- package/dist/session/wall-clock.js +14 -0
- package/dist/setup/agent-configs.d.ts +96 -0
- package/dist/setup/agent-configs.js +333 -0
- package/dist/setup/agent-io.d.ts +9 -0
- package/dist/setup/agent-io.js +16 -0
- package/dist/setup/agent-writer.d.ts +51 -0
- package/dist/setup/agent-writer.js +115 -0
- package/dist/setup/approval-migration.d.ts +47 -0
- package/dist/setup/approval-migration.js +68 -0
- package/dist/setup/auto-approve.d.ts +85 -0
- package/dist/setup/auto-approve.js +150 -0
- package/dist/setup/bridge-port.d.ts +15 -0
- package/dist/setup/bridge-port.js +24 -0
- package/dist/setup/desktop-shape.d.ts +57 -0
- package/dist/setup/desktop-shape.js +63 -0
- package/dist/setup/dev-server-wait.d.ts +68 -0
- package/dist/setup/dev-server-wait.js +67 -0
- package/dist/setup/drive-agent.d.ts +71 -0
- package/dist/setup/drive-agent.js +171 -0
- package/dist/setup/drive-plan.d.ts +68 -0
- package/dist/setup/drive-plan.js +130 -0
- package/dist/setup/ensure-daemon.d.ts +29 -0
- package/dist/setup/ensure-daemon.js +58 -0
- package/dist/setup/init-runtime.d.ts +47 -0
- package/dist/setup/init-runtime.js +160 -0
- package/dist/setup/interrupt.d.ts +25 -0
- package/dist/setup/interrupt.js +40 -0
- package/dist/setup/license-key.d.ts +39 -0
- package/dist/setup/license-key.js +72 -0
- package/dist/setup/listeners.d.ts +37 -0
- package/dist/setup/listeners.js +85 -0
- package/dist/setup/node-effects.d.ts +60 -0
- package/dist/setup/node-effects.js +210 -0
- package/dist/setup/page-probe.d.ts +39 -0
- package/dist/setup/page-probe.js +49 -0
- package/dist/setup/relaunch.d.ts +36 -0
- package/dist/setup/relaunch.js +57 -0
- package/dist/setup/remaining-steps.d.ts +19 -0
- package/dist/setup/remaining-steps.js +31 -0
- package/dist/setup/run-setup.d.ts +99 -0
- package/dist/setup/run-setup.js +203 -0
- package/dist/setup/session-pick.d.ts +47 -0
- package/dist/setup/session-pick.js +51 -0
- package/dist/setup/setup-command.d.ts +45 -0
- package/dist/setup/setup-command.js +199 -0
- package/dist/setup/setup-options.d.ts +74 -0
- package/dist/setup/setup-options.js +67 -0
- package/dist/setup/transcripts.d.ts +16 -0
- package/dist/setup/transcripts.js +43 -0
- package/dist/status-payload.d.ts +14 -1
- package/dist/status-payload.js +23 -1
- package/dist/telemetry/daemon-telemetry.d.ts +8 -1
- package/dist/telemetry/daemon-telemetry.js +52 -5
- package/dist/telemetry/error-class.js +1 -1
- package/dist/telemetry/feedback-context.d.ts +9 -1
- package/dist/telemetry/feedback-context.js +60 -29
- package/dist/telemetry/feedback-local.d.ts +15 -0
- package/dist/telemetry/feedback-local.js +56 -0
- package/dist/telemetry/feedback.d.ts +11 -0
- package/dist/telemetry/feedback.js +19 -6
- package/dist/telemetry/init-telemetry.d.ts +2 -0
- package/dist/telemetry/init-telemetry.js +2 -0
- package/dist/telemetry/install-source.d.ts +14 -0
- package/dist/telemetry/install-source.js +30 -0
- package/dist/telemetry/license-activation.d.ts +7 -1
- package/dist/telemetry/license-activation.js +9 -5
- package/dist/telemetry/mcp-connection.js +7 -0
- package/dist/telemetry/project-profile.d.ts +12 -1
- package/dist/telemetry/project-profile.js +11 -6
- package/dist/telemetry/proxy-telemetry.d.ts +3 -0
- package/dist/telemetry/proxy-telemetry.js +21 -0
- package/dist/telemetry/session-metrics.d.ts +12 -0
- package/dist/telemetry/session-metrics.js +35 -1
- package/dist/telemetry/telemetry.js +17 -2
- package/dist/telemetry/tool-refused.d.ts +3 -1
- package/dist/telemetry/tool-refused.js +34 -2
- package/dist/tools/act-capsule.d.ts +10 -0
- package/dist/tools/act-capsule.js +8 -2
- package/dist/tools/act-danger.d.ts +2 -1
- package/dist/tools/act-danger.js +11 -3
- package/dist/tools/act-observation.d.ts +41 -0
- package/dist/tools/act-observation.js +36 -0
- package/dist/tools/act-preflight.d.ts +20 -0
- package/dist/tools/act-preflight.js +98 -0
- package/dist/tools/act-sequence-retry.d.ts +45 -0
- package/dist/tools/act-sequence-retry.js +58 -0
- package/dist/tools/act-sequence-tool.d.ts +13 -0
- package/dist/tools/act-sequence-tool.js +135 -0
- package/dist/tools/act-target.d.ts +14 -0
- package/dist/tools/act-target.js +47 -0
- package/dist/tools/act-tools.d.ts +21 -1
- package/dist/tools/act-tools.js +100 -213
- package/dist/tools/assert-verdict.js +22 -16
- package/dist/tools/browser-tools.js +6 -2
- package/dist/tools/dynamic-tools.js +24 -5
- package/dist/tools/error-recovery.d.ts +1 -0
- package/dist/tools/error-recovery.js +8 -0
- package/dist/tools/invoke-tool.js +59 -9
- package/dist/tools/lease-tools.d.ts +30 -4
- package/dist/tools/lease-tools.js +169 -5
- package/dist/tools/merged-name-redirect.d.ts +13 -0
- package/dist/tools/merged-name-redirect.js +22 -0
- package/dist/tools/numeric-bounds.d.ts +100 -0
- package/dist/tools/numeric-bounds.js +125 -0
- package/dist/tools/observe-tools.js +47 -40
- package/dist/tools/read-tools.js +28 -7
- package/dist/tools/real-input-attempt.d.ts +10 -0
- package/dist/tools/real-input-attempt.js +59 -1
- package/dist/tools/reconcile-tools.js +4 -4
- package/dist/tools/tool-kit.d.ts +12 -0
- package/dist/tools/tool-kit.js +6 -1
- package/dist/tools/tool-names.d.ts +2 -0
- package/dist/tools/tool-names.js +2 -0
- package/dist/tools/tools-helpers.d.ts +19 -0
- package/dist/tools/tools-helpers.js +46 -0
- package/dist/tools/tools.d.ts +2 -0
- package/dist/tools/tools.js +56 -8
- package/dist/update/reticle-deps.d.ts +9 -0
- package/dist/update/reticle-deps.js +27 -0
- package/dist/update/sdk-sync.d.ts +1 -2
- package/dist/update/sdk-sync.js +1 -21
- package/dist/update/update-nudge.d.ts +18 -0
- package/dist/update/update-nudge.js +20 -0
- package/dist/version/peer-announce.js +4 -2
- package/dist/version/sdk-fix.d.ts +47 -0
- package/dist/version/sdk-fix.js +127 -0
- package/dist/version/version-nudge.d.ts +14 -0
- package/dist/version/version-nudge.js +21 -0
- package/dist/version/version-skew.d.ts +38 -3
- package/dist/version/version-skew.js +83 -7
- package/dist/visual/visual-store.d.ts +6 -6
- package/dist/visual/visual-store.js +18 -16
- package/dist/visual/visual-tools.js +57 -12
- package/docs/cli/doctor.mdx +1 -0
- package/docs/cli/serve.mdx +4 -2
- package/docs/cli.mdx +7 -3
- package/docs/desktop.mdx +1 -1
- package/docs/docs.json +1 -1
- package/docs/getting-started.md +19 -3
- package/docs/index.mdx +9 -6
- package/docs/install-agentic.mdx +38 -12
- package/docs/install-manual.mdx +1 -1
- package/docs/packages.mdx +1 -1
- package/docs/skill-file.mdx +3 -3
- package/docs/telemetry-contract.md +108 -4
- package/docs/tools-act-sequence.mdx +16 -0
- package/docs/usage.md +1 -1
- package/package.json +4 -3
- package/dist/init/cursor.d.ts +0 -24
- package/dist/init/cursor.js +0 -80
package/dist/init/astro-patch.js
CHANGED
|
@@ -270,3 +270,31 @@ export function patchAstroLayout(source, port, projectId, uiLibrary = UiLibrary.
|
|
|
270
270
|
code: `${source.slice(0, at)}${astroConnectScript(port, projectId, uiLibrary)}${source.slice(at)}`,
|
|
271
271
|
};
|
|
272
272
|
}
|
|
273
|
+
/** Where Astro keeps ambient types — `create-astro` ships this file. */
|
|
274
|
+
export const ASTRO_ENV_DTS_PATH = 'src/env.d.ts';
|
|
275
|
+
/**
|
|
276
|
+
* The declarations `astro check` needs for the Vite `define` names (#677).
|
|
277
|
+
*
|
|
278
|
+
* Matching SvelteKit's `hooks.client.ts` typing: `string | undefined`, because the define can be
|
|
279
|
+
* absent when the pairing token file is missing.
|
|
280
|
+
*/
|
|
281
|
+
export const ASTRO_ENV_DTS_DECLARES = 'declare const __RETICLE_TOKEN__: string | undefined;\n' +
|
|
282
|
+
'declare const __RETICLE_ROOT__: string | undefined;\n';
|
|
283
|
+
/** Present once either declare is in the file — both are written together. */
|
|
284
|
+
const ENV_DTS_MARKER = '__RETICLE_TOKEN__';
|
|
285
|
+
/**
|
|
286
|
+
* Append the Vite-define ambient declarations to `src/env.d.ts`, or create the file.
|
|
287
|
+
*
|
|
288
|
+
* Without this, `create-astro`'s default `"astro check && astro build"` fails with four
|
|
289
|
+
* `ts(2304) Cannot find name '__RETICLE_TOKEN__'` errors after a clean init (#677).
|
|
290
|
+
*/
|
|
291
|
+
export function patchAstroEnvDts(existing) {
|
|
292
|
+
if (null !== existing && existing.includes(ENV_DTS_MARKER)) {
|
|
293
|
+
return { kind: PatchKind.ALREADY };
|
|
294
|
+
}
|
|
295
|
+
if (null === existing || '' === existing.trim()) {
|
|
296
|
+
return { kind: PatchKind.APPLY, code: ASTRO_ENV_DTS_DECLARES };
|
|
297
|
+
}
|
|
298
|
+
const base = existing.endsWith('\n') ? existing : `${existing}\n`;
|
|
299
|
+
return { kind: PatchKind.APPLY, code: `${base}${ASTRO_ENV_DTS_DECLARES}` };
|
|
300
|
+
}
|
|
@@ -13,7 +13,10 @@
|
|
|
13
13
|
export declare const MAX_TESTIDS = 60;
|
|
14
14
|
/** Every distinct `data-testid` literal in the given sources, in first-seen order. */
|
|
15
15
|
export declare function scanTestids(sources: readonly string[]): string[];
|
|
16
|
-
/**
|
|
16
|
+
/**
|
|
17
|
+
* The store libraries this app depends on AND the running app cannot reveal on its own, as
|
|
18
|
+
* ready-to-uncomment registration lines.
|
|
19
|
+
*/
|
|
17
20
|
export declare function storeHints(deps: ReadonlySet<string>): string[];
|
|
18
21
|
/** A store instance we found in the app's own source, with everything needed to import and register it. */
|
|
19
22
|
export interface FoundStore {
|
|
@@ -49,9 +49,29 @@ const STORE_LIBRARIES = [
|
|
|
49
49
|
['pinia', "registerStore('cart', piniaStore(useCartStore()))"],
|
|
50
50
|
['svelte', "registerStore('cart', svelteStore(cartStore))"],
|
|
51
51
|
];
|
|
52
|
-
/**
|
|
52
|
+
/**
|
|
53
|
+
* Libraries that hand their store to React through a context provider, and therefore need no hint.
|
|
54
|
+
*
|
|
55
|
+
* `<Provider store>` and `<QueryClientProvider client>` put the store instance in the fiber tree as
|
|
56
|
+
* a prop, so the React adapter finds and registers it on the first commit — see `auto-stores.ts` in
|
|
57
|
+
* `@reticlehq/react`. Offering a commented `registerStore` line for these was asking someone to do
|
|
58
|
+
* by hand, and be nagged about, work that is already done by the time they read the report.
|
|
59
|
+
*
|
|
60
|
+
* Everything absent from this set is module-scope (Zustand, Valtio, a MobX singleton) or needs an
|
|
61
|
+
* argument only the source supplies (Jotai atoms, an XState actor). Nothing in the running app
|
|
62
|
+
* points at those, so they still need the app to hand them over, and the hint still earns its place.
|
|
63
|
+
*/
|
|
64
|
+
const AUTO_DISCOVERED_DEPS = new Set([
|
|
65
|
+
'@tanstack/react-query',
|
|
66
|
+
'@reduxjs/toolkit',
|
|
67
|
+
'redux',
|
|
68
|
+
]);
|
|
69
|
+
/**
|
|
70
|
+
* The store libraries this app depends on AND the running app cannot reveal on its own, as
|
|
71
|
+
* ready-to-uncomment registration lines.
|
|
72
|
+
*/
|
|
53
73
|
export function storeHints(deps) {
|
|
54
|
-
return STORE_LIBRARIES.filter(([dep]) => deps.has(dep)).map(([, hint]) => hint);
|
|
74
|
+
return STORE_LIBRARIES.filter(([dep]) => deps.has(dep) && !AUTO_DISCOVERED_DEPS.has(dep)).map(([, hint]) => hint);
|
|
55
75
|
}
|
|
56
76
|
/**
|
|
57
77
|
* Store factories whose EXPORTED result is the store instance itself — the form `registerStore`
|
package/dist/init/confirm.d.ts
CHANGED
|
@@ -19,17 +19,29 @@
|
|
|
19
19
|
* keeps today's cost and today's exit behaviour, and blocking never happens where blocking is
|
|
20
20
|
* wrong. The signal is the standard "am I being piped" one and needs no argument parsing, which
|
|
21
21
|
* also keeps `init`'s documented flag surface where it is.
|
|
22
|
-
* -
|
|
23
|
-
* person whose machine it runs on and orphans when the daemon exits, so the daemon stays out
|
|
24
|
-
* it
|
|
25
|
-
*
|
|
26
|
-
*
|
|
22
|
+
* - The DAEMON never starts anything. A dev server started by a long-lived daemon is invisible to
|
|
23
|
+
* the person whose machine it runs on and orphans when the daemon exits, so the daemon stays out
|
|
24
|
+
* of it. Note what that reasoning is actually about: attributability, not abstinence. A
|
|
25
|
+
* foreground `init` somebody ran satisfies it — the command is in their transcript, and it stops
|
|
26
|
+
* what it started if setup fails or is interrupted — which is why the runtime phase is allowed
|
|
27
|
+
* to boot one where the daemon is not. This function keeps its own shape either way: confirm the
|
|
28
|
+
* app if it connects, otherwise name the ONE command that is outstanding and the one that proves
|
|
29
|
+
* it worked.
|
|
27
30
|
*/
|
|
28
31
|
import { InitConfirmation } from '@reticlehq/core';
|
|
29
|
-
import type { InitOutcome } from '@reticlehq/core';
|
|
32
|
+
import type { DevServerEntry, InitOutcome } from '@reticlehq/core';
|
|
30
33
|
export interface ConfirmDeps {
|
|
31
34
|
/** Session ids connected right now, or null when nothing is listening on the bridge port. */
|
|
32
35
|
listSessionIds: () => Promise<readonly string[] | null>;
|
|
36
|
+
/**
|
|
37
|
+
* The dev servers that have announced themselves, read at the END of the wait rather than the
|
|
38
|
+
* start: a dev server booting alongside `init` is the common case, and asking before it has
|
|
39
|
+
* finished listening would report the state we are trying to move away from.
|
|
40
|
+
*
|
|
41
|
+
* Optional so every existing construction of these deps — and any embedder's — keeps working and
|
|
42
|
+
* simply gets today's less specific message.
|
|
43
|
+
*/
|
|
44
|
+
listDevServers?: () => readonly DevServerEntry[];
|
|
33
45
|
now: () => number;
|
|
34
46
|
sleep: (ms: number) => Promise<void>;
|
|
35
47
|
windowMs?: number;
|
|
@@ -68,7 +80,19 @@ export declare function confirmAppConnected(deps: ConfirmDeps): Promise<InitConf
|
|
|
68
80
|
* there is a command outstanding. A missing daemon is not a defect in the install — the daemon comes
|
|
69
81
|
* up when the agent loads the tools — so it is a notice.
|
|
70
82
|
*/
|
|
71
|
-
|
|
83
|
+
/**
|
|
84
|
+
* Narrow "no app connected" using what the dev servers themselves announced.
|
|
85
|
+
*
|
|
86
|
+
* `confirmAppConnected` can only observe the bridge, so its NO_SESSION covers two situations with
|
|
87
|
+
* OPPOSITE fixes: the dev server is not running Reticle at all, or it is and no page has been
|
|
88
|
+
* opened. An announced entry is proof the plugin is loaded in the process that is actually running
|
|
89
|
+
* — which means the config is right and it has already been restarted.
|
|
90
|
+
*
|
|
91
|
+
* Only the unexplained answer is sharpened. CONNECTED is the finished state and NO_DAEMON is a
|
|
92
|
+
* different fact; neither becomes more true because a dev server is up.
|
|
93
|
+
*/
|
|
94
|
+
export declare function sharpenWithDevServers(confirmation: InitConfirmation, running: readonly DevServerEntry[]): InitConfirmation;
|
|
95
|
+
export declare function confirmationMessage(confirmation: InitConfirmation, port: number, running?: readonly DevServerEntry[]): string;
|
|
72
96
|
/**
|
|
73
97
|
* Finish `init` on evidence rather than on a write.
|
|
74
98
|
*
|
package/dist/init/confirm.js
CHANGED
|
@@ -19,14 +19,21 @@
|
|
|
19
19
|
* keeps today's cost and today's exit behaviour, and blocking never happens where blocking is
|
|
20
20
|
* wrong. The signal is the standard "am I being piped" one and needs no argument parsing, which
|
|
21
21
|
* also keeps `init`'s documented flag surface where it is.
|
|
22
|
-
* -
|
|
23
|
-
* person whose machine it runs on and orphans when the daemon exits, so the daemon stays out
|
|
24
|
-
* it
|
|
25
|
-
*
|
|
26
|
-
*
|
|
22
|
+
* - The DAEMON never starts anything. A dev server started by a long-lived daemon is invisible to
|
|
23
|
+
* the person whose machine it runs on and orphans when the daemon exits, so the daemon stays out
|
|
24
|
+
* of it. Note what that reasoning is actually about: attributability, not abstinence. A
|
|
25
|
+
* foreground `init` somebody ran satisfies it — the command is in their transcript, and it stops
|
|
26
|
+
* what it started if setup fails or is interrupted — which is why the runtime phase is allowed
|
|
27
|
+
* to boot one where the daemon is not. This function keeps its own shape either way: confirm the
|
|
28
|
+
* app if it connects, otherwise name the ONE command that is outstanding and the one that proves
|
|
29
|
+
* it worked.
|
|
27
30
|
*/
|
|
28
31
|
import { InitConfirmation, RETICLE_DEFAULT_PORT } from '@reticlehq/core';
|
|
29
32
|
import { fetchStatus, summarizeStatus } from '../cli/cli-launch.js';
|
|
33
|
+
import { readDevServers } from '../daemon/dev-servers.js';
|
|
34
|
+
import { devServersForProject } from '@reticlehq/core';
|
|
35
|
+
import { readProjectId } from '../cli/cli-port.js';
|
|
36
|
+
import { reticleStateHome } from '../daemon/daemon.js';
|
|
30
37
|
import { reportInitOutcome } from '../telemetry/init-telemetry.js';
|
|
31
38
|
/**
|
|
32
39
|
* How long a human is asked to wait.
|
|
@@ -78,7 +85,23 @@ const PROVE_COMMAND = '`npx @reticlehq/server status`';
|
|
|
78
85
|
* there is a command outstanding. A missing daemon is not a defect in the install — the daemon comes
|
|
79
86
|
* up when the agent loads the tools — so it is a notice.
|
|
80
87
|
*/
|
|
81
|
-
|
|
88
|
+
/**
|
|
89
|
+
* Narrow "no app connected" using what the dev servers themselves announced.
|
|
90
|
+
*
|
|
91
|
+
* `confirmAppConnected` can only observe the bridge, so its NO_SESSION covers two situations with
|
|
92
|
+
* OPPOSITE fixes: the dev server is not running Reticle at all, or it is and no page has been
|
|
93
|
+
* opened. An announced entry is proof the plugin is loaded in the process that is actually running
|
|
94
|
+
* — which means the config is right and it has already been restarted.
|
|
95
|
+
*
|
|
96
|
+
* Only the unexplained answer is sharpened. CONNECTED is the finished state and NO_DAEMON is a
|
|
97
|
+
* different fact; neither becomes more true because a dev server is up.
|
|
98
|
+
*/
|
|
99
|
+
export function sharpenWithDevServers(confirmation, running) {
|
|
100
|
+
if (confirmation !== InitConfirmation.NO_SESSION)
|
|
101
|
+
return confirmation;
|
|
102
|
+
return 0 === running.length ? InitConfirmation.NO_SESSION : InitConfirmation.NO_PAGE;
|
|
103
|
+
}
|
|
104
|
+
export function confirmationMessage(confirmation, port, running = []) {
|
|
82
105
|
if (confirmation === InitConfirmation.CONNECTED) {
|
|
83
106
|
return (' [✓] an app is connected — that is the install finished, not just written.\n' +
|
|
84
107
|
' Ask your agent to drive a flow.');
|
|
@@ -89,6 +112,15 @@ export function confirmationMessage(confirmation, port) {
|
|
|
89
112
|
' The daemon starts on its own when your agent loads the Reticle tools. After that, ' +
|
|
90
113
|
`${PROVE_COMMAND} confirms the app.`);
|
|
91
114
|
}
|
|
115
|
+
if (confirmation === InitConfirmation.NO_PAGE) {
|
|
116
|
+
// Deliberately never says "restart". The announcement is proof they already did — telling them
|
|
117
|
+
// again is how a correct instruction reads as the tool not knowing what is going on.
|
|
118
|
+
const where = running.map((s) => ` ${s.url}`).join('\n');
|
|
119
|
+
return (' [⚠] your dev server has Reticle loaded, and no page has connected yet — so the only step ' +
|
|
120
|
+
'left is opening the app.\n' +
|
|
121
|
+
` Open it in a browser:\n${where}\n` +
|
|
122
|
+
` ${PROVE_COMMAND} then confirms it.`);
|
|
123
|
+
}
|
|
92
124
|
return (' [⚠] no app has connected yet — the files are written, the page half of the install is not ' +
|
|
93
125
|
'done.\n' +
|
|
94
126
|
' Restart your dev server and load the app in a browser — or ask your agent to, which it is ' +
|
|
@@ -142,13 +174,21 @@ export async function confirmInstall(result, io, deps, report = reportInitOutcom
|
|
|
142
174
|
}
|
|
143
175
|
io.print('');
|
|
144
176
|
io.print(WATCHING(deps.windowMs ?? CONFIRM_WINDOW_MS));
|
|
145
|
-
const
|
|
146
|
-
|
|
177
|
+
const observed = await confirmAppConnected(deps);
|
|
178
|
+
const running = deps.listDevServers?.() ?? [];
|
|
179
|
+
const confirmation = sharpenWithDevServers(observed, running);
|
|
180
|
+
io.print(confirmationMessage(confirmation, deps.port, running));
|
|
147
181
|
report({ ...outcome, confirmation });
|
|
148
182
|
}
|
|
149
183
|
/** The real deps: the daemon's own status endpoint, and whether a human is watching. */
|
|
150
184
|
export function nodeConfirmDeps(port = RETICLE_DEFAULT_PORT) {
|
|
151
185
|
return {
|
|
186
|
+
// Scoped to the project being set up. The registry is machine-wide, so unscoped it reported a
|
|
187
|
+
// sibling app's dev server as this one's — see devServersForProject.
|
|
188
|
+
listDevServers: () => devServersForProject(readDevServers(reticleStateHome()), {
|
|
189
|
+
projectId: readProjectId(process.cwd()),
|
|
190
|
+
root: process.cwd(),
|
|
191
|
+
}),
|
|
152
192
|
listSessionIds: async () => {
|
|
153
193
|
const payload = await fetchStatus(port);
|
|
154
194
|
// `fetchStatus` resolves undefined when nothing answered, which is precisely the "no daemon"
|
package/dist/init/cra.d.ts
CHANGED
|
@@ -12,9 +12,17 @@
|
|
|
12
12
|
* `REACT_APP_`. So it travels through `.env.development.local`, which is CRA's own documented
|
|
13
13
|
* mechanism and is gitignored by CRA's own template.
|
|
14
14
|
*/
|
|
15
|
-
/** The line added to `src/index.tsx`. Side-effect import: the module guards itself on NODE_ENV. */
|
|
15
|
+
/** The line added to `src/index.tsx` / `src/index.js`. Side-effect import: the module guards itself on NODE_ENV. */
|
|
16
16
|
export declare const CRA_DEV_MODULE_IMPORT = "import './reticle-dev';";
|
|
17
|
-
|
|
17
|
+
/**
|
|
18
|
+
* Where the connect module lands — `.ts` only when the app already speaks TypeScript.
|
|
19
|
+
*
|
|
20
|
+
* A JavaScript CRA project has no tsconfig and cannot resolve `.ts` (#675). Emitting `.ts` there
|
|
21
|
+
* makes the first compile after init fail while the plan still reports `[✓]`.
|
|
22
|
+
*/
|
|
23
|
+
export declare function craDevModulePath(typescript: boolean): string;
|
|
24
|
+
/** TypeScript default path — prefer `craDevModulePath` when the project's language is known. */
|
|
25
|
+
export declare const CRA_DEV_MODULE_PATH: string;
|
|
18
26
|
export declare const CRA_ENV_PATH = ".env.development.local";
|
|
19
27
|
export declare const TOKEN_VAR = "REACT_APP_RETICLE_TOKEN";
|
|
20
28
|
/**
|
|
@@ -59,5 +67,13 @@ export declare const CRA_TOKEN_PER_MACHINE_NOTICE: string;
|
|
|
59
67
|
export declare function craImportPatch(source: string): string | null;
|
|
60
68
|
/** Set the token variable, or null when nothing needs to change. */
|
|
61
69
|
export declare function craEnvPatch(existing: string | null, token: string, url?: string): string | null;
|
|
62
|
-
/**
|
|
63
|
-
export
|
|
70
|
+
/** Options for the CRA connect module. */
|
|
71
|
+
export interface CraDevModuleOptions {
|
|
72
|
+
/**
|
|
73
|
+
* When false, emit a `.js`-shaped body (no `export {}`). Default true for callers that predate
|
|
74
|
+
* the language branch.
|
|
75
|
+
*/
|
|
76
|
+
typescript?: boolean;
|
|
77
|
+
}
|
|
78
|
+
/** The dev-only connect module imported from the app entry. */
|
|
79
|
+
export declare function craDevModuleFile(port: number | undefined, projectId?: string, options?: CraDevModuleOptions): string;
|
package/dist/init/cra.js
CHANGED
|
@@ -14,9 +14,19 @@
|
|
|
14
14
|
*/
|
|
15
15
|
import { bridgeWsUrl } from '@reticlehq/core';
|
|
16
16
|
import { CLI } from './agent-rules.js';
|
|
17
|
-
/** The line added to `src/index.tsx`. Side-effect import: the module guards itself on NODE_ENV. */
|
|
17
|
+
/** The line added to `src/index.tsx` / `src/index.js`. Side-effect import: the module guards itself on NODE_ENV. */
|
|
18
18
|
export const CRA_DEV_MODULE_IMPORT = "import './reticle-dev';";
|
|
19
|
-
|
|
19
|
+
/**
|
|
20
|
+
* Where the connect module lands — `.ts` only when the app already speaks TypeScript.
|
|
21
|
+
*
|
|
22
|
+
* A JavaScript CRA project has no tsconfig and cannot resolve `.ts` (#675). Emitting `.ts` there
|
|
23
|
+
* makes the first compile after init fail while the plan still reports `[✓]`.
|
|
24
|
+
*/
|
|
25
|
+
export function craDevModulePath(typescript) {
|
|
26
|
+
return typescript ? 'src/reticle-dev.ts' : 'src/reticle-dev.js';
|
|
27
|
+
}
|
|
28
|
+
/** TypeScript default path — prefer `craDevModulePath` when the project's language is known. */
|
|
29
|
+
export const CRA_DEV_MODULE_PATH = craDevModulePath(true);
|
|
20
30
|
export const CRA_ENV_PATH = '.env.development.local';
|
|
21
31
|
export const TOKEN_VAR = 'REACT_APP_RETICLE_TOKEN';
|
|
22
32
|
/**
|
|
@@ -101,8 +111,9 @@ export function craEnvPatch(existing, token, url) {
|
|
|
101
111
|
}
|
|
102
112
|
return next === (existing ?? '') ? null : next;
|
|
103
113
|
}
|
|
104
|
-
/** The dev-only connect module imported from
|
|
105
|
-
export function craDevModuleFile(port, projectId) {
|
|
114
|
+
/** The dev-only connect module imported from the app entry. */
|
|
115
|
+
export function craDevModuleFile(port, projectId, options = {}) {
|
|
116
|
+
const typescript = false !== options.typescript;
|
|
106
117
|
const fields = [];
|
|
107
118
|
// `bridgeWsUrl`, not a hand-written string. This was the only client URL in the product spelling
|
|
108
119
|
// the host as `127.0.0.1` while every other generator said `localhost` — same endpoint, but a
|
|
@@ -112,27 +123,56 @@ export function craDevModuleFile(port, projectId) {
|
|
|
112
123
|
fields.push(`url: '${bridgeWsUrl(port)}'`);
|
|
113
124
|
if (projectId !== undefined && projectId.length > 0)
|
|
114
125
|
fields.push(`projectId: '${projectId}'`);
|
|
115
|
-
|
|
126
|
+
// Multiline on purpose (#684): a single-line connect + console.error fails CRA boilerplate
|
|
127
|
+
// Prettier (printWidth 80) and the project's own lint blocks a clean install.
|
|
128
|
+
const connectFields = [
|
|
129
|
+
...fields.map((f) => ` ${f},`),
|
|
130
|
+
' ...(url.length > 0 ? { url } : {}),',
|
|
131
|
+
' ...(token.length > 0 ? { token } : {}),',
|
|
132
|
+
].join('\n');
|
|
133
|
+
// Split so every emitted line stays under a CRA boilerplate printWidth of 80 (#684). A single
|
|
134
|
+
// JSON.stringify of the whole note is ~290 characters and fails prettier-as-eslint on install.
|
|
135
|
+
// Chunks are joined with `+` in the emitted file; together they equal `[reticle] ${CRA_TOKEN_MISSING_NOTE}`.
|
|
136
|
+
const missingChunks = [
|
|
137
|
+
`[reticle] ${TOKEN_VAR} is not set, so Reticle `,
|
|
138
|
+
'cannot pair with the daemon. The pairing token is ',
|
|
139
|
+
`per-machine and ${CRA_ENV_PATH} is gitignored by `,
|
|
140
|
+
"CRA's template, so it does not survive a clone. Run ",
|
|
141
|
+
`\`${CLI} init\` in this project to write it for this `,
|
|
142
|
+
'machine.',
|
|
143
|
+
].map((c) => JSON.stringify(c));
|
|
144
|
+
// Eight spaces match the indent inside `console.error(` below.
|
|
145
|
+
const missingExpr = missingChunks.join(' +\n ');
|
|
146
|
+
// `export {}` is a TypeScript empty-module marker. A `.js` file with it is fine under Babel, but
|
|
147
|
+
// the workaround reporters used was to drop it when renaming to `.js` — keep the JS emit clean.
|
|
148
|
+
const trailer = typescript ? '\nexport {};\n' : '\n';
|
|
116
149
|
return `// Dev-only: connect Reticle. Imported for its side effect from src/index.tsx.
|
|
117
150
|
//
|
|
118
|
-
// CRA's public/index.html is a static template the bundler never processes for
|
|
119
|
-
// connect cannot live there. The pairing token arrives through
|
|
120
|
-
// REACT_APP_* is the only thing CRA inlines
|
|
151
|
+
// CRA's public/index.html is a static template the bundler never processes for
|
|
152
|
+
// modules, so the connect cannot live there. The pairing token arrives through
|
|
153
|
+
// REACT_APP_RETICLE_TOKEN because REACT_APP_* is the only thing CRA inlines
|
|
154
|
+
// into browser code.
|
|
121
155
|
if (process.env.NODE_ENV === 'development') {
|
|
122
156
|
void import('@reticlehq/react').then(({ reticle, install }) => {
|
|
123
157
|
install();
|
|
124
158
|
const token = process.env.${TOKEN_VAR} ?? '';
|
|
125
|
-
// Written by \`reticle init\` from the daemon that was live when it ran, and
|
|
126
|
-
// re-running it. CRA gives us no hook to resolve this at
|
|
127
|
-
// moves, re-run \`reticle init\` rather
|
|
159
|
+
// Written by \`reticle init\` from the daemon that was live when it ran, and
|
|
160
|
+
// refreshed by re-running it. CRA gives us no hook to resolve this at
|
|
161
|
+
// dev-server start, so if the daemon moves, re-run \`reticle init\` rather
|
|
162
|
+
// than editing the url below.
|
|
128
163
|
const url = process.env.${URL_VAR} ?? '';
|
|
129
|
-
// Loud on purpose: without this the only symptom is the bridge's generic
|
|
130
|
-
|
|
164
|
+
// Loud on purpose: without this the only symptom is the bridge's generic
|
|
165
|
+
// auth failure.
|
|
166
|
+
if (token.length === 0) {
|
|
167
|
+
console.error(
|
|
168
|
+
${missingExpr},
|
|
169
|
+
);
|
|
170
|
+
}
|
|
131
171
|
// Still attempt it — a bridge running without a token pairs fine.
|
|
132
|
-
reticle.connect({
|
|
172
|
+
reticle.connect({
|
|
173
|
+
${connectFields}
|
|
174
|
+
});
|
|
133
175
|
});
|
|
134
176
|
}
|
|
135
|
-
|
|
136
|
-
export {};
|
|
137
|
-
`;
|
|
177
|
+
${trailer}`;
|
|
138
178
|
}
|
package/dist/init/csp-check.js
CHANGED
|
@@ -30,10 +30,10 @@ function bridgeOrigins(port) {
|
|
|
30
30
|
* Matches to the end of the directive (`;`) or the end of the enclosing quoted string, which is how
|
|
31
31
|
* these are written in both a Next `headers()` value and a `<meta content="...">`.
|
|
32
32
|
*/
|
|
33
|
-
function
|
|
33
|
+
function directiveSources(text, directive) {
|
|
34
34
|
// Stops at the directive separator or the closing double quote of the enclosing string. Single
|
|
35
35
|
// quotes are NOT terminators: `'self'` is a source, not the end of the list.
|
|
36
|
-
const match =
|
|
36
|
+
const match = new RegExp(`${directive}([^;"]*)`, 'i').exec(text);
|
|
37
37
|
const list = match?.[1];
|
|
38
38
|
if (list === undefined)
|
|
39
39
|
return undefined;
|
|
@@ -42,6 +42,21 @@ function connectSrcSources(text) {
|
|
|
42
42
|
.map((source) => source.trim())
|
|
43
43
|
.filter((source) => source.length > 0);
|
|
44
44
|
}
|
|
45
|
+
/**
|
|
46
|
+
* What this policy allows a WebSocket to reach — `connect-src`, or `default-src` when it is absent.
|
|
47
|
+
*
|
|
48
|
+
* The fallback is the CSP spec's, and leaving it out made the check blind to the commonest strict
|
|
49
|
+
* policy there is. MarkText, a production Electron editor, declares
|
|
50
|
+
* `default-src 'self'; script-src 'self'; …` with NO `connect-src`: its WebSockets are restricted to
|
|
51
|
+
* 'self', the bridge is blocked, and this returned "no problem" because it was looking for a
|
|
52
|
+
* directive that was not written. Every fetch-directive falls back to `default-src`; that is what
|
|
53
|
+
* `default` means, and it is why an author does not repeat themselves.
|
|
54
|
+
*
|
|
55
|
+
* Still undefined when NEITHER is present — a policy that constrains neither is not blocking us.
|
|
56
|
+
*/
|
|
57
|
+
function connectSrcSources(text) {
|
|
58
|
+
return directiveSources(text, 'connect-src') ?? directiveSources(text, 'default-src');
|
|
59
|
+
}
|
|
45
60
|
/**
|
|
46
61
|
* The problem with this app's `connect-src`, or undefined if there is not one.
|
|
47
62
|
*
|
|
@@ -21,5 +21,12 @@ export interface CspDiagnosis {
|
|
|
21
21
|
/** Exactly what to add — copy-pasteable, with the port actually in use. */
|
|
22
22
|
fix: string;
|
|
23
23
|
}
|
|
24
|
-
|
|
24
|
+
/**
|
|
25
|
+
* The places a Content-Security-Policy gets written in a JS app.
|
|
26
|
+
*
|
|
27
|
+
* Next config and middleware cover `headers()` and the edge-middleware style; the layouts and the
|
|
28
|
+
* plain `index.html` cover the `<meta http-equiv>` style. Both reported cases were in this list.
|
|
29
|
+
*/
|
|
30
|
+
export declare const CSP_FILES: readonly string[];
|
|
31
|
+
export declare function diagnoseWebCsp(read: ReadFile, port: number, alsoCheck?: readonly string[]): CspDiagnosis[];
|
|
25
32
|
export {};
|
package/dist/init/csp-doctor.js
CHANGED
|
@@ -18,7 +18,7 @@ import { cspConnectSrcProblem, devCspAddition } from './csp-check.js';
|
|
|
18
18
|
* Next config and middleware cover `headers()` and the edge-middleware style; the layouts and the
|
|
19
19
|
* plain `index.html` cover the `<meta http-equiv>` style. Both reported cases were in this list.
|
|
20
20
|
*/
|
|
21
|
-
const CSP_FILES = [
|
|
21
|
+
export const CSP_FILES = [
|
|
22
22
|
'next.config.js',
|
|
23
23
|
'next.config.mjs',
|
|
24
24
|
'next.config.ts',
|
|
@@ -31,12 +31,17 @@ const CSP_FILES = [
|
|
|
31
31
|
'pages/_document.js',
|
|
32
32
|
'index.html',
|
|
33
33
|
'public/index.html',
|
|
34
|
+
// Vite puts the entry HTML at the project root; electron-vite and Tauri put the RENDERER's one
|
|
35
|
+
// under src/. MarkText declares its policy in `src/renderer/index.html`, and a desktop app is the
|
|
36
|
+
// likeliest place to meet a strict CSP at all — Electron's own security guidance asks for one.
|
|
37
|
+
'src/index.html',
|
|
38
|
+
'src/renderer/index.html',
|
|
34
39
|
'vercel.json',
|
|
35
40
|
'netlify.toml',
|
|
36
41
|
];
|
|
37
|
-
export function diagnoseWebCsp(read, port) {
|
|
42
|
+
export function diagnoseWebCsp(read, port, alsoCheck = []) {
|
|
38
43
|
const findings = [];
|
|
39
|
-
for (const file of CSP_FILES) {
|
|
44
|
+
for (const file of [...alsoCheck, ...CSP_FILES]) {
|
|
40
45
|
const source = read(file);
|
|
41
46
|
if (source === undefined)
|
|
42
47
|
continue;
|
|
@@ -14,6 +14,8 @@
|
|
|
14
14
|
* which script, and whether to touch anything at all — and that is what wants testing. Spawning a
|
|
15
15
|
* process is not.
|
|
16
16
|
*/
|
|
17
|
+
/** Script names a JS project uses to run itself, in the order we would pick them. */
|
|
18
|
+
export declare const DEV_SCRIPT_NAMES: readonly ["dev", "start", "serve"];
|
|
17
19
|
export declare const DevScriptChoice: {
|
|
18
20
|
/** Something already answers on the port. Use it; never replace a server the user is running. */
|
|
19
21
|
readonly ALREADY_SERVING: "already-serving";
|
|
@@ -45,4 +47,4 @@ export declare function planDevScript(scripts: Readonly<Record<string, string>>,
|
|
|
45
47
|
* parsing attached, and `run.ts` is at its cohesion limit. Returns undefined for anything it cannot
|
|
46
48
|
* read: this phrasing decides nothing, so it must never be able to break an install.
|
|
47
49
|
*/
|
|
48
|
-
export declare function devCommandFrom(
|
|
50
|
+
export declare function devCommandFrom(pkg: unknown, packageManager: string): string | undefined;
|
package/dist/init/dev-script.js
CHANGED
|
@@ -15,7 +15,8 @@
|
|
|
15
15
|
* process is not.
|
|
16
16
|
*/
|
|
17
17
|
/** Script names a JS project uses to run itself, in the order we would pick them. */
|
|
18
|
-
const
|
|
18
|
+
export const DEV_SCRIPT_NAMES = ['dev', 'start', 'serve'];
|
|
19
|
+
const CANDIDATES = DEV_SCRIPT_NAMES;
|
|
19
20
|
export const DevScriptChoice = {
|
|
20
21
|
/** Something already answers on the port. Use it; never replace a server the user is running. */
|
|
21
22
|
ALREADY_SERVING: 'already-serving',
|
|
@@ -49,11 +50,13 @@ export function planDevScript(scripts, packageManager, serving) {
|
|
|
49
50
|
* parsing attached, and `run.ts` is at its cohesion limit. Returns undefined for anything it cannot
|
|
50
51
|
* read: this phrasing decides nothing, so it must never be able to break an install.
|
|
51
52
|
*/
|
|
52
|
-
export function devCommandFrom(
|
|
53
|
+
export function devCommandFrom(pkg, packageManager) {
|
|
53
54
|
try {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
55
|
+
// Takes the PARSED manifest. It used to take the raw string and parse it a fourth time — the
|
|
56
|
+
// caller now reads the file once, through a guard, so there is one place a malformed manifest
|
|
57
|
+
// can be noticed and it is not this one.
|
|
58
|
+
const scripts = 'object' === typeof pkg && null !== pkg
|
|
59
|
+
? (pkg.scripts ?? {})
|
|
57
60
|
: {};
|
|
58
61
|
return planDevScript(scripts, packageManager, false).command;
|
|
59
62
|
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Format a file `init` is about to write, using the project's own Prettier when it is installed.
|
|
3
|
+
*
|
|
4
|
+
* Reported from the field (#684): a clean CRA install failed the project's own lint because
|
|
5
|
+
* `src/reticle-dev.ts` was emitted as one long line. The project already had Prettier; init never
|
|
6
|
+
* asked it. Best-effort: resolve Prettier from the app (not from ours — we do not ship it), apply
|
|
7
|
+
* its config, and on any failure return the original content so init never fails because of a
|
|
8
|
+
* formatter. Sync only — `applyEffects` is sync, and Prettier 3's async `format` cannot join here.
|
|
9
|
+
*/
|
|
10
|
+
/** True when this write is a connect/dev module lint will treat as project source. */
|
|
11
|
+
export declare function isGeneratedSourcePath(relPath: string): boolean;
|
|
12
|
+
/**
|
|
13
|
+
* Format `content` for `relPath` under `projectRoot`, or return it unchanged.
|
|
14
|
+
*
|
|
15
|
+
* Only the sync Prettier API is used. Prettier 3's async `format` is skipped (returns the original)
|
|
16
|
+
* rather than holding init open on a promise `applyEffects` cannot await.
|
|
17
|
+
*/
|
|
18
|
+
export declare function formatGeneratedSource(content: string, relPath: string, projectRoot: string): string;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Format a file `init` is about to write, using the project's own Prettier when it is installed.
|
|
3
|
+
*
|
|
4
|
+
* Reported from the field (#684): a clean CRA install failed the project's own lint because
|
|
5
|
+
* `src/reticle-dev.ts` was emitted as one long line. The project already had Prettier; init never
|
|
6
|
+
* asked it. Best-effort: resolve Prettier from the app (not from ours — we do not ship it), apply
|
|
7
|
+
* its config, and on any failure return the original content so init never fails because of a
|
|
8
|
+
* formatter. Sync only — `applyEffects` is sync, and Prettier 3's async `format` cannot join here.
|
|
9
|
+
*/
|
|
10
|
+
import { createRequire } from 'node:module';
|
|
11
|
+
import { basename, join } from 'node:path';
|
|
12
|
+
/** Basenames of full-file generators that a project's lint will see. */
|
|
13
|
+
const GENERATED_SOURCE_NAMES = new Set(['reticle-dev.ts', 'reticle-dev.tsx', 'hooks.client.ts']);
|
|
14
|
+
/** True when this write is a connect/dev module lint will treat as project source. */
|
|
15
|
+
export function isGeneratedSourcePath(relPath) {
|
|
16
|
+
return GENERATED_SOURCE_NAMES.has(basename(relPath));
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Format `content` for `relPath` under `projectRoot`, or return it unchanged.
|
|
20
|
+
*
|
|
21
|
+
* Only the sync Prettier API is used. Prettier 3's async `format` is skipped (returns the original)
|
|
22
|
+
* rather than holding init open on a promise `applyEffects` cannot await.
|
|
23
|
+
*/
|
|
24
|
+
export function formatGeneratedSource(content, relPath, projectRoot) {
|
|
25
|
+
if (!isGeneratedSourcePath(relPath))
|
|
26
|
+
return content;
|
|
27
|
+
try {
|
|
28
|
+
const require = createRequire(join(projectRoot, 'package.json'));
|
|
29
|
+
const prettier = require('prettier');
|
|
30
|
+
const filePath = join(projectRoot, relPath);
|
|
31
|
+
const resolved = prettier.resolveConfig.sync?.(filePath) ?? {};
|
|
32
|
+
const formatted = prettier.format(content, { ...resolved, filepath: filePath });
|
|
33
|
+
// Prettier 2 returns a string; Prettier 3 returns a Promise we cannot join from sync code.
|
|
34
|
+
return 'string' === typeof formatted ? formatted : content;
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
return content;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What to say when the dependency install fails.
|
|
3
|
+
*
|
|
4
|
+
* Split out of plan.ts, which was at the 1000-line backstop. A cohesive unit rather than an
|
|
5
|
+
* arbitrary cut: it is prose about one step's failure modes, and the only thing it needs is which
|
|
6
|
+
* package manager was used.
|
|
7
|
+
*/
|
|
8
|
+
import { PackageManager } from './detect.js';
|
|
9
|
+
export declare function installFailureHint(pm: PackageManager): string;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What to say when the dependency install fails.
|
|
3
|
+
*
|
|
4
|
+
* Split out of plan.ts, which was at the 1000-line backstop. A cohesive unit rather than an
|
|
5
|
+
* arbitrary cut: it is prose about one step's failure modes, and the only thing it needs is which
|
|
6
|
+
* package manager was used.
|
|
7
|
+
*/
|
|
8
|
+
import { PackageManager } from './detect.js';
|
|
9
|
+
/**
|
|
10
|
+
* Every package manager fetches, so every one of them can fail for a reason that is nothing to do
|
|
11
|
+
* with the project: offline, a proxy that blocks npmjs, a corporate mirror that is down.
|
|
12
|
+
*
|
|
13
|
+
* The hint used to name only version pinning and pnpm's maturity window. Both are real causes, and
|
|
14
|
+
* neither is that one — so a blocked registry sent the reader through their own dependency versions
|
|
15
|
+
* looking for a problem that was entirely about reachability.
|
|
16
|
+
*/
|
|
17
|
+
const REGISTRY_HINT = 'If it could not reach the registry at all (offline, a proxy, a mirror that is down), that is ' +
|
|
18
|
+
'about reachability and not about this project: check `npm config get registry` and whether this ' +
|
|
19
|
+
'machine can reach it.';
|
|
20
|
+
export function installFailureHint(pm) {
|
|
21
|
+
if (pm !== PackageManager.PNPM) {
|
|
22
|
+
return `If the version was refused, install the SDK yourself. ${REGISTRY_HINT}`;
|
|
23
|
+
}
|
|
24
|
+
return ('If pnpm reported ERR_PNPM_NO_MATURE_MATCHING_VERSION, its minimumReleaseAge setting is holding ' +
|
|
25
|
+
'this release back. Either wait out the window, or allow these packages explicitly:\n' +
|
|
26
|
+
' pnpm config set minimumReleaseAgeExclude "@reticlehq/*"\n' +
|
|
27
|
+
'Do NOT drop the version pin — unpinned, pnpm installs an older SDK against a newer daemon, and ' +
|
|
28
|
+
`that mismatch surfaces as a -32000 with nothing naming a version.\n${REGISTRY_HINT}`);
|
|
29
|
+
}
|
|
@@ -78,5 +78,12 @@ export declare function clientSnippet(spec: ClientSpec): string;
|
|
|
78
78
|
* because a fresh Cursor profile has not written `~/.cursor` yet.
|
|
79
79
|
*/
|
|
80
80
|
export declare function clientMarkerRelPath(spec: ClientSpec): string;
|
|
81
|
+
/**
|
|
82
|
+
* Project-relative directory whose presence signals Cursor is in use for this repo.
|
|
83
|
+
*
|
|
84
|
+
* A fresh Cursor profile has not written `~/.cursor` yet, so the home marker alone misses real
|
|
85
|
+
* users. A project-level `.cursor/` is unambiguous evidence somebody uses Cursor here.
|
|
86
|
+
*/
|
|
87
|
+
export declare const CURSOR_PROJECT_MARKER = ".cursor";
|
|
81
88
|
/** Clients `init` can wire by writing a file — everything but the CLI-registered one. */
|
|
82
89
|
export declare function fileBackedClients(): readonly ClientSpec[];
|
package/dist/init/mcp-clients.js
CHANGED
|
@@ -286,6 +286,13 @@ export function clientMarkerRelPath(spec) {
|
|
|
286
286
|
const parts = spec.relPath.split('/');
|
|
287
287
|
return parts.length > 1 ? parts.slice(0, -1).join('/') : spec.relPath;
|
|
288
288
|
}
|
|
289
|
+
/**
|
|
290
|
+
* Project-relative directory whose presence signals Cursor is in use for this repo.
|
|
291
|
+
*
|
|
292
|
+
* A fresh Cursor profile has not written `~/.cursor` yet, so the home marker alone misses real
|
|
293
|
+
* users. A project-level `.cursor/` is unambiguous evidence somebody uses Cursor here.
|
|
294
|
+
*/
|
|
295
|
+
export const CURSOR_PROJECT_MARKER = '.cursor';
|
|
289
296
|
/** Clients `init` can wire by writing a file — everything but the CLI-registered one. */
|
|
290
297
|
export function fileBackedClients() {
|
|
291
298
|
return MCP_CLIENTS.filter((spec) => spec.scope !== ConfigScope.CLI);
|
package/dist/init/mcp.d.ts
CHANGED
|
@@ -43,7 +43,7 @@ export declare const NPX = "npx";
|
|
|
43
43
|
*
|
|
44
44
|
* So it stays unpinned, and the skew is handled where it actually shows up: the contract fingerprint
|
|
45
45
|
* makes a real mismatch loud on the next tool result (see version-skew), and a stale entry of our own
|
|
46
|
-
* shape is now repaired on re-run rather than reported "already registered" (see
|
|
46
|
+
* shape is now repaired on re-run rather than reported "already registered" (see mcp-clients.ts).
|
|
47
47
|
*/
|
|
48
48
|
export declare function npxServerArgs(): string[];
|
|
49
49
|
/**
|