browser-use 0.5.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/dist/agent/service.js +2 -0
  2. package/dist/agent/system_prompt.md +269 -0
  3. package/dist/agent/system_prompt_anthropic_flash.md +240 -0
  4. package/dist/agent/system_prompt_browser_use.md +18 -0
  5. package/dist/agent/system_prompt_browser_use_flash.md +15 -0
  6. package/dist/agent/system_prompt_browser_use_no_thinking.md +17 -0
  7. package/dist/agent/system_prompt_flash.md +16 -0
  8. package/dist/agent/system_prompt_flash_anthropic.md +30 -0
  9. package/dist/agent/system_prompt_no_thinking.md +245 -0
  10. package/dist/browser/cloud/index.d.ts +1 -0
  11. package/dist/browser/cloud/index.js +1 -0
  12. package/dist/browser/cloud/management.d.ts +130 -0
  13. package/dist/browser/cloud/management.js +140 -0
  14. package/dist/browser/events.d.ts +61 -3
  15. package/dist/browser/events.js +66 -0
  16. package/dist/browser/profile.d.ts +1 -0
  17. package/dist/browser/profile.js +1 -0
  18. package/dist/browser/session.d.ts +56 -2
  19. package/dist/browser/session.js +596 -24
  20. package/dist/browser/watchdogs/base.js +34 -1
  21. package/dist/browser/watchdogs/captcha-watchdog.d.ts +26 -0
  22. package/dist/browser/watchdogs/captcha-watchdog.js +151 -0
  23. package/dist/browser/watchdogs/index.d.ts +1 -0
  24. package/dist/browser/watchdogs/index.js +1 -0
  25. package/dist/browser/watchdogs/screenshot-watchdog.js +4 -3
  26. package/dist/cli.d.ts +120 -0
  27. package/dist/cli.js +1816 -4
  28. package/dist/controller/service.js +106 -362
  29. package/dist/controller/views.d.ts +9 -6
  30. package/dist/controller/views.js +8 -5
  31. package/dist/filesystem/file-system.js +1 -1
  32. package/dist/llm/litellm/chat.d.ts +11 -0
  33. package/dist/llm/litellm/chat.js +16 -0
  34. package/dist/llm/litellm/index.d.ts +1 -0
  35. package/dist/llm/litellm/index.js +1 -0
  36. package/dist/llm/models.js +29 -3
  37. package/dist/llm/oci-raw/chat.d.ts +64 -0
  38. package/dist/llm/oci-raw/chat.js +350 -0
  39. package/dist/llm/oci-raw/index.d.ts +2 -0
  40. package/dist/llm/oci-raw/index.js +2 -0
  41. package/dist/llm/oci-raw/serializer.d.ts +12 -0
  42. package/dist/llm/oci-raw/serializer.js +128 -0
  43. package/dist/mcp/server.d.ts +1 -0
  44. package/dist/mcp/server.js +62 -13
  45. package/dist/skill-cli/direct.d.ts +100 -0
  46. package/dist/skill-cli/direct.js +984 -0
  47. package/dist/skill-cli/index.d.ts +2 -0
  48. package/dist/skill-cli/index.js +2 -0
  49. package/dist/skill-cli/server.d.ts +2 -0
  50. package/dist/skill-cli/server.js +472 -11
  51. package/dist/skill-cli/tunnel.d.ts +61 -0
  52. package/dist/skill-cli/tunnel.js +257 -0
  53. package/dist/sync/auth.d.ts +8 -0
  54. package/dist/sync/auth.js +12 -0
  55. package/package.json +22 -4
@@ -1,4 +1,20 @@
1
1
  const resolveEventType = (eventTypeRef) => typeof eventTypeRef === 'string' ? eventTypeRef : eventTypeRef.name;
2
+ const LIFECYCLE_EVENT_NAMES = new Set([
3
+ 'BrowserStartEvent',
4
+ 'BrowserStopEvent',
5
+ 'BrowserStoppedEvent',
6
+ 'BrowserLaunchEvent',
7
+ 'BrowserKillEvent',
8
+ 'BrowserConnectedEvent',
9
+ 'BrowserReconnectingEvent',
10
+ 'BrowserReconnectedEvent',
11
+ 'BrowserErrorEvent',
12
+ ]);
13
+ const createConnectionError = (message) => {
14
+ const error = new Error(message);
15
+ error.name = 'ConnectionError';
16
+ return error;
17
+ };
2
18
  export class BaseWatchdog {
3
19
  static LISTENS_TO = [];
4
20
  static EMITS = [];
@@ -32,7 +48,24 @@ export class BaseWatchdog {
32
48
  continue;
33
49
  }
34
50
  const bound = method.bind(this);
35
- this.event_bus.on(event_type, bound, { handler_id });
51
+ const wrapped = async (event) => {
52
+ if (!LIFECYCLE_EVENT_NAMES.has(event_type) &&
53
+ this.browser_session.should_gate_watchdog_events &&
54
+ !this.browser_session.is_cdp_connected) {
55
+ if (this.browser_session.is_reconnecting) {
56
+ await this.browser_session.wait_for_reconnect();
57
+ if (!this.browser_session.is_cdp_connected) {
58
+ throw createConnectionError(`[${this.constructor.name}.${methodName}] Reconnection failed; browser connection is still unavailable`);
59
+ }
60
+ }
61
+ else {
62
+ this.browser_session.logger.debug(`[${this.constructor.name}.${methodName}] Skipped because browser connection is not available`);
63
+ return null;
64
+ }
65
+ }
66
+ return await bound(event);
67
+ };
68
+ this.event_bus.on(event_type, wrapped, { handler_id });
36
69
  this._registeredHandlers.push({ event_type, handler_id });
37
70
  registeredEventTypes.add(event_type);
38
71
  }
@@ -0,0 +1,26 @@
1
+ import { BrowserConnectedEvent, BrowserStoppedEvent, CaptchaSolverFinishedEvent, CaptchaSolverStartedEvent } from '../events.js';
2
+ import { BaseWatchdog } from './base.js';
3
+ type CaptchaResultType = 'success' | 'failed' | 'timeout' | 'unknown';
4
+ export interface CaptchaWaitResult {
5
+ waited: boolean;
6
+ vendor: string;
7
+ url: string;
8
+ duration_ms: number;
9
+ result: CaptchaResultType;
10
+ }
11
+ export declare class CaptchaWatchdog extends BaseWatchdog {
12
+ static LISTENS_TO: (typeof BrowserConnectedEvent | typeof BrowserStoppedEvent)[];
13
+ static EMITS: (typeof CaptchaSolverStartedEvent | typeof CaptchaSolverFinishedEvent)[];
14
+ private _cdpSession;
15
+ private _handlers;
16
+ private _captchaSolving;
17
+ private _captchaInfo;
18
+ private _captchaResult;
19
+ private _captchaDurationMs;
20
+ private _waiters;
21
+ on_BrowserConnectedEvent(): Promise<void>;
22
+ on_BrowserStoppedEvent(): Promise<void>;
23
+ protected onDetached(): void;
24
+ wait_if_captcha_solving(timeoutSeconds?: number): Promise<CaptchaWaitResult | null>;
25
+ }
26
+ export {};
@@ -0,0 +1,151 @@
1
+ import { BrowserConnectedEvent, BrowserStoppedEvent, CaptchaSolverFinishedEvent, CaptchaSolverStartedEvent, } from '../events.js';
2
+ import { BaseWatchdog } from './base.js';
3
+ export class CaptchaWatchdog extends BaseWatchdog {
4
+ static LISTENS_TO = [BrowserConnectedEvent, BrowserStoppedEvent];
5
+ static EMITS = [
6
+ CaptchaSolverStartedEvent,
7
+ CaptchaSolverFinishedEvent,
8
+ ];
9
+ _cdpSession = null;
10
+ _handlers = [];
11
+ _captchaSolving = false;
12
+ _captchaInfo = {
13
+ vendor: 'unknown',
14
+ url: '',
15
+ target_id: '',
16
+ };
17
+ _captchaResult = 'unknown';
18
+ _captchaDurationMs = 0;
19
+ _waiters = new Set();
20
+ async on_BrowserConnectedEvent() {
21
+ if (this._cdpSession) {
22
+ return;
23
+ }
24
+ const page = await this.browser_session.get_current_page();
25
+ if (!page) {
26
+ return;
27
+ }
28
+ try {
29
+ const cdpSession = (await this.browser_session.get_or_create_cdp_session(page));
30
+ const onStarted = (payload) => {
31
+ this._captchaSolving = true;
32
+ this._captchaResult = 'unknown';
33
+ this._captchaDurationMs = 0;
34
+ this._captchaInfo = {
35
+ vendor: String(payload?.vendor ?? 'unknown'),
36
+ url: String(payload?.url ?? ''),
37
+ target_id: String(payload?.targetId ?? ''),
38
+ };
39
+ void this.event_bus.dispatch(new CaptchaSolverStartedEvent({
40
+ target_id: this._captchaInfo.target_id,
41
+ vendor: this._captchaInfo.vendor,
42
+ url: this._captchaInfo.url,
43
+ started_at: Number(payload?.startedAt ?? Date.now()),
44
+ }));
45
+ };
46
+ const onFinished = (payload) => {
47
+ this._captchaSolving = false;
48
+ this._captchaDurationMs = Number(payload?.durationMs ?? 0);
49
+ this._captchaResult = payload?.success ? 'success' : 'failed';
50
+ const vendor = String(payload?.vendor ?? this._captchaInfo.vendor);
51
+ const url = String(payload?.url ?? this._captchaInfo.url);
52
+ const targetId = String(payload?.targetId ?? this._captchaInfo.target_id);
53
+ for (const resolve of this._waiters) {
54
+ resolve();
55
+ }
56
+ this._waiters.clear();
57
+ void this.event_bus.dispatch(new CaptchaSolverFinishedEvent({
58
+ target_id: targetId,
59
+ vendor,
60
+ url,
61
+ duration_ms: this._captchaDurationMs,
62
+ finished_at: Number(payload?.finishedAt ?? Date.now()),
63
+ success: Boolean(payload?.success),
64
+ }));
65
+ };
66
+ cdpSession.on?.('BrowserUse.captchaSolverStarted', onStarted);
67
+ cdpSession.on?.('BrowserUse.captchaSolverFinished', onFinished);
68
+ this._cdpSession = cdpSession;
69
+ this._handlers = [
70
+ { event: 'BrowserUse.captchaSolverStarted', handler: onStarted },
71
+ { event: 'BrowserUse.captchaSolverFinished', handler: onFinished },
72
+ ];
73
+ }
74
+ catch (error) {
75
+ this.browser_session.logger.debug(`CaptchaWatchdog monitoring unavailable: ${error.message}`);
76
+ await this.on_BrowserStoppedEvent();
77
+ }
78
+ }
79
+ async on_BrowserStoppedEvent() {
80
+ this._captchaSolving = false;
81
+ this._captchaResult = 'unknown';
82
+ this._captchaDurationMs = 0;
83
+ this._captchaInfo = { vendor: 'unknown', url: '', target_id: '' };
84
+ for (const resolve of this._waiters) {
85
+ resolve();
86
+ }
87
+ this._waiters.clear();
88
+ if (!this._cdpSession) {
89
+ return;
90
+ }
91
+ for (const { event, handler } of this._handlers) {
92
+ this._cdpSession.off?.(event, handler);
93
+ }
94
+ this._handlers = [];
95
+ try {
96
+ await this._cdpSession.detach?.();
97
+ }
98
+ catch {
99
+ // Ignore detach errors during shutdown.
100
+ }
101
+ finally {
102
+ this._cdpSession = null;
103
+ }
104
+ }
105
+ onDetached() {
106
+ void this.on_BrowserStoppedEvent();
107
+ }
108
+ async wait_if_captcha_solving(timeoutSeconds = 120) {
109
+ if (!this._captchaSolving) {
110
+ return null;
111
+ }
112
+ const vendor = this._captchaInfo.vendor;
113
+ const url = this._captchaInfo.url;
114
+ const timeoutMs = Math.max(0, timeoutSeconds * 1000);
115
+ try {
116
+ await new Promise((resolve, reject) => {
117
+ const onResolved = () => {
118
+ cleanup();
119
+ resolve();
120
+ };
121
+ const timeoutHandle = setTimeout(() => {
122
+ cleanup();
123
+ reject(new Error('timeout'));
124
+ }, timeoutMs);
125
+ const cleanup = () => {
126
+ clearTimeout(timeoutHandle);
127
+ this._waiters.delete(onResolved);
128
+ };
129
+ this._waiters.add(onResolved);
130
+ });
131
+ return {
132
+ waited: true,
133
+ vendor,
134
+ url,
135
+ duration_ms: this._captchaDurationMs,
136
+ result: this._captchaResult,
137
+ };
138
+ }
139
+ catch {
140
+ this._captchaSolving = false;
141
+ this._waiters.clear();
142
+ return {
143
+ waited: true,
144
+ vendor,
145
+ url,
146
+ duration_ms: timeoutMs,
147
+ result: 'timeout',
148
+ };
149
+ }
150
+ }
151
+ }
@@ -1,6 +1,7 @@
1
1
  export * from './base.js';
2
2
  export * from './aboutblank-watchdog.js';
3
3
  export * from './cdp-session-watchdog.js';
4
+ export * from './captcha-watchdog.js';
4
5
  export * from './crash-watchdog.js';
5
6
  export * from './default-action-watchdog.js';
6
7
  export * from './dom-watchdog.js';
@@ -1,6 +1,7 @@
1
1
  export * from './base.js';
2
2
  export * from './aboutblank-watchdog.js';
3
3
  export * from './cdp-session-watchdog.js';
4
+ export * from './captcha-watchdog.js';
4
5
  export * from './crash-watchdog.js';
5
6
  export * from './default-action-watchdog.js';
6
7
  export * from './dom-watchdog.js';
@@ -4,10 +4,11 @@ export class ScreenshotWatchdog extends BaseWatchdog {
4
4
  static LISTENS_TO = [ScreenshotEvent];
5
5
  async on_ScreenshotEvent(event) {
6
6
  try {
7
- return await this.browser_session.take_screenshot(event.full_page);
8
- }
9
- finally {
10
7
  await this.browser_session.remove_highlights();
11
8
  }
9
+ catch {
10
+ // Highlight cleanup is best-effort and should not block screenshots.
11
+ }
12
+ return await this.browser_session.take_screenshot(event.full_page, event.clip);
12
13
  }
13
14
  }
package/dist/cli.d.ts CHANGED
@@ -1,6 +1,10 @@
1
1
  #!/usr/bin/env node
2
+ import { spawnSync } from 'node:child_process';
2
3
  import { BrowserProfile } from './browser/profile.js';
4
+ import { CloudBrowserClient } from './browser/cloud/cloud.js';
5
+ import { CloudManagementClient } from './browser/cloud/management.js';
3
6
  import type { BaseChatModel } from './llm/base.js';
7
+ import { get_tunnel_manager } from './skill-cli/tunnel.js';
4
8
  type CliModelProvider = 'openai' | 'anthropic' | 'google' | 'deepseek' | 'groq' | 'openrouter' | 'azure' | 'mistral' | 'cerebras' | 'vercel' | 'oci' | 'aws-anthropic' | 'aws' | 'ollama' | 'browser-use';
5
9
  export interface ParsedCliArgs {
6
10
  help: boolean;
@@ -21,6 +25,10 @@ export interface ParsedCliArgs {
21
25
  provider: CliModelProvider | null;
22
26
  prompt: string | null;
23
27
  mcp: boolean;
28
+ json: boolean;
29
+ yes: boolean;
30
+ setup_mode: string | null;
31
+ api_key: string | null;
24
32
  positional: string[];
25
33
  }
26
34
  export declare const CLI_HISTORY_LIMIT = 100;
@@ -39,5 +47,117 @@ export declare const shouldStartInteractiveMode: (task: string | null, options?:
39
47
  export declare const getLlmFromCliArgs: (args: ParsedCliArgs) => BaseChatModel;
40
48
  export declare const buildBrowserProfileFromCliArgs: (args: ParsedCliArgs) => BrowserProfile | null;
41
49
  export declare const getCliUsage: () => string;
50
+ export interface RunInstallCommandOptions {
51
+ playwright_cli_path?: string;
52
+ spawn_impl?: typeof spawnSync;
53
+ }
54
+ type WritableLike = {
55
+ write(chunk: string): unknown;
56
+ };
57
+ export interface RunTunnelCommandOptions {
58
+ manager?: Pick<ReturnType<typeof get_tunnel_manager>, 'start_tunnel' | 'list_tunnels' | 'stop_tunnel' | 'stop_all_tunnels'>;
59
+ stdout?: WritableLike;
60
+ stderr?: WritableLike;
61
+ json_output?: boolean;
62
+ }
63
+ export interface RunSetupCommandOptions {
64
+ run_doctor_checks?: (options?: RunDoctorChecksOptions) => Promise<CliDoctorReport>;
65
+ install_command?: () => void | Promise<void>;
66
+ save_api_key?: (api_key: string) => void;
67
+ stdout?: WritableLike;
68
+ stderr?: WritableLike;
69
+ json_output?: boolean;
70
+ }
71
+ export interface RunTaskCommandOptions {
72
+ client?: Pick<CloudManagementClient, 'list_tasks' | 'get_task' | 'update_task' | 'get_task_logs'>;
73
+ stdout?: WritableLike;
74
+ stderr?: WritableLike;
75
+ }
76
+ export interface RunSessionCommandOptions {
77
+ client?: Pick<CloudManagementClient, 'list_sessions' | 'get_session' | 'update_session' | 'create_session' | 'create_session_public_share' | 'delete_session_public_share'>;
78
+ stdout?: WritableLike;
79
+ stderr?: WritableLike;
80
+ }
81
+ export interface RunProfileCommandOptions {
82
+ client?: Pick<CloudManagementClient, 'list_profiles' | 'get_profile' | 'create_profile' | 'update_profile' | 'delete_profile'>;
83
+ profile_lister?: () => Array<{
84
+ directory: string;
85
+ name: string;
86
+ email?: string;
87
+ }>;
88
+ local_session_factory?: (profile_directory: string) => {
89
+ start: () => Promise<unknown>;
90
+ stop?: () => Promise<void>;
91
+ get_cookies?: () => Promise<BrowserCookieInit[]>;
92
+ };
93
+ remote_session_factory?: (init: {
94
+ cdp_url: string;
95
+ }) => {
96
+ start: () => Promise<unknown>;
97
+ stop?: () => Promise<void>;
98
+ browser_context?: {
99
+ addCookies?: (cookies: BrowserCookieInit[]) => Promise<unknown>;
100
+ } | null;
101
+ };
102
+ cloud_browser_client_factory?: () => Pick<CloudBrowserClient, 'create_browser' | 'stop_browser'>;
103
+ stdout?: WritableLike;
104
+ stderr?: WritableLike;
105
+ }
106
+ export interface RunCloudTaskCommandOptions {
107
+ client?: Pick<CloudManagementClient, 'create_task' | 'create_session' | 'get_task' | 'update_session'>;
108
+ stdout?: WritableLike;
109
+ stderr?: WritableLike;
110
+ sleep_impl?: (ms: number) => Promise<void>;
111
+ }
112
+ type BrowserCookieInit = {
113
+ name: string;
114
+ value: string;
115
+ url?: string;
116
+ domain?: string;
117
+ path?: string;
118
+ expires?: number;
119
+ httpOnly?: boolean;
120
+ secure?: boolean;
121
+ sameSite?: 'Strict' | 'Lax' | 'None';
122
+ partitionKey?: string;
123
+ };
124
+ export declare const runInstallCommand: (options?: RunInstallCommandOptions) => void;
125
+ export declare const runTunnelCommand: (argv: string[], options?: RunTunnelCommandOptions) => Promise<0 | 1>;
126
+ export declare const runSetupCommand: (params: {
127
+ mode?: string | null;
128
+ yes?: boolean;
129
+ api_key?: string | null;
130
+ }, options?: RunSetupCommandOptions) => Promise<number>;
131
+ export declare const runTaskCommand: (argv: string[], options?: RunTaskCommandOptions) => Promise<0 | 1>;
132
+ export declare const runSessionCommand: (argv: string[], options?: RunSessionCommandOptions) => Promise<0 | 1>;
133
+ export declare const runProfileCommand: (argv: string[], options?: RunProfileCommandOptions) => Promise<0 | 1>;
134
+ export declare const hasCloudRunFlags: (argv: string[]) => boolean;
135
+ type PrefixedSubcommand = {
136
+ command: 'run' | 'task' | 'session' | 'profile';
137
+ argv: string[];
138
+ debug: boolean;
139
+ forwardedArgs: string[];
140
+ };
141
+ export declare const extractPrefixedSubcommand: (argv: string[]) => PrefixedSubcommand | null;
142
+ export declare const runCloudTaskCommand: (argv: string[], options?: RunCloudTaskCommandOptions) => Promise<0 | 1>;
143
+ export interface CliDoctorCheck {
144
+ status: 'ok' | 'warning' | 'missing' | 'error';
145
+ message: string;
146
+ note?: string;
147
+ fix?: string;
148
+ }
149
+ export interface CliDoctorReport {
150
+ status: 'healthy' | 'issues_found';
151
+ checks: Record<string, CliDoctorCheck>;
152
+ summary: string;
153
+ }
154
+ export interface RunDoctorChecksOptions {
155
+ version?: string;
156
+ browser_executable?: string | null;
157
+ api_key?: string | null;
158
+ cloudflared_path?: string | null;
159
+ fetch_impl?: typeof fetch;
160
+ }
161
+ export declare const runDoctorChecks: (options?: RunDoctorChecksOptions) => Promise<CliDoctorReport>;
42
162
  export declare function main(argv?: string[]): Promise<void>;
43
163
  export {};