stagehand 4.2.0a0.dev1533__tar.gz → 4.2.0a0.dev1535__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 (36) hide show
  1. {stagehand-4.2.0a0.dev1533 → stagehand-4.2.0a0.dev1535}/PKG-INFO +1 -1
  2. {stagehand-4.2.0a0.dev1533 → stagehand-4.2.0a0.dev1535}/pyproject.toml +1 -1
  3. {stagehand-4.2.0a0.dev1533 → stagehand-4.2.0a0.dev1535}/src/stagehand/_extension/service-worker.js +58 -74
  4. {stagehand-4.2.0a0.dev1533 → stagehand-4.2.0a0.dev1535}/src/stagehand/_generated/protocol_version.py +1 -1
  5. {stagehand-4.2.0a0.dev1533 → stagehand-4.2.0a0.dev1535}/README.md +0 -0
  6. {stagehand-4.2.0a0.dev1533 → stagehand-4.2.0a0.dev1535}/src/stagehand/__init__.py +0 -0
  7. {stagehand-4.2.0a0.dev1533 → stagehand-4.2.0a0.dev1535}/src/stagehand/_extension/blank.html +0 -0
  8. {stagehand-4.2.0a0.dev1533 → stagehand-4.2.0a0.dev1535}/src/stagehand/_extension/content-script.js +0 -0
  9. {stagehand-4.2.0a0.dev1533 → stagehand-4.2.0a0.dev1535}/src/stagehand/_extension/manifest.json +0 -0
  10. {stagehand-4.2.0a0.dev1533 → stagehand-4.2.0a0.dev1535}/src/stagehand/_extension/offscreen/service-worker-heartbeat.html +0 -0
  11. {stagehand-4.2.0a0.dev1533 → stagehand-4.2.0a0.dev1535}/src/stagehand/_extension/offscreen/service-worker-heartbeat.js +0 -0
  12. {stagehand-4.2.0a0.dev1533 → stagehand-4.2.0a0.dev1535}/src/stagehand/_extension/wake-service-worker.html +0 -0
  13. {stagehand-4.2.0a0.dev1533 → stagehand-4.2.0a0.dev1535}/src/stagehand/_extension/wake-service-worker.js +0 -0
  14. {stagehand-4.2.0a0.dev1533 → stagehand-4.2.0a0.dev1535}/src/stagehand/_generated/__init__.py +0 -0
  15. {stagehand-4.2.0a0.dev1533 → stagehand-4.2.0a0.dev1535}/src/stagehand/_generated/input_types.py +0 -0
  16. {stagehand-4.2.0a0.dev1533 → stagehand-4.2.0a0.dev1535}/src/stagehand/_generated/models.py +0 -0
  17. {stagehand-4.2.0a0.dev1533 → stagehand-4.2.0a0.dev1535}/src/stagehand/_sdk_identity.py +0 -0
  18. {stagehand-4.2.0a0.dev1533 → stagehand-4.2.0a0.dev1535}/src/stagehand/_validation.py +0 -0
  19. {stagehand-4.2.0a0.dev1533 → stagehand-4.2.0a0.dev1535}/src/stagehand/browser.py +0 -0
  20. {stagehand-4.2.0a0.dev1533 → stagehand-4.2.0a0.dev1535}/src/stagehand/browser_clipboard.py +0 -0
  21. {stagehand-4.2.0a0.dev1533 → stagehand-4.2.0a0.dev1535}/src/stagehand/browser_context.py +0 -0
  22. {stagehand-4.2.0a0.dev1533 → stagehand-4.2.0a0.dev1535}/src/stagehand/browserbase_services.py +0 -0
  23. {stagehand-4.2.0a0.dev1533 → stagehand-4.2.0a0.dev1535}/src/stagehand/browserbase_session.py +0 -0
  24. {stagehand-4.2.0a0.dev1533 → stagehand-4.2.0a0.dev1535}/src/stagehand/cdp_client.py +0 -0
  25. {stagehand-4.2.0a0.dev1533 → stagehand-4.2.0a0.dev1535}/src/stagehand/client_models.py +0 -0
  26. {stagehand-4.2.0a0.dev1533 → stagehand-4.2.0a0.dev1535}/src/stagehand/client_types.py +0 -0
  27. {stagehand-4.2.0a0.dev1533 → stagehand-4.2.0a0.dev1535}/src/stagehand/extension_assets.py +0 -0
  28. {stagehand-4.2.0a0.dev1533 → stagehand-4.2.0a0.dev1535}/src/stagehand/file_upload.py +0 -0
  29. {stagehand-4.2.0a0.dev1533 → stagehand-4.2.0a0.dev1535}/src/stagehand/locator.py +0 -0
  30. {stagehand-4.2.0a0.dev1533 → stagehand-4.2.0a0.dev1535}/src/stagehand/page.py +0 -0
  31. {stagehand-4.2.0a0.dev1533 → stagehand-4.2.0a0.dev1535}/src/stagehand/py.typed +0 -0
  32. {stagehand-4.2.0a0.dev1533 → stagehand-4.2.0a0.dev1535}/src/stagehand/response.py +0 -0
  33. {stagehand-4.2.0a0.dev1533 → stagehand-4.2.0a0.dev1535}/src/stagehand/rpc_client.py +0 -0
  34. {stagehand-4.2.0a0.dev1533 → stagehand-4.2.0a0.dev1535}/src/stagehand/stagehand.py +0 -0
  35. {stagehand-4.2.0a0.dev1533 → stagehand-4.2.0a0.dev1535}/src/stagehand/timeouts.py +0 -0
  36. {stagehand-4.2.0a0.dev1533 → stagehand-4.2.0a0.dev1535}/src/stagehand/webmcp.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: stagehand
3
- Version: 4.2.0a0.dev1533
3
+ Version: 4.2.0a0.dev1535
4
4
  Summary: Browserbase's SDK for building browser agents
5
5
  Keywords: ai,browser,automation,web-scraping,testing
6
6
  Author: Browserbase
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "stagehand"
3
- version = "4.2.0a0.dev1533"
3
+ version = "4.2.0a0.dev1535"
4
4
  description = "Browserbase's SDK for building browser agents"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.11"
@@ -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.1.0-alpha-2c098f44857665045dbed31168ac36af920774d9",
7362
+ version: "2.1.0-alpha-f3543d321e6c0edc800d9e73c79dd9d47f622189",
7363
7363
  "private": true,
7364
7364
  type: "module",
7365
7365
  exports: {
@@ -14633,6 +14633,13 @@ var Locator = class Locator {
14633
14633
  };
14634
14634
  //#endregion
14635
14635
  //#region understudy/frameLocator.ts
14636
+ /** Best-effort readiness budget for frame transitions, not an overall operation timeout. */
14637
+ var FRAME_LOCATOR_READY_TIMEOUT_MS = 1200;
14638
+ /**
14639
+ * Best-effort timeout for each locator-world attempt. Fallback eligibility can
14640
+ * extend an attempt while it waits for the main world.
14641
+ */
14642
+ var LOCATOR_WORLD_ATTEMPT_TIMEOUT_MS = 200;
14636
14643
  /**
14637
14644
  * FrameLocator: resolves iframe elements to their child Frames and allows
14638
14645
  * creating locators scoped to that frame. Supports chaining.
@@ -14658,12 +14665,18 @@ var FrameLocator = class FrameLocator {
14658
14665
  await parentSession.send("DOM.enable").catch(() => {});
14659
14666
  const iframeBackendNodeId = (await parentSession.send("DOM.describeNode", { objectId })).node.backendNodeId;
14660
14667
  const childIds = await listDirectChildFrameIdsFromRegistry(this.page, parentFrame.frameId, 1e3);
14661
- for (const fid of childIds) try {
14662
- if ((await parentSession.send("DOM.getFrameOwner", { frameId: fid })).backendNodeId === iframeBackendNodeId) {
14663
- await ensureChildFrameReady(this.page, parentFrame, fid, 1200);
14668
+ for (const fid of childIds) {
14669
+ let owner;
14670
+ try {
14671
+ owner = await parentSession.send("DOM.getFrameOwner", { frameId: fid });
14672
+ } catch {
14673
+ continue;
14674
+ }
14675
+ if (owner.backendNodeId === iframeBackendNodeId) {
14676
+ await ensureChildFrameReady(this.page, fid, FRAME_LOCATOR_READY_TIMEOUT_MS);
14664
14677
  return this.page.frameForId(fid);
14665
14678
  }
14666
- } catch {}
14679
+ }
14667
14680
  throw new Error(`Unable to obtain a content frame for selector: ${this.selector}`);
14668
14681
  } finally {
14669
14682
  await parentSession.send("Runtime.releaseObject", { objectId }).catch(() => {});
@@ -14758,66 +14771,25 @@ function findFrameNode(tree, targetId) {
14758
14771
  }
14759
14772
  }
14760
14773
  /**
14761
- * Ensure we can evaluate in the child frame with minimal delay.
14762
- * - If the child is same-process: parent session owns it and main world appears quickly.
14763
- * - If OOPIF and adoption not finished: wait briefly for ownership change, then main world.
14774
+ * Block until the Stagehand locator/extension world is usable in the child frame.
14775
+ * Re-resolves CDP session ownership on each attempt so OOPIF adoption cannot pin
14776
+ * the wait to a stale session for the full budget.
14764
14777
  */
14765
- async function ensureChildFrameReady(page, parentFrame, childFrameId, budgetMs) {
14766
- const parentSession = parentFrame.session;
14778
+ async function ensureChildFrameReady(page, childFrameId, budgetMs) {
14767
14779
  const deadline = Date.now() + Math.max(0, budgetMs);
14768
- const owner = page.getSessionForFrame(childFrameId);
14769
- if (owner && owner !== parentSession) {
14770
- try {
14771
- await executionContexts.waitForMainWorld(owner, childFrameId, 600);
14772
- } catch {}
14773
- return;
14774
- }
14775
- const hasMainWorldOnParent = () => {
14780
+ let lastError;
14781
+ while (Date.now() < deadline) {
14782
+ const session = page.getSessionForFrame(childFrameId);
14783
+ const remaining = deadline - Date.now();
14784
+ if (remaining <= 0) break;
14776
14785
  try {
14777
- return executionContexts.getMainWorld(parentSession, childFrameId) !== null;
14778
- } catch {
14779
- return false;
14786
+ await executionContexts.waitForLocatorWorld(session, childFrameId, Math.min(remaining, LOCATOR_WORLD_ATTEMPT_TIMEOUT_MS));
14787
+ if (page.getSessionForFrame(childFrameId) === session) return;
14788
+ } catch (error) {
14789
+ lastError = error;
14780
14790
  }
14781
- };
14782
- if (hasMainWorldOnParent()) return;
14783
- await parentSession.send("Page.setLifecycleEventsEnabled", { enabled: true }).catch(() => {});
14784
- await parentSession.send("Runtime.enable").catch(() => {});
14785
- await new Promise((resolve) => {
14786
- let done = false;
14787
- const finish = () => {
14788
- if (done) return;
14789
- done = true;
14790
- parentSession.off("Page.lifecycleEvent", onLifecycle);
14791
- resolve();
14792
- };
14793
- const onLifecycle = (evt) => {
14794
- if (evt.frameId !== childFrameId || evt.name !== "DOMContentLoaded" && evt.name !== "load" && evt.name !== "networkIdle" && evt.name !== "networkidle") return;
14795
- if (hasMainWorldOnParent()) return finish();
14796
- try {
14797
- const nowOwner = page.getSessionForFrame(childFrameId);
14798
- if (nowOwner && nowOwner !== parentSession) {
14799
- const left = Math.max(150, deadline - Date.now());
14800
- executionContexts.waitForMainWorld(nowOwner, childFrameId, left).finally(finish);
14801
- }
14802
- } catch {}
14803
- };
14804
- parentSession.on("Page.lifecycleEvent", onLifecycle);
14805
- const tick = () => {
14806
- if (done) return;
14807
- if (hasMainWorldOnParent()) return finish();
14808
- try {
14809
- const nowOwner = page.getSessionForFrame(childFrameId);
14810
- if (nowOwner && nowOwner !== parentSession) {
14811
- const left = Math.max(150, deadline - Date.now());
14812
- executionContexts.waitForMainWorld(nowOwner, childFrameId, left).finally(finish);
14813
- return;
14814
- }
14815
- } catch {}
14816
- if (Date.now() >= deadline) return finish();
14817
- setTimeout(tick, 50);
14818
- };
14819
- tick();
14820
- });
14791
+ }
14792
+ throw new Error(`Locator world not ready for frame ${childFrameId}: exhausted ${budgetMs} ms frame-readiness budget`, { cause: lastError });
14821
14793
  }
14822
14794
  //#endregion
14823
14795
  //#region understudy/a11y/snapshot/xpathUtils.ts
@@ -15179,27 +15151,39 @@ var DeepLocatorDelegate = class DeepLocatorDelegate {
15179
15151
  function deepLocatorFromPage(page, root, selector) {
15180
15152
  return new DeepLocatorDelegate(page, root, selector);
15181
15153
  }
15182
- async function resolveDeepXPathTarget(page, root, xpathOrSelector) {
15154
+ /**
15155
+ * Plan deep-XPath frame hops without resolving frames.
15156
+ * An iframe/frame step becomes a hop only when further selector steps follow it,
15157
+ * so a trailing iframe remains a parent-frame element target.
15158
+ */
15159
+ function planDeepXPathTarget(xpathOrSelector) {
15183
15160
  let path = xpathOrSelector.trim();
15184
15161
  if (path.startsWith("xpath=")) path = path.slice(6).trim();
15185
15162
  if (!path.startsWith("/")) path = "/" + path;
15186
15163
  const steps = parseXPath(path);
15187
- let fl;
15164
+ const frameHopSelectors = [];
15188
15165
  let buf = [];
15189
- const flushIntoFrameLocator = () => {
15190
- if (!buf.length) return;
15191
- const selectorForIframe = "xpath=" + buildXPathFromSteps(buf);
15192
- fl = fl ? fl.frameLocator(selectorForIframe) : frameLocatorFromFrame(page, root, selectorForIframe);
15193
- buf = [];
15194
- };
15195
- for (const st of steps) {
15166
+ for (let i = 0; i < steps.length; i++) {
15167
+ const st = steps[i];
15196
15168
  buf.push(st);
15197
- if (IFRAME_STEP_RE.test(st.name)) flushIntoFrameLocator();
15169
+ const hasStepsAfter = i < steps.length - 1;
15170
+ if (IFRAME_STEP_RE.test(st.name) && hasStepsAfter) {
15171
+ frameHopSelectors.push("xpath=" + buildXPathFromSteps(buf));
15172
+ buf = [];
15173
+ }
15198
15174
  }
15199
- const finalSelector = "xpath=" + buildXPathFromSteps(buf);
15175
+ return {
15176
+ frameHopSelectors,
15177
+ finalSelector: "xpath=" + buildXPathFromSteps(buf)
15178
+ };
15179
+ }
15180
+ async function resolveDeepXPathTarget(page, root, xpathOrSelector) {
15181
+ const plan = planDeepXPathTarget(xpathOrSelector);
15182
+ let fl;
15183
+ for (const hop of plan.frameHopSelectors) fl = fl ? fl.frameLocator(hop) : frameLocatorFromFrame(page, root, hop);
15200
15184
  return {
15201
15185
  frame: fl ? await fl.resolveFrame() : root,
15202
- selector: finalSelector
15186
+ selector: plan.finalSelector
15203
15187
  };
15204
15188
  }
15205
15189
  //#endregion
@@ -53981,7 +53965,7 @@ var WebTracerProvider = class extends BasicTracerProvider {
53981
53965
  };
53982
53966
  var package_default = {
53983
53967
  name: "@browserbasehq/stagehand-extension",
53984
- version: "1.1.0-alpha-2c098f44857665045dbed31168ac36af920774d9",
53968
+ version: "1.1.0-alpha-f3543d321e6c0edc800d9e73c79dd9d47f622189",
53985
53969
  "private": true,
53986
53970
  type: "module",
53987
53971
  scripts: {
@@ -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.1.0-alpha-2c098f44857665045dbed31168ac36af920774d9'
4
+ STAGEHAND_PROTOCOL_VERSION = '2.1.0-alpha-f3543d321e6c0edc800d9e73c79dd9d47f622189'