@reticlehq/server 3.5.0 โ 3.6.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/README.md +1 -1
- package/SKILL.md +16 -8
- package/dist/chromium-launch-options.d.ts +3 -1
- package/dist/chromium-launch-options.js +2 -1
- package/dist/command/cli/adhoc-verdict.d.ts +1 -0
- package/dist/command/cli/adhoc-verdict.js +6 -3
- package/dist/command/cli/answers/open-note.d.ts +2 -0
- package/dist/command/cli/answers/open-note.js +22 -0
- package/dist/command/cli/cli-flow-commands.js +4 -8
- package/dist/command/cli/cli-parse.d.ts +1 -1
- package/dist/command/cli/cli-parse.js +10 -10
- package/dist/command/cli/cli-verify.d.ts +1 -1
- package/dist/command/cli/cli-verify.js +35 -25
- package/dist/command/cli/cloud-cli.js +51 -12
- package/dist/command/cli/cloud-login.d.ts +8 -0
- package/dist/command/cli/cloud-login.js +36 -2
- package/dist/command/cli/demo/demo-page.js +11 -3
- package/dist/command/cli/doctor/browser/chromium-hint.d.ts +46 -0
- package/dist/command/cli/doctor/browser/chromium-hint.js +99 -1
- package/dist/command/cli/drive/drive-attach.d.ts +27 -2
- package/dist/command/cli/drive/drive-attach.js +71 -4
- package/dist/command/cli/drive/drive-command.d.ts +2 -1
- package/dist/command/cli/drive/drive-command.js +13 -7
- package/dist/command/cli/lifecycle/daemon-lifecycle.js +4 -1
- package/dist/command/cli/ports/port-holder.d.ts +10 -0
- package/dist/command/cli/ports/port-holder.js +24 -0
- package/dist/command/cli/setup-mcp-cli.js +6 -4
- package/dist/command/cli/tutorial.d.ts +2 -2
- package/dist/command/cli/tutorial.js +6 -9
- package/dist/command/cli.d.ts +6 -0
- package/dist/command/cli.js +28 -22
- package/dist/command/daemon/binding/daemon-status-probe.d.ts +2 -0
- package/dist/command/daemon/binding/daemon-status-probe.js +1 -0
- package/dist/command/daemon/daemon-resolve.d.ts +14 -0
- package/dist/command/daemon/daemon-resolve.js +33 -2
- package/dist/command/setup/agent-writer.d.ts +1 -1
- package/dist/command/setup/agent-writer.js +3 -2
- package/dist/command/setup/bringup/connect-lease.d.ts +1 -0
- package/dist/command/setup/bringup/connect-lease.js +1 -0
- package/dist/command/setup/bringup/dev-server-wait.d.ts +8 -0
- package/dist/command/setup/bringup/dev-server-wait.js +19 -0
- package/dist/command/setup/init/init-port.d.ts +4 -0
- package/dist/command/setup/init/init-port.js +10 -0
- package/dist/command/setup/init/init-runtime.d.ts +10 -0
- package/dist/command/setup/init/init-runtime.js +18 -1
- package/dist/command/setup/node-effects.js +2 -1
- package/dist/command/setup/remaining-steps.js +2 -1
- package/dist/command/setup/run-setup.d.ts +5 -0
- package/dist/command/setup/run-setup.js +35 -27
- package/dist/command/setup/setup-command.d.ts +2 -1
- package/dist/command/setup/setup-command.js +2 -0
- package/dist/command/version/version-skew.js +11 -2
- package/dist/features/crawl/crawl-tools.js +4 -0
- package/dist/features/crawl/crawl.d.ts +6 -0
- package/dist/features/crawl/crawl.js +9 -1
- package/dist/features/exhaust/ledger.d.ts +7 -0
- package/dist/features/exhaust/ledger.js +35 -9
- package/dist/features/harness/app-findings.d.ts +2 -0
- package/dist/features/harness/app-findings.js +52 -0
- package/dist/features/harness/drive-report.d.ts +27 -1
- package/dist/features/harness/drive-report.js +162 -11
- package/dist/features/harness/drivers.d.ts +10 -14
- package/dist/features/harness/drivers.js +10 -14
- package/dist/features/harness/fill-values.d.ts +3 -73
- package/dist/features/harness/fill-values.js +3 -169
- package/dist/features/harness/goals.d.ts +21 -0
- package/dist/features/harness/goals.js +77 -0
- package/dist/features/harness/harness.d.ts +21 -0
- package/dist/features/harness/harness.js +69 -2
- package/dist/features/harness/platform/drive-target.d.ts +30 -0
- package/dist/features/harness/platform/drive-target.js +81 -0
- package/dist/features/harness/platform/local-apps.d.ts +94 -0
- package/dist/features/harness/platform/local-apps.js +204 -0
- package/dist/features/harness/platform/remote-drive.d.ts +180 -0
- package/dist/features/harness/platform/remote-drive.js +365 -0
- package/dist/features/harness/platform/script.d.ts +48 -0
- package/dist/features/harness/platform/script.js +128 -0
- package/dist/features/harness/platform/server-driver.d.ts +41 -0
- package/dist/features/harness/platform/server-driver.js +179 -0
- package/dist/features/harness/platform-config.d.ts +7 -0
- package/dist/features/harness/platform-config.js +14 -2
- package/dist/features/harness/script/app-controls.d.ts +5 -0
- package/dist/features/harness/script/app-controls.js +40 -0
- package/dist/features/harness/script/lane-ids.d.ts +14 -0
- package/dist/features/harness/script/lane-ids.js +16 -0
- package/dist/features/harness/script/script-run.d.ts +41 -0
- package/dist/features/harness/script/script-run.js +299 -0
- package/dist/features/license/license.d.ts +2 -2
- package/dist/features/visual/visual-tools.d.ts +10 -1
- package/dist/features/visual/visual-tools.js +40 -3
- package/dist/hooks/driven-by.d.ts +4 -0
- package/dist/hooks/driven-by.js +16 -0
- package/dist/hooks/hook-commands.js +15 -4
- package/dist/hooks/tool-log.d.ts +9 -0
- package/dist/hooks/tool-log.js +29 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +76 -82
- package/dist/judgement/runs/artifact/build-verification-run.js +6 -0
- package/dist/judgement/runs/artifact/replay-mapping.d.ts +1 -1
- package/dist/judgement/runs/artifact/replay-mapping.js +16 -6
- package/dist/judgement/runs/artifact/run-store.d.ts +1 -1
- package/dist/judgement/runs/artifact/run-store.js +26 -1
- package/dist/judgement/runs/drive-run.d.ts +22 -0
- package/dist/judgement/runs/drive-run.js +99 -1
- package/dist/judgement/runs/repair-prompt.js +1 -1
- package/dist/judgement/runs/reticle-runner.js +8 -1
- package/dist/judgement/runs/verification-sync.d.ts +3 -2
- package/dist/judgement/runs/verification-sync.js +4 -3
- package/dist/language/flows/change/gate.d.ts +10 -0
- package/dist/language/flows/change/gate.js +22 -0
- package/dist/language/flows/decision.js +34 -0
- package/dist/language/flows/flow-anchor.d.ts +54 -8
- package/dist/language/flows/flow-anchor.js +88 -3
- package/dist/language/flows/flow-cross-step.d.ts +15 -0
- package/dist/language/flows/flow-cross-step.js +21 -0
- package/dist/language/flows/flow-learning.js +8 -11
- package/dist/language/flows/flow-mutate-tools.js +5 -3
- package/dist/language/flows/flow-replay-run.d.ts +23 -9
- package/dist/language/flows/flow-replay-run.js +101 -94
- package/dist/language/flows/flow-replay.d.ts +23 -1
- package/dist/language/flows/flow-replay.js +92 -19
- package/dist/language/flows/flow-scope.js +5 -1
- package/dist/language/flows/flow-step-runners.d.ts +20 -2
- package/dist/language/flows/flow-step-runners.js +236 -42
- package/dist/language/flows/flow-store-for-session.d.ts +2 -2
- package/dist/language/flows/flow-store-for-session.js +2 -2
- package/dist/language/flows/flow-tools.js +58 -34
- package/dist/language/flows/flows.js +5 -2
- package/dist/language/flows/heal-run.js +6 -4
- package/dist/language/flows/recording/flake.d.ts +2 -2
- package/dist/language/flows/recording/tape/recordings.d.ts +30 -4
- package/dist/language/flows/recording/tape/recordings.js +40 -8
- package/dist/language/flows/replay-from-hud.d.ts +20 -0
- package/dist/language/flows/replay-from-hud.js +51 -0
- package/dist/language/flows/replay.d.ts +9 -5
- package/dist/language/flows/replay.js +27 -9
- package/dist/language/flows/suite/suite-flakes.js +2 -0
- package/dist/language/flows/suite-selection.d.ts +2 -15
- package/dist/language/flows/suite-selection.js +4 -3
- package/dist/language/flows/verify-change-tools.js +8 -4
- package/dist/launch-chromium.d.ts +27 -5
- package/dist/launch-chromium.js +38 -8
- package/dist/memory/cloud/cloud-config.d.ts +12 -0
- package/dist/memory/cloud/cloud-config.js +15 -0
- package/dist/memory/cloud/cloud-sync.d.ts +17 -14
- package/dist/memory/cloud/cloud-sync.js +12 -1
- package/dist/memory/cloud/harness-config.d.ts +26 -1
- package/dist/memory/cloud/harness-config.js +99 -4
- package/dist/memory/cloud/hud-notices-source.d.ts +21 -0
- package/dist/memory/cloud/hud-notices-source.js +128 -0
- package/dist/memory/cloud/memory-scope.d.ts +144 -0
- package/dist/memory/cloud/memory-scope.js +205 -0
- package/dist/memory/cloud/sync-cycle.d.ts +12 -3
- package/dist/memory/cloud/sync-cycle.js +16 -3
- package/dist/memory/cloud/sync-daemon.js +7 -5
- package/dist/memory/cloud/sync-disk.d.ts +1 -1
- package/dist/memory/cloud/sync-disk.js +5 -8
- package/dist/memory/impact/account-watch.d.ts +19 -0
- package/dist/memory/impact/account-watch.js +34 -0
- package/dist/memory/impact/impact-recorder.d.ts +8 -0
- package/dist/memory/impact/impact-recorder.js +12 -2
- package/dist/memory/impact/impact-store.d.ts +16 -0
- package/dist/memory/impact/impact-store.js +142 -26
- package/dist/memory/intent/intent-shard.d.ts +2 -2
- package/dist/memory/intent/intent-tools.js +80 -2
- package/dist/memory/journal/envelope.d.ts +8 -8
- package/dist/memory/journal/journal-recorder.js +7 -1
- package/dist/memory/journal/on-disk/retention.d.ts +3 -0
- package/dist/memory/journal/on-disk/retention.js +5 -0
- package/dist/memory/journal/on-disk/startup-maintenance.js +3 -1
- package/dist/memory/journal/on-disk/workspace-tiers.js +7 -4
- package/dist/memory/journal/session-end.js +6 -4
- package/dist/memory/project/artifact-root-resolver.d.ts +26 -1
- package/dist/memory/project/artifact-root-resolver.js +94 -13
- package/dist/memory/project/artifact-root.d.ts +42 -5
- package/dist/memory/project/artifact-root.js +87 -8
- package/dist/memory/project/dir/reticle-dir.d.ts +4 -2
- package/dist/memory/project/dir/reticle-dir.js +3 -1
- package/dist/memory/project/project-tools.js +22 -3
- package/dist/memory/project/session-root.d.ts +24 -1
- package/dist/memory/project/session-root.js +41 -5
- package/dist/memory/project/sync-status.d.ts +39 -0
- package/dist/memory/project/sync-status.js +90 -0
- package/dist/memory/recall/memory-tools.js +2 -0
- package/dist/memory/recall/project-memory.d.ts +19 -0
- package/dist/memory/recall/project-memory.js +45 -6
- package/dist/portal/bridge/bridge.d.ts +3 -1
- package/dist/portal/bridge/bridge.js +19 -2
- package/dist/portal/bridge/pairing-token.d.ts +9 -0
- package/dist/portal/bridge/pairing-token.js +17 -0
- package/dist/portal/input/real-input.d.ts +81 -10
- package/dist/portal/input/real-input.js +207 -22
- package/dist/portal/input/viewport-tools.js +3 -3
- package/dist/portal/pool/browser-pool.d.ts +22 -9
- package/dist/portal/pool/browser-pool.js +70 -35
- package/dist/portal/pool/playwright-launcher.d.ts +13 -0
- package/dist/portal/pool/playwright-launcher.js +17 -1
- package/dist/portal/pool/pool-contract.d.ts +7 -4
- package/dist/portal/session/command-payload.d.ts +8 -0
- package/dist/portal/session/command-payload.js +19 -0
- package/dist/portal/session/dev-server/dev-command.d.ts +12 -0
- package/dist/portal/session/dev-server/dev-command.js +61 -12
- package/dist/portal/session/facts/departure-note.d.ts +22 -0
- package/dist/portal/session/facts/departure-note.js +47 -0
- package/dist/portal/session/facts/session-replaced.d.ts +5 -0
- package/dist/portal/session/facts/session-replaced.js +5 -0
- package/dist/portal/session/first-run-wiring.d.ts +42 -0
- package/dist/portal/session/first-run-wiring.js +132 -0
- package/dist/portal/session/human/notes-ledger.d.ts +20 -0
- package/dist/portal/session/human/notes-ledger.js +55 -0
- package/dist/portal/session/human/review-store.d.ts +12 -0
- package/dist/portal/session/human/review-store.js +18 -10
- package/dist/portal/session/live-control-tools.d.ts +0 -13
- package/dist/portal/session/live-control-tools.js +28 -3
- package/dist/portal/session/no-session-diagnosis.d.ts +7 -0
- package/dist/portal/session/no-session-diagnosis.js +15 -0
- package/dist/portal/session/no-session-next-action.d.ts +11 -0
- package/dist/portal/session/no-session-next-action.js +31 -5
- package/dist/portal/session/no-session-watch.d.ts +14 -1
- package/dist/portal/session/no-session-watch.js +63 -10
- package/dist/portal/session/presence/session-mirror.js +3 -0
- package/dist/portal/session/serving-directory.d.ts +27 -0
- package/dist/portal/session/serving-directory.js +45 -0
- package/dist/portal/session/session-health.d.ts +7 -0
- package/dist/portal/session/session-health.js +6 -0
- package/dist/portal/session/session-info.d.ts +8 -1
- package/dist/portal/session/session-info.js +6 -0
- package/dist/portal/session/session-manager.d.ts +21 -0
- package/dist/portal/session/session-manager.js +44 -8
- package/dist/portal/session/session-reaper.js +4 -1
- package/dist/portal/session/session-successor.d.ts +5 -0
- package/dist/portal/session/session-tools.js +26 -3
- package/dist/portal/session/session.d.ts +7 -2
- package/dist/portal/session/session.js +21 -18
- package/dist/start-options.d.ts +6 -0
- package/dist/status-payload.d.ts +10 -0
- package/dist/status-payload.js +23 -0
- package/dist/surface/http-server.js +11 -1
- package/dist/surface/mcp/mcp-proxy.d.ts +5 -0
- package/dist/surface/mcp/mcp-proxy.js +36 -5
- package/dist/surface/mcp/mcp.d.ts +11 -6
- package/dist/surface/mcp/mcp.js +27 -13
- package/dist/surface/mcp/server-instructions.d.ts +4 -2
- package/dist/surface/mcp/server-instructions.js +14 -4
- package/dist/surface/mcp/shared-params.js +2 -2
- package/dist/surface/tools/act/navigation/navigate-arrival.d.ts +8 -0
- package/dist/surface/tools/act/navigation/navigate-arrival.js +56 -2
- package/dist/surface/tools/act/settle-in-flight.js +25 -3
- package/dist/surface/tools/act-sequence-tool.js +2 -2
- package/dist/surface/tools/act-tools.js +23 -7
- package/dist/surface/tools/assert/assert-verdict.d.ts +1 -1
- package/dist/surface/tools/assert/assert-verdict.js +17 -2
- package/dist/surface/tools/browser-tools.js +8 -1
- package/dist/surface/tools/chat-drives.d.ts +26 -0
- package/dist/surface/tools/chat-drives.js +165 -0
- package/dist/surface/tools/empty-session-list.d.ts +41 -0
- package/dist/surface/tools/empty-session-list.js +80 -0
- package/dist/surface/tools/error-recovery.d.ts +6 -0
- package/dist/surface/tools/error-recovery.js +37 -4
- package/dist/surface/tools/explore-tools.d.ts +10 -1
- package/dist/surface/tools/explore-tools.js +82 -13
- package/dist/surface/tools/feedback-tools.js +14 -0
- package/dist/surface/tools/harness-explore.d.ts +96 -14
- package/dist/surface/tools/harness-explore.js +227 -206
- package/dist/surface/tools/harness-plan.d.ts +12 -0
- package/dist/surface/tools/harness-plan.js +31 -0
- package/dist/surface/tools/harness-script.d.ts +8 -0
- package/dist/surface/tools/harness-script.js +342 -0
- package/dist/surface/tools/harness-toolset.d.ts +14 -1
- package/dist/surface/tools/harness-toolset.js +77 -6
- package/dist/surface/tools/invoke-tool.js +52 -1
- package/dist/surface/tools/lease-seed.d.ts +29 -0
- package/dist/surface/tools/lease-seed.js +123 -0
- package/dist/surface/tools/lease-tools.d.ts +3 -23
- package/dist/surface/tools/lease-tools.js +30 -131
- package/dist/surface/tools/live-call-text.js +2 -2
- package/dist/surface/tools/next-step.d.ts +19 -0
- package/dist/surface/tools/next-step.js +159 -0
- package/dist/surface/tools/observe-tools.js +2 -4
- package/dist/surface/tools/platform-moment.d.ts +12 -0
- package/dist/surface/tools/platform-moment.js +168 -0
- package/dist/surface/tools/query-hint-schema.d.ts +7 -0
- package/dist/surface/tools/query-hint-schema.js +10 -0
- package/dist/surface/tools/read-tools.js +8 -2
- package/dist/surface/tools/real-input-attempt.js +96 -13
- package/dist/surface/tools/tool-kit.d.ts +15 -1
- package/dist/surface/tools/tool-kit.js +4 -6
- package/dist/surface/tools/tools.js +20 -48
- package/dist/telemetry/hud-metrics.d.ts +2 -0
- package/dist/telemetry/hud-metrics.js +17 -0
- package/dist/telemetry/telemetry.d.ts +12 -0
- package/dist/telemetry/telemetry.js +43 -14
- package/dist/telemetry/verification-of.js +1 -0
- package/dist/wire-journal.js +4 -1
- package/docs/README.md +1 -1
- package/docs/agent-cheatsheet.md +1 -1
- package/docs/autodrive.md +29 -25
- package/docs/cli/doctor.mdx +6 -0
- package/docs/cli/drive.mdx +8 -2
- package/docs/cli/init.mdx +11 -13
- package/docs/cli/status.mdx +5 -1
- package/docs/cli/version.mdx +3 -3
- package/docs/cli.mdx +1 -1
- package/docs/desktop.mdx +5 -1
- package/docs/environment.mdx +3 -7
- package/docs/getting-started.md +13 -11
- package/docs/human-control.md +1 -2
- package/docs/index.mdx +4 -3
- package/docs/install-manual.mdx +2 -2
- package/docs/packages/tauri.mdx +2 -2
- package/docs/packages/vite-plugin.mdx +22 -1
- package/docs/packages.mdx +1 -1
- package/docs/quickstart.mdx +17 -7
- package/docs/telemetry.md +1 -1
- package/docs/tools/session-and-feedback.mdx +9 -9
- package/docs/usage.md +5 -2
- package/docs/what-is-recorded.md +13 -3
- package/docs/what-is-reticle.mdx +3 -1
- package/package.json +8 -12
- package/dist/features/harness/driver.d.ts +0 -50
- package/dist/features/harness/driver.js +0 -236
- package/dist/features/harness/jev-driver.d.ts +0 -188
- package/dist/features/harness/jev-driver.js +0 -678
- package/dist/features/harness/openai-driver.d.ts +0 -58
- package/dist/features/harness/openai-driver.js +0 -206
- package/dist/memory/project/dir/fill-value-store.d.ts +0 -32
- package/dist/memory/project/dir/fill-value-store.js +0 -88
- package/docs/local-registry.md +0 -143
|
@@ -10,6 +10,18 @@ import { TelemetryEventKind, ProjectIdSource, type Crash, type Feedback, type Id
|
|
|
10
10
|
* analytics side learns a customer list only when we deliberately upload one.
|
|
11
11
|
*/
|
|
12
12
|
export declare const POSTHOG_GROUP_ORGANIZATION = "organization";
|
|
13
|
+
/**
|
|
14
|
+
* Read (or mint-and-persist) the anonymous machine id. `firstRun` is true the run that created it.
|
|
15
|
+
*
|
|
16
|
+
* Read first and create exclusively (`wx`), rather than asking `existsSync` and then writing: two
|
|
17
|
+
* processes starting together used to both see no file, both mint, and the second write replaced
|
|
18
|
+
* the first id, so one machine reported as two first runs. The loser of the exclusive create now
|
|
19
|
+
* reads the winner's id instead.
|
|
20
|
+
*/
|
|
21
|
+
export declare const resolveIdentity: (file?: string) => {
|
|
22
|
+
anonymousId: string;
|
|
23
|
+
firstRun: boolean;
|
|
24
|
+
};
|
|
13
25
|
/**
|
|
14
26
|
* One-way project fingerprint: distinct-count of this = "projects Reticle is used in", reveals nothing.
|
|
15
27
|
*
|
|
@@ -19,6 +19,7 @@ import { appendFileSync, readFileSync, writeFileSync, mkdirSync, existsSync, rmS
|
|
|
19
19
|
import { homedir, platform } from 'node:os';
|
|
20
20
|
import { dirname, join } from 'node:path';
|
|
21
21
|
import { TelemetryEventKind, TELEMETRY_EVENT_VERSION, ProjectIdSource, isSessionScoped, } from '@reticlehq/core/telemetry';
|
|
22
|
+
import { ReticleEnv } from '@reticlehq/core';
|
|
22
23
|
import { SERVER_VERSION } from '../command/version/identity/server-version.js';
|
|
23
24
|
const RETICLE_DIR = join(homedir(), '.reticle');
|
|
24
25
|
const ID_FILE = join(RETICLE_DIR, 'telemetry-id');
|
|
@@ -100,8 +101,8 @@ import { licenseFacts } from './license-activation.js';
|
|
|
100
101
|
import { gitFacts } from './git-facts.js';
|
|
101
102
|
import { currentAutomationHint } from './automation-hint.js';
|
|
102
103
|
const Env = {
|
|
103
|
-
DISABLE:
|
|
104
|
-
DO_NOT_TRACK:
|
|
104
|
+
DISABLE: ReticleEnv.TELEMETRY, // "0" / "false" / "off" โ disabled
|
|
105
|
+
DO_NOT_TRACK: ReticleEnv.DO_NOT_TRACK, // the cross-tool opt-out convention (any truthy value)
|
|
105
106
|
URL: 'RETICLE_TELEMETRY_URL', // override the PostHog host (EU cloud / self-hosted)
|
|
106
107
|
FILE: 'RETICLE_TELEMETRY_FILE', // record to a local JSONL file and send NOTHING โ see the sink note
|
|
107
108
|
KEY: 'RETICLE_TELEMETRY_KEY', // override the PostHog project key
|
|
@@ -140,17 +141,45 @@ const isDisabled = (env, cwd = process.cwd()) => {
|
|
|
140
141
|
* file, and a test run. This lifts one implicit guard for one user-initiated event kind.
|
|
141
142
|
*/
|
|
142
143
|
const onlyBlockedBySourceCheckout = (env, cwd) => isDisabled(env, cwd) && !isDisabled(env, '/');
|
|
143
|
-
/**
|
|
144
|
-
const
|
|
144
|
+
/** Node's code for "the file is already there" โ what an exclusive create answers when it lost. */
|
|
145
|
+
const EEXIST = 'EEXIST';
|
|
146
|
+
const isAlreadyThere = (error) => 'object' === typeof error && null !== error && EEXIST === error.code;
|
|
147
|
+
const readIdFile = (file) => {
|
|
145
148
|
try {
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
149
|
+
const id = readFileSync(file, 'utf8').trim();
|
|
150
|
+
return id.length > 0 ? id : undefined;
|
|
151
|
+
}
|
|
152
|
+
catch {
|
|
153
|
+
return undefined;
|
|
154
|
+
}
|
|
155
|
+
};
|
|
156
|
+
/**
|
|
157
|
+
* Read (or mint-and-persist) the anonymous machine id. `firstRun` is true the run that created it.
|
|
158
|
+
*
|
|
159
|
+
* Read first and create exclusively (`wx`), rather than asking `existsSync` and then writing: two
|
|
160
|
+
* processes starting together used to both see no file, both mint, and the second write replaced
|
|
161
|
+
* the first id, so one machine reported as two first runs. The loser of the exclusive create now
|
|
162
|
+
* reads the winner's id instead.
|
|
163
|
+
*/
|
|
164
|
+
export const resolveIdentity = (file = ID_FILE) => {
|
|
165
|
+
try {
|
|
166
|
+
const existing = readIdFile(file);
|
|
167
|
+
if (existing !== undefined)
|
|
168
|
+
return { anonymousId: existing, firstRun: false };
|
|
151
169
|
const id = randomUUID();
|
|
152
|
-
mkdirSync(
|
|
153
|
-
|
|
170
|
+
mkdirSync(dirname(file), { recursive: true });
|
|
171
|
+
try {
|
|
172
|
+
writeFileSync(file, id, { encoding: 'utf8', flag: 'wx' });
|
|
173
|
+
}
|
|
174
|
+
catch (error) {
|
|
175
|
+
if (!isAlreadyThere(error))
|
|
176
|
+
throw error;
|
|
177
|
+
const raced = readIdFile(file);
|
|
178
|
+
if (raced !== undefined)
|
|
179
|
+
return { anonymousId: raced, firstRun: false };
|
|
180
|
+
// An empty file left by a crash: replace it, as the old code did.
|
|
181
|
+
writeFileSync(file, id, 'utf8');
|
|
182
|
+
}
|
|
154
183
|
return { anonymousId: id, firstRun: true };
|
|
155
184
|
}
|
|
156
185
|
catch {
|
|
@@ -209,10 +238,10 @@ const packageRoot = (cwd) => {
|
|
|
209
238
|
/** Print the opt-out notice exactly once per machine (honest disclosure, the OSS-trust bar). */
|
|
210
239
|
const showNoticeOnce = () => {
|
|
211
240
|
try {
|
|
212
|
-
if (existsSync(NOTICE_FILE))
|
|
213
|
-
return;
|
|
214
241
|
mkdirSync(RETICLE_DIR, { recursive: true });
|
|
215
|
-
|
|
242
|
+
// Exclusive create IS the "once": it throws when the file is already there, so the check and
|
|
243
|
+
// the write cannot be split by a second process printing the notice too.
|
|
244
|
+
writeFileSync(NOTICE_FILE, '1', { encoding: 'utf8', flag: 'wx' });
|
|
216
245
|
process.stderr.write('reticle: anonymous usage telemetry helps improve reticle โ no code, no PII, ' +
|
|
217
246
|
`and your app's data never leaves your machine (${POLICY_URL}). ` +
|
|
218
247
|
'Opt out any time: reticle telemetry disable\n');
|
|
@@ -70,6 +70,7 @@ const REPLAY_VERDICTS = new Map([
|
|
|
70
70
|
[ReplayStatus.OK, { verified: Verified.YES, passed: true }],
|
|
71
71
|
[ReplayStatus.DRIFT, { verified: Verified.NO, passed: false }],
|
|
72
72
|
[ReplayStatus.ERROR, { verified: Verified.UNKNOWN, passed: false }],
|
|
73
|
+
[ReplayStatus.UNVERIFIABLE, { verified: Verified.UNKNOWN, passed: false }],
|
|
73
74
|
]);
|
|
74
75
|
function replayVerdict(toolName, status) {
|
|
75
76
|
if (ReticleTool.FLOW_REPLAY !== toolName || 'string' !== typeof status)
|
package/dist/wire-journal.js
CHANGED
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
* the 1000-line backstop is what asked for the split.
|
|
9
9
|
*/
|
|
10
10
|
import { artifactRootResolver } from './memory/project/artifact-root-resolver.js';
|
|
11
|
+
import { servingDirectoryOf } from './portal/session/serving-directory.js';
|
|
11
12
|
import { originOf } from './portal/session/session-manager.js';
|
|
12
13
|
import { Bridge } from './portal/bridge/bridge.js';
|
|
13
14
|
import { FlowStore } from './language/flows/flows.js';
|
|
@@ -35,7 +36,9 @@ export function attachJournal(bridge, deps) {
|
|
|
35
36
|
const ambientStore = new AmbientStore(deps.fs, deps.reticleRoot);
|
|
36
37
|
// Built once, not per session: the resolver walks config discovery and the user-level registry,
|
|
37
38
|
// and neither changes between two tabs connecting a second apart.
|
|
38
|
-
const resolveArtifactRoot = artifactRootResolver(deps.reticleRoot
|
|
39
|
+
const resolveArtifactRoot = artifactRootResolver(deps.reticleRoot, {
|
|
40
|
+
servingDirectory: servingDirectoryOf,
|
|
41
|
+
});
|
|
39
42
|
bridge.attachSessionCreate((session) => {
|
|
40
43
|
// Stamp the project's own `.reticle` before ANY counter fires for this session. Without it every
|
|
41
44
|
// verdict is recorded against wherever the daemon was started, which is how one app's evidence
|
package/docs/README.md
CHANGED
|
@@ -76,7 +76,7 @@ Everything here is published to [docs.reticle.sh](https://docs.reticle.sh) by `d
|
|
|
76
76
|
| [vs-screenshots.mdx](vs-screenshots.mdx) | why a better vision model does not fix a non-visual bug |
|
|
77
77
|
| [what-is-recorded.md](what-is-recorded.md) | what Reticle keeps, what is redacted, and what it takes for any of it to leave your machine |
|
|
78
78
|
| [telemetry.md](telemetry.md) | what is collected, and how to turn it off |
|
|
79
|
-
| [local-registry.md](local-registry.md) | installing an unpublished build |
|
|
79
|
+
| [local-registry.md](https://github.com/reticlehq/reticle/blob/main/docs/local-registry.md) | installing an unpublished build |
|
|
80
80
|
| [license-activation.mdx](license-activation.mdx) | you have a key: where to set it, how to confirm it, what to do when it fails |
|
|
81
81
|
| [enterprise.md](enterprise.md) | the licensed surface |
|
|
82
82
|
|
package/docs/agent-cheatsheet.md
CHANGED
|
@@ -135,7 +135,7 @@ Not on this surface at all, but one hop away: `reticle_run { tool, args }` calls
|
|
|
135
135
|
| --- | --- | --- |
|
|
136
136
|
| **flows** | `reticle_flow_save*` / `reticle_flow_replay` / `reticle_verify { action: "heal" }` | Replayable **golden journeys**, anchored to testids/signals; drift is legible and self-heals. |
|
|
137
137
|
| **baselines** | `reticle_baseline {action:"save"}` / `reticle_baseline {action:"diff"}` | Structural **"before" snapshots**; `reticle_baseline {action:"diff"}` flags regressions against them. |
|
|
138
|
-
| **project.json** | `reticle_project` | Cross-run **run-history**: "did it behave like last run?" read via `reticle_project`. |
|
|
138
|
+
| **project.json** | `reticle_project` | Cross-run **run-history**: "did it behave like last run?" read via `reticle_project`. Its `cloud.sync` says where this project's runs stand with the platform (on it, waiting, refused, last push); `push: true` syncs before answering. |
|
|
139
139
|
|
|
140
140
|
> `reticle_project` / `project.json` are the **run-history layer**. flows answer "does the journey still work?"; baselines answer "did the structure change?"; project.json answers "is this run consistent with prior runs?".
|
|
141
141
|
|
package/docs/autodrive.md
CHANGED
|
@@ -6,7 +6,7 @@ icon: steering-wheel
|
|
|
6
6
|
|
|
7
7
|
Driving an app is the expensive part of verifying one. Every snapshot, every act result and every observation lands in your agent's context and is re-read on every turn after, and none of it is kept: the next run starts from nothing and pays again.
|
|
8
8
|
|
|
9
|
-
`reticle_verify { action: "explore" }`
|
|
9
|
+
`reticle_verify { action: "explore" }` hands the driving to the Reticle Harness. It decides on the Reticle platform, and the daemon on your machine executes each step through the same tool surface your agent uses, records what it drove as saved flows, and hands back a few lines. It needs a linked project (`reticle connect`).
|
|
10
10
|
|
|
11
11
|
```jsonc
|
|
12
12
|
reticle_verify {
|
|
@@ -32,51 +32,55 @@ So the drive is a one-off: pay for it once, and the journeys it recorded become
|
|
|
32
32
|
|
|
33
33
|
A drive reads `.reticle` first: every saved flow with the consequence that must still hold, and every signal and testid your app declares that no flow has ever asserted. It builds a plan from that before it opens its eyes on a page.
|
|
34
34
|
|
|
35
|
-
|
|
35
|
+
With no persona, anything already recorded is **replayed**, deterministically, with no model call at all, and only the gaps are driven (see the plan below). With a persona, it drives that journey and replays nothing else: the saved flows have nothing to do with the journey you named. So a second run over the same app is mostly free, and the model budget is spent on the part nobody has proved yet rather than on rediscovering what is already on disk. A replay that goes red is reported as a regression; one that DRIFTS is reported separately, because the app moved under the recording and that needs re-anchoring rather than a code change.
|
|
36
36
|
|
|
37
37
|
Every journey a drive walks is saved, whatever happens to the drive, including one that broke, ran out of budget, or whose model simply stopped asking for tools.
|
|
38
38
|
|
|
39
|
-
##
|
|
39
|
+
## The platform plans the drive
|
|
40
40
|
|
|
41
|
-
|
|
41
|
+
With a platform credential (`reticle connect`, or `RETICLE_API_KEY`), the platform plans every drive. With a persona or without one, it proposes the people worth being, orders the saved flows, finds where they branch, and writes into each journey the product rules that apply to it, read from your project's own intents. The rules tell the Harness what the journey is for and where it ends (a journey that names Settings is not finished before Settings). They are not checked as assertions: a rule like "the row shows refunded" is guidance, and the checks are the consequences each step declares. Your machine sends what the project knows, with each saved step as a short hash and never the values it typed. It runs the plan it gets back and reports what happened. The plan is checked before it runs, and a plan that fails the checks is dropped. Every decision while it drives is the platform's too: your machine executes each step it is handed and reports what happened.
|
|
42
42
|
|
|
43
|
-
|
|
44
|
-
| --- | --- |
|
|
45
|
-
| `RETICLE_API_KEY` | `jev`, against the platform's own proxy, using the key `reticle link` already wrote. No model API key of your own, and the cheap path: it answers typed questions about the page rather than generating tool calls as text. |
|
|
46
|
-
| `ANTHROPIC_API_KEY` | `anthropic`, which generates its calls as text. |
|
|
47
|
-
| `OPENAI_API_KEY` | `openai`, the same, on OpenAI. |
|
|
48
|
-
| `JEV_API_KEY` | `jev`, against TypeSafe directly, for anyone who holds their own key. |
|
|
43
|
+
## With no persona, it writes a plan first
|
|
49
44
|
|
|
50
|
-
|
|
45
|
+
Called with no `persona`, explore writes the whole drive down before it starts, as a drive plan:
|
|
51
46
|
|
|
52
|
-
|
|
47
|
+
- **Journeys.** Each saved flow worth replaying, plus one open journey for each persona the platform proposes, for the request the user declared (`reticle_intent { action: "declare" }`), and for each intent nobody has proved. Replays need no model; only open journeys reach one.
|
|
48
|
+
- **Order.** A flow that `needs` another runs after it. An open journey runs after the flow everything else needs, usually sign-in.
|
|
49
|
+
- **Lanes.** Each journey nothing else needs gets a lane holding what it needs, in order. Lanes run side by side, each in its own leased browser context, four at a time. A journey that needs one from another lane waits for it, and is blocked if that journey failed. A prerequisite that commits something (a payment, an email) runs in one lane only, and the others wait on it rather than commit it twice.
|
|
50
|
+
- **Branches.** Flows that start with the same steps become one journey. The shared steps are driven once and marked as a checkpoint, then each flow continues from that point. Every flow after the first replays back to the checkpoint first, so none of them starts from the page the previous one left.
|
|
53
51
|
|
|
54
|
-
|
|
52
|
+
The plan appears at the top of the HUD's Agent Log: one row per lane, a card per journey, the running journey opened to its steps, and each card marked as it passes, fails or is blocked. The tool's answer carries one line per journey.
|
|
53
|
+
|
|
54
|
+
Two `reticle_flow_replay` arguments make the branches possible, and you can use them directly. `to` stops before a step. `at` continues at a step on the page as it is, without driving the steps before it. A part-way replay checks the steps it drove and records nothing about the flow as a whole.
|
|
55
|
+
|
|
56
|
+
## What it needs
|
|
57
|
+
|
|
58
|
+
**A project on the Reticle platform.** Every plan includes the Harness: Free comes with monthly Harness credits, one per decision the Harness makes. Run `reticle connect` once in your app's folder. The Harness runs on the platform: planning, personas, and every choice of what to press next. A model key of your own does not drive it, and a machine with no platform link gets the refusal and the way to fix it.
|
|
55
59
|
|
|
56
60
|
| Variable | What it does |
|
|
57
61
|
| --- | --- |
|
|
58
|
-
| `
|
|
59
|
-
| `RETICLE_HARNESS_MAX_STEPS` | Ceiling on
|
|
60
|
-
| `
|
|
61
|
-
|
|
62
|
-
## Two models, and what each one is for
|
|
62
|
+
| `RETICLE_API_KEY` | The key `reticle connect` (or `reticle link`) wrote. The daemon uses it to ask the platform to drive. |
|
|
63
|
+
| `RETICLE_HARNESS_MAX_STEPS` | Ceiling on steps in one drive. Bounds cost, not value. |
|
|
64
|
+
| `RETICLE_SECRET_<FIELD>` | The value for a secret field, such as `RETICLE_SECRET_AUTH_PASSWORD` for a field named `auth-password`. Only the field's NAME goes to the platform. The value is typed in on your machine and never sent. |
|
|
63
65
|
|
|
64
|
-
The
|
|
66
|
+
**What you see.** The HUD's Agent Log marks the moment the Harness takes over ("Reticle Harness is driving") and gives its steps their own colour, so you can tell its work from your agent's. Each Harness drive is recorded as its own run, named for its journey and credited to the Harness, beside your agent's run. Any "double-quoted text" in a persona must be on the page when the journey ends, and is checked.
|
|
65
67
|
|
|
66
|
-
|
|
68
|
+
## How it decides
|
|
67
69
|
|
|
68
|
-
|
|
70
|
+
The platform drives with Jev, a System One model that answers typed questions and cannot write. Every choice is a selection from candidates read off the page: which element, which tool, what consequence to claim. Three rules sit around those choices, because each one was a drive that stopped short or claimed nothing:
|
|
69
71
|
|
|
70
|
-
|
|
72
|
+
- A journey that names a page it has not reached ("then turn on automatic refunds in Settings") is not finished. The Harness goes there instead of stopping.
|
|
73
|
+
- A dialog whose destructive action already ran is closed rather than treated as the end of the journey.
|
|
74
|
+
- A control the destructive-action gate refused is a write, so the Harness always claims a request or a signal for it. A save the server rejects then fails visibly instead of passing as nothing to prove.
|
|
71
75
|
|
|
72
76
|
## Turning it off, and who pays for it
|
|
73
77
|
|
|
74
78
|
A project linked to a Reticle workspace reads two things from it before a drive starts, and honours both:
|
|
75
79
|
|
|
76
|
-
- **The switch.** Autonomous driving can be turned off per project
|
|
77
|
-
- **
|
|
80
|
+
- **The switch.** Autonomous driving can be turned off per project, from the HUD's Reticle Harness switch or the dashboard (Settings โ Verification model). A drive then refuses and says where to turn it back on. Switched off while a platform drive is running, the drive stops at its next turn with `stopReason: "stopped"`, keeps what it drove, and says so in the Agent Log. Everything else is unaffected, including the tools your own agent drives with.
|
|
81
|
+
- **Credits.** Every workspace gets Harness credits each 30 days: Free 500, Pro 4,800 a seat, Enterprise as agreed. One credit is one decision the Harness makes. The HUD shows how many are left; once they are spent a drive is refused with that number and the way to get more.
|
|
78
82
|
|
|
79
|
-
|
|
83
|
+
A daemon that cannot reach the platform at all drives normally: an unreachable settings endpoint is not a reason to lose a feature you were never told to stop using.
|
|
80
84
|
|
|
81
85
|
## What it will not do
|
|
82
86
|
|
package/docs/cli/doctor.mdx
CHANGED
|
@@ -74,6 +74,12 @@ All three captures below are real, taken by pointing `PLAYWRIGHT_BROWSERS_PATH`
|
|
|
74
74
|
|
|
75
75
|
**`โ using the installed Google Chrome`** (or Microsoft Edge) means the pinned build is absent and Reticle drives the browser you already have instead, through Playwright's channel. Nothing to do: the line also names the command that adds Playwright's own build, if you want it.
|
|
76
76
|
|
|
77
|
+
**`โ using <path> (RETICLE_CHROMIUM_PATH)`** means you named the browser with [`RETICLE_CHROMIUM_PATH`](/environment), so the bundled revision is not checked at all. If the path does not exist, is not a file (a directory, say), or is not executable, the line says which instead, and offers no install command, because installing would not fix a wrong path:
|
|
78
|
+
|
|
79
|
+
```
|
|
80
|
+
chromium โ RETICLE_CHROMIUM_PATH points at /opt/nope/chrome, which does not exist; fix the path, or unset it to use Playwright's own Chromium
|
|
81
|
+
```
|
|
82
|
+
|
|
77
83
|
When neither is there, Reticle does not refuse. The first command that needs a browser (a lease, `verify`, a drive) runs the bundled Playwright's own pinned install for you, announced on stderr so `reticle mcp`'s stdout stays clean. The two `โ` lines below are what you see when that has not happened yet, or failed.
|
|
78
84
|
|
|
79
85
|
**`โ wrong revision`** means builds are installed and none of them is the wanted one. One pinned download away. The line names the revision Playwright wants, then every revision the root actually holds, then the exact command:
|
package/docs/cli/drive.mdx
CHANGED
|
@@ -53,10 +53,16 @@ A daemon on `:4400` is the normal state the moment any agent connects, and `driv
|
|
|
53
53
|
|
|
54
54
|
```bash
|
|
55
55
|
$ npx @reticlehq/server drive http://localhost:5173
|
|
56
|
-
{"event":"reticle_drive_attached","port":4400,"url":"http://localhost:5173","sessionId":"lease-9f2bโฆ","ready":true}
|
|
56
|
+
{"event":"reticle_drive_attached","port":4400,"url":"http://localhost:5173","sessionId":"lease-9f2bโฆ","ready":true,"projectId":"web","title":"Web"}
|
|
57
57
|
```
|
|
58
58
|
|
|
59
|
-
A plain-text line follows it naming the same session, how long it survives untouched (any tool call against it resets that), and, if the page never dialled the bridge, why.
|
|
59
|
+
A plain-text line follows it naming the same session, the app it belongs to (the `projectId` and title the page reported), how long it survives untouched (any tool call against it resets that), and, if the page never dialled the bridge, why.
|
|
60
|
+
|
|
61
|
+
In a monorepo the port you meant for one app can be held by another. When the current directory's `.reticle.json` names a different project from the one the page reported, the line ends with a warning saying so, and the JSON carries both as `projectId` and `expectedProjectId`. Real capture, with app `admin` on the port, `drive` run from app `web`, and the sentence break shown as `...`:
|
|
62
|
+
|
|
63
|
+
```
|
|
64
|
+
attached to the Reticle daemon on :4497 ... it is driving http://localhost:5177/?__reticle_project=admin (project "admin", "Admin console") as session lease-74bf5522-8eee-4ea2-b66d-4c056c7dad3a, which every Reticle tool can address. It is released after 300s untouched; any tool call against it resets that. Warning: this directory's .reticle.json is project "web", but the page at http://localhost:5177/?__reticle_project=admin is project "admin", so another app is probably serving that port. Check which dev server is on it before trusting anything this session reports.
|
|
65
|
+
```
|
|
60
66
|
|
|
61
67
|
That session lives in the daemon, so the tools your agent already has open can address it by id. You do **not** need `reticle stop` first, and should not use it: the MCP proxy respawns a daemon as soon as the next tool call arrives, which is a race a manual `stop` loses.
|
|
62
68
|
|
package/docs/cli/init.mdx
CHANGED
|
@@ -74,21 +74,19 @@ With `--no-mcp`, the whole MCP and rules group collapses into one skipped line:
|
|
|
74
74
|
--no-mcp ... also skips the agent rule files (CLAUDE.md / AGENTS.md / .cursor) and the /reticle command
|
|
75
75
|
```
|
|
76
76
|
|
|
77
|
-
Run from a workspace root with several apps, it refuses to guess,
|
|
77
|
+
Run from a workspace root with several apps, it refuses to guess, prints a command for each one, and exits `1`:
|
|
78
78
|
|
|
79
79
|
```
|
|
80
|
-
Several apps found in this workspace. Re-run `reticle init`
|
|
81
|
-
adapters/build/next
|
|
82
|
-
adapters/build/vite
|
|
83
|
-
apps/atlas
|
|
84
|
-
apps/bench-app
|
|
85
|
-
apps/electron-smoke
|
|
86
|
-
apps/large-dom-bench
|
|
87
|
-
apps/next-smoke
|
|
88
|
-
apps/tauri-smoke
|
|
89
|
-
apps/vibe-builder-demo
|
|
90
|
-
|
|
91
|
-
Or name one without changing directory: reticle init --app apps/next-smoke
|
|
80
|
+
Several apps found in this workspace. Re-run `reticle init` for the one you want:
|
|
81
|
+
reticle init --app adapters/build/next
|
|
82
|
+
reticle init --app adapters/build/vite
|
|
83
|
+
reticle init --app apps/atlas
|
|
84
|
+
reticle init --app apps/bench-app
|
|
85
|
+
reticle init --app apps/electron-smoke
|
|
86
|
+
reticle init --app apps/large-dom-bench
|
|
87
|
+
reticle init --app apps/next-smoke
|
|
88
|
+
reticle init --app apps/tauri-smoke
|
|
89
|
+
reticle init --app apps/vibe-builder-demo
|
|
92
90
|
```
|
|
93
91
|
|
|
94
92
|
Given `--app`, it says which directory it moved to before printing the plan:
|
package/docs/cli/status.mdx
CHANGED
|
@@ -45,7 +45,11 @@ A session's parenthesised notes are the ones that explain an answer you would ot
|
|
|
45
45
|
|
|
46
46
|
### `--json`
|
|
47
47
|
|
|
48
|
-
The same facts as one
|
|
48
|
+
The same facts as one JSON line on stdout, so a caller can pipe it to a parser:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
npx @reticlehq/server status --json | jq '.running, .sessionCount'
|
|
52
|
+
```
|
|
49
53
|
|
|
50
54
|
```json
|
|
51
55
|
{
|
package/docs/cli/version.mdx
CHANGED
|
@@ -16,10 +16,10 @@ All three are the same command. No flags.
|
|
|
16
16
|
|
|
17
17
|
## What it prints
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
The version, and nothing else, on stdout, so `V=$(reticle version)` works:
|
|
20
20
|
|
|
21
|
-
```
|
|
22
|
-
|
|
21
|
+
```text
|
|
22
|
+
3.6.0
|
|
23
23
|
```
|
|
24
24
|
|
|
25
25
|
## Exit codes
|
package/docs/cli.mdx
CHANGED
|
@@ -38,7 +38,7 @@ For a self-hosted cloud, add `--url <cloud origin>`. If the app was already wire
|
|
|
38
38
|
|
|
39
39
|
### `reticle init`
|
|
40
40
|
|
|
41
|
-
Wires Reticle into the project in the current directory, then boots the app and proves a session connected. It exits non-zero if nothing connected, and prints what is left to do. It does not drive: proving a flow is the FIRST RUN, `reticle verify <url> --explore --persona "<who does what>"`.
|
|
41
|
+
Wires Reticle into the project in the current directory, then boots the app and proves a session connected. It exits non-zero if nothing connected, and prints what is left to do. It does not drive: proving a flow is the FIRST RUN, which your agent drives with `reticle_act_and_wait` and an `until` on its last step, or, with a linked project, `reticle verify <url> --explore --persona "<who does what>"`.
|
|
42
42
|
|
|
43
43
|
```
|
|
44
44
|
reticle init [--env KEY=VALUE]... [--app <dir>] [--license <key>]
|
package/docs/desktop.mdx
CHANGED
|
@@ -210,13 +210,15 @@ installReticleCapture(win);
|
|
|
210
210
|
|
|
211
211
|
That is all: no CDP flag, no extra packages, and it works on a packaged `file://` renderer. `reticle_screenshot` and `reticle_visual_diff` then work on your app.
|
|
212
212
|
|
|
213
|
+
In a multi-window app, name each window: `installReticleCapture(win, { label: 'settings' })`. The session list then shows `window: "settings"`. Electron windows have no name of their own, and two of them often share a url.
|
|
214
|
+
|
|
213
215
|
Alternatively, since an Electron renderer _is_ Chromium, `--remote-debugging-port=9222` plus `RETICLE_CDP_URL=http://127.0.0.1:9222` also works and additionally enables `fullPage` (the main-process route captures the window as composited, so it cannot scroll-stitch).
|
|
214
216
|
|
|
215
217
|
**Tauri: one Rust command.** The crate is versioned independently of the npm packages:
|
|
216
218
|
|
|
217
219
|
```toml
|
|
218
220
|
[dependencies]
|
|
219
|
-
reticle-tauri = "3.
|
|
221
|
+
reticle-tauri = "3.6"
|
|
220
222
|
```
|
|
221
223
|
|
|
222
224
|
```rust
|
|
@@ -344,6 +346,8 @@ Playwright MCP is faster. It is also structurally unable to see an IPC failure,
|
|
|
344
346
|
|
|
345
347
|
**`reticle open` says there is nothing to open.** That is correct for a desktop app. There is no URL, and there is no `reticle drive` for desktop either. Both launch a browser, which is not what you are testing.
|
|
346
348
|
|
|
349
|
+
**Several windows, and the wrong one gets driven.** Every window that loads the SDK is its own session, and `reticle_session { action: "list" }` names each (`window: "main"`: Tauri's label, or the `label` you gave `installReticleCapture` on Electron) with whether it is `hidden`. A page served as an error (a dev server's 404 for a static page, say) carries `documentStatus` and is never auto-selected ahead of a working one. To drive a specific window, pass its `sessionId`. To get rid of a stray hidden window for good, call `reticle_session { action: "end", sessionId, disconnect: true }`. It stays detached across its own reloads until the daemon restarts.
|
|
350
|
+
|
|
347
351
|
**A screenshot came back partly blank.** The window is occluded or minimized, so it is only partially composited. Bring it forward and capture again.
|
|
348
352
|
|
|
349
353
|
**`{ ok: false, reason: 'full-page-unsupported' }`.** You asked for `fullPage: true` on a platform that cannot render offscreen. Only Tauri on Linux (WebKitGTK) can. Capture the viewport instead, or scroll and capture in sections.
|
package/docs/environment.mdx
CHANGED
|
@@ -33,6 +33,7 @@ Reticle works with none of these set. Each one changes a single behaviour, and m
|
|
|
33
33
|
| Variable | Read by | What it does |
|
|
34
34
|
| --- | --- | --- |
|
|
35
35
|
| `RETICLE_CDP_URL` | daemon | Attach to a browser that is already running, over CDP, instead of launching one. |
|
|
36
|
+
| `RETICLE_CHROMIUM_PATH` | daemon, `drive`, `verify`, `doctor` | The Chromium executable to launch, for a machine where Playwright's own build is missing and cannot be installed and there is no Chrome or Edge in the usual place. When set, nothing else is tried: no Playwright build, no Chrome or Edge, no install. A path that does not exist, is not a file, or is not executable is refused with a message naming it and saying which. `doctor` reports on this path instead of the bundled build. |
|
|
36
37
|
| `RETICLE_MAX_CONTEXTS` | daemon | The most leased headless browser contexts the pool runs at once. |
|
|
37
38
|
| `RETICLE_MAX_MESSAGES_PER_SECOND` | daemon | Events per second a page may send before the bridge starts sampling them. It never disconnects. Raise it for a legitimately busy app, such as a streaming dashboard. |
|
|
38
39
|
|
|
@@ -62,13 +63,8 @@ Reticle works with none of these set. Each one changes a single behaviour, and m
|
|
|
62
63
|
| `RETICLE_CLOUD_KEY` | CLI, daemon | The key's earlier name. Still honoured. |
|
|
63
64
|
| `RETICLE_CLOUD_URL`, `RETICLE_URL` | CLI, daemon | The platform host. `RETICLE_CLOUD_URL` wins when both are set. |
|
|
64
65
|
| `RETICLE_SYNC_INTERVAL_MS` | `reticle sync --watch` | How often the watching sync runs. Every 60 seconds by default. |
|
|
65
|
-
| `
|
|
66
|
-
| `
|
|
67
|
-
| `RETICLE_HARNESS_BASE_URL` | autonomous drive | A proxy or gateway in front of the model API. |
|
|
68
|
-
| `RETICLE_HARNESS_MAX_STEPS` | autonomous drive | A hard ceiling on model turns in one drive. It bounds cost. |
|
|
69
|
-
| `RETICLE_HARNESS_DRIVER` | autonomous drive | Which model drives: `anthropic` (the default) or `jev`. |
|
|
70
|
-
| `JEV_API_KEY`, `RETICLE_HARNESS_JEV_URL` | autonomous drive | A direct key and base URL for the `jev` driver. The usual path is `RETICLE_API_KEY` through the platform. |
|
|
71
|
-
| `OPENAI_API_KEY`, `RETICLE_HARNESS_OPENAI_MODEL` | autonomous drive | A direct key and model for the OpenAI driver. |
|
|
66
|
+
| `RETICLE_HARNESS_MAX_STEPS` | autonomous drive | A hard ceiling on steps in one drive. It bounds cost. The drive itself runs on the platform and needs a linked project; every plan, Free included, has monthly Harness credits. |
|
|
67
|
+
| `RETICLE_SECRET_<FIELD>` | autonomous drive, replay | The value of a secret field, typed in on this machine. Only the field's name goes to the platform. |
|
|
72
68
|
|
|
73
69
|
## Licensing
|
|
74
70
|
|
package/docs/getting-started.md
CHANGED
|
@@ -4,7 +4,7 @@ description: 'Zero to your agent verifying your real app, step by step, with wor
|
|
|
4
4
|
icon: rocket
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
**To get started
|
|
7
|
+
**To get started: run the installer, then `reticle init` in your app directory before opening your coding agent.** The installer puts the CLI on the machine and registers its MCP tools with supported agents. `init` wires your app and checks that a browser session connected; without it the agent has the tools and nothing to point them at. For a cloud dashboard, use `reticle connect --project "My App"`, which does the same and also links a cloud project and syncs history. The first run is what proves anything: ask your agent to verify one journey in your app, or use `reticle_verify { action: "explore", persona: "<the journey worth proving>" }`. A connected app is not a verified one. You need Node 20.11 or newer, an app you run locally, and an agent that speaks MCP.
|
|
8
8
|
|
|
9
9
|
> **Looking for the fast path?** [Quickstart](/quickstart) gets you to a real verdict in five minutes, and every response on it was captured live. [Agentic install](/install-agentic) and [Manual install](/install-manual) cover setup in detail, per agent and per framework.
|
|
10
10
|
>
|
|
@@ -58,17 +58,9 @@ Everything is **dev-only** and **localhost-only**. It's tree-shaken out of produ
|
|
|
58
58
|
|
|
59
59
|
---
|
|
60
60
|
|
|
61
|
-
##
|
|
61
|
+
## Wire your app: on the first run, or `reticle init`
|
|
62
62
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
```bash
|
|
66
|
-
npx @reticlehq/server connect --project "My App"
|
|
67
|
-
```
|
|
68
|
-
|
|
69
|
-
Approve the short browser code if Reticle asks you to sign in. The command then links this folder and sends any history already on the machine. Open or restart your coding agent and ask it to verify one real journey. For a new project, the dashboard has no result until that first run is recorded.
|
|
70
|
-
|
|
71
|
-
## Local-only path: `reticle init`
|
|
63
|
+
Installing Reticle changes nothing in your project. The first time your agent uses Reticle in a project that has never connected (its first `reticle_session { action: "list" }`), Reticle runs `init` there itself and returns the files it changed under `wired`, so you can skip straight to asking your agent to verify a flow. Run `init` yourself to wire a project ahead of time, to preview the changes, or when the agent's MCP server was started outside the project (the call then answers `run_init` with this same command).
|
|
72
64
|
|
|
73
65
|
From your project root:
|
|
74
66
|
|
|
@@ -104,6 +96,16 @@ If you ran `--files-only` with a dev server already running, restart it, then sk
|
|
|
104
96
|
|
|
105
97
|
---
|
|
106
98
|
|
|
99
|
+
## Add a cloud dashboard: `reticle connect`
|
|
100
|
+
|
|
101
|
+
Optional. Instead of, or after, `init`, run this in your app directory:
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
npx @reticlehq/server connect --project "My App"
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
Approve the short browser code if Reticle asks you to sign in. The command then links this folder and sends any history already on the machine. Open or restart your coding agent and ask it to verify one real journey. For a new project, the dashboard has no result until that first run is recorded.
|
|
108
|
+
|
|
107
109
|
## Step 1: Connect your coding agent (MCP), once
|
|
108
110
|
|
|
109
111
|
You don't start the server manually; your agent starts it via MCP. Register Reticle **once, at the user (global) scope** so every project picks it up. There's nothing to add per project.
|
package/docs/human-control.md
CHANGED
|
@@ -25,10 +25,9 @@ MCP is **pull-based**: the agent only receives data when it calls a tool. Reticl
|
|
|
25
25
|
The floating panel (bottom-center, `present: true`) gives you:
|
|
26
26
|
|
|
27
27
|
- **Pause / Resume**: one toggle. Paused turns the panel + page border **amber** with a `PAUSED` badge.
|
|
28
|
-
- **Message box + send.** Type a correction ("check the error state first"), hit Send (or Enter). Your message shows as a `๐ง you:` bubble in the transcript **and** is delivered to the agent.
|
|
29
28
|
- **End** ends the session: panel turns **emerald**, shows `Session ended ยท <summary>`, then fades away.
|
|
30
29
|
- **Minimise (โพ)** collapses the panel to a bar that streams only the live line; click the bar to restore.
|
|
31
|
-
- **Flag a bug**, the button in the corner. Toggle it on, click the element that looks wrong, type what's wrong (โ/Ctrl+Enter to send, Esc to back out). Reticle pins a numbered marker, logs your flag in the panel, and hands the agent a structured mark.
|
|
30
|
+
- **Flag a bug**, the button in the corner. Toggle it on, click the element that looks wrong, type what's wrong (โ/Ctrl+Enter to send, Esc to back out). Reticle pins a numbered marker, logs your flag in the panel, and hands the agent a structured mark. Notes are kept in `.reticle/notes.json` (pending and resolved), so a reload or a daemon restart does not lose them, and a linked project syncs them to the dashboard.
|
|
32
31
|
|
|
33
32
|
## Flag a bug: annotate the mistake where you see it
|
|
34
33
|
|
package/docs/index.mdx
CHANGED
|
@@ -28,7 +28,7 @@ irm https://raw.githubusercontent.com/reticlehq/reticle/main/install/install.ps1
|
|
|
28
28
|
|
|
29
29
|
</CodeGroup>
|
|
30
30
|
|
|
31
|
-
That registers the MCP server with every coding agent it can reach, so the `reticle_*` tools are there the next time you open one. Then
|
|
31
|
+
That registers the MCP server with every coding agent it can reach, so the `reticle_*` tools are there the next time you open one. Then ask your agent to verify something in your app: its first Reticle call wires the app and lists the files it changed (`npx @reticlehq/server init` does the same by hand). The [quickstart](/quickstart) walks both.
|
|
32
32
|
|
|
33
33
|
### Or hand the whole thing to your agent
|
|
34
34
|
|
|
@@ -54,8 +54,9 @@ That one command wires the project, starts the dev server, opens the app and
|
|
|
54
54
|
waits for it to connect. Do not walk it by hand: read what it prints, do anything
|
|
55
55
|
it says is outstanding, and re-run it, which is safe. It exits non-zero until the
|
|
56
56
|
app connects, and that connection, not a config file, is what "installed" means.
|
|
57
|
-
Then prove a flow, which is a separate call:
|
|
58
|
-
|
|
57
|
+
Then prove a flow, which is a separate call: drive the journey with
|
|
58
|
+
reticle_act_and_wait and an `until` on its last step (or, with a linked project,
|
|
59
|
+
reticle_verify { action: "explore", persona: "<who does what>" }). Only if it could not run at all, follow
|
|
59
60
|
https://docs.reticle.sh/install-manual.md.
|
|
60
61
|
|
|
61
62
|
Afterwards, use it whenever you change any user-facing behaviour.
|
package/docs/install-manual.mdx
CHANGED
|
@@ -7,7 +7,7 @@ icon: screwdriver-wrench
|
|
|
7
7
|
|
|
8
8
|
**Installing Reticle by hand is two independent halves: register the MCP server so your agent gets the `reticle_*` tools, then add the SDK to your app so there is something for those tools to talk to.** You need both, in that order.
|
|
9
9
|
|
|
10
|
-
Do only the first half and the tools appear but every call reports no session. Do only the second and your app connects to a daemon nobody is asking questions.
|
|
10
|
+
Do only the first half and the tools appear but every call reports no session. Do only the second and your app connects to a daemon nobody is asking questions. Stop after the first half and your agent's first Reticle call wires the app itself when you ask it to verify something, and offers to otherwise.
|
|
11
11
|
|
|
12
12
|
<Warning>
|
|
13
13
|
**You probably do not need this page.** Two commands do all of it:
|
|
@@ -175,7 +175,7 @@ Screenshots and headless mode need the Rust crate, which is versioned independen
|
|
|
175
175
|
|
|
176
176
|
```toml
|
|
177
177
|
[dependencies]
|
|
178
|
-
reticle-tauri = "3.
|
|
178
|
+
reticle-tauri = "3.6"
|
|
179
179
|
```
|
|
180
180
|
|
|
181
181
|
```rust
|
package/docs/packages/tauri.mdx
CHANGED
|
@@ -21,10 +21,10 @@ Tauri IPC observation needs nothing on the Rust side. An `invoke('load_todos')`
|
|
|
21
21
|
|
|
22
22
|
```toml
|
|
23
23
|
[dependencies]
|
|
24
|
-
reticle-tauri = "3.
|
|
24
|
+
reticle-tauri = "3.6"
|
|
25
25
|
```
|
|
26
26
|
|
|
27
|
-
Its own dependencies are `tauri = "2"` plus the per-platform capture backends: `objc2` and friends on macOS, `webview2-com` and `windows` on Windows, `webkit2gtk` and `cairo-rs` on Linux and the BSDs.
|
|
27
|
+
Its own dependencies are `tauri = "2.12"` (the Windows backend must use the same `webview2-com` and `windows` versions Tauri does, so it follows Tauri's minor version) plus the per-platform capture backends: `objc2` and friends on macOS, `webview2-com` and `windows` on Windows, `webkit2gtk` and `cairo-rs` on Linux and the BSDs.
|
|
28
28
|
|
|
29
29
|
## Wiring
|
|
30
30
|
|
|
@@ -61,18 +61,39 @@ Plus a dynamic import of your dev module if one exists. It looks for `src/reticl
|
|
|
61
61
|
| `session` | `string` | Omitted, so the SDK generates one |
|
|
62
62
|
| `projectId` | `string` | Derived from the package name plus the root path |
|
|
63
63
|
| `token` | `string` | `readPairingToken()`, from `~/.reticle/pairing-token` |
|
|
64
|
+
| `present` | `boolean` | `true`. Set `false` to hide Reticle's presenter while keeping the agent connection active |
|
|
64
65
|
| `sourceMapping` | `boolean` | `true`. Set `false` to skip the Babel pass |
|
|
65
66
|
| `inject` | `boolean` | `true`. Set `false` to call `connect()` yourself |
|
|
66
67
|
| `desktop` | `boolean` | `false`. When `true` the connect passes `allowInProduction: true`, which an Electron or Tauri renderer needs, and a `vite build` in a non-production mode (`--mode development`) is instrumented too. A production-mode build is stubbed like a web build |
|
|
67
68
|
| `captureNetworkBodies` | `boolean` | `false`. Also enabled by `VITE_RETICLE_CAPTURE_BODIES=1` |
|
|
68
69
|
| `onWarn` | `(message: string) => void` | `console.warn` |
|
|
69
70
|
|
|
71
|
+
`reticle({ present: false })` still lets the plugin create and configure the connection; it only hides Reticle's visible presenter. `reticle({ inject: false })` disables that generated connection, so your application must call `connect()` itself. In that manual call, pass the pairing token explicitly:
|
|
72
|
+
|
|
73
|
+
```ts
|
|
74
|
+
reticle.connect({
|
|
75
|
+
token: __RETICLE_TOKEN__,
|
|
76
|
+
root: __RETICLE_ROOT__,
|
|
77
|
+
sdkVersion: __RETICLE_SDK_VERSION__,
|
|
78
|
+
});
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Add ambient declarations for these identifiers to `src/vite-env.d.ts` (or another included `.d.ts`) in a TypeScript app:
|
|
82
|
+
|
|
83
|
+
```ts
|
|
84
|
+
declare const __RETICLE_TOKEN__: string;
|
|
85
|
+
declare const __RETICLE_ROOT__: string;
|
|
86
|
+
declare const __RETICLE_SDK_VERSION__: string;
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Vite replaces these `define` identifiers in application source at build time; the declarations let TypeScript typecheck them and do not create runtime globals. The SDK does not discover the pairing token, so pass it explicitly in a hand-written connection:
|
|
90
|
+
|
|
70
91
|
## Other exports
|
|
71
92
|
|
|
72
93
|
| Export | Type | What it is |
|
|
73
94
|
| --- | --- | --- |
|
|
74
95
|
| `RETICLE_VITE_PLUGIN_NAME` | `'reticle'` | The plugin name |
|
|
75
|
-
| `RETICLE_TOKEN_GLOBAL` | `'__RETICLE_TOKEN__'` | The
|
|
96
|
+
| `RETICLE_TOKEN_GLOBAL` | `'__RETICLE_TOKEN__'` | The Vite `define` identifier replaced with the pairing token |
|
|
76
97
|
| `RETICLE_CONNECT_MODULE` | `'/@reticle-connect'` | The virtual module id |
|
|
77
98
|
| `RENDER_PREHOOK_SOURCE` | `string` | The inline render prehook snippet |
|
|
78
99
|
| `RETICLE_DEV_MODULE_CANDIDATES` | readonly tuple | The four dev-module paths it looks for |
|