From 13074f11bbc12057b60e89f37f850ca8f5bc7a83 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 17 Dec 2025 02:13:36 +0000 Subject: [PATCH 01/18] feat(api): manual updates --- .stats.yml | 6 +- README.md | 105 +- .../browserbase/api/models/sessions/Action.kt | 170 +- .../api/models/sessions/ModelConfig.kt | 579 +++--- .../api/models/sessions/SessionActParams.kt | 1233 ------------- .../api/models/sessions/SessionActResponse.kt | 269 --- .../api/models/sessions/SessionEndParams.kt | 229 --- .../api/models/sessions/SessionEndResponse.kt | 153 -- .../sessions/SessionExecuteAgentParams.kt | 1547 ----------------- .../sessions/SessionExecuteAgentResponse.kt | 158 -- .../models/sessions/SessionExtractParams.kt | 1064 ------------ .../models/sessions/SessionExtractResponse.kt | 457 ----- .../models/sessions/SessionNavigateParams.kt | 992 ----------- .../sessions/SessionNavigateResponse.kt | 216 --- .../models/sessions/SessionObserveParams.kt | 902 ---------- .../api/models/sessions/SessionStartParams.kt | 758 +------- .../models/sessions/SessionStartResponse.kt | 115 +- .../api/services/async/SessionServiceAsync.kt | 444 +---- .../services/async/SessionServiceAsyncImpl.kt | 261 --- .../api/services/blocking/SessionService.kt | 441 +---- .../services/blocking/SessionServiceImpl.kt | 237 --- .../api/models/sessions/ActionTest.kt | 28 +- .../api/models/sessions/ModelConfigTest.kt | 68 +- .../models/sessions/SessionActParamsTest.kt | 166 -- .../models/sessions/SessionActResponseTest.kt | 69 - .../models/sessions/SessionEndParamsTest.kt | 24 - .../models/sessions/SessionEndResponseTest.kt | 32 - .../sessions/SessionExecuteAgentParamsTest.kt | 170 -- .../SessionExecuteAgentResponseTest.kt | 34 - .../sessions/SessionExtractParamsTest.kt | 158 -- .../sessions/SessionExtractResponseTest.kt | 94 - .../sessions/SessionNavigateParamsTest.kt | 111 -- .../sessions/SessionNavigateResponseTest.kt | 36 - .../sessions/SessionObserveParamsTest.kt | 136 -- .../models/sessions/SessionStartParamsTest.kt | 66 +- .../sessions/SessionStartResponseTest.kt | 16 +- .../api/services/ErrorHandlingTest.kt | 204 +-- .../api/services/ServiceParamsTest.kt | 61 +- .../services/async/SessionServiceAsyncTest.kt | 238 +-- .../services/blocking/SessionServiceTest.kt | 232 +-- .../api/proguard/ProGuardCompatibilityTest.kt | 26 +- 41 files changed, 738 insertions(+), 11567 deletions(-) delete mode 100644 stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionActParams.kt delete mode 100644 stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionActResponse.kt delete mode 100644 stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionEndParams.kt delete mode 100644 stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionEndResponse.kt delete mode 100644 stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionExecuteAgentParams.kt delete mode 100644 stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionExecuteAgentResponse.kt delete mode 100644 stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionExtractParams.kt delete mode 100644 stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionExtractResponse.kt delete mode 100644 stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionNavigateParams.kt delete mode 100644 stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionNavigateResponse.kt delete mode 100644 stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionObserveParams.kt delete mode 100644 stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionActParamsTest.kt delete mode 100644 stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionActResponseTest.kt delete mode 100644 stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionEndParamsTest.kt delete mode 100644 stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionEndResponseTest.kt delete mode 100644 stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionExecuteAgentParamsTest.kt delete mode 100644 stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionExecuteAgentResponseTest.kt delete mode 100644 stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionExtractParamsTest.kt delete mode 100644 stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionExtractResponseTest.kt delete mode 100644 stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionNavigateParamsTest.kt delete mode 100644 stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionNavigateResponseTest.kt delete mode 100644 stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionObserveParamsTest.kt diff --git a/.stats.yml b/.stats.yml index 36782ae..f5e93e0 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-705638ac8966569986bd9ebb7c9761bf0016909e9f2753e77ceabb12c8049511.yml -openapi_spec_hash: a8fbbcaa38e91c7f97313620b42d8d62 +configured_endpoints: 1 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/browserbase%2Fstagehand-516862e7e90968bc55ac44ce7ffe2d5c1f738c11757471c2b9e0e4cff9384f2c.yml +openapi_spec_hash: 19bbe52a6ae0eec7fc3f6698e831ee55 config_hash: a35b56eb05306a0f02e83c11d57f975f diff --git a/README.md b/README.md index c383ecb..ae4e26a 100644 --- a/README.md +++ b/README.md @@ -48,18 +48,14 @@ This library requires Java 8 or later. ```java import com.browserbase.api.client.StagehandClient; import com.browserbase.api.client.okhttp.StagehandOkHttpClient; -import com.browserbase.api.models.sessions.SessionActParams; -import com.browserbase.api.models.sessions.SessionActResponse; +import com.browserbase.api.models.sessions.SessionStartParams; +import com.browserbase.api.models.sessions.SessionStartResponse; // Configures using the `stagehand.browserbaseApiKey`, `stagehand.browserbaseProjectId`, `stagehand.modelApiKey` and `stagehand.baseUrl` system properties // Or configures using the `BROWSERBASE_API_KEY`, `BROWSERBASE_PROJECT_ID`, `MODEL_API_KEY` and `STAGEHAND_BASE_URL` environment variables StagehandClient client = StagehandOkHttpClient.fromEnv(); -SessionActParams params = SessionActParams.builder() - .sessionId("00000000-your-session-id-000000000000") - .input("click the first link on the page") - .build(); -SessionActResponse response = client.sessions().act(params); +SessionStartResponse response = client.sessions().start(); ``` ## Client configuration @@ -136,7 +132,7 @@ The `withOptions()` method does not affect the original client or service. To send a request to the Stagehand API, build an instance of some `Params` class and pass it to the corresponding client method. When the response is received, it will be deserialized into an instance of a Java class. -For example, `client.sessions().act(...)` should be called with an instance of `SessionActParams`, and it will return an instance of `SessionActResponse`. +For example, `client.sessions().start(...)` should be called with an instance of `SessionStartParams`, and it will return an instance of `SessionStartResponse`. ## Immutability @@ -153,19 +149,15 @@ The default client is synchronous. To switch to asynchronous execution, call the ```java import com.browserbase.api.client.StagehandClient; import com.browserbase.api.client.okhttp.StagehandOkHttpClient; -import com.browserbase.api.models.sessions.SessionActParams; -import com.browserbase.api.models.sessions.SessionActResponse; +import com.browserbase.api.models.sessions.SessionStartParams; +import com.browserbase.api.models.sessions.SessionStartResponse; import java.util.concurrent.CompletableFuture; // Configures using the `stagehand.browserbaseApiKey`, `stagehand.browserbaseProjectId`, `stagehand.modelApiKey` and `stagehand.baseUrl` system properties // Or configures using the `BROWSERBASE_API_KEY`, `BROWSERBASE_PROJECT_ID`, `MODEL_API_KEY` and `STAGEHAND_BASE_URL` environment variables StagehandClient client = StagehandOkHttpClient.fromEnv(); -SessionActParams params = SessionActParams.builder() - .sessionId("00000000-your-session-id-000000000000") - .input("click the first link on the page") - .build(); -CompletableFuture response = client.async().sessions().act(params); +CompletableFuture response = client.async().sessions().start(); ``` Or create an asynchronous client from the beginning: @@ -173,19 +165,15 @@ Or create an asynchronous client from the beginning: ```java import com.browserbase.api.client.StagehandClientAsync; import com.browserbase.api.client.okhttp.StagehandOkHttpClientAsync; -import com.browserbase.api.models.sessions.SessionActParams; -import com.browserbase.api.models.sessions.SessionActResponse; +import com.browserbase.api.models.sessions.SessionStartParams; +import com.browserbase.api.models.sessions.SessionStartResponse; import java.util.concurrent.CompletableFuture; // Configures using the `stagehand.browserbaseApiKey`, `stagehand.browserbaseProjectId`, `stagehand.modelApiKey` and `stagehand.baseUrl` system properties // Or configures using the `BROWSERBASE_API_KEY`, `BROWSERBASE_PROJECT_ID`, `MODEL_API_KEY` and `STAGEHAND_BASE_URL` environment variables StagehandClientAsync client = StagehandOkHttpClientAsync.fromEnv(); -SessionActParams params = SessionActParams.builder() - .sessionId("00000000-your-session-id-000000000000") - .input("click the first link on the page") - .build(); -CompletableFuture response = client.sessions().act(params); +CompletableFuture response = client.sessions().start(); ``` The asynchronous client supports the same options as the synchronous one, except most methods return `CompletableFuture`s. @@ -202,11 +190,7 @@ import com.browserbase.api.core.http.HttpResponseFor; import com.browserbase.api.models.sessions.SessionStartParams; import com.browserbase.api.models.sessions.SessionStartResponse; -SessionStartParams params = SessionStartParams.builder() - .browserbaseApiKey("your Browserbase API key") - .browserbaseProjectId("your Browserbase Project ID") - .build(); -HttpResponseFor response = client.sessions().withRawResponse().start(params); +HttpResponseFor response = client.sessions().withRawResponse().start(); int statusCode = response.statusCode(); Headers headers = response.headers(); @@ -315,9 +299,7 @@ To set a custom timeout, configure the method call using the `timeout` method: ```java import com.browserbase.api.models.sessions.SessionStartResponse; -SessionStartResponse response = client.sessions().start( - params, RequestOptions.builder().timeout(Duration.ofSeconds(30)).build() -); +SessionStartResponse response = client.sessions().start(RequestOptions.builder().timeout(Duration.ofSeconds(30)).build()); ``` Or configure the default for all method calls at the client level: @@ -420,9 +402,9 @@ To set undocumented parameters, call the `putAdditionalHeader`, `putAdditionalQu ```java import com.browserbase.api.core.JsonValue; -import com.browserbase.api.models.sessions.SessionActParams; +import com.browserbase.api.models.sessions.SessionStartParams; -SessionActParams params = SessionActParams.builder() +SessionStartParams params = SessionStartParams.builder() .putAdditionalHeader("Secret-Header", "42") .putAdditionalQueryParam("secret_query_param", "42") .putAdditionalBodyProperty("secretProperty", JsonValue.from("42")) @@ -431,30 +413,12 @@ SessionActParams params = SessionActParams.builder() These can be accessed on the built object later using the `_additionalHeaders()`, `_additionalQueryParams()`, and `_additionalBodyProperties()` methods. -To set undocumented parameters on _nested_ headers, query params, or body classes, call the `putAdditionalProperty` method on the nested class: - -```java -import com.browserbase.api.core.JsonValue; -import com.browserbase.api.models.sessions.SessionActParams; - -SessionActParams params = SessionActParams.builder() - .options(SessionActParams.Options.builder() - .putAdditionalProperty("secretProperty", JsonValue.from("42")) - .build()) - .build(); -``` - -These properties can be accessed on the nested built object later using the `_additionalProperties()` method. - To set a documented parameter or property to an undocumented or not yet supported _value_, pass a [`JsonValue`](stagehand-java-core/src/main/kotlin/com/browserbase/api/core/Values.kt) object to its setter: ```java -import com.browserbase.api.core.JsonValue; -import com.browserbase.api.models.sessions.SessionActParams; +import com.browserbase.api.models.sessions.SessionStartParams; -SessionActParams params = SessionActParams.builder() - .input(JsonValue.from(42)) - .build(); +SessionStartParams params = SessionStartParams.builder().build(); ``` The most straightforward way to create a [`JsonValue`](stagehand-java-core/src/main/kotlin/com/browserbase/api/core/Values.kt) is using its `from(...)` method: @@ -496,20 +460,6 @@ JsonValue complexValue = JsonValue.from(Map.of( )); ``` -Normally a `Builder` class's `build` method will throw [`IllegalStateException`](https://docs.oracle.com/javase/8/docs/api/java/lang/IllegalStateException.html) if any required parameter or property is unset. - -To forcibly omit a required parameter or property, pass [`JsonMissing`](stagehand-java-core/src/main/kotlin/com/browserbase/api/core/Values.kt): - -```java -import com.browserbase.api.core.JsonMissing; -import com.browserbase.api.models.sessions.SessionActParams; - -SessionActParams params = SessionActParams.builder() - .input("click the sign in button") - .sessionId(JsonMissing.of()) - .build(); -``` - ### Response properties To access undocumented response properties, call the `_additionalProperties()` method: @@ -518,7 +468,7 @@ To access undocumented response properties, call the `_additionalProperties()` m import com.browserbase.api.core.JsonValue; import java.util.Map; -Map additionalProperties = client.sessions().act(params)._additionalProperties(); +Map additionalProperties = client.sessions().start(params)._additionalProperties(); JsonValue secretPropertyValue = additionalProperties.get("secretProperty"); String result = secretPropertyValue.accept(new JsonValue.Visitor<>() { @@ -546,22 +496,21 @@ To access a property's raw JSON value, which may be undocumented, call its `_` p ```java import com.browserbase.api.core.JsonField; -import com.browserbase.api.models.sessions.SessionActParams; import java.util.Optional; -JsonField input = client.sessions().act(params)._input(); +JsonField field = client.sessions().start(params)._field(); -if (input.isMissing()) { +if (field.isMissing()) { // The property is absent from the JSON response -} else if (input.isNull()) { +} else if (field.isNull()) { // The property was set to literal null } else { // Check if value was provided as a string // Other methods include `asNumber()`, `asBoolean()`, etc. - Optional jsonString = input.asString(); + Optional jsonString = field.asString(); // Try to deserialize into a custom type - MyClass myObject = input.asUnknown().orElseThrow().convert(MyClass.class); + MyClass myObject = field.asUnknown().orElseThrow().convert(MyClass.class); } ``` @@ -574,19 +523,17 @@ By default, the SDK will not throw an exception in this case. It will throw [`St If you would prefer to check that the response is completely well-typed upfront, then either call `validate()`: ```java -import com.browserbase.api.models.sessions.SessionActResponse; +import com.browserbase.api.models.sessions.SessionStartResponse; -SessionActResponse response = client.sessions().act(params).validate(); +SessionStartResponse response = client.sessions().start(params).validate(); ``` Or configure the method call to validate the response using the `responseValidation` method: ```java -import com.browserbase.api.models.sessions.SessionActResponse; +import com.browserbase.api.models.sessions.SessionStartResponse; -SessionActResponse response = client.sessions().act( - params, RequestOptions.builder().responseValidation(true).build() -); +SessionStartResponse response = client.sessions().start(RequestOptions.builder().responseValidation(true).build()); ``` Or configure the default for all method calls at the client level: diff --git a/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/Action.kt b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/Action.kt index d30a40b..e9ae4bc 100644 --- a/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/Action.kt +++ b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/Action.kt @@ -19,39 +19,28 @@ import java.util.Objects import java.util.Optional import kotlin.jvm.optionals.getOrNull +/** Action object returned by observe and used by act */ class Action @JsonCreator(mode = JsonCreator.Mode.DISABLED) private constructor( - private val arguments: JsonField>, private val description: JsonField, - private val method: JsonField, private val selector: JsonField, - private val backendNodeId: JsonField, + private val arguments: JsonField>, + private val method: JsonField, private val additionalProperties: MutableMap, ) { @JsonCreator private constructor( - @JsonProperty("arguments") - @ExcludeMissing - arguments: JsonField> = JsonMissing.of(), @JsonProperty("description") @ExcludeMissing description: JsonField = JsonMissing.of(), - @JsonProperty("method") @ExcludeMissing method: JsonField = JsonMissing.of(), @JsonProperty("selector") @ExcludeMissing selector: JsonField = JsonMissing.of(), - @JsonProperty("backendNodeId") + @JsonProperty("arguments") @ExcludeMissing - backendNodeId: JsonField = JsonMissing.of(), - ) : this(arguments, description, method, selector, backendNodeId, mutableMapOf()) - - /** - * Arguments for the method - * - * @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 arguments(): List = arguments.getRequired("arguments") + arguments: JsonField> = JsonMissing.of(), + @JsonProperty("method") @ExcludeMissing method: JsonField = JsonMissing.of(), + ) : this(description, selector, arguments, method, mutableMapOf()) /** * Human-readable description of the action @@ -62,15 +51,7 @@ private constructor( fun description(): String = description.getRequired("description") /** - * Method to execute (e.g., "click", "fill") - * - * @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 method(): String = method.getRequired("method") - - /** - * CSS or XPath selector for the element + * 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). @@ -78,19 +59,20 @@ private constructor( fun selector(): String = selector.getRequired("selector") /** - * CDP backend node ID + * 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 backendNodeId(): Optional = backendNodeId.getOptional("backendNodeId") + fun arguments(): Optional> = arguments.getOptional("arguments") /** - * Returns the raw JSON value of [arguments]. + * The method to execute (click, fill, etc.) * - * Unlike [arguments], this method doesn't throw if the JSON field has an unexpected type. + * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). */ - @JsonProperty("arguments") @ExcludeMissing fun _arguments(): JsonField> = arguments + fun method(): Optional = method.getOptional("method") /** * Returns the raw JSON value of [description]. @@ -100,27 +82,25 @@ private constructor( @JsonProperty("description") @ExcludeMissing fun _description(): JsonField = description /** - * Returns the raw JSON value of [method]. + * Returns the raw JSON value of [selector]. * - * Unlike [method], this method doesn't throw if the JSON field has an unexpected type. + * Unlike [selector], this method doesn't throw if the JSON field has an unexpected type. */ - @JsonProperty("method") @ExcludeMissing fun _method(): JsonField = method + @JsonProperty("selector") @ExcludeMissing fun _selector(): JsonField = selector /** - * Returns the raw JSON value of [selector]. + * Returns the raw JSON value of [arguments]. * - * Unlike [selector], this method doesn't throw if the JSON field has an unexpected type. + * Unlike [arguments], this method doesn't throw if the JSON field has an unexpected type. */ - @JsonProperty("selector") @ExcludeMissing fun _selector(): JsonField = selector + @JsonProperty("arguments") @ExcludeMissing fun _arguments(): JsonField> = arguments /** - * Returns the raw JSON value of [backendNodeId]. + * Returns the raw JSON value of [method]. * - * Unlike [backendNodeId], this method doesn't throw if the JSON field has an unexpected type. + * Unlike [method], this method doesn't throw if the JSON field has an unexpected type. */ - @JsonProperty("backendNodeId") - @ExcludeMissing - fun _backendNodeId(): JsonField = backendNodeId + @JsonProperty("method") @ExcludeMissing fun _method(): JsonField = method @JsonAnySetter private fun putAdditionalProperty(key: String, value: JsonValue) { @@ -141,9 +121,7 @@ private constructor( * * The following fields are required: * ```java - * .arguments() * .description() - * .method() * .selector() * ``` */ @@ -153,24 +131,45 @@ private constructor( /** A builder for [Action]. */ class Builder internal constructor() { - private var arguments: JsonField>? = null private var description: JsonField? = null - private var method: JsonField? = null private var selector: JsonField? = null - private var backendNodeId: JsonField = JsonMissing.of() + private var arguments: JsonField>? = null + private var method: JsonField = JsonMissing.of() private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic internal fun from(action: Action) = apply { - arguments = action.arguments.map { it.toMutableList() } description = action.description - method = action.method selector = action.selector - backendNodeId = action.backendNodeId + arguments = action.arguments.map { it.toMutableList() } + method = action.method additionalProperties = action.additionalProperties.toMutableMap() } - /** Arguments for the method */ + /** 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)) /** @@ -196,19 +195,7 @@ private constructor( } } - /** 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 } - - /** Method to execute (e.g., "click", "fill") */ + /** The method to execute (click, fill, etc.) */ fun method(method: String) = method(JsonField.of(method)) /** @@ -219,31 +206,6 @@ private constructor( */ fun method(method: JsonField) = apply { this.method = method } - /** CSS or XPath selector 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 } - - /** CDP backend node ID */ - fun backendNodeId(backendNodeId: Long) = backendNodeId(JsonField.of(backendNodeId)) - - /** - * Sets [Builder.backendNodeId] to an arbitrary JSON value. - * - * You should usually call [Builder.backendNodeId] with a well-typed [Long] 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 - } - fun additionalProperties(additionalProperties: Map) = apply { this.additionalProperties.clear() putAllAdditionalProperties(additionalProperties) @@ -270,9 +232,7 @@ private constructor( * * The following fields are required: * ```java - * .arguments() * .description() - * .method() * .selector() * ``` * @@ -280,11 +240,10 @@ private constructor( */ fun build(): Action = Action( - checkRequired("arguments", arguments).map { it.toImmutable() }, checkRequired("description", description), - checkRequired("method", method), checkRequired("selector", selector), - backendNodeId, + (arguments ?: JsonMissing.of()).map { it.toImmutable() }, + method, additionalProperties.toMutableMap(), ) } @@ -296,11 +255,10 @@ private constructor( return@apply } - arguments() description() - method() selector() - backendNodeId() + arguments() + method() validated = true } @@ -319,11 +277,10 @@ private constructor( */ @JvmSynthetic internal fun validity(): Int = - (arguments.asKnown().getOrNull()?.size ?: 0) + - (if (description.asKnown().isPresent) 1 else 0) + - (if (method.asKnown().isPresent) 1 else 0) + + (if (description.asKnown().isPresent) 1 else 0) + (if (selector.asKnown().isPresent) 1 else 0) + - (if (backendNodeId.asKnown().isPresent) 1 else 0) + (arguments.asKnown().getOrNull()?.size ?: 0) + + (if (method.asKnown().isPresent) 1 else 0) override fun equals(other: Any?): Boolean { if (this === other) { @@ -331,20 +288,19 @@ private constructor( } return other is Action && - arguments == other.arguments && description == other.description && - method == other.method && selector == other.selector && - backendNodeId == other.backendNodeId && + arguments == other.arguments && + method == other.method && additionalProperties == other.additionalProperties } private val hashCode: Int by lazy { - Objects.hash(arguments, description, method, selector, backendNodeId, additionalProperties) + Objects.hash(description, selector, arguments, method, additionalProperties) } override fun hashCode(): Int = hashCode override fun toString() = - "Action{arguments=$arguments, description=$description, method=$method, selector=$selector, backendNodeId=$backendNodeId, additionalProperties=$additionalProperties}" + "Action{description=$description, selector=$selector, arguments=$arguments, method=$method, additionalProperties=$additionalProperties}" } diff --git a/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/ModelConfig.kt b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/ModelConfig.kt index e08ebfa..0d210b0 100644 --- a/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/ModelConfig.kt +++ b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/ModelConfig.kt @@ -2,205 +2,61 @@ package com.browserbase.api.models.sessions -import com.browserbase.api.core.Enum +import com.browserbase.api.core.BaseDeserializer +import com.browserbase.api.core.BaseSerializer import com.browserbase.api.core.ExcludeMissing import com.browserbase.api.core.JsonField import com.browserbase.api.core.JsonMissing import com.browserbase.api.core.JsonValue +import com.browserbase.api.core.allMaxBy +import com.browserbase.api.core.checkRequired +import com.browserbase.api.core.getOrThrow import com.browserbase.api.errors.StagehandInvalidDataException import com.fasterxml.jackson.annotation.JsonAnyGetter import com.fasterxml.jackson.annotation.JsonAnySetter import com.fasterxml.jackson.annotation.JsonCreator import com.fasterxml.jackson.annotation.JsonProperty +import com.fasterxml.jackson.core.JsonGenerator +import com.fasterxml.jackson.core.ObjectCodec +import com.fasterxml.jackson.databind.JsonNode +import com.fasterxml.jackson.databind.SerializerProvider +import com.fasterxml.jackson.databind.annotation.JsonDeserialize +import com.fasterxml.jackson.databind.annotation.JsonSerialize +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef import java.util.Collections import java.util.Objects import java.util.Optional -import kotlin.jvm.optionals.getOrNull +@JsonDeserialize(using = ModelConfig.Deserializer::class) +@JsonSerialize(using = ModelConfig.Serializer::class) class ModelConfig -@JsonCreator(mode = JsonCreator.Mode.DISABLED) private constructor( - private val apiKey: JsonField, - private val baseUrl: JsonField, - private val model: JsonField, - private val provider: JsonField, - private val additionalProperties: MutableMap, + private val string: String? = null, + private val unionMember1: UnionMember1? = null, + private val _json: JsonValue? = null, ) { - @JsonCreator - private constructor( - @JsonProperty("apiKey") @ExcludeMissing apiKey: JsonField = JsonMissing.of(), - @JsonProperty("baseURL") @ExcludeMissing baseUrl: JsonField = JsonMissing.of(), - @JsonProperty("model") @ExcludeMissing model: JsonField = JsonMissing.of(), - @JsonProperty("provider") @ExcludeMissing provider: JsonField = JsonMissing.of(), - ) : this(apiKey, baseUrl, model, provider, mutableMapOf()) + fun string(): Optional = Optional.ofNullable(string) - /** - * 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(): Optional = apiKey.getOptional("apiKey") + fun unionMember1(): Optional = Optional.ofNullable(unionMember1) - /** - * Custom base URL for API - * - * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if the - * server responded with an unexpected value). - */ - fun baseUrl(): Optional = baseUrl.getOptional("baseURL") + fun isString(): Boolean = string != null - /** - * Model name - * - * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if the - * server responded with an unexpected value). - */ - fun model(): Optional = model.getOptional("model") + fun isUnionMember1(): Boolean = unionMember1 != null - /** - * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if the - * server responded with an unexpected value). - */ - fun provider(): Optional = provider.getOptional("provider") + fun asString(): String = string.getOrThrow("string") - /** - * Returns the raw JSON value of [apiKey]. - * - * Unlike [apiKey], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("apiKey") @ExcludeMissing fun _apiKey(): JsonField = apiKey + fun asUnionMember1(): UnionMember1 = unionMember1.getOrThrow("unionMember1") - /** - * Returns the raw JSON value of [baseUrl]. - * - * Unlike [baseUrl], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("baseURL") @ExcludeMissing fun _baseUrl(): JsonField = baseUrl + fun _json(): Optional = Optional.ofNullable(_json) - /** - * Returns the raw JSON value of [model]. - * - * Unlike [model], this method doesn't throw if the JSON field has an unexpected type. - */ - @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 - - @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 [ModelConfig]. */ - @JvmStatic fun builder() = Builder() - } - - /** A builder for [ModelConfig]. */ - class Builder internal constructor() { - - private var apiKey: JsonField = JsonMissing.of() - private var baseUrl: JsonField = JsonMissing.of() - private var model: JsonField = JsonMissing.of() - private var provider: JsonField = JsonMissing.of() - private var additionalProperties: MutableMap = mutableMapOf() - - @JvmSynthetic - internal fun from(modelConfig: ModelConfig) = apply { - apiKey = modelConfig.apiKey - baseUrl = modelConfig.baseUrl - model = modelConfig.model - provider = modelConfig.provider - additionalProperties = modelConfig.additionalProperties.toMutableMap() + fun accept(visitor: Visitor): T = + when { + string != null -> visitor.visitString(string) + unionMember1 != null -> visitor.visitUnionMember1(unionMember1) + else -> visitor.unknown(_json) } - /** API key for the model provider */ - fun apiKey(apiKey: String) = apiKey(JsonField.of(apiKey)) - - /** - * Sets [Builder.apiKey] to an arbitrary JSON value. - * - * You should usually call [Builder.apiKey] with a well-typed [String] value instead. This - * method is primarily for setting the field to an undocumented or not yet supported value. - */ - fun apiKey(apiKey: JsonField) = apply { this.apiKey = apiKey } - - /** Custom base URL for API */ - fun baseUrl(baseUrl: String) = baseUrl(JsonField.of(baseUrl)) - - /** - * Sets [Builder.baseUrl] to an arbitrary JSON value. - * - * You should usually call [Builder.baseUrl] with a well-typed [String] value instead. This - * method is primarily for setting the field to an undocumented or not yet supported value. - */ - fun baseUrl(baseUrl: JsonField) = apply { this.baseUrl = baseUrl } - - /** Model name */ - fun model(model: String) = model(JsonField.of(model)) - - /** - * Sets [Builder.model] to an arbitrary JSON value. - * - * You should usually call [Builder.model] with a well-typed [String] value instead. This - * method is primarily for setting the field to an undocumented or not yet supported value. - */ - fun model(model: JsonField) = apply { this.model = model } - - 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) - } - - 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 [ModelConfig]. - * - * Further updates to this [Builder] will not mutate the returned instance. - */ - fun build(): ModelConfig = - ModelConfig(apiKey, baseUrl, model, provider, additionalProperties.toMutableMap()) - } - private var validated: Boolean = false fun validate(): ModelConfig = apply { @@ -208,10 +64,15 @@ private constructor( return@apply } - apiKey() - baseUrl() - model() - provider().ifPresent { it.validate() } + accept( + object : Visitor { + override fun visitString(string: String) {} + + override fun visitUnionMember1(unionMember1: UnionMember1) { + unionMember1.validate() + } + } + ) validated = true } @@ -230,112 +91,291 @@ private constructor( */ @JvmSynthetic internal fun validity(): Int = - (if (apiKey.asKnown().isPresent) 1 else 0) + - (if (baseUrl.asKnown().isPresent) 1 else 0) + - (if (model.asKnown().isPresent) 1 else 0) + - (provider.asKnown().getOrNull()?.validity() ?: 0) + accept( + object : Visitor { + override fun visitString(string: String) = 1 - class Provider @JsonCreator private constructor(private val value: JsonField) : Enum { + override fun visitUnionMember1(unionMember1: UnionMember1) = unionMember1.validity() - /** - * 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 { + override fun unknown(json: JsonValue?) = 0 + } + ) - @JvmField val OPENAI = of("openai") + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } - @JvmField val ANTHROPIC = of("anthropic") + return other is ModelConfig && string == other.string && unionMember1 == other.unionMember1 + } - @JvmField val GOOGLE = of("google") + override fun hashCode(): Int = Objects.hash(string, unionMember1) - @JvmStatic fun of(value: String) = Provider(JsonField.of(value)) + override fun toString(): String = + when { + string != null -> "ModelConfig{string=$string}" + unionMember1 != null -> "ModelConfig{unionMember1=$unionMember1}" + _json != null -> "ModelConfig{_unknown=$_json}" + else -> throw IllegalStateException("Invalid ModelConfig") } - /** An enum containing [Provider]'s known values. */ - enum class Known { - OPENAI, - ANTHROPIC, - GOOGLE, - } + companion object { + + @JvmStatic fun ofString(string: String) = ModelConfig(string = string) + + @JvmStatic + fun ofUnionMember1(unionMember1: UnionMember1) = ModelConfig(unionMember1 = unionMember1) + } + + /** + * An interface that defines how to map each variant of [ModelConfig] to a value of type [T]. + */ + interface Visitor { + + fun visitString(string: String): T + + fun visitUnionMember1(unionMember1: UnionMember1): T /** - * An enum containing [Provider]'s known values, as well as an [_UNKNOWN] member. + * Maps an unknown variant of [ModelConfig] to a value of type [T]. + * + * An instance of [ModelConfig] can contain an unknown variant if it was deserialized from + * data that doesn't match any known variant. For example, if the SDK is on an older version + * than the API, then the API may respond with new variants that the SDK is unaware of. * - * 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. + * @throws StagehandInvalidDataException in the default implementation. */ - enum class Value { - OPENAI, - ANTHROPIC, - GOOGLE, - /** An enum member indicating that [Provider] was instantiated with an unknown value. */ - _UNKNOWN, + fun unknown(json: JsonValue?): T { + throw StagehandInvalidDataException("Unknown ModelConfig: $json") } + } + + internal class Deserializer : BaseDeserializer(ModelConfig::class) { + + override fun ObjectCodec.deserialize(node: JsonNode): ModelConfig { + val json = JsonValue.fromJsonNode(node) + + val bestMatches = + sequenceOf( + tryDeserialize(node, jacksonTypeRef())?.let { + ModelConfig(unionMember1 = it, _json = json) + }, + tryDeserialize(node, jacksonTypeRef())?.let { + ModelConfig(string = it, _json = json) + }, + ) + .filterNotNull() + .allMaxBy { it.validity() } + .toList() + return when (bestMatches.size) { + // This can happen if what we're deserializing is completely incompatible with all + // the possible variants (e.g. deserializing from array). + 0 -> ModelConfig(_json = json) + 1 -> bestMatches.single() + // If there's more than one match with the highest validity, then use the first + // completely valid match, or simply the first match if none are completely valid. + else -> bestMatches.firstOrNull { it.isValid() } ?: bestMatches.first() + } + } + } + + internal class Serializer : BaseSerializer(ModelConfig::class) { + + override fun serialize( + value: ModelConfig, + generator: JsonGenerator, + provider: SerializerProvider, + ) { + when { + value.string != null -> generator.writeObject(value.string) + value.unionMember1 != null -> generator.writeObject(value.unionMember1) + value._json != null -> generator.writeObject(value._json) + else -> throw IllegalStateException("Invalid ModelConfig") + } + } + } + + class UnionMember1 + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val modelName: JsonField, + private val apiKey: JsonField, + private val baseUrl: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("modelName") + @ExcludeMissing + modelName: JsonField = JsonMissing.of(), + @JsonProperty("apiKey") @ExcludeMissing apiKey: JsonField = JsonMissing.of(), + @JsonProperty("baseURL") @ExcludeMissing baseUrl: JsonField = JsonMissing.of(), + ) : this(modelName, apiKey, baseUrl, mutableMapOf()) /** - * 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. + * @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 value(): Value = - when (this) { - OPENAI -> Value.OPENAI - ANTHROPIC -> Value.ANTHROPIC - GOOGLE -> Value.GOOGLE - else -> Value._UNKNOWN - } + fun modelName(): String = modelName.getRequired("modelName") /** - * 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 the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun apiKey(): Optional = apiKey.getOptional("apiKey") + + /** + * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun baseUrl(): Optional = baseUrl.getOptional("baseURL") + + /** + * Returns the raw JSON value of [modelName]. * - * @throws StagehandInvalidDataException if this class instance's value is a not a known - * member. + * Unlike [modelName], this method doesn't throw if the JSON field has an unexpected type. */ - fun known(): Known = - when (this) { - OPENAI -> Known.OPENAI - ANTHROPIC -> Known.ANTHROPIC - GOOGLE -> Known.GOOGLE - else -> throw StagehandInvalidDataException("Unknown Provider: $value") - } + @JsonProperty("modelName") @ExcludeMissing fun _modelName(): JsonField = modelName /** - * Returns this class instance's primitive wire representation. + * Returns the raw JSON value of [apiKey]. * - * This differs from the [toString] method because that method is primarily for debugging - * and generally doesn't throw. + * Unlike [apiKey], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("apiKey") @ExcludeMissing fun _apiKey(): JsonField = apiKey + + /** + * Returns the raw JSON value of [baseUrl]. * - * @throws StagehandInvalidDataException if this class instance's value does not have the - * expected primitive type. + * Unlike [baseUrl], this method doesn't throw if the JSON field has an unexpected type. */ - fun asString(): String = - _value().asString().orElseThrow { - StagehandInvalidDataException("Value is not a String") + @JsonProperty("baseURL") @ExcludeMissing fun _baseUrl(): JsonField = baseUrl + + @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 [UnionMember1]. + * + * The following fields are required: + * ```java + * .modelName() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [UnionMember1]. */ + class Builder internal constructor() { + + private var modelName: JsonField? = null + private var apiKey: JsonField = JsonMissing.of() + private var baseUrl: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(unionMember1: UnionMember1) = apply { + modelName = unionMember1.modelName + apiKey = unionMember1.apiKey + baseUrl = unionMember1.baseUrl + additionalProperties = unionMember1.additionalProperties.toMutableMap() + } + + fun modelName(modelName: String) = modelName(JsonField.of(modelName)) + + /** + * Sets [Builder.modelName] to an arbitrary JSON value. + * + * You should usually call [Builder.modelName] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun modelName(modelName: JsonField) = apply { this.modelName = modelName } + + fun apiKey(apiKey: String) = apiKey(JsonField.of(apiKey)) + + /** + * Sets [Builder.apiKey] to an arbitrary JSON value. + * + * You should usually call [Builder.apiKey] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun apiKey(apiKey: JsonField) = apply { this.apiKey = apiKey } + + fun baseUrl(baseUrl: String) = baseUrl(JsonField.of(baseUrl)) + + /** + * Sets [Builder.baseUrl] to an arbitrary JSON value. + * + * You should usually call [Builder.baseUrl] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun baseUrl(baseUrl: JsonField) = apply { this.baseUrl = baseUrl } + + 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 [UnionMember1]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .modelName() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): UnionMember1 = + UnionMember1( + checkRequired("modelName", modelName), + apiKey, + baseUrl, + additionalProperties.toMutableMap(), + ) + } + private var validated: Boolean = false - fun validate(): Provider = apply { + fun validate(): UnionMember1 = apply { if (validated) { return@apply } - known() + modelName() + apiKey() + baseUrl() validated = true } @@ -353,40 +393,31 @@ private constructor( * * Used for best match union deserialization. */ - @JvmSynthetic internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1 + @JvmSynthetic + internal fun validity(): Int = + (if (modelName.asKnown().isPresent) 1 else 0) + + (if (apiKey.asKnown().isPresent) 1 else 0) + + (if (baseUrl.asKnown().isPresent) 1 else 0) override fun equals(other: Any?): Boolean { if (this === other) { return true } - return other is Provider && value == other.value + return other is UnionMember1 && + modelName == other.modelName && + apiKey == other.apiKey && + baseUrl == other.baseUrl && + additionalProperties == other.additionalProperties } - override fun hashCode() = value.hashCode() - - override fun toString() = value.toString() - } - - override fun equals(other: Any?): Boolean { - if (this === other) { - return true + private val hashCode: Int by lazy { + Objects.hash(modelName, apiKey, baseUrl, additionalProperties) } - return other is ModelConfig && - apiKey == other.apiKey && - baseUrl == other.baseUrl && - model == other.model && - provider == other.provider && - additionalProperties == other.additionalProperties - } + override fun hashCode(): Int = hashCode - private val hashCode: Int by lazy { - Objects.hash(apiKey, baseUrl, model, provider, additionalProperties) + override fun toString() = + "UnionMember1{modelName=$modelName, apiKey=$apiKey, baseUrl=$baseUrl, additionalProperties=$additionalProperties}" } - - override fun hashCode(): Int = hashCode - - override fun toString() = - "ModelConfig{apiKey=$apiKey, baseUrl=$baseUrl, model=$model, provider=$provider, additionalProperties=$additionalProperties}" } diff --git a/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionActParams.kt b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionActParams.kt deleted file mode 100644 index 34cae33..0000000 --- a/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionActParams.kt +++ /dev/null @@ -1,1233 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. - -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 -import com.browserbase.api.core.JsonValue -import com.browserbase.api.core.Params -import com.browserbase.api.core.allMaxBy -import com.browserbase.api.core.checkRequired -import com.browserbase.api.core.getOrThrow -import com.browserbase.api.core.http.Headers -import com.browserbase.api.core.http.QueryParams -import com.browserbase.api.core.toImmutable -import com.browserbase.api.errors.StagehandInvalidDataException -import com.fasterxml.jackson.annotation.JsonAnyGetter -import com.fasterxml.jackson.annotation.JsonAnySetter -import com.fasterxml.jackson.annotation.JsonCreator -import com.fasterxml.jackson.annotation.JsonProperty -import com.fasterxml.jackson.core.JsonGenerator -import com.fasterxml.jackson.core.ObjectCodec -import com.fasterxml.jackson.databind.JsonNode -import com.fasterxml.jackson.databind.SerializerProvider -import com.fasterxml.jackson.databind.annotation.JsonDeserialize -import com.fasterxml.jackson.databind.annotation.JsonSerialize -import com.fasterxml.jackson.module.kotlin.jacksonTypeRef -import java.util.Collections -import java.util.Objects -import java.util.Optional -import kotlin.jvm.optionals.getOrNull - -/** - * Performs a browser action based on natural language instruction or a specific action object - * returned by observe(). - */ -class SessionActParams -private constructor( - private val sessionId: String?, - private val xStreamResponse: XStreamResponse?, - private val body: Body, - private val additionalHeaders: Headers, - private val additionalQueryParams: QueryParams, -) : Params { - - fun sessionId(): Optional = Optional.ofNullable(sessionId) - - fun xStreamResponse(): Optional = Optional.ofNullable(xStreamResponse) - - /** - * Natural language instruction - * - * @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 input(): Input = body.input() - - /** - * Frame ID to act on (optional) - * - * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if the - * server responded with an unexpected value). - */ - fun frameId(): Optional = body.frameId() - - /** - * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if the - * server responded with an unexpected value). - */ - fun options(): Optional = body.options() - - /** - * Returns the raw JSON value of [input]. - * - * Unlike [input], this method doesn't throw if the JSON field has an unexpected type. - */ - fun _input(): JsonField = body._input() - - /** - * Returns the raw JSON value of [frameId]. - * - * Unlike [frameId], this method doesn't throw if the JSON field has an unexpected type. - */ - fun _frameId(): JsonField = body._frameId() - - /** - * Returns the raw JSON value of [options]. - * - * Unlike [options], this method doesn't throw if the JSON field has an unexpected type. - */ - fun _options(): JsonField = body._options() - - fun _additionalBodyProperties(): Map = body._additionalProperties() - - /** Additional headers to send with the request. */ - fun _additionalHeaders(): Headers = additionalHeaders - - /** Additional query param to send with the request. */ - fun _additionalQueryParams(): QueryParams = additionalQueryParams - - fun toBuilder() = Builder().from(this) - - companion object { - - /** - * Returns a mutable builder for constructing an instance of [SessionActParams]. - * - * The following fields are required: - * ```java - * .input() - * ``` - */ - @JvmStatic fun builder() = Builder() - } - - /** A builder for [SessionActParams]. */ - class Builder internal constructor() { - - private var sessionId: String? = null - private var xStreamResponse: XStreamResponse? = null - private var body: Body.Builder = Body.builder() - private var additionalHeaders: Headers.Builder = Headers.builder() - private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() - - @JvmSynthetic - internal fun from(sessionActParams: SessionActParams) = apply { - sessionId = sessionActParams.sessionId - xStreamResponse = sessionActParams.xStreamResponse - body = sessionActParams.body.toBuilder() - additionalHeaders = sessionActParams.additionalHeaders.toBuilder() - additionalQueryParams = sessionActParams.additionalQueryParams.toBuilder() - } - - fun sessionId(sessionId: String?) = apply { this.sessionId = sessionId } - - /** Alias for calling [Builder.sessionId] with `sessionId.orElse(null)`. */ - fun sessionId(sessionId: Optional) = sessionId(sessionId.getOrNull()) - - fun xStreamResponse(xStreamResponse: XStreamResponse?) = apply { - this.xStreamResponse = xStreamResponse - } - - /** Alias for calling [Builder.xStreamResponse] with `xStreamResponse.orElse(null)`. */ - fun xStreamResponse(xStreamResponse: Optional) = - xStreamResponse(xStreamResponse.getOrNull()) - - /** - * Sets the entire request body. - * - * This is generally only useful if you are already constructing the body separately. - * Otherwise, it's more convenient to use the top-level setters instead: - * - [input] - * - [frameId] - * - [options] - */ - fun body(body: Body) = apply { this.body = body.toBuilder() } - - /** Natural language instruction */ - fun input(input: Input) = apply { body.input(input) } - - /** - * Sets [Builder.input] to an arbitrary JSON value. - * - * You should usually call [Builder.input] with a well-typed [Input] value instead. This - * method is primarily for setting the field to an undocumented or not yet supported value. - */ - fun input(input: JsonField) = apply { body.input(input) } - - /** Alias for calling [input] with `Input.ofString(string)`. */ - fun input(string: String) = apply { body.input(string) } - - /** Alias for calling [input] with `Input.ofAction(action)`. */ - fun input(action: Action) = apply { body.input(action) } - - /** Frame ID to act on (optional) */ - fun frameId(frameId: String) = apply { body.frameId(frameId) } - - /** - * Sets [Builder.frameId] to an arbitrary JSON value. - * - * You should usually call [Builder.frameId] with a well-typed [String] value instead. This - * method is primarily for setting the field to an undocumented or not yet supported value. - */ - fun frameId(frameId: JsonField) = apply { body.frameId(frameId) } - - fun options(options: Options) = apply { body.options(options) } - - /** - * Sets [Builder.options] to an arbitrary JSON value. - * - * You should usually call [Builder.options] with a well-typed [Options] value instead. This - * method is primarily for setting the field to an undocumented or not yet supported value. - */ - fun options(options: JsonField) = apply { body.options(options) } - - fun additionalBodyProperties(additionalBodyProperties: Map) = apply { - body.additionalProperties(additionalBodyProperties) - } - - fun putAdditionalBodyProperty(key: String, value: JsonValue) = apply { - body.putAdditionalProperty(key, value) - } - - fun putAllAdditionalBodyProperties(additionalBodyProperties: Map) = - apply { - body.putAllAdditionalProperties(additionalBodyProperties) - } - - fun removeAdditionalBodyProperty(key: String) = apply { body.removeAdditionalProperty(key) } - - fun removeAllAdditionalBodyProperties(keys: Set) = apply { - body.removeAllAdditionalProperties(keys) - } - - fun additionalHeaders(additionalHeaders: Headers) = apply { - this.additionalHeaders.clear() - putAllAdditionalHeaders(additionalHeaders) - } - - fun additionalHeaders(additionalHeaders: Map>) = apply { - this.additionalHeaders.clear() - putAllAdditionalHeaders(additionalHeaders) - } - - fun putAdditionalHeader(name: String, value: String) = apply { - additionalHeaders.put(name, value) - } - - fun putAdditionalHeaders(name: String, values: Iterable) = apply { - additionalHeaders.put(name, values) - } - - fun putAllAdditionalHeaders(additionalHeaders: Headers) = apply { - this.additionalHeaders.putAll(additionalHeaders) - } - - fun putAllAdditionalHeaders(additionalHeaders: Map>) = apply { - this.additionalHeaders.putAll(additionalHeaders) - } - - fun replaceAdditionalHeaders(name: String, value: String) = apply { - additionalHeaders.replace(name, value) - } - - fun replaceAdditionalHeaders(name: String, values: Iterable) = apply { - additionalHeaders.replace(name, values) - } - - fun replaceAllAdditionalHeaders(additionalHeaders: Headers) = apply { - this.additionalHeaders.replaceAll(additionalHeaders) - } - - fun replaceAllAdditionalHeaders(additionalHeaders: Map>) = apply { - this.additionalHeaders.replaceAll(additionalHeaders) - } - - fun removeAdditionalHeaders(name: String) = apply { additionalHeaders.remove(name) } - - fun removeAllAdditionalHeaders(names: Set) = apply { - additionalHeaders.removeAll(names) - } - - fun additionalQueryParams(additionalQueryParams: QueryParams) = apply { - this.additionalQueryParams.clear() - putAllAdditionalQueryParams(additionalQueryParams) - } - - fun additionalQueryParams(additionalQueryParams: Map>) = apply { - this.additionalQueryParams.clear() - putAllAdditionalQueryParams(additionalQueryParams) - } - - fun putAdditionalQueryParam(key: String, value: String) = apply { - additionalQueryParams.put(key, value) - } - - fun putAdditionalQueryParams(key: String, values: Iterable) = apply { - additionalQueryParams.put(key, values) - } - - fun putAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { - this.additionalQueryParams.putAll(additionalQueryParams) - } - - fun putAllAdditionalQueryParams(additionalQueryParams: Map>) = - apply { - this.additionalQueryParams.putAll(additionalQueryParams) - } - - fun replaceAdditionalQueryParams(key: String, value: String) = apply { - additionalQueryParams.replace(key, value) - } - - fun replaceAdditionalQueryParams(key: String, values: Iterable) = apply { - additionalQueryParams.replace(key, values) - } - - fun replaceAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { - this.additionalQueryParams.replaceAll(additionalQueryParams) - } - - fun replaceAllAdditionalQueryParams(additionalQueryParams: Map>) = - apply { - this.additionalQueryParams.replaceAll(additionalQueryParams) - } - - fun removeAdditionalQueryParams(key: String) = apply { additionalQueryParams.remove(key) } - - fun removeAllAdditionalQueryParams(keys: Set) = apply { - additionalQueryParams.removeAll(keys) - } - - /** - * Returns an immutable instance of [SessionActParams]. - * - * Further updates to this [Builder] will not mutate the returned instance. - * - * The following fields are required: - * ```java - * .input() - * ``` - * - * @throws IllegalStateException if any required field is unset. - */ - fun build(): SessionActParams = - SessionActParams( - sessionId, - xStreamResponse, - body.build(), - additionalHeaders.build(), - additionalQueryParams.build(), - ) - } - - fun _body(): Body = body - - fun _pathParam(index: Int): String = - when (index) { - 0 -> sessionId ?: "" - else -> "" - } - - override fun _headers(): Headers = - Headers.builder() - .apply { - xStreamResponse?.let { put("x-stream-response", it.toString()) } - putAll(additionalHeaders) - } - .build() - - override fun _queryParams(): QueryParams = additionalQueryParams - - class Body - @JsonCreator(mode = JsonCreator.Mode.DISABLED) - private constructor( - private val input: JsonField, - private val frameId: JsonField, - private val options: JsonField, - private val additionalProperties: MutableMap, - ) { - - @JsonCreator - private constructor( - @JsonProperty("input") @ExcludeMissing input: JsonField = JsonMissing.of(), - @JsonProperty("frameId") @ExcludeMissing frameId: JsonField = JsonMissing.of(), - @JsonProperty("options") @ExcludeMissing options: JsonField = JsonMissing.of(), - ) : this(input, frameId, options, mutableMapOf()) - - /** - * Natural language instruction - * - * @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 input(): Input = input.getRequired("input") - - /** - * Frame ID to act on (optional) - * - * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if - * the server responded with an unexpected value). - */ - fun frameId(): Optional = frameId.getOptional("frameId") - - /** - * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if - * the server responded with an unexpected value). - */ - fun options(): Optional = options.getOptional("options") - - /** - * Returns the raw JSON value of [input]. - * - * Unlike [input], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("input") @ExcludeMissing fun _input(): JsonField = input - - /** - * Returns the raw JSON value of [frameId]. - * - * Unlike [frameId], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("frameId") @ExcludeMissing fun _frameId(): JsonField = frameId - - /** - * Returns the raw JSON value of [options]. - * - * Unlike [options], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("options") @ExcludeMissing fun _options(): JsonField = options - - @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 [Body]. - * - * The following fields are required: - * ```java - * .input() - * ``` - */ - @JvmStatic fun builder() = Builder() - } - - /** A builder for [Body]. */ - class Builder internal constructor() { - - private var input: JsonField? = null - private var frameId: JsonField = JsonMissing.of() - private var options: JsonField = JsonMissing.of() - private var additionalProperties: MutableMap = mutableMapOf() - - @JvmSynthetic - internal fun from(body: Body) = apply { - input = body.input - frameId = body.frameId - options = body.options - additionalProperties = body.additionalProperties.toMutableMap() - } - - /** Natural language instruction */ - fun input(input: Input) = input(JsonField.of(input)) - - /** - * Sets [Builder.input] to an arbitrary JSON value. - * - * You should usually call [Builder.input] with a well-typed [Input] value instead. This - * method is primarily for setting the field to an undocumented or not yet supported - * value. - */ - fun input(input: JsonField) = apply { this.input = input } - - /** Alias for calling [input] with `Input.ofString(string)`. */ - fun input(string: String) = input(Input.ofString(string)) - - /** Alias for calling [input] with `Input.ofAction(action)`. */ - fun input(action: Action) = input(Input.ofAction(action)) - - /** Frame ID to act on (optional) */ - fun frameId(frameId: String) = frameId(JsonField.of(frameId)) - - /** - * Sets [Builder.frameId] to an arbitrary JSON value. - * - * You should usually call [Builder.frameId] with a well-typed [String] value instead. - * This method is primarily for setting the field to an undocumented or not yet - * supported value. - */ - fun frameId(frameId: JsonField) = apply { this.frameId = frameId } - - fun options(options: Options) = options(JsonField.of(options)) - - /** - * Sets [Builder.options] to an arbitrary JSON value. - * - * You should usually call [Builder.options] with a well-typed [Options] value instead. - * This method is primarily for setting the field to an undocumented or not yet - * supported value. - */ - fun options(options: JsonField) = apply { this.options = options } - - 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 [Body]. - * - * Further updates to this [Builder] will not mutate the returned instance. - * - * The following fields are required: - * ```java - * .input() - * ``` - * - * @throws IllegalStateException if any required field is unset. - */ - fun build(): Body = - Body( - checkRequired("input", input), - frameId, - options, - additionalProperties.toMutableMap(), - ) - } - - private var validated: Boolean = false - - fun validate(): Body = apply { - if (validated) { - return@apply - } - - input().validate() - frameId() - options().ifPresent { it.validate() } - 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. - */ - @JvmSynthetic - internal fun validity(): Int = - (input.asKnown().getOrNull()?.validity() ?: 0) + - (if (frameId.asKnown().isPresent) 1 else 0) + - (options.asKnown().getOrNull()?.validity() ?: 0) - - override fun equals(other: Any?): Boolean { - if (this === other) { - return true - } - - return other is Body && - input == other.input && - frameId == other.frameId && - options == other.options && - additionalProperties == other.additionalProperties - } - - private val hashCode: Int by lazy { - Objects.hash(input, frameId, options, additionalProperties) - } - - override fun hashCode(): Int = hashCode - - override fun toString() = - "Body{input=$input, frameId=$frameId, options=$options, additionalProperties=$additionalProperties}" - } - - /** Natural language instruction */ - @JsonDeserialize(using = Input.Deserializer::class) - @JsonSerialize(using = Input.Serializer::class) - class Input - private constructor( - private val string: String? = null, - private val action: Action? = null, - private val _json: JsonValue? = null, - ) { - - /** Natural language instruction */ - fun string(): Optional = Optional.ofNullable(string) - - fun action(): Optional = Optional.ofNullable(action) - - fun isString(): Boolean = string != null - - fun isAction(): Boolean = action != null - - /** Natural language instruction */ - fun asString(): String = string.getOrThrow("string") - - fun asAction(): Action = action.getOrThrow("action") - - fun _json(): Optional = Optional.ofNullable(_json) - - fun accept(visitor: Visitor): T = - when { - string != null -> visitor.visitString(string) - action != null -> visitor.visitAction(action) - else -> visitor.unknown(_json) - } - - private var validated: Boolean = false - - fun validate(): Input = apply { - if (validated) { - return@apply - } - - accept( - object : Visitor { - override fun visitString(string: String) {} - - override fun visitAction(action: Action) { - action.validate() - } - } - ) - 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. - */ - @JvmSynthetic - internal fun validity(): Int = - accept( - object : Visitor { - override fun visitString(string: String) = 1 - - override fun visitAction(action: Action) = action.validity() - - override fun unknown(json: JsonValue?) = 0 - } - ) - - override fun equals(other: Any?): Boolean { - if (this === other) { - return true - } - - return other is Input && string == other.string && action == other.action - } - - override fun hashCode(): Int = Objects.hash(string, action) - - override fun toString(): String = - when { - string != null -> "Input{string=$string}" - action != null -> "Input{action=$action}" - _json != null -> "Input{_unknown=$_json}" - else -> throw IllegalStateException("Invalid Input") - } - - companion object { - - /** Natural language instruction */ - @JvmStatic fun ofString(string: String) = Input(string = string) - - @JvmStatic fun ofAction(action: Action) = Input(action = action) - } - - /** An interface that defines how to map each variant of [Input] to a value of type [T]. */ - interface Visitor { - - /** Natural language instruction */ - fun visitString(string: String): T - - fun visitAction(action: Action): T - - /** - * Maps an unknown variant of [Input] to a value of type [T]. - * - * An instance of [Input] can contain an unknown variant if it was deserialized from - * data that doesn't match any known variant. For example, if the SDK is on an older - * version than the API, then the API may respond with new variants that the SDK is - * unaware of. - * - * @throws StagehandInvalidDataException in the default implementation. - */ - fun unknown(json: JsonValue?): T { - throw StagehandInvalidDataException("Unknown Input: $json") - } - } - - internal class Deserializer : BaseDeserializer(Input::class) { - - override fun ObjectCodec.deserialize(node: JsonNode): Input { - val json = JsonValue.fromJsonNode(node) - - val bestMatches = - sequenceOf( - tryDeserialize(node, jacksonTypeRef())?.let { - Input(action = it, _json = json) - }, - tryDeserialize(node, jacksonTypeRef())?.let { - Input(string = it, _json = json) - }, - ) - .filterNotNull() - .allMaxBy { it.validity() } - .toList() - return when (bestMatches.size) { - // This can happen if what we're deserializing is completely incompatible with - // all the possible variants (e.g. deserializing from array). - 0 -> Input(_json = json) - 1 -> bestMatches.single() - // If there's more than one match with the highest validity, then use the first - // completely valid match, or simply the first match if none are completely - // valid. - else -> bestMatches.firstOrNull { it.isValid() } ?: bestMatches.first() - } - } - } - - internal class Serializer : BaseSerializer(Input::class) { - - override fun serialize( - value: Input, - generator: JsonGenerator, - provider: SerializerProvider, - ) { - when { - value.string != null -> generator.writeObject(value.string) - value.action != null -> generator.writeObject(value.action) - value._json != null -> generator.writeObject(value._json) - else -> throw IllegalStateException("Invalid Input") - } - } - } - } - - class Options - @JsonCreator(mode = JsonCreator.Mode.DISABLED) - private constructor( - private val model: JsonField, - private val timeout: JsonField, - private val variables: JsonField, - private val additionalProperties: MutableMap, - ) { - - @JsonCreator - private constructor( - @JsonProperty("model") @ExcludeMissing model: JsonField = JsonMissing.of(), - @JsonProperty("timeout") @ExcludeMissing timeout: JsonField = JsonMissing.of(), - @JsonProperty("variables") - @ExcludeMissing - variables: JsonField = JsonMissing.of(), - ) : this(model, timeout, variables, mutableMapOf()) - - /** - * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if - * the server responded with an unexpected value). - */ - fun model(): Optional = model.getOptional("model") - - /** - * Timeout in milliseconds - * - * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if - * the server responded with an unexpected value). - */ - fun timeout(): Optional = timeout.getOptional("timeout") - - /** - * Template variables for instruction - * - * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if - * the server responded with an unexpected value). - */ - fun variables(): Optional = variables.getOptional("variables") - - /** - * Returns the raw JSON value of [model]. - * - * Unlike [model], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("model") @ExcludeMissing fun _model(): JsonField = model - - /** - * Returns the raw JSON value of [timeout]. - * - * Unlike [timeout], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("timeout") @ExcludeMissing fun _timeout(): JsonField = timeout - - /** - * Returns the raw JSON value of [variables]. - * - * Unlike [variables], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("variables") - @ExcludeMissing - fun _variables(): JsonField = variables - - @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 [Options]. */ - @JvmStatic fun builder() = Builder() - } - - /** A builder for [Options]. */ - class Builder internal constructor() { - - private var model: JsonField = JsonMissing.of() - private var timeout: JsonField = JsonMissing.of() - private var variables: JsonField = JsonMissing.of() - private var additionalProperties: MutableMap = mutableMapOf() - - @JvmSynthetic - internal fun from(options: Options) = apply { - model = options.model - timeout = options.timeout - variables = options.variables - additionalProperties = options.additionalProperties.toMutableMap() - } - - fun model(model: ModelConfig) = model(JsonField.of(model)) - - /** - * Sets [Builder.model] to an arbitrary JSON value. - * - * You should usually call [Builder.model] with a well-typed [ModelConfig] value - * instead. This method is primarily for setting the field to an undocumented or not yet - * supported value. - */ - fun model(model: JsonField) = apply { this.model = model } - - /** Timeout in milliseconds */ - fun timeout(timeout: Long) = timeout(JsonField.of(timeout)) - - /** - * Sets [Builder.timeout] to an arbitrary JSON value. - * - * You should usually call [Builder.timeout] with a well-typed [Long] value instead. - * This method is primarily for setting the field to an undocumented or not yet - * supported value. - */ - fun timeout(timeout: JsonField) = apply { this.timeout = timeout } - - /** Template variables for instruction */ - fun variables(variables: Variables) = variables(JsonField.of(variables)) - - /** - * Sets [Builder.variables] to an arbitrary JSON value. - * - * You should usually call [Builder.variables] with a well-typed [Variables] value - * instead. This method is primarily for setting the field to an undocumented or not yet - * supported value. - */ - fun variables(variables: JsonField) = apply { this.variables = variables } - - 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 [Options]. - * - * Further updates to this [Builder] will not mutate the returned instance. - */ - fun build(): Options = - Options(model, timeout, variables, additionalProperties.toMutableMap()) - } - - private var validated: Boolean = false - - fun validate(): Options = apply { - if (validated) { - return@apply - } - - model().ifPresent { it.validate() } - timeout() - variables().ifPresent { it.validate() } - 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. - */ - @JvmSynthetic - internal fun validity(): Int = - (model.asKnown().getOrNull()?.validity() ?: 0) + - (if (timeout.asKnown().isPresent) 1 else 0) + - (variables.asKnown().getOrNull()?.validity() ?: 0) - - /** Template variables for instruction */ - class Variables - @JsonCreator - private constructor( - @com.fasterxml.jackson.annotation.JsonValue - private val additionalProperties: Map - ) { - - @JsonAnyGetter - @ExcludeMissing - fun _additionalProperties(): Map = additionalProperties - - fun toBuilder() = Builder().from(this) - - companion object { - - /** Returns a mutable builder for constructing an instance of [Variables]. */ - @JvmStatic fun builder() = Builder() - } - - /** A builder for [Variables]. */ - class Builder internal constructor() { - - private var additionalProperties: MutableMap = mutableMapOf() - - @JvmSynthetic - internal fun from(variables: Variables) = apply { - additionalProperties = variables.additionalProperties.toMutableMap() - } - - 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 [Variables]. - * - * Further updates to this [Builder] will not mutate the returned instance. - */ - fun build(): Variables = Variables(additionalProperties.toImmutable()) - } - - private var validated: Boolean = false - - fun validate(): Variables = apply { - if (validated) { - return@apply - } - - 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. - */ - @JvmSynthetic - internal fun validity(): Int = - additionalProperties.count { (_, value) -> !value.isNull() && !value.isMissing() } - - override fun equals(other: Any?): Boolean { - if (this === other) { - return true - } - - return other is Variables && additionalProperties == other.additionalProperties - } - - private val hashCode: Int by lazy { Objects.hash(additionalProperties) } - - override fun hashCode(): Int = hashCode - - override fun toString() = "Variables{additionalProperties=$additionalProperties}" - } - - override fun equals(other: Any?): Boolean { - if (this === other) { - return true - } - - return other is Options && - model == other.model && - timeout == other.timeout && - variables == other.variables && - additionalProperties == other.additionalProperties - } - - private val hashCode: Int by lazy { - Objects.hash(model, timeout, variables, additionalProperties) - } - - override fun hashCode(): Int = hashCode - - override fun toString() = - "Options{model=$model, timeout=$timeout, variables=$variables, additionalProperties=$additionalProperties}" - } - - class XStreamResponse @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 { - - @JvmField val TRUE = of("true") - - @JvmField val FALSE = of("false") - - @JvmStatic fun of(value: String) = XStreamResponse(JsonField.of(value)) - } - - /** An enum containing [XStreamResponse]'s known values. */ - enum class Known { - TRUE, - FALSE, - } - - /** - * An enum containing [XStreamResponse]'s known values, as well as an [_UNKNOWN] member. - * - * An instance of [XStreamResponse] 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, - FALSE, - /** - * An enum member indicating that [XStreamResponse] 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 - FALSE -> Value.FALSE - 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 - FALSE -> Known.FALSE - else -> throw StagehandInvalidDataException("Unknown XStreamResponse: $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().orElseThrow { - StagehandInvalidDataException("Value is not a String") - } - - private var validated: Boolean = false - - fun validate(): XStreamResponse = 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. - */ - @JvmSynthetic 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 XStreamResponse && 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 SessionActParams && - sessionId == other.sessionId && - xStreamResponse == other.xStreamResponse && - body == other.body && - additionalHeaders == other.additionalHeaders && - additionalQueryParams == other.additionalQueryParams - } - - override fun hashCode(): Int = - Objects.hash(sessionId, xStreamResponse, body, additionalHeaders, additionalQueryParams) - - override fun toString() = - "SessionActParams{sessionId=$sessionId, xStreamResponse=$xStreamResponse, body=$body, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" -} diff --git a/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionActResponse.kt b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionActResponse.kt deleted file mode 100644 index 69dfcab..0000000 --- a/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionActResponse.kt +++ /dev/null @@ -1,269 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. - -package com.browserbase.api.models.sessions - -import com.browserbase.api.core.ExcludeMissing -import com.browserbase.api.core.JsonField -import com.browserbase.api.core.JsonMissing -import com.browserbase.api.core.JsonValue -import com.browserbase.api.core.checkKnown -import com.browserbase.api.core.checkRequired -import com.browserbase.api.core.toImmutable -import com.browserbase.api.errors.StagehandInvalidDataException -import com.fasterxml.jackson.annotation.JsonAnyGetter -import com.fasterxml.jackson.annotation.JsonAnySetter -import com.fasterxml.jackson.annotation.JsonCreator -import com.fasterxml.jackson.annotation.JsonProperty -import java.util.Collections -import java.util.Objects -import kotlin.jvm.optionals.getOrNull - -class SessionActResponse -@JsonCreator(mode = JsonCreator.Mode.DISABLED) -private constructor( - private val actions: JsonField>, - private val message: JsonField, - private val success: JsonField, - private val additionalProperties: MutableMap, -) { - - @JsonCreator - private constructor( - @JsonProperty("actions") - @ExcludeMissing - actions: JsonField> = JsonMissing.of(), - @JsonProperty("message") @ExcludeMissing message: JsonField = JsonMissing.of(), - @JsonProperty("success") @ExcludeMissing success: JsonField = JsonMissing.of(), - ) : this(actions, message, success, mutableMapOf()) - - /** - * Actions that were executed - * - * @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 actions(): List = actions.getRequired("actions") - - /** - * Result message - * - * @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 message(): String = message.getRequired("message") - - /** - * Whether the action succeeded - * - * @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(): Boolean = success.getRequired("success") - - /** - * Returns the raw JSON value of [actions]. - * - * Unlike [actions], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("actions") @ExcludeMissing fun _actions(): JsonField> = actions - - /** - * Returns the raw JSON value of [message]. - * - * Unlike [message], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("message") @ExcludeMissing fun _message(): JsonField = message - - /** - * 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 - - @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 [SessionActResponse]. - * - * The following fields are required: - * ```java - * .actions() - * .message() - * .success() - * ``` - */ - @JvmStatic fun builder() = Builder() - } - - /** A builder for [SessionActResponse]. */ - class Builder internal constructor() { - - private var actions: JsonField>? = null - private var message: JsonField? = null - private var success: JsonField? = null - private var additionalProperties: MutableMap = mutableMapOf() - - @JvmSynthetic - internal fun from(sessionActResponse: SessionActResponse) = apply { - actions = sessionActResponse.actions.map { it.toMutableList() } - message = sessionActResponse.message - success = sessionActResponse.success - additionalProperties = sessionActResponse.additionalProperties.toMutableMap() - } - - /** Actions that were executed */ - fun actions(actions: List) = actions(JsonField.of(actions)) - - /** - * Sets [Builder.actions] to an arbitrary JSON value. - * - * You should usually call [Builder.actions] with a well-typed `List` value instead. - * This method is primarily for setting the field to an undocumented or not yet supported - * value. - */ - fun actions(actions: JsonField>) = apply { - this.actions = actions.map { it.toMutableList() } - } - - /** - * Adds a single [Action] to [actions]. - * - * @throws IllegalStateException if the field was previously set to a non-list. - */ - fun addAction(action: Action) = apply { - actions = - (actions ?: JsonField.of(mutableListOf())).also { - checkKnown("actions", it).add(action) - } - } - - /** Result message */ - fun message(message: String) = message(JsonField.of(message)) - - /** - * Sets [Builder.message] to an arbitrary JSON value. - * - * You should usually call [Builder.message] with a well-typed [String] value instead. This - * method is primarily for setting the field to an undocumented or not yet supported value. - */ - fun message(message: JsonField) = apply { this.message = message } - - /** Whether the action succeeded */ - 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 [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 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 [SessionActResponse]. - * - * Further updates to this [Builder] will not mutate the returned instance. - * - * The following fields are required: - * ```java - * .actions() - * .message() - * .success() - * ``` - * - * @throws IllegalStateException if any required field is unset. - */ - fun build(): SessionActResponse = - SessionActResponse( - checkRequired("actions", actions).map { it.toImmutable() }, - checkRequired("message", message), - checkRequired("success", success), - additionalProperties.toMutableMap(), - ) - } - - private var validated: Boolean = false - - fun validate(): SessionActResponse = apply { - if (validated) { - return@apply - } - - actions().forEach { it.validate() } - message() - success() - 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. - */ - @JvmSynthetic - internal fun validity(): Int = - (actions.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + - (if (message.asKnown().isPresent) 1 else 0) + - (if (success.asKnown().isPresent) 1 else 0) - - override fun equals(other: Any?): Boolean { - if (this === other) { - return true - } - - return other is SessionActResponse && - actions == other.actions && - message == other.message && - success == other.success && - additionalProperties == other.additionalProperties - } - - private val hashCode: Int by lazy { - Objects.hash(actions, message, success, additionalProperties) - } - - override fun hashCode(): Int = hashCode - - override fun toString() = - "SessionActResponse{actions=$actions, message=$message, success=$success, additionalProperties=$additionalProperties}" -} diff --git a/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionEndParams.kt b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionEndParams.kt deleted file mode 100644 index a3bb3fe..0000000 --- a/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionEndParams.kt +++ /dev/null @@ -1,229 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. - -package com.browserbase.api.models.sessions - -import com.browserbase.api.core.JsonValue -import com.browserbase.api.core.Params -import com.browserbase.api.core.http.Headers -import com.browserbase.api.core.http.QueryParams -import com.browserbase.api.core.toImmutable -import java.util.Objects -import java.util.Optional -import kotlin.jvm.optionals.getOrNull - -/** Closes the browser and cleans up all resources associated with the session. */ -class SessionEndParams -private constructor( - private val sessionId: String?, - private val additionalHeaders: Headers, - private val additionalQueryParams: QueryParams, - private val additionalBodyProperties: Map, -) : Params { - - fun sessionId(): Optional = Optional.ofNullable(sessionId) - - /** Additional body properties to send with the request. */ - fun _additionalBodyProperties(): Map = additionalBodyProperties - - /** Additional headers to send with the request. */ - fun _additionalHeaders(): Headers = additionalHeaders - - /** Additional query param to send with the request. */ - fun _additionalQueryParams(): QueryParams = additionalQueryParams - - fun toBuilder() = Builder().from(this) - - companion object { - - @JvmStatic fun none(): SessionEndParams = builder().build() - - /** Returns a mutable builder for constructing an instance of [SessionEndParams]. */ - @JvmStatic fun builder() = Builder() - } - - /** A builder for [SessionEndParams]. */ - class Builder internal constructor() { - - private var sessionId: String? = null - private var additionalHeaders: Headers.Builder = Headers.builder() - private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() - private var additionalBodyProperties: MutableMap = mutableMapOf() - - @JvmSynthetic - internal fun from(sessionEndParams: SessionEndParams) = apply { - sessionId = sessionEndParams.sessionId - additionalHeaders = sessionEndParams.additionalHeaders.toBuilder() - additionalQueryParams = sessionEndParams.additionalQueryParams.toBuilder() - additionalBodyProperties = sessionEndParams.additionalBodyProperties.toMutableMap() - } - - fun sessionId(sessionId: String?) = apply { this.sessionId = sessionId } - - /** Alias for calling [Builder.sessionId] with `sessionId.orElse(null)`. */ - fun sessionId(sessionId: Optional) = sessionId(sessionId.getOrNull()) - - fun additionalHeaders(additionalHeaders: Headers) = apply { - this.additionalHeaders.clear() - putAllAdditionalHeaders(additionalHeaders) - } - - fun additionalHeaders(additionalHeaders: Map>) = apply { - this.additionalHeaders.clear() - putAllAdditionalHeaders(additionalHeaders) - } - - fun putAdditionalHeader(name: String, value: String) = apply { - additionalHeaders.put(name, value) - } - - fun putAdditionalHeaders(name: String, values: Iterable) = apply { - additionalHeaders.put(name, values) - } - - fun putAllAdditionalHeaders(additionalHeaders: Headers) = apply { - this.additionalHeaders.putAll(additionalHeaders) - } - - fun putAllAdditionalHeaders(additionalHeaders: Map>) = apply { - this.additionalHeaders.putAll(additionalHeaders) - } - - fun replaceAdditionalHeaders(name: String, value: String) = apply { - additionalHeaders.replace(name, value) - } - - fun replaceAdditionalHeaders(name: String, values: Iterable) = apply { - additionalHeaders.replace(name, values) - } - - fun replaceAllAdditionalHeaders(additionalHeaders: Headers) = apply { - this.additionalHeaders.replaceAll(additionalHeaders) - } - - fun replaceAllAdditionalHeaders(additionalHeaders: Map>) = apply { - this.additionalHeaders.replaceAll(additionalHeaders) - } - - fun removeAdditionalHeaders(name: String) = apply { additionalHeaders.remove(name) } - - fun removeAllAdditionalHeaders(names: Set) = apply { - additionalHeaders.removeAll(names) - } - - fun additionalQueryParams(additionalQueryParams: QueryParams) = apply { - this.additionalQueryParams.clear() - putAllAdditionalQueryParams(additionalQueryParams) - } - - fun additionalQueryParams(additionalQueryParams: Map>) = apply { - this.additionalQueryParams.clear() - putAllAdditionalQueryParams(additionalQueryParams) - } - - fun putAdditionalQueryParam(key: String, value: String) = apply { - additionalQueryParams.put(key, value) - } - - fun putAdditionalQueryParams(key: String, values: Iterable) = apply { - additionalQueryParams.put(key, values) - } - - fun putAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { - this.additionalQueryParams.putAll(additionalQueryParams) - } - - fun putAllAdditionalQueryParams(additionalQueryParams: Map>) = - apply { - this.additionalQueryParams.putAll(additionalQueryParams) - } - - fun replaceAdditionalQueryParams(key: String, value: String) = apply { - additionalQueryParams.replace(key, value) - } - - fun replaceAdditionalQueryParams(key: String, values: Iterable) = apply { - additionalQueryParams.replace(key, values) - } - - fun replaceAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { - this.additionalQueryParams.replaceAll(additionalQueryParams) - } - - fun replaceAllAdditionalQueryParams(additionalQueryParams: Map>) = - apply { - this.additionalQueryParams.replaceAll(additionalQueryParams) - } - - fun removeAdditionalQueryParams(key: String) = apply { additionalQueryParams.remove(key) } - - fun removeAllAdditionalQueryParams(keys: Set) = apply { - additionalQueryParams.removeAll(keys) - } - - fun additionalBodyProperties(additionalBodyProperties: Map) = apply { - this.additionalBodyProperties.clear() - putAllAdditionalBodyProperties(additionalBodyProperties) - } - - fun putAdditionalBodyProperty(key: String, value: JsonValue) = apply { - additionalBodyProperties.put(key, value) - } - - fun putAllAdditionalBodyProperties(additionalBodyProperties: Map) = - apply { - this.additionalBodyProperties.putAll(additionalBodyProperties) - } - - fun removeAdditionalBodyProperty(key: String) = apply { - additionalBodyProperties.remove(key) - } - - fun removeAllAdditionalBodyProperties(keys: Set) = apply { - keys.forEach(::removeAdditionalBodyProperty) - } - - /** - * Returns an immutable instance of [SessionEndParams]. - * - * Further updates to this [Builder] will not mutate the returned instance. - */ - fun build(): SessionEndParams = - SessionEndParams( - sessionId, - additionalHeaders.build(), - additionalQueryParams.build(), - additionalBodyProperties.toImmutable(), - ) - } - - fun _body(): Optional> = - Optional.ofNullable(additionalBodyProperties.ifEmpty { null }) - - fun _pathParam(index: Int): String = - when (index) { - 0 -> sessionId ?: "" - else -> "" - } - - override fun _headers(): Headers = additionalHeaders - - override fun _queryParams(): QueryParams = additionalQueryParams - - override fun equals(other: Any?): Boolean { - if (this === other) { - return true - } - - return other is SessionEndParams && - sessionId == other.sessionId && - additionalHeaders == other.additionalHeaders && - additionalQueryParams == other.additionalQueryParams && - additionalBodyProperties == other.additionalBodyProperties - } - - override fun hashCode(): Int = - Objects.hash(sessionId, additionalHeaders, additionalQueryParams, additionalBodyProperties) - - override fun toString() = - "SessionEndParams{sessionId=$sessionId, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams, additionalBodyProperties=$additionalBodyProperties}" -} diff --git a/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionEndResponse.kt b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionEndResponse.kt deleted file mode 100644 index feba7d7..0000000 --- a/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionEndResponse.kt +++ /dev/null @@ -1,153 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. - -package com.browserbase.api.models.sessions - -import com.browserbase.api.core.ExcludeMissing -import com.browserbase.api.core.JsonField -import com.browserbase.api.core.JsonMissing -import com.browserbase.api.core.JsonValue -import com.browserbase.api.errors.StagehandInvalidDataException -import com.fasterxml.jackson.annotation.JsonAnyGetter -import com.fasterxml.jackson.annotation.JsonAnySetter -import com.fasterxml.jackson.annotation.JsonCreator -import com.fasterxml.jackson.annotation.JsonProperty -import java.util.Collections -import java.util.Objects -import java.util.Optional - -class SessionEndResponse -@JsonCreator(mode = JsonCreator.Mode.DISABLED) -private constructor( - private val success: JsonField, - private val additionalProperties: MutableMap, -) { - - @JsonCreator - private constructor( - @JsonProperty("success") @ExcludeMissing success: JsonField = JsonMissing.of() - ) : this(success, mutableMapOf()) - - /** - * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if the - * server responded with an unexpected value). - */ - fun success(): Optional = success.getOptional("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 - - @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 [SessionEndResponse]. */ - @JvmStatic fun builder() = Builder() - } - - /** A builder for [SessionEndResponse]. */ - class Builder internal constructor() { - - private var success: JsonField = JsonMissing.of() - private var additionalProperties: MutableMap = mutableMapOf() - - @JvmSynthetic - internal fun from(sessionEndResponse: SessionEndResponse) = apply { - success = sessionEndResponse.success - additionalProperties = sessionEndResponse.additionalProperties.toMutableMap() - } - - 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 [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 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 [SessionEndResponse]. - * - * Further updates to this [Builder] will not mutate the returned instance. - */ - fun build(): SessionEndResponse = - SessionEndResponse(success, additionalProperties.toMutableMap()) - } - - private var validated: Boolean = false - - fun validate(): SessionEndResponse = apply { - if (validated) { - return@apply - } - - success() - 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. - */ - @JvmSynthetic internal fun validity(): Int = (if (success.asKnown().isPresent) 1 else 0) - - override fun equals(other: Any?): Boolean { - if (this === other) { - return true - } - - return other is SessionEndResponse && - success == other.success && - additionalProperties == other.additionalProperties - } - - private val hashCode: Int by lazy { Objects.hash(success, additionalProperties) } - - override fun hashCode(): Int = hashCode - - override fun toString() = - "SessionEndResponse{success=$success, additionalProperties=$additionalProperties}" -} diff --git a/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionExecuteAgentParams.kt b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionExecuteAgentParams.kt deleted file mode 100644 index d2c5c47..0000000 --- a/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionExecuteAgentParams.kt +++ /dev/null @@ -1,1547 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. - -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 -import com.browserbase.api.core.JsonValue -import com.browserbase.api.core.Params -import com.browserbase.api.core.allMaxBy -import com.browserbase.api.core.checkRequired -import com.browserbase.api.core.getOrThrow -import com.browserbase.api.core.http.Headers -import com.browserbase.api.core.http.QueryParams -import com.browserbase.api.errors.StagehandInvalidDataException -import com.fasterxml.jackson.annotation.JsonAnyGetter -import com.fasterxml.jackson.annotation.JsonAnySetter -import com.fasterxml.jackson.annotation.JsonCreator -import com.fasterxml.jackson.annotation.JsonProperty -import com.fasterxml.jackson.core.JsonGenerator -import com.fasterxml.jackson.core.ObjectCodec -import com.fasterxml.jackson.databind.JsonNode -import com.fasterxml.jackson.databind.SerializerProvider -import com.fasterxml.jackson.databind.annotation.JsonDeserialize -import com.fasterxml.jackson.databind.annotation.JsonSerialize -import com.fasterxml.jackson.module.kotlin.jacksonTypeRef -import java.util.Collections -import java.util.Objects -import java.util.Optional -import kotlin.jvm.optionals.getOrNull - -/** Runs an autonomous agent that can perform multiple actions to complete a complex task. */ -class SessionExecuteAgentParams -private constructor( - private val sessionId: String?, - private val xStreamResponse: XStreamResponse?, - private val body: Body, - private val additionalHeaders: Headers, - private val additionalQueryParams: QueryParams, -) : Params { - - fun sessionId(): Optional = Optional.ofNullable(sessionId) - - fun xStreamResponse(): Optional = Optional.ofNullable(xStreamResponse) - - /** - * @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 agentConfig(): AgentConfig = body.agentConfig() - - /** - * @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 executeOptions(): ExecuteOptions = body.executeOptions() - - /** - * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if the - * server responded with an unexpected value). - */ - fun frameId(): Optional = body.frameId() - - /** - * Returns the raw JSON value of [agentConfig]. - * - * Unlike [agentConfig], this method doesn't throw if the JSON field has an unexpected type. - */ - fun _agentConfig(): JsonField = body._agentConfig() - - /** - * Returns the raw JSON value of [executeOptions]. - * - * Unlike [executeOptions], this method doesn't throw if the JSON field has an unexpected type. - */ - fun _executeOptions(): JsonField = body._executeOptions() - - /** - * Returns the raw JSON value of [frameId]. - * - * Unlike [frameId], this method doesn't throw if the JSON field has an unexpected type. - */ - fun _frameId(): JsonField = body._frameId() - - fun _additionalBodyProperties(): Map = body._additionalProperties() - - /** Additional headers to send with the request. */ - fun _additionalHeaders(): Headers = additionalHeaders - - /** Additional query param to send with the request. */ - fun _additionalQueryParams(): QueryParams = additionalQueryParams - - fun toBuilder() = Builder().from(this) - - companion object { - - /** - * Returns a mutable builder for constructing an instance of [SessionExecuteAgentParams]. - * - * The following fields are required: - * ```java - * .agentConfig() - * .executeOptions() - * ``` - */ - @JvmStatic fun builder() = Builder() - } - - /** A builder for [SessionExecuteAgentParams]. */ - class Builder internal constructor() { - - private var sessionId: String? = null - private var xStreamResponse: XStreamResponse? = null - private var body: Body.Builder = Body.builder() - private var additionalHeaders: Headers.Builder = Headers.builder() - private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() - - @JvmSynthetic - internal fun from(sessionExecuteAgentParams: SessionExecuteAgentParams) = apply { - sessionId = sessionExecuteAgentParams.sessionId - xStreamResponse = sessionExecuteAgentParams.xStreamResponse - body = sessionExecuteAgentParams.body.toBuilder() - additionalHeaders = sessionExecuteAgentParams.additionalHeaders.toBuilder() - additionalQueryParams = sessionExecuteAgentParams.additionalQueryParams.toBuilder() - } - - fun sessionId(sessionId: String?) = apply { this.sessionId = sessionId } - - /** Alias for calling [Builder.sessionId] with `sessionId.orElse(null)`. */ - fun sessionId(sessionId: Optional) = sessionId(sessionId.getOrNull()) - - fun xStreamResponse(xStreamResponse: XStreamResponse?) = apply { - this.xStreamResponse = xStreamResponse - } - - /** Alias for calling [Builder.xStreamResponse] with `xStreamResponse.orElse(null)`. */ - fun xStreamResponse(xStreamResponse: Optional) = - xStreamResponse(xStreamResponse.getOrNull()) - - /** - * Sets the entire request body. - * - * This is generally only useful if you are already constructing the body separately. - * Otherwise, it's more convenient to use the top-level setters instead: - * - [agentConfig] - * - [executeOptions] - * - [frameId] - */ - fun body(body: Body) = apply { this.body = body.toBuilder() } - - fun agentConfig(agentConfig: AgentConfig) = apply { body.agentConfig(agentConfig) } - - /** - * Sets [Builder.agentConfig] to an arbitrary JSON value. - * - * You should usually call [Builder.agentConfig] with a well-typed [AgentConfig] value - * instead. This method is primarily for setting the field to an undocumented or not yet - * supported value. - */ - fun agentConfig(agentConfig: JsonField) = apply { - body.agentConfig(agentConfig) - } - - fun executeOptions(executeOptions: ExecuteOptions) = apply { - body.executeOptions(executeOptions) - } - - /** - * Sets [Builder.executeOptions] to an arbitrary JSON value. - * - * You should usually call [Builder.executeOptions] with a well-typed [ExecuteOptions] value - * instead. This method is primarily for setting the field to an undocumented or not yet - * supported value. - */ - fun executeOptions(executeOptions: JsonField) = apply { - body.executeOptions(executeOptions) - } - - fun frameId(frameId: String) = apply { body.frameId(frameId) } - - /** - * Sets [Builder.frameId] to an arbitrary JSON value. - * - * You should usually call [Builder.frameId] with a well-typed [String] value instead. This - * method is primarily for setting the field to an undocumented or not yet supported value. - */ - fun frameId(frameId: JsonField) = apply { body.frameId(frameId) } - - fun additionalBodyProperties(additionalBodyProperties: Map) = apply { - body.additionalProperties(additionalBodyProperties) - } - - fun putAdditionalBodyProperty(key: String, value: JsonValue) = apply { - body.putAdditionalProperty(key, value) - } - - fun putAllAdditionalBodyProperties(additionalBodyProperties: Map) = - apply { - body.putAllAdditionalProperties(additionalBodyProperties) - } - - fun removeAdditionalBodyProperty(key: String) = apply { body.removeAdditionalProperty(key) } - - fun removeAllAdditionalBodyProperties(keys: Set) = apply { - body.removeAllAdditionalProperties(keys) - } - - fun additionalHeaders(additionalHeaders: Headers) = apply { - this.additionalHeaders.clear() - putAllAdditionalHeaders(additionalHeaders) - } - - fun additionalHeaders(additionalHeaders: Map>) = apply { - this.additionalHeaders.clear() - putAllAdditionalHeaders(additionalHeaders) - } - - fun putAdditionalHeader(name: String, value: String) = apply { - additionalHeaders.put(name, value) - } - - fun putAdditionalHeaders(name: String, values: Iterable) = apply { - additionalHeaders.put(name, values) - } - - fun putAllAdditionalHeaders(additionalHeaders: Headers) = apply { - this.additionalHeaders.putAll(additionalHeaders) - } - - fun putAllAdditionalHeaders(additionalHeaders: Map>) = apply { - this.additionalHeaders.putAll(additionalHeaders) - } - - fun replaceAdditionalHeaders(name: String, value: String) = apply { - additionalHeaders.replace(name, value) - } - - fun replaceAdditionalHeaders(name: String, values: Iterable) = apply { - additionalHeaders.replace(name, values) - } - - fun replaceAllAdditionalHeaders(additionalHeaders: Headers) = apply { - this.additionalHeaders.replaceAll(additionalHeaders) - } - - fun replaceAllAdditionalHeaders(additionalHeaders: Map>) = apply { - this.additionalHeaders.replaceAll(additionalHeaders) - } - - fun removeAdditionalHeaders(name: String) = apply { additionalHeaders.remove(name) } - - fun removeAllAdditionalHeaders(names: Set) = apply { - additionalHeaders.removeAll(names) - } - - fun additionalQueryParams(additionalQueryParams: QueryParams) = apply { - this.additionalQueryParams.clear() - putAllAdditionalQueryParams(additionalQueryParams) - } - - fun additionalQueryParams(additionalQueryParams: Map>) = apply { - this.additionalQueryParams.clear() - putAllAdditionalQueryParams(additionalQueryParams) - } - - fun putAdditionalQueryParam(key: String, value: String) = apply { - additionalQueryParams.put(key, value) - } - - fun putAdditionalQueryParams(key: String, values: Iterable) = apply { - additionalQueryParams.put(key, values) - } - - fun putAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { - this.additionalQueryParams.putAll(additionalQueryParams) - } - - fun putAllAdditionalQueryParams(additionalQueryParams: Map>) = - apply { - this.additionalQueryParams.putAll(additionalQueryParams) - } - - fun replaceAdditionalQueryParams(key: String, value: String) = apply { - additionalQueryParams.replace(key, value) - } - - fun replaceAdditionalQueryParams(key: String, values: Iterable) = apply { - additionalQueryParams.replace(key, values) - } - - fun replaceAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { - this.additionalQueryParams.replaceAll(additionalQueryParams) - } - - fun replaceAllAdditionalQueryParams(additionalQueryParams: Map>) = - apply { - this.additionalQueryParams.replaceAll(additionalQueryParams) - } - - fun removeAdditionalQueryParams(key: String) = apply { additionalQueryParams.remove(key) } - - fun removeAllAdditionalQueryParams(keys: Set) = apply { - additionalQueryParams.removeAll(keys) - } - - /** - * Returns an immutable instance of [SessionExecuteAgentParams]. - * - * Further updates to this [Builder] will not mutate the returned instance. - * - * The following fields are required: - * ```java - * .agentConfig() - * .executeOptions() - * ``` - * - * @throws IllegalStateException if any required field is unset. - */ - fun build(): SessionExecuteAgentParams = - SessionExecuteAgentParams( - sessionId, - xStreamResponse, - body.build(), - additionalHeaders.build(), - additionalQueryParams.build(), - ) - } - - fun _body(): Body = body - - fun _pathParam(index: Int): String = - when (index) { - 0 -> sessionId ?: "" - else -> "" - } - - override fun _headers(): Headers = - Headers.builder() - .apply { - xStreamResponse?.let { put("x-stream-response", it.toString()) } - putAll(additionalHeaders) - } - .build() - - override fun _queryParams(): QueryParams = additionalQueryParams - - class Body - @JsonCreator(mode = JsonCreator.Mode.DISABLED) - private constructor( - private val agentConfig: JsonField, - private val executeOptions: JsonField, - private val frameId: JsonField, - private val additionalProperties: MutableMap, - ) { - - @JsonCreator - private constructor( - @JsonProperty("agentConfig") - @ExcludeMissing - agentConfig: JsonField = JsonMissing.of(), - @JsonProperty("executeOptions") - @ExcludeMissing - executeOptions: JsonField = JsonMissing.of(), - @JsonProperty("frameId") @ExcludeMissing frameId: JsonField = JsonMissing.of(), - ) : this(agentConfig, executeOptions, frameId, mutableMapOf()) - - /** - * @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 agentConfig(): AgentConfig = agentConfig.getRequired("agentConfig") - - /** - * @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 executeOptions(): ExecuteOptions = executeOptions.getRequired("executeOptions") - - /** - * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if - * the server responded with an unexpected value). - */ - fun frameId(): Optional = frameId.getOptional("frameId") - - /** - * Returns the raw JSON value of [agentConfig]. - * - * Unlike [agentConfig], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("agentConfig") - @ExcludeMissing - fun _agentConfig(): JsonField = agentConfig - - /** - * Returns the raw JSON value of [executeOptions]. - * - * Unlike [executeOptions], this method doesn't throw if the JSON field has an unexpected - * type. - */ - @JsonProperty("executeOptions") - @ExcludeMissing - fun _executeOptions(): JsonField = executeOptions - - /** - * Returns the raw JSON value of [frameId]. - * - * Unlike [frameId], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("frameId") @ExcludeMissing fun _frameId(): JsonField = frameId - - @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 [Body]. - * - * The following fields are required: - * ```java - * .agentConfig() - * .executeOptions() - * ``` - */ - @JvmStatic fun builder() = Builder() - } - - /** A builder for [Body]. */ - class Builder internal constructor() { - - private var agentConfig: JsonField? = null - private var executeOptions: JsonField? = null - private var frameId: JsonField = JsonMissing.of() - private var additionalProperties: MutableMap = mutableMapOf() - - @JvmSynthetic - internal fun from(body: Body) = apply { - agentConfig = body.agentConfig - executeOptions = body.executeOptions - frameId = body.frameId - additionalProperties = body.additionalProperties.toMutableMap() - } - - fun agentConfig(agentConfig: AgentConfig) = agentConfig(JsonField.of(agentConfig)) - - /** - * Sets [Builder.agentConfig] to an arbitrary JSON value. - * - * You should usually call [Builder.agentConfig] with a well-typed [AgentConfig] value - * instead. This method is primarily for setting the field to an undocumented or not yet - * supported value. - */ - fun agentConfig(agentConfig: JsonField) = apply { - this.agentConfig = agentConfig - } - - fun executeOptions(executeOptions: ExecuteOptions) = - executeOptions(JsonField.of(executeOptions)) - - /** - * Sets [Builder.executeOptions] to an arbitrary JSON value. - * - * You should usually call [Builder.executeOptions] with a well-typed [ExecuteOptions] - * value instead. This method is primarily for setting the field to an undocumented or - * not yet supported value. - */ - fun executeOptions(executeOptions: JsonField) = apply { - this.executeOptions = executeOptions - } - - fun frameId(frameId: String) = frameId(JsonField.of(frameId)) - - /** - * Sets [Builder.frameId] to an arbitrary JSON value. - * - * You should usually call [Builder.frameId] with a well-typed [String] value instead. - * This method is primarily for setting the field to an undocumented or not yet - * supported value. - */ - fun frameId(frameId: JsonField) = apply { this.frameId = frameId } - - 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 [Body]. - * - * Further updates to this [Builder] will not mutate the returned instance. - * - * The following fields are required: - * ```java - * .agentConfig() - * .executeOptions() - * ``` - * - * @throws IllegalStateException if any required field is unset. - */ - fun build(): Body = - Body( - checkRequired("agentConfig", agentConfig), - checkRequired("executeOptions", executeOptions), - frameId, - additionalProperties.toMutableMap(), - ) - } - - private var validated: Boolean = false - - fun validate(): Body = apply { - if (validated) { - return@apply - } - - agentConfig().validate() - executeOptions().validate() - frameId() - 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. - */ - @JvmSynthetic - internal fun validity(): Int = - (agentConfig.asKnown().getOrNull()?.validity() ?: 0) + - (executeOptions.asKnown().getOrNull()?.validity() ?: 0) + - (if (frameId.asKnown().isPresent) 1 else 0) - - override fun equals(other: Any?): Boolean { - if (this === other) { - return true - } - - return other is Body && - agentConfig == other.agentConfig && - executeOptions == other.executeOptions && - frameId == other.frameId && - additionalProperties == other.additionalProperties - } - - private val hashCode: Int by lazy { - Objects.hash(agentConfig, executeOptions, frameId, additionalProperties) - } - - override fun hashCode(): Int = hashCode - - override fun toString() = - "Body{agentConfig=$agentConfig, executeOptions=$executeOptions, frameId=$frameId, additionalProperties=$additionalProperties}" - } - - class AgentConfig - @JsonCreator(mode = JsonCreator.Mode.DISABLED) - private constructor( - private val cua: JsonField, - private val model: JsonField, - private val provider: JsonField, - private val systemPrompt: JsonField, - private val additionalProperties: MutableMap, - ) { - - @JsonCreator - 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, provider, systemPrompt, mutableMapOf()) - - /** - * Enable Computer Use Agent mode - * - * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if - * the server responded with an unexpected value). - */ - fun cua(): Optional = cua.getOptional("cua") - - /** - * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if - * the server responded with an unexpected value). - */ - fun model(): Optional = model.getOptional("model") - - /** - * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if - * the server responded with an unexpected value). - */ - fun provider(): Optional = provider.getOptional("provider") - - /** - * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if - * the server responded with an unexpected value). - */ - fun systemPrompt(): Optional = systemPrompt.getOptional("systemPrompt") - - /** - * Returns the raw JSON value of [cua]. - * - * Unlike [cua], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("cua") @ExcludeMissing fun _cua(): JsonField = cua - - /** - * Returns the raw JSON value of [model]. - * - * Unlike [model], this method doesn't throw if the JSON field has an unexpected type. - */ - @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]. - * - * Unlike [systemPrompt], this method doesn't throw if the JSON field has an unexpected - * type. - */ - @JsonProperty("systemPrompt") - @ExcludeMissing - fun _systemPrompt(): JsonField = systemPrompt - - @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 [AgentConfig]. */ - @JvmStatic fun builder() = Builder() - } - - /** A builder for [AgentConfig]. */ - class Builder internal 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() - - @JvmSynthetic - internal fun from(agentConfig: AgentConfig) = apply { - cua = agentConfig.cua - model = agentConfig.model - provider = agentConfig.provider - systemPrompt = agentConfig.systemPrompt - additionalProperties = agentConfig.additionalProperties.toMutableMap() - } - - /** Enable Computer Use Agent mode */ - fun cua(cua: Boolean) = cua(JsonField.of(cua)) - - /** - * Sets [Builder.cua] to an arbitrary JSON value. - * - * You should usually call [Builder.cua] with a well-typed [Boolean] value instead. This - * method is primarily for setting the field to an undocumented or not yet supported - * value. - */ - fun cua(cua: JsonField) = apply { this.cua = cua } - - fun model(model: Model) = model(JsonField.of(model)) - - /** - * Sets [Builder.model] to an arbitrary JSON value. - * - * You should usually call [Builder.model] with a well-typed [Model] value instead. This - * method is primarily for setting the field to an undocumented or not yet supported - * value. - */ - fun model(model: JsonField) = apply { this.model = model } - - /** Alias for calling [model] with `Model.ofString(string)`. */ - fun model(string: String) = model(Model.ofString(string)) - - /** Alias for calling [model] with `Model.ofConfig(config)`. */ - fun model(config: ModelConfig) = model(Model.ofConfig(config)) - - 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 systemPrompt(systemPrompt: String) = systemPrompt(JsonField.of(systemPrompt)) - - /** - * Sets [Builder.systemPrompt] to an arbitrary JSON value. - * - * You should usually call [Builder.systemPrompt] with a well-typed [String] value - * instead. This method is primarily for setting the field to an undocumented or not yet - * supported value. - */ - fun systemPrompt(systemPrompt: JsonField) = apply { - this.systemPrompt = systemPrompt - } - - 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 [AgentConfig]. - * - * Further updates to this [Builder] will not mutate the returned instance. - */ - fun build(): AgentConfig = - AgentConfig(cua, model, provider, systemPrompt, additionalProperties.toMutableMap()) - } - - private var validated: Boolean = false - - fun validate(): AgentConfig = apply { - if (validated) { - return@apply - } - - cua() - model().ifPresent { it.validate() } - provider().ifPresent { it.validate() } - systemPrompt() - 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. - */ - @JvmSynthetic - internal fun validity(): Int = - (if (cua.asKnown().isPresent) 1 else 0) + - (model.asKnown().getOrNull()?.validity() ?: 0) + - (provider.asKnown().getOrNull()?.validity() ?: 0) + - (if (systemPrompt.asKnown().isPresent) 1 else 0) - - @JsonDeserialize(using = Model.Deserializer::class) - @JsonSerialize(using = Model.Serializer::class) - class Model - private constructor( - private val string: String? = null, - private val config: ModelConfig? = null, - private val _json: JsonValue? = null, - ) { - - fun string(): Optional = Optional.ofNullable(string) - - fun config(): Optional = Optional.ofNullable(config) - - fun isString(): Boolean = string != null - - fun isConfig(): Boolean = config != null - - fun asString(): String = string.getOrThrow("string") - - fun asConfig(): ModelConfig = config.getOrThrow("config") - - fun _json(): Optional = Optional.ofNullable(_json) - - fun accept(visitor: Visitor): T = - when { - string != null -> visitor.visitString(string) - config != null -> visitor.visitConfig(config) - else -> visitor.unknown(_json) - } - - private var validated: Boolean = false - - fun validate(): Model = apply { - if (validated) { - return@apply - } - - accept( - object : Visitor { - override fun visitString(string: String) {} - - override fun visitConfig(config: ModelConfig) { - config.validate() - } - } - ) - 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. - */ - @JvmSynthetic - internal fun validity(): Int = - accept( - object : Visitor { - override fun visitString(string: String) = 1 - - override fun visitConfig(config: ModelConfig) = config.validity() - - override fun unknown(json: JsonValue?) = 0 - } - ) - - override fun equals(other: Any?): Boolean { - if (this === other) { - return true - } - - return other is Model && string == other.string && config == other.config - } - - override fun hashCode(): Int = Objects.hash(string, config) - - override fun toString(): String = - when { - string != null -> "Model{string=$string}" - config != null -> "Model{config=$config}" - _json != null -> "Model{_unknown=$_json}" - else -> throw IllegalStateException("Invalid Model") - } - - companion object { - - @JvmStatic fun ofString(string: String) = Model(string = string) - - @JvmStatic fun ofConfig(config: ModelConfig) = Model(config = config) - } - - /** - * An interface that defines how to map each variant of [Model] to a value of type [T]. - */ - interface Visitor { - - fun visitString(string: String): T - - fun visitConfig(config: ModelConfig): T - - /** - * Maps an unknown variant of [Model] to a value of type [T]. - * - * An instance of [Model] can contain an unknown variant if it was deserialized from - * data that doesn't match any known variant. For example, if the SDK is on an older - * version than the API, then the API may respond with new variants that the SDK is - * unaware of. - * - * @throws StagehandInvalidDataException in the default implementation. - */ - fun unknown(json: JsonValue?): T { - throw StagehandInvalidDataException("Unknown Model: $json") - } - } - - internal class Deserializer : BaseDeserializer(Model::class) { - - override fun ObjectCodec.deserialize(node: JsonNode): Model { - val json = JsonValue.fromJsonNode(node) - - val bestMatches = - sequenceOf( - tryDeserialize(node, jacksonTypeRef())?.let { - Model(config = it, _json = json) - }, - tryDeserialize(node, jacksonTypeRef())?.let { - Model(string = it, _json = json) - }, - ) - .filterNotNull() - .allMaxBy { it.validity() } - .toList() - return when (bestMatches.size) { - // This can happen if what we're deserializing is completely incompatible - // with all the possible variants (e.g. deserializing from array). - 0 -> Model(_json = json) - 1 -> bestMatches.single() - // If there's more than one match with the highest validity, then use the - // first completely valid match, or simply the first match if none are - // completely valid. - else -> bestMatches.firstOrNull { it.isValid() } ?: bestMatches.first() - } - } - } - - internal class Serializer : BaseSerializer(Model::class) { - - override fun serialize( - value: Model, - generator: JsonGenerator, - provider: SerializerProvider, - ) { - when { - value.string != null -> generator.writeObject(value.string) - value.config != null -> generator.writeObject(value.config) - value._json != null -> generator.writeObject(value._json) - else -> throw IllegalStateException("Invalid Model") - } - } - } - } - - 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 { - - @JvmField val OPENAI = of("openai") - - @JvmField val ANTHROPIC = of("anthropic") - - @JvmField val GOOGLE = of("google") - - @JvmStatic fun of(value: String) = Provider(JsonField.of(value)) - } - - /** An enum containing [Provider]'s known values. */ - enum class Known { - OPENAI, - ANTHROPIC, - GOOGLE, - } - - /** - * 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, - /** - * 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 - 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 - 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().orElseThrow { - 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. - */ - @JvmSynthetic 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 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, provider, systemPrompt, additionalProperties) - } - - override fun hashCode(): Int = hashCode - - override fun toString() = - "AgentConfig{cua=$cua, model=$model, provider=$provider, systemPrompt=$systemPrompt, additionalProperties=$additionalProperties}" - } - - class ExecuteOptions - @JsonCreator(mode = JsonCreator.Mode.DISABLED) - private constructor( - private val instruction: JsonField, - private val highlightCursor: JsonField, - private val maxSteps: JsonField, - private val additionalProperties: MutableMap, - ) { - - @JsonCreator - private constructor( - @JsonProperty("instruction") - @ExcludeMissing - instruction: JsonField = JsonMissing.of(), - @JsonProperty("highlightCursor") - @ExcludeMissing - highlightCursor: JsonField = JsonMissing.of(), - @JsonProperty("maxSteps") @ExcludeMissing maxSteps: JsonField = JsonMissing.of(), - ) : this(instruction, highlightCursor, maxSteps, mutableMapOf()) - - /** - * Task for the agent to complete - * - * @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 instruction(): String = instruction.getRequired("instruction") - - /** - * Visually highlight the cursor during actions - * - * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if - * the server responded with an unexpected value). - */ - fun highlightCursor(): Optional = highlightCursor.getOptional("highlightCursor") - - /** - * Maximum number of steps the agent can take - * - * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if - * the server responded with an unexpected value). - */ - fun maxSteps(): Optional = maxSteps.getOptional("maxSteps") - - /** - * Returns the raw JSON value of [instruction]. - * - * Unlike [instruction], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("instruction") - @ExcludeMissing - fun _instruction(): JsonField = instruction - - /** - * Returns the raw JSON value of [highlightCursor]. - * - * Unlike [highlightCursor], this method doesn't throw if the JSON field has an unexpected - * type. - */ - @JsonProperty("highlightCursor") - @ExcludeMissing - fun _highlightCursor(): JsonField = highlightCursor - - /** - * Returns the raw JSON value of [maxSteps]. - * - * Unlike [maxSteps], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("maxSteps") @ExcludeMissing fun _maxSteps(): JsonField = maxSteps - - @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 [ExecuteOptions]. - * - * The following fields are required: - * ```java - * .instruction() - * ``` - */ - @JvmStatic fun builder() = Builder() - } - - /** A builder for [ExecuteOptions]. */ - class Builder internal constructor() { - - private var instruction: JsonField? = null - private var highlightCursor: JsonField = JsonMissing.of() - private var maxSteps: JsonField = JsonMissing.of() - private var additionalProperties: MutableMap = mutableMapOf() - - @JvmSynthetic - internal fun from(executeOptions: ExecuteOptions) = apply { - instruction = executeOptions.instruction - highlightCursor = executeOptions.highlightCursor - maxSteps = executeOptions.maxSteps - additionalProperties = executeOptions.additionalProperties.toMutableMap() - } - - /** Task for the agent to complete */ - fun instruction(instruction: String) = instruction(JsonField.of(instruction)) - - /** - * Sets [Builder.instruction] to an arbitrary JSON value. - * - * You should usually call [Builder.instruction] with a well-typed [String] value - * instead. This method is primarily for setting the field to an undocumented or not yet - * supported value. - */ - fun instruction(instruction: JsonField) = apply { - this.instruction = instruction - } - - /** Visually highlight the cursor during actions */ - fun highlightCursor(highlightCursor: Boolean) = - highlightCursor(JsonField.of(highlightCursor)) - - /** - * Sets [Builder.highlightCursor] to an arbitrary JSON value. - * - * You should usually call [Builder.highlightCursor] with a well-typed [Boolean] value - * instead. This method is primarily for setting the field to an undocumented or not yet - * supported value. - */ - fun highlightCursor(highlightCursor: JsonField) = apply { - this.highlightCursor = highlightCursor - } - - /** Maximum number of steps the agent can take */ - fun maxSteps(maxSteps: Long) = maxSteps(JsonField.of(maxSteps)) - - /** - * Sets [Builder.maxSteps] to an arbitrary JSON value. - * - * You should usually call [Builder.maxSteps] with a well-typed [Long] value instead. - * This method is primarily for setting the field to an undocumented or not yet - * supported value. - */ - fun maxSteps(maxSteps: JsonField) = apply { this.maxSteps = maxSteps } - - 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 [ExecuteOptions]. - * - * Further updates to this [Builder] will not mutate the returned instance. - * - * The following fields are required: - * ```java - * .instruction() - * ``` - * - * @throws IllegalStateException if any required field is unset. - */ - fun build(): ExecuteOptions = - ExecuteOptions( - checkRequired("instruction", instruction), - highlightCursor, - maxSteps, - additionalProperties.toMutableMap(), - ) - } - - private var validated: Boolean = false - - fun validate(): ExecuteOptions = apply { - if (validated) { - return@apply - } - - instruction() - highlightCursor() - maxSteps() - 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. - */ - @JvmSynthetic - internal fun validity(): Int = - (if (instruction.asKnown().isPresent) 1 else 0) + - (if (highlightCursor.asKnown().isPresent) 1 else 0) + - (if (maxSteps.asKnown().isPresent) 1 else 0) - - override fun equals(other: Any?): Boolean { - if (this === other) { - return true - } - - return other is ExecuteOptions && - instruction == other.instruction && - highlightCursor == other.highlightCursor && - maxSteps == other.maxSteps && - additionalProperties == other.additionalProperties - } - - private val hashCode: Int by lazy { - Objects.hash(instruction, highlightCursor, maxSteps, additionalProperties) - } - - override fun hashCode(): Int = hashCode - - override fun toString() = - "ExecuteOptions{instruction=$instruction, highlightCursor=$highlightCursor, maxSteps=$maxSteps, additionalProperties=$additionalProperties}" - } - - class XStreamResponse @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 { - - @JvmField val TRUE = of("true") - - @JvmField val FALSE = of("false") - - @JvmStatic fun of(value: String) = XStreamResponse(JsonField.of(value)) - } - - /** An enum containing [XStreamResponse]'s known values. */ - enum class Known { - TRUE, - FALSE, - } - - /** - * An enum containing [XStreamResponse]'s known values, as well as an [_UNKNOWN] member. - * - * An instance of [XStreamResponse] 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, - FALSE, - /** - * An enum member indicating that [XStreamResponse] 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 - FALSE -> Value.FALSE - 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 - FALSE -> Known.FALSE - else -> throw StagehandInvalidDataException("Unknown XStreamResponse: $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().orElseThrow { - StagehandInvalidDataException("Value is not a String") - } - - private var validated: Boolean = false - - fun validate(): XStreamResponse = 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. - */ - @JvmSynthetic 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 XStreamResponse && 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 SessionExecuteAgentParams && - sessionId == other.sessionId && - xStreamResponse == other.xStreamResponse && - body == other.body && - additionalHeaders == other.additionalHeaders && - additionalQueryParams == other.additionalQueryParams - } - - override fun hashCode(): Int = - Objects.hash(sessionId, xStreamResponse, body, additionalHeaders, additionalQueryParams) - - override fun toString() = - "SessionExecuteAgentParams{sessionId=$sessionId, xStreamResponse=$xStreamResponse, body=$body, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" -} diff --git a/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionExecuteAgentResponse.kt b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionExecuteAgentResponse.kt deleted file mode 100644 index 3c3af1d..0000000 --- a/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionExecuteAgentResponse.kt +++ /dev/null @@ -1,158 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. - -package com.browserbase.api.models.sessions - -import com.browserbase.api.core.ExcludeMissing -import com.browserbase.api.core.JsonField -import com.browserbase.api.core.JsonMissing -import com.browserbase.api.core.JsonValue -import com.browserbase.api.errors.StagehandInvalidDataException -import com.fasterxml.jackson.annotation.JsonAnyGetter -import com.fasterxml.jackson.annotation.JsonAnySetter -import com.fasterxml.jackson.annotation.JsonCreator -import com.fasterxml.jackson.annotation.JsonProperty -import java.util.Collections -import java.util.Objects -import java.util.Optional - -class SessionExecuteAgentResponse -@JsonCreator(mode = JsonCreator.Mode.DISABLED) -private constructor( - private val message: JsonField, - private val additionalProperties: MutableMap, -) { - - @JsonCreator - private constructor( - @JsonProperty("message") @ExcludeMissing message: JsonField = JsonMissing.of() - ) : this(message, mutableMapOf()) - - /** - * Final message from the agent - * - * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if the - * server responded with an unexpected value). - */ - fun message(): Optional = message.getOptional("message") - - /** - * Returns the raw JSON value of [message]. - * - * Unlike [message], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("message") @ExcludeMissing fun _message(): JsonField = message - - @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 [SessionExecuteAgentResponse]. - */ - @JvmStatic fun builder() = Builder() - } - - /** A builder for [SessionExecuteAgentResponse]. */ - class Builder internal constructor() { - - private var message: JsonField = JsonMissing.of() - private var additionalProperties: MutableMap = mutableMapOf() - - @JvmSynthetic - internal fun from(sessionExecuteAgentResponse: SessionExecuteAgentResponse) = apply { - message = sessionExecuteAgentResponse.message - additionalProperties = sessionExecuteAgentResponse.additionalProperties.toMutableMap() - } - - /** Final message from the agent */ - fun message(message: String) = message(JsonField.of(message)) - - /** - * Sets [Builder.message] to an arbitrary JSON value. - * - * You should usually call [Builder.message] with a well-typed [String] value instead. This - * method is primarily for setting the field to an undocumented or not yet supported value. - */ - fun message(message: JsonField) = apply { this.message = message } - - 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 [SessionExecuteAgentResponse]. - * - * Further updates to this [Builder] will not mutate the returned instance. - */ - fun build(): SessionExecuteAgentResponse = - SessionExecuteAgentResponse(message, additionalProperties.toMutableMap()) - } - - private var validated: Boolean = false - - fun validate(): SessionExecuteAgentResponse = apply { - if (validated) { - return@apply - } - - message() - 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. - */ - @JvmSynthetic internal fun validity(): Int = (if (message.asKnown().isPresent) 1 else 0) - - override fun equals(other: Any?): Boolean { - if (this === other) { - return true - } - - return other is SessionExecuteAgentResponse && - message == other.message && - additionalProperties == other.additionalProperties - } - - private val hashCode: Int by lazy { Objects.hash(message, additionalProperties) } - - override fun hashCode(): Int = hashCode - - override fun toString() = - "SessionExecuteAgentResponse{message=$message, additionalProperties=$additionalProperties}" -} diff --git a/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionExtractParams.kt b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionExtractParams.kt deleted file mode 100644 index 3833673..0000000 --- a/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionExtractParams.kt +++ /dev/null @@ -1,1064 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. - -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 -import com.browserbase.api.core.JsonValue -import com.browserbase.api.core.Params -import com.browserbase.api.core.http.Headers -import com.browserbase.api.core.http.QueryParams -import com.browserbase.api.core.toImmutable -import com.browserbase.api.errors.StagehandInvalidDataException -import com.fasterxml.jackson.annotation.JsonAnyGetter -import com.fasterxml.jackson.annotation.JsonAnySetter -import com.fasterxml.jackson.annotation.JsonCreator -import com.fasterxml.jackson.annotation.JsonProperty -import java.util.Collections -import java.util.Objects -import java.util.Optional -import kotlin.jvm.optionals.getOrNull - -/** - * Extracts data from the current page using natural language instructions and optional JSON schema - * for structured output. - */ -class SessionExtractParams -private constructor( - private val sessionId: String?, - private val xStreamResponse: XStreamResponse?, - private val body: Body, - private val additionalHeaders: Headers, - private val additionalQueryParams: QueryParams, -) : Params { - - fun sessionId(): Optional = Optional.ofNullable(sessionId) - - fun xStreamResponse(): Optional = Optional.ofNullable(xStreamResponse) - - /** - * Frame ID to extract from - * - * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if the - * server responded with an unexpected value). - */ - fun frameId(): Optional = body.frameId() - - /** - * Natural language instruction for extraction - * - * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if the - * server responded with an unexpected value). - */ - fun instruction(): Optional = body.instruction() - - /** - * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if the - * server responded with an unexpected value). - */ - fun options(): Optional = body.options() - - /** - * JSON Schema for structured output - * - * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if the - * server responded with an unexpected value). - */ - fun schema(): Optional = body.schema() - - /** - * Returns the raw JSON value of [frameId]. - * - * Unlike [frameId], this method doesn't throw if the JSON field has an unexpected type. - */ - fun _frameId(): JsonField = body._frameId() - - /** - * Returns the raw JSON value of [instruction]. - * - * Unlike [instruction], this method doesn't throw if the JSON field has an unexpected type. - */ - fun _instruction(): JsonField = body._instruction() - - /** - * Returns the raw JSON value of [options]. - * - * Unlike [options], this method doesn't throw if the JSON field has an unexpected type. - */ - fun _options(): JsonField = body._options() - - /** - * Returns the raw JSON value of [schema]. - * - * Unlike [schema], this method doesn't throw if the JSON field has an unexpected type. - */ - fun _schema(): JsonField = body._schema() - - fun _additionalBodyProperties(): Map = body._additionalProperties() - - /** Additional headers to send with the request. */ - fun _additionalHeaders(): Headers = additionalHeaders - - /** Additional query param to send with the request. */ - fun _additionalQueryParams(): QueryParams = additionalQueryParams - - fun toBuilder() = Builder().from(this) - - companion object { - - @JvmStatic fun none(): SessionExtractParams = builder().build() - - /** Returns a mutable builder for constructing an instance of [SessionExtractParams]. */ - @JvmStatic fun builder() = Builder() - } - - /** A builder for [SessionExtractParams]. */ - class Builder internal constructor() { - - private var sessionId: String? = null - private var xStreamResponse: XStreamResponse? = null - private var body: Body.Builder = Body.builder() - private var additionalHeaders: Headers.Builder = Headers.builder() - private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() - - @JvmSynthetic - internal fun from(sessionExtractParams: SessionExtractParams) = apply { - sessionId = sessionExtractParams.sessionId - xStreamResponse = sessionExtractParams.xStreamResponse - body = sessionExtractParams.body.toBuilder() - additionalHeaders = sessionExtractParams.additionalHeaders.toBuilder() - additionalQueryParams = sessionExtractParams.additionalQueryParams.toBuilder() - } - - fun sessionId(sessionId: String?) = apply { this.sessionId = sessionId } - - /** Alias for calling [Builder.sessionId] with `sessionId.orElse(null)`. */ - fun sessionId(sessionId: Optional) = sessionId(sessionId.getOrNull()) - - fun xStreamResponse(xStreamResponse: XStreamResponse?) = apply { - this.xStreamResponse = xStreamResponse - } - - /** Alias for calling [Builder.xStreamResponse] with `xStreamResponse.orElse(null)`. */ - fun xStreamResponse(xStreamResponse: Optional) = - xStreamResponse(xStreamResponse.getOrNull()) - - /** - * Sets the entire request body. - * - * This is generally only useful if you are already constructing the body separately. - * Otherwise, it's more convenient to use the top-level setters instead: - * - [frameId] - * - [instruction] - * - [options] - * - [schema] - */ - fun body(body: Body) = apply { this.body = body.toBuilder() } - - /** Frame ID to extract from */ - fun frameId(frameId: String) = apply { body.frameId(frameId) } - - /** - * Sets [Builder.frameId] to an arbitrary JSON value. - * - * You should usually call [Builder.frameId] with a well-typed [String] value instead. This - * method is primarily for setting the field to an undocumented or not yet supported value. - */ - fun frameId(frameId: JsonField) = apply { body.frameId(frameId) } - - /** Natural language instruction for extraction */ - fun instruction(instruction: String) = apply { body.instruction(instruction) } - - /** - * Sets [Builder.instruction] to an arbitrary JSON value. - * - * You should usually call [Builder.instruction] with a well-typed [String] value instead. - * This method is primarily for setting the field to an undocumented or not yet supported - * value. - */ - fun instruction(instruction: JsonField) = apply { body.instruction(instruction) } - - fun options(options: Options) = apply { body.options(options) } - - /** - * Sets [Builder.options] to an arbitrary JSON value. - * - * You should usually call [Builder.options] with a well-typed [Options] value instead. This - * method is primarily for setting the field to an undocumented or not yet supported value. - */ - fun options(options: JsonField) = apply { body.options(options) } - - /** JSON Schema for structured output */ - fun schema(schema: Schema) = apply { body.schema(schema) } - - /** - * Sets [Builder.schema] to an arbitrary JSON value. - * - * You should usually call [Builder.schema] with a well-typed [Schema] value instead. This - * method is primarily for setting the field to an undocumented or not yet supported value. - */ - fun schema(schema: JsonField) = apply { body.schema(schema) } - - fun additionalBodyProperties(additionalBodyProperties: Map) = apply { - body.additionalProperties(additionalBodyProperties) - } - - fun putAdditionalBodyProperty(key: String, value: JsonValue) = apply { - body.putAdditionalProperty(key, value) - } - - fun putAllAdditionalBodyProperties(additionalBodyProperties: Map) = - apply { - body.putAllAdditionalProperties(additionalBodyProperties) - } - - fun removeAdditionalBodyProperty(key: String) = apply { body.removeAdditionalProperty(key) } - - fun removeAllAdditionalBodyProperties(keys: Set) = apply { - body.removeAllAdditionalProperties(keys) - } - - fun additionalHeaders(additionalHeaders: Headers) = apply { - this.additionalHeaders.clear() - putAllAdditionalHeaders(additionalHeaders) - } - - fun additionalHeaders(additionalHeaders: Map>) = apply { - this.additionalHeaders.clear() - putAllAdditionalHeaders(additionalHeaders) - } - - fun putAdditionalHeader(name: String, value: String) = apply { - additionalHeaders.put(name, value) - } - - fun putAdditionalHeaders(name: String, values: Iterable) = apply { - additionalHeaders.put(name, values) - } - - fun putAllAdditionalHeaders(additionalHeaders: Headers) = apply { - this.additionalHeaders.putAll(additionalHeaders) - } - - fun putAllAdditionalHeaders(additionalHeaders: Map>) = apply { - this.additionalHeaders.putAll(additionalHeaders) - } - - fun replaceAdditionalHeaders(name: String, value: String) = apply { - additionalHeaders.replace(name, value) - } - - fun replaceAdditionalHeaders(name: String, values: Iterable) = apply { - additionalHeaders.replace(name, values) - } - - fun replaceAllAdditionalHeaders(additionalHeaders: Headers) = apply { - this.additionalHeaders.replaceAll(additionalHeaders) - } - - fun replaceAllAdditionalHeaders(additionalHeaders: Map>) = apply { - this.additionalHeaders.replaceAll(additionalHeaders) - } - - fun removeAdditionalHeaders(name: String) = apply { additionalHeaders.remove(name) } - - fun removeAllAdditionalHeaders(names: Set) = apply { - additionalHeaders.removeAll(names) - } - - fun additionalQueryParams(additionalQueryParams: QueryParams) = apply { - this.additionalQueryParams.clear() - putAllAdditionalQueryParams(additionalQueryParams) - } - - fun additionalQueryParams(additionalQueryParams: Map>) = apply { - this.additionalQueryParams.clear() - putAllAdditionalQueryParams(additionalQueryParams) - } - - fun putAdditionalQueryParam(key: String, value: String) = apply { - additionalQueryParams.put(key, value) - } - - fun putAdditionalQueryParams(key: String, values: Iterable) = apply { - additionalQueryParams.put(key, values) - } - - fun putAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { - this.additionalQueryParams.putAll(additionalQueryParams) - } - - fun putAllAdditionalQueryParams(additionalQueryParams: Map>) = - apply { - this.additionalQueryParams.putAll(additionalQueryParams) - } - - fun replaceAdditionalQueryParams(key: String, value: String) = apply { - additionalQueryParams.replace(key, value) - } - - fun replaceAdditionalQueryParams(key: String, values: Iterable) = apply { - additionalQueryParams.replace(key, values) - } - - fun replaceAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { - this.additionalQueryParams.replaceAll(additionalQueryParams) - } - - fun replaceAllAdditionalQueryParams(additionalQueryParams: Map>) = - apply { - this.additionalQueryParams.replaceAll(additionalQueryParams) - } - - fun removeAdditionalQueryParams(key: String) = apply { additionalQueryParams.remove(key) } - - fun removeAllAdditionalQueryParams(keys: Set) = apply { - additionalQueryParams.removeAll(keys) - } - - /** - * Returns an immutable instance of [SessionExtractParams]. - * - * Further updates to this [Builder] will not mutate the returned instance. - */ - fun build(): SessionExtractParams = - SessionExtractParams( - sessionId, - xStreamResponse, - body.build(), - additionalHeaders.build(), - additionalQueryParams.build(), - ) - } - - fun _body(): Body = body - - fun _pathParam(index: Int): String = - when (index) { - 0 -> sessionId ?: "" - else -> "" - } - - override fun _headers(): Headers = - Headers.builder() - .apply { - xStreamResponse?.let { put("x-stream-response", it.toString()) } - putAll(additionalHeaders) - } - .build() - - override fun _queryParams(): QueryParams = additionalQueryParams - - class Body - @JsonCreator(mode = JsonCreator.Mode.DISABLED) - private constructor( - private val frameId: JsonField, - private val instruction: JsonField, - private val options: JsonField, - private val schema: JsonField, - private val additionalProperties: MutableMap, - ) { - - @JsonCreator - private constructor( - @JsonProperty("frameId") @ExcludeMissing frameId: JsonField = JsonMissing.of(), - @JsonProperty("instruction") - @ExcludeMissing - instruction: JsonField = JsonMissing.of(), - @JsonProperty("options") @ExcludeMissing options: JsonField = JsonMissing.of(), - @JsonProperty("schema") @ExcludeMissing schema: JsonField = JsonMissing.of(), - ) : this(frameId, instruction, options, schema, mutableMapOf()) - - /** - * Frame ID to extract from - * - * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if - * the server responded with an unexpected value). - */ - fun frameId(): Optional = frameId.getOptional("frameId") - - /** - * Natural language instruction for extraction - * - * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if - * the server responded with an unexpected value). - */ - fun instruction(): Optional = instruction.getOptional("instruction") - - /** - * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if - * the server responded with an unexpected value). - */ - fun options(): Optional = options.getOptional("options") - - /** - * JSON Schema for structured output - * - * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if - * the server responded with an unexpected value). - */ - fun schema(): Optional = schema.getOptional("schema") - - /** - * Returns the raw JSON value of [frameId]. - * - * Unlike [frameId], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("frameId") @ExcludeMissing fun _frameId(): JsonField = frameId - - /** - * Returns the raw JSON value of [instruction]. - * - * Unlike [instruction], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("instruction") - @ExcludeMissing - fun _instruction(): JsonField = instruction - - /** - * Returns the raw JSON value of [options]. - * - * Unlike [options], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("options") @ExcludeMissing fun _options(): JsonField = options - - /** - * Returns the raw JSON value of [schema]. - * - * Unlike [schema], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("schema") @ExcludeMissing fun _schema(): JsonField = schema - - @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 [Body]. */ - @JvmStatic fun builder() = Builder() - } - - /** A builder for [Body]. */ - class Builder internal constructor() { - - private var frameId: JsonField = JsonMissing.of() - private var instruction: JsonField = JsonMissing.of() - private var options: JsonField = JsonMissing.of() - private var schema: JsonField = JsonMissing.of() - private var additionalProperties: MutableMap = mutableMapOf() - - @JvmSynthetic - internal fun from(body: Body) = apply { - frameId = body.frameId - instruction = body.instruction - options = body.options - schema = body.schema - additionalProperties = body.additionalProperties.toMutableMap() - } - - /** Frame ID to extract from */ - fun frameId(frameId: String) = frameId(JsonField.of(frameId)) - - /** - * Sets [Builder.frameId] to an arbitrary JSON value. - * - * You should usually call [Builder.frameId] with a well-typed [String] value instead. - * This method is primarily for setting the field to an undocumented or not yet - * supported value. - */ - fun frameId(frameId: JsonField) = apply { this.frameId = frameId } - - /** Natural language instruction for extraction */ - fun instruction(instruction: String) = instruction(JsonField.of(instruction)) - - /** - * Sets [Builder.instruction] to an arbitrary JSON value. - * - * You should usually call [Builder.instruction] with a well-typed [String] value - * instead. This method is primarily for setting the field to an undocumented or not yet - * supported value. - */ - fun instruction(instruction: JsonField) = apply { - this.instruction = instruction - } - - fun options(options: Options) = options(JsonField.of(options)) - - /** - * Sets [Builder.options] to an arbitrary JSON value. - * - * You should usually call [Builder.options] with a well-typed [Options] value instead. - * This method is primarily for setting the field to an undocumented or not yet - * supported value. - */ - fun options(options: JsonField) = apply { this.options = options } - - /** JSON Schema for structured output */ - fun schema(schema: Schema) = schema(JsonField.of(schema)) - - /** - * Sets [Builder.schema] to an arbitrary JSON value. - * - * You should usually call [Builder.schema] with a well-typed [Schema] value instead. - * This method is primarily for setting the field to an undocumented or not yet - * supported value. - */ - fun schema(schema: JsonField) = apply { this.schema = schema } - - 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 [Body]. - * - * Further updates to this [Builder] will not mutate the returned instance. - */ - fun build(): Body = - Body(frameId, instruction, options, schema, additionalProperties.toMutableMap()) - } - - private var validated: Boolean = false - - fun validate(): Body = apply { - if (validated) { - return@apply - } - - frameId() - instruction() - options().ifPresent { it.validate() } - schema().ifPresent { it.validate() } - 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. - */ - @JvmSynthetic - internal fun validity(): Int = - (if (frameId.asKnown().isPresent) 1 else 0) + - (if (instruction.asKnown().isPresent) 1 else 0) + - (options.asKnown().getOrNull()?.validity() ?: 0) + - (schema.asKnown().getOrNull()?.validity() ?: 0) - - override fun equals(other: Any?): Boolean { - if (this === other) { - return true - } - - return other is Body && - frameId == other.frameId && - instruction == other.instruction && - options == other.options && - schema == other.schema && - additionalProperties == other.additionalProperties - } - - private val hashCode: Int by lazy { - Objects.hash(frameId, instruction, options, schema, additionalProperties) - } - - override fun hashCode(): Int = hashCode - - override fun toString() = - "Body{frameId=$frameId, instruction=$instruction, options=$options, schema=$schema, additionalProperties=$additionalProperties}" - } - - class Options - @JsonCreator(mode = JsonCreator.Mode.DISABLED) - private constructor( - private val model: JsonField, - private val selector: JsonField, - private val timeout: JsonField, - private val additionalProperties: MutableMap, - ) { - - @JsonCreator - private constructor( - @JsonProperty("model") @ExcludeMissing model: JsonField = JsonMissing.of(), - @JsonProperty("selector") - @ExcludeMissing - selector: JsonField = JsonMissing.of(), - @JsonProperty("timeout") @ExcludeMissing timeout: JsonField = JsonMissing.of(), - ) : this(model, selector, timeout, mutableMapOf()) - - /** - * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if - * the server responded with an unexpected value). - */ - fun model(): Optional = model.getOptional("model") - - /** - * Extract only from elements matching this selector - * - * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if - * the server responded with an unexpected value). - */ - fun selector(): Optional = selector.getOptional("selector") - - /** - * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if - * the server responded with an unexpected value). - */ - fun timeout(): Optional = timeout.getOptional("timeout") - - /** - * Returns the raw JSON value of [model]. - * - * Unlike [model], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("model") @ExcludeMissing fun _model(): JsonField = model - - /** - * 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 [timeout]. - * - * Unlike [timeout], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("timeout") @ExcludeMissing fun _timeout(): JsonField = timeout - - @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 [Options]. */ - @JvmStatic fun builder() = Builder() - } - - /** A builder for [Options]. */ - class Builder internal constructor() { - - private var model: JsonField = JsonMissing.of() - private var selector: JsonField = JsonMissing.of() - private var timeout: JsonField = JsonMissing.of() - private var additionalProperties: MutableMap = mutableMapOf() - - @JvmSynthetic - internal fun from(options: Options) = apply { - model = options.model - selector = options.selector - timeout = options.timeout - additionalProperties = options.additionalProperties.toMutableMap() - } - - fun model(model: ModelConfig) = model(JsonField.of(model)) - - /** - * Sets [Builder.model] to an arbitrary JSON value. - * - * You should usually call [Builder.model] with a well-typed [ModelConfig] value - * instead. This method is primarily for setting the field to an undocumented or not yet - * supported value. - */ - fun model(model: JsonField) = apply { this.model = model } - - /** Extract only from elements matching this selector */ - 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 } - - fun timeout(timeout: Long) = timeout(JsonField.of(timeout)) - - /** - * Sets [Builder.timeout] to an arbitrary JSON value. - * - * You should usually call [Builder.timeout] with a well-typed [Long] value instead. - * This method is primarily for setting the field to an undocumented or not yet - * supported value. - */ - fun timeout(timeout: JsonField) = apply { this.timeout = timeout } - - 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 [Options]. - * - * Further updates to this [Builder] will not mutate the returned instance. - */ - fun build(): Options = - Options(model, selector, timeout, additionalProperties.toMutableMap()) - } - - private var validated: Boolean = false - - fun validate(): Options = apply { - if (validated) { - return@apply - } - - model().ifPresent { it.validate() } - selector() - timeout() - 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. - */ - @JvmSynthetic - internal fun validity(): Int = - (model.asKnown().getOrNull()?.validity() ?: 0) + - (if (selector.asKnown().isPresent) 1 else 0) + - (if (timeout.asKnown().isPresent) 1 else 0) - - override fun equals(other: Any?): Boolean { - if (this === other) { - return true - } - - return other is Options && - model == other.model && - selector == other.selector && - timeout == other.timeout && - additionalProperties == other.additionalProperties - } - - private val hashCode: Int by lazy { - Objects.hash(model, selector, timeout, additionalProperties) - } - - override fun hashCode(): Int = hashCode - - override fun toString() = - "Options{model=$model, selector=$selector, timeout=$timeout, additionalProperties=$additionalProperties}" - } - - /** JSON Schema for structured output */ - class Schema - @JsonCreator - private constructor( - @com.fasterxml.jackson.annotation.JsonValue - private val additionalProperties: Map - ) { - - @JsonAnyGetter - @ExcludeMissing - fun _additionalProperties(): Map = additionalProperties - - fun toBuilder() = Builder().from(this) - - companion object { - - /** Returns a mutable builder for constructing an instance of [Schema]. */ - @JvmStatic fun builder() = Builder() - } - - /** A builder for [Schema]. */ - class Builder internal constructor() { - - private var additionalProperties: MutableMap = mutableMapOf() - - @JvmSynthetic - internal fun from(schema: Schema) = apply { - additionalProperties = schema.additionalProperties.toMutableMap() - } - - 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 [Schema]. - * - * Further updates to this [Builder] will not mutate the returned instance. - */ - fun build(): Schema = Schema(additionalProperties.toImmutable()) - } - - private var validated: Boolean = false - - fun validate(): Schema = apply { - if (validated) { - return@apply - } - - 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. - */ - @JvmSynthetic - internal fun validity(): Int = - additionalProperties.count { (_, value) -> !value.isNull() && !value.isMissing() } - - override fun equals(other: Any?): Boolean { - if (this === other) { - return true - } - - return other is Schema && additionalProperties == other.additionalProperties - } - - private val hashCode: Int by lazy { Objects.hash(additionalProperties) } - - override fun hashCode(): Int = hashCode - - override fun toString() = "Schema{additionalProperties=$additionalProperties}" - } - - class XStreamResponse @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 { - - @JvmField val TRUE = of("true") - - @JvmField val FALSE = of("false") - - @JvmStatic fun of(value: String) = XStreamResponse(JsonField.of(value)) - } - - /** An enum containing [XStreamResponse]'s known values. */ - enum class Known { - TRUE, - FALSE, - } - - /** - * An enum containing [XStreamResponse]'s known values, as well as an [_UNKNOWN] member. - * - * An instance of [XStreamResponse] 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, - FALSE, - /** - * An enum member indicating that [XStreamResponse] 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 - FALSE -> Value.FALSE - 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 - FALSE -> Known.FALSE - else -> throw StagehandInvalidDataException("Unknown XStreamResponse: $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().orElseThrow { - StagehandInvalidDataException("Value is not a String") - } - - private var validated: Boolean = false - - fun validate(): XStreamResponse = 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. - */ - @JvmSynthetic 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 XStreamResponse && 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 SessionExtractParams && - sessionId == other.sessionId && - xStreamResponse == other.xStreamResponse && - body == other.body && - additionalHeaders == other.additionalHeaders && - additionalQueryParams == other.additionalQueryParams - } - - override fun hashCode(): Int = - Objects.hash(sessionId, xStreamResponse, body, additionalHeaders, additionalQueryParams) - - override fun toString() = - "SessionExtractParams{sessionId=$sessionId, xStreamResponse=$xStreamResponse, body=$body, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" -} diff --git a/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionExtractResponse.kt b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionExtractResponse.kt deleted file mode 100644 index 6816259..0000000 --- a/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionExtractResponse.kt +++ /dev/null @@ -1,457 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. - -package com.browserbase.api.models.sessions - -import com.browserbase.api.core.BaseDeserializer -import com.browserbase.api.core.BaseSerializer -import com.browserbase.api.core.ExcludeMissing -import com.browserbase.api.core.JsonField -import com.browserbase.api.core.JsonMissing -import com.browserbase.api.core.JsonValue -import com.browserbase.api.core.allMaxBy -import com.browserbase.api.core.getOrThrow -import com.browserbase.api.core.toImmutable -import com.browserbase.api.errors.StagehandInvalidDataException -import com.fasterxml.jackson.annotation.JsonAnyGetter -import com.fasterxml.jackson.annotation.JsonAnySetter -import com.fasterxml.jackson.annotation.JsonCreator -import com.fasterxml.jackson.annotation.JsonProperty -import com.fasterxml.jackson.core.JsonGenerator -import com.fasterxml.jackson.core.ObjectCodec -import com.fasterxml.jackson.databind.JsonNode -import com.fasterxml.jackson.databind.SerializerProvider -import com.fasterxml.jackson.databind.annotation.JsonDeserialize -import com.fasterxml.jackson.databind.annotation.JsonSerialize -import com.fasterxml.jackson.module.kotlin.jacksonTypeRef -import java.util.Collections -import java.util.Objects -import java.util.Optional - -/** Default extraction result */ -@JsonDeserialize(using = SessionExtractResponse.Deserializer::class) -@JsonSerialize(using = SessionExtractResponse.Serializer::class) -class SessionExtractResponse -private constructor( - private val extraction: Extraction? = null, - private val custom: Custom? = null, - private val _json: JsonValue? = null, -) { - - /** Default extraction result */ - fun extraction(): Optional = Optional.ofNullable(extraction) - - /** Structured data matching provided schema */ - fun custom(): Optional = Optional.ofNullable(custom) - - fun isExtraction(): Boolean = extraction != null - - fun isCustom(): Boolean = custom != null - - /** Default extraction result */ - fun asExtraction(): Extraction = extraction.getOrThrow("extraction") - - /** Structured data matching provided schema */ - fun asCustom(): Custom = custom.getOrThrow("custom") - - fun _json(): Optional = Optional.ofNullable(_json) - - fun accept(visitor: Visitor): T = - when { - extraction != null -> visitor.visitExtraction(extraction) - custom != null -> visitor.visitCustom(custom) - else -> visitor.unknown(_json) - } - - private var validated: Boolean = false - - fun validate(): SessionExtractResponse = apply { - if (validated) { - return@apply - } - - accept( - object : Visitor { - override fun visitExtraction(extraction: Extraction) { - extraction.validate() - } - - override fun visitCustom(custom: Custom) { - custom.validate() - } - } - ) - 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. - */ - @JvmSynthetic - internal fun validity(): Int = - accept( - object : Visitor { - override fun visitExtraction(extraction: Extraction) = extraction.validity() - - override fun visitCustom(custom: Custom) = custom.validity() - - override fun unknown(json: JsonValue?) = 0 - } - ) - - override fun equals(other: Any?): Boolean { - if (this === other) { - return true - } - - return other is SessionExtractResponse && - extraction == other.extraction && - custom == other.custom - } - - override fun hashCode(): Int = Objects.hash(extraction, custom) - - override fun toString(): String = - when { - extraction != null -> "SessionExtractResponse{extraction=$extraction}" - custom != null -> "SessionExtractResponse{custom=$custom}" - _json != null -> "SessionExtractResponse{_unknown=$_json}" - else -> throw IllegalStateException("Invalid SessionExtractResponse") - } - - companion object { - - /** Default extraction result */ - @JvmStatic - fun ofExtraction(extraction: Extraction) = SessionExtractResponse(extraction = extraction) - - /** Structured data matching provided schema */ - @JvmStatic fun ofCustom(custom: Custom) = SessionExtractResponse(custom = custom) - } - - /** - * An interface that defines how to map each variant of [SessionExtractResponse] to a value of - * type [T]. - */ - interface Visitor { - - /** Default extraction result */ - fun visitExtraction(extraction: Extraction): T - - /** Structured data matching provided schema */ - fun visitCustom(custom: Custom): T - - /** - * Maps an unknown variant of [SessionExtractResponse] to a value of type [T]. - * - * An instance of [SessionExtractResponse] can contain an unknown variant if it was - * deserialized from data that doesn't match any known variant. For example, if the SDK is - * on an older version than the API, then the API may respond with new variants that the SDK - * is unaware of. - * - * @throws StagehandInvalidDataException in the default implementation. - */ - fun unknown(json: JsonValue?): T { - throw StagehandInvalidDataException("Unknown SessionExtractResponse: $json") - } - } - - internal class Deserializer : - BaseDeserializer(SessionExtractResponse::class) { - - override fun ObjectCodec.deserialize(node: JsonNode): SessionExtractResponse { - val json = JsonValue.fromJsonNode(node) - - val bestMatches = - sequenceOf( - tryDeserialize(node, jacksonTypeRef())?.let { - SessionExtractResponse(extraction = it, _json = json) - }, - tryDeserialize(node, jacksonTypeRef())?.let { - SessionExtractResponse(custom = it, _json = json) - }, - ) - .filterNotNull() - .allMaxBy { it.validity() } - .toList() - return when (bestMatches.size) { - // This can happen if what we're deserializing is completely incompatible with all - // the possible variants (e.g. deserializing from boolean). - 0 -> SessionExtractResponse(_json = json) - 1 -> bestMatches.single() - // If there's more than one match with the highest validity, then use the first - // completely valid match, or simply the first match if none are completely valid. - else -> bestMatches.firstOrNull { it.isValid() } ?: bestMatches.first() - } - } - } - - internal class Serializer : - BaseSerializer(SessionExtractResponse::class) { - - override fun serialize( - value: SessionExtractResponse, - generator: JsonGenerator, - provider: SerializerProvider, - ) { - when { - value.extraction != null -> generator.writeObject(value.extraction) - value.custom != null -> generator.writeObject(value.custom) - value._json != null -> generator.writeObject(value._json) - else -> throw IllegalStateException("Invalid SessionExtractResponse") - } - } - } - - /** Default extraction result */ - class Extraction - @JsonCreator(mode = JsonCreator.Mode.DISABLED) - private constructor( - private val extraction: JsonField, - private val additionalProperties: MutableMap, - ) { - - @JsonCreator - private constructor( - @JsonProperty("extraction") - @ExcludeMissing - extraction: JsonField = JsonMissing.of() - ) : this(extraction, mutableMapOf()) - - /** - * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if - * the server responded with an unexpected value). - */ - fun extraction(): Optional = extraction.getOptional("extraction") - - /** - * Returns the raw JSON value of [extraction]. - * - * Unlike [extraction], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("extraction") - @ExcludeMissing - fun _extraction(): JsonField = extraction - - @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 [Extraction]. */ - @JvmStatic fun builder() = Builder() - } - - /** A builder for [Extraction]. */ - class Builder internal constructor() { - - private var extraction: JsonField = JsonMissing.of() - private var additionalProperties: MutableMap = mutableMapOf() - - @JvmSynthetic - internal fun from(extraction: Extraction) = apply { - this.extraction = extraction.extraction - additionalProperties = extraction.additionalProperties.toMutableMap() - } - - fun extraction(extraction: String) = extraction(JsonField.of(extraction)) - - /** - * Sets [Builder.extraction] to an arbitrary JSON value. - * - * You should usually call [Builder.extraction] with a well-typed [String] value - * instead. This method is primarily for setting the field to an undocumented or not yet - * supported value. - */ - fun extraction(extraction: JsonField) = apply { this.extraction = extraction } - - 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 [Extraction]. - * - * Further updates to this [Builder] will not mutate the returned instance. - */ - fun build(): Extraction = Extraction(extraction, additionalProperties.toMutableMap()) - } - - private var validated: Boolean = false - - fun validate(): Extraction = apply { - if (validated) { - return@apply - } - - extraction() - 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. - */ - @JvmSynthetic internal fun validity(): Int = (if (extraction.asKnown().isPresent) 1 else 0) - - override fun equals(other: Any?): Boolean { - if (this === other) { - return true - } - - return other is Extraction && - extraction == other.extraction && - additionalProperties == other.additionalProperties - } - - private val hashCode: Int by lazy { Objects.hash(extraction, additionalProperties) } - - override fun hashCode(): Int = hashCode - - override fun toString() = - "Extraction{extraction=$extraction, additionalProperties=$additionalProperties}" - } - - /** Structured data matching provided schema */ - class Custom - @JsonCreator - private constructor( - @com.fasterxml.jackson.annotation.JsonValue - private val additionalProperties: Map - ) { - - @JsonAnyGetter - @ExcludeMissing - fun _additionalProperties(): Map = additionalProperties - - fun toBuilder() = Builder().from(this) - - companion object { - - /** Returns a mutable builder for constructing an instance of [Custom]. */ - @JvmStatic fun builder() = Builder() - } - - /** A builder for [Custom]. */ - class Builder internal constructor() { - - private var additionalProperties: MutableMap = mutableMapOf() - - @JvmSynthetic - internal fun from(custom: Custom) = apply { - additionalProperties = custom.additionalProperties.toMutableMap() - } - - 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 [Custom]. - * - * Further updates to this [Builder] will not mutate the returned instance. - */ - fun build(): Custom = Custom(additionalProperties.toImmutable()) - } - - private var validated: Boolean = false - - fun validate(): Custom = apply { - if (validated) { - return@apply - } - - 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. - */ - @JvmSynthetic - internal fun validity(): Int = - additionalProperties.count { (_, value) -> !value.isNull() && !value.isMissing() } - - override fun equals(other: Any?): Boolean { - if (this === other) { - return true - } - - return other is Custom && additionalProperties == other.additionalProperties - } - - private val hashCode: Int by lazy { Objects.hash(additionalProperties) } - - override fun hashCode(): Int = hashCode - - override fun toString() = "Custom{additionalProperties=$additionalProperties}" - } -} diff --git a/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionNavigateParams.kt b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionNavigateParams.kt deleted file mode 100644 index e57efd3..0000000 --- a/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionNavigateParams.kt +++ /dev/null @@ -1,992 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. - -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 -import com.browserbase.api.core.JsonValue -import com.browserbase.api.core.Params -import com.browserbase.api.core.checkRequired -import com.browserbase.api.core.http.Headers -import com.browserbase.api.core.http.QueryParams -import com.browserbase.api.errors.StagehandInvalidDataException -import com.fasterxml.jackson.annotation.JsonAnyGetter -import com.fasterxml.jackson.annotation.JsonAnySetter -import com.fasterxml.jackson.annotation.JsonCreator -import com.fasterxml.jackson.annotation.JsonProperty -import java.util.Collections -import java.util.Objects -import java.util.Optional -import kotlin.jvm.optionals.getOrNull - -/** Navigates the browser to the specified URL and waits for page load. */ -class SessionNavigateParams -private constructor( - private val sessionId: String?, - private val xStreamResponse: XStreamResponse?, - private val body: Body, - private val additionalHeaders: Headers, - private val additionalQueryParams: QueryParams, -) : Params { - - fun sessionId(): Optional = Optional.ofNullable(sessionId) - - fun xStreamResponse(): Optional = Optional.ofNullable(xStreamResponse) - - /** - * URL to navigate to - * - * @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 url(): String = body.url() - - /** - * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if the - * server responded with an unexpected value). - */ - fun frameId(): Optional = body.frameId() - - /** - * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if the - * server responded with an unexpected value). - */ - fun options(): Optional = body.options() - - /** - * Returns the raw JSON value of [url]. - * - * Unlike [url], this method doesn't throw if the JSON field has an unexpected type. - */ - fun _url(): JsonField = body._url() - - /** - * Returns the raw JSON value of [frameId]. - * - * Unlike [frameId], this method doesn't throw if the JSON field has an unexpected type. - */ - fun _frameId(): JsonField = body._frameId() - - /** - * Returns the raw JSON value of [options]. - * - * Unlike [options], this method doesn't throw if the JSON field has an unexpected type. - */ - fun _options(): JsonField = body._options() - - fun _additionalBodyProperties(): Map = body._additionalProperties() - - /** Additional headers to send with the request. */ - fun _additionalHeaders(): Headers = additionalHeaders - - /** Additional query param to send with the request. */ - fun _additionalQueryParams(): QueryParams = additionalQueryParams - - fun toBuilder() = Builder().from(this) - - companion object { - - /** - * Returns a mutable builder for constructing an instance of [SessionNavigateParams]. - * - * The following fields are required: - * ```java - * .url() - * ``` - */ - @JvmStatic fun builder() = Builder() - } - - /** A builder for [SessionNavigateParams]. */ - class Builder internal constructor() { - - private var sessionId: String? = null - private var xStreamResponse: XStreamResponse? = null - private var body: Body.Builder = Body.builder() - private var additionalHeaders: Headers.Builder = Headers.builder() - private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() - - @JvmSynthetic - internal fun from(sessionNavigateParams: SessionNavigateParams) = apply { - sessionId = sessionNavigateParams.sessionId - xStreamResponse = sessionNavigateParams.xStreamResponse - body = sessionNavigateParams.body.toBuilder() - additionalHeaders = sessionNavigateParams.additionalHeaders.toBuilder() - additionalQueryParams = sessionNavigateParams.additionalQueryParams.toBuilder() - } - - fun sessionId(sessionId: String?) = apply { this.sessionId = sessionId } - - /** Alias for calling [Builder.sessionId] with `sessionId.orElse(null)`. */ - fun sessionId(sessionId: Optional) = sessionId(sessionId.getOrNull()) - - fun xStreamResponse(xStreamResponse: XStreamResponse?) = apply { - this.xStreamResponse = xStreamResponse - } - - /** Alias for calling [Builder.xStreamResponse] with `xStreamResponse.orElse(null)`. */ - fun xStreamResponse(xStreamResponse: Optional) = - xStreamResponse(xStreamResponse.getOrNull()) - - /** - * Sets the entire request body. - * - * This is generally only useful if you are already constructing the body separately. - * Otherwise, it's more convenient to use the top-level setters instead: - * - [url] - * - [frameId] - * - [options] - */ - fun body(body: Body) = apply { this.body = body.toBuilder() } - - /** URL to navigate to */ - fun url(url: String) = apply { body.url(url) } - - /** - * Sets [Builder.url] to an arbitrary JSON value. - * - * You should usually call [Builder.url] with a well-typed [String] value instead. This - * method is primarily for setting the field to an undocumented or not yet supported value. - */ - fun url(url: JsonField) = apply { body.url(url) } - - fun frameId(frameId: String) = apply { body.frameId(frameId) } - - /** - * Sets [Builder.frameId] to an arbitrary JSON value. - * - * You should usually call [Builder.frameId] with a well-typed [String] value instead. This - * method is primarily for setting the field to an undocumented or not yet supported value. - */ - fun frameId(frameId: JsonField) = apply { body.frameId(frameId) } - - fun options(options: Options) = apply { body.options(options) } - - /** - * Sets [Builder.options] to an arbitrary JSON value. - * - * You should usually call [Builder.options] with a well-typed [Options] value instead. This - * method is primarily for setting the field to an undocumented or not yet supported value. - */ - fun options(options: JsonField) = apply { body.options(options) } - - fun additionalBodyProperties(additionalBodyProperties: Map) = apply { - body.additionalProperties(additionalBodyProperties) - } - - fun putAdditionalBodyProperty(key: String, value: JsonValue) = apply { - body.putAdditionalProperty(key, value) - } - - fun putAllAdditionalBodyProperties(additionalBodyProperties: Map) = - apply { - body.putAllAdditionalProperties(additionalBodyProperties) - } - - fun removeAdditionalBodyProperty(key: String) = apply { body.removeAdditionalProperty(key) } - - fun removeAllAdditionalBodyProperties(keys: Set) = apply { - body.removeAllAdditionalProperties(keys) - } - - fun additionalHeaders(additionalHeaders: Headers) = apply { - this.additionalHeaders.clear() - putAllAdditionalHeaders(additionalHeaders) - } - - fun additionalHeaders(additionalHeaders: Map>) = apply { - this.additionalHeaders.clear() - putAllAdditionalHeaders(additionalHeaders) - } - - fun putAdditionalHeader(name: String, value: String) = apply { - additionalHeaders.put(name, value) - } - - fun putAdditionalHeaders(name: String, values: Iterable) = apply { - additionalHeaders.put(name, values) - } - - fun putAllAdditionalHeaders(additionalHeaders: Headers) = apply { - this.additionalHeaders.putAll(additionalHeaders) - } - - fun putAllAdditionalHeaders(additionalHeaders: Map>) = apply { - this.additionalHeaders.putAll(additionalHeaders) - } - - fun replaceAdditionalHeaders(name: String, value: String) = apply { - additionalHeaders.replace(name, value) - } - - fun replaceAdditionalHeaders(name: String, values: Iterable) = apply { - additionalHeaders.replace(name, values) - } - - fun replaceAllAdditionalHeaders(additionalHeaders: Headers) = apply { - this.additionalHeaders.replaceAll(additionalHeaders) - } - - fun replaceAllAdditionalHeaders(additionalHeaders: Map>) = apply { - this.additionalHeaders.replaceAll(additionalHeaders) - } - - fun removeAdditionalHeaders(name: String) = apply { additionalHeaders.remove(name) } - - fun removeAllAdditionalHeaders(names: Set) = apply { - additionalHeaders.removeAll(names) - } - - fun additionalQueryParams(additionalQueryParams: QueryParams) = apply { - this.additionalQueryParams.clear() - putAllAdditionalQueryParams(additionalQueryParams) - } - - fun additionalQueryParams(additionalQueryParams: Map>) = apply { - this.additionalQueryParams.clear() - putAllAdditionalQueryParams(additionalQueryParams) - } - - fun putAdditionalQueryParam(key: String, value: String) = apply { - additionalQueryParams.put(key, value) - } - - fun putAdditionalQueryParams(key: String, values: Iterable) = apply { - additionalQueryParams.put(key, values) - } - - fun putAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { - this.additionalQueryParams.putAll(additionalQueryParams) - } - - fun putAllAdditionalQueryParams(additionalQueryParams: Map>) = - apply { - this.additionalQueryParams.putAll(additionalQueryParams) - } - - fun replaceAdditionalQueryParams(key: String, value: String) = apply { - additionalQueryParams.replace(key, value) - } - - fun replaceAdditionalQueryParams(key: String, values: Iterable) = apply { - additionalQueryParams.replace(key, values) - } - - fun replaceAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { - this.additionalQueryParams.replaceAll(additionalQueryParams) - } - - fun replaceAllAdditionalQueryParams(additionalQueryParams: Map>) = - apply { - this.additionalQueryParams.replaceAll(additionalQueryParams) - } - - fun removeAdditionalQueryParams(key: String) = apply { additionalQueryParams.remove(key) } - - fun removeAllAdditionalQueryParams(keys: Set) = apply { - additionalQueryParams.removeAll(keys) - } - - /** - * Returns an immutable instance of [SessionNavigateParams]. - * - * Further updates to this [Builder] will not mutate the returned instance. - * - * The following fields are required: - * ```java - * .url() - * ``` - * - * @throws IllegalStateException if any required field is unset. - */ - fun build(): SessionNavigateParams = - SessionNavigateParams( - sessionId, - xStreamResponse, - body.build(), - additionalHeaders.build(), - additionalQueryParams.build(), - ) - } - - fun _body(): Body = body - - fun _pathParam(index: Int): String = - when (index) { - 0 -> sessionId ?: "" - else -> "" - } - - override fun _headers(): Headers = - Headers.builder() - .apply { - xStreamResponse?.let { put("x-stream-response", it.toString()) } - putAll(additionalHeaders) - } - .build() - - override fun _queryParams(): QueryParams = additionalQueryParams - - class Body - @JsonCreator(mode = JsonCreator.Mode.DISABLED) - private constructor( - private val url: JsonField, - private val frameId: JsonField, - private val options: JsonField, - private val additionalProperties: MutableMap, - ) { - - @JsonCreator - private constructor( - @JsonProperty("url") @ExcludeMissing url: JsonField = JsonMissing.of(), - @JsonProperty("frameId") @ExcludeMissing frameId: JsonField = JsonMissing.of(), - @JsonProperty("options") @ExcludeMissing options: JsonField = JsonMissing.of(), - ) : this(url, frameId, options, mutableMapOf()) - - /** - * URL to navigate to - * - * @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 url(): String = url.getRequired("url") - - /** - * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if - * the server responded with an unexpected value). - */ - fun frameId(): Optional = frameId.getOptional("frameId") - - /** - * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if - * the server responded with an unexpected value). - */ - fun options(): Optional = options.getOptional("options") - - /** - * Returns the raw JSON value of [url]. - * - * Unlike [url], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("url") @ExcludeMissing fun _url(): JsonField = url - - /** - * Returns the raw JSON value of [frameId]. - * - * Unlike [frameId], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("frameId") @ExcludeMissing fun _frameId(): JsonField = frameId - - /** - * Returns the raw JSON value of [options]. - * - * Unlike [options], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("options") @ExcludeMissing fun _options(): JsonField = options - - @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 [Body]. - * - * The following fields are required: - * ```java - * .url() - * ``` - */ - @JvmStatic fun builder() = Builder() - } - - /** A builder for [Body]. */ - class Builder internal constructor() { - - private var url: JsonField? = null - private var frameId: JsonField = JsonMissing.of() - private var options: JsonField = JsonMissing.of() - private var additionalProperties: MutableMap = mutableMapOf() - - @JvmSynthetic - internal fun from(body: Body) = apply { - url = body.url - frameId = body.frameId - options = body.options - additionalProperties = body.additionalProperties.toMutableMap() - } - - /** URL to navigate to */ - fun url(url: String) = url(JsonField.of(url)) - - /** - * Sets [Builder.url] to an arbitrary JSON value. - * - * You should usually call [Builder.url] with a well-typed [String] value instead. This - * method is primarily for setting the field to an undocumented or not yet supported - * value. - */ - fun url(url: JsonField) = apply { this.url = url } - - fun frameId(frameId: String) = frameId(JsonField.of(frameId)) - - /** - * Sets [Builder.frameId] to an arbitrary JSON value. - * - * You should usually call [Builder.frameId] with a well-typed [String] value instead. - * This method is primarily for setting the field to an undocumented or not yet - * supported value. - */ - fun frameId(frameId: JsonField) = apply { this.frameId = frameId } - - fun options(options: Options) = options(JsonField.of(options)) - - /** - * Sets [Builder.options] to an arbitrary JSON value. - * - * You should usually call [Builder.options] with a well-typed [Options] value instead. - * This method is primarily for setting the field to an undocumented or not yet - * supported value. - */ - fun options(options: JsonField) = apply { this.options = options } - - 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 [Body]. - * - * Further updates to this [Builder] will not mutate the returned instance. - * - * The following fields are required: - * ```java - * .url() - * ``` - * - * @throws IllegalStateException if any required field is unset. - */ - fun build(): Body = - Body( - checkRequired("url", url), - frameId, - options, - additionalProperties.toMutableMap(), - ) - } - - private var validated: Boolean = false - - fun validate(): Body = apply { - if (validated) { - return@apply - } - - url() - frameId() - options().ifPresent { it.validate() } - 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. - */ - @JvmSynthetic - internal fun validity(): Int = - (if (url.asKnown().isPresent) 1 else 0) + - (if (frameId.asKnown().isPresent) 1 else 0) + - (options.asKnown().getOrNull()?.validity() ?: 0) - - override fun equals(other: Any?): Boolean { - if (this === other) { - return true - } - - return other is Body && - url == other.url && - frameId == other.frameId && - options == other.options && - additionalProperties == other.additionalProperties - } - - private val hashCode: Int by lazy { - Objects.hash(url, frameId, options, additionalProperties) - } - - override fun hashCode(): Int = hashCode - - override fun toString() = - "Body{url=$url, frameId=$frameId, options=$options, additionalProperties=$additionalProperties}" - } - - class Options - @JsonCreator(mode = JsonCreator.Mode.DISABLED) - private constructor( - private val waitUntil: JsonField, - private val additionalProperties: MutableMap, - ) { - - @JsonCreator - private constructor( - @JsonProperty("waitUntil") - @ExcludeMissing - waitUntil: JsonField = JsonMissing.of() - ) : this(waitUntil, mutableMapOf()) - - /** - * When to consider navigation complete - * - * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if - * the server responded with an unexpected value). - */ - fun waitUntil(): Optional = waitUntil.getOptional("waitUntil") - - /** - * Returns the raw JSON value of [waitUntil]. - * - * Unlike [waitUntil], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("waitUntil") - @ExcludeMissing - fun _waitUntil(): JsonField = waitUntil - - @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 [Options]. */ - @JvmStatic fun builder() = Builder() - } - - /** A builder for [Options]. */ - class Builder internal constructor() { - - private var waitUntil: JsonField = JsonMissing.of() - private var additionalProperties: MutableMap = mutableMapOf() - - @JvmSynthetic - internal fun from(options: Options) = apply { - waitUntil = options.waitUntil - additionalProperties = options.additionalProperties.toMutableMap() - } - - /** When to consider navigation complete */ - fun waitUntil(waitUntil: WaitUntil) = waitUntil(JsonField.of(waitUntil)) - - /** - * Sets [Builder.waitUntil] to an arbitrary JSON value. - * - * You should usually call [Builder.waitUntil] with a well-typed [WaitUntil] value - * instead. This method is primarily for setting the field to an undocumented or not yet - * supported value. - */ - fun waitUntil(waitUntil: JsonField) = apply { this.waitUntil = waitUntil } - - 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 [Options]. - * - * Further updates to this [Builder] will not mutate the returned instance. - */ - fun build(): Options = Options(waitUntil, additionalProperties.toMutableMap()) - } - - private var validated: Boolean = false - - fun validate(): Options = apply { - if (validated) { - return@apply - } - - waitUntil().ifPresent { it.validate() } - 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. - */ - @JvmSynthetic - internal fun validity(): Int = (waitUntil.asKnown().getOrNull()?.validity() ?: 0) - - /** When to consider navigation complete */ - class WaitUntil @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 { - - @JvmField val LOAD = of("load") - - @JvmField val DOMCONTENTLOADED = of("domcontentloaded") - - @JvmField val NETWORKIDLE = of("networkidle") - - @JvmStatic fun of(value: String) = WaitUntil(JsonField.of(value)) - } - - /** An enum containing [WaitUntil]'s known values. */ - enum class Known { - LOAD, - DOMCONTENTLOADED, - NETWORKIDLE, - } - - /** - * An enum containing [WaitUntil]'s known values, as well as an [_UNKNOWN] member. - * - * An instance of [WaitUntil] 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 { - LOAD, - DOMCONTENTLOADED, - NETWORKIDLE, - /** - * An enum member indicating that [WaitUntil] 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) { - LOAD -> Value.LOAD - DOMCONTENTLOADED -> Value.DOMCONTENTLOADED - NETWORKIDLE -> Value.NETWORKIDLE - 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) { - LOAD -> Known.LOAD - DOMCONTENTLOADED -> Known.DOMCONTENTLOADED - NETWORKIDLE -> Known.NETWORKIDLE - else -> throw StagehandInvalidDataException("Unknown WaitUntil: $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().orElseThrow { - StagehandInvalidDataException("Value is not a String") - } - - private var validated: Boolean = false - - fun validate(): WaitUntil = 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. - */ - @JvmSynthetic 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 WaitUntil && 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 Options && - waitUntil == other.waitUntil && - additionalProperties == other.additionalProperties - } - - private val hashCode: Int by lazy { Objects.hash(waitUntil, additionalProperties) } - - override fun hashCode(): Int = hashCode - - override fun toString() = - "Options{waitUntil=$waitUntil, additionalProperties=$additionalProperties}" - } - - class XStreamResponse @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 { - - @JvmField val TRUE = of("true") - - @JvmField val FALSE = of("false") - - @JvmStatic fun of(value: String) = XStreamResponse(JsonField.of(value)) - } - - /** An enum containing [XStreamResponse]'s known values. */ - enum class Known { - TRUE, - FALSE, - } - - /** - * An enum containing [XStreamResponse]'s known values, as well as an [_UNKNOWN] member. - * - * An instance of [XStreamResponse] 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, - FALSE, - /** - * An enum member indicating that [XStreamResponse] 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 - FALSE -> Value.FALSE - 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 - FALSE -> Known.FALSE - else -> throw StagehandInvalidDataException("Unknown XStreamResponse: $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().orElseThrow { - StagehandInvalidDataException("Value is not a String") - } - - private var validated: Boolean = false - - fun validate(): XStreamResponse = 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. - */ - @JvmSynthetic 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 XStreamResponse && 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 SessionNavigateParams && - sessionId == other.sessionId && - xStreamResponse == other.xStreamResponse && - body == other.body && - additionalHeaders == other.additionalHeaders && - additionalQueryParams == other.additionalQueryParams - } - - override fun hashCode(): Int = - Objects.hash(sessionId, xStreamResponse, body, additionalHeaders, additionalQueryParams) - - override fun toString() = - "SessionNavigateParams{sessionId=$sessionId, xStreamResponse=$xStreamResponse, body=$body, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" -} diff --git a/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionNavigateResponse.kt b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionNavigateResponse.kt deleted file mode 100644 index 50422bd..0000000 --- a/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionNavigateResponse.kt +++ /dev/null @@ -1,216 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. - -package com.browserbase.api.models.sessions - -import com.browserbase.api.core.ExcludeMissing -import com.browserbase.api.core.JsonField -import com.browserbase.api.core.JsonMissing -import com.browserbase.api.core.JsonValue -import com.browserbase.api.errors.StagehandInvalidDataException -import com.fasterxml.jackson.annotation.JsonAnyGetter -import com.fasterxml.jackson.annotation.JsonAnySetter -import com.fasterxml.jackson.annotation.JsonCreator -import com.fasterxml.jackson.annotation.JsonProperty -import java.util.Collections -import java.util.Objects -import java.util.Optional - -/** Navigation response (may be null) */ -class SessionNavigateResponse -@JsonCreator(mode = JsonCreator.Mode.DISABLED) -private constructor( - private val ok: JsonField, - private val status: JsonField, - private val url: JsonField, - private val additionalProperties: MutableMap, -) { - - @JsonCreator - private constructor( - @JsonProperty("ok") @ExcludeMissing ok: JsonField = JsonMissing.of(), - @JsonProperty("status") @ExcludeMissing status: JsonField = JsonMissing.of(), - @JsonProperty("url") @ExcludeMissing url: JsonField = JsonMissing.of(), - ) : this(ok, status, url, mutableMapOf()) - - /** - * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if the - * server responded with an unexpected value). - */ - fun ok(): Optional = ok.getOptional("ok") - - /** - * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if the - * server responded with an unexpected value). - */ - fun status(): Optional = status.getOptional("status") - - /** - * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if the - * server responded with an unexpected value). - */ - fun url(): Optional = url.getOptional("url") - - /** - * Returns the raw JSON value of [ok]. - * - * Unlike [ok], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("ok") @ExcludeMissing fun _ok(): JsonField = ok - - /** - * Returns the raw JSON value of [status]. - * - * Unlike [status], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("status") @ExcludeMissing fun _status(): JsonField = status - - /** - * Returns the raw JSON value of [url]. - * - * Unlike [url], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("url") @ExcludeMissing fun _url(): JsonField = url - - @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 [SessionNavigateResponse]. */ - @JvmStatic fun builder() = Builder() - } - - /** A builder for [SessionNavigateResponse]. */ - class Builder internal constructor() { - - private var ok: JsonField = JsonMissing.of() - private var status: JsonField = JsonMissing.of() - private var url: JsonField = JsonMissing.of() - private var additionalProperties: MutableMap = mutableMapOf() - - @JvmSynthetic - internal fun from(sessionNavigateResponse: SessionNavigateResponse) = apply { - ok = sessionNavigateResponse.ok - status = sessionNavigateResponse.status - url = sessionNavigateResponse.url - additionalProperties = sessionNavigateResponse.additionalProperties.toMutableMap() - } - - fun ok(ok: Boolean) = ok(JsonField.of(ok)) - - /** - * Sets [Builder.ok] to an arbitrary JSON value. - * - * You should usually call [Builder.ok] with a well-typed [Boolean] value instead. This - * method is primarily for setting the field to an undocumented or not yet supported value. - */ - fun ok(ok: JsonField) = apply { this.ok = ok } - - fun status(status: Long) = status(JsonField.of(status)) - - /** - * Sets [Builder.status] to an arbitrary JSON value. - * - * You should usually call [Builder.status] with a well-typed [Long] value instead. This - * method is primarily for setting the field to an undocumented or not yet supported value. - */ - fun status(status: JsonField) = apply { this.status = status } - - fun url(url: String) = url(JsonField.of(url)) - - /** - * Sets [Builder.url] to an arbitrary JSON value. - * - * You should usually call [Builder.url] with a well-typed [String] value instead. This - * method is primarily for setting the field to an undocumented or not yet supported value. - */ - fun url(url: JsonField) = apply { this.url = url } - - 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 [SessionNavigateResponse]. - * - * Further updates to this [Builder] will not mutate the returned instance. - */ - fun build(): SessionNavigateResponse = - SessionNavigateResponse(ok, status, url, additionalProperties.toMutableMap()) - } - - private var validated: Boolean = false - - fun validate(): SessionNavigateResponse = apply { - if (validated) { - return@apply - } - - ok() - status() - url() - 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. - */ - @JvmSynthetic - internal fun validity(): Int = - (if (ok.asKnown().isPresent) 1 else 0) + - (if (status.asKnown().isPresent) 1 else 0) + - (if (url.asKnown().isPresent) 1 else 0) - - override fun equals(other: Any?): Boolean { - if (this === other) { - return true - } - - return other is SessionNavigateResponse && - ok == other.ok && - status == other.status && - url == other.url && - additionalProperties == other.additionalProperties - } - - private val hashCode: Int by lazy { Objects.hash(ok, status, url, additionalProperties) } - - override fun hashCode(): Int = hashCode - - override fun toString() = - "SessionNavigateResponse{ok=$ok, status=$status, url=$url, additionalProperties=$additionalProperties}" -} diff --git a/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionObserveParams.kt b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionObserveParams.kt deleted file mode 100644 index 0d67973..0000000 --- a/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionObserveParams.kt +++ /dev/null @@ -1,902 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. - -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 -import com.browserbase.api.core.JsonValue -import com.browserbase.api.core.Params -import com.browserbase.api.core.http.Headers -import com.browserbase.api.core.http.QueryParams -import com.browserbase.api.errors.StagehandInvalidDataException -import com.fasterxml.jackson.annotation.JsonAnyGetter -import com.fasterxml.jackson.annotation.JsonAnySetter -import com.fasterxml.jackson.annotation.JsonCreator -import com.fasterxml.jackson.annotation.JsonProperty -import java.util.Collections -import java.util.Objects -import java.util.Optional -import kotlin.jvm.optionals.getOrNull - -/** - * Returns a list of candidate actions that can be performed on the page, optionally filtered by - * natural language instruction. - */ -class SessionObserveParams -private constructor( - private val sessionId: String?, - private val xStreamResponse: XStreamResponse?, - private val body: Body, - private val additionalHeaders: Headers, - private val additionalQueryParams: QueryParams, -) : Params { - - fun sessionId(): Optional = Optional.ofNullable(sessionId) - - fun xStreamResponse(): Optional = Optional.ofNullable(xStreamResponse) - - /** - * Frame ID to observe - * - * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if the - * server responded with an unexpected value). - */ - fun frameId(): Optional = body.frameId() - - /** - * Natural language instruction to filter actions - * - * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if the - * server responded with an unexpected value). - */ - fun instruction(): Optional = body.instruction() - - /** - * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if the - * server responded with an unexpected value). - */ - fun options(): Optional = body.options() - - /** - * Returns the raw JSON value of [frameId]. - * - * Unlike [frameId], this method doesn't throw if the JSON field has an unexpected type. - */ - fun _frameId(): JsonField = body._frameId() - - /** - * Returns the raw JSON value of [instruction]. - * - * Unlike [instruction], this method doesn't throw if the JSON field has an unexpected type. - */ - fun _instruction(): JsonField = body._instruction() - - /** - * Returns the raw JSON value of [options]. - * - * Unlike [options], this method doesn't throw if the JSON field has an unexpected type. - */ - fun _options(): JsonField = body._options() - - fun _additionalBodyProperties(): Map = body._additionalProperties() - - /** Additional headers to send with the request. */ - fun _additionalHeaders(): Headers = additionalHeaders - - /** Additional query param to send with the request. */ - fun _additionalQueryParams(): QueryParams = additionalQueryParams - - fun toBuilder() = Builder().from(this) - - companion object { - - @JvmStatic fun none(): SessionObserveParams = builder().build() - - /** Returns a mutable builder for constructing an instance of [SessionObserveParams]. */ - @JvmStatic fun builder() = Builder() - } - - /** A builder for [SessionObserveParams]. */ - class Builder internal constructor() { - - private var sessionId: String? = null - private var xStreamResponse: XStreamResponse? = null - private var body: Body.Builder = Body.builder() - private var additionalHeaders: Headers.Builder = Headers.builder() - private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() - - @JvmSynthetic - internal fun from(sessionObserveParams: SessionObserveParams) = apply { - sessionId = sessionObserveParams.sessionId - xStreamResponse = sessionObserveParams.xStreamResponse - body = sessionObserveParams.body.toBuilder() - additionalHeaders = sessionObserveParams.additionalHeaders.toBuilder() - additionalQueryParams = sessionObserveParams.additionalQueryParams.toBuilder() - } - - fun sessionId(sessionId: String?) = apply { this.sessionId = sessionId } - - /** Alias for calling [Builder.sessionId] with `sessionId.orElse(null)`. */ - fun sessionId(sessionId: Optional) = sessionId(sessionId.getOrNull()) - - fun xStreamResponse(xStreamResponse: XStreamResponse?) = apply { - this.xStreamResponse = xStreamResponse - } - - /** Alias for calling [Builder.xStreamResponse] with `xStreamResponse.orElse(null)`. */ - fun xStreamResponse(xStreamResponse: Optional) = - xStreamResponse(xStreamResponse.getOrNull()) - - /** - * Sets the entire request body. - * - * This is generally only useful if you are already constructing the body separately. - * Otherwise, it's more convenient to use the top-level setters instead: - * - [frameId] - * - [instruction] - * - [options] - */ - fun body(body: Body) = apply { this.body = body.toBuilder() } - - /** Frame ID to observe */ - fun frameId(frameId: String) = apply { body.frameId(frameId) } - - /** - * Sets [Builder.frameId] to an arbitrary JSON value. - * - * You should usually call [Builder.frameId] with a well-typed [String] value instead. This - * method is primarily for setting the field to an undocumented or not yet supported value. - */ - fun frameId(frameId: JsonField) = apply { body.frameId(frameId) } - - /** Natural language instruction to filter actions */ - fun instruction(instruction: String) = apply { body.instruction(instruction) } - - /** - * Sets [Builder.instruction] to an arbitrary JSON value. - * - * You should usually call [Builder.instruction] with a well-typed [String] value instead. - * This method is primarily for setting the field to an undocumented or not yet supported - * value. - */ - fun instruction(instruction: JsonField) = apply { body.instruction(instruction) } - - fun options(options: Options) = apply { body.options(options) } - - /** - * Sets [Builder.options] to an arbitrary JSON value. - * - * You should usually call [Builder.options] with a well-typed [Options] value instead. This - * method is primarily for setting the field to an undocumented or not yet supported value. - */ - fun options(options: JsonField) = apply { body.options(options) } - - fun additionalBodyProperties(additionalBodyProperties: Map) = apply { - body.additionalProperties(additionalBodyProperties) - } - - fun putAdditionalBodyProperty(key: String, value: JsonValue) = apply { - body.putAdditionalProperty(key, value) - } - - fun putAllAdditionalBodyProperties(additionalBodyProperties: Map) = - apply { - body.putAllAdditionalProperties(additionalBodyProperties) - } - - fun removeAdditionalBodyProperty(key: String) = apply { body.removeAdditionalProperty(key) } - - fun removeAllAdditionalBodyProperties(keys: Set) = apply { - body.removeAllAdditionalProperties(keys) - } - - fun additionalHeaders(additionalHeaders: Headers) = apply { - this.additionalHeaders.clear() - putAllAdditionalHeaders(additionalHeaders) - } - - fun additionalHeaders(additionalHeaders: Map>) = apply { - this.additionalHeaders.clear() - putAllAdditionalHeaders(additionalHeaders) - } - - fun putAdditionalHeader(name: String, value: String) = apply { - additionalHeaders.put(name, value) - } - - fun putAdditionalHeaders(name: String, values: Iterable) = apply { - additionalHeaders.put(name, values) - } - - fun putAllAdditionalHeaders(additionalHeaders: Headers) = apply { - this.additionalHeaders.putAll(additionalHeaders) - } - - fun putAllAdditionalHeaders(additionalHeaders: Map>) = apply { - this.additionalHeaders.putAll(additionalHeaders) - } - - fun replaceAdditionalHeaders(name: String, value: String) = apply { - additionalHeaders.replace(name, value) - } - - fun replaceAdditionalHeaders(name: String, values: Iterable) = apply { - additionalHeaders.replace(name, values) - } - - fun replaceAllAdditionalHeaders(additionalHeaders: Headers) = apply { - this.additionalHeaders.replaceAll(additionalHeaders) - } - - fun replaceAllAdditionalHeaders(additionalHeaders: Map>) = apply { - this.additionalHeaders.replaceAll(additionalHeaders) - } - - fun removeAdditionalHeaders(name: String) = apply { additionalHeaders.remove(name) } - - fun removeAllAdditionalHeaders(names: Set) = apply { - additionalHeaders.removeAll(names) - } - - fun additionalQueryParams(additionalQueryParams: QueryParams) = apply { - this.additionalQueryParams.clear() - putAllAdditionalQueryParams(additionalQueryParams) - } - - fun additionalQueryParams(additionalQueryParams: Map>) = apply { - this.additionalQueryParams.clear() - putAllAdditionalQueryParams(additionalQueryParams) - } - - fun putAdditionalQueryParam(key: String, value: String) = apply { - additionalQueryParams.put(key, value) - } - - fun putAdditionalQueryParams(key: String, values: Iterable) = apply { - additionalQueryParams.put(key, values) - } - - fun putAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { - this.additionalQueryParams.putAll(additionalQueryParams) - } - - fun putAllAdditionalQueryParams(additionalQueryParams: Map>) = - apply { - this.additionalQueryParams.putAll(additionalQueryParams) - } - - fun replaceAdditionalQueryParams(key: String, value: String) = apply { - additionalQueryParams.replace(key, value) - } - - fun replaceAdditionalQueryParams(key: String, values: Iterable) = apply { - additionalQueryParams.replace(key, values) - } - - fun replaceAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { - this.additionalQueryParams.replaceAll(additionalQueryParams) - } - - fun replaceAllAdditionalQueryParams(additionalQueryParams: Map>) = - apply { - this.additionalQueryParams.replaceAll(additionalQueryParams) - } - - fun removeAdditionalQueryParams(key: String) = apply { additionalQueryParams.remove(key) } - - fun removeAllAdditionalQueryParams(keys: Set) = apply { - additionalQueryParams.removeAll(keys) - } - - /** - * Returns an immutable instance of [SessionObserveParams]. - * - * Further updates to this [Builder] will not mutate the returned instance. - */ - fun build(): SessionObserveParams = - SessionObserveParams( - sessionId, - xStreamResponse, - body.build(), - additionalHeaders.build(), - additionalQueryParams.build(), - ) - } - - fun _body(): Body = body - - fun _pathParam(index: Int): String = - when (index) { - 0 -> sessionId ?: "" - else -> "" - } - - override fun _headers(): Headers = - Headers.builder() - .apply { - xStreamResponse?.let { put("x-stream-response", it.toString()) } - putAll(additionalHeaders) - } - .build() - - override fun _queryParams(): QueryParams = additionalQueryParams - - class Body - @JsonCreator(mode = JsonCreator.Mode.DISABLED) - private constructor( - private val frameId: JsonField, - private val instruction: JsonField, - private val options: JsonField, - private val additionalProperties: MutableMap, - ) { - - @JsonCreator - private constructor( - @JsonProperty("frameId") @ExcludeMissing frameId: JsonField = JsonMissing.of(), - @JsonProperty("instruction") - @ExcludeMissing - instruction: JsonField = JsonMissing.of(), - @JsonProperty("options") @ExcludeMissing options: JsonField = JsonMissing.of(), - ) : this(frameId, instruction, options, mutableMapOf()) - - /** - * Frame ID to observe - * - * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if - * the server responded with an unexpected value). - */ - fun frameId(): Optional = frameId.getOptional("frameId") - - /** - * Natural language instruction to filter actions - * - * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if - * the server responded with an unexpected value). - */ - fun instruction(): Optional = instruction.getOptional("instruction") - - /** - * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if - * the server responded with an unexpected value). - */ - fun options(): Optional = options.getOptional("options") - - /** - * Returns the raw JSON value of [frameId]. - * - * Unlike [frameId], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("frameId") @ExcludeMissing fun _frameId(): JsonField = frameId - - /** - * Returns the raw JSON value of [instruction]. - * - * Unlike [instruction], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("instruction") - @ExcludeMissing - fun _instruction(): JsonField = instruction - - /** - * Returns the raw JSON value of [options]. - * - * Unlike [options], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("options") @ExcludeMissing fun _options(): JsonField = options - - @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 [Body]. */ - @JvmStatic fun builder() = Builder() - } - - /** A builder for [Body]. */ - class Builder internal constructor() { - - private var frameId: JsonField = JsonMissing.of() - private var instruction: JsonField = JsonMissing.of() - private var options: JsonField = JsonMissing.of() - private var additionalProperties: MutableMap = mutableMapOf() - - @JvmSynthetic - internal fun from(body: Body) = apply { - frameId = body.frameId - instruction = body.instruction - options = body.options - additionalProperties = body.additionalProperties.toMutableMap() - } - - /** Frame ID to observe */ - fun frameId(frameId: String) = frameId(JsonField.of(frameId)) - - /** - * Sets [Builder.frameId] to an arbitrary JSON value. - * - * You should usually call [Builder.frameId] with a well-typed [String] value instead. - * This method is primarily for setting the field to an undocumented or not yet - * supported value. - */ - fun frameId(frameId: JsonField) = apply { this.frameId = frameId } - - /** Natural language instruction to filter actions */ - fun instruction(instruction: String) = instruction(JsonField.of(instruction)) - - /** - * Sets [Builder.instruction] to an arbitrary JSON value. - * - * You should usually call [Builder.instruction] with a well-typed [String] value - * instead. This method is primarily for setting the field to an undocumented or not yet - * supported value. - */ - fun instruction(instruction: JsonField) = apply { - this.instruction = instruction - } - - fun options(options: Options) = options(JsonField.of(options)) - - /** - * Sets [Builder.options] to an arbitrary JSON value. - * - * You should usually call [Builder.options] with a well-typed [Options] value instead. - * This method is primarily for setting the field to an undocumented or not yet - * supported value. - */ - fun options(options: JsonField) = apply { this.options = options } - - 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 [Body]. - * - * Further updates to this [Builder] will not mutate the returned instance. - */ - fun build(): Body = - Body(frameId, instruction, options, additionalProperties.toMutableMap()) - } - - private var validated: Boolean = false - - fun validate(): Body = apply { - if (validated) { - return@apply - } - - frameId() - instruction() - options().ifPresent { it.validate() } - 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. - */ - @JvmSynthetic - internal fun validity(): Int = - (if (frameId.asKnown().isPresent) 1 else 0) + - (if (instruction.asKnown().isPresent) 1 else 0) + - (options.asKnown().getOrNull()?.validity() ?: 0) - - override fun equals(other: Any?): Boolean { - if (this === other) { - return true - } - - return other is Body && - frameId == other.frameId && - instruction == other.instruction && - options == other.options && - additionalProperties == other.additionalProperties - } - - private val hashCode: Int by lazy { - Objects.hash(frameId, instruction, options, additionalProperties) - } - - override fun hashCode(): Int = hashCode - - override fun toString() = - "Body{frameId=$frameId, instruction=$instruction, options=$options, additionalProperties=$additionalProperties}" - } - - class Options - @JsonCreator(mode = JsonCreator.Mode.DISABLED) - private constructor( - private val model: JsonField, - private val selector: JsonField, - private val timeout: JsonField, - private val additionalProperties: MutableMap, - ) { - - @JsonCreator - private constructor( - @JsonProperty("model") @ExcludeMissing model: JsonField = JsonMissing.of(), - @JsonProperty("selector") - @ExcludeMissing - selector: JsonField = JsonMissing.of(), - @JsonProperty("timeout") @ExcludeMissing timeout: JsonField = JsonMissing.of(), - ) : this(model, selector, timeout, mutableMapOf()) - - /** - * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if - * the server responded with an unexpected value). - */ - fun model(): Optional = model.getOptional("model") - - /** - * Observe only elements matching this selector - * - * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if - * the server responded with an unexpected value). - */ - fun selector(): Optional = selector.getOptional("selector") - - /** - * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if - * the server responded with an unexpected value). - */ - fun timeout(): Optional = timeout.getOptional("timeout") - - /** - * Returns the raw JSON value of [model]. - * - * Unlike [model], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("model") @ExcludeMissing fun _model(): JsonField = model - - /** - * 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 [timeout]. - * - * Unlike [timeout], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("timeout") @ExcludeMissing fun _timeout(): JsonField = timeout - - @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 [Options]. */ - @JvmStatic fun builder() = Builder() - } - - /** A builder for [Options]. */ - class Builder internal constructor() { - - private var model: JsonField = JsonMissing.of() - private var selector: JsonField = JsonMissing.of() - private var timeout: JsonField = JsonMissing.of() - private var additionalProperties: MutableMap = mutableMapOf() - - @JvmSynthetic - internal fun from(options: Options) = apply { - model = options.model - selector = options.selector - timeout = options.timeout - additionalProperties = options.additionalProperties.toMutableMap() - } - - fun model(model: ModelConfig) = model(JsonField.of(model)) - - /** - * Sets [Builder.model] to an arbitrary JSON value. - * - * You should usually call [Builder.model] with a well-typed [ModelConfig] value - * instead. This method is primarily for setting the field to an undocumented or not yet - * supported value. - */ - fun model(model: JsonField) = apply { this.model = model } - - /** Observe only elements matching this selector */ - 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 } - - fun timeout(timeout: Long) = timeout(JsonField.of(timeout)) - - /** - * Sets [Builder.timeout] to an arbitrary JSON value. - * - * You should usually call [Builder.timeout] with a well-typed [Long] value instead. - * This method is primarily for setting the field to an undocumented or not yet - * supported value. - */ - fun timeout(timeout: JsonField) = apply { this.timeout = timeout } - - 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 [Options]. - * - * Further updates to this [Builder] will not mutate the returned instance. - */ - fun build(): Options = - Options(model, selector, timeout, additionalProperties.toMutableMap()) - } - - private var validated: Boolean = false - - fun validate(): Options = apply { - if (validated) { - return@apply - } - - model().ifPresent { it.validate() } - selector() - timeout() - 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. - */ - @JvmSynthetic - internal fun validity(): Int = - (model.asKnown().getOrNull()?.validity() ?: 0) + - (if (selector.asKnown().isPresent) 1 else 0) + - (if (timeout.asKnown().isPresent) 1 else 0) - - override fun equals(other: Any?): Boolean { - if (this === other) { - return true - } - - return other is Options && - model == other.model && - selector == other.selector && - timeout == other.timeout && - additionalProperties == other.additionalProperties - } - - private val hashCode: Int by lazy { - Objects.hash(model, selector, timeout, additionalProperties) - } - - override fun hashCode(): Int = hashCode - - override fun toString() = - "Options{model=$model, selector=$selector, timeout=$timeout, additionalProperties=$additionalProperties}" - } - - class XStreamResponse @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 { - - @JvmField val TRUE = of("true") - - @JvmField val FALSE = of("false") - - @JvmStatic fun of(value: String) = XStreamResponse(JsonField.of(value)) - } - - /** An enum containing [XStreamResponse]'s known values. */ - enum class Known { - TRUE, - FALSE, - } - - /** - * An enum containing [XStreamResponse]'s known values, as well as an [_UNKNOWN] member. - * - * An instance of [XStreamResponse] 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, - FALSE, - /** - * An enum member indicating that [XStreamResponse] 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 - FALSE -> Value.FALSE - 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 - FALSE -> Known.FALSE - else -> throw StagehandInvalidDataException("Unknown XStreamResponse: $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().orElseThrow { - StagehandInvalidDataException("Value is not a String") - } - - private var validated: Boolean = false - - fun validate(): XStreamResponse = 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. - */ - @JvmSynthetic 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 XStreamResponse && 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 SessionObserveParams && - sessionId == other.sessionId && - xStreamResponse == other.xStreamResponse && - body == other.body && - additionalHeaders == other.additionalHeaders && - additionalQueryParams == other.additionalQueryParams - } - - override fun hashCode(): Int = - Objects.hash(sessionId, xStreamResponse, body, additionalHeaders, additionalQueryParams) - - override fun toString() = - "SessionObserveParams{sessionId=$sessionId, xStreamResponse=$xStreamResponse, body=$body, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" -} diff --git a/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionStartParams.kt b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionStartParams.kt index cda3e99..e0c55aa 100644 --- a/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionStartParams.kt +++ b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionStartParams.kt @@ -2,143 +2,39 @@ package com.browserbase.api.models.sessions -import com.browserbase.api.core.ExcludeMissing -import com.browserbase.api.core.JsonField import com.browserbase.api.core.JsonMissing import com.browserbase.api.core.JsonValue import com.browserbase.api.core.Params -import com.browserbase.api.core.checkRequired import com.browserbase.api.core.http.Headers import com.browserbase.api.core.http.QueryParams -import com.browserbase.api.errors.StagehandInvalidDataException -import com.fasterxml.jackson.annotation.JsonAnyGetter -import com.fasterxml.jackson.annotation.JsonAnySetter -import com.fasterxml.jackson.annotation.JsonCreator -import com.fasterxml.jackson.annotation.JsonProperty -import java.util.Collections import java.util.Objects import java.util.Optional +import kotlin.jvm.optionals.getOrNull /** - * Initializes a new Stagehand session with a browser instance. Returns a session ID that must be - * used for all subsequent requests. + * Creates a new browser session with the specified configuration. Returns a session ID used for all + * subsequent operations. */ class SessionStartParams private constructor( - private val body: Body, + private val xLanguage: JsonValue?, + private val xSdkVersion: JsonValue?, + private val xSentAt: JsonValue?, + private val xStreamResponse: JsonValue?, + private val body: JsonValue, private val additionalHeaders: Headers, private val additionalQueryParams: QueryParams, ) : Params { - /** - * API key for Browserbase Cloud - * - * @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 browserbaseApiKey(): String = body.browserbaseApiKey() - - /** - * Project ID for Browserbase - * - * @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 browserbaseProjectId(): String = body.browserbaseProjectId() - - /** - * Timeout in ms to wait for DOM to settle - * - * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if the - * server responded with an unexpected value). - */ - fun domSettleTimeout(): Optional = body.domSettleTimeout() - - /** - * AI model to use for actions (must be prefixed with provider/) - * - * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if the - * server responded with an unexpected value). - */ - fun model(): Optional = body.model() - - /** - * Enable self-healing for failed actions - * - * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if the - * server responded with an unexpected value). - */ - fun selfHeal(): Optional = body.selfHeal() - - /** - * Custom system prompt for AI actions - * - * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if the - * server responded with an unexpected value). - */ - fun systemPrompt(): Optional = body.systemPrompt() - - /** - * Logging verbosity level - * - * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if the - * server responded with an unexpected value). - */ - fun verbose(): Optional = body.verbose() - - /** - * Returns the raw JSON value of [browserbaseApiKey]. - * - * Unlike [browserbaseApiKey], this method doesn't throw if the JSON field has an unexpected - * type. - */ - fun _browserbaseApiKey(): JsonField = body._browserbaseApiKey() - - /** - * Returns the raw JSON value of [browserbaseProjectId]. - * - * Unlike [browserbaseProjectId], this method doesn't throw if the JSON field has an unexpected - * type. - */ - fun _browserbaseProjectId(): JsonField = body._browserbaseProjectId() - - /** - * Returns the raw JSON value of [domSettleTimeout]. - * - * Unlike [domSettleTimeout], this method doesn't throw if the JSON field has an unexpected - * type. - */ - fun _domSettleTimeout(): JsonField = body._domSettleTimeout() - - /** - * Returns the raw JSON value of [model]. - * - * Unlike [model], this method doesn't throw if the JSON field has an unexpected type. - */ - fun _model(): JsonField = body._model() - - /** - * Returns the raw JSON value of [selfHeal]. - * - * Unlike [selfHeal], this method doesn't throw if the JSON field has an unexpected type. - */ - fun _selfHeal(): JsonField = body._selfHeal() - - /** - * Returns the raw JSON value of [systemPrompt]. - * - * Unlike [systemPrompt], this method doesn't throw if the JSON field has an unexpected type. - */ - fun _systemPrompt(): JsonField = body._systemPrompt() - - /** - * Returns the raw JSON value of [verbose]. - * - * Unlike [verbose], this method doesn't throw if the JSON field has an unexpected type. - */ - fun _verbose(): JsonField = body._verbose() - - fun _additionalBodyProperties(): Map = body._additionalProperties() + fun xLanguage(): Optional = Optional.ofNullable(xLanguage) + + fun xSdkVersion(): Optional = Optional.ofNullable(xSdkVersion) + + fun xSentAt(): Optional = Optional.ofNullable(xSentAt) + + fun xStreamResponse(): Optional = Optional.ofNullable(xStreamResponse) + + fun body(): JsonValue = body /** Additional headers to send with the request. */ fun _additionalHeaders(): Headers = additionalHeaders @@ -150,160 +46,58 @@ private constructor( companion object { - /** - * Returns a mutable builder for constructing an instance of [SessionStartParams]. - * - * The following fields are required: - * ```java - * .browserbaseApiKey() - * .browserbaseProjectId() - * ``` - */ + @JvmStatic fun none(): SessionStartParams = builder().build() + + /** Returns a mutable builder for constructing an instance of [SessionStartParams]. */ @JvmStatic fun builder() = Builder() } /** A builder for [SessionStartParams]. */ class Builder internal constructor() { - private var body: Body.Builder = Body.builder() + private var xLanguage: JsonValue? = null + private var xSdkVersion: JsonValue? = null + private var xSentAt: JsonValue? = null + private var xStreamResponse: JsonValue? = null + private var body: JsonValue = JsonMissing.of() private var additionalHeaders: Headers.Builder = Headers.builder() private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() @JvmSynthetic internal fun from(sessionStartParams: SessionStartParams) = apply { - body = sessionStartParams.body.toBuilder() + xLanguage = sessionStartParams.xLanguage + xSdkVersion = sessionStartParams.xSdkVersion + xSentAt = sessionStartParams.xSentAt + xStreamResponse = sessionStartParams.xStreamResponse + body = sessionStartParams.body additionalHeaders = sessionStartParams.additionalHeaders.toBuilder() additionalQueryParams = sessionStartParams.additionalQueryParams.toBuilder() } - /** - * Sets the entire request body. - * - * This is generally only useful if you are already constructing the body separately. - * Otherwise, it's more convenient to use the top-level setters instead: - * - [browserbaseApiKey] - * - [browserbaseProjectId] - * - [domSettleTimeout] - * - [model] - * - [selfHeal] - * - etc. - */ - fun body(body: Body) = apply { this.body = body.toBuilder() } + fun xLanguage(xLanguage: JsonValue?) = apply { this.xLanguage = xLanguage } - /** API key for Browserbase Cloud */ - fun browserbaseApiKey(browserbaseApiKey: String) = apply { - body.browserbaseApiKey(browserbaseApiKey) - } + /** Alias for calling [Builder.xLanguage] with `xLanguage.orElse(null)`. */ + fun xLanguage(xLanguage: Optional) = xLanguage(xLanguage.getOrNull()) - /** - * Sets [Builder.browserbaseApiKey] to an arbitrary JSON value. - * - * You should usually call [Builder.browserbaseApiKey] with a well-typed [String] value - * instead. This method is primarily for setting the field to an undocumented or not yet - * supported value. - */ - fun browserbaseApiKey(browserbaseApiKey: JsonField) = apply { - body.browserbaseApiKey(browserbaseApiKey) - } + fun xSdkVersion(xSdkVersion: JsonValue?) = apply { this.xSdkVersion = xSdkVersion } - /** Project ID for Browserbase */ - fun browserbaseProjectId(browserbaseProjectId: String) = apply { - body.browserbaseProjectId(browserbaseProjectId) - } + /** Alias for calling [Builder.xSdkVersion] with `xSdkVersion.orElse(null)`. */ + fun xSdkVersion(xSdkVersion: Optional) = xSdkVersion(xSdkVersion.getOrNull()) - /** - * Sets [Builder.browserbaseProjectId] to an arbitrary JSON value. - * - * You should usually call [Builder.browserbaseProjectId] with a well-typed [String] value - * instead. This method is primarily for setting the field to an undocumented or not yet - * supported value. - */ - fun browserbaseProjectId(browserbaseProjectId: JsonField) = apply { - body.browserbaseProjectId(browserbaseProjectId) - } + fun xSentAt(xSentAt: JsonValue?) = apply { this.xSentAt = xSentAt } - /** Timeout in ms to wait for DOM to settle */ - fun domSettleTimeout(domSettleTimeout: Long) = apply { - body.domSettleTimeout(domSettleTimeout) - } + /** Alias for calling [Builder.xSentAt] with `xSentAt.orElse(null)`. */ + fun xSentAt(xSentAt: Optional) = xSentAt(xSentAt.getOrNull()) - /** - * Sets [Builder.domSettleTimeout] to an arbitrary JSON value. - * - * You should usually call [Builder.domSettleTimeout] with a well-typed [Long] value - * instead. This method is primarily for setting the field to an undocumented or not yet - * supported value. - */ - fun domSettleTimeout(domSettleTimeout: JsonField) = apply { - body.domSettleTimeout(domSettleTimeout) + fun xStreamResponse(xStreamResponse: JsonValue?) = apply { + this.xStreamResponse = xStreamResponse } - /** AI model to use for actions (must be prefixed with provider/) */ - fun model(model: String) = apply { body.model(model) } - - /** - * Sets [Builder.model] to an arbitrary JSON value. - * - * You should usually call [Builder.model] with a well-typed [String] value instead. This - * method is primarily for setting the field to an undocumented or not yet supported value. - */ - fun model(model: JsonField) = apply { body.model(model) } - - /** Enable self-healing for failed actions */ - fun selfHeal(selfHeal: Boolean) = apply { body.selfHeal(selfHeal) } - - /** - * Sets [Builder.selfHeal] to an arbitrary JSON value. - * - * You should usually call [Builder.selfHeal] with a well-typed [Boolean] value instead. - * This method is primarily for setting the field to an undocumented or not yet supported - * value. - */ - fun selfHeal(selfHeal: JsonField) = apply { body.selfHeal(selfHeal) } - - /** Custom system prompt for AI actions */ - fun systemPrompt(systemPrompt: String) = apply { body.systemPrompt(systemPrompt) } - - /** - * Sets [Builder.systemPrompt] to an arbitrary JSON value. - * - * You should usually call [Builder.systemPrompt] with a well-typed [String] value instead. - * This method is primarily for setting the field to an undocumented or not yet supported - * value. - */ - fun systemPrompt(systemPrompt: JsonField) = apply { - body.systemPrompt(systemPrompt) - } + /** Alias for calling [Builder.xStreamResponse] with `xStreamResponse.orElse(null)`. */ + fun xStreamResponse(xStreamResponse: Optional) = + xStreamResponse(xStreamResponse.getOrNull()) - /** Logging verbosity level */ - fun verbose(verbose: Long) = apply { body.verbose(verbose) } - - /** - * Sets [Builder.verbose] to an arbitrary JSON value. - * - * You should usually call [Builder.verbose] with a well-typed [Long] value instead. This - * method is primarily for setting the field to an undocumented or not yet supported value. - */ - fun verbose(verbose: JsonField) = apply { body.verbose(verbose) } - - fun additionalBodyProperties(additionalBodyProperties: Map) = apply { - body.additionalProperties(additionalBodyProperties) - } - - fun putAdditionalBodyProperty(key: String, value: JsonValue) = apply { - body.putAdditionalProperty(key, value) - } - - fun putAllAdditionalBodyProperties(additionalBodyProperties: Map) = - apply { - body.putAllAdditionalProperties(additionalBodyProperties) - } - - fun removeAdditionalBodyProperty(key: String) = apply { body.removeAdditionalProperty(key) } - - fun removeAllAdditionalBodyProperties(keys: Set) = apply { - body.removeAllAdditionalProperties(keys) - } + fun body(body: JsonValue) = apply { this.body = body } fun additionalHeaders(additionalHeaders: Headers) = apply { this.additionalHeaders.clear() @@ -407,469 +201,51 @@ private constructor( * Returns an immutable instance of [SessionStartParams]. * * Further updates to this [Builder] will not mutate the returned instance. - * - * The following fields are required: - * ```java - * .browserbaseApiKey() - * .browserbaseProjectId() - * ``` - * - * @throws IllegalStateException if any required field is unset. */ fun build(): SessionStartParams = SessionStartParams( - body.build(), + xLanguage, + xSdkVersion, + xSentAt, + xStreamResponse, + body, additionalHeaders.build(), additionalQueryParams.build(), ) } - fun _body(): Body = body + fun _body(): JsonValue = body - override fun _headers(): Headers = additionalHeaders + override fun _headers(): Headers = Headers.builder().apply { putAll(additionalHeaders) }.build() override fun _queryParams(): QueryParams = additionalQueryParams - class Body - @JsonCreator(mode = JsonCreator.Mode.DISABLED) - private constructor( - private val browserbaseApiKey: JsonField, - private val browserbaseProjectId: JsonField, - private val domSettleTimeout: JsonField, - private val model: JsonField, - private val selfHeal: JsonField, - private val systemPrompt: JsonField, - private val verbose: JsonField, - private val additionalProperties: MutableMap, - ) { - - @JsonCreator - private constructor( - @JsonProperty("BROWSERBASE_API_KEY") - @ExcludeMissing - browserbaseApiKey: JsonField = JsonMissing.of(), - @JsonProperty("BROWSERBASE_PROJECT_ID") - @ExcludeMissing - browserbaseProjectId: JsonField = JsonMissing.of(), - @JsonProperty("domSettleTimeout") - @ExcludeMissing - domSettleTimeout: JsonField = JsonMissing.of(), - @JsonProperty("model") @ExcludeMissing model: JsonField = JsonMissing.of(), - @JsonProperty("selfHeal") - @ExcludeMissing - selfHeal: JsonField = JsonMissing.of(), - @JsonProperty("systemPrompt") - @ExcludeMissing - systemPrompt: JsonField = JsonMissing.of(), - @JsonProperty("verbose") @ExcludeMissing verbose: JsonField = JsonMissing.of(), - ) : this( - browserbaseApiKey, - browserbaseProjectId, - domSettleTimeout, - model, - selfHeal, - systemPrompt, - verbose, - mutableMapOf(), - ) - - /** - * API key for Browserbase Cloud - * - * @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 browserbaseApiKey(): String = browserbaseApiKey.getRequired("BROWSERBASE_API_KEY") - - /** - * Project ID for Browserbase - * - * @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 browserbaseProjectId(): String = - browserbaseProjectId.getRequired("BROWSERBASE_PROJECT_ID") - - /** - * Timeout in ms to wait for DOM to settle - * - * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if - * the server responded with an unexpected value). - */ - fun domSettleTimeout(): Optional = domSettleTimeout.getOptional("domSettleTimeout") - - /** - * AI model to use for actions (must be prefixed with provider/) - * - * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if - * the server responded with an unexpected value). - */ - fun model(): Optional = model.getOptional("model") - - /** - * Enable self-healing for failed actions - * - * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if - * the server responded with an unexpected value). - */ - fun selfHeal(): Optional = selfHeal.getOptional("selfHeal") - - /** - * Custom system prompt for AI actions - * - * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if - * the server responded with an unexpected value). - */ - fun systemPrompt(): Optional = systemPrompt.getOptional("systemPrompt") - - /** - * Logging verbosity level - * - * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if - * the server responded with an unexpected value). - */ - fun verbose(): Optional = verbose.getOptional("verbose") - - /** - * Returns the raw JSON value of [browserbaseApiKey]. - * - * Unlike [browserbaseApiKey], this method doesn't throw if the JSON field has an unexpected - * type. - */ - @JsonProperty("BROWSERBASE_API_KEY") - @ExcludeMissing - fun _browserbaseApiKey(): JsonField = browserbaseApiKey - - /** - * Returns the raw JSON value of [browserbaseProjectId]. - * - * Unlike [browserbaseProjectId], this method doesn't throw if the JSON field has an - * unexpected type. - */ - @JsonProperty("BROWSERBASE_PROJECT_ID") - @ExcludeMissing - fun _browserbaseProjectId(): JsonField = browserbaseProjectId - - /** - * Returns the raw JSON value of [domSettleTimeout]. - * - * Unlike [domSettleTimeout], this method doesn't throw if the JSON field has an unexpected - * type. - */ - @JsonProperty("domSettleTimeout") - @ExcludeMissing - fun _domSettleTimeout(): JsonField = domSettleTimeout - - /** - * Returns the raw JSON value of [model]. - * - * Unlike [model], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("model") @ExcludeMissing fun _model(): JsonField = model - - /** - * Returns the raw JSON value of [selfHeal]. - * - * Unlike [selfHeal], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("selfHeal") @ExcludeMissing fun _selfHeal(): JsonField = selfHeal - - /** - * Returns the raw JSON value of [systemPrompt]. - * - * Unlike [systemPrompt], this method doesn't throw if the JSON field has an unexpected - * type. - */ - @JsonProperty("systemPrompt") - @ExcludeMissing - fun _systemPrompt(): JsonField = systemPrompt - - /** - * Returns the raw JSON value of [verbose]. - * - * Unlike [verbose], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("verbose") @ExcludeMissing fun _verbose(): JsonField = verbose - - @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 [Body]. - * - * The following fields are required: - * ```java - * .browserbaseApiKey() - * .browserbaseProjectId() - * ``` - */ - @JvmStatic fun builder() = Builder() - } - - /** A builder for [Body]. */ - class Builder internal constructor() { - - private var browserbaseApiKey: JsonField? = null - private var browserbaseProjectId: JsonField? = null - private var domSettleTimeout: JsonField = JsonMissing.of() - private var model: JsonField = JsonMissing.of() - private var selfHeal: JsonField = JsonMissing.of() - private var systemPrompt: JsonField = JsonMissing.of() - private var verbose: JsonField = JsonMissing.of() - private var additionalProperties: MutableMap = mutableMapOf() - - @JvmSynthetic - internal fun from(body: Body) = apply { - browserbaseApiKey = body.browserbaseApiKey - browserbaseProjectId = body.browserbaseProjectId - domSettleTimeout = body.domSettleTimeout - model = body.model - selfHeal = body.selfHeal - systemPrompt = body.systemPrompt - verbose = body.verbose - additionalProperties = body.additionalProperties.toMutableMap() - } - - /** API key for Browserbase Cloud */ - fun browserbaseApiKey(browserbaseApiKey: String) = - browserbaseApiKey(JsonField.of(browserbaseApiKey)) - - /** - * Sets [Builder.browserbaseApiKey] to an arbitrary JSON value. - * - * You should usually call [Builder.browserbaseApiKey] with a well-typed [String] value - * instead. This method is primarily for setting the field to an undocumented or not yet - * supported value. - */ - fun browserbaseApiKey(browserbaseApiKey: JsonField) = apply { - this.browserbaseApiKey = browserbaseApiKey - } - - /** Project ID for Browserbase */ - fun browserbaseProjectId(browserbaseProjectId: String) = - browserbaseProjectId(JsonField.of(browserbaseProjectId)) - - /** - * Sets [Builder.browserbaseProjectId] to an arbitrary JSON value. - * - * You should usually call [Builder.browserbaseProjectId] with a well-typed [String] - * value instead. This method is primarily for setting the field to an undocumented or - * not yet supported value. - */ - fun browserbaseProjectId(browserbaseProjectId: JsonField) = apply { - this.browserbaseProjectId = browserbaseProjectId - } - - /** Timeout in ms to wait for DOM to settle */ - fun domSettleTimeout(domSettleTimeout: Long) = - domSettleTimeout(JsonField.of(domSettleTimeout)) - - /** - * Sets [Builder.domSettleTimeout] to an arbitrary JSON value. - * - * You should usually call [Builder.domSettleTimeout] with a well-typed [Long] value - * instead. This method is primarily for setting the field to an undocumented or not yet - * supported value. - */ - fun domSettleTimeout(domSettleTimeout: JsonField) = apply { - this.domSettleTimeout = domSettleTimeout - } - - /** AI model to use for actions (must be prefixed with provider/) */ - fun model(model: String) = model(JsonField.of(model)) - - /** - * Sets [Builder.model] to an arbitrary JSON value. - * - * You should usually call [Builder.model] with a well-typed [String] value instead. - * This method is primarily for setting the field to an undocumented or not yet - * supported value. - */ - fun model(model: JsonField) = apply { this.model = model } - - /** Enable self-healing for failed actions */ - fun selfHeal(selfHeal: Boolean) = selfHeal(JsonField.of(selfHeal)) - - /** - * Sets [Builder.selfHeal] to an arbitrary JSON value. - * - * You should usually call [Builder.selfHeal] with a well-typed [Boolean] value instead. - * This method is primarily for setting the field to an undocumented or not yet - * supported value. - */ - fun selfHeal(selfHeal: JsonField) = apply { this.selfHeal = selfHeal } - - /** Custom system prompt for AI actions */ - fun systemPrompt(systemPrompt: String) = systemPrompt(JsonField.of(systemPrompt)) - - /** - * Sets [Builder.systemPrompt] to an arbitrary JSON value. - * - * You should usually call [Builder.systemPrompt] with a well-typed [String] value - * instead. This method is primarily for setting the field to an undocumented or not yet - * supported value. - */ - fun systemPrompt(systemPrompt: JsonField) = apply { - this.systemPrompt = systemPrompt - } - - /** Logging verbosity level */ - fun verbose(verbose: Long) = verbose(JsonField.of(verbose)) - - /** - * Sets [Builder.verbose] to an arbitrary JSON value. - * - * You should usually call [Builder.verbose] with a well-typed [Long] value instead. - * This method is primarily for setting the field to an undocumented or not yet - * supported value. - */ - fun verbose(verbose: JsonField) = apply { this.verbose = verbose } - - 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 [Body]. - * - * Further updates to this [Builder] will not mutate the returned instance. - * - * The following fields are required: - * ```java - * .browserbaseApiKey() - * .browserbaseProjectId() - * ``` - * - * @throws IllegalStateException if any required field is unset. - */ - fun build(): Body = - Body( - checkRequired("browserbaseApiKey", browserbaseApiKey), - checkRequired("browserbaseProjectId", browserbaseProjectId), - domSettleTimeout, - model, - selfHeal, - systemPrompt, - verbose, - additionalProperties.toMutableMap(), - ) - } - - private var validated: Boolean = false - - fun validate(): Body = apply { - if (validated) { - return@apply - } - - browserbaseApiKey() - browserbaseProjectId() - domSettleTimeout() - model() - selfHeal() - systemPrompt() - verbose() - 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. - */ - @JvmSynthetic - internal fun validity(): Int = - (if (browserbaseApiKey.asKnown().isPresent) 1 else 0) + - (if (browserbaseProjectId.asKnown().isPresent) 1 else 0) + - (if (domSettleTimeout.asKnown().isPresent) 1 else 0) + - (if (model.asKnown().isPresent) 1 else 0) + - (if (selfHeal.asKnown().isPresent) 1 else 0) + - (if (systemPrompt.asKnown().isPresent) 1 else 0) + - (if (verbose.asKnown().isPresent) 1 else 0) - - override fun equals(other: Any?): Boolean { - if (this === other) { - return true - } - - return other is Body && - browserbaseApiKey == other.browserbaseApiKey && - browserbaseProjectId == other.browserbaseProjectId && - domSettleTimeout == other.domSettleTimeout && - model == other.model && - selfHeal == other.selfHeal && - systemPrompt == other.systemPrompt && - verbose == other.verbose && - additionalProperties == other.additionalProperties - } - - private val hashCode: Int by lazy { - Objects.hash( - browserbaseApiKey, - browserbaseProjectId, - domSettleTimeout, - model, - selfHeal, - systemPrompt, - verbose, - additionalProperties, - ) - } - - override fun hashCode(): Int = hashCode - - override fun toString() = - "Body{browserbaseApiKey=$browserbaseApiKey, browserbaseProjectId=$browserbaseProjectId, domSettleTimeout=$domSettleTimeout, model=$model, selfHeal=$selfHeal, systemPrompt=$systemPrompt, verbose=$verbose, additionalProperties=$additionalProperties}" - } - override fun equals(other: Any?): Boolean { if (this === other) { return true } return other is SessionStartParams && + xLanguage == other.xLanguage && + xSdkVersion == other.xSdkVersion && + xSentAt == other.xSentAt && + xStreamResponse == other.xStreamResponse && body == other.body && additionalHeaders == other.additionalHeaders && additionalQueryParams == other.additionalQueryParams } - override fun hashCode(): Int = Objects.hash(body, additionalHeaders, additionalQueryParams) + override fun hashCode(): Int = + Objects.hash( + xLanguage, + xSdkVersion, + xSentAt, + xStreamResponse, + body, + additionalHeaders, + additionalQueryParams, + ) override fun toString() = - "SessionStartParams{body=$body, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" + "SessionStartParams{xLanguage=$xLanguage, xSdkVersion=$xSdkVersion, xSentAt=$xSentAt, xStreamResponse=$xStreamResponse, body=$body, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" } diff --git a/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionStartResponse.kt b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionStartResponse.kt index 2e71372..b63f41e 100644 --- a/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionStartResponse.kt +++ b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionStartResponse.kt @@ -3,61 +3,19 @@ package com.browserbase.api.models.sessions import com.browserbase.api.core.ExcludeMissing -import com.browserbase.api.core.JsonField -import com.browserbase.api.core.JsonMissing import com.browserbase.api.core.JsonValue -import com.browserbase.api.core.checkRequired import com.browserbase.api.errors.StagehandInvalidDataException import com.fasterxml.jackson.annotation.JsonAnyGetter import com.fasterxml.jackson.annotation.JsonAnySetter import com.fasterxml.jackson.annotation.JsonCreator -import com.fasterxml.jackson.annotation.JsonProperty import java.util.Collections import java.util.Objects class SessionStartResponse @JsonCreator(mode = JsonCreator.Mode.DISABLED) -private constructor( - private val available: JsonField, - private val sessionId: JsonField, - private val additionalProperties: MutableMap, -) { - - @JsonCreator - private constructor( - @JsonProperty("available") @ExcludeMissing available: JsonField = JsonMissing.of(), - @JsonProperty("sessionId") @ExcludeMissing sessionId: JsonField = JsonMissing.of(), - ) : this(available, sessionId, mutableMapOf()) +private constructor(private val additionalProperties: MutableMap) { - /** - * Whether the session is ready to use - * - * @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 available(): Boolean = available.getRequired("available") - - /** - * Unique identifier for the session - * - * @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 sessionId(): String = sessionId.getRequired("sessionId") - - /** - * Returns the raw JSON value of [available]. - * - * Unlike [available], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("available") @ExcludeMissing fun _available(): JsonField = available - - /** - * Returns the raw JSON value of [sessionId]. - * - * Unlike [sessionId], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("sessionId") @ExcludeMissing fun _sessionId(): JsonField = sessionId + @JsonCreator private constructor() : this(mutableMapOf()) @JsonAnySetter private fun putAdditionalProperty(key: String, value: JsonValue) { @@ -73,56 +31,20 @@ private constructor( companion object { - /** - * Returns a mutable builder for constructing an instance of [SessionStartResponse]. - * - * The following fields are required: - * ```java - * .available() - * .sessionId() - * ``` - */ + /** Returns a mutable builder for constructing an instance of [SessionStartResponse]. */ @JvmStatic fun builder() = Builder() } /** A builder for [SessionStartResponse]. */ class Builder internal constructor() { - private var available: JsonField? = null - private var sessionId: JsonField? = null private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic internal fun from(sessionStartResponse: SessionStartResponse) = apply { - available = sessionStartResponse.available - sessionId = sessionStartResponse.sessionId additionalProperties = sessionStartResponse.additionalProperties.toMutableMap() } - /** Whether the session is ready to use */ - fun available(available: Boolean) = available(JsonField.of(available)) - - /** - * Sets [Builder.available] to an arbitrary JSON value. - * - * You should usually call [Builder.available] with a well-typed [Boolean] value instead. - * This method is primarily for setting the field to an undocumented or not yet supported - * value. - */ - fun available(available: JsonField) = apply { this.available = available } - - /** Unique identifier for the session */ - fun sessionId(sessionId: String) = sessionId(JsonField.of(sessionId)) - - /** - * Sets [Builder.sessionId] to an arbitrary JSON value. - * - * You should usually call [Builder.sessionId] with a well-typed [String] value instead. - * This method is primarily for setting the field to an undocumented or not yet supported - * value. - */ - fun sessionId(sessionId: JsonField) = apply { this.sessionId = sessionId } - fun additionalProperties(additionalProperties: Map) = apply { this.additionalProperties.clear() putAllAdditionalProperties(additionalProperties) @@ -146,21 +68,9 @@ private constructor( * Returns an immutable instance of [SessionStartResponse]. * * Further updates to this [Builder] will not mutate the returned instance. - * - * The following fields are required: - * ```java - * .available() - * .sessionId() - * ``` - * - * @throws IllegalStateException if any required field is unset. */ fun build(): SessionStartResponse = - SessionStartResponse( - checkRequired("available", available), - checkRequired("sessionId", sessionId), - additionalProperties.toMutableMap(), - ) + SessionStartResponse(additionalProperties.toMutableMap()) } private var validated: Boolean = false @@ -170,8 +80,6 @@ private constructor( return@apply } - available() - sessionId() validated = true } @@ -188,26 +96,19 @@ private constructor( * * Used for best match union deserialization. */ - @JvmSynthetic - internal fun validity(): Int = - (if (available.asKnown().isPresent) 1 else 0) + - (if (sessionId.asKnown().isPresent) 1 else 0) + @JvmSynthetic internal fun validity(): Int = 0 override fun equals(other: Any?): Boolean { if (this === other) { return true } - return other is SessionStartResponse && - available == other.available && - sessionId == other.sessionId && - additionalProperties == other.additionalProperties + return other is SessionStartResponse && additionalProperties == other.additionalProperties } - private val hashCode: Int by lazy { Objects.hash(available, sessionId, additionalProperties) } + private val hashCode: Int by lazy { Objects.hash(additionalProperties) } override fun hashCode(): Int = hashCode - override fun toString() = - "SessionStartResponse{available=$available, sessionId=$sessionId, additionalProperties=$additionalProperties}" + override fun toString() = "SessionStartResponse{additionalProperties=$additionalProperties}" } diff --git a/stagehand-java-core/src/main/kotlin/com/browserbase/api/services/async/SessionServiceAsync.kt b/stagehand-java-core/src/main/kotlin/com/browserbase/api/services/async/SessionServiceAsync.kt index 5c78924..d481fec 100644 --- a/stagehand-java-core/src/main/kotlin/com/browserbase/api/services/async/SessionServiceAsync.kt +++ b/stagehand-java-core/src/main/kotlin/com/browserbase/api/services/async/SessionServiceAsync.kt @@ -5,21 +5,8 @@ package com.browserbase.api.services.async import com.browserbase.api.core.ClientOptions import com.browserbase.api.core.RequestOptions import com.browserbase.api.core.http.HttpResponseFor -import com.browserbase.api.models.sessions.Action -import com.browserbase.api.models.sessions.SessionActParams -import com.browserbase.api.models.sessions.SessionActResponse -import com.browserbase.api.models.sessions.SessionEndParams -import com.browserbase.api.models.sessions.SessionEndResponse -import com.browserbase.api.models.sessions.SessionExecuteAgentParams -import com.browserbase.api.models.sessions.SessionExecuteAgentResponse -import com.browserbase.api.models.sessions.SessionExtractParams -import com.browserbase.api.models.sessions.SessionExtractResponse -import com.browserbase.api.models.sessions.SessionNavigateParams -import com.browserbase.api.models.sessions.SessionNavigateResponse -import com.browserbase.api.models.sessions.SessionObserveParams import com.browserbase.api.models.sessions.SessionStartParams import com.browserbase.api.models.sessions.SessionStartResponse -import java.util.Optional import java.util.concurrent.CompletableFuture import java.util.function.Consumer @@ -38,207 +25,26 @@ interface SessionServiceAsync { fun withOptions(modifier: Consumer): SessionServiceAsync /** - * Performs a browser action based on natural language instruction or a specific action object - * returned by observe(). + * Creates a new browser session with the specified configuration. Returns a session ID used for + * all subsequent operations. */ - fun act(sessionId: String, params: SessionActParams): CompletableFuture = - act(sessionId, params, RequestOptions.none()) - - /** @see act */ - fun act( - sessionId: String, - params: SessionActParams, - requestOptions: RequestOptions = RequestOptions.none(), - ): CompletableFuture = - act(params.toBuilder().sessionId(sessionId).build(), requestOptions) - - /** @see act */ - fun act(params: SessionActParams): CompletableFuture = - act(params, RequestOptions.none()) - - /** @see act */ - fun act( - params: SessionActParams, - requestOptions: RequestOptions = RequestOptions.none(), - ): CompletableFuture - - /** Closes the browser and cleans up all resources associated with the session. */ - fun end(sessionId: String): CompletableFuture = - end(sessionId, SessionEndParams.none()) - - /** @see end */ - fun end( - sessionId: String, - params: SessionEndParams = SessionEndParams.none(), - requestOptions: RequestOptions = RequestOptions.none(), - ): CompletableFuture = - end(params.toBuilder().sessionId(sessionId).build(), requestOptions) - - /** @see end */ - fun end( - sessionId: String, - params: SessionEndParams = SessionEndParams.none(), - ): CompletableFuture = end(sessionId, params, RequestOptions.none()) - - /** @see end */ - fun end( - params: SessionEndParams, - requestOptions: RequestOptions = RequestOptions.none(), - ): CompletableFuture - - /** @see end */ - fun end(params: SessionEndParams): CompletableFuture = - end(params, RequestOptions.none()) - - /** @see end */ - fun end( - sessionId: String, - requestOptions: RequestOptions, - ): CompletableFuture = - end(sessionId, SessionEndParams.none(), requestOptions) - - /** Runs an autonomous agent that can perform multiple actions to complete a complex task. */ - fun executeAgent( - sessionId: String, - params: SessionExecuteAgentParams, - ): CompletableFuture = - executeAgent(sessionId, params, RequestOptions.none()) - - /** @see executeAgent */ - fun executeAgent( - sessionId: String, - params: SessionExecuteAgentParams, - requestOptions: RequestOptions = RequestOptions.none(), - ): CompletableFuture = - executeAgent(params.toBuilder().sessionId(sessionId).build(), requestOptions) - - /** @see executeAgent */ - fun executeAgent( - params: SessionExecuteAgentParams - ): CompletableFuture = executeAgent(params, RequestOptions.none()) - - /** @see executeAgent */ - fun executeAgent( - params: SessionExecuteAgentParams, - requestOptions: RequestOptions = RequestOptions.none(), - ): CompletableFuture - - /** - * Extracts data from the current page using natural language instructions and optional JSON - * schema for structured output. - */ - fun extract(sessionId: String): CompletableFuture = - extract(sessionId, SessionExtractParams.none()) - - /** @see extract */ - fun extract( - sessionId: String, - params: SessionExtractParams = SessionExtractParams.none(), - requestOptions: RequestOptions = RequestOptions.none(), - ): CompletableFuture = - extract(params.toBuilder().sessionId(sessionId).build(), requestOptions) - - /** @see extract */ - fun extract( - sessionId: String, - params: SessionExtractParams = SessionExtractParams.none(), - ): CompletableFuture = extract(sessionId, params, RequestOptions.none()) - - /** @see extract */ - fun extract( - params: SessionExtractParams, - requestOptions: RequestOptions = RequestOptions.none(), - ): CompletableFuture - - /** @see extract */ - fun extract(params: SessionExtractParams): CompletableFuture = - extract(params, RequestOptions.none()) - - /** @see extract */ - fun extract( - sessionId: String, - requestOptions: RequestOptions, - ): CompletableFuture = - extract(sessionId, SessionExtractParams.none(), requestOptions) - - /** Navigates the browser to the specified URL and waits for page load. */ - fun navigate( - sessionId: String, - params: SessionNavigateParams, - ): CompletableFuture> = - navigate(sessionId, params, RequestOptions.none()) - - /** @see navigate */ - fun navigate( - sessionId: String, - params: SessionNavigateParams, - requestOptions: RequestOptions = RequestOptions.none(), - ): CompletableFuture> = - navigate(params.toBuilder().sessionId(sessionId).build(), requestOptions) - - /** @see navigate */ - fun navigate( - params: SessionNavigateParams - ): CompletableFuture> = - navigate(params, RequestOptions.none()) - - /** @see navigate */ - fun navigate( - params: SessionNavigateParams, - requestOptions: RequestOptions = RequestOptions.none(), - ): CompletableFuture> - - /** - * Returns a list of candidate actions that can be performed on the page, optionally filtered by - * natural language instruction. - */ - fun observe(sessionId: String): CompletableFuture> = - observe(sessionId, SessionObserveParams.none()) - - /** @see observe */ - fun observe( - sessionId: String, - params: SessionObserveParams = SessionObserveParams.none(), - requestOptions: RequestOptions = RequestOptions.none(), - ): CompletableFuture> = - observe(params.toBuilder().sessionId(sessionId).build(), requestOptions) - - /** @see observe */ - fun observe( - sessionId: String, - params: SessionObserveParams = SessionObserveParams.none(), - ): CompletableFuture> = observe(sessionId, params, RequestOptions.none()) - - /** @see observe */ - fun observe( - params: SessionObserveParams, - requestOptions: RequestOptions = RequestOptions.none(), - ): CompletableFuture> - - /** @see observe */ - fun observe(params: SessionObserveParams): CompletableFuture> = - observe(params, RequestOptions.none()) - - /** @see observe */ - fun observe( - sessionId: String, - requestOptions: RequestOptions, - ): CompletableFuture> = - observe(sessionId, SessionObserveParams.none(), requestOptions) - - /** - * Initializes a new Stagehand session with a browser instance. Returns a session ID that must - * be used for all subsequent requests. - */ - fun start(params: SessionStartParams): CompletableFuture = - start(params, RequestOptions.none()) + fun start(): CompletableFuture = start(SessionStartParams.none()) /** @see start */ fun start( - params: SessionStartParams, + params: SessionStartParams = SessionStartParams.none(), requestOptions: RequestOptions = RequestOptions.none(), ): CompletableFuture + /** @see start */ + fun start( + params: SessionStartParams = SessionStartParams.none() + ): CompletableFuture = start(params, RequestOptions.none()) + + /** @see start */ + fun start(requestOptions: RequestOptions): CompletableFuture = + start(SessionStartParams.none(), requestOptions) + /** * A view of [SessionServiceAsync] that provides access to raw HTTP responses for each method. */ @@ -254,226 +60,28 @@ interface SessionServiceAsync { ): SessionServiceAsync.WithRawResponse /** - * Returns a raw HTTP response for `post /sessions/{sessionId}/act`, but is otherwise the - * same as [SessionServiceAsync.act]. - */ - fun act( - sessionId: String, - params: SessionActParams, - ): CompletableFuture> = - act(sessionId, params, RequestOptions.none()) - - /** @see act */ - fun act( - sessionId: String, - params: SessionActParams, - requestOptions: RequestOptions = RequestOptions.none(), - ): CompletableFuture> = - act(params.toBuilder().sessionId(sessionId).build(), requestOptions) - - /** @see act */ - fun act(params: SessionActParams): CompletableFuture> = - act(params, RequestOptions.none()) - - /** @see act */ - fun act( - params: SessionActParams, - requestOptions: RequestOptions = RequestOptions.none(), - ): CompletableFuture> - - /** - * Returns a raw HTTP response for `post /sessions/{sessionId}/end`, but is otherwise the - * same as [SessionServiceAsync.end]. - */ - fun end(sessionId: String): CompletableFuture> = - end(sessionId, SessionEndParams.none()) - - /** @see end */ - fun end( - sessionId: String, - params: SessionEndParams = SessionEndParams.none(), - requestOptions: RequestOptions = RequestOptions.none(), - ): CompletableFuture> = - end(params.toBuilder().sessionId(sessionId).build(), requestOptions) - - /** @see end */ - fun end( - sessionId: String, - params: SessionEndParams = SessionEndParams.none(), - ): CompletableFuture> = - end(sessionId, params, RequestOptions.none()) - - /** @see end */ - fun end( - params: SessionEndParams, - requestOptions: RequestOptions = RequestOptions.none(), - ): CompletableFuture> - - /** @see end */ - fun end(params: SessionEndParams): CompletableFuture> = - end(params, RequestOptions.none()) - - /** @see end */ - fun end( - sessionId: String, - requestOptions: RequestOptions, - ): CompletableFuture> = - end(sessionId, SessionEndParams.none(), requestOptions) - - /** - * Returns a raw HTTP response for `post /sessions/{sessionId}/agentExecute`, but is - * otherwise the same as [SessionServiceAsync.executeAgent]. - */ - fun executeAgent( - sessionId: String, - params: SessionExecuteAgentParams, - ): CompletableFuture> = - executeAgent(sessionId, params, RequestOptions.none()) - - /** @see executeAgent */ - fun executeAgent( - sessionId: String, - params: SessionExecuteAgentParams, - requestOptions: RequestOptions = RequestOptions.none(), - ): CompletableFuture> = - executeAgent(params.toBuilder().sessionId(sessionId).build(), requestOptions) - - /** @see executeAgent */ - fun executeAgent( - params: SessionExecuteAgentParams - ): CompletableFuture> = - executeAgent(params, RequestOptions.none()) - - /** @see executeAgent */ - fun executeAgent( - params: SessionExecuteAgentParams, - requestOptions: RequestOptions = RequestOptions.none(), - ): CompletableFuture> - - /** - * Returns a raw HTTP response for `post /sessions/{sessionId}/extract`, but is otherwise - * the same as [SessionServiceAsync.extract]. - */ - fun extract(sessionId: String): CompletableFuture> = - extract(sessionId, SessionExtractParams.none()) - - /** @see extract */ - fun extract( - sessionId: String, - params: SessionExtractParams = SessionExtractParams.none(), - requestOptions: RequestOptions = RequestOptions.none(), - ): CompletableFuture> = - extract(params.toBuilder().sessionId(sessionId).build(), requestOptions) - - /** @see extract */ - fun extract( - sessionId: String, - params: SessionExtractParams = SessionExtractParams.none(), - ): CompletableFuture> = - extract(sessionId, params, RequestOptions.none()) - - /** @see extract */ - fun extract( - params: SessionExtractParams, - requestOptions: RequestOptions = RequestOptions.none(), - ): CompletableFuture> - - /** @see extract */ - fun extract( - params: SessionExtractParams - ): CompletableFuture> = - extract(params, RequestOptions.none()) - - /** @see extract */ - fun extract( - sessionId: String, - requestOptions: RequestOptions, - ): CompletableFuture> = - extract(sessionId, SessionExtractParams.none(), requestOptions) - - /** - * Returns a raw HTTP response for `post /sessions/{sessionId}/navigate`, but is otherwise - * the same as [SessionServiceAsync.navigate]. - */ - fun navigate( - sessionId: String, - params: SessionNavigateParams, - ): CompletableFuture>> = - navigate(sessionId, params, RequestOptions.none()) - - /** @see navigate */ - fun navigate( - sessionId: String, - params: SessionNavigateParams, - requestOptions: RequestOptions = RequestOptions.none(), - ): CompletableFuture>> = - navigate(params.toBuilder().sessionId(sessionId).build(), requestOptions) - - /** @see navigate */ - fun navigate( - params: SessionNavigateParams - ): CompletableFuture>> = - navigate(params, RequestOptions.none()) - - /** @see navigate */ - fun navigate( - params: SessionNavigateParams, - requestOptions: RequestOptions = RequestOptions.none(), - ): CompletableFuture>> - - /** - * Returns a raw HTTP response for `post /sessions/{sessionId}/observe`, but is otherwise - * the same as [SessionServiceAsync.observe]. + * Returns a raw HTTP response for `post /sessions/start`, but is otherwise the same as + * [SessionServiceAsync.start]. */ - fun observe(sessionId: String): CompletableFuture>> = - observe(sessionId, SessionObserveParams.none()) - - /** @see observe */ - fun observe( - sessionId: String, - params: SessionObserveParams = SessionObserveParams.none(), - requestOptions: RequestOptions = RequestOptions.none(), - ): CompletableFuture>> = - observe(params.toBuilder().sessionId(sessionId).build(), requestOptions) + fun start(): CompletableFuture> = + start(SessionStartParams.none()) - /** @see observe */ - fun observe( - sessionId: String, - params: SessionObserveParams = SessionObserveParams.none(), - ): CompletableFuture>> = - observe(sessionId, params, RequestOptions.none()) - - /** @see observe */ - fun observe( - params: SessionObserveParams, + /** @see start */ + fun start( + params: SessionStartParams = SessionStartParams.none(), requestOptions: RequestOptions = RequestOptions.none(), - ): CompletableFuture>> - - /** @see observe */ - fun observe( - params: SessionObserveParams - ): CompletableFuture>> = observe(params, RequestOptions.none()) - - /** @see observe */ - fun observe( - sessionId: String, - requestOptions: RequestOptions, - ): CompletableFuture>> = - observe(sessionId, SessionObserveParams.none(), requestOptions) + ): CompletableFuture> - /** - * Returns a raw HTTP response for `post /sessions/start`, but is otherwise the same as - * [SessionServiceAsync.start]. - */ + /** @see start */ fun start( - params: SessionStartParams + params: SessionStartParams = SessionStartParams.none() ): CompletableFuture> = start(params, RequestOptions.none()) /** @see start */ fun start( - params: SessionStartParams, - requestOptions: RequestOptions = RequestOptions.none(), - ): CompletableFuture> + requestOptions: RequestOptions + ): CompletableFuture> = + start(SessionStartParams.none(), requestOptions) } } diff --git a/stagehand-java-core/src/main/kotlin/com/browserbase/api/services/async/SessionServiceAsyncImpl.kt b/stagehand-java-core/src/main/kotlin/com/browserbase/api/services/async/SessionServiceAsyncImpl.kt index baa7114..056c59c 100644 --- a/stagehand-java-core/src/main/kotlin/com/browserbase/api/services/async/SessionServiceAsyncImpl.kt +++ b/stagehand-java-core/src/main/kotlin/com/browserbase/api/services/async/SessionServiceAsyncImpl.kt @@ -4,7 +4,6 @@ package com.browserbase.api.services.async import com.browserbase.api.core.ClientOptions import com.browserbase.api.core.RequestOptions -import com.browserbase.api.core.checkRequired import com.browserbase.api.core.handlers.errorBodyHandler import com.browserbase.api.core.handlers.errorHandler import com.browserbase.api.core.handlers.jsonHandler @@ -16,24 +15,10 @@ import com.browserbase.api.core.http.HttpResponseFor import com.browserbase.api.core.http.json import com.browserbase.api.core.http.parseable import com.browserbase.api.core.prepareAsync -import com.browserbase.api.models.sessions.Action -import com.browserbase.api.models.sessions.SessionActParams -import com.browserbase.api.models.sessions.SessionActResponse -import com.browserbase.api.models.sessions.SessionEndParams -import com.browserbase.api.models.sessions.SessionEndResponse -import com.browserbase.api.models.sessions.SessionExecuteAgentParams -import com.browserbase.api.models.sessions.SessionExecuteAgentResponse -import com.browserbase.api.models.sessions.SessionExtractParams -import com.browserbase.api.models.sessions.SessionExtractResponse -import com.browserbase.api.models.sessions.SessionNavigateParams -import com.browserbase.api.models.sessions.SessionNavigateResponse -import com.browserbase.api.models.sessions.SessionObserveParams import com.browserbase.api.models.sessions.SessionStartParams import com.browserbase.api.models.sessions.SessionStartResponse -import java.util.Optional import java.util.concurrent.CompletableFuture import java.util.function.Consumer -import kotlin.jvm.optionals.getOrNull class SessionServiceAsyncImpl internal constructor(private val clientOptions: ClientOptions) : SessionServiceAsync { @@ -47,48 +32,6 @@ class SessionServiceAsyncImpl internal constructor(private val clientOptions: Cl override fun withOptions(modifier: Consumer): SessionServiceAsync = SessionServiceAsyncImpl(clientOptions.toBuilder().apply(modifier::accept).build()) - override fun act( - params: SessionActParams, - requestOptions: RequestOptions, - ): CompletableFuture = - // post /sessions/{sessionId}/act - withRawResponse().act(params, requestOptions).thenApply { it.parse() } - - override fun end( - params: SessionEndParams, - requestOptions: RequestOptions, - ): CompletableFuture = - // post /sessions/{sessionId}/end - withRawResponse().end(params, requestOptions).thenApply { it.parse() } - - override fun executeAgent( - params: SessionExecuteAgentParams, - requestOptions: RequestOptions, - ): CompletableFuture = - // post /sessions/{sessionId}/agentExecute - withRawResponse().executeAgent(params, requestOptions).thenApply { it.parse() } - - override fun extract( - params: SessionExtractParams, - requestOptions: RequestOptions, - ): CompletableFuture = - // post /sessions/{sessionId}/extract - withRawResponse().extract(params, requestOptions).thenApply { it.parse() } - - override fun navigate( - params: SessionNavigateParams, - requestOptions: RequestOptions, - ): CompletableFuture> = - // post /sessions/{sessionId}/navigate - withRawResponse().navigate(params, requestOptions).thenApply { it.parse() } - - override fun observe( - params: SessionObserveParams, - requestOptions: RequestOptions, - ): CompletableFuture> = - // post /sessions/{sessionId}/observe - withRawResponse().observe(params, requestOptions).thenApply { it.parse() } - override fun start( params: SessionStartParams, requestOptions: RequestOptions, @@ -109,210 +52,6 @@ class SessionServiceAsyncImpl internal constructor(private val clientOptions: Cl clientOptions.toBuilder().apply(modifier::accept).build() ) - private val actHandler: Handler = - jsonHandler(clientOptions.jsonMapper) - - override fun act( - params: SessionActParams, - requestOptions: RequestOptions, - ): CompletableFuture> { - // We check here instead of in the params builder because this can be specified - // positionally or in the params class. - checkRequired("sessionId", params.sessionId().getOrNull()) - val request = - HttpRequest.builder() - .method(HttpMethod.POST) - .baseUrl(clientOptions.baseUrl()) - .addPathSegments("sessions", params._pathParam(0), "act") - .body(json(clientOptions.jsonMapper, params._body())) - .build() - .prepareAsync(clientOptions, params) - val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) - return request - .thenComposeAsync { clientOptions.httpClient.executeAsync(it, requestOptions) } - .thenApply { response -> - errorHandler.handle(response).parseable { - response - .use { actHandler.handle(it) } - .also { - if (requestOptions.responseValidation!!) { - it.validate() - } - } - } - } - } - - private val endHandler: Handler = - jsonHandler(clientOptions.jsonMapper) - - override fun end( - params: SessionEndParams, - requestOptions: RequestOptions, - ): CompletableFuture> { - // We check here instead of in the params builder because this can be specified - // positionally or in the params class. - checkRequired("sessionId", params.sessionId().getOrNull()) - val request = - HttpRequest.builder() - .method(HttpMethod.POST) - .baseUrl(clientOptions.baseUrl()) - .addPathSegments("sessions", params._pathParam(0), "end") - .apply { params._body().ifPresent { body(json(clientOptions.jsonMapper, it)) } } - .build() - .prepareAsync(clientOptions, params) - val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) - return request - .thenComposeAsync { clientOptions.httpClient.executeAsync(it, requestOptions) } - .thenApply { response -> - errorHandler.handle(response).parseable { - response - .use { endHandler.handle(it) } - .also { - if (requestOptions.responseValidation!!) { - it.validate() - } - } - } - } - } - - private val executeAgentHandler: Handler = - jsonHandler(clientOptions.jsonMapper) - - override fun executeAgent( - params: SessionExecuteAgentParams, - requestOptions: RequestOptions, - ): CompletableFuture> { - // We check here instead of in the params builder because this can be specified - // positionally or in the params class. - checkRequired("sessionId", params.sessionId().getOrNull()) - val request = - HttpRequest.builder() - .method(HttpMethod.POST) - .baseUrl(clientOptions.baseUrl()) - .addPathSegments("sessions", params._pathParam(0), "agentExecute") - .body(json(clientOptions.jsonMapper, params._body())) - .build() - .prepareAsync(clientOptions, params) - val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) - return request - .thenComposeAsync { clientOptions.httpClient.executeAsync(it, requestOptions) } - .thenApply { response -> - errorHandler.handle(response).parseable { - response - .use { executeAgentHandler.handle(it) } - .also { - if (requestOptions.responseValidation!!) { - it.validate() - } - } - } - } - } - - private val extractHandler: Handler = - jsonHandler(clientOptions.jsonMapper) - - override fun extract( - params: SessionExtractParams, - requestOptions: RequestOptions, - ): CompletableFuture> { - // We check here instead of in the params builder because this can be specified - // positionally or in the params class. - checkRequired("sessionId", params.sessionId().getOrNull()) - val request = - HttpRequest.builder() - .method(HttpMethod.POST) - .baseUrl(clientOptions.baseUrl()) - .addPathSegments("sessions", params._pathParam(0), "extract") - .body(json(clientOptions.jsonMapper, params._body())) - .build() - .prepareAsync(clientOptions, params) - val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) - return request - .thenComposeAsync { clientOptions.httpClient.executeAsync(it, requestOptions) } - .thenApply { response -> - errorHandler.handle(response).parseable { - response - .use { extractHandler.handle(it) } - .also { - if (requestOptions.responseValidation!!) { - it.validate() - } - } - } - } - } - - private val navigateHandler: Handler> = - jsonHandler>(clientOptions.jsonMapper) - - override fun navigate( - params: SessionNavigateParams, - requestOptions: RequestOptions, - ): CompletableFuture>> { - // We check here instead of in the params builder because this can be specified - // positionally or in the params class. - checkRequired("sessionId", params.sessionId().getOrNull()) - val request = - HttpRequest.builder() - .method(HttpMethod.POST) - .baseUrl(clientOptions.baseUrl()) - .addPathSegments("sessions", params._pathParam(0), "navigate") - .body(json(clientOptions.jsonMapper, params._body())) - .build() - .prepareAsync(clientOptions, params) - val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) - return request - .thenComposeAsync { clientOptions.httpClient.executeAsync(it, requestOptions) } - .thenApply { response -> - errorHandler.handle(response).parseable { - response - .use { navigateHandler.handle(it) } - .also { - if (requestOptions.responseValidation!!) { - it.ifPresent { it.validate() } - } - } - } - } - } - - private val observeHandler: Handler> = - jsonHandler>(clientOptions.jsonMapper) - - override fun observe( - params: SessionObserveParams, - requestOptions: RequestOptions, - ): CompletableFuture>> { - // We check here instead of in the params builder because this can be specified - // positionally or in the params class. - checkRequired("sessionId", params.sessionId().getOrNull()) - val request = - HttpRequest.builder() - .method(HttpMethod.POST) - .baseUrl(clientOptions.baseUrl()) - .addPathSegments("sessions", params._pathParam(0), "observe") - .body(json(clientOptions.jsonMapper, params._body())) - .build() - .prepareAsync(clientOptions, params) - val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) - return request - .thenComposeAsync { clientOptions.httpClient.executeAsync(it, requestOptions) } - .thenApply { response -> - errorHandler.handle(response).parseable { - response - .use { observeHandler.handle(it) } - .also { - if (requestOptions.responseValidation!!) { - it.forEach { it.validate() } - } - } - } - } - } - private val startHandler: Handler = jsonHandler(clientOptions.jsonMapper) diff --git a/stagehand-java-core/src/main/kotlin/com/browserbase/api/services/blocking/SessionService.kt b/stagehand-java-core/src/main/kotlin/com/browserbase/api/services/blocking/SessionService.kt index aac24dc..ddd7ad3 100644 --- a/stagehand-java-core/src/main/kotlin/com/browserbase/api/services/blocking/SessionService.kt +++ b/stagehand-java-core/src/main/kotlin/com/browserbase/api/services/blocking/SessionService.kt @@ -5,22 +5,9 @@ package com.browserbase.api.services.blocking import com.browserbase.api.core.ClientOptions import com.browserbase.api.core.RequestOptions import com.browserbase.api.core.http.HttpResponseFor -import com.browserbase.api.models.sessions.Action -import com.browserbase.api.models.sessions.SessionActParams -import com.browserbase.api.models.sessions.SessionActResponse -import com.browserbase.api.models.sessions.SessionEndParams -import com.browserbase.api.models.sessions.SessionEndResponse -import com.browserbase.api.models.sessions.SessionExecuteAgentParams -import com.browserbase.api.models.sessions.SessionExecuteAgentResponse -import com.browserbase.api.models.sessions.SessionExtractParams -import com.browserbase.api.models.sessions.SessionExtractResponse -import com.browserbase.api.models.sessions.SessionNavigateParams -import com.browserbase.api.models.sessions.SessionNavigateResponse -import com.browserbase.api.models.sessions.SessionObserveParams import com.browserbase.api.models.sessions.SessionStartParams import com.browserbase.api.models.sessions.SessionStartResponse import com.google.errorprone.annotations.MustBeClosed -import java.util.Optional import java.util.function.Consumer interface SessionService { @@ -38,184 +25,24 @@ interface SessionService { fun withOptions(modifier: Consumer): SessionService /** - * Performs a browser action based on natural language instruction or a specific action object - * returned by observe(). + * Creates a new browser session with the specified configuration. Returns a session ID used for + * all subsequent operations. */ - fun act(sessionId: String, params: SessionActParams): SessionActResponse = - act(sessionId, params, RequestOptions.none()) + fun start(): SessionStartResponse = start(SessionStartParams.none()) - /** @see act */ - fun act( - sessionId: String, - params: SessionActParams, - requestOptions: RequestOptions = RequestOptions.none(), - ): SessionActResponse = act(params.toBuilder().sessionId(sessionId).build(), requestOptions) - - /** @see act */ - fun act(params: SessionActParams): SessionActResponse = act(params, RequestOptions.none()) - - /** @see act */ - fun act( - params: SessionActParams, - requestOptions: RequestOptions = RequestOptions.none(), - ): SessionActResponse - - /** Closes the browser and cleans up all resources associated with the session. */ - fun end(sessionId: String): SessionEndResponse = end(sessionId, SessionEndParams.none()) - - /** @see end */ - fun end( - sessionId: String, - params: SessionEndParams = SessionEndParams.none(), - requestOptions: RequestOptions = RequestOptions.none(), - ): SessionEndResponse = end(params.toBuilder().sessionId(sessionId).build(), requestOptions) - - /** @see end */ - fun end( - sessionId: String, - params: SessionEndParams = SessionEndParams.none(), - ): SessionEndResponse = end(sessionId, params, RequestOptions.none()) - - /** @see end */ - fun end( - params: SessionEndParams, - requestOptions: RequestOptions = RequestOptions.none(), - ): SessionEndResponse - - /** @see end */ - fun end(params: SessionEndParams): SessionEndResponse = end(params, RequestOptions.none()) - - /** @see end */ - fun end(sessionId: String, requestOptions: RequestOptions): SessionEndResponse = - end(sessionId, SessionEndParams.none(), requestOptions) - - /** Runs an autonomous agent that can perform multiple actions to complete a complex task. */ - fun executeAgent( - sessionId: String, - params: SessionExecuteAgentParams, - ): SessionExecuteAgentResponse = executeAgent(sessionId, params, RequestOptions.none()) - - /** @see executeAgent */ - fun executeAgent( - sessionId: String, - params: SessionExecuteAgentParams, - requestOptions: RequestOptions = RequestOptions.none(), - ): SessionExecuteAgentResponse = - executeAgent(params.toBuilder().sessionId(sessionId).build(), requestOptions) - - /** @see executeAgent */ - fun executeAgent(params: SessionExecuteAgentParams): SessionExecuteAgentResponse = - executeAgent(params, RequestOptions.none()) - - /** @see executeAgent */ - fun executeAgent( - params: SessionExecuteAgentParams, - requestOptions: RequestOptions = RequestOptions.none(), - ): SessionExecuteAgentResponse - - /** - * Extracts data from the current page using natural language instructions and optional JSON - * schema for structured output. - */ - fun extract(sessionId: String): SessionExtractResponse = - extract(sessionId, SessionExtractParams.none()) - - /** @see extract */ - fun extract( - sessionId: String, - params: SessionExtractParams = SessionExtractParams.none(), - requestOptions: RequestOptions = RequestOptions.none(), - ): SessionExtractResponse = - extract(params.toBuilder().sessionId(sessionId).build(), requestOptions) - - /** @see extract */ - fun extract( - sessionId: String, - params: SessionExtractParams = SessionExtractParams.none(), - ): SessionExtractResponse = extract(sessionId, params, RequestOptions.none()) - - /** @see extract */ - fun extract( - params: SessionExtractParams, - requestOptions: RequestOptions = RequestOptions.none(), - ): SessionExtractResponse - - /** @see extract */ - fun extract(params: SessionExtractParams): SessionExtractResponse = - extract(params, RequestOptions.none()) - - /** @see extract */ - fun extract(sessionId: String, requestOptions: RequestOptions): SessionExtractResponse = - extract(sessionId, SessionExtractParams.none(), requestOptions) - - /** Navigates the browser to the specified URL and waits for page load. */ - fun navigate( - sessionId: String, - params: SessionNavigateParams, - ): Optional = navigate(sessionId, params, RequestOptions.none()) - - /** @see navigate */ - fun navigate( - sessionId: String, - params: SessionNavigateParams, - requestOptions: RequestOptions = RequestOptions.none(), - ): Optional = - navigate(params.toBuilder().sessionId(sessionId).build(), requestOptions) - - /** @see navigate */ - fun navigate(params: SessionNavigateParams): Optional = - navigate(params, RequestOptions.none()) - - /** @see navigate */ - fun navigate( - params: SessionNavigateParams, - requestOptions: RequestOptions = RequestOptions.none(), - ): Optional - - /** - * Returns a list of candidate actions that can be performed on the page, optionally filtered by - * natural language instruction. - */ - fun observe(sessionId: String): List = observe(sessionId, SessionObserveParams.none()) - - /** @see observe */ - fun observe( - sessionId: String, - params: SessionObserveParams = SessionObserveParams.none(), - requestOptions: RequestOptions = RequestOptions.none(), - ): List = observe(params.toBuilder().sessionId(sessionId).build(), requestOptions) - - /** @see observe */ - fun observe( - sessionId: String, - params: SessionObserveParams = SessionObserveParams.none(), - ): List = observe(sessionId, params, RequestOptions.none()) - - /** @see observe */ - fun observe( - params: SessionObserveParams, + /** @see start */ + fun start( + params: SessionStartParams = SessionStartParams.none(), requestOptions: RequestOptions = RequestOptions.none(), - ): List - - /** @see observe */ - fun observe(params: SessionObserveParams): List = observe(params, RequestOptions.none()) - - /** @see observe */ - fun observe(sessionId: String, requestOptions: RequestOptions): List = - observe(sessionId, SessionObserveParams.none(), requestOptions) + ): SessionStartResponse - /** - * Initializes a new Stagehand session with a browser instance. Returns a session ID that must - * be used for all subsequent requests. - */ - fun start(params: SessionStartParams): SessionStartResponse = + /** @see start */ + fun start(params: SessionStartParams = SessionStartParams.none()): SessionStartResponse = start(params, RequestOptions.none()) /** @see start */ - fun start( - params: SessionStartParams, - requestOptions: RequestOptions = RequestOptions.none(), - ): SessionStartResponse + fun start(requestOptions: RequestOptions): SessionStartResponse = + start(SessionStartParams.none(), requestOptions) /** A view of [SessionService] that provides access to raw HTTP responses for each method. */ interface WithRawResponse { @@ -227,249 +54,29 @@ interface SessionService { */ fun withOptions(modifier: Consumer): SessionService.WithRawResponse - /** - * Returns a raw HTTP response for `post /sessions/{sessionId}/act`, but is otherwise the - * same as [SessionService.act]. - */ - @MustBeClosed - fun act(sessionId: String, params: SessionActParams): HttpResponseFor = - act(sessionId, params, RequestOptions.none()) - - /** @see act */ - @MustBeClosed - fun act( - sessionId: String, - params: SessionActParams, - requestOptions: RequestOptions = RequestOptions.none(), - ): HttpResponseFor = - act(params.toBuilder().sessionId(sessionId).build(), requestOptions) - - /** @see act */ - @MustBeClosed - fun act(params: SessionActParams): HttpResponseFor = - act(params, RequestOptions.none()) - - /** @see act */ - @MustBeClosed - fun act( - params: SessionActParams, - requestOptions: RequestOptions = RequestOptions.none(), - ): HttpResponseFor - - /** - * Returns a raw HTTP response for `post /sessions/{sessionId}/end`, but is otherwise the - * same as [SessionService.end]. - */ - @MustBeClosed - fun end(sessionId: String): HttpResponseFor = - end(sessionId, SessionEndParams.none()) - - /** @see end */ - @MustBeClosed - fun end( - sessionId: String, - params: SessionEndParams = SessionEndParams.none(), - requestOptions: RequestOptions = RequestOptions.none(), - ): HttpResponseFor = - end(params.toBuilder().sessionId(sessionId).build(), requestOptions) - - /** @see end */ - @MustBeClosed - fun end( - sessionId: String, - params: SessionEndParams = SessionEndParams.none(), - ): HttpResponseFor = end(sessionId, params, RequestOptions.none()) - - /** @see end */ - @MustBeClosed - fun end( - params: SessionEndParams, - requestOptions: RequestOptions = RequestOptions.none(), - ): HttpResponseFor - - /** @see end */ - @MustBeClosed - fun end(params: SessionEndParams): HttpResponseFor = - end(params, RequestOptions.none()) - - /** @see end */ - @MustBeClosed - fun end( - sessionId: String, - requestOptions: RequestOptions, - ): HttpResponseFor = - end(sessionId, SessionEndParams.none(), requestOptions) - - /** - * Returns a raw HTTP response for `post /sessions/{sessionId}/agentExecute`, but is - * otherwise the same as [SessionService.executeAgent]. - */ - @MustBeClosed - fun executeAgent( - sessionId: String, - params: SessionExecuteAgentParams, - ): HttpResponseFor = - executeAgent(sessionId, params, RequestOptions.none()) - - /** @see executeAgent */ - @MustBeClosed - fun executeAgent( - sessionId: String, - params: SessionExecuteAgentParams, - requestOptions: RequestOptions = RequestOptions.none(), - ): HttpResponseFor = - executeAgent(params.toBuilder().sessionId(sessionId).build(), requestOptions) - - /** @see executeAgent */ - @MustBeClosed - fun executeAgent( - params: SessionExecuteAgentParams - ): HttpResponseFor = - executeAgent(params, RequestOptions.none()) - - /** @see executeAgent */ - @MustBeClosed - fun executeAgent( - params: SessionExecuteAgentParams, - requestOptions: RequestOptions = RequestOptions.none(), - ): HttpResponseFor - - /** - * Returns a raw HTTP response for `post /sessions/{sessionId}/extract`, but is otherwise - * the same as [SessionService.extract]. - */ - @MustBeClosed - fun extract(sessionId: String): HttpResponseFor = - extract(sessionId, SessionExtractParams.none()) - - /** @see extract */ - @MustBeClosed - fun extract( - sessionId: String, - params: SessionExtractParams = SessionExtractParams.none(), - requestOptions: RequestOptions = RequestOptions.none(), - ): HttpResponseFor = - extract(params.toBuilder().sessionId(sessionId).build(), requestOptions) - - /** @see extract */ - @MustBeClosed - fun extract( - sessionId: String, - params: SessionExtractParams = SessionExtractParams.none(), - ): HttpResponseFor = - extract(sessionId, params, RequestOptions.none()) - - /** @see extract */ - @MustBeClosed - fun extract( - params: SessionExtractParams, - requestOptions: RequestOptions = RequestOptions.none(), - ): HttpResponseFor - - /** @see extract */ - @MustBeClosed - fun extract(params: SessionExtractParams): HttpResponseFor = - extract(params, RequestOptions.none()) - - /** @see extract */ - @MustBeClosed - fun extract( - sessionId: String, - requestOptions: RequestOptions, - ): HttpResponseFor = - extract(sessionId, SessionExtractParams.none(), requestOptions) - - /** - * Returns a raw HTTP response for `post /sessions/{sessionId}/navigate`, but is otherwise - * the same as [SessionService.navigate]. - */ - @MustBeClosed - fun navigate( - sessionId: String, - params: SessionNavigateParams, - ): HttpResponseFor> = - navigate(sessionId, params, RequestOptions.none()) - - /** @see navigate */ - @MustBeClosed - fun navigate( - sessionId: String, - params: SessionNavigateParams, - requestOptions: RequestOptions = RequestOptions.none(), - ): HttpResponseFor> = - navigate(params.toBuilder().sessionId(sessionId).build(), requestOptions) - - /** @see navigate */ - @MustBeClosed - fun navigate( - params: SessionNavigateParams - ): HttpResponseFor> = - navigate(params, RequestOptions.none()) - - /** @see navigate */ - @MustBeClosed - fun navigate( - params: SessionNavigateParams, - requestOptions: RequestOptions = RequestOptions.none(), - ): HttpResponseFor> - - /** - * Returns a raw HTTP response for `post /sessions/{sessionId}/observe`, but is otherwise - * the same as [SessionService.observe]. - */ - @MustBeClosed - fun observe(sessionId: String): HttpResponseFor> = - observe(sessionId, SessionObserveParams.none()) - - /** @see observe */ - @MustBeClosed - fun observe( - sessionId: String, - params: SessionObserveParams = SessionObserveParams.none(), - requestOptions: RequestOptions = RequestOptions.none(), - ): HttpResponseFor> = - observe(params.toBuilder().sessionId(sessionId).build(), requestOptions) - - /** @see observe */ - @MustBeClosed - fun observe( - sessionId: String, - params: SessionObserveParams = SessionObserveParams.none(), - ): HttpResponseFor> = observe(sessionId, params, RequestOptions.none()) - - /** @see observe */ - @MustBeClosed - fun observe( - params: SessionObserveParams, - requestOptions: RequestOptions = RequestOptions.none(), - ): HttpResponseFor> - - /** @see observe */ - @MustBeClosed - fun observe(params: SessionObserveParams): HttpResponseFor> = - observe(params, RequestOptions.none()) - - /** @see observe */ - @MustBeClosed - fun observe( - sessionId: String, - requestOptions: RequestOptions, - ): HttpResponseFor> = - observe(sessionId, SessionObserveParams.none(), requestOptions) - /** * Returns a raw HTTP response for `post /sessions/start`, but is otherwise the same as * [SessionService.start]. */ @MustBeClosed - fun start(params: SessionStartParams): HttpResponseFor = - start(params, RequestOptions.none()) + fun start(): HttpResponseFor = start(SessionStartParams.none()) /** @see start */ @MustBeClosed fun start( - params: SessionStartParams, + params: SessionStartParams = SessionStartParams.none(), requestOptions: RequestOptions = RequestOptions.none(), ): HttpResponseFor + + /** @see start */ + @MustBeClosed + fun start( + params: SessionStartParams = SessionStartParams.none() + ): HttpResponseFor = start(params, RequestOptions.none()) + + /** @see start */ + @MustBeClosed + fun start(requestOptions: RequestOptions): HttpResponseFor = + start(SessionStartParams.none(), requestOptions) } } diff --git a/stagehand-java-core/src/main/kotlin/com/browserbase/api/services/blocking/SessionServiceImpl.kt b/stagehand-java-core/src/main/kotlin/com/browserbase/api/services/blocking/SessionServiceImpl.kt index 6c09595..2a983bb 100644 --- a/stagehand-java-core/src/main/kotlin/com/browserbase/api/services/blocking/SessionServiceImpl.kt +++ b/stagehand-java-core/src/main/kotlin/com/browserbase/api/services/blocking/SessionServiceImpl.kt @@ -4,7 +4,6 @@ package com.browserbase.api.services.blocking import com.browserbase.api.core.ClientOptions import com.browserbase.api.core.RequestOptions -import com.browserbase.api.core.checkRequired import com.browserbase.api.core.handlers.errorBodyHandler import com.browserbase.api.core.handlers.errorHandler import com.browserbase.api.core.handlers.jsonHandler @@ -16,23 +15,9 @@ import com.browserbase.api.core.http.HttpResponseFor import com.browserbase.api.core.http.json import com.browserbase.api.core.http.parseable import com.browserbase.api.core.prepare -import com.browserbase.api.models.sessions.Action -import com.browserbase.api.models.sessions.SessionActParams -import com.browserbase.api.models.sessions.SessionActResponse -import com.browserbase.api.models.sessions.SessionEndParams -import com.browserbase.api.models.sessions.SessionEndResponse -import com.browserbase.api.models.sessions.SessionExecuteAgentParams -import com.browserbase.api.models.sessions.SessionExecuteAgentResponse -import com.browserbase.api.models.sessions.SessionExtractParams -import com.browserbase.api.models.sessions.SessionExtractResponse -import com.browserbase.api.models.sessions.SessionNavigateParams -import com.browserbase.api.models.sessions.SessionNavigateResponse -import com.browserbase.api.models.sessions.SessionObserveParams import com.browserbase.api.models.sessions.SessionStartParams import com.browserbase.api.models.sessions.SessionStartResponse -import java.util.Optional import java.util.function.Consumer -import kotlin.jvm.optionals.getOrNull class SessionServiceImpl internal constructor(private val clientOptions: ClientOptions) : SessionService { @@ -46,42 +31,6 @@ class SessionServiceImpl internal constructor(private val clientOptions: ClientO override fun withOptions(modifier: Consumer): SessionService = SessionServiceImpl(clientOptions.toBuilder().apply(modifier::accept).build()) - override fun act(params: SessionActParams, requestOptions: RequestOptions): SessionActResponse = - // post /sessions/{sessionId}/act - withRawResponse().act(params, requestOptions).parse() - - override fun end(params: SessionEndParams, requestOptions: RequestOptions): SessionEndResponse = - // post /sessions/{sessionId}/end - withRawResponse().end(params, requestOptions).parse() - - override fun executeAgent( - params: SessionExecuteAgentParams, - requestOptions: RequestOptions, - ): SessionExecuteAgentResponse = - // post /sessions/{sessionId}/agentExecute - withRawResponse().executeAgent(params, requestOptions).parse() - - override fun extract( - params: SessionExtractParams, - requestOptions: RequestOptions, - ): SessionExtractResponse = - // post /sessions/{sessionId}/extract - withRawResponse().extract(params, requestOptions).parse() - - override fun navigate( - params: SessionNavigateParams, - requestOptions: RequestOptions, - ): Optional = - // post /sessions/{sessionId}/navigate - withRawResponse().navigate(params, requestOptions).parse() - - override fun observe( - params: SessionObserveParams, - requestOptions: RequestOptions, - ): List = - // post /sessions/{sessionId}/observe - withRawResponse().observe(params, requestOptions).parse() - override fun start( params: SessionStartParams, requestOptions: RequestOptions, @@ -102,192 +51,6 @@ class SessionServiceImpl internal constructor(private val clientOptions: ClientO clientOptions.toBuilder().apply(modifier::accept).build() ) - private val actHandler: Handler = - jsonHandler(clientOptions.jsonMapper) - - override fun act( - params: SessionActParams, - requestOptions: RequestOptions, - ): HttpResponseFor { - // We check here instead of in the params builder because this can be specified - // positionally or in the params class. - checkRequired("sessionId", params.sessionId().getOrNull()) - val request = - HttpRequest.builder() - .method(HttpMethod.POST) - .baseUrl(clientOptions.baseUrl()) - .addPathSegments("sessions", params._pathParam(0), "act") - .body(json(clientOptions.jsonMapper, params._body())) - .build() - .prepare(clientOptions, params) - val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) - val response = clientOptions.httpClient.execute(request, requestOptions) - return errorHandler.handle(response).parseable { - response - .use { actHandler.handle(it) } - .also { - if (requestOptions.responseValidation!!) { - it.validate() - } - } - } - } - - private val endHandler: Handler = - jsonHandler(clientOptions.jsonMapper) - - override fun end( - params: SessionEndParams, - requestOptions: RequestOptions, - ): HttpResponseFor { - // We check here instead of in the params builder because this can be specified - // positionally or in the params class. - checkRequired("sessionId", params.sessionId().getOrNull()) - val request = - HttpRequest.builder() - .method(HttpMethod.POST) - .baseUrl(clientOptions.baseUrl()) - .addPathSegments("sessions", params._pathParam(0), "end") - .apply { params._body().ifPresent { body(json(clientOptions.jsonMapper, it)) } } - .build() - .prepare(clientOptions, params) - val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) - val response = clientOptions.httpClient.execute(request, requestOptions) - return errorHandler.handle(response).parseable { - response - .use { endHandler.handle(it) } - .also { - if (requestOptions.responseValidation!!) { - it.validate() - } - } - } - } - - private val executeAgentHandler: Handler = - jsonHandler(clientOptions.jsonMapper) - - override fun executeAgent( - params: SessionExecuteAgentParams, - requestOptions: RequestOptions, - ): HttpResponseFor { - // We check here instead of in the params builder because this can be specified - // positionally or in the params class. - checkRequired("sessionId", params.sessionId().getOrNull()) - val request = - HttpRequest.builder() - .method(HttpMethod.POST) - .baseUrl(clientOptions.baseUrl()) - .addPathSegments("sessions", params._pathParam(0), "agentExecute") - .body(json(clientOptions.jsonMapper, params._body())) - .build() - .prepare(clientOptions, params) - val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) - val response = clientOptions.httpClient.execute(request, requestOptions) - return errorHandler.handle(response).parseable { - response - .use { executeAgentHandler.handle(it) } - .also { - if (requestOptions.responseValidation!!) { - it.validate() - } - } - } - } - - private val extractHandler: Handler = - jsonHandler(clientOptions.jsonMapper) - - override fun extract( - params: SessionExtractParams, - requestOptions: RequestOptions, - ): HttpResponseFor { - // We check here instead of in the params builder because this can be specified - // positionally or in the params class. - checkRequired("sessionId", params.sessionId().getOrNull()) - val request = - HttpRequest.builder() - .method(HttpMethod.POST) - .baseUrl(clientOptions.baseUrl()) - .addPathSegments("sessions", params._pathParam(0), "extract") - .body(json(clientOptions.jsonMapper, params._body())) - .build() - .prepare(clientOptions, params) - val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) - val response = clientOptions.httpClient.execute(request, requestOptions) - return errorHandler.handle(response).parseable { - response - .use { extractHandler.handle(it) } - .also { - if (requestOptions.responseValidation!!) { - it.validate() - } - } - } - } - - private val navigateHandler: Handler> = - jsonHandler>(clientOptions.jsonMapper) - - override fun navigate( - params: SessionNavigateParams, - requestOptions: RequestOptions, - ): HttpResponseFor> { - // We check here instead of in the params builder because this can be specified - // positionally or in the params class. - checkRequired("sessionId", params.sessionId().getOrNull()) - val request = - HttpRequest.builder() - .method(HttpMethod.POST) - .baseUrl(clientOptions.baseUrl()) - .addPathSegments("sessions", params._pathParam(0), "navigate") - .body(json(clientOptions.jsonMapper, params._body())) - .build() - .prepare(clientOptions, params) - val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) - val response = clientOptions.httpClient.execute(request, requestOptions) - return errorHandler.handle(response).parseable { - response - .use { navigateHandler.handle(it) } - .also { - if (requestOptions.responseValidation!!) { - it.ifPresent { it.validate() } - } - } - } - } - - private val observeHandler: Handler> = - jsonHandler>(clientOptions.jsonMapper) - - override fun observe( - params: SessionObserveParams, - requestOptions: RequestOptions, - ): HttpResponseFor> { - // We check here instead of in the params builder because this can be specified - // positionally or in the params class. - checkRequired("sessionId", params.sessionId().getOrNull()) - val request = - HttpRequest.builder() - .method(HttpMethod.POST) - .baseUrl(clientOptions.baseUrl()) - .addPathSegments("sessions", params._pathParam(0), "observe") - .body(json(clientOptions.jsonMapper, params._body())) - .build() - .prepare(clientOptions, params) - val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) - val response = clientOptions.httpClient.execute(request, requestOptions) - return errorHandler.handle(response).parseable { - response - .use { observeHandler.handle(it) } - .also { - if (requestOptions.responseValidation!!) { - it.forEach { it.validate() } - } - } - } - } - private val startHandler: Handler = jsonHandler(clientOptions.jsonMapper) diff --git a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/ActionTest.kt b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/ActionTest.kt index fcd120c..4464f91 100644 --- a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/ActionTest.kt +++ b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/ActionTest.kt @@ -4,6 +4,7 @@ package com.browserbase.api.models.sessions import com.browserbase.api.core.jsonMapper import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import kotlin.jvm.optionals.getOrNull import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.Test @@ -13,18 +14,16 @@ internal class ActionTest { fun create() { val action = Action.builder() - .addArgument("string") - .description("description") - .method("method") - .selector("selector") - .backendNodeId(0L) + .description("Click the submit button") + .selector("[data-testid='submit-button']") + .addArgument("Hello World") + .method("click") .build() - assertThat(action.arguments()).containsExactly("string") - assertThat(action.description()).isEqualTo("description") - assertThat(action.method()).isEqualTo("method") - assertThat(action.selector()).isEqualTo("selector") - assertThat(action.backendNodeId()).contains(0L) + assertThat(action.description()).isEqualTo("Click the submit button") + assertThat(action.selector()).isEqualTo("[data-testid='submit-button']") + assertThat(action.arguments().getOrNull()).containsExactly("Hello World") + assertThat(action.method()).contains("click") } @Test @@ -32,11 +31,10 @@ internal class ActionTest { val jsonMapper = jsonMapper() val action = Action.builder() - .addArgument("string") - .description("description") - .method("method") - .selector("selector") - .backendNodeId(0L) + .description("Click the submit button") + .selector("[data-testid='submit-button']") + .addArgument("Hello World") + .method("click") .build() val roundtrippedAction = diff --git a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/ModelConfigTest.kt b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/ModelConfigTest.kt index 0430aec..b45bc3f 100644 --- a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/ModelConfigTest.kt +++ b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/ModelConfigTest.kt @@ -2,39 +2,66 @@ package com.browserbase.api.models.sessions +import com.browserbase.api.core.JsonValue import com.browserbase.api.core.jsonMapper +import com.browserbase.api.errors.StagehandInvalidDataException import com.fasterxml.jackson.module.kotlin.jacksonTypeRef import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.Test +import org.junit.jupiter.api.assertThrows internal class ModelConfigTest { @Test - fun create() { - val modelConfig = - ModelConfig.builder() + fun ofString() { + val string = "string" + + val modelConfig = ModelConfig.ofString(string) + + assertThat(modelConfig.string()).contains(string) + assertThat(modelConfig.unionMember1()).isEmpty + } + + @Test + fun ofStringRoundtrip() { + val jsonMapper = jsonMapper() + val modelConfig = ModelConfig.ofString("string") + + val roundtrippedModelConfig = + jsonMapper.readValue( + jsonMapper.writeValueAsString(modelConfig), + jacksonTypeRef(), + ) + + assertThat(roundtrippedModelConfig).isEqualTo(modelConfig) + } + + @Test + fun ofUnionMember1() { + val unionMember1 = + ModelConfig.UnionMember1.builder() + .modelName("modelName") .apiKey("apiKey") .baseUrl("https://example.com") - .model("model") - .provider(ModelConfig.Provider.OPENAI) .build() - assertThat(modelConfig.apiKey()).contains("apiKey") - assertThat(modelConfig.baseUrl()).contains("https://example.com") - assertThat(modelConfig.model()).contains("model") - assertThat(modelConfig.provider()).contains(ModelConfig.Provider.OPENAI) + val modelConfig = ModelConfig.ofUnionMember1(unionMember1) + + assertThat(modelConfig.string()).isEmpty + assertThat(modelConfig.unionMember1()).contains(unionMember1) } @Test - fun roundtrip() { + fun ofUnionMember1Roundtrip() { val jsonMapper = jsonMapper() val modelConfig = - ModelConfig.builder() - .apiKey("apiKey") - .baseUrl("https://example.com") - .model("model") - .provider(ModelConfig.Provider.OPENAI) - .build() + ModelConfig.ofUnionMember1( + ModelConfig.UnionMember1.builder() + .modelName("modelName") + .apiKey("apiKey") + .baseUrl("https://example.com") + .build() + ) val roundtrippedModelConfig = jsonMapper.readValue( @@ -44,4 +71,13 @@ internal class ModelConfigTest { assertThat(roundtrippedModelConfig).isEqualTo(modelConfig) } + + @Test + fun incompatibleJsonShapeDeserializesToUnknown() { + val value = JsonValue.from(listOf("invalid", "array")) + val modelConfig = jsonMapper().convertValue(value, jacksonTypeRef()) + + val e = assertThrows { modelConfig.validate() } + assertThat(e).hasMessageStartingWith("Unknown ") + } } diff --git a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionActParamsTest.kt b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionActParamsTest.kt deleted file mode 100644 index fbcca00..0000000 --- a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionActParamsTest.kt +++ /dev/null @@ -1,166 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. - -package com.browserbase.api.models.sessions - -import com.browserbase.api.core.JsonValue -import com.browserbase.api.core.http.Headers -import org.assertj.core.api.Assertions.assertThat -import org.junit.jupiter.api.Test - -internal class SessionActParamsTest { - - @Test - fun create() { - SessionActParams.builder() - .sessionId("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") - .xStreamResponse(SessionActParams.XStreamResponse.TRUE) - .input("click the sign in button") - .frameId("frameId") - .options( - SessionActParams.Options.builder() - .model( - ModelConfig.builder() - .apiKey("apiKey") - .baseUrl("https://example.com") - .model("model") - .provider(ModelConfig.Provider.OPENAI) - .build() - ) - .timeout(0L) - .variables( - SessionActParams.Options.Variables.builder() - .putAdditionalProperty("foo", JsonValue.from("string")) - .build() - ) - .build() - ) - .build() - } - - @Test - fun pathParams() { - val params = - SessionActParams.builder() - .sessionId("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") - .input("click the sign in button") - .build() - - assertThat(params._pathParam(0)).isEqualTo("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") - // out-of-bound path param - assertThat(params._pathParam(1)).isEqualTo("") - } - - @Test - fun headers() { - val params = - SessionActParams.builder() - .sessionId("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") - .xStreamResponse(SessionActParams.XStreamResponse.TRUE) - .input("click the sign in button") - .frameId("frameId") - .options( - SessionActParams.Options.builder() - .model( - ModelConfig.builder() - .apiKey("apiKey") - .baseUrl("https://example.com") - .model("model") - .provider(ModelConfig.Provider.OPENAI) - .build() - ) - .timeout(0L) - .variables( - SessionActParams.Options.Variables.builder() - .putAdditionalProperty("foo", JsonValue.from("string")) - .build() - ) - .build() - ) - .build() - - val headers = params._headers() - - assertThat(headers).isEqualTo(Headers.builder().put("x-stream-response", "true").build()) - } - - @Test - fun headersWithoutOptionalFields() { - val params = - SessionActParams.builder() - .sessionId("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") - .input("click the sign in button") - .build() - - val headers = params._headers() - - assertThat(headers).isEqualTo(Headers.builder().build()) - } - - @Test - fun body() { - val params = - SessionActParams.builder() - .sessionId("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") - .xStreamResponse(SessionActParams.XStreamResponse.TRUE) - .input("click the sign in button") - .frameId("frameId") - .options( - SessionActParams.Options.builder() - .model( - ModelConfig.builder() - .apiKey("apiKey") - .baseUrl("https://example.com") - .model("model") - .provider(ModelConfig.Provider.OPENAI) - .build() - ) - .timeout(0L) - .variables( - SessionActParams.Options.Variables.builder() - .putAdditionalProperty("foo", JsonValue.from("string")) - .build() - ) - .build() - ) - .build() - - val body = params._body() - - assertThat(body.input()) - .isEqualTo(SessionActParams.Input.ofString("click the sign in button")) - assertThat(body.frameId()).contains("frameId") - assertThat(body.options()) - .contains( - SessionActParams.Options.builder() - .model( - ModelConfig.builder() - .apiKey("apiKey") - .baseUrl("https://example.com") - .model("model") - .provider(ModelConfig.Provider.OPENAI) - .build() - ) - .timeout(0L) - .variables( - SessionActParams.Options.Variables.builder() - .putAdditionalProperty("foo", JsonValue.from("string")) - .build() - ) - .build() - ) - } - - @Test - fun bodyWithoutOptionalFields() { - val params = - SessionActParams.builder() - .sessionId("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") - .input("click the sign in button") - .build() - - val body = params._body() - - assertThat(body.input()) - .isEqualTo(SessionActParams.Input.ofString("click the sign in button")) - } -} diff --git a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionActResponseTest.kt b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionActResponseTest.kt deleted file mode 100644 index 7f4d8c8..0000000 --- a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionActResponseTest.kt +++ /dev/null @@ -1,69 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. - -package com.browserbase.api.models.sessions - -import com.browserbase.api.core.jsonMapper -import com.fasterxml.jackson.module.kotlin.jacksonTypeRef -import org.assertj.core.api.Assertions.assertThat -import org.junit.jupiter.api.Test - -internal class SessionActResponseTest { - - @Test - fun create() { - val sessionActResponse = - SessionActResponse.builder() - .addAction( - Action.builder() - .addArgument("string") - .description("description") - .method("method") - .selector("selector") - .backendNodeId(0L) - .build() - ) - .message("message") - .success(true) - .build() - - assertThat(sessionActResponse.actions()) - .containsExactly( - Action.builder() - .addArgument("string") - .description("description") - .method("method") - .selector("selector") - .backendNodeId(0L) - .build() - ) - assertThat(sessionActResponse.message()).isEqualTo("message") - assertThat(sessionActResponse.success()).isEqualTo(true) - } - - @Test - fun roundtrip() { - val jsonMapper = jsonMapper() - val sessionActResponse = - SessionActResponse.builder() - .addAction( - Action.builder() - .addArgument("string") - .description("description") - .method("method") - .selector("selector") - .backendNodeId(0L) - .build() - ) - .message("message") - .success(true) - .build() - - val roundtrippedSessionActResponse = - jsonMapper.readValue( - jsonMapper.writeValueAsString(sessionActResponse), - jacksonTypeRef(), - ) - - assertThat(roundtrippedSessionActResponse).isEqualTo(sessionActResponse) - } -} diff --git a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionEndParamsTest.kt b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionEndParamsTest.kt deleted file mode 100644 index ab839e5..0000000 --- a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionEndParamsTest.kt +++ /dev/null @@ -1,24 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. - -package com.browserbase.api.models.sessions - -import org.assertj.core.api.Assertions.assertThat -import org.junit.jupiter.api.Test - -internal class SessionEndParamsTest { - - @Test - fun create() { - SessionEndParams.builder().sessionId("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e").build() - } - - @Test - fun pathParams() { - val params = - SessionEndParams.builder().sessionId("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e").build() - - assertThat(params._pathParam(0)).isEqualTo("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") - // out-of-bound path param - assertThat(params._pathParam(1)).isEqualTo("") - } -} diff --git a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionEndResponseTest.kt b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionEndResponseTest.kt deleted file mode 100644 index b52414c..0000000 --- a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionEndResponseTest.kt +++ /dev/null @@ -1,32 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. - -package com.browserbase.api.models.sessions - -import com.browserbase.api.core.jsonMapper -import com.fasterxml.jackson.module.kotlin.jacksonTypeRef -import org.assertj.core.api.Assertions.assertThat -import org.junit.jupiter.api.Test - -internal class SessionEndResponseTest { - - @Test - fun create() { - val sessionEndResponse = SessionEndResponse.builder().success(true).build() - - assertThat(sessionEndResponse.success()).contains(true) - } - - @Test - fun roundtrip() { - val jsonMapper = jsonMapper() - val sessionEndResponse = SessionEndResponse.builder().success(true).build() - - val roundtrippedSessionEndResponse = - jsonMapper.readValue( - jsonMapper.writeValueAsString(sessionEndResponse), - jacksonTypeRef(), - ) - - assertThat(roundtrippedSessionEndResponse).isEqualTo(sessionEndResponse) - } -} diff --git a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionExecuteAgentParamsTest.kt b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionExecuteAgentParamsTest.kt deleted file mode 100644 index 6d0d59b..0000000 --- a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionExecuteAgentParamsTest.kt +++ /dev/null @@ -1,170 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. - -package com.browserbase.api.models.sessions - -import com.browserbase.api.core.http.Headers -import org.assertj.core.api.Assertions.assertThat -import org.junit.jupiter.api.Test - -internal class SessionExecuteAgentParamsTest { - - @Test - fun create() { - SessionExecuteAgentParams.builder() - .sessionId("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") - .xStreamResponse(SessionExecuteAgentParams.XStreamResponse.TRUE) - .agentConfig( - SessionExecuteAgentParams.AgentConfig.builder() - .cua(true) - .model("openai/gpt-4o") - .provider(SessionExecuteAgentParams.AgentConfig.Provider.OPENAI) - .systemPrompt("systemPrompt") - .build() - ) - .executeOptions( - SessionExecuteAgentParams.ExecuteOptions.builder() - .instruction("Find and click the first product") - .highlightCursor(true) - .maxSteps(10L) - .build() - ) - .frameId("frameId") - .build() - } - - @Test - fun pathParams() { - val params = - SessionExecuteAgentParams.builder() - .sessionId("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") - .agentConfig(SessionExecuteAgentParams.AgentConfig.builder().build()) - .executeOptions( - SessionExecuteAgentParams.ExecuteOptions.builder() - .instruction("Find and click the first product") - .build() - ) - .build() - - assertThat(params._pathParam(0)).isEqualTo("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") - // out-of-bound path param - assertThat(params._pathParam(1)).isEqualTo("") - } - - @Test - fun headers() { - val params = - SessionExecuteAgentParams.builder() - .sessionId("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") - .xStreamResponse(SessionExecuteAgentParams.XStreamResponse.TRUE) - .agentConfig( - SessionExecuteAgentParams.AgentConfig.builder() - .cua(true) - .model("openai/gpt-4o") - .provider(SessionExecuteAgentParams.AgentConfig.Provider.OPENAI) - .systemPrompt("systemPrompt") - .build() - ) - .executeOptions( - SessionExecuteAgentParams.ExecuteOptions.builder() - .instruction("Find and click the first product") - .highlightCursor(true) - .maxSteps(10L) - .build() - ) - .frameId("frameId") - .build() - - val headers = params._headers() - - assertThat(headers).isEqualTo(Headers.builder().put("x-stream-response", "true").build()) - } - - @Test - fun headersWithoutOptionalFields() { - val params = - SessionExecuteAgentParams.builder() - .sessionId("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") - .agentConfig(SessionExecuteAgentParams.AgentConfig.builder().build()) - .executeOptions( - SessionExecuteAgentParams.ExecuteOptions.builder() - .instruction("Find and click the first product") - .build() - ) - .build() - - val headers = params._headers() - - assertThat(headers).isEqualTo(Headers.builder().build()) - } - - @Test - fun body() { - val params = - SessionExecuteAgentParams.builder() - .sessionId("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") - .xStreamResponse(SessionExecuteAgentParams.XStreamResponse.TRUE) - .agentConfig( - SessionExecuteAgentParams.AgentConfig.builder() - .cua(true) - .model("openai/gpt-4o") - .provider(SessionExecuteAgentParams.AgentConfig.Provider.OPENAI) - .systemPrompt("systemPrompt") - .build() - ) - .executeOptions( - SessionExecuteAgentParams.ExecuteOptions.builder() - .instruction("Find and click the first product") - .highlightCursor(true) - .maxSteps(10L) - .build() - ) - .frameId("frameId") - .build() - - val body = params._body() - - assertThat(body.agentConfig()) - .isEqualTo( - SessionExecuteAgentParams.AgentConfig.builder() - .cua(true) - .model("openai/gpt-4o") - .provider(SessionExecuteAgentParams.AgentConfig.Provider.OPENAI) - .systemPrompt("systemPrompt") - .build() - ) - assertThat(body.executeOptions()) - .isEqualTo( - SessionExecuteAgentParams.ExecuteOptions.builder() - .instruction("Find and click the first product") - .highlightCursor(true) - .maxSteps(10L) - .build() - ) - assertThat(body.frameId()).contains("frameId") - } - - @Test - fun bodyWithoutOptionalFields() { - val params = - SessionExecuteAgentParams.builder() - .sessionId("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") - .agentConfig(SessionExecuteAgentParams.AgentConfig.builder().build()) - .executeOptions( - SessionExecuteAgentParams.ExecuteOptions.builder() - .instruction("Find and click the first product") - .build() - ) - .build() - - val body = params._body() - - assertThat(body.agentConfig()) - .isEqualTo(SessionExecuteAgentParams.AgentConfig.builder().build()) - assertThat(body.executeOptions()) - .isEqualTo( - SessionExecuteAgentParams.ExecuteOptions.builder() - .instruction("Find and click the first product") - .build() - ) - } -} diff --git a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionExecuteAgentResponseTest.kt b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionExecuteAgentResponseTest.kt deleted file mode 100644 index 4737af6..0000000 --- a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionExecuteAgentResponseTest.kt +++ /dev/null @@ -1,34 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. - -package com.browserbase.api.models.sessions - -import com.browserbase.api.core.jsonMapper -import com.fasterxml.jackson.module.kotlin.jacksonTypeRef -import org.assertj.core.api.Assertions.assertThat -import org.junit.jupiter.api.Test - -internal class SessionExecuteAgentResponseTest { - - @Test - fun create() { - val sessionExecuteAgentResponse = - SessionExecuteAgentResponse.builder().message("message").build() - - assertThat(sessionExecuteAgentResponse.message()).contains("message") - } - - @Test - fun roundtrip() { - val jsonMapper = jsonMapper() - val sessionExecuteAgentResponse = - SessionExecuteAgentResponse.builder().message("message").build() - - val roundtrippedSessionExecuteAgentResponse = - jsonMapper.readValue( - jsonMapper.writeValueAsString(sessionExecuteAgentResponse), - jacksonTypeRef(), - ) - - assertThat(roundtrippedSessionExecuteAgentResponse).isEqualTo(sessionExecuteAgentResponse) - } -} diff --git a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionExtractParamsTest.kt b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionExtractParamsTest.kt deleted file mode 100644 index 7df72a7..0000000 --- a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionExtractParamsTest.kt +++ /dev/null @@ -1,158 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. - -package com.browserbase.api.models.sessions - -import com.browserbase.api.core.JsonValue -import com.browserbase.api.core.http.Headers -import org.assertj.core.api.Assertions.assertThat -import org.junit.jupiter.api.Test - -internal class SessionExtractParamsTest { - - @Test - fun create() { - SessionExtractParams.builder() - .sessionId("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") - .xStreamResponse(SessionExtractParams.XStreamResponse.TRUE) - .frameId("frameId") - .instruction("extract the page title") - .options( - SessionExtractParams.Options.builder() - .model( - ModelConfig.builder() - .apiKey("apiKey") - .baseUrl("https://example.com") - .model("model") - .provider(ModelConfig.Provider.OPENAI) - .build() - ) - .selector("selector") - .timeout(0L) - .build() - ) - .schema( - SessionExtractParams.Schema.builder() - .putAdditionalProperty("foo", JsonValue.from("bar")) - .build() - ) - .build() - } - - @Test - fun pathParams() { - val params = - SessionExtractParams.builder().sessionId("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e").build() - - assertThat(params._pathParam(0)).isEqualTo("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") - // out-of-bound path param - assertThat(params._pathParam(1)).isEqualTo("") - } - - @Test - fun headers() { - val params = - SessionExtractParams.builder() - .sessionId("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") - .xStreamResponse(SessionExtractParams.XStreamResponse.TRUE) - .frameId("frameId") - .instruction("extract the page title") - .options( - SessionExtractParams.Options.builder() - .model( - ModelConfig.builder() - .apiKey("apiKey") - .baseUrl("https://example.com") - .model("model") - .provider(ModelConfig.Provider.OPENAI) - .build() - ) - .selector("selector") - .timeout(0L) - .build() - ) - .schema( - SessionExtractParams.Schema.builder() - .putAdditionalProperty("foo", JsonValue.from("bar")) - .build() - ) - .build() - - val headers = params._headers() - - assertThat(headers).isEqualTo(Headers.builder().put("x-stream-response", "true").build()) - } - - @Test - fun headersWithoutOptionalFields() { - val params = - SessionExtractParams.builder().sessionId("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e").build() - - val headers = params._headers() - - assertThat(headers).isEqualTo(Headers.builder().build()) - } - - @Test - fun body() { - val params = - SessionExtractParams.builder() - .sessionId("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") - .xStreamResponse(SessionExtractParams.XStreamResponse.TRUE) - .frameId("frameId") - .instruction("extract the page title") - .options( - SessionExtractParams.Options.builder() - .model( - ModelConfig.builder() - .apiKey("apiKey") - .baseUrl("https://example.com") - .model("model") - .provider(ModelConfig.Provider.OPENAI) - .build() - ) - .selector("selector") - .timeout(0L) - .build() - ) - .schema( - SessionExtractParams.Schema.builder() - .putAdditionalProperty("foo", JsonValue.from("bar")) - .build() - ) - .build() - - val body = params._body() - - assertThat(body.frameId()).contains("frameId") - assertThat(body.instruction()).contains("extract the page title") - assertThat(body.options()) - .contains( - SessionExtractParams.Options.builder() - .model( - ModelConfig.builder() - .apiKey("apiKey") - .baseUrl("https://example.com") - .model("model") - .provider(ModelConfig.Provider.OPENAI) - .build() - ) - .selector("selector") - .timeout(0L) - .build() - ) - assertThat(body.schema()) - .contains( - SessionExtractParams.Schema.builder() - .putAdditionalProperty("foo", JsonValue.from("bar")) - .build() - ) - } - - @Test - fun bodyWithoutOptionalFields() { - val params = - SessionExtractParams.builder().sessionId("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e").build() - - val body = params._body() - } -} diff --git a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionExtractResponseTest.kt b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionExtractResponseTest.kt deleted file mode 100644 index 42022d5..0000000 --- a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionExtractResponseTest.kt +++ /dev/null @@ -1,94 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. - -package com.browserbase.api.models.sessions - -import com.browserbase.api.core.JsonValue -import com.browserbase.api.core.jsonMapper -import com.browserbase.api.errors.StagehandInvalidDataException -import com.fasterxml.jackson.module.kotlin.jacksonTypeRef -import org.assertj.core.api.Assertions.assertThat -import org.junit.jupiter.api.Test -import org.junit.jupiter.api.assertThrows -import org.junit.jupiter.params.ParameterizedTest -import org.junit.jupiter.params.provider.EnumSource - -internal class SessionExtractResponseTest { - - @Test - fun ofExtraction() { - val extraction = - SessionExtractResponse.Extraction.builder().extraction("extraction").build() - - val sessionExtractResponse = SessionExtractResponse.ofExtraction(extraction) - - assertThat(sessionExtractResponse.extraction()).contains(extraction) - assertThat(sessionExtractResponse.custom()).isEmpty - } - - @Test - fun ofExtractionRoundtrip() { - val jsonMapper = jsonMapper() - val sessionExtractResponse = - SessionExtractResponse.ofExtraction( - SessionExtractResponse.Extraction.builder().extraction("extraction").build() - ) - - val roundtrippedSessionExtractResponse = - jsonMapper.readValue( - jsonMapper.writeValueAsString(sessionExtractResponse), - jacksonTypeRef(), - ) - - assertThat(roundtrippedSessionExtractResponse).isEqualTo(sessionExtractResponse) - } - - @Test - fun ofCustom() { - val custom = - SessionExtractResponse.Custom.builder() - .putAdditionalProperty("foo", JsonValue.from("bar")) - .build() - - val sessionExtractResponse = SessionExtractResponse.ofCustom(custom) - - assertThat(sessionExtractResponse.extraction()).isEmpty - assertThat(sessionExtractResponse.custom()).contains(custom) - } - - @Test - fun ofCustomRoundtrip() { - val jsonMapper = jsonMapper() - val sessionExtractResponse = - SessionExtractResponse.ofCustom( - SessionExtractResponse.Custom.builder() - .putAdditionalProperty("foo", JsonValue.from("bar")) - .build() - ) - - val roundtrippedSessionExtractResponse = - jsonMapper.readValue( - jsonMapper.writeValueAsString(sessionExtractResponse), - jacksonTypeRef(), - ) - - assertThat(roundtrippedSessionExtractResponse).isEqualTo(sessionExtractResponse) - } - - enum class IncompatibleJsonShapeTestCase(val value: JsonValue) { - BOOLEAN(JsonValue.from(false)), - STRING(JsonValue.from("invalid")), - INTEGER(JsonValue.from(-1)), - FLOAT(JsonValue.from(3.14)), - ARRAY(JsonValue.from(listOf("invalid", "array"))), - } - - @ParameterizedTest - @EnumSource - fun incompatibleJsonShapeDeserializesToUnknown(testCase: IncompatibleJsonShapeTestCase) { - val sessionExtractResponse = - jsonMapper().convertValue(testCase.value, jacksonTypeRef()) - - val e = assertThrows { sessionExtractResponse.validate() } - assertThat(e).hasMessageStartingWith("Unknown ") - } -} diff --git a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionNavigateParamsTest.kt b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionNavigateParamsTest.kt deleted file mode 100644 index fe762db..0000000 --- a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionNavigateParamsTest.kt +++ /dev/null @@ -1,111 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. - -package com.browserbase.api.models.sessions - -import com.browserbase.api.core.http.Headers -import org.assertj.core.api.Assertions.assertThat -import org.junit.jupiter.api.Test - -internal class SessionNavigateParamsTest { - - @Test - fun create() { - SessionNavigateParams.builder() - .sessionId("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") - .xStreamResponse(SessionNavigateParams.XStreamResponse.TRUE) - .url("https://example.com") - .frameId("frameId") - .options( - SessionNavigateParams.Options.builder() - .waitUntil(SessionNavigateParams.Options.WaitUntil.LOAD) - .build() - ) - .build() - } - - @Test - fun pathParams() { - val params = - SessionNavigateParams.builder() - .sessionId("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") - .url("https://example.com") - .build() - - assertThat(params._pathParam(0)).isEqualTo("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") - // out-of-bound path param - assertThat(params._pathParam(1)).isEqualTo("") - } - - @Test - fun headers() { - val params = - SessionNavigateParams.builder() - .sessionId("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") - .xStreamResponse(SessionNavigateParams.XStreamResponse.TRUE) - .url("https://example.com") - .frameId("frameId") - .options( - SessionNavigateParams.Options.builder() - .waitUntil(SessionNavigateParams.Options.WaitUntil.LOAD) - .build() - ) - .build() - - val headers = params._headers() - - assertThat(headers).isEqualTo(Headers.builder().put("x-stream-response", "true").build()) - } - - @Test - fun headersWithoutOptionalFields() { - val params = - SessionNavigateParams.builder() - .sessionId("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") - .url("https://example.com") - .build() - - val headers = params._headers() - - assertThat(headers).isEqualTo(Headers.builder().build()) - } - - @Test - fun body() { - val params = - SessionNavigateParams.builder() - .sessionId("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") - .xStreamResponse(SessionNavigateParams.XStreamResponse.TRUE) - .url("https://example.com") - .frameId("frameId") - .options( - SessionNavigateParams.Options.builder() - .waitUntil(SessionNavigateParams.Options.WaitUntil.LOAD) - .build() - ) - .build() - - val body = params._body() - - assertThat(body.url()).isEqualTo("https://example.com") - assertThat(body.frameId()).contains("frameId") - assertThat(body.options()) - .contains( - SessionNavigateParams.Options.builder() - .waitUntil(SessionNavigateParams.Options.WaitUntil.LOAD) - .build() - ) - } - - @Test - fun bodyWithoutOptionalFields() { - val params = - SessionNavigateParams.builder() - .sessionId("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") - .url("https://example.com") - .build() - - val body = params._body() - - assertThat(body.url()).isEqualTo("https://example.com") - } -} diff --git a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionNavigateResponseTest.kt b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionNavigateResponseTest.kt deleted file mode 100644 index 1385964..0000000 --- a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionNavigateResponseTest.kt +++ /dev/null @@ -1,36 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. - -package com.browserbase.api.models.sessions - -import com.browserbase.api.core.jsonMapper -import com.fasterxml.jackson.module.kotlin.jacksonTypeRef -import org.assertj.core.api.Assertions.assertThat -import org.junit.jupiter.api.Test - -internal class SessionNavigateResponseTest { - - @Test - fun create() { - val sessionNavigateResponse = - SessionNavigateResponse.builder().ok(true).status(0L).url("url").build() - - assertThat(sessionNavigateResponse.ok()).contains(true) - assertThat(sessionNavigateResponse.status()).contains(0L) - assertThat(sessionNavigateResponse.url()).contains("url") - } - - @Test - fun roundtrip() { - val jsonMapper = jsonMapper() - val sessionNavigateResponse = - SessionNavigateResponse.builder().ok(true).status(0L).url("url").build() - - val roundtrippedSessionNavigateResponse = - jsonMapper.readValue( - jsonMapper.writeValueAsString(sessionNavigateResponse), - jacksonTypeRef(), - ) - - assertThat(roundtrippedSessionNavigateResponse).isEqualTo(sessionNavigateResponse) - } -} diff --git a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionObserveParamsTest.kt b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionObserveParamsTest.kt deleted file mode 100644 index a8ab677..0000000 --- a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionObserveParamsTest.kt +++ /dev/null @@ -1,136 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. - -package com.browserbase.api.models.sessions - -import com.browserbase.api.core.http.Headers -import org.assertj.core.api.Assertions.assertThat -import org.junit.jupiter.api.Test - -internal class SessionObserveParamsTest { - - @Test - fun create() { - SessionObserveParams.builder() - .sessionId("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") - .xStreamResponse(SessionObserveParams.XStreamResponse.TRUE) - .frameId("frameId") - .instruction("instruction") - .options( - SessionObserveParams.Options.builder() - .model( - ModelConfig.builder() - .apiKey("apiKey") - .baseUrl("https://example.com") - .model("model") - .provider(ModelConfig.Provider.OPENAI) - .build() - ) - .selector("selector") - .timeout(0L) - .build() - ) - .build() - } - - @Test - fun pathParams() { - val params = - SessionObserveParams.builder().sessionId("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e").build() - - assertThat(params._pathParam(0)).isEqualTo("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") - // out-of-bound path param - assertThat(params._pathParam(1)).isEqualTo("") - } - - @Test - fun headers() { - val params = - SessionObserveParams.builder() - .sessionId("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") - .xStreamResponse(SessionObserveParams.XStreamResponse.TRUE) - .frameId("frameId") - .instruction("instruction") - .options( - SessionObserveParams.Options.builder() - .model( - ModelConfig.builder() - .apiKey("apiKey") - .baseUrl("https://example.com") - .model("model") - .provider(ModelConfig.Provider.OPENAI) - .build() - ) - .selector("selector") - .timeout(0L) - .build() - ) - .build() - - val headers = params._headers() - - assertThat(headers).isEqualTo(Headers.builder().put("x-stream-response", "true").build()) - } - - @Test - fun headersWithoutOptionalFields() { - val params = - SessionObserveParams.builder().sessionId("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e").build() - - val headers = params._headers() - - assertThat(headers).isEqualTo(Headers.builder().build()) - } - - @Test - fun body() { - val params = - SessionObserveParams.builder() - .sessionId("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") - .xStreamResponse(SessionObserveParams.XStreamResponse.TRUE) - .frameId("frameId") - .instruction("instruction") - .options( - SessionObserveParams.Options.builder() - .model( - ModelConfig.builder() - .apiKey("apiKey") - .baseUrl("https://example.com") - .model("model") - .provider(ModelConfig.Provider.OPENAI) - .build() - ) - .selector("selector") - .timeout(0L) - .build() - ) - .build() - - val body = params._body() - - assertThat(body.frameId()).contains("frameId") - assertThat(body.instruction()).contains("instruction") - assertThat(body.options()) - .contains( - SessionObserveParams.Options.builder() - .model( - ModelConfig.builder() - .apiKey("apiKey") - .baseUrl("https://example.com") - .model("model") - .provider(ModelConfig.Provider.OPENAI) - .build() - ) - .selector("selector") - .timeout(0L) - .build() - ) - } - - @Test - fun bodyWithoutOptionalFields() { - val params = - SessionObserveParams.builder().sessionId("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e").build() - - val body = params._body() - } -} diff --git a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionStartParamsTest.kt b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionStartParamsTest.kt index 9454bf3..627f9ae 100644 --- a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionStartParamsTest.kt +++ b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionStartParamsTest.kt @@ -2,6 +2,8 @@ package com.browserbase.api.models.sessions +import com.browserbase.api.core.JsonValue +import com.browserbase.api.core.http.Headers import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.Test @@ -10,51 +12,59 @@ internal class SessionStartParamsTest { @Test fun create() { SessionStartParams.builder() - .browserbaseApiKey("BROWSERBASE_API_KEY") - .browserbaseProjectId("BROWSERBASE_PROJECT_ID") - .domSettleTimeout(0L) - .model("openai/gpt-4o") - .selfHeal(true) - .systemPrompt("systemPrompt") - .verbose(1L) + .xLanguage(JsonValue.from(mapOf())) + .xSdkVersion(JsonValue.from(mapOf())) + .xSentAt(JsonValue.from(mapOf())) + .xStreamResponse(JsonValue.from(mapOf())) + .body(JsonValue.from(mapOf())) .build() } @Test - fun body() { + fun headers() { val params = SessionStartParams.builder() - .browserbaseApiKey("BROWSERBASE_API_KEY") - .browserbaseProjectId("BROWSERBASE_PROJECT_ID") - .domSettleTimeout(0L) - .model("openai/gpt-4o") - .selfHeal(true) - .systemPrompt("systemPrompt") - .verbose(1L) + .xLanguage(JsonValue.from(mapOf())) + .xSdkVersion(JsonValue.from(mapOf())) + .xSentAt(JsonValue.from(mapOf())) + .xStreamResponse(JsonValue.from(mapOf())) + .body(JsonValue.from(mapOf())) .build() - val body = params._body() + val headers = params._headers() - assertThat(body.browserbaseApiKey()).isEqualTo("BROWSERBASE_API_KEY") - assertThat(body.browserbaseProjectId()).isEqualTo("BROWSERBASE_PROJECT_ID") - assertThat(body.domSettleTimeout()).contains(0L) - assertThat(body.model()).contains("openai/gpt-4o") - assertThat(body.selfHeal()).contains(true) - assertThat(body.systemPrompt()).contains("systemPrompt") - assertThat(body.verbose()).contains(1L) + assertThat(headers).isEqualTo(Headers.builder().build()) } @Test - fun bodyWithoutOptionalFields() { + fun headersWithoutOptionalFields() { + val params = SessionStartParams.builder().build() + + val headers = params._headers() + + assertThat(headers).isEqualTo(Headers.builder().build()) + } + + @Test + fun body() { val params = SessionStartParams.builder() - .browserbaseApiKey("BROWSERBASE_API_KEY") - .browserbaseProjectId("BROWSERBASE_PROJECT_ID") + .xLanguage(JsonValue.from(mapOf())) + .xSdkVersion(JsonValue.from(mapOf())) + .xSentAt(JsonValue.from(mapOf())) + .xStreamResponse(JsonValue.from(mapOf())) + .body(JsonValue.from(mapOf())) .build() val body = params._body() - assertThat(body.browserbaseApiKey()).isEqualTo("BROWSERBASE_API_KEY") - assertThat(body.browserbaseProjectId()).isEqualTo("BROWSERBASE_PROJECT_ID") + assertThat(body).isEqualTo(JsonValue.from(mapOf())) + } + + @Test + fun bodyWithoutOptionalFields() { + val params = SessionStartParams.builder().build() + + val body = params._body() } } diff --git a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionStartResponseTest.kt b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionStartResponseTest.kt index 714c73d..51616d7 100644 --- a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionStartResponseTest.kt +++ b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionStartResponseTest.kt @@ -11,25 +11,13 @@ internal class SessionStartResponseTest { @Test fun create() { - val sessionStartResponse = - SessionStartResponse.builder() - .available(true) - .sessionId("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") - .build() - - assertThat(sessionStartResponse.available()).isEqualTo(true) - assertThat(sessionStartResponse.sessionId()) - .isEqualTo("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + val sessionStartResponse = SessionStartResponse.builder().build() } @Test fun roundtrip() { val jsonMapper = jsonMapper() - val sessionStartResponse = - SessionStartResponse.builder() - .available(true) - .sessionId("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") - .build() + val sessionStartResponse = SessionStartResponse.builder().build() val roundtrippedSessionStartResponse = jsonMapper.readValue( diff --git a/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/ErrorHandlingTest.kt b/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/ErrorHandlingTest.kt index 509b889..ccf1223 100644 --- a/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/ErrorHandlingTest.kt +++ b/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/ErrorHandlingTest.kt @@ -74,13 +74,11 @@ internal class ErrorHandlingTest { assertThrows { sessionService.start( SessionStartParams.builder() - .browserbaseApiKey("BROWSERBASE_API_KEY") - .browserbaseProjectId("BROWSERBASE_PROJECT_ID") - .domSettleTimeout(0L) - .model("openai/gpt-4o") - .selfHeal(true) - .systemPrompt("systemPrompt") - .verbose(1L) + .xLanguage(JsonValue.from(mapOf())) + .xSdkVersion(JsonValue.from(mapOf())) + .xSentAt(JsonValue.from(mapOf())) + .xStreamResponse(JsonValue.from(mapOf())) + .body(JsonValue.from(mapOf())) .build() ) } @@ -104,13 +102,11 @@ internal class ErrorHandlingTest { assertThrows { sessionService.start( SessionStartParams.builder() - .browserbaseApiKey("BROWSERBASE_API_KEY") - .browserbaseProjectId("BROWSERBASE_PROJECT_ID") - .domSettleTimeout(0L) - .model("openai/gpt-4o") - .selfHeal(true) - .systemPrompt("systemPrompt") - .verbose(1L) + .xLanguage(JsonValue.from(mapOf())) + .xSdkVersion(JsonValue.from(mapOf())) + .xSentAt(JsonValue.from(mapOf())) + .xStreamResponse(JsonValue.from(mapOf())) + .body(JsonValue.from(mapOf())) .build() ) } @@ -134,13 +130,11 @@ internal class ErrorHandlingTest { assertThrows { sessionService.start( SessionStartParams.builder() - .browserbaseApiKey("BROWSERBASE_API_KEY") - .browserbaseProjectId("BROWSERBASE_PROJECT_ID") - .domSettleTimeout(0L) - .model("openai/gpt-4o") - .selfHeal(true) - .systemPrompt("systemPrompt") - .verbose(1L) + .xLanguage(JsonValue.from(mapOf())) + .xSdkVersion(JsonValue.from(mapOf())) + .xSentAt(JsonValue.from(mapOf())) + .xStreamResponse(JsonValue.from(mapOf())) + .body(JsonValue.from(mapOf())) .build() ) } @@ -164,13 +158,11 @@ internal class ErrorHandlingTest { assertThrows { sessionService.start( SessionStartParams.builder() - .browserbaseApiKey("BROWSERBASE_API_KEY") - .browserbaseProjectId("BROWSERBASE_PROJECT_ID") - .domSettleTimeout(0L) - .model("openai/gpt-4o") - .selfHeal(true) - .systemPrompt("systemPrompt") - .verbose(1L) + .xLanguage(JsonValue.from(mapOf())) + .xSdkVersion(JsonValue.from(mapOf())) + .xSentAt(JsonValue.from(mapOf())) + .xStreamResponse(JsonValue.from(mapOf())) + .body(JsonValue.from(mapOf())) .build() ) } @@ -194,13 +186,11 @@ internal class ErrorHandlingTest { assertThrows { sessionService.start( SessionStartParams.builder() - .browserbaseApiKey("BROWSERBASE_API_KEY") - .browserbaseProjectId("BROWSERBASE_PROJECT_ID") - .domSettleTimeout(0L) - .model("openai/gpt-4o") - .selfHeal(true) - .systemPrompt("systemPrompt") - .verbose(1L) + .xLanguage(JsonValue.from(mapOf())) + .xSdkVersion(JsonValue.from(mapOf())) + .xSentAt(JsonValue.from(mapOf())) + .xStreamResponse(JsonValue.from(mapOf())) + .body(JsonValue.from(mapOf())) .build() ) } @@ -224,13 +214,11 @@ internal class ErrorHandlingTest { assertThrows { sessionService.start( SessionStartParams.builder() - .browserbaseApiKey("BROWSERBASE_API_KEY") - .browserbaseProjectId("BROWSERBASE_PROJECT_ID") - .domSettleTimeout(0L) - .model("openai/gpt-4o") - .selfHeal(true) - .systemPrompt("systemPrompt") - .verbose(1L) + .xLanguage(JsonValue.from(mapOf())) + .xSdkVersion(JsonValue.from(mapOf())) + .xSentAt(JsonValue.from(mapOf())) + .xStreamResponse(JsonValue.from(mapOf())) + .body(JsonValue.from(mapOf())) .build() ) } @@ -254,13 +242,11 @@ internal class ErrorHandlingTest { assertThrows { sessionService.start( SessionStartParams.builder() - .browserbaseApiKey("BROWSERBASE_API_KEY") - .browserbaseProjectId("BROWSERBASE_PROJECT_ID") - .domSettleTimeout(0L) - .model("openai/gpt-4o") - .selfHeal(true) - .systemPrompt("systemPrompt") - .verbose(1L) + .xLanguage(JsonValue.from(mapOf())) + .xSdkVersion(JsonValue.from(mapOf())) + .xSentAt(JsonValue.from(mapOf())) + .xStreamResponse(JsonValue.from(mapOf())) + .body(JsonValue.from(mapOf())) .build() ) } @@ -284,13 +270,11 @@ internal class ErrorHandlingTest { assertThrows { sessionService.start( SessionStartParams.builder() - .browserbaseApiKey("BROWSERBASE_API_KEY") - .browserbaseProjectId("BROWSERBASE_PROJECT_ID") - .domSettleTimeout(0L) - .model("openai/gpt-4o") - .selfHeal(true) - .systemPrompt("systemPrompt") - .verbose(1L) + .xLanguage(JsonValue.from(mapOf())) + .xSdkVersion(JsonValue.from(mapOf())) + .xSentAt(JsonValue.from(mapOf())) + .xStreamResponse(JsonValue.from(mapOf())) + .body(JsonValue.from(mapOf())) .build() ) } @@ -314,13 +298,11 @@ internal class ErrorHandlingTest { assertThrows { sessionService.start( SessionStartParams.builder() - .browserbaseApiKey("BROWSERBASE_API_KEY") - .browserbaseProjectId("BROWSERBASE_PROJECT_ID") - .domSettleTimeout(0L) - .model("openai/gpt-4o") - .selfHeal(true) - .systemPrompt("systemPrompt") - .verbose(1L) + .xLanguage(JsonValue.from(mapOf())) + .xSdkVersion(JsonValue.from(mapOf())) + .xSentAt(JsonValue.from(mapOf())) + .xStreamResponse(JsonValue.from(mapOf())) + .body(JsonValue.from(mapOf())) .build() ) } @@ -344,13 +326,11 @@ internal class ErrorHandlingTest { assertThrows { sessionService.start( SessionStartParams.builder() - .browserbaseApiKey("BROWSERBASE_API_KEY") - .browserbaseProjectId("BROWSERBASE_PROJECT_ID") - .domSettleTimeout(0L) - .model("openai/gpt-4o") - .selfHeal(true) - .systemPrompt("systemPrompt") - .verbose(1L) + .xLanguage(JsonValue.from(mapOf())) + .xSdkVersion(JsonValue.from(mapOf())) + .xSentAt(JsonValue.from(mapOf())) + .xStreamResponse(JsonValue.from(mapOf())) + .body(JsonValue.from(mapOf())) .build() ) } @@ -374,13 +354,11 @@ internal class ErrorHandlingTest { assertThrows { sessionService.start( SessionStartParams.builder() - .browserbaseApiKey("BROWSERBASE_API_KEY") - .browserbaseProjectId("BROWSERBASE_PROJECT_ID") - .domSettleTimeout(0L) - .model("openai/gpt-4o") - .selfHeal(true) - .systemPrompt("systemPrompt") - .verbose(1L) + .xLanguage(JsonValue.from(mapOf())) + .xSdkVersion(JsonValue.from(mapOf())) + .xSentAt(JsonValue.from(mapOf())) + .xStreamResponse(JsonValue.from(mapOf())) + .body(JsonValue.from(mapOf())) .build() ) } @@ -404,13 +382,11 @@ internal class ErrorHandlingTest { assertThrows { sessionService.start( SessionStartParams.builder() - .browserbaseApiKey("BROWSERBASE_API_KEY") - .browserbaseProjectId("BROWSERBASE_PROJECT_ID") - .domSettleTimeout(0L) - .model("openai/gpt-4o") - .selfHeal(true) - .systemPrompt("systemPrompt") - .verbose(1L) + .xLanguage(JsonValue.from(mapOf())) + .xSdkVersion(JsonValue.from(mapOf())) + .xSentAt(JsonValue.from(mapOf())) + .xStreamResponse(JsonValue.from(mapOf())) + .body(JsonValue.from(mapOf())) .build() ) } @@ -434,13 +410,11 @@ internal class ErrorHandlingTest { assertThrows { sessionService.start( SessionStartParams.builder() - .browserbaseApiKey("BROWSERBASE_API_KEY") - .browserbaseProjectId("BROWSERBASE_PROJECT_ID") - .domSettleTimeout(0L) - .model("openai/gpt-4o") - .selfHeal(true) - .systemPrompt("systemPrompt") - .verbose(1L) + .xLanguage(JsonValue.from(mapOf())) + .xSdkVersion(JsonValue.from(mapOf())) + .xSentAt(JsonValue.from(mapOf())) + .xStreamResponse(JsonValue.from(mapOf())) + .body(JsonValue.from(mapOf())) .build() ) } @@ -464,13 +438,11 @@ internal class ErrorHandlingTest { assertThrows { sessionService.start( SessionStartParams.builder() - .browserbaseApiKey("BROWSERBASE_API_KEY") - .browserbaseProjectId("BROWSERBASE_PROJECT_ID") - .domSettleTimeout(0L) - .model("openai/gpt-4o") - .selfHeal(true) - .systemPrompt("systemPrompt") - .verbose(1L) + .xLanguage(JsonValue.from(mapOf())) + .xSdkVersion(JsonValue.from(mapOf())) + .xSentAt(JsonValue.from(mapOf())) + .xStreamResponse(JsonValue.from(mapOf())) + .body(JsonValue.from(mapOf())) .build() ) } @@ -494,13 +466,11 @@ internal class ErrorHandlingTest { assertThrows { sessionService.start( SessionStartParams.builder() - .browserbaseApiKey("BROWSERBASE_API_KEY") - .browserbaseProjectId("BROWSERBASE_PROJECT_ID") - .domSettleTimeout(0L) - .model("openai/gpt-4o") - .selfHeal(true) - .systemPrompt("systemPrompt") - .verbose(1L) + .xLanguage(JsonValue.from(mapOf())) + .xSdkVersion(JsonValue.from(mapOf())) + .xSentAt(JsonValue.from(mapOf())) + .xStreamResponse(JsonValue.from(mapOf())) + .body(JsonValue.from(mapOf())) .build() ) } @@ -524,13 +494,11 @@ internal class ErrorHandlingTest { assertThrows { sessionService.start( SessionStartParams.builder() - .browserbaseApiKey("BROWSERBASE_API_KEY") - .browserbaseProjectId("BROWSERBASE_PROJECT_ID") - .domSettleTimeout(0L) - .model("openai/gpt-4o") - .selfHeal(true) - .systemPrompt("systemPrompt") - .verbose(1L) + .xLanguage(JsonValue.from(mapOf())) + .xSdkVersion(JsonValue.from(mapOf())) + .xSentAt(JsonValue.from(mapOf())) + .xStreamResponse(JsonValue.from(mapOf())) + .body(JsonValue.from(mapOf())) .build() ) } @@ -552,13 +520,11 @@ internal class ErrorHandlingTest { assertThrows { sessionService.start( SessionStartParams.builder() - .browserbaseApiKey("BROWSERBASE_API_KEY") - .browserbaseProjectId("BROWSERBASE_PROJECT_ID") - .domSettleTimeout(0L) - .model("openai/gpt-4o") - .selfHeal(true) - .systemPrompt("systemPrompt") - .verbose(1L) + .xLanguage(JsonValue.from(mapOf())) + .xSdkVersion(JsonValue.from(mapOf())) + .xSentAt(JsonValue.from(mapOf())) + .xStreamResponse(JsonValue.from(mapOf())) + .body(JsonValue.from(mapOf())) .build() ) } diff --git a/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/ServiceParamsTest.kt b/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/ServiceParamsTest.kt index aa39440..8af7ae3 100644 --- a/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/ServiceParamsTest.kt +++ b/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/ServiceParamsTest.kt @@ -5,12 +5,9 @@ package com.browserbase.api.services import com.browserbase.api.client.StagehandClient import com.browserbase.api.client.okhttp.StagehandOkHttpClient import com.browserbase.api.core.JsonValue -import com.browserbase.api.models.sessions.ModelConfig -import com.browserbase.api.models.sessions.SessionActParams import com.browserbase.api.models.sessions.SessionStartParams import com.github.tomakehurst.wiremock.client.WireMock.anyUrl import com.github.tomakehurst.wiremock.client.WireMock.equalTo -import com.github.tomakehurst.wiremock.client.WireMock.matchingJsonPath import com.github.tomakehurst.wiremock.client.WireMock.ok import com.github.tomakehurst.wiremock.client.WireMock.post import com.github.tomakehurst.wiremock.client.WireMock.postRequestedFor @@ -48,16 +45,13 @@ internal class ServiceParamsTest { sessionService.start( SessionStartParams.builder() - .browserbaseApiKey("BROWSERBASE_API_KEY") - .browserbaseProjectId("BROWSERBASE_PROJECT_ID") - .domSettleTimeout(0L) - .model("openai/gpt-4o") - .selfHeal(true) - .systemPrompt("systemPrompt") - .verbose(1L) + .xLanguage(JsonValue.from(mapOf())) + .xSdkVersion(JsonValue.from(mapOf())) + .xSentAt(JsonValue.from(mapOf())) + .xStreamResponse(JsonValue.from(mapOf())) + .body(JsonValue.from(mapOf())) .putAdditionalHeader("Secret-Header", "42") .putAdditionalQueryParam("secret_query_param", "42") - .putAdditionalBodyProperty("secretProperty", JsonValue.from("42")) .build() ) @@ -65,51 +59,6 @@ internal class ServiceParamsTest { postRequestedFor(anyUrl()) .withHeader("Secret-Header", equalTo("42")) .withQueryParam("secret_query_param", equalTo("42")) - .withRequestBody(matchingJsonPath("$.secretProperty", equalTo("42"))) - ) - } - - @Disabled("Prism tests are disabled") - @Test - fun act() { - val sessionService = client.sessions() - stubFor(post(anyUrl()).willReturn(ok("{}"))) - - sessionService.act( - SessionActParams.builder() - .sessionId("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") - .xStreamResponse(SessionActParams.XStreamResponse.TRUE) - .input("click the sign in button") - .frameId("frameId") - .options( - SessionActParams.Options.builder() - .model( - ModelConfig.builder() - .apiKey("apiKey") - .baseUrl("https://example.com") - .model("model") - .provider(ModelConfig.Provider.OPENAI) - .build() - ) - .timeout(0L) - .variables( - SessionActParams.Options.Variables.builder() - .putAdditionalProperty("foo", JsonValue.from("string")) - .build() - ) - .build() - ) - .putAdditionalHeader("Secret-Header", "42") - .putAdditionalQueryParam("secret_query_param", "42") - .putAdditionalBodyProperty("secretProperty", JsonValue.from("42")) - .build() - ) - - verify( - postRequestedFor(anyUrl()) - .withHeader("Secret-Header", equalTo("42")) - .withQueryParam("secret_query_param", equalTo("42")) - .withRequestBody(matchingJsonPath("$.secretProperty", equalTo("42"))) ) } } diff --git a/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/async/SessionServiceAsyncTest.kt b/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/async/SessionServiceAsyncTest.kt index d041842..57ff039 100644 --- a/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/async/SessionServiceAsyncTest.kt +++ b/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/async/SessionServiceAsyncTest.kt @@ -5,14 +5,7 @@ package com.browserbase.api.services.async import com.browserbase.api.TestServerExtension import com.browserbase.api.client.okhttp.StagehandOkHttpClientAsync import com.browserbase.api.core.JsonValue -import com.browserbase.api.models.sessions.ModelConfig -import com.browserbase.api.models.sessions.SessionActParams -import com.browserbase.api.models.sessions.SessionExecuteAgentParams -import com.browserbase.api.models.sessions.SessionExtractParams -import com.browserbase.api.models.sessions.SessionNavigateParams -import com.browserbase.api.models.sessions.SessionObserveParams import com.browserbase.api.models.sessions.SessionStartParams -import kotlin.jvm.optionals.getOrNull import org.junit.jupiter.api.Disabled import org.junit.jupiter.api.Test import org.junit.jupiter.api.extension.ExtendWith @@ -20,225 +13,6 @@ import org.junit.jupiter.api.extension.ExtendWith @ExtendWith(TestServerExtension::class) internal class SessionServiceAsyncTest { - @Disabled("Prism tests are disabled") - @Test - fun act() { - val client = - StagehandOkHttpClientAsync.builder() - .baseUrl(TestServerExtension.BASE_URL) - .browserbaseApiKey("My Browserbase API Key") - .browserbaseProjectId("My Browserbase Project ID") - .modelApiKey("My Model API Key") - .build() - val sessionServiceAsync = client.sessions() - - val responseFuture = - sessionServiceAsync.act( - SessionActParams.builder() - .sessionId("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") - .xStreamResponse(SessionActParams.XStreamResponse.TRUE) - .input("click the sign in button") - .frameId("frameId") - .options( - SessionActParams.Options.builder() - .model( - ModelConfig.builder() - .apiKey("apiKey") - .baseUrl("https://example.com") - .model("model") - .provider(ModelConfig.Provider.OPENAI) - .build() - ) - .timeout(0L) - .variables( - SessionActParams.Options.Variables.builder() - .putAdditionalProperty("foo", JsonValue.from("string")) - .build() - ) - .build() - ) - .build() - ) - - val response = responseFuture.get() - response.validate() - } - - @Disabled("Prism tests are disabled") - @Test - fun end() { - val client = - StagehandOkHttpClientAsync.builder() - .baseUrl(TestServerExtension.BASE_URL) - .browserbaseApiKey("My Browserbase API Key") - .browserbaseProjectId("My Browserbase Project ID") - .modelApiKey("My Model API Key") - .build() - val sessionServiceAsync = client.sessions() - - val responseFuture = sessionServiceAsync.end("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") - - val response = responseFuture.get() - response.validate() - } - - @Disabled("Prism tests are disabled") - @Test - fun executeAgent() { - val client = - StagehandOkHttpClientAsync.builder() - .baseUrl(TestServerExtension.BASE_URL) - .browserbaseApiKey("My Browserbase API Key") - .browserbaseProjectId("My Browserbase Project ID") - .modelApiKey("My Model API Key") - .build() - val sessionServiceAsync = client.sessions() - - val responseFuture = - sessionServiceAsync.executeAgent( - SessionExecuteAgentParams.builder() - .sessionId("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") - .xStreamResponse(SessionExecuteAgentParams.XStreamResponse.TRUE) - .agentConfig( - SessionExecuteAgentParams.AgentConfig.builder() - .cua(true) - .model("openai/gpt-4o") - .provider(SessionExecuteAgentParams.AgentConfig.Provider.OPENAI) - .systemPrompt("systemPrompt") - .build() - ) - .executeOptions( - SessionExecuteAgentParams.ExecuteOptions.builder() - .instruction("Find and click the first product") - .highlightCursor(true) - .maxSteps(10L) - .build() - ) - .frameId("frameId") - .build() - ) - - val response = responseFuture.get() - response.validate() - } - - @Disabled("Prism tests are disabled") - @Test - fun extract() { - val client = - StagehandOkHttpClientAsync.builder() - .baseUrl(TestServerExtension.BASE_URL) - .browserbaseApiKey("My Browserbase API Key") - .browserbaseProjectId("My Browserbase Project ID") - .modelApiKey("My Model API Key") - .build() - val sessionServiceAsync = client.sessions() - - val responseFuture = - sessionServiceAsync.extract( - SessionExtractParams.builder() - .sessionId("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") - .xStreamResponse(SessionExtractParams.XStreamResponse.TRUE) - .frameId("frameId") - .instruction("extract the page title") - .options( - SessionExtractParams.Options.builder() - .model( - ModelConfig.builder() - .apiKey("apiKey") - .baseUrl("https://example.com") - .model("model") - .provider(ModelConfig.Provider.OPENAI) - .build() - ) - .selector("selector") - .timeout(0L) - .build() - ) - .schema( - SessionExtractParams.Schema.builder() - .putAdditionalProperty("foo", JsonValue.from("bar")) - .build() - ) - .build() - ) - - val response = responseFuture.get() - response.validate() - } - - @Disabled("Prism tests are disabled") - @Test - fun navigate() { - val client = - StagehandOkHttpClientAsync.builder() - .baseUrl(TestServerExtension.BASE_URL) - .browserbaseApiKey("My Browserbase API Key") - .browserbaseProjectId("My Browserbase Project ID") - .modelApiKey("My Model API Key") - .build() - val sessionServiceAsync = client.sessions() - - val responseFuture = - sessionServiceAsync.navigate( - SessionNavigateParams.builder() - .sessionId("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") - .xStreamResponse(SessionNavigateParams.XStreamResponse.TRUE) - .url("https://example.com") - .frameId("frameId") - .options( - SessionNavigateParams.Options.builder() - .waitUntil(SessionNavigateParams.Options.WaitUntil.LOAD) - .build() - ) - .build() - ) - - val response = responseFuture.get() - val unwrappedResponse = response.getOrNull() - unwrappedResponse?.validate() - } - - @Disabled("Prism tests are disabled") - @Test - fun observe() { - val client = - StagehandOkHttpClientAsync.builder() - .baseUrl(TestServerExtension.BASE_URL) - .browserbaseApiKey("My Browserbase API Key") - .browserbaseProjectId("My Browserbase Project ID") - .modelApiKey("My Model API Key") - .build() - val sessionServiceAsync = client.sessions() - - val actionsFuture = - sessionServiceAsync.observe( - SessionObserveParams.builder() - .sessionId("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") - .xStreamResponse(SessionObserveParams.XStreamResponse.TRUE) - .frameId("frameId") - .instruction("instruction") - .options( - SessionObserveParams.Options.builder() - .model( - ModelConfig.builder() - .apiKey("apiKey") - .baseUrl("https://example.com") - .model("model") - .provider(ModelConfig.Provider.OPENAI) - .build() - ) - .selector("selector") - .timeout(0L) - .build() - ) - .build() - ) - - val actions = actionsFuture.get() - actions.forEach { it.validate() } - } - @Disabled("Prism tests are disabled") @Test fun start() { @@ -254,13 +28,11 @@ internal class SessionServiceAsyncTest { val responseFuture = sessionServiceAsync.start( SessionStartParams.builder() - .browserbaseApiKey("BROWSERBASE_API_KEY") - .browserbaseProjectId("BROWSERBASE_PROJECT_ID") - .domSettleTimeout(0L) - .model("openai/gpt-4o") - .selfHeal(true) - .systemPrompt("systemPrompt") - .verbose(1L) + .xLanguage(JsonValue.from(mapOf())) + .xSdkVersion(JsonValue.from(mapOf())) + .xSentAt(JsonValue.from(mapOf())) + .xStreamResponse(JsonValue.from(mapOf())) + .body(JsonValue.from(mapOf())) .build() ) diff --git a/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/blocking/SessionServiceTest.kt b/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/blocking/SessionServiceTest.kt index 10177a3..c782cd2 100644 --- a/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/blocking/SessionServiceTest.kt +++ b/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/blocking/SessionServiceTest.kt @@ -5,14 +5,7 @@ package com.browserbase.api.services.blocking import com.browserbase.api.TestServerExtension import com.browserbase.api.client.okhttp.StagehandOkHttpClient import com.browserbase.api.core.JsonValue -import com.browserbase.api.models.sessions.ModelConfig -import com.browserbase.api.models.sessions.SessionActParams -import com.browserbase.api.models.sessions.SessionExecuteAgentParams -import com.browserbase.api.models.sessions.SessionExtractParams -import com.browserbase.api.models.sessions.SessionNavigateParams -import com.browserbase.api.models.sessions.SessionObserveParams import com.browserbase.api.models.sessions.SessionStartParams -import kotlin.jvm.optionals.getOrNull import org.junit.jupiter.api.Disabled import org.junit.jupiter.api.Test import org.junit.jupiter.api.extension.ExtendWith @@ -20,219 +13,6 @@ import org.junit.jupiter.api.extension.ExtendWith @ExtendWith(TestServerExtension::class) internal class SessionServiceTest { - @Disabled("Prism tests are disabled") - @Test - fun act() { - val client = - StagehandOkHttpClient.builder() - .baseUrl(TestServerExtension.BASE_URL) - .browserbaseApiKey("My Browserbase API Key") - .browserbaseProjectId("My Browserbase Project ID") - .modelApiKey("My Model API Key") - .build() - val sessionService = client.sessions() - - val response = - sessionService.act( - SessionActParams.builder() - .sessionId("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") - .xStreamResponse(SessionActParams.XStreamResponse.TRUE) - .input("click the sign in button") - .frameId("frameId") - .options( - SessionActParams.Options.builder() - .model( - ModelConfig.builder() - .apiKey("apiKey") - .baseUrl("https://example.com") - .model("model") - .provider(ModelConfig.Provider.OPENAI) - .build() - ) - .timeout(0L) - .variables( - SessionActParams.Options.Variables.builder() - .putAdditionalProperty("foo", JsonValue.from("string")) - .build() - ) - .build() - ) - .build() - ) - - response.validate() - } - - @Disabled("Prism tests are disabled") - @Test - fun end() { - val client = - StagehandOkHttpClient.builder() - .baseUrl(TestServerExtension.BASE_URL) - .browserbaseApiKey("My Browserbase API Key") - .browserbaseProjectId("My Browserbase Project ID") - .modelApiKey("My Model API Key") - .build() - val sessionService = client.sessions() - - val response = sessionService.end("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") - - response.validate() - } - - @Disabled("Prism tests are disabled") - @Test - fun executeAgent() { - val client = - StagehandOkHttpClient.builder() - .baseUrl(TestServerExtension.BASE_URL) - .browserbaseApiKey("My Browserbase API Key") - .browserbaseProjectId("My Browserbase Project ID") - .modelApiKey("My Model API Key") - .build() - val sessionService = client.sessions() - - val response = - sessionService.executeAgent( - SessionExecuteAgentParams.builder() - .sessionId("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") - .xStreamResponse(SessionExecuteAgentParams.XStreamResponse.TRUE) - .agentConfig( - SessionExecuteAgentParams.AgentConfig.builder() - .cua(true) - .model("openai/gpt-4o") - .provider(SessionExecuteAgentParams.AgentConfig.Provider.OPENAI) - .systemPrompt("systemPrompt") - .build() - ) - .executeOptions( - SessionExecuteAgentParams.ExecuteOptions.builder() - .instruction("Find and click the first product") - .highlightCursor(true) - .maxSteps(10L) - .build() - ) - .frameId("frameId") - .build() - ) - - response.validate() - } - - @Disabled("Prism tests are disabled") - @Test - fun extract() { - val client = - StagehandOkHttpClient.builder() - .baseUrl(TestServerExtension.BASE_URL) - .browserbaseApiKey("My Browserbase API Key") - .browserbaseProjectId("My Browserbase Project ID") - .modelApiKey("My Model API Key") - .build() - val sessionService = client.sessions() - - val response = - sessionService.extract( - SessionExtractParams.builder() - .sessionId("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") - .xStreamResponse(SessionExtractParams.XStreamResponse.TRUE) - .frameId("frameId") - .instruction("extract the page title") - .options( - SessionExtractParams.Options.builder() - .model( - ModelConfig.builder() - .apiKey("apiKey") - .baseUrl("https://example.com") - .model("model") - .provider(ModelConfig.Provider.OPENAI) - .build() - ) - .selector("selector") - .timeout(0L) - .build() - ) - .schema( - SessionExtractParams.Schema.builder() - .putAdditionalProperty("foo", JsonValue.from("bar")) - .build() - ) - .build() - ) - - response.validate() - } - - @Disabled("Prism tests are disabled") - @Test - fun navigate() { - val client = - StagehandOkHttpClient.builder() - .baseUrl(TestServerExtension.BASE_URL) - .browserbaseApiKey("My Browserbase API Key") - .browserbaseProjectId("My Browserbase Project ID") - .modelApiKey("My Model API Key") - .build() - val sessionService = client.sessions() - - val response = - sessionService.navigate( - SessionNavigateParams.builder() - .sessionId("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") - .xStreamResponse(SessionNavigateParams.XStreamResponse.TRUE) - .url("https://example.com") - .frameId("frameId") - .options( - SessionNavigateParams.Options.builder() - .waitUntil(SessionNavigateParams.Options.WaitUntil.LOAD) - .build() - ) - .build() - ) - - val unwrappedResponse = response.getOrNull() - unwrappedResponse?.validate() - } - - @Disabled("Prism tests are disabled") - @Test - fun observe() { - val client = - StagehandOkHttpClient.builder() - .baseUrl(TestServerExtension.BASE_URL) - .browserbaseApiKey("My Browserbase API Key") - .browserbaseProjectId("My Browserbase Project ID") - .modelApiKey("My Model API Key") - .build() - val sessionService = client.sessions() - - val actions = - sessionService.observe( - SessionObserveParams.builder() - .sessionId("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") - .xStreamResponse(SessionObserveParams.XStreamResponse.TRUE) - .frameId("frameId") - .instruction("instruction") - .options( - SessionObserveParams.Options.builder() - .model( - ModelConfig.builder() - .apiKey("apiKey") - .baseUrl("https://example.com") - .model("model") - .provider(ModelConfig.Provider.OPENAI) - .build() - ) - .selector("selector") - .timeout(0L) - .build() - ) - .build() - ) - - actions.forEach { it.validate() } - } - @Disabled("Prism tests are disabled") @Test fun start() { @@ -248,13 +28,11 @@ internal class SessionServiceTest { val response = sessionService.start( SessionStartParams.builder() - .browserbaseApiKey("BROWSERBASE_API_KEY") - .browserbaseProjectId("BROWSERBASE_PROJECT_ID") - .domSettleTimeout(0L) - .model("openai/gpt-4o") - .selfHeal(true) - .systemPrompt("systemPrompt") - .verbose(1L) + .xLanguage(JsonValue.from(mapOf())) + .xSdkVersion(JsonValue.from(mapOf())) + .xSentAt(JsonValue.from(mapOf())) + .xStreamResponse(JsonValue.from(mapOf())) + .body(JsonValue.from(mapOf())) .build() ) diff --git a/stagehand-java-proguard-test/src/test/kotlin/com/browserbase/api/proguard/ProGuardCompatibilityTest.kt b/stagehand-java-proguard-test/src/test/kotlin/com/browserbase/api/proguard/ProGuardCompatibilityTest.kt index 3960aa2..63da21d 100644 --- a/stagehand-java-proguard-test/src/test/kotlin/com/browserbase/api/proguard/ProGuardCompatibilityTest.kt +++ b/stagehand-java-proguard-test/src/test/kotlin/com/browserbase/api/proguard/ProGuardCompatibilityTest.kt @@ -5,7 +5,7 @@ package com.browserbase.api.proguard import com.browserbase.api.client.okhttp.StagehandOkHttpClient import com.browserbase.api.core.jsonMapper import com.browserbase.api.models.sessions.Action -import com.browserbase.api.models.sessions.SessionExtractResponse +import com.browserbase.api.models.sessions.ModelConfig import com.fasterxml.jackson.module.kotlin.jacksonTypeRef import kotlin.reflect.full.memberFunctions import kotlin.reflect.jvm.javaMethod @@ -61,11 +61,10 @@ internal class ProGuardCompatibilityTest { val jsonMapper = jsonMapper() val action = Action.builder() - .addArgument("string") - .description("description") - .method("method") - .selector("selector") - .backendNodeId(0L) + .description("Click the submit button") + .selector("[data-testid='submit-button']") + .addArgument("Hello World") + .method("click") .build() val roundtrippedAction = @@ -75,19 +74,16 @@ internal class ProGuardCompatibilityTest { } @Test - fun sessionExtractResponseRoundtrip() { + fun modelConfigRoundtrip() { val jsonMapper = jsonMapper() - val sessionExtractResponse = - SessionExtractResponse.ofExtraction( - SessionExtractResponse.Extraction.builder().extraction("extraction").build() - ) + val modelConfig = ModelConfig.ofString("string") - val roundtrippedSessionExtractResponse = + val roundtrippedModelConfig = jsonMapper.readValue( - jsonMapper.writeValueAsString(sessionExtractResponse), - jacksonTypeRef(), + jsonMapper.writeValueAsString(modelConfig), + jacksonTypeRef(), ) - assertThat(roundtrippedSessionExtractResponse).isEqualTo(sessionExtractResponse) + assertThat(roundtrippedModelConfig).isEqualTo(modelConfig) } } From 653676a2e7ca92be91a6931bd293a4be2617e79d Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 17 Dec 2025 02:15:15 +0000 Subject: [PATCH 02/18] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index f5e93e0..855c5aa 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 1 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/browserbase%2Fstagehand-516862e7e90968bc55ac44ce7ffe2d5c1f738c11757471c2b9e0e4cff9384f2c.yml -openapi_spec_hash: 19bbe52a6ae0eec7fc3f6698e831ee55 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/browserbase%2Fstagehand-24dc965121b5ad70c846fd8b96ce4638d13bac7e86ba0f50a8d13a5664ac4929.yml +openapi_spec_hash: 5a8e70d2a5358bfd6917f907b4a4d1f3 config_hash: a35b56eb05306a0f02e83c11d57f975f From d7aabe36f42d8344477f2f468bd3ba15837c0516 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 17 Dec 2025 02:40:24 +0000 Subject: [PATCH 03/18] feat(api): manual updates --- .stats.yml | 8 +- README.md | 14 + .../api/models/sessions/SessionActParams.kt | 267 ++++++++++ .../api/models/sessions/SessionActResponse.kt | 113 +++++ .../api/models/sessions/SessionEndParams.kt | 289 +++++++++++ .../api/models/sessions/SessionEndResponse.kt | 113 +++++ .../sessions/SessionExecuteAgentParams.kt | 269 ++++++++++ .../sessions/SessionExecuteAgentResponse.kt | 118 +++++ .../models/sessions/SessionExtractParams.kt | 267 ++++++++++ .../models/sessions/SessionExtractResponse.kt | 114 +++++ .../models/sessions/SessionNavigateParams.kt | 267 ++++++++++ .../sessions/SessionNavigateResponse.kt | 115 +++++ .../models/sessions/SessionObserveParams.kt | 269 ++++++++++ .../models/sessions/SessionObserveResponse.kt | 114 +++++ .../api/services/async/SessionServiceAsync.kt | 466 ++++++++++++++++++ .../services/async/SessionServiceAsyncImpl.kt | 240 +++++++++ .../api/services/blocking/SessionService.kt | 459 +++++++++++++++++ .../services/blocking/SessionServiceImpl.kt | 216 ++++++++ .../models/sessions/SessionActParamsTest.kt | 82 +++ .../models/sessions/SessionActResponseTest.kt | 30 ++ .../models/sessions/SessionEndParamsTest.kt | 56 +++ .../models/sessions/SessionEndResponseTest.kt | 30 ++ .../sessions/SessionExecuteAgentParamsTest.kt | 85 ++++ .../SessionExecuteAgentResponseTest.kt | 30 ++ .../sessions/SessionExtractParamsTest.kt | 82 +++ .../sessions/SessionExtractResponseTest.kt | 30 ++ .../sessions/SessionNavigateParamsTest.kt | 85 ++++ .../sessions/SessionNavigateResponseTest.kt | 30 ++ .../sessions/SessionObserveParamsTest.kt | 82 +++ .../sessions/SessionObserveResponseTest.kt | 30 ++ .../services/async/SessionServiceAsyncTest.kt | 173 +++++++ .../services/blocking/SessionServiceTest.kt | 167 +++++++ 32 files changed, 4706 insertions(+), 4 deletions(-) create mode 100644 stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionActParams.kt create mode 100644 stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionActResponse.kt create mode 100644 stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionEndParams.kt create mode 100644 stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionEndResponse.kt create mode 100644 stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionExecuteAgentParams.kt create mode 100644 stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionExecuteAgentResponse.kt create mode 100644 stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionExtractParams.kt create mode 100644 stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionExtractResponse.kt create mode 100644 stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionNavigateParams.kt create mode 100644 stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionNavigateResponse.kt create mode 100644 stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionObserveParams.kt create mode 100644 stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionObserveResponse.kt create mode 100644 stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionActParamsTest.kt create mode 100644 stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionActResponseTest.kt create mode 100644 stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionEndParamsTest.kt create mode 100644 stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionEndResponseTest.kt create mode 100644 stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionExecuteAgentParamsTest.kt create mode 100644 stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionExecuteAgentResponseTest.kt create mode 100644 stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionExtractParamsTest.kt create mode 100644 stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionExtractResponseTest.kt create mode 100644 stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionNavigateParamsTest.kt create mode 100644 stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionNavigateResponseTest.kt create mode 100644 stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionObserveParamsTest.kt create mode 100644 stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionObserveResponseTest.kt diff --git a/.stats.yml b/.stats.yml index 855c5aa..c436ede 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 1 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/browserbase%2Fstagehand-24dc965121b5ad70c846fd8b96ce4638d13bac7e86ba0f50a8d13a5664ac4929.yml -openapi_spec_hash: 5a8e70d2a5358bfd6917f907b4a4d1f3 -config_hash: a35b56eb05306a0f02e83c11d57f975f +configured_endpoints: 7 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/browserbase%2Fstagehand-c1a6f03afe5d6823c198e5ac476fb688dacc783dae1fefdf6bf142084e298e16.yml +openapi_spec_hash: d20e8f697ce8d5bb80295fc1e8ce02e8 +config_hash: e457d704d820df5d25acfd379169f132 diff --git a/README.md b/README.md index ae4e26a..1bab387 100644 --- a/README.md +++ b/README.md @@ -460,6 +460,20 @@ JsonValue complexValue = JsonValue.from(Map.of( )); ``` +Normally a `Builder` class's `build` method will throw [`IllegalStateException`](https://docs.oracle.com/javase/8/docs/api/java/lang/IllegalStateException.html) if any required parameter or property is unset. + +To forcibly omit a required parameter or property, pass [`JsonMissing`](stagehand-java-core/src/main/kotlin/com/browserbase/api/core/Values.kt): + +```java +import com.browserbase.api.core.JsonMissing; +import com.browserbase.api.models.sessions.SessionActParams; +import com.browserbase.api.models.sessions.SessionStartParams; + +SessionStartParams params = SessionActParams.builder() + .id(JsonMissing.of()) + .build(); +``` + ### Response properties To access undocumented response properties, call the `_additionalProperties()` method: diff --git a/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionActParams.kt b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionActParams.kt new file mode 100644 index 0000000..9992e1f --- /dev/null +++ b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionActParams.kt @@ -0,0 +1,267 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.browserbase.api.models.sessions + +import com.browserbase.api.core.JsonMissing +import com.browserbase.api.core.JsonValue +import com.browserbase.api.core.Params +import com.browserbase.api.core.http.Headers +import com.browserbase.api.core.http.QueryParams +import java.util.Objects +import java.util.Optional +import kotlin.jvm.optionals.getOrNull + +/** Executes a browser action using natural language instructions or a predefined Action object. */ +class SessionActParams +private constructor( + private val id: JsonValue?, + private val xLanguage: JsonValue?, + private val xSdkVersion: JsonValue?, + private val xSentAt: JsonValue?, + private val xStreamResponse: JsonValue?, + private val body: JsonValue, + private val additionalHeaders: Headers, + private val additionalQueryParams: QueryParams, +) : Params { + + fun id(): Optional = Optional.ofNullable(id) + + fun xLanguage(): Optional = Optional.ofNullable(xLanguage) + + fun xSdkVersion(): Optional = Optional.ofNullable(xSdkVersion) + + fun xSentAt(): Optional = Optional.ofNullable(xSentAt) + + fun xStreamResponse(): Optional = Optional.ofNullable(xStreamResponse) + + fun body(): JsonValue = body + + /** Additional headers to send with the request. */ + fun _additionalHeaders(): Headers = additionalHeaders + + /** Additional query param to send with the request. */ + fun _additionalQueryParams(): QueryParams = additionalQueryParams + + fun toBuilder() = Builder().from(this) + + companion object { + + @JvmStatic fun none(): SessionActParams = builder().build() + + /** Returns a mutable builder for constructing an instance of [SessionActParams]. */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [SessionActParams]. */ + class Builder internal constructor() { + + private var id: JsonValue? = null + private var xLanguage: JsonValue? = null + private var xSdkVersion: JsonValue? = null + private var xSentAt: JsonValue? = null + private var xStreamResponse: JsonValue? = null + private var body: JsonValue = JsonMissing.of() + private var additionalHeaders: Headers.Builder = Headers.builder() + private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() + + @JvmSynthetic + internal fun from(sessionActParams: SessionActParams) = apply { + id = sessionActParams.id + xLanguage = sessionActParams.xLanguage + xSdkVersion = sessionActParams.xSdkVersion + xSentAt = sessionActParams.xSentAt + xStreamResponse = sessionActParams.xStreamResponse + body = sessionActParams.body + additionalHeaders = sessionActParams.additionalHeaders.toBuilder() + additionalQueryParams = sessionActParams.additionalQueryParams.toBuilder() + } + + fun id(id: JsonValue?) = apply { this.id = id } + + /** Alias for calling [Builder.id] with `id.orElse(null)`. */ + fun id(id: Optional) = id(id.getOrNull()) + + fun xLanguage(xLanguage: JsonValue?) = apply { this.xLanguage = xLanguage } + + /** Alias for calling [Builder.xLanguage] with `xLanguage.orElse(null)`. */ + fun xLanguage(xLanguage: Optional) = xLanguage(xLanguage.getOrNull()) + + fun xSdkVersion(xSdkVersion: JsonValue?) = apply { this.xSdkVersion = xSdkVersion } + + /** Alias for calling [Builder.xSdkVersion] with `xSdkVersion.orElse(null)`. */ + fun xSdkVersion(xSdkVersion: Optional) = xSdkVersion(xSdkVersion.getOrNull()) + + fun xSentAt(xSentAt: JsonValue?) = apply { this.xSentAt = xSentAt } + + /** Alias for calling [Builder.xSentAt] with `xSentAt.orElse(null)`. */ + fun xSentAt(xSentAt: Optional) = xSentAt(xSentAt.getOrNull()) + + fun xStreamResponse(xStreamResponse: JsonValue?) = apply { + this.xStreamResponse = xStreamResponse + } + + /** Alias for calling [Builder.xStreamResponse] with `xStreamResponse.orElse(null)`. */ + fun xStreamResponse(xStreamResponse: Optional) = + xStreamResponse(xStreamResponse.getOrNull()) + + fun body(body: JsonValue) = apply { this.body = body } + + fun additionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun additionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun putAdditionalHeader(name: String, value: String) = apply { + additionalHeaders.put(name, value) + } + + fun putAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.put(name, values) + } + + fun putAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun putAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun replaceAdditionalHeaders(name: String, value: String) = apply { + additionalHeaders.replace(name, value) + } + + fun replaceAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.replace(name, values) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun removeAdditionalHeaders(name: String) = apply { additionalHeaders.remove(name) } + + fun removeAllAdditionalHeaders(names: Set) = apply { + additionalHeaders.removeAll(names) + } + + fun additionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun additionalQueryParams(additionalQueryParams: Map>) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun putAdditionalQueryParam(key: String, value: String) = apply { + additionalQueryParams.put(key, value) + } + + fun putAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.put(key, values) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun replaceAdditionalQueryParams(key: String, value: String) = apply { + additionalQueryParams.replace(key, value) + } + + fun replaceAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.replace(key, values) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun removeAdditionalQueryParams(key: String) = apply { additionalQueryParams.remove(key) } + + fun removeAllAdditionalQueryParams(keys: Set) = apply { + additionalQueryParams.removeAll(keys) + } + + /** + * Returns an immutable instance of [SessionActParams]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): SessionActParams = + SessionActParams( + id, + xLanguage, + xSdkVersion, + xSentAt, + xStreamResponse, + body, + additionalHeaders.build(), + additionalQueryParams.build(), + ) + } + + fun _body(): JsonValue = body + + fun _pathParam(index: Int): String = + when (index) { + 0 -> id?.toString() ?: "" + else -> "" + } + + override fun _headers(): Headers = Headers.builder().apply { putAll(additionalHeaders) }.build() + + override fun _queryParams(): QueryParams = additionalQueryParams + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is SessionActParams && + id == other.id && + xLanguage == other.xLanguage && + xSdkVersion == other.xSdkVersion && + xSentAt == other.xSentAt && + xStreamResponse == other.xStreamResponse && + body == other.body && + additionalHeaders == other.additionalHeaders && + additionalQueryParams == other.additionalQueryParams + } + + override fun hashCode(): Int = + Objects.hash( + id, + xLanguage, + xSdkVersion, + xSentAt, + xStreamResponse, + body, + additionalHeaders, + additionalQueryParams, + ) + + override fun toString() = + "SessionActParams{id=$id, xLanguage=$xLanguage, xSdkVersion=$xSdkVersion, xSentAt=$xSentAt, xStreamResponse=$xStreamResponse, body=$body, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" +} diff --git a/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionActResponse.kt b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionActResponse.kt new file mode 100644 index 0000000..57b8827 --- /dev/null +++ b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionActResponse.kt @@ -0,0 +1,113 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.browserbase.api.models.sessions + +import com.browserbase.api.core.ExcludeMissing +import com.browserbase.api.core.JsonValue +import com.browserbase.api.errors.StagehandInvalidDataException +import com.fasterxml.jackson.annotation.JsonAnyGetter +import com.fasterxml.jackson.annotation.JsonAnySetter +import com.fasterxml.jackson.annotation.JsonCreator +import java.util.Collections +import java.util.Objects + +class SessionActResponse +@JsonCreator(mode = JsonCreator.Mode.DISABLED) +private constructor(private val additionalProperties: MutableMap) { + + @JsonCreator private constructor() : this(mutableMapOf()) + + @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 [SessionActResponse]. */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [SessionActResponse]. */ + class Builder internal constructor() { + + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(sessionActResponse: SessionActResponse) = apply { + additionalProperties = sessionActResponse.additionalProperties.toMutableMap() + } + + 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 [SessionActResponse]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): SessionActResponse = SessionActResponse(additionalProperties.toMutableMap()) + } + + private var validated: Boolean = false + + fun validate(): SessionActResponse = apply { + if (validated) { + return@apply + } + + 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. + */ + @JvmSynthetic internal fun validity(): Int = 0 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is SessionActResponse && additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { Objects.hash(additionalProperties) } + + override fun hashCode(): Int = hashCode + + override fun toString() = "SessionActResponse{additionalProperties=$additionalProperties}" +} diff --git a/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionEndParams.kt b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionEndParams.kt new file mode 100644 index 0000000..02f9cb0 --- /dev/null +++ b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionEndParams.kt @@ -0,0 +1,289 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.browserbase.api.models.sessions + +import com.browserbase.api.core.JsonValue +import com.browserbase.api.core.Params +import com.browserbase.api.core.http.Headers +import com.browserbase.api.core.http.QueryParams +import com.browserbase.api.core.toImmutable +import java.util.Objects +import java.util.Optional +import kotlin.jvm.optionals.getOrNull + +/** Terminates the browser session and releases all associated resources. */ +class SessionEndParams +private constructor( + private val id: JsonValue?, + private val xLanguage: JsonValue?, + private val xSdkVersion: JsonValue?, + private val xSentAt: JsonValue?, + private val xStreamResponse: JsonValue?, + private val additionalHeaders: Headers, + private val additionalQueryParams: QueryParams, + private val additionalBodyProperties: Map, +) : Params { + + fun id(): Optional = Optional.ofNullable(id) + + fun xLanguage(): Optional = Optional.ofNullable(xLanguage) + + fun xSdkVersion(): Optional = Optional.ofNullable(xSdkVersion) + + fun xSentAt(): Optional = Optional.ofNullable(xSentAt) + + fun xStreamResponse(): Optional = Optional.ofNullable(xStreamResponse) + + /** Additional body properties to send with the request. */ + fun _additionalBodyProperties(): Map = additionalBodyProperties + + /** Additional headers to send with the request. */ + fun _additionalHeaders(): Headers = additionalHeaders + + /** Additional query param to send with the request. */ + fun _additionalQueryParams(): QueryParams = additionalQueryParams + + fun toBuilder() = Builder().from(this) + + companion object { + + @JvmStatic fun none(): SessionEndParams = builder().build() + + /** Returns a mutable builder for constructing an instance of [SessionEndParams]. */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [SessionEndParams]. */ + class Builder internal constructor() { + + private var id: JsonValue? = null + private var xLanguage: JsonValue? = null + private var xSdkVersion: JsonValue? = null + private var xSentAt: JsonValue? = null + private var xStreamResponse: JsonValue? = null + private var additionalHeaders: Headers.Builder = Headers.builder() + private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() + private var additionalBodyProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(sessionEndParams: SessionEndParams) = apply { + id = sessionEndParams.id + xLanguage = sessionEndParams.xLanguage + xSdkVersion = sessionEndParams.xSdkVersion + xSentAt = sessionEndParams.xSentAt + xStreamResponse = sessionEndParams.xStreamResponse + additionalHeaders = sessionEndParams.additionalHeaders.toBuilder() + additionalQueryParams = sessionEndParams.additionalQueryParams.toBuilder() + additionalBodyProperties = sessionEndParams.additionalBodyProperties.toMutableMap() + } + + fun id(id: JsonValue?) = apply { this.id = id } + + /** Alias for calling [Builder.id] with `id.orElse(null)`. */ + fun id(id: Optional) = id(id.getOrNull()) + + fun xLanguage(xLanguage: JsonValue?) = apply { this.xLanguage = xLanguage } + + /** Alias for calling [Builder.xLanguage] with `xLanguage.orElse(null)`. */ + fun xLanguage(xLanguage: Optional) = xLanguage(xLanguage.getOrNull()) + + fun xSdkVersion(xSdkVersion: JsonValue?) = apply { this.xSdkVersion = xSdkVersion } + + /** Alias for calling [Builder.xSdkVersion] with `xSdkVersion.orElse(null)`. */ + fun xSdkVersion(xSdkVersion: Optional) = xSdkVersion(xSdkVersion.getOrNull()) + + fun xSentAt(xSentAt: JsonValue?) = apply { this.xSentAt = xSentAt } + + /** Alias for calling [Builder.xSentAt] with `xSentAt.orElse(null)`. */ + fun xSentAt(xSentAt: Optional) = xSentAt(xSentAt.getOrNull()) + + fun xStreamResponse(xStreamResponse: JsonValue?) = apply { + this.xStreamResponse = xStreamResponse + } + + /** Alias for calling [Builder.xStreamResponse] with `xStreamResponse.orElse(null)`. */ + fun xStreamResponse(xStreamResponse: Optional) = + xStreamResponse(xStreamResponse.getOrNull()) + + fun additionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun additionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun putAdditionalHeader(name: String, value: String) = apply { + additionalHeaders.put(name, value) + } + + fun putAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.put(name, values) + } + + fun putAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun putAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun replaceAdditionalHeaders(name: String, value: String) = apply { + additionalHeaders.replace(name, value) + } + + fun replaceAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.replace(name, values) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun removeAdditionalHeaders(name: String) = apply { additionalHeaders.remove(name) } + + fun removeAllAdditionalHeaders(names: Set) = apply { + additionalHeaders.removeAll(names) + } + + fun additionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun additionalQueryParams(additionalQueryParams: Map>) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun putAdditionalQueryParam(key: String, value: String) = apply { + additionalQueryParams.put(key, value) + } + + fun putAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.put(key, values) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun replaceAdditionalQueryParams(key: String, value: String) = apply { + additionalQueryParams.replace(key, value) + } + + fun replaceAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.replace(key, values) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun removeAdditionalQueryParams(key: String) = apply { additionalQueryParams.remove(key) } + + fun removeAllAdditionalQueryParams(keys: Set) = apply { + additionalQueryParams.removeAll(keys) + } + + fun additionalBodyProperties(additionalBodyProperties: Map) = apply { + this.additionalBodyProperties.clear() + putAllAdditionalBodyProperties(additionalBodyProperties) + } + + fun putAdditionalBodyProperty(key: String, value: JsonValue) = apply { + additionalBodyProperties.put(key, value) + } + + fun putAllAdditionalBodyProperties(additionalBodyProperties: Map) = + apply { + this.additionalBodyProperties.putAll(additionalBodyProperties) + } + + fun removeAdditionalBodyProperty(key: String) = apply { + additionalBodyProperties.remove(key) + } + + fun removeAllAdditionalBodyProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalBodyProperty) + } + + /** + * Returns an immutable instance of [SessionEndParams]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): SessionEndParams = + SessionEndParams( + id, + xLanguage, + xSdkVersion, + xSentAt, + xStreamResponse, + additionalHeaders.build(), + additionalQueryParams.build(), + additionalBodyProperties.toImmutable(), + ) + } + + fun _body(): Optional> = + Optional.ofNullable(additionalBodyProperties.ifEmpty { null }) + + fun _pathParam(index: Int): String = + when (index) { + 0 -> id?.toString() ?: "" + else -> "" + } + + override fun _headers(): Headers = Headers.builder().apply { putAll(additionalHeaders) }.build() + + override fun _queryParams(): QueryParams = additionalQueryParams + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is SessionEndParams && + id == other.id && + xLanguage == other.xLanguage && + xSdkVersion == other.xSdkVersion && + xSentAt == other.xSentAt && + xStreamResponse == other.xStreamResponse && + additionalHeaders == other.additionalHeaders && + additionalQueryParams == other.additionalQueryParams && + additionalBodyProperties == other.additionalBodyProperties + } + + override fun hashCode(): Int = + Objects.hash( + id, + xLanguage, + xSdkVersion, + xSentAt, + xStreamResponse, + additionalHeaders, + additionalQueryParams, + additionalBodyProperties, + ) + + override fun toString() = + "SessionEndParams{id=$id, xLanguage=$xLanguage, xSdkVersion=$xSdkVersion, xSentAt=$xSentAt, xStreamResponse=$xStreamResponse, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams, additionalBodyProperties=$additionalBodyProperties}" +} diff --git a/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionEndResponse.kt b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionEndResponse.kt new file mode 100644 index 0000000..970e0fd --- /dev/null +++ b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionEndResponse.kt @@ -0,0 +1,113 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.browserbase.api.models.sessions + +import com.browserbase.api.core.ExcludeMissing +import com.browserbase.api.core.JsonValue +import com.browserbase.api.errors.StagehandInvalidDataException +import com.fasterxml.jackson.annotation.JsonAnyGetter +import com.fasterxml.jackson.annotation.JsonAnySetter +import com.fasterxml.jackson.annotation.JsonCreator +import java.util.Collections +import java.util.Objects + +class SessionEndResponse +@JsonCreator(mode = JsonCreator.Mode.DISABLED) +private constructor(private val additionalProperties: MutableMap) { + + @JsonCreator private constructor() : this(mutableMapOf()) + + @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 [SessionEndResponse]. */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [SessionEndResponse]. */ + class Builder internal constructor() { + + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(sessionEndResponse: SessionEndResponse) = apply { + additionalProperties = sessionEndResponse.additionalProperties.toMutableMap() + } + + 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 [SessionEndResponse]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): SessionEndResponse = SessionEndResponse(additionalProperties.toMutableMap()) + } + + private var validated: Boolean = false + + fun validate(): SessionEndResponse = apply { + if (validated) { + return@apply + } + + 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. + */ + @JvmSynthetic internal fun validity(): Int = 0 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is SessionEndResponse && additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { Objects.hash(additionalProperties) } + + override fun hashCode(): Int = hashCode + + override fun toString() = "SessionEndResponse{additionalProperties=$additionalProperties}" +} diff --git a/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionExecuteAgentParams.kt b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionExecuteAgentParams.kt new file mode 100644 index 0000000..eca9552 --- /dev/null +++ b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionExecuteAgentParams.kt @@ -0,0 +1,269 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.browserbase.api.models.sessions + +import com.browserbase.api.core.JsonMissing +import com.browserbase.api.core.JsonValue +import com.browserbase.api.core.Params +import com.browserbase.api.core.http.Headers +import com.browserbase.api.core.http.QueryParams +import java.util.Objects +import java.util.Optional +import kotlin.jvm.optionals.getOrNull + +/** Runs an autonomous AI agent that can perform complex multi-step browser tasks. */ +class SessionExecuteAgentParams +private constructor( + private val id: JsonValue?, + private val xLanguage: JsonValue?, + private val xSdkVersion: JsonValue?, + private val xSentAt: JsonValue?, + private val xStreamResponse: JsonValue?, + private val body: JsonValue, + private val additionalHeaders: Headers, + private val additionalQueryParams: QueryParams, +) : Params { + + fun id(): Optional = Optional.ofNullable(id) + + fun xLanguage(): Optional = Optional.ofNullable(xLanguage) + + fun xSdkVersion(): Optional = Optional.ofNullable(xSdkVersion) + + fun xSentAt(): Optional = Optional.ofNullable(xSentAt) + + fun xStreamResponse(): Optional = Optional.ofNullable(xStreamResponse) + + fun body(): JsonValue = body + + /** Additional headers to send with the request. */ + fun _additionalHeaders(): Headers = additionalHeaders + + /** Additional query param to send with the request. */ + fun _additionalQueryParams(): QueryParams = additionalQueryParams + + fun toBuilder() = Builder().from(this) + + companion object { + + @JvmStatic fun none(): SessionExecuteAgentParams = builder().build() + + /** + * Returns a mutable builder for constructing an instance of [SessionExecuteAgentParams]. + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [SessionExecuteAgentParams]. */ + class Builder internal constructor() { + + private var id: JsonValue? = null + private var xLanguage: JsonValue? = null + private var xSdkVersion: JsonValue? = null + private var xSentAt: JsonValue? = null + private var xStreamResponse: JsonValue? = null + private var body: JsonValue = JsonMissing.of() + private var additionalHeaders: Headers.Builder = Headers.builder() + private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() + + @JvmSynthetic + internal fun from(sessionExecuteAgentParams: SessionExecuteAgentParams) = apply { + id = sessionExecuteAgentParams.id + xLanguage = sessionExecuteAgentParams.xLanguage + xSdkVersion = sessionExecuteAgentParams.xSdkVersion + xSentAt = sessionExecuteAgentParams.xSentAt + xStreamResponse = sessionExecuteAgentParams.xStreamResponse + body = sessionExecuteAgentParams.body + additionalHeaders = sessionExecuteAgentParams.additionalHeaders.toBuilder() + additionalQueryParams = sessionExecuteAgentParams.additionalQueryParams.toBuilder() + } + + fun id(id: JsonValue?) = apply { this.id = id } + + /** Alias for calling [Builder.id] with `id.orElse(null)`. */ + fun id(id: Optional) = id(id.getOrNull()) + + fun xLanguage(xLanguage: JsonValue?) = apply { this.xLanguage = xLanguage } + + /** Alias for calling [Builder.xLanguage] with `xLanguage.orElse(null)`. */ + fun xLanguage(xLanguage: Optional) = xLanguage(xLanguage.getOrNull()) + + fun xSdkVersion(xSdkVersion: JsonValue?) = apply { this.xSdkVersion = xSdkVersion } + + /** Alias for calling [Builder.xSdkVersion] with `xSdkVersion.orElse(null)`. */ + fun xSdkVersion(xSdkVersion: Optional) = xSdkVersion(xSdkVersion.getOrNull()) + + fun xSentAt(xSentAt: JsonValue?) = apply { this.xSentAt = xSentAt } + + /** Alias for calling [Builder.xSentAt] with `xSentAt.orElse(null)`. */ + fun xSentAt(xSentAt: Optional) = xSentAt(xSentAt.getOrNull()) + + fun xStreamResponse(xStreamResponse: JsonValue?) = apply { + this.xStreamResponse = xStreamResponse + } + + /** Alias for calling [Builder.xStreamResponse] with `xStreamResponse.orElse(null)`. */ + fun xStreamResponse(xStreamResponse: Optional) = + xStreamResponse(xStreamResponse.getOrNull()) + + fun body(body: JsonValue) = apply { this.body = body } + + fun additionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun additionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun putAdditionalHeader(name: String, value: String) = apply { + additionalHeaders.put(name, value) + } + + fun putAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.put(name, values) + } + + fun putAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun putAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun replaceAdditionalHeaders(name: String, value: String) = apply { + additionalHeaders.replace(name, value) + } + + fun replaceAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.replace(name, values) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun removeAdditionalHeaders(name: String) = apply { additionalHeaders.remove(name) } + + fun removeAllAdditionalHeaders(names: Set) = apply { + additionalHeaders.removeAll(names) + } + + fun additionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun additionalQueryParams(additionalQueryParams: Map>) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun putAdditionalQueryParam(key: String, value: String) = apply { + additionalQueryParams.put(key, value) + } + + fun putAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.put(key, values) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun replaceAdditionalQueryParams(key: String, value: String) = apply { + additionalQueryParams.replace(key, value) + } + + fun replaceAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.replace(key, values) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun removeAdditionalQueryParams(key: String) = apply { additionalQueryParams.remove(key) } + + fun removeAllAdditionalQueryParams(keys: Set) = apply { + additionalQueryParams.removeAll(keys) + } + + /** + * Returns an immutable instance of [SessionExecuteAgentParams]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): SessionExecuteAgentParams = + SessionExecuteAgentParams( + id, + xLanguage, + xSdkVersion, + xSentAt, + xStreamResponse, + body, + additionalHeaders.build(), + additionalQueryParams.build(), + ) + } + + fun _body(): JsonValue = body + + fun _pathParam(index: Int): String = + when (index) { + 0 -> id?.toString() ?: "" + else -> "" + } + + override fun _headers(): Headers = Headers.builder().apply { putAll(additionalHeaders) }.build() + + override fun _queryParams(): QueryParams = additionalQueryParams + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is SessionExecuteAgentParams && + id == other.id && + xLanguage == other.xLanguage && + xSdkVersion == other.xSdkVersion && + xSentAt == other.xSentAt && + xStreamResponse == other.xStreamResponse && + body == other.body && + additionalHeaders == other.additionalHeaders && + additionalQueryParams == other.additionalQueryParams + } + + override fun hashCode(): Int = + Objects.hash( + id, + xLanguage, + xSdkVersion, + xSentAt, + xStreamResponse, + body, + additionalHeaders, + additionalQueryParams, + ) + + override fun toString() = + "SessionExecuteAgentParams{id=$id, xLanguage=$xLanguage, xSdkVersion=$xSdkVersion, xSentAt=$xSentAt, xStreamResponse=$xStreamResponse, body=$body, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" +} diff --git a/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionExecuteAgentResponse.kt b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionExecuteAgentResponse.kt new file mode 100644 index 0000000..700a7ba --- /dev/null +++ b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionExecuteAgentResponse.kt @@ -0,0 +1,118 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.browserbase.api.models.sessions + +import com.browserbase.api.core.ExcludeMissing +import com.browserbase.api.core.JsonValue +import com.browserbase.api.errors.StagehandInvalidDataException +import com.fasterxml.jackson.annotation.JsonAnyGetter +import com.fasterxml.jackson.annotation.JsonAnySetter +import com.fasterxml.jackson.annotation.JsonCreator +import java.util.Collections +import java.util.Objects + +class SessionExecuteAgentResponse +@JsonCreator(mode = JsonCreator.Mode.DISABLED) +private constructor(private val additionalProperties: MutableMap) { + + @JsonCreator private constructor() : this(mutableMapOf()) + + @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 [SessionExecuteAgentResponse]. + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [SessionExecuteAgentResponse]. */ + class Builder internal constructor() { + + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(sessionExecuteAgentResponse: SessionExecuteAgentResponse) = apply { + additionalProperties = sessionExecuteAgentResponse.additionalProperties.toMutableMap() + } + + 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 [SessionExecuteAgentResponse]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): SessionExecuteAgentResponse = + SessionExecuteAgentResponse(additionalProperties.toMutableMap()) + } + + private var validated: Boolean = false + + fun validate(): SessionExecuteAgentResponse = apply { + if (validated) { + return@apply + } + + 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. + */ + @JvmSynthetic internal fun validity(): Int = 0 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is SessionExecuteAgentResponse && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { Objects.hash(additionalProperties) } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "SessionExecuteAgentResponse{additionalProperties=$additionalProperties}" +} diff --git a/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionExtractParams.kt b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionExtractParams.kt new file mode 100644 index 0000000..18414ff --- /dev/null +++ b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionExtractParams.kt @@ -0,0 +1,267 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.browserbase.api.models.sessions + +import com.browserbase.api.core.JsonMissing +import com.browserbase.api.core.JsonValue +import com.browserbase.api.core.Params +import com.browserbase.api.core.http.Headers +import com.browserbase.api.core.http.QueryParams +import java.util.Objects +import java.util.Optional +import kotlin.jvm.optionals.getOrNull + +/** Extracts structured data from the current page using AI-powered analysis. */ +class SessionExtractParams +private constructor( + private val id: JsonValue?, + private val xLanguage: JsonValue?, + private val xSdkVersion: JsonValue?, + private val xSentAt: JsonValue?, + private val xStreamResponse: JsonValue?, + private val body: JsonValue, + private val additionalHeaders: Headers, + private val additionalQueryParams: QueryParams, +) : Params { + + fun id(): Optional = Optional.ofNullable(id) + + fun xLanguage(): Optional = Optional.ofNullable(xLanguage) + + fun xSdkVersion(): Optional = Optional.ofNullable(xSdkVersion) + + fun xSentAt(): Optional = Optional.ofNullable(xSentAt) + + fun xStreamResponse(): Optional = Optional.ofNullable(xStreamResponse) + + fun body(): JsonValue = body + + /** Additional headers to send with the request. */ + fun _additionalHeaders(): Headers = additionalHeaders + + /** Additional query param to send with the request. */ + fun _additionalQueryParams(): QueryParams = additionalQueryParams + + fun toBuilder() = Builder().from(this) + + companion object { + + @JvmStatic fun none(): SessionExtractParams = builder().build() + + /** Returns a mutable builder for constructing an instance of [SessionExtractParams]. */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [SessionExtractParams]. */ + class Builder internal constructor() { + + private var id: JsonValue? = null + private var xLanguage: JsonValue? = null + private var xSdkVersion: JsonValue? = null + private var xSentAt: JsonValue? = null + private var xStreamResponse: JsonValue? = null + private var body: JsonValue = JsonMissing.of() + private var additionalHeaders: Headers.Builder = Headers.builder() + private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() + + @JvmSynthetic + internal fun from(sessionExtractParams: SessionExtractParams) = apply { + id = sessionExtractParams.id + xLanguage = sessionExtractParams.xLanguage + xSdkVersion = sessionExtractParams.xSdkVersion + xSentAt = sessionExtractParams.xSentAt + xStreamResponse = sessionExtractParams.xStreamResponse + body = sessionExtractParams.body + additionalHeaders = sessionExtractParams.additionalHeaders.toBuilder() + additionalQueryParams = sessionExtractParams.additionalQueryParams.toBuilder() + } + + fun id(id: JsonValue?) = apply { this.id = id } + + /** Alias for calling [Builder.id] with `id.orElse(null)`. */ + fun id(id: Optional) = id(id.getOrNull()) + + fun xLanguage(xLanguage: JsonValue?) = apply { this.xLanguage = xLanguage } + + /** Alias for calling [Builder.xLanguage] with `xLanguage.orElse(null)`. */ + fun xLanguage(xLanguage: Optional) = xLanguage(xLanguage.getOrNull()) + + fun xSdkVersion(xSdkVersion: JsonValue?) = apply { this.xSdkVersion = xSdkVersion } + + /** Alias for calling [Builder.xSdkVersion] with `xSdkVersion.orElse(null)`. */ + fun xSdkVersion(xSdkVersion: Optional) = xSdkVersion(xSdkVersion.getOrNull()) + + fun xSentAt(xSentAt: JsonValue?) = apply { this.xSentAt = xSentAt } + + /** Alias for calling [Builder.xSentAt] with `xSentAt.orElse(null)`. */ + fun xSentAt(xSentAt: Optional) = xSentAt(xSentAt.getOrNull()) + + fun xStreamResponse(xStreamResponse: JsonValue?) = apply { + this.xStreamResponse = xStreamResponse + } + + /** Alias for calling [Builder.xStreamResponse] with `xStreamResponse.orElse(null)`. */ + fun xStreamResponse(xStreamResponse: Optional) = + xStreamResponse(xStreamResponse.getOrNull()) + + fun body(body: JsonValue) = apply { this.body = body } + + fun additionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun additionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun putAdditionalHeader(name: String, value: String) = apply { + additionalHeaders.put(name, value) + } + + fun putAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.put(name, values) + } + + fun putAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun putAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun replaceAdditionalHeaders(name: String, value: String) = apply { + additionalHeaders.replace(name, value) + } + + fun replaceAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.replace(name, values) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun removeAdditionalHeaders(name: String) = apply { additionalHeaders.remove(name) } + + fun removeAllAdditionalHeaders(names: Set) = apply { + additionalHeaders.removeAll(names) + } + + fun additionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun additionalQueryParams(additionalQueryParams: Map>) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun putAdditionalQueryParam(key: String, value: String) = apply { + additionalQueryParams.put(key, value) + } + + fun putAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.put(key, values) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun replaceAdditionalQueryParams(key: String, value: String) = apply { + additionalQueryParams.replace(key, value) + } + + fun replaceAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.replace(key, values) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun removeAdditionalQueryParams(key: String) = apply { additionalQueryParams.remove(key) } + + fun removeAllAdditionalQueryParams(keys: Set) = apply { + additionalQueryParams.removeAll(keys) + } + + /** + * Returns an immutable instance of [SessionExtractParams]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): SessionExtractParams = + SessionExtractParams( + id, + xLanguage, + xSdkVersion, + xSentAt, + xStreamResponse, + body, + additionalHeaders.build(), + additionalQueryParams.build(), + ) + } + + fun _body(): JsonValue = body + + fun _pathParam(index: Int): String = + when (index) { + 0 -> id?.toString() ?: "" + else -> "" + } + + override fun _headers(): Headers = Headers.builder().apply { putAll(additionalHeaders) }.build() + + override fun _queryParams(): QueryParams = additionalQueryParams + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is SessionExtractParams && + id == other.id && + xLanguage == other.xLanguage && + xSdkVersion == other.xSdkVersion && + xSentAt == other.xSentAt && + xStreamResponse == other.xStreamResponse && + body == other.body && + additionalHeaders == other.additionalHeaders && + additionalQueryParams == other.additionalQueryParams + } + + override fun hashCode(): Int = + Objects.hash( + id, + xLanguage, + xSdkVersion, + xSentAt, + xStreamResponse, + body, + additionalHeaders, + additionalQueryParams, + ) + + override fun toString() = + "SessionExtractParams{id=$id, xLanguage=$xLanguage, xSdkVersion=$xSdkVersion, xSentAt=$xSentAt, xStreamResponse=$xStreamResponse, body=$body, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" +} diff --git a/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionExtractResponse.kt b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionExtractResponse.kt new file mode 100644 index 0000000..1e08b0f --- /dev/null +++ b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionExtractResponse.kt @@ -0,0 +1,114 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.browserbase.api.models.sessions + +import com.browserbase.api.core.ExcludeMissing +import com.browserbase.api.core.JsonValue +import com.browserbase.api.errors.StagehandInvalidDataException +import com.fasterxml.jackson.annotation.JsonAnyGetter +import com.fasterxml.jackson.annotation.JsonAnySetter +import com.fasterxml.jackson.annotation.JsonCreator +import java.util.Collections +import java.util.Objects + +class SessionExtractResponse +@JsonCreator(mode = JsonCreator.Mode.DISABLED) +private constructor(private val additionalProperties: MutableMap) { + + @JsonCreator private constructor() : this(mutableMapOf()) + + @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 [SessionExtractResponse]. */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [SessionExtractResponse]. */ + class Builder internal constructor() { + + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(sessionExtractResponse: SessionExtractResponse) = apply { + additionalProperties = sessionExtractResponse.additionalProperties.toMutableMap() + } + + 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 [SessionExtractResponse]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): SessionExtractResponse = + SessionExtractResponse(additionalProperties.toMutableMap()) + } + + private var validated: Boolean = false + + fun validate(): SessionExtractResponse = apply { + if (validated) { + return@apply + } + + 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. + */ + @JvmSynthetic internal fun validity(): Int = 0 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is SessionExtractResponse && additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { Objects.hash(additionalProperties) } + + override fun hashCode(): Int = hashCode + + override fun toString() = "SessionExtractResponse{additionalProperties=$additionalProperties}" +} diff --git a/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionNavigateParams.kt b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionNavigateParams.kt new file mode 100644 index 0000000..9f282ab --- /dev/null +++ b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionNavigateParams.kt @@ -0,0 +1,267 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.browserbase.api.models.sessions + +import com.browserbase.api.core.JsonMissing +import com.browserbase.api.core.JsonValue +import com.browserbase.api.core.Params +import com.browserbase.api.core.http.Headers +import com.browserbase.api.core.http.QueryParams +import java.util.Objects +import java.util.Optional +import kotlin.jvm.optionals.getOrNull + +/** Navigates the browser to the specified URL. */ +class SessionNavigateParams +private constructor( + private val id: JsonValue?, + private val xLanguage: JsonValue?, + private val xSdkVersion: JsonValue?, + private val xSentAt: JsonValue?, + private val xStreamResponse: JsonValue?, + private val body: JsonValue, + private val additionalHeaders: Headers, + private val additionalQueryParams: QueryParams, +) : Params { + + fun id(): Optional = Optional.ofNullable(id) + + fun xLanguage(): Optional = Optional.ofNullable(xLanguage) + + fun xSdkVersion(): Optional = Optional.ofNullable(xSdkVersion) + + fun xSentAt(): Optional = Optional.ofNullable(xSentAt) + + fun xStreamResponse(): Optional = Optional.ofNullable(xStreamResponse) + + fun body(): JsonValue = body + + /** Additional headers to send with the request. */ + fun _additionalHeaders(): Headers = additionalHeaders + + /** Additional query param to send with the request. */ + fun _additionalQueryParams(): QueryParams = additionalQueryParams + + fun toBuilder() = Builder().from(this) + + companion object { + + @JvmStatic fun none(): SessionNavigateParams = builder().build() + + /** Returns a mutable builder for constructing an instance of [SessionNavigateParams]. */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [SessionNavigateParams]. */ + class Builder internal constructor() { + + private var id: JsonValue? = null + private var xLanguage: JsonValue? = null + private var xSdkVersion: JsonValue? = null + private var xSentAt: JsonValue? = null + private var xStreamResponse: JsonValue? = null + private var body: JsonValue = JsonMissing.of() + private var additionalHeaders: Headers.Builder = Headers.builder() + private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() + + @JvmSynthetic + internal fun from(sessionNavigateParams: SessionNavigateParams) = apply { + id = sessionNavigateParams.id + xLanguage = sessionNavigateParams.xLanguage + xSdkVersion = sessionNavigateParams.xSdkVersion + xSentAt = sessionNavigateParams.xSentAt + xStreamResponse = sessionNavigateParams.xStreamResponse + body = sessionNavigateParams.body + additionalHeaders = sessionNavigateParams.additionalHeaders.toBuilder() + additionalQueryParams = sessionNavigateParams.additionalQueryParams.toBuilder() + } + + fun id(id: JsonValue?) = apply { this.id = id } + + /** Alias for calling [Builder.id] with `id.orElse(null)`. */ + fun id(id: Optional) = id(id.getOrNull()) + + fun xLanguage(xLanguage: JsonValue?) = apply { this.xLanguage = xLanguage } + + /** Alias for calling [Builder.xLanguage] with `xLanguage.orElse(null)`. */ + fun xLanguage(xLanguage: Optional) = xLanguage(xLanguage.getOrNull()) + + fun xSdkVersion(xSdkVersion: JsonValue?) = apply { this.xSdkVersion = xSdkVersion } + + /** Alias for calling [Builder.xSdkVersion] with `xSdkVersion.orElse(null)`. */ + fun xSdkVersion(xSdkVersion: Optional) = xSdkVersion(xSdkVersion.getOrNull()) + + fun xSentAt(xSentAt: JsonValue?) = apply { this.xSentAt = xSentAt } + + /** Alias for calling [Builder.xSentAt] with `xSentAt.orElse(null)`. */ + fun xSentAt(xSentAt: Optional) = xSentAt(xSentAt.getOrNull()) + + fun xStreamResponse(xStreamResponse: JsonValue?) = apply { + this.xStreamResponse = xStreamResponse + } + + /** Alias for calling [Builder.xStreamResponse] with `xStreamResponse.orElse(null)`. */ + fun xStreamResponse(xStreamResponse: Optional) = + xStreamResponse(xStreamResponse.getOrNull()) + + fun body(body: JsonValue) = apply { this.body = body } + + fun additionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun additionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun putAdditionalHeader(name: String, value: String) = apply { + additionalHeaders.put(name, value) + } + + fun putAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.put(name, values) + } + + fun putAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun putAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun replaceAdditionalHeaders(name: String, value: String) = apply { + additionalHeaders.replace(name, value) + } + + fun replaceAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.replace(name, values) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun removeAdditionalHeaders(name: String) = apply { additionalHeaders.remove(name) } + + fun removeAllAdditionalHeaders(names: Set) = apply { + additionalHeaders.removeAll(names) + } + + fun additionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun additionalQueryParams(additionalQueryParams: Map>) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun putAdditionalQueryParam(key: String, value: String) = apply { + additionalQueryParams.put(key, value) + } + + fun putAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.put(key, values) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun replaceAdditionalQueryParams(key: String, value: String) = apply { + additionalQueryParams.replace(key, value) + } + + fun replaceAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.replace(key, values) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun removeAdditionalQueryParams(key: String) = apply { additionalQueryParams.remove(key) } + + fun removeAllAdditionalQueryParams(keys: Set) = apply { + additionalQueryParams.removeAll(keys) + } + + /** + * Returns an immutable instance of [SessionNavigateParams]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): SessionNavigateParams = + SessionNavigateParams( + id, + xLanguage, + xSdkVersion, + xSentAt, + xStreamResponse, + body, + additionalHeaders.build(), + additionalQueryParams.build(), + ) + } + + fun _body(): JsonValue = body + + fun _pathParam(index: Int): String = + when (index) { + 0 -> id?.toString() ?: "" + else -> "" + } + + override fun _headers(): Headers = Headers.builder().apply { putAll(additionalHeaders) }.build() + + override fun _queryParams(): QueryParams = additionalQueryParams + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is SessionNavigateParams && + id == other.id && + xLanguage == other.xLanguage && + xSdkVersion == other.xSdkVersion && + xSentAt == other.xSentAt && + xStreamResponse == other.xStreamResponse && + body == other.body && + additionalHeaders == other.additionalHeaders && + additionalQueryParams == other.additionalQueryParams + } + + override fun hashCode(): Int = + Objects.hash( + id, + xLanguage, + xSdkVersion, + xSentAt, + xStreamResponse, + body, + additionalHeaders, + additionalQueryParams, + ) + + override fun toString() = + "SessionNavigateParams{id=$id, xLanguage=$xLanguage, xSdkVersion=$xSdkVersion, xSentAt=$xSentAt, xStreamResponse=$xStreamResponse, body=$body, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" +} diff --git a/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionNavigateResponse.kt b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionNavigateResponse.kt new file mode 100644 index 0000000..916d1a2 --- /dev/null +++ b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionNavigateResponse.kt @@ -0,0 +1,115 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.browserbase.api.models.sessions + +import com.browserbase.api.core.ExcludeMissing +import com.browserbase.api.core.JsonValue +import com.browserbase.api.errors.StagehandInvalidDataException +import com.fasterxml.jackson.annotation.JsonAnyGetter +import com.fasterxml.jackson.annotation.JsonAnySetter +import com.fasterxml.jackson.annotation.JsonCreator +import java.util.Collections +import java.util.Objects + +class SessionNavigateResponse +@JsonCreator(mode = JsonCreator.Mode.DISABLED) +private constructor(private val additionalProperties: MutableMap) { + + @JsonCreator private constructor() : this(mutableMapOf()) + + @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 [SessionNavigateResponse]. */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [SessionNavigateResponse]. */ + class Builder internal constructor() { + + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(sessionNavigateResponse: SessionNavigateResponse) = apply { + additionalProperties = sessionNavigateResponse.additionalProperties.toMutableMap() + } + + 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 [SessionNavigateResponse]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): SessionNavigateResponse = + SessionNavigateResponse(additionalProperties.toMutableMap()) + } + + private var validated: Boolean = false + + fun validate(): SessionNavigateResponse = apply { + if (validated) { + return@apply + } + + 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. + */ + @JvmSynthetic internal fun validity(): Int = 0 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is SessionNavigateResponse && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { Objects.hash(additionalProperties) } + + override fun hashCode(): Int = hashCode + + override fun toString() = "SessionNavigateResponse{additionalProperties=$additionalProperties}" +} diff --git a/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionObserveParams.kt b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionObserveParams.kt new file mode 100644 index 0000000..3f4fb2b --- /dev/null +++ b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionObserveParams.kt @@ -0,0 +1,269 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.browserbase.api.models.sessions + +import com.browserbase.api.core.JsonMissing +import com.browserbase.api.core.JsonValue +import com.browserbase.api.core.Params +import com.browserbase.api.core.http.Headers +import com.browserbase.api.core.http.QueryParams +import java.util.Objects +import java.util.Optional +import kotlin.jvm.optionals.getOrNull + +/** + * Identifies and returns available actions on the current page that match the given instruction. + */ +class SessionObserveParams +private constructor( + private val id: JsonValue?, + private val xLanguage: JsonValue?, + private val xSdkVersion: JsonValue?, + private val xSentAt: JsonValue?, + private val xStreamResponse: JsonValue?, + private val body: JsonValue, + private val additionalHeaders: Headers, + private val additionalQueryParams: QueryParams, +) : Params { + + fun id(): Optional = Optional.ofNullable(id) + + fun xLanguage(): Optional = Optional.ofNullable(xLanguage) + + fun xSdkVersion(): Optional = Optional.ofNullable(xSdkVersion) + + fun xSentAt(): Optional = Optional.ofNullable(xSentAt) + + fun xStreamResponse(): Optional = Optional.ofNullable(xStreamResponse) + + fun body(): JsonValue = body + + /** Additional headers to send with the request. */ + fun _additionalHeaders(): Headers = additionalHeaders + + /** Additional query param to send with the request. */ + fun _additionalQueryParams(): QueryParams = additionalQueryParams + + fun toBuilder() = Builder().from(this) + + companion object { + + @JvmStatic fun none(): SessionObserveParams = builder().build() + + /** Returns a mutable builder for constructing an instance of [SessionObserveParams]. */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [SessionObserveParams]. */ + class Builder internal constructor() { + + private var id: JsonValue? = null + private var xLanguage: JsonValue? = null + private var xSdkVersion: JsonValue? = null + private var xSentAt: JsonValue? = null + private var xStreamResponse: JsonValue? = null + private var body: JsonValue = JsonMissing.of() + private var additionalHeaders: Headers.Builder = Headers.builder() + private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() + + @JvmSynthetic + internal fun from(sessionObserveParams: SessionObserveParams) = apply { + id = sessionObserveParams.id + xLanguage = sessionObserveParams.xLanguage + xSdkVersion = sessionObserveParams.xSdkVersion + xSentAt = sessionObserveParams.xSentAt + xStreamResponse = sessionObserveParams.xStreamResponse + body = sessionObserveParams.body + additionalHeaders = sessionObserveParams.additionalHeaders.toBuilder() + additionalQueryParams = sessionObserveParams.additionalQueryParams.toBuilder() + } + + fun id(id: JsonValue?) = apply { this.id = id } + + /** Alias for calling [Builder.id] with `id.orElse(null)`. */ + fun id(id: Optional) = id(id.getOrNull()) + + fun xLanguage(xLanguage: JsonValue?) = apply { this.xLanguage = xLanguage } + + /** Alias for calling [Builder.xLanguage] with `xLanguage.orElse(null)`. */ + fun xLanguage(xLanguage: Optional) = xLanguage(xLanguage.getOrNull()) + + fun xSdkVersion(xSdkVersion: JsonValue?) = apply { this.xSdkVersion = xSdkVersion } + + /** Alias for calling [Builder.xSdkVersion] with `xSdkVersion.orElse(null)`. */ + fun xSdkVersion(xSdkVersion: Optional) = xSdkVersion(xSdkVersion.getOrNull()) + + fun xSentAt(xSentAt: JsonValue?) = apply { this.xSentAt = xSentAt } + + /** Alias for calling [Builder.xSentAt] with `xSentAt.orElse(null)`. */ + fun xSentAt(xSentAt: Optional) = xSentAt(xSentAt.getOrNull()) + + fun xStreamResponse(xStreamResponse: JsonValue?) = apply { + this.xStreamResponse = xStreamResponse + } + + /** Alias for calling [Builder.xStreamResponse] with `xStreamResponse.orElse(null)`. */ + fun xStreamResponse(xStreamResponse: Optional) = + xStreamResponse(xStreamResponse.getOrNull()) + + fun body(body: JsonValue) = apply { this.body = body } + + fun additionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun additionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun putAdditionalHeader(name: String, value: String) = apply { + additionalHeaders.put(name, value) + } + + fun putAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.put(name, values) + } + + fun putAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun putAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun replaceAdditionalHeaders(name: String, value: String) = apply { + additionalHeaders.replace(name, value) + } + + fun replaceAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.replace(name, values) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun removeAdditionalHeaders(name: String) = apply { additionalHeaders.remove(name) } + + fun removeAllAdditionalHeaders(names: Set) = apply { + additionalHeaders.removeAll(names) + } + + fun additionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun additionalQueryParams(additionalQueryParams: Map>) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun putAdditionalQueryParam(key: String, value: String) = apply { + additionalQueryParams.put(key, value) + } + + fun putAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.put(key, values) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun replaceAdditionalQueryParams(key: String, value: String) = apply { + additionalQueryParams.replace(key, value) + } + + fun replaceAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.replace(key, values) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun removeAdditionalQueryParams(key: String) = apply { additionalQueryParams.remove(key) } + + fun removeAllAdditionalQueryParams(keys: Set) = apply { + additionalQueryParams.removeAll(keys) + } + + /** + * Returns an immutable instance of [SessionObserveParams]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): SessionObserveParams = + SessionObserveParams( + id, + xLanguage, + xSdkVersion, + xSentAt, + xStreamResponse, + body, + additionalHeaders.build(), + additionalQueryParams.build(), + ) + } + + fun _body(): JsonValue = body + + fun _pathParam(index: Int): String = + when (index) { + 0 -> id?.toString() ?: "" + else -> "" + } + + override fun _headers(): Headers = Headers.builder().apply { putAll(additionalHeaders) }.build() + + override fun _queryParams(): QueryParams = additionalQueryParams + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is SessionObserveParams && + id == other.id && + xLanguage == other.xLanguage && + xSdkVersion == other.xSdkVersion && + xSentAt == other.xSentAt && + xStreamResponse == other.xStreamResponse && + body == other.body && + additionalHeaders == other.additionalHeaders && + additionalQueryParams == other.additionalQueryParams + } + + override fun hashCode(): Int = + Objects.hash( + id, + xLanguage, + xSdkVersion, + xSentAt, + xStreamResponse, + body, + additionalHeaders, + additionalQueryParams, + ) + + override fun toString() = + "SessionObserveParams{id=$id, xLanguage=$xLanguage, xSdkVersion=$xSdkVersion, xSentAt=$xSentAt, xStreamResponse=$xStreamResponse, body=$body, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" +} diff --git a/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionObserveResponse.kt b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionObserveResponse.kt new file mode 100644 index 0000000..a27fc10 --- /dev/null +++ b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionObserveResponse.kt @@ -0,0 +1,114 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.browserbase.api.models.sessions + +import com.browserbase.api.core.ExcludeMissing +import com.browserbase.api.core.JsonValue +import com.browserbase.api.errors.StagehandInvalidDataException +import com.fasterxml.jackson.annotation.JsonAnyGetter +import com.fasterxml.jackson.annotation.JsonAnySetter +import com.fasterxml.jackson.annotation.JsonCreator +import java.util.Collections +import java.util.Objects + +class SessionObserveResponse +@JsonCreator(mode = JsonCreator.Mode.DISABLED) +private constructor(private val additionalProperties: MutableMap) { + + @JsonCreator private constructor() : this(mutableMapOf()) + + @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 [SessionObserveResponse]. */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [SessionObserveResponse]. */ + class Builder internal constructor() { + + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(sessionObserveResponse: SessionObserveResponse) = apply { + additionalProperties = sessionObserveResponse.additionalProperties.toMutableMap() + } + + 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 [SessionObserveResponse]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): SessionObserveResponse = + SessionObserveResponse(additionalProperties.toMutableMap()) + } + + private var validated: Boolean = false + + fun validate(): SessionObserveResponse = apply { + if (validated) { + return@apply + } + + 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. + */ + @JvmSynthetic internal fun validity(): Int = 0 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is SessionObserveResponse && additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { Objects.hash(additionalProperties) } + + override fun hashCode(): Int = hashCode + + override fun toString() = "SessionObserveResponse{additionalProperties=$additionalProperties}" +} diff --git a/stagehand-java-core/src/main/kotlin/com/browserbase/api/services/async/SessionServiceAsync.kt b/stagehand-java-core/src/main/kotlin/com/browserbase/api/services/async/SessionServiceAsync.kt index d481fec..435bf27 100644 --- a/stagehand-java-core/src/main/kotlin/com/browserbase/api/services/async/SessionServiceAsync.kt +++ b/stagehand-java-core/src/main/kotlin/com/browserbase/api/services/async/SessionServiceAsync.kt @@ -3,8 +3,21 @@ package com.browserbase.api.services.async import com.browserbase.api.core.ClientOptions +import com.browserbase.api.core.JsonValue import com.browserbase.api.core.RequestOptions import com.browserbase.api.core.http.HttpResponseFor +import com.browserbase.api.models.sessions.SessionActParams +import com.browserbase.api.models.sessions.SessionActResponse +import com.browserbase.api.models.sessions.SessionEndParams +import com.browserbase.api.models.sessions.SessionEndResponse +import com.browserbase.api.models.sessions.SessionExecuteAgentParams +import com.browserbase.api.models.sessions.SessionExecuteAgentResponse +import com.browserbase.api.models.sessions.SessionExtractParams +import com.browserbase.api.models.sessions.SessionExtractResponse +import com.browserbase.api.models.sessions.SessionNavigateParams +import com.browserbase.api.models.sessions.SessionNavigateResponse +import com.browserbase.api.models.sessions.SessionObserveParams +import com.browserbase.api.models.sessions.SessionObserveResponse import com.browserbase.api.models.sessions.SessionStartParams import com.browserbase.api.models.sessions.SessionStartResponse import java.util.concurrent.CompletableFuture @@ -24,6 +37,215 @@ interface SessionServiceAsync { */ fun withOptions(modifier: Consumer): SessionServiceAsync + /** + * Executes a browser action using natural language instructions or a predefined Action object. + */ + fun act(id: JsonValue): CompletableFuture = act(id, SessionActParams.none()) + + /** @see act */ + fun act( + id: JsonValue, + params: SessionActParams = SessionActParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture = + act(params.toBuilder().id(id).build(), requestOptions) + + /** @see act */ + fun act( + id: JsonValue, + params: SessionActParams = SessionActParams.none(), + ): CompletableFuture = act(id, params, RequestOptions.none()) + + /** @see act */ + fun act( + params: SessionActParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture + + /** @see act */ + fun act(params: SessionActParams): CompletableFuture = + act(params, RequestOptions.none()) + + /** @see act */ + fun act(id: JsonValue, requestOptions: RequestOptions): CompletableFuture = + act(id, SessionActParams.none(), requestOptions) + + /** Terminates the browser session and releases all associated resources. */ + fun end(id: JsonValue): CompletableFuture = end(id, SessionEndParams.none()) + + /** @see end */ + fun end( + id: JsonValue, + params: SessionEndParams = SessionEndParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture = + end(params.toBuilder().id(id).build(), requestOptions) + + /** @see end */ + fun end( + id: JsonValue, + params: SessionEndParams = SessionEndParams.none(), + ): CompletableFuture = end(id, params, RequestOptions.none()) + + /** @see end */ + fun end( + params: SessionEndParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture + + /** @see end */ + fun end(params: SessionEndParams): CompletableFuture = + end(params, RequestOptions.none()) + + /** @see end */ + fun end(id: JsonValue, requestOptions: RequestOptions): CompletableFuture = + end(id, SessionEndParams.none(), requestOptions) + + /** Runs an autonomous AI agent that can perform complex multi-step browser tasks. */ + fun executeAgent(id: JsonValue): CompletableFuture = + executeAgent(id, SessionExecuteAgentParams.none()) + + /** @see executeAgent */ + fun executeAgent( + id: JsonValue, + params: SessionExecuteAgentParams = SessionExecuteAgentParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture = + executeAgent(params.toBuilder().id(id).build(), requestOptions) + + /** @see executeAgent */ + fun executeAgent( + id: JsonValue, + params: SessionExecuteAgentParams = SessionExecuteAgentParams.none(), + ): CompletableFuture = + executeAgent(id, params, RequestOptions.none()) + + /** @see executeAgent */ + fun executeAgent( + params: SessionExecuteAgentParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture + + /** @see executeAgent */ + fun executeAgent( + params: SessionExecuteAgentParams + ): CompletableFuture = executeAgent(params, RequestOptions.none()) + + /** @see executeAgent */ + fun executeAgent( + id: JsonValue, + requestOptions: RequestOptions, + ): CompletableFuture = + executeAgent(id, SessionExecuteAgentParams.none(), requestOptions) + + /** Extracts structured data from the current page using AI-powered analysis. */ + fun extract(id: JsonValue): CompletableFuture = + extract(id, SessionExtractParams.none()) + + /** @see extract */ + fun extract( + id: JsonValue, + params: SessionExtractParams = SessionExtractParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture = + extract(params.toBuilder().id(id).build(), requestOptions) + + /** @see extract */ + fun extract( + id: JsonValue, + params: SessionExtractParams = SessionExtractParams.none(), + ): CompletableFuture = extract(id, params, RequestOptions.none()) + + /** @see extract */ + fun extract( + params: SessionExtractParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture + + /** @see extract */ + fun extract(params: SessionExtractParams): CompletableFuture = + extract(params, RequestOptions.none()) + + /** @see extract */ + fun extract( + id: JsonValue, + requestOptions: RequestOptions, + ): CompletableFuture = + extract(id, SessionExtractParams.none(), requestOptions) + + /** Navigates the browser to the specified URL. */ + fun navigate(id: JsonValue): CompletableFuture = + navigate(id, SessionNavigateParams.none()) + + /** @see navigate */ + fun navigate( + id: JsonValue, + params: SessionNavigateParams = SessionNavigateParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture = + navigate(params.toBuilder().id(id).build(), requestOptions) + + /** @see navigate */ + fun navigate( + id: JsonValue, + params: SessionNavigateParams = SessionNavigateParams.none(), + ): CompletableFuture = navigate(id, params, RequestOptions.none()) + + /** @see navigate */ + fun navigate( + params: SessionNavigateParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture + + /** @see navigate */ + fun navigate(params: SessionNavigateParams): CompletableFuture = + navigate(params, RequestOptions.none()) + + /** @see navigate */ + fun navigate( + id: JsonValue, + requestOptions: RequestOptions, + ): CompletableFuture = + navigate(id, SessionNavigateParams.none(), requestOptions) + + /** + * Identifies and returns available actions on the current page that match the given + * instruction. + */ + fun observe(id: JsonValue): CompletableFuture = + observe(id, SessionObserveParams.none()) + + /** @see observe */ + fun observe( + id: JsonValue, + params: SessionObserveParams = SessionObserveParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture = + observe(params.toBuilder().id(id).build(), requestOptions) + + /** @see observe */ + fun observe( + id: JsonValue, + params: SessionObserveParams = SessionObserveParams.none(), + ): CompletableFuture = observe(id, params, RequestOptions.none()) + + /** @see observe */ + fun observe( + params: SessionObserveParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture + + /** @see observe */ + fun observe(params: SessionObserveParams): CompletableFuture = + observe(params, RequestOptions.none()) + + /** @see observe */ + fun observe( + id: JsonValue, + requestOptions: RequestOptions, + ): CompletableFuture = + observe(id, SessionObserveParams.none(), requestOptions) + /** * Creates a new browser session with the specified configuration. Returns a session ID used for * all subsequent operations. @@ -59,6 +281,250 @@ interface SessionServiceAsync { modifier: Consumer ): SessionServiceAsync.WithRawResponse + /** + * Returns a raw HTTP response for `post /sessions/{id}/act`, but is otherwise the same as + * [SessionServiceAsync.act]. + */ + fun act(id: JsonValue): CompletableFuture> = + act(id, SessionActParams.none()) + + /** @see act */ + fun act( + id: JsonValue, + params: SessionActParams = SessionActParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture> = + act(params.toBuilder().id(id).build(), requestOptions) + + /** @see act */ + fun act( + id: JsonValue, + params: SessionActParams = SessionActParams.none(), + ): CompletableFuture> = + act(id, params, RequestOptions.none()) + + /** @see act */ + fun act( + params: SessionActParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture> + + /** @see act */ + fun act(params: SessionActParams): CompletableFuture> = + act(params, RequestOptions.none()) + + /** @see act */ + fun act( + id: JsonValue, + requestOptions: RequestOptions, + ): CompletableFuture> = + act(id, SessionActParams.none(), requestOptions) + + /** + * Returns a raw HTTP response for `post /sessions/{id}/end`, but is otherwise the same as + * [SessionServiceAsync.end]. + */ + fun end(id: JsonValue): CompletableFuture> = + end(id, SessionEndParams.none()) + + /** @see end */ + fun end( + id: JsonValue, + params: SessionEndParams = SessionEndParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture> = + end(params.toBuilder().id(id).build(), requestOptions) + + /** @see end */ + fun end( + id: JsonValue, + params: SessionEndParams = SessionEndParams.none(), + ): CompletableFuture> = + end(id, params, RequestOptions.none()) + + /** @see end */ + fun end( + params: SessionEndParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture> + + /** @see end */ + fun end(params: SessionEndParams): CompletableFuture> = + end(params, RequestOptions.none()) + + /** @see end */ + fun end( + id: JsonValue, + requestOptions: RequestOptions, + ): CompletableFuture> = + end(id, SessionEndParams.none(), requestOptions) + + /** + * Returns a raw HTTP response for `post /sessions/{id}/agentExecute`, but is otherwise the + * same as [SessionServiceAsync.executeAgent]. + */ + fun executeAgent( + id: JsonValue + ): CompletableFuture> = + executeAgent(id, SessionExecuteAgentParams.none()) + + /** @see executeAgent */ + fun executeAgent( + id: JsonValue, + params: SessionExecuteAgentParams = SessionExecuteAgentParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture> = + executeAgent(params.toBuilder().id(id).build(), requestOptions) + + /** @see executeAgent */ + fun executeAgent( + id: JsonValue, + params: SessionExecuteAgentParams = SessionExecuteAgentParams.none(), + ): CompletableFuture> = + executeAgent(id, params, RequestOptions.none()) + + /** @see executeAgent */ + fun executeAgent( + params: SessionExecuteAgentParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture> + + /** @see executeAgent */ + fun executeAgent( + params: SessionExecuteAgentParams + ): CompletableFuture> = + executeAgent(params, RequestOptions.none()) + + /** @see executeAgent */ + fun executeAgent( + id: JsonValue, + requestOptions: RequestOptions, + ): CompletableFuture> = + executeAgent(id, SessionExecuteAgentParams.none(), requestOptions) + + /** + * Returns a raw HTTP response for `post /sessions/{id}/extract`, but is otherwise the same + * as [SessionServiceAsync.extract]. + */ + fun extract(id: JsonValue): CompletableFuture> = + extract(id, SessionExtractParams.none()) + + /** @see extract */ + fun extract( + id: JsonValue, + params: SessionExtractParams = SessionExtractParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture> = + extract(params.toBuilder().id(id).build(), requestOptions) + + /** @see extract */ + fun extract( + id: JsonValue, + params: SessionExtractParams = SessionExtractParams.none(), + ): CompletableFuture> = + extract(id, params, RequestOptions.none()) + + /** @see extract */ + fun extract( + params: SessionExtractParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture> + + /** @see extract */ + fun extract( + params: SessionExtractParams + ): CompletableFuture> = + extract(params, RequestOptions.none()) + + /** @see extract */ + fun extract( + id: JsonValue, + requestOptions: RequestOptions, + ): CompletableFuture> = + extract(id, SessionExtractParams.none(), requestOptions) + + /** + * Returns a raw HTTP response for `post /sessions/{id}/navigate`, but is otherwise the same + * as [SessionServiceAsync.navigate]. + */ + fun navigate(id: JsonValue): CompletableFuture> = + navigate(id, SessionNavigateParams.none()) + + /** @see navigate */ + fun navigate( + id: JsonValue, + params: SessionNavigateParams = SessionNavigateParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture> = + navigate(params.toBuilder().id(id).build(), requestOptions) + + /** @see navigate */ + fun navigate( + id: JsonValue, + params: SessionNavigateParams = SessionNavigateParams.none(), + ): CompletableFuture> = + navigate(id, params, RequestOptions.none()) + + /** @see navigate */ + fun navigate( + params: SessionNavigateParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture> + + /** @see navigate */ + fun navigate( + params: SessionNavigateParams + ): CompletableFuture> = + navigate(params, RequestOptions.none()) + + /** @see navigate */ + fun navigate( + id: JsonValue, + requestOptions: RequestOptions, + ): CompletableFuture> = + navigate(id, SessionNavigateParams.none(), requestOptions) + + /** + * Returns a raw HTTP response for `post /sessions/{id}/observe`, but is otherwise the same + * as [SessionServiceAsync.observe]. + */ + fun observe(id: JsonValue): CompletableFuture> = + observe(id, SessionObserveParams.none()) + + /** @see observe */ + fun observe( + id: JsonValue, + params: SessionObserveParams = SessionObserveParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture> = + observe(params.toBuilder().id(id).build(), requestOptions) + + /** @see observe */ + fun observe( + id: JsonValue, + params: SessionObserveParams = SessionObserveParams.none(), + ): CompletableFuture> = + observe(id, params, RequestOptions.none()) + + /** @see observe */ + fun observe( + params: SessionObserveParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture> + + /** @see observe */ + fun observe( + params: SessionObserveParams + ): CompletableFuture> = + observe(params, RequestOptions.none()) + + /** @see observe */ + fun observe( + id: JsonValue, + requestOptions: RequestOptions, + ): CompletableFuture> = + observe(id, SessionObserveParams.none(), requestOptions) + /** * Returns a raw HTTP response for `post /sessions/start`, but is otherwise the same as * [SessionServiceAsync.start]. diff --git a/stagehand-java-core/src/main/kotlin/com/browserbase/api/services/async/SessionServiceAsyncImpl.kt b/stagehand-java-core/src/main/kotlin/com/browserbase/api/services/async/SessionServiceAsyncImpl.kt index 056c59c..7746896 100644 --- a/stagehand-java-core/src/main/kotlin/com/browserbase/api/services/async/SessionServiceAsyncImpl.kt +++ b/stagehand-java-core/src/main/kotlin/com/browserbase/api/services/async/SessionServiceAsyncImpl.kt @@ -15,6 +15,18 @@ import com.browserbase.api.core.http.HttpResponseFor import com.browserbase.api.core.http.json import com.browserbase.api.core.http.parseable import com.browserbase.api.core.prepareAsync +import com.browserbase.api.models.sessions.SessionActParams +import com.browserbase.api.models.sessions.SessionActResponse +import com.browserbase.api.models.sessions.SessionEndParams +import com.browserbase.api.models.sessions.SessionEndResponse +import com.browserbase.api.models.sessions.SessionExecuteAgentParams +import com.browserbase.api.models.sessions.SessionExecuteAgentResponse +import com.browserbase.api.models.sessions.SessionExtractParams +import com.browserbase.api.models.sessions.SessionExtractResponse +import com.browserbase.api.models.sessions.SessionNavigateParams +import com.browserbase.api.models.sessions.SessionNavigateResponse +import com.browserbase.api.models.sessions.SessionObserveParams +import com.browserbase.api.models.sessions.SessionObserveResponse import com.browserbase.api.models.sessions.SessionStartParams import com.browserbase.api.models.sessions.SessionStartResponse import java.util.concurrent.CompletableFuture @@ -32,6 +44,48 @@ class SessionServiceAsyncImpl internal constructor(private val clientOptions: Cl override fun withOptions(modifier: Consumer): SessionServiceAsync = SessionServiceAsyncImpl(clientOptions.toBuilder().apply(modifier::accept).build()) + override fun act( + params: SessionActParams, + requestOptions: RequestOptions, + ): CompletableFuture = + // post /sessions/{id}/act + withRawResponse().act(params, requestOptions).thenApply { it.parse() } + + override fun end( + params: SessionEndParams, + requestOptions: RequestOptions, + ): CompletableFuture = + // post /sessions/{id}/end + withRawResponse().end(params, requestOptions).thenApply { it.parse() } + + override fun executeAgent( + params: SessionExecuteAgentParams, + requestOptions: RequestOptions, + ): CompletableFuture = + // post /sessions/{id}/agentExecute + withRawResponse().executeAgent(params, requestOptions).thenApply { it.parse() } + + override fun extract( + params: SessionExtractParams, + requestOptions: RequestOptions, + ): CompletableFuture = + // post /sessions/{id}/extract + withRawResponse().extract(params, requestOptions).thenApply { it.parse() } + + override fun navigate( + params: SessionNavigateParams, + requestOptions: RequestOptions, + ): CompletableFuture = + // post /sessions/{id}/navigate + withRawResponse().navigate(params, requestOptions).thenApply { it.parse() } + + override fun observe( + params: SessionObserveParams, + requestOptions: RequestOptions, + ): CompletableFuture = + // post /sessions/{id}/observe + withRawResponse().observe(params, requestOptions).thenApply { it.parse() } + override fun start( params: SessionStartParams, requestOptions: RequestOptions, @@ -52,6 +106,192 @@ class SessionServiceAsyncImpl internal constructor(private val clientOptions: Cl clientOptions.toBuilder().apply(modifier::accept).build() ) + private val actHandler: Handler = + jsonHandler(clientOptions.jsonMapper) + + override fun act( + params: SessionActParams, + requestOptions: RequestOptions, + ): CompletableFuture> { + val request = + HttpRequest.builder() + .method(HttpMethod.POST) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("sessions", params._pathParam(0), "act") + .body(json(clientOptions.jsonMapper, params._body())) + .build() + .prepareAsync(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + return request + .thenComposeAsync { clientOptions.httpClient.executeAsync(it, requestOptions) } + .thenApply { response -> + errorHandler.handle(response).parseable { + response + .use { actHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } + } + + private val endHandler: Handler = + jsonHandler(clientOptions.jsonMapper) + + override fun end( + params: SessionEndParams, + requestOptions: RequestOptions, + ): CompletableFuture> { + val request = + HttpRequest.builder() + .method(HttpMethod.POST) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("sessions", params._pathParam(0), "end") + .apply { params._body().ifPresent { body(json(clientOptions.jsonMapper, it)) } } + .build() + .prepareAsync(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + return request + .thenComposeAsync { clientOptions.httpClient.executeAsync(it, requestOptions) } + .thenApply { response -> + errorHandler.handle(response).parseable { + response + .use { endHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } + } + + private val executeAgentHandler: Handler = + jsonHandler(clientOptions.jsonMapper) + + override fun executeAgent( + params: SessionExecuteAgentParams, + requestOptions: RequestOptions, + ): CompletableFuture> { + val request = + HttpRequest.builder() + .method(HttpMethod.POST) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("sessions", params._pathParam(0), "agentExecute") + .body(json(clientOptions.jsonMapper, params._body())) + .build() + .prepareAsync(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + return request + .thenComposeAsync { clientOptions.httpClient.executeAsync(it, requestOptions) } + .thenApply { response -> + errorHandler.handle(response).parseable { + response + .use { executeAgentHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } + } + + private val extractHandler: Handler = + jsonHandler(clientOptions.jsonMapper) + + override fun extract( + params: SessionExtractParams, + requestOptions: RequestOptions, + ): CompletableFuture> { + val request = + HttpRequest.builder() + .method(HttpMethod.POST) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("sessions", params._pathParam(0), "extract") + .body(json(clientOptions.jsonMapper, params._body())) + .build() + .prepareAsync(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + return request + .thenComposeAsync { clientOptions.httpClient.executeAsync(it, requestOptions) } + .thenApply { response -> + errorHandler.handle(response).parseable { + response + .use { extractHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } + } + + private val navigateHandler: Handler = + jsonHandler(clientOptions.jsonMapper) + + override fun navigate( + params: SessionNavigateParams, + requestOptions: RequestOptions, + ): CompletableFuture> { + val request = + HttpRequest.builder() + .method(HttpMethod.POST) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("sessions", params._pathParam(0), "navigate") + .body(json(clientOptions.jsonMapper, params._body())) + .build() + .prepareAsync(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + return request + .thenComposeAsync { clientOptions.httpClient.executeAsync(it, requestOptions) } + .thenApply { response -> + errorHandler.handle(response).parseable { + response + .use { navigateHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } + } + + private val observeHandler: Handler = + jsonHandler(clientOptions.jsonMapper) + + override fun observe( + params: SessionObserveParams, + requestOptions: RequestOptions, + ): CompletableFuture> { + val request = + HttpRequest.builder() + .method(HttpMethod.POST) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("sessions", params._pathParam(0), "observe") + .body(json(clientOptions.jsonMapper, params._body())) + .build() + .prepareAsync(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + return request + .thenComposeAsync { clientOptions.httpClient.executeAsync(it, requestOptions) } + .thenApply { response -> + errorHandler.handle(response).parseable { + response + .use { observeHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } + } + private val startHandler: Handler = jsonHandler(clientOptions.jsonMapper) diff --git a/stagehand-java-core/src/main/kotlin/com/browserbase/api/services/blocking/SessionService.kt b/stagehand-java-core/src/main/kotlin/com/browserbase/api/services/blocking/SessionService.kt index ddd7ad3..f29cc14 100644 --- a/stagehand-java-core/src/main/kotlin/com/browserbase/api/services/blocking/SessionService.kt +++ b/stagehand-java-core/src/main/kotlin/com/browserbase/api/services/blocking/SessionService.kt @@ -3,8 +3,21 @@ package com.browserbase.api.services.blocking import com.browserbase.api.core.ClientOptions +import com.browserbase.api.core.JsonValue import com.browserbase.api.core.RequestOptions import com.browserbase.api.core.http.HttpResponseFor +import com.browserbase.api.models.sessions.SessionActParams +import com.browserbase.api.models.sessions.SessionActResponse +import com.browserbase.api.models.sessions.SessionEndParams +import com.browserbase.api.models.sessions.SessionEndResponse +import com.browserbase.api.models.sessions.SessionExecuteAgentParams +import com.browserbase.api.models.sessions.SessionExecuteAgentResponse +import com.browserbase.api.models.sessions.SessionExtractParams +import com.browserbase.api.models.sessions.SessionExtractResponse +import com.browserbase.api.models.sessions.SessionNavigateParams +import com.browserbase.api.models.sessions.SessionNavigateResponse +import com.browserbase.api.models.sessions.SessionObserveParams +import com.browserbase.api.models.sessions.SessionObserveResponse import com.browserbase.api.models.sessions.SessionStartParams import com.browserbase.api.models.sessions.SessionStartResponse import com.google.errorprone.annotations.MustBeClosed @@ -24,6 +37,187 @@ interface SessionService { */ fun withOptions(modifier: Consumer): SessionService + /** + * Executes a browser action using natural language instructions or a predefined Action object. + */ + fun act(id: JsonValue): SessionActResponse = act(id, SessionActParams.none()) + + /** @see act */ + fun act( + id: JsonValue, + params: SessionActParams = SessionActParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): SessionActResponse = act(params.toBuilder().id(id).build(), requestOptions) + + /** @see act */ + fun act(id: JsonValue, params: SessionActParams = SessionActParams.none()): SessionActResponse = + act(id, params, RequestOptions.none()) + + /** @see act */ + fun act( + params: SessionActParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): SessionActResponse + + /** @see act */ + fun act(params: SessionActParams): SessionActResponse = act(params, RequestOptions.none()) + + /** @see act */ + fun act(id: JsonValue, requestOptions: RequestOptions): SessionActResponse = + act(id, SessionActParams.none(), requestOptions) + + /** Terminates the browser session and releases all associated resources. */ + fun end(id: JsonValue): SessionEndResponse = end(id, SessionEndParams.none()) + + /** @see end */ + fun end( + id: JsonValue, + params: SessionEndParams = SessionEndParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): SessionEndResponse = end(params.toBuilder().id(id).build(), requestOptions) + + /** @see end */ + fun end(id: JsonValue, params: SessionEndParams = SessionEndParams.none()): SessionEndResponse = + end(id, params, RequestOptions.none()) + + /** @see end */ + fun end( + params: SessionEndParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): SessionEndResponse + + /** @see end */ + fun end(params: SessionEndParams): SessionEndResponse = end(params, RequestOptions.none()) + + /** @see end */ + fun end(id: JsonValue, requestOptions: RequestOptions): SessionEndResponse = + end(id, SessionEndParams.none(), requestOptions) + + /** Runs an autonomous AI agent that can perform complex multi-step browser tasks. */ + fun executeAgent(id: JsonValue): SessionExecuteAgentResponse = + executeAgent(id, SessionExecuteAgentParams.none()) + + /** @see executeAgent */ + fun executeAgent( + id: JsonValue, + params: SessionExecuteAgentParams = SessionExecuteAgentParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): SessionExecuteAgentResponse = executeAgent(params.toBuilder().id(id).build(), requestOptions) + + /** @see executeAgent */ + fun executeAgent( + id: JsonValue, + params: SessionExecuteAgentParams = SessionExecuteAgentParams.none(), + ): SessionExecuteAgentResponse = executeAgent(id, params, RequestOptions.none()) + + /** @see executeAgent */ + fun executeAgent( + params: SessionExecuteAgentParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): SessionExecuteAgentResponse + + /** @see executeAgent */ + fun executeAgent(params: SessionExecuteAgentParams): SessionExecuteAgentResponse = + executeAgent(params, RequestOptions.none()) + + /** @see executeAgent */ + fun executeAgent(id: JsonValue, requestOptions: RequestOptions): SessionExecuteAgentResponse = + executeAgent(id, SessionExecuteAgentParams.none(), requestOptions) + + /** Extracts structured data from the current page using AI-powered analysis. */ + fun extract(id: JsonValue): SessionExtractResponse = extract(id, SessionExtractParams.none()) + + /** @see extract */ + fun extract( + id: JsonValue, + params: SessionExtractParams = SessionExtractParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): SessionExtractResponse = extract(params.toBuilder().id(id).build(), requestOptions) + + /** @see extract */ + fun extract( + id: JsonValue, + params: SessionExtractParams = SessionExtractParams.none(), + ): SessionExtractResponse = extract(id, params, RequestOptions.none()) + + /** @see extract */ + fun extract( + params: SessionExtractParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): SessionExtractResponse + + /** @see extract */ + fun extract(params: SessionExtractParams): SessionExtractResponse = + extract(params, RequestOptions.none()) + + /** @see extract */ + fun extract(id: JsonValue, requestOptions: RequestOptions): SessionExtractResponse = + extract(id, SessionExtractParams.none(), requestOptions) + + /** Navigates the browser to the specified URL. */ + fun navigate(id: JsonValue): SessionNavigateResponse = + navigate(id, SessionNavigateParams.none()) + + /** @see navigate */ + fun navigate( + id: JsonValue, + params: SessionNavigateParams = SessionNavigateParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): SessionNavigateResponse = navigate(params.toBuilder().id(id).build(), requestOptions) + + /** @see navigate */ + fun navigate( + id: JsonValue, + params: SessionNavigateParams = SessionNavigateParams.none(), + ): SessionNavigateResponse = navigate(id, params, RequestOptions.none()) + + /** @see navigate */ + fun navigate( + params: SessionNavigateParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): SessionNavigateResponse + + /** @see navigate */ + fun navigate(params: SessionNavigateParams): SessionNavigateResponse = + navigate(params, RequestOptions.none()) + + /** @see navigate */ + fun navigate(id: JsonValue, requestOptions: RequestOptions): SessionNavigateResponse = + navigate(id, SessionNavigateParams.none(), requestOptions) + + /** + * Identifies and returns available actions on the current page that match the given + * instruction. + */ + fun observe(id: JsonValue): SessionObserveResponse = observe(id, SessionObserveParams.none()) + + /** @see observe */ + fun observe( + id: JsonValue, + params: SessionObserveParams = SessionObserveParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): SessionObserveResponse = observe(params.toBuilder().id(id).build(), requestOptions) + + /** @see observe */ + fun observe( + id: JsonValue, + params: SessionObserveParams = SessionObserveParams.none(), + ): SessionObserveResponse = observe(id, params, RequestOptions.none()) + + /** @see observe */ + fun observe( + params: SessionObserveParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): SessionObserveResponse + + /** @see observe */ + fun observe(params: SessionObserveParams): SessionObserveResponse = + observe(params, RequestOptions.none()) + + /** @see observe */ + fun observe(id: JsonValue, requestOptions: RequestOptions): SessionObserveResponse = + observe(id, SessionObserveParams.none(), requestOptions) + /** * Creates a new browser session with the specified configuration. Returns a session ID used for * all subsequent operations. @@ -54,6 +248,271 @@ interface SessionService { */ fun withOptions(modifier: Consumer): SessionService.WithRawResponse + /** + * Returns a raw HTTP response for `post /sessions/{id}/act`, but is otherwise the same as + * [SessionService.act]. + */ + @MustBeClosed + fun act(id: JsonValue): HttpResponseFor = + act(id, SessionActParams.none()) + + /** @see act */ + @MustBeClosed + fun act( + id: JsonValue, + params: SessionActParams = SessionActParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor = + act(params.toBuilder().id(id).build(), requestOptions) + + /** @see act */ + @MustBeClosed + fun act( + id: JsonValue, + params: SessionActParams = SessionActParams.none(), + ): HttpResponseFor = act(id, params, RequestOptions.none()) + + /** @see act */ + @MustBeClosed + fun act( + params: SessionActParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor + + /** @see act */ + @MustBeClosed + fun act(params: SessionActParams): HttpResponseFor = + act(params, RequestOptions.none()) + + /** @see act */ + @MustBeClosed + fun act( + id: JsonValue, + requestOptions: RequestOptions, + ): HttpResponseFor = act(id, SessionActParams.none(), requestOptions) + + /** + * Returns a raw HTTP response for `post /sessions/{id}/end`, but is otherwise the same as + * [SessionService.end]. + */ + @MustBeClosed + fun end(id: JsonValue): HttpResponseFor = + end(id, SessionEndParams.none()) + + /** @see end */ + @MustBeClosed + fun end( + id: JsonValue, + params: SessionEndParams = SessionEndParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor = + end(params.toBuilder().id(id).build(), requestOptions) + + /** @see end */ + @MustBeClosed + fun end( + id: JsonValue, + params: SessionEndParams = SessionEndParams.none(), + ): HttpResponseFor = end(id, params, RequestOptions.none()) + + /** @see end */ + @MustBeClosed + fun end( + params: SessionEndParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor + + /** @see end */ + @MustBeClosed + fun end(params: SessionEndParams): HttpResponseFor = + end(params, RequestOptions.none()) + + /** @see end */ + @MustBeClosed + fun end( + id: JsonValue, + requestOptions: RequestOptions, + ): HttpResponseFor = end(id, SessionEndParams.none(), requestOptions) + + /** + * Returns a raw HTTP response for `post /sessions/{id}/agentExecute`, but is otherwise the + * same as [SessionService.executeAgent]. + */ + @MustBeClosed + fun executeAgent(id: JsonValue): HttpResponseFor = + executeAgent(id, SessionExecuteAgentParams.none()) + + /** @see executeAgent */ + @MustBeClosed + fun executeAgent( + id: JsonValue, + params: SessionExecuteAgentParams = SessionExecuteAgentParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor = + executeAgent(params.toBuilder().id(id).build(), requestOptions) + + /** @see executeAgent */ + @MustBeClosed + fun executeAgent( + id: JsonValue, + params: SessionExecuteAgentParams = SessionExecuteAgentParams.none(), + ): HttpResponseFor = + executeAgent(id, params, RequestOptions.none()) + + /** @see executeAgent */ + @MustBeClosed + fun executeAgent( + params: SessionExecuteAgentParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor + + /** @see executeAgent */ + @MustBeClosed + fun executeAgent( + params: SessionExecuteAgentParams + ): HttpResponseFor = + executeAgent(params, RequestOptions.none()) + + /** @see executeAgent */ + @MustBeClosed + fun executeAgent( + id: JsonValue, + requestOptions: RequestOptions, + ): HttpResponseFor = + executeAgent(id, SessionExecuteAgentParams.none(), requestOptions) + + /** + * Returns a raw HTTP response for `post /sessions/{id}/extract`, but is otherwise the same + * as [SessionService.extract]. + */ + @MustBeClosed + fun extract(id: JsonValue): HttpResponseFor = + extract(id, SessionExtractParams.none()) + + /** @see extract */ + @MustBeClosed + fun extract( + id: JsonValue, + params: SessionExtractParams = SessionExtractParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor = + extract(params.toBuilder().id(id).build(), requestOptions) + + /** @see extract */ + @MustBeClosed + fun extract( + id: JsonValue, + params: SessionExtractParams = SessionExtractParams.none(), + ): HttpResponseFor = extract(id, params, RequestOptions.none()) + + /** @see extract */ + @MustBeClosed + fun extract( + params: SessionExtractParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor + + /** @see extract */ + @MustBeClosed + fun extract(params: SessionExtractParams): HttpResponseFor = + extract(params, RequestOptions.none()) + + /** @see extract */ + @MustBeClosed + fun extract( + id: JsonValue, + requestOptions: RequestOptions, + ): HttpResponseFor = + extract(id, SessionExtractParams.none(), requestOptions) + + /** + * Returns a raw HTTP response for `post /sessions/{id}/navigate`, but is otherwise the same + * as [SessionService.navigate]. + */ + @MustBeClosed + fun navigate(id: JsonValue): HttpResponseFor = + navigate(id, SessionNavigateParams.none()) + + /** @see navigate */ + @MustBeClosed + fun navigate( + id: JsonValue, + params: SessionNavigateParams = SessionNavigateParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor = + navigate(params.toBuilder().id(id).build(), requestOptions) + + /** @see navigate */ + @MustBeClosed + fun navigate( + id: JsonValue, + params: SessionNavigateParams = SessionNavigateParams.none(), + ): HttpResponseFor = navigate(id, params, RequestOptions.none()) + + /** @see navigate */ + @MustBeClosed + fun navigate( + params: SessionNavigateParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor + + /** @see navigate */ + @MustBeClosed + fun navigate(params: SessionNavigateParams): HttpResponseFor = + navigate(params, RequestOptions.none()) + + /** @see navigate */ + @MustBeClosed + fun navigate( + id: JsonValue, + requestOptions: RequestOptions, + ): HttpResponseFor = + navigate(id, SessionNavigateParams.none(), requestOptions) + + /** + * Returns a raw HTTP response for `post /sessions/{id}/observe`, but is otherwise the same + * as [SessionService.observe]. + */ + @MustBeClosed + fun observe(id: JsonValue): HttpResponseFor = + observe(id, SessionObserveParams.none()) + + /** @see observe */ + @MustBeClosed + fun observe( + id: JsonValue, + params: SessionObserveParams = SessionObserveParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor = + observe(params.toBuilder().id(id).build(), requestOptions) + + /** @see observe */ + @MustBeClosed + fun observe( + id: JsonValue, + params: SessionObserveParams = SessionObserveParams.none(), + ): HttpResponseFor = observe(id, params, RequestOptions.none()) + + /** @see observe */ + @MustBeClosed + fun observe( + params: SessionObserveParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor + + /** @see observe */ + @MustBeClosed + fun observe(params: SessionObserveParams): HttpResponseFor = + observe(params, RequestOptions.none()) + + /** @see observe */ + @MustBeClosed + fun observe( + id: JsonValue, + requestOptions: RequestOptions, + ): HttpResponseFor = + observe(id, SessionObserveParams.none(), requestOptions) + /** * Returns a raw HTTP response for `post /sessions/start`, but is otherwise the same as * [SessionService.start]. diff --git a/stagehand-java-core/src/main/kotlin/com/browserbase/api/services/blocking/SessionServiceImpl.kt b/stagehand-java-core/src/main/kotlin/com/browserbase/api/services/blocking/SessionServiceImpl.kt index 2a983bb..467e9db 100644 --- a/stagehand-java-core/src/main/kotlin/com/browserbase/api/services/blocking/SessionServiceImpl.kt +++ b/stagehand-java-core/src/main/kotlin/com/browserbase/api/services/blocking/SessionServiceImpl.kt @@ -15,6 +15,18 @@ import com.browserbase.api.core.http.HttpResponseFor import com.browserbase.api.core.http.json import com.browserbase.api.core.http.parseable import com.browserbase.api.core.prepare +import com.browserbase.api.models.sessions.SessionActParams +import com.browserbase.api.models.sessions.SessionActResponse +import com.browserbase.api.models.sessions.SessionEndParams +import com.browserbase.api.models.sessions.SessionEndResponse +import com.browserbase.api.models.sessions.SessionExecuteAgentParams +import com.browserbase.api.models.sessions.SessionExecuteAgentResponse +import com.browserbase.api.models.sessions.SessionExtractParams +import com.browserbase.api.models.sessions.SessionExtractResponse +import com.browserbase.api.models.sessions.SessionNavigateParams +import com.browserbase.api.models.sessions.SessionNavigateResponse +import com.browserbase.api.models.sessions.SessionObserveParams +import com.browserbase.api.models.sessions.SessionObserveResponse import com.browserbase.api.models.sessions.SessionStartParams import com.browserbase.api.models.sessions.SessionStartResponse import java.util.function.Consumer @@ -31,6 +43,42 @@ class SessionServiceImpl internal constructor(private val clientOptions: ClientO override fun withOptions(modifier: Consumer): SessionService = SessionServiceImpl(clientOptions.toBuilder().apply(modifier::accept).build()) + override fun act(params: SessionActParams, requestOptions: RequestOptions): SessionActResponse = + // post /sessions/{id}/act + withRawResponse().act(params, requestOptions).parse() + + override fun end(params: SessionEndParams, requestOptions: RequestOptions): SessionEndResponse = + // post /sessions/{id}/end + withRawResponse().end(params, requestOptions).parse() + + override fun executeAgent( + params: SessionExecuteAgentParams, + requestOptions: RequestOptions, + ): SessionExecuteAgentResponse = + // post /sessions/{id}/agentExecute + withRawResponse().executeAgent(params, requestOptions).parse() + + override fun extract( + params: SessionExtractParams, + requestOptions: RequestOptions, + ): SessionExtractResponse = + // post /sessions/{id}/extract + withRawResponse().extract(params, requestOptions).parse() + + override fun navigate( + params: SessionNavigateParams, + requestOptions: RequestOptions, + ): SessionNavigateResponse = + // post /sessions/{id}/navigate + withRawResponse().navigate(params, requestOptions).parse() + + override fun observe( + params: SessionObserveParams, + requestOptions: RequestOptions, + ): SessionObserveResponse = + // post /sessions/{id}/observe + withRawResponse().observe(params, requestOptions).parse() + override fun start( params: SessionStartParams, requestOptions: RequestOptions, @@ -51,6 +99,174 @@ class SessionServiceImpl internal constructor(private val clientOptions: ClientO clientOptions.toBuilder().apply(modifier::accept).build() ) + private val actHandler: Handler = + jsonHandler(clientOptions.jsonMapper) + + override fun act( + params: SessionActParams, + requestOptions: RequestOptions, + ): HttpResponseFor { + val request = + HttpRequest.builder() + .method(HttpMethod.POST) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("sessions", params._pathParam(0), "act") + .body(json(clientOptions.jsonMapper, params._body())) + .build() + .prepare(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.execute(request, requestOptions) + return errorHandler.handle(response).parseable { + response + .use { actHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } + + private val endHandler: Handler = + jsonHandler(clientOptions.jsonMapper) + + override fun end( + params: SessionEndParams, + requestOptions: RequestOptions, + ): HttpResponseFor { + val request = + HttpRequest.builder() + .method(HttpMethod.POST) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("sessions", params._pathParam(0), "end") + .apply { params._body().ifPresent { body(json(clientOptions.jsonMapper, it)) } } + .build() + .prepare(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.execute(request, requestOptions) + return errorHandler.handle(response).parseable { + response + .use { endHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } + + private val executeAgentHandler: Handler = + jsonHandler(clientOptions.jsonMapper) + + override fun executeAgent( + params: SessionExecuteAgentParams, + requestOptions: RequestOptions, + ): HttpResponseFor { + val request = + HttpRequest.builder() + .method(HttpMethod.POST) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("sessions", params._pathParam(0), "agentExecute") + .body(json(clientOptions.jsonMapper, params._body())) + .build() + .prepare(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.execute(request, requestOptions) + return errorHandler.handle(response).parseable { + response + .use { executeAgentHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } + + private val extractHandler: Handler = + jsonHandler(clientOptions.jsonMapper) + + override fun extract( + params: SessionExtractParams, + requestOptions: RequestOptions, + ): HttpResponseFor { + val request = + HttpRequest.builder() + .method(HttpMethod.POST) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("sessions", params._pathParam(0), "extract") + .body(json(clientOptions.jsonMapper, params._body())) + .build() + .prepare(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.execute(request, requestOptions) + return errorHandler.handle(response).parseable { + response + .use { extractHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } + + private val navigateHandler: Handler = + jsonHandler(clientOptions.jsonMapper) + + override fun navigate( + params: SessionNavigateParams, + requestOptions: RequestOptions, + ): HttpResponseFor { + val request = + HttpRequest.builder() + .method(HttpMethod.POST) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("sessions", params._pathParam(0), "navigate") + .body(json(clientOptions.jsonMapper, params._body())) + .build() + .prepare(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.execute(request, requestOptions) + return errorHandler.handle(response).parseable { + response + .use { navigateHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } + + private val observeHandler: Handler = + jsonHandler(clientOptions.jsonMapper) + + override fun observe( + params: SessionObserveParams, + requestOptions: RequestOptions, + ): HttpResponseFor { + val request = + HttpRequest.builder() + .method(HttpMethod.POST) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("sessions", params._pathParam(0), "observe") + .body(json(clientOptions.jsonMapper, params._body())) + .build() + .prepare(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.execute(request, requestOptions) + return errorHandler.handle(response).parseable { + response + .use { observeHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } + private val startHandler: Handler = jsonHandler(clientOptions.jsonMapper) diff --git a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionActParamsTest.kt b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionActParamsTest.kt new file mode 100644 index 0000000..4b81e39 --- /dev/null +++ b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionActParamsTest.kt @@ -0,0 +1,82 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.browserbase.api.models.sessions + +import com.browserbase.api.core.JsonValue +import com.browserbase.api.core.http.Headers +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class SessionActParamsTest { + + @Test + fun create() { + SessionActParams.builder() + .id(JsonValue.from(mapOf())) + .xLanguage(JsonValue.from(mapOf())) + .xSdkVersion(JsonValue.from(mapOf())) + .xSentAt(JsonValue.from(mapOf())) + .xStreamResponse(JsonValue.from(mapOf())) + .body(JsonValue.from(mapOf())) + .build() + } + + @Test + fun pathParams() { + val params = SessionActParams.builder().id(JsonValue.from(mapOf())).build() + + assertThat(params._pathParam(0)).isEqualTo("[object Object]") + // out-of-bound path param + assertThat(params._pathParam(1)).isEqualTo("") + } + + @Test + fun headers() { + val params = + SessionActParams.builder() + .id(JsonValue.from(mapOf())) + .xLanguage(JsonValue.from(mapOf())) + .xSdkVersion(JsonValue.from(mapOf())) + .xSentAt(JsonValue.from(mapOf())) + .xStreamResponse(JsonValue.from(mapOf())) + .body(JsonValue.from(mapOf())) + .build() + + val headers = params._headers() + + assertThat(headers).isEqualTo(Headers.builder().build()) + } + + @Test + fun headersWithoutOptionalFields() { + val params = SessionActParams.builder().id(JsonValue.from(mapOf())).build() + + val headers = params._headers() + + assertThat(headers).isEqualTo(Headers.builder().build()) + } + + @Test + fun body() { + val params = + SessionActParams.builder() + .id(JsonValue.from(mapOf())) + .xLanguage(JsonValue.from(mapOf())) + .xSdkVersion(JsonValue.from(mapOf())) + .xSentAt(JsonValue.from(mapOf())) + .xStreamResponse(JsonValue.from(mapOf())) + .body(JsonValue.from(mapOf())) + .build() + + val body = params._body() + + assertThat(body).isEqualTo(JsonValue.from(mapOf())) + } + + @Test + fun bodyWithoutOptionalFields() { + val params = SessionActParams.builder().id(JsonValue.from(mapOf())).build() + + val body = params._body() + } +} diff --git a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionActResponseTest.kt b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionActResponseTest.kt new file mode 100644 index 0000000..83f3fa4 --- /dev/null +++ b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionActResponseTest.kt @@ -0,0 +1,30 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.browserbase.api.models.sessions + +import com.browserbase.api.core.jsonMapper +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class SessionActResponseTest { + + @Test + fun create() { + val sessionActResponse = SessionActResponse.builder().build() + } + + @Test + fun roundtrip() { + val jsonMapper = jsonMapper() + val sessionActResponse = SessionActResponse.builder().build() + + val roundtrippedSessionActResponse = + jsonMapper.readValue( + jsonMapper.writeValueAsString(sessionActResponse), + jacksonTypeRef(), + ) + + assertThat(roundtrippedSessionActResponse).isEqualTo(sessionActResponse) + } +} diff --git a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionEndParamsTest.kt b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionEndParamsTest.kt new file mode 100644 index 0000000..514fc5e --- /dev/null +++ b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionEndParamsTest.kt @@ -0,0 +1,56 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.browserbase.api.models.sessions + +import com.browserbase.api.core.JsonValue +import com.browserbase.api.core.http.Headers +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class SessionEndParamsTest { + + @Test + fun create() { + SessionEndParams.builder() + .id(JsonValue.from(mapOf())) + .xLanguage(JsonValue.from(mapOf())) + .xSdkVersion(JsonValue.from(mapOf())) + .xSentAt(JsonValue.from(mapOf())) + .xStreamResponse(JsonValue.from(mapOf())) + .build() + } + + @Test + fun pathParams() { + val params = SessionEndParams.builder().id(JsonValue.from(mapOf())).build() + + assertThat(params._pathParam(0)).isEqualTo("[object Object]") + // out-of-bound path param + assertThat(params._pathParam(1)).isEqualTo("") + } + + @Test + fun headers() { + val params = + SessionEndParams.builder() + .id(JsonValue.from(mapOf())) + .xLanguage(JsonValue.from(mapOf())) + .xSdkVersion(JsonValue.from(mapOf())) + .xSentAt(JsonValue.from(mapOf())) + .xStreamResponse(JsonValue.from(mapOf())) + .build() + + val headers = params._headers() + + assertThat(headers).isEqualTo(Headers.builder().build()) + } + + @Test + fun headersWithoutOptionalFields() { + val params = SessionEndParams.builder().id(JsonValue.from(mapOf())).build() + + val headers = params._headers() + + assertThat(headers).isEqualTo(Headers.builder().build()) + } +} diff --git a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionEndResponseTest.kt b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionEndResponseTest.kt new file mode 100644 index 0000000..30e45db --- /dev/null +++ b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionEndResponseTest.kt @@ -0,0 +1,30 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.browserbase.api.models.sessions + +import com.browserbase.api.core.jsonMapper +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class SessionEndResponseTest { + + @Test + fun create() { + val sessionEndResponse = SessionEndResponse.builder().build() + } + + @Test + fun roundtrip() { + val jsonMapper = jsonMapper() + val sessionEndResponse = SessionEndResponse.builder().build() + + val roundtrippedSessionEndResponse = + jsonMapper.readValue( + jsonMapper.writeValueAsString(sessionEndResponse), + jacksonTypeRef(), + ) + + assertThat(roundtrippedSessionEndResponse).isEqualTo(sessionEndResponse) + } +} diff --git a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionExecuteAgentParamsTest.kt b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionExecuteAgentParamsTest.kt new file mode 100644 index 0000000..90f1e1f --- /dev/null +++ b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionExecuteAgentParamsTest.kt @@ -0,0 +1,85 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.browserbase.api.models.sessions + +import com.browserbase.api.core.JsonValue +import com.browserbase.api.core.http.Headers +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class SessionExecuteAgentParamsTest { + + @Test + fun create() { + SessionExecuteAgentParams.builder() + .id(JsonValue.from(mapOf())) + .xLanguage(JsonValue.from(mapOf())) + .xSdkVersion(JsonValue.from(mapOf())) + .xSentAt(JsonValue.from(mapOf())) + .xStreamResponse(JsonValue.from(mapOf())) + .body(JsonValue.from(mapOf())) + .build() + } + + @Test + fun pathParams() { + val params = + SessionExecuteAgentParams.builder().id(JsonValue.from(mapOf())).build() + + assertThat(params._pathParam(0)).isEqualTo("[object Object]") + // out-of-bound path param + assertThat(params._pathParam(1)).isEqualTo("") + } + + @Test + fun headers() { + val params = + SessionExecuteAgentParams.builder() + .id(JsonValue.from(mapOf())) + .xLanguage(JsonValue.from(mapOf())) + .xSdkVersion(JsonValue.from(mapOf())) + .xSentAt(JsonValue.from(mapOf())) + .xStreamResponse(JsonValue.from(mapOf())) + .body(JsonValue.from(mapOf())) + .build() + + val headers = params._headers() + + assertThat(headers).isEqualTo(Headers.builder().build()) + } + + @Test + fun headersWithoutOptionalFields() { + val params = + SessionExecuteAgentParams.builder().id(JsonValue.from(mapOf())).build() + + val headers = params._headers() + + assertThat(headers).isEqualTo(Headers.builder().build()) + } + + @Test + fun body() { + val params = + SessionExecuteAgentParams.builder() + .id(JsonValue.from(mapOf())) + .xLanguage(JsonValue.from(mapOf())) + .xSdkVersion(JsonValue.from(mapOf())) + .xSentAt(JsonValue.from(mapOf())) + .xStreamResponse(JsonValue.from(mapOf())) + .body(JsonValue.from(mapOf())) + .build() + + val body = params._body() + + assertThat(body).isEqualTo(JsonValue.from(mapOf())) + } + + @Test + fun bodyWithoutOptionalFields() { + val params = + SessionExecuteAgentParams.builder().id(JsonValue.from(mapOf())).build() + + val body = params._body() + } +} diff --git a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionExecuteAgentResponseTest.kt b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionExecuteAgentResponseTest.kt new file mode 100644 index 0000000..0c28d46 --- /dev/null +++ b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionExecuteAgentResponseTest.kt @@ -0,0 +1,30 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.browserbase.api.models.sessions + +import com.browserbase.api.core.jsonMapper +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class SessionExecuteAgentResponseTest { + + @Test + fun create() { + val sessionExecuteAgentResponse = SessionExecuteAgentResponse.builder().build() + } + + @Test + fun roundtrip() { + val jsonMapper = jsonMapper() + val sessionExecuteAgentResponse = SessionExecuteAgentResponse.builder().build() + + val roundtrippedSessionExecuteAgentResponse = + jsonMapper.readValue( + jsonMapper.writeValueAsString(sessionExecuteAgentResponse), + jacksonTypeRef(), + ) + + assertThat(roundtrippedSessionExecuteAgentResponse).isEqualTo(sessionExecuteAgentResponse) + } +} diff --git a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionExtractParamsTest.kt b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionExtractParamsTest.kt new file mode 100644 index 0000000..e631276 --- /dev/null +++ b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionExtractParamsTest.kt @@ -0,0 +1,82 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.browserbase.api.models.sessions + +import com.browserbase.api.core.JsonValue +import com.browserbase.api.core.http.Headers +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class SessionExtractParamsTest { + + @Test + fun create() { + SessionExtractParams.builder() + .id(JsonValue.from(mapOf())) + .xLanguage(JsonValue.from(mapOf())) + .xSdkVersion(JsonValue.from(mapOf())) + .xSentAt(JsonValue.from(mapOf())) + .xStreamResponse(JsonValue.from(mapOf())) + .body(JsonValue.from(mapOf())) + .build() + } + + @Test + fun pathParams() { + val params = SessionExtractParams.builder().id(JsonValue.from(mapOf())).build() + + assertThat(params._pathParam(0)).isEqualTo("[object Object]") + // out-of-bound path param + assertThat(params._pathParam(1)).isEqualTo("") + } + + @Test + fun headers() { + val params = + SessionExtractParams.builder() + .id(JsonValue.from(mapOf())) + .xLanguage(JsonValue.from(mapOf())) + .xSdkVersion(JsonValue.from(mapOf())) + .xSentAt(JsonValue.from(mapOf())) + .xStreamResponse(JsonValue.from(mapOf())) + .body(JsonValue.from(mapOf())) + .build() + + val headers = params._headers() + + assertThat(headers).isEqualTo(Headers.builder().build()) + } + + @Test + fun headersWithoutOptionalFields() { + val params = SessionExtractParams.builder().id(JsonValue.from(mapOf())).build() + + val headers = params._headers() + + assertThat(headers).isEqualTo(Headers.builder().build()) + } + + @Test + fun body() { + val params = + SessionExtractParams.builder() + .id(JsonValue.from(mapOf())) + .xLanguage(JsonValue.from(mapOf())) + .xSdkVersion(JsonValue.from(mapOf())) + .xSentAt(JsonValue.from(mapOf())) + .xStreamResponse(JsonValue.from(mapOf())) + .body(JsonValue.from(mapOf())) + .build() + + val body = params._body() + + assertThat(body).isEqualTo(JsonValue.from(mapOf())) + } + + @Test + fun bodyWithoutOptionalFields() { + val params = SessionExtractParams.builder().id(JsonValue.from(mapOf())).build() + + val body = params._body() + } +} diff --git a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionExtractResponseTest.kt b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionExtractResponseTest.kt new file mode 100644 index 0000000..04bed64 --- /dev/null +++ b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionExtractResponseTest.kt @@ -0,0 +1,30 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.browserbase.api.models.sessions + +import com.browserbase.api.core.jsonMapper +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class SessionExtractResponseTest { + + @Test + fun create() { + val sessionExtractResponse = SessionExtractResponse.builder().build() + } + + @Test + fun roundtrip() { + val jsonMapper = jsonMapper() + val sessionExtractResponse = SessionExtractResponse.builder().build() + + val roundtrippedSessionExtractResponse = + jsonMapper.readValue( + jsonMapper.writeValueAsString(sessionExtractResponse), + jacksonTypeRef(), + ) + + assertThat(roundtrippedSessionExtractResponse).isEqualTo(sessionExtractResponse) + } +} diff --git a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionNavigateParamsTest.kt b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionNavigateParamsTest.kt new file mode 100644 index 0000000..6d8a60d --- /dev/null +++ b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionNavigateParamsTest.kt @@ -0,0 +1,85 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.browserbase.api.models.sessions + +import com.browserbase.api.core.JsonValue +import com.browserbase.api.core.http.Headers +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class SessionNavigateParamsTest { + + @Test + fun create() { + SessionNavigateParams.builder() + .id(JsonValue.from(mapOf())) + .xLanguage(JsonValue.from(mapOf())) + .xSdkVersion(JsonValue.from(mapOf())) + .xSentAt(JsonValue.from(mapOf())) + .xStreamResponse(JsonValue.from(mapOf())) + .body(JsonValue.from(mapOf())) + .build() + } + + @Test + fun pathParams() { + val params = + SessionNavigateParams.builder().id(JsonValue.from(mapOf())).build() + + assertThat(params._pathParam(0)).isEqualTo("[object Object]") + // out-of-bound path param + assertThat(params._pathParam(1)).isEqualTo("") + } + + @Test + fun headers() { + val params = + SessionNavigateParams.builder() + .id(JsonValue.from(mapOf())) + .xLanguage(JsonValue.from(mapOf())) + .xSdkVersion(JsonValue.from(mapOf())) + .xSentAt(JsonValue.from(mapOf())) + .xStreamResponse(JsonValue.from(mapOf())) + .body(JsonValue.from(mapOf())) + .build() + + val headers = params._headers() + + assertThat(headers).isEqualTo(Headers.builder().build()) + } + + @Test + fun headersWithoutOptionalFields() { + val params = + SessionNavigateParams.builder().id(JsonValue.from(mapOf())).build() + + val headers = params._headers() + + assertThat(headers).isEqualTo(Headers.builder().build()) + } + + @Test + fun body() { + val params = + SessionNavigateParams.builder() + .id(JsonValue.from(mapOf())) + .xLanguage(JsonValue.from(mapOf())) + .xSdkVersion(JsonValue.from(mapOf())) + .xSentAt(JsonValue.from(mapOf())) + .xStreamResponse(JsonValue.from(mapOf())) + .body(JsonValue.from(mapOf())) + .build() + + val body = params._body() + + assertThat(body).isEqualTo(JsonValue.from(mapOf())) + } + + @Test + fun bodyWithoutOptionalFields() { + val params = + SessionNavigateParams.builder().id(JsonValue.from(mapOf())).build() + + val body = params._body() + } +} diff --git a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionNavigateResponseTest.kt b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionNavigateResponseTest.kt new file mode 100644 index 0000000..6d62909 --- /dev/null +++ b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionNavigateResponseTest.kt @@ -0,0 +1,30 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.browserbase.api.models.sessions + +import com.browserbase.api.core.jsonMapper +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class SessionNavigateResponseTest { + + @Test + fun create() { + val sessionNavigateResponse = SessionNavigateResponse.builder().build() + } + + @Test + fun roundtrip() { + val jsonMapper = jsonMapper() + val sessionNavigateResponse = SessionNavigateResponse.builder().build() + + val roundtrippedSessionNavigateResponse = + jsonMapper.readValue( + jsonMapper.writeValueAsString(sessionNavigateResponse), + jacksonTypeRef(), + ) + + assertThat(roundtrippedSessionNavigateResponse).isEqualTo(sessionNavigateResponse) + } +} diff --git a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionObserveParamsTest.kt b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionObserveParamsTest.kt new file mode 100644 index 0000000..8943f1d --- /dev/null +++ b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionObserveParamsTest.kt @@ -0,0 +1,82 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.browserbase.api.models.sessions + +import com.browserbase.api.core.JsonValue +import com.browserbase.api.core.http.Headers +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class SessionObserveParamsTest { + + @Test + fun create() { + SessionObserveParams.builder() + .id(JsonValue.from(mapOf())) + .xLanguage(JsonValue.from(mapOf())) + .xSdkVersion(JsonValue.from(mapOf())) + .xSentAt(JsonValue.from(mapOf())) + .xStreamResponse(JsonValue.from(mapOf())) + .body(JsonValue.from(mapOf())) + .build() + } + + @Test + fun pathParams() { + val params = SessionObserveParams.builder().id(JsonValue.from(mapOf())).build() + + assertThat(params._pathParam(0)).isEqualTo("[object Object]") + // out-of-bound path param + assertThat(params._pathParam(1)).isEqualTo("") + } + + @Test + fun headers() { + val params = + SessionObserveParams.builder() + .id(JsonValue.from(mapOf())) + .xLanguage(JsonValue.from(mapOf())) + .xSdkVersion(JsonValue.from(mapOf())) + .xSentAt(JsonValue.from(mapOf())) + .xStreamResponse(JsonValue.from(mapOf())) + .body(JsonValue.from(mapOf())) + .build() + + val headers = params._headers() + + assertThat(headers).isEqualTo(Headers.builder().build()) + } + + @Test + fun headersWithoutOptionalFields() { + val params = SessionObserveParams.builder().id(JsonValue.from(mapOf())).build() + + val headers = params._headers() + + assertThat(headers).isEqualTo(Headers.builder().build()) + } + + @Test + fun body() { + val params = + SessionObserveParams.builder() + .id(JsonValue.from(mapOf())) + .xLanguage(JsonValue.from(mapOf())) + .xSdkVersion(JsonValue.from(mapOf())) + .xSentAt(JsonValue.from(mapOf())) + .xStreamResponse(JsonValue.from(mapOf())) + .body(JsonValue.from(mapOf())) + .build() + + val body = params._body() + + assertThat(body).isEqualTo(JsonValue.from(mapOf())) + } + + @Test + fun bodyWithoutOptionalFields() { + val params = SessionObserveParams.builder().id(JsonValue.from(mapOf())).build() + + val body = params._body() + } +} diff --git a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionObserveResponseTest.kt b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionObserveResponseTest.kt new file mode 100644 index 0000000..b597689 --- /dev/null +++ b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionObserveResponseTest.kt @@ -0,0 +1,30 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.browserbase.api.models.sessions + +import com.browserbase.api.core.jsonMapper +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class SessionObserveResponseTest { + + @Test + fun create() { + val sessionObserveResponse = SessionObserveResponse.builder().build() + } + + @Test + fun roundtrip() { + val jsonMapper = jsonMapper() + val sessionObserveResponse = SessionObserveResponse.builder().build() + + val roundtrippedSessionObserveResponse = + jsonMapper.readValue( + jsonMapper.writeValueAsString(sessionObserveResponse), + jacksonTypeRef(), + ) + + assertThat(roundtrippedSessionObserveResponse).isEqualTo(sessionObserveResponse) + } +} diff --git a/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/async/SessionServiceAsyncTest.kt b/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/async/SessionServiceAsyncTest.kt index 57ff039..dba84aa 100644 --- a/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/async/SessionServiceAsyncTest.kt +++ b/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/async/SessionServiceAsyncTest.kt @@ -5,6 +5,12 @@ package com.browserbase.api.services.async import com.browserbase.api.TestServerExtension import com.browserbase.api.client.okhttp.StagehandOkHttpClientAsync import com.browserbase.api.core.JsonValue +import com.browserbase.api.models.sessions.SessionActParams +import com.browserbase.api.models.sessions.SessionEndParams +import com.browserbase.api.models.sessions.SessionExecuteAgentParams +import com.browserbase.api.models.sessions.SessionExtractParams +import com.browserbase.api.models.sessions.SessionNavigateParams +import com.browserbase.api.models.sessions.SessionObserveParams import com.browserbase.api.models.sessions.SessionStartParams import org.junit.jupiter.api.Disabled import org.junit.jupiter.api.Test @@ -13,6 +19,173 @@ import org.junit.jupiter.api.extension.ExtendWith @ExtendWith(TestServerExtension::class) internal class SessionServiceAsyncTest { + @Disabled("Prism tests are disabled") + @Test + fun act() { + val client = + StagehandOkHttpClientAsync.builder() + .baseUrl(TestServerExtension.BASE_URL) + .browserbaseApiKey("My Browserbase API Key") + .browserbaseProjectId("My Browserbase Project ID") + .modelApiKey("My Model API Key") + .build() + val sessionServiceAsync = client.sessions() + + val responseFuture = + sessionServiceAsync.act( + SessionActParams.builder() + .id(JsonValue.from(mapOf())) + .xLanguage(JsonValue.from(mapOf())) + .xSdkVersion(JsonValue.from(mapOf())) + .xSentAt(JsonValue.from(mapOf())) + .xStreamResponse(JsonValue.from(mapOf())) + .body(JsonValue.from(mapOf())) + .build() + ) + + val response = responseFuture.get() + response.validate() + } + + @Disabled("Prism tests are disabled") + @Test + fun end() { + val client = + StagehandOkHttpClientAsync.builder() + .baseUrl(TestServerExtension.BASE_URL) + .browserbaseApiKey("My Browserbase API Key") + .browserbaseProjectId("My Browserbase Project ID") + .modelApiKey("My Model API Key") + .build() + val sessionServiceAsync = client.sessions() + + val responseFuture = + sessionServiceAsync.end( + SessionEndParams.builder() + .id(JsonValue.from(mapOf())) + .xLanguage(JsonValue.from(mapOf())) + .xSdkVersion(JsonValue.from(mapOf())) + .xSentAt(JsonValue.from(mapOf())) + .xStreamResponse(JsonValue.from(mapOf())) + .build() + ) + + val response = responseFuture.get() + response.validate() + } + + @Disabled("Prism tests are disabled") + @Test + fun executeAgent() { + val client = + StagehandOkHttpClientAsync.builder() + .baseUrl(TestServerExtension.BASE_URL) + .browserbaseApiKey("My Browserbase API Key") + .browserbaseProjectId("My Browserbase Project ID") + .modelApiKey("My Model API Key") + .build() + val sessionServiceAsync = client.sessions() + + val responseFuture = + sessionServiceAsync.executeAgent( + SessionExecuteAgentParams.builder() + .id(JsonValue.from(mapOf())) + .xLanguage(JsonValue.from(mapOf())) + .xSdkVersion(JsonValue.from(mapOf())) + .xSentAt(JsonValue.from(mapOf())) + .xStreamResponse(JsonValue.from(mapOf())) + .body(JsonValue.from(mapOf())) + .build() + ) + + val response = responseFuture.get() + response.validate() + } + + @Disabled("Prism tests are disabled") + @Test + fun extract() { + val client = + StagehandOkHttpClientAsync.builder() + .baseUrl(TestServerExtension.BASE_URL) + .browserbaseApiKey("My Browserbase API Key") + .browserbaseProjectId("My Browserbase Project ID") + .modelApiKey("My Model API Key") + .build() + val sessionServiceAsync = client.sessions() + + val responseFuture = + sessionServiceAsync.extract( + SessionExtractParams.builder() + .id(JsonValue.from(mapOf())) + .xLanguage(JsonValue.from(mapOf())) + .xSdkVersion(JsonValue.from(mapOf())) + .xSentAt(JsonValue.from(mapOf())) + .xStreamResponse(JsonValue.from(mapOf())) + .body(JsonValue.from(mapOf())) + .build() + ) + + val response = responseFuture.get() + response.validate() + } + + @Disabled("Prism tests are disabled") + @Test + fun navigate() { + val client = + StagehandOkHttpClientAsync.builder() + .baseUrl(TestServerExtension.BASE_URL) + .browserbaseApiKey("My Browserbase API Key") + .browserbaseProjectId("My Browserbase Project ID") + .modelApiKey("My Model API Key") + .build() + val sessionServiceAsync = client.sessions() + + val responseFuture = + sessionServiceAsync.navigate( + SessionNavigateParams.builder() + .id(JsonValue.from(mapOf())) + .xLanguage(JsonValue.from(mapOf())) + .xSdkVersion(JsonValue.from(mapOf())) + .xSentAt(JsonValue.from(mapOf())) + .xStreamResponse(JsonValue.from(mapOf())) + .body(JsonValue.from(mapOf())) + .build() + ) + + val response = responseFuture.get() + response.validate() + } + + @Disabled("Prism tests are disabled") + @Test + fun observe() { + val client = + StagehandOkHttpClientAsync.builder() + .baseUrl(TestServerExtension.BASE_URL) + .browserbaseApiKey("My Browserbase API Key") + .browserbaseProjectId("My Browserbase Project ID") + .modelApiKey("My Model API Key") + .build() + val sessionServiceAsync = client.sessions() + + val responseFuture = + sessionServiceAsync.observe( + SessionObserveParams.builder() + .id(JsonValue.from(mapOf())) + .xLanguage(JsonValue.from(mapOf())) + .xSdkVersion(JsonValue.from(mapOf())) + .xSentAt(JsonValue.from(mapOf())) + .xStreamResponse(JsonValue.from(mapOf())) + .body(JsonValue.from(mapOf())) + .build() + ) + + val response = responseFuture.get() + response.validate() + } + @Disabled("Prism tests are disabled") @Test fun start() { diff --git a/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/blocking/SessionServiceTest.kt b/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/blocking/SessionServiceTest.kt index c782cd2..03853cd 100644 --- a/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/blocking/SessionServiceTest.kt +++ b/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/blocking/SessionServiceTest.kt @@ -5,6 +5,12 @@ package com.browserbase.api.services.blocking import com.browserbase.api.TestServerExtension import com.browserbase.api.client.okhttp.StagehandOkHttpClient import com.browserbase.api.core.JsonValue +import com.browserbase.api.models.sessions.SessionActParams +import com.browserbase.api.models.sessions.SessionEndParams +import com.browserbase.api.models.sessions.SessionExecuteAgentParams +import com.browserbase.api.models.sessions.SessionExtractParams +import com.browserbase.api.models.sessions.SessionNavigateParams +import com.browserbase.api.models.sessions.SessionObserveParams import com.browserbase.api.models.sessions.SessionStartParams import org.junit.jupiter.api.Disabled import org.junit.jupiter.api.Test @@ -13,6 +19,167 @@ import org.junit.jupiter.api.extension.ExtendWith @ExtendWith(TestServerExtension::class) internal class SessionServiceTest { + @Disabled("Prism tests are disabled") + @Test + fun act() { + val client = + StagehandOkHttpClient.builder() + .baseUrl(TestServerExtension.BASE_URL) + .browserbaseApiKey("My Browserbase API Key") + .browserbaseProjectId("My Browserbase Project ID") + .modelApiKey("My Model API Key") + .build() + val sessionService = client.sessions() + + val response = + sessionService.act( + SessionActParams.builder() + .id(JsonValue.from(mapOf())) + .xLanguage(JsonValue.from(mapOf())) + .xSdkVersion(JsonValue.from(mapOf())) + .xSentAt(JsonValue.from(mapOf())) + .xStreamResponse(JsonValue.from(mapOf())) + .body(JsonValue.from(mapOf())) + .build() + ) + + response.validate() + } + + @Disabled("Prism tests are disabled") + @Test + fun end() { + val client = + StagehandOkHttpClient.builder() + .baseUrl(TestServerExtension.BASE_URL) + .browserbaseApiKey("My Browserbase API Key") + .browserbaseProjectId("My Browserbase Project ID") + .modelApiKey("My Model API Key") + .build() + val sessionService = client.sessions() + + val response = + sessionService.end( + SessionEndParams.builder() + .id(JsonValue.from(mapOf())) + .xLanguage(JsonValue.from(mapOf())) + .xSdkVersion(JsonValue.from(mapOf())) + .xSentAt(JsonValue.from(mapOf())) + .xStreamResponse(JsonValue.from(mapOf())) + .build() + ) + + response.validate() + } + + @Disabled("Prism tests are disabled") + @Test + fun executeAgent() { + val client = + StagehandOkHttpClient.builder() + .baseUrl(TestServerExtension.BASE_URL) + .browserbaseApiKey("My Browserbase API Key") + .browserbaseProjectId("My Browserbase Project ID") + .modelApiKey("My Model API Key") + .build() + val sessionService = client.sessions() + + val response = + sessionService.executeAgent( + SessionExecuteAgentParams.builder() + .id(JsonValue.from(mapOf())) + .xLanguage(JsonValue.from(mapOf())) + .xSdkVersion(JsonValue.from(mapOf())) + .xSentAt(JsonValue.from(mapOf())) + .xStreamResponse(JsonValue.from(mapOf())) + .body(JsonValue.from(mapOf())) + .build() + ) + + response.validate() + } + + @Disabled("Prism tests are disabled") + @Test + fun extract() { + val client = + StagehandOkHttpClient.builder() + .baseUrl(TestServerExtension.BASE_URL) + .browserbaseApiKey("My Browserbase API Key") + .browserbaseProjectId("My Browserbase Project ID") + .modelApiKey("My Model API Key") + .build() + val sessionService = client.sessions() + + val response = + sessionService.extract( + SessionExtractParams.builder() + .id(JsonValue.from(mapOf())) + .xLanguage(JsonValue.from(mapOf())) + .xSdkVersion(JsonValue.from(mapOf())) + .xSentAt(JsonValue.from(mapOf())) + .xStreamResponse(JsonValue.from(mapOf())) + .body(JsonValue.from(mapOf())) + .build() + ) + + response.validate() + } + + @Disabled("Prism tests are disabled") + @Test + fun navigate() { + val client = + StagehandOkHttpClient.builder() + .baseUrl(TestServerExtension.BASE_URL) + .browserbaseApiKey("My Browserbase API Key") + .browserbaseProjectId("My Browserbase Project ID") + .modelApiKey("My Model API Key") + .build() + val sessionService = client.sessions() + + val response = + sessionService.navigate( + SessionNavigateParams.builder() + .id(JsonValue.from(mapOf())) + .xLanguage(JsonValue.from(mapOf())) + .xSdkVersion(JsonValue.from(mapOf())) + .xSentAt(JsonValue.from(mapOf())) + .xStreamResponse(JsonValue.from(mapOf())) + .body(JsonValue.from(mapOf())) + .build() + ) + + response.validate() + } + + @Disabled("Prism tests are disabled") + @Test + fun observe() { + val client = + StagehandOkHttpClient.builder() + .baseUrl(TestServerExtension.BASE_URL) + .browserbaseApiKey("My Browserbase API Key") + .browserbaseProjectId("My Browserbase Project ID") + .modelApiKey("My Model API Key") + .build() + val sessionService = client.sessions() + + val response = + sessionService.observe( + SessionObserveParams.builder() + .id(JsonValue.from(mapOf())) + .xLanguage(JsonValue.from(mapOf())) + .xSdkVersion(JsonValue.from(mapOf())) + .xSentAt(JsonValue.from(mapOf())) + .xStreamResponse(JsonValue.from(mapOf())) + .body(JsonValue.from(mapOf())) + .build() + ) + + response.validate() + } + @Disabled("Prism tests are disabled") @Test fun start() { From 067c9e644940fa3671665a902bc605b8e358473f Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 17 Dec 2025 18:20:37 +0000 Subject: [PATCH 04/18] feat(api): manual updates --- .stats.yml | 6 +- README.md | 104 +- .../main/kotlin/stagehand.publish.gradle.kts | 2 +- .../api/models/sessions/SessionActParams.kt | 1547 +++- .../api/models/sessions/SessionActResponse.kt | 731 +- .../api/models/sessions/SessionEndParams.kt | 347 +- .../api/models/sessions/SessionEndResponse.kt | 193 +- .../sessions/SessionExecuteAgentParams.kt | 269 - .../sessions/SessionExecuteAgentResponse.kt | 118 - .../models/sessions/SessionExecuteParams.kt | 1403 +++ .../models/sessions/SessionExecuteResponse.kt | 1775 ++++ .../models/sessions/SessionExtractParams.kt | 1069 ++- .../models/sessions/SessionExtractResponse.kt | 395 +- .../models/sessions/SessionNavigateParams.kt | 1074 ++- .../sessions/SessionNavigateResponse.kt | 392 +- .../models/sessions/SessionObserveParams.kt | 907 +- .../models/sessions/SessionObserveResponse.kt | 439 +- .../api/models/sessions/SessionStartParams.kt | 7696 ++++++++++++++++- .../models/sessions/SessionStartResponse.kt | 428 +- .../api/services/async/SessionServiceAsync.kt | 323 +- .../services/async/SessionServiceAsyncImpl.kt | 72 +- .../api/services/blocking/SessionService.kt | 295 +- .../services/blocking/SessionServiceImpl.kt | 72 +- .../models/sessions/SessionActParamsTest.kt | 122 +- .../models/sessions/SessionActResponseTest.kt | 73 +- .../models/sessions/SessionEndParamsTest.kt | 38 +- .../models/sessions/SessionEndResponseTest.kt | 8 +- .../sessions/SessionExecuteAgentParamsTest.kt | 85 - .../SessionExecuteAgentResponseTest.kt | 30 - .../sessions/SessionExecuteParamsTest.kt | 199 + .../sessions/SessionExecuteResponseTest.kt | 151 + .../sessions/SessionExtractParamsTest.kt | 115 +- .../sessions/SessionExtractResponseTest.kt | 32 +- .../sessions/SessionNavigateParamsTest.kt | 102 +- .../sessions/SessionNavigateResponseTest.kt | 33 +- .../sessions/SessionObserveParamsTest.kt | 94 +- .../sessions/SessionObserveResponseTest.kt | 52 +- .../models/sessions/SessionStartParamsTest.kt | 607 +- .../sessions/SessionStartResponseTest.kt | 31 +- .../api/services/ErrorHandlingTest.kt | 547 +- .../api/services/ServiceParamsTest.kt | 35 +- .../services/async/SessionServiceAsyncTest.kt | 290 +- .../services/blocking/SessionServiceTest.kt | 290 +- 43 files changed, 20977 insertions(+), 1614 deletions(-) delete mode 100644 stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionExecuteAgentParams.kt delete mode 100644 stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionExecuteAgentResponse.kt create mode 100644 stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionExecuteParams.kt create mode 100644 stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionExecuteResponse.kt delete mode 100644 stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionExecuteAgentParamsTest.kt delete mode 100644 stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionExecuteAgentResponseTest.kt create mode 100644 stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionExecuteParamsTest.kt create mode 100644 stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionExecuteResponseTest.kt diff --git a/.stats.yml b/.stats.yml index c436ede..87bd24b 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-c1a6f03afe5d6823c198e5ac476fb688dacc783dae1fefdf6bf142084e298e16.yml -openapi_spec_hash: d20e8f697ce8d5bb80295fc1e8ce02e8 -config_hash: e457d704d820df5d25acfd379169f132 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/browserbase%2Fstagehand-349e1b0f6291eedd731c1660155a50adcb3424fb8cd9e17bbdc0939ff3bbffcd.yml +openapi_spec_hash: 456b593ea71d72bc31a6338a25363e9f +config_hash: 5f6b5ec6e84fb01932ba87c6a9623d9b diff --git a/README.md b/README.md index 1bab387..019da3c 100644 --- a/README.md +++ b/README.md @@ -48,14 +48,18 @@ This library requires Java 8 or later. ```java import com.browserbase.api.client.StagehandClient; import com.browserbase.api.client.okhttp.StagehandOkHttpClient; -import com.browserbase.api.models.sessions.SessionStartParams; -import com.browserbase.api.models.sessions.SessionStartResponse; +import com.browserbase.api.models.sessions.SessionActParams; +import com.browserbase.api.models.sessions.SessionActResponse; // Configures using the `stagehand.browserbaseApiKey`, `stagehand.browserbaseProjectId`, `stagehand.modelApiKey` and `stagehand.baseUrl` system properties // Or configures using the `BROWSERBASE_API_KEY`, `BROWSERBASE_PROJECT_ID`, `MODEL_API_KEY` and `STAGEHAND_BASE_URL` environment variables StagehandClient client = StagehandOkHttpClient.fromEnv(); -SessionStartResponse response = client.sessions().start(); +SessionActParams params = SessionActParams.builder() + .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") + .input("Click the login button") + .build(); +SessionActResponse response = client.sessions().act(params); ``` ## Client configuration @@ -132,7 +136,7 @@ The `withOptions()` method does not affect the original client or service. To send a request to the Stagehand API, build an instance of some `Params` class and pass it to the corresponding client method. When the response is received, it will be deserialized into an instance of a Java class. -For example, `client.sessions().start(...)` should be called with an instance of `SessionStartParams`, and it will return an instance of `SessionStartResponse`. +For example, `client.sessions().act(...)` should be called with an instance of `SessionActParams`, and it will return an instance of `SessionActResponse`. ## Immutability @@ -149,15 +153,19 @@ The default client is synchronous. To switch to asynchronous execution, call the ```java import com.browserbase.api.client.StagehandClient; import com.browserbase.api.client.okhttp.StagehandOkHttpClient; -import com.browserbase.api.models.sessions.SessionStartParams; -import com.browserbase.api.models.sessions.SessionStartResponse; +import com.browserbase.api.models.sessions.SessionActParams; +import com.browserbase.api.models.sessions.SessionActResponse; import java.util.concurrent.CompletableFuture; // Configures using the `stagehand.browserbaseApiKey`, `stagehand.browserbaseProjectId`, `stagehand.modelApiKey` and `stagehand.baseUrl` system properties // Or configures using the `BROWSERBASE_API_KEY`, `BROWSERBASE_PROJECT_ID`, `MODEL_API_KEY` and `STAGEHAND_BASE_URL` environment variables StagehandClient client = StagehandOkHttpClient.fromEnv(); -CompletableFuture response = client.async().sessions().start(); +SessionActParams params = SessionActParams.builder() + .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") + .input("Click the login button") + .build(); +CompletableFuture response = client.async().sessions().act(params); ``` Or create an asynchronous client from the beginning: @@ -165,15 +173,19 @@ Or create an asynchronous client from the beginning: ```java import com.browserbase.api.client.StagehandClientAsync; import com.browserbase.api.client.okhttp.StagehandOkHttpClientAsync; -import com.browserbase.api.models.sessions.SessionStartParams; -import com.browserbase.api.models.sessions.SessionStartResponse; +import com.browserbase.api.models.sessions.SessionActParams; +import com.browserbase.api.models.sessions.SessionActResponse; import java.util.concurrent.CompletableFuture; // Configures using the `stagehand.browserbaseApiKey`, `stagehand.browserbaseProjectId`, `stagehand.modelApiKey` and `stagehand.baseUrl` system properties // Or configures using the `BROWSERBASE_API_KEY`, `BROWSERBASE_PROJECT_ID`, `MODEL_API_KEY` and `STAGEHAND_BASE_URL` environment variables StagehandClientAsync client = StagehandOkHttpClientAsync.fromEnv(); -CompletableFuture response = client.sessions().start(); +SessionActParams params = SessionActParams.builder() + .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") + .input("Click the login button") + .build(); +CompletableFuture response = client.sessions().act(params); ``` The asynchronous client supports the same options as the synchronous one, except most methods return `CompletableFuture`s. @@ -187,10 +199,14 @@ To access this data, prefix any HTTP method call on a client or service with `wi ```java import com.browserbase.api.core.http.Headers; import com.browserbase.api.core.http.HttpResponseFor; -import com.browserbase.api.models.sessions.SessionStartParams; -import com.browserbase.api.models.sessions.SessionStartResponse; +import com.browserbase.api.models.sessions.SessionActParams; +import com.browserbase.api.models.sessions.SessionActResponse; -HttpResponseFor response = client.sessions().withRawResponse().start(); +SessionActParams params = SessionActParams.builder() + .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") + .input("Click the login button") + .build(); +HttpResponseFor response = client.sessions().withRawResponse().act(params); int statusCode = response.statusCode(); Headers headers = response.headers(); @@ -199,9 +215,9 @@ Headers headers = response.headers(); You can still deserialize the response into an instance of a Java class if needed: ```java -import com.browserbase.api.models.sessions.SessionStartResponse; +import com.browserbase.api.models.sessions.SessionActResponse; -SessionStartResponse parsedResponse = response.parse(); +SessionActResponse parsedResponse = response.parse(); ``` ## Error handling @@ -297,9 +313,11 @@ Requests time out after 1 minute by default. To set a custom timeout, configure the method call using the `timeout` method: ```java -import com.browserbase.api.models.sessions.SessionStartResponse; +import com.browserbase.api.models.sessions.SessionActResponse; -SessionStartResponse response = client.sessions().start(RequestOptions.builder().timeout(Duration.ofSeconds(30)).build()); +SessionActResponse response = client.sessions().act( + params, RequestOptions.builder().timeout(Duration.ofSeconds(30)).build() +); ``` Or configure the default for all method calls at the client level: @@ -402,9 +420,9 @@ To set undocumented parameters, call the `putAdditionalHeader`, `putAdditionalQu ```java import com.browserbase.api.core.JsonValue; -import com.browserbase.api.models.sessions.SessionStartParams; +import com.browserbase.api.models.sessions.SessionActParams; -SessionStartParams params = SessionStartParams.builder() +SessionActParams params = SessionActParams.builder() .putAdditionalHeader("Secret-Header", "42") .putAdditionalQueryParam("secret_query_param", "42") .putAdditionalBodyProperty("secretProperty", JsonValue.from("42")) @@ -413,12 +431,29 @@ SessionStartParams params = SessionStartParams.builder() These can be accessed on the built object later using the `_additionalHeaders()`, `_additionalQueryParams()`, and `_additionalBodyProperties()` methods. +To set undocumented parameters on _nested_ headers, query params, or body classes, call the `putAdditionalProperty` method on the nested class: + +```java +import com.browserbase.api.core.JsonValue; +import com.browserbase.api.models.sessions.SessionActParams; + +SessionActParams params = SessionActParams.builder() + .options(SessionActParams.Options.builder() + .putAdditionalProperty("secretProperty", JsonValue.from("42")) + .build()) + .build(); +``` + +These properties can be accessed on the nested built object later using the `_additionalProperties()` method. + To set a documented parameter or property to an undocumented or not yet supported _value_, pass a [`JsonValue`](stagehand-java-core/src/main/kotlin/com/browserbase/api/core/Values.kt) object to its setter: ```java -import com.browserbase.api.models.sessions.SessionStartParams; +import com.browserbase.api.models.sessions.SessionActParams; -SessionStartParams params = SessionStartParams.builder().build(); +SessionActParams params = SessionActParams.builder() + .input("Click the login button") + .build(); ``` The most straightforward way to create a [`JsonValue`](stagehand-java-core/src/main/kotlin/com/browserbase/api/core/Values.kt) is using its `from(...)` method: @@ -467,9 +502,9 @@ To forcibly omit a required parameter or property, pass [`JsonMissing`](stagehan ```java import com.browserbase.api.core.JsonMissing; import com.browserbase.api.models.sessions.SessionActParams; -import com.browserbase.api.models.sessions.SessionStartParams; -SessionStartParams params = SessionActParams.builder() +SessionActParams params = SessionActParams.builder() + .input("Click the login button") .id(JsonMissing.of()) .build(); ``` @@ -482,7 +517,7 @@ To access undocumented response properties, call the `_additionalProperties()` m import com.browserbase.api.core.JsonValue; import java.util.Map; -Map additionalProperties = client.sessions().start(params)._additionalProperties(); +Map additionalProperties = client.sessions().act(params)._additionalProperties(); JsonValue secretPropertyValue = additionalProperties.get("secretProperty"); String result = secretPropertyValue.accept(new JsonValue.Visitor<>() { @@ -510,21 +545,22 @@ To access a property's raw JSON value, which may be undocumented, call its `_` p ```java import com.browserbase.api.core.JsonField; +import com.browserbase.api.models.sessions.SessionActParams; import java.util.Optional; -JsonField field = client.sessions().start(params)._field(); +JsonField input = client.sessions().act(params)._input(); -if (field.isMissing()) { +if (input.isMissing()) { // The property is absent from the JSON response -} else if (field.isNull()) { +} else if (input.isNull()) { // The property was set to literal null } else { // Check if value was provided as a string // Other methods include `asNumber()`, `asBoolean()`, etc. - Optional jsonString = field.asString(); + Optional jsonString = input.asString(); // Try to deserialize into a custom type - MyClass myObject = field.asUnknown().orElseThrow().convert(MyClass.class); + MyClass myObject = input.asUnknown().orElseThrow().convert(MyClass.class); } ``` @@ -537,17 +573,19 @@ By default, the SDK will not throw an exception in this case. It will throw [`St If you would prefer to check that the response is completely well-typed upfront, then either call `validate()`: ```java -import com.browserbase.api.models.sessions.SessionStartResponse; +import com.browserbase.api.models.sessions.SessionActResponse; -SessionStartResponse response = client.sessions().start(params).validate(); +SessionActResponse response = client.sessions().act(params).validate(); ``` Or configure the method call to validate the response using the `responseValidation` method: ```java -import com.browserbase.api.models.sessions.SessionStartResponse; +import com.browserbase.api.models.sessions.SessionActResponse; -SessionStartResponse response = client.sessions().start(RequestOptions.builder().responseValidation(true).build()); +SessionActResponse response = client.sessions().act( + params, RequestOptions.builder().responseValidation(true).build() +); ``` Or configure the default for all method calls at the client level: diff --git a/buildSrc/src/main/kotlin/stagehand.publish.gradle.kts b/buildSrc/src/main/kotlin/stagehand.publish.gradle.kts index 7b0ce3f..796aad4 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]. 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!") + description.set("Stagehand SDK for AI browser automation [ALPHA].") url.set("https://docs.stagehand.dev") licenses { diff --git a/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionActParams.kt b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionActParams.kt index 9992e1f..7e98b5d 100644 --- a/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionActParams.kt +++ b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionActParams.kt @@ -2,11 +2,36 @@ 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 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 import com.browserbase.api.core.http.QueryParams +import com.browserbase.api.core.toImmutable +import com.browserbase.api.errors.StagehandInvalidDataException +import com.fasterxml.jackson.annotation.JsonAnyGetter +import com.fasterxml.jackson.annotation.JsonAnySetter +import com.fasterxml.jackson.annotation.JsonCreator +import com.fasterxml.jackson.annotation.JsonProperty +import com.fasterxml.jackson.core.JsonGenerator +import com.fasterxml.jackson.core.ObjectCodec +import com.fasterxml.jackson.databind.JsonNode +import com.fasterxml.jackson.databind.SerializerProvider +import com.fasterxml.jackson.databind.annotation.JsonDeserialize +import com.fasterxml.jackson.databind.annotation.JsonSerialize +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import java.time.OffsetDateTime +import java.time.format.DateTimeFormatter +import java.util.Collections import java.util.Objects import java.util.Optional import kotlin.jvm.optionals.getOrNull @@ -14,27 +39,75 @@ import kotlin.jvm.optionals.getOrNull /** Executes a browser action using natural language instructions or a predefined Action object. */ class SessionActParams private constructor( - private val id: JsonValue?, - private val xLanguage: JsonValue?, - private val xSdkVersion: JsonValue?, - private val xSentAt: JsonValue?, - private val xStreamResponse: JsonValue?, - private val body: JsonValue, + private val id: String?, + private val xLanguage: XLanguage?, + private val xSdkVersion: String?, + private val xSentAt: OffsetDateTime?, + private val xStreamResponse: XStreamResponse?, + private val body: Body, private val additionalHeaders: Headers, private val additionalQueryParams: QueryParams, ) : Params { - fun id(): Optional = Optional.ofNullable(id) + /** Unique session identifier */ + fun id(): Optional = Optional.ofNullable(id) - fun xLanguage(): Optional = Optional.ofNullable(xLanguage) + /** Client SDK language */ + fun xLanguage(): Optional = Optional.ofNullable(xLanguage) - fun xSdkVersion(): Optional = Optional.ofNullable(xSdkVersion) + /** Version of the Stagehand SDK */ + fun xSdkVersion(): Optional = Optional.ofNullable(xSdkVersion) - fun xSentAt(): Optional = Optional.ofNullable(xSentAt) + /** ISO timestamp when request was sent */ + fun xSentAt(): Optional = Optional.ofNullable(xSentAt) - fun xStreamResponse(): Optional = Optional.ofNullable(xStreamResponse) + /** Whether to stream the response via SSE */ + fun xStreamResponse(): Optional = Optional.ofNullable(xStreamResponse) - fun body(): JsonValue = body + /** + * Natural language instruction or Action object + * + * @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 input(): Input = body.input() + + /** + * Target frame ID for the action + * + * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun frameId(): Optional = body.frameId() + + /** + * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun options(): Optional = body.options() + + /** + * Returns the raw JSON value of [input]. + * + * Unlike [input], this method doesn't throw if the JSON field has an unexpected type. + */ + fun _input(): JsonField = body._input() + + /** + * Returns the raw JSON value of [frameId]. + * + * Unlike [frameId], this method doesn't throw if the JSON field has an unexpected type. + */ + fun _frameId(): JsonField = body._frameId() + + /** + * Returns the raw JSON value of [options]. + * + * Unlike [options], this method doesn't throw if the JSON field has an unexpected type. + */ + fun _options(): JsonField = body._options() + + fun _additionalBodyProperties(): Map = body._additionalProperties() /** Additional headers to send with the request. */ fun _additionalHeaders(): Headers = additionalHeaders @@ -46,21 +119,26 @@ private constructor( companion object { - @JvmStatic fun none(): SessionActParams = builder().build() - - /** Returns a mutable builder for constructing an instance of [SessionActParams]. */ + /** + * Returns a mutable builder for constructing an instance of [SessionActParams]. + * + * The following fields are required: + * ```java + * .input() + * ``` + */ @JvmStatic fun builder() = Builder() } /** A builder for [SessionActParams]. */ class Builder internal constructor() { - private var id: JsonValue? = null - private var xLanguage: JsonValue? = null - private var xSdkVersion: JsonValue? = null - private var xSentAt: JsonValue? = null - private var xStreamResponse: JsonValue? = null - private var body: JsonValue = JsonMissing.of() + private var id: String? = null + private var xLanguage: XLanguage? = null + private var xSdkVersion: String? = null + private var xSentAt: OffsetDateTime? = null + private var xStreamResponse: XStreamResponse? = null + private var body: Body.Builder = Body.builder() private var additionalHeaders: Headers.Builder = Headers.builder() private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() @@ -71,40 +149,111 @@ private constructor( xSdkVersion = sessionActParams.xSdkVersion xSentAt = sessionActParams.xSentAt xStreamResponse = sessionActParams.xStreamResponse - body = sessionActParams.body + body = sessionActParams.body.toBuilder() additionalHeaders = sessionActParams.additionalHeaders.toBuilder() additionalQueryParams = sessionActParams.additionalQueryParams.toBuilder() } - fun id(id: JsonValue?) = apply { this.id = id } + /** Unique session identifier */ + fun id(id: String?) = apply { this.id = id } /** Alias for calling [Builder.id] with `id.orElse(null)`. */ - fun id(id: Optional) = id(id.getOrNull()) + fun id(id: Optional) = id(id.getOrNull()) - fun xLanguage(xLanguage: JsonValue?) = apply { this.xLanguage = xLanguage } + /** Client SDK language */ + fun xLanguage(xLanguage: XLanguage?) = apply { this.xLanguage = xLanguage } /** Alias for calling [Builder.xLanguage] with `xLanguage.orElse(null)`. */ - fun xLanguage(xLanguage: Optional) = xLanguage(xLanguage.getOrNull()) + fun xLanguage(xLanguage: Optional) = xLanguage(xLanguage.getOrNull()) - fun xSdkVersion(xSdkVersion: JsonValue?) = apply { this.xSdkVersion = xSdkVersion } + /** Version of the Stagehand SDK */ + fun xSdkVersion(xSdkVersion: String?) = apply { this.xSdkVersion = xSdkVersion } /** Alias for calling [Builder.xSdkVersion] with `xSdkVersion.orElse(null)`. */ - fun xSdkVersion(xSdkVersion: Optional) = xSdkVersion(xSdkVersion.getOrNull()) + fun xSdkVersion(xSdkVersion: Optional) = xSdkVersion(xSdkVersion.getOrNull()) - fun xSentAt(xSentAt: JsonValue?) = apply { this.xSentAt = xSentAt } + /** ISO timestamp when request was sent */ + fun xSentAt(xSentAt: OffsetDateTime?) = apply { this.xSentAt = xSentAt } /** Alias for calling [Builder.xSentAt] with `xSentAt.orElse(null)`. */ - fun xSentAt(xSentAt: Optional) = xSentAt(xSentAt.getOrNull()) + fun xSentAt(xSentAt: Optional) = xSentAt(xSentAt.getOrNull()) - fun xStreamResponse(xStreamResponse: JsonValue?) = apply { + /** Whether to stream the response via SSE */ + fun xStreamResponse(xStreamResponse: XStreamResponse?) = apply { this.xStreamResponse = xStreamResponse } /** Alias for calling [Builder.xStreamResponse] with `xStreamResponse.orElse(null)`. */ - fun xStreamResponse(xStreamResponse: Optional) = + fun xStreamResponse(xStreamResponse: Optional) = xStreamResponse(xStreamResponse.getOrNull()) - fun body(body: JsonValue) = apply { this.body = body } + /** + * Sets the entire request body. + * + * This is generally only useful if you are already constructing the body separately. + * Otherwise, it's more convenient to use the top-level setters instead: + * - [input] + * - [frameId] + * - [options] + */ + fun body(body: Body) = apply { this.body = body.toBuilder() } + + /** Natural language instruction or Action object */ + fun input(input: Input) = apply { body.input(input) } + + /** + * Sets [Builder.input] to an arbitrary JSON value. + * + * You should usually call [Builder.input] with a well-typed [Input] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun input(input: JsonField) = apply { body.input(input) } + + /** Alias for calling [input] with `Input.ofString(string)`. */ + 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) } + + /** Target frame ID for the action */ + fun frameId(frameId: String) = apply { body.frameId(frameId) } + + /** + * Sets [Builder.frameId] to an arbitrary JSON value. + * + * You should usually call [Builder.frameId] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun frameId(frameId: JsonField) = apply { body.frameId(frameId) } + + fun options(options: Options) = apply { body.options(options) } + + /** + * Sets [Builder.options] to an arbitrary JSON value. + * + * You should usually call [Builder.options] with a well-typed [Options] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun options(options: JsonField) = apply { body.options(options) } + + fun additionalBodyProperties(additionalBodyProperties: Map) = apply { + body.additionalProperties(additionalBodyProperties) + } + + fun putAdditionalBodyProperty(key: String, value: JsonValue) = apply { + body.putAdditionalProperty(key, value) + } + + fun putAllAdditionalBodyProperties(additionalBodyProperties: Map) = + apply { + body.putAllAdditionalProperties(additionalBodyProperties) + } + + fun removeAdditionalBodyProperty(key: String) = apply { body.removeAdditionalProperty(key) } + + fun removeAllAdditionalBodyProperties(keys: Set) = apply { + body.removeAllAdditionalProperties(keys) + } fun additionalHeaders(additionalHeaders: Headers) = apply { this.additionalHeaders.clear() @@ -208,6 +357,13 @@ private constructor( * Returns an immutable instance of [SessionActParams]. * * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .input() + * ``` + * + * @throws IllegalStateException if any required field is unset. */ fun build(): SessionActParams = SessionActParams( @@ -216,24 +372,1341 @@ private constructor( xSdkVersion, xSentAt, xStreamResponse, - body, + body.build(), additionalHeaders.build(), additionalQueryParams.build(), ) } - fun _body(): JsonValue = body + fun _body(): Body = body fun _pathParam(index: Int): String = when (index) { - 0 -> id?.toString() ?: "" + 0 -> id ?: "" else -> "" } - override fun _headers(): Headers = Headers.builder().apply { putAll(additionalHeaders) }.build() + override fun _headers(): Headers = + Headers.builder() + .apply { + xLanguage?.let { put("x-language", it.toString()) } + xSdkVersion?.let { put("x-sdk-version", it) } + xSentAt?.let { put("x-sent-at", DateTimeFormatter.ISO_OFFSET_DATE_TIME.format(it)) } + xStreamResponse?.let { put("x-stream-response", it.toString()) } + putAll(additionalHeaders) + } + .build() override fun _queryParams(): QueryParams = additionalQueryParams + class Body + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val input: JsonField, + private val frameId: JsonField, + private val options: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("input") @ExcludeMissing input: JsonField = JsonMissing.of(), + @JsonProperty("frameId") @ExcludeMissing frameId: JsonField = JsonMissing.of(), + @JsonProperty("options") @ExcludeMissing options: JsonField = JsonMissing.of(), + ) : this(input, frameId, options, mutableMapOf()) + + /** + * Natural language instruction or Action object + * + * @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 input(): Input = input.getRequired("input") + + /** + * Target frame ID for the action + * + * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun frameId(): Optional = frameId.getOptional("frameId") + + /** + * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun options(): Optional = options.getOptional("options") + + /** + * Returns the raw JSON value of [input]. + * + * Unlike [input], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("input") @ExcludeMissing fun _input(): JsonField = input + + /** + * Returns the raw JSON value of [frameId]. + * + * Unlike [frameId], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("frameId") @ExcludeMissing fun _frameId(): JsonField = frameId + + /** + * Returns the raw JSON value of [options]. + * + * Unlike [options], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("options") @ExcludeMissing fun _options(): JsonField = options + + @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 [Body]. + * + * The following fields are required: + * ```java + * .input() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Body]. */ + class Builder internal constructor() { + + private var input: JsonField? = null + private var frameId: JsonField = JsonMissing.of() + private var options: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(body: Body) = apply { + input = body.input + frameId = body.frameId + options = body.options + additionalProperties = body.additionalProperties.toMutableMap() + } + + /** Natural language instruction or Action object */ + fun input(input: Input) = input(JsonField.of(input)) + + /** + * Sets [Builder.input] to an arbitrary JSON value. + * + * You should usually call [Builder.input] with a well-typed [Input] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun input(input: JsonField) = apply { this.input = input } + + /** Alias for calling [input] with `Input.ofString(string)`. */ + 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)) + + /** Target frame ID for the action */ + fun frameId(frameId: String) = frameId(JsonField.of(frameId)) + + /** + * Sets [Builder.frameId] to an arbitrary JSON value. + * + * You should usually call [Builder.frameId] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun frameId(frameId: JsonField) = apply { this.frameId = frameId } + + fun options(options: Options) = options(JsonField.of(options)) + + /** + * Sets [Builder.options] to an arbitrary JSON value. + * + * You should usually call [Builder.options] with a well-typed [Options] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun options(options: JsonField) = apply { this.options = options } + + 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 [Body]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .input() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): Body = + Body( + checkRequired("input", input), + frameId, + options, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): Body = apply { + if (validated) { + return@apply + } + + input().validate() + frameId() + options().ifPresent { it.validate() } + 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. + */ + @JvmSynthetic + internal fun validity(): Int = + (input.asKnown().getOrNull()?.validity() ?: 0) + + (if (frameId.asKnown().isPresent) 1 else 0) + + (options.asKnown().getOrNull()?.validity() ?: 0) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Body && + input == other.input && + frameId == other.frameId && + options == other.options && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(input, frameId, options, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Body{input=$input, frameId=$frameId, options=$options, additionalProperties=$additionalProperties}" + } + + /** Natural language instruction or Action object */ + @JsonDeserialize(using = Input.Deserializer::class) + @JsonSerialize(using = Input.Serializer::class) + class Input + private constructor( + private val string: String? = null, + private val action: ActionInput? = null, + private val _json: JsonValue? = null, + ) { + + fun string(): Optional = Optional.ofNullable(string) + + /** Action object returned by observe and used by act */ + fun action(): Optional = Optional.ofNullable(action) + + fun isString(): Boolean = string != null + + fun isAction(): Boolean = action != null + + fun asString(): String = string.getOrThrow("string") + + /** Action object returned by observe and used by act */ + fun asAction(): ActionInput = action.getOrThrow("action") + + fun _json(): Optional = Optional.ofNullable(_json) + + fun accept(visitor: Visitor): T = + when { + string != null -> visitor.visitString(string) + action != null -> visitor.visitAction(action) + else -> visitor.unknown(_json) + } + + private var validated: Boolean = false + + fun validate(): Input = apply { + if (validated) { + return@apply + } + + accept( + object : Visitor { + override fun visitString(string: String) {} + + override fun visitAction(action: ActionInput) { + action.validate() + } + } + ) + 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. + */ + @JvmSynthetic + internal fun validity(): Int = + accept( + object : Visitor { + override fun visitString(string: String) = 1 + + override fun visitAction(action: ActionInput) = action.validity() + + override fun unknown(json: JsonValue?) = 0 + } + ) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Input && string == other.string && action == other.action + } + + override fun hashCode(): Int = Objects.hash(string, action) + + override fun toString(): String = + when { + string != null -> "Input{string=$string}" + action != null -> "Input{action=$action}" + _json != null -> "Input{_unknown=$_json}" + else -> throw IllegalStateException("Invalid Input") + } + + companion object { + + @JvmStatic fun ofString(string: String) = Input(string = string) + + /** Action object returned by observe and used by act */ + @JvmStatic fun ofAction(action: ActionInput) = Input(action = action) + } + + /** An interface that defines how to map each variant of [Input] to a value of type [T]. */ + interface Visitor { + + fun visitString(string: String): T + + /** Action object returned by observe and used by act */ + fun visitAction(action: ActionInput): T + + /** + * Maps an unknown variant of [Input] to a value of type [T]. + * + * An instance of [Input] can contain an unknown variant if it was deserialized from + * data that doesn't match any known variant. For example, if the SDK is on an older + * version than the API, then the API may respond with new variants that the SDK is + * unaware of. + * + * @throws StagehandInvalidDataException in the default implementation. + */ + fun unknown(json: JsonValue?): T { + throw StagehandInvalidDataException("Unknown Input: $json") + } + } + + internal class Deserializer : BaseDeserializer(Input::class) { + + override fun ObjectCodec.deserialize(node: JsonNode): Input { + val json = JsonValue.fromJsonNode(node) + + val bestMatches = + sequenceOf( + tryDeserialize(node, jacksonTypeRef())?.let { + Input(action = it, _json = json) + }, + tryDeserialize(node, jacksonTypeRef())?.let { + Input(string = it, _json = json) + }, + ) + .filterNotNull() + .allMaxBy { it.validity() } + .toList() + return when (bestMatches.size) { + // This can happen if what we're deserializing is completely incompatible with + // all the possible variants (e.g. deserializing from array). + 0 -> Input(_json = json) + 1 -> bestMatches.single() + // If there's more than one match with the highest validity, then use the first + // completely valid match, or simply the first match if none are completely + // valid. + else -> bestMatches.firstOrNull { it.isValid() } ?: bestMatches.first() + } + } + } + + internal class Serializer : BaseSerializer(Input::class) { + + override fun serialize( + value: Input, + generator: JsonGenerator, + provider: SerializerProvider, + ) { + when { + value.string != null -> generator.writeObject(value.string) + value.action != null -> generator.writeObject(value.action) + value._json != null -> generator.writeObject(value._json) + else -> throw IllegalStateException("Invalid Input") + } + } + } + + /** 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(): Optional> = arguments.getOptional("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(): Optional = method.getOptional("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: + * ```java + * .description() + * .selector() + * ``` + */ + @JvmStatic 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() + + @JvmSynthetic + 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: + * ```java + * .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. + */ + @JvmSynthetic + internal fun validity(): Int = + (if (description.asKnown().isPresent) 1 else 0) + + (if (selector.asKnown().isPresent) 1 else 0) + + (arguments.asKnown().getOrNull()?.size ?: 0) + + (if (method.asKnown().isPresent) 1 else 0) + + 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 + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val model: JsonField, + private val timeout: JsonField, + private val variables: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("model") @ExcludeMissing model: JsonField = JsonMissing.of(), + @JsonProperty("timeout") @ExcludeMissing timeout: JsonField = JsonMissing.of(), + @JsonProperty("variables") + @ExcludeMissing + variables: JsonField = JsonMissing.of(), + ) : this(model, timeout, variables, mutableMapOf()) + + /** + * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun model(): Optional = model.getOptional("model") + + /** + * Timeout in ms for the action + * + * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun timeout(): Optional = timeout.getOptional("timeout") + + /** + * Variables to substitute in the action instruction + * + * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun variables(): Optional = variables.getOptional("variables") + + /** + * Returns the raw JSON value of [model]. + * + * Unlike [model], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("model") @ExcludeMissing fun _model(): JsonField = model + + /** + * Returns the raw JSON value of [timeout]. + * + * Unlike [timeout], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("timeout") @ExcludeMissing fun _timeout(): JsonField = timeout + + /** + * Returns the raw JSON value of [variables]. + * + * Unlike [variables], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("variables") + @ExcludeMissing + fun _variables(): JsonField = variables + + @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 [Options]. */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Options]. */ + class Builder internal constructor() { + + private var model: JsonField = JsonMissing.of() + private var timeout: JsonField = JsonMissing.of() + private var variables: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(options: Options) = apply { + model = options.model + timeout = options.timeout + variables = options.variables + additionalProperties = options.additionalProperties.toMutableMap() + } + + fun model(model: ModelConfig) = model(JsonField.of(model)) + + /** + * Sets [Builder.model] to an arbitrary JSON value. + * + * You should usually call [Builder.model] with a well-typed [ModelConfig] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + 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.ofUnionMember1(unionMember1)`. */ + fun model(unionMember1: ModelConfig.UnionMember1) = + model(ModelConfig.ofUnionMember1(unionMember1)) + + /** Timeout in ms for the action */ + fun timeout(timeout: Double) = timeout(JsonField.of(timeout)) + + /** + * Sets [Builder.timeout] to an arbitrary JSON value. + * + * You should usually call [Builder.timeout] with a well-typed [Double] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun timeout(timeout: JsonField) = apply { this.timeout = timeout } + + /** Variables to substitute in the action instruction */ + fun variables(variables: Variables) = variables(JsonField.of(variables)) + + /** + * Sets [Builder.variables] to an arbitrary JSON value. + * + * You should usually call [Builder.variables] with a well-typed [Variables] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun variables(variables: JsonField) = apply { this.variables = variables } + + 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 [Options]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): Options = + Options(model, timeout, variables, additionalProperties.toMutableMap()) + } + + private var validated: Boolean = false + + fun validate(): Options = apply { + if (validated) { + return@apply + } + + model().ifPresent { it.validate() } + timeout() + variables().ifPresent { it.validate() } + 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. + */ + @JvmSynthetic + internal fun validity(): Int = + (model.asKnown().getOrNull()?.validity() ?: 0) + + (if (timeout.asKnown().isPresent) 1 else 0) + + (variables.asKnown().getOrNull()?.validity() ?: 0) + + /** Variables to substitute in the action instruction */ + class Variables + @JsonCreator + private constructor( + @com.fasterxml.jackson.annotation.JsonValue + private val additionalProperties: Map + ) { + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = additionalProperties + + fun toBuilder() = Builder().from(this) + + companion object { + + /** Returns a mutable builder for constructing an instance of [Variables]. */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Variables]. */ + class Builder internal constructor() { + + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(variables: Variables) = apply { + additionalProperties = variables.additionalProperties.toMutableMap() + } + + 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 [Variables]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): Variables = Variables(additionalProperties.toImmutable()) + } + + private var validated: Boolean = false + + fun validate(): Variables = apply { + if (validated) { + return@apply + } + + 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. + */ + @JvmSynthetic + internal fun validity(): Int = + additionalProperties.count { (_, value) -> !value.isNull() && !value.isMissing() } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Variables && additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { Objects.hash(additionalProperties) } + + override fun hashCode(): Int = hashCode + + override fun toString() = "Variables{additionalProperties=$additionalProperties}" + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Options && + model == other.model && + timeout == other.timeout && + variables == other.variables && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(model, timeout, variables, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Options{model=$model, timeout=$timeout, variables=$variables, additionalProperties=$additionalProperties}" + } + + /** Client SDK language */ + class XLanguage @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 { + + @JvmField val TYPESCRIPT = of("typescript") + + @JvmField val PYTHON = of("python") + + @JvmField val PLAYGROUND = of("playground") + + @JvmStatic fun of(value: String) = XLanguage(JsonField.of(value)) + } + + /** An enum containing [XLanguage]'s known values. */ + enum class Known { + TYPESCRIPT, + PYTHON, + PLAYGROUND, + } + + /** + * An enum containing [XLanguage]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [XLanguage] 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 { + TYPESCRIPT, + PYTHON, + PLAYGROUND, + /** + * An enum member indicating that [XLanguage] 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) { + TYPESCRIPT -> Value.TYPESCRIPT + PYTHON -> Value.PYTHON + PLAYGROUND -> Value.PLAYGROUND + 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) { + TYPESCRIPT -> Known.TYPESCRIPT + PYTHON -> Known.PYTHON + PLAYGROUND -> Known.PLAYGROUND + else -> throw StagehandInvalidDataException("Unknown XLanguage: $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().orElseThrow { + StagehandInvalidDataException("Value is not a String") + } + + private var validated: Boolean = false + + fun validate(): XLanguage = 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. + */ + @JvmSynthetic 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 XLanguage && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + /** Whether to stream the response via SSE */ + class XStreamResponse @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 { + + @JvmField val TRUE = of("true") + + @JvmField val FALSE = of("false") + + @JvmStatic fun of(value: String) = XStreamResponse(JsonField.of(value)) + } + + /** An enum containing [XStreamResponse]'s known values. */ + enum class Known { + TRUE, + FALSE, + } + + /** + * An enum containing [XStreamResponse]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [XStreamResponse] 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, + FALSE, + /** + * An enum member indicating that [XStreamResponse] 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 + FALSE -> Value.FALSE + 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 + FALSE -> Known.FALSE + else -> throw StagehandInvalidDataException("Unknown XStreamResponse: $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().orElseThrow { + StagehandInvalidDataException("Value is not a String") + } + + private var validated: Boolean = false + + fun validate(): XStreamResponse = 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. + */ + @JvmSynthetic 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 XStreamResponse && 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-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionActResponse.kt b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionActResponse.kt index 57b8827..bfa1f65 100644 --- a/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionActResponse.kt +++ b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionActResponse.kt @@ -2,20 +2,63 @@ 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 import com.browserbase.api.core.JsonValue +import com.browserbase.api.core.checkKnown +import com.browserbase.api.core.checkRequired +import com.browserbase.api.core.toImmutable import com.browserbase.api.errors.StagehandInvalidDataException import com.fasterxml.jackson.annotation.JsonAnyGetter import com.fasterxml.jackson.annotation.JsonAnySetter import com.fasterxml.jackson.annotation.JsonCreator +import com.fasterxml.jackson.annotation.JsonProperty import java.util.Collections import java.util.Objects +import java.util.Optional +import kotlin.jvm.optionals.getOrNull class SessionActResponse @JsonCreator(mode = JsonCreator.Mode.DISABLED) -private constructor(private val additionalProperties: MutableMap) { +private constructor( + private val data: JsonField, + private val success: JsonField, + private val additionalProperties: MutableMap, +) { - @JsonCreator private constructor() : this(mutableMapOf()) + @JsonCreator + private constructor( + @JsonProperty("data") @ExcludeMissing data: JsonField = JsonMissing.of(), + @JsonProperty("success") @ExcludeMissing success: JsonField = JsonMissing.of(), + ) : this(data, success, mutableMapOf()) + + /** + * @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 data(): Data = data.getRequired("data") + + /** + * @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") + + /** + * Returns the raw JSON value of [data]. + * + * Unlike [data], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("data") @ExcludeMissing fun _data(): JsonField = data + + /** + * 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 @JsonAnySetter private fun putAdditionalProperty(key: String, value: JsonValue) { @@ -31,20 +74,52 @@ private constructor(private val additionalProperties: MutableMap? = null + private var success: JsonField? = null private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic internal fun from(sessionActResponse: SessionActResponse) = apply { + data = sessionActResponse.data + success = sessionActResponse.success additionalProperties = sessionActResponse.additionalProperties.toMutableMap() } + fun data(data: Data) = data(JsonField.of(data)) + + /** + * Sets [Builder.data] to an arbitrary JSON value. + * + * You should usually call [Builder.data] with a well-typed [Data] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun data(data: JsonField) = apply { this.data = data } + + fun success(success: Success) = 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 + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun success(success: JsonField) = apply { this.success = success } + fun additionalProperties(additionalProperties: Map) = apply { this.additionalProperties.clear() putAllAdditionalProperties(additionalProperties) @@ -68,8 +143,21 @@ private constructor(private val additionalProperties: MutableMap, + private val actionId: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("result") @ExcludeMissing result: JsonField = JsonMissing.of(), + @JsonProperty("actionId") @ExcludeMissing actionId: JsonField = JsonMissing.of(), + ) : this(result, actionId, mutableMapOf()) + + /** + * @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 result(): Result = result.getRequired("result") + + /** + * Action ID for tracking + * + * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun actionId(): Optional = actionId.getOptional("actionId") + + /** + * Returns the raw JSON value of [result]. + * + * Unlike [result], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("result") @ExcludeMissing fun _result(): JsonField = result + + /** + * Returns the raw JSON value of [actionId]. + * + * Unlike [actionId], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("actionId") @ExcludeMissing fun _actionId(): JsonField = actionId + + @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 [Data]. + * + * The following fields are required: + * ```java + * .result() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Data]. */ + class Builder internal constructor() { + + private var result: JsonField? = null + private var actionId: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(data: Data) = apply { + result = data.result + actionId = data.actionId + additionalProperties = data.additionalProperties.toMutableMap() + } + + fun result(result: Result) = result(JsonField.of(result)) + + /** + * Sets [Builder.result] to an arbitrary JSON value. + * + * You should usually call [Builder.result] with a well-typed [Result] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun result(result: JsonField) = apply { this.result = result } + + /** Action ID for tracking */ + fun actionId(actionId: String) = actionId(JsonField.of(actionId)) + + /** + * Sets [Builder.actionId] to an arbitrary JSON value. + * + * You should usually call [Builder.actionId] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun actionId(actionId: JsonField) = apply { this.actionId = actionId } + + 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 [Data]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .result() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): Data = + Data(checkRequired("result", result), actionId, additionalProperties.toMutableMap()) + } + + private var validated: Boolean = false + + fun validate(): Data = apply { + if (validated) { + return@apply + } + + result().validate() + actionId() + 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. + */ + @JvmSynthetic + internal fun validity(): Int = + (result.asKnown().getOrNull()?.validity() ?: 0) + + (if (actionId.asKnown().isPresent) 1 else 0) + + class Result + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val actionDescription: JsonField, + private val actions: JsonField>, + private val message: JsonField, + private val success: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("actionDescription") + @ExcludeMissing + actionDescription: JsonField = JsonMissing.of(), + @JsonProperty("actions") + @ExcludeMissing + actions: JsonField> = JsonMissing.of(), + @JsonProperty("message") + @ExcludeMissing + message: JsonField = JsonMissing.of(), + @JsonProperty("success") + @ExcludeMissing + success: JsonField = JsonMissing.of(), + ) : this(actionDescription, actions, message, success, mutableMapOf()) + + /** + * Description of the action that was performed + * + * @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 actionDescription(): String = actionDescription.getRequired("actionDescription") + + /** + * List of actions that were executed + * + * @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 actions(): List = actions.getRequired("actions") + + /** + * Human-readable result message + * + * @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 message(): String = message.getRequired("message") + + /** + * Whether the action completed successfully + * + * @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(): Boolean = success.getRequired("success") + + /** + * Returns the raw JSON value of [actionDescription]. + * + * Unlike [actionDescription], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("actionDescription") + @ExcludeMissing + fun _actionDescription(): JsonField = actionDescription + + /** + * Returns the raw JSON value of [actions]. + * + * Unlike [actions], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("actions") + @ExcludeMissing + fun _actions(): JsonField> = actions + + /** + * Returns the raw JSON value of [message]. + * + * Unlike [message], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("message") @ExcludeMissing fun _message(): JsonField = message + + /** + * 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 + + @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 [Result]. + * + * The following fields are required: + * ```java + * .actionDescription() + * .actions() + * .message() + * .success() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Result]. */ + class Builder internal constructor() { + + private var actionDescription: JsonField? = null + private var actions: JsonField>? = null + private var message: JsonField? = null + private var success: JsonField? = null + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(result: Result) = apply { + actionDescription = result.actionDescription + actions = result.actions.map { it.toMutableList() } + message = result.message + success = result.success + additionalProperties = result.additionalProperties.toMutableMap() + } + + /** Description of the action that was performed */ + fun actionDescription(actionDescription: String) = + actionDescription(JsonField.of(actionDescription)) + + /** + * Sets [Builder.actionDescription] to an arbitrary JSON value. + * + * You should usually call [Builder.actionDescription] with a well-typed [String] + * value instead. This method is primarily for setting the field to an undocumented + * or not yet supported value. + */ + fun actionDescription(actionDescription: JsonField) = apply { + this.actionDescription = actionDescription + } + + /** List of actions that were executed */ + fun actions(actions: List) = actions(JsonField.of(actions)) + + /** + * Sets [Builder.actions] to an arbitrary JSON value. + * + * You should usually call [Builder.actions] with a well-typed `List` value + * instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun actions(actions: JsonField>) = apply { + this.actions = actions.map { it.toMutableList() } + } + + /** + * Adds a single [Action] to [actions]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addAction(action: Action) = apply { + actions = + (actions ?: JsonField.of(mutableListOf())).also { + checkKnown("actions", it).add(action) + } + } + + /** Human-readable result message */ + fun message(message: String) = message(JsonField.of(message)) + + /** + * Sets [Builder.message] to an arbitrary JSON value. + * + * You should usually call [Builder.message] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun message(message: JsonField) = apply { this.message = message } + + /** Whether the action completed successfully */ + 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 [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 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 [Result]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .actionDescription() + * .actions() + * .message() + * .success() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): Result = + Result( + checkRequired("actionDescription", actionDescription), + checkRequired("actions", actions).map { it.toImmutable() }, + checkRequired("message", message), + checkRequired("success", success), + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): Result = apply { + if (validated) { + return@apply + } + + actionDescription() + actions().forEach { it.validate() } + message() + success() + 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. + */ + @JvmSynthetic + internal fun validity(): Int = + (if (actionDescription.asKnown().isPresent) 1 else 0) + + (actions.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + + (if (message.asKnown().isPresent) 1 else 0) + + (if (success.asKnown().isPresent) 1 else 0) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Result && + actionDescription == other.actionDescription && + actions == other.actions && + message == other.message && + success == other.success && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(actionDescription, actions, message, success, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Result{actionDescription=$actionDescription, actions=$actions, message=$message, success=$success, additionalProperties=$additionalProperties}" + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Data && + result == other.result && + actionId == other.actionId && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { Objects.hash(result, actionId, additionalProperties) } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "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 { + + @JvmField val TRUE = of(true) + + @JvmStatic 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().orElseThrow { + 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. + */ + @JvmSynthetic 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 } - return other is SessionActResponse && additionalProperties == other.additionalProperties + return other is SessionActResponse && + data == other.data && + success == other.success && + additionalProperties == other.additionalProperties } - private val hashCode: Int by lazy { Objects.hash(additionalProperties) } + private val hashCode: Int by lazy { Objects.hash(data, success, additionalProperties) } override fun hashCode(): Int = hashCode - override fun toString() = "SessionActResponse{additionalProperties=$additionalProperties}" + override fun toString() = + "SessionActResponse{data=$data, success=$success, additionalProperties=$additionalProperties}" } diff --git a/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionEndParams.kt b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionEndParams.kt index 02f9cb0..90a656f 100644 --- a/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionEndParams.kt +++ b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionEndParams.kt @@ -2,11 +2,17 @@ package com.browserbase.api.models.sessions +import com.browserbase.api.core.Enum +import com.browserbase.api.core.JsonField import com.browserbase.api.core.JsonValue import com.browserbase.api.core.Params import com.browserbase.api.core.http.Headers import com.browserbase.api.core.http.QueryParams import com.browserbase.api.core.toImmutable +import com.browserbase.api.errors.StagehandInvalidDataException +import com.fasterxml.jackson.annotation.JsonCreator +import java.time.OffsetDateTime +import java.time.format.DateTimeFormatter import java.util.Objects import java.util.Optional import kotlin.jvm.optionals.getOrNull @@ -14,25 +20,30 @@ import kotlin.jvm.optionals.getOrNull /** Terminates the browser session and releases all associated resources. */ class SessionEndParams private constructor( - private val id: JsonValue?, - private val xLanguage: JsonValue?, - private val xSdkVersion: JsonValue?, - private val xSentAt: JsonValue?, - private val xStreamResponse: JsonValue?, + private val id: String?, + private val xLanguage: XLanguage?, + private val xSdkVersion: String?, + private val xSentAt: OffsetDateTime?, + private val xStreamResponse: XStreamResponse?, private val additionalHeaders: Headers, private val additionalQueryParams: QueryParams, private val additionalBodyProperties: Map, ) : Params { - fun id(): Optional = Optional.ofNullable(id) + /** Unique session identifier */ + fun id(): Optional = Optional.ofNullable(id) - fun xLanguage(): Optional = Optional.ofNullable(xLanguage) + /** Client SDK language */ + fun xLanguage(): Optional = Optional.ofNullable(xLanguage) - fun xSdkVersion(): Optional = Optional.ofNullable(xSdkVersion) + /** Version of the Stagehand SDK */ + fun xSdkVersion(): Optional = Optional.ofNullable(xSdkVersion) - fun xSentAt(): Optional = Optional.ofNullable(xSentAt) + /** ISO timestamp when request was sent */ + fun xSentAt(): Optional = Optional.ofNullable(xSentAt) - fun xStreamResponse(): Optional = Optional.ofNullable(xStreamResponse) + /** Whether to stream the response via SSE */ + fun xStreamResponse(): Optional = Optional.ofNullable(xStreamResponse) /** Additional body properties to send with the request. */ fun _additionalBodyProperties(): Map = additionalBodyProperties @@ -56,11 +67,11 @@ private constructor( /** A builder for [SessionEndParams]. */ class Builder internal constructor() { - private var id: JsonValue? = null - private var xLanguage: JsonValue? = null - private var xSdkVersion: JsonValue? = null - private var xSentAt: JsonValue? = null - private var xStreamResponse: JsonValue? = null + private var id: String? = null + private var xLanguage: XLanguage? = null + private var xSdkVersion: String? = null + private var xSentAt: OffsetDateTime? = null + private var xStreamResponse: XStreamResponse? = null private var additionalHeaders: Headers.Builder = Headers.builder() private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() private var additionalBodyProperties: MutableMap = mutableMapOf() @@ -77,32 +88,37 @@ private constructor( additionalBodyProperties = sessionEndParams.additionalBodyProperties.toMutableMap() } - fun id(id: JsonValue?) = apply { this.id = id } + /** Unique session identifier */ + fun id(id: String?) = apply { this.id = id } /** Alias for calling [Builder.id] with `id.orElse(null)`. */ - fun id(id: Optional) = id(id.getOrNull()) + fun id(id: Optional) = id(id.getOrNull()) - fun xLanguage(xLanguage: JsonValue?) = apply { this.xLanguage = xLanguage } + /** Client SDK language */ + fun xLanguage(xLanguage: XLanguage?) = apply { this.xLanguage = xLanguage } /** Alias for calling [Builder.xLanguage] with `xLanguage.orElse(null)`. */ - fun xLanguage(xLanguage: Optional) = xLanguage(xLanguage.getOrNull()) + fun xLanguage(xLanguage: Optional) = xLanguage(xLanguage.getOrNull()) - fun xSdkVersion(xSdkVersion: JsonValue?) = apply { this.xSdkVersion = xSdkVersion } + /** Version of the Stagehand SDK */ + fun xSdkVersion(xSdkVersion: String?) = apply { this.xSdkVersion = xSdkVersion } /** Alias for calling [Builder.xSdkVersion] with `xSdkVersion.orElse(null)`. */ - fun xSdkVersion(xSdkVersion: Optional) = xSdkVersion(xSdkVersion.getOrNull()) + fun xSdkVersion(xSdkVersion: Optional) = xSdkVersion(xSdkVersion.getOrNull()) - fun xSentAt(xSentAt: JsonValue?) = apply { this.xSentAt = xSentAt } + /** ISO timestamp when request was sent */ + fun xSentAt(xSentAt: OffsetDateTime?) = apply { this.xSentAt = xSentAt } /** Alias for calling [Builder.xSentAt] with `xSentAt.orElse(null)`. */ - fun xSentAt(xSentAt: Optional) = xSentAt(xSentAt.getOrNull()) + fun xSentAt(xSentAt: Optional) = xSentAt(xSentAt.getOrNull()) - fun xStreamResponse(xStreamResponse: JsonValue?) = apply { + /** Whether to stream the response via SSE */ + fun xStreamResponse(xStreamResponse: XStreamResponse?) = apply { this.xStreamResponse = xStreamResponse } /** Alias for calling [Builder.xStreamResponse] with `xStreamResponse.orElse(null)`. */ - fun xStreamResponse(xStreamResponse: Optional) = + fun xStreamResponse(xStreamResponse: Optional) = xStreamResponse(xStreamResponse.getOrNull()) fun additionalHeaders(additionalHeaders: Headers) = apply { @@ -248,14 +264,291 @@ private constructor( fun _pathParam(index: Int): String = when (index) { - 0 -> id?.toString() ?: "" + 0 -> id ?: "" else -> "" } - override fun _headers(): Headers = Headers.builder().apply { putAll(additionalHeaders) }.build() + override fun _headers(): Headers = + Headers.builder() + .apply { + xLanguage?.let { put("x-language", it.toString()) } + xSdkVersion?.let { put("x-sdk-version", it) } + xSentAt?.let { put("x-sent-at", DateTimeFormatter.ISO_OFFSET_DATE_TIME.format(it)) } + xStreamResponse?.let { put("x-stream-response", it.toString()) } + putAll(additionalHeaders) + } + .build() override fun _queryParams(): QueryParams = additionalQueryParams + /** Client SDK language */ + class XLanguage @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 { + + @JvmField val TYPESCRIPT = of("typescript") + + @JvmField val PYTHON = of("python") + + @JvmField val PLAYGROUND = of("playground") + + @JvmStatic fun of(value: String) = XLanguage(JsonField.of(value)) + } + + /** An enum containing [XLanguage]'s known values. */ + enum class Known { + TYPESCRIPT, + PYTHON, + PLAYGROUND, + } + + /** + * An enum containing [XLanguage]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [XLanguage] 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 { + TYPESCRIPT, + PYTHON, + PLAYGROUND, + /** + * An enum member indicating that [XLanguage] 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) { + TYPESCRIPT -> Value.TYPESCRIPT + PYTHON -> Value.PYTHON + PLAYGROUND -> Value.PLAYGROUND + 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) { + TYPESCRIPT -> Known.TYPESCRIPT + PYTHON -> Known.PYTHON + PLAYGROUND -> Known.PLAYGROUND + else -> throw StagehandInvalidDataException("Unknown XLanguage: $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().orElseThrow { + StagehandInvalidDataException("Value is not a String") + } + + private var validated: Boolean = false + + fun validate(): XLanguage = 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. + */ + @JvmSynthetic 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 XLanguage && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + /** Whether to stream the response via SSE */ + class XStreamResponse @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 { + + @JvmField val TRUE = of("true") + + @JvmField val FALSE = of("false") + + @JvmStatic fun of(value: String) = XStreamResponse(JsonField.of(value)) + } + + /** An enum containing [XStreamResponse]'s known values. */ + enum class Known { + TRUE, + FALSE, + } + + /** + * An enum containing [XStreamResponse]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [XStreamResponse] 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, + FALSE, + /** + * An enum member indicating that [XStreamResponse] 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 + FALSE -> Value.FALSE + 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 + FALSE -> Known.FALSE + else -> throw StagehandInvalidDataException("Unknown XStreamResponse: $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().orElseThrow { + StagehandInvalidDataException("Value is not a String") + } + + private var validated: Boolean = false + + fun validate(): XStreamResponse = 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. + */ + @JvmSynthetic 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 XStreamResponse && 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-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionEndResponse.kt b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionEndResponse.kt index 970e0fd..3bed0ac 100644 --- a/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionEndResponse.kt +++ b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionEndResponse.kt @@ -2,20 +2,45 @@ 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 import com.browserbase.api.core.JsonValue +import com.browserbase.api.core.checkRequired import com.browserbase.api.errors.StagehandInvalidDataException import com.fasterxml.jackson.annotation.JsonAnyGetter import com.fasterxml.jackson.annotation.JsonAnySetter import com.fasterxml.jackson.annotation.JsonCreator +import com.fasterxml.jackson.annotation.JsonProperty import java.util.Collections import java.util.Objects +import kotlin.jvm.optionals.getOrNull class SessionEndResponse @JsonCreator(mode = JsonCreator.Mode.DISABLED) -private constructor(private val additionalProperties: MutableMap) { +private constructor( + private val success: JsonField, + private val additionalProperties: MutableMap, +) { - @JsonCreator private constructor() : this(mutableMapOf()) + @JsonCreator + private constructor( + @JsonProperty("success") @ExcludeMissing success: JsonField = JsonMissing.of() + ) : this(success, mutableMapOf()) + + /** + * @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") + + /** + * 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 @JsonAnySetter private fun putAdditionalProperty(key: String, value: JsonValue) { @@ -31,20 +56,39 @@ private constructor(private val additionalProperties: MutableMap? = null private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic internal fun from(sessionEndResponse: SessionEndResponse) = apply { + success = sessionEndResponse.success additionalProperties = sessionEndResponse.additionalProperties.toMutableMap() } + fun success(success: Success) = 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 + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun success(success: JsonField) = apply { this.success = success } + fun additionalProperties(additionalProperties: Map) = apply { this.additionalProperties.clear() putAllAdditionalProperties(additionalProperties) @@ -68,8 +112,19 @@ private constructor(private val additionalProperties: MutableMap) : 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 { + + @JvmField val TRUE = of(true) + + @JvmStatic 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().orElseThrow { + 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. + */ + @JvmSynthetic 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 } - return other is SessionEndResponse && additionalProperties == other.additionalProperties + return other is SessionEndResponse && + success == other.success && + additionalProperties == other.additionalProperties } - private val hashCode: Int by lazy { Objects.hash(additionalProperties) } + private val hashCode: Int by lazy { Objects.hash(success, additionalProperties) } override fun hashCode(): Int = hashCode - override fun toString() = "SessionEndResponse{additionalProperties=$additionalProperties}" + override fun toString() = + "SessionEndResponse{success=$success, additionalProperties=$additionalProperties}" } diff --git a/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionExecuteAgentParams.kt b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionExecuteAgentParams.kt deleted file mode 100644 index eca9552..0000000 --- a/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionExecuteAgentParams.kt +++ /dev/null @@ -1,269 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. - -package com.browserbase.api.models.sessions - -import com.browserbase.api.core.JsonMissing -import com.browserbase.api.core.JsonValue -import com.browserbase.api.core.Params -import com.browserbase.api.core.http.Headers -import com.browserbase.api.core.http.QueryParams -import java.util.Objects -import java.util.Optional -import kotlin.jvm.optionals.getOrNull - -/** Runs an autonomous AI agent that can perform complex multi-step browser tasks. */ -class SessionExecuteAgentParams -private constructor( - private val id: JsonValue?, - private val xLanguage: JsonValue?, - private val xSdkVersion: JsonValue?, - private val xSentAt: JsonValue?, - private val xStreamResponse: JsonValue?, - private val body: JsonValue, - private val additionalHeaders: Headers, - private val additionalQueryParams: QueryParams, -) : Params { - - fun id(): Optional = Optional.ofNullable(id) - - fun xLanguage(): Optional = Optional.ofNullable(xLanguage) - - fun xSdkVersion(): Optional = Optional.ofNullable(xSdkVersion) - - fun xSentAt(): Optional = Optional.ofNullable(xSentAt) - - fun xStreamResponse(): Optional = Optional.ofNullable(xStreamResponse) - - fun body(): JsonValue = body - - /** Additional headers to send with the request. */ - fun _additionalHeaders(): Headers = additionalHeaders - - /** Additional query param to send with the request. */ - fun _additionalQueryParams(): QueryParams = additionalQueryParams - - fun toBuilder() = Builder().from(this) - - companion object { - - @JvmStatic fun none(): SessionExecuteAgentParams = builder().build() - - /** - * Returns a mutable builder for constructing an instance of [SessionExecuteAgentParams]. - */ - @JvmStatic fun builder() = Builder() - } - - /** A builder for [SessionExecuteAgentParams]. */ - class Builder internal constructor() { - - private var id: JsonValue? = null - private var xLanguage: JsonValue? = null - private var xSdkVersion: JsonValue? = null - private var xSentAt: JsonValue? = null - private var xStreamResponse: JsonValue? = null - private var body: JsonValue = JsonMissing.of() - private var additionalHeaders: Headers.Builder = Headers.builder() - private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() - - @JvmSynthetic - internal fun from(sessionExecuteAgentParams: SessionExecuteAgentParams) = apply { - id = sessionExecuteAgentParams.id - xLanguage = sessionExecuteAgentParams.xLanguage - xSdkVersion = sessionExecuteAgentParams.xSdkVersion - xSentAt = sessionExecuteAgentParams.xSentAt - xStreamResponse = sessionExecuteAgentParams.xStreamResponse - body = sessionExecuteAgentParams.body - additionalHeaders = sessionExecuteAgentParams.additionalHeaders.toBuilder() - additionalQueryParams = sessionExecuteAgentParams.additionalQueryParams.toBuilder() - } - - fun id(id: JsonValue?) = apply { this.id = id } - - /** Alias for calling [Builder.id] with `id.orElse(null)`. */ - fun id(id: Optional) = id(id.getOrNull()) - - fun xLanguage(xLanguage: JsonValue?) = apply { this.xLanguage = xLanguage } - - /** Alias for calling [Builder.xLanguage] with `xLanguage.orElse(null)`. */ - fun xLanguage(xLanguage: Optional) = xLanguage(xLanguage.getOrNull()) - - fun xSdkVersion(xSdkVersion: JsonValue?) = apply { this.xSdkVersion = xSdkVersion } - - /** Alias for calling [Builder.xSdkVersion] with `xSdkVersion.orElse(null)`. */ - fun xSdkVersion(xSdkVersion: Optional) = xSdkVersion(xSdkVersion.getOrNull()) - - fun xSentAt(xSentAt: JsonValue?) = apply { this.xSentAt = xSentAt } - - /** Alias for calling [Builder.xSentAt] with `xSentAt.orElse(null)`. */ - fun xSentAt(xSentAt: Optional) = xSentAt(xSentAt.getOrNull()) - - fun xStreamResponse(xStreamResponse: JsonValue?) = apply { - this.xStreamResponse = xStreamResponse - } - - /** Alias for calling [Builder.xStreamResponse] with `xStreamResponse.orElse(null)`. */ - fun xStreamResponse(xStreamResponse: Optional) = - xStreamResponse(xStreamResponse.getOrNull()) - - fun body(body: JsonValue) = apply { this.body = body } - - fun additionalHeaders(additionalHeaders: Headers) = apply { - this.additionalHeaders.clear() - putAllAdditionalHeaders(additionalHeaders) - } - - fun additionalHeaders(additionalHeaders: Map>) = apply { - this.additionalHeaders.clear() - putAllAdditionalHeaders(additionalHeaders) - } - - fun putAdditionalHeader(name: String, value: String) = apply { - additionalHeaders.put(name, value) - } - - fun putAdditionalHeaders(name: String, values: Iterable) = apply { - additionalHeaders.put(name, values) - } - - fun putAllAdditionalHeaders(additionalHeaders: Headers) = apply { - this.additionalHeaders.putAll(additionalHeaders) - } - - fun putAllAdditionalHeaders(additionalHeaders: Map>) = apply { - this.additionalHeaders.putAll(additionalHeaders) - } - - fun replaceAdditionalHeaders(name: String, value: String) = apply { - additionalHeaders.replace(name, value) - } - - fun replaceAdditionalHeaders(name: String, values: Iterable) = apply { - additionalHeaders.replace(name, values) - } - - fun replaceAllAdditionalHeaders(additionalHeaders: Headers) = apply { - this.additionalHeaders.replaceAll(additionalHeaders) - } - - fun replaceAllAdditionalHeaders(additionalHeaders: Map>) = apply { - this.additionalHeaders.replaceAll(additionalHeaders) - } - - fun removeAdditionalHeaders(name: String) = apply { additionalHeaders.remove(name) } - - fun removeAllAdditionalHeaders(names: Set) = apply { - additionalHeaders.removeAll(names) - } - - fun additionalQueryParams(additionalQueryParams: QueryParams) = apply { - this.additionalQueryParams.clear() - putAllAdditionalQueryParams(additionalQueryParams) - } - - fun additionalQueryParams(additionalQueryParams: Map>) = apply { - this.additionalQueryParams.clear() - putAllAdditionalQueryParams(additionalQueryParams) - } - - fun putAdditionalQueryParam(key: String, value: String) = apply { - additionalQueryParams.put(key, value) - } - - fun putAdditionalQueryParams(key: String, values: Iterable) = apply { - additionalQueryParams.put(key, values) - } - - fun putAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { - this.additionalQueryParams.putAll(additionalQueryParams) - } - - fun putAllAdditionalQueryParams(additionalQueryParams: Map>) = - apply { - this.additionalQueryParams.putAll(additionalQueryParams) - } - - fun replaceAdditionalQueryParams(key: String, value: String) = apply { - additionalQueryParams.replace(key, value) - } - - fun replaceAdditionalQueryParams(key: String, values: Iterable) = apply { - additionalQueryParams.replace(key, values) - } - - fun replaceAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { - this.additionalQueryParams.replaceAll(additionalQueryParams) - } - - fun replaceAllAdditionalQueryParams(additionalQueryParams: Map>) = - apply { - this.additionalQueryParams.replaceAll(additionalQueryParams) - } - - fun removeAdditionalQueryParams(key: String) = apply { additionalQueryParams.remove(key) } - - fun removeAllAdditionalQueryParams(keys: Set) = apply { - additionalQueryParams.removeAll(keys) - } - - /** - * Returns an immutable instance of [SessionExecuteAgentParams]. - * - * Further updates to this [Builder] will not mutate the returned instance. - */ - fun build(): SessionExecuteAgentParams = - SessionExecuteAgentParams( - id, - xLanguage, - xSdkVersion, - xSentAt, - xStreamResponse, - body, - additionalHeaders.build(), - additionalQueryParams.build(), - ) - } - - fun _body(): JsonValue = body - - fun _pathParam(index: Int): String = - when (index) { - 0 -> id?.toString() ?: "" - else -> "" - } - - override fun _headers(): Headers = Headers.builder().apply { putAll(additionalHeaders) }.build() - - override fun _queryParams(): QueryParams = additionalQueryParams - - override fun equals(other: Any?): Boolean { - if (this === other) { - return true - } - - return other is SessionExecuteAgentParams && - id == other.id && - xLanguage == other.xLanguage && - xSdkVersion == other.xSdkVersion && - xSentAt == other.xSentAt && - xStreamResponse == other.xStreamResponse && - body == other.body && - additionalHeaders == other.additionalHeaders && - additionalQueryParams == other.additionalQueryParams - } - - override fun hashCode(): Int = - Objects.hash( - id, - xLanguage, - xSdkVersion, - xSentAt, - xStreamResponse, - body, - additionalHeaders, - additionalQueryParams, - ) - - override fun toString() = - "SessionExecuteAgentParams{id=$id, xLanguage=$xLanguage, xSdkVersion=$xSdkVersion, xSentAt=$xSentAt, xStreamResponse=$xStreamResponse, body=$body, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" -} diff --git a/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionExecuteAgentResponse.kt b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionExecuteAgentResponse.kt deleted file mode 100644 index 700a7ba..0000000 --- a/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionExecuteAgentResponse.kt +++ /dev/null @@ -1,118 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. - -package com.browserbase.api.models.sessions - -import com.browserbase.api.core.ExcludeMissing -import com.browserbase.api.core.JsonValue -import com.browserbase.api.errors.StagehandInvalidDataException -import com.fasterxml.jackson.annotation.JsonAnyGetter -import com.fasterxml.jackson.annotation.JsonAnySetter -import com.fasterxml.jackson.annotation.JsonCreator -import java.util.Collections -import java.util.Objects - -class SessionExecuteAgentResponse -@JsonCreator(mode = JsonCreator.Mode.DISABLED) -private constructor(private val additionalProperties: MutableMap) { - - @JsonCreator private constructor() : this(mutableMapOf()) - - @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 [SessionExecuteAgentResponse]. - */ - @JvmStatic fun builder() = Builder() - } - - /** A builder for [SessionExecuteAgentResponse]. */ - class Builder internal constructor() { - - private var additionalProperties: MutableMap = mutableMapOf() - - @JvmSynthetic - internal fun from(sessionExecuteAgentResponse: SessionExecuteAgentResponse) = apply { - additionalProperties = sessionExecuteAgentResponse.additionalProperties.toMutableMap() - } - - 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 [SessionExecuteAgentResponse]. - * - * Further updates to this [Builder] will not mutate the returned instance. - */ - fun build(): SessionExecuteAgentResponse = - SessionExecuteAgentResponse(additionalProperties.toMutableMap()) - } - - private var validated: Boolean = false - - fun validate(): SessionExecuteAgentResponse = apply { - if (validated) { - return@apply - } - - 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. - */ - @JvmSynthetic internal fun validity(): Int = 0 - - override fun equals(other: Any?): Boolean { - if (this === other) { - return true - } - - return other is SessionExecuteAgentResponse && - additionalProperties == other.additionalProperties - } - - private val hashCode: Int by lazy { Objects.hash(additionalProperties) } - - override fun hashCode(): Int = hashCode - - override fun toString() = - "SessionExecuteAgentResponse{additionalProperties=$additionalProperties}" -} diff --git a/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionExecuteParams.kt b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionExecuteParams.kt new file mode 100644 index 0000000..4b615cf --- /dev/null +++ b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionExecuteParams.kt @@ -0,0 +1,1403 @@ +// File generated from our OpenAPI spec by Stainless. + +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 +import com.browserbase.api.core.JsonValue +import com.browserbase.api.core.Params +import com.browserbase.api.core.checkRequired +import com.browserbase.api.core.http.Headers +import com.browserbase.api.core.http.QueryParams +import com.browserbase.api.errors.StagehandInvalidDataException +import com.fasterxml.jackson.annotation.JsonAnyGetter +import com.fasterxml.jackson.annotation.JsonAnySetter +import com.fasterxml.jackson.annotation.JsonCreator +import com.fasterxml.jackson.annotation.JsonProperty +import java.time.OffsetDateTime +import java.time.format.DateTimeFormatter +import java.util.Collections +import java.util.Objects +import java.util.Optional +import kotlin.jvm.optionals.getOrNull + +/** Runs an autonomous AI agent that can perform complex multi-step browser tasks. */ +class SessionExecuteParams +private constructor( + private val id: String?, + private val xLanguage: XLanguage?, + private val xSdkVersion: String?, + private val xSentAt: OffsetDateTime?, + private val xStreamResponse: XStreamResponse?, + private val body: Body, + private val additionalHeaders: Headers, + private val additionalQueryParams: QueryParams, +) : Params { + + /** Unique session identifier */ + fun id(): Optional = Optional.ofNullable(id) + + /** Client SDK language */ + fun xLanguage(): Optional = Optional.ofNullable(xLanguage) + + /** Version of the Stagehand SDK */ + fun xSdkVersion(): Optional = Optional.ofNullable(xSdkVersion) + + /** ISO timestamp when request was sent */ + fun xSentAt(): Optional = Optional.ofNullable(xSentAt) + + /** Whether to stream the response via SSE */ + fun xStreamResponse(): Optional = Optional.ofNullable(xStreamResponse) + + /** + * @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 agentConfig(): AgentConfig = body.agentConfig() + + /** + * @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 executeOptions(): ExecuteOptions = body.executeOptions() + + /** + * Target frame ID for the agent + * + * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun frameId(): Optional = body.frameId() + + /** + * Returns the raw JSON value of [agentConfig]. + * + * Unlike [agentConfig], this method doesn't throw if the JSON field has an unexpected type. + */ + fun _agentConfig(): JsonField = body._agentConfig() + + /** + * Returns the raw JSON value of [executeOptions]. + * + * Unlike [executeOptions], this method doesn't throw if the JSON field has an unexpected type. + */ + fun _executeOptions(): JsonField = body._executeOptions() + + /** + * Returns the raw JSON value of [frameId]. + * + * Unlike [frameId], this method doesn't throw if the JSON field has an unexpected type. + */ + fun _frameId(): JsonField = body._frameId() + + fun _additionalBodyProperties(): Map = body._additionalProperties() + + /** Additional headers to send with the request. */ + fun _additionalHeaders(): Headers = additionalHeaders + + /** Additional query param to send with the request. */ + fun _additionalQueryParams(): QueryParams = additionalQueryParams + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [SessionExecuteParams]. + * + * The following fields are required: + * ```java + * .agentConfig() + * .executeOptions() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [SessionExecuteParams]. */ + class Builder internal constructor() { + + private var id: String? = null + private var xLanguage: XLanguage? = null + private var xSdkVersion: String? = null + private var xSentAt: OffsetDateTime? = null + private var xStreamResponse: XStreamResponse? = null + private var body: Body.Builder = Body.builder() + private var additionalHeaders: Headers.Builder = Headers.builder() + private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() + + @JvmSynthetic + internal fun from(sessionExecuteParams: SessionExecuteParams) = apply { + id = sessionExecuteParams.id + xLanguage = sessionExecuteParams.xLanguage + xSdkVersion = sessionExecuteParams.xSdkVersion + xSentAt = sessionExecuteParams.xSentAt + xStreamResponse = sessionExecuteParams.xStreamResponse + body = sessionExecuteParams.body.toBuilder() + additionalHeaders = sessionExecuteParams.additionalHeaders.toBuilder() + additionalQueryParams = sessionExecuteParams.additionalQueryParams.toBuilder() + } + + /** Unique session identifier */ + fun id(id: String?) = apply { this.id = id } + + /** Alias for calling [Builder.id] with `id.orElse(null)`. */ + fun id(id: Optional) = id(id.getOrNull()) + + /** Client SDK language */ + fun xLanguage(xLanguage: XLanguage?) = apply { this.xLanguage = xLanguage } + + /** Alias for calling [Builder.xLanguage] with `xLanguage.orElse(null)`. */ + fun xLanguage(xLanguage: Optional) = xLanguage(xLanguage.getOrNull()) + + /** Version of the Stagehand SDK */ + fun xSdkVersion(xSdkVersion: String?) = apply { this.xSdkVersion = xSdkVersion } + + /** Alias for calling [Builder.xSdkVersion] with `xSdkVersion.orElse(null)`. */ + fun xSdkVersion(xSdkVersion: Optional) = xSdkVersion(xSdkVersion.getOrNull()) + + /** ISO timestamp when request was sent */ + fun xSentAt(xSentAt: OffsetDateTime?) = apply { this.xSentAt = xSentAt } + + /** Alias for calling [Builder.xSentAt] with `xSentAt.orElse(null)`. */ + fun xSentAt(xSentAt: Optional) = xSentAt(xSentAt.getOrNull()) + + /** Whether to stream the response via SSE */ + fun xStreamResponse(xStreamResponse: XStreamResponse?) = apply { + this.xStreamResponse = xStreamResponse + } + + /** Alias for calling [Builder.xStreamResponse] with `xStreamResponse.orElse(null)`. */ + fun xStreamResponse(xStreamResponse: Optional) = + xStreamResponse(xStreamResponse.getOrNull()) + + /** + * Sets the entire request body. + * + * This is generally only useful if you are already constructing the body separately. + * Otherwise, it's more convenient to use the top-level setters instead: + * - [agentConfig] + * - [executeOptions] + * - [frameId] + */ + fun body(body: Body) = apply { this.body = body.toBuilder() } + + fun agentConfig(agentConfig: AgentConfig) = apply { body.agentConfig(agentConfig) } + + /** + * Sets [Builder.agentConfig] to an arbitrary JSON value. + * + * You should usually call [Builder.agentConfig] with a well-typed [AgentConfig] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun agentConfig(agentConfig: JsonField) = apply { + body.agentConfig(agentConfig) + } + + fun executeOptions(executeOptions: ExecuteOptions) = apply { + body.executeOptions(executeOptions) + } + + /** + * Sets [Builder.executeOptions] to an arbitrary JSON value. + * + * You should usually call [Builder.executeOptions] with a well-typed [ExecuteOptions] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun executeOptions(executeOptions: JsonField) = apply { + body.executeOptions(executeOptions) + } + + /** Target frame ID for the agent */ + fun frameId(frameId: String) = apply { body.frameId(frameId) } + + /** + * Sets [Builder.frameId] to an arbitrary JSON value. + * + * You should usually call [Builder.frameId] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun frameId(frameId: JsonField) = apply { body.frameId(frameId) } + + fun additionalBodyProperties(additionalBodyProperties: Map) = apply { + body.additionalProperties(additionalBodyProperties) + } + + fun putAdditionalBodyProperty(key: String, value: JsonValue) = apply { + body.putAdditionalProperty(key, value) + } + + fun putAllAdditionalBodyProperties(additionalBodyProperties: Map) = + apply { + body.putAllAdditionalProperties(additionalBodyProperties) + } + + fun removeAdditionalBodyProperty(key: String) = apply { body.removeAdditionalProperty(key) } + + fun removeAllAdditionalBodyProperties(keys: Set) = apply { + body.removeAllAdditionalProperties(keys) + } + + fun additionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun additionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun putAdditionalHeader(name: String, value: String) = apply { + additionalHeaders.put(name, value) + } + + fun putAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.put(name, values) + } + + fun putAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun putAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun replaceAdditionalHeaders(name: String, value: String) = apply { + additionalHeaders.replace(name, value) + } + + fun replaceAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.replace(name, values) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun removeAdditionalHeaders(name: String) = apply { additionalHeaders.remove(name) } + + fun removeAllAdditionalHeaders(names: Set) = apply { + additionalHeaders.removeAll(names) + } + + fun additionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun additionalQueryParams(additionalQueryParams: Map>) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun putAdditionalQueryParam(key: String, value: String) = apply { + additionalQueryParams.put(key, value) + } + + fun putAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.put(key, values) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun replaceAdditionalQueryParams(key: String, value: String) = apply { + additionalQueryParams.replace(key, value) + } + + fun replaceAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.replace(key, values) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun removeAdditionalQueryParams(key: String) = apply { additionalQueryParams.remove(key) } + + fun removeAllAdditionalQueryParams(keys: Set) = apply { + additionalQueryParams.removeAll(keys) + } + + /** + * Returns an immutable instance of [SessionExecuteParams]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .agentConfig() + * .executeOptions() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): SessionExecuteParams = + SessionExecuteParams( + id, + xLanguage, + xSdkVersion, + xSentAt, + xStreamResponse, + body.build(), + additionalHeaders.build(), + additionalQueryParams.build(), + ) + } + + fun _body(): Body = body + + fun _pathParam(index: Int): String = + when (index) { + 0 -> id ?: "" + else -> "" + } + + override fun _headers(): Headers = + Headers.builder() + .apply { + xLanguage?.let { put("x-language", it.toString()) } + xSdkVersion?.let { put("x-sdk-version", it) } + xSentAt?.let { put("x-sent-at", DateTimeFormatter.ISO_OFFSET_DATE_TIME.format(it)) } + xStreamResponse?.let { put("x-stream-response", it.toString()) } + putAll(additionalHeaders) + } + .build() + + override fun _queryParams(): QueryParams = additionalQueryParams + + class Body + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val agentConfig: JsonField, + private val executeOptions: JsonField, + private val frameId: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("agentConfig") + @ExcludeMissing + agentConfig: JsonField = JsonMissing.of(), + @JsonProperty("executeOptions") + @ExcludeMissing + executeOptions: JsonField = JsonMissing.of(), + @JsonProperty("frameId") @ExcludeMissing frameId: JsonField = JsonMissing.of(), + ) : this(agentConfig, executeOptions, frameId, mutableMapOf()) + + /** + * @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 agentConfig(): AgentConfig = agentConfig.getRequired("agentConfig") + + /** + * @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 executeOptions(): ExecuteOptions = executeOptions.getRequired("executeOptions") + + /** + * Target frame ID for the agent + * + * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun frameId(): Optional = frameId.getOptional("frameId") + + /** + * Returns the raw JSON value of [agentConfig]. + * + * Unlike [agentConfig], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("agentConfig") + @ExcludeMissing + fun _agentConfig(): JsonField = agentConfig + + /** + * Returns the raw JSON value of [executeOptions]. + * + * Unlike [executeOptions], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("executeOptions") + @ExcludeMissing + fun _executeOptions(): JsonField = executeOptions + + /** + * Returns the raw JSON value of [frameId]. + * + * Unlike [frameId], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("frameId") @ExcludeMissing fun _frameId(): JsonField = frameId + + @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 [Body]. + * + * The following fields are required: + * ```java + * .agentConfig() + * .executeOptions() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Body]. */ + class Builder internal constructor() { + + private var agentConfig: JsonField? = null + private var executeOptions: JsonField? = null + private var frameId: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(body: Body) = apply { + agentConfig = body.agentConfig + executeOptions = body.executeOptions + frameId = body.frameId + additionalProperties = body.additionalProperties.toMutableMap() + } + + fun agentConfig(agentConfig: AgentConfig) = agentConfig(JsonField.of(agentConfig)) + + /** + * Sets [Builder.agentConfig] to an arbitrary JSON value. + * + * You should usually call [Builder.agentConfig] with a well-typed [AgentConfig] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun agentConfig(agentConfig: JsonField) = apply { + this.agentConfig = agentConfig + } + + fun executeOptions(executeOptions: ExecuteOptions) = + executeOptions(JsonField.of(executeOptions)) + + /** + * Sets [Builder.executeOptions] to an arbitrary JSON value. + * + * You should usually call [Builder.executeOptions] with a well-typed [ExecuteOptions] + * value instead. This method is primarily for setting the field to an undocumented or + * not yet supported value. + */ + fun executeOptions(executeOptions: JsonField) = apply { + this.executeOptions = executeOptions + } + + /** Target frame ID for the agent */ + fun frameId(frameId: String) = frameId(JsonField.of(frameId)) + + /** + * Sets [Builder.frameId] to an arbitrary JSON value. + * + * You should usually call [Builder.frameId] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun frameId(frameId: JsonField) = apply { this.frameId = frameId } + + 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 [Body]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .agentConfig() + * .executeOptions() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): Body = + Body( + checkRequired("agentConfig", agentConfig), + checkRequired("executeOptions", executeOptions), + frameId, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): Body = apply { + if (validated) { + return@apply + } + + agentConfig().validate() + executeOptions().validate() + frameId() + 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. + */ + @JvmSynthetic + internal fun validity(): Int = + (agentConfig.asKnown().getOrNull()?.validity() ?: 0) + + (executeOptions.asKnown().getOrNull()?.validity() ?: 0) + + (if (frameId.asKnown().isPresent) 1 else 0) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Body && + agentConfig == other.agentConfig && + executeOptions == other.executeOptions && + frameId == other.frameId && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(agentConfig, executeOptions, frameId, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Body{agentConfig=$agentConfig, executeOptions=$executeOptions, frameId=$frameId, additionalProperties=$additionalProperties}" + } + + class AgentConfig + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val cua: JsonField, + private val model: JsonField, + private val systemPrompt: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("cua") @ExcludeMissing cua: JsonField = JsonMissing.of(), + @JsonProperty("model") @ExcludeMissing model: JsonField = JsonMissing.of(), + @JsonProperty("systemPrompt") + @ExcludeMissing + systemPrompt: JsonField = JsonMissing.of(), + ) : this(cua, model, systemPrompt, mutableMapOf()) + + /** + * Enable Computer Use Agent mode + * + * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun cua(): Optional = cua.getOptional("cua") + + /** + * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun model(): Optional = model.getOptional("model") + + /** + * Custom system prompt for the agent + * + * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun systemPrompt(): Optional = systemPrompt.getOptional("systemPrompt") + + /** + * Returns the raw JSON value of [cua]. + * + * Unlike [cua], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("cua") @ExcludeMissing fun _cua(): JsonField = cua + + /** + * Returns the raw JSON value of [model]. + * + * Unlike [model], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("model") @ExcludeMissing fun _model(): JsonField = model + + /** + * Returns the raw JSON value of [systemPrompt]. + * + * Unlike [systemPrompt], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("systemPrompt") + @ExcludeMissing + fun _systemPrompt(): JsonField = systemPrompt + + @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 [AgentConfig]. */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [AgentConfig]. */ + class Builder internal constructor() { + + private var cua: JsonField = JsonMissing.of() + private var model: JsonField = JsonMissing.of() + private var systemPrompt: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(agentConfig: AgentConfig) = apply { + cua = agentConfig.cua + model = agentConfig.model + systemPrompt = agentConfig.systemPrompt + additionalProperties = agentConfig.additionalProperties.toMutableMap() + } + + /** Enable Computer Use Agent mode */ + fun cua(cua: Boolean) = cua(JsonField.of(cua)) + + /** + * Sets [Builder.cua] to an arbitrary JSON value. + * + * You should usually call [Builder.cua] with a well-typed [Boolean] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun cua(cua: JsonField) = apply { this.cua = cua } + + fun model(model: ModelConfig) = model(JsonField.of(model)) + + /** + * Sets [Builder.model] to an arbitrary JSON value. + * + * You should usually call [Builder.model] with a well-typed [ModelConfig] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + 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.ofUnionMember1(unionMember1)`. */ + fun model(unionMember1: ModelConfig.UnionMember1) = + model(ModelConfig.ofUnionMember1(unionMember1)) + + /** Custom system prompt for the agent */ + fun systemPrompt(systemPrompt: String) = systemPrompt(JsonField.of(systemPrompt)) + + /** + * Sets [Builder.systemPrompt] to an arbitrary JSON value. + * + * You should usually call [Builder.systemPrompt] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun systemPrompt(systemPrompt: JsonField) = apply { + this.systemPrompt = systemPrompt + } + + 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 [AgentConfig]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): AgentConfig = + AgentConfig(cua, model, systemPrompt, additionalProperties.toMutableMap()) + } + + private var validated: Boolean = false + + fun validate(): AgentConfig = apply { + if (validated) { + return@apply + } + + cua() + model().ifPresent { it.validate() } + systemPrompt() + 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. + */ + @JvmSynthetic + internal fun validity(): Int = + (if (cua.asKnown().isPresent) 1 else 0) + + (model.asKnown().getOrNull()?.validity() ?: 0) + + (if (systemPrompt.asKnown().isPresent) 1 else 0) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is AgentConfig && + cua == other.cua && + model == other.model && + systemPrompt == other.systemPrompt && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(cua, model, systemPrompt, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "AgentConfig{cua=$cua, model=$model, systemPrompt=$systemPrompt, additionalProperties=$additionalProperties}" + } + + class ExecuteOptions + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val instruction: JsonField, + private val highlightCursor: JsonField, + private val maxSteps: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("instruction") + @ExcludeMissing + instruction: JsonField = JsonMissing.of(), + @JsonProperty("highlightCursor") + @ExcludeMissing + highlightCursor: JsonField = JsonMissing.of(), + @JsonProperty("maxSteps") @ExcludeMissing maxSteps: JsonField = JsonMissing.of(), + ) : this(instruction, highlightCursor, maxSteps, mutableMapOf()) + + /** + * Natural language instruction for the agent + * + * @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 instruction(): String = instruction.getRequired("instruction") + + /** + * Whether to visually highlight the cursor during execution + * + * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun highlightCursor(): Optional = highlightCursor.getOptional("highlightCursor") + + /** + * Maximum number of steps the agent can take + * + * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun maxSteps(): Optional = maxSteps.getOptional("maxSteps") + + /** + * Returns the raw JSON value of [instruction]. + * + * Unlike [instruction], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("instruction") + @ExcludeMissing + fun _instruction(): JsonField = instruction + + /** + * Returns the raw JSON value of [highlightCursor]. + * + * Unlike [highlightCursor], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("highlightCursor") + @ExcludeMissing + fun _highlightCursor(): JsonField = highlightCursor + + /** + * Returns the raw JSON value of [maxSteps]. + * + * Unlike [maxSteps], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("maxSteps") @ExcludeMissing fun _maxSteps(): JsonField = maxSteps + + @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 [ExecuteOptions]. + * + * The following fields are required: + * ```java + * .instruction() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [ExecuteOptions]. */ + class Builder internal constructor() { + + private var instruction: JsonField? = null + private var highlightCursor: JsonField = JsonMissing.of() + private var maxSteps: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(executeOptions: ExecuteOptions) = apply { + instruction = executeOptions.instruction + highlightCursor = executeOptions.highlightCursor + maxSteps = executeOptions.maxSteps + additionalProperties = executeOptions.additionalProperties.toMutableMap() + } + + /** Natural language instruction for the agent */ + fun instruction(instruction: String) = instruction(JsonField.of(instruction)) + + /** + * Sets [Builder.instruction] to an arbitrary JSON value. + * + * You should usually call [Builder.instruction] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun instruction(instruction: JsonField) = apply { + this.instruction = instruction + } + + /** Whether to visually highlight the cursor during execution */ + fun highlightCursor(highlightCursor: Boolean) = + highlightCursor(JsonField.of(highlightCursor)) + + /** + * Sets [Builder.highlightCursor] to an arbitrary JSON value. + * + * You should usually call [Builder.highlightCursor] with a well-typed [Boolean] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun highlightCursor(highlightCursor: JsonField) = apply { + this.highlightCursor = highlightCursor + } + + /** Maximum number of steps the agent can take */ + fun maxSteps(maxSteps: Double) = maxSteps(JsonField.of(maxSteps)) + + /** + * Sets [Builder.maxSteps] to an arbitrary JSON value. + * + * You should usually call [Builder.maxSteps] with a well-typed [Double] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun maxSteps(maxSteps: JsonField) = apply { this.maxSteps = maxSteps } + + 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 [ExecuteOptions]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .instruction() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): ExecuteOptions = + ExecuteOptions( + checkRequired("instruction", instruction), + highlightCursor, + maxSteps, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): ExecuteOptions = apply { + if (validated) { + return@apply + } + + instruction() + highlightCursor() + maxSteps() + 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. + */ + @JvmSynthetic + internal fun validity(): Int = + (if (instruction.asKnown().isPresent) 1 else 0) + + (if (highlightCursor.asKnown().isPresent) 1 else 0) + + (if (maxSteps.asKnown().isPresent) 1 else 0) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is ExecuteOptions && + instruction == other.instruction && + highlightCursor == other.highlightCursor && + maxSteps == other.maxSteps && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(instruction, highlightCursor, maxSteps, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "ExecuteOptions{instruction=$instruction, highlightCursor=$highlightCursor, maxSteps=$maxSteps, additionalProperties=$additionalProperties}" + } + + /** Client SDK language */ + class XLanguage @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 { + + @JvmField val TYPESCRIPT = of("typescript") + + @JvmField val PYTHON = of("python") + + @JvmField val PLAYGROUND = of("playground") + + @JvmStatic fun of(value: String) = XLanguage(JsonField.of(value)) + } + + /** An enum containing [XLanguage]'s known values. */ + enum class Known { + TYPESCRIPT, + PYTHON, + PLAYGROUND, + } + + /** + * An enum containing [XLanguage]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [XLanguage] 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 { + TYPESCRIPT, + PYTHON, + PLAYGROUND, + /** + * An enum member indicating that [XLanguage] 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) { + TYPESCRIPT -> Value.TYPESCRIPT + PYTHON -> Value.PYTHON + PLAYGROUND -> Value.PLAYGROUND + 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) { + TYPESCRIPT -> Known.TYPESCRIPT + PYTHON -> Known.PYTHON + PLAYGROUND -> Known.PLAYGROUND + else -> throw StagehandInvalidDataException("Unknown XLanguage: $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().orElseThrow { + StagehandInvalidDataException("Value is not a String") + } + + private var validated: Boolean = false + + fun validate(): XLanguage = 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. + */ + @JvmSynthetic 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 XLanguage && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + /** Whether to stream the response via SSE */ + class XStreamResponse @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 { + + @JvmField val TRUE = of("true") + + @JvmField val FALSE = of("false") + + @JvmStatic fun of(value: String) = XStreamResponse(JsonField.of(value)) + } + + /** An enum containing [XStreamResponse]'s known values. */ + enum class Known { + TRUE, + FALSE, + } + + /** + * An enum containing [XStreamResponse]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [XStreamResponse] 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, + FALSE, + /** + * An enum member indicating that [XStreamResponse] 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 + FALSE -> Value.FALSE + 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 + FALSE -> Known.FALSE + else -> throw StagehandInvalidDataException("Unknown XStreamResponse: $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().orElseThrow { + StagehandInvalidDataException("Value is not a String") + } + + private var validated: Boolean = false + + fun validate(): XStreamResponse = 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. + */ + @JvmSynthetic 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 XStreamResponse && 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 SessionExecuteParams && + id == other.id && + xLanguage == other.xLanguage && + xSdkVersion == other.xSdkVersion && + xSentAt == other.xSentAt && + xStreamResponse == other.xStreamResponse && + body == other.body && + additionalHeaders == other.additionalHeaders && + additionalQueryParams == other.additionalQueryParams + } + + override fun hashCode(): Int = + Objects.hash( + id, + xLanguage, + xSdkVersion, + xSentAt, + xStreamResponse, + body, + additionalHeaders, + additionalQueryParams, + ) + + override fun toString() = + "SessionExecuteParams{id=$id, xLanguage=$xLanguage, xSdkVersion=$xSdkVersion, xSentAt=$xSentAt, xStreamResponse=$xStreamResponse, body=$body, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" +} diff --git a/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionExecuteResponse.kt b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionExecuteResponse.kt new file mode 100644 index 0000000..2478f77 --- /dev/null +++ b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionExecuteResponse.kt @@ -0,0 +1,1775 @@ +// File generated from our OpenAPI spec by Stainless. + +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 +import com.browserbase.api.core.JsonValue +import com.browserbase.api.core.checkKnown +import com.browserbase.api.core.checkRequired +import com.browserbase.api.core.toImmutable +import com.browserbase.api.errors.StagehandInvalidDataException +import com.fasterxml.jackson.annotation.JsonAnyGetter +import com.fasterxml.jackson.annotation.JsonAnySetter +import com.fasterxml.jackson.annotation.JsonCreator +import com.fasterxml.jackson.annotation.JsonProperty +import java.util.Collections +import java.util.Objects +import java.util.Optional +import kotlin.jvm.optionals.getOrNull + +class SessionExecuteResponse +@JsonCreator(mode = JsonCreator.Mode.DISABLED) +private constructor( + private val data: 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(), + ) : this(data, success, mutableMapOf()) + + /** + * @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 data(): Data = data.getRequired("data") + + /** + * @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") + + /** + * Returns the raw JSON value of [data]. + * + * Unlike [data], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("data") @ExcludeMissing fun _data(): JsonField = data + + /** + * 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 + + @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 [SessionExecuteResponse]. + * + * The following fields are required: + * ```java + * .data() + * .success() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [SessionExecuteResponse]. */ + class Builder internal constructor() { + + private var data: JsonField? = null + private var success: JsonField? = null + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(sessionExecuteResponse: SessionExecuteResponse) = apply { + data = sessionExecuteResponse.data + success = sessionExecuteResponse.success + additionalProperties = sessionExecuteResponse.additionalProperties.toMutableMap() + } + + fun data(data: Data) = data(JsonField.of(data)) + + /** + * Sets [Builder.data] to an arbitrary JSON value. + * + * You should usually call [Builder.data] with a well-typed [Data] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun data(data: JsonField) = apply { this.data = data } + + fun success(success: Success) = 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 + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun success(success: JsonField) = apply { this.success = success } + + 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 [SessionExecuteResponse]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .data() + * .success() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): SessionExecuteResponse = + SessionExecuteResponse( + checkRequired("data", data), + checkRequired("success", success), + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): SessionExecuteResponse = apply { + if (validated) { + return@apply + } + + data().validate() + success().validate() + 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. + */ + @JvmSynthetic + internal fun validity(): Int = + (data.asKnown().getOrNull()?.validity() ?: 0) + + (success.asKnown().getOrNull()?.validity() ?: 0) + + class Data + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val result: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("result") @ExcludeMissing result: JsonField = JsonMissing.of() + ) : this(result, mutableMapOf()) + + /** + * @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 result(): Result = result.getRequired("result") + + /** + * Returns the raw JSON value of [result]. + * + * Unlike [result], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("result") @ExcludeMissing fun _result(): JsonField = result + + @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 [Data]. + * + * The following fields are required: + * ```java + * .result() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Data]. */ + class Builder internal constructor() { + + private var result: JsonField? = null + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(data: Data) = apply { + result = data.result + additionalProperties = data.additionalProperties.toMutableMap() + } + + fun result(result: Result) = result(JsonField.of(result)) + + /** + * Sets [Builder.result] to an arbitrary JSON value. + * + * You should usually call [Builder.result] with a well-typed [Result] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun result(result: JsonField) = apply { this.result = result } + + 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 [Data]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .result() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): Data = + Data(checkRequired("result", result), additionalProperties.toMutableMap()) + } + + private var validated: Boolean = false + + fun validate(): Data = apply { + if (validated) { + return@apply + } + + result().validate() + 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. + */ + @JvmSynthetic internal fun validity(): Int = (result.asKnown().getOrNull()?.validity() ?: 0) + + class Result + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val actions: JsonField>, + private val completed: JsonField, + private val message: JsonField, + private val success: JsonField, + private val metadata: JsonField, + private val usage: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("actions") + @ExcludeMissing + actions: JsonField> = JsonMissing.of(), + @JsonProperty("completed") + @ExcludeMissing + completed: JsonField = JsonMissing.of(), + @JsonProperty("message") + @ExcludeMissing + message: JsonField = JsonMissing.of(), + @JsonProperty("success") + @ExcludeMissing + success: JsonField = JsonMissing.of(), + @JsonProperty("metadata") + @ExcludeMissing + metadata: JsonField = JsonMissing.of(), + @JsonProperty("usage") @ExcludeMissing usage: JsonField = JsonMissing.of(), + ) : this(actions, completed, message, success, metadata, usage, mutableMapOf()) + + /** + * @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 actions(): List = actions.getRequired("actions") + + /** + * Whether the agent finished its task + * + * @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 completed(): Boolean = completed.getRequired("completed") + + /** + * Summary of what the agent accomplished + * + * @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 message(): String = message.getRequired("message") + + /** + * Whether the agent completed successfully + * + * @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(): Boolean = success.getRequired("success") + + /** + * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. + * if the server responded with an unexpected value). + */ + fun metadata(): Optional = metadata.getOptional("metadata") + + /** + * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. + * if the server responded with an unexpected value). + */ + fun usage(): Optional = usage.getOptional("usage") + + /** + * Returns the raw JSON value of [actions]. + * + * Unlike [actions], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("actions") + @ExcludeMissing + fun _actions(): JsonField> = actions + + /** + * Returns the raw JSON value of [completed]. + * + * Unlike [completed], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("completed") + @ExcludeMissing + fun _completed(): JsonField = completed + + /** + * Returns the raw JSON value of [message]. + * + * Unlike [message], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("message") @ExcludeMissing fun _message(): JsonField = message + + /** + * 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 + + /** + * Returns the raw JSON value of [metadata]. + * + * Unlike [metadata], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("metadata") + @ExcludeMissing + fun _metadata(): JsonField = metadata + + /** + * Returns the raw JSON value of [usage]. + * + * Unlike [usage], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("usage") @ExcludeMissing fun _usage(): JsonField = usage + + @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 [Result]. + * + * The following fields are required: + * ```java + * .actions() + * .completed() + * .message() + * .success() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Result]. */ + class Builder internal constructor() { + + private var actions: JsonField>? = null + private var completed: JsonField? = null + private var message: JsonField? = null + private var success: JsonField? = null + private var metadata: JsonField = JsonMissing.of() + private var usage: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(result: Result) = apply { + actions = result.actions.map { it.toMutableList() } + completed = result.completed + message = result.message + success = result.success + metadata = result.metadata + usage = result.usage + additionalProperties = result.additionalProperties.toMutableMap() + } + + fun actions(actions: List) = actions(JsonField.of(actions)) + + /** + * Sets [Builder.actions] to an arbitrary JSON value. + * + * You should usually call [Builder.actions] with a well-typed `List` value + * instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun actions(actions: JsonField>) = apply { + this.actions = actions.map { it.toMutableList() } + } + + /** + * Adds a single [Action] to [actions]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addAction(action: Action) = apply { + actions = + (actions ?: JsonField.of(mutableListOf())).also { + checkKnown("actions", it).add(action) + } + } + + /** Whether the agent finished its task */ + fun completed(completed: Boolean) = completed(JsonField.of(completed)) + + /** + * Sets [Builder.completed] to an arbitrary JSON value. + * + * You should usually call [Builder.completed] with a well-typed [Boolean] value + * instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun completed(completed: JsonField) = apply { this.completed = completed } + + /** Summary of what the agent accomplished */ + fun message(message: String) = message(JsonField.of(message)) + + /** + * Sets [Builder.message] to an arbitrary JSON value. + * + * You should usually call [Builder.message] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun message(message: JsonField) = apply { this.message = message } + + /** Whether the agent completed successfully */ + 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 [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 metadata(metadata: Metadata) = metadata(JsonField.of(metadata)) + + /** + * Sets [Builder.metadata] to an arbitrary JSON value. + * + * You should usually call [Builder.metadata] with a well-typed [Metadata] value + * instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun metadata(metadata: JsonField) = apply { this.metadata = metadata } + + fun usage(usage: Usage) = usage(JsonField.of(usage)) + + /** + * Sets [Builder.usage] to an arbitrary JSON value. + * + * You should usually call [Builder.usage] with a well-typed [Usage] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun usage(usage: JsonField) = apply { this.usage = usage } + + 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 [Result]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .actions() + * .completed() + * .message() + * .success() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): Result = + Result( + checkRequired("actions", actions).map { it.toImmutable() }, + checkRequired("completed", completed), + checkRequired("message", message), + checkRequired("success", success), + metadata, + usage, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): Result = apply { + if (validated) { + return@apply + } + + actions().forEach { it.validate() } + completed() + message() + success() + metadata().ifPresent { it.validate() } + usage().ifPresent { it.validate() } + 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. + */ + @JvmSynthetic + internal fun validity(): Int = + (actions.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + + (if (completed.asKnown().isPresent) 1 else 0) + + (if (message.asKnown().isPresent) 1 else 0) + + (if (success.asKnown().isPresent) 1 else 0) + + (metadata.asKnown().getOrNull()?.validity() ?: 0) + + (usage.asKnown().getOrNull()?.validity() ?: 0) + + class Action + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val type: JsonField, + private val action: JsonField, + private val instruction: JsonField, + private val pageText: JsonField, + private val pageUrl: JsonField, + private val reasoning: JsonField, + private val taskCompleted: JsonField, + private val timeMs: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("type") + @ExcludeMissing + type: JsonField = JsonMissing.of(), + @JsonProperty("action") + @ExcludeMissing + action: JsonField = JsonMissing.of(), + @JsonProperty("instruction") + @ExcludeMissing + instruction: JsonField = JsonMissing.of(), + @JsonProperty("pageText") + @ExcludeMissing + pageText: JsonField = JsonMissing.of(), + @JsonProperty("pageUrl") + @ExcludeMissing + pageUrl: JsonField = JsonMissing.of(), + @JsonProperty("reasoning") + @ExcludeMissing + reasoning: JsonField = JsonMissing.of(), + @JsonProperty("taskCompleted") + @ExcludeMissing + taskCompleted: JsonField = JsonMissing.of(), + @JsonProperty("timeMs") + @ExcludeMissing + timeMs: JsonField = JsonMissing.of(), + ) : this( + type, + action, + instruction, + pageText, + pageUrl, + reasoning, + taskCompleted, + timeMs, + mutableMapOf(), + ) + + /** + * Type of action taken + * + * @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 type(): String = type.getRequired("type") + + /** + * @throws StagehandInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun action(): Optional = action.getOptional("action") + + /** + * @throws StagehandInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun instruction(): Optional = instruction.getOptional("instruction") + + /** + * @throws StagehandInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun pageText(): Optional = pageText.getOptional("pageText") + + /** + * @throws StagehandInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun pageUrl(): Optional = pageUrl.getOptional("pageUrl") + + /** + * Agent's reasoning for taking this action + * + * @throws StagehandInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun reasoning(): Optional = reasoning.getOptional("reasoning") + + /** + * @throws StagehandInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun taskCompleted(): Optional = taskCompleted.getOptional("taskCompleted") + + /** + * Time taken for this action in ms + * + * @throws StagehandInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun timeMs(): Optional = timeMs.getOptional("timeMs") + + /** + * Returns the raw JSON value of [type]. + * + * Unlike [type], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("type") @ExcludeMissing fun _type(): JsonField = type + + /** + * Returns the raw JSON value of [action]. + * + * Unlike [action], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("action") @ExcludeMissing fun _action(): JsonField = action + + /** + * Returns the raw JSON value of [instruction]. + * + * Unlike [instruction], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("instruction") + @ExcludeMissing + fun _instruction(): JsonField = instruction + + /** + * Returns the raw JSON value of [pageText]. + * + * Unlike [pageText], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("pageText") + @ExcludeMissing + fun _pageText(): JsonField = pageText + + /** + * Returns the raw JSON value of [pageUrl]. + * + * Unlike [pageUrl], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("pageUrl") @ExcludeMissing fun _pageUrl(): JsonField = pageUrl + + /** + * Returns the raw JSON value of [reasoning]. + * + * Unlike [reasoning], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("reasoning") + @ExcludeMissing + fun _reasoning(): JsonField = reasoning + + /** + * Returns the raw JSON value of [taskCompleted]. + * + * Unlike [taskCompleted], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("taskCompleted") + @ExcludeMissing + fun _taskCompleted(): JsonField = taskCompleted + + /** + * Returns the raw JSON value of [timeMs]. + * + * Unlike [timeMs], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("timeMs") @ExcludeMissing fun _timeMs(): JsonField = timeMs + + @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: + * ```java + * .type() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Action]. */ + class Builder internal constructor() { + + private var type: JsonField? = null + private var action: JsonField = JsonMissing.of() + private var instruction: JsonField = JsonMissing.of() + private var pageText: JsonField = JsonMissing.of() + private var pageUrl: JsonField = JsonMissing.of() + private var reasoning: JsonField = JsonMissing.of() + private var taskCompleted: JsonField = JsonMissing.of() + private var timeMs: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(action: Action) = apply { + type = action.type + this.action = action.action + instruction = action.instruction + pageText = action.pageText + pageUrl = action.pageUrl + reasoning = action.reasoning + taskCompleted = action.taskCompleted + timeMs = action.timeMs + additionalProperties = action.additionalProperties.toMutableMap() + } + + /** Type of action taken */ + fun type(type: String) = type(JsonField.of(type)) + + /** + * Sets [Builder.type] to an arbitrary JSON value. + * + * You should usually call [Builder.type] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or + * not yet supported value. + */ + fun type(type: JsonField) = apply { this.type = type } + + fun action(action: String) = action(JsonField.of(action)) + + /** + * Sets [Builder.action] to an arbitrary JSON value. + * + * You should usually call [Builder.action] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or + * not yet supported value. + */ + fun action(action: JsonField) = apply { this.action = action } + + fun instruction(instruction: String) = instruction(JsonField.of(instruction)) + + /** + * Sets [Builder.instruction] to an arbitrary JSON value. + * + * You should usually call [Builder.instruction] with a well-typed [String] + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun instruction(instruction: JsonField) = apply { + this.instruction = instruction + } + + fun pageText(pageText: String) = pageText(JsonField.of(pageText)) + + /** + * Sets [Builder.pageText] to an arbitrary JSON value. + * + * You should usually call [Builder.pageText] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or + * not yet supported value. + */ + fun pageText(pageText: JsonField) = apply { this.pageText = pageText } + + fun pageUrl(pageUrl: String) = pageUrl(JsonField.of(pageUrl)) + + /** + * Sets [Builder.pageUrl] to an arbitrary JSON value. + * + * You should usually call [Builder.pageUrl] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or + * not yet supported value. + */ + fun pageUrl(pageUrl: JsonField) = apply { this.pageUrl = pageUrl } + + /** Agent's reasoning for taking this action */ + fun reasoning(reasoning: String) = reasoning(JsonField.of(reasoning)) + + /** + * Sets [Builder.reasoning] to an arbitrary JSON value. + * + * You should usually call [Builder.reasoning] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or + * not yet supported value. + */ + fun reasoning(reasoning: JsonField) = apply { + this.reasoning = reasoning + } + + fun taskCompleted(taskCompleted: Boolean) = + taskCompleted(JsonField.of(taskCompleted)) + + /** + * Sets [Builder.taskCompleted] to an arbitrary JSON value. + * + * You should usually call [Builder.taskCompleted] with a well-typed [Boolean] + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun taskCompleted(taskCompleted: JsonField) = apply { + this.taskCompleted = taskCompleted + } + + /** Time taken for this action in ms */ + fun timeMs(timeMs: Double) = timeMs(JsonField.of(timeMs)) + + /** + * Sets [Builder.timeMs] to an arbitrary JSON value. + * + * You should usually call [Builder.timeMs] with a well-typed [Double] value + * instead. This method is primarily for setting the field to an undocumented or + * not yet supported value. + */ + fun timeMs(timeMs: JsonField) = apply { this.timeMs = timeMs } + + 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: + * ```java + * .type() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): Action = + Action( + checkRequired("type", type), + action, + instruction, + pageText, + pageUrl, + reasoning, + taskCompleted, + timeMs, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): Action = apply { + if (validated) { + return@apply + } + + type() + action() + instruction() + pageText() + pageUrl() + reasoning() + taskCompleted() + timeMs() + 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. + */ + @JvmSynthetic + internal fun validity(): Int = + (if (type.asKnown().isPresent) 1 else 0) + + (if (action.asKnown().isPresent) 1 else 0) + + (if (instruction.asKnown().isPresent) 1 else 0) + + (if (pageText.asKnown().isPresent) 1 else 0) + + (if (pageUrl.asKnown().isPresent) 1 else 0) + + (if (reasoning.asKnown().isPresent) 1 else 0) + + (if (taskCompleted.asKnown().isPresent) 1 else 0) + + (if (timeMs.asKnown().isPresent) 1 else 0) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Action && + type == other.type && + action == other.action && + instruction == other.instruction && + pageText == other.pageText && + pageUrl == other.pageUrl && + reasoning == other.reasoning && + taskCompleted == other.taskCompleted && + timeMs == other.timeMs && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash( + type, + action, + instruction, + pageText, + pageUrl, + reasoning, + taskCompleted, + timeMs, + additionalProperties, + ) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Action{type=$type, action=$action, instruction=$instruction, pageText=$pageText, pageUrl=$pageUrl, reasoning=$reasoning, taskCompleted=$taskCompleted, timeMs=$timeMs, additionalProperties=$additionalProperties}" + } + + class Metadata + @JsonCreator + private constructor( + @com.fasterxml.jackson.annotation.JsonValue + private val additionalProperties: Map + ) { + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = additionalProperties + + fun toBuilder() = Builder().from(this) + + companion object { + + /** Returns a mutable builder for constructing an instance of [Metadata]. */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Metadata]. */ + class Builder internal constructor() { + + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(metadata: Metadata) = apply { + additionalProperties = metadata.additionalProperties.toMutableMap() + } + + 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 [Metadata]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): Metadata = Metadata(additionalProperties.toImmutable()) + } + + private var validated: Boolean = false + + fun validate(): Metadata = apply { + if (validated) { + return@apply + } + + 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. + */ + @JvmSynthetic + internal fun validity(): Int = + additionalProperties.count { (_, value) -> + !value.isNull() && !value.isMissing() + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Metadata && additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { Objects.hash(additionalProperties) } + + override fun hashCode(): Int = hashCode + + override fun toString() = "Metadata{additionalProperties=$additionalProperties}" + } + + class Usage + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val inferenceTimeMs: JsonField, + private val inputTokens: JsonField, + private val outputTokens: JsonField, + private val cachedInputTokens: JsonField, + private val reasoningTokens: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("inference_time_ms") + @ExcludeMissing + inferenceTimeMs: JsonField = JsonMissing.of(), + @JsonProperty("input_tokens") + @ExcludeMissing + inputTokens: JsonField = JsonMissing.of(), + @JsonProperty("output_tokens") + @ExcludeMissing + outputTokens: JsonField = JsonMissing.of(), + @JsonProperty("cached_input_tokens") + @ExcludeMissing + cachedInputTokens: JsonField = JsonMissing.of(), + @JsonProperty("reasoning_tokens") + @ExcludeMissing + reasoningTokens: JsonField = JsonMissing.of(), + ) : this( + inferenceTimeMs, + inputTokens, + outputTokens, + cachedInputTokens, + reasoningTokens, + mutableMapOf(), + ) + + /** + * @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 inferenceTimeMs(): Double = inferenceTimeMs.getRequired("inference_time_ms") + + /** + * @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 inputTokens(): Double = inputTokens.getRequired("input_tokens") + + /** + * @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 outputTokens(): Double = outputTokens.getRequired("output_tokens") + + /** + * @throws StagehandInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun cachedInputTokens(): Optional = + cachedInputTokens.getOptional("cached_input_tokens") + + /** + * @throws StagehandInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun reasoningTokens(): Optional = + reasoningTokens.getOptional("reasoning_tokens") + + /** + * Returns the raw JSON value of [inferenceTimeMs]. + * + * Unlike [inferenceTimeMs], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("inference_time_ms") + @ExcludeMissing + fun _inferenceTimeMs(): JsonField = inferenceTimeMs + + /** + * Returns the raw JSON value of [inputTokens]. + * + * Unlike [inputTokens], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("input_tokens") + @ExcludeMissing + fun _inputTokens(): JsonField = inputTokens + + /** + * Returns the raw JSON value of [outputTokens]. + * + * Unlike [outputTokens], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("output_tokens") + @ExcludeMissing + fun _outputTokens(): JsonField = outputTokens + + /** + * Returns the raw JSON value of [cachedInputTokens]. + * + * Unlike [cachedInputTokens], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("cached_input_tokens") + @ExcludeMissing + fun _cachedInputTokens(): JsonField = cachedInputTokens + + /** + * Returns the raw JSON value of [reasoningTokens]. + * + * Unlike [reasoningTokens], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("reasoning_tokens") + @ExcludeMissing + fun _reasoningTokens(): JsonField = reasoningTokens + + @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 [Usage]. + * + * The following fields are required: + * ```java + * .inferenceTimeMs() + * .inputTokens() + * .outputTokens() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Usage]. */ + class Builder internal constructor() { + + private var inferenceTimeMs: JsonField? = null + private var inputTokens: JsonField? = null + private var outputTokens: JsonField? = null + private var cachedInputTokens: JsonField = JsonMissing.of() + private var reasoningTokens: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(usage: Usage) = apply { + inferenceTimeMs = usage.inferenceTimeMs + inputTokens = usage.inputTokens + outputTokens = usage.outputTokens + cachedInputTokens = usage.cachedInputTokens + reasoningTokens = usage.reasoningTokens + additionalProperties = usage.additionalProperties.toMutableMap() + } + + fun inferenceTimeMs(inferenceTimeMs: Double) = + inferenceTimeMs(JsonField.of(inferenceTimeMs)) + + /** + * Sets [Builder.inferenceTimeMs] to an arbitrary JSON value. + * + * You should usually call [Builder.inferenceTimeMs] with a well-typed [Double] + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun inferenceTimeMs(inferenceTimeMs: JsonField) = apply { + this.inferenceTimeMs = inferenceTimeMs + } + + fun inputTokens(inputTokens: Double) = inputTokens(JsonField.of(inputTokens)) + + /** + * Sets [Builder.inputTokens] to an arbitrary JSON value. + * + * You should usually call [Builder.inputTokens] with a well-typed [Double] + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun inputTokens(inputTokens: JsonField) = apply { + this.inputTokens = inputTokens + } + + fun outputTokens(outputTokens: Double) = + outputTokens(JsonField.of(outputTokens)) + + /** + * Sets [Builder.outputTokens] to an arbitrary JSON value. + * + * You should usually call [Builder.outputTokens] with a well-typed [Double] + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun outputTokens(outputTokens: JsonField) = apply { + this.outputTokens = outputTokens + } + + fun cachedInputTokens(cachedInputTokens: Double) = + cachedInputTokens(JsonField.of(cachedInputTokens)) + + /** + * Sets [Builder.cachedInputTokens] to an arbitrary JSON value. + * + * You should usually call [Builder.cachedInputTokens] with a well-typed + * [Double] value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun cachedInputTokens(cachedInputTokens: JsonField) = apply { + this.cachedInputTokens = cachedInputTokens + } + + fun reasoningTokens(reasoningTokens: Double) = + reasoningTokens(JsonField.of(reasoningTokens)) + + /** + * Sets [Builder.reasoningTokens] to an arbitrary JSON value. + * + * You should usually call [Builder.reasoningTokens] with a well-typed [Double] + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun reasoningTokens(reasoningTokens: JsonField) = apply { + this.reasoningTokens = reasoningTokens + } + + 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 [Usage]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .inferenceTimeMs() + * .inputTokens() + * .outputTokens() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): Usage = + Usage( + checkRequired("inferenceTimeMs", inferenceTimeMs), + checkRequired("inputTokens", inputTokens), + checkRequired("outputTokens", outputTokens), + cachedInputTokens, + reasoningTokens, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): Usage = apply { + if (validated) { + return@apply + } + + inferenceTimeMs() + inputTokens() + outputTokens() + cachedInputTokens() + reasoningTokens() + 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. + */ + @JvmSynthetic + internal fun validity(): Int = + (if (inferenceTimeMs.asKnown().isPresent) 1 else 0) + + (if (inputTokens.asKnown().isPresent) 1 else 0) + + (if (outputTokens.asKnown().isPresent) 1 else 0) + + (if (cachedInputTokens.asKnown().isPresent) 1 else 0) + + (if (reasoningTokens.asKnown().isPresent) 1 else 0) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Usage && + inferenceTimeMs == other.inferenceTimeMs && + inputTokens == other.inputTokens && + outputTokens == other.outputTokens && + cachedInputTokens == other.cachedInputTokens && + reasoningTokens == other.reasoningTokens && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash( + inferenceTimeMs, + inputTokens, + outputTokens, + cachedInputTokens, + reasoningTokens, + additionalProperties, + ) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Usage{inferenceTimeMs=$inferenceTimeMs, inputTokens=$inputTokens, outputTokens=$outputTokens, cachedInputTokens=$cachedInputTokens, reasoningTokens=$reasoningTokens, additionalProperties=$additionalProperties}" + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Result && + actions == other.actions && + completed == other.completed && + message == other.message && + success == other.success && + metadata == other.metadata && + usage == other.usage && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash( + actions, + completed, + message, + success, + metadata, + usage, + additionalProperties, + ) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Result{actions=$actions, completed=$completed, message=$message, success=$success, metadata=$metadata, usage=$usage, additionalProperties=$additionalProperties}" + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Data && + result == other.result && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { Objects.hash(result, additionalProperties) } + + override fun hashCode(): Int = hashCode + + 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 { + + @JvmField val TRUE = of(true) + + @JvmStatic 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().orElseThrow { + 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. + */ + @JvmSynthetic 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 + } + + return other is SessionExecuteResponse && + data == other.data && + success == other.success && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { Objects.hash(data, success, additionalProperties) } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "SessionExecuteResponse{data=$data, success=$success, additionalProperties=$additionalProperties}" +} diff --git a/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionExtractParams.kt b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionExtractParams.kt index 18414ff..b86cdc3 100644 --- a/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionExtractParams.kt +++ b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionExtractParams.kt @@ -2,11 +2,23 @@ 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 import com.browserbase.api.core.JsonValue import com.browserbase.api.core.Params import com.browserbase.api.core.http.Headers import com.browserbase.api.core.http.QueryParams +import com.browserbase.api.core.toImmutable +import com.browserbase.api.errors.StagehandInvalidDataException +import com.fasterxml.jackson.annotation.JsonAnyGetter +import com.fasterxml.jackson.annotation.JsonAnySetter +import com.fasterxml.jackson.annotation.JsonCreator +import com.fasterxml.jackson.annotation.JsonProperty +import java.time.OffsetDateTime +import java.time.format.DateTimeFormatter +import java.util.Collections import java.util.Objects import java.util.Optional import kotlin.jvm.optionals.getOrNull @@ -14,27 +26,90 @@ import kotlin.jvm.optionals.getOrNull /** Extracts structured data from the current page using AI-powered analysis. */ class SessionExtractParams private constructor( - private val id: JsonValue?, - private val xLanguage: JsonValue?, - private val xSdkVersion: JsonValue?, - private val xSentAt: JsonValue?, - private val xStreamResponse: JsonValue?, - private val body: JsonValue, + private val id: String?, + private val xLanguage: XLanguage?, + private val xSdkVersion: String?, + private val xSentAt: OffsetDateTime?, + private val xStreamResponse: XStreamResponse?, + private val body: Body, private val additionalHeaders: Headers, private val additionalQueryParams: QueryParams, ) : Params { - fun id(): Optional = Optional.ofNullable(id) + /** Unique session identifier */ + fun id(): Optional = Optional.ofNullable(id) - fun xLanguage(): Optional = Optional.ofNullable(xLanguage) + /** Client SDK language */ + fun xLanguage(): Optional = Optional.ofNullable(xLanguage) - fun xSdkVersion(): Optional = Optional.ofNullable(xSdkVersion) + /** Version of the Stagehand SDK */ + fun xSdkVersion(): Optional = Optional.ofNullable(xSdkVersion) - fun xSentAt(): Optional = Optional.ofNullable(xSentAt) + /** ISO timestamp when request was sent */ + fun xSentAt(): Optional = Optional.ofNullable(xSentAt) - fun xStreamResponse(): Optional = Optional.ofNullable(xStreamResponse) + /** Whether to stream the response via SSE */ + fun xStreamResponse(): Optional = Optional.ofNullable(xStreamResponse) - fun body(): JsonValue = body + /** + * Target frame ID for the extraction + * + * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun frameId(): Optional = body.frameId() + + /** + * Natural language instruction for what to extract + * + * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun instruction(): Optional = body.instruction() + + /** + * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun options(): Optional = body.options() + + /** + * JSON Schema defining the structure of data to extract + * + * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun schema(): Optional = body.schema() + + /** + * Returns the raw JSON value of [frameId]. + * + * Unlike [frameId], this method doesn't throw if the JSON field has an unexpected type. + */ + fun _frameId(): JsonField = body._frameId() + + /** + * Returns the raw JSON value of [instruction]. + * + * Unlike [instruction], this method doesn't throw if the JSON field has an unexpected type. + */ + fun _instruction(): JsonField = body._instruction() + + /** + * Returns the raw JSON value of [options]. + * + * Unlike [options], this method doesn't throw if the JSON field has an unexpected type. + */ + fun _options(): JsonField = body._options() + + /** + * Returns the raw JSON value of [schema]. + * + * Unlike [schema], this method doesn't throw if the JSON field has an unexpected type. + */ + fun _schema(): JsonField = body._schema() + + fun _additionalBodyProperties(): Map = body._additionalProperties() /** Additional headers to send with the request. */ fun _additionalHeaders(): Headers = additionalHeaders @@ -55,12 +130,12 @@ private constructor( /** A builder for [SessionExtractParams]. */ class Builder internal constructor() { - private var id: JsonValue? = null - private var xLanguage: JsonValue? = null - private var xSdkVersion: JsonValue? = null - private var xSentAt: JsonValue? = null - private var xStreamResponse: JsonValue? = null - private var body: JsonValue = JsonMissing.of() + private var id: String? = null + private var xLanguage: XLanguage? = null + private var xSdkVersion: String? = null + private var xSentAt: OffsetDateTime? = null + private var xStreamResponse: XStreamResponse? = null + private var body: Body.Builder = Body.builder() private var additionalHeaders: Headers.Builder = Headers.builder() private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() @@ -71,40 +146,118 @@ private constructor( xSdkVersion = sessionExtractParams.xSdkVersion xSentAt = sessionExtractParams.xSentAt xStreamResponse = sessionExtractParams.xStreamResponse - body = sessionExtractParams.body + body = sessionExtractParams.body.toBuilder() additionalHeaders = sessionExtractParams.additionalHeaders.toBuilder() additionalQueryParams = sessionExtractParams.additionalQueryParams.toBuilder() } - fun id(id: JsonValue?) = apply { this.id = id } + /** Unique session identifier */ + fun id(id: String?) = apply { this.id = id } /** Alias for calling [Builder.id] with `id.orElse(null)`. */ - fun id(id: Optional) = id(id.getOrNull()) + fun id(id: Optional) = id(id.getOrNull()) - fun xLanguage(xLanguage: JsonValue?) = apply { this.xLanguage = xLanguage } + /** Client SDK language */ + fun xLanguage(xLanguage: XLanguage?) = apply { this.xLanguage = xLanguage } /** Alias for calling [Builder.xLanguage] with `xLanguage.orElse(null)`. */ - fun xLanguage(xLanguage: Optional) = xLanguage(xLanguage.getOrNull()) + fun xLanguage(xLanguage: Optional) = xLanguage(xLanguage.getOrNull()) - fun xSdkVersion(xSdkVersion: JsonValue?) = apply { this.xSdkVersion = xSdkVersion } + /** Version of the Stagehand SDK */ + fun xSdkVersion(xSdkVersion: String?) = apply { this.xSdkVersion = xSdkVersion } /** Alias for calling [Builder.xSdkVersion] with `xSdkVersion.orElse(null)`. */ - fun xSdkVersion(xSdkVersion: Optional) = xSdkVersion(xSdkVersion.getOrNull()) + fun xSdkVersion(xSdkVersion: Optional) = xSdkVersion(xSdkVersion.getOrNull()) - fun xSentAt(xSentAt: JsonValue?) = apply { this.xSentAt = xSentAt } + /** ISO timestamp when request was sent */ + fun xSentAt(xSentAt: OffsetDateTime?) = apply { this.xSentAt = xSentAt } /** Alias for calling [Builder.xSentAt] with `xSentAt.orElse(null)`. */ - fun xSentAt(xSentAt: Optional) = xSentAt(xSentAt.getOrNull()) + fun xSentAt(xSentAt: Optional) = xSentAt(xSentAt.getOrNull()) - fun xStreamResponse(xStreamResponse: JsonValue?) = apply { + /** Whether to stream the response via SSE */ + fun xStreamResponse(xStreamResponse: XStreamResponse?) = apply { this.xStreamResponse = xStreamResponse } /** Alias for calling [Builder.xStreamResponse] with `xStreamResponse.orElse(null)`. */ - fun xStreamResponse(xStreamResponse: Optional) = + fun xStreamResponse(xStreamResponse: Optional) = xStreamResponse(xStreamResponse.getOrNull()) - fun body(body: JsonValue) = apply { this.body = body } + /** + * Sets the entire request body. + * + * This is generally only useful if you are already constructing the body separately. + * Otherwise, it's more convenient to use the top-level setters instead: + * - [frameId] + * - [instruction] + * - [options] + * - [schema] + */ + fun body(body: Body) = apply { this.body = body.toBuilder() } + + /** Target frame ID for the extraction */ + fun frameId(frameId: String) = apply { body.frameId(frameId) } + + /** + * Sets [Builder.frameId] to an arbitrary JSON value. + * + * You should usually call [Builder.frameId] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun frameId(frameId: JsonField) = apply { body.frameId(frameId) } + + /** Natural language instruction for what to extract */ + fun instruction(instruction: String) = apply { body.instruction(instruction) } + + /** + * Sets [Builder.instruction] to an arbitrary JSON value. + * + * You should usually call [Builder.instruction] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun instruction(instruction: JsonField) = apply { body.instruction(instruction) } + + fun options(options: Options) = apply { body.options(options) } + + /** + * Sets [Builder.options] to an arbitrary JSON value. + * + * You should usually call [Builder.options] with a well-typed [Options] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun options(options: JsonField) = apply { body.options(options) } + + /** JSON Schema defining the structure of data to extract */ + fun schema(schema: Schema) = apply { body.schema(schema) } + + /** + * Sets [Builder.schema] to an arbitrary JSON value. + * + * You should usually call [Builder.schema] with a well-typed [Schema] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun schema(schema: JsonField) = apply { body.schema(schema) } + + fun additionalBodyProperties(additionalBodyProperties: Map) = apply { + body.additionalProperties(additionalBodyProperties) + } + + fun putAdditionalBodyProperty(key: String, value: JsonValue) = apply { + body.putAdditionalProperty(key, value) + } + + fun putAllAdditionalBodyProperties(additionalBodyProperties: Map) = + apply { + body.putAllAdditionalProperties(additionalBodyProperties) + } + + fun removeAdditionalBodyProperty(key: String) = apply { body.removeAdditionalProperty(key) } + + fun removeAllAdditionalBodyProperties(keys: Set) = apply { + body.removeAllAdditionalProperties(keys) + } fun additionalHeaders(additionalHeaders: Headers) = apply { this.additionalHeaders.clear() @@ -216,24 +369,872 @@ private constructor( xSdkVersion, xSentAt, xStreamResponse, - body, + body.build(), additionalHeaders.build(), additionalQueryParams.build(), ) } - fun _body(): JsonValue = body + fun _body(): Body = body fun _pathParam(index: Int): String = when (index) { - 0 -> id?.toString() ?: "" + 0 -> id ?: "" else -> "" } - override fun _headers(): Headers = Headers.builder().apply { putAll(additionalHeaders) }.build() + override fun _headers(): Headers = + Headers.builder() + .apply { + xLanguage?.let { put("x-language", it.toString()) } + xSdkVersion?.let { put("x-sdk-version", it) } + xSentAt?.let { put("x-sent-at", DateTimeFormatter.ISO_OFFSET_DATE_TIME.format(it)) } + xStreamResponse?.let { put("x-stream-response", it.toString()) } + putAll(additionalHeaders) + } + .build() override fun _queryParams(): QueryParams = additionalQueryParams + class Body + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val frameId: JsonField, + private val instruction: JsonField, + private val options: JsonField, + private val schema: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("frameId") @ExcludeMissing frameId: JsonField = JsonMissing.of(), + @JsonProperty("instruction") + @ExcludeMissing + instruction: JsonField = JsonMissing.of(), + @JsonProperty("options") @ExcludeMissing options: JsonField = JsonMissing.of(), + @JsonProperty("schema") @ExcludeMissing schema: JsonField = JsonMissing.of(), + ) : this(frameId, instruction, options, schema, mutableMapOf()) + + /** + * Target frame ID for the extraction + * + * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun frameId(): Optional = frameId.getOptional("frameId") + + /** + * Natural language instruction for what to extract + * + * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun instruction(): Optional = instruction.getOptional("instruction") + + /** + * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun options(): Optional = options.getOptional("options") + + /** + * JSON Schema defining the structure of data to extract + * + * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun schema(): Optional = schema.getOptional("schema") + + /** + * Returns the raw JSON value of [frameId]. + * + * Unlike [frameId], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("frameId") @ExcludeMissing fun _frameId(): JsonField = frameId + + /** + * Returns the raw JSON value of [instruction]. + * + * Unlike [instruction], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("instruction") + @ExcludeMissing + fun _instruction(): JsonField = instruction + + /** + * Returns the raw JSON value of [options]. + * + * Unlike [options], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("options") @ExcludeMissing fun _options(): JsonField = options + + /** + * Returns the raw JSON value of [schema]. + * + * Unlike [schema], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("schema") @ExcludeMissing fun _schema(): JsonField = schema + + @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 [Body]. */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Body]. */ + class Builder internal constructor() { + + private var frameId: JsonField = JsonMissing.of() + private var instruction: JsonField = JsonMissing.of() + private var options: JsonField = JsonMissing.of() + private var schema: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(body: Body) = apply { + frameId = body.frameId + instruction = body.instruction + options = body.options + schema = body.schema + additionalProperties = body.additionalProperties.toMutableMap() + } + + /** Target frame ID for the extraction */ + fun frameId(frameId: String) = frameId(JsonField.of(frameId)) + + /** + * Sets [Builder.frameId] to an arbitrary JSON value. + * + * You should usually call [Builder.frameId] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun frameId(frameId: JsonField) = apply { this.frameId = frameId } + + /** Natural language instruction for what to extract */ + fun instruction(instruction: String) = instruction(JsonField.of(instruction)) + + /** + * Sets [Builder.instruction] to an arbitrary JSON value. + * + * You should usually call [Builder.instruction] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun instruction(instruction: JsonField) = apply { + this.instruction = instruction + } + + fun options(options: Options) = options(JsonField.of(options)) + + /** + * Sets [Builder.options] to an arbitrary JSON value. + * + * You should usually call [Builder.options] with a well-typed [Options] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun options(options: JsonField) = apply { this.options = options } + + /** JSON Schema defining the structure of data to extract */ + fun schema(schema: Schema) = schema(JsonField.of(schema)) + + /** + * Sets [Builder.schema] to an arbitrary JSON value. + * + * You should usually call [Builder.schema] with a well-typed [Schema] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun schema(schema: JsonField) = apply { this.schema = schema } + + 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 [Body]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): Body = + Body(frameId, instruction, options, schema, additionalProperties.toMutableMap()) + } + + private var validated: Boolean = false + + fun validate(): Body = apply { + if (validated) { + return@apply + } + + frameId() + instruction() + options().ifPresent { it.validate() } + schema().ifPresent { it.validate() } + 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. + */ + @JvmSynthetic + internal fun validity(): Int = + (if (frameId.asKnown().isPresent) 1 else 0) + + (if (instruction.asKnown().isPresent) 1 else 0) + + (options.asKnown().getOrNull()?.validity() ?: 0) + + (schema.asKnown().getOrNull()?.validity() ?: 0) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Body && + frameId == other.frameId && + instruction == other.instruction && + options == other.options && + schema == other.schema && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(frameId, instruction, options, schema, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Body{frameId=$frameId, instruction=$instruction, options=$options, schema=$schema, additionalProperties=$additionalProperties}" + } + + class Options + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val model: JsonField, + private val selector: JsonField, + private val timeout: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("model") @ExcludeMissing model: JsonField = JsonMissing.of(), + @JsonProperty("selector") + @ExcludeMissing + selector: JsonField = JsonMissing.of(), + @JsonProperty("timeout") @ExcludeMissing timeout: JsonField = JsonMissing.of(), + ) : this(model, selector, timeout, mutableMapOf()) + + /** + * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun model(): Optional = model.getOptional("model") + + /** + * CSS selector to scope extraction to a specific element + * + * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun selector(): Optional = selector.getOptional("selector") + + /** + * Timeout in ms for the extraction + * + * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun timeout(): Optional = timeout.getOptional("timeout") + + /** + * Returns the raw JSON value of [model]. + * + * Unlike [model], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("model") @ExcludeMissing fun _model(): JsonField = model + + /** + * 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 [timeout]. + * + * Unlike [timeout], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("timeout") @ExcludeMissing fun _timeout(): JsonField = timeout + + @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 [Options]. */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Options]. */ + class Builder internal constructor() { + + private var model: JsonField = JsonMissing.of() + private var selector: JsonField = JsonMissing.of() + private var timeout: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(options: Options) = apply { + model = options.model + selector = options.selector + timeout = options.timeout + additionalProperties = options.additionalProperties.toMutableMap() + } + + fun model(model: ModelConfig) = model(JsonField.of(model)) + + /** + * Sets [Builder.model] to an arbitrary JSON value. + * + * You should usually call [Builder.model] with a well-typed [ModelConfig] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + 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.ofUnionMember1(unionMember1)`. */ + fun model(unionMember1: ModelConfig.UnionMember1) = + model(ModelConfig.ofUnionMember1(unionMember1)) + + /** CSS selector to scope extraction to a specific 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 } + + /** Timeout in ms for the extraction */ + fun timeout(timeout: Double) = timeout(JsonField.of(timeout)) + + /** + * Sets [Builder.timeout] to an arbitrary JSON value. + * + * You should usually call [Builder.timeout] with a well-typed [Double] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun timeout(timeout: JsonField) = apply { this.timeout = timeout } + + 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 [Options]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): Options = + Options(model, selector, timeout, additionalProperties.toMutableMap()) + } + + private var validated: Boolean = false + + fun validate(): Options = apply { + if (validated) { + return@apply + } + + model().ifPresent { it.validate() } + selector() + timeout() + 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. + */ + @JvmSynthetic + internal fun validity(): Int = + (model.asKnown().getOrNull()?.validity() ?: 0) + + (if (selector.asKnown().isPresent) 1 else 0) + + (if (timeout.asKnown().isPresent) 1 else 0) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Options && + model == other.model && + selector == other.selector && + timeout == other.timeout && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(model, selector, timeout, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Options{model=$model, selector=$selector, timeout=$timeout, additionalProperties=$additionalProperties}" + } + + /** JSON Schema defining the structure of data to extract */ + class Schema + @JsonCreator + private constructor( + @com.fasterxml.jackson.annotation.JsonValue + private val additionalProperties: Map + ) { + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = additionalProperties + + fun toBuilder() = Builder().from(this) + + companion object { + + /** Returns a mutable builder for constructing an instance of [Schema]. */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Schema]. */ + class Builder internal constructor() { + + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(schema: Schema) = apply { + additionalProperties = schema.additionalProperties.toMutableMap() + } + + 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 [Schema]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): Schema = Schema(additionalProperties.toImmutable()) + } + + private var validated: Boolean = false + + fun validate(): Schema = apply { + if (validated) { + return@apply + } + + 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. + */ + @JvmSynthetic + internal fun validity(): Int = + additionalProperties.count { (_, value) -> !value.isNull() && !value.isMissing() } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Schema && additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { Objects.hash(additionalProperties) } + + override fun hashCode(): Int = hashCode + + override fun toString() = "Schema{additionalProperties=$additionalProperties}" + } + + /** Client SDK language */ + class XLanguage @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 { + + @JvmField val TYPESCRIPT = of("typescript") + + @JvmField val PYTHON = of("python") + + @JvmField val PLAYGROUND = of("playground") + + @JvmStatic fun of(value: String) = XLanguage(JsonField.of(value)) + } + + /** An enum containing [XLanguage]'s known values. */ + enum class Known { + TYPESCRIPT, + PYTHON, + PLAYGROUND, + } + + /** + * An enum containing [XLanguage]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [XLanguage] 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 { + TYPESCRIPT, + PYTHON, + PLAYGROUND, + /** + * An enum member indicating that [XLanguage] 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) { + TYPESCRIPT -> Value.TYPESCRIPT + PYTHON -> Value.PYTHON + PLAYGROUND -> Value.PLAYGROUND + 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) { + TYPESCRIPT -> Known.TYPESCRIPT + PYTHON -> Known.PYTHON + PLAYGROUND -> Known.PLAYGROUND + else -> throw StagehandInvalidDataException("Unknown XLanguage: $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().orElseThrow { + StagehandInvalidDataException("Value is not a String") + } + + private var validated: Boolean = false + + fun validate(): XLanguage = 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. + */ + @JvmSynthetic 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 XLanguage && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + /** Whether to stream the response via SSE */ + class XStreamResponse @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 { + + @JvmField val TRUE = of("true") + + @JvmField val FALSE = of("false") + + @JvmStatic fun of(value: String) = XStreamResponse(JsonField.of(value)) + } + + /** An enum containing [XStreamResponse]'s known values. */ + enum class Known { + TRUE, + FALSE, + } + + /** + * An enum containing [XStreamResponse]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [XStreamResponse] 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, + FALSE, + /** + * An enum member indicating that [XStreamResponse] 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 + FALSE -> Value.FALSE + 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 + FALSE -> Known.FALSE + else -> throw StagehandInvalidDataException("Unknown XStreamResponse: $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().orElseThrow { + StagehandInvalidDataException("Value is not a String") + } + + private var validated: Boolean = false + + fun validate(): XStreamResponse = 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. + */ + @JvmSynthetic 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 XStreamResponse && 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-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionExtractResponse.kt b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionExtractResponse.kt index 1e08b0f..f48f24f 100644 --- a/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionExtractResponse.kt +++ b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionExtractResponse.kt @@ -2,20 +2,61 @@ 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 import com.browserbase.api.core.JsonValue +import com.browserbase.api.core.checkRequired import com.browserbase.api.errors.StagehandInvalidDataException import com.fasterxml.jackson.annotation.JsonAnyGetter import com.fasterxml.jackson.annotation.JsonAnySetter import com.fasterxml.jackson.annotation.JsonCreator +import com.fasterxml.jackson.annotation.JsonProperty import java.util.Collections import java.util.Objects +import java.util.Optional +import kotlin.jvm.optionals.getOrNull class SessionExtractResponse @JsonCreator(mode = JsonCreator.Mode.DISABLED) -private constructor(private val additionalProperties: MutableMap) { +private constructor( + private val data: JsonField, + private val success: JsonField, + private val additionalProperties: MutableMap, +) { - @JsonCreator private constructor() : this(mutableMapOf()) + @JsonCreator + private constructor( + @JsonProperty("data") @ExcludeMissing data: JsonField = JsonMissing.of(), + @JsonProperty("success") @ExcludeMissing success: JsonField = JsonMissing.of(), + ) : this(data, success, mutableMapOf()) + + /** + * @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 data(): Data = data.getRequired("data") + + /** + * @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") + + /** + * Returns the raw JSON value of [data]. + * + * Unlike [data], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("data") @ExcludeMissing fun _data(): JsonField = data + + /** + * 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 @JsonAnySetter private fun putAdditionalProperty(key: String, value: JsonValue) { @@ -31,20 +72,52 @@ private constructor(private val additionalProperties: MutableMap? = null + private var success: JsonField? = null private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic internal fun from(sessionExtractResponse: SessionExtractResponse) = apply { + data = sessionExtractResponse.data + success = sessionExtractResponse.success additionalProperties = sessionExtractResponse.additionalProperties.toMutableMap() } + fun data(data: Data) = data(JsonField.of(data)) + + /** + * Sets [Builder.data] to an arbitrary JSON value. + * + * You should usually call [Builder.data] with a well-typed [Data] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun data(data: JsonField) = apply { this.data = data } + + fun success(success: Success) = 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 + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun success(success: JsonField) = apply { this.success = success } + fun additionalProperties(additionalProperties: Map) = apply { this.additionalProperties.clear() putAllAdditionalProperties(additionalProperties) @@ -68,9 +141,21 @@ private constructor(private val additionalProperties: MutableMap, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("result") @ExcludeMissing result: JsonValue = JsonMissing.of(), + @JsonProperty("actionId") @ExcludeMissing actionId: JsonField = JsonMissing.of(), + ) : this(result, actionId, mutableMapOf()) + + /** Extracted data matching the requested schema */ + @JsonProperty("result") @ExcludeMissing fun _result(): JsonValue = result + + /** + * Action ID for tracking + * + * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun actionId(): Optional = actionId.getOptional("actionId") + + /** + * Returns the raw JSON value of [actionId]. + * + * Unlike [actionId], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("actionId") @ExcludeMissing fun _actionId(): JsonField = actionId + + @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 [Data]. + * + * The following fields are required: + * ```java + * .result() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Data]. */ + class Builder internal constructor() { + + private var result: JsonValue? = null + private var actionId: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(data: Data) = apply { + result = data.result + actionId = data.actionId + additionalProperties = data.additionalProperties.toMutableMap() + } + + /** Extracted data matching the requested schema */ + fun result(result: JsonValue) = apply { this.result = result } + + /** Action ID for tracking */ + fun actionId(actionId: String) = actionId(JsonField.of(actionId)) + + /** + * Sets [Builder.actionId] to an arbitrary JSON value. + * + * You should usually call [Builder.actionId] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun actionId(actionId: JsonField) = apply { this.actionId = actionId } + + 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 [Data]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .result() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): Data = + Data(checkRequired("result", result), actionId, additionalProperties.toMutableMap()) + } + + private var validated: Boolean = false + + fun validate(): Data = apply { + if (validated) { + return@apply + } + + actionId() + 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. + */ + @JvmSynthetic internal fun validity(): Int = (if (actionId.asKnown().isPresent) 1 else 0) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Data && + result == other.result && + actionId == other.actionId && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { Objects.hash(result, actionId, additionalProperties) } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "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 { + + @JvmField val TRUE = of(true) + + @JvmStatic 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().orElseThrow { + 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. + */ + @JvmSynthetic 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 } - return other is SessionExtractResponse && additionalProperties == other.additionalProperties + return other is SessionExtractResponse && + data == other.data && + success == other.success && + additionalProperties == other.additionalProperties } - private val hashCode: Int by lazy { Objects.hash(additionalProperties) } + private val hashCode: Int by lazy { Objects.hash(data, success, additionalProperties) } override fun hashCode(): Int = hashCode - override fun toString() = "SessionExtractResponse{additionalProperties=$additionalProperties}" + override fun toString() = + "SessionExtractResponse{data=$data, success=$success, additionalProperties=$additionalProperties}" } diff --git a/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionNavigateParams.kt b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionNavigateParams.kt index 9f282ab..b07cf2c 100644 --- a/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionNavigateParams.kt +++ b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionNavigateParams.kt @@ -2,11 +2,23 @@ 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 import com.browserbase.api.core.JsonValue import com.browserbase.api.core.Params +import com.browserbase.api.core.checkRequired import com.browserbase.api.core.http.Headers import com.browserbase.api.core.http.QueryParams +import com.browserbase.api.errors.StagehandInvalidDataException +import com.fasterxml.jackson.annotation.JsonAnyGetter +import com.fasterxml.jackson.annotation.JsonAnySetter +import com.fasterxml.jackson.annotation.JsonCreator +import com.fasterxml.jackson.annotation.JsonProperty +import java.time.OffsetDateTime +import java.time.format.DateTimeFormatter +import java.util.Collections import java.util.Objects import java.util.Optional import kotlin.jvm.optionals.getOrNull @@ -14,27 +26,75 @@ import kotlin.jvm.optionals.getOrNull /** Navigates the browser to the specified URL. */ class SessionNavigateParams private constructor( - private val id: JsonValue?, - private val xLanguage: JsonValue?, - private val xSdkVersion: JsonValue?, - private val xSentAt: JsonValue?, - private val xStreamResponse: JsonValue?, - private val body: JsonValue, + private val id: String?, + private val xLanguage: XLanguage?, + private val xSdkVersion: String?, + private val xSentAt: OffsetDateTime?, + private val xStreamResponse: XStreamResponse?, + private val body: Body, private val additionalHeaders: Headers, private val additionalQueryParams: QueryParams, ) : Params { - fun id(): Optional = Optional.ofNullable(id) + /** Unique session identifier */ + fun id(): Optional = Optional.ofNullable(id) - fun xLanguage(): Optional = Optional.ofNullable(xLanguage) + /** Client SDK language */ + fun xLanguage(): Optional = Optional.ofNullable(xLanguage) - fun xSdkVersion(): Optional = Optional.ofNullable(xSdkVersion) + /** Version of the Stagehand SDK */ + fun xSdkVersion(): Optional = Optional.ofNullable(xSdkVersion) - fun xSentAt(): Optional = Optional.ofNullable(xSentAt) + /** ISO timestamp when request was sent */ + fun xSentAt(): Optional = Optional.ofNullable(xSentAt) - fun xStreamResponse(): Optional = Optional.ofNullable(xStreamResponse) + /** Whether to stream the response via SSE */ + fun xStreamResponse(): Optional = Optional.ofNullable(xStreamResponse) - fun body(): JsonValue = body + /** + * URL to navigate to + * + * @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 url(): String = body.url() + + /** + * Target frame ID for the navigation + * + * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun frameId(): Optional = body.frameId() + + /** + * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun options(): Optional = body.options() + + /** + * Returns the raw JSON value of [url]. + * + * Unlike [url], this method doesn't throw if the JSON field has an unexpected type. + */ + fun _url(): JsonField = body._url() + + /** + * Returns the raw JSON value of [frameId]. + * + * Unlike [frameId], this method doesn't throw if the JSON field has an unexpected type. + */ + fun _frameId(): JsonField = body._frameId() + + /** + * Returns the raw JSON value of [options]. + * + * Unlike [options], this method doesn't throw if the JSON field has an unexpected type. + */ + fun _options(): JsonField = body._options() + + fun _additionalBodyProperties(): Map = body._additionalProperties() /** Additional headers to send with the request. */ fun _additionalHeaders(): Headers = additionalHeaders @@ -46,21 +106,26 @@ private constructor( companion object { - @JvmStatic fun none(): SessionNavigateParams = builder().build() - - /** Returns a mutable builder for constructing an instance of [SessionNavigateParams]. */ + /** + * Returns a mutable builder for constructing an instance of [SessionNavigateParams]. + * + * The following fields are required: + * ```java + * .url() + * ``` + */ @JvmStatic fun builder() = Builder() } /** A builder for [SessionNavigateParams]. */ class Builder internal constructor() { - private var id: JsonValue? = null - private var xLanguage: JsonValue? = null - private var xSdkVersion: JsonValue? = null - private var xSentAt: JsonValue? = null - private var xStreamResponse: JsonValue? = null - private var body: JsonValue = JsonMissing.of() + private var id: String? = null + private var xLanguage: XLanguage? = null + private var xSdkVersion: String? = null + private var xSentAt: OffsetDateTime? = null + private var xStreamResponse: XStreamResponse? = null + private var body: Body.Builder = Body.builder() private var additionalHeaders: Headers.Builder = Headers.builder() private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() @@ -71,40 +136,105 @@ private constructor( xSdkVersion = sessionNavigateParams.xSdkVersion xSentAt = sessionNavigateParams.xSentAt xStreamResponse = sessionNavigateParams.xStreamResponse - body = sessionNavigateParams.body + body = sessionNavigateParams.body.toBuilder() additionalHeaders = sessionNavigateParams.additionalHeaders.toBuilder() additionalQueryParams = sessionNavigateParams.additionalQueryParams.toBuilder() } - fun id(id: JsonValue?) = apply { this.id = id } + /** Unique session identifier */ + fun id(id: String?) = apply { this.id = id } /** Alias for calling [Builder.id] with `id.orElse(null)`. */ - fun id(id: Optional) = id(id.getOrNull()) + fun id(id: Optional) = id(id.getOrNull()) - fun xLanguage(xLanguage: JsonValue?) = apply { this.xLanguage = xLanguage } + /** Client SDK language */ + fun xLanguage(xLanguage: XLanguage?) = apply { this.xLanguage = xLanguage } /** Alias for calling [Builder.xLanguage] with `xLanguage.orElse(null)`. */ - fun xLanguage(xLanguage: Optional) = xLanguage(xLanguage.getOrNull()) + fun xLanguage(xLanguage: Optional) = xLanguage(xLanguage.getOrNull()) - fun xSdkVersion(xSdkVersion: JsonValue?) = apply { this.xSdkVersion = xSdkVersion } + /** Version of the Stagehand SDK */ + fun xSdkVersion(xSdkVersion: String?) = apply { this.xSdkVersion = xSdkVersion } /** Alias for calling [Builder.xSdkVersion] with `xSdkVersion.orElse(null)`. */ - fun xSdkVersion(xSdkVersion: Optional) = xSdkVersion(xSdkVersion.getOrNull()) + fun xSdkVersion(xSdkVersion: Optional) = xSdkVersion(xSdkVersion.getOrNull()) - fun xSentAt(xSentAt: JsonValue?) = apply { this.xSentAt = xSentAt } + /** ISO timestamp when request was sent */ + fun xSentAt(xSentAt: OffsetDateTime?) = apply { this.xSentAt = xSentAt } /** Alias for calling [Builder.xSentAt] with `xSentAt.orElse(null)`. */ - fun xSentAt(xSentAt: Optional) = xSentAt(xSentAt.getOrNull()) + fun xSentAt(xSentAt: Optional) = xSentAt(xSentAt.getOrNull()) - fun xStreamResponse(xStreamResponse: JsonValue?) = apply { + /** Whether to stream the response via SSE */ + fun xStreamResponse(xStreamResponse: XStreamResponse?) = apply { this.xStreamResponse = xStreamResponse } /** Alias for calling [Builder.xStreamResponse] with `xStreamResponse.orElse(null)`. */ - fun xStreamResponse(xStreamResponse: Optional) = + fun xStreamResponse(xStreamResponse: Optional) = xStreamResponse(xStreamResponse.getOrNull()) - fun body(body: JsonValue) = apply { this.body = body } + /** + * Sets the entire request body. + * + * This is generally only useful if you are already constructing the body separately. + * Otherwise, it's more convenient to use the top-level setters instead: + * - [url] + * - [frameId] + * - [options] + */ + fun body(body: Body) = apply { this.body = body.toBuilder() } + + /** URL to navigate to */ + fun url(url: String) = apply { body.url(url) } + + /** + * Sets [Builder.url] to an arbitrary JSON value. + * + * You should usually call [Builder.url] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun url(url: JsonField) = apply { body.url(url) } + + /** Target frame ID for the navigation */ + fun frameId(frameId: String) = apply { body.frameId(frameId) } + + /** + * Sets [Builder.frameId] to an arbitrary JSON value. + * + * You should usually call [Builder.frameId] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun frameId(frameId: JsonField) = apply { body.frameId(frameId) } + + fun options(options: Options) = apply { body.options(options) } + + /** + * Sets [Builder.options] to an arbitrary JSON value. + * + * You should usually call [Builder.options] with a well-typed [Options] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun options(options: JsonField) = apply { body.options(options) } + + fun additionalBodyProperties(additionalBodyProperties: Map) = apply { + body.additionalProperties(additionalBodyProperties) + } + + fun putAdditionalBodyProperty(key: String, value: JsonValue) = apply { + body.putAdditionalProperty(key, value) + } + + fun putAllAdditionalBodyProperties(additionalBodyProperties: Map) = + apply { + body.putAllAdditionalProperties(additionalBodyProperties) + } + + fun removeAdditionalBodyProperty(key: String) = apply { body.removeAdditionalProperty(key) } + + fun removeAllAdditionalBodyProperties(keys: Set) = apply { + body.removeAllAdditionalProperties(keys) + } fun additionalHeaders(additionalHeaders: Headers) = apply { this.additionalHeaders.clear() @@ -208,6 +338,13 @@ private constructor( * Returns an immutable instance of [SessionNavigateParams]. * * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .url() + * ``` + * + * @throws IllegalStateException if any required field is unset. */ fun build(): SessionNavigateParams = SessionNavigateParams( @@ -216,24 +353,887 @@ private constructor( xSdkVersion, xSentAt, xStreamResponse, - body, + body.build(), additionalHeaders.build(), additionalQueryParams.build(), ) } - fun _body(): JsonValue = body + fun _body(): Body = body fun _pathParam(index: Int): String = when (index) { - 0 -> id?.toString() ?: "" + 0 -> id ?: "" else -> "" } - override fun _headers(): Headers = Headers.builder().apply { putAll(additionalHeaders) }.build() + override fun _headers(): Headers = + Headers.builder() + .apply { + xLanguage?.let { put("x-language", it.toString()) } + xSdkVersion?.let { put("x-sdk-version", it) } + xSentAt?.let { put("x-sent-at", DateTimeFormatter.ISO_OFFSET_DATE_TIME.format(it)) } + xStreamResponse?.let { put("x-stream-response", it.toString()) } + putAll(additionalHeaders) + } + .build() override fun _queryParams(): QueryParams = additionalQueryParams + class Body + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val url: JsonField, + private val frameId: JsonField, + private val options: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("url") @ExcludeMissing url: JsonField = JsonMissing.of(), + @JsonProperty("frameId") @ExcludeMissing frameId: JsonField = JsonMissing.of(), + @JsonProperty("options") @ExcludeMissing options: JsonField = JsonMissing.of(), + ) : this(url, frameId, options, mutableMapOf()) + + /** + * URL to navigate to + * + * @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 url(): String = url.getRequired("url") + + /** + * Target frame ID for the navigation + * + * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun frameId(): Optional = frameId.getOptional("frameId") + + /** + * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun options(): Optional = options.getOptional("options") + + /** + * Returns the raw JSON value of [url]. + * + * Unlike [url], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("url") @ExcludeMissing fun _url(): JsonField = url + + /** + * Returns the raw JSON value of [frameId]. + * + * Unlike [frameId], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("frameId") @ExcludeMissing fun _frameId(): JsonField = frameId + + /** + * Returns the raw JSON value of [options]. + * + * Unlike [options], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("options") @ExcludeMissing fun _options(): JsonField = options + + @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 [Body]. + * + * The following fields are required: + * ```java + * .url() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Body]. */ + class Builder internal constructor() { + + private var url: JsonField? = null + private var frameId: JsonField = JsonMissing.of() + private var options: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(body: Body) = apply { + url = body.url + frameId = body.frameId + options = body.options + additionalProperties = body.additionalProperties.toMutableMap() + } + + /** URL to navigate to */ + fun url(url: String) = url(JsonField.of(url)) + + /** + * Sets [Builder.url] to an arbitrary JSON value. + * + * You should usually call [Builder.url] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun url(url: JsonField) = apply { this.url = url } + + /** Target frame ID for the navigation */ + fun frameId(frameId: String) = frameId(JsonField.of(frameId)) + + /** + * Sets [Builder.frameId] to an arbitrary JSON value. + * + * You should usually call [Builder.frameId] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun frameId(frameId: JsonField) = apply { this.frameId = frameId } + + fun options(options: Options) = options(JsonField.of(options)) + + /** + * Sets [Builder.options] to an arbitrary JSON value. + * + * You should usually call [Builder.options] with a well-typed [Options] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun options(options: JsonField) = apply { this.options = options } + + 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 [Body]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .url() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): Body = + Body( + checkRequired("url", url), + frameId, + options, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): Body = apply { + if (validated) { + return@apply + } + + url() + frameId() + options().ifPresent { it.validate() } + 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. + */ + @JvmSynthetic + internal fun validity(): Int = + (if (url.asKnown().isPresent) 1 else 0) + + (if (frameId.asKnown().isPresent) 1 else 0) + + (options.asKnown().getOrNull()?.validity() ?: 0) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Body && + url == other.url && + frameId == other.frameId && + options == other.options && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(url, frameId, options, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Body{url=$url, frameId=$frameId, options=$options, additionalProperties=$additionalProperties}" + } + + class Options + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val referer: JsonField, + private val timeout: JsonField, + private val waitUntil: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("referer") @ExcludeMissing referer: JsonField = JsonMissing.of(), + @JsonProperty("timeout") @ExcludeMissing timeout: JsonField = JsonMissing.of(), + @JsonProperty("waitUntil") + @ExcludeMissing + waitUntil: JsonField = JsonMissing.of(), + ) : this(referer, timeout, waitUntil, mutableMapOf()) + + /** + * Referer header to send with the request + * + * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun referer(): Optional = referer.getOptional("referer") + + /** + * Timeout in ms for the navigation + * + * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun timeout(): Optional = timeout.getOptional("timeout") + + /** + * When to consider navigation complete + * + * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun waitUntil(): Optional = waitUntil.getOptional("waitUntil") + + /** + * Returns the raw JSON value of [referer]. + * + * Unlike [referer], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("referer") @ExcludeMissing fun _referer(): JsonField = referer + + /** + * Returns the raw JSON value of [timeout]. + * + * Unlike [timeout], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("timeout") @ExcludeMissing fun _timeout(): JsonField = timeout + + /** + * Returns the raw JSON value of [waitUntil]. + * + * Unlike [waitUntil], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("waitUntil") + @ExcludeMissing + fun _waitUntil(): JsonField = waitUntil + + @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 [Options]. */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Options]. */ + class Builder internal constructor() { + + private var referer: JsonField = JsonMissing.of() + private var timeout: JsonField = JsonMissing.of() + private var waitUntil: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(options: Options) = apply { + referer = options.referer + timeout = options.timeout + waitUntil = options.waitUntil + additionalProperties = options.additionalProperties.toMutableMap() + } + + /** Referer header to send with the request */ + fun referer(referer: String) = referer(JsonField.of(referer)) + + /** + * Sets [Builder.referer] to an arbitrary JSON value. + * + * You should usually call [Builder.referer] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun referer(referer: JsonField) = apply { this.referer = referer } + + /** Timeout in ms for the navigation */ + fun timeout(timeout: Double) = timeout(JsonField.of(timeout)) + + /** + * Sets [Builder.timeout] to an arbitrary JSON value. + * + * You should usually call [Builder.timeout] with a well-typed [Double] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun timeout(timeout: JsonField) = apply { this.timeout = timeout } + + /** When to consider navigation complete */ + fun waitUntil(waitUntil: WaitUntil) = waitUntil(JsonField.of(waitUntil)) + + /** + * Sets [Builder.waitUntil] to an arbitrary JSON value. + * + * You should usually call [Builder.waitUntil] with a well-typed [WaitUntil] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun waitUntil(waitUntil: JsonField) = apply { this.waitUntil = waitUntil } + + 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 [Options]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): Options = + Options(referer, timeout, waitUntil, additionalProperties.toMutableMap()) + } + + private var validated: Boolean = false + + fun validate(): Options = apply { + if (validated) { + return@apply + } + + referer() + timeout() + waitUntil().ifPresent { it.validate() } + 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. + */ + @JvmSynthetic + internal fun validity(): Int = + (if (referer.asKnown().isPresent) 1 else 0) + + (if (timeout.asKnown().isPresent) 1 else 0) + + (waitUntil.asKnown().getOrNull()?.validity() ?: 0) + + /** When to consider navigation complete */ + class WaitUntil @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 { + + @JvmField val LOAD = of("load") + + @JvmField val DOMCONTENTLOADED = of("domcontentloaded") + + @JvmField val NETWORKIDLE = of("networkidle") + + @JvmStatic fun of(value: String) = WaitUntil(JsonField.of(value)) + } + + /** An enum containing [WaitUntil]'s known values. */ + enum class Known { + LOAD, + DOMCONTENTLOADED, + NETWORKIDLE, + } + + /** + * An enum containing [WaitUntil]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [WaitUntil] 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 { + LOAD, + DOMCONTENTLOADED, + NETWORKIDLE, + /** + * An enum member indicating that [WaitUntil] 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) { + LOAD -> Value.LOAD + DOMCONTENTLOADED -> Value.DOMCONTENTLOADED + NETWORKIDLE -> Value.NETWORKIDLE + 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) { + LOAD -> Known.LOAD + DOMCONTENTLOADED -> Known.DOMCONTENTLOADED + NETWORKIDLE -> Known.NETWORKIDLE + else -> throw StagehandInvalidDataException("Unknown WaitUntil: $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().orElseThrow { + StagehandInvalidDataException("Value is not a String") + } + + private var validated: Boolean = false + + fun validate(): WaitUntil = 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. + */ + @JvmSynthetic 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 WaitUntil && 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 Options && + referer == other.referer && + timeout == other.timeout && + waitUntil == other.waitUntil && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(referer, timeout, waitUntil, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Options{referer=$referer, timeout=$timeout, waitUntil=$waitUntil, additionalProperties=$additionalProperties}" + } + + /** Client SDK language */ + class XLanguage @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 { + + @JvmField val TYPESCRIPT = of("typescript") + + @JvmField val PYTHON = of("python") + + @JvmField val PLAYGROUND = of("playground") + + @JvmStatic fun of(value: String) = XLanguage(JsonField.of(value)) + } + + /** An enum containing [XLanguage]'s known values. */ + enum class Known { + TYPESCRIPT, + PYTHON, + PLAYGROUND, + } + + /** + * An enum containing [XLanguage]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [XLanguage] 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 { + TYPESCRIPT, + PYTHON, + PLAYGROUND, + /** + * An enum member indicating that [XLanguage] 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) { + TYPESCRIPT -> Value.TYPESCRIPT + PYTHON -> Value.PYTHON + PLAYGROUND -> Value.PLAYGROUND + 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) { + TYPESCRIPT -> Known.TYPESCRIPT + PYTHON -> Known.PYTHON + PLAYGROUND -> Known.PLAYGROUND + else -> throw StagehandInvalidDataException("Unknown XLanguage: $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().orElseThrow { + StagehandInvalidDataException("Value is not a String") + } + + private var validated: Boolean = false + + fun validate(): XLanguage = 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. + */ + @JvmSynthetic 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 XLanguage && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + /** Whether to stream the response via SSE */ + class XStreamResponse @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 { + + @JvmField val TRUE = of("true") + + @JvmField val FALSE = of("false") + + @JvmStatic fun of(value: String) = XStreamResponse(JsonField.of(value)) + } + + /** An enum containing [XStreamResponse]'s known values. */ + enum class Known { + TRUE, + FALSE, + } + + /** + * An enum containing [XStreamResponse]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [XStreamResponse] 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, + FALSE, + /** + * An enum member indicating that [XStreamResponse] 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 + FALSE -> Value.FALSE + 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 + FALSE -> Known.FALSE + else -> throw StagehandInvalidDataException("Unknown XStreamResponse: $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().orElseThrow { + StagehandInvalidDataException("Value is not a String") + } + + private var validated: Boolean = false + + fun validate(): XStreamResponse = 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. + */ + @JvmSynthetic 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 XStreamResponse && 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-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionNavigateResponse.kt b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionNavigateResponse.kt index 916d1a2..56a53a4 100644 --- a/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionNavigateResponse.kt +++ b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionNavigateResponse.kt @@ -2,20 +2,61 @@ 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 import com.browserbase.api.core.JsonValue +import com.browserbase.api.core.checkRequired import com.browserbase.api.errors.StagehandInvalidDataException import com.fasterxml.jackson.annotation.JsonAnyGetter import com.fasterxml.jackson.annotation.JsonAnySetter import com.fasterxml.jackson.annotation.JsonCreator +import com.fasterxml.jackson.annotation.JsonProperty import java.util.Collections import java.util.Objects +import java.util.Optional +import kotlin.jvm.optionals.getOrNull class SessionNavigateResponse @JsonCreator(mode = JsonCreator.Mode.DISABLED) -private constructor(private val additionalProperties: MutableMap) { +private constructor( + private val data: JsonField, + private val success: JsonField, + private val additionalProperties: MutableMap, +) { - @JsonCreator private constructor() : this(mutableMapOf()) + @JsonCreator + private constructor( + @JsonProperty("data") @ExcludeMissing data: JsonField = JsonMissing.of(), + @JsonProperty("success") @ExcludeMissing success: JsonField = JsonMissing.of(), + ) : this(data, success, mutableMapOf()) + + /** + * @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 data(): Data = data.getRequired("data") + + /** + * @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") + + /** + * Returns the raw JSON value of [data]. + * + * Unlike [data], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("data") @ExcludeMissing fun _data(): JsonField = data + + /** + * 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 @JsonAnySetter private fun putAdditionalProperty(key: String, value: JsonValue) { @@ -31,20 +72,52 @@ private constructor(private val additionalProperties: MutableMap? = null + private var success: JsonField? = null private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic internal fun from(sessionNavigateResponse: SessionNavigateResponse) = apply { + data = sessionNavigateResponse.data + success = sessionNavigateResponse.success additionalProperties = sessionNavigateResponse.additionalProperties.toMutableMap() } + fun data(data: Data) = data(JsonField.of(data)) + + /** + * Sets [Builder.data] to an arbitrary JSON value. + * + * You should usually call [Builder.data] with a well-typed [Data] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun data(data: JsonField) = apply { this.data = data } + + fun success(success: Success) = 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 + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun success(success: JsonField) = apply { this.success = success } + fun additionalProperties(additionalProperties: Map) = apply { this.additionalProperties.clear() putAllAdditionalProperties(additionalProperties) @@ -68,9 +141,21 @@ private constructor(private val additionalProperties: MutableMap, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("result") @ExcludeMissing result: JsonValue = JsonMissing.of(), + @JsonProperty("actionId") @ExcludeMissing actionId: JsonField = JsonMissing.of(), + ) : this(result, actionId, mutableMapOf()) + + /** Navigation response (Playwright Response object or null) */ + @JsonProperty("result") @ExcludeMissing fun _result(): JsonValue = result + + /** + * Action ID for tracking + * + * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun actionId(): Optional = actionId.getOptional("actionId") + + /** + * Returns the raw JSON value of [actionId]. + * + * Unlike [actionId], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("actionId") @ExcludeMissing fun _actionId(): JsonField = actionId + + @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 [Data]. + * + * The following fields are required: + * ```java + * .result() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Data]. */ + class Builder internal constructor() { + + private var result: JsonValue? = null + private var actionId: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(data: Data) = apply { + result = data.result + actionId = data.actionId + additionalProperties = data.additionalProperties.toMutableMap() + } + + /** Navigation response (Playwright Response object or null) */ + fun result(result: JsonValue) = apply { this.result = result } + + /** Action ID for tracking */ + fun actionId(actionId: String) = actionId(JsonField.of(actionId)) + + /** + * Sets [Builder.actionId] to an arbitrary JSON value. + * + * You should usually call [Builder.actionId] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun actionId(actionId: JsonField) = apply { this.actionId = actionId } + + 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 [Data]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .result() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): Data = + Data(checkRequired("result", result), actionId, additionalProperties.toMutableMap()) + } + + private var validated: Boolean = false + + fun validate(): Data = apply { + if (validated) { + return@apply + } + + actionId() + 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. + */ + @JvmSynthetic internal fun validity(): Int = (if (actionId.asKnown().isPresent) 1 else 0) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Data && + result == other.result && + actionId == other.actionId && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { Objects.hash(result, actionId, additionalProperties) } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "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 { + + @JvmField val TRUE = of(true) + + @JvmStatic 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().orElseThrow { + 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. + */ + @JvmSynthetic 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) { @@ -104,12 +479,15 @@ private constructor(private val additionalProperties: MutableMap = Optional.ofNullable(id) + /** Unique session identifier */ + fun id(): Optional = Optional.ofNullable(id) - fun xLanguage(): Optional = Optional.ofNullable(xLanguage) + /** Client SDK language */ + fun xLanguage(): Optional = Optional.ofNullable(xLanguage) - fun xSdkVersion(): Optional = Optional.ofNullable(xSdkVersion) + /** Version of the Stagehand SDK */ + fun xSdkVersion(): Optional = Optional.ofNullable(xSdkVersion) - fun xSentAt(): Optional = Optional.ofNullable(xSentAt) + /** ISO timestamp when request was sent */ + fun xSentAt(): Optional = Optional.ofNullable(xSentAt) - fun xStreamResponse(): Optional = Optional.ofNullable(xStreamResponse) + /** Whether to stream the response via SSE */ + fun xStreamResponse(): Optional = Optional.ofNullable(xStreamResponse) - fun body(): JsonValue = body + /** + * Target frame ID for the observation + * + * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun frameId(): Optional = body.frameId() + + /** + * Natural language instruction for what actions to find + * + * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun instruction(): Optional = body.instruction() + + /** + * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun options(): Optional = body.options() + + /** + * Returns the raw JSON value of [frameId]. + * + * Unlike [frameId], this method doesn't throw if the JSON field has an unexpected type. + */ + fun _frameId(): JsonField = body._frameId() + + /** + * Returns the raw JSON value of [instruction]. + * + * Unlike [instruction], this method doesn't throw if the JSON field has an unexpected type. + */ + fun _instruction(): JsonField = body._instruction() + + /** + * Returns the raw JSON value of [options]. + * + * Unlike [options], this method doesn't throw if the JSON field has an unexpected type. + */ + fun _options(): JsonField = body._options() + + fun _additionalBodyProperties(): Map = body._additionalProperties() /** Additional headers to send with the request. */ fun _additionalHeaders(): Headers = additionalHeaders @@ -57,12 +116,12 @@ private constructor( /** A builder for [SessionObserveParams]. */ class Builder internal constructor() { - private var id: JsonValue? = null - private var xLanguage: JsonValue? = null - private var xSdkVersion: JsonValue? = null - private var xSentAt: JsonValue? = null - private var xStreamResponse: JsonValue? = null - private var body: JsonValue = JsonMissing.of() + private var id: String? = null + private var xLanguage: XLanguage? = null + private var xSdkVersion: String? = null + private var xSentAt: OffsetDateTime? = null + private var xStreamResponse: XStreamResponse? = null + private var body: Body.Builder = Body.builder() private var additionalHeaders: Headers.Builder = Headers.builder() private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() @@ -73,40 +132,106 @@ private constructor( xSdkVersion = sessionObserveParams.xSdkVersion xSentAt = sessionObserveParams.xSentAt xStreamResponse = sessionObserveParams.xStreamResponse - body = sessionObserveParams.body + body = sessionObserveParams.body.toBuilder() additionalHeaders = sessionObserveParams.additionalHeaders.toBuilder() additionalQueryParams = sessionObserveParams.additionalQueryParams.toBuilder() } - fun id(id: JsonValue?) = apply { this.id = id } + /** Unique session identifier */ + fun id(id: String?) = apply { this.id = id } /** Alias for calling [Builder.id] with `id.orElse(null)`. */ - fun id(id: Optional) = id(id.getOrNull()) + fun id(id: Optional) = id(id.getOrNull()) - fun xLanguage(xLanguage: JsonValue?) = apply { this.xLanguage = xLanguage } + /** Client SDK language */ + fun xLanguage(xLanguage: XLanguage?) = apply { this.xLanguage = xLanguage } /** Alias for calling [Builder.xLanguage] with `xLanguage.orElse(null)`. */ - fun xLanguage(xLanguage: Optional) = xLanguage(xLanguage.getOrNull()) + fun xLanguage(xLanguage: Optional) = xLanguage(xLanguage.getOrNull()) - fun xSdkVersion(xSdkVersion: JsonValue?) = apply { this.xSdkVersion = xSdkVersion } + /** Version of the Stagehand SDK */ + fun xSdkVersion(xSdkVersion: String?) = apply { this.xSdkVersion = xSdkVersion } /** Alias for calling [Builder.xSdkVersion] with `xSdkVersion.orElse(null)`. */ - fun xSdkVersion(xSdkVersion: Optional) = xSdkVersion(xSdkVersion.getOrNull()) + fun xSdkVersion(xSdkVersion: Optional) = xSdkVersion(xSdkVersion.getOrNull()) - fun xSentAt(xSentAt: JsonValue?) = apply { this.xSentAt = xSentAt } + /** ISO timestamp when request was sent */ + fun xSentAt(xSentAt: OffsetDateTime?) = apply { this.xSentAt = xSentAt } /** Alias for calling [Builder.xSentAt] with `xSentAt.orElse(null)`. */ - fun xSentAt(xSentAt: Optional) = xSentAt(xSentAt.getOrNull()) + fun xSentAt(xSentAt: Optional) = xSentAt(xSentAt.getOrNull()) - fun xStreamResponse(xStreamResponse: JsonValue?) = apply { + /** Whether to stream the response via SSE */ + fun xStreamResponse(xStreamResponse: XStreamResponse?) = apply { this.xStreamResponse = xStreamResponse } /** Alias for calling [Builder.xStreamResponse] with `xStreamResponse.orElse(null)`. */ - fun xStreamResponse(xStreamResponse: Optional) = + fun xStreamResponse(xStreamResponse: Optional) = xStreamResponse(xStreamResponse.getOrNull()) - fun body(body: JsonValue) = apply { this.body = body } + /** + * Sets the entire request body. + * + * This is generally only useful if you are already constructing the body separately. + * Otherwise, it's more convenient to use the top-level setters instead: + * - [frameId] + * - [instruction] + * - [options] + */ + fun body(body: Body) = apply { this.body = body.toBuilder() } + + /** Target frame ID for the observation */ + fun frameId(frameId: String) = apply { body.frameId(frameId) } + + /** + * Sets [Builder.frameId] to an arbitrary JSON value. + * + * You should usually call [Builder.frameId] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun frameId(frameId: JsonField) = apply { body.frameId(frameId) } + + /** Natural language instruction for what actions to find */ + fun instruction(instruction: String) = apply { body.instruction(instruction) } + + /** + * Sets [Builder.instruction] to an arbitrary JSON value. + * + * You should usually call [Builder.instruction] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun instruction(instruction: JsonField) = apply { body.instruction(instruction) } + + fun options(options: Options) = apply { body.options(options) } + + /** + * Sets [Builder.options] to an arbitrary JSON value. + * + * You should usually call [Builder.options] with a well-typed [Options] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun options(options: JsonField) = apply { body.options(options) } + + fun additionalBodyProperties(additionalBodyProperties: Map) = apply { + body.additionalProperties(additionalBodyProperties) + } + + fun putAdditionalBodyProperty(key: String, value: JsonValue) = apply { + body.putAdditionalProperty(key, value) + } + + fun putAllAdditionalBodyProperties(additionalBodyProperties: Map) = + apply { + body.putAllAdditionalProperties(additionalBodyProperties) + } + + fun removeAdditionalBodyProperty(key: String) = apply { body.removeAdditionalProperty(key) } + + fun removeAllAdditionalBodyProperties(keys: Set) = apply { + body.removeAllAdditionalProperties(keys) + } fun additionalHeaders(additionalHeaders: Headers) = apply { this.additionalHeaders.clear() @@ -218,24 +343,738 @@ private constructor( xSdkVersion, xSentAt, xStreamResponse, - body, + body.build(), additionalHeaders.build(), additionalQueryParams.build(), ) } - fun _body(): JsonValue = body + fun _body(): Body = body fun _pathParam(index: Int): String = when (index) { - 0 -> id?.toString() ?: "" + 0 -> id ?: "" else -> "" } - override fun _headers(): Headers = Headers.builder().apply { putAll(additionalHeaders) }.build() + override fun _headers(): Headers = + Headers.builder() + .apply { + xLanguage?.let { put("x-language", it.toString()) } + xSdkVersion?.let { put("x-sdk-version", it) } + xSentAt?.let { put("x-sent-at", DateTimeFormatter.ISO_OFFSET_DATE_TIME.format(it)) } + xStreamResponse?.let { put("x-stream-response", it.toString()) } + putAll(additionalHeaders) + } + .build() override fun _queryParams(): QueryParams = additionalQueryParams + class Body + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val frameId: JsonField, + private val instruction: JsonField, + private val options: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("frameId") @ExcludeMissing frameId: JsonField = JsonMissing.of(), + @JsonProperty("instruction") + @ExcludeMissing + instruction: JsonField = JsonMissing.of(), + @JsonProperty("options") @ExcludeMissing options: JsonField = JsonMissing.of(), + ) : this(frameId, instruction, options, mutableMapOf()) + + /** + * Target frame ID for the observation + * + * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun frameId(): Optional = frameId.getOptional("frameId") + + /** + * Natural language instruction for what actions to find + * + * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun instruction(): Optional = instruction.getOptional("instruction") + + /** + * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun options(): Optional = options.getOptional("options") + + /** + * Returns the raw JSON value of [frameId]. + * + * Unlike [frameId], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("frameId") @ExcludeMissing fun _frameId(): JsonField = frameId + + /** + * Returns the raw JSON value of [instruction]. + * + * Unlike [instruction], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("instruction") + @ExcludeMissing + fun _instruction(): JsonField = instruction + + /** + * Returns the raw JSON value of [options]. + * + * Unlike [options], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("options") @ExcludeMissing fun _options(): JsonField = options + + @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 [Body]. */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Body]. */ + class Builder internal constructor() { + + private var frameId: JsonField = JsonMissing.of() + private var instruction: JsonField = JsonMissing.of() + private var options: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(body: Body) = apply { + frameId = body.frameId + instruction = body.instruction + options = body.options + additionalProperties = body.additionalProperties.toMutableMap() + } + + /** Target frame ID for the observation */ + fun frameId(frameId: String) = frameId(JsonField.of(frameId)) + + /** + * Sets [Builder.frameId] to an arbitrary JSON value. + * + * You should usually call [Builder.frameId] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun frameId(frameId: JsonField) = apply { this.frameId = frameId } + + /** Natural language instruction for what actions to find */ + fun instruction(instruction: String) = instruction(JsonField.of(instruction)) + + /** + * Sets [Builder.instruction] to an arbitrary JSON value. + * + * You should usually call [Builder.instruction] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun instruction(instruction: JsonField) = apply { + this.instruction = instruction + } + + fun options(options: Options) = options(JsonField.of(options)) + + /** + * Sets [Builder.options] to an arbitrary JSON value. + * + * You should usually call [Builder.options] with a well-typed [Options] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun options(options: JsonField) = apply { this.options = options } + + 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 [Body]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): Body = + Body(frameId, instruction, options, additionalProperties.toMutableMap()) + } + + private var validated: Boolean = false + + fun validate(): Body = apply { + if (validated) { + return@apply + } + + frameId() + instruction() + options().ifPresent { it.validate() } + 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. + */ + @JvmSynthetic + internal fun validity(): Int = + (if (frameId.asKnown().isPresent) 1 else 0) + + (if (instruction.asKnown().isPresent) 1 else 0) + + (options.asKnown().getOrNull()?.validity() ?: 0) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Body && + frameId == other.frameId && + instruction == other.instruction && + options == other.options && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(frameId, instruction, options, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Body{frameId=$frameId, instruction=$instruction, options=$options, additionalProperties=$additionalProperties}" + } + + class Options + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val model: JsonField, + private val selector: JsonField, + private val timeout: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("model") @ExcludeMissing model: JsonField = JsonMissing.of(), + @JsonProperty("selector") + @ExcludeMissing + selector: JsonField = JsonMissing.of(), + @JsonProperty("timeout") @ExcludeMissing timeout: JsonField = JsonMissing.of(), + ) : this(model, selector, timeout, mutableMapOf()) + + /** + * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun model(): Optional = model.getOptional("model") + + /** + * CSS selector to scope observation to a specific element + * + * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun selector(): Optional = selector.getOptional("selector") + + /** + * Timeout in ms for the observation + * + * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun timeout(): Optional = timeout.getOptional("timeout") + + /** + * Returns the raw JSON value of [model]. + * + * Unlike [model], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("model") @ExcludeMissing fun _model(): JsonField = model + + /** + * 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 [timeout]. + * + * Unlike [timeout], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("timeout") @ExcludeMissing fun _timeout(): JsonField = timeout + + @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 [Options]. */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Options]. */ + class Builder internal constructor() { + + private var model: JsonField = JsonMissing.of() + private var selector: JsonField = JsonMissing.of() + private var timeout: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(options: Options) = apply { + model = options.model + selector = options.selector + timeout = options.timeout + additionalProperties = options.additionalProperties.toMutableMap() + } + + fun model(model: ModelConfig) = model(JsonField.of(model)) + + /** + * Sets [Builder.model] to an arbitrary JSON value. + * + * You should usually call [Builder.model] with a well-typed [ModelConfig] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + 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.ofUnionMember1(unionMember1)`. */ + fun model(unionMember1: ModelConfig.UnionMember1) = + model(ModelConfig.ofUnionMember1(unionMember1)) + + /** CSS selector to scope observation to a specific 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 } + + /** Timeout in ms for the observation */ + fun timeout(timeout: Double) = timeout(JsonField.of(timeout)) + + /** + * Sets [Builder.timeout] to an arbitrary JSON value. + * + * You should usually call [Builder.timeout] with a well-typed [Double] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun timeout(timeout: JsonField) = apply { this.timeout = timeout } + + 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 [Options]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): Options = + Options(model, selector, timeout, additionalProperties.toMutableMap()) + } + + private var validated: Boolean = false + + fun validate(): Options = apply { + if (validated) { + return@apply + } + + model().ifPresent { it.validate() } + selector() + timeout() + 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. + */ + @JvmSynthetic + internal fun validity(): Int = + (model.asKnown().getOrNull()?.validity() ?: 0) + + (if (selector.asKnown().isPresent) 1 else 0) + + (if (timeout.asKnown().isPresent) 1 else 0) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Options && + model == other.model && + selector == other.selector && + timeout == other.timeout && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(model, selector, timeout, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Options{model=$model, selector=$selector, timeout=$timeout, additionalProperties=$additionalProperties}" + } + + /** Client SDK language */ + class XLanguage @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 { + + @JvmField val TYPESCRIPT = of("typescript") + + @JvmField val PYTHON = of("python") + + @JvmField val PLAYGROUND = of("playground") + + @JvmStatic fun of(value: String) = XLanguage(JsonField.of(value)) + } + + /** An enum containing [XLanguage]'s known values. */ + enum class Known { + TYPESCRIPT, + PYTHON, + PLAYGROUND, + } + + /** + * An enum containing [XLanguage]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [XLanguage] 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 { + TYPESCRIPT, + PYTHON, + PLAYGROUND, + /** + * An enum member indicating that [XLanguage] 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) { + TYPESCRIPT -> Value.TYPESCRIPT + PYTHON -> Value.PYTHON + PLAYGROUND -> Value.PLAYGROUND + 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) { + TYPESCRIPT -> Known.TYPESCRIPT + PYTHON -> Known.PYTHON + PLAYGROUND -> Known.PLAYGROUND + else -> throw StagehandInvalidDataException("Unknown XLanguage: $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().orElseThrow { + StagehandInvalidDataException("Value is not a String") + } + + private var validated: Boolean = false + + fun validate(): XLanguage = 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. + */ + @JvmSynthetic 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 XLanguage && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + /** Whether to stream the response via SSE */ + class XStreamResponse @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 { + + @JvmField val TRUE = of("true") + + @JvmField val FALSE = of("false") + + @JvmStatic fun of(value: String) = XStreamResponse(JsonField.of(value)) + } + + /** An enum containing [XStreamResponse]'s known values. */ + enum class Known { + TRUE, + FALSE, + } + + /** + * An enum containing [XStreamResponse]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [XStreamResponse] 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, + FALSE, + /** + * An enum member indicating that [XStreamResponse] 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 + FALSE -> Value.FALSE + 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 + FALSE -> Known.FALSE + else -> throw StagehandInvalidDataException("Unknown XStreamResponse: $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().orElseThrow { + StagehandInvalidDataException("Value is not a String") + } + + private var validated: Boolean = false + + fun validate(): XStreamResponse = 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. + */ + @JvmSynthetic 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 XStreamResponse && 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-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionObserveResponse.kt b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionObserveResponse.kt index a27fc10..a06fd48 100644 --- a/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionObserveResponse.kt +++ b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionObserveResponse.kt @@ -2,20 +2,63 @@ 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 import com.browserbase.api.core.JsonValue +import com.browserbase.api.core.checkKnown +import com.browserbase.api.core.checkRequired +import com.browserbase.api.core.toImmutable import com.browserbase.api.errors.StagehandInvalidDataException import com.fasterxml.jackson.annotation.JsonAnyGetter import com.fasterxml.jackson.annotation.JsonAnySetter import com.fasterxml.jackson.annotation.JsonCreator +import com.fasterxml.jackson.annotation.JsonProperty import java.util.Collections import java.util.Objects +import java.util.Optional +import kotlin.jvm.optionals.getOrNull class SessionObserveResponse @JsonCreator(mode = JsonCreator.Mode.DISABLED) -private constructor(private val additionalProperties: MutableMap) { +private constructor( + private val data: JsonField, + private val success: JsonField, + private val additionalProperties: MutableMap, +) { - @JsonCreator private constructor() : this(mutableMapOf()) + @JsonCreator + private constructor( + @JsonProperty("data") @ExcludeMissing data: JsonField = JsonMissing.of(), + @JsonProperty("success") @ExcludeMissing success: JsonField = JsonMissing.of(), + ) : this(data, success, mutableMapOf()) + + /** + * @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 data(): Data = data.getRequired("data") + + /** + * @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") + + /** + * Returns the raw JSON value of [data]. + * + * Unlike [data], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("data") @ExcludeMissing fun _data(): JsonField = data + + /** + * 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 @JsonAnySetter private fun putAdditionalProperty(key: String, value: JsonValue) { @@ -31,20 +74,52 @@ private constructor(private val additionalProperties: MutableMap? = null + private var success: JsonField? = null private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic internal fun from(sessionObserveResponse: SessionObserveResponse) = apply { + data = sessionObserveResponse.data + success = sessionObserveResponse.success additionalProperties = sessionObserveResponse.additionalProperties.toMutableMap() } + fun data(data: Data) = data(JsonField.of(data)) + + /** + * Sets [Builder.data] to an arbitrary JSON value. + * + * You should usually call [Builder.data] with a well-typed [Data] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun data(data: JsonField) = apply { this.data = data } + + fun success(success: Success) = 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 + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun success(success: JsonField) = apply { this.success = success } + fun additionalProperties(additionalProperties: Map) = apply { this.additionalProperties.clear() putAllAdditionalProperties(additionalProperties) @@ -68,9 +143,21 @@ private constructor(private val additionalProperties: MutableMap>, + private val actionId: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("result") + @ExcludeMissing + result: JsonField> = JsonMissing.of(), + @JsonProperty("actionId") @ExcludeMissing actionId: JsonField = JsonMissing.of(), + ) : this(result, actionId, mutableMapOf()) + + /** + * @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 result(): List = result.getRequired("result") + + /** + * Action ID for tracking + * + * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun actionId(): Optional = actionId.getOptional("actionId") + + /** + * Returns the raw JSON value of [result]. + * + * Unlike [result], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("result") @ExcludeMissing fun _result(): JsonField> = result + + /** + * Returns the raw JSON value of [actionId]. + * + * Unlike [actionId], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("actionId") @ExcludeMissing fun _actionId(): JsonField = actionId + + @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 [Data]. + * + * The following fields are required: + * ```java + * .result() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Data]. */ + class Builder internal constructor() { + + private var result: JsonField>? = null + private var actionId: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(data: Data) = apply { + result = data.result.map { it.toMutableList() } + actionId = data.actionId + additionalProperties = data.additionalProperties.toMutableMap() + } + + fun result(result: List) = result(JsonField.of(result)) + + /** + * Sets [Builder.result] to an arbitrary JSON value. + * + * You should usually call [Builder.result] with a well-typed `List` value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun result(result: JsonField>) = apply { + this.result = result.map { it.toMutableList() } + } + + /** + * Adds a single [Action] to [Builder.result]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addResult(result: Action) = apply { + this.result = + (this.result ?: JsonField.of(mutableListOf())).also { + checkKnown("result", it).add(result) + } + } + + /** Action ID for tracking */ + fun actionId(actionId: String) = actionId(JsonField.of(actionId)) + + /** + * Sets [Builder.actionId] to an arbitrary JSON value. + * + * You should usually call [Builder.actionId] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun actionId(actionId: JsonField) = apply { this.actionId = actionId } + + 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 [Data]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .result() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): Data = + Data( + checkRequired("result", result).map { it.toImmutable() }, + actionId, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): Data = apply { + if (validated) { + return@apply + } + + result().forEach { it.validate() } + actionId() + 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. + */ + @JvmSynthetic + internal fun validity(): Int = + (result.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + + (if (actionId.asKnown().isPresent) 1 else 0) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Data && + result == other.result && + actionId == other.actionId && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { Objects.hash(result, actionId, additionalProperties) } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "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 { + + @JvmField val TRUE = of(true) + + @JvmStatic 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().orElseThrow { + 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. + */ + @JvmSynthetic 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 } - return other is SessionObserveResponse && additionalProperties == other.additionalProperties + return other is SessionObserveResponse && + data == other.data && + success == other.success && + additionalProperties == other.additionalProperties } - private val hashCode: Int by lazy { Objects.hash(additionalProperties) } + private val hashCode: Int by lazy { Objects.hash(data, success, additionalProperties) } override fun hashCode(): Int = hashCode - override fun toString() = "SessionObserveResponse{additionalProperties=$additionalProperties}" + override fun toString() = + "SessionObserveResponse{data=$data, success=$success, additionalProperties=$additionalProperties}" } diff --git a/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionStartParams.kt b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionStartParams.kt index e0c55aa..20ba71d 100644 --- a/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionStartParams.kt +++ b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionStartParams.kt @@ -2,11 +2,36 @@ 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 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 import com.browserbase.api.core.http.QueryParams +import com.browserbase.api.core.toImmutable +import com.browserbase.api.errors.StagehandInvalidDataException +import com.fasterxml.jackson.annotation.JsonAnyGetter +import com.fasterxml.jackson.annotation.JsonAnySetter +import com.fasterxml.jackson.annotation.JsonCreator +import com.fasterxml.jackson.annotation.JsonProperty +import com.fasterxml.jackson.core.JsonGenerator +import com.fasterxml.jackson.core.ObjectCodec +import com.fasterxml.jackson.databind.JsonNode +import com.fasterxml.jackson.databind.SerializerProvider +import com.fasterxml.jackson.databind.annotation.JsonDeserialize +import com.fasterxml.jackson.databind.annotation.JsonSerialize +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import java.time.OffsetDateTime +import java.time.format.DateTimeFormatter +import java.util.Collections import java.util.Objects import java.util.Optional import kotlin.jvm.optionals.getOrNull @@ -17,24 +42,204 @@ import kotlin.jvm.optionals.getOrNull */ class SessionStartParams private constructor( - private val xLanguage: JsonValue?, - private val xSdkVersion: JsonValue?, - private val xSentAt: JsonValue?, - private val xStreamResponse: JsonValue?, - private val body: JsonValue, + private val xLanguage: XLanguage?, + private val xSdkVersion: String?, + private val xSentAt: OffsetDateTime?, + private val xStreamResponse: XStreamResponse?, + private val body: Body, private val additionalHeaders: Headers, private val additionalQueryParams: QueryParams, ) : Params { - fun xLanguage(): Optional = Optional.ofNullable(xLanguage) + /** Client SDK language */ + fun xLanguage(): Optional = Optional.ofNullable(xLanguage) - fun xSdkVersion(): Optional = Optional.ofNullable(xSdkVersion) + /** Version of the Stagehand SDK */ + fun xSdkVersion(): Optional = Optional.ofNullable(xSdkVersion) - fun xSentAt(): Optional = Optional.ofNullable(xSentAt) + /** ISO timestamp when request was sent */ + fun xSentAt(): Optional = Optional.ofNullable(xSentAt) - fun xStreamResponse(): Optional = Optional.ofNullable(xStreamResponse) + /** Whether to stream the response via SSE */ + fun xStreamResponse(): Optional = Optional.ofNullable(xStreamResponse) - fun body(): JsonValue = body + /** + * Model name to use for AI operations + * + * @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 = body.modelName() + + /** + * Timeout in ms for act operations + * + * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun actTimeoutMs(): Optional = body.actTimeoutMs() + + /** + * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun browser(): Optional = body.browser() + + /** + * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun browserbaseSessionCreateParams(): Optional = + body.browserbaseSessionCreateParams() + + /** + * Existing Browserbase session ID to resume + * + * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun browserbaseSessionId(): Optional = body.browserbaseSessionId() + + /** + * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun debugDom(): Optional = body.debugDom() + + /** + * Timeout in ms to wait for DOM to settle + * + * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun domSettleTimeoutMs(): Optional = body.domSettleTimeoutMs() + + /** + * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun experimental(): Optional = body.experimental() + + /** + * Enable self-healing for failed actions + * + * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun selfHeal(): Optional = body.selfHeal() + + /** + * Custom system prompt for AI operations + * + * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun systemPrompt(): Optional = body.systemPrompt() + + /** + * Logging verbosity level (0=quiet, 1=normal, 2=debug) + * + * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun verbose(): Optional = body.verbose() + + /** + * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun waitForCaptchaSolves(): Optional = body.waitForCaptchaSolves() + + /** + * Returns the raw JSON value of [modelName]. + * + * Unlike [modelName], this method doesn't throw if the JSON field has an unexpected type. + */ + fun _modelName(): JsonField = body._modelName() + + /** + * Returns the raw JSON value of [actTimeoutMs]. + * + * Unlike [actTimeoutMs], this method doesn't throw if the JSON field has an unexpected type. + */ + fun _actTimeoutMs(): JsonField = body._actTimeoutMs() + + /** + * Returns the raw JSON value of [browser]. + * + * Unlike [browser], this method doesn't throw if the JSON field has an unexpected type. + */ + fun _browser(): JsonField = body._browser() + + /** + * Returns the raw JSON value of [browserbaseSessionCreateParams]. + * + * Unlike [browserbaseSessionCreateParams], this method doesn't throw if the JSON field has an + * unexpected type. + */ + fun _browserbaseSessionCreateParams(): JsonField = + body._browserbaseSessionCreateParams() + + /** + * Returns the raw JSON value of [browserbaseSessionId]. + * + * Unlike [browserbaseSessionId], this method doesn't throw if the JSON field has an unexpected + * type. + */ + fun _browserbaseSessionId(): JsonField = body._browserbaseSessionId() + + /** + * Returns the raw JSON value of [debugDom]. + * + * Unlike [debugDom], this method doesn't throw if the JSON field has an unexpected type. + */ + fun _debugDom(): JsonField = body._debugDom() + + /** + * Returns the raw JSON value of [domSettleTimeoutMs]. + * + * Unlike [domSettleTimeoutMs], this method doesn't throw if the JSON field has an unexpected + * type. + */ + fun _domSettleTimeoutMs(): JsonField = body._domSettleTimeoutMs() + + /** + * Returns the raw JSON value of [experimental]. + * + * Unlike [experimental], this method doesn't throw if the JSON field has an unexpected type. + */ + fun _experimental(): JsonField = body._experimental() + + /** + * Returns the raw JSON value of [selfHeal]. + * + * Unlike [selfHeal], this method doesn't throw if the JSON field has an unexpected type. + */ + fun _selfHeal(): JsonField = body._selfHeal() + + /** + * Returns the raw JSON value of [systemPrompt]. + * + * Unlike [systemPrompt], this method doesn't throw if the JSON field has an unexpected type. + */ + fun _systemPrompt(): JsonField = body._systemPrompt() + + /** + * Returns the raw JSON value of [verbose]. + * + * Unlike [verbose], this method doesn't throw if the JSON field has an unexpected type. + */ + fun _verbose(): JsonField = body._verbose() + + /** + * Returns the raw JSON value of [waitForCaptchaSolves]. + * + * Unlike [waitForCaptchaSolves], this method doesn't throw if the JSON field has an unexpected + * type. + */ + fun _waitForCaptchaSolves(): JsonField = body._waitForCaptchaSolves() + + fun _additionalBodyProperties(): Map = body._additionalProperties() /** Additional headers to send with the request. */ fun _additionalHeaders(): Headers = additionalHeaders @@ -46,20 +251,25 @@ private constructor( companion object { - @JvmStatic fun none(): SessionStartParams = builder().build() - - /** Returns a mutable builder for constructing an instance of [SessionStartParams]. */ + /** + * Returns a mutable builder for constructing an instance of [SessionStartParams]. + * + * The following fields are required: + * ```java + * .modelName() + * ``` + */ @JvmStatic fun builder() = Builder() } /** A builder for [SessionStartParams]. */ class Builder internal constructor() { - private var xLanguage: JsonValue? = null - private var xSdkVersion: JsonValue? = null - private var xSentAt: JsonValue? = null - private var xStreamResponse: JsonValue? = null - private var body: JsonValue = JsonMissing.of() + private var xLanguage: XLanguage? = null + private var xSdkVersion: String? = null + private var xSentAt: OffsetDateTime? = null + private var xStreamResponse: XStreamResponse? = null + private var body: Body.Builder = Body.builder() private var additionalHeaders: Headers.Builder = Headers.builder() private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() @@ -69,35 +279,229 @@ private constructor( xSdkVersion = sessionStartParams.xSdkVersion xSentAt = sessionStartParams.xSentAt xStreamResponse = sessionStartParams.xStreamResponse - body = sessionStartParams.body + body = sessionStartParams.body.toBuilder() additionalHeaders = sessionStartParams.additionalHeaders.toBuilder() additionalQueryParams = sessionStartParams.additionalQueryParams.toBuilder() } - fun xLanguage(xLanguage: JsonValue?) = apply { this.xLanguage = xLanguage } + /** Client SDK language */ + fun xLanguage(xLanguage: XLanguage?) = apply { this.xLanguage = xLanguage } /** Alias for calling [Builder.xLanguage] with `xLanguage.orElse(null)`. */ - fun xLanguage(xLanguage: Optional) = xLanguage(xLanguage.getOrNull()) + fun xLanguage(xLanguage: Optional) = xLanguage(xLanguage.getOrNull()) - fun xSdkVersion(xSdkVersion: JsonValue?) = apply { this.xSdkVersion = xSdkVersion } + /** Version of the Stagehand SDK */ + fun xSdkVersion(xSdkVersion: String?) = apply { this.xSdkVersion = xSdkVersion } /** Alias for calling [Builder.xSdkVersion] with `xSdkVersion.orElse(null)`. */ - fun xSdkVersion(xSdkVersion: Optional) = xSdkVersion(xSdkVersion.getOrNull()) + fun xSdkVersion(xSdkVersion: Optional) = xSdkVersion(xSdkVersion.getOrNull()) - fun xSentAt(xSentAt: JsonValue?) = apply { this.xSentAt = xSentAt } + /** ISO timestamp when request was sent */ + fun xSentAt(xSentAt: OffsetDateTime?) = apply { this.xSentAt = xSentAt } /** Alias for calling [Builder.xSentAt] with `xSentAt.orElse(null)`. */ - fun xSentAt(xSentAt: Optional) = xSentAt(xSentAt.getOrNull()) + fun xSentAt(xSentAt: Optional) = xSentAt(xSentAt.getOrNull()) - fun xStreamResponse(xStreamResponse: JsonValue?) = apply { + /** Whether to stream the response via SSE */ + fun xStreamResponse(xStreamResponse: XStreamResponse?) = apply { this.xStreamResponse = xStreamResponse } /** Alias for calling [Builder.xStreamResponse] with `xStreamResponse.orElse(null)`. */ - fun xStreamResponse(xStreamResponse: Optional) = + fun xStreamResponse(xStreamResponse: Optional) = xStreamResponse(xStreamResponse.getOrNull()) - fun body(body: JsonValue) = apply { this.body = body } + /** + * Sets the entire request body. + * + * This is generally only useful if you are already constructing the body separately. + * Otherwise, it's more convenient to use the top-level setters instead: + * - [modelName] + * - [actTimeoutMs] + * - [browser] + * - [browserbaseSessionCreateParams] + * - [browserbaseSessionId] + * - etc. + */ + fun body(body: Body) = apply { this.body = body.toBuilder() } + + /** Model name to use for AI operations */ + fun modelName(modelName: String) = apply { body.modelName(modelName) } + + /** + * Sets [Builder.modelName] to an arbitrary JSON value. + * + * You should usually call [Builder.modelName] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun modelName(modelName: JsonField) = apply { body.modelName(modelName) } + + /** Timeout in ms for act operations */ + fun actTimeoutMs(actTimeoutMs: Double) = apply { body.actTimeoutMs(actTimeoutMs) } + + /** + * Sets [Builder.actTimeoutMs] to an arbitrary JSON value. + * + * You should usually call [Builder.actTimeoutMs] with a well-typed [Double] value instead. + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun actTimeoutMs(actTimeoutMs: JsonField) = apply { + body.actTimeoutMs(actTimeoutMs) + } + + fun browser(browser: Browser) = apply { body.browser(browser) } + + /** + * Sets [Builder.browser] to an arbitrary JSON value. + * + * You should usually call [Builder.browser] with a well-typed [Browser] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun browser(browser: JsonField) = apply { body.browser(browser) } + + fun browserbaseSessionCreateParams( + browserbaseSessionCreateParams: BrowserbaseSessionCreateParams + ) = apply { body.browserbaseSessionCreateParams(browserbaseSessionCreateParams) } + + /** + * Sets [Builder.browserbaseSessionCreateParams] to an arbitrary JSON value. + * + * You should usually call [Builder.browserbaseSessionCreateParams] with a well-typed + * [BrowserbaseSessionCreateParams] value instead. This method is primarily for setting the + * field to an undocumented or not yet supported value. + */ + fun browserbaseSessionCreateParams( + browserbaseSessionCreateParams: JsonField + ) = apply { body.browserbaseSessionCreateParams(browserbaseSessionCreateParams) } + + /** Existing Browserbase session ID to resume */ + fun browserbaseSessionId(browserbaseSessionId: String) = apply { + body.browserbaseSessionId(browserbaseSessionId) + } + + /** + * Sets [Builder.browserbaseSessionId] to an arbitrary JSON value. + * + * You should usually call [Builder.browserbaseSessionId] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun browserbaseSessionId(browserbaseSessionId: JsonField) = apply { + body.browserbaseSessionId(browserbaseSessionId) + } + + fun debugDom(debugDom: Boolean) = apply { body.debugDom(debugDom) } + + /** + * Sets [Builder.debugDom] to an arbitrary JSON value. + * + * You should usually call [Builder.debugDom] with a well-typed [Boolean] value instead. + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun debugDom(debugDom: JsonField) = apply { body.debugDom(debugDom) } + + /** Timeout in ms to wait for DOM to settle */ + fun domSettleTimeoutMs(domSettleTimeoutMs: Double) = apply { + body.domSettleTimeoutMs(domSettleTimeoutMs) + } + + /** + * Sets [Builder.domSettleTimeoutMs] to an arbitrary JSON value. + * + * You should usually call [Builder.domSettleTimeoutMs] with a well-typed [Double] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun domSettleTimeoutMs(domSettleTimeoutMs: JsonField) = apply { + body.domSettleTimeoutMs(domSettleTimeoutMs) + } + + fun experimental(experimental: Boolean) = apply { body.experimental(experimental) } + + /** + * Sets [Builder.experimental] to an arbitrary JSON value. + * + * You should usually call [Builder.experimental] with a well-typed [Boolean] value instead. + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun experimental(experimental: JsonField) = apply { + body.experimental(experimental) + } + + /** Enable self-healing for failed actions */ + fun selfHeal(selfHeal: Boolean) = apply { body.selfHeal(selfHeal) } + + /** + * Sets [Builder.selfHeal] to an arbitrary JSON value. + * + * You should usually call [Builder.selfHeal] with a well-typed [Boolean] value instead. + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun selfHeal(selfHeal: JsonField) = apply { body.selfHeal(selfHeal) } + + /** Custom system prompt for AI operations */ + fun systemPrompt(systemPrompt: String) = apply { body.systemPrompt(systemPrompt) } + + /** + * Sets [Builder.systemPrompt] to an arbitrary JSON value. + * + * You should usually call [Builder.systemPrompt] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun systemPrompt(systemPrompt: JsonField) = apply { + body.systemPrompt(systemPrompt) + } + + /** Logging verbosity level (0=quiet, 1=normal, 2=debug) */ + fun verbose(verbose: Verbose) = apply { body.verbose(verbose) } + + /** + * Sets [Builder.verbose] to an arbitrary JSON value. + * + * You should usually call [Builder.verbose] with a well-typed [Verbose] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun verbose(verbose: JsonField) = apply { body.verbose(verbose) } + + fun waitForCaptchaSolves(waitForCaptchaSolves: Boolean) = apply { + body.waitForCaptchaSolves(waitForCaptchaSolves) + } + + /** + * Sets [Builder.waitForCaptchaSolves] to an arbitrary JSON value. + * + * You should usually call [Builder.waitForCaptchaSolves] with a well-typed [Boolean] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun waitForCaptchaSolves(waitForCaptchaSolves: JsonField) = apply { + body.waitForCaptchaSolves(waitForCaptchaSolves) + } + + fun additionalBodyProperties(additionalBodyProperties: Map) = apply { + body.additionalProperties(additionalBodyProperties) + } + + fun putAdditionalBodyProperty(key: String, value: JsonValue) = apply { + body.putAdditionalProperty(key, value) + } + + fun putAllAdditionalBodyProperties(additionalBodyProperties: Map) = + apply { + body.putAllAdditionalProperties(additionalBodyProperties) + } + + fun removeAdditionalBodyProperty(key: String) = apply { body.removeAdditionalProperty(key) } + + fun removeAllAdditionalBodyProperties(keys: Set) = apply { + body.removeAllAdditionalProperties(keys) + } fun additionalHeaders(additionalHeaders: Headers) = apply { this.additionalHeaders.clear() @@ -201,6 +605,13 @@ private constructor( * Returns an immutable instance of [SessionStartParams]. * * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .modelName() + * ``` + * + * @throws IllegalStateException if any required field is unset. */ fun build(): SessionStartParams = SessionStartParams( @@ -208,18 +619,7241 @@ private constructor( xSdkVersion, xSentAt, xStreamResponse, - body, + body.build(), additionalHeaders.build(), additionalQueryParams.build(), ) } - fun _body(): JsonValue = body + fun _body(): Body = body - override fun _headers(): Headers = Headers.builder().apply { putAll(additionalHeaders) }.build() + override fun _headers(): Headers = + Headers.builder() + .apply { + xLanguage?.let { put("x-language", it.toString()) } + xSdkVersion?.let { put("x-sdk-version", it) } + xSentAt?.let { put("x-sent-at", DateTimeFormatter.ISO_OFFSET_DATE_TIME.format(it)) } + xStreamResponse?.let { put("x-stream-response", it.toString()) } + putAll(additionalHeaders) + } + .build() override fun _queryParams(): QueryParams = additionalQueryParams + class Body + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val modelName: JsonField, + private val actTimeoutMs: JsonField, + private val browser: JsonField, + private val browserbaseSessionCreateParams: JsonField, + private val browserbaseSessionId: JsonField, + private val debugDom: JsonField, + private val domSettleTimeoutMs: JsonField, + private val experimental: JsonField, + private val selfHeal: JsonField, + private val systemPrompt: JsonField, + private val verbose: JsonField, + private val waitForCaptchaSolves: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("modelName") + @ExcludeMissing + modelName: JsonField = JsonMissing.of(), + @JsonProperty("actTimeoutMs") + @ExcludeMissing + actTimeoutMs: JsonField = JsonMissing.of(), + @JsonProperty("browser") @ExcludeMissing browser: JsonField = JsonMissing.of(), + @JsonProperty("browserbaseSessionCreateParams") + @ExcludeMissing + browserbaseSessionCreateParams: JsonField = + JsonMissing.of(), + @JsonProperty("browserbaseSessionID") + @ExcludeMissing + browserbaseSessionId: JsonField = JsonMissing.of(), + @JsonProperty("debugDom") + @ExcludeMissing + debugDom: JsonField = JsonMissing.of(), + @JsonProperty("domSettleTimeoutMs") + @ExcludeMissing + domSettleTimeoutMs: JsonField = JsonMissing.of(), + @JsonProperty("experimental") + @ExcludeMissing + experimental: JsonField = JsonMissing.of(), + @JsonProperty("selfHeal") + @ExcludeMissing + selfHeal: JsonField = JsonMissing.of(), + @JsonProperty("systemPrompt") + @ExcludeMissing + systemPrompt: JsonField = JsonMissing.of(), + @JsonProperty("verbose") @ExcludeMissing verbose: JsonField = JsonMissing.of(), + @JsonProperty("waitForCaptchaSolves") + @ExcludeMissing + waitForCaptchaSolves: JsonField = JsonMissing.of(), + ) : this( + modelName, + actTimeoutMs, + browser, + browserbaseSessionCreateParams, + browserbaseSessionId, + debugDom, + domSettleTimeoutMs, + experimental, + selfHeal, + systemPrompt, + verbose, + waitForCaptchaSolves, + mutableMapOf(), + ) + + /** + * Model name to use for AI operations + * + * @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") + + /** + * Timeout in ms for act operations + * + * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun actTimeoutMs(): Optional = actTimeoutMs.getOptional("actTimeoutMs") + + /** + * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun browser(): Optional = browser.getOptional("browser") + + /** + * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun browserbaseSessionCreateParams(): Optional = + browserbaseSessionCreateParams.getOptional("browserbaseSessionCreateParams") + + /** + * Existing Browserbase session ID to resume + * + * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun browserbaseSessionId(): Optional = + browserbaseSessionId.getOptional("browserbaseSessionID") + + /** + * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun debugDom(): Optional = debugDom.getOptional("debugDom") + + /** + * Timeout in ms to wait for DOM to settle + * + * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun domSettleTimeoutMs(): Optional = + domSettleTimeoutMs.getOptional("domSettleTimeoutMs") + + /** + * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun experimental(): Optional = experimental.getOptional("experimental") + + /** + * Enable self-healing for failed actions + * + * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun selfHeal(): Optional = selfHeal.getOptional("selfHeal") + + /** + * Custom system prompt for AI operations + * + * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun systemPrompt(): Optional = systemPrompt.getOptional("systemPrompt") + + /** + * Logging verbosity level (0=quiet, 1=normal, 2=debug) + * + * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun verbose(): Optional = verbose.getOptional("verbose") + + /** + * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun waitForCaptchaSolves(): Optional = + waitForCaptchaSolves.getOptional("waitForCaptchaSolves") + + /** + * Returns the raw JSON value of [modelName]. + * + * Unlike [modelName], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("modelName") @ExcludeMissing fun _modelName(): JsonField = modelName + + /** + * Returns the raw JSON value of [actTimeoutMs]. + * + * Unlike [actTimeoutMs], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("actTimeoutMs") + @ExcludeMissing + fun _actTimeoutMs(): JsonField = actTimeoutMs + + /** + * Returns the raw JSON value of [browser]. + * + * Unlike [browser], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("browser") @ExcludeMissing fun _browser(): JsonField = browser + + /** + * Returns the raw JSON value of [browserbaseSessionCreateParams]. + * + * Unlike [browserbaseSessionCreateParams], this method doesn't throw if the JSON field has + * an unexpected type. + */ + @JsonProperty("browserbaseSessionCreateParams") + @ExcludeMissing + fun _browserbaseSessionCreateParams(): JsonField = + browserbaseSessionCreateParams + + /** + * Returns the raw JSON value of [browserbaseSessionId]. + * + * Unlike [browserbaseSessionId], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("browserbaseSessionID") + @ExcludeMissing + fun _browserbaseSessionId(): JsonField = browserbaseSessionId + + /** + * Returns the raw JSON value of [debugDom]. + * + * Unlike [debugDom], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("debugDom") @ExcludeMissing fun _debugDom(): JsonField = debugDom + + /** + * Returns the raw JSON value of [domSettleTimeoutMs]. + * + * Unlike [domSettleTimeoutMs], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("domSettleTimeoutMs") + @ExcludeMissing + fun _domSettleTimeoutMs(): JsonField = domSettleTimeoutMs + + /** + * Returns the raw JSON value of [experimental]. + * + * Unlike [experimental], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("experimental") + @ExcludeMissing + fun _experimental(): JsonField = experimental + + /** + * Returns the raw JSON value of [selfHeal]. + * + * Unlike [selfHeal], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("selfHeal") @ExcludeMissing fun _selfHeal(): JsonField = selfHeal + + /** + * Returns the raw JSON value of [systemPrompt]. + * + * Unlike [systemPrompt], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("systemPrompt") + @ExcludeMissing + fun _systemPrompt(): JsonField = systemPrompt + + /** + * Returns the raw JSON value of [verbose]. + * + * Unlike [verbose], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("verbose") @ExcludeMissing fun _verbose(): JsonField = verbose + + /** + * Returns the raw JSON value of [waitForCaptchaSolves]. + * + * Unlike [waitForCaptchaSolves], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("waitForCaptchaSolves") + @ExcludeMissing + fun _waitForCaptchaSolves(): JsonField = waitForCaptchaSolves + + @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 [Body]. + * + * The following fields are required: + * ```java + * .modelName() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Body]. */ + class Builder internal constructor() { + + private var modelName: JsonField? = null + private var actTimeoutMs: JsonField = JsonMissing.of() + private var browser: JsonField = JsonMissing.of() + private var browserbaseSessionCreateParams: JsonField = + JsonMissing.of() + private var browserbaseSessionId: JsonField = JsonMissing.of() + private var debugDom: JsonField = JsonMissing.of() + private var domSettleTimeoutMs: JsonField = JsonMissing.of() + private var experimental: JsonField = JsonMissing.of() + private var selfHeal: JsonField = JsonMissing.of() + private var systemPrompt: JsonField = JsonMissing.of() + private var verbose: JsonField = JsonMissing.of() + private var waitForCaptchaSolves: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(body: Body) = apply { + modelName = body.modelName + actTimeoutMs = body.actTimeoutMs + browser = body.browser + browserbaseSessionCreateParams = body.browserbaseSessionCreateParams + browserbaseSessionId = body.browserbaseSessionId + debugDom = body.debugDom + domSettleTimeoutMs = body.domSettleTimeoutMs + experimental = body.experimental + selfHeal = body.selfHeal + systemPrompt = body.systemPrompt + verbose = body.verbose + waitForCaptchaSolves = body.waitForCaptchaSolves + additionalProperties = body.additionalProperties.toMutableMap() + } + + /** Model name to use for AI operations */ + fun modelName(modelName: String) = modelName(JsonField.of(modelName)) + + /** + * Sets [Builder.modelName] to an arbitrary JSON value. + * + * You should usually call [Builder.modelName] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun modelName(modelName: JsonField) = apply { this.modelName = modelName } + + /** Timeout in ms for act operations */ + fun actTimeoutMs(actTimeoutMs: Double) = actTimeoutMs(JsonField.of(actTimeoutMs)) + + /** + * Sets [Builder.actTimeoutMs] to an arbitrary JSON value. + * + * You should usually call [Builder.actTimeoutMs] with a well-typed [Double] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun actTimeoutMs(actTimeoutMs: JsonField) = apply { + this.actTimeoutMs = actTimeoutMs + } + + fun browser(browser: Browser) = browser(JsonField.of(browser)) + + /** + * Sets [Builder.browser] to an arbitrary JSON value. + * + * You should usually call [Builder.browser] with a well-typed [Browser] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun browser(browser: JsonField) = apply { this.browser = browser } + + fun browserbaseSessionCreateParams( + browserbaseSessionCreateParams: BrowserbaseSessionCreateParams + ) = browserbaseSessionCreateParams(JsonField.of(browserbaseSessionCreateParams)) + + /** + * Sets [Builder.browserbaseSessionCreateParams] to an arbitrary JSON value. + * + * You should usually call [Builder.browserbaseSessionCreateParams] with a well-typed + * [BrowserbaseSessionCreateParams] value instead. This method is primarily for setting + * the field to an undocumented or not yet supported value. + */ + fun browserbaseSessionCreateParams( + browserbaseSessionCreateParams: JsonField + ) = apply { this.browserbaseSessionCreateParams = browserbaseSessionCreateParams } + + /** Existing Browserbase session ID to resume */ + fun browserbaseSessionId(browserbaseSessionId: String) = + browserbaseSessionId(JsonField.of(browserbaseSessionId)) + + /** + * Sets [Builder.browserbaseSessionId] to an arbitrary JSON value. + * + * You should usually call [Builder.browserbaseSessionId] with a well-typed [String] + * value instead. This method is primarily for setting the field to an undocumented or + * not yet supported value. + */ + fun browserbaseSessionId(browserbaseSessionId: JsonField) = apply { + this.browserbaseSessionId = browserbaseSessionId + } + + fun debugDom(debugDom: Boolean) = debugDom(JsonField.of(debugDom)) + + /** + * Sets [Builder.debugDom] to an arbitrary JSON value. + * + * You should usually call [Builder.debugDom] with a well-typed [Boolean] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun debugDom(debugDom: JsonField) = apply { this.debugDom = debugDom } + + /** Timeout in ms to wait for DOM to settle */ + fun domSettleTimeoutMs(domSettleTimeoutMs: Double) = + domSettleTimeoutMs(JsonField.of(domSettleTimeoutMs)) + + /** + * Sets [Builder.domSettleTimeoutMs] to an arbitrary JSON value. + * + * You should usually call [Builder.domSettleTimeoutMs] with a well-typed [Double] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun domSettleTimeoutMs(domSettleTimeoutMs: JsonField) = apply { + this.domSettleTimeoutMs = domSettleTimeoutMs + } + + fun experimental(experimental: Boolean) = experimental(JsonField.of(experimental)) + + /** + * Sets [Builder.experimental] to an arbitrary JSON value. + * + * You should usually call [Builder.experimental] with a well-typed [Boolean] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun experimental(experimental: JsonField) = apply { + this.experimental = experimental + } + + /** Enable self-healing for failed actions */ + fun selfHeal(selfHeal: Boolean) = selfHeal(JsonField.of(selfHeal)) + + /** + * Sets [Builder.selfHeal] to an arbitrary JSON value. + * + * You should usually call [Builder.selfHeal] with a well-typed [Boolean] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun selfHeal(selfHeal: JsonField) = apply { this.selfHeal = selfHeal } + + /** Custom system prompt for AI operations */ + fun systemPrompt(systemPrompt: String) = systemPrompt(JsonField.of(systemPrompt)) + + /** + * Sets [Builder.systemPrompt] to an arbitrary JSON value. + * + * You should usually call [Builder.systemPrompt] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun systemPrompt(systemPrompt: JsonField) = apply { + this.systemPrompt = systemPrompt + } + + /** Logging verbosity level (0=quiet, 1=normal, 2=debug) */ + fun verbose(verbose: Verbose) = verbose(JsonField.of(verbose)) + + /** + * Sets [Builder.verbose] to an arbitrary JSON value. + * + * You should usually call [Builder.verbose] with a well-typed [Verbose] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun verbose(verbose: JsonField) = apply { this.verbose = verbose } + + fun waitForCaptchaSolves(waitForCaptchaSolves: Boolean) = + waitForCaptchaSolves(JsonField.of(waitForCaptchaSolves)) + + /** + * Sets [Builder.waitForCaptchaSolves] to an arbitrary JSON value. + * + * You should usually call [Builder.waitForCaptchaSolves] with a well-typed [Boolean] + * value instead. This method is primarily for setting the field to an undocumented or + * not yet supported value. + */ + fun waitForCaptchaSolves(waitForCaptchaSolves: JsonField) = apply { + this.waitForCaptchaSolves = waitForCaptchaSolves + } + + 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 [Body]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .modelName() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): Body = + Body( + checkRequired("modelName", modelName), + actTimeoutMs, + browser, + browserbaseSessionCreateParams, + browserbaseSessionId, + debugDom, + domSettleTimeoutMs, + experimental, + selfHeal, + systemPrompt, + verbose, + waitForCaptchaSolves, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): Body = apply { + if (validated) { + return@apply + } + + modelName() + actTimeoutMs() + browser().ifPresent { it.validate() } + browserbaseSessionCreateParams().ifPresent { it.validate() } + browserbaseSessionId() + debugDom() + domSettleTimeoutMs() + experimental() + selfHeal() + systemPrompt() + verbose().ifPresent { it.validate() } + waitForCaptchaSolves() + 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. + */ + @JvmSynthetic + internal fun validity(): Int = + (if (modelName.asKnown().isPresent) 1 else 0) + + (if (actTimeoutMs.asKnown().isPresent) 1 else 0) + + (browser.asKnown().getOrNull()?.validity() ?: 0) + + (browserbaseSessionCreateParams.asKnown().getOrNull()?.validity() ?: 0) + + (if (browserbaseSessionId.asKnown().isPresent) 1 else 0) + + (if (debugDom.asKnown().isPresent) 1 else 0) + + (if (domSettleTimeoutMs.asKnown().isPresent) 1 else 0) + + (if (experimental.asKnown().isPresent) 1 else 0) + + (if (selfHeal.asKnown().isPresent) 1 else 0) + + (if (systemPrompt.asKnown().isPresent) 1 else 0) + + (verbose.asKnown().getOrNull()?.validity() ?: 0) + + (if (waitForCaptchaSolves.asKnown().isPresent) 1 else 0) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Body && + modelName == other.modelName && + actTimeoutMs == other.actTimeoutMs && + browser == other.browser && + browserbaseSessionCreateParams == other.browserbaseSessionCreateParams && + browserbaseSessionId == other.browserbaseSessionId && + debugDom == other.debugDom && + domSettleTimeoutMs == other.domSettleTimeoutMs && + experimental == other.experimental && + selfHeal == other.selfHeal && + systemPrompt == other.systemPrompt && + verbose == other.verbose && + waitForCaptchaSolves == other.waitForCaptchaSolves && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash( + modelName, + actTimeoutMs, + browser, + browserbaseSessionCreateParams, + browserbaseSessionId, + debugDom, + domSettleTimeoutMs, + experimental, + selfHeal, + systemPrompt, + verbose, + waitForCaptchaSolves, + additionalProperties, + ) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Body{modelName=$modelName, actTimeoutMs=$actTimeoutMs, browser=$browser, browserbaseSessionCreateParams=$browserbaseSessionCreateParams, browserbaseSessionId=$browserbaseSessionId, debugDom=$debugDom, domSettleTimeoutMs=$domSettleTimeoutMs, experimental=$experimental, selfHeal=$selfHeal, systemPrompt=$systemPrompt, verbose=$verbose, waitForCaptchaSolves=$waitForCaptchaSolves, additionalProperties=$additionalProperties}" + } + + class Browser + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val cdpUrl: JsonField, + private val launchOptions: JsonField, + private val type: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("cdpUrl") @ExcludeMissing cdpUrl: JsonField = JsonMissing.of(), + @JsonProperty("launchOptions") + @ExcludeMissing + launchOptions: JsonField = JsonMissing.of(), + @JsonProperty("type") @ExcludeMissing type: JsonField = JsonMissing.of(), + ) : this(cdpUrl, launchOptions, type, mutableMapOf()) + + /** + * Chrome DevTools Protocol URL for connecting to existing browser + * + * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun cdpUrl(): Optional = cdpUrl.getOptional("cdpUrl") + + /** + * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun launchOptions(): Optional = launchOptions.getOptional("launchOptions") + + /** + * Browser type to use + * + * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun type(): Optional = type.getOptional("type") + + /** + * Returns the raw JSON value of [cdpUrl]. + * + * Unlike [cdpUrl], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("cdpUrl") @ExcludeMissing fun _cdpUrl(): JsonField = cdpUrl + + /** + * Returns the raw JSON value of [launchOptions]. + * + * Unlike [launchOptions], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("launchOptions") + @ExcludeMissing + fun _launchOptions(): JsonField = launchOptions + + /** + * Returns the raw JSON value of [type]. + * + * Unlike [type], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("type") @ExcludeMissing fun _type(): JsonField = type + + @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 [Browser]. */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Browser]. */ + class Builder internal constructor() { + + private var cdpUrl: JsonField = JsonMissing.of() + private var launchOptions: JsonField = JsonMissing.of() + private var type: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(browser: Browser) = apply { + cdpUrl = browser.cdpUrl + launchOptions = browser.launchOptions + type = browser.type + additionalProperties = browser.additionalProperties.toMutableMap() + } + + /** Chrome DevTools Protocol URL for connecting to existing browser */ + fun cdpUrl(cdpUrl: String) = cdpUrl(JsonField.of(cdpUrl)) + + /** + * Sets [Builder.cdpUrl] to an arbitrary JSON value. + * + * You should usually call [Builder.cdpUrl] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun cdpUrl(cdpUrl: JsonField) = apply { this.cdpUrl = cdpUrl } + + fun launchOptions(launchOptions: LaunchOptions) = + launchOptions(JsonField.of(launchOptions)) + + /** + * Sets [Builder.launchOptions] to an arbitrary JSON value. + * + * You should usually call [Builder.launchOptions] with a well-typed [LaunchOptions] + * value instead. This method is primarily for setting the field to an undocumented or + * not yet supported value. + */ + fun launchOptions(launchOptions: JsonField) = apply { + this.launchOptions = launchOptions + } + + /** Browser type to use */ + fun type(type: Type) = type(JsonField.of(type)) + + /** + * Sets [Builder.type] to an arbitrary JSON value. + * + * You should usually call [Builder.type] with a well-typed [Type] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun type(type: JsonField) = apply { this.type = type } + + 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 [Browser]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): Browser = + Browser(cdpUrl, launchOptions, type, additionalProperties.toMutableMap()) + } + + private var validated: Boolean = false + + fun validate(): Browser = apply { + if (validated) { + return@apply + } + + cdpUrl() + launchOptions().ifPresent { it.validate() } + type().ifPresent { it.validate() } + 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. + */ + @JvmSynthetic + internal fun validity(): Int = + (if (cdpUrl.asKnown().isPresent) 1 else 0) + + (launchOptions.asKnown().getOrNull()?.validity() ?: 0) + + (type.asKnown().getOrNull()?.validity() ?: 0) + + class LaunchOptions + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val acceptDownloads: JsonField, + private val args: JsonField>, + private val cdpUrl: JsonField, + private val chromiumSandbox: JsonField, + private val connectTimeoutMs: JsonField, + private val deviceScaleFactor: JsonField, + private val devtools: JsonField, + private val downloadsPath: JsonField, + private val executablePath: JsonField, + private val hasTouch: JsonField, + private val headless: JsonField, + private val ignoreDefaultArgs: JsonField, + private val ignoreHttpsErrors: JsonField, + private val locale: JsonField, + private val preserveUserDataDir: JsonField, + private val proxy: JsonField, + private val userDataDir: JsonField, + private val viewport: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("acceptDownloads") + @ExcludeMissing + acceptDownloads: JsonField = JsonMissing.of(), + @JsonProperty("args") + @ExcludeMissing + args: JsonField> = JsonMissing.of(), + @JsonProperty("cdpUrl") + @ExcludeMissing + cdpUrl: JsonField = JsonMissing.of(), + @JsonProperty("chromiumSandbox") + @ExcludeMissing + chromiumSandbox: JsonField = JsonMissing.of(), + @JsonProperty("connectTimeoutMs") + @ExcludeMissing + connectTimeoutMs: JsonField = JsonMissing.of(), + @JsonProperty("deviceScaleFactor") + @ExcludeMissing + deviceScaleFactor: JsonField = JsonMissing.of(), + @JsonProperty("devtools") + @ExcludeMissing + devtools: JsonField = JsonMissing.of(), + @JsonProperty("downloadsPath") + @ExcludeMissing + downloadsPath: JsonField = JsonMissing.of(), + @JsonProperty("executablePath") + @ExcludeMissing + executablePath: JsonField = JsonMissing.of(), + @JsonProperty("hasTouch") + @ExcludeMissing + hasTouch: JsonField = JsonMissing.of(), + @JsonProperty("headless") + @ExcludeMissing + headless: JsonField = JsonMissing.of(), + @JsonProperty("ignoreDefaultArgs") + @ExcludeMissing + ignoreDefaultArgs: JsonField = JsonMissing.of(), + @JsonProperty("ignoreHTTPSErrors") + @ExcludeMissing + ignoreHttpsErrors: JsonField = JsonMissing.of(), + @JsonProperty("locale") + @ExcludeMissing + locale: JsonField = JsonMissing.of(), + @JsonProperty("preserveUserDataDir") + @ExcludeMissing + preserveUserDataDir: JsonField = JsonMissing.of(), + @JsonProperty("proxy") @ExcludeMissing proxy: JsonField = JsonMissing.of(), + @JsonProperty("userDataDir") + @ExcludeMissing + userDataDir: JsonField = JsonMissing.of(), + @JsonProperty("viewport") + @ExcludeMissing + viewport: JsonField = JsonMissing.of(), + ) : this( + acceptDownloads, + args, + cdpUrl, + chromiumSandbox, + connectTimeoutMs, + deviceScaleFactor, + devtools, + downloadsPath, + executablePath, + hasTouch, + headless, + ignoreDefaultArgs, + ignoreHttpsErrors, + locale, + preserveUserDataDir, + proxy, + userDataDir, + viewport, + mutableMapOf(), + ) + + /** + * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. + * if the server responded with an unexpected value). + */ + fun acceptDownloads(): Optional = + acceptDownloads.getOptional("acceptDownloads") + + /** + * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. + * if the server responded with an unexpected value). + */ + fun args(): Optional> = args.getOptional("args") + + /** + * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. + * if the server responded with an unexpected value). + */ + fun cdpUrl(): Optional = cdpUrl.getOptional("cdpUrl") + + /** + * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. + * if the server responded with an unexpected value). + */ + fun chromiumSandbox(): Optional = + chromiumSandbox.getOptional("chromiumSandbox") + + /** + * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. + * if the server responded with an unexpected value). + */ + fun connectTimeoutMs(): Optional = + connectTimeoutMs.getOptional("connectTimeoutMs") + + /** + * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. + * if the server responded with an unexpected value). + */ + fun deviceScaleFactor(): Optional = + deviceScaleFactor.getOptional("deviceScaleFactor") + + /** + * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. + * if the server responded with an unexpected value). + */ + fun devtools(): Optional = devtools.getOptional("devtools") + + /** + * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. + * if the server responded with an unexpected value). + */ + fun downloadsPath(): Optional = downloadsPath.getOptional("downloadsPath") + + /** + * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. + * if the server responded with an unexpected value). + */ + fun executablePath(): Optional = executablePath.getOptional("executablePath") + + /** + * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. + * if the server responded with an unexpected value). + */ + fun hasTouch(): Optional = hasTouch.getOptional("hasTouch") + + /** + * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. + * if the server responded with an unexpected value). + */ + fun headless(): Optional = headless.getOptional("headless") + + /** + * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. + * if the server responded with an unexpected value). + */ + fun ignoreDefaultArgs(): Optional = + ignoreDefaultArgs.getOptional("ignoreDefaultArgs") + + /** + * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. + * if the server responded with an unexpected value). + */ + fun ignoreHttpsErrors(): Optional = + ignoreHttpsErrors.getOptional("ignoreHTTPSErrors") + + /** + * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. + * if the server responded with an unexpected value). + */ + fun locale(): Optional = locale.getOptional("locale") + + /** + * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. + * if the server responded with an unexpected value). + */ + fun preserveUserDataDir(): Optional = + preserveUserDataDir.getOptional("preserveUserDataDir") + + /** + * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. + * if the server responded with an unexpected value). + */ + fun proxy(): Optional = proxy.getOptional("proxy") + + /** + * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. + * if the server responded with an unexpected value). + */ + fun userDataDir(): Optional = userDataDir.getOptional("userDataDir") + + /** + * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. + * if the server responded with an unexpected value). + */ + fun viewport(): Optional = viewport.getOptional("viewport") + + /** + * Returns the raw JSON value of [acceptDownloads]. + * + * Unlike [acceptDownloads], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("acceptDownloads") + @ExcludeMissing + fun _acceptDownloads(): JsonField = acceptDownloads + + /** + * Returns the raw JSON value of [args]. + * + * Unlike [args], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("args") @ExcludeMissing fun _args(): JsonField> = args + + /** + * Returns the raw JSON value of [cdpUrl]. + * + * Unlike [cdpUrl], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("cdpUrl") @ExcludeMissing fun _cdpUrl(): JsonField = cdpUrl + + /** + * Returns the raw JSON value of [chromiumSandbox]. + * + * Unlike [chromiumSandbox], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("chromiumSandbox") + @ExcludeMissing + fun _chromiumSandbox(): JsonField = chromiumSandbox + + /** + * Returns the raw JSON value of [connectTimeoutMs]. + * + * Unlike [connectTimeoutMs], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("connectTimeoutMs") + @ExcludeMissing + fun _connectTimeoutMs(): JsonField = connectTimeoutMs + + /** + * Returns the raw JSON value of [deviceScaleFactor]. + * + * Unlike [deviceScaleFactor], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("deviceScaleFactor") + @ExcludeMissing + fun _deviceScaleFactor(): JsonField = deviceScaleFactor + + /** + * Returns the raw JSON value of [devtools]. + * + * Unlike [devtools], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("devtools") @ExcludeMissing fun _devtools(): JsonField = devtools + + /** + * Returns the raw JSON value of [downloadsPath]. + * + * Unlike [downloadsPath], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("downloadsPath") + @ExcludeMissing + fun _downloadsPath(): JsonField = downloadsPath + + /** + * Returns the raw JSON value of [executablePath]. + * + * Unlike [executablePath], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("executablePath") + @ExcludeMissing + fun _executablePath(): JsonField = executablePath + + /** + * Returns the raw JSON value of [hasTouch]. + * + * Unlike [hasTouch], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("hasTouch") @ExcludeMissing fun _hasTouch(): JsonField = hasTouch + + /** + * Returns the raw JSON value of [headless]. + * + * Unlike [headless], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("headless") @ExcludeMissing fun _headless(): JsonField = headless + + /** + * Returns the raw JSON value of [ignoreDefaultArgs]. + * + * Unlike [ignoreDefaultArgs], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("ignoreDefaultArgs") + @ExcludeMissing + fun _ignoreDefaultArgs(): JsonField = ignoreDefaultArgs + + /** + * Returns the raw JSON value of [ignoreHttpsErrors]. + * + * Unlike [ignoreHttpsErrors], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("ignoreHTTPSErrors") + @ExcludeMissing + fun _ignoreHttpsErrors(): JsonField = ignoreHttpsErrors + + /** + * Returns the raw JSON value of [locale]. + * + * Unlike [locale], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("locale") @ExcludeMissing fun _locale(): JsonField = locale + + /** + * Returns the raw JSON value of [preserveUserDataDir]. + * + * Unlike [preserveUserDataDir], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("preserveUserDataDir") + @ExcludeMissing + fun _preserveUserDataDir(): JsonField = preserveUserDataDir + + /** + * Returns the raw JSON value of [proxy]. + * + * Unlike [proxy], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("proxy") @ExcludeMissing fun _proxy(): JsonField = proxy + + /** + * Returns the raw JSON value of [userDataDir]. + * + * Unlike [userDataDir], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("userDataDir") + @ExcludeMissing + fun _userDataDir(): JsonField = userDataDir + + /** + * Returns the raw JSON value of [viewport]. + * + * Unlike [viewport], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("viewport") + @ExcludeMissing + fun _viewport(): JsonField = viewport + + @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 [LaunchOptions]. */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [LaunchOptions]. */ + class Builder internal constructor() { + + private var acceptDownloads: JsonField = JsonMissing.of() + private var args: JsonField>? = null + private var cdpUrl: JsonField = JsonMissing.of() + private var chromiumSandbox: JsonField = JsonMissing.of() + private var connectTimeoutMs: JsonField = JsonMissing.of() + private var deviceScaleFactor: JsonField = JsonMissing.of() + private var devtools: JsonField = JsonMissing.of() + private var downloadsPath: JsonField = JsonMissing.of() + private var executablePath: JsonField = JsonMissing.of() + private var hasTouch: JsonField = JsonMissing.of() + private var headless: JsonField = JsonMissing.of() + private var ignoreDefaultArgs: JsonField = JsonMissing.of() + private var ignoreHttpsErrors: JsonField = JsonMissing.of() + private var locale: JsonField = JsonMissing.of() + private var preserveUserDataDir: JsonField = JsonMissing.of() + private var proxy: JsonField = JsonMissing.of() + private var userDataDir: JsonField = JsonMissing.of() + private var viewport: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(launchOptions: LaunchOptions) = apply { + acceptDownloads = launchOptions.acceptDownloads + args = launchOptions.args.map { it.toMutableList() } + cdpUrl = launchOptions.cdpUrl + chromiumSandbox = launchOptions.chromiumSandbox + connectTimeoutMs = launchOptions.connectTimeoutMs + deviceScaleFactor = launchOptions.deviceScaleFactor + devtools = launchOptions.devtools + downloadsPath = launchOptions.downloadsPath + executablePath = launchOptions.executablePath + hasTouch = launchOptions.hasTouch + headless = launchOptions.headless + ignoreDefaultArgs = launchOptions.ignoreDefaultArgs + ignoreHttpsErrors = launchOptions.ignoreHttpsErrors + locale = launchOptions.locale + preserveUserDataDir = launchOptions.preserveUserDataDir + proxy = launchOptions.proxy + userDataDir = launchOptions.userDataDir + viewport = launchOptions.viewport + additionalProperties = launchOptions.additionalProperties.toMutableMap() + } + + fun acceptDownloads(acceptDownloads: Boolean) = + acceptDownloads(JsonField.of(acceptDownloads)) + + /** + * Sets [Builder.acceptDownloads] to an arbitrary JSON value. + * + * You should usually call [Builder.acceptDownloads] with a well-typed [Boolean] + * value instead. This method is primarily for setting the field to an undocumented + * or not yet supported value. + */ + fun acceptDownloads(acceptDownloads: JsonField) = apply { + this.acceptDownloads = acceptDownloads + } + + fun args(args: List) = args(JsonField.of(args)) + + /** + * Sets [Builder.args] to an arbitrary JSON value. + * + * You should usually call [Builder.args] with a well-typed `List` value + * instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun args(args: JsonField>) = apply { + this.args = args.map { it.toMutableList() } + } + + /** + * Adds a single [String] to [args]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addArg(arg: String) = apply { + args = + (args ?: JsonField.of(mutableListOf())).also { + checkKnown("args", it).add(arg) + } + } + + fun cdpUrl(cdpUrl: String) = cdpUrl(JsonField.of(cdpUrl)) + + /** + * Sets [Builder.cdpUrl] to an arbitrary JSON value. + * + * You should usually call [Builder.cdpUrl] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun cdpUrl(cdpUrl: JsonField) = apply { this.cdpUrl = cdpUrl } + + fun chromiumSandbox(chromiumSandbox: Boolean) = + chromiumSandbox(JsonField.of(chromiumSandbox)) + + /** + * Sets [Builder.chromiumSandbox] to an arbitrary JSON value. + * + * You should usually call [Builder.chromiumSandbox] with a well-typed [Boolean] + * value instead. This method is primarily for setting the field to an undocumented + * or not yet supported value. + */ + fun chromiumSandbox(chromiumSandbox: JsonField) = apply { + this.chromiumSandbox = chromiumSandbox + } + + fun connectTimeoutMs(connectTimeoutMs: Double) = + connectTimeoutMs(JsonField.of(connectTimeoutMs)) + + /** + * Sets [Builder.connectTimeoutMs] to an arbitrary JSON value. + * + * You should usually call [Builder.connectTimeoutMs] with a well-typed [Double] + * value instead. This method is primarily for setting the field to an undocumented + * or not yet supported value. + */ + fun connectTimeoutMs(connectTimeoutMs: JsonField) = apply { + this.connectTimeoutMs = connectTimeoutMs + } + + fun deviceScaleFactor(deviceScaleFactor: Double) = + deviceScaleFactor(JsonField.of(deviceScaleFactor)) + + /** + * Sets [Builder.deviceScaleFactor] to an arbitrary JSON value. + * + * You should usually call [Builder.deviceScaleFactor] with a well-typed [Double] + * value instead. This method is primarily for setting the field to an undocumented + * or not yet supported value. + */ + fun deviceScaleFactor(deviceScaleFactor: JsonField) = apply { + this.deviceScaleFactor = deviceScaleFactor + } + + fun devtools(devtools: Boolean) = devtools(JsonField.of(devtools)) + + /** + * Sets [Builder.devtools] to an arbitrary JSON value. + * + * You should usually call [Builder.devtools] with a well-typed [Boolean] value + * instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun devtools(devtools: JsonField) = apply { this.devtools = devtools } + + fun downloadsPath(downloadsPath: String) = + downloadsPath(JsonField.of(downloadsPath)) + + /** + * Sets [Builder.downloadsPath] to an arbitrary JSON value. + * + * You should usually call [Builder.downloadsPath] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun downloadsPath(downloadsPath: JsonField) = apply { + this.downloadsPath = downloadsPath + } + + fun executablePath(executablePath: String) = + executablePath(JsonField.of(executablePath)) + + /** + * Sets [Builder.executablePath] to an arbitrary JSON value. + * + * You should usually call [Builder.executablePath] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun executablePath(executablePath: JsonField) = apply { + this.executablePath = executablePath + } + + fun hasTouch(hasTouch: Boolean) = hasTouch(JsonField.of(hasTouch)) + + /** + * Sets [Builder.hasTouch] to an arbitrary JSON value. + * + * You should usually call [Builder.hasTouch] with a well-typed [Boolean] value + * instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun hasTouch(hasTouch: JsonField) = apply { this.hasTouch = hasTouch } + + fun headless(headless: Boolean) = headless(JsonField.of(headless)) + + /** + * Sets [Builder.headless] to an arbitrary JSON value. + * + * You should usually call [Builder.headless] with a well-typed [Boolean] value + * instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun headless(headless: JsonField) = apply { this.headless = headless } + + fun ignoreDefaultArgs(ignoreDefaultArgs: IgnoreDefaultArgs) = + ignoreDefaultArgs(JsonField.of(ignoreDefaultArgs)) + + /** + * Sets [Builder.ignoreDefaultArgs] to an arbitrary JSON value. + * + * You should usually call [Builder.ignoreDefaultArgs] with a well-typed + * [IgnoreDefaultArgs] value instead. This method is primarily for setting the field + * to an undocumented or not yet supported value. + */ + fun ignoreDefaultArgs(ignoreDefaultArgs: JsonField) = apply { + this.ignoreDefaultArgs = ignoreDefaultArgs + } + + /** Alias for calling [ignoreDefaultArgs] with `IgnoreDefaultArgs.ofBool(bool)`. */ + fun ignoreDefaultArgs(bool: Boolean) = + ignoreDefaultArgs(IgnoreDefaultArgs.ofBool(bool)) + + /** + * Alias for calling [ignoreDefaultArgs] with + * `IgnoreDefaultArgs.ofStrings(strings)`. + */ + fun ignoreDefaultArgsOfStrings(strings: List) = + ignoreDefaultArgs(IgnoreDefaultArgs.ofStrings(strings)) + + fun ignoreHttpsErrors(ignoreHttpsErrors: Boolean) = + ignoreHttpsErrors(JsonField.of(ignoreHttpsErrors)) + + /** + * Sets [Builder.ignoreHttpsErrors] to an arbitrary JSON value. + * + * You should usually call [Builder.ignoreHttpsErrors] with a well-typed [Boolean] + * value instead. This method is primarily for setting the field to an undocumented + * or not yet supported value. + */ + fun ignoreHttpsErrors(ignoreHttpsErrors: JsonField) = apply { + this.ignoreHttpsErrors = ignoreHttpsErrors + } + + fun locale(locale: String) = locale(JsonField.of(locale)) + + /** + * Sets [Builder.locale] to an arbitrary JSON value. + * + * You should usually call [Builder.locale] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun locale(locale: JsonField) = apply { this.locale = locale } + + fun preserveUserDataDir(preserveUserDataDir: Boolean) = + preserveUserDataDir(JsonField.of(preserveUserDataDir)) + + /** + * Sets [Builder.preserveUserDataDir] to an arbitrary JSON value. + * + * You should usually call [Builder.preserveUserDataDir] with a well-typed [Boolean] + * value instead. This method is primarily for setting the field to an undocumented + * or not yet supported value. + */ + fun preserveUserDataDir(preserveUserDataDir: JsonField) = apply { + this.preserveUserDataDir = preserveUserDataDir + } + + fun proxy(proxy: Proxy) = proxy(JsonField.of(proxy)) + + /** + * Sets [Builder.proxy] to an arbitrary JSON value. + * + * You should usually call [Builder.proxy] with a well-typed [Proxy] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun proxy(proxy: JsonField) = apply { this.proxy = proxy } + + fun userDataDir(userDataDir: String) = userDataDir(JsonField.of(userDataDir)) + + /** + * Sets [Builder.userDataDir] to an arbitrary JSON value. + * + * You should usually call [Builder.userDataDir] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun userDataDir(userDataDir: JsonField) = apply { + this.userDataDir = userDataDir + } + + fun viewport(viewport: Viewport) = viewport(JsonField.of(viewport)) + + /** + * Sets [Builder.viewport] to an arbitrary JSON value. + * + * You should usually call [Builder.viewport] with a well-typed [Viewport] value + * instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun viewport(viewport: JsonField) = apply { this.viewport = viewport } + + 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 [LaunchOptions]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): LaunchOptions = + LaunchOptions( + acceptDownloads, + (args ?: JsonMissing.of()).map { it.toImmutable() }, + cdpUrl, + chromiumSandbox, + connectTimeoutMs, + deviceScaleFactor, + devtools, + downloadsPath, + executablePath, + hasTouch, + headless, + ignoreDefaultArgs, + ignoreHttpsErrors, + locale, + preserveUserDataDir, + proxy, + userDataDir, + viewport, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): LaunchOptions = apply { + if (validated) { + return@apply + } + + acceptDownloads() + args() + cdpUrl() + chromiumSandbox() + connectTimeoutMs() + deviceScaleFactor() + devtools() + downloadsPath() + executablePath() + hasTouch() + headless() + ignoreDefaultArgs().ifPresent { it.validate() } + ignoreHttpsErrors() + locale() + preserveUserDataDir() + proxy().ifPresent { it.validate() } + userDataDir() + viewport().ifPresent { it.validate() } + 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. + */ + @JvmSynthetic + internal fun validity(): Int = + (if (acceptDownloads.asKnown().isPresent) 1 else 0) + + (args.asKnown().getOrNull()?.size ?: 0) + + (if (cdpUrl.asKnown().isPresent) 1 else 0) + + (if (chromiumSandbox.asKnown().isPresent) 1 else 0) + + (if (connectTimeoutMs.asKnown().isPresent) 1 else 0) + + (if (deviceScaleFactor.asKnown().isPresent) 1 else 0) + + (if (devtools.asKnown().isPresent) 1 else 0) + + (if (downloadsPath.asKnown().isPresent) 1 else 0) + + (if (executablePath.asKnown().isPresent) 1 else 0) + + (if (hasTouch.asKnown().isPresent) 1 else 0) + + (if (headless.asKnown().isPresent) 1 else 0) + + (ignoreDefaultArgs.asKnown().getOrNull()?.validity() ?: 0) + + (if (ignoreHttpsErrors.asKnown().isPresent) 1 else 0) + + (if (locale.asKnown().isPresent) 1 else 0) + + (if (preserveUserDataDir.asKnown().isPresent) 1 else 0) + + (proxy.asKnown().getOrNull()?.validity() ?: 0) + + (if (userDataDir.asKnown().isPresent) 1 else 0) + + (viewport.asKnown().getOrNull()?.validity() ?: 0) + + @JsonDeserialize(using = IgnoreDefaultArgs.Deserializer::class) + @JsonSerialize(using = IgnoreDefaultArgs.Serializer::class) + class IgnoreDefaultArgs + private constructor( + private val bool: Boolean? = null, + private val strings: List? = null, + private val _json: JsonValue? = null, + ) { + + fun bool(): Optional = Optional.ofNullable(bool) + + fun strings(): Optional> = Optional.ofNullable(strings) + + fun isBool(): Boolean = bool != null + + fun isStrings(): Boolean = strings != null + + fun asBool(): Boolean = bool.getOrThrow("bool") + + fun asStrings(): List = strings.getOrThrow("strings") + + fun _json(): Optional = Optional.ofNullable(_json) + + fun accept(visitor: Visitor): T = + when { + bool != null -> visitor.visitBool(bool) + strings != null -> visitor.visitStrings(strings) + else -> visitor.unknown(_json) + } + + private var validated: Boolean = false + + fun validate(): IgnoreDefaultArgs = apply { + if (validated) { + return@apply + } + + accept( + object : Visitor { + override fun visitBool(bool: Boolean) {} + + override fun visitStrings(strings: List) {} + } + ) + 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. + */ + @JvmSynthetic + internal fun validity(): Int = + accept( + object : Visitor { + override fun visitBool(bool: Boolean) = 1 + + override fun visitStrings(strings: List) = strings.size + + override fun unknown(json: JsonValue?) = 0 + } + ) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is IgnoreDefaultArgs && + bool == other.bool && + strings == other.strings + } + + override fun hashCode(): Int = Objects.hash(bool, strings) + + override fun toString(): String = + when { + bool != null -> "IgnoreDefaultArgs{bool=$bool}" + strings != null -> "IgnoreDefaultArgs{strings=$strings}" + _json != null -> "IgnoreDefaultArgs{_unknown=$_json}" + else -> throw IllegalStateException("Invalid IgnoreDefaultArgs") + } + + companion object { + + @JvmStatic fun ofBool(bool: Boolean) = IgnoreDefaultArgs(bool = bool) + + @JvmStatic + fun ofStrings(strings: List) = + IgnoreDefaultArgs(strings = strings.toImmutable()) + } + + /** + * An interface that defines how to map each variant of [IgnoreDefaultArgs] to a + * value of type [T]. + */ + interface Visitor { + + fun visitBool(bool: Boolean): T + + fun visitStrings(strings: List): T + + /** + * Maps an unknown variant of [IgnoreDefaultArgs] to a value of type [T]. + * + * An instance of [IgnoreDefaultArgs] can contain an unknown variant if it was + * deserialized from data that doesn't match any known variant. For example, if + * the SDK is on an older version than the API, then the API may respond with + * new variants that the SDK is unaware of. + * + * @throws StagehandInvalidDataException in the default implementation. + */ + fun unknown(json: JsonValue?): T { + throw StagehandInvalidDataException("Unknown IgnoreDefaultArgs: $json") + } + } + + internal class Deserializer : + BaseDeserializer(IgnoreDefaultArgs::class) { + + override fun ObjectCodec.deserialize(node: JsonNode): IgnoreDefaultArgs { + val json = JsonValue.fromJsonNode(node) + + val bestMatches = + sequenceOf( + tryDeserialize(node, jacksonTypeRef())?.let { + IgnoreDefaultArgs(bool = it, _json = json) + }, + tryDeserialize(node, jacksonTypeRef>())?.let { + IgnoreDefaultArgs(strings = it, _json = json) + }, + ) + .filterNotNull() + .allMaxBy { it.validity() } + .toList() + return when (bestMatches.size) { + // This can happen if what we're deserializing is completely + // incompatible with all the possible variants (e.g. deserializing from + // string). + 0 -> IgnoreDefaultArgs(_json = json) + 1 -> bestMatches.single() + // If there's more than one match with the highest validity, then use + // the first completely valid match, or simply the first match if none + // are completely valid. + else -> bestMatches.firstOrNull { it.isValid() } ?: bestMatches.first() + } + } + } + + internal class Serializer : + BaseSerializer(IgnoreDefaultArgs::class) { + + override fun serialize( + value: IgnoreDefaultArgs, + generator: JsonGenerator, + provider: SerializerProvider, + ) { + when { + value.bool != null -> generator.writeObject(value.bool) + value.strings != null -> generator.writeObject(value.strings) + value._json != null -> generator.writeObject(value._json) + else -> throw IllegalStateException("Invalid IgnoreDefaultArgs") + } + } + } + } + + class Proxy + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val server: JsonField, + private val bypass: JsonField, + private val password: JsonField, + private val username: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("server") + @ExcludeMissing + server: JsonField = JsonMissing.of(), + @JsonProperty("bypass") + @ExcludeMissing + bypass: JsonField = JsonMissing.of(), + @JsonProperty("password") + @ExcludeMissing + password: JsonField = JsonMissing.of(), + @JsonProperty("username") + @ExcludeMissing + username: JsonField = JsonMissing.of(), + ) : this(server, bypass, password, username, mutableMapOf()) + + /** + * @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 server(): String = server.getRequired("server") + + /** + * @throws StagehandInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun bypass(): Optional = bypass.getOptional("bypass") + + /** + * @throws StagehandInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun password(): Optional = password.getOptional("password") + + /** + * @throws StagehandInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun username(): Optional = username.getOptional("username") + + /** + * Returns the raw JSON value of [server]. + * + * Unlike [server], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("server") @ExcludeMissing fun _server(): JsonField = server + + /** + * Returns the raw JSON value of [bypass]. + * + * Unlike [bypass], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("bypass") @ExcludeMissing fun _bypass(): JsonField = bypass + + /** + * Returns the raw JSON value of [password]. + * + * Unlike [password], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("password") + @ExcludeMissing + fun _password(): JsonField = password + + /** + * Returns the raw JSON value of [username]. + * + * Unlike [username], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("username") + @ExcludeMissing + fun _username(): JsonField = username + + @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 [Proxy]. + * + * The following fields are required: + * ```java + * .server() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Proxy]. */ + class Builder internal constructor() { + + private var server: JsonField? = null + private var bypass: JsonField = JsonMissing.of() + private var password: JsonField = JsonMissing.of() + private var username: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(proxy: Proxy) = apply { + server = proxy.server + bypass = proxy.bypass + password = proxy.password + username = proxy.username + additionalProperties = proxy.additionalProperties.toMutableMap() + } + + fun server(server: String) = server(JsonField.of(server)) + + /** + * Sets [Builder.server] to an arbitrary JSON value. + * + * You should usually call [Builder.server] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or + * not yet supported value. + */ + fun server(server: JsonField) = apply { this.server = server } + + fun bypass(bypass: String) = bypass(JsonField.of(bypass)) + + /** + * Sets [Builder.bypass] to an arbitrary JSON value. + * + * You should usually call [Builder.bypass] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or + * not yet supported value. + */ + fun bypass(bypass: JsonField) = apply { this.bypass = bypass } + + fun password(password: String) = password(JsonField.of(password)) + + /** + * Sets [Builder.password] to an arbitrary JSON value. + * + * You should usually call [Builder.password] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or + * not yet supported value. + */ + fun password(password: JsonField) = apply { this.password = password } + + fun username(username: String) = username(JsonField.of(username)) + + /** + * Sets [Builder.username] to an arbitrary JSON value. + * + * You should usually call [Builder.username] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or + * not yet supported value. + */ + fun username(username: JsonField) = apply { this.username = username } + + 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 [Proxy]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .server() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): Proxy = + Proxy( + checkRequired("server", server), + bypass, + password, + username, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): Proxy = apply { + if (validated) { + return@apply + } + + server() + bypass() + password() + username() + 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. + */ + @JvmSynthetic + internal fun validity(): Int = + (if (server.asKnown().isPresent) 1 else 0) + + (if (bypass.asKnown().isPresent) 1 else 0) + + (if (password.asKnown().isPresent) 1 else 0) + + (if (username.asKnown().isPresent) 1 else 0) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Proxy && + server == other.server && + bypass == other.bypass && + password == other.password && + username == other.username && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(server, bypass, password, username, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Proxy{server=$server, bypass=$bypass, password=$password, username=$username, additionalProperties=$additionalProperties}" + } + + class Viewport + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val height: JsonField, + private val width: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("height") + @ExcludeMissing + height: JsonField = JsonMissing.of(), + @JsonProperty("width") + @ExcludeMissing + width: JsonField = JsonMissing.of(), + ) : this(height, width, mutableMapOf()) + + /** + * @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 height(): Double = height.getRequired("height") + + /** + * @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 width(): Double = width.getRequired("width") + + /** + * Returns the raw JSON value of [height]. + * + * Unlike [height], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("height") @ExcludeMissing fun _height(): JsonField = height + + /** + * Returns the raw JSON value of [width]. + * + * Unlike [width], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("width") @ExcludeMissing fun _width(): JsonField = width + + @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 [Viewport]. + * + * The following fields are required: + * ```java + * .height() + * .width() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Viewport]. */ + class Builder internal constructor() { + + private var height: JsonField? = null + private var width: JsonField? = null + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(viewport: Viewport) = apply { + height = viewport.height + width = viewport.width + additionalProperties = viewport.additionalProperties.toMutableMap() + } + + fun height(height: Double) = height(JsonField.of(height)) + + /** + * Sets [Builder.height] to an arbitrary JSON value. + * + * You should usually call [Builder.height] with a well-typed [Double] value + * instead. This method is primarily for setting the field to an undocumented or + * not yet supported value. + */ + fun height(height: JsonField) = apply { this.height = height } + + fun width(width: Double) = width(JsonField.of(width)) + + /** + * Sets [Builder.width] to an arbitrary JSON value. + * + * You should usually call [Builder.width] with a well-typed [Double] value + * instead. This method is primarily for setting the field to an undocumented or + * not yet supported value. + */ + fun width(width: JsonField) = apply { this.width = width } + + 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 [Viewport]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .height() + * .width() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): Viewport = + Viewport( + checkRequired("height", height), + checkRequired("width", width), + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): Viewport = apply { + if (validated) { + return@apply + } + + height() + width() + 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. + */ + @JvmSynthetic + internal fun validity(): Int = + (if (height.asKnown().isPresent) 1 else 0) + + (if (width.asKnown().isPresent) 1 else 0) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Viewport && + height == other.height && + width == other.width && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(height, width, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Viewport{height=$height, width=$width, additionalProperties=$additionalProperties}" + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is LaunchOptions && + acceptDownloads == other.acceptDownloads && + args == other.args && + cdpUrl == other.cdpUrl && + chromiumSandbox == other.chromiumSandbox && + connectTimeoutMs == other.connectTimeoutMs && + deviceScaleFactor == other.deviceScaleFactor && + devtools == other.devtools && + downloadsPath == other.downloadsPath && + executablePath == other.executablePath && + hasTouch == other.hasTouch && + headless == other.headless && + ignoreDefaultArgs == other.ignoreDefaultArgs && + ignoreHttpsErrors == other.ignoreHttpsErrors && + locale == other.locale && + preserveUserDataDir == other.preserveUserDataDir && + proxy == other.proxy && + userDataDir == other.userDataDir && + viewport == other.viewport && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash( + acceptDownloads, + args, + cdpUrl, + chromiumSandbox, + connectTimeoutMs, + deviceScaleFactor, + devtools, + downloadsPath, + executablePath, + hasTouch, + headless, + ignoreDefaultArgs, + ignoreHttpsErrors, + locale, + preserveUserDataDir, + proxy, + userDataDir, + viewport, + additionalProperties, + ) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "LaunchOptions{acceptDownloads=$acceptDownloads, args=$args, cdpUrl=$cdpUrl, chromiumSandbox=$chromiumSandbox, connectTimeoutMs=$connectTimeoutMs, deviceScaleFactor=$deviceScaleFactor, devtools=$devtools, downloadsPath=$downloadsPath, executablePath=$executablePath, hasTouch=$hasTouch, headless=$headless, ignoreDefaultArgs=$ignoreDefaultArgs, ignoreHttpsErrors=$ignoreHttpsErrors, locale=$locale, preserveUserDataDir=$preserveUserDataDir, proxy=$proxy, userDataDir=$userDataDir, viewport=$viewport, additionalProperties=$additionalProperties}" + } + + /** Browser type to use */ + class Type @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 { + + @JvmField val LOCAL = of("local") + + @JvmField val BROWSERBASE = of("browserbase") + + @JvmStatic fun of(value: String) = Type(JsonField.of(value)) + } + + /** An enum containing [Type]'s known values. */ + enum class Known { + LOCAL, + BROWSERBASE, + } + + /** + * An enum containing [Type]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [Type] 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 { + LOCAL, + BROWSERBASE, + /** An enum member indicating that [Type] 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) { + LOCAL -> Value.LOCAL + BROWSERBASE -> Value.BROWSERBASE + 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) { + LOCAL -> Known.LOCAL + BROWSERBASE -> Known.BROWSERBASE + else -> throw StagehandInvalidDataException("Unknown Type: $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().orElseThrow { + StagehandInvalidDataException("Value is not a String") + } + + private var validated: Boolean = false + + fun validate(): Type = 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. + */ + @JvmSynthetic 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 Type && 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 Browser && + cdpUrl == other.cdpUrl && + launchOptions == other.launchOptions && + type == other.type && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(cdpUrl, launchOptions, type, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Browser{cdpUrl=$cdpUrl, launchOptions=$launchOptions, type=$type, additionalProperties=$additionalProperties}" + } + + class BrowserbaseSessionCreateParams + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val browserSettings: JsonField, + private val extensionId: JsonField, + private val keepAlive: JsonField, + private val projectId: JsonField, + private val proxies: JsonField, + private val region: JsonField, + private val timeout: JsonField, + private val userMetadata: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("browserSettings") + @ExcludeMissing + browserSettings: JsonField = JsonMissing.of(), + @JsonProperty("extensionId") + @ExcludeMissing + extensionId: JsonField = JsonMissing.of(), + @JsonProperty("keepAlive") + @ExcludeMissing + keepAlive: JsonField = JsonMissing.of(), + @JsonProperty("projectId") + @ExcludeMissing + projectId: JsonField = JsonMissing.of(), + @JsonProperty("proxies") @ExcludeMissing proxies: JsonField = JsonMissing.of(), + @JsonProperty("region") @ExcludeMissing region: JsonField = JsonMissing.of(), + @JsonProperty("timeout") @ExcludeMissing timeout: JsonField = JsonMissing.of(), + @JsonProperty("userMetadata") + @ExcludeMissing + userMetadata: JsonField = JsonMissing.of(), + ) : this( + browserSettings, + extensionId, + keepAlive, + projectId, + proxies, + region, + timeout, + userMetadata, + mutableMapOf(), + ) + + /** + * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun browserSettings(): Optional = + browserSettings.getOptional("browserSettings") + + /** + * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun extensionId(): Optional = extensionId.getOptional("extensionId") + + /** + * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun keepAlive(): Optional = keepAlive.getOptional("keepAlive") + + /** + * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun projectId(): Optional = projectId.getOptional("projectId") + + /** + * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun proxies(): Optional = proxies.getOptional("proxies") + + /** + * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun region(): Optional = region.getOptional("region") + + /** + * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun timeout(): Optional = timeout.getOptional("timeout") + + /** + * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun userMetadata(): Optional = userMetadata.getOptional("userMetadata") + + /** + * Returns the raw JSON value of [browserSettings]. + * + * Unlike [browserSettings], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("browserSettings") + @ExcludeMissing + fun _browserSettings(): JsonField = browserSettings + + /** + * Returns the raw JSON value of [extensionId]. + * + * Unlike [extensionId], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("extensionId") + @ExcludeMissing + fun _extensionId(): JsonField = extensionId + + /** + * Returns the raw JSON value of [keepAlive]. + * + * Unlike [keepAlive], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("keepAlive") @ExcludeMissing fun _keepAlive(): JsonField = keepAlive + + /** + * Returns the raw JSON value of [projectId]. + * + * Unlike [projectId], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("projectId") @ExcludeMissing fun _projectId(): JsonField = projectId + + /** + * Returns the raw JSON value of [proxies]. + * + * Unlike [proxies], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("proxies") @ExcludeMissing fun _proxies(): JsonField = proxies + + /** + * Returns the raw JSON value of [region]. + * + * Unlike [region], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("region") @ExcludeMissing fun _region(): JsonField = region + + /** + * Returns the raw JSON value of [timeout]. + * + * Unlike [timeout], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("timeout") @ExcludeMissing fun _timeout(): JsonField = timeout + + /** + * Returns the raw JSON value of [userMetadata]. + * + * Unlike [userMetadata], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("userMetadata") + @ExcludeMissing + fun _userMetadata(): JsonField = userMetadata + + @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 + * [BrowserbaseSessionCreateParams]. + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [BrowserbaseSessionCreateParams]. */ + class Builder internal constructor() { + + private var browserSettings: JsonField = JsonMissing.of() + private var extensionId: JsonField = JsonMissing.of() + private var keepAlive: JsonField = JsonMissing.of() + private var projectId: JsonField = JsonMissing.of() + private var proxies: JsonField = JsonMissing.of() + private var region: JsonField = JsonMissing.of() + private var timeout: JsonField = JsonMissing.of() + private var userMetadata: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(browserbaseSessionCreateParams: BrowserbaseSessionCreateParams) = + apply { + browserSettings = browserbaseSessionCreateParams.browserSettings + extensionId = browserbaseSessionCreateParams.extensionId + keepAlive = browserbaseSessionCreateParams.keepAlive + projectId = browserbaseSessionCreateParams.projectId + proxies = browserbaseSessionCreateParams.proxies + region = browserbaseSessionCreateParams.region + timeout = browserbaseSessionCreateParams.timeout + userMetadata = browserbaseSessionCreateParams.userMetadata + additionalProperties = + browserbaseSessionCreateParams.additionalProperties.toMutableMap() + } + + fun browserSettings(browserSettings: BrowserSettings) = + browserSettings(JsonField.of(browserSettings)) + + /** + * Sets [Builder.browserSettings] to an arbitrary JSON value. + * + * You should usually call [Builder.browserSettings] with a well-typed [BrowserSettings] + * value instead. This method is primarily for setting the field to an undocumented or + * not yet supported value. + */ + fun browserSettings(browserSettings: JsonField) = apply { + this.browserSettings = browserSettings + } + + fun extensionId(extensionId: String) = extensionId(JsonField.of(extensionId)) + + /** + * Sets [Builder.extensionId] to an arbitrary JSON value. + * + * You should usually call [Builder.extensionId] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun extensionId(extensionId: JsonField) = apply { + this.extensionId = extensionId + } + + fun keepAlive(keepAlive: Boolean) = keepAlive(JsonField.of(keepAlive)) + + /** + * Sets [Builder.keepAlive] to an arbitrary JSON value. + * + * You should usually call [Builder.keepAlive] with a well-typed [Boolean] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun keepAlive(keepAlive: JsonField) = apply { this.keepAlive = keepAlive } + + fun projectId(projectId: String) = projectId(JsonField.of(projectId)) + + /** + * Sets [Builder.projectId] to an arbitrary JSON value. + * + * You should usually call [Builder.projectId] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun projectId(projectId: JsonField) = apply { this.projectId = projectId } + + fun proxies(proxies: Proxies) = proxies(JsonField.of(proxies)) + + /** + * Sets [Builder.proxies] to an arbitrary JSON value. + * + * You should usually call [Builder.proxies] with a well-typed [Proxies] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun proxies(proxies: JsonField) = apply { this.proxies = proxies } + + /** Alias for calling [proxies] with `Proxies.ofBool(bool)`. */ + fun proxies(bool: Boolean) = proxies(Proxies.ofBool(bool)) + + /** + * Alias for calling [proxies] with + * `Proxies.ofUnnamedSchemaWithArrayParent0s(unnamedSchemaWithArrayParent0s)`. + */ + fun proxiesOfUnnamedSchemaWithArrayParent0s( + unnamedSchemaWithArrayParent0s: List + ) = proxies(Proxies.ofUnnamedSchemaWithArrayParent0s(unnamedSchemaWithArrayParent0s)) + + fun region(region: Region) = region(JsonField.of(region)) + + /** + * Sets [Builder.region] to an arbitrary JSON value. + * + * You should usually call [Builder.region] with a well-typed [Region] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun region(region: JsonField) = apply { this.region = region } + + fun timeout(timeout: Double) = timeout(JsonField.of(timeout)) + + /** + * Sets [Builder.timeout] to an arbitrary JSON value. + * + * You should usually call [Builder.timeout] with a well-typed [Double] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun timeout(timeout: JsonField) = apply { this.timeout = timeout } + + fun userMetadata(userMetadata: UserMetadata) = userMetadata(JsonField.of(userMetadata)) + + /** + * Sets [Builder.userMetadata] to an arbitrary JSON value. + * + * You should usually call [Builder.userMetadata] with a well-typed [UserMetadata] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun userMetadata(userMetadata: JsonField) = apply { + this.userMetadata = userMetadata + } + + 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 [BrowserbaseSessionCreateParams]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): BrowserbaseSessionCreateParams = + BrowserbaseSessionCreateParams( + browserSettings, + extensionId, + keepAlive, + projectId, + proxies, + region, + timeout, + userMetadata, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): BrowserbaseSessionCreateParams = apply { + if (validated) { + return@apply + } + + browserSettings().ifPresent { it.validate() } + extensionId() + keepAlive() + projectId() + proxies().ifPresent { it.validate() } + region().ifPresent { it.validate() } + timeout() + userMetadata().ifPresent { it.validate() } + 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. + */ + @JvmSynthetic + internal fun validity(): Int = + (browserSettings.asKnown().getOrNull()?.validity() ?: 0) + + (if (extensionId.asKnown().isPresent) 1 else 0) + + (if (keepAlive.asKnown().isPresent) 1 else 0) + + (if (projectId.asKnown().isPresent) 1 else 0) + + (proxies.asKnown().getOrNull()?.validity() ?: 0) + + (region.asKnown().getOrNull()?.validity() ?: 0) + + (if (timeout.asKnown().isPresent) 1 else 0) + + (userMetadata.asKnown().getOrNull()?.validity() ?: 0) + + class BrowserSettings + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val advancedStealth: JsonField, + private val blockAds: JsonField, + private val context: JsonField, + private val extensionId: JsonField, + private val fingerprint: JsonField, + private val logSession: JsonField, + private val recordSession: JsonField, + private val solveCaptchas: JsonField, + private val viewport: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("advancedStealth") + @ExcludeMissing + advancedStealth: JsonField = JsonMissing.of(), + @JsonProperty("blockAds") + @ExcludeMissing + blockAds: JsonField = JsonMissing.of(), + @JsonProperty("context") + @ExcludeMissing + context: JsonField = JsonMissing.of(), + @JsonProperty("extensionId") + @ExcludeMissing + extensionId: JsonField = JsonMissing.of(), + @JsonProperty("fingerprint") + @ExcludeMissing + fingerprint: JsonField = JsonMissing.of(), + @JsonProperty("logSession") + @ExcludeMissing + logSession: JsonField = JsonMissing.of(), + @JsonProperty("recordSession") + @ExcludeMissing + recordSession: JsonField = JsonMissing.of(), + @JsonProperty("solveCaptchas") + @ExcludeMissing + solveCaptchas: JsonField = JsonMissing.of(), + @JsonProperty("viewport") + @ExcludeMissing + viewport: JsonField = JsonMissing.of(), + ) : this( + advancedStealth, + blockAds, + context, + extensionId, + fingerprint, + logSession, + recordSession, + solveCaptchas, + viewport, + mutableMapOf(), + ) + + /** + * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. + * if the server responded with an unexpected value). + */ + fun advancedStealth(): Optional = + advancedStealth.getOptional("advancedStealth") + + /** + * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. + * if the server responded with an unexpected value). + */ + fun blockAds(): Optional = blockAds.getOptional("blockAds") + + /** + * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. + * if the server responded with an unexpected value). + */ + fun context(): Optional = context.getOptional("context") + + /** + * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. + * if the server responded with an unexpected value). + */ + fun extensionId(): Optional = extensionId.getOptional("extensionId") + + /** + * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. + * if the server responded with an unexpected value). + */ + fun fingerprint(): Optional = fingerprint.getOptional("fingerprint") + + /** + * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. + * if the server responded with an unexpected value). + */ + fun logSession(): Optional = logSession.getOptional("logSession") + + /** + * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. + * if the server responded with an unexpected value). + */ + fun recordSession(): Optional = recordSession.getOptional("recordSession") + + /** + * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. + * if the server responded with an unexpected value). + */ + fun solveCaptchas(): Optional = solveCaptchas.getOptional("solveCaptchas") + + /** + * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. + * if the server responded with an unexpected value). + */ + fun viewport(): Optional = viewport.getOptional("viewport") + + /** + * Returns the raw JSON value of [advancedStealth]. + * + * Unlike [advancedStealth], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("advancedStealth") + @ExcludeMissing + fun _advancedStealth(): JsonField = advancedStealth + + /** + * Returns the raw JSON value of [blockAds]. + * + * Unlike [blockAds], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("blockAds") @ExcludeMissing fun _blockAds(): JsonField = blockAds + + /** + * Returns the raw JSON value of [context]. + * + * Unlike [context], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("context") @ExcludeMissing fun _context(): JsonField = context + + /** + * Returns the raw JSON value of [extensionId]. + * + * Unlike [extensionId], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("extensionId") + @ExcludeMissing + fun _extensionId(): JsonField = extensionId + + /** + * Returns the raw JSON value of [fingerprint]. + * + * Unlike [fingerprint], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("fingerprint") + @ExcludeMissing + fun _fingerprint(): JsonField = fingerprint + + /** + * Returns the raw JSON value of [logSession]. + * + * Unlike [logSession], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("logSession") + @ExcludeMissing + fun _logSession(): JsonField = logSession + + /** + * Returns the raw JSON value of [recordSession]. + * + * Unlike [recordSession], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("recordSession") + @ExcludeMissing + fun _recordSession(): JsonField = recordSession + + /** + * Returns the raw JSON value of [solveCaptchas]. + * + * Unlike [solveCaptchas], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("solveCaptchas") + @ExcludeMissing + fun _solveCaptchas(): JsonField = solveCaptchas + + /** + * Returns the raw JSON value of [viewport]. + * + * Unlike [viewport], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("viewport") + @ExcludeMissing + fun _viewport(): JsonField = viewport + + @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 [BrowserSettings]. */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [BrowserSettings]. */ + class Builder internal constructor() { + + private var advancedStealth: JsonField = JsonMissing.of() + private var blockAds: JsonField = JsonMissing.of() + private var context: JsonField = JsonMissing.of() + private var extensionId: JsonField = JsonMissing.of() + private var fingerprint: JsonField = JsonMissing.of() + private var logSession: JsonField = JsonMissing.of() + private var recordSession: JsonField = JsonMissing.of() + private var solveCaptchas: JsonField = JsonMissing.of() + private var viewport: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(browserSettings: BrowserSettings) = apply { + advancedStealth = browserSettings.advancedStealth + blockAds = browserSettings.blockAds + context = browserSettings.context + extensionId = browserSettings.extensionId + fingerprint = browserSettings.fingerprint + logSession = browserSettings.logSession + recordSession = browserSettings.recordSession + solveCaptchas = browserSettings.solveCaptchas + viewport = browserSettings.viewport + additionalProperties = browserSettings.additionalProperties.toMutableMap() + } + + fun advancedStealth(advancedStealth: Boolean) = + advancedStealth(JsonField.of(advancedStealth)) + + /** + * Sets [Builder.advancedStealth] to an arbitrary JSON value. + * + * You should usually call [Builder.advancedStealth] with a well-typed [Boolean] + * value instead. This method is primarily for setting the field to an undocumented + * or not yet supported value. + */ + fun advancedStealth(advancedStealth: JsonField) = apply { + this.advancedStealth = advancedStealth + } + + fun blockAds(blockAds: Boolean) = blockAds(JsonField.of(blockAds)) + + /** + * Sets [Builder.blockAds] to an arbitrary JSON value. + * + * You should usually call [Builder.blockAds] with a well-typed [Boolean] value + * instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun blockAds(blockAds: JsonField) = apply { this.blockAds = blockAds } + + fun context(context: Context) = context(JsonField.of(context)) + + /** + * Sets [Builder.context] to an arbitrary JSON value. + * + * You should usually call [Builder.context] with a well-typed [Context] value + * instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun context(context: JsonField) = apply { this.context = context } + + fun extensionId(extensionId: String) = extensionId(JsonField.of(extensionId)) + + /** + * Sets [Builder.extensionId] to an arbitrary JSON value. + * + * You should usually call [Builder.extensionId] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun extensionId(extensionId: JsonField) = apply { + this.extensionId = extensionId + } + + fun fingerprint(fingerprint: Fingerprint) = fingerprint(JsonField.of(fingerprint)) + + /** + * Sets [Builder.fingerprint] to an arbitrary JSON value. + * + * You should usually call [Builder.fingerprint] with a well-typed [Fingerprint] + * value instead. This method is primarily for setting the field to an undocumented + * or not yet supported value. + */ + fun fingerprint(fingerprint: JsonField) = apply { + this.fingerprint = fingerprint + } + + fun logSession(logSession: Boolean) = logSession(JsonField.of(logSession)) + + /** + * Sets [Builder.logSession] to an arbitrary JSON value. + * + * You should usually call [Builder.logSession] with a well-typed [Boolean] value + * instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun logSession(logSession: JsonField) = apply { + this.logSession = logSession + } + + fun recordSession(recordSession: Boolean) = + recordSession(JsonField.of(recordSession)) + + /** + * Sets [Builder.recordSession] to an arbitrary JSON value. + * + * You should usually call [Builder.recordSession] with a well-typed [Boolean] value + * instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun recordSession(recordSession: JsonField) = apply { + this.recordSession = recordSession + } + + fun solveCaptchas(solveCaptchas: Boolean) = + solveCaptchas(JsonField.of(solveCaptchas)) + + /** + * Sets [Builder.solveCaptchas] to an arbitrary JSON value. + * + * You should usually call [Builder.solveCaptchas] with a well-typed [Boolean] value + * instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun solveCaptchas(solveCaptchas: JsonField) = apply { + this.solveCaptchas = solveCaptchas + } + + fun viewport(viewport: Viewport) = viewport(JsonField.of(viewport)) + + /** + * Sets [Builder.viewport] to an arbitrary JSON value. + * + * You should usually call [Builder.viewport] with a well-typed [Viewport] value + * instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun viewport(viewport: JsonField) = apply { this.viewport = viewport } + + 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 [BrowserSettings]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): BrowserSettings = + BrowserSettings( + advancedStealth, + blockAds, + context, + extensionId, + fingerprint, + logSession, + recordSession, + solveCaptchas, + viewport, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): BrowserSettings = apply { + if (validated) { + return@apply + } + + advancedStealth() + blockAds() + context().ifPresent { it.validate() } + extensionId() + fingerprint().ifPresent { it.validate() } + logSession() + recordSession() + solveCaptchas() + viewport().ifPresent { it.validate() } + 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. + */ + @JvmSynthetic + internal fun validity(): Int = + (if (advancedStealth.asKnown().isPresent) 1 else 0) + + (if (blockAds.asKnown().isPresent) 1 else 0) + + (context.asKnown().getOrNull()?.validity() ?: 0) + + (if (extensionId.asKnown().isPresent) 1 else 0) + + (fingerprint.asKnown().getOrNull()?.validity() ?: 0) + + (if (logSession.asKnown().isPresent) 1 else 0) + + (if (recordSession.asKnown().isPresent) 1 else 0) + + (if (solveCaptchas.asKnown().isPresent) 1 else 0) + + (viewport.asKnown().getOrNull()?.validity() ?: 0) + + class Context + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val id: JsonField, + private val persist: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("id") @ExcludeMissing id: JsonField = JsonMissing.of(), + @JsonProperty("persist") + @ExcludeMissing + persist: JsonField = JsonMissing.of(), + ) : this(id, persist, mutableMapOf()) + + /** + * @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 id(): String = id.getRequired("id") + + /** + * @throws StagehandInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun persist(): Optional = persist.getOptional("persist") + + /** + * Returns the raw JSON value of [id]. + * + * Unlike [id], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("id") @ExcludeMissing fun _id(): JsonField = id + + /** + * Returns the raw JSON value of [persist]. + * + * Unlike [persist], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("persist") + @ExcludeMissing + fun _persist(): JsonField = persist + + @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 [Context]. + * + * The following fields are required: + * ```java + * .id() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Context]. */ + class Builder internal constructor() { + + private var id: JsonField? = null + private var persist: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(context: Context) = apply { + id = context.id + persist = context.persist + additionalProperties = context.additionalProperties.toMutableMap() + } + + fun id(id: String) = id(JsonField.of(id)) + + /** + * Sets [Builder.id] to an arbitrary JSON value. + * + * You should usually call [Builder.id] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or + * not yet supported value. + */ + fun id(id: JsonField) = apply { this.id = id } + + fun persist(persist: Boolean) = persist(JsonField.of(persist)) + + /** + * Sets [Builder.persist] to an arbitrary JSON value. + * + * You should usually call [Builder.persist] with a well-typed [Boolean] value + * instead. This method is primarily for setting the field to an undocumented or + * not yet supported value. + */ + fun persist(persist: JsonField) = apply { this.persist = persist } + + 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 [Context]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .id() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): Context = + Context( + checkRequired("id", id), + persist, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): Context = apply { + if (validated) { + return@apply + } + + id() + persist() + 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. + */ + @JvmSynthetic + internal fun validity(): Int = + (if (id.asKnown().isPresent) 1 else 0) + + (if (persist.asKnown().isPresent) 1 else 0) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Context && + id == other.id && + persist == other.persist && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(id, persist, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Context{id=$id, persist=$persist, additionalProperties=$additionalProperties}" + } + + class Fingerprint + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val browsers: JsonField>, + private val devices: JsonField>, + private val httpVersion: JsonField, + private val locales: JsonField>, + private val operatingSystems: JsonField>, + private val screen: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("browsers") + @ExcludeMissing + browsers: JsonField> = JsonMissing.of(), + @JsonProperty("devices") + @ExcludeMissing + devices: JsonField> = JsonMissing.of(), + @JsonProperty("httpVersion") + @ExcludeMissing + httpVersion: JsonField = JsonMissing.of(), + @JsonProperty("locales") + @ExcludeMissing + locales: JsonField> = JsonMissing.of(), + @JsonProperty("operatingSystems") + @ExcludeMissing + operatingSystems: JsonField> = JsonMissing.of(), + @JsonProperty("screen") + @ExcludeMissing + screen: JsonField = JsonMissing.of(), + ) : this( + browsers, + devices, + httpVersion, + locales, + operatingSystems, + screen, + mutableMapOf(), + ) + + /** + * @throws StagehandInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun browsers(): Optional> = browsers.getOptional("browsers") + + /** + * @throws StagehandInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun devices(): Optional> = devices.getOptional("devices") + + /** + * @throws StagehandInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun httpVersion(): Optional = httpVersion.getOptional("httpVersion") + + /** + * @throws StagehandInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun locales(): Optional> = locales.getOptional("locales") + + /** + * @throws StagehandInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun operatingSystems(): Optional> = + operatingSystems.getOptional("operatingSystems") + + /** + * @throws StagehandInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun screen(): Optional = screen.getOptional("screen") + + /** + * Returns the raw JSON value of [browsers]. + * + * Unlike [browsers], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("browsers") + @ExcludeMissing + fun _browsers(): JsonField> = browsers + + /** + * Returns the raw JSON value of [devices]. + * + * Unlike [devices], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("devices") + @ExcludeMissing + fun _devices(): JsonField> = devices + + /** + * Returns the raw JSON value of [httpVersion]. + * + * Unlike [httpVersion], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("httpVersion") + @ExcludeMissing + fun _httpVersion(): JsonField = httpVersion + + /** + * Returns the raw JSON value of [locales]. + * + * Unlike [locales], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("locales") + @ExcludeMissing + fun _locales(): JsonField> = locales + + /** + * Returns the raw JSON value of [operatingSystems]. + * + * Unlike [operatingSystems], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("operatingSystems") + @ExcludeMissing + fun _operatingSystems(): JsonField> = operatingSystems + + /** + * Returns the raw JSON value of [screen]. + * + * Unlike [screen], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("screen") @ExcludeMissing fun _screen(): JsonField = screen + + @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 [Fingerprint]. */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Fingerprint]. */ + class Builder internal constructor() { + + private var browsers: JsonField>? = null + private var devices: JsonField>? = null + private var httpVersion: JsonField = JsonMissing.of() + private var locales: JsonField>? = null + private var operatingSystems: JsonField>? = null + private var screen: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(fingerprint: Fingerprint) = apply { + browsers = fingerprint.browsers.map { it.toMutableList() } + devices = fingerprint.devices.map { it.toMutableList() } + httpVersion = fingerprint.httpVersion + locales = fingerprint.locales.map { it.toMutableList() } + operatingSystems = fingerprint.operatingSystems.map { it.toMutableList() } + screen = fingerprint.screen + additionalProperties = fingerprint.additionalProperties.toMutableMap() + } + + fun browsers(browsers: List) = browsers(JsonField.of(browsers)) + + /** + * Sets [Builder.browsers] to an arbitrary JSON value. + * + * You should usually call [Builder.browsers] with a well-typed `List` + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun browsers(browsers: JsonField>) = apply { + this.browsers = browsers.map { it.toMutableList() } + } + + /** + * Adds a single [Browser] to [browsers]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addBrowser(browser: Browser) = apply { + browsers = + (browsers ?: JsonField.of(mutableListOf())).also { + checkKnown("browsers", it).add(browser) + } + } + + fun devices(devices: List) = devices(JsonField.of(devices)) + + /** + * Sets [Builder.devices] to an arbitrary JSON value. + * + * You should usually call [Builder.devices] with a well-typed `List` + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun devices(devices: JsonField>) = apply { + this.devices = devices.map { it.toMutableList() } + } + + /** + * Adds a single [Device] to [devices]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addDevice(device: Device) = apply { + devices = + (devices ?: JsonField.of(mutableListOf())).also { + checkKnown("devices", it).add(device) + } + } + + fun httpVersion(httpVersion: HttpVersion) = + httpVersion(JsonField.of(httpVersion)) + + /** + * Sets [Builder.httpVersion] to an arbitrary JSON value. + * + * You should usually call [Builder.httpVersion] with a well-typed [HttpVersion] + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun httpVersion(httpVersion: JsonField) = apply { + this.httpVersion = httpVersion + } + + fun locales(locales: List) = locales(JsonField.of(locales)) + + /** + * Sets [Builder.locales] to an arbitrary JSON value. + * + * You should usually call [Builder.locales] with a well-typed `List` + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun locales(locales: JsonField>) = apply { + this.locales = locales.map { it.toMutableList() } + } + + /** + * Adds a single [String] to [locales]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addLocale(locale: String) = apply { + locales = + (locales ?: JsonField.of(mutableListOf())).also { + checkKnown("locales", it).add(locale) + } + } + + fun operatingSystems(operatingSystems: List) = + operatingSystems(JsonField.of(operatingSystems)) + + /** + * Sets [Builder.operatingSystems] to an arbitrary JSON value. + * + * You should usually call [Builder.operatingSystems] with a well-typed + * `List` value instead. This method is primarily for setting + * the field to an undocumented or not yet supported value. + */ + fun operatingSystems(operatingSystems: JsonField>) = + apply { + this.operatingSystems = operatingSystems.map { it.toMutableList() } + } + + /** + * Adds a single [OperatingSystem] to [operatingSystems]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addOperatingSystem(operatingSystem: OperatingSystem) = apply { + operatingSystems = + (operatingSystems ?: JsonField.of(mutableListOf())).also { + checkKnown("operatingSystems", it).add(operatingSystem) + } + } + + fun screen(screen: Screen) = screen(JsonField.of(screen)) + + /** + * Sets [Builder.screen] to an arbitrary JSON value. + * + * You should usually call [Builder.screen] with a well-typed [Screen] value + * instead. This method is primarily for setting the field to an undocumented or + * not yet supported value. + */ + fun screen(screen: JsonField) = apply { this.screen = screen } + + 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 [Fingerprint]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): Fingerprint = + Fingerprint( + (browsers ?: JsonMissing.of()).map { it.toImmutable() }, + (devices ?: JsonMissing.of()).map { it.toImmutable() }, + httpVersion, + (locales ?: JsonMissing.of()).map { it.toImmutable() }, + (operatingSystems ?: JsonMissing.of()).map { it.toImmutable() }, + screen, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): Fingerprint = apply { + if (validated) { + return@apply + } + + browsers().ifPresent { it.forEach { it.validate() } } + devices().ifPresent { it.forEach { it.validate() } } + httpVersion().ifPresent { it.validate() } + locales() + operatingSystems().ifPresent { it.forEach { it.validate() } } + screen().ifPresent { it.validate() } + 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. + */ + @JvmSynthetic + internal fun validity(): Int = + (browsers.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + + (devices.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + + (httpVersion.asKnown().getOrNull()?.validity() ?: 0) + + (locales.asKnown().getOrNull()?.size ?: 0) + + (operatingSystems.asKnown().getOrNull()?.sumOf { it.validity().toInt() } + ?: 0) + + (screen.asKnown().getOrNull()?.validity() ?: 0) + + class Browser + @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 { + + @JvmField val CHROME = of("chrome") + + @JvmField val EDGE = of("edge") + + @JvmField val FIREFOX = of("firefox") + + @JvmField val SAFARI = of("safari") + + @JvmStatic fun of(value: String) = Browser(JsonField.of(value)) + } + + /** An enum containing [Browser]'s known values. */ + enum class Known { + CHROME, + EDGE, + FIREFOX, + SAFARI, + } + + /** + * An enum containing [Browser]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [Browser] 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 { + CHROME, + EDGE, + FIREFOX, + SAFARI, + /** + * An enum member indicating that [Browser] 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) { + CHROME -> Value.CHROME + EDGE -> Value.EDGE + FIREFOX -> Value.FIREFOX + SAFARI -> Value.SAFARI + 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) { + CHROME -> Known.CHROME + EDGE -> Known.EDGE + FIREFOX -> Known.FIREFOX + SAFARI -> Known.SAFARI + else -> throw StagehandInvalidDataException("Unknown Browser: $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().orElseThrow { + StagehandInvalidDataException("Value is not a String") + } + + private var validated: Boolean = false + + fun validate(): Browser = 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. + */ + @JvmSynthetic + 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 Browser && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + class Device + @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 { + + @JvmField val DESKTOP = of("desktop") + + @JvmField val MOBILE = of("mobile") + + @JvmStatic fun of(value: String) = Device(JsonField.of(value)) + } + + /** An enum containing [Device]'s known values. */ + enum class Known { + DESKTOP, + MOBILE, + } + + /** + * An enum containing [Device]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [Device] 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 { + DESKTOP, + MOBILE, + /** + * An enum member indicating that [Device] 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) { + DESKTOP -> Value.DESKTOP + MOBILE -> Value.MOBILE + 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) { + DESKTOP -> Known.DESKTOP + MOBILE -> Known.MOBILE + else -> throw StagehandInvalidDataException("Unknown Device: $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().orElseThrow { + StagehandInvalidDataException("Value is not a String") + } + + private var validated: Boolean = false + + fun validate(): Device = 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. + */ + @JvmSynthetic + 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 Device && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + class HttpVersion + @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 { + + @JvmField val _1 = of("1") + + @JvmField val _2 = of("2") + + @JvmStatic fun of(value: String) = HttpVersion(JsonField.of(value)) + } + + /** An enum containing [HttpVersion]'s known values. */ + enum class Known { + _1, + _2, + } + + /** + * An enum containing [HttpVersion]'s known values, as well as an [_UNKNOWN] + * member. + * + * An instance of [HttpVersion] 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 { + _1, + _2, + /** + * An enum member indicating that [HttpVersion] 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) { + _1 -> Value._1 + _2 -> Value._2 + 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) { + _1 -> Known._1 + _2 -> Known._2 + else -> + throw StagehandInvalidDataException("Unknown HttpVersion: $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().orElseThrow { + StagehandInvalidDataException("Value is not a String") + } + + private var validated: Boolean = false + + fun validate(): HttpVersion = 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. + */ + @JvmSynthetic + 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 HttpVersion && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + class OperatingSystem + @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 { + + @JvmField val ANDROID = of("android") + + @JvmField val IOS = of("ios") + + @JvmField val LINUX = of("linux") + + @JvmField val MACOS = of("macos") + + @JvmField val WINDOWS = of("windows") + + @JvmStatic fun of(value: String) = OperatingSystem(JsonField.of(value)) + } + + /** An enum containing [OperatingSystem]'s known values. */ + enum class Known { + ANDROID, + IOS, + LINUX, + MACOS, + WINDOWS, + } + + /** + * An enum containing [OperatingSystem]'s known values, as well as an [_UNKNOWN] + * member. + * + * An instance of [OperatingSystem] 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 { + ANDROID, + IOS, + LINUX, + MACOS, + WINDOWS, + /** + * An enum member indicating that [OperatingSystem] 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) { + ANDROID -> Value.ANDROID + IOS -> Value.IOS + LINUX -> Value.LINUX + MACOS -> Value.MACOS + WINDOWS -> Value.WINDOWS + 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) { + ANDROID -> Known.ANDROID + IOS -> Known.IOS + LINUX -> Known.LINUX + MACOS -> Known.MACOS + WINDOWS -> Known.WINDOWS + else -> + throw StagehandInvalidDataException( + "Unknown OperatingSystem: $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().orElseThrow { + StagehandInvalidDataException("Value is not a String") + } + + private var validated: Boolean = false + + fun validate(): OperatingSystem = 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. + */ + @JvmSynthetic + 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 OperatingSystem && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + class Screen + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val maxHeight: JsonField, + private val maxWidth: JsonField, + private val minHeight: JsonField, + private val minWidth: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("maxHeight") + @ExcludeMissing + maxHeight: JsonField = JsonMissing.of(), + @JsonProperty("maxWidth") + @ExcludeMissing + maxWidth: JsonField = JsonMissing.of(), + @JsonProperty("minHeight") + @ExcludeMissing + minHeight: JsonField = JsonMissing.of(), + @JsonProperty("minWidth") + @ExcludeMissing + minWidth: JsonField = JsonMissing.of(), + ) : this(maxHeight, maxWidth, minHeight, minWidth, mutableMapOf()) + + /** + * @throws StagehandInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun maxHeight(): Optional = maxHeight.getOptional("maxHeight") + + /** + * @throws StagehandInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun maxWidth(): Optional = maxWidth.getOptional("maxWidth") + + /** + * @throws StagehandInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun minHeight(): Optional = minHeight.getOptional("minHeight") + + /** + * @throws StagehandInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun minWidth(): Optional = minWidth.getOptional("minWidth") + + /** + * Returns the raw JSON value of [maxHeight]. + * + * Unlike [maxHeight], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("maxHeight") + @ExcludeMissing + fun _maxHeight(): JsonField = maxHeight + + /** + * Returns the raw JSON value of [maxWidth]. + * + * Unlike [maxWidth], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("maxWidth") + @ExcludeMissing + fun _maxWidth(): JsonField = maxWidth + + /** + * Returns the raw JSON value of [minHeight]. + * + * Unlike [minHeight], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("minHeight") + @ExcludeMissing + fun _minHeight(): JsonField = minHeight + + /** + * Returns the raw JSON value of [minWidth]. + * + * Unlike [minWidth], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("minWidth") + @ExcludeMissing + fun _minWidth(): JsonField = minWidth + + @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 [Screen]. */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Screen]. */ + class Builder internal constructor() { + + private var maxHeight: JsonField = JsonMissing.of() + private var maxWidth: JsonField = JsonMissing.of() + private var minHeight: JsonField = JsonMissing.of() + private var minWidth: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = + mutableMapOf() + + @JvmSynthetic + internal fun from(screen: Screen) = apply { + maxHeight = screen.maxHeight + maxWidth = screen.maxWidth + minHeight = screen.minHeight + minWidth = screen.minWidth + additionalProperties = screen.additionalProperties.toMutableMap() + } + + fun maxHeight(maxHeight: Double) = maxHeight(JsonField.of(maxHeight)) + + /** + * Sets [Builder.maxHeight] to an arbitrary JSON value. + * + * You should usually call [Builder.maxHeight] with a well-typed [Double] + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun maxHeight(maxHeight: JsonField) = apply { + this.maxHeight = maxHeight + } + + fun maxWidth(maxWidth: Double) = maxWidth(JsonField.of(maxWidth)) + + /** + * Sets [Builder.maxWidth] to an arbitrary JSON value. + * + * You should usually call [Builder.maxWidth] with a well-typed [Double] + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun maxWidth(maxWidth: JsonField) = apply { + this.maxWidth = maxWidth + } + + fun minHeight(minHeight: Double) = minHeight(JsonField.of(minHeight)) + + /** + * Sets [Builder.minHeight] to an arbitrary JSON value. + * + * You should usually call [Builder.minHeight] with a well-typed [Double] + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun minHeight(minHeight: JsonField) = apply { + this.minHeight = minHeight + } + + fun minWidth(minWidth: Double) = minWidth(JsonField.of(minWidth)) + + /** + * Sets [Builder.minWidth] to an arbitrary JSON value. + * + * You should usually call [Builder.minWidth] with a well-typed [Double] + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun minWidth(minWidth: JsonField) = apply { + this.minWidth = minWidth + } + + 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 [Screen]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): Screen = + Screen( + maxHeight, + maxWidth, + minHeight, + minWidth, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): Screen = apply { + if (validated) { + return@apply + } + + maxHeight() + maxWidth() + minHeight() + minWidth() + 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. + */ + @JvmSynthetic + internal fun validity(): Int = + (if (maxHeight.asKnown().isPresent) 1 else 0) + + (if (maxWidth.asKnown().isPresent) 1 else 0) + + (if (minHeight.asKnown().isPresent) 1 else 0) + + (if (minWidth.asKnown().isPresent) 1 else 0) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Screen && + maxHeight == other.maxHeight && + maxWidth == other.maxWidth && + minHeight == other.minHeight && + minWidth == other.minWidth && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(maxHeight, maxWidth, minHeight, minWidth, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Screen{maxHeight=$maxHeight, maxWidth=$maxWidth, minHeight=$minHeight, minWidth=$minWidth, additionalProperties=$additionalProperties}" + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Fingerprint && + browsers == other.browsers && + devices == other.devices && + httpVersion == other.httpVersion && + locales == other.locales && + operatingSystems == other.operatingSystems && + screen == other.screen && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash( + browsers, + devices, + httpVersion, + locales, + operatingSystems, + screen, + additionalProperties, + ) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Fingerprint{browsers=$browsers, devices=$devices, httpVersion=$httpVersion, locales=$locales, operatingSystems=$operatingSystems, screen=$screen, additionalProperties=$additionalProperties}" + } + + class Viewport + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val height: JsonField, + private val width: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("height") + @ExcludeMissing + height: JsonField = JsonMissing.of(), + @JsonProperty("width") + @ExcludeMissing + width: JsonField = JsonMissing.of(), + ) : this(height, width, mutableMapOf()) + + /** + * @throws StagehandInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun height(): Optional = height.getOptional("height") + + /** + * @throws StagehandInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun width(): Optional = width.getOptional("width") + + /** + * Returns the raw JSON value of [height]. + * + * Unlike [height], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("height") @ExcludeMissing fun _height(): JsonField = height + + /** + * Returns the raw JSON value of [width]. + * + * Unlike [width], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("width") @ExcludeMissing fun _width(): JsonField = width + + @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 [Viewport]. */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Viewport]. */ + class Builder internal constructor() { + + private var height: JsonField = JsonMissing.of() + private var width: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(viewport: Viewport) = apply { + height = viewport.height + width = viewport.width + additionalProperties = viewport.additionalProperties.toMutableMap() + } + + fun height(height: Double) = height(JsonField.of(height)) + + /** + * Sets [Builder.height] to an arbitrary JSON value. + * + * You should usually call [Builder.height] with a well-typed [Double] value + * instead. This method is primarily for setting the field to an undocumented or + * not yet supported value. + */ + fun height(height: JsonField) = apply { this.height = height } + + fun width(width: Double) = width(JsonField.of(width)) + + /** + * Sets [Builder.width] to an arbitrary JSON value. + * + * You should usually call [Builder.width] with a well-typed [Double] value + * instead. This method is primarily for setting the field to an undocumented or + * not yet supported value. + */ + fun width(width: JsonField) = apply { this.width = width } + + 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 [Viewport]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): Viewport = + Viewport(height, width, additionalProperties.toMutableMap()) + } + + private var validated: Boolean = false + + fun validate(): Viewport = apply { + if (validated) { + return@apply + } + + height() + width() + 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. + */ + @JvmSynthetic + internal fun validity(): Int = + (if (height.asKnown().isPresent) 1 else 0) + + (if (width.asKnown().isPresent) 1 else 0) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Viewport && + height == other.height && + width == other.width && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(height, width, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Viewport{height=$height, width=$width, additionalProperties=$additionalProperties}" + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is BrowserSettings && + advancedStealth == other.advancedStealth && + blockAds == other.blockAds && + context == other.context && + extensionId == other.extensionId && + fingerprint == other.fingerprint && + logSession == other.logSession && + recordSession == other.recordSession && + solveCaptchas == other.solveCaptchas && + viewport == other.viewport && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash( + advancedStealth, + blockAds, + context, + extensionId, + fingerprint, + logSession, + recordSession, + solveCaptchas, + viewport, + additionalProperties, + ) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "BrowserSettings{advancedStealth=$advancedStealth, blockAds=$blockAds, context=$context, extensionId=$extensionId, fingerprint=$fingerprint, logSession=$logSession, recordSession=$recordSession, solveCaptchas=$solveCaptchas, viewport=$viewport, additionalProperties=$additionalProperties}" + } + + @JsonDeserialize(using = Proxies.Deserializer::class) + @JsonSerialize(using = Proxies.Serializer::class) + class Proxies + private constructor( + private val bool: Boolean? = null, + private val unnamedSchemaWithArrayParent0s: List? = null, + private val _json: JsonValue? = null, + ) { + + fun bool(): Optional = Optional.ofNullable(bool) + + fun unnamedSchemaWithArrayParent0s(): Optional> = + Optional.ofNullable(unnamedSchemaWithArrayParent0s) + + fun isBool(): Boolean = bool != null + + fun isUnnamedSchemaWithArrayParent0s(): Boolean = unnamedSchemaWithArrayParent0s != null + + fun asBool(): Boolean = bool.getOrThrow("bool") + + fun asUnnamedSchemaWithArrayParent0s(): List = + unnamedSchemaWithArrayParent0s.getOrThrow("unnamedSchemaWithArrayParent0s") + + fun _json(): Optional = Optional.ofNullable(_json) + + fun accept(visitor: Visitor): T = + when { + bool != null -> visitor.visitBool(bool) + unnamedSchemaWithArrayParent0s != null -> + visitor.visitUnnamedSchemaWithArrayParent0s(unnamedSchemaWithArrayParent0s) + else -> visitor.unknown(_json) + } + + private var validated: Boolean = false + + fun validate(): Proxies = apply { + if (validated) { + return@apply + } + + accept( + object : Visitor { + override fun visitBool(bool: Boolean) {} + + override fun visitUnnamedSchemaWithArrayParent0s( + unnamedSchemaWithArrayParent0s: List + ) { + unnamedSchemaWithArrayParent0s.forEach { it.validate() } + } + } + ) + 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. + */ + @JvmSynthetic + internal fun validity(): Int = + accept( + object : Visitor { + override fun visitBool(bool: Boolean) = 1 + + override fun visitUnnamedSchemaWithArrayParent0s( + unnamedSchemaWithArrayParent0s: List + ) = unnamedSchemaWithArrayParent0s.sumOf { it.validity().toInt() } + + override fun unknown(json: JsonValue?) = 0 + } + ) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Proxies && + bool == other.bool && + unnamedSchemaWithArrayParent0s == other.unnamedSchemaWithArrayParent0s + } + + override fun hashCode(): Int = Objects.hash(bool, unnamedSchemaWithArrayParent0s) + + override fun toString(): String = + when { + bool != null -> "Proxies{bool=$bool}" + unnamedSchemaWithArrayParent0s != null -> + "Proxies{unnamedSchemaWithArrayParent0s=$unnamedSchemaWithArrayParent0s}" + _json != null -> "Proxies{_unknown=$_json}" + else -> throw IllegalStateException("Invalid Proxies") + } + + companion object { + + @JvmStatic fun ofBool(bool: Boolean) = Proxies(bool = bool) + + @JvmStatic + fun ofUnnamedSchemaWithArrayParent0s( + unnamedSchemaWithArrayParent0s: List + ) = + Proxies( + unnamedSchemaWithArrayParent0s = + unnamedSchemaWithArrayParent0s.toImmutable() + ) + } + + /** + * An interface that defines how to map each variant of [Proxies] to a value of type + * [T]. + */ + interface Visitor { + + fun visitBool(bool: Boolean): T + + fun visitUnnamedSchemaWithArrayParent0s( + unnamedSchemaWithArrayParent0s: List + ): T + + /** + * Maps an unknown variant of [Proxies] to a value of type [T]. + * + * An instance of [Proxies] can contain an unknown variant if it was deserialized + * from data that doesn't match any known variant. For example, if the SDK is on an + * older version than the API, then the API may respond with new variants that the + * SDK is unaware of. + * + * @throws StagehandInvalidDataException in the default implementation. + */ + fun unknown(json: JsonValue?): T { + throw StagehandInvalidDataException("Unknown Proxies: $json") + } + } + + internal class Deserializer : BaseDeserializer(Proxies::class) { + + override fun ObjectCodec.deserialize(node: JsonNode): Proxies { + val json = JsonValue.fromJsonNode(node) + + val bestMatches = + sequenceOf( + tryDeserialize(node, jacksonTypeRef())?.let { + Proxies(bool = it, _json = json) + }, + tryDeserialize( + node, + jacksonTypeRef>(), + ) + ?.let { + Proxies(unnamedSchemaWithArrayParent0s = it, _json = json) + }, + ) + .filterNotNull() + .allMaxBy { it.validity() } + .toList() + return when (bestMatches.size) { + // This can happen if what we're deserializing is completely incompatible + // with all the possible variants (e.g. deserializing from string). + 0 -> Proxies(_json = json) + 1 -> bestMatches.single() + // If there's more than one match with the highest validity, then use the + // first completely valid match, or simply the first match if none are + // completely valid. + else -> bestMatches.firstOrNull { it.isValid() } ?: bestMatches.first() + } + } + } + + internal class Serializer : BaseSerializer(Proxies::class) { + + override fun serialize( + value: Proxies, + generator: JsonGenerator, + provider: SerializerProvider, + ) { + when { + value.bool != null -> generator.writeObject(value.bool) + value.unnamedSchemaWithArrayParent0s != null -> + generator.writeObject(value.unnamedSchemaWithArrayParent0s) + value._json != null -> generator.writeObject(value._json) + else -> throw IllegalStateException("Invalid Proxies") + } + } + } + + @JsonDeserialize(using = UnnamedSchemaWithArrayParent0.Deserializer::class) + @JsonSerialize(using = UnnamedSchemaWithArrayParent0.Serializer::class) + class UnnamedSchemaWithArrayParent0 + private constructor( + private val browserbaseProxyConfig: BrowserbaseProxyConfig? = null, + private val externalProxyConfig: ExternalProxyConfig? = null, + private val _json: JsonValue? = null, + ) { + + fun browserbaseProxyConfig(): Optional = + Optional.ofNullable(browserbaseProxyConfig) + + fun externalProxyConfig(): Optional = + Optional.ofNullable(externalProxyConfig) + + fun isBrowserbaseProxyConfig(): Boolean = browserbaseProxyConfig != null + + fun isExternalProxyConfig(): Boolean = externalProxyConfig != null + + fun asBrowserbaseProxyConfig(): BrowserbaseProxyConfig = + browserbaseProxyConfig.getOrThrow("browserbaseProxyConfig") + + fun asExternalProxyConfig(): ExternalProxyConfig = + externalProxyConfig.getOrThrow("externalProxyConfig") + + fun _json(): Optional = Optional.ofNullable(_json) + + fun accept(visitor: Visitor): T = + when { + browserbaseProxyConfig != null -> + visitor.visitBrowserbaseProxyConfig(browserbaseProxyConfig) + externalProxyConfig != null -> + visitor.visitExternalProxyConfig(externalProxyConfig) + else -> visitor.unknown(_json) + } + + private var validated: Boolean = false + + fun validate(): UnnamedSchemaWithArrayParent0 = apply { + if (validated) { + return@apply + } + + accept( + object : Visitor { + override fun visitBrowserbaseProxyConfig( + browserbaseProxyConfig: BrowserbaseProxyConfig + ) { + browserbaseProxyConfig.validate() + } + + override fun visitExternalProxyConfig( + externalProxyConfig: ExternalProxyConfig + ) { + externalProxyConfig.validate() + } + } + ) + 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. + */ + @JvmSynthetic + internal fun validity(): Int = + accept( + object : Visitor { + override fun visitBrowserbaseProxyConfig( + browserbaseProxyConfig: BrowserbaseProxyConfig + ) = browserbaseProxyConfig.validity() + + override fun visitExternalProxyConfig( + externalProxyConfig: ExternalProxyConfig + ) = externalProxyConfig.validity() + + override fun unknown(json: JsonValue?) = 0 + } + ) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is UnnamedSchemaWithArrayParent0 && + browserbaseProxyConfig == other.browserbaseProxyConfig && + externalProxyConfig == other.externalProxyConfig + } + + override fun hashCode(): Int = + Objects.hash(browserbaseProxyConfig, externalProxyConfig) + + override fun toString(): String = + when { + browserbaseProxyConfig != null -> + "UnnamedSchemaWithArrayParent0{browserbaseProxyConfig=$browserbaseProxyConfig}" + externalProxyConfig != null -> + "UnnamedSchemaWithArrayParent0{externalProxyConfig=$externalProxyConfig}" + _json != null -> "UnnamedSchemaWithArrayParent0{_unknown=$_json}" + else -> throw IllegalStateException("Invalid UnnamedSchemaWithArrayParent0") + } + + companion object { + + @JvmStatic + fun ofBrowserbaseProxyConfig(browserbaseProxyConfig: BrowserbaseProxyConfig) = + UnnamedSchemaWithArrayParent0( + browserbaseProxyConfig = browserbaseProxyConfig + ) + + @JvmStatic + fun ofExternalProxyConfig(externalProxyConfig: ExternalProxyConfig) = + UnnamedSchemaWithArrayParent0(externalProxyConfig = externalProxyConfig) + } + + /** + * An interface that defines how to map each variant of + * [UnnamedSchemaWithArrayParent0] to a value of type [T]. + */ + interface Visitor { + + fun visitBrowserbaseProxyConfig( + browserbaseProxyConfig: BrowserbaseProxyConfig + ): T + + fun visitExternalProxyConfig(externalProxyConfig: ExternalProxyConfig): T + + /** + * Maps an unknown variant of [UnnamedSchemaWithArrayParent0] to a value of type + * [T]. + * + * An instance of [UnnamedSchemaWithArrayParent0] can contain an unknown variant + * if it was deserialized from data that doesn't match any known variant. For + * example, if the SDK is on an older version than the API, then the API may + * respond with new variants that the SDK is unaware of. + * + * @throws StagehandInvalidDataException in the default implementation. + */ + fun unknown(json: JsonValue?): T { + throw StagehandInvalidDataException( + "Unknown UnnamedSchemaWithArrayParent0: $json" + ) + } + } + + internal class Deserializer : + BaseDeserializer( + UnnamedSchemaWithArrayParent0::class + ) { + + override fun ObjectCodec.deserialize( + node: JsonNode + ): UnnamedSchemaWithArrayParent0 { + val json = JsonValue.fromJsonNode(node) + + val bestMatches = + sequenceOf( + tryDeserialize(node, jacksonTypeRef()) + ?.let { + UnnamedSchemaWithArrayParent0( + browserbaseProxyConfig = it, + _json = json, + ) + }, + tryDeserialize(node, jacksonTypeRef()) + ?.let { + UnnamedSchemaWithArrayParent0( + externalProxyConfig = it, + _json = json, + ) + }, + ) + .filterNotNull() + .allMaxBy { it.validity() } + .toList() + return when (bestMatches.size) { + // This can happen if what we're deserializing is completely + // incompatible with all the possible variants (e.g. deserializing from + // boolean). + 0 -> UnnamedSchemaWithArrayParent0(_json = json) + 1 -> bestMatches.single() + // If there's more than one match with the highest validity, then use + // the first completely valid match, or simply the first match if none + // are completely valid. + else -> bestMatches.firstOrNull { it.isValid() } ?: bestMatches.first() + } + } + } + + internal class Serializer : + BaseSerializer( + UnnamedSchemaWithArrayParent0::class + ) { + + override fun serialize( + value: UnnamedSchemaWithArrayParent0, + generator: JsonGenerator, + provider: SerializerProvider, + ) { + when { + value.browserbaseProxyConfig != null -> + generator.writeObject(value.browserbaseProxyConfig) + value.externalProxyConfig != null -> + generator.writeObject(value.externalProxyConfig) + value._json != null -> generator.writeObject(value._json) + else -> + throw IllegalStateException("Invalid UnnamedSchemaWithArrayParent0") + } + } + } + + class BrowserbaseProxyConfig + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val type: JsonField, + private val domainPattern: JsonField, + private val geolocation: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("type") + @ExcludeMissing + type: JsonField = JsonMissing.of(), + @JsonProperty("domainPattern") + @ExcludeMissing + domainPattern: JsonField = JsonMissing.of(), + @JsonProperty("geolocation") + @ExcludeMissing + geolocation: JsonField = JsonMissing.of(), + ) : this(type, domainPattern, geolocation, mutableMapOf()) + + /** + * @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 type(): Type = type.getRequired("type") + + /** + * @throws StagehandInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun domainPattern(): Optional = + domainPattern.getOptional("domainPattern") + + /** + * @throws StagehandInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun geolocation(): Optional = + geolocation.getOptional("geolocation") + + /** + * Returns the raw JSON value of [type]. + * + * Unlike [type], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("type") @ExcludeMissing fun _type(): JsonField = type + + /** + * Returns the raw JSON value of [domainPattern]. + * + * Unlike [domainPattern], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("domainPattern") + @ExcludeMissing + fun _domainPattern(): JsonField = domainPattern + + /** + * Returns the raw JSON value of [geolocation]. + * + * Unlike [geolocation], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("geolocation") + @ExcludeMissing + fun _geolocation(): JsonField = geolocation + + @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 + * [BrowserbaseProxyConfig]. + * + * The following fields are required: + * ```java + * .type() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [BrowserbaseProxyConfig]. */ + class Builder internal constructor() { + + private var type: JsonField? = null + private var domainPattern: JsonField = JsonMissing.of() + private var geolocation: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = + mutableMapOf() + + @JvmSynthetic + internal fun from(browserbaseProxyConfig: BrowserbaseProxyConfig) = apply { + type = browserbaseProxyConfig.type + domainPattern = browserbaseProxyConfig.domainPattern + geolocation = browserbaseProxyConfig.geolocation + additionalProperties = + browserbaseProxyConfig.additionalProperties.toMutableMap() + } + + fun type(type: Type) = type(JsonField.of(type)) + + /** + * Sets [Builder.type] to an arbitrary JSON value. + * + * You should usually call [Builder.type] with a well-typed [Type] value + * instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun type(type: JsonField) = apply { this.type = type } + + fun domainPattern(domainPattern: String) = + domainPattern(JsonField.of(domainPattern)) + + /** + * Sets [Builder.domainPattern] to an arbitrary JSON value. + * + * You should usually call [Builder.domainPattern] with a well-typed + * [String] value instead. This method is primarily for setting the field to + * an undocumented or not yet supported value. + */ + fun domainPattern(domainPattern: JsonField) = apply { + this.domainPattern = domainPattern + } + + fun geolocation(geolocation: Geolocation) = + geolocation(JsonField.of(geolocation)) + + /** + * Sets [Builder.geolocation] to an arbitrary JSON value. + * + * You should usually call [Builder.geolocation] with a well-typed + * [Geolocation] value instead. This method is primarily for setting the + * field to an undocumented or not yet supported value. + */ + fun geolocation(geolocation: JsonField) = apply { + this.geolocation = geolocation + } + + 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 [BrowserbaseProxyConfig]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .type() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): BrowserbaseProxyConfig = + BrowserbaseProxyConfig( + checkRequired("type", type), + domainPattern, + geolocation, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): BrowserbaseProxyConfig = apply { + if (validated) { + return@apply + } + + type().validate() + domainPattern() + geolocation().ifPresent { it.validate() } + 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. + */ + @JvmSynthetic + internal fun validity(): Int = + (type.asKnown().getOrNull()?.validity() ?: 0) + + (if (domainPattern.asKnown().isPresent) 1 else 0) + + (geolocation.asKnown().getOrNull()?.validity() ?: 0) + + class Type + @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 { + + @JvmField val BROWSERBASE = of("browserbase") + + @JvmStatic fun of(value: String) = Type(JsonField.of(value)) + } + + /** An enum containing [Type]'s known values. */ + enum class Known { + BROWSERBASE + } + + /** + * An enum containing [Type]'s known values, as well as an [_UNKNOWN] + * member. + * + * An instance of [Type] 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 { + BROWSERBASE, + /** + * An enum member indicating that [Type] 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) { + BROWSERBASE -> Value.BROWSERBASE + 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) { + BROWSERBASE -> Known.BROWSERBASE + else -> throw StagehandInvalidDataException("Unknown Type: $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().orElseThrow { + StagehandInvalidDataException("Value is not a String") + } + + private var validated: Boolean = false + + fun validate(): Type = 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. + */ + @JvmSynthetic + 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 Type && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + class Geolocation + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val country: JsonField, + private val city: JsonField, + private val state: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("country") + @ExcludeMissing + country: JsonField = JsonMissing.of(), + @JsonProperty("city") + @ExcludeMissing + city: JsonField = JsonMissing.of(), + @JsonProperty("state") + @ExcludeMissing + state: JsonField = JsonMissing.of(), + ) : this(country, city, state, mutableMapOf()) + + /** + * @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 country(): String = country.getRequired("country") + + /** + * @throws StagehandInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun city(): Optional = city.getOptional("city") + + /** + * @throws StagehandInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun state(): Optional = state.getOptional("state") + + /** + * Returns the raw JSON value of [country]. + * + * Unlike [country], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("country") + @ExcludeMissing + fun _country(): JsonField = country + + /** + * Returns the raw JSON value of [city]. + * + * Unlike [city], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("city") @ExcludeMissing fun _city(): JsonField = city + + /** + * Returns the raw JSON value of [state]. + * + * Unlike [state], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("state") + @ExcludeMissing + fun _state(): JsonField = state + + @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 + * [Geolocation]. + * + * The following fields are required: + * ```java + * .country() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Geolocation]. */ + class Builder internal constructor() { + + private var country: JsonField? = null + private var city: JsonField = JsonMissing.of() + private var state: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = + mutableMapOf() + + @JvmSynthetic + internal fun from(geolocation: Geolocation) = apply { + country = geolocation.country + city = geolocation.city + state = geolocation.state + additionalProperties = + geolocation.additionalProperties.toMutableMap() + } + + fun country(country: String) = country(JsonField.of(country)) + + /** + * Sets [Builder.country] to an arbitrary JSON value. + * + * You should usually call [Builder.country] with a well-typed [String] + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun country(country: JsonField) = apply { + this.country = country + } + + fun city(city: String) = city(JsonField.of(city)) + + /** + * Sets [Builder.city] to an arbitrary JSON value. + * + * You should usually call [Builder.city] with a well-typed [String] + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun city(city: JsonField) = apply { this.city = city } + + fun state(state: String) = state(JsonField.of(state)) + + /** + * Sets [Builder.state] to an arbitrary JSON value. + * + * You should usually call [Builder.state] with a well-typed [String] + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun state(state: JsonField) = apply { this.state = state } + + 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 [Geolocation]. + * + * Further updates to this [Builder] will not mutate the returned + * instance. + * + * The following fields are required: + * ```java + * .country() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): Geolocation = + Geolocation( + checkRequired("country", country), + city, + state, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): Geolocation = apply { + if (validated) { + return@apply + } + + country() + city() + state() + 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. + */ + @JvmSynthetic + internal fun validity(): Int = + (if (country.asKnown().isPresent) 1 else 0) + + (if (city.asKnown().isPresent) 1 else 0) + + (if (state.asKnown().isPresent) 1 else 0) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Geolocation && + country == other.country && + city == other.city && + state == other.state && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(country, city, state, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Geolocation{country=$country, city=$city, state=$state, additionalProperties=$additionalProperties}" + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is BrowserbaseProxyConfig && + type == other.type && + domainPattern == other.domainPattern && + geolocation == other.geolocation && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(type, domainPattern, geolocation, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "BrowserbaseProxyConfig{type=$type, domainPattern=$domainPattern, geolocation=$geolocation, additionalProperties=$additionalProperties}" + } + + class ExternalProxyConfig + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val server: JsonField, + private val type: JsonField, + private val domainPattern: JsonField, + private val password: JsonField, + private val username: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("server") + @ExcludeMissing + server: JsonField = JsonMissing.of(), + @JsonProperty("type") + @ExcludeMissing + type: JsonField = JsonMissing.of(), + @JsonProperty("domainPattern") + @ExcludeMissing + domainPattern: JsonField = JsonMissing.of(), + @JsonProperty("password") + @ExcludeMissing + password: JsonField = JsonMissing.of(), + @JsonProperty("username") + @ExcludeMissing + username: JsonField = JsonMissing.of(), + ) : this(server, type, domainPattern, password, username, mutableMapOf()) + + /** + * @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 server(): String = server.getRequired("server") + + /** + * @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 type(): Type = type.getRequired("type") + + /** + * @throws StagehandInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun domainPattern(): Optional = + domainPattern.getOptional("domainPattern") + + /** + * @throws StagehandInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun password(): Optional = password.getOptional("password") + + /** + * @throws StagehandInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun username(): Optional = username.getOptional("username") + + /** + * Returns the raw JSON value of [server]. + * + * Unlike [server], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("server") + @ExcludeMissing + fun _server(): JsonField = server + + /** + * Returns the raw JSON value of [type]. + * + * Unlike [type], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("type") @ExcludeMissing fun _type(): JsonField = type + + /** + * Returns the raw JSON value of [domainPattern]. + * + * Unlike [domainPattern], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("domainPattern") + @ExcludeMissing + fun _domainPattern(): JsonField = domainPattern + + /** + * Returns the raw JSON value of [password]. + * + * Unlike [password], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("password") + @ExcludeMissing + fun _password(): JsonField = password + + /** + * Returns the raw JSON value of [username]. + * + * Unlike [username], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("username") + @ExcludeMissing + fun _username(): JsonField = username + + @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 + * [ExternalProxyConfig]. + * + * The following fields are required: + * ```java + * .server() + * .type() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [ExternalProxyConfig]. */ + class Builder internal constructor() { + + private var server: JsonField? = null + private var type: JsonField? = null + private var domainPattern: JsonField = JsonMissing.of() + private var password: JsonField = JsonMissing.of() + private var username: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = + mutableMapOf() + + @JvmSynthetic + internal fun from(externalProxyConfig: ExternalProxyConfig) = apply { + server = externalProxyConfig.server + type = externalProxyConfig.type + domainPattern = externalProxyConfig.domainPattern + password = externalProxyConfig.password + username = externalProxyConfig.username + additionalProperties = + externalProxyConfig.additionalProperties.toMutableMap() + } + + fun server(server: String) = server(JsonField.of(server)) + + /** + * Sets [Builder.server] to an arbitrary JSON value. + * + * You should usually call [Builder.server] with a well-typed [String] value + * instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun server(server: JsonField) = apply { this.server = server } + + fun type(type: Type) = type(JsonField.of(type)) + + /** + * Sets [Builder.type] to an arbitrary JSON value. + * + * You should usually call [Builder.type] with a well-typed [Type] value + * instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun type(type: JsonField) = apply { this.type = type } + + fun domainPattern(domainPattern: String) = + domainPattern(JsonField.of(domainPattern)) + + /** + * Sets [Builder.domainPattern] to an arbitrary JSON value. + * + * You should usually call [Builder.domainPattern] with a well-typed + * [String] value instead. This method is primarily for setting the field to + * an undocumented or not yet supported value. + */ + fun domainPattern(domainPattern: JsonField) = apply { + this.domainPattern = domainPattern + } + + fun password(password: String) = password(JsonField.of(password)) + + /** + * Sets [Builder.password] to an arbitrary JSON value. + * + * You should usually call [Builder.password] with a well-typed [String] + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun password(password: JsonField) = apply { + this.password = password + } + + fun username(username: String) = username(JsonField.of(username)) + + /** + * Sets [Builder.username] to an arbitrary JSON value. + * + * You should usually call [Builder.username] with a well-typed [String] + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun username(username: JsonField) = apply { + this.username = username + } + + 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 [ExternalProxyConfig]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .server() + * .type() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): ExternalProxyConfig = + ExternalProxyConfig( + checkRequired("server", server), + checkRequired("type", type), + domainPattern, + password, + username, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): ExternalProxyConfig = apply { + if (validated) { + return@apply + } + + server() + type().validate() + domainPattern() + password() + username() + 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. + */ + @JvmSynthetic + internal fun validity(): Int = + (if (server.asKnown().isPresent) 1 else 0) + + (type.asKnown().getOrNull()?.validity() ?: 0) + + (if (domainPattern.asKnown().isPresent) 1 else 0) + + (if (password.asKnown().isPresent) 1 else 0) + + (if (username.asKnown().isPresent) 1 else 0) + + class Type + @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 { + + @JvmField val EXTERNAL = of("external") + + @JvmStatic fun of(value: String) = Type(JsonField.of(value)) + } + + /** An enum containing [Type]'s known values. */ + enum class Known { + EXTERNAL + } + + /** + * An enum containing [Type]'s known values, as well as an [_UNKNOWN] + * member. + * + * An instance of [Type] 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 { + EXTERNAL, + /** + * An enum member indicating that [Type] 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) { + EXTERNAL -> Value.EXTERNAL + 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) { + EXTERNAL -> Known.EXTERNAL + else -> throw StagehandInvalidDataException("Unknown Type: $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().orElseThrow { + StagehandInvalidDataException("Value is not a String") + } + + private var validated: Boolean = false + + fun validate(): Type = 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. + */ + @JvmSynthetic + 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 Type && 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 ExternalProxyConfig && + server == other.server && + type == other.type && + domainPattern == other.domainPattern && + password == other.password && + username == other.username && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash( + server, + type, + domainPattern, + password, + username, + additionalProperties, + ) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "ExternalProxyConfig{server=$server, type=$type, domainPattern=$domainPattern, password=$password, username=$username, additionalProperties=$additionalProperties}" + } + } + } + + class Region @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 { + + @JvmField val US_WEST_2 = of("us-west-2") + + @JvmField val US_EAST_1 = of("us-east-1") + + @JvmField val EU_CENTRAL_1 = of("eu-central-1") + + @JvmField val AP_SOUTHEAST_1 = of("ap-southeast-1") + + @JvmStatic fun of(value: String) = Region(JsonField.of(value)) + } + + /** An enum containing [Region]'s known values. */ + enum class Known { + US_WEST_2, + US_EAST_1, + EU_CENTRAL_1, + AP_SOUTHEAST_1, + } + + /** + * An enum containing [Region]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [Region] 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 { + US_WEST_2, + US_EAST_1, + EU_CENTRAL_1, + AP_SOUTHEAST_1, + /** + * An enum member indicating that [Region] 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) { + US_WEST_2 -> Value.US_WEST_2 + US_EAST_1 -> Value.US_EAST_1 + EU_CENTRAL_1 -> Value.EU_CENTRAL_1 + AP_SOUTHEAST_1 -> Value.AP_SOUTHEAST_1 + 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) { + US_WEST_2 -> Known.US_WEST_2 + US_EAST_1 -> Known.US_EAST_1 + EU_CENTRAL_1 -> Known.EU_CENTRAL_1 + AP_SOUTHEAST_1 -> Known.AP_SOUTHEAST_1 + else -> throw StagehandInvalidDataException("Unknown Region: $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().orElseThrow { + StagehandInvalidDataException("Value is not a String") + } + + private var validated: Boolean = false + + fun validate(): Region = 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. + */ + @JvmSynthetic 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 Region && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + class UserMetadata + @JsonCreator + private constructor( + @com.fasterxml.jackson.annotation.JsonValue + private val additionalProperties: Map + ) { + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = additionalProperties + + fun toBuilder() = Builder().from(this) + + companion object { + + /** Returns a mutable builder for constructing an instance of [UserMetadata]. */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [UserMetadata]. */ + class Builder internal constructor() { + + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(userMetadata: UserMetadata) = apply { + additionalProperties = userMetadata.additionalProperties.toMutableMap() + } + + 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 [UserMetadata]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): UserMetadata = UserMetadata(additionalProperties.toImmutable()) + } + + private var validated: Boolean = false + + fun validate(): UserMetadata = apply { + if (validated) { + return@apply + } + + 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. + */ + @JvmSynthetic + internal fun validity(): Int = + additionalProperties.count { (_, value) -> !value.isNull() && !value.isMissing() } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is UserMetadata && additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { Objects.hash(additionalProperties) } + + override fun hashCode(): Int = hashCode + + override fun toString() = "UserMetadata{additionalProperties=$additionalProperties}" + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is BrowserbaseSessionCreateParams && + browserSettings == other.browserSettings && + extensionId == other.extensionId && + keepAlive == other.keepAlive && + projectId == other.projectId && + proxies == other.proxies && + region == other.region && + timeout == other.timeout && + userMetadata == other.userMetadata && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash( + browserSettings, + extensionId, + keepAlive, + projectId, + proxies, + region, + timeout, + userMetadata, + additionalProperties, + ) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "BrowserbaseSessionCreateParams{browserSettings=$browserSettings, extensionId=$extensionId, keepAlive=$keepAlive, projectId=$projectId, proxies=$proxies, region=$region, timeout=$timeout, userMetadata=$userMetadata, additionalProperties=$additionalProperties}" + } + + /** Logging verbosity level (0=quiet, 1=normal, 2=debug) */ + class Verbose @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 { + + @JvmField val _0 = of(0.0) + + @JvmField val _1 = of(1.0) + + @JvmField val _2 = of(2.0) + + @JvmStatic fun of(value: Double) = Verbose(JsonField.of(value)) + } + + /** An enum containing [Verbose]'s known values. */ + enum class Known { + _0, + _1, + _2, + } + + /** + * An enum containing [Verbose]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [Verbose] 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 { + _0, + _1, + _2, + /** An enum member indicating that [Verbose] 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) { + _0 -> Value._0 + _1 -> Value._1 + _2 -> Value._2 + 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) { + _0 -> Known._0 + _1 -> Known._1 + _2 -> Known._2 + else -> throw StagehandInvalidDataException("Unknown Verbose: $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 asDouble(): Double = + _value().asNumber().getOrNull()?.toDouble() + ?: throw StagehandInvalidDataException("Value is not a Double") + + private var validated: Boolean = false + + fun validate(): Verbose = 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. + */ + @JvmSynthetic 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 Verbose && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + /** Client SDK language */ + class XLanguage @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 { + + @JvmField val TYPESCRIPT = of("typescript") + + @JvmField val PYTHON = of("python") + + @JvmField val PLAYGROUND = of("playground") + + @JvmStatic fun of(value: String) = XLanguage(JsonField.of(value)) + } + + /** An enum containing [XLanguage]'s known values. */ + enum class Known { + TYPESCRIPT, + PYTHON, + PLAYGROUND, + } + + /** + * An enum containing [XLanguage]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [XLanguage] 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 { + TYPESCRIPT, + PYTHON, + PLAYGROUND, + /** + * An enum member indicating that [XLanguage] 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) { + TYPESCRIPT -> Value.TYPESCRIPT + PYTHON -> Value.PYTHON + PLAYGROUND -> Value.PLAYGROUND + 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) { + TYPESCRIPT -> Known.TYPESCRIPT + PYTHON -> Known.PYTHON + PLAYGROUND -> Known.PLAYGROUND + else -> throw StagehandInvalidDataException("Unknown XLanguage: $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().orElseThrow { + StagehandInvalidDataException("Value is not a String") + } + + private var validated: Boolean = false + + fun validate(): XLanguage = 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. + */ + @JvmSynthetic 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 XLanguage && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + /** Whether to stream the response via SSE */ + class XStreamResponse @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 { + + @JvmField val TRUE = of("true") + + @JvmField val FALSE = of("false") + + @JvmStatic fun of(value: String) = XStreamResponse(JsonField.of(value)) + } + + /** An enum containing [XStreamResponse]'s known values. */ + enum class Known { + TRUE, + FALSE, + } + + /** + * An enum containing [XStreamResponse]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [XStreamResponse] 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, + FALSE, + /** + * An enum member indicating that [XStreamResponse] 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 + FALSE -> Value.FALSE + 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 + FALSE -> Known.FALSE + else -> throw StagehandInvalidDataException("Unknown XStreamResponse: $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().orElseThrow { + StagehandInvalidDataException("Value is not a String") + } + + private var validated: Boolean = false + + fun validate(): XStreamResponse = 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. + */ + @JvmSynthetic 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 XStreamResponse && 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-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionStartResponse.kt b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionStartResponse.kt index b63f41e..420925f 100644 --- a/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionStartResponse.kt +++ b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionStartResponse.kt @@ -2,20 +2,60 @@ 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 import com.browserbase.api.core.JsonValue +import com.browserbase.api.core.checkRequired import com.browserbase.api.errors.StagehandInvalidDataException import com.fasterxml.jackson.annotation.JsonAnyGetter import com.fasterxml.jackson.annotation.JsonAnySetter import com.fasterxml.jackson.annotation.JsonCreator +import com.fasterxml.jackson.annotation.JsonProperty import java.util.Collections import java.util.Objects +import kotlin.jvm.optionals.getOrNull class SessionStartResponse @JsonCreator(mode = JsonCreator.Mode.DISABLED) -private constructor(private val additionalProperties: MutableMap) { +private constructor( + private val data: JsonField, + private val success: JsonField, + private val additionalProperties: MutableMap, +) { - @JsonCreator private constructor() : this(mutableMapOf()) + @JsonCreator + private constructor( + @JsonProperty("data") @ExcludeMissing data: JsonField = JsonMissing.of(), + @JsonProperty("success") @ExcludeMissing success: JsonField = JsonMissing.of(), + ) : this(data, success, mutableMapOf()) + + /** + * @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 data(): Data = data.getRequired("data") + + /** + * @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") + + /** + * Returns the raw JSON value of [data]. + * + * Unlike [data], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("data") @ExcludeMissing fun _data(): JsonField = data + + /** + * 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 @JsonAnySetter private fun putAdditionalProperty(key: String, value: JsonValue) { @@ -31,20 +71,52 @@ private constructor(private val additionalProperties: MutableMap? = null + private var success: JsonField? = null private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic internal fun from(sessionStartResponse: SessionStartResponse) = apply { + data = sessionStartResponse.data + success = sessionStartResponse.success additionalProperties = sessionStartResponse.additionalProperties.toMutableMap() } + fun data(data: Data) = data(JsonField.of(data)) + + /** + * Sets [Builder.data] to an arbitrary JSON value. + * + * You should usually call [Builder.data] with a well-typed [Data] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun data(data: JsonField) = apply { this.data = data } + + fun success(success: Success) = 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 + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun success(success: JsonField) = apply { this.success = success } + fun additionalProperties(additionalProperties: Map) = apply { this.additionalProperties.clear() putAllAdditionalProperties(additionalProperties) @@ -68,9 +140,21 @@ private constructor(private val additionalProperties: MutableMap, + private val sessionId: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("available") + @ExcludeMissing + available: JsonField = JsonMissing.of(), + @JsonProperty("sessionId") + @ExcludeMissing + sessionId: JsonField = JsonMissing.of(), + ) : this(available, sessionId, mutableMapOf()) + + /** + * @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 available(): Boolean = available.getRequired("available") + + /** + * Unique session identifier + * + * @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 sessionId(): String = sessionId.getRequired("sessionId") + + /** + * Returns the raw JSON value of [available]. + * + * Unlike [available], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("available") @ExcludeMissing fun _available(): JsonField = available + + /** + * Returns the raw JSON value of [sessionId]. + * + * Unlike [sessionId], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("sessionId") @ExcludeMissing fun _sessionId(): JsonField = sessionId + + @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 [Data]. + * + * The following fields are required: + * ```java + * .available() + * .sessionId() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Data]. */ + class Builder internal constructor() { + + private var available: JsonField? = null + private var sessionId: JsonField? = null + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(data: Data) = apply { + available = data.available + sessionId = data.sessionId + additionalProperties = data.additionalProperties.toMutableMap() + } + + fun available(available: Boolean) = available(JsonField.of(available)) + + /** + * Sets [Builder.available] to an arbitrary JSON value. + * + * You should usually call [Builder.available] with a well-typed [Boolean] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun available(available: JsonField) = apply { this.available = available } + + /** Unique session identifier */ + fun sessionId(sessionId: String) = sessionId(JsonField.of(sessionId)) + + /** + * Sets [Builder.sessionId] to an arbitrary JSON value. + * + * You should usually call [Builder.sessionId] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun sessionId(sessionId: JsonField) = apply { this.sessionId = sessionId } + + 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 [Data]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .available() + * .sessionId() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): Data = + Data( + checkRequired("available", available), + checkRequired("sessionId", sessionId), + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): Data = apply { + if (validated) { + return@apply + } + + available() + sessionId() + 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. + */ + @JvmSynthetic + internal fun validity(): Int = + (if (available.asKnown().isPresent) 1 else 0) + + (if (sessionId.asKnown().isPresent) 1 else 0) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Data && + available == other.available && + sessionId == other.sessionId && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(available, sessionId, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Data{available=$available, sessionId=$sessionId, 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 { + + @JvmField val TRUE = of(true) + + @JvmStatic 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().orElseThrow { + 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. + */ + @JvmSynthetic 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 } - return other is SessionStartResponse && additionalProperties == other.additionalProperties + return other is SessionStartResponse && + data == other.data && + success == other.success && + additionalProperties == other.additionalProperties } - private val hashCode: Int by lazy { Objects.hash(additionalProperties) } + private val hashCode: Int by lazy { Objects.hash(data, success, additionalProperties) } override fun hashCode(): Int = hashCode - override fun toString() = "SessionStartResponse{additionalProperties=$additionalProperties}" + override fun toString() = + "SessionStartResponse{data=$data, success=$success, additionalProperties=$additionalProperties}" } diff --git a/stagehand-java-core/src/main/kotlin/com/browserbase/api/services/async/SessionServiceAsync.kt b/stagehand-java-core/src/main/kotlin/com/browserbase/api/services/async/SessionServiceAsync.kt index 435bf27..423fd57 100644 --- a/stagehand-java-core/src/main/kotlin/com/browserbase/api/services/async/SessionServiceAsync.kt +++ b/stagehand-java-core/src/main/kotlin/com/browserbase/api/services/async/SessionServiceAsync.kt @@ -3,15 +3,14 @@ package com.browserbase.api.services.async import com.browserbase.api.core.ClientOptions -import com.browserbase.api.core.JsonValue import com.browserbase.api.core.RequestOptions import com.browserbase.api.core.http.HttpResponseFor import com.browserbase.api.models.sessions.SessionActParams import com.browserbase.api.models.sessions.SessionActResponse import com.browserbase.api.models.sessions.SessionEndParams import com.browserbase.api.models.sessions.SessionEndResponse -import com.browserbase.api.models.sessions.SessionExecuteAgentParams -import com.browserbase.api.models.sessions.SessionExecuteAgentResponse +import com.browserbase.api.models.sessions.SessionExecuteParams +import com.browserbase.api.models.sessions.SessionExecuteResponse import com.browserbase.api.models.sessions.SessionExtractParams import com.browserbase.api.models.sessions.SessionExtractResponse import com.browserbase.api.models.sessions.SessionNavigateParams @@ -40,21 +39,20 @@ interface SessionServiceAsync { /** * Executes a browser action using natural language instructions or a predefined Action object. */ - fun act(id: JsonValue): CompletableFuture = act(id, SessionActParams.none()) + fun act(id: String, params: SessionActParams): CompletableFuture = + act(id, params, RequestOptions.none()) /** @see act */ fun act( - id: JsonValue, - params: SessionActParams = SessionActParams.none(), + id: String, + params: SessionActParams, requestOptions: RequestOptions = RequestOptions.none(), ): CompletableFuture = act(params.toBuilder().id(id).build(), requestOptions) /** @see act */ - fun act( - id: JsonValue, - params: SessionActParams = SessionActParams.none(), - ): CompletableFuture = act(id, params, RequestOptions.none()) + fun act(params: SessionActParams): CompletableFuture = + act(params, RequestOptions.none()) /** @see act */ fun act( @@ -62,20 +60,12 @@ interface SessionServiceAsync { requestOptions: RequestOptions = RequestOptions.none(), ): CompletableFuture - /** @see act */ - fun act(params: SessionActParams): CompletableFuture = - act(params, RequestOptions.none()) - - /** @see act */ - fun act(id: JsonValue, requestOptions: RequestOptions): CompletableFuture = - act(id, SessionActParams.none(), requestOptions) - /** Terminates the browser session and releases all associated resources. */ - fun end(id: JsonValue): CompletableFuture = end(id, SessionEndParams.none()) + fun end(id: String): CompletableFuture = end(id, SessionEndParams.none()) /** @see end */ fun end( - id: JsonValue, + id: String, params: SessionEndParams = SessionEndParams.none(), requestOptions: RequestOptions = RequestOptions.none(), ): CompletableFuture = @@ -83,7 +73,7 @@ interface SessionServiceAsync { /** @see end */ fun end( - id: JsonValue, + id: String, params: SessionEndParams = SessionEndParams.none(), ): CompletableFuture = end(id, params, RequestOptions.none()) @@ -98,53 +88,40 @@ interface SessionServiceAsync { end(params, RequestOptions.none()) /** @see end */ - fun end(id: JsonValue, requestOptions: RequestOptions): CompletableFuture = + fun end(id: String, requestOptions: RequestOptions): CompletableFuture = end(id, SessionEndParams.none(), requestOptions) /** Runs an autonomous AI agent that can perform complex multi-step browser tasks. */ - fun executeAgent(id: JsonValue): CompletableFuture = - executeAgent(id, SessionExecuteAgentParams.none()) - - /** @see executeAgent */ - fun executeAgent( - id: JsonValue, - params: SessionExecuteAgentParams = SessionExecuteAgentParams.none(), + fun execute( + id: String, + params: SessionExecuteParams, + ): CompletableFuture = execute(id, params, RequestOptions.none()) + + /** @see execute */ + fun execute( + id: String, + params: SessionExecuteParams, requestOptions: RequestOptions = RequestOptions.none(), - ): CompletableFuture = - executeAgent(params.toBuilder().id(id).build(), requestOptions) - - /** @see executeAgent */ - fun executeAgent( - id: JsonValue, - params: SessionExecuteAgentParams = SessionExecuteAgentParams.none(), - ): CompletableFuture = - executeAgent(id, params, RequestOptions.none()) - - /** @see executeAgent */ - fun executeAgent( - params: SessionExecuteAgentParams, - requestOptions: RequestOptions = RequestOptions.none(), - ): CompletableFuture + ): CompletableFuture = + execute(params.toBuilder().id(id).build(), requestOptions) - /** @see executeAgent */ - fun executeAgent( - params: SessionExecuteAgentParams - ): CompletableFuture = executeAgent(params, RequestOptions.none()) + /** @see execute */ + fun execute(params: SessionExecuteParams): CompletableFuture = + execute(params, RequestOptions.none()) - /** @see executeAgent */ - fun executeAgent( - id: JsonValue, - requestOptions: RequestOptions, - ): CompletableFuture = - executeAgent(id, SessionExecuteAgentParams.none(), requestOptions) + /** @see execute */ + fun execute( + params: SessionExecuteParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture /** Extracts structured data from the current page using AI-powered analysis. */ - fun extract(id: JsonValue): CompletableFuture = + fun extract(id: String): CompletableFuture = extract(id, SessionExtractParams.none()) /** @see extract */ fun extract( - id: JsonValue, + id: String, params: SessionExtractParams = SessionExtractParams.none(), requestOptions: RequestOptions = RequestOptions.none(), ): CompletableFuture = @@ -152,7 +129,7 @@ interface SessionServiceAsync { /** @see extract */ fun extract( - id: JsonValue, + id: String, params: SessionExtractParams = SessionExtractParams.none(), ): CompletableFuture = extract(id, params, RequestOptions.none()) @@ -168,34 +145,24 @@ interface SessionServiceAsync { /** @see extract */ fun extract( - id: JsonValue, + id: String, requestOptions: RequestOptions, ): CompletableFuture = extract(id, SessionExtractParams.none(), requestOptions) /** Navigates the browser to the specified URL. */ - fun navigate(id: JsonValue): CompletableFuture = - navigate(id, SessionNavigateParams.none()) - - /** @see navigate */ - fun navigate( - id: JsonValue, - params: SessionNavigateParams = SessionNavigateParams.none(), - requestOptions: RequestOptions = RequestOptions.none(), - ): CompletableFuture = - navigate(params.toBuilder().id(id).build(), requestOptions) - - /** @see navigate */ fun navigate( - id: JsonValue, - params: SessionNavigateParams = SessionNavigateParams.none(), + id: String, + params: SessionNavigateParams, ): CompletableFuture = navigate(id, params, RequestOptions.none()) /** @see navigate */ fun navigate( + id: String, params: SessionNavigateParams, requestOptions: RequestOptions = RequestOptions.none(), - ): CompletableFuture + ): CompletableFuture = + navigate(params.toBuilder().id(id).build(), requestOptions) /** @see navigate */ fun navigate(params: SessionNavigateParams): CompletableFuture = @@ -203,21 +170,20 @@ interface SessionServiceAsync { /** @see navigate */ fun navigate( - id: JsonValue, - requestOptions: RequestOptions, - ): CompletableFuture = - navigate(id, SessionNavigateParams.none(), requestOptions) + params: SessionNavigateParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture /** * Identifies and returns available actions on the current page that match the given * instruction. */ - fun observe(id: JsonValue): CompletableFuture = + fun observe(id: String): CompletableFuture = observe(id, SessionObserveParams.none()) /** @see observe */ fun observe( - id: JsonValue, + id: String, params: SessionObserveParams = SessionObserveParams.none(), requestOptions: RequestOptions = RequestOptions.none(), ): CompletableFuture = @@ -225,7 +191,7 @@ interface SessionServiceAsync { /** @see observe */ fun observe( - id: JsonValue, + id: String, params: SessionObserveParams = SessionObserveParams.none(), ): CompletableFuture = observe(id, params, RequestOptions.none()) @@ -241,7 +207,7 @@ interface SessionServiceAsync { /** @see observe */ fun observe( - id: JsonValue, + id: String, requestOptions: RequestOptions, ): CompletableFuture = observe(id, SessionObserveParams.none(), requestOptions) @@ -250,23 +216,15 @@ interface SessionServiceAsync { * Creates a new browser session with the specified configuration. Returns a session ID used for * all subsequent operations. */ - fun start(): CompletableFuture = start(SessionStartParams.none()) + fun start(params: SessionStartParams): CompletableFuture = + start(params, RequestOptions.none()) /** @see start */ fun start( - params: SessionStartParams = SessionStartParams.none(), + params: SessionStartParams, requestOptions: RequestOptions = RequestOptions.none(), ): CompletableFuture - /** @see start */ - fun start( - params: SessionStartParams = SessionStartParams.none() - ): CompletableFuture = start(params, RequestOptions.none()) - - /** @see start */ - fun start(requestOptions: RequestOptions): CompletableFuture = - start(SessionStartParams.none(), requestOptions) - /** * A view of [SessionServiceAsync] that provides access to raw HTTP responses for each method. */ @@ -282,32 +240,22 @@ interface SessionServiceAsync { ): SessionServiceAsync.WithRawResponse /** - * Returns a raw HTTP response for `post /sessions/{id}/act`, but is otherwise the same as - * [SessionServiceAsync.act]. + * Returns a raw HTTP response for `post /v1/sessions/{id}/act`, but is otherwise the same + * as [SessionServiceAsync.act]. */ - fun act(id: JsonValue): CompletableFuture> = - act(id, SessionActParams.none()) - - /** @see act */ fun act( - id: JsonValue, - params: SessionActParams = SessionActParams.none(), - requestOptions: RequestOptions = RequestOptions.none(), - ): CompletableFuture> = - act(params.toBuilder().id(id).build(), requestOptions) - - /** @see act */ - fun act( - id: JsonValue, - params: SessionActParams = SessionActParams.none(), + id: String, + params: SessionActParams, ): CompletableFuture> = act(id, params, RequestOptions.none()) /** @see act */ fun act( + id: String, params: SessionActParams, requestOptions: RequestOptions = RequestOptions.none(), - ): CompletableFuture> + ): CompletableFuture> = + act(params.toBuilder().id(id).build(), requestOptions) /** @see act */ fun act(params: SessionActParams): CompletableFuture> = @@ -315,21 +263,20 @@ interface SessionServiceAsync { /** @see act */ fun act( - id: JsonValue, - requestOptions: RequestOptions, - ): CompletableFuture> = - act(id, SessionActParams.none(), requestOptions) + params: SessionActParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture> /** - * Returns a raw HTTP response for `post /sessions/{id}/end`, but is otherwise the same as - * [SessionServiceAsync.end]. + * Returns a raw HTTP response for `post /v1/sessions/{id}/end`, but is otherwise the same + * as [SessionServiceAsync.end]. */ - fun end(id: JsonValue): CompletableFuture> = + fun end(id: String): CompletableFuture> = end(id, SessionEndParams.none()) /** @see end */ fun end( - id: JsonValue, + id: String, params: SessionEndParams = SessionEndParams.none(), requestOptions: RequestOptions = RequestOptions.none(), ): CompletableFuture> = @@ -337,7 +284,7 @@ interface SessionServiceAsync { /** @see end */ fun end( - id: JsonValue, + id: String, params: SessionEndParams = SessionEndParams.none(), ): CompletableFuture> = end(id, params, RequestOptions.none()) @@ -354,64 +301,51 @@ interface SessionServiceAsync { /** @see end */ fun end( - id: JsonValue, + id: String, requestOptions: RequestOptions, ): CompletableFuture> = end(id, SessionEndParams.none(), requestOptions) /** - * Returns a raw HTTP response for `post /sessions/{id}/agentExecute`, but is otherwise the - * same as [SessionServiceAsync.executeAgent]. + * Returns a raw HTTP response for `post /v1/sessions/{id}/agentExecute`, but is otherwise + * the same as [SessionServiceAsync.execute]. */ - fun executeAgent( - id: JsonValue - ): CompletableFuture> = - executeAgent(id, SessionExecuteAgentParams.none()) - - /** @see executeAgent */ - fun executeAgent( - id: JsonValue, - params: SessionExecuteAgentParams = SessionExecuteAgentParams.none(), + fun execute( + id: String, + params: SessionExecuteParams, + ): CompletableFuture> = + execute(id, params, RequestOptions.none()) + + /** @see execute */ + fun execute( + id: String, + params: SessionExecuteParams, requestOptions: RequestOptions = RequestOptions.none(), - ): CompletableFuture> = - executeAgent(params.toBuilder().id(id).build(), requestOptions) - - /** @see executeAgent */ - fun executeAgent( - id: JsonValue, - params: SessionExecuteAgentParams = SessionExecuteAgentParams.none(), - ): CompletableFuture> = - executeAgent(id, params, RequestOptions.none()) - - /** @see executeAgent */ - fun executeAgent( - params: SessionExecuteAgentParams, + ): CompletableFuture> = + execute(params.toBuilder().id(id).build(), requestOptions) + + /** @see execute */ + fun execute( + params: SessionExecuteParams + ): CompletableFuture> = + execute(params, RequestOptions.none()) + + /** @see execute */ + fun execute( + params: SessionExecuteParams, requestOptions: RequestOptions = RequestOptions.none(), - ): CompletableFuture> - - /** @see executeAgent */ - fun executeAgent( - params: SessionExecuteAgentParams - ): CompletableFuture> = - executeAgent(params, RequestOptions.none()) - - /** @see executeAgent */ - fun executeAgent( - id: JsonValue, - requestOptions: RequestOptions, - ): CompletableFuture> = - executeAgent(id, SessionExecuteAgentParams.none(), requestOptions) + ): CompletableFuture> /** - * Returns a raw HTTP response for `post /sessions/{id}/extract`, but is otherwise the same - * as [SessionServiceAsync.extract]. + * Returns a raw HTTP response for `post /v1/sessions/{id}/extract`, but is otherwise the + * same as [SessionServiceAsync.extract]. */ - fun extract(id: JsonValue): CompletableFuture> = + fun extract(id: String): CompletableFuture> = extract(id, SessionExtractParams.none()) /** @see extract */ fun extract( - id: JsonValue, + id: String, params: SessionExtractParams = SessionExtractParams.none(), requestOptions: RequestOptions = RequestOptions.none(), ): CompletableFuture> = @@ -419,7 +353,7 @@ interface SessionServiceAsync { /** @see extract */ fun extract( - id: JsonValue, + id: String, params: SessionExtractParams = SessionExtractParams.none(), ): CompletableFuture> = extract(id, params, RequestOptions.none()) @@ -438,38 +372,28 @@ interface SessionServiceAsync { /** @see extract */ fun extract( - id: JsonValue, + id: String, requestOptions: RequestOptions, ): CompletableFuture> = extract(id, SessionExtractParams.none(), requestOptions) /** - * Returns a raw HTTP response for `post /sessions/{id}/navigate`, but is otherwise the same - * as [SessionServiceAsync.navigate]. + * Returns a raw HTTP response for `post /v1/sessions/{id}/navigate`, but is otherwise the + * same as [SessionServiceAsync.navigate]. */ - fun navigate(id: JsonValue): CompletableFuture> = - navigate(id, SessionNavigateParams.none()) - - /** @see navigate */ fun navigate( - id: JsonValue, - params: SessionNavigateParams = SessionNavigateParams.none(), - requestOptions: RequestOptions = RequestOptions.none(), - ): CompletableFuture> = - navigate(params.toBuilder().id(id).build(), requestOptions) - - /** @see navigate */ - fun navigate( - id: JsonValue, - params: SessionNavigateParams = SessionNavigateParams.none(), + id: String, + params: SessionNavigateParams, ): CompletableFuture> = navigate(id, params, RequestOptions.none()) /** @see navigate */ fun navigate( + id: String, params: SessionNavigateParams, requestOptions: RequestOptions = RequestOptions.none(), - ): CompletableFuture> + ): CompletableFuture> = + navigate(params.toBuilder().id(id).build(), requestOptions) /** @see navigate */ fun navigate( @@ -479,21 +403,20 @@ interface SessionServiceAsync { /** @see navigate */ fun navigate( - id: JsonValue, - requestOptions: RequestOptions, - ): CompletableFuture> = - navigate(id, SessionNavigateParams.none(), requestOptions) + params: SessionNavigateParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture> /** - * Returns a raw HTTP response for `post /sessions/{id}/observe`, but is otherwise the same - * as [SessionServiceAsync.observe]. + * Returns a raw HTTP response for `post /v1/sessions/{id}/observe`, but is otherwise the + * same as [SessionServiceAsync.observe]. */ - fun observe(id: JsonValue): CompletableFuture> = + fun observe(id: String): CompletableFuture> = observe(id, SessionObserveParams.none()) /** @see observe */ fun observe( - id: JsonValue, + id: String, params: SessionObserveParams = SessionObserveParams.none(), requestOptions: RequestOptions = RequestOptions.none(), ): CompletableFuture> = @@ -501,7 +424,7 @@ interface SessionServiceAsync { /** @see observe */ fun observe( - id: JsonValue, + id: String, params: SessionObserveParams = SessionObserveParams.none(), ): CompletableFuture> = observe(id, params, RequestOptions.none()) @@ -520,34 +443,24 @@ interface SessionServiceAsync { /** @see observe */ fun observe( - id: JsonValue, + id: String, requestOptions: RequestOptions, ): CompletableFuture> = observe(id, SessionObserveParams.none(), requestOptions) /** - * Returns a raw HTTP response for `post /sessions/start`, but is otherwise the same as + * Returns a raw HTTP response for `post /v1/sessions/start`, but is otherwise the same as * [SessionServiceAsync.start]. */ - fun start(): CompletableFuture> = - start(SessionStartParams.none()) - - /** @see start */ - fun start( - params: SessionStartParams = SessionStartParams.none(), - requestOptions: RequestOptions = RequestOptions.none(), - ): CompletableFuture> - - /** @see start */ fun start( - params: SessionStartParams = SessionStartParams.none() + params: SessionStartParams ): CompletableFuture> = start(params, RequestOptions.none()) /** @see start */ fun start( - requestOptions: RequestOptions - ): CompletableFuture> = - start(SessionStartParams.none(), requestOptions) + params: SessionStartParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture> } } diff --git a/stagehand-java-core/src/main/kotlin/com/browserbase/api/services/async/SessionServiceAsyncImpl.kt b/stagehand-java-core/src/main/kotlin/com/browserbase/api/services/async/SessionServiceAsyncImpl.kt index 7746896..99037bc 100644 --- a/stagehand-java-core/src/main/kotlin/com/browserbase/api/services/async/SessionServiceAsyncImpl.kt +++ b/stagehand-java-core/src/main/kotlin/com/browserbase/api/services/async/SessionServiceAsyncImpl.kt @@ -4,6 +4,7 @@ package com.browserbase.api.services.async import com.browserbase.api.core.ClientOptions import com.browserbase.api.core.RequestOptions +import com.browserbase.api.core.checkRequired import com.browserbase.api.core.handlers.errorBodyHandler import com.browserbase.api.core.handlers.errorHandler import com.browserbase.api.core.handlers.jsonHandler @@ -19,8 +20,8 @@ import com.browserbase.api.models.sessions.SessionActParams import com.browserbase.api.models.sessions.SessionActResponse import com.browserbase.api.models.sessions.SessionEndParams import com.browserbase.api.models.sessions.SessionEndResponse -import com.browserbase.api.models.sessions.SessionExecuteAgentParams -import com.browserbase.api.models.sessions.SessionExecuteAgentResponse +import com.browserbase.api.models.sessions.SessionExecuteParams +import com.browserbase.api.models.sessions.SessionExecuteResponse import com.browserbase.api.models.sessions.SessionExtractParams import com.browserbase.api.models.sessions.SessionExtractResponse import com.browserbase.api.models.sessions.SessionNavigateParams @@ -31,6 +32,7 @@ import com.browserbase.api.models.sessions.SessionStartParams import com.browserbase.api.models.sessions.SessionStartResponse import java.util.concurrent.CompletableFuture import java.util.function.Consumer +import kotlin.jvm.optionals.getOrNull class SessionServiceAsyncImpl internal constructor(private val clientOptions: ClientOptions) : SessionServiceAsync { @@ -48,49 +50,49 @@ class SessionServiceAsyncImpl internal constructor(private val clientOptions: Cl params: SessionActParams, requestOptions: RequestOptions, ): CompletableFuture = - // post /sessions/{id}/act + // post /v1/sessions/{id}/act withRawResponse().act(params, requestOptions).thenApply { it.parse() } override fun end( params: SessionEndParams, requestOptions: RequestOptions, ): CompletableFuture = - // post /sessions/{id}/end + // post /v1/sessions/{id}/end withRawResponse().end(params, requestOptions).thenApply { it.parse() } - override fun executeAgent( - params: SessionExecuteAgentParams, + override fun execute( + params: SessionExecuteParams, requestOptions: RequestOptions, - ): CompletableFuture = - // post /sessions/{id}/agentExecute - withRawResponse().executeAgent(params, requestOptions).thenApply { it.parse() } + ): CompletableFuture = + // post /v1/sessions/{id}/agentExecute + withRawResponse().execute(params, requestOptions).thenApply { it.parse() } override fun extract( params: SessionExtractParams, requestOptions: RequestOptions, ): CompletableFuture = - // post /sessions/{id}/extract + // post /v1/sessions/{id}/extract withRawResponse().extract(params, requestOptions).thenApply { it.parse() } override fun navigate( params: SessionNavigateParams, requestOptions: RequestOptions, ): CompletableFuture = - // post /sessions/{id}/navigate + // post /v1/sessions/{id}/navigate withRawResponse().navigate(params, requestOptions).thenApply { it.parse() } override fun observe( params: SessionObserveParams, requestOptions: RequestOptions, ): CompletableFuture = - // post /sessions/{id}/observe + // post /v1/sessions/{id}/observe withRawResponse().observe(params, requestOptions).thenApply { it.parse() } override fun start( params: SessionStartParams, requestOptions: RequestOptions, ): CompletableFuture = - // post /sessions/start + // post /v1/sessions/start withRawResponse().start(params, requestOptions).thenApply { it.parse() } class WithRawResponseImpl internal constructor(private val clientOptions: ClientOptions) : @@ -113,11 +115,14 @@ class SessionServiceAsyncImpl internal constructor(private val clientOptions: Cl params: SessionActParams, requestOptions: RequestOptions, ): CompletableFuture> { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("id", params.id().getOrNull()) val request = HttpRequest.builder() .method(HttpMethod.POST) .baseUrl(clientOptions.baseUrl()) - .addPathSegments("sessions", params._pathParam(0), "act") + .addPathSegments("v1", "sessions", params._pathParam(0), "act") .body(json(clientOptions.jsonMapper, params._body())) .build() .prepareAsync(clientOptions, params) @@ -144,11 +149,14 @@ class SessionServiceAsyncImpl internal constructor(private val clientOptions: Cl params: SessionEndParams, requestOptions: RequestOptions, ): CompletableFuture> { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("id", params.id().getOrNull()) val request = HttpRequest.builder() .method(HttpMethod.POST) .baseUrl(clientOptions.baseUrl()) - .addPathSegments("sessions", params._pathParam(0), "end") + .addPathSegments("v1", "sessions", params._pathParam(0), "end") .apply { params._body().ifPresent { body(json(clientOptions.jsonMapper, it)) } } .build() .prepareAsync(clientOptions, params) @@ -168,18 +176,21 @@ class SessionServiceAsyncImpl internal constructor(private val clientOptions: Cl } } - private val executeAgentHandler: Handler = - jsonHandler(clientOptions.jsonMapper) + private val executeHandler: Handler = + jsonHandler(clientOptions.jsonMapper) - override fun executeAgent( - params: SessionExecuteAgentParams, + override fun execute( + params: SessionExecuteParams, requestOptions: RequestOptions, - ): CompletableFuture> { + ): CompletableFuture> { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("id", params.id().getOrNull()) val request = HttpRequest.builder() .method(HttpMethod.POST) .baseUrl(clientOptions.baseUrl()) - .addPathSegments("sessions", params._pathParam(0), "agentExecute") + .addPathSegments("v1", "sessions", params._pathParam(0), "agentExecute") .body(json(clientOptions.jsonMapper, params._body())) .build() .prepareAsync(clientOptions, params) @@ -189,7 +200,7 @@ class SessionServiceAsyncImpl internal constructor(private val clientOptions: Cl .thenApply { response -> errorHandler.handle(response).parseable { response - .use { executeAgentHandler.handle(it) } + .use { executeHandler.handle(it) } .also { if (requestOptions.responseValidation!!) { it.validate() @@ -206,11 +217,14 @@ class SessionServiceAsyncImpl internal constructor(private val clientOptions: Cl params: SessionExtractParams, requestOptions: RequestOptions, ): CompletableFuture> { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("id", params.id().getOrNull()) val request = HttpRequest.builder() .method(HttpMethod.POST) .baseUrl(clientOptions.baseUrl()) - .addPathSegments("sessions", params._pathParam(0), "extract") + .addPathSegments("v1", "sessions", params._pathParam(0), "extract") .body(json(clientOptions.jsonMapper, params._body())) .build() .prepareAsync(clientOptions, params) @@ -237,11 +251,14 @@ class SessionServiceAsyncImpl internal constructor(private val clientOptions: Cl params: SessionNavigateParams, requestOptions: RequestOptions, ): CompletableFuture> { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("id", params.id().getOrNull()) val request = HttpRequest.builder() .method(HttpMethod.POST) .baseUrl(clientOptions.baseUrl()) - .addPathSegments("sessions", params._pathParam(0), "navigate") + .addPathSegments("v1", "sessions", params._pathParam(0), "navigate") .body(json(clientOptions.jsonMapper, params._body())) .build() .prepareAsync(clientOptions, params) @@ -268,11 +285,14 @@ class SessionServiceAsyncImpl internal constructor(private val clientOptions: Cl params: SessionObserveParams, requestOptions: RequestOptions, ): CompletableFuture> { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("id", params.id().getOrNull()) val request = HttpRequest.builder() .method(HttpMethod.POST) .baseUrl(clientOptions.baseUrl()) - .addPathSegments("sessions", params._pathParam(0), "observe") + .addPathSegments("v1", "sessions", params._pathParam(0), "observe") .body(json(clientOptions.jsonMapper, params._body())) .build() .prepareAsync(clientOptions, params) @@ -303,7 +323,7 @@ class SessionServiceAsyncImpl internal constructor(private val clientOptions: Cl HttpRequest.builder() .method(HttpMethod.POST) .baseUrl(clientOptions.baseUrl()) - .addPathSegments("sessions", "start") + .addPathSegments("v1", "sessions", "start") .body(json(clientOptions.jsonMapper, params._body())) .build() .prepareAsync(clientOptions, params) diff --git a/stagehand-java-core/src/main/kotlin/com/browserbase/api/services/blocking/SessionService.kt b/stagehand-java-core/src/main/kotlin/com/browserbase/api/services/blocking/SessionService.kt index f29cc14..df7bb72 100644 --- a/stagehand-java-core/src/main/kotlin/com/browserbase/api/services/blocking/SessionService.kt +++ b/stagehand-java-core/src/main/kotlin/com/browserbase/api/services/blocking/SessionService.kt @@ -3,15 +3,14 @@ package com.browserbase.api.services.blocking import com.browserbase.api.core.ClientOptions -import com.browserbase.api.core.JsonValue import com.browserbase.api.core.RequestOptions import com.browserbase.api.core.http.HttpResponseFor import com.browserbase.api.models.sessions.SessionActParams import com.browserbase.api.models.sessions.SessionActResponse import com.browserbase.api.models.sessions.SessionEndParams import com.browserbase.api.models.sessions.SessionEndResponse -import com.browserbase.api.models.sessions.SessionExecuteAgentParams -import com.browserbase.api.models.sessions.SessionExecuteAgentResponse +import com.browserbase.api.models.sessions.SessionExecuteParams +import com.browserbase.api.models.sessions.SessionExecuteResponse import com.browserbase.api.models.sessions.SessionExtractParams import com.browserbase.api.models.sessions.SessionExtractResponse import com.browserbase.api.models.sessions.SessionNavigateParams @@ -40,18 +39,18 @@ interface SessionService { /** * Executes a browser action using natural language instructions or a predefined Action object. */ - fun act(id: JsonValue): SessionActResponse = act(id, SessionActParams.none()) + fun act(id: String, params: SessionActParams): SessionActResponse = + act(id, params, RequestOptions.none()) /** @see act */ fun act( - id: JsonValue, - params: SessionActParams = SessionActParams.none(), + id: String, + params: SessionActParams, requestOptions: RequestOptions = RequestOptions.none(), ): SessionActResponse = act(params.toBuilder().id(id).build(), requestOptions) /** @see act */ - fun act(id: JsonValue, params: SessionActParams = SessionActParams.none()): SessionActResponse = - act(id, params, RequestOptions.none()) + fun act(params: SessionActParams): SessionActResponse = act(params, RequestOptions.none()) /** @see act */ fun act( @@ -59,25 +58,18 @@ interface SessionService { requestOptions: RequestOptions = RequestOptions.none(), ): SessionActResponse - /** @see act */ - fun act(params: SessionActParams): SessionActResponse = act(params, RequestOptions.none()) - - /** @see act */ - fun act(id: JsonValue, requestOptions: RequestOptions): SessionActResponse = - act(id, SessionActParams.none(), requestOptions) - /** Terminates the browser session and releases all associated resources. */ - fun end(id: JsonValue): SessionEndResponse = end(id, SessionEndParams.none()) + fun end(id: String): SessionEndResponse = end(id, SessionEndParams.none()) /** @see end */ fun end( - id: JsonValue, + id: String, params: SessionEndParams = SessionEndParams.none(), requestOptions: RequestOptions = RequestOptions.none(), ): SessionEndResponse = end(params.toBuilder().id(id).build(), requestOptions) /** @see end */ - fun end(id: JsonValue, params: SessionEndParams = SessionEndParams.none()): SessionEndResponse = + fun end(id: String, params: SessionEndParams = SessionEndParams.none()): SessionEndResponse = end(id, params, RequestOptions.none()) /** @see end */ @@ -90,53 +82,43 @@ interface SessionService { fun end(params: SessionEndParams): SessionEndResponse = end(params, RequestOptions.none()) /** @see end */ - fun end(id: JsonValue, requestOptions: RequestOptions): SessionEndResponse = + fun end(id: String, requestOptions: RequestOptions): SessionEndResponse = end(id, SessionEndParams.none(), requestOptions) /** Runs an autonomous AI agent that can perform complex multi-step browser tasks. */ - fun executeAgent(id: JsonValue): SessionExecuteAgentResponse = - executeAgent(id, SessionExecuteAgentParams.none()) + fun execute(id: String, params: SessionExecuteParams): SessionExecuteResponse = + execute(id, params, RequestOptions.none()) - /** @see executeAgent */ - fun executeAgent( - id: JsonValue, - params: SessionExecuteAgentParams = SessionExecuteAgentParams.none(), + /** @see execute */ + fun execute( + id: String, + params: SessionExecuteParams, requestOptions: RequestOptions = RequestOptions.none(), - ): SessionExecuteAgentResponse = executeAgent(params.toBuilder().id(id).build(), requestOptions) + ): SessionExecuteResponse = execute(params.toBuilder().id(id).build(), requestOptions) - /** @see executeAgent */ - fun executeAgent( - id: JsonValue, - params: SessionExecuteAgentParams = SessionExecuteAgentParams.none(), - ): SessionExecuteAgentResponse = executeAgent(id, params, RequestOptions.none()) + /** @see execute */ + fun execute(params: SessionExecuteParams): SessionExecuteResponse = + execute(params, RequestOptions.none()) - /** @see executeAgent */ - fun executeAgent( - params: SessionExecuteAgentParams, + /** @see execute */ + fun execute( + params: SessionExecuteParams, requestOptions: RequestOptions = RequestOptions.none(), - ): SessionExecuteAgentResponse - - /** @see executeAgent */ - fun executeAgent(params: SessionExecuteAgentParams): SessionExecuteAgentResponse = - executeAgent(params, RequestOptions.none()) - - /** @see executeAgent */ - fun executeAgent(id: JsonValue, requestOptions: RequestOptions): SessionExecuteAgentResponse = - executeAgent(id, SessionExecuteAgentParams.none(), requestOptions) + ): SessionExecuteResponse /** Extracts structured data from the current page using AI-powered analysis. */ - fun extract(id: JsonValue): SessionExtractResponse = extract(id, SessionExtractParams.none()) + fun extract(id: String): SessionExtractResponse = extract(id, SessionExtractParams.none()) /** @see extract */ fun extract( - id: JsonValue, + id: String, params: SessionExtractParams = SessionExtractParams.none(), requestOptions: RequestOptions = RequestOptions.none(), ): SessionExtractResponse = extract(params.toBuilder().id(id).build(), requestOptions) /** @see extract */ fun extract( - id: JsonValue, + id: String, params: SessionExtractParams = SessionExtractParams.none(), ): SessionExtractResponse = extract(id, params, RequestOptions.none()) @@ -151,25 +133,23 @@ interface SessionService { extract(params, RequestOptions.none()) /** @see extract */ - fun extract(id: JsonValue, requestOptions: RequestOptions): SessionExtractResponse = + fun extract(id: String, requestOptions: RequestOptions): SessionExtractResponse = extract(id, SessionExtractParams.none(), requestOptions) /** Navigates the browser to the specified URL. */ - fun navigate(id: JsonValue): SessionNavigateResponse = - navigate(id, SessionNavigateParams.none()) + fun navigate(id: String, params: SessionNavigateParams): SessionNavigateResponse = + navigate(id, params, RequestOptions.none()) /** @see navigate */ fun navigate( - id: JsonValue, - params: SessionNavigateParams = SessionNavigateParams.none(), + id: String, + params: SessionNavigateParams, requestOptions: RequestOptions = RequestOptions.none(), ): SessionNavigateResponse = navigate(params.toBuilder().id(id).build(), requestOptions) /** @see navigate */ - fun navigate( - id: JsonValue, - params: SessionNavigateParams = SessionNavigateParams.none(), - ): SessionNavigateResponse = navigate(id, params, RequestOptions.none()) + fun navigate(params: SessionNavigateParams): SessionNavigateResponse = + navigate(params, RequestOptions.none()) /** @see navigate */ fun navigate( @@ -177,30 +157,22 @@ interface SessionService { requestOptions: RequestOptions = RequestOptions.none(), ): SessionNavigateResponse - /** @see navigate */ - fun navigate(params: SessionNavigateParams): SessionNavigateResponse = - navigate(params, RequestOptions.none()) - - /** @see navigate */ - fun navigate(id: JsonValue, requestOptions: RequestOptions): SessionNavigateResponse = - navigate(id, SessionNavigateParams.none(), requestOptions) - /** * Identifies and returns available actions on the current page that match the given * instruction. */ - fun observe(id: JsonValue): SessionObserveResponse = observe(id, SessionObserveParams.none()) + fun observe(id: String): SessionObserveResponse = observe(id, SessionObserveParams.none()) /** @see observe */ fun observe( - id: JsonValue, + id: String, params: SessionObserveParams = SessionObserveParams.none(), requestOptions: RequestOptions = RequestOptions.none(), ): SessionObserveResponse = observe(params.toBuilder().id(id).build(), requestOptions) /** @see observe */ fun observe( - id: JsonValue, + id: String, params: SessionObserveParams = SessionObserveParams.none(), ): SessionObserveResponse = observe(id, params, RequestOptions.none()) @@ -215,29 +187,22 @@ interface SessionService { observe(params, RequestOptions.none()) /** @see observe */ - fun observe(id: JsonValue, requestOptions: RequestOptions): SessionObserveResponse = + fun observe(id: String, requestOptions: RequestOptions): SessionObserveResponse = observe(id, SessionObserveParams.none(), requestOptions) /** * Creates a new browser session with the specified configuration. Returns a session ID used for * all subsequent operations. */ - fun start(): SessionStartResponse = start(SessionStartParams.none()) + fun start(params: SessionStartParams): SessionStartResponse = + start(params, RequestOptions.none()) /** @see start */ fun start( - params: SessionStartParams = SessionStartParams.none(), + params: SessionStartParams, requestOptions: RequestOptions = RequestOptions.none(), ): SessionStartResponse - /** @see start */ - fun start(params: SessionStartParams = SessionStartParams.none()): SessionStartResponse = - start(params, RequestOptions.none()) - - /** @see start */ - fun start(requestOptions: RequestOptions): SessionStartResponse = - start(SessionStartParams.none(), requestOptions) - /** A view of [SessionService] that provides access to raw HTTP responses for each method. */ interface WithRawResponse { @@ -249,28 +214,26 @@ interface SessionService { fun withOptions(modifier: Consumer): SessionService.WithRawResponse /** - * Returns a raw HTTP response for `post /sessions/{id}/act`, but is otherwise the same as - * [SessionService.act]. + * Returns a raw HTTP response for `post /v1/sessions/{id}/act`, but is otherwise the same + * as [SessionService.act]. */ @MustBeClosed - fun act(id: JsonValue): HttpResponseFor = - act(id, SessionActParams.none()) + fun act(id: String, params: SessionActParams): HttpResponseFor = + act(id, params, RequestOptions.none()) /** @see act */ @MustBeClosed fun act( - id: JsonValue, - params: SessionActParams = SessionActParams.none(), + id: String, + params: SessionActParams, requestOptions: RequestOptions = RequestOptions.none(), ): HttpResponseFor = act(params.toBuilder().id(id).build(), requestOptions) /** @see act */ @MustBeClosed - fun act( - id: JsonValue, - params: SessionActParams = SessionActParams.none(), - ): HttpResponseFor = act(id, params, RequestOptions.none()) + fun act(params: SessionActParams): HttpResponseFor = + act(params, RequestOptions.none()) /** @see act */ @MustBeClosed @@ -279,30 +242,17 @@ interface SessionService { requestOptions: RequestOptions = RequestOptions.none(), ): HttpResponseFor - /** @see act */ - @MustBeClosed - fun act(params: SessionActParams): HttpResponseFor = - act(params, RequestOptions.none()) - - /** @see act */ - @MustBeClosed - fun act( - id: JsonValue, - requestOptions: RequestOptions, - ): HttpResponseFor = act(id, SessionActParams.none(), requestOptions) - /** - * Returns a raw HTTP response for `post /sessions/{id}/end`, but is otherwise the same as - * [SessionService.end]. + * Returns a raw HTTP response for `post /v1/sessions/{id}/end`, but is otherwise the same + * as [SessionService.end]. */ @MustBeClosed - fun end(id: JsonValue): HttpResponseFor = - end(id, SessionEndParams.none()) + fun end(id: String): HttpResponseFor = end(id, SessionEndParams.none()) /** @see end */ @MustBeClosed fun end( - id: JsonValue, + id: String, params: SessionEndParams = SessionEndParams.none(), requestOptions: RequestOptions = RequestOptions.none(), ): HttpResponseFor = @@ -311,7 +261,7 @@ interface SessionService { /** @see end */ @MustBeClosed fun end( - id: JsonValue, + id: String, params: SessionEndParams = SessionEndParams.none(), ): HttpResponseFor = end(id, params, RequestOptions.none()) @@ -329,70 +279,52 @@ interface SessionService { /** @see end */ @MustBeClosed - fun end( - id: JsonValue, - requestOptions: RequestOptions, - ): HttpResponseFor = end(id, SessionEndParams.none(), requestOptions) + fun end(id: String, requestOptions: RequestOptions): HttpResponseFor = + end(id, SessionEndParams.none(), requestOptions) /** - * Returns a raw HTTP response for `post /sessions/{id}/agentExecute`, but is otherwise the - * same as [SessionService.executeAgent]. + * Returns a raw HTTP response for `post /v1/sessions/{id}/agentExecute`, but is otherwise + * the same as [SessionService.execute]. */ @MustBeClosed - fun executeAgent(id: JsonValue): HttpResponseFor = - executeAgent(id, SessionExecuteAgentParams.none()) + fun execute( + id: String, + params: SessionExecuteParams, + ): HttpResponseFor = execute(id, params, RequestOptions.none()) - /** @see executeAgent */ + /** @see execute */ @MustBeClosed - fun executeAgent( - id: JsonValue, - params: SessionExecuteAgentParams = SessionExecuteAgentParams.none(), + fun execute( + id: String, + params: SessionExecuteParams, requestOptions: RequestOptions = RequestOptions.none(), - ): HttpResponseFor = - executeAgent(params.toBuilder().id(id).build(), requestOptions) + ): HttpResponseFor = + execute(params.toBuilder().id(id).build(), requestOptions) - /** @see executeAgent */ + /** @see execute */ @MustBeClosed - fun executeAgent( - id: JsonValue, - params: SessionExecuteAgentParams = SessionExecuteAgentParams.none(), - ): HttpResponseFor = - executeAgent(id, params, RequestOptions.none()) + fun execute(params: SessionExecuteParams): HttpResponseFor = + execute(params, RequestOptions.none()) - /** @see executeAgent */ + /** @see execute */ @MustBeClosed - fun executeAgent( - params: SessionExecuteAgentParams, + fun execute( + params: SessionExecuteParams, requestOptions: RequestOptions = RequestOptions.none(), - ): HttpResponseFor - - /** @see executeAgent */ - @MustBeClosed - fun executeAgent( - params: SessionExecuteAgentParams - ): HttpResponseFor = - executeAgent(params, RequestOptions.none()) - - /** @see executeAgent */ - @MustBeClosed - fun executeAgent( - id: JsonValue, - requestOptions: RequestOptions, - ): HttpResponseFor = - executeAgent(id, SessionExecuteAgentParams.none(), requestOptions) + ): HttpResponseFor /** - * Returns a raw HTTP response for `post /sessions/{id}/extract`, but is otherwise the same - * as [SessionService.extract]. + * Returns a raw HTTP response for `post /v1/sessions/{id}/extract`, but is otherwise the + * same as [SessionService.extract]. */ @MustBeClosed - fun extract(id: JsonValue): HttpResponseFor = + fun extract(id: String): HttpResponseFor = extract(id, SessionExtractParams.none()) /** @see extract */ @MustBeClosed fun extract( - id: JsonValue, + id: String, params: SessionExtractParams = SessionExtractParams.none(), requestOptions: RequestOptions = RequestOptions.none(), ): HttpResponseFor = @@ -401,7 +333,7 @@ interface SessionService { /** @see extract */ @MustBeClosed fun extract( - id: JsonValue, + id: String, params: SessionExtractParams = SessionExtractParams.none(), ): HttpResponseFor = extract(id, params, RequestOptions.none()) @@ -420,41 +352,29 @@ interface SessionService { /** @see extract */ @MustBeClosed fun extract( - id: JsonValue, + id: String, requestOptions: RequestOptions, ): HttpResponseFor = extract(id, SessionExtractParams.none(), requestOptions) /** - * Returns a raw HTTP response for `post /sessions/{id}/navigate`, but is otherwise the same - * as [SessionService.navigate]. + * Returns a raw HTTP response for `post /v1/sessions/{id}/navigate`, but is otherwise the + * same as [SessionService.navigate]. */ @MustBeClosed - fun navigate(id: JsonValue): HttpResponseFor = - navigate(id, SessionNavigateParams.none()) - - /** @see navigate */ - @MustBeClosed fun navigate( - id: JsonValue, - params: SessionNavigateParams = SessionNavigateParams.none(), - requestOptions: RequestOptions = RequestOptions.none(), - ): HttpResponseFor = - navigate(params.toBuilder().id(id).build(), requestOptions) - - /** @see navigate */ - @MustBeClosed - fun navigate( - id: JsonValue, - params: SessionNavigateParams = SessionNavigateParams.none(), + id: String, + params: SessionNavigateParams, ): HttpResponseFor = navigate(id, params, RequestOptions.none()) /** @see navigate */ @MustBeClosed fun navigate( + id: String, params: SessionNavigateParams, requestOptions: RequestOptions = RequestOptions.none(), - ): HttpResponseFor + ): HttpResponseFor = + navigate(params.toBuilder().id(id).build(), requestOptions) /** @see navigate */ @MustBeClosed @@ -464,23 +384,22 @@ interface SessionService { /** @see navigate */ @MustBeClosed fun navigate( - id: JsonValue, - requestOptions: RequestOptions, - ): HttpResponseFor = - navigate(id, SessionNavigateParams.none(), requestOptions) + params: SessionNavigateParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor /** - * Returns a raw HTTP response for `post /sessions/{id}/observe`, but is otherwise the same - * as [SessionService.observe]. + * Returns a raw HTTP response for `post /v1/sessions/{id}/observe`, but is otherwise the + * same as [SessionService.observe]. */ @MustBeClosed - fun observe(id: JsonValue): HttpResponseFor = + fun observe(id: String): HttpResponseFor = observe(id, SessionObserveParams.none()) /** @see observe */ @MustBeClosed fun observe( - id: JsonValue, + id: String, params: SessionObserveParams = SessionObserveParams.none(), requestOptions: RequestOptions = RequestOptions.none(), ): HttpResponseFor = @@ -489,7 +408,7 @@ interface SessionService { /** @see observe */ @MustBeClosed fun observe( - id: JsonValue, + id: String, params: SessionObserveParams = SessionObserveParams.none(), ): HttpResponseFor = observe(id, params, RequestOptions.none()) @@ -508,34 +427,24 @@ interface SessionService { /** @see observe */ @MustBeClosed fun observe( - id: JsonValue, + id: String, requestOptions: RequestOptions, ): HttpResponseFor = observe(id, SessionObserveParams.none(), requestOptions) /** - * Returns a raw HTTP response for `post /sessions/start`, but is otherwise the same as + * Returns a raw HTTP response for `post /v1/sessions/start`, but is otherwise the same as * [SessionService.start]. */ @MustBeClosed - fun start(): HttpResponseFor = start(SessionStartParams.none()) + fun start(params: SessionStartParams): HttpResponseFor = + start(params, RequestOptions.none()) /** @see start */ @MustBeClosed fun start( - params: SessionStartParams = SessionStartParams.none(), + params: SessionStartParams, requestOptions: RequestOptions = RequestOptions.none(), ): HttpResponseFor - - /** @see start */ - @MustBeClosed - fun start( - params: SessionStartParams = SessionStartParams.none() - ): HttpResponseFor = start(params, RequestOptions.none()) - - /** @see start */ - @MustBeClosed - fun start(requestOptions: RequestOptions): HttpResponseFor = - start(SessionStartParams.none(), requestOptions) } } diff --git a/stagehand-java-core/src/main/kotlin/com/browserbase/api/services/blocking/SessionServiceImpl.kt b/stagehand-java-core/src/main/kotlin/com/browserbase/api/services/blocking/SessionServiceImpl.kt index 467e9db..aac8272 100644 --- a/stagehand-java-core/src/main/kotlin/com/browserbase/api/services/blocking/SessionServiceImpl.kt +++ b/stagehand-java-core/src/main/kotlin/com/browserbase/api/services/blocking/SessionServiceImpl.kt @@ -4,6 +4,7 @@ package com.browserbase.api.services.blocking import com.browserbase.api.core.ClientOptions import com.browserbase.api.core.RequestOptions +import com.browserbase.api.core.checkRequired import com.browserbase.api.core.handlers.errorBodyHandler import com.browserbase.api.core.handlers.errorHandler import com.browserbase.api.core.handlers.jsonHandler @@ -19,8 +20,8 @@ import com.browserbase.api.models.sessions.SessionActParams import com.browserbase.api.models.sessions.SessionActResponse import com.browserbase.api.models.sessions.SessionEndParams import com.browserbase.api.models.sessions.SessionEndResponse -import com.browserbase.api.models.sessions.SessionExecuteAgentParams -import com.browserbase.api.models.sessions.SessionExecuteAgentResponse +import com.browserbase.api.models.sessions.SessionExecuteParams +import com.browserbase.api.models.sessions.SessionExecuteResponse import com.browserbase.api.models.sessions.SessionExtractParams import com.browserbase.api.models.sessions.SessionExtractResponse import com.browserbase.api.models.sessions.SessionNavigateParams @@ -30,6 +31,7 @@ import com.browserbase.api.models.sessions.SessionObserveResponse import com.browserbase.api.models.sessions.SessionStartParams import com.browserbase.api.models.sessions.SessionStartResponse import java.util.function.Consumer +import kotlin.jvm.optionals.getOrNull class SessionServiceImpl internal constructor(private val clientOptions: ClientOptions) : SessionService { @@ -44,46 +46,46 @@ class SessionServiceImpl internal constructor(private val clientOptions: ClientO SessionServiceImpl(clientOptions.toBuilder().apply(modifier::accept).build()) override fun act(params: SessionActParams, requestOptions: RequestOptions): SessionActResponse = - // post /sessions/{id}/act + // post /v1/sessions/{id}/act withRawResponse().act(params, requestOptions).parse() override fun end(params: SessionEndParams, requestOptions: RequestOptions): SessionEndResponse = - // post /sessions/{id}/end + // post /v1/sessions/{id}/end withRawResponse().end(params, requestOptions).parse() - override fun executeAgent( - params: SessionExecuteAgentParams, + override fun execute( + params: SessionExecuteParams, requestOptions: RequestOptions, - ): SessionExecuteAgentResponse = - // post /sessions/{id}/agentExecute - withRawResponse().executeAgent(params, requestOptions).parse() + ): SessionExecuteResponse = + // post /v1/sessions/{id}/agentExecute + withRawResponse().execute(params, requestOptions).parse() override fun extract( params: SessionExtractParams, requestOptions: RequestOptions, ): SessionExtractResponse = - // post /sessions/{id}/extract + // post /v1/sessions/{id}/extract withRawResponse().extract(params, requestOptions).parse() override fun navigate( params: SessionNavigateParams, requestOptions: RequestOptions, ): SessionNavigateResponse = - // post /sessions/{id}/navigate + // post /v1/sessions/{id}/navigate withRawResponse().navigate(params, requestOptions).parse() override fun observe( params: SessionObserveParams, requestOptions: RequestOptions, ): SessionObserveResponse = - // post /sessions/{id}/observe + // post /v1/sessions/{id}/observe withRawResponse().observe(params, requestOptions).parse() override fun start( params: SessionStartParams, requestOptions: RequestOptions, ): SessionStartResponse = - // post /sessions/start + // post /v1/sessions/start withRawResponse().start(params, requestOptions).parse() class WithRawResponseImpl internal constructor(private val clientOptions: ClientOptions) : @@ -106,11 +108,14 @@ class SessionServiceImpl internal constructor(private val clientOptions: ClientO params: SessionActParams, requestOptions: RequestOptions, ): HttpResponseFor { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("id", params.id().getOrNull()) val request = HttpRequest.builder() .method(HttpMethod.POST) .baseUrl(clientOptions.baseUrl()) - .addPathSegments("sessions", params._pathParam(0), "act") + .addPathSegments("v1", "sessions", params._pathParam(0), "act") .body(json(clientOptions.jsonMapper, params._body())) .build() .prepare(clientOptions, params) @@ -134,11 +139,14 @@ class SessionServiceImpl internal constructor(private val clientOptions: ClientO params: SessionEndParams, requestOptions: RequestOptions, ): HttpResponseFor { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("id", params.id().getOrNull()) val request = HttpRequest.builder() .method(HttpMethod.POST) .baseUrl(clientOptions.baseUrl()) - .addPathSegments("sessions", params._pathParam(0), "end") + .addPathSegments("v1", "sessions", params._pathParam(0), "end") .apply { params._body().ifPresent { body(json(clientOptions.jsonMapper, it)) } } .build() .prepare(clientOptions, params) @@ -155,18 +163,21 @@ class SessionServiceImpl internal constructor(private val clientOptions: ClientO } } - private val executeAgentHandler: Handler = - jsonHandler(clientOptions.jsonMapper) + private val executeHandler: Handler = + jsonHandler(clientOptions.jsonMapper) - override fun executeAgent( - params: SessionExecuteAgentParams, + override fun execute( + params: SessionExecuteParams, requestOptions: RequestOptions, - ): HttpResponseFor { + ): HttpResponseFor { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("id", params.id().getOrNull()) val request = HttpRequest.builder() .method(HttpMethod.POST) .baseUrl(clientOptions.baseUrl()) - .addPathSegments("sessions", params._pathParam(0), "agentExecute") + .addPathSegments("v1", "sessions", params._pathParam(0), "agentExecute") .body(json(clientOptions.jsonMapper, params._body())) .build() .prepare(clientOptions, params) @@ -174,7 +185,7 @@ class SessionServiceImpl internal constructor(private val clientOptions: ClientO val response = clientOptions.httpClient.execute(request, requestOptions) return errorHandler.handle(response).parseable { response - .use { executeAgentHandler.handle(it) } + .use { executeHandler.handle(it) } .also { if (requestOptions.responseValidation!!) { it.validate() @@ -190,11 +201,14 @@ class SessionServiceImpl internal constructor(private val clientOptions: ClientO params: SessionExtractParams, requestOptions: RequestOptions, ): HttpResponseFor { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("id", params.id().getOrNull()) val request = HttpRequest.builder() .method(HttpMethod.POST) .baseUrl(clientOptions.baseUrl()) - .addPathSegments("sessions", params._pathParam(0), "extract") + .addPathSegments("v1", "sessions", params._pathParam(0), "extract") .body(json(clientOptions.jsonMapper, params._body())) .build() .prepare(clientOptions, params) @@ -218,11 +232,14 @@ class SessionServiceImpl internal constructor(private val clientOptions: ClientO params: SessionNavigateParams, requestOptions: RequestOptions, ): HttpResponseFor { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("id", params.id().getOrNull()) val request = HttpRequest.builder() .method(HttpMethod.POST) .baseUrl(clientOptions.baseUrl()) - .addPathSegments("sessions", params._pathParam(0), "navigate") + .addPathSegments("v1", "sessions", params._pathParam(0), "navigate") .body(json(clientOptions.jsonMapper, params._body())) .build() .prepare(clientOptions, params) @@ -246,11 +263,14 @@ class SessionServiceImpl internal constructor(private val clientOptions: ClientO params: SessionObserveParams, requestOptions: RequestOptions, ): HttpResponseFor { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("id", params.id().getOrNull()) val request = HttpRequest.builder() .method(HttpMethod.POST) .baseUrl(clientOptions.baseUrl()) - .addPathSegments("sessions", params._pathParam(0), "observe") + .addPathSegments("v1", "sessions", params._pathParam(0), "observe") .body(json(clientOptions.jsonMapper, params._body())) .build() .prepare(clientOptions, params) @@ -278,7 +298,7 @@ class SessionServiceImpl internal constructor(private val clientOptions: ClientO HttpRequest.builder() .method(HttpMethod.POST) .baseUrl(clientOptions.baseUrl()) - .addPathSegments("sessions", "start") + .addPathSegments("v1", "sessions", "start") .body(json(clientOptions.jsonMapper, params._body())) .build() .prepare(clientOptions, params) diff --git a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionActParamsTest.kt b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionActParamsTest.kt index 4b81e39..c31444c 100644 --- a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionActParamsTest.kt +++ b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionActParamsTest.kt @@ -4,6 +4,7 @@ package com.browserbase.api.models.sessions import com.browserbase.api.core.JsonValue import com.browserbase.api.core.http.Headers +import java.time.OffsetDateTime import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.Test @@ -12,20 +13,36 @@ internal class SessionActParamsTest { @Test fun create() { SessionActParams.builder() - .id(JsonValue.from(mapOf())) - .xLanguage(JsonValue.from(mapOf())) - .xSdkVersion(JsonValue.from(mapOf())) - .xSentAt(JsonValue.from(mapOf())) - .xStreamResponse(JsonValue.from(mapOf())) - .body(JsonValue.from(mapOf())) + .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") + .xLanguage(SessionActParams.XLanguage.TYPESCRIPT) + .xSdkVersion("3.0.6") + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) + .xStreamResponse(SessionActParams.XStreamResponse.TRUE) + .input("Click the login button") + .frameId("frameId") + .options( + SessionActParams.Options.builder() + .model("string") + .timeout(30000.0) + .variables( + SessionActParams.Options.Variables.builder() + .putAdditionalProperty("username", JsonValue.from("john_doe")) + .build() + ) + .build() + ) .build() } @Test fun pathParams() { - val params = SessionActParams.builder().id(JsonValue.from(mapOf())).build() + val params = + SessionActParams.builder() + .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") + .input("Click the login button") + .build() - assertThat(params._pathParam(0)).isEqualTo("[object Object]") + assertThat(params._pathParam(0)).isEqualTo("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") // out-of-bound path param assertThat(params._pathParam(1)).isEqualTo("") } @@ -34,22 +51,46 @@ internal class SessionActParamsTest { fun headers() { val params = SessionActParams.builder() - .id(JsonValue.from(mapOf())) - .xLanguage(JsonValue.from(mapOf())) - .xSdkVersion(JsonValue.from(mapOf())) - .xSentAt(JsonValue.from(mapOf())) - .xStreamResponse(JsonValue.from(mapOf())) - .body(JsonValue.from(mapOf())) + .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") + .xLanguage(SessionActParams.XLanguage.TYPESCRIPT) + .xSdkVersion("3.0.6") + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) + .xStreamResponse(SessionActParams.XStreamResponse.TRUE) + .input("Click the login button") + .frameId("frameId") + .options( + SessionActParams.Options.builder() + .model("string") + .timeout(30000.0) + .variables( + SessionActParams.Options.Variables.builder() + .putAdditionalProperty("username", JsonValue.from("john_doe")) + .build() + ) + .build() + ) .build() val headers = params._headers() - assertThat(headers).isEqualTo(Headers.builder().build()) + assertThat(headers) + .isEqualTo( + Headers.builder() + .put("x-language", "typescript") + .put("x-sdk-version", "3.0.6") + .put("x-sent-at", "2025-01-15T10:30:00.000Z") + .put("x-stream-response", "true") + .build() + ) } @Test fun headersWithoutOptionalFields() { - val params = SessionActParams.builder().id(JsonValue.from(mapOf())).build() + val params = + SessionActParams.builder() + .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") + .input("Click the login button") + .build() val headers = params._headers() @@ -60,23 +101,56 @@ internal class SessionActParamsTest { fun body() { val params = SessionActParams.builder() - .id(JsonValue.from(mapOf())) - .xLanguage(JsonValue.from(mapOf())) - .xSdkVersion(JsonValue.from(mapOf())) - .xSentAt(JsonValue.from(mapOf())) - .xStreamResponse(JsonValue.from(mapOf())) - .body(JsonValue.from(mapOf())) + .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") + .xLanguage(SessionActParams.XLanguage.TYPESCRIPT) + .xSdkVersion("3.0.6") + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) + .xStreamResponse(SessionActParams.XStreamResponse.TRUE) + .input("Click the login button") + .frameId("frameId") + .options( + SessionActParams.Options.builder() + .model("string") + .timeout(30000.0) + .variables( + SessionActParams.Options.Variables.builder() + .putAdditionalProperty("username", JsonValue.from("john_doe")) + .build() + ) + .build() + ) .build() val body = params._body() - assertThat(body).isEqualTo(JsonValue.from(mapOf())) + assertThat(body.input()) + .isEqualTo(SessionActParams.Input.ofString("Click the login button")) + assertThat(body.frameId()).contains("frameId") + assertThat(body.options()) + .contains( + SessionActParams.Options.builder() + .model("string") + .timeout(30000.0) + .variables( + SessionActParams.Options.Variables.builder() + .putAdditionalProperty("username", JsonValue.from("john_doe")) + .build() + ) + .build() + ) } @Test fun bodyWithoutOptionalFields() { - val params = SessionActParams.builder().id(JsonValue.from(mapOf())).build() + val params = + SessionActParams.builder() + .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") + .input("Click the login button") + .build() val body = params._body() + + assertThat(body.input()) + .isEqualTo(SessionActParams.Input.ofString("Click the login button")) } } diff --git a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionActResponseTest.kt b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionActResponseTest.kt index 83f3fa4..000d7fd 100644 --- a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionActResponseTest.kt +++ b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionActResponseTest.kt @@ -11,13 +11,82 @@ internal class SessionActResponseTest { @Test fun create() { - val sessionActResponse = SessionActResponse.builder().build() + val sessionActResponse = + SessionActResponse.builder() + .data( + SessionActResponse.Data.builder() + .result( + SessionActResponse.Data.Result.builder() + .actionDescription("Clicked button with text 'Login'") + .addAction( + Action.builder() + .description("Click the submit button") + .selector("[data-testid='submit-button']") + .addArgument("Hello World") + .method("click") + .build() + ) + .message("Successfully clicked the login button") + .success(true) + .build() + ) + .actionId("actionId") + .build() + ) + .success(SessionActResponse.Success.TRUE) + .build() + + assertThat(sessionActResponse.data()) + .isEqualTo( + SessionActResponse.Data.builder() + .result( + SessionActResponse.Data.Result.builder() + .actionDescription("Clicked button with text 'Login'") + .addAction( + Action.builder() + .description("Click the submit button") + .selector("[data-testid='submit-button']") + .addArgument("Hello World") + .method("click") + .build() + ) + .message("Successfully clicked the login button") + .success(true) + .build() + ) + .actionId("actionId") + .build() + ) + assertThat(sessionActResponse.success()).isEqualTo(SessionActResponse.Success.TRUE) } @Test fun roundtrip() { val jsonMapper = jsonMapper() - val sessionActResponse = SessionActResponse.builder().build() + val sessionActResponse = + SessionActResponse.builder() + .data( + SessionActResponse.Data.builder() + .result( + SessionActResponse.Data.Result.builder() + .actionDescription("Clicked button with text 'Login'") + .addAction( + Action.builder() + .description("Click the submit button") + .selector("[data-testid='submit-button']") + .addArgument("Hello World") + .method("click") + .build() + ) + .message("Successfully clicked the login button") + .success(true) + .build() + ) + .actionId("actionId") + .build() + ) + .success(SessionActResponse.Success.TRUE) + .build() val roundtrippedSessionActResponse = jsonMapper.readValue( diff --git a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionEndParamsTest.kt b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionEndParamsTest.kt index 514fc5e..14faac3 100644 --- a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionEndParamsTest.kt +++ b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionEndParamsTest.kt @@ -2,8 +2,8 @@ package com.browserbase.api.models.sessions -import com.browserbase.api.core.JsonValue import com.browserbase.api.core.http.Headers +import java.time.OffsetDateTime import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.Test @@ -12,19 +12,19 @@ internal class SessionEndParamsTest { @Test fun create() { SessionEndParams.builder() - .id(JsonValue.from(mapOf())) - .xLanguage(JsonValue.from(mapOf())) - .xSdkVersion(JsonValue.from(mapOf())) - .xSentAt(JsonValue.from(mapOf())) - .xStreamResponse(JsonValue.from(mapOf())) + .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") + .xLanguage(SessionEndParams.XLanguage.TYPESCRIPT) + .xSdkVersion("3.0.6") + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) + .xStreamResponse(SessionEndParams.XStreamResponse.TRUE) .build() } @Test fun pathParams() { - val params = SessionEndParams.builder().id(JsonValue.from(mapOf())).build() + val params = SessionEndParams.builder().id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123").build() - assertThat(params._pathParam(0)).isEqualTo("[object Object]") + assertThat(params._pathParam(0)).isEqualTo("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") // out-of-bound path param assertThat(params._pathParam(1)).isEqualTo("") } @@ -33,21 +33,29 @@ internal class SessionEndParamsTest { fun headers() { val params = SessionEndParams.builder() - .id(JsonValue.from(mapOf())) - .xLanguage(JsonValue.from(mapOf())) - .xSdkVersion(JsonValue.from(mapOf())) - .xSentAt(JsonValue.from(mapOf())) - .xStreamResponse(JsonValue.from(mapOf())) + .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") + .xLanguage(SessionEndParams.XLanguage.TYPESCRIPT) + .xSdkVersion("3.0.6") + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) + .xStreamResponse(SessionEndParams.XStreamResponse.TRUE) .build() val headers = params._headers() - assertThat(headers).isEqualTo(Headers.builder().build()) + assertThat(headers) + .isEqualTo( + Headers.builder() + .put("x-language", "typescript") + .put("x-sdk-version", "3.0.6") + .put("x-sent-at", "2025-01-15T10:30:00.000Z") + .put("x-stream-response", "true") + .build() + ) } @Test fun headersWithoutOptionalFields() { - val params = SessionEndParams.builder().id(JsonValue.from(mapOf())).build() + val params = SessionEndParams.builder().id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123").build() val headers = params._headers() diff --git a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionEndResponseTest.kt b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionEndResponseTest.kt index 30e45db..27a2a36 100644 --- a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionEndResponseTest.kt +++ b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionEndResponseTest.kt @@ -11,13 +11,17 @@ internal class SessionEndResponseTest { @Test fun create() { - val sessionEndResponse = SessionEndResponse.builder().build() + val sessionEndResponse = + SessionEndResponse.builder().success(SessionEndResponse.Success.TRUE).build() + + assertThat(sessionEndResponse.success()).isEqualTo(SessionEndResponse.Success.TRUE) } @Test fun roundtrip() { val jsonMapper = jsonMapper() - val sessionEndResponse = SessionEndResponse.builder().build() + val sessionEndResponse = + SessionEndResponse.builder().success(SessionEndResponse.Success.TRUE).build() val roundtrippedSessionEndResponse = jsonMapper.readValue( diff --git a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionExecuteAgentParamsTest.kt b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionExecuteAgentParamsTest.kt deleted file mode 100644 index 90f1e1f..0000000 --- a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionExecuteAgentParamsTest.kt +++ /dev/null @@ -1,85 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. - -package com.browserbase.api.models.sessions - -import com.browserbase.api.core.JsonValue -import com.browserbase.api.core.http.Headers -import org.assertj.core.api.Assertions.assertThat -import org.junit.jupiter.api.Test - -internal class SessionExecuteAgentParamsTest { - - @Test - fun create() { - SessionExecuteAgentParams.builder() - .id(JsonValue.from(mapOf())) - .xLanguage(JsonValue.from(mapOf())) - .xSdkVersion(JsonValue.from(mapOf())) - .xSentAt(JsonValue.from(mapOf())) - .xStreamResponse(JsonValue.from(mapOf())) - .body(JsonValue.from(mapOf())) - .build() - } - - @Test - fun pathParams() { - val params = - SessionExecuteAgentParams.builder().id(JsonValue.from(mapOf())).build() - - assertThat(params._pathParam(0)).isEqualTo("[object Object]") - // out-of-bound path param - assertThat(params._pathParam(1)).isEqualTo("") - } - - @Test - fun headers() { - val params = - SessionExecuteAgentParams.builder() - .id(JsonValue.from(mapOf())) - .xLanguage(JsonValue.from(mapOf())) - .xSdkVersion(JsonValue.from(mapOf())) - .xSentAt(JsonValue.from(mapOf())) - .xStreamResponse(JsonValue.from(mapOf())) - .body(JsonValue.from(mapOf())) - .build() - - val headers = params._headers() - - assertThat(headers).isEqualTo(Headers.builder().build()) - } - - @Test - fun headersWithoutOptionalFields() { - val params = - SessionExecuteAgentParams.builder().id(JsonValue.from(mapOf())).build() - - val headers = params._headers() - - assertThat(headers).isEqualTo(Headers.builder().build()) - } - - @Test - fun body() { - val params = - SessionExecuteAgentParams.builder() - .id(JsonValue.from(mapOf())) - .xLanguage(JsonValue.from(mapOf())) - .xSdkVersion(JsonValue.from(mapOf())) - .xSentAt(JsonValue.from(mapOf())) - .xStreamResponse(JsonValue.from(mapOf())) - .body(JsonValue.from(mapOf())) - .build() - - val body = params._body() - - assertThat(body).isEqualTo(JsonValue.from(mapOf())) - } - - @Test - fun bodyWithoutOptionalFields() { - val params = - SessionExecuteAgentParams.builder().id(JsonValue.from(mapOf())).build() - - val body = params._body() - } -} diff --git a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionExecuteAgentResponseTest.kt b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionExecuteAgentResponseTest.kt deleted file mode 100644 index 0c28d46..0000000 --- a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionExecuteAgentResponseTest.kt +++ /dev/null @@ -1,30 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. - -package com.browserbase.api.models.sessions - -import com.browserbase.api.core.jsonMapper -import com.fasterxml.jackson.module.kotlin.jacksonTypeRef -import org.assertj.core.api.Assertions.assertThat -import org.junit.jupiter.api.Test - -internal class SessionExecuteAgentResponseTest { - - @Test - fun create() { - val sessionExecuteAgentResponse = SessionExecuteAgentResponse.builder().build() - } - - @Test - fun roundtrip() { - val jsonMapper = jsonMapper() - val sessionExecuteAgentResponse = SessionExecuteAgentResponse.builder().build() - - val roundtrippedSessionExecuteAgentResponse = - jsonMapper.readValue( - jsonMapper.writeValueAsString(sessionExecuteAgentResponse), - jacksonTypeRef(), - ) - - assertThat(roundtrippedSessionExecuteAgentResponse).isEqualTo(sessionExecuteAgentResponse) - } -} diff --git a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionExecuteParamsTest.kt b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionExecuteParamsTest.kt new file mode 100644 index 0000000..b40f381 --- /dev/null +++ b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionExecuteParamsTest.kt @@ -0,0 +1,199 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.browserbase.api.models.sessions + +import com.browserbase.api.core.http.Headers +import java.time.OffsetDateTime +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class SessionExecuteParamsTest { + + @Test + fun create() { + SessionExecuteParams.builder() + .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") + .xLanguage(SessionExecuteParams.XLanguage.TYPESCRIPT) + .xSdkVersion("3.0.6") + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) + .xStreamResponse(SessionExecuteParams.XStreamResponse.TRUE) + .agentConfig( + SessionExecuteParams.AgentConfig.builder() + .cua(true) + .model("string") + .systemPrompt("systemPrompt") + .build() + ) + .executeOptions( + SessionExecuteParams.ExecuteOptions.builder() + .instruction( + "Log in with username 'demo' and password 'test123', then navigate to settings" + ) + .highlightCursor(true) + .maxSteps(20.0) + .build() + ) + .frameId("frameId") + .build() + } + + @Test + fun pathParams() { + val params = + SessionExecuteParams.builder() + .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") + .agentConfig(SessionExecuteParams.AgentConfig.builder().build()) + .executeOptions( + SessionExecuteParams.ExecuteOptions.builder() + .instruction( + "Log in with username 'demo' and password 'test123', then navigate to settings" + ) + .build() + ) + .build() + + assertThat(params._pathParam(0)).isEqualTo("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") + // out-of-bound path param + assertThat(params._pathParam(1)).isEqualTo("") + } + + @Test + fun headers() { + val params = + SessionExecuteParams.builder() + .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") + .xLanguage(SessionExecuteParams.XLanguage.TYPESCRIPT) + .xSdkVersion("3.0.6") + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) + .xStreamResponse(SessionExecuteParams.XStreamResponse.TRUE) + .agentConfig( + SessionExecuteParams.AgentConfig.builder() + .cua(true) + .model("string") + .systemPrompt("systemPrompt") + .build() + ) + .executeOptions( + SessionExecuteParams.ExecuteOptions.builder() + .instruction( + "Log in with username 'demo' and password 'test123', then navigate to settings" + ) + .highlightCursor(true) + .maxSteps(20.0) + .build() + ) + .frameId("frameId") + .build() + + val headers = params._headers() + + assertThat(headers) + .isEqualTo( + Headers.builder() + .put("x-language", "typescript") + .put("x-sdk-version", "3.0.6") + .put("x-sent-at", "2025-01-15T10:30:00.000Z") + .put("x-stream-response", "true") + .build() + ) + } + + @Test + fun headersWithoutOptionalFields() { + val params = + SessionExecuteParams.builder() + .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") + .agentConfig(SessionExecuteParams.AgentConfig.builder().build()) + .executeOptions( + SessionExecuteParams.ExecuteOptions.builder() + .instruction( + "Log in with username 'demo' and password 'test123', then navigate to settings" + ) + .build() + ) + .build() + + val headers = params._headers() + + assertThat(headers).isEqualTo(Headers.builder().build()) + } + + @Test + fun body() { + val params = + SessionExecuteParams.builder() + .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") + .xLanguage(SessionExecuteParams.XLanguage.TYPESCRIPT) + .xSdkVersion("3.0.6") + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) + .xStreamResponse(SessionExecuteParams.XStreamResponse.TRUE) + .agentConfig( + SessionExecuteParams.AgentConfig.builder() + .cua(true) + .model("string") + .systemPrompt("systemPrompt") + .build() + ) + .executeOptions( + SessionExecuteParams.ExecuteOptions.builder() + .instruction( + "Log in with username 'demo' and password 'test123', then navigate to settings" + ) + .highlightCursor(true) + .maxSteps(20.0) + .build() + ) + .frameId("frameId") + .build() + + val body = params._body() + + assertThat(body.agentConfig()) + .isEqualTo( + SessionExecuteParams.AgentConfig.builder() + .cua(true) + .model("string") + .systemPrompt("systemPrompt") + .build() + ) + assertThat(body.executeOptions()) + .isEqualTo( + SessionExecuteParams.ExecuteOptions.builder() + .instruction( + "Log in with username 'demo' and password 'test123', then navigate to settings" + ) + .highlightCursor(true) + .maxSteps(20.0) + .build() + ) + assertThat(body.frameId()).contains("frameId") + } + + @Test + fun bodyWithoutOptionalFields() { + val params = + SessionExecuteParams.builder() + .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") + .agentConfig(SessionExecuteParams.AgentConfig.builder().build()) + .executeOptions( + SessionExecuteParams.ExecuteOptions.builder() + .instruction( + "Log in with username 'demo' and password 'test123', then navigate to settings" + ) + .build() + ) + .build() + + val body = params._body() + + assertThat(body.agentConfig()).isEqualTo(SessionExecuteParams.AgentConfig.builder().build()) + assertThat(body.executeOptions()) + .isEqualTo( + SessionExecuteParams.ExecuteOptions.builder() + .instruction( + "Log in with username 'demo' and password 'test123', then navigate to settings" + ) + .build() + ) + } +} diff --git a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionExecuteResponseTest.kt b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionExecuteResponseTest.kt new file mode 100644 index 0000000..d2fb4d9 --- /dev/null +++ b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionExecuteResponseTest.kt @@ -0,0 +1,151 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.browserbase.api.models.sessions + +import com.browserbase.api.core.JsonValue +import com.browserbase.api.core.jsonMapper +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class SessionExecuteResponseTest { + + @Test + fun create() { + val sessionExecuteResponse = + SessionExecuteResponse.builder() + .data( + SessionExecuteResponse.Data.builder() + .result( + SessionExecuteResponse.Data.Result.builder() + .addAction( + SessionExecuteResponse.Data.Result.Action.builder() + .type("click") + .action("action") + .instruction("instruction") + .pageText("pageText") + .pageUrl("pageUrl") + .reasoning("reasoning") + .taskCompleted(true) + .timeMs(0.0) + .build() + ) + .completed(true) + .message("Successfully logged in and navigated to dashboard") + .success(true) + .metadata( + SessionExecuteResponse.Data.Result.Metadata.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) + .usage( + SessionExecuteResponse.Data.Result.Usage.builder() + .inferenceTimeMs(2500.0) + .inputTokens(1500.0) + .outputTokens(250.0) + .cachedInputTokens(0.0) + .reasoningTokens(0.0) + .build() + ) + .build() + ) + .build() + ) + .success(SessionExecuteResponse.Success.TRUE) + .build() + + assertThat(sessionExecuteResponse.data()) + .isEqualTo( + SessionExecuteResponse.Data.builder() + .result( + SessionExecuteResponse.Data.Result.builder() + .addAction( + SessionExecuteResponse.Data.Result.Action.builder() + .type("click") + .action("action") + .instruction("instruction") + .pageText("pageText") + .pageUrl("pageUrl") + .reasoning("reasoning") + .taskCompleted(true) + .timeMs(0.0) + .build() + ) + .completed(true) + .message("Successfully logged in and navigated to dashboard") + .success(true) + .metadata( + SessionExecuteResponse.Data.Result.Metadata.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) + .usage( + SessionExecuteResponse.Data.Result.Usage.builder() + .inferenceTimeMs(2500.0) + .inputTokens(1500.0) + .outputTokens(250.0) + .cachedInputTokens(0.0) + .reasoningTokens(0.0) + .build() + ) + .build() + ) + .build() + ) + assertThat(sessionExecuteResponse.success()).isEqualTo(SessionExecuteResponse.Success.TRUE) + } + + @Test + fun roundtrip() { + val jsonMapper = jsonMapper() + val sessionExecuteResponse = + SessionExecuteResponse.builder() + .data( + SessionExecuteResponse.Data.builder() + .result( + SessionExecuteResponse.Data.Result.builder() + .addAction( + SessionExecuteResponse.Data.Result.Action.builder() + .type("click") + .action("action") + .instruction("instruction") + .pageText("pageText") + .pageUrl("pageUrl") + .reasoning("reasoning") + .taskCompleted(true) + .timeMs(0.0) + .build() + ) + .completed(true) + .message("Successfully logged in and navigated to dashboard") + .success(true) + .metadata( + SessionExecuteResponse.Data.Result.Metadata.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) + .usage( + SessionExecuteResponse.Data.Result.Usage.builder() + .inferenceTimeMs(2500.0) + .inputTokens(1500.0) + .outputTokens(250.0) + .cachedInputTokens(0.0) + .reasoningTokens(0.0) + .build() + ) + .build() + ) + .build() + ) + .success(SessionExecuteResponse.Success.TRUE) + .build() + + val roundtrippedSessionExecuteResponse = + jsonMapper.readValue( + jsonMapper.writeValueAsString(sessionExecuteResponse), + jacksonTypeRef(), + ) + + assertThat(roundtrippedSessionExecuteResponse).isEqualTo(sessionExecuteResponse) + } +} diff --git a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionExtractParamsTest.kt b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionExtractParamsTest.kt index e631276..4a3c252 100644 --- a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionExtractParamsTest.kt +++ b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionExtractParamsTest.kt @@ -4,6 +4,7 @@ package com.browserbase.api.models.sessions import com.browserbase.api.core.JsonValue import com.browserbase.api.core.http.Headers +import java.time.OffsetDateTime import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.Test @@ -12,20 +13,34 @@ internal class SessionExtractParamsTest { @Test fun create() { SessionExtractParams.builder() - .id(JsonValue.from(mapOf())) - .xLanguage(JsonValue.from(mapOf())) - .xSdkVersion(JsonValue.from(mapOf())) - .xSentAt(JsonValue.from(mapOf())) - .xStreamResponse(JsonValue.from(mapOf())) - .body(JsonValue.from(mapOf())) + .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") + .xLanguage(SessionExtractParams.XLanguage.TYPESCRIPT) + .xSdkVersion("3.0.6") + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) + .xStreamResponse(SessionExtractParams.XStreamResponse.TRUE) + .frameId("frameId") + .instruction("Extract all product names and prices from the page") + .options( + SessionExtractParams.Options.builder() + .model("string") + .selector("#main-content") + .timeout(30000.0) + .build() + ) + .schema( + SessionExtractParams.Schema.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) .build() } @Test fun pathParams() { - val params = SessionExtractParams.builder().id(JsonValue.from(mapOf())).build() + val params = + SessionExtractParams.builder().id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123").build() - assertThat(params._pathParam(0)).isEqualTo("[object Object]") + assertThat(params._pathParam(0)).isEqualTo("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") // out-of-bound path param assertThat(params._pathParam(1)).isEqualTo("") } @@ -34,22 +49,44 @@ internal class SessionExtractParamsTest { fun headers() { val params = SessionExtractParams.builder() - .id(JsonValue.from(mapOf())) - .xLanguage(JsonValue.from(mapOf())) - .xSdkVersion(JsonValue.from(mapOf())) - .xSentAt(JsonValue.from(mapOf())) - .xStreamResponse(JsonValue.from(mapOf())) - .body(JsonValue.from(mapOf())) + .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") + .xLanguage(SessionExtractParams.XLanguage.TYPESCRIPT) + .xSdkVersion("3.0.6") + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) + .xStreamResponse(SessionExtractParams.XStreamResponse.TRUE) + .frameId("frameId") + .instruction("Extract all product names and prices from the page") + .options( + SessionExtractParams.Options.builder() + .model("string") + .selector("#main-content") + .timeout(30000.0) + .build() + ) + .schema( + SessionExtractParams.Schema.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) .build() val headers = params._headers() - assertThat(headers).isEqualTo(Headers.builder().build()) + assertThat(headers) + .isEqualTo( + Headers.builder() + .put("x-language", "typescript") + .put("x-sdk-version", "3.0.6") + .put("x-sent-at", "2025-01-15T10:30:00.000Z") + .put("x-stream-response", "true") + .build() + ) } @Test fun headersWithoutOptionalFields() { - val params = SessionExtractParams.builder().id(JsonValue.from(mapOf())).build() + val params = + SessionExtractParams.builder().id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123").build() val headers = params._headers() @@ -60,22 +97,52 @@ internal class SessionExtractParamsTest { fun body() { val params = SessionExtractParams.builder() - .id(JsonValue.from(mapOf())) - .xLanguage(JsonValue.from(mapOf())) - .xSdkVersion(JsonValue.from(mapOf())) - .xSentAt(JsonValue.from(mapOf())) - .xStreamResponse(JsonValue.from(mapOf())) - .body(JsonValue.from(mapOf())) + .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") + .xLanguage(SessionExtractParams.XLanguage.TYPESCRIPT) + .xSdkVersion("3.0.6") + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) + .xStreamResponse(SessionExtractParams.XStreamResponse.TRUE) + .frameId("frameId") + .instruction("Extract all product names and prices from the page") + .options( + SessionExtractParams.Options.builder() + .model("string") + .selector("#main-content") + .timeout(30000.0) + .build() + ) + .schema( + SessionExtractParams.Schema.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) .build() val body = params._body() - assertThat(body).isEqualTo(JsonValue.from(mapOf())) + assertThat(body.frameId()).contains("frameId") + assertThat(body.instruction()) + .contains("Extract all product names and prices from the page") + assertThat(body.options()) + .contains( + SessionExtractParams.Options.builder() + .model("string") + .selector("#main-content") + .timeout(30000.0) + .build() + ) + assertThat(body.schema()) + .contains( + SessionExtractParams.Schema.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) } @Test fun bodyWithoutOptionalFields() { - val params = SessionExtractParams.builder().id(JsonValue.from(mapOf())).build() + val params = + SessionExtractParams.builder().id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123").build() val body = params._body() } diff --git a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionExtractResponseTest.kt b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionExtractResponseTest.kt index 04bed64..6cf7056 100644 --- a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionExtractResponseTest.kt +++ b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionExtractResponseTest.kt @@ -2,6 +2,7 @@ package com.browserbase.api.models.sessions +import com.browserbase.api.core.JsonValue import com.browserbase.api.core.jsonMapper import com.fasterxml.jackson.module.kotlin.jacksonTypeRef import org.assertj.core.api.Assertions.assertThat @@ -11,13 +12,40 @@ internal class SessionExtractResponseTest { @Test fun create() { - val sessionExtractResponse = SessionExtractResponse.builder().build() + val sessionExtractResponse = + SessionExtractResponse.builder() + .data( + SessionExtractResponse.Data.builder() + .result(JsonValue.from(mapOf())) + .actionId("actionId") + .build() + ) + .success(SessionExtractResponse.Success.TRUE) + .build() + + assertThat(sessionExtractResponse.data()) + .isEqualTo( + SessionExtractResponse.Data.builder() + .result(JsonValue.from(mapOf())) + .actionId("actionId") + .build() + ) + assertThat(sessionExtractResponse.success()).isEqualTo(SessionExtractResponse.Success.TRUE) } @Test fun roundtrip() { val jsonMapper = jsonMapper() - val sessionExtractResponse = SessionExtractResponse.builder().build() + val sessionExtractResponse = + SessionExtractResponse.builder() + .data( + SessionExtractResponse.Data.builder() + .result(JsonValue.from(mapOf())) + .actionId("actionId") + .build() + ) + .success(SessionExtractResponse.Success.TRUE) + .build() val roundtrippedSessionExtractResponse = jsonMapper.readValue( diff --git a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionNavigateParamsTest.kt b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionNavigateParamsTest.kt index 6d8a60d..aa845c3 100644 --- a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionNavigateParamsTest.kt +++ b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionNavigateParamsTest.kt @@ -2,8 +2,8 @@ package com.browserbase.api.models.sessions -import com.browserbase.api.core.JsonValue import com.browserbase.api.core.http.Headers +import java.time.OffsetDateTime import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.Test @@ -12,21 +12,32 @@ internal class SessionNavigateParamsTest { @Test fun create() { SessionNavigateParams.builder() - .id(JsonValue.from(mapOf())) - .xLanguage(JsonValue.from(mapOf())) - .xSdkVersion(JsonValue.from(mapOf())) - .xSentAt(JsonValue.from(mapOf())) - .xStreamResponse(JsonValue.from(mapOf())) - .body(JsonValue.from(mapOf())) + .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") + .xLanguage(SessionNavigateParams.XLanguage.TYPESCRIPT) + .xSdkVersion("3.0.6") + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) + .xStreamResponse(SessionNavigateParams.XStreamResponse.TRUE) + .url("https://example.com") + .frameId("frameId") + .options( + SessionNavigateParams.Options.builder() + .referer("referer") + .timeout(30000.0) + .waitUntil(SessionNavigateParams.Options.WaitUntil.NETWORKIDLE) + .build() + ) .build() } @Test fun pathParams() { val params = - SessionNavigateParams.builder().id(JsonValue.from(mapOf())).build() + SessionNavigateParams.builder() + .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") + .url("https://example.com") + .build() - assertThat(params._pathParam(0)).isEqualTo("[object Object]") + assertThat(params._pathParam(0)).isEqualTo("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") // out-of-bound path param assertThat(params._pathParam(1)).isEqualTo("") } @@ -35,23 +46,42 @@ internal class SessionNavigateParamsTest { fun headers() { val params = SessionNavigateParams.builder() - .id(JsonValue.from(mapOf())) - .xLanguage(JsonValue.from(mapOf())) - .xSdkVersion(JsonValue.from(mapOf())) - .xSentAt(JsonValue.from(mapOf())) - .xStreamResponse(JsonValue.from(mapOf())) - .body(JsonValue.from(mapOf())) + .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") + .xLanguage(SessionNavigateParams.XLanguage.TYPESCRIPT) + .xSdkVersion("3.0.6") + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) + .xStreamResponse(SessionNavigateParams.XStreamResponse.TRUE) + .url("https://example.com") + .frameId("frameId") + .options( + SessionNavigateParams.Options.builder() + .referer("referer") + .timeout(30000.0) + .waitUntil(SessionNavigateParams.Options.WaitUntil.NETWORKIDLE) + .build() + ) .build() val headers = params._headers() - assertThat(headers).isEqualTo(Headers.builder().build()) + assertThat(headers) + .isEqualTo( + Headers.builder() + .put("x-language", "typescript") + .put("x-sdk-version", "3.0.6") + .put("x-sent-at", "2025-01-15T10:30:00.000Z") + .put("x-stream-response", "true") + .build() + ) } @Test fun headersWithoutOptionalFields() { val params = - SessionNavigateParams.builder().id(JsonValue.from(mapOf())).build() + SessionNavigateParams.builder() + .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") + .url("https://example.com") + .build() val headers = params._headers() @@ -62,24 +92,46 @@ internal class SessionNavigateParamsTest { fun body() { val params = SessionNavigateParams.builder() - .id(JsonValue.from(mapOf())) - .xLanguage(JsonValue.from(mapOf())) - .xSdkVersion(JsonValue.from(mapOf())) - .xSentAt(JsonValue.from(mapOf())) - .xStreamResponse(JsonValue.from(mapOf())) - .body(JsonValue.from(mapOf())) + .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") + .xLanguage(SessionNavigateParams.XLanguage.TYPESCRIPT) + .xSdkVersion("3.0.6") + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) + .xStreamResponse(SessionNavigateParams.XStreamResponse.TRUE) + .url("https://example.com") + .frameId("frameId") + .options( + SessionNavigateParams.Options.builder() + .referer("referer") + .timeout(30000.0) + .waitUntil(SessionNavigateParams.Options.WaitUntil.NETWORKIDLE) + .build() + ) .build() val body = params._body() - assertThat(body).isEqualTo(JsonValue.from(mapOf())) + assertThat(body.url()).isEqualTo("https://example.com") + assertThat(body.frameId()).contains("frameId") + assertThat(body.options()) + .contains( + SessionNavigateParams.Options.builder() + .referer("referer") + .timeout(30000.0) + .waitUntil(SessionNavigateParams.Options.WaitUntil.NETWORKIDLE) + .build() + ) } @Test fun bodyWithoutOptionalFields() { val params = - SessionNavigateParams.builder().id(JsonValue.from(mapOf())).build() + SessionNavigateParams.builder() + .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") + .url("https://example.com") + .build() val body = params._body() + + assertThat(body.url()).isEqualTo("https://example.com") } } diff --git a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionNavigateResponseTest.kt b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionNavigateResponseTest.kt index 6d62909..e02a0e3 100644 --- a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionNavigateResponseTest.kt +++ b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionNavigateResponseTest.kt @@ -2,6 +2,7 @@ package com.browserbase.api.models.sessions +import com.browserbase.api.core.JsonValue import com.browserbase.api.core.jsonMapper import com.fasterxml.jackson.module.kotlin.jacksonTypeRef import org.assertj.core.api.Assertions.assertThat @@ -11,13 +12,41 @@ internal class SessionNavigateResponseTest { @Test fun create() { - val sessionNavigateResponse = SessionNavigateResponse.builder().build() + val sessionNavigateResponse = + SessionNavigateResponse.builder() + .data( + SessionNavigateResponse.Data.builder() + .result(JsonValue.from(mapOf())) + .actionId("actionId") + .build() + ) + .success(SessionNavigateResponse.Success.TRUE) + .build() + + assertThat(sessionNavigateResponse.data()) + .isEqualTo( + SessionNavigateResponse.Data.builder() + .result(JsonValue.from(mapOf())) + .actionId("actionId") + .build() + ) + assertThat(sessionNavigateResponse.success()) + .isEqualTo(SessionNavigateResponse.Success.TRUE) } @Test fun roundtrip() { val jsonMapper = jsonMapper() - val sessionNavigateResponse = SessionNavigateResponse.builder().build() + val sessionNavigateResponse = + SessionNavigateResponse.builder() + .data( + SessionNavigateResponse.Data.builder() + .result(JsonValue.from(mapOf())) + .actionId("actionId") + .build() + ) + .success(SessionNavigateResponse.Success.TRUE) + .build() val roundtrippedSessionNavigateResponse = jsonMapper.readValue( diff --git a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionObserveParamsTest.kt b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionObserveParamsTest.kt index 8943f1d..95ccd9b 100644 --- a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionObserveParamsTest.kt +++ b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionObserveParamsTest.kt @@ -2,8 +2,8 @@ package com.browserbase.api.models.sessions -import com.browserbase.api.core.JsonValue import com.browserbase.api.core.http.Headers +import java.time.OffsetDateTime import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.Test @@ -12,20 +12,29 @@ internal class SessionObserveParamsTest { @Test fun create() { SessionObserveParams.builder() - .id(JsonValue.from(mapOf())) - .xLanguage(JsonValue.from(mapOf())) - .xSdkVersion(JsonValue.from(mapOf())) - .xSentAt(JsonValue.from(mapOf())) - .xStreamResponse(JsonValue.from(mapOf())) - .body(JsonValue.from(mapOf())) + .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") + .xLanguage(SessionObserveParams.XLanguage.TYPESCRIPT) + .xSdkVersion("3.0.6") + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) + .xStreamResponse(SessionObserveParams.XStreamResponse.TRUE) + .frameId("frameId") + .instruction("Find all clickable navigation links") + .options( + SessionObserveParams.Options.builder() + .model("string") + .selector("nav") + .timeout(30000.0) + .build() + ) .build() } @Test fun pathParams() { - val params = SessionObserveParams.builder().id(JsonValue.from(mapOf())).build() + val params = + SessionObserveParams.builder().id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123").build() - assertThat(params._pathParam(0)).isEqualTo("[object Object]") + assertThat(params._pathParam(0)).isEqualTo("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") // out-of-bound path param assertThat(params._pathParam(1)).isEqualTo("") } @@ -34,22 +43,39 @@ internal class SessionObserveParamsTest { fun headers() { val params = SessionObserveParams.builder() - .id(JsonValue.from(mapOf())) - .xLanguage(JsonValue.from(mapOf())) - .xSdkVersion(JsonValue.from(mapOf())) - .xSentAt(JsonValue.from(mapOf())) - .xStreamResponse(JsonValue.from(mapOf())) - .body(JsonValue.from(mapOf())) + .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") + .xLanguage(SessionObserveParams.XLanguage.TYPESCRIPT) + .xSdkVersion("3.0.6") + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) + .xStreamResponse(SessionObserveParams.XStreamResponse.TRUE) + .frameId("frameId") + .instruction("Find all clickable navigation links") + .options( + SessionObserveParams.Options.builder() + .model("string") + .selector("nav") + .timeout(30000.0) + .build() + ) .build() val headers = params._headers() - assertThat(headers).isEqualTo(Headers.builder().build()) + assertThat(headers) + .isEqualTo( + Headers.builder() + .put("x-language", "typescript") + .put("x-sdk-version", "3.0.6") + .put("x-sent-at", "2025-01-15T10:30:00.000Z") + .put("x-stream-response", "true") + .build() + ) } @Test fun headersWithoutOptionalFields() { - val params = SessionObserveParams.builder().id(JsonValue.from(mapOf())).build() + val params = + SessionObserveParams.builder().id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123").build() val headers = params._headers() @@ -60,22 +86,40 @@ internal class SessionObserveParamsTest { fun body() { val params = SessionObserveParams.builder() - .id(JsonValue.from(mapOf())) - .xLanguage(JsonValue.from(mapOf())) - .xSdkVersion(JsonValue.from(mapOf())) - .xSentAt(JsonValue.from(mapOf())) - .xStreamResponse(JsonValue.from(mapOf())) - .body(JsonValue.from(mapOf())) + .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") + .xLanguage(SessionObserveParams.XLanguage.TYPESCRIPT) + .xSdkVersion("3.0.6") + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) + .xStreamResponse(SessionObserveParams.XStreamResponse.TRUE) + .frameId("frameId") + .instruction("Find all clickable navigation links") + .options( + SessionObserveParams.Options.builder() + .model("string") + .selector("nav") + .timeout(30000.0) + .build() + ) .build() val body = params._body() - assertThat(body).isEqualTo(JsonValue.from(mapOf())) + assertThat(body.frameId()).contains("frameId") + assertThat(body.instruction()).contains("Find all clickable navigation links") + assertThat(body.options()) + .contains( + SessionObserveParams.Options.builder() + .model("string") + .selector("nav") + .timeout(30000.0) + .build() + ) } @Test fun bodyWithoutOptionalFields() { - val params = SessionObserveParams.builder().id(JsonValue.from(mapOf())).build() + val params = + SessionObserveParams.builder().id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123").build() val body = params._body() } diff --git a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionObserveResponseTest.kt b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionObserveResponseTest.kt index b597689..e3d72c3 100644 --- a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionObserveResponseTest.kt +++ b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionObserveResponseTest.kt @@ -11,13 +11,61 @@ internal class SessionObserveResponseTest { @Test fun create() { - val sessionObserveResponse = SessionObserveResponse.builder().build() + val sessionObserveResponse = + SessionObserveResponse.builder() + .data( + SessionObserveResponse.Data.builder() + .addResult( + Action.builder() + .description("Click the submit button") + .selector("[data-testid='submit-button']") + .addArgument("Hello World") + .method("click") + .build() + ) + .actionId("actionId") + .build() + ) + .success(SessionObserveResponse.Success.TRUE) + .build() + + assertThat(sessionObserveResponse.data()) + .isEqualTo( + SessionObserveResponse.Data.builder() + .addResult( + Action.builder() + .description("Click the submit button") + .selector("[data-testid='submit-button']") + .addArgument("Hello World") + .method("click") + .build() + ) + .actionId("actionId") + .build() + ) + assertThat(sessionObserveResponse.success()).isEqualTo(SessionObserveResponse.Success.TRUE) } @Test fun roundtrip() { val jsonMapper = jsonMapper() - val sessionObserveResponse = SessionObserveResponse.builder().build() + val sessionObserveResponse = + SessionObserveResponse.builder() + .data( + SessionObserveResponse.Data.builder() + .addResult( + Action.builder() + .description("Click the submit button") + .selector("[data-testid='submit-button']") + .addArgument("Hello World") + .method("click") + .build() + ) + .actionId("actionId") + .build() + ) + .success(SessionObserveResponse.Success.TRUE) + .build() val roundtrippedSessionObserveResponse = jsonMapper.readValue( diff --git a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionStartParamsTest.kt b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionStartParamsTest.kt index 627f9ae..13ae538 100644 --- a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionStartParamsTest.kt +++ b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionStartParamsTest.kt @@ -4,6 +4,7 @@ package com.browserbase.api.models.sessions import com.browserbase.api.core.JsonValue import com.browserbase.api.core.http.Headers +import java.time.OffsetDateTime import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.Test @@ -12,11 +13,148 @@ internal class SessionStartParamsTest { @Test fun create() { SessionStartParams.builder() - .xLanguage(JsonValue.from(mapOf())) - .xSdkVersion(JsonValue.from(mapOf())) - .xSentAt(JsonValue.from(mapOf())) - .xStreamResponse(JsonValue.from(mapOf())) - .body(JsonValue.from(mapOf())) + .xLanguage(SessionStartParams.XLanguage.TYPESCRIPT) + .xSdkVersion("3.0.6") + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) + .xStreamResponse(SessionStartParams.XStreamResponse.TRUE) + .modelName("gpt-4o") + .actTimeoutMs(30000.0) + .browser( + SessionStartParams.Browser.builder() + .cdpUrl("ws://localhost:9222") + .launchOptions( + SessionStartParams.Browser.LaunchOptions.builder() + .acceptDownloads(true) + .addArg("string") + .cdpUrl("cdpUrl") + .chromiumSandbox(true) + .connectTimeoutMs(0.0) + .deviceScaleFactor(0.0) + .devtools(true) + .downloadsPath("downloadsPath") + .executablePath("executablePath") + .hasTouch(true) + .headless(true) + .ignoreDefaultArgs(true) + .ignoreHttpsErrors(true) + .locale("locale") + .preserveUserDataDir(true) + .proxy( + SessionStartParams.Browser.LaunchOptions.Proxy.builder() + .server("server") + .bypass("bypass") + .password("password") + .username("username") + .build() + ) + .userDataDir("userDataDir") + .viewport( + SessionStartParams.Browser.LaunchOptions.Viewport.builder() + .height(0.0) + .width(0.0) + .build() + ) + .build() + ) + .type(SessionStartParams.Browser.Type.LOCAL) + .build() + ) + .browserbaseSessionCreateParams( + SessionStartParams.BrowserbaseSessionCreateParams.builder() + .browserSettings( + SessionStartParams.BrowserbaseSessionCreateParams.BrowserSettings.builder() + .advancedStealth(true) + .blockAds(true) + .context( + SessionStartParams.BrowserbaseSessionCreateParams.BrowserSettings + .Context + .builder() + .id("id") + .persist(true) + .build() + ) + .extensionId("extensionId") + .fingerprint( + SessionStartParams.BrowserbaseSessionCreateParams.BrowserSettings + .Fingerprint + .builder() + .addBrowser( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .Browser + .CHROME + ) + .addDevice( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .Device + .DESKTOP + ) + .httpVersion( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .HttpVersion + ._1 + ) + .addLocale("string") + .addOperatingSystem( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .OperatingSystem + .ANDROID + ) + .screen( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .Screen + .builder() + .maxHeight(0.0) + .maxWidth(0.0) + .minHeight(0.0) + .minWidth(0.0) + .build() + ) + .build() + ) + .logSession(true) + .recordSession(true) + .solveCaptchas(true) + .viewport( + SessionStartParams.BrowserbaseSessionCreateParams.BrowserSettings + .Viewport + .builder() + .height(0.0) + .width(0.0) + .build() + ) + .build() + ) + .extensionId("extensionId") + .keepAlive(true) + .projectId("projectId") + .proxies(true) + .region(SessionStartParams.BrowserbaseSessionCreateParams.Region.US_WEST_2) + .timeout(0.0) + .userMetadata( + SessionStartParams.BrowserbaseSessionCreateParams.UserMetadata.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) + .build() + ) + .browserbaseSessionId("browserbaseSessionID") + .debugDom(true) + .domSettleTimeoutMs(5000.0) + .experimental(true) + .selfHeal(true) + .systemPrompt("systemPrompt") + .verbose(SessionStartParams.Verbose._1) + .waitForCaptchaSolves(true) .build() } @@ -24,21 +162,170 @@ internal class SessionStartParamsTest { fun headers() { val params = SessionStartParams.builder() - .xLanguage(JsonValue.from(mapOf())) - .xSdkVersion(JsonValue.from(mapOf())) - .xSentAt(JsonValue.from(mapOf())) - .xStreamResponse(JsonValue.from(mapOf())) - .body(JsonValue.from(mapOf())) + .xLanguage(SessionStartParams.XLanguage.TYPESCRIPT) + .xSdkVersion("3.0.6") + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) + .xStreamResponse(SessionStartParams.XStreamResponse.TRUE) + .modelName("gpt-4o") + .actTimeoutMs(30000.0) + .browser( + SessionStartParams.Browser.builder() + .cdpUrl("ws://localhost:9222") + .launchOptions( + SessionStartParams.Browser.LaunchOptions.builder() + .acceptDownloads(true) + .addArg("string") + .cdpUrl("cdpUrl") + .chromiumSandbox(true) + .connectTimeoutMs(0.0) + .deviceScaleFactor(0.0) + .devtools(true) + .downloadsPath("downloadsPath") + .executablePath("executablePath") + .hasTouch(true) + .headless(true) + .ignoreDefaultArgs(true) + .ignoreHttpsErrors(true) + .locale("locale") + .preserveUserDataDir(true) + .proxy( + SessionStartParams.Browser.LaunchOptions.Proxy.builder() + .server("server") + .bypass("bypass") + .password("password") + .username("username") + .build() + ) + .userDataDir("userDataDir") + .viewport( + SessionStartParams.Browser.LaunchOptions.Viewport.builder() + .height(0.0) + .width(0.0) + .build() + ) + .build() + ) + .type(SessionStartParams.Browser.Type.LOCAL) + .build() + ) + .browserbaseSessionCreateParams( + SessionStartParams.BrowserbaseSessionCreateParams.builder() + .browserSettings( + SessionStartParams.BrowserbaseSessionCreateParams.BrowserSettings + .builder() + .advancedStealth(true) + .blockAds(true) + .context( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .Context + .builder() + .id("id") + .persist(true) + .build() + ) + .extensionId("extensionId") + .fingerprint( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .builder() + .addBrowser( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .Browser + .CHROME + ) + .addDevice( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .Device + .DESKTOP + ) + .httpVersion( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .HttpVersion + ._1 + ) + .addLocale("string") + .addOperatingSystem( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .OperatingSystem + .ANDROID + ) + .screen( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .Screen + .builder() + .maxHeight(0.0) + .maxWidth(0.0) + .minHeight(0.0) + .minWidth(0.0) + .build() + ) + .build() + ) + .logSession(true) + .recordSession(true) + .solveCaptchas(true) + .viewport( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .Viewport + .builder() + .height(0.0) + .width(0.0) + .build() + ) + .build() + ) + .extensionId("extensionId") + .keepAlive(true) + .projectId("projectId") + .proxies(true) + .region(SessionStartParams.BrowserbaseSessionCreateParams.Region.US_WEST_2) + .timeout(0.0) + .userMetadata( + SessionStartParams.BrowserbaseSessionCreateParams.UserMetadata.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) + .build() + ) + .browserbaseSessionId("browserbaseSessionID") + .debugDom(true) + .domSettleTimeoutMs(5000.0) + .experimental(true) + .selfHeal(true) + .systemPrompt("systemPrompt") + .verbose(SessionStartParams.Verbose._1) + .waitForCaptchaSolves(true) .build() val headers = params._headers() - assertThat(headers).isEqualTo(Headers.builder().build()) + assertThat(headers) + .isEqualTo( + Headers.builder() + .put("x-language", "typescript") + .put("x-sdk-version", "3.0.6") + .put("x-sent-at", "2025-01-15T10:30:00.000Z") + .put("x-stream-response", "true") + .build() + ) } @Test fun headersWithoutOptionalFields() { - val params = SessionStartParams.builder().build() + val params = SessionStartParams.builder().modelName("gpt-4o").build() val headers = params._headers() @@ -49,22 +336,304 @@ internal class SessionStartParamsTest { fun body() { val params = SessionStartParams.builder() - .xLanguage(JsonValue.from(mapOf())) - .xSdkVersion(JsonValue.from(mapOf())) - .xSentAt(JsonValue.from(mapOf())) - .xStreamResponse(JsonValue.from(mapOf())) - .body(JsonValue.from(mapOf())) + .xLanguage(SessionStartParams.XLanguage.TYPESCRIPT) + .xSdkVersion("3.0.6") + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) + .xStreamResponse(SessionStartParams.XStreamResponse.TRUE) + .modelName("gpt-4o") + .actTimeoutMs(30000.0) + .browser( + SessionStartParams.Browser.builder() + .cdpUrl("ws://localhost:9222") + .launchOptions( + SessionStartParams.Browser.LaunchOptions.builder() + .acceptDownloads(true) + .addArg("string") + .cdpUrl("cdpUrl") + .chromiumSandbox(true) + .connectTimeoutMs(0.0) + .deviceScaleFactor(0.0) + .devtools(true) + .downloadsPath("downloadsPath") + .executablePath("executablePath") + .hasTouch(true) + .headless(true) + .ignoreDefaultArgs(true) + .ignoreHttpsErrors(true) + .locale("locale") + .preserveUserDataDir(true) + .proxy( + SessionStartParams.Browser.LaunchOptions.Proxy.builder() + .server("server") + .bypass("bypass") + .password("password") + .username("username") + .build() + ) + .userDataDir("userDataDir") + .viewport( + SessionStartParams.Browser.LaunchOptions.Viewport.builder() + .height(0.0) + .width(0.0) + .build() + ) + .build() + ) + .type(SessionStartParams.Browser.Type.LOCAL) + .build() + ) + .browserbaseSessionCreateParams( + SessionStartParams.BrowserbaseSessionCreateParams.builder() + .browserSettings( + SessionStartParams.BrowserbaseSessionCreateParams.BrowserSettings + .builder() + .advancedStealth(true) + .blockAds(true) + .context( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .Context + .builder() + .id("id") + .persist(true) + .build() + ) + .extensionId("extensionId") + .fingerprint( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .builder() + .addBrowser( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .Browser + .CHROME + ) + .addDevice( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .Device + .DESKTOP + ) + .httpVersion( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .HttpVersion + ._1 + ) + .addLocale("string") + .addOperatingSystem( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .OperatingSystem + .ANDROID + ) + .screen( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .Screen + .builder() + .maxHeight(0.0) + .maxWidth(0.0) + .minHeight(0.0) + .minWidth(0.0) + .build() + ) + .build() + ) + .logSession(true) + .recordSession(true) + .solveCaptchas(true) + .viewport( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .Viewport + .builder() + .height(0.0) + .width(0.0) + .build() + ) + .build() + ) + .extensionId("extensionId") + .keepAlive(true) + .projectId("projectId") + .proxies(true) + .region(SessionStartParams.BrowserbaseSessionCreateParams.Region.US_WEST_2) + .timeout(0.0) + .userMetadata( + SessionStartParams.BrowserbaseSessionCreateParams.UserMetadata.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) + .build() + ) + .browserbaseSessionId("browserbaseSessionID") + .debugDom(true) + .domSettleTimeoutMs(5000.0) + .experimental(true) + .selfHeal(true) + .systemPrompt("systemPrompt") + .verbose(SessionStartParams.Verbose._1) + .waitForCaptchaSolves(true) .build() val body = params._body() - assertThat(body).isEqualTo(JsonValue.from(mapOf())) + assertThat(body.modelName()).isEqualTo("gpt-4o") + assertThat(body.actTimeoutMs()).contains(30000.0) + assertThat(body.browser()) + .contains( + SessionStartParams.Browser.builder() + .cdpUrl("ws://localhost:9222") + .launchOptions( + SessionStartParams.Browser.LaunchOptions.builder() + .acceptDownloads(true) + .addArg("string") + .cdpUrl("cdpUrl") + .chromiumSandbox(true) + .connectTimeoutMs(0.0) + .deviceScaleFactor(0.0) + .devtools(true) + .downloadsPath("downloadsPath") + .executablePath("executablePath") + .hasTouch(true) + .headless(true) + .ignoreDefaultArgs(true) + .ignoreHttpsErrors(true) + .locale("locale") + .preserveUserDataDir(true) + .proxy( + SessionStartParams.Browser.LaunchOptions.Proxy.builder() + .server("server") + .bypass("bypass") + .password("password") + .username("username") + .build() + ) + .userDataDir("userDataDir") + .viewport( + SessionStartParams.Browser.LaunchOptions.Viewport.builder() + .height(0.0) + .width(0.0) + .build() + ) + .build() + ) + .type(SessionStartParams.Browser.Type.LOCAL) + .build() + ) + assertThat(body.browserbaseSessionCreateParams()) + .contains( + SessionStartParams.BrowserbaseSessionCreateParams.builder() + .browserSettings( + SessionStartParams.BrowserbaseSessionCreateParams.BrowserSettings.builder() + .advancedStealth(true) + .blockAds(true) + .context( + SessionStartParams.BrowserbaseSessionCreateParams.BrowserSettings + .Context + .builder() + .id("id") + .persist(true) + .build() + ) + .extensionId("extensionId") + .fingerprint( + SessionStartParams.BrowserbaseSessionCreateParams.BrowserSettings + .Fingerprint + .builder() + .addBrowser( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .Browser + .CHROME + ) + .addDevice( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .Device + .DESKTOP + ) + .httpVersion( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .HttpVersion + ._1 + ) + .addLocale("string") + .addOperatingSystem( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .OperatingSystem + .ANDROID + ) + .screen( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .Screen + .builder() + .maxHeight(0.0) + .maxWidth(0.0) + .minHeight(0.0) + .minWidth(0.0) + .build() + ) + .build() + ) + .logSession(true) + .recordSession(true) + .solveCaptchas(true) + .viewport( + SessionStartParams.BrowserbaseSessionCreateParams.BrowserSettings + .Viewport + .builder() + .height(0.0) + .width(0.0) + .build() + ) + .build() + ) + .extensionId("extensionId") + .keepAlive(true) + .projectId("projectId") + .proxies(true) + .region(SessionStartParams.BrowserbaseSessionCreateParams.Region.US_WEST_2) + .timeout(0.0) + .userMetadata( + SessionStartParams.BrowserbaseSessionCreateParams.UserMetadata.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) + .build() + ) + assertThat(body.browserbaseSessionId()).contains("browserbaseSessionID") + assertThat(body.debugDom()).contains(true) + assertThat(body.domSettleTimeoutMs()).contains(5000.0) + assertThat(body.experimental()).contains(true) + assertThat(body.selfHeal()).contains(true) + assertThat(body.systemPrompt()).contains("systemPrompt") + assertThat(body.verbose()).contains(SessionStartParams.Verbose._1) + assertThat(body.waitForCaptchaSolves()).contains(true) } @Test fun bodyWithoutOptionalFields() { - val params = SessionStartParams.builder().build() + val params = SessionStartParams.builder().modelName("gpt-4o").build() val body = params._body() + + assertThat(body.modelName()).isEqualTo("gpt-4o") } } diff --git a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionStartResponseTest.kt b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionStartResponseTest.kt index 51616d7..717d6d6 100644 --- a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionStartResponseTest.kt +++ b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionStartResponseTest.kt @@ -11,13 +11,40 @@ internal class SessionStartResponseTest { @Test fun create() { - val sessionStartResponse = SessionStartResponse.builder().build() + val sessionStartResponse = + SessionStartResponse.builder() + .data( + SessionStartResponse.Data.builder() + .available(true) + .sessionId("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") + .build() + ) + .success(SessionStartResponse.Success.TRUE) + .build() + + assertThat(sessionStartResponse.data()) + .isEqualTo( + SessionStartResponse.Data.builder() + .available(true) + .sessionId("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") + .build() + ) + assertThat(sessionStartResponse.success()).isEqualTo(SessionStartResponse.Success.TRUE) } @Test fun roundtrip() { val jsonMapper = jsonMapper() - val sessionStartResponse = SessionStartResponse.builder().build() + val sessionStartResponse = + SessionStartResponse.builder() + .data( + SessionStartResponse.Data.builder() + .available(true) + .sessionId("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") + .build() + ) + .success(SessionStartResponse.Success.TRUE) + .build() val roundtrippedSessionStartResponse = jsonMapper.readValue( diff --git a/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/ErrorHandlingTest.kt b/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/ErrorHandlingTest.kt index ccf1223..32b00d3 100644 --- a/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/ErrorHandlingTest.kt +++ b/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/ErrorHandlingTest.kt @@ -16,13 +16,14 @@ import com.browserbase.api.errors.StagehandException import com.browserbase.api.errors.UnauthorizedException import com.browserbase.api.errors.UnexpectedStatusCodeException import com.browserbase.api.errors.UnprocessableEntityException -import com.browserbase.api.models.sessions.SessionStartParams +import com.browserbase.api.models.sessions.SessionActParams import com.github.tomakehurst.wiremock.client.WireMock.anyUrl import com.github.tomakehurst.wiremock.client.WireMock.post import com.github.tomakehurst.wiremock.client.WireMock.status import com.github.tomakehurst.wiremock.client.WireMock.stubFor import com.github.tomakehurst.wiremock.junit5.WireMockRuntimeInfo import com.github.tomakehurst.wiremock.junit5.WireMockTest +import java.time.OffsetDateTime import org.assertj.core.api.Assertions.assertThat import org.assertj.core.api.Assertions.entry import org.junit.jupiter.api.BeforeEach @@ -61,7 +62,7 @@ internal class ErrorHandlingTest { } @Test - fun sessionsStart400() { + fun sessionsAct400() { val sessionService = client.sessions() stubFor( post(anyUrl()) @@ -72,13 +73,29 @@ internal class ErrorHandlingTest { val e = assertThrows { - sessionService.start( - SessionStartParams.builder() - .xLanguage(JsonValue.from(mapOf())) - .xSdkVersion(JsonValue.from(mapOf())) - .xSentAt(JsonValue.from(mapOf())) - .xStreamResponse(JsonValue.from(mapOf())) - .body(JsonValue.from(mapOf())) + sessionService.act( + SessionActParams.builder() + .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") + .xLanguage(SessionActParams.XLanguage.TYPESCRIPT) + .xSdkVersion("3.0.6") + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) + .xStreamResponse(SessionActParams.XStreamResponse.TRUE) + .input("Click the login button") + .frameId("frameId") + .options( + SessionActParams.Options.builder() + .model("string") + .timeout(30000.0) + .variables( + SessionActParams.Options.Variables.builder() + .putAdditionalProperty( + "username", + JsonValue.from("john_doe"), + ) + .build() + ) + .build() + ) .build() ) } @@ -89,7 +106,7 @@ internal class ErrorHandlingTest { } @Test - fun sessionsStart400WithRawResponse() { + fun sessionsAct400WithRawResponse() { val sessionService = client.sessions().withRawResponse() stubFor( post(anyUrl()) @@ -100,13 +117,29 @@ internal class ErrorHandlingTest { val e = assertThrows { - sessionService.start( - SessionStartParams.builder() - .xLanguage(JsonValue.from(mapOf())) - .xSdkVersion(JsonValue.from(mapOf())) - .xSentAt(JsonValue.from(mapOf())) - .xStreamResponse(JsonValue.from(mapOf())) - .body(JsonValue.from(mapOf())) + sessionService.act( + SessionActParams.builder() + .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") + .xLanguage(SessionActParams.XLanguage.TYPESCRIPT) + .xSdkVersion("3.0.6") + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) + .xStreamResponse(SessionActParams.XStreamResponse.TRUE) + .input("Click the login button") + .frameId("frameId") + .options( + SessionActParams.Options.builder() + .model("string") + .timeout(30000.0) + .variables( + SessionActParams.Options.Variables.builder() + .putAdditionalProperty( + "username", + JsonValue.from("john_doe"), + ) + .build() + ) + .build() + ) .build() ) } @@ -117,7 +150,7 @@ internal class ErrorHandlingTest { } @Test - fun sessionsStart401() { + fun sessionsAct401() { val sessionService = client.sessions() stubFor( post(anyUrl()) @@ -128,13 +161,29 @@ internal class ErrorHandlingTest { val e = assertThrows { - sessionService.start( - SessionStartParams.builder() - .xLanguage(JsonValue.from(mapOf())) - .xSdkVersion(JsonValue.from(mapOf())) - .xSentAt(JsonValue.from(mapOf())) - .xStreamResponse(JsonValue.from(mapOf())) - .body(JsonValue.from(mapOf())) + sessionService.act( + SessionActParams.builder() + .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") + .xLanguage(SessionActParams.XLanguage.TYPESCRIPT) + .xSdkVersion("3.0.6") + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) + .xStreamResponse(SessionActParams.XStreamResponse.TRUE) + .input("Click the login button") + .frameId("frameId") + .options( + SessionActParams.Options.builder() + .model("string") + .timeout(30000.0) + .variables( + SessionActParams.Options.Variables.builder() + .putAdditionalProperty( + "username", + JsonValue.from("john_doe"), + ) + .build() + ) + .build() + ) .build() ) } @@ -145,7 +194,7 @@ internal class ErrorHandlingTest { } @Test - fun sessionsStart401WithRawResponse() { + fun sessionsAct401WithRawResponse() { val sessionService = client.sessions().withRawResponse() stubFor( post(anyUrl()) @@ -156,13 +205,29 @@ internal class ErrorHandlingTest { val e = assertThrows { - sessionService.start( - SessionStartParams.builder() - .xLanguage(JsonValue.from(mapOf())) - .xSdkVersion(JsonValue.from(mapOf())) - .xSentAt(JsonValue.from(mapOf())) - .xStreamResponse(JsonValue.from(mapOf())) - .body(JsonValue.from(mapOf())) + sessionService.act( + SessionActParams.builder() + .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") + .xLanguage(SessionActParams.XLanguage.TYPESCRIPT) + .xSdkVersion("3.0.6") + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) + .xStreamResponse(SessionActParams.XStreamResponse.TRUE) + .input("Click the login button") + .frameId("frameId") + .options( + SessionActParams.Options.builder() + .model("string") + .timeout(30000.0) + .variables( + SessionActParams.Options.Variables.builder() + .putAdditionalProperty( + "username", + JsonValue.from("john_doe"), + ) + .build() + ) + .build() + ) .build() ) } @@ -173,7 +238,7 @@ internal class ErrorHandlingTest { } @Test - fun sessionsStart403() { + fun sessionsAct403() { val sessionService = client.sessions() stubFor( post(anyUrl()) @@ -184,13 +249,29 @@ internal class ErrorHandlingTest { val e = assertThrows { - sessionService.start( - SessionStartParams.builder() - .xLanguage(JsonValue.from(mapOf())) - .xSdkVersion(JsonValue.from(mapOf())) - .xSentAt(JsonValue.from(mapOf())) - .xStreamResponse(JsonValue.from(mapOf())) - .body(JsonValue.from(mapOf())) + sessionService.act( + SessionActParams.builder() + .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") + .xLanguage(SessionActParams.XLanguage.TYPESCRIPT) + .xSdkVersion("3.0.6") + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) + .xStreamResponse(SessionActParams.XStreamResponse.TRUE) + .input("Click the login button") + .frameId("frameId") + .options( + SessionActParams.Options.builder() + .model("string") + .timeout(30000.0) + .variables( + SessionActParams.Options.Variables.builder() + .putAdditionalProperty( + "username", + JsonValue.from("john_doe"), + ) + .build() + ) + .build() + ) .build() ) } @@ -201,7 +282,7 @@ internal class ErrorHandlingTest { } @Test - fun sessionsStart403WithRawResponse() { + fun sessionsAct403WithRawResponse() { val sessionService = client.sessions().withRawResponse() stubFor( post(anyUrl()) @@ -212,13 +293,29 @@ internal class ErrorHandlingTest { val e = assertThrows { - sessionService.start( - SessionStartParams.builder() - .xLanguage(JsonValue.from(mapOf())) - .xSdkVersion(JsonValue.from(mapOf())) - .xSentAt(JsonValue.from(mapOf())) - .xStreamResponse(JsonValue.from(mapOf())) - .body(JsonValue.from(mapOf())) + sessionService.act( + SessionActParams.builder() + .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") + .xLanguage(SessionActParams.XLanguage.TYPESCRIPT) + .xSdkVersion("3.0.6") + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) + .xStreamResponse(SessionActParams.XStreamResponse.TRUE) + .input("Click the login button") + .frameId("frameId") + .options( + SessionActParams.Options.builder() + .model("string") + .timeout(30000.0) + .variables( + SessionActParams.Options.Variables.builder() + .putAdditionalProperty( + "username", + JsonValue.from("john_doe"), + ) + .build() + ) + .build() + ) .build() ) } @@ -229,7 +326,7 @@ internal class ErrorHandlingTest { } @Test - fun sessionsStart404() { + fun sessionsAct404() { val sessionService = client.sessions() stubFor( post(anyUrl()) @@ -240,13 +337,29 @@ internal class ErrorHandlingTest { val e = assertThrows { - sessionService.start( - SessionStartParams.builder() - .xLanguage(JsonValue.from(mapOf())) - .xSdkVersion(JsonValue.from(mapOf())) - .xSentAt(JsonValue.from(mapOf())) - .xStreamResponse(JsonValue.from(mapOf())) - .body(JsonValue.from(mapOf())) + sessionService.act( + SessionActParams.builder() + .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") + .xLanguage(SessionActParams.XLanguage.TYPESCRIPT) + .xSdkVersion("3.0.6") + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) + .xStreamResponse(SessionActParams.XStreamResponse.TRUE) + .input("Click the login button") + .frameId("frameId") + .options( + SessionActParams.Options.builder() + .model("string") + .timeout(30000.0) + .variables( + SessionActParams.Options.Variables.builder() + .putAdditionalProperty( + "username", + JsonValue.from("john_doe"), + ) + .build() + ) + .build() + ) .build() ) } @@ -257,7 +370,7 @@ internal class ErrorHandlingTest { } @Test - fun sessionsStart404WithRawResponse() { + fun sessionsAct404WithRawResponse() { val sessionService = client.sessions().withRawResponse() stubFor( post(anyUrl()) @@ -268,13 +381,29 @@ internal class ErrorHandlingTest { val e = assertThrows { - sessionService.start( - SessionStartParams.builder() - .xLanguage(JsonValue.from(mapOf())) - .xSdkVersion(JsonValue.from(mapOf())) - .xSentAt(JsonValue.from(mapOf())) - .xStreamResponse(JsonValue.from(mapOf())) - .body(JsonValue.from(mapOf())) + sessionService.act( + SessionActParams.builder() + .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") + .xLanguage(SessionActParams.XLanguage.TYPESCRIPT) + .xSdkVersion("3.0.6") + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) + .xStreamResponse(SessionActParams.XStreamResponse.TRUE) + .input("Click the login button") + .frameId("frameId") + .options( + SessionActParams.Options.builder() + .model("string") + .timeout(30000.0) + .variables( + SessionActParams.Options.Variables.builder() + .putAdditionalProperty( + "username", + JsonValue.from("john_doe"), + ) + .build() + ) + .build() + ) .build() ) } @@ -285,7 +414,7 @@ internal class ErrorHandlingTest { } @Test - fun sessionsStart422() { + fun sessionsAct422() { val sessionService = client.sessions() stubFor( post(anyUrl()) @@ -296,13 +425,29 @@ internal class ErrorHandlingTest { val e = assertThrows { - sessionService.start( - SessionStartParams.builder() - .xLanguage(JsonValue.from(mapOf())) - .xSdkVersion(JsonValue.from(mapOf())) - .xSentAt(JsonValue.from(mapOf())) - .xStreamResponse(JsonValue.from(mapOf())) - .body(JsonValue.from(mapOf())) + sessionService.act( + SessionActParams.builder() + .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") + .xLanguage(SessionActParams.XLanguage.TYPESCRIPT) + .xSdkVersion("3.0.6") + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) + .xStreamResponse(SessionActParams.XStreamResponse.TRUE) + .input("Click the login button") + .frameId("frameId") + .options( + SessionActParams.Options.builder() + .model("string") + .timeout(30000.0) + .variables( + SessionActParams.Options.Variables.builder() + .putAdditionalProperty( + "username", + JsonValue.from("john_doe"), + ) + .build() + ) + .build() + ) .build() ) } @@ -313,7 +458,7 @@ internal class ErrorHandlingTest { } @Test - fun sessionsStart422WithRawResponse() { + fun sessionsAct422WithRawResponse() { val sessionService = client.sessions().withRawResponse() stubFor( post(anyUrl()) @@ -324,13 +469,29 @@ internal class ErrorHandlingTest { val e = assertThrows { - sessionService.start( - SessionStartParams.builder() - .xLanguage(JsonValue.from(mapOf())) - .xSdkVersion(JsonValue.from(mapOf())) - .xSentAt(JsonValue.from(mapOf())) - .xStreamResponse(JsonValue.from(mapOf())) - .body(JsonValue.from(mapOf())) + sessionService.act( + SessionActParams.builder() + .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") + .xLanguage(SessionActParams.XLanguage.TYPESCRIPT) + .xSdkVersion("3.0.6") + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) + .xStreamResponse(SessionActParams.XStreamResponse.TRUE) + .input("Click the login button") + .frameId("frameId") + .options( + SessionActParams.Options.builder() + .model("string") + .timeout(30000.0) + .variables( + SessionActParams.Options.Variables.builder() + .putAdditionalProperty( + "username", + JsonValue.from("john_doe"), + ) + .build() + ) + .build() + ) .build() ) } @@ -341,7 +502,7 @@ internal class ErrorHandlingTest { } @Test - fun sessionsStart429() { + fun sessionsAct429() { val sessionService = client.sessions() stubFor( post(anyUrl()) @@ -352,13 +513,29 @@ internal class ErrorHandlingTest { val e = assertThrows { - sessionService.start( - SessionStartParams.builder() - .xLanguage(JsonValue.from(mapOf())) - .xSdkVersion(JsonValue.from(mapOf())) - .xSentAt(JsonValue.from(mapOf())) - .xStreamResponse(JsonValue.from(mapOf())) - .body(JsonValue.from(mapOf())) + sessionService.act( + SessionActParams.builder() + .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") + .xLanguage(SessionActParams.XLanguage.TYPESCRIPT) + .xSdkVersion("3.0.6") + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) + .xStreamResponse(SessionActParams.XStreamResponse.TRUE) + .input("Click the login button") + .frameId("frameId") + .options( + SessionActParams.Options.builder() + .model("string") + .timeout(30000.0) + .variables( + SessionActParams.Options.Variables.builder() + .putAdditionalProperty( + "username", + JsonValue.from("john_doe"), + ) + .build() + ) + .build() + ) .build() ) } @@ -369,7 +546,7 @@ internal class ErrorHandlingTest { } @Test - fun sessionsStart429WithRawResponse() { + fun sessionsAct429WithRawResponse() { val sessionService = client.sessions().withRawResponse() stubFor( post(anyUrl()) @@ -380,13 +557,29 @@ internal class ErrorHandlingTest { val e = assertThrows { - sessionService.start( - SessionStartParams.builder() - .xLanguage(JsonValue.from(mapOf())) - .xSdkVersion(JsonValue.from(mapOf())) - .xSentAt(JsonValue.from(mapOf())) - .xStreamResponse(JsonValue.from(mapOf())) - .body(JsonValue.from(mapOf())) + sessionService.act( + SessionActParams.builder() + .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") + .xLanguage(SessionActParams.XLanguage.TYPESCRIPT) + .xSdkVersion("3.0.6") + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) + .xStreamResponse(SessionActParams.XStreamResponse.TRUE) + .input("Click the login button") + .frameId("frameId") + .options( + SessionActParams.Options.builder() + .model("string") + .timeout(30000.0) + .variables( + SessionActParams.Options.Variables.builder() + .putAdditionalProperty( + "username", + JsonValue.from("john_doe"), + ) + .build() + ) + .build() + ) .build() ) } @@ -397,7 +590,7 @@ internal class ErrorHandlingTest { } @Test - fun sessionsStart500() { + fun sessionsAct500() { val sessionService = client.sessions() stubFor( post(anyUrl()) @@ -408,13 +601,29 @@ internal class ErrorHandlingTest { val e = assertThrows { - sessionService.start( - SessionStartParams.builder() - .xLanguage(JsonValue.from(mapOf())) - .xSdkVersion(JsonValue.from(mapOf())) - .xSentAt(JsonValue.from(mapOf())) - .xStreamResponse(JsonValue.from(mapOf())) - .body(JsonValue.from(mapOf())) + sessionService.act( + SessionActParams.builder() + .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") + .xLanguage(SessionActParams.XLanguage.TYPESCRIPT) + .xSdkVersion("3.0.6") + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) + .xStreamResponse(SessionActParams.XStreamResponse.TRUE) + .input("Click the login button") + .frameId("frameId") + .options( + SessionActParams.Options.builder() + .model("string") + .timeout(30000.0) + .variables( + SessionActParams.Options.Variables.builder() + .putAdditionalProperty( + "username", + JsonValue.from("john_doe"), + ) + .build() + ) + .build() + ) .build() ) } @@ -425,7 +634,7 @@ internal class ErrorHandlingTest { } @Test - fun sessionsStart500WithRawResponse() { + fun sessionsAct500WithRawResponse() { val sessionService = client.sessions().withRawResponse() stubFor( post(anyUrl()) @@ -436,13 +645,29 @@ internal class ErrorHandlingTest { val e = assertThrows { - sessionService.start( - SessionStartParams.builder() - .xLanguage(JsonValue.from(mapOf())) - .xSdkVersion(JsonValue.from(mapOf())) - .xSentAt(JsonValue.from(mapOf())) - .xStreamResponse(JsonValue.from(mapOf())) - .body(JsonValue.from(mapOf())) + sessionService.act( + SessionActParams.builder() + .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") + .xLanguage(SessionActParams.XLanguage.TYPESCRIPT) + .xSdkVersion("3.0.6") + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) + .xStreamResponse(SessionActParams.XStreamResponse.TRUE) + .input("Click the login button") + .frameId("frameId") + .options( + SessionActParams.Options.builder() + .model("string") + .timeout(30000.0) + .variables( + SessionActParams.Options.Variables.builder() + .putAdditionalProperty( + "username", + JsonValue.from("john_doe"), + ) + .build() + ) + .build() + ) .build() ) } @@ -453,7 +678,7 @@ internal class ErrorHandlingTest { } @Test - fun sessionsStart999() { + fun sessionsAct999() { val sessionService = client.sessions() stubFor( post(anyUrl()) @@ -464,13 +689,29 @@ internal class ErrorHandlingTest { val e = assertThrows { - sessionService.start( - SessionStartParams.builder() - .xLanguage(JsonValue.from(mapOf())) - .xSdkVersion(JsonValue.from(mapOf())) - .xSentAt(JsonValue.from(mapOf())) - .xStreamResponse(JsonValue.from(mapOf())) - .body(JsonValue.from(mapOf())) + sessionService.act( + SessionActParams.builder() + .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") + .xLanguage(SessionActParams.XLanguage.TYPESCRIPT) + .xSdkVersion("3.0.6") + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) + .xStreamResponse(SessionActParams.XStreamResponse.TRUE) + .input("Click the login button") + .frameId("frameId") + .options( + SessionActParams.Options.builder() + .model("string") + .timeout(30000.0) + .variables( + SessionActParams.Options.Variables.builder() + .putAdditionalProperty( + "username", + JsonValue.from("john_doe"), + ) + .build() + ) + .build() + ) .build() ) } @@ -481,7 +722,7 @@ internal class ErrorHandlingTest { } @Test - fun sessionsStart999WithRawResponse() { + fun sessionsAct999WithRawResponse() { val sessionService = client.sessions().withRawResponse() stubFor( post(anyUrl()) @@ -492,13 +733,29 @@ internal class ErrorHandlingTest { val e = assertThrows { - sessionService.start( - SessionStartParams.builder() - .xLanguage(JsonValue.from(mapOf())) - .xSdkVersion(JsonValue.from(mapOf())) - .xSentAt(JsonValue.from(mapOf())) - .xStreamResponse(JsonValue.from(mapOf())) - .body(JsonValue.from(mapOf())) + sessionService.act( + SessionActParams.builder() + .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") + .xLanguage(SessionActParams.XLanguage.TYPESCRIPT) + .xSdkVersion("3.0.6") + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) + .xStreamResponse(SessionActParams.XStreamResponse.TRUE) + .input("Click the login button") + .frameId("frameId") + .options( + SessionActParams.Options.builder() + .model("string") + .timeout(30000.0) + .variables( + SessionActParams.Options.Variables.builder() + .putAdditionalProperty( + "username", + JsonValue.from("john_doe"), + ) + .build() + ) + .build() + ) .build() ) } @@ -509,7 +766,7 @@ internal class ErrorHandlingTest { } @Test - fun sessionsStartInvalidJsonBody() { + fun sessionsActInvalidJsonBody() { val sessionService = client.sessions() stubFor( post(anyUrl()) @@ -518,13 +775,29 @@ internal class ErrorHandlingTest { val e = assertThrows { - sessionService.start( - SessionStartParams.builder() - .xLanguage(JsonValue.from(mapOf())) - .xSdkVersion(JsonValue.from(mapOf())) - .xSentAt(JsonValue.from(mapOf())) - .xStreamResponse(JsonValue.from(mapOf())) - .body(JsonValue.from(mapOf())) + sessionService.act( + SessionActParams.builder() + .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") + .xLanguage(SessionActParams.XLanguage.TYPESCRIPT) + .xSdkVersion("3.0.6") + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) + .xStreamResponse(SessionActParams.XStreamResponse.TRUE) + .input("Click the login button") + .frameId("frameId") + .options( + SessionActParams.Options.builder() + .model("string") + .timeout(30000.0) + .variables( + SessionActParams.Options.Variables.builder() + .putAdditionalProperty( + "username", + JsonValue.from("john_doe"), + ) + .build() + ) + .build() + ) .build() ) } diff --git a/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/ServiceParamsTest.kt b/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/ServiceParamsTest.kt index 8af7ae3..060d011 100644 --- a/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/ServiceParamsTest.kt +++ b/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/ServiceParamsTest.kt @@ -5,9 +5,10 @@ package com.browserbase.api.services import com.browserbase.api.client.StagehandClient import com.browserbase.api.client.okhttp.StagehandOkHttpClient import com.browserbase.api.core.JsonValue -import com.browserbase.api.models.sessions.SessionStartParams +import com.browserbase.api.models.sessions.SessionActParams import com.github.tomakehurst.wiremock.client.WireMock.anyUrl import com.github.tomakehurst.wiremock.client.WireMock.equalTo +import com.github.tomakehurst.wiremock.client.WireMock.matchingJsonPath import com.github.tomakehurst.wiremock.client.WireMock.ok import com.github.tomakehurst.wiremock.client.WireMock.post import com.github.tomakehurst.wiremock.client.WireMock.postRequestedFor @@ -15,6 +16,7 @@ import com.github.tomakehurst.wiremock.client.WireMock.stubFor import com.github.tomakehurst.wiremock.client.WireMock.verify import com.github.tomakehurst.wiremock.junit5.WireMockRuntimeInfo import com.github.tomakehurst.wiremock.junit5.WireMockTest +import java.time.OffsetDateTime import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Disabled import org.junit.jupiter.api.Test @@ -39,19 +41,33 @@ internal class ServiceParamsTest { @Disabled("Prism tests are disabled") @Test - fun start() { + fun act() { val sessionService = client.sessions() stubFor(post(anyUrl()).willReturn(ok("{}"))) - sessionService.start( - SessionStartParams.builder() - .xLanguage(JsonValue.from(mapOf())) - .xSdkVersion(JsonValue.from(mapOf())) - .xSentAt(JsonValue.from(mapOf())) - .xStreamResponse(JsonValue.from(mapOf())) - .body(JsonValue.from(mapOf())) + sessionService.act( + SessionActParams.builder() + .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") + .xLanguage(SessionActParams.XLanguage.TYPESCRIPT) + .xSdkVersion("3.0.6") + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) + .xStreamResponse(SessionActParams.XStreamResponse.TRUE) + .input("Click the login button") + .frameId("frameId") + .options( + SessionActParams.Options.builder() + .model("string") + .timeout(30000.0) + .variables( + SessionActParams.Options.Variables.builder() + .putAdditionalProperty("username", JsonValue.from("john_doe")) + .build() + ) + .build() + ) .putAdditionalHeader("Secret-Header", "42") .putAdditionalQueryParam("secret_query_param", "42") + .putAdditionalBodyProperty("secretProperty", JsonValue.from("42")) .build() ) @@ -59,6 +75,7 @@ internal class ServiceParamsTest { postRequestedFor(anyUrl()) .withHeader("Secret-Header", equalTo("42")) .withQueryParam("secret_query_param", equalTo("42")) + .withRequestBody(matchingJsonPath("$.secretProperty", equalTo("42"))) ) } } diff --git a/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/async/SessionServiceAsyncTest.kt b/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/async/SessionServiceAsyncTest.kt index dba84aa..0011f6f 100644 --- a/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/async/SessionServiceAsyncTest.kt +++ b/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/async/SessionServiceAsyncTest.kt @@ -7,11 +7,12 @@ import com.browserbase.api.client.okhttp.StagehandOkHttpClientAsync import com.browserbase.api.core.JsonValue import com.browserbase.api.models.sessions.SessionActParams import com.browserbase.api.models.sessions.SessionEndParams -import com.browserbase.api.models.sessions.SessionExecuteAgentParams +import com.browserbase.api.models.sessions.SessionExecuteParams import com.browserbase.api.models.sessions.SessionExtractParams import com.browserbase.api.models.sessions.SessionNavigateParams import com.browserbase.api.models.sessions.SessionObserveParams import com.browserbase.api.models.sessions.SessionStartParams +import java.time.OffsetDateTime import org.junit.jupiter.api.Disabled import org.junit.jupiter.api.Test import org.junit.jupiter.api.extension.ExtendWith @@ -34,12 +35,24 @@ internal class SessionServiceAsyncTest { val responseFuture = sessionServiceAsync.act( SessionActParams.builder() - .id(JsonValue.from(mapOf())) - .xLanguage(JsonValue.from(mapOf())) - .xSdkVersion(JsonValue.from(mapOf())) - .xSentAt(JsonValue.from(mapOf())) - .xStreamResponse(JsonValue.from(mapOf())) - .body(JsonValue.from(mapOf())) + .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") + .xLanguage(SessionActParams.XLanguage.TYPESCRIPT) + .xSdkVersion("3.0.6") + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) + .xStreamResponse(SessionActParams.XStreamResponse.TRUE) + .input("Click the login button") + .frameId("frameId") + .options( + SessionActParams.Options.builder() + .model("string") + .timeout(30000.0) + .variables( + SessionActParams.Options.Variables.builder() + .putAdditionalProperty("username", JsonValue.from("john_doe")) + .build() + ) + .build() + ) .build() ) @@ -62,11 +75,11 @@ internal class SessionServiceAsyncTest { val responseFuture = sessionServiceAsync.end( SessionEndParams.builder() - .id(JsonValue.from(mapOf())) - .xLanguage(JsonValue.from(mapOf())) - .xSdkVersion(JsonValue.from(mapOf())) - .xSentAt(JsonValue.from(mapOf())) - .xStreamResponse(JsonValue.from(mapOf())) + .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") + .xLanguage(SessionEndParams.XLanguage.TYPESCRIPT) + .xSdkVersion("3.0.6") + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) + .xStreamResponse(SessionEndParams.XStreamResponse.TRUE) .build() ) @@ -76,7 +89,7 @@ internal class SessionServiceAsyncTest { @Disabled("Prism tests are disabled") @Test - fun executeAgent() { + fun execute() { val client = StagehandOkHttpClientAsync.builder() .baseUrl(TestServerExtension.BASE_URL) @@ -87,14 +100,30 @@ internal class SessionServiceAsyncTest { val sessionServiceAsync = client.sessions() val responseFuture = - sessionServiceAsync.executeAgent( - SessionExecuteAgentParams.builder() - .id(JsonValue.from(mapOf())) - .xLanguage(JsonValue.from(mapOf())) - .xSdkVersion(JsonValue.from(mapOf())) - .xSentAt(JsonValue.from(mapOf())) - .xStreamResponse(JsonValue.from(mapOf())) - .body(JsonValue.from(mapOf())) + sessionServiceAsync.execute( + SessionExecuteParams.builder() + .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") + .xLanguage(SessionExecuteParams.XLanguage.TYPESCRIPT) + .xSdkVersion("3.0.6") + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) + .xStreamResponse(SessionExecuteParams.XStreamResponse.TRUE) + .agentConfig( + SessionExecuteParams.AgentConfig.builder() + .cua(true) + .model("string") + .systemPrompt("systemPrompt") + .build() + ) + .executeOptions( + SessionExecuteParams.ExecuteOptions.builder() + .instruction( + "Log in with username 'demo' and password 'test123', then navigate to settings" + ) + .highlightCursor(true) + .maxSteps(20.0) + .build() + ) + .frameId("frameId") .build() ) @@ -117,12 +146,25 @@ internal class SessionServiceAsyncTest { val responseFuture = sessionServiceAsync.extract( SessionExtractParams.builder() - .id(JsonValue.from(mapOf())) - .xLanguage(JsonValue.from(mapOf())) - .xSdkVersion(JsonValue.from(mapOf())) - .xSentAt(JsonValue.from(mapOf())) - .xStreamResponse(JsonValue.from(mapOf())) - .body(JsonValue.from(mapOf())) + .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") + .xLanguage(SessionExtractParams.XLanguage.TYPESCRIPT) + .xSdkVersion("3.0.6") + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) + .xStreamResponse(SessionExtractParams.XStreamResponse.TRUE) + .frameId("frameId") + .instruction("Extract all product names and prices from the page") + .options( + SessionExtractParams.Options.builder() + .model("string") + .selector("#main-content") + .timeout(30000.0) + .build() + ) + .schema( + SessionExtractParams.Schema.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) .build() ) @@ -145,12 +187,20 @@ internal class SessionServiceAsyncTest { val responseFuture = sessionServiceAsync.navigate( SessionNavigateParams.builder() - .id(JsonValue.from(mapOf())) - .xLanguage(JsonValue.from(mapOf())) - .xSdkVersion(JsonValue.from(mapOf())) - .xSentAt(JsonValue.from(mapOf())) - .xStreamResponse(JsonValue.from(mapOf())) - .body(JsonValue.from(mapOf())) + .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") + .xLanguage(SessionNavigateParams.XLanguage.TYPESCRIPT) + .xSdkVersion("3.0.6") + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) + .xStreamResponse(SessionNavigateParams.XStreamResponse.TRUE) + .url("https://example.com") + .frameId("frameId") + .options( + SessionNavigateParams.Options.builder() + .referer("referer") + .timeout(30000.0) + .waitUntil(SessionNavigateParams.Options.WaitUntil.NETWORKIDLE) + .build() + ) .build() ) @@ -173,12 +223,20 @@ internal class SessionServiceAsyncTest { val responseFuture = sessionServiceAsync.observe( SessionObserveParams.builder() - .id(JsonValue.from(mapOf())) - .xLanguage(JsonValue.from(mapOf())) - .xSdkVersion(JsonValue.from(mapOf())) - .xSentAt(JsonValue.from(mapOf())) - .xStreamResponse(JsonValue.from(mapOf())) - .body(JsonValue.from(mapOf())) + .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") + .xLanguage(SessionObserveParams.XLanguage.TYPESCRIPT) + .xSdkVersion("3.0.6") + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) + .xStreamResponse(SessionObserveParams.XStreamResponse.TRUE) + .frameId("frameId") + .instruction("Find all clickable navigation links") + .options( + SessionObserveParams.Options.builder() + .model("string") + .selector("nav") + .timeout(30000.0) + .build() + ) .build() ) @@ -201,11 +259,155 @@ internal class SessionServiceAsyncTest { val responseFuture = sessionServiceAsync.start( SessionStartParams.builder() - .xLanguage(JsonValue.from(mapOf())) - .xSdkVersion(JsonValue.from(mapOf())) - .xSentAt(JsonValue.from(mapOf())) - .xStreamResponse(JsonValue.from(mapOf())) - .body(JsonValue.from(mapOf())) + .xLanguage(SessionStartParams.XLanguage.TYPESCRIPT) + .xSdkVersion("3.0.6") + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) + .xStreamResponse(SessionStartParams.XStreamResponse.TRUE) + .modelName("gpt-4o") + .actTimeoutMs(30000.0) + .browser( + SessionStartParams.Browser.builder() + .cdpUrl("ws://localhost:9222") + .launchOptions( + SessionStartParams.Browser.LaunchOptions.builder() + .acceptDownloads(true) + .addArg("string") + .cdpUrl("cdpUrl") + .chromiumSandbox(true) + .connectTimeoutMs(0.0) + .deviceScaleFactor(0.0) + .devtools(true) + .downloadsPath("downloadsPath") + .executablePath("executablePath") + .hasTouch(true) + .headless(true) + .ignoreDefaultArgs(true) + .ignoreHttpsErrors(true) + .locale("locale") + .preserveUserDataDir(true) + .proxy( + SessionStartParams.Browser.LaunchOptions.Proxy.builder() + .server("server") + .bypass("bypass") + .password("password") + .username("username") + .build() + ) + .userDataDir("userDataDir") + .viewport( + SessionStartParams.Browser.LaunchOptions.Viewport.builder() + .height(0.0) + .width(0.0) + .build() + ) + .build() + ) + .type(SessionStartParams.Browser.Type.LOCAL) + .build() + ) + .browserbaseSessionCreateParams( + SessionStartParams.BrowserbaseSessionCreateParams.builder() + .browserSettings( + SessionStartParams.BrowserbaseSessionCreateParams.BrowserSettings + .builder() + .advancedStealth(true) + .blockAds(true) + .context( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .Context + .builder() + .id("id") + .persist(true) + .build() + ) + .extensionId("extensionId") + .fingerprint( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .builder() + .addBrowser( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .Browser + .CHROME + ) + .addDevice( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .Device + .DESKTOP + ) + .httpVersion( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .HttpVersion + ._1 + ) + .addLocale("string") + .addOperatingSystem( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .OperatingSystem + .ANDROID + ) + .screen( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .Screen + .builder() + .maxHeight(0.0) + .maxWidth(0.0) + .minHeight(0.0) + .minWidth(0.0) + .build() + ) + .build() + ) + .logSession(true) + .recordSession(true) + .solveCaptchas(true) + .viewport( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .Viewport + .builder() + .height(0.0) + .width(0.0) + .build() + ) + .build() + ) + .extensionId("extensionId") + .keepAlive(true) + .projectId("projectId") + .proxies(true) + .region( + SessionStartParams.BrowserbaseSessionCreateParams.Region.US_WEST_2 + ) + .timeout(0.0) + .userMetadata( + SessionStartParams.BrowserbaseSessionCreateParams.UserMetadata + .builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) + .build() + ) + .browserbaseSessionId("browserbaseSessionID") + .debugDom(true) + .domSettleTimeoutMs(5000.0) + .experimental(true) + .selfHeal(true) + .systemPrompt("systemPrompt") + .verbose(SessionStartParams.Verbose._1) + .waitForCaptchaSolves(true) .build() ) diff --git a/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/blocking/SessionServiceTest.kt b/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/blocking/SessionServiceTest.kt index 03853cd..3f62ca6 100644 --- a/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/blocking/SessionServiceTest.kt +++ b/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/blocking/SessionServiceTest.kt @@ -7,11 +7,12 @@ import com.browserbase.api.client.okhttp.StagehandOkHttpClient import com.browserbase.api.core.JsonValue import com.browserbase.api.models.sessions.SessionActParams import com.browserbase.api.models.sessions.SessionEndParams -import com.browserbase.api.models.sessions.SessionExecuteAgentParams +import com.browserbase.api.models.sessions.SessionExecuteParams import com.browserbase.api.models.sessions.SessionExtractParams import com.browserbase.api.models.sessions.SessionNavigateParams import com.browserbase.api.models.sessions.SessionObserveParams import com.browserbase.api.models.sessions.SessionStartParams +import java.time.OffsetDateTime import org.junit.jupiter.api.Disabled import org.junit.jupiter.api.Test import org.junit.jupiter.api.extension.ExtendWith @@ -34,12 +35,24 @@ internal class SessionServiceTest { val response = sessionService.act( SessionActParams.builder() - .id(JsonValue.from(mapOf())) - .xLanguage(JsonValue.from(mapOf())) - .xSdkVersion(JsonValue.from(mapOf())) - .xSentAt(JsonValue.from(mapOf())) - .xStreamResponse(JsonValue.from(mapOf())) - .body(JsonValue.from(mapOf())) + .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") + .xLanguage(SessionActParams.XLanguage.TYPESCRIPT) + .xSdkVersion("3.0.6") + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) + .xStreamResponse(SessionActParams.XStreamResponse.TRUE) + .input("Click the login button") + .frameId("frameId") + .options( + SessionActParams.Options.builder() + .model("string") + .timeout(30000.0) + .variables( + SessionActParams.Options.Variables.builder() + .putAdditionalProperty("username", JsonValue.from("john_doe")) + .build() + ) + .build() + ) .build() ) @@ -61,11 +74,11 @@ internal class SessionServiceTest { val response = sessionService.end( SessionEndParams.builder() - .id(JsonValue.from(mapOf())) - .xLanguage(JsonValue.from(mapOf())) - .xSdkVersion(JsonValue.from(mapOf())) - .xSentAt(JsonValue.from(mapOf())) - .xStreamResponse(JsonValue.from(mapOf())) + .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") + .xLanguage(SessionEndParams.XLanguage.TYPESCRIPT) + .xSdkVersion("3.0.6") + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) + .xStreamResponse(SessionEndParams.XStreamResponse.TRUE) .build() ) @@ -74,7 +87,7 @@ internal class SessionServiceTest { @Disabled("Prism tests are disabled") @Test - fun executeAgent() { + fun execute() { val client = StagehandOkHttpClient.builder() .baseUrl(TestServerExtension.BASE_URL) @@ -85,14 +98,30 @@ internal class SessionServiceTest { val sessionService = client.sessions() val response = - sessionService.executeAgent( - SessionExecuteAgentParams.builder() - .id(JsonValue.from(mapOf())) - .xLanguage(JsonValue.from(mapOf())) - .xSdkVersion(JsonValue.from(mapOf())) - .xSentAt(JsonValue.from(mapOf())) - .xStreamResponse(JsonValue.from(mapOf())) - .body(JsonValue.from(mapOf())) + sessionService.execute( + SessionExecuteParams.builder() + .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") + .xLanguage(SessionExecuteParams.XLanguage.TYPESCRIPT) + .xSdkVersion("3.0.6") + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) + .xStreamResponse(SessionExecuteParams.XStreamResponse.TRUE) + .agentConfig( + SessionExecuteParams.AgentConfig.builder() + .cua(true) + .model("string") + .systemPrompt("systemPrompt") + .build() + ) + .executeOptions( + SessionExecuteParams.ExecuteOptions.builder() + .instruction( + "Log in with username 'demo' and password 'test123', then navigate to settings" + ) + .highlightCursor(true) + .maxSteps(20.0) + .build() + ) + .frameId("frameId") .build() ) @@ -114,12 +143,25 @@ internal class SessionServiceTest { val response = sessionService.extract( SessionExtractParams.builder() - .id(JsonValue.from(mapOf())) - .xLanguage(JsonValue.from(mapOf())) - .xSdkVersion(JsonValue.from(mapOf())) - .xSentAt(JsonValue.from(mapOf())) - .xStreamResponse(JsonValue.from(mapOf())) - .body(JsonValue.from(mapOf())) + .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") + .xLanguage(SessionExtractParams.XLanguage.TYPESCRIPT) + .xSdkVersion("3.0.6") + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) + .xStreamResponse(SessionExtractParams.XStreamResponse.TRUE) + .frameId("frameId") + .instruction("Extract all product names and prices from the page") + .options( + SessionExtractParams.Options.builder() + .model("string") + .selector("#main-content") + .timeout(30000.0) + .build() + ) + .schema( + SessionExtractParams.Schema.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) .build() ) @@ -141,12 +183,20 @@ internal class SessionServiceTest { val response = sessionService.navigate( SessionNavigateParams.builder() - .id(JsonValue.from(mapOf())) - .xLanguage(JsonValue.from(mapOf())) - .xSdkVersion(JsonValue.from(mapOf())) - .xSentAt(JsonValue.from(mapOf())) - .xStreamResponse(JsonValue.from(mapOf())) - .body(JsonValue.from(mapOf())) + .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") + .xLanguage(SessionNavigateParams.XLanguage.TYPESCRIPT) + .xSdkVersion("3.0.6") + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) + .xStreamResponse(SessionNavigateParams.XStreamResponse.TRUE) + .url("https://example.com") + .frameId("frameId") + .options( + SessionNavigateParams.Options.builder() + .referer("referer") + .timeout(30000.0) + .waitUntil(SessionNavigateParams.Options.WaitUntil.NETWORKIDLE) + .build() + ) .build() ) @@ -168,12 +218,20 @@ internal class SessionServiceTest { val response = sessionService.observe( SessionObserveParams.builder() - .id(JsonValue.from(mapOf())) - .xLanguage(JsonValue.from(mapOf())) - .xSdkVersion(JsonValue.from(mapOf())) - .xSentAt(JsonValue.from(mapOf())) - .xStreamResponse(JsonValue.from(mapOf())) - .body(JsonValue.from(mapOf())) + .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") + .xLanguage(SessionObserveParams.XLanguage.TYPESCRIPT) + .xSdkVersion("3.0.6") + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) + .xStreamResponse(SessionObserveParams.XStreamResponse.TRUE) + .frameId("frameId") + .instruction("Find all clickable navigation links") + .options( + SessionObserveParams.Options.builder() + .model("string") + .selector("nav") + .timeout(30000.0) + .build() + ) .build() ) @@ -195,11 +253,155 @@ internal class SessionServiceTest { val response = sessionService.start( SessionStartParams.builder() - .xLanguage(JsonValue.from(mapOf())) - .xSdkVersion(JsonValue.from(mapOf())) - .xSentAt(JsonValue.from(mapOf())) - .xStreamResponse(JsonValue.from(mapOf())) - .body(JsonValue.from(mapOf())) + .xLanguage(SessionStartParams.XLanguage.TYPESCRIPT) + .xSdkVersion("3.0.6") + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) + .xStreamResponse(SessionStartParams.XStreamResponse.TRUE) + .modelName("gpt-4o") + .actTimeoutMs(30000.0) + .browser( + SessionStartParams.Browser.builder() + .cdpUrl("ws://localhost:9222") + .launchOptions( + SessionStartParams.Browser.LaunchOptions.builder() + .acceptDownloads(true) + .addArg("string") + .cdpUrl("cdpUrl") + .chromiumSandbox(true) + .connectTimeoutMs(0.0) + .deviceScaleFactor(0.0) + .devtools(true) + .downloadsPath("downloadsPath") + .executablePath("executablePath") + .hasTouch(true) + .headless(true) + .ignoreDefaultArgs(true) + .ignoreHttpsErrors(true) + .locale("locale") + .preserveUserDataDir(true) + .proxy( + SessionStartParams.Browser.LaunchOptions.Proxy.builder() + .server("server") + .bypass("bypass") + .password("password") + .username("username") + .build() + ) + .userDataDir("userDataDir") + .viewport( + SessionStartParams.Browser.LaunchOptions.Viewport.builder() + .height(0.0) + .width(0.0) + .build() + ) + .build() + ) + .type(SessionStartParams.Browser.Type.LOCAL) + .build() + ) + .browserbaseSessionCreateParams( + SessionStartParams.BrowserbaseSessionCreateParams.builder() + .browserSettings( + SessionStartParams.BrowserbaseSessionCreateParams.BrowserSettings + .builder() + .advancedStealth(true) + .blockAds(true) + .context( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .Context + .builder() + .id("id") + .persist(true) + .build() + ) + .extensionId("extensionId") + .fingerprint( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .builder() + .addBrowser( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .Browser + .CHROME + ) + .addDevice( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .Device + .DESKTOP + ) + .httpVersion( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .HttpVersion + ._1 + ) + .addLocale("string") + .addOperatingSystem( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .OperatingSystem + .ANDROID + ) + .screen( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .Screen + .builder() + .maxHeight(0.0) + .maxWidth(0.0) + .minHeight(0.0) + .minWidth(0.0) + .build() + ) + .build() + ) + .logSession(true) + .recordSession(true) + .solveCaptchas(true) + .viewport( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .Viewport + .builder() + .height(0.0) + .width(0.0) + .build() + ) + .build() + ) + .extensionId("extensionId") + .keepAlive(true) + .projectId("projectId") + .proxies(true) + .region( + SessionStartParams.BrowserbaseSessionCreateParams.Region.US_WEST_2 + ) + .timeout(0.0) + .userMetadata( + SessionStartParams.BrowserbaseSessionCreateParams.UserMetadata + .builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) + .build() + ) + .browserbaseSessionId("browserbaseSessionID") + .debugDom(true) + .domSettleTimeoutMs(5000.0) + .experimental(true) + .selfHeal(true) + .systemPrompt("systemPrompt") + .verbose(SessionStartParams.Verbose._1) + .waitForCaptchaSolves(true) .build() ) From dd65420fecb521fba36cbf2a623ce675973a27a0 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 17 Dec 2025 18:22:21 +0000 Subject: [PATCH 05/18] feat(api): manual updates --- .stats.yml | 6 +- README.md | 28 +- .../api/services/ErrorHandlingTest.kt | 2892 +++++++++++++++-- .../api/services/ServiceParamsTest.kt | 169 + 4 files changed, 2788 insertions(+), 307 deletions(-) diff --git a/.stats.yml b/.stats.yml index 87bd24b..a5338dd 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-349e1b0f6291eedd731c1660155a50adcb3424fb8cd9e17bbdc0939ff3bbffcd.yml -openapi_spec_hash: 456b593ea71d72bc31a6338a25363e9f -config_hash: 5f6b5ec6e84fb01932ba87c6a9623d9b +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/browserbase%2Fstagehand-e6a9dca1a93568e403ac72128d86f30c8c3f1336d4b67017d7e61b1836f10f47.yml +openapi_spec_hash: ef01e0649bb0e283df0aa81c369649df +config_hash: abc9d1eb9779bb5629eaed7074c42809 diff --git a/README.md b/README.md index 019da3c..852c752 100644 --- a/README.md +++ b/README.md @@ -57,7 +57,7 @@ StagehandClient client = StagehandOkHttpClient.fromEnv(); SessionActParams params = SessionActParams.builder() .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") - .input("Click the login button") + .input("click the first link on the page") .build(); SessionActResponse response = client.sessions().act(params); ``` @@ -163,7 +163,7 @@ StagehandClient client = StagehandOkHttpClient.fromEnv(); SessionActParams params = SessionActParams.builder() .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") - .input("Click the login button") + .input("click the first link on the page") .build(); CompletableFuture response = client.async().sessions().act(params); ``` @@ -183,7 +183,7 @@ StagehandClientAsync client = StagehandOkHttpClientAsync.fromEnv(); SessionActParams params = SessionActParams.builder() .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") - .input("Click the login button") + .input("click the first link on the page") .build(); CompletableFuture response = client.sessions().act(params); ``` @@ -199,14 +199,13 @@ To access this data, prefix any HTTP method call on a client or service with `wi ```java import com.browserbase.api.core.http.Headers; import com.browserbase.api.core.http.HttpResponseFor; -import com.browserbase.api.models.sessions.SessionActParams; -import com.browserbase.api.models.sessions.SessionActResponse; +import com.browserbase.api.models.sessions.SessionStartParams; +import com.browserbase.api.models.sessions.SessionStartResponse; -SessionActParams params = SessionActParams.builder() - .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") - .input("Click the login button") +SessionStartParams params = SessionStartParams.builder() + .modelName("gpt-4o") .build(); -HttpResponseFor response = client.sessions().withRawResponse().act(params); +HttpResponseFor response = client.sessions().withRawResponse().start(params); int statusCode = response.statusCode(); Headers headers = response.headers(); @@ -215,9 +214,9 @@ Headers headers = response.headers(); You can still deserialize the response into an instance of a Java class if needed: ```java -import com.browserbase.api.models.sessions.SessionActResponse; +import com.browserbase.api.models.sessions.SessionStartResponse; -SessionActResponse parsedResponse = response.parse(); +SessionStartResponse parsedResponse = response.parse(); ``` ## Error handling @@ -313,9 +312,9 @@ Requests time out after 1 minute by default. To set a custom timeout, configure the method call using the `timeout` method: ```java -import com.browserbase.api.models.sessions.SessionActResponse; +import com.browserbase.api.models.sessions.SessionStartResponse; -SessionActResponse response = client.sessions().act( +SessionStartResponse response = client.sessions().start( params, RequestOptions.builder().timeout(Duration.ofSeconds(30)).build() ); ``` @@ -449,10 +448,11 @@ These properties can be accessed on the nested built object later using the `_ad To set a documented parameter or property to an undocumented or not yet supported _value_, pass a [`JsonValue`](stagehand-java-core/src/main/kotlin/com/browserbase/api/core/Values.kt) object to its setter: ```java +import com.browserbase.api.core.JsonValue; import com.browserbase.api.models.sessions.SessionActParams; SessionActParams params = SessionActParams.builder() - .input("Click the login button") + .input(JsonValue.from(42)) .build(); ``` diff --git a/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/ErrorHandlingTest.kt b/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/ErrorHandlingTest.kt index 32b00d3..87af3f1 100644 --- a/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/ErrorHandlingTest.kt +++ b/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/ErrorHandlingTest.kt @@ -16,7 +16,7 @@ import com.browserbase.api.errors.StagehandException import com.browserbase.api.errors.UnauthorizedException import com.browserbase.api.errors.UnexpectedStatusCodeException import com.browserbase.api.errors.UnprocessableEntityException -import com.browserbase.api.models.sessions.SessionActParams +import com.browserbase.api.models.sessions.SessionStartParams import com.github.tomakehurst.wiremock.client.WireMock.anyUrl import com.github.tomakehurst.wiremock.client.WireMock.post import com.github.tomakehurst.wiremock.client.WireMock.status @@ -62,7 +62,7 @@ internal class ErrorHandlingTest { } @Test - fun sessionsAct400() { + fun sessionsStart400() { val sessionService = client.sessions() stubFor( post(anyUrl()) @@ -73,29 +73,165 @@ internal class ErrorHandlingTest { val e = assertThrows { - sessionService.act( - SessionActParams.builder() - .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") - .xLanguage(SessionActParams.XLanguage.TYPESCRIPT) + sessionService.start( + SessionStartParams.builder() + .xLanguage(SessionStartParams.XLanguage.TYPESCRIPT) .xSdkVersion("3.0.6") .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) - .xStreamResponse(SessionActParams.XStreamResponse.TRUE) - .input("Click the login button") - .frameId("frameId") - .options( - SessionActParams.Options.builder() - .model("string") - .timeout(30000.0) - .variables( - SessionActParams.Options.Variables.builder() - .putAdditionalProperty( - "username", - JsonValue.from("john_doe"), + .xStreamResponse(SessionStartParams.XStreamResponse.TRUE) + .modelName("gpt-4o") + .actTimeoutMs(30000.0) + .browser( + SessionStartParams.Browser.builder() + .cdpUrl("ws://localhost:9222") + .launchOptions( + SessionStartParams.Browser.LaunchOptions.builder() + .acceptDownloads(true) + .addArg("string") + .cdpUrl("cdpUrl") + .chromiumSandbox(true) + .connectTimeoutMs(0.0) + .deviceScaleFactor(0.0) + .devtools(true) + .downloadsPath("downloadsPath") + .executablePath("executablePath") + .hasTouch(true) + .headless(true) + .ignoreDefaultArgs(true) + .ignoreHttpsErrors(true) + .locale("locale") + .preserveUserDataDir(true) + .proxy( + SessionStartParams.Browser.LaunchOptions.Proxy.builder() + .server("server") + .bypass("bypass") + .password("password") + .username("username") + .build() ) + .userDataDir("userDataDir") + .viewport( + SessionStartParams.Browser.LaunchOptions.Viewport + .builder() + .height(0.0) + .width(0.0) + .build() + ) + .build() + ) + .type(SessionStartParams.Browser.Type.LOCAL) + .build() + ) + .browserbaseSessionCreateParams( + SessionStartParams.BrowserbaseSessionCreateParams.builder() + .browserSettings( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .builder() + .advancedStealth(true) + .blockAds(true) + .context( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .Context + .builder() + .id("id") + .persist(true) + .build() + ) + .extensionId("extensionId") + .fingerprint( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .builder() + .addBrowser( + SessionStartParams + .BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .Browser + .CHROME + ) + .addDevice( + SessionStartParams + .BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .Device + .DESKTOP + ) + .httpVersion( + SessionStartParams + .BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .HttpVersion + ._1 + ) + .addLocale("string") + .addOperatingSystem( + SessionStartParams + .BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .OperatingSystem + .ANDROID + ) + .screen( + SessionStartParams + .BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .Screen + .builder() + .maxHeight(0.0) + .maxWidth(0.0) + .minHeight(0.0) + .minWidth(0.0) + .build() + ) + .build() + ) + .logSession(true) + .recordSession(true) + .solveCaptchas(true) + .viewport( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .Viewport + .builder() + .height(0.0) + .width(0.0) + .build() + ) + .build() + ) + .extensionId("extensionId") + .keepAlive(true) + .projectId("projectId") + .proxies(true) + .region( + SessionStartParams.BrowserbaseSessionCreateParams.Region + .US_WEST_2 + ) + .timeout(0.0) + .userMetadata( + SessionStartParams.BrowserbaseSessionCreateParams.UserMetadata + .builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) .build() ) .build() ) + .browserbaseSessionId("browserbaseSessionID") + .debugDom(true) + .domSettleTimeoutMs(5000.0) + .experimental(true) + .selfHeal(true) + .systemPrompt("systemPrompt") + .verbose(SessionStartParams.Verbose._1) + .waitForCaptchaSolves(true) .build() ) } @@ -106,7 +242,7 @@ internal class ErrorHandlingTest { } @Test - fun sessionsAct400WithRawResponse() { + fun sessionsStart400WithRawResponse() { val sessionService = client.sessions().withRawResponse() stubFor( post(anyUrl()) @@ -117,29 +253,165 @@ internal class ErrorHandlingTest { val e = assertThrows { - sessionService.act( - SessionActParams.builder() - .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") - .xLanguage(SessionActParams.XLanguage.TYPESCRIPT) + sessionService.start( + SessionStartParams.builder() + .xLanguage(SessionStartParams.XLanguage.TYPESCRIPT) .xSdkVersion("3.0.6") .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) - .xStreamResponse(SessionActParams.XStreamResponse.TRUE) - .input("Click the login button") - .frameId("frameId") - .options( - SessionActParams.Options.builder() - .model("string") - .timeout(30000.0) - .variables( - SessionActParams.Options.Variables.builder() - .putAdditionalProperty( - "username", - JsonValue.from("john_doe"), + .xStreamResponse(SessionStartParams.XStreamResponse.TRUE) + .modelName("gpt-4o") + .actTimeoutMs(30000.0) + .browser( + SessionStartParams.Browser.builder() + .cdpUrl("ws://localhost:9222") + .launchOptions( + SessionStartParams.Browser.LaunchOptions.builder() + .acceptDownloads(true) + .addArg("string") + .cdpUrl("cdpUrl") + .chromiumSandbox(true) + .connectTimeoutMs(0.0) + .deviceScaleFactor(0.0) + .devtools(true) + .downloadsPath("downloadsPath") + .executablePath("executablePath") + .hasTouch(true) + .headless(true) + .ignoreDefaultArgs(true) + .ignoreHttpsErrors(true) + .locale("locale") + .preserveUserDataDir(true) + .proxy( + SessionStartParams.Browser.LaunchOptions.Proxy.builder() + .server("server") + .bypass("bypass") + .password("password") + .username("username") + .build() + ) + .userDataDir("userDataDir") + .viewport( + SessionStartParams.Browser.LaunchOptions.Viewport + .builder() + .height(0.0) + .width(0.0) + .build() ) .build() ) + .type(SessionStartParams.Browser.Type.LOCAL) .build() ) + .browserbaseSessionCreateParams( + SessionStartParams.BrowserbaseSessionCreateParams.builder() + .browserSettings( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .builder() + .advancedStealth(true) + .blockAds(true) + .context( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .Context + .builder() + .id("id") + .persist(true) + .build() + ) + .extensionId("extensionId") + .fingerprint( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .builder() + .addBrowser( + SessionStartParams + .BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .Browser + .CHROME + ) + .addDevice( + SessionStartParams + .BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .Device + .DESKTOP + ) + .httpVersion( + SessionStartParams + .BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .HttpVersion + ._1 + ) + .addLocale("string") + .addOperatingSystem( + SessionStartParams + .BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .OperatingSystem + .ANDROID + ) + .screen( + SessionStartParams + .BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .Screen + .builder() + .maxHeight(0.0) + .maxWidth(0.0) + .minHeight(0.0) + .minWidth(0.0) + .build() + ) + .build() + ) + .logSession(true) + .recordSession(true) + .solveCaptchas(true) + .viewport( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .Viewport + .builder() + .height(0.0) + .width(0.0) + .build() + ) + .build() + ) + .extensionId("extensionId") + .keepAlive(true) + .projectId("projectId") + .proxies(true) + .region( + SessionStartParams.BrowserbaseSessionCreateParams.Region + .US_WEST_2 + ) + .timeout(0.0) + .userMetadata( + SessionStartParams.BrowserbaseSessionCreateParams.UserMetadata + .builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) + .build() + ) + .browserbaseSessionId("browserbaseSessionID") + .debugDom(true) + .domSettleTimeoutMs(5000.0) + .experimental(true) + .selfHeal(true) + .systemPrompt("systemPrompt") + .verbose(SessionStartParams.Verbose._1) + .waitForCaptchaSolves(true) .build() ) } @@ -150,7 +422,7 @@ internal class ErrorHandlingTest { } @Test - fun sessionsAct401() { + fun sessionsStart401() { val sessionService = client.sessions() stubFor( post(anyUrl()) @@ -161,29 +433,165 @@ internal class ErrorHandlingTest { val e = assertThrows { - sessionService.act( - SessionActParams.builder() - .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") - .xLanguage(SessionActParams.XLanguage.TYPESCRIPT) + sessionService.start( + SessionStartParams.builder() + .xLanguage(SessionStartParams.XLanguage.TYPESCRIPT) .xSdkVersion("3.0.6") .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) - .xStreamResponse(SessionActParams.XStreamResponse.TRUE) - .input("Click the login button") - .frameId("frameId") - .options( - SessionActParams.Options.builder() - .model("string") - .timeout(30000.0) - .variables( - SessionActParams.Options.Variables.builder() - .putAdditionalProperty( - "username", - JsonValue.from("john_doe"), + .xStreamResponse(SessionStartParams.XStreamResponse.TRUE) + .modelName("gpt-4o") + .actTimeoutMs(30000.0) + .browser( + SessionStartParams.Browser.builder() + .cdpUrl("ws://localhost:9222") + .launchOptions( + SessionStartParams.Browser.LaunchOptions.builder() + .acceptDownloads(true) + .addArg("string") + .cdpUrl("cdpUrl") + .chromiumSandbox(true) + .connectTimeoutMs(0.0) + .deviceScaleFactor(0.0) + .devtools(true) + .downloadsPath("downloadsPath") + .executablePath("executablePath") + .hasTouch(true) + .headless(true) + .ignoreDefaultArgs(true) + .ignoreHttpsErrors(true) + .locale("locale") + .preserveUserDataDir(true) + .proxy( + SessionStartParams.Browser.LaunchOptions.Proxy.builder() + .server("server") + .bypass("bypass") + .password("password") + .username("username") + .build() + ) + .userDataDir("userDataDir") + .viewport( + SessionStartParams.Browser.LaunchOptions.Viewport + .builder() + .height(0.0) + .width(0.0) + .build() ) .build() ) + .type(SessionStartParams.Browser.Type.LOCAL) .build() ) + .browserbaseSessionCreateParams( + SessionStartParams.BrowserbaseSessionCreateParams.builder() + .browserSettings( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .builder() + .advancedStealth(true) + .blockAds(true) + .context( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .Context + .builder() + .id("id") + .persist(true) + .build() + ) + .extensionId("extensionId") + .fingerprint( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .builder() + .addBrowser( + SessionStartParams + .BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .Browser + .CHROME + ) + .addDevice( + SessionStartParams + .BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .Device + .DESKTOP + ) + .httpVersion( + SessionStartParams + .BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .HttpVersion + ._1 + ) + .addLocale("string") + .addOperatingSystem( + SessionStartParams + .BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .OperatingSystem + .ANDROID + ) + .screen( + SessionStartParams + .BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .Screen + .builder() + .maxHeight(0.0) + .maxWidth(0.0) + .minHeight(0.0) + .minWidth(0.0) + .build() + ) + .build() + ) + .logSession(true) + .recordSession(true) + .solveCaptchas(true) + .viewport( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .Viewport + .builder() + .height(0.0) + .width(0.0) + .build() + ) + .build() + ) + .extensionId("extensionId") + .keepAlive(true) + .projectId("projectId") + .proxies(true) + .region( + SessionStartParams.BrowserbaseSessionCreateParams.Region + .US_WEST_2 + ) + .timeout(0.0) + .userMetadata( + SessionStartParams.BrowserbaseSessionCreateParams.UserMetadata + .builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) + .build() + ) + .browserbaseSessionId("browserbaseSessionID") + .debugDom(true) + .domSettleTimeoutMs(5000.0) + .experimental(true) + .selfHeal(true) + .systemPrompt("systemPrompt") + .verbose(SessionStartParams.Verbose._1) + .waitForCaptchaSolves(true) .build() ) } @@ -194,7 +602,7 @@ internal class ErrorHandlingTest { } @Test - fun sessionsAct401WithRawResponse() { + fun sessionsStart401WithRawResponse() { val sessionService = client.sessions().withRawResponse() stubFor( post(anyUrl()) @@ -205,29 +613,165 @@ internal class ErrorHandlingTest { val e = assertThrows { - sessionService.act( - SessionActParams.builder() - .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") - .xLanguage(SessionActParams.XLanguage.TYPESCRIPT) + sessionService.start( + SessionStartParams.builder() + .xLanguage(SessionStartParams.XLanguage.TYPESCRIPT) .xSdkVersion("3.0.6") .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) - .xStreamResponse(SessionActParams.XStreamResponse.TRUE) - .input("Click the login button") - .frameId("frameId") - .options( - SessionActParams.Options.builder() - .model("string") - .timeout(30000.0) - .variables( - SessionActParams.Options.Variables.builder() - .putAdditionalProperty( - "username", - JsonValue.from("john_doe"), + .xStreamResponse(SessionStartParams.XStreamResponse.TRUE) + .modelName("gpt-4o") + .actTimeoutMs(30000.0) + .browser( + SessionStartParams.Browser.builder() + .cdpUrl("ws://localhost:9222") + .launchOptions( + SessionStartParams.Browser.LaunchOptions.builder() + .acceptDownloads(true) + .addArg("string") + .cdpUrl("cdpUrl") + .chromiumSandbox(true) + .connectTimeoutMs(0.0) + .deviceScaleFactor(0.0) + .devtools(true) + .downloadsPath("downloadsPath") + .executablePath("executablePath") + .hasTouch(true) + .headless(true) + .ignoreDefaultArgs(true) + .ignoreHttpsErrors(true) + .locale("locale") + .preserveUserDataDir(true) + .proxy( + SessionStartParams.Browser.LaunchOptions.Proxy.builder() + .server("server") + .bypass("bypass") + .password("password") + .username("username") + .build() + ) + .userDataDir("userDataDir") + .viewport( + SessionStartParams.Browser.LaunchOptions.Viewport + .builder() + .height(0.0) + .width(0.0) + .build() ) .build() ) + .type(SessionStartParams.Browser.Type.LOCAL) .build() ) + .browserbaseSessionCreateParams( + SessionStartParams.BrowserbaseSessionCreateParams.builder() + .browserSettings( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .builder() + .advancedStealth(true) + .blockAds(true) + .context( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .Context + .builder() + .id("id") + .persist(true) + .build() + ) + .extensionId("extensionId") + .fingerprint( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .builder() + .addBrowser( + SessionStartParams + .BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .Browser + .CHROME + ) + .addDevice( + SessionStartParams + .BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .Device + .DESKTOP + ) + .httpVersion( + SessionStartParams + .BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .HttpVersion + ._1 + ) + .addLocale("string") + .addOperatingSystem( + SessionStartParams + .BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .OperatingSystem + .ANDROID + ) + .screen( + SessionStartParams + .BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .Screen + .builder() + .maxHeight(0.0) + .maxWidth(0.0) + .minHeight(0.0) + .minWidth(0.0) + .build() + ) + .build() + ) + .logSession(true) + .recordSession(true) + .solveCaptchas(true) + .viewport( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .Viewport + .builder() + .height(0.0) + .width(0.0) + .build() + ) + .build() + ) + .extensionId("extensionId") + .keepAlive(true) + .projectId("projectId") + .proxies(true) + .region( + SessionStartParams.BrowserbaseSessionCreateParams.Region + .US_WEST_2 + ) + .timeout(0.0) + .userMetadata( + SessionStartParams.BrowserbaseSessionCreateParams.UserMetadata + .builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) + .build() + ) + .browserbaseSessionId("browserbaseSessionID") + .debugDom(true) + .domSettleTimeoutMs(5000.0) + .experimental(true) + .selfHeal(true) + .systemPrompt("systemPrompt") + .verbose(SessionStartParams.Verbose._1) + .waitForCaptchaSolves(true) .build() ) } @@ -238,7 +782,7 @@ internal class ErrorHandlingTest { } @Test - fun sessionsAct403() { + fun sessionsStart403() { val sessionService = client.sessions() stubFor( post(anyUrl()) @@ -249,29 +793,165 @@ internal class ErrorHandlingTest { val e = assertThrows { - sessionService.act( - SessionActParams.builder() - .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") - .xLanguage(SessionActParams.XLanguage.TYPESCRIPT) + sessionService.start( + SessionStartParams.builder() + .xLanguage(SessionStartParams.XLanguage.TYPESCRIPT) .xSdkVersion("3.0.6") .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) - .xStreamResponse(SessionActParams.XStreamResponse.TRUE) - .input("Click the login button") - .frameId("frameId") - .options( - SessionActParams.Options.builder() - .model("string") - .timeout(30000.0) - .variables( - SessionActParams.Options.Variables.builder() - .putAdditionalProperty( - "username", - JsonValue.from("john_doe"), + .xStreamResponse(SessionStartParams.XStreamResponse.TRUE) + .modelName("gpt-4o") + .actTimeoutMs(30000.0) + .browser( + SessionStartParams.Browser.builder() + .cdpUrl("ws://localhost:9222") + .launchOptions( + SessionStartParams.Browser.LaunchOptions.builder() + .acceptDownloads(true) + .addArg("string") + .cdpUrl("cdpUrl") + .chromiumSandbox(true) + .connectTimeoutMs(0.0) + .deviceScaleFactor(0.0) + .devtools(true) + .downloadsPath("downloadsPath") + .executablePath("executablePath") + .hasTouch(true) + .headless(true) + .ignoreDefaultArgs(true) + .ignoreHttpsErrors(true) + .locale("locale") + .preserveUserDataDir(true) + .proxy( + SessionStartParams.Browser.LaunchOptions.Proxy.builder() + .server("server") + .bypass("bypass") + .password("password") + .username("username") + .build() + ) + .userDataDir("userDataDir") + .viewport( + SessionStartParams.Browser.LaunchOptions.Viewport + .builder() + .height(0.0) + .width(0.0) + .build() + ) + .build() + ) + .type(SessionStartParams.Browser.Type.LOCAL) + .build() + ) + .browserbaseSessionCreateParams( + SessionStartParams.BrowserbaseSessionCreateParams.builder() + .browserSettings( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .builder() + .advancedStealth(true) + .blockAds(true) + .context( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .Context + .builder() + .id("id") + .persist(true) + .build() ) + .extensionId("extensionId") + .fingerprint( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .builder() + .addBrowser( + SessionStartParams + .BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .Browser + .CHROME + ) + .addDevice( + SessionStartParams + .BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .Device + .DESKTOP + ) + .httpVersion( + SessionStartParams + .BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .HttpVersion + ._1 + ) + .addLocale("string") + .addOperatingSystem( + SessionStartParams + .BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .OperatingSystem + .ANDROID + ) + .screen( + SessionStartParams + .BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .Screen + .builder() + .maxHeight(0.0) + .maxWidth(0.0) + .minHeight(0.0) + .minWidth(0.0) + .build() + ) + .build() + ) + .logSession(true) + .recordSession(true) + .solveCaptchas(true) + .viewport( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .Viewport + .builder() + .height(0.0) + .width(0.0) + .build() + ) + .build() + ) + .extensionId("extensionId") + .keepAlive(true) + .projectId("projectId") + .proxies(true) + .region( + SessionStartParams.BrowserbaseSessionCreateParams.Region + .US_WEST_2 + ) + .timeout(0.0) + .userMetadata( + SessionStartParams.BrowserbaseSessionCreateParams.UserMetadata + .builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) .build() ) .build() ) + .browserbaseSessionId("browserbaseSessionID") + .debugDom(true) + .domSettleTimeoutMs(5000.0) + .experimental(true) + .selfHeal(true) + .systemPrompt("systemPrompt") + .verbose(SessionStartParams.Verbose._1) + .waitForCaptchaSolves(true) .build() ) } @@ -282,7 +962,7 @@ internal class ErrorHandlingTest { } @Test - fun sessionsAct403WithRawResponse() { + fun sessionsStart403WithRawResponse() { val sessionService = client.sessions().withRawResponse() stubFor( post(anyUrl()) @@ -293,29 +973,165 @@ internal class ErrorHandlingTest { val e = assertThrows { - sessionService.act( - SessionActParams.builder() - .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") - .xLanguage(SessionActParams.XLanguage.TYPESCRIPT) + sessionService.start( + SessionStartParams.builder() + .xLanguage(SessionStartParams.XLanguage.TYPESCRIPT) .xSdkVersion("3.0.6") .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) - .xStreamResponse(SessionActParams.XStreamResponse.TRUE) - .input("Click the login button") - .frameId("frameId") - .options( - SessionActParams.Options.builder() - .model("string") - .timeout(30000.0) - .variables( - SessionActParams.Options.Variables.builder() - .putAdditionalProperty( - "username", - JsonValue.from("john_doe"), + .xStreamResponse(SessionStartParams.XStreamResponse.TRUE) + .modelName("gpt-4o") + .actTimeoutMs(30000.0) + .browser( + SessionStartParams.Browser.builder() + .cdpUrl("ws://localhost:9222") + .launchOptions( + SessionStartParams.Browser.LaunchOptions.builder() + .acceptDownloads(true) + .addArg("string") + .cdpUrl("cdpUrl") + .chromiumSandbox(true) + .connectTimeoutMs(0.0) + .deviceScaleFactor(0.0) + .devtools(true) + .downloadsPath("downloadsPath") + .executablePath("executablePath") + .hasTouch(true) + .headless(true) + .ignoreDefaultArgs(true) + .ignoreHttpsErrors(true) + .locale("locale") + .preserveUserDataDir(true) + .proxy( + SessionStartParams.Browser.LaunchOptions.Proxy.builder() + .server("server") + .bypass("bypass") + .password("password") + .username("username") + .build() + ) + .userDataDir("userDataDir") + .viewport( + SessionStartParams.Browser.LaunchOptions.Viewport + .builder() + .height(0.0) + .width(0.0) + .build() + ) + .build() + ) + .type(SessionStartParams.Browser.Type.LOCAL) + .build() + ) + .browserbaseSessionCreateParams( + SessionStartParams.BrowserbaseSessionCreateParams.builder() + .browserSettings( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .builder() + .advancedStealth(true) + .blockAds(true) + .context( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .Context + .builder() + .id("id") + .persist(true) + .build() + ) + .extensionId("extensionId") + .fingerprint( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .builder() + .addBrowser( + SessionStartParams + .BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .Browser + .CHROME + ) + .addDevice( + SessionStartParams + .BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .Device + .DESKTOP + ) + .httpVersion( + SessionStartParams + .BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .HttpVersion + ._1 + ) + .addLocale("string") + .addOperatingSystem( + SessionStartParams + .BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .OperatingSystem + .ANDROID + ) + .screen( + SessionStartParams + .BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .Screen + .builder() + .maxHeight(0.0) + .maxWidth(0.0) + .minHeight(0.0) + .minWidth(0.0) + .build() + ) + .build() ) + .logSession(true) + .recordSession(true) + .solveCaptchas(true) + .viewport( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .Viewport + .builder() + .height(0.0) + .width(0.0) + .build() + ) + .build() + ) + .extensionId("extensionId") + .keepAlive(true) + .projectId("projectId") + .proxies(true) + .region( + SessionStartParams.BrowserbaseSessionCreateParams.Region + .US_WEST_2 + ) + .timeout(0.0) + .userMetadata( + SessionStartParams.BrowserbaseSessionCreateParams.UserMetadata + .builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) .build() ) .build() ) + .browserbaseSessionId("browserbaseSessionID") + .debugDom(true) + .domSettleTimeoutMs(5000.0) + .experimental(true) + .selfHeal(true) + .systemPrompt("systemPrompt") + .verbose(SessionStartParams.Verbose._1) + .waitForCaptchaSolves(true) .build() ) } @@ -326,7 +1142,7 @@ internal class ErrorHandlingTest { } @Test - fun sessionsAct404() { + fun sessionsStart404() { val sessionService = client.sessions() stubFor( post(anyUrl()) @@ -337,29 +1153,165 @@ internal class ErrorHandlingTest { val e = assertThrows { - sessionService.act( - SessionActParams.builder() - .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") - .xLanguage(SessionActParams.XLanguage.TYPESCRIPT) + sessionService.start( + SessionStartParams.builder() + .xLanguage(SessionStartParams.XLanguage.TYPESCRIPT) .xSdkVersion("3.0.6") .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) - .xStreamResponse(SessionActParams.XStreamResponse.TRUE) - .input("Click the login button") - .frameId("frameId") - .options( - SessionActParams.Options.builder() - .model("string") - .timeout(30000.0) - .variables( - SessionActParams.Options.Variables.builder() - .putAdditionalProperty( - "username", - JsonValue.from("john_doe"), + .xStreamResponse(SessionStartParams.XStreamResponse.TRUE) + .modelName("gpt-4o") + .actTimeoutMs(30000.0) + .browser( + SessionStartParams.Browser.builder() + .cdpUrl("ws://localhost:9222") + .launchOptions( + SessionStartParams.Browser.LaunchOptions.builder() + .acceptDownloads(true) + .addArg("string") + .cdpUrl("cdpUrl") + .chromiumSandbox(true) + .connectTimeoutMs(0.0) + .deviceScaleFactor(0.0) + .devtools(true) + .downloadsPath("downloadsPath") + .executablePath("executablePath") + .hasTouch(true) + .headless(true) + .ignoreDefaultArgs(true) + .ignoreHttpsErrors(true) + .locale("locale") + .preserveUserDataDir(true) + .proxy( + SessionStartParams.Browser.LaunchOptions.Proxy.builder() + .server("server") + .bypass("bypass") + .password("password") + .username("username") + .build() + ) + .userDataDir("userDataDir") + .viewport( + SessionStartParams.Browser.LaunchOptions.Viewport + .builder() + .height(0.0) + .width(0.0) + .build() ) .build() ) + .type(SessionStartParams.Browser.Type.LOCAL) .build() ) + .browserbaseSessionCreateParams( + SessionStartParams.BrowserbaseSessionCreateParams.builder() + .browserSettings( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .builder() + .advancedStealth(true) + .blockAds(true) + .context( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .Context + .builder() + .id("id") + .persist(true) + .build() + ) + .extensionId("extensionId") + .fingerprint( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .builder() + .addBrowser( + SessionStartParams + .BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .Browser + .CHROME + ) + .addDevice( + SessionStartParams + .BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .Device + .DESKTOP + ) + .httpVersion( + SessionStartParams + .BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .HttpVersion + ._1 + ) + .addLocale("string") + .addOperatingSystem( + SessionStartParams + .BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .OperatingSystem + .ANDROID + ) + .screen( + SessionStartParams + .BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .Screen + .builder() + .maxHeight(0.0) + .maxWidth(0.0) + .minHeight(0.0) + .minWidth(0.0) + .build() + ) + .build() + ) + .logSession(true) + .recordSession(true) + .solveCaptchas(true) + .viewport( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .Viewport + .builder() + .height(0.0) + .width(0.0) + .build() + ) + .build() + ) + .extensionId("extensionId") + .keepAlive(true) + .projectId("projectId") + .proxies(true) + .region( + SessionStartParams.BrowserbaseSessionCreateParams.Region + .US_WEST_2 + ) + .timeout(0.0) + .userMetadata( + SessionStartParams.BrowserbaseSessionCreateParams.UserMetadata + .builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) + .build() + ) + .browserbaseSessionId("browserbaseSessionID") + .debugDom(true) + .domSettleTimeoutMs(5000.0) + .experimental(true) + .selfHeal(true) + .systemPrompt("systemPrompt") + .verbose(SessionStartParams.Verbose._1) + .waitForCaptchaSolves(true) .build() ) } @@ -370,7 +1322,7 @@ internal class ErrorHandlingTest { } @Test - fun sessionsAct404WithRawResponse() { + fun sessionsStart404WithRawResponse() { val sessionService = client.sessions().withRawResponse() stubFor( post(anyUrl()) @@ -381,29 +1333,165 @@ internal class ErrorHandlingTest { val e = assertThrows { - sessionService.act( - SessionActParams.builder() - .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") - .xLanguage(SessionActParams.XLanguage.TYPESCRIPT) + sessionService.start( + SessionStartParams.builder() + .xLanguage(SessionStartParams.XLanguage.TYPESCRIPT) .xSdkVersion("3.0.6") .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) - .xStreamResponse(SessionActParams.XStreamResponse.TRUE) - .input("Click the login button") - .frameId("frameId") - .options( - SessionActParams.Options.builder() - .model("string") - .timeout(30000.0) - .variables( - SessionActParams.Options.Variables.builder() - .putAdditionalProperty( - "username", - JsonValue.from("john_doe"), + .xStreamResponse(SessionStartParams.XStreamResponse.TRUE) + .modelName("gpt-4o") + .actTimeoutMs(30000.0) + .browser( + SessionStartParams.Browser.builder() + .cdpUrl("ws://localhost:9222") + .launchOptions( + SessionStartParams.Browser.LaunchOptions.builder() + .acceptDownloads(true) + .addArg("string") + .cdpUrl("cdpUrl") + .chromiumSandbox(true) + .connectTimeoutMs(0.0) + .deviceScaleFactor(0.0) + .devtools(true) + .downloadsPath("downloadsPath") + .executablePath("executablePath") + .hasTouch(true) + .headless(true) + .ignoreDefaultArgs(true) + .ignoreHttpsErrors(true) + .locale("locale") + .preserveUserDataDir(true) + .proxy( + SessionStartParams.Browser.LaunchOptions.Proxy.builder() + .server("server") + .bypass("bypass") + .password("password") + .username("username") + .build() + ) + .userDataDir("userDataDir") + .viewport( + SessionStartParams.Browser.LaunchOptions.Viewport + .builder() + .height(0.0) + .width(0.0) + .build() ) .build() ) + .type(SessionStartParams.Browser.Type.LOCAL) .build() ) + .browserbaseSessionCreateParams( + SessionStartParams.BrowserbaseSessionCreateParams.builder() + .browserSettings( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .builder() + .advancedStealth(true) + .blockAds(true) + .context( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .Context + .builder() + .id("id") + .persist(true) + .build() + ) + .extensionId("extensionId") + .fingerprint( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .builder() + .addBrowser( + SessionStartParams + .BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .Browser + .CHROME + ) + .addDevice( + SessionStartParams + .BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .Device + .DESKTOP + ) + .httpVersion( + SessionStartParams + .BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .HttpVersion + ._1 + ) + .addLocale("string") + .addOperatingSystem( + SessionStartParams + .BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .OperatingSystem + .ANDROID + ) + .screen( + SessionStartParams + .BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .Screen + .builder() + .maxHeight(0.0) + .maxWidth(0.0) + .minHeight(0.0) + .minWidth(0.0) + .build() + ) + .build() + ) + .logSession(true) + .recordSession(true) + .solveCaptchas(true) + .viewport( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .Viewport + .builder() + .height(0.0) + .width(0.0) + .build() + ) + .build() + ) + .extensionId("extensionId") + .keepAlive(true) + .projectId("projectId") + .proxies(true) + .region( + SessionStartParams.BrowserbaseSessionCreateParams.Region + .US_WEST_2 + ) + .timeout(0.0) + .userMetadata( + SessionStartParams.BrowserbaseSessionCreateParams.UserMetadata + .builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) + .build() + ) + .browserbaseSessionId("browserbaseSessionID") + .debugDom(true) + .domSettleTimeoutMs(5000.0) + .experimental(true) + .selfHeal(true) + .systemPrompt("systemPrompt") + .verbose(SessionStartParams.Verbose._1) + .waitForCaptchaSolves(true) .build() ) } @@ -414,7 +1502,7 @@ internal class ErrorHandlingTest { } @Test - fun sessionsAct422() { + fun sessionsStart422() { val sessionService = client.sessions() stubFor( post(anyUrl()) @@ -425,29 +1513,165 @@ internal class ErrorHandlingTest { val e = assertThrows { - sessionService.act( - SessionActParams.builder() - .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") - .xLanguage(SessionActParams.XLanguage.TYPESCRIPT) + sessionService.start( + SessionStartParams.builder() + .xLanguage(SessionStartParams.XLanguage.TYPESCRIPT) .xSdkVersion("3.0.6") .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) - .xStreamResponse(SessionActParams.XStreamResponse.TRUE) - .input("Click the login button") - .frameId("frameId") - .options( - SessionActParams.Options.builder() - .model("string") - .timeout(30000.0) - .variables( - SessionActParams.Options.Variables.builder() - .putAdditionalProperty( - "username", - JsonValue.from("john_doe"), + .xStreamResponse(SessionStartParams.XStreamResponse.TRUE) + .modelName("gpt-4o") + .actTimeoutMs(30000.0) + .browser( + SessionStartParams.Browser.builder() + .cdpUrl("ws://localhost:9222") + .launchOptions( + SessionStartParams.Browser.LaunchOptions.builder() + .acceptDownloads(true) + .addArg("string") + .cdpUrl("cdpUrl") + .chromiumSandbox(true) + .connectTimeoutMs(0.0) + .deviceScaleFactor(0.0) + .devtools(true) + .downloadsPath("downloadsPath") + .executablePath("executablePath") + .hasTouch(true) + .headless(true) + .ignoreDefaultArgs(true) + .ignoreHttpsErrors(true) + .locale("locale") + .preserveUserDataDir(true) + .proxy( + SessionStartParams.Browser.LaunchOptions.Proxy.builder() + .server("server") + .bypass("bypass") + .password("password") + .username("username") + .build() + ) + .userDataDir("userDataDir") + .viewport( + SessionStartParams.Browser.LaunchOptions.Viewport + .builder() + .height(0.0) + .width(0.0) + .build() ) .build() ) + .type(SessionStartParams.Browser.Type.LOCAL) .build() ) + .browserbaseSessionCreateParams( + SessionStartParams.BrowserbaseSessionCreateParams.builder() + .browserSettings( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .builder() + .advancedStealth(true) + .blockAds(true) + .context( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .Context + .builder() + .id("id") + .persist(true) + .build() + ) + .extensionId("extensionId") + .fingerprint( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .builder() + .addBrowser( + SessionStartParams + .BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .Browser + .CHROME + ) + .addDevice( + SessionStartParams + .BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .Device + .DESKTOP + ) + .httpVersion( + SessionStartParams + .BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .HttpVersion + ._1 + ) + .addLocale("string") + .addOperatingSystem( + SessionStartParams + .BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .OperatingSystem + .ANDROID + ) + .screen( + SessionStartParams + .BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .Screen + .builder() + .maxHeight(0.0) + .maxWidth(0.0) + .minHeight(0.0) + .minWidth(0.0) + .build() + ) + .build() + ) + .logSession(true) + .recordSession(true) + .solveCaptchas(true) + .viewport( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .Viewport + .builder() + .height(0.0) + .width(0.0) + .build() + ) + .build() + ) + .extensionId("extensionId") + .keepAlive(true) + .projectId("projectId") + .proxies(true) + .region( + SessionStartParams.BrowserbaseSessionCreateParams.Region + .US_WEST_2 + ) + .timeout(0.0) + .userMetadata( + SessionStartParams.BrowserbaseSessionCreateParams.UserMetadata + .builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) + .build() + ) + .browserbaseSessionId("browserbaseSessionID") + .debugDom(true) + .domSettleTimeoutMs(5000.0) + .experimental(true) + .selfHeal(true) + .systemPrompt("systemPrompt") + .verbose(SessionStartParams.Verbose._1) + .waitForCaptchaSolves(true) .build() ) } @@ -458,7 +1682,7 @@ internal class ErrorHandlingTest { } @Test - fun sessionsAct422WithRawResponse() { + fun sessionsStart422WithRawResponse() { val sessionService = client.sessions().withRawResponse() stubFor( post(anyUrl()) @@ -469,29 +1693,165 @@ internal class ErrorHandlingTest { val e = assertThrows { - sessionService.act( - SessionActParams.builder() - .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") - .xLanguage(SessionActParams.XLanguage.TYPESCRIPT) + sessionService.start( + SessionStartParams.builder() + .xLanguage(SessionStartParams.XLanguage.TYPESCRIPT) .xSdkVersion("3.0.6") .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) - .xStreamResponse(SessionActParams.XStreamResponse.TRUE) - .input("Click the login button") - .frameId("frameId") - .options( - SessionActParams.Options.builder() - .model("string") - .timeout(30000.0) - .variables( - SessionActParams.Options.Variables.builder() - .putAdditionalProperty( - "username", - JsonValue.from("john_doe"), + .xStreamResponse(SessionStartParams.XStreamResponse.TRUE) + .modelName("gpt-4o") + .actTimeoutMs(30000.0) + .browser( + SessionStartParams.Browser.builder() + .cdpUrl("ws://localhost:9222") + .launchOptions( + SessionStartParams.Browser.LaunchOptions.builder() + .acceptDownloads(true) + .addArg("string") + .cdpUrl("cdpUrl") + .chromiumSandbox(true) + .connectTimeoutMs(0.0) + .deviceScaleFactor(0.0) + .devtools(true) + .downloadsPath("downloadsPath") + .executablePath("executablePath") + .hasTouch(true) + .headless(true) + .ignoreDefaultArgs(true) + .ignoreHttpsErrors(true) + .locale("locale") + .preserveUserDataDir(true) + .proxy( + SessionStartParams.Browser.LaunchOptions.Proxy.builder() + .server("server") + .bypass("bypass") + .password("password") + .username("username") + .build() + ) + .userDataDir("userDataDir") + .viewport( + SessionStartParams.Browser.LaunchOptions.Viewport + .builder() + .height(0.0) + .width(0.0) + .build() + ) + .build() + ) + .type(SessionStartParams.Browser.Type.LOCAL) + .build() + ) + .browserbaseSessionCreateParams( + SessionStartParams.BrowserbaseSessionCreateParams.builder() + .browserSettings( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .builder() + .advancedStealth(true) + .blockAds(true) + .context( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .Context + .builder() + .id("id") + .persist(true) + .build() + ) + .extensionId("extensionId") + .fingerprint( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .builder() + .addBrowser( + SessionStartParams + .BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .Browser + .CHROME + ) + .addDevice( + SessionStartParams + .BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .Device + .DESKTOP + ) + .httpVersion( + SessionStartParams + .BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .HttpVersion + ._1 + ) + .addLocale("string") + .addOperatingSystem( + SessionStartParams + .BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .OperatingSystem + .ANDROID + ) + .screen( + SessionStartParams + .BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .Screen + .builder() + .maxHeight(0.0) + .maxWidth(0.0) + .minHeight(0.0) + .minWidth(0.0) + .build() + ) + .build() ) + .logSession(true) + .recordSession(true) + .solveCaptchas(true) + .viewport( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .Viewport + .builder() + .height(0.0) + .width(0.0) + .build() + ) + .build() + ) + .extensionId("extensionId") + .keepAlive(true) + .projectId("projectId") + .proxies(true) + .region( + SessionStartParams.BrowserbaseSessionCreateParams.Region + .US_WEST_2 + ) + .timeout(0.0) + .userMetadata( + SessionStartParams.BrowserbaseSessionCreateParams.UserMetadata + .builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) .build() ) .build() ) + .browserbaseSessionId("browserbaseSessionID") + .debugDom(true) + .domSettleTimeoutMs(5000.0) + .experimental(true) + .selfHeal(true) + .systemPrompt("systemPrompt") + .verbose(SessionStartParams.Verbose._1) + .waitForCaptchaSolves(true) .build() ) } @@ -502,7 +1862,7 @@ internal class ErrorHandlingTest { } @Test - fun sessionsAct429() { + fun sessionsStart429() { val sessionService = client.sessions() stubFor( post(anyUrl()) @@ -513,29 +1873,165 @@ internal class ErrorHandlingTest { val e = assertThrows { - sessionService.act( - SessionActParams.builder() - .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") - .xLanguage(SessionActParams.XLanguage.TYPESCRIPT) + sessionService.start( + SessionStartParams.builder() + .xLanguage(SessionStartParams.XLanguage.TYPESCRIPT) .xSdkVersion("3.0.6") .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) - .xStreamResponse(SessionActParams.XStreamResponse.TRUE) - .input("Click the login button") - .frameId("frameId") - .options( - SessionActParams.Options.builder() - .model("string") - .timeout(30000.0) - .variables( - SessionActParams.Options.Variables.builder() - .putAdditionalProperty( - "username", - JsonValue.from("john_doe"), + .xStreamResponse(SessionStartParams.XStreamResponse.TRUE) + .modelName("gpt-4o") + .actTimeoutMs(30000.0) + .browser( + SessionStartParams.Browser.builder() + .cdpUrl("ws://localhost:9222") + .launchOptions( + SessionStartParams.Browser.LaunchOptions.builder() + .acceptDownloads(true) + .addArg("string") + .cdpUrl("cdpUrl") + .chromiumSandbox(true) + .connectTimeoutMs(0.0) + .deviceScaleFactor(0.0) + .devtools(true) + .downloadsPath("downloadsPath") + .executablePath("executablePath") + .hasTouch(true) + .headless(true) + .ignoreDefaultArgs(true) + .ignoreHttpsErrors(true) + .locale("locale") + .preserveUserDataDir(true) + .proxy( + SessionStartParams.Browser.LaunchOptions.Proxy.builder() + .server("server") + .bypass("bypass") + .password("password") + .username("username") + .build() + ) + .userDataDir("userDataDir") + .viewport( + SessionStartParams.Browser.LaunchOptions.Viewport + .builder() + .height(0.0) + .width(0.0) + .build() ) .build() ) + .type(SessionStartParams.Browser.Type.LOCAL) .build() ) + .browserbaseSessionCreateParams( + SessionStartParams.BrowserbaseSessionCreateParams.builder() + .browserSettings( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .builder() + .advancedStealth(true) + .blockAds(true) + .context( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .Context + .builder() + .id("id") + .persist(true) + .build() + ) + .extensionId("extensionId") + .fingerprint( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .builder() + .addBrowser( + SessionStartParams + .BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .Browser + .CHROME + ) + .addDevice( + SessionStartParams + .BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .Device + .DESKTOP + ) + .httpVersion( + SessionStartParams + .BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .HttpVersion + ._1 + ) + .addLocale("string") + .addOperatingSystem( + SessionStartParams + .BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .OperatingSystem + .ANDROID + ) + .screen( + SessionStartParams + .BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .Screen + .builder() + .maxHeight(0.0) + .maxWidth(0.0) + .minHeight(0.0) + .minWidth(0.0) + .build() + ) + .build() + ) + .logSession(true) + .recordSession(true) + .solveCaptchas(true) + .viewport( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .Viewport + .builder() + .height(0.0) + .width(0.0) + .build() + ) + .build() + ) + .extensionId("extensionId") + .keepAlive(true) + .projectId("projectId") + .proxies(true) + .region( + SessionStartParams.BrowserbaseSessionCreateParams.Region + .US_WEST_2 + ) + .timeout(0.0) + .userMetadata( + SessionStartParams.BrowserbaseSessionCreateParams.UserMetadata + .builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) + .build() + ) + .browserbaseSessionId("browserbaseSessionID") + .debugDom(true) + .domSettleTimeoutMs(5000.0) + .experimental(true) + .selfHeal(true) + .systemPrompt("systemPrompt") + .verbose(SessionStartParams.Verbose._1) + .waitForCaptchaSolves(true) .build() ) } @@ -546,7 +2042,7 @@ internal class ErrorHandlingTest { } @Test - fun sessionsAct429WithRawResponse() { + fun sessionsStart429WithRawResponse() { val sessionService = client.sessions().withRawResponse() stubFor( post(anyUrl()) @@ -557,29 +2053,165 @@ internal class ErrorHandlingTest { val e = assertThrows { - sessionService.act( - SessionActParams.builder() - .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") - .xLanguage(SessionActParams.XLanguage.TYPESCRIPT) + sessionService.start( + SessionStartParams.builder() + .xLanguage(SessionStartParams.XLanguage.TYPESCRIPT) .xSdkVersion("3.0.6") .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) - .xStreamResponse(SessionActParams.XStreamResponse.TRUE) - .input("Click the login button") - .frameId("frameId") - .options( - SessionActParams.Options.builder() - .model("string") - .timeout(30000.0) - .variables( - SessionActParams.Options.Variables.builder() - .putAdditionalProperty( - "username", - JsonValue.from("john_doe"), + .xStreamResponse(SessionStartParams.XStreamResponse.TRUE) + .modelName("gpt-4o") + .actTimeoutMs(30000.0) + .browser( + SessionStartParams.Browser.builder() + .cdpUrl("ws://localhost:9222") + .launchOptions( + SessionStartParams.Browser.LaunchOptions.builder() + .acceptDownloads(true) + .addArg("string") + .cdpUrl("cdpUrl") + .chromiumSandbox(true) + .connectTimeoutMs(0.0) + .deviceScaleFactor(0.0) + .devtools(true) + .downloadsPath("downloadsPath") + .executablePath("executablePath") + .hasTouch(true) + .headless(true) + .ignoreDefaultArgs(true) + .ignoreHttpsErrors(true) + .locale("locale") + .preserveUserDataDir(true) + .proxy( + SessionStartParams.Browser.LaunchOptions.Proxy.builder() + .server("server") + .bypass("bypass") + .password("password") + .username("username") + .build() + ) + .userDataDir("userDataDir") + .viewport( + SessionStartParams.Browser.LaunchOptions.Viewport + .builder() + .height(0.0) + .width(0.0) + .build() ) .build() ) + .type(SessionStartParams.Browser.Type.LOCAL) .build() ) + .browserbaseSessionCreateParams( + SessionStartParams.BrowserbaseSessionCreateParams.builder() + .browserSettings( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .builder() + .advancedStealth(true) + .blockAds(true) + .context( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .Context + .builder() + .id("id") + .persist(true) + .build() + ) + .extensionId("extensionId") + .fingerprint( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .builder() + .addBrowser( + SessionStartParams + .BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .Browser + .CHROME + ) + .addDevice( + SessionStartParams + .BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .Device + .DESKTOP + ) + .httpVersion( + SessionStartParams + .BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .HttpVersion + ._1 + ) + .addLocale("string") + .addOperatingSystem( + SessionStartParams + .BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .OperatingSystem + .ANDROID + ) + .screen( + SessionStartParams + .BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .Screen + .builder() + .maxHeight(0.0) + .maxWidth(0.0) + .minHeight(0.0) + .minWidth(0.0) + .build() + ) + .build() + ) + .logSession(true) + .recordSession(true) + .solveCaptchas(true) + .viewport( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .Viewport + .builder() + .height(0.0) + .width(0.0) + .build() + ) + .build() + ) + .extensionId("extensionId") + .keepAlive(true) + .projectId("projectId") + .proxies(true) + .region( + SessionStartParams.BrowserbaseSessionCreateParams.Region + .US_WEST_2 + ) + .timeout(0.0) + .userMetadata( + SessionStartParams.BrowserbaseSessionCreateParams.UserMetadata + .builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) + .build() + ) + .browserbaseSessionId("browserbaseSessionID") + .debugDom(true) + .domSettleTimeoutMs(5000.0) + .experimental(true) + .selfHeal(true) + .systemPrompt("systemPrompt") + .verbose(SessionStartParams.Verbose._1) + .waitForCaptchaSolves(true) .build() ) } @@ -590,7 +2222,7 @@ internal class ErrorHandlingTest { } @Test - fun sessionsAct500() { + fun sessionsStart500() { val sessionService = client.sessions() stubFor( post(anyUrl()) @@ -601,29 +2233,165 @@ internal class ErrorHandlingTest { val e = assertThrows { - sessionService.act( - SessionActParams.builder() - .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") - .xLanguage(SessionActParams.XLanguage.TYPESCRIPT) + sessionService.start( + SessionStartParams.builder() + .xLanguage(SessionStartParams.XLanguage.TYPESCRIPT) .xSdkVersion("3.0.6") .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) - .xStreamResponse(SessionActParams.XStreamResponse.TRUE) - .input("Click the login button") - .frameId("frameId") - .options( - SessionActParams.Options.builder() - .model("string") - .timeout(30000.0) - .variables( - SessionActParams.Options.Variables.builder() - .putAdditionalProperty( - "username", - JsonValue.from("john_doe"), + .xStreamResponse(SessionStartParams.XStreamResponse.TRUE) + .modelName("gpt-4o") + .actTimeoutMs(30000.0) + .browser( + SessionStartParams.Browser.builder() + .cdpUrl("ws://localhost:9222") + .launchOptions( + SessionStartParams.Browser.LaunchOptions.builder() + .acceptDownloads(true) + .addArg("string") + .cdpUrl("cdpUrl") + .chromiumSandbox(true) + .connectTimeoutMs(0.0) + .deviceScaleFactor(0.0) + .devtools(true) + .downloadsPath("downloadsPath") + .executablePath("executablePath") + .hasTouch(true) + .headless(true) + .ignoreDefaultArgs(true) + .ignoreHttpsErrors(true) + .locale("locale") + .preserveUserDataDir(true) + .proxy( + SessionStartParams.Browser.LaunchOptions.Proxy.builder() + .server("server") + .bypass("bypass") + .password("password") + .username("username") + .build() + ) + .userDataDir("userDataDir") + .viewport( + SessionStartParams.Browser.LaunchOptions.Viewport + .builder() + .height(0.0) + .width(0.0) + .build() ) .build() ) + .type(SessionStartParams.Browser.Type.LOCAL) .build() ) + .browserbaseSessionCreateParams( + SessionStartParams.BrowserbaseSessionCreateParams.builder() + .browserSettings( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .builder() + .advancedStealth(true) + .blockAds(true) + .context( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .Context + .builder() + .id("id") + .persist(true) + .build() + ) + .extensionId("extensionId") + .fingerprint( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .builder() + .addBrowser( + SessionStartParams + .BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .Browser + .CHROME + ) + .addDevice( + SessionStartParams + .BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .Device + .DESKTOP + ) + .httpVersion( + SessionStartParams + .BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .HttpVersion + ._1 + ) + .addLocale("string") + .addOperatingSystem( + SessionStartParams + .BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .OperatingSystem + .ANDROID + ) + .screen( + SessionStartParams + .BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .Screen + .builder() + .maxHeight(0.0) + .maxWidth(0.0) + .minHeight(0.0) + .minWidth(0.0) + .build() + ) + .build() + ) + .logSession(true) + .recordSession(true) + .solveCaptchas(true) + .viewport( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .Viewport + .builder() + .height(0.0) + .width(0.0) + .build() + ) + .build() + ) + .extensionId("extensionId") + .keepAlive(true) + .projectId("projectId") + .proxies(true) + .region( + SessionStartParams.BrowserbaseSessionCreateParams.Region + .US_WEST_2 + ) + .timeout(0.0) + .userMetadata( + SessionStartParams.BrowserbaseSessionCreateParams.UserMetadata + .builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) + .build() + ) + .browserbaseSessionId("browserbaseSessionID") + .debugDom(true) + .domSettleTimeoutMs(5000.0) + .experimental(true) + .selfHeal(true) + .systemPrompt("systemPrompt") + .verbose(SessionStartParams.Verbose._1) + .waitForCaptchaSolves(true) .build() ) } @@ -634,7 +2402,7 @@ internal class ErrorHandlingTest { } @Test - fun sessionsAct500WithRawResponse() { + fun sessionsStart500WithRawResponse() { val sessionService = client.sessions().withRawResponse() stubFor( post(anyUrl()) @@ -645,29 +2413,165 @@ internal class ErrorHandlingTest { val e = assertThrows { - sessionService.act( - SessionActParams.builder() - .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") - .xLanguage(SessionActParams.XLanguage.TYPESCRIPT) + sessionService.start( + SessionStartParams.builder() + .xLanguage(SessionStartParams.XLanguage.TYPESCRIPT) .xSdkVersion("3.0.6") .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) - .xStreamResponse(SessionActParams.XStreamResponse.TRUE) - .input("Click the login button") - .frameId("frameId") - .options( - SessionActParams.Options.builder() - .model("string") - .timeout(30000.0) - .variables( - SessionActParams.Options.Variables.builder() - .putAdditionalProperty( - "username", - JsonValue.from("john_doe"), + .xStreamResponse(SessionStartParams.XStreamResponse.TRUE) + .modelName("gpt-4o") + .actTimeoutMs(30000.0) + .browser( + SessionStartParams.Browser.builder() + .cdpUrl("ws://localhost:9222") + .launchOptions( + SessionStartParams.Browser.LaunchOptions.builder() + .acceptDownloads(true) + .addArg("string") + .cdpUrl("cdpUrl") + .chromiumSandbox(true) + .connectTimeoutMs(0.0) + .deviceScaleFactor(0.0) + .devtools(true) + .downloadsPath("downloadsPath") + .executablePath("executablePath") + .hasTouch(true) + .headless(true) + .ignoreDefaultArgs(true) + .ignoreHttpsErrors(true) + .locale("locale") + .preserveUserDataDir(true) + .proxy( + SessionStartParams.Browser.LaunchOptions.Proxy.builder() + .server("server") + .bypass("bypass") + .password("password") + .username("username") + .build() + ) + .userDataDir("userDataDir") + .viewport( + SessionStartParams.Browser.LaunchOptions.Viewport + .builder() + .height(0.0) + .width(0.0) + .build() ) .build() ) + .type(SessionStartParams.Browser.Type.LOCAL) .build() ) + .browserbaseSessionCreateParams( + SessionStartParams.BrowserbaseSessionCreateParams.builder() + .browserSettings( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .builder() + .advancedStealth(true) + .blockAds(true) + .context( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .Context + .builder() + .id("id") + .persist(true) + .build() + ) + .extensionId("extensionId") + .fingerprint( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .builder() + .addBrowser( + SessionStartParams + .BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .Browser + .CHROME + ) + .addDevice( + SessionStartParams + .BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .Device + .DESKTOP + ) + .httpVersion( + SessionStartParams + .BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .HttpVersion + ._1 + ) + .addLocale("string") + .addOperatingSystem( + SessionStartParams + .BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .OperatingSystem + .ANDROID + ) + .screen( + SessionStartParams + .BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .Screen + .builder() + .maxHeight(0.0) + .maxWidth(0.0) + .minHeight(0.0) + .minWidth(0.0) + .build() + ) + .build() + ) + .logSession(true) + .recordSession(true) + .solveCaptchas(true) + .viewport( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .Viewport + .builder() + .height(0.0) + .width(0.0) + .build() + ) + .build() + ) + .extensionId("extensionId") + .keepAlive(true) + .projectId("projectId") + .proxies(true) + .region( + SessionStartParams.BrowserbaseSessionCreateParams.Region + .US_WEST_2 + ) + .timeout(0.0) + .userMetadata( + SessionStartParams.BrowserbaseSessionCreateParams.UserMetadata + .builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) + .build() + ) + .browserbaseSessionId("browserbaseSessionID") + .debugDom(true) + .domSettleTimeoutMs(5000.0) + .experimental(true) + .selfHeal(true) + .systemPrompt("systemPrompt") + .verbose(SessionStartParams.Verbose._1) + .waitForCaptchaSolves(true) .build() ) } @@ -678,7 +2582,7 @@ internal class ErrorHandlingTest { } @Test - fun sessionsAct999() { + fun sessionsStart999() { val sessionService = client.sessions() stubFor( post(anyUrl()) @@ -689,29 +2593,165 @@ internal class ErrorHandlingTest { val e = assertThrows { - sessionService.act( - SessionActParams.builder() - .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") - .xLanguage(SessionActParams.XLanguage.TYPESCRIPT) + sessionService.start( + SessionStartParams.builder() + .xLanguage(SessionStartParams.XLanguage.TYPESCRIPT) .xSdkVersion("3.0.6") .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) - .xStreamResponse(SessionActParams.XStreamResponse.TRUE) - .input("Click the login button") - .frameId("frameId") - .options( - SessionActParams.Options.builder() - .model("string") - .timeout(30000.0) - .variables( - SessionActParams.Options.Variables.builder() - .putAdditionalProperty( - "username", - JsonValue.from("john_doe"), + .xStreamResponse(SessionStartParams.XStreamResponse.TRUE) + .modelName("gpt-4o") + .actTimeoutMs(30000.0) + .browser( + SessionStartParams.Browser.builder() + .cdpUrl("ws://localhost:9222") + .launchOptions( + SessionStartParams.Browser.LaunchOptions.builder() + .acceptDownloads(true) + .addArg("string") + .cdpUrl("cdpUrl") + .chromiumSandbox(true) + .connectTimeoutMs(0.0) + .deviceScaleFactor(0.0) + .devtools(true) + .downloadsPath("downloadsPath") + .executablePath("executablePath") + .hasTouch(true) + .headless(true) + .ignoreDefaultArgs(true) + .ignoreHttpsErrors(true) + .locale("locale") + .preserveUserDataDir(true) + .proxy( + SessionStartParams.Browser.LaunchOptions.Proxy.builder() + .server("server") + .bypass("bypass") + .password("password") + .username("username") + .build() + ) + .userDataDir("userDataDir") + .viewport( + SessionStartParams.Browser.LaunchOptions.Viewport + .builder() + .height(0.0) + .width(0.0) + .build() ) .build() ) + .type(SessionStartParams.Browser.Type.LOCAL) + .build() + ) + .browserbaseSessionCreateParams( + SessionStartParams.BrowserbaseSessionCreateParams.builder() + .browserSettings( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .builder() + .advancedStealth(true) + .blockAds(true) + .context( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .Context + .builder() + .id("id") + .persist(true) + .build() + ) + .extensionId("extensionId") + .fingerprint( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .builder() + .addBrowser( + SessionStartParams + .BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .Browser + .CHROME + ) + .addDevice( + SessionStartParams + .BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .Device + .DESKTOP + ) + .httpVersion( + SessionStartParams + .BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .HttpVersion + ._1 + ) + .addLocale("string") + .addOperatingSystem( + SessionStartParams + .BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .OperatingSystem + .ANDROID + ) + .screen( + SessionStartParams + .BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .Screen + .builder() + .maxHeight(0.0) + .maxWidth(0.0) + .minHeight(0.0) + .minWidth(0.0) + .build() + ) + .build() + ) + .logSession(true) + .recordSession(true) + .solveCaptchas(true) + .viewport( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .Viewport + .builder() + .height(0.0) + .width(0.0) + .build() + ) + .build() + ) + .extensionId("extensionId") + .keepAlive(true) + .projectId("projectId") + .proxies(true) + .region( + SessionStartParams.BrowserbaseSessionCreateParams.Region + .US_WEST_2 + ) + .timeout(0.0) + .userMetadata( + SessionStartParams.BrowserbaseSessionCreateParams.UserMetadata + .builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) .build() ) + .browserbaseSessionId("browserbaseSessionID") + .debugDom(true) + .domSettleTimeoutMs(5000.0) + .experimental(true) + .selfHeal(true) + .systemPrompt("systemPrompt") + .verbose(SessionStartParams.Verbose._1) + .waitForCaptchaSolves(true) .build() ) } @@ -722,7 +2762,7 @@ internal class ErrorHandlingTest { } @Test - fun sessionsAct999WithRawResponse() { + fun sessionsStart999WithRawResponse() { val sessionService = client.sessions().withRawResponse() stubFor( post(anyUrl()) @@ -733,29 +2773,165 @@ internal class ErrorHandlingTest { val e = assertThrows { - sessionService.act( - SessionActParams.builder() - .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") - .xLanguage(SessionActParams.XLanguage.TYPESCRIPT) + sessionService.start( + SessionStartParams.builder() + .xLanguage(SessionStartParams.XLanguage.TYPESCRIPT) .xSdkVersion("3.0.6") .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) - .xStreamResponse(SessionActParams.XStreamResponse.TRUE) - .input("Click the login button") - .frameId("frameId") - .options( - SessionActParams.Options.builder() - .model("string") - .timeout(30000.0) - .variables( - SessionActParams.Options.Variables.builder() - .putAdditionalProperty( - "username", - JsonValue.from("john_doe"), + .xStreamResponse(SessionStartParams.XStreamResponse.TRUE) + .modelName("gpt-4o") + .actTimeoutMs(30000.0) + .browser( + SessionStartParams.Browser.builder() + .cdpUrl("ws://localhost:9222") + .launchOptions( + SessionStartParams.Browser.LaunchOptions.builder() + .acceptDownloads(true) + .addArg("string") + .cdpUrl("cdpUrl") + .chromiumSandbox(true) + .connectTimeoutMs(0.0) + .deviceScaleFactor(0.0) + .devtools(true) + .downloadsPath("downloadsPath") + .executablePath("executablePath") + .hasTouch(true) + .headless(true) + .ignoreDefaultArgs(true) + .ignoreHttpsErrors(true) + .locale("locale") + .preserveUserDataDir(true) + .proxy( + SessionStartParams.Browser.LaunchOptions.Proxy.builder() + .server("server") + .bypass("bypass") + .password("password") + .username("username") + .build() + ) + .userDataDir("userDataDir") + .viewport( + SessionStartParams.Browser.LaunchOptions.Viewport + .builder() + .height(0.0) + .width(0.0) + .build() + ) + .build() + ) + .type(SessionStartParams.Browser.Type.LOCAL) + .build() + ) + .browserbaseSessionCreateParams( + SessionStartParams.BrowserbaseSessionCreateParams.builder() + .browserSettings( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .builder() + .advancedStealth(true) + .blockAds(true) + .context( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .Context + .builder() + .id("id") + .persist(true) + .build() + ) + .extensionId("extensionId") + .fingerprint( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .builder() + .addBrowser( + SessionStartParams + .BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .Browser + .CHROME + ) + .addDevice( + SessionStartParams + .BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .Device + .DESKTOP + ) + .httpVersion( + SessionStartParams + .BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .HttpVersion + ._1 + ) + .addLocale("string") + .addOperatingSystem( + SessionStartParams + .BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .OperatingSystem + .ANDROID + ) + .screen( + SessionStartParams + .BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .Screen + .builder() + .maxHeight(0.0) + .maxWidth(0.0) + .minHeight(0.0) + .minWidth(0.0) + .build() + ) + .build() + ) + .logSession(true) + .recordSession(true) + .solveCaptchas(true) + .viewport( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .Viewport + .builder() + .height(0.0) + .width(0.0) + .build() ) .build() ) + .extensionId("extensionId") + .keepAlive(true) + .projectId("projectId") + .proxies(true) + .region( + SessionStartParams.BrowserbaseSessionCreateParams.Region + .US_WEST_2 + ) + .timeout(0.0) + .userMetadata( + SessionStartParams.BrowserbaseSessionCreateParams.UserMetadata + .builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) .build() ) + .browserbaseSessionId("browserbaseSessionID") + .debugDom(true) + .domSettleTimeoutMs(5000.0) + .experimental(true) + .selfHeal(true) + .systemPrompt("systemPrompt") + .verbose(SessionStartParams.Verbose._1) + .waitForCaptchaSolves(true) .build() ) } @@ -766,7 +2942,7 @@ internal class ErrorHandlingTest { } @Test - fun sessionsActInvalidJsonBody() { + fun sessionsStartInvalidJsonBody() { val sessionService = client.sessions() stubFor( post(anyUrl()) @@ -775,29 +2951,165 @@ internal class ErrorHandlingTest { val e = assertThrows { - sessionService.act( - SessionActParams.builder() - .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") - .xLanguage(SessionActParams.XLanguage.TYPESCRIPT) + sessionService.start( + SessionStartParams.builder() + .xLanguage(SessionStartParams.XLanguage.TYPESCRIPT) .xSdkVersion("3.0.6") .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) - .xStreamResponse(SessionActParams.XStreamResponse.TRUE) - .input("Click the login button") - .frameId("frameId") - .options( - SessionActParams.Options.builder() - .model("string") - .timeout(30000.0) - .variables( - SessionActParams.Options.Variables.builder() - .putAdditionalProperty( - "username", - JsonValue.from("john_doe"), + .xStreamResponse(SessionStartParams.XStreamResponse.TRUE) + .modelName("gpt-4o") + .actTimeoutMs(30000.0) + .browser( + SessionStartParams.Browser.builder() + .cdpUrl("ws://localhost:9222") + .launchOptions( + SessionStartParams.Browser.LaunchOptions.builder() + .acceptDownloads(true) + .addArg("string") + .cdpUrl("cdpUrl") + .chromiumSandbox(true) + .connectTimeoutMs(0.0) + .deviceScaleFactor(0.0) + .devtools(true) + .downloadsPath("downloadsPath") + .executablePath("executablePath") + .hasTouch(true) + .headless(true) + .ignoreDefaultArgs(true) + .ignoreHttpsErrors(true) + .locale("locale") + .preserveUserDataDir(true) + .proxy( + SessionStartParams.Browser.LaunchOptions.Proxy.builder() + .server("server") + .bypass("bypass") + .password("password") + .username("username") + .build() ) + .userDataDir("userDataDir") + .viewport( + SessionStartParams.Browser.LaunchOptions.Viewport + .builder() + .height(0.0) + .width(0.0) + .build() + ) + .build() + ) + .type(SessionStartParams.Browser.Type.LOCAL) + .build() + ) + .browserbaseSessionCreateParams( + SessionStartParams.BrowserbaseSessionCreateParams.builder() + .browserSettings( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .builder() + .advancedStealth(true) + .blockAds(true) + .context( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .Context + .builder() + .id("id") + .persist(true) + .build() + ) + .extensionId("extensionId") + .fingerprint( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .builder() + .addBrowser( + SessionStartParams + .BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .Browser + .CHROME + ) + .addDevice( + SessionStartParams + .BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .Device + .DESKTOP + ) + .httpVersion( + SessionStartParams + .BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .HttpVersion + ._1 + ) + .addLocale("string") + .addOperatingSystem( + SessionStartParams + .BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .OperatingSystem + .ANDROID + ) + .screen( + SessionStartParams + .BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .Screen + .builder() + .maxHeight(0.0) + .maxWidth(0.0) + .minHeight(0.0) + .minWidth(0.0) + .build() + ) + .build() + ) + .logSession(true) + .recordSession(true) + .solveCaptchas(true) + .viewport( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .Viewport + .builder() + .height(0.0) + .width(0.0) + .build() + ) + .build() + ) + .extensionId("extensionId") + .keepAlive(true) + .projectId("projectId") + .proxies(true) + .region( + SessionStartParams.BrowserbaseSessionCreateParams.Region + .US_WEST_2 + ) + .timeout(0.0) + .userMetadata( + SessionStartParams.BrowserbaseSessionCreateParams.UserMetadata + .builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) .build() ) .build() ) + .browserbaseSessionId("browserbaseSessionID") + .debugDom(true) + .domSettleTimeoutMs(5000.0) + .experimental(true) + .selfHeal(true) + .systemPrompt("systemPrompt") + .verbose(SessionStartParams.Verbose._1) + .waitForCaptchaSolves(true) .build() ) } diff --git a/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/ServiceParamsTest.kt b/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/ServiceParamsTest.kt index 060d011..ecf30b0 100644 --- a/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/ServiceParamsTest.kt +++ b/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/ServiceParamsTest.kt @@ -6,6 +6,7 @@ import com.browserbase.api.client.StagehandClient import com.browserbase.api.client.okhttp.StagehandOkHttpClient import com.browserbase.api.core.JsonValue import com.browserbase.api.models.sessions.SessionActParams +import com.browserbase.api.models.sessions.SessionStartParams import com.github.tomakehurst.wiremock.client.WireMock.anyUrl import com.github.tomakehurst.wiremock.client.WireMock.equalTo import com.github.tomakehurst.wiremock.client.WireMock.matchingJsonPath @@ -39,6 +40,174 @@ internal class ServiceParamsTest { .build() } + @Disabled("Prism tests are disabled") + @Test + fun start() { + val sessionService = client.sessions() + stubFor(post(anyUrl()).willReturn(ok("{}"))) + + sessionService.start( + SessionStartParams.builder() + .xLanguage(SessionStartParams.XLanguage.TYPESCRIPT) + .xSdkVersion("3.0.6") + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) + .xStreamResponse(SessionStartParams.XStreamResponse.TRUE) + .modelName("gpt-4o") + .actTimeoutMs(30000.0) + .browser( + SessionStartParams.Browser.builder() + .cdpUrl("ws://localhost:9222") + .launchOptions( + SessionStartParams.Browser.LaunchOptions.builder() + .acceptDownloads(true) + .addArg("string") + .cdpUrl("cdpUrl") + .chromiumSandbox(true) + .connectTimeoutMs(0.0) + .deviceScaleFactor(0.0) + .devtools(true) + .downloadsPath("downloadsPath") + .executablePath("executablePath") + .hasTouch(true) + .headless(true) + .ignoreDefaultArgs(true) + .ignoreHttpsErrors(true) + .locale("locale") + .preserveUserDataDir(true) + .proxy( + SessionStartParams.Browser.LaunchOptions.Proxy.builder() + .server("server") + .bypass("bypass") + .password("password") + .username("username") + .build() + ) + .userDataDir("userDataDir") + .viewport( + SessionStartParams.Browser.LaunchOptions.Viewport.builder() + .height(0.0) + .width(0.0) + .build() + ) + .build() + ) + .type(SessionStartParams.Browser.Type.LOCAL) + .build() + ) + .browserbaseSessionCreateParams( + SessionStartParams.BrowserbaseSessionCreateParams.builder() + .browserSettings( + SessionStartParams.BrowserbaseSessionCreateParams.BrowserSettings + .builder() + .advancedStealth(true) + .blockAds(true) + .context( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .Context + .builder() + .id("id") + .persist(true) + .build() + ) + .extensionId("extensionId") + .fingerprint( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .builder() + .addBrowser( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .Browser + .CHROME + ) + .addDevice( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .Device + .DESKTOP + ) + .httpVersion( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .HttpVersion + ._1 + ) + .addLocale("string") + .addOperatingSystem( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .OperatingSystem + .ANDROID + ) + .screen( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .Fingerprint + .Screen + .builder() + .maxHeight(0.0) + .maxWidth(0.0) + .minHeight(0.0) + .minWidth(0.0) + .build() + ) + .build() + ) + .logSession(true) + .recordSession(true) + .solveCaptchas(true) + .viewport( + SessionStartParams.BrowserbaseSessionCreateParams + .BrowserSettings + .Viewport + .builder() + .height(0.0) + .width(0.0) + .build() + ) + .build() + ) + .extensionId("extensionId") + .keepAlive(true) + .projectId("projectId") + .proxies(true) + .region(SessionStartParams.BrowserbaseSessionCreateParams.Region.US_WEST_2) + .timeout(0.0) + .userMetadata( + SessionStartParams.BrowserbaseSessionCreateParams.UserMetadata.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) + .build() + ) + .browserbaseSessionId("browserbaseSessionID") + .debugDom(true) + .domSettleTimeoutMs(5000.0) + .experimental(true) + .selfHeal(true) + .systemPrompt("systemPrompt") + .verbose(SessionStartParams.Verbose._1) + .waitForCaptchaSolves(true) + .putAdditionalHeader("Secret-Header", "42") + .putAdditionalQueryParam("secret_query_param", "42") + .putAdditionalBodyProperty("secretProperty", JsonValue.from("42")) + .build() + ) + + verify( + postRequestedFor(anyUrl()) + .withHeader("Secret-Header", equalTo("42")) + .withQueryParam("secret_query_param", equalTo("42")) + .withRequestBody(matchingJsonPath("$.secretProperty", equalTo("42"))) + ) + } + @Disabled("Prism tests are disabled") @Test fun act() { From adace53fc3e4a0fb4b866172aec98519ec0f29d5 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 17 Dec 2025 18:24:23 +0000 Subject: [PATCH 06/18] feat(api): manual updates --- .stats.yml | 2 +- README.md | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.stats.yml b/.stats.yml index a5338dd..4bcf91f 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: abc9d1eb9779bb5629eaed7074c42809 +config_hash: 0f2a6f228fb92683466c107fce3bcd21 diff --git a/README.md b/README.md index 852c752..15d5186 100644 --- a/README.md +++ b/README.md @@ -56,7 +56,7 @@ import com.browserbase.api.models.sessions.SessionActResponse; StagehandClient client = StagehandOkHttpClient.fromEnv(); SessionActParams params = SessionActParams.builder() - .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") + .id("00000000-your-session-id-000000000000") .input("click the first link on the page") .build(); SessionActResponse response = client.sessions().act(params); @@ -162,7 +162,7 @@ import java.util.concurrent.CompletableFuture; StagehandClient client = StagehandOkHttpClient.fromEnv(); SessionActParams params = SessionActParams.builder() - .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") + .id("00000000-your-session-id-000000000000") .input("click the first link on the page") .build(); CompletableFuture response = client.async().sessions().act(params); @@ -182,7 +182,7 @@ import java.util.concurrent.CompletableFuture; StagehandClientAsync client = StagehandOkHttpClientAsync.fromEnv(); SessionActParams params = SessionActParams.builder() - .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") + .id("00000000-your-session-id-000000000000") .input("click the first link on the page") .build(); CompletableFuture response = client.sessions().act(params); From 3cf20739785134610aa7bcbdbce3215c3c3a9970 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 17 Dec 2025 18:26:29 +0000 Subject: [PATCH 07/18] feat(api): manual updates --- .stats.yml | 2 +- README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 4bcf91f..2790605 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: 0f2a6f228fb92683466c107fce3bcd21 +config_hash: 88e87ba7021be93d267ecfc8f5e6b891 diff --git a/README.md b/README.md index 15d5186..3c37038 100644 --- a/README.md +++ b/README.md @@ -203,7 +203,7 @@ import com.browserbase.api.models.sessions.SessionStartParams; import com.browserbase.api.models.sessions.SessionStartResponse; SessionStartParams params = SessionStartParams.builder() - .modelName("gpt-4o") + .modelName("openai/gpt-5-nano") .build(); HttpResponseFor response = client.sessions().withRawResponse().start(params); From 07db616b7209716efa346035d65f5d7bf616c992 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 17 Dec 2025 18:46:23 +0000 Subject: [PATCH 08/18] feat(api): manual updates --- .stats.yml | 4 +- .../main/kotlin/stagehand.publish.gradle.kts | 2 +- .../api/models/sessions/SessionActResponse.kt | 143 +---- .../api/models/sessions/SessionEndResponse.kt | 190 +----- .../models/sessions/SessionExecuteResponse.kt | 143 +---- .../models/sessions/SessionExtractResponse.kt | 143 +---- .../sessions/SessionNavigateResponse.kt | 143 +---- .../models/sessions/SessionObserveResponse.kt | 143 +---- .../api/models/sessions/SessionStartParams.kt | 546 +++--------------- .../models/sessions/SessionStartResponse.kt | 143 +---- .../models/sessions/SessionActResponseTest.kt | 6 +- .../models/sessions/SessionEndResponseTest.kt | 8 +- .../sessions/SessionExecuteResponseTest.kt | 6 +- .../sessions/SessionExtractResponseTest.kt | 6 +- .../sessions/SessionNavigateResponseTest.kt | 7 +- .../sessions/SessionObserveResponseTest.kt | 6 +- .../models/sessions/SessionStartParamsTest.kt | 8 +- .../sessions/SessionStartResponseTest.kt | 6 +- .../api/services/ErrorHandlingTest.kt | 34 +- .../api/services/ServiceParamsTest.kt | 2 +- .../services/async/SessionServiceAsyncTest.kt | 2 +- .../services/blocking/SessionServiceTest.kt | 2 +- 22 files changed, 229 insertions(+), 1464 deletions(-) diff --git a/.stats.yml b/.stats.yml index 2790605..08f0cef 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 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/browserbase%2Fstagehand-d571232203ef4e00986a3245224267db6f8aaffdad57780f712e0694dc8d9e37.yml +openapi_spec_hash: d5d635dd7b24a2e1255c6f2a895253ff config_hash: 88e87ba7021be93d267ecfc8f5e6b891 diff --git a/buildSrc/src/main/kotlin/stagehand.publish.gradle.kts b/buildSrc/src/main/kotlin/stagehand.publish.gradle.kts index 796aad4..7b0ce3f 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-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionActResponse.kt b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionActResponse.kt index bfa1f65..db27614 100644 --- a/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionActResponse.kt +++ b/stagehand-java-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 @@ -24,14 +23,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()) /** @@ -41,10 +40,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]. @@ -58,7 +59,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) { @@ -90,7 +91,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() @JvmSynthetic @@ -110,15 +111,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() @@ -168,7 +170,7 @@ private constructor( } data().validate() - success().validate() + success() validated = true } @@ -187,8 +189,7 @@ private constructor( */ @JvmSynthetic internal fun validity(): Int = - (data.asKnown().getOrNull()?.validity() ?: 0) + - (success.asKnown().getOrNull()?.validity() ?: 0) + (data.asKnown().getOrNull()?.validity() ?: 0) + (if (success.asKnown().isPresent) 1 else 0) class Data @JsonCreator(mode = JsonCreator.Mode.DISABLED) @@ -690,124 +691,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 { - - @JvmField val TRUE = of(true) - - @JvmStatic 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().orElseThrow { - 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. - */ - @JvmSynthetic 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-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionEndResponse.kt b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionEndResponse.kt index 3bed0ac..3345222 100644 --- a/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionEndResponse.kt +++ b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionEndResponse.kt @@ -2,12 +2,9 @@ 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 import com.browserbase.api.core.JsonValue -import com.browserbase.api.core.checkRequired import com.browserbase.api.errors.StagehandInvalidDataException import com.fasterxml.jackson.annotation.JsonAnyGetter import com.fasterxml.jackson.annotation.JsonAnySetter @@ -15,32 +12,29 @@ import com.fasterxml.jackson.annotation.JsonCreator import com.fasterxml.jackson.annotation.JsonProperty import java.util.Collections import java.util.Objects -import kotlin.jvm.optionals.getOrNull class SessionEndResponse @JsonCreator(mode = JsonCreator.Mode.DISABLED) private constructor( - private val success: JsonField, + private val success: JsonValue, private val additionalProperties: MutableMap, ) { @JsonCreator private constructor( - @JsonProperty("success") @ExcludeMissing success: JsonField = JsonMissing.of() + @JsonProperty("success") @ExcludeMissing success: JsonValue = JsonMissing.of() ) : this(success, mutableMapOf()) /** - * @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") - - /** - * Returns the raw JSON value of [success]. + * Expected to always return the following: + * ```java + * JsonValue.from(true) + * ``` * - * Unlike [success], this method doesn't throw if the JSON field has an unexpected type. + * However, this method can be useful for debugging and logging (e.g. if the server responded + * with an unexpected value). */ - @JsonProperty("success") @ExcludeMissing fun _success(): JsonField = success + @JsonProperty("success") @ExcludeMissing fun _success(): JsonValue = success @JsonAnySetter private fun putAdditionalProperty(key: String, value: JsonValue) { @@ -56,21 +50,14 @@ private constructor( companion object { - /** - * Returns a mutable builder for constructing an instance of [SessionEndResponse]. - * - * The following fields are required: - * ```java - * .success() - * ``` - */ + /** Returns a mutable builder for constructing an instance of [SessionEndResponse]. */ @JvmStatic fun builder() = Builder() } /** A builder for [SessionEndResponse]. */ class Builder internal constructor() { - private var success: JsonField? = null + private var success: JsonValue = JsonValue.from(true) private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic @@ -79,15 +66,19 @@ private constructor( additionalProperties = sessionEndResponse.additionalProperties.toMutableMap() } - fun success(success: Success) = success(JsonField.of(success)) - /** - * Sets [Builder.success] to an arbitrary JSON value. + * Sets the field to an arbitrary JSON value. * - * You should usually call [Builder.success] with a well-typed [Success] value instead. This - * method is primarily for setting the field to an undocumented or not yet supported value. + * It is usually unnecessary to call this method because the field defaults to the + * following: + * ```java + * JsonValue.from(true) + * ``` + * + * 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: JsonValue) = apply { this.success = success } fun additionalProperties(additionalProperties: Map) = apply { this.additionalProperties.clear() @@ -112,19 +103,9 @@ private constructor( * Returns an immutable instance of [SessionEndResponse]. * * Further updates to this [Builder] will not mutate the returned instance. - * - * The following fields are required: - * ```java - * .success() - * ``` - * - * @throws IllegalStateException if any required field is unset. */ fun build(): SessionEndResponse = - SessionEndResponse( - checkRequired("success", success), - additionalProperties.toMutableMap(), - ) + SessionEndResponse(success, additionalProperties.toMutableMap()) } private var validated: Boolean = false @@ -134,7 +115,11 @@ private constructor( return@apply } - success().validate() + _success().let { + if (it != JsonValue.from(true)) { + throw StagehandInvalidDataException("'success' is invalid, received $it") + } + } validated = true } @@ -151,125 +136,8 @@ private constructor( * * Used for best match union deserialization. */ - @JvmSynthetic internal fun validity(): Int = (success.asKnown().getOrNull()?.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 { - - @JvmField val TRUE = of(true) - - @JvmStatic 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().orElseThrow { - 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. - */ - @JvmSynthetic 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() - } + @JvmSynthetic + internal fun validity(): Int = success.let { if (it == JsonValue.from(true)) 1 else 0 } override fun equals(other: Any?): Boolean { if (this === other) { diff --git a/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionExecuteResponse.kt b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionExecuteResponse.kt index 2478f77..8718994 100644 --- a/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionExecuteResponse.kt +++ b/stagehand-java-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 @@ -24,14 +23,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()) /** @@ -41,10 +40,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]. @@ -58,7 +59,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) { @@ -90,7 +91,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() @JvmSynthetic @@ -110,15 +111,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() @@ -168,7 +170,7 @@ private constructor( } data().validate() - success().validate() + success() validated = true } @@ -187,8 +189,7 @@ private constructor( */ @JvmSynthetic internal fun validity(): Int = - (data.asKnown().getOrNull()?.validity() ?: 0) + - (success.asKnown().getOrNull()?.validity() ?: 0) + (data.asKnown().getOrNull()?.validity() ?: 0) + (if (success.asKnown().isPresent) 1 else 0) class Data @JsonCreator(mode = JsonCreator.Mode.DISABLED) @@ -1637,124 +1638,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 { - - @JvmField val TRUE = of(true) - - @JvmStatic 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().orElseThrow { - 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. - */ - @JvmSynthetic 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-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionExtractResponse.kt b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionExtractResponse.kt index f48f24f..e281560 100644 --- a/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionExtractResponse.kt +++ b/stagehand-java-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 @@ -22,14 +21,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()) /** @@ -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() @JvmSynthetic @@ -108,15 +109,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() @@ -166,7 +168,7 @@ private constructor( } data().validate() - success().validate() + success() validated = true } @@ -185,8 +187,7 @@ private constructor( */ @JvmSynthetic internal fun validity(): Int = - (data.asKnown().getOrNull()?.validity() ?: 0) + - (success.asKnown().getOrNull()?.validity() ?: 0) + (data.asKnown().getOrNull()?.validity() ?: 0) + (if (success.asKnown().isPresent) 1 else 0) class Data @JsonCreator(mode = JsonCreator.Mode.DISABLED) @@ -355,124 +356,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 { - - @JvmField val TRUE = of(true) - - @JvmStatic 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().orElseThrow { - 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. - */ - @JvmSynthetic 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-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionNavigateResponse.kt b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionNavigateResponse.kt index 56a53a4..2518477 100644 --- a/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionNavigateResponse.kt +++ b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionNavigateResponse.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 SessionNavigateResponse @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() @JvmSynthetic @@ -108,15 +109,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() @@ -166,7 +168,7 @@ private constructor( } data().validate() - success().validate() + success() validated = true } @@ -185,8 +187,7 @@ private constructor( */ @JvmSynthetic internal fun validity(): Int = - (data.asKnown().getOrNull()?.validity() ?: 0) + - (success.asKnown().getOrNull()?.validity() ?: 0) + (data.asKnown().getOrNull()?.validity() ?: 0) + (if (success.asKnown().isPresent) 1 else 0) class Data @JsonCreator(mode = JsonCreator.Mode.DISABLED) @@ -355,124 +356,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 { - - @JvmField val TRUE = of(true) - - @JvmStatic 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().orElseThrow { - 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. - */ - @JvmSynthetic 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-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionObserveResponse.kt b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionObserveResponse.kt index a06fd48..cb2404e 100644 --- a/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionObserveResponse.kt +++ b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionObserveResponse.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 @@ -24,14 +23,14 @@ class SessionObserveResponse @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()) /** @@ -41,10 +40,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]. @@ -58,7 +59,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) { @@ -90,7 +91,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() @JvmSynthetic @@ -110,15 +111,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() @@ -168,7 +170,7 @@ private constructor( } data().validate() - success().validate() + success() validated = true } @@ -187,8 +189,7 @@ private constructor( */ @JvmSynthetic internal fun validity(): Int = - (data.asKnown().getOrNull()?.validity() ?: 0) + - (success.asKnown().getOrNull()?.validity() ?: 0) + (data.asKnown().getOrNull()?.validity() ?: 0) + (if (success.asKnown().isPresent) 1 else 0) class Data @JsonCreator(mode = JsonCreator.Mode.DISABLED) @@ -399,124 +400,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 { - - @JvmField val TRUE = of(true) - - @JvmStatic 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().orElseThrow { - 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. - */ - @JvmSynthetic 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-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionStartParams.kt b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionStartParams.kt index 20ba71d..59c94ad 100644 --- a/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionStartParams.kt +++ b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionStartParams.kt @@ -142,7 +142,7 @@ private constructor( * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). */ - fun verbose(): Optional = body.verbose() + fun verbose(): Optional = body.verbose() /** * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if the @@ -229,7 +229,7 @@ private constructor( * * Unlike [verbose], this method doesn't throw if the JSON field has an unexpected type. */ - fun _verbose(): JsonField = body._verbose() + fun _verbose(): JsonField = body._verbose() /** * Returns the raw JSON value of [waitForCaptchaSolves]. @@ -459,15 +459,15 @@ private constructor( } /** Logging verbosity level (0=quiet, 1=normal, 2=debug) */ - fun verbose(verbose: Verbose) = apply { body.verbose(verbose) } + fun verbose(verbose: Long) = apply { body.verbose(verbose) } /** * Sets [Builder.verbose] to an arbitrary JSON value. * - * You should usually call [Builder.verbose] with a well-typed [Verbose] value instead. This + * You should usually call [Builder.verbose] with a well-typed [Long] value instead. This * method is primarily for setting the field to an undocumented or not yet supported value. */ - fun verbose(verbose: JsonField) = apply { body.verbose(verbose) } + fun verbose(verbose: JsonField) = apply { body.verbose(verbose) } fun waitForCaptchaSolves(waitForCaptchaSolves: Boolean) = apply { body.waitForCaptchaSolves(waitForCaptchaSolves) @@ -653,7 +653,7 @@ private constructor( private val experimental: JsonField, private val selfHeal: JsonField, private val systemPrompt: JsonField, - private val verbose: JsonField, + private val verbose: JsonField, private val waitForCaptchaSolves: JsonField, private val additionalProperties: MutableMap, ) { @@ -689,7 +689,7 @@ private constructor( @JsonProperty("systemPrompt") @ExcludeMissing systemPrompt: JsonField = JsonMissing.of(), - @JsonProperty("verbose") @ExcludeMissing verbose: JsonField = JsonMissing.of(), + @JsonProperty("verbose") @ExcludeMissing verbose: JsonField = JsonMissing.of(), @JsonProperty("waitForCaptchaSolves") @ExcludeMissing waitForCaptchaSolves: JsonField = JsonMissing.of(), @@ -790,7 +790,7 @@ private constructor( * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if * the server responded with an unexpected value). */ - fun verbose(): Optional = verbose.getOptional("verbose") + fun verbose(): Optional = verbose.getOptional("verbose") /** * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if @@ -893,7 +893,7 @@ private constructor( * * Unlike [verbose], this method doesn't throw if the JSON field has an unexpected type. */ - @JsonProperty("verbose") @ExcludeMissing fun _verbose(): JsonField = verbose + @JsonProperty("verbose") @ExcludeMissing fun _verbose(): JsonField = verbose /** * Returns the raw JSON value of [waitForCaptchaSolves]. @@ -944,7 +944,7 @@ private constructor( private var experimental: JsonField = JsonMissing.of() private var selfHeal: JsonField = JsonMissing.of() private var systemPrompt: JsonField = JsonMissing.of() - private var verbose: JsonField = JsonMissing.of() + private var verbose: JsonField = JsonMissing.of() private var waitForCaptchaSolves: JsonField = JsonMissing.of() private var additionalProperties: MutableMap = mutableMapOf() @@ -1098,16 +1098,16 @@ private constructor( } /** Logging verbosity level (0=quiet, 1=normal, 2=debug) */ - fun verbose(verbose: Verbose) = verbose(JsonField.of(verbose)) + fun verbose(verbose: Long) = verbose(JsonField.of(verbose)) /** * Sets [Builder.verbose] to an arbitrary JSON value. * - * You should usually call [Builder.verbose] with a well-typed [Verbose] value instead. + * You should usually call [Builder.verbose] with a well-typed [Long] value instead. * This method is primarily for setting the field to an undocumented or not yet * supported value. */ - fun verbose(verbose: JsonField) = apply { this.verbose = verbose } + fun verbose(verbose: JsonField) = apply { this.verbose = verbose } fun waitForCaptchaSolves(waitForCaptchaSolves: Boolean) = waitForCaptchaSolves(JsonField.of(waitForCaptchaSolves)) @@ -1189,7 +1189,7 @@ private constructor( experimental() selfHeal() systemPrompt() - verbose().ifPresent { it.validate() } + verbose() waitForCaptchaSolves() validated = true } @@ -1220,7 +1220,7 @@ private constructor( (if (experimental.asKnown().isPresent) 1 else 0) + (if (selfHeal.asKnown().isPresent) 1 else 0) + (if (systemPrompt.asKnown().isPresent) 1 else 0) + - (verbose.asKnown().getOrNull()?.validity() ?: 0) + + (if (verbose.asKnown().isPresent) 1 else 0) + (if (waitForCaptchaSolves.asKnown().isPresent) 1 else 0) override fun equals(other: Any?): Boolean { @@ -6084,7 +6084,7 @@ private constructor( class BrowserbaseProxyConfig @JsonCreator(mode = JsonCreator.Mode.DISABLED) private constructor( - private val type: JsonField, + private val type: JsonValue, private val domainPattern: JsonField, private val geolocation: JsonField, private val additionalProperties: MutableMap, @@ -6092,9 +6092,7 @@ private constructor( @JsonCreator private constructor( - @JsonProperty("type") - @ExcludeMissing - type: JsonField = JsonMissing.of(), + @JsonProperty("type") @ExcludeMissing type: JsonValue = JsonMissing.of(), @JsonProperty("domainPattern") @ExcludeMissing domainPattern: JsonField = JsonMissing.of(), @@ -6104,11 +6102,15 @@ private constructor( ) : this(type, domainPattern, geolocation, mutableMapOf()) /** - * @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). + * Expected to always return the following: + * ```java + * JsonValue.from("browserbase") + * ``` + * + * However, this method can be useful for debugging and logging (e.g. if the + * server responded with an unexpected value). */ - fun type(): Type = type.getRequired("type") + @JsonProperty("type") @ExcludeMissing fun _type(): JsonValue = type /** * @throws StagehandInvalidDataException if the JSON field has an unexpected @@ -6124,14 +6126,6 @@ private constructor( fun geolocation(): Optional = geolocation.getOptional("geolocation") - /** - * Returns the raw JSON value of [type]. - * - * Unlike [type], this method doesn't throw if the JSON field has an unexpected - * type. - */ - @JsonProperty("type") @ExcludeMissing fun _type(): JsonField = type - /** * Returns the raw JSON value of [domainPattern]. * @@ -6169,11 +6163,6 @@ private constructor( /** * Returns a mutable builder for constructing an instance of * [BrowserbaseProxyConfig]. - * - * The following fields are required: - * ```java - * .type() - * ``` */ @JvmStatic fun builder() = Builder() } @@ -6181,7 +6170,7 @@ private constructor( /** A builder for [BrowserbaseProxyConfig]. */ class Builder internal constructor() { - private var type: JsonField? = null + private var type: JsonValue = JsonValue.from("browserbase") private var domainPattern: JsonField = JsonMissing.of() private var geolocation: JsonField = JsonMissing.of() private var additionalProperties: MutableMap = @@ -6196,16 +6185,19 @@ private constructor( browserbaseProxyConfig.additionalProperties.toMutableMap() } - fun type(type: Type) = type(JsonField.of(type)) - /** - * Sets [Builder.type] to an arbitrary JSON value. + * Sets the field to an arbitrary JSON value. * - * You should usually call [Builder.type] with a well-typed [Type] value - * instead. This method is primarily for setting the field to an - * undocumented or not yet supported value. + * It is usually unnecessary to call this method because the field defaults + * to the following: + * ```java + * JsonValue.from("browserbase") + * ``` + * + * This method is primarily for setting the field to an undocumented or not + * yet supported value. */ - fun type(type: JsonField) = apply { this.type = type } + fun type(type: JsonValue) = apply { this.type = type } fun domainPattern(domainPattern: String) = domainPattern(JsonField.of(domainPattern)) @@ -6261,17 +6253,10 @@ private constructor( * Returns an immutable instance of [BrowserbaseProxyConfig]. * * Further updates to this [Builder] will not mutate the returned instance. - * - * The following fields are required: - * ```java - * .type() - * ``` - * - * @throws IllegalStateException if any required field is unset. */ fun build(): BrowserbaseProxyConfig = BrowserbaseProxyConfig( - checkRequired("type", type), + type, domainPattern, geolocation, additionalProperties.toMutableMap(), @@ -6285,7 +6270,13 @@ private constructor( return@apply } - type().validate() + _type().let { + if (it != JsonValue.from("browserbase")) { + throw StagehandInvalidDataException( + "'type' is invalid, received $it" + ) + } + } domainPattern() geolocation().ifPresent { it.validate() } validated = true @@ -6307,139 +6298,10 @@ private constructor( */ @JvmSynthetic internal fun validity(): Int = - (type.asKnown().getOrNull()?.validity() ?: 0) + + type.let { if (it == JsonValue.from("browserbase")) 1 else 0 } + (if (domainPattern.asKnown().isPresent) 1 else 0) + (geolocation.asKnown().getOrNull()?.validity() ?: 0) - class Type - @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 { - - @JvmField val BROWSERBASE = of("browserbase") - - @JvmStatic fun of(value: String) = Type(JsonField.of(value)) - } - - /** An enum containing [Type]'s known values. */ - enum class Known { - BROWSERBASE - } - - /** - * An enum containing [Type]'s known values, as well as an [_UNKNOWN] - * member. - * - * An instance of [Type] 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 { - BROWSERBASE, - /** - * An enum member indicating that [Type] 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) { - BROWSERBASE -> Value.BROWSERBASE - 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) { - BROWSERBASE -> Known.BROWSERBASE - else -> throw StagehandInvalidDataException("Unknown Type: $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().orElseThrow { - StagehandInvalidDataException("Value is not a String") - } - - private var validated: Boolean = false - - fun validate(): Type = 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. - */ - @JvmSynthetic - 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 Type && value == other.value - } - - override fun hashCode() = value.hashCode() - - override fun toString() = value.toString() - } - class Geolocation @JsonCreator(mode = JsonCreator.Mode.DISABLED) private constructor( @@ -6713,7 +6575,7 @@ private constructor( @JsonCreator(mode = JsonCreator.Mode.DISABLED) private constructor( private val server: JsonField, - private val type: JsonField, + private val type: JsonValue, private val domainPattern: JsonField, private val password: JsonField, private val username: JsonField, @@ -6725,9 +6587,7 @@ private constructor( @JsonProperty("server") @ExcludeMissing server: JsonField = JsonMissing.of(), - @JsonProperty("type") - @ExcludeMissing - type: JsonField = JsonMissing.of(), + @JsonProperty("type") @ExcludeMissing type: JsonValue = JsonMissing.of(), @JsonProperty("domainPattern") @ExcludeMissing domainPattern: JsonField = JsonMissing.of(), @@ -6747,11 +6607,15 @@ private constructor( fun server(): String = server.getRequired("server") /** - * @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). + * Expected to always return the following: + * ```java + * JsonValue.from("external") + * ``` + * + * However, this method can be useful for debugging and logging (e.g. if the + * server responded with an unexpected value). */ - fun type(): Type = type.getRequired("type") + @JsonProperty("type") @ExcludeMissing fun _type(): JsonValue = type /** * @throws StagehandInvalidDataException if the JSON field has an unexpected @@ -6782,14 +6646,6 @@ private constructor( @ExcludeMissing fun _server(): JsonField = server - /** - * Returns the raw JSON value of [type]. - * - * Unlike [type], this method doesn't throw if the JSON field has an unexpected - * type. - */ - @JsonProperty("type") @ExcludeMissing fun _type(): JsonField = type - /** * Returns the raw JSON value of [domainPattern]. * @@ -6841,7 +6697,6 @@ private constructor( * The following fields are required: * ```java * .server() - * .type() * ``` */ @JvmStatic fun builder() = Builder() @@ -6851,7 +6706,7 @@ private constructor( class Builder internal constructor() { private var server: JsonField? = null - private var type: JsonField? = null + private var type: JsonValue = JsonValue.from("external") private var domainPattern: JsonField = JsonMissing.of() private var password: JsonField = JsonMissing.of() private var username: JsonField = JsonMissing.of() @@ -6880,16 +6735,19 @@ private constructor( */ fun server(server: JsonField) = apply { this.server = server } - fun type(type: Type) = type(JsonField.of(type)) - /** - * Sets [Builder.type] to an arbitrary JSON value. + * Sets the field to an arbitrary JSON value. * - * You should usually call [Builder.type] with a well-typed [Type] value - * instead. This method is primarily for setting the field to an - * undocumented or not yet supported value. + * It is usually unnecessary to call this method because the field defaults + * to the following: + * ```java + * JsonValue.from("external") + * ``` + * + * This method is primarily for setting the field to an undocumented or not + * yet supported value. */ - fun type(type: JsonField) = apply { this.type = type } + fun type(type: JsonValue) = apply { this.type = type } fun domainPattern(domainPattern: String) = domainPattern(JsonField.of(domainPattern)) @@ -6961,7 +6819,6 @@ private constructor( * The following fields are required: * ```java * .server() - * .type() * ``` * * @throws IllegalStateException if any required field is unset. @@ -6969,7 +6826,7 @@ private constructor( fun build(): ExternalProxyConfig = ExternalProxyConfig( checkRequired("server", server), - checkRequired("type", type), + type, domainPattern, password, username, @@ -6985,7 +6842,13 @@ private constructor( } server() - type().validate() + _type().let { + if (it != JsonValue.from("external")) { + throw StagehandInvalidDataException( + "'type' is invalid, received $it" + ) + } + } domainPattern() password() username() @@ -7009,140 +6872,11 @@ private constructor( @JvmSynthetic internal fun validity(): Int = (if (server.asKnown().isPresent) 1 else 0) + - (type.asKnown().getOrNull()?.validity() ?: 0) + + type.let { if (it == JsonValue.from("external")) 1 else 0 } + (if (domainPattern.asKnown().isPresent) 1 else 0) + (if (password.asKnown().isPresent) 1 else 0) + (if (username.asKnown().isPresent) 1 else 0) - class Type - @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 { - - @JvmField val EXTERNAL = of("external") - - @JvmStatic fun of(value: String) = Type(JsonField.of(value)) - } - - /** An enum containing [Type]'s known values. */ - enum class Known { - EXTERNAL - } - - /** - * An enum containing [Type]'s known values, as well as an [_UNKNOWN] - * member. - * - * An instance of [Type] 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 { - EXTERNAL, - /** - * An enum member indicating that [Type] 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) { - EXTERNAL -> Value.EXTERNAL - 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) { - EXTERNAL -> Known.EXTERNAL - else -> throw StagehandInvalidDataException("Unknown Type: $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().orElseThrow { - StagehandInvalidDataException("Value is not a String") - } - - private var validated: Boolean = false - - fun validate(): Type = 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. - */ - @JvmSynthetic - 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 Type && value == other.value - } - - override fun hashCode() = value.hashCode() - - override fun toString() = value.toString() - } - override fun equals(other: Any?): Boolean { if (this === other) { return true @@ -7456,136 +7190,6 @@ private constructor( "BrowserbaseSessionCreateParams{browserSettings=$browserSettings, extensionId=$extensionId, keepAlive=$keepAlive, projectId=$projectId, proxies=$proxies, region=$region, timeout=$timeout, userMetadata=$userMetadata, additionalProperties=$additionalProperties}" } - /** Logging verbosity level (0=quiet, 1=normal, 2=debug) */ - class Verbose @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 { - - @JvmField val _0 = of(0.0) - - @JvmField val _1 = of(1.0) - - @JvmField val _2 = of(2.0) - - @JvmStatic fun of(value: Double) = Verbose(JsonField.of(value)) - } - - /** An enum containing [Verbose]'s known values. */ - enum class Known { - _0, - _1, - _2, - } - - /** - * An enum containing [Verbose]'s known values, as well as an [_UNKNOWN] member. - * - * An instance of [Verbose] 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 { - _0, - _1, - _2, - /** An enum member indicating that [Verbose] 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) { - _0 -> Value._0 - _1 -> Value._1 - _2 -> Value._2 - 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) { - _0 -> Known._0 - _1 -> Known._1 - _2 -> Known._2 - else -> throw StagehandInvalidDataException("Unknown Verbose: $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 asDouble(): Double = - _value().asNumber().getOrNull()?.toDouble() - ?: throw StagehandInvalidDataException("Value is not a Double") - - private var validated: Boolean = false - - fun validate(): Verbose = 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. - */ - @JvmSynthetic 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 Verbose && value == other.value - } - - override fun hashCode() = value.hashCode() - - override fun toString() = value.toString() - } - /** Client SDK language */ class XLanguage @JsonCreator private constructor(private val value: JsonField) : Enum { diff --git a/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionStartResponse.kt b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionStartResponse.kt index 420925f..a172070 100644 --- a/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionStartResponse.kt +++ b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionStartResponse.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 @@ -21,14 +20,14 @@ class SessionStartResponse @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()) /** @@ -38,10 +37,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]. @@ -55,7 +56,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) { @@ -87,7 +88,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() @JvmSynthetic @@ -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 } @@ -184,8 +186,7 @@ private constructor( */ @JvmSynthetic internal fun validity(): Int = - (data.asKnown().getOrNull()?.validity() ?: 0) + - (success.asKnown().getOrNull()?.validity() ?: 0) + (data.asKnown().getOrNull()?.validity() ?: 0) + (if (success.asKnown().isPresent) 1 else 0) class Data @JsonCreator(mode = JsonCreator.Mode.DISABLED) @@ -388,124 +389,6 @@ private constructor( "Data{available=$available, sessionId=$sessionId, 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 { - - @JvmField val TRUE = of(true) - - @JvmStatic 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().orElseThrow { - 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. - */ - @JvmSynthetic 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-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionActResponseTest.kt b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionActResponseTest.kt index 000d7fd..f5e0363 100644 --- a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionActResponseTest.kt +++ b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionActResponseTest.kt @@ -33,7 +33,7 @@ internal class SessionActResponseTest { .actionId("actionId") .build() ) - .success(SessionActResponse.Success.TRUE) + .success(true) .build() assertThat(sessionActResponse.data()) @@ -57,7 +57,7 @@ internal class SessionActResponseTest { .actionId("actionId") .build() ) - assertThat(sessionActResponse.success()).isEqualTo(SessionActResponse.Success.TRUE) + assertThat(sessionActResponse.success()).isEqualTo(true) } @Test @@ -85,7 +85,7 @@ internal class SessionActResponseTest { .actionId("actionId") .build() ) - .success(SessionActResponse.Success.TRUE) + .success(true) .build() val roundtrippedSessionActResponse = diff --git a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionEndResponseTest.kt b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionEndResponseTest.kt index 27a2a36..30e45db 100644 --- a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionEndResponseTest.kt +++ b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionEndResponseTest.kt @@ -11,17 +11,13 @@ internal class SessionEndResponseTest { @Test fun create() { - val sessionEndResponse = - SessionEndResponse.builder().success(SessionEndResponse.Success.TRUE).build() - - assertThat(sessionEndResponse.success()).isEqualTo(SessionEndResponse.Success.TRUE) + val sessionEndResponse = SessionEndResponse.builder().build() } @Test fun roundtrip() { val jsonMapper = jsonMapper() - val sessionEndResponse = - SessionEndResponse.builder().success(SessionEndResponse.Success.TRUE).build() + val sessionEndResponse = SessionEndResponse.builder().build() val roundtrippedSessionEndResponse = jsonMapper.readValue( diff --git a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionExecuteResponseTest.kt b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionExecuteResponseTest.kt index d2fb4d9..85a2099 100644 --- a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionExecuteResponseTest.kt +++ b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionExecuteResponseTest.kt @@ -51,7 +51,7 @@ internal class SessionExecuteResponseTest { ) .build() ) - .success(SessionExecuteResponse.Success.TRUE) + .success(true) .build() assertThat(sessionExecuteResponse.data()) @@ -92,7 +92,7 @@ internal class SessionExecuteResponseTest { ) .build() ) - assertThat(sessionExecuteResponse.success()).isEqualTo(SessionExecuteResponse.Success.TRUE) + assertThat(sessionExecuteResponse.success()).isEqualTo(true) } @Test @@ -137,7 +137,7 @@ internal class SessionExecuteResponseTest { ) .build() ) - .success(SessionExecuteResponse.Success.TRUE) + .success(true) .build() val roundtrippedSessionExecuteResponse = diff --git a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionExtractResponseTest.kt b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionExtractResponseTest.kt index 6cf7056..3f055cd 100644 --- a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionExtractResponseTest.kt +++ b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionExtractResponseTest.kt @@ -20,7 +20,7 @@ internal class SessionExtractResponseTest { .actionId("actionId") .build() ) - .success(SessionExtractResponse.Success.TRUE) + .success(true) .build() assertThat(sessionExtractResponse.data()) @@ -30,7 +30,7 @@ internal class SessionExtractResponseTest { .actionId("actionId") .build() ) - assertThat(sessionExtractResponse.success()).isEqualTo(SessionExtractResponse.Success.TRUE) + assertThat(sessionExtractResponse.success()).isEqualTo(true) } @Test @@ -44,7 +44,7 @@ internal class SessionExtractResponseTest { .actionId("actionId") .build() ) - .success(SessionExtractResponse.Success.TRUE) + .success(true) .build() val roundtrippedSessionExtractResponse = diff --git a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionNavigateResponseTest.kt b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionNavigateResponseTest.kt index e02a0e3..bca29d9 100644 --- a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionNavigateResponseTest.kt +++ b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionNavigateResponseTest.kt @@ -20,7 +20,7 @@ internal class SessionNavigateResponseTest { .actionId("actionId") .build() ) - .success(SessionNavigateResponse.Success.TRUE) + .success(true) .build() assertThat(sessionNavigateResponse.data()) @@ -30,8 +30,7 @@ internal class SessionNavigateResponseTest { .actionId("actionId") .build() ) - assertThat(sessionNavigateResponse.success()) - .isEqualTo(SessionNavigateResponse.Success.TRUE) + assertThat(sessionNavigateResponse.success()).isEqualTo(true) } @Test @@ -45,7 +44,7 @@ internal class SessionNavigateResponseTest { .actionId("actionId") .build() ) - .success(SessionNavigateResponse.Success.TRUE) + .success(true) .build() val roundtrippedSessionNavigateResponse = diff --git a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionObserveResponseTest.kt b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionObserveResponseTest.kt index e3d72c3..2cc31b8 100644 --- a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionObserveResponseTest.kt +++ b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionObserveResponseTest.kt @@ -26,7 +26,7 @@ internal class SessionObserveResponseTest { .actionId("actionId") .build() ) - .success(SessionObserveResponse.Success.TRUE) + .success(true) .build() assertThat(sessionObserveResponse.data()) @@ -43,7 +43,7 @@ internal class SessionObserveResponseTest { .actionId("actionId") .build() ) - assertThat(sessionObserveResponse.success()).isEqualTo(SessionObserveResponse.Success.TRUE) + assertThat(sessionObserveResponse.success()).isEqualTo(true) } @Test @@ -64,7 +64,7 @@ internal class SessionObserveResponseTest { .actionId("actionId") .build() ) - .success(SessionObserveResponse.Success.TRUE) + .success(true) .build() val roundtrippedSessionObserveResponse = diff --git a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionStartParamsTest.kt b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionStartParamsTest.kt index 13ae538..0dc5811 100644 --- a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionStartParamsTest.kt +++ b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionStartParamsTest.kt @@ -153,7 +153,7 @@ internal class SessionStartParamsTest { .experimental(true) .selfHeal(true) .systemPrompt("systemPrompt") - .verbose(SessionStartParams.Verbose._1) + .verbose(1L) .waitForCaptchaSolves(true) .build() } @@ -306,7 +306,7 @@ internal class SessionStartParamsTest { .experimental(true) .selfHeal(true) .systemPrompt("systemPrompt") - .verbose(SessionStartParams.Verbose._1) + .verbose(1L) .waitForCaptchaSolves(true) .build() @@ -480,7 +480,7 @@ internal class SessionStartParamsTest { .experimental(true) .selfHeal(true) .systemPrompt("systemPrompt") - .verbose(SessionStartParams.Verbose._1) + .verbose(1L) .waitForCaptchaSolves(true) .build() @@ -624,7 +624,7 @@ internal class SessionStartParamsTest { assertThat(body.experimental()).contains(true) assertThat(body.selfHeal()).contains(true) assertThat(body.systemPrompt()).contains("systemPrompt") - assertThat(body.verbose()).contains(SessionStartParams.Verbose._1) + assertThat(body.verbose()).contains(1L) assertThat(body.waitForCaptchaSolves()).contains(true) } diff --git a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionStartResponseTest.kt b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionStartResponseTest.kt index 717d6d6..3af1696 100644 --- a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionStartResponseTest.kt +++ b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionStartResponseTest.kt @@ -19,7 +19,7 @@ internal class SessionStartResponseTest { .sessionId("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") .build() ) - .success(SessionStartResponse.Success.TRUE) + .success(true) .build() assertThat(sessionStartResponse.data()) @@ -29,7 +29,7 @@ internal class SessionStartResponseTest { .sessionId("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") .build() ) - assertThat(sessionStartResponse.success()).isEqualTo(SessionStartResponse.Success.TRUE) + assertThat(sessionStartResponse.success()).isEqualTo(true) } @Test @@ -43,7 +43,7 @@ internal class SessionStartResponseTest { .sessionId("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") .build() ) - .success(SessionStartResponse.Success.TRUE) + .success(true) .build() val roundtrippedSessionStartResponse = diff --git a/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/ErrorHandlingTest.kt b/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/ErrorHandlingTest.kt index 87af3f1..967794c 100644 --- a/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/ErrorHandlingTest.kt +++ b/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/ErrorHandlingTest.kt @@ -230,7 +230,7 @@ internal class ErrorHandlingTest { .experimental(true) .selfHeal(true) .systemPrompt("systemPrompt") - .verbose(SessionStartParams.Verbose._1) + .verbose(1L) .waitForCaptchaSolves(true) .build() ) @@ -410,7 +410,7 @@ internal class ErrorHandlingTest { .experimental(true) .selfHeal(true) .systemPrompt("systemPrompt") - .verbose(SessionStartParams.Verbose._1) + .verbose(1L) .waitForCaptchaSolves(true) .build() ) @@ -590,7 +590,7 @@ internal class ErrorHandlingTest { .experimental(true) .selfHeal(true) .systemPrompt("systemPrompt") - .verbose(SessionStartParams.Verbose._1) + .verbose(1L) .waitForCaptchaSolves(true) .build() ) @@ -770,7 +770,7 @@ internal class ErrorHandlingTest { .experimental(true) .selfHeal(true) .systemPrompt("systemPrompt") - .verbose(SessionStartParams.Verbose._1) + .verbose(1L) .waitForCaptchaSolves(true) .build() ) @@ -950,7 +950,7 @@ internal class ErrorHandlingTest { .experimental(true) .selfHeal(true) .systemPrompt("systemPrompt") - .verbose(SessionStartParams.Verbose._1) + .verbose(1L) .waitForCaptchaSolves(true) .build() ) @@ -1130,7 +1130,7 @@ internal class ErrorHandlingTest { .experimental(true) .selfHeal(true) .systemPrompt("systemPrompt") - .verbose(SessionStartParams.Verbose._1) + .verbose(1L) .waitForCaptchaSolves(true) .build() ) @@ -1310,7 +1310,7 @@ internal class ErrorHandlingTest { .experimental(true) .selfHeal(true) .systemPrompt("systemPrompt") - .verbose(SessionStartParams.Verbose._1) + .verbose(1L) .waitForCaptchaSolves(true) .build() ) @@ -1490,7 +1490,7 @@ internal class ErrorHandlingTest { .experimental(true) .selfHeal(true) .systemPrompt("systemPrompt") - .verbose(SessionStartParams.Verbose._1) + .verbose(1L) .waitForCaptchaSolves(true) .build() ) @@ -1670,7 +1670,7 @@ internal class ErrorHandlingTest { .experimental(true) .selfHeal(true) .systemPrompt("systemPrompt") - .verbose(SessionStartParams.Verbose._1) + .verbose(1L) .waitForCaptchaSolves(true) .build() ) @@ -1850,7 +1850,7 @@ internal class ErrorHandlingTest { .experimental(true) .selfHeal(true) .systemPrompt("systemPrompt") - .verbose(SessionStartParams.Verbose._1) + .verbose(1L) .waitForCaptchaSolves(true) .build() ) @@ -2030,7 +2030,7 @@ internal class ErrorHandlingTest { .experimental(true) .selfHeal(true) .systemPrompt("systemPrompt") - .verbose(SessionStartParams.Verbose._1) + .verbose(1L) .waitForCaptchaSolves(true) .build() ) @@ -2210,7 +2210,7 @@ internal class ErrorHandlingTest { .experimental(true) .selfHeal(true) .systemPrompt("systemPrompt") - .verbose(SessionStartParams.Verbose._1) + .verbose(1L) .waitForCaptchaSolves(true) .build() ) @@ -2390,7 +2390,7 @@ internal class ErrorHandlingTest { .experimental(true) .selfHeal(true) .systemPrompt("systemPrompt") - .verbose(SessionStartParams.Verbose._1) + .verbose(1L) .waitForCaptchaSolves(true) .build() ) @@ -2570,7 +2570,7 @@ internal class ErrorHandlingTest { .experimental(true) .selfHeal(true) .systemPrompt("systemPrompt") - .verbose(SessionStartParams.Verbose._1) + .verbose(1L) .waitForCaptchaSolves(true) .build() ) @@ -2750,7 +2750,7 @@ internal class ErrorHandlingTest { .experimental(true) .selfHeal(true) .systemPrompt("systemPrompt") - .verbose(SessionStartParams.Verbose._1) + .verbose(1L) .waitForCaptchaSolves(true) .build() ) @@ -2930,7 +2930,7 @@ internal class ErrorHandlingTest { .experimental(true) .selfHeal(true) .systemPrompt("systemPrompt") - .verbose(SessionStartParams.Verbose._1) + .verbose(1L) .waitForCaptchaSolves(true) .build() ) @@ -3108,7 +3108,7 @@ internal class ErrorHandlingTest { .experimental(true) .selfHeal(true) .systemPrompt("systemPrompt") - .verbose(SessionStartParams.Verbose._1) + .verbose(1L) .waitForCaptchaSolves(true) .build() ) diff --git a/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/ServiceParamsTest.kt b/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/ServiceParamsTest.kt index ecf30b0..beb2b92 100644 --- a/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/ServiceParamsTest.kt +++ b/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/ServiceParamsTest.kt @@ -192,7 +192,7 @@ internal class ServiceParamsTest { .experimental(true) .selfHeal(true) .systemPrompt("systemPrompt") - .verbose(SessionStartParams.Verbose._1) + .verbose(1L) .waitForCaptchaSolves(true) .putAdditionalHeader("Secret-Header", "42") .putAdditionalQueryParam("secret_query_param", "42") diff --git a/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/async/SessionServiceAsyncTest.kt b/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/async/SessionServiceAsyncTest.kt index 0011f6f..fd11f6e 100644 --- a/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/async/SessionServiceAsyncTest.kt +++ b/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/async/SessionServiceAsyncTest.kt @@ -406,7 +406,7 @@ internal class SessionServiceAsyncTest { .experimental(true) .selfHeal(true) .systemPrompt("systemPrompt") - .verbose(SessionStartParams.Verbose._1) + .verbose(1L) .waitForCaptchaSolves(true) .build() ) diff --git a/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/blocking/SessionServiceTest.kt b/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/blocking/SessionServiceTest.kt index 3f62ca6..ba02cd0 100644 --- a/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/blocking/SessionServiceTest.kt +++ b/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/blocking/SessionServiceTest.kt @@ -400,7 +400,7 @@ internal class SessionServiceTest { .experimental(true) .selfHeal(true) .systemPrompt("systemPrompt") - .verbose(SessionStartParams.Verbose._1) + .verbose(1L) .waitForCaptchaSolves(true) .build() ) From 28f7978e1f040169dbb20aa68efb8e5ceb9a34d2 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 17 Dec 2025 18:56:01 +0000 Subject: [PATCH 09/18] feat(api): manual updates --- .stats.yml | 4 +- .../api/models/sessions/ModelConfig.kt | 116 +++--- .../api/models/sessions/SessionActParams.kt | 19 +- .../api/models/sessions/SessionEndResponse.kt | 73 ++-- .../models/sessions/SessionExecuteParams.kt | 19 +- .../models/sessions/SessionExtractParams.kt | 19 +- .../models/sessions/SessionObserveParams.kt | 19 +- .../api/models/sessions/SessionStartParams.kt | 352 +++++++++++------- .../api/models/sessions/ModelConfigTest.kt | 44 +-- .../models/sessions/SessionActParamsTest.kt | 8 +- .../models/sessions/SessionEndResponseTest.kt | 6 +- .../sessions/SessionExecuteParamsTest.kt | 8 +- .../sessions/SessionExtractParamsTest.kt | 8 +- .../sessions/SessionObserveParamsTest.kt | 8 +- .../models/sessions/SessionStartParamsTest.kt | 8 +- .../api/services/ErrorHandlingTest.kt | 34 +- .../api/services/ServiceParamsTest.kt | 4 +- .../services/async/SessionServiceAsyncTest.kt | 10 +- .../services/blocking/SessionServiceTest.kt | 10 +- .../api/proguard/ProGuardCompatibilityTest.kt | 2 +- 20 files changed, 473 insertions(+), 298 deletions(-) diff --git a/.stats.yml b/.stats.yml index 08f0cef..38ef77c 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-d571232203ef4e00986a3245224267db6f8aaffdad57780f712e0694dc8d9e37.yml -openapi_spec_hash: d5d635dd7b24a2e1255c6f2a895253ff +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/browserbase%2Fstagehand-817d1d4e845b1946dac8ee10fd34b3f533aa36f74ac598582ffb1b0399a5a932.yml +openapi_spec_hash: 9d856db62b34909fec94743235b3d7be config_hash: 88e87ba7021be93d267ecfc8f5e6b891 diff --git a/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/ModelConfig.kt b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/ModelConfig.kt index 0d210b0..e416a06 100644 --- a/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/ModelConfig.kt +++ b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/ModelConfig.kt @@ -27,33 +27,44 @@ import java.util.Collections import java.util.Objects import java.util.Optional +/** + * 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(): Optional = Optional.ofNullable(string) + /** + * Model name string with provider prefix (e.g., 'openai/gpt-5-nano', + * 'anthropic/claude-4.5-opus') + */ + fun name(): Optional = Optional.ofNullable(name) - fun unionMember1(): Optional = Optional.ofNullable(unionMember1) + fun modelConfigObject(): Optional = Optional.ofNullable(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(): Optional = Optional.ofNullable(_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) } @@ -66,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() } } ) @@ -93,9 +104,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 } @@ -106,25 +118,32 @@ 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 { - @JvmStatic fun ofString(string: String) = ModelConfig(string = string) + /** + * Model name string with provider prefix (e.g., 'openai/gpt-5-nano', + * 'anthropic/claude-4.5-opus') + */ + @JvmStatic fun ofName(name: String) = ModelConfig(name = name) @JvmStatic - fun ofUnionMember1(unionMember1: UnionMember1) = ModelConfig(unionMember1 = unionMember1) + fun ofModelConfigObject(modelConfigObject: ModelConfigObject) = + ModelConfig(modelConfigObject = modelConfigObject) } /** @@ -132,9 +151,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]. @@ -157,11 +180,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() @@ -187,15 +210,15 @@ 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, @@ -214,18 +237,24 @@ private constructor( ) : this(modelName, apiKey, baseUrl, 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(): Optional = apiKey.getOptional("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). */ @@ -267,7 +296,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: * ```java @@ -277,7 +306,7 @@ private constructor( @JvmStatic fun builder() = Builder() } - /** A builder for [UnionMember1]. */ + /** A builder for [ModelConfigObject]. */ class Builder internal constructor() { private var modelName: JsonField? = null @@ -286,13 +315,14 @@ private constructor( private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic - 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 + 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)) /** @@ -304,6 +334,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)) /** @@ -315,6 +346,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)) /** @@ -346,7 +378,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. * @@ -357,8 +389,8 @@ private constructor( * * @throws IllegalStateException if any required field is unset. */ - fun build(): UnionMember1 = - UnionMember1( + fun build(): ModelConfigObject = + ModelConfigObject( checkRequired("modelName", modelName), apiKey, baseUrl, @@ -368,7 +400,7 @@ private constructor( private var validated: Boolean = false - fun validate(): UnionMember1 = apply { + fun validate(): ModelConfigObject = apply { if (validated) { return@apply } @@ -404,7 +436,7 @@ private constructor( return true } - return other is UnionMember1 && + return other is ModelConfigObject && modelName == other.modelName && apiKey == other.apiKey && baseUrl == other.baseUrl && @@ -418,6 +450,6 @@ private constructor( override fun hashCode(): Int = hashCode override fun toString() = - "UnionMember1{modelName=$modelName, apiKey=$apiKey, baseUrl=$baseUrl, additionalProperties=$additionalProperties}" + "ModelConfigObject{modelName=$modelName, apiKey=$apiKey, baseUrl=$baseUrl, additionalProperties=$additionalProperties}" } } diff --git a/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionActParams.kt b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionActParams.kt index 7e98b5d..019f026 100644 --- a/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionActParams.kt +++ b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionActParams.kt @@ -1133,6 +1133,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). */ @@ -1211,6 +1214,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)) /** @@ -1222,12 +1229,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-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionEndResponse.kt b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionEndResponse.kt index 3345222..3a886e7 100644 --- a/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionEndResponse.kt +++ b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionEndResponse.kt @@ -3,8 +3,10 @@ package com.browserbase.api.models.sessions import com.browserbase.api.core.ExcludeMissing +import com.browserbase.api.core.JsonField import com.browserbase.api.core.JsonMissing import com.browserbase.api.core.JsonValue +import com.browserbase.api.core.checkRequired import com.browserbase.api.errors.StagehandInvalidDataException import com.fasterxml.jackson.annotation.JsonAnyGetter import com.fasterxml.jackson.annotation.JsonAnySetter @@ -16,25 +18,29 @@ import java.util.Objects class SessionEndResponse @JsonCreator(mode = JsonCreator.Mode.DISABLED) private constructor( - private val success: JsonValue, + private val success: JsonField, private val additionalProperties: MutableMap, ) { @JsonCreator private constructor( - @JsonProperty("success") @ExcludeMissing success: JsonValue = JsonMissing.of() + @JsonProperty("success") @ExcludeMissing success: JsonField = JsonMissing.of() ) : this(success, mutableMapOf()) /** - * Expected to always return the following: - * ```java - * JsonValue.from(true) - * ``` + * Indicates whether the request was successful * - * However, this method can be useful for debugging and logging (e.g. if the server responded - * with an unexpected value). + * @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). */ - @JsonProperty("success") @ExcludeMissing fun _success(): JsonValue = 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 @JsonAnySetter private fun putAdditionalProperty(key: String, value: JsonValue) { @@ -50,14 +56,21 @@ private constructor( companion object { - /** Returns a mutable builder for constructing an instance of [SessionEndResponse]. */ + /** + * Returns a mutable builder for constructing an instance of [SessionEndResponse]. + * + * The following fields are required: + * ```java + * .success() + * ``` + */ @JvmStatic fun builder() = Builder() } /** A builder for [SessionEndResponse]. */ class Builder internal constructor() { - private var success: JsonValue = JsonValue.from(true) + private var success: JsonField? = null private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic @@ -66,19 +79,16 @@ private constructor( additionalProperties = sessionEndResponse.additionalProperties.toMutableMap() } + /** Indicates whether the request was successful */ + fun success(success: Boolean) = success(JsonField.of(success)) + /** - * Sets the field to an arbitrary JSON value. + * Sets [Builder.success] to an arbitrary JSON value. * - * It is usually unnecessary to call this method because the field defaults to the - * following: - * ```java - * JsonValue.from(true) - * ``` - * - * This method is primarily for setting the field to an undocumented or not yet supported - * value. + * 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: JsonValue) = apply { this.success = success } + fun success(success: JsonField) = apply { this.success = success } fun additionalProperties(additionalProperties: Map) = apply { this.additionalProperties.clear() @@ -103,9 +113,19 @@ private constructor( * Returns an immutable instance of [SessionEndResponse]. * * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .success() + * ``` + * + * @throws IllegalStateException if any required field is unset. */ fun build(): SessionEndResponse = - SessionEndResponse(success, additionalProperties.toMutableMap()) + SessionEndResponse( + checkRequired("success", success), + additionalProperties.toMutableMap(), + ) } private var validated: Boolean = false @@ -115,11 +135,7 @@ private constructor( return@apply } - _success().let { - if (it != JsonValue.from(true)) { - throw StagehandInvalidDataException("'success' is invalid, received $it") - } - } + success() validated = true } @@ -136,8 +152,7 @@ private constructor( * * Used for best match union deserialization. */ - @JvmSynthetic - internal fun validity(): Int = success.let { if (it == JsonValue.from(true)) 1 else 0 } + @JvmSynthetic internal fun validity(): Int = (if (success.asKnown().isPresent) 1 else 0) override fun equals(other: Any?): Boolean { if (this === other) { diff --git a/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionExecuteParams.kt b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionExecuteParams.kt index 4b615cf..73880ff 100644 --- a/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionExecuteParams.kt +++ b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionExecuteParams.kt @@ -657,6 +657,9 @@ private constructor( fun cua(): Optional = cua.getOptional("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). */ @@ -740,6 +743,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)) /** @@ -751,12 +758,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)) /** Custom system prompt for the agent */ fun systemPrompt(systemPrompt: String) = systemPrompt(JsonField.of(systemPrompt)) diff --git a/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionExtractParams.kt b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionExtractParams.kt index b86cdc3..3a5c4bd 100644 --- a/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionExtractParams.kt +++ b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionExtractParams.kt @@ -666,6 +666,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). */ @@ -742,6 +745,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)) /** @@ -753,12 +760,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-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionObserveParams.kt b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionObserveParams.kt index 7e40f70..66c3b91 100644 --- a/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionObserveParams.kt +++ b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionObserveParams.kt @@ -606,6 +606,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). */ @@ -682,6 +685,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)) /** @@ -693,12 +700,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 observation to a specific element */ fun selector(selector: String) = selector(JsonField.of(selector)) diff --git a/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionStartParams.kt b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionStartParams.kt index 59c94ad..57f072f 100644 --- a/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionStartParams.kt +++ b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionStartParams.kt @@ -142,7 +142,7 @@ private constructor( * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). */ - fun verbose(): Optional = body.verbose() + fun verbose(): Optional = body.verbose() /** * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if the @@ -229,7 +229,7 @@ private constructor( * * Unlike [verbose], this method doesn't throw if the JSON field has an unexpected type. */ - fun _verbose(): JsonField = body._verbose() + fun _verbose(): JsonField = body._verbose() /** * Returns the raw JSON value of [waitForCaptchaSolves]. @@ -459,15 +459,15 @@ private constructor( } /** Logging verbosity level (0=quiet, 1=normal, 2=debug) */ - fun verbose(verbose: Long) = apply { body.verbose(verbose) } + fun verbose(verbose: Verbose) = apply { body.verbose(verbose) } /** * Sets [Builder.verbose] to an arbitrary JSON value. * - * You should usually call [Builder.verbose] with a well-typed [Long] value instead. This + * You should usually call [Builder.verbose] with a well-typed [Verbose] value instead. This * method is primarily for setting the field to an undocumented or not yet supported value. */ - fun verbose(verbose: JsonField) = apply { body.verbose(verbose) } + fun verbose(verbose: JsonField) = apply { body.verbose(verbose) } fun waitForCaptchaSolves(waitForCaptchaSolves: Boolean) = apply { body.waitForCaptchaSolves(waitForCaptchaSolves) @@ -653,7 +653,7 @@ private constructor( private val experimental: JsonField, private val selfHeal: JsonField, private val systemPrompt: JsonField, - private val verbose: JsonField, + private val verbose: JsonField, private val waitForCaptchaSolves: JsonField, private val additionalProperties: MutableMap, ) { @@ -689,7 +689,7 @@ private constructor( @JsonProperty("systemPrompt") @ExcludeMissing systemPrompt: JsonField = JsonMissing.of(), - @JsonProperty("verbose") @ExcludeMissing verbose: JsonField = JsonMissing.of(), + @JsonProperty("verbose") @ExcludeMissing verbose: JsonField = JsonMissing.of(), @JsonProperty("waitForCaptchaSolves") @ExcludeMissing waitForCaptchaSolves: JsonField = JsonMissing.of(), @@ -790,7 +790,7 @@ private constructor( * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if * the server responded with an unexpected value). */ - fun verbose(): Optional = verbose.getOptional("verbose") + fun verbose(): Optional = verbose.getOptional("verbose") /** * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if @@ -893,7 +893,7 @@ private constructor( * * Unlike [verbose], this method doesn't throw if the JSON field has an unexpected type. */ - @JsonProperty("verbose") @ExcludeMissing fun _verbose(): JsonField = verbose + @JsonProperty("verbose") @ExcludeMissing fun _verbose(): JsonField = verbose /** * Returns the raw JSON value of [waitForCaptchaSolves]. @@ -944,7 +944,7 @@ private constructor( private var experimental: JsonField = JsonMissing.of() private var selfHeal: JsonField = JsonMissing.of() private var systemPrompt: JsonField = JsonMissing.of() - private var verbose: JsonField = JsonMissing.of() + private var verbose: JsonField = JsonMissing.of() private var waitForCaptchaSolves: JsonField = JsonMissing.of() private var additionalProperties: MutableMap = mutableMapOf() @@ -1098,16 +1098,16 @@ private constructor( } /** Logging verbosity level (0=quiet, 1=normal, 2=debug) */ - fun verbose(verbose: Long) = verbose(JsonField.of(verbose)) + fun verbose(verbose: Verbose) = verbose(JsonField.of(verbose)) /** * Sets [Builder.verbose] to an arbitrary JSON value. * - * You should usually call [Builder.verbose] with a well-typed [Long] value instead. + * You should usually call [Builder.verbose] with a well-typed [Verbose] value instead. * This method is primarily for setting the field to an undocumented or not yet * supported value. */ - fun verbose(verbose: JsonField) = apply { this.verbose = verbose } + fun verbose(verbose: JsonField) = apply { this.verbose = verbose } fun waitForCaptchaSolves(waitForCaptchaSolves: Boolean) = waitForCaptchaSolves(JsonField.of(waitForCaptchaSolves)) @@ -1189,7 +1189,7 @@ private constructor( experimental() selfHeal() systemPrompt() - verbose() + verbose().ifPresent { it.validate() } waitForCaptchaSolves() validated = true } @@ -1220,7 +1220,7 @@ private constructor( (if (experimental.asKnown().isPresent) 1 else 0) + (if (selfHeal.asKnown().isPresent) 1 else 0) + (if (systemPrompt.asKnown().isPresent) 1 else 0) + - (if (verbose.asKnown().isPresent) 1 else 0) + + (verbose.asKnown().getOrNull()?.validity() ?: 0) + (if (waitForCaptchaSolves.asKnown().isPresent) 1 else 0) override fun equals(other: Any?): Boolean { @@ -5862,35 +5862,29 @@ private constructor( @JsonSerialize(using = UnnamedSchemaWithArrayParent0.Serializer::class) class UnnamedSchemaWithArrayParent0 private constructor( - private val browserbaseProxyConfig: BrowserbaseProxyConfig? = null, - private val externalProxyConfig: ExternalProxyConfig? = null, + private val browserbase: Browserbase? = null, + private val external: External? = null, private val _json: JsonValue? = null, ) { - fun browserbaseProxyConfig(): Optional = - Optional.ofNullable(browserbaseProxyConfig) + fun browserbase(): Optional = Optional.ofNullable(browserbase) - fun externalProxyConfig(): Optional = - Optional.ofNullable(externalProxyConfig) + fun external(): Optional = Optional.ofNullable(external) - fun isBrowserbaseProxyConfig(): Boolean = browserbaseProxyConfig != null + fun isBrowserbase(): Boolean = browserbase != null - fun isExternalProxyConfig(): Boolean = externalProxyConfig != null + fun isExternal(): Boolean = external != null - fun asBrowserbaseProxyConfig(): BrowserbaseProxyConfig = - browserbaseProxyConfig.getOrThrow("browserbaseProxyConfig") + fun asBrowserbase(): Browserbase = browserbase.getOrThrow("browserbase") - fun asExternalProxyConfig(): ExternalProxyConfig = - externalProxyConfig.getOrThrow("externalProxyConfig") + fun asExternal(): External = external.getOrThrow("external") fun _json(): Optional = Optional.ofNullable(_json) fun accept(visitor: Visitor): T = when { - browserbaseProxyConfig != null -> - visitor.visitBrowserbaseProxyConfig(browserbaseProxyConfig) - externalProxyConfig != null -> - visitor.visitExternalProxyConfig(externalProxyConfig) + browserbase != null -> visitor.visitBrowserbase(browserbase) + external != null -> visitor.visitExternal(external) else -> visitor.unknown(_json) } @@ -5903,16 +5897,12 @@ private constructor( accept( object : Visitor { - override fun visitBrowserbaseProxyConfig( - browserbaseProxyConfig: BrowserbaseProxyConfig - ) { - browserbaseProxyConfig.validate() + override fun visitBrowserbase(browserbase: Browserbase) { + browserbase.validate() } - override fun visitExternalProxyConfig( - externalProxyConfig: ExternalProxyConfig - ) { - externalProxyConfig.validate() + override fun visitExternal(external: External) { + external.validate() } } ) @@ -5937,13 +5927,10 @@ private constructor( internal fun validity(): Int = accept( object : Visitor { - override fun visitBrowserbaseProxyConfig( - browserbaseProxyConfig: BrowserbaseProxyConfig - ) = browserbaseProxyConfig.validity() + override fun visitBrowserbase(browserbase: Browserbase) = + browserbase.validity() - override fun visitExternalProxyConfig( - externalProxyConfig: ExternalProxyConfig - ) = externalProxyConfig.validity() + override fun visitExternal(external: External) = external.validity() override fun unknown(json: JsonValue?) = 0 } @@ -5955,19 +5942,17 @@ private constructor( } return other is UnnamedSchemaWithArrayParent0 && - browserbaseProxyConfig == other.browserbaseProxyConfig && - externalProxyConfig == other.externalProxyConfig + browserbase == other.browserbase && + external == other.external } - override fun hashCode(): Int = - Objects.hash(browserbaseProxyConfig, externalProxyConfig) + override fun hashCode(): Int = Objects.hash(browserbase, external) override fun toString(): String = when { - browserbaseProxyConfig != null -> - "UnnamedSchemaWithArrayParent0{browserbaseProxyConfig=$browserbaseProxyConfig}" - externalProxyConfig != null -> - "UnnamedSchemaWithArrayParent0{externalProxyConfig=$externalProxyConfig}" + browserbase != null -> + "UnnamedSchemaWithArrayParent0{browserbase=$browserbase}" + external != null -> "UnnamedSchemaWithArrayParent0{external=$external}" _json != null -> "UnnamedSchemaWithArrayParent0{_unknown=$_json}" else -> throw IllegalStateException("Invalid UnnamedSchemaWithArrayParent0") } @@ -5975,14 +5960,12 @@ private constructor( companion object { @JvmStatic - fun ofBrowserbaseProxyConfig(browserbaseProxyConfig: BrowserbaseProxyConfig) = - UnnamedSchemaWithArrayParent0( - browserbaseProxyConfig = browserbaseProxyConfig - ) + fun ofBrowserbase(browserbase: Browserbase) = + UnnamedSchemaWithArrayParent0(browserbase = browserbase) @JvmStatic - fun ofExternalProxyConfig(externalProxyConfig: ExternalProxyConfig) = - UnnamedSchemaWithArrayParent0(externalProxyConfig = externalProxyConfig) + fun ofExternal(external: External) = + UnnamedSchemaWithArrayParent0(external = external) } /** @@ -5991,11 +5974,9 @@ private constructor( */ interface Visitor { - fun visitBrowserbaseProxyConfig( - browserbaseProxyConfig: BrowserbaseProxyConfig - ): T + fun visitBrowserbase(browserbase: Browserbase): T - fun visitExternalProxyConfig(externalProxyConfig: ExternalProxyConfig): T + fun visitExternal(external: External): T /** * Maps an unknown variant of [UnnamedSchemaWithArrayParent0] to a value of type @@ -6024,38 +6005,22 @@ private constructor( node: JsonNode ): UnnamedSchemaWithArrayParent0 { val json = JsonValue.fromJsonNode(node) + val type = json.asObject().getOrNull()?.get("type")?.asString()?.getOrNull() - val bestMatches = - sequenceOf( - tryDeserialize(node, jacksonTypeRef()) - ?.let { - UnnamedSchemaWithArrayParent0( - browserbaseProxyConfig = it, - _json = json, - ) - }, - tryDeserialize(node, jacksonTypeRef()) - ?.let { - UnnamedSchemaWithArrayParent0( - externalProxyConfig = it, - _json = json, - ) - }, - ) - .filterNotNull() - .allMaxBy { it.validity() } - .toList() - return when (bestMatches.size) { - // This can happen if what we're deserializing is completely - // incompatible with all the possible variants (e.g. deserializing from - // boolean). - 0 -> UnnamedSchemaWithArrayParent0(_json = json) - 1 -> bestMatches.single() - // If there's more than one match with the highest validity, then use - // the first completely valid match, or simply the first match if none - // are completely valid. - else -> bestMatches.firstOrNull { it.isValid() } ?: bestMatches.first() + when (type) { + "browserbase" -> { + return tryDeserialize(node, jacksonTypeRef())?.let { + UnnamedSchemaWithArrayParent0(browserbase = it, _json = json) + } ?: UnnamedSchemaWithArrayParent0(_json = json) + } + "external" -> { + return tryDeserialize(node, jacksonTypeRef())?.let { + UnnamedSchemaWithArrayParent0(external = it, _json = json) + } ?: UnnamedSchemaWithArrayParent0(_json = json) + } } + + return UnnamedSchemaWithArrayParent0(_json = json) } } @@ -6070,10 +6035,8 @@ private constructor( provider: SerializerProvider, ) { when { - value.browserbaseProxyConfig != null -> - generator.writeObject(value.browserbaseProxyConfig) - value.externalProxyConfig != null -> - generator.writeObject(value.externalProxyConfig) + value.browserbase != null -> generator.writeObject(value.browserbase) + value.external != null -> generator.writeObject(value.external) value._json != null -> generator.writeObject(value._json) else -> throw IllegalStateException("Invalid UnnamedSchemaWithArrayParent0") @@ -6081,7 +6044,7 @@ private constructor( } } - class BrowserbaseProxyConfig + class Browserbase @JsonCreator(mode = JsonCreator.Mode.DISABLED) private constructor( private val type: JsonValue, @@ -6161,13 +6124,12 @@ private constructor( companion object { /** - * Returns a mutable builder for constructing an instance of - * [BrowserbaseProxyConfig]. + * Returns a mutable builder for constructing an instance of [Browserbase]. */ @JvmStatic fun builder() = Builder() } - /** A builder for [BrowserbaseProxyConfig]. */ + /** A builder for [Browserbase]. */ class Builder internal constructor() { private var type: JsonValue = JsonValue.from("browserbase") @@ -6177,12 +6139,11 @@ private constructor( mutableMapOf() @JvmSynthetic - internal fun from(browserbaseProxyConfig: BrowserbaseProxyConfig) = apply { - type = browserbaseProxyConfig.type - domainPattern = browserbaseProxyConfig.domainPattern - geolocation = browserbaseProxyConfig.geolocation - additionalProperties = - browserbaseProxyConfig.additionalProperties.toMutableMap() + internal fun from(browserbase: Browserbase) = apply { + type = browserbase.type + domainPattern = browserbase.domainPattern + geolocation = browserbase.geolocation + additionalProperties = browserbase.additionalProperties.toMutableMap() } /** @@ -6250,12 +6211,12 @@ private constructor( } /** - * Returns an immutable instance of [BrowserbaseProxyConfig]. + * Returns an immutable instance of [Browserbase]. * * Further updates to this [Builder] will not mutate the returned instance. */ - fun build(): BrowserbaseProxyConfig = - BrowserbaseProxyConfig( + fun build(): Browserbase = + Browserbase( type, domainPattern, geolocation, @@ -6265,7 +6226,7 @@ private constructor( private var validated: Boolean = false - fun validate(): BrowserbaseProxyConfig = apply { + fun validate(): Browserbase = apply { if (validated) { return@apply } @@ -6554,7 +6515,7 @@ private constructor( return true } - return other is BrowserbaseProxyConfig && + return other is Browserbase && type == other.type && domainPattern == other.domainPattern && geolocation == other.geolocation && @@ -6568,10 +6529,10 @@ private constructor( override fun hashCode(): Int = hashCode override fun toString() = - "BrowserbaseProxyConfig{type=$type, domainPattern=$domainPattern, geolocation=$geolocation, additionalProperties=$additionalProperties}" + "Browserbase{type=$type, domainPattern=$domainPattern, geolocation=$geolocation, additionalProperties=$additionalProperties}" } - class ExternalProxyConfig + class External @JsonCreator(mode = JsonCreator.Mode.DISABLED) private constructor( private val server: JsonField, @@ -6691,8 +6652,7 @@ private constructor( companion object { /** - * Returns a mutable builder for constructing an instance of - * [ExternalProxyConfig]. + * Returns a mutable builder for constructing an instance of [External]. * * The following fields are required: * ```java @@ -6702,7 +6662,7 @@ private constructor( @JvmStatic fun builder() = Builder() } - /** A builder for [ExternalProxyConfig]. */ + /** A builder for [External]. */ class Builder internal constructor() { private var server: JsonField? = null @@ -6714,14 +6674,13 @@ private constructor( mutableMapOf() @JvmSynthetic - internal fun from(externalProxyConfig: ExternalProxyConfig) = apply { - server = externalProxyConfig.server - type = externalProxyConfig.type - domainPattern = externalProxyConfig.domainPattern - password = externalProxyConfig.password - username = externalProxyConfig.username - additionalProperties = - externalProxyConfig.additionalProperties.toMutableMap() + internal fun from(external: External) = apply { + server = external.server + type = external.type + domainPattern = external.domainPattern + password = external.password + username = external.username + additionalProperties = external.additionalProperties.toMutableMap() } fun server(server: String) = server(JsonField.of(server)) @@ -6812,7 +6771,7 @@ private constructor( } /** - * Returns an immutable instance of [ExternalProxyConfig]. + * Returns an immutable instance of [External]. * * Further updates to this [Builder] will not mutate the returned instance. * @@ -6823,8 +6782,8 @@ private constructor( * * @throws IllegalStateException if any required field is unset. */ - fun build(): ExternalProxyConfig = - ExternalProxyConfig( + fun build(): External = + External( checkRequired("server", server), type, domainPattern, @@ -6836,7 +6795,7 @@ private constructor( private var validated: Boolean = false - fun validate(): ExternalProxyConfig = apply { + fun validate(): External = apply { if (validated) { return@apply } @@ -6882,7 +6841,7 @@ private constructor( return true } - return other is ExternalProxyConfig && + return other is External && server == other.server && type == other.type && domainPattern == other.domainPattern && @@ -6905,7 +6864,7 @@ private constructor( override fun hashCode(): Int = hashCode override fun toString() = - "ExternalProxyConfig{server=$server, type=$type, domainPattern=$domainPattern, password=$password, username=$username, additionalProperties=$additionalProperties}" + "External{server=$server, type=$type, domainPattern=$domainPattern, password=$password, username=$username, additionalProperties=$additionalProperties}" } } } @@ -7190,6 +7149,137 @@ private constructor( "BrowserbaseSessionCreateParams{browserSettings=$browserSettings, extensionId=$extensionId, keepAlive=$keepAlive, projectId=$projectId, proxies=$proxies, region=$region, timeout=$timeout, userMetadata=$userMetadata, additionalProperties=$additionalProperties}" } + /** Logging verbosity level (0=quiet, 1=normal, 2=debug) */ + class Verbose @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 { + + @JvmField val _0 = of(0L) + + @JvmField val _1 = of(1L) + + @JvmField val _2 = of(2L) + + @JvmStatic fun of(value: Long) = Verbose(JsonField.of(value)) + } + + /** An enum containing [Verbose]'s known values. */ + enum class Known { + _0, + _1, + _2, + } + + /** + * An enum containing [Verbose]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [Verbose] 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 { + _0, + _1, + _2, + /** An enum member indicating that [Verbose] 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) { + _0 -> Value._0 + _1 -> Value._1 + _2 -> Value._2 + 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) { + _0 -> Known._0 + _1 -> Known._1 + _2 -> Known._2 + else -> throw StagehandInvalidDataException("Unknown Verbose: $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 asLong(): Long = + _value().asNumber().getOrNull()?.let { + if (it.toDouble() % 1 == 0.0) it.toLong() else null + } ?: throw StagehandInvalidDataException("Value is not a Long") + + private var validated: Boolean = false + + fun validate(): Verbose = 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. + */ + @JvmSynthetic 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 Verbose && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + /** Client SDK language */ class XLanguage @JsonCreator private constructor(private val value: JsonField) : Enum { diff --git a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/ModelConfigTest.kt b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/ModelConfigTest.kt index b45bc3f..d83a01a 100644 --- a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/ModelConfigTest.kt +++ b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/ModelConfigTest.kt @@ -13,19 +13,19 @@ import org.junit.jupiter.api.assertThrows internal class ModelConfigTest { @Test - fun ofString() { - val string = "string" + fun ofName() { + val name = "openai/gpt-5-nano" - val modelConfig = ModelConfig.ofString(string) + val modelConfig = ModelConfig.ofName(name) - assertThat(modelConfig.string()).contains(string) - assertThat(modelConfig.unionMember1()).isEmpty + assertThat(modelConfig.name()).contains(name) + assertThat(modelConfig.modelConfigObject()).isEmpty } @Test - fun ofStringRoundtrip() { + fun ofNameRoundtrip() { val jsonMapper = jsonMapper() - val modelConfig = ModelConfig.ofString("string") + val modelConfig = ModelConfig.ofName("openai/gpt-5-nano") val roundtrippedModelConfig = jsonMapper.readValue( @@ -37,29 +37,29 @@ internal class ModelConfigTest { } @Test - fun ofUnionMember1() { - val unionMember1 = - ModelConfig.UnionMember1.builder() - .modelName("modelName") - .apiKey("apiKey") - .baseUrl("https://example.com") + fun ofModelConfigObject() { + val modelConfigObject = + ModelConfig.ModelConfigObject.builder() + .modelName("gpt-5-nano") + .apiKey("sk-some-openai-api-key") + .baseUrl("https://api.openai.com/v1") .build() - val modelConfig = ModelConfig.ofUnionMember1(unionMember1) + val modelConfig = ModelConfig.ofModelConfigObject(modelConfigObject) - assertThat(modelConfig.string()).isEmpty - assertThat(modelConfig.unionMember1()).contains(unionMember1) + assertThat(modelConfig.name()).isEmpty + assertThat(modelConfig.modelConfigObject()).contains(modelConfigObject) } @Test - fun ofUnionMember1Roundtrip() { + fun ofModelConfigObjectRoundtrip() { val jsonMapper = jsonMapper() val modelConfig = - ModelConfig.ofUnionMember1( - ModelConfig.UnionMember1.builder() - .modelName("modelName") - .apiKey("apiKey") - .baseUrl("https://example.com") + ModelConfig.ofModelConfigObject( + ModelConfig.ModelConfigObject.builder() + .modelName("gpt-5-nano") + .apiKey("sk-some-openai-api-key") + .baseUrl("https://api.openai.com/v1") .build() ) diff --git a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionActParamsTest.kt b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionActParamsTest.kt index c31444c..2b5fb57 100644 --- a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionActParamsTest.kt +++ b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionActParamsTest.kt @@ -22,7 +22,7 @@ internal class SessionActParamsTest { .frameId("frameId") .options( SessionActParams.Options.builder() - .model("string") + .model("openai/gpt-5-nano") .timeout(30000.0) .variables( SessionActParams.Options.Variables.builder() @@ -60,7 +60,7 @@ internal class SessionActParamsTest { .frameId("frameId") .options( SessionActParams.Options.builder() - .model("string") + .model("openai/gpt-5-nano") .timeout(30000.0) .variables( SessionActParams.Options.Variables.builder() @@ -110,7 +110,7 @@ internal class SessionActParamsTest { .frameId("frameId") .options( SessionActParams.Options.builder() - .model("string") + .model("openai/gpt-5-nano") .timeout(30000.0) .variables( SessionActParams.Options.Variables.builder() @@ -129,7 +129,7 @@ internal class SessionActParamsTest { assertThat(body.options()) .contains( SessionActParams.Options.builder() - .model("string") + .model("openai/gpt-5-nano") .timeout(30000.0) .variables( SessionActParams.Options.Variables.builder() diff --git a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionEndResponseTest.kt b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionEndResponseTest.kt index 30e45db..041295f 100644 --- a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionEndResponseTest.kt +++ b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionEndResponseTest.kt @@ -11,13 +11,15 @@ internal class SessionEndResponseTest { @Test fun create() { - val sessionEndResponse = SessionEndResponse.builder().build() + val sessionEndResponse = SessionEndResponse.builder().success(true).build() + + assertThat(sessionEndResponse.success()).isEqualTo(true) } @Test fun roundtrip() { val jsonMapper = jsonMapper() - val sessionEndResponse = SessionEndResponse.builder().build() + val sessionEndResponse = SessionEndResponse.builder().success(true).build() val roundtrippedSessionEndResponse = jsonMapper.readValue( diff --git a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionExecuteParamsTest.kt b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionExecuteParamsTest.kt index b40f381..7d7caf8 100644 --- a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionExecuteParamsTest.kt +++ b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionExecuteParamsTest.kt @@ -20,7 +20,7 @@ internal class SessionExecuteParamsTest { .agentConfig( SessionExecuteParams.AgentConfig.builder() .cua(true) - .model("string") + .model("openai/gpt-5-nano") .systemPrompt("systemPrompt") .build() ) @@ -69,7 +69,7 @@ internal class SessionExecuteParamsTest { .agentConfig( SessionExecuteParams.AgentConfig.builder() .cua(true) - .model("string") + .model("openai/gpt-5-nano") .systemPrompt("systemPrompt") .build() ) @@ -130,7 +130,7 @@ internal class SessionExecuteParamsTest { .agentConfig( SessionExecuteParams.AgentConfig.builder() .cua(true) - .model("string") + .model("openai/gpt-5-nano") .systemPrompt("systemPrompt") .build() ) @@ -152,7 +152,7 @@ internal class SessionExecuteParamsTest { .isEqualTo( SessionExecuteParams.AgentConfig.builder() .cua(true) - .model("string") + .model("openai/gpt-5-nano") .systemPrompt("systemPrompt") .build() ) diff --git a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionExtractParamsTest.kt b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionExtractParamsTest.kt index 4a3c252..30bc290 100644 --- a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionExtractParamsTest.kt +++ b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionExtractParamsTest.kt @@ -22,7 +22,7 @@ internal class SessionExtractParamsTest { .instruction("Extract all product names and prices from the page") .options( SessionExtractParams.Options.builder() - .model("string") + .model("openai/gpt-5-nano") .selector("#main-content") .timeout(30000.0) .build() @@ -58,7 +58,7 @@ internal class SessionExtractParamsTest { .instruction("Extract all product names and prices from the page") .options( SessionExtractParams.Options.builder() - .model("string") + .model("openai/gpt-5-nano") .selector("#main-content") .timeout(30000.0) .build() @@ -106,7 +106,7 @@ internal class SessionExtractParamsTest { .instruction("Extract all product names and prices from the page") .options( SessionExtractParams.Options.builder() - .model("string") + .model("openai/gpt-5-nano") .selector("#main-content") .timeout(30000.0) .build() @@ -126,7 +126,7 @@ internal class SessionExtractParamsTest { assertThat(body.options()) .contains( SessionExtractParams.Options.builder() - .model("string") + .model("openai/gpt-5-nano") .selector("#main-content") .timeout(30000.0) .build() diff --git a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionObserveParamsTest.kt b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionObserveParamsTest.kt index 95ccd9b..98d7d9a 100644 --- a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionObserveParamsTest.kt +++ b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionObserveParamsTest.kt @@ -21,7 +21,7 @@ internal class SessionObserveParamsTest { .instruction("Find all clickable navigation links") .options( SessionObserveParams.Options.builder() - .model("string") + .model("openai/gpt-5-nano") .selector("nav") .timeout(30000.0) .build() @@ -52,7 +52,7 @@ internal class SessionObserveParamsTest { .instruction("Find all clickable navigation links") .options( SessionObserveParams.Options.builder() - .model("string") + .model("openai/gpt-5-nano") .selector("nav") .timeout(30000.0) .build() @@ -95,7 +95,7 @@ internal class SessionObserveParamsTest { .instruction("Find all clickable navigation links") .options( SessionObserveParams.Options.builder() - .model("string") + .model("openai/gpt-5-nano") .selector("nav") .timeout(30000.0) .build() @@ -109,7 +109,7 @@ internal class SessionObserveParamsTest { assertThat(body.options()) .contains( SessionObserveParams.Options.builder() - .model("string") + .model("openai/gpt-5-nano") .selector("nav") .timeout(30000.0) .build() diff --git a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionStartParamsTest.kt b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionStartParamsTest.kt index 0dc5811..13ae538 100644 --- a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionStartParamsTest.kt +++ b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionStartParamsTest.kt @@ -153,7 +153,7 @@ internal class SessionStartParamsTest { .experimental(true) .selfHeal(true) .systemPrompt("systemPrompt") - .verbose(1L) + .verbose(SessionStartParams.Verbose._1) .waitForCaptchaSolves(true) .build() } @@ -306,7 +306,7 @@ internal class SessionStartParamsTest { .experimental(true) .selfHeal(true) .systemPrompt("systemPrompt") - .verbose(1L) + .verbose(SessionStartParams.Verbose._1) .waitForCaptchaSolves(true) .build() @@ -480,7 +480,7 @@ internal class SessionStartParamsTest { .experimental(true) .selfHeal(true) .systemPrompt("systemPrompt") - .verbose(1L) + .verbose(SessionStartParams.Verbose._1) .waitForCaptchaSolves(true) .build() @@ -624,7 +624,7 @@ internal class SessionStartParamsTest { assertThat(body.experimental()).contains(true) assertThat(body.selfHeal()).contains(true) assertThat(body.systemPrompt()).contains("systemPrompt") - assertThat(body.verbose()).contains(1L) + assertThat(body.verbose()).contains(SessionStartParams.Verbose._1) assertThat(body.waitForCaptchaSolves()).contains(true) } diff --git a/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/ErrorHandlingTest.kt b/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/ErrorHandlingTest.kt index 967794c..87af3f1 100644 --- a/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/ErrorHandlingTest.kt +++ b/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/ErrorHandlingTest.kt @@ -230,7 +230,7 @@ internal class ErrorHandlingTest { .experimental(true) .selfHeal(true) .systemPrompt("systemPrompt") - .verbose(1L) + .verbose(SessionStartParams.Verbose._1) .waitForCaptchaSolves(true) .build() ) @@ -410,7 +410,7 @@ internal class ErrorHandlingTest { .experimental(true) .selfHeal(true) .systemPrompt("systemPrompt") - .verbose(1L) + .verbose(SessionStartParams.Verbose._1) .waitForCaptchaSolves(true) .build() ) @@ -590,7 +590,7 @@ internal class ErrorHandlingTest { .experimental(true) .selfHeal(true) .systemPrompt("systemPrompt") - .verbose(1L) + .verbose(SessionStartParams.Verbose._1) .waitForCaptchaSolves(true) .build() ) @@ -770,7 +770,7 @@ internal class ErrorHandlingTest { .experimental(true) .selfHeal(true) .systemPrompt("systemPrompt") - .verbose(1L) + .verbose(SessionStartParams.Verbose._1) .waitForCaptchaSolves(true) .build() ) @@ -950,7 +950,7 @@ internal class ErrorHandlingTest { .experimental(true) .selfHeal(true) .systemPrompt("systemPrompt") - .verbose(1L) + .verbose(SessionStartParams.Verbose._1) .waitForCaptchaSolves(true) .build() ) @@ -1130,7 +1130,7 @@ internal class ErrorHandlingTest { .experimental(true) .selfHeal(true) .systemPrompt("systemPrompt") - .verbose(1L) + .verbose(SessionStartParams.Verbose._1) .waitForCaptchaSolves(true) .build() ) @@ -1310,7 +1310,7 @@ internal class ErrorHandlingTest { .experimental(true) .selfHeal(true) .systemPrompt("systemPrompt") - .verbose(1L) + .verbose(SessionStartParams.Verbose._1) .waitForCaptchaSolves(true) .build() ) @@ -1490,7 +1490,7 @@ internal class ErrorHandlingTest { .experimental(true) .selfHeal(true) .systemPrompt("systemPrompt") - .verbose(1L) + .verbose(SessionStartParams.Verbose._1) .waitForCaptchaSolves(true) .build() ) @@ -1670,7 +1670,7 @@ internal class ErrorHandlingTest { .experimental(true) .selfHeal(true) .systemPrompt("systemPrompt") - .verbose(1L) + .verbose(SessionStartParams.Verbose._1) .waitForCaptchaSolves(true) .build() ) @@ -1850,7 +1850,7 @@ internal class ErrorHandlingTest { .experimental(true) .selfHeal(true) .systemPrompt("systemPrompt") - .verbose(1L) + .verbose(SessionStartParams.Verbose._1) .waitForCaptchaSolves(true) .build() ) @@ -2030,7 +2030,7 @@ internal class ErrorHandlingTest { .experimental(true) .selfHeal(true) .systemPrompt("systemPrompt") - .verbose(1L) + .verbose(SessionStartParams.Verbose._1) .waitForCaptchaSolves(true) .build() ) @@ -2210,7 +2210,7 @@ internal class ErrorHandlingTest { .experimental(true) .selfHeal(true) .systemPrompt("systemPrompt") - .verbose(1L) + .verbose(SessionStartParams.Verbose._1) .waitForCaptchaSolves(true) .build() ) @@ -2390,7 +2390,7 @@ internal class ErrorHandlingTest { .experimental(true) .selfHeal(true) .systemPrompt("systemPrompt") - .verbose(1L) + .verbose(SessionStartParams.Verbose._1) .waitForCaptchaSolves(true) .build() ) @@ -2570,7 +2570,7 @@ internal class ErrorHandlingTest { .experimental(true) .selfHeal(true) .systemPrompt("systemPrompt") - .verbose(1L) + .verbose(SessionStartParams.Verbose._1) .waitForCaptchaSolves(true) .build() ) @@ -2750,7 +2750,7 @@ internal class ErrorHandlingTest { .experimental(true) .selfHeal(true) .systemPrompt("systemPrompt") - .verbose(1L) + .verbose(SessionStartParams.Verbose._1) .waitForCaptchaSolves(true) .build() ) @@ -2930,7 +2930,7 @@ internal class ErrorHandlingTest { .experimental(true) .selfHeal(true) .systemPrompt("systemPrompt") - .verbose(1L) + .verbose(SessionStartParams.Verbose._1) .waitForCaptchaSolves(true) .build() ) @@ -3108,7 +3108,7 @@ internal class ErrorHandlingTest { .experimental(true) .selfHeal(true) .systemPrompt("systemPrompt") - .verbose(1L) + .verbose(SessionStartParams.Verbose._1) .waitForCaptchaSolves(true) .build() ) diff --git a/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/ServiceParamsTest.kt b/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/ServiceParamsTest.kt index beb2b92..a50efce 100644 --- a/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/ServiceParamsTest.kt +++ b/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/ServiceParamsTest.kt @@ -192,7 +192,7 @@ internal class ServiceParamsTest { .experimental(true) .selfHeal(true) .systemPrompt("systemPrompt") - .verbose(1L) + .verbose(SessionStartParams.Verbose._1) .waitForCaptchaSolves(true) .putAdditionalHeader("Secret-Header", "42") .putAdditionalQueryParam("secret_query_param", "42") @@ -225,7 +225,7 @@ internal class ServiceParamsTest { .frameId("frameId") .options( SessionActParams.Options.builder() - .model("string") + .model("openai/gpt-5-nano") .timeout(30000.0) .variables( SessionActParams.Options.Variables.builder() diff --git a/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/async/SessionServiceAsyncTest.kt b/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/async/SessionServiceAsyncTest.kt index fd11f6e..8abcbcb 100644 --- a/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/async/SessionServiceAsyncTest.kt +++ b/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/async/SessionServiceAsyncTest.kt @@ -44,7 +44,7 @@ internal class SessionServiceAsyncTest { .frameId("frameId") .options( SessionActParams.Options.builder() - .model("string") + .model("openai/gpt-5-nano") .timeout(30000.0) .variables( SessionActParams.Options.Variables.builder() @@ -110,7 +110,7 @@ internal class SessionServiceAsyncTest { .agentConfig( SessionExecuteParams.AgentConfig.builder() .cua(true) - .model("string") + .model("openai/gpt-5-nano") .systemPrompt("systemPrompt") .build() ) @@ -155,7 +155,7 @@ internal class SessionServiceAsyncTest { .instruction("Extract all product names and prices from the page") .options( SessionExtractParams.Options.builder() - .model("string") + .model("openai/gpt-5-nano") .selector("#main-content") .timeout(30000.0) .build() @@ -232,7 +232,7 @@ internal class SessionServiceAsyncTest { .instruction("Find all clickable navigation links") .options( SessionObserveParams.Options.builder() - .model("string") + .model("openai/gpt-5-nano") .selector("nav") .timeout(30000.0) .build() @@ -406,7 +406,7 @@ internal class SessionServiceAsyncTest { .experimental(true) .selfHeal(true) .systemPrompt("systemPrompt") - .verbose(1L) + .verbose(SessionStartParams.Verbose._1) .waitForCaptchaSolves(true) .build() ) diff --git a/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/blocking/SessionServiceTest.kt b/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/blocking/SessionServiceTest.kt index ba02cd0..937b3ea 100644 --- a/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/blocking/SessionServiceTest.kt +++ b/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/blocking/SessionServiceTest.kt @@ -44,7 +44,7 @@ internal class SessionServiceTest { .frameId("frameId") .options( SessionActParams.Options.builder() - .model("string") + .model("openai/gpt-5-nano") .timeout(30000.0) .variables( SessionActParams.Options.Variables.builder() @@ -108,7 +108,7 @@ internal class SessionServiceTest { .agentConfig( SessionExecuteParams.AgentConfig.builder() .cua(true) - .model("string") + .model("openai/gpt-5-nano") .systemPrompt("systemPrompt") .build() ) @@ -152,7 +152,7 @@ internal class SessionServiceTest { .instruction("Extract all product names and prices from the page") .options( SessionExtractParams.Options.builder() - .model("string") + .model("openai/gpt-5-nano") .selector("#main-content") .timeout(30000.0) .build() @@ -227,7 +227,7 @@ internal class SessionServiceTest { .instruction("Find all clickable navigation links") .options( SessionObserveParams.Options.builder() - .model("string") + .model("openai/gpt-5-nano") .selector("nav") .timeout(30000.0) .build() @@ -400,7 +400,7 @@ internal class SessionServiceTest { .experimental(true) .selfHeal(true) .systemPrompt("systemPrompt") - .verbose(1L) + .verbose(SessionStartParams.Verbose._1) .waitForCaptchaSolves(true) .build() ) diff --git a/stagehand-java-proguard-test/src/test/kotlin/com/browserbase/api/proguard/ProGuardCompatibilityTest.kt b/stagehand-java-proguard-test/src/test/kotlin/com/browserbase/api/proguard/ProGuardCompatibilityTest.kt index 63da21d..0d52560 100644 --- a/stagehand-java-proguard-test/src/test/kotlin/com/browserbase/api/proguard/ProGuardCompatibilityTest.kt +++ b/stagehand-java-proguard-test/src/test/kotlin/com/browserbase/api/proguard/ProGuardCompatibilityTest.kt @@ -76,7 +76,7 @@ internal class ProGuardCompatibilityTest { @Test fun modelConfigRoundtrip() { val jsonMapper = jsonMapper() - val modelConfig = ModelConfig.ofString("string") + val modelConfig = ModelConfig.ofName("openai/gpt-5-nano") val roundtrippedModelConfig = jsonMapper.readValue( From f15d8ac7cc7ebfc32e24940c1f1ea5c43b5aae26 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 17 Dec 2025 19:06:17 +0000 Subject: [PATCH 10/18] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 38ef77c..65bd734 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-817d1d4e845b1946dac8ee10fd34b3f533aa36f74ac598582ffb1b0399a5a932.yml -openapi_spec_hash: 9d856db62b34909fec94743235b3d7be +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/browserbase%2Fstagehand-e09ad013e10b6a6bb76dd9b2067696ba92bd7acb862b39bbfe2f296ebdb6eddf.yml +openapi_spec_hash: 2f633591561e4737534842273441a818 config_hash: 88e87ba7021be93d267ecfc8f5e6b891 From 9b6860a4f60d1a740fbb026eef291e40fb8e1845 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 17 Dec 2025 20:09:02 +0000 Subject: [PATCH 11/18] feat(api): manual updates --- .stats.yml | 6 +- .../api/models/sessions/SessionStartParams.kt | 304 ++++-------------- .../models/sessions/SessionActParamsTest.kt | 8 +- .../models/sessions/SessionEndParamsTest.kt | 6 +- .../sessions/SessionExecuteParamsTest.kt | 8 +- .../sessions/SessionExtractParamsTest.kt | 8 +- .../sessions/SessionNavigateParamsTest.kt | 8 +- .../sessions/SessionObserveParamsTest.kt | 8 +- .../models/sessions/SessionStartParamsTest.kt | 16 +- .../api/services/ErrorHandlingTest.kt | 68 ++-- .../api/services/ServiceParamsTest.kt | 6 +- .../services/async/SessionServiceAsyncTest.kt | 16 +- .../services/blocking/SessionServiceTest.kt | 16 +- 13 files changed, 156 insertions(+), 322 deletions(-) diff --git a/.stats.yml b/.stats.yml index 65bd734..604325f 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-e09ad013e10b6a6bb76dd9b2067696ba92bd7acb862b39bbfe2f296ebdb6eddf.yml -openapi_spec_hash: 2f633591561e4737534842273441a818 -config_hash: 88e87ba7021be93d267ecfc8f5e6b891 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/browserbase%2Fstagehand-e96507dd78e76fccc77ba7fb09704da127ead6f4d73ea854e9b2150e90787ff4.yml +openapi_spec_hash: 0c2548b8fdd6de6789b19123e69609c1 +config_hash: c3abb41dbe698d59b3bf12f393013d54 diff --git a/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionStartParams.kt b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionStartParams.kt index 57f072f..16eecb4 100644 --- a/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionStartParams.kt +++ b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionStartParams.kt @@ -142,7 +142,7 @@ private constructor( * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). */ - fun verbose(): Optional = body.verbose() + fun verbose(): Optional = body.verbose() /** * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if the @@ -229,7 +229,7 @@ private constructor( * * Unlike [verbose], this method doesn't throw if the JSON field has an unexpected type. */ - fun _verbose(): JsonField = body._verbose() + fun _verbose(): JsonField = body._verbose() /** * Returns the raw JSON value of [waitForCaptchaSolves]. @@ -459,15 +459,15 @@ private constructor( } /** Logging verbosity level (0=quiet, 1=normal, 2=debug) */ - fun verbose(verbose: Verbose) = apply { body.verbose(verbose) } + fun verbose(verbose: Long) = apply { body.verbose(verbose) } /** * Sets [Builder.verbose] to an arbitrary JSON value. * - * You should usually call [Builder.verbose] with a well-typed [Verbose] value instead. This + * You should usually call [Builder.verbose] with a well-typed [Long] value instead. This * method is primarily for setting the field to an undocumented or not yet supported value. */ - fun verbose(verbose: JsonField) = apply { body.verbose(verbose) } + fun verbose(verbose: JsonField) = apply { body.verbose(verbose) } fun waitForCaptchaSolves(waitForCaptchaSolves: Boolean) = apply { body.waitForCaptchaSolves(waitForCaptchaSolves) @@ -653,7 +653,7 @@ private constructor( private val experimental: JsonField, private val selfHeal: JsonField, private val systemPrompt: JsonField, - private val verbose: JsonField, + private val verbose: JsonField, private val waitForCaptchaSolves: JsonField, private val additionalProperties: MutableMap, ) { @@ -689,7 +689,7 @@ private constructor( @JsonProperty("systemPrompt") @ExcludeMissing systemPrompt: JsonField = JsonMissing.of(), - @JsonProperty("verbose") @ExcludeMissing verbose: JsonField = JsonMissing.of(), + @JsonProperty("verbose") @ExcludeMissing verbose: JsonField = JsonMissing.of(), @JsonProperty("waitForCaptchaSolves") @ExcludeMissing waitForCaptchaSolves: JsonField = JsonMissing.of(), @@ -790,7 +790,7 @@ private constructor( * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if * the server responded with an unexpected value). */ - fun verbose(): Optional = verbose.getOptional("verbose") + fun verbose(): Optional = verbose.getOptional("verbose") /** * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if @@ -893,7 +893,7 @@ private constructor( * * Unlike [verbose], this method doesn't throw if the JSON field has an unexpected type. */ - @JsonProperty("verbose") @ExcludeMissing fun _verbose(): JsonField = verbose + @JsonProperty("verbose") @ExcludeMissing fun _verbose(): JsonField = verbose /** * Returns the raw JSON value of [waitForCaptchaSolves]. @@ -944,7 +944,7 @@ private constructor( private var experimental: JsonField = JsonMissing.of() private var selfHeal: JsonField = JsonMissing.of() private var systemPrompt: JsonField = JsonMissing.of() - private var verbose: JsonField = JsonMissing.of() + private var verbose: JsonField = JsonMissing.of() private var waitForCaptchaSolves: JsonField = JsonMissing.of() private var additionalProperties: MutableMap = mutableMapOf() @@ -1098,16 +1098,16 @@ private constructor( } /** Logging verbosity level (0=quiet, 1=normal, 2=debug) */ - fun verbose(verbose: Verbose) = verbose(JsonField.of(verbose)) + fun verbose(verbose: Long) = verbose(JsonField.of(verbose)) /** * Sets [Builder.verbose] to an arbitrary JSON value. * - * You should usually call [Builder.verbose] with a well-typed [Verbose] value instead. + * You should usually call [Builder.verbose] with a well-typed [Long] value instead. * This method is primarily for setting the field to an undocumented or not yet * supported value. */ - fun verbose(verbose: JsonField) = apply { this.verbose = verbose } + fun verbose(verbose: JsonField) = apply { this.verbose = verbose } fun waitForCaptchaSolves(waitForCaptchaSolves: Boolean) = waitForCaptchaSolves(JsonField.of(waitForCaptchaSolves)) @@ -1189,7 +1189,7 @@ private constructor( experimental() selfHeal() systemPrompt() - verbose().ifPresent { it.validate() } + verbose() waitForCaptchaSolves() validated = true } @@ -1220,7 +1220,7 @@ private constructor( (if (experimental.asKnown().isPresent) 1 else 0) + (if (selfHeal.asKnown().isPresent) 1 else 0) + (if (systemPrompt.asKnown().isPresent) 1 else 0) + - (verbose.asKnown().getOrNull()?.validity() ?: 0) + + (if (verbose.asKnown().isPresent) 1 else 0) + (if (waitForCaptchaSolves.asKnown().isPresent) 1 else 0) override fun equals(other: Any?): Boolean { @@ -3408,13 +3408,9 @@ private constructor( /** Alias for calling [proxies] with `Proxies.ofBool(bool)`. */ fun proxies(bool: Boolean) = proxies(Proxies.ofBool(bool)) - /** - * Alias for calling [proxies] with - * `Proxies.ofUnnamedSchemaWithArrayParent0s(unnamedSchemaWithArrayParent0s)`. - */ - fun proxiesOfUnnamedSchemaWithArrayParent0s( - unnamedSchemaWithArrayParent0s: List - ) = proxies(Proxies.ofUnnamedSchemaWithArrayParent0s(unnamedSchemaWithArrayParent0s)) + /** Alias for calling [proxies] with `Proxies.ofProxyConfigList(proxyConfigList)`. */ + fun proxiesOfProxyConfigList(proxyConfigList: List) = + proxies(Proxies.ofProxyConfigList(proxyConfigList)) fun region(region: Region) = region(JsonField.of(region)) @@ -5668,31 +5664,30 @@ private constructor( class Proxies private constructor( private val bool: Boolean? = null, - private val unnamedSchemaWithArrayParent0s: List? = null, + private val proxyConfigList: List? = null, private val _json: JsonValue? = null, ) { fun bool(): Optional = Optional.ofNullable(bool) - fun unnamedSchemaWithArrayParent0s(): Optional> = - Optional.ofNullable(unnamedSchemaWithArrayParent0s) + fun proxyConfigList(): Optional> = + Optional.ofNullable(proxyConfigList) fun isBool(): Boolean = bool != null - fun isUnnamedSchemaWithArrayParent0s(): Boolean = unnamedSchemaWithArrayParent0s != null + fun isProxyConfigList(): Boolean = proxyConfigList != null fun asBool(): Boolean = bool.getOrThrow("bool") - fun asUnnamedSchemaWithArrayParent0s(): List = - unnamedSchemaWithArrayParent0s.getOrThrow("unnamedSchemaWithArrayParent0s") + fun asProxyConfigList(): List = + proxyConfigList.getOrThrow("proxyConfigList") fun _json(): Optional = Optional.ofNullable(_json) fun accept(visitor: Visitor): T = when { bool != null -> visitor.visitBool(bool) - unnamedSchemaWithArrayParent0s != null -> - visitor.visitUnnamedSchemaWithArrayParent0s(unnamedSchemaWithArrayParent0s) + proxyConfigList != null -> visitor.visitProxyConfigList(proxyConfigList) else -> visitor.unknown(_json) } @@ -5707,10 +5702,8 @@ private constructor( object : Visitor { override fun visitBool(bool: Boolean) {} - override fun visitUnnamedSchemaWithArrayParent0s( - unnamedSchemaWithArrayParent0s: List - ) { - unnamedSchemaWithArrayParent0s.forEach { it.validate() } + override fun visitProxyConfigList(proxyConfigList: List) { + proxyConfigList.forEach { it.validate() } } } ) @@ -5737,9 +5730,8 @@ private constructor( object : Visitor { override fun visitBool(bool: Boolean) = 1 - override fun visitUnnamedSchemaWithArrayParent0s( - unnamedSchemaWithArrayParent0s: List - ) = unnamedSchemaWithArrayParent0s.sumOf { it.validity().toInt() } + override fun visitProxyConfigList(proxyConfigList: List) = + proxyConfigList.sumOf { it.validity().toInt() } override fun unknown(json: JsonValue?) = 0 } @@ -5752,16 +5744,15 @@ private constructor( return other is Proxies && bool == other.bool && - unnamedSchemaWithArrayParent0s == other.unnamedSchemaWithArrayParent0s + proxyConfigList == other.proxyConfigList } - override fun hashCode(): Int = Objects.hash(bool, unnamedSchemaWithArrayParent0s) + override fun hashCode(): Int = Objects.hash(bool, proxyConfigList) override fun toString(): String = when { bool != null -> "Proxies{bool=$bool}" - unnamedSchemaWithArrayParent0s != null -> - "Proxies{unnamedSchemaWithArrayParent0s=$unnamedSchemaWithArrayParent0s}" + proxyConfigList != null -> "Proxies{proxyConfigList=$proxyConfigList}" _json != null -> "Proxies{_unknown=$_json}" else -> throw IllegalStateException("Invalid Proxies") } @@ -5771,13 +5762,8 @@ private constructor( @JvmStatic fun ofBool(bool: Boolean) = Proxies(bool = bool) @JvmStatic - fun ofUnnamedSchemaWithArrayParent0s( - unnamedSchemaWithArrayParent0s: List - ) = - Proxies( - unnamedSchemaWithArrayParent0s = - unnamedSchemaWithArrayParent0s.toImmutable() - ) + fun ofProxyConfigList(proxyConfigList: List) = + Proxies(proxyConfigList = proxyConfigList.toImmutable()) } /** @@ -5788,9 +5774,7 @@ private constructor( fun visitBool(bool: Boolean): T - fun visitUnnamedSchemaWithArrayParent0s( - unnamedSchemaWithArrayParent0s: List - ): T + fun visitProxyConfigList(proxyConfigList: List): T /** * Maps an unknown variant of [Proxies] to a value of type [T]. @@ -5817,13 +5801,9 @@ private constructor( tryDeserialize(node, jacksonTypeRef())?.let { Proxies(bool = it, _json = json) }, - tryDeserialize( - node, - jacksonTypeRef>(), - ) - ?.let { - Proxies(unnamedSchemaWithArrayParent0s = it, _json = json) - }, + tryDeserialize(node, jacksonTypeRef>())?.let { + Proxies(proxyConfigList = it, _json = json) + }, ) .filterNotNull() .allMaxBy { it.validity() } @@ -5850,17 +5830,17 @@ private constructor( ) { when { value.bool != null -> generator.writeObject(value.bool) - value.unnamedSchemaWithArrayParent0s != null -> - generator.writeObject(value.unnamedSchemaWithArrayParent0s) + value.proxyConfigList != null -> + generator.writeObject(value.proxyConfigList) value._json != null -> generator.writeObject(value._json) else -> throw IllegalStateException("Invalid Proxies") } } } - @JsonDeserialize(using = UnnamedSchemaWithArrayParent0.Deserializer::class) - @JsonSerialize(using = UnnamedSchemaWithArrayParent0.Serializer::class) - class UnnamedSchemaWithArrayParent0 + @JsonDeserialize(using = ProxyConfig.Deserializer::class) + @JsonSerialize(using = ProxyConfig.Serializer::class) + class ProxyConfig private constructor( private val browserbase: Browserbase? = null, private val external: External? = null, @@ -5890,7 +5870,7 @@ private constructor( private var validated: Boolean = false - fun validate(): UnnamedSchemaWithArrayParent0 = apply { + fun validate(): ProxyConfig = apply { if (validated) { return@apply } @@ -5941,7 +5921,7 @@ private constructor( return true } - return other is UnnamedSchemaWithArrayParent0 && + return other is ProxyConfig && browserbase == other.browserbase && external == other.external } @@ -5950,27 +5930,24 @@ private constructor( override fun toString(): String = when { - browserbase != null -> - "UnnamedSchemaWithArrayParent0{browserbase=$browserbase}" - external != null -> "UnnamedSchemaWithArrayParent0{external=$external}" - _json != null -> "UnnamedSchemaWithArrayParent0{_unknown=$_json}" - else -> throw IllegalStateException("Invalid UnnamedSchemaWithArrayParent0") + browserbase != null -> "ProxyConfig{browserbase=$browserbase}" + external != null -> "ProxyConfig{external=$external}" + _json != null -> "ProxyConfig{_unknown=$_json}" + else -> throw IllegalStateException("Invalid ProxyConfig") } companion object { @JvmStatic fun ofBrowserbase(browserbase: Browserbase) = - UnnamedSchemaWithArrayParent0(browserbase = browserbase) + ProxyConfig(browserbase = browserbase) - @JvmStatic - fun ofExternal(external: External) = - UnnamedSchemaWithArrayParent0(external = external) + @JvmStatic fun ofExternal(external: External) = ProxyConfig(external = external) } /** - * An interface that defines how to map each variant of - * [UnnamedSchemaWithArrayParent0] to a value of type [T]. + * An interface that defines how to map each variant of [ProxyConfig] to a value of + * type [T]. */ interface Visitor { @@ -5979,58 +5956,47 @@ private constructor( fun visitExternal(external: External): T /** - * Maps an unknown variant of [UnnamedSchemaWithArrayParent0] to a value of type - * [T]. + * Maps an unknown variant of [ProxyConfig] to a value of type [T]. * - * An instance of [UnnamedSchemaWithArrayParent0] can contain an unknown variant - * if it was deserialized from data that doesn't match any known variant. For - * example, if the SDK is on an older version than the API, then the API may - * respond with new variants that the SDK is unaware of. + * An instance of [ProxyConfig] can contain an unknown variant if it was + * deserialized from data that doesn't match any known variant. For example, if + * the SDK is on an older version than the API, then the API may respond with + * new variants that the SDK is unaware of. * * @throws StagehandInvalidDataException in the default implementation. */ fun unknown(json: JsonValue?): T { - throw StagehandInvalidDataException( - "Unknown UnnamedSchemaWithArrayParent0: $json" - ) + throw StagehandInvalidDataException("Unknown ProxyConfig: $json") } } - internal class Deserializer : - BaseDeserializer( - UnnamedSchemaWithArrayParent0::class - ) { + internal class Deserializer : BaseDeserializer(ProxyConfig::class) { - override fun ObjectCodec.deserialize( - node: JsonNode - ): UnnamedSchemaWithArrayParent0 { + override fun ObjectCodec.deserialize(node: JsonNode): ProxyConfig { val json = JsonValue.fromJsonNode(node) val type = json.asObject().getOrNull()?.get("type")?.asString()?.getOrNull() when (type) { "browserbase" -> { return tryDeserialize(node, jacksonTypeRef())?.let { - UnnamedSchemaWithArrayParent0(browserbase = it, _json = json) - } ?: UnnamedSchemaWithArrayParent0(_json = json) + ProxyConfig(browserbase = it, _json = json) + } ?: ProxyConfig(_json = json) } "external" -> { return tryDeserialize(node, jacksonTypeRef())?.let { - UnnamedSchemaWithArrayParent0(external = it, _json = json) - } ?: UnnamedSchemaWithArrayParent0(_json = json) + ProxyConfig(external = it, _json = json) + } ?: ProxyConfig(_json = json) } } - return UnnamedSchemaWithArrayParent0(_json = json) + return ProxyConfig(_json = json) } } - internal class Serializer : - BaseSerializer( - UnnamedSchemaWithArrayParent0::class - ) { + internal class Serializer : BaseSerializer(ProxyConfig::class) { override fun serialize( - value: UnnamedSchemaWithArrayParent0, + value: ProxyConfig, generator: JsonGenerator, provider: SerializerProvider, ) { @@ -6038,8 +6004,7 @@ private constructor( value.browserbase != null -> generator.writeObject(value.browserbase) value.external != null -> generator.writeObject(value.external) value._json != null -> generator.writeObject(value._json) - else -> - throw IllegalStateException("Invalid UnnamedSchemaWithArrayParent0") + else -> throw IllegalStateException("Invalid ProxyConfig") } } } @@ -7149,137 +7114,6 @@ private constructor( "BrowserbaseSessionCreateParams{browserSettings=$browserSettings, extensionId=$extensionId, keepAlive=$keepAlive, projectId=$projectId, proxies=$proxies, region=$region, timeout=$timeout, userMetadata=$userMetadata, additionalProperties=$additionalProperties}" } - /** Logging verbosity level (0=quiet, 1=normal, 2=debug) */ - class Verbose @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 { - - @JvmField val _0 = of(0L) - - @JvmField val _1 = of(1L) - - @JvmField val _2 = of(2L) - - @JvmStatic fun of(value: Long) = Verbose(JsonField.of(value)) - } - - /** An enum containing [Verbose]'s known values. */ - enum class Known { - _0, - _1, - _2, - } - - /** - * An enum containing [Verbose]'s known values, as well as an [_UNKNOWN] member. - * - * An instance of [Verbose] 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 { - _0, - _1, - _2, - /** An enum member indicating that [Verbose] 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) { - _0 -> Value._0 - _1 -> Value._1 - _2 -> Value._2 - 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) { - _0 -> Known._0 - _1 -> Known._1 - _2 -> Known._2 - else -> throw StagehandInvalidDataException("Unknown Verbose: $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 asLong(): Long = - _value().asNumber().getOrNull()?.let { - if (it.toDouble() % 1 == 0.0) it.toLong() else null - } ?: throw StagehandInvalidDataException("Value is not a Long") - - private var validated: Boolean = false - - fun validate(): Verbose = 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. - */ - @JvmSynthetic 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 Verbose && value == other.value - } - - override fun hashCode() = value.hashCode() - - override fun toString() = value.toString() - } - /** Client SDK language */ class XLanguage @JsonCreator private constructor(private val value: JsonField) : Enum { diff --git a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionActParamsTest.kt b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionActParamsTest.kt index 2b5fb57..9c19cb7 100644 --- a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionActParamsTest.kt +++ b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionActParamsTest.kt @@ -16,7 +16,7 @@ internal class SessionActParamsTest { .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") .xLanguage(SessionActParams.XLanguage.TYPESCRIPT) .xSdkVersion("3.0.6") - .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00Z")) .xStreamResponse(SessionActParams.XStreamResponse.TRUE) .input("Click the login button") .frameId("frameId") @@ -54,7 +54,7 @@ internal class SessionActParamsTest { .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") .xLanguage(SessionActParams.XLanguage.TYPESCRIPT) .xSdkVersion("3.0.6") - .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00Z")) .xStreamResponse(SessionActParams.XStreamResponse.TRUE) .input("Click the login button") .frameId("frameId") @@ -78,7 +78,7 @@ internal class SessionActParamsTest { Headers.builder() .put("x-language", "typescript") .put("x-sdk-version", "3.0.6") - .put("x-sent-at", "2025-01-15T10:30:00.000Z") + .put("x-sent-at", "2025-01-15T10:30:00Z") .put("x-stream-response", "true") .build() ) @@ -104,7 +104,7 @@ internal class SessionActParamsTest { .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") .xLanguage(SessionActParams.XLanguage.TYPESCRIPT) .xSdkVersion("3.0.6") - .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00Z")) .xStreamResponse(SessionActParams.XStreamResponse.TRUE) .input("Click the login button") .frameId("frameId") diff --git a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionEndParamsTest.kt b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionEndParamsTest.kt index 14faac3..bc50272 100644 --- a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionEndParamsTest.kt +++ b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionEndParamsTest.kt @@ -15,7 +15,7 @@ internal class SessionEndParamsTest { .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") .xLanguage(SessionEndParams.XLanguage.TYPESCRIPT) .xSdkVersion("3.0.6") - .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00Z")) .xStreamResponse(SessionEndParams.XStreamResponse.TRUE) .build() } @@ -36,7 +36,7 @@ internal class SessionEndParamsTest { .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") .xLanguage(SessionEndParams.XLanguage.TYPESCRIPT) .xSdkVersion("3.0.6") - .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00Z")) .xStreamResponse(SessionEndParams.XStreamResponse.TRUE) .build() @@ -47,7 +47,7 @@ internal class SessionEndParamsTest { Headers.builder() .put("x-language", "typescript") .put("x-sdk-version", "3.0.6") - .put("x-sent-at", "2025-01-15T10:30:00.000Z") + .put("x-sent-at", "2025-01-15T10:30:00Z") .put("x-stream-response", "true") .build() ) diff --git a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionExecuteParamsTest.kt b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionExecuteParamsTest.kt index 7d7caf8..4de6985 100644 --- a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionExecuteParamsTest.kt +++ b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionExecuteParamsTest.kt @@ -15,7 +15,7 @@ internal class SessionExecuteParamsTest { .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") .xLanguage(SessionExecuteParams.XLanguage.TYPESCRIPT) .xSdkVersion("3.0.6") - .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00Z")) .xStreamResponse(SessionExecuteParams.XStreamResponse.TRUE) .agentConfig( SessionExecuteParams.AgentConfig.builder() @@ -64,7 +64,7 @@ internal class SessionExecuteParamsTest { .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") .xLanguage(SessionExecuteParams.XLanguage.TYPESCRIPT) .xSdkVersion("3.0.6") - .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00Z")) .xStreamResponse(SessionExecuteParams.XStreamResponse.TRUE) .agentConfig( SessionExecuteParams.AgentConfig.builder() @@ -92,7 +92,7 @@ internal class SessionExecuteParamsTest { Headers.builder() .put("x-language", "typescript") .put("x-sdk-version", "3.0.6") - .put("x-sent-at", "2025-01-15T10:30:00.000Z") + .put("x-sent-at", "2025-01-15T10:30:00Z") .put("x-stream-response", "true") .build() ) @@ -125,7 +125,7 @@ internal class SessionExecuteParamsTest { .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") .xLanguage(SessionExecuteParams.XLanguage.TYPESCRIPT) .xSdkVersion("3.0.6") - .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00Z")) .xStreamResponse(SessionExecuteParams.XStreamResponse.TRUE) .agentConfig( SessionExecuteParams.AgentConfig.builder() diff --git a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionExtractParamsTest.kt b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionExtractParamsTest.kt index 30bc290..b8d0a00 100644 --- a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionExtractParamsTest.kt +++ b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionExtractParamsTest.kt @@ -16,7 +16,7 @@ internal class SessionExtractParamsTest { .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") .xLanguage(SessionExtractParams.XLanguage.TYPESCRIPT) .xSdkVersion("3.0.6") - .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00Z")) .xStreamResponse(SessionExtractParams.XStreamResponse.TRUE) .frameId("frameId") .instruction("Extract all product names and prices from the page") @@ -52,7 +52,7 @@ internal class SessionExtractParamsTest { .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") .xLanguage(SessionExtractParams.XLanguage.TYPESCRIPT) .xSdkVersion("3.0.6") - .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00Z")) .xStreamResponse(SessionExtractParams.XStreamResponse.TRUE) .frameId("frameId") .instruction("Extract all product names and prices from the page") @@ -77,7 +77,7 @@ internal class SessionExtractParamsTest { Headers.builder() .put("x-language", "typescript") .put("x-sdk-version", "3.0.6") - .put("x-sent-at", "2025-01-15T10:30:00.000Z") + .put("x-sent-at", "2025-01-15T10:30:00Z") .put("x-stream-response", "true") .build() ) @@ -100,7 +100,7 @@ internal class SessionExtractParamsTest { .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") .xLanguage(SessionExtractParams.XLanguage.TYPESCRIPT) .xSdkVersion("3.0.6") - .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00Z")) .xStreamResponse(SessionExtractParams.XStreamResponse.TRUE) .frameId("frameId") .instruction("Extract all product names and prices from the page") diff --git a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionNavigateParamsTest.kt b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionNavigateParamsTest.kt index aa845c3..3bba7d4 100644 --- a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionNavigateParamsTest.kt +++ b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionNavigateParamsTest.kt @@ -15,7 +15,7 @@ internal class SessionNavigateParamsTest { .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") .xLanguage(SessionNavigateParams.XLanguage.TYPESCRIPT) .xSdkVersion("3.0.6") - .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00Z")) .xStreamResponse(SessionNavigateParams.XStreamResponse.TRUE) .url("https://example.com") .frameId("frameId") @@ -49,7 +49,7 @@ internal class SessionNavigateParamsTest { .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") .xLanguage(SessionNavigateParams.XLanguage.TYPESCRIPT) .xSdkVersion("3.0.6") - .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00Z")) .xStreamResponse(SessionNavigateParams.XStreamResponse.TRUE) .url("https://example.com") .frameId("frameId") @@ -69,7 +69,7 @@ internal class SessionNavigateParamsTest { Headers.builder() .put("x-language", "typescript") .put("x-sdk-version", "3.0.6") - .put("x-sent-at", "2025-01-15T10:30:00.000Z") + .put("x-sent-at", "2025-01-15T10:30:00Z") .put("x-stream-response", "true") .build() ) @@ -95,7 +95,7 @@ internal class SessionNavigateParamsTest { .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") .xLanguage(SessionNavigateParams.XLanguage.TYPESCRIPT) .xSdkVersion("3.0.6") - .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00Z")) .xStreamResponse(SessionNavigateParams.XStreamResponse.TRUE) .url("https://example.com") .frameId("frameId") diff --git a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionObserveParamsTest.kt b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionObserveParamsTest.kt index 98d7d9a..db03460 100644 --- a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionObserveParamsTest.kt +++ b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionObserveParamsTest.kt @@ -15,7 +15,7 @@ internal class SessionObserveParamsTest { .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") .xLanguage(SessionObserveParams.XLanguage.TYPESCRIPT) .xSdkVersion("3.0.6") - .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00Z")) .xStreamResponse(SessionObserveParams.XStreamResponse.TRUE) .frameId("frameId") .instruction("Find all clickable navigation links") @@ -46,7 +46,7 @@ internal class SessionObserveParamsTest { .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") .xLanguage(SessionObserveParams.XLanguage.TYPESCRIPT) .xSdkVersion("3.0.6") - .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00Z")) .xStreamResponse(SessionObserveParams.XStreamResponse.TRUE) .frameId("frameId") .instruction("Find all clickable navigation links") @@ -66,7 +66,7 @@ internal class SessionObserveParamsTest { Headers.builder() .put("x-language", "typescript") .put("x-sdk-version", "3.0.6") - .put("x-sent-at", "2025-01-15T10:30:00.000Z") + .put("x-sent-at", "2025-01-15T10:30:00Z") .put("x-stream-response", "true") .build() ) @@ -89,7 +89,7 @@ internal class SessionObserveParamsTest { .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") .xLanguage(SessionObserveParams.XLanguage.TYPESCRIPT) .xSdkVersion("3.0.6") - .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00Z")) .xStreamResponse(SessionObserveParams.XStreamResponse.TRUE) .frameId("frameId") .instruction("Find all clickable navigation links") diff --git a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionStartParamsTest.kt b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionStartParamsTest.kt index 13ae538..56f4736 100644 --- a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionStartParamsTest.kt +++ b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionStartParamsTest.kt @@ -15,7 +15,7 @@ internal class SessionStartParamsTest { SessionStartParams.builder() .xLanguage(SessionStartParams.XLanguage.TYPESCRIPT) .xSdkVersion("3.0.6") - .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00Z")) .xStreamResponse(SessionStartParams.XStreamResponse.TRUE) .modelName("gpt-4o") .actTimeoutMs(30000.0) @@ -153,7 +153,7 @@ internal class SessionStartParamsTest { .experimental(true) .selfHeal(true) .systemPrompt("systemPrompt") - .verbose(SessionStartParams.Verbose._1) + .verbose(1L) .waitForCaptchaSolves(true) .build() } @@ -164,7 +164,7 @@ internal class SessionStartParamsTest { SessionStartParams.builder() .xLanguage(SessionStartParams.XLanguage.TYPESCRIPT) .xSdkVersion("3.0.6") - .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00Z")) .xStreamResponse(SessionStartParams.XStreamResponse.TRUE) .modelName("gpt-4o") .actTimeoutMs(30000.0) @@ -306,7 +306,7 @@ internal class SessionStartParamsTest { .experimental(true) .selfHeal(true) .systemPrompt("systemPrompt") - .verbose(SessionStartParams.Verbose._1) + .verbose(1L) .waitForCaptchaSolves(true) .build() @@ -317,7 +317,7 @@ internal class SessionStartParamsTest { Headers.builder() .put("x-language", "typescript") .put("x-sdk-version", "3.0.6") - .put("x-sent-at", "2025-01-15T10:30:00.000Z") + .put("x-sent-at", "2025-01-15T10:30:00Z") .put("x-stream-response", "true") .build() ) @@ -338,7 +338,7 @@ internal class SessionStartParamsTest { SessionStartParams.builder() .xLanguage(SessionStartParams.XLanguage.TYPESCRIPT) .xSdkVersion("3.0.6") - .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00Z")) .xStreamResponse(SessionStartParams.XStreamResponse.TRUE) .modelName("gpt-4o") .actTimeoutMs(30000.0) @@ -480,7 +480,7 @@ internal class SessionStartParamsTest { .experimental(true) .selfHeal(true) .systemPrompt("systemPrompt") - .verbose(SessionStartParams.Verbose._1) + .verbose(1L) .waitForCaptchaSolves(true) .build() @@ -624,7 +624,7 @@ internal class SessionStartParamsTest { assertThat(body.experimental()).contains(true) assertThat(body.selfHeal()).contains(true) assertThat(body.systemPrompt()).contains("systemPrompt") - assertThat(body.verbose()).contains(SessionStartParams.Verbose._1) + assertThat(body.verbose()).contains(1L) assertThat(body.waitForCaptchaSolves()).contains(true) } diff --git a/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/ErrorHandlingTest.kt b/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/ErrorHandlingTest.kt index 87af3f1..e453d81 100644 --- a/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/ErrorHandlingTest.kt +++ b/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/ErrorHandlingTest.kt @@ -77,7 +77,7 @@ internal class ErrorHandlingTest { SessionStartParams.builder() .xLanguage(SessionStartParams.XLanguage.TYPESCRIPT) .xSdkVersion("3.0.6") - .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00Z")) .xStreamResponse(SessionStartParams.XStreamResponse.TRUE) .modelName("gpt-4o") .actTimeoutMs(30000.0) @@ -230,7 +230,7 @@ internal class ErrorHandlingTest { .experimental(true) .selfHeal(true) .systemPrompt("systemPrompt") - .verbose(SessionStartParams.Verbose._1) + .verbose(1L) .waitForCaptchaSolves(true) .build() ) @@ -257,7 +257,7 @@ internal class ErrorHandlingTest { SessionStartParams.builder() .xLanguage(SessionStartParams.XLanguage.TYPESCRIPT) .xSdkVersion("3.0.6") - .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00Z")) .xStreamResponse(SessionStartParams.XStreamResponse.TRUE) .modelName("gpt-4o") .actTimeoutMs(30000.0) @@ -410,7 +410,7 @@ internal class ErrorHandlingTest { .experimental(true) .selfHeal(true) .systemPrompt("systemPrompt") - .verbose(SessionStartParams.Verbose._1) + .verbose(1L) .waitForCaptchaSolves(true) .build() ) @@ -437,7 +437,7 @@ internal class ErrorHandlingTest { SessionStartParams.builder() .xLanguage(SessionStartParams.XLanguage.TYPESCRIPT) .xSdkVersion("3.0.6") - .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00Z")) .xStreamResponse(SessionStartParams.XStreamResponse.TRUE) .modelName("gpt-4o") .actTimeoutMs(30000.0) @@ -590,7 +590,7 @@ internal class ErrorHandlingTest { .experimental(true) .selfHeal(true) .systemPrompt("systemPrompt") - .verbose(SessionStartParams.Verbose._1) + .verbose(1L) .waitForCaptchaSolves(true) .build() ) @@ -617,7 +617,7 @@ internal class ErrorHandlingTest { SessionStartParams.builder() .xLanguage(SessionStartParams.XLanguage.TYPESCRIPT) .xSdkVersion("3.0.6") - .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00Z")) .xStreamResponse(SessionStartParams.XStreamResponse.TRUE) .modelName("gpt-4o") .actTimeoutMs(30000.0) @@ -770,7 +770,7 @@ internal class ErrorHandlingTest { .experimental(true) .selfHeal(true) .systemPrompt("systemPrompt") - .verbose(SessionStartParams.Verbose._1) + .verbose(1L) .waitForCaptchaSolves(true) .build() ) @@ -797,7 +797,7 @@ internal class ErrorHandlingTest { SessionStartParams.builder() .xLanguage(SessionStartParams.XLanguage.TYPESCRIPT) .xSdkVersion("3.0.6") - .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00Z")) .xStreamResponse(SessionStartParams.XStreamResponse.TRUE) .modelName("gpt-4o") .actTimeoutMs(30000.0) @@ -950,7 +950,7 @@ internal class ErrorHandlingTest { .experimental(true) .selfHeal(true) .systemPrompt("systemPrompt") - .verbose(SessionStartParams.Verbose._1) + .verbose(1L) .waitForCaptchaSolves(true) .build() ) @@ -977,7 +977,7 @@ internal class ErrorHandlingTest { SessionStartParams.builder() .xLanguage(SessionStartParams.XLanguage.TYPESCRIPT) .xSdkVersion("3.0.6") - .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00Z")) .xStreamResponse(SessionStartParams.XStreamResponse.TRUE) .modelName("gpt-4o") .actTimeoutMs(30000.0) @@ -1130,7 +1130,7 @@ internal class ErrorHandlingTest { .experimental(true) .selfHeal(true) .systemPrompt("systemPrompt") - .verbose(SessionStartParams.Verbose._1) + .verbose(1L) .waitForCaptchaSolves(true) .build() ) @@ -1157,7 +1157,7 @@ internal class ErrorHandlingTest { SessionStartParams.builder() .xLanguage(SessionStartParams.XLanguage.TYPESCRIPT) .xSdkVersion("3.0.6") - .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00Z")) .xStreamResponse(SessionStartParams.XStreamResponse.TRUE) .modelName("gpt-4o") .actTimeoutMs(30000.0) @@ -1310,7 +1310,7 @@ internal class ErrorHandlingTest { .experimental(true) .selfHeal(true) .systemPrompt("systemPrompt") - .verbose(SessionStartParams.Verbose._1) + .verbose(1L) .waitForCaptchaSolves(true) .build() ) @@ -1337,7 +1337,7 @@ internal class ErrorHandlingTest { SessionStartParams.builder() .xLanguage(SessionStartParams.XLanguage.TYPESCRIPT) .xSdkVersion("3.0.6") - .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00Z")) .xStreamResponse(SessionStartParams.XStreamResponse.TRUE) .modelName("gpt-4o") .actTimeoutMs(30000.0) @@ -1490,7 +1490,7 @@ internal class ErrorHandlingTest { .experimental(true) .selfHeal(true) .systemPrompt("systemPrompt") - .verbose(SessionStartParams.Verbose._1) + .verbose(1L) .waitForCaptchaSolves(true) .build() ) @@ -1517,7 +1517,7 @@ internal class ErrorHandlingTest { SessionStartParams.builder() .xLanguage(SessionStartParams.XLanguage.TYPESCRIPT) .xSdkVersion("3.0.6") - .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00Z")) .xStreamResponse(SessionStartParams.XStreamResponse.TRUE) .modelName("gpt-4o") .actTimeoutMs(30000.0) @@ -1670,7 +1670,7 @@ internal class ErrorHandlingTest { .experimental(true) .selfHeal(true) .systemPrompt("systemPrompt") - .verbose(SessionStartParams.Verbose._1) + .verbose(1L) .waitForCaptchaSolves(true) .build() ) @@ -1697,7 +1697,7 @@ internal class ErrorHandlingTest { SessionStartParams.builder() .xLanguage(SessionStartParams.XLanguage.TYPESCRIPT) .xSdkVersion("3.0.6") - .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00Z")) .xStreamResponse(SessionStartParams.XStreamResponse.TRUE) .modelName("gpt-4o") .actTimeoutMs(30000.0) @@ -1850,7 +1850,7 @@ internal class ErrorHandlingTest { .experimental(true) .selfHeal(true) .systemPrompt("systemPrompt") - .verbose(SessionStartParams.Verbose._1) + .verbose(1L) .waitForCaptchaSolves(true) .build() ) @@ -1877,7 +1877,7 @@ internal class ErrorHandlingTest { SessionStartParams.builder() .xLanguage(SessionStartParams.XLanguage.TYPESCRIPT) .xSdkVersion("3.0.6") - .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00Z")) .xStreamResponse(SessionStartParams.XStreamResponse.TRUE) .modelName("gpt-4o") .actTimeoutMs(30000.0) @@ -2030,7 +2030,7 @@ internal class ErrorHandlingTest { .experimental(true) .selfHeal(true) .systemPrompt("systemPrompt") - .verbose(SessionStartParams.Verbose._1) + .verbose(1L) .waitForCaptchaSolves(true) .build() ) @@ -2057,7 +2057,7 @@ internal class ErrorHandlingTest { SessionStartParams.builder() .xLanguage(SessionStartParams.XLanguage.TYPESCRIPT) .xSdkVersion("3.0.6") - .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00Z")) .xStreamResponse(SessionStartParams.XStreamResponse.TRUE) .modelName("gpt-4o") .actTimeoutMs(30000.0) @@ -2210,7 +2210,7 @@ internal class ErrorHandlingTest { .experimental(true) .selfHeal(true) .systemPrompt("systemPrompt") - .verbose(SessionStartParams.Verbose._1) + .verbose(1L) .waitForCaptchaSolves(true) .build() ) @@ -2237,7 +2237,7 @@ internal class ErrorHandlingTest { SessionStartParams.builder() .xLanguage(SessionStartParams.XLanguage.TYPESCRIPT) .xSdkVersion("3.0.6") - .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00Z")) .xStreamResponse(SessionStartParams.XStreamResponse.TRUE) .modelName("gpt-4o") .actTimeoutMs(30000.0) @@ -2390,7 +2390,7 @@ internal class ErrorHandlingTest { .experimental(true) .selfHeal(true) .systemPrompt("systemPrompt") - .verbose(SessionStartParams.Verbose._1) + .verbose(1L) .waitForCaptchaSolves(true) .build() ) @@ -2417,7 +2417,7 @@ internal class ErrorHandlingTest { SessionStartParams.builder() .xLanguage(SessionStartParams.XLanguage.TYPESCRIPT) .xSdkVersion("3.0.6") - .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00Z")) .xStreamResponse(SessionStartParams.XStreamResponse.TRUE) .modelName("gpt-4o") .actTimeoutMs(30000.0) @@ -2570,7 +2570,7 @@ internal class ErrorHandlingTest { .experimental(true) .selfHeal(true) .systemPrompt("systemPrompt") - .verbose(SessionStartParams.Verbose._1) + .verbose(1L) .waitForCaptchaSolves(true) .build() ) @@ -2597,7 +2597,7 @@ internal class ErrorHandlingTest { SessionStartParams.builder() .xLanguage(SessionStartParams.XLanguage.TYPESCRIPT) .xSdkVersion("3.0.6") - .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00Z")) .xStreamResponse(SessionStartParams.XStreamResponse.TRUE) .modelName("gpt-4o") .actTimeoutMs(30000.0) @@ -2750,7 +2750,7 @@ internal class ErrorHandlingTest { .experimental(true) .selfHeal(true) .systemPrompt("systemPrompt") - .verbose(SessionStartParams.Verbose._1) + .verbose(1L) .waitForCaptchaSolves(true) .build() ) @@ -2777,7 +2777,7 @@ internal class ErrorHandlingTest { SessionStartParams.builder() .xLanguage(SessionStartParams.XLanguage.TYPESCRIPT) .xSdkVersion("3.0.6") - .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00Z")) .xStreamResponse(SessionStartParams.XStreamResponse.TRUE) .modelName("gpt-4o") .actTimeoutMs(30000.0) @@ -2930,7 +2930,7 @@ internal class ErrorHandlingTest { .experimental(true) .selfHeal(true) .systemPrompt("systemPrompt") - .verbose(SessionStartParams.Verbose._1) + .verbose(1L) .waitForCaptchaSolves(true) .build() ) @@ -2955,7 +2955,7 @@ internal class ErrorHandlingTest { SessionStartParams.builder() .xLanguage(SessionStartParams.XLanguage.TYPESCRIPT) .xSdkVersion("3.0.6") - .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00Z")) .xStreamResponse(SessionStartParams.XStreamResponse.TRUE) .modelName("gpt-4o") .actTimeoutMs(30000.0) @@ -3108,7 +3108,7 @@ internal class ErrorHandlingTest { .experimental(true) .selfHeal(true) .systemPrompt("systemPrompt") - .verbose(SessionStartParams.Verbose._1) + .verbose(1L) .waitForCaptchaSolves(true) .build() ) diff --git a/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/ServiceParamsTest.kt b/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/ServiceParamsTest.kt index a50efce..0cdc99d 100644 --- a/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/ServiceParamsTest.kt +++ b/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/ServiceParamsTest.kt @@ -50,7 +50,7 @@ internal class ServiceParamsTest { SessionStartParams.builder() .xLanguage(SessionStartParams.XLanguage.TYPESCRIPT) .xSdkVersion("3.0.6") - .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00Z")) .xStreamResponse(SessionStartParams.XStreamResponse.TRUE) .modelName("gpt-4o") .actTimeoutMs(30000.0) @@ -192,7 +192,7 @@ internal class ServiceParamsTest { .experimental(true) .selfHeal(true) .systemPrompt("systemPrompt") - .verbose(SessionStartParams.Verbose._1) + .verbose(1L) .waitForCaptchaSolves(true) .putAdditionalHeader("Secret-Header", "42") .putAdditionalQueryParam("secret_query_param", "42") @@ -219,7 +219,7 @@ internal class ServiceParamsTest { .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") .xLanguage(SessionActParams.XLanguage.TYPESCRIPT) .xSdkVersion("3.0.6") - .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00Z")) .xStreamResponse(SessionActParams.XStreamResponse.TRUE) .input("Click the login button") .frameId("frameId") diff --git a/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/async/SessionServiceAsyncTest.kt b/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/async/SessionServiceAsyncTest.kt index 8abcbcb..270a06b 100644 --- a/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/async/SessionServiceAsyncTest.kt +++ b/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/async/SessionServiceAsyncTest.kt @@ -38,7 +38,7 @@ internal class SessionServiceAsyncTest { .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") .xLanguage(SessionActParams.XLanguage.TYPESCRIPT) .xSdkVersion("3.0.6") - .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00Z")) .xStreamResponse(SessionActParams.XStreamResponse.TRUE) .input("Click the login button") .frameId("frameId") @@ -78,7 +78,7 @@ internal class SessionServiceAsyncTest { .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") .xLanguage(SessionEndParams.XLanguage.TYPESCRIPT) .xSdkVersion("3.0.6") - .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00Z")) .xStreamResponse(SessionEndParams.XStreamResponse.TRUE) .build() ) @@ -105,7 +105,7 @@ internal class SessionServiceAsyncTest { .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") .xLanguage(SessionExecuteParams.XLanguage.TYPESCRIPT) .xSdkVersion("3.0.6") - .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00Z")) .xStreamResponse(SessionExecuteParams.XStreamResponse.TRUE) .agentConfig( SessionExecuteParams.AgentConfig.builder() @@ -149,7 +149,7 @@ internal class SessionServiceAsyncTest { .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") .xLanguage(SessionExtractParams.XLanguage.TYPESCRIPT) .xSdkVersion("3.0.6") - .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00Z")) .xStreamResponse(SessionExtractParams.XStreamResponse.TRUE) .frameId("frameId") .instruction("Extract all product names and prices from the page") @@ -190,7 +190,7 @@ internal class SessionServiceAsyncTest { .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") .xLanguage(SessionNavigateParams.XLanguage.TYPESCRIPT) .xSdkVersion("3.0.6") - .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00Z")) .xStreamResponse(SessionNavigateParams.XStreamResponse.TRUE) .url("https://example.com") .frameId("frameId") @@ -226,7 +226,7 @@ internal class SessionServiceAsyncTest { .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") .xLanguage(SessionObserveParams.XLanguage.TYPESCRIPT) .xSdkVersion("3.0.6") - .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00Z")) .xStreamResponse(SessionObserveParams.XStreamResponse.TRUE) .frameId("frameId") .instruction("Find all clickable navigation links") @@ -261,7 +261,7 @@ internal class SessionServiceAsyncTest { SessionStartParams.builder() .xLanguage(SessionStartParams.XLanguage.TYPESCRIPT) .xSdkVersion("3.0.6") - .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00Z")) .xStreamResponse(SessionStartParams.XStreamResponse.TRUE) .modelName("gpt-4o") .actTimeoutMs(30000.0) @@ -406,7 +406,7 @@ internal class SessionServiceAsyncTest { .experimental(true) .selfHeal(true) .systemPrompt("systemPrompt") - .verbose(SessionStartParams.Verbose._1) + .verbose(1L) .waitForCaptchaSolves(true) .build() ) diff --git a/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/blocking/SessionServiceTest.kt b/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/blocking/SessionServiceTest.kt index 937b3ea..af06455 100644 --- a/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/blocking/SessionServiceTest.kt +++ b/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/blocking/SessionServiceTest.kt @@ -38,7 +38,7 @@ internal class SessionServiceTest { .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") .xLanguage(SessionActParams.XLanguage.TYPESCRIPT) .xSdkVersion("3.0.6") - .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00Z")) .xStreamResponse(SessionActParams.XStreamResponse.TRUE) .input("Click the login button") .frameId("frameId") @@ -77,7 +77,7 @@ internal class SessionServiceTest { .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") .xLanguage(SessionEndParams.XLanguage.TYPESCRIPT) .xSdkVersion("3.0.6") - .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00Z")) .xStreamResponse(SessionEndParams.XStreamResponse.TRUE) .build() ) @@ -103,7 +103,7 @@ internal class SessionServiceTest { .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") .xLanguage(SessionExecuteParams.XLanguage.TYPESCRIPT) .xSdkVersion("3.0.6") - .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00Z")) .xStreamResponse(SessionExecuteParams.XStreamResponse.TRUE) .agentConfig( SessionExecuteParams.AgentConfig.builder() @@ -146,7 +146,7 @@ internal class SessionServiceTest { .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") .xLanguage(SessionExtractParams.XLanguage.TYPESCRIPT) .xSdkVersion("3.0.6") - .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00Z")) .xStreamResponse(SessionExtractParams.XStreamResponse.TRUE) .frameId("frameId") .instruction("Extract all product names and prices from the page") @@ -186,7 +186,7 @@ internal class SessionServiceTest { .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") .xLanguage(SessionNavigateParams.XLanguage.TYPESCRIPT) .xSdkVersion("3.0.6") - .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00Z")) .xStreamResponse(SessionNavigateParams.XStreamResponse.TRUE) .url("https://example.com") .frameId("frameId") @@ -221,7 +221,7 @@ internal class SessionServiceTest { .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") .xLanguage(SessionObserveParams.XLanguage.TYPESCRIPT) .xSdkVersion("3.0.6") - .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00Z")) .xStreamResponse(SessionObserveParams.XStreamResponse.TRUE) .frameId("frameId") .instruction("Find all clickable navigation links") @@ -255,7 +255,7 @@ internal class SessionServiceTest { SessionStartParams.builder() .xLanguage(SessionStartParams.XLanguage.TYPESCRIPT) .xSdkVersion("3.0.6") - .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00.000Z")) + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00Z")) .xStreamResponse(SessionStartParams.XStreamResponse.TRUE) .modelName("gpt-4o") .actTimeoutMs(30000.0) @@ -400,7 +400,7 @@ internal class SessionServiceTest { .experimental(true) .selfHeal(true) .systemPrompt("systemPrompt") - .verbose(SessionStartParams.Verbose._1) + .verbose(1L) .waitForCaptchaSolves(true) .build() ) From b6bdf1a26a45556dcfee59b088983cd7e7839f43 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 18 Dec 2025 01:38:54 +0000 Subject: [PATCH 12/18] feat(api): manual updates --- .stats.yml | 6 +- README.md | 2 + .../client/okhttp/StagehandOkHttpClient.kt | 13 + .../okhttp/StagehandOkHttpClientAsync.kt | 13 + .../com/browserbase/api/core/ClientOptions.kt | 50 + .../api/core/handlers/SseHandler.kt | 137 ++ .../api/core/handlers/StreamHandler.kt | 102 ++ .../browserbase/api/core/http/SseMessage.kt | 74 ++ .../browserbase/api/errors/SseException.kt | 91 ++ .../api/models/sessions/SessionActParams.kt | 326 +---- .../models/sessions/SessionNavigateParams.kt | 81 +- .../models/sessions/SessionStartResponse.kt | 51 +- .../api/models/sessions/StreamEvent.kt | 1175 +++++++++++++++++ .../api/services/async/SessionServiceAsync.kt | 291 ++++ .../services/async/SessionServiceAsyncImpl.kt | 228 ++++ .../api/services/blocking/SessionService.kt | 294 +++++ .../services/blocking/SessionServiceImpl.kt | 202 +++ .../api/core/handlers/SseHandlerTest.kt | 134 ++ .../api/core/handlers/StreamHandlerTest.kt | 94 ++ .../sessions/SessionNavigateParamsTest.kt | 4 + .../sessions/SessionStartResponseTest.kt | 3 + .../api/models/sessions/StreamEventTest.kt | 66 + .../services/async/SessionServiceAsyncTest.kt | 166 +++ .../services/blocking/SessionServiceTest.kt | 166 +++ 24 files changed, 3441 insertions(+), 328 deletions(-) create mode 100644 stagehand-java-core/src/main/kotlin/com/browserbase/api/core/handlers/SseHandler.kt create mode 100644 stagehand-java-core/src/main/kotlin/com/browserbase/api/core/handlers/StreamHandler.kt create mode 100644 stagehand-java-core/src/main/kotlin/com/browserbase/api/core/http/SseMessage.kt create mode 100644 stagehand-java-core/src/main/kotlin/com/browserbase/api/errors/SseException.kt create mode 100644 stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/StreamEvent.kt create mode 100644 stagehand-java-core/src/test/kotlin/com/browserbase/api/core/handlers/SseHandlerTest.kt create mode 100644 stagehand-java-core/src/test/kotlin/com/browserbase/api/core/handlers/StreamHandlerTest.kt create mode 100644 stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/StreamEventTest.kt diff --git a/.stats.yml b/.stats.yml index 604325f..5dba58c 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-e96507dd78e76fccc77ba7fb09704da127ead6f4d73ea854e9b2150e90787ff4.yml -openapi_spec_hash: 0c2548b8fdd6de6789b19123e69609c1 -config_hash: c3abb41dbe698d59b3bf12f393013d54 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/browserbase%2Fstagehand-f7d6b6489159f611a2bfdc267ce0a6fc0455bed1ffa0c310044baaa5d8381b9b.yml +openapi_spec_hash: cd88d8068abfde8382da0bed674e440c +config_hash: 5c69fb596588b8ace08203858518c149 diff --git a/README.md b/README.md index 3c37038..be1932d 100644 --- a/README.md +++ b/README.md @@ -236,6 +236,8 @@ The SDK throws custom unchecked exception types: | 5xx | [`InternalServerException`](stagehand-java-core/src/main/kotlin/com/browserbase/api/errors/InternalServerException.kt) | | others | [`UnexpectedStatusCodeException`](stagehand-java-core/src/main/kotlin/com/browserbase/api/errors/UnexpectedStatusCodeException.kt) | + [`SseException`](stagehand-java-core/src/main/kotlin/com/browserbase/api/errors/SseException.kt) is thrown for errors encountered during [SSE streaming](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events) after a successful initial HTTP response. + - [`StagehandIoException`](stagehand-java-core/src/main/kotlin/com/browserbase/api/errors/StagehandIoException.kt): I/O networking errors. - [`StagehandRetryableException`](stagehand-java-core/src/main/kotlin/com/browserbase/api/errors/StagehandRetryableException.kt): Generic error indicating a failure that could be retried by the client. diff --git a/stagehand-java-client-okhttp/src/main/kotlin/com/browserbase/api/client/okhttp/StagehandOkHttpClient.kt b/stagehand-java-client-okhttp/src/main/kotlin/com/browserbase/api/client/okhttp/StagehandOkHttpClient.kt index 8955635..40010ee 100644 --- a/stagehand-java-client-okhttp/src/main/kotlin/com/browserbase/api/client/okhttp/StagehandOkHttpClient.kt +++ b/stagehand-java-client-okhttp/src/main/kotlin/com/browserbase/api/client/okhttp/StagehandOkHttpClient.kt @@ -7,6 +7,7 @@ import com.browserbase.api.client.StagehandClientImpl import com.browserbase.api.core.ClientOptions import com.browserbase.api.core.Sleeper import com.browserbase.api.core.Timeout +import com.browserbase.api.core.http.AsyncStreamResponse import com.browserbase.api.core.http.Headers import com.browserbase.api.core.http.HttpClient import com.browserbase.api.core.http.QueryParams @@ -16,6 +17,7 @@ import java.net.Proxy import java.time.Clock import java.time.Duration import java.util.Optional +import java.util.concurrent.Executor import javax.net.ssl.HostnameVerifier import javax.net.ssl.SSLSocketFactory import javax.net.ssl.X509TrustManager @@ -121,6 +123,17 @@ class StagehandOkHttpClient private constructor() { */ fun jsonMapper(jsonMapper: JsonMapper) = apply { clientOptions.jsonMapper(jsonMapper) } + /** + * The executor to use for running [AsyncStreamResponse.Handler] callbacks. + * + * Defaults to a dedicated cached thread pool. + * + * This class takes ownership of the executor and shuts it down, if possible, when closed. + */ + fun streamHandlerExecutor(streamHandlerExecutor: Executor) = apply { + clientOptions.streamHandlerExecutor(streamHandlerExecutor) + } + /** * The interface to use for delaying execution, like during retries. * diff --git a/stagehand-java-client-okhttp/src/main/kotlin/com/browserbase/api/client/okhttp/StagehandOkHttpClientAsync.kt b/stagehand-java-client-okhttp/src/main/kotlin/com/browserbase/api/client/okhttp/StagehandOkHttpClientAsync.kt index 2cb208d..33ce68f 100644 --- a/stagehand-java-client-okhttp/src/main/kotlin/com/browserbase/api/client/okhttp/StagehandOkHttpClientAsync.kt +++ b/stagehand-java-client-okhttp/src/main/kotlin/com/browserbase/api/client/okhttp/StagehandOkHttpClientAsync.kt @@ -7,6 +7,7 @@ import com.browserbase.api.client.StagehandClientAsyncImpl import com.browserbase.api.core.ClientOptions import com.browserbase.api.core.Sleeper import com.browserbase.api.core.Timeout +import com.browserbase.api.core.http.AsyncStreamResponse import com.browserbase.api.core.http.Headers import com.browserbase.api.core.http.HttpClient import com.browserbase.api.core.http.QueryParams @@ -16,6 +17,7 @@ import java.net.Proxy import java.time.Clock import java.time.Duration import java.util.Optional +import java.util.concurrent.Executor import javax.net.ssl.HostnameVerifier import javax.net.ssl.SSLSocketFactory import javax.net.ssl.X509TrustManager @@ -121,6 +123,17 @@ class StagehandOkHttpClientAsync private constructor() { */ fun jsonMapper(jsonMapper: JsonMapper) = apply { clientOptions.jsonMapper(jsonMapper) } + /** + * The executor to use for running [AsyncStreamResponse.Handler] callbacks. + * + * Defaults to a dedicated cached thread pool. + * + * This class takes ownership of the executor and shuts it down, if possible, when closed. + */ + fun streamHandlerExecutor(streamHandlerExecutor: Executor) = apply { + clientOptions.streamHandlerExecutor(streamHandlerExecutor) + } + /** * The interface to use for delaying execution, like during retries. * diff --git a/stagehand-java-core/src/main/kotlin/com/browserbase/api/core/ClientOptions.kt b/stagehand-java-core/src/main/kotlin/com/browserbase/api/core/ClientOptions.kt index 8692cb0..2da3f9a 100644 --- a/stagehand-java-core/src/main/kotlin/com/browserbase/api/core/ClientOptions.kt +++ b/stagehand-java-core/src/main/kotlin/com/browserbase/api/core/ClientOptions.kt @@ -2,6 +2,7 @@ package com.browserbase.api.core +import com.browserbase.api.core.http.AsyncStreamResponse import com.browserbase.api.core.http.Headers import com.browserbase.api.core.http.HttpClient import com.browserbase.api.core.http.PhantomReachableClosingHttpClient @@ -11,6 +12,11 @@ import com.fasterxml.jackson.databind.json.JsonMapper import java.time.Clock import java.time.Duration import java.util.Optional +import java.util.concurrent.Executor +import java.util.concurrent.ExecutorService +import java.util.concurrent.Executors +import java.util.concurrent.ThreadFactory +import java.util.concurrent.atomic.AtomicLong import kotlin.jvm.optionals.getOrNull /** A class representing the SDK client configuration. */ @@ -40,6 +46,14 @@ private constructor( * rarely needs to be overridden. */ @get:JvmName("jsonMapper") val jsonMapper: JsonMapper, + /** + * The executor to use for running [AsyncStreamResponse.Handler] callbacks. + * + * Defaults to a dedicated cached thread pool. + * + * This class takes ownership of the executor and shuts it down, if possible, when closed. + */ + @get:JvmName("streamHandlerExecutor") val streamHandlerExecutor: Executor, /** * The interface to use for delaying execution, like during retries. * @@ -147,6 +161,7 @@ private constructor( private var httpClient: HttpClient? = null private var checkJacksonVersionCompatibility: Boolean = true private var jsonMapper: JsonMapper = jsonMapper() + private var streamHandlerExecutor: Executor? = null private var sleeper: Sleeper? = null private var clock: Clock = Clock.systemUTC() private var baseUrl: String? = null @@ -164,6 +179,7 @@ private constructor( httpClient = clientOptions.originalHttpClient checkJacksonVersionCompatibility = clientOptions.checkJacksonVersionCompatibility jsonMapper = clientOptions.jsonMapper + streamHandlerExecutor = clientOptions.streamHandlerExecutor sleeper = clientOptions.sleeper clock = clientOptions.clock baseUrl = clientOptions.baseUrl @@ -207,6 +223,20 @@ private constructor( */ fun jsonMapper(jsonMapper: JsonMapper) = apply { this.jsonMapper = jsonMapper } + /** + * The executor to use for running [AsyncStreamResponse.Handler] callbacks. + * + * Defaults to a dedicated cached thread pool. + * + * This class takes ownership of the executor and shuts it down, if possible, when closed. + */ + fun streamHandlerExecutor(streamHandlerExecutor: Executor) = apply { + this.streamHandlerExecutor = + if (streamHandlerExecutor is ExecutorService) + PhantomReachableExecutorService(streamHandlerExecutor) + else streamHandlerExecutor + } + /** * The interface to use for delaying execution, like during retries. * @@ -422,6 +452,24 @@ private constructor( */ fun build(): ClientOptions { val httpClient = checkRequired("httpClient", httpClient) + val streamHandlerExecutor = + streamHandlerExecutor + ?: PhantomReachableExecutorService( + Executors.newCachedThreadPool( + object : ThreadFactory { + + private val threadFactory: ThreadFactory = + Executors.defaultThreadFactory() + private val count = AtomicLong(0) + + override fun newThread(runnable: Runnable): Thread = + threadFactory.newThread(runnable).also { + it.name = + "stagehand-stream-handler-thread-${count.getAndIncrement()}" + } + } + ) + ) val sleeper = sleeper ?: PhantomReachableSleeper(DefaultSleeper()) val browserbaseApiKey = checkRequired("browserbaseApiKey", browserbaseApiKey) val browserbaseProjectId = checkRequired("browserbaseProjectId", browserbaseProjectId) @@ -464,6 +512,7 @@ private constructor( .build(), checkJacksonVersionCompatibility, jsonMapper, + streamHandlerExecutor, sleeper, clock, baseUrl, @@ -491,6 +540,7 @@ private constructor( */ fun close() { httpClient.close() + (streamHandlerExecutor as? ExecutorService)?.shutdown() sleeper.close() } } diff --git a/stagehand-java-core/src/main/kotlin/com/browserbase/api/core/handlers/SseHandler.kt b/stagehand-java-core/src/main/kotlin/com/browserbase/api/core/handlers/SseHandler.kt new file mode 100644 index 0000000..039faae --- /dev/null +++ b/stagehand-java-core/src/main/kotlin/com/browserbase/api/core/handlers/SseHandler.kt @@ -0,0 +1,137 @@ +// File generated from our OpenAPI spec by Stainless. + +@file:JvmName("SseHandler") + +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 + +@JvmSynthetic +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 +} + +@JvmSynthetic +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-java-core/src/main/kotlin/com/browserbase/api/core/handlers/StreamHandler.kt b/stagehand-java-core/src/main/kotlin/com/browserbase/api/core/handlers/StreamHandler.kt new file mode 100644 index 0000000..4cd4f25 --- /dev/null +++ b/stagehand-java-core/src/main/kotlin/com/browserbase/api/core/handlers/StreamHandler.kt @@ -0,0 +1,102 @@ +@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 +import java.util.stream.Stream +import kotlin.streams.asStream + +@JvmSynthetic +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 stream(): Stream = sequence.asStream() + + 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-java-core/src/main/kotlin/com/browserbase/api/core/http/SseMessage.kt b/stagehand-java-core/src/main/kotlin/com/browserbase/api/core/http/SseMessage.kt new file mode 100644 index 0000000..21cc44e --- /dev/null +++ b/stagehand-java-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 { + @JvmStatic 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-java-core/src/main/kotlin/com/browserbase/api/errors/SseException.kt b/stagehand-java-core/src/main/kotlin/com/browserbase/api/errors/SseException.kt new file mode 100644 index 0000000..0dfdd2f --- /dev/null +++ b/stagehand-java-core/src/main/kotlin/com/browserbase/api/errors/SseException.kt @@ -0,0 +1,91 @@ +// 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 +import java.util.Optional +import kotlin.jvm.optionals.getOrNull + +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: + * ```java + * .statusCode() + * .headers() + * .body() + * ``` + */ + @JvmStatic 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 + + @JvmSynthetic + 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 } + + /** Alias for calling [Builder.cause] with `cause.orElse(null)`. */ + fun cause(cause: Optional) = cause(cause.getOrNull()) + + /** + * Returns an immutable instance of [SseException]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .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-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionActParams.kt b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionActParams.kt index 019f026..a37780c 100644 --- a/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionActParams.kt +++ b/stagehand-java-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 @@ -213,7 +212,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) } @@ -515,7 +514,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)) @@ -641,14 +640,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(): Optional = Optional.ofNullable(string) /** Action object returned by observe and used by act */ - fun action(): Optional = Optional.ofNullable(action) + fun action(): Optional = Optional.ofNullable(action) fun isString(): Boolean = string != null @@ -657,7 +656,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(): Optional = Optional.ofNullable(_json) @@ -679,7 +678,7 @@ private constructor( object : Visitor { override fun visitString(string: String) {} - override fun visitAction(action: ActionInput) { + override fun visitAction(action: Action) { action.validate() } } @@ -707,7 +706,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 } @@ -736,7 +735,7 @@ private constructor( @JvmStatic fun ofString(string: String) = Input(string = string) /** Action object returned by observe and used by act */ - @JvmStatic fun ofAction(action: ActionInput) = Input(action = action) + @JvmStatic fun ofAction(action: Action) = Input(action = action) } /** An interface that defines how to map each variant of [Input] to a value of type [T]. */ @@ -745,7 +744,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]. @@ -769,7 +768,7 @@ private constructor( val bestMatches = sequenceOf( - tryDeserialize(node, jacksonTypeRef())?.let { + tryDeserialize(node, jacksonTypeRef())?.let { Input(action = it, _json = json) }, tryDeserialize(node, jacksonTypeRef())?.let { @@ -807,311 +806,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(): Optional> = arguments.getOptional("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(): Optional = method.getOptional("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: - * ```java - * .description() - * .selector() - * ``` - */ - @JvmStatic 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() - - @JvmSynthetic - 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: - * ```java - * .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. - */ - @JvmSynthetic - internal fun validity(): Int = - (if (description.asKnown().isPresent) 1 else 0) + - (if (selector.asKnown().isPresent) 1 else 0) + - (arguments.asKnown().getOrNull()?.size ?: 0) + - (if (method.asKnown().isPresent) 1 else 0) - - 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 diff --git a/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionNavigateParams.kt b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionNavigateParams.kt index b07cf2c..112be92 100644 --- a/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionNavigateParams.kt +++ b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionNavigateParams.kt @@ -73,6 +73,14 @@ private constructor( */ fun options(): Optional = 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(): Optional = body.streamResponse() + /** * Returns the raw JSON value of [url]. * @@ -94,6 +102,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. */ @@ -182,6 +197,7 @@ private constructor( * - [url] * - [frameId] * - [options] + * - [streamResponse] */ fun body(body: Body) = apply { this.body = body.toBuilder() } @@ -217,6 +233,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) } @@ -386,6 +416,7 @@ private constructor( private val url: JsonField, private val frameId: JsonField, private val options: JsonField, + private val streamResponse: JsonField, private val additionalProperties: MutableMap, ) { @@ -394,7 +425,10 @@ private constructor( @JsonProperty("url") @ExcludeMissing url: JsonField = JsonMissing.of(), @JsonProperty("frameId") @ExcludeMissing frameId: JsonField = JsonMissing.of(), @JsonProperty("options") @ExcludeMissing options: JsonField = JsonMissing.of(), - ) : this(url, frameId, options, mutableMapOf()) + @JsonProperty("streamResponse") + @ExcludeMissing + streamResponse: JsonField = JsonMissing.of(), + ) : this(url, frameId, options, streamResponse, mutableMapOf()) /** * URL to navigate to @@ -418,6 +452,14 @@ private constructor( */ fun options(): Optional = options.getOptional("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(): Optional = streamResponse.getOptional("streamResponse") + /** * Returns the raw JSON value of [url]. * @@ -439,6 +481,16 @@ private constructor( */ @JsonProperty("options") @ExcludeMissing fun _options(): JsonField = options + /** + * Returns the raw JSON value of [streamResponse]. + * + * Unlike [streamResponse], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("streamResponse") + @ExcludeMissing + fun _streamResponse(): JsonField = streamResponse + @JsonAnySetter private fun putAdditionalProperty(key: String, value: JsonValue) { additionalProperties.put(key, value) @@ -470,6 +522,7 @@ private constructor( private var url: JsonField? = null private var frameId: JsonField = JsonMissing.of() private var options: JsonField = JsonMissing.of() + private var streamResponse: JsonField = JsonMissing.of() private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic @@ -477,6 +530,7 @@ private constructor( url = body.url frameId = body.frameId options = body.options + streamResponse = body.streamResponse additionalProperties = body.additionalProperties.toMutableMap() } @@ -515,6 +569,21 @@ private constructor( */ fun options(options: JsonField) = apply { this.options = options } + /** Whether to stream the response via SSE */ + fun streamResponse(streamResponse: Boolean) = + streamResponse(JsonField.of(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 { + this.streamResponse = streamResponse + } + fun additionalProperties(additionalProperties: Map) = apply { this.additionalProperties.clear() putAllAdditionalProperties(additionalProperties) @@ -551,6 +620,7 @@ private constructor( checkRequired("url", url), frameId, options, + streamResponse, additionalProperties.toMutableMap(), ) } @@ -565,6 +635,7 @@ private constructor( url() frameId() options().ifPresent { it.validate() } + streamResponse() validated = true } @@ -586,7 +657,8 @@ private constructor( internal fun validity(): Int = (if (url.asKnown().isPresent) 1 else 0) + (if (frameId.asKnown().isPresent) 1 else 0) + - (options.asKnown().getOrNull()?.validity() ?: 0) + (options.asKnown().getOrNull()?.validity() ?: 0) + + (if (streamResponse.asKnown().isPresent) 1 else 0) override fun equals(other: Any?): Boolean { if (this === other) { @@ -597,17 +669,18 @@ private constructor( url == other.url && frameId == other.frameId && options == other.options && + streamResponse == other.streamResponse && additionalProperties == other.additionalProperties } private val hashCode: Int by lazy { - Objects.hash(url, frameId, options, additionalProperties) + Objects.hash(url, frameId, options, streamResponse, additionalProperties) } override fun hashCode(): Int = hashCode override fun toString() = - "Body{url=$url, frameId=$frameId, options=$options, additionalProperties=$additionalProperties}" + "Body{url=$url, frameId=$frameId, options=$options, streamResponse=$streamResponse, additionalProperties=$additionalProperties}" } class Options diff --git a/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionStartResponse.kt b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionStartResponse.kt index a172070..13ed630 100644 --- a/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionStartResponse.kt +++ b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionStartResponse.kt @@ -192,6 +192,7 @@ private constructor( @JsonCreator(mode = JsonCreator.Mode.DISABLED) private constructor( private val available: JsonField, + private val connectUrl: JsonField, private val sessionId: JsonField, private val additionalProperties: MutableMap, ) { @@ -201,10 +202,13 @@ private constructor( @JsonProperty("available") @ExcludeMissing available: JsonField = JsonMissing.of(), + @JsonProperty("connectUrl") + @ExcludeMissing + connectUrl: JsonField = JsonMissing.of(), @JsonProperty("sessionId") @ExcludeMissing sessionId: JsonField = JsonMissing.of(), - ) : this(available, sessionId, mutableMapOf()) + ) : this(available, connectUrl, sessionId, mutableMapOf()) /** * @throws StagehandInvalidDataException if the JSON field has an unexpected type or is @@ -213,7 +217,15 @@ private constructor( fun available(): Boolean = available.getRequired("available") /** - * Unique session identifier + * CDP WebSocket URL for connecting to the Browserbase cloud browser + * + * @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 connectUrl(): String = connectUrl.getRequired("connectUrl") + + /** + * Unique Browserbase session identifier * * @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). @@ -227,6 +239,15 @@ private constructor( */ @JsonProperty("available") @ExcludeMissing fun _available(): JsonField = available + /** + * Returns the raw JSON value of [connectUrl]. + * + * Unlike [connectUrl], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("connectUrl") + @ExcludeMissing + fun _connectUrl(): JsonField = connectUrl + /** * Returns the raw JSON value of [sessionId]. * @@ -254,6 +275,7 @@ private constructor( * The following fields are required: * ```java * .available() + * .connectUrl() * .sessionId() * ``` */ @@ -264,12 +286,14 @@ private constructor( class Builder internal constructor() { private var available: JsonField? = null + private var connectUrl: JsonField? = null private var sessionId: JsonField? = null private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic internal fun from(data: Data) = apply { available = data.available + connectUrl = data.connectUrl sessionId = data.sessionId additionalProperties = data.additionalProperties.toMutableMap() } @@ -285,7 +309,19 @@ private constructor( */ fun available(available: JsonField) = apply { this.available = available } - /** Unique session identifier */ + /** CDP WebSocket URL for connecting to the Browserbase cloud browser */ + fun connectUrl(connectUrl: String) = connectUrl(JsonField.of(connectUrl)) + + /** + * Sets [Builder.connectUrl] to an arbitrary JSON value. + * + * You should usually call [Builder.connectUrl] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun connectUrl(connectUrl: JsonField) = apply { this.connectUrl = connectUrl } + + /** Unique Browserbase session identifier */ fun sessionId(sessionId: String) = sessionId(JsonField.of(sessionId)) /** @@ -324,6 +360,7 @@ private constructor( * The following fields are required: * ```java * .available() + * .connectUrl() * .sessionId() * ``` * @@ -332,6 +369,7 @@ private constructor( fun build(): Data = Data( checkRequired("available", available), + checkRequired("connectUrl", connectUrl), checkRequired("sessionId", sessionId), additionalProperties.toMutableMap(), ) @@ -345,6 +383,7 @@ private constructor( } available() + connectUrl() sessionId() validated = true } @@ -366,6 +405,7 @@ private constructor( @JvmSynthetic internal fun validity(): Int = (if (available.asKnown().isPresent) 1 else 0) + + (if (connectUrl.asKnown().isPresent) 1 else 0) + (if (sessionId.asKnown().isPresent) 1 else 0) override fun equals(other: Any?): Boolean { @@ -375,18 +415,19 @@ private constructor( return other is Data && available == other.available && + connectUrl == other.connectUrl && sessionId == other.sessionId && additionalProperties == other.additionalProperties } private val hashCode: Int by lazy { - Objects.hash(available, sessionId, additionalProperties) + Objects.hash(available, connectUrl, sessionId, additionalProperties) } override fun hashCode(): Int = hashCode override fun toString() = - "Data{available=$available, sessionId=$sessionId, additionalProperties=$additionalProperties}" + "Data{available=$available, connectUrl=$connectUrl, sessionId=$sessionId, additionalProperties=$additionalProperties}" } override fun equals(other: Any?): Boolean { diff --git a/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/StreamEvent.kt b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/StreamEvent.kt new file mode 100644 index 0000000..d58dc3b --- /dev/null +++ b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/StreamEvent.kt @@ -0,0 +1,1175 @@ +// File generated from our OpenAPI spec by Stainless. + +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 +import com.browserbase.api.core.JsonValue +import com.browserbase.api.core.allMaxBy +import com.browserbase.api.core.checkRequired +import com.browserbase.api.core.getOrThrow +import com.browserbase.api.errors.StagehandInvalidDataException +import com.fasterxml.jackson.annotation.JsonAnyGetter +import com.fasterxml.jackson.annotation.JsonAnySetter +import com.fasterxml.jackson.annotation.JsonCreator +import com.fasterxml.jackson.annotation.JsonProperty +import com.fasterxml.jackson.core.JsonGenerator +import com.fasterxml.jackson.core.ObjectCodec +import com.fasterxml.jackson.databind.JsonNode +import com.fasterxml.jackson.databind.SerializerProvider +import com.fasterxml.jackson.databind.annotation.JsonDeserialize +import com.fasterxml.jackson.databind.annotation.JsonSerialize +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import java.util.Collections +import java.util.Objects +import java.util.Optional +import kotlin.jvm.optionals.getOrNull + +/** Server-Sent Event emitted during streaming responses. Events are sent as `data: \n\n`. */ +class StreamEvent +@JsonCreator(mode = JsonCreator.Mode.DISABLED) +private constructor( + private val id: JsonField, + private val data: JsonField, + private val type: JsonField, + private val additionalProperties: MutableMap, +) { + + @JsonCreator + private constructor( + @JsonProperty("id") @ExcludeMissing id: JsonField = JsonMissing.of(), + @JsonProperty("data") @ExcludeMissing data: JsonField = JsonMissing.of(), + @JsonProperty("type") @ExcludeMissing type: JsonField = JsonMissing.of(), + ) : this(id, data, type, mutableMapOf()) + + /** + * Unique identifier for this event + * + * @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 id(): String = id.getRequired("id") + + /** + * @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 data(): Data = data.getRequired("data") + + /** + * Type of stream event - system events or log messages + * + * @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 type(): Type = type.getRequired("type") + + /** + * Returns the raw JSON value of [id]. + * + * Unlike [id], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("id") @ExcludeMissing fun _id(): JsonField = id + + /** + * Returns the raw JSON value of [data]. + * + * Unlike [data], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("data") @ExcludeMissing fun _data(): JsonField = data + + /** + * Returns the raw JSON value of [type]. + * + * Unlike [type], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("type") @ExcludeMissing fun _type(): JsonField = type + + @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 [StreamEvent]. + * + * The following fields are required: + * ```java + * .id() + * .data() + * .type() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [StreamEvent]. */ + class Builder internal constructor() { + + private var id: JsonField? = null + private var data: JsonField? = null + private var type: JsonField? = null + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(streamEvent: StreamEvent) = apply { + id = streamEvent.id + data = streamEvent.data + type = streamEvent.type + additionalProperties = streamEvent.additionalProperties.toMutableMap() + } + + /** Unique identifier for this event */ + fun id(id: String) = id(JsonField.of(id)) + + /** + * Sets [Builder.id] to an arbitrary JSON value. + * + * You should usually call [Builder.id] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun id(id: JsonField) = apply { this.id = id } + + fun data(data: Data) = data(JsonField.of(data)) + + /** + * Sets [Builder.data] to an arbitrary JSON value. + * + * You should usually call [Builder.data] with a well-typed [Data] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun data(data: JsonField) = apply { this.data = data } + + /** + * Alias for calling [data] with + * `Data.ofStreamEventSystemDataOutput(streamEventSystemDataOutput)`. + */ + fun data(streamEventSystemDataOutput: Data.StreamEventSystemDataOutput) = + data(Data.ofStreamEventSystemDataOutput(streamEventSystemDataOutput)) + + /** + * Alias for calling [data] with + * `Data.ofStreamEventLogDataOutput(streamEventLogDataOutput)`. + */ + fun data(streamEventLogDataOutput: Data.StreamEventLogDataOutput) = + data(Data.ofStreamEventLogDataOutput(streamEventLogDataOutput)) + + /** Type of stream event - system events or log messages */ + fun type(type: Type) = type(JsonField.of(type)) + + /** + * Sets [Builder.type] to an arbitrary JSON value. + * + * You should usually call [Builder.type] with a well-typed [Type] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun type(type: JsonField) = apply { this.type = type } + + 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 [StreamEvent]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .id() + * .data() + * .type() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): StreamEvent = + StreamEvent( + checkRequired("id", id), + checkRequired("data", data), + checkRequired("type", type), + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): StreamEvent = apply { + if (validated) { + return@apply + } + + id() + data().validate() + type().validate() + 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. + */ + @JvmSynthetic + internal fun validity(): Int = + (if (id.asKnown().isPresent) 1 else 0) + + (data.asKnown().getOrNull()?.validity() ?: 0) + + (type.asKnown().getOrNull()?.validity() ?: 0) + + @JsonDeserialize(using = Data.Deserializer::class) + @JsonSerialize(using = Data.Serializer::class) + class Data + private constructor( + private val streamEventSystemDataOutput: StreamEventSystemDataOutput? = null, + private val streamEventLogDataOutput: StreamEventLogDataOutput? = null, + private val _json: JsonValue? = null, + ) { + + fun streamEventSystemDataOutput(): Optional = + Optional.ofNullable(streamEventSystemDataOutput) + + fun streamEventLogDataOutput(): Optional = + Optional.ofNullable(streamEventLogDataOutput) + + fun isStreamEventSystemDataOutput(): Boolean = streamEventSystemDataOutput != null + + fun isStreamEventLogDataOutput(): Boolean = streamEventLogDataOutput != null + + fun asStreamEventSystemDataOutput(): StreamEventSystemDataOutput = + streamEventSystemDataOutput.getOrThrow("streamEventSystemDataOutput") + + fun asStreamEventLogDataOutput(): StreamEventLogDataOutput = + streamEventLogDataOutput.getOrThrow("streamEventLogDataOutput") + + fun _json(): Optional = Optional.ofNullable(_json) + + fun accept(visitor: Visitor): T = + when { + streamEventSystemDataOutput != null -> + visitor.visitStreamEventSystemDataOutput(streamEventSystemDataOutput) + streamEventLogDataOutput != null -> + visitor.visitStreamEventLogDataOutput(streamEventLogDataOutput) + else -> visitor.unknown(_json) + } + + private var validated: Boolean = false + + fun validate(): Data = apply { + if (validated) { + return@apply + } + + accept( + object : Visitor { + override fun visitStreamEventSystemDataOutput( + streamEventSystemDataOutput: StreamEventSystemDataOutput + ) { + streamEventSystemDataOutput.validate() + } + + override fun visitStreamEventLogDataOutput( + streamEventLogDataOutput: StreamEventLogDataOutput + ) { + streamEventLogDataOutput.validate() + } + } + ) + 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. + */ + @JvmSynthetic + internal fun validity(): Int = + accept( + object : Visitor { + override fun visitStreamEventSystemDataOutput( + streamEventSystemDataOutput: StreamEventSystemDataOutput + ) = streamEventSystemDataOutput.validity() + + override fun visitStreamEventLogDataOutput( + streamEventLogDataOutput: StreamEventLogDataOutput + ) = streamEventLogDataOutput.validity() + + override fun unknown(json: JsonValue?) = 0 + } + ) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Data && + streamEventSystemDataOutput == other.streamEventSystemDataOutput && + streamEventLogDataOutput == other.streamEventLogDataOutput + } + + override fun hashCode(): Int = + Objects.hash(streamEventSystemDataOutput, streamEventLogDataOutput) + + override fun toString(): String = + when { + streamEventSystemDataOutput != null -> + "Data{streamEventSystemDataOutput=$streamEventSystemDataOutput}" + streamEventLogDataOutput != null -> + "Data{streamEventLogDataOutput=$streamEventLogDataOutput}" + _json != null -> "Data{_unknown=$_json}" + else -> throw IllegalStateException("Invalid Data") + } + + companion object { + + @JvmStatic + fun ofStreamEventSystemDataOutput( + streamEventSystemDataOutput: StreamEventSystemDataOutput + ) = Data(streamEventSystemDataOutput = streamEventSystemDataOutput) + + @JvmStatic + fun ofStreamEventLogDataOutput(streamEventLogDataOutput: StreamEventLogDataOutput) = + Data(streamEventLogDataOutput = streamEventLogDataOutput) + } + + /** An interface that defines how to map each variant of [Data] to a value of type [T]. */ + interface Visitor { + + fun visitStreamEventSystemDataOutput( + streamEventSystemDataOutput: StreamEventSystemDataOutput + ): T + + fun visitStreamEventLogDataOutput(streamEventLogDataOutput: StreamEventLogDataOutput): T + + /** + * Maps an unknown variant of [Data] to a value of type [T]. + * + * An instance of [Data] can contain an unknown variant if it was deserialized from data + * that doesn't match any known variant. For example, if the SDK is on an older version + * than the API, then the API may respond with new variants that the SDK is unaware of. + * + * @throws StagehandInvalidDataException in the default implementation. + */ + fun unknown(json: JsonValue?): T { + throw StagehandInvalidDataException("Unknown Data: $json") + } + } + + internal class Deserializer : BaseDeserializer(Data::class) { + + override fun ObjectCodec.deserialize(node: JsonNode): Data { + val json = JsonValue.fromJsonNode(node) + + val bestMatches = + sequenceOf( + tryDeserialize(node, jacksonTypeRef()) + ?.let { Data(streamEventSystemDataOutput = it, _json = json) }, + tryDeserialize(node, jacksonTypeRef())?.let { + Data(streamEventLogDataOutput = it, _json = json) + }, + ) + .filterNotNull() + .allMaxBy { it.validity() } + .toList() + return when (bestMatches.size) { + // This can happen if what we're deserializing is completely incompatible with + // all the possible variants (e.g. deserializing from boolean). + 0 -> Data(_json = json) + 1 -> bestMatches.single() + // If there's more than one match with the highest validity, then use the first + // completely valid match, or simply the first match if none are completely + // valid. + else -> bestMatches.firstOrNull { it.isValid() } ?: bestMatches.first() + } + } + } + + internal class Serializer : BaseSerializer(Data::class) { + + override fun serialize( + value: Data, + generator: JsonGenerator, + provider: SerializerProvider, + ) { + when { + value.streamEventSystemDataOutput != null -> + generator.writeObject(value.streamEventSystemDataOutput) + value.streamEventLogDataOutput != null -> + generator.writeObject(value.streamEventLogDataOutput) + value._json != null -> generator.writeObject(value._json) + else -> throw IllegalStateException("Invalid Data") + } + } + } + + class StreamEventSystemDataOutput + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val status: JsonField, + private val error: JsonField, + private val result: JsonValue, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("status") + @ExcludeMissing + status: JsonField = JsonMissing.of(), + @JsonProperty("error") @ExcludeMissing error: JsonField = JsonMissing.of(), + @JsonProperty("result") @ExcludeMissing result: JsonValue = JsonMissing.of(), + ) : this(status, error, result, mutableMapOf()) + + /** + * Current status of the streaming operation + * + * @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 status(): Status = status.getRequired("status") + + /** + * Error message (present when status is 'error') + * + * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. + * if the server responded with an unexpected value). + */ + fun error(): Optional = error.getOptional("error") + + /** Operation result (present when status is 'finished') */ + @JsonProperty("result") @ExcludeMissing fun _result(): JsonValue = result + + /** + * Returns the raw JSON value of [status]. + * + * Unlike [status], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("status") @ExcludeMissing fun _status(): JsonField = status + + /** + * Returns the raw JSON value of [error]. + * + * Unlike [error], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("error") @ExcludeMissing fun _error(): JsonField = error + + @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 + * [StreamEventSystemDataOutput]. + * + * The following fields are required: + * ```java + * .status() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [StreamEventSystemDataOutput]. */ + class Builder internal constructor() { + + private var status: JsonField? = null + private var error: JsonField = JsonMissing.of() + private var result: JsonValue = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(streamEventSystemDataOutput: StreamEventSystemDataOutput) = + apply { + status = streamEventSystemDataOutput.status + error = streamEventSystemDataOutput.error + result = streamEventSystemDataOutput.result + additionalProperties = + streamEventSystemDataOutput.additionalProperties.toMutableMap() + } + + /** Current status of the streaming operation */ + fun status(status: Status) = status(JsonField.of(status)) + + /** + * Sets [Builder.status] to an arbitrary JSON value. + * + * You should usually call [Builder.status] with a well-typed [Status] value + * instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun status(status: JsonField) = apply { this.status = status } + + /** Error message (present when status is 'error') */ + fun error(error: String) = error(JsonField.of(error)) + + /** + * Sets [Builder.error] to an arbitrary JSON value. + * + * You should usually call [Builder.error] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun error(error: JsonField) = apply { this.error = error } + + /** Operation result (present when status is 'finished') */ + fun result(result: JsonValue) = apply { this.result = result } + + 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 [StreamEventSystemDataOutput]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .status() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): StreamEventSystemDataOutput = + StreamEventSystemDataOutput( + checkRequired("status", status), + error, + result, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): StreamEventSystemDataOutput = apply { + if (validated) { + return@apply + } + + status().validate() + error() + 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. + */ + @JvmSynthetic + internal fun validity(): Int = + (status.asKnown().getOrNull()?.validity() ?: 0) + + (if (error.asKnown().isPresent) 1 else 0) + + /** Current status of the streaming operation */ + class Status @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 { + + @JvmField val STARTING = of("starting") + + @JvmField val CONNECTED = of("connected") + + @JvmField val RUNNING = of("running") + + @JvmField val FINISHED = of("finished") + + @JvmField val ERROR = of("error") + + @JvmStatic fun of(value: String) = Status(JsonField.of(value)) + } + + /** An enum containing [Status]'s known values. */ + enum class Known { + STARTING, + CONNECTED, + RUNNING, + FINISHED, + ERROR, + } + + /** + * An enum containing [Status]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [Status] 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 { + STARTING, + CONNECTED, + RUNNING, + FINISHED, + ERROR, + /** + * An enum member indicating that [Status] 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) { + STARTING -> Value.STARTING + CONNECTED -> Value.CONNECTED + RUNNING -> Value.RUNNING + FINISHED -> Value.FINISHED + ERROR -> Value.ERROR + 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) { + STARTING -> Known.STARTING + CONNECTED -> Known.CONNECTED + RUNNING -> Known.RUNNING + FINISHED -> Known.FINISHED + ERROR -> Known.ERROR + else -> throw StagehandInvalidDataException("Unknown Status: $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().orElseThrow { + StagehandInvalidDataException("Value is not a String") + } + + private var validated: Boolean = false + + fun validate(): Status = 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. + */ + @JvmSynthetic 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 Status && 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 StreamEventSystemDataOutput && + status == other.status && + error == other.error && + result == other.result && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(status, error, result, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "StreamEventSystemDataOutput{status=$status, error=$error, result=$result, additionalProperties=$additionalProperties}" + } + + class StreamEventLogDataOutput + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val message: JsonField, + private val status: JsonValue, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("message") + @ExcludeMissing + message: JsonField = JsonMissing.of(), + @JsonProperty("status") @ExcludeMissing status: JsonValue = JsonMissing.of(), + ) : this(message, status, mutableMapOf()) + + /** + * Log message from the operation + * + * @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 message(): String = message.getRequired("message") + + /** + * Expected to always return the following: + * ```java + * JsonValue.from("running") + * ``` + * + * However, this method can be useful for debugging and logging (e.g. if the server + * responded with an unexpected value). + */ + @JsonProperty("status") @ExcludeMissing fun _status(): JsonValue = status + + /** + * Returns the raw JSON value of [message]. + * + * Unlike [message], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("message") @ExcludeMissing fun _message(): JsonField = message + + @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 + * [StreamEventLogDataOutput]. + * + * The following fields are required: + * ```java + * .message() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [StreamEventLogDataOutput]. */ + class Builder internal constructor() { + + private var message: JsonField? = null + private var status: JsonValue = JsonValue.from("running") + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(streamEventLogDataOutput: StreamEventLogDataOutput) = apply { + message = streamEventLogDataOutput.message + status = streamEventLogDataOutput.status + additionalProperties = + streamEventLogDataOutput.additionalProperties.toMutableMap() + } + + /** Log message from the operation */ + fun message(message: String) = message(JsonField.of(message)) + + /** + * Sets [Builder.message] to an arbitrary JSON value. + * + * You should usually call [Builder.message] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun message(message: JsonField) = apply { this.message = message } + + /** + * Sets the field to an arbitrary JSON value. + * + * It is usually unnecessary to call this method because the field defaults to the + * following: + * ```java + * JsonValue.from("running") + * ``` + * + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun status(status: JsonValue) = apply { this.status = status } + + 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 [StreamEventLogDataOutput]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .message() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): StreamEventLogDataOutput = + StreamEventLogDataOutput( + checkRequired("message", message), + status, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): StreamEventLogDataOutput = apply { + if (validated) { + return@apply + } + + message() + _status().let { + if (it != JsonValue.from("running")) { + throw StagehandInvalidDataException("'status' is invalid, received $it") + } + } + 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. + */ + @JvmSynthetic + internal fun validity(): Int = + (if (message.asKnown().isPresent) 1 else 0) + + status.let { if (it == JsonValue.from("running")) 1 else 0 } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is StreamEventLogDataOutput && + message == other.message && + status == other.status && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(message, status, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "StreamEventLogDataOutput{message=$message, status=$status, additionalProperties=$additionalProperties}" + } + } + + /** Type of stream event - system events or log messages */ + class Type @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 { + + @JvmField val SYSTEM = of("system") + + @JvmField val LOG = of("log") + + @JvmStatic fun of(value: String) = Type(JsonField.of(value)) + } + + /** An enum containing [Type]'s known values. */ + enum class Known { + SYSTEM, + LOG, + } + + /** + * An enum containing [Type]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [Type] 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 { + SYSTEM, + LOG, + /** An enum member indicating that [Type] 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) { + SYSTEM -> Value.SYSTEM + LOG -> Value.LOG + 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) { + SYSTEM -> Known.SYSTEM + LOG -> Known.LOG + else -> throw StagehandInvalidDataException("Unknown Type: $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().orElseThrow { + StagehandInvalidDataException("Value is not a String") + } + + private var validated: Boolean = false + + fun validate(): Type = 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. + */ + @JvmSynthetic 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 Type && 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 StreamEvent && + id == other.id && + data == other.data && + type == other.type && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { Objects.hash(id, data, type, additionalProperties) } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "StreamEvent{id=$id, data=$data, type=$type, additionalProperties=$additionalProperties}" +} diff --git a/stagehand-java-core/src/main/kotlin/com/browserbase/api/services/async/SessionServiceAsync.kt b/stagehand-java-core/src/main/kotlin/com/browserbase/api/services/async/SessionServiceAsync.kt index 423fd57..5c9171e 100644 --- a/stagehand-java-core/src/main/kotlin/com/browserbase/api/services/async/SessionServiceAsync.kt +++ b/stagehand-java-core/src/main/kotlin/com/browserbase/api/services/async/SessionServiceAsync.kt @@ -4,7 +4,9 @@ package com.browserbase.api.services.async import com.browserbase.api.core.ClientOptions import com.browserbase.api.core.RequestOptions +import com.browserbase.api.core.http.AsyncStreamResponse import com.browserbase.api.core.http.HttpResponseFor +import com.browserbase.api.core.http.StreamResponse import com.browserbase.api.models.sessions.SessionActParams import com.browserbase.api.models.sessions.SessionActResponse import com.browserbase.api.models.sessions.SessionEndParams @@ -19,6 +21,8 @@ import com.browserbase.api.models.sessions.SessionObserveParams import com.browserbase.api.models.sessions.SessionObserveResponse import com.browserbase.api.models.sessions.SessionStartParams import com.browserbase.api.models.sessions.SessionStartResponse +import com.browserbase.api.models.sessions.StreamEvent +import com.google.errorprone.annotations.MustBeClosed import java.util.concurrent.CompletableFuture import java.util.function.Consumer @@ -60,6 +64,30 @@ interface SessionServiceAsync { requestOptions: RequestOptions = RequestOptions.none(), ): CompletableFuture + /** + * Executes a browser action using natural language instructions or a predefined Action object. + */ + fun actStreaming(id: String, params: SessionActParams): AsyncStreamResponse = + actStreaming(id, params, RequestOptions.none()) + + /** @see actStreaming */ + fun actStreaming( + id: String, + params: SessionActParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): AsyncStreamResponse = + actStreaming(params.toBuilder().id(id).build(), requestOptions) + + /** @see actStreaming */ + fun actStreaming(params: SessionActParams): AsyncStreamResponse = + actStreaming(params, RequestOptions.none()) + + /** @see actStreaming */ + fun actStreaming( + params: SessionActParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): AsyncStreamResponse + /** Terminates the browser session and releases all associated resources. */ fun end(id: String): CompletableFuture = end(id, SessionEndParams.none()) @@ -115,6 +143,30 @@ interface SessionServiceAsync { requestOptions: RequestOptions = RequestOptions.none(), ): CompletableFuture + /** Runs an autonomous AI agent that can perform complex multi-step browser tasks. */ + fun executeStreaming( + id: String, + params: SessionExecuteParams, + ): AsyncStreamResponse = executeStreaming(id, params, RequestOptions.none()) + + /** @see executeStreaming */ + fun executeStreaming( + id: String, + params: SessionExecuteParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): AsyncStreamResponse = + executeStreaming(params.toBuilder().id(id).build(), requestOptions) + + /** @see executeStreaming */ + fun executeStreaming(params: SessionExecuteParams): AsyncStreamResponse = + executeStreaming(params, RequestOptions.none()) + + /** @see executeStreaming */ + fun executeStreaming( + params: SessionExecuteParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): AsyncStreamResponse + /** Extracts structured data from the current page using AI-powered analysis. */ fun extract(id: String): CompletableFuture = extract(id, SessionExtractParams.none()) @@ -150,6 +202,41 @@ interface SessionServiceAsync { ): CompletableFuture = extract(id, SessionExtractParams.none(), requestOptions) + /** Extracts structured data from the current page using AI-powered analysis. */ + fun extractStreaming(id: String): AsyncStreamResponse = + extractStreaming(id, SessionExtractParams.none()) + + /** @see extractStreaming */ + fun extractStreaming( + id: String, + params: SessionExtractParams = SessionExtractParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): AsyncStreamResponse = + extractStreaming(params.toBuilder().id(id).build(), requestOptions) + + /** @see extractStreaming */ + fun extractStreaming( + id: String, + params: SessionExtractParams = SessionExtractParams.none(), + ): AsyncStreamResponse = extractStreaming(id, params, RequestOptions.none()) + + /** @see extractStreaming */ + fun extractStreaming( + params: SessionExtractParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): AsyncStreamResponse + + /** @see extractStreaming */ + fun extractStreaming(params: SessionExtractParams): AsyncStreamResponse = + extractStreaming(params, RequestOptions.none()) + + /** @see extractStreaming */ + fun extractStreaming( + id: String, + requestOptions: RequestOptions, + ): AsyncStreamResponse = + extractStreaming(id, SessionExtractParams.none(), requestOptions) + /** Navigates the browser to the specified URL. */ fun navigate( id: String, @@ -212,6 +299,44 @@ interface SessionServiceAsync { ): CompletableFuture = observe(id, SessionObserveParams.none(), requestOptions) + /** + * Identifies and returns available actions on the current page that match the given + * instruction. + */ + fun observeStreaming(id: String): AsyncStreamResponse = + observeStreaming(id, SessionObserveParams.none()) + + /** @see observeStreaming */ + fun observeStreaming( + id: String, + params: SessionObserveParams = SessionObserveParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): AsyncStreamResponse = + observeStreaming(params.toBuilder().id(id).build(), requestOptions) + + /** @see observeStreaming */ + fun observeStreaming( + id: String, + params: SessionObserveParams = SessionObserveParams.none(), + ): AsyncStreamResponse = observeStreaming(id, params, RequestOptions.none()) + + /** @see observeStreaming */ + fun observeStreaming( + params: SessionObserveParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): AsyncStreamResponse + + /** @see observeStreaming */ + fun observeStreaming(params: SessionObserveParams): AsyncStreamResponse = + observeStreaming(params, RequestOptions.none()) + + /** @see observeStreaming */ + fun observeStreaming( + id: String, + requestOptions: RequestOptions, + ): AsyncStreamResponse = + observeStreaming(id, SessionObserveParams.none(), requestOptions) + /** * Creates a new browser session with the specified configuration. Returns a session ID used for * all subsequent operations. @@ -267,6 +392,40 @@ interface SessionServiceAsync { requestOptions: RequestOptions = RequestOptions.none(), ): CompletableFuture> + /** + * Returns a raw HTTP response for `post /v1/sessions/{id}/act`, but is otherwise the same + * as [SessionServiceAsync.actStreaming]. + */ + @MustBeClosed + fun actStreaming( + id: String, + params: SessionActParams, + ): CompletableFuture>> = + actStreaming(id, params, RequestOptions.none()) + + /** @see actStreaming */ + @MustBeClosed + fun actStreaming( + id: String, + params: SessionActParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture>> = + actStreaming(params.toBuilder().id(id).build(), requestOptions) + + /** @see actStreaming */ + @MustBeClosed + fun actStreaming( + params: SessionActParams + ): CompletableFuture>> = + actStreaming(params, RequestOptions.none()) + + /** @see actStreaming */ + @MustBeClosed + fun actStreaming( + params: SessionActParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture>> + /** * Returns a raw HTTP response for `post /v1/sessions/{id}/end`, but is otherwise the same * as [SessionServiceAsync.end]. @@ -336,6 +495,40 @@ interface SessionServiceAsync { requestOptions: RequestOptions = RequestOptions.none(), ): CompletableFuture> + /** + * Returns a raw HTTP response for `post /v1/sessions/{id}/agentExecute`, but is otherwise + * the same as [SessionServiceAsync.executeStreaming]. + */ + @MustBeClosed + fun executeStreaming( + id: String, + params: SessionExecuteParams, + ): CompletableFuture>> = + executeStreaming(id, params, RequestOptions.none()) + + /** @see executeStreaming */ + @MustBeClosed + fun executeStreaming( + id: String, + params: SessionExecuteParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture>> = + executeStreaming(params.toBuilder().id(id).build(), requestOptions) + + /** @see executeStreaming */ + @MustBeClosed + fun executeStreaming( + params: SessionExecuteParams + ): CompletableFuture>> = + executeStreaming(params, RequestOptions.none()) + + /** @see executeStreaming */ + @MustBeClosed + fun executeStreaming( + params: SessionExecuteParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture>> + /** * Returns a raw HTTP response for `post /v1/sessions/{id}/extract`, but is otherwise the * same as [SessionServiceAsync.extract]. @@ -377,6 +570,55 @@ interface SessionServiceAsync { ): CompletableFuture> = extract(id, SessionExtractParams.none(), requestOptions) + /** + * Returns a raw HTTP response for `post /v1/sessions/{id}/extract`, but is otherwise the + * same as [SessionServiceAsync.extractStreaming]. + */ + @MustBeClosed + fun extractStreaming( + id: String + ): CompletableFuture>> = + extractStreaming(id, SessionExtractParams.none()) + + /** @see extractStreaming */ + @MustBeClosed + fun extractStreaming( + id: String, + params: SessionExtractParams = SessionExtractParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture>> = + extractStreaming(params.toBuilder().id(id).build(), requestOptions) + + /** @see extractStreaming */ + @MustBeClosed + fun extractStreaming( + id: String, + params: SessionExtractParams = SessionExtractParams.none(), + ): CompletableFuture>> = + extractStreaming(id, params, RequestOptions.none()) + + /** @see extractStreaming */ + @MustBeClosed + fun extractStreaming( + params: SessionExtractParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture>> + + /** @see extractStreaming */ + @MustBeClosed + fun extractStreaming( + params: SessionExtractParams + ): CompletableFuture>> = + extractStreaming(params, RequestOptions.none()) + + /** @see extractStreaming */ + @MustBeClosed + fun extractStreaming( + id: String, + requestOptions: RequestOptions, + ): CompletableFuture>> = + extractStreaming(id, SessionExtractParams.none(), requestOptions) + /** * Returns a raw HTTP response for `post /v1/sessions/{id}/navigate`, but is otherwise the * same as [SessionServiceAsync.navigate]. @@ -448,6 +690,55 @@ interface SessionServiceAsync { ): CompletableFuture> = observe(id, SessionObserveParams.none(), requestOptions) + /** + * Returns a raw HTTP response for `post /v1/sessions/{id}/observe`, but is otherwise the + * same as [SessionServiceAsync.observeStreaming]. + */ + @MustBeClosed + fun observeStreaming( + id: String + ): CompletableFuture>> = + observeStreaming(id, SessionObserveParams.none()) + + /** @see observeStreaming */ + @MustBeClosed + fun observeStreaming( + id: String, + params: SessionObserveParams = SessionObserveParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture>> = + observeStreaming(params.toBuilder().id(id).build(), requestOptions) + + /** @see observeStreaming */ + @MustBeClosed + fun observeStreaming( + id: String, + params: SessionObserveParams = SessionObserveParams.none(), + ): CompletableFuture>> = + observeStreaming(id, params, RequestOptions.none()) + + /** @see observeStreaming */ + @MustBeClosed + fun observeStreaming( + params: SessionObserveParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture>> + + /** @see observeStreaming */ + @MustBeClosed + fun observeStreaming( + params: SessionObserveParams + ): CompletableFuture>> = + observeStreaming(params, RequestOptions.none()) + + /** @see observeStreaming */ + @MustBeClosed + fun observeStreaming( + id: String, + requestOptions: RequestOptions, + ): CompletableFuture>> = + observeStreaming(id, SessionObserveParams.none(), requestOptions) + /** * Returns a raw HTTP response for `post /v1/sessions/start`, but is otherwise the same as * [SessionServiceAsync.start]. diff --git a/stagehand-java-core/src/main/kotlin/com/browserbase/api/services/async/SessionServiceAsyncImpl.kt b/stagehand-java-core/src/main/kotlin/com/browserbase/api/services/async/SessionServiceAsyncImpl.kt index 99037bc..82062e4 100644 --- a/stagehand-java-core/src/main/kotlin/com/browserbase/api/services/async/SessionServiceAsyncImpl.kt +++ b/stagehand-java-core/src/main/kotlin/com/browserbase/api/services/async/SessionServiceAsyncImpl.kt @@ -3,18 +3,25 @@ package com.browserbase.api.services.async import com.browserbase.api.core.ClientOptions +import com.browserbase.api.core.JsonValue import com.browserbase.api.core.RequestOptions import com.browserbase.api.core.checkRequired import com.browserbase.api.core.handlers.errorBodyHandler import com.browserbase.api.core.handlers.errorHandler import com.browserbase.api.core.handlers.jsonHandler +import com.browserbase.api.core.handlers.mapJson +import com.browserbase.api.core.handlers.sseHandler +import com.browserbase.api.core.http.AsyncStreamResponse import com.browserbase.api.core.http.HttpMethod import com.browserbase.api.core.http.HttpRequest import com.browserbase.api.core.http.HttpResponse import com.browserbase.api.core.http.HttpResponse.Handler import com.browserbase.api.core.http.HttpResponseFor +import com.browserbase.api.core.http.StreamResponse import com.browserbase.api.core.http.json +import com.browserbase.api.core.http.map import com.browserbase.api.core.http.parseable +import com.browserbase.api.core.http.toAsync import com.browserbase.api.core.prepareAsync import com.browserbase.api.models.sessions.SessionActParams import com.browserbase.api.models.sessions.SessionActResponse @@ -30,6 +37,7 @@ import com.browserbase.api.models.sessions.SessionObserveParams import com.browserbase.api.models.sessions.SessionObserveResponse import com.browserbase.api.models.sessions.SessionStartParams import com.browserbase.api.models.sessions.SessionStartResponse +import com.browserbase.api.models.sessions.StreamEvent import java.util.concurrent.CompletableFuture import java.util.function.Consumer import kotlin.jvm.optionals.getOrNull @@ -53,6 +61,16 @@ class SessionServiceAsyncImpl internal constructor(private val clientOptions: Cl // post /v1/sessions/{id}/act withRawResponse().act(params, requestOptions).thenApply { it.parse() } + override fun actStreaming( + params: SessionActParams, + requestOptions: RequestOptions, + ): AsyncStreamResponse = + // post /v1/sessions/{id}/act + withRawResponse() + .actStreaming(params, requestOptions) + .thenApply { it.parse() } + .toAsync(clientOptions.streamHandlerExecutor) + override fun end( params: SessionEndParams, requestOptions: RequestOptions, @@ -67,6 +85,16 @@ class SessionServiceAsyncImpl internal constructor(private val clientOptions: Cl // post /v1/sessions/{id}/agentExecute withRawResponse().execute(params, requestOptions).thenApply { it.parse() } + override fun executeStreaming( + params: SessionExecuteParams, + requestOptions: RequestOptions, + ): AsyncStreamResponse = + // post /v1/sessions/{id}/agentExecute + withRawResponse() + .executeStreaming(params, requestOptions) + .thenApply { it.parse() } + .toAsync(clientOptions.streamHandlerExecutor) + override fun extract( params: SessionExtractParams, requestOptions: RequestOptions, @@ -74,6 +102,16 @@ class SessionServiceAsyncImpl internal constructor(private val clientOptions: Cl // post /v1/sessions/{id}/extract withRawResponse().extract(params, requestOptions).thenApply { it.parse() } + override fun extractStreaming( + params: SessionExtractParams, + requestOptions: RequestOptions, + ): AsyncStreamResponse = + // post /v1/sessions/{id}/extract + withRawResponse() + .extractStreaming(params, requestOptions) + .thenApply { it.parse() } + .toAsync(clientOptions.streamHandlerExecutor) + override fun navigate( params: SessionNavigateParams, requestOptions: RequestOptions, @@ -88,6 +126,16 @@ class SessionServiceAsyncImpl internal constructor(private val clientOptions: Cl // post /v1/sessions/{id}/observe withRawResponse().observe(params, requestOptions).thenApply { it.parse() } + override fun observeStreaming( + params: SessionObserveParams, + requestOptions: RequestOptions, + ): AsyncStreamResponse = + // post /v1/sessions/{id}/observe + withRawResponse() + .observeStreaming(params, requestOptions) + .thenApply { it.parse() } + .toAsync(clientOptions.streamHandlerExecutor) + override fun start( params: SessionStartParams, requestOptions: RequestOptions, @@ -142,6 +190,51 @@ class SessionServiceAsyncImpl internal constructor(private val clientOptions: Cl } } + private val actStreamingHandler: Handler> = + sseHandler(clientOptions.jsonMapper).mapJson() + + override fun actStreaming( + params: SessionActParams, + requestOptions: RequestOptions, + ): CompletableFuture>> { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("id", params.id().getOrNull()) + val request = + HttpRequest.builder() + .method(HttpMethod.POST) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("v1", "sessions", params._pathParam(0), "act") + .body( + json( + clientOptions.jsonMapper, + params + ._body() + .toBuilder() + .putAdditionalProperty("streamResponse", JsonValue.from(true)) + .build(), + ) + ) + .build() + .prepareAsync(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + return request + .thenComposeAsync { clientOptions.httpClient.executeAsync(it, requestOptions) } + .thenApply { response -> + errorHandler.handle(response).parseable { + response + .let { actStreamingHandler.handle(it) } + .let { streamResponse -> + if (requestOptions.responseValidation!!) { + streamResponse.map { it.validate() } + } else { + streamResponse + } + } + } + } + } + private val endHandler: Handler = jsonHandler(clientOptions.jsonMapper) @@ -210,6 +303,51 @@ class SessionServiceAsyncImpl internal constructor(private val clientOptions: Cl } } + private val executeStreamingHandler: Handler> = + sseHandler(clientOptions.jsonMapper).mapJson() + + override fun executeStreaming( + params: SessionExecuteParams, + requestOptions: RequestOptions, + ): CompletableFuture>> { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("id", params.id().getOrNull()) + val request = + HttpRequest.builder() + .method(HttpMethod.POST) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("v1", "sessions", params._pathParam(0), "agentExecute") + .body( + json( + clientOptions.jsonMapper, + params + ._body() + .toBuilder() + .putAdditionalProperty("streamResponse", JsonValue.from(true)) + .build(), + ) + ) + .build() + .prepareAsync(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + return request + .thenComposeAsync { clientOptions.httpClient.executeAsync(it, requestOptions) } + .thenApply { response -> + errorHandler.handle(response).parseable { + response + .let { executeStreamingHandler.handle(it) } + .let { streamResponse -> + if (requestOptions.responseValidation!!) { + streamResponse.map { it.validate() } + } else { + streamResponse + } + } + } + } + } + private val extractHandler: Handler = jsonHandler(clientOptions.jsonMapper) @@ -244,6 +382,51 @@ class SessionServiceAsyncImpl internal constructor(private val clientOptions: Cl } } + private val extractStreamingHandler: Handler> = + sseHandler(clientOptions.jsonMapper).mapJson() + + override fun extractStreaming( + params: SessionExtractParams, + requestOptions: RequestOptions, + ): CompletableFuture>> { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("id", params.id().getOrNull()) + val request = + HttpRequest.builder() + .method(HttpMethod.POST) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("v1", "sessions", params._pathParam(0), "extract") + .body( + json( + clientOptions.jsonMapper, + params + ._body() + .toBuilder() + .putAdditionalProperty("streamResponse", JsonValue.from(true)) + .build(), + ) + ) + .build() + .prepareAsync(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + return request + .thenComposeAsync { clientOptions.httpClient.executeAsync(it, requestOptions) } + .thenApply { response -> + errorHandler.handle(response).parseable { + response + .let { extractStreamingHandler.handle(it) } + .let { streamResponse -> + if (requestOptions.responseValidation!!) { + streamResponse.map { it.validate() } + } else { + streamResponse + } + } + } + } + } + private val navigateHandler: Handler = jsonHandler(clientOptions.jsonMapper) @@ -312,6 +495,51 @@ class SessionServiceAsyncImpl internal constructor(private val clientOptions: Cl } } + private val observeStreamingHandler: Handler> = + sseHandler(clientOptions.jsonMapper).mapJson() + + override fun observeStreaming( + params: SessionObserveParams, + requestOptions: RequestOptions, + ): CompletableFuture>> { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("id", params.id().getOrNull()) + val request = + HttpRequest.builder() + .method(HttpMethod.POST) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("v1", "sessions", params._pathParam(0), "observe") + .body( + json( + clientOptions.jsonMapper, + params + ._body() + .toBuilder() + .putAdditionalProperty("streamResponse", JsonValue.from(true)) + .build(), + ) + ) + .build() + .prepareAsync(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + return request + .thenComposeAsync { clientOptions.httpClient.executeAsync(it, requestOptions) } + .thenApply { response -> + errorHandler.handle(response).parseable { + response + .let { observeStreamingHandler.handle(it) } + .let { streamResponse -> + if (requestOptions.responseValidation!!) { + streamResponse.map { it.validate() } + } else { + streamResponse + } + } + } + } + } + private val startHandler: Handler = jsonHandler(clientOptions.jsonMapper) diff --git a/stagehand-java-core/src/main/kotlin/com/browserbase/api/services/blocking/SessionService.kt b/stagehand-java-core/src/main/kotlin/com/browserbase/api/services/blocking/SessionService.kt index df7bb72..0d56e93 100644 --- a/stagehand-java-core/src/main/kotlin/com/browserbase/api/services/blocking/SessionService.kt +++ b/stagehand-java-core/src/main/kotlin/com/browserbase/api/services/blocking/SessionService.kt @@ -5,6 +5,7 @@ package com.browserbase.api.services.blocking import com.browserbase.api.core.ClientOptions import com.browserbase.api.core.RequestOptions import com.browserbase.api.core.http.HttpResponseFor +import com.browserbase.api.core.http.StreamResponse import com.browserbase.api.models.sessions.SessionActParams import com.browserbase.api.models.sessions.SessionActResponse import com.browserbase.api.models.sessions.SessionEndParams @@ -19,6 +20,7 @@ import com.browserbase.api.models.sessions.SessionObserveParams import com.browserbase.api.models.sessions.SessionObserveResponse import com.browserbase.api.models.sessions.SessionStartParams import com.browserbase.api.models.sessions.SessionStartResponse +import com.browserbase.api.models.sessions.StreamEvent import com.google.errorprone.annotations.MustBeClosed import java.util.function.Consumer @@ -58,6 +60,33 @@ interface SessionService { requestOptions: RequestOptions = RequestOptions.none(), ): SessionActResponse + /** + * Executes a browser action using natural language instructions or a predefined Action object. + */ + @MustBeClosed + fun actStreaming(id: String, params: SessionActParams): StreamResponse = + actStreaming(id, params, RequestOptions.none()) + + /** @see actStreaming */ + @MustBeClosed + fun actStreaming( + id: String, + params: SessionActParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): StreamResponse = actStreaming(params.toBuilder().id(id).build(), requestOptions) + + /** @see actStreaming */ + @MustBeClosed + fun actStreaming(params: SessionActParams): StreamResponse = + actStreaming(params, RequestOptions.none()) + + /** @see actStreaming */ + @MustBeClosed + fun actStreaming( + params: SessionActParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): StreamResponse + /** Terminates the browser session and releases all associated resources. */ fun end(id: String): SessionEndResponse = end(id, SessionEndParams.none()) @@ -106,6 +135,32 @@ interface SessionService { requestOptions: RequestOptions = RequestOptions.none(), ): SessionExecuteResponse + /** Runs an autonomous AI agent that can perform complex multi-step browser tasks. */ + @MustBeClosed + fun executeStreaming(id: String, params: SessionExecuteParams): StreamResponse = + executeStreaming(id, params, RequestOptions.none()) + + /** @see executeStreaming */ + @MustBeClosed + fun executeStreaming( + id: String, + params: SessionExecuteParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): StreamResponse = + executeStreaming(params.toBuilder().id(id).build(), requestOptions) + + /** @see executeStreaming */ + @MustBeClosed + fun executeStreaming(params: SessionExecuteParams): StreamResponse = + executeStreaming(params, RequestOptions.none()) + + /** @see executeStreaming */ + @MustBeClosed + fun executeStreaming( + params: SessionExecuteParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): StreamResponse + /** Extracts structured data from the current page using AI-powered analysis. */ fun extract(id: String): SessionExtractResponse = extract(id, SessionExtractParams.none()) @@ -136,6 +191,44 @@ interface SessionService { fun extract(id: String, requestOptions: RequestOptions): SessionExtractResponse = extract(id, SessionExtractParams.none(), requestOptions) + /** Extracts structured data from the current page using AI-powered analysis. */ + @MustBeClosed + fun extractStreaming(id: String): StreamResponse = + extractStreaming(id, SessionExtractParams.none()) + + /** @see extractStreaming */ + @MustBeClosed + fun extractStreaming( + id: String, + params: SessionExtractParams = SessionExtractParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): StreamResponse = + extractStreaming(params.toBuilder().id(id).build(), requestOptions) + + /** @see extractStreaming */ + @MustBeClosed + fun extractStreaming( + id: String, + params: SessionExtractParams = SessionExtractParams.none(), + ): StreamResponse = extractStreaming(id, params, RequestOptions.none()) + + /** @see extractStreaming */ + @MustBeClosed + fun extractStreaming( + params: SessionExtractParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): StreamResponse + + /** @see extractStreaming */ + @MustBeClosed + fun extractStreaming(params: SessionExtractParams): StreamResponse = + extractStreaming(params, RequestOptions.none()) + + /** @see extractStreaming */ + @MustBeClosed + fun extractStreaming(id: String, requestOptions: RequestOptions): StreamResponse = + extractStreaming(id, SessionExtractParams.none(), requestOptions) + /** Navigates the browser to the specified URL. */ fun navigate(id: String, params: SessionNavigateParams): SessionNavigateResponse = navigate(id, params, RequestOptions.none()) @@ -190,6 +283,47 @@ interface SessionService { fun observe(id: String, requestOptions: RequestOptions): SessionObserveResponse = observe(id, SessionObserveParams.none(), requestOptions) + /** + * Identifies and returns available actions on the current page that match the given + * instruction. + */ + @MustBeClosed + fun observeStreaming(id: String): StreamResponse = + observeStreaming(id, SessionObserveParams.none()) + + /** @see observeStreaming */ + @MustBeClosed + fun observeStreaming( + id: String, + params: SessionObserveParams = SessionObserveParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): StreamResponse = + observeStreaming(params.toBuilder().id(id).build(), requestOptions) + + /** @see observeStreaming */ + @MustBeClosed + fun observeStreaming( + id: String, + params: SessionObserveParams = SessionObserveParams.none(), + ): StreamResponse = observeStreaming(id, params, RequestOptions.none()) + + /** @see observeStreaming */ + @MustBeClosed + fun observeStreaming( + params: SessionObserveParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): StreamResponse + + /** @see observeStreaming */ + @MustBeClosed + fun observeStreaming(params: SessionObserveParams): StreamResponse = + observeStreaming(params, RequestOptions.none()) + + /** @see observeStreaming */ + @MustBeClosed + fun observeStreaming(id: String, requestOptions: RequestOptions): StreamResponse = + observeStreaming(id, SessionObserveParams.none(), requestOptions) + /** * Creates a new browser session with the specified configuration. Returns a session ID used for * all subsequent operations. @@ -242,6 +376,38 @@ interface SessionService { requestOptions: RequestOptions = RequestOptions.none(), ): HttpResponseFor + /** + * Returns a raw HTTP response for `post /v1/sessions/{id}/act`, but is otherwise the same + * as [SessionService.actStreaming]. + */ + @MustBeClosed + fun actStreaming( + id: String, + params: SessionActParams, + ): HttpResponseFor> = + actStreaming(id, params, RequestOptions.none()) + + /** @see actStreaming */ + @MustBeClosed + fun actStreaming( + id: String, + params: SessionActParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor> = + actStreaming(params.toBuilder().id(id).build(), requestOptions) + + /** @see actStreaming */ + @MustBeClosed + fun actStreaming(params: SessionActParams): HttpResponseFor> = + actStreaming(params, RequestOptions.none()) + + /** @see actStreaming */ + @MustBeClosed + fun actStreaming( + params: SessionActParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor> + /** * Returns a raw HTTP response for `post /v1/sessions/{id}/end`, but is otherwise the same * as [SessionService.end]. @@ -313,6 +479,40 @@ interface SessionService { requestOptions: RequestOptions = RequestOptions.none(), ): HttpResponseFor + /** + * Returns a raw HTTP response for `post /v1/sessions/{id}/agentExecute`, but is otherwise + * the same as [SessionService.executeStreaming]. + */ + @MustBeClosed + fun executeStreaming( + id: String, + params: SessionExecuteParams, + ): HttpResponseFor> = + executeStreaming(id, params, RequestOptions.none()) + + /** @see executeStreaming */ + @MustBeClosed + fun executeStreaming( + id: String, + params: SessionExecuteParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor> = + executeStreaming(params.toBuilder().id(id).build(), requestOptions) + + /** @see executeStreaming */ + @MustBeClosed + fun executeStreaming( + params: SessionExecuteParams + ): HttpResponseFor> = + executeStreaming(params, RequestOptions.none()) + + /** @see executeStreaming */ + @MustBeClosed + fun executeStreaming( + params: SessionExecuteParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor> + /** * Returns a raw HTTP response for `post /v1/sessions/{id}/extract`, but is otherwise the * same as [SessionService.extract]. @@ -357,6 +557,53 @@ interface SessionService { ): HttpResponseFor = extract(id, SessionExtractParams.none(), requestOptions) + /** + * Returns a raw HTTP response for `post /v1/sessions/{id}/extract`, but is otherwise the + * same as [SessionService.extractStreaming]. + */ + @MustBeClosed + fun extractStreaming(id: String): HttpResponseFor> = + extractStreaming(id, SessionExtractParams.none()) + + /** @see extractStreaming */ + @MustBeClosed + fun extractStreaming( + id: String, + params: SessionExtractParams = SessionExtractParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor> = + extractStreaming(params.toBuilder().id(id).build(), requestOptions) + + /** @see extractStreaming */ + @MustBeClosed + fun extractStreaming( + id: String, + params: SessionExtractParams = SessionExtractParams.none(), + ): HttpResponseFor> = + extractStreaming(id, params, RequestOptions.none()) + + /** @see extractStreaming */ + @MustBeClosed + fun extractStreaming( + params: SessionExtractParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor> + + /** @see extractStreaming */ + @MustBeClosed + fun extractStreaming( + params: SessionExtractParams + ): HttpResponseFor> = + extractStreaming(params, RequestOptions.none()) + + /** @see extractStreaming */ + @MustBeClosed + fun extractStreaming( + id: String, + requestOptions: RequestOptions, + ): HttpResponseFor> = + extractStreaming(id, SessionExtractParams.none(), requestOptions) + /** * Returns a raw HTTP response for `post /v1/sessions/{id}/navigate`, but is otherwise the * same as [SessionService.navigate]. @@ -432,6 +679,53 @@ interface SessionService { ): HttpResponseFor = observe(id, SessionObserveParams.none(), requestOptions) + /** + * Returns a raw HTTP response for `post /v1/sessions/{id}/observe`, but is otherwise the + * same as [SessionService.observeStreaming]. + */ + @MustBeClosed + fun observeStreaming(id: String): HttpResponseFor> = + observeStreaming(id, SessionObserveParams.none()) + + /** @see observeStreaming */ + @MustBeClosed + fun observeStreaming( + id: String, + params: SessionObserveParams = SessionObserveParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor> = + observeStreaming(params.toBuilder().id(id).build(), requestOptions) + + /** @see observeStreaming */ + @MustBeClosed + fun observeStreaming( + id: String, + params: SessionObserveParams = SessionObserveParams.none(), + ): HttpResponseFor> = + observeStreaming(id, params, RequestOptions.none()) + + /** @see observeStreaming */ + @MustBeClosed + fun observeStreaming( + params: SessionObserveParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor> + + /** @see observeStreaming */ + @MustBeClosed + fun observeStreaming( + params: SessionObserveParams + ): HttpResponseFor> = + observeStreaming(params, RequestOptions.none()) + + /** @see observeStreaming */ + @MustBeClosed + fun observeStreaming( + id: String, + requestOptions: RequestOptions, + ): HttpResponseFor> = + observeStreaming(id, SessionObserveParams.none(), requestOptions) + /** * Returns a raw HTTP response for `post /v1/sessions/start`, but is otherwise the same as * [SessionService.start]. diff --git a/stagehand-java-core/src/main/kotlin/com/browserbase/api/services/blocking/SessionServiceImpl.kt b/stagehand-java-core/src/main/kotlin/com/browserbase/api/services/blocking/SessionServiceImpl.kt index aac8272..4bfce1b 100644 --- a/stagehand-java-core/src/main/kotlin/com/browserbase/api/services/blocking/SessionServiceImpl.kt +++ b/stagehand-java-core/src/main/kotlin/com/browserbase/api/services/blocking/SessionServiceImpl.kt @@ -3,17 +3,22 @@ package com.browserbase.api.services.blocking import com.browserbase.api.core.ClientOptions +import com.browserbase.api.core.JsonValue import com.browserbase.api.core.RequestOptions import com.browserbase.api.core.checkRequired import com.browserbase.api.core.handlers.errorBodyHandler import com.browserbase.api.core.handlers.errorHandler import com.browserbase.api.core.handlers.jsonHandler +import com.browserbase.api.core.handlers.mapJson +import com.browserbase.api.core.handlers.sseHandler import com.browserbase.api.core.http.HttpMethod import com.browserbase.api.core.http.HttpRequest import com.browserbase.api.core.http.HttpResponse import com.browserbase.api.core.http.HttpResponse.Handler import com.browserbase.api.core.http.HttpResponseFor +import com.browserbase.api.core.http.StreamResponse import com.browserbase.api.core.http.json +import com.browserbase.api.core.http.map import com.browserbase.api.core.http.parseable import com.browserbase.api.core.prepare import com.browserbase.api.models.sessions.SessionActParams @@ -30,6 +35,7 @@ import com.browserbase.api.models.sessions.SessionObserveParams import com.browserbase.api.models.sessions.SessionObserveResponse import com.browserbase.api.models.sessions.SessionStartParams import com.browserbase.api.models.sessions.SessionStartResponse +import com.browserbase.api.models.sessions.StreamEvent import java.util.function.Consumer import kotlin.jvm.optionals.getOrNull @@ -49,6 +55,13 @@ class SessionServiceImpl internal constructor(private val clientOptions: ClientO // post /v1/sessions/{id}/act withRawResponse().act(params, requestOptions).parse() + override fun actStreaming( + params: SessionActParams, + requestOptions: RequestOptions, + ): StreamResponse = + // post /v1/sessions/{id}/act + withRawResponse().actStreaming(params, requestOptions).parse() + override fun end(params: SessionEndParams, requestOptions: RequestOptions): SessionEndResponse = // post /v1/sessions/{id}/end withRawResponse().end(params, requestOptions).parse() @@ -60,6 +73,13 @@ class SessionServiceImpl internal constructor(private val clientOptions: ClientO // post /v1/sessions/{id}/agentExecute withRawResponse().execute(params, requestOptions).parse() + override fun executeStreaming( + params: SessionExecuteParams, + requestOptions: RequestOptions, + ): StreamResponse = + // post /v1/sessions/{id}/agentExecute + withRawResponse().executeStreaming(params, requestOptions).parse() + override fun extract( params: SessionExtractParams, requestOptions: RequestOptions, @@ -67,6 +87,13 @@ class SessionServiceImpl internal constructor(private val clientOptions: ClientO // post /v1/sessions/{id}/extract withRawResponse().extract(params, requestOptions).parse() + override fun extractStreaming( + params: SessionExtractParams, + requestOptions: RequestOptions, + ): StreamResponse = + // post /v1/sessions/{id}/extract + withRawResponse().extractStreaming(params, requestOptions).parse() + override fun navigate( params: SessionNavigateParams, requestOptions: RequestOptions, @@ -81,6 +108,13 @@ class SessionServiceImpl internal constructor(private val clientOptions: ClientO // post /v1/sessions/{id}/observe withRawResponse().observe(params, requestOptions).parse() + override fun observeStreaming( + params: SessionObserveParams, + requestOptions: RequestOptions, + ): StreamResponse = + // post /v1/sessions/{id}/observe + withRawResponse().observeStreaming(params, requestOptions).parse() + override fun start( params: SessionStartParams, requestOptions: RequestOptions, @@ -132,6 +166,48 @@ class SessionServiceImpl internal constructor(private val clientOptions: ClientO } } + private val actStreamingHandler: Handler> = + sseHandler(clientOptions.jsonMapper).mapJson() + + override fun actStreaming( + params: SessionActParams, + requestOptions: RequestOptions, + ): HttpResponseFor> { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("id", params.id().getOrNull()) + val request = + HttpRequest.builder() + .method(HttpMethod.POST) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("v1", "sessions", params._pathParam(0), "act") + .body( + json( + clientOptions.jsonMapper, + params + ._body() + .toBuilder() + .putAdditionalProperty("streamResponse", JsonValue.from(true)) + .build(), + ) + ) + .build() + .prepare(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.execute(request, requestOptions) + return errorHandler.handle(response).parseable { + response + .let { actStreamingHandler.handle(it) } + .let { streamResponse -> + if (requestOptions.responseValidation!!) { + streamResponse.map { it.validate() } + } else { + streamResponse + } + } + } + } + private val endHandler: Handler = jsonHandler(clientOptions.jsonMapper) @@ -194,6 +270,48 @@ class SessionServiceImpl internal constructor(private val clientOptions: ClientO } } + private val executeStreamingHandler: Handler> = + sseHandler(clientOptions.jsonMapper).mapJson() + + override fun executeStreaming( + params: SessionExecuteParams, + requestOptions: RequestOptions, + ): HttpResponseFor> { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("id", params.id().getOrNull()) + val request = + HttpRequest.builder() + .method(HttpMethod.POST) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("v1", "sessions", params._pathParam(0), "agentExecute") + .body( + json( + clientOptions.jsonMapper, + params + ._body() + .toBuilder() + .putAdditionalProperty("streamResponse", JsonValue.from(true)) + .build(), + ) + ) + .build() + .prepare(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.execute(request, requestOptions) + return errorHandler.handle(response).parseable { + response + .let { executeStreamingHandler.handle(it) } + .let { streamResponse -> + if (requestOptions.responseValidation!!) { + streamResponse.map { it.validate() } + } else { + streamResponse + } + } + } + } + private val extractHandler: Handler = jsonHandler(clientOptions.jsonMapper) @@ -225,6 +343,48 @@ class SessionServiceImpl internal constructor(private val clientOptions: ClientO } } + private val extractStreamingHandler: Handler> = + sseHandler(clientOptions.jsonMapper).mapJson() + + override fun extractStreaming( + params: SessionExtractParams, + requestOptions: RequestOptions, + ): HttpResponseFor> { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("id", params.id().getOrNull()) + val request = + HttpRequest.builder() + .method(HttpMethod.POST) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("v1", "sessions", params._pathParam(0), "extract") + .body( + json( + clientOptions.jsonMapper, + params + ._body() + .toBuilder() + .putAdditionalProperty("streamResponse", JsonValue.from(true)) + .build(), + ) + ) + .build() + .prepare(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.execute(request, requestOptions) + return errorHandler.handle(response).parseable { + response + .let { extractStreamingHandler.handle(it) } + .let { streamResponse -> + if (requestOptions.responseValidation!!) { + streamResponse.map { it.validate() } + } else { + streamResponse + } + } + } + } + private val navigateHandler: Handler = jsonHandler(clientOptions.jsonMapper) @@ -287,6 +447,48 @@ class SessionServiceImpl internal constructor(private val clientOptions: ClientO } } + private val observeStreamingHandler: Handler> = + sseHandler(clientOptions.jsonMapper).mapJson() + + override fun observeStreaming( + params: SessionObserveParams, + requestOptions: RequestOptions, + ): HttpResponseFor> { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("id", params.id().getOrNull()) + val request = + HttpRequest.builder() + .method(HttpMethod.POST) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("v1", "sessions", params._pathParam(0), "observe") + .body( + json( + clientOptions.jsonMapper, + params + ._body() + .toBuilder() + .putAdditionalProperty("streamResponse", JsonValue.from(true)) + .build(), + ) + ) + .build() + .prepare(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.execute(request, requestOptions) + return errorHandler.handle(response).parseable { + response + .let { observeStreamingHandler.handle(it) } + .let { streamResponse -> + if (requestOptions.responseValidation!!) { + streamResponse.map { it.validate() } + } else { + streamResponse + } + } + } + } + private val startHandler: Handler = jsonHandler(clientOptions.jsonMapper) diff --git a/stagehand-java-core/src/test/kotlin/com/browserbase/api/core/handlers/SseHandlerTest.kt b/stagehand-java-core/src/test/kotlin/com/browserbase/api/core/handlers/SseHandlerTest.kt new file mode 100644 index 0000000..29105f3 --- /dev/null +++ b/stagehand-java-core/src/test/kotlin/com/browserbase/api/core/handlers/SseHandlerTest.kt @@ -0,0 +1,134 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.browserbase.api.core.handlers + +import com.browserbase.api.core.http.Headers +import com.browserbase.api.core.http.HttpResponse +import com.browserbase.api.core.http.SseMessage +import com.browserbase.api.core.jsonMapper +import java.io.InputStream +import java.util.stream.Collectors.toList +import org.assertj.core.api.Assertions.assertThat +import org.assertj.core.api.Assertions.catchThrowable +import org.junit.jupiter.api.Test +import org.junit.jupiter.params.ParameterizedTest +import org.junit.jupiter.params.provider.EnumSource + +internal class SseHandlerTest { + + enum class TestCase( + internal val body: String, + internal val expectedMessages: List? = null, + internal val expectedException: Exception? = null, + ) { + DATA_MISSING_EVENT( + buildString { + append("data: {\"foo\":true}\n") + append("\n") + }, + listOf(sseMessageBuilder().data("{\"foo\":true}").build()), + ), + MULTIPLE_DATA_MISSING_EVENT( + buildString { + append("data: {\"foo\":true}\n") + append("\n") + append("data: {\"bar\":false}\n") + append("\n") + }, + listOf( + sseMessageBuilder().data("{\"foo\":true}").build(), + sseMessageBuilder().data("{\"bar\":false}").build(), + ), + ), + DATA_JSON_ESCAPED_DOUBLE_NEW_LINE( + buildString { + append("data: {\n") + append("data: \"foo\":\n") + append("data: true}\n") + append("\n\n") + }, + listOf(sseMessageBuilder().data("{\n\"foo\":\ntrue}").build()), + ), + MULTIPLE_DATA_LINES( + buildString { + append("data: {\n") + append("data: \"foo\":\n") + append("data: true}\n") + append("\n\n") + }, + listOf(sseMessageBuilder().data("{\n\"foo\":\ntrue}").build()), + ), + SPECIAL_NEW_LINE_CHARACTER( + buildString { + append("data: {\"content\":\" culpa\"}\n") + append("\n") + append("data: {\"content\":\" \u2028\"}\n") + append("\n") + append("data: {\"content\":\"foo\"}\n") + append("\n") + }, + listOf( + sseMessageBuilder().data("{\"content\":\" culpa\"}").build(), + sseMessageBuilder().data("{\"content\":\" \u2028\"}").build(), + sseMessageBuilder().data("{\"content\":\"foo\"}").build(), + ), + ), + MULTI_BYTE_CHARACTER( + buildString { + append("data: {\"content\":\"\u0438\u0437\u0432\u0435\u0441\u0442\u043d\u0438\"}\n") + append("\n") + }, + listOf(sseMessageBuilder().data("{\"content\":\"известни\"}").build()), + ), + } + + @ParameterizedTest + @EnumSource + fun handle(testCase: TestCase) { + val response = httpResponse(testCase.body) + var messages: List? = null + var exception: Exception? = null + + try { + messages = + sseHandler(jsonMapper()).handle(response).use { it.stream().collect(toList()) } + } catch (e: Exception) { + exception = e + } + + if (testCase.expectedMessages != null) { + assertThat(messages).containsExactlyElementsOf(testCase.expectedMessages) + } + if (testCase.expectedException != null) { + assertThat(exception).isInstanceOf(testCase.expectedException.javaClass) + assertThat(exception).hasMessage(testCase.expectedException.message) + } + } + + @Test + fun cannotReuseStream() { + val response = httpResponse("body") + val streamResponse = sseHandler(jsonMapper()).handle(response) + + val throwable = + streamResponse.use { + it.stream().collect(toList()) + catchThrowable { it.stream().collect(toList()) } + } + + assertThat(throwable).isInstanceOf(IllegalStateException::class.java) + } +} + +private fun httpResponse(body: String): HttpResponse = + object : HttpResponse { + override fun statusCode(): Int = 0 + + override fun headers(): Headers = Headers.builder().build() + + override fun body(): InputStream = body.toByteArray().inputStream() + + override fun close() {} + } + +private fun sseMessageBuilder() = SseMessage.builder().jsonMapper(jsonMapper()) diff --git a/stagehand-java-core/src/test/kotlin/com/browserbase/api/core/handlers/StreamHandlerTest.kt b/stagehand-java-core/src/test/kotlin/com/browserbase/api/core/handlers/StreamHandlerTest.kt new file mode 100644 index 0000000..7da5378 --- /dev/null +++ b/stagehand-java-core/src/test/kotlin/com/browserbase/api/core/handlers/StreamHandlerTest.kt @@ -0,0 +1,94 @@ +package com.browserbase.api.core.handlers + +import com.browserbase.api.core.http.Headers +import com.browserbase.api.core.http.HttpResponse +import com.browserbase.api.errors.StagehandIoException +import java.io.IOException +import java.io.InputStream +import kotlin.streams.asSequence +import kotlin.test.Test +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.assertThrows + +internal class StreamHandlerTest { + + @Test + fun streamHandler_splitsStreamOnNewlines() { + val handler = streamHandler { _, lines -> yieldAll(lines) } + val streamResponse = handler.handle(httpResponse("a\nbb\nccc\ndddd".byteInputStream())) + + val lines = streamResponse.stream().asSequence().toList() + + assertThat(lines).containsExactly("a", "bb", "ccc", "dddd") + } + + @Test + fun streamHandler_whenClosedEarly_stopsYielding() { + val handler = streamHandler { _, lines -> yieldAll(lines) } + val streamResponse = handler.handle(httpResponse("a\nbb\nccc\ndddd".byteInputStream())) + + val lines = + streamResponse + .stream() + .asSequence() + .onEach { + if (it == "bb") { + streamResponse.close() + } + } + .toList() + + assertThat(lines).containsExactly("a", "bb") + } + + @Test + fun streamHandler_whenReaderThrowsIOException_wrapsException() { + val handler = streamHandler { _, lines -> lines.forEach {} } + val streamResponse = handler.handle(httpResponse("a\nb\nc\n".byteInputStream().throwing())) + + val e = assertThrows { streamResponse.stream().forEach {} } + assertThat(e).hasMessage("Stream failed") + assertThat(e).hasCauseInstanceOf(IOException::class.java) + } + + @Test + fun streamHandler_whenBlockThrowsIOException_doesNotWrapException() { + val ioException = IOException("BOOM!") + val handler = + streamHandler { _, lines -> + lines.forEachIndexed { index, _ -> + if (index == 2) { + throw ioException + } + } + } + val streamResponse = handler.handle(httpResponse("a\nb\nc\n".byteInputStream())) + + val e = assertThrows { streamResponse.stream().forEach {} } + assertThat(e).isSameAs(ioException) + } + + private fun httpResponse(body: InputStream): HttpResponse = + object : HttpResponse { + + override fun statusCode(): Int = 0 + + override fun headers(): Headers = Headers.builder().build() + + override fun body(): InputStream = body + + override fun close() {} + } + + private fun InputStream.throwing(): InputStream = + object : InputStream() { + + override fun read(): Int { + val byte = this@throwing.read() + if (byte == -1) { + throw IOException("BOOM!") + } + return byte + } + } +} diff --git a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionNavigateParamsTest.kt b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionNavigateParamsTest.kt index 3bba7d4..169d089 100644 --- a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionNavigateParamsTest.kt +++ b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionNavigateParamsTest.kt @@ -26,6 +26,7 @@ internal class SessionNavigateParamsTest { .waitUntil(SessionNavigateParams.Options.WaitUntil.NETWORKIDLE) .build() ) + .streamResponse(true) .build() } @@ -60,6 +61,7 @@ internal class SessionNavigateParamsTest { .waitUntil(SessionNavigateParams.Options.WaitUntil.NETWORKIDLE) .build() ) + .streamResponse(true) .build() val headers = params._headers() @@ -106,6 +108,7 @@ internal class SessionNavigateParamsTest { .waitUntil(SessionNavigateParams.Options.WaitUntil.NETWORKIDLE) .build() ) + .streamResponse(true) .build() val body = params._body() @@ -120,6 +123,7 @@ internal class SessionNavigateParamsTest { .waitUntil(SessionNavigateParams.Options.WaitUntil.NETWORKIDLE) .build() ) + assertThat(body.streamResponse()).contains(true) } @Test diff --git a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionStartResponseTest.kt b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionStartResponseTest.kt index 3af1696..4a712ec 100644 --- a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionStartResponseTest.kt +++ b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionStartResponseTest.kt @@ -16,6 +16,7 @@ internal class SessionStartResponseTest { .data( SessionStartResponse.Data.builder() .available(true) + .connectUrl("wss://connect.browserbase.com/?signingKey=abc123") .sessionId("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") .build() ) @@ -26,6 +27,7 @@ internal class SessionStartResponseTest { .isEqualTo( SessionStartResponse.Data.builder() .available(true) + .connectUrl("wss://connect.browserbase.com/?signingKey=abc123") .sessionId("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") .build() ) @@ -40,6 +42,7 @@ internal class SessionStartResponseTest { .data( SessionStartResponse.Data.builder() .available(true) + .connectUrl("wss://connect.browserbase.com/?signingKey=abc123") .sessionId("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") .build() ) diff --git a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/StreamEventTest.kt b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/StreamEventTest.kt new file mode 100644 index 0000000..9d58bf8 --- /dev/null +++ b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/StreamEventTest.kt @@ -0,0 +1,66 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.browserbase.api.models.sessions + +import com.browserbase.api.core.JsonValue +import com.browserbase.api.core.jsonMapper +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class StreamEventTest { + + @Test + fun create() { + val streamEvent = + StreamEvent.builder() + .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") + .data( + StreamEvent.Data.StreamEventSystemDataOutput.builder() + .status(StreamEvent.Data.StreamEventSystemDataOutput.Status.STARTING) + .error("error") + .result(JsonValue.from(mapOf())) + .build() + ) + .type(StreamEvent.Type.SYSTEM) + .build() + + assertThat(streamEvent.id()).isEqualTo("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") + assertThat(streamEvent.data()) + .isEqualTo( + StreamEvent.Data.ofStreamEventSystemDataOutput( + StreamEvent.Data.StreamEventSystemDataOutput.builder() + .status(StreamEvent.Data.StreamEventSystemDataOutput.Status.STARTING) + .error("error") + .result(JsonValue.from(mapOf())) + .build() + ) + ) + assertThat(streamEvent.type()).isEqualTo(StreamEvent.Type.SYSTEM) + } + + @Test + fun roundtrip() { + val jsonMapper = jsonMapper() + val streamEvent = + StreamEvent.builder() + .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") + .data( + StreamEvent.Data.StreamEventSystemDataOutput.builder() + .status(StreamEvent.Data.StreamEventSystemDataOutput.Status.STARTING) + .error("error") + .result(JsonValue.from(mapOf())) + .build() + ) + .type(StreamEvent.Type.SYSTEM) + .build() + + val roundtrippedStreamEvent = + jsonMapper.readValue( + jsonMapper.writeValueAsString(streamEvent), + jacksonTypeRef(), + ) + + assertThat(roundtrippedStreamEvent).isEqualTo(streamEvent) + } +} diff --git a/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/async/SessionServiceAsyncTest.kt b/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/async/SessionServiceAsyncTest.kt index 270a06b..78ba6e7 100644 --- a/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/async/SessionServiceAsyncTest.kt +++ b/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/async/SessionServiceAsyncTest.kt @@ -60,6 +60,47 @@ internal class SessionServiceAsyncTest { response.validate() } + @Disabled("Prism tests are disabled") + @Test + fun actStreaming() { + val client = + StagehandOkHttpClientAsync.builder() + .baseUrl(TestServerExtension.BASE_URL) + .browserbaseApiKey("My Browserbase API Key") + .browserbaseProjectId("My Browserbase Project ID") + .modelApiKey("My Model API Key") + .build() + val sessionServiceAsync = client.sessions() + + val responseStreamResponse = + sessionServiceAsync.actStreaming( + SessionActParams.builder() + .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") + .xLanguage(SessionActParams.XLanguage.TYPESCRIPT) + .xSdkVersion("3.0.6") + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00Z")) + .xStreamResponse(SessionActParams.XStreamResponse.TRUE) + .input("Click the login button") + .frameId("frameId") + .options( + SessionActParams.Options.builder() + .model("openai/gpt-5-nano") + .timeout(30000.0) + .variables( + SessionActParams.Options.Variables.builder() + .putAdditionalProperty("username", JsonValue.from("john_doe")) + .build() + ) + .build() + ) + .build() + ) + + val onCompleteFuture = + responseStreamResponse.subscribe { response -> response.validate() }.onCompleteFuture() + onCompleteFuture.get() + } + @Disabled("Prism tests are disabled") @Test fun end() { @@ -131,6 +172,51 @@ internal class SessionServiceAsyncTest { response.validate() } + @Disabled("Prism tests are disabled") + @Test + fun executeStreaming() { + val client = + StagehandOkHttpClientAsync.builder() + .baseUrl(TestServerExtension.BASE_URL) + .browserbaseApiKey("My Browserbase API Key") + .browserbaseProjectId("My Browserbase Project ID") + .modelApiKey("My Model API Key") + .build() + val sessionServiceAsync = client.sessions() + + val responseStreamResponse = + sessionServiceAsync.executeStreaming( + SessionExecuteParams.builder() + .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") + .xLanguage(SessionExecuteParams.XLanguage.TYPESCRIPT) + .xSdkVersion("3.0.6") + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00Z")) + .xStreamResponse(SessionExecuteParams.XStreamResponse.TRUE) + .agentConfig( + SessionExecuteParams.AgentConfig.builder() + .cua(true) + .model("openai/gpt-5-nano") + .systemPrompt("systemPrompt") + .build() + ) + .executeOptions( + SessionExecuteParams.ExecuteOptions.builder() + .instruction( + "Log in with username 'demo' and password 'test123', then navigate to settings" + ) + .highlightCursor(true) + .maxSteps(20.0) + .build() + ) + .frameId("frameId") + .build() + ) + + val onCompleteFuture = + responseStreamResponse.subscribe { response -> response.validate() }.onCompleteFuture() + onCompleteFuture.get() + } + @Disabled("Prism tests are disabled") @Test fun extract() { @@ -172,6 +258,48 @@ internal class SessionServiceAsyncTest { response.validate() } + @Disabled("Prism tests are disabled") + @Test + fun extractStreaming() { + val client = + StagehandOkHttpClientAsync.builder() + .baseUrl(TestServerExtension.BASE_URL) + .browserbaseApiKey("My Browserbase API Key") + .browserbaseProjectId("My Browserbase Project ID") + .modelApiKey("My Model API Key") + .build() + val sessionServiceAsync = client.sessions() + + val responseStreamResponse = + sessionServiceAsync.extractStreaming( + SessionExtractParams.builder() + .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") + .xLanguage(SessionExtractParams.XLanguage.TYPESCRIPT) + .xSdkVersion("3.0.6") + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00Z")) + .xStreamResponse(SessionExtractParams.XStreamResponse.TRUE) + .frameId("frameId") + .instruction("Extract all product names and prices from the page") + .options( + SessionExtractParams.Options.builder() + .model("openai/gpt-5-nano") + .selector("#main-content") + .timeout(30000.0) + .build() + ) + .schema( + SessionExtractParams.Schema.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) + .build() + ) + + val onCompleteFuture = + responseStreamResponse.subscribe { response -> response.validate() }.onCompleteFuture() + onCompleteFuture.get() + } + @Disabled("Prism tests are disabled") @Test fun navigate() { @@ -201,6 +329,7 @@ internal class SessionServiceAsyncTest { .waitUntil(SessionNavigateParams.Options.WaitUntil.NETWORKIDLE) .build() ) + .streamResponse(true) .build() ) @@ -244,6 +373,43 @@ internal class SessionServiceAsyncTest { response.validate() } + @Disabled("Prism tests are disabled") + @Test + fun observeStreaming() { + val client = + StagehandOkHttpClientAsync.builder() + .baseUrl(TestServerExtension.BASE_URL) + .browserbaseApiKey("My Browserbase API Key") + .browserbaseProjectId("My Browserbase Project ID") + .modelApiKey("My Model API Key") + .build() + val sessionServiceAsync = client.sessions() + + val responseStreamResponse = + sessionServiceAsync.observeStreaming( + SessionObserveParams.builder() + .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") + .xLanguage(SessionObserveParams.XLanguage.TYPESCRIPT) + .xSdkVersion("3.0.6") + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00Z")) + .xStreamResponse(SessionObserveParams.XStreamResponse.TRUE) + .frameId("frameId") + .instruction("Find all clickable navigation links") + .options( + SessionObserveParams.Options.builder() + .model("openai/gpt-5-nano") + .selector("nav") + .timeout(30000.0) + .build() + ) + .build() + ) + + val onCompleteFuture = + responseStreamResponse.subscribe { response -> response.validate() }.onCompleteFuture() + onCompleteFuture.get() + } + @Disabled("Prism tests are disabled") @Test fun start() { diff --git a/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/blocking/SessionServiceTest.kt b/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/blocking/SessionServiceTest.kt index af06455..3355c14 100644 --- a/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/blocking/SessionServiceTest.kt +++ b/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/blocking/SessionServiceTest.kt @@ -59,6 +59,47 @@ internal class SessionServiceTest { response.validate() } + @Disabled("Prism tests are disabled") + @Test + fun actStreaming() { + val client = + StagehandOkHttpClient.builder() + .baseUrl(TestServerExtension.BASE_URL) + .browserbaseApiKey("My Browserbase API Key") + .browserbaseProjectId("My Browserbase Project ID") + .modelApiKey("My Model API Key") + .build() + val sessionService = client.sessions() + + val responseStreamResponse = + sessionService.actStreaming( + SessionActParams.builder() + .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") + .xLanguage(SessionActParams.XLanguage.TYPESCRIPT) + .xSdkVersion("3.0.6") + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00Z")) + .xStreamResponse(SessionActParams.XStreamResponse.TRUE) + .input("Click the login button") + .frameId("frameId") + .options( + SessionActParams.Options.builder() + .model("openai/gpt-5-nano") + .timeout(30000.0) + .variables( + SessionActParams.Options.Variables.builder() + .putAdditionalProperty("username", JsonValue.from("john_doe")) + .build() + ) + .build() + ) + .build() + ) + + responseStreamResponse.use { + responseStreamResponse.stream().forEach { response -> response.validate() } + } + } + @Disabled("Prism tests are disabled") @Test fun end() { @@ -128,6 +169,51 @@ internal class SessionServiceTest { response.validate() } + @Disabled("Prism tests are disabled") + @Test + fun executeStreaming() { + val client = + StagehandOkHttpClient.builder() + .baseUrl(TestServerExtension.BASE_URL) + .browserbaseApiKey("My Browserbase API Key") + .browserbaseProjectId("My Browserbase Project ID") + .modelApiKey("My Model API Key") + .build() + val sessionService = client.sessions() + + val responseStreamResponse = + sessionService.executeStreaming( + SessionExecuteParams.builder() + .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") + .xLanguage(SessionExecuteParams.XLanguage.TYPESCRIPT) + .xSdkVersion("3.0.6") + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00Z")) + .xStreamResponse(SessionExecuteParams.XStreamResponse.TRUE) + .agentConfig( + SessionExecuteParams.AgentConfig.builder() + .cua(true) + .model("openai/gpt-5-nano") + .systemPrompt("systemPrompt") + .build() + ) + .executeOptions( + SessionExecuteParams.ExecuteOptions.builder() + .instruction( + "Log in with username 'demo' and password 'test123', then navigate to settings" + ) + .highlightCursor(true) + .maxSteps(20.0) + .build() + ) + .frameId("frameId") + .build() + ) + + responseStreamResponse.use { + responseStreamResponse.stream().forEach { response -> response.validate() } + } + } + @Disabled("Prism tests are disabled") @Test fun extract() { @@ -168,6 +254,48 @@ internal class SessionServiceTest { response.validate() } + @Disabled("Prism tests are disabled") + @Test + fun extractStreaming() { + val client = + StagehandOkHttpClient.builder() + .baseUrl(TestServerExtension.BASE_URL) + .browserbaseApiKey("My Browserbase API Key") + .browserbaseProjectId("My Browserbase Project ID") + .modelApiKey("My Model API Key") + .build() + val sessionService = client.sessions() + + val responseStreamResponse = + sessionService.extractStreaming( + SessionExtractParams.builder() + .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") + .xLanguage(SessionExtractParams.XLanguage.TYPESCRIPT) + .xSdkVersion("3.0.6") + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00Z")) + .xStreamResponse(SessionExtractParams.XStreamResponse.TRUE) + .frameId("frameId") + .instruction("Extract all product names and prices from the page") + .options( + SessionExtractParams.Options.builder() + .model("openai/gpt-5-nano") + .selector("#main-content") + .timeout(30000.0) + .build() + ) + .schema( + SessionExtractParams.Schema.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) + .build() + ) + + responseStreamResponse.use { + responseStreamResponse.stream().forEach { response -> response.validate() } + } + } + @Disabled("Prism tests are disabled") @Test fun navigate() { @@ -197,6 +325,7 @@ internal class SessionServiceTest { .waitUntil(SessionNavigateParams.Options.WaitUntil.NETWORKIDLE) .build() ) + .streamResponse(true) .build() ) @@ -238,6 +367,43 @@ internal class SessionServiceTest { response.validate() } + @Disabled("Prism tests are disabled") + @Test + fun observeStreaming() { + val client = + StagehandOkHttpClient.builder() + .baseUrl(TestServerExtension.BASE_URL) + .browserbaseApiKey("My Browserbase API Key") + .browserbaseProjectId("My Browserbase Project ID") + .modelApiKey("My Model API Key") + .build() + val sessionService = client.sessions() + + val responseStreamResponse = + sessionService.observeStreaming( + SessionObserveParams.builder() + .id("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") + .xLanguage(SessionObserveParams.XLanguage.TYPESCRIPT) + .xSdkVersion("3.0.6") + .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00Z")) + .xStreamResponse(SessionObserveParams.XStreamResponse.TRUE) + .frameId("frameId") + .instruction("Find all clickable navigation links") + .options( + SessionObserveParams.Options.builder() + .model("openai/gpt-5-nano") + .selector("nav") + .timeout(30000.0) + .build() + ) + .build() + ) + + responseStreamResponse.use { + responseStreamResponse.stream().forEach { response -> response.validate() } + } + } + @Disabled("Prism tests are disabled") @Test fun start() { From d9e462c24ed6d3e165a5873e7f70f011d768500a Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 19 Dec 2025 23:35:48 +0000 Subject: [PATCH 13/18] feat(api): manual updates --- .stats.yml | 4 +- .../browserbase/api/models/sessions/Action.kt | 47 ++- .../api/models/sessions/ModelConfig.kt | 190 ++++++++- .../api/models/sessions/SessionActResponse.kt | 360 +++++++++++++++++ .../models/sessions/SessionExecuteParams.kt | 187 ++++++++- .../models/sessions/SessionObserveResponse.kt | 375 +++++++++++++++++- .../api/models/sessions/SessionStartParams.kt | 240 +++++++---- .../models/sessions/SessionStartResponse.kt | 84 ++-- .../api/models/sessions/StreamEvent.kt | 5 +- .../api/models/sessions/ActionTest.kt | 3 + .../api/models/sessions/ModelConfigTest.kt | 2 + .../models/sessions/SessionActResponseTest.kt | 9 +- .../sessions/SessionExecuteParamsTest.kt | 4 + .../sessions/SessionObserveResponseTest.kt | 9 +- .../models/sessions/SessionStartParamsTest.kt | 20 +- .../sessions/SessionStartResponseTest.kt | 6 +- .../api/services/ErrorHandlingTest.kt | 85 ++-- .../api/services/ServiceParamsTest.kt | 5 +- .../services/async/SessionServiceAsyncTest.kt | 7 +- .../services/blocking/SessionServiceTest.kt | 7 +- .../api/proguard/ProGuardCompatibilityTest.kt | 1 + 21 files changed, 1424 insertions(+), 226 deletions(-) diff --git a/.stats.yml b/.stats.yml index 5dba58c..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-f7d6b6489159f611a2bfdc267ce0a6fc0455bed1ffa0c310044baaa5d8381b9b.yml -openapi_spec_hash: cd88d8068abfde8382da0bed674e440c +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/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/Action.kt b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/Action.kt index e9ae4bc..2ce760b 100644 --- a/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/Action.kt +++ b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/Action.kt @@ -26,6 +26,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, ) { @@ -39,8 +40,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 @@ -66,6 +70,14 @@ private constructor( */ fun arguments(): Optional> = arguments.getOptional("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(): Optional = backendNodeId.getOptional("backendNodeId") + /** * The method to execute (click, fill, etc.) * @@ -95,6 +107,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]. * @@ -134,6 +155,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() @@ -142,6 +164,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() } @@ -195,6 +218,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)) @@ -243,6 +280,7 @@ private constructor( checkRequired("description", description), checkRequired("selector", selector), (arguments ?: JsonMissing.of()).map { it.toImmutable() }, + backendNodeId, method, additionalProperties.toMutableMap(), ) @@ -258,6 +296,7 @@ private constructor( description() selector() arguments() + backendNodeId() method() validated = true } @@ -280,6 +319,7 @@ private constructor( (if (description.asKnown().isPresent) 1 else 0) + (if (selector.asKnown().isPresent) 1 else 0) + (arguments.asKnown().getOrNull()?.size ?: 0) + + (if (backendNodeId.asKnown().isPresent) 1 else 0) + (if (method.asKnown().isPresent) 1 else 0) override fun equals(other: Any?): Boolean { @@ -291,16 +331,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-java-core/src/main/kotlin/com/browserbase/api/models/sessions/ModelConfig.kt b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/ModelConfig.kt index e416a06..bfbf0aa 100644 --- a/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/ModelConfig.kt +++ b/stagehand-java-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,6 +27,7 @@ import com.fasterxml.jackson.module.kotlin.jacksonTypeRef import java.util.Collections import java.util.Objects import java.util.Optional +import kotlin.jvm.optionals.getOrNull /** * Model name string with provider prefix (e.g., 'openai/gpt-5-nano', 'anthropic/claude-4.5-opus') @@ -224,6 +226,7 @@ private constructor( private val modelName: JsonField, private val apiKey: JsonField, private val baseUrl: JsonField, + private val provider: JsonField, private val additionalProperties: MutableMap, ) { @@ -234,7 +237,10 @@ 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') @@ -260,6 +266,14 @@ private constructor( */ fun baseUrl(): Optional = baseUrl.getOptional("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(): Optional = provider.getOptional("provider") + /** * Returns the raw JSON value of [modelName]. * @@ -281,6 +295,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) @@ -312,6 +333,7 @@ private 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() @JvmSynthetic @@ -319,6 +341,7 @@ private constructor( modelName = modelConfigObject.modelName apiKey = modelConfigObject.apiKey baseUrl = modelConfigObject.baseUrl + provider = modelConfigObject.provider additionalProperties = modelConfigObject.additionalProperties.toMutableMap() } @@ -358,6 +381,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) @@ -394,6 +429,7 @@ private constructor( checkRequired("modelName", modelName), apiKey, baseUrl, + provider, additionalProperties.toMutableMap(), ) } @@ -408,6 +444,7 @@ private constructor( modelName() apiKey() baseUrl() + provider().ifPresent { it.validate() } validated = true } @@ -429,7 +466,151 @@ private constructor( internal fun validity(): Int = (if (modelName.asKnown().isPresent) 1 else 0) + (if (apiKey.asKnown().isPresent) 1 else 0) + - (if (baseUrl.asKnown().isPresent) 1 else 0) + (if (baseUrl.asKnown().isPresent) 1 else 0) + + (provider.asKnown().getOrNull()?.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 { + + @JvmField val OPENAI = of("openai") + + @JvmField val ANTHROPIC = of("anthropic") + + @JvmField val GOOGLE = of("google") + + @JvmField val MICROSOFT = of("microsoft") + + @JvmStatic 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().orElseThrow { + 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. + */ + @JvmSynthetic 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) { @@ -440,16 +621,17 @@ private constructor( 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() = - "ModelConfigObject{modelName=$modelName, apiKey=$apiKey, baseUrl=$baseUrl, additionalProperties=$additionalProperties}" + "ModelConfigObject{modelName=$modelName, apiKey=$apiKey, baseUrl=$baseUrl, provider=$provider, additionalProperties=$additionalProperties}" } } diff --git a/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionActResponse.kt b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionActResponse.kt index db27614..62bec51 100644 --- a/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionActResponse.kt +++ b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionActResponse.kt @@ -649,6 +649,366 @@ private constructor( (if (message.asKnown().isPresent) 1 else 0) + (if (success.asKnown().isPresent) 1 else 0) + /** 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(): Optional> = arguments.getOptional("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(): Optional = backendNodeId.getOptional("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(): Optional = method.getOptional("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: + * ```java + * .description() + * .selector() + * ``` + */ + @JvmStatic 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() + + @JvmSynthetic + 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: + * ```java + * .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. + */ + @JvmSynthetic + internal fun validity(): Int = + (if (description.asKnown().isPresent) 1 else 0) + + (if (selector.asKnown().isPresent) 1 else 0) + + (arguments.asKnown().getOrNull()?.size ?: 0) + + (if (backendNodeId.asKnown().isPresent) 1 else 0) + + (if (method.asKnown().isPresent) 1 else 0) + + 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 diff --git a/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionExecuteParams.kt b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionExecuteParams.kt index 73880ff..8cb0da8 100644 --- a/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionExecuteParams.kt +++ b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionExecuteParams.kt @@ -635,6 +635,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, ) { @@ -643,10 +644,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 @@ -665,6 +669,14 @@ private constructor( */ fun model(): Optional = model.getOptional("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(): Optional = provider.getOptional("provider") + /** * Custom system prompt for the agent * @@ -687,6 +699,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]. * @@ -720,6 +739,7 @@ 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() @@ -727,6 +747,7 @@ private constructor( internal fun from(agentConfig: AgentConfig) = apply { cua = agentConfig.cua model = agentConfig.model + provider = agentConfig.provider systemPrompt = agentConfig.systemPrompt additionalProperties = agentConfig.additionalProperties.toMutableMap() } @@ -767,6 +788,18 @@ private constructor( 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)) + + /** + * 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)) @@ -806,7 +839,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 @@ -818,6 +851,7 @@ private constructor( cua() model().ifPresent { it.validate() } + provider().ifPresent { it.validate() } systemPrompt() validated = true } @@ -840,8 +874,152 @@ private constructor( internal fun validity(): Int = (if (cua.asKnown().isPresent) 1 else 0) + (model.asKnown().getOrNull()?.validity() ?: 0) + + (provider.asKnown().getOrNull()?.validity() ?: 0) + (if (systemPrompt.asKnown().isPresent) 1 else 0) + /** 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 { + + @JvmField val OPENAI = of("openai") + + @JvmField val ANTHROPIC = of("anthropic") + + @JvmField val GOOGLE = of("google") + + @JvmField val MICROSOFT = of("microsoft") + + @JvmStatic 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().orElseThrow { + 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. + */ + @JvmSynthetic 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 @@ -850,18 +1028,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-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionObserveResponse.kt b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionObserveResponse.kt index cb2404e..9c1c551 100644 --- a/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionObserveResponse.kt +++ b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionObserveResponse.kt @@ -194,7 +194,7 @@ private constructor( class Data @JsonCreator(mode = JsonCreator.Mode.DISABLED) private constructor( - private val result: JsonField>, + private val result: JsonField>, private val actionId: JsonField, private val additionalProperties: MutableMap, ) { @@ -203,7 +203,7 @@ private constructor( private constructor( @JsonProperty("result") @ExcludeMissing - result: JsonField> = JsonMissing.of(), + result: JsonField> = JsonMissing.of(), @JsonProperty("actionId") @ExcludeMissing actionId: JsonField = JsonMissing.of(), ) : this(result, actionId, mutableMapOf()) @@ -211,7 +211,7 @@ private constructor( * @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 result(): List = result.getRequired("result") + fun result(): List = result.getRequired("result") /** * Action ID for tracking @@ -226,7 +226,7 @@ private constructor( * * Unlike [result], this method doesn't throw if the JSON field has an unexpected type. */ - @JsonProperty("result") @ExcludeMissing fun _result(): JsonField> = result + @JsonProperty("result") @ExcludeMissing fun _result(): JsonField> = result /** * Returns the raw JSON value of [actionId]. @@ -263,7 +263,7 @@ private constructor( /** A builder for [Data]. */ class Builder internal constructor() { - private var result: JsonField>? = null + private var result: JsonField>? = null private var actionId: JsonField = JsonMissing.of() private var additionalProperties: MutableMap = mutableMapOf() @@ -274,25 +274,25 @@ private constructor( additionalProperties = data.additionalProperties.toMutableMap() } - fun result(result: List) = result(JsonField.of(result)) + fun result(result: List) = result(JsonField.of(result)) /** * Sets [Builder.result] to an arbitrary JSON value. * - * You should usually call [Builder.result] with a well-typed `List` value + * You should usually call [Builder.result] with a well-typed `List` value * instead. This method is primarily for setting the field to an undocumented or not yet * supported value. */ - fun result(result: JsonField>) = apply { + fun result(result: JsonField>) = apply { this.result = result.map { it.toMutableList() } } /** - * Adds a single [Action] to [Builder.result]. + * Adds a single [Result] to [Builder.result]. * * @throws IllegalStateException if the field was previously set to a non-list. */ - fun addResult(result: Action) = apply { + fun addResult(result: Result) = apply { this.result = (this.result ?: JsonField.of(mutableListOf())).also { checkKnown("result", it).add(result) @@ -381,6 +381,361 @@ private constructor( (result.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + (if (actionId.asKnown().isPresent) 1 else 0) + /** Action object returned by observe and used by act */ + class Result + @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(): Optional> = arguments.getOptional("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(): Optional = backendNodeId.getOptional("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(): Optional = method.getOptional("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 [Result]. + * + * The following fields are required: + * ```java + * .description() + * .selector() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Result]. */ + 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() + + @JvmSynthetic + internal fun from(result: Result) = apply { + description = result.description + selector = result.selector + arguments = result.arguments.map { it.toMutableList() } + backendNodeId = result.backendNodeId + method = result.method + additionalProperties = result.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 [Result]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .description() + * .selector() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): Result = + Result( + checkRequired("description", description), + checkRequired("selector", selector), + (arguments ?: JsonMissing.of()).map { it.toImmutable() }, + backendNodeId, + method, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): Result = 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. + */ + @JvmSynthetic + internal fun validity(): Int = + (if (description.asKnown().isPresent) 1 else 0) + + (if (selector.asKnown().isPresent) 1 else 0) + + (arguments.asKnown().getOrNull()?.size ?: 0) + + (if (backendNodeId.asKnown().isPresent) 1 else 0) + + (if (method.asKnown().isPresent) 1 else 0) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Result && + 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() = + "Result{description=$description, selector=$selector, arguments=$arguments, backendNodeId=$backendNodeId, method=$method, additionalProperties=$additionalProperties}" + } + override fun equals(other: Any?): Boolean { if (this === other) { return true diff --git a/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionStartParams.kt b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionStartParams.kt index 16eecb4..ca9fdd1 100644 --- a/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionStartParams.kt +++ b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionStartParams.kt @@ -72,7 +72,7 @@ private constructor( fun modelName(): String = body.modelName() /** - * Timeout in ms for act operations + * Timeout in ms for act operations (deprecated, v2 only) * * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). @@ -100,12 +100,6 @@ private constructor( */ fun browserbaseSessionId(): Optional = body.browserbaseSessionId() - /** - * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if the - * server responded with an unexpected value). - */ - fun debugDom(): Optional = body.debugDom() - /** * Timeout in ms to wait for DOM to settle * @@ -142,9 +136,11 @@ private constructor( * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). */ - fun verbose(): Optional = body.verbose() + fun verbose(): Optional = body.verbose() /** + * Wait for captcha solves (deprecated, v2 only) + * * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). */ @@ -188,13 +184,6 @@ private constructor( */ fun _browserbaseSessionId(): JsonField = body._browserbaseSessionId() - /** - * Returns the raw JSON value of [debugDom]. - * - * Unlike [debugDom], this method doesn't throw if the JSON field has an unexpected type. - */ - fun _debugDom(): JsonField = body._debugDom() - /** * Returns the raw JSON value of [domSettleTimeoutMs]. * @@ -229,7 +218,7 @@ private constructor( * * Unlike [verbose], this method doesn't throw if the JSON field has an unexpected type. */ - fun _verbose(): JsonField = body._verbose() + fun _verbose(): JsonField = body._verbose() /** * Returns the raw JSON value of [waitForCaptchaSolves]. @@ -337,7 +326,7 @@ private constructor( */ fun modelName(modelName: JsonField) = apply { body.modelName(modelName) } - /** Timeout in ms for act operations */ + /** Timeout in ms for act operations (deprecated, v2 only) */ fun actTimeoutMs(actTimeoutMs: Double) = apply { body.actTimeoutMs(actTimeoutMs) } /** @@ -392,17 +381,6 @@ private constructor( body.browserbaseSessionId(browserbaseSessionId) } - fun debugDom(debugDom: Boolean) = apply { body.debugDom(debugDom) } - - /** - * Sets [Builder.debugDom] to an arbitrary JSON value. - * - * You should usually call [Builder.debugDom] with a well-typed [Boolean] value instead. - * This method is primarily for setting the field to an undocumented or not yet supported - * value. - */ - fun debugDom(debugDom: JsonField) = apply { body.debugDom(debugDom) } - /** Timeout in ms to wait for DOM to settle */ fun domSettleTimeoutMs(domSettleTimeoutMs: Double) = apply { body.domSettleTimeoutMs(domSettleTimeoutMs) @@ -459,16 +437,17 @@ private constructor( } /** Logging verbosity level (0=quiet, 1=normal, 2=debug) */ - fun verbose(verbose: Long) = apply { body.verbose(verbose) } + fun verbose(verbose: Verbose) = apply { body.verbose(verbose) } /** * Sets [Builder.verbose] to an arbitrary JSON value. * - * You should usually call [Builder.verbose] with a well-typed [Long] value instead. This + * You should usually call [Builder.verbose] with a well-typed [Verbose] value instead. This * method is primarily for setting the field to an undocumented or not yet supported value. */ - fun verbose(verbose: JsonField) = apply { body.verbose(verbose) } + fun verbose(verbose: JsonField) = apply { body.verbose(verbose) } + /** Wait for captcha solves (deprecated, v2 only) */ fun waitForCaptchaSolves(waitForCaptchaSolves: Boolean) = apply { body.waitForCaptchaSolves(waitForCaptchaSolves) } @@ -648,12 +627,11 @@ private constructor( private val browser: JsonField, private val browserbaseSessionCreateParams: JsonField, private val browserbaseSessionId: JsonField, - private val debugDom: JsonField, private val domSettleTimeoutMs: JsonField, private val experimental: JsonField, private val selfHeal: JsonField, private val systemPrompt: JsonField, - private val verbose: JsonField, + private val verbose: JsonField, private val waitForCaptchaSolves: JsonField, private val additionalProperties: MutableMap, ) { @@ -674,9 +652,6 @@ private constructor( @JsonProperty("browserbaseSessionID") @ExcludeMissing browserbaseSessionId: JsonField = JsonMissing.of(), - @JsonProperty("debugDom") - @ExcludeMissing - debugDom: JsonField = JsonMissing.of(), @JsonProperty("domSettleTimeoutMs") @ExcludeMissing domSettleTimeoutMs: JsonField = JsonMissing.of(), @@ -689,7 +664,7 @@ private constructor( @JsonProperty("systemPrompt") @ExcludeMissing systemPrompt: JsonField = JsonMissing.of(), - @JsonProperty("verbose") @ExcludeMissing verbose: JsonField = JsonMissing.of(), + @JsonProperty("verbose") @ExcludeMissing verbose: JsonField = JsonMissing.of(), @JsonProperty("waitForCaptchaSolves") @ExcludeMissing waitForCaptchaSolves: JsonField = JsonMissing.of(), @@ -699,7 +674,6 @@ private constructor( browser, browserbaseSessionCreateParams, browserbaseSessionId, - debugDom, domSettleTimeoutMs, experimental, selfHeal, @@ -718,7 +692,7 @@ private constructor( fun modelName(): String = modelName.getRequired("modelName") /** - * Timeout in ms for act operations + * Timeout in ms for act operations (deprecated, v2 only) * * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if * the server responded with an unexpected value). @@ -747,12 +721,6 @@ private constructor( fun browserbaseSessionId(): Optional = browserbaseSessionId.getOptional("browserbaseSessionID") - /** - * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if - * the server responded with an unexpected value). - */ - fun debugDom(): Optional = debugDom.getOptional("debugDom") - /** * Timeout in ms to wait for DOM to settle * @@ -790,9 +758,11 @@ private constructor( * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if * the server responded with an unexpected value). */ - fun verbose(): Optional = verbose.getOptional("verbose") + fun verbose(): Optional = verbose.getOptional("verbose") /** + * Wait for captcha solves (deprecated, v2 only) + * * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if * the server responded with an unexpected value). */ @@ -844,13 +814,6 @@ private constructor( @ExcludeMissing fun _browserbaseSessionId(): JsonField = browserbaseSessionId - /** - * Returns the raw JSON value of [debugDom]. - * - * Unlike [debugDom], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("debugDom") @ExcludeMissing fun _debugDom(): JsonField = debugDom - /** * Returns the raw JSON value of [domSettleTimeoutMs]. * @@ -893,7 +856,7 @@ private constructor( * * Unlike [verbose], this method doesn't throw if the JSON field has an unexpected type. */ - @JsonProperty("verbose") @ExcludeMissing fun _verbose(): JsonField = verbose + @JsonProperty("verbose") @ExcludeMissing fun _verbose(): JsonField = verbose /** * Returns the raw JSON value of [waitForCaptchaSolves]. @@ -939,12 +902,11 @@ private constructor( private var browserbaseSessionCreateParams: JsonField = JsonMissing.of() private var browserbaseSessionId: JsonField = JsonMissing.of() - private var debugDom: JsonField = JsonMissing.of() private var domSettleTimeoutMs: JsonField = JsonMissing.of() private var experimental: JsonField = JsonMissing.of() private var selfHeal: JsonField = JsonMissing.of() private var systemPrompt: JsonField = JsonMissing.of() - private var verbose: JsonField = JsonMissing.of() + private var verbose: JsonField = JsonMissing.of() private var waitForCaptchaSolves: JsonField = JsonMissing.of() private var additionalProperties: MutableMap = mutableMapOf() @@ -955,7 +917,6 @@ private constructor( browser = body.browser browserbaseSessionCreateParams = body.browserbaseSessionCreateParams browserbaseSessionId = body.browserbaseSessionId - debugDom = body.debugDom domSettleTimeoutMs = body.domSettleTimeoutMs experimental = body.experimental selfHeal = body.selfHeal @@ -977,7 +938,7 @@ private constructor( */ fun modelName(modelName: JsonField) = apply { this.modelName = modelName } - /** Timeout in ms for act operations */ + /** Timeout in ms for act operations (deprecated, v2 only) */ fun actTimeoutMs(actTimeoutMs: Double) = actTimeoutMs(JsonField.of(actTimeoutMs)) /** @@ -1032,17 +993,6 @@ private constructor( this.browserbaseSessionId = browserbaseSessionId } - fun debugDom(debugDom: Boolean) = debugDom(JsonField.of(debugDom)) - - /** - * Sets [Builder.debugDom] to an arbitrary JSON value. - * - * You should usually call [Builder.debugDom] with a well-typed [Boolean] value instead. - * This method is primarily for setting the field to an undocumented or not yet - * supported value. - */ - fun debugDom(debugDom: JsonField) = apply { this.debugDom = debugDom } - /** Timeout in ms to wait for DOM to settle */ fun domSettleTimeoutMs(domSettleTimeoutMs: Double) = domSettleTimeoutMs(JsonField.of(domSettleTimeoutMs)) @@ -1098,17 +1048,18 @@ private constructor( } /** Logging verbosity level (0=quiet, 1=normal, 2=debug) */ - fun verbose(verbose: Long) = verbose(JsonField.of(verbose)) + fun verbose(verbose: Verbose) = verbose(JsonField.of(verbose)) /** * Sets [Builder.verbose] to an arbitrary JSON value. * - * You should usually call [Builder.verbose] with a well-typed [Long] value instead. + * You should usually call [Builder.verbose] with a well-typed [Verbose] value instead. * This method is primarily for setting the field to an undocumented or not yet * supported value. */ - fun verbose(verbose: JsonField) = apply { this.verbose = verbose } + fun verbose(verbose: JsonField) = apply { this.verbose = verbose } + /** Wait for captcha solves (deprecated, v2 only) */ fun waitForCaptchaSolves(waitForCaptchaSolves: Boolean) = waitForCaptchaSolves(JsonField.of(waitForCaptchaSolves)) @@ -1161,7 +1112,6 @@ private constructor( browser, browserbaseSessionCreateParams, browserbaseSessionId, - debugDom, domSettleTimeoutMs, experimental, selfHeal, @@ -1184,12 +1134,11 @@ private constructor( browser().ifPresent { it.validate() } browserbaseSessionCreateParams().ifPresent { it.validate() } browserbaseSessionId() - debugDom() domSettleTimeoutMs() experimental() selfHeal() systemPrompt() - verbose() + verbose().ifPresent { it.validate() } waitForCaptchaSolves() validated = true } @@ -1215,12 +1164,11 @@ private constructor( (browser.asKnown().getOrNull()?.validity() ?: 0) + (browserbaseSessionCreateParams.asKnown().getOrNull()?.validity() ?: 0) + (if (browserbaseSessionId.asKnown().isPresent) 1 else 0) + - (if (debugDom.asKnown().isPresent) 1 else 0) + (if (domSettleTimeoutMs.asKnown().isPresent) 1 else 0) + (if (experimental.asKnown().isPresent) 1 else 0) + (if (selfHeal.asKnown().isPresent) 1 else 0) + (if (systemPrompt.asKnown().isPresent) 1 else 0) + - (if (verbose.asKnown().isPresent) 1 else 0) + + (verbose.asKnown().getOrNull()?.validity() ?: 0) + (if (waitForCaptchaSolves.asKnown().isPresent) 1 else 0) override fun equals(other: Any?): Boolean { @@ -1234,7 +1182,6 @@ private constructor( browser == other.browser && browserbaseSessionCreateParams == other.browserbaseSessionCreateParams && browserbaseSessionId == other.browserbaseSessionId && - debugDom == other.debugDom && domSettleTimeoutMs == other.domSettleTimeoutMs && experimental == other.experimental && selfHeal == other.selfHeal && @@ -1251,7 +1198,6 @@ private constructor( browser, browserbaseSessionCreateParams, browserbaseSessionId, - debugDom, domSettleTimeoutMs, experimental, selfHeal, @@ -1265,7 +1211,7 @@ private constructor( override fun hashCode(): Int = hashCode override fun toString() = - "Body{modelName=$modelName, actTimeoutMs=$actTimeoutMs, browser=$browser, browserbaseSessionCreateParams=$browserbaseSessionCreateParams, browserbaseSessionId=$browserbaseSessionId, debugDom=$debugDom, domSettleTimeoutMs=$domSettleTimeoutMs, experimental=$experimental, selfHeal=$selfHeal, systemPrompt=$systemPrompt, verbose=$verbose, waitForCaptchaSolves=$waitForCaptchaSolves, additionalProperties=$additionalProperties}" + "Body{modelName=$modelName, actTimeoutMs=$actTimeoutMs, browser=$browser, browserbaseSessionCreateParams=$browserbaseSessionCreateParams, browserbaseSessionId=$browserbaseSessionId, domSettleTimeoutMs=$domSettleTimeoutMs, experimental=$experimental, selfHeal=$selfHeal, systemPrompt=$systemPrompt, verbose=$verbose, waitForCaptchaSolves=$waitForCaptchaSolves, additionalProperties=$additionalProperties}" } class Browser @@ -7114,6 +7060,140 @@ private constructor( "BrowserbaseSessionCreateParams{browserSettings=$browserSettings, extensionId=$extensionId, keepAlive=$keepAlive, projectId=$projectId, proxies=$proxies, region=$region, timeout=$timeout, userMetadata=$userMetadata, additionalProperties=$additionalProperties}" } + /** Logging verbosity level (0=quiet, 1=normal, 2=debug) */ + class Verbose @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 { + + @JvmField val _0 = of("0") + + @JvmField val _1 = of("1") + + @JvmField val _2 = of("2") + + @JvmStatic fun of(value: String) = Verbose(JsonField.of(value)) + } + + /** An enum containing [Verbose]'s known values. */ + enum class Known { + _0, + _1, + _2, + } + + /** + * An enum containing [Verbose]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [Verbose] 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 { + _0, + _1, + _2, + /** An enum member indicating that [Verbose] 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) { + _0 -> Value._0 + _1 -> Value._1 + _2 -> Value._2 + 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) { + _0 -> Known._0 + _1 -> Known._1 + _2 -> Known._2 + else -> throw StagehandInvalidDataException("Unknown Verbose: $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().orElseThrow { + StagehandInvalidDataException("Value is not a String") + } + + private var validated: Boolean = false + + fun validate(): Verbose = 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. + */ + @JvmSynthetic 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 Verbose && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + /** Client SDK language */ class XLanguage @JsonCreator private constructor(private val value: JsonField) : Enum { diff --git a/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionStartResponse.kt b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionStartResponse.kt index 13ed630..e342e19 100644 --- a/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionStartResponse.kt +++ b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionStartResponse.kt @@ -14,6 +14,7 @@ import com.fasterxml.jackson.annotation.JsonCreator import com.fasterxml.jackson.annotation.JsonProperty import java.util.Collections import java.util.Objects +import java.util.Optional import kotlin.jvm.optionals.getOrNull class SessionStartResponse @@ -192,8 +193,8 @@ private constructor( @JsonCreator(mode = JsonCreator.Mode.DISABLED) private constructor( private val available: JsonField, - private val connectUrl: JsonField, private val sessionId: JsonField, + private val cdpUrl: JsonField, private val additionalProperties: MutableMap, ) { @@ -202,13 +203,11 @@ private constructor( @JsonProperty("available") @ExcludeMissing available: JsonField = JsonMissing.of(), - @JsonProperty("connectUrl") - @ExcludeMissing - connectUrl: JsonField = JsonMissing.of(), @JsonProperty("sessionId") @ExcludeMissing sessionId: JsonField = JsonMissing.of(), - ) : this(available, connectUrl, sessionId, mutableMapOf()) + @JsonProperty("cdpUrl") @ExcludeMissing cdpUrl: JsonField = JsonMissing.of(), + ) : this(available, sessionId, cdpUrl, mutableMapOf()) /** * @throws StagehandInvalidDataException if the JSON field has an unexpected type or is @@ -217,20 +216,21 @@ private constructor( fun available(): Boolean = available.getRequired("available") /** - * CDP WebSocket URL for connecting to the Browserbase cloud browser + * Unique Browserbase session identifier * * @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 connectUrl(): String = connectUrl.getRequired("connectUrl") + fun sessionId(): String = sessionId.getRequired("sessionId") /** - * Unique Browserbase session identifier + * CDP WebSocket URL for connecting to the Browserbase cloud browser (present when + * available) * - * @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). + * @throws StagehandInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). */ - fun sessionId(): String = sessionId.getRequired("sessionId") + fun cdpUrl(): Optional = cdpUrl.getOptional("cdpUrl") /** * Returns the raw JSON value of [available]. @@ -240,20 +240,18 @@ private constructor( @JsonProperty("available") @ExcludeMissing fun _available(): JsonField = available /** - * Returns the raw JSON value of [connectUrl]. + * Returns the raw JSON value of [sessionId]. * - * Unlike [connectUrl], this method doesn't throw if the JSON field has an unexpected type. + * Unlike [sessionId], this method doesn't throw if the JSON field has an unexpected type. */ - @JsonProperty("connectUrl") - @ExcludeMissing - fun _connectUrl(): JsonField = connectUrl + @JsonProperty("sessionId") @ExcludeMissing fun _sessionId(): JsonField = sessionId /** - * Returns the raw JSON value of [sessionId]. + * Returns the raw JSON value of [cdpUrl]. * - * Unlike [sessionId], this method doesn't throw if the JSON field has an unexpected type. + * Unlike [cdpUrl], this method doesn't throw if the JSON field has an unexpected type. */ - @JsonProperty("sessionId") @ExcludeMissing fun _sessionId(): JsonField = sessionId + @JsonProperty("cdpUrl") @ExcludeMissing fun _cdpUrl(): JsonField = cdpUrl @JsonAnySetter private fun putAdditionalProperty(key: String, value: JsonValue) { @@ -275,7 +273,6 @@ private constructor( * The following fields are required: * ```java * .available() - * .connectUrl() * .sessionId() * ``` */ @@ -286,15 +283,15 @@ private constructor( class Builder internal constructor() { private var available: JsonField? = null - private var connectUrl: JsonField? = null private var sessionId: JsonField? = null + private var cdpUrl: JsonField = JsonMissing.of() private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic internal fun from(data: Data) = apply { available = data.available - connectUrl = data.connectUrl sessionId = data.sessionId + cdpUrl = data.cdpUrl additionalProperties = data.additionalProperties.toMutableMap() } @@ -309,29 +306,35 @@ private constructor( */ fun available(available: JsonField) = apply { this.available = available } - /** CDP WebSocket URL for connecting to the Browserbase cloud browser */ - fun connectUrl(connectUrl: String) = connectUrl(JsonField.of(connectUrl)) + /** Unique Browserbase session identifier */ + fun sessionId(sessionId: String) = sessionId(JsonField.of(sessionId)) /** - * Sets [Builder.connectUrl] to an arbitrary JSON value. + * Sets [Builder.sessionId] to an arbitrary JSON value. * - * You should usually call [Builder.connectUrl] with a well-typed [String] value - * instead. This method is primarily for setting the field to an undocumented or not yet + * You should usually call [Builder.sessionId] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet * supported value. */ - fun connectUrl(connectUrl: JsonField) = apply { this.connectUrl = connectUrl } + fun sessionId(sessionId: JsonField) = apply { this.sessionId = sessionId } - /** Unique Browserbase session identifier */ - fun sessionId(sessionId: String) = sessionId(JsonField.of(sessionId)) + /** + * CDP WebSocket URL for connecting to the Browserbase cloud browser (present when + * available) + */ + fun cdpUrl(cdpUrl: String?) = cdpUrl(JsonField.ofNullable(cdpUrl)) + + /** Alias for calling [Builder.cdpUrl] with `cdpUrl.orElse(null)`. */ + fun cdpUrl(cdpUrl: Optional) = cdpUrl(cdpUrl.getOrNull()) /** - * Sets [Builder.sessionId] to an arbitrary JSON value. + * Sets [Builder.cdpUrl] to an arbitrary JSON value. * - * You should usually call [Builder.sessionId] with a well-typed [String] value instead. + * You should usually call [Builder.cdpUrl] with a well-typed [String] value instead. * This method is primarily for setting the field to an undocumented or not yet * supported value. */ - fun sessionId(sessionId: JsonField) = apply { this.sessionId = sessionId } + fun cdpUrl(cdpUrl: JsonField) = apply { this.cdpUrl = cdpUrl } fun additionalProperties(additionalProperties: Map) = apply { this.additionalProperties.clear() @@ -360,7 +363,6 @@ private constructor( * The following fields are required: * ```java * .available() - * .connectUrl() * .sessionId() * ``` * @@ -369,8 +371,8 @@ private constructor( fun build(): Data = Data( checkRequired("available", available), - checkRequired("connectUrl", connectUrl), checkRequired("sessionId", sessionId), + cdpUrl, additionalProperties.toMutableMap(), ) } @@ -383,8 +385,8 @@ private constructor( } available() - connectUrl() sessionId() + cdpUrl() validated = true } @@ -405,8 +407,8 @@ private constructor( @JvmSynthetic internal fun validity(): Int = (if (available.asKnown().isPresent) 1 else 0) + - (if (connectUrl.asKnown().isPresent) 1 else 0) + - (if (sessionId.asKnown().isPresent) 1 else 0) + (if (sessionId.asKnown().isPresent) 1 else 0) + + (if (cdpUrl.asKnown().isPresent) 1 else 0) override fun equals(other: Any?): Boolean { if (this === other) { @@ -415,19 +417,19 @@ private constructor( return other is Data && available == other.available && - connectUrl == other.connectUrl && sessionId == other.sessionId && + cdpUrl == other.cdpUrl && additionalProperties == other.additionalProperties } private val hashCode: Int by lazy { - Objects.hash(available, connectUrl, sessionId, additionalProperties) + Objects.hash(available, sessionId, cdpUrl, additionalProperties) } override fun hashCode(): Int = hashCode override fun toString() = - "Data{available=$available, connectUrl=$connectUrl, sessionId=$sessionId, additionalProperties=$additionalProperties}" + "Data{available=$available, sessionId=$sessionId, cdpUrl=$cdpUrl, additionalProperties=$additionalProperties}" } override fun equals(other: Any?): Boolean { diff --git a/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/StreamEvent.kt b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/StreamEvent.kt index d58dc3b..a123e6a 100644 --- a/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/StreamEvent.kt +++ b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/StreamEvent.kt @@ -29,7 +29,10 @@ import java.util.Objects import java.util.Optional import kotlin.jvm.optionals.getOrNull -/** Server-Sent Event emitted during streaming responses. Events are sent as `data: \n\n`. */ +/** + * Server-Sent Event emitted during streaming responses. Events are sent as `data: \n\n`. Key + * order: data (with status first), type, id. + */ class StreamEvent @JsonCreator(mode = JsonCreator.Mode.DISABLED) private constructor( diff --git a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/ActionTest.kt b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/ActionTest.kt index 4464f91..c76617d 100644 --- a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/ActionTest.kt +++ b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/ActionTest.kt @@ -17,12 +17,14 @@ internal class ActionTest { .description("Click the submit button") .selector("[data-testid='submit-button']") .addArgument("Hello World") + .backendNodeId(0.0) .method("click") .build() assertThat(action.description()).isEqualTo("Click the submit button") assertThat(action.selector()).isEqualTo("[data-testid='submit-button']") assertThat(action.arguments().getOrNull()).containsExactly("Hello World") + assertThat(action.backendNodeId()).contains(0.0) assertThat(action.method()).contains("click") } @@ -34,6 +36,7 @@ internal class ActionTest { .description("Click the submit button") .selector("[data-testid='submit-button']") .addArgument("Hello World") + .backendNodeId(0.0) .method("click") .build() diff --git a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/ModelConfigTest.kt b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/ModelConfigTest.kt index d83a01a..fc5ea48 100644 --- a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/ModelConfigTest.kt +++ b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/ModelConfigTest.kt @@ -43,6 +43,7 @@ internal class ModelConfigTest { .modelName("gpt-5-nano") .apiKey("sk-some-openai-api-key") .baseUrl("https://api.openai.com/v1") + .provider(ModelConfig.ModelConfigObject.Provider.OPENAI) .build() val modelConfig = ModelConfig.ofModelConfigObject(modelConfigObject) @@ -60,6 +61,7 @@ internal class ModelConfigTest { .modelName("gpt-5-nano") .apiKey("sk-some-openai-api-key") .baseUrl("https://api.openai.com/v1") + .provider(ModelConfig.ModelConfigObject.Provider.OPENAI) .build() ) diff --git a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionActResponseTest.kt b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionActResponseTest.kt index f5e0363..52cc63c 100644 --- a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionActResponseTest.kt +++ b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionActResponseTest.kt @@ -19,10 +19,11 @@ internal class SessionActResponseTest { SessionActResponse.Data.Result.builder() .actionDescription("Clicked button with text 'Login'") .addAction( - Action.builder() + SessionActResponse.Data.Result.Action.builder() .description("Click the submit button") .selector("[data-testid='submit-button']") .addArgument("Hello World") + .backendNodeId(0.0) .method("click") .build() ) @@ -43,10 +44,11 @@ internal class SessionActResponseTest { SessionActResponse.Data.Result.builder() .actionDescription("Clicked button with text 'Login'") .addAction( - Action.builder() + SessionActResponse.Data.Result.Action.builder() .description("Click the submit button") .selector("[data-testid='submit-button']") .addArgument("Hello World") + .backendNodeId(0.0) .method("click") .build() ) @@ -71,10 +73,11 @@ internal class SessionActResponseTest { SessionActResponse.Data.Result.builder() .actionDescription("Clicked button with text 'Login'") .addAction( - Action.builder() + SessionActResponse.Data.Result.Action.builder() .description("Click the submit button") .selector("[data-testid='submit-button']") .addArgument("Hello World") + .backendNodeId(0.0) .method("click") .build() ) diff --git a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionExecuteParamsTest.kt b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionExecuteParamsTest.kt index 4de6985..8869791 100644 --- a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionExecuteParamsTest.kt +++ b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionExecuteParamsTest.kt @@ -21,6 +21,7 @@ internal class SessionExecuteParamsTest { SessionExecuteParams.AgentConfig.builder() .cua(true) .model("openai/gpt-5-nano") + .provider(SessionExecuteParams.AgentConfig.Provider.OPENAI) .systemPrompt("systemPrompt") .build() ) @@ -70,6 +71,7 @@ internal class SessionExecuteParamsTest { SessionExecuteParams.AgentConfig.builder() .cua(true) .model("openai/gpt-5-nano") + .provider(SessionExecuteParams.AgentConfig.Provider.OPENAI) .systemPrompt("systemPrompt") .build() ) @@ -131,6 +133,7 @@ internal class SessionExecuteParamsTest { SessionExecuteParams.AgentConfig.builder() .cua(true) .model("openai/gpt-5-nano") + .provider(SessionExecuteParams.AgentConfig.Provider.OPENAI) .systemPrompt("systemPrompt") .build() ) @@ -153,6 +156,7 @@ internal class SessionExecuteParamsTest { SessionExecuteParams.AgentConfig.builder() .cua(true) .model("openai/gpt-5-nano") + .provider(SessionExecuteParams.AgentConfig.Provider.OPENAI) .systemPrompt("systemPrompt") .build() ) diff --git a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionObserveResponseTest.kt b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionObserveResponseTest.kt index 2cc31b8..938fff3 100644 --- a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionObserveResponseTest.kt +++ b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionObserveResponseTest.kt @@ -16,10 +16,11 @@ internal class SessionObserveResponseTest { .data( SessionObserveResponse.Data.builder() .addResult( - Action.builder() + SessionObserveResponse.Data.Result.builder() .description("Click the submit button") .selector("[data-testid='submit-button']") .addArgument("Hello World") + .backendNodeId(0.0) .method("click") .build() ) @@ -33,10 +34,11 @@ internal class SessionObserveResponseTest { .isEqualTo( SessionObserveResponse.Data.builder() .addResult( - Action.builder() + SessionObserveResponse.Data.Result.builder() .description("Click the submit button") .selector("[data-testid='submit-button']") .addArgument("Hello World") + .backendNodeId(0.0) .method("click") .build() ) @@ -54,10 +56,11 @@ internal class SessionObserveResponseTest { .data( SessionObserveResponse.Data.builder() .addResult( - Action.builder() + SessionObserveResponse.Data.Result.builder() .description("Click the submit button") .selector("[data-testid='submit-button']") .addArgument("Hello World") + .backendNodeId(0.0) .method("click") .build() ) diff --git a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionStartParamsTest.kt b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionStartParamsTest.kt index 56f4736..765a962 100644 --- a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionStartParamsTest.kt +++ b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionStartParamsTest.kt @@ -18,7 +18,7 @@ internal class SessionStartParamsTest { .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00Z")) .xStreamResponse(SessionStartParams.XStreamResponse.TRUE) .modelName("gpt-4o") - .actTimeoutMs(30000.0) + .actTimeoutMs(0.0) .browser( SessionStartParams.Browser.builder() .cdpUrl("ws://localhost:9222") @@ -148,12 +148,11 @@ internal class SessionStartParamsTest { .build() ) .browserbaseSessionId("browserbaseSessionID") - .debugDom(true) .domSettleTimeoutMs(5000.0) .experimental(true) .selfHeal(true) .systemPrompt("systemPrompt") - .verbose(1L) + .verbose(SessionStartParams.Verbose._1) .waitForCaptchaSolves(true) .build() } @@ -167,7 +166,7 @@ internal class SessionStartParamsTest { .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00Z")) .xStreamResponse(SessionStartParams.XStreamResponse.TRUE) .modelName("gpt-4o") - .actTimeoutMs(30000.0) + .actTimeoutMs(0.0) .browser( SessionStartParams.Browser.builder() .cdpUrl("ws://localhost:9222") @@ -301,12 +300,11 @@ internal class SessionStartParamsTest { .build() ) .browserbaseSessionId("browserbaseSessionID") - .debugDom(true) .domSettleTimeoutMs(5000.0) .experimental(true) .selfHeal(true) .systemPrompt("systemPrompt") - .verbose(1L) + .verbose(SessionStartParams.Verbose._1) .waitForCaptchaSolves(true) .build() @@ -341,7 +339,7 @@ internal class SessionStartParamsTest { .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00Z")) .xStreamResponse(SessionStartParams.XStreamResponse.TRUE) .modelName("gpt-4o") - .actTimeoutMs(30000.0) + .actTimeoutMs(0.0) .browser( SessionStartParams.Browser.builder() .cdpUrl("ws://localhost:9222") @@ -475,19 +473,18 @@ internal class SessionStartParamsTest { .build() ) .browserbaseSessionId("browserbaseSessionID") - .debugDom(true) .domSettleTimeoutMs(5000.0) .experimental(true) .selfHeal(true) .systemPrompt("systemPrompt") - .verbose(1L) + .verbose(SessionStartParams.Verbose._1) .waitForCaptchaSolves(true) .build() val body = params._body() assertThat(body.modelName()).isEqualTo("gpt-4o") - assertThat(body.actTimeoutMs()).contains(30000.0) + assertThat(body.actTimeoutMs()).contains(0.0) assertThat(body.browser()) .contains( SessionStartParams.Browser.builder() @@ -619,12 +616,11 @@ internal class SessionStartParamsTest { .build() ) assertThat(body.browserbaseSessionId()).contains("browserbaseSessionID") - assertThat(body.debugDom()).contains(true) assertThat(body.domSettleTimeoutMs()).contains(5000.0) assertThat(body.experimental()).contains(true) assertThat(body.selfHeal()).contains(true) assertThat(body.systemPrompt()).contains("systemPrompt") - assertThat(body.verbose()).contains(1L) + assertThat(body.verbose()).contains(SessionStartParams.Verbose._1) assertThat(body.waitForCaptchaSolves()).contains(true) } diff --git a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionStartResponseTest.kt b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionStartResponseTest.kt index 4a712ec..0ae6883 100644 --- a/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionStartResponseTest.kt +++ b/stagehand-java-core/src/test/kotlin/com/browserbase/api/models/sessions/SessionStartResponseTest.kt @@ -16,8 +16,8 @@ internal class SessionStartResponseTest { .data( SessionStartResponse.Data.builder() .available(true) - .connectUrl("wss://connect.browserbase.com/?signingKey=abc123") .sessionId("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") + .cdpUrl("wss://connect.browserbase.com/?signingKey=abc123") .build() ) .success(true) @@ -27,8 +27,8 @@ internal class SessionStartResponseTest { .isEqualTo( SessionStartResponse.Data.builder() .available(true) - .connectUrl("wss://connect.browserbase.com/?signingKey=abc123") .sessionId("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") + .cdpUrl("wss://connect.browserbase.com/?signingKey=abc123") .build() ) assertThat(sessionStartResponse.success()).isEqualTo(true) @@ -42,8 +42,8 @@ internal class SessionStartResponseTest { .data( SessionStartResponse.Data.builder() .available(true) - .connectUrl("wss://connect.browserbase.com/?signingKey=abc123") .sessionId("c4dbf3a9-9a58-4b22-8a1c-9f20f9f9e123") + .cdpUrl("wss://connect.browserbase.com/?signingKey=abc123") .build() ) .success(true) diff --git a/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/ErrorHandlingTest.kt b/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/ErrorHandlingTest.kt index e453d81..f704c1a 100644 --- a/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/ErrorHandlingTest.kt +++ b/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/ErrorHandlingTest.kt @@ -80,7 +80,7 @@ internal class ErrorHandlingTest { .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00Z")) .xStreamResponse(SessionStartParams.XStreamResponse.TRUE) .modelName("gpt-4o") - .actTimeoutMs(30000.0) + .actTimeoutMs(0.0) .browser( SessionStartParams.Browser.builder() .cdpUrl("ws://localhost:9222") @@ -225,12 +225,11 @@ internal class ErrorHandlingTest { .build() ) .browserbaseSessionId("browserbaseSessionID") - .debugDom(true) .domSettleTimeoutMs(5000.0) .experimental(true) .selfHeal(true) .systemPrompt("systemPrompt") - .verbose(1L) + .verbose(SessionStartParams.Verbose._1) .waitForCaptchaSolves(true) .build() ) @@ -260,7 +259,7 @@ internal class ErrorHandlingTest { .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00Z")) .xStreamResponse(SessionStartParams.XStreamResponse.TRUE) .modelName("gpt-4o") - .actTimeoutMs(30000.0) + .actTimeoutMs(0.0) .browser( SessionStartParams.Browser.builder() .cdpUrl("ws://localhost:9222") @@ -405,12 +404,11 @@ internal class ErrorHandlingTest { .build() ) .browserbaseSessionId("browserbaseSessionID") - .debugDom(true) .domSettleTimeoutMs(5000.0) .experimental(true) .selfHeal(true) .systemPrompt("systemPrompt") - .verbose(1L) + .verbose(SessionStartParams.Verbose._1) .waitForCaptchaSolves(true) .build() ) @@ -440,7 +438,7 @@ internal class ErrorHandlingTest { .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00Z")) .xStreamResponse(SessionStartParams.XStreamResponse.TRUE) .modelName("gpt-4o") - .actTimeoutMs(30000.0) + .actTimeoutMs(0.0) .browser( SessionStartParams.Browser.builder() .cdpUrl("ws://localhost:9222") @@ -585,12 +583,11 @@ internal class ErrorHandlingTest { .build() ) .browserbaseSessionId("browserbaseSessionID") - .debugDom(true) .domSettleTimeoutMs(5000.0) .experimental(true) .selfHeal(true) .systemPrompt("systemPrompt") - .verbose(1L) + .verbose(SessionStartParams.Verbose._1) .waitForCaptchaSolves(true) .build() ) @@ -620,7 +617,7 @@ internal class ErrorHandlingTest { .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00Z")) .xStreamResponse(SessionStartParams.XStreamResponse.TRUE) .modelName("gpt-4o") - .actTimeoutMs(30000.0) + .actTimeoutMs(0.0) .browser( SessionStartParams.Browser.builder() .cdpUrl("ws://localhost:9222") @@ -765,12 +762,11 @@ internal class ErrorHandlingTest { .build() ) .browserbaseSessionId("browserbaseSessionID") - .debugDom(true) .domSettleTimeoutMs(5000.0) .experimental(true) .selfHeal(true) .systemPrompt("systemPrompt") - .verbose(1L) + .verbose(SessionStartParams.Verbose._1) .waitForCaptchaSolves(true) .build() ) @@ -800,7 +796,7 @@ internal class ErrorHandlingTest { .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00Z")) .xStreamResponse(SessionStartParams.XStreamResponse.TRUE) .modelName("gpt-4o") - .actTimeoutMs(30000.0) + .actTimeoutMs(0.0) .browser( SessionStartParams.Browser.builder() .cdpUrl("ws://localhost:9222") @@ -945,12 +941,11 @@ internal class ErrorHandlingTest { .build() ) .browserbaseSessionId("browserbaseSessionID") - .debugDom(true) .domSettleTimeoutMs(5000.0) .experimental(true) .selfHeal(true) .systemPrompt("systemPrompt") - .verbose(1L) + .verbose(SessionStartParams.Verbose._1) .waitForCaptchaSolves(true) .build() ) @@ -980,7 +975,7 @@ internal class ErrorHandlingTest { .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00Z")) .xStreamResponse(SessionStartParams.XStreamResponse.TRUE) .modelName("gpt-4o") - .actTimeoutMs(30000.0) + .actTimeoutMs(0.0) .browser( SessionStartParams.Browser.builder() .cdpUrl("ws://localhost:9222") @@ -1125,12 +1120,11 @@ internal class ErrorHandlingTest { .build() ) .browserbaseSessionId("browserbaseSessionID") - .debugDom(true) .domSettleTimeoutMs(5000.0) .experimental(true) .selfHeal(true) .systemPrompt("systemPrompt") - .verbose(1L) + .verbose(SessionStartParams.Verbose._1) .waitForCaptchaSolves(true) .build() ) @@ -1160,7 +1154,7 @@ internal class ErrorHandlingTest { .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00Z")) .xStreamResponse(SessionStartParams.XStreamResponse.TRUE) .modelName("gpt-4o") - .actTimeoutMs(30000.0) + .actTimeoutMs(0.0) .browser( SessionStartParams.Browser.builder() .cdpUrl("ws://localhost:9222") @@ -1305,12 +1299,11 @@ internal class ErrorHandlingTest { .build() ) .browserbaseSessionId("browserbaseSessionID") - .debugDom(true) .domSettleTimeoutMs(5000.0) .experimental(true) .selfHeal(true) .systemPrompt("systemPrompt") - .verbose(1L) + .verbose(SessionStartParams.Verbose._1) .waitForCaptchaSolves(true) .build() ) @@ -1340,7 +1333,7 @@ internal class ErrorHandlingTest { .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00Z")) .xStreamResponse(SessionStartParams.XStreamResponse.TRUE) .modelName("gpt-4o") - .actTimeoutMs(30000.0) + .actTimeoutMs(0.0) .browser( SessionStartParams.Browser.builder() .cdpUrl("ws://localhost:9222") @@ -1485,12 +1478,11 @@ internal class ErrorHandlingTest { .build() ) .browserbaseSessionId("browserbaseSessionID") - .debugDom(true) .domSettleTimeoutMs(5000.0) .experimental(true) .selfHeal(true) .systemPrompt("systemPrompt") - .verbose(1L) + .verbose(SessionStartParams.Verbose._1) .waitForCaptchaSolves(true) .build() ) @@ -1520,7 +1512,7 @@ internal class ErrorHandlingTest { .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00Z")) .xStreamResponse(SessionStartParams.XStreamResponse.TRUE) .modelName("gpt-4o") - .actTimeoutMs(30000.0) + .actTimeoutMs(0.0) .browser( SessionStartParams.Browser.builder() .cdpUrl("ws://localhost:9222") @@ -1665,12 +1657,11 @@ internal class ErrorHandlingTest { .build() ) .browserbaseSessionId("browserbaseSessionID") - .debugDom(true) .domSettleTimeoutMs(5000.0) .experimental(true) .selfHeal(true) .systemPrompt("systemPrompt") - .verbose(1L) + .verbose(SessionStartParams.Verbose._1) .waitForCaptchaSolves(true) .build() ) @@ -1700,7 +1691,7 @@ internal class ErrorHandlingTest { .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00Z")) .xStreamResponse(SessionStartParams.XStreamResponse.TRUE) .modelName("gpt-4o") - .actTimeoutMs(30000.0) + .actTimeoutMs(0.0) .browser( SessionStartParams.Browser.builder() .cdpUrl("ws://localhost:9222") @@ -1845,12 +1836,11 @@ internal class ErrorHandlingTest { .build() ) .browserbaseSessionId("browserbaseSessionID") - .debugDom(true) .domSettleTimeoutMs(5000.0) .experimental(true) .selfHeal(true) .systemPrompt("systemPrompt") - .verbose(1L) + .verbose(SessionStartParams.Verbose._1) .waitForCaptchaSolves(true) .build() ) @@ -1880,7 +1870,7 @@ internal class ErrorHandlingTest { .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00Z")) .xStreamResponse(SessionStartParams.XStreamResponse.TRUE) .modelName("gpt-4o") - .actTimeoutMs(30000.0) + .actTimeoutMs(0.0) .browser( SessionStartParams.Browser.builder() .cdpUrl("ws://localhost:9222") @@ -2025,12 +2015,11 @@ internal class ErrorHandlingTest { .build() ) .browserbaseSessionId("browserbaseSessionID") - .debugDom(true) .domSettleTimeoutMs(5000.0) .experimental(true) .selfHeal(true) .systemPrompt("systemPrompt") - .verbose(1L) + .verbose(SessionStartParams.Verbose._1) .waitForCaptchaSolves(true) .build() ) @@ -2060,7 +2049,7 @@ internal class ErrorHandlingTest { .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00Z")) .xStreamResponse(SessionStartParams.XStreamResponse.TRUE) .modelName("gpt-4o") - .actTimeoutMs(30000.0) + .actTimeoutMs(0.0) .browser( SessionStartParams.Browser.builder() .cdpUrl("ws://localhost:9222") @@ -2205,12 +2194,11 @@ internal class ErrorHandlingTest { .build() ) .browserbaseSessionId("browserbaseSessionID") - .debugDom(true) .domSettleTimeoutMs(5000.0) .experimental(true) .selfHeal(true) .systemPrompt("systemPrompt") - .verbose(1L) + .verbose(SessionStartParams.Verbose._1) .waitForCaptchaSolves(true) .build() ) @@ -2240,7 +2228,7 @@ internal class ErrorHandlingTest { .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00Z")) .xStreamResponse(SessionStartParams.XStreamResponse.TRUE) .modelName("gpt-4o") - .actTimeoutMs(30000.0) + .actTimeoutMs(0.0) .browser( SessionStartParams.Browser.builder() .cdpUrl("ws://localhost:9222") @@ -2385,12 +2373,11 @@ internal class ErrorHandlingTest { .build() ) .browserbaseSessionId("browserbaseSessionID") - .debugDom(true) .domSettleTimeoutMs(5000.0) .experimental(true) .selfHeal(true) .systemPrompt("systemPrompt") - .verbose(1L) + .verbose(SessionStartParams.Verbose._1) .waitForCaptchaSolves(true) .build() ) @@ -2420,7 +2407,7 @@ internal class ErrorHandlingTest { .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00Z")) .xStreamResponse(SessionStartParams.XStreamResponse.TRUE) .modelName("gpt-4o") - .actTimeoutMs(30000.0) + .actTimeoutMs(0.0) .browser( SessionStartParams.Browser.builder() .cdpUrl("ws://localhost:9222") @@ -2565,12 +2552,11 @@ internal class ErrorHandlingTest { .build() ) .browserbaseSessionId("browserbaseSessionID") - .debugDom(true) .domSettleTimeoutMs(5000.0) .experimental(true) .selfHeal(true) .systemPrompt("systemPrompt") - .verbose(1L) + .verbose(SessionStartParams.Verbose._1) .waitForCaptchaSolves(true) .build() ) @@ -2600,7 +2586,7 @@ internal class ErrorHandlingTest { .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00Z")) .xStreamResponse(SessionStartParams.XStreamResponse.TRUE) .modelName("gpt-4o") - .actTimeoutMs(30000.0) + .actTimeoutMs(0.0) .browser( SessionStartParams.Browser.builder() .cdpUrl("ws://localhost:9222") @@ -2745,12 +2731,11 @@ internal class ErrorHandlingTest { .build() ) .browserbaseSessionId("browserbaseSessionID") - .debugDom(true) .domSettleTimeoutMs(5000.0) .experimental(true) .selfHeal(true) .systemPrompt("systemPrompt") - .verbose(1L) + .verbose(SessionStartParams.Verbose._1) .waitForCaptchaSolves(true) .build() ) @@ -2780,7 +2765,7 @@ internal class ErrorHandlingTest { .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00Z")) .xStreamResponse(SessionStartParams.XStreamResponse.TRUE) .modelName("gpt-4o") - .actTimeoutMs(30000.0) + .actTimeoutMs(0.0) .browser( SessionStartParams.Browser.builder() .cdpUrl("ws://localhost:9222") @@ -2925,12 +2910,11 @@ internal class ErrorHandlingTest { .build() ) .browserbaseSessionId("browserbaseSessionID") - .debugDom(true) .domSettleTimeoutMs(5000.0) .experimental(true) .selfHeal(true) .systemPrompt("systemPrompt") - .verbose(1L) + .verbose(SessionStartParams.Verbose._1) .waitForCaptchaSolves(true) .build() ) @@ -2958,7 +2942,7 @@ internal class ErrorHandlingTest { .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00Z")) .xStreamResponse(SessionStartParams.XStreamResponse.TRUE) .modelName("gpt-4o") - .actTimeoutMs(30000.0) + .actTimeoutMs(0.0) .browser( SessionStartParams.Browser.builder() .cdpUrl("ws://localhost:9222") @@ -3103,12 +3087,11 @@ internal class ErrorHandlingTest { .build() ) .browserbaseSessionId("browserbaseSessionID") - .debugDom(true) .domSettleTimeoutMs(5000.0) .experimental(true) .selfHeal(true) .systemPrompt("systemPrompt") - .verbose(1L) + .verbose(SessionStartParams.Verbose._1) .waitForCaptchaSolves(true) .build() ) diff --git a/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/ServiceParamsTest.kt b/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/ServiceParamsTest.kt index 0cdc99d..2243046 100644 --- a/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/ServiceParamsTest.kt +++ b/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/ServiceParamsTest.kt @@ -53,7 +53,7 @@ internal class ServiceParamsTest { .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00Z")) .xStreamResponse(SessionStartParams.XStreamResponse.TRUE) .modelName("gpt-4o") - .actTimeoutMs(30000.0) + .actTimeoutMs(0.0) .browser( SessionStartParams.Browser.builder() .cdpUrl("ws://localhost:9222") @@ -187,12 +187,11 @@ internal class ServiceParamsTest { .build() ) .browserbaseSessionId("browserbaseSessionID") - .debugDom(true) .domSettleTimeoutMs(5000.0) .experimental(true) .selfHeal(true) .systemPrompt("systemPrompt") - .verbose(1L) + .verbose(SessionStartParams.Verbose._1) .waitForCaptchaSolves(true) .putAdditionalHeader("Secret-Header", "42") .putAdditionalQueryParam("secret_query_param", "42") diff --git a/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/async/SessionServiceAsyncTest.kt b/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/async/SessionServiceAsyncTest.kt index 78ba6e7..f9bc4be 100644 --- a/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/async/SessionServiceAsyncTest.kt +++ b/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/async/SessionServiceAsyncTest.kt @@ -152,6 +152,7 @@ internal class SessionServiceAsyncTest { SessionExecuteParams.AgentConfig.builder() .cua(true) .model("openai/gpt-5-nano") + .provider(SessionExecuteParams.AgentConfig.Provider.OPENAI) .systemPrompt("systemPrompt") .build() ) @@ -196,6 +197,7 @@ internal class SessionServiceAsyncTest { SessionExecuteParams.AgentConfig.builder() .cua(true) .model("openai/gpt-5-nano") + .provider(SessionExecuteParams.AgentConfig.Provider.OPENAI) .systemPrompt("systemPrompt") .build() ) @@ -430,7 +432,7 @@ internal class SessionServiceAsyncTest { .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00Z")) .xStreamResponse(SessionStartParams.XStreamResponse.TRUE) .modelName("gpt-4o") - .actTimeoutMs(30000.0) + .actTimeoutMs(0.0) .browser( SessionStartParams.Browser.builder() .cdpUrl("ws://localhost:9222") @@ -567,12 +569,11 @@ internal class SessionServiceAsyncTest { .build() ) .browserbaseSessionId("browserbaseSessionID") - .debugDom(true) .domSettleTimeoutMs(5000.0) .experimental(true) .selfHeal(true) .systemPrompt("systemPrompt") - .verbose(1L) + .verbose(SessionStartParams.Verbose._1) .waitForCaptchaSolves(true) .build() ) diff --git a/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/blocking/SessionServiceTest.kt b/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/blocking/SessionServiceTest.kt index 3355c14..1bad240 100644 --- a/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/blocking/SessionServiceTest.kt +++ b/stagehand-java-core/src/test/kotlin/com/browserbase/api/services/blocking/SessionServiceTest.kt @@ -150,6 +150,7 @@ internal class SessionServiceTest { SessionExecuteParams.AgentConfig.builder() .cua(true) .model("openai/gpt-5-nano") + .provider(SessionExecuteParams.AgentConfig.Provider.OPENAI) .systemPrompt("systemPrompt") .build() ) @@ -193,6 +194,7 @@ internal class SessionServiceTest { SessionExecuteParams.AgentConfig.builder() .cua(true) .model("openai/gpt-5-nano") + .provider(SessionExecuteParams.AgentConfig.Provider.OPENAI) .systemPrompt("systemPrompt") .build() ) @@ -424,7 +426,7 @@ internal class SessionServiceTest { .xSentAt(OffsetDateTime.parse("2025-01-15T10:30:00Z")) .xStreamResponse(SessionStartParams.XStreamResponse.TRUE) .modelName("gpt-4o") - .actTimeoutMs(30000.0) + .actTimeoutMs(0.0) .browser( SessionStartParams.Browser.builder() .cdpUrl("ws://localhost:9222") @@ -561,12 +563,11 @@ internal class SessionServiceTest { .build() ) .browserbaseSessionId("browserbaseSessionID") - .debugDom(true) .domSettleTimeoutMs(5000.0) .experimental(true) .selfHeal(true) .systemPrompt("systemPrompt") - .verbose(1L) + .verbose(SessionStartParams.Verbose._1) .waitForCaptchaSolves(true) .build() ) diff --git a/stagehand-java-proguard-test/src/test/kotlin/com/browserbase/api/proguard/ProGuardCompatibilityTest.kt b/stagehand-java-proguard-test/src/test/kotlin/com/browserbase/api/proguard/ProGuardCompatibilityTest.kt index 0d52560..f3e08fa 100644 --- a/stagehand-java-proguard-test/src/test/kotlin/com/browserbase/api/proguard/ProGuardCompatibilityTest.kt +++ b/stagehand-java-proguard-test/src/test/kotlin/com/browserbase/api/proguard/ProGuardCompatibilityTest.kt @@ -64,6 +64,7 @@ internal class ProGuardCompatibilityTest { .description("Click the submit button") .selector("[data-testid='submit-button']") .addArgument("Hello World") + .backendNodeId(0.0) .method("click") .build() From 54eba3455dbfc5dd61c1c3b88aedd34c56bce37a Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 20 Dec 2025 04:57:19 +0000 Subject: [PATCH 14/18] docs: add more examples --- README.md | 92 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) diff --git a/README.md b/README.md index be1932d..251bfd6 100644 --- a/README.md +++ b/README.md @@ -190,6 +190,98 @@ CompletableFuture response = client.sessions().act(params); The asynchronous client supports the same options as the synchronous one, except most methods return `CompletableFuture`s. +## Streaming + +The SDK defines methods that return response "chunk" streams, where each chunk can be individually processed as soon as it arrives instead of waiting on the full response. Streaming methods generally correspond to [SSE](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events) or [JSONL](https://jsonlines.org) responses. + +Some of these methods may have streaming and non-streaming variants, but a streaming method will always have a `Streaming` suffix in its name, even if it doesn't have a non-streaming variant. + +These streaming methods return [`StreamResponse`](stagehand-java-core/src/main/kotlin/com/browserbase/api/core/http/StreamResponse.kt) for synchronous clients: + +```java +import com.browserbase.api.core.http.StreamResponse; +import com.browserbase.api.models.sessions.StreamEvent; + +try (StreamResponse streamResponse = client.sessions().actStreaming(params)) { + streamResponse.stream().forEach(chunk -> { + System.out.println(chunk); + }); + System.out.println("No more chunks!"); +} +``` + +Or [`AsyncStreamResponse`](stagehand-java-core/src/main/kotlin/com/browserbase/api/core/http/AsyncStreamResponse.kt) for asynchronous clients: + +```java +import com.browserbase.api.core.http.AsyncStreamResponse; +import com.browserbase.api.models.sessions.StreamEvent; +import java.util.Optional; + +client.async().sessions().actStreaming(params).subscribe(chunk -> { + System.out.println(chunk); +}); + +// If you need to handle errors or completion of the stream +client.async().sessions().actStreaming(params).subscribe(new AsyncStreamResponse.Handler<>() { + @Override + public void onNext(StreamEvent chunk) { + System.out.println(chunk); + } + + @Override + public void onComplete(Optional error) { + if (error.isPresent()) { + System.out.println("Something went wrong!"); + throw new RuntimeException(error.get()); + } else { + System.out.println("No more chunks!"); + } + } +}); + +// Or use futures +client.async().sessions().actStreaming(params) + .subscribe(chunk -> { + System.out.println(chunk); + }) + .onCompleteFuture(); + .whenComplete((unused, error) -> { + if (error != null) { + System.out.println("Something went wrong!"); + throw new RuntimeException(error); + } else { + System.out.println("No more chunks!"); + } + }); +``` + +Async streaming uses a dedicated per-client cached thread pool [`Executor`](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/Executor.html) to stream without blocking the current thread. This default is suitable for most purposes. + +To use a different `Executor`, configure the subscription using the `executor` parameter: + +```java +import java.util.concurrent.Executor; +import java.util.concurrent.Executors; + +Executor executor = Executors.newFixedThreadPool(4); +client.async().sessions().actStreaming(params).subscribe( + chunk -> System.out.println(chunk), executor +); +``` + +Or configure the client globally using the `streamHandlerExecutor` method: + +```java +import com.browserbase.api.client.StagehandClient; +import com.browserbase.api.client.okhttp.StagehandOkHttpClient; +import java.util.concurrent.Executors; + +StagehandClient client = StagehandOkHttpClient.builder() + .fromEnv() + .streamHandlerExecutor(Executors.newFixedThreadPool(4)) + .build(); +``` + ## Raw responses The SDK defines methods that deserialize responses into instances of Java classes. However, these methods don't provide access to the response headers, status code, or the raw response body. From 9de17a2552f759f6e8f37de4c3b9bb5d403edcc4 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 22 Dec 2025 21:50:02 +0000 Subject: [PATCH 15/18] feat: [STG-1053] [server] Use fastify-zod-openapi + zod v4 for openapi generation --- .stats.yml | 4 ++-- .../api/models/sessions/SessionStartParams.kt | 22 ++++++++----------- 2 files changed, 11 insertions(+), 15 deletions(-) diff --git a/.stats.yml b/.stats.yml index d90df61..2c7a523 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-4fb17cafc413ae3d575e3268602b01d2d0e9ebeb734a41b6086b3353ff0d2523.yml -openapi_spec_hash: 8d48d8564849246f6f14d900c6c5f60c +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/browserbase%2Fstagehand-ed52466945f2f8dfd3814a29e948d7bf30af7b76a7a7689079c03b8baf64e26f.yml +openapi_spec_hash: 5d57aaf2362b0d882372dbf76477ba23 config_hash: 5c69fb596588b8ace08203858518c149 diff --git a/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionStartParams.kt b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionStartParams.kt index ca9fdd1..3a7009b 100644 --- a/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionStartParams.kt +++ b/stagehand-java-core/src/main/kotlin/com/browserbase/api/models/sessions/SessionStartParams.kt @@ -7061,7 +7061,7 @@ private constructor( } /** Logging verbosity level (0=quiet, 1=normal, 2=debug) */ - class Verbose @JsonCreator private constructor(private val value: JsonField) : Enum { + class Verbose @JsonCreator private constructor(private val value: JsonField) : Enum { /** * Returns this class instance's raw value. @@ -7071,17 +7071,17 @@ private constructor( * 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 + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value companion object { - @JvmField val _0 = of("0") + @JvmField val _0 = of(0.0) - @JvmField val _1 = of("1") + @JvmField val _1 = of(1.0) - @JvmField val _2 = of("2") + @JvmField val _2 = of(2.0) - @JvmStatic fun of(value: String) = Verbose(JsonField.of(value)) + @JvmStatic fun of(value: Double) = Verbose(JsonField.of(value)) } /** An enum containing [Verbose]'s known values. */ @@ -7143,16 +7143,12 @@ private constructor( /** * 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().orElseThrow { - StagehandInvalidDataException("Value is not a String") - } + fun asDouble(): Double = + _value().asNumber().getOrNull()?.toDouble() + ?: throw StagehandInvalidDataException("Value is not a Double") private var validated: Boolean = false From 7a48117fdabd0fb78416ceb3914706783663c2cf Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 23 Dec 2025 19:53:39 +0000 Subject: [PATCH 16/18] codegen metadata --- .stats.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.stats.yml b/.stats.yml index 2c7a523..21604fb 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-ed52466945f2f8dfd3814a29e948d7bf30af7b76a7a7689079c03b8baf64e26f.yml openapi_spec_hash: 5d57aaf2362b0d882372dbf76477ba23 -config_hash: 5c69fb596588b8ace08203858518c149 +config_hash: 6b5d2b7e13aea77b1fd038e5eb8c0662 From 3ec0974c5fc0fe0d8698cb2473aca5462744a6f8 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 23 Dec 2025 20:07:15 +0000 Subject: [PATCH 17/18] codegen metadata --- .stats.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.stats.yml b/.stats.yml index 21604fb..5a89fb7 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-ed52466945f2f8dfd3814a29e948d7bf30af7b76a7a7689079c03b8baf64e26f.yml openapi_spec_hash: 5d57aaf2362b0d882372dbf76477ba23 -config_hash: 6b5d2b7e13aea77b1fd038e5eb8c0662 +config_hash: 989ddfee371586e9156b4d484ec0a6cc From b4a8836cd87824522fb686bea64ffc8d6576cdae Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 23 Dec 2025 20:07:32 +0000 Subject: [PATCH 18/18] release: 0.3.0 --- .release-please-manifest.json | 2 +- CHANGELOG.md | 24 ++++++++++++++++++++++++ README.md | 10 +++++----- build.gradle.kts | 2 +- 4 files changed, 31 insertions(+), 7 deletions(-) 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/CHANGELOG.md b/CHANGELOG.md index 04011d6..81e4589 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,29 @@ # Changelog +## 0.3.0 (2025-12-23) + +Full Changelog: [v0.2.0...v0.3.0](https://github.com/browserbase/stagehand-java/compare/v0.2.0...v0.3.0) + +### Features + +* [STG-1053] [server] Use fastify-zod-openapi + zod v4 for openapi generation ([9de17a2](https://github.com/browserbase/stagehand-java/commit/9de17a2552f759f6e8f37de4c3b9bb5d403edcc4)) +* **api:** manual updates ([d9e462c](https://github.com/browserbase/stagehand-java/commit/d9e462c24ed6d3e165a5873e7f70f011d768500a)) +* **api:** manual updates ([b6bdf1a](https://github.com/browserbase/stagehand-java/commit/b6bdf1a26a45556dcfee59b088983cd7e7839f43)) +* **api:** manual updates ([9b6860a](https://github.com/browserbase/stagehand-java/commit/9b6860a4f60d1a740fbb026eef291e40fb8e1845)) +* **api:** manual updates ([28f7978](https://github.com/browserbase/stagehand-java/commit/28f7978e1f040169dbb20aa68efb8e5ceb9a34d2)) +* **api:** manual updates ([07db616](https://github.com/browserbase/stagehand-java/commit/07db616b7209716efa346035d65f5d7bf616c992)) +* **api:** manual updates ([3cf2073](https://github.com/browserbase/stagehand-java/commit/3cf20739785134610aa7bcbdbce3215c3c3a9970)) +* **api:** manual updates ([adace53](https://github.com/browserbase/stagehand-java/commit/adace53fc3e4a0fb4b866172aec98519ec0f29d5)) +* **api:** manual updates ([dd65420](https://github.com/browserbase/stagehand-java/commit/dd65420fecb521fba36cbf2a623ce675973a27a0)) +* **api:** manual updates ([067c9e6](https://github.com/browserbase/stagehand-java/commit/067c9e644940fa3671665a902bc605b8e358473f)) +* **api:** manual updates ([d7aabe3](https://github.com/browserbase/stagehand-java/commit/d7aabe36f42d8344477f2f468bd3ba15837c0516)) +* **api:** manual updates ([13074f1](https://github.com/browserbase/stagehand-java/commit/13074f11bbc12057b60e89f37f850ca8f5bc7a83)) + + +### Documentation + +* add more examples ([54eba34](https://github.com/browserbase/stagehand-java/commit/54eba3455dbfc5dd61c1c3b88aedd34c56bce37a)) + ## 0.2.0 (2025-12-16) Full Changelog: [v0.1.0...v0.2.0](https://github.com/browserbase/stagehand-java/compare/v0.1.0...v0.2.0) diff --git a/README.md b/README.md index 251bfd6..ab416ca 100644 --- a/README.md +++ b/README.md @@ -2,8 +2,8 @@ -[![Maven Central](https://img.shields.io/maven-central/v/com.browserbase.api/stagehand-java)](https://central.sonatype.com/artifact/com.browserbase.api/stagehand-java/0.2.0) -[![javadoc](https://javadoc.io/badge2/com.browserbase.api/stagehand-java/0.2.0/javadoc.svg)](https://javadoc.io/doc/com.browserbase.api/stagehand-java/0.2.0) +[![Maven Central](https://img.shields.io/maven-central/v/com.browserbase.api/stagehand-java)](https://central.sonatype.com/artifact/com.browserbase.api/stagehand-java/0.3.0) +[![javadoc](https://javadoc.io/badge2/com.browserbase.api/stagehand-java/0.3.0/javadoc.svg)](https://javadoc.io/doc/com.browserbase.api/stagehand-java/0.3.0) @@ -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). Javadocs are available on [javadoc.io](https://javadoc.io/doc/com.browserbase.api/stagehand-java/0.2.0). +The REST API documentation can be found on [docs.stagehand.dev](https://docs.stagehand.dev). Javadocs are available on [javadoc.io](https://javadoc.io/doc/com.browserbase.api/stagehand-java/0.3.0). @@ -24,7 +24,7 @@ The REST API documentation can be found on [docs.stagehand.dev](https://docs.sta ### Gradle ```kotlin -implementation("com.browserbase.api:stagehand-java:0.2.0") +implementation("com.browserbase.api:stagehand-java:0.3.0") ``` ### Maven @@ -33,7 +33,7 @@ implementation("com.browserbase.api:stagehand-java:0.2.0") com.browserbase.api stagehand-java - 0.2.0 + 0.3.0 ``` diff --git a/build.gradle.kts b/build.gradle.kts index 63a11b4..d06f0a9 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 {