diff --git a/.changeset/lemon-eggs-happen.md b/.changeset/lemon-eggs-happen.md new file mode 100644 index 000000000..95c8bfc6b --- /dev/null +++ b/.changeset/lemon-eggs-happen.md @@ -0,0 +1,5 @@ +--- +"@browserbasehq/stagehand": patch +--- + +log Browserbase session status when websocket is closed due to session timeout diff --git a/packages/core/lib/v3/v3.ts b/packages/core/lib/v3/v3.ts index f57067a46..3c795d8ac 100644 --- a/packages/core/lib/v3/v3.ts +++ b/packages/core/lib/v3/v3.ts @@ -149,6 +149,10 @@ export class V3 { return this.browserbaseDebugUrl; } private _onCdpClosed = (why: string) => { + if (this.state.kind === "BROWSERBASE") { + void this._logBrowserbaseSessionStatus(); + } + // Single place to react to the transport closing this._immediateShutdown(`CDP transport closed: ${why}`).catch(() => {}); }; @@ -1459,6 +1463,33 @@ export class V3 { throw new StagehandInvalidArgumentError("Unsupported page object."); } + private async _logBrowserbaseSessionStatus(): Promise { + if (this.state.kind !== "BROWSERBASE") { + return; + } + + try { + const snapshot = (await this.state.bb.sessions.retrieve( + this.state.sessionId, + )) as { id?: string; status?: string }; + if (!snapshot?.status) return; + + const sessionId = snapshot.id ?? this.state.sessionId; + const message = + snapshot.status === "TIMED_OUT" + ? `Browserbase session timed out (sessionId: ${sessionId})` + : `Browserbase session status: ${snapshot.status}`; + + this.logger({ + category: "v3", + message, + level: 0, + }); + } catch { + // Ignore failures; nothing to log + } + } + /** * Create a v3 agent instance (AISDK tool-based) with execute(). * Mirrors the v2 Stagehand.agent() tool mode (no CUA provider here).