e2e 0.21.1 → 0.21.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/README.md +2 -0
- package/dist/.build.json +1 -1
- package/dist/agent/act-validation.js +1 -0
- package/dist/agent/act.js +7 -3
- package/dist/agent/action-dispatcher.js +30 -8
- package/dist/agent/actions.d.ts +2 -0
- package/dist/agent/actions.js +5 -2
- package/dist/agent/error.js +1 -0
- package/dist/agent/executor.d.ts +14 -6
- package/dist/agent/index.js +5 -1
- package/dist/agent/invocation.d.ts +3 -0
- package/dist/agent/model/sdk.d.ts +5 -0
- package/dist/agent/model/sdk.js +18 -1
- package/dist/agent/observation.js +1 -0
- package/dist/agent/primitives.js +14 -3
- package/dist/agent/replay.js +9 -3
- package/dist/agent/step-cache.d.ts +3 -2
- package/dist/agent/step-cache.js +7 -4
- package/dist/agent/tool-loop.js +4 -1
- package/dist/cache/context.js +1 -1
- package/dist/cache/recorder.d.ts +2 -1
- package/dist/cache/recorder.js +11 -2
- package/dist/cache/trace-fields.d.ts +10 -0
- package/dist/cache/trace-fields.js +17 -0
- package/dist/cache/trace.d.ts +9 -1
- package/dist/cache/trace.js +26 -7
- package/dist/cli/feedback.js +2 -1
- package/dist/cli/init/sibling-versions.json +1 -1
- package/dist/collect/select.js +12 -2
- package/dist/config/agent.d.ts +1 -1
- package/dist/config/diagnose.js +9 -3
- package/dist/config/esm-hooks.js +3 -2
- package/dist/config/resolve.js +3 -2
- package/dist/config/typescript.js +52 -2
- package/dist/engine/contract.d.ts +3 -2
- package/dist/engine/manifest.js +2 -2
- package/dist/internal/errors.js +5 -2
- package/dist/internal/source.js +2 -0
- package/dist/internal/unserved-model.d.ts +5 -0
- package/dist/internal/unserved-model.js +22 -0
- package/dist/locator/screen.js +1 -2
- package/dist/oauth/copilot.js +23 -5
- package/dist/oauth/device-code.js +35 -19
- package/dist/oauth/errors.d.ts +3 -0
- package/dist/oauth/errors.js +26 -11
- package/dist/oauth/providers/github-copilot.d.ts +4 -0
- package/dist/oauth/providers/github-copilot.js +64 -16
- package/dist/oauth/providers/openai.d.ts +2 -2
- package/dist/oauth/providers/openai.js +47 -19
- package/dist/oauth/providers/opencode-console.js +36 -15
- package/dist/oauth/providers/xai.js +18 -9
- package/dist/oauth/token-endpoint.d.ts +15 -6
- package/dist/oauth/token-endpoint.js +18 -6
- package/dist/report/code-frame.js +9 -3
- package/dist/report/failure-text.d.ts +10 -2
- package/dist/report/failure-text.js +24 -8
- package/dist/report/list-model.d.ts +13 -0
- package/dist/report/list-steps.d.ts +6 -1
- package/dist/report/list-steps.js +29 -0
- package/dist/report/list.d.ts +1 -0
- package/dist/report/list.js +16 -7
- package/dist/report/live-window.js +2 -1
- package/dist/report/markdown.js +1 -1
- package/dist/run/fixtures.js +2 -0
- package/dist/run/host-trace.d.ts +3 -2
- package/dist/run/host-trace.js +2 -1
- package/dist/run/last-run.d.ts +9 -0
- package/dist/run/last-run.js +28 -0
- package/dist/run/open-session.d.ts +3 -1
- package/dist/run/open-session.js +1 -1
- package/dist/run/runner.js +6 -2
- package/dist/run/sessions.js +3 -3
- package/dist/run/standalone-attempt.d.ts +2 -1
- package/dist/run/standalone-attempt.js +3 -1
- package/dist/run/steps.d.ts +3 -1
- package/dist/run/units.d.ts +8 -0
- package/dist/run/units.js +14 -0
- package/dist/run/worker-models.d.ts +2 -0
- package/dist/run/worker-models.js +7 -0
- package/dist/types.d.ts +2 -2
- package/docs/authentication.mdx +26 -23
- package/docs/browser.mdx +7 -4
- package/docs/bug-bash.mdx +2 -2
- package/docs/cache.mdx +6 -1
- package/docs/ci/bitrise.mdx +1 -1
- package/docs/ci/codemagic.mdx +2 -2
- package/docs/ci/eas-workflows.mdx +1 -1
- package/docs/coding-agents.mdx +7 -35
- package/docs/debugging.mdx +24 -36
- package/docs/executors.mdx +1 -1
- package/docs/github.mdx +2 -1
- package/docs/integrations/eas.mdx +1 -1
- package/docs/integrations/index.mdx +6 -0
- package/docs/integrations/lightpanda.mdx +192 -0
- package/docs/integrations/testmu.mdx +152 -0
- package/docs/mcp.mdx +123 -0
- package/docs/migrate/detox.mdx +1 -1
- package/docs/migrate/maestro.mdx +101 -105
- package/docs/migrate/playwright.mdx +65 -70
- package/docs/mobile.mdx +18 -3
- package/docs/models.mdx +4 -2
- package/docs/quickstart.mdx +7 -0
- package/docs/reference/agent.mdx +369 -277
- package/docs/reference/app.mdx +141 -32
- package/docs/reference/cli.mdx +674 -558
- package/docs/reference/config.mdx +1406 -752
- package/docs/reference/engine.mdx +1062 -256
- package/docs/reference/environment.mdx +156 -84
- package/docs/reference/errors.mdx +106 -72
- package/docs/reference/expect.mdx +752 -372
- package/docs/reference/mcp.mdx +366 -141
- package/docs/reference/mobile.mdx +844 -403
- package/docs/reference/reporters.mdx +312 -106
- package/docs/reference/runner.mdx +373 -174
- package/docs/reference/screen.mdx +931 -398
- package/docs/reference/security.mdx +106 -40
- package/docs/reference/test.mdx +626 -273
- package/docs/reference/web.mdx +956 -533
- package/docs/security.mdx +6 -5
- package/docs/snippets/model-provider.jsx +763 -0
- package/docs/snippets/setup-prompt-card.jsx +22 -0
- package/docs/snippets/show-more.jsx +22 -0
- package/docs/snippets/video-card.jsx +34 -0
- package/docs/snippets/video.jsx +25 -0
- package/docs/subscriptions.mdx +10 -3
- package/docs/telemetry.mdx +39 -39
- package/package.json +3 -2
- package/schema/report-v1.schema.json +6 -0
- package/skills/e2e/references/agent.md +8 -3
- package/skills/e2e/references/debugging.md +1 -1
- package/skills/e2e/references/mcp.md +1 -1
- package/skills/e2e/references/setup.md +12 -3
- package/skills/e2e/references/writing-tests.md +1 -1
package/docs/reference/agent.mdx
CHANGED
|
@@ -6,100 +6,272 @@ icon: "robot"
|
|
|
6
6
|
"twitter:image": "https://e2e.tester.army/docs/images/og/reference/agent.png?v=9a239b0466"
|
|
7
7
|
---
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
`
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
9
|
+
The `agent` fixture runs natural-language steps against the app: `act`
|
|
10
|
+
interacts with it, `assert` checks the current screen, `waitFor` waits for a
|
|
11
|
+
condition, and `extract` reads structured data. Each call has its own timeout
|
|
12
|
+
and model-call budget.
|
|
13
|
+
|
|
14
|
+
```ts title="tests/team.e2e.ts"
|
|
15
|
+
import { test } from 'e2e';
|
|
16
|
+
|
|
17
|
+
test('invite a teammate', async ({ agent }) => {
|
|
18
|
+
await agent.act('invite {email} as an editor', { params: { email: 'ada@example.test' } });
|
|
19
|
+
await agent.waitFor('the members list shows ada@example.test');
|
|
20
|
+
await agent.assert('ada@example.test is listed as an editor');
|
|
21
|
+
});
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
The built-in agent needs a configured model. Without one, the first
|
|
25
|
+
acquisition of the `agent` fixture records one run-level `MODEL_UNAVAILABLE`
|
|
26
|
+
and stops the run (exit 2). [Custom executors](/executors) can run `act` and
|
|
27
|
+
`assert` without a model; `waitFor` and `extract` still need one.
|
|
28
|
+
|
|
29
|
+
## Reference
|
|
30
|
+
|
|
31
|
+
| Method | Returns |
|
|
32
|
+
| --- | --- |
|
|
33
|
+
| [`agent.act`](#agent-act) | `Promise<ActResult>` |
|
|
34
|
+
| [`agent.assert`](#agent-assert) | `Promise<void>` |
|
|
35
|
+
| [`agent.waitFor`](#agent-waitfor) | `Promise<void>` |
|
|
36
|
+
| [`agent.extract`](#agent-extract) | `Promise<InferOutput<Schema>>` |
|
|
37
|
+
|
|
38
|
+
[Types](#types) holds the signatures. [Budgets](#budgets) lists each
|
|
39
|
+
method's default timeout, model calls, and action steps, and the rules for
|
|
40
|
+
lowering them. Every method takes `agent`: the
|
|
41
|
+
name of a configured agent (`agents.<name>`) that runs that one call in place
|
|
42
|
+
of the test's.
|
|
43
|
+
|
|
44
|
+
### agent.act
|
|
45
|
+
|
|
46
|
+
Plans and executes one bounded multi-action flow. A passing verdict resolves
|
|
47
|
+
with an `ActResult`. A failing or blocked one throws an
|
|
48
|
+
[`AgentError`](#agenterror) whose `code` and `blocked` flag say why.
|
|
17
49
|
|
|
18
50
|
```ts
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
extract<Schema extends StandardSchemaV1>(
|
|
26
|
-
instruction: string,
|
|
27
|
-
options: ExtractOptions<Schema>,
|
|
28
|
-
): Promise<StandardSchemaV1.InferOutput<Schema>>;
|
|
29
|
-
/** Judges a natural-language assertion against a fresh observation. */
|
|
30
|
-
assert(assertion: string, options?: AssertOptions): Promise<void>;
|
|
31
|
-
}
|
|
51
|
+
await agent.act('invite {email} as an editor', { params: { email: 'ada@example.test' } });
|
|
52
|
+
|
|
53
|
+
const member = credentials.user('member');
|
|
54
|
+
const { summary, cache } = await agent.act('Sign in', {
|
|
55
|
+
params: { username: member.username, password: member.password },
|
|
56
|
+
});
|
|
32
57
|
```
|
|
33
58
|
|
|
34
|
-
|
|
59
|
+
- `instruction` is 1 through 8192 UTF-8 bytes after NFC normalization.
|
|
60
|
+
- The [`ActResult`](#types) carries the step's `summary`, the `modelCalls`
|
|
61
|
+
and `actions` it spent, and `cache`: how the [replay cache](/cache) took
|
|
62
|
+
part.
|
|
63
|
+
- The agent acts through the [action tools](#action-tools) and requests
|
|
64
|
+
screenshots itself through the
|
|
65
|
+
[pixel tools](#pixel-tools-screenshot-and-the-point-verbs).
|
|
35
66
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
67
|
+
| Option | Type | Default |
|
|
68
|
+
| --- | --- | --- |
|
|
69
|
+
| `params` | `AgentParams` | none |
|
|
70
|
+
| `timeout` | `number` | `config.timeout`, 120000 |
|
|
71
|
+
| `maxSteps` | `number` | `agents.<name>.maxSteps`, 25 |
|
|
72
|
+
| `maxModelCalls` | `number` | `agents.<name>.maxModelCalls`, 25 |
|
|
73
|
+
| `agent` | `string` | the test's agent |
|
|
74
|
+
|
|
75
|
+
`params` values come from your code, never from the model. Wrap a value that
|
|
76
|
+
differs on every run in [`unique()`](#unique). The model sees a `Secret` as
|
|
77
|
+
its name and purpose only. Before the runner fills it, it checks the field
|
|
78
|
+
the model picked: an enabled editable input, and a password field for a
|
|
79
|
+
password. `locator.fill` runs no such check, since your code chose the field.
|
|
80
|
+
|
|
81
|
+
A failed verdict is `ACTION_FAILED` unless the executor names a more specific
|
|
82
|
+
code, such as `LOCATOR_NOT_FOUND` or `AUTHENTICATION_FAILED`. A blocked
|
|
83
|
+
verdict means the step could not reach a product verdict. It carries one of
|
|
84
|
+
these codes:
|
|
39
85
|
|
|
40
|
-
|
|
|
41
|
-
| --- |
|
|
42
|
-
|
|
|
43
|
-
|
|
|
44
|
-
|
|
|
45
|
-
|
|
|
86
|
+
| Blocked on | Codes |
|
|
87
|
+
| --- | --- |
|
|
88
|
+
| credentials | `AUTH_CREDENTIAL_UNAVAILABLE`, `AUTH_CREDENTIAL_INVALID`, `SECRET_UNAVAILABLE` |
|
|
89
|
+
| environment | `ENVIRONMENT_UNAVAILABLE`, `APP_UNREACHABLE`, `APP_ALREADY_RUNNING` |
|
|
90
|
+
| seed data | `SEED_DATA_MISSING` |
|
|
91
|
+
| test setup | `TEST_SETUP_FAILED`, `APP_NOT_OPEN`, `POLICY_DENIED` |
|
|
92
|
+
| automation | `MODEL_UNAVAILABLE`, `AUTOMATION_UNSUPPORTED`, `STEP_BUDGET_EXHAUSTED`, `STEP_TIMEOUT`, `CONTEXT_OVERFLOW` |
|
|
46
93
|
|
|
47
|
-
|
|
48
|
-
must be positive integers no larger than the configured limits; a larger one
|
|
49
|
-
is `INVALID_ARGUMENT`. All durations are in milliseconds.
|
|
94
|
+
The runner's own stops, and the checks on the call itself:
|
|
50
95
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
`
|
|
96
|
+
| Throws | When |
|
|
97
|
+
| --- | --- |
|
|
98
|
+
| `STEP_BUDGET_EXHAUSTED`, `STEP_TIMEOUT` | A budget or the deadline ran out. |
|
|
99
|
+
| `CANCELLED` | The runner cancelled the step. |
|
|
100
|
+
| `STEP_NO_CONCLUSION` | The turns ran out without a conclusion. |
|
|
101
|
+
| `CONTEXT_OVERFLOW` | A request exceeded the model's context window. |
|
|
102
|
+
| `MODEL_PROVIDER_FAILED` | The provider's transport failed after its retries. |
|
|
103
|
+
| `MODEL_OUTPUT_INVALID` | A verdict outside the grammar. |
|
|
104
|
+
| `REPLAY_STALE` | Under a strict cache, the step's recording no longer replays. |
|
|
105
|
+
| `INVALID_ARGUMENT` | A malformed instruction, oversized `params`, an unknown option, or a budget above the configured limit. An unknown `agent` name fails before the step opens. |
|
|
106
|
+
| `UNSUPPORTED_CAPABILITY` | `schema` or `vision`, which `act` does not take. |
|
|
56
107
|
|
|
57
|
-
|
|
108
|
+
### agent.assert
|
|
109
|
+
|
|
110
|
+
Checks one fresh observation without polling.
|
|
58
111
|
|
|
59
112
|
```ts
|
|
60
|
-
|
|
113
|
+
await agent.assert('the dashboard shows a trial badge');
|
|
61
114
|
```
|
|
62
115
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
`
|
|
116
|
+
- The judge sees the assertion, the current observation, and the agent's
|
|
117
|
+
`context`, never prior steps or `act` summaries. It answers `holds`,
|
|
118
|
+
`fails`, or `inconclusive`.
|
|
119
|
+
- When the subject appears more than once, such as a total in a summary and
|
|
120
|
+
on a pay button, every instance must agree: one that contradicts it fails.
|
|
121
|
+
Name the place (`the order summary total is $42.00`) to judge only that one.
|
|
122
|
+
- A claim about some item, such as `a todo is marked done`, holds when one
|
|
123
|
+
item matches.
|
|
124
|
+
|
|
125
|
+
| Option | Type | Default |
|
|
126
|
+
| --- | --- | --- |
|
|
127
|
+
| `timeout` | `number` | `agents.<name>.judgmentTimeout`, 30000 |
|
|
128
|
+
| `screenshot` | `boolean` | `true` |
|
|
129
|
+
| `vision` | [`VisionMode`](#vision) | `false` |
|
|
130
|
+
| `agent` | `string` | the test's agent |
|
|
131
|
+
|
|
132
|
+
`screenshot` controls the evidence attached after the judgment, passing or
|
|
133
|
+
failing.
|
|
134
|
+
`vision` controls what the model is shown before it. No evidence is captured
|
|
135
|
+
with `screenshot: false`, or once a secret has been filled in the attempt.
|
|
136
|
+
|
|
137
|
+
| Throws | When |
|
|
138
|
+
| --- | --- |
|
|
139
|
+
| `ASSERTION_FAILED` | The judgment is false. |
|
|
140
|
+
| `ASSERTION_INCONCLUSIVE` | The screen did not show enough to decide. |
|
|
66
141
|
|
|
67
|
-
|
|
68
|
-
|
|
142
|
+
Both carry the explanation and, when permitted, a screenshot path. An
|
|
143
|
+
inconclusive judgment made from the tree alone adds a vision hint to its
|
|
144
|
+
message:
|
|
69
145
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
146
|
+
- The hint reads `pass vision: true when the answer is in pixels`. Until a
|
|
147
|
+
step of the attempt has received pixels, it is worded as a condition
|
|
148
|
+
(`if the engine captures pixels, ...`).
|
|
149
|
+
- There is no hint when the engine declares no screenshot capture, a secret
|
|
150
|
+
was filled, or an earlier step's pixel request was degraded: `vision: true`
|
|
151
|
+
could add no evidence then.
|
|
152
|
+
|
|
153
|
+
<Note>
|
|
154
|
+
A custom `StepExecutor` judges the assertion itself, and `assert` carries the
|
|
155
|
+
executor's explanation alone, with no vision hint. It honors `screenshot`,
|
|
156
|
+
since the runner takes that evidence after the verdict. It receives `vision`
|
|
157
|
+
as `step.vision` when it declares `vision: true`; otherwise `vision` is
|
|
158
|
+
`UNSUPPORTED_CAPABILITY`. Its budget and timeout are under
|
|
159
|
+
[Budgets](#budgets).
|
|
160
|
+
</Note>
|
|
161
|
+
|
|
162
|
+
### agent.waitFor
|
|
163
|
+
|
|
164
|
+
Polls a natural-language condition until a judgment holds.
|
|
75
165
|
|
|
76
166
|
```ts
|
|
77
|
-
await agent.
|
|
167
|
+
await agent.waitFor('the upload progress reports completion', { interval: 500 }); // default: 3000
|
|
168
|
+
```
|
|
78
169
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
170
|
+
- It observes and judges at once, and succeeds on the first judgment that
|
|
171
|
+
holds.
|
|
172
|
+
- After a false or inconclusive judgment it waits out `interval`. Then it
|
|
173
|
+
observes every 500 ms (or every `interval`, when shorter) without a model
|
|
174
|
+
call. It judges again only once the screen differs from the one last
|
|
175
|
+
judged, pixels included under `vision`.
|
|
176
|
+
- Judgments follow the [`agent.assert`](#agent-assert) rules: a value shown
|
|
177
|
+
in more than one place holds only once every instance agrees.
|
|
178
|
+
|
|
179
|
+
| Option | Type | Default |
|
|
180
|
+
| --- | --- | --- |
|
|
181
|
+
| `timeout` | `number` | `agents.<name>.judgmentTimeout`, 30000 |
|
|
182
|
+
| `interval` | `number` | 3000 |
|
|
183
|
+
| `maxModelCalls` | `number` | `agents.<name>.maxModelCalls`, 25 |
|
|
184
|
+
| `vision` | [`VisionMode`](#vision) | `false` |
|
|
185
|
+
| `agent` | `string` | the test's agent |
|
|
186
|
+
|
|
187
|
+
`interval` is the least time between two judgments, 100 through 60000 ms.
|
|
188
|
+
|
|
189
|
+
| Throws | When |
|
|
190
|
+
| --- | --- |
|
|
191
|
+
| `STEP_TIMEOUT` | The deadline expired. |
|
|
192
|
+
| `STEP_BUDGET_EXHAUSTED` | The budget ran out. |
|
|
193
|
+
| `INVALID_ARGUMENT` | An out-of-range option, or one `waitFor` does not take. |
|
|
194
|
+
|
|
195
|
+
`STEP_TIMEOUT` and `STEP_BUDGET_EXHAUSTED` carry the last judgment. When that
|
|
196
|
+
round was inconclusive, they add the same vision hint as `agent.assert`.
|
|
197
|
+
|
|
198
|
+
### agent.extract
|
|
199
|
+
|
|
200
|
+
Reads structured output from one fresh observation, validates it against
|
|
201
|
+
`schema`, and returns the validated value. It performs no app actions.
|
|
202
|
+
|
|
203
|
+
```ts
|
|
204
|
+
import { z } from 'zod';
|
|
205
|
+
|
|
206
|
+
const summary = await agent.extract('the workspace name and plan', {
|
|
207
|
+
schema: z.object({ name: z.string(), plan: z.string() }),
|
|
82
208
|
});
|
|
83
209
|
```
|
|
84
210
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
211
|
+
- When the schema has a JSON Schema projection (zod does), the model receives
|
|
212
|
+
its shape: types, fields, required fields, and allowed literals. Value rules
|
|
213
|
+
such as `min`, `max`, lengths, patterns, and formats stay with your schema,
|
|
214
|
+
which judges the value the model read.
|
|
215
|
+
- The model can answer that the screen does not show the data. That throws
|
|
216
|
+
`ASSERTION_INCONCLUSIVE` with what was missing, instead of returning a
|
|
217
|
+
placeholder such as `""` or `0`. To accept absence as an answer, say so in
|
|
218
|
+
the instruction and the schema (`'the phone number, or null when none is
|
|
219
|
+
shown'` with `z.string().nullable()`).
|
|
220
|
+
|
|
221
|
+
| Option | Type | Default |
|
|
222
|
+
| --- | --- | --- |
|
|
223
|
+
| `schema` | `StandardSchemaV1` | required |
|
|
224
|
+
| `timeout` | `number` | `agents.<name>.judgmentTimeout`, 30000 |
|
|
225
|
+
| `vision` | [`VisionMode`](#vision) | `false` |
|
|
226
|
+
| `agent` | `string` | the test's agent |
|
|
89
227
|
|
|
90
|
-
|
|
228
|
+
| Throws | When |
|
|
229
|
+
| --- | --- |
|
|
230
|
+
| `INVALID_ARGUMENT` | The schema is not Standard Schema v1. |
|
|
231
|
+
| `ASSERTION_INCONCLUSIVE` | The screen does not show the data. |
|
|
232
|
+
| `MODEL_OUTPUT_INVALID` | Validation still fails after the repair round. |
|
|
91
233
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
234
|
+
## Budgets
|
|
235
|
+
|
|
236
|
+
Model calls count every model request, repair rounds included. Action steps
|
|
237
|
+
count committed engine actions. The remaining test timeout caps every
|
|
238
|
+
timeout.
|
|
239
|
+
|
|
240
|
+
| Method | Model calls | Action steps | Default timeout |
|
|
241
|
+
| --- | ---: | ---: | --- |
|
|
242
|
+
| `act` | `agents.<name>.maxModelCalls`, 25 | `agents.<name>.maxSteps`, 25 | `config.timeout`, 120000 ms |
|
|
243
|
+
| `waitFor` | `agents.<name>.maxModelCalls`, 25 | 0 | `agents.<name>.judgmentTimeout`, 30000 ms |
|
|
244
|
+
| `extract` | 2 | 0 | `agents.<name>.judgmentTimeout`, 30000 ms |
|
|
245
|
+
| `assert` | 2 | 0 | `agents.<name>.judgmentTimeout`, 30000 ms |
|
|
246
|
+
|
|
247
|
+
- `actionTimeout` limits engine operations, not model calls.
|
|
248
|
+
- Per-call budgets (`maxSteps`, `maxModelCalls`) can only lower the
|
|
249
|
+
configured limits. They must be positive integers no larger than those
|
|
250
|
+
limits; a larger one is `INVALID_ARGUMENT`.
|
|
251
|
+
- All durations are in milliseconds.
|
|
252
|
+
|
|
253
|
+
The `assert` row holds for the built-in agent. When the selected agent has a
|
|
254
|
+
custom `executor`, `assert` runs on it as a step. Its budget is the agent's
|
|
255
|
+
`maxSteps` and `maxModelCalls`, and its default timeout is `config.timeout`.
|
|
256
|
+
For `vision` and `screenshot` there, see the Note under
|
|
257
|
+
[`agent.assert`](#agent-assert).
|
|
258
|
+
|
|
259
|
+
## Action tools
|
|
260
|
+
|
|
261
|
+
The built-in agent offers one tool per verb the target's engine declares, and
|
|
262
|
+
none for a verb it does not. A tool that targets a node takes its id from the
|
|
263
|
+
newest observation. Every tool returns what changed on screen and is
|
|
264
|
+
recorded for the [replay cache](/cache), with its node when it has one. On an engine that declares
|
|
265
|
+
`tapModifiers`, `tap`, `double_tap`, and `right_click` take `modifiers`
|
|
266
|
+
(`Shift`, `Control`, `Alt`, `Meta`, `ControlOrMeta`) to hold keys for the
|
|
267
|
+
click, as a Shift-click extends a selection.
|
|
96
268
|
|
|
97
269
|
| Tool | Engine action | What it does |
|
|
98
270
|
| --- | --- | --- |
|
|
99
|
-
| `tap({ target })` | `tap` | Taps or clicks one node: the gesture for a button, link, menu item, tab, checkbox, row, or field. |
|
|
100
|
-
| `double_tap({ target })` | `doubleTap` | Double-clicks one node, for an item that opens or enters editing on the second click. |
|
|
271
|
+
| `tap({ target, modifiers? })` | `tap` | Taps or clicks one node: the gesture for a button, link, menu item, tab, checkbox, row, or field. |
|
|
272
|
+
| `double_tap({ target, modifiers? })` | `doubleTap` | Double-clicks one node, for an item that opens or enters editing on the second click. |
|
|
101
273
|
| `long_press({ target })` | `longPress` | Presses one node and holds, for a long-press menu or action. |
|
|
102
|
-
| `right_click({ target })` | `secondaryTap` | Right-clicks one node to open its context menu. |
|
|
274
|
+
| `right_click({ target, modifiers? })` | `secondaryTap` | Right-clicks one node to open its context menu. |
|
|
103
275
|
| `hover({ target })` | `hover` | Moves the pointer over one node without pressing: hover menus, flyouts, tooltips, controls revealed on mouse-over. |
|
|
104
276
|
| `type({ target?, value, replace? })` | `fill`; without `target`, `keyboard` | Replaces the node's value; without a target, types into whatever has focus. |
|
|
105
277
|
| `type_secret({ target, name })` | `fill` | Fills a secret declared in the step's params. Offered only when the step declares one. |
|
|
@@ -107,7 +279,7 @@ acted on. A verb the engine does not declare is not offered.
|
|
|
107
279
|
| `select({ target, value })` | `selectOption` | Picks an option by its visible label. |
|
|
108
280
|
| `check({ target, checked? })` | `check` and `uncheck` | Sets a checkbox, switch, or radio to a state (`true` by default). A control already in that state is left alone, unlike a tap, which flips it. |
|
|
109
281
|
| `scroll({ direction, target?, times? })` | `swipe` | Scrolls the viewport or one scrollable node, up to 20 screens per call. |
|
|
110
|
-
| `scroll_to({ target })` or `scroll_to({ text, direction?, target? })` | `scrollIntoView`; with `text`, `swipe` | With `target` alone, brings one listed node into the viewport, for a node the tree lists below or above the fold. With `text`, pages the list (`target`, else the viewport) screen by screen in `direction` (down by default) until a node reading that text shows
|
|
282
|
+
| `scroll_to({ target })` or `scroll_to({ text, direction?, target? })` | `scrollIntoView`; with `text`, `swipe` | With `target` alone, brings one listed node into the viewport, for a node the tree lists below or above the fold. With `text`, pages the list (`target`, else the viewport) screen by screen in `direction` (down by default) until a node reading that text shows, then brings it in when the engine can. That is for a row deep in a long or windowed list the tree has not rendered yet. The node's label must be the text, or hold it with no part of a word on either side, so `Row 12` never stops at `Row 120`. When `target` names a list, the node must be inside it, so a heading elsewhere reading the same does not end the paging. One action however many screens, up to 800; a screen that stops moving or the cap is `LOCATOR_NOT_FOUND`. Each form is offered only with its action kind. |
|
|
111
283
|
| `drag({ target, to })` | `dragTo` | Drags one node and drops it on another: reordering, kanban columns, drop zones. |
|
|
112
284
|
| `upload({ target, files })` | `setInputFiles` | Attaches files to a file input. Paths are project-relative; see the policy below. |
|
|
113
285
|
| `navigate({ url })` | `session.open` | Opens a URL or an app-relative path. |
|
|
@@ -120,44 +292,53 @@ the next observation checks stability without waiting for a second scroll
|
|
|
120
292
|
effect. Engines with `scrollIntoView` still wait for the final adjustment
|
|
121
293
|
that brings the matched node into view. Replay follows the same rule.
|
|
122
294
|
|
|
123
|
-
`upload` takes the model's path but the runner decides
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
file
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
295
|
+
`upload` takes the model's path, but the runner decides:
|
|
296
|
+
|
|
297
|
+
- Each path resolves against the project root, as in
|
|
298
|
+
`locator.setInputFiles`.
|
|
299
|
+
- A path outside the project (through a symlink too), or one that names a
|
|
300
|
+
hidden file or a file under a hidden directory such as `.env`, `.git`, or
|
|
301
|
+
`.e2e`, is refused with `POLICY_DENIED`.
|
|
302
|
+
- A path that names no regular file is `INVALID_ARGUMENT`, an ordinary action
|
|
303
|
+
failure the model reads and corrects.
|
|
304
|
+
- Every refusal and the final allow is a `policy` event named `upload.path`
|
|
305
|
+
on the step. Nothing reaches the engine until every path passes.
|
|
306
|
+
|
|
307
|
+
On engines with a keyboard, including the browser and device engines, `type`
|
|
308
|
+
and `press` can omit `target` to act on the focused field. `type` then
|
|
309
|
+
inserts at the caret; `replace: true` clears first. The browser engine
|
|
310
|
+
rejects typing when no editable field has focus. It checks the focused
|
|
311
|
+
element inside shadow roots and frames too, so focus on a button there is
|
|
312
|
+
refused. When an action closes an on-screen keyboard, the result says so. On
|
|
313
|
+
a touch screen that tap was often spent on closing it, and the model acts on
|
|
314
|
+
the control again.
|
|
315
|
+
|
|
316
|
+
When the engine reports text selected inside the focused field, the screen
|
|
317
|
+
the model reads lists it as `selection="..."` after the value. The web engine
|
|
318
|
+
does for an input, a textarea, and a `contenteditable` editor; a secure field
|
|
319
|
+
reports none. The runner drops it from a field whose value or text holds a
|
|
320
|
+
registered secret. It also drops it from a field cut at its length limit when
|
|
321
|
+
the selection is not in the part shown. So selected characters of a secret
|
|
322
|
+
never reach the model. A `press` of `Shift+ArrowLeft` shows what it selected,
|
|
323
|
+
and `times` repeats it in one call. So the agent extends a selection to
|
|
324
|
+
exactly the word it wants in one more turn, before it formats or replaces it.
|
|
325
|
+
|
|
326
|
+
The tap variants are separate tools, not an option on `tap`, on purpose.
|
|
327
|
+
Offered as an optional `kind`, a model filled it on ordinary buttons (a
|
|
328
|
+
double-click on Save), and a double-click on a submit button submits twice.
|
|
329
|
+
A tool has to be chosen, and each one says what takes a plain tap instead.
|
|
148
330
|
|
|
149
331
|
Mobile engines declare `hover`, `doubleTap`, `longPress`, `check`,
|
|
150
|
-
`uncheck`, `dragTo`, and `session.back
|
|
151
|
-
`double_tap`, `long_press`, `check`, `drag`, and `back
|
|
152
|
-
`secondaryTap`, `scrollIntoView`, or `setInputFiles`. Tab
|
|
153
|
-
verb yet: a new tab is invisible to the model.
|
|
332
|
+
`uncheck`, `dragTo`, and `session.back`. So a device offers `hover`,
|
|
333
|
+
`double_tap`, `long_press`, `check`, `drag`, and `back`. They declare no
|
|
334
|
+
`secondaryTap`, `selectOption`, `scrollIntoView`, or `setInputFiles`. Tab
|
|
335
|
+
switching has no verb yet: a new tab is invisible to the model.
|
|
154
336
|
|
|
155
|
-
|
|
337
|
+
## Pixel tools: screenshot and the point verbs
|
|
156
338
|
|
|
157
|
-
`act` reads the semantic tree and requests screenshots when it needs them
|
|
158
|
-
A screen with no listed interactive nodes, such
|
|
159
|
-
|
|
160
|
-
`vision` option for `act`.
|
|
339
|
+
`act` reads the semantic tree and requests screenshots when it needs them;
|
|
340
|
+
the same model reads both. A screen with no listed interactive nodes, such
|
|
341
|
+
as a canvas, opens with a screenshot.
|
|
161
342
|
|
|
162
343
|
The built-in agent offers these tools while no secret has been filled:
|
|
163
344
|
|
|
@@ -170,172 +351,52 @@ The built-in agent offers these tools while no secret has been filled:
|
|
|
170
351
|
| `press_at({ x, y, key })` | Sends a key to the control at the point. If no control is listed, taps to focus and uses the engine's keyboard. |
|
|
171
352
|
| `select_at({ x, y, value })` | Selects an option by visible label in the control at the point. |
|
|
172
353
|
|
|
173
|
-
Coordinates refer to the latest screenshot. The model must take a
|
|
174
|
-
before
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
354
|
+
- Coordinates refer to the latest screenshot. The model must take a
|
|
355
|
+
screenshot before it uses a point tool, and should prefer node ids for
|
|
356
|
+
listed controls.
|
|
357
|
+
- The runner checks each point against the tree. A point on a listed control
|
|
358
|
+
gets the same policy checks and [replay cache](/cache) recording as an
|
|
359
|
+
action by id.
|
|
360
|
+
- `tap_at` needs an engine whose `actions` or `pointerActions` include `tap`,
|
|
361
|
+
and `hover_at` one whose include `hover`. Without the pointer kind, the
|
|
362
|
+
point must land on a listed control.
|
|
363
|
+
- A bare-point tap or hover replays only on a viewport of the recorded size,
|
|
364
|
+
or at the same place inside the listed node that contained it.
|
|
365
|
+
- Once screenshots are in use, the post-action wait also detects pixel
|
|
366
|
+
changes, including canvas redraws.
|
|
367
|
+
- Screenshots have a maximum long side of 768 px. Older images are removed in
|
|
368
|
+
batches, keeping the newest two.
|
|
369
|
+
- A step that sent pixels records `visionInput: true` and
|
|
370
|
+
`metrics.pixelBytes`.
|
|
178
371
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
On engines with a keyboard, including the browser and device engines, `type`
|
|
184
|
-
and `press` can omit `target` to act on the focused field. `type` inserts at
|
|
185
|
-
the caret; `replace: true` clears first. The browser engine rejects typing
|
|
186
|
-
when no editable field has focus. The focused element is checked inside shadow
|
|
187
|
-
roots and frames, so focus on a button there is refused. Device engines also
|
|
188
|
-
offer `dismiss_keyboard`.
|
|
189
|
-
When an action closes an on-screen keyboard, the result says so: on a touch
|
|
190
|
-
screen that tap was often spent on closing it, and the model acts on the
|
|
191
|
-
control again.
|
|
372
|
+
A secret filled during the step withholds every later screenshot
|
|
373
|
+
(`PIXEL_TAINTED`). A step that opens on a tainted viewport offers none of the
|
|
374
|
+
six pixel tools.
|
|
192
375
|
|
|
193
376
|
If semantic capture times out, an engine that proves masking independently
|
|
194
377
|
can return a fresh screenshot with an explicit unavailable-tree warning.
|
|
195
378
|
Every `act` observation with unavailable semantics includes that image and
|
|
196
|
-
warning
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
judgment with `vision: true`, fails
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
If semantic capture fails, trace replay stops and the step cannot record a
|
|
204
|
-
new trace entry, even if the tree later recovers.
|
|
205
|
-
|
|
206
|
-
A secret filled during the step withholds every later screenshot
|
|
207
|
-
(`PIXEL_TAINTED`), and a step that opens on a tainted viewport offers none of
|
|
208
|
-
the six pixel tools. `tap_at` needs an engine whose `actions` or
|
|
209
|
-
`pointerActions` include `tap`, and `hover_at` one whose include `hover`;
|
|
210
|
-
without the pointer kind the point must land on a listed control. A
|
|
211
|
-
bare-point tap or hover replays from the [replay cache](/cache) only on a
|
|
212
|
-
viewport of the recorded size, or at the same place inside the listed node
|
|
213
|
-
that contained it. A step that sent pixels records `visionInput: true` and
|
|
214
|
-
`metrics.pixelBytes`.
|
|
215
|
-
|
|
216
|
-
A failed or blocked step throws an `AgentError`. A failed verdict is
|
|
217
|
-
`ACTION_FAILED` unless the executor names a more specific code, such as
|
|
218
|
-
`LOCATOR_NOT_FOUND` or `AUTHENTICATION_FAILED`. A blocked verdict, a step
|
|
219
|
-
that could not reach a product verdict, carries one of these codes:
|
|
220
|
-
|
|
221
|
-
| Blocked on | Codes |
|
|
222
|
-
| --- | --- |
|
|
223
|
-
| credentials | `AUTH_CREDENTIAL_UNAVAILABLE`, `AUTH_CREDENTIAL_INVALID`, `SECRET_UNAVAILABLE` |
|
|
224
|
-
| environment | `ENVIRONMENT_UNAVAILABLE`, `APP_UNREACHABLE`, `APP_ALREADY_RUNNING` |
|
|
225
|
-
| seed data | `SEED_DATA_MISSING` |
|
|
226
|
-
| test setup | `TEST_SETUP_FAILED`, `APP_NOT_OPEN`, `POLICY_DENIED` |
|
|
227
|
-
| automation | `MODEL_UNAVAILABLE`, `AUTOMATION_UNSUPPORTED`, `STEP_BUDGET_EXHAUSTED`, `STEP_TIMEOUT`, `CONTEXT_OVERFLOW` |
|
|
228
|
-
|
|
229
|
-
The runner's own stops are
|
|
230
|
-
`STEP_BUDGET_EXHAUSTED` and `STEP_TIMEOUT` when a budget or the deadline ran
|
|
231
|
-
out, `CANCELLED`, `STEP_NO_CONCLUSION` when the turns ran out without a
|
|
232
|
-
conclusion, `CONTEXT_OVERFLOW`, `MODEL_PROVIDER_FAILED`,
|
|
233
|
-
`MODEL_OUTPUT_INVALID` for a verdict outside the grammar, and `REPLAY_STALE`
|
|
234
|
-
under a strict cache. Every code is in [Errors](/reference/errors#agenterror).
|
|
235
|
-
|
|
236
|
-
`act` also throws `INVALID_ARGUMENT` for a malformed instruction, oversized
|
|
237
|
-
`params`, an unknown option, or a budget above the configured limit, and
|
|
238
|
-
`UNSUPPORTED_CAPABILITY` for `schema` or `vision`, which `act` does not take.
|
|
239
|
-
|
|
240
|
-
## agent.assert
|
|
241
|
-
|
|
242
|
-
```ts
|
|
243
|
-
assert(assertion: string, options?: AssertOptions): Promise<void>;
|
|
244
|
-
```
|
|
245
|
-
|
|
246
|
-
Checks one fresh observation without polling. The judge sees only the
|
|
247
|
-
assertion and current observation, never prior steps or `act` summaries.
|
|
248
|
-
It answers `holds`, `fails`, or `inconclusive`. When what the assertion is
|
|
249
|
-
about appears more than once, such as a total in a summary and on a pay
|
|
250
|
-
button, every instance must agree: one that contradicts it fails. Name
|
|
251
|
-
the place (`the order summary total is $42.00`) to judge only that one. A
|
|
252
|
-
claim about some item, such as `a todo is marked done`, still holds when one
|
|
253
|
-
item matches.
|
|
254
|
-
|
|
255
|
-
Throws `ASSERTION_FAILED` on a false judgment and `ASSERTION_INCONCLUSIVE`
|
|
256
|
-
when the screen did not show enough to decide. Both carry the explanation
|
|
257
|
-
and, when permitted, a screenshot path. An inconclusive judgment made from
|
|
258
|
-
the tree alone adds `pass vision: true when the answer is in pixels` to its
|
|
259
|
-
message, worded as a condition (`if the engine captures pixels, ...`) until
|
|
260
|
-
a step of the attempt has received pixels. There is no hint when the engine
|
|
261
|
-
declares no screenshot capture, a secret was filled, or an earlier step's
|
|
262
|
-
pixel request was degraded: `vision: true` could add no evidence then. The
|
|
263
|
-
hint is the built-in judge's; with a custom `executor`, `assert` carries the
|
|
264
|
-
executor's explanation alone. No evidence is captured with
|
|
265
|
-
`screenshot: false` or once a secret has been filled in the attempt.
|
|
266
|
-
`screenshot` controls failure evidence attached after the judgment; `vision`
|
|
267
|
-
controls what the model is shown before it. A custom `StepExecutor` judges
|
|
268
|
-
the assertion itself: it honors `screenshot`, since the runner takes that
|
|
269
|
-
evidence after the verdict, and rejects `vision` with
|
|
270
|
-
`UNSUPPORTED_CAPABILITY`, since the executor decides what its model sees.
|
|
271
|
-
|
|
272
|
-
```ts
|
|
273
|
-
await agent.assert('the dashboard shows a trial badge');
|
|
274
|
-
```
|
|
275
|
-
|
|
276
|
-
## agent.waitFor
|
|
277
|
-
|
|
278
|
-
```ts
|
|
279
|
-
waitFor(condition: string, options?: WaitForOptions): Promise<void>;
|
|
280
|
-
```
|
|
281
|
-
|
|
282
|
-
Observes and judges at once. After a false or inconclusive judgment it
|
|
283
|
-
waits out `interval`, then observes every 500 ms (or every `interval`, when
|
|
284
|
-
shorter) without a model call, and judges again only once the screen
|
|
285
|
-
differs from the one last judged, pixels included under `vision`. Succeeds
|
|
286
|
-
on the first judgment that holds. Judgments follow the `agent.assert`
|
|
287
|
-
rules, so a value shown in more than one place holds only once every
|
|
288
|
-
instance agrees.
|
|
289
|
-
|
|
290
|
-
Throws `STEP_TIMEOUT` on deadline expiry and `STEP_BUDGET_EXHAUSTED` on
|
|
291
|
-
budget exhaustion, each carrying the last judgment (with the same vision
|
|
292
|
-
hint as `agent.assert` when that round was inconclusive), and
|
|
293
|
-
`INVALID_ARGUMENT` for an out-of-range option or one `waitFor` does not
|
|
294
|
-
take.
|
|
295
|
-
|
|
296
|
-
```ts
|
|
297
|
-
await agent.waitFor('the upload progress reports completion', { interval: 500 });
|
|
298
|
-
```
|
|
379
|
+
warning. Earlier node ids are then invalid, and the next successful semantic
|
|
380
|
+
capture presents the whole tree again. The screenshot shows the current
|
|
381
|
+
viewport; an unavailable tree does not prove that a control or message is
|
|
382
|
+
absent. After a secret fill there is no fallback. When semantic capture times
|
|
383
|
+
out before the step does, `act`, and a judgment with `vision: true`, fails
|
|
384
|
+
with `POLICY_DENIED`.
|
|
299
385
|
|
|
300
|
-
|
|
386
|
+
If semantic capture fails, trace replay stops. The step cannot record a new
|
|
387
|
+
trace entry, even if the tree recovers later.
|
|
301
388
|
|
|
302
|
-
|
|
303
|
-
extract<Schema extends StandardSchemaV1>(
|
|
304
|
-
instruction: string,
|
|
305
|
-
options: ExtractOptions<Schema>,
|
|
306
|
-
): Promise<StandardSchemaV1.InferOutput<Schema>>;
|
|
307
|
-
```
|
|
389
|
+
## Vision
|
|
308
390
|
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
its shape: types, fields, required fields, and allowed literals. Value rules
|
|
314
|
-
such as `min`, `max`, lengths, patterns, and formats stay with your schema,
|
|
315
|
-
which judges the value the model read. The model can also answer that the
|
|
316
|
-
screen does not show the data, which throws `ASSERTION_INCONCLUSIVE` with
|
|
317
|
-
what was missing, instead of returning a placeholder such as `""` or `0`.
|
|
318
|
-
To accept absence as an answer, say so in the instruction and the schema
|
|
319
|
-
(`'the phone number, or null when none is shown'` with
|
|
320
|
-
`z.string().nullable()`).
|
|
321
|
-
|
|
322
|
-
The budget is two model calls: one extraction and one repair round for
|
|
323
|
-
output that failed validation. Throws `INVALID_ARGUMENT` for a schema that is
|
|
324
|
-
not Standard Schema v1, `ASSERTION_INCONCLUSIVE` when the screen does not
|
|
325
|
-
show the data, and `MODEL_OUTPUT_INVALID` when validation still fails after
|
|
326
|
-
the repair.
|
|
391
|
+
`assert`, `waitFor`, and `extract` accept `vision`; `act` requests its own
|
|
392
|
+
screenshots through the [pixel tools](#pixel-tools-screenshot-and-the-point-verbs).
|
|
393
|
+
A screenshot goes to the model that asked for it, so it must accept images:
|
|
394
|
+
the judge (else `model`) for a judgment, `model` for `act`.
|
|
327
395
|
|
|
328
396
|
```ts
|
|
329
|
-
|
|
330
|
-
schema: z.object({ name: z.string(), plan: z.string() }),
|
|
331
|
-
});
|
|
397
|
+
await agent.assert('no overlay covers the checkout form', { vision: 'only' }); // default: false
|
|
332
398
|
```
|
|
333
399
|
|
|
334
|
-
## Vision
|
|
335
|
-
|
|
336
|
-
`assert`, `waitFor`, and `extract` accept `vision`. Screenshots require a
|
|
337
|
-
judge model that accepts images.
|
|
338
|
-
|
|
339
400
|
| `vision` | Evidence sent to the judge |
|
|
340
401
|
| --- | --- |
|
|
341
402
|
| `false`, the default | Semantic tree |
|
|
@@ -344,30 +405,48 @@ judge model that accepts images.
|
|
|
344
405
|
|
|
345
406
|
Use `'only'` for visual checks, such as whether an overlay covers a form or a
|
|
346
407
|
chart looks correct. Screenshots show the current viewport, so scroll to the
|
|
347
|
-
relevant content first.
|
|
348
|
-
|
|
408
|
+
relevant content first.
|
|
409
|
+
|
|
410
|
+
Pixels are withheld, and the tree is sent alone, when:
|
|
349
411
|
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
masked fewer regions than the secure fields it observed
|
|
353
|
-
|
|
354
|
-
|
|
412
|
+
- a secret fill has tainted the viewport (`visionDegraded: "PIXEL_TAINTED"`
|
|
413
|
+
on the step),
|
|
414
|
+
- the engine masked fewer regions than the secure fields it observed
|
|
415
|
+
(`MASKING_UNPROVEN`), or
|
|
416
|
+
- the engine cannot capture pixels (`UNSUPPORTED_CAPABILITY`).
|
|
417
|
+
|
|
418
|
+
In `'only'` mode those cases fail with `POLICY_DENIED` instead.
|
|
355
419
|
|
|
356
420
|
With `vision: true` or `'only'`, a recoverable semantic-capture failure can
|
|
357
421
|
use a fresh screenshot when the engine proves masking independently. With
|
|
358
422
|
`vision: false`, or after a secret fill, the capture failure stops the
|
|
359
|
-
judgment before any model call
|
|
423
|
+
judgment before any model call: a missing tree cannot support a judgment
|
|
360
424
|
about an empty screen.
|
|
361
425
|
|
|
362
426
|
If capture fails before a judgment, the report records zero model calls and
|
|
363
427
|
omits `observationRevision` and `explanation`. The step error describes the
|
|
364
428
|
capture failure. An answer the closed grammar rejects is a `schema` event on
|
|
365
|
-
the step and earns one repair round
|
|
366
|
-
step fails with `MODEL_OUTPUT_INVALID
|
|
429
|
+
the step and earns one repair round. When the repaired answer is rejected
|
|
430
|
+
too, the step fails with `MODEL_OUTPUT_INVALID`, and its `explanation` is the
|
|
431
|
+
rejection.
|
|
367
432
|
|
|
368
433
|
## Types
|
|
369
434
|
|
|
370
435
|
```ts
|
|
436
|
+
export interface Agent {
|
|
437
|
+
/** Plans and executes a bounded multi-action flow; resolves with what the step did. */
|
|
438
|
+
act(instruction: string, options?: ActOptions): Promise<ActResult>;
|
|
439
|
+
/** Polls a natural-language condition until true or timed out. */
|
|
440
|
+
waitFor(condition: string, options?: WaitForOptions): Promise<void>;
|
|
441
|
+
/** Extracts and validates structured screen data. */
|
|
442
|
+
extract<Schema extends StandardSchemaV1>(
|
|
443
|
+
instruction: string,
|
|
444
|
+
options: ExtractOptions<Schema>,
|
|
445
|
+
): Promise<StandardSchemaV1.InferOutput<Schema>>;
|
|
446
|
+
/** Judges a natural-language assertion against a fresh observation. */
|
|
447
|
+
assert(assertion: string, options?: AssertOptions): Promise<void>;
|
|
448
|
+
}
|
|
449
|
+
|
|
371
450
|
/**
|
|
372
451
|
* Parameters and budgets for one `act` call.
|
|
373
452
|
*/
|
|
@@ -471,6 +550,16 @@ export interface StepCacheInfo {
|
|
|
471
550
|
notRecorded?: 'param-collision';
|
|
472
551
|
replayedActions: number;
|
|
473
552
|
totalActions: number;
|
|
553
|
+
/** The step's cache key, which names its entry file (`<cache.dir>/<entry>.json` in the file store). */
|
|
554
|
+
entry?: string;
|
|
555
|
+
/**
|
|
556
|
+
* Why the replay missed or handed off, past what the reason token says:
|
|
557
|
+
* the recorded action it stopped at and what went wrong there, or the
|
|
558
|
+
* screen the recording started on against the one the step did.
|
|
559
|
+
*/
|
|
560
|
+
detail?: string;
|
|
561
|
+
/** Configured model when the consulted entry was recorded; absent on older entries. */
|
|
562
|
+
recordedBy?: { readonly provider: string; readonly model: string };
|
|
474
563
|
}
|
|
475
564
|
|
|
476
565
|
type TraceReplayMissReason = 'retry' | 'no-entry' | 'invalid-entry' | 'truncated' | 'wrong-context';
|
|
@@ -499,12 +588,20 @@ export type AgentParam =
|
|
|
499
588
|
Each `StepCacheInfo.reason` is explained under
|
|
500
589
|
[Why a step was not replayed](/cache#why-a-step-was-not-replayed).
|
|
501
590
|
|
|
502
|
-
`Unique` is what `unique()` returns
|
|
503
|
-
the replay cache records as a slot and substitutes on replay. See
|
|
504
|
-
[Cache](/cache).
|
|
591
|
+
`Unique` is what [`unique()`](#unique) returns.
|
|
505
592
|
|
|
506
593
|
## unique
|
|
507
594
|
|
|
595
|
+
Marks an `act` param whose value differs on every run. The
|
|
596
|
+
[replay cache](/cache) records a slot instead of the value, and substitutes
|
|
597
|
+
this run's value on replay.
|
|
598
|
+
|
|
599
|
+
```ts
|
|
600
|
+
await agent.act('create a company named {name}', {
|
|
601
|
+
params: { name: unique(`Acme ${Date.now()}`) },
|
|
602
|
+
});
|
|
603
|
+
```
|
|
604
|
+
|
|
508
605
|
```ts
|
|
509
606
|
import { unique } from 'e2e';
|
|
510
607
|
|
|
@@ -521,14 +618,9 @@ export interface Unique {
|
|
|
521
618
|
export function unique(value: string): Unique;
|
|
522
619
|
```
|
|
523
620
|
|
|
524
|
-
Throws
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
```ts
|
|
528
|
-
await agent.act('create a company named {name}', {
|
|
529
|
-
params: { name: unique(`Acme ${Date.now()}`) },
|
|
530
|
-
});
|
|
531
|
-
```
|
|
621
|
+
| Throws | When |
|
|
622
|
+
| --- | --- |
|
|
623
|
+
| `INVALID_ARGUMENT` | The value is not a string, is empty or only whitespace, or contains the placeholder text `{{param:`. |
|
|
532
624
|
|
|
533
625
|
## AgentError
|
|
534
626
|
|