@oya-ai/browser 1.0.209 → 1.0.213

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 CHANGED
@@ -25,21 +25,30 @@ import { Oya } from '@oya-ai/browser';
25
25
 
26
26
  const browser = await new Oya().browser.start();
27
27
  await browser.goto('https://news.ycombinator.com');
28
- console.log(await browser.ask('What are the top 3 stories?'));
28
+ console.log(await browser.ask('What are the top 3 stories and their points?'));
29
+ await browser.stop();
29
30
  ```
30
31
 
31
- Two things to have first: an API key from [oyabrowser.com](https://oyabrowser.com)
32
- (or your own deployment) in `OYA_API_KEY`, and a browser to drive.
32
+ The one thing to have first is an API key from [oyabrowser.com](https://oyabrowser.com)
33
+ (or your own deployment) in `OYA_API_KEY`.
33
34
 
34
- **The fastest browser to have is one you already have.** Open the
35
- [Oya desktop browser](https://oyabrowser.com) and sign in with the same key: `start()`
36
- hands over the browser that is already connected when no provider is configured, so the
37
- five lines above work with nothing else set up. `stop()` leaves a browser you borrowed
38
- alone, because you did not start it.
35
+ **Which browser `start()` gives you**, when no provider is configured: the
36
+ [Oya desktop browser](https://oyabrowser.com) if it is open and signed in with the same
37
+ key, else a new one in Oya Cloud. `stop()` leaves a browser you borrowed alone, because
38
+ you did not start it. To run browsers somewhere else (your own Docker, Browserbase,
39
+ Steel, Anchor, Browser Use, or a Chrome of your own over CDP), pass `{ provider }` or set
40
+ a default with `npx @oya-ai/cli init`. Your code does not change.
39
41
 
40
- When you would rather it start one for you, run `npx @oya-ai/cli init` and pick where
41
- browsers run: Oya Cloud, your own Docker, Browserbase, Steel, Anchor, Browser Use, or a
42
- Chrome of your own over CDP. Your code does not change.
42
+ **Which model `ask()` uses:** the key's saved one, or Oya's when it has none. Pick one in
43
+ code, for this client only and never saved to the key:
44
+
45
+ ```js
46
+ const oya = new Oya({
47
+ model: { provider: 'anthropic', name: 'claude-sonnet-5', apiKey: process.env.ANTHROPIC_API_KEY },
48
+ });
49
+ ```
50
+
51
+ Without `apiKey`, `name` runs on the credential your key already uses, which must be the same provider.
43
52
 
44
53
  **Where the key comes from**, in order: `new Oya({ apiKey })`, then `OYA_API_KEY`, then the
45
54
  file `oya login` wrote (`~/.oya/config.json`, or `OYA_CONFIG_HOME`), which is read on Node
package/dist/index.cjs CHANGED
@@ -131,18 +131,20 @@ function saveKey(apiKey, baseUrl) {
131
131
  var OPTIONS_ORIGIN = { apiKeyFrom: "the apiKey option", baseUrlFrom: "the baseUrl option", savedKey: false };
132
132
  var Http = class {
133
133
  /** Stores where to call, with which key, how long to wait, which fetch to use, and where the key and address came from. */
134
- constructor(baseUrl, apiKey, timeoutMs, fetchImpl, origin = OPTIONS_ORIGIN) {
134
+ constructor(baseUrl, apiKey, timeoutMs, fetchImpl, origin = OPTIONS_ORIGIN, defaults = {}) {
135
135
  this.baseUrl = baseUrl;
136
136
  this.apiKey = apiKey;
137
137
  this.timeoutMs = timeoutMs;
138
138
  this.fetchImpl = fetchImpl;
139
139
  this.origin = origin;
140
+ this.defaults = defaults;
140
141
  }
141
142
  baseUrl;
142
143
  apiKey;
143
144
  timeoutMs;
144
145
  fetchImpl;
145
146
  origin;
147
+ defaults;
146
148
  /** Sends one request and returns the parsed answer, or throws an OyaError when it failed. */
147
149
  async request(method, path, body, timeoutMs = this.timeoutMs, headers = {}) {
148
150
  const res = await this.send(`${this.baseUrl}${path}`, this.init(method, body, timeoutMs, headers), timeoutMs);
@@ -150,7 +152,11 @@ var Http = class {
150
152
  }
151
153
  /** The fetch options for one call, with this client's key on them. */
152
154
  init(method, body, timeoutMs, headers) {
153
- return requestInit(method, body, timeoutMs, { Authorization: `Bearer ${this.apiKey}`, ...headers });
155
+ return requestInit(method, body, timeoutMs, {
156
+ Authorization: `Bearer ${this.apiKey}`,
157
+ ...this.defaults,
158
+ ...headers
159
+ });
154
160
  }
155
161
  /**
156
162
  * fetch's own failures say only "fetch failed" or "The operation was
@@ -235,7 +241,7 @@ function deploymentOf(url) {
235
241
  }
236
242
  }
237
243
  function noKey(saved, address) {
238
- if (!saved.apiKey) return "No API key. Pass { apiKey }, set OYA_API_KEY, or run `npx @oya-ai/cli login`.";
244
+ if (!saved.apiKey) return "No API key. Get one at https://oyabrowser.com, then set OYA_API_KEY or pass { apiKey }.";
239
245
  const why = `the key saved in ~/.oya/config.json is for ${saved.baseUrl} and is only sent there`;
240
246
  return `No API key for ${address}: ${why}. Pass { apiKey }, set OYA_API_KEY, or run \`npx @oya-ai/cli login --url ${address}\`.`;
241
247
  }
@@ -247,7 +253,18 @@ function createHttp(options) {
247
253
  if (!fetchImpl) throw new Error("No fetch available, pass { fetch } or use Node 18+.");
248
254
  const origin = { apiKeyFrom: key.from, baseUrlFrom: address.from, savedKey: !!saved.apiKey };
249
255
  const timeout = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
250
- return new Http(webAddress(address), key.value, timeout, fetchImpl.bind(globalThis), origin);
256
+ return new Http(webAddress(address), key.value, timeout, fetchImpl.bind(globalThis), origin, modelHeaders(options));
257
+ }
258
+ var MODEL_FIX = "Check the model option.";
259
+ function modelHeaders({ model }) {
260
+ if (!model) return {};
261
+ const fields = [
262
+ ["provider", "X-Oya-Llm-Provider"],
263
+ ["name", "X-Oya-Llm-Model"],
264
+ ["apiKey", "X-Oya-Llm-Api-Key"]
265
+ ];
266
+ const set = fields.filter(([field]) => model[field]);
267
+ return Object.fromEntries(set.map(([field, name]) => [name, headerSafe(model[field], `model.${field}`, MODEL_FIX)]));
251
268
  }
252
269
  var LOCAL_HOST = /^(localhost|127\.)/i;
253
270
  function webAddress({ value, from }) {
package/dist/index.d.cts CHANGED
@@ -986,6 +986,7 @@ interface ControlOverview {
986
986
  /**
987
987
  * The options the `Oya` client is constructed with.
988
988
  */
989
+
989
990
  /** How to reach the control plane, and as whom. */
990
991
  interface OyaOptions {
991
992
  /** Defaults to OYA_API_KEY. */
@@ -996,6 +997,28 @@ interface OyaOptions {
996
997
  timeoutMs?: number;
997
998
  /** A fetch to use instead of the global one, for tests, proxies or old runtimes. */
998
999
  fetch?: typeof globalThis.fetch;
1000
+ /**
1001
+ * The model behind `ask()`, `extract()`, runs and healed replays, for this client
1002
+ * only. Left out, the key's saved model is used (`oya init`, the console).
1003
+ */
1004
+ model?: ModelOptions;
1005
+ }
1006
+ /**
1007
+ * A model picked in code, sent with every call and never saved to the key, so the
1008
+ * console and the desktop app keep theirs.
1009
+ */
1010
+ interface ModelOptions {
1011
+ /** Whose model. */
1012
+ provider: LlmProvider;
1013
+ /** The model id, e.g. 'claude-sonnet-5'. The provider's default when left out. */
1014
+ name?: string;
1015
+ /**
1016
+ * Your own key for that provider: calls go to the provider's own endpoint and are
1017
+ * billed to you. Without one, `name` runs on the credential your key already uses
1018
+ * (its saved one, else the server's), which must be `provider`'s; the server's own
1019
+ * offers its priced models only.
1020
+ */
1021
+ apiKey?: string;
999
1022
  }
1000
1023
  /** What `Oya.signup()` takes. */
1001
1024
  interface SignupOptions {
@@ -1045,8 +1068,9 @@ declare class Http {
1045
1068
  private readonly timeoutMs;
1046
1069
  private readonly fetchImpl;
1047
1070
  readonly origin: Origin;
1071
+ private readonly defaults;
1048
1072
  /** Stores where to call, with which key, how long to wait, which fetch to use, and where the key and address came from. */
1049
- constructor(baseUrl: string, apiKey: string, timeoutMs: number, fetchImpl: typeof globalThis.fetch, origin?: Origin);
1073
+ constructor(baseUrl: string, apiKey: string, timeoutMs: number, fetchImpl: typeof globalThis.fetch, origin?: Origin, defaults?: Record<string, string>);
1050
1074
  /** Sends one request and returns the parsed answer, or throws an OyaError when it failed. */
1051
1075
  request<T>(method: string, path: string, body?: unknown, timeoutMs?: number, headers?: Record<string, string>): Promise<T>;
1052
1076
  /** The fetch options for one call, with this client's key on them. */
@@ -1657,4 +1681,4 @@ declare class Oya {
1657
1681
  }
1658
1682
 
1659
1683
  export { Browser, MAX_FILE_BYTES, Oya, OyaError, Run, Oya as default, file };
1660
- export type { Activity, Analysis, AnalyzeOptions, AttentionRequest, Block, BrowserDetail, BrowserInfo, CaptchaResult, CaptchaSolver, Config, ConfigUpdate, ControlCredential, ControlEvent, ControlOverview, ControlRole, ControlSession, Cookie, CookieFormat, DesktopOptions, EcsAuth, EcsConfig, Element, FileValue, Fingerprint, Health, HumanInputAction, ImportOptions, LlmCatalogEntry, LlmProvider, MfaConfig, MfaResult, OyaOptions, PageFormat, PersonaGroup, PersonaInfo, PersonaPrefs, PlayResult, Playbook, PlaybookAnswer, PlaybookExport, PlaybookSummary, ProjectSettings, Provider, ProxyCreate, ProxyInfo, RecoverOptions, RunData, RunInfo, RunResult, SandboxRuntime, Signup, SignupOptions, SiteCredentials, StartOptions, StartResult, StopResult, SubmitOptions };
1684
+ export type { Activity, Analysis, AnalyzeOptions, AttentionRequest, Block, BrowserDetail, BrowserInfo, CaptchaResult, CaptchaSolver, Config, ConfigUpdate, ControlCredential, ControlEvent, ControlOverview, ControlRole, ControlSession, Cookie, CookieFormat, DesktopOptions, EcsAuth, EcsConfig, Element, FileValue, Fingerprint, Health, HumanInputAction, ImportOptions, LlmCatalogEntry, LlmProvider, MfaConfig, MfaResult, ModelOptions, OyaOptions, PageFormat, PersonaGroup, PersonaInfo, PersonaPrefs, PlayResult, Playbook, PlaybookAnswer, PlaybookExport, PlaybookSummary, ProjectSettings, Provider, ProxyCreate, ProxyInfo, RecoverOptions, RunData, RunInfo, RunResult, SandboxRuntime, Signup, SignupOptions, SiteCredentials, StartOptions, StartResult, StopResult, SubmitOptions };
package/dist/index.d.ts CHANGED
@@ -986,6 +986,7 @@ interface ControlOverview {
986
986
  /**
987
987
  * The options the `Oya` client is constructed with.
988
988
  */
989
+
989
990
  /** How to reach the control plane, and as whom. */
990
991
  interface OyaOptions {
991
992
  /** Defaults to OYA_API_KEY. */
@@ -996,6 +997,28 @@ interface OyaOptions {
996
997
  timeoutMs?: number;
997
998
  /** A fetch to use instead of the global one, for tests, proxies or old runtimes. */
998
999
  fetch?: typeof globalThis.fetch;
1000
+ /**
1001
+ * The model behind `ask()`, `extract()`, runs and healed replays, for this client
1002
+ * only. Left out, the key's saved model is used (`oya init`, the console).
1003
+ */
1004
+ model?: ModelOptions;
1005
+ }
1006
+ /**
1007
+ * A model picked in code, sent with every call and never saved to the key, so the
1008
+ * console and the desktop app keep theirs.
1009
+ */
1010
+ interface ModelOptions {
1011
+ /** Whose model. */
1012
+ provider: LlmProvider;
1013
+ /** The model id, e.g. 'claude-sonnet-5'. The provider's default when left out. */
1014
+ name?: string;
1015
+ /**
1016
+ * Your own key for that provider: calls go to the provider's own endpoint and are
1017
+ * billed to you. Without one, `name` runs on the credential your key already uses
1018
+ * (its saved one, else the server's), which must be `provider`'s; the server's own
1019
+ * offers its priced models only.
1020
+ */
1021
+ apiKey?: string;
999
1022
  }
1000
1023
  /** What `Oya.signup()` takes. */
1001
1024
  interface SignupOptions {
@@ -1045,8 +1068,9 @@ declare class Http {
1045
1068
  private readonly timeoutMs;
1046
1069
  private readonly fetchImpl;
1047
1070
  readonly origin: Origin;
1071
+ private readonly defaults;
1048
1072
  /** Stores where to call, with which key, how long to wait, which fetch to use, and where the key and address came from. */
1049
- constructor(baseUrl: string, apiKey: string, timeoutMs: number, fetchImpl: typeof globalThis.fetch, origin?: Origin);
1073
+ constructor(baseUrl: string, apiKey: string, timeoutMs: number, fetchImpl: typeof globalThis.fetch, origin?: Origin, defaults?: Record<string, string>);
1050
1074
  /** Sends one request and returns the parsed answer, or throws an OyaError when it failed. */
1051
1075
  request<T>(method: string, path: string, body?: unknown, timeoutMs?: number, headers?: Record<string, string>): Promise<T>;
1052
1076
  /** The fetch options for one call, with this client's key on them. */
@@ -1657,4 +1681,4 @@ declare class Oya {
1657
1681
  }
1658
1682
 
1659
1683
  export { Browser, MAX_FILE_BYTES, Oya, OyaError, Run, Oya as default, file };
1660
- export type { Activity, Analysis, AnalyzeOptions, AttentionRequest, Block, BrowserDetail, BrowserInfo, CaptchaResult, CaptchaSolver, Config, ConfigUpdate, ControlCredential, ControlEvent, ControlOverview, ControlRole, ControlSession, Cookie, CookieFormat, DesktopOptions, EcsAuth, EcsConfig, Element, FileValue, Fingerprint, Health, HumanInputAction, ImportOptions, LlmCatalogEntry, LlmProvider, MfaConfig, MfaResult, OyaOptions, PageFormat, PersonaGroup, PersonaInfo, PersonaPrefs, PlayResult, Playbook, PlaybookAnswer, PlaybookExport, PlaybookSummary, ProjectSettings, Provider, ProxyCreate, ProxyInfo, RecoverOptions, RunData, RunInfo, RunResult, SandboxRuntime, Signup, SignupOptions, SiteCredentials, StartOptions, StartResult, StopResult, SubmitOptions };
1684
+ export type { Activity, Analysis, AnalyzeOptions, AttentionRequest, Block, BrowserDetail, BrowserInfo, CaptchaResult, CaptchaSolver, Config, ConfigUpdate, ControlCredential, ControlEvent, ControlOverview, ControlRole, ControlSession, Cookie, CookieFormat, DesktopOptions, EcsAuth, EcsConfig, Element, FileValue, Fingerprint, Health, HumanInputAction, ImportOptions, LlmCatalogEntry, LlmProvider, MfaConfig, MfaResult, ModelOptions, OyaOptions, PageFormat, PersonaGroup, PersonaInfo, PersonaPrefs, PlayResult, Playbook, PlaybookAnswer, PlaybookExport, PlaybookSummary, ProjectSettings, Provider, ProxyCreate, ProxyInfo, RecoverOptions, RunData, RunInfo, RunResult, SandboxRuntime, Signup, SignupOptions, SiteCredentials, StartOptions, StartResult, StopResult, SubmitOptions };
package/dist/index.js CHANGED
@@ -99,18 +99,20 @@ function saveKey(apiKey, baseUrl) {
99
99
  var OPTIONS_ORIGIN = { apiKeyFrom: "the apiKey option", baseUrlFrom: "the baseUrl option", savedKey: false };
100
100
  var Http = class {
101
101
  /** Stores where to call, with which key, how long to wait, which fetch to use, and where the key and address came from. */
102
- constructor(baseUrl, apiKey, timeoutMs, fetchImpl, origin = OPTIONS_ORIGIN) {
102
+ constructor(baseUrl, apiKey, timeoutMs, fetchImpl, origin = OPTIONS_ORIGIN, defaults = {}) {
103
103
  this.baseUrl = baseUrl;
104
104
  this.apiKey = apiKey;
105
105
  this.timeoutMs = timeoutMs;
106
106
  this.fetchImpl = fetchImpl;
107
107
  this.origin = origin;
108
+ this.defaults = defaults;
108
109
  }
109
110
  baseUrl;
110
111
  apiKey;
111
112
  timeoutMs;
112
113
  fetchImpl;
113
114
  origin;
115
+ defaults;
114
116
  /** Sends one request and returns the parsed answer, or throws an OyaError when it failed. */
115
117
  async request(method, path, body, timeoutMs = this.timeoutMs, headers = {}) {
116
118
  const res = await this.send(`${this.baseUrl}${path}`, this.init(method, body, timeoutMs, headers), timeoutMs);
@@ -118,7 +120,11 @@ var Http = class {
118
120
  }
119
121
  /** The fetch options for one call, with this client's key on them. */
120
122
  init(method, body, timeoutMs, headers) {
121
- return requestInit(method, body, timeoutMs, { Authorization: `Bearer ${this.apiKey}`, ...headers });
123
+ return requestInit(method, body, timeoutMs, {
124
+ Authorization: `Bearer ${this.apiKey}`,
125
+ ...this.defaults,
126
+ ...headers
127
+ });
122
128
  }
123
129
  /**
124
130
  * fetch's own failures say only "fetch failed" or "The operation was
@@ -203,7 +209,7 @@ function deploymentOf(url) {
203
209
  }
204
210
  }
205
211
  function noKey(saved, address) {
206
- if (!saved.apiKey) return "No API key. Pass { apiKey }, set OYA_API_KEY, or run `npx @oya-ai/cli login`.";
212
+ if (!saved.apiKey) return "No API key. Get one at https://oyabrowser.com, then set OYA_API_KEY or pass { apiKey }.";
207
213
  const why = `the key saved in ~/.oya/config.json is for ${saved.baseUrl} and is only sent there`;
208
214
  return `No API key for ${address}: ${why}. Pass { apiKey }, set OYA_API_KEY, or run \`npx @oya-ai/cli login --url ${address}\`.`;
209
215
  }
@@ -215,7 +221,18 @@ function createHttp(options) {
215
221
  if (!fetchImpl) throw new Error("No fetch available, pass { fetch } or use Node 18+.");
216
222
  const origin = { apiKeyFrom: key.from, baseUrlFrom: address.from, savedKey: !!saved.apiKey };
217
223
  const timeout = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
218
- return new Http(webAddress(address), key.value, timeout, fetchImpl.bind(globalThis), origin);
224
+ return new Http(webAddress(address), key.value, timeout, fetchImpl.bind(globalThis), origin, modelHeaders(options));
225
+ }
226
+ var MODEL_FIX = "Check the model option.";
227
+ function modelHeaders({ model }) {
228
+ if (!model) return {};
229
+ const fields = [
230
+ ["provider", "X-Oya-Llm-Provider"],
231
+ ["name", "X-Oya-Llm-Model"],
232
+ ["apiKey", "X-Oya-Llm-Api-Key"]
233
+ ];
234
+ const set = fields.filter(([field]) => model[field]);
235
+ return Object.fromEntries(set.map(([field, name]) => [name, headerSafe(model[field], `model.${field}`, MODEL_FIX)]));
219
236
  }
220
237
  var LOCAL_HOST = /^(localhost|127\.)/i;
221
238
  function webAddress({ value, from }) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oya-ai/browser",
3
- "version": "1.0.209",
3
+ "version": "1.0.213",
4
4
  "description": "Rotate thousands of browsers behind one API, personas, proxies, stealth, CAPTCHA and MFA.",
5
5
  "license": "MIT",
6
6
  "homepage": "https://oyabrowser.com",