@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
|
@@ -8,14 +8,55 @@
|
|
|
8
8
|
* which `memory/project` has no business knowing. The resolver takes the answer as an injected
|
|
9
9
|
* function; the composition roots pass this one.
|
|
10
10
|
*/
|
|
11
|
-
import { isLoopbackHostname } from '@reticlehq/core';
|
|
11
|
+
import { isLocalhostSubdomain, isLoopbackHostname, } from '@reticlehq/core';
|
|
12
|
+
import { readFileSync } from 'node:fs';
|
|
13
|
+
import { homedir } from 'node:os';
|
|
14
|
+
import { join } from 'node:path';
|
|
15
|
+
import { z } from 'zod';
|
|
12
16
|
import { captureLookup, findListenerCwd } from '../../command/cli/ports/port-holder.js';
|
|
13
17
|
import { reticleStateHome } from '../../command/daemon/daemon.js';
|
|
14
18
|
import { readDevServers } from '../../command/daemon/dev-servers.js';
|
|
19
|
+
import { checkoutAt, hasLinkedWorktrees } from '../../command/cli/config/checkout.js';
|
|
20
|
+
import { callingClientDirectory } from '../../hooks/client-directory.js';
|
|
21
|
+
import { originOf } from './session-manager.js';
|
|
15
22
|
const DEFAULT_PORT = { 'http:': 80, 'https:': 443 };
|
|
23
|
+
/** portless keeps its route table here: `$PORTLESS_STATE_DIR`, else `~/.portless`. */
|
|
24
|
+
const PORTLESS_STATE_DIR_ENV = 'PORTLESS_STATE_DIR';
|
|
25
|
+
const PORTLESS_STATE_DIR = '.portless';
|
|
26
|
+
const PORTLESS_ROUTES_FILE = 'routes.json';
|
|
27
|
+
const PORTLESS_PORT_FILE = 'proxy.port';
|
|
28
|
+
const PortlessRoutesSchema = z.array(z.object({ hostname: z.string(), port: z.number().int() }).passthrough());
|
|
29
|
+
/** A file's text, or undefined when it cannot be read. */
|
|
30
|
+
function readOrUndefined(path) {
|
|
31
|
+
try {
|
|
32
|
+
return readFileSync(path, 'utf8');
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
// Missing or unreadable: not there for this purpose.
|
|
36
|
+
return undefined;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
/** The portless proxy on this machine, read from its state folder. Undefined when none runs. */
|
|
40
|
+
function readPortless() {
|
|
41
|
+
const dir = process.env[PORTLESS_STATE_DIR_ENV] ?? join(homedir(), PORTLESS_STATE_DIR);
|
|
42
|
+
const port = Number(readOrUndefined(join(dir, PORTLESS_PORT_FILE))?.trim());
|
|
43
|
+
if (!Number.isInteger(port))
|
|
44
|
+
return undefined;
|
|
45
|
+
let routes = [];
|
|
46
|
+
try {
|
|
47
|
+
const parsed = PortlessRoutesSchema.safeParse(JSON.parse(readOrUndefined(join(dir, PORTLESS_ROUTES_FILE)) ?? '[]'));
|
|
48
|
+
if (parsed.success)
|
|
49
|
+
routes = parsed.data;
|
|
50
|
+
}
|
|
51
|
+
catch {
|
|
52
|
+
// A table being rewritten reads as empty: the page stays unplaced, never placed wrong.
|
|
53
|
+
}
|
|
54
|
+
return { ports: [port], routes };
|
|
55
|
+
}
|
|
16
56
|
const liveIo = {
|
|
17
57
|
devServers: () => readDevServers(reticleStateHome()),
|
|
18
58
|
listenerCwd: (port) => findListenerCwd(port, captureLookup),
|
|
59
|
+
devProxy: readPortless,
|
|
19
60
|
};
|
|
20
61
|
/**
|
|
21
62
|
* The directory of the dev server that served `origin`, or undefined when it cannot be observed.
|
|
@@ -23,7 +64,8 @@ const liveIo = {
|
|
|
23
64
|
* Two observations, exact one first. A dev server whose plugin announced this port names its own
|
|
24
65
|
* root and works on every platform. Otherwise the process listening on the port is asked for its
|
|
25
66
|
* working directory, which covers frameworks with no announcing plugin (Next.js) wherever `lsof`
|
|
26
|
-
* runs.
|
|
67
|
+
* runs. Behind a dev proxy, the proxy's route table first names the dev server's own port. Loopback
|
|
68
|
+
* only: a remote page's port says nothing about any process on this machine.
|
|
27
69
|
*/
|
|
28
70
|
export function servingDirectoryOf(origin, io = liveIo) {
|
|
29
71
|
let url;
|
|
@@ -33,13 +75,59 @@ export function servingDirectoryOf(origin, io = liveIo) {
|
|
|
33
75
|
catch {
|
|
34
76
|
return undefined;
|
|
35
77
|
}
|
|
36
|
-
if (!isLoopbackHostname(url.hostname))
|
|
78
|
+
if (!isLoopbackHostname(url.hostname) && !isLocalhostSubdomain(url.hostname))
|
|
37
79
|
return undefined;
|
|
38
|
-
|
|
39
|
-
|
|
80
|
+
// Exact first: a dev proxy serves every worktree on one port, under the name it announced.
|
|
81
|
+
const byUrl = io.devServers().find((entry) => originOf(entry.url) === url.origin);
|
|
82
|
+
if (byUrl !== undefined)
|
|
83
|
+
return byUrl.root;
|
|
84
|
+
const pagePort = '' === url.port ? DEFAULT_PORT[url.protocol] : Number(url.port);
|
|
85
|
+
if (pagePort === undefined)
|
|
40
86
|
return undefined;
|
|
87
|
+
// Behind a dev proxy the page's port is the proxy's, and `lsof` on it names the proxy's folder.
|
|
88
|
+
// The proxy's route table names the dev server's own port.
|
|
89
|
+
const proxy = isLocalhostSubdomain(url.hostname) ? io.devProxy?.() : undefined;
|
|
90
|
+
const route = proxy?.routes.find((r) => r.hostname === url.hostname.toLowerCase());
|
|
91
|
+
if (route === undefined && true === proxy?.ports.includes(pagePort))
|
|
92
|
+
return undefined;
|
|
93
|
+
const port = route?.port ?? pagePort;
|
|
41
94
|
const announced = io.devServers().find((entry) => entry.port === port);
|
|
42
95
|
if (announced !== undefined)
|
|
43
96
|
return announced.root;
|
|
44
97
|
return io.listenerCwd(port) ?? undefined;
|
|
45
98
|
}
|
|
99
|
+
/** The checkout whose dev server serves `origin` right now, or undefined. */
|
|
100
|
+
function checkoutServing(origin) {
|
|
101
|
+
const serving = servingDirectoryOf(origin);
|
|
102
|
+
return serving === undefined ? undefined : checkoutAt(serving);
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* The live answers for a worktree-scoped resolve: the calling agent's checkout (from the directory
|
|
106
|
+
* its MCP proxy runs in) and each tab's checkout (from the dev server that served it).
|
|
107
|
+
*
|
|
108
|
+
* A tab is placed once for each connection. A page that a different dev server serves has reloaded,
|
|
109
|
+
* and a reload is a new connection. A cache by origin and time named a port that moved to another
|
|
110
|
+
* worktree after the old one for its whole lifetime.
|
|
111
|
+
* ponytail: a lookup that failed stays failed for that connection; the tab then counts as unknown.
|
|
112
|
+
*/
|
|
113
|
+
export function liveCheckoutSource(placeOrigin = checkoutServing) {
|
|
114
|
+
const placed = new WeakMap();
|
|
115
|
+
return {
|
|
116
|
+
caller: () => {
|
|
117
|
+
const dir = callingClientDirectory();
|
|
118
|
+
const checkout = dir === undefined ? undefined : checkoutAt(dir);
|
|
119
|
+
// A repository with no linked worktree has nothing to tell apart: skip the serving lookups.
|
|
120
|
+
return checkout !== undefined && hasLinkedWorktrees(checkout.commonDir)
|
|
121
|
+
? checkout
|
|
122
|
+
: undefined;
|
|
123
|
+
},
|
|
124
|
+
ofTab: (tab) => {
|
|
125
|
+
if (placed.has(tab))
|
|
126
|
+
return placed.get(tab);
|
|
127
|
+
const origin = originOf(tab.url);
|
|
128
|
+
const checkout = origin === undefined ? undefined : placeOrigin(origin);
|
|
129
|
+
placed.set(tab, checkout);
|
|
130
|
+
return checkout;
|
|
131
|
+
},
|
|
132
|
+
};
|
|
133
|
+
}
|
|
@@ -6,6 +6,11 @@ export interface SessionInfo {
|
|
|
6
6
|
url: string;
|
|
7
7
|
/** Stable build-stamped project identity; absent for v1.0 SDKs that don't send it. */
|
|
8
8
|
projectId?: string;
|
|
9
|
+
/**
|
|
10
|
+
* The linked git worktree whose dev server served this tab, with its branch. Present only when the
|
|
11
|
+
* daemon can tell, and only for a worktree, not the main checkout.
|
|
12
|
+
*/
|
|
13
|
+
worktree?: string;
|
|
9
14
|
/** Absent when the page has no title — never the empty string. Fall back to `url`. */
|
|
10
15
|
title?: string;
|
|
11
16
|
adapters: string[];
|
|
@@ -19,12 +24,24 @@ export interface SessionInfo {
|
|
|
19
24
|
* not render like it.
|
|
20
25
|
*/
|
|
21
26
|
runtime?: string;
|
|
27
|
+
/**
|
|
28
|
+
* `injected` when a hosted verifier put the SDK in this page from outside. Absent means the app
|
|
29
|
+
* installed it. A reader must not count an injected session as the app having the SDK.
|
|
30
|
+
*/
|
|
31
|
+
instrumentation?: string;
|
|
22
32
|
/** The desktop window's own name (Tauri's label: `main`, `setup`) — absent on a web page. */
|
|
23
33
|
window?: string;
|
|
24
34
|
/** Present only when the document was served as an error (4xx/5xx): a 404 page is not the app. */
|
|
25
35
|
documentStatus?: number;
|
|
26
36
|
/** Present only when the page's SDK version differs from the daemon's — see version-skew.ts. */
|
|
27
37
|
versionSkew?: string;
|
|
38
|
+
/** The page's SDK version, when the page said. */
|
|
39
|
+
sdkVersion?: string;
|
|
40
|
+
/**
|
|
41
|
+
* Present only when the page SDK is a minor release or more behind the daemon. The page still
|
|
42
|
+
* connects, but the commands and fixes added since are not in it. Says how to update it.
|
|
43
|
+
*/
|
|
44
|
+
sdkBehind?: string;
|
|
28
45
|
/** ms since the SDK last reported anything (silence ⇒ likely throttled). */
|
|
29
46
|
lastSeenMs: number;
|
|
30
47
|
hidden: boolean;
|
|
@@ -76,7 +93,9 @@ interface SessionView {
|
|
|
76
93
|
adapters: string[];
|
|
77
94
|
hasCapabilities: boolean;
|
|
78
95
|
runtime: string | undefined;
|
|
96
|
+
instrumentation?: string | undefined;
|
|
79
97
|
versionSkew: string | undefined;
|
|
98
|
+
sdkVersion?: string | undefined;
|
|
80
99
|
hidden: boolean;
|
|
81
100
|
page?: PageIdentity;
|
|
82
101
|
health: () => SessionHealth;
|
|
@@ -84,6 +103,13 @@ interface SessionView {
|
|
|
84
103
|
pendingMarkCount: () => number;
|
|
85
104
|
unresponsive: () => boolean;
|
|
86
105
|
}
|
|
106
|
+
/**
|
|
107
|
+
* The note for a page whose SDK is behind the daemon, or undefined. One sentence for the listing
|
|
108
|
+
* and for each verdict on that page, so the two never disagree.
|
|
109
|
+
*/
|
|
110
|
+
export declare function sdkBehindNote(session: {
|
|
111
|
+
readonly sdkVersion?: string | undefined;
|
|
112
|
+
}): string | undefined;
|
|
87
113
|
/**
|
|
88
114
|
* Project a live Session into the shape the tools return.
|
|
89
115
|
*
|
|
@@ -6,10 +6,26 @@
|
|
|
6
6
|
* it, and separating them keeps the wire-facing shape reviewable on its own.
|
|
7
7
|
*/
|
|
8
8
|
import { SESSION_LEASE } from '@reticlehq/core';
|
|
9
|
+
import { SERVER_VERSION } from '../../command/version/identity/server-version.js';
|
|
10
|
+
import { SDK_BEHIND_NARRATION, sdkIsBehind } from '../../command/version/version-skew.js';
|
|
9
11
|
/** A document served as 4xx/5xx — a dev server's 404 page that still mounted the SDK, say. */
|
|
10
12
|
export function isErrorDocument(page) {
|
|
11
13
|
return (page?.documentStatus ?? 0) >= 400;
|
|
12
14
|
}
|
|
15
|
+
/**
|
|
16
|
+
* The note for a page whose SDK is behind the daemon, or undefined. One sentence for the listing
|
|
17
|
+
* and for each verdict on that page, so the two never disagree.
|
|
18
|
+
*/
|
|
19
|
+
export function sdkBehindNote(session) {
|
|
20
|
+
const sdk = session.sdkVersion;
|
|
21
|
+
return sdk !== undefined && sdkIsBehind(sdk, SERVER_VERSION)
|
|
22
|
+
? SDK_BEHIND_NARRATION(sdk, SERVER_VERSION)
|
|
23
|
+
: undefined;
|
|
24
|
+
}
|
|
25
|
+
function sdkBehindField(session) {
|
|
26
|
+
const note = sdkBehindNote(session);
|
|
27
|
+
return note === undefined ? {} : { sdkBehind: note };
|
|
28
|
+
}
|
|
13
29
|
/**
|
|
14
30
|
* Project a live Session into the shape the tools return.
|
|
15
31
|
*
|
|
@@ -31,10 +47,14 @@ export function buildSessionInfo(session) {
|
|
|
31
47
|
hasCapabilities: session.hasCapabilities,
|
|
32
48
|
// Omitted when the page never said, so absence stays readable as "unknown" rather than "web".
|
|
33
49
|
...(session.runtime === undefined ? {} : { runtime: session.runtime }),
|
|
50
|
+
// Said only when injected: an installed SDK is the default every older page meant.
|
|
51
|
+
...(session.instrumentation === undefined ? {} : { instrumentation: session.instrumentation }),
|
|
34
52
|
...(session.page?.windowLabel === undefined ? {} : { window: session.page.windowLabel }),
|
|
35
53
|
...(isErrorDocument(session.page) ? { documentStatus: session.page?.documentStatus ?? 0 } : {}),
|
|
36
54
|
// On every listing, not buried in a log — skew explains failures that read as app bugs.
|
|
37
55
|
...(session.versionSkew === undefined ? {} : { versionSkew: session.versionSkew }),
|
|
56
|
+
...(session.sdkVersion === undefined ? {} : { sdkVersion: session.sdkVersion }),
|
|
57
|
+
...sdkBehindField(session),
|
|
38
58
|
hidden: session.hidden,
|
|
39
59
|
...session.health(),
|
|
40
60
|
};
|
|
@@ -1,8 +1,16 @@
|
|
|
1
|
+
import { originOf, type Checkout } from '@reticlehq/core';
|
|
1
2
|
import type { NoSessionReason } from '@reticlehq/core/telemetry';
|
|
2
3
|
import { Session, type SessionInfo } from './session.js';
|
|
3
4
|
import { AttachmentHistory } from './presence/attachment-history.js';
|
|
4
5
|
import type { NoSessionNextAction } from './no-session-next-action.js';
|
|
5
6
|
import { type SessionIdentity } from './session-successor.js';
|
|
7
|
+
/** The two checkout facts a worktree-scoped resolve needs. */
|
|
8
|
+
export interface CheckoutSource {
|
|
9
|
+
/** The git checkout of the agent making this call. */
|
|
10
|
+
caller: () => Checkout | undefined;
|
|
11
|
+
/** The git checkout whose dev server served this tab connection. */
|
|
12
|
+
ofTab: (tab: Tab) => Checkout | undefined;
|
|
13
|
+
}
|
|
6
14
|
/**
|
|
7
15
|
* The agent's active project, used to scope auto-selection. `projectId` is the stable build-stamped
|
|
8
16
|
* identity (authoritative when present); `url` is the app origin, a fallback hint for older SDKs that
|
|
@@ -12,8 +20,8 @@ interface ResolveScope {
|
|
|
12
20
|
projectId?: string;
|
|
13
21
|
url?: string;
|
|
14
22
|
}
|
|
15
|
-
/**
|
|
16
|
-
export
|
|
23
|
+
/** Core's `originOf`, re-exported for this module's existing importers. */
|
|
24
|
+
export { originOf };
|
|
17
25
|
/**
|
|
18
26
|
* Honest, scoped error when sessions exist but none match the agent's project.
|
|
19
27
|
*
|
|
@@ -40,6 +48,8 @@ export declare class SessionManager {
|
|
|
40
48
|
#private;
|
|
41
49
|
/** Set the active project's default resolve scope (called once at daemon wiring). */
|
|
42
50
|
setDefaultScope(scope: ResolveScope | undefined): void;
|
|
51
|
+
/** Scope id-less calls to the calling agent's own git worktree (called once at daemon wiring). */
|
|
52
|
+
setCheckoutScope(scope: CheckoutSource | undefined): void;
|
|
43
53
|
setConnectionRecorder(record: ((projectId: string | undefined) => void) | undefined): void;
|
|
44
54
|
add(session: Session): Session | undefined;
|
|
45
55
|
/**
|
|
@@ -140,4 +150,26 @@ export declare class SessionManager {
|
|
|
140
150
|
tombstoneUrls(): readonly string[];
|
|
141
151
|
resolve(sessionId?: string, scope?: ResolveScope): Session;
|
|
142
152
|
}
|
|
143
|
-
export {
|
|
153
|
+
export interface Tab {
|
|
154
|
+
id: string;
|
|
155
|
+
url: string;
|
|
156
|
+
}
|
|
157
|
+
export interface CheckoutScope<S> {
|
|
158
|
+
sessions: S[];
|
|
159
|
+
/** Set when every tab is known to be served from another worktree of the agent's repository. */
|
|
160
|
+
refusal?: string;
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Which of a project's tabs belong to the agent's own git checkout.
|
|
164
|
+
*
|
|
165
|
+
* Every worktree of a project declares the same projectId, so the project scope lets an agent in
|
|
166
|
+
* worktree A land on the tab worktree B serves. That tab runs B's code, and a verdict on it is about
|
|
167
|
+
* code agent A never touched. The agent's checkout comes from the directory its MCP proxy runs in;
|
|
168
|
+
* a tab's checkout comes from the dev server that served it.
|
|
169
|
+
*
|
|
170
|
+
* It narrows only on facts. A tab known to come from another worktree of the agent's repository is
|
|
171
|
+
* dropped. A tab whose checkout cannot be read stays, because it can be the agent's own.
|
|
172
|
+
*/
|
|
173
|
+
export declare function scopeToCallerCheckout<S extends Tab>(sessions: readonly S[], caller: Checkout | undefined, checkoutOfTab: (tab: S) => Checkout | undefined): CheckoutScope<S>;
|
|
174
|
+
/** `/wt/a (branch feat/a)`, or the folder alone on a detached HEAD. */
|
|
175
|
+
export declare function describeCheckout(checkout: Checkout | undefined): string;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { NO_SESSION_CONNECTED_ERROR } from '@reticlehq/core';
|
|
1
|
+
import { NO_SESSION_CONNECTED_ERROR, originOf, samePath } from '@reticlehq/core';
|
|
2
2
|
import { notePendingNoSessionReason } from '../../telemetry/tool-refused.js';
|
|
3
3
|
import { declareDrivenRedactionKeys, forgetDrivenRedactionKeys, } from '../input/driven-redaction.js';
|
|
4
4
|
import { Session } from './session.js';
|
|
@@ -6,17 +6,8 @@ import { AttachmentHistory } from './presence/attachment-history.js';
|
|
|
6
6
|
import { claimedSessionOf, openedBeforeDeparture, pickDocumentSuccessor, } from './session-successor.js';
|
|
7
7
|
import { SESSION_DISCONNECTED_REASON, SESSION_PARKED_REASON } from './facts/session-replaced.js';
|
|
8
8
|
import { isErrorDocument } from './session-info.js';
|
|
9
|
-
/**
|
|
10
|
-
export
|
|
11
|
-
if (url === undefined)
|
|
12
|
-
return undefined;
|
|
13
|
-
try {
|
|
14
|
-
return new URL(url).origin;
|
|
15
|
-
}
|
|
16
|
-
catch {
|
|
17
|
-
return undefined;
|
|
18
|
-
}
|
|
19
|
-
}
|
|
9
|
+
/** Core's `originOf`, re-exported for this module's existing importers. */
|
|
10
|
+
export { originOf };
|
|
20
11
|
/**
|
|
21
12
|
* Narrow a session list to those belonging to the scoped project. With a `projectId` the match is by
|
|
22
13
|
* that stable id (origin ignored — it survives port swaps). With only a `url`, match by origin. With
|
|
@@ -114,6 +105,12 @@ export class SessionManager {
|
|
|
114
105
|
setDefaultScope(scope) {
|
|
115
106
|
this.#defaultScope = scope;
|
|
116
107
|
}
|
|
108
|
+
/** Where the calling agent's checkout and each tab's checkout come from. Unset: no worktree scope. */
|
|
109
|
+
#checkoutScope;
|
|
110
|
+
/** Scope id-less calls to the calling agent's own git worktree (called once at daemon wiring). */
|
|
111
|
+
setCheckoutScope(scope) {
|
|
112
|
+
this.#checkoutScope = scope;
|
|
113
|
+
}
|
|
117
114
|
/**
|
|
118
115
|
* Told about every session that registers, so the fact outlives this process.
|
|
119
116
|
*
|
|
@@ -246,10 +243,17 @@ export class SessionManager {
|
|
|
246
243
|
return this.#tombstones.get(sessionId);
|
|
247
244
|
}
|
|
248
245
|
list() {
|
|
246
|
+
// Only an agent whose repository has worktrees pays for the serving lookups.
|
|
247
|
+
const worktreeOf = this.#checkoutScope?.caller() === undefined ? undefined : this.#checkoutScope.ofTab;
|
|
249
248
|
return [...this.#sessions.values()].map((s) => {
|
|
250
249
|
const info = s.info();
|
|
251
250
|
const attachment = this.#attachment.of(s.id);
|
|
252
|
-
|
|
251
|
+
const served = worktreeOf?.(s);
|
|
252
|
+
return {
|
|
253
|
+
...info,
|
|
254
|
+
...(attachment === undefined ? {} : { attachment }),
|
|
255
|
+
...(true === served?.linked ? { worktree: describeCheckout(served) } : {}),
|
|
256
|
+
};
|
|
253
257
|
});
|
|
254
258
|
}
|
|
255
259
|
/** Continuity for one session — "has this been attached the whole time I am reasoning about?" */
|
|
@@ -532,7 +536,14 @@ export class SessionManager {
|
|
|
532
536
|
// An explicit per-call scope wins; otherwise the daemon's active-project default applies.
|
|
533
537
|
const effectiveScope = scope ?? this.#defaultScope;
|
|
534
538
|
const connected = [...this.#sessions.values()];
|
|
535
|
-
const
|
|
539
|
+
const inProject = scopeSessions(connected, effectiveScope);
|
|
540
|
+
// Then to the agent's own worktree: every worktree of a project declares the same projectId.
|
|
541
|
+
const byCheckout = this.#checkoutScope === undefined
|
|
542
|
+
? { sessions: inProject }
|
|
543
|
+
: scopeToCallerCheckout(inProject, this.#checkoutScope.caller(), this.#checkoutScope.ofTab);
|
|
544
|
+
if (byCheckout.refusal !== undefined)
|
|
545
|
+
throw new Error(byCheckout.refusal);
|
|
546
|
+
const all = byCheckout.sessions;
|
|
536
547
|
if (0 === all.length) {
|
|
537
548
|
// Sessions exist, but none belong to the scoped project — never fall back to a foreign tab.
|
|
538
549
|
// ponytail: still a refusal, deliberately. Auto-targeting the only connected tab would be the
|
|
@@ -626,3 +637,47 @@ export class SessionManager {
|
|
|
626
637
|
return best.s;
|
|
627
638
|
}
|
|
628
639
|
}
|
|
640
|
+
/**
|
|
641
|
+
* Which of a project's tabs belong to the agent's own git checkout.
|
|
642
|
+
*
|
|
643
|
+
* Every worktree of a project declares the same projectId, so the project scope lets an agent in
|
|
644
|
+
* worktree A land on the tab worktree B serves. That tab runs B's code, and a verdict on it is about
|
|
645
|
+
* code agent A never touched. The agent's checkout comes from the directory its MCP proxy runs in;
|
|
646
|
+
* a tab's checkout comes from the dev server that served it.
|
|
647
|
+
*
|
|
648
|
+
* It narrows only on facts. A tab known to come from another worktree of the agent's repository is
|
|
649
|
+
* dropped. A tab whose checkout cannot be read stays, because it can be the agent's own.
|
|
650
|
+
*/
|
|
651
|
+
export function scopeToCallerCheckout(sessions, caller, checkoutOfTab) {
|
|
652
|
+
if (caller === undefined)
|
|
653
|
+
return { sessions: [...sessions] };
|
|
654
|
+
const placed = sessions.map((session) => ({ session, checkout: checkoutOfTab(session) }));
|
|
655
|
+
const mine = placed.filter((p) => isSame(p.checkout?.root, caller.root)).map((p) => p.session);
|
|
656
|
+
if (mine.length > 0)
|
|
657
|
+
return { sessions: mine };
|
|
658
|
+
const siblings = placed.filter((p) => isSame(p.checkout?.commonDir, caller.commonDir));
|
|
659
|
+
if (siblings.length !== placed.length) {
|
|
660
|
+
return { sessions: placed.filter((p) => !siblings.includes(p)).map((p) => p.session) };
|
|
661
|
+
}
|
|
662
|
+
if (0 === siblings.length)
|
|
663
|
+
return { sessions: [] };
|
|
664
|
+
const listed = siblings
|
|
665
|
+
.map((p) => `${describeCheckout(p.checkout)} (sessionId '${p.session.id}', ${p.session.url})`)
|
|
666
|
+
.join(', ');
|
|
667
|
+
return {
|
|
668
|
+
sessions: [],
|
|
669
|
+
refusal: `every tab of this app is served from another worktree: ${listed}. This agent runs in ` +
|
|
670
|
+
`${describeCheckout(caller)}. A verdict on another worktree's tab is about code this agent ` +
|
|
671
|
+
'did not change. Start the dev server in this worktree, or pass sessionId to drive that tab ' +
|
|
672
|
+
'on purpose.',
|
|
673
|
+
};
|
|
674
|
+
}
|
|
675
|
+
const isSame = (a, b) => a !== undefined && samePath(a, b);
|
|
676
|
+
/** `/wt/a (branch feat/a)`, or the folder alone on a detached HEAD. */
|
|
677
|
+
export function describeCheckout(checkout) {
|
|
678
|
+
if (checkout === undefined)
|
|
679
|
+
return 'an unknown folder';
|
|
680
|
+
return checkout.branch === undefined
|
|
681
|
+
? checkout.root
|
|
682
|
+
: `${checkout.root} (branch ${checkout.branch})`;
|
|
683
|
+
}
|
|
@@ -9,20 +9,12 @@
|
|
|
9
9
|
* Unique at the departed origin (and project, when known). Two live tabs at that origin is still a
|
|
10
10
|
* guess, and a guess here would drive the wrong app.
|
|
11
11
|
*/
|
|
12
|
-
import { RETICLE_URL_PARAM } from '@reticlehq/core';
|
|
12
|
+
import { RETICLE_URL_PARAM, originOf } from '@reticlehq/core';
|
|
13
13
|
const POLL_MS = 25;
|
|
14
14
|
const REAL_CLOCK = {
|
|
15
15
|
now: () => Date.now(),
|
|
16
16
|
sleep: (ms) => new Promise((resolve) => setTimeout(resolve, ms)),
|
|
17
17
|
};
|
|
18
|
-
function originOf(url) {
|
|
19
|
-
try {
|
|
20
|
-
return new URL(url).origin;
|
|
21
|
-
}
|
|
22
|
-
catch {
|
|
23
|
-
return undefined;
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
18
|
/**
|
|
27
19
|
* The session a URL explicitly CLAIMS to be, via `__reticle_session`.
|
|
28
20
|
*
|
|
@@ -1,8 +1,15 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
import { HudCorner, HudVisibility, ReticleCommand } from '@reticlehq/core';
|
|
2
|
+
import { HudCorner, HudVisibility, HUD_MIN_SDK_VERSION, HUD_RELOAD_TO_RESTORE, ReticleCommand, } from '@reticlehq/core';
|
|
3
3
|
import { ReticleTool } from '@reticlehq/core';
|
|
4
4
|
import { asNumber, asString } from '@reticlehq/core';
|
|
5
|
+
import { compareVersions } from '../../command/version/version-skew.js';
|
|
5
6
|
import { idleMsSchema } from '../../surface/tools/args/numeric-bounds.js';
|
|
7
|
+
function sdkPredatesHud(version) {
|
|
8
|
+
if (version === undefined)
|
|
9
|
+
return true;
|
|
10
|
+
const order = compareVersions(version, HUD_MIN_SDK_VERSION);
|
|
11
|
+
return order === undefined || order < 0;
|
|
12
|
+
}
|
|
6
13
|
/**
|
|
7
14
|
* Session lifecycle controls. The presenter session begins on the agent's first action and ends
|
|
8
15
|
* either when the agent ends it (reticle_end_session) or after an idle window — and the human keeps the
|
|
@@ -22,7 +29,8 @@ export const SESSION_TOOLS = [
|
|
|
22
29
|
...Object.values(HudVisibility),
|
|
23
30
|
...Object.values(HudCorner),
|
|
24
31
|
])
|
|
25
|
-
.optional()
|
|
32
|
+
.optional()
|
|
33
|
+
.describe('Hide, show or remove the HUD, or move it to a corner.'),
|
|
26
34
|
sessionId: z
|
|
27
35
|
.string()
|
|
28
36
|
.optional()
|
|
@@ -57,8 +65,18 @@ export const SESSION_TOOLS = [
|
|
|
57
65
|
// no HUD mounted. Reported, never `applied: true`: an agent told the HUD moved would test a
|
|
58
66
|
// control it is still covering.
|
|
59
67
|
const applied = res.result?.hud;
|
|
60
|
-
if (
|
|
61
|
-
|
|
68
|
+
if (hud !== undefined || corner !== undefined) {
|
|
69
|
+
if (Array.isArray(applied) && applied.includes(HUD_RELOAD_TO_RESTORE)) {
|
|
70
|
+
throw new Error(`the HUD on session ${session.id} was removed; reload the page to restore it.`);
|
|
71
|
+
}
|
|
72
|
+
if (!Array.isArray(applied)) {
|
|
73
|
+
if (sdkPredatesHud(session.sdkVersion)) {
|
|
74
|
+
const versionText = session.sdkVersion !== undefined ? `page SDK ${session.sdkVersion}` : 'the page SDK';
|
|
75
|
+
throw new Error(`${versionText} on session ${session.id} predates \`hud\` (needs ${HUD_MIN_SDK_VERSION}+). Update the SDK (npx @reticlehq/server update) or test with the HUD where it is.`);
|
|
76
|
+
}
|
|
77
|
+
throw new Error(`the page did not apply \`hud\`: no HUD is mounted on session ${session.id}, so no HUD covers the page. Continue without \`hud\`.`);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
62
80
|
return res.result ?? { applied: true };
|
|
63
81
|
},
|
|
64
82
|
},
|
|
@@ -2,6 +2,7 @@ import type { WebSocket } from 'ws';
|
|
|
2
2
|
import { type ChannelId, type ImpactSnapshot, type ProjectId } from '@reticlehq/core';
|
|
3
3
|
import { type NarrationBy } from './narration-args.js';
|
|
4
4
|
import type { HandshakeFacts } from './facts/handshake-facts.js';
|
|
5
|
+
import type { ProductionDrive } from '../production/production-drive.js';
|
|
5
6
|
import { LastAct } from './last-act.js';
|
|
6
7
|
import { GapLedger } from '@reticlehq/engine/evidence/gap-ledger.js';
|
|
7
8
|
import { type PageRuntime } from './timing/command-timeout.js';
|
|
@@ -31,18 +32,18 @@ export declare class Session implements HandshakeFacts {
|
|
|
31
32
|
* MINTED HERE. This is one of the two places a projectId enters the daemon with its provenance
|
|
32
33
|
* intact: the field is `projectId` on a zod-parsed HELLO, so the page said what it is. Every
|
|
33
34
|
* downstream reader takes the brand from this property rather than re-blessing a string.
|
|
35
|
+
* Set once more, by `adoptProject`, when a page that said nothing names its project later.
|
|
34
36
|
*/
|
|
35
|
-
|
|
37
|
+
projectId: ProjectId | undefined;
|
|
38
|
+
/** Take a later HELLO's project id when the first carried none. A set project is kept. */
|
|
39
|
+
adoptProject(projectId: string): boolean;
|
|
36
40
|
/**
|
|
37
41
|
* The `.reticle` directory this session's evidence belongs in — impact counters AND capsules.
|
|
38
42
|
* Stamped once, from the project it declared in HELLO, so every counter agrees where it goes.
|
|
39
43
|
* Undefined when nothing could name a project: callers fall back to the daemon's own root.
|
|
40
44
|
*/
|
|
41
45
|
artifactRoot: string | undefined;
|
|
42
|
-
/**
|
|
43
|
-
* Same-origin endpoints this session's project declared as background (`.reticle.json`
|
|
44
|
-
* `background`). Stamped with `artifactRoot`, from the same project. Empty excludes nothing.
|
|
45
|
-
*/
|
|
46
|
+
/** Same-origin `background` endpoints of this session's project, stamped with `artifactRoot`. */
|
|
46
47
|
background: readonly string[];
|
|
47
48
|
url: string;
|
|
48
49
|
title: string;
|
|
@@ -54,11 +55,14 @@ export declare class Session implements HandshakeFacts {
|
|
|
54
55
|
channels?: readonly ChannelId[] | undefined;
|
|
55
56
|
commands?: readonly string[] | undefined;
|
|
56
57
|
sourceMapping?: boolean | undefined;
|
|
58
|
+
instrumentation?: HandshakeFacts['instrumentation'];
|
|
57
59
|
readonly redactKeys: readonly string[];
|
|
58
60
|
/** The desktop window this is and its document's HTTP status, merged from every PAGE_HEALTH. */
|
|
59
61
|
readonly page: ReturnType<typeof readHealthEvent>['page'];
|
|
60
62
|
/** The newest journal action: a verdict's screenshot names it, so the run pairs it with its check. */
|
|
61
63
|
lastActionId: string | undefined;
|
|
64
|
+
/** Set when a production nonce opened this session: every act then passes the production policy. */
|
|
65
|
+
production: ProductionDrive | undefined;
|
|
62
66
|
constructor(hello: HelloMessage, socket: WebSocket, clock: Clock);
|
|
63
67
|
/** Milliseconds since this session connected — the authoritative buffer clock. */
|
|
64
68
|
elapsed(): number;
|
|
@@ -267,11 +271,7 @@ export declare class Session implements HandshakeFacts {
|
|
|
267
271
|
pushView(name: typeof ReticleCommand.FLOW_PROGRESS | typeof ReticleCommand.PLAN, args: object): void;
|
|
268
272
|
/** The one-time lease block on the first agent command, then undefined forever after. */
|
|
269
273
|
takeSessionLease(): SessionLease | undefined;
|
|
270
|
-
/**
|
|
271
|
-
* Returns a human-readable age warning after SESSION_LEASE.WARN_AFTER_MS (10 min), else undefined.
|
|
272
|
-
* Spliced onto every session-bound tool result so the agent is passively reminded to clean up
|
|
273
|
-
* without needing an explicit polling loop.
|
|
274
|
-
*/
|
|
274
|
+
/** The age reminder spliced onto session-bound results, so the agent cleans up without polling. */
|
|
275
275
|
ageWarning(): string | undefined;
|
|
276
276
|
/** Wired by SessionManager.add, the one place every session registers. */
|
|
277
277
|
setViewers(read: () => Session[]): void;
|