@reticlehq/server 3.6.0 → 3.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/SKILL.md +122 -123
- package/dist/command/cli/adhoc-suite.d.ts +14 -0
- package/dist/command/cli/adhoc-suite.js +42 -7
- package/dist/command/cli/adhoc-verdict.d.ts +18 -2
- package/dist/command/cli/adhoc-verdict.js +70 -6
- package/dist/command/cli/answers/gate-exit.d.ts +23 -0
- package/dist/command/cli/answers/gate-exit.js +45 -0
- package/dist/command/cli/answers/gate-hook-message.d.ts +2 -0
- package/dist/command/cli/answers/gate-hook-message.js +3 -1
- package/dist/command/cli/auth/device-flow.d.ts +13 -2
- package/dist/command/cli/auth/device-flow.js +17 -0
- package/dist/command/cli/cli-doctor.js +14 -0
- package/dist/command/cli/cli-flow-commands.d.ts +0 -11
- package/dist/command/cli/cli-flow-commands.js +28 -105
- package/dist/command/cli/cli-kill.js +3 -2
- package/dist/command/cli/cli-parse-grammar.d.ts +24 -0
- package/dist/command/cli/cli-parse-grammar.js +75 -0
- package/dist/command/cli/cli-parse-verify.d.ts +2 -0
- package/dist/command/cli/cli-parse-verify.js +18 -0
- package/dist/command/cli/cli-parse.d.ts +19 -28
- package/dist/command/cli/cli-parse.js +82 -182
- package/dist/command/cli/cli-update-commands.d.ts +1 -1
- package/dist/command/cli/cli-update-commands.js +61 -9
- package/dist/command/cli/cli-usage.d.ts +33 -0
- package/dist/command/cli/cli-usage.js +287 -0
- package/dist/command/cli/cli-verify.d.ts +34 -4
- package/dist/command/cli/cli-verify.js +81 -12
- package/dist/command/cli/cloud-cli.d.ts +13 -0
- package/dist/command/cli/cloud-cli.js +145 -333
- package/dist/command/cli/cloud-kit.d.ts +12 -0
- package/dist/command/cli/cloud-kit.js +41 -2
- package/dist/command/cli/cloud-link.d.ts +57 -0
- package/dist/command/cli/cloud-link.js +308 -0
- package/dist/command/cli/cloud-login.d.ts +15 -1
- package/dist/command/cli/cloud-login.js +67 -13
- package/dist/command/cli/context-command.d.ts +1 -0
- package/dist/command/cli/context-command.js +33 -0
- package/dist/command/cli/daemon-start-options.d.ts +3 -0
- package/dist/command/cli/daemon-start-options.js +24 -3
- package/dist/command/cli/doctor/doctor-coverage-line.d.ts +2 -0
- package/dist/command/cli/doctor/doctor-coverage-line.js +47 -0
- package/dist/command/cli/doctor/doctor-project-line.d.ts +0 -12
- package/dist/command/cli/doctor/doctor-project-line.js +5 -4
- package/dist/command/cli/doctor/doctor-rows.d.ts +6 -0
- package/dist/command/cli/doctor/doctor-rows.js +6 -0
- package/dist/command/cli/doctor/doctor-signing-line.d.ts +38 -0
- package/dist/command/cli/doctor/doctor-signing-line.js +114 -0
- package/dist/command/cli/known-regression.d.ts +13 -0
- package/dist/command/cli/known-regression.js +34 -0
- package/dist/command/cli/launch/sdk-version-match.d.ts +12 -0
- package/dist/command/cli/launch/sdk-version-match.js +25 -0
- package/dist/command/cli/lifecycle/daemon-lifecycle.js +11 -2
- package/dist/command/cli/mcp-command.d.ts +6 -0
- package/dist/command/cli/mcp-command.js +13 -5
- package/dist/command/cli/ports/port-holder.js +1 -1
- package/dist/command/cli/project-name.d.ts +29 -1
- package/dist/command/cli/project-name.js +107 -2
- package/dist/command/cli/setup-mcp-cli.d.ts +17 -1
- package/dist/command/cli/setup-mcp-cli.js +29 -8
- package/dist/command/cli/status/status-lines.d.ts +1 -0
- package/dist/command/cli/status/status-lines.js +47 -2
- package/dist/command/cli/status/workspace-links.d.ts +10 -0
- package/dist/command/cli/status/workspace-links.js +29 -0
- package/dist/command/cli/try-command.d.ts +96 -0
- package/dist/command/cli/try-command.js +362 -0
- package/dist/command/cli/tutorial.d.ts +0 -100
- package/dist/command/cli/tutorial.js +0 -178
- package/dist/command/cli/verify-results.d.ts +19 -0
- package/dist/command/cli/verify-results.js +29 -0
- package/dist/command/cli-onboarding.d.ts +0 -11
- package/dist/command/cli-onboarding.js +0 -15
- package/dist/command/cli.d.ts +14 -0
- package/dist/command/cli.js +103 -83
- package/dist/command/daemon/daemon-resilience.js +4 -4
- package/dist/command/daemon/daemon-resolve.d.ts +9 -1
- package/dist/command/daemon/daemon-resolve.js +49 -10
- package/dist/command/setup/bringup/bridge-port.d.ts +3 -1
- package/dist/command/setup/bringup/bridge-port.js +13 -3
- package/dist/command/setup/bringup/dev-server-log-cap.js +2 -0
- package/dist/command/setup/bringup/ensure-daemon.js +9 -2
- package/dist/command/setup/init/agent-restart.d.ts +23 -0
- package/dist/command/setup/init/agent-restart.js +28 -0
- package/dist/command/setup/init/init-port.d.ts +10 -1
- package/dist/command/setup/init/init-port.js +22 -2
- package/dist/command/setup/init/init-runtime.d.ts +12 -2
- package/dist/command/setup/init/init-runtime.js +96 -37
- package/dist/command/setup/node-effects.d.ts +2 -0
- package/dist/command/setup/node-effects.js +36 -8
- package/dist/command/setup/probe/existing-app.d.ts +12 -0
- package/dist/command/setup/probe/existing-app.js +14 -0
- package/dist/command/setup/remaining-steps.js +1 -1
- package/dist/command/setup/run-setup.d.ts +29 -9
- package/dist/command/setup/run-setup.js +34 -28
- package/dist/command/setup/setup-command.d.ts +23 -0
- package/dist/command/setup/setup-command.js +57 -4
- package/dist/command/setup/setup-mcp.js +25 -2
- package/dist/command/setup/tauri-signing.d.ts +19 -0
- package/dist/command/setup/tauri-signing.js +79 -0
- package/dist/command/setup/terminal/listeners.d.ts +10 -1
- package/dist/command/setup/terminal/listeners.js +37 -6
- package/dist/command/update/update-nudge.d.ts +9 -0
- package/dist/command/update/update-nudge.js +1 -1
- package/dist/command/update/updater.js +11 -15
- package/dist/command/version/version-nudge.js +3 -0
- package/dist/command/version/version-skew.d.ts +20 -1
- package/dist/command/version/version-skew.js +38 -2
- package/dist/features/crawl/crawl.js +14 -1
- package/dist/features/exhaust/ledger.d.ts +14 -14
- package/dist/features/harness/drive-report.d.ts +39 -5
- package/dist/features/harness/drive-report.js +271 -54
- package/dist/features/harness/drive-runs.d.ts +120 -0
- package/dist/features/harness/drive-runs.js +289 -0
- package/dist/features/harness/drivers.d.ts +1 -1
- package/dist/features/harness/drivers.js +1 -1
- package/dist/features/harness/explore/console-pages.d.ts +15 -0
- package/dist/features/harness/explore/console-pages.js +146 -0
- package/dist/features/harness/explore/disparity.d.ts +19 -0
- package/dist/features/harness/explore/disparity.js +71 -0
- package/dist/features/harness/explore/fake-app.d.ts +16 -0
- package/dist/features/harness/explore/fake-app.js +49 -0
- package/dist/features/harness/explore/goal-search.d.ts +26 -0
- package/dist/features/harness/explore/goal-search.js +144 -0
- package/dist/features/harness/explore/page-tree.d.ts +49 -0
- package/dist/features/harness/explore/page-tree.js +148 -0
- package/dist/features/harness/explore/site-map.d.ts +34 -0
- package/dist/features/harness/explore/site-map.js +150 -0
- package/dist/features/harness/goals.d.ts +68 -7
- package/dist/features/harness/goals.js +289 -36
- package/dist/features/harness/harness.d.ts +30 -1
- package/dist/features/harness/harness.js +141 -7
- package/dist/features/harness/platform/local-apps.d.ts +36 -3
- package/dist/features/harness/platform/local-apps.js +81 -5
- package/dist/features/harness/platform/persona-credentials.d.ts +20 -0
- package/dist/features/harness/platform/persona-credentials.js +69 -0
- package/dist/features/harness/platform/platform-drives.d.ts +61 -0
- package/dist/features/harness/platform/platform-drives.js +114 -0
- package/dist/features/harness/platform/refusal.d.ts +52 -0
- package/dist/features/harness/platform/refusal.js +71 -0
- package/dist/features/harness/platform/remote-drive.d.ts +8 -2
- package/dist/features/harness/platform/remote-drive.js +22 -9
- package/dist/features/harness/platform/script.d.ts +57 -11
- package/dist/features/harness/platform/script.js +144 -12
- package/dist/features/harness/platform/server-driver.d.ts +17 -4
- package/dist/features/harness/platform/server-driver.js +29 -26
- package/dist/features/harness/platform-config.d.ts +38 -5
- package/dist/features/harness/platform-config.js +93 -8
- package/dist/features/harness/route-guess.d.ts +13 -0
- package/dist/features/harness/route-guess.js +49 -0
- package/dist/features/harness/script/script-run.d.ts +30 -1
- package/dist/features/harness/script/script-run.js +355 -48
- package/dist/features/license/license.d.ts +2 -2
- package/dist/features/visual/step-shots.d.ts +31 -0
- package/dist/features/visual/step-shots.js +231 -0
- package/dist/features/visual/visual-tools.js +22 -14
- package/dist/hooks/client-directory.d.ts +18 -0
- package/dist/hooks/client-directory.js +57 -0
- package/dist/hooks/coding-agents.d.ts +34 -0
- package/dist/hooks/coding-agents.js +117 -0
- package/dist/hooks/driven-by.d.ts +21 -2
- package/dist/hooks/driven-by.js +42 -2
- package/dist/hooks/hook-bus.d.ts +4 -0
- package/dist/hooks/hook-bus.js +18 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +26 -183
- package/dist/judgement/capsule/capsule-store.d.ts +2 -2
- package/dist/judgement/capsule/causal-summary.d.ts +15 -1
- package/dist/judgement/capsule/causal-summary.js +33 -0
- package/dist/judgement/runs/artifact/build-verification-run.d.ts +1 -1
- package/dist/judgement/runs/artifact/build-verification-run.js +20 -4
- package/dist/judgement/runs/artifact/gap-summary.d.ts +0 -18
- package/dist/judgement/runs/artifact/gap-summary.js +12 -3
- package/dist/judgement/runs/artifact/replay-mapping.js +25 -9
- package/dist/judgement/runs/artifact/run-store.d.ts +13 -1
- package/dist/judgement/runs/artifact/run-store.js +175 -8
- package/dist/judgement/runs/context-tools.js +59 -1
- package/dist/judgement/runs/default-run-id.d.ts +3 -0
- package/dist/judgement/runs/default-run-id.js +16 -0
- package/dist/judgement/runs/drive-run.d.ts +53 -5
- package/dist/judgement/runs/drive-run.js +234 -20
- package/dist/judgement/runs/resume.d.ts +44 -0
- package/dist/judgement/runs/resume.js +137 -0
- package/dist/judgement/runs/reticle-runner.js +5 -2
- package/dist/judgement/runs/runner-port.d.ts +5 -1
- package/dist/judgement/runs/runner-port.js +8 -2
- package/dist/judgement/runs/verification-sync.d.ts +2 -0
- package/dist/judgement/runs/verification-sync.js +36 -15
- package/dist/language/flows/decision.js +2 -1
- package/dist/language/flows/fields/flow-secret-field.d.ts +12 -0
- package/dist/language/flows/fields/flow-secret-field.js +25 -2
- package/dist/language/flows/flow-anchor.d.ts +7 -2
- package/dist/language/flows/flow-anchor.js +10 -3
- package/dist/language/flows/flow-intent.d.ts +1 -0
- package/dist/language/flows/flow-journey.d.ts +6 -0
- package/dist/language/flows/flow-journey.js +20 -0
- package/dist/language/flows/flow-learning.d.ts +4 -0
- package/dist/language/flows/flow-learning.js +37 -3
- package/dist/language/flows/flow-replay-run.js +16 -18
- package/dist/language/flows/flow-replay-types.d.ts +1 -1
- package/dist/language/flows/flow-replay.d.ts +18 -1
- package/dist/language/flows/flow-replay.js +22 -7
- package/dist/language/flows/flow-result.d.ts +22 -1
- package/dist/language/flows/flow-result.js +47 -2
- package/dist/language/flows/flow-step-runners.d.ts +2 -0
- package/dist/language/flows/flow-step-runners.js +12 -6
- package/dist/language/flows/flow-store-for-session.js +5 -1
- package/dist/language/flows/flow-tools.d.ts +10 -0
- package/dist/language/flows/flow-tools.js +61 -62
- package/dist/language/flows/flows.d.ts +16 -1
- package/dist/language/flows/flows.js +69 -10
- package/dist/language/flows/narrow-write.d.ts +7 -0
- package/dist/language/flows/narrow-write.js +36 -1
- package/dist/language/flows/recording/recording-backtrack.js +14 -1
- package/dist/language/flows/recording/tape/recordings.d.ts +29 -1
- package/dist/language/flows/recording/tape/recordings.js +60 -10
- package/dist/language/flows/replay.js +29 -6
- package/dist/language/flows/single-replay.d.ts +7 -0
- package/dist/language/flows/single-replay.js +26 -0
- package/dist/language/flows/verify-change-tools.d.ts +1 -0
- package/dist/language/flows/verify-change-tools.js +200 -193
- package/dist/memory/cloud/cloud-config.d.ts +10 -1
- package/dist/memory/cloud/cloud-config.js +19 -5
- package/dist/memory/cloud/cloud-sync.js +3 -3
- package/dist/memory/cloud/harness-config.d.ts +49 -0
- package/dist/memory/cloud/harness-config.js +16 -20
- package/dist/memory/cloud/memory-scope.d.ts +17 -0
- package/dist/memory/cloud/memory-scope.js +22 -0
- package/dist/memory/cloud/sync-cycle.d.ts +32 -4
- package/dist/memory/cloud/sync-cycle.js +113 -12
- package/dist/memory/cloud/sync-daemon.d.ts +11 -0
- package/dist/memory/cloud/sync-daemon.js +114 -4
- package/dist/memory/cloud/sync-disk.js +26 -2
- package/dist/memory/cloud/sync-screenshots.d.ts +32 -0
- package/dist/memory/cloud/sync-screenshots.js +105 -0
- package/dist/memory/cloud/unsynced-roots.d.ts +47 -0
- package/dist/memory/cloud/unsynced-roots.js +166 -0
- package/dist/memory/impact/account-watch.d.ts +16 -1
- package/dist/memory/impact/account-watch.js +26 -1
- package/dist/memory/impact/impact-store.d.ts +1 -4
- package/dist/memory/impact/impact-store.js +32 -42
- package/dist/memory/intent/inline-intent.d.ts +1 -0
- package/dist/memory/intent/intent-shard-store.js +16 -4
- package/dist/memory/intent/intent-shard.d.ts +12 -0
- package/dist/memory/intent/intent-store.d.ts +1 -0
- package/dist/memory/intent/intent-tools.js +42 -2
- package/dist/memory/intent/open-intents.d.ts +6 -0
- package/dist/memory/intent/open-intents.js +10 -1
- package/dist/memory/intent/settled-words.d.ts +24 -0
- package/dist/memory/intent/settled-words.js +130 -0
- package/dist/memory/journal/drive-flow.d.ts +16 -0
- package/dist/memory/journal/drive-flow.js +34 -2
- package/dist/memory/journal/drive-run-flush.d.ts +2 -0
- package/dist/memory/journal/drive-run-flush.js +20 -5
- package/dist/memory/journal/journal-recorder.js +46 -3
- package/dist/memory/journal/on-disk/retention.d.ts +5 -0
- package/dist/memory/journal/on-disk/retention.js +27 -2
- package/dist/memory/journal/on-disk/workspace-tiers.js +2 -0
- package/dist/memory/journal/session-end.d.ts +15 -1
- package/dist/memory/journal/session-end.js +38 -7
- package/dist/memory/project/artifact-root-resolver.js +33 -5
- package/dist/memory/project/artifact-root.d.ts +4 -3
- package/dist/memory/project/artifact-root.js +2 -2
- package/dist/memory/project/dir/reticle-dir.d.ts +14 -0
- package/dist/memory/project/dir/reticle-dir.js +23 -2
- package/dist/memory/project/link-directory.d.ts +15 -0
- package/dist/memory/project/link-directory.js +44 -0
- package/dist/memory/project/root-claims.d.ts +6 -0
- package/dist/memory/project/root-claims.js +39 -0
- package/dist/memory/project/session-root.d.ts +2 -0
- package/dist/memory/project/session-root.js +9 -1
- package/dist/memory/project/sync-status.d.ts +46 -0
- package/dist/memory/project/sync-status.js +135 -1
- package/dist/memory/recall/memory-tools.js +46 -3
- package/dist/memory/recall/platform-memory.d.ts +34 -0
- package/dist/memory/recall/platform-memory.js +139 -0
- package/dist/memory/recall/project-memory.js +36 -8
- package/dist/portal/bridge/bridge.d.ts +9 -5
- package/dist/portal/bridge/bridge.js +66 -23
- package/dist/portal/bridge/harness-request.d.ts +23 -0
- package/dist/portal/bridge/harness-request.js +27 -0
- package/dist/portal/bridge/wrong-path.d.ts +17 -0
- package/dist/portal/bridge/wrong-path.js +35 -0
- package/dist/portal/input/network-mock-tools.js +11 -2
- package/dist/portal/input/real-input.d.ts +2 -0
- package/dist/portal/input/real-input.js +13 -10
- package/dist/portal/pool/browser-pool.d.ts +48 -0
- package/dist/portal/pool/browser-pool.js +120 -2
- package/dist/portal/pool/context-permissions.d.ts +33 -0
- package/dist/portal/pool/context-permissions.js +33 -0
- package/dist/portal/pool/lease-marker-stamp.d.ts +23 -0
- package/dist/portal/pool/lease-marker-stamp.js +49 -0
- package/dist/portal/pool/playwright-launcher.d.ts +27 -5
- package/dist/portal/pool/playwright-launcher.js +59 -14
- package/dist/portal/pool/pool-contract.d.ts +21 -1
- package/dist/portal/session/agent-link.d.ts +8 -0
- package/dist/portal/session/agent-link.js +17 -0
- package/dist/portal/session/command-payload.js +6 -1
- package/dist/portal/session/daemon-answers.d.ts +3 -3
- package/dist/portal/session/daemon-answers.js +4 -2
- package/dist/portal/session/dev-server/dev-command.d.ts +9 -0
- package/dist/portal/session/dev-server/dev-command.js +27 -1
- package/dist/portal/session/facts/observed-state.d.ts +16 -18
- package/dist/portal/session/facts/observed-state.js +46 -3
- package/dist/portal/session/human/live-control.d.ts +9 -2
- package/dist/portal/session/human/live-control.js +12 -3
- package/dist/portal/session/live-control-tools.js +82 -13
- package/dist/portal/session/narration-args.d.ts +5 -0
- package/dist/portal/session/narration-args.js +17 -0
- package/dist/portal/session/no-session-diagnosis.d.ts +1 -1
- package/dist/portal/session/no-session-diagnosis.js +31 -9
- package/dist/portal/session/no-session-next-action.d.ts +20 -0
- package/dist/portal/session/no-session-next-action.js +134 -61
- package/dist/portal/session/no-session-watch.js +179 -22
- package/dist/portal/session/presence/session-lease.js +1 -1
- package/dist/portal/session/recorded-gaps.d.ts +97 -0
- package/dist/portal/session/recorded-gaps.js +251 -0
- package/dist/portal/session/session-health.d.ts +11 -0
- package/dist/portal/session/session-health.js +3 -1
- package/dist/portal/session/session-info.js +2 -1
- package/dist/portal/session/session-manager.d.ts +18 -0
- package/dist/portal/session/session-manager.js +54 -3
- package/dist/portal/session/session-successor.d.ts +8 -0
- package/dist/portal/session/session-successor.js +1 -1
- package/dist/portal/session/session.d.ts +15 -28
- package/dist/portal/session/session.js +60 -61
- package/dist/portal/session/timing/command-timeout.js +25 -1
- package/dist/portal/session/timing/wall-clock.d.ts +1 -1
- package/dist/portal/session/timing/wall-clock.js +1 -1
- package/dist/portal/session/zero-install-first-call.d.ts +31 -0
- package/dist/portal/session/zero-install-first-call.js +88 -0
- package/dist/start-options.d.ts +7 -1
- package/dist/start-wiring.d.ts +63 -0
- package/dist/start-wiring.js +169 -0
- package/dist/status-payload.d.ts +13 -1
- package/dist/status-payload.js +13 -1
- package/dist/surface/http-server.js +7 -1
- package/dist/surface/mcp/attach-memory.d.ts +1 -0
- package/dist/surface/mcp/attach-memory.js +12 -1
- package/dist/surface/mcp/mcp-proxy.d.ts +4 -0
- package/dist/surface/mcp/mcp-proxy.js +29 -8
- package/dist/surface/mcp/mcp.d.ts +23 -0
- package/dist/surface/mcp/mcp.js +34 -4
- package/dist/surface/mcp/proxy/drive-calls.d.ts +10 -0
- package/dist/surface/mcp/proxy/drive-calls.js +27 -0
- package/dist/surface/mcp/proxy/mcp-post-transport.js +5 -0
- package/dist/surface/mcp/server-instructions.js +22 -14
- package/dist/surface/mcp/shared-params.js +1 -1
- package/dist/surface/mcp/surface-vocabulary.d.ts +2 -0
- package/dist/surface/mcp/surface-vocabulary.js +1 -0
- package/dist/surface/tools/account-tool.d.ts +22 -0
- package/dist/surface/tools/account-tool.js +157 -0
- package/dist/surface/tools/act/act-danger.d.ts +11 -0
- package/dist/surface/tools/act/act-danger.js +38 -1
- package/dist/surface/tools/act/act-observation.d.ts +33 -0
- package/dist/surface/tools/act/act-observation.js +57 -0
- package/dist/surface/tools/act/act-preflight.js +25 -2
- package/dist/surface/tools/act/act-target.js +8 -3
- package/dist/surface/tools/act/resolve-target.d.ts +1 -1
- package/dist/surface/tools/act/resolve-target.js +18 -3
- package/dist/surface/tools/act/screen-request.d.ts +34 -0
- package/dist/surface/tools/act/screen-request.js +113 -0
- package/dist/surface/tools/act/sequence-grade.d.ts +8 -0
- package/dist/surface/tools/act/sequence-grade.js +13 -2
- package/dist/surface/tools/act-sequence-tool.js +136 -27
- package/dist/surface/tools/act-tools.d.ts +0 -9
- package/dist/surface/tools/act-tools.js +48 -34
- package/dist/surface/tools/agent/app-notes-learning.d.ts +7 -0
- package/dist/surface/tools/agent/app-notes-learning.js +80 -0
- package/dist/surface/tools/agent/app-notes.d.ts +4 -0
- package/dist/surface/tools/agent/app-notes.js +48 -0
- package/dist/surface/tools/agent/build-staleness.d.ts +7 -0
- package/dist/surface/tools/agent/build-staleness.js +62 -0
- package/dist/surface/tools/agent/compact-envelope.d.ts +80 -0
- package/dist/surface/tools/agent/compact-envelope.js +374 -0
- package/dist/surface/tools/agent/for-the-agent.d.ts +12 -0
- package/dist/surface/tools/agent/for-the-agent.js +44 -0
- package/dist/surface/tools/agent/notices.d.ts +50 -0
- package/dist/surface/tools/agent/notices.js +152 -0
- package/dist/surface/tools/agent/reteach.d.ts +11 -0
- package/dist/surface/tools/agent/reteach.js +50 -0
- package/dist/surface/tools/args/alias-args.d.ts +5 -0
- package/dist/surface/tools/args/alias-args.js +10 -0
- package/dist/surface/tools/args/confirm-dangerous-arg.d.ts +6 -0
- package/dist/surface/tools/args/confirm-dangerous-arg.js +6 -0
- package/dist/surface/tools/assert/assert-source.d.ts +15 -0
- package/dist/surface/tools/assert/assert-source.js +40 -0
- package/dist/surface/tools/assert/assert-verdict.js +25 -15
- package/dist/surface/tools/browser-tools.js +43 -1
- package/dist/surface/tools/chat-drives.d.ts +75 -0
- package/dist/surface/tools/chat-drives.js +265 -21
- package/dist/surface/tools/coverage-tools.d.ts +2 -10
- package/dist/surface/tools/coverage-tools.js +2 -53
- package/dist/surface/tools/dynamic-tools.js +29 -1
- package/dist/surface/tools/empty-session-list.d.ts +10 -0
- package/dist/surface/tools/empty-session-list.js +45 -5
- package/dist/surface/tools/error-recovery.d.ts +8 -0
- package/dist/surface/tools/error-recovery.js +69 -5
- package/dist/surface/tools/explore-tools.d.ts +23 -2
- package/dist/surface/tools/explore-tools.js +377 -74
- package/dist/surface/tools/feedback-tools.d.ts +2 -3
- package/dist/surface/tools/feedback-tools.js +4 -3
- package/dist/surface/tools/gap-novelty.d.ts +3 -1
- package/dist/surface/tools/gap-novelty.js +8 -1
- package/dist/surface/tools/harness-explore.d.ts +52 -73
- package/dist/surface/tools/harness-explore.js +177 -146
- package/dist/surface/tools/harness-gate.d.ts +88 -0
- package/dist/surface/tools/harness-gate.js +235 -0
- package/dist/surface/tools/harness-hunt.d.ts +43 -0
- package/dist/surface/tools/harness-hunt.js +215 -0
- package/dist/surface/tools/harness-plan.d.ts +5 -0
- package/dist/surface/tools/harness-plan.js +7 -0
- package/dist/surface/tools/harness-script.d.ts +22 -0
- package/dist/surface/tools/harness-script.js +256 -38
- package/dist/surface/tools/harness-tab-guard.d.ts +5 -0
- package/dist/surface/tools/harness-tab-guard.js +27 -0
- package/dist/surface/tools/harness-toolset.d.ts +8 -0
- package/dist/surface/tools/harness-toolset.js +27 -4
- package/dist/surface/tools/human-notes.d.ts +16 -0
- package/dist/surface/tools/human-notes.js +27 -0
- package/dist/surface/tools/invoke-tool.d.ts +5 -2
- package/dist/surface/tools/invoke-tool.js +220 -93
- package/dist/surface/tools/lease-hint.js +26 -5
- package/dist/surface/tools/lease-permissions.d.ts +33 -0
- package/dist/surface/tools/lease-permissions.js +73 -0
- package/dist/surface/tools/lease-readiness.d.ts +38 -0
- package/dist/surface/tools/lease-readiness.js +57 -0
- package/dist/surface/tools/lease-seed.d.ts +20 -0
- package/dist/surface/tools/lease-seed.js +45 -1
- package/dist/surface/tools/lease-tools.d.ts +10 -1
- package/dist/surface/tools/lease-tools.js +119 -69
- package/dist/surface/tools/live-call-text.js +2 -2
- package/dist/surface/tools/merge-tools.js +42 -2
- package/dist/surface/tools/merged-name-redirect.js +4 -0
- package/dist/surface/tools/next-step.d.ts +11 -1
- package/dist/surface/tools/next-step.js +73 -18
- package/dist/surface/tools/observe-tools.js +43 -5
- package/dist/surface/tools/platform-moment.d.ts +60 -0
- package/dist/surface/tools/platform-moment.js +132 -4
- package/dist/surface/tools/read-tools.js +65 -14
- package/dist/surface/tools/reticle-result.d.ts +120 -0
- package/dist/surface/tools/reticle-result.js +364 -0
- package/dist/surface/tools/tool-kit.d.ts +68 -2
- package/dist/surface/tools/tool-kit.js +73 -1
- package/dist/surface/tools/tools.js +25 -13
- package/dist/telemetry/account-envelope.d.ts +7 -0
- package/dist/telemetry/account-envelope.js +61 -0
- package/dist/telemetry/agent-client.d.ts +15 -0
- package/dist/telemetry/agent-client.js +57 -0
- package/dist/telemetry/app-instrumented.js +9 -2
- package/dist/telemetry/argument-shape.d.ts +7 -0
- package/dist/telemetry/argument-shape.js +86 -1
- package/dist/telemetry/automation-hint.d.ts +2 -3
- package/dist/telemetry/automation-hint.js +33 -8
- package/dist/telemetry/cli-telemetry.js +7 -2
- package/dist/telemetry/daemon-telemetry.js +3 -0
- package/dist/telemetry/error-fingerprint.d.ts +10 -1
- package/dist/telemetry/error-fingerprint.js +61 -5
- package/dist/telemetry/feedback-cli.d.ts +0 -13
- package/dist/telemetry/feedback-cli.js +0 -77
- package/dist/telemetry/feedback.d.ts +13 -0
- package/dist/telemetry/feedback.js +183 -17
- package/dist/telemetry/harness-run.d.ts +18 -0
- package/dist/telemetry/harness-run.js +80 -0
- package/dist/telemetry/hud-events.d.ts +16 -0
- package/dist/telemetry/hud-events.js +27 -0
- package/dist/telemetry/hud-metrics.d.ts +27 -6
- package/dist/telemetry/hud-metrics.js +99 -25
- package/dist/telemetry/init-telemetry.js +2 -2
- package/dist/telemetry/install-source.d.ts +13 -25
- package/dist/telemetry/install-source.js +44 -3
- package/dist/telemetry/mcp-connection.d.ts +0 -14
- package/dist/telemetry/mcp-connection.js +5 -1
- package/dist/telemetry/onboarding-firsts.d.ts +32 -0
- package/dist/telemetry/onboarding-firsts.js +81 -6
- package/dist/telemetry/platform-linked.d.ts +5 -0
- package/dist/telemetry/platform-linked.js +32 -0
- package/dist/telemetry/project-profile.js +5 -3
- package/dist/telemetry/proxy-telemetry.js +4 -1
- package/dist/telemetry/session-metrics.d.ts +15 -4
- package/dist/telemetry/session-metrics.js +88 -52
- package/dist/telemetry/telemetry.d.ts +26 -2
- package/dist/telemetry/telemetry.js +102 -21
- package/dist/telemetry/verification-of.d.ts +3 -1
- package/dist/telemetry/verification-of.js +12 -4
- package/dist/wire-journal.d.ts +2 -2
- package/dist/wire-journal.js +16 -5
- package/docs/README.md +2 -2
- package/docs/actions.mdx +6 -3
- package/docs/adapters.md +1 -1
- package/docs/agent-cheatsheet.md +24 -27
- package/docs/architecture.md +5 -5
- package/docs/autodrive.md +13 -12
- package/docs/benchmarks.md +5 -5
- package/docs/best-practices.mdx +27 -9
- package/docs/capabilities.mdx +14 -16
- package/docs/cli/affected.mdx +1 -1
- package/docs/cli/cloud.mdx +54 -75
- package/docs/cli/doctor.mdx +8 -3
- package/docs/cli/drive.mdx +12 -12
- package/docs/cli/feedback.mdx +3 -3
- package/docs/cli/gate.mdx +7 -2
- package/docs/cli/help.mdx +50 -55
- package/docs/cli/init.mdx +32 -15
- package/docs/cli/license.mdx +12 -8
- package/docs/cli/mcp.mdx +4 -4
- package/docs/cli/open.mdx +3 -3
- package/docs/cli/report.mdx +4 -2
- package/docs/cli/restart.mdx +2 -2
- package/docs/cli/rollback.mdx +14 -8
- package/docs/cli/serve.mdx +4 -4
- package/docs/cli/setup.mdx +23 -0
- package/docs/cli/status.mdx +13 -4
- package/docs/cli/stop.mdx +67 -8
- package/docs/cli/try.mdx +62 -0
- package/docs/cli/update.mdx +4 -3
- package/docs/cli/verify.mdx +17 -6
- package/docs/cli/version.mdx +3 -2
- package/docs/cli.mdx +110 -41
- package/docs/debugging.md +3 -3
- package/docs/deploy-checks.md +1 -1
- package/docs/desktop.mdx +5 -3
- package/docs/enterprise.md +11 -10
- package/docs/environment.mdx +5 -2
- package/docs/faq.mdx +3 -3
- package/docs/first-drive.md +5 -4
- package/docs/flows.md +35 -27
- package/docs/for-agents.md +4 -5
- package/docs/frameworks.mdx +32 -21
- package/docs/getting-started.md +66 -64
- package/docs/human-control.md +15 -14
- package/docs/index.mdx +15 -43
- package/docs/install-agentic.mdx +22 -37
- package/docs/install-manual.mdx +22 -12
- package/docs/instrumentation.mdx +5 -3
- package/docs/integration-patterns.md +7 -7
- package/docs/license-activation.mdx +1 -1
- package/docs/multi-agent-testing.md +24 -6
- package/docs/packages/babel-plugin.mdx +4 -2
- package/docs/packages/browser.mdx +16 -10
- package/docs/packages/core.mdx +12 -5
- package/docs/packages/electron.mdx +3 -2
- package/docs/packages/engine.mdx +1 -1
- package/docs/packages/eslint-plugin.mdx +18 -12
- package/docs/packages/next.mdx +8 -7
- package/docs/packages/open-verification.mdx +1 -1
- package/docs/packages/server.mdx +5 -5
- package/docs/packages/tauri.mdx +8 -8
- package/docs/packages/test.mdx +4 -10
- package/docs/packages/vite-plugin.mdx +11 -4
- package/docs/packages.mdx +11 -15
- package/docs/platform-integration.md +6 -5
- package/docs/predicates.mdx +40 -24
- package/docs/quickstart.mdx +58 -29
- package/docs/required-checks.md +8 -7
- package/docs/reticle-manual.md +15 -5
- package/docs/skill-file.mdx +17 -79
- package/docs/skill-setup.md +9 -9
- package/docs/skill.md +200 -0
- package/docs/system-map.md +7 -7
- package/docs/telemetry.md +22 -24
- package/docs/testing.md +4 -4
- package/docs/token-efficiency.md +12 -12
- package/docs/tools/act-and-wait.mdx +9 -2
- package/docs/tools/act-sequence.mdx +6 -7
- package/docs/tools/act.mdx +2 -2
- package/docs/tools/assert.mdx +18 -17
- package/docs/tools/console.mdx +9 -9
- package/docs/tools/inspect.mdx +16 -7
- package/docs/tools/look.mdx +24 -0
- package/docs/tools/navigate.mdx +5 -3
- package/docs/tools/network.mdx +2 -2
- package/docs/tools/observe.mdx +6 -6
- package/docs/tools/overview.mdx +34 -33
- package/docs/tools/query.mdx +5 -5
- package/docs/tools/session-and-feedback.mdx +13 -4
- package/docs/tools/sessions.mdx +8 -8
- package/docs/tools/snapshot.mdx +6 -5
- package/docs/tools/state.mdx +9 -9
- package/docs/tools/tools-and-run.mdx +26 -24
- package/docs/tools/verify.mdx +28 -0
- package/docs/tools/wait-for.mdx +8 -4
- package/docs/troubleshooting.mdx +21 -6
- package/docs/usage.md +51 -45
- package/docs/use-cases.mdx +3 -3
- package/docs/vs-chrome-devtools-mcp.mdx +9 -6
- package/docs/vs-playwright-mcp.mdx +3 -1
- package/docs/what-is-recorded.md +7 -5
- package/docs/what-is-reticle.mdx +2 -2
- package/docs/why-reticle.mdx +1 -1
- package/package.json +6 -5
- package/dist/command/cli/demo/demo-page.d.ts +0 -78
- package/dist/command/cli/demo/demo-page.js +0 -249
- package/dist/command/cli/demo/demo-run.d.ts +0 -38
- package/dist/command/cli/demo/demo-run.js +0 -138
- package/dist/judgement/hunt/hunt-report.d.ts +0 -49
- package/dist/judgement/hunt/hunt-report.js +0 -84
- package/dist/language/flows/buddy-status.d.ts +0 -25
- package/dist/language/flows/buddy-status.js +0 -32
- package/dist/language/flows/change/watch-batcher.d.ts +0 -18
- package/dist/language/flows/change/watch-batcher.js +0 -19
- package/dist/memory/cloud/harness-offer.d.ts +0 -44
- package/dist/memory/cloud/harness-offer.js +0 -145
- package/dist/surface/tools/feature-capture.d.ts +0 -151
- package/dist/surface/tools/feature-capture.js +0 -235
- package/dist/surface/tools/tool-hit-rate.d.ts +0 -87
- package/dist/surface/tools/tool-hit-rate.js +0 -90
- package/dist/telemetry/harness-drive.d.ts +0 -4
- package/dist/telemetry/harness-drive.js +0 -35
- package/dist/telemetry/identify.d.ts +0 -22
- package/dist/telemetry/identify.js +0 -73
- package/docs/cli/capsules.mdx +0 -70
- package/docs/cli/hunt.mdx +0 -73
- package/docs/cli/identify.mdx +0 -76
- package/docs/cli/kill.mdx +0 -91
- package/docs/cli/watch.mdx +0 -62
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The wiring `start` and `startDaemon` share, built in one place so the two entry points cannot drift.
|
|
3
|
+
*
|
|
4
|
+
* Split from `index.ts`: that file is the package's front door and the two entry points; these are
|
|
5
|
+
* the pieces both of them assemble — the browser pool, the drive/real-input provider, the CDP network
|
|
6
|
+
* router, and the per-project lookups the daemon closes over. `daemon-parity.test.ts` checks both
|
|
7
|
+
* entry points still call them.
|
|
8
|
+
*/
|
|
9
|
+
import { join } from 'node:path';
|
|
10
|
+
import { cpus, homedir } from 'node:os';
|
|
11
|
+
import { bridgeWsUrl, EventType, ReticleDir, ReticleEnv } from '@reticlehq/core';
|
|
12
|
+
import { fetchPlatformConfig } from './features/harness/platform-config.js';
|
|
13
|
+
import { platformEnvPort } from './memory/cloud/cloud-config.js';
|
|
14
|
+
import { knownProjectCandidates, projectDirectoryFor, } from './memory/project/artifact-root-resolver.js';
|
|
15
|
+
import { createNodeFileSystem } from './memory/project/fs/fs-port.js';
|
|
16
|
+
import { originOf } from './portal/session/session-manager.js';
|
|
17
|
+
import { setBrowserMode, BrowserMode } from './telemetry/browser-mode.js';
|
|
18
|
+
import { sdkFixForDirectory } from './command/version/sdk-fix.js';
|
|
19
|
+
import { SERVER_VERSION } from './command/version/identity/server-version.js';
|
|
20
|
+
import { CdpRealInputProvider, LaunchedRealInputProvider } from './portal/input/real-input.js';
|
|
21
|
+
import { BrowserPool } from './portal/pool/browser-pool.js';
|
|
22
|
+
import { playwrightLauncher, resolveMaxContexts } from './portal/pool/playwright-launcher.js';
|
|
23
|
+
import { readReaderBundle, zeroInstallScript as zeroInstallScriptFor, } from './portal/pool/zero-install.js';
|
|
24
|
+
/**
|
|
25
|
+
* Build the shared browser pool (one headless Chromium, N capped isolated leased contexts). Lazy —
|
|
26
|
+
* no Chromium launches until the first lease — so creating it is free even when never used.
|
|
27
|
+
*/
|
|
28
|
+
/** Where the zero-install reader connects: this daemon's own bridge, with its pairing token. */
|
|
29
|
+
export function readerConnect(port, token) {
|
|
30
|
+
return { url: bridgeWsUrl(port), ...(token === undefined ? {} : { token }) };
|
|
31
|
+
}
|
|
32
|
+
export function createBrowserPool(headless, reader) {
|
|
33
|
+
const maxContexts = resolveMaxContexts(process.env[ReticleEnv.MAX_CONTEXTS], cpus().length);
|
|
34
|
+
const genSessionId = () => `lease-${'function' === typeof globalThis.crypto?.randomUUID
|
|
35
|
+
? globalThis.crypto.randomUUID()
|
|
36
|
+
: String(Date.now())}`;
|
|
37
|
+
// Built on first use and kept: the page that needs it is one whose app never connected.
|
|
38
|
+
let script;
|
|
39
|
+
const zeroInstallScript = () => {
|
|
40
|
+
if (script === undefined) {
|
|
41
|
+
const bundle = readReaderBundle();
|
|
42
|
+
script = bundle === undefined ? null : zeroInstallScriptFor(bundle, reader);
|
|
43
|
+
}
|
|
44
|
+
return script ?? undefined;
|
|
45
|
+
};
|
|
46
|
+
return new BrowserPool(playwrightLauncher({ headless }), {
|
|
47
|
+
maxContexts,
|
|
48
|
+
genSessionId,
|
|
49
|
+
zeroInstallScript,
|
|
50
|
+
launchHeaded: playwrightLauncher({ headless: false }),
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Route CDP-authoritative network detail onto the driven session's journal.
|
|
55
|
+
*
|
|
56
|
+
* The page and the SDK session share an origin, so a NET_DETAIL is pushed to the matching connected
|
|
57
|
+
* session. Shared by both entry points: `startDaemon` previously omitted it entirely, so on the path
|
|
58
|
+
* users actually take, CDP network detail was collected and then dropped on the floor.
|
|
59
|
+
*/
|
|
60
|
+
export function makeNetworkDetailRouter(bridge, driveUrl) {
|
|
61
|
+
const driveOrigin = originOf(driveUrl ?? '');
|
|
62
|
+
return (detail) => {
|
|
63
|
+
// Route by the DOCUMENT that issued the request, not by the request's own origin.
|
|
64
|
+
//
|
|
65
|
+
// Matching the request's origin only works for same-origin calls. An app on one origin calling an
|
|
66
|
+
// API on another — most API calls — produced a detail matching no session, and it was dropped
|
|
67
|
+
// without a trace. The drive-URL fallback papered over it on the launched path and did nothing on
|
|
68
|
+
// the CDP-attach path, where driveUrl is undefined and the fallback compares against ''.
|
|
69
|
+
const pageOrigin = originOf(detail.pageUrl ?? '');
|
|
70
|
+
const requestOrigin = originOf(detail.url);
|
|
71
|
+
for (const session of bridge.sessions.all()) {
|
|
72
|
+
const origin = originOf(session.url);
|
|
73
|
+
// originOf returns `string | undefined`, NEVER '' — so the old `!== ''` guards were dead, and a
|
|
74
|
+
// bare `origin === requestOrigin` matched `undefined === undefined` when BOTH the session URL and
|
|
75
|
+
// the detail URL were unparseable. That routed a NET_DETAIL (with its response headers, incl.
|
|
76
|
+
// set-cookie) onto an unrelated session. Require a DEFINED origin; undefined operands then simply
|
|
77
|
+
// fail to match any of the three candidates.
|
|
78
|
+
const matches = origin !== undefined &&
|
|
79
|
+
(origin === pageOrigin || origin === requestOrigin || origin === driveOrigin);
|
|
80
|
+
if (matches) {
|
|
81
|
+
session.pushEvent({
|
|
82
|
+
t: 0,
|
|
83
|
+
type: EventType.NET_DETAIL,
|
|
84
|
+
sessionId: session.id,
|
|
85
|
+
data: { ...detail },
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Resolve the drive/real-input provider from options — shared by start and startDaemon so the
|
|
93
|
+
* precedence (driveUrl launch+own → CDP attach → none) and the storageState/injectConnect plumbing
|
|
94
|
+
* live in ONE place. `onNavigateError` is the entrypoint's own cleanup (close the bridge/shared server)
|
|
95
|
+
* so a failed launch never leaks a WS port. A past divergence between the two paths let daemon mode
|
|
96
|
+
* run with a different setup — this removes that risk.
|
|
97
|
+
*/
|
|
98
|
+
export async function resolveRealInput(options, onNavigateError, onNetworkDetail) {
|
|
99
|
+
const driveUrl = options.driveUrl;
|
|
100
|
+
if (driveUrl !== undefined && driveUrl.length > 0) {
|
|
101
|
+
const headless = options.headless ?? true;
|
|
102
|
+
// The one place that knows. Everything downstream reads it rather than re-deriving it, and a
|
|
103
|
+
// daemon that launches nothing keeps the default (ATTACHED) rather than guessing.
|
|
104
|
+
setBrowserMode(headless ? BrowserMode.HEADLESS : BrowserMode.HEADED);
|
|
105
|
+
const injectConnect = options.injectConnect;
|
|
106
|
+
const storageState = options.storageState;
|
|
107
|
+
const factory = options.realInputFactory ??
|
|
108
|
+
((opts) => new LaunchedRealInputProvider({
|
|
109
|
+
driveUrl: opts.driveUrl,
|
|
110
|
+
headless: opts.headless,
|
|
111
|
+
...(injectConnect !== undefined ? { injectConnect } : {}),
|
|
112
|
+
...(storageState !== undefined ? { storageState } : {}),
|
|
113
|
+
...(onNetworkDetail !== undefined ? { onNetworkDetail } : {}),
|
|
114
|
+
}));
|
|
115
|
+
const launched = factory({ driveUrl, headless });
|
|
116
|
+
try {
|
|
117
|
+
await launched.navigate();
|
|
118
|
+
}
|
|
119
|
+
catch (error) {
|
|
120
|
+
await onNavigateError(); // no leaked WS port on a failed start
|
|
121
|
+
throw error;
|
|
122
|
+
}
|
|
123
|
+
return { realInput: launched, owned: launched };
|
|
124
|
+
}
|
|
125
|
+
const cdpUrl = options.cdpUrl ?? process.env[ReticleEnv.CDP_URL];
|
|
126
|
+
if (cdpUrl !== undefined && cdpUrl.length > 0) {
|
|
127
|
+
// Same network sink as the launched path. Whether Reticle opened the browser or attached to one
|
|
128
|
+
// someone else opened has no bearing on whether it can read that browser's network.
|
|
129
|
+
const cdp = new CdpRealInputProvider({
|
|
130
|
+
cdpUrl,
|
|
131
|
+
...(onNetworkDetail !== undefined ? { onNetworkDetail } : {}),
|
|
132
|
+
});
|
|
133
|
+
return { realInput: cdp, owned: cdp };
|
|
134
|
+
}
|
|
135
|
+
return {};
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* The SDK-upgrade sentence for the package.json of the project the page announced, evaluated at
|
|
139
|
+
* each HELLO so a just-edited manifest is what we name. The daemon's cwd only when that project's
|
|
140
|
+
* directory is unknown, and the framework-neutral sensor when that is not an app either (#1135).
|
|
141
|
+
*/
|
|
142
|
+
export function sdkFixForProject(projectId) {
|
|
143
|
+
return sdkFixForDirectory(SERVER_VERSION, projectDirectoryFor(projectId) ?? process.cwd());
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Resolve a session's artifact root, from everything this machine knows about where projects live.
|
|
147
|
+
*
|
|
148
|
+
* Built once per daemon and closed over by every tool call. The two sources are read lazily and
|
|
149
|
+
* cheaply on each call rather than snapshotted at startup: `init` can run in another terminal while
|
|
150
|
+
* this daemon is up, and a resolution that used a startup snapshot would keep answering with a map
|
|
151
|
+
* from before the project the agent is now driving existed.
|
|
152
|
+
*/
|
|
153
|
+
/**
|
|
154
|
+
* Every `.reticle` root on this machine that sync should consider, from the same two sources the
|
|
155
|
+
* artifact resolver uses.
|
|
156
|
+
*
|
|
157
|
+
* Read on every call rather than snapshotted, for the same reason: `reticle link` can run in
|
|
158
|
+
* another terminal while this daemon is up, and a startup snapshot would keep that repo silent
|
|
159
|
+
* until somebody restarted a process they have no reason to suspect.
|
|
160
|
+
*
|
|
161
|
+
* Returns directories that MIGHT be linked; the caller resolves each and skips the ones that are
|
|
162
|
+
* not. Deciding that here would mean reading every cloud.json on every tick.
|
|
163
|
+
*/
|
|
164
|
+
export function knownProjectRoots() {
|
|
165
|
+
return [...new Set(knownProjectCandidates().map((c) => join(c.directory, ReticleDir.ROOT)))];
|
|
166
|
+
}
|
|
167
|
+
/** This project's platform credential (stored, else the env key), as the env the platform readers take. */
|
|
168
|
+
export const platformEnvFor = (root) => platformEnvPort(createNodeFileSystem(), root ?? join(process.cwd(), ReticleDir.ROOT), homedir(), process.env);
|
|
169
|
+
export const loadHarnessConfig = async (root) => fetchPlatformConfig(await platformEnvFor(root)());
|
package/dist/status-payload.d.ts
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
* answering requests. See takeVersionSkewOnto in command/version/version-nudge.ts.
|
|
8
8
|
*/
|
|
9
9
|
import type { SessionInfo } from './portal/session/session-info.js';
|
|
10
|
+
import { instrumentationOf, type InstrumentedTab } from './portal/session/recorded-gaps.js';
|
|
10
11
|
interface StatusPayload {
|
|
11
12
|
running: true;
|
|
12
13
|
version: string;
|
|
@@ -30,12 +31,23 @@ interface StatusPayload {
|
|
|
30
31
|
whyLead?: string;
|
|
31
32
|
/** Port of the verify HTTP endpoint this daemon serves — present only when started with `--http`. */
|
|
32
33
|
verifyPort?: number;
|
|
34
|
+
/**
|
|
35
|
+
* Each connected tab's instrumentation coverage and, once a verdict recorded a gap, the prompt for
|
|
36
|
+
* a coding agent — what `reticle doctor` prints as its coverage line.
|
|
37
|
+
*/
|
|
38
|
+
coverage?: TabCoverage[];
|
|
33
39
|
}
|
|
40
|
+
type TabCoverage = {
|
|
41
|
+
sessionId: string;
|
|
42
|
+
url?: string;
|
|
43
|
+
} & ReturnType<typeof instrumentationOf>;
|
|
34
44
|
export declare function statusPayload(sessionCount: number, sessions: SessionInfo[],
|
|
35
45
|
/** The no-session diagnosis, injected so this stays pure and the port probe stays off this path. */
|
|
36
46
|
why?: string, verifyPort?: number,
|
|
37
47
|
/** The short rendering of the same diagnosis. Absent on a daemon that has no provider wired. */
|
|
38
|
-
whyLead?: string
|
|
48
|
+
whyLead?: string,
|
|
49
|
+
/** The live tabs, for their coverage. */
|
|
50
|
+
tabs?: readonly InstrumentedTab[]): StatusPayload;
|
|
39
51
|
/**
|
|
40
52
|
* Why `serve --http` cannot claim success against an already-running daemon — or undefined when
|
|
41
53
|
* that daemon already serves the verify HTTP endpoint on the wanted port.
|
package/dist/status-payload.js
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import { CONTRACT_FINGERPRINT } from '@reticlehq/core';
|
|
2
2
|
import { SERVER_VERSION } from './command/version/identity/server-version.js';
|
|
3
|
+
import { instrumentationOf } from './portal/session/recorded-gaps.js';
|
|
3
4
|
export function statusPayload(sessionCount, sessions,
|
|
4
5
|
/** The no-session diagnosis, injected so this stays pure and the port probe stays off this path. */
|
|
5
6
|
why, verifyPort,
|
|
6
7
|
/** The short rendering of the same diagnosis. Absent on a daemon that has no provider wired. */
|
|
7
|
-
whyLead
|
|
8
|
+
whyLead,
|
|
9
|
+
/** The live tabs, for their coverage. */
|
|
10
|
+
tabs = []) {
|
|
8
11
|
return {
|
|
9
12
|
running: true,
|
|
10
13
|
version: SERVER_VERSION,
|
|
@@ -16,6 +19,15 @@ whyLead) {
|
|
|
16
19
|
...(0 === sessionCount && why !== undefined ? { why } : {}),
|
|
17
20
|
...(0 === sessionCount && whyLead !== undefined ? { whyLead } : {}),
|
|
18
21
|
...(verifyPort === undefined ? {} : { verifyPort }),
|
|
22
|
+
...(0 === tabs.length
|
|
23
|
+
? {}
|
|
24
|
+
: {
|
|
25
|
+
coverage: tabs.map((tab) => ({
|
|
26
|
+
sessionId: tab.id,
|
|
27
|
+
...(tab.url === undefined ? {} : { url: tab.url }),
|
|
28
|
+
...instrumentationOf(tab),
|
|
29
|
+
})),
|
|
30
|
+
}),
|
|
19
31
|
};
|
|
20
32
|
}
|
|
21
33
|
/**
|
|
@@ -5,6 +5,7 @@ import { getSessionMetrics } from '../telemetry/session-metrics.js';
|
|
|
5
5
|
import { agentPeerSkew, PEER_VERSION_PARAM, PEER_CONTRACT_PARAM, } from '../command/version/peer-announce.js';
|
|
6
6
|
import { log } from '../log.js';
|
|
7
7
|
import { isLoopbackHost, isLocalWebOrigin, isLoopbackPeer, requestToken, tokensMatch, } from '../portal/bridge/token-auth.js';
|
|
8
|
+
import { clientDirectoryFromPeer, runWithClientDirectory } from '../hooks/client-directory.js';
|
|
8
9
|
import { LOOPBACK_IDLE_MS } from './loopback-agent.js';
|
|
9
10
|
/**
|
|
10
11
|
* Creates a shared HTTP server that handles both the WebSocket bridge (browser SDK) and the
|
|
@@ -212,7 +213,12 @@ export function createSharedServer(options = {}) {
|
|
|
212
213
|
res.end('session not found');
|
|
213
214
|
return;
|
|
214
215
|
}
|
|
215
|
-
|
|
216
|
+
const clientDirectory = clientDirectoryFromPeer(isLoopbackPeer(req.socket.remoteAddress), req.headers);
|
|
217
|
+
const deliver = () => transport.handlePostMessage(req, res);
|
|
218
|
+
const posted = clientDirectory === undefined
|
|
219
|
+
? deliver()
|
|
220
|
+
: runWithClientDirectory(clientDirectory, deliver);
|
|
221
|
+
posted.catch((err) => {
|
|
216
222
|
const message = err instanceof Error ? err.message : String(err);
|
|
217
223
|
log('mcp_message_error', { error: message });
|
|
218
224
|
});
|
|
@@ -71,6 +71,7 @@ export declare function describeAttachState(state: AttachState): string | undefi
|
|
|
71
71
|
/** What `reticle status` reports about the client side of the install. */
|
|
72
72
|
interface AttachStatusFields {
|
|
73
73
|
mcpClient: AttachState;
|
|
74
|
+
mcpClientSaid: string;
|
|
74
75
|
mcpClientAction?: string;
|
|
75
76
|
}
|
|
76
77
|
/**
|
|
@@ -169,6 +169,13 @@ export function describeAttachState(state) {
|
|
|
169
169
|
return NEVER_CALLED_ACTION;
|
|
170
170
|
return undefined;
|
|
171
171
|
}
|
|
172
|
+
/** Each state in words, for a person: the state names are the record's, never the reader's. */
|
|
173
|
+
const ATTACH_STATE_SAID = {
|
|
174
|
+
[AttachState.ENUMERATED]: "✓ your agent has read and used Reticle's tools",
|
|
175
|
+
[AttachState.NEVER_CALLED]: "your agent read Reticle's tools and has not called one yet",
|
|
176
|
+
[AttachState.NEVER_ENUMERATED]: '✗ your agent started Reticle and never read its tools',
|
|
177
|
+
[AttachState.NEVER_ATTACHED]: 'no agent has started Reticle on this port yet',
|
|
178
|
+
};
|
|
172
179
|
/**
|
|
173
180
|
* The client-side fields for one `status` run.
|
|
174
181
|
*
|
|
@@ -181,5 +188,9 @@ export function attachStatusFields(stateDir, port) {
|
|
|
181
188
|
const action = describeAttachState(state);
|
|
182
189
|
// OMITTED rather than undefined: `exactOptionalPropertyTypes` is on, and an absent key is also
|
|
183
190
|
// what keeps the healthy line to one fact.
|
|
184
|
-
return {
|
|
191
|
+
return {
|
|
192
|
+
mcpClient: state,
|
|
193
|
+
mcpClientSaid: ATTACH_STATE_SAID[state],
|
|
194
|
+
...(action === undefined ? {} : { mcpClientAction: action }),
|
|
195
|
+
};
|
|
185
196
|
}
|
|
@@ -25,6 +25,8 @@ export declare const RECONNECT_INITIALIZE_ID = "__reticle_proxy_reinit";
|
|
|
25
25
|
export declare class PendingRequests {
|
|
26
26
|
#private;
|
|
27
27
|
observeOutbound(line: string): void;
|
|
28
|
+
/** Whether this unanswered request asked for a Harness drive. */
|
|
29
|
+
isDrive(id: unknown): boolean;
|
|
28
30
|
observeInbound(line: string): void;
|
|
29
31
|
get unanswered(): string[];
|
|
30
32
|
/**
|
|
@@ -34,6 +36,8 @@ export declare class PendingRequests {
|
|
|
34
36
|
take(id: unknown): boolean;
|
|
35
37
|
/** Take every unanswered id and forget them, so the same request is failed at most once. */
|
|
36
38
|
drain(): string[];
|
|
39
|
+
/** Forget which requests were drives, once their replies are written. */
|
|
40
|
+
clearDrives(): void;
|
|
37
41
|
}
|
|
38
42
|
/**
|
|
39
43
|
* JSON-RPC errors for every request that was in flight when the stream died.
|
|
@@ -32,6 +32,7 @@ export { accountProxyLogWrite, proxyLog, proxyLogPath, PROXY_LOG_CHECK_BYTES, re
|
|
|
32
32
|
import { proxyLog } from './proxy/proxy-log.js';
|
|
33
33
|
import { OutageReason, OutageStage, reportMcpOutage } from './faults/mcp-outage.js';
|
|
34
34
|
import { postToSession } from './proxy/mcp-post-transport.js';
|
|
35
|
+
import { MSG_DRIVE_MAY_BE_RUNNING, isHarnessDriveCall } from './proxy/drive-calls.js';
|
|
35
36
|
import { reconnectDelayMs } from './proxy/proxy-backoff.js';
|
|
36
37
|
import { PROXY_IDLE_EXIT_EVENT, ProxyIdleExit, resolveProxyIdleExitMs } from './proxy-idle-exit.js';
|
|
37
38
|
export { reconnectDelayMs } from './proxy/proxy-backoff.js';
|
|
@@ -84,11 +85,20 @@ const INITIALIZED_METHOD = 'notifications/initialized';
|
|
|
84
85
|
*/
|
|
85
86
|
export class PendingRequests {
|
|
86
87
|
#ids = new Set();
|
|
88
|
+
/** The pending requests that start or poll a Harness drive, which outlives a lost connection. */
|
|
89
|
+
#drives = new Set();
|
|
87
90
|
observeOutbound(line) {
|
|
88
91
|
const msg = parseJsonRpc(line);
|
|
89
92
|
if (null === msg || msg.id === undefined || msg.method === undefined)
|
|
90
93
|
return;
|
|
91
|
-
|
|
94
|
+
const id = JSON.stringify(msg.id);
|
|
95
|
+
this.#ids.add(id);
|
|
96
|
+
if (isHarnessDriveCall(msg))
|
|
97
|
+
this.#drives.add(id);
|
|
98
|
+
}
|
|
99
|
+
/** Whether this unanswered request asked for a Harness drive. */
|
|
100
|
+
isDrive(id) {
|
|
101
|
+
return this.#drives.has(JSON.stringify(id));
|
|
92
102
|
}
|
|
93
103
|
observeInbound(line) {
|
|
94
104
|
const msg = parseJsonRpc(line);
|
|
@@ -104,6 +114,7 @@ export class PendingRequests {
|
|
|
104
114
|
* a duplicate response to one id is a protocol violation, not a belt-and-braces retry.
|
|
105
115
|
*/
|
|
106
116
|
take(id) {
|
|
117
|
+
this.#drives.delete(JSON.stringify(id));
|
|
107
118
|
return this.#ids.delete(JSON.stringify(id));
|
|
108
119
|
}
|
|
109
120
|
/** Take every unanswered id and forget them, so the same request is failed at most once. */
|
|
@@ -112,6 +123,10 @@ export class PendingRequests {
|
|
|
112
123
|
this.#ids.clear();
|
|
113
124
|
return ids;
|
|
114
125
|
}
|
|
126
|
+
/** Forget which requests were drives, once their replies are written. */
|
|
127
|
+
clearDrives() {
|
|
128
|
+
this.#drives.clear();
|
|
129
|
+
}
|
|
115
130
|
}
|
|
116
131
|
/**
|
|
117
132
|
* JSON-RPC errors for every request that was in flight when the stream died.
|
|
@@ -126,9 +141,12 @@ export class PendingRequests {
|
|
|
126
141
|
* with the MCP server still perfectly alive. An agent cannot tell that apart from "still working".
|
|
127
142
|
*/
|
|
128
143
|
export function streamLossReplies(pending, reason, nextStep) {
|
|
129
|
-
|
|
130
|
-
.
|
|
131
|
-
|
|
144
|
+
const replies = pending.drain().map((id) => {
|
|
145
|
+
const parsed = JSON.parse(id);
|
|
146
|
+
return transportLossReply(parsed, reason, nextStep, pending.isDrive(parsed));
|
|
147
|
+
});
|
|
148
|
+
pending.clearDrives();
|
|
149
|
+
return replies;
|
|
132
150
|
}
|
|
133
151
|
/**
|
|
134
152
|
* -32001: a server-defined error. Not -32603 (internal): nothing went wrong INSIDE the call, the
|
|
@@ -142,14 +160,16 @@ const TRANSPORT_LOSS_CODE = -32001;
|
|
|
142
160
|
* `nextStep` is appended when the caller knows one. Without it this reply describes a condition and
|
|
143
161
|
* stops there, which is all a first-run user got out of their first ever tool call.
|
|
144
162
|
*/
|
|
145
|
-
function transportLossReply(id, reason, nextStep) {
|
|
163
|
+
function transportLossReply(id, reason, nextStep, drive = false) {
|
|
146
164
|
return JSON.stringify({
|
|
147
165
|
jsonrpc: '2.0',
|
|
148
166
|
id,
|
|
149
167
|
error: {
|
|
150
168
|
code: TRANSPORT_LOSS_CODE,
|
|
151
|
-
message:
|
|
152
|
-
|
|
169
|
+
message: (drive
|
|
170
|
+
? `the daemon connection dropped (${reason}) before this call was answered. ${MSG_DRIVE_MAY_BE_RUNNING}`
|
|
171
|
+
: `the daemon connection dropped (${reason}) before this call was answered — it did NOT ` +
|
|
172
|
+
'complete. Reticle is recovering the connection; retry if the action is safe to repeat.') +
|
|
153
173
|
(nextStep === undefined ? '' : ` ${nextStep}`),
|
|
154
174
|
},
|
|
155
175
|
});
|
|
@@ -490,6 +510,7 @@ onUsableSession = () => undefined) {
|
|
|
490
510
|
if (null === failure)
|
|
491
511
|
return;
|
|
492
512
|
const msg = parseJsonRpc(line);
|
|
513
|
+
const drive = null !== msg && pending.isDrive(msg.id);
|
|
493
514
|
if (null === msg || msg.id === undefined || !pending.take(msg.id))
|
|
494
515
|
return;
|
|
495
516
|
// No outage is reported here, deliberately. A POST leg that died while the SSE stream is
|
|
@@ -503,7 +524,7 @@ onUsableSession = () => undefined) {
|
|
|
503
524
|
reason: failure.reason,
|
|
504
525
|
note: 'the stream is still up, so nothing else would ever have answered this call',
|
|
505
526
|
});
|
|
506
|
-
emit(transportLossReply(msg.id, failure.reason));
|
|
527
|
+
emit(transportLossReply(msg.id, failure.reason, undefined, drive));
|
|
507
528
|
});
|
|
508
529
|
};
|
|
509
530
|
function onSseEvent(event, data, p) {
|
|
@@ -3,6 +3,7 @@ import { z } from 'zod';
|
|
|
3
3
|
import { type ToolDeps } from '../tools/tools.js';
|
|
4
4
|
import type { ToolDef } from '../tools/tools.js';
|
|
5
5
|
import { type ToolSurface } from '../tools/tool-surface.js';
|
|
6
|
+
import { type ToolCall } from '../tools/tool-kit.js';
|
|
6
7
|
import { type InstructionState } from './server-instructions.js';
|
|
7
8
|
/** The JSON-RPC method the SDK registers its tool dispatcher under. */
|
|
8
9
|
export declare const CALL_TOOL_METHOD = "tools/call";
|
|
@@ -36,6 +37,28 @@ export { firstSentence } from '../tools/first-sentence.js';
|
|
|
36
37
|
* form with `RETICLE_ENCODING=pretty`; `RETICLE_ENCODING=toon` is the even-denser tabular encoding.
|
|
37
38
|
*/
|
|
38
39
|
export declare function encodeResult(result: unknown, encoding: string): string;
|
|
40
|
+
/** The slice of the SDK's per-request `extra` a tool call reads: cancellation and progress. */
|
|
41
|
+
interface McpRequestExtra {
|
|
42
|
+
signal?: AbortSignal;
|
|
43
|
+
_meta?: {
|
|
44
|
+
progressToken?: string | number;
|
|
45
|
+
};
|
|
46
|
+
sendNotification?: (notification: {
|
|
47
|
+
method: typeof PROGRESS_NOTIFICATION;
|
|
48
|
+
params: {
|
|
49
|
+
progressToken: string | number;
|
|
50
|
+
progress: number;
|
|
51
|
+
message: string;
|
|
52
|
+
};
|
|
53
|
+
}) => Promise<void>;
|
|
54
|
+
}
|
|
55
|
+
declare const PROGRESS_NOTIFICATION = "notifications/progress";
|
|
56
|
+
/**
|
|
57
|
+
* The request's cancellation and, when the client sent a progress token, a progress reporter. A
|
|
58
|
+
* long call (a Harness drive's wait) reports each step, so a client that resets its timeout on
|
|
59
|
+
* progress keeps waiting instead of abandoning a call that is working.
|
|
60
|
+
*/
|
|
61
|
+
export declare function toolCallOf(extra: McpRequestExtra | undefined): ToolCall;
|
|
39
62
|
/**
|
|
40
63
|
* The tools a profile advertises directly.
|
|
41
64
|
*
|
package/dist/surface/mcp/mcp.js
CHANGED
|
@@ -38,6 +38,7 @@ import { SERVER_VERSION } from '../../command/version/identity/server-version.js
|
|
|
38
38
|
import { setMcpClientNameHook } from '../../telemetry/feedback-context.js';
|
|
39
39
|
import { getSessionMetrics } from '../../telemetry/session-metrics.js';
|
|
40
40
|
import { reportMcpConnected } from '../../telemetry/mcp-connection.js';
|
|
41
|
+
import { noteAgentAttached, noteAgentDetached, runAsAgent } from '../../hooks/coding-agents.js';
|
|
41
42
|
import { parsePredicate } from '@reticlehq/engine/question/predicate/predicate-parse.js';
|
|
42
43
|
/**
|
|
43
44
|
* Merge the runtime-spliced envelope into a tool's declared outputSchema so structuredContent
|
|
@@ -192,6 +193,27 @@ export function encodeResult(result, encoding) {
|
|
|
192
193
|
}
|
|
193
194
|
return encoding === PRETTY_VALUE ? JSON.stringify(result, null, 2) : JSON.stringify(result);
|
|
194
195
|
}
|
|
196
|
+
const PROGRESS_NOTIFICATION = 'notifications/progress';
|
|
197
|
+
/**
|
|
198
|
+
* The request's cancellation and, when the client sent a progress token, a progress reporter. A
|
|
199
|
+
* long call (a Harness drive's wait) reports each step, so a client that resets its timeout on
|
|
200
|
+
* progress keeps waiting instead of abandoning a call that is working.
|
|
201
|
+
*/
|
|
202
|
+
export function toolCallOf(extra) {
|
|
203
|
+
const token = extra?._meta?.progressToken;
|
|
204
|
+
const send = extra?.sendNotification;
|
|
205
|
+
return {
|
|
206
|
+
...(extra?.signal === undefined ? {} : { signal: extra.signal }),
|
|
207
|
+
...(token === undefined || send === undefined
|
|
208
|
+
? {}
|
|
209
|
+
: {
|
|
210
|
+
progress: (progress, message) => void send({
|
|
211
|
+
method: PROGRESS_NOTIFICATION,
|
|
212
|
+
params: { progressToken: token, progress, message },
|
|
213
|
+
}).catch(() => undefined),
|
|
214
|
+
}),
|
|
215
|
+
};
|
|
216
|
+
}
|
|
195
217
|
/**
|
|
196
218
|
* The tools a profile advertises directly.
|
|
197
219
|
*
|
|
@@ -430,8 +452,10 @@ function installUnadvertisedToolHelp(server, advertised, known) {
|
|
|
430
452
|
return original(asCallOf(request, moved.tool, moved.action), extra);
|
|
431
453
|
}
|
|
432
454
|
const help = name === undefined ? undefined : unadvertisedToolHelp(name, advertised, known);
|
|
455
|
+
// A failed RESULT, not a JSON-RPC error: a client that reads only `result` rendered the error
|
|
456
|
+
// as an empty success, and the agent believed `reticle_flow_save` had saved its flow.
|
|
433
457
|
if (help !== undefined)
|
|
434
|
-
|
|
458
|
+
return { content: [{ type: 'text', text: help }], isError: true };
|
|
435
459
|
return original(request, extra);
|
|
436
460
|
});
|
|
437
461
|
}
|
|
@@ -537,12 +561,15 @@ tools = tableForSurface(profile)) {
|
|
|
537
561
|
if (info?.name === undefined)
|
|
538
562
|
return;
|
|
539
563
|
getSessionMetrics().recordClient(info.name, info.version);
|
|
564
|
+
// So the HUD can say which agent is connected, and credit a note to the one that read it.
|
|
565
|
+
noteAgentAttached(deps.attachId, info.name);
|
|
540
566
|
// The one signal that separates "Reticle is running" from "somebody is USING it", reported from
|
|
541
567
|
// the first moment it can carry WHO. It used to fire from the SSE `connect()` resolution, which
|
|
542
568
|
// happens before the handshake — so every connect row was anonymous, and the field meant to say
|
|
543
569
|
// which agent client converts best was empty on every event ever sent.
|
|
544
|
-
reportMcpConnected(info.name);
|
|
570
|
+
void runAsAgent(deps.attachId, () => Promise.resolve(reportMcpConnected(info.name)));
|
|
545
571
|
};
|
|
572
|
+
server.server.onclose = () => noteAgentDetached(deps.attachId);
|
|
546
573
|
// Which agent is on the other end, for a feedback report. Registered as a lazy hook rather than
|
|
547
574
|
// read here: the handshake has not happened yet at construction time, and a report filed twenty
|
|
548
575
|
// tool calls later is exactly when we want the answer.
|
|
@@ -624,9 +651,12 @@ tools = tableForSurface(profile)) {
|
|
|
624
651
|
// clients. This removes the single largest remaining slice of the per-request tax (~36% of the
|
|
625
652
|
// hybrid payload) with no loss the agent can observe.
|
|
626
653
|
const config = advertisedConfig(tool, advertised, profile);
|
|
627
|
-
registerTool(tool.name, config, async (args) => {
|
|
654
|
+
registerTool(tool.name, config, async (args, extra) => {
|
|
628
655
|
try {
|
|
629
|
-
|
|
656
|
+
// Inside the caller's connection, so the telemetry this call emits after its handler (the
|
|
657
|
+
// verdict, a defect, a refusal) is credited to the agent that made it, not to whichever
|
|
658
|
+
// agent is attached.
|
|
659
|
+
const result = await runAsAgent(deps.attachId, () => runTool(tool, deps, args, toolCallOf(extra)));
|
|
630
660
|
// A tool this codebase did not write may not hand the agent a verdict.
|
|
631
661
|
//
|
|
632
662
|
// Only reached for a tool absent from the first-party table, so the shipped surface pays a
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/** A `tools/call` of reticle_verify explore, directly or through the reticle_run hatch. */
|
|
2
|
+
export declare function isHarnessDriveCall(msg: {
|
|
3
|
+
method?: unknown;
|
|
4
|
+
params?: unknown;
|
|
5
|
+
}): boolean;
|
|
6
|
+
/**
|
|
7
|
+
* A drive lives in the daemon, not in the call: a lost connection does not end it, and retrying the
|
|
8
|
+
* call as if it had not run pays for a second drive.
|
|
9
|
+
*/
|
|
10
|
+
export declare const MSG_DRIVE_MAY_BE_RUNNING: string;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/** Which proxied calls are Harness drives, and what to tell an agent whose drive call was lost. */
|
|
2
|
+
import { ReticleTool } from '@reticlehq/core';
|
|
3
|
+
const TOOLS_CALL = 'tools/call';
|
|
4
|
+
const EXPLORE_ACTION = 'explore';
|
|
5
|
+
/** A `tools/call` of reticle_verify explore, directly or through the reticle_run hatch. */
|
|
6
|
+
export function isHarnessDriveCall(msg) {
|
|
7
|
+
if (TOOLS_CALL !== msg.method)
|
|
8
|
+
return false;
|
|
9
|
+
const params = (msg.params ?? {});
|
|
10
|
+
const args = (params.arguments ?? {});
|
|
11
|
+
if (ReticleTool.VERIFY_EXPLORE === params.name)
|
|
12
|
+
return true;
|
|
13
|
+
if (ReticleTool.VERIFY === params.name)
|
|
14
|
+
return EXPLORE_ACTION === args['action'];
|
|
15
|
+
if (ReticleTool.RUN !== params.name)
|
|
16
|
+
return false;
|
|
17
|
+
const inner = (args['args'] ?? {});
|
|
18
|
+
return (ReticleTool.VERIFY_EXPLORE === args['tool'] ||
|
|
19
|
+
(ReticleTool.VERIFY === args['tool'] && EXPLORE_ACTION === inner['action']));
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* A drive lives in the daemon, not in the call: a lost connection does not end it, and retrying the
|
|
23
|
+
* call as if it had not run pays for a second drive.
|
|
24
|
+
*/
|
|
25
|
+
export const MSG_DRIVE_MAY_BE_RUNNING = `The Harness drive this call started or polled may still be running in the daemon. Once ` +
|
|
26
|
+
`Reticle reconnects, call ${ReticleTool.VERIFY} {action:"explore"} with no runId to get the ` +
|
|
27
|
+
`running drive back (it will not start a second), then poll it by runId.`;
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
* saying honestly that it never arrived — and the file it came from is about the SSE stream.
|
|
8
8
|
*/
|
|
9
9
|
import * as http from 'node:http';
|
|
10
|
+
import { MCP_CLIENT_DIRECTORY_HEADER } from '@reticlehq/core';
|
|
10
11
|
import { log } from '../../../log.js';
|
|
11
12
|
import { getSessionMetrics } from '../../../telemetry/session-metrics.js';
|
|
12
13
|
import { reconnectDelayMs } from './proxy-backoff.js';
|
|
@@ -47,6 +48,10 @@ export function postToSession(url, body, request = (options, callback) => http.r
|
|
|
47
48
|
headers: {
|
|
48
49
|
'Content-Type': 'application/json',
|
|
49
50
|
'Content-Length': bodyBuf.byteLength,
|
|
51
|
+
// The project this proxy was started in. The daemon serves every project; without this
|
|
52
|
+
// it can only see the directory it itself started in. Percent-encoded: a cwd such as
|
|
53
|
+
// `/work/项目` is not a legal header value, and Node throws before the request is sent.
|
|
54
|
+
[MCP_CLIENT_DIRECTORY_HEADER]: encodeURIComponent(process.cwd()),
|
|
50
55
|
},
|
|
51
56
|
};
|
|
52
57
|
// A keep-alive socket carries historical bytes; retry safety depends on this request's delta.
|