@oya-ai/browser 1.0.96 → 1.0.97

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 CHANGED
@@ -142,6 +142,14 @@ var Browser = class {
142
142
  async pressKey(key) {
143
143
  await this.command("press_key", { key });
144
144
  }
145
+ /**
146
+ * Answer a native dialog holding the page. alert() and beforeunload are
147
+ * answered for you; a confirm() or prompt() waits for this, and every other
148
+ * command fails fast with the dialog's text until it is answered.
149
+ */
150
+ async handleDialog(accept, promptText) {
151
+ return this.command("handle_dialog", { accept, prompt_text: promptText });
152
+ }
145
153
  /** `at` aims the wheel at an inner scroller (a results panel, a chat pane) instead of the page. */
146
154
  async scroll(direction, amount, at) {
147
155
  await this.command("scroll", at ? { direction, amount: amount ?? 500, ...at, smooth: false } : { direction, amount });
@@ -557,8 +565,21 @@ var Oya = class {
557
565
  },
558
566
  /** Store the second factor for this identity. Sealed at rest, never read back. */
559
567
  setMfa: (id, config) => this.http.request("PUT", `/api/personas/${id}/mfa`, config),
560
- clearMfa: async (id) => {
561
- await this.http.request("DELETE", `/api/personas/${id}/mfa`);
568
+ clearMfa: async (id, domain) => {
569
+ await this.http.request("DELETE", `/api/personas/${id}/mfa${domain ? `?domain=${encodeURIComponent(domain)}` : ""}`);
570
+ },
571
+ /**
572
+ * Store a site login for this identity. Sealed at rest, never read back.
573
+ *
574
+ * Signing in once on the desktop and inheriting the cookies is still the
575
+ * better path. This is for portals that expire a session server-side
576
+ * between runs, where an unattended run has nothing else to recover with.
577
+ */
578
+ setCredentials: (id, config) => this.http.request("PUT", `/api/personas/${id}/credentials`, config),
579
+ /** Which sites this identity can sign in to. Usernames only. */
580
+ credentials: (id) => this.http.request("GET", `/api/personas/${id}/credentials`),
581
+ clearCredentials: async (id, domain) => {
582
+ await this.http.request("DELETE", `/api/personas/${id}/credentials?domain=${encodeURIComponent(domain)}`);
562
583
  }
563
584
  };
564
585
  /**
package/dist/index.d.cts CHANGED
@@ -163,8 +163,8 @@ interface FileValue {
163
163
  type RunData = Record<string, string | number | FileValue>;
164
164
  interface AttentionRequest {
165
165
  id: string;
166
- /** captcha / mfa: finish it in the live view. agent: the agent's question. heal_failed: replay and the agent both gave up. */
167
- reason: 'captcha' | 'mfa' | 'agent' | 'heal_failed';
166
+ /** captcha / login / mfa: finish it in the live view. agent: the agent's question. heal_failed: replay and the agent both gave up. */
167
+ reason: 'captcha' | 'login' | 'mfa' | 'agent' | 'heal_failed';
168
168
  message: string;
169
169
  liveViewUrl?: string;
170
170
  at: number;
@@ -324,6 +324,18 @@ interface PersonaInfo {
324
324
  mfa: {
325
325
  configured: boolean;
326
326
  type?: string;
327
+ domain?: string;
328
+ };
329
+ /** Per-site factors and stored logins. Usernames and types only, never secrets. */
330
+ sites: {
331
+ mfa: {
332
+ domain: string;
333
+ type: string;
334
+ }[];
335
+ credentials: {
336
+ domain: string;
337
+ username: string;
338
+ }[];
327
339
  };
328
340
  login: {
329
341
  cookies: number;
@@ -349,7 +361,22 @@ interface StopResult {
349
361
  sandboxRemoved?: boolean | null;
350
362
  error?: string;
351
363
  }
364
+ /**
365
+ * A second factor. `domain` files it against one site, because a persona driving
366
+ * several portals meets several kinds of factor; without it the record is the
367
+ * persona-wide default.
368
+ *
369
+ * `gmail` and `graph` read the code straight out of a mailbox. `email` and `sms`
370
+ * poll an endpoint you host — set `x-oya-received-at` on its response (epoch ms)
371
+ * and a code from a previous run will never be reused.
372
+ *
373
+ * The code is pulled out of the message by your own configured LLM, because
374
+ * portals rewrite these templates constantly and the code is not always digits.
375
+ * `pattern` is only the fallback for when no LLM key is set or the call fails.
376
+ */
352
377
  type MfaConfig = {
378
+ domain?: string;
379
+ } & ({
353
380
  type: 'totp';
354
381
  secret: string;
355
382
  } | {
@@ -358,7 +385,22 @@ type MfaConfig = {
358
385
  headers?: Record<string, string>;
359
386
  pattern?: string;
360
387
  timeoutMs?: number;
361
- };
388
+ } | {
389
+ type: 'gmail' | 'graph';
390
+ refreshToken: string;
391
+ clientId: string;
392
+ clientSecret?: string;
393
+ tenant?: string;
394
+ query?: string;
395
+ pattern?: string;
396
+ timeoutMs?: number;
397
+ });
398
+ /** A site login. The password is write-only: no API ever reads it back. */
399
+ interface SiteCredentials {
400
+ domain: string;
401
+ username: string;
402
+ password: string;
403
+ }
362
404
  interface BrowserInfo {
363
405
  id: string;
364
406
  name: string;
@@ -477,6 +519,16 @@ declare class Browser {
477
519
  }>;
478
520
  private elementId;
479
521
  pressKey(key: string): Promise<void>;
522
+ /**
523
+ * Answer a native dialog holding the page. alert() and beforeunload are
524
+ * answered for you; a confirm() or prompt() waits for this, and every other
525
+ * command fails fast with the dialog's text until it is answered.
526
+ */
527
+ handleDialog(accept: boolean, promptText?: string): Promise<{
528
+ type: string;
529
+ message: string;
530
+ accepted: boolean;
531
+ }>;
480
532
  /** `at` aims the wheel at an inner scroller (a results panel, a chat pane) instead of the page. */
481
533
  scroll(direction: 'up' | 'down' | 'top' | 'bottom', amount?: number, at?: {
482
534
  x: number;
@@ -787,7 +839,27 @@ declare class Oya {
787
839
  configured: boolean;
788
840
  type: string;
789
841
  }>;
790
- clearMfa: (id: string) => Promise<void>;
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>;
791
863
  };
792
864
  /**
793
865
  * This key's settings: LLM credentials, browser provider, solver.
@@ -854,10 +926,30 @@ declare class Oya {
854
926
  configured: boolean;
855
927
  type: string;
856
928
  }>;
857
- clearMfa: (id: string) => Promise<void>;
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>;
858
950
  };
859
951
  usage(): Promise<unknown>;
860
952
  private waitUntilConnected;
861
953
  }
862
954
 
863
- export { type Activity, type Analysis, type AttentionRequest, Browser, type BrowserDetail, type BrowserInfo, type CaptchaResult, type CaptchaSolver, type Config, type ConfigUpdate, type ControlCredential, type ControlEvent, type ControlOverview, type ControlRole, type ControlSession, type Element, type FileValue, type Fingerprint, type Health, type HumanInputAction, type LlmProvider, MAX_FILE_BYTES, type MfaConfig, type MfaResult, Oya, OyaError, type OyaOptions, type PersonaInfo, type PersonaPrefs, type PlayResult, type Playbook, type PlaybookSummary, type ProjectSettings, type Provider, type ProxyCreate, type ProxyInfo, Run, type RunData, type RunInfo, type RunResult, type StartOptions, type StartResult, type StopResult, type SubmitOptions, Oya as default, file };
955
+ export { type Activity, type Analysis, type AttentionRequest, Browser, type BrowserDetail, type BrowserInfo, type CaptchaResult, type CaptchaSolver, type Config, type ConfigUpdate, type ControlCredential, type ControlEvent, type ControlOverview, type ControlRole, type ControlSession, type Element, type FileValue, type Fingerprint, type Health, type HumanInputAction, type LlmProvider, MAX_FILE_BYTES, type MfaConfig, type MfaResult, Oya, OyaError, type OyaOptions, type PersonaInfo, type PersonaPrefs, type PlayResult, type Playbook, type PlaybookSummary, type ProjectSettings, type Provider, type ProxyCreate, type ProxyInfo, Run, type RunData, type RunInfo, type RunResult, type SiteCredentials, type StartOptions, type StartResult, type StopResult, type SubmitOptions, Oya as default, file };
package/dist/index.d.ts CHANGED
@@ -163,8 +163,8 @@ interface FileValue {
163
163
  type RunData = Record<string, string | number | FileValue>;
164
164
  interface AttentionRequest {
165
165
  id: string;
166
- /** captcha / mfa: finish it in the live view. agent: the agent's question. heal_failed: replay and the agent both gave up. */
167
- reason: 'captcha' | 'mfa' | 'agent' | 'heal_failed';
166
+ /** captcha / login / mfa: finish it in the live view. agent: the agent's question. heal_failed: replay and the agent both gave up. */
167
+ reason: 'captcha' | 'login' | 'mfa' | 'agent' | 'heal_failed';
168
168
  message: string;
169
169
  liveViewUrl?: string;
170
170
  at: number;
@@ -324,6 +324,18 @@ interface PersonaInfo {
324
324
  mfa: {
325
325
  configured: boolean;
326
326
  type?: string;
327
+ domain?: string;
328
+ };
329
+ /** Per-site factors and stored logins. Usernames and types only, never secrets. */
330
+ sites: {
331
+ mfa: {
332
+ domain: string;
333
+ type: string;
334
+ }[];
335
+ credentials: {
336
+ domain: string;
337
+ username: string;
338
+ }[];
327
339
  };
328
340
  login: {
329
341
  cookies: number;
@@ -349,7 +361,22 @@ interface StopResult {
349
361
  sandboxRemoved?: boolean | null;
350
362
  error?: string;
351
363
  }
364
+ /**
365
+ * A second factor. `domain` files it against one site, because a persona driving
366
+ * several portals meets several kinds of factor; without it the record is the
367
+ * persona-wide default.
368
+ *
369
+ * `gmail` and `graph` read the code straight out of a mailbox. `email` and `sms`
370
+ * poll an endpoint you host — set `x-oya-received-at` on its response (epoch ms)
371
+ * and a code from a previous run will never be reused.
372
+ *
373
+ * The code is pulled out of the message by your own configured LLM, because
374
+ * portals rewrite these templates constantly and the code is not always digits.
375
+ * `pattern` is only the fallback for when no LLM key is set or the call fails.
376
+ */
352
377
  type MfaConfig = {
378
+ domain?: string;
379
+ } & ({
353
380
  type: 'totp';
354
381
  secret: string;
355
382
  } | {
@@ -358,7 +385,22 @@ type MfaConfig = {
358
385
  headers?: Record<string, string>;
359
386
  pattern?: string;
360
387
  timeoutMs?: number;
361
- };
388
+ } | {
389
+ type: 'gmail' | 'graph';
390
+ refreshToken: string;
391
+ clientId: string;
392
+ clientSecret?: string;
393
+ tenant?: string;
394
+ query?: string;
395
+ pattern?: string;
396
+ timeoutMs?: number;
397
+ });
398
+ /** A site login. The password is write-only: no API ever reads it back. */
399
+ interface SiteCredentials {
400
+ domain: string;
401
+ username: string;
402
+ password: string;
403
+ }
362
404
  interface BrowserInfo {
363
405
  id: string;
364
406
  name: string;
@@ -477,6 +519,16 @@ declare class Browser {
477
519
  }>;
478
520
  private elementId;
479
521
  pressKey(key: string): Promise<void>;
522
+ /**
523
+ * Answer a native dialog holding the page. alert() and beforeunload are
524
+ * answered for you; a confirm() or prompt() waits for this, and every other
525
+ * command fails fast with the dialog's text until it is answered.
526
+ */
527
+ handleDialog(accept: boolean, promptText?: string): Promise<{
528
+ type: string;
529
+ message: string;
530
+ accepted: boolean;
531
+ }>;
480
532
  /** `at` aims the wheel at an inner scroller (a results panel, a chat pane) instead of the page. */
481
533
  scroll(direction: 'up' | 'down' | 'top' | 'bottom', amount?: number, at?: {
482
534
  x: number;
@@ -787,7 +839,27 @@ declare class Oya {
787
839
  configured: boolean;
788
840
  type: string;
789
841
  }>;
790
- clearMfa: (id: string) => Promise<void>;
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>;
791
863
  };
792
864
  /**
793
865
  * This key's settings: LLM credentials, browser provider, solver.
@@ -854,10 +926,30 @@ declare class Oya {
854
926
  configured: boolean;
855
927
  type: string;
856
928
  }>;
857
- clearMfa: (id: string) => Promise<void>;
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>;
858
950
  };
859
951
  usage(): Promise<unknown>;
860
952
  private waitUntilConnected;
861
953
  }
862
954
 
863
- export { type Activity, type Analysis, type AttentionRequest, Browser, type BrowserDetail, type BrowserInfo, type CaptchaResult, type CaptchaSolver, type Config, type ConfigUpdate, type ControlCredential, type ControlEvent, type ControlOverview, type ControlRole, type ControlSession, type Element, type FileValue, type Fingerprint, type Health, type HumanInputAction, type LlmProvider, MAX_FILE_BYTES, type MfaConfig, type MfaResult, Oya, OyaError, type OyaOptions, type PersonaInfo, type PersonaPrefs, type PlayResult, type Playbook, type PlaybookSummary, type ProjectSettings, type Provider, type ProxyCreate, type ProxyInfo, Run, type RunData, type RunInfo, type RunResult, type StartOptions, type StartResult, type StopResult, type SubmitOptions, Oya as default, file };
955
+ export { type Activity, type Analysis, type AttentionRequest, Browser, type BrowserDetail, type BrowserInfo, type CaptchaResult, type CaptchaSolver, type Config, type ConfigUpdate, type ControlCredential, type ControlEvent, type ControlOverview, type ControlRole, type ControlSession, type Element, type FileValue, type Fingerprint, type Health, type HumanInputAction, type LlmProvider, MAX_FILE_BYTES, type MfaConfig, type MfaResult, Oya, OyaError, type OyaOptions, type PersonaInfo, type PersonaPrefs, type PlayResult, type Playbook, type PlaybookSummary, type ProjectSettings, type Provider, type ProxyCreate, type ProxyInfo, Run, type RunData, type RunInfo, type RunResult, type SiteCredentials, type StartOptions, type StartResult, type StopResult, type SubmitOptions, Oya as default, file };
package/dist/index.js CHANGED
@@ -110,6 +110,14 @@ var Browser = class {
110
110
  async pressKey(key) {
111
111
  await this.command("press_key", { key });
112
112
  }
113
+ /**
114
+ * Answer a native dialog holding the page. alert() and beforeunload are
115
+ * answered for you; a confirm() or prompt() waits for this, and every other
116
+ * command fails fast with the dialog's text until it is answered.
117
+ */
118
+ async handleDialog(accept, promptText) {
119
+ return this.command("handle_dialog", { accept, prompt_text: promptText });
120
+ }
113
121
  /** `at` aims the wheel at an inner scroller (a results panel, a chat pane) instead of the page. */
114
122
  async scroll(direction, amount, at) {
115
123
  await this.command("scroll", at ? { direction, amount: amount ?? 500, ...at, smooth: false } : { direction, amount });
@@ -525,8 +533,21 @@ var Oya = class {
525
533
  },
526
534
  /** Store the second factor for this identity. Sealed at rest, never read back. */
527
535
  setMfa: (id, config) => this.http.request("PUT", `/api/personas/${id}/mfa`, config),
528
- clearMfa: async (id) => {
529
- await this.http.request("DELETE", `/api/personas/${id}/mfa`);
536
+ clearMfa: async (id, domain) => {
537
+ await this.http.request("DELETE", `/api/personas/${id}/mfa${domain ? `?domain=${encodeURIComponent(domain)}` : ""}`);
538
+ },
539
+ /**
540
+ * Store a site login for this identity. Sealed at rest, never read back.
541
+ *
542
+ * Signing in once on the desktop and inheriting the cookies is still the
543
+ * better path. This is for portals that expire a session server-side
544
+ * between runs, where an unattended run has nothing else to recover with.
545
+ */
546
+ setCredentials: (id, config) => this.http.request("PUT", `/api/personas/${id}/credentials`, config),
547
+ /** Which sites this identity can sign in to. Usernames only. */
548
+ credentials: (id) => this.http.request("GET", `/api/personas/${id}/credentials`),
549
+ clearCredentials: async (id, domain) => {
550
+ await this.http.request("DELETE", `/api/personas/${id}/credentials?domain=${encodeURIComponent(domain)}`);
530
551
  }
531
552
  };
532
553
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oya-ai/browser",
3
- "version": "1.0.96",
3
+ "version": "1.0.97",
4
4
  "description": "Rotate thousands of browsers behind one API — personas, proxies, stealth, CAPTCHA and MFA.",
5
5
  "license": "MIT",
6
6
  "homepage": "https://browser.getoya.ai",