opensteer 0.4.8 → 0.4.9

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.
@@ -341,7 +341,9 @@ var StealthCdpRuntime = class _StealthCdpRuntime {
341
341
  const frameRecords = await this.getFrameRecords();
342
342
  const mainFrame = frameRecords[0];
343
343
  if (!mainFrame) return;
344
- await this.waitForFrameVisualStability(mainFrame.frameId, timeout, settleMs);
344
+ await this.waitForFrameVisualStability(mainFrame.frameId, timeout, settleMs, {
345
+ retryTransientContextErrors: true
346
+ });
345
347
  }
346
348
  async collectVisibleFrameIds() {
347
349
  const frameRecords = await this.getFrameRecords();
@@ -370,19 +372,40 @@ var StealthCdpRuntime = class _StealthCdpRuntime {
370
372
  }
371
373
  return visibleFrameIds;
372
374
  }
373
- async waitForFrameVisualStability(frameId, timeout, settleMs) {
375
+ async waitForFrameVisualStability(frameId, timeout, settleMs, options = {}) {
374
376
  if (timeout <= 0) return;
375
377
  const script = buildStabilityScript(timeout, settleMs);
376
- let contextId = await this.ensureFrameContextId(frameId);
377
- try {
378
- await this.evaluateWithGuard(contextId, script, timeout);
379
- } catch (error) {
380
- if (!isMissingExecutionContextError(error)) {
381
- throw error;
378
+ const retryTransientContextErrors = options.retryTransientContextErrors ?? true;
379
+ if (!retryTransientContextErrors) {
380
+ let contextId = await this.ensureFrameContextId(frameId);
381
+ try {
382
+ await this.evaluateWithGuard(contextId, script, timeout);
383
+ } catch (error) {
384
+ if (!isMissingExecutionContextReferenceError(error)) {
385
+ throw error;
386
+ }
387
+ this.contextsByFrame.delete(frameId);
388
+ contextId = await this.ensureFrameContextId(frameId);
389
+ await this.evaluateWithGuard(contextId, script, timeout);
390
+ }
391
+ return;
392
+ }
393
+ const deadline = Date.now() + timeout;
394
+ while (true) {
395
+ const remaining = Math.max(0, deadline - Date.now());
396
+ if (remaining === 0) {
397
+ return;
398
+ }
399
+ const contextId = await this.ensureFrameContextId(frameId);
400
+ try {
401
+ await this.evaluateWithGuard(contextId, script, remaining);
402
+ return;
403
+ } catch (error) {
404
+ if (!isTransientExecutionContextError(error)) {
405
+ throw error;
406
+ }
407
+ this.contextsByFrame.delete(frameId);
382
408
  }
383
- this.contextsByFrame.delete(frameId);
384
- contextId = await this.ensureFrameContextId(frameId);
385
- await this.evaluateWithGuard(contextId, script, timeout);
386
409
  }
387
410
  }
388
411
  async initialize() {
@@ -502,7 +525,10 @@ async function waitForVisualStabilityAcrossFrames(page, options = {}) {
502
525
  await runtime.waitForFrameVisualStability(
503
526
  frameId,
504
527
  remaining,
505
- settleMs
528
+ settleMs,
529
+ {
530
+ retryTransientContextErrors: false
531
+ }
506
532
  );
507
533
  } catch (error) {
508
534
  if (isIgnorableFrameError(error)) return;
@@ -540,7 +566,12 @@ function sameFrameIds(before, after) {
540
566
  function formatCdpException(details) {
541
567
  return details.exception?.description || details.text || "CDP runtime evaluation failed.";
542
568
  }
543
- function isMissingExecutionContextError(error) {
569
+ function isTransientExecutionContextError(error) {
570
+ if (!(error instanceof Error)) return false;
571
+ const message = error.message;
572
+ return message.includes("Execution context was destroyed") || message.includes("Cannot find context with specified id") || message.includes("Cannot find execution context");
573
+ }
574
+ function isMissingExecutionContextReferenceError(error) {
544
575
  if (!(error instanceof Error)) return false;
545
576
  const message = error.message;
546
577
  return message.includes("Cannot find context with specified id") || message.includes("Cannot find execution context");
@@ -548,7 +579,7 @@ function isMissingExecutionContextError(error) {
548
579
  function isIgnorableFrameError(error) {
549
580
  if (!(error instanceof Error)) return false;
550
581
  const message = error.message;
551
- return message.includes("Frame was detached") || message.includes("Execution context was destroyed") || message.includes("Target page, context or browser has been closed") || message.includes("Cannot find context with specified id") || message.includes("Cannot find execution context") || message.includes("No frame for given id found");
582
+ return message.includes("Frame was detached") || message.includes("Target page, context or browser has been closed") || isTransientExecutionContextError(error) || message.includes("No frame for given id found");
552
583
  }
553
584
  function sleep(ms) {
554
585
  return new Promise((resolve) => {
@@ -1493,7 +1493,9 @@ var StealthCdpRuntime = class _StealthCdpRuntime {
1493
1493
  const frameRecords = await this.getFrameRecords();
1494
1494
  const mainFrame = frameRecords[0];
1495
1495
  if (!mainFrame) return;
1496
- await this.waitForFrameVisualStability(mainFrame.frameId, timeout, settleMs);
1496
+ await this.waitForFrameVisualStability(mainFrame.frameId, timeout, settleMs, {
1497
+ retryTransientContextErrors: true
1498
+ });
1497
1499
  }
1498
1500
  async collectVisibleFrameIds() {
1499
1501
  const frameRecords = await this.getFrameRecords();
@@ -1522,19 +1524,40 @@ var StealthCdpRuntime = class _StealthCdpRuntime {
1522
1524
  }
1523
1525
  return visibleFrameIds;
1524
1526
  }
1525
- async waitForFrameVisualStability(frameId, timeout, settleMs) {
1527
+ async waitForFrameVisualStability(frameId, timeout, settleMs, options = {}) {
1526
1528
  if (timeout <= 0) return;
1527
1529
  const script = buildStabilityScript(timeout, settleMs);
1528
- let contextId = await this.ensureFrameContextId(frameId);
1529
- try {
1530
- await this.evaluateWithGuard(contextId, script, timeout);
1531
- } catch (error) {
1532
- if (!isMissingExecutionContextError(error)) {
1533
- throw error;
1530
+ const retryTransientContextErrors = options.retryTransientContextErrors ?? true;
1531
+ if (!retryTransientContextErrors) {
1532
+ let contextId = await this.ensureFrameContextId(frameId);
1533
+ try {
1534
+ await this.evaluateWithGuard(contextId, script, timeout);
1535
+ } catch (error) {
1536
+ if (!isMissingExecutionContextReferenceError(error)) {
1537
+ throw error;
1538
+ }
1539
+ this.contextsByFrame.delete(frameId);
1540
+ contextId = await this.ensureFrameContextId(frameId);
1541
+ await this.evaluateWithGuard(contextId, script, timeout);
1542
+ }
1543
+ return;
1544
+ }
1545
+ const deadline = Date.now() + timeout;
1546
+ while (true) {
1547
+ const remaining = Math.max(0, deadline - Date.now());
1548
+ if (remaining === 0) {
1549
+ return;
1550
+ }
1551
+ const contextId = await this.ensureFrameContextId(frameId);
1552
+ try {
1553
+ await this.evaluateWithGuard(contextId, script, remaining);
1554
+ return;
1555
+ } catch (error) {
1556
+ if (!isTransientExecutionContextError(error)) {
1557
+ throw error;
1558
+ }
1559
+ this.contextsByFrame.delete(frameId);
1534
1560
  }
1535
- this.contextsByFrame.delete(frameId);
1536
- contextId = await this.ensureFrameContextId(frameId);
1537
- await this.evaluateWithGuard(contextId, script, timeout);
1538
1561
  }
1539
1562
  }
1540
1563
  async initialize() {
@@ -1654,7 +1677,10 @@ async function waitForVisualStabilityAcrossFrames(page, options = {}) {
1654
1677
  await runtime.waitForFrameVisualStability(
1655
1678
  frameId,
1656
1679
  remaining,
1657
- settleMs
1680
+ settleMs,
1681
+ {
1682
+ retryTransientContextErrors: false
1683
+ }
1658
1684
  );
1659
1685
  } catch (error) {
1660
1686
  if (isIgnorableFrameError(error)) return;
@@ -1692,7 +1718,12 @@ function sameFrameIds(before, after) {
1692
1718
  function formatCdpException(details) {
1693
1719
  return details.exception?.description || details.text || "CDP runtime evaluation failed.";
1694
1720
  }
1695
- function isMissingExecutionContextError(error) {
1721
+ function isTransientExecutionContextError(error) {
1722
+ if (!(error instanceof Error)) return false;
1723
+ const message = error.message;
1724
+ return message.includes("Execution context was destroyed") || message.includes("Cannot find context with specified id") || message.includes("Cannot find execution context");
1725
+ }
1726
+ function isMissingExecutionContextReferenceError(error) {
1696
1727
  if (!(error instanceof Error)) return false;
1697
1728
  const message = error.message;
1698
1729
  return message.includes("Cannot find context with specified id") || message.includes("Cannot find execution context");
@@ -1700,7 +1731,7 @@ function isMissingExecutionContextError(error) {
1700
1731
  function isIgnorableFrameError(error) {
1701
1732
  if (!(error instanceof Error)) return false;
1702
1733
  const message = error.message;
1703
- return message.includes("Frame was detached") || message.includes("Execution context was destroyed") || message.includes("Target page, context or browser has been closed") || message.includes("Cannot find context with specified id") || message.includes("Cannot find execution context") || message.includes("No frame for given id found");
1734
+ return message.includes("Frame was detached") || message.includes("Target page, context or browser has been closed") || isTransientExecutionContextError(error) || message.includes("No frame for given id found");
1704
1735
  }
1705
1736
  function sleep(ms) {
1706
1737
  return new Promise((resolve) => {
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  Opensteer
3
- } from "../chunk-GQ7HNCM2.js";
3
+ } from "../chunk-U6YJI5GO.js";
4
4
  import "../chunk-3H5RRIMZ.js";
5
5
 
6
6
  // src/cli/server.ts
package/dist/index.cjs CHANGED
@@ -1568,7 +1568,9 @@ var StealthCdpRuntime = class _StealthCdpRuntime {
1568
1568
  const frameRecords = await this.getFrameRecords();
1569
1569
  const mainFrame = frameRecords[0];
1570
1570
  if (!mainFrame) return;
1571
- await this.waitForFrameVisualStability(mainFrame.frameId, timeout, settleMs);
1571
+ await this.waitForFrameVisualStability(mainFrame.frameId, timeout, settleMs, {
1572
+ retryTransientContextErrors: true
1573
+ });
1572
1574
  }
1573
1575
  async collectVisibleFrameIds() {
1574
1576
  const frameRecords = await this.getFrameRecords();
@@ -1597,19 +1599,40 @@ var StealthCdpRuntime = class _StealthCdpRuntime {
1597
1599
  }
1598
1600
  return visibleFrameIds;
1599
1601
  }
1600
- async waitForFrameVisualStability(frameId, timeout, settleMs) {
1602
+ async waitForFrameVisualStability(frameId, timeout, settleMs, options = {}) {
1601
1603
  if (timeout <= 0) return;
1602
1604
  const script = buildStabilityScript(timeout, settleMs);
1603
- let contextId = await this.ensureFrameContextId(frameId);
1604
- try {
1605
- await this.evaluateWithGuard(contextId, script, timeout);
1606
- } catch (error) {
1607
- if (!isMissingExecutionContextError(error)) {
1608
- throw error;
1605
+ const retryTransientContextErrors = options.retryTransientContextErrors ?? true;
1606
+ if (!retryTransientContextErrors) {
1607
+ let contextId = await this.ensureFrameContextId(frameId);
1608
+ try {
1609
+ await this.evaluateWithGuard(contextId, script, timeout);
1610
+ } catch (error) {
1611
+ if (!isMissingExecutionContextReferenceError(error)) {
1612
+ throw error;
1613
+ }
1614
+ this.contextsByFrame.delete(frameId);
1615
+ contextId = await this.ensureFrameContextId(frameId);
1616
+ await this.evaluateWithGuard(contextId, script, timeout);
1617
+ }
1618
+ return;
1619
+ }
1620
+ const deadline = Date.now() + timeout;
1621
+ while (true) {
1622
+ const remaining = Math.max(0, deadline - Date.now());
1623
+ if (remaining === 0) {
1624
+ return;
1625
+ }
1626
+ const contextId = await this.ensureFrameContextId(frameId);
1627
+ try {
1628
+ await this.evaluateWithGuard(contextId, script, remaining);
1629
+ return;
1630
+ } catch (error) {
1631
+ if (!isTransientExecutionContextError(error)) {
1632
+ throw error;
1633
+ }
1634
+ this.contextsByFrame.delete(frameId);
1609
1635
  }
1610
- this.contextsByFrame.delete(frameId);
1611
- contextId = await this.ensureFrameContextId(frameId);
1612
- await this.evaluateWithGuard(contextId, script, timeout);
1613
1636
  }
1614
1637
  }
1615
1638
  async initialize() {
@@ -1729,7 +1752,10 @@ async function waitForVisualStabilityAcrossFrames(page, options = {}) {
1729
1752
  await runtime.waitForFrameVisualStability(
1730
1753
  frameId,
1731
1754
  remaining,
1732
- settleMs
1755
+ settleMs,
1756
+ {
1757
+ retryTransientContextErrors: false
1758
+ }
1733
1759
  );
1734
1760
  } catch (error) {
1735
1761
  if (isIgnorableFrameError(error)) return;
@@ -1767,7 +1793,12 @@ function sameFrameIds(before, after) {
1767
1793
  function formatCdpException(details) {
1768
1794
  return details.exception?.description || details.text || "CDP runtime evaluation failed.";
1769
1795
  }
1770
- function isMissingExecutionContextError(error) {
1796
+ function isTransientExecutionContextError(error) {
1797
+ if (!(error instanceof Error)) return false;
1798
+ const message = error.message;
1799
+ return message.includes("Execution context was destroyed") || message.includes("Cannot find context with specified id") || message.includes("Cannot find execution context");
1800
+ }
1801
+ function isMissingExecutionContextReferenceError(error) {
1771
1802
  if (!(error instanceof Error)) return false;
1772
1803
  const message = error.message;
1773
1804
  return message.includes("Cannot find context with specified id") || message.includes("Cannot find execution context");
@@ -1775,7 +1806,7 @@ function isMissingExecutionContextError(error) {
1775
1806
  function isIgnorableFrameError(error) {
1776
1807
  if (!(error instanceof Error)) return false;
1777
1808
  const message = error.message;
1778
- return message.includes("Frame was detached") || message.includes("Execution context was destroyed") || message.includes("Target page, context or browser has been closed") || message.includes("Cannot find context with specified id") || message.includes("Cannot find execution context") || message.includes("No frame for given id found");
1809
+ return message.includes("Frame was detached") || message.includes("Target page, context or browser has been closed") || isTransientExecutionContextError(error) || message.includes("No frame for given id found");
1779
1810
  }
1780
1811
  function sleep(ms) {
1781
1812
  return new Promise((resolve) => {
package/dist/index.js CHANGED
@@ -68,7 +68,7 @@ import {
68
68
  switchTab,
69
69
  typeText,
70
70
  waitForVisualStability
71
- } from "./chunk-GQ7HNCM2.js";
71
+ } from "./chunk-U6YJI5GO.js";
72
72
  import {
73
73
  createResolveCallback
74
74
  } from "./chunk-SRJLH34D.js";
package/package.json CHANGED
@@ -1,75 +1,82 @@
1
1
  {
2
- "name": "opensteer",
3
- "version": "0.4.8",
4
- "description": "Open-source browser automation SDK with robust selectors and deterministic replay.",
5
- "license": "MIT",
6
- "type": "module",
7
- "bin": {
8
- "opensteer": "./bin/opensteer.mjs"
9
- },
10
- "main": "./dist/index.cjs",
11
- "module": "./dist/index.js",
12
- "types": "./dist/index.d.ts",
13
- "exports": {
14
- ".": {
15
- "types": "./dist/index.d.ts",
16
- "import": "./dist/index.js",
17
- "require": "./dist/index.cjs"
2
+ "name": "opensteer",
3
+ "version": "0.4.9",
4
+ "packageManager": "pnpm@10.29.3",
5
+ "description": "Open-source browser automation SDK with robust selectors and deterministic replay.",
6
+ "license": "MIT",
7
+ "type": "module",
8
+ "bin": {
9
+ "opensteer": "./bin/opensteer.mjs"
10
+ },
11
+ "main": "./dist/index.cjs",
12
+ "module": "./dist/index.js",
13
+ "types": "./dist/index.d.ts",
14
+ "exports": {
15
+ ".": {
16
+ "types": "./dist/index.d.ts",
17
+ "import": "./dist/index.js",
18
+ "require": "./dist/index.cjs"
19
+ }
20
+ },
21
+ "files": [
22
+ "dist",
23
+ "bin",
24
+ "README.md",
25
+ "LICENSE",
26
+ "CHANGELOG.md"
27
+ ],
28
+ "scripts": {
29
+ "build": "tsup src/index.ts src/cli/server.ts --dts --format esm,cjs --clean --external ai --external zod --external @ai-sdk/openai --external @ai-sdk/anthropic --external @ai-sdk/google --external @ai-sdk/xai --external @ai-sdk/groq",
30
+ "prepublishOnly": "pnpm run build",
31
+ "test": "vitest run",
32
+ "test:live-web": "vitest run --config vitest.live-web.config.ts",
33
+ "test:unit": "vitest run tests/html tests/element-path tests/config.test.ts tests/storage",
34
+ "test:actions": "vitest run tests/actions",
35
+ "test:integration": "vitest run tests/integration",
36
+ "test:ai": "vitest run tests/ai tests/e2e/ai-resolve.test.ts tests/e2e/ai-extract-products.test.ts",
37
+ "test:e2e": "vitest run tests/e2e",
38
+ "test:app:dev": "pnpm --dir tests/test-app run dev",
39
+ "typecheck": "tsc -p tsconfig.json --noEmit"
40
+ },
41
+ "dependencies": {
42
+ "@ai-sdk/anthropic": "^3.0.46",
43
+ "@ai-sdk/google": "^3.0.30",
44
+ "@ai-sdk/groq": "^3.0.24",
45
+ "@ai-sdk/openai": "^3.0.26",
46
+ "@ai-sdk/xai": "^3.0.57",
47
+ "ai": "^6.0.77",
48
+ "cheerio": "^1.0.0-rc.12",
49
+ "dotenv": "^17.2.4",
50
+ "playwright": "^1.50.0",
51
+ "ws": "^8.18.0",
52
+ "zod": "^4.3.6"
53
+ },
54
+ "devDependencies": {
55
+ "@types/node": "^22.10.0",
56
+ "@types/ws": "^8.5.13",
57
+ "domhandler": "^5.0.3",
58
+ "tsup": "^8.0.1",
59
+ "typescript": "^5.6.3",
60
+ "vite": "^7.3.1",
61
+ "vitest": "^2.1.8"
62
+ },
63
+ "pnpm": {
64
+ "onlyBuiltDependencies": [
65
+ "esbuild"
66
+ ]
67
+ },
68
+ "engines": {
69
+ "node": ">=20"
70
+ },
71
+ "keywords": [
72
+ "browser-automation",
73
+ "selectors",
74
+ "playwright",
75
+ "llm",
76
+ "agents"
77
+ ],
78
+ "repository": {
79
+ "type": "git",
80
+ "url": "https://github.com/opensteer-ai/opensteer"
18
81
  }
19
- },
20
- "files": [
21
- "dist",
22
- "bin",
23
- "README.md",
24
- "LICENSE",
25
- "CHANGELOG.md"
26
- ],
27
- "dependencies": {
28
- "@ai-sdk/anthropic": "^3.0.46",
29
- "@ai-sdk/google": "^3.0.30",
30
- "@ai-sdk/groq": "^3.0.24",
31
- "@ai-sdk/openai": "^3.0.26",
32
- "@ai-sdk/xai": "^3.0.57",
33
- "ai": "^6.0.77",
34
- "cheerio": "^1.0.0-rc.12",
35
- "dotenv": "^17.2.4",
36
- "playwright": "^1.50.0",
37
- "ws": "^8.18.0",
38
- "zod": "^4.3.6"
39
- },
40
- "devDependencies": {
41
- "@types/node": "^22.10.0",
42
- "@types/ws": "^8.5.13",
43
- "domhandler": "^5.0.3",
44
- "tsup": "^8.0.1",
45
- "typescript": "^5.6.3",
46
- "vite": "^7.3.1",
47
- "vitest": "^2.1.8"
48
- },
49
- "engines": {
50
- "node": ">=20"
51
- },
52
- "keywords": [
53
- "browser-automation",
54
- "selectors",
55
- "playwright",
56
- "llm",
57
- "agents"
58
- ],
59
- "repository": {
60
- "type": "git",
61
- "url": "https://github.com/opensteer-ai/opensteer"
62
- },
63
- "scripts": {
64
- "build": "tsup src/index.ts src/cli/server.ts --dts --format esm,cjs --clean --external ai --external zod --external @ai-sdk/openai --external @ai-sdk/anthropic --external @ai-sdk/google --external @ai-sdk/xai --external @ai-sdk/groq",
65
- "test": "vitest run",
66
- "test:live-web": "vitest run --config vitest.live-web.config.ts",
67
- "test:unit": "vitest run tests/html tests/element-path tests/config.test.ts tests/storage",
68
- "test:actions": "vitest run tests/actions",
69
- "test:integration": "vitest run tests/integration",
70
- "test:ai": "vitest run tests/ai tests/e2e/ai-resolve.test.ts tests/e2e/ai-extract-products.test.ts",
71
- "test:e2e": "vitest run tests/e2e",
72
- "test:app:dev": "pnpm --dir tests/test-app run dev",
73
- "typecheck": "tsc -p tsconfig.json --noEmit"
74
- }
75
- }
82
+ }