@reticlehq/server 3.7.0 → 3.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/SKILL.md +59 -68
- package/bin/reticle.js +9 -2
- package/dist/command/cli/adhoc-suite.js +1 -1
- package/dist/command/cli/adhoc-verdict.d.ts +12 -0
- package/dist/command/cli/adhoc-verdict.js +62 -4
- package/dist/command/cli/answers/gate-hook-message.d.ts +2 -0
- package/dist/command/cli/answers/gate-hook-message.js +5 -1
- package/dist/command/cli/auth/cloud-session.d.ts +11 -19
- package/dist/command/cli/auth/cloud-session.js +23 -0
- package/dist/command/cli/auth/device-flow.d.ts +3 -37
- package/dist/command/cli/cli-doctor.js +66 -21
- package/dist/command/cli/cli-flow-commands.js +53 -11
- package/dist/command/cli/cli-kill.d.ts +8 -0
- package/dist/command/cli/cli-kill.js +43 -3
- package/dist/command/cli/cli-parse-feedback.d.ts +4 -0
- package/dist/command/cli/cli-parse-feedback.js +13 -1
- package/dist/command/cli/cli-parse-grammar.d.ts +1 -2
- package/dist/command/cli/cli-parse-grammar.js +1 -6
- package/dist/command/cli/cli-parse-serve.d.ts +24 -0
- package/dist/command/cli/cli-parse-serve.js +124 -0
- package/dist/command/cli/cli-parse.d.ts +12 -11
- package/dist/command/cli/cli-parse.js +100 -123
- package/dist/command/cli/cli-usage.d.ts +0 -11
- package/dist/command/cli/cli-usage.js +43 -16
- package/dist/command/cli/cli-verify.d.ts +1 -1
- package/dist/command/cli/cli-verify.js +29 -14
- package/dist/command/cli/cloud-cli.js +27 -9
- package/dist/command/cli/cloud-kit.js +3 -3
- package/dist/command/cli/cloud-link.d.ts +1 -20
- package/dist/command/cli/cloud-link.js +2 -0
- package/dist/command/cli/cloud-login.d.ts +6 -2
- package/dist/command/cli/cloud-login.js +13 -41
- package/dist/command/cli/config/checkout.d.ts +10 -0
- package/dist/command/cli/config/checkout.js +78 -0
- package/dist/command/cli/doctor/doctor-agent-link.d.ts +23 -0
- package/dist/command/cli/doctor/doctor-agent-link.js +28 -0
- package/dist/command/cli/doctor/doctor-coverage-line.js +1 -7
- package/dist/command/cli/doctor/doctor-rows.d.ts +4 -0
- package/dist/command/cli/doctor/doctor-rows.js +4 -0
- package/dist/command/cli/drive/drive-attach.d.ts +5 -0
- package/dist/command/cli/drive/drive-attach.js +21 -1
- package/dist/command/cli/hook/codex-transcript.d.ts +20 -0
- package/dist/command/cli/hook/codex-transcript.js +224 -0
- package/dist/command/cli/hook/episode-structure.d.ts +24 -0
- package/dist/command/cli/hook/episode-structure.js +138 -0
- package/dist/command/cli/hook/hook-command.d.ts +9 -0
- package/dist/command/cli/hook/hook-command.js +211 -0
- package/dist/command/cli/hook/hook-fast.d.ts +31 -0
- package/dist/command/cli/hook/hook-fast.js +136 -0
- package/dist/command/cli/hook/prompt-hook.d.ts +30 -0
- package/dist/command/cli/hook/prompt-hook.js +199 -0
- package/dist/command/cli/hook/tool-hook.d.ts +21 -0
- package/dist/command/cli/hook/tool-hook.js +259 -0
- package/dist/command/cli/launch/cli-launch.d.ts +2 -0
- package/dist/command/cli/launch/cli-launch.js +22 -2
- package/dist/command/cli/lifecycle/daemon-lifecycle.js +28 -2
- package/dist/command/cli/mcp-command.d.ts +9 -0
- package/dist/command/cli/mcp-command.js +127 -41
- package/dist/command/cli/open-navigate.d.ts +43 -0
- package/dist/command/cli/open-navigate.js +85 -0
- package/dist/command/cli/ports/port-holder.d.ts +16 -4
- package/dist/command/cli/ports/port-holder.js +58 -12
- package/dist/command/cli/ports/resolve/cli-port.js +18 -2
- package/dist/command/cli/project-name.d.ts +1 -7
- package/dist/command/cli/project-name.js +1 -0
- package/dist/command/cli/report-command.d.ts +8 -2
- package/dist/command/cli/report-command.js +95 -18
- package/dist/command/cli/status-fields.d.ts +9 -2
- package/dist/command/cli/status-fields.js +148 -4
- package/dist/command/cli/try-command.d.ts +3 -4
- package/dist/command/cli/try-command.js +6 -11
- package/dist/command/cli/verify-results.d.ts +4 -1
- package/dist/command/cli/verify-results.js +3 -1
- package/dist/command/cli.d.ts +1 -7
- package/dist/command/cli.js +79 -160
- package/dist/command/daemon/daemon-resilience.d.ts +6 -1
- package/dist/command/daemon/daemon-resilience.js +31 -18
- package/dist/command/daemon/daemon.d.ts +11 -0
- package/dist/command/daemon/daemon.js +70 -2
- package/dist/command/daemon/lifetime/daemon-usefulness.d.ts +2 -0
- package/dist/command/daemon/lifetime/daemon-usefulness.js +13 -2
- package/dist/command/daemon/wake-decision.js +4 -2
- package/dist/command/daemon/win32-escape.d.ts +32 -0
- package/dist/command/daemon/win32-escape.js +119 -0
- package/dist/command/setup/agent-configs.d.ts +9 -0
- package/dist/command/setup/agent-configs.js +9 -0
- package/dist/command/setup/auto-approve.d.ts +10 -3
- package/dist/command/setup/auto-approve.js +51 -3
- package/dist/command/setup/bringup/dev-server-files.d.ts +1 -9
- package/dist/command/setup/bringup/dev-server-wait.js +5 -1
- package/dist/command/setup/bringup/ensure-daemon.js +4 -7
- package/dist/command/setup/init/init-host.js +6 -0
- package/dist/command/setup/init/init-port.js +5 -4
- package/dist/command/setup/init/init-runtime.js +7 -1
- package/dist/command/setup/node-effects.d.ts +8 -0
- package/dist/command/setup/node-effects.js +36 -4
- package/dist/command/setup/probe/dev-port.d.ts +26 -0
- package/dist/command/setup/probe/dev-port.js +117 -0
- package/dist/command/setup/probe/page-probe.d.ts +1 -1
- package/dist/command/setup/probe/page-probe.js +11 -3
- package/dist/command/setup/remaining-steps.d.ts +0 -7
- package/dist/command/setup/remaining-steps.js +3 -2
- package/dist/command/setup/run-setup.d.ts +11 -0
- package/dist/command/setup/run-setup.js +33 -5
- package/dist/command/setup/setup-command.d.ts +2 -0
- package/dist/command/setup/setup-command.js +22 -4
- package/dist/command/update/updater.d.ts +1 -6
- package/dist/command/update/updater.js +4 -5
- package/dist/command/update/version-seen.d.ts +24 -0
- package/dist/command/update/version-seen.js +65 -0
- package/dist/command/version/peer-announce.d.ts +9 -1
- package/dist/command/version/peer-announce.js +25 -2
- package/dist/command/version/sdk-fix.d.ts +5 -6
- package/dist/command/version/sdk-fix.js +17 -32
- package/dist/command/version/version-skew.d.ts +16 -1
- package/dist/command/version/version-skew.js +84 -10
- package/dist/features/crawl/crawl-tools.js +2 -2
- package/dist/features/crawl/crawl.js +2 -0
- package/dist/features/exhaust/ledger.d.ts +15 -96
- package/dist/features/exhaust/ledger.js +3 -3
- package/dist/features/harness/drive-runs.d.ts +28 -4
- package/dist/features/harness/drive-runs.js +99 -7
- package/dist/features/harness/drivers.d.ts +1 -1
- package/dist/features/harness/drivers.js +1 -1
- package/dist/features/harness/harness.d.ts +5 -0
- package/dist/features/harness/harness.js +24 -12
- package/dist/features/harness/platform/platform-drives.d.ts +7 -1
- package/dist/features/harness/platform/platform-drives.js +12 -7
- package/dist/features/harness/platform/refusal.d.ts +1 -1
- package/dist/features/harness/platform/refusal.js +4 -4
- package/dist/features/harness/platform/remote-drive.js +70 -28
- package/dist/features/harness/platform/server-driver.js +22 -1
- package/dist/features/harness/platform-config.d.ts +1 -10
- package/dist/features/harness/platform-config.js +0 -20
- package/dist/features/license/license.d.ts +2 -14
- package/dist/features/visual/step-shots.d.ts +33 -1
- package/dist/features/visual/step-shots.js +155 -1
- package/dist/features/visual/visual-tools.js +12 -4
- package/dist/hooks/coding-agents.d.ts +6 -0
- package/dist/hooks/coding-agents.js +24 -3
- package/dist/hooks/episode-stamp.d.ts +32 -0
- package/dist/hooks/episode-stamp.js +61 -0
- package/dist/hooks/hook-commands.js +19 -9
- package/dist/index.d.ts +5 -1
- package/dist/index.js +66 -24
- package/dist/judgement/app-graph/journal-steps.d.ts +8 -0
- package/dist/judgement/app-graph/journal-steps.js +92 -0
- package/dist/judgement/capsule/capsule-store.d.ts +2 -39
- package/dist/judgement/domain/domain-model.js +1 -10
- package/dist/judgement/domain/domain-tools.js +4 -2
- package/dist/judgement/runs/artifact/run-store.d.ts +28 -8
- package/dist/judgement/runs/artifact/run-store.js +153 -28
- package/dist/judgement/runs/default-run-id.d.ts +3 -1
- package/dist/judgement/runs/default-run-id.js +15 -3
- package/dist/judgement/runs/drive-run.d.ts +3 -3
- package/dist/judgement/runs/drive-run.js +11 -7
- package/dist/judgement/runs/run-ledger.d.ts +21 -0
- package/dist/judgement/runs/run-ledger.js +143 -0
- package/dist/judgement/runs/runner-port.d.ts +1 -1
- package/dist/judgement/runs/runner-port.js +8 -2
- package/dist/judgement/runs/verification-sync.d.ts +4 -3
- package/dist/judgement/runs/verification-sync.js +27 -5
- package/dist/language/flows/affected-tools.js +2 -1
- package/dist/language/flows/annotate-notes/annotate.js +8 -3
- package/dist/language/flows/annotate-tools.js +1 -1
- package/dist/language/flows/change/affected.d.ts +8 -0
- package/dist/language/flows/change/affected.js +20 -7
- package/dist/language/flows/decision.js +19 -4
- package/dist/language/flows/fields/flow-secret-field.d.ts +9 -0
- package/dist/language/flows/fields/flow-secret-field.js +67 -5
- package/dist/language/flows/flow-anchor.d.ts +5 -0
- package/dist/language/flows/flow-anchor.js +4 -0
- package/dist/language/flows/flow-cross-step.d.ts +7 -1
- package/dist/language/flows/flow-cross-step.js +9 -0
- package/dist/language/flows/flow-expect-grammar.js +15 -10
- package/dist/language/flows/flow-intent.js +6 -1
- package/dist/language/flows/flow-journey.d.ts +8 -0
- package/dist/language/flows/flow-journey.js +13 -0
- package/dist/language/flows/flow-lease.d.ts +27 -0
- package/dist/language/flows/flow-lease.js +59 -0
- package/dist/language/flows/flow-replay-run.d.ts +1 -87
- package/dist/language/flows/flow-replay-run.js +111 -310
- package/dist/language/flows/flow-replay.js +21 -19
- package/dist/language/flows/flow-replayable.d.ts +38 -0
- package/dist/language/flows/flow-replayable.js +179 -0
- package/dist/language/flows/flow-start-path.d.ts +108 -0
- package/dist/language/flows/flow-start-path.js +313 -0
- package/dist/language/flows/flow-step-runners.d.ts +23 -2
- package/dist/language/flows/flow-step-runners.js +191 -32
- package/dist/language/flows/flow-store-for-session.d.ts +8 -1
- package/dist/language/flows/flow-store-for-session.js +6 -0
- package/dist/language/flows/flow-tools.d.ts +2 -23
- package/dist/language/flows/flow-tools.js +63 -113
- package/dist/language/flows/flows.d.ts +4 -6
- package/dist/language/flows/flows.js +90 -15
- package/dist/language/flows/heal-run.d.ts +10 -4
- package/dist/language/flows/heal-run.js +26 -9
- package/dist/language/flows/recording/flake.d.ts +3 -27
- package/dist/language/flows/recording/flake.js +1 -1
- package/dist/language/flows/recording/recording-backtrack.js +1 -4
- package/dist/language/flows/recording/tape/recordings.d.ts +11 -1
- package/dist/language/flows/recording/tape/recordings.js +9 -3
- package/dist/language/flows/replay.d.ts +25 -5
- package/dist/language/flows/replay.js +83 -16
- package/dist/language/flows/stores/assertion-tiers-store.js +1 -1
- package/dist/language/flows/suite/coverage.d.ts +9 -0
- package/dist/language/flows/suite/coverage.js +12 -1
- package/dist/language/flows/suite-selection.d.ts +25 -0
- package/dist/language/flows/suite-selection.js +41 -9
- package/dist/machine/git-tracks.d.ts +6 -0
- package/dist/machine/git-tracks.js +36 -0
- package/dist/memory/cloud/background-sync.d.ts +25 -0
- package/dist/memory/cloud/background-sync.js +79 -0
- package/dist/memory/cloud/cloud-config.d.ts +12 -1
- package/dist/memory/cloud/cloud-config.js +39 -13
- package/dist/memory/cloud/cloud-sync.d.ts +3 -24
- package/dist/memory/cloud/cloud-sync.js +5 -2
- package/dist/memory/cloud/harness-config.d.ts +0 -7
- package/dist/memory/cloud/memory-scope.d.ts +19 -0
- package/dist/memory/cloud/memory-scope.js +48 -0
- package/dist/memory/cloud/sync-answer.d.ts +43 -0
- package/dist/memory/cloud/sync-answer.js +42 -0
- package/dist/memory/cloud/sync-cycle.d.ts +40 -10
- package/dist/memory/cloud/sync-cycle.js +97 -144
- package/dist/memory/cloud/sync-daemon.d.ts +50 -3
- package/dist/memory/cloud/sync-daemon.js +473 -83
- package/dist/memory/cloud/sync-describe.d.ts +28 -0
- package/dist/memory/cloud/sync-describe.js +92 -0
- package/dist/memory/cloud/sync-disk.d.ts +9 -1
- package/dist/memory/cloud/sync-disk.js +137 -33
- package/dist/memory/cloud/sync-flow-versions.d.ts +26 -0
- package/dist/memory/cloud/sync-flow-versions.js +42 -0
- package/dist/memory/impact/impact-store.js +32 -15
- package/dist/memory/intent/intent-shard.d.ts +41 -266
- package/dist/memory/intent/intent-tools.js +20 -61
- package/dist/memory/intent/record-request.d.ts +27 -0
- package/dist/memory/intent/record-request.js +88 -0
- package/dist/memory/intent/settled-words.js +9 -1
- package/dist/memory/journal/drive-flow.d.ts +3 -0
- package/dist/memory/journal/drive-flow.js +11 -41
- package/dist/memory/journal/envelope-store.js +1 -1
- package/dist/memory/journal/envelope.d.ts +6 -154
- package/dist/memory/journal/episode-log.d.ts +107 -0
- package/dist/memory/journal/episode-log.js +302 -0
- package/dist/memory/journal/journal-recorder.d.ts +7 -0
- package/dist/memory/journal/journal-recorder.js +22 -9
- package/dist/memory/journal/on-disk/ambient-file.d.ts +1 -7
- package/dist/memory/journal/on-disk/ambient-file.js +1 -1
- package/dist/memory/journal/on-disk/workspace-gitignore.d.ts +24 -3
- package/dist/memory/journal/on-disk/workspace-gitignore.js +38 -7
- package/dist/memory/journal/on-disk/workspace-tiers.js +7 -0
- package/dist/memory/journal/self-observation.js +3 -1
- package/dist/memory/journal/session-end.js +23 -9
- package/dist/memory/journal/session-journal.js +39 -20
- package/dist/memory/project/artifact-root-resolver.d.ts +14 -1
- package/dist/memory/project/artifact-root-resolver.js +68 -23
- package/dist/memory/project/artifact-root.d.ts +17 -3
- package/dist/memory/project/artifact-root.js +47 -9
- package/dist/memory/project/fs/fs-port.d.ts +5 -0
- package/dist/memory/project/fs/fs-port.js +13 -0
- package/dist/memory/project/learned-routes.d.ts +3 -4
- package/dist/memory/project/learned-routes.js +3 -11
- package/dist/memory/project/link-directory.js +5 -2
- package/dist/memory/project/root-claims.d.ts +3 -1
- package/dist/memory/project/root-claims.js +41 -7
- package/dist/memory/project/session-root.d.ts +1 -1
- package/dist/memory/project/session-root.js +1 -15
- package/dist/memory/project/sync-status.js +5 -6
- package/dist/memory/recall/memory-tools.js +2 -2
- package/dist/memory/recall/platform-memory.d.ts +3 -1
- package/dist/memory/recall/platform-memory.js +9 -1
- package/dist/memory/recall/project-memory.js +15 -19
- package/dist/portal/bridge/auth-failure-reason.d.ts +13 -0
- package/dist/portal/bridge/auth-failure-reason.js +19 -0
- package/dist/portal/bridge/bridge.d.ts +19 -4
- package/dist/portal/bridge/bridge.js +150 -177
- package/dist/portal/bridge/harness-request.d.ts +15 -0
- package/dist/portal/bridge/harness-request.js +19 -0
- package/dist/portal/bridge/origin/origin-follow.d.ts +46 -0
- package/dist/portal/bridge/origin/origin-follow.js +110 -0
- package/dist/portal/bridge/pairing-token.d.ts +6 -0
- package/dist/portal/bridge/pairing-token.js +47 -16
- package/dist/portal/bridge/protocol-skew.d.ts +27 -2
- package/dist/portal/bridge/protocol-skew.js +66 -2
- package/dist/portal/bridge/session-nonces.d.ts +46 -0
- package/dist/portal/bridge/session-nonces.js +72 -0
- package/dist/portal/input/viewport-tools.d.ts +31 -0
- package/dist/portal/input/viewport-tools.js +106 -15
- package/dist/portal/pool/bounded-close.d.ts +23 -0
- package/dist/portal/pool/bounded-close.js +38 -0
- package/dist/portal/pool/browser-pool.d.ts +44 -39
- package/dist/portal/pool/browser-pool.js +247 -95
- package/dist/portal/pool/context-permissions.d.ts +9 -1
- package/dist/portal/pool/context-permissions.js +26 -0
- package/dist/portal/pool/lease-emulation.d.ts +37 -0
- package/dist/portal/pool/lease-emulation.js +29 -0
- package/dist/portal/pool/playwright-launcher.d.ts +6 -0
- package/dist/portal/pool/playwright-launcher.js +74 -7
- package/dist/portal/pool/pool-contract.d.ts +23 -1
- package/dist/portal/pool/pool-lease.d.ts +128 -0
- package/dist/portal/pool/pool-lease.js +49 -0
- package/dist/portal/pool/zero-install.d.ts +8 -1
- package/dist/portal/pool/zero-install.js +24 -2
- package/dist/portal/production/production-activation.d.ts +136 -0
- package/dist/portal/production/production-activation.js +173 -0
- package/dist/portal/production/production-drive.d.ts +52 -0
- package/dist/portal/production/production-drive.js +301 -0
- package/dist/portal/production/production-hello.d.ts +23 -0
- package/dist/portal/production/production-hello.js +23 -0
- package/dist/portal/realm/web-realm.js +42 -15
- package/dist/portal/session/control-envelope.d.ts +1 -1
- package/dist/portal/session/dev-server/served-document.d.ts +0 -5
- package/dist/portal/session/dev-server/served-document.js +6 -8
- package/dist/portal/session/facts/handshake-facts.d.ts +8 -1
- package/dist/portal/session/first-run-wiring.d.ts +3 -36
- package/dist/portal/session/first-run-wiring.js +10 -103
- package/dist/portal/session/live-control-tools.js +61 -19
- package/dist/portal/session/no-session-next-action.d.ts +11 -0
- package/dist/portal/session/no-session-next-action.js +40 -15
- package/dist/portal/session/no-session-watch.d.ts +7 -0
- package/dist/portal/session/no-session-watch.js +67 -23
- package/dist/portal/session/output-budget.d.ts +10 -0
- package/dist/portal/session/output-budget.js +16 -0
- package/dist/portal/session/presence/session-lease.d.ts +2 -0
- package/dist/portal/session/presence/session-lease.js +8 -0
- package/dist/portal/session/recorded-gaps.d.ts +15 -11
- package/dist/portal/session/recorded-gaps.js +39 -18
- package/dist/portal/session/serving-directory.d.ts +24 -2
- package/dist/portal/session/serving-directory.js +93 -5
- package/dist/portal/session/session-info.d.ts +26 -0
- package/dist/portal/session/session-info.js +20 -0
- package/dist/portal/session/session-manager.d.ts +35 -3
- package/dist/portal/session/session-manager.js +69 -14
- package/dist/portal/session/session-successor.js +1 -9
- package/dist/portal/session/session-tools.js +22 -4
- package/dist/portal/session/session.d.ts +10 -10
- package/dist/portal/session/session.js +37 -29
- package/dist/portal/session/zero-install-first-call.d.ts +7 -2
- package/dist/portal/session/zero-install-first-call.js +43 -20
- package/dist/start-wiring.d.ts +2 -2
- package/dist/start-wiring.js +17 -3
- package/dist/status-payload.d.ts +11 -1
- package/dist/status-payload.js +7 -1
- package/dist/surface/agent-presence-grace.d.ts +11 -0
- package/dist/surface/agent-presence-grace.js +34 -0
- package/dist/surface/http-server.d.ts +12 -1
- package/dist/surface/http-server.js +64 -15
- package/dist/surface/mcp/faults/mcp-outage.d.ts +12 -2
- package/dist/surface/mcp/faults/mcp-outage.js +19 -1
- package/dist/surface/mcp/mcp-proxy.d.ts +17 -74
- package/dist/surface/mcp/mcp-proxy.js +194 -267
- package/dist/surface/mcp/mcp.d.ts +20 -3
- package/dist/surface/mcp/mcp.js +88 -25
- package/dist/surface/mcp/proxy/drive-calls.d.ts +44 -0
- package/dist/surface/mcp/proxy/drive-calls.js +114 -5
- package/dist/surface/mcp/proxy/proxy-boot.d.ts +11 -0
- package/dist/surface/mcp/proxy/proxy-boot.js +1 -0
- package/dist/surface/mcp/proxy/proxy-daemon-probe.d.ts +6 -0
- package/dist/surface/mcp/proxy/proxy-daemon-probe.js +14 -1
- package/dist/surface/mcp/proxy/proxy-handshake.d.ts +34 -2
- package/dist/surface/mcp/proxy/proxy-handshake.js +76 -8
- package/dist/surface/mcp/server-instructions.js +35 -16
- package/dist/surface/mcp/shared-params.d.ts +8 -0
- package/dist/surface/mcp/shared-params.js +15 -1
- package/dist/surface/mcp/sse-frame-parser.d.ts +11 -0
- package/dist/surface/mcp/sse-frame-parser.js +18 -0
- package/dist/surface/mcp/surface-vocabulary.d.ts +2 -0
- package/dist/surface/mcp/surface-vocabulary.js +13 -0
- package/dist/surface/mcp/tool-catalog-cache.d.ts +2 -0
- package/dist/surface/mcp/tool-catalog-cache.js +14 -4
- package/dist/surface/tools/account-tool.d.ts +4 -3
- package/dist/surface/tools/account-tool.js +20 -31
- package/dist/surface/tools/act/act-danger.d.ts +2 -0
- package/dist/surface/tools/act/act-danger.js +41 -14
- package/dist/surface/tools/act/act-observation.d.ts +11 -0
- package/dist/surface/tools/act/act-observation.js +33 -0
- package/dist/surface/tools/act/act-preflight.js +10 -3
- package/dist/surface/tools/act/act-sequence-retry.js +2 -1
- package/dist/surface/tools/act/act-target.js +19 -5
- package/dist/surface/tools/act/durable.js +1 -1
- package/dist/surface/tools/act/navigation/navigate-arrival.d.ts +9 -7
- package/dist/surface/tools/act/navigation/navigate-arrival.js +11 -14
- package/dist/surface/tools/act/unsettled-find.d.ts +36 -0
- package/dist/surface/tools/act/unsettled-find.js +71 -0
- package/dist/surface/tools/act-sequence-tool.js +53 -24
- package/dist/surface/tools/act-tools.d.ts +2 -3
- package/dist/surface/tools/act-tools.js +49 -47
- package/dist/surface/tools/agent/compact-envelope.d.ts +2 -2
- package/dist/surface/tools/agent/for-the-agent.js +41 -3
- package/dist/surface/tools/assert/assert-grade.js +8 -3
- package/dist/surface/tools/assert/assert-verdict.js +4 -2
- package/dist/surface/tools/browser-tools.js +7 -4
- package/dist/surface/tools/chat-drives.js +50 -25
- package/dist/surface/tools/coverage-tools.js +1 -1
- package/dist/surface/tools/dynamic-tools.d.ts +8 -0
- package/dist/surface/tools/dynamic-tools.js +89 -34
- package/dist/surface/tools/empty-session-list.d.ts +18 -25
- package/dist/surface/tools/empty-session-list.js +67 -38
- package/dist/surface/tools/error-recovery.d.ts +17 -7
- package/dist/surface/tools/error-recovery.js +53 -20
- package/dist/surface/tools/explore-tools.d.ts +10 -0
- package/dist/surface/tools/explore-tools.js +72 -19
- package/dist/surface/tools/feedback-tools.js +23 -2
- package/dist/surface/tools/gap-novelty.d.ts +6 -0
- package/dist/surface/tools/gap-novelty.js +9 -0
- package/dist/surface/tools/gaps/capability-absences.js +4 -3
- package/dist/surface/tools/harness-explore.d.ts +1 -1
- package/dist/surface/tools/harness-explore.js +6 -4
- package/dist/surface/tools/harness-gate.d.ts +43 -21
- package/dist/surface/tools/harness-gate.js +55 -81
- package/dist/surface/tools/harness-script.d.ts +2 -0
- package/dist/surface/tools/harness-script.js +11 -6
- package/dist/surface/tools/harness-toolset.js +3 -4
- package/dist/surface/tools/invoke-tool.d.ts +0 -8
- package/dist/surface/tools/invoke-tool.js +164 -178
- package/dist/surface/tools/lease-hint.d.ts +9 -0
- package/dist/surface/tools/lease-hint.js +22 -3
- package/dist/surface/tools/lease-permissions.d.ts +1 -1
- package/dist/surface/tools/lease-readiness.d.ts +55 -0
- package/dist/surface/tools/lease-readiness.js +150 -2
- package/dist/surface/tools/lease-tools.d.ts +3 -75
- package/dist/surface/tools/lease-tools.js +124 -188
- package/dist/surface/tools/map-tools.d.ts +20 -0
- package/dist/surface/tools/map-tools.js +145 -0
- package/dist/surface/tools/merge-tools.js +11 -7
- package/dist/surface/tools/next-step.js +6 -3
- package/dist/surface/tools/observe-tools.js +46 -35
- package/dist/surface/tools/platform-moment.d.ts +3 -12
- package/dist/surface/tools/platform-moment.js +12 -24
- package/dist/surface/tools/read/complete-snapshot.d.ts +7 -1
- package/dist/surface/tools/read/complete-snapshot.js +13 -2
- package/dist/surface/tools/read/query-paginate.js +6 -0
- package/dist/surface/tools/read/query-shape.d.ts +9 -0
- package/dist/surface/tools/read/query-shape.js +15 -0
- package/dist/surface/tools/read/snapshot-unmounted-note.d.ts +1 -0
- package/dist/surface/tools/read/snapshot-unmounted-note.js +73 -0
- package/dist/surface/tools/read-tools.js +5 -5
- package/dist/surface/tools/real-input-attempt.d.ts +11 -0
- package/dist/surface/tools/real-input-attempt.js +206 -38
- package/dist/surface/tools/reconcile-tools.js +21 -8
- package/dist/surface/tools/reticle-result.d.ts +3 -0
- package/dist/surface/tools/reticle-result.js +8 -1
- package/dist/surface/tools/run-report.d.ts +22 -0
- package/dist/surface/tools/run-report.js +141 -0
- package/dist/surface/tools/session-ports.d.ts +57 -0
- package/dist/surface/tools/session-ports.js +102 -0
- package/dist/surface/tools/tool-kit.d.ts +58 -4
- package/dist/surface/tools/tool-kit.js +140 -6
- package/dist/surface/tools/tool-surface.d.ts +2 -0
- package/dist/surface/tools/tool-surface.js +45 -0
- package/dist/surface/tools/tools.js +49 -87
- package/dist/telemetry/automation-hint.d.ts +5 -0
- package/dist/telemetry/automation-hint.js +7 -0
- package/dist/telemetry/cli-telemetry.d.ts +22 -0
- package/dist/telemetry/cli-telemetry.js +80 -11
- package/dist/telemetry/daemon-telemetry.d.ts +3 -1
- package/dist/telemetry/daemon-telemetry.js +9 -2
- package/dist/telemetry/feedback-cli.d.ts +1 -1
- package/dist/telemetry/feedback-cli.js +8 -3
- package/dist/telemetry/feedback.d.ts +1 -1
- package/dist/telemetry/feedback.js +51 -4
- package/dist/telemetry/harness-run.d.ts +3 -3
- package/dist/telemetry/harness-run.js +18 -7
- package/dist/telemetry/hud-events.d.ts +1 -1
- package/dist/telemetry/hud-metrics.d.ts +6 -3
- package/dist/telemetry/hud-metrics.js +20 -8
- package/dist/telemetry/install-source.js +1 -1
- package/dist/telemetry/mcp-connection.d.ts +1 -1
- package/dist/telemetry/mcp-connection.js +21 -2
- package/dist/telemetry/onboarding-firsts.d.ts +6 -1
- package/dist/telemetry/onboarding-firsts.js +41 -1
- package/dist/telemetry/proxy-telemetry.d.ts +42 -0
- package/dist/telemetry/proxy-telemetry.js +70 -1
- package/dist/telemetry/session-metrics.d.ts +1 -3
- package/dist/telemetry/session-metrics.js +16 -12
- package/dist/telemetry/telemetry.d.ts +9 -1
- package/dist/telemetry/telemetry.js +16 -1
- package/dist/telemetry/verification-of.d.ts +3 -1
- package/dist/telemetry/verification-of.js +7 -1
- package/dist/wire-journal.js +12 -2
- package/docs/README.md +4 -2
- package/docs/actions.mdx +7 -6
- package/docs/adapters.md +2 -1
- package/docs/agent-cheatsheet.md +19 -5
- package/docs/architecture.md +13 -10
- package/docs/autodrive.md +6 -5
- package/docs/benchmarks.md +2 -2
- package/docs/capabilities.mdx +1 -1
- package/docs/cli/affected.mdx +1 -1
- package/docs/cli/cloud.mdx +6 -6
- package/docs/cli/doctor.mdx +3 -1
- package/docs/cli/feedback.mdx +11 -7
- package/docs/cli/gate.mdx +1 -1
- package/docs/cli/help.mdx +1 -1
- package/docs/cli/init.mdx +20 -16
- package/docs/cli/mcp.mdx +5 -2
- package/docs/cli/open.mdx +5 -2
- package/docs/cli/report.mdx +1 -1
- package/docs/cli/restart.mdx +1 -1
- package/docs/cli/rollback.mdx +4 -4
- package/docs/cli/serve.mdx +7 -5
- package/docs/cli/setup.mdx +1 -1
- package/docs/cli/status.mdx +6 -2
- package/docs/cli/stop.mdx +3 -3
- package/docs/cli/telemetry.mdx +5 -1
- package/docs/cli/try.mdx +8 -8
- package/docs/cli/update.mdx +8 -5
- package/docs/cli/verify.mdx +12 -5
- package/docs/cli/version.mdx +1 -1
- package/docs/cli.mdx +10 -6
- package/docs/debugging.md +1 -1
- package/docs/deploy-checks.md +8 -6
- package/docs/desktop.mdx +14 -18
- package/docs/enterprise.md +6 -6
- package/docs/environment.mdx +5 -3
- package/docs/faq.mdx +9 -6
- package/docs/first-drive.md +19 -9
- package/docs/flows.md +3 -4
- package/docs/for-agents.md +1 -1
- package/docs/frameworks.mdx +34 -11
- package/docs/getting-started.md +46 -29
- package/docs/http-transport.md +2 -2
- package/docs/human-control.md +8 -8
- package/docs/index.mdx +2 -2
- package/docs/install-agentic.mdx +18 -19
- package/docs/install-manual.mdx +8 -4
- package/docs/integration-patterns.md +5 -5
- package/docs/multi-agent-testing.md +7 -5
- package/docs/packages/browser.mdx +34 -2
- package/docs/packages/core.mdx +2 -1
- package/docs/packages/electron.mdx +15 -3
- package/docs/packages/eslint-plugin.mdx +1 -1
- package/docs/packages/next.mdx +17 -5
- package/docs/packages/react.mdx +8 -1
- package/docs/packages/server.mdx +3 -3
- package/docs/packages/tauri.mdx +3 -3
- package/docs/packages/vite-plugin.mdx +1 -1
- package/docs/packages.mdx +19 -6
- package/docs/platform-integration.md +12 -4
- package/docs/predicates.mdx +18 -7
- package/docs/production-mode.md +108 -0
- package/docs/prompt-capture.md +99 -0
- package/docs/quickstart.mdx +14 -12
- package/docs/recipes.mdx +9 -8
- package/docs/required-checks.md +3 -2
- package/docs/skill-file.mdx +4 -3
- package/docs/skill-setup.md +2 -2
- package/docs/skill.md +62 -70
- package/docs/state-files.md +1 -0
- package/docs/state-management.mdx +11 -9
- package/docs/system-map.md +14 -13
- package/docs/telemetry.md +32 -24
- package/docs/testing.md +9 -5
- package/docs/tools/act-and-wait.mdx +17 -13
- package/docs/tools/act-sequence.mdx +40 -66
- package/docs/tools/act.mdx +7 -5
- package/docs/tools/assert.mdx +1 -1
- package/docs/tools/look.mdx +1 -1
- package/docs/tools/navigate.mdx +1 -1
- package/docs/tools/network.mdx +13 -11
- package/docs/tools/overview.mdx +3 -3
- package/docs/tools/query.mdx +3 -3
- package/docs/tools/session-and-feedback.mdx +9 -6
- package/docs/tools/sessions.mdx +7 -0
- package/docs/tools/snapshot.mdx +9 -7
- package/docs/tools/tools-and-run.mdx +11 -10
- package/docs/tools/verify.mdx +1 -1
- package/docs/troubleshooting.mdx +21 -9
- package/docs/usage.md +58 -43
- package/docs/use-cases.mdx +2 -2
- package/docs/vs-chrome-devtools-mcp.mdx +5 -5
- package/docs/vs-playwright-mcp.mdx +5 -4
- package/docs/what-is-recorded.md +12 -7
- package/docs/what-is-reticle.mdx +2 -2
- package/docs/why-reticle.mdx +1 -1
- package/package.json +9 -12
- package/dist/command/dev/stale-issue-guard.d.ts +0 -34
- package/dist/command/dev/stale-issue-guard.js +0 -69
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Something already serving half of the port the dev server is about to take (#1377).
|
|
3
|
+
*
|
|
4
|
+
* With a Docker or nginx stack on 5173, `init` started `pnpm dev`, and on macOS Vite can bind
|
|
5
|
+
* `[::1]` beside a process holding `0.0.0.0:5173` and print no error. `localhost:5173` then served
|
|
6
|
+
* the instrumented dev server and `127.0.0.1:5173` the stale container bundle, which looked like
|
|
7
|
+
* "the SDK sometimes doesn't connect". Busy-port detection read the dev server's own output, and
|
|
8
|
+
* Vite says nothing in that case, so the port is asked before anything is spawned. Only that
|
|
9
|
+
* one-sided case is refused; a port busy on both loopbacks is one the dev server sees and moves off.
|
|
10
|
+
*/
|
|
11
|
+
import { readFileSync } from 'node:fs';
|
|
12
|
+
import { connect } from 'node:net';
|
|
13
|
+
import { join } from 'node:path';
|
|
14
|
+
import { frameworkDevPort } from '@reticlehq/init';
|
|
15
|
+
/** A `port:` in a dev config: it may move the server, so the framework default is not assumed. */
|
|
16
|
+
const CONFIG_SETS_PORT = /\bport\s*:/;
|
|
17
|
+
/**
|
|
18
|
+
* The port the dev server will take, when that is known: the one its script pins, else the
|
|
19
|
+
* framework's default unless the dev config names a port of its own. Undefined otherwise, and
|
|
20
|
+
* nothing is probed: a guessed port refusing a start would be a worse failure than this one.
|
|
21
|
+
*/
|
|
22
|
+
export function expectedDevPort(facts) {
|
|
23
|
+
if (facts.pinned !== undefined)
|
|
24
|
+
return facts.pinned;
|
|
25
|
+
if (facts.framework === undefined)
|
|
26
|
+
return undefined;
|
|
27
|
+
if (facts.devConfig !== undefined && CONFIG_SETS_PORT.test(facts.devConfig))
|
|
28
|
+
return undefined;
|
|
29
|
+
return frameworkDevPort(facts.framework);
|
|
30
|
+
}
|
|
31
|
+
/** How long one loopback address may take to answer. Local, so anything slower is nothing. */
|
|
32
|
+
const PROBE_TIMEOUT_MS = 400;
|
|
33
|
+
/** Both loopbacks: the case this exists for is a server on one and not the other. */
|
|
34
|
+
const LOOPBACKS = ['127.0.0.1', '::1'];
|
|
35
|
+
function answers(port, host) {
|
|
36
|
+
return new Promise((resolve) => {
|
|
37
|
+
const socket = connect({ port, host });
|
|
38
|
+
const done = (open) => {
|
|
39
|
+
socket.destroy();
|
|
40
|
+
resolve(open);
|
|
41
|
+
};
|
|
42
|
+
socket.setTimeout(PROBE_TIMEOUT_MS, () => done(false));
|
|
43
|
+
socket.once('connect', () => done(true));
|
|
44
|
+
socket.once('error', () => done(false));
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* The one loopback something answers on at `port` while the other is free, or undefined.
|
|
49
|
+
*
|
|
50
|
+
* Only that split is refused. A port busy on both loopbacks is one the dev server sees: Vite and
|
|
51
|
+
* Next move to the next port and print it, and setup reads that, as it always has. A second Vite
|
|
52
|
+
* app on 5173 is the common case, and stopping there would break a start that works. The dev server
|
|
53
|
+
* cannot see a listener on only one loopback, because it binds the other with no error, and then
|
|
54
|
+
* `localhost` and `127.0.0.1` serve two different apps.
|
|
55
|
+
*/
|
|
56
|
+
export async function loneLoopbackOnDevPort(port) {
|
|
57
|
+
const open = await Promise.all(LOOPBACKS.map((host) => answers(port, host)));
|
|
58
|
+
const answering = LOOPBACKS.filter((_, i) => true === open[i]);
|
|
59
|
+
return 1 === answering.length ? answering[0] : undefined;
|
|
60
|
+
}
|
|
61
|
+
/** What setup says instead of starting a dev server on the other half of a split port. */
|
|
62
|
+
export function splitDevPortNote(port, host) {
|
|
63
|
+
const shown = (h) => (h.includes(':') ? `[${h}]` : h);
|
|
64
|
+
const other = LOOPBACKS.find((h) => h !== host) ?? host;
|
|
65
|
+
return (`Port ${String(port)} is half taken: something answers on ${shown(host)}:${String(port)} and ` +
|
|
66
|
+
`nothing on ${shown(other)}:${String(port)}. The dev server would bind ${shown(other)} with no ` +
|
|
67
|
+
'error, and then localhost and 127.0.0.1 would serve two different apps, so which one a browser ' +
|
|
68
|
+
'or a lease reaches would be luck. If it is this app already running, re-run with ' +
|
|
69
|
+
`--url http://localhost:${String(port)} to attach to it. Otherwise stop whatever holds the ` +
|
|
70
|
+
'port, or give the dev server another one.');
|
|
71
|
+
}
|
|
72
|
+
/** The dev configs that can move a framework's server off its default port. */
|
|
73
|
+
const DEV_CONFIGS = [
|
|
74
|
+
'vite.config.ts',
|
|
75
|
+
'vite.config.js',
|
|
76
|
+
'vite.config.mts',
|
|
77
|
+
'vite.config.mjs',
|
|
78
|
+
'vite.config.cjs',
|
|
79
|
+
'astro.config.mjs',
|
|
80
|
+
'astro.config.ts',
|
|
81
|
+
'angular.json',
|
|
82
|
+
];
|
|
83
|
+
/** The text of every dev config present in `appDir`, joined, or undefined when there is none. */
|
|
84
|
+
export function devConfigText(appDir) {
|
|
85
|
+
const texts = DEV_CONFIGS.flatMap((name) => {
|
|
86
|
+
try {
|
|
87
|
+
return [readFileSync(join(appDir, name), 'utf8')];
|
|
88
|
+
}
|
|
89
|
+
catch {
|
|
90
|
+
return [];
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
return 0 === texts.length ? undefined : texts.join('\n');
|
|
94
|
+
}
|
|
95
|
+
/** The scripts a project runs itself with, in the order init picks them. */
|
|
96
|
+
const DEV_SCRIPTS = ['dev', 'start', 'serve'];
|
|
97
|
+
const PINNED_PORT = [/--port[= ]\s*(\d+)/, /(?:^|\s)-p\s*(\d+)/, /(?:^|\s)PORT=(\d+)/];
|
|
98
|
+
/** The port the project's dev script pins (`--port`, `-p`, `PORT=`), or undefined. */
|
|
99
|
+
export function pinnedDevPort(appDir) {
|
|
100
|
+
let scripts = {};
|
|
101
|
+
try {
|
|
102
|
+
const manifest = JSON.parse(readFileSync(join(appDir, 'package.json'), 'utf8'));
|
|
103
|
+
scripts = manifest.scripts ?? {};
|
|
104
|
+
}
|
|
105
|
+
catch {
|
|
106
|
+
return undefined;
|
|
107
|
+
}
|
|
108
|
+
const body = DEV_SCRIPTS.map((name) => scripts[name]).find((value) => 'string' === typeof value && 0 < value.trim().length);
|
|
109
|
+
if (body === undefined)
|
|
110
|
+
return undefined;
|
|
111
|
+
for (const pattern of PINNED_PORT) {
|
|
112
|
+
const digits = pattern.exec(body)?.[1];
|
|
113
|
+
if (digits !== undefined)
|
|
114
|
+
return Number.parseInt(digits, 10);
|
|
115
|
+
}
|
|
116
|
+
return undefined;
|
|
117
|
+
}
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
export interface PageProbe {
|
|
15
15
|
/** The server answered at all. */
|
|
16
16
|
readonly served: boolean;
|
|
17
|
-
/** The SDK
|
|
17
|
+
/** The SDK is referenced in what it answered with. A reference, not proof that the SDK loaded. */
|
|
18
18
|
readonly sdkInPage: boolean;
|
|
19
19
|
/**
|
|
20
20
|
* The server ANSWERED and its certificate was refused. A self-signed dev cert is an ordinary
|
|
@@ -16,6 +16,10 @@ export const PageFinding = {
|
|
|
16
16
|
SDK_MISSING: 'sdk-missing',
|
|
17
17
|
SDK_PRESENT: 'sdk-present',
|
|
18
18
|
};
|
|
19
|
+
/** Where a reference that never loaded shows itself. Shared by both SDK_PRESENT sentences. */
|
|
20
|
+
const FAILED_IMPORT = 'open the browser console and look for a failed import of @reticlehq/browser: a CDN 404 (for ' +
|
|
21
|
+
'example a version that is not published yet, or a private registry), a blocked script, or a ' +
|
|
22
|
+
'wrong path.';
|
|
19
23
|
/** Pure, so the mapping is testable without a server or a browser. */
|
|
20
24
|
export function readPage(probe) {
|
|
21
25
|
if (true === probe.tlsRefused)
|
|
@@ -34,8 +38,11 @@ export function readPage(probe) {
|
|
|
34
38
|
* the one piece of positive evidence in the run.
|
|
35
39
|
*/
|
|
36
40
|
export function describePage(finding, url, daemonSpoke = false) {
|
|
41
|
+
// The probe reads the HTML text. It sees a REFERENCE to the SDK, not an SDK that loaded: a
|
|
42
|
+
// pinned CDN version that returns 404 leaves the reference in place and no SDK in the page.
|
|
37
43
|
if (PageFinding.SDK_PRESENT === finding && daemonSpoke) {
|
|
38
|
-
return `The
|
|
44
|
+
return (`The page at ${url} references the SDK. That does not prove the SDK loaded: the daemon's ` +
|
|
45
|
+
`account above says if an SDK session dialled. If none did, ${FAILED_IMPORT}`);
|
|
39
46
|
}
|
|
40
47
|
switch (finding) {
|
|
41
48
|
case PageFinding.NOT_SERVED:
|
|
@@ -56,9 +63,10 @@ export function describePage(finding, url, daemonSpoke = false) {
|
|
|
56
63
|
// gate cell the page console read "could not open a websocket to ws://localhost:<port>, 3
|
|
57
64
|
// attempts, all failed": the SDK dialled three times and the socket failed, having returned
|
|
58
65
|
// early from nothing. What is knowable here is that the SDK is present and no session arrived.
|
|
59
|
-
return (`The
|
|
66
|
+
return (`The page at ${url} references the SDK, and the SDK never dialled the bridge. First, ` +
|
|
67
|
+
`${FAILED_IMPORT} If the import loaded, the cause is a localhost guard, a ` +
|
|
60
68
|
'production-only check, a bridge port that differs on the two sides, or `localhost` ' +
|
|
61
|
-
'resolving to IPv6 where the daemon is only on IPv4
|
|
69
|
+
'resolving to IPv6 where the daemon is only on IPv4. `npx @reticlehq/server doctor` names ' +
|
|
62
70
|
'that last one, and the page console names the first three.');
|
|
63
71
|
}
|
|
64
72
|
}
|
|
@@ -1,10 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* What is left to do by hand, from wherever setup stopped.
|
|
3
|
-
*
|
|
4
|
-
* Naming a cause is not the same as being recoverable. Setup can misbehave, and when it does the
|
|
5
|
-
* caller should not have to re-read the whole procedure and work out for itself which parts already
|
|
6
|
-
* worked — it should pick up at the step that did not. Ordered, and only ever the REMAINING steps.
|
|
7
|
-
*/
|
|
8
1
|
/** How far a run got. Everything here is knowable from the result object setup already builds. */
|
|
9
2
|
export interface Progress {
|
|
10
3
|
readonly initDone: boolean;
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
* caller should not have to re-read the whole procedure and work out for itself which parts already
|
|
6
6
|
* worked — it should pick up at the step that did not. Ordered, and only ever the REMAINING steps.
|
|
7
7
|
*/
|
|
8
|
+
import { FEEDBACK_KIND_CHOICES } from '@reticlehq/core';
|
|
8
9
|
const DOCS_INDEX = 'https://docs.reticle.sh/llms.txt';
|
|
9
10
|
/**
|
|
10
11
|
* The shell form on purpose, not `reticle_session { action: "feedback" }`.
|
|
@@ -14,7 +15,7 @@ const DOCS_INDEX = 'https://docs.reticle.sh/llms.txt';
|
|
|
14
15
|
* the tool surface is unreachable. Naming the tool here would ask the reader to file through the
|
|
15
16
|
* thing that is broken. The shell command needs no daemon and no session.
|
|
16
17
|
*/
|
|
17
|
-
const FEEDBACK_CMD =
|
|
18
|
+
const FEEDBACK_CMD = `npx @reticlehq/server feedback --agent --kind ${FEEDBACK_KIND_CHOICES} "what happened"`;
|
|
18
19
|
export function remainingSteps(p) {
|
|
19
20
|
const steps = [];
|
|
20
21
|
if (!p.initDone) {
|
|
@@ -35,7 +36,7 @@ export function remainingSteps(p) {
|
|
|
35
36
|
'what produce a verdict. Or hand the whole drive to Reticle with `reticle_verify { action: ' +
|
|
36
37
|
'"explore", persona: "<who does what>" }`, which records what it drove so later runs replay ' +
|
|
37
38
|
'with no model in the loop; that route runs on the Reticle platform and needs a linked ' +
|
|
38
|
-
'project (`reticle connect`); a new account gets
|
|
39
|
+
'project (`reticle connect`); a new account gets free credits to try it.');
|
|
39
40
|
}
|
|
40
41
|
// Whether anything is actually outstanding, read BEFORE the docs pointer is added -- that line is
|
|
41
42
|
// an offer, not a task, and a run with nothing left still gets it.
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
import { type CandidateSession } from './session-pick.js';
|
|
13
13
|
import { type PageProbe } from './probe/page-probe.js';
|
|
14
14
|
import { AppShape } from './desktop-shape.js';
|
|
15
|
+
import { InitStop } from '@reticlehq/core/telemetry';
|
|
15
16
|
/**
|
|
16
17
|
* Said before Reticle starts its own static server for a plain page, while it can still be acted
|
|
17
18
|
* on: the page may already be served by something with an API behind it, and only the person
|
|
@@ -36,6 +37,8 @@ export interface SetupOutcome {
|
|
|
36
37
|
/** True when the app is running, instrumented and connected. Writing files alone is not that. */
|
|
37
38
|
readonly ok: boolean;
|
|
38
39
|
readonly reachedPhase: SetupPhase;
|
|
40
|
+
/** On a failure: the step it stopped at, for the `init_completed` event. */
|
|
41
|
+
readonly stop?: InitStop | undefined;
|
|
39
42
|
readonly url?: string | undefined;
|
|
40
43
|
readonly sessionId?: string | undefined;
|
|
41
44
|
/**
|
|
@@ -82,6 +85,12 @@ export interface SetupEffects {
|
|
|
82
85
|
* starting a second one on the next port.
|
|
83
86
|
*/
|
|
84
87
|
readonly existingAppUrl?: () => Promise<string | undefined>;
|
|
88
|
+
/**
|
|
89
|
+
* The one loopback address something answers on at a port, when the other is free. Undefined
|
|
90
|
+
* when both are free or both answer. Asked before the dev server is started, never after: see
|
|
91
|
+
* probe/dev-port.ts.
|
|
92
|
+
*/
|
|
93
|
+
readonly loneLoopbackOnDevPort?: (port: number) => Promise<string | undefined>;
|
|
85
94
|
/** Everything the dev server has printed so far. */
|
|
86
95
|
readonly devServerOutput: () => string;
|
|
87
96
|
readonly devServerExited: () => boolean;
|
|
@@ -147,6 +156,8 @@ export interface SetupInput {
|
|
|
147
156
|
readonly devCommandIsStaticPage?: boolean | undefined;
|
|
148
157
|
/** The app is already served here, so nothing is started. */
|
|
149
158
|
readonly suppliedUrl?: string | undefined;
|
|
159
|
+
/** The port the dev command will take, when it is known. See probe/dev-port.ts. */
|
|
160
|
+
readonly devPort?: number | undefined;
|
|
150
161
|
/**
|
|
151
162
|
* The caller's own budget for the connect wait, when they named one.
|
|
152
163
|
*
|
|
@@ -27,7 +27,9 @@ const WINDOWS_QUIET_MEANS_HUNG_MS_APPLIES = 'win32' === process.platform;
|
|
|
27
27
|
import { liveSessionOfProject, pickSession } from './session-pick.js';
|
|
28
28
|
import { readPage, describePage, findingBeforeOpen, PageFinding, } from './probe/page-probe.js';
|
|
29
29
|
import { remainingSteps } from './remaining-steps.js';
|
|
30
|
+
import { splitDevPortNote } from './probe/dev-port.js';
|
|
30
31
|
import { AppShape, isDesktop, policyFor } from './desktop-shape.js';
|
|
32
|
+
import { InitStop } from '@reticlehq/core/telemetry';
|
|
31
33
|
/** Where a run got to, and why it stopped if it did. */
|
|
32
34
|
/**
|
|
33
35
|
* How long to keep asking whether the SDK has reached the page before giving up on opening a window.
|
|
@@ -81,6 +83,16 @@ const asProgress = (input, o) => ({
|
|
|
81
83
|
...(undefined === o.url ? {} : { url: o.url }),
|
|
82
84
|
...(undefined === input.devCommand ? {} : { devCommand: input.devCommand }),
|
|
83
85
|
});
|
|
86
|
+
/** The connect step a web page stopped at. A bundle-connect page's HTML never shows the SDK. */
|
|
87
|
+
const connectStop = (finding, htmlCarriesSdk) => {
|
|
88
|
+
if (PageFinding.NOT_SERVED === finding)
|
|
89
|
+
return InitStop.PAGE_NOT_SERVED;
|
|
90
|
+
if (PageFinding.TLS_REFUSED === finding)
|
|
91
|
+
return InitStop.PAGE_TLS_REFUSED;
|
|
92
|
+
if (PageFinding.SDK_MISSING === finding && htmlCarriesSdk)
|
|
93
|
+
return InitStop.SDK_MISSING;
|
|
94
|
+
return InitStop.NO_SESSION;
|
|
95
|
+
};
|
|
84
96
|
const stop = (input, phase, partial, notes) => ({
|
|
85
97
|
ok: false,
|
|
86
98
|
reachedPhase: phase,
|
|
@@ -143,9 +155,20 @@ export async function runSetupPhases(input, fx) {
|
|
|
143
155
|
'No dev command: the project names no dev, start or serve script, and no app url was given (`reticle init --url <app>`). ' +
|
|
144
156
|
'Stopping here rather than invent one — start the app yourself and pass --url to say ' +
|
|
145
157
|
'where it is serving, or add a dev/start/serve script to package.json and re-run.');
|
|
146
|
-
return stop(input, SetupPhase.DEV_SERVER, {}, notes);
|
|
158
|
+
return stop(input, SetupPhase.DEV_SERVER, { stop: InitStop.NO_DEV_COMMAND }, notes);
|
|
147
159
|
}
|
|
148
160
|
else {
|
|
161
|
+
// Not this project's announced server (that branch is above). Something answering on one
|
|
162
|
+
// loopback and not the other is the split a new server cannot see: it binds the free one with
|
|
163
|
+
// no error, and the two addresses serve different apps (#1377). Something on both loopbacks
|
|
164
|
+
// is a busy port the dev server sees and moves off, so it starts as before.
|
|
165
|
+
const lone = undefined === input.devPort || undefined === fx.loneLoopbackOnDevPort
|
|
166
|
+
? undefined
|
|
167
|
+
: await fx.loneLoopbackOnDevPort(input.devPort);
|
|
168
|
+
if (undefined !== lone && undefined !== input.devPort) {
|
|
169
|
+
note(splitDevPortNote(input.devPort, lone));
|
|
170
|
+
return stop(input, SetupPhase.DEV_SERVER, { stop: InitStop.SPLIT_LOOPBACK }, notes);
|
|
171
|
+
}
|
|
149
172
|
if (true === input.devCommandIsStaticPage)
|
|
150
173
|
note(STATIC_PAGE_URL_HINT);
|
|
151
174
|
await fx.startDevServer(input.devCommand, input.appDir);
|
|
@@ -190,8 +213,10 @@ export async function runSetupPhases(input, fx) {
|
|
|
190
213
|
break;
|
|
191
214
|
}
|
|
192
215
|
if (WaitVerdict.DEAD === verdict) {
|
|
193
|
-
|
|
194
|
-
|
|
216
|
+
const busy = portBusyMessage(fx.devServerOutput());
|
|
217
|
+
note(busy ?? devServerDiedMessage(fx.devServerOutput()));
|
|
218
|
+
const step = undefined === busy ? InitStop.DEV_SERVER_EXITED : InitStop.PORT_BUSY;
|
|
219
|
+
return stop(input, SetupPhase.DEV_SERVER, { stop: step }, notes);
|
|
195
220
|
}
|
|
196
221
|
if (WaitVerdict.HUNG === verdict) {
|
|
197
222
|
// Says BOTH were checked. A server that prints nothing but IS listening is the CRA case and
|
|
@@ -206,7 +231,8 @@ export async function runSetupPhases(input, fx) {
|
|
|
206
231
|
? `The dev server did not become ready${within}. `
|
|
207
232
|
: `The dev server stopped making progress before ${watching} became ready. `) +
|
|
208
233
|
'Check its log, increase --timeout for a slow build, or pass --url with the address it serves.');
|
|
209
|
-
|
|
234
|
+
const step = undefined === watching ? InitStop.NO_URL : InitStop.NOT_READY;
|
|
235
|
+
return stop(input, SetupPhase.DEV_SERVER, { stop: step }, notes);
|
|
210
236
|
}
|
|
211
237
|
await fx.sleep(input.pollMs);
|
|
212
238
|
}
|
|
@@ -344,6 +370,7 @@ export async function runSetupPhases(input, fx) {
|
|
|
344
370
|
await fx.sleep(input.pollMs);
|
|
345
371
|
}
|
|
346
372
|
if (null === session) {
|
|
373
|
+
let step = InitStop.DESKTOP_NO_SESSION;
|
|
347
374
|
if (isDesktop(input.shape)) {
|
|
348
375
|
// Nothing outside the app can fetch its webview, so there is no page to describe. What is
|
|
349
376
|
// wrong here is desktop-shaped: the preload, the capture helper, or a CSP that blocks the
|
|
@@ -376,9 +403,10 @@ export async function runSetupPhases(input, fx) {
|
|
|
376
403
|
if (PageFinding.SDK_MISSING !== finding || input.htmlCarriesSdk) {
|
|
377
404
|
note(describePage(finding, url, undefined !== why));
|
|
378
405
|
}
|
|
406
|
+
step = connectStop(finding, input.htmlCarriesSdk);
|
|
379
407
|
}
|
|
380
408
|
await releaseLease(lease);
|
|
381
|
-
return stop(input, SetupPhase.CONNECT, { url }, notes);
|
|
409
|
+
return stop(input, SetupPhase.CONNECT, { url, stop: step }, notes);
|
|
382
410
|
}
|
|
383
411
|
// ── connected, which is where ONBOARDING ends ────────────────────────────────────────────────
|
|
384
412
|
//
|
|
@@ -31,6 +31,8 @@ interface SetupCommandInput extends Omit<SetupInput, 'shape'> {
|
|
|
31
31
|
readonly pairingToken?: string | undefined;
|
|
32
32
|
/** False for `--no-first-run`: connect, and say nothing more. */
|
|
33
33
|
readonly firstRun: boolean;
|
|
34
|
+
/** The framework init detected, for the dev server's default port. See probe/dev-port.ts. */
|
|
35
|
+
readonly framework?: string | undefined;
|
|
34
36
|
/** `--json`: an agent is reading, so nothing is driven on its behalf. */
|
|
35
37
|
readonly json: boolean;
|
|
36
38
|
/**
|
|
@@ -8,8 +8,9 @@
|
|
|
8
8
|
import { chmodSync, existsSync, readFileSync, writeFileSync } from 'node:fs';
|
|
9
9
|
import { homedir } from 'node:os';
|
|
10
10
|
import { join } from 'node:path';
|
|
11
|
-
import { planAgentConfigs } from './agent-configs.js';
|
|
11
|
+
import { planAgentConfigs, platformKey } from './agent-configs.js';
|
|
12
12
|
import { AppShape, describeShape, readShape } from './desktop-shape.js';
|
|
13
|
+
import { devConfigText, expectedDevPort, loneLoopbackOnDevPort, pinnedDevPort, } from './probe/dev-port.js';
|
|
13
14
|
import { SigningEnv, tauriSigningEnv } from './tauri-signing.js';
|
|
14
15
|
import { stopOnInterrupt } from './terminal/interrupt.js';
|
|
15
16
|
import { stopOnCrash, crashSentence } from './terminal/crash.js';
|
|
@@ -92,7 +93,7 @@ function hasElectronDependency(dir) {
|
|
|
92
93
|
const agentWord = (n) => (1 === n ? 'agent' : 'agents');
|
|
93
94
|
/** Returns how many agents it wrote a config for, so a caller does not then say "none found". */
|
|
94
95
|
export function registerOtherAgents(print) {
|
|
95
|
-
const platform = process.platform;
|
|
96
|
+
const platform = platformKey(process.platform);
|
|
96
97
|
const home = homedir();
|
|
97
98
|
const results = applyAgentPlan(planAgentConfigs({ home, platform, exists: agentIo.exists, readFile: agentIo.readFile }), agentIo);
|
|
98
99
|
const wrote = results.filter((r) => 'created' === r.action || 'merged' === r.action);
|
|
@@ -219,7 +220,7 @@ export async function runSetupCommand(input, print) {
|
|
|
219
220
|
flowSaved: false,
|
|
220
221
|
notes: undefined === daemon.message ? [] : [daemon.message],
|
|
221
222
|
fallback: [
|
|
222
|
-
`Once those sessions are done, free the port with \`npx @reticlehq/server
|
|
223
|
+
`Once those sessions are done, free the port with \`npx @reticlehq/server stop --force --port ${String(input.bridgePort)}\` and re-run init.`,
|
|
223
224
|
],
|
|
224
225
|
};
|
|
225
226
|
}
|
|
@@ -265,6 +266,9 @@ export async function runSetupCommand(input, print) {
|
|
|
265
266
|
server.start(command, cwd, { ...input.env, ...signing });
|
|
266
267
|
return Promise.resolve();
|
|
267
268
|
},
|
|
269
|
+
// Asked before the dev script is spawned: a listener on one loopback only is not this
|
|
270
|
+
// project's, and the dev server could not see it (#1377).
|
|
271
|
+
loneLoopbackOnDevPort,
|
|
268
272
|
// The server the plugin announced (Vite), or failing that the one a previous init handed over
|
|
269
273
|
// and recorded — the only way to know a Next or Angular server on the port is this project's own.
|
|
270
274
|
existingAppUrl: async () => urlOfExistingApp(readDevServers(reticleStateHome()), {
|
|
@@ -327,7 +331,21 @@ export async function runSetupCommand(input, print) {
|
|
|
327
331
|
// activity, and on a slow desktop build the daemon init had just started idled out mid-wait.
|
|
328
332
|
const releaseDaemon = holdDaemon(input.bridgePort);
|
|
329
333
|
try {
|
|
330
|
-
|
|
334
|
+
// The port the project's own dev script will take, when it can be known (#1377). Not with
|
|
335
|
+
// --url, where nothing is started.
|
|
336
|
+
const devPort = undefined === input.devCommand || undefined !== input.suppliedUrl
|
|
337
|
+
? undefined
|
|
338
|
+
: expectedDevPort({
|
|
339
|
+
pinned: pinnedDevPort(input.appDir),
|
|
340
|
+
framework: input.framework,
|
|
341
|
+
devConfig: devConfigText(input.appDir),
|
|
342
|
+
});
|
|
343
|
+
const outcome = await runSetupPhases({
|
|
344
|
+
...input,
|
|
345
|
+
shape,
|
|
346
|
+
projectId: readProjectId(input.appDir),
|
|
347
|
+
...(undefined === devPort ? {} : { devPort }),
|
|
348
|
+
}, effects);
|
|
331
349
|
// The app stays up only when there is something worth watching.
|
|
332
350
|
if (outcome.ok) {
|
|
333
351
|
server.handOver(outcome.url);
|
|
@@ -1,9 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
declare const VersionChangeDirection: {
|
|
3
|
-
readonly UPDATE: "update";
|
|
4
|
-
readonly ROLLBACK: "rollback";
|
|
5
|
-
};
|
|
6
|
-
type VersionChangeDirection = (typeof VersionChangeDirection)[keyof typeof VersionChangeDirection];
|
|
1
|
+
import { VersionChangeDirection } from './version-seen.js';
|
|
7
2
|
/**
|
|
8
3
|
* Report a completed version move. Never throws — an install that worked must still be reported done.
|
|
9
4
|
*
|
|
@@ -10,11 +10,8 @@ import { windowsShellArg } from '@reticlehq/init';
|
|
|
10
10
|
import { TelemetryEventKind } from '@reticlehq/core/telemetry';
|
|
11
11
|
import { getTelemetry } from '../../telemetry/telemetry.js';
|
|
12
12
|
import { wasNudged } from './nudge-credit.js';
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
UPDATE: 'update',
|
|
16
|
-
ROLLBACK: 'rollback',
|
|
17
|
-
};
|
|
13
|
+
import { VersionChangeDirection, noteRunningVersion } from './version-seen.js';
|
|
14
|
+
import { INSTALL_STATE_DIR } from '../../telemetry/install-source.js';
|
|
18
15
|
/**
|
|
19
16
|
* Report a completed version move. Never throws — an install that worked must still be reported done.
|
|
20
17
|
*
|
|
@@ -30,6 +27,8 @@ export async function reportVersionChange(from, to, direction) {
|
|
|
30
27
|
// updated from a shell script or a package bump with no agent involved at all.
|
|
31
28
|
versionChange: { from, to, direction, ...(nudged ? { nudged } : {}) },
|
|
32
29
|
});
|
|
30
|
+
// Record the new version now, so the next start does not report this move a second time.
|
|
31
|
+
noteRunningVersion(to, INSTALL_STATE_DIR);
|
|
33
32
|
}
|
|
34
33
|
catch {
|
|
35
34
|
/* best-effort, like every other send */
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/** Which way the installed version moved. A rollback means a release hurt someone enough to retreat. */
|
|
2
|
+
export declare const VersionChangeDirection: {
|
|
3
|
+
readonly UPDATE: "update";
|
|
4
|
+
readonly ROLLBACK: "rollback";
|
|
5
|
+
};
|
|
6
|
+
export type VersionChangeDirection = (typeof VersionChangeDirection)[keyof typeof VersionChangeDirection];
|
|
7
|
+
export interface VersionMove {
|
|
8
|
+
readonly from: string;
|
|
9
|
+
readonly to: string;
|
|
10
|
+
readonly direction: VersionChangeDirection;
|
|
11
|
+
}
|
|
12
|
+
/** What a version that is not one of our release numbers reports as. */
|
|
13
|
+
export declare const OTHER_VERSION = "other";
|
|
14
|
+
/**
|
|
15
|
+
* A version string that came from outside this process, made safe to send: one of our release
|
|
16
|
+
* numbers as it is, anything else as `other`, and nothing when there is no value.
|
|
17
|
+
*/
|
|
18
|
+
export declare function releaseVersionOf(raw: string | undefined): string | undefined;
|
|
19
|
+
/**
|
|
20
|
+
* Record `current` as the last version this machine ran, and return the move when the record held
|
|
21
|
+
* a different version. Never throws. A home that cannot be written reports no move, so a read-only
|
|
22
|
+
* home does not send a move on every start.
|
|
23
|
+
*/
|
|
24
|
+
export declare function noteRunningVersion(current: string, stateDir: string): VersionMove | undefined;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `version_changed` for every version move on a machine, not only a move through `reticle update`.
|
|
3
|
+
*
|
|
4
|
+
* Each CLI start compares its version with the last version that this machine ran, kept in
|
|
5
|
+
* `~/.reticle/last-version`. A difference is one move. The file then holds the new version, so the
|
|
6
|
+
* move is reported once. The first start on a machine records the version and reports nothing: an
|
|
7
|
+
* install is not a move.
|
|
8
|
+
*/
|
|
9
|
+
import { mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
10
|
+
import { join } from 'node:path';
|
|
11
|
+
import { isNewerVersion } from './update-nudge.js';
|
|
12
|
+
/** Which way the installed version moved. A rollback means a release hurt someone enough to retreat. */
|
|
13
|
+
export const VersionChangeDirection = {
|
|
14
|
+
UPDATE: 'update',
|
|
15
|
+
ROLLBACK: 'rollback',
|
|
16
|
+
};
|
|
17
|
+
const LAST_VERSION_FILE = 'last-version';
|
|
18
|
+
/** Our own release numbers only. Anything else in the file is not sent. */
|
|
19
|
+
const RELEASE_VERSION = /^\d+\.\d+\.\d+(?:-[a-z]+(?:\.\d+)?)?$/;
|
|
20
|
+
/** What a version that is not one of our release numbers reports as. */
|
|
21
|
+
export const OTHER_VERSION = 'other';
|
|
22
|
+
/**
|
|
23
|
+
* A version string that came from outside this process, made safe to send: one of our release
|
|
24
|
+
* numbers as it is, anything else as `other`, and nothing when there is no value.
|
|
25
|
+
*/
|
|
26
|
+
export function releaseVersionOf(raw) {
|
|
27
|
+
if (raw === undefined) {
|
|
28
|
+
return undefined;
|
|
29
|
+
}
|
|
30
|
+
return RELEASE_VERSION.test(raw) ? raw : OTHER_VERSION;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Record `current` as the last version this machine ran, and return the move when the record held
|
|
34
|
+
* a different version. Never throws. A home that cannot be written reports no move, so a read-only
|
|
35
|
+
* home does not send a move on every start.
|
|
36
|
+
*/
|
|
37
|
+
export function noteRunningVersion(current, stateDir) {
|
|
38
|
+
const file = join(stateDir, LAST_VERSION_FILE);
|
|
39
|
+
let last;
|
|
40
|
+
try {
|
|
41
|
+
last = readFileSync(file, 'utf8').trim();
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
last = undefined;
|
|
45
|
+
}
|
|
46
|
+
if (last === current) {
|
|
47
|
+
return undefined;
|
|
48
|
+
}
|
|
49
|
+
try {
|
|
50
|
+
mkdirSync(stateDir, { recursive: true });
|
|
51
|
+
writeFileSync(file, current, 'utf8');
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
return undefined;
|
|
55
|
+
}
|
|
56
|
+
// ponytail: read-then-write is not atomic. Two first starts of a new version at the same moment
|
|
57
|
+
// can both report the move. Use an exclusive claim file if the duplicates show in the data.
|
|
58
|
+
if (last === undefined || !RELEASE_VERSION.test(last) || !RELEASE_VERSION.test(current)) {
|
|
59
|
+
return undefined;
|
|
60
|
+
}
|
|
61
|
+
const direction = isNewerVersion(current, last)
|
|
62
|
+
? VersionChangeDirection.UPDATE
|
|
63
|
+
: VersionChangeDirection.ROLLBACK;
|
|
64
|
+
return { from: last, to: current, direction };
|
|
65
|
+
}
|
|
@@ -1,8 +1,16 @@
|
|
|
1
1
|
export declare const PEER_VERSION_PARAM = "peerVersion";
|
|
2
2
|
export declare const PEER_CONTRACT_PARAM = "peerContract";
|
|
3
|
+
/** The coding agent's own session id, on the same connect. */
|
|
4
|
+
export declare const AGENT_SESSION_PARAM = "agentSession";
|
|
5
|
+
/** The agent's session id in this process's environment, when it is a plain id. */
|
|
6
|
+
export declare function agentSessionInEnv(env: NodeJS.ProcessEnv): string | undefined;
|
|
7
|
+
/** The query suffix that announces the agent's session, or '' when the agent named none. */
|
|
8
|
+
export declare function agentSessionQuery(env: NodeJS.ProcessEnv): string;
|
|
9
|
+
/** The announced session id, when it is a plain id. */
|
|
10
|
+
export declare function agentSessionOf(value: string | null): string | undefined;
|
|
3
11
|
/**
|
|
4
12
|
* Compare an attaching agent process against this daemon: the skew to tell THAT connection, or
|
|
5
13
|
* undefined when they agree. Returned rather than queued daemon-wide, because it is true only for the
|
|
6
14
|
* agent that announced it (#1136).
|
|
7
15
|
*/
|
|
8
|
-
export declare function agentPeerSkew(version: string | null, contract: string | null): string | undefined;
|
|
16
|
+
export declare function agentPeerSkew(version: string | null, contract: string | null, pageSdkVersions?: readonly (string | undefined)[]): string | undefined;
|
|
@@ -16,19 +16,42 @@ import { SERVER_VERSION } from './identity/server-version.js';
|
|
|
16
16
|
import { daemonFix, describeSkew } from './version-skew.js';
|
|
17
17
|
export const PEER_VERSION_PARAM = 'peerVersion';
|
|
18
18
|
export const PEER_CONTRACT_PARAM = 'peerContract';
|
|
19
|
+
/** The coding agent's own session id, on the same connect. */
|
|
20
|
+
export const AGENT_SESSION_PARAM = 'agentSession';
|
|
21
|
+
/**
|
|
22
|
+
* Where an agent puts its session id in its MCP server's environment. Claude Code sets
|
|
23
|
+
* `CLAUDE_CODE_SESSION_ID`, the same id its hooks receive as `session_id` (checked 2026-10-19).
|
|
24
|
+
* Other agents set none that is documented, so their connections announce nothing.
|
|
25
|
+
*/
|
|
26
|
+
const AGENT_SESSION_ENVS = ['CLAUDE_CODE_SESSION_ID'];
|
|
27
|
+
/** A session id is a plain token: anything else is not used as a file name. */
|
|
28
|
+
const PLAIN_ID = /^[\w-]{1,128}$/;
|
|
29
|
+
/** The agent's session id in this process's environment, when it is a plain id. */
|
|
30
|
+
export function agentSessionInEnv(env) {
|
|
31
|
+
return agentSessionOf(AGENT_SESSION_ENVS.map((name) => env[name]).find((v) => v !== undefined) ?? null);
|
|
32
|
+
}
|
|
33
|
+
/** The query suffix that announces the agent's session, or '' when the agent named none. */
|
|
34
|
+
export function agentSessionQuery(env) {
|
|
35
|
+
const id = agentSessionInEnv(env);
|
|
36
|
+
return id === undefined ? '' : `&${AGENT_SESSION_PARAM}=${encodeURIComponent(id)}`;
|
|
37
|
+
}
|
|
38
|
+
/** The announced session id, when it is a plain id. */
|
|
39
|
+
export function agentSessionOf(value) {
|
|
40
|
+
return null !== value && PLAIN_ID.test(value) ? value : undefined;
|
|
41
|
+
}
|
|
19
42
|
/**
|
|
20
43
|
* Compare an attaching agent process against this daemon: the skew to tell THAT connection, or
|
|
21
44
|
* undefined when they agree. Returned rather than queued daemon-wide, because it is true only for the
|
|
22
45
|
* agent that announced it (#1136).
|
|
23
46
|
*/
|
|
24
|
-
export function agentPeerSkew(version, contract) {
|
|
47
|
+
export function agentPeerSkew(version, contract, pageSdkVersions = []) {
|
|
25
48
|
const skew = describeSkew({
|
|
26
49
|
what: "the agent's MCP server",
|
|
27
50
|
version: version ?? undefined,
|
|
28
51
|
contract: contract ?? undefined,
|
|
29
52
|
// Inverted from cli-launch: here THIS process is the daemon and the peer is the agent's
|
|
30
53
|
// MCP server, so the daemon is the newer half whenever the announcing agent is behind.
|
|
31
|
-
fix: daemonFix(SERVER_VERSION, version ?? undefined),
|
|
54
|
+
fix: daemonFix(SERVER_VERSION, version ?? undefined, pageSdkVersions),
|
|
32
55
|
}, { version: SERVER_VERSION, contract: CONTRACT_FINGERPRINT });
|
|
33
56
|
return skew;
|
|
34
57
|
}
|
|
@@ -5,25 +5,24 @@
|
|
|
5
5
|
* because those answers are never actively wrong. When a project directory IS in hand, name the
|
|
6
6
|
* packages actually in package.json and the manager the lockfile implies.
|
|
7
7
|
*
|
|
8
|
-
*
|
|
9
|
-
* (`library-path-boundary.test.ts`);
|
|
10
|
-
* lockfile → manager map is the same evidence `detectPackageManager` reads, kept here so a HELLO
|
|
11
|
-
* does not load the install plan.
|
|
8
|
+
* The manager is init's own rule, `detectPackageManager` over `resolveLockfiles`, read through a
|
|
9
|
+
* declared crossing (`library-path-boundary.test.ts`); a copy kept here had fallen behind it.
|
|
12
10
|
*/
|
|
11
|
+
import { PackageManager } from '@reticlehq/init';
|
|
13
12
|
/** What a project contributes to the remedy, when we were able to read one. */
|
|
14
13
|
interface SdkFixContext {
|
|
15
14
|
/** `@reticlehq/*` packages declared in package.json. Empty / omitted means none yet. */
|
|
16
15
|
packages?: readonly string[];
|
|
17
16
|
packageManager: PackageManagerName;
|
|
18
17
|
}
|
|
19
|
-
/**
|
|
18
|
+
/** init's manager names, under the name this module exports. */
|
|
20
19
|
export declare const PackageManagerName: {
|
|
21
20
|
readonly PNPM: "pnpm";
|
|
22
21
|
readonly YARN: "yarn";
|
|
23
22
|
readonly BUN: "bun";
|
|
24
23
|
readonly NPM: "npm";
|
|
25
24
|
};
|
|
26
|
-
export type PackageManagerName =
|
|
25
|
+
export type PackageManagerName = PackageManager;
|
|
27
26
|
/**
|
|
28
27
|
* The one sentence telling the human how to bring the page's SDK in line with this daemon.
|
|
29
28
|
*
|