@reticlehq/server 2.3.0 → 2.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/SKILL.md +702 -0
- package/dist/bridge/auth-failure-reason.d.ts +19 -0
- package/dist/bridge/auth-failure-reason.js +29 -0
- package/dist/{bridge-security.d.ts → bridge/bridge-security.d.ts} +1 -1
- package/dist/{bridge-security.js → bridge/bridge-security.js} +1 -1
- package/dist/{bridge.d.ts → bridge/bridge.d.ts} +1 -1
- package/dist/{bridge.js → bridge/bridge.js} +105 -15
- package/dist/{bridge.test-harness.d.ts → bridge/bridge.test-harness.d.ts} +6 -11
- package/dist/{bridge.test-harness.js → bridge/bridge.test-harness.js} +21 -9
- package/dist/{pairing-token.js → bridge/pairing-token.js} +1 -1
- package/dist/capsule/capsule-store.d.ts +8 -3
- package/dist/capsule/capsule-store.js +7 -2
- package/dist/capsule/capsule.js +3 -3
- package/dist/capsule/causal-summary.d.ts +8 -0
- package/dist/capsule/causal-summary.js +22 -12
- package/dist/capsule/divergence.d.ts +9 -4
- package/dist/capsule/divergence.js +8 -8
- package/dist/capsule/predicate-to-links.js +11 -8
- package/dist/{cli-doctor.js → cli/cli-doctor.js} +9 -2
- package/dist/{cli-flow-commands.d.ts → cli/cli-flow-commands.d.ts} +2 -2
- package/dist/{cli-flow-commands.js → cli/cli-flow-commands.js} +15 -15
- package/dist/{cli-launch.d.ts → cli/cli-launch.d.ts} +32 -3
- package/dist/cli/cli-launch.js +171 -0
- package/dist/cli/cli-parse.d.ts +143 -0
- package/dist/{cli-parse.js → cli/cli-parse.js} +146 -65
- package/dist/{cli-port.d.ts → cli/cli-port.d.ts} +15 -0
- package/dist/{cli-port.js → cli/cli-port.js} +29 -8
- package/dist/cli/cli-update-commands.d.ts +4 -0
- package/dist/cli/cli-update-commands.js +93 -0
- package/dist/{cli-verify.js → cli/cli-verify.js} +14 -14
- package/dist/{cloud-cli.js → cli/cloud-cli.js} +29 -24
- package/dist/cli.d.ts +2 -2
- package/dist/cli.js +182 -93
- package/dist/cloud/cloud-config.d.ts +0 -1
- package/dist/cloud/cloud-config.js +9 -9
- package/dist/cloud/cloud-sync.d.ts +1 -7
- package/dist/cloud/cloud-sync.js +12 -12
- package/dist/crawl/crawl-empty.d.ts +16 -0
- package/dist/crawl/crawl-empty.js +24 -0
- package/dist/crawl/crawl-tools.js +4 -1
- package/dist/crawl/crawl.js +26 -7
- package/dist/daemon/daemon-resilience.d.ts +49 -0
- package/dist/daemon/daemon-resilience.js +191 -0
- package/dist/daemon/daemon-usefulness.d.ts +61 -0
- package/dist/daemon/daemon-usefulness.js +62 -0
- package/dist/{daemon.d.ts → daemon/daemon.d.ts} +33 -8
- package/dist/{daemon.js → daemon/daemon.js} +80 -48
- package/dist/daemon/idle-grace.d.ts +32 -0
- package/dist/daemon/idle-grace.js +41 -0
- package/dist/{idle-shutdown.d.ts → daemon/idle-shutdown.d.ts} +13 -0
- package/dist/{idle-shutdown.js → daemon/idle-shutdown.js} +27 -4
- package/dist/domain/domain-model.js +2 -2
- package/dist/events/body-failures.js +8 -8
- package/dist/events/contradictions.d.ts +1 -1
- package/dist/events/contradictions.js +60 -10
- package/dist/events/echo-mismatch.js +10 -10
- package/dist/events/event-filters.js +6 -6
- package/dist/events/json-salvage.d.ts +2 -1
- package/dist/events/json-salvage.js +6 -6
- package/dist/events/observed-in-window.d.ts +12 -0
- package/dist/events/observed-in-window.js +21 -0
- package/dist/events/predicate-eval.d.ts +43 -20
- package/dist/events/predicate-eval.js +159 -55
- package/dist/events/predicate.d.ts +2 -2
- package/dist/events/predicate.js +112 -35
- package/dist/events/reconcile.js +5 -5
- package/dist/events/ring-buffer.js +1 -1
- package/dist/events/stale-response.js +6 -6
- package/dist/events/testid-near-miss.d.ts +22 -0
- package/dist/events/testid-near-miss.js +33 -0
- package/dist/events/unit-mismatch.js +8 -8
- package/dist/flows/affected-tools.js +19 -4
- package/dist/flows/affected.js +1 -1
- package/dist/flows/annotate-target.d.ts +1 -0
- package/dist/flows/annotate-target.js +20 -0
- package/dist/flows/annotate-tools.js +25 -3
- package/dist/flows/annotate.js +17 -4
- package/dist/flows/assertion-integrity.d.ts +2 -1
- package/dist/flows/assertion-tiers-store.d.ts +3 -66
- package/dist/flows/assertion-tiers-store.js +2 -2
- package/dist/flows/attributed-failure.d.ts +17 -0
- package/dist/flows/attributed-failure.js +20 -0
- package/dist/flows/buddy-status.d.ts +2 -1
- package/dist/flows/buddy-status.js +2 -2
- package/dist/flows/coverage.d.ts +3 -2
- package/dist/flows/coverage.js +2 -2
- package/dist/flows/decision.d.ts +0 -6
- package/dist/flows/decision.js +64 -8
- package/dist/flows/empty-flow.d.ts +6 -0
- package/dist/flows/empty-flow.js +24 -0
- package/dist/flows/flake-store.d.ts +0 -1
- package/dist/flows/flake-store.js +1 -1
- package/dist/flows/flake.d.ts +2 -1
- package/dist/flows/flake.js +2 -2
- package/dist/flows/flow-classify.js +12 -0
- package/dist/flows/flow-replay-run.js +4 -4
- package/dist/flows/flow-replay.d.ts +5 -7
- package/dist/flows/flow-replay.js +114 -47
- package/dist/flows/flow-report.js +1 -1
- package/dist/flows/flow-scope.d.ts +1 -6
- package/dist/flows/flow-step-runners.d.ts +26 -6
- package/dist/flows/flow-step-runners.js +157 -6
- package/dist/flows/flow-success.js +20 -15
- package/dist/flows/flow-tools.js +67 -13
- package/dist/flows/flows.js +15 -11
- package/dist/flows/gate.d.ts +4 -3
- package/dist/flows/gate.js +1 -1
- package/dist/flows/heal-run.d.ts +0 -8
- package/dist/flows/heal-run.js +5 -5
- package/dist/flows/heal.js +3 -3
- package/dist/flows/predicate-to-expect.d.ts +38 -0
- package/dist/flows/predicate-to-expect.js +95 -0
- package/dist/flows/replay.d.ts +16 -1
- package/dist/flows/replay.js +58 -22
- package/dist/flows/role-anchor-nearest.d.ts +6 -0
- package/dist/flows/role-anchor-nearest.js +45 -0
- package/dist/flows/server-verify.d.ts +1 -1
- package/dist/flows/server-verify.js +5 -5
- package/dist/flows/verify-change-tools.js +32 -10
- package/dist/flows/verify-change-verdict.d.ts +15 -0
- package/dist/flows/verify-change-verdict.js +25 -0
- package/dist/flows/watch-batcher.d.ts +3 -2
- package/dist/honesty/already-true.d.ts +2 -0
- package/dist/honesty/already-true.js +31 -0
- package/dist/honesty/blind-spots.d.ts +16 -3
- package/dist/honesty/blind-spots.js +24 -12
- package/dist/honesty/honesty.d.ts +3 -2
- package/dist/honesty/honesty.js +4 -4
- package/dist/honesty/uncaptured-bodies.js +1 -1
- package/dist/honesty/unread-outcome.js +2 -2
- package/dist/honesty/verified.d.ts +22 -3
- package/dist/honesty/verified.js +48 -8
- package/dist/http-server.js +14 -7
- package/dist/hunt/hunt-report.d.ts +2 -1
- package/dist/hunt/hunt-report.js +2 -2
- package/dist/index.d.ts +8 -6
- package/dist/index.js +32 -25
- package/dist/init/agent-rules.d.ts +2 -1
- package/dist/init/agent-rules.js +45 -7
- package/dist/init/app-choice.d.ts +20 -0
- package/dist/init/app-choice.js +25 -0
- package/dist/init/astro-host.d.ts +21 -0
- package/dist/init/astro-host.js +27 -0
- package/dist/init/astro-patch.d.ts +16 -0
- package/dist/init/astro-patch.js +240 -0
- package/dist/init/capabilities.d.ts +17 -0
- package/dist/init/capabilities.js +54 -0
- package/dist/init/cra.d.ts +37 -0
- package/dist/init/cra.js +90 -0
- package/dist/init/cursor.js +39 -4
- package/dist/init/desktop-doctor.d.ts +3 -2
- package/dist/init/desktop-doctor.js +4 -4
- package/dist/init/detect.d.ts +26 -0
- package/dist/init/detect.js +78 -5
- package/dist/init/mcp-registered.d.ts +12 -0
- package/dist/init/mcp-registered.js +14 -0
- package/dist/init/mcp.d.ts +27 -2
- package/dist/init/mcp.js +40 -4
- package/dist/init/next-patch.d.ts +39 -0
- package/dist/init/next-patch.js +196 -0
- package/dist/init/node-io.js +48 -6
- package/dist/init/patch-kind.d.ts +20 -0
- package/dist/init/patch-kind.js +10 -0
- package/dist/init/plan-framework.d.ts +50 -0
- package/dist/init/plan-framework.js +341 -0
- package/dist/init/plan.d.ts +119 -6
- package/dist/init/plan.js +230 -131
- package/dist/init/project-id.d.ts +5 -9
- package/dist/init/project-id.js +10 -22
- package/dist/init/run.d.ts +22 -0
- package/dist/init/run.js +393 -28
- package/dist/init/slash-command.d.ts +27 -0
- package/dist/init/slash-command.js +61 -0
- package/dist/init/snippets.d.ts +41 -3
- package/dist/init/snippets.js +185 -10
- package/dist/init/vite-config.d.ts +4 -10
- package/dist/init/vite-config.js +15 -7
- package/dist/init/workspace-apps.d.ts +23 -0
- package/dist/init/workspace-apps.js +68 -0
- package/dist/input/driven-redaction.d.ts +15 -0
- package/dist/input/driven-redaction.js +76 -0
- package/dist/input/network-detail.d.ts +9 -3
- package/dist/input/network-detail.js +43 -23
- package/dist/input/network-mock-tools.js +2 -2
- package/dist/input/network-mock.js +4 -4
- package/dist/input/real-input.js +8 -3
- package/dist/input/scroll-find.js +2 -2
- package/dist/input/scroll-tools.d.ts +0 -5
- package/dist/input/scroll-tools.js +11 -4
- package/dist/input/viewport-tools.js +2 -2
- package/dist/journal/ambient-store.d.ts +0 -2
- package/dist/journal/ambient-store.js +1 -1
- package/dist/journal/ambient.js +1 -1
- package/dist/journal/attach-journal.d.ts +2 -1
- package/dist/journal/deviation-report.js +6 -6
- package/dist/journal/deviation-service.js +1 -1
- package/dist/journal/envelope-store.d.ts +0 -2
- package/dist/journal/envelope-store.js +1 -1
- package/dist/journal/envelope.d.ts +2 -3
- package/dist/journal/envelope.js +3 -3
- package/dist/journal/journal-query.js +1 -1
- package/dist/journal/journal-recorder.d.ts +2 -1
- package/dist/journal/journal-recorder.js +2 -2
- package/dist/journal/rollups.js +9 -9
- package/dist/journal/session-end.d.ts +2 -1
- package/dist/journal/session-journal.js +4 -4
- package/dist/license/license.d.ts +0 -14
- package/dist/license/license.js +8 -8
- package/dist/log.d.ts +10 -0
- package/dist/log.js +11 -1
- package/dist/mcp/mcp-is-error.d.ts +13 -0
- package/dist/mcp/mcp-is-error.js +18 -0
- package/dist/mcp/mcp-outage.d.ts +31 -0
- package/dist/mcp/mcp-outage.js +48 -0
- package/dist/mcp/mcp-proxy.d.ts +124 -0
- package/dist/mcp/mcp-proxy.js +697 -0
- package/dist/{mcp.d.ts → mcp/mcp.d.ts} +13 -10
- package/dist/{mcp.js → mcp/mcp.js} +110 -35
- package/dist/mcp/proxy-handshake.d.ts +3 -0
- package/dist/mcp/proxy-handshake.js +54 -0
- package/dist/mcp/proxy-lifecycle.d.ts +64 -0
- package/dist/mcp/proxy-lifecycle.js +70 -0
- package/dist/mcp/tool-catalog-cache.d.ts +29 -0
- package/dist/mcp/tool-catalog-cache.js +55 -0
- package/dist/oracles/propose-consequences.d.ts +2 -1
- package/dist/oracles/propose-consequences.js +16 -11
- package/dist/oracles/self-instrument.d.ts +2 -1
- package/dist/oracles/self-instrument.js +1 -1
- package/dist/phenomena/phenomena.js +3 -3
- package/dist/platform.d.ts +16 -0
- package/dist/platform.js +16 -0
- package/dist/pool/playwright-launcher.d.ts +15 -2
- package/dist/pool/playwright-launcher.js +21 -2
- package/dist/project/fs-port.js +1 -1
- package/dist/project/project-tools.js +2 -2
- package/dist/runs/build-verification-run.js +1 -1
- package/dist/runs/repair-prompt.d.ts +0 -6
- package/dist/runs/repair-prompt.js +3 -3
- package/dist/runs/risk-classify.js +1 -1
- package/dist/runs/run-diff.d.ts +0 -2
- package/dist/runs/run-diff.js +3 -3
- package/dist/runs/run-tools.js +2 -2
- package/dist/runs/verification-sync.js +2 -2
- package/dist/runs/verify-http.js +1 -1
- package/dist/runs/verify-server.js +1 -1
- package/dist/session/command-timeout.d.ts +11 -3
- package/dist/session/command-timeout.js +2 -2
- package/dist/session/control-envelope.d.ts +6 -0
- package/dist/session/control-envelope.js +7 -1
- package/dist/session/dev-server-probe.d.ts +13 -0
- package/dist/session/dev-server-probe.js +52 -0
- package/dist/session/last-act.d.ts +17 -3
- package/dist/session/last-act.js +16 -4
- package/dist/session/live-control-tools.js +7 -2
- package/dist/session/live-control.js +1 -1
- package/dist/session/looks-like-dev-server.d.ts +14 -0
- package/dist/session/looks-like-dev-server.js +25 -0
- package/dist/session/no-session-diagnosis.d.ts +38 -0
- package/dist/session/no-session-diagnosis.js +70 -0
- package/dist/session/no-session-watch.d.ts +19 -0
- package/dist/session/no-session-watch.js +61 -0
- package/dist/session/observed-state.d.ts +4 -0
- package/dist/session/observed-state.js +19 -1
- package/dist/session/output-budget.js +1 -1
- package/dist/session/session-health.d.ts +8 -1
- package/dist/session/session-health.js +8 -7
- package/dist/session/session-info.d.ts +26 -7
- package/dist/session/session-info.js +42 -1
- package/dist/session/session-lease.d.ts +0 -11
- package/dist/session/session-lease.js +1 -1
- package/dist/session/session-manager.d.ts +3 -0
- package/dist/session/session-manager.js +58 -9
- package/dist/session/session-readiness.d.ts +1 -1
- package/dist/session/session-readiness.js +6 -1
- package/dist/session/session-reaper.js +1 -1
- package/dist/session/session-reconnect.d.ts +32 -0
- package/dist/session/session-reconnect.js +42 -0
- package/dist/session/session.d.ts +20 -2
- package/dist/session/session.js +76 -26
- package/dist/session/state-select.d.ts +1 -1
- package/dist/session/state-select.js +1 -1
- package/dist/status-payload.d.ts +19 -0
- package/dist/status-payload.js +11 -0
- package/dist/telemetry/argument-shape.js +10 -1
- package/dist/telemetry/browser-mode.d.ts +27 -0
- package/dist/telemetry/browser-mode.js +33 -0
- package/dist/telemetry/bug-found.d.ts +17 -21
- package/dist/telemetry/bug-found.js +120 -8
- package/dist/telemetry/cli-telemetry.d.ts +2 -12
- package/dist/telemetry/cli-telemetry.js +27 -4
- package/dist/telemetry/daemon-telemetry.d.ts +19 -0
- package/dist/telemetry/daemon-telemetry.js +12 -2
- package/dist/telemetry/dev-repo.js +4 -4
- package/dist/telemetry/error-fingerprint.js +21 -2
- package/dist/telemetry/feedback-cli.d.ts +1 -1
- package/dist/telemetry/feedback-cli.js +4 -4
- package/dist/telemetry/feedback-context.d.ts +22 -0
- package/dist/telemetry/feedback-context.js +41 -1
- package/dist/telemetry/feedback-delivery.d.ts +20 -0
- package/dist/telemetry/feedback-delivery.js +30 -0
- package/dist/telemetry/feedback-outbox.d.ts +22 -0
- package/dist/telemetry/feedback-outbox.js +87 -0
- package/dist/telemetry/feedback.d.ts +22 -1
- package/dist/telemetry/feedback.js +67 -8
- package/dist/telemetry/git-facts.js +1 -1
- package/dist/telemetry/session-metrics.d.ts +2 -0
- package/dist/telemetry/session-metrics.js +68 -6
- package/dist/telemetry/telemetry.d.ts +27 -2
- package/dist/telemetry/telemetry.js +119 -29
- package/dist/telemetry/verification-of.d.ts +22 -0
- package/dist/telemetry/verification-of.js +84 -0
- package/dist/tools/act-capsule.js +2 -2
- package/dist/tools/act-danger.d.ts +12 -0
- package/dist/tools/act-danger.js +20 -3
- package/dist/tools/act-helpers.js +4 -4
- package/dist/tools/act-tools.d.ts +0 -8
- package/dist/tools/act-tools.js +84 -115
- package/dist/tools/act-view.js +7 -7
- package/dist/tools/alias-args.d.ts +17 -0
- package/dist/tools/alias-args.js +25 -0
- package/dist/tools/assert-grade.js +9 -9
- package/dist/tools/assert-verdict.d.ts +3 -1
- package/dist/tools/assert-verdict.js +8 -5
- package/dist/tools/browser-tools.js +30 -11
- package/dist/tools/contract-tools.js +1 -1
- package/dist/tools/coverage-identity.d.ts +34 -0
- package/dist/tools/coverage-identity.js +46 -0
- package/dist/tools/coverage-tools.js +10 -14
- package/dist/tools/dynamic-tools.d.ts +2 -1
- package/dist/tools/dynamic-tools.js +90 -18
- package/dist/tools/error-recovery.d.ts +20 -2
- package/dist/tools/error-recovery.js +179 -4
- package/dist/tools/feedback-tools.d.ts +12 -1
- package/dist/tools/feedback-tools.js +28 -5
- package/dist/tools/invoke-tool.d.ts +0 -6
- package/dist/tools/invoke-tool.js +57 -32
- package/dist/tools/lease-hint.d.ts +17 -0
- package/dist/tools/lease-hint.js +24 -0
- package/dist/tools/lease-tools.js +6 -5
- package/dist/tools/merge-tools.d.ts +10 -1
- package/dist/tools/merge-tools.js +9 -3
- package/dist/tools/merged-name-redirect.d.ts +13 -0
- package/dist/tools/merged-name-redirect.js +55 -0
- package/dist/tools/navigate-result.d.ts +17 -0
- package/dist/tools/navigate-result.js +31 -0
- package/dist/tools/observe-tools.js +54 -20
- package/dist/tools/observed-nothing.d.ts +25 -0
- package/dist/tools/observed-nothing.js +33 -0
- package/dist/tools/query-paginate.js +2 -2
- package/dist/tools/query-shape.d.ts +18 -0
- package/dist/tools/query-shape.js +39 -0
- package/dist/tools/read-tools.js +85 -20
- package/dist/tools/real-input-attempt.d.ts +28 -0
- package/dist/tools/real-input-attempt.js +88 -0
- package/dist/tools/reconcile-tools.js +7 -7
- package/dist/tools/reload-result.d.ts +14 -0
- package/dist/tools/reload-result.js +29 -0
- package/dist/tools/snapshot-delta.d.ts +4 -5
- package/dist/tools/snapshot-delta.js +0 -0
- package/dist/tools/tool-kit.d.ts +8 -0
- package/dist/tools/tool-surface.d.ts +83 -0
- package/dist/tools/tool-surface.js +204 -0
- package/dist/tools/tools-helpers.js +6 -6
- package/dist/tools/tools.d.ts +15 -0
- package/dist/tools/tools.js +53 -17
- package/dist/tools/unadvertised-help.d.ts +5 -0
- package/dist/tools/unadvertised-help.js +39 -0
- package/dist/trace.d.ts +69 -0
- package/dist/trace.js +150 -0
- package/dist/update/nudge-credit.d.ts +4 -0
- package/dist/update/nudge-credit.js +53 -0
- package/dist/update/sdk-sync.d.ts +21 -0
- package/dist/update/sdk-sync.js +42 -0
- package/dist/update/update-checker.js +3 -3
- package/dist/update/update-nudge.d.ts +63 -6
- package/dist/update/update-nudge.js +128 -15
- package/dist/update/updater.d.ts +1 -9
- package/dist/update/updater.js +13 -8
- package/dist/version/peer-announce.d.ts +4 -0
- package/dist/version/peer-announce.js +30 -0
- package/dist/{server-version.js → version/server-version.js} +5 -1
- package/dist/version/version-nudge.d.ts +28 -0
- package/dist/version/version-nudge.js +40 -0
- package/dist/version/version-skew.d.ts +66 -0
- package/dist/version/version-skew.js +71 -0
- package/dist/visual/visual-diff.js +2 -2
- package/dist/visual/visual-tools.js +4 -4
- package/docs/agent-cheatsheet.md +85 -0
- package/docs/architecture.md +113 -0
- package/docs/benchmarks.md +255 -0
- package/docs/debugging.md +102 -0
- package/docs/deploy-checks.md +69 -0
- package/docs/desktop-apps.md +256 -0
- package/docs/enterprise.md +62 -0
- package/docs/fixtures.md +28 -0
- package/docs/flows.md +166 -0
- package/docs/getting-started.md +469 -0
- package/docs/human-control.md +63 -0
- package/docs/integration-patterns.md +171 -0
- package/docs/local-registry.md +126 -0
- package/docs/mint.json +61 -0
- package/docs/multi-agent-testing.md +55 -0
- package/docs/platform-integration.md +122 -0
- package/docs/telemetry-contract.md +214 -0
- package/docs/telemetry.md +184 -0
- package/docs/testing.md +82 -0
- package/docs/token-efficiency.md +80 -0
- package/docs/usage.md +1046 -0
- package/package.json +8 -5
- package/dist/cli-launch.js +0 -112
- package/dist/cli-parse.d.ts +0 -140
- package/dist/daemon-resilience.d.ts +0 -22
- package/dist/daemon-resilience.js +0 -85
- package/dist/mcp-proxy.d.ts +0 -35
- package/dist/mcp-proxy.js +0 -190
- package/dist/tools/profiles.d.ts +0 -37
- package/dist/tools/profiles.js +0 -139
- /package/dist/{pairing-token.d.ts → bridge/pairing-token.d.ts} +0 -0
- /package/dist/{token-auth.d.ts → bridge/token-auth.d.ts} +0 -0
- /package/dist/{token-auth.js → bridge/token-auth.js} +0 -0
- /package/dist/{cli-doctor.d.ts → cli/cli-doctor.d.ts} +0 -0
- /package/dist/{cli-verify.d.ts → cli/cli-verify.d.ts} +0 -0
- /package/dist/{cloud-cli.d.ts → cli/cloud-cli.d.ts} +0 -0
- /package/dist/{server-version.d.ts → version/server-version.d.ts} +0 -0
|
@@ -30,6 +30,9 @@ function sessionFacts(deps, sessionId) {
|
|
|
30
30
|
return {
|
|
31
31
|
...(session.runtime !== undefined ? { runtime: session.runtime } : {}),
|
|
32
32
|
...(session.engine !== undefined ? { engine: session.engine } : {}),
|
|
33
|
+
// The app's own account of what it is. Without this the reported stack came from the daemon's
|
|
34
|
+
// working directory, so feedback from one app was filed against another's framework.
|
|
35
|
+
...(0 < session.adapters.length ? { adapters: session.adapters } : {}),
|
|
33
36
|
driven,
|
|
34
37
|
};
|
|
35
38
|
}
|
|
@@ -83,7 +86,10 @@ export const FEEDBACK_TOOLS = [
|
|
|
83
86
|
.describe('Only to attach a specific tab s runtime/engine context. Omit it — a report about a session that never connected is still worth filing.'),
|
|
84
87
|
},
|
|
85
88
|
outputSchema: {
|
|
89
|
+
/** Confirmed delivery. Always false here: the agent path queues and returns. */
|
|
86
90
|
sent: z.boolean(),
|
|
91
|
+
/** Validated, redacted and queued. This is the one to read. */
|
|
92
|
+
accepted: z.boolean(),
|
|
87
93
|
reason: z.string().optional(),
|
|
88
94
|
redacted: z.array(z.string()),
|
|
89
95
|
context: z.unknown(),
|
|
@@ -106,12 +112,17 @@ export const FEEDBACK_TOOLS = [
|
|
|
106
112
|
...optionalText(args, 'impact'),
|
|
107
113
|
...optionalText(args, 'currentApproach'),
|
|
108
114
|
...optionalText(args, 'model'),
|
|
109
|
-
}, {
|
|
115
|
+
}, {
|
|
116
|
+
session: sessionFacts(deps, asString(args['sessionId'])),
|
|
117
|
+
// The AGENT does not wait for the network. `reticle feedback` (a human, at a terminal,
|
|
118
|
+
// watching for an answer) still does — see submitFeedback's `background`.
|
|
119
|
+
background: true,
|
|
120
|
+
});
|
|
110
121
|
return {
|
|
111
122
|
...receipt,
|
|
112
|
-
note: receipt.
|
|
113
|
-
? '
|
|
114
|
-
: 'NOT
|
|
123
|
+
note: receipt.accepted
|
|
124
|
+
? 'Accepted — thank you. It sends in the background so you are not kept waiting; if it fails you will be told on a later tool result. Continue your task; do not retry a failing call just to re-report it.'
|
|
125
|
+
: 'NOT accepted (see reason). Tell the human what you found so it is not lost.',
|
|
115
126
|
};
|
|
116
127
|
},
|
|
117
128
|
},
|
|
@@ -128,8 +139,20 @@ export const FEEDBACK_PROMPT = {
|
|
|
128
139
|
ask: 'Ask the human, in your own words and only once: how did this verification go, and what would have made Reticle more useful? If they answer, file it with `reticle feedback` (they run it) or relay it yourself.',
|
|
129
140
|
command: 'reticle feedback',
|
|
130
141
|
};
|
|
131
|
-
/**
|
|
142
|
+
/**
|
|
143
|
+
* Tools whose completion means "a verification just happened" — the only moment worth asking at,
|
|
144
|
+
* and the set that decides what `verification_completed` counts.
|
|
145
|
+
*
|
|
146
|
+
* ACT_AND_WAIT belongs here and was missing for a long time. It declares `verified` in its
|
|
147
|
+
* outputSchema, returns the whole verdict block, and its own description calls it "one hop for the
|
|
148
|
+
* act->observe->assert loop" — it IS the verification path most agents take. The guard that should
|
|
149
|
+
* have caught the omission keyed on the tool NAME (/assert|verify/), which act_and_wait does not
|
|
150
|
+
* match, so it slipped through in silence. Measured over a day of real telemetry: act_and_wait 14
|
|
151
|
+
* calls, assert ZERO, verification_completed 2. Agents were verifying the entire time and the metric
|
|
152
|
+
* could not see it. The contract test now checks the SHAPE instead.
|
|
153
|
+
*/
|
|
132
154
|
export const VERIFICATION_TOOLS = new Set([
|
|
155
|
+
ReticleTool.ACT_AND_WAIT,
|
|
133
156
|
ReticleTool.ASSERT,
|
|
134
157
|
ReticleTool.FLOW_VERIFY,
|
|
135
158
|
ReticleTool.VERIFY_CHANGE,
|
|
@@ -1,10 +1,4 @@
|
|
|
1
1
|
import type { ToolDef, ToolDeps } from './tools.js';
|
|
2
|
-
/**
|
|
3
|
-
* The live-session tools whose result MUST carry the
|
|
4
|
-
* session-health envelope. Owned in ONE place — not retrofitted per handler — so a throttled tab
|
|
5
|
-
* can never return a healthy-looking result from any of these. `runTool` is the single choke point
|
|
6
|
-
* (mcp.ts + tool-invoker.ts) that splices health on; the guard test asserts the set is exhaustive.
|
|
7
|
-
*/
|
|
8
2
|
export declare const SESSION_BOUND_TOOLS: ReadonlySet<string>;
|
|
9
3
|
/**
|
|
10
4
|
* Tools that carry a `sessionId` arg but are NOT live-session-health tools — they read/write
|
|
@@ -2,18 +2,32 @@ import { healthEnvelope } from '../session/session-health.js';
|
|
|
2
2
|
import { TelemetryActor, TelemetryEventKind } from '@reticlehq/core';
|
|
3
3
|
import { getSessionMetrics } from '../telemetry/session-metrics.js';
|
|
4
4
|
import { getTelemetry } from '../telemetry/telemetry.js';
|
|
5
|
-
import { VERIFICATION_TOOLS } from './feedback-tools.js';
|
|
6
5
|
import { takeUpdateNudge } from '../update/update-nudge.js';
|
|
6
|
+
import { takeVersionSkew } from '../version/version-nudge.js';
|
|
7
|
+
import { noteToolCall } from '../daemon/daemon-usefulness.js';
|
|
7
8
|
import { bugsInResult } from '../telemetry/bug-found.js';
|
|
9
|
+
import { verificationOf } from '../telemetry/verification-of.js';
|
|
8
10
|
import { asString } from './tools-helpers.js';
|
|
9
11
|
import { ReticleTool } from './tool-names.js';
|
|
10
12
|
import { takeFeedbackPrompt } from './feedback-tools.js';
|
|
13
|
+
import { takeFeedbackUndelivered } from '../telemetry/feedback-delivery.js';
|
|
14
|
+
import { span } from '../trace.js';
|
|
11
15
|
/**
|
|
12
16
|
* The live-session tools whose result MUST carry the
|
|
13
17
|
* session-health envelope. Owned in ONE place — not retrofitted per handler — so a throttled tab
|
|
14
18
|
* can never return a healthy-looking result from any of these. `runTool` is the single choke point
|
|
15
19
|
* (mcp.ts + tool-invoker.ts) that splices health on; the guard test asserts the set is exhaustive.
|
|
16
20
|
*/
|
|
21
|
+
/**
|
|
22
|
+
* Tools that DRIVE the page. An action with no verdict after it is the signature of the loop
|
|
23
|
+
* breaking mid-task — see `abandonedActions`. `act_and_wait` is one of these AND a verification, so
|
|
24
|
+
* it settles its own action, which is exactly right: it is the tool that does both.
|
|
25
|
+
*/
|
|
26
|
+
const ACTION_TOOLS = new Set([
|
|
27
|
+
ReticleTool.ACT,
|
|
28
|
+
ReticleTool.ACT_SEQUENCE,
|
|
29
|
+
ReticleTool.ACT_AND_WAIT,
|
|
30
|
+
]);
|
|
17
31
|
export const SESSION_BOUND_TOOLS = new Set([
|
|
18
32
|
ReticleTool.SNAPSHOT,
|
|
19
33
|
ReticleTool.QUERY,
|
|
@@ -72,44 +86,27 @@ export const SESSION_EXEMPT_TOOLS = new Set([
|
|
|
72
86
|
ReticleTool.FEEDBACK,
|
|
73
87
|
]);
|
|
74
88
|
function isPlainObject(value) {
|
|
75
|
-
return typeof value
|
|
89
|
+
return 'object' === typeof value && value !== null && !Array.isArray(value);
|
|
76
90
|
}
|
|
77
91
|
/**
|
|
78
92
|
* Emit `verification_completed` when a verification tool produced a verdict.
|
|
79
93
|
*
|
|
80
94
|
* Read off the RESULT here rather than emitted from `decideVerified`, which is where the verdict is
|
|
81
95
|
* actually decided: that function is pure, and the repo's rules keep clocks, IO and side effects out
|
|
82
|
-
* of pure logic for good reason. Reading the result also means all
|
|
83
|
-
* by one site instead of
|
|
96
|
+
* of pure logic for good reason. Reading the result also means all the verification tools are covered
|
|
97
|
+
* by one site instead of N handler edits, and the next one is covered the moment it joins the set.
|
|
84
98
|
*
|
|
85
|
-
*
|
|
86
|
-
*
|
|
87
|
-
* putting in front of an investor — not "tools were called" but "this many greens were caught lying".
|
|
99
|
+
* The RULE itself lives in verification-of.ts, because getting it wrong is silent and it feeds the
|
|
100
|
+
* one number shown to investors — see that file for the two ways it was wrong.
|
|
88
101
|
*/
|
|
89
|
-
function recordVerification(toolName, result, durationMs) {
|
|
90
|
-
|
|
102
|
+
function recordVerification(toolName, result, durationMs, brand) {
|
|
103
|
+
const verification = verificationOf(toolName, result, durationMs, brand);
|
|
104
|
+
if (verification === undefined)
|
|
91
105
|
return;
|
|
92
|
-
|
|
93
|
-
// flow_verify reports `status: pass|fail`; assert reports a boolean `pass`. Accept either shape so
|
|
94
|
-
// the whole family is covered without normalizing four tools' contracts for a metric's convenience.
|
|
95
|
-
const passed = typeof result['pass'] === 'boolean'
|
|
96
|
-
? result['pass']
|
|
97
|
-
: result['status'] === 'pass'
|
|
98
|
-
? true
|
|
99
|
-
: undefined;
|
|
100
|
-
if (verified === undefined && passed === undefined)
|
|
101
|
-
return; // not a verdict-bearing result
|
|
102
|
-
const metrics = getSessionMetrics();
|
|
103
|
-
metrics.recordVerification();
|
|
106
|
+
getSessionMetrics().recordVerification();
|
|
104
107
|
void getTelemetry().emit(TelemetryEventKind.VERIFICATION_COMPLETED, {
|
|
105
108
|
actor: TelemetryActor.AGENT,
|
|
106
|
-
verification
|
|
107
|
-
via: toolName,
|
|
108
|
-
verified: verified ?? (passed === true ? 'yes' : 'no'),
|
|
109
|
-
passed: passed ?? verified === 'yes',
|
|
110
|
-
falseGreenCaught: passed === true && verified === 'no',
|
|
111
|
-
durationMs,
|
|
112
|
-
},
|
|
109
|
+
verification,
|
|
113
110
|
});
|
|
114
111
|
}
|
|
115
112
|
/**
|
|
@@ -121,7 +118,7 @@ function recordVerification(toolName, result, durationMs) {
|
|
|
121
118
|
*/
|
|
122
119
|
function reportBugsFound(toolName, result) {
|
|
123
120
|
const bugs = bugsInResult(toolName, result);
|
|
124
|
-
if (bugs.length
|
|
121
|
+
if (0 === bugs.length)
|
|
125
122
|
return;
|
|
126
123
|
const metrics = getSessionMetrics();
|
|
127
124
|
for (const bug of bugs) {
|
|
@@ -151,6 +148,12 @@ export async function runTool(tool, deps, args) {
|
|
|
151
148
|
// Started/settled as a pair rather than a bare counter: several agents can be inside runTool at
|
|
152
149
|
// once, so a single "last start" field would attribute one tool's duration to another. The returned
|
|
153
150
|
// closure carries this call's own identity, which is also what makes peak-concurrency measurable.
|
|
151
|
+
// A daemon that has served even one tool call is doing a job for somebody; see daemon-usefulness.
|
|
152
|
+
noteToolCall();
|
|
153
|
+
// An ACTION is what gets abandoned. Counted here, against verifications, so "the agent drove the
|
|
154
|
+
// page and then wandered off" becomes a number instead of an impression.
|
|
155
|
+
if (ACTION_TOOLS.has(tool.name))
|
|
156
|
+
getSessionMetrics().recordAction();
|
|
154
157
|
const settleTiming = getSessionMetrics().startToolCall(tool.name, args);
|
|
155
158
|
const startedAt = Date.now();
|
|
156
159
|
const rawSessionId = asString(args['sessionId']);
|
|
@@ -175,7 +178,10 @@ export async function runTool(tool, deps, args) {
|
|
|
175
178
|
deps.pool?.touch(leaseId);
|
|
176
179
|
let raw;
|
|
177
180
|
try {
|
|
178
|
-
|
|
181
|
+
// The one dispatch point every tool call passes through, so it is where the trace's root span
|
|
182
|
+
// belongs: with RETICLE_TRACE on, every stage that runs underneath inherits this call's id and
|
|
183
|
+
// nests under it. Free when off — see trace.ts.
|
|
184
|
+
raw = await span('tool.handler', { tool: tool.name, session: session?.id }, () => tool.handler(deps, args));
|
|
179
185
|
}
|
|
180
186
|
finally {
|
|
181
187
|
// In a `finally` so a THROWN call still settles: otherwise every failing tool would leak a
|
|
@@ -187,7 +193,10 @@ export async function runTool(tool, deps, args) {
|
|
|
187
193
|
// session-bound early return, because two of the four verification tools (flow_verify,
|
|
188
194
|
// verify_change) are session-EXEMPT and would otherwise never carry it.
|
|
189
195
|
if (isPlainObject(raw)) {
|
|
190
|
-
|
|
196
|
+
// The brand comes from the session's own PAGE_HEALTH report, so it is present for the four
|
|
197
|
+
// session-bound verification tools and absent for flow_verify (session-exempt) — which replays
|
|
198
|
+
// into a browser Reticle launched, where `browser` already says what happened.
|
|
199
|
+
recordVerification(tool.name, raw, Date.now() - startedAt, session?.brand);
|
|
191
200
|
reportBugsFound(tool.name, raw);
|
|
192
201
|
}
|
|
193
202
|
const prompt = isPlainObject(raw) ? takeFeedbackPrompt(tool.name) : undefined;
|
|
@@ -195,12 +204,28 @@ export async function runTool(tool, deps, args) {
|
|
|
195
204
|
// and ASK for is something it will never ask for. Spliced on ANY tool result, not just a
|
|
196
205
|
// verification, because an out-of-date install is worth mentioning whatever the agent is doing.
|
|
197
206
|
const update = isPlainObject(raw) ? takeUpdateNudge() : undefined;
|
|
198
|
-
|
|
207
|
+
// Same one-shot channel, for the same reason. Skew was only ever reported in
|
|
208
|
+
// reticle_sessions.versionSkew and a CLI log line — two places an agent driving a flow never
|
|
209
|
+
// looks — so it could work a whole session against a mismatched pair and never learn the one fact
|
|
210
|
+
// that explains the behaviour. It rides out here on whatever tool it happens to be calling.
|
|
211
|
+
const skew = isPlainObject(raw) ? takeVersionSkew() : undefined;
|
|
212
|
+
// A feedback report that was accepted and then failed to send. Same one-shot channel, because the
|
|
213
|
+
// reporter is the only person who can act on it and they are not reading the daemon log — and a
|
|
214
|
+
// report announced as accepted and then silently lost is the failure the awaited send existed to
|
|
215
|
+
// prevent. See feedback-delivery.ts.
|
|
216
|
+
const undelivered = isPlainObject(raw) ? takeFeedbackUndelivered() : undefined;
|
|
217
|
+
const result = prompt === undefined && update === undefined && skew === undefined && undelivered === undefined
|
|
199
218
|
? raw
|
|
200
219
|
: {
|
|
201
220
|
...raw,
|
|
202
221
|
...(prompt !== undefined ? { feedback_prompt: prompt } : {}),
|
|
203
222
|
...(update !== undefined ? { update_available: update } : {}),
|
|
223
|
+
...(skew !== undefined ? { version_skew: skew } : {}),
|
|
224
|
+
...(undelivered !== undefined
|
|
225
|
+
? {
|
|
226
|
+
feedback_undelivered: `your earlier report did NOT send: ${undelivered}. Tell the human what you found so it is not lost.`,
|
|
227
|
+
}
|
|
228
|
+
: {}),
|
|
204
229
|
};
|
|
205
230
|
if (!bound || !isPlainObject(result))
|
|
206
231
|
return result;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Why a leased tab did not dial in.
|
|
3
|
+
*
|
|
4
|
+
* The lease pool opens the app itself, which is what makes it the highest-value path in the product
|
|
5
|
+
* — it does not wait for the human's tab. Measured over a day: lease sessions had a median of 30
|
|
6
|
+
* tool calls and produced 46% of all bugs found, against a median of 1 call for everything else.
|
|
7
|
+
*
|
|
8
|
+
* When it fails it is almost always a PORT MISMATCH: the tab loads, and the app's SDK dials the port
|
|
9
|
+
* it was BUILT with, which need not be the daemon that issued the lease. Verified by driving it —
|
|
10
|
+
* against a matching daemon `acquire` returns ready:true and the session is driveable immediately;
|
|
11
|
+
* against a different one the tab connects to the OTHER daemon instead.
|
|
12
|
+
*
|
|
13
|
+
* The old hint asked "is <url> running with @reticlehq/core enabled?", which is the one thing that
|
|
14
|
+
* cannot be in doubt: the pool just navigated a real browser to it. Naming the true cause first is
|
|
15
|
+
* the difference between a two-minute fix and abandoning the best path Reticle has.
|
|
16
|
+
*/
|
|
17
|
+
export declare function leaseNotConnectedHint(url: string, port: number): string;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Why a leased tab did not dial in.
|
|
3
|
+
*
|
|
4
|
+
* The lease pool opens the app itself, which is what makes it the highest-value path in the product
|
|
5
|
+
* — it does not wait for the human's tab. Measured over a day: lease sessions had a median of 30
|
|
6
|
+
* tool calls and produced 46% of all bugs found, against a median of 1 call for everything else.
|
|
7
|
+
*
|
|
8
|
+
* When it fails it is almost always a PORT MISMATCH: the tab loads, and the app's SDK dials the port
|
|
9
|
+
* it was BUILT with, which need not be the daemon that issued the lease. Verified by driving it —
|
|
10
|
+
* against a matching daemon `acquire` returns ready:true and the session is driveable immediately;
|
|
11
|
+
* against a different one the tab connects to the OTHER daemon instead.
|
|
12
|
+
*
|
|
13
|
+
* The old hint asked "is <url> running with @reticlehq/core enabled?", which is the one thing that
|
|
14
|
+
* cannot be in doubt: the pool just navigated a real browser to it. Naming the true cause first is
|
|
15
|
+
* the difference between a two-minute fix and abandoning the best path Reticle has.
|
|
16
|
+
*/
|
|
17
|
+
export function leaseNotConnectedHint(url, port) {
|
|
18
|
+
return (`the leased tab loaded ${url} but never dialled this daemon (port ${String(port)}). The usual ` +
|
|
19
|
+
`cause is a PORT MISMATCH: the app's SDK connects to the port it was BUILT with, so a daemon on ` +
|
|
20
|
+
`a different port never hears from it — check the app's reticle port (\`.reticle.json\`, ` +
|
|
21
|
+
`RETICLE_PORT, or the build plugin's \`port\`) matches ${String(port)}, or start the daemon on ` +
|
|
22
|
+
`the port the app expects. If the app carries no Reticle SDK at all, run \`reticle init\` in it ` +
|
|
23
|
+
`first. The tab stays leased either way — release it with reticle_lease{action:"release"}.`);
|
|
24
|
+
}
|
|
@@ -9,7 +9,8 @@
|
|
|
9
9
|
* Attach-only: the pool drives a browser against an already-running dev server — it never starts one.
|
|
10
10
|
*/
|
|
11
11
|
import { z } from 'zod';
|
|
12
|
-
import {
|
|
12
|
+
import { leaseNotConnectedHint } from './lease-hint.js';
|
|
13
|
+
import { RETICLE_URL_PARAM, RETICLE_DEFAULT_PORT } from '@reticlehq/core';
|
|
13
14
|
import { ReticleTool } from './tool-names.js';
|
|
14
15
|
import { asString } from './tools-helpers.js';
|
|
15
16
|
const POOL_UNAVAILABLE = 'browser pool unavailable — the lease tools need the daemon-managed pool (start Reticle via `reticle mcp`).';
|
|
@@ -58,7 +59,7 @@ export function cleanNavError(err) {
|
|
|
58
59
|
}
|
|
59
60
|
/** A fresh, collision-resistant lease id. Uses crypto at the I/O boundary (not pure logic). */
|
|
60
61
|
function newLeaseId() {
|
|
61
|
-
const uuid = typeof globalThis.crypto?.randomUUID
|
|
62
|
+
const uuid = 'function' === typeof globalThis.crypto?.randomUUID
|
|
62
63
|
? globalThis.crypto.randomUUID()
|
|
63
64
|
: `${String(Date.now())}-${String(performance.now())}`;
|
|
64
65
|
return `lease-${uuid}`;
|
|
@@ -119,7 +120,7 @@ export const LEASE_TOOLS = [
|
|
|
119
120
|
if (pool === undefined)
|
|
120
121
|
throw new Error(POOL_UNAVAILABLE);
|
|
121
122
|
const url = asString(args['url']);
|
|
122
|
-
if (url === undefined || url.length
|
|
123
|
+
if (url === undefined || 0 === url.length)
|
|
123
124
|
throw new Error('reticle_lease{action:"acquire"} requires a url');
|
|
124
125
|
const projectId = asString(args['projectId']);
|
|
125
126
|
const sessionId = newLeaseId();
|
|
@@ -144,7 +145,7 @@ export const LEASE_TOOLS = [
|
|
|
144
145
|
...(ready
|
|
145
146
|
? {}
|
|
146
147
|
: {
|
|
147
|
-
hint:
|
|
148
|
+
hint: leaseNotConnectedHint(url, deps.bridgePort ?? RETICLE_DEFAULT_PORT),
|
|
148
149
|
}),
|
|
149
150
|
};
|
|
150
151
|
},
|
|
@@ -166,7 +167,7 @@ export const LEASE_TOOLS = [
|
|
|
166
167
|
if (pool === undefined)
|
|
167
168
|
throw new Error(POOL_UNAVAILABLE);
|
|
168
169
|
const sessionId = asString(args['sessionId']);
|
|
169
|
-
if (sessionId === undefined || sessionId.length
|
|
170
|
+
if (sessionId === undefined || 0 === sessionId.length) {
|
|
170
171
|
throw new Error('reticle_lease{action:"release"} requires a sessionId');
|
|
171
172
|
}
|
|
172
173
|
await pool.release(sessionId);
|
|
@@ -16,11 +16,13 @@ import type { ToolDef } from './tool-kit.js';
|
|
|
16
16
|
* like flow_replay/flow_verify/flow_heal that return their own documented verdict shapes — are NOT
|
|
17
17
|
* merged. Only sibling families whose value is the capability, not the contract, are consolidated.
|
|
18
18
|
*/
|
|
19
|
-
|
|
19
|
+
interface MergeSpec {
|
|
20
20
|
name: string;
|
|
21
21
|
description: string;
|
|
22
22
|
/** action value → the original tool whose handler serves it. */
|
|
23
23
|
actions: Record<string, ToolDef>;
|
|
24
|
+
/** A concrete call, carried through to the merged def (see ToolDef.example). */
|
|
25
|
+
example?: Record<string, unknown>;
|
|
24
26
|
}
|
|
25
27
|
/** A merge declared by member NAME, resolved against the assembled tool list. */
|
|
26
28
|
export interface MergePlan {
|
|
@@ -28,6 +30,12 @@ export interface MergePlan {
|
|
|
28
30
|
description: string;
|
|
29
31
|
/** action value → the existing tool name whose handler serves it. */
|
|
30
32
|
members: Record<string, string>;
|
|
33
|
+
/**
|
|
34
|
+
* A concrete call for the merged tool. Merging discards the members' own examples — the schema is
|
|
35
|
+
* a union and theirs are per-member — so a merged tool that reaches the core surface has no
|
|
36
|
+
* example at all unless the plan states one.
|
|
37
|
+
*/
|
|
38
|
+
example?: Record<string, unknown>;
|
|
31
39
|
}
|
|
32
40
|
/**
|
|
33
41
|
* Apply the consolidation to an assembled tool list: drop each plan's members and each retired name from
|
|
@@ -40,3 +48,4 @@ export interface MergePlan {
|
|
|
40
48
|
*/
|
|
41
49
|
export declare function applyMerges(tools: readonly ToolDef[], plans: readonly MergePlan[], retired?: readonly string[]): ToolDef[];
|
|
42
50
|
export declare function mergeTools(spec: MergeSpec): ToolDef;
|
|
51
|
+
export {};
|
|
@@ -33,17 +33,23 @@ export function applyMerges(tools, plans, retired = []) {
|
|
|
33
33
|
actions[action] = member;
|
|
34
34
|
consumed.add(memberName);
|
|
35
35
|
}
|
|
36
|
-
merged.push(mergeTools({
|
|
36
|
+
merged.push(mergeTools({
|
|
37
|
+
name: plan.name,
|
|
38
|
+
description: plan.description,
|
|
39
|
+
actions,
|
|
40
|
+
...(plan.example === undefined ? {} : { example: plan.example }),
|
|
41
|
+
}));
|
|
37
42
|
}
|
|
38
43
|
return [...tools.filter((t) => !consumed.has(t.name)), ...merged];
|
|
39
44
|
}
|
|
40
45
|
export function mergeTools(spec) {
|
|
41
46
|
const actionNames = Object.keys(spec.actions);
|
|
42
|
-
if (actionNames.length
|
|
47
|
+
if (0 === actionNames.length)
|
|
43
48
|
throw new Error(`mergeTools(${spec.name}): no actions`);
|
|
44
49
|
return {
|
|
45
50
|
name: spec.name,
|
|
46
51
|
description: spec.description,
|
|
52
|
+
...(spec.example === undefined ? {} : { example: spec.example }),
|
|
47
53
|
inputSchema: {
|
|
48
54
|
action: z
|
|
49
55
|
.enum(actionNames)
|
|
@@ -52,7 +58,7 @@ export function mergeTools(spec) {
|
|
|
52
58
|
},
|
|
53
59
|
handler: (deps, args) => {
|
|
54
60
|
const action = args['action'];
|
|
55
|
-
const chosen = typeof action
|
|
61
|
+
const chosen = 'string' === typeof action ? spec.actions[action] : undefined;
|
|
56
62
|
if (chosen === undefined) {
|
|
57
63
|
return Promise.resolve({
|
|
58
64
|
error: `unknown action '${String(action)}' for ${spec.name}`,
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
interface MergedNameRedirect {
|
|
2
|
+
/** The tool to call instead. */
|
|
3
|
+
tool: string;
|
|
4
|
+
/** The action that selects the old behaviour, when the name was merged rather than retired. */
|
|
5
|
+
action?: string;
|
|
6
|
+
/** Why there is no direct replacement, for a retired name. */
|
|
7
|
+
note?: string;
|
|
8
|
+
}
|
|
9
|
+
/** Where `name` went, or undefined when it is a live tool or not ours. */
|
|
10
|
+
export declare function mergedNameRedirect(name: string): MergedNameRedirect | undefined;
|
|
11
|
+
/** The sentence handed to an agent that called `name`. */
|
|
12
|
+
export declare function mergedNameMessage(name: string, redirect: MergedNameRedirect): string;
|
|
13
|
+
export {};
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Where a merged or retired tool's old name went.
|
|
3
|
+
*
|
|
4
|
+
* Twenty-two names exported from `ReticleTool` are no longer tools: `reticle_record_start` became
|
|
5
|
+
* `reticle_record { action: "start" }`, `reticle_diff` became `reticle_baseline { action: "diff" }`,
|
|
6
|
+
* and three were retired outright. Confirmed live in a field sweep, they all answered `unknown tool`
|
|
7
|
+
* — which is the wrong answer, because the capability exists and only moved. An agent trained on an
|
|
8
|
+
* earlier release, or reading the merged tool's own description (which names every action), reaches
|
|
9
|
+
* for exactly these.
|
|
10
|
+
*
|
|
11
|
+
* DERIVED from `MERGE_PLANS` and `RETIRED_FROM_SURFACE` rather than written out, so the next merge is
|
|
12
|
+
* covered the day it lands instead of the day someone notices.
|
|
13
|
+
*/
|
|
14
|
+
import { MERGE_PLANS, RETIRED_FROM_SURFACE } from './tools.js';
|
|
15
|
+
import { ReticleTool } from './tool-names.js';
|
|
16
|
+
/** Retired names, and where the capability actually lives now. */
|
|
17
|
+
const RETIRED_NOTE = {
|
|
18
|
+
[ReticleTool.REFRESH]: {
|
|
19
|
+
tool: ReticleTool.NAVIGATE,
|
|
20
|
+
note: 'reloading was absorbed into reticle_navigate { reload: true }',
|
|
21
|
+
},
|
|
22
|
+
[ReticleTool.RUN_RECORD]: {
|
|
23
|
+
tool: ReticleTool.PROJECT,
|
|
24
|
+
note: 'run outcomes are persisted automatically by reticle_flow_replay; read them with reticle_project',
|
|
25
|
+
},
|
|
26
|
+
[ReticleTool.WAIT_READY]: {
|
|
27
|
+
tool: ReticleTool.SESSIONS,
|
|
28
|
+
note: 'waiting is implicit — the first live call already blocks until the session is ready',
|
|
29
|
+
},
|
|
30
|
+
};
|
|
31
|
+
const BY_OLD_NAME = (() => {
|
|
32
|
+
const map = new Map();
|
|
33
|
+
for (const plan of MERGE_PLANS) {
|
|
34
|
+
for (const [action, oldName] of Object.entries(plan.members)) {
|
|
35
|
+
map.set(oldName, { tool: plan.name, action });
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
for (const name of RETIRED_FROM_SURFACE) {
|
|
39
|
+
const known = RETIRED_NOTE[name];
|
|
40
|
+
if (known !== undefined)
|
|
41
|
+
map.set(name, known);
|
|
42
|
+
}
|
|
43
|
+
return map;
|
|
44
|
+
})();
|
|
45
|
+
/** Where `name` went, or undefined when it is a live tool or not ours. */
|
|
46
|
+
export function mergedNameRedirect(name) {
|
|
47
|
+
return BY_OLD_NAME.get(name);
|
|
48
|
+
}
|
|
49
|
+
/** The sentence handed to an agent that called `name`. */
|
|
50
|
+
export function mergedNameMessage(name, redirect) {
|
|
51
|
+
return redirect.action === undefined
|
|
52
|
+
? `${name} no longer exists — ${redirect.note ?? `use ${redirect.tool}`}.`
|
|
53
|
+
: `${name} was merged into ${redirect.tool}. Call ${redirect.tool} { action: "${redirect.action}", ... } — ` +
|
|
54
|
+
`through reticle_run if it is not advertised under this profile.`;
|
|
55
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The honest envelope for a navigation nobody can confirm.
|
|
3
|
+
*
|
|
4
|
+
* `window.location.assign(url)` returns before the page moves, and the SDK that would report on the
|
|
5
|
+
* new document is destroyed by the navigation itself. So a successful NAVIGATE means the browser
|
|
6
|
+
* accepted the instruction — not that anything arrived. Driven against a dead URL it returned
|
|
7
|
+
* `{"ok":true}` while the session died, which is the worst combination available: the agent believes
|
|
8
|
+
* it navigated, is looking at nothing, and has lost Reticle.
|
|
9
|
+
*
|
|
10
|
+
* `reticle_act` already draws this line — `dispatched` (sent) versus `settled` (a frame flushed).
|
|
11
|
+
* This gives navigate the same honesty without changing what it does.
|
|
12
|
+
*/
|
|
13
|
+
export declare function navigateResult(result: {
|
|
14
|
+
ok?: unknown;
|
|
15
|
+
url?: unknown;
|
|
16
|
+
reason?: unknown;
|
|
17
|
+
}): Record<string, unknown>;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The honest envelope for a navigation nobody can confirm.
|
|
3
|
+
*
|
|
4
|
+
* `window.location.assign(url)` returns before the page moves, and the SDK that would report on the
|
|
5
|
+
* new document is destroyed by the navigation itself. So a successful NAVIGATE means the browser
|
|
6
|
+
* accepted the instruction — not that anything arrived. Driven against a dead URL it returned
|
|
7
|
+
* `{"ok":true}` while the session died, which is the worst combination available: the agent believes
|
|
8
|
+
* it navigated, is looking at nothing, and has lost Reticle.
|
|
9
|
+
*
|
|
10
|
+
* `reticle_act` already draws this line — `dispatched` (sent) versus `settled` (a frame flushed).
|
|
11
|
+
* This gives navigate the same honesty without changing what it does.
|
|
12
|
+
*/
|
|
13
|
+
export function navigateResult(result) {
|
|
14
|
+
const ok = true === result.ok;
|
|
15
|
+
const base = {
|
|
16
|
+
ok,
|
|
17
|
+
...('string' === typeof result.url ? { url: result.url } : {}),
|
|
18
|
+
...('string' === typeof result.reason ? { reason: result.reason } : {}),
|
|
19
|
+
};
|
|
20
|
+
// A refusal is conclusive: the page never moved, so there is nothing unconfirmed to report.
|
|
21
|
+
if (!ok)
|
|
22
|
+
return base;
|
|
23
|
+
return {
|
|
24
|
+
...base,
|
|
25
|
+
confirmed: false,
|
|
26
|
+
note: 'ok means the navigation was DISPATCHED, not that the page arrived — the SDK is torn down by ' +
|
|
27
|
+
'the navigation itself, so nothing here can see the new document. Call reticle_sessions to ' +
|
|
28
|
+
'confirm a session reconnected at the new URL before acting; if none appears, the page did ' +
|
|
29
|
+
'not load or is not instrumented.',
|
|
30
|
+
};
|
|
31
|
+
}
|