@testdriverai/agent 7.11.240-test → 7.11.241-canary

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.
Files changed (52) hide show
  1. package/ai/skills/testdriver-agent/SKILL.md +174 -91
  2. package/ai/skills/testdriver-assert/SKILL.md +73 -269
  3. package/ai/skills/testdriver-aws-setup/SKILL.md +194 -312
  4. package/ai/skills/testdriver-bring-your-own-machine/SKILL.md +137 -204
  5. package/ai/skills/testdriver-cache/SKILL.md +142 -149
  6. package/ai/skills/testdriver-caching/SKILL.md +97 -87
  7. package/ai/skills/testdriver-captcha/SKILL.md +126 -111
  8. package/ai/skills/testdriver-ci-cd/SKILL.md +153 -542
  9. package/ai/skills/testdriver-click/SKILL.md +74 -229
  10. package/ai/skills/testdriver-client/SKILL.md +175 -229
  11. package/ai/skills/testdriver-customizing-devices/SKILL.md +72 -250
  12. package/ai/skills/testdriver-dashcam/SKILL.md +71 -404
  13. package/ai/skills/testdriver-debugging-with-screenshots/SKILL.md +103 -369
  14. package/ai/skills/testdriver-double-click/SKILL.md +46 -67
  15. package/ai/skills/testdriver-errors/SKILL.md +102 -176
  16. package/ai/skills/testdriver-events/SKILL.md +170 -327
  17. package/ai/skills/testdriver-exec/SKILL.md +92 -256
  18. package/ai/skills/testdriver-extract/SKILL.md +69 -170
  19. package/ai/skills/testdriver-find/SKILL.md +140 -736
  20. package/ai/skills/testdriver-focus-application/SKILL.md +69 -246
  21. package/ai/skills/testdriver-generating-tests/SKILL.md +102 -136
  22. package/ai/skills/testdriver-hosted/SKILL.md +79 -143
  23. package/ai/skills/testdriver-hover/SKILL.md +62 -235
  24. package/ai/skills/testdriver-locating-elements/SKILL.md +71 -366
  25. package/ai/skills/testdriver-making-assertions/SKILL.md +114 -72
  26. package/ai/skills/testdriver-mcp-setup/SKILL.md +79 -62
  27. package/ai/skills/testdriver-mouse-down/SKILL.md +46 -124
  28. package/ai/skills/testdriver-mouse-up/SKILL.md +45 -128
  29. package/ai/skills/testdriver-options/SKILL.md +73 -46
  30. package/ai/skills/testdriver-parse/SKILL.md +95 -184
  31. package/ai/skills/testdriver-performing-actions/SKILL.md +101 -91
  32. package/ai/skills/testdriver-press-keys/SKILL.md +59 -299
  33. package/ai/skills/testdriver-provision/SKILL.md +135 -179
  34. package/ai/skills/testdriver-quickstart/SKILL.md +24 -8
  35. package/ai/skills/testdriver-quickstart-claude/SKILL.md +84 -0
  36. package/ai/skills/testdriver-quickstart-github/SKILL.md +62 -32
  37. package/ai/skills/testdriver-quickstart-manual/SKILL.md +59 -32
  38. package/ai/skills/testdriver-quickstart-vscode/SKILL.md +96 -0
  39. package/ai/skills/testdriver-redraw/SKILL.md +100 -164
  40. package/ai/skills/testdriver-reusable-code/SKILL.md +95 -199
  41. package/ai/skills/testdriver-right-click/SKILL.md +45 -88
  42. package/ai/skills/testdriver-screenshot/SKILL.md +47 -201
  43. package/ai/skills/testdriver-screenshots/SKILL.md +86 -136
  44. package/ai/skills/testdriver-scroll/SKILL.md +71 -154
  45. package/ai/skills/testdriver-secrets/SKILL.md +94 -90
  46. package/ai/skills/testdriver-self-hosted/SKILL.md +82 -140
  47. package/ai/skills/testdriver-test-results-json/SKILL.md +165 -202
  48. package/ai/skills/testdriver-type/SKILL.md +56 -304
  49. package/ai/skills/testdriver-variables/SKILL.md +119 -80
  50. package/ai/skills/testdriver-wait/SKILL.md +31 -29
  51. package/ai/skills/testdriver-what-is-testdriver/SKILL.md +80 -32
  52. package/package.json +1 -1
@@ -1,356 +1,199 @@
1
1
  ---
2
2
  name: testdriver:events
3
- description: Listen to SDK lifecycle events with wildcard support
3
+ description: Listen to what TestDriver does during a test through its event emitter.
4
4
  ---
5
5
  <!-- Generated from events.mdx. DO NOT EDIT. -->
6
6
 
7
- ## Overview
8
-
9
- TestDriver uses [EventEmitter2](https://github.com/EventEmitter2/EventEmitter2) for its event system. Events use a namespace pattern with colons. They permit wildcard listeners.
10
-
11
- Use the emitter through `testdriver.emitter`:
12
-
13
- ```javascript
14
- testdriver.emitter.on('command:start', (data) => {
15
- console.log(`Running: ${data.command}`);
16
- });
17
- ```
18
-
19
- ### Configuration
20
-
21
- The internal emitter is created with:
22
-
23
- ```javascript
24
- new EventEmitter2({
25
- wildcard: true,
26
- delimiter: ':',
27
- maxListeners: 20,
28
- verboseMemoryLeak: false,
29
- ignoreErrors: false,
30
- });
31
- ```
32
-
33
- ### Wildcard Listeners
34
-
35
- Use `*` to match one level. Use `**` to match many levels:
36
-
37
- ```javascript
38
- // Match all log events
39
- testdriver.emitter.on('log:*', (message) => {
40
- console.log(message);
41
- });
42
-
43
- // Match all events in any namespace
44
- testdriver.emitter.on('**', (...args) => {
45
- console.log('Event:', this.event, args);
46
- });
47
- ```
48
-
49
- ## Event Reference
50
-
51
- ### Command Events
52
-
53
- Emitted during the execution of SDK commands (`click`, `type`, `find`, etc.).
54
-
55
- | Event | Payload |
56
- |---|---|
57
- | `command:start` | `{ command, depth, data, timestamp, sourcePosition }` |
58
- | `command:success` | `{ command, depth, data, duration, response, timestamp, sourcePosition }` |
59
- | `command:error` | `{ command, depth, data, error, duration, timestamp, sourcePosition }` |
60
- | `command:status` | `{ command, status: "executing", data, depth, timestamp }` |
61
- | `command:progress` | `{ command, status: "completed", timing, data, depth, timestamp }` |
62
-
63
- ```javascript
64
- testdriver.emitter.on('command:start', ({ command, data }) => {
65
- console.log(`Starting ${command}`, data);
66
- });
67
-
68
- testdriver.emitter.on('command:error', ({ command, error, duration }) => {
69
- console.error(`${command} failed after ${duration}ms: ${error}`);
70
- });
71
- ```
72
-
73
- ### Step Events
74
-
75
- Emitted for each AI reasoning step within a command.
76
-
77
- | Event | Payload |
78
- |---|---|
79
- | `step:start` | `{ stepIndex, prompt, commandCount, timestamp, sourcePosition }` |
80
- | `step:success` | `{ stepIndex, prompt, commandCount, duration, timestamp, sourcePosition }` |
81
- | `step:error` | `{ stepIndex, prompt, error, duration?, timestamp, sourcePosition? }` |
82
-
83
- ```javascript
84
- testdriver.emitter.on('step:start', ({ stepIndex, prompt }) => {
85
- console.log(`Step ${stepIndex}: ${prompt}`);
86
- });
87
- ```
88
-
89
- ### Test Events
90
-
91
- Emitted when a test file execution starts.
92
-
93
- | Event | Payload |
94
- |---|---|
95
- | `test:start` | `{ filePath, timestamp }` |
96
- | `test:success` | *Emitted on test completion* |
97
- | `test:error` | *Emitted on test failure* |
98
-
99
- ### Log Events
100
-
101
- Emitted for all log output from the SDK.
102
-
103
- | Event | Payload |
104
- |---|---|
105
- | `log:log` | `(message: string)` — general log message |
106
- | `log:warn` | `(message: string)` — warning message |
107
- | `log:debug` | `(message: string)` — debug output (only when `VERBOSE`/`DEBUG`/`TD_DEBUG` env set) |
108
- | `log:info` | `(message: string)` — informational message |
109
- | `log:error` | `(message: string)` — error message |
110
- | `log:narration` | `(message: string, overwrite?: boolean)` — in-place status line |
111
- | `log:markdown` | `(markdown: string)` — full static markdown content |
112
- | `log:markdown:start` | `(streamId: string)` — begin streaming markdown |
113
- | `log:markdown:chunk` | `(streamId: string, chunk: string)` — incremental chunk |
114
- | `log:markdown:end` | `(streamId: string)` — end streaming markdown |
7
+ TestDriver reports what it's doing through an event emitter. Get it with [`getEmitter()`](/client#getemitter) and listen with `on()`:
115
8
 
116
9
  ```javascript
117
- // Capture all logs
118
- testdriver.emitter.on('log:*', function (message) {
119
- console.log(`[${this.event}]`, message);
120
- });
121
- ```
122
-
123
- ### Screen Capture Events
124
-
125
- Emitted during screenshot capture.
10
+ const emitter = testdriver.getEmitter();
126
11
 
127
- | Event | Payload |
128
- |---|---|
129
- | `screen-capture:start` | `{ scale, silent, display }` |
130
- | `screen-capture:end` | `{ scale, silent, display }` |
131
- | `screen-capture:error` | `{ error, scale, silent, display }` |
132
-
133
- ### Sandbox Events
134
-
135
- Emitted for sandbox WebSocket lifecycle and communication.
136
-
137
- | Event | Payload |
138
- |---|---|
139
- | `sandbox:connected` | *No payload* — WebSocket connection established |
140
- | `sandbox:authenticated` | `{ traceId }` — authentication successful |
141
- | `sandbox:error` | `(err: Error \| string)` — connection or sandbox error |
142
- | `sandbox:sent` | `(message: object)` — WebSocket message sent |
143
- | `sandbox:received` | *No payload* — successful message reply received |
144
- | `sandbox:progress` | `{ step, message }` — sandbox setup progress |
145
-
146
- ```javascript
147
- testdriver.emitter.on('sandbox:connected', () => {
148
- console.log('Connected to sandbox');
149
- });
150
-
151
- testdriver.emitter.on('sandbox:progress', ({ step, message }) => {
152
- console.log(`Sandbox: [${step}] ${message}`);
12
+ emitter.on('sandbox:progress', ({ step, message }) => {
13
+ console.log(`[${step}] ${message}`);
153
14
  });
154
15
  ```
155
16
 
156
- ### Redraw Events
157
-
158
- Emitted during screen stability detection. See [Redraw](/redraw) for more details.
159
-
160
- | Event | Payload |
161
- |---|---|
162
- | `redraw:status` | `{ redraw: { enabled, settled, hasChangedFromInitial, consecutiveFramesStable, diffFromInitial, diffFromLast, text }, network: { enabled, settled, rxBytes, txBytes, text }, timeout: { isTimeout, elapsed, max, text } }` |
163
- | `redraw:complete` | `{ screenSettled, hasChangedFromInitial, consecutiveFramesStable, networkSettled, isTimeout, timeElapsed }` |
164
-
165
- ```javascript
166
- testdriver.emitter.on('redraw:complete', (result) => {
167
- if (result.isTimeout) {
168
- console.warn('Redraw timed out after', result.timeElapsed, 'ms');
169
- }
170
- });
171
- ```
17
+ The emitter is an [EventEmitter2](https://github.com/EventEmitter2/EventEmitter2) instance. Event names are segments separated by colons, such as `redraw:complete`.
172
18
 
173
- ### File Events
19
+ ## Listen in a test
174
20
 
175
- Emitted during file load/save operations in the agent.
21
+ The emitter exists as soon as you create the client, so add listeners before the first command:
176
22
 
177
- | Event | Payload |
178
- |---|---|
179
- | `file:start` | `{ operation: "load" \| "save" \| "run", filePath, timestamp }` |
180
- | `file:stop` | `{ operation, filePath, duration, success, sourceMap?, reason?, timestamp }` |
181
- | `file:load` | `{ filePath, size, timestamp }` |
182
- | `file:save` | `{ filePath, size, timestamp }` |
183
- | `file:diff` | `{ filePath, diff: { patches, sourceMaps, summary: { additions, deletions, modifications } }, timestamp }` |
184
- | `file:error` | `{ operation, filePath, error, duration?, timestamp }` |
23
+ ```javascript tests/login.test.mjs
24
+ import { describe, expect, it } from 'vitest';
25
+ import { TestDriver } from 'testdriverai/vitest/hooks';
185
26
 
186
- ### Error Events
27
+ describe('Login', () => {
28
+ it('shows an error for an empty form', async (context) => {
29
+ const testdriver = TestDriver(context);
30
+ const emitter = testdriver.getEmitter();
187
31
 
188
- Emitted for errors at various severity levels.
32
+ const clicks = [];
33
+ emitter.on('mouse-click', ({ x, y, button }) => {
34
+ clicks.push({ x, y, button });
35
+ });
189
36
 
190
- | Event | Payload |
191
- |---|---|
192
- | `error:fatal` | `(error: string \| Error)` — terminates the process |
193
- | `error:general` | `(message: string)` — non-fatal error |
194
- | `error:sandbox` | `(err: Error \| string)` — sandbox/WebSocket error |
37
+ await testdriver.provision.chrome({ url: 'https://testdriver-sandbox.vercel.app/login' });
38
+ await testdriver.find('Sign in button below the password field').click();
195
39
 
196
- ```javascript
197
- testdriver.emitter.on('error:*', function (err) {
198
- console.error(`[${this.event}]`, err);
40
+ console.log(clicks); // e.g. [{ x: 683, y: 412, button: 'left' }]
41
+ expect(await testdriver.assert('an error says the fields are required')).toBe(true);
42
+ });
199
43
  });
200
44
  ```
201
45
 
202
- ### SDK Events
203
-
204
- Emitted for API request lifecycle.
46
+ ## Use wildcards
205
47
 
206
- | Event | Payload |
207
- |---|---|
208
- | `sdk:request` | `{ path }` — outgoing API request |
209
- | `sdk:response` | `{ path }` — API response received |
210
- | `sdk:retry` | `{ path, attempt, error, delayMs }` — request retry |
211
-
212
- ### Other Events
213
-
214
- | Event | Payload |
215
- |---|---|
216
- | `exit` | `(exitCode: number)` — `0` for success, `1` for failure |
217
- | `status` | `(message: string)` — general status updates |
218
- | `mouse-click` | `{ x, y, button, click, double }` — mouse click performed |
219
- | `terminal:stdout` | Terminal stdout output |
220
- | `terminal:stderr` | Terminal stderr output |
221
-
222
- ## Practical Examples
223
-
224
- ### Custom Test Reporter
225
-
226
- ```javascript
227
- const results = [];
228
-
229
- testdriver.emitter.on('command:success', ({ command, duration }) => {
230
- results.push({ command, duration, status: 'pass' });
231
- });
232
-
233
- testdriver.emitter.on('command:error', ({ command, duration, error }) => {
234
- results.push({ command, duration, status: 'fail', error });
235
- });
236
-
237
- // After test completes
238
- afterAll(() => {
239
- console.table(results);
240
- });
241
- ```
242
-
243
- ### Progress Monitoring
48
+ `*` matches one segment. `**` matches any number of segments. Use a `function` listener, not an arrow function, to read the event's name from `this.event`:
244
49
 
245
50
  ```javascript
246
- testdriver.emitter.on('step:start', ({ stepIndex, prompt }) => {
247
- process.stdout.write(`\r Step ${stepIndex}: ${prompt}`);
248
- });
249
-
250
- testdriver.emitter.on('command:progress', ({ command, timing }) => {
251
- process.stdout.write(`\r ${command} completed in ${timing}ms`);
51
+ // Every error event: error:fatal, error:sdk, and so on
52
+ emitter.on('error:*', function (error) {
53
+ console.error(`[${this.event}]`, error);
252
54
  });
253
- ```
254
-
255
- ### Debug Logging
256
55
 
257
- ```javascript
258
- // Log every event (verbose)
259
- testdriver.emitter.on('**', function (...args) {
260
- console.debug(`[EVENT] ${this.event}`, ...args);
56
+ // Every event, with its arguments
57
+ emitter.on('**', function (...args) {
58
+ console.debug(this.event, ...args);
261
59
  });
262
60
  ```
263
61
 
264
- ## Types
265
-
266
- ```typescript
267
- interface CommandStartEvent {
268
- command: string;
269
- depth: number;
270
- data: Record<string, any>;
271
- timestamp: number;
272
- sourcePosition: SourcePosition;
273
- }
274
-
275
- interface CommandSuccessEvent {
276
- command: string;
277
- depth: number;
278
- data: Record<string, any>;
279
- duration: number;
280
- response: any;
281
- timestamp: number;
282
- sourcePosition: SourcePosition;
283
- }
284
-
285
- interface CommandErrorEvent {
286
- command: string;
287
- depth: number;
288
- data: Record<string, any>;
289
- error: string;
290
- duration: number;
291
- timestamp: number;
292
- sourcePosition: SourcePosition;
293
- }
294
-
295
- interface StepStartEvent {
296
- stepIndex: number;
297
- prompt: string;
298
- commandCount: number;
299
- timestamp: number;
300
- sourcePosition: SourcePosition;
301
- }
302
-
303
- interface StepSuccessEvent {
304
- stepIndex: number;
305
- prompt: string;
306
- commandCount: number;
307
- duration: number;
308
- timestamp: number;
309
- sourcePosition: SourcePosition;
310
- }
311
-
312
- interface RedrawStatusEvent {
313
- redraw: {
314
- enabled: boolean;
315
- settled: boolean;
316
- hasChangedFromInitial: boolean;
317
- consecutiveFramesStable: number;
318
- diffFromInitial: number;
319
- diffFromLast: number;
320
- text: string;
321
- };
322
- network: {
323
- enabled: boolean;
324
- settled: boolean;
325
- rxBytes: number;
326
- txBytes: number;
327
- text: string;
328
- };
329
- timeout: {
330
- isTimeout: boolean;
331
- elapsed: number;
332
- max: number;
333
- text: string;
334
- };
335
- }
336
-
337
- interface RedrawCompleteEvent {
338
- screenSettled: boolean;
339
- hasChangedFromInitial: boolean;
340
- consecutiveFramesStable: number;
341
- networkSettled: boolean;
342
- isTimeout: boolean;
343
- timeElapsed: number;
344
- }
345
-
346
- interface SandboxProgressEvent {
347
- step: string;
348
- message: string;
349
- }
350
-
351
- interface SourcePosition {
352
- file: string;
353
- line: number;
354
- column: number;
355
- }
356
- ```
62
+ `log:*` matches `log:log` and `log:warn` but not `log:markdown:start`, which has three segments. Use `log:**` to match all of them.
63
+
64
+ ## Log events
65
+
66
+ The SDK prints these to the console unless you turn logging off with the `logging` option.
67
+
68
+ | Event | Arguments | When |
69
+ | --- | --- | --- |
70
+ | `log:log` | `(message: string)` | General output, such as each action and `find()` |
71
+ | `log:warn` | `(message: string)` | A warning |
72
+ | `log:debug` | `(message: string)` | Debug detail. Always emitted, but printed only when `VERBOSE` or `TD_DEBUG` is set |
73
+ | `log:narration` | `(message: string, overwrite?: boolean)` | Progress detail for an action, such as how long a redraw wait took |
74
+ | `log:markdown` | `(markdown: string)` | A complete Markdown message from `ai()` |
75
+ | `log:markdown:start` | `(streamId: string)` | `ai()` starts streaming a Markdown message |
76
+ | `log:markdown:chunk` | `(streamId: string, chunk: string)` | The next piece of that message |
77
+ | `log:markdown:end` | `(streamId: string)` | The message is complete |
78
+
79
+ There's no `log:info` or `log:error` in the event list. Listen to `log:log` and `error:*` instead.
80
+
81
+ ## Error events
82
+
83
+ | Event | Arguments | When |
84
+ | --- | --- | --- |
85
+ | `error:fatal` | `(error: string \| Error)` | TestDriver hit an error it can't recover from |
86
+ | `error:general` | `(message: string)` | A non-fatal error |
87
+ | `error:sdk` | `({ message, code, ... })` | A request to the TestDriver API failed |
88
+ | `error:sandbox` | `(message: string)` | The sandbox reported an error, or the realtime connection to it failed |
89
+
90
+ ## Sandbox events
91
+
92
+ | Event | Arguments | When |
93
+ | --- | --- | --- |
94
+ | `sandbox:authenticated` | `({ traceId })` | The connection to the sandbox is authenticated |
95
+ | `sandbox:connected` | none | The client is connected to a sandbox |
96
+ | `sandbox:progress` | `({ step, message })` | A setup step while the sandbox starts, or recovery after a dropped connection |
97
+ | `sandbox:sent` | `(message: object)` | A message was sent to the sandbox |
98
+ | `sandbox:received` | none | The sandbox replied to a message |
99
+ | `sandbox:file` | `(message: object)` | The sandbox sent a file message |
100
+ | `show-window` | `(url: string)` | The live preview URL is ready to open |
101
+
102
+ ## Action events
103
+
104
+ | Event | Arguments | When |
105
+ | --- | --- | --- |
106
+ | `mouse-click` | `({ x, y, button, double })` | A click, double-click, right-click, `mouseDown()`, or `mouseUp()` was sent. `button` is `'left'` or `'right'`, and `double` is `true` for a double-click |
107
+ | `exec:output` | `({ chunk, requestId })` | A piece of output from a running [`exec()`](/exec) command |
108
+ | `screen-capture:start` | `({ scale, silent, display })` | TestDriver starts capturing the screen |
109
+ | `screen-capture:end` | `({ scale, silent, display })` | The capture finished |
110
+ | `screen-capture:error` | `({ error, scale, silent, display })` | The capture failed |
111
+
112
+ ## Redraw events
113
+
114
+ Emitted only when [redraw detection](/redraw) is on.
115
+
116
+ | Event | Arguments | When |
117
+ | --- | --- | --- |
118
+ | `redraw:status` | `(status: object)` | Every 500 ms while TestDriver waits for the screen to settle |
119
+ | `redraw:complete` | `(result: object)` | The wait ended, either settled or timed out |
120
+
121
+ <ResponseField name="redraw:status" type="object">
122
+ <Expandable title="properties">
123
+ <ResponseField name="redraw" type="object">
124
+ Screen state: `enabled`, `settled`, `hasChangedFromInitial`, `consecutiveFramesStable` (booleans), `diffFromInitial` and `diffFromLast` (percent of pixels that differ), and `text` (a short summary for the console).
125
+ </ResponseField>
126
+ <ResponseField name="network" type="object">
127
+ Network state: `enabled`, `settled` (booleans), `rxBytes` and `txBytes` (bytes since the last check), and `text`.
128
+ </ResponseField>
129
+ <ResponseField name="timeout" type="object">
130
+ Timing: `isTimeout` (boolean), `elapsed` and `max` (milliseconds), and `text`.
131
+ </ResponseField>
132
+ </Expandable>
133
+ </ResponseField>
134
+
135
+ <ResponseField name="redraw:complete" type="object">
136
+ <Expandable title="properties">
137
+ <ResponseField name="screenSettled" type="boolean">
138
+ Whether the screen settled. `true` when the screen check is off.
139
+ </ResponseField>
140
+ <ResponseField name="networkSettled" type="boolean">
141
+ Whether network traffic settled. `true` when the network check is off.
142
+ </ResponseField>
143
+ <ResponseField name="hasChangedFromInitial" type="boolean">
144
+ Whether the screen changed after the action.
145
+ </ResponseField>
146
+ <ResponseField name="consecutiveFramesStable" type="boolean">
147
+ Whether the last frames stopped changing.
148
+ </ResponseField>
149
+ <ResponseField name="isTimeout" type="boolean">
150
+ Whether the wait ended because it ran out of time.
151
+ </ResponseField>
152
+ <ResponseField name="timeElapsed" type="number">
153
+ How long the wait took, in milliseconds.
154
+ </ResponseField>
155
+ </Expandable>
156
+ </ResponseField>
157
+
158
+ ## API request events
159
+
160
+ | Event | Arguments | When |
161
+ | --- | --- | --- |
162
+ | `sdk:request` | `({ path })` | A request to the TestDriver API starts |
163
+ | `sdk:response` | `({ path })` | The API responded |
164
+ | `sdk:retry` | `({ path, attempt, error, delayMs })` | A failed request will be retried after `delayMs` milliseconds |
165
+
166
+ ## ai() command events
167
+
168
+ These fire for the commands the AI runs inside [`ai()`](/errors#aierror). Commands you call yourself, such as `testdriver.click()`, don't emit them.
169
+
170
+ | Event | Arguments |
171
+ | --- | --- |
172
+ | `command:start` | `({ command, depth, data, timestamp, sourcePosition })` |
173
+ | `command:status` | `({ command, status: 'executing', data, depth, timestamp })` |
174
+ | `command:progress` | `({ command, status: 'completed', timing, data, depth, timestamp })` |
175
+ | `command:success` | `({ command, depth, data, duration, response, timestamp, sourcePosition })` |
176
+ | `command:error` | `({ command, depth, data, error, duration, timestamp, sourcePosition })` |
177
+
178
+ - `command` is the command name, and `data` is the full command the AI generated.
179
+ - `error` is the error message as a string.
180
+ - `timing` and `duration` are in milliseconds.
181
+
182
+ ## Other events
183
+
184
+ | Event | Arguments | When |
185
+ | --- | --- | --- |
186
+ | `runner:log` | `({ level, message, timestamp })` | A log line from the sandbox's runner. Sent only when debug logging is on |
187
+ | `exit` | `(exitCode: number)` | The agent stopped. `0` means success, `1` means failure |
188
+
189
+ The event list also contains names that Vitest tests don't emit:
190
+
191
+ - `step:*`, `test:*`, and `file:*` come from running YAML test files.
192
+ - `command:stop`, `command:location`, `sandbox:error`, `sandbox:disconnected`, `sdk:error`, `sdk:progress`, `status`, `mouse-move`, `terminal:stdout`, `terminal:stderr`, `matches:show`, and `vm:show` aren't currently emitted.
193
+
194
+ ## Related
195
+
196
+ - [getEmitter()](/client#getemitter): get the client's emitter
197
+ - [Redraw](/redraw): what the redraw events measure
198
+ - [Errors](/errors): the errors TestDriver throws
199
+ - [Debug a failing test](/debugging-with-screenshots): find out why a test failed