Skip to content

feat: observe-act flow + stagehand v4 upgrade - #222

Merged
CahidArda merged 5 commits into
mainfrom
DX-2913
Aug 17, 2026
Merged

feat: observe-act flow + stagehand v4 upgrade#222
CahidArda merged 5 commits into
mainfrom
DX-2913

Conversation

@alitariksahin

Copy link
Copy Markdown
Collaborator

No description provided.

@alitariksahin alitariksahin self-assigned this Aug 12, 2026
@linear-code

linear-code Bot commented Aug 12, 2026

Copy link
Copy Markdown

DX-2913

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds an “observe → act” replay path to the SDKs, enabling deterministic browser actions by reusing a pre-resolved action object (rather than re-invoking an LLM).

Changes:

  • Extend observe() results to include suggested method and arguments to support replay.
  • Add tab.act(action) overload (TypeScript) and broaden Tab.act(...) to accept pre-resolved actions (Python async + generated sync).
  • Add/adjust tests and release notes (Python changelog + JS changeset).

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
packages/sdk/src/types.ts Adds method/arguments to observe elements and exports BrowserAction union for replay.
packages/sdk/src/index.ts Re-exports BrowserAction from the SDK entrypoint.
packages/sdk/src/client.ts Adds Tab.act(...) overload to accept either an instruction string or a pre-resolved action body.
packages/sdk/src/tests/box-browser.test.ts Adds coverage ensuring replay posts action (not instruction) and updates observe expectations.
packages/python-sdk/upstash_box/types.py Extends BrowserObserveElement with method/arguments.
packages/python-sdk/upstash_box/_sync/client.py Updates generated sync client act() to accept string or pre-resolved action models.
packages/python-sdk/upstash_box/_async/client.py Updates async client act() to accept string or pre-resolved action models.
packages/python-sdk/tests/_async/test_box_browser.py Adds an async unit test asserting replay posts action deterministically.
packages/python-sdk/CHANGELOG.md Documents the new replay capability and the added observe fields.
.changeset/browser-act-replay.md Adds a changeset entry describing the feature and new exported type.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread packages/sdk/src/types.ts
@alitariksahin alitariksahin changed the title feat: observe-act flow feat: observe-act flow + stagehand v4 upgrade Aug 13, 2026
@alitariksahin
alitariksahin requested a balanced review from Copilot August 13, 2026 15:02

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 22 out of 22 changed files in this pull request and generated no new comments.

Suppressed comments (5)

packages/sdk/src/client.ts:530

  • Do not forward the BrowserObserveElement verbatim. That public type permits url, while Stagehand v4 validates replay actions with a strict schema containing only selector, description, method, and arguments; an observed element carrying url will therefore make the advertised observe()act(action) flow fail. Build the wire action from only those four fields.
        : { action: instructionOrAction, tab: this.id };

packages/python-sdk/upstash_box/_async/client.py:611

  • Restrict the serialized replay action to Stagehand v4's strict action fields. BrowserObserveElement includes url, and _Model also allows arbitrary extra response fields, so dumping the whole model can send unsupported keys and cause an actual observe() result to be rejected by act().
            body = {"action": instruction.model_dump(exclude_none=True), "tab": self.id}

packages/sdk/src/types.ts:1184

  • Keep accepting legacy "run" markers when reading recording metadata. Recordings are retained for 14 days, so recordings created before this upgrade can still contain these markers; narrowing the type makes the mapper return values outside its declared type and breaks exhaustive consumers. Removing tab.run() only prevents new markers and does not invalidate stored recordings.
  /** "tab_switch" (recorder-observed). */
  type: "tab_switch";

packages/python-sdk/upstash_box/types.py:822

  • Keep "run" in the deserialization type for legacy recordings. Stored recordings remain available for 14 days, and _map_recording() validates server data through this model, so fetching a pre-upgrade recording containing a run marker will now raise a Pydantic validation error.
    # "tab_switch" (recorder-observed).
    type: Literal["tab_switch"] = "tab_switch"

packages/python-sdk/upstash_box/_sync/client.py:604

  • The generated sync path has the same strict-schema issue: dumping a BrowserObserveElement forwards its permitted url and any allowed extras, which Stagehand v4 rejects for replay actions. Filter to the four action fields in _async/client.py, then regenerate this file rather than editing it directly.
            body = {"action": instruction.model_dump(exclude_none=True), "tab": self.id}

@CahidArda
CahidArda merged commit b91e466 into main Aug 17, 2026
11 of 12 checks passed
@CahidArda
CahidArda deleted the DX-2913 branch August 17, 2026 12:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants