Skip to content

Commit eec542e

Browse files
authored
feat: expose a public failure and retry contract for browser-action errors (#232)
Skyvern-AI/rustwright-cloud#221 --------- Co-authored-by: suchintan <3853670+suchintan@users.noreply.github.com>
1 parent 58be34b commit eec542e

22 files changed

Lines changed: 3261 additions & 391 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ All notable user-facing changes to Rustwright are documented in this file.
77
### Changed
88

99
- Verified support for standard CPython 3.9 through 3.14 and CPython 3.15.0rc1. Python 3.15 support remains pre-release, and CI tracks 3.15-dev until GA.
10+
- Added a public failure and retry contract for browser actions. Rust, Python, and MCP callers can inspect the failure phase, target kind, command-write status, and retry safety. A tracked input command with unknown delivery now raises `UnknownOutcomeError` in Python and is never reported as safe to retry. Other bindings keep their existing error types and receive a clear diagnostic message.
1011

1112
## [0.2.0] - 2026-08-03
1213

bindings/CONTRACT.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,8 @@ the same OS thread and copy the borrowed UTF-8 message into language-owned
103103
memory. It is NULL when no error is recorded and is valid only until the next
104104
Rustwright ABI call on that thread. Never free it.
105105
106+
`rw_last_error()` is diagnostic prose, not a machine-readable taxonomy; bindings must not parse it to decide whether to retry.
107+
106108
`rw_browser_ws_endpoint` and `rw_page_target_id` return NULL on failure and set
107109
the same last-error slot. All ABI entry points catch Rust panics; no unwind is
108110
allowed to cross the C boundary.

docs/PARITY.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -731,8 +731,8 @@ The package-root inventory below comes from `rustwright.__all__`; sync and async
731731

732732
| Module | Matching Playwright exports | Playwright exports | Missing | Rustwright-only/extra |
733733
| --- | ---: | ---: | ---: | ---: |
734-
| `sync_api` | 50 | 55 | 5 | 8 |
735-
| `async_api` | 51 | 55 | 4 | 8 |
734+
| `sync_api` | 50 | 55 | 5 | 9 |
735+
| `async_api` | 51 | 55 | 4 | 9 |
736736

737737
Missing sync exports: `FormData`, `ScreencastFrame`, `ScreencastSize`, `Selectors`, `VirtualCredential`.
738738

@@ -760,6 +760,7 @@ Missing async exports: `FormData`, `ScreencastFrame`, `ScreencastSize`, `Virtual
760760
| `Response` | yes | yes |
761761
| `TargetClosedError` | no | no |
762762
| `TimeoutError` | yes | yes |
763+
| `UnknownOutcomeError` | yes | yes |
763764
| `Video` | yes | yes |
764765
| `async_playwright` | no | yes |
765766
| `backend_marker` | yes | yes |
@@ -776,6 +777,7 @@ Missing async exports: `FormData`, `ScreencastFrame`, `ScreencastSize`, `Virtual
776777
- OOPIF support is new. Cross-origin frame locator actions work in covered cases, but non-main-frame remote `JSHandle` follow-up operations remain a gap, and drag, screenshot, and bounding-box behavior in OOPIFs is not yet claimed as full parity.
777778
- Anti-bot and stealth behavior is partial. Rustwright suppresses some common automation signals, but recent public fingerprint checks were only clean on about 2 of 4 targets. Rustwright does not promise undetectability.
778779
- Drop-in compatibility import names are intended to be opt-in for the public alpha. The final compatibility-mode API is being finalized separately.
780+
- `UnknownOutcomeError` is a Rustwright safety extension. Compatibility shims intentionally do not export it.
779781
- The implementation still has large monolithic files. A module split is planned before beta.
780782

781783
## Node.js subset

docs/api-surface/playwright-async-api.json

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1817,11 +1817,14 @@
18171817
"StorageState",
18181818
"StorageStateCookie",
18191819
"TimeoutError",
1820+
"UnknownOutcomeError",
18201821
"ViewportSize",
18211822
"async_playwright",
18221823
"expect"
18231824
],
1824-
"extra": [],
1825+
"extra": [
1826+
"UnknownOutcomeError"
1827+
],
18251828
"missing": {},
18261829
"reference": [
18271830
"APIResponseAssertions",
@@ -1856,7 +1859,7 @@
18561859
},
18571860
"reference_module": "playwright.async_api",
18581861
"summary": {
1859-
"extra_members": 0,
1862+
"extra_members": 1,
18601863
"missing_classes": 0,
18611864
"missing_members": 0,
18621865
"signature_diffs": 0,

docs/api-surface/playwright-async-api.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,6 @@
44
- Candidate: `rustwright.async_api`
55
- Missing classes: `0`
66
- Missing members: `0`
7-
- Extra members: `0`
7+
- Extra members: `1`
88
- Unclassified missing members: `0`
99
- Signature diffs: `0`

docs/api-surface/playwright-sync-api.json

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1817,11 +1817,14 @@
18171817
"StorageState",
18181818
"StorageStateCookie",
18191819
"TimeoutError",
1820+
"UnknownOutcomeError",
18201821
"ViewportSize",
18211822
"expect",
18221823
"sync_playwright"
18231824
],
1824-
"extra": [],
1825+
"extra": [
1826+
"UnknownOutcomeError"
1827+
],
18251828
"missing": {},
18261829
"reference": [
18271830
"APIResponseAssertions",
@@ -1856,7 +1859,7 @@
18561859
},
18571860
"reference_module": "playwright.sync_api",
18581861
"summary": {
1859-
"extra_members": 0,
1862+
"extra_members": 1,
18601863
"missing_classes": 0,
18611864
"missing_members": 0,
18621865
"signature_diffs": 0,

docs/api-surface/playwright-sync-api.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,6 @@
44
- Candidate: `rustwright.sync_api`
55
- Missing classes: `0`
66
- Missing members: `0`
7-
- Extra members: `0`
7+
- Extra members: `1`
88
- Unclassified missing members: `0`
99
- Signature diffs: `0`

0 commit comments

Comments
 (0)