@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
|
@@ -93,6 +93,11 @@ const COMMON_TLDS = new Set([
|
|
|
93
93
|
'in',
|
|
94
94
|
'eu',
|
|
95
95
|
]);
|
|
96
|
+
/**
|
|
97
|
+
* One path separator in every spelling that a report can carry: `/` and `\`, and the JSON-escaped
|
|
98
|
+
* forms `\/`, `\\` and `\\/`. An agent that pastes a JSON string doubles each backslash.
|
|
99
|
+
*/
|
|
100
|
+
const PATH_SEP = String.raw `(?:\\{0,2}\/|\\{1,2})`;
|
|
96
101
|
/**
|
|
97
102
|
* The shapes that leak. Ordered most-specific first — a URL carrying inline credentials must be
|
|
98
103
|
* caught as a URL before the bare-token rule chews the middle out of it.
|
|
@@ -117,22 +122,48 @@ const REDACTIONS = [
|
|
|
117
122
|
// Credential assignments: the KEY stays (it is the useful part), the VALUE goes. The auth SCHEME
|
|
118
123
|
// (`Bearer`, `Basic`, `Token`) is consumed as part of the value, not left as the value — matching
|
|
119
124
|
// only `\S+` after the separator ate the word "Bearer" and published the secret right behind it.
|
|
125
|
+
// A linking verb is skipped too: "my password is hunter2" lost the word "is" and kept hunter2.
|
|
126
|
+
{
|
|
127
|
+
pattern: /\b(authorization|api[-_]?key|secret|token|password|passwd|pwd)\b(?:\s*[:=]\s*|\s+(?:(?:is|was|=|:)\s+)?)(?:(?:bearer|basic|token|digest)\s+)?\S+/gi,
|
|
128
|
+
label: 'credential-assignment',
|
|
129
|
+
},
|
|
130
|
+
// An environment-style assignment: `STRIPE_SECRET_KEY=…`, `AWS_SECRET_ACCESS_KEY=…`, `DB_PASS: …`.
|
|
131
|
+
// `\b` does not end a word at `_`, so the rule above never saw these. The sensitive word must be
|
|
132
|
+
// one whole `_` segment of the name, so `PASSPORT_ID` or `TOKENIZER_MODE` stay.
|
|
120
133
|
{
|
|
121
|
-
pattern: /\b(
|
|
134
|
+
pattern: /\b((?:[A-Za-z0-9]+_)*(?:SECRET|TOKEN|PASS|PASSWORD|PASSWD|PWD|PASSPHRASE|API_?KEY|PRIVATE_?KEY|ACCESS_?KEY|AUTH|CREDENTIALS?)(?:_[A-Za-z0-9]+)*)\s*[:=]\s*\S+/gi,
|
|
122
135
|
label: 'credential-assignment',
|
|
123
136
|
},
|
|
124
|
-
// Vendor key formats that are self-identifying (sk-…, ghp_…, AKIA…, xoxb-…, eyJ… JWTs).
|
|
137
|
+
// Vendor key formats that are self-identifying (sk-…, sk_live_…, ghp_…, AKIA…, xoxb-…, eyJ… JWTs).
|
|
125
138
|
{ pattern: /\b(?:sk|pk|rk)-[A-Za-z0-9_-]{16,}\b/g, label: 'vendor-key' },
|
|
139
|
+
{ pattern: /\b(?:sk|pk|rk)_(?:live|test)_[A-Za-z0-9]{10,}\b/g, label: 'vendor-key' },
|
|
126
140
|
{ pattern: /\bgh[pousr]_[A-Za-z0-9]{20,}\b/g, label: 'github-token' },
|
|
127
|
-
{ pattern: /\
|
|
141
|
+
{ pattern: /\bgithub_pat_[A-Za-z0-9_]{20,}\b/g, label: 'github-token' },
|
|
142
|
+
{ pattern: /\bglpat-[A-Za-z0-9_-]{20,}\b/g, label: 'gitlab-token' },
|
|
143
|
+
{ pattern: /\bAIza[0-9A-Za-z_-]{35}\b/g, label: 'google-key' },
|
|
144
|
+
{ pattern: /\b(?:AKIA|ASIA)[0-9A-Z]{16}\b/g, label: 'aws-key' },
|
|
128
145
|
{ pattern: /\bxox[baprs]-[A-Za-z0-9-]{10,}\b/g, label: 'slack-token' },
|
|
129
146
|
{ pattern: /\beyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\b/g, label: 'jwt' },
|
|
147
|
+
// A payment card: 13 to 19 digits, spaces or dashes allowed, that pass the Luhn check. An id or a
|
|
148
|
+
// millisecond timestamp rarely starts with 2 to 6 AND passes Luhn, so those stay.
|
|
149
|
+
{
|
|
150
|
+
pattern: /\b[2-6](?:[ -]?\d){12,18}\b/g,
|
|
151
|
+
label: 'card-number',
|
|
152
|
+
replace: (digits) => (luhnValid(digits.replace(/\D/g, '')) ? REDACTED : digits),
|
|
153
|
+
},
|
|
154
|
+
// A phone number: an international `+` number, or a ten-digit (123) 456-7890 shape.
|
|
155
|
+
{
|
|
156
|
+
pattern: /(?<![\w+])\+\d[\d ().-]{6,18}\d(?!\w)/g,
|
|
157
|
+
label: 'phone',
|
|
158
|
+
replace: (number) => (8 <= number.replace(/\D/g, '').length ? REDACTED : number),
|
|
159
|
+
},
|
|
160
|
+
{ pattern: /(?<![\w(])\(?\d{3}\)?[ .-]\d{3}[ .-]\d{4}\b/g, label: 'phone' },
|
|
130
161
|
// Home directories carry the account name, and a trace is full of them. The name runs to the next
|
|
131
162
|
// separator, quote or line end, NOT the next space: `C:\Users\Jane Doe\…` stopped at the space and
|
|
132
163
|
// sent the surname. Then the rest of the path goes with it. Over-redacting a sentence that follows
|
|
133
164
|
// a bare home directory is the price, and it is the right way round.
|
|
134
165
|
{
|
|
135
|
-
pattern:
|
|
166
|
+
pattern: new RegExp(String.raw `(?:\\\\\?\\)?(?:${PATH_SEP}(?:Users|home)${PATH_SEP}|[A-Za-z]:${PATH_SEP}Users${PATH_SEP})[^\\/\r\n"'${'`'}]+(?:[\\/][^\s\\/"'${'`'}]*)*`, 'gi'),
|
|
136
167
|
label: 'home-path',
|
|
137
168
|
},
|
|
138
169
|
// Any other absolute path: a Windows one (segments may hold spaces when a separator follows)...
|
|
@@ -164,6 +195,20 @@ const REDACTIONS = [
|
|
|
164
195
|
},
|
|
165
196
|
},
|
|
166
197
|
];
|
|
198
|
+
/** The Luhn checksum every payment card number carries. */
|
|
199
|
+
function luhnValid(digits) {
|
|
200
|
+
let sum = 0;
|
|
201
|
+
for (let i = 0; i < digits.length; i++) {
|
|
202
|
+
let d = Number(digits[digits.length - 1 - i]);
|
|
203
|
+
if (1 === i % 2) {
|
|
204
|
+
d *= 2;
|
|
205
|
+
if (9 < d)
|
|
206
|
+
d -= 9;
|
|
207
|
+
}
|
|
208
|
+
sum += d;
|
|
209
|
+
}
|
|
210
|
+
return 0 === sum % 10;
|
|
211
|
+
}
|
|
167
212
|
/** Strip credential/PII shapes and cap the length. Pure — the tests read like a spec of what leaks. */
|
|
168
213
|
export function redactFeedbackText(input, max) {
|
|
169
214
|
const removed = new Set();
|
|
@@ -284,6 +329,8 @@ export async function submitFeedback(input, opts = {}) {
|
|
|
284
329
|
...Object.fromEntries([...redactions].filter(([, r]) => r.text !== '').map(([key, r]) => [key, r.text])),
|
|
285
330
|
text: body.text,
|
|
286
331
|
...(input.rating !== undefined ? { rating: input.rating } : {}),
|
|
332
|
+
// Not redacted: the person gave this address so the maintainers can answer. Sent only then.
|
|
333
|
+
...(input.contact !== undefined ? { contact: input.contact } : {}),
|
|
287
334
|
...context,
|
|
288
335
|
});
|
|
289
336
|
if (!parsed.success) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { HarnessRunSource, type HarnessRun } from '@reticlehq/core/telemetry';
|
|
1
|
+
import { HarnessRunReason, HarnessRunSource, type HarnessRun } from '@reticlehq/core/telemetry';
|
|
2
2
|
import { DriveOrigin, DriveStatus } from '../features/harness/drive-runs.js';
|
|
3
3
|
import { type Telemetry } from './telemetry.js';
|
|
4
4
|
export interface HarnessRunStart {
|
|
@@ -8,11 +8,11 @@ export interface HarnessRunStart {
|
|
|
8
8
|
/** Who started it. A saved plan is a plan whoever pressed Run. */
|
|
9
9
|
export declare function harnessRunSource(origin: DriveOrigin, planId: string | undefined): HarnessRunSource;
|
|
10
10
|
/** How a finished run ended, from what the registry recorded. */
|
|
11
|
-
export declare function harnessRunEnd(status: DriveStatus, result: Record<string, unknown> | undefined): Pick<HarnessRun, 'outcome' | 'journeys' | 'replayed'>;
|
|
11
|
+
export declare function harnessRunEnd(status: DriveStatus, result: Record<string, unknown> | undefined, reason?: HarnessRunReason): Pick<HarnessRun, 'outcome' | 'journeys' | 'replayed' | 'reason'>;
|
|
12
12
|
/** Report the run's start, run it, report its end, and hand back exactly what it did. */
|
|
13
13
|
export declare function reportHarnessRun<T extends {
|
|
14
14
|
status: DriveStatus;
|
|
15
15
|
result: Record<string, unknown>;
|
|
16
16
|
}>(start: HarnessRunStart, run: () => Promise<T>, refused: (error: unknown) => boolean, telemetry?: Pick<Telemetry, 'emit'>): Promise<T>;
|
|
17
17
|
/** A run the gate refused before it could start: still somebody who asked for one. */
|
|
18
|
-
export declare function reportHarnessBlocked(start: HarnessRunStart, telemetry?: Pick<Telemetry, 'emit'>): void;
|
|
18
|
+
export declare function reportHarnessBlocked(start: HarnessRunStart, reason: HarnessRunReason, telemetry?: Pick<Telemetry, 'emit'>): void;
|
|
@@ -10,8 +10,8 @@
|
|
|
10
10
|
*/
|
|
11
11
|
import { asRecord } from '@reticlehq/core';
|
|
12
12
|
import { JourneyBy } from '@reticlehq/core/artifacts';
|
|
13
|
-
import { HarnessRunOutcome, HarnessRunPhase, HarnessRunSource, TelemetryEventKind, countBucket, } from '@reticlehq/core/telemetry';
|
|
14
|
-
import { DriveOrigin, DriveStatus } from '../features/harness/drive-runs.js';
|
|
13
|
+
import { HarnessRunOutcome, HarnessRunPhase, HarnessRunReason, HarnessRunSource, TelemetryEventKind, countBucket, } from '@reticlehq/core/telemetry';
|
|
14
|
+
import { DriveOrigin, DriveRefusedError, DriveStatus } from '../features/harness/drive-runs.js';
|
|
15
15
|
import { getTelemetry } from './telemetry.js';
|
|
16
16
|
const SOURCE_OF = {
|
|
17
17
|
[DriveOrigin.AGENT]: HarnessRunSource.AGENT,
|
|
@@ -24,7 +24,7 @@ export function harnessRunSource(origin, planId) {
|
|
|
24
24
|
return planId === undefined ? SOURCE_OF[origin] : HarnessRunSource.PLAN;
|
|
25
25
|
}
|
|
26
26
|
/** How a finished run ended, from what the registry recorded. */
|
|
27
|
-
export function harnessRunEnd(status, result) {
|
|
27
|
+
export function harnessRunEnd(status, result, reason) {
|
|
28
28
|
const journeys = Array.isArray(result?.['journeys']) ? result['journeys'] : undefined;
|
|
29
29
|
const replayed = (journeys ?? []).filter((j) => JourneyBy.REPLAY === asRecord(j)['by']).length;
|
|
30
30
|
const outcome = DriveStatus.REFUSED === status
|
|
@@ -38,7 +38,18 @@ export function harnessRunEnd(status, result) {
|
|
|
38
38
|
: HarnessRunOutcome.NOT_PROVED;
|
|
39
39
|
// An unplanned drive is one journey; a refused one drove none.
|
|
40
40
|
const count = journeys?.length ?? (HarnessRunOutcome.BLOCKED === outcome ? 0 : 1);
|
|
41
|
-
|
|
41
|
+
// Why it did not drive: only a blocked or failed run has a reason, and a break names itself.
|
|
42
|
+
const why = HarnessRunOutcome.BLOCKED === outcome
|
|
43
|
+
? (reason ?? HarnessRunReason.OTHER)
|
|
44
|
+
: HarnessRunOutcome.FAILED === outcome
|
|
45
|
+
? (reason ?? HarnessRunReason.BROKEN)
|
|
46
|
+
: undefined;
|
|
47
|
+
return {
|
|
48
|
+
outcome,
|
|
49
|
+
journeys: countBucket(count),
|
|
50
|
+
replayed: countBucket(replayed),
|
|
51
|
+
...(why === undefined ? {} : { reason: why }),
|
|
52
|
+
};
|
|
42
53
|
}
|
|
43
54
|
function emit(telemetry, harness) {
|
|
44
55
|
try {
|
|
@@ -64,17 +75,17 @@ export async function reportHarnessRun(start, run, refused, telemetry = getTelem
|
|
|
64
75
|
emit(telemetry, {
|
|
65
76
|
phase: HarnessRunPhase.COMPLETED,
|
|
66
77
|
...start,
|
|
67
|
-
...harnessRunEnd(refused(error) ? DriveStatus.REFUSED : DriveStatus.BROKEN, undefined),
|
|
78
|
+
...harnessRunEnd(refused(error) ? DriveStatus.REFUSED : DriveStatus.BROKEN, undefined, error instanceof DriveRefusedError ? error.reason : undefined),
|
|
68
79
|
});
|
|
69
80
|
throw error;
|
|
70
81
|
}
|
|
71
82
|
}
|
|
72
83
|
/** A run the gate refused before it could start: still somebody who asked for one. */
|
|
73
|
-
export function reportHarnessBlocked(start, telemetry = getTelemetry()) {
|
|
84
|
+
export function reportHarnessBlocked(start, reason, telemetry = getTelemetry()) {
|
|
74
85
|
emit(telemetry, { phase: HarnessRunPhase.STARTED, ...start });
|
|
75
86
|
emit(telemetry, {
|
|
76
87
|
phase: HarnessRunPhase.COMPLETED,
|
|
77
88
|
...start,
|
|
78
|
-
...harnessRunEnd(DriveStatus.REFUSED, undefined),
|
|
89
|
+
...harnessRunEnd(DriveStatus.REFUSED, undefined, reason),
|
|
79
90
|
});
|
|
80
91
|
}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* order; these say how often and by whom, which a window summed across a session cannot.
|
|
5
5
|
*
|
|
6
6
|
* Sent by the daemon, like every HUD measure, so every opt-out applies, and only from the names the
|
|
7
|
-
* wire schema already narrowed. The dedupe (per
|
|
7
|
+
* wire schema already narrowed. The dedupe (per daemon, per page or surface) lives in `HudMetrics`.
|
|
8
8
|
*/
|
|
9
9
|
import type { HudUseData } from '@reticlehq/core';
|
|
10
10
|
import { type Telemetry } from './telemetry.js';
|
|
@@ -26,13 +26,16 @@ export interface HudSummary {
|
|
|
26
26
|
/** Times each rail slide became the visible one. Slide ids are Reticle's own, never page text. */
|
|
27
27
|
hudSlides?: Record<string, number>;
|
|
28
28
|
}
|
|
29
|
-
/**
|
|
29
|
+
/**
|
|
30
|
+
* The same page opened again within this long is one view, not two. Per daemon, not per tab: a page
|
|
31
|
+
* reload makes a new tab id, and a page that reloads in a loop is still one person on one page.
|
|
32
|
+
*/
|
|
30
33
|
export declare const HUD_VIEW_DEDUPE_MS = 30000;
|
|
31
34
|
/** What one HUD use means for the per-event signals, beside what it adds to the summary. */
|
|
32
35
|
export interface HudSignals {
|
|
33
|
-
/** A page
|
|
36
|
+
/** A page not opened within the dedupe window. */
|
|
34
37
|
viewed?: HudPanel;
|
|
35
|
-
/** A sign-in prompt this
|
|
38
|
+
/** A sign-in prompt this daemon had not shown before. */
|
|
36
39
|
prompted?: HudPromptSurface;
|
|
37
40
|
/** Tabs with a HUD right now. */
|
|
38
41
|
tabs: number;
|
|
@@ -16,7 +16,10 @@ export const HUD_JOURNEY_MAX = 60;
|
|
|
16
16
|
/** Distinct slide ids counted per window; past this a broken notices file is not a dashboard. */
|
|
17
17
|
const MAX_SLIDE_IDS = 20;
|
|
18
18
|
const SLIDE_ID = /^[a-z0-9-]{1,56}$/;
|
|
19
|
-
/**
|
|
19
|
+
/**
|
|
20
|
+
* The same page opened again within this long is one view, not two. Per daemon, not per tab: a page
|
|
21
|
+
* reload makes a new tab id, and a page that reloads in a loop is still one person on one page.
|
|
22
|
+
*/
|
|
20
23
|
export const HUD_VIEW_DEDUPE_MS = 30_000;
|
|
21
24
|
/** A tab whose page reported HUD use without saying which tab: an older caller, or a test. */
|
|
22
25
|
const UNNAMED_TAB = '';
|
|
@@ -28,6 +31,10 @@ export class HudMetrics {
|
|
|
28
31
|
#journey = [];
|
|
29
32
|
#slides = new Map();
|
|
30
33
|
#tabs = new Map();
|
|
34
|
+
/** When each page last counted as a view. Daemon-lifetime: a window reset keeps it. */
|
|
35
|
+
#viewedAt = new Map();
|
|
36
|
+
/** The prompts already reported. Daemon-lifetime, like the views. */
|
|
37
|
+
#prompted = new Set();
|
|
31
38
|
#cut = false;
|
|
32
39
|
/** Did anything happen this window. A HUD merely sitting open is not worth a flush of its own. */
|
|
33
40
|
#changed = false;
|
|
@@ -37,8 +44,8 @@ export class HudMetrics {
|
|
|
37
44
|
record(use, tabId = UNNAMED_TAB) {
|
|
38
45
|
const tab = this.#tab(tabId);
|
|
39
46
|
const signals = { tabs: this.#tabs.size };
|
|
40
|
-
if (use.prompt !== undefined && !
|
|
41
|
-
|
|
47
|
+
if (use.prompt !== undefined && !this.#prompted.has(use.prompt)) {
|
|
48
|
+
this.#prompted.add(use.prompt);
|
|
42
49
|
signals.prompted = use.prompt;
|
|
43
50
|
}
|
|
44
51
|
// A control the HUD never rendered is dropped here, the one place HUD use is counted, so free
|
|
@@ -53,6 +60,7 @@ export class HudMetrics {
|
|
|
53
60
|
const key = use.toggle === undefined ? control : `${control}:${use.toggle}`;
|
|
54
61
|
this.#controls.set(key, (this.#controls.get(key) ?? 0) + 1);
|
|
55
62
|
this.#step(key);
|
|
63
|
+
tab.pressed = true;
|
|
56
64
|
}
|
|
57
65
|
const at = this.#now();
|
|
58
66
|
const since = tab.hidden ? undefined : at;
|
|
@@ -62,13 +70,18 @@ export class HudMetrics {
|
|
|
62
70
|
this.#step(`view:${use.view}`);
|
|
63
71
|
}
|
|
64
72
|
if (use.panel !== undefined && use.panel !== tab.panel?.value) {
|
|
73
|
+
// The HUD opens the Agent Log by itself when an agent acts, or on load when the person left it
|
|
74
|
+
// open. No press came first, so it is not a choice and not a view. Its time still counts in
|
|
75
|
+
// `hudPanelMs`.
|
|
76
|
+
const opensByItself = HudPanel.CHAT === use.panel && !tab.pressed;
|
|
77
|
+
tab.pressed = false;
|
|
65
78
|
this.#close(tab.panel, this.#panelMs);
|
|
66
79
|
tab.panel = { value: use.panel, since };
|
|
67
80
|
if (use.panel !== HudPanel.NONE) {
|
|
68
81
|
this.#step(`panel:${use.panel}`);
|
|
69
|
-
const last =
|
|
70
|
-
if (last === undefined || at - last >= HUD_VIEW_DEDUPE_MS) {
|
|
71
|
-
|
|
82
|
+
const last = this.#viewedAt.get(use.panel);
|
|
83
|
+
if (!opensByItself && (last === undefined || at - last >= HUD_VIEW_DEDUPE_MS)) {
|
|
84
|
+
this.#viewedAt.set(use.panel, at);
|
|
72
85
|
signals.viewed = use.panel;
|
|
73
86
|
}
|
|
74
87
|
}
|
|
@@ -111,8 +124,7 @@ export class HudMetrics {
|
|
|
111
124
|
view: undefined,
|
|
112
125
|
panel: undefined,
|
|
113
126
|
hidden: false,
|
|
114
|
-
|
|
115
|
-
prompted: new Set(),
|
|
127
|
+
pressed: false,
|
|
116
128
|
};
|
|
117
129
|
this.#tabs.set(tabId, tab);
|
|
118
130
|
return tab;
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
* WHICH CHANNELS ARE GENUINELY DETECTABLE TODAY, so nobody later reads a small `unknown` as success:
|
|
12
12
|
* - `plugin` — real. The Claude Code plugin registers the MCP server itself and can set the marker
|
|
13
13
|
* in that server's `env`, so it is carried by the process without anybody typing anything.
|
|
14
|
-
* - `skill_file` / `npx_skill` / `docs_site` / `readme` — real ONLY where that channel's own copy
|
|
14
|
+
* - `skill_file` / `npx_skill` / `docs_site` / `readme` / `blog` — real ONLY where that channel's own copy
|
|
15
15
|
* of the install command carries the marker. Each is a separately published artifact, so a copy
|
|
16
16
|
* that has not been updated is indistinguishable from no channel at all.
|
|
17
17
|
* - `cli_direct` — NOT detectable. Nobody types a marker to say they typed a command. It exists so
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export declare function markDaemonStart(now: number): void;
|
|
2
|
-
export declare function reportMcpConnected(client?: string, now?: () => number): void;
|
|
2
|
+
export declare function reportMcpConnected(client?: string, attachId?: string, now?: () => number): void;
|
|
3
3
|
/** Tests only. */
|
|
4
4
|
export declare function resetMcpConnections(): void;
|
|
@@ -13,11 +13,14 @@ import { TelemetryEventKind } from '@reticlehq/core/telemetry';
|
|
|
13
13
|
import { getTelemetry } from './telemetry.js';
|
|
14
14
|
import { appEverConnected } from './app-instrumented.js';
|
|
15
15
|
let connectsSeen = 0;
|
|
16
|
+
/** The proxies already reported. A proxy sends one id on every connect of its process. */
|
|
17
|
+
const proxiesSeen = new Set();
|
|
16
18
|
/** Set when the daemon starts, so the FIRST connect can report how long Reticle sat unused. */
|
|
17
19
|
let daemonStartedAt;
|
|
18
20
|
export function markDaemonStart(now) {
|
|
19
21
|
daemonStartedAt = now;
|
|
20
22
|
connectsSeen = 0;
|
|
23
|
+
proxiesSeen.clear();
|
|
21
24
|
}
|
|
22
25
|
/**
|
|
23
26
|
* Report one client attaching, BY NAME. Best-effort; a metric must never affect whether a client
|
|
@@ -32,12 +35,24 @@ export function markDaemonStart(now) {
|
|
|
32
35
|
* An unnamed call reports NOTHING. A stream that opens and never completes a handshake is a probe,
|
|
33
36
|
* not a client attaching, and counting it was what put an unattributable row exactly where the name
|
|
34
37
|
* belonged.
|
|
38
|
+
*
|
|
39
|
+
* ONCE per proxy. `attachId` is the proxy's own id, and the proxy sends the same id each time it
|
|
40
|
+
* reconnects. A reconnect of a known proxy is the same agent coming back, and an event for each one
|
|
41
|
+
* made this the largest event kind with no new fact in it. The proxy counts its own drops on
|
|
42
|
+
* `mcp_proxy_exited`. An older proxy sends no id, so each of its connects still reports.
|
|
35
43
|
*/
|
|
36
44
|
/** `connection.client`'s wire cap. */
|
|
37
45
|
const MAX_CLIENT_NAME = 64;
|
|
38
|
-
export function reportMcpConnected(client, now = () => Date.now()) {
|
|
39
|
-
if (client === undefined)
|
|
46
|
+
export function reportMcpConnected(client, attachId, now = () => Date.now()) {
|
|
47
|
+
if (client === undefined) {
|
|
40
48
|
return;
|
|
49
|
+
}
|
|
50
|
+
if (attachId !== undefined) {
|
|
51
|
+
if (proxiesSeen.has(attachId)) {
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
proxiesSeen.add(attachId);
|
|
55
|
+
}
|
|
41
56
|
try {
|
|
42
57
|
const reconnect = connectsSeen > 0;
|
|
43
58
|
connectsSeen += 1;
|
|
@@ -56,6 +71,9 @@ export function reportMcpConnected(client, now = () => Date.now()) {
|
|
|
56
71
|
// `app_instrumented` sets, never a second counter, so the two halves of the funnel cannot
|
|
57
72
|
// disagree about one daemon run.
|
|
58
73
|
appConnected: appEverConnected(),
|
|
74
|
+
// The proxy that attached. Its `mcp_connection_lost` and `mcp_proxy_exited` rows carry the
|
|
75
|
+
// same id and no `sessionId`, so this row is how they join this daemon run.
|
|
76
|
+
...(attachId === undefined ? {} : { proxyId: attachId }),
|
|
59
77
|
},
|
|
60
78
|
});
|
|
61
79
|
}
|
|
@@ -66,5 +84,6 @@ export function reportMcpConnected(client, now = () => Date.now()) {
|
|
|
66
84
|
/** Tests only. */
|
|
67
85
|
export function resetMcpConnections() {
|
|
68
86
|
connectsSeen = 0;
|
|
87
|
+
proxiesSeen.clear();
|
|
69
88
|
daemonStartedAt = undefined;
|
|
70
89
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type OnboardingStep } from '@reticlehq/core';
|
|
1
|
+
import { NextStepOffered, type OnboardingStep } from '@reticlehq/core';
|
|
2
2
|
/** Report `step` once per process, and only if this machine + project has never reported it. */
|
|
3
3
|
export declare function reportFirstStep(step: OnboardingStep): void;
|
|
4
4
|
/** A successful page read. The dispatcher calls this after excluding refusals and pauses. */
|
|
@@ -44,6 +44,11 @@ export declare function noteDriven(): void;
|
|
|
44
44
|
* took: it fired on every verdict, so a busy session put hundreds of first-run steps in the funnel.
|
|
45
45
|
*/
|
|
46
46
|
export declare function noteVerdictProduced(elapsedMs: number): void;
|
|
47
|
+
export declare function noteNextStepOffered(offered: NextStepOffered, wired: () => boolean): void;
|
|
48
|
+
/** Called on every agent call, before its handler runs. Closes an open offer, once. */
|
|
49
|
+
export declare function noteNextCall(tool: string, args: Record<string, unknown>): void;
|
|
50
|
+
/** Tests only: forget an open offer. */
|
|
51
|
+
export declare function resetNextStepOffered(): void;
|
|
47
52
|
/** Arm again for the next daemon run — the tests' seam, mirroring resetAppInstrumented. */
|
|
48
53
|
export declare function resetOnboardingFirsts(): void;
|
|
49
54
|
/**
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ActionType, OnboardingPhase, OnboardingStepStatus, ReticleTool, } from '@reticlehq/core';
|
|
1
|
+
import { ActionType, NextStepOffered, OnboardingPhase, OnboardingStepStatus, ReticleTool, } from '@reticlehq/core';
|
|
2
2
|
import { mkdirSync, writeFileSync } from 'node:fs';
|
|
3
3
|
import { homedir } from 'node:os';
|
|
4
4
|
import { join } from 'node:path';
|
|
@@ -124,6 +124,46 @@ export function noteVerdictProduced(elapsedMs) {
|
|
|
124
124
|
elapsedMs: Math.max(0, Math.round(elapsedMs)),
|
|
125
125
|
});
|
|
126
126
|
}
|
|
127
|
+
// ponytail: one pending offer per daemon, not per agent. Two agents in two unwired projects at the
|
|
128
|
+
// same moment can close each other's offer. Key it by attach id if the data shows that case.
|
|
129
|
+
let pending;
|
|
130
|
+
const STEP = 'next_step_offered';
|
|
131
|
+
const ACQUIRE = 'acquire';
|
|
132
|
+
export function noteNextStepOffered(offered, wired) {
|
|
133
|
+
pending = { offered, wired };
|
|
134
|
+
void reportOnboardingStep({
|
|
135
|
+
phase: OnboardingPhase.FIRST_RUN,
|
|
136
|
+
step: STEP,
|
|
137
|
+
status: OnboardingStepStatus.STARTED,
|
|
138
|
+
offered,
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
/** Called on every agent call, before its handler runs. Closes an open offer, once. */
|
|
142
|
+
export function noteNextCall(tool, args) {
|
|
143
|
+
const offer = pending;
|
|
144
|
+
if (offer === undefined) {
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
pending = undefined;
|
|
148
|
+
void reportOnboardingStep({
|
|
149
|
+
phase: OnboardingPhase.FIRST_RUN,
|
|
150
|
+
step: STEP,
|
|
151
|
+
status: OnboardingStepStatus.COMPLETED,
|
|
152
|
+
offered: offer.offered,
|
|
153
|
+
nextFollowed: followed(offer, tool, args),
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
function followed(offer, tool, args) {
|
|
157
|
+
if (NextStepOffered.LEASE === offer.offered) {
|
|
158
|
+
return (ReticleTool.LEASE_ACQUIRE === tool ||
|
|
159
|
+
(ReticleTool.LEASE === tool && ACQUIRE === args['action']));
|
|
160
|
+
}
|
|
161
|
+
return offer.wired();
|
|
162
|
+
}
|
|
163
|
+
/** Tests only: forget an open offer. */
|
|
164
|
+
export function resetNextStepOffered() {
|
|
165
|
+
pending = undefined;
|
|
166
|
+
}
|
|
127
167
|
/** Looking: the tools that read the page without changing it. */
|
|
128
168
|
const LOOK_TOOLS = new Set([
|
|
129
169
|
ReticleTool.SNAPSHOT,
|
|
@@ -1,3 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The MCP proxy's session rollup.
|
|
3
|
+
*
|
|
4
|
+
* POST socket failures (`ENOBUFS`, `EMFILE`, `ECONNREFUSED` before any bytes were sent) happen in
|
|
5
|
+
* this process, not the daemon's. `tool_refused` never fires (the handler never ran) and
|
|
6
|
+
* `mcp_connection_lost` never fires (the SSE stream is fine). Counts live on SessionMetrics here
|
|
7
|
+
* and leave as one `session_progress` — an existing kind, omitted when nothing happened.
|
|
8
|
+
*
|
|
9
|
+
* The send is awaited. Fire-and-forget microseconds before `process.exit` is how `daemon_stopped`
|
|
10
|
+
* never arrived: the POST was killed every time and nothing threw.
|
|
11
|
+
*/
|
|
12
|
+
import { type ProxyExitReason, type WakeRefusalPresence } from '@reticlehq/core/telemetry';
|
|
1
13
|
import { type SessionMetrics } from './session-metrics.js';
|
|
2
14
|
import { type Telemetry } from './telemetry.js';
|
|
3
15
|
export declare function flushProxySessionMetrics(telemetry?: Telemetry, metrics?: SessionMetrics): Promise<void>;
|
|
16
|
+
/**
|
|
17
|
+
* This proxy process's id. The proxy sends it to the daemon on every connect, and the daemon puts
|
|
18
|
+
* it on `mcp_client_connected`. The proxy's own events carry it too, so an outage or an exit joins
|
|
19
|
+
* the daemon run it served. A random UUID for each process: it names nothing on the machine.
|
|
20
|
+
*/
|
|
21
|
+
export declare const PROXY_ID: `${string}-${string}-${string}-${string}-${string}`;
|
|
22
|
+
/** The proxy lost its daemon stream. */
|
|
23
|
+
export declare function noteProxyDrop(): void;
|
|
24
|
+
/** The client sent a `tools/call` through the proxy. */
|
|
25
|
+
export declare function noteProxyToolCall(): void;
|
|
26
|
+
/** Reset between tests. A real process reports each of these at most once. */
|
|
27
|
+
export declare function resetProxyExitReporting(): void;
|
|
28
|
+
/**
|
|
29
|
+
* Send `mcp_proxy_exited`, once per process. Awaited by the caller before it exits, because a send
|
|
30
|
+
* that is not awaited before `process.exit` does not arrive. `emit` bounds the send with its own
|
|
31
|
+
* timeout, and it never throws.
|
|
32
|
+
*
|
|
33
|
+
* Sent even when every count is zero: a proxy that left with nothing else to say is the case that
|
|
34
|
+
* was invisible.
|
|
35
|
+
*/
|
|
36
|
+
export declare function reportProxyExited(reason: ProxyExitReason, telemetry?: Telemetry, uptimeMs?: number): Promise<void>;
|
|
37
|
+
/** Everything the proxy sends on its way out. Awaited, then the caller exits. */
|
|
38
|
+
export declare function flushProxyExit(reason: ProxyExitReason): Promise<void>;
|
|
39
|
+
/** Send `daemon_died_unclean`. Fire-and-forget is fine for callers: the process lives on. */
|
|
40
|
+
export declare function reportDaemonDiedUnclean(ageMs: number, telemetry?: Telemetry): Promise<void>;
|
|
41
|
+
/**
|
|
42
|
+
* Send `wake_refused`, once per process. A dormant proxy refuses again on every client request, and
|
|
43
|
+
* one event per request would count the client's retries, not the refusal.
|
|
44
|
+
*/
|
|
45
|
+
export declare function reportWakeRefused(presence: WakeRefusalPresence, telemetry?: Telemetry): Promise<void>;
|
|
@@ -9,7 +9,8 @@
|
|
|
9
9
|
* The send is awaited. Fire-and-forget microseconds before `process.exit` is how `daemon_stopped`
|
|
10
10
|
* never arrived: the POST was killed every time and nothing threw.
|
|
11
11
|
*/
|
|
12
|
-
import { TelemetryEventKind } from '@reticlehq/core/telemetry';
|
|
12
|
+
import { TelemetryEventKind, } from '@reticlehq/core/telemetry';
|
|
13
|
+
import { randomUUID } from 'node:crypto';
|
|
13
14
|
import { getSessionMetrics } from './session-metrics.js';
|
|
14
15
|
import { getTelemetry } from './telemetry.js';
|
|
15
16
|
export async function flushProxySessionMetrics(telemetry = getTelemetry(), metrics = getSessionMetrics()) {
|
|
@@ -22,3 +23,71 @@ export async function flushProxySessionMetrics(telemetry = getTelemetry(), metri
|
|
|
22
23
|
session: metrics.summarize(false),
|
|
23
24
|
});
|
|
24
25
|
}
|
|
26
|
+
/**
|
|
27
|
+
* This proxy process's id. The proxy sends it to the daemon on every connect, and the daemon puts
|
|
28
|
+
* it on `mcp_client_connected`. The proxy's own events carry it too, so an outage or an exit joins
|
|
29
|
+
* the daemon run it served. A random UUID for each process: it names nothing on the machine.
|
|
30
|
+
*/
|
|
31
|
+
export const PROXY_ID = randomUUID();
|
|
32
|
+
/** What this proxy process saw in its life, for `mcp_proxy_exited`. One proxy per process. */
|
|
33
|
+
let drops = 0;
|
|
34
|
+
let toolCalls = 0;
|
|
35
|
+
let exitReported = false;
|
|
36
|
+
let wakeRefusalReported = false;
|
|
37
|
+
/** The proxy lost its daemon stream. */
|
|
38
|
+
export function noteProxyDrop() {
|
|
39
|
+
drops += 1;
|
|
40
|
+
}
|
|
41
|
+
/** The client sent a `tools/call` through the proxy. */
|
|
42
|
+
export function noteProxyToolCall() {
|
|
43
|
+
toolCalls += 1;
|
|
44
|
+
}
|
|
45
|
+
/** Reset between tests. A real process reports each of these at most once. */
|
|
46
|
+
export function resetProxyExitReporting() {
|
|
47
|
+
drops = 0;
|
|
48
|
+
toolCalls = 0;
|
|
49
|
+
exitReported = false;
|
|
50
|
+
wakeRefusalReported = false;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Send `mcp_proxy_exited`, once per process. Awaited by the caller before it exits, because a send
|
|
54
|
+
* that is not awaited before `process.exit` does not arrive. `emit` bounds the send with its own
|
|
55
|
+
* timeout, and it never throws.
|
|
56
|
+
*
|
|
57
|
+
* Sent even when every count is zero: a proxy that left with nothing else to say is the case that
|
|
58
|
+
* was invisible.
|
|
59
|
+
*/
|
|
60
|
+
export async function reportProxyExited(reason, telemetry = getTelemetry(),
|
|
61
|
+
// The process clock, read at this boundary: the proxy's uptime IS the process's.
|
|
62
|
+
uptimeMs = Math.round(process.uptime() * 1000)) {
|
|
63
|
+
if (exitReported) {
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
exitReported = true;
|
|
67
|
+
await telemetry.emit(TelemetryEventKind.MCP_PROXY_EXITED, {
|
|
68
|
+
proxyExit: { reason, uptimeMs, drops, toolCalls, proxyId: PROXY_ID },
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
/** Everything the proxy sends on its way out. Awaited, then the caller exits. */
|
|
72
|
+
export async function flushProxyExit(reason) {
|
|
73
|
+
await Promise.allSettled([flushProxySessionMetrics(), reportProxyExited(reason)]);
|
|
74
|
+
}
|
|
75
|
+
/** Send `daemon_died_unclean`. Fire-and-forget is fine for callers: the process lives on. */
|
|
76
|
+
export async function reportDaemonDiedUnclean(ageMs, telemetry = getTelemetry()) {
|
|
77
|
+
await telemetry.emit(TelemetryEventKind.DAEMON_DIED_UNCLEAN, {
|
|
78
|
+
daemonDeath: { ageMs: Math.max(0, Math.round(ageMs)) },
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Send `wake_refused`, once per process. A dormant proxy refuses again on every client request, and
|
|
83
|
+
* one event per request would count the client's retries, not the refusal.
|
|
84
|
+
*/
|
|
85
|
+
export async function reportWakeRefused(presence, telemetry = getTelemetry()) {
|
|
86
|
+
if (wakeRefusalReported) {
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
wakeRefusalReported = true;
|
|
90
|
+
await telemetry.emit(TelemetryEventKind.WAKE_REFUSED, {
|
|
91
|
+
wakeRefusal: { presence },
|
|
92
|
+
});
|
|
93
|
+
}
|
|
@@ -108,7 +108,7 @@ export declare class SessionMetrics {
|
|
|
108
108
|
* Zero of these at shutdown means the daemon ran and no app ever connected — a broken install.
|
|
109
109
|
* Non-zero with no tool calls is the opposite problem. See SessionSummary.appConnects.
|
|
110
110
|
*/
|
|
111
|
-
recordAppConnected(): void;
|
|
111
|
+
recordAppConnected(sdkVersion?: string): void;
|
|
112
112
|
/** One action driven at the page. Settled by the next verdict; see #unsettledActions. */
|
|
113
113
|
recordAction(): void;
|
|
114
114
|
recordVerification(): void;
|
|
@@ -146,8 +146,6 @@ export declare class SessionMetrics {
|
|
|
146
146
|
recordFeedbackPrompt(): void;
|
|
147
147
|
/** An agent was shown a platform or Harness advisory. */
|
|
148
148
|
recordNudge(kind: AgentNudgeKind): void;
|
|
149
|
-
/** A Harness drive was refused because the app's coverage is below the gate. */
|
|
150
|
-
recordHarnessRefused(percent: number): void;
|
|
151
149
|
/** Which tool surface was advertised to agents this session. */
|
|
152
150
|
recordSurface(surface: string): void;
|
|
153
151
|
/**
|