Skip to content

stagehand-python@4.4.0a0.dev1660

@miguelg719 miguelg719 tagged this 29 Oct 01:15
# why
if the sdk process dies without `disconnect()` / `close()` (crash,
`SIGKILL`, dropped connection), nothing tells the browser: a local
chrome stagehand launched keeps running, and the extension stays
initialized, so reconnecting fails with "A Stagehand instance is already
initialized". builds on #3305 & adopts the mechanism from
`service-watchdog`

# what changed
- on connect the sdk creates a hidden target on its own cdp connection;
chrome destroys it when that connection ends. the extension watches
`Target.targetDestroyed` over its own connection, with no heartbeat or
timers
- on loss: a local browser stagehand launched without `keepAlive` gets
`Browser.close`; anything else keeps running, and the extension releases
the instance & closes its own connection, so browserbase applies its
`keepAlive` policy and a new client can attach
- `disconnect()` detaches (disarms the watchdog) before closing; if the
detach isn't acknowledged, the socket & handle stay open, since closing
would read as a loss
- registration checks the marker really is hidden (`type: "other"`);
with an older extension or a chrome without hidden targets the sdk warns
once & continues without the watchdog
- one client per browser: a second client gets "A Stagehand client is
already connected"
- ts & python; docs & changeset

# test plan
- extension unit tests: loss/terminate/detach ordering, close of the
extension's connection on loss, registration races
- sdk unit tests in both sdks: loss policy per
provider/origin/keepAlive, unacknowledged detach keeps the handle usable
- real chrome (ts & python): `SIGKILL`/`SIGINT` matrix (owned
keepAlive=false is shut down, keepAlive=true & externally launched
chrome survive and re-attach), disconnect → reconnect → create
- live browserbase: hidden target works through the proxy; after
`SIGKILL` of the host, a `keepAlive: false` session is `COMPLETED`
within 5s, and a `keepAlive: true` session stays `RUNNING` & accepts
`connect()` + `Stagehand.create()`

---------

Co-authored-by: Sean McGuire <seanmcguire1@outlook.com>
Assets 2
Loading