stagehand 4.2.2a0.dev1615__tar.gz → 4.3.0a0.dev1620__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.
Files changed (39) hide show
  1. {stagehand-4.2.2a0.dev1615 → stagehand-4.3.0a0.dev1620}/PKG-INFO +1 -1
  2. {stagehand-4.2.2a0.dev1615 → stagehand-4.3.0a0.dev1620}/pyproject.toml +1 -1
  3. {stagehand-4.2.2a0.dev1615 → stagehand-4.3.0a0.dev1620}/src/stagehand/_extension/service-worker.js +22 -4
  4. {stagehand-4.2.2a0.dev1615 → stagehand-4.3.0a0.dev1620}/src/stagehand/_generated/protocol_version.py +1 -1
  5. {stagehand-4.2.2a0.dev1615 → stagehand-4.3.0a0.dev1620}/src/stagehand/_validation.py +13 -0
  6. {stagehand-4.2.2a0.dev1615 → stagehand-4.3.0a0.dev1620}/src/stagehand/browser.py +14 -1
  7. {stagehand-4.2.2a0.dev1615 → stagehand-4.3.0a0.dev1620}/src/stagehand/client_models.py +3 -1
  8. {stagehand-4.2.2a0.dev1615 → stagehand-4.3.0a0.dev1620}/src/stagehand/client_types.py +2 -0
  9. {stagehand-4.2.2a0.dev1615 → stagehand-4.3.0a0.dev1620}/src/stagehand/stagehand.py +4 -1
  10. {stagehand-4.2.2a0.dev1615 → stagehand-4.3.0a0.dev1620}/README.md +0 -0
  11. {stagehand-4.2.2a0.dev1615 → stagehand-4.3.0a0.dev1620}/src/stagehand/__init__.py +0 -0
  12. {stagehand-4.2.2a0.dev1615 → stagehand-4.3.0a0.dev1620}/src/stagehand/_extension/blank.html +0 -0
  13. {stagehand-4.2.2a0.dev1615 → stagehand-4.3.0a0.dev1620}/src/stagehand/_extension/content-script.js +0 -0
  14. {stagehand-4.2.2a0.dev1615 → stagehand-4.3.0a0.dev1620}/src/stagehand/_extension/manifest.json +0 -0
  15. {stagehand-4.2.2a0.dev1615 → stagehand-4.3.0a0.dev1620}/src/stagehand/_extension/offscreen/service-worker-heartbeat.html +0 -0
  16. {stagehand-4.2.2a0.dev1615 → stagehand-4.3.0a0.dev1620}/src/stagehand/_extension/offscreen/service-worker-heartbeat.js +0 -0
  17. {stagehand-4.2.2a0.dev1615 → stagehand-4.3.0a0.dev1620}/src/stagehand/_extension/wake-service-worker.html +0 -0
  18. {stagehand-4.2.2a0.dev1615 → stagehand-4.3.0a0.dev1620}/src/stagehand/_extension/wake-service-worker.js +0 -0
  19. {stagehand-4.2.2a0.dev1615 → stagehand-4.3.0a0.dev1620}/src/stagehand/_generated/__init__.py +0 -0
  20. {stagehand-4.2.2a0.dev1615 → stagehand-4.3.0a0.dev1620}/src/stagehand/_generated/input_types.py +0 -0
  21. {stagehand-4.2.2a0.dev1615 → stagehand-4.3.0a0.dev1620}/src/stagehand/_generated/models.py +0 -0
  22. {stagehand-4.2.2a0.dev1615 → stagehand-4.3.0a0.dev1620}/src/stagehand/_sdk_identity.py +0 -0
  23. {stagehand-4.2.2a0.dev1615 → stagehand-4.3.0a0.dev1620}/src/stagehand/browser_clipboard.py +0 -0
  24. {stagehand-4.2.2a0.dev1615 → stagehand-4.3.0a0.dev1620}/src/stagehand/browser_context.py +0 -0
  25. {stagehand-4.2.2a0.dev1615 → stagehand-4.3.0a0.dev1620}/src/stagehand/browserbase_connection.py +0 -0
  26. {stagehand-4.2.2a0.dev1615 → stagehand-4.3.0a0.dev1620}/src/stagehand/browserbase_rpc.py +0 -0
  27. {stagehand-4.2.2a0.dev1615 → stagehand-4.3.0a0.dev1620}/src/stagehand/browserbase_services.py +0 -0
  28. {stagehand-4.2.2a0.dev1615 → stagehand-4.3.0a0.dev1620}/src/stagehand/browserbase_session.py +0 -0
  29. {stagehand-4.2.2a0.dev1615 → stagehand-4.3.0a0.dev1620}/src/stagehand/browserbase_transport.py +0 -0
  30. {stagehand-4.2.2a0.dev1615 → stagehand-4.3.0a0.dev1620}/src/stagehand/cdp_client.py +0 -0
  31. {stagehand-4.2.2a0.dev1615 → stagehand-4.3.0a0.dev1620}/src/stagehand/extension_assets.py +0 -0
  32. {stagehand-4.2.2a0.dev1615 → stagehand-4.3.0a0.dev1620}/src/stagehand/file_upload.py +0 -0
  33. {stagehand-4.2.2a0.dev1615 → stagehand-4.3.0a0.dev1620}/src/stagehand/locator.py +0 -0
  34. {stagehand-4.2.2a0.dev1615 → stagehand-4.3.0a0.dev1620}/src/stagehand/page.py +0 -0
  35. {stagehand-4.2.2a0.dev1615 → stagehand-4.3.0a0.dev1620}/src/stagehand/py.typed +0 -0
  36. {stagehand-4.2.2a0.dev1615 → stagehand-4.3.0a0.dev1620}/src/stagehand/response.py +0 -0
  37. {stagehand-4.2.2a0.dev1615 → stagehand-4.3.0a0.dev1620}/src/stagehand/rpc_client.py +0 -0
  38. {stagehand-4.2.2a0.dev1615 → stagehand-4.3.0a0.dev1620}/src/stagehand/timeouts.py +0 -0
  39. {stagehand-4.2.2a0.dev1615 → stagehand-4.3.0a0.dev1620}/src/stagehand/webmcp.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: stagehand
3
- Version: 4.2.2a0.dev1615
3
+ Version: 4.3.0a0.dev1620
4
4
  Summary: Browserbase's SDK for building browser agents
5
5
  Keywords: ai,agent,ai-agent,browser,browser-agent,browser-automation,computer-use,headless,playwright,cdp,llm,automation,web-scraping,testing
6
6
  Author: Browserbase
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "stagehand"
3
- version = "4.2.2a0.dev1615"
3
+ version = "4.3.0a0.dev1620"
4
4
  description = "Browserbase's SDK for building browser agents"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.11"
@@ -7363,7 +7363,7 @@ function isRecord$1(value) {
7363
7363
  }
7364
7364
  var package_default$1 = {
7365
7365
  name: "@browserbasehq/stagehand-protocol",
7366
- version: "3.0.0-alpha-c6b6f278c880d2f8b770ac0c1ecc63f248515968",
7366
+ version: "3.0.0-alpha-76cd7e0f2ff04b0fb5c07e27e0db70746d0ad3c8",
7367
7367
  "private": true,
7368
7368
  type: "module",
7369
7369
  exports: {
@@ -12529,7 +12529,22 @@ strictObject({
12529
12529
  }).meta({ id: "LocalBrowserLaunchOptions" });
12530
12530
  strictObject({
12531
12531
  cdpUrl: string().min(1),
12532
- extensionId: string().optional()
12532
+ extensionId: string().optional(),
12533
+ /**
12534
+ * Browser-level CDP WebSocket URL dialed by the extension inside Chrome.
12535
+ * Defaults to the client's URL. Set this when the client connects through
12536
+ * a gateway the extension cannot or should not use.
12537
+ */
12538
+ extensionCdpUrl: url({
12539
+ protocol: /^wss?$/,
12540
+ hostname: /.+/
12541
+ }).refine((value) => {
12542
+ try {
12543
+ return new URL(value).port !== "0";
12544
+ } catch {
12545
+ return false;
12546
+ }
12547
+ }, { message: "Port must be between 1 and 65535" }).optional()
12533
12548
  }).meta({ id: "LocalBrowserConnectOptions" });
12534
12549
  var DEFAULT_BROWSERBASE_URL = "https://api.browserbase.com";
12535
12550
  var BrowserbaseClientOptionsSchema = strictObject({
@@ -54456,7 +54471,7 @@ var WebTracerProvider = class extends BasicTracerProvider {
54456
54471
  };
54457
54472
  var package_default = {
54458
54473
  name: "@browserbasehq/stagehand-extension",
54459
- version: "1.2.0-alpha-c6b6f278c880d2f8b770ac0c1ecc63f248515968",
54474
+ version: "1.2.0-alpha-76cd7e0f2ff04b0fb5c07e27e0db70746d0ad3c8",
54460
54475
  "private": true,
54461
54476
  type: "module",
54462
54477
  scripts: {
@@ -58376,12 +58391,14 @@ var StagehandRuntime = class {
58376
58391
  const { cdpUrl } = params;
58377
58392
  const previousSession = this.browserSession;
58378
58393
  this.browserSession = void 0;
58394
+ this.browserSessionCdpUrl = void 0;
58379
58395
  this.disposeAllPageEventSubscriptions();
58380
58396
  this.pagesById.clear();
58381
58397
  this.responseHandles.clear();
58382
58398
  await previousSession?.close();
58383
58399
  try {
58384
58400
  this.browserSession = await this.adapters.browserSessionFactory(cdpUrl, this.logger, bootstrapLogger);
58401
+ this.browserSessionCdpUrl = cdpUrl;
58385
58402
  } catch (error) {
58386
58403
  await this.browserSession?.close();
58387
58404
  this.browserSession = void 0;
@@ -58396,7 +58413,7 @@ var StagehandRuntime = class {
58396
58413
  const state = this.state.getState();
58397
58414
  if (state.status !== "idle") throw new Error("A Stagehand instance is already initialized");
58398
58415
  this.logger.setLevel(params.logLevel);
58399
- if (!this.browserSession?.connected) {
58416
+ if (!this.browserSession?.connected || params.browserCdpUrl !== void 0 && params.browserCdpUrl !== this.browserSessionCdpUrl) {
58400
58417
  if (!params.browserCdpUrl) throw new Error("stagehand.init requires browserCdpUrl until resident mode is active");
58401
58418
  await this.replaceBrowserConnection({ cdpUrl: params.browserCdpUrl }, logger);
58402
58419
  }
@@ -58798,6 +58815,7 @@ var StagehandRuntime = class {
58798
58815
  await this.enqueueLifecycle(async () => {
58799
58816
  const session = this.browserSession;
58800
58817
  this.browserSession = void 0;
58818
+ this.browserSessionCdpUrl = void 0;
58801
58819
  this.clearStagehandInstance();
58802
58820
  await session?.close();
58803
58821
  });
@@ -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 = '3.0.0-alpha-c6b6f278c880d2f8b770ac0c1ecc63f248515968'
4
+ STAGEHAND_PROTOCOL_VERSION = '3.0.0-alpha-76cd7e0f2ff04b0fb5c07e27e0db70746d0ad3c8'
@@ -16,6 +16,19 @@ def _validate_url(value: str) -> str:
16
16
  WireUrl = Annotated[str, AfterValidator(_validate_url)]
17
17
 
18
18
 
19
+ def _validate_websocket_url(value: str) -> str:
20
+ parsed = urlparse(value)
21
+ if parsed.scheme not in ("ws", "wss") or not parsed.hostname:
22
+ raise ValueError("must be a ws:// or wss:// URL with a host")
23
+ _url_adapter.validate_python(value)
24
+ if parsed.port == 0:
25
+ raise ValueError("port must be between 1 and 65535")
26
+ return value
27
+
28
+
29
+ WireWebSocketUrl = Annotated[str, AfterValidator(_validate_websocket_url)]
30
+
31
+
19
32
  class WireModel(BaseModel):
20
33
  model_config = ConfigDict(validate_assignment=True, allow_inf_nan=False)
21
34
 
@@ -85,6 +85,8 @@ _CHROME_REQUEST_TIMEOUT_SECONDS = 0.1
85
85
  class _WorkerInitMetadata:
86
86
  api_key: str | None
87
87
  browser: BrowserSessionMetadata | None
88
+ browser_cdp_url: str | None = None
89
+ """The CDP WebSocket the extension dials, when it is not the client's own."""
88
90
 
89
91
 
90
92
  @dataclass(frozen=True)
@@ -533,18 +535,25 @@ class LocalBrowser:
533
535
  *,
534
536
  cdp_url: str,
535
537
  extension_id: str | None = None,
538
+ extension_cdp_url: str | None = None,
536
539
  ) -> StagehandBrowser:
537
540
  """Connect to an existing browser.
538
541
 
539
542
  Args:
540
543
  extension_id: Deprecated and ignored. Omit this argument; Stagehand
541
544
  discovers the installed extension automatically.
545
+ extension_cdp_url: The browser-level CDP WebSocket that Stagehand's
546
+ extension dials from inside the browser. Defaults to the one this
547
+ client connected to. Set it when the client reaches Chrome through
548
+ a proxy the browser cannot or should not use, such as an
549
+ authenticated gateway whose URL carries credentials.
542
550
  """
543
551
  options = LocalBrowserConnectOptions.model_validate({
544
552
  name: value
545
553
  for name, value in (
546
554
  ("cdp_url", cdp_url),
547
555
  ("extension_id", extension_id),
556
+ ("extension_cdp_url", extension_cdp_url),
548
557
  )
549
558
  if value is not None
550
559
  })
@@ -553,7 +562,11 @@ class LocalBrowser:
553
562
  origin="connected",
554
563
  source=_ConnectedBrowserSource(options.cdp_url),
555
564
  local_extension_dir=lambda: str(extension_directory()),
556
- worker_init_metadata=_WorkerInitMetadata(api_key=None, browser=None),
565
+ worker_init_metadata=_WorkerInitMetadata(
566
+ api_key=None,
567
+ browser=None,
568
+ browser_cdp_url=options.extension_cdp_url,
569
+ ),
557
570
  )
558
571
 
559
572
 
@@ -18,7 +18,7 @@ from ._generated.models import (
18
18
  StagehandResultMetadata,
19
19
  TelemetryConfig,
20
20
  )
21
- from ._validation import WireModel, WireUrl
21
+ from ._validation import WireModel, WireUrl, WireWebSocketUrl
22
22
  from .browserbase_session import DEFAULT_BROWSERBASE_URL
23
23
  from .client_types import Cache as CacheInput
24
24
 
@@ -108,6 +108,8 @@ class LocalBrowserConnectOptions(WireModel):
108
108
  cdp_url: Annotated[str, Field(min_length=1)]
109
109
  extension_id: str | None = None
110
110
  """Deprecated and ignored. Omit this field; Stagehand discovers the extension automatically."""
111
+ extension_cdp_url: WireWebSocketUrl | None = None
112
+ """Browser-level CDP WebSocket the extension dials, when it differs from `cdp_url`."""
111
113
 
112
114
 
113
115
  class BrowserbaseClientOptions(WireModel):
@@ -67,6 +67,8 @@ class LocalBrowserConnectOptions(TypedDict):
67
67
  cdp_url: str
68
68
  extension_id: NotRequired[str]
69
69
  """Deprecated and ignored. Omit this field; Stagehand discovers the extension automatically."""
70
+ extension_cdp_url: NotRequired[str]
71
+ """Browser-level CDP WebSocket the extension dials, when it differs from `cdp_url`."""
70
72
 
71
73
 
72
74
  class BrowserbaseClientOptions(TypedDict, total=False):
@@ -503,7 +503,10 @@ class Stagehand:
503
503
  def _worker_init_params(
504
504
  self, claimed: _ClaimedBrowser, *, has_browserbase_connection: bool
505
505
  ) -> StagehandInitParams:
506
- browser_cdp_url = claimed.cdp_client.web_socket_debugger_url
506
+ browser_cdp_url = (
507
+ claimed.worker_init_metadata.browser_cdp_url
508
+ or claimed.cdp_client.web_socket_debugger_url
509
+ )
507
510
  if browser_cdp_url is None:
508
511
  raise RuntimeError("The browser CDP WebSocket URL is unavailable")
509
512
  values = self._create_config.model_dump(