Skip to content
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
2 changes: 1 addition & 1 deletion .release-please-manifest.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
".": "0.2.0"
".": "0.3.0"
}
6 changes: 3 additions & 3 deletions .stats.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
configured_endpoints: 7
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/browserbase%2Fstagehand-705638ac8966569986bd9ebb7c9761bf0016909e9f2753e77ceabb12c8049511.yml
openapi_spec_hash: a8fbbcaa38e91c7f97313620b42d8d62
config_hash: a35b56eb05306a0f02e83c11d57f975f
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/browserbase%2Fstagehand-4fb17cafc413ae3d575e3268602b01d2d0e9ebeb734a41b6086b3353ff0d2523.yml
openapi_spec_hash: 8d48d8564849246f6f14d900c6c5f60c
config_hash: 5c69fb596588b8ace08203858518c149
23 changes: 23 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,28 @@
# Changelog

## 0.3.0 (2025-12-20)

Full Changelog: [v0.2.0...v0.3.0](https://github.com/browserbase/stagehand-java/compare/v0.2.0...v0.3.0)

### Features

* **api:** manual updates ([d9e462c](https://github.com/browserbase/stagehand-java/commit/d9e462c24ed6d3e165a5873e7f70f011d768500a))
* **api:** manual updates ([b6bdf1a](https://github.com/browserbase/stagehand-java/commit/b6bdf1a26a45556dcfee59b088983cd7e7839f43))
* **api:** manual updates ([9b6860a](https://github.com/browserbase/stagehand-java/commit/9b6860a4f60d1a740fbb026eef291e40fb8e1845))
* **api:** manual updates ([28f7978](https://github.com/browserbase/stagehand-java/commit/28f7978e1f040169dbb20aa68efb8e5ceb9a34d2))
* **api:** manual updates ([07db616](https://github.com/browserbase/stagehand-java/commit/07db616b7209716efa346035d65f5d7bf616c992))
* **api:** manual updates ([3cf2073](https://github.com/browserbase/stagehand-java/commit/3cf20739785134610aa7bcbdbce3215c3c3a9970))
* **api:** manual updates ([adace53](https://github.com/browserbase/stagehand-java/commit/adace53fc3e4a0fb4b866172aec98519ec0f29d5))
* **api:** manual updates ([dd65420](https://github.com/browserbase/stagehand-java/commit/dd65420fecb521fba36cbf2a623ce675973a27a0))
* **api:** manual updates ([067c9e6](https://github.com/browserbase/stagehand-java/commit/067c9e644940fa3671665a902bc605b8e358473f))
* **api:** manual updates ([d7aabe3](https://github.com/browserbase/stagehand-java/commit/d7aabe36f42d8344477f2f468bd3ba15837c0516))
* **api:** manual updates ([13074f1](https://github.com/browserbase/stagehand-java/commit/13074f11bbc12057b60e89f37f850ca8f5bc7a83))


### Documentation

* add more examples ([54eba34](https://github.com/browserbase/stagehand-java/commit/54eba3455dbfc5dd61c1c3b88aedd34c56bce37a))

## 0.2.0 (2025-12-16)

Full Changelog: [v0.1.0...v0.2.0](https://github.com/browserbase/stagehand-java/compare/v0.1.0...v0.2.0)
Expand Down
117 changes: 105 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

<!-- x-release-please-start-version -->

[![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.2.0)
[![javadoc](https://javadoc.io/badge2/com.browserbase.api/stagehand-java/0.2.0/javadoc.svg)](https://javadoc.io/doc/com.browserbase.api/stagehand-java/0.2.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.3.0)
[![javadoc](https://javadoc.io/badge2/com.browserbase.api/stagehand-java/0.3.0/javadoc.svg)](https://javadoc.io/doc/com.browserbase.api/stagehand-java/0.3.0)

<!-- x-release-please-end -->

Expand All @@ -13,7 +13,7 @@ It is generated with [Stainless](https://www.stainless.com/).

<!-- x-release-please-start-version -->

The REST API documentation can be found on [docs.stagehand.dev](https://docs.stagehand.dev). Javadocs are available on [javadoc.io](https://javadoc.io/doc/com.browserbase.api/stagehand-java/0.2.0).
The REST API documentation can be found on [docs.stagehand.dev](https://docs.stagehand.dev). Javadocs are available on [javadoc.io](https://javadoc.io/doc/com.browserbase.api/stagehand-java/0.3.0).

<!-- x-release-please-end -->

Expand All @@ -24,7 +24,7 @@ The REST API documentation can be found on [docs.stagehand.dev](https://docs.sta
### Gradle

```kotlin
implementation("com.browserbase.api:stagehand-java:0.2.0")
implementation("com.browserbase.api:stagehand-java:0.3.0")
```

### Maven
Expand All @@ -33,7 +33,7 @@ implementation("com.browserbase.api:stagehand-java:0.2.0")
<dependency>
<groupId>com.browserbase.api</groupId>
<artifactId>stagehand-java</artifactId>
<version>0.2.0</version>
<version>0.3.0</version>
</dependency>
```

Expand All @@ -56,7 +56,7 @@ import com.browserbase.api.models.sessions.SessionActResponse;
StagehandClient client = StagehandOkHttpClient.fromEnv();

SessionActParams params = SessionActParams.builder()
.sessionId("00000000-your-session-id-000000000000")
.id("00000000-your-session-id-000000000000")
.input("click the first link on the page")
.build();
SessionActResponse response = client.sessions().act(params);
Expand Down Expand Up @@ -162,7 +162,7 @@ import java.util.concurrent.CompletableFuture;
StagehandClient client = StagehandOkHttpClient.fromEnv();

SessionActParams params = SessionActParams.builder()
.sessionId("00000000-your-session-id-000000000000")
.id("00000000-your-session-id-000000000000")
.input("click the first link on the page")
.build();
CompletableFuture<SessionActResponse> response = client.async().sessions().act(params);
Expand All @@ -182,14 +182,106 @@ import java.util.concurrent.CompletableFuture;
StagehandClientAsync client = StagehandOkHttpClientAsync.fromEnv();

SessionActParams params = SessionActParams.builder()
.sessionId("00000000-your-session-id-000000000000")
.id("00000000-your-session-id-000000000000")
.input("click the first link on the page")
.build();
CompletableFuture<SessionActResponse> response = client.sessions().act(params);
```

The asynchronous client supports the same options as the synchronous one, except most methods return `CompletableFuture`s.

## Streaming

The SDK defines methods that return response "chunk" streams, where each chunk can be individually processed as soon as it arrives instead of waiting on the full response. Streaming methods generally correspond to [SSE](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events) or [JSONL](https://jsonlines.org) responses.

Some of these methods may have streaming and non-streaming variants, but a streaming method will always have a `Streaming` suffix in its name, even if it doesn't have a non-streaming variant.

These streaming methods return [`StreamResponse`](stagehand-java-core/src/main/kotlin/com/browserbase/api/core/http/StreamResponse.kt) for synchronous clients:

```java
import com.browserbase.api.core.http.StreamResponse;
import com.browserbase.api.models.sessions.StreamEvent;

try (StreamResponse<StreamEvent> streamResponse = client.sessions().actStreaming(params)) {
streamResponse.stream().forEach(chunk -> {
System.out.println(chunk);
});
System.out.println("No more chunks!");
}
```

Or [`AsyncStreamResponse`](stagehand-java-core/src/main/kotlin/com/browserbase/api/core/http/AsyncStreamResponse.kt) for asynchronous clients:

```java
import com.browserbase.api.core.http.AsyncStreamResponse;
import com.browserbase.api.models.sessions.StreamEvent;
import java.util.Optional;

client.async().sessions().actStreaming(params).subscribe(chunk -> {
System.out.println(chunk);
});

// If you need to handle errors or completion of the stream
client.async().sessions().actStreaming(params).subscribe(new AsyncStreamResponse.Handler<>() {
@Override
public void onNext(StreamEvent chunk) {
System.out.println(chunk);
}

@Override
public void onComplete(Optional<Throwable> error) {
if (error.isPresent()) {
System.out.println("Something went wrong!");
throw new RuntimeException(error.get());
} else {
System.out.println("No more chunks!");
}
}
});

// Or use futures
client.async().sessions().actStreaming(params)
.subscribe(chunk -> {
System.out.println(chunk);
})
.onCompleteFuture();
.whenComplete((unused, error) -> {
if (error != null) {
System.out.println("Something went wrong!");
throw new RuntimeException(error);
} else {
System.out.println("No more chunks!");
}
});
```

Async streaming uses a dedicated per-client cached thread pool [`Executor`](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/Executor.html) to stream without blocking the current thread. This default is suitable for most purposes.

To use a different `Executor`, configure the subscription using the `executor` parameter:

```java
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;

Executor executor = Executors.newFixedThreadPool(4);
client.async().sessions().actStreaming(params).subscribe(
chunk -> System.out.println(chunk), executor
);
```

Or configure the client globally using the `streamHandlerExecutor` method:

```java
import com.browserbase.api.client.StagehandClient;
import com.browserbase.api.client.okhttp.StagehandOkHttpClient;
import java.util.concurrent.Executors;

StagehandClient client = StagehandOkHttpClient.builder()
.fromEnv()
.streamHandlerExecutor(Executors.newFixedThreadPool(4))
.build();
```

## Raw responses

The SDK defines methods that deserialize responses into instances of Java classes. However, these methods don't provide access to the response headers, status code, or the raw response body.
Expand All @@ -203,8 +295,7 @@ import com.browserbase.api.models.sessions.SessionStartParams;
import com.browserbase.api.models.sessions.SessionStartResponse;

SessionStartParams params = SessionStartParams.builder()
.browserbaseApiKey("your Browserbase API key")
.browserbaseProjectId("your Browserbase Project ID")
.modelName("openai/gpt-5-nano")
.build();
HttpResponseFor<SessionStartResponse> response = client.sessions().withRawResponse().start(params);

Expand Down Expand Up @@ -237,6 +328,8 @@ The SDK throws custom unchecked exception types:
| 5xx | [`InternalServerException`](stagehand-java-core/src/main/kotlin/com/browserbase/api/errors/InternalServerException.kt) |
| others | [`UnexpectedStatusCodeException`](stagehand-java-core/src/main/kotlin/com/browserbase/api/errors/UnexpectedStatusCodeException.kt) |

[`SseException`](stagehand-java-core/src/main/kotlin/com/browserbase/api/errors/SseException.kt) is thrown for errors encountered during [SSE streaming](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events) after a successful initial HTTP response.

- [`StagehandIoException`](stagehand-java-core/src/main/kotlin/com/browserbase/api/errors/StagehandIoException.kt): I/O networking errors.

- [`StagehandRetryableException`](stagehand-java-core/src/main/kotlin/com/browserbase/api/errors/StagehandRetryableException.kt): Generic error indicating a failure that could be retried by the client.
Expand Down Expand Up @@ -505,8 +598,8 @@ import com.browserbase.api.core.JsonMissing;
import com.browserbase.api.models.sessions.SessionActParams;

SessionActParams params = SessionActParams.builder()
.input("click the sign in button")
.sessionId(JsonMissing.of())
.input("Click the login button")
.id(JsonMissing.of())
.build();
```

Expand Down
2 changes: 1 addition & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ repositories {

allprojects {
group = "com.browserbase.api"
version = "0.2.0" // x-release-please-version
version = "0.3.0" // x-release-please-version
}

subprojects {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import com.browserbase.api.client.StagehandClientImpl
import com.browserbase.api.core.ClientOptions
import com.browserbase.api.core.Sleeper
import com.browserbase.api.core.Timeout
import com.browserbase.api.core.http.AsyncStreamResponse
import com.browserbase.api.core.http.Headers
import com.browserbase.api.core.http.HttpClient
import com.browserbase.api.core.http.QueryParams
Expand All @@ -16,6 +17,7 @@ import java.net.Proxy
import java.time.Clock
import java.time.Duration
import java.util.Optional
import java.util.concurrent.Executor
import javax.net.ssl.HostnameVerifier
import javax.net.ssl.SSLSocketFactory
import javax.net.ssl.X509TrustManager
Expand Down Expand Up @@ -121,6 +123,17 @@ class StagehandOkHttpClient private constructor() {
*/
fun jsonMapper(jsonMapper: JsonMapper) = apply { clientOptions.jsonMapper(jsonMapper) }

/**
* The executor to use for running [AsyncStreamResponse.Handler] callbacks.
*
* Defaults to a dedicated cached thread pool.
*
* This class takes ownership of the executor and shuts it down, if possible, when closed.
*/
fun streamHandlerExecutor(streamHandlerExecutor: Executor) = apply {
clientOptions.streamHandlerExecutor(streamHandlerExecutor)
}

/**
* The interface to use for delaying execution, like during retries.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import com.browserbase.api.client.StagehandClientAsyncImpl
import com.browserbase.api.core.ClientOptions
import com.browserbase.api.core.Sleeper
import com.browserbase.api.core.Timeout
import com.browserbase.api.core.http.AsyncStreamResponse
import com.browserbase.api.core.http.Headers
import com.browserbase.api.core.http.HttpClient
import com.browserbase.api.core.http.QueryParams
Expand All @@ -16,6 +17,7 @@ import java.net.Proxy
import java.time.Clock
import java.time.Duration
import java.util.Optional
import java.util.concurrent.Executor
import javax.net.ssl.HostnameVerifier
import javax.net.ssl.SSLSocketFactory
import javax.net.ssl.X509TrustManager
Expand Down Expand Up @@ -121,6 +123,17 @@ class StagehandOkHttpClientAsync private constructor() {
*/
fun jsonMapper(jsonMapper: JsonMapper) = apply { clientOptions.jsonMapper(jsonMapper) }

/**
* The executor to use for running [AsyncStreamResponse.Handler] callbacks.
*
* Defaults to a dedicated cached thread pool.
*
* This class takes ownership of the executor and shuts it down, if possible, when closed.
*/
fun streamHandlerExecutor(streamHandlerExecutor: Executor) = apply {
clientOptions.streamHandlerExecutor(streamHandlerExecutor)
}

/**
* The interface to use for delaying execution, like during retries.
*
Expand Down
Loading
Loading