stagehand 4.0.3a0.dev1475__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.dev1475 → stagehand-4.0.3a0.dev1476}/PKG-INFO +1 -1
- {stagehand-4.0.3a0.dev1475 → stagehand-4.0.3a0.dev1476}/pyproject.toml +1 -1
- {stagehand-4.0.3a0.dev1475 → stagehand-4.0.3a0.dev1476}/src/stagehand/_extension/service-worker.js +7 -21
- {stagehand-4.0.3a0.dev1475 → stagehand-4.0.3a0.dev1476}/src/stagehand/_generated/input_types.py +0 -4
- {stagehand-4.0.3a0.dev1475 → stagehand-4.0.3a0.dev1476}/src/stagehand/_generated/models.py +0 -8
- {stagehand-4.0.3a0.dev1475 → stagehand-4.0.3a0.dev1476}/src/stagehand/_generated/protocol_version.py +1 -1
- {stagehand-4.0.3a0.dev1475 → stagehand-4.0.3a0.dev1476}/src/stagehand/browser.py +56 -13
- {stagehand-4.0.3a0.dev1475 → stagehand-4.0.3a0.dev1476}/src/stagehand/browser_context.py +11 -9
- {stagehand-4.0.3a0.dev1475 → stagehand-4.0.3a0.dev1476}/src/stagehand/browserbase_session.py +18 -1
- {stagehand-4.0.3a0.dev1475 → stagehand-4.0.3a0.dev1476}/src/stagehand/rpc_client.py +0 -1
- {stagehand-4.0.3a0.dev1475 → stagehand-4.0.3a0.dev1476}/src/stagehand/stagehand.py +7 -3
- {stagehand-4.0.3a0.dev1475 → stagehand-4.0.3a0.dev1476}/README.md +0 -0
- {stagehand-4.0.3a0.dev1475 → stagehand-4.0.3a0.dev1476}/src/stagehand/__init__.py +0 -0
- {stagehand-4.0.3a0.dev1475 → stagehand-4.0.3a0.dev1476}/src/stagehand/_extension/blank.html +0 -0
- {stagehand-4.0.3a0.dev1475 → stagehand-4.0.3a0.dev1476}/src/stagehand/_extension/content-script.js +0 -0
- {stagehand-4.0.3a0.dev1475 → stagehand-4.0.3a0.dev1476}/src/stagehand/_extension/manifest.json +0 -0
- {stagehand-4.0.3a0.dev1475 → stagehand-4.0.3a0.dev1476}/src/stagehand/_extension/offscreen/service-worker-heartbeat.html +0 -0
- {stagehand-4.0.3a0.dev1475 → stagehand-4.0.3a0.dev1476}/src/stagehand/_extension/offscreen/service-worker-heartbeat.js +0 -0
- {stagehand-4.0.3a0.dev1475 → stagehand-4.0.3a0.dev1476}/src/stagehand/_extension/wake-service-worker.html +0 -0
- {stagehand-4.0.3a0.dev1475 → stagehand-4.0.3a0.dev1476}/src/stagehand/_extension/wake-service-worker.js +0 -0
- {stagehand-4.0.3a0.dev1475 → stagehand-4.0.3a0.dev1476}/src/stagehand/_generated/__init__.py +0 -0
- {stagehand-4.0.3a0.dev1475 → stagehand-4.0.3a0.dev1476}/src/stagehand/_sdk_identity.py +0 -0
- {stagehand-4.0.3a0.dev1475 → stagehand-4.0.3a0.dev1476}/src/stagehand/_validation.py +0 -0
- {stagehand-4.0.3a0.dev1475 → stagehand-4.0.3a0.dev1476}/src/stagehand/browser_clipboard.py +0 -0
- {stagehand-4.0.3a0.dev1475 → stagehand-4.0.3a0.dev1476}/src/stagehand/cdp_client.py +0 -0
- {stagehand-4.0.3a0.dev1475 → stagehand-4.0.3a0.dev1476}/src/stagehand/client_models.py +0 -0
- {stagehand-4.0.3a0.dev1475 → stagehand-4.0.3a0.dev1476}/src/stagehand/client_types.py +0 -0
- {stagehand-4.0.3a0.dev1475 → stagehand-4.0.3a0.dev1476}/src/stagehand/extension_assets.py +0 -0
- {stagehand-4.0.3a0.dev1475 → stagehand-4.0.3a0.dev1476}/src/stagehand/file_upload.py +0 -0
- {stagehand-4.0.3a0.dev1475 → stagehand-4.0.3a0.dev1476}/src/stagehand/locator.py +0 -0
- {stagehand-4.0.3a0.dev1475 → stagehand-4.0.3a0.dev1476}/src/stagehand/page.py +0 -0
- {stagehand-4.0.3a0.dev1475 → stagehand-4.0.3a0.dev1476}/src/stagehand/py.typed +0 -0
- {stagehand-4.0.3a0.dev1475 → stagehand-4.0.3a0.dev1476}/src/stagehand/response.py +0 -0
- {stagehand-4.0.3a0.dev1475 → stagehand-4.0.3a0.dev1476}/src/stagehand/timeouts.py +0 -0
- {stagehand-4.0.3a0.dev1475 → stagehand-4.0.3a0.dev1476}/src/stagehand/webmcp.py +0 -0
{stagehand-4.0.3a0.dev1475 → 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,
|
|
@@ -11555,10 +11549,6 @@ function createContextController(runtime) {
|
|
|
11555
11549
|
logger.debug("context.set_active_page", {});
|
|
11556
11550
|
return runtime.contextSetActivePage(params);
|
|
11557
11551
|
}
|
|
11558
|
-
async function close(_params, { logger }) {
|
|
11559
|
-
logger.debug("context.close", {});
|
|
11560
|
-
return runtime.contextClose();
|
|
11561
|
-
}
|
|
11562
11552
|
async function addInitScript(params, { logger }) {
|
|
11563
11553
|
logger.debug("context.add_init_script", {});
|
|
11564
11554
|
return runtime.contextAddInitScript(params);
|
|
@@ -11616,7 +11606,6 @@ function createContextController(runtime) {
|
|
|
11616
11606
|
newPage,
|
|
11617
11607
|
activePage,
|
|
11618
11608
|
setActivePage,
|
|
11619
|
-
close,
|
|
11620
11609
|
addInitScript,
|
|
11621
11610
|
setExtraHTTPHeaders,
|
|
11622
11611
|
getDomainPolicy,
|
|
@@ -12335,8 +12324,9 @@ function reportPageEventListenerError(error) {
|
|
|
12335
12324
|
//#endregion
|
|
12336
12325
|
//#region ../sdk-ts/src/browserContext.ts
|
|
12337
12326
|
var BrowserContext$1 = class {
|
|
12338
|
-
constructor(rpcClient) {
|
|
12327
|
+
constructor(rpcClient, closeBrowser) {
|
|
12339
12328
|
this.rpcClient = rpcClient;
|
|
12329
|
+
this.closeBrowser = closeBrowser;
|
|
12340
12330
|
}
|
|
12341
12331
|
get clipboard() {
|
|
12342
12332
|
return this.clipboardRef ??= new BrowserClipboard(this.rpcClient);
|
|
@@ -12356,9 +12346,10 @@ var BrowserContext$1 = class {
|
|
|
12356
12346
|
async setActivePage(page) {
|
|
12357
12347
|
await this.rpcClient.send(StagehandMethods.contextSetActivePage, { pageId: page.pageId });
|
|
12358
12348
|
}
|
|
12359
|
-
/** Close the
|
|
12349
|
+
/** Close the underlying browser. */
|
|
12360
12350
|
async close() {
|
|
12361
|
-
|
|
12351
|
+
if (!this.closeBrowser) throw new Error("Browser context is not attached to a browser");
|
|
12352
|
+
await this.closeBrowser();
|
|
12362
12353
|
}
|
|
12363
12354
|
async addInitScript(script, arg) {
|
|
12364
12355
|
const source = await normalizeInitScriptSource$1(script, arg, "context.addInitScript");
|
|
@@ -51020,7 +51011,6 @@ var RPCRouter = class {
|
|
|
51020
51011
|
case "context.new_page": return this.contextController.newPage(parseParams(StagehandMethods.contextNewPage, request.params), context);
|
|
51021
51012
|
case "context.active_page": return this.contextController.activePage(parseParams(StagehandMethods.contextActivePage, request.params), context);
|
|
51022
51013
|
case "context.set_active_page": return this.contextController.setActivePage(parseParams(StagehandMethods.contextSetActivePage, request.params), context);
|
|
51023
|
-
case "context.close": return this.contextController.close(parseParams(StagehandMethods.contextClose, request.params), context);
|
|
51024
51014
|
case "context.add_init_script": return this.contextController.addInitScript(parseParams(StagehandMethods.contextAddInitScript, request.params), context);
|
|
51025
51015
|
case "context.set_extra_http_headers": return this.contextController.setExtraHTTPHeaders(parseParams(StagehandMethods.contextSetExtraHTTPHeaders, request.params), context);
|
|
51026
51016
|
case "context.get_domain_policy": return this.contextController.getDomainPolicy(parseParams(StagehandMethods.contextGetDomainPolicy, request.params), context);
|
|
@@ -53447,7 +53437,7 @@ var WebTracerProvider = class extends BasicTracerProvider {
|
|
|
53447
53437
|
};
|
|
53448
53438
|
var package_default = {
|
|
53449
53439
|
name: "@browserbasehq/stagehand-extension",
|
|
53450
|
-
version: "1.0.2-alpha-
|
|
53440
|
+
version: "1.0.2-alpha-6555e81e837012088eb12a39c06aed0527a2e5af",
|
|
53451
53441
|
"private": true,
|
|
53452
53442
|
type: "module",
|
|
53453
53443
|
scripts: {
|
|
@@ -57030,10 +57020,6 @@ var StagehandRuntime = class {
|
|
|
57030
57020
|
await this.requireBrowserSession().setActivePage(page);
|
|
57031
57021
|
return { ok: true };
|
|
57032
57022
|
}
|
|
57033
|
-
async contextClose() {
|
|
57034
|
-
await this.close();
|
|
57035
|
-
return { closed: true };
|
|
57036
|
-
}
|
|
57037
57023
|
async contextAddInitScript(params) {
|
|
57038
57024
|
await this.requireBrowserSession().addInitScript(params.source);
|
|
57039
57025
|
return { ok: true };
|
|
@@ -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.dev1475 → 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.dev1475 → 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(
|
|
@@ -547,11 +551,11 @@ class Stagehand:
|
|
|
547
551
|
fail_closed: bool,
|
|
548
552
|
) -> None:
|
|
549
553
|
if fail_closed:
|
|
550
|
-
|
|
554
|
+
browser_invalidation = _invalidate_browser(browser)
|
|
551
555
|
try:
|
|
552
556
|
await self._release_resources()
|
|
553
557
|
finally:
|
|
554
|
-
await
|
|
558
|
+
await browser_invalidation
|
|
555
559
|
return
|
|
556
560
|
|
|
557
561
|
try:
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{stagehand-4.0.3a0.dev1475 → stagehand-4.0.3a0.dev1476}/src/stagehand/_extension/content-script.js
RENAMED
|
File without changes
|
{stagehand-4.0.3a0.dev1475 → 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.dev1475 → 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
|