@crawlee/stagehand 4.0.0-rc.0 → 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 +2 -3
- package/index.js +1 -3
- package/index.mjs +4 -11
- package/internals/stagehand-controller.d.ts +0 -14
- package/internals/stagehand-controller.js +5 -5
- package/internals/stagehand-crawler.d.ts +34 -47
- package/internals/stagehand-crawler.js +16 -11
- package/internals/stagehand-launcher.d.ts +15 -28
- package/internals/stagehand-launcher.js +13 -5
- package/internals/stagehand-plugin.d.ts +0 -14
- package/internals/stagehand-plugin.js +13 -19
- package/package.json +9 -10
package/README.md
CHANGED
|
@@ -34,7 +34,7 @@ Crawlee is available as the [`crawlee`](https://www.npmjs.com/package/crawlee) N
|
|
|
34
34
|
|
|
35
35
|
We recommend visiting the [Introduction tutorial](https://crawlee.dev/js/docs/introduction) in Crawlee documentation for more information.
|
|
36
36
|
|
|
37
|
-
> Crawlee requires **Node.js
|
|
37
|
+
> Crawlee requires **Node.js 22.13 or higher**.
|
|
38
38
|
|
|
39
39
|
### With Crawlee CLI
|
|
40
40
|
|
package/index.d.ts
CHANGED
|
@@ -53,7 +53,6 @@ export * from '@crawlee/browser';
|
|
|
53
53
|
export { StagehandCrawler, createStagehandRouter } from './internals/stagehand-crawler';
|
|
54
54
|
export { stagehandBrowserPool, remoteStagehandBrowserPool } from './internals/stagehand-browser-pool';
|
|
55
55
|
export type { StagehandBrowserPool, StagehandBrowserPoolOptions, RemoteStagehandBrowserPoolOptions, } from './internals/stagehand-browser-pool';
|
|
56
|
-
export type { StagehandOptions, StagehandPage, StagehandCrawlingContext, StagehandHook,
|
|
56
|
+
export type { StagehandOptions, StagehandPage, StagehandCrawlingContext, StagehandHook, StagehandGotoOptions, StagehandCrawlerOptions, } from './internals/stagehand-crawler';
|
|
57
57
|
export type { StagehandLaunchContext } from './internals/stagehand-launcher';
|
|
58
|
-
export
|
|
59
|
-
export type { ActOptions, ActResult, Action, AgentConfig, AgentResult, ExtractOptions, ModelConfiguration, ObserveOptions, Stagehand, } from '@browserbasehq/stagehand';
|
|
58
|
+
export type { ActOptions, ActResult, Action, AgentConfig, ExtractOptions, ModelConfiguration, ObserveOptions, Stagehand, } from '@browserbasehq/stagehand';
|
package/index.js
CHANGED
|
@@ -51,7 +51,7 @@
|
|
|
51
51
|
* @module @crawlee/stagehand
|
|
52
52
|
*/
|
|
53
53
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
54
|
-
exports.
|
|
54
|
+
exports.remoteStagehandBrowserPool = exports.stagehandBrowserPool = exports.createStagehandRouter = exports.StagehandCrawler = void 0;
|
|
55
55
|
const tslib_1 = require("tslib");
|
|
56
56
|
// Re-export everything from @crawlee/browser for convenience
|
|
57
57
|
tslib_1.__exportStar(require("@crawlee/browser"), exports);
|
|
@@ -63,5 +63,3 @@ Object.defineProperty(exports, "createStagehandRouter", { enumerable: true, get:
|
|
|
63
63
|
var stagehand_browser_pool_1 = require("./internals/stagehand-browser-pool");
|
|
64
64
|
Object.defineProperty(exports, "stagehandBrowserPool", { enumerable: true, get: function () { return stagehand_browser_pool_1.stagehandBrowserPool; } });
|
|
65
65
|
Object.defineProperty(exports, "remoteStagehandBrowserPool", { enumerable: true, get: function () { return stagehand_browser_pool_1.remoteStagehandBrowserPool; } });
|
|
66
|
-
// Export utilities as namespace
|
|
67
|
-
exports.stagehandUtils = tslib_1.__importStar(require("./internals/utils/stagehand-utils"));
|
package/index.mjs
CHANGED
|
@@ -2,6 +2,7 @@ import mod from "./index.js";
|
|
|
2
2
|
|
|
3
3
|
export default mod;
|
|
4
4
|
export const API_PROCESSED_REQUESTS_DELAY_MILLIS = mod.API_PROCESSED_REQUESTS_DELAY_MILLIS;
|
|
5
|
+
export const AfterCommitError = mod.AfterCommitError;
|
|
5
6
|
export const ApifyLogAdapter = mod.ApifyLogAdapter;
|
|
6
7
|
export const ArgumentValidationError = mod.ArgumentValidationError;
|
|
7
8
|
export const AutoscaledPool = mod.AutoscaledPool;
|
|
@@ -18,13 +19,13 @@ export const ContextPipelineInitializationError = mod.ContextPipelineInitializat
|
|
|
18
19
|
export const ContextPipelineInterruptedError = mod.ContextPipelineInterruptedError;
|
|
19
20
|
export const CookieParseError = mod.CookieParseError;
|
|
20
21
|
export const CpuLoadSignal = mod.CpuLoadSignal;
|
|
22
|
+
export const CrawlingRequest = mod.CrawlingRequest;
|
|
21
23
|
export const CriticalError = mod.CriticalError;
|
|
22
24
|
export const DATASET_ITERATORS_DEFAULT_LIMIT = mod.DATASET_ITERATORS_DEFAULT_LIMIT;
|
|
23
25
|
export const DEFAULT_CURRENT_HISTORY_SECS = mod.DEFAULT_CURRENT_HISTORY_SECS;
|
|
24
26
|
export const DEFAULT_SNAPSHOT_HISTORY_SECS = mod.DEFAULT_SNAPSHOT_HISTORY_SECS;
|
|
25
27
|
export const Dataset = mod.Dataset;
|
|
26
28
|
export const EnqueueStrategy = mod.EnqueueStrategy;
|
|
27
|
-
export const ErrorSnapshotter = mod.ErrorSnapshotter;
|
|
28
29
|
export const ErrorTracker = mod.ErrorTracker;
|
|
29
30
|
export const EventLoopLoadSignal = mod.EventLoopLoadSignal;
|
|
30
31
|
export const EventManager = mod.EventManager;
|
|
@@ -36,7 +37,6 @@ export const LogLevel = mod.LogLevel;
|
|
|
36
37
|
export const Logger = mod.Logger;
|
|
37
38
|
export const LoggerJson = mod.LoggerJson;
|
|
38
39
|
export const LoggerText = mod.LoggerText;
|
|
39
|
-
export const MAX_POOL_SIZE = mod.MAX_POOL_SIZE;
|
|
40
40
|
export const MAX_QUERIES_FOR_CONSISTENCY = mod.MAX_QUERIES_FOR_CONSISTENCY;
|
|
41
41
|
export const MemoryLoadSignal = mod.MemoryLoadSignal;
|
|
42
42
|
export const MemoryStorageBackend = mod.MemoryStorageBackend;
|
|
@@ -45,7 +45,6 @@ export const MissingSessionError = mod.MissingSessionError;
|
|
|
45
45
|
export const NavigationSkippedError = mod.NavigationSkippedError;
|
|
46
46
|
export const NonRetryableError = mod.NonRetryableError;
|
|
47
47
|
export const OwnedOrInjected = mod.OwnedOrInjected;
|
|
48
|
-
export const PERSIST_STATE_KEY = mod.PERSIST_STATE_KEY;
|
|
49
48
|
export const PersistentRateLimitError = mod.PersistentRateLimitError;
|
|
50
49
|
export const ProxyConfiguration = mod.ProxyConfiguration;
|
|
51
50
|
export const QUERY_HEAD_BUFFER = mod.QUERY_HEAD_BUFFER;
|
|
@@ -69,6 +68,7 @@ export const ServiceLocator = mod.ServiceLocator;
|
|
|
69
68
|
export const Session = mod.Session;
|
|
70
69
|
export const SessionError = mod.SessionError;
|
|
71
70
|
export const SessionPool = mod.SessionPool;
|
|
71
|
+
export const SessionRetiredError = mod.SessionRetiredError;
|
|
72
72
|
export const SitemapRequestLoader = mod.SitemapRequestLoader;
|
|
73
73
|
export const SnapshotStore = mod.SnapshotStore;
|
|
74
74
|
export const Snapshotter = mod.Snapshotter;
|
|
@@ -77,13 +77,11 @@ export const StateValidationError = mod.StateValidationError;
|
|
|
77
77
|
export const Statistics = mod.Statistics;
|
|
78
78
|
export const StorageBackendLoadSignal = mod.StorageBackendLoadSignal;
|
|
79
79
|
export const StorageInstanceManager = mod.StorageInstanceManager;
|
|
80
|
-
export const StorageStatsTracker = mod.StorageStatsTracker;
|
|
81
80
|
export const StorageTransaction = mod.StorageTransaction;
|
|
82
81
|
export const SystemStatus = mod.SystemStatus;
|
|
83
82
|
export const ThrottlingRequestManager = mod.ThrottlingRequestManager;
|
|
84
83
|
export const activeStorageTransaction = mod.activeStorageTransaction;
|
|
85
84
|
export const applyRequestTransform = mod.applyRequestTransform;
|
|
86
|
-
export const assertBrowserPoolNotConfigured = mod.assertBrowserPoolNotConfigured;
|
|
87
85
|
export const assertJsonSerializable = mod.assertJsonSerializable;
|
|
88
86
|
export const bindMethodsToServiceLocator = mod.bindMethodsToServiceLocator;
|
|
89
87
|
export const browserPoolCookieToToughCookie = mod.browserPoolCookieToToughCookie;
|
|
@@ -101,6 +99,7 @@ export const createDeserialize = mod.createDeserialize;
|
|
|
101
99
|
export const createDualIterable = mod.createDualIterable;
|
|
102
100
|
export const createRequestDebugInfo = mod.createRequestDebugInfo;
|
|
103
101
|
export const createRequestOptions = mod.createRequestOptions;
|
|
102
|
+
export const createSkippedRequestArgs = mod.createSkippedRequestArgs;
|
|
104
103
|
export const createStagehandRouter = mod.createStagehandRouter;
|
|
105
104
|
export const createStorageTransaction = mod.createStorageTransaction;
|
|
106
105
|
export const currentStorageTransaction = mod.currentStorageTransaction;
|
|
@@ -119,7 +118,6 @@ export const log = mod.log;
|
|
|
119
118
|
export const mergeCookies = mod.mergeCookies;
|
|
120
119
|
export const navigationDeadlineKey = mod.navigationDeadlineKey;
|
|
121
120
|
export const operationRejectedInTransaction = mod.operationRejectedInTransaction;
|
|
122
|
-
export const parseArgument = mod.parseArgument;
|
|
123
121
|
export const parseRetryAfterHeader = mod.parseRetryAfterHeader;
|
|
124
122
|
export const parseValue = mod.parseValue;
|
|
125
123
|
export const purgeDefaultStorages = mod.purgeDefaultStorages;
|
|
@@ -127,17 +125,12 @@ export const rejectOperationInTransaction = mod.rejectOperationInTransaction;
|
|
|
127
125
|
export const remainingNavigationWindowMillis = mod.remainingNavigationWindowMillis;
|
|
128
126
|
export const remoteStagehandBrowserPool = mod.remoteStagehandBrowserPool;
|
|
129
127
|
export const resolveBaseUrlForEnqueueLinksFiltering = mod.resolveBaseUrlForEnqueueLinksFiltering;
|
|
130
|
-
export const resolveStorageIdentifier = mod.resolveStorageIdentifier;
|
|
131
|
-
export const schemas = mod.schemas;
|
|
132
128
|
export const serializeArray = mod.serializeArray;
|
|
133
129
|
export const serializeValue = mod.serializeValue;
|
|
134
130
|
export const serviceLocator = mod.serviceLocator;
|
|
135
131
|
export const snapshotValue = mod.snapshotValue;
|
|
136
132
|
export const stagehandBrowserPool = mod.stagehandBrowserPool;
|
|
137
|
-
export const stagehandUtils = mod.stagehandUtils;
|
|
138
|
-
export const supportsDomainThrottling = mod.supportsDomainThrottling;
|
|
139
133
|
export const toughCookieToBrowserPoolCookie = mod.toughCookieToBrowserPoolCookie;
|
|
140
|
-
export const tryAbsoluteURL = mod.tryAbsoluteURL;
|
|
141
134
|
export const updateEnqueueLinksPatternCache = mod.updateEnqueueLinksPatternCache;
|
|
142
135
|
export const urlPatternSchema = mod.urlPatternSchema;
|
|
143
136
|
export const useState = mod.useState;
|
|
@@ -29,20 +29,6 @@ export declare class StagehandController extends BrowserController<BrowserType,
|
|
|
29
29
|
* We use Playwright's browser API directly since we connected via CDP.
|
|
30
30
|
*/
|
|
31
31
|
protected _newPage(_contextOptions?: unknown): Promise<Page>;
|
|
32
|
-
/**
|
|
33
|
-
* Waits until Stagehand knows about the page, so that `act()`/`extract()`/`observe()` can resolve it.
|
|
34
|
-
*
|
|
35
|
-
* Stagehand only learns about pages from CDP `Target.attachedToTarget` events on its own connection,
|
|
36
|
-
* and it maps them by main frame id. We create pages through a separate `connectOverCDP()` handle, so
|
|
37
|
-
* `context.newPage()` resolves before Stagehand has processed that event — the page is unresolvable for
|
|
38
|
-
* a short window, and the AI methods fail with 'Failed to resolve V3 Page from Playwright page'.
|
|
39
|
-
* Stagehand's own `newPage()` polls for the same reason.
|
|
40
|
-
*/
|
|
41
|
-
private waitForStagehandToRegisterPage;
|
|
42
|
-
/**
|
|
43
|
-
* Reads the page's main frame id, which is the key Stagehand resolves pages by.
|
|
44
|
-
*/
|
|
45
|
-
private getMainFrameId;
|
|
46
32
|
/**
|
|
47
33
|
* Normalizes proxy options for Playwright.
|
|
48
34
|
*/
|
|
@@ -51,10 +51,10 @@ class StagehandController extends browser_pool_1.BrowserController {
|
|
|
51
51
|
const page = await context.newPage();
|
|
52
52
|
// Track active pages
|
|
53
53
|
page.once('close', () => {
|
|
54
|
-
this.
|
|
54
|
+
this.registerPageClosed(page);
|
|
55
55
|
});
|
|
56
56
|
try {
|
|
57
|
-
await this
|
|
57
|
+
await this.#waitForStagehandToRegisterPage(page);
|
|
58
58
|
}
|
|
59
59
|
catch (error) {
|
|
60
60
|
await page.close().catch(() => { });
|
|
@@ -77,9 +77,9 @@ class StagehandController extends browser_pool_1.BrowserController {
|
|
|
77
77
|
* a short window, and the AI methods fail with 'Failed to resolve V3 Page from Playwright page'.
|
|
78
78
|
* Stagehand's own `newPage()` polls for the same reason.
|
|
79
79
|
*/
|
|
80
|
-
async waitForStagehandToRegisterPage(page, timeoutMs = 10_000) {
|
|
80
|
+
async #waitForStagehandToRegisterPage(page, timeoutMs = 10_000) {
|
|
81
81
|
const stagehand = this.getStagehand();
|
|
82
|
-
const mainFrameId = await this
|
|
82
|
+
const mainFrameId = await this.#getMainFrameId(page);
|
|
83
83
|
const deadline = Date.now() + timeoutMs;
|
|
84
84
|
while (Date.now() < deadline) {
|
|
85
85
|
if (stagehand.context.resolvePageByMainFrameId(mainFrameId)) {
|
|
@@ -94,7 +94,7 @@ class StagehandController extends browser_pool_1.BrowserController {
|
|
|
94
94
|
/**
|
|
95
95
|
* Reads the page's main frame id, which is the key Stagehand resolves pages by.
|
|
96
96
|
*/
|
|
97
|
-
async getMainFrameId(page) {
|
|
97
|
+
async #getMainFrameId(page) {
|
|
98
98
|
const cdpSession = await page.context().newCDPSession(page);
|
|
99
99
|
try {
|
|
100
100
|
const { frameTree } = await cdpSession.send('Page.getFrameTree');
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import type { Action, ActOptions, ActResult, AgentConfig, ExtractOptions, LLMClient, ModelConfiguration, NonStreamingAgentInstance, ObserveOptions, Stagehand, StreamingAgentInstance } from '@browserbasehq/stagehand';
|
|
2
|
-
import type { BrowserCrawlerOptions, BrowserCrawlingContext, BrowserHook,
|
|
2
|
+
import type { BrowserCrawlerOptions, BrowserCrawlingContext, BrowserHook, GetUserDataFromRequest, RequestHandler, RouterHandler, RouterRoutes, RouteSchemas, RoutesFromSchemas } from '@crawlee/browser';
|
|
3
3
|
import { BrowserCrawler } from '@crawlee/browser';
|
|
4
4
|
import type { Dictionary } from '@crawlee/types';
|
|
5
5
|
// @ts-ignore optional peer dependency or compatibility with es2022
|
|
6
|
-
import type {
|
|
6
|
+
import type { Page, Response } from 'playwright';
|
|
7
7
|
import { z } from 'zod';
|
|
8
8
|
import type { StagehandLaunchContext } from './stagehand-launcher';
|
|
9
9
|
/**
|
|
@@ -187,11 +187,6 @@ export interface StagehandCrawlingContext<UserData extends Dictionary = any> ext
|
|
|
187
187
|
* Hook function for StagehandCrawler.
|
|
188
188
|
*/
|
|
189
189
|
export type StagehandHook<UserData extends Dictionary = any> = BrowserHook<StagehandCrawlingContext<UserData>>;
|
|
190
|
-
/**
|
|
191
|
-
* Request handler for StagehandCrawler.
|
|
192
|
-
*/
|
|
193
|
-
export interface StagehandRequestHandler extends RequestHandler<LoadedContext<StagehandCrawlingContext>> {
|
|
194
|
-
}
|
|
195
190
|
/**
|
|
196
191
|
* Options for StagehandCrawler.
|
|
197
192
|
*/
|
|
@@ -313,21 +308,12 @@ export interface StagehandCrawlerOptions<ContextExtension = Dictionary<never>, E
|
|
|
313
308
|
* await crawler.run(['https://example.com']);
|
|
314
309
|
* ```
|
|
315
310
|
*/
|
|
316
|
-
export declare class StagehandCrawler<ContextExtension = Dictionary<never>, ExtendedContext extends StagehandCrawlingContext = StagehandCrawlingContext & ContextExtension, Routes extends Record<keyof Routes, Dictionary> = Record<string, GetUserDataFromRequest<StagehandCrawlingContext['request']>>, StatisticStateExtension extends object = {}> extends BrowserCrawler<StagehandPage, Response,
|
|
311
|
+
export declare class StagehandCrawler<ContextExtension = Dictionary<never>, ExtendedContext extends StagehandCrawlingContext = StagehandCrawlingContext & ContextExtension, Routes extends Record<keyof Routes, Dictionary> = Record<string, GetUserDataFromRequest<StagehandCrawlingContext['request']>>, StatisticStateExtension extends object = {}> extends BrowserCrawler<StagehandPage, Response, StagehandCrawlingContext, ContextExtension, ExtendedContext, Routes, StatisticStateExtension> {
|
|
312
|
+
#private;
|
|
313
|
+
/**
|
|
314
|
+
* @internal
|
|
315
|
+
*/
|
|
317
316
|
protected static optionsShape: {
|
|
318
|
-
stagehandOptions: z.ZodOptional<z.ZodCustom<Dictionary, Dictionary>>;
|
|
319
|
-
headless: z.ZodOptional<z.ZodBoolean>;
|
|
320
|
-
navigationTimeoutSecs: z.ZodDefault<z.ZodCustom<number, number>>;
|
|
321
|
-
preNavigationHooks: z.ZodDefault<z.ZodCustom<unknown[], unknown[]>>;
|
|
322
|
-
postNavigationHooks: z.ZodDefault<z.ZodCustom<unknown[], unknown[]>>;
|
|
323
|
-
launchContext: z.ZodDefault<z.ZodCustom<Dictionary, Dictionary>>;
|
|
324
|
-
browserPool: z.ZodOptional<z.ZodType<Dictionary<any>, unknown, z.core.$ZodTypeInternals<Dictionary<any>, unknown>>>;
|
|
325
|
-
browserPoolBuilder: z.ZodOptional<z.ZodCustom<(...args: any[]) => unknown, (...args: any[]) => unknown>>;
|
|
326
|
-
remoteBrowser: z.ZodOptional<z.ZodCustom<Dictionary, Dictionary>>;
|
|
327
|
-
saveResponseCookies: z.ZodDefault<z.ZodBoolean>;
|
|
328
|
-
proxyConfiguration: z.ZodOptional<z.ZodType<Dictionary<any>, unknown, z.core.$ZodTypeInternals<Dictionary<any>, unknown>>>;
|
|
329
|
-
ignoreIframes: z.ZodDefault<z.ZodBoolean>;
|
|
330
|
-
ignoreShadowRoots: z.ZodDefault<z.ZodBoolean>;
|
|
331
317
|
contextPipelineBuilder: z.ZodOptional<z.ZodCustom<Dictionary, Dictionary>>;
|
|
332
318
|
extendContext: z.ZodOptional<z.ZodCustom<(...args: any[]) => unknown, (...args: any[]) => unknown>>;
|
|
333
319
|
requestList: z.ZodOptional<z.ZodType<Dictionary<any>, unknown, z.core.$ZodTypeInternals<Dictionary<any>, unknown>>>;
|
|
@@ -359,27 +345,23 @@ export declare class StagehandCrawler<ContextExtension = Dictionary<never>, Exte
|
|
|
359
345
|
}, z.core.$strict>]>>;
|
|
360
346
|
onSkippedRequest: z.ZodOptional<z.ZodCustom<(...args: any[]) => unknown, (...args: any[]) => unknown>>;
|
|
361
347
|
// @ts-ignore optional peer dependency or compatibility with es2022
|
|
362
|
-
httpClient: z.ZodOptional<z.
|
|
348
|
+
httpClient: z.ZodOptional<z.ZodInstanceOf<import("@crawlee/http-client").BaseHttpClient>>;
|
|
363
349
|
// @ts-ignore optional peer dependency or compatibility with es2022
|
|
364
|
-
configuration: z.ZodOptional<z.
|
|
350
|
+
configuration: z.ZodOptional<z.ZodInstanceOf<import("@crawlee/browser").Configuration>>;
|
|
365
351
|
storageBackend: z.ZodOptional<z.ZodType<Dictionary<any>, unknown, z.core.$ZodTypeInternals<Dictionary<any>, unknown>>>;
|
|
366
352
|
// @ts-ignore optional peer dependency or compatibility with es2022
|
|
367
|
-
eventManager: z.ZodOptional<z.
|
|
353
|
+
eventManager: z.ZodOptional<z.ZodInstanceOf<import("@crawlee/browser").EventManager>>;
|
|
368
354
|
logger: z.ZodOptional<z.ZodType<Dictionary<any>, unknown, z.core.$ZodTypeInternals<Dictionary<any>, unknown>>>;
|
|
369
355
|
minConcurrency: z.ZodOptional<z.ZodCustom<number, number>>;
|
|
370
356
|
maxConcurrency: z.ZodOptional<z.ZodCustom<number, number>>;
|
|
357
|
+
initialConcurrency: z.ZodOptional<z.ZodCustom<number, number>>;
|
|
371
358
|
maxRequestsPerMinute: z.ZodOptional<z.ZodCustom<number, number>>;
|
|
372
359
|
keepAlive: z.ZodOptional<z.ZodBoolean>;
|
|
373
360
|
statistics: z.ZodOptional<z.ZodCustom<Dictionary, Dictionary>>;
|
|
374
361
|
id: z.ZodOptional<z.ZodString>;
|
|
375
|
-
};
|
|
376
|
-
protected static optionsSchema: z.ZodObject<{
|
|
377
|
-
stagehandOptions: z.ZodOptional<z.ZodCustom<Dictionary, Dictionary>>;
|
|
378
|
-
headless: z.ZodOptional<z.ZodBoolean>;
|
|
379
362
|
navigationTimeoutSecs: z.ZodDefault<z.ZodCustom<number, number>>;
|
|
380
363
|
preNavigationHooks: z.ZodDefault<z.ZodCustom<unknown[], unknown[]>>;
|
|
381
364
|
postNavigationHooks: z.ZodDefault<z.ZodCustom<unknown[], unknown[]>>;
|
|
382
|
-
launchContext: z.ZodDefault<z.ZodCustom<Dictionary, Dictionary>>;
|
|
383
365
|
browserPool: z.ZodOptional<z.ZodType<Dictionary<any>, unknown, z.core.$ZodTypeInternals<Dictionary<any>, unknown>>>;
|
|
384
366
|
browserPoolBuilder: z.ZodOptional<z.ZodCustom<(...args: any[]) => unknown, (...args: any[]) => unknown>>;
|
|
385
367
|
remoteBrowser: z.ZodOptional<z.ZodCustom<Dictionary, Dictionary>>;
|
|
@@ -387,6 +369,12 @@ export declare class StagehandCrawler<ContextExtension = Dictionary<never>, Exte
|
|
|
387
369
|
proxyConfiguration: z.ZodOptional<z.ZodType<Dictionary<any>, unknown, z.core.$ZodTypeInternals<Dictionary<any>, unknown>>>;
|
|
388
370
|
ignoreIframes: z.ZodDefault<z.ZodBoolean>;
|
|
389
371
|
ignoreShadowRoots: z.ZodDefault<z.ZodBoolean>;
|
|
372
|
+
launchContext: z.ZodDefault<z.ZodCustom<Dictionary, Dictionary>>;
|
|
373
|
+
stagehandOptions: z.ZodOptional<z.ZodCustom<Dictionary, Dictionary>>;
|
|
374
|
+
headless: z.ZodOptional<z.ZodBoolean>;
|
|
375
|
+
};
|
|
376
|
+
/** @internal */
|
|
377
|
+
protected static optionsSchema: z.ZodObject<{
|
|
390
378
|
contextPipelineBuilder: z.ZodOptional<z.ZodCustom<Dictionary, Dictionary>>;
|
|
391
379
|
extendContext: z.ZodOptional<z.ZodCustom<(...args: any[]) => unknown, (...args: any[]) => unknown>>;
|
|
392
380
|
requestList: z.ZodOptional<z.ZodType<Dictionary<any>, unknown, z.core.$ZodTypeInternals<Dictionary<any>, unknown>>>;
|
|
@@ -418,19 +406,33 @@ export declare class StagehandCrawler<ContextExtension = Dictionary<never>, Exte
|
|
|
418
406
|
}, z.core.$strict>]>>;
|
|
419
407
|
onSkippedRequest: z.ZodOptional<z.ZodCustom<(...args: any[]) => unknown, (...args: any[]) => unknown>>;
|
|
420
408
|
// @ts-ignore optional peer dependency or compatibility with es2022
|
|
421
|
-
httpClient: z.ZodOptional<z.
|
|
409
|
+
httpClient: z.ZodOptional<z.ZodInstanceOf<import("@crawlee/http-client").BaseHttpClient>>;
|
|
422
410
|
// @ts-ignore optional peer dependency or compatibility with es2022
|
|
423
|
-
configuration: z.ZodOptional<z.
|
|
411
|
+
configuration: z.ZodOptional<z.ZodInstanceOf<import("@crawlee/browser").Configuration>>;
|
|
424
412
|
storageBackend: z.ZodOptional<z.ZodType<Dictionary<any>, unknown, z.core.$ZodTypeInternals<Dictionary<any>, unknown>>>;
|
|
425
413
|
// @ts-ignore optional peer dependency or compatibility with es2022
|
|
426
|
-
eventManager: z.ZodOptional<z.
|
|
414
|
+
eventManager: z.ZodOptional<z.ZodInstanceOf<import("@crawlee/browser").EventManager>>;
|
|
427
415
|
logger: z.ZodOptional<z.ZodType<Dictionary<any>, unknown, z.core.$ZodTypeInternals<Dictionary<any>, unknown>>>;
|
|
428
416
|
minConcurrency: z.ZodOptional<z.ZodCustom<number, number>>;
|
|
429
417
|
maxConcurrency: z.ZodOptional<z.ZodCustom<number, number>>;
|
|
418
|
+
initialConcurrency: z.ZodOptional<z.ZodCustom<number, number>>;
|
|
430
419
|
maxRequestsPerMinute: z.ZodOptional<z.ZodCustom<number, number>>;
|
|
431
420
|
keepAlive: z.ZodOptional<z.ZodBoolean>;
|
|
432
421
|
statistics: z.ZodOptional<z.ZodCustom<Dictionary, Dictionary>>;
|
|
433
422
|
id: z.ZodOptional<z.ZodString>;
|
|
423
|
+
navigationTimeoutSecs: z.ZodDefault<z.ZodCustom<number, number>>;
|
|
424
|
+
preNavigationHooks: z.ZodDefault<z.ZodCustom<unknown[], unknown[]>>;
|
|
425
|
+
postNavigationHooks: z.ZodDefault<z.ZodCustom<unknown[], unknown[]>>;
|
|
426
|
+
browserPool: z.ZodOptional<z.ZodType<Dictionary<any>, unknown, z.core.$ZodTypeInternals<Dictionary<any>, unknown>>>;
|
|
427
|
+
browserPoolBuilder: z.ZodOptional<z.ZodCustom<(...args: any[]) => unknown, (...args: any[]) => unknown>>;
|
|
428
|
+
remoteBrowser: z.ZodOptional<z.ZodCustom<Dictionary, Dictionary>>;
|
|
429
|
+
saveResponseCookies: z.ZodDefault<z.ZodBoolean>;
|
|
430
|
+
proxyConfiguration: z.ZodOptional<z.ZodType<Dictionary<any>, unknown, z.core.$ZodTypeInternals<Dictionary<any>, unknown>>>;
|
|
431
|
+
ignoreIframes: z.ZodDefault<z.ZodBoolean>;
|
|
432
|
+
ignoreShadowRoots: z.ZodDefault<z.ZodBoolean>;
|
|
433
|
+
launchContext: z.ZodDefault<z.ZodCustom<Dictionary, Dictionary>>;
|
|
434
|
+
stagehandOptions: z.ZodOptional<z.ZodCustom<Dictionary, Dictionary>>;
|
|
435
|
+
headless: z.ZodOptional<z.ZodBoolean>;
|
|
434
436
|
}, z.core.$strict>;
|
|
435
437
|
/**
|
|
436
438
|
* Creates a new instance of StagehandCrawler.
|
|
@@ -438,21 +440,6 @@ export declare class StagehandCrawler<ContextExtension = Dictionary<never>, Exte
|
|
|
438
440
|
* @param options - Crawler configuration options
|
|
439
441
|
*/
|
|
440
442
|
constructor(options?: StagehandCrawlerOptions<ContextExtension, ExtendedContext, Routes, StatisticStateExtension>);
|
|
441
|
-
protected buildContextPipeline(): ContextPipeline<CrawlingContext, StagehandCrawlingContext>;
|
|
442
|
-
/**
|
|
443
|
-
* Resolves the {@link StagehandController} that owns the given page, or
|
|
444
|
-
* `undefined` when the pool does not expose controllers (e.g. a custom
|
|
445
|
-
* {@link IBrowserPool} implementation).
|
|
446
|
-
*
|
|
447
|
-
* Stagehand needs direct controller access to reach the `Stagehand`
|
|
448
|
-
* instance bound to the page's browser, which is why it reaches past the
|
|
449
|
-
* {@link IBrowserPool} abstraction here.
|
|
450
|
-
*/
|
|
451
|
-
private getBrowserControllerByPage;
|
|
452
|
-
/**
|
|
453
|
-
* Enhance the page with Stagehand AI methods.
|
|
454
|
-
*/
|
|
455
|
-
private setUpStagehand;
|
|
456
443
|
/**
|
|
457
444
|
* Navigation handler for Stagehand crawler.
|
|
458
445
|
* Uses standard Playwright navigation.
|
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.StagehandCrawler = void 0;
|
|
4
4
|
exports.createStagehandRouter = createStagehandRouter;
|
|
5
5
|
const browser_1 = require("@crawlee/browser");
|
|
6
|
+
const internal_1 = require("@crawlee/utils/internal");
|
|
6
7
|
const zod_1 = require("zod");
|
|
7
8
|
const stagehand_browser_pool_1 = require("./stagehand-browser-pool");
|
|
8
9
|
const stagehand_utils_1 = require("./utils/stagehand-utils");
|
|
@@ -56,11 +57,16 @@ const stagehand_utils_1 = require("./utils/stagehand-utils");
|
|
|
56
57
|
* ```
|
|
57
58
|
*/
|
|
58
59
|
class StagehandCrawler extends browser_1.BrowserCrawler {
|
|
60
|
+
/**
|
|
61
|
+
* @internal
|
|
62
|
+
*/
|
|
59
63
|
static optionsShape = {
|
|
60
64
|
...browser_1.BrowserCrawler.optionsShape,
|
|
61
|
-
|
|
65
|
+
launchContext: internal_1.schemas.anyObject.default(() => ({})),
|
|
66
|
+
stagehandOptions: internal_1.schemas.anyObject.optional(),
|
|
62
67
|
headless: zod_1.z.boolean().optional(),
|
|
63
68
|
};
|
|
69
|
+
/** @internal */
|
|
64
70
|
static optionsSchema = zod_1.z.strictObject(StagehandCrawler.optionsShape);
|
|
65
71
|
/**
|
|
66
72
|
* Creates a new instance of StagehandCrawler.
|
|
@@ -68,11 +74,11 @@ class StagehandCrawler extends browser_1.BrowserCrawler {
|
|
|
68
74
|
* @param options - Crawler configuration options
|
|
69
75
|
*/
|
|
70
76
|
constructor(options = {}) {
|
|
71
|
-
const parsedOptions = (0,
|
|
72
|
-
const { stagehandOptions, launchContext, headless, configuration,
|
|
77
|
+
const parsedOptions = (0, internal_1.parseArgument)(options, StagehandCrawler.optionsSchema, 'StagehandCrawlerOptions');
|
|
78
|
+
const { stagehandOptions, launchContext, headless, configuration, ...browserCrawlerOptions } = parsedOptions;
|
|
73
79
|
if (options.browserPool) {
|
|
74
80
|
// The raw options, not the parsed ones: `launchContext` has a default, so by now it is always set.
|
|
75
|
-
(0,
|
|
81
|
+
(0, internal_1.assertBrowserPoolNotConfigured)(new.target.name, {
|
|
76
82
|
launchContext: options.launchContext,
|
|
77
83
|
stagehandOptions: options.stagehandOptions,
|
|
78
84
|
headless: options.headless,
|
|
@@ -80,7 +86,6 @@ class StagehandCrawler extends browser_1.BrowserCrawler {
|
|
|
80
86
|
}
|
|
81
87
|
super({
|
|
82
88
|
...browserCrawlerOptions,
|
|
83
|
-
launchContext,
|
|
84
89
|
configuration,
|
|
85
90
|
// The pool serves plain Playwright pages - a page only becomes a `StagehandPage` further down the
|
|
86
91
|
// pipeline, once `setUpStagehand` enhances it - so its page type is narrower than the crawler's.
|
|
@@ -98,11 +103,11 @@ class StagehandCrawler extends browser_1.BrowserCrawler {
|
|
|
98
103
|
headless,
|
|
99
104
|
configuration,
|
|
100
105
|
})),
|
|
101
|
-
contextPipelineBuilder:
|
|
106
|
+
contextPipelineBuilder: () => this.#buildContextPipeline(),
|
|
102
107
|
});
|
|
103
108
|
}
|
|
104
|
-
buildContextPipeline() {
|
|
105
|
-
return
|
|
109
|
+
#buildContextPipeline() {
|
|
110
|
+
return this.buildContextPipeline().compose(this.#setUpStagehand.bind(this));
|
|
106
111
|
}
|
|
107
112
|
/**
|
|
108
113
|
* Resolves the {@link StagehandController} that owns the given page, or
|
|
@@ -113,7 +118,7 @@ class StagehandCrawler extends browser_1.BrowserCrawler {
|
|
|
113
118
|
* instance bound to the page's browser, which is why it reaches past the
|
|
114
119
|
* {@link IBrowserPool} abstraction here.
|
|
115
120
|
*/
|
|
116
|
-
getBrowserControllerByPage(page) {
|
|
121
|
+
#getBrowserControllerByPage(page) {
|
|
117
122
|
if ('getBrowserControllerByPage' in this.browserPool) {
|
|
118
123
|
return this.browserPool.getBrowserControllerByPage(page);
|
|
119
124
|
}
|
|
@@ -122,8 +127,8 @@ class StagehandCrawler extends browser_1.BrowserCrawler {
|
|
|
122
127
|
/**
|
|
123
128
|
* Enhance the page with Stagehand AI methods.
|
|
124
129
|
*/
|
|
125
|
-
async setUpStagehand(crawlingContext) {
|
|
126
|
-
const controller = this
|
|
130
|
+
async #setUpStagehand(crawlingContext) {
|
|
131
|
+
const controller = this.#getBrowserControllerByPage(crawlingContext.page);
|
|
127
132
|
if (!controller) {
|
|
128
133
|
throw new Error('Could not resolve StagehandController for page — is the browser pool configured correctly?');
|
|
129
134
|
}
|
|
@@ -14,10 +14,6 @@ export interface StagehandLaunchContext extends BrowserLaunchContext<LaunchOptio
|
|
|
14
14
|
* These will be passed to Stagehand's localBrowserLaunchOptions after fingerprinting is applied.
|
|
15
15
|
*/
|
|
16
16
|
launchOptions?: LaunchOptions & Parameters<BrowserType['launchPersistentContext']>[1];
|
|
17
|
-
/**
|
|
18
|
-
* Stagehand-specific configuration for AI operations.
|
|
19
|
-
*/
|
|
20
|
-
stagehandOptions?: StagehandOptions;
|
|
21
17
|
/**
|
|
22
18
|
* URL to a HTTP proxy server. It must define the port number,
|
|
23
19
|
* and it may also contain proxy username and password.
|
|
@@ -32,21 +28,6 @@ export interface StagehandLaunchContext extends BrowserLaunchContext<LaunchOptio
|
|
|
32
28
|
* @default false
|
|
33
29
|
*/
|
|
34
30
|
useChrome?: boolean;
|
|
35
|
-
/**
|
|
36
|
-
* With this option selected, all pages will be opened in a new incognito browser context.
|
|
37
|
-
* @default false
|
|
38
|
-
*/
|
|
39
|
-
useIncognitoPages?: boolean;
|
|
40
|
-
/**
|
|
41
|
-
* Sets the User Data Directory path.
|
|
42
|
-
* The user data directory contains profile data such as history, bookmarks, and cookies.
|
|
43
|
-
*/
|
|
44
|
-
userDataDir?: string;
|
|
45
|
-
/**
|
|
46
|
-
* By default this function uses `require("playwright").chromium`.
|
|
47
|
-
* If you want to use a different browser you can pass it by this property.
|
|
48
|
-
*/
|
|
49
|
-
launcher?: BrowserType;
|
|
50
31
|
}
|
|
51
32
|
/**
|
|
52
33
|
* StagehandLauncher is based on BrowserLauncher and creates StagehandPlugin instances.
|
|
@@ -57,13 +38,10 @@ export interface StagehandLaunchContext extends BrowserLaunchContext<LaunchOptio
|
|
|
57
38
|
export declare class StagehandLauncher extends BrowserLauncher<StagehandPlugin> {
|
|
58
39
|
#private;
|
|
59
40
|
readonly configuration: Configuration;
|
|
41
|
+
/**
|
|
42
|
+
* @internal
|
|
43
|
+
*/
|
|
60
44
|
protected static optionsShape: {
|
|
61
|
-
// @ts-ignore optional peer dependency or compatibility with es2022
|
|
62
|
-
launcher: z.ZodOptional<z.ZodCustom<import("@crawlee/types", { with: { "resolution-mode": "import" } }).Dictionary, import("@crawlee/types", { with: { "resolution-mode": "import" } }).Dictionary>>;
|
|
63
|
-
// @ts-ignore optional peer dependency or compatibility with es2022
|
|
64
|
-
launchContextOptions: z.ZodOptional<z.ZodCustom<import("@crawlee/types", { with: { "resolution-mode": "import" } }).Dictionary, import("@crawlee/types", { with: { "resolution-mode": "import" } }).Dictionary>>;
|
|
65
|
-
// @ts-ignore optional peer dependency or compatibility with es2022
|
|
66
|
-
stagehandOptions: z.ZodOptional<z.ZodCustom<import("@crawlee/types", { with: { "resolution-mode": "import" } }).Dictionary, import("@crawlee/types", { with: { "resolution-mode": "import" } }).Dictionary>>;
|
|
67
45
|
proxyUrl: z.ZodOptional<z.ZodURL>;
|
|
68
46
|
useChrome: z.ZodOptional<z.ZodBoolean>;
|
|
69
47
|
useIncognitoPages: z.ZodOptional<z.ZodBoolean>;
|
|
@@ -73,14 +51,15 @@ export declare class StagehandLauncher extends BrowserLauncher<StagehandPlugin>
|
|
|
73
51
|
// @ts-ignore optional peer dependency or compatibility with es2022
|
|
74
52
|
launchOptions: z.ZodOptional<z.ZodCustom<import("@crawlee/types", { with: { "resolution-mode": "import" } }).Dictionary, import("@crawlee/types", { with: { "resolution-mode": "import" } }).Dictionary>>;
|
|
75
53
|
userAgent: z.ZodOptional<z.ZodString>;
|
|
76
|
-
};
|
|
77
|
-
protected static optionsSchema: z.ZodObject<{
|
|
78
54
|
// @ts-ignore optional peer dependency or compatibility with es2022
|
|
79
55
|
launcher: z.ZodOptional<z.ZodCustom<import("@crawlee/types", { with: { "resolution-mode": "import" } }).Dictionary, import("@crawlee/types", { with: { "resolution-mode": "import" } }).Dictionary>>;
|
|
80
56
|
// @ts-ignore optional peer dependency or compatibility with es2022
|
|
81
57
|
launchContextOptions: z.ZodOptional<z.ZodCustom<import("@crawlee/types", { with: { "resolution-mode": "import" } }).Dictionary, import("@crawlee/types", { with: { "resolution-mode": "import" } }).Dictionary>>;
|
|
82
58
|
// @ts-ignore optional peer dependency or compatibility with es2022
|
|
83
59
|
stagehandOptions: z.ZodOptional<z.ZodCustom<import("@crawlee/types", { with: { "resolution-mode": "import" } }).Dictionary, import("@crawlee/types", { with: { "resolution-mode": "import" } }).Dictionary>>;
|
|
60
|
+
};
|
|
61
|
+
/** @internal */
|
|
62
|
+
protected static optionsSchema: z.ZodObject<{
|
|
84
63
|
proxyUrl: z.ZodOptional<z.ZodURL>;
|
|
85
64
|
useChrome: z.ZodOptional<z.ZodBoolean>;
|
|
86
65
|
useIncognitoPages: z.ZodOptional<z.ZodBoolean>;
|
|
@@ -90,11 +69,19 @@ export declare class StagehandLauncher extends BrowserLauncher<StagehandPlugin>
|
|
|
90
69
|
// @ts-ignore optional peer dependency or compatibility with es2022
|
|
91
70
|
launchOptions: z.ZodOptional<z.ZodCustom<import("@crawlee/types", { with: { "resolution-mode": "import" } }).Dictionary, import("@crawlee/types", { with: { "resolution-mode": "import" } }).Dictionary>>;
|
|
92
71
|
userAgent: z.ZodOptional<z.ZodString>;
|
|
72
|
+
// @ts-ignore optional peer dependency or compatibility with es2022
|
|
73
|
+
launcher: z.ZodOptional<z.ZodCustom<import("@crawlee/types", { with: { "resolution-mode": "import" } }).Dictionary, import("@crawlee/types", { with: { "resolution-mode": "import" } }).Dictionary>>;
|
|
74
|
+
// @ts-ignore optional peer dependency or compatibility with es2022
|
|
75
|
+
launchContextOptions: z.ZodOptional<z.ZodCustom<import("@crawlee/types", { with: { "resolution-mode": "import" } }).Dictionary, import("@crawlee/types", { with: { "resolution-mode": "import" } }).Dictionary>>;
|
|
76
|
+
// @ts-ignore optional peer dependency or compatibility with es2022
|
|
77
|
+
stagehandOptions: z.ZodOptional<z.ZodCustom<import("@crawlee/types", { with: { "resolution-mode": "import" } }).Dictionary, import("@crawlee/types", { with: { "resolution-mode": "import" } }).Dictionary>>;
|
|
93
78
|
}, z.core.$strict>;
|
|
94
79
|
/**
|
|
95
80
|
* All StagehandLauncher parameters are passed via the launchContext object.
|
|
96
81
|
*/
|
|
97
|
-
constructor(launchContext?: StagehandLaunchContext
|
|
82
|
+
constructor(launchContext?: StagehandLaunchContext & {
|
|
83
|
+
stagehandOptions?: StagehandOptions;
|
|
84
|
+
}, configuration?: Configuration);
|
|
98
85
|
/**
|
|
99
86
|
* Creates a new StagehandPlugin instance with resolved options.
|
|
100
87
|
*/
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.StagehandLauncher = void 0;
|
|
4
4
|
const browser_1 = require("@crawlee/browser");
|
|
5
|
+
const internal_1 = require("@crawlee/utils/internal");
|
|
5
6
|
const zod_1 = require("zod");
|
|
6
7
|
const stagehand_plugin_1 = require("./stagehand-plugin");
|
|
7
8
|
/**
|
|
@@ -12,20 +13,27 @@ const stagehand_plugin_1 = require("./stagehand-plugin");
|
|
|
12
13
|
*/
|
|
13
14
|
class StagehandLauncher extends browser_1.BrowserLauncher {
|
|
14
15
|
configuration;
|
|
16
|
+
/**
|
|
17
|
+
* @internal
|
|
18
|
+
*/
|
|
15
19
|
static optionsShape = {
|
|
16
20
|
...browser_1.BrowserLauncher.optionsShape,
|
|
17
21
|
// Passthrough schemas — the launcher module object must keep its prototype through parsing.
|
|
18
|
-
launcher:
|
|
19
|
-
launchContextOptions:
|
|
20
|
-
stagehandOptions:
|
|
22
|
+
launcher: internal_1.schemas.anyObject.optional(),
|
|
23
|
+
launchContextOptions: internal_1.schemas.anyObject.optional(),
|
|
24
|
+
stagehandOptions: internal_1.schemas.anyObject.optional(),
|
|
21
25
|
};
|
|
26
|
+
/** @internal */
|
|
22
27
|
static optionsSchema = zod_1.z.strictObject(StagehandLauncher.optionsShape);
|
|
23
28
|
#stagehandOptions;
|
|
24
29
|
/**
|
|
25
30
|
* All StagehandLauncher parameters are passed via the launchContext object.
|
|
26
31
|
*/
|
|
27
|
-
constructor(
|
|
28
|
-
|
|
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');
|
|
29
37
|
const { launcher = browser_1.BrowserLauncher.requireLauncherOrThrow('playwright', 'apify/actor-node-playwright-*').chromium, stagehandOptions = {}, } = parsedContext;
|
|
30
38
|
const { launchOptions = {}, ...rest } = parsedContext;
|
|
31
39
|
// Call super first before initializing properties
|
|
@@ -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
|
|
@@ -28,16 +27,11 @@ export interface StagehandPluginOptions extends BrowserPluginOptions<LaunchOptio
|
|
|
28
27
|
*/
|
|
29
28
|
export declare class StagehandPlugin extends BrowserPlugin<BrowserType, LaunchOptions, PlaywrightBrowser> {
|
|
30
29
|
#private;
|
|
31
|
-
readonly stagehandOptions: StagehandOptions;
|
|
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
|
*/
|
|
@@ -50,12 +44,4 @@ export declare class StagehandPlugin extends BrowserPlugin<BrowserType, LaunchOp
|
|
|
50
44
|
* Determines if this is a Chromium-based browser.
|
|
51
45
|
*/
|
|
52
46
|
protected isChromiumBasedBrowser(): boolean;
|
|
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;
|
|
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;
|
|
24
|
+
#stagehandOptions;
|
|
25
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
|
? {
|
|
@@ -79,7 +79,7 @@ class StagehandPlugin extends browser_pool_1.BrowserPlugin {
|
|
|
79
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,7 +96,7 @@ class StagehandPlugin extends browser_pool_1.BrowserPlugin {
|
|
|
96
96
|
/**
|
|
97
97
|
* Cleans up Stagehand instance when browser disconnects.
|
|
98
98
|
*/
|
|
99
|
-
async cleanupStagehand(browser) {
|
|
99
|
+
async #cleanupStagehand(browser) {
|
|
100
100
|
const stagehand = this.#stagehandInstances.get(browser);
|
|
101
101
|
if (stagehand) {
|
|
102
102
|
try {
|
|
@@ -139,9 +139,9 @@ class StagehandPlugin extends browser_pool_1.BrowserPlugin {
|
|
|
139
139
|
/**
|
|
140
140
|
* Augments launch errors with helpful context.
|
|
141
141
|
*/
|
|
142
|
-
augmentLaunchError(error, launchContext) {
|
|
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-rc.
|
|
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,14 +56,13 @@
|
|
|
56
56
|
"access": "public"
|
|
57
57
|
},
|
|
58
58
|
"dependencies": {
|
|
59
|
-
"@
|
|
60
|
-
"@crawlee/browser": "4.0.0-rc.
|
|
61
|
-
"@crawlee/
|
|
62
|
-
"@crawlee/
|
|
63
|
-
"@crawlee/
|
|
64
|
-
"@crawlee/utils": "4.0.0-rc.0",
|
|
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",
|
|
65
64
|
"tslib": "^2.8.1",
|
|
66
|
-
"zod": "^4.4
|
|
65
|
+
"zod": "^4.5.4"
|
|
67
66
|
},
|
|
68
67
|
"peerDependencies": {
|
|
69
68
|
"@browserbasehq/stagehand": "^3.0.0",
|
|
@@ -88,5 +87,5 @@
|
|
|
88
87
|
}
|
|
89
88
|
}
|
|
90
89
|
},
|
|
91
|
-
"gitHead": "
|
|
90
|
+
"gitHead": "f354ca5e943bed1a5c657a1fce1974c053f9fff0"
|
|
92
91
|
}
|