diff --git a/.release-please-manifest.json b/.release-please-manifest.json
index 10f3091..6b7b74c 100644
--- a/.release-please-manifest.json
+++ b/.release-please-manifest.json
@@ -1,3 +1,3 @@
{
- ".": "0.2.0"
+ ".": "0.3.0"
}
\ No newline at end of file
diff --git a/.stats.yml b/.stats.yml
index 2790605..d90df61 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 7
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/browserbase%2Fstagehand-e6a9dca1a93568e403ac72128d86f30c8c3f1336d4b67017d7e61b1836f10f47.yml
-openapi_spec_hash: ef01e0649bb0e283df0aa81c369649df
-config_hash: 88e87ba7021be93d267ecfc8f5e6b891
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/browserbase%2Fstagehand-4fb17cafc413ae3d575e3268602b01d2d0e9ebeb734a41b6086b3353ff0d2523.yml
+openapi_spec_hash: 8d48d8564849246f6f14d900c6c5f60c
+config_hash: 5c69fb596588b8ace08203858518c149
diff --git a/CHANGELOG.md b/CHANGELOG.md
index a77936c..13da95d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,30 @@
# Changelog
+## 0.3.0 (2025-12-20)
+
+Full Changelog: [v0.2.0...v0.3.0](https://github.com/browserbase/stagehand-kotlin/compare/v0.2.0...v0.3.0)
+
+### Features
+
+* **api:** manual updates ([e4a62fb](https://github.com/browserbase/stagehand-kotlin/commit/e4a62fb0ab12733c844757cbe8ab9894f6c8c8a1))
+* **api:** manual updates ([9480988](https://github.com/browserbase/stagehand-kotlin/commit/9480988b36974e37584a16a2173af3072840d4b8))
+* **api:** manual updates ([d0d4e1b](https://github.com/browserbase/stagehand-kotlin/commit/d0d4e1b22d4fa7a4ea49333800a4c5137659f5e6))
+* **api:** manual updates ([e631708](https://github.com/browserbase/stagehand-kotlin/commit/e63170897295bc07dc47d493573c1290eb26e5f1))
+* **api:** manual updates ([1697e14](https://github.com/browserbase/stagehand-kotlin/commit/1697e144099d3d39c43d1b2ad6ab830e9c4267da))
+
+
+### Chores
+
+* **internal:** codegen related update ([c6b00cb](https://github.com/browserbase/stagehand-kotlin/commit/c6b00cb1704aee4abf1aade497aed8270e250edc))
+* **internal:** codegen related update ([3b4a6f0](https://github.com/browserbase/stagehand-kotlin/commit/3b4a6f0749d57d3a817722988351a2899dca5199))
+* **internal:** codegen related update ([5531737](https://github.com/browserbase/stagehand-kotlin/commit/55317375b13e137f0ae5ebd5fcc05f1393bdf633))
+* **internal:** codegen related update ([842e54f](https://github.com/browserbase/stagehand-kotlin/commit/842e54f32d89d64633746138a28a1947c2f7aaf4))
+
+
+### Documentation
+
+* add more examples ([16aa06e](https://github.com/browserbase/stagehand-kotlin/commit/16aa06e0a826df71165130395e41f6fad0a4f708))
+
## 0.2.0 (2025-12-17)
Full Changelog: [v0.1.0...v0.2.0](https://github.com/browserbase/stagehand-kotlin/compare/v0.1.0...v0.2.0)
diff --git a/README.md b/README.md
index a4eea7e..edd7eaf 100644
--- a/README.md
+++ b/README.md
@@ -2,8 +2,8 @@
-[](https://central.sonatype.com/artifact/com.browserbase.api/stagehand-kotlin/0.2.0)
-[](https://javadoc.io/doc/com.browserbase.api/stagehand-kotlin/0.2.0)
+[](https://central.sonatype.com/artifact/com.browserbase.api/stagehand-kotlin/0.3.0)
+[](https://javadoc.io/doc/com.browserbase.api/stagehand-kotlin/0.3.0)
@@ -13,7 +13,7 @@ It is generated with [Stainless](https://www.stainless.com/).
-The REST API documentation can be found on [docs.stagehand.dev](https://docs.stagehand.dev). KDocs are available on [javadoc.io](https://javadoc.io/doc/com.browserbase.api/stagehand-kotlin/0.2.0).
+The REST API documentation can be found on [docs.stagehand.dev](https://docs.stagehand.dev). KDocs are available on [javadoc.io](https://javadoc.io/doc/com.browserbase.api/stagehand-kotlin/0.3.0).
@@ -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-kotlin:0.2.0")
+implementation("com.browserbase.api:stagehand-kotlin:0.3.0")
```
### Maven
@@ -33,7 +33,7 @@ implementation("com.browserbase.api:stagehand-kotlin:0.2.0")
com.browserbase.api
stagehand-kotlin
- 0.2.0
+ 0.3.0
```
@@ -188,6 +188,21 @@ val response: SessionActResponse = client.sessions().act(params)
The asynchronous client supports the same options as the synchronous one, except most methods are [suspending](https://kotlinlang.org/docs/coroutines-guide.html).
+## 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-kotlin-core/src/main/kotlin/com/browserbase/api/core/http/StreamResponse.kt) for synchronous clients:
+
+```kotlin
+client.sessions().actStreaming(params).use { response ->
+ response.asSequence().forEach { println(it) }
+ println("No more chunks!")
+}
+```
+
## Raw responses
The SDK defines methods that deserialize responses into instances of Kotlin classes. However, these methods don't provide access to the response headers, status code, or the raw response body.
@@ -234,6 +249,8 @@ The SDK throws custom unchecked exception types:
| 5xx | [`InternalServerException`](stagehand-kotlin-core/src/main/kotlin/com/browserbase/api/errors/InternalServerException.kt) |
| others | [`UnexpectedStatusCodeException`](stagehand-kotlin-core/src/main/kotlin/com/browserbase/api/errors/UnexpectedStatusCodeException.kt) |
+ [`SseException`](stagehand-kotlin-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-kotlin-core/src/main/kotlin/com/browserbase/api/errors/StagehandIoException.kt): I/O networking errors.
- [`StagehandRetryableException`](stagehand-kotlin-core/src/main/kotlin/com/browserbase/api/errors/StagehandRetryableException.kt): Generic error indicating a failure that could be retried by the client.
diff --git a/build.gradle.kts b/build.gradle.kts
index b5a0b67..0f0fb80 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -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 {
diff --git a/buildSrc/src/main/kotlin/stagehand.publish.gradle.kts b/buildSrc/src/main/kotlin/stagehand.publish.gradle.kts
index f1d4d88..d6f4029 100644
--- a/buildSrc/src/main/kotlin/stagehand.publish.gradle.kts
+++ b/buildSrc/src/main/kotlin/stagehand.publish.gradle.kts
@@ -10,7 +10,7 @@ configure {
pom {
name.set("Stagehand API")
- description.set("Stagehand SDK for AI browser automation [ALPHA].")
+ description.set("Stagehand SDK for AI browser automation [ALPHA]. This API allows clients to\nexecute browser automation tasks remotely on the Browserbase cloud.\n\nAll endpoints except /sessions/start require an active session ID. Responses are\nstreamed using Server-Sent Events (SSE) when the `x-stream-response: true`\nheader is provided.\n\nThis SDK is currently ALPHA software and is not production ready! Please try it\nand give us your feedback, stay tuned for upcoming release announcements!")
url.set("https://docs.stagehand.dev")
licenses {
diff --git a/stagehand-kotlin-core/src/main/kotlin/com/browserbase/api/core/handlers/SseHandler.kt b/stagehand-kotlin-core/src/main/kotlin/com/browserbase/api/core/handlers/SseHandler.kt
new file mode 100644
index 0000000..b4bbf80
--- /dev/null
+++ b/stagehand-kotlin-core/src/main/kotlin/com/browserbase/api/core/handlers/SseHandler.kt
@@ -0,0 +1,133 @@
+// File generated from our OpenAPI spec by Stainless.
+
+package com.browserbase.api.core.handlers
+
+import com.browserbase.api.core.JsonMissing
+import com.browserbase.api.core.http.HttpResponse
+import com.browserbase.api.core.http.HttpResponse.Handler
+import com.browserbase.api.core.http.SseMessage
+import com.browserbase.api.core.http.StreamResponse
+import com.browserbase.api.core.http.map
+import com.browserbase.api.errors.SseException
+import com.fasterxml.jackson.databind.json.JsonMapper
+import com.fasterxml.jackson.module.kotlin.jacksonTypeRef
+
+internal fun sseHandler(jsonMapper: JsonMapper): Handler> =
+ 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("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") -> {
+ throw SseException.builder()
+ .statusCode(response.statusCode())
+ .headers(response.headers())
+ .body(
+ try {
+ jsonMapper.readValue(message.data, jacksonTypeRef())
+ } catch (e: Exception) {
+ JsonMissing.of()
+ }
+ )
+ .build()
+ }
+ }
+
+ if (message.event == null) {
+ yield(message)
+ }
+ }
+ }
+
+private class SseState(
+ val jsonMapper: JsonMapper,
+ var event: String? = null,
+ val data: MutableList = mutableListOf(),
+ var lastId: String? = null,
+ var retry: Int? = null,
+) {
+ // https://html.spec.whatwg.org/multipage/server-sent-events.html#event-stream-interpretation
+ fun decode(line: String): SseMessage? {
+ if (line.isEmpty()) {
+ return flush()
+ }
+
+ if (line.startsWith(':')) {
+ return null
+ }
+
+ val fieldName: String
+ var value: String
+
+ val colonIndex = line.indexOf(':')
+ if (colonIndex == -1) {
+ fieldName = line
+ value = ""
+ } else {
+ fieldName = line.substring(0, colonIndex)
+ value = line.substring(colonIndex + 1)
+ }
+
+ if (value.startsWith(' ')) {
+ value = value.substring(1)
+ }
+
+ when (fieldName) {
+ "event" -> event = value
+ "data" -> data.add(value)
+ "id" -> {
+ if (!value.contains('\u0000')) {
+ lastId = value
+ }
+ }
+ "retry" -> value.toIntOrNull()?.let { retry = it }
+ }
+
+ return null
+ }
+
+ private fun flush(): SseMessage? {
+ if (isEmpty()) {
+ return null
+ }
+
+ val message =
+ SseMessage.builder()
+ .jsonMapper(jsonMapper)
+ .event(event)
+ .data(data.joinToString("\n"))
+ .id(lastId)
+ .retry(retry)
+ .build()
+
+ // NOTE: Per the SSE spec, do not reset lastId.
+ event = null
+ data.clear()
+ retry = null
+
+ return message
+ }
+
+ private fun isEmpty(): Boolean =
+ event.isNullOrEmpty() && data.isEmpty() && lastId.isNullOrEmpty() && retry == null
+}
+
+internal inline fun Handler>.mapJson():
+ Handler> =
+ object : Handler> {
+ override fun handle(response: HttpResponse): StreamResponse =
+ this@mapJson.handle(response).map { it.json() }
+ }
diff --git a/stagehand-kotlin-core/src/main/kotlin/com/browserbase/api/core/handlers/StreamHandler.kt b/stagehand-kotlin-core/src/main/kotlin/com/browserbase/api/core/handlers/StreamHandler.kt
new file mode 100644
index 0000000..75e8226
--- /dev/null
+++ b/stagehand-kotlin-core/src/main/kotlin/com/browserbase/api/core/handlers/StreamHandler.kt
@@ -0,0 +1,99 @@
+@file:JvmName("StreamHandler")
+
+package com.browserbase.api.core.handlers
+
+import com.browserbase.api.core.http.HttpResponse
+import com.browserbase.api.core.http.HttpResponse.Handler
+import com.browserbase.api.core.http.PhantomReachableClosingStreamResponse
+import com.browserbase.api.core.http.StreamResponse
+import com.browserbase.api.errors.StagehandIoException
+import java.io.IOException
+
+internal fun streamHandler(
+ block: suspend SequenceScope.(response: HttpResponse, lines: Sequence) -> Unit
+): Handler> =
+ object : Handler> {
+
+ override fun handle(response: HttpResponse): StreamResponse {
+ val reader = response.body().bufferedReader()
+ val sequence =
+ // Wrap in a `CloseableSequence` to avoid performing a read on the `reader`
+ // after it has been closed, which would throw an `IOException`.
+ CloseableSequence(
+ sequence {
+ reader.useLines { lines ->
+ block(
+ response,
+ // We wrap the `lines` instead of the top-level sequence because
+ // we only want to catch `IOException` from the reader; not from
+ // the user's own code.
+ IOExceptionWrappingSequence(lines),
+ )
+ }
+ }
+ .constrainOnce()
+ )
+
+ return PhantomReachableClosingStreamResponse(
+ object : StreamResponse {
+
+ override fun asSequence(): Sequence = sequence
+
+ override fun close() {
+ sequence.close()
+ reader.close()
+ response.close()
+ }
+ }
+ )
+ }
+ }
+
+/** A sequence that catches, wraps, and rethrows [IOException] as [StagehandIoException]. */
+private class IOExceptionWrappingSequence(private val sequence: Sequence) : Sequence {
+
+ override fun iterator(): Iterator {
+ val iterator = sequence.iterator()
+ return object : Iterator {
+
+ override fun next(): T =
+ try {
+ iterator.next()
+ } catch (e: IOException) {
+ throw StagehandIoException("Stream failed", e)
+ }
+
+ override fun hasNext(): Boolean =
+ try {
+ iterator.hasNext()
+ } catch (e: IOException) {
+ throw StagehandIoException("Stream failed", e)
+ }
+ }
+ }
+}
+
+/**
+ * A sequence that can be closed.
+ *
+ * Once [close] is called, it will not yield more elements. It will also no longer consult the
+ * underlying [Iterator.hasNext] method.
+ */
+private class CloseableSequence(private val sequence: Sequence) : Sequence {
+
+ private var isClosed: Boolean = false
+
+ override fun iterator(): Iterator {
+ val iterator = sequence.iterator()
+ return object : Iterator {
+
+ override fun next(): T = iterator.next()
+
+ override fun hasNext(): Boolean = !isClosed && iterator.hasNext()
+ }
+ }
+
+ fun close() {
+ isClosed = true
+ }
+}
diff --git a/stagehand-kotlin-core/src/main/kotlin/com/browserbase/api/core/http/SseMessage.kt b/stagehand-kotlin-core/src/main/kotlin/com/browserbase/api/core/http/SseMessage.kt
new file mode 100644
index 0000000..531d5c4
--- /dev/null
+++ b/stagehand-kotlin-core/src/main/kotlin/com/browserbase/api/core/http/SseMessage.kt
@@ -0,0 +1,74 @@
+// File generated from our OpenAPI spec by Stainless.
+
+package com.browserbase.api.core.http
+
+import com.browserbase.api.errors.StagehandInvalidDataException
+import com.fasterxml.jackson.databind.json.JsonMapper
+import com.fasterxml.jackson.module.kotlin.jacksonTypeRef
+import java.util.Objects
+
+internal class SseMessage
+private constructor(
+ val jsonMapper: JsonMapper,
+ val event: String?,
+ val data: String,
+ val id: String?,
+ val retry: Int?,
+) {
+
+ companion object {
+ fun builder() = Builder()
+ }
+
+ class Builder internal constructor() {
+
+ private var jsonMapper: JsonMapper? = null
+ private var event: String? = null
+ private var data: String = ""
+ private var id: String? = null
+ private var retry: Int? = null
+
+ fun jsonMapper(jsonMapper: JsonMapper) = apply { this.jsonMapper = jsonMapper }
+
+ fun event(event: String?) = apply { this.event = event }
+
+ fun data(data: String) = apply { this.data = data }
+
+ fun id(id: String?) = apply { this.id = id }
+
+ fun retry(retry: Int?) = apply { this.retry = retry }
+
+ fun build(): SseMessage = SseMessage(jsonMapper!!, event, data, id, retry)
+ }
+
+ inline fun json(): T =
+ try {
+ jsonMapper.readerFor(jacksonTypeRef()).readValue(jsonNode)
+ } catch (e: Exception) {
+ throw StagehandInvalidDataException("Error reading response", e)
+ }
+
+ private val jsonNode by lazy {
+ try {
+ jsonMapper.readTree(data)
+ } catch (e: Exception) {
+ throw StagehandInvalidDataException("Error reading response", e)
+ }
+ }
+
+ override fun equals(other: Any?): Boolean {
+ if (this === other) {
+ return true
+ }
+
+ return other is SseMessage &&
+ event == other.event &&
+ data == other.data &&
+ id == other.id &&
+ retry == other.retry
+ }
+
+ override fun hashCode(): Int = Objects.hash(event, data, id, retry)
+
+ override fun toString(): String = "SseMessage{event=$event, data=$data, id=$id, retry=$retry}"
+}
diff --git a/stagehand-kotlin-core/src/main/kotlin/com/browserbase/api/errors/SseException.kt b/stagehand-kotlin-core/src/main/kotlin/com/browserbase/api/errors/SseException.kt
new file mode 100644
index 0000000..dfbbdeb
--- /dev/null
+++ b/stagehand-kotlin-core/src/main/kotlin/com/browserbase/api/errors/SseException.kt
@@ -0,0 +1,85 @@
+// File generated from our OpenAPI spec by Stainless.
+
+package com.browserbase.api.errors
+
+import com.browserbase.api.core.JsonValue
+import com.browserbase.api.core.checkRequired
+import com.browserbase.api.core.http.Headers
+
+class SseException
+private constructor(
+ private val statusCode: Int,
+ private val headers: Headers,
+ private val body: JsonValue,
+ cause: Throwable?,
+) : StagehandServiceException("$statusCode: $body", cause) {
+
+ override fun statusCode(): Int = statusCode
+
+ override fun headers(): Headers = headers
+
+ override fun body(): JsonValue = body
+
+ fun toBuilder() = Builder().from(this)
+
+ companion object {
+
+ /**
+ * Returns a mutable builder for constructing an instance of [SseException].
+ *
+ * The following fields are required:
+ * ```kotlin
+ * .statusCode()
+ * .headers()
+ * .body()
+ * ```
+ */
+ fun builder() = Builder()
+ }
+
+ /** A builder for [SseException]. */
+ class Builder internal constructor() {
+
+ private var statusCode: Int? = null
+ private var headers: Headers? = null
+ private var body: JsonValue? = null
+ private var cause: Throwable? = null
+
+ internal fun from(sseException: SseException) = apply {
+ statusCode = sseException.statusCode
+ headers = sseException.headers
+ body = sseException.body
+ cause = sseException.cause
+ }
+
+ fun statusCode(statusCode: Int) = apply { this.statusCode = statusCode }
+
+ fun headers(headers: Headers) = apply { this.headers = headers }
+
+ fun body(body: JsonValue) = apply { this.body = body }
+
+ fun cause(cause: Throwable?) = apply { this.cause = cause }
+
+ /**
+ * Returns an immutable instance of [SseException].
+ *
+ * Further updates to this [Builder] will not mutate the returned instance.
+ *
+ * The following fields are required:
+ * ```kotlin
+ * .statusCode()
+ * .headers()
+ * .body()
+ * ```
+ *
+ * @throws IllegalStateException if any required field is unset.
+ */
+ fun build(): SseException =
+ SseException(
+ checkRequired("statusCode", statusCode),
+ checkRequired("headers", headers),
+ checkRequired("body", body),
+ cause,
+ )
+ }
+}
diff --git a/stagehand-kotlin-core/src/main/kotlin/com/browserbase/api/models/sessions/Action.kt b/stagehand-kotlin-core/src/main/kotlin/com/browserbase/api/models/sessions/Action.kt
index dc420a8..7dbc7a3 100644
--- a/stagehand-kotlin-core/src/main/kotlin/com/browserbase/api/models/sessions/Action.kt
+++ b/stagehand-kotlin-core/src/main/kotlin/com/browserbase/api/models/sessions/Action.kt
@@ -24,6 +24,7 @@ private constructor(
private val description: JsonField,
private val selector: JsonField,
private val arguments: JsonField>,
+ private val backendNodeId: JsonField,
private val method: JsonField,
private val additionalProperties: MutableMap,
) {
@@ -37,8 +38,11 @@ private constructor(
@JsonProperty("arguments")
@ExcludeMissing
arguments: JsonField> = JsonMissing.of(),
+ @JsonProperty("backendNodeId")
+ @ExcludeMissing
+ backendNodeId: JsonField = JsonMissing.of(),
@JsonProperty("method") @ExcludeMissing method: JsonField = JsonMissing.of(),
- ) : this(description, selector, arguments, method, mutableMapOf())
+ ) : this(description, selector, arguments, backendNodeId, method, mutableMapOf())
/**
* Human-readable description of the action
@@ -64,6 +68,14 @@ private constructor(
*/
fun arguments(): List? = arguments.getNullable("arguments")
+ /**
+ * Backend node ID for the element
+ *
+ * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if the
+ * server responded with an unexpected value).
+ */
+ fun backendNodeId(): Double? = backendNodeId.getNullable("backendNodeId")
+
/**
* The method to execute (click, fill, etc.)
*
@@ -93,6 +105,15 @@ private constructor(
*/
@JsonProperty("arguments") @ExcludeMissing fun _arguments(): JsonField> = arguments
+ /**
+ * Returns the raw JSON value of [backendNodeId].
+ *
+ * Unlike [backendNodeId], this method doesn't throw if the JSON field has an unexpected type.
+ */
+ @JsonProperty("backendNodeId")
+ @ExcludeMissing
+ fun _backendNodeId(): JsonField = backendNodeId
+
/**
* Returns the raw JSON value of [method].
*
@@ -132,6 +153,7 @@ private constructor(
private var description: JsonField? = null
private var selector: JsonField? = null
private var arguments: JsonField>? = null
+ private var backendNodeId: JsonField = JsonMissing.of()
private var method: JsonField = JsonMissing.of()
private var additionalProperties: MutableMap = mutableMapOf()
@@ -139,6 +161,7 @@ private constructor(
description = action.description
selector = action.selector
arguments = action.arguments.map { it.toMutableList() }
+ backendNodeId = action.backendNodeId
method = action.method
additionalProperties = action.additionalProperties.toMutableMap()
}
@@ -192,6 +215,20 @@ private constructor(
}
}
+ /** Backend node ID for the element */
+ fun backendNodeId(backendNodeId: Double) = backendNodeId(JsonField.of(backendNodeId))
+
+ /**
+ * Sets [Builder.backendNodeId] to an arbitrary JSON value.
+ *
+ * You should usually call [Builder.backendNodeId] with a well-typed [Double] value instead.
+ * This method is primarily for setting the field to an undocumented or not yet supported
+ * value.
+ */
+ fun backendNodeId(backendNodeId: JsonField) = apply {
+ this.backendNodeId = backendNodeId
+ }
+
/** The method to execute (click, fill, etc.) */
fun method(method: String) = method(JsonField.of(method))
@@ -240,6 +277,7 @@ private constructor(
checkRequired("description", description),
checkRequired("selector", selector),
(arguments ?: JsonMissing.of()).map { it.toImmutable() },
+ backendNodeId,
method,
additionalProperties.toMutableMap(),
)
@@ -255,6 +293,7 @@ private constructor(
description()
selector()
arguments()
+ backendNodeId()
method()
validated = true
}
@@ -276,6 +315,7 @@ private constructor(
(if (description.asKnown() == null) 0 else 1) +
(if (selector.asKnown() == null) 0 else 1) +
(arguments.asKnown()?.size ?: 0) +
+ (if (backendNodeId.asKnown() == null) 0 else 1) +
(if (method.asKnown() == null) 0 else 1)
override fun equals(other: Any?): Boolean {
@@ -287,16 +327,17 @@ private constructor(
description == other.description &&
selector == other.selector &&
arguments == other.arguments &&
+ backendNodeId == other.backendNodeId &&
method == other.method &&
additionalProperties == other.additionalProperties
}
private val hashCode: Int by lazy {
- Objects.hash(description, selector, arguments, method, additionalProperties)
+ Objects.hash(description, selector, arguments, backendNodeId, method, additionalProperties)
}
override fun hashCode(): Int = hashCode
override fun toString() =
- "Action{description=$description, selector=$selector, arguments=$arguments, method=$method, additionalProperties=$additionalProperties}"
+ "Action{description=$description, selector=$selector, arguments=$arguments, backendNodeId=$backendNodeId, method=$method, additionalProperties=$additionalProperties}"
}
diff --git a/stagehand-kotlin-core/src/main/kotlin/com/browserbase/api/models/sessions/ModelConfig.kt b/stagehand-kotlin-core/src/main/kotlin/com/browserbase/api/models/sessions/ModelConfig.kt
index 426b552..10629da 100644
--- a/stagehand-kotlin-core/src/main/kotlin/com/browserbase/api/models/sessions/ModelConfig.kt
+++ b/stagehand-kotlin-core/src/main/kotlin/com/browserbase/api/models/sessions/ModelConfig.kt
@@ -4,6 +4,7 @@ package com.browserbase.api.models.sessions
import com.browserbase.api.core.BaseDeserializer
import com.browserbase.api.core.BaseSerializer
+import com.browserbase.api.core.Enum
import com.browserbase.api.core.ExcludeMissing
import com.browserbase.api.core.JsonField
import com.browserbase.api.core.JsonMissing
@@ -26,33 +27,44 @@ import com.fasterxml.jackson.module.kotlin.jacksonTypeRef
import java.util.Collections
import java.util.Objects
+/**
+ * Model name string with provider prefix (e.g., 'openai/gpt-5-nano', 'anthropic/claude-4.5-opus')
+ */
@JsonDeserialize(using = ModelConfig.Deserializer::class)
@JsonSerialize(using = ModelConfig.Serializer::class)
class ModelConfig
private constructor(
- private val string: String? = null,
- private val unionMember1: UnionMember1? = null,
+ private val name: String? = null,
+ private val modelConfigObject: ModelConfigObject? = null,
private val _json: JsonValue? = null,
) {
- fun string(): String? = string
+ /**
+ * Model name string with provider prefix (e.g., 'openai/gpt-5-nano',
+ * 'anthropic/claude-4.5-opus')
+ */
+ fun name(): String? = name
- fun unionMember1(): UnionMember1? = unionMember1
+ fun modelConfigObject(): ModelConfigObject? = modelConfigObject
- fun isString(): Boolean = string != null
+ fun isName(): Boolean = name != null
- fun isUnionMember1(): Boolean = unionMember1 != null
+ fun isModelConfigObject(): Boolean = modelConfigObject != null
- fun asString(): String = string.getOrThrow("string")
+ /**
+ * Model name string with provider prefix (e.g., 'openai/gpt-5-nano',
+ * 'anthropic/claude-4.5-opus')
+ */
+ fun asName(): String = name.getOrThrow("name")
- fun asUnionMember1(): UnionMember1 = unionMember1.getOrThrow("unionMember1")
+ fun asModelConfigObject(): ModelConfigObject = modelConfigObject.getOrThrow("modelConfigObject")
fun _json(): JsonValue? = _json
fun accept(visitor: Visitor): T =
when {
- string != null -> visitor.visitString(string)
- unionMember1 != null -> visitor.visitUnionMember1(unionMember1)
+ name != null -> visitor.visitName(name)
+ modelConfigObject != null -> visitor.visitModelConfigObject(modelConfigObject)
else -> visitor.unknown(_json)
}
@@ -65,10 +77,10 @@ private constructor(
accept(
object : Visitor {
- override fun visitString(string: String) {}
+ override fun visitName(name: String) {}
- override fun visitUnionMember1(unionMember1: UnionMember1) {
- unionMember1.validate()
+ override fun visitModelConfigObject(modelConfigObject: ModelConfigObject) {
+ modelConfigObject.validate()
}
}
)
@@ -91,9 +103,10 @@ private constructor(
internal fun validity(): Int =
accept(
object : Visitor {
- override fun visitString(string: String) = 1
+ override fun visitName(name: String) = 1
- override fun visitUnionMember1(unionMember1: UnionMember1) = unionMember1.validity()
+ override fun visitModelConfigObject(modelConfigObject: ModelConfigObject) =
+ modelConfigObject.validity()
override fun unknown(json: JsonValue?) = 0
}
@@ -104,24 +117,31 @@ private constructor(
return true
}
- return other is ModelConfig && string == other.string && unionMember1 == other.unionMember1
+ return other is ModelConfig &&
+ name == other.name &&
+ modelConfigObject == other.modelConfigObject
}
- override fun hashCode(): Int = Objects.hash(string, unionMember1)
+ override fun hashCode(): Int = Objects.hash(name, modelConfigObject)
override fun toString(): String =
when {
- string != null -> "ModelConfig{string=$string}"
- unionMember1 != null -> "ModelConfig{unionMember1=$unionMember1}"
+ name != null -> "ModelConfig{name=$name}"
+ modelConfigObject != null -> "ModelConfig{modelConfigObject=$modelConfigObject}"
_json != null -> "ModelConfig{_unknown=$_json}"
else -> throw IllegalStateException("Invalid ModelConfig")
}
companion object {
- fun ofString(string: String) = ModelConfig(string = string)
+ /**
+ * Model name string with provider prefix (e.g., 'openai/gpt-5-nano',
+ * 'anthropic/claude-4.5-opus')
+ */
+ fun ofName(name: String) = ModelConfig(name = name)
- fun ofUnionMember1(unionMember1: UnionMember1) = ModelConfig(unionMember1 = unionMember1)
+ fun ofModelConfigObject(modelConfigObject: ModelConfigObject) =
+ ModelConfig(modelConfigObject = modelConfigObject)
}
/**
@@ -129,9 +149,13 @@ private constructor(
*/
interface Visitor {
- fun visitString(string: String): T
+ /**
+ * Model name string with provider prefix (e.g., 'openai/gpt-5-nano',
+ * 'anthropic/claude-4.5-opus')
+ */
+ fun visitName(name: String): T
- fun visitUnionMember1(unionMember1: UnionMember1): T
+ fun visitModelConfigObject(modelConfigObject: ModelConfigObject): T
/**
* Maps an unknown variant of [ModelConfig] to a value of type [T].
@@ -154,11 +178,11 @@ private constructor(
val bestMatches =
sequenceOf(
- tryDeserialize(node, jacksonTypeRef())?.let {
- ModelConfig(unionMember1 = it, _json = json)
+ tryDeserialize(node, jacksonTypeRef())?.let {
+ ModelConfig(modelConfigObject = it, _json = json)
},
tryDeserialize(node, jacksonTypeRef())?.let {
- ModelConfig(string = it, _json = json)
+ ModelConfig(name = it, _json = json)
},
)
.filterNotNull()
@@ -184,20 +208,21 @@ private constructor(
provider: SerializerProvider,
) {
when {
- value.string != null -> generator.writeObject(value.string)
- value.unionMember1 != null -> generator.writeObject(value.unionMember1)
+ value.name != null -> generator.writeObject(value.name)
+ value.modelConfigObject != null -> generator.writeObject(value.modelConfigObject)
value._json != null -> generator.writeObject(value._json)
else -> throw IllegalStateException("Invalid ModelConfig")
}
}
}
- class UnionMember1
+ class ModelConfigObject
@JsonCreator(mode = JsonCreator.Mode.DISABLED)
private constructor(
private val modelName: JsonField,
private val apiKey: JsonField,
private val baseUrl: JsonField,
+ private val provider: JsonField,
private val additionalProperties: MutableMap,
) {
@@ -208,26 +233,43 @@ private constructor(
modelName: JsonField = JsonMissing.of(),
@JsonProperty("apiKey") @ExcludeMissing apiKey: JsonField = JsonMissing.of(),
@JsonProperty("baseURL") @ExcludeMissing baseUrl: JsonField = JsonMissing.of(),
- ) : this(modelName, apiKey, baseUrl, mutableMapOf())
+ @JsonProperty("provider")
+ @ExcludeMissing
+ provider: JsonField = JsonMissing.of(),
+ ) : this(modelName, apiKey, baseUrl, provider, mutableMapOf())
/**
+ * Model name string without prefix (e.g., 'gpt-5-nano', 'claude-4.5-opus')
+ *
* @throws StagehandInvalidDataException if the JSON field has an unexpected type or is
* unexpectedly missing or null (e.g. if the server responded with an unexpected value).
*/
fun modelName(): String = modelName.getRequired("modelName")
/**
+ * API key for the model provider
+ *
* @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if
* the server responded with an unexpected value).
*/
fun apiKey(): String? = apiKey.getNullable("apiKey")
/**
+ * Base URL for the model provider
+ *
* @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if
* the server responded with an unexpected value).
*/
fun baseUrl(): String? = baseUrl.getNullable("baseURL")
+ /**
+ * AI provider for the model (or provide a baseURL endpoint instead)
+ *
+ * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if
+ * the server responded with an unexpected value).
+ */
+ fun provider(): Provider? = provider.getNullable("provider")
+
/**
* Returns the raw JSON value of [modelName].
*
@@ -249,6 +291,13 @@ private constructor(
*/
@JsonProperty("baseURL") @ExcludeMissing fun _baseUrl(): JsonField = baseUrl
+ /**
+ * Returns the raw JSON value of [provider].
+ *
+ * Unlike [provider], this method doesn't throw if the JSON field has an unexpected type.
+ */
+ @JsonProperty("provider") @ExcludeMissing fun _provider(): JsonField = provider
+
@JsonAnySetter
private fun putAdditionalProperty(key: String, value: JsonValue) {
additionalProperties.put(key, value)
@@ -264,7 +313,7 @@ private constructor(
companion object {
/**
- * Returns a mutable builder for constructing an instance of [UnionMember1].
+ * Returns a mutable builder for constructing an instance of [ModelConfigObject].
*
* The following fields are required:
* ```kotlin
@@ -274,21 +323,24 @@ private constructor(
fun builder() = Builder()
}
- /** A builder for [UnionMember1]. */
+ /** A builder for [ModelConfigObject]. */
class Builder internal constructor() {
private var modelName: JsonField? = null
private var apiKey: JsonField = JsonMissing.of()
private var baseUrl: JsonField = JsonMissing.of()
+ private var provider: JsonField = JsonMissing.of()
private var additionalProperties: MutableMap = mutableMapOf()
- internal fun from(unionMember1: UnionMember1) = apply {
- modelName = unionMember1.modelName
- apiKey = unionMember1.apiKey
- baseUrl = unionMember1.baseUrl
- additionalProperties = unionMember1.additionalProperties.toMutableMap()
+ internal fun from(modelConfigObject: ModelConfigObject) = apply {
+ modelName = modelConfigObject.modelName
+ apiKey = modelConfigObject.apiKey
+ baseUrl = modelConfigObject.baseUrl
+ provider = modelConfigObject.provider
+ additionalProperties = modelConfigObject.additionalProperties.toMutableMap()
}
+ /** Model name string without prefix (e.g., 'gpt-5-nano', 'claude-4.5-opus') */
fun modelName(modelName: String) = modelName(JsonField.of(modelName))
/**
@@ -300,6 +352,7 @@ private constructor(
*/
fun modelName(modelName: JsonField) = apply { this.modelName = modelName }
+ /** API key for the model provider */
fun apiKey(apiKey: String) = apiKey(JsonField.of(apiKey))
/**
@@ -311,6 +364,7 @@ private constructor(
*/
fun apiKey(apiKey: JsonField) = apply { this.apiKey = apiKey }
+ /** Base URL for the model provider */
fun baseUrl(baseUrl: String) = baseUrl(JsonField.of(baseUrl))
/**
@@ -322,6 +376,18 @@ private constructor(
*/
fun baseUrl(baseUrl: JsonField) = apply { this.baseUrl = baseUrl }
+ /** AI provider for the model (or provide a baseURL endpoint instead) */
+ fun provider(provider: Provider) = provider(JsonField.of(provider))
+
+ /**
+ * Sets [Builder.provider] to an arbitrary JSON value.
+ *
+ * You should usually call [Builder.provider] with a well-typed [Provider] value
+ * instead. This method is primarily for setting the field to an undocumented or not yet
+ * supported value.
+ */
+ fun provider(provider: JsonField) = apply { this.provider = provider }
+
fun additionalProperties(additionalProperties: Map) = apply {
this.additionalProperties.clear()
putAllAdditionalProperties(additionalProperties)
@@ -342,7 +408,7 @@ private constructor(
}
/**
- * Returns an immutable instance of [UnionMember1].
+ * Returns an immutable instance of [ModelConfigObject].
*
* Further updates to this [Builder] will not mutate the returned instance.
*
@@ -353,18 +419,19 @@ private constructor(
*
* @throws IllegalStateException if any required field is unset.
*/
- fun build(): UnionMember1 =
- UnionMember1(
+ fun build(): ModelConfigObject =
+ ModelConfigObject(
checkRequired("modelName", modelName),
apiKey,
baseUrl,
+ provider,
additionalProperties.toMutableMap(),
)
}
private var validated: Boolean = false
- fun validate(): UnionMember1 = apply {
+ fun validate(): ModelConfigObject = apply {
if (validated) {
return@apply
}
@@ -372,6 +439,7 @@ private constructor(
modelName()
apiKey()
baseUrl()
+ provider()?.validate()
validated = true
}
@@ -392,27 +460,170 @@ private constructor(
internal fun validity(): Int =
(if (modelName.asKnown() == null) 0 else 1) +
(if (apiKey.asKnown() == null) 0 else 1) +
- (if (baseUrl.asKnown() == null) 0 else 1)
+ (if (baseUrl.asKnown() == null) 0 else 1) +
+ (provider.asKnown()?.validity() ?: 0)
+
+ /** AI provider for the model (or provide a baseURL endpoint instead) */
+ class Provider @JsonCreator private constructor(private val value: JsonField) :
+ Enum {
+
+ /**
+ * Returns this class instance's raw value.
+ *
+ * This is usually only useful if this instance was deserialized from data that doesn't
+ * match any known member, and you want to know that value. For example, if the SDK is
+ * on an older version than the API, then the API may respond with new members that the
+ * SDK is unaware of.
+ */
+ @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value
+
+ companion object {
+
+ val OPENAI = of("openai")
+
+ val ANTHROPIC = of("anthropic")
+
+ val GOOGLE = of("google")
+
+ val MICROSOFT = of("microsoft")
+
+ fun of(value: String) = Provider(JsonField.of(value))
+ }
+
+ /** An enum containing [Provider]'s known values. */
+ enum class Known {
+ OPENAI,
+ ANTHROPIC,
+ GOOGLE,
+ MICROSOFT,
+ }
+
+ /**
+ * An enum containing [Provider]'s known values, as well as an [_UNKNOWN] member.
+ *
+ * An instance of [Provider] can contain an unknown value in a couple of cases:
+ * - It was deserialized from data that doesn't match any known member. For example, if
+ * the SDK is on an older version than the API, then the API may respond with new
+ * members that the SDK is unaware of.
+ * - It was constructed with an arbitrary value using the [of] method.
+ */
+ enum class Value {
+ OPENAI,
+ ANTHROPIC,
+ GOOGLE,
+ MICROSOFT,
+ /**
+ * An enum member indicating that [Provider] was instantiated with an unknown value.
+ */
+ _UNKNOWN,
+ }
+
+ /**
+ * Returns an enum member corresponding to this class instance's value, or
+ * [Value._UNKNOWN] if the class was instantiated with an unknown value.
+ *
+ * Use the [known] method instead if you're certain the value is always known or if you
+ * want to throw for the unknown case.
+ */
+ fun value(): Value =
+ when (this) {
+ OPENAI -> Value.OPENAI
+ ANTHROPIC -> Value.ANTHROPIC
+ GOOGLE -> Value.GOOGLE
+ MICROSOFT -> Value.MICROSOFT
+ else -> Value._UNKNOWN
+ }
+
+ /**
+ * Returns an enum member corresponding to this class instance's value.
+ *
+ * Use the [value] method instead if you're uncertain the value is always known and
+ * don't want to throw for the unknown case.
+ *
+ * @throws StagehandInvalidDataException if this class instance's value is a not a known
+ * member.
+ */
+ fun known(): Known =
+ when (this) {
+ OPENAI -> Known.OPENAI
+ ANTHROPIC -> Known.ANTHROPIC
+ GOOGLE -> Known.GOOGLE
+ MICROSOFT -> Known.MICROSOFT
+ else -> throw StagehandInvalidDataException("Unknown Provider: $value")
+ }
+
+ /**
+ * Returns this class instance's primitive wire representation.
+ *
+ * This differs from the [toString] method because that method is primarily for
+ * debugging and generally doesn't throw.
+ *
+ * @throws StagehandInvalidDataException if this class instance's value does not have
+ * the expected primitive type.
+ */
+ fun asString(): String =
+ _value().asString() ?: throw StagehandInvalidDataException("Value is not a String")
+
+ private var validated: Boolean = false
+
+ fun validate(): Provider = apply {
+ if (validated) {
+ return@apply
+ }
+
+ known()
+ validated = true
+ }
+
+ fun isValid(): Boolean =
+ try {
+ validate()
+ true
+ } catch (e: StagehandInvalidDataException) {
+ false
+ }
+
+ /**
+ * Returns a score indicating how many valid values are contained in this object
+ * recursively.
+ *
+ * Used for best match union deserialization.
+ */
+ internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1
+
+ override fun equals(other: Any?): Boolean {
+ if (this === other) {
+ return true
+ }
+
+ return other is Provider && value == other.value
+ }
+
+ override fun hashCode() = value.hashCode()
+
+ override fun toString() = value.toString()
+ }
override fun equals(other: Any?): Boolean {
if (this === other) {
return true
}
- return other is UnionMember1 &&
+ return other is ModelConfigObject &&
modelName == other.modelName &&
apiKey == other.apiKey &&
baseUrl == other.baseUrl &&
+ provider == other.provider &&
additionalProperties == other.additionalProperties
}
private val hashCode: Int by lazy {
- Objects.hash(modelName, apiKey, baseUrl, additionalProperties)
+ Objects.hash(modelName, apiKey, baseUrl, provider, additionalProperties)
}
override fun hashCode(): Int = hashCode
override fun toString() =
- "UnionMember1{modelName=$modelName, apiKey=$apiKey, baseUrl=$baseUrl, additionalProperties=$additionalProperties}"
+ "ModelConfigObject{modelName=$modelName, apiKey=$apiKey, baseUrl=$baseUrl, provider=$provider, additionalProperties=$additionalProperties}"
}
}
diff --git a/stagehand-kotlin-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionActParams.kt b/stagehand-kotlin-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionActParams.kt
index 9649ae7..e0860c1 100644
--- a/stagehand-kotlin-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionActParams.kt
+++ b/stagehand-kotlin-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionActParams.kt
@@ -11,7 +11,6 @@ import com.browserbase.api.core.JsonMissing
import com.browserbase.api.core.JsonValue
import com.browserbase.api.core.Params
import com.browserbase.api.core.allMaxBy
-import com.browserbase.api.core.checkKnown
import com.browserbase.api.core.checkRequired
import com.browserbase.api.core.getOrThrow
import com.browserbase.api.core.http.Headers
@@ -194,7 +193,7 @@ private constructor(
fun input(string: String) = apply { body.input(string) }
/** Alias for calling [input] with `Input.ofAction(action)`. */
- fun input(action: Input.ActionInput) = apply { body.input(action) }
+ fun input(action: Action) = apply { body.input(action) }
/** Target frame ID for the action */
fun frameId(frameId: String) = apply { body.frameId(frameId) }
@@ -495,7 +494,7 @@ private constructor(
fun input(string: String) = input(Input.ofString(string))
/** Alias for calling [input] with `Input.ofAction(action)`. */
- fun input(action: Input.ActionInput) = input(Input.ofAction(action))
+ fun input(action: Action) = input(Input.ofAction(action))
/** Target frame ID for the action */
fun frameId(frameId: String) = frameId(JsonField.of(frameId))
@@ -620,14 +619,14 @@ private constructor(
class Input
private constructor(
private val string: String? = null,
- private val action: ActionInput? = null,
+ private val action: Action? = null,
private val _json: JsonValue? = null,
) {
fun string(): String? = string
/** Action object returned by observe and used by act */
- fun action(): ActionInput? = action
+ fun action(): Action? = action
fun isString(): Boolean = string != null
@@ -636,7 +635,7 @@ private constructor(
fun asString(): String = string.getOrThrow("string")
/** Action object returned by observe and used by act */
- fun asAction(): ActionInput = action.getOrThrow("action")
+ fun asAction(): Action = action.getOrThrow("action")
fun _json(): JsonValue? = _json
@@ -658,7 +657,7 @@ private constructor(
object : Visitor {
override fun visitString(string: String) {}
- override fun visitAction(action: ActionInput) {
+ override fun visitAction(action: Action) {
action.validate()
}
}
@@ -685,7 +684,7 @@ private constructor(
object : Visitor {
override fun visitString(string: String) = 1
- override fun visitAction(action: ActionInput) = action.validity()
+ override fun visitAction(action: Action) = action.validity()
override fun unknown(json: JsonValue?) = 0
}
@@ -714,7 +713,7 @@ private constructor(
fun ofString(string: String) = Input(string = string)
/** Action object returned by observe and used by act */
- fun ofAction(action: ActionInput) = Input(action = action)
+ fun ofAction(action: Action) = Input(action = action)
}
/** An interface that defines how to map each variant of [Input] to a value of type [T]. */
@@ -723,7 +722,7 @@ private constructor(
fun visitString(string: String): T
/** Action object returned by observe and used by act */
- fun visitAction(action: ActionInput): T
+ fun visitAction(action: Action): T
/**
* Maps an unknown variant of [Input] to a value of type [T].
@@ -747,7 +746,7 @@ private constructor(
val bestMatches =
sequenceOf(
- tryDeserialize(node, jacksonTypeRef())?.let {
+ tryDeserialize(node, jacksonTypeRef())?.let {
Input(action = it, _json = json)
},
tryDeserialize(node, jacksonTypeRef())?.let {
@@ -785,309 +784,6 @@ private constructor(
}
}
}
-
- /** Action object returned by observe and used by act */
- class ActionInput
- @JsonCreator(mode = JsonCreator.Mode.DISABLED)
- private constructor(
- private val description: JsonField,
- private val selector: JsonField,
- private val arguments: JsonField>,
- private val method: JsonField,
- private val additionalProperties: MutableMap,
- ) {
-
- @JsonCreator
- private constructor(
- @JsonProperty("description")
- @ExcludeMissing
- description: JsonField = JsonMissing.of(),
- @JsonProperty("selector")
- @ExcludeMissing
- selector: JsonField = JsonMissing.of(),
- @JsonProperty("arguments")
- @ExcludeMissing
- arguments: JsonField> = JsonMissing.of(),
- @JsonProperty("method") @ExcludeMissing method: JsonField = JsonMissing.of(),
- ) : this(description, selector, arguments, method, mutableMapOf())
-
- /**
- * Human-readable description of the action
- *
- * @throws StagehandInvalidDataException if the JSON field has an unexpected type or is
- * unexpectedly missing or null (e.g. if the server responded with an unexpected
- * value).
- */
- fun description(): String = description.getRequired("description")
-
- /**
- * CSS selector or XPath for the element
- *
- * @throws StagehandInvalidDataException if the JSON field has an unexpected type or is
- * unexpectedly missing or null (e.g. if the server responded with an unexpected
- * value).
- */
- fun selector(): String = selector.getRequired("selector")
-
- /**
- * Arguments to pass to the method
- *
- * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g.
- * if the server responded with an unexpected value).
- */
- fun arguments(): List? = arguments.getNullable("arguments")
-
- /**
- * The method to execute (click, fill, etc.)
- *
- * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g.
- * if the server responded with an unexpected value).
- */
- fun method(): String? = method.getNullable("method")
-
- /**
- * Returns the raw JSON value of [description].
- *
- * Unlike [description], this method doesn't throw if the JSON field has an unexpected
- * type.
- */
- @JsonProperty("description")
- @ExcludeMissing
- fun _description(): JsonField = description
-
- /**
- * Returns the raw JSON value of [selector].
- *
- * Unlike [selector], this method doesn't throw if the JSON field has an unexpected
- * type.
- */
- @JsonProperty("selector") @ExcludeMissing fun _selector(): JsonField = selector
-
- /**
- * Returns the raw JSON value of [arguments].
- *
- * Unlike [arguments], this method doesn't throw if the JSON field has an unexpected
- * type.
- */
- @JsonProperty("arguments")
- @ExcludeMissing
- fun _arguments(): JsonField> = arguments
-
- /**
- * Returns the raw JSON value of [method].
- *
- * Unlike [method], this method doesn't throw if the JSON field has an unexpected type.
- */
- @JsonProperty("method") @ExcludeMissing fun _method(): JsonField = method
-
- @JsonAnySetter
- private fun putAdditionalProperty(key: String, value: JsonValue) {
- additionalProperties.put(key, value)
- }
-
- @JsonAnyGetter
- @ExcludeMissing
- fun _additionalProperties(): Map =
- Collections.unmodifiableMap(additionalProperties)
-
- fun toBuilder() = Builder().from(this)
-
- companion object {
-
- /**
- * Returns a mutable builder for constructing an instance of [ActionInput].
- *
- * The following fields are required:
- * ```kotlin
- * .description()
- * .selector()
- * ```
- */
- fun builder() = Builder()
- }
-
- /** A builder for [ActionInput]. */
- class Builder internal constructor() {
-
- private var description: JsonField? = null
- private var selector: JsonField? = null
- private var arguments: JsonField>? = null
- private var method: JsonField = JsonMissing.of()
- private var additionalProperties: MutableMap = mutableMapOf()
-
- internal fun from(actionInput: ActionInput) = apply {
- description = actionInput.description
- selector = actionInput.selector
- arguments = actionInput.arguments.map { it.toMutableList() }
- method = actionInput.method
- additionalProperties = actionInput.additionalProperties.toMutableMap()
- }
-
- /** Human-readable description of the action */
- fun description(description: String) = description(JsonField.of(description))
-
- /**
- * Sets [Builder.description] to an arbitrary JSON value.
- *
- * You should usually call [Builder.description] with a well-typed [String] value
- * instead. This method is primarily for setting the field to an undocumented or not
- * yet supported value.
- */
- fun description(description: JsonField) = apply {
- this.description = description
- }
-
- /** CSS selector or XPath for the element */
- fun selector(selector: String) = selector(JsonField.of(selector))
-
- /**
- * Sets [Builder.selector] to an arbitrary JSON value.
- *
- * You should usually call [Builder.selector] with a well-typed [String] value
- * instead. This method is primarily for setting the field to an undocumented or not
- * yet supported value.
- */
- fun selector(selector: JsonField) = apply { this.selector = selector }
-
- /** Arguments to pass to the method */
- fun arguments(arguments: List) = arguments(JsonField.of(arguments))
-
- /**
- * Sets [Builder.arguments] to an arbitrary JSON value.
- *
- * You should usually call [Builder.arguments] with a well-typed `List`
- * value instead. This method is primarily for setting the field to an undocumented
- * or not yet supported value.
- */
- fun arguments(arguments: JsonField>) = apply {
- this.arguments = arguments.map { it.toMutableList() }
- }
-
- /**
- * Adds a single [String] to [arguments].
- *
- * @throws IllegalStateException if the field was previously set to a non-list.
- */
- fun addArgument(argument: String) = apply {
- arguments =
- (arguments ?: JsonField.of(mutableListOf())).also {
- checkKnown("arguments", it).add(argument)
- }
- }
-
- /** The method to execute (click, fill, etc.) */
- fun method(method: String) = method(JsonField.of(method))
-
- /**
- * Sets [Builder.method] to an arbitrary JSON value.
- *
- * You should usually call [Builder.method] with a well-typed [String] value
- * instead. This method is primarily for setting the field to an undocumented or not
- * yet supported value.
- */
- fun method(method: JsonField) = apply { this.method = method }
-
- fun additionalProperties(additionalProperties: Map) = apply {
- this.additionalProperties.clear()
- putAllAdditionalProperties(additionalProperties)
- }
-
- fun putAdditionalProperty(key: String, value: JsonValue) = apply {
- additionalProperties.put(key, value)
- }
-
- fun putAllAdditionalProperties(additionalProperties: Map) =
- apply {
- this.additionalProperties.putAll(additionalProperties)
- }
-
- fun removeAdditionalProperty(key: String) = apply {
- additionalProperties.remove(key)
- }
-
- fun removeAllAdditionalProperties(keys: Set) = apply {
- keys.forEach(::removeAdditionalProperty)
- }
-
- /**
- * Returns an immutable instance of [ActionInput].
- *
- * Further updates to this [Builder] will not mutate the returned instance.
- *
- * The following fields are required:
- * ```kotlin
- * .description()
- * .selector()
- * ```
- *
- * @throws IllegalStateException if any required field is unset.
- */
- fun build(): ActionInput =
- ActionInput(
- checkRequired("description", description),
- checkRequired("selector", selector),
- (arguments ?: JsonMissing.of()).map { it.toImmutable() },
- method,
- additionalProperties.toMutableMap(),
- )
- }
-
- private var validated: Boolean = false
-
- fun validate(): ActionInput = apply {
- if (validated) {
- return@apply
- }
-
- description()
- selector()
- arguments()
- method()
- validated = true
- }
-
- fun isValid(): Boolean =
- try {
- validate()
- true
- } catch (e: StagehandInvalidDataException) {
- false
- }
-
- /**
- * Returns a score indicating how many valid values are contained in this object
- * recursively.
- *
- * Used for best match union deserialization.
- */
- internal fun validity(): Int =
- (if (description.asKnown() == null) 0 else 1) +
- (if (selector.asKnown() == null) 0 else 1) +
- (arguments.asKnown()?.size ?: 0) +
- (if (method.asKnown() == null) 0 else 1)
-
- override fun equals(other: Any?): Boolean {
- if (this === other) {
- return true
- }
-
- return other is ActionInput &&
- description == other.description &&
- selector == other.selector &&
- arguments == other.arguments &&
- method == other.method &&
- additionalProperties == other.additionalProperties
- }
-
- private val hashCode: Int by lazy {
- Objects.hash(description, selector, arguments, method, additionalProperties)
- }
-
- override fun hashCode(): Int = hashCode
-
- override fun toString() =
- "ActionInput{description=$description, selector=$selector, arguments=$arguments, method=$method, additionalProperties=$additionalProperties}"
- }
}
class Options
@@ -1109,6 +805,9 @@ private constructor(
) : this(model, timeout, variables, mutableMapOf())
/**
+ * Model name string with provider prefix (e.g., 'openai/gpt-5-nano',
+ * 'anthropic/claude-4.5-opus')
+ *
* @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if
* the server responded with an unexpected value).
*/
@@ -1186,6 +885,10 @@ private constructor(
additionalProperties = options.additionalProperties.toMutableMap()
}
+ /**
+ * Model name string with provider prefix (e.g., 'openai/gpt-5-nano',
+ * 'anthropic/claude-4.5-opus')
+ */
fun model(model: ModelConfig) = model(JsonField.of(model))
/**
@@ -1197,12 +900,14 @@ private constructor(
*/
fun model(model: JsonField) = apply { this.model = model }
- /** Alias for calling [model] with `ModelConfig.ofString(string)`. */
- fun model(string: String) = model(ModelConfig.ofString(string))
+ /** Alias for calling [model] with `ModelConfig.ofName(name)`. */
+ fun model(name: String) = model(ModelConfig.ofName(name))
- /** Alias for calling [model] with `ModelConfig.ofUnionMember1(unionMember1)`. */
- fun model(unionMember1: ModelConfig.UnionMember1) =
- model(ModelConfig.ofUnionMember1(unionMember1))
+ /**
+ * Alias for calling [model] with `ModelConfig.ofModelConfigObject(modelConfigObject)`.
+ */
+ fun model(modelConfigObject: ModelConfig.ModelConfigObject) =
+ model(ModelConfig.ofModelConfigObject(modelConfigObject))
/** Timeout in ms for the action */
fun timeout(timeout: Double) = timeout(JsonField.of(timeout))
diff --git a/stagehand-kotlin-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionActResponse.kt b/stagehand-kotlin-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionActResponse.kt
index e10b0fe..b3e8813 100644
--- a/stagehand-kotlin-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionActResponse.kt
+++ b/stagehand-kotlin-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionActResponse.kt
@@ -2,7 +2,6 @@
package com.browserbase.api.models.sessions
-import com.browserbase.api.core.Enum
import com.browserbase.api.core.ExcludeMissing
import com.browserbase.api.core.JsonField
import com.browserbase.api.core.JsonMissing
@@ -22,14 +21,14 @@ class SessionActResponse
@JsonCreator(mode = JsonCreator.Mode.DISABLED)
private constructor(
private val data: JsonField,
- private val success: JsonField,
+ private val success: JsonField,
private val additionalProperties: MutableMap,
) {
@JsonCreator
private constructor(
@JsonProperty("data") @ExcludeMissing data: JsonField = JsonMissing.of(),
- @JsonProperty("success") @ExcludeMissing success: JsonField = JsonMissing.of(),
+ @JsonProperty("success") @ExcludeMissing success: JsonField = JsonMissing.of(),
) : this(data, success, mutableMapOf())
/**
@@ -39,10 +38,12 @@ private constructor(
fun data(): Data = data.getRequired("data")
/**
+ * Indicates whether the request was successful
+ *
* @throws StagehandInvalidDataException if the JSON field has an unexpected type or is
* unexpectedly missing or null (e.g. if the server responded with an unexpected value).
*/
- fun success(): Success = success.getRequired("success")
+ fun success(): Boolean = success.getRequired("success")
/**
* Returns the raw JSON value of [data].
@@ -56,7 +57,7 @@ private constructor(
*
* Unlike [success], this method doesn't throw if the JSON field has an unexpected type.
*/
- @JsonProperty("success") @ExcludeMissing fun _success(): JsonField = success
+ @JsonProperty("success") @ExcludeMissing fun _success(): JsonField = success
@JsonAnySetter
private fun putAdditionalProperty(key: String, value: JsonValue) {
@@ -88,7 +89,7 @@ private constructor(
class Builder internal constructor() {
private var data: JsonField? = null
- private var success: JsonField? = null
+ private var success: JsonField? = null
private var additionalProperties: MutableMap = mutableMapOf()
internal fun from(sessionActResponse: SessionActResponse) = apply {
@@ -107,15 +108,16 @@ private constructor(
*/
fun data(data: JsonField) = apply { this.data = data }
- fun success(success: Success) = success(JsonField.of(success))
+ /** Indicates whether the request was successful */
+ fun success(success: Boolean) = success(JsonField.of(success))
/**
* Sets [Builder.success] to an arbitrary JSON value.
*
- * You should usually call [Builder.success] with a well-typed [Success] value instead. This
+ * You should usually call [Builder.success] with a well-typed [Boolean] value instead. This
* method is primarily for setting the field to an undocumented or not yet supported value.
*/
- fun success(success: JsonField) = apply { this.success = success }
+ fun success(success: JsonField) = apply { this.success = success }
fun additionalProperties(additionalProperties: Map) = apply {
this.additionalProperties.clear()
@@ -165,7 +167,7 @@ private constructor(
}
data().validate()
- success().validate()
+ success()
validated = true
}
@@ -183,7 +185,7 @@ private constructor(
* Used for best match union deserialization.
*/
internal fun validity(): Int =
- (data.asKnown()?.validity() ?: 0) + (success.asKnown()?.validity() ?: 0)
+ (data.asKnown()?.validity() ?: 0) + (if (success.asKnown() == null) 0 else 1)
class Data
@JsonCreator(mode = JsonCreator.Mode.DISABLED)
@@ -638,6 +640,364 @@ private constructor(
(if (message.asKnown() == null) 0 else 1) +
(if (success.asKnown() == null) 0 else 1)
+ /** Action object returned by observe and used by act */
+ class Action
+ @JsonCreator(mode = JsonCreator.Mode.DISABLED)
+ private constructor(
+ private val description: JsonField,
+ private val selector: JsonField,
+ private val arguments: JsonField>,
+ private val backendNodeId: JsonField,
+ private val method: JsonField,
+ private val additionalProperties: MutableMap,
+ ) {
+
+ @JsonCreator
+ private constructor(
+ @JsonProperty("description")
+ @ExcludeMissing
+ description: JsonField = JsonMissing.of(),
+ @JsonProperty("selector")
+ @ExcludeMissing
+ selector: JsonField = JsonMissing.of(),
+ @JsonProperty("arguments")
+ @ExcludeMissing
+ arguments: JsonField> = JsonMissing.of(),
+ @JsonProperty("backendNodeId")
+ @ExcludeMissing
+ backendNodeId: JsonField = JsonMissing.of(),
+ @JsonProperty("method")
+ @ExcludeMissing
+ method: JsonField = JsonMissing.of(),
+ ) : this(description, selector, arguments, backendNodeId, method, mutableMapOf())
+
+ /**
+ * Human-readable description of the action
+ *
+ * @throws StagehandInvalidDataException if the JSON field has an unexpected type or
+ * is unexpectedly missing or null (e.g. if the server responded with an
+ * unexpected value).
+ */
+ fun description(): String = description.getRequired("description")
+
+ /**
+ * CSS selector or XPath for the element
+ *
+ * @throws StagehandInvalidDataException if the JSON field has an unexpected type or
+ * is unexpectedly missing or null (e.g. if the server responded with an
+ * unexpected value).
+ */
+ fun selector(): String = selector.getRequired("selector")
+
+ /**
+ * Arguments to pass to the method
+ *
+ * @throws StagehandInvalidDataException if the JSON field has an unexpected type
+ * (e.g. if the server responded with an unexpected value).
+ */
+ fun arguments(): List? = arguments.getNullable("arguments")
+
+ /**
+ * Backend node ID for the element
+ *
+ * @throws StagehandInvalidDataException if the JSON field has an unexpected type
+ * (e.g. if the server responded with an unexpected value).
+ */
+ fun backendNodeId(): Double? = backendNodeId.getNullable("backendNodeId")
+
+ /**
+ * The method to execute (click, fill, etc.)
+ *
+ * @throws StagehandInvalidDataException if the JSON field has an unexpected type
+ * (e.g. if the server responded with an unexpected value).
+ */
+ fun method(): String? = method.getNullable("method")
+
+ /**
+ * Returns the raw JSON value of [description].
+ *
+ * Unlike [description], this method doesn't throw if the JSON field has an
+ * unexpected type.
+ */
+ @JsonProperty("description")
+ @ExcludeMissing
+ fun _description(): JsonField = description
+
+ /**
+ * Returns the raw JSON value of [selector].
+ *
+ * Unlike [selector], this method doesn't throw if the JSON field has an unexpected
+ * type.
+ */
+ @JsonProperty("selector")
+ @ExcludeMissing
+ fun _selector(): JsonField = selector
+
+ /**
+ * Returns the raw JSON value of [arguments].
+ *
+ * Unlike [arguments], this method doesn't throw if the JSON field has an unexpected
+ * type.
+ */
+ @JsonProperty("arguments")
+ @ExcludeMissing
+ fun _arguments(): JsonField> = arguments
+
+ /**
+ * Returns the raw JSON value of [backendNodeId].
+ *
+ * Unlike [backendNodeId], this method doesn't throw if the JSON field has an
+ * unexpected type.
+ */
+ @JsonProperty("backendNodeId")
+ @ExcludeMissing
+ fun _backendNodeId(): JsonField = backendNodeId
+
+ /**
+ * Returns the raw JSON value of [method].
+ *
+ * Unlike [method], this method doesn't throw if the JSON field has an unexpected
+ * type.
+ */
+ @JsonProperty("method") @ExcludeMissing fun _method(): JsonField = method
+
+ @JsonAnySetter
+ private fun putAdditionalProperty(key: String, value: JsonValue) {
+ additionalProperties.put(key, value)
+ }
+
+ @JsonAnyGetter
+ @ExcludeMissing
+ fun _additionalProperties(): Map =
+ Collections.unmodifiableMap(additionalProperties)
+
+ fun toBuilder() = Builder().from(this)
+
+ companion object {
+
+ /**
+ * Returns a mutable builder for constructing an instance of [Action].
+ *
+ * The following fields are required:
+ * ```kotlin
+ * .description()
+ * .selector()
+ * ```
+ */
+ fun builder() = Builder()
+ }
+
+ /** A builder for [Action]. */
+ class Builder internal constructor() {
+
+ private var description: JsonField? = null
+ private var selector: JsonField? = null
+ private var arguments: JsonField>? = null
+ private var backendNodeId: JsonField = JsonMissing.of()
+ private var method: JsonField = JsonMissing.of()
+ private var additionalProperties: MutableMap = mutableMapOf()
+
+ internal fun from(action: Action) = apply {
+ description = action.description
+ selector = action.selector
+ arguments = action.arguments.map { it.toMutableList() }
+ backendNodeId = action.backendNodeId
+ method = action.method
+ additionalProperties = action.additionalProperties.toMutableMap()
+ }
+
+ /** Human-readable description of the action */
+ fun description(description: String) = description(JsonField.of(description))
+
+ /**
+ * Sets [Builder.description] to an arbitrary JSON value.
+ *
+ * You should usually call [Builder.description] with a well-typed [String]
+ * value instead. This method is primarily for setting the field to an
+ * undocumented or not yet supported value.
+ */
+ fun description(description: JsonField) = apply {
+ this.description = description
+ }
+
+ /** CSS selector or XPath for the element */
+ fun selector(selector: String) = selector(JsonField.of(selector))
+
+ /**
+ * Sets [Builder.selector] to an arbitrary JSON value.
+ *
+ * You should usually call [Builder.selector] with a well-typed [String] value
+ * instead. This method is primarily for setting the field to an undocumented or
+ * not yet supported value.
+ */
+ fun selector(selector: JsonField) = apply { this.selector = selector }
+
+ /** Arguments to pass to the method */
+ fun arguments(arguments: List) = arguments(JsonField.of(arguments))
+
+ /**
+ * Sets [Builder.arguments] to an arbitrary JSON value.
+ *
+ * You should usually call [Builder.arguments] with a well-typed `List`
+ * value instead. This method is primarily for setting the field to an
+ * undocumented or not yet supported value.
+ */
+ fun arguments(arguments: JsonField>) = apply {
+ this.arguments = arguments.map { it.toMutableList() }
+ }
+
+ /**
+ * Adds a single [String] to [arguments].
+ *
+ * @throws IllegalStateException if the field was previously set to a non-list.
+ */
+ fun addArgument(argument: String) = apply {
+ arguments =
+ (arguments ?: JsonField.of(mutableListOf())).also {
+ checkKnown("arguments", it).add(argument)
+ }
+ }
+
+ /** Backend node ID for the element */
+ fun backendNodeId(backendNodeId: Double) =
+ backendNodeId(JsonField.of(backendNodeId))
+
+ /**
+ * Sets [Builder.backendNodeId] to an arbitrary JSON value.
+ *
+ * You should usually call [Builder.backendNodeId] with a well-typed [Double]
+ * value instead. This method is primarily for setting the field to an
+ * undocumented or not yet supported value.
+ */
+ fun backendNodeId(backendNodeId: JsonField) = apply {
+ this.backendNodeId = backendNodeId
+ }
+
+ /** The method to execute (click, fill, etc.) */
+ fun method(method: String) = method(JsonField.of(method))
+
+ /**
+ * Sets [Builder.method] to an arbitrary JSON value.
+ *
+ * You should usually call [Builder.method] with a well-typed [String] value
+ * instead. This method is primarily for setting the field to an undocumented or
+ * not yet supported value.
+ */
+ fun method(method: JsonField) = apply { this.method = method }
+
+ fun additionalProperties(additionalProperties: Map) = apply {
+ this.additionalProperties.clear()
+ putAllAdditionalProperties(additionalProperties)
+ }
+
+ fun putAdditionalProperty(key: String, value: JsonValue) = apply {
+ additionalProperties.put(key, value)
+ }
+
+ fun putAllAdditionalProperties(additionalProperties: Map) =
+ apply {
+ this.additionalProperties.putAll(additionalProperties)
+ }
+
+ fun removeAdditionalProperty(key: String) = apply {
+ additionalProperties.remove(key)
+ }
+
+ fun removeAllAdditionalProperties(keys: Set) = apply {
+ keys.forEach(::removeAdditionalProperty)
+ }
+
+ /**
+ * Returns an immutable instance of [Action].
+ *
+ * Further updates to this [Builder] will not mutate the returned instance.
+ *
+ * The following fields are required:
+ * ```kotlin
+ * .description()
+ * .selector()
+ * ```
+ *
+ * @throws IllegalStateException if any required field is unset.
+ */
+ fun build(): Action =
+ Action(
+ checkRequired("description", description),
+ checkRequired("selector", selector),
+ (arguments ?: JsonMissing.of()).map { it.toImmutable() },
+ backendNodeId,
+ method,
+ additionalProperties.toMutableMap(),
+ )
+ }
+
+ private var validated: Boolean = false
+
+ fun validate(): Action = apply {
+ if (validated) {
+ return@apply
+ }
+
+ description()
+ selector()
+ arguments()
+ backendNodeId()
+ method()
+ validated = true
+ }
+
+ fun isValid(): Boolean =
+ try {
+ validate()
+ true
+ } catch (e: StagehandInvalidDataException) {
+ false
+ }
+
+ /**
+ * Returns a score indicating how many valid values are contained in this object
+ * recursively.
+ *
+ * Used for best match union deserialization.
+ */
+ internal fun validity(): Int =
+ (if (description.asKnown() == null) 0 else 1) +
+ (if (selector.asKnown() == null) 0 else 1) +
+ (arguments.asKnown()?.size ?: 0) +
+ (if (backendNodeId.asKnown() == null) 0 else 1) +
+ (if (method.asKnown() == null) 0 else 1)
+
+ override fun equals(other: Any?): Boolean {
+ if (this === other) {
+ return true
+ }
+
+ return other is Action &&
+ description == other.description &&
+ selector == other.selector &&
+ arguments == other.arguments &&
+ backendNodeId == other.backendNodeId &&
+ method == other.method &&
+ additionalProperties == other.additionalProperties
+ }
+
+ private val hashCode: Int by lazy {
+ Objects.hash(
+ description,
+ selector,
+ arguments,
+ backendNodeId,
+ method,
+ additionalProperties,
+ )
+ }
+
+ override fun hashCode(): Int = hashCode
+
+ override fun toString() =
+ "Action{description=$description, selector=$selector, arguments=$arguments, backendNodeId=$backendNodeId, method=$method, additionalProperties=$additionalProperties}"
+ }
+
override fun equals(other: Any?): Boolean {
if (this === other) {
return true
@@ -680,122 +1040,6 @@ private constructor(
"Data{result=$result, actionId=$actionId, additionalProperties=$additionalProperties}"
}
- class Success @JsonCreator private constructor(private val value: JsonField) : Enum {
-
- /**
- * Returns this class instance's raw value.
- *
- * This is usually only useful if this instance was deserialized from data that doesn't
- * match any known member, and you want to know that value. For example, if the SDK is on an
- * older version than the API, then the API may respond with new members that the SDK is
- * unaware of.
- */
- @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value
-
- companion object {
-
- val TRUE = of(true)
-
- fun of(value: Boolean) = Success(JsonField.of(value))
- }
-
- /** An enum containing [Success]'s known values. */
- enum class Known {
- TRUE
- }
-
- /**
- * An enum containing [Success]'s known values, as well as an [_UNKNOWN] member.
- *
- * An instance of [Success] can contain an unknown value in a couple of cases:
- * - It was deserialized from data that doesn't match any known member. For example, if the
- * SDK is on an older version than the API, then the API may respond with new members that
- * the SDK is unaware of.
- * - It was constructed with an arbitrary value using the [of] method.
- */
- enum class Value {
- TRUE,
- /** An enum member indicating that [Success] was instantiated with an unknown value. */
- _UNKNOWN,
- }
-
- /**
- * Returns an enum member corresponding to this class instance's value, or [Value._UNKNOWN]
- * if the class was instantiated with an unknown value.
- *
- * Use the [known] method instead if you're certain the value is always known or if you want
- * to throw for the unknown case.
- */
- fun value(): Value =
- when (this) {
- TRUE -> Value.TRUE
- else -> Value._UNKNOWN
- }
-
- /**
- * Returns an enum member corresponding to this class instance's value.
- *
- * Use the [value] method instead if you're uncertain the value is always known and don't
- * want to throw for the unknown case.
- *
- * @throws StagehandInvalidDataException if this class instance's value is a not a known
- * member.
- */
- fun known(): Known =
- when (this) {
- TRUE -> Known.TRUE
- else -> throw StagehandInvalidDataException("Unknown Success: $value")
- }
-
- /**
- * Returns this class instance's primitive wire representation.
- *
- * @throws StagehandInvalidDataException if this class instance's value does not have the
- * expected primitive type.
- */
- fun asBoolean(): Boolean =
- _value().asBoolean() ?: throw StagehandInvalidDataException("Value is not a Boolean")
-
- private var validated: Boolean = false
-
- fun validate(): Success = apply {
- if (validated) {
- return@apply
- }
-
- known()
- validated = true
- }
-
- fun isValid(): Boolean =
- try {
- validate()
- true
- } catch (e: StagehandInvalidDataException) {
- false
- }
-
- /**
- * Returns a score indicating how many valid values are contained in this object
- * recursively.
- *
- * Used for best match union deserialization.
- */
- internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1
-
- override fun equals(other: Any?): Boolean {
- if (this === other) {
- return true
- }
-
- return other is Success && value == other.value
- }
-
- override fun hashCode() = value.hashCode()
-
- override fun toString() = value.toString()
- }
-
override fun equals(other: Any?): Boolean {
if (this === other) {
return true
diff --git a/stagehand-kotlin-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionEndResponse.kt b/stagehand-kotlin-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionEndResponse.kt
index 5168fc3..09c9d2f 100644
--- a/stagehand-kotlin-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionEndResponse.kt
+++ b/stagehand-kotlin-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionEndResponse.kt
@@ -2,7 +2,6 @@
package com.browserbase.api.models.sessions
-import com.browserbase.api.core.Enum
import com.browserbase.api.core.ExcludeMissing
import com.browserbase.api.core.JsonField
import com.browserbase.api.core.JsonMissing
@@ -19,27 +18,29 @@ import java.util.Objects
class SessionEndResponse
@JsonCreator(mode = JsonCreator.Mode.DISABLED)
private constructor(
- private val success: JsonField,
+ private val success: JsonField,
private val additionalProperties: MutableMap,
) {
@JsonCreator
private constructor(
- @JsonProperty("success") @ExcludeMissing success: JsonField = JsonMissing.of()
+ @JsonProperty("success") @ExcludeMissing success: JsonField = JsonMissing.of()
) : this(success, mutableMapOf())
/**
+ * Indicates whether the request was successful
+ *
* @throws StagehandInvalidDataException if the JSON field has an unexpected type or is
* unexpectedly missing or null (e.g. if the server responded with an unexpected value).
*/
- fun success(): Success = success.getRequired("success")
+ fun success(): Boolean = success.getRequired("success")
/**
* Returns the raw JSON value of [success].
*
* Unlike [success], this method doesn't throw if the JSON field has an unexpected type.
*/
- @JsonProperty("success") @ExcludeMissing fun _success(): JsonField = success
+ @JsonProperty("success") @ExcludeMissing fun _success(): JsonField = success
@JsonAnySetter
private fun putAdditionalProperty(key: String, value: JsonValue) {
@@ -69,7 +70,7 @@ private constructor(
/** A builder for [SessionEndResponse]. */
class Builder internal constructor() {
- private var success: JsonField? = null
+ private var success: JsonField? = null
private var additionalProperties: MutableMap = mutableMapOf()
internal fun from(sessionEndResponse: SessionEndResponse) = apply {
@@ -77,15 +78,16 @@ private constructor(
additionalProperties = sessionEndResponse.additionalProperties.toMutableMap()
}
- fun success(success: Success) = success(JsonField.of(success))
+ /** Indicates whether the request was successful */
+ fun success(success: Boolean) = success(JsonField.of(success))
/**
* Sets [Builder.success] to an arbitrary JSON value.
*
- * You should usually call [Builder.success] with a well-typed [Success] value instead. This
+ * You should usually call [Builder.success] with a well-typed [Boolean] value instead. This
* method is primarily for setting the field to an undocumented or not yet supported value.
*/
- fun success(success: JsonField) = apply { this.success = success }
+ fun success(success: JsonField) = apply { this.success = success }
fun additionalProperties(additionalProperties: Map) = apply {
this.additionalProperties.clear()
@@ -132,7 +134,7 @@ private constructor(
return@apply
}
- success().validate()
+ success()
validated = true
}
@@ -149,123 +151,7 @@ private constructor(
*
* Used for best match union deserialization.
*/
- internal fun validity(): Int = (success.asKnown()?.validity() ?: 0)
-
- class Success @JsonCreator private constructor(private val value: JsonField) : Enum {
-
- /**
- * Returns this class instance's raw value.
- *
- * This is usually only useful if this instance was deserialized from data that doesn't
- * match any known member, and you want to know that value. For example, if the SDK is on an
- * older version than the API, then the API may respond with new members that the SDK is
- * unaware of.
- */
- @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value
-
- companion object {
-
- val TRUE = of(true)
-
- fun of(value: Boolean) = Success(JsonField.of(value))
- }
-
- /** An enum containing [Success]'s known values. */
- enum class Known {
- TRUE
- }
-
- /**
- * An enum containing [Success]'s known values, as well as an [_UNKNOWN] member.
- *
- * An instance of [Success] can contain an unknown value in a couple of cases:
- * - It was deserialized from data that doesn't match any known member. For example, if the
- * SDK is on an older version than the API, then the API may respond with new members that
- * the SDK is unaware of.
- * - It was constructed with an arbitrary value using the [of] method.
- */
- enum class Value {
- TRUE,
- /** An enum member indicating that [Success] was instantiated with an unknown value. */
- _UNKNOWN,
- }
-
- /**
- * Returns an enum member corresponding to this class instance's value, or [Value._UNKNOWN]
- * if the class was instantiated with an unknown value.
- *
- * Use the [known] method instead if you're certain the value is always known or if you want
- * to throw for the unknown case.
- */
- fun value(): Value =
- when (this) {
- TRUE -> Value.TRUE
- else -> Value._UNKNOWN
- }
-
- /**
- * Returns an enum member corresponding to this class instance's value.
- *
- * Use the [value] method instead if you're uncertain the value is always known and don't
- * want to throw for the unknown case.
- *
- * @throws StagehandInvalidDataException if this class instance's value is a not a known
- * member.
- */
- fun known(): Known =
- when (this) {
- TRUE -> Known.TRUE
- else -> throw StagehandInvalidDataException("Unknown Success: $value")
- }
-
- /**
- * Returns this class instance's primitive wire representation.
- *
- * @throws StagehandInvalidDataException if this class instance's value does not have the
- * expected primitive type.
- */
- fun asBoolean(): Boolean =
- _value().asBoolean() ?: throw StagehandInvalidDataException("Value is not a Boolean")
-
- private var validated: Boolean = false
-
- fun validate(): Success = apply {
- if (validated) {
- return@apply
- }
-
- known()
- validated = true
- }
-
- fun isValid(): Boolean =
- try {
- validate()
- true
- } catch (e: StagehandInvalidDataException) {
- false
- }
-
- /**
- * Returns a score indicating how many valid values are contained in this object
- * recursively.
- *
- * Used for best match union deserialization.
- */
- internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1
-
- override fun equals(other: Any?): Boolean {
- if (this === other) {
- return true
- }
-
- return other is Success && value == other.value
- }
-
- override fun hashCode() = value.hashCode()
-
- override fun toString() = value.toString()
- }
+ internal fun validity(): Int = (if (success.asKnown() == null) 0 else 1)
override fun equals(other: Any?): Boolean {
if (this === other) {
diff --git a/stagehand-kotlin-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionExecuteParams.kt b/stagehand-kotlin-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionExecuteParams.kt
index 6a8face..c56549c 100644
--- a/stagehand-kotlin-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionExecuteParams.kt
+++ b/stagehand-kotlin-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionExecuteParams.kt
@@ -614,6 +614,7 @@ private constructor(
private constructor(
private val cua: JsonField,
private val model: JsonField,
+ private val provider: JsonField,
private val systemPrompt: JsonField,
private val additionalProperties: MutableMap,
) {
@@ -622,10 +623,13 @@ private constructor(
private constructor(
@JsonProperty("cua") @ExcludeMissing cua: JsonField = JsonMissing.of(),
@JsonProperty("model") @ExcludeMissing model: JsonField = JsonMissing.of(),
+ @JsonProperty("provider")
+ @ExcludeMissing
+ provider: JsonField = JsonMissing.of(),
@JsonProperty("systemPrompt")
@ExcludeMissing
systemPrompt: JsonField = JsonMissing.of(),
- ) : this(cua, model, systemPrompt, mutableMapOf())
+ ) : this(cua, model, provider, systemPrompt, mutableMapOf())
/**
* Enable Computer Use Agent mode
@@ -636,11 +640,22 @@ private constructor(
fun cua(): Boolean? = cua.getNullable("cua")
/**
+ * Model name string with provider prefix (e.g., 'openai/gpt-5-nano',
+ * 'anthropic/claude-4.5-opus')
+ *
* @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if
* the server responded with an unexpected value).
*/
fun model(): ModelConfig? = model.getNullable("model")
+ /**
+ * AI provider for the agent (legacy, use model: openai/gpt-5-nano instead)
+ *
+ * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if
+ * the server responded with an unexpected value).
+ */
+ fun provider(): Provider? = provider.getNullable("provider")
+
/**
* Custom system prompt for the agent
*
@@ -663,6 +678,13 @@ private constructor(
*/
@JsonProperty("model") @ExcludeMissing fun _model(): JsonField = model
+ /**
+ * Returns the raw JSON value of [provider].
+ *
+ * Unlike [provider], this method doesn't throw if the JSON field has an unexpected type.
+ */
+ @JsonProperty("provider") @ExcludeMissing fun _provider(): JsonField = provider
+
/**
* Returns the raw JSON value of [systemPrompt].
*
@@ -696,12 +718,14 @@ private constructor(
private var cua: JsonField = JsonMissing.of()
private var model: JsonField = JsonMissing.of()
+ private var provider: JsonField = JsonMissing.of()
private var systemPrompt: JsonField = JsonMissing.of()
private var additionalProperties: MutableMap = mutableMapOf()
internal fun from(agentConfig: AgentConfig) = apply {
cua = agentConfig.cua
model = agentConfig.model
+ provider = agentConfig.provider
systemPrompt = agentConfig.systemPrompt
additionalProperties = agentConfig.additionalProperties.toMutableMap()
}
@@ -718,6 +742,10 @@ private constructor(
*/
fun cua(cua: JsonField) = apply { this.cua = cua }
+ /**
+ * Model name string with provider prefix (e.g., 'openai/gpt-5-nano',
+ * 'anthropic/claude-4.5-opus')
+ */
fun model(model: ModelConfig) = model(JsonField.of(model))
/**
@@ -729,12 +757,26 @@ private constructor(
*/
fun model(model: JsonField) = apply { this.model = model }
- /** Alias for calling [model] with `ModelConfig.ofString(string)`. */
- fun model(string: String) = model(ModelConfig.ofString(string))
+ /** Alias for calling [model] with `ModelConfig.ofName(name)`. */
+ fun model(name: String) = model(ModelConfig.ofName(name))
+
+ /**
+ * Alias for calling [model] with `ModelConfig.ofModelConfigObject(modelConfigObject)`.
+ */
+ fun model(modelConfigObject: ModelConfig.ModelConfigObject) =
+ model(ModelConfig.ofModelConfigObject(modelConfigObject))
+
+ /** AI provider for the agent (legacy, use model: openai/gpt-5-nano instead) */
+ fun provider(provider: Provider) = provider(JsonField.of(provider))
- /** Alias for calling [model] with `ModelConfig.ofUnionMember1(unionMember1)`. */
- fun model(unionMember1: ModelConfig.UnionMember1) =
- model(ModelConfig.ofUnionMember1(unionMember1))
+ /**
+ * Sets [Builder.provider] to an arbitrary JSON value.
+ *
+ * You should usually call [Builder.provider] with a well-typed [Provider] value
+ * instead. This method is primarily for setting the field to an undocumented or not yet
+ * supported value.
+ */
+ fun provider(provider: JsonField) = apply { this.provider = provider }
/** Custom system prompt for the agent */
fun systemPrompt(systemPrompt: String) = systemPrompt(JsonField.of(systemPrompt))
@@ -775,7 +817,7 @@ private constructor(
* Further updates to this [Builder] will not mutate the returned instance.
*/
fun build(): AgentConfig =
- AgentConfig(cua, model, systemPrompt, additionalProperties.toMutableMap())
+ AgentConfig(cua, model, provider, systemPrompt, additionalProperties.toMutableMap())
}
private var validated: Boolean = false
@@ -787,6 +829,7 @@ private constructor(
cua()
model()?.validate()
+ provider()?.validate()
systemPrompt()
validated = true
}
@@ -808,8 +851,150 @@ private constructor(
internal fun validity(): Int =
(if (cua.asKnown() == null) 0 else 1) +
(model.asKnown()?.validity() ?: 0) +
+ (provider.asKnown()?.validity() ?: 0) +
(if (systemPrompt.asKnown() == null) 0 else 1)
+ /** AI provider for the agent (legacy, use model: openai/gpt-5-nano instead) */
+ class Provider @JsonCreator private constructor(private val value: JsonField) :
+ Enum {
+
+ /**
+ * Returns this class instance's raw value.
+ *
+ * This is usually only useful if this instance was deserialized from data that doesn't
+ * match any known member, and you want to know that value. For example, if the SDK is
+ * on an older version than the API, then the API may respond with new members that the
+ * SDK is unaware of.
+ */
+ @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value
+
+ companion object {
+
+ val OPENAI = of("openai")
+
+ val ANTHROPIC = of("anthropic")
+
+ val GOOGLE = of("google")
+
+ val MICROSOFT = of("microsoft")
+
+ fun of(value: String) = Provider(JsonField.of(value))
+ }
+
+ /** An enum containing [Provider]'s known values. */
+ enum class Known {
+ OPENAI,
+ ANTHROPIC,
+ GOOGLE,
+ MICROSOFT,
+ }
+
+ /**
+ * An enum containing [Provider]'s known values, as well as an [_UNKNOWN] member.
+ *
+ * An instance of [Provider] can contain an unknown value in a couple of cases:
+ * - It was deserialized from data that doesn't match any known member. For example, if
+ * the SDK is on an older version than the API, then the API may respond with new
+ * members that the SDK is unaware of.
+ * - It was constructed with an arbitrary value using the [of] method.
+ */
+ enum class Value {
+ OPENAI,
+ ANTHROPIC,
+ GOOGLE,
+ MICROSOFT,
+ /**
+ * An enum member indicating that [Provider] was instantiated with an unknown value.
+ */
+ _UNKNOWN,
+ }
+
+ /**
+ * Returns an enum member corresponding to this class instance's value, or
+ * [Value._UNKNOWN] if the class was instantiated with an unknown value.
+ *
+ * Use the [known] method instead if you're certain the value is always known or if you
+ * want to throw for the unknown case.
+ */
+ fun value(): Value =
+ when (this) {
+ OPENAI -> Value.OPENAI
+ ANTHROPIC -> Value.ANTHROPIC
+ GOOGLE -> Value.GOOGLE
+ MICROSOFT -> Value.MICROSOFT
+ else -> Value._UNKNOWN
+ }
+
+ /**
+ * Returns an enum member corresponding to this class instance's value.
+ *
+ * Use the [value] method instead if you're uncertain the value is always known and
+ * don't want to throw for the unknown case.
+ *
+ * @throws StagehandInvalidDataException if this class instance's value is a not a known
+ * member.
+ */
+ fun known(): Known =
+ when (this) {
+ OPENAI -> Known.OPENAI
+ ANTHROPIC -> Known.ANTHROPIC
+ GOOGLE -> Known.GOOGLE
+ MICROSOFT -> Known.MICROSOFT
+ else -> throw StagehandInvalidDataException("Unknown Provider: $value")
+ }
+
+ /**
+ * Returns this class instance's primitive wire representation.
+ *
+ * This differs from the [toString] method because that method is primarily for
+ * debugging and generally doesn't throw.
+ *
+ * @throws StagehandInvalidDataException if this class instance's value does not have
+ * the expected primitive type.
+ */
+ fun asString(): String =
+ _value().asString() ?: throw StagehandInvalidDataException("Value is not a String")
+
+ private var validated: Boolean = false
+
+ fun validate(): Provider = apply {
+ if (validated) {
+ return@apply
+ }
+
+ known()
+ validated = true
+ }
+
+ fun isValid(): Boolean =
+ try {
+ validate()
+ true
+ } catch (e: StagehandInvalidDataException) {
+ false
+ }
+
+ /**
+ * Returns a score indicating how many valid values are contained in this object
+ * recursively.
+ *
+ * Used for best match union deserialization.
+ */
+ internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1
+
+ override fun equals(other: Any?): Boolean {
+ if (this === other) {
+ return true
+ }
+
+ return other is Provider && value == other.value
+ }
+
+ override fun hashCode() = value.hashCode()
+
+ override fun toString() = value.toString()
+ }
+
override fun equals(other: Any?): Boolean {
if (this === other) {
return true
@@ -818,18 +1003,19 @@ private constructor(
return other is AgentConfig &&
cua == other.cua &&
model == other.model &&
+ provider == other.provider &&
systemPrompt == other.systemPrompt &&
additionalProperties == other.additionalProperties
}
private val hashCode: Int by lazy {
- Objects.hash(cua, model, systemPrompt, additionalProperties)
+ Objects.hash(cua, model, provider, systemPrompt, additionalProperties)
}
override fun hashCode(): Int = hashCode
override fun toString() =
- "AgentConfig{cua=$cua, model=$model, systemPrompt=$systemPrompt, additionalProperties=$additionalProperties}"
+ "AgentConfig{cua=$cua, model=$model, provider=$provider, systemPrompt=$systemPrompt, additionalProperties=$additionalProperties}"
}
class ExecuteOptions
diff --git a/stagehand-kotlin-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionExecuteResponse.kt b/stagehand-kotlin-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionExecuteResponse.kt
index f42572f..444c2a5 100644
--- a/stagehand-kotlin-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionExecuteResponse.kt
+++ b/stagehand-kotlin-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionExecuteResponse.kt
@@ -2,7 +2,6 @@
package com.browserbase.api.models.sessions
-import com.browserbase.api.core.Enum
import com.browserbase.api.core.ExcludeMissing
import com.browserbase.api.core.JsonField
import com.browserbase.api.core.JsonMissing
@@ -22,14 +21,14 @@ class SessionExecuteResponse
@JsonCreator(mode = JsonCreator.Mode.DISABLED)
private constructor(
private val data: JsonField,
- private val success: JsonField,
+ private val success: JsonField,
private val additionalProperties: MutableMap,
) {
@JsonCreator
private constructor(
@JsonProperty("data") @ExcludeMissing data: JsonField = JsonMissing.of(),
- @JsonProperty("success") @ExcludeMissing success: JsonField = JsonMissing.of(),
+ @JsonProperty("success") @ExcludeMissing success: JsonField = JsonMissing.of(),
) : this(data, success, mutableMapOf())
/**
@@ -39,10 +38,12 @@ private constructor(
fun data(): Data = data.getRequired("data")
/**
+ * Indicates whether the request was successful
+ *
* @throws StagehandInvalidDataException if the JSON field has an unexpected type or is
* unexpectedly missing or null (e.g. if the server responded with an unexpected value).
*/
- fun success(): Success = success.getRequired("success")
+ fun success(): Boolean = success.getRequired("success")
/**
* Returns the raw JSON value of [data].
@@ -56,7 +57,7 @@ private constructor(
*
* Unlike [success], this method doesn't throw if the JSON field has an unexpected type.
*/
- @JsonProperty("success") @ExcludeMissing fun _success(): JsonField = success
+ @JsonProperty("success") @ExcludeMissing fun _success(): JsonField = success
@JsonAnySetter
private fun putAdditionalProperty(key: String, value: JsonValue) {
@@ -88,7 +89,7 @@ private constructor(
class Builder internal constructor() {
private var data: JsonField? = null
- private var success: JsonField? = null
+ private var success: JsonField? = null
private var additionalProperties: MutableMap = mutableMapOf()
internal fun from(sessionExecuteResponse: SessionExecuteResponse) = apply {
@@ -107,15 +108,16 @@ private constructor(
*/
fun data(data: JsonField) = apply { this.data = data }
- fun success(success: Success) = success(JsonField.of(success))
+ /** Indicates whether the request was successful */
+ fun success(success: Boolean) = success(JsonField.of(success))
/**
* Sets [Builder.success] to an arbitrary JSON value.
*
- * You should usually call [Builder.success] with a well-typed [Success] value instead. This
+ * You should usually call [Builder.success] with a well-typed [Boolean] value instead. This
* method is primarily for setting the field to an undocumented or not yet supported value.
*/
- fun success(success: JsonField) = apply { this.success = success }
+ fun success(success: JsonField) = apply { this.success = success }
fun additionalProperties(additionalProperties: Map) = apply {
this.additionalProperties.clear()
@@ -165,7 +167,7 @@ private constructor(
}
data().validate()
- success().validate()
+ success()
validated = true
}
@@ -183,7 +185,7 @@ private constructor(
* Used for best match union deserialization.
*/
internal fun validity(): Int =
- (data.asKnown()?.validity() ?: 0) + (success.asKnown()?.validity() ?: 0)
+ (data.asKnown()?.validity() ?: 0) + (if (success.asKnown() == null) 0 else 1)
class Data
@JsonCreator(mode = JsonCreator.Mode.DISABLED)
@@ -1622,122 +1624,6 @@ private constructor(
override fun toString() = "Data{result=$result, additionalProperties=$additionalProperties}"
}
- class Success @JsonCreator private constructor(private val value: JsonField) : Enum {
-
- /**
- * Returns this class instance's raw value.
- *
- * This is usually only useful if this instance was deserialized from data that doesn't
- * match any known member, and you want to know that value. For example, if the SDK is on an
- * older version than the API, then the API may respond with new members that the SDK is
- * unaware of.
- */
- @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value
-
- companion object {
-
- val TRUE = of(true)
-
- fun of(value: Boolean) = Success(JsonField.of(value))
- }
-
- /** An enum containing [Success]'s known values. */
- enum class Known {
- TRUE
- }
-
- /**
- * An enum containing [Success]'s known values, as well as an [_UNKNOWN] member.
- *
- * An instance of [Success] can contain an unknown value in a couple of cases:
- * - It was deserialized from data that doesn't match any known member. For example, if the
- * SDK is on an older version than the API, then the API may respond with new members that
- * the SDK is unaware of.
- * - It was constructed with an arbitrary value using the [of] method.
- */
- enum class Value {
- TRUE,
- /** An enum member indicating that [Success] was instantiated with an unknown value. */
- _UNKNOWN,
- }
-
- /**
- * Returns an enum member corresponding to this class instance's value, or [Value._UNKNOWN]
- * if the class was instantiated with an unknown value.
- *
- * Use the [known] method instead if you're certain the value is always known or if you want
- * to throw for the unknown case.
- */
- fun value(): Value =
- when (this) {
- TRUE -> Value.TRUE
- else -> Value._UNKNOWN
- }
-
- /**
- * Returns an enum member corresponding to this class instance's value.
- *
- * Use the [value] method instead if you're uncertain the value is always known and don't
- * want to throw for the unknown case.
- *
- * @throws StagehandInvalidDataException if this class instance's value is a not a known
- * member.
- */
- fun known(): Known =
- when (this) {
- TRUE -> Known.TRUE
- else -> throw StagehandInvalidDataException("Unknown Success: $value")
- }
-
- /**
- * Returns this class instance's primitive wire representation.
- *
- * @throws StagehandInvalidDataException if this class instance's value does not have the
- * expected primitive type.
- */
- fun asBoolean(): Boolean =
- _value().asBoolean() ?: throw StagehandInvalidDataException("Value is not a Boolean")
-
- private var validated: Boolean = false
-
- fun validate(): Success = apply {
- if (validated) {
- return@apply
- }
-
- known()
- validated = true
- }
-
- fun isValid(): Boolean =
- try {
- validate()
- true
- } catch (e: StagehandInvalidDataException) {
- false
- }
-
- /**
- * Returns a score indicating how many valid values are contained in this object
- * recursively.
- *
- * Used for best match union deserialization.
- */
- internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1
-
- override fun equals(other: Any?): Boolean {
- if (this === other) {
- return true
- }
-
- return other is Success && value == other.value
- }
-
- override fun hashCode() = value.hashCode()
-
- override fun toString() = value.toString()
- }
-
override fun equals(other: Any?): Boolean {
if (this === other) {
return true
diff --git a/stagehand-kotlin-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionExtractParams.kt b/stagehand-kotlin-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionExtractParams.kt
index 15600fe..6bb32ec 100644
--- a/stagehand-kotlin-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionExtractParams.kt
+++ b/stagehand-kotlin-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionExtractParams.kt
@@ -645,6 +645,9 @@ private constructor(
) : this(model, selector, timeout, mutableMapOf())
/**
+ * Model name string with provider prefix (e.g., 'openai/gpt-5-nano',
+ * 'anthropic/claude-4.5-opus')
+ *
* @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if
* the server responded with an unexpected value).
*/
@@ -720,6 +723,10 @@ private constructor(
additionalProperties = options.additionalProperties.toMutableMap()
}
+ /**
+ * Model name string with provider prefix (e.g., 'openai/gpt-5-nano',
+ * 'anthropic/claude-4.5-opus')
+ */
fun model(model: ModelConfig) = model(JsonField.of(model))
/**
@@ -731,12 +738,14 @@ private constructor(
*/
fun model(model: JsonField) = apply { this.model = model }
- /** Alias for calling [model] with `ModelConfig.ofString(string)`. */
- fun model(string: String) = model(ModelConfig.ofString(string))
+ /** Alias for calling [model] with `ModelConfig.ofName(name)`. */
+ fun model(name: String) = model(ModelConfig.ofName(name))
- /** Alias for calling [model] with `ModelConfig.ofUnionMember1(unionMember1)`. */
- fun model(unionMember1: ModelConfig.UnionMember1) =
- model(ModelConfig.ofUnionMember1(unionMember1))
+ /**
+ * Alias for calling [model] with `ModelConfig.ofModelConfigObject(modelConfigObject)`.
+ */
+ fun model(modelConfigObject: ModelConfig.ModelConfigObject) =
+ model(ModelConfig.ofModelConfigObject(modelConfigObject))
/** CSS selector to scope extraction to a specific element */
fun selector(selector: String) = selector(JsonField.of(selector))
diff --git a/stagehand-kotlin-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionExtractResponse.kt b/stagehand-kotlin-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionExtractResponse.kt
index 38ee91a..5c99f5a 100644
--- a/stagehand-kotlin-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionExtractResponse.kt
+++ b/stagehand-kotlin-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionExtractResponse.kt
@@ -2,7 +2,6 @@
package com.browserbase.api.models.sessions
-import com.browserbase.api.core.Enum
import com.browserbase.api.core.ExcludeMissing
import com.browserbase.api.core.JsonField
import com.browserbase.api.core.JsonMissing
@@ -20,14 +19,14 @@ class SessionExtractResponse
@JsonCreator(mode = JsonCreator.Mode.DISABLED)
private constructor(
private val data: JsonField,
- private val success: JsonField,
+ private val success: JsonField,
private val additionalProperties: MutableMap,
) {
@JsonCreator
private constructor(
@JsonProperty("data") @ExcludeMissing data: JsonField = JsonMissing.of(),
- @JsonProperty("success") @ExcludeMissing success: JsonField = JsonMissing.of(),
+ @JsonProperty("success") @ExcludeMissing success: JsonField = JsonMissing.of(),
) : this(data, success, mutableMapOf())
/**
@@ -37,10 +36,12 @@ private constructor(
fun data(): Data = data.getRequired("data")
/**
+ * Indicates whether the request was successful
+ *
* @throws StagehandInvalidDataException if the JSON field has an unexpected type or is
* unexpectedly missing or null (e.g. if the server responded with an unexpected value).
*/
- fun success(): Success = success.getRequired("success")
+ fun success(): Boolean = success.getRequired("success")
/**
* Returns the raw JSON value of [data].
@@ -54,7 +55,7 @@ private constructor(
*
* Unlike [success], this method doesn't throw if the JSON field has an unexpected type.
*/
- @JsonProperty("success") @ExcludeMissing fun _success(): JsonField = success
+ @JsonProperty("success") @ExcludeMissing fun _success(): JsonField = success
@JsonAnySetter
private fun putAdditionalProperty(key: String, value: JsonValue) {
@@ -86,7 +87,7 @@ private constructor(
class Builder internal constructor() {
private var data: JsonField? = null
- private var success: JsonField? = null
+ private var success: JsonField? = null
private var additionalProperties: MutableMap = mutableMapOf()
internal fun from(sessionExtractResponse: SessionExtractResponse) = apply {
@@ -105,15 +106,16 @@ private constructor(
*/
fun data(data: JsonField) = apply { this.data = data }
- fun success(success: Success) = success(JsonField.of(success))
+ /** Indicates whether the request was successful */
+ fun success(success: Boolean) = success(JsonField.of(success))
/**
* Sets [Builder.success] to an arbitrary JSON value.
*
- * You should usually call [Builder.success] with a well-typed [Success] value instead. This
+ * You should usually call [Builder.success] with a well-typed [Boolean] value instead. This
* method is primarily for setting the field to an undocumented or not yet supported value.
*/
- fun success(success: JsonField) = apply { this.success = success }
+ fun success(success: JsonField) = apply { this.success = success }
fun additionalProperties(additionalProperties: Map) = apply {
this.additionalProperties.clear()
@@ -163,7 +165,7 @@ private constructor(
}
data().validate()
- success().validate()
+ success()
validated = true
}
@@ -181,7 +183,7 @@ private constructor(
* Used for best match union deserialization.
*/
internal fun validity(): Int =
- (data.asKnown()?.validity() ?: 0) + (success.asKnown()?.validity() ?: 0)
+ (data.asKnown()?.validity() ?: 0) + (if (success.asKnown() == null) 0 else 1)
class Data
@JsonCreator(mode = JsonCreator.Mode.DISABLED)
@@ -349,122 +351,6 @@ private constructor(
"Data{result=$result, actionId=$actionId, additionalProperties=$additionalProperties}"
}
- class Success @JsonCreator private constructor(private val value: JsonField) : Enum {
-
- /**
- * Returns this class instance's raw value.
- *
- * This is usually only useful if this instance was deserialized from data that doesn't
- * match any known member, and you want to know that value. For example, if the SDK is on an
- * older version than the API, then the API may respond with new members that the SDK is
- * unaware of.
- */
- @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value
-
- companion object {
-
- val TRUE = of(true)
-
- fun of(value: Boolean) = Success(JsonField.of(value))
- }
-
- /** An enum containing [Success]'s known values. */
- enum class Known {
- TRUE
- }
-
- /**
- * An enum containing [Success]'s known values, as well as an [_UNKNOWN] member.
- *
- * An instance of [Success] can contain an unknown value in a couple of cases:
- * - It was deserialized from data that doesn't match any known member. For example, if the
- * SDK is on an older version than the API, then the API may respond with new members that
- * the SDK is unaware of.
- * - It was constructed with an arbitrary value using the [of] method.
- */
- enum class Value {
- TRUE,
- /** An enum member indicating that [Success] was instantiated with an unknown value. */
- _UNKNOWN,
- }
-
- /**
- * Returns an enum member corresponding to this class instance's value, or [Value._UNKNOWN]
- * if the class was instantiated with an unknown value.
- *
- * Use the [known] method instead if you're certain the value is always known or if you want
- * to throw for the unknown case.
- */
- fun value(): Value =
- when (this) {
- TRUE -> Value.TRUE
- else -> Value._UNKNOWN
- }
-
- /**
- * Returns an enum member corresponding to this class instance's value.
- *
- * Use the [value] method instead if you're uncertain the value is always known and don't
- * want to throw for the unknown case.
- *
- * @throws StagehandInvalidDataException if this class instance's value is a not a known
- * member.
- */
- fun known(): Known =
- when (this) {
- TRUE -> Known.TRUE
- else -> throw StagehandInvalidDataException("Unknown Success: $value")
- }
-
- /**
- * Returns this class instance's primitive wire representation.
- *
- * @throws StagehandInvalidDataException if this class instance's value does not have the
- * expected primitive type.
- */
- fun asBoolean(): Boolean =
- _value().asBoolean() ?: throw StagehandInvalidDataException("Value is not a Boolean")
-
- private var validated: Boolean = false
-
- fun validate(): Success = apply {
- if (validated) {
- return@apply
- }
-
- known()
- validated = true
- }
-
- fun isValid(): Boolean =
- try {
- validate()
- true
- } catch (e: StagehandInvalidDataException) {
- false
- }
-
- /**
- * Returns a score indicating how many valid values are contained in this object
- * recursively.
- *
- * Used for best match union deserialization.
- */
- internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1
-
- override fun equals(other: Any?): Boolean {
- if (this === other) {
- return true
- }
-
- return other is Success && value == other.value
- }
-
- override fun hashCode() = value.hashCode()
-
- override fun toString() = value.toString()
- }
-
override fun equals(other: Any?): Boolean {
if (this === other) {
return true
diff --git a/stagehand-kotlin-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionNavigateParams.kt b/stagehand-kotlin-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionNavigateParams.kt
index c61a8aa..ec1df26 100644
--- a/stagehand-kotlin-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionNavigateParams.kt
+++ b/stagehand-kotlin-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionNavigateParams.kt
@@ -71,6 +71,14 @@ private constructor(
*/
fun options(): Options? = body.options()
+ /**
+ * Whether to stream the response via SSE
+ *
+ * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if the
+ * server responded with an unexpected value).
+ */
+ fun streamResponse(): Boolean? = body.streamResponse()
+
/**
* Returns the raw JSON value of [url].
*
@@ -92,6 +100,13 @@ private constructor(
*/
fun _options(): JsonField = body._options()
+ /**
+ * Returns the raw JSON value of [streamResponse].
+ *
+ * Unlike [streamResponse], this method doesn't throw if the JSON field has an unexpected type.
+ */
+ fun _streamResponse(): JsonField = body._streamResponse()
+
fun _additionalBodyProperties(): Map = body._additionalProperties()
/** Additional headers to send with the request. */
@@ -163,6 +178,7 @@ private constructor(
* - [url]
* - [frameId]
* - [options]
+ * - [streamResponse]
*/
fun body(body: Body) = apply { this.body = body.toBuilder() }
@@ -198,6 +214,20 @@ private constructor(
*/
fun options(options: JsonField) = apply { body.options(options) }
+ /** Whether to stream the response via SSE */
+ fun streamResponse(streamResponse: Boolean) = apply { body.streamResponse(streamResponse) }
+
+ /**
+ * Sets [Builder.streamResponse] to an arbitrary JSON value.
+ *
+ * You should usually call [Builder.streamResponse] with a well-typed [Boolean] value
+ * instead. This method is primarily for setting the field to an undocumented or not yet
+ * supported value.
+ */
+ fun streamResponse(streamResponse: JsonField) = apply {
+ body.streamResponse(streamResponse)
+ }
+
fun additionalBodyProperties(additionalBodyProperties: Map) = apply {
body.additionalProperties(additionalBodyProperties)
}
@@ -367,6 +397,7 @@ private constructor(
private val url: JsonField,
private val frameId: JsonField,
private val options: JsonField,
+ private val streamResponse: JsonField,
private val additionalProperties: MutableMap,
) {
@@ -375,7 +406,10 @@ private constructor(
@JsonProperty("url") @ExcludeMissing url: JsonField = JsonMissing.of(),
@JsonProperty("frameId") @ExcludeMissing frameId: JsonField