@reticlehq/server 2.7.0 → 2.9.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/README.md +14 -5
- package/SKILL.md +130 -778
- package/dist/bridge/bridge.d.ts +23 -0
- package/dist/bridge/bridge.js +80 -2
- package/dist/bridge/bridge.test-harness.d.ts +5 -0
- package/dist/bridge/bridge.test-harness.js +6 -4
- package/dist/capsule/causal-summary.d.ts +36 -1
- package/dist/capsule/causal-summary.js +33 -7
- package/dist/capsule/divergence.js +7 -1
- package/dist/cli/chromium-hint.d.ts +33 -5
- package/dist/cli/chromium-hint.js +82 -12
- package/dist/cli/cli-doctor.js +65 -34
- package/dist/cli/cli-flow-commands.js +8 -8
- package/dist/cli/cli-kill.d.ts +58 -0
- package/dist/cli/cli-kill.js +162 -0
- package/dist/cli/cli-parse.d.ts +16 -1
- package/dist/cli/cli-parse.js +32 -9
- package/dist/cli/cli-port.d.ts +32 -0
- package/dist/cli/cli-port.js +82 -35
- package/dist/cli/cli-verify.d.ts +21 -0
- package/dist/cli/cli-verify.js +47 -3
- package/dist/cli/config-discovery.d.ts +35 -0
- package/dist/cli/config-discovery.js +163 -0
- package/dist/cli/doctor-daemon-line.js +4 -1
- package/dist/cli/doctor-project-line.d.ts +37 -0
- package/dist/cli/doctor-project-line.js +35 -0
- package/dist/cli/doctor-rows.d.ts +51 -0
- package/dist/cli/doctor-rows.js +54 -0
- package/dist/cli/doctor-sessions-line.d.ts +12 -0
- package/dist/cli/doctor-sessions-line.js +69 -0
- package/dist/cli/drive-attach.d.ts +99 -0
- package/dist/cli/drive-attach.js +203 -0
- package/dist/cli/drive-command.d.ts +13 -0
- package/dist/cli/drive-command.js +103 -0
- package/dist/cli/open-note.d.ts +20 -0
- package/dist/cli/open-note.js +37 -0
- package/dist/cli/port-holder.d.ts +10 -0
- package/dist/cli/port-holder.js +26 -2
- package/dist/cli/status-next-action.d.ts +37 -0
- package/dist/cli/status-next-action.js +61 -0
- package/dist/cli.js +119 -39
- package/dist/crawl/crawl-tools.js +12 -2
- package/dist/crawl/crawl.d.ts +13 -0
- package/dist/crawl/crawl.js +50 -2
- package/dist/events/contradictions.d.ts +46 -0
- package/dist/events/contradictions.js +35 -22
- package/dist/events/declared.d.ts +45 -0
- package/dist/events/declared.js +73 -0
- package/dist/events/echo-mismatch.d.ts +8 -2
- package/dist/events/echo-mismatch.js +33 -5
- package/dist/events/event-filters.d.ts +1 -1
- package/dist/events/event-filters.js +7 -4
- package/dist/events/predicate-eval.d.ts +17 -72
- package/dist/events/predicate-eval.js +117 -236
- package/dist/events/predicate-parse.js +31 -3
- package/dist/events/predicate-route.d.ts +32 -0
- package/dist/events/predicate-route.js +102 -0
- package/dist/events/predicate-schema.d.ts +99 -0
- package/dist/events/predicate-schema.js +309 -0
- package/dist/events/predicate.d.ts +8 -0
- package/dist/events/predicate.js +296 -22
- package/dist/flows/annotate-tools.js +3 -0
- package/dist/flows/annotate.js +18 -4
- package/dist/flows/coverage.d.ts +38 -5
- package/dist/flows/coverage.js +30 -4
- package/dist/flows/decision.d.ts +15 -0
- package/dist/flows/decision.js +1 -1
- package/dist/flows/flow-classify.js +1 -1
- package/dist/flows/flow-replay-run.js +8 -1
- package/dist/flows/flow-tools.js +21 -5
- package/dist/flows/heal-run.js +1 -1
- package/dist/flows/replay.js +3 -0
- package/dist/honesty/accepted-write.d.ts +3 -0
- package/dist/honesty/accepted-write.js +8 -3
- package/dist/honesty/already-true.js +15 -0
- package/dist/honesty/blind-spots.js +10 -2
- package/dist/honesty/honesty.d.ts +11 -0
- package/dist/honesty/honesty.js +1 -0
- package/dist/honesty/uncaptured-bodies.d.ts +4 -2
- package/dist/honesty/uncaptured-bodies.js +9 -2
- package/dist/honesty/unread-outcome.d.ts +8 -0
- package/dist/honesty/unread-outcome.js +36 -9
- package/dist/honesty/unsettled.d.ts +49 -0
- package/dist/honesty/unsettled.js +82 -0
- package/dist/honesty/verified.d.ts +36 -3
- package/dist/honesty/verified.js +54 -11
- package/dist/http-server.d.ts +19 -0
- package/dist/http-server.js +202 -4
- package/dist/impact/impact-recorder.d.ts +23 -0
- package/dist/impact/impact-recorder.js +76 -0
- package/dist/impact/impact-store.d.ts +47 -0
- package/dist/impact/impact-store.js +171 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +47 -10
- package/dist/init/agent-rules.d.ts +36 -0
- package/dist/init/agent-rules.js +132 -22
- package/dist/init/astro-patch.d.ts +2 -1
- package/dist/init/astro-patch.js +38 -6
- package/dist/init/capabilities.d.ts +22 -0
- package/dist/init/capabilities.js +76 -0
- package/dist/init/confirm.d.ts +114 -0
- package/dist/init/confirm.js +165 -0
- package/dist/init/connect-steps.d.ts +2 -0
- package/dist/init/connect-steps.js +50 -0
- package/dist/init/cra.js +3 -2
- package/dist/init/csp-check.d.ts +38 -0
- package/dist/init/csp-check.js +92 -0
- package/dist/init/csp-doctor.d.ts +25 -0
- package/dist/init/csp-doctor.js +49 -0
- package/dist/init/cursor.js +6 -9
- package/dist/init/detect.d.ts +8 -0
- package/dist/init/detect.js +33 -3
- package/dist/init/mcp-clients.d.ts +1 -0
- package/dist/init/mcp-clients.js +51 -7
- package/dist/init/mcp.d.ts +15 -0
- package/dist/init/mcp.js +19 -0
- package/dist/init/non-js-project.js +29 -5
- package/dist/init/plan-framework.d.ts +10 -0
- package/dist/init/plan-framework.js +78 -16
- package/dist/init/plan.d.ts +47 -6
- package/dist/init/plan.js +228 -69
- package/dist/init/run.d.ts +24 -2
- package/dist/init/run.js +157 -45
- package/dist/init/slash-command.d.ts +1 -1
- package/dist/init/slash-command.js +54 -6
- package/dist/init/snippets.d.ts +45 -5
- package/dist/init/snippets.js +194 -42
- package/dist/init/vite-config.js +53 -5
- package/dist/input/network-mock-tools.d.ts +19 -0
- package/dist/input/network-mock-tools.js +37 -5
- package/dist/input/scroll-find.d.ts +6 -0
- package/dist/input/scroll-find.js +17 -2
- package/dist/input/scroll-tools.js +4 -0
- package/dist/journal/attach-journal.d.ts +9 -1
- package/dist/journal/attach-journal.js +13 -2
- package/dist/journal/journal-query.d.ts +13 -0
- package/dist/journal/journal-query.js +28 -3
- package/dist/journal/workspace-gitignore.d.ts +10 -0
- package/dist/journal/workspace-gitignore.js +59 -0
- package/dist/license/license.js +1 -1
- package/dist/mcp/mcp-proxy.d.ts +35 -30
- package/dist/mcp/mcp-proxy.js +306 -104
- package/dist/mcp/mcp.d.ts +10 -1
- package/dist/mcp/mcp.js +70 -34
- package/dist/mcp/proxy-handshake.d.ts +82 -1
- package/dist/mcp/proxy-handshake.js +109 -2
- package/dist/mcp/proxy-lifecycle.d.ts +11 -2
- package/dist/mcp/proxy-lifecycle.js +12 -3
- package/dist/mcp/proxy-log.d.ts +63 -0
- package/dist/mcp/proxy-log.js +132 -0
- package/dist/mcp/server-instructions.d.ts +17 -0
- package/dist/mcp/server-instructions.js +56 -0
- package/dist/mcp/shared-params.d.ts +27 -0
- package/dist/mcp/shared-params.js +36 -0
- package/dist/pool/browser-pool.d.ts +22 -2
- package/dist/pool/browser-pool.js +44 -4
- package/dist/project/learned-routes.d.ts +24 -0
- package/dist/project/learned-routes.js +63 -0
- package/dist/project/project-store.d.ts +6 -0
- package/dist/project/project-store.js +25 -1
- package/dist/project/reticle-dir.d.ts +2 -0
- package/dist/project/reticle-dir.js +1 -0
- package/dist/session/connection-memory.d.ts +59 -0
- package/dist/session/connection-memory.js +108 -0
- package/dist/session/dev-command.d.ts +26 -0
- package/dist/session/dev-command.js +89 -0
- package/dist/session/dev-server-probe.d.ts +68 -0
- package/dist/session/dev-server-probe.js +102 -7
- package/dist/session/last-act.d.ts +26 -0
- package/dist/session/last-act.js +35 -1
- package/dist/session/live-control-tools.js +42 -5
- package/dist/session/no-session-diagnosis.d.ts +67 -2
- package/dist/session/no-session-diagnosis.js +236 -27
- package/dist/session/no-session-next-action.d.ts +46 -0
- package/dist/session/no-session-next-action.js +85 -0
- package/dist/session/no-session-watch.d.ts +40 -1
- package/dist/session/no-session-watch.js +174 -8
- package/dist/session/pending-commands.d.ts +12 -0
- package/dist/session/pending-commands.js +13 -1
- package/dist/session/ref-provenance.d.ts +54 -0
- package/dist/session/ref-provenance.js +61 -0
- package/dist/session/session-lease.js +1 -1
- package/dist/session/session-manager.d.ts +4 -0
- package/dist/session/session-manager.js +35 -5
- package/dist/session/session.d.ts +10 -1
- package/dist/session/session.js +146 -5
- package/dist/telemetry/app-instrumented.d.ts +8 -0
- package/dist/telemetry/app-instrumented.js +10 -0
- package/dist/telemetry/automation-hint.d.ts +17 -0
- package/dist/telemetry/automation-hint.js +71 -0
- package/dist/telemetry/bug-found.d.ts +15 -17
- package/dist/telemetry/bug-found.js +52 -21
- package/dist/telemetry/cli-telemetry.js +7 -1
- package/dist/telemetry/daemon-telemetry.js +24 -0
- package/dist/telemetry/feedback.js +1 -1
- package/dist/telemetry/init-telemetry.js +9 -1
- package/dist/telemetry/install-source.d.ts +56 -0
- package/dist/telemetry/install-source.js +74 -0
- package/dist/telemetry/instrumentation-stall.d.ts +50 -0
- package/dist/telemetry/instrumentation-stall.js +90 -0
- package/dist/telemetry/run-telemetry.js +4 -1
- package/dist/telemetry/session-metrics.d.ts +8 -0
- package/dist/telemetry/session-metrics.js +15 -0
- package/dist/telemetry/telemetry.d.ts +7 -1
- package/dist/telemetry/telemetry.js +26 -2
- package/dist/telemetry/tool-refused.d.ts +19 -0
- package/dist/telemetry/tool-refused.js +55 -0
- package/dist/telemetry/verification-of.js +46 -7
- package/dist/temp-dir.d.ts +27 -0
- package/dist/temp-dir.js +46 -0
- package/dist/tools/act-tools.js +209 -28
- package/dist/tools/assert-grade.d.ts +1 -1
- package/dist/tools/assert-grade.js +27 -5
- package/dist/tools/assert-verdict.js +49 -7
- package/dist/tools/browser-tools.js +10 -0
- package/dist/tools/contract-tools.js +4 -0
- package/dist/tools/dynamic-tools.js +16 -7
- package/dist/tools/error-recovery.d.ts +10 -0
- package/dist/tools/error-recovery.js +73 -9
- package/dist/tools/feedback-invite.js +1 -1
- package/dist/tools/invoke-tool.js +159 -26
- package/dist/tools/lease-hint.d.ts +30 -8
- package/dist/tools/lease-hint.js +65 -14
- package/dist/tools/lease-tools.d.ts +40 -1
- package/dist/tools/lease-tools.js +181 -83
- package/dist/tools/navigate-result.js +1 -1
- package/dist/tools/observe-tools.js +10 -4
- package/dist/tools/observed-nothing.js +1 -1
- package/dist/tools/react-grace.d.ts +52 -0
- package/dist/tools/react-grace.js +90 -0
- package/dist/tools/read-tools.js +67 -5
- package/dist/tools/resolve-target.d.ts +33 -0
- package/dist/tools/resolve-target.js +53 -0
- package/dist/tools/settle-in-flight.d.ts +94 -0
- package/dist/tools/settle-in-flight.js +146 -0
- package/dist/tools/snapshot-delta.d.ts +10 -0
- package/dist/tools/snapshot-delta.js +194 -9
- package/dist/tools/tool-kit.d.ts +8 -0
- package/dist/tools/tool-surface.d.ts +60 -0
- package/dist/tools/tool-surface.js +86 -1
- package/dist/tools/tools.js +61 -8
- package/dist/tools/unadvertised-help.js +9 -6
- package/docs/README.md +55 -11
- package/docs/actions.mdx +120 -0
- package/docs/agent-cheatsheet.md +95 -29
- package/docs/architecture.md +52 -35
- package/docs/benchmarks.md +127 -75
- package/docs/best-practices.mdx +216 -0
- package/docs/capabilities.mdx +534 -0
- package/docs/cli/affected.mdx +53 -0
- package/docs/cli/capsules.mdx +70 -0
- package/docs/cli/cloud.mdx +153 -0
- package/docs/cli/doctor.mdx +109 -0
- package/docs/cli/drive.mdx +74 -0
- package/docs/cli/feedback.mdx +67 -0
- package/docs/cli/gate.mdx +64 -0
- package/docs/cli/help.mdx +94 -0
- package/docs/cli/hunt.mdx +73 -0
- package/docs/cli/identify.mdx +76 -0
- package/docs/cli/init.mdx +121 -0
- package/docs/cli/kill.mdx +91 -0
- package/docs/cli/license.mdx +48 -0
- package/docs/cli/mcp.mdx +61 -0
- package/docs/cli/open.mdx +74 -0
- package/docs/cli/restart.mdx +60 -0
- package/docs/cli/rollback.mdx +35 -0
- package/docs/cli/serve.mdx +69 -0
- package/docs/cli/status.mdx +88 -0
- package/docs/cli/stop.mdx +64 -0
- package/docs/cli/telemetry.mdx +57 -0
- package/docs/cli/update.mdx +52 -0
- package/docs/cli/verify.mdx +76 -0
- package/docs/cli/version.mdx +39 -0
- package/docs/cli/watch.mdx +62 -0
- package/docs/cli.mdx +241 -0
- package/docs/debugging.md +16 -10
- package/docs/deploy-checks.md +45 -12
- package/docs/desktop.mdx +384 -0
- package/docs/docs.json +364 -0
- package/docs/enterprise.md +22 -16
- package/docs/faq.mdx +102 -0
- package/docs/fixtures.md +13 -7
- package/docs/flows.md +29 -23
- package/docs/for-agents.md +71 -0
- package/docs/frameworks.mdx +238 -0
- package/docs/gate-plan.md +48 -42
- package/docs/gates.md +28 -22
- package/docs/getting-started.md +129 -77
- package/docs/human-control.md +24 -18
- package/docs/index.mdx +143 -0
- package/docs/install-agentic.mdx +224 -0
- package/docs/install-manual.mdx +196 -0
- package/docs/instrumentation.mdx +238 -0
- package/docs/integration-patterns.md +41 -35
- package/docs/local-registry.md +19 -13
- package/docs/multi-agent-testing.md +19 -13
- package/docs/packages/babel-plugin.mdx +79 -0
- package/docs/packages/browser.mdx +111 -0
- package/docs/packages/core.mdx +116 -0
- package/docs/packages/electron.mdx +85 -0
- package/docs/packages/eslint-plugin.mdx +86 -0
- package/docs/packages/next.mdx +89 -0
- package/docs/packages/react.mdx +91 -0
- package/docs/packages/server.mdx +98 -0
- package/docs/packages/tauri.mdx +63 -0
- package/docs/packages/test.mdx +119 -0
- package/docs/packages/vite-plugin.mdx +94 -0
- package/docs/packages.mdx +218 -0
- package/docs/platform-integration.md +35 -26
- package/docs/predicates.mdx +248 -0
- package/docs/quickstart.mdx +257 -0
- package/docs/recipes.mdx +282 -0
- package/docs/skill-file.mdx +107 -0
- package/docs/state-management.mdx +199 -0
- package/docs/style.css +14 -0
- package/docs/system-map.md +50 -33
- package/docs/telemetry-contract.md +106 -52
- package/docs/telemetry-events.mdx +475 -0
- package/docs/telemetry.md +63 -55
- package/docs/testing.md +44 -6
- package/docs/token-efficiency.md +37 -27
- package/docs/tools-act-and-wait.mdx +173 -0
- package/docs/tools-act-sequence.mdx +137 -0
- package/docs/tools-act.mdx +95 -0
- package/docs/tools-assert.mdx +129 -0
- package/docs/tools-console.mdx +63 -0
- package/docs/tools-inspect.mdx +88 -0
- package/docs/tools-navigate.mdx +99 -0
- package/docs/tools-network.mdx +119 -0
- package/docs/tools-observe.mdx +145 -0
- package/docs/tools-overview.mdx +160 -0
- package/docs/tools-query.mdx +126 -0
- package/docs/tools-session-and-feedback.mdx +112 -0
- package/docs/tools-sessions.mdx +94 -0
- package/docs/tools-snapshot.mdx +129 -0
- package/docs/tools-state.mdx +104 -0
- package/docs/tools-tools-and-run.mdx +156 -0
- package/docs/tools-wait-for.mdx +85 -0
- package/docs/troubleshooting.mdx +263 -0
- package/docs/usage.md +209 -165
- package/docs/vs-chrome-devtools-mcp.mdx +123 -0
- package/docs/vs-playwright-mcp.mdx +125 -0
- package/docs/vs-screenshots.mdx +137 -0
- package/docs/what-is-reticle.mdx +63 -0
- package/docs/why-reticle.mdx +109 -0
- package/package.json +5 -5
- package/docs/desktop-apps.md +0 -256
- package/docs/matrix/2.5.0/claude-code-machine.json +0 -19
- package/docs/matrix/2.5.0/codex-machine.json +0 -20
- package/docs/matrix/2.5.0/cursor-machine.json +0 -22
- package/docs/matrix/2.5.0/gemini-machine.json +0 -22
- package/docs/matrix/2.5.0/opencode-machine.json +0 -22
- package/docs/matrix/2.5.0/vscode-machine.json +0 -22
- package/docs/matrix/2.5.0/windsurf-machine.json +0 -22
- package/docs/matrix/MATRIX.md +0 -26
- package/docs/matrix/README.md +0 -59
- package/docs/mint.json +0 -61
package/dist/init/detect.js
CHANGED
|
@@ -168,12 +168,42 @@ const INSTALL_ARGS = {
|
|
|
168
168
|
[PackageManager.BUN]: ['add', '-d'],
|
|
169
169
|
[PackageManager.NPM]: ['i', '-D'],
|
|
170
170
|
};
|
|
171
|
+
/**
|
|
172
|
+
* Flags added only to the install we RUN, never to the one we print.
|
|
173
|
+
*
|
|
174
|
+
* The install is a child process whose output lands above ours. Measured on a real install: the run
|
|
175
|
+
* opened with "added 602 packages", a funding notice, and "14 vulnerabilities (7 moderate, 7 high)"
|
|
176
|
+
* with `npm audit fix` advice, before one line of Reticle output. A user's first impression of a
|
|
177
|
+
* verification tool was a wall of somebody else's security warnings, at exactly the moment they are
|
|
178
|
+
* deciding whether this tool is careful — and that audit summary describes their existing dependency
|
|
179
|
+
* tree, which our two dev packages neither caused nor can fix.
|
|
180
|
+
*
|
|
181
|
+
* Kept off `installCommand`, which is the string shown in the plan and the one a user copies when
|
|
182
|
+
* running it by hand: nobody should be taught to type our noise-suppression flags.
|
|
183
|
+
*
|
|
184
|
+
* Quieted, never silenced — the exit code and stderr are untouched, so a real failure of the step
|
|
185
|
+
* everything downstream depends on stays as loud as it was.
|
|
186
|
+
*
|
|
187
|
+
* npm only: pnpm, yarn and bun reject these, and an unknown flag would turn a working install into a
|
|
188
|
+
* hard failure, which is the opposite of the problem being fixed.
|
|
189
|
+
*/
|
|
190
|
+
const QUIET_INSTALL_ARGS = {
|
|
191
|
+
[PackageManager.NPM]: ['--no-audit', '--no-fund'],
|
|
192
|
+
};
|
|
171
193
|
/** Build a dev-dependency install command for one or more packages (e.g. the kit + its build plugin). */
|
|
172
194
|
export function installCommandParts(pm, pkgs) {
|
|
173
195
|
const list = 'string' === typeof pkgs ? [pkgs] : pkgs;
|
|
174
|
-
return { command: pm, args: [...INSTALL_ARGS[pm], ...list] };
|
|
196
|
+
return { command: pm, args: [...INSTALL_ARGS[pm], ...list, ...(QUIET_INSTALL_ARGS[pm] ?? [])] };
|
|
175
197
|
}
|
|
198
|
+
/**
|
|
199
|
+
* The install command as a human reads it — and deliberately NOT `installCommandParts` joined.
|
|
200
|
+
*
|
|
201
|
+
* This string is what the plan prints and what a user retypes when running the step by hand, so it
|
|
202
|
+
* must not carry the flags we add only to quieten our own child process. Built from `INSTALL_ARGS`
|
|
203
|
+
* directly for that reason; routing it through the parts would put `--no-audit --no-fund` in front of
|
|
204
|
+
* every reader and teach them our noise-suppression as if it were part of installing Reticle.
|
|
205
|
+
*/
|
|
176
206
|
export function installCommand(pm, pkgs) {
|
|
177
|
-
const
|
|
178
|
-
return `${
|
|
207
|
+
const list = 'string' === typeof pkgs ? [pkgs] : pkgs;
|
|
208
|
+
return `${pm} ${[...INSTALL_ARGS[pm], ...list].join(' ')}`;
|
|
179
209
|
}
|
package/dist/init/mcp-clients.js
CHANGED
|
@@ -18,13 +18,13 @@
|
|
|
18
18
|
* an install that reports success and registers nothing, which is the exact failure class this
|
|
19
19
|
* repo's install gate exists to catch.
|
|
20
20
|
*/
|
|
21
|
-
import { NPX, MCP_SERVER_NAME, npxServerArgs } from './mcp.js';
|
|
22
|
-
import { RETICLE_NPM_PACKAGE } from '../version/server-version.js';
|
|
21
|
+
import { NPX, MCP_SERVER_NAME, npxServerArgs, isReticleRegistration } from './mcp.js';
|
|
23
22
|
export const McpClient = {
|
|
24
23
|
CLAUDE_CODE: 'claude-code',
|
|
25
24
|
CURSOR: 'cursor',
|
|
26
25
|
WINDSURF: 'windsurf',
|
|
27
26
|
OPENCODE: 'opencode',
|
|
27
|
+
ANTIGRAVITY: 'antigravity',
|
|
28
28
|
CODEX: 'codex',
|
|
29
29
|
GEMINI: 'gemini',
|
|
30
30
|
VSCODE: 'vscode',
|
|
@@ -107,13 +107,57 @@ export const MCP_CLIENTS = [
|
|
|
107
107
|
{
|
|
108
108
|
id: McpClient.OPENCODE,
|
|
109
109
|
label: 'OpenCode',
|
|
110
|
-
|
|
111
|
-
|
|
110
|
+
/**
|
|
111
|
+
* HOME, not PROJECT — OpenCode is installed globally and configured globally, like Cursor.
|
|
112
|
+
*
|
|
113
|
+
* It was project-scoped as `opencode.json`, and registration is gated on the marker already
|
|
114
|
+
* existing, so a project that had never written one was skipped in SILENCE: the user has OpenCode
|
|
115
|
+
* installed, `init` says nothing about it, and the tools never appear. In the field every OpenCode
|
|
116
|
+
* user connected a client and produced zero tool calls and zero app connections, which is what
|
|
117
|
+
* "you were never wired" looks like from outside.
|
|
118
|
+
*
|
|
119
|
+
* Path verified against a real install (OpenCode 1.3.17), not recalled. The extension is `.jsonc`,
|
|
120
|
+
* which the old project marker could not have matched even where a project config existed. JSONC
|
|
121
|
+
* permits comments, and a config that genuinely has them fails to parse — which `mergeClientConfig`
|
|
122
|
+
* already answers with MANUAL and a printed block, rather than rewriting somebody's file and
|
|
123
|
+
* dropping their comments.
|
|
124
|
+
*/
|
|
125
|
+
scope: ConfigScope.HOME,
|
|
126
|
+
relPath: '.config/opencode/opencode.jsonc',
|
|
112
127
|
format: ConfigFormat.JSON,
|
|
113
128
|
serversKey: 'mcp',
|
|
114
129
|
entry: openCodeEntry,
|
|
115
130
|
docs: 'https://opencode.ai/docs/config — `mcp` key, type:"local", command is an array',
|
|
116
131
|
},
|
|
132
|
+
{
|
|
133
|
+
id: McpClient.ANTIGRAVITY,
|
|
134
|
+
label: 'Antigravity',
|
|
135
|
+
/**
|
|
136
|
+
* Nine users connected an MCP client through Antigravity and drove nothing at all.
|
|
137
|
+
*
|
|
138
|
+
* `init` did not know this client, so they hand-wired a registration - the connections are in the
|
|
139
|
+
* field data, so they got that far - and then never ran `init`, never instrumented an app, and
|
|
140
|
+
* never called a tool. Nothing in that state tells anyone there is a second half.
|
|
141
|
+
*
|
|
142
|
+
* Path and shape from Google's documentation rather than recall: `mcpServers`, at
|
|
143
|
+
* `~/.gemini/config/mcp_config.json`, and one file serves the 2.0 IDE, the CLI and the SDK. Same
|
|
144
|
+
* `command`/`args` object Cursor, Windsurf and Gemini CLI already use.
|
|
145
|
+
*
|
|
146
|
+
* It shares the `~/.gemini` tree with Gemini CLI, which is why the marker matters: registration is
|
|
147
|
+
* gated on the marker DIRECTORY, and these resolve to `.gemini/config` and `.gemini` respectively,
|
|
148
|
+
* so having one installed cannot make `init` write a config for the other.
|
|
149
|
+
*
|
|
150
|
+
* NOT verified against a running install. The path is documented, the merge is the shared JSON
|
|
151
|
+
* path that every other client here uses, and an unparseable config still degrades to a printed
|
|
152
|
+
* block rather than a rewrite.
|
|
153
|
+
*/
|
|
154
|
+
scope: ConfigScope.HOME,
|
|
155
|
+
relPath: '.gemini/config/mcp_config.json',
|
|
156
|
+
format: ConfigFormat.JSON,
|
|
157
|
+
serversKey: 'mcpServers',
|
|
158
|
+
entry: commandArgsEntry,
|
|
159
|
+
docs: 'https://antigravity.google/docs/mcp — ~/.gemini/config/mcp_config.json, `mcpServers` key',
|
|
160
|
+
},
|
|
117
161
|
{
|
|
118
162
|
id: McpClient.CODEX,
|
|
119
163
|
label: 'Codex CLI',
|
|
@@ -163,7 +207,8 @@ function parseConfig(existing) {
|
|
|
163
207
|
*
|
|
164
208
|
* What IS repaired is a stale entry of our own shape — an old pin, a moved command — which
|
|
165
209
|
* presence-only idempotency reported as "already registered" and never fixed, so an upgrade could
|
|
166
|
-
* not repair the thing an upgrade exists to repair
|
|
210
|
+
* not repair the thing an upgrade exists to repair — and a WRONG one, naming a Reticle package that
|
|
211
|
+
* has no MCP server in it (see isReticleRegistration).
|
|
167
212
|
*/
|
|
168
213
|
function leaveEntryAlone(existing, spec) {
|
|
169
214
|
if (JSON.stringify(existing) === JSON.stringify(spec.entry()))
|
|
@@ -173,8 +218,7 @@ function leaveEntryAlone(existing, spec) {
|
|
|
173
218
|
const record = existing;
|
|
174
219
|
// Both shapes carry the package name somewhere in a string; find it without assuming which field.
|
|
175
220
|
const tokens = [record.command, record.args].flat().filter((v) => 'string' === typeof v);
|
|
176
|
-
|
|
177
|
-
return !ours;
|
|
221
|
+
return !isReticleRegistration(tokens);
|
|
178
222
|
}
|
|
179
223
|
/**
|
|
180
224
|
* Merge our server into this client's config.
|
package/dist/init/mcp.d.ts
CHANGED
|
@@ -41,6 +41,21 @@ export declare const NPX = "npx";
|
|
|
41
41
|
* shape is now repaired on re-run rather than reported "already registered" (see cursor.ts).
|
|
42
42
|
*/
|
|
43
43
|
export declare function npxServerArgs(): string[];
|
|
44
|
+
/**
|
|
45
|
+
* Is this existing registration one WE are responsible for?
|
|
46
|
+
*
|
|
47
|
+
* Deliberately the SCOPE and not the server package. An entry naming any `@reticlehq/*` package is
|
|
48
|
+
* ours to repair — including one naming the WRONG package, which is the case this widened for:
|
|
49
|
+
* `args: ["@reticlehq/core","mcp"]` was reported from the field, where `core` has no `mcp` bin, so
|
|
50
|
+
* the client showed the server errored with zero tools while `init` reported it already wired and
|
|
51
|
+
* left it alone on every re-run. Every `reticle_*` tool was blocked until a human edited that file.
|
|
52
|
+
*
|
|
53
|
+
* An entry that names no Reticle package at all — a local build, a wrapper script — is still someone
|
|
54
|
+
* else's deliberate choice and is left exactly as it is.
|
|
55
|
+
*
|
|
56
|
+
* @param tokens every string in the entry's command + args, in any of the client shapes.
|
|
57
|
+
*/
|
|
58
|
+
export declare function isReticleRegistration(tokens: readonly string[]): boolean;
|
|
44
59
|
interface ClaudeAddCommand {
|
|
45
60
|
command: string;
|
|
46
61
|
args: string[];
|
package/dist/init/mcp.js
CHANGED
|
@@ -49,6 +49,25 @@ const CLAUDE_CLI = 'claude';
|
|
|
49
49
|
export function npxServerArgs() {
|
|
50
50
|
return [RETICLE_PACKAGE, MCP_SUBCOMMAND];
|
|
51
51
|
}
|
|
52
|
+
/** The npm scope every Reticle package shares — the marker of a registration we are entitled to fix. */
|
|
53
|
+
const RETICLE_SCOPE = '@reticlehq/';
|
|
54
|
+
/**
|
|
55
|
+
* Is this existing registration one WE are responsible for?
|
|
56
|
+
*
|
|
57
|
+
* Deliberately the SCOPE and not the server package. An entry naming any `@reticlehq/*` package is
|
|
58
|
+
* ours to repair — including one naming the WRONG package, which is the case this widened for:
|
|
59
|
+
* `args: ["@reticlehq/core","mcp"]` was reported from the field, where `core` has no `mcp` bin, so
|
|
60
|
+
* the client showed the server errored with zero tools while `init` reported it already wired and
|
|
61
|
+
* left it alone on every re-run. Every `reticle_*` tool was blocked until a human edited that file.
|
|
62
|
+
*
|
|
63
|
+
* An entry that names no Reticle package at all — a local build, a wrapper script — is still someone
|
|
64
|
+
* else's deliberate choice and is left exactly as it is.
|
|
65
|
+
*
|
|
66
|
+
* @param tokens every string in the entry's command + args, in any of the client shapes.
|
|
67
|
+
*/
|
|
68
|
+
export function isReticleRegistration(tokens) {
|
|
69
|
+
return tokens.includes(NPX) && tokens.some((t) => t.includes(RETICLE_SCOPE));
|
|
70
|
+
}
|
|
52
71
|
/** The full `npx …` invocation — the tail after `claude mcp add … --`. */
|
|
53
72
|
function serverInvocation() {
|
|
54
73
|
return [NPX, ...npxServerArgs()];
|
|
@@ -29,7 +29,13 @@ const ECOSYSTEM_MARKERS = [
|
|
|
29
29
|
['pom.xml', 'Java'],
|
|
30
30
|
['build.gradle', 'Java'],
|
|
31
31
|
['mix.exs', 'Elixir'],
|
|
32
|
+
// Not like the others. Every ecosystem above can grow a JS front end that Reticle instruments
|
|
33
|
+
// perfectly well, so their message ends with a lead. Flutter web paints into a canvas, and there
|
|
34
|
+
// is no DOM behind it at any path, so the honest answer is a named refusal.
|
|
35
|
+
['pubspec.yaml', 'Flutter'],
|
|
32
36
|
];
|
|
37
|
+
/** The one ecosystem where no directory, front end or flag could ever help. */
|
|
38
|
+
const FLUTTER = 'Flutter';
|
|
33
39
|
/** The ecosystem this directory looks like, or undefined when nothing says. */
|
|
34
40
|
export function detectNonJsEcosystem(exists) {
|
|
35
41
|
for (const [marker, name] of ECOSYSTEM_MARKERS) {
|
|
@@ -51,10 +57,28 @@ export function noPackageJsonMessage(exists) {
|
|
|
51
57
|
return ('No package.json found here, and no app directory beneath it either. Run `reticle init` from ' +
|
|
52
58
|
"your app's directory, or from a repo root that contains it.");
|
|
53
59
|
}
|
|
60
|
+
if (ecosystem === FLUTTER) {
|
|
61
|
+
// An agent on a Flutter workspace asked us to "support Flutter, or clearly identify it as
|
|
62
|
+
// unsupported during init". The second is the truthful one, and saying it by name in one line
|
|
63
|
+
// is the difference between an agent that stops and an agent that spends an hour looking for
|
|
64
|
+
// the package.json we told it was missing.
|
|
65
|
+
return ('This is a Flutter project. Reticle cannot instrument it, and no directory or flag will ' +
|
|
66
|
+
'change that: Reticle reads the DOM of a running page, and Flutter web paints its entire UI ' +
|
|
67
|
+
'into a single canvas element with no DOM behind it. Nothing here is missing or misconfigured. ' +
|
|
68
|
+
'If this repo also contains an ordinary web app with its own package.json, run `reticle init` ' +
|
|
69
|
+
'inside that directory instead.');
|
|
70
|
+
}
|
|
54
71
|
return (`This looks like a ${ecosystem} project, and there is no package.json here or in any app ` +
|
|
55
|
-
'directory beneath it.
|
|
56
|
-
'
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
72
|
+
'directory beneath it. That is not a blocker: Reticle needs its SDK loaded by the page, not ' +
|
|
73
|
+
'built by npm, and a page with no build step can load it from a URL. ' +
|
|
74
|
+
// The old message ended at "there is no directory you could run this from that would change
|
|
75
|
+
// that", which read as a refusal and was acted on as one — agents went looking for a bundler,
|
|
76
|
+
// or for a standalone build to inject by hand, or gave up and used a different tool. The
|
|
77
|
+
// capability was there the whole time; only the sentence was missing. Proven end to end on a
|
|
78
|
+
// page served by `python3 -m http.server` before this line was written.
|
|
79
|
+
'Add the script-tag snippet below to a template you only serve in development, then reload the ' +
|
|
80
|
+
'page. ' +
|
|
81
|
+
'If this project ALSO has a JS front end (a `frontend/`, `client/` or `assets/` directory with ' +
|
|
82
|
+
'its own package.json), running `reticle init` there instead gives you source mapping and ' +
|
|
83
|
+
'framework state as well: point at it with `--app <dir>`.');
|
|
60
84
|
}
|
|
@@ -57,3 +57,13 @@ export declare function svelteKitSteps(input: PlanInput): Step[];
|
|
|
57
57
|
* and a half-edited build config is worse than a documented manual step.
|
|
58
58
|
*/
|
|
59
59
|
export declare function astroSteps(input: PlanInput): Step[];
|
|
60
|
+
/**
|
|
61
|
+
* A Content-Security-Policy whose `connect-src` excludes the bridge, said out loud at install time.
|
|
62
|
+
*
|
|
63
|
+
* Both reported cases were Next apps where `init` printed success for every step and the app then
|
|
64
|
+
* never connected: the browser blocked the WebSocket and reported it in its own console, which
|
|
65
|
+
* nothing on this side reads. A NOTICE rather than a step, because editing someone's security policy
|
|
66
|
+
* is theirs to do — but it carries the exact text to paste, which is the difference between a
|
|
67
|
+
* warning and a fix.
|
|
68
|
+
*/
|
|
69
|
+
export declare function cspStep(input: PlanInput): Step[];
|
|
@@ -9,7 +9,9 @@ import { patchAstroConfig, patchAstroLayout } from './astro-patch.js';
|
|
|
9
9
|
import { CRA_DEV_MODULE_IMPORT, CRA_DEV_MODULE_PATH, CRA_ENV_PATH, CRA_TOKEN_PER_MACHINE_NOTICE, TOKEN_VAR, craDevModuleFile, craEnvPatch, craImportPatch, } from './cra.js';
|
|
10
10
|
import { PatchKind } from './patch-kind.js';
|
|
11
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, nuxtManual, NUXT_PLUGIN_PATH, } from './snippets.js';
|
|
12
|
-
import { StepStatus } from './plan.js';
|
|
12
|
+
import { RETICLE_CONFIG_FILE, StepStatus } from './plan.js';
|
|
13
|
+
import { RETICLE_DEFAULT_PORT } from '@reticlehq/core';
|
|
14
|
+
import { CSP_STEP_TITLE, cspPlanProblem } from './csp-check.js';
|
|
13
15
|
/** What adding `reticle()` to a Vite config buys, which differs by framework. */
|
|
14
16
|
export const VITE_PLUGIN_DETAIL = {
|
|
15
17
|
/** A plain Vite app gets both halves from the plugin. */
|
|
@@ -23,6 +25,36 @@ export const VITE_PLUGIN_DETAIL = {
|
|
|
23
25
|
SVELTEKIT: 'add reticle() to plugins (stamps data-reticle-source in .svelte components)',
|
|
24
26
|
};
|
|
25
27
|
const CAPABILITIES_TITLE = 'Capabilities + store';
|
|
28
|
+
/**
|
|
29
|
+
* The one step `init` genuinely cannot finish, addressed to the AGENT reading this report.
|
|
30
|
+
*
|
|
31
|
+
* It used to read "Capabilities are empty until you edit that file" and describe the consequence to
|
|
32
|
+
* a human — homework, in a report a human mostly does not read, naming no file to open and no thing
|
|
33
|
+
* to look for. The agent that ran `init` is right there, has the codebase, and can finish this in
|
|
34
|
+
* the same minute; what it needed was the specific instruction, not the rationale.
|
|
35
|
+
*
|
|
36
|
+
* What is left is exactly what could not be PROVEN from source: which atoms/actor/queryClient an
|
|
37
|
+
* adapter-wrapped store should be built from, and which elements matter enough to name. `init`
|
|
38
|
+
* emits nothing it cannot prove, because a wrong import here throws on every dev page load — worse
|
|
39
|
+
* than an empty file.
|
|
40
|
+
*/
|
|
41
|
+
const CAPABILITIES_TODO_TITLE = 'AGENT: finish the capabilities file';
|
|
42
|
+
function capabilitiesTodo(path, stores) {
|
|
43
|
+
const store = stores.length > 0
|
|
44
|
+
? `This app depends on a state library init cannot wire on its own (it needs an argument only ` +
|
|
45
|
+
`reading the code can supply). Uncomment the suggested line in that file and complete it: ` +
|
|
46
|
+
`${stores.join('; ')}.`
|
|
47
|
+
: `No state library was detected. If the app holds state somewhere init cannot see, register ` +
|
|
48
|
+
`it — see node_modules/@reticlehq/server/docs/usage.md.`;
|
|
49
|
+
return (`${path} was written but registers nothing, so \`hasCapabilities\` stays false and reticle_state ` +
|
|
50
|
+
`has nothing to read.\n` +
|
|
51
|
+
`Do this now, before driving anything:\n` +
|
|
52
|
+
` 1. ${store}\n` +
|
|
53
|
+
` 2. Open the app's main flow and add \`testids\` for the elements it touches (or add ` +
|
|
54
|
+
`data-testid attributes where there are none).\n` +
|
|
55
|
+
` 3. Prove it: drive one flow and check reticle_state returns your keys. An empty state read ` +
|
|
56
|
+
`means this file is still not doing anything, whatever else went green.`);
|
|
57
|
+
}
|
|
26
58
|
/**
|
|
27
59
|
* The dev module carrying `registerCapabilities` / `registerStore`.
|
|
28
60
|
*
|
|
@@ -37,23 +69,32 @@ function capabilitiesStep(input) {
|
|
|
37
69
|
title: CAPABILITIES_TITLE,
|
|
38
70
|
target: VITE_DEV_MODULE_PATH,
|
|
39
71
|
status: StepStatus.ALREADY,
|
|
40
|
-
detail: 'file exists
|
|
72
|
+
detail: 'file exists, left alone, it is yours to edit',
|
|
41
73
|
},
|
|
42
74
|
];
|
|
43
75
|
}
|
|
44
76
|
const testids = input.testids ?? [];
|
|
45
77
|
const stores = input.storeHints ?? [];
|
|
78
|
+
const wired = input.foundStores ?? [];
|
|
46
79
|
const found = testids.length > 0
|
|
47
80
|
? `${String(testids.length)} data-testid values`
|
|
48
81
|
: 'no data-testid values yet';
|
|
49
|
-
|
|
82
|
+
// A store we found and wired IS a registration, so the "registers nothing" notice must not fire.
|
|
83
|
+
const nothingToRegister = 0 === testids.length && 0 === stores.length && 0 === wired.length;
|
|
50
84
|
return [
|
|
51
85
|
{
|
|
52
86
|
title: CAPABILITIES_TITLE,
|
|
53
87
|
target: VITE_DEV_MODULE_PATH,
|
|
54
88
|
status: StepStatus.APPLY,
|
|
55
|
-
detail: `${found}; ${
|
|
56
|
-
|
|
89
|
+
detail: `${found}; ${wired.length > 0
|
|
90
|
+
? `registered ${wired.map((s) => `'${s.key}'`).join(', ')} from your source`
|
|
91
|
+
: stores.length > 0
|
|
92
|
+
? `store: uncomment the ${String(stores.length)} suggested line(s)`
|
|
93
|
+
: 'no state library detected'}`,
|
|
94
|
+
write: {
|
|
95
|
+
path: VITE_DEV_MODULE_PATH,
|
|
96
|
+
content: viteDevModuleFile(testids, stores, wired, input.detection.uiLibrary),
|
|
97
|
+
},
|
|
57
98
|
dependsOnInstall: true,
|
|
58
99
|
},
|
|
59
100
|
// The write is real; what it registers is not. `registerCapabilities({ testids: [], signals: [],
|
|
@@ -67,14 +108,10 @@ function capabilitiesStep(input) {
|
|
|
67
108
|
...(nothingToRegister
|
|
68
109
|
? [
|
|
69
110
|
{
|
|
70
|
-
title:
|
|
111
|
+
title: CAPABILITIES_TODO_TITLE,
|
|
71
112
|
target: VITE_DEV_MODULE_PATH,
|
|
72
113
|
status: StepStatus.NOTICE,
|
|
73
|
-
detail:
|
|
74
|
-
'no state library was detected, so `hasCapabilities` stays false and reticle_state ' +
|
|
75
|
-
'has nothing to read. Add data-testid to the elements your main flow touches, or ' +
|
|
76
|
-
'register a store in that file, and the agent gains what the app BELIEVES rather than ' +
|
|
77
|
-
'only what it rendered.',
|
|
114
|
+
detail: capabilitiesTodo(VITE_DEV_MODULE_PATH, stores),
|
|
78
115
|
},
|
|
79
116
|
]
|
|
80
117
|
: []),
|
|
@@ -94,7 +131,7 @@ function viteConfigSteps(input, detail) {
|
|
|
94
131
|
title: 'Vite plugin',
|
|
95
132
|
target: 'vite.config',
|
|
96
133
|
status: StepStatus.MANUAL,
|
|
97
|
-
detail: viteManual(port),
|
|
134
|
+
detail: viteManual(port, input.detection.uiLibrary),
|
|
98
135
|
},
|
|
99
136
|
];
|
|
100
137
|
}
|
|
@@ -115,7 +152,7 @@ function viteConfigSteps(input, detail) {
|
|
|
115
152
|
title: 'Vite plugin',
|
|
116
153
|
target: cfg.path,
|
|
117
154
|
status: StepStatus.MANUAL,
|
|
118
|
-
detail: `${patch.reason}\n\n${viteManual(port)}`,
|
|
155
|
+
detail: `${patch.reason}\n\n${viteManual(port, input.detection.uiLibrary)}`,
|
|
119
156
|
},
|
|
120
157
|
];
|
|
121
158
|
}
|
|
@@ -177,7 +214,10 @@ export function nextSteps(input) {
|
|
|
177
214
|
detail: 'create dev-only connect component',
|
|
178
215
|
write: {
|
|
179
216
|
path: devPath,
|
|
180
|
-
content: nextReticleDevFile(input.options.port, input.options.projectId, input.testids ?? [], input.storeHints ?? []
|
|
217
|
+
content: nextReticleDevFile(input.options.port, input.options.projectId, input.testids ?? [], input.storeHints ?? [],
|
|
218
|
+
// Next's dev module is not a sibling of `src/` — its imports are resolved from wherever
|
|
219
|
+
// the component actually lands (`app/`, or `src/app/` in a --src-dir app).
|
|
220
|
+
input.nextFoundStores ?? []),
|
|
181
221
|
},
|
|
182
222
|
dependsOnInstall: true,
|
|
183
223
|
};
|
|
@@ -338,7 +378,7 @@ export function svelteKitSteps(input) {
|
|
|
338
378
|
detail: 'create dev-only client connect (SvelteKit renders via app.html)',
|
|
339
379
|
write: {
|
|
340
380
|
path: SVELTEKIT_HOOKS_PATH,
|
|
341
|
-
content: svelteKitHooksFile(input.options.port, input.options.projectId),
|
|
381
|
+
content: svelteKitHooksFile(input.options.port, input.options.projectId, input.detection.uiLibrary),
|
|
342
382
|
},
|
|
343
383
|
dependsOnInstall: true,
|
|
344
384
|
},
|
|
@@ -375,7 +415,7 @@ export function astroSteps(input) {
|
|
|
375
415
|
// single recipe that does the whole job.
|
|
376
416
|
const manualWithLayout = astroManual(input.options.port, input.options.projectId, layout.path);
|
|
377
417
|
const configPatch = patchAstroConfig(config.source);
|
|
378
|
-
const layoutPatch = patchAstroLayout(layout.source, input.options.port, input.options.projectId);
|
|
418
|
+
const layoutPatch = patchAstroLayout(layout.source, input.options.port, input.options.projectId, input.detection.uiLibrary);
|
|
379
419
|
if (configPatch.kind === PatchKind.MANUAL || layoutPatch.kind === PatchKind.MANUAL) {
|
|
380
420
|
return [
|
|
381
421
|
{
|
|
@@ -391,3 +431,25 @@ export function astroSteps(input) {
|
|
|
391
431
|
patchStep('Connect snippet (Astro)', layout.path, layoutPatch, 'add the dev-only connect <script> before </body>', manualWithLayout),
|
|
392
432
|
];
|
|
393
433
|
}
|
|
434
|
+
/**
|
|
435
|
+
* A Content-Security-Policy whose `connect-src` excludes the bridge, said out loud at install time.
|
|
436
|
+
*
|
|
437
|
+
* Both reported cases were Next apps where `init` printed success for every step and the app then
|
|
438
|
+
* never connected: the browser blocked the WebSocket and reported it in its own console, which
|
|
439
|
+
* nothing on this side reads. A NOTICE rather than a step, because editing someone's security policy
|
|
440
|
+
* is theirs to do — but it carries the exact text to paste, which is the difference between a
|
|
441
|
+
* warning and a fix.
|
|
442
|
+
*/
|
|
443
|
+
export function cspStep(input) {
|
|
444
|
+
const problem = cspPlanProblem([input.nextConfigSource, input.nextLayout?.source], input.options.port ?? RETICLE_DEFAULT_PORT);
|
|
445
|
+
if (problem === undefined)
|
|
446
|
+
return [];
|
|
447
|
+
return [
|
|
448
|
+
{
|
|
449
|
+
title: CSP_STEP_TITLE,
|
|
450
|
+
target: input.nextConfigFile ?? RETICLE_CONFIG_FILE,
|
|
451
|
+
status: StepStatus.NOTICE,
|
|
452
|
+
detail: problem,
|
|
453
|
+
},
|
|
454
|
+
];
|
|
455
|
+
}
|
package/dist/init/plan.d.ts
CHANGED
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
* contents, produce an ordered list of steps — each marked apply / manual / already / skip. The
|
|
4
4
|
* runner performs the `write` side-effects; this module decides *what* should happen.
|
|
5
5
|
*/
|
|
6
|
-
import { Framework, type Detection } from './detect.js';
|
|
6
|
+
import { Framework, UiLibrary, type Detection } from './detect.js';
|
|
7
|
+
import type { FoundStore } from './capabilities.js';
|
|
7
8
|
import { type McpClient } from './mcp-clients.js';
|
|
8
9
|
/**
|
|
9
10
|
* Pin the SDK to the CLI's own version.
|
|
@@ -15,14 +16,20 @@ import { type McpClient } from './mcp-clients.js';
|
|
|
15
16
|
* irrelevant, and a skewed pair impossible to install by accident.
|
|
16
17
|
*/
|
|
17
18
|
export declare function pinnedPackages(packages: readonly string[], version: string | undefined): readonly string[];
|
|
18
|
-
/**
|
|
19
|
-
|
|
19
|
+
/**
|
|
20
|
+
* The dev-dependencies `reticle init` installs — kit (or sensor) first, build plugin next.
|
|
21
|
+
*
|
|
22
|
+
* `uiLibrary` matters because the framework does not always name the renderer. The rule below was
|
|
23
|
+
* already written for Nuxt, correctly, and applied only there: a Vue app on plain Vite is
|
|
24
|
+
* `Framework.VITE` and a SvelteKit app renders Svelte, and both were being handed the React kit
|
|
25
|
+
* right after `init` had detected the real UI library and said so on screen.
|
|
26
|
+
*/
|
|
27
|
+
export declare function frameworkPackages(framework: Framework, uiLibrary?: UiLibrary): readonly string[];
|
|
20
28
|
/** Exported so the init telemetry can tell an MCP-registration failure from a dependency install. */
|
|
21
29
|
export declare const MCP_TARGET = "global (claude user scope)";
|
|
22
|
-
/** True when this step is what makes the app dial the daemon. */
|
|
23
|
-
export declare function isConnectStep(title: string): boolean;
|
|
24
30
|
/** The step that runs the package manager — the other thing that commonly fails on a user's machine. */
|
|
25
31
|
export declare const DEPS_TARGET = "package.json";
|
|
32
|
+
export declare const RETICLE_CONFIG_FILE = ".reticle.json";
|
|
26
33
|
export declare const StepStatus: {
|
|
27
34
|
readonly APPLY: "apply";
|
|
28
35
|
readonly MANUAL: "manual";
|
|
@@ -77,6 +84,13 @@ export interface Step {
|
|
|
77
84
|
}
|
|
78
85
|
export interface Plan {
|
|
79
86
|
framework: Framework;
|
|
87
|
+
/**
|
|
88
|
+
* The renderer this app actually uses, carried so every consumer agrees on WHICH packages the
|
|
89
|
+
* plan installed. The retry guard checks node_modules for exactly those names; without this it
|
|
90
|
+
* looked for `@reticlehq/react` in a Vue app that had correctly been given the sensor, decided the
|
|
91
|
+
* install had failed, and skipped every wiring step on the retry.
|
|
92
|
+
*/
|
|
93
|
+
uiLibrary: UiLibrary;
|
|
80
94
|
steps: Step[];
|
|
81
95
|
}
|
|
82
96
|
export interface PlanInput {
|
|
@@ -144,6 +158,10 @@ export interface PlanInput {
|
|
|
144
158
|
testids?: readonly string[] | undefined;
|
|
145
159
|
/** Ready-to-uncomment `registerStore` lines for the state libraries the app actually depends on. */
|
|
146
160
|
storeHints?: readonly string[] | undefined;
|
|
161
|
+
/** Store instances found in the app's own source — imported and registered outright, not hinted. */
|
|
162
|
+
foundStores?: readonly FoundStore[] | undefined;
|
|
163
|
+
/** The same stores, with specifiers resolved from Next's dev-module directory instead of `src/`. */
|
|
164
|
+
nextFoundStores?: readonly FoundStore[] | undefined;
|
|
147
165
|
/** Whether src/reticle-dev.ts already exists — it is the one generated file users are meant to edit. */
|
|
148
166
|
viteDevModuleExists?: boolean | undefined;
|
|
149
167
|
/** Whether src/hooks.client.ts already exists (SvelteKit idempotency). */
|
|
@@ -159,10 +177,19 @@ export interface PlanInput {
|
|
|
159
177
|
pairingToken?: string;
|
|
160
178
|
/** Whether .reticle.json already exists in the project root (idempotency). */
|
|
161
179
|
reticleConfigExists?: boolean;
|
|
180
|
+
/**
|
|
181
|
+
* Its CONTENT, so an existing config can be checked instead of trusted.
|
|
182
|
+
*
|
|
183
|
+
* Existence alone said "a file is present" and was reported as "this is configured correctly" —
|
|
184
|
+
* see reticleConfigStep for the port that survived every re-run because of it.
|
|
185
|
+
*/
|
|
186
|
+
reticleConfigSource?: string | null | undefined;
|
|
162
187
|
/** Current project-root CLAUDE.md content (for the idempotent agent-rule merge), or null/undefined. */
|
|
163
188
|
claudeMdContent?: string | null | undefined;
|
|
164
|
-
/** Current project-root AGENTS.md content (cross-agent
|
|
189
|
+
/** Current project-root AGENTS.md content (the cross-agent rule), or null/undefined. */
|
|
165
190
|
agentsMdContent?: string | null | undefined;
|
|
191
|
+
/** Current project-root RETICLE.md content (the full rules), or null when absent. */
|
|
192
|
+
reticleMdContent?: string | null | undefined;
|
|
166
193
|
/**
|
|
167
194
|
* Current .cursor/rules/reticle.mdc content, or null when absent.
|
|
168
195
|
*
|
|
@@ -175,6 +202,20 @@ export interface PlanInput {
|
|
|
175
202
|
claudeCommandContent?: string | null | undefined;
|
|
176
203
|
/** Current .cursor/commands/reticle.md content, or null when absent. */
|
|
177
204
|
cursorCommandContent?: string | null | undefined;
|
|
205
|
+
/**
|
|
206
|
+
* Absolute directory the AGENT runs in, when that is not the app's directory.
|
|
207
|
+
*
|
|
208
|
+
* The rule and command files are read by the agent, not by the app, so a monorepo whose app is a
|
|
209
|
+
* directory down must still get its `/reticle` where the human's session actually stands. Absent
|
|
210
|
+
* (the single-package case) leaves every path project-relative exactly as before.
|
|
211
|
+
*/
|
|
212
|
+
agentFileRoot?: string | undefined;
|
|
213
|
+
/**
|
|
214
|
+
* Content of the `.reticle.json` already sitting at that agent root, or null/undefined when there
|
|
215
|
+
* is none. Content rather than existence, for the reason `reticleConfigSource` is: a root config
|
|
216
|
+
* that disagrees with the app's is worse than no root config, and only reading it can tell.
|
|
217
|
+
*/
|
|
218
|
+
agentRootConfigSource?: string | null | undefined;
|
|
178
219
|
options: {
|
|
179
220
|
port: number | undefined;
|
|
180
221
|
mcp: boolean;
|