@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
|
@@ -45,7 +45,7 @@ export interface PlatformModelConfig {
|
|
|
45
45
|
*/
|
|
46
46
|
providerReady: boolean;
|
|
47
47
|
/**
|
|
48
|
-
*
|
|
48
|
+
* Credits used and held this 30 days, and when the grant ends (`endsAt`, epoch ms) when
|
|
49
49
|
* the platform says. Absent when the plan is unbounded or the API is older.
|
|
50
50
|
*/
|
|
51
51
|
credits?: Credits & {
|
|
@@ -59,8 +59,6 @@ export interface PlatformModelConfig {
|
|
|
59
59
|
* the API's origin 404s. Absent from an older platform.
|
|
60
60
|
*/
|
|
61
61
|
planUrl?: string;
|
|
62
|
-
/** The platform's coverage gate (`harnessUnlocked`, `coverageScore`, `harnessLock`), when it sent one. */
|
|
63
|
-
gate?: PlatformGate;
|
|
64
62
|
/** The plan in force (`plan`), for the HUD's account menu. */
|
|
65
63
|
plan?: PlatformPlan;
|
|
66
64
|
/** Harness runs the platform holds for this project (`harnessRuns.total`). */
|
|
@@ -74,13 +72,6 @@ export interface PlatformPlan {
|
|
|
74
72
|
daysLeft?: number;
|
|
75
73
|
seats?: number;
|
|
76
74
|
}
|
|
77
|
-
/** The platform's Harness coverage gate, as the HUD is pushed it. */
|
|
78
|
-
export interface PlatformGate {
|
|
79
|
-
unlocked: boolean;
|
|
80
|
-
percent?: number;
|
|
81
|
-
reason?: string;
|
|
82
|
-
prompt?: string;
|
|
83
|
-
}
|
|
84
75
|
/** A GET, narrowed to what this file uses, so a test can answer it without a network. */
|
|
85
76
|
export type ConfigFetch = (url: string, init: {
|
|
86
77
|
method: string;
|
|
@@ -66,24 +66,6 @@ function webUrl(value, key) {
|
|
|
66
66
|
return {};
|
|
67
67
|
}
|
|
68
68
|
}
|
|
69
|
-
/** The gate out of `/v1/model/config`, or undefined from a platform that does not send one. */
|
|
70
|
-
function gateOf(record) {
|
|
71
|
-
const unlocked = record['harnessUnlocked'];
|
|
72
|
-
if ('boolean' !== typeof unlocked)
|
|
73
|
-
return undefined;
|
|
74
|
-
const score = record['coverageScore'];
|
|
75
|
-
const lock = record['harnessLock'];
|
|
76
|
-
const lockRecord = 'object' === typeof lock && null !== lock ? lock : {};
|
|
77
|
-
const reason = lockRecord['reason'];
|
|
78
|
-
const prompt = lockRecord['prompt'];
|
|
79
|
-
return {
|
|
80
|
-
unlocked,
|
|
81
|
-
// Rounded down, as core's rule is: a locked app never shows 80%.
|
|
82
|
-
...('number' === typeof score ? { percent: Math.floor(score * 100 + 1e-9) } : {}),
|
|
83
|
-
...('string' === typeof reason ? { reason } : {}),
|
|
84
|
-
...('string' === typeof prompt ? { prompt } : {}),
|
|
85
|
-
};
|
|
86
|
-
}
|
|
87
69
|
/** When the grant ends, epoch ms, from an ISO date or a number. Anything else: not said. */
|
|
88
70
|
function endsAtOf(value) {
|
|
89
71
|
const at = 'number' === typeof value ? value : 'string' === typeof value ? Date.parse(value) : NaN;
|
|
@@ -121,7 +103,6 @@ function parse(body) {
|
|
|
121
103
|
const kind = 'object' === typeof credits && null !== credits
|
|
122
104
|
? Object.values(CreditKind).find((k) => k === credits['kind'])
|
|
123
105
|
: undefined;
|
|
124
|
-
const gate = gateOf(record);
|
|
125
106
|
const endsAt = endsAtOf('object' === typeof credits && null !== credits
|
|
126
107
|
? credits['endsAt']
|
|
127
108
|
: undefined);
|
|
@@ -130,7 +111,6 @@ function parse(body) {
|
|
|
130
111
|
harnessEnabled: true === enabled,
|
|
131
112
|
harnessEntitled: 'boolean' === typeof entitled ? entitled : true,
|
|
132
113
|
providerReady: 'boolean' === typeof ready ? ready : true,
|
|
133
|
-
...(gate === undefined ? {} : { gate }),
|
|
134
114
|
...hudFieldsOf(record),
|
|
135
115
|
...webUrl(record['planUrl'], 'planUrl'),
|
|
136
116
|
...('number' === typeof used && 'number' === typeof limit
|
|
@@ -37,20 +37,8 @@ declare const LicensePayloadSchema: z.ZodObject<{
|
|
|
37
37
|
org: z.ZodString;
|
|
38
38
|
plan: z.ZodString;
|
|
39
39
|
exp: z.ZodNumber;
|
|
40
|
-
features: z.ZodOptional<z.ZodArray<z.ZodString
|
|
41
|
-
},
|
|
42
|
-
plan: string;
|
|
43
|
-
org: string;
|
|
44
|
-
lid: string;
|
|
45
|
-
exp: number;
|
|
46
|
-
features?: string[] | undefined;
|
|
47
|
-
}, {
|
|
48
|
-
plan: string;
|
|
49
|
-
org: string;
|
|
50
|
-
lid: string;
|
|
51
|
-
exp: number;
|
|
52
|
-
features?: string[] | undefined;
|
|
53
|
-
}>;
|
|
40
|
+
features: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
41
|
+
}, z.core.$strip>;
|
|
54
42
|
export type LicensePayload = z.infer<typeof LicensePayloadSchema>;
|
|
55
43
|
type LicenseCheck = {
|
|
56
44
|
status: typeof LicenseStatus.VALID;
|
|
@@ -4,10 +4,15 @@ export interface ShotOptions {
|
|
|
4
4
|
step?: string;
|
|
5
5
|
verdict?: boolean;
|
|
6
6
|
}
|
|
7
|
-
/**
|
|
7
|
+
/**
|
|
8
|
+
* What a tool result carries: where the picture is and how it was taken, or why there is none.
|
|
9
|
+
*
|
|
10
|
+
* `pending: true` means the path is reserved and the capture has started, but the file may not yet be on disk. This happens on the fast path when a prior capture on the same tab proved the source works: the step does not wait for the write to land. Copy the file only after a short delay, or poll until it appears.
|
|
11
|
+
*/
|
|
8
12
|
export type ScreenshotField = {
|
|
9
13
|
path: string;
|
|
10
14
|
source: ScreenshotSource;
|
|
15
|
+
pending?: true;
|
|
11
16
|
} | {
|
|
12
17
|
error: string;
|
|
13
18
|
};
|
|
@@ -29,3 +34,30 @@ export declare function jpegSize(bytes: Uint8Array): {
|
|
|
29
34
|
export declare function takeStepShot(deps: ToolDeps, sessionId: string, tool: string, opts?: ShotOptions): Promise<ScreenshotField>;
|
|
30
35
|
/** The replay hook that gives every reported flow step its screenshot, filed as `<flow>#<step>`. */
|
|
31
36
|
export declare function replayStepShooter(deps: ToolDeps, sessionId: string): (result: FlowStepResult, flow: string) => Promise<void>;
|
|
37
|
+
/**
|
|
38
|
+
* Frames: the pictures between the steps.
|
|
39
|
+
*
|
|
40
|
+
* A run had one picture per step, so the cloud replay jumped from step to step and showed nothing of
|
|
41
|
+
* what happened between them. A tab that Reticle drives (a leased tab, or the page `reticle drive`
|
|
42
|
+
* opened) is filmed about once a second into the run of its last step. The frames go in the same
|
|
43
|
+
* directory and record as the step shots, with the tool `frame`, so the existing upload sends them
|
|
44
|
+
* and the replay plays them in `seq` order.
|
|
45
|
+
*
|
|
46
|
+
* Bounded twice. A page that did not change is not filmed again. A run keeps at most
|
|
47
|
+
* `FRAME.MAX_PER_RUN` frames, and the gap between frames doubles each quarter of that budget, so a
|
|
48
|
+
* long run is thinned, not cut off at its start. The step shots keep the rest of the per-run limit.
|
|
49
|
+
*
|
|
50
|
+
* ponytail: a desktop shell is not filmed (its capture is a PNG, see the header), and an undriven
|
|
51
|
+
* tab is not filmed (only the page could draw itself, once a second, in the user's own tab).
|
|
52
|
+
*/
|
|
53
|
+
export declare const FRAME: {
|
|
54
|
+
readonly TOOL: "frame";
|
|
55
|
+
readonly EVERY_MS: 1000;
|
|
56
|
+
readonly MAX_PER_RUN: 100;
|
|
57
|
+
/** CDP quality for a frame: lower than a step shot, as for the chat's live view. */
|
|
58
|
+
readonly JPEG_QUALITY: 50;
|
|
59
|
+
};
|
|
60
|
+
/** Stop filming a tab. Safe to call for a tab that is not filmed. */
|
|
61
|
+
export declare function stopFilming(sessionId: string): void;
|
|
62
|
+
/** One tick of a tab's film: one frame, when the budget, the gap and the page allow. Never throws. */
|
|
63
|
+
export declare function filmNow(sessionId: string): Promise<void>;
|
|
@@ -171,6 +171,7 @@ async function shoot(deps, session, tool, { step, verdict }) {
|
|
|
171
171
|
if (!isValidRunId(runId))
|
|
172
172
|
return { error: `no screenshot: unusable run id ${runId}` };
|
|
173
173
|
const dir = stepShotDir(root, runId);
|
|
174
|
+
void filmTab(deps, session, dir);
|
|
174
175
|
const seq = await allocate(deps.fs, dir);
|
|
175
176
|
if (seq > STEP_SCREENSHOT.MAX_PER_RUN) {
|
|
176
177
|
return {
|
|
@@ -215,7 +216,7 @@ async function shoot(deps, session, tool, { step, verdict }) {
|
|
|
215
216
|
});
|
|
216
217
|
noteLanding(dir, land);
|
|
217
218
|
if (predicted !== undefined)
|
|
218
|
-
return { path, source: predicted };
|
|
219
|
+
return { path, source: predicted, pending: true };
|
|
219
220
|
// Nothing worked last time: wait, and tell the truth either way.
|
|
220
221
|
const pixels = await taken;
|
|
221
222
|
await land;
|
|
@@ -229,3 +230,156 @@ export function replayStepShooter(deps, sessionId) {
|
|
|
229
230
|
});
|
|
230
231
|
};
|
|
231
232
|
}
|
|
233
|
+
/**
|
|
234
|
+
* Frames: the pictures between the steps.
|
|
235
|
+
*
|
|
236
|
+
* A run had one picture per step, so the cloud replay jumped from step to step and showed nothing of
|
|
237
|
+
* what happened between them. A tab that Reticle drives (a leased tab, or the page `reticle drive`
|
|
238
|
+
* opened) is filmed about once a second into the run of its last step. The frames go in the same
|
|
239
|
+
* directory and record as the step shots, with the tool `frame`, so the existing upload sends them
|
|
240
|
+
* and the replay plays them in `seq` order.
|
|
241
|
+
*
|
|
242
|
+
* Bounded twice. A page that did not change is not filmed again. A run keeps at most
|
|
243
|
+
* `FRAME.MAX_PER_RUN` frames, and the gap between frames doubles each quarter of that budget, so a
|
|
244
|
+
* long run is thinned, not cut off at its start. The step shots keep the rest of the per-run limit.
|
|
245
|
+
*
|
|
246
|
+
* ponytail: a desktop shell is not filmed (its capture is a PNG, see the header), and an undriven
|
|
247
|
+
* tab is not filmed (only the page could draw itself, once a second, in the user's own tab).
|
|
248
|
+
*/
|
|
249
|
+
export const FRAME = {
|
|
250
|
+
TOOL: STEP_SCREENSHOT.FRAME_TOOL,
|
|
251
|
+
EVERY_MS: 1_000,
|
|
252
|
+
MAX_PER_RUN: 100,
|
|
253
|
+
/** CDP quality for a frame: lower than a step shot, as for the chat's live view. */
|
|
254
|
+
JPEG_QUALITY: 50,
|
|
255
|
+
};
|
|
256
|
+
/** The quarters the budget is split into: the gap between frames doubles at each. */
|
|
257
|
+
const FRAME_STAGES = 4;
|
|
258
|
+
/**
|
|
259
|
+
* The frames a new one is compared with. A page that flips between a few looks (a blinking caret,
|
|
260
|
+
* a spinner) is unchanged, not a new frame every tick.
|
|
261
|
+
*/
|
|
262
|
+
const RECENT_FRAMES = 4;
|
|
263
|
+
/** The longest wait, in ticks, between captures of a page that keeps looking the same. */
|
|
264
|
+
const MAX_STILL_TICKS = 32;
|
|
265
|
+
const films = new Map();
|
|
266
|
+
/** Frames kept per run directory. */
|
|
267
|
+
const framesIn = new Map();
|
|
268
|
+
/** Is this a tab Reticle drives, with a real browser behind it? */
|
|
269
|
+
async function driven(deps, session) {
|
|
270
|
+
if (true === deps.pool?.leasedSessionIds().includes(session.id))
|
|
271
|
+
return true;
|
|
272
|
+
return (deps.realInput?.screenshot !== undefined &&
|
|
273
|
+
true === (await deps.realInput.isAvailableFor(session.url)));
|
|
274
|
+
}
|
|
275
|
+
/** Start filming a driven tab, or point its film at the run its newest step went to. */
|
|
276
|
+
async function filmTab(deps, session, dir) {
|
|
277
|
+
const film = films.get(session.id);
|
|
278
|
+
if (film !== undefined) {
|
|
279
|
+
film.dir = dir;
|
|
280
|
+
// A step usually changes the page: look again at the next tick.
|
|
281
|
+
film.still = 1;
|
|
282
|
+
return;
|
|
283
|
+
}
|
|
284
|
+
if (!(await driven(deps, session).catch(() => false)))
|
|
285
|
+
return;
|
|
286
|
+
if (films.has(session.id))
|
|
287
|
+
return;
|
|
288
|
+
const timer = setInterval(() => {
|
|
289
|
+
void filmNow(session.id);
|
|
290
|
+
}, FRAME.EVERY_MS);
|
|
291
|
+
// A film never holds a process open.
|
|
292
|
+
timer.unref?.();
|
|
293
|
+
films.set(session.id, { deps, dir, timer, busy: undefined, recent: [], idle: 0, still: 1 });
|
|
294
|
+
}
|
|
295
|
+
/** Stop filming a tab. Safe to call for a tab that is not filmed. */
|
|
296
|
+
export function stopFilming(sessionId) {
|
|
297
|
+
const film = films.get(sessionId);
|
|
298
|
+
if (film === undefined)
|
|
299
|
+
return;
|
|
300
|
+
clearInterval(film.timer);
|
|
301
|
+
films.delete(sessionId);
|
|
302
|
+
}
|
|
303
|
+
/** One tick of a tab's film: one frame, when the budget, the gap and the page allow. Never throws. */
|
|
304
|
+
export async function filmNow(sessionId) {
|
|
305
|
+
const film = films.get(sessionId);
|
|
306
|
+
if (film === undefined || film.busy !== undefined)
|
|
307
|
+
return;
|
|
308
|
+
film.busy = frame(sessionId, film).finally(() => {
|
|
309
|
+
film.busy = undefined;
|
|
310
|
+
});
|
|
311
|
+
await film.busy;
|
|
312
|
+
}
|
|
313
|
+
async function frame(sessionId, film) {
|
|
314
|
+
let session;
|
|
315
|
+
try {
|
|
316
|
+
session = film.deps.sessions.resolve(sessionId);
|
|
317
|
+
// An ended tab has nothing more to show.
|
|
318
|
+
if (session.isEnded())
|
|
319
|
+
session = undefined;
|
|
320
|
+
}
|
|
321
|
+
catch {
|
|
322
|
+
session = undefined;
|
|
323
|
+
}
|
|
324
|
+
if (session === undefined) {
|
|
325
|
+
stopFilming(sessionId);
|
|
326
|
+
return;
|
|
327
|
+
}
|
|
328
|
+
const dir = film.dir;
|
|
329
|
+
const kept = framesIn.get(dir) ?? 0;
|
|
330
|
+
if (kept >= FRAME.MAX_PER_RUN)
|
|
331
|
+
return;
|
|
332
|
+
film.idle += 1;
|
|
333
|
+
const gap = 2 ** Math.floor(kept / (FRAME.MAX_PER_RUN / FRAME_STAGES));
|
|
334
|
+
if (film.idle < Math.max(gap, film.still))
|
|
335
|
+
return;
|
|
336
|
+
film.idle = 0;
|
|
337
|
+
try {
|
|
338
|
+
const bytes = await framePixels(film.deps, session);
|
|
339
|
+
const size = bytes === undefined ? undefined : jpegSize(bytes);
|
|
340
|
+
if (bytes === undefined || size === undefined)
|
|
341
|
+
return;
|
|
342
|
+
const sha256 = createHash('sha256').update(bytes).digest('hex');
|
|
343
|
+
if (film.recent.includes(sha256)) {
|
|
344
|
+
film.still = Math.min(film.still * 2, MAX_STILL_TICKS);
|
|
345
|
+
return;
|
|
346
|
+
}
|
|
347
|
+
film.recent = [...film.recent, sha256].slice(-RECENT_FRAMES);
|
|
348
|
+
film.still = 1;
|
|
349
|
+
const seq = await allocate(film.deps.fs, dir);
|
|
350
|
+
// The step shots' own limit is the platform's: a frame never takes the last of it.
|
|
351
|
+
if (seq > STEP_SCREENSHOT.MAX_PER_RUN)
|
|
352
|
+
return;
|
|
353
|
+
framesIn.set(dir, kept + 1);
|
|
354
|
+
const file = `${String(seq).padStart(SEQ_WIDTH, '0')}-${FRAME.TOOL}${JPEG_EXT}`;
|
|
355
|
+
const record = {
|
|
356
|
+
seq,
|
|
357
|
+
file,
|
|
358
|
+
tool: FRAME.TOOL,
|
|
359
|
+
source: ScreenshotSource.BROWSER,
|
|
360
|
+
...size,
|
|
361
|
+
sha256,
|
|
362
|
+
};
|
|
363
|
+
const fs = film.deps.fs;
|
|
364
|
+
const land = (async () => {
|
|
365
|
+
await fs.mkdir(dir);
|
|
366
|
+
await fs.writeFileBytes(join(dir, file), bytes);
|
|
367
|
+
await fs.appendFile(join(dir, STEP_SCREENSHOT.MANIFEST_FILE), `${JSON.stringify(record)}\n`);
|
|
368
|
+
})().catch(() => undefined);
|
|
369
|
+
noteLanding(dir, land);
|
|
370
|
+
await land;
|
|
371
|
+
}
|
|
372
|
+
catch {
|
|
373
|
+
// A frame is a courtesy: the next tick tries again.
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
/** The real pixels of a driven tab, as a frame. */
|
|
377
|
+
async function framePixels(deps, session) {
|
|
378
|
+
const opts = { jpegQuality: FRAME.JPEG_QUALITY, cssScale: true };
|
|
379
|
+
const leased = await deps.pool?.screenshotLease(session.id, opts);
|
|
380
|
+
if (leased !== undefined)
|
|
381
|
+
return leased;
|
|
382
|
+
if (true !== (await deps.realInput?.isAvailableFor(session.url)))
|
|
383
|
+
return undefined;
|
|
384
|
+
return deps.realInput?.screenshot?.(session.url, opts);
|
|
385
|
+
}
|
|
@@ -205,8 +205,8 @@ function runtimeOf(deps, sessionId) {
|
|
|
205
205
|
* to one app and the screenshot aimed at a different (desktop) session, CDP fails and the shell
|
|
206
206
|
* capture is still correct.
|
|
207
207
|
*
|
|
208
|
-
*
|
|
209
|
-
*
|
|
208
|
+
* CDP and leased pages honor `clip`/`ref`. The desktop shell photographs the whole window,
|
|
209
|
+
* so scoped desktop captures are refused instead of saved or compared as full-window images.
|
|
210
210
|
*
|
|
211
211
|
* `fullPage` is different, because it cannot be emulated by cropping: only WebKitGTK (Tauri on Linux)
|
|
212
212
|
* can render a full document offscreen. Where the shell cannot, it REFUSES and this reports
|
|
@@ -238,8 +238,14 @@ async function capture(deps, sessionId, args) {
|
|
|
238
238
|
// The window's own backing store, via the Electron/Tauri adapter — the only route whose pixels
|
|
239
239
|
// really are the desktop app.
|
|
240
240
|
const desktop = await desktopCapture(deps, sessionId, true === args['fullPage']);
|
|
241
|
-
if (desktop.png !== undefined)
|
|
241
|
+
if (desktop.png !== undefined) {
|
|
242
|
+
// Check the route that supplied the pixels, not the session runtime: a desktop session can
|
|
243
|
+
// use CDP, and a page without desktop capture can still fall back to a leased browser.
|
|
244
|
+
if (args['clip'] !== undefined || args['ref'] !== undefined) {
|
|
245
|
+
return { reason: VisualReason.CROP_UNSUPPORTED };
|
|
246
|
+
}
|
|
242
247
|
return { png: desktop.png, runtime: runtimeOf(deps, sessionId) };
|
|
248
|
+
}
|
|
243
249
|
if (desktop.reason !== undefined)
|
|
244
250
|
return desktop;
|
|
245
251
|
/*
|
|
@@ -251,7 +257,9 @@ async function capture(deps, sessionId, args) {
|
|
|
251
257
|
*/
|
|
252
258
|
const leased = sessionId === undefined
|
|
253
259
|
? undefined
|
|
254
|
-
:
|
|
260
|
+
: // The same scope as the provider route: `clip` and `ref` were dropped here, so a scoped
|
|
261
|
+
// shot of a lease saved the whole viewport and answered `saved: true`.
|
|
262
|
+
await deps.pool?.screenshotLease(sessionId, await buildOpts(deps, sessionId, args));
|
|
255
263
|
// A leased page is a real browser page, whatever the session is.
|
|
256
264
|
if (leased !== undefined)
|
|
257
265
|
return { png: leased, runtime: AppRuntime.WEB };
|
|
@@ -4,6 +4,12 @@ export declare function agentLabel(name: string): string;
|
|
|
4
4
|
export declare function agentClientOf(name: string | undefined): AgentClient | undefined;
|
|
5
5
|
/** An MCP connection finished its handshake as `name`. */
|
|
6
6
|
export declare function noteAgentAttached(attachId: string, name: string): void;
|
|
7
|
+
/** Connection `attachId` announced the agent session `session`. */
|
|
8
|
+
export declare function noteAgentSession(attachId: string, session: string): void;
|
|
9
|
+
/** The agent session connection `attachId` announced, if any. */
|
|
10
|
+
export declare function agentSessionOf(attachId: string | undefined): string | undefined;
|
|
11
|
+
/** The name connection `attachId` gave in its handshake, while it is attached. */
|
|
12
|
+
export declare function agentNameOf(attachId: string | undefined): string | undefined;
|
|
7
13
|
/** That connection closed. */
|
|
8
14
|
export declare function noteAgentDetached(attachId: string): void;
|
|
9
15
|
/** The friendly names of the agents attached now, each once. */
|
|
@@ -40,8 +40,9 @@ export function agentLabel(name) {
|
|
|
40
40
|
}
|
|
41
41
|
/** The closed telemetry value for a client name: never the name itself, which is the client's text. */
|
|
42
42
|
export function agentClientOf(name) {
|
|
43
|
-
if (name === undefined || 0 === name.trim().length)
|
|
43
|
+
if (name === undefined || 0 === name.trim().length) {
|
|
44
44
|
return undefined;
|
|
45
|
+
}
|
|
45
46
|
return knownAgent(name)?.[2] ?? AgentClient.OTHER;
|
|
46
47
|
}
|
|
47
48
|
/** An MCP connection finished its handshake as `name`. */
|
|
@@ -49,10 +50,29 @@ export function noteAgentAttached(attachId, name) {
|
|
|
49
50
|
byAttach.set(attachId, name);
|
|
50
51
|
changed();
|
|
51
52
|
}
|
|
53
|
+
/**
|
|
54
|
+
* The agent's own session id per connection, as its MCP server announced it. Kept after the
|
|
55
|
+
* connection closes: a run written at a session's end still needs it.
|
|
56
|
+
* ponytail: never pruned; one short string per MCP connect for the daemon's lifetime.
|
|
57
|
+
*/
|
|
58
|
+
const sessionByAttach = new Map();
|
|
59
|
+
/** Connection `attachId` announced the agent session `session`. */
|
|
60
|
+
export function noteAgentSession(attachId, session) {
|
|
61
|
+
sessionByAttach.set(attachId, session);
|
|
62
|
+
}
|
|
63
|
+
/** The agent session connection `attachId` announced, if any. */
|
|
64
|
+
export function agentSessionOf(attachId) {
|
|
65
|
+
return attachId === undefined ? undefined : sessionByAttach.get(attachId);
|
|
66
|
+
}
|
|
67
|
+
/** The name connection `attachId` gave in its handshake, while it is attached. */
|
|
68
|
+
export function agentNameOf(attachId) {
|
|
69
|
+
return attachId === undefined ? undefined : byAttach.get(attachId);
|
|
70
|
+
}
|
|
52
71
|
/** That connection closed. */
|
|
53
72
|
export function noteAgentDetached(attachId) {
|
|
54
|
-
if (byAttach.delete(attachId))
|
|
73
|
+
if (byAttach.delete(attachId)) {
|
|
55
74
|
changed();
|
|
75
|
+
}
|
|
56
76
|
}
|
|
57
77
|
/** The friendly names of the agents attached now, each once. */
|
|
58
78
|
export function connectedAgents() {
|
|
@@ -95,8 +115,9 @@ export function callerClientName() {
|
|
|
95
115
|
export function callingClientName() {
|
|
96
116
|
const own = calling.getStore();
|
|
97
117
|
const name = own === undefined ? undefined : byAttach.get(own);
|
|
98
|
-
if (name !== undefined)
|
|
118
|
+
if (name !== undefined) {
|
|
99
119
|
return name;
|
|
120
|
+
}
|
|
100
121
|
const all = [...new Set(byAttach.values())];
|
|
101
122
|
return 1 === all.length ? all[0] : undefined;
|
|
102
123
|
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Which episode a run belongs to, the commit it ran against, and the agent session behind it.
|
|
3
|
+
*
|
|
4
|
+
* The episode log notes each episode here as it writes; the run store reads it back to stamp a run
|
|
5
|
+
* with `episodeId`, `agentSession` and `project.commit`, so a run joins to the agent's trajectory
|
|
6
|
+
* exactly instead of by time and file. A leaf: it imports nothing, so both sides can reach it.
|
|
7
|
+
*/
|
|
8
|
+
export interface EpisodeStamp {
|
|
9
|
+
episodeId: string;
|
|
10
|
+
/** The git HEAD at the episode's start, once git has answered. */
|
|
11
|
+
head?: string;
|
|
12
|
+
/**
|
|
13
|
+
* The coding agent's own session id, as its MCP server announced it (Claude Code's
|
|
14
|
+
* `CLAUDE_CODE_SESSION_ID`, which is the `session_id` its hooks receive). Names the
|
|
15
|
+
* `agent-<session>.jsonl` the agent hooks write.
|
|
16
|
+
*/
|
|
17
|
+
agentSession?: string;
|
|
18
|
+
}
|
|
19
|
+
/** What one write to an episode says. Every field may be absent: a HEAD arrives later, alone. */
|
|
20
|
+
export interface EpisodeNote {
|
|
21
|
+
head?: string;
|
|
22
|
+
sessionId?: string;
|
|
23
|
+
agentSession?: string;
|
|
24
|
+
}
|
|
25
|
+
/** An episode wrote to `root`. */
|
|
26
|
+
export declare function noteEpisode(root: string, episodeId: string, note?: EpisodeNote): void;
|
|
27
|
+
/**
|
|
28
|
+
* The episode a run written to `root` belongs to: the calling connection's; else, outside a call,
|
|
29
|
+
* the one whose calls last drove the run's tab; else the project's only episode. Two episodes and
|
|
30
|
+
* nothing to tell them apart is undefined, never the newest one.
|
|
31
|
+
*/
|
|
32
|
+
export declare function episodeStampFor(root: string, attachId?: string, sessionId?: string): EpisodeStamp | undefined;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Which episode a run belongs to, the commit it ran against, and the agent session behind it.
|
|
3
|
+
*
|
|
4
|
+
* The episode log notes each episode here as it writes; the run store reads it back to stamp a run
|
|
5
|
+
* with `episodeId`, `agentSession` and `project.commit`, so a run joins to the agent's trajectory
|
|
6
|
+
* exactly instead of by time and file. A leaf: it imports nothing, so both sides can reach it.
|
|
7
|
+
*/
|
|
8
|
+
/** Per project root, each episode by id. */
|
|
9
|
+
const byRoot = new Map();
|
|
10
|
+
/** Orders calls across episodes, so "the last episode to drive a tab" is well defined. */
|
|
11
|
+
let tick = 0;
|
|
12
|
+
/** An episode wrote to `root`. */
|
|
13
|
+
export function noteEpisode(root, episodeId, note = {}) {
|
|
14
|
+
const episodes = byRoot.get(root) ?? new Map();
|
|
15
|
+
const known = episodes.get(episodeId) ?? { episodeId, tabs: new Map() };
|
|
16
|
+
if (note.head !== undefined) {
|
|
17
|
+
known.head = note.head;
|
|
18
|
+
}
|
|
19
|
+
if (note.agentSession !== undefined) {
|
|
20
|
+
known.agentSession = note.agentSession;
|
|
21
|
+
}
|
|
22
|
+
if (note.sessionId !== undefined) {
|
|
23
|
+
known.tabs.set(note.sessionId, (tick += 1));
|
|
24
|
+
}
|
|
25
|
+
episodes.set(episodeId, known);
|
|
26
|
+
byRoot.set(root, episodes);
|
|
27
|
+
}
|
|
28
|
+
const stampOf = ({ episodeId, head, agentSession }) => ({
|
|
29
|
+
episodeId,
|
|
30
|
+
...(head === undefined ? {} : { head }),
|
|
31
|
+
...(agentSession === undefined ? {} : { agentSession }),
|
|
32
|
+
});
|
|
33
|
+
/**
|
|
34
|
+
* The episode a run written to `root` belongs to: the calling connection's; else, outside a call,
|
|
35
|
+
* the one whose calls last drove the run's tab; else the project's only episode. Two episodes and
|
|
36
|
+
* nothing to tell them apart is undefined, never the newest one.
|
|
37
|
+
*/
|
|
38
|
+
export function episodeStampFor(root, attachId, sessionId) {
|
|
39
|
+
const episodes = byRoot.get(root);
|
|
40
|
+
if (episodes === undefined) {
|
|
41
|
+
return undefined;
|
|
42
|
+
}
|
|
43
|
+
const own = attachId === undefined ? undefined : episodes.get(attachId);
|
|
44
|
+
if (own !== undefined) {
|
|
45
|
+
return stampOf(own);
|
|
46
|
+
}
|
|
47
|
+
if (sessionId !== undefined) {
|
|
48
|
+
let driver;
|
|
49
|
+
for (const episode of episodes.values()) {
|
|
50
|
+
const at = episode.tabs.get(sessionId);
|
|
51
|
+
if (at !== undefined && (driver === undefined || at > (driver.tabs.get(sessionId) ?? 0))) {
|
|
52
|
+
driver = episode;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
if (driver !== undefined) {
|
|
56
|
+
return stampOf(driver);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
const [only, ...more] = episodes.values();
|
|
60
|
+
return only !== undefined && 0 === more.length ? stampOf(only) : undefined;
|
|
61
|
+
}
|
|
@@ -49,12 +49,20 @@ const MAX_IN_FLIGHT = 8;
|
|
|
49
49
|
let inFlight = 0;
|
|
50
50
|
const reported = new Set();
|
|
51
51
|
function reportOnce(key, message) {
|
|
52
|
-
if (reported.has(key))
|
|
52
|
+
if (reported.has(key)) {
|
|
53
53
|
return;
|
|
54
|
+
}
|
|
54
55
|
reported.add(key);
|
|
55
56
|
log(`hook: ${message}`);
|
|
56
57
|
}
|
|
57
|
-
/**
|
|
58
|
+
/**
|
|
59
|
+
* Cached config plus the file and mtime it was read at, so an edit takes effect without a
|
|
60
|
+
* daemon restart.
|
|
61
|
+
*
|
|
62
|
+
* The path is part of the key. Two roots can share an mtime — a coarse filesystem stamps
|
|
63
|
+
* every write in the same millisecond — and a cache that remembers only the time returns
|
|
64
|
+
* the other root's commands.
|
|
65
|
+
*/
|
|
58
66
|
let cached;
|
|
59
67
|
/**
|
|
60
68
|
* Read `.reticle/hooks.json`, or nothing.
|
|
@@ -76,21 +84,22 @@ export function readHookConfig(reticleRoot) {
|
|
|
76
84
|
return {};
|
|
77
85
|
}
|
|
78
86
|
try {
|
|
79
|
-
return readOpenHookConfig(fd);
|
|
87
|
+
return readOpenHookConfig(fd, path);
|
|
80
88
|
}
|
|
81
89
|
finally {
|
|
82
90
|
closeSync(fd);
|
|
83
91
|
}
|
|
84
92
|
}
|
|
85
|
-
function readOpenHookConfig(fd) {
|
|
93
|
+
function readOpenHookConfig(fd, path) {
|
|
86
94
|
const mtime = fstatSync(fd).mtimeMs;
|
|
87
|
-
if (cached !== undefined && cached.at === mtime)
|
|
95
|
+
if (cached !== undefined && cached.path === path && cached.at === mtime) {
|
|
88
96
|
return cached.config;
|
|
97
|
+
}
|
|
89
98
|
try {
|
|
90
99
|
const parsed = HookConfigSchema.safeParse(JSON.parse(readFileSync(fd, 'utf8')));
|
|
91
100
|
if (!parsed.success) {
|
|
92
101
|
reportOnce(`config:${String(mtime)}`, `${ReticleDir.HOOKS_FILE} is not a map of event→command`);
|
|
93
|
-
cached = { at: mtime, config: {} };
|
|
102
|
+
cached = { path, at: mtime, config: {} };
|
|
94
103
|
return {};
|
|
95
104
|
}
|
|
96
105
|
// An unknown event name is the likeliest mistake in this file and the one that is otherwise
|
|
@@ -103,12 +112,12 @@ function readOpenHookConfig(fd) {
|
|
|
103
112
|
}
|
|
104
113
|
reportOnce(`unknown:${event}`, `${ReticleDir.HOOKS_FILE} names "${event}", which is not a Reticle event. Known events: ${HOOK_EVENT_NAMES.join(', ')}`);
|
|
105
114
|
}
|
|
106
|
-
cached = { at: mtime, config: known };
|
|
115
|
+
cached = { path, at: mtime, config: known };
|
|
107
116
|
return known;
|
|
108
117
|
}
|
|
109
118
|
catch (error) {
|
|
110
119
|
reportOnce(`parse:${String(mtime)}`, `${ReticleDir.HOOKS_FILE} could not be read: ${error instanceof Error ? error.message : String(error)}`);
|
|
111
|
-
cached = { at: mtime, config: {} };
|
|
120
|
+
cached = { path, at: mtime, config: {} };
|
|
112
121
|
return {};
|
|
113
122
|
}
|
|
114
123
|
}
|
|
@@ -167,8 +176,9 @@ export function runHookCommand(command, payload, cwd) {
|
|
|
167
176
|
export function installCommandHooks(reticleRoot) {
|
|
168
177
|
return onHook(undefined, (payload) => {
|
|
169
178
|
const command = readHookConfig(reticleRoot)[payload.event];
|
|
170
|
-
if (command === undefined || 0 === command.trim().length)
|
|
179
|
+
if (command === undefined || 0 === command.trim().length) {
|
|
171
180
|
return;
|
|
181
|
+
}
|
|
172
182
|
runHookCommand(command, payload, reticleRoot);
|
|
173
183
|
});
|
|
174
184
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -6,6 +6,7 @@ export { replayVerdictLine } from './language/flows/replay-from-hud.js';
|
|
|
6
6
|
export { ReticleTool } from '@reticlehq/core';
|
|
7
7
|
export { RingBuffer } from '@reticlehq/engine/window/ring-buffer.js';
|
|
8
8
|
export { Bridge } from './portal/bridge/bridge.js';
|
|
9
|
+
export type { FollowNavigation, OriginFollowRequest, } from './portal/bridge/origin/origin-follow.js';
|
|
9
10
|
export { Session } from './portal/session/session.js';
|
|
10
11
|
export { SessionManager } from './portal/session/session-manager.js';
|
|
11
12
|
export type { SessionInfo, SessionHealth } from './portal/session/session.js';
|
|
@@ -14,7 +15,8 @@ export type { RecommendationInputs } from './portal/session/presence/session-rec
|
|
|
14
15
|
export { TOOLS } from './surface/tools/tools.js';
|
|
15
16
|
export type { ToolDeps, ToolDef } from './surface/tools/tools.js';
|
|
16
17
|
export { createToolInvoker, UNKNOWN_TOOL_ERROR } from './surface/tools/tool-invoker.js';
|
|
17
|
-
export { runTool
|
|
18
|
+
export { runTool } from './surface/tools/invoke-tool.js';
|
|
19
|
+
export { SESSION_BOUND_TOOLS, SESSION_EXEMPT_TOOLS } from './surface/tools/tool-kit.js';
|
|
18
20
|
export type { ToolInvoker } from './surface/tools/tool-invoker.js';
|
|
19
21
|
/**
|
|
20
22
|
* The port-presence check the CLI commands (`drive`, `verify`, `status`, `doctor`, `kill`) all share,
|
|
@@ -72,6 +74,8 @@ export interface RunningServer {
|
|
|
72
74
|
* the client owns the process and there is no stream to warn. See SharedServer.announceShutdown.
|
|
73
75
|
*/
|
|
74
76
|
announceShutdown?: () => void;
|
|
77
|
+
/** Daemon only: run `handler` when a caller with the pairing token POSTs SHUTDOWN_PATH. */
|
|
78
|
+
onShutdownRequest?: (handler: () => void) => void;
|
|
75
79
|
close: () => Promise<void>;
|
|
76
80
|
}
|
|
77
81
|
export { resolveBridgeSecurity } from './portal/bridge/bridge-security.js';
|