@oya-ai/browser 1.0.97 → 1.0.99
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/dist/index.cjs +510 -323
- package/dist/index.d.cts +798 -431
- package/dist/index.d.ts +798 -431
- package/dist/index.js +512 -325
- package/package.json +14 -6
package/dist/index.d.cts
CHANGED
|
@@ -1,14 +1,232 @@
|
|
|
1
|
-
/**
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Types for browsers themselves: starting one, what a page looks like to the
|
|
3
|
+
* SDK, the results of CAPTCHA and MFA handling, and the fleet listing.
|
|
4
|
+
*/
|
|
5
|
+
/** Where a browser comes from. Configuration, not something a caller must know. */
|
|
6
|
+
type Provider = 'oya-cloud' | 'oya-selfhosted' | 'browseruse' | 'browserbase' | 'steel' | 'anchor' | 'cdp';
|
|
7
|
+
/** How `oya.browser.start()` should start a browser. Every field is optional. */
|
|
8
|
+
interface StartOptions {
|
|
9
|
+
/** Reuse this value when retrying the same logical creation. */
|
|
10
|
+
idempotencyKey?: string;
|
|
11
|
+
/** Wait for capacity for up to five minutes; zero rejects immediately. */
|
|
12
|
+
queueMs?: number;
|
|
13
|
+
/** Spend ceiling for this browser, in US dollars. */
|
|
14
|
+
budgetUsd?: number;
|
|
15
|
+
/** Run under the project's governance: policies, budgets and recordings. */
|
|
16
|
+
governed?: boolean;
|
|
17
|
+
/** Egress and recording rules for a governed browser. */
|
|
18
|
+
policy?: {
|
|
19
|
+
/** Hosts the browser may reach; everything else is blocked. */
|
|
20
|
+
allowedHosts?: string[];
|
|
21
|
+
/** Hosts where a person, not the agent, must act. */
|
|
22
|
+
humanHosts?: string[];
|
|
23
|
+
/** Where the browser must run. */
|
|
24
|
+
region?: string;
|
|
25
|
+
/** Blur typed values out of the session recording. */
|
|
26
|
+
redactRecording?: boolean;
|
|
27
|
+
};
|
|
28
|
+
/** Place in the queue when capacity is short. */
|
|
29
|
+
priority?: 'low' | 'normal' | 'high';
|
|
30
|
+
/** Saved login profile. Defaults to the desktop's default profile. */
|
|
31
|
+
profile?: string;
|
|
32
|
+
/**
|
|
33
|
+
* Which identity to run as. A persona is one device: fingerprint, cookie jar
|
|
34
|
+
* and proxy bound together and stable for its life.
|
|
35
|
+
* 'default' — this key's own persona (the default)
|
|
36
|
+
* 'auto' — the least recently used persona under its concurrency cap
|
|
37
|
+
* <id> — a specific persona
|
|
38
|
+
*/
|
|
39
|
+
persona?: 'default' | 'auto' | (string & {});
|
|
40
|
+
/** Solve CAPTCHAs as they appear rather than waiting to be asked. */
|
|
41
|
+
captcha?: 'auto' | 'off';
|
|
42
|
+
/** Override the key's configured provider for this browser only. */
|
|
43
|
+
provider?: Provider;
|
|
44
|
+
/** Required only for the 'cdp' provider. */
|
|
45
|
+
wsUrl?: string;
|
|
46
|
+
/** A label for the fleet listing. */
|
|
47
|
+
name?: string;
|
|
48
|
+
/** How long to wait for a cloud browser to dial in. Default 120s. */
|
|
49
|
+
readyTimeoutMs?: number;
|
|
50
|
+
}
|
|
51
|
+
/** What the server answers when a browser starts. */
|
|
52
|
+
interface StartResult {
|
|
53
|
+
/** The browser's id, for every later call. */
|
|
54
|
+
id: string;
|
|
55
|
+
/** Which provider runs it. */
|
|
56
|
+
provider: string;
|
|
57
|
+
/** Which persona it runs as. */
|
|
58
|
+
persona: string;
|
|
59
|
+
/** 'starting' while a cloud browser has yet to dial in. */
|
|
60
|
+
status: 'ready' | 'starting';
|
|
61
|
+
/** Point Playwright, Puppeteer or browser-use at this. */
|
|
62
|
+
cdpUrl?: string;
|
|
63
|
+
/** Anything the server wants the caller to know about this start. */
|
|
64
|
+
note?: string;
|
|
65
|
+
}
|
|
66
|
+
/** One element on the page, numbered by `analyze()`. */
|
|
67
|
+
interface Element {
|
|
68
|
+
/** The number to pass to `click()` and `type()`. Valid until the page changes. */
|
|
69
|
+
id: number;
|
|
70
|
+
/** What kind of control it is: link, button, input and so on. */
|
|
71
|
+
type: string;
|
|
72
|
+
/** Visible label, capped at 80 characters by the analyzer. */
|
|
73
|
+
text?: string;
|
|
74
|
+
/** Where a link goes. */
|
|
75
|
+
href?: string;
|
|
76
|
+
/** The current value of a field. */
|
|
77
|
+
value?: string;
|
|
78
|
+
/** Whether a checkbox or radio is ticked. */
|
|
79
|
+
checked?: boolean;
|
|
80
|
+
/** Whether it refuses input. */
|
|
81
|
+
disabled?: boolean;
|
|
82
|
+
/** Whether it is on screen. */
|
|
83
|
+
visible: boolean;
|
|
84
|
+
/** The HTML tag name. */
|
|
85
|
+
tag?: string;
|
|
86
|
+
/** The element's DOM `id`. Usually the most stable handle a site offers. */
|
|
87
|
+
domId?: string;
|
|
88
|
+
/** Its `aria-label`. */
|
|
89
|
+
ariaLabel?: string;
|
|
90
|
+
/** `data-testid`, when the site ships one. */
|
|
91
|
+
testId?: string;
|
|
92
|
+
/** Its `name` attribute. */
|
|
93
|
+
name?: string;
|
|
94
|
+
/** A field's placeholder text. */
|
|
95
|
+
placeholder?: string;
|
|
96
|
+
/** Action of the enclosing form. */
|
|
97
|
+
formName?: string;
|
|
98
|
+
}
|
|
99
|
+
/** The page as `analyze()` sees it. */
|
|
100
|
+
interface Analysis {
|
|
101
|
+
/** The page as markdown. */
|
|
102
|
+
markdown: string;
|
|
103
|
+
/** Every numbered element, visible or not. */
|
|
104
|
+
elements: Element[];
|
|
105
|
+
/** The window size, in CSS pixels. */
|
|
106
|
+
viewport?: {
|
|
107
|
+
/** Width in CSS pixels. */
|
|
108
|
+
width: number;
|
|
109
|
+
/** Height in CSS pixels. */
|
|
110
|
+
height: number;
|
|
111
|
+
};
|
|
112
|
+
/** How far the page is scrolled. */
|
|
113
|
+
scroll?: {
|
|
114
|
+
/** Horizontal offset in CSS pixels. */
|
|
115
|
+
x: number;
|
|
116
|
+
/** Vertical offset in CSS pixels. */
|
|
117
|
+
y: number;
|
|
118
|
+
};
|
|
119
|
+
/** True when the page was too long to send in full. */
|
|
120
|
+
truncated?: boolean;
|
|
121
|
+
}
|
|
122
|
+
/** What `solveCaptcha()` found and did. */
|
|
123
|
+
interface CaptchaResult {
|
|
124
|
+
/** Whether a CAPTCHA was on the page. */
|
|
125
|
+
present: boolean;
|
|
126
|
+
/** Whether it was cleared. */
|
|
127
|
+
solved: boolean;
|
|
128
|
+
/** 'provider' when the vendor solved it, 'solver' when we did, 'none' otherwise. */
|
|
129
|
+
method: 'provider' | 'solver' | 'none';
|
|
130
|
+
/** Which kind of CAPTCHA it was. */
|
|
131
|
+
type?: string;
|
|
132
|
+
/** Invisible reCAPTCHA v3 scores the visit passively; there is nothing on screen to clear. */
|
|
133
|
+
invisible?: boolean;
|
|
134
|
+
/** The site key the solver was given. */
|
|
135
|
+
sitekey?: string | null;
|
|
136
|
+
/** Why it was not solved. */
|
|
137
|
+
error?: string;
|
|
138
|
+
}
|
|
139
|
+
/** What `completeMfa()` found and did. */
|
|
140
|
+
interface MfaResult {
|
|
141
|
+
/** Whether an MFA prompt was on the page. */
|
|
142
|
+
present: boolean;
|
|
143
|
+
/** Whether it was answered and accepted. */
|
|
144
|
+
completed: boolean;
|
|
145
|
+
/** Which factor answered it, or 'handoff' when a person must. */
|
|
146
|
+
method?: 'totp' | 'email' | 'sms' | 'handoff' | 'none';
|
|
147
|
+
/** Whether the code was typed in. */
|
|
148
|
+
filled?: boolean;
|
|
149
|
+
/** Whether the form was submitted. */
|
|
150
|
+
submitted?: boolean;
|
|
151
|
+
/** Open this to finish by hand when nothing automated can. */
|
|
152
|
+
liveViewUrl?: string | null;
|
|
153
|
+
/** Why it could not be completed. */
|
|
154
|
+
error?: string;
|
|
155
|
+
}
|
|
156
|
+
/** How a browser is doing, judged from its recent commands and heartbeats. */
|
|
157
|
+
type Health = 'ok' | 'stale' | 'errors' | 'dead';
|
|
158
|
+
/** One thing a browser did. */
|
|
159
|
+
interface Activity {
|
|
160
|
+
/** When, as an ISO timestamp. */
|
|
161
|
+
ts: string;
|
|
162
|
+
/** The command's name. */
|
|
163
|
+
action: string;
|
|
164
|
+
/** A one-line account of it. */
|
|
165
|
+
summary: string;
|
|
166
|
+
/** Whether it succeeded. */
|
|
167
|
+
ok: boolean;
|
|
168
|
+
/** How long it took. */
|
|
169
|
+
ms: number;
|
|
170
|
+
/** Why it failed. */
|
|
171
|
+
error?: string;
|
|
172
|
+
}
|
|
173
|
+
/** The outcome of stopping one browser. */
|
|
174
|
+
interface StopResult {
|
|
175
|
+
/** The browser. */
|
|
176
|
+
id: string;
|
|
177
|
+
/** Whether it stopped. */
|
|
178
|
+
ok: boolean;
|
|
179
|
+
/** Which provider ran it. */
|
|
180
|
+
provider?: string | null;
|
|
181
|
+
/** For a cloud browser, whether its sandbox was destroyed (and billing ended). */
|
|
182
|
+
sandboxRemoved?: boolean | null;
|
|
183
|
+
/** Why it did not stop. */
|
|
184
|
+
error?: string;
|
|
185
|
+
}
|
|
186
|
+
/** One browser in the fleet listing. */
|
|
187
|
+
interface BrowserInfo {
|
|
188
|
+
/** The browser's id. */
|
|
189
|
+
id: string;
|
|
190
|
+
/** Its label. */
|
|
191
|
+
name: string;
|
|
192
|
+
/** An Oya Browser on the control socket, or a third-party browser over CDP. */
|
|
193
|
+
clientType: 'oya' | 'cdp';
|
|
194
|
+
/** Which provider runs it. */
|
|
195
|
+
provider: string | null;
|
|
196
|
+
/** The persona id it runs as. */
|
|
197
|
+
persona: string | null;
|
|
198
|
+
/** That persona's name. */
|
|
199
|
+
personaName: string | null;
|
|
200
|
+
/** How it is doing. */
|
|
201
|
+
health: Health;
|
|
202
|
+
/** When it connected. */
|
|
203
|
+
connectedAt: string;
|
|
204
|
+
/** When it was last heard from. */
|
|
205
|
+
lastSeen: string;
|
|
206
|
+
/** The page it is on. */
|
|
207
|
+
currentUrl: string;
|
|
208
|
+
/** Commands run so far. */
|
|
209
|
+
commands: number;
|
|
210
|
+
/** Commands that failed. */
|
|
211
|
+
errors: number;
|
|
212
|
+
/** Commands in flight. */
|
|
213
|
+
pending: number;
|
|
214
|
+
/** When it last ran a command. */
|
|
215
|
+
lastCommandAt: string | null;
|
|
216
|
+
/** The last failure's message. */
|
|
217
|
+
lastError: string | null;
|
|
218
|
+
}
|
|
219
|
+
/** A browser plus what it has been doing, from `browser.status()`. */
|
|
220
|
+
interface BrowserDetail extends BrowserInfo {
|
|
221
|
+
/** Its most recent commands, newest first. */
|
|
222
|
+
activity: Activity[];
|
|
9
223
|
}
|
|
10
224
|
|
|
11
|
-
/**
|
|
225
|
+
/**
|
|
226
|
+
* Types for a key's settings: the LLM behind `ask()`, the browser provider and
|
|
227
|
+
* the CAPTCHA solver, as `config.set()` accepts them and `config.get()` returns them.
|
|
228
|
+
*/
|
|
229
|
+
|
|
12
230
|
/** Which model drives `ask()` and the chat API. */
|
|
13
231
|
type LlmProvider = 'openai' | 'anthropic'
|
|
14
232
|
/** Gemini via AI Studio. */
|
|
@@ -24,6 +242,7 @@ type CaptchaSolver = 'capsolver' | '2captcha' | '';
|
|
|
24
242
|
* `null` clears a field and falls back to the deployment default.
|
|
25
243
|
*/
|
|
26
244
|
interface ConfigUpdate {
|
|
245
|
+
/** Which LLM vendor `ask()` and the chat API call. */
|
|
27
246
|
llm_provider?: LlmProvider | null;
|
|
28
247
|
/** The credential for whichever `llm_provider` is set — the field name is shared. */
|
|
29
248
|
openai_api_key?: string | null;
|
|
@@ -31,111 +250,119 @@ interface ConfigUpdate {
|
|
|
31
250
|
openai_base_url?: string | null;
|
|
32
251
|
/** Overrides the provider's default model. */
|
|
33
252
|
chat_model?: string | null;
|
|
253
|
+
/** Where this key's browsers run unless `start()` names a provider. */
|
|
34
254
|
browser_provider?: Provider | null;
|
|
255
|
+
/** Anchor's API key, for the 'anchor' provider. */
|
|
35
256
|
anchor_api_key?: string | null;
|
|
257
|
+
/** Browserbase's API key, for the 'browserbase' provider. */
|
|
36
258
|
browserbase_api_key?: string | null;
|
|
259
|
+
/** The Browserbase project browsers are created in. */
|
|
37
260
|
browserbase_project_id?: string | null;
|
|
261
|
+
/** Steel's API key, for the 'steel' provider. */
|
|
38
262
|
steel_api_key?: string | null;
|
|
263
|
+
/** Browser Use Cloud's API key, for the 'browseruse' provider. */
|
|
39
264
|
browseruse_api_key?: string | null;
|
|
265
|
+
/** The DevTools WebSocket URL of your own Chrome, for the 'cdp' provider. */
|
|
40
266
|
cdp_ws_url?: string | null;
|
|
267
|
+
/** Which CAPTCHA solving service to call. */
|
|
41
268
|
captcha_solver?: CaptchaSolver | null;
|
|
269
|
+
/** The solving service's API key. */
|
|
42
270
|
captcha_api_key?: string | null;
|
|
271
|
+
/** Set once onboarding has been completed, so the console stops offering it. */
|
|
43
272
|
onboarded?: string | null;
|
|
44
273
|
}
|
|
45
274
|
/** What `config.get()` returns. Secrets read back masked, never in full. */
|
|
46
275
|
interface Config extends Omit<ConfigUpdate, 'llm_provider' | 'browser_provider' | 'captcha_solver'> {
|
|
276
|
+
/** The configured LLM vendor, or empty for the deployment default. */
|
|
47
277
|
llm_provider?: LlmProvider | '';
|
|
278
|
+
/** The configured browser provider, or empty for the deployment default. */
|
|
48
279
|
browser_provider?: Provider | '';
|
|
280
|
+
/** The configured CAPTCHA solver; empty when solving is off. */
|
|
49
281
|
captcha_solver?: CaptchaSolver;
|
|
50
282
|
/** What this key would actually use right now, deployment defaults included. */
|
|
51
283
|
effective: {
|
|
284
|
+
/** The LLM endpoint in use. */
|
|
52
285
|
baseUrl: string;
|
|
286
|
+
/** The model in use. */
|
|
53
287
|
model: string;
|
|
288
|
+
/** Whether any LLM credential is available. */
|
|
54
289
|
hasLlmKey: boolean;
|
|
55
290
|
};
|
|
56
291
|
/** True when the LLM key in play belongs to the deployment, not this key. */
|
|
57
292
|
inherited: boolean;
|
|
293
|
+
/** Whether this key has its own LLM credential stored. */
|
|
58
294
|
has_openai_key: boolean;
|
|
295
|
+
/** Every browser provider, what it needs configured, and whether it is. */
|
|
59
296
|
providers: Array<{
|
|
297
|
+
/** The provider. */
|
|
60
298
|
id: Provider;
|
|
299
|
+
/** Its display name. */
|
|
61
300
|
label: string;
|
|
301
|
+
/** The config fields it requires. */
|
|
62
302
|
needs: string[];
|
|
303
|
+
/** Whether those fields are set. */
|
|
63
304
|
configured: boolean;
|
|
64
305
|
}>;
|
|
65
306
|
}
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
redactRecording?: boolean;
|
|
80
|
-
};
|
|
81
|
-
priority?: 'low' | 'normal' | 'high';
|
|
82
|
-
/** Saved login profile. Defaults to the desktop's default profile. */
|
|
83
|
-
profile?: string;
|
|
84
|
-
/**
|
|
85
|
-
* Which identity to run as. A persona is one device: fingerprint, cookie jar
|
|
86
|
-
* and proxy bound together and stable for its life.
|
|
87
|
-
* 'default' — this key's own persona (the default)
|
|
88
|
-
* 'auto' — the least recently used persona under its concurrency cap
|
|
89
|
-
* <id> — a specific persona
|
|
90
|
-
*/
|
|
91
|
-
persona?: 'default' | 'auto' | (string & {});
|
|
92
|
-
/** Solve CAPTCHAs as they appear rather than waiting to be asked. */
|
|
93
|
-
captcha?: 'auto' | 'off';
|
|
94
|
-
/** Override the key's configured provider for this browser only. */
|
|
95
|
-
provider?: Provider;
|
|
96
|
-
/** Required only for the 'cdp' provider. */
|
|
97
|
-
wsUrl?: string;
|
|
98
|
-
name?: string;
|
|
99
|
-
/** How long to wait for a cloud browser to dial in. Default 120s. */
|
|
100
|
-
readyTimeoutMs?: number;
|
|
101
|
-
}
|
|
102
|
-
interface StartResult {
|
|
103
|
-
id: string;
|
|
104
|
-
provider: string;
|
|
105
|
-
persona: string;
|
|
106
|
-
status: 'ready' | 'starting';
|
|
107
|
-
/** Point Playwright, Puppeteer or browser-use at this. */
|
|
108
|
-
cdpUrl?: string;
|
|
109
|
-
note?: string;
|
|
307
|
+
|
|
308
|
+
/**
|
|
309
|
+
* OyaError: the one error type the SDK throws for a failed call, carrying the
|
|
310
|
+
* HTTP status and the server's answer so a caller can branch on either.
|
|
311
|
+
*/
|
|
312
|
+
/** A failed API call or browser command. */
|
|
313
|
+
declare class OyaError extends Error {
|
|
314
|
+
/** The HTTP status, or the SDK's own status for errors it raises itself. */
|
|
315
|
+
readonly status: number;
|
|
316
|
+
/** The server's response body, parsed when it was JSON. */
|
|
317
|
+
readonly body: unknown;
|
|
318
|
+
/** Records the message, status and body. */
|
|
319
|
+
constructor(message: string, status: number, body: unknown);
|
|
110
320
|
}
|
|
321
|
+
|
|
322
|
+
/**
|
|
323
|
+
* Types for agent work: task values and files, playbooks and their replays,
|
|
324
|
+
* and background runs with their attention requests.
|
|
325
|
+
*/
|
|
326
|
+
|
|
327
|
+
/** A saved flow, replayable without an LLM. */
|
|
111
328
|
interface Playbook {
|
|
329
|
+
/** The name it is played by. */
|
|
112
330
|
name: string;
|
|
113
331
|
/** Inputs `play()` accepts; any left out reuse the recorded value. */
|
|
114
332
|
variables: string[];
|
|
115
333
|
/** What each variable was recorded with. A secret has none — it never left the page. */
|
|
116
334
|
defaults: Record<string, string>;
|
|
335
|
+
/** How many steps it replays. */
|
|
117
336
|
steps: number;
|
|
118
337
|
/** The same flow as a Playwright module: `export default async function run(page, vars)`. */
|
|
119
338
|
code: string;
|
|
120
339
|
}
|
|
340
|
+
/** What a `play()` did. */
|
|
121
341
|
interface PlayResult {
|
|
122
342
|
/** Steps replayed before finishing or handing over to the agent. */
|
|
123
343
|
steps: number;
|
|
344
|
+
/** Steps in the playbook. */
|
|
124
345
|
total: number;
|
|
125
346
|
/** A step no longer fit the page and the agent finished the task. */
|
|
126
347
|
fellBack: boolean;
|
|
127
348
|
/** The agent's fix was saved as `draft`; promote it with `oya.playbooks.promote(name)`. */
|
|
128
349
|
healed?: boolean;
|
|
350
|
+
/** The draft's name, when one was saved. */
|
|
129
351
|
draft?: string;
|
|
130
352
|
/** The agent's summary, when it fell back. */
|
|
131
353
|
text?: string;
|
|
132
354
|
}
|
|
355
|
+
/** A playbook in the listing, with its history and any pending fix. */
|
|
133
356
|
interface PlaybookSummary extends Playbook {
|
|
357
|
+
/** When it was saved. */
|
|
134
358
|
createdAt: string | null;
|
|
359
|
+
/** When a draft last replaced it. */
|
|
135
360
|
promotedAt: string | null;
|
|
136
361
|
/** A healed replay's fix, waiting for `promote()` or `remove('<name>:draft')`. */
|
|
137
362
|
draft: (Playbook & {
|
|
363
|
+
/** When the replay was healed. */
|
|
138
364
|
healedAt: string;
|
|
365
|
+
/** The step the replay broke at. */
|
|
139
366
|
healedFrom: number;
|
|
140
367
|
}) | null;
|
|
141
368
|
}
|
|
@@ -161,29 +388,46 @@ interface FileValue {
|
|
|
161
388
|
* upload tool rather than typing it.
|
|
162
389
|
*/
|
|
163
390
|
type RunData = Record<string, string | number | FileValue>;
|
|
391
|
+
/** A run is waiting on a person. */
|
|
164
392
|
interface AttentionRequest {
|
|
393
|
+
/** Identifies this request; a new one means a new problem. */
|
|
165
394
|
id: string;
|
|
166
395
|
/** captcha / login / mfa: finish it in the live view. agent: the agent's question. heal_failed: replay and the agent both gave up. */
|
|
167
396
|
reason: 'captcha' | 'login' | 'mfa' | 'agent' | 'heal_failed';
|
|
397
|
+
/** What is needed, in words. */
|
|
168
398
|
message: string;
|
|
399
|
+
/** Where to finish it by hand. */
|
|
169
400
|
liveViewUrl?: string;
|
|
401
|
+
/** When it was raised, in epoch milliseconds. */
|
|
170
402
|
at: number;
|
|
171
403
|
}
|
|
404
|
+
/** What a finished run produced: a replay's result, an agent's answer, or both. */
|
|
172
405
|
type RunResult = Partial<PlayResult> & {
|
|
406
|
+
/** The agent's answer. */
|
|
173
407
|
text?: string;
|
|
174
408
|
};
|
|
409
|
+
/** A background run's state. */
|
|
175
410
|
interface RunInfo {
|
|
411
|
+
/** The run's id. */
|
|
176
412
|
id: string;
|
|
413
|
+
/** The browser it runs on. */
|
|
177
414
|
browserId: string;
|
|
415
|
+
/** Where it is. */
|
|
178
416
|
status: 'running' | 'needs_attention' | 'succeeded' | 'failed';
|
|
417
|
+
/** When it started, in epoch milliseconds. */
|
|
179
418
|
createdAt: number;
|
|
419
|
+
/** When it ended. */
|
|
180
420
|
endedAt?: number;
|
|
421
|
+
/** The open request for a person, if any. */
|
|
181
422
|
attention: AttentionRequest | null;
|
|
423
|
+
/** What it produced, once it succeeded. */
|
|
182
424
|
result?: RunResult;
|
|
425
|
+
/** Why it failed. */
|
|
183
426
|
error?: string;
|
|
184
427
|
/** HTTP-style status of a failure: 429 when a quota stopped the run. */
|
|
185
428
|
errorStatus?: number;
|
|
186
429
|
}
|
|
430
|
+
/** The inputs and callbacks for `browser.submit()`. */
|
|
187
431
|
interface SubmitOptions {
|
|
188
432
|
/** Task values the agent can read; for a playbook, its variables (secret ones included). */
|
|
189
433
|
data?: RunData;
|
|
@@ -191,7 +435,9 @@ interface SubmitOptions {
|
|
|
191
435
|
secrets?: RunData;
|
|
192
436
|
/** Playbooks only: let the agent finish a broken replay and save its fix as a draft. Default true. */
|
|
193
437
|
autoHeal?: boolean;
|
|
438
|
+
/** Fires once with the result when the run succeeds. */
|
|
194
439
|
onSuccess?: (result: RunResult) => unknown;
|
|
440
|
+
/** Fires once when the run fails, or when it can no longer be polled. */
|
|
195
441
|
onFailure?: (error: OyaError) => unknown;
|
|
196
442
|
/** Call `respond()` once it is handled: `'done'` after finishing by hand, or your answer to the agent. */
|
|
197
443
|
onHumanAttention?: (request: AttentionRequest & {
|
|
@@ -202,165 +448,151 @@ interface SubmitOptions {
|
|
|
202
448
|
/** How often to check on the run. Default 2000. */
|
|
203
449
|
pollMs?: number;
|
|
204
450
|
}
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
value?: string;
|
|
212
|
-
checked?: boolean;
|
|
213
|
-
disabled?: boolean;
|
|
214
|
-
visible: boolean;
|
|
215
|
-
tag?: string;
|
|
216
|
-
/** The element's DOM `id`. Usually the most stable handle a site offers. */
|
|
217
|
-
domId?: string;
|
|
218
|
-
ariaLabel?: string;
|
|
219
|
-
/** `data-testid`, when the site ships one. */
|
|
220
|
-
testId?: string;
|
|
221
|
-
name?: string;
|
|
222
|
-
placeholder?: string;
|
|
223
|
-
/** Action of the enclosing form. */
|
|
224
|
-
formName?: string;
|
|
225
|
-
}
|
|
226
|
-
interface Analysis {
|
|
227
|
-
/** The page as markdown. */
|
|
228
|
-
markdown: string;
|
|
229
|
-
elements: Element[];
|
|
230
|
-
viewport?: {
|
|
231
|
-
width: number;
|
|
232
|
-
height: number;
|
|
233
|
-
};
|
|
234
|
-
scroll?: {
|
|
235
|
-
x: number;
|
|
236
|
-
y: number;
|
|
237
|
-
};
|
|
238
|
-
truncated?: boolean;
|
|
239
|
-
}
|
|
240
|
-
interface CaptchaResult {
|
|
241
|
-
present: boolean;
|
|
242
|
-
solved: boolean;
|
|
243
|
-
/** 'provider' when the vendor solved it, 'solver' when we did, 'none' otherwise. */
|
|
244
|
-
method: 'provider' | 'solver' | 'none';
|
|
245
|
-
type?: string;
|
|
246
|
-
/** Invisible reCAPTCHA v3 scores the visit passively; there is nothing on screen to clear. */
|
|
247
|
-
invisible?: boolean;
|
|
248
|
-
sitekey?: string | null;
|
|
249
|
-
error?: string;
|
|
250
|
-
}
|
|
251
|
-
interface MfaResult {
|
|
252
|
-
present: boolean;
|
|
253
|
-
completed: boolean;
|
|
254
|
-
method?: 'totp' | 'email' | 'sms' | 'handoff' | 'none';
|
|
255
|
-
filled?: boolean;
|
|
256
|
-
submitted?: boolean;
|
|
257
|
-
/** Open this to finish by hand when nothing automated can. */
|
|
258
|
-
liveViewUrl?: string | null;
|
|
259
|
-
error?: string;
|
|
260
|
-
}
|
|
451
|
+
|
|
452
|
+
/**
|
|
453
|
+
* Types for identities: a persona's device and fingerprint, the proxies it
|
|
454
|
+
* exits through, and the second factors and site logins stored for it.
|
|
455
|
+
*/
|
|
456
|
+
/** The device a persona presents. Fixed for its life. */
|
|
261
457
|
interface Fingerprint {
|
|
458
|
+
/** `navigator.platform`. */
|
|
262
459
|
platform: string;
|
|
460
|
+
/** IANA timezone. */
|
|
263
461
|
timezone: string;
|
|
462
|
+
/** BCP 47 locale. */
|
|
264
463
|
locale: string;
|
|
464
|
+
/** Screen size, as `WIDTHxHEIGHT`. */
|
|
265
465
|
screen: string;
|
|
466
|
+
/** The GPU the WebGL renderer reports. */
|
|
266
467
|
webgl: string;
|
|
468
|
+
/** Logical CPU cores reported. */
|
|
267
469
|
hardwareConcurrency: number;
|
|
470
|
+
/** Device memory reported, in GB. */
|
|
268
471
|
deviceMemory: number;
|
|
472
|
+
/** Seed for the persona's stable canvas noise. */
|
|
269
473
|
canvasSeed: number;
|
|
270
474
|
}
|
|
271
475
|
/** Device choices made at creation. Fixed for the persona's life. */
|
|
272
476
|
interface PersonaPrefs {
|
|
477
|
+
/** Which operating system to present. */
|
|
273
478
|
platform?: 'Win32' | 'MacIntel' | 'Linux x86_64';
|
|
479
|
+
/** IANA timezone; must be one the platform can coherently claim. */
|
|
274
480
|
timezone?: string;
|
|
481
|
+
/** BCP 47 locale; must be one the platform can coherently claim. */
|
|
275
482
|
locale?: string;
|
|
276
483
|
}
|
|
277
484
|
/** A proxy exit. Credentials go in on create and never come back out. */
|
|
278
485
|
interface ProxyInfo {
|
|
486
|
+
/** The proxy's id. */
|
|
279
487
|
id: string;
|
|
488
|
+
/** Its display name. */
|
|
280
489
|
label: string;
|
|
490
|
+
/** Residential IPs look like homes; datacenter ones are cheaper and easier to flag. */
|
|
281
491
|
kind: 'residential' | 'datacenter';
|
|
282
492
|
/** Two-letter country, optionally a region: "US", "US-CA". */
|
|
283
493
|
geo: string | null;
|
|
284
494
|
/** Provided by the host rather than this key. Cannot be removed. */
|
|
285
495
|
shared: boolean;
|
|
496
|
+
/** Whether its last check passed. */
|
|
286
497
|
healthy: boolean;
|
|
287
498
|
/** Healthy and not cooling down after a failure. */
|
|
288
499
|
available: boolean;
|
|
289
500
|
/** Where traffic actually leaves, as of the last check. */
|
|
290
501
|
exitIp: string | null;
|
|
502
|
+
/** When it was last checked. */
|
|
291
503
|
lastCheckedAt: string | null;
|
|
292
504
|
/** Personas on it now, out of `maxPersonas`. */
|
|
293
505
|
assigned: number;
|
|
506
|
+
/** How many personas may share it. */
|
|
294
507
|
maxPersonas: number;
|
|
508
|
+
/** How long until a failed proxy is tried again. */
|
|
295
509
|
cooldownMsRemaining: number;
|
|
296
510
|
}
|
|
511
|
+
/** A proxy to add. */
|
|
297
512
|
interface ProxyCreate {
|
|
298
513
|
/** http(s)://user:pass@host:port from your vendor. Chromium cannot use SOCKS5 with a password. */
|
|
299
514
|
url: string;
|
|
515
|
+
/** A display name. */
|
|
300
516
|
label?: string;
|
|
517
|
+
/** Two-letter country, optionally a region, used to match personas' geo hints. */
|
|
301
518
|
geo?: string;
|
|
519
|
+
/** Residential or datacenter. */
|
|
302
520
|
kind?: 'residential' | 'datacenter';
|
|
303
521
|
/** Personas that may share it. Keep 1 for a sticky-session URL so each keeps its own IP. */
|
|
304
522
|
maxPersonas?: number;
|
|
305
523
|
}
|
|
524
|
+
/** A persona: one device, its cookie jar and its proxy. */
|
|
306
525
|
interface PersonaInfo {
|
|
526
|
+
/** The persona's id. */
|
|
307
527
|
id: string;
|
|
528
|
+
/** Its display name. */
|
|
308
529
|
name: string;
|
|
530
|
+
/** Whether it is this key's own default persona. */
|
|
309
531
|
isDefault: boolean;
|
|
532
|
+
/** Browsers running as it now. */
|
|
310
533
|
activeBrowsers: number;
|
|
534
|
+
/** How many may run as it at once; null for no cap. */
|
|
311
535
|
maxConcurrent: number | null;
|
|
536
|
+
/** Where its proxy should be, before one is assigned. */
|
|
312
537
|
proxy: {
|
|
538
|
+
/** Two-letter country, optionally a region. */
|
|
313
539
|
geo: string | null;
|
|
314
540
|
} | null;
|
|
315
541
|
/** The proxy it is actually on, once assigned or pinned. */
|
|
316
542
|
exit: {
|
|
543
|
+
/** The proxy's id. */
|
|
317
544
|
id: string;
|
|
545
|
+
/** Its display name. */
|
|
318
546
|
label: string;
|
|
547
|
+
/** Its country and region. */
|
|
319
548
|
geo: string | null;
|
|
549
|
+
/** Whether its last check passed. */
|
|
320
550
|
healthy: boolean;
|
|
321
551
|
} | null;
|
|
552
|
+
/** The device choices it was created with. */
|
|
322
553
|
prefs: PersonaPrefs | null;
|
|
554
|
+
/** The device it presents. */
|
|
323
555
|
fingerprint: Fingerprint;
|
|
556
|
+
/** Its persona-wide second factor. */
|
|
324
557
|
mfa: {
|
|
558
|
+
/** Whether a factor is stored. */
|
|
325
559
|
configured: boolean;
|
|
560
|
+
/** Which kind of factor. */
|
|
326
561
|
type?: string;
|
|
562
|
+
/** The site it is filed against, if any. */
|
|
327
563
|
domain?: string;
|
|
328
564
|
};
|
|
329
565
|
/** Per-site factors and stored logins. Usernames and types only, never secrets. */
|
|
330
566
|
sites: {
|
|
567
|
+
/** Second factors filed against one site. */
|
|
331
568
|
mfa: {
|
|
569
|
+
/** The site. */
|
|
332
570
|
domain: string;
|
|
571
|
+
/** Which kind of factor. */
|
|
333
572
|
type: string;
|
|
334
573
|
}[];
|
|
574
|
+
/** Stored site logins. */
|
|
335
575
|
credentials: {
|
|
576
|
+
/** The site. */
|
|
336
577
|
domain: string;
|
|
578
|
+
/** The account name. */
|
|
337
579
|
username: string;
|
|
338
580
|
}[];
|
|
339
581
|
};
|
|
582
|
+
/** What its cookie jar holds. */
|
|
340
583
|
login: {
|
|
584
|
+
/** Cookies in the jar. */
|
|
341
585
|
cookies: number;
|
|
586
|
+
/** Sites it holds a session for. */
|
|
342
587
|
sites: string[];
|
|
588
|
+
/** When the jar last changed. */
|
|
343
589
|
updatedAt: string | null;
|
|
344
590
|
};
|
|
591
|
+
/** When it was created. */
|
|
345
592
|
createdAt: string;
|
|
593
|
+
/** When a browser last ran as it. */
|
|
346
594
|
lastUsedAt: string | null;
|
|
347
595
|
}
|
|
348
|
-
type Health = 'ok' | 'stale' | 'errors' | 'dead';
|
|
349
|
-
interface Activity {
|
|
350
|
-
ts: string;
|
|
351
|
-
action: string;
|
|
352
|
-
summary: string;
|
|
353
|
-
ok: boolean;
|
|
354
|
-
ms: number;
|
|
355
|
-
error?: string;
|
|
356
|
-
}
|
|
357
|
-
interface StopResult {
|
|
358
|
-
id: string;
|
|
359
|
-
ok: boolean;
|
|
360
|
-
provider?: string | null;
|
|
361
|
-
sandboxRemoved?: boolean | null;
|
|
362
|
-
error?: string;
|
|
363
|
-
}
|
|
364
596
|
/**
|
|
365
597
|
* A second factor. `domain` files it against one site, because a persona driving
|
|
366
598
|
* several portals meets several kinds of factor; without it the record is the
|
|
@@ -375,122 +607,452 @@ interface StopResult {
|
|
|
375
607
|
* `pattern` is only the fallback for when no LLM key is set or the call fails.
|
|
376
608
|
*/
|
|
377
609
|
type MfaConfig = {
|
|
610
|
+
/** The site this factor answers for; without it, the persona-wide default. */
|
|
378
611
|
domain?: string;
|
|
379
612
|
} & ({
|
|
613
|
+
/** An authenticator app's time-based codes. */
|
|
380
614
|
type: 'totp';
|
|
615
|
+
/** The base32 seed. */
|
|
381
616
|
secret: string;
|
|
382
617
|
} | {
|
|
618
|
+
/** Codes delivered to an endpoint you host. */
|
|
383
619
|
type: 'email' | 'sms';
|
|
620
|
+
/** The endpoint polled for the latest message. */
|
|
384
621
|
url: string;
|
|
622
|
+
/** Headers sent with each poll. */
|
|
385
623
|
headers?: Record<string, string>;
|
|
624
|
+
/** Fallback regex for the code, used when no LLM is available. */
|
|
386
625
|
pattern?: string;
|
|
626
|
+
/** How long to wait for a code. */
|
|
387
627
|
timeoutMs?: number;
|
|
388
628
|
} | {
|
|
629
|
+
/** Codes read from a Gmail or Microsoft 365 mailbox. */
|
|
389
630
|
type: 'gmail' | 'graph';
|
|
631
|
+
/** The mailbox's OAuth refresh token. */
|
|
390
632
|
refreshToken: string;
|
|
633
|
+
/** The OAuth client the token was issued to. */
|
|
391
634
|
clientId: string;
|
|
635
|
+
/** That client's secret, when it has one. */
|
|
392
636
|
clientSecret?: string;
|
|
637
|
+
/** The Microsoft tenant, for `graph`. */
|
|
393
638
|
tenant?: string;
|
|
639
|
+
/** A mailbox search narrowing which messages are read. */
|
|
394
640
|
query?: string;
|
|
641
|
+
/** Fallback regex for the code, used when no LLM is available. */
|
|
395
642
|
pattern?: string;
|
|
643
|
+
/** How long to wait for a code. */
|
|
396
644
|
timeoutMs?: number;
|
|
397
645
|
});
|
|
398
646
|
/** A site login. The password is write-only: no API ever reads it back. */
|
|
399
647
|
interface SiteCredentials {
|
|
648
|
+
/** The site it signs in to. */
|
|
400
649
|
domain: string;
|
|
650
|
+
/** The account name. */
|
|
401
651
|
username: string;
|
|
652
|
+
/** The password; stored sealed and never returned. */
|
|
402
653
|
password: string;
|
|
403
654
|
}
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
personaName: string | null;
|
|
411
|
-
health: Health;
|
|
412
|
-
connectedAt: string;
|
|
413
|
-
lastSeen: string;
|
|
414
|
-
currentUrl: string;
|
|
415
|
-
commands: number;
|
|
416
|
-
errors: number;
|
|
417
|
-
pending: number;
|
|
418
|
-
lastCommandAt: string | null;
|
|
419
|
-
lastError: string | null;
|
|
420
|
-
}
|
|
421
|
-
interface BrowserDetail extends BrowserInfo {
|
|
422
|
-
activity: Activity[];
|
|
423
|
-
}
|
|
424
|
-
interface OyaOptions {
|
|
425
|
-
/** Defaults to OYA_API_KEY. */
|
|
426
|
-
apiKey?: string;
|
|
427
|
-
/** Defaults to OYA_BASE_URL, then https://browser.getoya.ai. */
|
|
428
|
-
baseUrl?: string;
|
|
429
|
-
/** Per-request timeout. Navigation gets its own, longer budget. */
|
|
430
|
-
timeoutMs?: number;
|
|
431
|
-
fetch?: typeof globalThis.fetch;
|
|
432
|
-
}
|
|
433
|
-
declare class OyaError extends Error {
|
|
434
|
-
readonly status: number;
|
|
435
|
-
readonly body: unknown;
|
|
436
|
-
constructor(message: string, status: number, body: unknown);
|
|
437
|
-
}
|
|
655
|
+
|
|
656
|
+
/**
|
|
657
|
+
* Types for the durable control plane: sessions and their lifecycle, human
|
|
658
|
+
* takeover, project settings, lifecycle events and service credentials.
|
|
659
|
+
*/
|
|
660
|
+
/** What a member or credential may do: read, operate browsers, or also administer the project. */
|
|
438
661
|
type ControlRole = 'viewer' | 'operator' | 'administrator';
|
|
439
662
|
/** What a human holding the control lease may send. Mirrors the server's allowlist. */
|
|
440
663
|
type HumanInputAction = 'click' | 'type' | 'press_key' | 'scroll' | 'click_coordinates' | 'double_click' | 'drag' | 'mouse_move' | 'scroll_at' | 'type_text' | 'keyboard_type' | 'navigate' | 'back' | 'forward' | 'reload' | 'screenshot' | 'analyze' | 'read_page';
|
|
664
|
+
/** A browser session as the control plane records it, including ones no longer connected. */
|
|
441
665
|
interface ControlSession {
|
|
666
|
+
/** The session's id, which is also the browser's. */
|
|
442
667
|
id: string;
|
|
668
|
+
/** The project it belongs to. */
|
|
443
669
|
project: string;
|
|
670
|
+
/** Which provider runs it. */
|
|
444
671
|
provider: string;
|
|
672
|
+
/** The persona it runs as. */
|
|
445
673
|
persona: string | null;
|
|
674
|
+
/** Where it is in its lifecycle. */
|
|
446
675
|
state: 'queued' | 'provisioning' | 'ready' | 'disconnected' | 'stopping' | 'cleanup_pending' | 'stopped' | 'failed' | 'unknown_outcome';
|
|
676
|
+
/** Whether the control plane provisioned it (and so must clean it up). */
|
|
447
677
|
managed: boolean;
|
|
678
|
+
/** When it was created, in epoch milliseconds. */
|
|
448
679
|
createdAt: number;
|
|
680
|
+
/** When its state last changed. */
|
|
449
681
|
updatedAt: number;
|
|
682
|
+
/** Estimated spend so far, in US dollars. */
|
|
450
683
|
costUsd: number;
|
|
684
|
+
/** Who is driving it. */
|
|
451
685
|
control: {
|
|
686
|
+
/** The agent, a person, or nobody while paused. */
|
|
452
687
|
mode: 'agent' | 'human' | 'paused';
|
|
688
|
+
/** When a human lease runs out. */
|
|
453
689
|
expiresAt?: number;
|
|
454
690
|
};
|
|
691
|
+
/** Why cleanup has not finished. */
|
|
455
692
|
cleanupError?: string;
|
|
456
693
|
}
|
|
694
|
+
/** A project's limits, retention and rate cards. */
|
|
457
695
|
interface ProjectSettings {
|
|
696
|
+
/** Days recordings are kept. */
|
|
458
697
|
recordingDays: number;
|
|
698
|
+
/** Days audit events are kept. */
|
|
459
699
|
auditDays: number;
|
|
700
|
+
/** Spend ceiling in US dollars; null for none. */
|
|
460
701
|
budgetUsd: number | null;
|
|
702
|
+
/** Browsers that may run at once; null for no cap. */
|
|
461
703
|
maxConcurrent: number | null;
|
|
704
|
+
/** Price per unit, by what is metered. */
|
|
462
705
|
rates: Record<string, number>;
|
|
706
|
+
/** The default policy for governed browsers. */
|
|
463
707
|
policy: Record<string, unknown>;
|
|
464
708
|
}
|
|
709
|
+
/** One durable lifecycle event. */
|
|
465
710
|
interface ControlEvent {
|
|
711
|
+
/** Increasing id, used as the read cursor. */
|
|
466
712
|
id: number;
|
|
713
|
+
/** The project it belongs to. */
|
|
467
714
|
project: string;
|
|
715
|
+
/** What happened. */
|
|
468
716
|
type: string;
|
|
717
|
+
/** The session it concerns, if any. */
|
|
469
718
|
sessionId: string | null;
|
|
719
|
+
/** When, in epoch milliseconds. */
|
|
470
720
|
at: number;
|
|
721
|
+
/** Event-specific fields. */
|
|
471
722
|
detail: Record<string, unknown>;
|
|
472
723
|
}
|
|
724
|
+
/** A service credential. Its token is shown once, at creation. */
|
|
473
725
|
interface ControlCredential {
|
|
726
|
+
/** The credential's id, for revoking it. */
|
|
474
727
|
id: string;
|
|
728
|
+
/** What it is for. */
|
|
475
729
|
label: string;
|
|
730
|
+
/** What it may do. */
|
|
476
731
|
role: ControlRole;
|
|
732
|
+
/** When it stops working; null for never. */
|
|
477
733
|
expiresAt: number | null;
|
|
734
|
+
/** When it was revoked, if it was. */
|
|
478
735
|
revokedAt: number | null;
|
|
479
736
|
}
|
|
737
|
+
/** The project at a glance: settings, sessions, recent events. */
|
|
480
738
|
interface ControlOverview {
|
|
481
739
|
/** costUsd: estimated lifetime spend, metered from rate cards. */
|
|
482
740
|
project: {
|
|
741
|
+
/** The project's id. */
|
|
483
742
|
id: string;
|
|
743
|
+
/** Its name. */
|
|
484
744
|
name: string;
|
|
745
|
+
/** Its limits and retention. */
|
|
485
746
|
settings: ProjectSettings;
|
|
747
|
+
/** Estimated lifetime spend, in US dollars. */
|
|
486
748
|
costUsd?: number;
|
|
487
749
|
};
|
|
750
|
+
/** Every session the control plane knows about. */
|
|
488
751
|
sessions: ControlSession[];
|
|
752
|
+
/** Recent lifecycle events. */
|
|
489
753
|
events: ControlEvent[];
|
|
754
|
+
/** True while the server is draining for a restart. */
|
|
490
755
|
draining: boolean;
|
|
756
|
+
/** Service credentials, for administrators. */
|
|
491
757
|
credentials?: ControlCredential[];
|
|
492
758
|
}
|
|
493
759
|
|
|
760
|
+
/**
|
|
761
|
+
* The options the `Oya` client is constructed with.
|
|
762
|
+
*/
|
|
763
|
+
/** How to reach the control plane, and as whom. */
|
|
764
|
+
interface OyaOptions {
|
|
765
|
+
/** Defaults to OYA_API_KEY. */
|
|
766
|
+
apiKey?: string;
|
|
767
|
+
/** Defaults to OYA_BASE_URL, then https://browser.getoya.ai. */
|
|
768
|
+
baseUrl?: string;
|
|
769
|
+
/** Per-request timeout. Navigation gets its own, longer budget. */
|
|
770
|
+
timeoutMs?: number;
|
|
771
|
+
/** A fetch to use instead of the global one, for tests, proxies or old runtimes. */
|
|
772
|
+
fetch?: typeof globalThis.fetch;
|
|
773
|
+
}
|
|
774
|
+
|
|
775
|
+
/** The one HTTP path. Everything else in this package is a wrapper over it. */
|
|
776
|
+
declare class Http {
|
|
777
|
+
readonly baseUrl: string;
|
|
778
|
+
readonly apiKey: string;
|
|
779
|
+
private readonly timeoutMs;
|
|
780
|
+
private readonly fetchImpl;
|
|
781
|
+
/** Stores where to call, with which key, how long to wait and which fetch to use. */
|
|
782
|
+
constructor(baseUrl: string, apiKey: string, timeoutMs: number, fetchImpl: typeof globalThis.fetch);
|
|
783
|
+
/** Sends one request and returns the parsed answer, or throws an OyaError when it failed. */
|
|
784
|
+
request<T>(method: string, path: string, body?: unknown, timeoutMs?: number, headers?: Record<string, string>): Promise<T>;
|
|
785
|
+
}
|
|
786
|
+
|
|
787
|
+
/**
|
|
788
|
+
* The shapes the client's namespaces (`oya.browser`, `oya.control`,
|
|
789
|
+
* `oya.personas` …) take and return that are not part of the exported types,
|
|
790
|
+
* named so each field can say what it is.
|
|
791
|
+
*/
|
|
792
|
+
|
|
793
|
+
/** What stopping several browsers did. */
|
|
794
|
+
interface StopManyResult {
|
|
795
|
+
/** How many stopped. */
|
|
796
|
+
stopped: number;
|
|
797
|
+
/** Each browser's outcome. */
|
|
798
|
+
results: StopResult[];
|
|
799
|
+
}
|
|
800
|
+
/** A plain acknowledgement. */
|
|
801
|
+
interface Ack {
|
|
802
|
+
/** Whether it was done. */
|
|
803
|
+
ok: boolean;
|
|
804
|
+
}
|
|
805
|
+
/** A single-use live-stream ticket. */
|
|
806
|
+
interface Ticket {
|
|
807
|
+
/** The ticket. */
|
|
808
|
+
ticket: string;
|
|
809
|
+
/** Seconds until it expires. */
|
|
810
|
+
expiresIn: number;
|
|
811
|
+
}
|
|
812
|
+
/** A page of lifecycle events. */
|
|
813
|
+
interface EventPage {
|
|
814
|
+
/** Events after the cursor asked for. */
|
|
815
|
+
events: ControlEvent[];
|
|
816
|
+
/** Pass this as `after` to read on. */
|
|
817
|
+
cursor: number;
|
|
818
|
+
}
|
|
819
|
+
/** A service credential to mint. */
|
|
820
|
+
interface CredentialRequest {
|
|
821
|
+
/** What it may do. */
|
|
822
|
+
role: ControlRole;
|
|
823
|
+
/** What it is for. */
|
|
824
|
+
label?: string;
|
|
825
|
+
/** When it stops working, in epoch milliseconds. */
|
|
826
|
+
expiresAt?: number;
|
|
827
|
+
}
|
|
828
|
+
/** A new service credential, with its token: shown this once. */
|
|
829
|
+
interface NewCredential extends ControlCredential {
|
|
830
|
+
/** The secret to authenticate with. */
|
|
831
|
+
token: string;
|
|
832
|
+
}
|
|
833
|
+
/** One project member. */
|
|
834
|
+
interface Member {
|
|
835
|
+
/** The member's user id. */
|
|
836
|
+
userId: string;
|
|
837
|
+
/** What they may do. */
|
|
838
|
+
role: ControlRole;
|
|
839
|
+
}
|
|
840
|
+
/** The project's owner and members. */
|
|
841
|
+
interface MemberList {
|
|
842
|
+
/** The owner's user id. */
|
|
843
|
+
owner: string | null;
|
|
844
|
+
/** Everyone else. */
|
|
845
|
+
members: Member[];
|
|
846
|
+
}
|
|
847
|
+
/** An invitation code. */
|
|
848
|
+
interface Invite {
|
|
849
|
+
/** The code to hand to the invitee. */
|
|
850
|
+
code: string;
|
|
851
|
+
/** Seconds until it expires. */
|
|
852
|
+
expiresIn: number;
|
|
853
|
+
}
|
|
854
|
+
/** A registered webhook. */
|
|
855
|
+
interface Webhook {
|
|
856
|
+
/** Its id, for removing it. */
|
|
857
|
+
id: string;
|
|
858
|
+
/** The key its deliveries are signed with. */
|
|
859
|
+
secret: string;
|
|
860
|
+
}
|
|
861
|
+
/** One proxy's check. */
|
|
862
|
+
interface ProxyCheck {
|
|
863
|
+
/** The proxy. */
|
|
864
|
+
id: string;
|
|
865
|
+
/** Whether it answered. */
|
|
866
|
+
ok: boolean;
|
|
867
|
+
/** Where its traffic actually leaves. */
|
|
868
|
+
exitIp?: string | null;
|
|
869
|
+
/** Why it failed. */
|
|
870
|
+
error?: string;
|
|
871
|
+
}
|
|
872
|
+
/** Where a persona's proxy should be. */
|
|
873
|
+
interface GeoHint {
|
|
874
|
+
/** Two-letter country, optionally a region. */
|
|
875
|
+
geo?: string;
|
|
876
|
+
}
|
|
877
|
+
/** A persona to create. */
|
|
878
|
+
interface PersonaCreate {
|
|
879
|
+
/** Its display name. */
|
|
880
|
+
name?: string;
|
|
881
|
+
/** Device choices, fixed for its life. */
|
|
882
|
+
prefs?: PersonaPrefs;
|
|
883
|
+
/** Where its proxy should be. */
|
|
884
|
+
proxy?: GeoHint;
|
|
885
|
+
/** How many browsers may run as it at once; null for no cap. */
|
|
886
|
+
maxConcurrent?: number | null;
|
|
887
|
+
}
|
|
888
|
+
/** What may change on a persona. Never the device. */
|
|
889
|
+
interface PersonaUpdate {
|
|
890
|
+
/** Its display name. */
|
|
891
|
+
name?: string;
|
|
892
|
+
/** How many browsers may run as it at once; null for no cap. */
|
|
893
|
+
maxConcurrent?: number | null;
|
|
894
|
+
/** Where its proxy should be; null clears the hint. */
|
|
895
|
+
proxy?: GeoHint | null;
|
|
896
|
+
}
|
|
897
|
+
/** Options for a clone. */
|
|
898
|
+
interface CloneOptions {
|
|
899
|
+
/** The new persona's name. */
|
|
900
|
+
name?: string;
|
|
901
|
+
}
|
|
902
|
+
/** What a persona may claim, per platform. */
|
|
903
|
+
interface PersonaOptions {
|
|
904
|
+
/** The platforms on offer. */
|
|
905
|
+
platforms: string[];
|
|
906
|
+
/** Timezones each platform may coherently claim. */
|
|
907
|
+
timezones: Record<string, string[]>;
|
|
908
|
+
/** Locales each platform may coherently claim. */
|
|
909
|
+
locales: Record<string, string[]>;
|
|
910
|
+
}
|
|
911
|
+
/** The proxy a persona is pinned to. */
|
|
912
|
+
interface PinnedProxy {
|
|
913
|
+
/** The proxy's id. */
|
|
914
|
+
id: string;
|
|
915
|
+
/** Its display name. */
|
|
916
|
+
label: string;
|
|
917
|
+
}
|
|
918
|
+
/** The outcome of pinning a proxy. */
|
|
919
|
+
interface ProxyPin {
|
|
920
|
+
/** Whether it was saved. */
|
|
921
|
+
ok: boolean;
|
|
922
|
+
/** The proxy now pinned, or null when assignment is left to connect time. */
|
|
923
|
+
proxy: PinnedProxy | null;
|
|
924
|
+
}
|
|
925
|
+
/** A stored second factor, as confirmed. */
|
|
926
|
+
interface MfaSaved {
|
|
927
|
+
/** Whether it is stored. */
|
|
928
|
+
configured: boolean;
|
|
929
|
+
/** Which kind of factor. */
|
|
930
|
+
type: string;
|
|
931
|
+
}
|
|
932
|
+
/** A site login the persona can use. Never the password. */
|
|
933
|
+
interface SiteLogin {
|
|
934
|
+
/** The site. */
|
|
935
|
+
domain: string;
|
|
936
|
+
/** The account name. */
|
|
937
|
+
username: string;
|
|
938
|
+
}
|
|
939
|
+
/** A stored site login, as confirmed. */
|
|
940
|
+
interface CredentialsSaved extends SiteLogin {
|
|
941
|
+
/** Whether it is stored. */
|
|
942
|
+
configured: boolean;
|
|
943
|
+
}
|
|
944
|
+
/** The sites a persona can sign in to. */
|
|
945
|
+
interface SiteLogins {
|
|
946
|
+
/** Usernames only. */
|
|
947
|
+
credentials: SiteLogin[];
|
|
948
|
+
}
|
|
949
|
+
|
|
950
|
+
/**
|
|
951
|
+
* The shapes Browser's methods take and return that are not part of the
|
|
952
|
+
* exported types: tab listings, dialog answers, share links and the like.
|
|
953
|
+
* Named here so each field can say what it is.
|
|
954
|
+
*/
|
|
955
|
+
|
|
956
|
+
/** What `type()` reports back. */
|
|
957
|
+
interface TypeResult {
|
|
958
|
+
/** An autocomplete list opened under the field; pick from it before moving on. */
|
|
959
|
+
suggestions_visible?: boolean;
|
|
960
|
+
}
|
|
961
|
+
/** The dialog `handleDialog()` answered. */
|
|
962
|
+
interface DialogResult {
|
|
963
|
+
/** alert, confirm, prompt or beforeunload. */
|
|
964
|
+
type: string;
|
|
965
|
+
/** The dialog's text. */
|
|
966
|
+
message: string;
|
|
967
|
+
/** Whether it was accepted. */
|
|
968
|
+
accepted: boolean;
|
|
969
|
+
}
|
|
970
|
+
/** A point on the page, in CSS pixels. */
|
|
971
|
+
interface Point {
|
|
972
|
+
/** From the left edge. */
|
|
973
|
+
x: number;
|
|
974
|
+
/** From the top edge. */
|
|
975
|
+
y: number;
|
|
976
|
+
}
|
|
977
|
+
/** One open tab. */
|
|
978
|
+
interface Tab {
|
|
979
|
+
/** The tab's id, for `switchTab()` and `closeTab()`. */
|
|
980
|
+
id: string;
|
|
981
|
+
/** The page it shows. */
|
|
982
|
+
url: string;
|
|
983
|
+
/** The page's title. */
|
|
984
|
+
title: string;
|
|
985
|
+
/** Whether it is the tab commands act on. */
|
|
986
|
+
active: boolean;
|
|
987
|
+
}
|
|
988
|
+
/** Task values for `ask()`. */
|
|
989
|
+
interface AskValues {
|
|
990
|
+
/** Values the agent can read. */
|
|
991
|
+
data?: RunData;
|
|
992
|
+
/** Values the agent never sees. */
|
|
993
|
+
secrets?: RunData;
|
|
994
|
+
}
|
|
995
|
+
/** How `play()` handles a step that no longer fits. */
|
|
996
|
+
interface PlayOptions {
|
|
997
|
+
/** Let the agent finish the task and save its fix as a draft. Default true. */
|
|
998
|
+
autoHeal?: boolean;
|
|
999
|
+
}
|
|
1000
|
+
/** What `submit()` runs: a prompt for the agent, or a saved playbook. */
|
|
1001
|
+
type Task = {
|
|
1002
|
+
/** A natural-language task for the agent. */
|
|
1003
|
+
prompt: string;
|
|
1004
|
+
} | {
|
|
1005
|
+
/** The name of a saved playbook. */
|
|
1006
|
+
playbook: string;
|
|
1007
|
+
};
|
|
1008
|
+
/** How a `shareUrl()` link works. */
|
|
1009
|
+
interface ShareOptions {
|
|
1010
|
+
/** Let whoever opens it act in the browser. Default view-only. */
|
|
1011
|
+
control?: boolean;
|
|
1012
|
+
/** How long it lasts. Default one hour. */
|
|
1013
|
+
expiresInSeconds?: number;
|
|
1014
|
+
}
|
|
1015
|
+
/** A link from `shareUrl()`. */
|
|
1016
|
+
interface ShareLink {
|
|
1017
|
+
/** The link to hand out. */
|
|
1018
|
+
url: string;
|
|
1019
|
+
/** Its credential's id, for `revokeShare()`. */
|
|
1020
|
+
id: string;
|
|
1021
|
+
/** When it stops working, in epoch milliseconds; null for never. */
|
|
1022
|
+
expiresAt: number | null;
|
|
1023
|
+
}
|
|
1024
|
+
|
|
1025
|
+
/** The callbacks a run can fire. */
|
|
1026
|
+
type RunCallbacks = Pick<SubmitOptions, 'onSuccess' | 'onFailure' | 'onHumanAttention' | 'onHealed'>;
|
|
1027
|
+
|
|
1028
|
+
/**
|
|
1029
|
+
* Run: a task submitted with `browser.submit()`, running in the background.
|
|
1030
|
+
* The polling itself lives in run-watch.ts.
|
|
1031
|
+
*/
|
|
1032
|
+
|
|
1033
|
+
/** A submitted task. Callbacks fire as it changes; `done` settles when it ends. */
|
|
1034
|
+
declare class Run {
|
|
1035
|
+
private readonly http;
|
|
1036
|
+
readonly id: string;
|
|
1037
|
+
/** Settles with the result when the run succeeds, or rejects when it fails. */
|
|
1038
|
+
readonly done: Promise<RunResult>;
|
|
1039
|
+
/** Starts watching the run straight away. */
|
|
1040
|
+
constructor(http: Http, id: string, callbacks: RunCallbacks, pollMs?: number);
|
|
1041
|
+
/** The run's current state. */
|
|
1042
|
+
status(): Promise<RunInfo>;
|
|
1043
|
+
/** Answer the open attention request: `'done'` after handling it by hand, or your reply to the agent. */
|
|
1044
|
+
respond(response?: string): Promise<void>;
|
|
1045
|
+
/** Polls until the run ends, firing callbacks on the way. */
|
|
1046
|
+
private watch;
|
|
1047
|
+
}
|
|
1048
|
+
|
|
1049
|
+
/**
|
|
1050
|
+
* Browser: one running browser, driven through the API. Page actions go
|
|
1051
|
+
* through the command endpoint; CAPTCHA, MFA, agent runs, playbooks and live
|
|
1052
|
+
* view links have their own endpoints. The small rules the methods share
|
|
1053
|
+
* (element ids, aimed scrolls, agent errors) are the functions below the class.
|
|
1054
|
+
*/
|
|
1055
|
+
|
|
494
1056
|
/**
|
|
495
1057
|
* One running browser.
|
|
496
1058
|
*
|
|
@@ -501,54 +1063,56 @@ interface ControlOverview {
|
|
|
501
1063
|
declare class Browser {
|
|
502
1064
|
private readonly http;
|
|
503
1065
|
private readonly autoCaptcha;
|
|
1066
|
+
/** The browser's id. */
|
|
504
1067
|
readonly id: string;
|
|
1068
|
+
/** Which provider runs it. */
|
|
505
1069
|
readonly provider: string;
|
|
1070
|
+
/** Which persona it runs as. */
|
|
506
1071
|
readonly persona: string;
|
|
507
1072
|
/** Point Playwright, Puppeteer or browser-use here. */
|
|
508
1073
|
readonly cdpUrl?: string;
|
|
1074
|
+
/** Wraps a started browser; `autoCaptcha` solves CAPTCHAs after every `goto()`. */
|
|
509
1075
|
constructor(http: Http, info: StartResult, autoCaptcha: boolean);
|
|
1076
|
+
/** Runs one browser command; a command that ran and failed throws. */
|
|
510
1077
|
private command;
|
|
1078
|
+
/** Navigates, then clears any CAPTCHA when `captcha: 'auto'` was asked for. */
|
|
511
1079
|
goto(url: string): Promise<void>;
|
|
512
1080
|
/** The page as markdown plus numbered elements to act on. */
|
|
513
1081
|
analyze(): Promise<Analysis>;
|
|
514
1082
|
/** Only the visible elements, which is what an agent almost always wants. */
|
|
515
1083
|
elements(): Promise<Element[]>;
|
|
1084
|
+
/** Clicks an element by its id from `analyze()`. */
|
|
516
1085
|
click(elementId: number | string): Promise<void>;
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
1086
|
+
/** Types into an element by its id from `analyze()`. */
|
|
1087
|
+
type(elementId: number | string, text: string): Promise<TypeResult>;
|
|
1088
|
+
/** A valid element id, or an OyaError saying where ids come from. */
|
|
520
1089
|
private elementId;
|
|
1090
|
+
/** Presses one key, such as Enter or Escape. */
|
|
521
1091
|
pressKey(key: string): Promise<void>;
|
|
522
1092
|
/**
|
|
523
1093
|
* Answer a native dialog holding the page. alert() and beforeunload are
|
|
524
1094
|
* answered for you; a confirm() or prompt() waits for this, and every other
|
|
525
1095
|
* command fails fast with the dialog's text until it is answered.
|
|
526
1096
|
*/
|
|
527
|
-
handleDialog(accept: boolean, promptText?: string): Promise<
|
|
528
|
-
type: string;
|
|
529
|
-
message: string;
|
|
530
|
-
accepted: boolean;
|
|
531
|
-
}>;
|
|
1097
|
+
handleDialog(accept: boolean, promptText?: string): Promise<DialogResult>;
|
|
532
1098
|
/** `at` aims the wheel at an inner scroller (a results panel, a chat pane) instead of the page. */
|
|
533
|
-
scroll(direction: 'up' | 'down' | 'top' | 'bottom', amount?: number, at?:
|
|
534
|
-
|
|
535
|
-
y: number;
|
|
536
|
-
}): Promise<void>;
|
|
1099
|
+
scroll(direction: 'up' | 'down' | 'top' | 'bottom', amount?: number, at?: Point): Promise<void>;
|
|
1100
|
+
/** Waits until `selector` matches, up to `timeout` milliseconds. */
|
|
537
1101
|
waitFor(selector: string, timeout?: number): Promise<void>;
|
|
538
1102
|
/** A `data:image/…;base64,` URL. PNG or JPEG depending on the driver. */
|
|
539
1103
|
screenshot(): Promise<string>;
|
|
1104
|
+
/** The active tab's URL, or empty when there is none. */
|
|
540
1105
|
url(): Promise<string>;
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
title: string;
|
|
545
|
-
active: boolean;
|
|
546
|
-
}>>;
|
|
1106
|
+
/** Every open tab. */
|
|
1107
|
+
tabs(): Promise<Array<Tab>>;
|
|
1108
|
+
/** Opens a tab, optionally at `url`, and returns its id. */
|
|
547
1109
|
openTab(url?: string): Promise<string>;
|
|
1110
|
+
/** Makes a tab the one commands act on. */
|
|
548
1111
|
switchTab(tabId: string): Promise<void>;
|
|
1112
|
+
/** Closes a tab. */
|
|
549
1113
|
closeTab(tabId: string): Promise<void>;
|
|
550
1114
|
/**
|
|
551
|
-
|
|
1115
|
+
* Detect and clear a CAPTCHA. Providers that solve natively are left to do
|
|
552
1116
|
* it; everything else goes to the configured solver.
|
|
553
1117
|
*/
|
|
554
1118
|
solveCaptcha(): Promise<CaptchaResult>;
|
|
@@ -563,10 +1127,7 @@ declare class Browser {
|
|
|
563
1127
|
* the matching option; `secrets` it never sees. It types both through placeholders,
|
|
564
1128
|
* with filters like `{{name|first}}`, so a playbook saved from the run stores no values.
|
|
565
1129
|
*/
|
|
566
|
-
ask(prompt: string, { data, secrets }?:
|
|
567
|
-
data?: RunData;
|
|
568
|
-
secrets?: RunData;
|
|
569
|
-
}): Promise<string>;
|
|
1130
|
+
ask(prompt: string, { data, secrets }?: AskValues): Promise<string>;
|
|
570
1131
|
/**
|
|
571
1132
|
* Save the last `ask()` on this browser as a named playbook. Every value that was
|
|
572
1133
|
* typed, picked or clicked becomes a variable, with what the run used kept in
|
|
@@ -581,31 +1142,17 @@ declare class Browser {
|
|
|
581
1142
|
* saved as a draft (`healed`, `draft`); off, the step's error is thrown.
|
|
582
1143
|
* Play `'<name>:draft'` to try a draft before promoting it.
|
|
583
1144
|
*/
|
|
584
|
-
play(name: string, data?: RunData, { autoHeal }?:
|
|
585
|
-
autoHeal?: boolean;
|
|
586
|
-
}): Promise<PlayResult>;
|
|
1145
|
+
play(name: string, data?: RunData, { autoHeal }?: PlayOptions): Promise<PlayResult>;
|
|
587
1146
|
/**
|
|
588
1147
|
* Start a prompt or playbook in the background and hear back through callbacks.
|
|
589
1148
|
* `onHumanAttention` fires for an unsolved CAPTCHA, an unfinished MFA, the agent
|
|
590
1149
|
* asking for help, or a replay the agent could not heal; the run waits (up to 30
|
|
591
1150
|
* minutes) until you call `respond()`.
|
|
592
1151
|
*/
|
|
593
|
-
submit(task:
|
|
594
|
-
prompt: string;
|
|
595
|
-
} | {
|
|
596
|
-
playbook: string;
|
|
597
|
-
}, options?: SubmitOptions): Promise<Run>;
|
|
1152
|
+
submit(task: Task, options?: SubmitOptions): Promise<Run>;
|
|
598
1153
|
/**
|
|
599
|
-
* Watch it work: the console, opened on this browser.
|
|
600
|
-
*
|
|
601
|
-
* This used to return the raw frame stream with the project's API key in the
|
|
602
|
-
* query string — a permanent credential in browser history, Referer headers
|
|
603
|
-
* and every proxy log on the way, and a URL that renders as a wall of
|
|
604
|
-
* text/event-stream if a person actually opens it. It is the console deep
|
|
605
|
-
* link now, the same one the server hands back from `completeMfa()`, and it
|
|
606
|
-
* carries no credential at all.
|
|
607
|
-
*
|
|
608
|
-
* For the frames themselves, use `liveStreamUrl()`.
|
|
1154
|
+
* Watch it work: the console, opened on this browser. It carries no
|
|
1155
|
+
* credential. For the frames themselves, use `liveStreamUrl()`.
|
|
609
1156
|
*/
|
|
610
1157
|
liveViewUrl(): string;
|
|
611
1158
|
/**
|
|
@@ -625,14 +1172,7 @@ declare class Browser {
|
|
|
625
1172
|
* rest of your project. Anyone holding the link has that access until it
|
|
626
1173
|
* expires or you revoke it, so treat it like a password.
|
|
627
1174
|
*/
|
|
628
|
-
shareUrl({ control, expiresInSeconds }?:
|
|
629
|
-
control?: boolean;
|
|
630
|
-
expiresInSeconds?: number;
|
|
631
|
-
}): Promise<{
|
|
632
|
-
url: string;
|
|
633
|
-
id: string;
|
|
634
|
-
expiresAt: number | null;
|
|
635
|
-
}>;
|
|
1175
|
+
shareUrl({ control, expiresInSeconds }?: ShareOptions): Promise<ShareLink>;
|
|
636
1176
|
/** Revoke a link from `shareUrl()` before it expires, by the id it returned. */
|
|
637
1177
|
revokeShare(id: string): Promise<void>;
|
|
638
1178
|
/** Counters, health and the last 50 things this browser did. */
|
|
@@ -647,18 +1187,6 @@ declare class Browser {
|
|
|
647
1187
|
/** @deprecated use stop() — close() only dropped the socket, and a cloud browser redialled. */
|
|
648
1188
|
close(): Promise<void>;
|
|
649
1189
|
}
|
|
650
|
-
type RunCallbacks = Pick<SubmitOptions, 'onSuccess' | 'onFailure' | 'onHumanAttention' | 'onHealed'>;
|
|
651
|
-
/** A submitted task. Callbacks fire as it changes; `done` settles when it ends. */
|
|
652
|
-
declare class Run {
|
|
653
|
-
private readonly http;
|
|
654
|
-
readonly id: string;
|
|
655
|
-
readonly done: Promise<RunResult>;
|
|
656
|
-
constructor(http: Http, id: string, callbacks: RunCallbacks, pollMs?: number);
|
|
657
|
-
status(): Promise<RunInfo>;
|
|
658
|
-
/** Answer the open attention request: `'done'` after handling it by hand, or your reply to the agent. */
|
|
659
|
-
respond(response?: string): Promise<void>;
|
|
660
|
-
private watch;
|
|
661
|
-
}
|
|
662
1190
|
|
|
663
1191
|
/**
|
|
664
1192
|
* Files as task values.
|
|
@@ -678,100 +1206,52 @@ declare const MAX_FILE_BYTES: number;
|
|
|
678
1206
|
* from the extension.
|
|
679
1207
|
*/
|
|
680
1208
|
declare function file(source: string | Uint8Array | Blob, options?: {
|
|
1209
|
+
/** The filename the site sees. */
|
|
681
1210
|
name?: string;
|
|
1211
|
+
/** The MIME type, instead of the one guessed from the extension. */
|
|
682
1212
|
type?: string;
|
|
683
1213
|
}): Promise<FileValue>;
|
|
684
1214
|
|
|
685
|
-
/**
|
|
686
|
-
* @oya-ai/browser — thousands of browsers, one API.
|
|
687
|
-
*
|
|
688
|
-
* import { Oya } from '@oya-ai/browser';
|
|
689
|
-
*
|
|
690
|
-
* const oya = new Oya(); // OYA_API_KEY
|
|
691
|
-
* const browser = await oya.browser.start({ persona: 'auto', captcha: 'auto' });
|
|
692
|
-
* await browser.goto('https://example.com');
|
|
693
|
-
*
|
|
694
|
-
* Which provider actually runs the browser — Oya Cloud, your own machines,
|
|
695
|
-
* Browser Use, Browserbase, Steel, Anchor, or a CDP URL you hand us — is
|
|
696
|
-
* configuration on your API key, not something this code has to know.
|
|
697
|
-
*/
|
|
698
|
-
|
|
1215
|
+
/** The client: one API key, every browser behind it. */
|
|
699
1216
|
declare class Oya {
|
|
1217
|
+
/** The one HTTP path every call goes through. */
|
|
700
1218
|
private readonly http;
|
|
1219
|
+
/** Reads the key and URL from `options`, then OYA_API_KEY and OYA_BASE_URL. Throws without a key. */
|
|
701
1220
|
constructor(options?: OyaOptions);
|
|
1221
|
+
/** Start, reattach to, list and stop browsers. */
|
|
702
1222
|
readonly browser: {
|
|
703
|
-
/** Start a browser and wait until it can take commands. */
|
|
704
1223
|
start: (options?: StartOptions) => Promise<Browser>;
|
|
705
|
-
/** Reattach to a browser that is already running. */
|
|
706
1224
|
get: (id: string) => Promise<Browser>;
|
|
707
1225
|
list: () => Promise<BrowserInfo[]>;
|
|
708
|
-
|
|
709
|
-
stop: (ids: string[] | "all") => Promise<{
|
|
710
|
-
stopped: number;
|
|
711
|
-
results: StopResult[];
|
|
712
|
-
}>;
|
|
1226
|
+
stop: (ids: string[] | "all") => Promise<StopManyResult>;
|
|
713
1227
|
stopAll: () => Promise<number>;
|
|
714
1228
|
};
|
|
715
1229
|
/** Durable operational controls, including disconnected and cleanup-pending sessions. */
|
|
716
1230
|
readonly control: {
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
1231
|
+
createWebhook: (url: string, types?: string[]) => Promise<Webhook>;
|
|
1232
|
+
removeWebhook: (id: string) => Promise<Ack>;
|
|
1233
|
+
replayDelivery: (id: string) => Promise<Ack>;
|
|
1234
|
+
members: () => Promise<MemberList>;
|
|
1235
|
+
inviteMember: (role?: ControlRole) => Promise<Invite>;
|
|
1236
|
+
removeMember: (userId: string) => Promise<Ack>;
|
|
1237
|
+
createCredential: (options: CredentialRequest) => Promise<NewCredential>;
|
|
1238
|
+
revokeCredential: (id: string) => Promise<Ack>;
|
|
1239
|
+
recover: (id: string, replace?: boolean) => Promise<unknown>;
|
|
1240
|
+
ticket: (id: string) => Promise<Ticket>;
|
|
1241
|
+
events: (after?: number) => Promise<EventPage>;
|
|
721
1242
|
cancel: (id: string) => Promise<ControlSession>;
|
|
722
1243
|
stop: (id: string, force?: boolean) => Promise<StopResult>;
|
|
723
1244
|
takeover: (id: string, action: "acquire" | "release" | "resume") => Promise<ControlSession["control"]>;
|
|
724
1245
|
input: (id: string, action: HumanInputAction, params: Record<string, unknown>) => Promise<unknown>;
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
}>;
|
|
730
|
-
events: (after?: number) => Promise<{
|
|
731
|
-
events: ControlEvent[];
|
|
732
|
-
cursor: number;
|
|
733
|
-
}>;
|
|
734
|
-
createCredential: (options: {
|
|
735
|
-
role: ControlRole;
|
|
736
|
-
label?: string;
|
|
737
|
-
expiresAt?: number;
|
|
738
|
-
}) => Promise<ControlCredential & {
|
|
739
|
-
token: string;
|
|
740
|
-
}>;
|
|
741
|
-
revokeCredential: (id: string) => Promise<{
|
|
742
|
-
ok: boolean;
|
|
743
|
-
}>;
|
|
744
|
-
members: () => Promise<{
|
|
745
|
-
owner: string | null;
|
|
746
|
-
members: {
|
|
747
|
-
userId: string;
|
|
748
|
-
role: ControlRole;
|
|
749
|
-
}[];
|
|
750
|
-
}>;
|
|
751
|
-
inviteMember: (role?: ControlRole) => Promise<{
|
|
752
|
-
code: string;
|
|
753
|
-
expiresIn: number;
|
|
754
|
-
}>;
|
|
755
|
-
removeMember: (userId: string) => Promise<{
|
|
756
|
-
ok: boolean;
|
|
757
|
-
}>;
|
|
758
|
-
createWebhook: (url: string, types?: string[]) => Promise<{
|
|
759
|
-
id: string;
|
|
760
|
-
secret: string;
|
|
761
|
-
}>;
|
|
762
|
-
removeWebhook: (id: string) => Promise<{
|
|
763
|
-
ok: boolean;
|
|
764
|
-
}>;
|
|
765
|
-
replayDelivery: (id: string) => Promise<{
|
|
766
|
-
ok: boolean;
|
|
767
|
-
}>;
|
|
1246
|
+
overview: () => Promise<ControlOverview>;
|
|
1247
|
+
sessions: () => Promise<ControlSession[]>;
|
|
1248
|
+
session: (id: string) => Promise<ControlSession>;
|
|
1249
|
+
settings: (changes: Partial<ProjectSettings>) => Promise<ControlOverview["project"]>;
|
|
768
1250
|
};
|
|
769
1251
|
/** Playbooks saved with `browser.toPlaybook()`. */
|
|
770
1252
|
readonly playbooks: {
|
|
771
1253
|
list: () => Promise<PlaybookSummary[]>;
|
|
772
|
-
/** Delete a playbook and its draft, or only the draft with `'<name>:draft'`. */
|
|
773
1254
|
remove: (name: string) => Promise<void>;
|
|
774
|
-
/** Replace a playbook with the draft a healed replay saved. Try it first with `browser.play('<name>:draft')`. */
|
|
775
1255
|
promote: (name: string) => Promise<Playbook>;
|
|
776
1256
|
};
|
|
777
1257
|
/**
|
|
@@ -782,84 +1262,24 @@ declare class Oya {
|
|
|
782
1262
|
list: () => Promise<ProxyInfo[]>;
|
|
783
1263
|
create: (proxy: ProxyCreate) => Promise<ProxyInfo>;
|
|
784
1264
|
remove: (id: string) => Promise<void>;
|
|
785
|
-
|
|
786
|
-
check: () => Promise<Array<{
|
|
787
|
-
id: string;
|
|
788
|
-
ok: boolean;
|
|
789
|
-
exitIp?: string | null;
|
|
790
|
-
error?: string;
|
|
791
|
-
}>>;
|
|
1265
|
+
check: () => Promise<Array<ProxyCheck>>;
|
|
792
1266
|
};
|
|
1267
|
+
/** Identities: fingerprint, cookie jar and proxy bound together, plus their stored factors and logins. */
|
|
793
1268
|
readonly personas: {
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
*/
|
|
800
|
-
create: (options?: {
|
|
801
|
-
name?: string;
|
|
802
|
-
prefs?: PersonaPrefs;
|
|
803
|
-
proxy?: {
|
|
804
|
-
geo?: string;
|
|
805
|
-
};
|
|
806
|
-
maxConcurrent?: number | null;
|
|
807
|
-
}) => Promise<PersonaInfo>;
|
|
808
|
-
/** Name, concurrency cap and proxy hint. Never the device — clone for that. */
|
|
809
|
-
update: (id: string, changes: {
|
|
810
|
-
name?: string;
|
|
811
|
-
maxConcurrent?: number | null;
|
|
812
|
-
proxy?: {
|
|
813
|
-
geo?: string;
|
|
814
|
-
} | null;
|
|
815
|
-
}) => Promise<PersonaInfo>;
|
|
816
|
-
/** A new persona of the same kind of device: same choices, fresh identity, empty jar. */
|
|
817
|
-
clone: (id: string, options?: {
|
|
818
|
-
name?: string;
|
|
819
|
-
}) => Promise<PersonaInfo>;
|
|
820
|
-
/** The fingerprint these choices would produce. Persists nothing. */
|
|
1269
|
+
setCredentials: (id: string, config: SiteCredentials) => Promise<CredentialsSaved>;
|
|
1270
|
+
credentials: (id: string) => Promise<SiteLogins>;
|
|
1271
|
+
clearCredentials: (id: string, domain: string) => Promise<void>;
|
|
1272
|
+
setMfa: (id: string, config: MfaConfig) => Promise<MfaSaved>;
|
|
1273
|
+
clearMfa: (id: string, domain?: string) => Promise<void>;
|
|
821
1274
|
preview: (prefs?: PersonaPrefs) => Promise<Fingerprint>;
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
platforms: string[];
|
|
825
|
-
timezones: Record<string, string[]>;
|
|
826
|
-
locales: Record<string, string[]>;
|
|
827
|
-
}>;
|
|
828
|
-
/** Pin the persona to one of your proxies, or `null` to let assignment happen at connect. */
|
|
829
|
-
pinProxy: (id: string, proxyId: string | null) => Promise<{
|
|
830
|
-
ok: boolean;
|
|
831
|
-
proxy: {
|
|
832
|
-
id: string;
|
|
833
|
-
label: string;
|
|
834
|
-
} | null;
|
|
835
|
-
}>;
|
|
1275
|
+
options: () => Promise<PersonaOptions>;
|
|
1276
|
+
pinProxy: (id: string, proxyId: string | null) => Promise<ProxyPin>;
|
|
836
1277
|
remove: (id: string) => Promise<void>;
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
clearMfa: (id: string, domain?: string) => Promise<void>;
|
|
843
|
-
/**
|
|
844
|
-
* Store a site login for this identity. Sealed at rest, never read back.
|
|
845
|
-
*
|
|
846
|
-
* Signing in once on the desktop and inheriting the cookies is still the
|
|
847
|
-
* better path. This is for portals that expire a session server-side
|
|
848
|
-
* between runs, where an unattended run has nothing else to recover with.
|
|
849
|
-
*/
|
|
850
|
-
setCredentials: (id: string, config: SiteCredentials) => Promise<{
|
|
851
|
-
configured: boolean;
|
|
852
|
-
domain: string;
|
|
853
|
-
username: string;
|
|
854
|
-
}>;
|
|
855
|
-
/** Which sites this identity can sign in to. Usernames only. */
|
|
856
|
-
credentials: (id: string) => Promise<{
|
|
857
|
-
credentials: {
|
|
858
|
-
domain: string;
|
|
859
|
-
username: string;
|
|
860
|
-
}[];
|
|
861
|
-
}>;
|
|
862
|
-
clearCredentials: (id: string, domain: string) => Promise<void>;
|
|
1278
|
+
list: () => Promise<PersonaInfo[]>;
|
|
1279
|
+
get: (id: string) => Promise<PersonaInfo>;
|
|
1280
|
+
create: (options?: PersonaCreate) => Promise<PersonaInfo>;
|
|
1281
|
+
update: (id: string, changes: PersonaUpdate) => Promise<PersonaInfo>;
|
|
1282
|
+
clone: (id: string, options?: CloneOptions) => Promise<PersonaInfo>;
|
|
863
1283
|
};
|
|
864
1284
|
/**
|
|
865
1285
|
* This key's settings: LLM credentials, browser provider, solver.
|
|
@@ -878,77 +1298,24 @@ declare class Oya {
|
|
|
878
1298
|
};
|
|
879
1299
|
/** Saved profiles. `personas` is retained as an alias for existing clients. */
|
|
880
1300
|
readonly profiles: {
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
*/
|
|
887
|
-
create: (options?: {
|
|
888
|
-
name?: string;
|
|
889
|
-
prefs?: PersonaPrefs;
|
|
890
|
-
proxy?: {
|
|
891
|
-
geo?: string;
|
|
892
|
-
};
|
|
893
|
-
maxConcurrent?: number | null;
|
|
894
|
-
}) => Promise<PersonaInfo>;
|
|
895
|
-
/** Name, concurrency cap and proxy hint. Never the device — clone for that. */
|
|
896
|
-
update: (id: string, changes: {
|
|
897
|
-
name?: string;
|
|
898
|
-
maxConcurrent?: number | null;
|
|
899
|
-
proxy?: {
|
|
900
|
-
geo?: string;
|
|
901
|
-
} | null;
|
|
902
|
-
}) => Promise<PersonaInfo>;
|
|
903
|
-
/** A new persona of the same kind of device: same choices, fresh identity, empty jar. */
|
|
904
|
-
clone: (id: string, options?: {
|
|
905
|
-
name?: string;
|
|
906
|
-
}) => Promise<PersonaInfo>;
|
|
907
|
-
/** The fingerprint these choices would produce. Persists nothing. */
|
|
1301
|
+
setCredentials: (id: string, config: SiteCredentials) => Promise<CredentialsSaved>;
|
|
1302
|
+
credentials: (id: string) => Promise<SiteLogins>;
|
|
1303
|
+
clearCredentials: (id: string, domain: string) => Promise<void>;
|
|
1304
|
+
setMfa: (id: string, config: MfaConfig) => Promise<MfaSaved>;
|
|
1305
|
+
clearMfa: (id: string, domain?: string) => Promise<void>;
|
|
908
1306
|
preview: (prefs?: PersonaPrefs) => Promise<Fingerprint>;
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
platforms: string[];
|
|
912
|
-
timezones: Record<string, string[]>;
|
|
913
|
-
locales: Record<string, string[]>;
|
|
914
|
-
}>;
|
|
915
|
-
/** Pin the persona to one of your proxies, or `null` to let assignment happen at connect. */
|
|
916
|
-
pinProxy: (id: string, proxyId: string | null) => Promise<{
|
|
917
|
-
ok: boolean;
|
|
918
|
-
proxy: {
|
|
919
|
-
id: string;
|
|
920
|
-
label: string;
|
|
921
|
-
} | null;
|
|
922
|
-
}>;
|
|
1307
|
+
options: () => Promise<PersonaOptions>;
|
|
1308
|
+
pinProxy: (id: string, proxyId: string | null) => Promise<ProxyPin>;
|
|
923
1309
|
remove: (id: string) => Promise<void>;
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
clearMfa: (id: string, domain?: string) => Promise<void>;
|
|
930
|
-
/**
|
|
931
|
-
* Store a site login for this identity. Sealed at rest, never read back.
|
|
932
|
-
*
|
|
933
|
-
* Signing in once on the desktop and inheriting the cookies is still the
|
|
934
|
-
* better path. This is for portals that expire a session server-side
|
|
935
|
-
* between runs, where an unattended run has nothing else to recover with.
|
|
936
|
-
*/
|
|
937
|
-
setCredentials: (id: string, config: SiteCredentials) => Promise<{
|
|
938
|
-
configured: boolean;
|
|
939
|
-
domain: string;
|
|
940
|
-
username: string;
|
|
941
|
-
}>;
|
|
942
|
-
/** Which sites this identity can sign in to. Usernames only. */
|
|
943
|
-
credentials: (id: string) => Promise<{
|
|
944
|
-
credentials: {
|
|
945
|
-
domain: string;
|
|
946
|
-
username: string;
|
|
947
|
-
}[];
|
|
948
|
-
}>;
|
|
949
|
-
clearCredentials: (id: string, domain: string) => Promise<void>;
|
|
1310
|
+
list: () => Promise<PersonaInfo[]>;
|
|
1311
|
+
get: (id: string) => Promise<PersonaInfo>;
|
|
1312
|
+
create: (options?: PersonaCreate) => Promise<PersonaInfo>;
|
|
1313
|
+
update: (id: string, changes: PersonaUpdate) => Promise<PersonaInfo>;
|
|
1314
|
+
clone: (id: string, options?: CloneOptions) => Promise<PersonaInfo>;
|
|
950
1315
|
};
|
|
1316
|
+
/** What this key has spent. */
|
|
951
1317
|
usage(): Promise<unknown>;
|
|
1318
|
+
/** Waits for a starting browser to dial in, through this client's own list and session calls. */
|
|
952
1319
|
private waitUntilConnected;
|
|
953
1320
|
}
|
|
954
1321
|
|