@reticlehq/server 2.13.1 → 2.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/SKILL.md +8 -18
- package/bin/reticle.js +3 -0
- package/dist/bridge/auth-failure-reason.js +12 -1
- package/dist/bridge/bridge-security.d.ts +8 -0
- package/dist/bridge/bridge-security.js +6 -1
- package/dist/bridge/bridge.d.ts +3 -0
- package/dist/bridge/bridge.js +23 -1
- package/dist/bridge/bridge.test-harness.d.ts +10 -1
- package/dist/bridge/bridge.test-harness.js +7 -1
- package/dist/bridge/pairing-token.d.ts +17 -0
- package/dist/bridge/pairing-token.js +26 -0
- package/dist/bridge/token-auth.d.ts +7 -0
- package/dist/bridge/token-auth.js +7 -1
- package/dist/capsule/capsule-store.d.ts +4 -4
- package/dist/capsule/capsule.d.ts +1 -1
- package/dist/capsule/capsule.js +3 -3
- package/dist/capsule/causal-summary.d.ts +21 -1
- package/dist/capsule/causal-summary.js +8 -6
- package/dist/capsule/divergence.d.ts +1 -1
- package/dist/capsule/divergence.js +26 -10
- package/dist/chromium-launch-options.d.ts +2 -1
- package/dist/cli/adhoc-verdict.d.ts +58 -0
- package/dist/cli/adhoc-verdict.js +115 -0
- package/dist/cli/chromium-hint.d.ts +18 -4
- package/dist/cli/chromium-hint.js +54 -6
- package/dist/cli/cli-doctor.js +1 -2
- package/dist/cli/cli-flow-commands.d.ts +16 -2
- package/dist/cli/cli-flow-commands.js +28 -9
- package/dist/cli/cli-parse-feedback.js +1 -1
- package/dist/cli/cli-parse.d.ts +2 -1
- package/dist/cli/cli-parse.js +38 -0
- package/dist/cli/cli-port.d.ts +5 -13
- package/dist/cli/cli-port.js +5 -38
- package/dist/cli/cli-update-commands.js +4 -4
- package/dist/cli/cli-verify.d.ts +24 -7
- package/dist/cli/cli-verify.js +87 -13
- package/dist/cli/cloud-keystore.d.ts +2 -1
- package/dist/cli/cloud-login.d.ts +2 -1
- package/dist/cli/cloud-session.d.ts +2 -1
- package/dist/cli/cloud-session.js +1 -1
- package/dist/cli/daemon-start-options.d.ts +2 -1
- package/dist/cli/device-flow.d.ts +2 -2
- package/dist/cli/doctor-daemon-line.d.ts +2 -1
- package/dist/cli/doctor-project-line.d.ts +2 -1
- package/dist/cli/doctor-rows.d.ts +2 -1
- package/dist/cli/drive-attach.d.ts +4 -3
- package/dist/cli/gate-hook-message.d.ts +2 -1
- package/dist/cli/status-next-action.js +10 -11
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +21 -9
- package/dist/cloud/account-state.d.ts +20 -0
- package/dist/cloud/account-state.js +65 -0
- package/dist/cloud/cloud-sync.d.ts +46 -3
- package/dist/cloud/cloud-sync.js +116 -0
- package/dist/cloud/sync-cycle.d.ts +5 -4
- package/dist/cloud/sync-cycle.js +1 -1
- package/dist/cloud/sync-daemon.d.ts +3 -19
- package/dist/cloud/sync-daemon.js +2 -2
- package/dist/crawl/crawl-tools.js +1 -1
- package/dist/crawl/crawl.d.ts +5 -5
- package/dist/crawl/crawl.js +138 -4
- package/dist/daemon/daemon-resilience.d.ts +3 -2
- package/dist/daemon/daemon-resilience.js +43 -4
- package/dist/daemon/daemon-resolve.d.ts +0 -9
- package/dist/daemon/daemon-resolve.js +2 -2
- package/dist/daemon/dev-servers.d.ts +1 -1
- package/dist/daemon/dev-servers.js +1 -1
- package/dist/daemon/loopback-alias.d.ts +2 -1
- package/dist/daemon/startup-failure.d.ts +11 -0
- package/dist/daemon/startup-failure.js +46 -0
- package/dist/events/contradictions.d.ts +10 -16
- package/dist/events/contradictions.js +149 -17
- package/dist/events/declared.d.ts +13 -1
- package/dist/events/declared.js +59 -3
- package/dist/events/echo-mismatch.js +75 -6
- package/dist/events/lineage.d.ts +52 -0
- package/dist/events/lineage.js +122 -0
- package/dist/events/net-evidence.d.ts +21 -0
- package/dist/events/net-evidence.js +81 -0
- package/dist/events/predicate-console.d.ts +13 -0
- package/dist/events/predicate-console.js +138 -0
- package/dist/events/predicate-element.d.ts +13 -0
- package/dist/events/predicate-element.js +214 -0
- package/dist/events/predicate-eval.d.ts +15 -3
- package/dist/events/predicate-eval.js +128 -110
- package/dist/events/predicate-parse.js +34 -1
- package/dist/events/predicate-request-body.d.ts +50 -0
- package/dist/events/predicate-request-body.js +120 -0
- package/dist/events/predicate-route.d.ts +21 -1
- package/dist/events/predicate-route.js +149 -21
- package/dist/events/predicate-schema.d.ts +8 -1
- package/dist/events/predicate-schema.js +34 -0
- package/dist/events/predicate.d.ts +2 -0
- package/dist/events/predicate.js +52 -159
- package/dist/events/split-text-miss.d.ts +6 -4
- package/dist/events/split-text-miss.js +12 -5
- package/dist/flows/affected-tools.js +22 -9
- package/dist/flows/annotate.d.ts +2 -1
- package/dist/flows/annotate.js +19 -1
- package/dist/flows/coverage.d.ts +2 -2
- package/dist/flows/flake.d.ts +3 -3
- package/dist/flows/flow-expect-grammar.d.ts +33 -0
- package/dist/flows/flow-expect-grammar.js +155 -0
- package/dist/flows/flow-replay-run.d.ts +1 -1
- package/dist/flows/flow-replay-run.js +28 -15
- package/dist/flows/flow-replay.d.ts +10 -0
- package/dist/flows/flow-replay.js +57 -22
- package/dist/flows/flow-secret-field.d.ts +14 -0
- package/dist/flows/flow-secret-field.js +22 -0
- package/dist/flows/flow-step-runners.d.ts +1 -0
- package/dist/flows/flow-step-runners.js +91 -34
- package/dist/flows/flow-success.js +22 -0
- package/dist/flows/flow-tools.js +27 -8
- package/dist/flows/flow-upload-resolve.d.ts +23 -0
- package/dist/flows/flow-upload-resolve.js +46 -0
- package/dist/flows/flows.d.ts +15 -0
- package/dist/flows/flows.js +17 -14
- package/dist/flows/git-changed.d.ts +23 -4
- package/dist/flows/git-changed.js +32 -6
- package/dist/flows/heal-run.js +2 -2
- package/dist/flows/predicate-to-expect.d.ts +3 -2
- package/dist/flows/predicate-to-expect.js +11 -5
- package/dist/flows/recording-backtrack.d.ts +24 -0
- package/dist/flows/recording-backtrack.js +73 -0
- package/dist/flows/recordings.d.ts +6 -0
- package/dist/flows/replay-halt.d.ts +26 -0
- package/dist/flows/replay-halt.js +30 -0
- package/dist/flows/replay.d.ts +0 -8
- package/dist/flows/replay.js +15 -3
- package/dist/flows/suite-flakes.d.ts +2 -1
- package/dist/flows/verify-change-tools.js +16 -4
- package/dist/honesty/already-true.d.ts +14 -0
- package/dist/honesty/already-true.js +47 -4
- package/dist/honesty/blind-spots.d.ts +3 -1
- package/dist/honesty/blind-spots.js +24 -1
- package/dist/honesty/body-capture-remedy.d.ts +42 -0
- package/dist/honesty/body-capture-remedy.js +95 -0
- package/dist/honesty/feature-capture.d.ts +3 -2
- package/dist/honesty/feature-capture.js +1 -1
- package/dist/honesty/gap-ledger.d.ts +1 -1
- package/dist/honesty/gap-ledger.js +1 -1
- package/dist/honesty/instrumentation-gaps.d.ts +8 -1
- package/dist/honesty/instrumentation-gaps.js +12 -2
- package/dist/honesty/observability.d.ts +4 -3
- package/dist/honesty/tool-hit-rate.d.ts +3 -2
- package/dist/honesty/uncaptured-bodies.d.ts +3 -1
- package/dist/honesty/uncaptured-bodies.js +6 -2
- package/dist/honesty/unsettled.d.ts +9 -0
- package/dist/honesty/unsettled.js +45 -0
- package/dist/honesty/verified.d.ts +32 -1
- package/dist/honesty/verified.js +37 -10
- package/dist/impact/impact-store.d.ts +5 -14
- package/dist/impact/impact-store.js +49 -6
- package/dist/index.js +1 -1
- package/dist/input/network-detail.d.ts +26 -1
- package/dist/input/network-detail.js +44 -12
- package/dist/input/network-mock-tools.js +24 -17
- package/dist/input/real-input.js +1 -1
- package/dist/input/viewport-tools.js +25 -13
- package/dist/intent/inline-intent.d.ts +0 -10
- package/dist/intent/inline-intent.js +1 -1
- package/dist/intent/intent-shard-store.d.ts +3 -2
- package/dist/intent/intent-shard-store.js +1 -1
- package/dist/intent/intent-shard.d.ts +14 -14
- package/dist/intent/intent-shard.js +4 -4
- package/dist/intent/intent-store.d.ts +1 -1
- package/dist/intent/intent-store.js +1 -1
- package/dist/intent/intent-subject.d.ts +2 -1
- package/dist/intent/open-intents.d.ts +3 -2
- package/dist/license/license.d.ts +4 -4
- package/dist/license/license.js +1 -1
- package/dist/mcp/attach-memory.d.ts +2 -1
- package/dist/mcp/client-identity.d.ts +2 -1
- package/dist/mcp/mcp-outage.d.ts +1 -1
- package/dist/mcp/mcp-outage.js +1 -1
- package/dist/mcp/mcp-proxy.d.ts +3 -1
- package/dist/mcp/mcp-proxy.js +32 -7
- package/dist/mcp/mcp.js +3 -1
- package/dist/mcp/proxy-handshake.d.ts +2 -1
- package/dist/mcp/proxy-idle-exit.d.ts +45 -0
- package/dist/mcp/proxy-idle-exit.js +94 -0
- package/dist/mcp/server-instructions.d.ts +2 -1
- package/dist/memory/project-memory.d.ts +2 -3
- package/dist/memory/project-memory.js +1 -1
- package/dist/oracles/propose-consequences.js +5 -5
- package/dist/oracles/self-instrument.d.ts +2 -2
- package/dist/oracles/self-instrument.js +1 -1
- package/dist/platform.d.ts +3 -5
- package/dist/platform.js +3 -5
- package/dist/pool/browser-pool.d.ts +92 -0
- package/dist/pool/browser-pool.js +119 -5
- package/dist/pool/playwright-launcher.js +29 -2
- package/dist/pool/storage-seed.d.ts +23 -0
- package/dist/pool/storage-seed.js +198 -0
- package/dist/project/artifact-root.d.ts +2 -1
- package/dist/project/memory-fs.d.ts +2 -1
- package/dist/project/reticle-dir.js +1 -1
- package/dist/project/session-root.d.ts +8 -0
- package/dist/project/session-root.js +9 -2
- package/dist/runs/reticle-runner.d.ts +14 -1
- package/dist/runs/reticle-runner.js +39 -2
- package/dist/session/attachment-history.d.ts +2 -1
- package/dist/session/fake-session.d.ts +37 -0
- package/dist/session/fake-session.js +81 -0
- package/dist/session/lease-visibility.d.ts +2 -1
- package/dist/session/live-control-tools.js +6 -0
- package/dist/session/no-session-diagnosis.d.ts +17 -1
- package/dist/session/no-session-diagnosis.js +32 -6
- package/dist/session/no-session-next-action.d.ts +14 -0
- package/dist/session/no-session-next-action.js +18 -0
- package/dist/session/no-session-watch.js +46 -3
- package/dist/session/registered-projects.d.ts +54 -0
- package/dist/session/registered-projects.js +73 -0
- package/dist/session/review-store.d.ts +2 -1
- package/dist/session/session-health.d.ts +62 -1
- package/dist/session/session-health.js +82 -2
- package/dist/session/session-manager.d.ts +11 -1
- package/dist/session/session-manager.js +18 -3
- package/dist/session/session-replaced.d.ts +24 -0
- package/dist/session/session-replaced.js +29 -0
- package/dist/session/session-successor.js +20 -4
- package/dist/session/session.d.ts +13 -5
- package/dist/session/session.js +31 -23
- package/dist/setup/agent-configs.d.ts +3 -2
- package/dist/setup/agent-writer.d.ts +3 -2
- package/dist/setup/approval-migration.d.ts +2 -1
- package/dist/setup/approval-migration.js +1 -1
- package/dist/setup/auto-approve.d.ts +11 -19
- package/dist/setup/auto-approve.js +15 -12
- package/dist/{init → setup}/confirm.js +1 -1
- package/dist/setup/desktop-shape.d.ts +3 -2
- package/dist/setup/drive-agent.d.ts +2 -3
- package/dist/setup/drive-agent.js +1 -1
- package/dist/setup/drive-plan.d.ts +3 -2
- package/dist/setup/ensure-daemon.d.ts +2 -1
- package/dist/setup/existing-app.d.ts +12 -0
- package/dist/setup/existing-app.js +13 -0
- package/dist/setup/init-host.d.ts +11 -0
- package/dist/setup/init-host.js +26 -0
- package/dist/setup/init-runtime.d.ts +4 -10
- package/dist/setup/init-runtime.js +23 -16
- package/dist/setup/license-key.d.ts +2 -1
- package/dist/setup/listeners.d.ts +2 -1
- package/dist/setup/loopback-probe-urls.d.ts +18 -0
- package/dist/setup/loopback-probe-urls.js +52 -0
- package/dist/setup/node-effects.d.ts +3 -0
- package/dist/setup/node-effects.js +26 -11
- package/dist/setup/page-probe.d.ts +5 -0
- package/dist/setup/relaunch.d.ts +2 -1
- package/dist/setup/run-setup.d.ts +5 -1
- package/dist/setup/run-setup.js +141 -50
- package/dist/setup/setup-command.d.ts +3 -2
- package/dist/setup/setup-command.js +8 -0
- package/dist/setup/setup-options.d.ts +5 -3
- package/dist/setup/setup-options.js +3 -2
- package/dist/setup/wait-progress.d.ts +28 -0
- package/dist/setup/wait-progress.js +43 -0
- package/dist/telemetry/app-instrumented.d.ts +2 -1
- package/dist/telemetry/app-instrumented.js +1 -1
- package/dist/telemetry/automation-hint.d.ts +1 -1
- package/dist/telemetry/automation-hint.js +1 -1
- package/dist/telemetry/cli-telemetry.js +1 -1
- package/dist/telemetry/connect-failure.d.ts +1 -1
- package/dist/telemetry/connect-failure.js +1 -1
- package/dist/telemetry/crash-cause.d.ts +3 -2
- package/dist/telemetry/crash-cause.js +1 -1
- package/dist/telemetry/daemon-telemetry.d.ts +3 -2
- package/dist/telemetry/daemon-telemetry.js +1 -1
- package/dist/telemetry/error-class.d.ts +3 -2
- package/dist/telemetry/error-class.js +1 -1
- package/dist/telemetry/feedback-cli.js +1 -1
- package/dist/telemetry/feedback-context.d.ts +3 -2
- package/dist/telemetry/feedback-context.js +5 -4
- package/dist/telemetry/feedback-local.d.ts +3 -2
- package/dist/telemetry/feedback.d.ts +4 -3
- package/dist/telemetry/feedback.js +1 -1
- package/dist/telemetry/git-facts.d.ts +2 -2
- package/dist/telemetry/git-facts.js +1 -1
- package/dist/telemetry/identify.d.ts +1 -1
- package/dist/telemetry/identify.js +1 -1
- package/dist/telemetry/init-telemetry.d.ts +2 -14
- package/dist/telemetry/init-telemetry.js +4 -13
- package/dist/telemetry/install-source.d.ts +7 -13
- package/dist/telemetry/install-source.js +7 -29
- package/dist/telemetry/license-activation.d.ts +3 -2
- package/dist/telemetry/license-activation.js +1 -1
- package/dist/telemetry/machine-snapshot.d.ts +1 -1
- package/dist/telemetry/mcp-connection.js +1 -1
- package/dist/telemetry/project-profile.d.ts +0 -14
- package/dist/telemetry/project-profile.js +1 -1
- package/dist/telemetry/proxy-telemetry.js +1 -1
- package/dist/telemetry/session-metrics.d.ts +1 -1
- package/dist/telemetry/session-metrics.js +1 -1
- package/dist/telemetry/telemetry.d.ts +1 -17
- package/dist/telemetry/telemetry.js +4 -4
- package/dist/telemetry/tool-refused.d.ts +1 -1
- package/dist/telemetry/tool-refused.js +1 -1
- package/dist/tools/act-observation.d.ts +3 -2
- package/dist/tools/act-preflight.js +8 -3
- package/dist/tools/act-target.d.ts +4 -0
- package/dist/tools/act-target.js +14 -5
- package/dist/tools/act-tools.d.ts +0 -2
- package/dist/tools/act-tools.js +45 -15
- package/dist/tools/assert-source.d.ts +30 -0
- package/dist/tools/assert-source.js +21 -0
- package/dist/tools/assert-verdict.d.ts +1 -1
- package/dist/tools/assert-verdict.js +14 -4
- package/dist/tools/browser-tools.js +28 -8
- package/dist/tools/complete-snapshot.d.ts +3 -2
- package/dist/tools/dynamic-tools.js +8 -0
- package/dist/tools/error-recovery.d.ts +10 -0
- package/dist/tools/error-recovery.js +23 -0
- package/dist/tools/feedback-tools.js +1 -1
- package/dist/tools/invoke-tool.js +2 -0
- package/dist/tools/lease-tools.d.ts +48 -20
- package/dist/tools/lease-tools.js +311 -76
- package/dist/tools/lineage-tools.d.ts +14 -0
- package/dist/tools/lineage-tools.js +64 -0
- package/dist/tools/merge-tools.js +1 -3
- package/dist/tools/navigate-arrival.d.ts +45 -1
- package/dist/tools/navigate-arrival.js +39 -6
- package/dist/tools/navigate-result.d.ts +8 -1
- package/dist/tools/navigate-result.js +14 -4
- package/dist/tools/numeric-bounds.d.ts +0 -11
- package/dist/tools/numeric-bounds.js +4 -4
- package/dist/tools/observe-tools.js +22 -26
- package/dist/tools/observed-nothing.d.ts +9 -0
- package/dist/tools/observed-nothing.js +2 -1
- package/dist/tools/read-tools.js +12 -17
- package/dist/tools/real-input-attempt.d.ts +14 -6
- package/dist/tools/real-input-attempt.js +75 -18
- package/dist/tools/reconcile-tools.js +2 -1
- package/dist/tools/reload-result.d.ts +6 -1
- package/dist/tools/reload-result.js +7 -2
- package/dist/tools/resolve-target.d.ts +7 -1
- package/dist/tools/resolve-target.js +72 -9
- package/dist/tools/settle-in-flight.d.ts +1 -1
- package/dist/tools/settle-in-flight.js +9 -2
- package/dist/tools/snapshot-delta.d.ts +24 -1
- package/dist/tools/snapshot-delta.js +66 -7
- package/dist/tools/tool-names.d.ts +1 -0
- package/dist/tools/tool-names.js +1 -0
- package/dist/tools/tool-surface.js +20 -2
- package/dist/tools/tools.js +120 -11
- package/dist/tools/verify-next-baton.d.ts +2 -1
- package/dist/update/sdk-sync.d.ts +1 -1
- package/dist/update/sdk-sync.js +1 -1
- package/dist/update/updater.js +1 -1
- package/dist/version/sdk-fix.d.ts +2 -1
- package/dist/version/version-skew.d.ts +0 -8
- package/dist/version/version-skew.js +1 -1
- package/docs/README.md +8 -6
- package/docs/actions.mdx +1 -1
- package/docs/agent-cheatsheet.md +4 -2
- package/docs/architecture.md +1 -1
- package/docs/cli/mcp.mdx +3 -1
- package/docs/cli/watch.mdx +1 -1
- package/docs/cli.mdx +1 -1
- package/docs/desktop.mdx +1 -1
- package/docs/docs.json +8 -3
- package/docs/faq.mdx +9 -0
- package/docs/first-drive.md +136 -0
- package/docs/frameworks.mdx +29 -7
- package/docs/gate-plan.md +2 -2
- package/docs/gates.md +19 -11
- package/docs/getting-started.md +7 -1
- package/docs/http-transport.md +164 -0
- package/docs/index.mdx +5 -3
- package/docs/install-manual.mdx +1 -1
- package/docs/packages/tauri.mdx +1 -1
- package/docs/packages.mdx +15 -3
- package/docs/platform-integration.md +1 -1
- package/docs/predicates.mdx +2 -0
- package/docs/system-map.md +2 -2
- package/docs/telemetry-contract.md +4 -4
- package/docs/telemetry-events.mdx +1 -1
- package/docs/telemetry.md +3 -3
- package/docs/tools-navigate.mdx +14 -6
- package/docs/usage.md +4 -4
- package/package.json +7 -4
- package/dist/init/agent-rules.d.ts +0 -116
- package/dist/init/agent-rules.js +0 -279
- package/dist/init/app-choice.d.ts +0 -20
- package/dist/init/app-choice.js +0 -25
- package/dist/init/astro-host.d.ts +0 -21
- package/dist/init/astro-host.js +0 -27
- package/dist/init/astro-patch.d.ts +0 -33
- package/dist/init/astro-patch.js +0 -300
- package/dist/init/capabilities.d.ts +0 -40
- package/dist/init/capabilities.js +0 -150
- package/dist/init/closing-hint.d.ts +0 -36
- package/dist/init/closing-hint.js +0 -120
- package/dist/init/connect-steps.d.ts +0 -2
- package/dist/init/connect-steps.js +0 -50
- package/dist/init/cra.d.ts +0 -79
- package/dist/init/cra.js +0 -178
- package/dist/init/csp-check.d.ts +0 -38
- package/dist/init/csp-check.js +0 -107
- package/dist/init/csp-doctor.d.ts +0 -32
- package/dist/init/csp-doctor.js +0 -54
- package/dist/init/desktop-doctor.d.ts +0 -41
- package/dist/init/desktop-doctor.js +0 -198
- package/dist/init/detect.d.ts +0 -96
- package/dist/init/detect.js +0 -209
- package/dist/init/dev-script.d.ts +0 -50
- package/dist/init/dev-script.js +0 -66
- package/dist/init/format-generated.d.ts +0 -18
- package/dist/init/format-generated.js +0 -39
- package/dist/init/install-hint.d.ts +0 -9
- package/dist/init/install-hint.js +0 -29
- package/dist/init/mcp-clients.d.ts +0 -89
- package/dist/init/mcp-clients.js +0 -299
- package/dist/init/mcp-registered.d.ts +0 -12
- package/dist/init/mcp-registered.js +0 -14
- package/dist/init/mcp.d.ts +0 -89
- package/dist/init/mcp.js +0 -129
- package/dist/init/next-patch.d.ts +0 -39
- package/dist/init/next-patch.js +0 -196
- package/dist/init/node-io.d.ts +0 -7
- package/dist/init/node-io.js +0 -117
- package/dist/init/non-js-project.d.ts +0 -27
- package/dist/init/non-js-project.js +0 -84
- package/dist/init/patch-kind.d.ts +0 -20
- package/dist/init/patch-kind.js +0 -10
- package/dist/init/plan-framework.d.ts +0 -64
- package/dist/init/plan-framework.js +0 -565
- package/dist/init/plan.d.ts +0 -242
- package/dist/init/plan.js +0 -703
- package/dist/init/preflight.d.ts +0 -28
- package/dist/init/preflight.js +0 -38
- package/dist/init/project-id.d.ts +0 -12
- package/dist/init/project-id.js +0 -25
- package/dist/init/refresh-rules.d.ts +0 -39
- package/dist/init/refresh-rules.js +0 -51
- package/dist/init/run.d.ts +0 -117
- package/dist/init/run.js +0 -806
- package/dist/init/slash-command.d.ts +0 -27
- package/dist/init/slash-command.js +0 -132
- package/dist/init/snippets.d.ts +0 -134
- package/dist/init/snippets.js +0 -572
- package/dist/init/vite-config.d.ts +0 -18
- package/dist/init/vite-config.js +0 -114
- package/dist/init/windows-quote.d.ts +0 -38
- package/dist/init/windows-quote.js +0 -70
- package/dist/init/workspace-apps.d.ts +0 -30
- package/dist/init/workspace-apps.js +0 -178
- package/dist/project/remember-project.d.ts +0 -24
- package/dist/project/remember-project.js +0 -40
- /package/dist/{init → setup}/confirm.d.ts +0 -0
package/dist/setup/run-setup.js
CHANGED
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
* and a real browser to find out what happens when neither works.
|
|
13
13
|
*/
|
|
14
14
|
import { judgeWait, QUIET_MEANS_HUNG_MS, urlToWatch, WaitVerdict } from './dev-server-wait.js';
|
|
15
|
+
import { waitProgressLine } from './wait-progress.js';
|
|
15
16
|
/**
|
|
16
17
|
* Windows gets longer to say something before silence counts as a wedge.
|
|
17
18
|
*
|
|
@@ -26,10 +27,17 @@ import { judgeWait, QUIET_MEANS_HUNG_MS, urlToWatch, WaitVerdict } from './dev-s
|
|
|
26
27
|
const WINDOWS_QUIET_MEANS_HUNG_MS = 3 * 60_000;
|
|
27
28
|
const WINDOWS_QUIET_MEANS_HUNG_MS_APPLIES = 'win32' === process.platform;
|
|
28
29
|
import { pickSession } from './session-pick.js';
|
|
29
|
-
import { readPage, describePage } from './page-probe.js';
|
|
30
|
+
import { readPage, describePage, PageFinding } from './page-probe.js';
|
|
30
31
|
import { remainingSteps } from './remaining-steps.js';
|
|
31
32
|
import { AppShape, isDesktop, policyFor } from './desktop-shape.js';
|
|
32
33
|
/** Where a run got to, and why it stopped if it did. */
|
|
34
|
+
/**
|
|
35
|
+
* How long to keep asking whether the SDK has reached the page before giving up on opening a window.
|
|
36
|
+
* Bounded by the connect budget, so a short budget is never overrun by the readiness check.
|
|
37
|
+
*/
|
|
38
|
+
const SDK_READY_WINDOW_MS = 15_000;
|
|
39
|
+
/** The wait left when no browser was opened: only a tab that is ALREADY loaded can still appear. */
|
|
40
|
+
const NO_BROWSER_GRACE_MS = 3_000;
|
|
33
41
|
export const SetupPhase = {
|
|
34
42
|
DEV_SERVER: 'dev-server',
|
|
35
43
|
CONNECT: 'connect',
|
|
@@ -68,54 +76,81 @@ export async function runSetupPhases(input, fx) {
|
|
|
68
76
|
};
|
|
69
77
|
// ── the app has to be running ────────────────────────────────────────────────────────────────
|
|
70
78
|
let url = input.suppliedUrl;
|
|
79
|
+
let attachedToExisting = false;
|
|
71
80
|
if (undefined === url) {
|
|
72
|
-
|
|
81
|
+
const announced = undefined === fx.existingAppUrl ? undefined : await fx.existingAppUrl();
|
|
82
|
+
if (undefined !== announced && 0 < announced.length) {
|
|
83
|
+
// The plugin already announced a live server for THIS project. Starting `dev` beside it is
|
|
84
|
+
// how Vite binds 5174, a second tab opens, and `reticle_sessions` lists three with no way
|
|
85
|
+
// to pick. The registry is scoped; an unscoped listen would attach to a sibling app.
|
|
86
|
+
url = announced;
|
|
87
|
+
attachedToExisting = true;
|
|
88
|
+
note(`This project is already running at ${announced} — attaching instead of starting a second server.`);
|
|
89
|
+
}
|
|
90
|
+
else if (undefined === input.devCommand) {
|
|
73
91
|
note(
|
|
74
92
|
// "stop here rather than invent one" is the SKILL.md rule, and the words are the contract —
|
|
75
93
|
// inventing a dev command is how a setup script runs the wrong thing and reports success.
|
|
76
94
|
'No dev command: the project names no dev, start or serve script, and there is no --url. ' +
|
|
77
|
-
'Stopping here rather than invent one —
|
|
95
|
+
'Stopping here rather than invent one — start the app yourself and pass --url to say ' +
|
|
96
|
+
'where it is serving, or add a dev/start/serve script to package.json and re-run.');
|
|
78
97
|
return stop(input, SetupPhase.DEV_SERVER, {}, notes);
|
|
79
98
|
}
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
99
|
+
else {
|
|
100
|
+
await fx.startDevServer(input.devCommand, input.appDir);
|
|
101
|
+
const startedAt = fx.now();
|
|
102
|
+
// This loop used to poll in complete silence. Reported as thirty minutes of nothing ending in a
|
|
103
|
+
// SIGKILL — and whatever made that wait long, a user who cannot tell "still starting" from
|
|
104
|
+
// "wedged" has been given no way to act. See wait-progress.ts.
|
|
105
|
+
let spokeAtMs;
|
|
106
|
+
for (;;) {
|
|
107
|
+
const watching = urlToWatch(fx.devServerOutput(), fx.observedPorts());
|
|
108
|
+
const waitedMs = fx.now() - startedAt;
|
|
109
|
+
const progress = waitProgressLine(waitedMs, watching, spokeAtMs);
|
|
110
|
+
if (progress !== undefined) {
|
|
111
|
+
note(progress);
|
|
112
|
+
spokeAtMs = waitedMs;
|
|
113
|
+
}
|
|
114
|
+
const probe = undefined === watching
|
|
115
|
+
? { served: false, sdkInPage: false }
|
|
116
|
+
: await fx.probePage(watching);
|
|
117
|
+
const serving = probe.served;
|
|
118
|
+
const verdict = judgeWait({
|
|
119
|
+
output: fx.devServerOutput(),
|
|
120
|
+
launcherExited: fx.devServerExited(),
|
|
121
|
+
serving,
|
|
122
|
+
quietForMs: fx.devServerQuietForMs(),
|
|
123
|
+
elapsedMs: fx.now() - startedAt,
|
|
124
|
+
quietMeansHungMs: WINDOWS_QUIET_MEANS_HUNG_MS_APPLIES
|
|
125
|
+
? WINDOWS_QUIET_MEANS_HUNG_MS
|
|
126
|
+
: QUIET_MEANS_HUNG_MS,
|
|
127
|
+
});
|
|
128
|
+
if (WaitVerdict.READY === verdict && undefined !== watching) {
|
|
129
|
+
// Prefer the URL that answered when the announcement was the wrong family (#884).
|
|
130
|
+
url = probe.reachedUrl ?? watching;
|
|
131
|
+
break;
|
|
132
|
+
}
|
|
133
|
+
// A desktop shell serves its webview from inside the app, so there is no port to answer and
|
|
134
|
+
// nothing to be READY. Once it has announced a url, or bound one we can see, that is as far
|
|
135
|
+
// as this phase can get: the session it dials from its own window is the real signal.
|
|
136
|
+
if (isDesktop(input.shape) && undefined !== watching) {
|
|
137
|
+
url = watching;
|
|
138
|
+
break;
|
|
139
|
+
}
|
|
140
|
+
if (WaitVerdict.DEAD === verdict) {
|
|
141
|
+
note('The dev server exited without serving anything.');
|
|
142
|
+
return stop(input, SetupPhase.DEV_SERVER, {}, notes);
|
|
143
|
+
}
|
|
144
|
+
if (WaitVerdict.HUNG === verdict) {
|
|
145
|
+
// Says BOTH were checked. A server that prints nothing but IS listening is the CRA case and
|
|
146
|
+
// must not be failed, so a reader has to be able to tell "we looked at the log" from "we
|
|
147
|
+
// looked at the log AND the ports".
|
|
148
|
+
note('The dev server neither printed a URL nor bound a port, so setup has nothing to open. ' +
|
|
149
|
+
'Check its log, or pass --url with the address it serves.');
|
|
150
|
+
return stop(input, SetupPhase.DEV_SERVER, {}, notes);
|
|
151
|
+
}
|
|
152
|
+
await fx.sleep(input.pollMs);
|
|
117
153
|
}
|
|
118
|
-
await fx.sleep(input.pollMs);
|
|
119
154
|
}
|
|
120
155
|
}
|
|
121
156
|
// ── and something has to connect from inside it ──────────────────────────────────────────────
|
|
@@ -123,17 +158,73 @@ export async function runSetupPhases(input, fx) {
|
|
|
123
158
|
// Through `note`, not `fx.note`: a caller reading the result should see it too.
|
|
124
159
|
if (undefined !== policy.note)
|
|
125
160
|
note(policy.note);
|
|
126
|
-
const
|
|
127
|
-
|
|
128
|
-
//
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
161
|
+
const listed = await fx.listSessions();
|
|
162
|
+
const requiredRuntime = isDesktop(input.shape) ? input.shape : undefined;
|
|
163
|
+
// A tab already on this URL is the answer. Opening another is how three sessions appear.
|
|
164
|
+
// `before` is empty so pickSession will take that tab rather than waiting for a new one.
|
|
165
|
+
const alreadyConnected = attachedToExisting
|
|
166
|
+
? pickSession(listed, url, new Set(), requiredRuntime)
|
|
167
|
+
: null;
|
|
168
|
+
const before = new Set(listed.map((s) => s.sessionId));
|
|
169
|
+
// Do not put a window in front of somebody until the page behind it can actually do something.
|
|
170
|
+
//
|
|
171
|
+
// The probe that says whether the SDK is even IN the page used to run only in the failure branch
|
|
172
|
+
// below, AFTER the browser was already open. So a mis-wired app opened a real window onto a page
|
|
173
|
+
// that was never going to connect, and the person watching it saw a browser appear and then
|
|
174
|
+
// nothing happen for the whole connect budget — which reads as "Reticle is broken" rather than
|
|
175
|
+
// "the bundle predates the config edit". One fetch, before the window, turns that into a sentence.
|
|
176
|
+
//
|
|
177
|
+
// Only the browser is gated. The wait below still runs: something else may connect (an already
|
|
178
|
+
// open tab, a desktop window), and the probe is a statement about one fetch of the document, not
|
|
179
|
+
// proof that nothing can ever dial in.
|
|
180
|
+
const budgetMs = input.connectBudgetMs ?? Math.max(input.phaseTimeoutMs, policy.connectBudgetMs);
|
|
181
|
+
let openedBrowser = false;
|
|
182
|
+
if (null === alreadyConnected && input.openBrowser && policy.openBrowser) {
|
|
183
|
+
// SERVED is the precondition, not SDK_PRESENT: a url that answers nothing is the only state
|
|
184
|
+
// where a window is certainly useless. Whether the SDK is in the served HTML is a DIFFERENT
|
|
185
|
+
// question — Vite injects a marker, while Nuxt, React Router, Astro, SvelteKit and CRA deliver
|
|
186
|
+
// the connect in the JS BUNDLE, so their HTML never carries it. Gating on presence failed five
|
|
187
|
+
// of ten scaffolds in the install gate: no window, so no bundle, so no session, so exit 1 on a
|
|
188
|
+
// correct install. page-probe.ts says it is a diagnostic for a connect that already failed; the
|
|
189
|
+
// same signal as a precondition deadlocks every case it is wrong about.
|
|
190
|
+
//
|
|
191
|
+
// So presence decides only WHEN: open the moment it appears (the fast path for the frameworks
|
|
192
|
+
// that inline it), otherwise once the short readiness window is out.
|
|
193
|
+
const readyBy = fx.now() + Math.min(SDK_READY_WINDOW_MS, budgetMs);
|
|
194
|
+
let finding = readPage(await fx.probePage(url));
|
|
195
|
+
while (PageFinding.SDK_MISSING === finding && fx.now() < readyBy) {
|
|
196
|
+
await fx.sleep(input.pollMs);
|
|
197
|
+
finding = readPage(await fx.probePage(url));
|
|
198
|
+
}
|
|
199
|
+
if (PageFinding.NOT_SERVED === finding || PageFinding.TLS_REFUSED === finding) {
|
|
200
|
+
note(describePage(finding, url));
|
|
201
|
+
note('Not opening a browser: nothing answered that url, so the window could only show an error ' +
|
|
202
|
+
'page. Fix the line above and re-run — `init` is idempotent.');
|
|
203
|
+
}
|
|
204
|
+
else {
|
|
205
|
+
// Said BEFORE the window appears, so somebody watching a page that stays inert has already
|
|
206
|
+
// been told which of the two it is.
|
|
207
|
+
if (PageFinding.SDK_MISSING === finding)
|
|
208
|
+
note(describePage(finding, url));
|
|
209
|
+
await fx.openBrowser(url);
|
|
210
|
+
openedBrowser = true;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
// Waiting the full budget for a session when nothing was opened to create one is dead time, and
|
|
214
|
+
// it used to be over two minutes of it: the browser is the session source on web, so declining to
|
|
215
|
+
// open it and then waiting as if we had is a promise to the reader that cannot be kept. Something
|
|
216
|
+
// else may still dial in — a tab the user already has open, a desktop window — and the existing
|
|
217
|
+
// diagnosis says such a session "will appear within a second of the page loading", so a short
|
|
218
|
+
// grace is the honest wait. A run that DID open a browser keeps the whole budget.
|
|
219
|
+
const deadline = fx.now() +
|
|
220
|
+
(openedBrowser || !(input.openBrowser && policy.openBrowser)
|
|
221
|
+
? budgetMs
|
|
222
|
+
: Math.min(NO_BROWSER_GRACE_MS, budgetMs));
|
|
223
|
+
let session = alreadyConnected;
|
|
224
|
+
while (null === session) {
|
|
134
225
|
// On a desktop app, only the desktop window counts. AppShape and the runtime a page reports use
|
|
135
226
|
// the same three names, so the shape IS the requirement — see session-pick.
|
|
136
|
-
session = pickSession(await fx.listSessions(), url, before,
|
|
227
|
+
session = pickSession(await fx.listSessions(), url, before, requiredRuntime);
|
|
137
228
|
if (null !== session)
|
|
138
229
|
break;
|
|
139
230
|
if (deadline <= fx.now())
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* run-setup.ts and the pieces it calls.
|
|
7
7
|
*/
|
|
8
8
|
import { type SetupInput, type SetupOutcome } from './run-setup.js';
|
|
9
|
-
|
|
9
|
+
interface SetupCommandInput extends Omit<SetupInput, 'shape'> {
|
|
10
10
|
/** Where setup was invoked, which is not the app directory in a monorepo. */
|
|
11
11
|
readonly invokedAt: string;
|
|
12
12
|
readonly bridgePort: number;
|
|
@@ -26,7 +26,7 @@ export interface SetupCommandInput extends Omit<SetupInput, 'shape'> {
|
|
|
26
26
|
* so a VS Code user has no tools outside the directory they ran init in.
|
|
27
27
|
*/
|
|
28
28
|
export declare function registerOtherAgents(print: (line: string) => void): void;
|
|
29
|
-
|
|
29
|
+
interface SetupCommandResult extends SetupOutcome {
|
|
30
30
|
/** Set when a weak flow was re-recorded with the stronger model. */
|
|
31
31
|
readonly escalated?: {
|
|
32
32
|
readonly from: string;
|
|
@@ -43,3 +43,4 @@ export interface SetupCommandResult extends SetupOutcome {
|
|
|
43
43
|
* files and a dead tab.
|
|
44
44
|
*/
|
|
45
45
|
export declare function runSetupCommand(input: SetupCommandInput, print: (line: string) => void): Promise<SetupCommandResult>;
|
|
46
|
+
export {};
|
|
@@ -16,8 +16,12 @@ import { ApprovalOutcome, grantAutoApproval } from './auto-approve.js';
|
|
|
16
16
|
import { agentIo } from './agent-io.js';
|
|
17
17
|
import { EnsureDaemon, ensureDaemon, nodeEnsureDaemonDeps } from './ensure-daemon.js';
|
|
18
18
|
import { openInBrowser } from '../cli/cli-launch.js';
|
|
19
|
+
import { readProjectId } from '../cli/cli-port.js';
|
|
20
|
+
import { reticleStateHome } from '../daemon/daemon.js';
|
|
21
|
+
import { readDevServers } from '../daemon/dev-servers.js';
|
|
19
22
|
import { chooseDriver, DRIVERS, shouldEscalate } from './drive-plan.js';
|
|
20
23
|
import { driveWith } from './drive-agent.js';
|
|
24
|
+
import { urlOfExistingApp } from './existing-app.js';
|
|
21
25
|
import { binaryExists, flowsSaved, listSessions, OwnedDevServer, probePage, } from './node-effects.js';
|
|
22
26
|
import { runSetupPhases, } from './run-setup.js';
|
|
23
27
|
/** The capabilities file init scaffolds, in the order a project is likely to have it. */
|
|
@@ -105,6 +109,10 @@ export async function runSetupCommand(input, print) {
|
|
|
105
109
|
server.start(command, cwd, input.env);
|
|
106
110
|
return Promise.resolve();
|
|
107
111
|
},
|
|
112
|
+
existingAppUrl: () => Promise.resolve(urlOfExistingApp(readDevServers(reticleStateHome()), {
|
|
113
|
+
projectId: readProjectId(input.appDir),
|
|
114
|
+
root: input.appDir,
|
|
115
|
+
})),
|
|
108
116
|
devServerOutput: () => server.output(),
|
|
109
117
|
devServerExited: () => server.exited(),
|
|
110
118
|
devServerQuietForMs: () => server.quietForMs(),
|
|
@@ -18,8 +18,9 @@
|
|
|
18
18
|
* backend named in the README, the variable that skips an auth wall: all readable by
|
|
19
19
|
* an agent, none inferable by a script. Without this a real app sits on a login
|
|
20
20
|
* screen and there is no flow to drive at all.
|
|
21
|
-
* --
|
|
22
|
-
*
|
|
21
|
+
* --url the app is already running here, so do not start anything. This is also the answer
|
|
22
|
+
* when the project's own scripts do not name a dev command: start it yourself and say
|
|
23
|
+
* where. There is no flag that overrides the dev command; --url replaces the need.
|
|
23
24
|
*
|
|
24
25
|
* Everything else on this type is an operator's dial, not an agent's judgement.
|
|
25
26
|
*/
|
|
@@ -29,7 +30,7 @@ export declare const DEFAULT_BRIDGE_PORT = 4400;
|
|
|
29
30
|
export declare const DEFAULT_PHASE_TIMEOUT_MS = 120000;
|
|
30
31
|
/** What the drive may spend before it is stopped. */
|
|
31
32
|
export declare const DEFAULT_DRIVE_BUDGET_USD = 3;
|
|
32
|
-
|
|
33
|
+
interface SetupOptions {
|
|
33
34
|
/** The journey to drive, in the caller's own words. */
|
|
34
35
|
readonly flow?: string | undefined;
|
|
35
36
|
/** Which app in a monorepo. */
|
|
@@ -72,3 +73,4 @@ export declare function parseEnvAssignment(pair: string): {
|
|
|
72
73
|
* something else should see its variable missing, not see setup invent one.
|
|
73
74
|
*/
|
|
74
75
|
export declare function collectEnv(pairs: readonly string[]): Record<string, string>;
|
|
76
|
+
export {};
|
|
@@ -18,8 +18,9 @@
|
|
|
18
18
|
* backend named in the README, the variable that skips an auth wall: all readable by
|
|
19
19
|
* an agent, none inferable by a script. Without this a real app sits on a login
|
|
20
20
|
* screen and there is no flow to drive at all.
|
|
21
|
-
* --
|
|
22
|
-
*
|
|
21
|
+
* --url the app is already running here, so do not start anything. This is also the answer
|
|
22
|
+
* when the project's own scripts do not name a dev command: start it yourself and say
|
|
23
|
+
* where. There is no flag that overrides the dev command; --url replaces the need.
|
|
23
24
|
*
|
|
24
25
|
* Everything else on this type is an operator's dial, not an agent's judgement.
|
|
25
26
|
*/
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Say what the dev-server wait is waiting FOR, while it waits.
|
|
3
|
+
*
|
|
4
|
+
* `init`'s wait loop polled in complete silence. Reported as thirty minutes of nothing, ending in a
|
|
5
|
+
* SIGKILL: no output, no exit, no verdict. The cause of that particular wait is still unexplained,
|
|
6
|
+
* but the silence is a failure on its own terms — a user cannot tell "still starting" from "wedged",
|
|
7
|
+
* and cannot see the thing most likely to be wrong, which is the URL being watched rather than the
|
|
8
|
+
* server itself.
|
|
9
|
+
*
|
|
10
|
+
* That distinction is not hypothetical: `dev-server-wait.ts` already reasons about a server that
|
|
11
|
+
* serves happily on a port we never found (the CRA case, where no url is printed outside a tty), and
|
|
12
|
+
* has never said so out loud while it happens.
|
|
13
|
+
*
|
|
14
|
+
* Pure, and the clock is the caller's. `elapsedMs` and `lastSpokeAtMs` come in; nothing here reads a
|
|
15
|
+
* real clock, so the decision is testable without one and cannot assert a duration.
|
|
16
|
+
*/
|
|
17
|
+
/**
|
|
18
|
+
* How often to speak. Long enough that a normal start — under a second — says nothing at all, since
|
|
19
|
+
* announcing a wait that is not happening is noise in the first command a user ever runs.
|
|
20
|
+
*/
|
|
21
|
+
export declare const WAIT_PROGRESS_EVERY_MS = 15000;
|
|
22
|
+
/**
|
|
23
|
+
* The line to print now, or undefined to stay quiet.
|
|
24
|
+
*
|
|
25
|
+
* `lastSpokeAtMs` is when this last returned a line, so the caller can poll as fast as it likes
|
|
26
|
+
* without a line per poll burying the output it exists to explain.
|
|
27
|
+
*/
|
|
28
|
+
export declare function waitProgressLine(elapsedMs: number, watching: string | undefined, lastSpokeAtMs: number | undefined): string | undefined;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Say what the dev-server wait is waiting FOR, while it waits.
|
|
3
|
+
*
|
|
4
|
+
* `init`'s wait loop polled in complete silence. Reported as thirty minutes of nothing, ending in a
|
|
5
|
+
* SIGKILL: no output, no exit, no verdict. The cause of that particular wait is still unexplained,
|
|
6
|
+
* but the silence is a failure on its own terms — a user cannot tell "still starting" from "wedged",
|
|
7
|
+
* and cannot see the thing most likely to be wrong, which is the URL being watched rather than the
|
|
8
|
+
* server itself.
|
|
9
|
+
*
|
|
10
|
+
* That distinction is not hypothetical: `dev-server-wait.ts` already reasons about a server that
|
|
11
|
+
* serves happily on a port we never found (the CRA case, where no url is printed outside a tty), and
|
|
12
|
+
* has never said so out loud while it happens.
|
|
13
|
+
*
|
|
14
|
+
* Pure, and the clock is the caller's. `elapsedMs` and `lastSpokeAtMs` come in; nothing here reads a
|
|
15
|
+
* real clock, so the decision is testable without one and cannot assert a duration.
|
|
16
|
+
*/
|
|
17
|
+
/**
|
|
18
|
+
* How often to speak. Long enough that a normal start — under a second — says nothing at all, since
|
|
19
|
+
* announcing a wait that is not happening is noise in the first command a user ever runs.
|
|
20
|
+
*/
|
|
21
|
+
export const WAIT_PROGRESS_EVERY_MS = 15_000;
|
|
22
|
+
/**
|
|
23
|
+
* The line to print now, or undefined to stay quiet.
|
|
24
|
+
*
|
|
25
|
+
* `lastSpokeAtMs` is when this last returned a line, so the caller can poll as fast as it likes
|
|
26
|
+
* without a line per poll burying the output it exists to explain.
|
|
27
|
+
*/
|
|
28
|
+
export function waitProgressLine(elapsedMs, watching, lastSpokeAtMs) {
|
|
29
|
+
if (elapsedMs < WAIT_PROGRESS_EVERY_MS)
|
|
30
|
+
return undefined;
|
|
31
|
+
const since = elapsedMs - (lastSpokeAtMs ?? 0);
|
|
32
|
+
if (lastSpokeAtMs !== undefined && since < WAIT_PROGRESS_EVERY_MS)
|
|
33
|
+
return undefined;
|
|
34
|
+
const seconds = `${String(Math.floor(elapsedMs / 1000))}s`;
|
|
35
|
+
if (watching === undefined) {
|
|
36
|
+
// A different problem, and one the reader can act on: we do not know where to look. The CRA
|
|
37
|
+
// case reaches here, and so does any launcher whose url never appears in its output.
|
|
38
|
+
return (`Waiting ${seconds} for the dev server. It has not announced a url yet and no port was ` +
|
|
39
|
+
`observed, so there is nothing to watch — if it IS up, stop this and pass --url <its url>.`);
|
|
40
|
+
}
|
|
41
|
+
return (`Waiting ${seconds} for the dev server — watching ${watching}. If the app is already up ` +
|
|
42
|
+
`somewhere else, that url is the thing to check first.`);
|
|
43
|
+
}
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
* `project_profiled` already carries it on the same daemon run, so the two join on sessionId.
|
|
17
17
|
*/
|
|
18
18
|
export declare function markInstrumentationClock(now: number): void;
|
|
19
|
-
|
|
19
|
+
interface InstrumentationFacts {
|
|
20
20
|
/** Whether this project has a projectId stamped — i.e. `init` has run here. */
|
|
21
21
|
initialized: boolean;
|
|
22
22
|
/**
|
|
@@ -43,3 +43,4 @@ export declare function reportAppInstrumented(facts: InstrumentationFacts, now?:
|
|
|
43
43
|
export declare function appEverConnected(): boolean;
|
|
44
44
|
/** Tests only. */
|
|
45
45
|
export declare function resetAppInstrumented(): void;
|
|
46
|
+
export {};
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
* project path, the URL, or anything from the page. The stack is deliberately NOT repeated here;
|
|
16
16
|
* `project_profiled` already carries it on the same daemon run, so the two join on sessionId.
|
|
17
17
|
*/
|
|
18
|
-
import { TelemetryEventKind } from '@reticlehq/core';
|
|
18
|
+
import { TelemetryEventKind } from '@reticlehq/core/telemetry';
|
|
19
19
|
import { getTelemetry } from './telemetry.js';
|
|
20
20
|
let reported = false;
|
|
21
21
|
/** Set at daemon start so the first connect can report how long the install sat un-instrumented. */
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
* developer machines trip it; it separates nothing.
|
|
26
26
|
*/
|
|
27
27
|
import { existsSync } from 'node:fs';
|
|
28
|
-
import { AutomationHint } from '@reticlehq/core';
|
|
28
|
+
import { AutomationHint } from '@reticlehq/core/telemetry';
|
|
29
29
|
/** Container runtimes drop one of these at the filesystem root. */
|
|
30
30
|
const CONTAINER_MARKERS = ['/.dockerenv', '/run/.containerenv'];
|
|
31
31
|
/** Hosted dev environments that declare themselves. Self-declared, never inferred. */
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Lives in its own module so `cli.ts` stays a dispatcher, and so the `_daemon` exclusion below sits
|
|
5
5
|
* next to the explanation of why it exists rather than buried in a startup function.
|
|
6
6
|
*/
|
|
7
|
-
import { TelemetryEventKind } from '@reticlehq/core';
|
|
7
|
+
import { TelemetryEventKind } from '@reticlehq/core/telemetry';
|
|
8
8
|
import { DAEMON_INNER_COMMAND, knownCommand } from '../cli/cli-parse.js';
|
|
9
9
|
import { getTelemetry } from './telemetry.js';
|
|
10
10
|
import { describeCliFlags } from './argument-shape.js';
|
|
@@ -11,6 +11,6 @@
|
|
|
11
11
|
* this list needs another entry — which is a signal in itself, and the reason it is never merged
|
|
12
12
|
* into one of the known causes.
|
|
13
13
|
*/
|
|
14
|
-
import { ConnectFailure } from '@reticlehq/core';
|
|
14
|
+
import { ConnectFailure } from '@reticlehq/core/telemetry';
|
|
15
15
|
/** The cause behind a connection error, or `OTHER` when we do not recognize it. */
|
|
16
16
|
export declare function classifyConnectFailure(error: unknown): ConnectFailure;
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
* this list needs another entry — which is a signal in itself, and the reason it is never merged
|
|
12
12
|
* into one of the known causes.
|
|
13
13
|
*/
|
|
14
|
-
import { ConnectFailure } from '@reticlehq/core';
|
|
14
|
+
import { ConnectFailure } from '@reticlehq/core/telemetry';
|
|
15
15
|
/** Ordered most-specific first; the first match wins. Patterns track messages we have actually seen. */
|
|
16
16
|
const RULES = [
|
|
17
17
|
// Playwright's own wording when the browser was never downloaded.
|
|
@@ -20,14 +20,14 @@
|
|
|
20
20
|
* are read and deliberately thrown away.
|
|
21
21
|
*/
|
|
22
22
|
/** The structured cause of a crash, when the error carries one. Every field is optional. */
|
|
23
|
-
|
|
23
|
+
interface CrashCause {
|
|
24
24
|
syscall?: string;
|
|
25
25
|
errno?: string;
|
|
26
26
|
loopback?: boolean;
|
|
27
27
|
port?: CrashPort;
|
|
28
28
|
internalFrame?: string;
|
|
29
29
|
}
|
|
30
|
-
import { CrashPort } from '@reticlehq/core';
|
|
30
|
+
import { CrashPort } from '@reticlehq/core/telemetry';
|
|
31
31
|
/**
|
|
32
32
|
* The innermost frame that names NODE's own source.
|
|
33
33
|
*
|
|
@@ -45,3 +45,4 @@ export declare function innermostInternalFrame(stack: string): string | undefine
|
|
|
45
45
|
* comparison is testable — the port itself is used to answer one enum and is then discarded.
|
|
46
46
|
*/
|
|
47
47
|
export declare function crashCause(value: unknown, knownPorts: readonly number[]): CrashCause;
|
|
48
|
+
export {};
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
* reported as an enum, and the frame names a line in NODE's source. The address and the port number
|
|
20
20
|
* are read and deliberately thrown away.
|
|
21
21
|
*/
|
|
22
|
-
import { CrashPort } from '@reticlehq/core';
|
|
22
|
+
import { CrashPort } from '@reticlehq/core/telemetry';
|
|
23
23
|
import { reticleFrames } from './error-fingerprint.js';
|
|
24
24
|
/** IPv4 loopback is the whole 127/8 block, not just 127.0.0.1. */
|
|
25
25
|
const IPV4_LOOPBACK = /^127\./;
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* (nothing here may ever be able to fail a daemon start), and because `cli.ts` is a dispatcher — the
|
|
7
7
|
* more of this that lives there, the harder it is to see what a command actually does.
|
|
8
8
|
*/
|
|
9
|
-
import { type SessionSummary } from '@reticlehq/core';
|
|
9
|
+
import { type SessionSummary } from '@reticlehq/core/telemetry';
|
|
10
10
|
/**
|
|
11
11
|
* How often a running daemon rolls up its window.
|
|
12
12
|
*
|
|
@@ -36,7 +36,7 @@ export declare const SESSION_FLUSH_MS: number;
|
|
|
36
36
|
*/
|
|
37
37
|
export declare const FIRST_FLUSH_MS: number;
|
|
38
38
|
/** Stops the timers this installed. Called from the daemon's shutdown path. */
|
|
39
|
-
|
|
39
|
+
interface DaemonTelemetry {
|
|
40
40
|
/**
|
|
41
41
|
* Emit the final, rich session summary and stop flushing. Safe to call more than once.
|
|
42
42
|
*
|
|
@@ -61,3 +61,4 @@ export declare function installDaemonTelemetry(cwd: string, now?: () => number,
|
|
|
61
61
|
* trustworthy.
|
|
62
62
|
*/
|
|
63
63
|
port?: number): DaemonTelemetry;
|
|
64
|
+
export {};
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* (nothing here may ever be able to fail a daemon start), and because `cli.ts` is a dispatcher — the
|
|
7
7
|
* more of this that lives there, the harder it is to see what a command actually does.
|
|
8
8
|
*/
|
|
9
|
-
import { TelemetryEventKind } from '@reticlehq/core';
|
|
9
|
+
import { TelemetryEventKind } from '@reticlehq/core/telemetry';
|
|
10
10
|
import { getTelemetry } from './telemetry.js';
|
|
11
11
|
import { getSessionMetrics } from './session-metrics.js';
|
|
12
12
|
import { profileProject } from './project-profile.js';
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
* counts. The full message is already fingerprinted and skeletonised elsewhere.
|
|
12
12
|
*/
|
|
13
13
|
/** Whose defect. Ordered by which fix it implies. */
|
|
14
|
-
|
|
14
|
+
declare const ErrorClass: {
|
|
15
15
|
/** Missing/unknown parameter, wrong type, unparseable predicate. **Our schema is unclear.** */
|
|
16
16
|
readonly SCHEMA: "schema";
|
|
17
17
|
/** No session, stale ref, disconnected. The world moved under the agent; not a schema problem. */
|
|
@@ -21,6 +21,7 @@ export declare const ErrorClass: {
|
|
|
21
21
|
/** Unrecognised. The bucket to watch: a large one is a blind spot, not a long tail. */
|
|
22
22
|
readonly OTHER: "other";
|
|
23
23
|
};
|
|
24
|
-
|
|
24
|
+
type ErrorClass = (typeof ErrorClass)[keyof typeof ErrorClass];
|
|
25
25
|
/** Which bucket this message belongs to. Never throws — a classifier must not break a tool path. */
|
|
26
26
|
export declare function classifyError(message: string): ErrorClass;
|
|
27
|
+
export {};
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
* counts. The full message is already fingerprinted and skeletonised elsewhere.
|
|
12
12
|
*/
|
|
13
13
|
/** Whose defect. Ordered by which fix it implies. */
|
|
14
|
-
|
|
14
|
+
const ErrorClass = {
|
|
15
15
|
/** Missing/unknown parameter, wrong type, unparseable predicate. **Our schema is unclear.** */
|
|
16
16
|
SCHEMA: 'schema',
|
|
17
17
|
/** No session, stale ref, disconnected. The world moved under the agent; not a schema problem. */
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { FeedbackKind, FeedbackSource } from '@reticlehq/core';
|
|
1
|
+
import { FeedbackKind, FeedbackSource } from '@reticlehq/core/telemetry';
|
|
2
2
|
import { AGENT_FLAG, BUG_FLAG, FEEDBACK_KINDS, KIND_FLAG, RATING_FLAG } from '../cli/cli-parse.js';
|
|
3
3
|
import { describeFeedbackPayload, submitFeedback } from './feedback.js';
|
|
4
4
|
import { describeTelemetry, setTelemetryEnabled } from './telemetry.js';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { McpScope, StackUnknownReason, type Feedback } from '@reticlehq/core';
|
|
1
|
+
import { McpScope, StackUnknownReason, type Feedback } from '@reticlehq/core/telemetry';
|
|
2
2
|
/** The context fields — the whole `Feedback` shape minus what the author supplies. */
|
|
3
|
-
|
|
3
|
+
type FeedbackContext = Pick<Feedback, 'stack' | 'stackMajor' | 'runtime' | 'engine' | 'driver' | 'client' | 'clientVersion' | 'mcpScope'>;
|
|
4
4
|
export declare function detectStack(cwd: string, read?: (path: string) => string): {
|
|
5
5
|
stack?: string;
|
|
6
6
|
stackMajor?: number;
|
|
@@ -55,3 +55,4 @@ export declare function reconcileStack(fromCwd: {
|
|
|
55
55
|
};
|
|
56
56
|
/** Assemble the full context. Every field independently optional — a partial context still ships. */
|
|
57
57
|
export declare function feedbackContext(cwd: string, session?: SessionFacts): FeedbackContext;
|
|
58
|
+
export {};
|
|
@@ -12,9 +12,8 @@
|
|
|
12
12
|
import { mcpClientIdentity, setMcpClientIdentityHook } from '../mcp/client-identity.js';
|
|
13
13
|
import { existsSync, readFileSync, readdirSync } from 'node:fs';
|
|
14
14
|
import { isAbsolute, join } from 'node:path';
|
|
15
|
-
import { AppRuntime, McpScope, PageDriver, StackUnknownReason, } from '@reticlehq/core';
|
|
16
|
-
import { parseMajor } from '
|
|
17
|
-
import { findWorkspaceApps } from '../init/workspace-apps.js';
|
|
15
|
+
import { AppRuntime, McpScope, PageDriver, StackUnknownReason, } from '@reticlehq/core/telemetry';
|
|
16
|
+
import { parseMajor, findWorkspaceApps } from '@reticlehq/init';
|
|
18
17
|
/**
|
|
19
18
|
* Dependency → reported stack, in resolution order. Meta-frameworks come FIRST: a Next app also
|
|
20
19
|
* depends on react, and reporting `react` for it would collapse the single most important segment
|
|
@@ -30,6 +29,8 @@ const STACK_BY_DEP = [
|
|
|
30
29
|
['nuxt', 'nuxt'],
|
|
31
30
|
['astro', 'astro'],
|
|
32
31
|
['@remix-run/react', 'remix'],
|
|
32
|
+
['@tanstack/react-start', 'tanstack-start'],
|
|
33
|
+
['@tanstack/start', 'tanstack-start'],
|
|
33
34
|
['@angular/core', 'angular'],
|
|
34
35
|
['react', 'react'],
|
|
35
36
|
['vue', 'vue'],
|
|
@@ -215,7 +216,7 @@ function detectClient() {
|
|
|
215
216
|
* `sveltekit` are not — that pairing means the daemon's directory is not this session's project.
|
|
216
217
|
*/
|
|
217
218
|
const ADAPTER_IMPLIES = {
|
|
218
|
-
react: ['react', 'next', 'remix'],
|
|
219
|
+
react: ['react', 'next', 'remix', 'tanstack-start'],
|
|
219
220
|
svelte: ['svelte', 'sveltekit'],
|
|
220
221
|
vue: ['vue', 'nuxt'],
|
|
221
222
|
solid: ['solid'],
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { Feedback } from '@reticlehq/core';
|
|
2
|
-
|
|
1
|
+
import type { Feedback } from '@reticlehq/core/telemetry';
|
|
2
|
+
interface SavedFeedback {
|
|
3
3
|
path: string;
|
|
4
4
|
/** A ready-to-run command that turns the file into an issue. */
|
|
5
5
|
command: string;
|
|
@@ -13,3 +13,4 @@ export declare function saveFeedbackLocally(cwd: string, input: {
|
|
|
13
13
|
kind?: string;
|
|
14
14
|
source?: string;
|
|
15
15
|
}, text: string, context: Partial<Feedback>, now?: number): SavedFeedback | undefined;
|
|
16
|
+
export {};
|