stagehand 4.4.0a0.dev1660__tar.gz → 4.4.0a0.dev1661__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.4.0a0.dev1660 → stagehand-4.4.0a0.dev1661}/PKG-INFO +1 -1
  2. {stagehand-4.4.0a0.dev1660 → stagehand-4.4.0a0.dev1661}/pyproject.toml +1 -1
  3. {stagehand-4.4.0a0.dev1660 → stagehand-4.4.0a0.dev1661}/src/stagehand/_extension/service-worker.js +96 -38
  4. {stagehand-4.4.0a0.dev1660 → stagehand-4.4.0a0.dev1661}/src/stagehand/_generated/protocol_version.py +1 -1
  5. {stagehand-4.4.0a0.dev1660 → stagehand-4.4.0a0.dev1661}/README.md +0 -0
  6. {stagehand-4.4.0a0.dev1660 → stagehand-4.4.0a0.dev1661}/src/stagehand/__init__.py +0 -0
  7. {stagehand-4.4.0a0.dev1660 → stagehand-4.4.0a0.dev1661}/src/stagehand/_extension/blank.html +0 -0
  8. {stagehand-4.4.0a0.dev1660 → stagehand-4.4.0a0.dev1661}/src/stagehand/_extension/content-script.js +0 -0
  9. {stagehand-4.4.0a0.dev1660 → stagehand-4.4.0a0.dev1661}/src/stagehand/_extension/manifest.json +0 -0
  10. {stagehand-4.4.0a0.dev1660 → stagehand-4.4.0a0.dev1661}/src/stagehand/_extension/offscreen/service-worker-heartbeat.html +0 -0
  11. {stagehand-4.4.0a0.dev1660 → stagehand-4.4.0a0.dev1661}/src/stagehand/_extension/offscreen/service-worker-heartbeat.js +0 -0
  12. {stagehand-4.4.0a0.dev1660 → stagehand-4.4.0a0.dev1661}/src/stagehand/_extension/wake-service-worker.html +0 -0
  13. {stagehand-4.4.0a0.dev1660 → stagehand-4.4.0a0.dev1661}/src/stagehand/_extension/wake-service-worker.js +0 -0
  14. {stagehand-4.4.0a0.dev1660 → stagehand-4.4.0a0.dev1661}/src/stagehand/_generated/__init__.py +0 -0
  15. {stagehand-4.4.0a0.dev1660 → stagehand-4.4.0a0.dev1661}/src/stagehand/_generated/input_types.py +0 -0
  16. {stagehand-4.4.0a0.dev1660 → stagehand-4.4.0a0.dev1661}/src/stagehand/_generated/models.py +0 -0
  17. {stagehand-4.4.0a0.dev1660 → stagehand-4.4.0a0.dev1661}/src/stagehand/_sdk_identity.py +0 -0
  18. {stagehand-4.4.0a0.dev1660 → stagehand-4.4.0a0.dev1661}/src/stagehand/_validation.py +0 -0
  19. {stagehand-4.4.0a0.dev1660 → stagehand-4.4.0a0.dev1661}/src/stagehand/browser.py +0 -0
  20. {stagehand-4.4.0a0.dev1660 → stagehand-4.4.0a0.dev1661}/src/stagehand/browser_clipboard.py +0 -0
  21. {stagehand-4.4.0a0.dev1660 → stagehand-4.4.0a0.dev1661}/src/stagehand/browser_context.py +0 -0
  22. {stagehand-4.4.0a0.dev1660 → stagehand-4.4.0a0.dev1661}/src/stagehand/browserbase_connection.py +0 -0
  23. {stagehand-4.4.0a0.dev1660 → stagehand-4.4.0a0.dev1661}/src/stagehand/browserbase_rpc.py +0 -0
  24. {stagehand-4.4.0a0.dev1660 → stagehand-4.4.0a0.dev1661}/src/stagehand/browserbase_services.py +0 -0
  25. {stagehand-4.4.0a0.dev1660 → stagehand-4.4.0a0.dev1661}/src/stagehand/browserbase_session.py +0 -0
  26. {stagehand-4.4.0a0.dev1660 → stagehand-4.4.0a0.dev1661}/src/stagehand/browserbase_transport.py +0 -0
  27. {stagehand-4.4.0a0.dev1660 → stagehand-4.4.0a0.dev1661}/src/stagehand/cdp_client.py +0 -0
  28. {stagehand-4.4.0a0.dev1660 → stagehand-4.4.0a0.dev1661}/src/stagehand/client_models.py +0 -0
  29. {stagehand-4.4.0a0.dev1660 → stagehand-4.4.0a0.dev1661}/src/stagehand/client_types.py +0 -0
  30. {stagehand-4.4.0a0.dev1660 → stagehand-4.4.0a0.dev1661}/src/stagehand/extension_assets.py +0 -0
  31. {stagehand-4.4.0a0.dev1660 → stagehand-4.4.0a0.dev1661}/src/stagehand/file_upload.py +0 -0
  32. {stagehand-4.4.0a0.dev1660 → stagehand-4.4.0a0.dev1661}/src/stagehand/locator.py +0 -0
  33. {stagehand-4.4.0a0.dev1660 → stagehand-4.4.0a0.dev1661}/src/stagehand/page.py +0 -0
  34. {stagehand-4.4.0a0.dev1660 → stagehand-4.4.0a0.dev1661}/src/stagehand/py.typed +0 -0
  35. {stagehand-4.4.0a0.dev1660 → stagehand-4.4.0a0.dev1661}/src/stagehand/response.py +0 -0
  36. {stagehand-4.4.0a0.dev1660 → stagehand-4.4.0a0.dev1661}/src/stagehand/rpc_client.py +0 -0
  37. {stagehand-4.4.0a0.dev1660 → stagehand-4.4.0a0.dev1661}/src/stagehand/stagehand.py +0 -0
  38. {stagehand-4.4.0a0.dev1660 → stagehand-4.4.0a0.dev1661}/src/stagehand/timeouts.py +0 -0
  39. {stagehand-4.4.0a0.dev1660 → stagehand-4.4.0a0.dev1661}/src/stagehand/webmcp.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: stagehand
3
- Version: 4.4.0a0.dev1660
3
+ Version: 4.4.0a0.dev1661
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.4.0a0.dev1660"
3
+ version = "4.4.0a0.dev1661"
4
4
  description = "Browserbase's SDK for building browser agents"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.11"
@@ -9206,7 +9206,7 @@ function isRecord$1(value) {
9206
9206
  }
9207
9207
  var package_default$1 = {
9208
9208
  name: "@browserbasehq/stagehand-protocol",
9209
- version: "3.1.1-alpha-d59afde37e995b165a41f754a12a446f11d471a2",
9209
+ version: "3.1.1-alpha-44d99dfbdd24baaf06986492792348582266d8f0",
9210
9210
  "private": true,
9211
9211
  type: "module",
9212
9212
  exports: {
@@ -56394,7 +56394,7 @@ var WebTracerProvider = class extends BasicTracerProvider {
56394
56394
  };
56395
56395
  var package_default = {
56396
56396
  name: "@browserbasehq/stagehand-extension",
56397
- version: "1.3.0-alpha-d59afde37e995b165a41f754a12a446f11d471a2",
56397
+ version: "1.3.0-alpha-44d99dfbdd24baaf06986492792348582266d8f0",
56398
56398
  "private": true,
56399
56399
  type: "module",
56400
56400
  scripts: {
@@ -56601,7 +56601,7 @@ var FrameRegistry = class {
56601
56601
  * Record that a frame attached. If `parentId` is null and `frameId` differs from the current
56602
56602
  * root, this is a root swap and we rename the root id.
56603
56603
  *
56604
- * IMPORTANT: The emitter's `sessionId` is the **owner** for the new/attached frame.
56604
+ * The provided `sessionId` is the selected **owner** for the new/attached frame.
56605
56605
  */
56606
56606
  onFrameAttached(frameId, parentId, sessionId) {
56607
56607
  if (!parentId && frameId !== this.rootFrameId) {
@@ -58449,7 +58449,7 @@ var Page = class Page {
58449
58449
  }
58450
58450
  /**
58451
58451
  * Parent/child session emitted a `frameAttached`.
58452
- * Topology update + ownership stamped to **emitting session**.
58452
+ * Topology update + ownership stamped to the session selected by Context.
58453
58453
  */
58454
58454
  onFrameAttached(frameId, parentId, session) {
58455
58455
  this.ensureOrdinal(frameId);
@@ -58497,7 +58497,7 @@ var Page = class Page {
58497
58497
  * An OOPIF child session whose **main** frame id equals the parent iframe’s frameId
58498
58498
  * has been attached; adopt the session into this Page and seed ownership for its subtree.
58499
58499
  */
58500
- adoptOopifSession(childSession, childMainFrameId) {
58500
+ adoptOopifSession(childSession, childMainFrameId, onFrameTreeSeeded) {
58501
58501
  if (this.disposed) return;
58502
58502
  const previous = childSession.id ? this.sessions.get(childSession.id) : void 0;
58503
58503
  if (childSession.id) this.sessions.set(childSession.id, childSession);
@@ -58512,9 +58512,6 @@ var Page = class Page {
58512
58512
  childSession.on("Page.frameNavigated", (evt) => {
58513
58513
  this.onFrameNavigated(evt.frame, childSession);
58514
58514
  });
58515
- childSession.on("Page.frameAttached", (evt) => {
58516
- this.onFrameAttached(evt.frameId, evt.parentFrameId ?? null, childSession);
58517
- });
58518
58515
  childSession.on("Page.frameDetached", (evt) => {
58519
58516
  this.onFrameDetached(evt.frameId, evt.reason ?? "remove");
58520
58517
  });
@@ -58532,6 +58529,7 @@ var Page = class Page {
58532
58529
  if (!this.disposed && this.sessions.get(childSession.id ?? "") === childSession) {
58533
58530
  this.registry.seedFromFrameTree(childSession.id ?? "child", frameTree);
58534
58531
  this.reconcilePendingWebMCPTools();
58532
+ onFrameTreeSeeded?.();
58535
58533
  }
58536
58534
  } catch {}
58537
58535
  })();
@@ -61574,6 +61572,8 @@ var BrowserContext = class BrowserContext {
61574
61572
  this.sessionOwnerPage = /* @__PURE__ */ new Map();
61575
61573
  this.frameOwnerPage = /* @__PURE__ */ new Map();
61576
61574
  this.pendingOopifByMainFrame = /* @__PURE__ */ new Map();
61575
+ this.pendingOopifParentByMainFrame = /* @__PURE__ */ new Map();
61576
+ this.adoptedOopifSessionByFrame = /* @__PURE__ */ new Map();
61577
61577
  this.createdAtByTarget = /* @__PURE__ */ new Map();
61578
61578
  this.typeByTarget = /* @__PURE__ */ new Map();
61579
61579
  this.pendingCreatedTargetUrl = /* @__PURE__ */ new Map();
@@ -61899,6 +61899,8 @@ var BrowserContext = class BrowserContext {
61899
61899
  this.sessionOwnerPage.clear();
61900
61900
  this.frameOwnerPage.clear();
61901
61901
  this.pendingOopifByMainFrame.clear();
61902
+ this.pendingOopifParentByMainFrame.clear();
61903
+ this.adoptedOopifSessionByFrame.clear();
61902
61904
  this.createdAtByTarget.clear();
61903
61905
  this.typeByTarget.clear();
61904
61906
  this.pendingCreatedTargetUrl.clear();
@@ -62103,34 +62105,91 @@ var BrowserContext = class BrowserContext {
62103
62105
  this.pendingCreatedTargetUrl.delete(info.targetId);
62104
62106
  page.seedCurrentUrl(pendingSeedUrl ?? info.url ?? "");
62105
62107
  this.installFrameEventBridges(sessionId, page);
62108
+ this.adoptPendingOopifsByParent();
62106
62109
  await this.applyInitScriptsToPage(page, { seedOnly: scriptsInstalled });
62107
62110
  return;
62108
62111
  }
62109
62112
  try {
62110
62113
  const { frameTree } = await session.send("Page.getFrameTree");
62111
62114
  const childMainId = frameTree.frame.id;
62112
- let owner = this.frameOwnerPage.get(childMainId);
62113
- if (!owner) {
62114
- for (const p of this.pagesByTarget.values()) if ((function find(n) {
62115
- if (n.frame.id === childMainId) return true;
62116
- for (const c of n.childFrames ?? []) if (find(c)) return true;
62117
- return false;
62118
- })(p.asProtocolFrameTree(p.mainFrameId()))) {
62119
- owner = p;
62120
- break;
62121
- }
62122
- }
62115
+ const parentFrameId = frameTree.frame.parentId;
62116
+ const owner = this.findPageOwningFrame(childMainId) ?? (parentFrameId ? this.findPageOwningFrame(parentFrameId) : void 0);
62123
62117
  if (owner) {
62124
- owner.adoptOopifSession(session, childMainId);
62125
- this.sessionOwnerPage.set(sessionId, owner);
62126
- this.installFrameEventBridges(sessionId, owner);
62127
- executionContexts.waitForMainWorld(session, childMainId).catch(() => {});
62128
- } else this.pendingOopifByMainFrame.set(childMainId, sessionId);
62118
+ this.adoptOopif(owner, session, childMainId);
62119
+ this.adoptPendingOopifsByParent();
62120
+ } else {
62121
+ this.pendingOopifByMainFrame.set(childMainId, sessionId);
62122
+ if (parentFrameId) this.pendingOopifParentByMainFrame.set(childMainId, parentFrameId);
62123
+ }
62129
62124
  } catch {}
62130
62125
  } finally {
62131
62126
  await resume();
62132
62127
  }
62133
62128
  }
62129
+ /**
62130
+ * Page whose frame graph contains `frameId`, including adopted OOPIF roots.
62131
+ */
62132
+ findPageOwningFrame(frameId) {
62133
+ const known = this.frameOwnerPage.get(frameId);
62134
+ if (known) {
62135
+ if (this.pagesByTarget.get(known.targetId()) === known && known.registry.frames.has(frameId)) return known;
62136
+ this.frameOwnerPage.delete(frameId);
62137
+ }
62138
+ for (const p of this.pagesByTarget.values()) if (p.listAllFrameIds().includes(frameId)) return p;
62139
+ }
62140
+ adoptOopif(owner, session, childMainId) {
62141
+ owner.adoptOopifSession(session, childMainId, () => {
62142
+ this.adoptPendingOopifsByParent();
62143
+ });
62144
+ this.adoptedOopifSessionByFrame.set(childMainId, session.id);
62145
+ this.sessionOwnerPage.set(session.id, owner);
62146
+ this.frameOwnerPage.set(childMainId, owner);
62147
+ this.installFrameEventBridges(session.id, owner);
62148
+ executionContexts.waitForMainWorld(session, childMainId).catch(() => {});
62149
+ }
62150
+ removePendingOopif(frameId) {
62151
+ this.pendingOopifByMainFrame.delete(frameId);
62152
+ this.pendingOopifParentByMainFrame.delete(frameId);
62153
+ }
62154
+ removePendingOopifsForPage(page) {
62155
+ const pageFrameIds = /* @__PURE__ */ new Set([page.mainFrameId(), ...page.registry.frames.keys()]);
62156
+ for (const [frameId, owner] of this.frameOwnerPage) if (owner === page) pageFrameIds.add(frameId);
62157
+ let removed;
62158
+ do {
62159
+ removed = false;
62160
+ for (const [frameId] of this.pendingOopifByMainFrame) {
62161
+ const parentId = this.pendingOopifParentByMainFrame.get(frameId);
62162
+ if (!pageFrameIds.has(frameId) && (!parentId || !pageFrameIds.has(parentId))) continue;
62163
+ pageFrameIds.add(frameId);
62164
+ this.removePendingOopif(frameId);
62165
+ removed = true;
62166
+ }
62167
+ } while (removed);
62168
+ }
62169
+ /**
62170
+ * An OOPIF that already existed when we attached (e.g. reconnecting to a live
62171
+ * browser, or a nested OOPIF) never emits `frameAttached` on its parent, so the
62172
+ * pending map would hold it forever. Adopt it once the page owning its parent is known.
62173
+ */
62174
+ adoptPendingOopifsByParent() {
62175
+ let adopted = true;
62176
+ while (adopted) {
62177
+ adopted = false;
62178
+ for (const [childMainId, parentFrameId] of Array.from(this.pendingOopifParentByMainFrame.entries())) {
62179
+ const childSessionId = this.pendingOopifByMainFrame.get(childMainId);
62180
+ const child = childSessionId ? this.conn.getSession(childSessionId) : void 0;
62181
+ if (!child) {
62182
+ this.removePendingOopif(childMainId);
62183
+ continue;
62184
+ }
62185
+ const owner = this.findPageOwningFrame(parentFrameId);
62186
+ if (!owner) continue;
62187
+ this.removePendingOopif(childMainId);
62188
+ this.adoptOopif(owner, child, childMainId);
62189
+ adopted = true;
62190
+ }
62191
+ }
62192
+ }
62134
62193
  async closePopupIfBlockedByDomainPolicy(info, source) {
62135
62194
  if (!this.domainPolicy || !isTopLevelPage(info)) return false;
62136
62195
  if (!info.openerId && !info.openerFrameId) return false;
@@ -62179,13 +62238,16 @@ var BrowserContext = class BrowserContext {
62179
62238
  * - Drop any staged child for this session.
62180
62239
  */
62181
62240
  onDetachedFromTarget(sessionId, targetId) {
62241
+ const closingPage = targetId ? this.pagesByTarget.get(targetId) : void 0;
62242
+ if (closingPage) this.removePendingOopifsForPage(closingPage);
62182
62243
  const owner = this.sessionOwnerPage.get(sessionId);
62183
62244
  if (owner) {
62184
62245
  owner.detachOopifSession(sessionId);
62185
62246
  this.sessionOwnerPage.delete(sessionId);
62186
62247
  }
62187
62248
  if (targetId && this.pagesByTarget.has(targetId)) this.cleanupByTarget(targetId);
62188
- for (const [fid, sid] of Array.from(this.pendingOopifByMainFrame.entries())) if (sid === sessionId) this.pendingOopifByMainFrame.delete(fid);
62249
+ for (const [fid, sid] of Array.from(this.pendingOopifByMainFrame.entries())) if (sid === sessionId) this.removePendingOopif(fid);
62250
+ for (const [fid, sid] of Array.from(this.adoptedOopifSessionByFrame.entries())) if (sid === sessionId) this.adoptedOopifSessionByFrame.delete(fid);
62189
62251
  this._targetSessionListeners.delete(sessionId);
62190
62252
  const session = this.conn.getSession(sessionId);
62191
62253
  if (session) this.uninstallDomainPolicyHandler(session);
@@ -62199,15 +62261,12 @@ var BrowserContext = class BrowserContext {
62199
62261
  this.recordPageCreationFailure(targetId, /* @__PURE__ */ new Error(`Target closed before page registration (${targetId})`), "Target closed before page registration");
62200
62262
  const page = this.pagesByTarget.get(targetId);
62201
62263
  if (!page) return;
62264
+ this.removePendingOopifsForPage(page);
62202
62265
  page.dispose();
62203
62266
  const mainId = page.mainFrameId();
62204
62267
  this.mainFrameToTarget.delete(mainId);
62205
- this.frameOwnerPage.delete(mainId);
62268
+ for (const [frameId, owner] of this.frameOwnerPage) if (owner === page) this.frameOwnerPage.delete(frameId);
62206
62269
  for (const [sid, p] of Array.from(this.sessionOwnerPage.entries())) if (p === page) this.sessionOwnerPage.delete(sid);
62207
- for (const [fid] of Array.from(this.pendingOopifByMainFrame.entries())) {
62208
- const owner = this.frameOwnerPage.get(fid);
62209
- if (!owner || owner === page) this.pendingOopifByMainFrame.delete(fid);
62210
- }
62211
62270
  this.pagesByTarget.delete(targetId);
62212
62271
  this.createdAtByTarget.delete(targetId);
62213
62272
  this.typeByTarget.delete(targetId);
@@ -62220,23 +62279,21 @@ var BrowserContext = class BrowserContext {
62220
62279
  }
62221
62280
  /**
62222
62281
  * Wire Page-domain frame events for a session into the owning Page & mappings.
62223
- * We forward the *emitting session* with every event so Page can stamp ownership precisely.
62282
+ * Attachments preserve live adopted OOPIF ownership while updating topology.
62224
62283
  */
62225
62284
  installFrameEventBridges(sessionId, owner) {
62226
62285
  const session = this.conn.getSession(sessionId);
62227
62286
  if (!session) return;
62228
62287
  session.on("Page.frameAttached", (evt) => {
62229
62288
  const { frameId, parentFrameId } = evt;
62230
- owner.onFrameAttached(frameId, parentFrameId ?? null, session);
62289
+ const adoptedSessionId = this.adoptedOopifSessionByFrame.get(frameId);
62290
+ const adoptedSession = adoptedSessionId ? this.conn.getSession(adoptedSessionId) : void 0;
62291
+ owner.onFrameAttached(frameId, parentFrameId ?? null, adoptedSession ?? session);
62231
62292
  const pendingChildSessionId = this.pendingOopifByMainFrame.get(frameId);
62232
62293
  if (pendingChildSessionId) {
62233
62294
  const child = this.conn.getSession(pendingChildSessionId);
62234
- if (child) {
62235
- owner.adoptOopifSession(child, frameId);
62236
- this.sessionOwnerPage.set(child.id, owner);
62237
- this.installFrameEventBridges(pendingChildSessionId, owner);
62238
- }
62239
- this.pendingOopifByMainFrame.delete(frameId);
62295
+ this.removePendingOopif(frameId);
62296
+ if (child) this.adoptOopif(owner, child, frameId);
62240
62297
  }
62241
62298
  this.frameOwnerPage.set(frameId, owner);
62242
62299
  if (!parentFrameId) {
@@ -62245,6 +62302,7 @@ var BrowserContext = class BrowserContext {
62245
62302
  if (topTargetId) this.mainFrameToTarget.set(newRoot, topTargetId);
62246
62303
  this.frameOwnerPage.set(newRoot, owner);
62247
62304
  }
62305
+ this.adoptPendingOopifsByParent();
62248
62306
  });
62249
62307
  session.on("Page.frameDetached", (evt) => {
62250
62308
  owner.onFrameDetached(evt.frameId, evt.reason ?? "remove");
@@ -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.1.1-alpha-d59afde37e995b165a41f754a12a446f11d471a2'
4
+ STAGEHAND_PROTOCOL_VERSION = '3.1.1-alpha-44d99dfbdd24baaf06986492792348582266d8f0'