stagehand 4.2.0a0.dev1590__tar.gz → 4.2.1a0.dev1593__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.dev1590 → stagehand-4.2.1a0.dev1593}/PKG-INFO +1 -1
  2. {stagehand-4.2.0a0.dev1590 → stagehand-4.2.1a0.dev1593}/pyproject.toml +1 -1
  3. {stagehand-4.2.0a0.dev1590 → stagehand-4.2.1a0.dev1593}/src/stagehand/_extension/content-script.js +74 -81
  4. {stagehand-4.2.0a0.dev1590 → stagehand-4.2.1a0.dev1593}/src/stagehand/_extension/manifest.json +1 -1
  5. {stagehand-4.2.0a0.dev1590 → stagehand-4.2.1a0.dev1593}/src/stagehand/_extension/service-worker.js +94 -196
  6. {stagehand-4.2.0a0.dev1590 → stagehand-4.2.1a0.dev1593}/src/stagehand/_generated/models.py +6 -31
  7. {stagehand-4.2.0a0.dev1590 → stagehand-4.2.1a0.dev1593}/src/stagehand/_generated/protocol_version.py +1 -1
  8. {stagehand-4.2.0a0.dev1590 → stagehand-4.2.1a0.dev1593}/src/stagehand/rpc_client.py +4 -1
  9. {stagehand-4.2.0a0.dev1590 → stagehand-4.2.1a0.dev1593}/README.md +0 -0
  10. {stagehand-4.2.0a0.dev1590 → stagehand-4.2.1a0.dev1593}/src/stagehand/__init__.py +0 -0
  11. {stagehand-4.2.0a0.dev1590 → stagehand-4.2.1a0.dev1593}/src/stagehand/_extension/blank.html +0 -0
  12. {stagehand-4.2.0a0.dev1590 → stagehand-4.2.1a0.dev1593}/src/stagehand/_extension/offscreen/service-worker-heartbeat.html +0 -0
  13. {stagehand-4.2.0a0.dev1590 → stagehand-4.2.1a0.dev1593}/src/stagehand/_extension/offscreen/service-worker-heartbeat.js +0 -0
  14. {stagehand-4.2.0a0.dev1590 → stagehand-4.2.1a0.dev1593}/src/stagehand/_extension/wake-service-worker.html +0 -0
  15. {stagehand-4.2.0a0.dev1590 → stagehand-4.2.1a0.dev1593}/src/stagehand/_extension/wake-service-worker.js +0 -0
  16. {stagehand-4.2.0a0.dev1590 → stagehand-4.2.1a0.dev1593}/src/stagehand/_generated/__init__.py +0 -0
  17. {stagehand-4.2.0a0.dev1590 → stagehand-4.2.1a0.dev1593}/src/stagehand/_generated/input_types.py +0 -0
  18. {stagehand-4.2.0a0.dev1590 → stagehand-4.2.1a0.dev1593}/src/stagehand/_sdk_identity.py +0 -0
  19. {stagehand-4.2.0a0.dev1590 → stagehand-4.2.1a0.dev1593}/src/stagehand/_validation.py +0 -0
  20. {stagehand-4.2.0a0.dev1590 → stagehand-4.2.1a0.dev1593}/src/stagehand/browser.py +0 -0
  21. {stagehand-4.2.0a0.dev1590 → stagehand-4.2.1a0.dev1593}/src/stagehand/browser_clipboard.py +0 -0
  22. {stagehand-4.2.0a0.dev1590 → stagehand-4.2.1a0.dev1593}/src/stagehand/browser_context.py +0 -0
  23. {stagehand-4.2.0a0.dev1590 → stagehand-4.2.1a0.dev1593}/src/stagehand/browserbase_services.py +0 -0
  24. {stagehand-4.2.0a0.dev1590 → stagehand-4.2.1a0.dev1593}/src/stagehand/browserbase_session.py +0 -0
  25. {stagehand-4.2.0a0.dev1590 → stagehand-4.2.1a0.dev1593}/src/stagehand/cdp_client.py +0 -0
  26. {stagehand-4.2.0a0.dev1590 → stagehand-4.2.1a0.dev1593}/src/stagehand/client_models.py +0 -0
  27. {stagehand-4.2.0a0.dev1590 → stagehand-4.2.1a0.dev1593}/src/stagehand/client_types.py +0 -0
  28. {stagehand-4.2.0a0.dev1590 → stagehand-4.2.1a0.dev1593}/src/stagehand/extension_assets.py +0 -0
  29. {stagehand-4.2.0a0.dev1590 → stagehand-4.2.1a0.dev1593}/src/stagehand/file_upload.py +0 -0
  30. {stagehand-4.2.0a0.dev1590 → stagehand-4.2.1a0.dev1593}/src/stagehand/locator.py +0 -0
  31. {stagehand-4.2.0a0.dev1590 → stagehand-4.2.1a0.dev1593}/src/stagehand/page.py +0 -0
  32. {stagehand-4.2.0a0.dev1590 → stagehand-4.2.1a0.dev1593}/src/stagehand/py.typed +0 -0
  33. {stagehand-4.2.0a0.dev1590 → stagehand-4.2.1a0.dev1593}/src/stagehand/response.py +0 -0
  34. {stagehand-4.2.0a0.dev1590 → stagehand-4.2.1a0.dev1593}/src/stagehand/stagehand.py +0 -0
  35. {stagehand-4.2.0a0.dev1590 → stagehand-4.2.1a0.dev1593}/src/stagehand/timeouts.py +0 -0
  36. {stagehand-4.2.0a0.dev1590 → stagehand-4.2.1a0.dev1593}/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.dev1590
3
+ Version: 4.2.1a0.dev1593
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.0a0.dev1590"
3
+ version = "4.2.1a0.dev1593"
4
4
  description = "Browserbase's SDK for building browser agents"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.11"
@@ -990,7 +990,7 @@ var checkState = (el, state) => {
990
990
  /**
991
991
  * Set up MutationObservers on all shadow roots to detect changes.
992
992
  */
993
- var setupShadowObservers = (callback, observers) => {
993
+ var setupShadowObservers = (callback, observers, isSettled) => {
994
994
  const seenRoots = /* @__PURE__ */ new WeakSet();
995
995
  const observeShadowRoots = (node) => {
996
996
  const shadowRoot = getOpenOrClosedShadowRoot(node);
@@ -1000,6 +1000,7 @@ var setupShadowObservers = (callback, observers) => {
1000
1000
  callback();
1001
1001
  scan();
1002
1002
  });
1003
+ observers.push(shadowObserver);
1003
1004
  shadowObserver.observe(shadowRoot, {
1004
1005
  childList: true,
1005
1006
  subtree: true,
@@ -1011,14 +1012,13 @@ var setupShadowObservers = (callback, observers) => {
1011
1012
  "disabled"
1012
1013
  ]
1013
1014
  });
1014
- observers.push(shadowObserver);
1015
1015
  for (const child of Array.from(shadowRoot.children)) observeShadowRoots(child);
1016
1016
  }
1017
1017
  for (const child of Array.from(node.children)) observeShadowRoots(child);
1018
1018
  };
1019
1019
  const root = document.documentElement || document.body;
1020
1020
  const scan = () => {
1021
- if (root) observeShadowRoots(root);
1021
+ if (!isSettled() && root) observeShadowRoots(root);
1022
1022
  };
1023
1023
  scan();
1024
1024
  return scan;
@@ -1029,106 +1029,99 @@ var setupShadowObservers = (callback, observers) => {
1029
1029
  *
1030
1030
  * @param selectorRaw - CSS selector or XPath expression to wait for
1031
1031
  * @param stateRaw - Element state: 'attached' | 'detached' | 'visible' | 'hidden'
1032
- * @param timeoutRaw - Maximum time to wait in milliseconds
1032
+ * @param timeoutRaw - Maximum time to wait in milliseconds; defaults to 30,000, zero is unlimited
1033
1033
  * @param pierceShadowRaw - Whether to search inside shadow DOM
1034
- * @returns Promise that resolves to true when condition is met, or rejects on timeout
1034
+ * @returns A disposable handle whose promise resolves when the condition is met
1035
1035
  */
1036
- function waitForSelector(selectorRaw, stateRaw, timeoutRaw, pierceShadowRaw) {
1036
+ function createSelectorWait(selectorRaw, stateRaw, timeoutRaw, pierceShadowRaw) {
1037
1037
  const selector = String(selectorRaw ?? "").trim();
1038
1038
  const state = String(stateRaw ?? "visible") || "visible";
1039
- const timeout = typeof timeoutRaw === "number" && timeoutRaw > 0 ? timeoutRaw : 3e4;
1039
+ const timeout = typeof timeoutRaw === "number" && timeoutRaw >= 0 ? timeoutRaw : 3e4;
1040
1040
  const pierceShadow = pierceShadowRaw !== false;
1041
- return new Promise((resolve, reject) => {
1042
- let timeoutId = null;
1043
- let domReadyHandler = null;
1041
+ let dispose = () => {};
1042
+ const promise = new Promise((resolve, reject) => {
1044
1043
  let settled = false;
1045
- const clearTimer = () => {
1046
- if (timeoutId !== null) {
1047
- clearTimeout(timeoutId);
1048
- timeoutId = null;
1049
- }
1050
- };
1051
- if (checkState(findElement(selector, pierceShadow), state)) {
1052
- settled = true;
1053
- resolve(true);
1054
- return;
1055
- }
1044
+ let timeoutId;
1045
+ let shadowScanInterval;
1046
+ let domReadyHandler;
1047
+ let rescanShadowRoots;
1056
1048
  const observers = [];
1057
- let shadowScanInterval = null;
1058
- let rescanShadowRoots = null;
1059
- const cleanup = () => {
1060
- for (const obs of observers) obs.disconnect();
1061
- if (shadowScanInterval !== null) {
1062
- clearInterval(shadowScanInterval);
1063
- shadowScanInterval = null;
1064
- }
1049
+ const settle = (error) => {
1050
+ if (settled) return;
1051
+ settled = true;
1052
+ clearTimeout(timeoutId);
1053
+ clearInterval(shadowScanInterval);
1054
+ for (const observer of observers) observer.disconnect();
1055
+ observers.length = 0;
1056
+ rescanShadowRoots = void 0;
1065
1057
  if (domReadyHandler) {
1066
1058
  document.removeEventListener("DOMContentLoaded", domReadyHandler);
1067
- domReadyHandler = null;
1059
+ domReadyHandler = void 0;
1068
1060
  }
1061
+ if (error) reject(error);
1062
+ else resolve(true);
1069
1063
  };
1064
+ dispose = () => settle(/* @__PURE__ */ new Error("Selector wait disposed"));
1070
1065
  const check = () => {
1071
1066
  if (settled) return;
1072
- if (checkState(findElement(selector, pierceShadow), state)) {
1073
- settled = true;
1074
- clearTimer();
1075
- cleanup();
1076
- resolve(true);
1067
+ try {
1068
+ if (checkState(findElement(selector, pierceShadow), state)) settle();
1069
+ } catch (error) {
1070
+ settle(error instanceof Error ? error : new Error(String(error)));
1077
1071
  }
1078
1072
  };
1079
- if (!(document.body || document.documentElement)) {
1073
+ const setupObservers = () => {
1074
+ if (settled) return;
1075
+ const root = document.body || document.documentElement;
1076
+ if (!root) return;
1077
+ try {
1078
+ const mainObserver = new MutationObserver(() => {
1079
+ check();
1080
+ rescanShadowRoots?.();
1081
+ });
1082
+ observers.push(mainObserver);
1083
+ mainObserver.observe(root, {
1084
+ childList: true,
1085
+ subtree: true,
1086
+ attributes: true,
1087
+ attributeFilter: [
1088
+ "style",
1089
+ "class",
1090
+ "hidden",
1091
+ "disabled"
1092
+ ]
1093
+ });
1094
+ if (pierceShadow) {
1095
+ rescanShadowRoots = setupShadowObservers(check, observers, () => settled);
1096
+ shadowScanInterval = setInterval(() => {
1097
+ rescanShadowRoots?.();
1098
+ check();
1099
+ }, 100);
1100
+ }
1101
+ } catch (error) {
1102
+ settle(error instanceof Error ? error : new Error(String(error)));
1103
+ }
1104
+ };
1105
+ check();
1106
+ if (settled) return;
1107
+ if (document.body || document.documentElement) setupObservers();
1108
+ else {
1080
1109
  domReadyHandler = () => {
1110
+ if (settled) return;
1081
1111
  document.removeEventListener("DOMContentLoaded", domReadyHandler);
1082
- domReadyHandler = null;
1112
+ domReadyHandler = void 0;
1083
1113
  check();
1084
1114
  setupObservers();
1085
1115
  };
1086
1116
  document.addEventListener("DOMContentLoaded", domReadyHandler);
1087
- timeoutId = setTimeout(() => {
1088
- if (settled) return;
1089
- settled = true;
1090
- clearTimer();
1091
- cleanup();
1092
- reject(/* @__PURE__ */ new Error(`waitForSelector: Timeout ${timeout}ms exceeded waiting for "${selector}" to be ${state}`));
1093
- }, timeout);
1094
- return;
1095
1117
  }
1096
- const setupObservers = () => {
1097
- const root = document.body || document.documentElement;
1098
- if (!root) return;
1099
- const mainObserver = new MutationObserver(() => {
1100
- check();
1101
- rescanShadowRoots?.();
1102
- });
1103
- mainObserver.observe(root, {
1104
- childList: true,
1105
- subtree: true,
1106
- attributes: true,
1107
- attributeFilter: [
1108
- "style",
1109
- "class",
1110
- "hidden",
1111
- "disabled"
1112
- ]
1113
- });
1114
- observers.push(mainObserver);
1115
- if (pierceShadow) {
1116
- rescanShadowRoots = setupShadowObservers(check, observers);
1117
- shadowScanInterval = setInterval(() => {
1118
- rescanShadowRoots?.();
1119
- check();
1120
- }, 100);
1121
- }
1122
- };
1123
- setupObservers();
1124
- timeoutId = setTimeout(() => {
1125
- if (settled) return;
1126
- settled = true;
1127
- clearTimer();
1128
- cleanup();
1129
- reject(/* @__PURE__ */ new Error(`waitForSelector: Timeout ${timeout}ms exceeded waiting for "${selector}" to be ${state}`));
1130
- }, timeout);
1118
+ if (!settled && timeout > 0) timeoutId = setTimeout(() => settle(/* @__PURE__ */ new Error(`waitForSelector: Timeout ${timeout}ms exceeded waiting for "${selector}" to be ${state}`)), timeout);
1131
1119
  });
1120
+ promise.catch(() => {});
1121
+ return {
1122
+ promise,
1123
+ dispose: () => dispose()
1124
+ };
1132
1125
  }
1133
1126
  //#endregion
1134
1127
  //#region dom/locatorScripts/registry.ts
@@ -1142,7 +1135,7 @@ var locatorScripts = Object.freeze({
1142
1135
  resolveCssSelector,
1143
1136
  resolveTextSelector,
1144
1137
  resolveXPathMainWorld,
1145
- waitForSelector
1138
+ createSelectorWait
1146
1139
  });
1147
1140
  //#endregion
1148
1141
  //#region content-script.ts
@@ -31,5 +31,5 @@
31
31
  }
32
32
  ],
33
33
  "options_page": "wake-service-worker.html",
34
- "version": "1.1.0"
34
+ "version": "1.1.1"
35
35
  }
@@ -7363,7 +7363,7 @@ function isRecord$1(value) {
7363
7363
  }
7364
7364
  var package_default$1 = {
7365
7365
  name: "@browserbasehq/stagehand-protocol",
7366
- version: "2.1.0-alpha-535b80d78b84a5ad3ead386d5399029bb873b80e",
7366
+ version: "2.1.1-alpha-bfeda482351a8613e3f8fe485b181bb8588b77ab",
7367
7367
  "private": true,
7368
7368
  type: "module",
7369
7369
  exports: {
@@ -7437,164 +7437,12 @@ function parseProtocolVersion(version) {
7437
7437
  }
7438
7438
  //#endregion
7439
7439
  //#region ../protocol/schemas.ts
7440
- var OpenAIModelIdSchema = _enum([
7441
- "gpt-4.1",
7442
- "gpt-4.1-2025-04-14",
7443
- "gpt-4.1-mini",
7444
- "gpt-4.1-mini-2025-04-14",
7445
- "gpt-4.1-nano",
7446
- "gpt-4.1-nano-2025-04-14",
7447
- "gpt-4o",
7448
- "gpt-4o-2024-05-13",
7449
- "gpt-4o-2024-08-06",
7450
- "gpt-4o-2024-11-20",
7451
- "gpt-4o-audio-preview",
7452
- "gpt-4o-audio-preview-2024-12-17",
7453
- "gpt-4o-search-preview",
7454
- "gpt-4o-search-preview-2025-03-11",
7455
- "gpt-4o-mini-search-preview",
7456
- "gpt-4o-mini-search-preview-2025-03-11",
7457
- "gpt-4o-mini",
7458
- "gpt-4o-mini-2024-07-18",
7459
- "gpt-3.5-turbo-0125",
7460
- "gpt-3.5-turbo",
7461
- "gpt-3.5-turbo-1106",
7462
- "gpt-5-chat-latest",
7463
- "o1",
7464
- "o1-2024-12-17",
7465
- "o3",
7466
- "o3-2025-04-16",
7467
- "o3-mini",
7468
- "o3-mini-2025-01-31",
7469
- "o4-mini",
7470
- "o4-mini-2025-04-16",
7471
- "gpt-5",
7472
- "gpt-5-2025-08-07",
7473
- "gpt-5-codex",
7474
- "gpt-5-mini",
7475
- "gpt-5-mini-2025-08-07",
7476
- "gpt-5-nano",
7477
- "gpt-5-nano-2025-08-07",
7478
- "gpt-5-pro",
7479
- "gpt-5-pro-2025-10-06",
7480
- "gpt-5.1",
7481
- "gpt-5.1-chat-latest",
7482
- "gpt-5.1-codex-mini",
7483
- "gpt-5.1-codex",
7484
- "gpt-5.1-codex-max",
7485
- "gpt-5.2",
7486
- "gpt-5.2-chat-latest",
7487
- "gpt-5.2-pro",
7488
- "gpt-5.2-codex",
7489
- "gpt-5.3-chat-latest",
7490
- "gpt-5.3-codex",
7491
- "gpt-5.4",
7492
- "gpt-5.4-2026-03-05",
7493
- "gpt-5.4-mini",
7494
- "gpt-5.4-mini-2026-03-17",
7495
- "gpt-5.4-nano",
7496
- "gpt-5.4-nano-2026-03-17",
7497
- "gpt-5.4-pro",
7498
- "gpt-5.4-pro-2026-03-05",
7499
- "gpt-5.5",
7500
- "gpt-5.5-2026-04-23",
7501
- "gpt-5.6",
7502
- "gpt-5.6-luna",
7503
- "gpt-5.6-sol",
7504
- "gpt-5.6-terra"
7505
- ]).meta({ id: "OpenAIModelId" });
7506
- var AnthropicModelIdSchema = _enum([
7507
- "claude-3-haiku-20240307",
7508
- "claude-haiku-4-5-20251001",
7509
- "claude-haiku-4-5",
7510
- "claude-opus-4-0",
7511
- "claude-opus-4-20250514",
7512
- "claude-opus-4-1-20250805",
7513
- "claude-opus-4-1",
7514
- "claude-opus-4-5",
7515
- "claude-opus-4-5-20251101",
7516
- "claude-sonnet-4-0",
7517
- "claude-sonnet-4-20250514",
7518
- "claude-sonnet-4-5-20250929",
7519
- "claude-sonnet-4-5",
7520
- "claude-sonnet-4-6",
7521
- "claude-opus-4-6",
7522
- "claude-opus-4-7",
7523
- "claude-opus-4-8",
7524
- "claude-fable-5",
7525
- "claude-sonnet-5"
7526
- ]).meta({ id: "AnthropicModelId" });
7527
- var GoogleModelIdSchema = _enum([
7528
- "gemini-2.0-flash",
7529
- "gemini-2.0-flash-001",
7530
- "gemini-2.0-flash-lite",
7531
- "gemini-2.0-flash-lite-001",
7532
- "gemini-2.5-pro",
7533
- "gemini-2.5-flash",
7534
- "gemini-2.5-flash-image",
7535
- "gemini-2.5-flash-lite",
7536
- "gemini-2.5-flash-preview-tts",
7537
- "gemini-2.5-pro-preview-tts",
7538
- "gemini-2.5-flash-native-audio-latest",
7539
- "gemini-2.5-flash-native-audio-preview-09-2025",
7540
- "gemini-2.5-flash-native-audio-preview-12-2025",
7541
- "gemini-2.5-computer-use-preview-10-2025",
7542
- "gemini-3-pro-preview",
7543
- "gemini-3-pro-image-preview",
7544
- "gemini-3-flash-preview",
7545
- "gemini-3.1-pro-preview",
7546
- "gemini-3.1-pro-preview-customtools",
7547
- "gemini-3.1-flash-image-preview",
7548
- "gemini-3.1-flash-lite-preview",
7549
- "gemini-3.1-flash-tts-preview",
7550
- "gemini-3.5-flash",
7551
- "gemini-3.6-flash",
7552
- "gemini-pro-latest",
7553
- "gemini-flash-latest",
7554
- "gemini-flash-lite-latest",
7555
- "deep-research-pro-preview-12-2025",
7556
- "deep-research-max-preview-04-2026",
7557
- "deep-research-preview-04-2026",
7558
- "nano-banana-pro-preview",
7559
- "aqa",
7560
- "gemini-robotics-er-1.5-preview",
7561
- "gemma-3-1b-it",
7562
- "gemma-3-4b-it",
7563
- "gemma-3n-e4b-it",
7564
- "gemma-3n-e2b-it",
7565
- "gemma-3-12b-it",
7566
- "gemma-3-27b-it"
7567
- ]).meta({ id: "GoogleModelId" });
7568
- var GroqModelIdSchema = _enum([
7569
- "gemma2-9b-it",
7570
- "llama-3.1-8b-instant",
7571
- "llama-3.3-70b-versatile",
7572
- "meta-llama/llama-guard-4-12b",
7573
- "openai/gpt-oss-120b",
7574
- "openai/gpt-oss-20b",
7575
- "deepseek-r1-distill-llama-70b",
7576
- "meta-llama/llama-4-maverick-17b-128e-instruct",
7577
- "meta-llama/llama-4-scout-17b-16e-instruct",
7578
- "meta-llama/llama-prompt-guard-2-22m",
7579
- "meta-llama/llama-prompt-guard-2-86m",
7580
- "moonshotai/kimi-k2-instruct-0905",
7581
- "qwen/qwen3-32b",
7582
- "llama-guard-3-8b",
7583
- "llama3-70b-8192",
7584
- "llama3-8b-8192",
7585
- "mixtral-8x7b-32768",
7586
- "qwen-qwq-32b",
7587
- "qwen-2.5-32b",
7588
- "deepseek-r1-distill-qwen-32b"
7589
- ]).meta({ id: "GroqModelId" });
7590
- var CerebrasModelIdSchema = _enum([
7591
- "llama3.1-8b",
7592
- "gpt-oss-120b",
7593
- "qwen-3-235b-a22b-instruct-2507",
7594
- "qwen-3-235b-a22b-thinking-2507",
7595
- "zai-glm-4.6",
7596
- "zai-glm-4.7"
7597
- ]).meta({ id: "CerebrasModelId" });
7440
+ var ModelIdSchema = string().min(1).regex(/^\S+$/);
7441
+ var OpenAIModelIdSchema = ModelIdSchema.meta({ id: "OpenAIModelId" });
7442
+ var AnthropicModelIdSchema = ModelIdSchema.meta({ id: "AnthropicModelId" });
7443
+ var GoogleModelIdSchema = ModelIdSchema.meta({ id: "GoogleModelId" });
7444
+ var GroqModelIdSchema = ModelIdSchema.meta({ id: "GroqModelId" });
7445
+ var CerebrasModelIdSchema = ModelIdSchema.meta({ id: "CerebrasModelId" });
7598
7446
  var ModelProviderSchema = _enum([
7599
7447
  "openai",
7600
7448
  "anthropic",
@@ -7610,7 +7458,7 @@ var ModelNameSchema = union([
7610
7458
  templateLiteral(["cerebras/", CerebrasModelIdSchema]).meta({ id: "CerebrasModelName" })
7611
7459
  ]).meta({
7612
7460
  id: "ModelName",
7613
- description: "An explicitly supported model name with its provider prefix"
7461
+ description: "A model name with a supported provider prefix"
7614
7462
  });
7615
7463
  var CookieSchema = strictObject({
7616
7464
  name: string(),
@@ -8013,7 +7861,7 @@ var ModelConfigSchema = strictObject({
8013
7861
  }),
8014
7862
  headers: record(string(), string()).optional().meta({ description: "Custom headers sent with every request to the model provider" })
8015
7863
  }).meta({ id: "ModelConnection" }).extend({ modelName: ModelNameSchema.meta({
8016
- description: "An explicitly supported model name with its provider prefix",
7864
+ description: "A model name with a supported provider prefix",
8017
7865
  example: "openai/gpt-5.4-mini"
8018
7866
  }) }).meta({ id: "ModelConfig" });
8019
7867
  /** Serializable reference to an LLM implemented by the connected Stagehand client. */
@@ -17071,33 +16919,82 @@ var Frame = class {
17071
16919
  return res.result.value;
17072
16920
  }
17073
16921
  /** Evaluate an internal expression in Stagehand's selected locator world. */
17074
- async evaluateInLocatorWorld(expression, progress) {
16922
+ async evaluateInLocatorWorld(buildExpression, progress) {
16923
+ const response = await this.evaluateLocatorExpression(buildExpression, { progress });
16924
+ if (response.exceptionDetails) throw new Error(response.exceptionDetails.text ?? "Locator-world evaluation failed");
16925
+ return response.result.value;
16926
+ }
16927
+ /** Own a disposable browser wait, including a handle delivered after expiry. */
16928
+ async waitInLocatorWorld(buildExpression, progress) {
16929
+ const dispose = (objectId) => Promise.all([progress.cleanup(() => this.session.send("Runtime.callFunctionOn", {
16930
+ objectId,
16931
+ functionDeclaration: "function() { this.dispose(); }",
16932
+ returnByValue: true
16933
+ })), progress.cleanup(() => this.session.send("Runtime.releaseObject", { objectId }))]);
16934
+ for (let attempt = 0;; attempt++) {
16935
+ progress.throwIfStopped();
16936
+ const response = await this.evaluateLocatorExpression(buildExpression, {
16937
+ progress,
16938
+ returnByValue: false,
16939
+ awaitPromise: false,
16940
+ onLateResult: async (late) => {
16941
+ if (late.result.objectId) await dispose(late.result.objectId);
16942
+ }
16943
+ });
16944
+ const objectId = response.result.objectId;
16945
+ let completed = false;
16946
+ try {
16947
+ if (response.exceptionDetails || !objectId) throw new Error(response.exceptionDetails?.exception?.description ?? response.exceptionDetails?.text ?? "Selector wait handle was not returned");
16948
+ let result;
16949
+ try {
16950
+ result = await progress.run("waiting for selector", () => this.session.send("Runtime.callFunctionOn", {
16951
+ objectId,
16952
+ functionDeclaration: "function() { return this.promise; }",
16953
+ awaitPromise: true,
16954
+ returnByValue: true
16955
+ }));
16956
+ } catch (error) {
16957
+ progress.throwIfStopped();
16958
+ const message = error instanceof Error ? error.message : String(error);
16959
+ if (attempt !== 0 || !message.includes("Cannot find context with specified id")) throw error;
16960
+ executionContexts.unregisterLocatorContext(this.session, response.contextId);
16961
+ continue;
16962
+ }
16963
+ if (result.exceptionDetails) throw new Error(result.exceptionDetails.exception?.description ?? result.exceptionDetails.text ?? "Selector wait failed");
16964
+ completed = true;
16965
+ return result.result.value;
16966
+ } finally {
16967
+ if (objectId) if (completed) progress.cleanup(() => this.session.send("Runtime.releaseObject", { objectId }));
16968
+ else await dispose(objectId);
16969
+ }
16970
+ }
16971
+ }
16972
+ async evaluateLocatorExpression(buildExpression, options) {
16973
+ const { progress } = options;
17075
16974
  await runLocatorStep(progress, "enabling runtime", () => this.session.send("Runtime.enable").catch((error) => {
17076
16975
  if (progress && isCdpClosedError(error)) throw error;
17077
16976
  }));
17078
16977
  let locatorWorld = await executionContexts.waitForLocatorWorld(this.session, this.frameId, 1e3, progress);
16978
+ const evaluate = () => runLocatorStep(progress, "evaluating locator helper", () => this.session.send("Runtime.evaluate", {
16979
+ expression: buildExpression(),
16980
+ contextId: locatorWorld.contextId,
16981
+ awaitPromise: options.awaitPromise ?? true,
16982
+ returnByValue: options.returnByValue ?? true
16983
+ }), options.onLateResult);
17079
16984
  let response;
17080
16985
  try {
17081
- response = await runLocatorStep(progress, "evaluating locator helper", () => this.session.send("Runtime.evaluate", {
17082
- expression,
17083
- contextId: locatorWorld.contextId,
17084
- awaitPromise: true,
17085
- returnByValue: true
17086
- }));
16986
+ response = await evaluate();
17087
16987
  } catch (error) {
17088
16988
  progress?.throwIfStopped();
17089
16989
  if (!(error instanceof Error ? error.message : String(error)).includes("Cannot find context with specified id")) throw error;
17090
16990
  executionContexts.unregisterLocatorContext(this.session, locatorWorld.contextId);
17091
16991
  locatorWorld = await executionContexts.waitForLocatorWorld(this.session, this.frameId, 1e3, progress);
17092
- response = await runLocatorStep(progress, "evaluating locator helper", () => this.session.send("Runtime.evaluate", {
17093
- expression,
17094
- contextId: locatorWorld.contextId,
17095
- awaitPromise: true,
17096
- returnByValue: true
17097
- }));
16992
+ response = await evaluate();
17098
16993
  }
17099
- if (response.exceptionDetails) throw new Error(response.exceptionDetails.text ?? "Locator-world evaluation failed");
17100
- return response.result.value;
16994
+ return {
16995
+ ...response,
16996
+ contextId: locatorWorld.contextId
16997
+ };
17101
16998
  }
17102
16999
  /** Page.captureScreenshot (frame-scoped session) */
17103
17000
  async screenshot(options, progress) {
@@ -54394,7 +54291,7 @@ var WebTracerProvider = class extends BasicTracerProvider {
54394
54291
  };
54395
54292
  var package_default = {
54396
54293
  name: "@browserbasehq/stagehand-extension",
54397
- version: "1.1.0-alpha-535b80d78b84a5ad3ead386d5399029bb873b80e",
54294
+ version: "1.1.1-alpha-bfeda482351a8613e3f8fe485b181bb8588b77ab",
54398
54295
  "private": true,
54399
54296
  type: "module",
54400
54297
  scripts: {
@@ -56333,7 +56230,7 @@ var Page = class Page {
56333
56230
  this.initScripts.push(source);
56334
56231
  }
56335
56232
  async ensureCursorScript() {
56336
- await this.mainFrameWrapper.evaluateInLocatorWorld("globalThis.__stagehandLocatorScripts.installCursorOverlay()").catch(() => {});
56233
+ await this.mainFrameWrapper.evaluateInLocatorWorld(() => "globalThis.__stagehandLocatorScripts.installCursorOverlay()").catch(() => {});
56337
56234
  }
56338
56235
  async enableCursorOverlay() {
56339
56236
  if (this.cursorEnabled) return;
@@ -56343,7 +56240,7 @@ var Page = class Page {
56343
56240
  async updateCursor(x, y, progress) {
56344
56241
  if (!this.cursorEnabled) return;
56345
56242
  try {
56346
- await this.mainFrameWrapper.evaluateInLocatorWorld(`globalThis.__stagehandLocatorScripts.moveCursorOverlay(${Math.round(x)}, ${Math.round(y)})`, progress);
56243
+ await this.mainFrameWrapper.evaluateInLocatorWorld(() => `globalThis.__stagehandLocatorScripts.moveCursorOverlay(${Math.round(x)}, ${Math.round(y)})`, progress);
56347
56244
  } catch {
56348
56245
  progress?.throwIfStopped();
56349
56246
  }
@@ -57356,27 +57253,28 @@ var Page = class Page {
57356
57253
  * @param selector CSS selector to wait for (supports '>>' for iframe hops)
57357
57254
  * @param options
57358
57255
  * @param options.state Element state to wait for: 'attached' | 'detached' | 'visible' | 'hidden' (default: 'visible')
57359
- * @param options.timeout Maximum time to wait in milliseconds (default: 30000)
57256
+ * @param options.timeout Maximum time to wait in milliseconds (default: 30000; zero is unlimited)
57360
57257
  * @param options.pierceShadow Whether to search inside shadow DOM (default: true)
57361
57258
  * @returns True when the condition is met
57362
57259
  * @throws Error if timeout is reached before the condition is met
57363
57260
  */
57364
- async waitForSelector(selector, options) {
57365
- const timeout = options?.timeout ?? 3e4;
57366
- const state = options?.state ?? "visible";
57367
- const pierceShadow = options?.pierceShadow ?? true;
57368
- const startTime = Date.now();
57369
- const root = this.mainFrameWrapper;
57370
- const { frame: targetFrame, selector: finalSelector } = await resolveLocatorTarget(this, root, selector);
57371
- const elapsed = Date.now() - startTime;
57372
- const remainingTimeout = Math.max(0, timeout - elapsed);
57373
- const expression = buildLocatorInvocation("waitForSelector", [
57374
- JSON.stringify(finalSelector),
57375
- JSON.stringify(state),
57376
- String(remainingTimeout),
57377
- String(pierceShadow)
57378
- ]);
57379
- return targetFrame.evaluateInLocatorWorld(expression);
57261
+ async waitForSelector(selector, options, parentProgress) {
57262
+ return runWithProgress(parentProgress ?? {
57263
+ name: "waitForSelector",
57264
+ timeout: options?.timeout ?? 3e4
57265
+ }, async (progress) => {
57266
+ const { frame: targetFrame, selector: finalSelector } = await resolveLocatorTarget(this, this.mainFrameWrapper, selector, progress);
57267
+ return targetFrame.waitInLocatorWorld(() => {
57268
+ const remaining = progress.remainingMs();
57269
+ progress.throwIfStopped();
57270
+ return buildLocatorInvocation("createSelectorWait", [
57271
+ JSON.stringify(finalSelector),
57272
+ JSON.stringify(options?.state ?? "visible"),
57273
+ String(remaining === Infinity ? 0 : Math.ceil(remaining)),
57274
+ String(options?.pierceShadow ?? true)
57275
+ ]);
57276
+ }, progress);
57277
+ });
57380
57278
  }
57381
57279
  /** Internal batch evaluation; page.evaluate continues to use the main world unchanged. */
57382
57280
  async evaluateWithShadowRoots(functionSource) {
@@ -145,12 +145,7 @@ class Animations(StrEnum):
145
145
 
146
146
 
147
147
  class AnthropicModelName(RootModel[StrictStr]):
148
- root: Annotated[
149
- StrictStr,
150
- Field(
151
- pattern="^anthropic\\/(claude-3-haiku-20240307|claude-haiku-4-5-20251001|claude-haiku-4-5|claude-opus-4-0|claude-opus-4-20250514|claude-opus-4-1-20250805|claude-opus-4-1|claude-opus-4-5|claude-opus-4-5-20251101|claude-sonnet-4-0|claude-sonnet-4-20250514|claude-sonnet-4-5-20250929|claude-sonnet-4-5|claude-sonnet-4-6|claude-opus-4-6|claude-opus-4-7|claude-opus-4-8|claude-fable-5|claude-sonnet-5)$"
152
- ),
153
- ]
148
+ root: Annotated[StrictStr, Field(pattern="^anthropic\\/\\S+$")]
154
149
 
155
150
 
156
151
  class Browser(StrEnum):
@@ -350,12 +345,7 @@ class Caret(StrEnum):
350
345
 
351
346
 
352
347
  class CerebrasModelName(RootModel[StrictStr]):
353
- root: Annotated[
354
- StrictStr,
355
- Field(
356
- pattern="^cerebras\\/(llama3\\.1-8b|gpt-oss-120b|qwen-3-235b-a22b-instruct-2507|qwen-3-235b-a22b-thinking-2507|zai-glm-4\\.6|zai-glm-4\\.7)$"
357
- ),
358
- ]
348
+ root: Annotated[StrictStr, Field(pattern="^cerebras\\/\\S+$")]
359
349
 
360
350
 
361
351
  class ClearCookieOptions(WireModel):
@@ -709,21 +699,11 @@ class FieldSchema9(
709
699
 
710
700
 
711
701
  class GoogleModelName(RootModel[StrictStr]):
712
- root: Annotated[
713
- StrictStr,
714
- Field(
715
- pattern="^google\\/(gemini-2\\.0-flash|gemini-2\\.0-flash-001|gemini-2\\.0-flash-lite|gemini-2\\.0-flash-lite-001|gemini-2\\.5-pro|gemini-2\\.5-flash|gemini-2\\.5-flash-image|gemini-2\\.5-flash-lite|gemini-2\\.5-flash-preview-tts|gemini-2\\.5-pro-preview-tts|gemini-2\\.5-flash-native-audio-latest|gemini-2\\.5-flash-native-audio-preview-09-2025|gemini-2\\.5-flash-native-audio-preview-12-2025|gemini-2\\.5-computer-use-preview-10-2025|gemini-3-pro-preview|gemini-3-pro-image-preview|gemini-3-flash-preview|gemini-3\\.1-pro-preview|gemini-3\\.1-pro-preview-customtools|gemini-3\\.1-flash-image-preview|gemini-3\\.1-flash-lite-preview|gemini-3\\.1-flash-tts-preview|gemini-3\\.5-flash|gemini-3\\.6-flash|gemini-pro-latest|gemini-flash-latest|gemini-flash-lite-latest|deep-research-pro-preview-12-2025|deep-research-max-preview-04-2026|deep-research-preview-04-2026|nano-banana-pro-preview|aqa|gemini-robotics-er-1\\.5-preview|gemma-3-1b-it|gemma-3-4b-it|gemma-3n-e4b-it|gemma-3n-e2b-it|gemma-3-12b-it|gemma-3-27b-it)$"
716
- ),
717
- ]
702
+ root: Annotated[StrictStr, Field(pattern="^google\\/\\S+$")]
718
703
 
719
704
 
720
705
  class GroqModelName(RootModel[StrictStr]):
721
- root: Annotated[
722
- StrictStr,
723
- Field(
724
- pattern="^groq\\/(gemma2-9b-it|llama-3\\.1-8b-instant|llama-3\\.3-70b-versatile|meta-llama\\/llama-guard-4-12b|openai\\/gpt-oss-120b|openai\\/gpt-oss-20b|deepseek-r1-distill-llama-70b|meta-llama\\/llama-4-maverick-17b-128e-instruct|meta-llama\\/llama-4-scout-17b-16e-instruct|meta-llama\\/llama-prompt-guard-2-22m|meta-llama\\/llama-prompt-guard-2-86m|moonshotai\\/kimi-k2-instruct-0905|qwen\\/qwen3-32b|llama-guard-3-8b|llama3-70b-8192|llama3-8b-8192|mixtral-8x7b-32768|qwen-qwq-32b|qwen-2\\.5-32b|deepseek-r1-distill-qwen-32b)$"
725
- ),
726
- ]
706
+ root: Annotated[StrictStr, Field(pattern="^groq\\/\\S+$")]
727
707
 
728
708
 
729
709
  class HttpVersion(StrEnum):
@@ -1462,19 +1442,14 @@ class ObserveResult(WireModel):
1462
1442
 
1463
1443
 
1464
1444
  class OpenAIModelName(RootModel[StrictStr]):
1465
- root: Annotated[
1466
- StrictStr,
1467
- Field(
1468
- pattern="^openai\\/(gpt-4\\.1|gpt-4\\.1-2025-04-14|gpt-4\\.1-mini|gpt-4\\.1-mini-2025-04-14|gpt-4\\.1-nano|gpt-4\\.1-nano-2025-04-14|gpt-4o|gpt-4o-2024-05-13|gpt-4o-2024-08-06|gpt-4o-2024-11-20|gpt-4o-audio-preview|gpt-4o-audio-preview-2024-12-17|gpt-4o-search-preview|gpt-4o-search-preview-2025-03-11|gpt-4o-mini-search-preview|gpt-4o-mini-search-preview-2025-03-11|gpt-4o-mini|gpt-4o-mini-2024-07-18|gpt-3\\.5-turbo-0125|gpt-3\\.5-turbo|gpt-3\\.5-turbo-1106|gpt-5-chat-latest|o1|o1-2024-12-17|o3|o3-2025-04-16|o3-mini|o3-mini-2025-01-31|o4-mini|o4-mini-2025-04-16|gpt-5|gpt-5-2025-08-07|gpt-5-codex|gpt-5-mini|gpt-5-mini-2025-08-07|gpt-5-nano|gpt-5-nano-2025-08-07|gpt-5-pro|gpt-5-pro-2025-10-06|gpt-5\\.1|gpt-5\\.1-chat-latest|gpt-5\\.1-codex-mini|gpt-5\\.1-codex|gpt-5\\.1-codex-max|gpt-5\\.2|gpt-5\\.2-chat-latest|gpt-5\\.2-pro|gpt-5\\.2-codex|gpt-5\\.3-chat-latest|gpt-5\\.3-codex|gpt-5\\.4|gpt-5\\.4-2026-03-05|gpt-5\\.4-mini|gpt-5\\.4-mini-2026-03-17|gpt-5\\.4-nano|gpt-5\\.4-nano-2026-03-17|gpt-5\\.4-pro|gpt-5\\.4-pro-2026-03-05|gpt-5\\.5|gpt-5\\.5-2026-04-23|gpt-5\\.6|gpt-5\\.6-luna|gpt-5\\.6-sol|gpt-5\\.6-terra)$"
1469
- ),
1470
- ]
1445
+ root: Annotated[StrictStr, Field(pattern="^openai\\/\\S+$")]
1471
1446
 
1472
1447
 
1473
1448
  class ModelName(
1474
1449
  RootModel[Union[OpenAIModelName, AnthropicModelName, GoogleModelName, GroqModelName, CerebrasModelName]]
1475
1450
  ):
1476
1451
  root: Union[OpenAIModelName, AnthropicModelName, GoogleModelName, GroqModelName, CerebrasModelName]
1477
- """An explicitly supported model name with its provider prefix"""
1452
+ """A model name with a supported provider prefix"""
1478
1453
 
1479
1454
 
1480
1455
  class OperatingSystem(StrEnum):
@@ -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-535b80d78b84a5ad3ead386d5399029bb873b80e'
4
+ STAGEHAND_PROTOCOL_VERSION = '2.1.1-alpha-bfeda482351a8613e3f8fe485b181bb8588b77ab'
@@ -569,7 +569,10 @@ def _rpc_response_timeout_seconds(method: str, params: BaseModel) -> float | Non
569
569
  operation_timeout_ms = _numeric_property(params, "ms")
570
570
 
571
571
  if operation_timeout_ms is not None:
572
- if method in {"page.pdf", "page.snapshot"} and operation_timeout_ms == 0:
572
+ if (
573
+ method in {"page.pdf", "page.snapshot", "page.wait_for_selector"}
574
+ and operation_timeout_ms == 0
575
+ ):
573
576
  return None
574
577
  return (_RPC_RESPONSE_GRACE_MS + max(0, operation_timeout_ms)) / 1_000
575
578