feat: expose browser-side function waits across Stagehand SDKs

Merged
SU
8d ago
+1303-73

why

Expose browser-side predicate waiting consistently across Stagehand SDKs, without transport polling.

This is PR2 of 2, stacked directly on #3179 (amel/wait-for-function-extension). Polling, navigation recovery, and cleanup live in the parent; merge it first using the repository’s stacked-PR handoff rules.

what changed

  • Register page.wait_for_function and connect the extension controller/runtime to the internal implementation.
  • Add TypeScript waitForFunction(expression, arg?, options?), Python wait_for_function(expression, *, arg, polling, timeout), and Go WaitForFunction. As in Playwright, an expression that evaluates to a function is invoked on each poll and receives the optional JSON arg.
  • Preserve JSON result keys through opaque wire metadata, with roundtrip coverage for own toString, constructor, and hasOwnProperty keys in nested payloads. No browser-handle API is introduced.
  • Provide RAF/interval polling and no deadline by default in all three SDKs; pass timeout to bound a wait. An omitted or zero timeout also drops the client response deadline.
  • Derive internal wait options from the canonical protocol contract. Reuse the TypeScript argument serializer. Model Go’s string-or-number polling option through its existing typed-union generator extension point.
  • Regenerate protocol/models/final ZIP and include docs plus minor release entries for all five packages.

Reviewed with the requested Thermo-Nuclear Code Quality Review skill, including an independent cross-review of SDK boundaries. No SDK polling loops, duplicated serializer, broad generator abstraction, or new 1,000-line file crossing.

test plan

  • 9 real-Chrome tests passed, including main-world access, async predicates, custom intervals, error propagation, navigation recovery, concurrent waits, and timeout-zero closure.
  • 79 extension/selector tests and 788 protocol/docs/SDK/architecture guards passed.
  • 184 Python tests plus Ruff/type checks passed; Go SDK package tests passed.
  • Follow-up review: 26 wire tests passed; canonical option types emit unchanged JavaScript, and the rebuilt extension ZIP remains identical.
  • Extension/SDK/protocol typechecks, dependency-ordered build, generated-model/ZIP checks, formatting, lint, and git diff --check passed.