Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
f94c8c9
chore(internal): codegen related update
stainless-app[bot] Mar 6, 2026
3bf036a
chore(internal): bump palantir-java-format
stainless-app[bot] Mar 6, 2026
4a1399c
chore(ci): skip uploading artifacts on stainless-internal branches
stainless-app[bot] Mar 7, 2026
5a9506d
feat: Add missing cdpHeaders field to v3 server openapi spec
stainless-app[bot] Mar 9, 2026
b276ce1
codegen metadata
stainless-app[bot] Mar 10, 2026
76ea3fc
fix(client): incorrect `Retry-After` parsing
stainless-app[bot] Mar 11, 2026
1d88e38
chore(internal): tweak CI branches
stainless-app[bot] Mar 17, 2026
53bdc6b
chore(internal): update retry delay tests
stainless-app[bot] Mar 18, 2026
173adb9
fix(client): allow updating header/query affecting fields in `toBuild…
stainless-app[bot] Mar 18, 2026
72fa653
feat: [STG-1607] Yield finished SSE event instead of silently droppin…
stainless-app[bot] Mar 18, 2026
f404196
feat: Revert broken finished SSE yield config
stainless-app[bot] Mar 19, 2026
d6758da
chore(internal): bump ktfmt
stainless-app[bot] Mar 20, 2026
b10e2ad
feat: variables for observe
stainless-app[bot] Mar 23, 2026
690533c
chore(internal): update gitignore
stainless-app[bot] Mar 24, 2026
6f7efad
feat: Add explicit SSE event names for local v3 streaming
stainless-app[bot] Mar 24, 2026
dbf7424
feat: Include LLM headers in ModelConfig
stainless-app[bot] Mar 24, 2026
db9534f
chore(ci): skip lint on metadata-only changes
stainless-app[bot] Mar 25, 2026
eb1fe8b
release: 3.18.0
stainless-app[bot] Mar 25, 2026
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
26 changes: 16 additions & 10 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
name: CI
on:
push:
branches-ignore:
- 'generated'
- 'codegen/**'
- 'integrated/**'
- 'stl-preview-head/**'
- 'stl-preview-base/**'
branches:
- '**'
- '!integrated/**'
- '!stl-preview-head/**'
- '!stl-preview-base/**'
- '!generated'
- '!codegen/**'
- 'codegen/stl/**'
pull_request:
branches-ignore:
- 'stl-preview-head/**'
Expand All @@ -17,7 +19,7 @@ jobs:
timeout-minutes: 15
name: lint
runs-on: ${{ github.repository == 'stainless-sdks/stagehand-java' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }}
if: github.event_name == 'push' || github.event.pull_request.head.repo.fork
if: (github.event_name == 'push' || github.event.pull_request.head.repo.fork) && (github.event_name != 'push' || github.event.head_commit.message != 'codegen metadata')

steps:
- uses: actions/checkout@v6
Expand All @@ -44,7 +46,7 @@ jobs:
contents: read
id-token: write
runs-on: ${{ github.repository == 'stainless-sdks/stagehand-java' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }}
if: github.event_name == 'push' || github.event.pull_request.head.repo.fork
if: (github.event_name == 'push' || github.event.pull_request.head.repo.fork) && (github.event_name != 'push' || github.event.head_commit.message != 'codegen metadata')

steps:
- uses: actions/checkout@v6
Expand All @@ -65,14 +67,18 @@ jobs:
run: ./scripts/build

- name: Get GitHub OIDC Token
if: github.repository == 'stainless-sdks/stagehand-java'
if: |-
github.repository == 'stainless-sdks/stagehand-java' &&
!startsWith(github.ref, 'refs/heads/stl/')
id: github-oidc
uses: actions/github-script@v8
with:
script: core.setOutput('github_token', await core.getIDToken());

- name: Build and upload Maven artifacts
if: github.repository == 'stainless-sdks/stagehand-java'
if: |-
github.repository == 'stainless-sdks/stagehand-java' &&
!startsWith(github.ref, 'refs/heads/stl/')
env:
URL: https://pkg.stainless.com/s
AUTH: ${{ steps.github-oidc.outputs.github_token }}
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
.prism.log
.stdy.log
.gradle
.idea
.kotlin
Expand Down
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.7.1"
".": "3.18.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: 8
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/browserbase%2Fstagehand-a4e672f457dd99336f4b2a113fd7c7c6c9db0941b38d57cff6e3641549a6c4ed.yml
openapi_spec_hash: eae9c8561e420db8e4d238c1e59617fb
config_hash: 2a565ad6662259a2e90fa5f1f5095525
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/browserbase%2Fstagehand-bc309fd00fe0507f4cbe3bc77fa27d0fbffeaa6e71998778da34de42608a67e8.yml
openapi_spec_hash: 1db1af5c1b068bba1d652102f4454668
config_hash: d6c6f623d03971bdba921650e5eb7e5f
31 changes: 31 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,36 @@
# Changelog

## 3.18.0 (2026-03-25)

Full Changelog: [v0.7.1...v3.18.0](https://github.com/browserbase/stagehand-java/compare/v0.7.1...v3.18.0)

### Features

* [STG-1607] Yield finished SSE event instead of silently dropping it ([72fa653](https://github.com/browserbase/stagehand-java/commit/72fa6531d9996c0653fa610b5b05e8027c3a450b))
* Add explicit SSE event names for local v3 streaming ([6f7efad](https://github.com/browserbase/stagehand-java/commit/6f7efad3e19a4fdb911b2c478afb02ad2b63f8e9))
* Add missing cdpHeaders field to v3 server openapi spec ([5a9506d](https://github.com/browserbase/stagehand-java/commit/5a9506d5dfeb1ae172834941aad3bbd9e96f2973))
* Include LLM headers in ModelConfig ([dbf7424](https://github.com/browserbase/stagehand-java/commit/dbf74248557129e0e82067e7ce44bcbc4813174c))
* Revert broken finished SSE yield config ([f404196](https://github.com/browserbase/stagehand-java/commit/f4041968aefba0e64380ca1d14ff20e5f93f9494))
* variables for observe ([b10e2ad](https://github.com/browserbase/stagehand-java/commit/b10e2ad429ebac12464ac332eb32c2d11035c1ff))


### Bug Fixes

* **client:** allow updating header/query affecting fields in `toBuilder()` ([173adb9](https://github.com/browserbase/stagehand-java/commit/173adb9d14281cf3cb1eccedd850f5da1f95f41f))
* **client:** incorrect `Retry-After` parsing ([76ea3fc](https://github.com/browserbase/stagehand-java/commit/76ea3fc583bfe9ca7295856db85378b44d765b0f))


### Chores

* **ci:** skip lint on metadata-only changes ([db9534f](https://github.com/browserbase/stagehand-java/commit/db9534f195b6045ad9679b08243c36d55340569b))
* **ci:** skip uploading artifacts on stainless-internal branches ([4a1399c](https://github.com/browserbase/stagehand-java/commit/4a1399c7a535d9bf8934e9d142878e57a1537b8d))
* **internal:** bump ktfmt ([d6758da](https://github.com/browserbase/stagehand-java/commit/d6758da0fe85d048b4f8fcd740be7c37901bb253))
* **internal:** bump palantir-java-format ([3bf036a](https://github.com/browserbase/stagehand-java/commit/3bf036aed5ba8fb90fe4bf5bc6b62a49f09f7dcc))
* **internal:** codegen related update ([f94c8c9](https://github.com/browserbase/stagehand-java/commit/f94c8c9a86af4592fba5c42645ccc1099a8ab1fe))
* **internal:** tweak CI branches ([1d88e38](https://github.com/browserbase/stagehand-java/commit/1d88e3802216d33841d3595d3d9fa024189dfc28))
* **internal:** update gitignore ([690533c](https://github.com/browserbase/stagehand-java/commit/690533ceee3c5d482a17d67c36a7bceb62a63ec2))
* **internal:** update retry delay tests ([53bdc6b](https://github.com/browserbase/stagehand-java/commit/53bdc6ba4804aca38996fe28d5eeff412a10d189))

## 0.7.1 (2026-03-04)

Full Changelog: [v0.7.0...v0.7.1](https://github.com/browserbase/stagehand-java/compare/v0.7.0...v0.7.1)
Expand Down
8 changes: 4 additions & 4 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.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)
[![Maven Central](https://img.shields.io/maven-central/v/com.browserbase.api/stagehand-java)](https://central.sonatype.com/artifact/com.browserbase.api/stagehand-java/3.18.0)
[![javadoc](https://javadoc.io/badge2/com.browserbase.api/stagehand-java/3.18.0/javadoc.svg)](https://javadoc.io/doc/com.browserbase.api/stagehand-java/3.18.0)

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

Expand Down Expand Up @@ -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.1")
implementation("com.browserbase.api:stagehand-java:3.18.0")
```

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

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

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

subprojects {
Expand Down
2 changes: 1 addition & 1 deletion buildSrc/src/main/kotlin/stagehand.java.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ tasks.withType<Test>().configureEach {

val palantir by configurations.creating
dependencies {
palantir("com.palantir.javaformat:palantir-java-format:2.73.0")
palantir("com.palantir.javaformat:palantir-java-format:2.89.0")
}

fun registerPalantir(
Expand Down
2 changes: 1 addition & 1 deletion buildSrc/src/main/kotlin/stagehand.kotlin.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ tasks.withType<Test>().configureEach {

val ktfmt by configurations.creating
dependencies {
ktfmt("com.facebook:ktfmt:0.56")
ktfmt("com.facebook:ktfmt:0.61")
}

fun registerKtfmt(
Expand Down
6 changes: 3 additions & 3 deletions scripts/fast-format
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ if [ ! -f "$FILE_LIST" ]; then
exit 1
fi

if ! command -v ktfmt-fast-format &> /dev/null; then
echo "Error: ktfmt-fast-format not found"
if ! command -v ktfmt &> /dev/null; then
echo "Error: ktfmt not found"
exit 1
fi

Expand All @@ -36,7 +36,7 @@ echo "==> Done looking for Kotlin files"

if [[ -n "$kt_files" ]]; then
echo "==> will format Kotlin files"
echo "$kt_files" | tr '\n' '\0' | xargs -0 ktfmt-fast-format --kotlinlang-style "$@"
echo "$kt_files" | tr '\n' '\0' | xargs -0 ktfmt --kotlinlang-style "$@"
else
echo "No Kotlin files to format -- expected outcome during incremental formatting"
fi
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -485,23 +485,24 @@ private constructor(
headers.put("X-Stainless-Runtime", "JRE")
headers.put("X-Stainless-Runtime-Version", getJavaVersion())
headers.put("X-Stainless-Kotlin-Version", KotlinVersion.CURRENT.toString())
// We replace after all the default headers to allow end-users to overwrite them.
headers.replaceAll(this.headers.build())
queryParams.replaceAll(this.queryParams.build())
browserbaseApiKey.let {
if (!it.isEmpty()) {
headers.put("x-bb-api-key", it)
headers.replace("x-bb-api-key", it)
}
}
browserbaseProjectId.let {
if (!it.isEmpty()) {
headers.put("x-bb-project-id", it)
headers.replace("x-bb-project-id", it)
}
}
modelApiKey.let {
if (!it.isEmpty()) {
headers.put("x-model-api-key", it)
headers.replace("x-model-api-key", it)
}
}
headers.replaceAll(this.headers.build())
queryParams.replaceAll(this.queryParams.build())

return ClientOptions(
httpClient,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,23 +18,11 @@ import com.fasterxml.jackson.module.kotlin.jacksonTypeRef
internal fun sseHandler(jsonMapper: JsonMapper): Handler<StreamResponse<SseMessage>> =
streamHandler { response, lines ->
val state = SseState(jsonMapper)
var done = false
for (line in lines) {
// Stop emitting messages, but iterate through the full stream.
if (done) {
continue
}

val message = state.decode(line) ?: continue

when {
message.data.startsWith("{\"data\":{\"status\":\"finished\"") -> {
// In this case we don't break because we still want to iterate through the full
// stream.
done = true
continue
}
message.data.startsWith("error") -> {
when (message.event) {
"error" -> {
throw SseException.builder()
.statusCode(response.statusCode())
.headers(response.headers())
Expand All @@ -47,10 +35,10 @@ internal fun sseHandler(jsonMapper: JsonMapper): Handler<StreamResponse<SseMessa
)
.build()
}
}

if (message.event == null) {
yield(message)
"starting",
"connected",
"running",
"finished" -> yield(message)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ private constructor(
?: headers.values("Retry-After").getOrNull(0)?.let { retryAfter ->
retryAfter.toFloatOrNull()?.times(TimeUnit.SECONDS.toNanos(1))
?: try {
ChronoUnit.MILLIS.between(
ChronoUnit.NANOS.between(
OffsetDateTime.now(clock),
OffsetDateTime.parse(
retryAfter,
Expand All @@ -214,13 +214,8 @@ private constructor(
}
}
?.let { retryAfterNanos ->
// If the API asks us to wait a certain amount of time (and it's a reasonable
// amount), just
// do what it says.
val retryAfter = Duration.ofNanos(retryAfterNanos.toLong())
if (retryAfter in Duration.ofNanos(0)..Duration.ofMinutes(1)) {
return retryAfter
}
// If the API asks us to wait a certain amount of time, do what it says.
return Duration.ofNanos(retryAfterNanos.toLong())
}

// Apply exponential backoff, but not more than the max.
Expand Down
Loading
Loading