@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
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
* anybody could lose. When it does shut down, the MCP proxy reconnects and `ensureDaemon` spawns a
|
|
20
20
|
* fresh one on the next call, which is a path already exercised hundreds of times a day.
|
|
21
21
|
*/
|
|
22
|
-
import { STATUS_HOLD_MS } from '@reticlehq/core';
|
|
22
|
+
import { SESSION_LIFECYCLE, STATUS_HOLD_MS } from '@reticlehq/core';
|
|
23
23
|
/** Set the first time any tool is dispatched through runTool — the chokepoint every path shares. */
|
|
24
24
|
let servedToolCall = false;
|
|
25
25
|
export function noteToolCall() {
|
|
@@ -48,10 +48,20 @@ export function noteSetupHold(now) {
|
|
|
48
48
|
function setupHolding(now) {
|
|
49
49
|
return undefined !== setupHeldAt && now - setupHeldAt < SETUP_HOLD_MS;
|
|
50
50
|
}
|
|
51
|
+
/** When an agent last attached or detached. Undefined until the first one. */
|
|
52
|
+
let agentSeenAt;
|
|
53
|
+
/** Call on each attach and each detach of an agent. */
|
|
54
|
+
export function noteAgentPresence(now) {
|
|
55
|
+
agentSeenAt = now;
|
|
56
|
+
}
|
|
57
|
+
function agentRecent(now) {
|
|
58
|
+
return undefined !== agentSeenAt && now - agentSeenAt < SESSION_LIFECYCLE.DAEMON_AGENT_RECENT_MS;
|
|
59
|
+
}
|
|
51
60
|
/** Tests only. */
|
|
52
61
|
export function resetDaemonUsefulness() {
|
|
53
62
|
servedToolCall = false;
|
|
54
63
|
setupHeldAt = undefined;
|
|
64
|
+
agentSeenAt = undefined;
|
|
55
65
|
}
|
|
56
66
|
/**
|
|
57
67
|
* True when the daemon has done nothing for anyone and has nothing to lose by exiting.
|
|
@@ -72,8 +82,9 @@ export function isUselessDaemon(facts) {
|
|
|
72
82
|
* no app and sit there for the length of an editor session.
|
|
73
83
|
*/
|
|
74
84
|
export function buildIdlePredicate(agentConnected, sessions, pool, now = () => Date.now()) {
|
|
85
|
+
// An agent that attached recently counts as attached: see DAEMON_AGENT_RECENT_MS.
|
|
75
86
|
return () => !setupHolding(now()) &&
|
|
76
|
-
(!agentConnected() ||
|
|
87
|
+
(!(agentConnected() || agentRecent(now())) ||
|
|
77
88
|
isUselessDaemon({
|
|
78
89
|
servedToolCall: everServedToolCall(),
|
|
79
90
|
everConnected: sessions.everConnected(),
|
|
@@ -30,9 +30,11 @@ export const WakeAction = {
|
|
|
30
30
|
* prevent.
|
|
31
31
|
*/
|
|
32
32
|
export function decideWake(presence, daemonProjectId, callerProjectId) {
|
|
33
|
-
if (PortPresence.FREE === presence)
|
|
33
|
+
if (PortPresence.FREE === presence) {
|
|
34
34
|
return WakeAction.SPAWN;
|
|
35
|
-
|
|
35
|
+
}
|
|
36
|
+
if (PortPresence.DAEMON !== presence) {
|
|
36
37
|
return WakeAction.REFUSE;
|
|
38
|
+
}
|
|
37
39
|
return adoptable(daemonProjectId, callerProjectId) ? WakeAction.USE : WakeAction.REFUSE;
|
|
38
40
|
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/** What the launcher must start. */
|
|
2
|
+
export interface EscapeRequest {
|
|
3
|
+
readonly command: string;
|
|
4
|
+
readonly args: readonly string[];
|
|
5
|
+
readonly cwd: string;
|
|
6
|
+
readonly env: Readonly<Record<string, string | undefined>>;
|
|
7
|
+
readonly logPath: string;
|
|
8
|
+
/** The spec file. The launcher writes the daemon pid to `<specPath>.pid`. */
|
|
9
|
+
readonly specPath: string;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* `launched: false` means nothing started, so the caller can start the daemon another way.
|
|
13
|
+
* `launched: true` with no pid means a daemon may start, but its pid is not known in time.
|
|
14
|
+
*/
|
|
15
|
+
export type EscapeResult = {
|
|
16
|
+
launched: false;
|
|
17
|
+
} | {
|
|
18
|
+
launched: true;
|
|
19
|
+
pid?: number;
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* The launcher, as `node -e` source. It has no double quote and no backslash, so it passes as one
|
|
23
|
+
* Windows argument in double quotes. Its one argument is the spec path.
|
|
24
|
+
*/
|
|
25
|
+
export declare const JOB_ESCAPE_LAUNCHER: string;
|
|
26
|
+
/** The PowerShell script: start the launcher through WMI, then wait for the pid file. */
|
|
27
|
+
export declare function wmiScript(request: EscapeRequest): string;
|
|
28
|
+
/**
|
|
29
|
+
* Start `request` through WMI. Never throws: every failure reads as `launched: false`, unless the
|
|
30
|
+
* launcher already claimed the spec, which means it is starting the daemon.
|
|
31
|
+
*/
|
|
32
|
+
export declare function escapeJobViaWmi(request: EscapeRequest, run?: (script: string) => void): EscapeResult;
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Start the daemon outside the Windows Job Object of the process that starts it.
|
|
3
|
+
*
|
|
4
|
+
* A child of `spawn(..., { detached: true })` stays in the job of its parent. An agent host can run
|
|
5
|
+
* `reticle mcp` in a job with KILL_ON_JOB_CLOSE, and the close of that job then kills the daemon
|
|
6
|
+
* too. A process that WMI `Win32_Process.Create` starts is in no job of ours.
|
|
7
|
+
*
|
|
8
|
+
* WMI cannot give the new process our stdio or our env. So WMI starts a small launcher, and the
|
|
9
|
+
* launcher does the same detached spawn as `spawnDaemon`: stdout and stderr go to the daemon log,
|
|
10
|
+
* opened for append, and the env is ours. The daemon is a child of the launcher, so it is outside
|
|
11
|
+
* the job too. The launcher reads the spawn spec from a file and writes the daemon pid to a file.
|
|
12
|
+
*
|
|
13
|
+
* The spec file is also the lock between the launcher and the fallback. The launcher claims it with
|
|
14
|
+
* a rename before it starts anything. The parent removes it after the WMI call. Only one of the two
|
|
15
|
+
* can win. If the parent wins, nothing started and the detached fallback is safe.
|
|
16
|
+
*/
|
|
17
|
+
import { execFileSync } from 'node:child_process';
|
|
18
|
+
import { readFileSync, unlinkSync, writeFileSync } from 'node:fs';
|
|
19
|
+
/**
|
|
20
|
+
* The launcher, as `node -e` source. It has no double quote and no backslash, so it passes as one
|
|
21
|
+
* Windows argument in double quotes. Its one argument is the spec path.
|
|
22
|
+
*/
|
|
23
|
+
export const JOB_ESCAPE_LAUNCHER = [
|
|
24
|
+
"const fs=require('fs'),cp=require('child_process');",
|
|
25
|
+
"const f=process.argv[1],t=f+'.taken';",
|
|
26
|
+
'fs.renameSync(f,t);',
|
|
27
|
+
"const s=JSON.parse(fs.readFileSync(t,'utf8'));",
|
|
28
|
+
'fs.unlinkSync(t);',
|
|
29
|
+
"const fd=fs.openSync(s.log,'a');",
|
|
30
|
+
"const c=cp.spawn(s.command,s.args,{cwd:s.cwd,env:s.env,detached:true,stdio:['ignore',fd,fd]});",
|
|
31
|
+
"c.on('error',()=>{});",
|
|
32
|
+
'c.unref();',
|
|
33
|
+
"fs.writeFileSync(f+'.tmp',String(c.pid));",
|
|
34
|
+
"fs.renameSync(f+'.tmp',f+'.pid');",
|
|
35
|
+
].join('');
|
|
36
|
+
const PID_SUFFIX = '.pid';
|
|
37
|
+
/** How long the script waits for the launcher to report the daemon pid. */
|
|
38
|
+
const PID_WAIT_MS = 5000;
|
|
39
|
+
/** A hard limit on the whole PowerShell call: its start, the WMI call and the pid wait. */
|
|
40
|
+
const WMI_CALL_TIMEOUT_MS = 8000;
|
|
41
|
+
const POWERSHELL = 'powershell.exe';
|
|
42
|
+
const ENCODING_UTF16LE = 'utf16le';
|
|
43
|
+
/** A PowerShell single-quoted literal. */
|
|
44
|
+
function psLiteral(value) {
|
|
45
|
+
return `'${value.replaceAll("'", "''")}'`;
|
|
46
|
+
}
|
|
47
|
+
/** The PowerShell script: start the launcher through WMI, then wait for the pid file. */
|
|
48
|
+
export function wmiScript(request) {
|
|
49
|
+
const commandLine = `"${request.command}" -e "${JOB_ESCAPE_LAUNCHER}" "${request.specPath}"`;
|
|
50
|
+
const pidPath = `${request.specPath}${PID_SUFFIX}`;
|
|
51
|
+
return [
|
|
52
|
+
"$ErrorActionPreference = 'Stop'",
|
|
53
|
+
// SW_HIDE, so the launcher opens no console window.
|
|
54
|
+
'$startup = New-CimInstance -CimClass (Get-CimClass -ClassName Win32_ProcessStartup) -ClientOnly -Property @{ ShowWindow = [uint16]0 }',
|
|
55
|
+
`$null = Invoke-CimMethod -ClassName Win32_Process -MethodName Create -Arguments @{ CommandLine = ${psLiteral(commandLine)}; CurrentDirectory = ${psLiteral(request.cwd)}; ProcessStartupInformation = $startup }`,
|
|
56
|
+
`$deadline = (Get-Date).AddMilliseconds(${PID_WAIT_MS})`,
|
|
57
|
+
`while (-not (Test-Path -LiteralPath ${psLiteral(pidPath)}) -and (Get-Date) -lt $deadline) { Start-Sleep -Milliseconds 50 }`,
|
|
58
|
+
].join('\n');
|
|
59
|
+
}
|
|
60
|
+
function runPowerShell(script) {
|
|
61
|
+
execFileSync(POWERSHELL, [
|
|
62
|
+
'-NoProfile',
|
|
63
|
+
'-NonInteractive',
|
|
64
|
+
'-EncodedCommand',
|
|
65
|
+
Buffer.from(script, ENCODING_UTF16LE).toString('base64'),
|
|
66
|
+
], { stdio: 'ignore', timeout: WMI_CALL_TIMEOUT_MS, windowsHide: true });
|
|
67
|
+
}
|
|
68
|
+
function removeIfPresent(path) {
|
|
69
|
+
try {
|
|
70
|
+
unlinkSync(path);
|
|
71
|
+
return true;
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
return false;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
function readLauncherPid(pidPath) {
|
|
78
|
+
try {
|
|
79
|
+
const pid = parseInt(readFileSync(pidPath, 'utf8').trim(), 10);
|
|
80
|
+
return Number.isInteger(pid) && pid > 0 ? pid : undefined;
|
|
81
|
+
}
|
|
82
|
+
catch {
|
|
83
|
+
return undefined;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Start `request` through WMI. Never throws: every failure reads as `launched: false`, unless the
|
|
88
|
+
* launcher already claimed the spec, which means it is starting the daemon.
|
|
89
|
+
*/
|
|
90
|
+
export function escapeJobViaWmi(request, run = runPowerShell) {
|
|
91
|
+
const pidPath = `${request.specPath}${PID_SUFFIX}`;
|
|
92
|
+
try {
|
|
93
|
+
removeIfPresent(pidPath);
|
|
94
|
+
writeFileSync(request.specPath, JSON.stringify({
|
|
95
|
+
command: request.command,
|
|
96
|
+
args: request.args,
|
|
97
|
+
cwd: request.cwd,
|
|
98
|
+
env: request.env,
|
|
99
|
+
log: request.logPath,
|
|
100
|
+
}),
|
|
101
|
+
// The spec holds the env. Only the user may read it, and it lives until the launcher reads it.
|
|
102
|
+
{ encoding: 'utf8', mode: 0o600 });
|
|
103
|
+
}
|
|
104
|
+
catch {
|
|
105
|
+
return { launched: false };
|
|
106
|
+
}
|
|
107
|
+
try {
|
|
108
|
+
run(wmiScript(request));
|
|
109
|
+
}
|
|
110
|
+
catch {
|
|
111
|
+
// PowerShell missing, blocked, failed or timed out. The spec says whether the launcher ran.
|
|
112
|
+
}
|
|
113
|
+
if (removeIfPresent(request.specPath)) {
|
|
114
|
+
return { launched: false };
|
|
115
|
+
}
|
|
116
|
+
const pid = readLauncherPid(pidPath);
|
|
117
|
+
removeIfPresent(pidPath);
|
|
118
|
+
return pid === undefined ? { launched: true } : { launched: true, pid };
|
|
119
|
+
}
|
|
@@ -40,6 +40,15 @@ export interface PlatformPaths {
|
|
|
40
40
|
readonly linux: string;
|
|
41
41
|
readonly win32: string;
|
|
42
42
|
}
|
|
43
|
+
/**
|
|
44
|
+
* The `PlatformPaths` row to plan for on a host that reports `platform`.
|
|
45
|
+
*
|
|
46
|
+
* Casting `process.platform` to the three keys broke on every other platform Node reports: on
|
|
47
|
+
* `android` (Termux), `freebsd` or `openbsd` the row lookup returned `undefined`, `join` threw
|
|
48
|
+
* `ERR_INVALID_ARG_TYPE`, and `init` stopped after the wiring and before the dev server. Each of
|
|
49
|
+
* those keeps a Unix home layout, so they plan with the `linux` paths.
|
|
50
|
+
*/
|
|
51
|
+
export declare const platformKey: (platform: NodeJS.Platform) => keyof PlatformPaths;
|
|
43
52
|
interface AgentClient {
|
|
44
53
|
readonly id: string;
|
|
45
54
|
readonly name: string;
|
|
@@ -39,6 +39,15 @@ const MCP_SUBCOMMAND = 'mcp';
|
|
|
39
39
|
const RETICLE_KEY = 'reticle';
|
|
40
40
|
/** The stdio entry, in the shape most clients expect. */
|
|
41
41
|
const STDIO = { command: NPX, args: [SERVER_PACKAGE, MCP_SUBCOMMAND] };
|
|
42
|
+
/**
|
|
43
|
+
* The `PlatformPaths` row to plan for on a host that reports `platform`.
|
|
44
|
+
*
|
|
45
|
+
* Casting `process.platform` to the three keys broke on every other platform Node reports: on
|
|
46
|
+
* `android` (Termux), `freebsd` or `openbsd` the row lookup returned `undefined`, `join` threw
|
|
47
|
+
* `ERR_INVALID_ARG_TYPE`, and `init` stopped after the wiring and before the dev server. Each of
|
|
48
|
+
* those keeps a Unix home layout, so they plan with the `linux` paths.
|
|
49
|
+
*/
|
|
50
|
+
export const platformKey = (platform) => 'darwin' === platform || 'win32' === platform ? platform : 'linux';
|
|
42
51
|
const VSCODE_USER = {
|
|
43
52
|
darwin: 'Library/Application Support/Code/User',
|
|
44
53
|
linux: '.config/Code/User',
|
|
@@ -20,9 +20,10 @@
|
|
|
20
20
|
* the in-app step to take instead. Nothing is written at all for an agent that is not installed:
|
|
21
21
|
* an absent agent has no Accept button to remove.
|
|
22
22
|
*
|
|
23
|
-
* Codex
|
|
24
|
-
*
|
|
25
|
-
*
|
|
23
|
+
* Codex has a per-server rule, `default_tools_approval_mode`, in the `[mcp_servers.reticle]` table
|
|
24
|
+
* that `codex mcp add` writes. Its config is TOML, which this repo does not reformat: the grant adds
|
|
25
|
+
* one line under our own table header and changes no other line. When that header is not there in
|
|
26
|
+
* its plain form, nothing is written and the setting is named instead.
|
|
26
27
|
*/
|
|
27
28
|
import { type PlatformPaths } from './agent-configs.js';
|
|
28
29
|
import type { AgentWriterIo } from './agent-writer.js';
|
|
@@ -43,6 +44,12 @@ export interface ApprovalGrant {
|
|
|
43
44
|
* a grant is only ever merged into a file the user already owns, never created.
|
|
44
45
|
*/
|
|
45
46
|
readonly supersedesInApp?: boolean;
|
|
47
|
+
/**
|
|
48
|
+
* For a config that is not JSON: the new text, or null when the edit is not safe. Then nothing is
|
|
49
|
+
* written and `manual` tells the user what to add.
|
|
50
|
+
*/
|
|
51
|
+
readonly editText?: (current: string) => string | null;
|
|
52
|
+
readonly manual?: (file: string) => string;
|
|
46
53
|
}
|
|
47
54
|
export declare const APPROVAL_GRANTS: readonly ApprovalGrant[];
|
|
48
55
|
export declare const ApprovalOutcome: {
|
|
@@ -20,9 +20,10 @@
|
|
|
20
20
|
* the in-app step to take instead. Nothing is written at all for an agent that is not installed:
|
|
21
21
|
* an absent agent has no Accept button to remove.
|
|
22
22
|
*
|
|
23
|
-
* Codex
|
|
24
|
-
*
|
|
25
|
-
*
|
|
23
|
+
* Codex has a per-server rule, `default_tools_approval_mode`, in the `[mcp_servers.reticle]` table
|
|
24
|
+
* that `codex mcp add` writes. Its config is TOML, which this repo does not reformat: the grant adds
|
|
25
|
+
* one line under our own table header and changes no other line. When that header is not there in
|
|
26
|
+
* its plain form, nothing is written and the setting is named instead.
|
|
26
27
|
*/
|
|
27
28
|
import { joinFor, parentOf } from './agent-configs.js';
|
|
28
29
|
const RETICLE_KEY = 'reticle';
|
|
@@ -41,6 +42,26 @@ function addToList(current, outer, key, value) {
|
|
|
41
42
|
const next = { ...scope, [key]: [...list, value] };
|
|
42
43
|
return null === outer ? next : { ...current, [outer]: next };
|
|
43
44
|
}
|
|
45
|
+
const CODEX_RULE = 'default_tools_approval_mode = "approve"';
|
|
46
|
+
const CODEX_TABLE = new RegExp(`^\\s*\\[\\s*mcp_servers\\s*\\.\\s*(?:${RETICLE_KEY}|"${RETICLE_KEY}"|'${RETICLE_KEY}')\\s*\\]\\s*(?:#.*)?$`);
|
|
47
|
+
const CODEX_MODE_KEY = /^\s*default_tools_approval_mode\s*=/;
|
|
48
|
+
const TOML_HEADER = /^\s*\[/;
|
|
49
|
+
/** One line under our `[mcp_servers.reticle]` header. A mode the user set is kept. */
|
|
50
|
+
function codexApprove(current) {
|
|
51
|
+
const eol = current.includes('\r\n') ? '\r\n' : '\n';
|
|
52
|
+
const lines = current.split(/\r?\n/);
|
|
53
|
+
const at = lines.findIndex((line) => CODEX_TABLE.test(line));
|
|
54
|
+
if (at < 0) {
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
const next = lines.findIndex((line, i) => i > at && TOML_HEADER.test(line));
|
|
58
|
+
const table = lines.slice(at + 1, next < 0 ? undefined : next);
|
|
59
|
+
if (table.some((line) => CODEX_MODE_KEY.test(line))) {
|
|
60
|
+
return current;
|
|
61
|
+
}
|
|
62
|
+
lines.splice(at + 1, 0, CODEX_RULE);
|
|
63
|
+
return lines.join(eol);
|
|
64
|
+
}
|
|
44
65
|
export const APPROVAL_GRANTS = [
|
|
45
66
|
{
|
|
46
67
|
id: 'claude-code',
|
|
@@ -98,6 +119,16 @@ export const APPROVAL_GRANTS = [
|
|
|
98
119
|
return { ...c, mcpServers: { ...servers, [RETICLE_KEY]: { ...entry, trust: true } } };
|
|
99
120
|
},
|
|
100
121
|
},
|
|
122
|
+
{
|
|
123
|
+
id: 'codex',
|
|
124
|
+
name: 'Codex',
|
|
125
|
+
paths: home('.codex/config.toml'),
|
|
126
|
+
markers: [home('.codex')],
|
|
127
|
+
rule: `mcp_servers.${RETICLE_KEY}.${CODEX_RULE}`,
|
|
128
|
+
grant: (c) => c,
|
|
129
|
+
editText: codexApprove,
|
|
130
|
+
manual: (file) => `add \`${CODEX_RULE}\` under [mcp_servers.${RETICLE_KEY}] in ${file}. Without it, Codex asks before every reticle tool call, and refuses each one under approval_policy = "never".`,
|
|
131
|
+
},
|
|
101
132
|
];
|
|
102
133
|
export const ApprovalOutcome = {
|
|
103
134
|
GRANTED: 'granted',
|
|
@@ -123,6 +154,23 @@ export function grantAutoApproval(io, where, grants = APPROVAL_GRANTS) {
|
|
|
123
154
|
return { ...base, outcome: ApprovalOutcome.ABSENT };
|
|
124
155
|
try {
|
|
125
156
|
const existed = io.exists(file);
|
|
157
|
+
if (grant.editText !== undefined) {
|
|
158
|
+
const current = existed ? io.readFile(file) : '';
|
|
159
|
+
const next = grant.editText(current);
|
|
160
|
+
if (null === next) {
|
|
161
|
+
const warn = grant.manual?.(file);
|
|
162
|
+
return {
|
|
163
|
+
...base,
|
|
164
|
+
outcome: ApprovalOutcome.DEFERRED,
|
|
165
|
+
...(warn === undefined ? {} : { warn }),
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
if (next === current) {
|
|
169
|
+
return { ...base, outcome: ApprovalOutcome.ALREADY };
|
|
170
|
+
}
|
|
171
|
+
io.writeFile(file, next);
|
|
172
|
+
return { ...base, outcome: ApprovalOutcome.GRANTED };
|
|
173
|
+
}
|
|
126
174
|
if (true === grant.supersedesInApp && !existed) {
|
|
127
175
|
return {
|
|
128
176
|
...base,
|
|
@@ -13,15 +13,7 @@ declare const HandedOverSchema: z.ZodObject<{
|
|
|
13
13
|
pid: z.ZodNumber;
|
|
14
14
|
url: z.ZodString;
|
|
15
15
|
appDir: z.ZodString;
|
|
16
|
-
},
|
|
17
|
-
url: string;
|
|
18
|
-
pid: number;
|
|
19
|
-
appDir: string;
|
|
20
|
-
}, {
|
|
21
|
-
url: string;
|
|
22
|
-
pid: number;
|
|
23
|
-
appDir: string;
|
|
24
|
-
}>;
|
|
16
|
+
}, z.core.$strip>;
|
|
25
17
|
export type HandedOver = z.infer<typeof HandedOverSchema>;
|
|
26
18
|
/**
|
|
27
19
|
* Written when `init` leaves a server running, so the next `init` can attach to it.
|
|
@@ -52,7 +52,11 @@ export function judgeWait(facts) {
|
|
|
52
52
|
*/
|
|
53
53
|
const CRA_PORT_BUSY = /Something is already running on port (\d+)/i;
|
|
54
54
|
const NAMED_PORT_BUSY = /Port (\d+) is (?:already )?in use/i;
|
|
55
|
-
|
|
55
|
+
// Node prints `address already in use <address>:<port>`; the port sits after the last colon of the
|
|
56
|
+
// address, so the first digit can belong to the host (`0.0.0.0:3000` said port 0, #1846). The scan
|
|
57
|
+
// also stops at the line end: the stack frame under the error (`at Server (node:net:1817:16)`)
|
|
58
|
+
// carries digits of its own, and they are not the port.
|
|
59
|
+
const EADDRINUSE_PORT = /(?:EADDRINUSE|address already in use)[^\d\n]*(?:.*:)?(\d+)/i;
|
|
56
60
|
export function portBusyMessage(output) {
|
|
57
61
|
const match = CRA_PORT_BUSY.exec(output) ?? NAMED_PORT_BUSY.exec(output) ?? EADDRINUSE_PORT.exec(output);
|
|
58
62
|
const port = match?.[1];
|
|
@@ -19,11 +19,11 @@
|
|
|
19
19
|
* `bridge-port.ts`.
|
|
20
20
|
*/
|
|
21
21
|
import { log } from '../../../log.js';
|
|
22
|
-
import { isAlive,
|
|
22
|
+
import { isAlive, reticleStateHome, spawnDaemon } from '../../daemon/daemon.js';
|
|
23
23
|
import { readDaemonRegistry } from '../../daemon/daemon-resolve.js';
|
|
24
24
|
import { LOOPBACK_HOST, STATUS_HOLD_MS } from '@reticlehq/core';
|
|
25
25
|
import { probePresence, presenceIsUsable } from '../../daemon/binding/port-presence.js';
|
|
26
|
-
import { probeDaemon, waitForDaemonBind } from '../../../surface/mcp/mcp-proxy.js';
|
|
26
|
+
import { daemonProcessAlive, probeDaemon, waitForDaemonBind } from '../../../surface/mcp/mcp-proxy.js';
|
|
27
27
|
import { daemonSpawnArgs, headlessByDefault } from '../../cli/daemon-start-options.js';
|
|
28
28
|
import { fetchStatus, summarizeStatus } from '../../daemon/binding/daemon-status-probe.js';
|
|
29
29
|
import { runKill } from '../../cli/cli-kill.js';
|
|
@@ -76,7 +76,7 @@ export async function ensureDaemon(port, deps) {
|
|
|
76
76
|
message: `The Reticle daemon on port ${String(port)} is ${theirs}, which speaks a different wire ` +
|
|
77
77
|
`contract than this init, so it will refuse your app — and ` +
|
|
78
78
|
`${String(sessionCount)} session(s) are still using it, so init will not stop it. When ` +
|
|
79
|
-
`they are done, run \`npx @reticlehq/server
|
|
79
|
+
`they are done, run \`npx @reticlehq/server stop --force --port ${String(port)}\` and re-run init.`,
|
|
80
80
|
};
|
|
81
81
|
}
|
|
82
82
|
if (!(await deps.replace(port)))
|
|
@@ -168,10 +168,7 @@ export function nodeEnsureDaemonDeps(skewed) {
|
|
|
168
168
|
log('reticle_setup_daemon_started', { port, started });
|
|
169
169
|
return started;
|
|
170
170
|
},
|
|
171
|
-
starting:
|
|
172
|
-
const pid = readPid(port);
|
|
173
|
-
return null !== pid && isAlive(pid);
|
|
174
|
-
},
|
|
171
|
+
starting: daemonProcessAlive,
|
|
175
172
|
// The same wait `reticle restart` does: poll until `/status` answers as a daemon, bounded. A
|
|
176
173
|
// cold daemon on a fresh HOME outlived the proxy's shorter reconnect budget this used to borrow.
|
|
177
174
|
waitReady: async (port) => {
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
import { homedir } from 'node:os';
|
|
1
2
|
import { spanSync } from '../../../trace.js';
|
|
3
|
+
import { hookBinFor } from '../../cli/hook/hook-fast.js';
|
|
2
4
|
import { reportInitOutcome } from '../../../telemetry/init-telemetry.js';
|
|
3
5
|
import { reportOnboardingStep } from '../../../telemetry/onboarding-funnel.js';
|
|
4
6
|
import { defaultPairingTokenDir, readOrCreatePairingTokenSync, } from '../../../portal/bridge/pairing-token.js';
|
|
@@ -38,6 +40,10 @@ export function serverInitHost() {
|
|
|
38
40
|
},
|
|
39
41
|
// Claude Code marks every process it spawns. If the marker ever changes, init falls back to the
|
|
40
42
|
// notice it printed before, which is the safe direction.
|
|
43
|
+
/** This CLI's own bin, so the agent hooks run it with node instead of paying npx's start. */
|
|
44
|
+
hookBin() {
|
|
45
|
+
return hookBinFor(homedir(), process.platform);
|
|
46
|
+
},
|
|
41
47
|
insideClaudeCode() {
|
|
42
48
|
return CLAUDE_CODE_MARKER_VALUE === process.env[CLAUDE_CODE_MARKER_ENV];
|
|
43
49
|
},
|
|
@@ -58,11 +58,12 @@ dir) {
|
|
|
58
58
|
// it recorded. Moving off it strands that agent: an MCP resolves its port once, at startup.
|
|
59
59
|
if (true === deps.daemonStartedHere?.(RETICLE_DEFAULT_PORT))
|
|
60
60
|
return undefined;
|
|
61
|
-
//
|
|
62
|
-
//
|
|
63
|
-
//
|
|
61
|
+
// A daemon that serves other projects, one or several, is somebody else's: it is rooted in their
|
|
62
|
+
// directory and linked to their cloud project, even when its bridge would accept this page. A
|
|
63
|
+
// daemon serving nobody, or this project among others, is kept. A project that has never been
|
|
64
|
+
// through init has no id yet, so every named holder is somebody else.
|
|
64
65
|
const holders = await deps.daemonProjects(RETICLE_DEFAULT_PORT);
|
|
65
|
-
if (
|
|
66
|
+
if (0 === holders.length || (projectId !== undefined && holders.includes(projectId)))
|
|
66
67
|
return undefined;
|
|
67
68
|
const seed = projectId ?? dir;
|
|
68
69
|
return deps.pickPort(seed === undefined ? PROJECT_PORT_FIRST : projectPortFor(seed));
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
import { existsSync, readFileSync, writeFileSync } from 'node:fs';
|
|
9
9
|
import { join } from 'node:path';
|
|
10
10
|
import { InitConfirmation, RETICLE_DEFAULT_PORT } from '@reticlehq/core';
|
|
11
|
-
import { FEEDBACK_HINT, Framework, InitFailure } from '@reticlehq/init';
|
|
11
|
+
import { COMMUNITY_HINT, FEEDBACK_HINT, Framework, InitFailure, } from '@reticlehq/init';
|
|
12
12
|
import { confirmInstall, nodeConfirmDeps } from '../terminal/confirm.js';
|
|
13
13
|
import { writeLicenseKey } from '../license-key.js';
|
|
14
14
|
import { registerOtherAgents, runSetupCommand, } from '../setup-command.js';
|
|
@@ -228,6 +228,8 @@ firstFlow) {
|
|
|
228
228
|
return undefined === devCommand ? {} : { devCommand, devCommandIsStaticPage: true };
|
|
229
229
|
})(),
|
|
230
230
|
...(undefined === parsed.url ? {} : { suppliedUrl: parsed.url }),
|
|
231
|
+
// So setup can tell which port the dev server will take, before it starts one (#1377).
|
|
232
|
+
framework: context.framework,
|
|
231
233
|
}, (line) => io.print(line))
|
|
232
234
|
.then(async (outcome) => {
|
|
233
235
|
if (result.outcome !== undefined) {
|
|
@@ -247,6 +249,8 @@ firstFlow) {
|
|
|
247
249
|
outcome.reachedPhase === SetupPhase.DEV_SERVER
|
|
248
250
|
? InitFailure.DEV_SERVER
|
|
249
251
|
: InitFailure.APP_CONNECTION;
|
|
252
|
+
if (outcome.stop !== undefined)
|
|
253
|
+
init.stop = outcome.stop;
|
|
250
254
|
}
|
|
251
255
|
reportOnce(init);
|
|
252
256
|
}
|
|
@@ -282,12 +286,14 @@ firstFlow) {
|
|
|
282
286
|
io.print(` ${String(i + 1)}. ${step}`);
|
|
283
287
|
// Already spaced by the blank line above when nothing was listed.
|
|
284
288
|
ask(0 < outcome.fallback.length);
|
|
289
|
+
io.print(COMMUNITY_HINT);
|
|
285
290
|
return;
|
|
286
291
|
}
|
|
287
292
|
if (outcome.ok) {
|
|
288
293
|
io.print(`✓ setup complete — ${outcome.url ?? 'the app'} is instrumented and its first flow is ` +
|
|
289
294
|
'saved. The tab stays open; a linked project sends the flow and its run to your dashboard.');
|
|
290
295
|
ask();
|
|
296
|
+
io.print(COMMUNITY_HINT);
|
|
291
297
|
return;
|
|
292
298
|
}
|
|
293
299
|
// A run that produced no verdict did not succeed, and the exit code is the one place a caller
|
|
@@ -13,6 +13,14 @@
|
|
|
13
13
|
*/
|
|
14
14
|
import type { CandidateSession } from './session-pick.js';
|
|
15
15
|
import type { PageProbe } from './probe/page-probe.js';
|
|
16
|
+
/**
|
|
17
|
+
* The state home when this process can write it, else the project's own `.reticle/logs`.
|
|
18
|
+
*
|
|
19
|
+
* A sandboxed agent host or a locked-down profile cannot write the state home. Init had already
|
|
20
|
+
* wired the project by then, so a log folder must not be the reason it stops. The caller prints the
|
|
21
|
+
* log path, so the fallback is never silent.
|
|
22
|
+
*/
|
|
23
|
+
export declare function writableLogDir(preferred: string, projectDir: string): string;
|
|
16
24
|
/** The dev server this process started, and the only one it will ever stop. */
|
|
17
25
|
export declare class OwnedDevServer {
|
|
18
26
|
private readonly logDir;
|
|
@@ -12,9 +12,10 @@
|
|
|
12
12
|
* listening indefinitely.
|
|
13
13
|
*/
|
|
14
14
|
import { spawn, spawnSync } from 'node:child_process';
|
|
15
|
-
import { existsSync, mkdirSync, readdirSync, readFileSync, rmSync, statSync } from 'node:fs';
|
|
15
|
+
import { accessSync, constants as fsConstants, existsSync, mkdirSync, readdirSync, readFileSync, rmSync, statSync, writeFileSync, } from 'node:fs';
|
|
16
16
|
import { join } from 'node:path';
|
|
17
17
|
import { fileURLToPath } from 'node:url';
|
|
18
|
+
import { ReticleDir } from '@reticlehq/core';
|
|
18
19
|
import { isAlive } from '../daemon/daemon.js';
|
|
19
20
|
import { DEV_SERVER_LOG_CAP_BYTES, ROTATED_SUFFIX } from './bringup/dev-server-log-cap.js';
|
|
20
21
|
import { devServerLogName, recordHandOver, sweepDeadDevServers, } from './bringup/dev-server-files.js';
|
|
@@ -29,6 +30,37 @@ const ASTRO_DEV_BACKGROUND_ENV = 'ASTRO_DEV_BACKGROUND';
|
|
|
29
30
|
const PROBE_TIMEOUT_MS = 5_000;
|
|
30
31
|
/** The supervisor that owns the server's output and keeps its log bounded. */
|
|
31
32
|
const LOG_CAP_SCRIPT = fileURLToPath(new URL('./bringup/dev-server-log-cap.js', import.meta.url));
|
|
33
|
+
/** The error code of a `wx` write to a file that is already there. */
|
|
34
|
+
const EEXIST = 'EEXIST';
|
|
35
|
+
/**
|
|
36
|
+
* The state home when this process can write it, else the project's own `.reticle/logs`.
|
|
37
|
+
*
|
|
38
|
+
* A sandboxed agent host or a locked-down profile cannot write the state home. Init had already
|
|
39
|
+
* wired the project by then, so a log folder must not be the reason it stops. The caller prints the
|
|
40
|
+
* log path, so the fallback is never silent.
|
|
41
|
+
*/
|
|
42
|
+
export function writableLogDir(preferred, projectDir) {
|
|
43
|
+
try {
|
|
44
|
+
mkdirSync(preferred, { recursive: true });
|
|
45
|
+
accessSync(preferred, fsConstants.W_OK);
|
|
46
|
+
return preferred;
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
const fallback = join(projectDir, ReticleDir.ROOT, ReticleDir.LOGS_SUBDIR);
|
|
50
|
+
mkdirSync(fallback, { recursive: true });
|
|
51
|
+
// Its own ignore file, because the workspace one may not be written yet on a first init. `wx`
|
|
52
|
+
// creates it only when it is absent, in one step, so a file that is already there is kept.
|
|
53
|
+
try {
|
|
54
|
+
writeFileSync(join(fallback, '.gitignore'), '*\n', { flag: 'wx' });
|
|
55
|
+
}
|
|
56
|
+
catch (error) {
|
|
57
|
+
if (error.code !== EEXIST) {
|
|
58
|
+
throw error;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return fallback;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
32
64
|
/** The dev server this process started, and the only one it will ever stop. */
|
|
33
65
|
export class OwnedDevServer {
|
|
34
66
|
logDir;
|
|
@@ -51,11 +83,11 @@ export class OwnedDevServer {
|
|
|
51
83
|
* dev-server-log-cap.ts. It is the process group leader, so `pid()` and `stop()` cover both.
|
|
52
84
|
*/
|
|
53
85
|
start(command, cwd, env) {
|
|
54
|
-
|
|
86
|
+
const logDir = writableLogDir(this.logDir, cwd);
|
|
55
87
|
// Logs of servers that are gone, from every project, so the state home stops growing a file
|
|
56
88
|
// per app ever started. This one's are replaced below anyway.
|
|
57
|
-
sweepDeadDevServers(
|
|
58
|
-
const log = join(
|
|
89
|
+
sweepDeadDevServers(logDir, { alive: isAlive, now: Date.now(), keep: cwd });
|
|
90
|
+
const log = join(logDir, devServerLogName(cwd));
|
|
59
91
|
// Unlinked rather than truncated: a previous server for this project may still hold the old
|
|
60
92
|
// file open, and truncating under it would interleave its lines into this run's output.
|
|
61
93
|
rmSync(log, { force: true });
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The port the dev server will take, when that is known: the one its script pins, else the
|
|
3
|
+
* framework's default unless the dev config names a port of its own. Undefined otherwise, and
|
|
4
|
+
* nothing is probed: a guessed port refusing a start would be a worse failure than this one.
|
|
5
|
+
*/
|
|
6
|
+
export declare function expectedDevPort(facts: {
|
|
7
|
+
pinned?: number | undefined;
|
|
8
|
+
framework?: string | undefined;
|
|
9
|
+
devConfig?: string | undefined;
|
|
10
|
+
}): number | undefined;
|
|
11
|
+
/**
|
|
12
|
+
* The one loopback something answers on at `port` while the other is free, or undefined.
|
|
13
|
+
*
|
|
14
|
+
* Only that split is refused. A port busy on both loopbacks is one the dev server sees: Vite and
|
|
15
|
+
* Next move to the next port and print it, and setup reads that, as it always has. A second Vite
|
|
16
|
+
* app on 5173 is the common case, and stopping there would break a start that works. The dev server
|
|
17
|
+
* cannot see a listener on only one loopback, because it binds the other with no error, and then
|
|
18
|
+
* `localhost` and `127.0.0.1` serve two different apps.
|
|
19
|
+
*/
|
|
20
|
+
export declare function loneLoopbackOnDevPort(port: number): Promise<string | undefined>;
|
|
21
|
+
/** What setup says instead of starting a dev server on the other half of a split port. */
|
|
22
|
+
export declare function splitDevPortNote(port: number, host: string): string;
|
|
23
|
+
/** The text of every dev config present in `appDir`, joined, or undefined when there is none. */
|
|
24
|
+
export declare function devConfigText(appDir: string): string | undefined;
|
|
25
|
+
/** The port the project's dev script pins (`--port`, `-p`, `PORT=`), or undefined. */
|
|
26
|
+
export declare function pinnedDevPort(appDir: string): number | undefined;
|