From a27e6f69e67575d0c61d0b849ce6415108ad9a8b Mon Sep 17 00:00:00 2001 From: monadoid Date: Thu, 26 Feb 2026 10:57:57 -0700 Subject: [PATCH 1/3] STG-1293: add local server multiregion example --- .../LocalServerMultiregionBrowserExample.java | 152 ++++++++++++++++++ 1 file changed, 152 insertions(+) create mode 100644 stagehand-java-example/src/main/java/com/stagehand/api/example/LocalServerMultiregionBrowserExample.java diff --git a/stagehand-java-example/src/main/java/com/stagehand/api/example/LocalServerMultiregionBrowserExample.java b/stagehand-java-example/src/main/java/com/stagehand/api/example/LocalServerMultiregionBrowserExample.java new file mode 100644 index 0000000..a647507 --- /dev/null +++ b/stagehand-java-example/src/main/java/com/stagehand/api/example/LocalServerMultiregionBrowserExample.java @@ -0,0 +1,152 @@ +package com.stagehand.api.example; + +import com.browserbase.api.client.StagehandClient; +import com.browserbase.api.client.okhttp.StagehandOkHttpClient; +import com.browserbase.api.core.JsonValue; +import com.browserbase.api.core.RequestOptions; +import com.browserbase.api.core.http.StreamResponse; +import com.browserbase.api.models.sessions.ModelConfig; +import com.browserbase.api.models.sessions.SessionActParams; +import com.browserbase.api.models.sessions.SessionEndParams; +import com.browserbase.api.models.sessions.SessionExecuteParams; +import com.browserbase.api.models.sessions.SessionExtractParams; +import com.browserbase.api.models.sessions.SessionNavigateParams; +import com.browserbase.api.models.sessions.SessionObserveParams; +import com.browserbase.api.models.sessions.SessionStartParams; +import com.browserbase.api.models.sessions.SessionStartResponse; +import com.browserbase.api.models.sessions.StreamEvent; +import java.time.Duration; +import java.util.List; +import java.util.Map; + +/** + * Local Stagehand server + multiregion Browserbase example demonstrating SSE streaming. + * + * This example shows the full flow of: + * 1. Starting a Browserbase session in eu-central-1 (via local Stagehand server) + * 2. Navigating to a webpage + * 3. Observing possible actions (streaming) + * 4. Acting on an element (streaming) + * 5. Extracting structured data (streaming) + * 6. Running an autonomous agent (streaming) + * 7. Ending the session + * + * Required environment variables: + * - BROWSERBASE_API_KEY: Your Browserbase API key + * - BROWSERBASE_PROJECT_ID: Your Browserbase project ID + * - MODEL_API_KEY: Your OpenAI API key + * - STAGEHAND_API_URL: Local Stagehand server base URL + */ +public class LocalServerMultiregionBrowserExample { + public static void main(String[] args) { + Env.load(); + StagehandClient client = StagehandOkHttpClient.builder().fromEnv().build(); + + SessionStartResponse startResponse = client.sessions() + .start(SessionStartParams.builder() + .modelName("anthropic/claude-sonnet-4-6") + .browser(SessionStartParams.Browser.builder() + .type(SessionStartParams.Browser.Type.BROWSERBASE) + .build()) + .browserbaseSessionCreateParams(SessionStartParams.BrowserbaseSessionCreateParams.builder() + .projectId(System.getProperty("stagehand.browserbaseProjectId")) + .region(SessionStartParams.BrowserbaseSessionCreateParams.Region.EU_CENTRAL_1) + .build()) + .build()); + + String sessionId = startResponse.data().sessionId(); + System.out.println("Session started: " + sessionId); + + try { + client.sessions() + .navigate(SessionNavigateParams.builder() + .id(sessionId) + .url("https://news.ycombinator.com") + .build()); + System.out.println("Navigated to Hacker News"); + + SessionObserveParams observeParams = SessionObserveParams.builder() + .id(sessionId) + .instruction("find the link to view comments for the top post") + .xStreamResponse(SessionObserveParams.XStreamResponse.TRUE) + .build(); + try (StreamResponse observeStream = client.sessions().observeStreaming(observeParams)) { + printStreamEvents("observe", observeStream); + } + + SessionActParams actParams = SessionActParams.builder() + .id(sessionId) + .input("Click the comments link for the top post") + .xStreamResponse(SessionActParams.XStreamResponse.TRUE) + .build(); + try (StreamResponse actStream = client.sessions().actStreaming(actParams)) { + printStreamEvents("act", actStream); + } + + SessionExtractParams extractParams = SessionExtractParams.builder() + .id(sessionId) + .instruction("extract the text of the top comment on this page") + .schema(SessionExtractParams.Schema.builder() + .putAdditionalProperty("type", JsonValue.from("object")) + .putAdditionalProperty( + "properties", + JsonValue.from(Map.of( + "commentText", + Map.of( + "type", + "string", + "description", + "The text content of the top comment"), + "author", + Map.of( + "type", + "string", + "description", + "The username of the comment author")))) + .putAdditionalProperty("required", JsonValue.from(List.of("commentText"))) + .build()) + .xStreamResponse(SessionExtractParams.XStreamResponse.TRUE) + .build(); + try (StreamResponse extractStream = client.sessions().extractStreaming(extractParams)) { + printStreamEvents("extract", extractStream); + } + + SessionExecuteParams executeParams = SessionExecuteParams.builder() + .id(sessionId) + .executeOptions(SessionExecuteParams.ExecuteOptions.builder() + .instruction( + "Find any personal website, GitHub, LinkedIn, or other best profile URL for the" + + " top comment author on this page. Click on the username to go to their" + + " profile page and look for any links they have shared. Use Google Search" + + " with their username or other details from their profile if you don't find" + + " any direct links.") + .maxSteps(15.0) + .build()) + .agentConfig(SessionExecuteParams.AgentConfig.builder() + .model(ModelConfig.builder() + .modelName("anthropic/claude-opus-4-6") + .apiKey(System.getProperty("stagehand.modelApiKey")) + .build()) + .cua(false) + .build()) + .xStreamResponse(SessionExecuteParams.XStreamResponse.TRUE) + .build(); + try (StreamResponse executeStream = client.sessions() + .executeStreaming( + executeParams, + RequestOptions.builder() + .timeout(Duration.ofMinutes(5)) + .build())) { + printStreamEvents("execute", executeStream); + } + } finally { + client.sessions().end(SessionEndParams.builder().id(sessionId).build()); + System.out.println("Session ended"); + } + } + + private static void printStreamEvents(String label, StreamResponse stream) { + stream.stream().forEach(event -> System.out.println("[" + label + "] " + event.type() + " " + event.data())); + System.out.println("[" + label + "] stream complete"); + } +} From 6a0462ae75409f7c945a39903337e4a14ce74d28 Mon Sep 17 00:00:00 2001 From: monadoid Date: Thu, 26 Feb 2026 11:13:52 -0700 Subject: [PATCH 2/3] STG-1293: document multiregion example --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index ef8257a..998c280 100644 --- a/README.md +++ b/README.md @@ -111,6 +111,8 @@ Examples live at: - `stagehand-java-example/src/main/java/com/stagehand/api/example/RemoteBrowserPlaywrightExample.java` - `stagehand-java-example/src/main/java/com/stagehand/api/example/LocalBrowserPlaywrightExample.java` +Multiregion support: see `stagehand-java-example/src/main/java/com/stagehand/api/example/LocalServerMultiregionBrowserExample.java`. + Set your environment variables (from `examples/.env.example`): - `STAGEHAND_API_URL` From eab6c3de169e7774747cb1469586c6413202d28d Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 26 Feb 2026 19:55:49 +0000 Subject: [PATCH 3/3] release: 0.7.1 --- .release-please-manifest.json | 2 +- CHANGELOG.md | 4 ++++ README.md | 8 ++++---- build.gradle.kts | 2 +- 4 files changed, 10 insertions(+), 6 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 1b77f50..1bc5713 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.7.0" + ".": "0.7.1" } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 44a3c93..6e22e1b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## 0.7.1 (2026-02-26) + +Full Changelog: [v0.7.0...v0.7.1](https://github.com/browserbase/stagehand-java/compare/v0.7.0...v0.7.1) + ## 0.7.0 (2026-02-25) Full Changelog: [v0.6.1...v0.7.0](https://github.com/browserbase/stagehand-java/compare/v0.6.1...v0.7.0) diff --git a/README.md b/README.md index 998c280..e6a636f 100644 --- a/README.md +++ b/README.md @@ -2,8 +2,8 @@ -[![Maven Central](https://img.shields.io/maven-central/v/com.browserbase.api/stagehand-java)](https://central.sonatype.com/artifact/com.browserbase.api/stagehand-java/0.7.0) -[![javadoc](https://javadoc.io/badge2/com.browserbase.api/stagehand-java/0.7.0/javadoc.svg)](https://javadoc.io/doc/com.browserbase.api/stagehand-java/0.7.0) +[![Maven Central](https://img.shields.io/maven-central/v/com.browserbase.api/stagehand-java)](https://central.sonatype.com/artifact/com.browserbase.api/stagehand-java/0.7.1) +[![javadoc](https://javadoc.io/badge2/com.browserbase.api/stagehand-java/0.7.1/javadoc.svg)](https://javadoc.io/doc/com.browserbase.api/stagehand-java/0.7.1) @@ -85,7 +85,7 @@ Most existing browser automation tools either require you to write low-level cod ### Gradle ```kotlin -implementation("com.browserbase.api:stagehand-java:0.7.0") +implementation("com.browserbase.api:stagehand-java:0.7.1") ``` ### Maven @@ -94,7 +94,7 @@ implementation("com.browserbase.api:stagehand-java:0.7.0") com.browserbase.api stagehand-java - 0.7.0 + 0.7.1 ``` diff --git a/build.gradle.kts b/build.gradle.kts index f240422..79fb854 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -8,7 +8,7 @@ repositories { allprojects { group = "com.browserbase.api" - version = "0.7.0" // x-release-please-version + version = "0.7.1" // x-release-please-version } subprojects {