@crawlee/stagehand 4.0.0-beta.99 → 4.0.0-rc.1
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 +1 -1
- package/index.d.ts +4 -3
- package/index.js +5 -3
- package/index.mjs +26 -15
- package/internals/stagehand-browser-pool.d.ts +63 -0
- package/internals/stagehand-browser-pool.js +55 -0
- package/internals/stagehand-controller.d.ts +1 -16
- package/internals/stagehand-controller.js +12 -12
- package/internals/stagehand-crawler.d.ts +140 -128
- package/internals/stagehand-crawler.js +45 -26
- package/internals/stagehand-launcher.d.ts +34 -36
- package/internals/stagehand-launcher.js +22 -13
- package/internals/stagehand-plugin.d.ts +3 -17
- package/internals/stagehand-plugin.js +20 -26
- package/package.json +12 -18
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.StagehandLauncher = void 0;
|
|
4
|
-
const tslib_1 = require("tslib");
|
|
5
4
|
const browser_1 = require("@crawlee/browser");
|
|
6
|
-
const
|
|
5
|
+
const internal_1 = require("@crawlee/utils/internal");
|
|
6
|
+
const zod_1 = require("zod");
|
|
7
7
|
const stagehand_plugin_1 = require("./stagehand-plugin");
|
|
8
8
|
/**
|
|
9
9
|
* StagehandLauncher is based on BrowserLauncher and creates StagehandPlugin instances.
|
|
@@ -13,31 +13,40 @@ const stagehand_plugin_1 = require("./stagehand-plugin");
|
|
|
13
13
|
*/
|
|
14
14
|
class StagehandLauncher extends browser_1.BrowserLauncher {
|
|
15
15
|
configuration;
|
|
16
|
+
/**
|
|
17
|
+
* @internal
|
|
18
|
+
*/
|
|
16
19
|
static optionsShape = {
|
|
17
20
|
...browser_1.BrowserLauncher.optionsShape,
|
|
18
|
-
launcher
|
|
19
|
-
|
|
20
|
-
|
|
21
|
+
// Passthrough schemas — the launcher module object must keep its prototype through parsing.
|
|
22
|
+
launcher: internal_1.schemas.anyObject.optional(),
|
|
23
|
+
launchContextOptions: internal_1.schemas.anyObject.optional(),
|
|
24
|
+
stagehandOptions: internal_1.schemas.anyObject.optional(),
|
|
21
25
|
};
|
|
22
|
-
|
|
26
|
+
/** @internal */
|
|
27
|
+
static optionsSchema = zod_1.z.strictObject(StagehandLauncher.optionsShape);
|
|
28
|
+
#stagehandOptions;
|
|
23
29
|
/**
|
|
24
30
|
* All StagehandLauncher parameters are passed via the launchContext object.
|
|
25
31
|
*/
|
|
26
|
-
constructor(
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
32
|
+
constructor(
|
|
33
|
+
// `stagehandOptions` is not part of the public `StagehandLaunchContext`: it is how
|
|
34
|
+
// `stagehandBrowserPool()` threads the crawler's resolved Stagehand options through the launcher.
|
|
35
|
+
launchContext = {}, configuration = browser_1.Configuration.getGlobalConfiguration()) {
|
|
36
|
+
const parsedContext = (0, internal_1.parseArgument)(launchContext, StagehandLauncher.optionsSchema, 'StagehandLaunchContext');
|
|
37
|
+
const { launcher = browser_1.BrowserLauncher.requireLauncherOrThrow('playwright', 'apify/actor-node-playwright-*').chromium, stagehandOptions = {}, } = parsedContext;
|
|
38
|
+
const { launchOptions = {}, ...rest } = parsedContext;
|
|
30
39
|
// Call super first before initializing properties
|
|
31
40
|
super({
|
|
32
41
|
...rest,
|
|
33
42
|
launchOptions: {
|
|
34
43
|
...launchOptions,
|
|
35
|
-
executablePath: getDefaultExecutablePath(
|
|
44
|
+
executablePath: getDefaultExecutablePath(parsedContext, configuration),
|
|
36
45
|
},
|
|
37
46
|
launcher,
|
|
38
47
|
}, configuration);
|
|
39
48
|
this.configuration = configuration;
|
|
40
|
-
this
|
|
49
|
+
this.#stagehandOptions = {
|
|
41
50
|
env: 'LOCAL',
|
|
42
51
|
model: 'openai/gpt-4.1-mini',
|
|
43
52
|
...stagehandOptions,
|
|
@@ -52,7 +61,7 @@ class StagehandLauncher extends browser_1.BrowserLauncher {
|
|
|
52
61
|
...this.otherLaunchContextProps,
|
|
53
62
|
proxyUrl: this.proxyUrl,
|
|
54
63
|
launchOptions: this.createLaunchOptions(),
|
|
55
|
-
stagehandOptions: this
|
|
64
|
+
stagehandOptions: this.#stagehandOptions, // Set AFTER to override any unresolved options
|
|
56
65
|
});
|
|
57
66
|
}
|
|
58
67
|
}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import type { Stagehand } from '@browserbasehq/stagehand';
|
|
2
1
|
import type { BrowserController, BrowserPluginOptions, LaunchContext } from '@crawlee/browser-pool';
|
|
3
2
|
import { BrowserPlugin } from '@crawlee/browser-pool';
|
|
4
3
|
// @ts-ignore optional peer dependency or compatibility with es2022
|
|
@@ -27,17 +26,12 @@ export interface StagehandPluginOptions extends BrowserPluginOptions<LaunchOptio
|
|
|
27
26
|
* - Some fingerprinting options may not be fully applied (Stagehand controls browser launch)
|
|
28
27
|
*/
|
|
29
28
|
export declare class StagehandPlugin extends BrowserPlugin<BrowserType, LaunchOptions, PlaywrightBrowser> {
|
|
30
|
-
|
|
31
|
-
private readonly stagehandInstances;
|
|
29
|
+
#private;
|
|
32
30
|
constructor(library: BrowserType, options?: StagehandPluginOptions);
|
|
33
31
|
/**
|
|
34
32
|
* Launches a browser using Stagehand and connects Playwright to it via CDP.
|
|
35
33
|
*/
|
|
36
34
|
protected _launch(launchContext: LaunchContext<BrowserType>): Promise<PlaywrightBrowser>;
|
|
37
|
-
/**
|
|
38
|
-
* Cleans up Stagehand instance when browser disconnects.
|
|
39
|
-
*/
|
|
40
|
-
private _cleanupStagehand;
|
|
41
35
|
/**
|
|
42
36
|
* Creates a controller for the Stagehand browser.
|
|
43
37
|
*/
|
|
@@ -45,17 +39,9 @@ export declare class StagehandPlugin extends BrowserPlugin<BrowserType, LaunchOp
|
|
|
45
39
|
/**
|
|
46
40
|
* Adds proxy configuration to launch options.
|
|
47
41
|
*/
|
|
48
|
-
protected
|
|
42
|
+
protected addProxyToLaunchOptions(launchContext: LaunchContext<BrowserType>): Promise<void>;
|
|
49
43
|
/**
|
|
50
44
|
* Determines if this is a Chromium-based browser.
|
|
51
45
|
*/
|
|
52
|
-
protected
|
|
53
|
-
/**
|
|
54
|
-
* Augments launch errors with helpful context.
|
|
55
|
-
*/
|
|
56
|
-
private _augmentLaunchError;
|
|
57
|
-
/**
|
|
58
|
-
* Gets the Stagehand instance for a given browser.
|
|
59
|
-
*/
|
|
60
|
-
getStagehandForBrowser(browser: PlaywrightBrowser): Stagehand | undefined;
|
|
46
|
+
protected isChromiumBasedBrowser(): boolean;
|
|
61
47
|
}
|
|
@@ -21,11 +21,11 @@ const stagehand_controller_1 = require("./stagehand-controller");
|
|
|
21
21
|
* - Some fingerprinting options may not be fully applied (Stagehand controls browser launch)
|
|
22
22
|
*/
|
|
23
23
|
class StagehandPlugin extends browser_pool_1.BrowserPlugin {
|
|
24
|
-
stagehandOptions;
|
|
25
|
-
stagehandInstances = new WeakMap();
|
|
24
|
+
#stagehandOptions;
|
|
25
|
+
#stagehandInstances = new WeakMap();
|
|
26
26
|
constructor(library, options = {}) {
|
|
27
27
|
super(library, options);
|
|
28
|
-
this
|
|
28
|
+
this.#stagehandOptions = options.stagehandOptions ?? {};
|
|
29
29
|
}
|
|
30
30
|
/**
|
|
31
31
|
* Launches a browser using Stagehand and connects Playwright to it via CDP.
|
|
@@ -34,26 +34,26 @@ class StagehandPlugin extends browser_pool_1.BrowserPlugin {
|
|
|
34
34
|
const { launchOptions = {}, proxyUrl } = launchContext;
|
|
35
35
|
// Import Stagehand dynamically to avoid peer dependency issues
|
|
36
36
|
const { Stagehand } = await import('@browserbasehq/stagehand');
|
|
37
|
-
const isLocal = this
|
|
37
|
+
const isLocal = this.#stagehandOptions.env === 'LOCAL' || !this.#stagehandOptions.env;
|
|
38
38
|
// Use anonymizeProxy to handle proxy authentication transparently
|
|
39
39
|
const [anonymizedProxyUrl, closeAnonymizedProxy] = await (0, browser_pool_1.anonymizeProxySugar)(proxyUrl, undefined, undefined, {
|
|
40
40
|
ignoreProxyCertificate: launchContext.ignoreProxyCertificate,
|
|
41
41
|
});
|
|
42
42
|
// Build model configuration
|
|
43
43
|
// For LOCAL env, we merge apiKey into the model config since Stagehand expects it there
|
|
44
|
-
let modelConfig = this
|
|
45
|
-
if (isLocal && this
|
|
44
|
+
let modelConfig = this.#stagehandOptions.model;
|
|
45
|
+
if (isLocal && this.#stagehandOptions.apiKey) {
|
|
46
46
|
const modelName = typeof modelConfig === 'string' ? modelConfig : modelConfig?.modelName;
|
|
47
47
|
modelConfig = {
|
|
48
48
|
...(typeof modelConfig === 'object' ? modelConfig : {}),
|
|
49
49
|
...(modelName ? { modelName } : {}),
|
|
50
|
-
apiKey: this
|
|
50
|
+
apiKey: this.#stagehandOptions.apiKey,
|
|
51
51
|
};
|
|
52
52
|
}
|
|
53
53
|
// Build Stagehand configuration by spreading our options and adding launch options
|
|
54
54
|
const stagehandConfig = {
|
|
55
|
-
...this
|
|
56
|
-
env: this
|
|
55
|
+
...this.#stagehandOptions,
|
|
56
|
+
env: this.#stagehandOptions.env ?? 'LOCAL',
|
|
57
57
|
model: modelConfig,
|
|
58
58
|
localBrowserLaunchOptions: isLocal
|
|
59
59
|
? {
|
|
@@ -76,10 +76,10 @@ class StagehandPlugin extends browser_pool_1.BrowserPlugin {
|
|
|
76
76
|
}
|
|
77
77
|
const browser = await playwright_1.chromium.connectOverCDP(cdpUrl);
|
|
78
78
|
// Store the Stagehand instance for AI operations
|
|
79
|
-
this
|
|
79
|
+
this.#stagehandInstances.set(browser, stagehand);
|
|
80
80
|
// Handle browser disconnection - cleanup both Stagehand and anonymized proxy
|
|
81
81
|
browser.on('disconnected', async () => {
|
|
82
|
-
await this
|
|
82
|
+
await this.#cleanupStagehand(browser);
|
|
83
83
|
await closeAnonymizedProxy();
|
|
84
84
|
});
|
|
85
85
|
return browser;
|
|
@@ -88,7 +88,7 @@ class StagehandPlugin extends browser_pool_1.BrowserPlugin {
|
|
|
88
88
|
// Clean up on failure
|
|
89
89
|
await stagehand.close().catch(() => { });
|
|
90
90
|
await closeAnonymizedProxy();
|
|
91
|
-
const augmentedError = this
|
|
91
|
+
const augmentedError = this.#augmentLaunchError(error, launchContext);
|
|
92
92
|
core_1.serviceLocator.getLogger().error('Stagehand browser launch failed', { message: augmentedError.message });
|
|
93
93
|
throw augmentedError;
|
|
94
94
|
}
|
|
@@ -96,8 +96,8 @@ class StagehandPlugin extends browser_pool_1.BrowserPlugin {
|
|
|
96
96
|
/**
|
|
97
97
|
* Cleans up Stagehand instance when browser disconnects.
|
|
98
98
|
*/
|
|
99
|
-
async
|
|
100
|
-
const stagehand = this
|
|
99
|
+
async #cleanupStagehand(browser) {
|
|
100
|
+
const stagehand = this.#stagehandInstances.get(browser);
|
|
101
101
|
if (stagehand) {
|
|
102
102
|
try {
|
|
103
103
|
await stagehand.close();
|
|
@@ -105,19 +105,19 @@ class StagehandPlugin extends browser_pool_1.BrowserPlugin {
|
|
|
105
105
|
catch {
|
|
106
106
|
// Ignore cleanup errors
|
|
107
107
|
}
|
|
108
|
-
this
|
|
108
|
+
this.#stagehandInstances.delete(browser);
|
|
109
109
|
}
|
|
110
110
|
}
|
|
111
111
|
/**
|
|
112
112
|
* Creates a controller for the Stagehand browser.
|
|
113
113
|
*/
|
|
114
114
|
createController() {
|
|
115
|
-
return new stagehand_controller_1.StagehandController(this, this
|
|
115
|
+
return new stagehand_controller_1.StagehandController(this, this.#stagehandInstances);
|
|
116
116
|
}
|
|
117
117
|
/**
|
|
118
118
|
* Adds proxy configuration to launch options.
|
|
119
119
|
*/
|
|
120
|
-
async
|
|
120
|
+
async addProxyToLaunchOptions(launchContext) {
|
|
121
121
|
launchContext.launchOptions ??= {};
|
|
122
122
|
const { launchOptions, proxyUrl } = launchContext;
|
|
123
123
|
if (proxyUrl) {
|
|
@@ -132,16 +132,16 @@ class StagehandPlugin extends browser_pool_1.BrowserPlugin {
|
|
|
132
132
|
/**
|
|
133
133
|
* Determines if this is a Chromium-based browser.
|
|
134
134
|
*/
|
|
135
|
-
|
|
135
|
+
isChromiumBasedBrowser() {
|
|
136
136
|
const name = this.library?.name?.();
|
|
137
137
|
return name === 'chromium';
|
|
138
138
|
}
|
|
139
139
|
/**
|
|
140
140
|
* Augments launch errors with helpful context.
|
|
141
141
|
*/
|
|
142
|
-
|
|
142
|
+
#augmentLaunchError(error, launchContext) {
|
|
143
143
|
const message = error instanceof Error ? error.message : String(error);
|
|
144
|
-
const model = this
|
|
144
|
+
const model = this.#stagehandOptions.model;
|
|
145
145
|
let helpText = '';
|
|
146
146
|
if (typeof model === 'string') {
|
|
147
147
|
const modelStr = model.toLowerCase();
|
|
@@ -159,11 +159,5 @@ class StagehandPlugin extends browser_pool_1.BrowserPlugin {
|
|
|
159
159
|
`Executable path: ${launchContext.launchOptions?.executablePath ?? 'default'}\n` +
|
|
160
160
|
`Model: ${model}${helpText}`, { cause: error });
|
|
161
161
|
}
|
|
162
|
-
/**
|
|
163
|
-
* Gets the Stagehand instance for a given browser.
|
|
164
|
-
*/
|
|
165
|
-
getStagehandForBrowser(browser) {
|
|
166
|
-
return this.stagehandInstances.get(browser);
|
|
167
|
-
}
|
|
168
162
|
}
|
|
169
163
|
exports.StagehandPlugin = StagehandPlugin;
|
package/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@crawlee/stagehand",
|
|
3
|
-
"version": "4.0.0-
|
|
3
|
+
"version": "4.0.0-rc.1",
|
|
4
4
|
"description": "AI-powered web crawling with Stagehand integration for Crawlee - enables natural language browser automation with act(), extract(), and observe() methods.",
|
|
5
5
|
"engines": {
|
|
6
|
-
"node": ">=22.
|
|
6
|
+
"node": ">=22.13.0"
|
|
7
7
|
},
|
|
8
8
|
"main": "./index.js",
|
|
9
9
|
"module": "./index.mjs",
|
|
@@ -56,19 +56,17 @@
|
|
|
56
56
|
"access": "public"
|
|
57
57
|
},
|
|
58
58
|
"dependencies": {
|
|
59
|
-
"@
|
|
60
|
-
"@crawlee/browser": "4.0.0-
|
|
61
|
-
"@crawlee/
|
|
62
|
-
"@crawlee/
|
|
63
|
-
"@crawlee/
|
|
64
|
-
"
|
|
65
|
-
"
|
|
66
|
-
"tslib": "^2.8.1"
|
|
59
|
+
"@crawlee/browser": "4.0.0-rc.1",
|
|
60
|
+
"@crawlee/browser-pool": "4.0.0-rc.1",
|
|
61
|
+
"@crawlee/core": "4.0.0-rc.1",
|
|
62
|
+
"@crawlee/types": "4.0.0-rc.1",
|
|
63
|
+
"@crawlee/utils": "4.0.0-rc.1",
|
|
64
|
+
"tslib": "^2.8.1",
|
|
65
|
+
"zod": "^4.5.4"
|
|
67
66
|
},
|
|
68
67
|
"peerDependencies": {
|
|
69
68
|
"@browserbasehq/stagehand": "^3.0.0",
|
|
70
|
-
"playwright": "*"
|
|
71
|
-
"zod": "^3.0.0 || ^4.0.0"
|
|
69
|
+
"playwright": "*"
|
|
72
70
|
},
|
|
73
71
|
"peerDependenciesMeta": {
|
|
74
72
|
"@browserbasehq/stagehand": {
|
|
@@ -76,15 +74,11 @@
|
|
|
76
74
|
},
|
|
77
75
|
"playwright": {
|
|
78
76
|
"optional": true
|
|
79
|
-
},
|
|
80
|
-
"zod": {
|
|
81
|
-
"optional": true
|
|
82
77
|
}
|
|
83
78
|
},
|
|
84
79
|
"devDependencies": {
|
|
85
80
|
"@browserbasehq/stagehand": "3.0.7",
|
|
86
|
-
"playwright": "^1.60.0"
|
|
87
|
-
"zod": "^4.3.5"
|
|
81
|
+
"playwright": "^1.60.0"
|
|
88
82
|
},
|
|
89
83
|
"lerna": {
|
|
90
84
|
"command": {
|
|
@@ -93,5 +87,5 @@
|
|
|
93
87
|
}
|
|
94
88
|
}
|
|
95
89
|
},
|
|
96
|
-
"gitHead": "
|
|
90
|
+
"gitHead": "f354ca5e943bed1a5c657a1fce1974c053f9fff0"
|
|
97
91
|
}
|