stagehand 4.0.3a0.dev1474__tar.gz → 4.0.3a0.dev1476__tar.gz
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.
- {stagehand-4.0.3a0.dev1474 → stagehand-4.0.3a0.dev1476}/PKG-INFO +1 -1
- {stagehand-4.0.3a0.dev1474 → stagehand-4.0.3a0.dev1476}/pyproject.toml +1 -1
- {stagehand-4.0.3a0.dev1474 → stagehand-4.0.3a0.dev1476}/src/stagehand/_extension/service-worker.js +140 -68
- {stagehand-4.0.3a0.dev1474 → stagehand-4.0.3a0.dev1476}/src/stagehand/_generated/input_types.py +0 -4
- {stagehand-4.0.3a0.dev1474 → stagehand-4.0.3a0.dev1476}/src/stagehand/_generated/models.py +0 -8
- {stagehand-4.0.3a0.dev1474 → stagehand-4.0.3a0.dev1476}/src/stagehand/_generated/protocol_version.py +1 -1
- {stagehand-4.0.3a0.dev1474 → stagehand-4.0.3a0.dev1476}/src/stagehand/browser.py +56 -13
- {stagehand-4.0.3a0.dev1474 → stagehand-4.0.3a0.dev1476}/src/stagehand/browser_context.py +11 -9
- {stagehand-4.0.3a0.dev1474 → stagehand-4.0.3a0.dev1476}/src/stagehand/browserbase_session.py +18 -1
- {stagehand-4.0.3a0.dev1474 → stagehand-4.0.3a0.dev1476}/src/stagehand/rpc_client.py +0 -1
- {stagehand-4.0.3a0.dev1474 → stagehand-4.0.3a0.dev1476}/src/stagehand/stagehand.py +15 -5
- {stagehand-4.0.3a0.dev1474 → stagehand-4.0.3a0.dev1476}/README.md +0 -0
- {stagehand-4.0.3a0.dev1474 → stagehand-4.0.3a0.dev1476}/src/stagehand/__init__.py +0 -0
- {stagehand-4.0.3a0.dev1474 → stagehand-4.0.3a0.dev1476}/src/stagehand/_extension/blank.html +0 -0
- {stagehand-4.0.3a0.dev1474 → stagehand-4.0.3a0.dev1476}/src/stagehand/_extension/content-script.js +0 -0
- {stagehand-4.0.3a0.dev1474 → stagehand-4.0.3a0.dev1476}/src/stagehand/_extension/manifest.json +0 -0
- {stagehand-4.0.3a0.dev1474 → stagehand-4.0.3a0.dev1476}/src/stagehand/_extension/offscreen/service-worker-heartbeat.html +0 -0
- {stagehand-4.0.3a0.dev1474 → stagehand-4.0.3a0.dev1476}/src/stagehand/_extension/offscreen/service-worker-heartbeat.js +0 -0
- {stagehand-4.0.3a0.dev1474 → stagehand-4.0.3a0.dev1476}/src/stagehand/_extension/wake-service-worker.html +0 -0
- {stagehand-4.0.3a0.dev1474 → stagehand-4.0.3a0.dev1476}/src/stagehand/_extension/wake-service-worker.js +0 -0
- {stagehand-4.0.3a0.dev1474 → stagehand-4.0.3a0.dev1476}/src/stagehand/_generated/__init__.py +0 -0
- {stagehand-4.0.3a0.dev1474 → stagehand-4.0.3a0.dev1476}/src/stagehand/_sdk_identity.py +0 -0
- {stagehand-4.0.3a0.dev1474 → stagehand-4.0.3a0.dev1476}/src/stagehand/_validation.py +0 -0
- {stagehand-4.0.3a0.dev1474 → stagehand-4.0.3a0.dev1476}/src/stagehand/browser_clipboard.py +0 -0
- {stagehand-4.0.3a0.dev1474 → stagehand-4.0.3a0.dev1476}/src/stagehand/cdp_client.py +0 -0
- {stagehand-4.0.3a0.dev1474 → stagehand-4.0.3a0.dev1476}/src/stagehand/client_models.py +0 -0
- {stagehand-4.0.3a0.dev1474 → stagehand-4.0.3a0.dev1476}/src/stagehand/client_types.py +0 -0
- {stagehand-4.0.3a0.dev1474 → stagehand-4.0.3a0.dev1476}/src/stagehand/extension_assets.py +0 -0
- {stagehand-4.0.3a0.dev1474 → stagehand-4.0.3a0.dev1476}/src/stagehand/file_upload.py +0 -0
- {stagehand-4.0.3a0.dev1474 → stagehand-4.0.3a0.dev1476}/src/stagehand/locator.py +0 -0
- {stagehand-4.0.3a0.dev1474 → stagehand-4.0.3a0.dev1476}/src/stagehand/page.py +0 -0
- {stagehand-4.0.3a0.dev1474 → stagehand-4.0.3a0.dev1476}/src/stagehand/py.typed +0 -0
- {stagehand-4.0.3a0.dev1474 → stagehand-4.0.3a0.dev1476}/src/stagehand/response.py +0 -0
- {stagehand-4.0.3a0.dev1474 → stagehand-4.0.3a0.dev1476}/src/stagehand/timeouts.py +0 -0
- {stagehand-4.0.3a0.dev1474 → stagehand-4.0.3a0.dev1476}/src/stagehand/webmcp.py +0 -0
{stagehand-4.0.3a0.dev1474 → stagehand-4.0.3a0.dev1476}/src/stagehand/_extension/service-worker.js
RENAMED
|
@@ -7359,7 +7359,7 @@ function isRecord$1(value) {
|
|
|
7359
7359
|
}
|
|
7360
7360
|
var package_default$1 = {
|
|
7361
7361
|
name: "@browserbasehq/stagehand-protocol",
|
|
7362
|
-
version: "2.0.0-alpha-
|
|
7362
|
+
version: "2.0.0-alpha-6555e81e837012088eb12a39c06aed0527a2e5af",
|
|
7363
7363
|
"private": true,
|
|
7364
7364
|
type: "module",
|
|
7365
7365
|
scripts: {
|
|
@@ -8302,7 +8302,6 @@ var PageNavigationOptionsSchema = strictObject({
|
|
|
8302
8302
|
}).meta({ id: "PageNavigationOptions" });
|
|
8303
8303
|
var PageVoidResultSchema = strictObject({ ok: literal(true) }).meta({ id: "PageVoidResult" });
|
|
8304
8304
|
var ContextVoidResultSchema = strictObject({ ok: literal(true) }).meta({ id: "ContextVoidResult" });
|
|
8305
|
-
var ContextCloseResultSchema = strictObject({ closed: literal(true) }).meta({ id: "ContextCloseResult" });
|
|
8306
8305
|
var PageScreenshotClipSchema = strictObject({
|
|
8307
8306
|
x: number$1(),
|
|
8308
8307
|
y: number$1(),
|
|
@@ -8784,11 +8783,6 @@ var StagehandMethods = {
|
|
|
8784
8783
|
params: ContextSetActivePageParamsSchema,
|
|
8785
8784
|
result: ContextVoidResultSchema
|
|
8786
8785
|
},
|
|
8787
|
-
contextClose: {
|
|
8788
|
-
name: "context.close",
|
|
8789
|
-
params: EmptyParamsSchema,
|
|
8790
|
-
result: ContextCloseResultSchema
|
|
8791
|
-
},
|
|
8792
8786
|
contextAddInitScript: {
|
|
8793
8787
|
name: "context.add_init_script",
|
|
8794
8788
|
params: ContextAddInitScriptParamsSchema,
|
|
@@ -11460,7 +11454,9 @@ var RPCClient = class {
|
|
|
11460
11454
|
});
|
|
11461
11455
|
return;
|
|
11462
11456
|
}
|
|
11457
|
+
let releaseStagehandInstanceRequest;
|
|
11463
11458
|
try {
|
|
11459
|
+
if (request.data.method !== StagehandMethods.stagehandInit.name && request.data.method !== StagehandMethods.stagehandClose.name) releaseStagehandInstanceRequest = this.router.runtime.acquireStagehandInstanceRequest();
|
|
11464
11460
|
const result = await this.router.handle(stagehandRequest.data, runtimeAttachments);
|
|
11465
11461
|
const parsedResult = method.result.safeParse(result);
|
|
11466
11462
|
if (!parsedResult.success) {
|
|
@@ -11470,6 +11466,7 @@ var RPCClient = class {
|
|
|
11470
11466
|
});
|
|
11471
11467
|
return;
|
|
11472
11468
|
}
|
|
11469
|
+
await this.router.beforeResponse(stagehandRequest.data);
|
|
11473
11470
|
await this.runtime.send(JSONRPCSuccessResponseSchema.parse({
|
|
11474
11471
|
jsonrpc: "2.0",
|
|
11475
11472
|
id: request.data.id,
|
|
@@ -11484,6 +11481,8 @@ var RPCClient = class {
|
|
|
11484
11481
|
return;
|
|
11485
11482
|
}
|
|
11486
11483
|
await this.sendError(request.data.id, JSONRPCErrorCodes.internalError, error instanceof Error ? error.message : String(error), { name: error instanceof Error ? error.name : "Error" });
|
|
11484
|
+
} finally {
|
|
11485
|
+
releaseStagehandInstanceRequest?.();
|
|
11487
11486
|
}
|
|
11488
11487
|
}
|
|
11489
11488
|
receiveResponse(response) {
|
|
@@ -11550,10 +11549,6 @@ function createContextController(runtime) {
|
|
|
11550
11549
|
logger.debug("context.set_active_page", {});
|
|
11551
11550
|
return runtime.contextSetActivePage(params);
|
|
11552
11551
|
}
|
|
11553
|
-
async function close(_params, { logger }) {
|
|
11554
|
-
logger.debug("context.close", {});
|
|
11555
|
-
return runtime.contextClose();
|
|
11556
|
-
}
|
|
11557
11552
|
async function addInitScript(params, { logger }) {
|
|
11558
11553
|
logger.debug("context.add_init_script", {});
|
|
11559
11554
|
return runtime.contextAddInitScript(params);
|
|
@@ -11611,7 +11606,6 @@ function createContextController(runtime) {
|
|
|
11611
11606
|
newPage,
|
|
11612
11607
|
activePage,
|
|
11613
11608
|
setActivePage,
|
|
11614
|
-
close,
|
|
11615
11609
|
addInitScript,
|
|
11616
11610
|
setExtraHTTPHeaders,
|
|
11617
11611
|
getDomainPolicy,
|
|
@@ -12330,8 +12324,9 @@ function reportPageEventListenerError(error) {
|
|
|
12330
12324
|
//#endregion
|
|
12331
12325
|
//#region ../sdk-ts/src/browserContext.ts
|
|
12332
12326
|
var BrowserContext$1 = class {
|
|
12333
|
-
constructor(rpcClient) {
|
|
12327
|
+
constructor(rpcClient, closeBrowser) {
|
|
12334
12328
|
this.rpcClient = rpcClient;
|
|
12329
|
+
this.closeBrowser = closeBrowser;
|
|
12335
12330
|
}
|
|
12336
12331
|
get clipboard() {
|
|
12337
12332
|
return this.clipboardRef ??= new BrowserClipboard(this.rpcClient);
|
|
@@ -12351,9 +12346,10 @@ var BrowserContext$1 = class {
|
|
|
12351
12346
|
async setActivePage(page) {
|
|
12352
12347
|
await this.rpcClient.send(StagehandMethods.contextSetActivePage, { pageId: page.pageId });
|
|
12353
12348
|
}
|
|
12354
|
-
/** Close the
|
|
12349
|
+
/** Close the underlying browser. */
|
|
12355
12350
|
async close() {
|
|
12356
|
-
|
|
12351
|
+
if (!this.closeBrowser) throw new Error("Browser context is not attached to a browser");
|
|
12352
|
+
await this.closeBrowser();
|
|
12357
12353
|
}
|
|
12358
12354
|
async addInitScript(script, arg) {
|
|
12359
12355
|
const source = await normalizeInitScriptSource$1(script, arg, "context.addInitScript");
|
|
@@ -50846,13 +50842,13 @@ async function observe({ params, page, model, clientLLMGenerate, logger, systemP
|
|
|
50846
50842
|
//#endregion
|
|
50847
50843
|
//#region controllers/stagehandController.ts
|
|
50848
50844
|
function createStagehandController(runtime, options = {}) {
|
|
50849
|
-
const closeRuntime = options.close ?? (() => runtime.
|
|
50845
|
+
const closeRuntime = options.close ?? (() => runtime.disposeStagehandInstance());
|
|
50850
50846
|
async function runOperation(name, { logger, telemetryScope }, run) {
|
|
50851
50847
|
return await logger.span(name, {}, (logger) => runtime.runWithTelemetryContext(telemetryScope, logger, () => run(logger)));
|
|
50852
50848
|
}
|
|
50853
50849
|
async function init(params, { logger }) {
|
|
50854
50850
|
const compatibility = checkProtocolCompatibility(params.protocolVersion, STAGEHAND_PROTOCOL_VERSION);
|
|
50855
|
-
if (
|
|
50851
|
+
if (compatibility.compatible === false) throw new StagehandProtocolCompatibilityError(compatibility.reason);
|
|
50856
50852
|
logger.setLevel(params.logLevel);
|
|
50857
50853
|
logger.info("stagehand.init", {});
|
|
50858
50854
|
return options.initialize ? await options.initialize(params) : await runtime.initialize(params, logger);
|
|
@@ -50961,7 +50957,7 @@ var RPCRouter = class {
|
|
|
50961
50957
|
}
|
|
50962
50958
|
async handle(request, runtimeAttachments) {
|
|
50963
50959
|
const initParams = request.method === StagehandMethods.stagehandInit.name ? request.params : void 0;
|
|
50964
|
-
if (initParams) this.runtime.tracing.configure(initParams.telemetry, initParams.clientInfo);
|
|
50960
|
+
if (initParams) await this.runtime.tracing.configure(initParams.telemetry, initParams.clientInfo);
|
|
50965
50961
|
const parentContext = W3C_TRACE_CONTEXT_PROPAGATOR.extract(ROOT_CONTEXT, request, {
|
|
50966
50962
|
get(carrier, key) {
|
|
50967
50963
|
if (key === "traceparent" || key === "tracestate") return carrier[key];
|
|
@@ -50996,9 +50992,12 @@ var RPCRouter = class {
|
|
|
50996
50992
|
throw error;
|
|
50997
50993
|
} finally {
|
|
50998
50994
|
span.end();
|
|
50999
|
-
if (request.method === StagehandMethods.stagehandClose.name) await this.runtime.tracing.shutdown();
|
|
51000
50995
|
}
|
|
51001
50996
|
}
|
|
50997
|
+
async beforeResponse(request) {
|
|
50998
|
+
if (request.method !== StagehandMethods.stagehandClose.name) return;
|
|
50999
|
+
await this.runtime.tracing.forceFlush().catch(() => void 0);
|
|
51000
|
+
}
|
|
51002
51001
|
async route(request, context, parsedInitParams) {
|
|
51003
51002
|
switch (request.method) {
|
|
51004
51003
|
case "stagehand.init": return this.stagehandController.init(parsedInitParams ?? parseParams(StagehandMethods.stagehandInit, request.params), context);
|
|
@@ -51012,7 +51011,6 @@ var RPCRouter = class {
|
|
|
51012
51011
|
case "context.new_page": return this.contextController.newPage(parseParams(StagehandMethods.contextNewPage, request.params), context);
|
|
51013
51012
|
case "context.active_page": return this.contextController.activePage(parseParams(StagehandMethods.contextActivePage, request.params), context);
|
|
51014
51013
|
case "context.set_active_page": return this.contextController.setActivePage(parseParams(StagehandMethods.contextSetActivePage, request.params), context);
|
|
51015
|
-
case "context.close": return this.contextController.close(parseParams(StagehandMethods.contextClose, request.params), context);
|
|
51016
51014
|
case "context.add_init_script": return this.contextController.addInitScript(parseParams(StagehandMethods.contextAddInitScript, request.params), context);
|
|
51017
51015
|
case "context.set_extra_http_headers": return this.contextController.setExtraHTTPHeaders(parseParams(StagehandMethods.contextSetExtraHTTPHeaders, request.params), context);
|
|
51018
51016
|
case "context.get_domain_policy": return this.contextController.getDomainPolicy(parseParams(StagehandMethods.contextGetDomainPolicy, request.params), context);
|
|
@@ -51260,14 +51258,10 @@ var StagehandLogger = class StagehandLogger {
|
|
|
51260
51258
|
};
|
|
51261
51259
|
//#endregion
|
|
51262
51260
|
//#region runtimeState.ts
|
|
51263
|
-
var StagehandRuntimeStateSchema = discriminatedUnion("status", [
|
|
51264
|
-
|
|
51265
|
-
|
|
51266
|
-
|
|
51267
|
-
initParams: StagehandInitParamsSchema
|
|
51268
|
-
}),
|
|
51269
|
-
strictObject({ status: literal("closed") })
|
|
51270
|
-
]);
|
|
51261
|
+
var StagehandRuntimeStateSchema = discriminatedUnion("status", [strictObject({ status: literal("idle") }), strictObject({
|
|
51262
|
+
status: literal("initialized"),
|
|
51263
|
+
initParams: StagehandInitParamsSchema
|
|
51264
|
+
})]);
|
|
51271
51265
|
//#endregion
|
|
51272
51266
|
//#region ../../node_modules/.pnpm/@opentelemetry+otlp-exporter-base@0.220.0_@opentelemetry+api@1.9.1/node_modules/@opentelemetry/otlp-exporter-base/build/esm/OTLPExporterBase.js
|
|
51273
51267
|
var OTLPExporterBase = class {
|
|
@@ -53443,7 +53437,7 @@ var WebTracerProvider = class extends BasicTracerProvider {
|
|
|
53443
53437
|
};
|
|
53444
53438
|
var package_default = {
|
|
53445
53439
|
name: "@browserbasehq/stagehand-extension",
|
|
53446
|
-
version: "1.0.2-alpha-
|
|
53440
|
+
version: "1.0.2-alpha-6555e81e837012088eb12a39c06aed0527a2e5af",
|
|
53447
53441
|
"private": true,
|
|
53448
53442
|
type: "module",
|
|
53449
53443
|
scripts: {
|
|
@@ -53518,22 +53512,48 @@ function createStagehandTracing(options = {}, dependencies = DEFAULT_TRACING_RUN
|
|
|
53518
53512
|
const pendingTracer = trace.getTracer(STAGEHAND_TRACER_NAME);
|
|
53519
53513
|
let runtime;
|
|
53520
53514
|
let shutDown = false;
|
|
53515
|
+
let globalsRegistered = false;
|
|
53516
|
+
let lifecycleTail = Promise.resolve();
|
|
53517
|
+
let activeTelemetry;
|
|
53518
|
+
let activeClientInfo;
|
|
53519
|
+
function enqueueLifecycle(run) {
|
|
53520
|
+
const result = lifecycleTail.then(run, run);
|
|
53521
|
+
lifecycleTail = result.catch(() => void 0);
|
|
53522
|
+
return result;
|
|
53523
|
+
}
|
|
53521
53524
|
return {
|
|
53522
53525
|
get tracer() {
|
|
53523
53526
|
return runtime?.tracer ?? pendingTracer;
|
|
53524
53527
|
},
|
|
53525
53528
|
configure(telemetry, clientInfo) {
|
|
53526
|
-
|
|
53527
|
-
|
|
53528
|
-
|
|
53529
|
-
|
|
53530
|
-
|
|
53531
|
-
|
|
53529
|
+
return enqueueLifecycle(async () => {
|
|
53530
|
+
if (shutDown) return;
|
|
53531
|
+
if (runtime && telemetry === activeTelemetry && clientInfo === activeClientInfo) return;
|
|
53532
|
+
const previousRuntime = runtime;
|
|
53533
|
+
runtime = void 0;
|
|
53534
|
+
await previousRuntime?.shutdown();
|
|
53535
|
+
const registerGlobals = options.registerGlobals !== false && !globalsRegistered;
|
|
53536
|
+
runtime = createStagehandTracingRuntime({
|
|
53537
|
+
...options,
|
|
53538
|
+
clientName: clientInfo.name,
|
|
53539
|
+
clientVersion: clientInfo.version,
|
|
53540
|
+
registerGlobals
|
|
53541
|
+
}, { spanProcessors: [...dependencies.spanProcessors, createOtlpSpanProcessor(telemetry.traces)] });
|
|
53542
|
+
activeTelemetry = telemetry;
|
|
53543
|
+
activeClientInfo = clientInfo;
|
|
53544
|
+
globalsRegistered ||= registerGlobals;
|
|
53545
|
+
});
|
|
53532
53546
|
},
|
|
53533
|
-
forceFlush: () => runtime?.forceFlush() ?? Promise.resolve(),
|
|
53547
|
+
forceFlush: () => enqueueLifecycle(() => runtime?.forceFlush() ?? Promise.resolve()),
|
|
53534
53548
|
shutdown: () => {
|
|
53535
53549
|
shutDown = true;
|
|
53536
|
-
return
|
|
53550
|
+
return enqueueLifecycle(async () => {
|
|
53551
|
+
const activeRuntime = runtime;
|
|
53552
|
+
runtime = void 0;
|
|
53553
|
+
activeTelemetry = void 0;
|
|
53554
|
+
activeClientInfo = void 0;
|
|
53555
|
+
await activeRuntime?.shutdown();
|
|
53556
|
+
});
|
|
53537
53557
|
}
|
|
53538
53558
|
};
|
|
53539
53559
|
}
|
|
@@ -56822,6 +56842,9 @@ var StagehandMetricsAccumulator = class {
|
|
|
56822
56842
|
snapshot() {
|
|
56823
56843
|
return { ...this.values };
|
|
56824
56844
|
}
|
|
56845
|
+
reset() {
|
|
56846
|
+
Object.assign(this.values, EMPTY_METRICS);
|
|
56847
|
+
}
|
|
56825
56848
|
};
|
|
56826
56849
|
//#endregion
|
|
56827
56850
|
//#region responseHandleTable.ts
|
|
@@ -56909,10 +56932,13 @@ var StagehandRuntime = class {
|
|
|
56909
56932
|
this.tracing = tracing;
|
|
56910
56933
|
this.metrics = new StagehandMetricsAccumulator();
|
|
56911
56934
|
this.responseHandles = new ResponseHandleTable();
|
|
56912
|
-
this.state = createStore()(() => StagehandRuntimeStateSchema.parse({ status: "
|
|
56935
|
+
this.state = createStore()(() => StagehandRuntimeStateSchema.parse({ status: "idle" }));
|
|
56913
56936
|
this.pagesById = /* @__PURE__ */ new Map();
|
|
56914
56937
|
this.pageEventSubscriptions = /* @__PURE__ */ new Map();
|
|
56915
56938
|
this.initializationInProgress = false;
|
|
56939
|
+
this.lifecycleTail = Promise.resolve();
|
|
56940
|
+
this.stagehandInstanceClosing = false;
|
|
56941
|
+
this.activeStagehandInstanceRequests = 0;
|
|
56916
56942
|
this.logger = new StagehandLogger(tracing, adapters.emitLog);
|
|
56917
56943
|
}
|
|
56918
56944
|
async replaceBrowserConnection(params, bootstrapLogger) {
|
|
@@ -56932,29 +56958,31 @@ var StagehandRuntime = class {
|
|
|
56932
56958
|
}
|
|
56933
56959
|
}
|
|
56934
56960
|
async initialize(params, logger = this.logger) {
|
|
56935
|
-
const state = this.state.getState();
|
|
56936
|
-
if (state.status === "closed") throw new Error("Stagehand has been closed and cannot be initialized again");
|
|
56937
56961
|
if (this.initializationInProgress) throw new Error("Stagehand initialization is already in progress");
|
|
56938
56962
|
this.initializationInProgress = true;
|
|
56939
56963
|
try {
|
|
56940
|
-
this.
|
|
56941
|
-
|
|
56942
|
-
if (
|
|
56943
|
-
|
|
56944
|
-
|
|
56945
|
-
|
|
56946
|
-
|
|
56947
|
-
|
|
56948
|
-
|
|
56949
|
-
|
|
56950
|
-
|
|
56951
|
-
|
|
56952
|
-
|
|
56953
|
-
|
|
56954
|
-
|
|
56955
|
-
|
|
56956
|
-
|
|
56957
|
-
|
|
56964
|
+
return await this.enqueueLifecycle(async () => {
|
|
56965
|
+
const state = this.state.getState();
|
|
56966
|
+
if (state.status !== "idle") throw new Error("A Stagehand instance is already initialized");
|
|
56967
|
+
this.logger.setLevel(params.logLevel);
|
|
56968
|
+
if (!this.browserSession?.connected) {
|
|
56969
|
+
if (!params.browserCdpUrl) throw new Error("stagehand.init requires browserCdpUrl until resident mode is active");
|
|
56970
|
+
await this.replaceBrowserConnection({ cdpUrl: params.browserCdpUrl }, logger);
|
|
56971
|
+
}
|
|
56972
|
+
const pages = await this.runWithTelemetryContext(Symbol("stagehand.init"), logger, async () => {
|
|
56973
|
+
if (state.status === "idle") await this.browserSession?.prepareForInitialization?.();
|
|
56974
|
+
return await this.contextPages();
|
|
56975
|
+
});
|
|
56976
|
+
await this.tracing.configure(params.telemetry, params.clientInfo);
|
|
56977
|
+
this.state.setState(StagehandRuntimeStateSchema.parse({
|
|
56978
|
+
status: "initialized",
|
|
56979
|
+
initParams: params
|
|
56980
|
+
}), true);
|
|
56981
|
+
return {
|
|
56982
|
+
initialized: true,
|
|
56983
|
+
pages
|
|
56984
|
+
};
|
|
56985
|
+
});
|
|
56958
56986
|
} finally {
|
|
56959
56987
|
this.initializationInProgress = false;
|
|
56960
56988
|
}
|
|
@@ -56992,10 +57020,6 @@ var StagehandRuntime = class {
|
|
|
56992
57020
|
await this.requireBrowserSession().setActivePage(page);
|
|
56993
57021
|
return { ok: true };
|
|
56994
57022
|
}
|
|
56995
|
-
async contextClose() {
|
|
56996
|
-
await this.close();
|
|
56997
|
-
return { closed: true };
|
|
56998
|
-
}
|
|
56999
57023
|
async contextAddInitScript(params) {
|
|
57000
57024
|
await this.requireBrowserSession().addInitScript(params.source);
|
|
57001
57025
|
return { ok: true };
|
|
@@ -57291,16 +57315,64 @@ var StagehandRuntime = class {
|
|
|
57291
57315
|
return { set: true };
|
|
57292
57316
|
}
|
|
57293
57317
|
async close() {
|
|
57294
|
-
|
|
57295
|
-
|
|
57318
|
+
await this.enqueueLifecycle(async () => {
|
|
57319
|
+
const session = this.browserSession;
|
|
57320
|
+
this.browserSession = void 0;
|
|
57321
|
+
this.clearStagehandInstance();
|
|
57322
|
+
await session?.close();
|
|
57323
|
+
});
|
|
57324
|
+
}
|
|
57325
|
+
async disposeStagehandInstance() {
|
|
57326
|
+
if (this.stagehandInstanceDisposal) return await this.stagehandInstanceDisposal;
|
|
57327
|
+
this.stagehandInstanceClosing = true;
|
|
57328
|
+
const disposal = this.enqueueLifecycle(async () => {
|
|
57329
|
+
await this.waitForStagehandInstanceRequests();
|
|
57330
|
+
this.clearStagehandInstance();
|
|
57331
|
+
});
|
|
57332
|
+
this.stagehandInstanceDisposal = disposal.finally(() => {
|
|
57333
|
+
this.stagehandInstanceClosing = false;
|
|
57334
|
+
this.stagehandInstanceDisposal = void 0;
|
|
57335
|
+
});
|
|
57336
|
+
return await this.stagehandInstanceDisposal;
|
|
57337
|
+
}
|
|
57338
|
+
acquireStagehandInstanceRequest() {
|
|
57339
|
+
if (this.stagehandInstanceClosing) throw new Error("Stagehand instance is closing");
|
|
57340
|
+
this.activeStagehandInstanceRequests += 1;
|
|
57341
|
+
let released = false;
|
|
57342
|
+
return () => {
|
|
57343
|
+
if (released) return;
|
|
57344
|
+
released = true;
|
|
57345
|
+
this.activeStagehandInstanceRequests -= 1;
|
|
57346
|
+
if (this.activeStagehandInstanceRequests !== 0) return;
|
|
57347
|
+
this.stagehandInstanceRequestsDrained?.resolve();
|
|
57348
|
+
this.stagehandInstanceRequestsDrained = void 0;
|
|
57349
|
+
};
|
|
57350
|
+
}
|
|
57351
|
+
clearStagehandInstance() {
|
|
57296
57352
|
this.disposeAllPageEventSubscriptions();
|
|
57297
57353
|
this.pagesById.clear();
|
|
57298
57354
|
this.responseHandles.clear();
|
|
57299
|
-
|
|
57300
|
-
|
|
57301
|
-
|
|
57302
|
-
|
|
57355
|
+
this.metrics.reset();
|
|
57356
|
+
this.state.setState(StagehandRuntimeStateSchema.parse({ status: "idle" }), true);
|
|
57357
|
+
}
|
|
57358
|
+
enqueueLifecycle(run) {
|
|
57359
|
+
const result = this.lifecycleTail.then(run, run);
|
|
57360
|
+
this.lifecycleTail = result.then(() => void 0, () => void 0);
|
|
57361
|
+
return result;
|
|
57362
|
+
}
|
|
57363
|
+
waitForStagehandInstanceRequests() {
|
|
57364
|
+
if (this.activeStagehandInstanceRequests === 0) return Promise.resolve();
|
|
57365
|
+
if (!this.stagehandInstanceRequestsDrained) {
|
|
57366
|
+
let resolve;
|
|
57367
|
+
const promise = new Promise((drained) => {
|
|
57368
|
+
resolve = drained;
|
|
57369
|
+
});
|
|
57370
|
+
this.stagehandInstanceRequestsDrained = {
|
|
57371
|
+
promise,
|
|
57372
|
+
resolve
|
|
57373
|
+
};
|
|
57303
57374
|
}
|
|
57375
|
+
return this.stagehandInstanceRequestsDrained.promise;
|
|
57304
57376
|
}
|
|
57305
57377
|
pageRefForId(pageId) {
|
|
57306
57378
|
return pageRefFromUnderstudyPage(this.resolvePage(pageId));
|
|
@@ -430,14 +430,6 @@ class ContextClipboardWriteTextParams(WireModel):
|
|
|
430
430
|
text: StrictStr
|
|
431
431
|
|
|
432
432
|
|
|
433
|
-
class ContextCloseResult(WireModel):
|
|
434
|
-
model_config = ConfigDict(
|
|
435
|
-
extra="forbid",
|
|
436
|
-
validate_by_name=True,
|
|
437
|
-
)
|
|
438
|
-
closed: Literal[True]
|
|
439
|
-
|
|
440
|
-
|
|
441
433
|
class ContextCookiesParams(WireModel):
|
|
442
434
|
model_config = ConfigDict(
|
|
443
435
|
extra="forbid",
|
{stagehand-4.0.3a0.dev1474 → stagehand-4.0.3a0.dev1476}/src/stagehand/_generated/protocol_version.py
RENAMED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
"""Generated from packages/protocol/package.json. Do not edit."""
|
|
2
2
|
|
|
3
3
|
PROTOCOL_SEMVER_PATTERN = '^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[A-Za-z-][0-9A-Za-z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[A-Za-z-][0-9A-Za-z-]*))*))?(?:\\+([0-9A-Za-z-]+(?:\\.[0-9A-Za-z-]+)*))?$'
|
|
4
|
-
STAGEHAND_PROTOCOL_VERSION = '2.0.0-alpha-
|
|
4
|
+
STAGEHAND_PROTOCOL_VERSION = '2.0.0-alpha-6555e81e837012088eb12a39c06aed0527a2e5af'
|
|
@@ -22,7 +22,7 @@ from ._generated.models import (
|
|
|
22
22
|
BrowserSessionMetadata,
|
|
23
23
|
)
|
|
24
24
|
from .browserbase_session import DEFAULT_BROWSERBASE_URL, _create_browserbase_session_client
|
|
25
|
-
from .cdp_client import CDPClient
|
|
25
|
+
from .cdp_client import CDPClient, CDPConnectionClosedError
|
|
26
26
|
from .client_models import (
|
|
27
27
|
BrowserbaseConnectOptions,
|
|
28
28
|
LocalBrowserConnectOptions,
|
|
@@ -98,7 +98,8 @@ class StagehandBrowser:
|
|
|
98
98
|
"_attachment",
|
|
99
99
|
"_claimed",
|
|
100
100
|
"_close_callback",
|
|
101
|
-
"
|
|
101
|
+
"_invalidate_callback",
|
|
102
|
+
"_terminal_task",
|
|
102
103
|
"_context",
|
|
103
104
|
"_origin",
|
|
104
105
|
"_provider",
|
|
@@ -112,6 +113,7 @@ class StagehandBrowser:
|
|
|
112
113
|
attachment: _ClaimedBrowser,
|
|
113
114
|
close: Callable[[], Awaitable[None]],
|
|
114
115
|
*,
|
|
116
|
+
invalidate: Callable[[], Awaitable[None]] | None = None,
|
|
115
117
|
session_id: str | None = None,
|
|
116
118
|
_token: object | None = None,
|
|
117
119
|
) -> None:
|
|
@@ -121,8 +123,9 @@ class StagehandBrowser:
|
|
|
121
123
|
self._origin = origin
|
|
122
124
|
self._attachment = attachment
|
|
123
125
|
self._close_callback = close
|
|
126
|
+
self._invalidate_callback = invalidate or close
|
|
124
127
|
self._claimed = False
|
|
125
|
-
self.
|
|
128
|
+
self._terminal_task: asyncio.Task[None] | None = None
|
|
126
129
|
self._context: BrowserContext | None = None
|
|
127
130
|
self._session_id = session_id
|
|
128
131
|
|
|
@@ -141,7 +144,7 @@ class StagehandBrowser:
|
|
|
141
144
|
|
|
142
145
|
@property
|
|
143
146
|
def closed(self) -> bool:
|
|
144
|
-
return self.
|
|
147
|
+
return self._terminal_task is not None
|
|
145
148
|
|
|
146
149
|
@property
|
|
147
150
|
def context(self) -> BrowserContext:
|
|
@@ -153,15 +156,12 @@ class StagehandBrowser:
|
|
|
153
156
|
return self._context
|
|
154
157
|
|
|
155
158
|
def close(self) -> Awaitable[None]:
|
|
156
|
-
if self.
|
|
157
|
-
self.
|
|
158
|
-
self.
|
|
159
|
+
if self._terminal_task is None:
|
|
160
|
+
self._terminal_task = asyncio.create_task(
|
|
161
|
+
_run_browser_terminal_callback(self._close_callback),
|
|
159
162
|
name="stagehand-browser-close",
|
|
160
163
|
)
|
|
161
|
-
return asyncio.shield(self.
|
|
162
|
-
|
|
163
|
-
async def _run_close(self) -> None:
|
|
164
|
-
await self._close_callback()
|
|
164
|
+
return asyncio.shield(self._terminal_task)
|
|
165
165
|
|
|
166
166
|
|
|
167
167
|
def _claim_browser(browser: object) -> _ClaimedBrowser:
|
|
@@ -181,6 +181,23 @@ def _release_browser(browser: StagehandBrowser) -> None:
|
|
|
181
181
|
browser._claimed = False
|
|
182
182
|
|
|
183
183
|
|
|
184
|
+
def _invalidate_browser(browser: StagehandBrowser) -> Awaitable[None]:
|
|
185
|
+
if not isinstance(browser, StagehandBrowser):
|
|
186
|
+
raise TypeError("browser must be created by local_browser or browserbase")
|
|
187
|
+
if browser._terminal_task is None:
|
|
188
|
+
browser._terminal_task = asyncio.create_task(
|
|
189
|
+
_run_browser_terminal_callback(browser._invalidate_callback),
|
|
190
|
+
name="stagehand-browser-invalidate",
|
|
191
|
+
)
|
|
192
|
+
return asyncio.shield(browser._terminal_task)
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
async def _run_browser_terminal_callback(
|
|
196
|
+
callback: Callable[[], Awaitable[None]],
|
|
197
|
+
) -> None:
|
|
198
|
+
await callback()
|
|
199
|
+
|
|
200
|
+
|
|
184
201
|
def _attach_browser_context(
|
|
185
202
|
browser: StagehandBrowser,
|
|
186
203
|
context: BrowserContext,
|
|
@@ -289,13 +306,34 @@ async def _connect_browser(
|
|
|
289
306
|
|
|
290
307
|
connected_client = cdp_client
|
|
291
308
|
|
|
292
|
-
async def
|
|
309
|
+
async def invalidate() -> None:
|
|
293
310
|
try:
|
|
294
311
|
await connected_client.close()
|
|
295
312
|
finally:
|
|
296
313
|
if owns_source:
|
|
297
314
|
await source.close()
|
|
298
315
|
|
|
316
|
+
async def close() -> None:
|
|
317
|
+
errors: list[BaseException] = []
|
|
318
|
+
try:
|
|
319
|
+
if provider == "local" and origin == "connected":
|
|
320
|
+
try:
|
|
321
|
+
await connected_client.send_command("Browser.close")
|
|
322
|
+
except CDPConnectionClosedError:
|
|
323
|
+
pass
|
|
324
|
+
else:
|
|
325
|
+
await source.close()
|
|
326
|
+
except BaseException as error:
|
|
327
|
+
errors.append(error)
|
|
328
|
+
try:
|
|
329
|
+
await connected_client.close()
|
|
330
|
+
except BaseException as error:
|
|
331
|
+
errors.append(error)
|
|
332
|
+
if len(errors) == 1:
|
|
333
|
+
raise errors[0]
|
|
334
|
+
if errors:
|
|
335
|
+
raise BaseExceptionGroup("Browser termination and cleanup failed", errors)
|
|
336
|
+
|
|
299
337
|
return StagehandBrowser(
|
|
300
338
|
provider,
|
|
301
339
|
origin,
|
|
@@ -304,6 +342,7 @@ async def _connect_browser(
|
|
|
304
342
|
worker_init_metadata=worker_init_metadata,
|
|
305
343
|
),
|
|
306
344
|
close,
|
|
345
|
+
invalidate=invalidate,
|
|
307
346
|
session_id=(
|
|
308
347
|
worker_init_metadata.browser.session_id if worker_init_metadata.browser else None
|
|
309
348
|
),
|
|
@@ -563,7 +602,11 @@ class BrowserbaseBrowser:
|
|
|
563
602
|
return await _connect_browser(
|
|
564
603
|
provider="browserbase",
|
|
565
604
|
origin="connected",
|
|
566
|
-
source=
|
|
605
|
+
source=ResolvedBrowserSource(
|
|
606
|
+
cdp_url=connection.cdp_url,
|
|
607
|
+
keep_alive=True,
|
|
608
|
+
_close_callback=connection.close,
|
|
609
|
+
),
|
|
567
610
|
extension_id=options.extension_id,
|
|
568
611
|
preloaded_extension=options.extension_id is None,
|
|
569
612
|
worker_init_metadata=_WorkerInitMetadata(
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import re
|
|
4
|
-
from collections.abc import Mapping, Sequence
|
|
4
|
+
from collections.abc import Awaitable, Callable, Mapping, Sequence
|
|
5
5
|
from pathlib import Path
|
|
6
6
|
|
|
7
7
|
from ._generated.input_types import CookieParam
|
|
@@ -12,7 +12,6 @@ from ._generated.models import (
|
|
|
12
12
|
ContextAddCookiesParams,
|
|
13
13
|
ContextAddInitScriptParams,
|
|
14
14
|
ContextClearCookiesParams,
|
|
15
|
-
ContextCloseResult,
|
|
16
15
|
ContextCookiesParams,
|
|
17
16
|
ContextCookiesResult,
|
|
18
17
|
ContextGetDomainPolicyResult,
|
|
@@ -35,8 +34,13 @@ from .rpc_client import RPCClient
|
|
|
35
34
|
|
|
36
35
|
|
|
37
36
|
class BrowserContext:
|
|
38
|
-
def __init__(
|
|
37
|
+
def __init__(
|
|
38
|
+
self,
|
|
39
|
+
rpc_client: RPCClient,
|
|
40
|
+
close_browser: Callable[[], Awaitable[None]] | None = None,
|
|
41
|
+
) -> None:
|
|
39
42
|
self._rpc_client = rpc_client
|
|
43
|
+
self._close_browser = close_browser
|
|
40
44
|
self._clipboard: BrowserClipboard | None = None
|
|
41
45
|
|
|
42
46
|
@property
|
|
@@ -76,12 +80,10 @@ class BrowserContext:
|
|
|
76
80
|
)
|
|
77
81
|
|
|
78
82
|
async def close(self) -> None:
|
|
79
|
-
"""Close the
|
|
80
|
-
|
|
81
|
-
"context
|
|
82
|
-
|
|
83
|
-
ContextCloseResult,
|
|
84
|
-
)
|
|
83
|
+
"""Close the underlying browser."""
|
|
84
|
+
if self._close_browser is None:
|
|
85
|
+
raise RuntimeError("Browser context is not attached to a browser")
|
|
86
|
+
await self._close_browser()
|
|
85
87
|
|
|
86
88
|
async def add_init_script(self, source: str | Path) -> None:
|
|
87
89
|
if isinstance(source, Path):
|
{stagehand-4.0.3a0.dev1474 → stagehand-4.0.3a0.dev1476}/src/stagehand/browserbase_session.py
RENAMED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import asyncio
|
|
4
|
-
from collections.abc import Mapping
|
|
4
|
+
from collections.abc import Awaitable, Callable, Mapping
|
|
5
5
|
from dataclasses import dataclass, field
|
|
6
6
|
from typing import Any, Protocol
|
|
7
7
|
|
|
@@ -142,6 +142,11 @@ class _BrowserbaseSessionConnection:
|
|
|
142
142
|
session_id: str
|
|
143
143
|
cdp_url: str
|
|
144
144
|
region: BrowserbaseRegion | None = None
|
|
145
|
+
_close_callback: Callable[[], Awaitable[None]] | None = field(default=None, repr=False)
|
|
146
|
+
|
|
147
|
+
async def close(self) -> None:
|
|
148
|
+
if self._close_callback is not None:
|
|
149
|
+
await self._close_callback()
|
|
145
150
|
|
|
146
151
|
|
|
147
152
|
@dataclass
|
|
@@ -254,10 +259,22 @@ class _BrowserbaseSessionClient:
|
|
|
254
259
|
cdp_url = connect_url.strip() if connect_url is not None else ""
|
|
255
260
|
if not cdp_url:
|
|
256
261
|
raise BrowserbaseSessionError("Browserbase session is not available for connection")
|
|
262
|
+
released = False
|
|
263
|
+
close_lock = asyncio.Lock()
|
|
264
|
+
|
|
265
|
+
async def close() -> None:
|
|
266
|
+
nonlocal released
|
|
267
|
+
async with close_lock:
|
|
268
|
+
if released:
|
|
269
|
+
return
|
|
270
|
+
await self._api.release_session(retrieved_id.strip() or normalized_session_id)
|
|
271
|
+
released = True
|
|
272
|
+
|
|
257
273
|
return _BrowserbaseSessionConnection(
|
|
258
274
|
session_id=retrieved_id.strip() or normalized_session_id,
|
|
259
275
|
cdp_url=cdp_url,
|
|
260
276
|
region=region,
|
|
277
|
+
_close_callback=close,
|
|
261
278
|
)
|
|
262
279
|
|
|
263
280
|
async def _delete_extension_best_effort(self, extension_id: str | None) -> None:
|
|
@@ -47,6 +47,7 @@ from .browser import (
|
|
|
47
47
|
_claim_browser,
|
|
48
48
|
_ClaimedBrowser,
|
|
49
49
|
_detach_browser_context,
|
|
50
|
+
_invalidate_browser,
|
|
50
51
|
_release_browser,
|
|
51
52
|
)
|
|
52
53
|
from .browser_context import BrowserContext
|
|
@@ -278,7 +279,10 @@ class Stagehand:
|
|
|
278
279
|
init_params,
|
|
279
280
|
StagehandInitResult,
|
|
280
281
|
)
|
|
281
|
-
_attach_browser_context(
|
|
282
|
+
_attach_browser_context(
|
|
283
|
+
self._browser_handle,
|
|
284
|
+
BrowserContext(rpc_client, self._browser_handle.close),
|
|
285
|
+
)
|
|
282
286
|
self._initialized = True
|
|
283
287
|
|
|
284
288
|
async def act(
|
|
@@ -450,6 +454,7 @@ class Stagehand:
|
|
|
450
454
|
|
|
451
455
|
async def close(self) -> None:
|
|
452
456
|
async def close_impl() -> None:
|
|
457
|
+
release_browser_claim = not self._initialized
|
|
453
458
|
try:
|
|
454
459
|
if self._initialized and self._rpc_client is not None:
|
|
455
460
|
try:
|
|
@@ -458,10 +463,15 @@ class Stagehand:
|
|
|
458
463
|
EmptyParams(),
|
|
459
464
|
StagehandCloseResult,
|
|
460
465
|
)
|
|
466
|
+
release_browser_claim = True
|
|
461
467
|
except CDPConnectionClosedError:
|
|
462
|
-
|
|
468
|
+
release_browser_claim = True
|
|
463
469
|
finally:
|
|
464
|
-
|
|
470
|
+
try:
|
|
471
|
+
await asyncio.shield(self._release_resources())
|
|
472
|
+
finally:
|
|
473
|
+
if release_browser_claim:
|
|
474
|
+
_release_browser(self._browser_handle)
|
|
465
475
|
|
|
466
476
|
if self._close_task is None:
|
|
467
477
|
self._close_task = asyncio.create_task(
|
|
@@ -541,11 +551,11 @@ class Stagehand:
|
|
|
541
551
|
fail_closed: bool,
|
|
542
552
|
) -> None:
|
|
543
553
|
if fail_closed:
|
|
544
|
-
|
|
554
|
+
browser_invalidation = _invalidate_browser(browser)
|
|
545
555
|
try:
|
|
546
556
|
await self._release_resources()
|
|
547
557
|
finally:
|
|
548
|
-
await
|
|
558
|
+
await browser_invalidation
|
|
549
559
|
return
|
|
550
560
|
|
|
551
561
|
try:
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{stagehand-4.0.3a0.dev1474 → stagehand-4.0.3a0.dev1476}/src/stagehand/_extension/content-script.js
RENAMED
|
File without changes
|
{stagehand-4.0.3a0.dev1474 → stagehand-4.0.3a0.dev1476}/src/stagehand/_extension/manifest.json
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{stagehand-4.0.3a0.dev1474 → stagehand-4.0.3a0.dev1476}/src/stagehand/_generated/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|