Skip to content

Add session metadata for model name if env: BROWSERBASE #765

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 10 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/odd-doodles-shop.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@browserbasehq/stagehand": patch
---

Add session create metadata when env is BROWSERBASE for model client + name
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,4 @@ tmp/
eval-summary.json
package-lock.json
evals/deterministic/tests/BrowserContext/tmp-test.har
evals/test-results
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/**
* Just extends sessions.test.ts but with a custom client.
*/
import { test, expect } from "@playwright/test";
import { Stagehand } from "@browserbasehq/stagehand";
import StagehandConfig from "@/evals/deterministic/stagehand.config";
import Browserbase from "@browserbasehq/sdk";
import { AISdkClient } from "@/examples/external_clients/aisdk";
import { google } from "@ai-sdk/google/dist";

test.describe("Browserbase Sessions with custom client metadata", () => {
let browserbase: Browserbase;
let sessionId: string;
let bigStagehand: Stagehand;

test.beforeAll(async () => {
browserbase = new Browserbase({
apiKey: process.env.BROWSERBASE_API_KEY,
});
bigStagehand = new Stagehand({
...StagehandConfig,
env: "BROWSERBASE",
modelName: undefined,
llmClient: new AISdkClient({
model: google("gemini-2.0-flash"),
}),
Comment on lines +23 to +26
Copy link
Contributor

Choose a reason for hiding this comment

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

logic: Setting modelName to undefined while providing an llmClient with a specific model (gemini-2.0-flash) seems inconsistent. Consider setting modelName to match the provided model or document why this is intentionally different.

Copy link
Member Author

Choose a reason for hiding this comment

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

this is intentional to mock when users don't provide a modelName

});
await bigStagehand.init();
await bigStagehand.page.goto(
"https://docs.stagehand.dev/get_started/introduction",
);
sessionId = bigStagehand.browserbaseSessionID;
if (!sessionId) {
throw new Error("Failed to get browserbase session ID");
}
});
test.afterAll(async () => {
await bigStagehand.close();
});
test("creates the right session metadata", async () => {
const session = await browserbase.sessions.retrieve(sessionId);
expect(session.userMetadata.stagehand).toBe("true");
expect(session.userMetadata.modelName).toBe("NO_MODEL_DEFINED");
expect(session.userMetadata.usingCustomClient).toBe("true");
Comment on lines +42 to +44
Copy link
Contributor

Choose a reason for hiding this comment

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

style: Values in userMetadata are stored as strings ('true', 'NO_MODEL_DEFINED'). Consider using a type-safe enum or constants for these values to prevent typos and ensure consistency.

Copy link
Member Author

Choose a reason for hiding this comment

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

k

});
});
6 changes: 6 additions & 0 deletions evals/deterministic/tests/browserbase/sessions.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,4 +64,10 @@ test.describe("Browserbase Sessions", () => {
"https://docs.stagehand.dev/get_started/introduction",
);
});
test("creates the right session metadata", async () => {
const session = await browserbase.sessions.retrieve(sessionId);
expect(session.userMetadata.stagehand).toBe("true");
expect(session.userMetadata.modelName).toBe("gpt-4o");
expect(session.userMetadata.usingCustomClient).toBe("false");
});
});
9 changes: 8 additions & 1 deletion lib/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@ async function getBrowser(
env: "LOCAL" | "BROWSERBASE" = "LOCAL",
headless: boolean = false,
logger: (message: LogLine) => void,
modelName: string,
usingCustomClient: boolean,
browserbaseSessionCreateParams?: Browserbase.Sessions.SessionCreateParams,
browserbaseSessionID?: string,
localBrowserLaunchOptions?: LocalBrowserLaunchOptions,
Expand Down Expand Up @@ -165,6 +167,8 @@ async function getBrowser(
userMetadata: {
...(browserbaseSessionCreateParams?.userMetadata || {}),
stagehand: "true",
modelName: modelName?.replace("/", "_") || "unknown",
usingCustomClient: usingCustomClient.toString(),
},
});

Expand Down Expand Up @@ -403,6 +407,7 @@ export class Stagehand {
private _browser: Browser | undefined;
private _isClosed: boolean = false;
private _history: Array<HistoryEntry> = [];
private _usingCustomClient: boolean;
public get history(): ReadonlyArray<HistoryEntry> {
return Object.freeze([...this._history]);
}
Expand Down Expand Up @@ -557,6 +562,7 @@ export class Stagehand {
// Update logger verbosity level
this.stagehandLogger.setVerbosity(this.verbose);
this.modelName = modelName ?? DEFAULT_MODEL_NAME;
this._usingCustomClient = !modelName;

let modelApiKey: string | undefined;

Expand Down Expand Up @@ -640,7 +646,6 @@ export class Stagehand {
}
this.logInferenceToFile = logInferenceToFile;
this.selfHeal = selfHeal;
this.disablePino = disablePino;
}

private registerSignalHandlers() {
Expand Down Expand Up @@ -739,6 +744,8 @@ export class Stagehand {
this.env,
this.headless,
this.logger,
this._usingCustomClient ? "NO_MODEL_DEFINED" : this.modelName,
Copy link
Contributor

Choose a reason for hiding this comment

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

style: Consider using a constant for 'NO_MODEL_DEFINED' to avoid magic strings

this._usingCustomClient,
this.browserbaseSessionCreateParams,
this.browserbaseSessionID,
this.localBrowserLaunchOptions,
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"module": "./dist/index.js",
"types": "./dist/index.d.ts",
"scripts": {
"example": "pnpm --filter @browserbasehq/stagehand-examples run start",
"example": "pnpm run build && pnpm --filter @browserbasehq/stagehand-examples run start",
"format": "prettier --write .",
"prettier": "prettier --check .",
"prettier:fix": "prettier --write .",
Expand Down
2 changes: 1 addition & 1 deletion stagehand.config.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { ConstructorParams } from "@/dist";
import type { ConstructorParams } from "./dist";
import dotenv from "dotenv";
dotenv.config();

Expand Down