@oya-ai/browser 1.0.83 → 1.0.86
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +202 -59
- package/dist/index.cjs +5 -2
- package/dist/index.d.cts +5 -2
- package/dist/index.d.ts +5 -2
- package/dist/index.js +5 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -26,81 +26,210 @@ Get an API key at [browser.getoya.ai](https://browser.getoya.ai) or self-host yo
|
|
|
26
26
|
|
|
27
27
|
---
|
|
28
28
|
|
|
29
|
-
##
|
|
29
|
+
## Quickstart
|
|
30
30
|
|
|
31
|
-
|
|
31
|
+
Requires Node.js 18+; examples use ES modules. Set `OYA_API_KEY` in your environment. `OYA_BASE_URL` optionally points to a self-hosted control plane.
|
|
32
32
|
|
|
33
|
-
```
|
|
33
|
+
```js
|
|
34
|
+
import { Oya } from "@oya-ai/browser";
|
|
35
|
+
|
|
36
|
+
const oya = new Oya();
|
|
37
|
+
const browser = await oya.browser.start({ captcha: "auto" });
|
|
38
|
+
try {
|
|
39
|
+
await browser.goto("https://example.com");
|
|
40
|
+
console.log(await browser.ask("What is the main heading on this page?"));
|
|
41
|
+
} finally {
|
|
42
|
+
await browser.stop();
|
|
43
|
+
}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
On Node.js 24+, `await using browser = await oya.browser.start()` also stops the browser when its scope exits, including on error.
|
|
47
|
+
|
|
48
|
+
## Portal automation: record once, replay with new inputs
|
|
49
|
+
|
|
50
|
+
This example adapts the portal-automation project's workflow: reuse a persona, attach to an existing browser or start one, run a prompt the first time, then replay its saved playbook. The portal, workflow names, and request values below are fictional. Supply your own test portal and credentials through environment variables; adapt the task to its actual pages.
|
|
51
|
+
|
|
52
|
+
Save as `portal.mjs` and run `node portal.mjs` after setting `OYA_API_KEY`, `PORTAL_URL`, `PORTAL_USERNAME`, and `PORTAL_PASSWORD`. Set `OYA_BROWSER_ID` only to reuse an already running browser.
|
|
53
|
+
|
|
54
|
+
```js
|
|
55
|
+
import { createInterface } from "node:readline/promises";
|
|
34
56
|
import { Oya } from "@oya-ai/browser";
|
|
35
57
|
|
|
36
|
-
|
|
58
|
+
function requiredEnv(name) {
|
|
59
|
+
const value = process.env[name];
|
|
60
|
+
if (!value) throw new Error(`Set ${name} before running this example.`);
|
|
61
|
+
return value;
|
|
62
|
+
}
|
|
37
63
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
64
|
+
const oya = new Oya({ apiKey: requiredEnv("OYA_API_KEY") });
|
|
65
|
+
const portalUrl = requiredEnv("PORTAL_URL");
|
|
66
|
+
const playbookName = "portal-request-review";
|
|
67
|
+
const secrets = {
|
|
68
|
+
username: requiredEnv("PORTAL_USERNAME"),
|
|
69
|
+
password: requiredEnv("PORTAL_PASSWORD"),
|
|
70
|
+
};
|
|
71
|
+
// Fictional test inputs. data is visible to the agent.
|
|
72
|
+
const data = {
|
|
73
|
+
customerName: "Alex Example",
|
|
74
|
+
requestId: "DEMO-0001",
|
|
75
|
+
requestedDate: "2030-01-15",
|
|
76
|
+
};
|
|
77
|
+
const task = [
|
|
78
|
+
"If not logged in, log in with {{username}} and {{password}}.",
|
|
79
|
+
"Open New Request and enter {{requestId}} as the reference.",
|
|
80
|
+
"Fill first name {{customerName|first}} and last name {{customerName|last}}.",
|
|
81
|
+
"Set the requested date to {{requestedDate|date:MM/DD/YYYY}}.",
|
|
82
|
+
"If a field is already correct, do not type its value again.",
|
|
83
|
+
"If an action times out, inspect the page before retrying it.",
|
|
84
|
+
"If information is missing, ask the person instead of guessing.",
|
|
85
|
+
"Stop on the review page. Do not submit the request.",
|
|
86
|
+
].join("\n");
|
|
87
|
+
|
|
88
|
+
const existingId = process.env.OYA_BROWSER_ID;
|
|
89
|
+
let browser;
|
|
90
|
+
if (existingId) {
|
|
91
|
+
browser = await oya.browser.get(existingId);
|
|
92
|
+
} else {
|
|
93
|
+
const persona = (await oya.personas.list())
|
|
94
|
+
.find((p) => p.name === "portal-demo")
|
|
95
|
+
?? await oya.personas.create({ name: "portal-demo" });
|
|
96
|
+
browser = await oya.browser.start({ persona: persona.id, captcha: "auto" });
|
|
97
|
+
}
|
|
41
98
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
99
|
+
try {
|
|
100
|
+
console.log("Watch in your Oya dashboard:", browser.liveViewUrl());
|
|
101
|
+
await browser.goto(portalUrl);
|
|
102
|
+
const exists = (await oya.playbooks.list()).some((p) => p.name === playbookName);
|
|
103
|
+
const run = await browser.submit(
|
|
104
|
+
exists ? { playbook: playbookName } : { prompt: task },
|
|
105
|
+
{
|
|
106
|
+
// Replay accepts all variables in data; the playbook remembers secret names.
|
|
107
|
+
...(exists ? { data: { ...data, ...secrets } } : { data, secrets }),
|
|
108
|
+
onSuccess: () => console.log("Run succeeded."),
|
|
109
|
+
onFailure: (error) => console.error("Run failed with status:", error.status),
|
|
110
|
+
onHealed: (result) => {
|
|
111
|
+
console.log("A repair draft is ready for review:", result.draft);
|
|
112
|
+
},
|
|
113
|
+
onHumanAttention: async (request) => {
|
|
114
|
+
console.log("Attention needed:", request.reason);
|
|
115
|
+
console.log(request.message);
|
|
116
|
+
console.log("Open:", request.liveViewUrl ?? browser.liveViewUrl());
|
|
117
|
+
const terminal = createInterface({ input: process.stdin, output: process.stdout });
|
|
118
|
+
try {
|
|
119
|
+
const answer = await terminal.question(request.reason === "agent"
|
|
120
|
+
? "Answer the agent: "
|
|
121
|
+
: "Handle this in the live view, then press Enter: ");
|
|
122
|
+
await request.respond(answer || "done");
|
|
123
|
+
} finally {
|
|
124
|
+
terminal.close();
|
|
125
|
+
}
|
|
126
|
+
},
|
|
127
|
+
},
|
|
128
|
+
);
|
|
129
|
+
|
|
130
|
+
await run.done; // Rejects on failure; do not save a failed run as a playbook.
|
|
131
|
+
const info = await run.status();
|
|
132
|
+
console.log("Run status:", info.status);
|
|
133
|
+
if (!exists) {
|
|
134
|
+
const playbook = await browser.toPlaybook(playbookName);
|
|
135
|
+
console.log("Saved:", playbook.name, "Steps:", playbook.steps);
|
|
136
|
+
console.log("Variables:", playbook.variables);
|
|
137
|
+
// playbook.code contains the flow as an exported Playwright module.
|
|
138
|
+
}
|
|
139
|
+
} finally {
|
|
140
|
+
// Leave an attached browser open; stop only the browser this script started.
|
|
141
|
+
if (!existingId) await browser.stop();
|
|
142
|
+
}
|
|
45
143
|
```
|
|
46
144
|
|
|
47
|
-
|
|
145
|
+
`submit()` starts a background run and returns a `Run` handle. The SDK polls every two seconds by default (`pollMs` overrides this). `run.done` resolves with the result or rejects with an error; `run.status()` reads the run record. Attention reasons are `captcha`, `mfa`, `agent`, and `heal_failed`. A run waits up to 30 minutes for `request.respond()` or `run.respond()`. Run records are held in server memory for one hour after completion; they do not survive a server restart.
|
|
48
146
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
147
|
+
### Data, secrets, and reusable placeholders
|
|
148
|
+
|
|
149
|
+
Use `{{name}}` references in prompts instead of interpolating values into the prompt text. `data` is available to the agent for reasoning; `secrets` supplies values for typing without including them as readable task inputs. Filters include `first`, `last`, `digits`, and `date:MM/DD/YYYY`.
|
|
150
|
+
|
|
151
|
+
For prompt runs, pass credentials in `secrets`. For replay, pass all variables in `data`: the saved playbook tracks which variables are secret, including during healing. Placeholder-based inputs remain variables in the saved flow. This is not a blanket redaction guarantee for page content, screenshots, agent replies, or application logs; inspect exported code before sharing it.
|
|
152
|
+
|
|
153
|
+
### Review a repaired playbook
|
|
154
|
+
|
|
155
|
+
Replay normally runs recorded steps without an LLM. With `autoHeal: true` (the default), a broken step can hand over to the agent, which saves a repair as `<name>:draft`. Promotion replaces the saved playbook with that draft.
|
|
156
|
+
|
|
157
|
+
The following continues with an active `browser` and the inputs above. Replaying a draft performs its actions, so review its code and use test inputs before promoting it.
|
|
158
|
+
|
|
159
|
+
```js
|
|
160
|
+
const saved = (await oya.playbooks.list())
|
|
161
|
+
.find((p) => p.name === playbookName);
|
|
162
|
+
if (saved?.draft) {
|
|
163
|
+
// Review saved.draft.code before executing it.
|
|
164
|
+
await browser.play(`${playbookName}:draft`, { ...data, ...secrets }, { autoHeal: false });
|
|
165
|
+
await oya.playbooks.promote(playbookName);
|
|
166
|
+
}
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
Use `autoHeal: false` with `play()` or `submit({ playbook: name }, options)` to fail at a broken step without agent repair. `oya.playbooks.remove(name)` removes a playbook and its draft; `remove("<name>:draft")` removes only the draft.
|
|
170
|
+
|
|
171
|
+
## Use your own model key
|
|
172
|
+
|
|
173
|
+
As in the portal-automation project's model setup script, configure the model on your Oya API key once for subsequent agent runs:
|
|
174
|
+
|
|
175
|
+
```js
|
|
176
|
+
import { Oya } from "@oya-ai/browser";
|
|
177
|
+
|
|
178
|
+
const modelKey = process.env.GEMINI_API_KEY;
|
|
179
|
+
if (!modelKey) throw new Error("Set GEMINI_API_KEY first.");
|
|
180
|
+
const oya = new Oya();
|
|
181
|
+
await oya.config.set({
|
|
182
|
+
llm_provider: "gemini", // "openai" | "anthropic" | "gemini" | "vertex"
|
|
183
|
+
openai_api_key: modelKey, // Shared field name for every supported provider.
|
|
184
|
+
// chat_model: process.env.OYA_CHAT_MODEL, // Optional provider model override.
|
|
53
185
|
});
|
|
54
186
|
```
|
|
55
187
|
|
|
56
|
-
|
|
188
|
+
### Gemini Enterprise (ex-Vertex AI)
|
|
57
189
|
|
|
58
|
-
|
|
190
|
+
`llm_provider: "vertex"` targets express mode, whose API keys work against a global endpoint with no GCP project or location:
|
|
59
191
|
|
|
60
|
-
```
|
|
61
|
-
|
|
62
|
-
console.log(pb.variables); // ["orderNumber"]
|
|
63
|
-
console.log(pb.code); // the same flow as Playwright
|
|
64
|
-
|
|
65
|
-
// Later, on any browser. If the site changed, the agent finishes the task
|
|
66
|
-
// and saves its fix as a draft ("download-invoice:draft").
|
|
67
|
-
const result = await browser.play("download-invoice", { orderNumber: "2077" });
|
|
68
|
-
if (result.healed) await oya.playbooks.promote("download-invoice"); // after reviewing it
|
|
69
|
-
// autoHeal: false throws at the broken step instead.
|
|
192
|
+
```js
|
|
193
|
+
await oya.config.set({ llm_provider: "vertex", openai_api_key: process.env.VERTEX_EXPRESS_KEY });
|
|
70
194
|
```
|
|
71
195
|
|
|
72
|
-
|
|
196
|
+
For an enterprise project instead, point at its OpenAI-compatible endpoint. That path authenticates with a Google OAuth access token rather than an API key, and the token expires after about an hour, so it suits a one-off run rather than a long-lived deployment:
|
|
73
197
|
|
|
74
|
-
```
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
onHumanAttention: async (req) => {
|
|
81
|
-
console.log(req.reason, req.message, req.liveViewUrl);
|
|
82
|
-
await req.respond("done"); // or your answer, when req.reason === "agent"
|
|
83
|
-
},
|
|
84
|
-
onHealed: (result) => console.log("fix saved as", result.draft),
|
|
198
|
+
```js
|
|
199
|
+
await oya.config.set({
|
|
200
|
+
llm_provider: "vertex",
|
|
201
|
+
openai_base_url: "https://us-central1-aiplatform.googleapis.com/v1/projects/PROJECT/locations/us-central1/endpoints/openapi",
|
|
202
|
+
openai_api_key: accessToken, // gcloud auth print-access-token
|
|
203
|
+
chat_model: "google/gemini-2.5-flash", // this endpoint prefixes model ids
|
|
85
204
|
});
|
|
86
|
-
await run.done;
|
|
87
205
|
```
|
|
88
206
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
207
|
+
Omit `chat_model` to use the configured provider's default. `oya.config.get()` reads configuration. To return to the shared model configuration:
|
|
208
|
+
|
|
209
|
+
```js
|
|
210
|
+
await oya.config.set({ llm_provider: null, openai_api_key: null, chat_model: null });
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
## Live view, sharing, and embedded streams
|
|
214
|
+
|
|
215
|
+
`browser.liveViewUrl()` returns a dashboard link without an API key; the viewer signs into Oya. For a scoped handoff to someone else, create an expiring share link:
|
|
216
|
+
|
|
217
|
+
```js
|
|
218
|
+
const share = await browser.shareUrl({ control: true, expiresInSeconds: 900 });
|
|
219
|
+
// Deliver share.url privately to the intended operator.
|
|
220
|
+
// Once the handoff is finished:
|
|
221
|
+
await browser.revokeShare(share.id);
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
Share links are view-only by default. `control: true` permits browser interaction. Anyone holding the link has its access until expiry or revocation.
|
|
225
|
+
|
|
226
|
+
For an embedded SSE stream of JPEG frames, use `await browser.liveStreamUrl()`. It mints a single-use connection ticket valid for 60 seconds; request a new URL for each connection.
|
|
98
227
|
|
|
99
228
|
---
|
|
100
229
|
|
|
101
230
|
## 🛡️ Deterministic Personas (Anti-Ban Identity)
|
|
102
231
|
|
|
103
|
-
A persona
|
|
232
|
+
A persona groups a stable device fingerprint, saved login cookies, and a proxy assignment for reuse across browser sessions.
|
|
104
233
|
|
|
105
234
|
```ts
|
|
106
235
|
import { Oya } from "@oya-ai/browser";
|
|
@@ -112,7 +241,7 @@ const persona = await oya.personas.create({
|
|
|
112
241
|
name: "us-shopper",
|
|
113
242
|
prefs: { platform: "MacIntel", timezone: "America/New_York", locale: "en-US" },
|
|
114
243
|
proxy: { geo: "US" },
|
|
115
|
-
maxConcurrent: 2, //
|
|
244
|
+
maxConcurrent: 2, // Limit simultaneous sessions for this identity
|
|
116
245
|
});
|
|
117
246
|
|
|
118
247
|
// Launch a browser with this persona (or persona: 'auto' for least-recently-used)
|
|
@@ -208,7 +337,7 @@ console.log("Page Title:", await page.title());
|
|
|
208
337
|
|
|
209
338
|
---
|
|
210
339
|
|
|
211
|
-
##
|
|
340
|
+
## API reference
|
|
212
341
|
|
|
213
342
|
### Initialization
|
|
214
343
|
|
|
@@ -243,14 +372,18 @@ const oya = new Oya({
|
|
|
243
372
|
- `queueMs?: number` — Wait duration for fleet capacity (ms)
|
|
244
373
|
- `budgetUsd?: number` — Enforce budget limit for session
|
|
245
374
|
- `idempotencyKey?: string` — Safe retry token
|
|
246
|
-
- `governed?: boolean` —
|
|
375
|
+
- `governed?: boolean` — Enable governed session controls
|
|
376
|
+
- `profile?: string` — Saved login profile (takes precedence over `persona`)
|
|
377
|
+
- `priority?: 'low' | 'normal' | 'high'` — Queue priority
|
|
378
|
+
- `policy?: { allowedHosts?, humanHosts?, region?, redactRecording? }` — Session policy
|
|
379
|
+
- `readyTimeoutMs?: number` — Wait budget for a starting browser to connect
|
|
247
380
|
|
|
248
381
|
### Browser Instance Methods (`browser.*`)
|
|
249
382
|
|
|
250
383
|
| Method | Returns | Description |
|
|
251
384
|
|:---|:---|:---|
|
|
252
385
|
| `goto(url)` | `Promise<void>` | Navigate to URL (with optional auto-CAPTCHA) |
|
|
253
|
-
| `ask(prompt)` | `Promise<string>` | Natural-language AI driving using key's configured model |
|
|
386
|
+
| `ask(prompt, { data?, secrets? }?)` | `Promise<string>` | Natural-language AI driving using key's configured model |
|
|
254
387
|
| `analyze()` | `Promise<Analysis>` | Returns markdown representation and numbered elements |
|
|
255
388
|
| `elements()` | `Promise<Element[]>` | Returns only visible interactable elements |
|
|
256
389
|
| `click(elementId)` | `Promise<void>` | Click element by numeric ID from `analyze()` |
|
|
@@ -266,11 +399,19 @@ const oya = new Oya({
|
|
|
266
399
|
| `closeTab(tabId)` | `Promise<void>` | Close target tab |
|
|
267
400
|
| `solveCaptcha()` | `Promise<CaptchaResult>` | Detect and solve on-screen CAPTCHA |
|
|
268
401
|
| `completeMfa()` | `Promise<MfaResult>` | Resolve TOTP/SMS MFA or return `liveViewUrl` |
|
|
269
|
-
| `liveViewUrl()` | `string` |
|
|
402
|
+
| `liveViewUrl()` | `string` | Dashboard link for this browser |
|
|
403
|
+
| `liveStreamUrl()` | `Promise<string>` | SSE frame stream URL with a single-use ticket |
|
|
404
|
+
| `shareUrl(options?)` | `Promise<{ url, id, expiresAt }>` | Expiring browser share link; optional control access |
|
|
405
|
+
| `revokeShare(id)` | `Promise<void>` | Revoke a share link |
|
|
406
|
+
| `submit(task, options?)` | `Promise<Run>` | Background prompt or playbook with callbacks |
|
|
407
|
+
| `toPlaybook(name)` | `Promise<Playbook>` | Save the latest agent flow and export Playwright code |
|
|
408
|
+
| `play(name, data?, { autoHeal? }?)` | `Promise<PlayResult>` | Replay a saved flow |
|
|
270
409
|
| `status()` | `Promise<BrowserDetail>` | Instance metrics, health, and recent activity log |
|
|
271
410
|
| `stop()` | `Promise<StopResult>` | Tear down sandbox and release CDP session |
|
|
272
411
|
|
|
273
|
-
###
|
|
412
|
+
### Profile and persona management (`oya.profiles`, `oya.personas`)
|
|
413
|
+
|
|
414
|
+
`oya.profiles` exposes the same methods as `oya.personas`; the persona name remains available for existing integrations.
|
|
274
415
|
|
|
275
416
|
| Method | Description |
|
|
276
417
|
|:---|:---|
|
|
@@ -312,7 +453,7 @@ await oya.personas.pinProxy(persona.id, proxy.id);
|
|
|
312
453
|
| `session(id)` | Get detailed session execution state |
|
|
313
454
|
| `takeover(id, 'acquire' \| 'release' \| 'resume')` | Manage human control leases |
|
|
314
455
|
| `ticket(id)` | Generate single-use connection ticket for secure handoff |
|
|
315
|
-
| `events(after?)` |
|
|
456
|
+
| `events(after?)` | Read audit events and a pagination cursor |
|
|
316
457
|
| `createCredential(options)` | Mint scoped service credential (`viewer` / `operator` / `administrator`) |
|
|
317
458
|
| `createWebhook(url, types)` | Register HMAC-signed webhook for fleet lifecycle events |
|
|
318
459
|
|
|
@@ -320,7 +461,7 @@ await oya.personas.pinProxy(persona.id, proxy.id);
|
|
|
320
461
|
|
|
321
462
|
## 🚨 Error Handling
|
|
322
463
|
|
|
323
|
-
|
|
464
|
+
API error responses and failed browser commands throw `OyaError`. Network failures, request timeouts, and configuration errors may throw other error types:
|
|
324
465
|
|
|
325
466
|
```ts
|
|
326
467
|
import { Oya, OyaError } from "@oya-ai/browser";
|
|
@@ -331,7 +472,9 @@ try {
|
|
|
331
472
|
} catch (err) {
|
|
332
473
|
if (err instanceof OyaError) {
|
|
333
474
|
console.error(`Oya API Error (${err.status}):`, err.message);
|
|
334
|
-
|
|
475
|
+
// err.body contains response details; inspect privately if needed.
|
|
476
|
+
} else {
|
|
477
|
+
throw err;
|
|
335
478
|
}
|
|
336
479
|
}
|
|
337
480
|
```
|
package/dist/index.cjs
CHANGED
|
@@ -171,7 +171,7 @@ var Browser = class {
|
|
|
171
171
|
await this.command("close_tab", { tab_id: tabId });
|
|
172
172
|
}
|
|
173
173
|
/**
|
|
174
|
-
|
|
174
|
+
x * Detect and clear a CAPTCHA. Providers that solve natively are left to do
|
|
175
175
|
* it; everything else goes to the configured solver.
|
|
176
176
|
*/
|
|
177
177
|
solveCaptcha() {
|
|
@@ -506,7 +506,10 @@ var Oya = class {
|
|
|
506
506
|
*
|
|
507
507
|
* Bring your own LLM key (it pays for its own tokens, so no hourly chat quota applies):
|
|
508
508
|
* await oya.config.set({ llm_provider: 'gemini', openai_api_key: process.env.GEMINI_API_KEY });
|
|
509
|
-
* `llm_provider` is 'openai' | 'anthropic' | 'gemini'; `chat_model` overrides
|
|
509
|
+
* `llm_provider` is 'openai' | 'anthropic' | 'gemini' | 'vertex'; `chat_model` overrides
|
|
510
|
+
* its default model. 'vertex' is Gemini Enterprise (ex-Vertex AI) in express mode, which
|
|
511
|
+
* needs no GCP project; for a project-scoped endpoint, set `openai_base_url` to
|
|
512
|
+
* `.../endpoints/openapi` and pass an OAuth access token as `openai_api_key`.
|
|
510
513
|
*/
|
|
511
514
|
config = {
|
|
512
515
|
get: () => this.http.request("GET", "/api/config"),
|
package/dist/index.d.cts
CHANGED
|
@@ -424,7 +424,7 @@ declare class Browser {
|
|
|
424
424
|
switchTab(tabId: string): Promise<void>;
|
|
425
425
|
closeTab(tabId: string): Promise<void>;
|
|
426
426
|
/**
|
|
427
|
-
|
|
427
|
+
x * Detect and clear a CAPTCHA. Providers that solve natively are left to do
|
|
428
428
|
* it; everything else goes to the configured solver.
|
|
429
429
|
*/
|
|
430
430
|
solveCaptcha(): Promise<CaptchaResult>;
|
|
@@ -699,7 +699,10 @@ declare class Oya {
|
|
|
699
699
|
*
|
|
700
700
|
* Bring your own LLM key (it pays for its own tokens, so no hourly chat quota applies):
|
|
701
701
|
* await oya.config.set({ llm_provider: 'gemini', openai_api_key: process.env.GEMINI_API_KEY });
|
|
702
|
-
* `llm_provider` is 'openai' | 'anthropic' | 'gemini'; `chat_model` overrides
|
|
702
|
+
* `llm_provider` is 'openai' | 'anthropic' | 'gemini' | 'vertex'; `chat_model` overrides
|
|
703
|
+
* its default model. 'vertex' is Gemini Enterprise (ex-Vertex AI) in express mode, which
|
|
704
|
+
* needs no GCP project; for a project-scoped endpoint, set `openai_base_url` to
|
|
705
|
+
* `.../endpoints/openapi` and pass an OAuth access token as `openai_api_key`.
|
|
703
706
|
*/
|
|
704
707
|
readonly config: {
|
|
705
708
|
get: <T = Record<string, unknown>>() => Promise<T>;
|
package/dist/index.d.ts
CHANGED
|
@@ -424,7 +424,7 @@ declare class Browser {
|
|
|
424
424
|
switchTab(tabId: string): Promise<void>;
|
|
425
425
|
closeTab(tabId: string): Promise<void>;
|
|
426
426
|
/**
|
|
427
|
-
|
|
427
|
+
x * Detect and clear a CAPTCHA. Providers that solve natively are left to do
|
|
428
428
|
* it; everything else goes to the configured solver.
|
|
429
429
|
*/
|
|
430
430
|
solveCaptcha(): Promise<CaptchaResult>;
|
|
@@ -699,7 +699,10 @@ declare class Oya {
|
|
|
699
699
|
*
|
|
700
700
|
* Bring your own LLM key (it pays for its own tokens, so no hourly chat quota applies):
|
|
701
701
|
* await oya.config.set({ llm_provider: 'gemini', openai_api_key: process.env.GEMINI_API_KEY });
|
|
702
|
-
* `llm_provider` is 'openai' | 'anthropic' | 'gemini'; `chat_model` overrides
|
|
702
|
+
* `llm_provider` is 'openai' | 'anthropic' | 'gemini' | 'vertex'; `chat_model` overrides
|
|
703
|
+
* its default model. 'vertex' is Gemini Enterprise (ex-Vertex AI) in express mode, which
|
|
704
|
+
* needs no GCP project; for a project-scoped endpoint, set `openai_base_url` to
|
|
705
|
+
* `.../endpoints/openapi` and pass an OAuth access token as `openai_api_key`.
|
|
703
706
|
*/
|
|
704
707
|
readonly config: {
|
|
705
708
|
get: <T = Record<string, unknown>>() => Promise<T>;
|
package/dist/index.js
CHANGED
|
@@ -141,7 +141,7 @@ var Browser = class {
|
|
|
141
141
|
await this.command("close_tab", { tab_id: tabId });
|
|
142
142
|
}
|
|
143
143
|
/**
|
|
144
|
-
|
|
144
|
+
x * Detect and clear a CAPTCHA. Providers that solve natively are left to do
|
|
145
145
|
* it; everything else goes to the configured solver.
|
|
146
146
|
*/
|
|
147
147
|
solveCaptcha() {
|
|
@@ -476,7 +476,10 @@ var Oya = class {
|
|
|
476
476
|
*
|
|
477
477
|
* Bring your own LLM key (it pays for its own tokens, so no hourly chat quota applies):
|
|
478
478
|
* await oya.config.set({ llm_provider: 'gemini', openai_api_key: process.env.GEMINI_API_KEY });
|
|
479
|
-
* `llm_provider` is 'openai' | 'anthropic' | 'gemini'; `chat_model` overrides
|
|
479
|
+
* `llm_provider` is 'openai' | 'anthropic' | 'gemini' | 'vertex'; `chat_model` overrides
|
|
480
|
+
* its default model. 'vertex' is Gemini Enterprise (ex-Vertex AI) in express mode, which
|
|
481
|
+
* needs no GCP project; for a project-scoped endpoint, set `openai_base_url` to
|
|
482
|
+
* `.../endpoints/openapi` and pass an OAuth access token as `openai_api_key`.
|
|
480
483
|
*/
|
|
481
484
|
config = {
|
|
482
485
|
get: () => this.http.request("GET", "/api/config"),
|
package/package.json
CHANGED