@revyl/verify 0.6.0 → 0.6.2

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/CHANGELOG.md CHANGED
@@ -1,6 +1,48 @@
1
1
  # Changelog
2
2
 
3
- ## 0.6.0 (unreleased)
3
+ ## 0.6.2 (unreleased)
4
+
5
+ - A Mac or Linux computer that starts prints only its start line with the session link, as Web, iOS and Android do: `[verify] mac: starting computer https://app.revyl.ai/sessions/…?kind=computer`. It no longer adds "Mac computers need a current paid Revyl plan, and Linux computers are not generally available. Ask support@revyl.ai about access." That guidance stays on the errors for a computer that doesn't start: a start Revyl refuses (`computer_not_enabled`, or `runtime_unavailable` for Linux), a start that times out, and a release Verify can't confirm.
6
+ - `verify init --platform mac` no longer prints the availability note under "Next:" or writes it at the top of `verify/example.mts`.
7
+ - Every call sends the same requests as 0.6.1.
8
+
9
+ ## Go 0.5.2 (unreleased)
10
+
11
+ Published as the `go/v0.5.2` tag.
12
+
13
+ - A computer that starts sends only its start line with the session link to `OpenOptions.Log`, as in TypeScript 0.6.2: `mac: starting mac computer https://app.revyl.ai/sessions/…?kind=computer`. Refusals, timeouts and an unconfirmed release keep the availability guidance in their errors.
14
+ - `verify.Version` and the `User-Agent` report 0.5.2. Every call sends the same requests as v0.5.1.
15
+
16
+ ## Python 0.4.2 (unreleased)
17
+
18
+ - A computer that starts prints only its start line with the session link, as in TypeScript 0.6.2: `[verify] mac: starting computer https://app.revyl.ai/sessions/…?kind=computer`. Refusals, timeouts and an unconfirmed release keep the availability guidance in their errors.
19
+ - Every call sends the same requests as 0.4.1.
20
+
21
+ ## 0.6.1 (2026-11-13)
22
+
23
+ - An iOS or Android `open()` that Revyl refuses as invalid (HTTP 400 or 422) throws `INVALID_ARGUMENT` with Revyl's explanation instead of a bare `API_ERROR … failed with HTTP 422`. For a device model or OS version Revyl doesn't offer, the message lists the values it accepts, as in `Revyl refused to start the session (HTTP 422): Unsupported ios runtime '18.5'. Available: ['iOS 27.1', …, 'iOS 18.5']. Change the target to a value Revyl accepts and run again.` No session was started. Web and hosted starts keep their safe diagnostic codes and copy no server text.
24
+ - `device.osVersion` is the name Revyl uses, such as `'iOS 18.5'` or `'Android 14'`, as before; Verify sends it unchanged. The docs now show it that way, with models Revyl offers (`iPhone 16`, `iPhone Air`, `Pixel 7`).
25
+ - `verify init --platform web --url <url>` with a URL other than `https://example.com` writes an example with one validation that passes on any page that loads, instead of example.com's steps.
26
+ - Mac computer messages say what Revyl checks: a current paid plan. `init --platform mac` prints that instead of "early access", and computer errors say `Mac computers need a current paid Revyl plan, and Linux computers are not generally available.`
27
+ - Every other call sends the same requests as 0.6.0.
28
+ - Docs: device selectors Revyl accepts, a mobile exact-actions script that searches Settings for Accessibility, a web exact-actions script that scrolls back up before it locates the cart, `node verify/checkout.mts` in CI, non-owning attach examples that navigate to a public page, Mac availability on paid plans, `init --platform` in the README, your own model's Claude results, and `end-to-end.md` marked as a record of the 0.1.0 and 0.2.0 runs.
29
+
30
+ ## Go 0.5.1 (2026-11-13)
31
+
32
+ Published as the `go/v0.5.1` tag.
33
+
34
+ - `ErrValidationFailed` names the step and the reason, as TypeScript does: `Validation failed: "<text>". <reason> See <link>`.
35
+ - An iOS or Android `Open` that Revyl refuses as invalid (HTTP 400 or 422) returns `ErrInvalidArgument` with Revyl's explanation, as in TypeScript 0.6.1, including the device models or OS versions it accepts. No session was started.
36
+ - The computer availability message says Mac computers need a current paid Revyl plan. Every other call sends the same requests as v0.5.0.
37
+
38
+ ## Python 0.4.1 (2026-11-13)
39
+
40
+ - `VALIDATION_FAILED` names the step and the reason, as TypeScript does: `Validation failed: "<text>". <reason> See <link>`. `AsyncSession` gets the same message.
41
+ - An iOS or Android `open()` that Revyl refuses as invalid (HTTP 400 or 422) raises `INVALID_ARGUMENT` with Revyl's explanation, as in TypeScript 0.6.1, including the device models or OS versions it accepts. No session was started.
42
+ - The computer availability message says Mac computers need a current paid Revyl plan. Every other call sends the same requests as 0.4.0.
43
+ - Docs: device selectors Revyl accepts, `open_url("https://example.com")` in the exact-actions example, and a non-owning attach example.
44
+
45
+ ## 0.6.0 (2026-11-12)
4
46
 
5
47
  - Early access: a Mac computer's screen. `tap({ x, y })` clicks a point in screenshot pixels and resolves with it, `screenSize()` returns the screenshot's size, `typeFocused(text, { clear: false })` types where the cursor is, and `pressKey(key, { modifiers })` takes the Web keys and modifiers, where `'meta'` is Command and `'alt'` is Option, as in `pressKey('a', { modifiers: ['meta'] })` to select all.
6
48
  - `typeFocused` on a computer requires `{ clear: false }` and throws `INVALID_ARGUMENT` without it, naming the fix. It takes up to 16,384 characters, with line breaks and tabs; other control characters are refused before anything is sent. Text over 500 characters goes in pieces, in order, and a failure part way says how many characters were certainly typed and whether the failed piece may have been.
@@ -12,7 +54,7 @@
12
54
  - Error messages on a computer say what happened and what to do next. `screen_control_lost` on a screen action throws `SESSION_BUSY` saying nothing was sent and to try again. `owner_unavailable`, a 5xx or no answer on a screen action throws `ACTION_UNCERTAIN` saying to take a screenshot before repeating it. `invalid_request` on `tap({ x, y })` says nothing was clicked and to pick the point from a new screenshot, and `screen_key_unsupported` says nothing was pressed. Partial typing counts characters as Unicode code points, the same in TypeScript, Python and Go, and a failure in the first piece says nothing was certainly typed. Every other computer refusal adds a next step, and the `screen_starting` message says "1 second" rather than "1 seconds".
13
55
  - Docs: a Screen section in `computers.md`, the platform table, `api.md`, `errors.md`, `agents.md` and `llms.txt`. The Web docs say `'meta'` is not the shortcut key there; use `'ctrl'`.
14
56
 
15
- ## Go 0.5.0 (unreleased)
57
+ ## Go 0.5.0 (2026-11-12)
16
58
 
17
59
  Published as the `go/v0.5.0` tag.
18
60
 
@@ -20,7 +62,7 @@ Published as the `go/v0.5.0` tag.
20
62
  - The same limits, errors and refusals as TypeScript 0.6.0: `ErrSessionBusy` for `screen_control_held`, `ErrActionUncertain` for an action Revyl can't confirm, `ErrAuthRejected` for a 403, `ErrActionFailed` for `screen_target_not_found`, a wait of up to 30 seconds on `screen_starting`, and `ErrNotAvailableOnPlatform` before any request for `Locate` and the other exact actions. Every other call sends the same requests as v0.4.0.
21
63
  - The same error messages as TypeScript 0.6.0, each with a next step, with partial typing counted in Unicode code points.
22
64
 
23
- ## Python 0.4.0 (unreleased)
65
+ ## Python 0.4.0 (2026-11-12)
24
66
 
25
67
  - Early access: a Mac computer's screen, as in TypeScript 0.6.0. `tap(Point(x, y))`, `tap("description")` returning the point it clicked, `screen_size()`, `type_focused(text, clear=False)` and `press_key(key, modifiers=[...])`, where `"meta"` is Command. Leaving `clear` out raises `INVALID_ARGUMENT` naming the fix. `AsyncSession` has the same methods.
26
68
  - The same limits, errors and refusals as TypeScript 0.6.0, and every other call sends the same requests as 0.3.0.
@@ -175,7 +217,7 @@ First PyPI release of `revyl-verify` (import `revyl_verify`, Python ≥3.10), pu
175
217
  - Add the source-free `revyl-verify` npm alias with matching API, TypeScript types and CLI, pinned to the exact `@revyl/verify` version. Validate and pack both packages; optional CI publication checks each version independently and publishes the scoped package before the alias.
176
218
  - Add a standard-library-only Go SDK for web, iOS, Android, and early-access Mac and Linux computers. Computer commands, binary files, process handles, screenshots, recording metadata, and confirmed-release cleanup require computer access through support@revyl.ai. Capacity refusals have a distinct `COMPUTER_LIMIT` code; no start or operation is automatically replayed.
177
219
 
178
- ## 0.2.0
220
+ ## 0.2.0 (2026-10-27)
179
221
 
180
222
  Prepared for release; see npm for publication status.
181
223
 
@@ -191,7 +233,7 @@ Prepared for release; see npm for publication status.
191
233
 
192
234
  Regression validation uses fake API responses. The [end-to-end record](https://github.com/RevylAI/verify/blob/v0.2.0/packages/verify/docs/end-to-end.md) distinguishes baseline live runs from startup fixes still awaiting live re-verification.
193
235
 
194
- ## 0.1.0
236
+ ## 0.1.0 (2026-10-26)
195
237
 
196
238
  Published manually from a maintainer's Mac without provenance.
197
239
 
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Verify
2
2
 
3
- ![Terminal output from one Verify script beside a Mac computer's Terminal window showing the macOS version, and the screens the script reached in a cloud browser, an Android emulator, and an iOS simulator](https://raw.githubusercontent.com/RevylAI/verify/v0.6.0/docs/images/verify-hero.webp)
3
+ ![Terminal output from one Verify script beside a Mac computer's Terminal window showing the macOS version, and the screens the script reached in a cloud browser, an Android emulator, and an iOS simulator](https://raw.githubusercontent.com/RevylAI/verify/v0.6.2/docs/images/verify-hero.webp)
4
4
 
5
5
  Verify runs end-to-end checks in a cloud browser, iOS simulator, or Android emulator on Revyl. You write what the agent should do and what must be true afterward, in plain sentences, and call it from a script, a coding agent, CI, or the test runner you already use. When you know exactly what to press, you can tap, type and swipe yourself instead. Verify also opens Mac computers for commands, files, screenshots, and clicks and keys on the screen.
6
6
 
@@ -38,12 +38,12 @@ Ask me before anything that needs my login or approval.
38
38
  Or set it up yourself:
39
39
 
40
40
  ```bash
41
- npx @revyl/verify init
41
+ npx @revyl/verify init --platform ios
42
42
  ```
43
43
 
44
- `init` adds Verify to your project, asks what to open, writes `verify.config.ts` and an example script, signs you in through the browser on the first interactive run, and prints the command that runs the example. With no app id, the iOS and Android examples open the built-in Settings app, so they run on a new account before you upload anything. To skip the config, run `npm install @revyl/verify` and save the example above as `verify/check.mts`, then run `node verify/check.mts`. [Getting started](https://github.com/RevylAI/verify/blob/v0.6.0/packages/verify/docs/getting-started.md) covers sign-in, your own app, and [CI](https://github.com/RevylAI/verify/blob/v0.6.0/packages/verify/docs/ci.md).
44
+ `init` adds Verify to your project, writes `verify.config.ts` and an example script for the platform you pass (`web`, `ios`, `android` or `mac`; in a terminal, leave `--platform` out and it asks), writes `verify.config.ts` and an example script, signs you in through the browser on the first interactive run, and prints the command that runs the example. With no app id, the iOS and Android examples open the built-in Settings app, so they run on a new account before you upload anything. To skip the config, run `npm install @revyl/verify` and save the example above as `verify/check.mts`, then run `node verify/check.mts`. [Getting started](https://github.com/RevylAI/verify/blob/v0.6.2/packages/verify/docs/getting-started.md) covers sign-in, your own app, and [CI](https://github.com/RevylAI/verify/blob/v0.6.2/packages/verify/docs/ci.md).
45
45
 
46
- For finished projects, see [`examples/`](https://github.com/RevylAI/verify/tree/v0.6.0/examples/): a [web store](https://github.com/RevylAI/verify/tree/v0.6.0/examples/web-store/), [mobile Settings](https://github.com/RevylAI/verify/tree/v0.6.0/examples/mobile-settings/), a [Mac workspace](https://github.com/RevylAI/verify/tree/v0.6.0/examples/mac-workspace/), a small [agent platform](https://github.com/RevylAI/verify/tree/v0.6.0/examples/agent-platform/) that runs web and iOS side by side, and [your own model](https://github.com/RevylAI/verify/tree/v0.6.0/examples/byo-model/) (with [Python](https://github.com/RevylAI/verify/blob/v0.6.0/python/examples/byo_model.py) and [Go](https://github.com/RevylAI/verify/blob/v0.6.0/go/examples/byomodel/main.go) versions).
46
+ For finished projects, see [`examples/`](https://github.com/RevylAI/verify/tree/v0.6.2/examples/): a [web store](https://github.com/RevylAI/verify/tree/v0.6.2/examples/web-store/), [mobile Settings](https://github.com/RevylAI/verify/tree/v0.6.2/examples/mobile-settings/), a [Mac workspace](https://github.com/RevylAI/verify/tree/v0.6.2/examples/mac-workspace/), a small [agent platform](https://github.com/RevylAI/verify/tree/v0.6.2/examples/agent-platform/) that runs web and iOS side by side, and [your own model](https://github.com/RevylAI/verify/tree/v0.6.2/examples/byo-model/) (with [Python](https://github.com/RevylAI/verify/blob/v0.6.2/python/examples/byo_model.py) and [Go](https://github.com/RevylAI/verify/blob/v0.6.2/go/examples/byomodel/main.go) versions).
47
47
 
48
48
  ## Exact actions
49
49
 
@@ -60,7 +60,7 @@ await session.instruction('Accept the terms if they are shown'); // the age
60
60
  await session.validation('The welcome screen is shown');
61
61
  ```
62
62
 
63
- `doubleTap`, `typeFocused`, `back`, `goHome`, `openUrl`, `launchApp`, `locate` and `screenSize` round them out; [which call works where](#which-call-works-where) shows the platform limits. Early access. Since TypeScript (`@revyl/verify`) 0.4.0, Python (`revyl-verify`) 0.2.0 and Go v0.3.0. `doubleTap`, `longPress`, `drag`, `typeFocused`, `goHome`, and Web keys and modifiers in `pressKey`, are new in TypeScript 0.5.0, Python 0.3.0 and Go v0.4.0. On a Mac computer's screen, `tap` (by point or by description), `screenSize`, `typeFocused` and `pressKey` are new in TypeScript 0.6.0, Python 0.4.0 and Go v0.5.0. The [Python](https://github.com/RevylAI/verify/blob/v0.6.0/python/README.md#exact-actions) and [Go](https://github.com/RevylAI/verify/blob/v0.6.0/go/README.md#exact-actions) READMEs show them with each language's names. The [web](https://github.com/RevylAI/verify/blob/v0.6.0/packages/verify/docs/web.md#exact-actions) and [mobile](https://github.com/RevylAI/verify/blob/v0.6.0/packages/verify/docs/mobile.md#exact-actions) guides have runnable scripts, and [api.md](https://github.com/RevylAI/verify/blob/v0.6.0/packages/verify/docs/api.md#exact-actions) lists every call.
63
+ `doubleTap`, `typeFocused`, `back`, `goHome`, `openUrl`, `launchApp`, `locate` and `screenSize` round them out; [which call works where](#which-call-works-where) shows the platform limits. Early access. Since TypeScript (`@revyl/verify`) 0.4.0, Python (`revyl-verify`) 0.2.0 and Go v0.3.0. `doubleTap`, `longPress`, `drag`, `typeFocused`, `goHome`, and Web keys and modifiers in `pressKey`, are new in TypeScript 0.5.0, Python 0.3.0 and Go v0.4.0. On a Mac computer's screen, `tap` (by point or by description), `screenSize`, `typeFocused` and `pressKey` are new in TypeScript 0.6.0, Python 0.4.0 and Go v0.5.0. The [Python](https://github.com/RevylAI/verify/blob/v0.6.2/python/README.md#exact-actions) and [Go](https://github.com/RevylAI/verify/blob/v0.6.2/go/README.md#exact-actions) READMEs show them with each language's names. The [web](https://github.com/RevylAI/verify/blob/v0.6.2/packages/verify/docs/web.md#exact-actions) and [mobile](https://github.com/RevylAI/verify/blob/v0.6.2/packages/verify/docs/mobile.md#exact-actions) guides have runnable scripts, and [api.md](https://github.com/RevylAI/verify/blob/v0.6.2/packages/verify/docs/api.md#exact-actions) lists every call.
64
64
 
65
65
  ## Your own model
66
66
 
@@ -74,7 +74,7 @@ await session.instruction('Open Privacy', { model: 'openai/gpt-5.5' });
74
74
  await open('ios', { model: { id: 'qwen-3.8-27b', baseURL: 'https://api.cerebras.ai/v1', apiKey: process.env.CEREBRAS_API_KEY } });
75
75
  ```
76
76
 
77
- Since TypeScript (`@revyl/verify`) 0.4.0, Python (`revyl-verify`) 0.2.0 and Go v0.3.0; the [Python](https://github.com/RevylAI/verify/blob/v0.6.0/python/README.md#your-own-model) and [Go](https://github.com/RevylAI/verify/blob/v0.6.0/go/README.md#your-own-model) READMEs show them with each language's names. Built in: `anthropic`, `openai`, `google`, `openrouter`, `groq`, `cerebras`, `xai` and `ollama`; anything OpenAI-compatible works through `baseURL`. Early access; [Use your own model](https://github.com/RevylAI/verify/blob/v0.6.0/packages/verify/docs/own-model.md) covers the providers, picking a model, what Revyl still sees, limits and troubleshooting.
77
+ Since TypeScript (`@revyl/verify`) 0.4.0, Python (`revyl-verify`) 0.2.0 and Go v0.3.0; the [Python](https://github.com/RevylAI/verify/blob/v0.6.2/python/README.md#your-own-model) and [Go](https://github.com/RevylAI/verify/blob/v0.6.2/go/README.md#your-own-model) READMEs show them with each language's names. Built in: `anthropic`, `openai`, `google`, `openrouter`, `groq`, `cerebras`, `xai` and `ollama`; anything OpenAI-compatible works through `baseURL`. Early access; [Use your own model](https://github.com/RevylAI/verify/blob/v0.6.2/packages/verify/docs/own-model.md) covers the providers, picking a model, what Revyl still sees, limits and troubleshooting.
78
78
 
79
79
  ## Packages
80
80
 
@@ -82,8 +82,8 @@ Since TypeScript (`@revyl/verify`) 0.4.0, Python (`revyl-verify`) 0.2.0 and Go v
82
82
  | --- | --- | --- |
83
83
  | [`@revyl/verify`](https://www.npmjs.com/package/@revyl/verify) | `npm install @revyl/verify` | TypeScript SDK and the `verify` CLI (`init`, `login`, `logout`, `whoami`). Published on npm, Node.js 22.18 or later. |
84
84
  | [`revyl-verify`](https://www.npmjs.com/package/revyl-verify) (npm) | `npm install revyl-verify` | Alias of `@revyl/verify` at the same version. |
85
- | [Go module](https://github.com/RevylAI/verify/tree/go/v0.5.0/go) | `go get github.com/RevylAI/verify/go@v0.5.0` | Published as the `go/v0.5.0` tag, Go 1.26.9 or later. Calls return errors instead of throwing. |
86
- | [`revyl-verify`](https://pypi.org/project/revyl-verify/) (PyPI) | `pip install revyl-verify` or `uv add revyl-verify` | Python SDK, published on PyPI. Python 3.10 or later, sync and asyncio APIs, no CLI; see the [Python guide](https://github.com/RevylAI/verify/blob/v0.6.0/python/README.md). |
85
+ | [Go module](https://github.com/RevylAI/verify/tree/go/v0.5.2/go) | `go get github.com/RevylAI/verify/go@v0.5.2` | Published as the `go/v0.5.2` tag, Go 1.26.9 or later. Calls return errors instead of throwing. |
86
+ | [`revyl-verify`](https://pypi.org/project/revyl-verify/) (PyPI) | `pip install revyl-verify` or `uv add revyl-verify` | Python SDK, published on PyPI. Python 3.10 or later, sync and asyncio APIs, no CLI; see the [Python guide](https://github.com/RevylAI/verify/blob/v0.6.2/python/README.md). |
87
87
 
88
88
  ## Platforms
89
89
 
@@ -116,16 +116,16 @@ Since TypeScript (`@revyl/verify`) 0.4.0, Python (`revyl-verify`) 0.2.0 and Go v
116
116
 
117
117
  A call a platform doesn't support throws `NOT_AVAILABLE_ON_PLATFORM`, and its message names the alternative.
118
118
 
119
- Web is available to every organization. Mac computers are early access and have a server-bounded lifetime; see [computers](https://github.com/RevylAI/verify/blob/v0.6.0/packages/verify/docs/computers.md).
119
+ Web is available to every organization. Mac computers are available to organizations on a current paid Revyl plan and have a server-bounded lifetime; see [computers](https://github.com/RevylAI/verify/blob/v0.6.2/packages/verify/docs/computers.md).
120
120
 
121
121
  ## Documentation
122
122
 
123
- The [documentation](https://github.com/RevylAI/verify/tree/v0.6.0/packages/verify/docs/) covers the [API](https://github.com/RevylAI/verify/blob/v0.6.0/packages/verify/docs/api.md), [configuration](https://github.com/RevylAI/verify/blob/v0.6.0/packages/verify/docs/configuration.md), [web](https://github.com/RevylAI/verify/blob/v0.6.0/packages/verify/docs/web.md), [mobile](https://github.com/RevylAI/verify/blob/v0.6.0/packages/verify/docs/mobile.md), [computers](https://github.com/RevylAI/verify/blob/v0.6.0/packages/verify/docs/computers.md), [CI](https://github.com/RevylAI/verify/blob/v0.6.0/packages/verify/docs/ci.md), [your own model](https://github.com/RevylAI/verify/blob/v0.6.0/packages/verify/docs/own-model.md), [errors and troubleshooting](https://github.com/RevylAI/verify/blob/v0.6.0/packages/verify/docs/errors.md), [coding agents](https://github.com/RevylAI/verify/blob/v0.6.0/packages/verify/docs/agents.md), and [live end-to-end results](https://github.com/RevylAI/verify/blob/v0.6.0/packages/verify/docs/end-to-end.md). The npm package ships these pages in `node_modules/@revyl/verify/docs/`, with an [llms.txt](https://github.com/RevylAI/verify/blob/v0.6.0/packages/verify/docs/llms.txt) index, so a coding agent can read the docs for the version you installed. The Revyl docs site has an overview at [docs.revyl.com/verify](https://docs.revyl.com/verify).
123
+ The [documentation](https://github.com/RevylAI/verify/tree/v0.6.2/packages/verify/docs/) covers the [API](https://github.com/RevylAI/verify/blob/v0.6.2/packages/verify/docs/api.md), [configuration](https://github.com/RevylAI/verify/blob/v0.6.2/packages/verify/docs/configuration.md), [web](https://github.com/RevylAI/verify/blob/v0.6.2/packages/verify/docs/web.md), [mobile](https://github.com/RevylAI/verify/blob/v0.6.2/packages/verify/docs/mobile.md), [computers](https://github.com/RevylAI/verify/blob/v0.6.2/packages/verify/docs/computers.md), [CI](https://github.com/RevylAI/verify/blob/v0.6.2/packages/verify/docs/ci.md), [your own model](https://github.com/RevylAI/verify/blob/v0.6.2/packages/verify/docs/own-model.md), [errors and troubleshooting](https://github.com/RevylAI/verify/blob/v0.6.2/packages/verify/docs/errors.md), [coding agents](https://github.com/RevylAI/verify/blob/v0.6.2/packages/verify/docs/agents.md), and [live end-to-end results](https://github.com/RevylAI/verify/blob/v0.6.2/packages/verify/docs/end-to-end.md). The npm package ships these pages in `node_modules/@revyl/verify/docs/`, with an [llms.txt](https://github.com/RevylAI/verify/blob/v0.6.2/packages/verify/docs/llms.txt) index, so a coding agent can read the docs for the version you installed. The Revyl docs site has an overview at [docs.revyl.com/verify](https://docs.revyl.com/verify).
124
124
 
125
125
  ## Status
126
126
 
127
- Verify is at 0.x, so APIs can still change between minor releases; the [changelog](https://github.com/RevylAI/verify/blob/v0.6.0/CHANGELOG.md) records each release. Mac computers are early access. See [Contributing](https://github.com/RevylAI/verify/blob/v0.6.0/CONTRIBUTING.md) and [Releasing](https://github.com/RevylAI/verify/blob/v0.6.0/RELEASING.md) to work on Verify.
127
+ Verify is at 0.x, so APIs can still change between minor releases; the [changelog](https://github.com/RevylAI/verify/blob/v0.6.2/CHANGELOG.md) records each release. See [Contributing](https://github.com/RevylAI/verify/blob/v0.6.2/CONTRIBUTING.md) and [Releasing](https://github.com/RevylAI/verify/blob/v0.6.2/RELEASING.md) to work on Verify.
128
128
 
129
129
  ## License
130
130
 
131
- [Apache 2.0](https://github.com/RevylAI/verify/blob/v0.6.0/LICENSE).
131
+ [Apache 2.0](https://github.com/RevylAI/verify/blob/v0.6.2/LICENSE).
@@ -46,8 +46,12 @@ export class RevylClient {
46
46
  throw apiError(method, path, response);
47
47
  return parseJson(response, `${method} ${path}`);
48
48
  }
49
- startDevice(request, signal) {
50
- return this.json('POST', '/api/v1/execution/start_device', { body: request, retry: false, timeoutMs: 120_000, signal });
49
+ async startDevice(request, signal) {
50
+ const path = '/api/v1/execution/start_device';
51
+ const response = await this.send('POST', path, { body: request, retry: false, timeoutMs: 120_000, signal });
52
+ if (response.status < 200 || response.status >= 300)
53
+ throw (request.platform !== 'web' && mobileStartRefusal(response)) || apiError('POST', path, response);
54
+ return parseJson(response, `POST ${path}`);
51
55
  }
52
56
  getDeviceSession(sessionId, signal) {
53
57
  return this.json('GET', `/api/v1/execution/device-sessions/${encodeURIComponent(sessionId)}`, { signal });
@@ -216,6 +220,21 @@ const START_ERROR_DETAILS = new Set([
216
220
  export function responseRefusalReason(response) {
217
221
  return responseKnownDetail(response, REFUSAL_REASONS);
218
222
  }
223
+ function mobileStartRefusal(response) {
224
+ if (response.status !== 400 && response.status !== 422 || edgeBlockedError(response))
225
+ return undefined;
226
+ let detail;
227
+ try {
228
+ detail = JSON.parse(new TextDecoder().decode(response.body))?.detail;
229
+ }
230
+ catch {
231
+ return undefined;
232
+ }
233
+ if (typeof detail !== 'string' || /^[a-z0-9_]*$/.test(detail.trim()))
234
+ return undefined;
235
+ const message = detail.trim().slice(0, 500);
236
+ return new VerifyError('INVALID_ARGUMENT', `Revyl refused to start the session (HTTP ${response.status}): ${/[.!?]$/.test(message) ? message : `${message}.`} Change the target to a value Revyl accepts and run again.`, { httpStatus: response.status });
237
+ }
219
238
  function responseKnownDetail(response, codes) {
220
239
  try {
221
240
  const parsed = JSON.parse(new TextDecoder().decode(response.body));
package/dist/cli/init.js CHANGED
@@ -99,10 +99,9 @@ ${target}
99
99
  });
100
100
  `;
101
101
  }
102
- function scriptTemplate({ platform, appId }) {
102
+ function scriptTemplate({ platform, appId, url }) {
103
103
  if (platform === 'mac') {
104
- return `// Mac computers are in early access; ask support@revyl.ai to enable your organization.
105
- import assert from 'node:assert/strict';
104
+ return `import assert from 'node:assert/strict';
106
105
  import { open } from '@revyl/verify';
107
106
 
108
107
  const session = await open('mac');
@@ -117,16 +116,19 @@ try {
117
116
  }
118
117
  `;
119
118
  }
120
- const steps = platform === 'web'
119
+ const steps = platform === 'web' && (url === undefined || /^https:\/\/example\.com\/?$/.test(url))
121
120
  ? `await session.instruction('Follow the link on the page');
122
121
  await session.validation('A page about domains reserved for documentation is shown');`
123
- : !appId && platform === 'ios'
124
- ? `await session.instruction('Open General, then About');
122
+ : platform === 'web'
123
+ ? `// Checks only that ${url} loads. Replace it with steps for your app, such as an instruction followed by a validation.
124
+ await session.validation('The page has finished loading and shows its content, not an error page');`
125
+ : !appId && platform === 'ios'
126
+ ? `await session.instruction('Open General, then About');
125
127
  await session.validation('The screen shows the operating system version');`
126
- : !appId && platform === 'android'
127
- ? `await session.instruction('Open the screen that shows information about this device, such as About or About phone, then scroll or navigate until the operating system version is visible');
128
+ : !appId && platform === 'android'
129
+ ? `await session.instruction('Open the screen that shows information about this device, such as About or About phone, then scroll or navigate until the operating system version is visible');
128
130
  await session.validation('The screen shows the version of the operating system');`
129
- : `await session.instruction('Wait for the app to finish opening and show its first screen');
131
+ : `await session.instruction('Wait for the app to finish opening and show its first screen');
130
132
  await session.validation('The app has opened and shows its first screen without an error');`;
131
133
  return `import { open } from '${PACKAGE_NAME}';
132
134
 
package/dist/cli/main.js CHANGED
@@ -125,11 +125,9 @@ async function initCommand(args) {
125
125
  const result = await initProject(process.cwd(), answers, { force: values.force ?? false });
126
126
  process.stdout.write(`Created ${result.created.join(' and ')}${result.gitignoreUpdated ? ', and added .verify/ to .gitignore' : ''}.\n`);
127
127
  await signInAndCheck(interactive);
128
- const steps = answers.platform === 'mac'
129
- ? ['Mac computers are early access. Ask support@revyl.ai about access.', 'Once your organization has Mac access, run: node verify/example.mts']
130
- : answers.appId
131
- ? ['Run: node verify/example.mts']
132
- : ['Run: node verify/example.mts', 'To test your own app, put its Revyl app id in verify.config.ts in place of the Settings bundle id.'];
128
+ const steps = answers.platform === 'mac' || answers.appId
129
+ ? ['Run: node verify/example.mts']
130
+ : ['Run: node verify/example.mts', 'To test your own app, put its Revyl app id in verify.config.ts in place of the Settings bundle id.'];
133
131
  process.stdout.write([
134
132
  'Next:',
135
133
  ...steps.map((step, index) => ` ${index + 1}. ${step}`),
@@ -11,7 +11,7 @@ import { DeviceSession, checkLocation, pngSize } from './session.js';
11
11
  const UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
12
12
  const STATES = new Set(['starting', 'active', 'closing', 'stopped', 'failed', 'owner_lost']);
13
13
  const MAX_OUTPUT_BYTES = 1_048_576;
14
- const COMPUTER_AVAILABILITY = 'Computers are early access. Ask support@revyl.ai about access.';
14
+ const COMPUTER_AVAILABILITY = 'Mac computers need a current paid Revyl plan, and Linux computers are not generally available. Ask support@revyl.ai about access.';
15
15
  const COMPUTER_CAPACITY = 'Computer admission was refused because of queued work (including iOS) or the concurrency limit. Verify will not retry the start.';
16
16
  const ERROR_CODES = new Set(['computer_not_enabled', 'run_closed', 'inaccessible', 'invalid_handle', 'operation_not_found', 'owner_unavailable', 'invalid_request', 'unauthenticated', 'forbidden', 'runtime_unavailable', 'start_failed', 'computer_limit', 'request_conflict', 'run_conflict', 'evidence_conflict', 'evidence_unavailable', 'authentication_unavailable', 'operation_limit', 'screen_starting', 'screen_unavailable', 'screen_control_held', 'screen_control_lost', 'screen_input_unavailable', 'screen_input_uncertain', 'screen_key_unsupported', 'screen_text_unsupported', 'screen_target_not_found', 'screen_target_unavailable']);
17
17
  const COMPUTER_KEYS = { enter: 'Return', backspace: 'BackSpace', tab: 'Tab', escape: 'Escape', delete: 'Delete', space: 'space', arrowup: 'Up', arrowdown: 'Down', arrowleft: 'Left', arrowright: 'Right', home: 'Home', end: 'End', pageup: 'Page_Up', pagedown: 'Page_Down' };
@@ -57,7 +57,7 @@ export class ComputerSession {
57
57
  let createAcknowledged = false;
58
58
  trackSession(session);
59
59
  try {
60
- session.log(`starting computer ${session.viewerUrl}. ${COMPUTER_AVAILABILITY}`);
60
+ session.log(`starting computer ${session.viewerUrl}`);
61
61
  const response = await session.request('POST', '', { computer_session_id: session.id, os: target.platform === 'mac' ? 'macos' : 'linux' }, signal);
62
62
  createAcknowledged = true;
63
63
  let report = session.parseReport(response);
package/docs/agents.md CHANGED
@@ -19,7 +19,7 @@ This page is for AI coding agents (Claude Code, Cursor, Codex, and others) that
19
19
  await session.close();
20
20
  }
21
21
  ```
22
- 4. Run it with `node path/to/script.ts`. Share the session link from the first `[verify]` line with the user, so they can watch.
22
+ 4. Name it `.mts` and run it with `node path/to/script.mts`; Node runs a `.mts` file as an ES module whatever `package.json` says, while a `.ts` file fails to import in a CommonJS project. Share the session link from the first `[verify]` line with the user, so they can watch.
23
23
  5. Read the outcome from the exit code and stderr. Each step prints `✓` or `✗` with its text; a failure prints `CODE: message`, ending with the session link. Look at any screenshot you saved before changing the script or the app.
24
24
 
25
25
  ## Exact actions and coordinates
@@ -53,11 +53,11 @@ try {
53
53
  }
54
54
  ```
55
55
 
56
- The [Python](https://github.com/RevylAI/verify/blob/v0.6.0/python/README.md#exact-actions) and [Go](https://github.com/RevylAI/verify/blob/v0.6.0/go/README.md#exact-actions) READMEs state the same rule with each language's names. [api.md](api.md#exact-actions) lists every call and its errors.
56
+ The [Python](https://github.com/RevylAI/verify/blob/v0.6.2/python/README.md#exact-actions) and [Go](https://github.com/RevylAI/verify/blob/v0.6.2/go/README.md#exact-actions) READMEs state the same rule with each language's names. [api.md](api.md#exact-actions) lists every call and its errors.
57
57
 
58
58
  ## Rules
59
59
 
60
- Mac computers are early access. Ask support@revyl.ai about access before starting a computer; do not repeat an uncertain start/stop to probe availability.
60
+ Mac computers are available to organizations on a current paid Revyl plan. Ask before starting a computer, as for a device; do not repeat an uncertain start/stop to probe availability.
61
61
 
62
62
  For computer work, use structured `exec(['program', 'arg'])`, `readFile`, `writeFile`, `stat`, and run-owned handles from `processes()`/`terminate(id)`. Check command output with ordinary assertions and close in `finally`; screenshots are supported, but instruction/validation are not. To use the screen, read a point off `screenshot()` and `tap({ x, y })` it, or describe it with `tap({ target })`, and type with `typeFocused(text, { clear: false })`. A described click takes several seconds, because Revyl takes a screenshot and finds the element first. It can pick a look-alike, and when the target isn't on the screen it can still click something else instead of failing. So check the point it returns or take a screenshot afterwards, and for anything that's hard to undo, read the point off `screenshot()` and use `tap({ x, y })`. After `ACTION_UNCERTAIN`, take a screenshot before you act again. Do not fall back to agent steps on computers or shell/file methods on mobile/web. See [computers.md](computers.md) for limits. Starting a computer is a paid external action and needs the same approval as starting a device.
63
63
 
package/docs/api.md CHANGED
@@ -8,7 +8,7 @@ import { attach, open, defineConfig, VerifyError, isVerifyError } from '@revyl/v
8
8
 
9
9
  Starts a Revyl cloud browser, device, or Mac computer. Mobile first-screen readiness is [best-effort](mobile.md#steps), not a foreground/rendered-readiness guarantee. Computer starts retain a 10-minute default timeout; an unclaimed start may fail after 120 seconds with no-host context.
10
10
 
11
- Mac computers are early access. Ask support@revyl.ai about access.
11
+ Mac computers are available to organizations on a current paid Revyl plan.
12
12
 
13
13
  ```ts
14
14
  const web = await open('web'); // a target named in verify.config.ts
@@ -63,20 +63,20 @@ Starts a child app session inside this computer, returning the normal session AP
63
63
  Mac supports Web and iOS children. The server remains authoritative for access, capability and capacity. Children require and share the parent's known deadline. Closing a child leaves the parent running; closing the parent cancels pending starts and gives child cleanup at most five seconds total before requesting confirmed computer release. The parent stop also stops any remaining children, so a slow child cannot prevent that request. A failed child start never closes the parent.
64
64
 
65
65
  ```ts
66
- const computer = await attach(existingComputerId, { log: false });
66
+ const computer = await attach(existingComputerId, { stopOnClose: false, log: false }); // not yours, so close() leaves it running
67
67
  try {
68
68
  const web = await computer.open({
69
69
  platform: 'web',
70
70
  app: { appId: webAppId, buildId: externalBuildId },
71
71
  });
72
- await web.navigate('http://localhost:3000');
73
- await web.validation('The home page is visible');
72
+ await web.navigate('https://www.saucedemo.com');
73
+ await web.validation('The Swag Labs login form is shown');
74
74
  } finally {
75
75
  await computer.close();
76
76
  }
77
77
  ```
78
78
 
79
- This requires an already-running service on the computer. The initial Web build still uses HTTPS; navigation after start can reach the computer's localhost. No localhost-start option is implied.
79
+ The initial Web build uses HTTPS. After start, `navigate()` can also reach `http://localhost:<port>` on the computer, but only when a service is already listening there, such as one an earlier step of a `revyl-macos` job started. Verify has no call that starts one, and a process started through `exec()` ends when the command returns. Leave out `stopOnClose: false` only for a computer your script owns: then `close()` stops it.
80
80
 
81
81
  ## session.navigate(url)
82
82
 
@@ -84,7 +84,7 @@ Web only, hosted or normal. Sends one deterministic `open_url` action and checks
84
84
 
85
85
  ## Exact actions
86
86
 
87
- **Early access.** Since TypeScript (`@revyl/verify`) 0.4.0, Python (`revyl-verify`) 0.2.0 and Go v0.3.0. `doubleTap`, `longPress`, `drag`, `typeFocused`, `goHome`, and Web keys and modifiers in `pressKey`, are new in TypeScript 0.5.0, Python 0.3.0 and Go v0.4.0. On a Mac computer's screen, `tap` (by point or by description), `screenSize`, `typeFocused` and `pressKey` are new in TypeScript 0.6.0, Python 0.4.0 and Go v0.5.0. The [Python](https://github.com/RevylAI/verify/blob/v0.6.0/python/README.md#exact-actions) and [Go](https://github.com/RevylAI/verify/blob/v0.6.0/go/README.md#exact-actions) READMEs show them with each language's names. Web, iOS and Android sessions, and a Mac computer's screen, take device actions that need no agent.
87
+ **Early access.** Since TypeScript (`@revyl/verify`) 0.4.0, Python (`revyl-verify`) 0.2.0 and Go v0.3.0. `doubleTap`, `longPress`, `drag`, `typeFocused`, `goHome`, and Web keys and modifiers in `pressKey`, are new in TypeScript 0.5.0, Python 0.3.0 and Go v0.4.0. On a Mac computer's screen, `tap` (by point or by description), `screenSize`, `typeFocused` and `pressKey` are new in TypeScript 0.6.0, Python 0.4.0 and Go v0.5.0. The [Python](https://github.com/RevylAI/verify/blob/v0.6.2/python/README.md#exact-actions) and [Go](https://github.com/RevylAI/verify/blob/v0.6.2/go/README.md#exact-actions) READMEs show them with each language's names. Web, iOS and Android sessions, and a Mac computer's screen, take device actions that need no agent.
88
88
 
89
89
  | Call | Web | iOS | Android | Mac computer |
90
90
  | --- | --- | --- | --- | --- |
@@ -182,7 +182,7 @@ When inspecting `revyl device report --session-id <id>`, read validation verdict
182
182
 
183
183
  ## Your own model
184
184
 
185
- **Early access.** Since TypeScript (`@revyl/verify`) 0.4.0, Python (`revyl-verify`) 0.2.0 and Go v0.3.0; the [Python](https://github.com/RevylAI/verify/blob/v0.6.0/python/README.md#your-own-model) and [Go](https://github.com/RevylAI/verify/blob/v0.6.0/go/README.md#your-own-model) READMEs show them with each language's names. Runs instructions and validations on a model you choose, in your process, instead of Revyl's agent. Revyl still provides the browser or device. Leave `model` out and Revyl's agent runs the step, as before.
185
+ **Early access.** Since TypeScript (`@revyl/verify`) 0.4.0, Python (`revyl-verify`) 0.2.0 and Go v0.3.0; the [Python](https://github.com/RevylAI/verify/blob/v0.6.2/python/README.md#your-own-model) and [Go](https://github.com/RevylAI/verify/blob/v0.6.2/go/README.md#your-own-model) READMEs show them with each language's names. Runs instructions and validations on a model you choose, in your process, instead of Revyl's agent. Revyl still provides the browser or device. Leave `model` out and Revyl's agent runs the step, as before.
186
186
 
187
187
  ```ts
188
188
  const session = await open('ios', { model: 'anthropic/claude-sonnet-5-5' }); // every step on your model
package/docs/ci.md CHANGED
@@ -4,7 +4,7 @@ Verify is a library, so it runs wherever your code runs. Browsers, devices, and
4
4
 
5
5
  ## A script in GitHub Actions
6
6
 
7
- Add `REVYL_API_KEY` as a repository secret, then run your script with `node`. A failed instruction or validation makes the script exit non-zero, which fails the job.
7
+ Add `REVYL_API_KEY` as a repository secret, then run your script with `node`. Name it `.mts`, as `init` does, so Node runs it as an ES module whatever your `package.json` says. A failed instruction or validation makes the script exit non-zero, which fails the job.
8
8
 
9
9
  ```yaml
10
10
  name: Verify
@@ -22,7 +22,7 @@ jobs:
22
22
  node-version: 24
23
23
  cache: npm
24
24
  - run: npm ci
25
- - run: node verify/checkout.ts
25
+ - run: node verify/checkout.mts
26
26
  env:
27
27
  REVYL_API_KEY: ${{ secrets.REVYL_API_KEY }}
28
28
  - if: ${{ !cancelled() }}
package/docs/computers.md CHANGED
@@ -1,6 +1,6 @@
1
- # Mac computers (early access)
1
+ # Mac computers
2
2
 
3
- Verify opens a Revyl cloud macOS computer for commands, files, processes, screenshots, and clicks and keys on its screen. It does not open an assigned physical computer. Mac computers are **early access**. Ask [support@revyl.ai](mailto:support@revyl.ai) about access.
3
+ Verify opens a Revyl cloud macOS computer for commands, files, processes, screenshots, and clicks and keys on its screen. It does not open an assigned physical computer. Mac computers are available to organizations on a current paid Revyl plan. If yours can't start one, ask [support@revyl.ai](mailto:support@revyl.ai).
4
4
 
5
5
  ```bash
6
6
  export REVYL_API_KEY=...
@@ -124,7 +124,7 @@ The HTTPS URL is signed and short-lived. Keep it private, including its query st
124
124
 
125
125
  ## Availability and errors
126
126
 
127
- Mac computers are early access. A `503 runtime_unavailable` or typed `computer_not_enabled` becomes `NOT_AVAILABLE_ON_PLATFORM` with this availability guidance. A `429 computer_limit` becomes `COMPUTER_LIMIT`: queued work (including iOS) or the concurrency limit can cause it, and the response does not identify which. Verify does not retry the create or send a stop after these definite admission refusals. `operation_limit` remains `SESSION_BUSY`. Availability is determined by the server.
127
+ Mac computers are available to organizations on a current paid Revyl plan. A `503 runtime_unavailable` or typed `computer_not_enabled` becomes `NOT_AVAILABLE_ON_PLATFORM` with this availability guidance. A `429 computer_limit` becomes `COMPUTER_LIMIT`: queued work (including iOS) or the concurrency limit can cause it, and the response does not identify which. Verify does not retry the create or send a stop after these definite admission refusals. `operation_limit` remains `SESSION_BUSY`. Availability is determined by the server.
128
128
 
129
129
  The default `startTimeout` remains 600000 ms; override it explicitly if needed. An unclaimed start can transition to `failed` with `failure_reason: 'no_host'` after 120 seconds from create. Verify stops readiness polling and throws `SESSION_START_FAILED` with that context, then attempts bounded cleanup. This is not a 120-second timeout for every start: claimed guests may take longer. `device_limit` also yields `SESSION_START_FAILED`, with queued-work/concurrency context. A start timeout or unconfirmed close does not prove resources were released. Inspect the session and contact support rather than blindly repeating a start or stop.
130
130
 
@@ -8,8 +8,8 @@ import { defineConfig } from '@revyl/verify';
8
8
  export default defineConfig({
9
9
  targets: {
10
10
  web: { platform: 'web', app: { appId: '…', url: 'https://example.com' }, viewport: { width: 1280, height: 800 } },
11
- ios: { platform: 'ios', app: { appId: '…' }, device: { model: 'iPhone 16', osVersion: '18.5' } },
12
- pixel: { platform: 'android', app: { buildId: '…' }, device: { model: 'Pixel 8' } },
11
+ ios: { platform: 'ios', app: { appId: '…' }, device: { model: 'iPhone 16', osVersion: 'iOS 18.5' } },
12
+ pixel: { platform: 'android', app: { buildId: '…' }, device: { model: 'Pixel 7', osVersion: 'Android 14' } },
13
13
  mac: { platform: 'mac' },
14
14
  },
15
15
  stepTimeout: 240_000,
@@ -20,7 +20,7 @@ Unknown keys are rejected, so a typo fails loudly instead of being ignored.
20
20
 
21
21
  ## Top-level options
22
22
 
23
- Mac targets are early access. Ask support@revyl.ai about access. See [computer availability](computers.md#availability-and-errors).
23
+ Mac computers are available to organizations on a current paid Revyl plan. See [computer availability](computers.md#availability-and-errors).
24
24
 
25
25
  | Option | Default | Meaning |
26
26
  | --- | --- | --- |
@@ -50,7 +50,7 @@ Mac targets are early access. Ask support@revyl.ai about access. See [computer a
50
50
  | `app.buildId` | An exact Revyl build to install. |
51
51
  | `app.artifactUrl` | An HTTPS URL of an `.apk`, `.app.zip`, or `.ipa` to install. |
52
52
  | `app.bundleId` | An app already on the device to launch instead, such as a system app. |
53
- | `device` | `{ model?, osVersion? }`, for example `{ model: 'Pixel 8', osVersion: '15' }` |
53
+ | `device` | `{ model?, osVersion? }`, written as Revyl names them, for example `{ model: 'iPhone 16', osVersion: 'iOS 18.5' }` or `{ model: 'Pixel 7', osVersion: 'Android 14' }`. Revyl picks its default for a value you leave out. A model or OS version Revyl doesn't offer, or a pair that doesn't go together, throws `INVALID_ARGUMENT` listing the values it accepts, and no session starts |
54
54
  | `startTimeout` | Milliseconds to wait for the device. Default 600000. |
55
55
  | `idleTimeoutSeconds` | Default 600. |
56
56
 
@@ -1,5 +1,7 @@
1
1
  # Verify working end to end
2
2
 
3
+ **Historical record.** This page documents the 0.1.0 and 0.2.0 runs of October 2026 and is kept for its method. It does not describe the current release: the [changelog](https://github.com/RevylAI/verify/blob/main/CHANGELOG.md) and the guides do.
4
+
3
5
  These live runs were made on **2026-10-27**. The baseline uses source commit [`6029513369f13e73914b550d0cd26ece615b4e13`](https://github.com/RevylAI/verify/tree/6029513369f13e73914b550d0cd26ece615b4e13); the separate published-package check used `@revyl/verify@0.1.0`. The [re-verification below](#re-verification-at-061e5cfa) uses `061e5cfa31c5489aa304c2b640bbaf40e3d88561`, including an unpublished packed 0.2.0 tarball. Neither is a publication announcement.
4
6
 
5
7
  Only reviewed public scripts, sanitized transcripts, result projections, and two reviewed screenshots were used here. No private reports, device identifiers, session links, signed recording URLs, or recordings are published.
package/docs/errors.md CHANGED
@@ -18,7 +18,7 @@
18
18
 
19
19
  `web_runtime_unavailable` does not distinguish full capacity from an unavailable runtime. `computer_limit` does not distinguish queued work from concurrency exhaustion. Inspect these fields to classify refusal without parsing prose; do not infer a specific cause or automatically start a replacement session.
20
20
 
21
- Ordinary start errors retain recognized safe server diagnostic codes such as `web_app_required` in the message even when they are not typed refusal reasons. Arbitrary server messages and payloads are not copied into startup diagnostics.
21
+ Ordinary start errors retain recognized safe server diagnostic codes such as `web_app_required` in the message even when they are not typed refusal reasons. An iOS or Android start that Revyl refuses as invalid (HTTP 400 or 422), such as a device model or OS version it doesn't offer, throws `INVALID_ARGUMENT` with Revyl's explanation, which lists the values it accepts; nothing was started. Other server messages and payloads, including every Web and hosted start's, are not copied into startup diagnostics.
22
22
 
23
23
  Web navigation timeouts expose `reason: 'request_timeout'` with HTTP 504 and `code: 'ACTION_UNCERTAIN'`: the action budget expired before navigation was confirmed, but the request may still commit and the session remains open. A normalized `protocol_error` also preserves uncertainty and its HTTP status. Neither error causes Verify to replay navigation or close the session. Inspect the live page before deciding whether to navigate again.
24
24
 
@@ -37,7 +37,7 @@ try {
37
37
 
38
38
  | Code | What happened | What to do |
39
39
  | --- | --- | --- |
40
- | `INVALID_ARGUMENT` | A call got a bad value: an unknown target name, an empty step, two steps at once on one session, a point outside the screenshot, `typeFocused` on a computer without `{ clear: false }` | The message names the argument |
40
+ | `INVALID_ARGUMENT` | A call got a bad value: an unknown target name, an empty step, two steps at once on one session, a point outside the screenshot, `typeFocused` on a computer without `{ clear: false }`, or a device model or OS version Revyl doesn't offer | The message names the argument, and for a device, the values Revyl accepts |
41
41
  | `CONFIG_NOT_FOUND` | `open('name')` found no `verify.config.ts` at or above the current folder | Run `npx @revyl/verify init`, pass `options.config`, or pass a target object |
42
42
  | `CONFIG_INVALID` | The config failed validation or did not load | The message names the exact option and the rule |
43
43
  | `AUTH_MISSING` | No `REVYL_API_KEY` and no saved login | Run `npx @revyl/verify login` in a terminal, or set `REVYL_API_KEY` |
@@ -86,7 +86,7 @@ The generated iOS and Android targets open Settings. To test your own app, repla
86
86
 
87
87
  - **Web:** create a Web app in Revyl (see [web.md](web.md#create-the-web-app)) and set `app.url` to a public HTTPS URL. Revyl's cloud browser cannot reach `localhost`.
88
88
  - **iOS and Android:** upload a build to the app in Revyl, for example with `revyl build upload`; each session installs the newest one. See [mobile.md](mobile.md).
89
- - **Mac:** computers are early access; ask support@revyl.ai about access. Agent instruction/validation are unavailable. See [computers.md](computers.md#availability-and-errors).
89
+ - **Mac:** computers are available to organizations on a current paid Revyl plan. Agent instruction/validation are unavailable. See [computers.md](computers.md#availability-and-errors).
90
90
 
91
91
  ## Run the script
92
92
 
package/docs/llms.txt CHANGED
@@ -4,14 +4,14 @@
4
4
 
5
5
  ## Docs
6
6
 
7
- Mac computers are early access; ask support@revyl.ai about access. See computers.md#availability-and-errors.
7
+ Mac computers are available to organizations on a current paid Revyl plan. See computers.md#availability-and-errors.
8
8
 
9
9
  - [Getting started](getting-started.md): install, authenticate, init, run a script
10
10
  - [API](api.md): open(), attach(), hosted children, navigate(), report(), agent steps, screenshot(), exec(), file/process methods, close()
11
11
  - [Configuration](configuration.md): verify.config.ts targets, environment variables, the init and whoami commands
12
12
  - [Web](web.md): Revyl web sessions, URLs and builds, sign-in, steps, and exact actions
13
13
  - [Mobile](mobile.md): iOS and Android devices, installing apps, and exact actions
14
- - [Computers](computers.md#availability-and-errors): Mac early access, commands and files, the screen (clicks, typing and keys), expiry, capacity errors, recording metadata, and confirmed release
14
+ - [Computers](computers.md#availability-and-errors): Mac availability, commands and files, the screen (clicks, typing and keys), expiry, capacity errors, recording metadata, and confirmed release
15
15
  - [Verify working end to end](end-to-end.md): live verification scope, observed outcomes, and limits of the evidence
16
16
  - [CI and test runners](ci.md): GitHub Actions, node:test, Vitest, Jest, Playwright Test
17
17
  - [Use your own model](own-model.md): run instructions and validations on Claude, GPT, Gemini, a local model or any OpenAI-compatible endpoint; providers, limits, privacy and troubleshooting
package/docs/mobile.md CHANGED
@@ -3,8 +3,8 @@
3
3
  An `ios` or `android` target opens your app on a Revyl cloud simulator or emulator.
4
4
 
5
5
  ```ts
6
- { platform: 'ios', app: { appId: '…' }, device: { model: 'iPhone 16', osVersion: '18.5' } }
7
- { platform: 'android', app: { buildId: '…' }, device: { model: 'Pixel 8' } }
6
+ { platform: 'ios', app: { appId: '…' }, device: { model: 'iPhone 16', osVersion: 'iOS 18.5' } }
7
+ { platform: 'android', app: { buildId: '…' }, device: { model: 'Pixel 7', osVersion: 'Android 14' } }
8
8
  { platform: 'android', app: { artifactUrl: 'https://ci.example.com/app-release.apk' } }
9
9
  { platform: 'ios', app: { bundleId: 'com.apple.Preferences' } } // an app already on the device
10
10
  ```
@@ -18,17 +18,17 @@ An `ios` or `android` target opens your app on a Revyl cloud simulator or emulat
18
18
 
19
19
  ## Devices
20
20
 
21
- `device.model` and `device.osVersion` pick the simulator or emulator. Without them, Revyl picks its default for the platform. To run the same script on several devices, give each its own target and open them one after another or in parallel:
21
+ `device.model` and `device.osVersion` pick the simulator or emulator. Write them as Revyl names them: `'iOS 18.5'` and `'Android 14'`, not `'18.5'` or `'14'`. Without them, Revyl picks its default for the platform, and with only a model, its default OS version, which that model must support. A value Revyl doesn't offer throws `INVALID_ARGUMENT` before any session starts, and the message lists the models or versions it accepts. To run the same script on several devices, give each its own target and open them one after another or in parallel:
22
22
 
23
23
  ```ts
24
24
  targets: {
25
- 'iphone-se': { platform: 'ios', app: { appId }, device: { model: 'iPhone SE (3rd generation)' } },
26
- 'iphone-16': { platform: 'ios', app: { appId }, device: { model: 'iPhone 16' } },
25
+ 'iphone-air': { platform: 'ios', app: { appId }, device: { model: 'iPhone Air' } },
26
+ 'iphone-16': { platform: 'ios', app: { appId }, device: { model: 'iPhone 16', osVersion: 'iOS 18.5' } },
27
27
  },
28
28
  ```
29
29
 
30
30
  ```ts
31
- for (const name of ['iphone-se', 'iphone-16']) {
31
+ for (const name of ['iphone-air', 'iphone-16']) {
32
32
  const session = await open(name);
33
33
  try {
34
34
  await session.validation('The onboarding screen fits without overlapping text');
@@ -46,11 +46,11 @@ After connection and any explicit bundle launch, `open()` makes a best-effort fi
46
46
 
47
47
  The generated mobile example starts with an instruction to wait for the first screen before validating it. For your own scripts, make the first instruction describe the screen or action you actually need; a screenshot with content can still show a loading screen or another app.
48
48
 
49
- For Android Settings, instruct the agent to scroll or navigate until the OS version is visible before validating it. Opening About alone can leave the version offscreen.
49
+ For Android Settings (`bundleId: 'com.android.settings'`), instruct the agent to scroll or navigate until the OS version is visible before validating it, as in `instruction('Open About phone, then scroll or navigate until the Android version is visible')`. Opening About alone can leave the version offscreen.
50
50
 
51
51
  ## Exact actions
52
52
 
53
- **Early access.** Since TypeScript (`@revyl/verify`) 0.4.0, Python (`revyl-verify`) 0.2.0 and Go v0.3.0. `doubleTap`, `longPress`, `drag`, `typeFocused`, `goHome`, and Web keys and modifiers in `pressKey`, are new in TypeScript 0.5.0, Python 0.3.0 and Go v0.4.0. The [Python](https://github.com/RevylAI/verify/blob/v0.6.0/python/README.md#exact-actions) and [Go](https://github.com/RevylAI/verify/blob/v0.6.0/go/README.md#exact-actions) READMEs show them with each language's names. When you know exactly what to press, skip the agent. Exact actions run on the device as given, with no model, and mix freely with `instruction()` and `validation()` in one script:
53
+ **Early access.** Since TypeScript (`@revyl/verify`) 0.4.0, Python (`revyl-verify`) 0.2.0 and Go v0.3.0. `doubleTap`, `longPress`, `drag`, `typeFocused`, `goHome`, and Web keys and modifiers in `pressKey`, are new in TypeScript 0.5.0, Python 0.3.0 and Go v0.4.0. The [Python](https://github.com/RevylAI/verify/blob/v0.6.2/python/README.md#exact-actions) and [Go](https://github.com/RevylAI/verify/blob/v0.6.2/go/README.md#exact-actions) READMEs show them with each language's names. When you know exactly what to press, skip the agent. Exact actions run on the device as given, with no model, and mix freely with `instruction()` and `validation()` in one script:
54
54
 
55
55
  ```ts
56
56
  import { open } from '@revyl/verify';
@@ -66,10 +66,10 @@ try {
66
66
  await session.swipe('down'); // the finger moves down, so the list scrolls to the top
67
67
  const search = await session.locate('Search field'); // a point in screenshot pixels
68
68
  await session.tap(search); // a tap by coordinates
69
- await session.type(search, 'Wallpaper');
69
+ await session.type(search, 'Accessibility');
70
70
  await session.pressKey('enter');
71
- await session.instruction('Open the Wallpaper result'); // hand the fuzzy part to the agent
72
- await session.validation('The Wallpaper settings are shown');
71
+ await session.instruction('Open the Accessibility result'); // hand the fuzzy part to the agent
72
+ await session.validation('The Accessibility settings are shown');
73
73
  } finally {
74
74
  await session.close();
75
75
  }
package/docs/own-model.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Use your own model
2
2
 
3
- **Early access.** Since TypeScript (`@revyl/verify`) 0.4.0, Python (`revyl-verify`) 0.2.0 and Go v0.3.0; the [Python](https://github.com/RevylAI/verify/blob/v0.6.0/python/README.md#your-own-model) and [Go](https://github.com/RevylAI/verify/blob/v0.6.0/go/README.md#your-own-model) READMEs show them with each language's names. Verify normally runs `instruction()` and `validation()` on Revyl's agent. Pass a `model` and the agent loop runs in your process instead, on a model you choose, with your own key. Revyl still provides the cloud browser or device and, by default, finds the elements your model names on screen.
3
+ **Early access.** Since TypeScript (`@revyl/verify`) 0.4.0, Python (`revyl-verify`) 0.2.0 and Go v0.3.0; the [Python](https://github.com/RevylAI/verify/blob/v0.6.2/python/README.md#your-own-model) and [Go](https://github.com/RevylAI/verify/blob/v0.6.2/go/README.md#your-own-model) READMEs show them with each language's names. Verify normally runs `instruction()` and `validation()` on Revyl's agent. Pass a `model` and the agent loop runs in your process instead, on a model you choose, with your own key. Revyl still provides the cloud browser or device and, by default, finds the elements your model names on screen.
4
4
 
5
5
  Use it when you want a specific model, your own prompts and key, or faster steps on a cheap model. Leave `model` out and nothing changes.
6
6
 
@@ -52,7 +52,7 @@ log.Println(step.Model.ID, len(step.Model.Turns), step.Model.InputTokens, step.M
52
52
  _, err = s.Validation(ctx, "The screen shows the iOS version")
53
53
  ```
54
54
 
55
- The [Python](https://github.com/RevylAI/verify/blob/v0.6.0/python/README.md#your-own-model) and [Go](https://github.com/RevylAI/verify/blob/v0.6.0/go/README.md#your-own-model) READMEs have the full reference for each.
55
+ The [Python](https://github.com/RevylAI/verify/blob/v0.6.2/python/README.md#your-own-model) and [Go](https://github.com/RevylAI/verify/blob/v0.6.2/go/README.md#your-own-model) READMEs have the full reference for each.
56
56
 
57
57
  Set `model` on `open()` to run every step on it, or on one step to override it:
58
58
 
@@ -67,7 +67,7 @@ The string is `'provider/model'`. Everything after the first slash is the provid
67
67
 
68
68
  | Prefix | Key variable | Endpoint | Status |
69
69
  | --- | --- | --- | --- |
70
- | `anthropic/` | `ANTHROPIC_API_KEY` | Anthropic Messages API | The one-line form run live against an Anthropic-compatible proxy with Claude Sonnet 5.5, real screenshots and tool schemas; the run on a Revyl device is pending |
70
+ | `anthropic/` | `ANTHROPIC_API_KEY` | Anthropic Messages API | Run live with Claude Sonnet 5.5 on Revyl iOS, Android and Web sessions in TypeScript, Python and Go, including `grounding: 'model'` on iOS |
71
71
  | `openai/` | `OPENAI_API_KEY` | `https://api.openai.com/v1` | Request shape checked; not yet run live |
72
72
  | `google/` | `GOOGLE_API_KEY`, or `GEMINI_API_KEY` when it is unset | `https://generativelanguage.googleapis.com/v1beta/openai/` | Request shape checked; not yet run live |
73
73
  | `openrouter/` | `OPENROUTER_API_KEY` | `https://openrouter.ai/api/v1` | Request shape checked; not yet run live |
@@ -97,7 +97,7 @@ Measured in production on Cerebras `qwen-3.8-27b`, a fast vision model (about 0.
97
97
  | | your model, `grounding: 'revyl'` | pass, 21.2 s | pass, 1.3 s | 4 + 1 | 7,854/355 + 1,380/136 |
98
98
  | | your model, `grounding: 'model'` | fail after 20 turns, 64.4 s | | 20 | 52,726 total |
99
99
 
100
- Each local turn costs one model call plus one device action: about 3.7 s per turn on iOS and 5.3 s on Web here, most of it the device action and the screen settling. These are two short flows on one model, so treat them as a direction, not a benchmark. Claude, GPT and Gemini have not been measured yet, and `grounding: 'model'` has not yet been shown to pass with any model.
100
+ Each local turn costs one model call plus one device action: about 3.7 s per turn on iOS and 5.3 s on Web here, most of it the device action and the screen settling. These are two short flows on one model, so treat them as a direction, not a benchmark. GPT and Gemini have not been measured yet. Claude Sonnet 5.5 passed with `grounding: 'model'` on iOS Settings in 3 turns; that is one run, so treat `grounding: 'model'` as dependent on the model.
101
101
 
102
102
  Start with the default grounding and the cheapest vision model your provider has. Move to a stronger model if steps run out of turns or pick the wrong elements.
103
103
 
package/docs/web.md CHANGED
@@ -53,7 +53,7 @@ Revyl runs one step at a time on a session. A step sent while another is still r
53
53
 
54
54
  ## Exact actions
55
55
 
56
- **Early access.** Since TypeScript (`@revyl/verify`) 0.4.0, Python (`revyl-verify`) 0.2.0 and Go v0.3.0. `doubleTap`, `longPress`, `drag`, `typeFocused`, `goHome`, and Web keys and modifiers in `pressKey`, are new in TypeScript 0.5.0, Python 0.3.0 and Go v0.4.0. The [Python](https://github.com/RevylAI/verify/blob/v0.6.0/python/README.md#exact-actions) and [Go](https://github.com/RevylAI/verify/blob/v0.6.0/go/README.md#exact-actions) READMEs show them with each language's names. When you know exactly what to click, skip the agent. Exact actions run in the browser as given, with no model, and mix freely with `instruction()` and `validation()`:
56
+ **Early access.** Since TypeScript (`@revyl/verify`) 0.4.0, Python (`revyl-verify`) 0.2.0 and Go v0.3.0. `doubleTap`, `longPress`, `drag`, `typeFocused`, `goHome`, and Web keys and modifiers in `pressKey`, are new in TypeScript 0.5.0, Python 0.3.0 and Go v0.4.0. The [Python](https://github.com/RevylAI/verify/blob/v0.6.2/python/README.md#exact-actions) and [Go](https://github.com/RevylAI/verify/blob/v0.6.2/go/README.md#exact-actions) READMEs show them with each language's names. When you know exactly what to click, skip the agent. Exact actions run in the browser as given, with no model, and mix freely with `instruction()` and `validation()`:
57
57
 
58
58
  ```ts
59
59
  import { open } from '@revyl/verify';
@@ -66,6 +66,7 @@ try {
66
66
  await session.validation('A list of products is shown');
67
67
  await session.swipe('up'); // the finger moves up, so the page scrolls down
68
68
  await session.instruction('Add the Sauce Labs Onesie to the cart'); // hand the fuzzy part to the agent
69
+ await session.swipe('down'); // back to the top, so the cart icon is on screen
69
70
  const cart = await session.locate('Shopping cart icon'); // a point in screenshot pixels
70
71
  await session.tap(cart); // a tap by coordinates
71
72
  await session.validation('The cart lists the Sauce Labs Onesie');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@revyl/verify",
3
- "version": "0.6.0",
3
+ "version": "0.6.2",
4
4
  "description": "Open Revyl cloud browsers and mobile devices for agent steps, or Mac computers for commands and files, from TypeScript.",
5
5
  "keywords": [
6
6
  "e2e",