browser-pilot 0.0.16 → 0.0.18
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 +39 -0
- package/dist/actions.cjs +797 -69
- package/dist/actions.d.cts +101 -4
- package/dist/actions.d.ts +101 -4
- package/dist/actions.mjs +17 -1
- package/dist/{browser-ZCR6AA4D.mjs → browser-GHQRYU4R.mjs} +2 -2
- package/dist/browser.cjs +1366 -72
- package/dist/browser.d.cts +230 -6
- package/dist/browser.d.ts +230 -6
- package/dist/browser.mjs +37 -5
- package/dist/{chunk-EZNZ72VA.mjs → chunk-ASEIFKKV.mjs} +126 -0
- package/dist/{chunk-TJ5B56NV.mjs → chunk-FSB25GRR.mjs} +129 -1
- package/dist/chunk-MIJ7UIKB.mjs +96 -0
- package/dist/{chunk-6GBYX7C2.mjs → chunk-MRY3HRFJ.mjs} +799 -353
- package/dist/chunk-OIHU7OFY.mjs +91 -0
- package/dist/{chunk-NNEHWWHL.mjs → chunk-SW52ALBD.mjs} +588 -5
- package/dist/{chunk-V3VLBQAM.mjs → chunk-ZDODXEBD.mjs} +586 -69
- package/dist/cli.mjs +784 -176
- package/dist/combobox-RAKBA2BW.mjs +6 -0
- package/dist/index.cjs +1669 -71
- package/dist/index.d.cts +58 -7
- package/dist/index.d.ts +58 -7
- package/dist/index.mjs +192 -3
- package/dist/{page-IUUTJ3SW.mjs → page-SD64DY3F.mjs} +1 -1
- package/dist/providers.cjs +127 -0
- package/dist/providers.d.cts +38 -3
- package/dist/providers.d.ts +38 -3
- package/dist/providers.mjs +3 -1
- package/dist/{types-BzM-IfsL.d.ts → types-B_v62K7C.d.ts} +146 -2
- package/dist/{types-DeVSWhXj.d.cts → types-D2pJQpWs.d.cts} +7 -1
- package/dist/{types-DeVSWhXj.d.ts → types-D2pJQpWs.d.ts} +7 -1
- package/dist/{types-BflRmiDz.d.cts → types-Yuybzq53.d.cts} +146 -2
- package/dist/upload-E6MCC2OF.mjs +6 -0
- package/package.json +10 -3
|
@@ -2,6 +2,108 @@ import {
|
|
|
2
2
|
createCDPClient
|
|
3
3
|
} from "./chunk-BVZALQT4.mjs";
|
|
4
4
|
|
|
5
|
+
// src/providers/browser-use.ts
|
|
6
|
+
var BrowserUseProvider = class {
|
|
7
|
+
name = "browser-use";
|
|
8
|
+
apiKey;
|
|
9
|
+
baseUrl;
|
|
10
|
+
proxyCountryCode;
|
|
11
|
+
profileId;
|
|
12
|
+
timeout;
|
|
13
|
+
allowResizing;
|
|
14
|
+
customProxy;
|
|
15
|
+
constructor(options) {
|
|
16
|
+
this.apiKey = options.apiKey;
|
|
17
|
+
this.baseUrl = options.baseUrl ?? "https://api.browser-use.com/api/v2";
|
|
18
|
+
this.proxyCountryCode = options.proxyCountryCode === void 0 ? "uk" : options.proxyCountryCode;
|
|
19
|
+
this.profileId = options.profileId;
|
|
20
|
+
this.timeout = options.timeout;
|
|
21
|
+
this.allowResizing = options.allowResizing;
|
|
22
|
+
this.customProxy = options.customProxy;
|
|
23
|
+
}
|
|
24
|
+
async createSession(options = {}) {
|
|
25
|
+
const body = {};
|
|
26
|
+
body["proxyCountryCode"] = this.proxyCountryCode;
|
|
27
|
+
if (options.width) body["browserScreenWidth"] = options.width;
|
|
28
|
+
if (options.height) body["browserScreenHeight"] = options.height;
|
|
29
|
+
if (this.profileId) body["profileId"] = this.profileId;
|
|
30
|
+
if (this.timeout !== void 0) body["timeout"] = this.timeout;
|
|
31
|
+
if (this.allowResizing !== void 0) body["allowResizing"] = this.allowResizing;
|
|
32
|
+
if (this.customProxy) body["customProxy"] = this.customProxy;
|
|
33
|
+
const response = await fetch(`${this.baseUrl}/browsers`, {
|
|
34
|
+
method: "POST",
|
|
35
|
+
headers: {
|
|
36
|
+
"X-Browser-Use-API-Key": this.apiKey,
|
|
37
|
+
"Content-Type": "application/json"
|
|
38
|
+
},
|
|
39
|
+
body: JSON.stringify(body)
|
|
40
|
+
});
|
|
41
|
+
if (!response.ok) {
|
|
42
|
+
const text = await response.text();
|
|
43
|
+
this.throwApiError(response.status, text);
|
|
44
|
+
}
|
|
45
|
+
const session = await response.json();
|
|
46
|
+
if (!session.cdpUrl) {
|
|
47
|
+
throw new Error("Browser Use session does not have a cdpUrl");
|
|
48
|
+
}
|
|
49
|
+
return this.toProviderSession(session);
|
|
50
|
+
}
|
|
51
|
+
async resumeSession(sessionId) {
|
|
52
|
+
const response = await fetch(`${this.baseUrl}/browsers/${sessionId}`, {
|
|
53
|
+
headers: {
|
|
54
|
+
"X-Browser-Use-API-Key": this.apiKey
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
if (!response.ok) {
|
|
58
|
+
const text = await response.text();
|
|
59
|
+
throw new Error(`Browser Use resumeSession failed: ${response.status} ${text}`);
|
|
60
|
+
}
|
|
61
|
+
const session = await response.json();
|
|
62
|
+
if (session.status !== "active" || !session.cdpUrl) {
|
|
63
|
+
throw new Error(
|
|
64
|
+
"Browser Use session is not active or does not have a cdpUrl (may be stopped)"
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
return this.toProviderSession(session);
|
|
68
|
+
}
|
|
69
|
+
toProviderSession(session) {
|
|
70
|
+
return {
|
|
71
|
+
wsUrl: session.cdpUrl,
|
|
72
|
+
sessionId: session.id,
|
|
73
|
+
metadata: {
|
|
74
|
+
liveUrl: session.liveUrl,
|
|
75
|
+
status: session.status,
|
|
76
|
+
timeoutAt: session.timeoutAt,
|
|
77
|
+
proxyCountryCode: this.proxyCountryCode
|
|
78
|
+
},
|
|
79
|
+
close: async () => {
|
|
80
|
+
await fetch(`${this.baseUrl}/browsers/${session.id}`, {
|
|
81
|
+
method: "PATCH",
|
|
82
|
+
headers: {
|
|
83
|
+
"X-Browser-Use-API-Key": this.apiKey,
|
|
84
|
+
"Content-Type": "application/json"
|
|
85
|
+
},
|
|
86
|
+
body: JSON.stringify({ action: "stop" })
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
throwApiError(status, body) {
|
|
92
|
+
switch (status) {
|
|
93
|
+
case 402:
|
|
94
|
+
throw new Error(`Browser Use: insufficient credits (min $0.10 required). ${body}`);
|
|
95
|
+
case 403:
|
|
96
|
+
throw new Error(`Browser Use: invalid API key. ${body}`);
|
|
97
|
+
case 422:
|
|
98
|
+
throw new Error(`Browser Use: validation error. ${body}`);
|
|
99
|
+
case 429:
|
|
100
|
+
throw new Error(`Browser Use: rate limit exceeded. ${body}`);
|
|
101
|
+
default:
|
|
102
|
+
throw new Error(`Browser Use createSession failed: ${status} ${body}`);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
|
|
5
107
|
// src/providers/browserbase.ts
|
|
6
108
|
var BrowserBaseProvider = class {
|
|
7
109
|
name = "browserbase";
|
|
@@ -514,6 +616,17 @@ async function resolveBrowserEndpoint(options = {}, deps = defaultDependencies)
|
|
|
514
616
|
);
|
|
515
617
|
}
|
|
516
618
|
|
|
619
|
+
// src/runtime/env.ts
|
|
620
|
+
function getProcessEnv() {
|
|
621
|
+
if (typeof globalThis.process !== "undefined" && globalThis.process.env) {
|
|
622
|
+
return globalThis.process.env;
|
|
623
|
+
}
|
|
624
|
+
return {};
|
|
625
|
+
}
|
|
626
|
+
function getEnv(name) {
|
|
627
|
+
return getProcessEnv()[name];
|
|
628
|
+
}
|
|
629
|
+
|
|
517
630
|
// src/providers/index.ts
|
|
518
631
|
function createProvider(options) {
|
|
519
632
|
switch (options.provider) {
|
|
@@ -535,6 +648,18 @@ function createProvider(options) {
|
|
|
535
648
|
return new BrowserlessProvider({
|
|
536
649
|
token: options.apiKey
|
|
537
650
|
});
|
|
651
|
+
case "browser-use": {
|
|
652
|
+
const apiKey = options.apiKey ?? getEnv("BROWSER_USE_API_KEY");
|
|
653
|
+
if (!apiKey) {
|
|
654
|
+
throw new Error("Browser Use provider requires apiKey or BROWSER_USE_API_KEY env var");
|
|
655
|
+
}
|
|
656
|
+
return new BrowserUseProvider({
|
|
657
|
+
apiKey,
|
|
658
|
+
proxyCountryCode: options.proxyCountryCode === void 0 ? "uk" : options.proxyCountryCode,
|
|
659
|
+
profileId: options.profileId,
|
|
660
|
+
timeout: options.cloudTimeout
|
|
661
|
+
});
|
|
662
|
+
}
|
|
538
663
|
case "generic":
|
|
539
664
|
if (!options.wsUrl) {
|
|
540
665
|
throw new Error("Generic provider requires wsUrl");
|
|
@@ -548,6 +673,7 @@ function createProvider(options) {
|
|
|
548
673
|
}
|
|
549
674
|
|
|
550
675
|
export {
|
|
676
|
+
BrowserUseProvider,
|
|
551
677
|
BrowserBaseProvider,
|
|
552
678
|
BrowserlessProvider,
|
|
553
679
|
GenericProvider,
|
|
@@ -3,7 +3,109 @@ import {
|
|
|
3
3
|
} from "./chunk-LCNFBXB5.mjs";
|
|
4
4
|
import {
|
|
5
5
|
Page
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-MRY3HRFJ.mjs";
|
|
7
|
+
|
|
8
|
+
// src/providers/browser-use.ts
|
|
9
|
+
var BrowserUseProvider = class {
|
|
10
|
+
name = "browser-use";
|
|
11
|
+
apiKey;
|
|
12
|
+
baseUrl;
|
|
13
|
+
proxyCountryCode;
|
|
14
|
+
profileId;
|
|
15
|
+
timeout;
|
|
16
|
+
allowResizing;
|
|
17
|
+
customProxy;
|
|
18
|
+
constructor(options) {
|
|
19
|
+
this.apiKey = options.apiKey;
|
|
20
|
+
this.baseUrl = options.baseUrl ?? "https://api.browser-use.com/api/v2";
|
|
21
|
+
this.proxyCountryCode = options.proxyCountryCode === void 0 ? "uk" : options.proxyCountryCode;
|
|
22
|
+
this.profileId = options.profileId;
|
|
23
|
+
this.timeout = options.timeout;
|
|
24
|
+
this.allowResizing = options.allowResizing;
|
|
25
|
+
this.customProxy = options.customProxy;
|
|
26
|
+
}
|
|
27
|
+
async createSession(options = {}) {
|
|
28
|
+
const body = {};
|
|
29
|
+
body["proxyCountryCode"] = this.proxyCountryCode;
|
|
30
|
+
if (options.width) body["browserScreenWidth"] = options.width;
|
|
31
|
+
if (options.height) body["browserScreenHeight"] = options.height;
|
|
32
|
+
if (this.profileId) body["profileId"] = this.profileId;
|
|
33
|
+
if (this.timeout !== void 0) body["timeout"] = this.timeout;
|
|
34
|
+
if (this.allowResizing !== void 0) body["allowResizing"] = this.allowResizing;
|
|
35
|
+
if (this.customProxy) body["customProxy"] = this.customProxy;
|
|
36
|
+
const response = await fetch(`${this.baseUrl}/browsers`, {
|
|
37
|
+
method: "POST",
|
|
38
|
+
headers: {
|
|
39
|
+
"X-Browser-Use-API-Key": this.apiKey,
|
|
40
|
+
"Content-Type": "application/json"
|
|
41
|
+
},
|
|
42
|
+
body: JSON.stringify(body)
|
|
43
|
+
});
|
|
44
|
+
if (!response.ok) {
|
|
45
|
+
const text = await response.text();
|
|
46
|
+
this.throwApiError(response.status, text);
|
|
47
|
+
}
|
|
48
|
+
const session = await response.json();
|
|
49
|
+
if (!session.cdpUrl) {
|
|
50
|
+
throw new Error("Browser Use session does not have a cdpUrl");
|
|
51
|
+
}
|
|
52
|
+
return this.toProviderSession(session);
|
|
53
|
+
}
|
|
54
|
+
async resumeSession(sessionId) {
|
|
55
|
+
const response = await fetch(`${this.baseUrl}/browsers/${sessionId}`, {
|
|
56
|
+
headers: {
|
|
57
|
+
"X-Browser-Use-API-Key": this.apiKey
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
if (!response.ok) {
|
|
61
|
+
const text = await response.text();
|
|
62
|
+
throw new Error(`Browser Use resumeSession failed: ${response.status} ${text}`);
|
|
63
|
+
}
|
|
64
|
+
const session = await response.json();
|
|
65
|
+
if (session.status !== "active" || !session.cdpUrl) {
|
|
66
|
+
throw new Error(
|
|
67
|
+
"Browser Use session is not active or does not have a cdpUrl (may be stopped)"
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
return this.toProviderSession(session);
|
|
71
|
+
}
|
|
72
|
+
toProviderSession(session) {
|
|
73
|
+
return {
|
|
74
|
+
wsUrl: session.cdpUrl,
|
|
75
|
+
sessionId: session.id,
|
|
76
|
+
metadata: {
|
|
77
|
+
liveUrl: session.liveUrl,
|
|
78
|
+
status: session.status,
|
|
79
|
+
timeoutAt: session.timeoutAt,
|
|
80
|
+
proxyCountryCode: this.proxyCountryCode
|
|
81
|
+
},
|
|
82
|
+
close: async () => {
|
|
83
|
+
await fetch(`${this.baseUrl}/browsers/${session.id}`, {
|
|
84
|
+
method: "PATCH",
|
|
85
|
+
headers: {
|
|
86
|
+
"X-Browser-Use-API-Key": this.apiKey,
|
|
87
|
+
"Content-Type": "application/json"
|
|
88
|
+
},
|
|
89
|
+
body: JSON.stringify({ action: "stop" })
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
throwApiError(status, body) {
|
|
95
|
+
switch (status) {
|
|
96
|
+
case 402:
|
|
97
|
+
throw new Error(`Browser Use: insufficient credits (min $0.10 required). ${body}`);
|
|
98
|
+
case 403:
|
|
99
|
+
throw new Error(`Browser Use: invalid API key. ${body}`);
|
|
100
|
+
case 422:
|
|
101
|
+
throw new Error(`Browser Use: validation error. ${body}`);
|
|
102
|
+
case 429:
|
|
103
|
+
throw new Error(`Browser Use: rate limit exceeded. ${body}`);
|
|
104
|
+
default:
|
|
105
|
+
throw new Error(`Browser Use createSession failed: ${status} ${body}`);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
};
|
|
7
109
|
|
|
8
110
|
// src/providers/browserbase.ts
|
|
9
111
|
var BrowserBaseProvider = class {
|
|
@@ -514,6 +616,17 @@ async function resolveBrowserEndpoint(options = {}, deps = defaultDependencies)
|
|
|
514
616
|
);
|
|
515
617
|
}
|
|
516
618
|
|
|
619
|
+
// src/runtime/env.ts
|
|
620
|
+
function getProcessEnv() {
|
|
621
|
+
if (typeof globalThis.process !== "undefined" && globalThis.process.env) {
|
|
622
|
+
return globalThis.process.env;
|
|
623
|
+
}
|
|
624
|
+
return {};
|
|
625
|
+
}
|
|
626
|
+
function getEnv(name) {
|
|
627
|
+
return getProcessEnv()[name];
|
|
628
|
+
}
|
|
629
|
+
|
|
517
630
|
// src/providers/index.ts
|
|
518
631
|
function createProvider(options) {
|
|
519
632
|
switch (options.provider) {
|
|
@@ -535,6 +648,18 @@ function createProvider(options) {
|
|
|
535
648
|
return new BrowserlessProvider({
|
|
536
649
|
token: options.apiKey
|
|
537
650
|
});
|
|
651
|
+
case "browser-use": {
|
|
652
|
+
const apiKey = options.apiKey ?? getEnv("BROWSER_USE_API_KEY");
|
|
653
|
+
if (!apiKey) {
|
|
654
|
+
throw new Error("Browser Use provider requires apiKey or BROWSER_USE_API_KEY env var");
|
|
655
|
+
}
|
|
656
|
+
return new BrowserUseProvider({
|
|
657
|
+
apiKey,
|
|
658
|
+
proxyCountryCode: options.proxyCountryCode === void 0 ? "uk" : options.proxyCountryCode,
|
|
659
|
+
profileId: options.profileId,
|
|
660
|
+
timeout: options.cloudTimeout
|
|
661
|
+
});
|
|
662
|
+
}
|
|
538
663
|
case "generic":
|
|
539
664
|
if (!options.wsUrl) {
|
|
540
665
|
throw new Error("Generic provider requires wsUrl");
|
|
@@ -611,6 +736,9 @@ var Browser = class _Browser {
|
|
|
611
736
|
}
|
|
612
737
|
const provider = createProvider(connectOptions);
|
|
613
738
|
const session = await provider.createSession(connectOptions.session);
|
|
739
|
+
if (session.metadata?.["liveUrl"]) {
|
|
740
|
+
console.error(`Live viewer: ${session.metadata["liveUrl"]}`);
|
|
741
|
+
}
|
|
614
742
|
const cdp = await createCDPClient(session.wsUrl, {
|
|
615
743
|
debug: connectOptions.debug,
|
|
616
744
|
timeout: connectOptions.timeout
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
// src/browser/combobox.ts
|
|
2
|
+
var DEFAULT_LISTBOX_SELECTORS = [
|
|
3
|
+
'[role="listbox"]',
|
|
4
|
+
'[role="menu"]',
|
|
5
|
+
'[role="tree"]',
|
|
6
|
+
'ul[class*="dropdown"]',
|
|
7
|
+
'ul[class*="option"]',
|
|
8
|
+
'ul[class*="list"]',
|
|
9
|
+
'div[class*="dropdown"]',
|
|
10
|
+
'div[class*="menu"]'
|
|
11
|
+
];
|
|
12
|
+
var DEFAULT_OPTION_SELECTORS = [
|
|
13
|
+
'[role="option"]',
|
|
14
|
+
'[role="menuitem"]',
|
|
15
|
+
'[role="treeitem"]',
|
|
16
|
+
"li"
|
|
17
|
+
];
|
|
18
|
+
async function chooseOption(page, config) {
|
|
19
|
+
const {
|
|
20
|
+
trigger,
|
|
21
|
+
listbox,
|
|
22
|
+
optionSelector,
|
|
23
|
+
searchText,
|
|
24
|
+
value,
|
|
25
|
+
match = "contains",
|
|
26
|
+
timeout = 1e4
|
|
27
|
+
} = config;
|
|
28
|
+
try {
|
|
29
|
+
await page.click(trigger, { timeout });
|
|
30
|
+
const listboxSelectors = listbox ? Array.isArray(listbox) ? listbox : [listbox] : DEFAULT_LISTBOX_SELECTORS;
|
|
31
|
+
const listboxFound = await page.waitFor(listboxSelectors, {
|
|
32
|
+
timeout: Math.min(timeout, 3e3),
|
|
33
|
+
optional: true,
|
|
34
|
+
state: "visible"
|
|
35
|
+
});
|
|
36
|
+
if (!listboxFound) {
|
|
37
|
+
return {
|
|
38
|
+
success: false,
|
|
39
|
+
failedAt: "open",
|
|
40
|
+
error: "Listbox did not appear after clicking trigger"
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
if (searchText) {
|
|
44
|
+
try {
|
|
45
|
+
const triggerSel = Array.isArray(trigger) ? trigger[0] : trigger;
|
|
46
|
+
await page.type(triggerSel, searchText, {
|
|
47
|
+
delay: 30,
|
|
48
|
+
timeout: Math.min(timeout, 3e3)
|
|
49
|
+
});
|
|
50
|
+
await new Promise((resolve) => setTimeout(resolve, 200));
|
|
51
|
+
} catch {
|
|
52
|
+
return { success: false, failedAt: "search", error: "Failed to type search text" };
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
const optionSelectors = optionSelector ? [optionSelector] : DEFAULT_OPTION_SELECTORS;
|
|
56
|
+
const matchFn = match === "exact" ? "exact" : match === "startsWith" ? "startsWith" : "contains";
|
|
57
|
+
const clickedOption = await page.evaluate(`(() => {
|
|
58
|
+
const selectors = ${JSON.stringify(optionSelectors)};
|
|
59
|
+
const targetValue = ${JSON.stringify(value)};
|
|
60
|
+
const matchMode = ${JSON.stringify(matchFn)};
|
|
61
|
+
|
|
62
|
+
for (const sel of selectors) {
|
|
63
|
+
const options = document.querySelectorAll(sel);
|
|
64
|
+
for (const opt of options) {
|
|
65
|
+
const text = (opt.textContent || '').trim();
|
|
66
|
+
let matches = false;
|
|
67
|
+
if (matchMode === 'exact') matches = text === targetValue;
|
|
68
|
+
else if (matchMode === 'startsWith') matches = text.startsWith(targetValue);
|
|
69
|
+
else matches = text.includes(targetValue);
|
|
70
|
+
|
|
71
|
+
if (matches) {
|
|
72
|
+
opt.click();
|
|
73
|
+
return text;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return null;
|
|
78
|
+
})()`);
|
|
79
|
+
if (!clickedOption) {
|
|
80
|
+
return { success: false, failedAt: "select", error: `No option matching "${value}" found` };
|
|
81
|
+
}
|
|
82
|
+
return {
|
|
83
|
+
success: true,
|
|
84
|
+
selectedText: String(clickedOption)
|
|
85
|
+
};
|
|
86
|
+
} catch (error) {
|
|
87
|
+
return {
|
|
88
|
+
success: false,
|
|
89
|
+
error: error instanceof Error ? error.message : String(error)
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export {
|
|
95
|
+
chooseOption
|
|
96
|
+
};
|