From 94f5e41da83de8caa24c27b32d430f8ea5e6d0d8 Mon Sep 17 00:00:00 2001 From: Matthew Tang Date: Tue, 10 Jun 2025 14:46:07 -0700 Subject: [PATCH 001/602] feat: Add support for Veo frame interpolation and video extension PiperOrigin-RevId: 769807331 --- .../google/genai/examples/GenerateVideos.java | 1 + .../genai/examples/GenerateVideosAsync.java | 1 + .../java/com/google/genai/AsyncModels.java | 10 +- src/main/java/com/google/genai/Models.java | 96 ++++++++++++++++++- .../genai/types/GenerateVideosConfig.java | 26 +++++ .../genai/types/GenerateVideosParameters.java | 31 +++++- .../java/com/google/genai/OperationsTest.java | 1 + 7 files changed, 157 insertions(+), 9 deletions(-) diff --git a/examples/src/main/java/com/google/genai/examples/GenerateVideos.java b/examples/src/main/java/com/google/genai/examples/GenerateVideos.java index 3f7faf64a06..9aea0a414e0 100644 --- a/examples/src/main/java/com/google/genai/examples/GenerateVideos.java +++ b/examples/src/main/java/com/google/genai/examples/GenerateVideos.java @@ -77,6 +77,7 @@ public static void main(String[] args) { "veo-2.0-generate-001", "A neon hologram of a cat driving at top speed", null, + null, generateVideosConfig); // GenerateVideosOperation.done() is empty if the operation is not done. diff --git a/examples/src/main/java/com/google/genai/examples/GenerateVideosAsync.java b/examples/src/main/java/com/google/genai/examples/GenerateVideosAsync.java index 4897db41b92..a31e6b34bf9 100644 --- a/examples/src/main/java/com/google/genai/examples/GenerateVideosAsync.java +++ b/examples/src/main/java/com/google/genai/examples/GenerateVideosAsync.java @@ -78,6 +78,7 @@ public static void main(String[] args) { "veo-2.0-generate-001", "A neon hologram of a cat driving at top speed", null, + null, generateVideosConfig); generateVideosOperationFuture diff --git a/src/main/java/com/google/genai/AsyncModels.java b/src/main/java/com/google/genai/AsyncModels.java index 05bd6c277dd..93400028306 100644 --- a/src/main/java/com/google/genai/AsyncModels.java +++ b/src/main/java/com/google/genai/AsyncModels.java @@ -46,6 +46,7 @@ import com.google.genai.types.UpdateModelConfig; import com.google.genai.types.UpscaleImageConfig; import com.google.genai.types.UpscaleImageResponse; +import com.google.genai.types.Video; import java.util.List; import java.util.concurrent.CompletableFuture; import java.util.function.Function; @@ -122,21 +123,24 @@ public CompletableFuture computeTokens( } /** - * Asynchronously generates videos given a GenAI model, and a prompt or an image. + * Asynchronously generates videos given a GenAI model, and an input (text, image, or video). * *

This method is experimental. * * @param model the name of the GenAI model to use for generating videos * @param prompt the text prompt for generating the videos. Optional for image to video use cases. * @param image the input image for generating the videos. Optional if prompt is provided. + * @param video the input video for video extension use cases. Optional if prompt or image is + * provided. * @param config a {@link com.google.genai.types.GenerateVideosConfig} instance that specifies the * optional configurations * @return a {@link com.google.genai.types.GenerateVideosOperation} instance that contains the * generated videos. */ public CompletableFuture generateVideos( - String model, String prompt, Image image, GenerateVideosConfig config) { - return CompletableFuture.supplyAsync(() -> models.generateVideos(model, prompt, image, config)); + String model, String prompt, Image image, Video video, GenerateVideosConfig config) { + return CompletableFuture.supplyAsync( + () -> models.generateVideos(model, prompt, image, video, config)); } /** diff --git a/src/main/java/com/google/genai/Models.java b/src/main/java/com/google/genai/Models.java index 94baff7bebf..7d1bb8ad9a2 100644 --- a/src/main/java/com/google/genai/Models.java +++ b/src/main/java/com/google/genai/Models.java @@ -69,6 +69,7 @@ import com.google.genai.types.UpscaleImageAPIParameters; import com.google.genai.types.UpscaleImageConfig; import com.google.genai.types.UpscaleImageResponse; +import com.google.genai.types.Video; import java.io.IOException; import java.lang.reflect.Method; import java.util.ArrayList; @@ -1687,6 +1688,34 @@ ObjectNode imageToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode par return toObject; } + @ExcludeFromGeneratedCoverageReport + ObjectNode videoToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"uri"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"video", "uri"}, + Common.getValueByPath(fromObject, new String[] {"uri"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"videoBytes"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"video", "encodedVideo"}, + Transformers.tBytes( + this.apiClient, Common.getValueByPath(fromObject, new String[] {"videoBytes"}))); + } + + if (Common.getValueByPath(fromObject, new String[] {"mimeType"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"encoding"}, + Common.getValueByPath(fromObject, new String[] {"mimeType"})); + } + + return toObject; + } + @ExcludeFromGeneratedCoverageReport ObjectNode generateVideosConfigToMldev( ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { @@ -1758,6 +1787,10 @@ ObjectNode generateVideosConfigToMldev( throw new IllegalArgumentException("generateAudio parameter is not supported in Gemini API."); } + if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"lastFrame"}))) { + throw new IllegalArgumentException("lastFrame parameter is not supported in Gemini API."); + } + return toObject; } @@ -1791,6 +1824,10 @@ ObjectNode generateVideosParametersToMldev( toObject)); } + if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"video"}))) { + throw new IllegalArgumentException("video parameter is not supported in Gemini API."); + } + if (Common.getValueByPath(fromObject, new String[] {"config"}) != null) { Common.setValueByPath( toObject, @@ -3910,6 +3947,34 @@ ObjectNode computeTokensParametersToVertex( return toObject; } + @ExcludeFromGeneratedCoverageReport + ObjectNode videoToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"uri"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"gcsUri"}, + Common.getValueByPath(fromObject, new String[] {"uri"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"videoBytes"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"bytesBase64Encoded"}, + Transformers.tBytes( + this.apiClient, Common.getValueByPath(fromObject, new String[] {"videoBytes"}))); + } + + if (Common.getValueByPath(fromObject, new String[] {"mimeType"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"mimeType"}, + Common.getValueByPath(fromObject, new String[] {"mimeType"})); + } + + return toObject; + } + @ExcludeFromGeneratedCoverageReport ObjectNode generateVideosConfigToVertex( ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { @@ -3999,6 +4064,17 @@ ObjectNode generateVideosConfigToVertex( Common.getValueByPath(fromObject, new String[] {"generateAudio"})); } + if (Common.getValueByPath(fromObject, new String[] {"lastFrame"}) != null) { + Common.setValueByPath( + parentObject, + new String[] {"instances[0]", "lastFrame"}, + imageToVertex( + apiClient, + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"lastFrame"})), + toObject)); + } + return toObject; } @@ -4032,6 +4108,17 @@ ObjectNode generateVideosParametersToVertex( toObject)); } + if (Common.getValueByPath(fromObject, new String[] {"video"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"instances[0]", "video"}, + videoToVertex( + apiClient, + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"video"})), + toObject)); + } + if (Common.getValueByPath(fromObject, new String[] {"config"}) != null) { Common.setValueByPath( toObject, @@ -6698,20 +6785,22 @@ public ComputeTokensResponse computeTokens( } /** - * Generates videos given a GenAI model, and a prompt or an image. + * Generates videos given a GenAI model, and an input (text, image, or video). * *

This method is experimental. * * @param model the name of the GenAI model to use for generating videos * @param prompt the text prompt for generating the videos. Optional for image to video use cases. * @param image the input image for generating the videos. Optional if prompt is provided. + * @param video the input video for video extension use cases. Optional if prompt or image is + * provided. * @param config a {@link com.google.genai.types.GenerateVideosConfig} instance that specifies the * optional configurations * @return a {@link com.google.genai.types.GenerateVideosOperation} instance that contains the * generated videos. */ public GenerateVideosOperation generateVideos( - String model, String prompt, Image image, GenerateVideosConfig config) { + String model, String prompt, Image image, Video video, GenerateVideosConfig config) { GenerateVideosParameters.Builder parameterBuilder = GenerateVideosParameters.builder(); @@ -6724,6 +6813,9 @@ public GenerateVideosOperation generateVideos( if (!Common.isZero(image)) { parameterBuilder.image(image); } + if (!Common.isZero(video)) { + parameterBuilder.video(video); + } if (!Common.isZero(config)) { parameterBuilder.config(config); } diff --git a/src/main/java/com/google/genai/types/GenerateVideosConfig.java b/src/main/java/com/google/genai/types/GenerateVideosConfig.java index 32605aebcec..1ff013293f6 100644 --- a/src/main/java/com/google/genai/types/GenerateVideosConfig.java +++ b/src/main/java/com/google/genai/types/GenerateVideosConfig.java @@ -93,6 +93,13 @@ public abstract class GenerateVideosConfig extends JsonSerializable { @JsonProperty("generateAudio") public abstract Optional generateAudio(); + /** + * Image to use as the last frame of generated videos. Only supported for image to video use + * cases. + */ + @JsonProperty("lastFrame") + public abstract Optional lastFrame(); + /** Instantiates a builder for GenerateVideosConfig. */ public static Builder builder() { return new AutoValue_GenerateVideosConfig.Builder(); @@ -228,6 +235,25 @@ public Builder httpOptions(HttpOptions.Builder httpOptionsBuilder) { @JsonProperty("generateAudio") public abstract Builder generateAudio(boolean generateAudio); + /** + * Setter for lastFrame. + * + *

lastFrame: Image to use as the last frame of generated videos. Only supported for image to + * video use cases. + */ + @JsonProperty("lastFrame") + public abstract Builder lastFrame(Image lastFrame); + + /** + * Setter for lastFrame builder. + * + *

lastFrame: Image to use as the last frame of generated videos. Only supported for image to + * video use cases. + */ + public Builder lastFrame(Image.Builder lastFrameBuilder) { + return lastFrame(lastFrameBuilder.build()); + } + public abstract GenerateVideosConfig build(); } diff --git a/src/main/java/com/google/genai/types/GenerateVideosParameters.java b/src/main/java/com/google/genai/types/GenerateVideosParameters.java index 719883572dd..3382b826425 100644 --- a/src/main/java/com/google/genai/types/GenerateVideosParameters.java +++ b/src/main/java/com/google/genai/types/GenerateVideosParameters.java @@ -26,7 +26,7 @@ import com.google.genai.JsonSerializable; import java.util.Optional; -/** Class that represents the parameters for generating an image. */ +/** Class that represents the parameters for generating videos. */ @AutoValue @InternalApi @JsonDeserialize(builder = GenerateVideosParameters.Builder.class) @@ -42,10 +42,14 @@ public abstract class GenerateVideosParameters extends JsonSerializable { @JsonProperty("prompt") public abstract Optional prompt(); - /** The input image for generating the videos. Optional if prompt is provided. */ + /** The input image for generating the videos. Optional if prompt or video is provided. */ @JsonProperty("image") public abstract Optional image(); + /** The input video for video extension use cases. Optional if prompt or image is provided. */ + @JsonProperty("video") + public abstract Optional

image: The input image for generating the videos. Optional if prompt is provided. + *

image: The input image for generating the videos. Optional if prompt or video is provided. */ @JsonProperty("image") public abstract Builder image(Image image); @@ -95,12 +99,31 @@ private static Builder create() { /** * Setter for image builder. * - *

image: The input image for generating the videos. Optional if prompt is provided. + *

image: The input image for generating the videos. Optional if prompt or video is provided. */ public Builder image(Image.Builder imageBuilder) { return image(imageBuilder.build()); } + /** + * Setter for video. + * + *

video: The input video for video extension use cases. Optional if prompt or image is + * provided. + */ + @JsonProperty("video") + public abstract Builder video(Video video); + + /** + * Setter for video builder. + * + *

video: The input video for video extension use cases. Optional if prompt or image is + * provided. + */ + public Builder video(Video.Builder videoBuilder) { + return video(videoBuilder.build()); + } + /** * Setter for config. * diff --git a/src/test/java/com/google/genai/OperationsTest.java b/src/test/java/com/google/genai/OperationsTest.java index c5e2b62d511..4cd1a6b763e 100644 --- a/src/test/java/com/google/genai/OperationsTest.java +++ b/src/test/java/com/google/genai/OperationsTest.java @@ -53,6 +53,7 @@ public void testGetVideosOperation(boolean vertexAI) throws Exception { "veo-2.0-generate-001", "A neon hologram of a cat driving at top speed", null, + null, generateVideosConfig); // GenerateVideosOperation.done() is empty if the operation is not done. From 7a4a8ac093adba2f0fb7b2558b41274da450010c Mon Sep 17 00:00:00 2001 From: Jaycee Li Date: Wed, 11 Jun 2025 11:54:43 -0700 Subject: [PATCH 002/602] feat: Support maxConnections and maxConnectionsPerHost in Client instantiation PiperOrigin-RevId: 770254513 --- src/main/java/com/google/genai/ApiClient.java | 52 +++++--- src/main/java/com/google/genai/Client.java | 46 +++++-- .../java/com/google/genai/HttpApiClient.java | 13 +- .../com/google/genai/ReplayApiClient.java | 7 +- .../com/google/genai/types/ClientOptions.java | 80 ++++++++++++ .../com/google/genai/FakeUploadApiClient.java | 6 +- .../com/google/genai/HttpApiClientTest.java | 119 +++++++++++++++--- 7 files changed, 277 insertions(+), 46 deletions(-) create mode 100644 src/main/java/com/google/genai/types/ClientOptions.java diff --git a/src/main/java/com/google/genai/ApiClient.java b/src/main/java/com/google/genai/ApiClient.java index d6159c38884..82fdf4e2a19 100644 --- a/src/main/java/com/google/genai/ApiClient.java +++ b/src/main/java/com/google/genai/ApiClient.java @@ -22,6 +22,7 @@ import com.google.auth.oauth2.GoogleCredentials; import com.google.common.collect.ImmutableMap; import com.google.genai.errors.GenAiIOException; +import com.google.genai.types.ClientOptions; import com.google.genai.types.HttpOptions; import java.io.IOException; import java.util.Map; @@ -32,6 +33,7 @@ import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.impl.client.HttpClients; +import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; import org.jspecify.annotations.Nullable; /** Interface for an API client which issues HTTP requests to the GenAI APIs. */ @@ -41,19 +43,24 @@ abstract class ApiClient { private static final Logger logger = Logger.getLogger(ApiClient.class.getName()); CloseableHttpClient httpClient; - // For Google AI APIs + HttpOptions httpOptions; + final boolean vertexAI; + final Optional clientOptions; + // For Gemini APIs final Optional apiKey; // For Vertex AI APIs final Optional project; final Optional location; final Optional credentials; - HttpOptions httpOptions; - final boolean vertexAI; /** Constructs an ApiClient for Google AI APIs. */ - protected ApiClient(Optional apiKey, Optional customHttpOptions) { + protected ApiClient( + Optional apiKey, + Optional customHttpOptions, + Optional clientOptions) { checkNotNull(apiKey, "API Key cannot be null"); checkNotNull(customHttpOptions, "customHttpOptions cannot be null"); + checkNotNull(clientOptions, "clientOptions cannot be null"); try { this.apiKey = Optional.of(apiKey.orElse(getApiKeyFromEnv())); @@ -68,6 +75,7 @@ protected ApiClient(Optional apiKey, Optional customHttpOpt this.location = Optional.empty(); this.credentials = Optional.empty(); this.vertexAI = false; + this.clientOptions = clientOptions; this.httpOptions = defaultHttpOptions(/* vertexAI= */ false, this.location); @@ -75,18 +83,20 @@ protected ApiClient(Optional apiKey, Optional customHttpOpt this.httpOptions = mergeHttpOptions(customHttpOptions.get()); } - this.httpClient = createHttpClient(httpOptions.timeout()); + this.httpClient = createHttpClient(httpOptions.timeout(), clientOptions); } ApiClient( Optional project, Optional location, Optional credentials, - Optional customHttpOptions) { + Optional customHttpOptions, + Optional clientOptions) { checkNotNull(project, "project cannot be null"); checkNotNull(location, "location cannot be null"); checkNotNull(credentials, "credentials cannot be null"); checkNotNull(customHttpOptions, "customHttpOptions cannot be null"); + checkNotNull(clientOptions, "clientOptions cannot be null"); try { this.project = Optional.of(project.orElse(System.getenv("GOOGLE_CLOUD_PROJECT"))); @@ -114,6 +124,8 @@ protected ApiClient(Optional apiKey, Optional customHttpOpt this.credentials = Optional.of(credentials.orElseGet(() -> defaultCredentials())); + this.clientOptions = clientOptions; + this.httpOptions = defaultHttpOptions(/* vertexAI= */ true, this.location); if (customHttpOptions.isPresent()) { @@ -121,7 +133,7 @@ protected ApiClient(Optional apiKey, Optional customHttpOpt } this.apiKey = Optional.empty(); this.vertexAI = true; - this.httpClient = createHttpClient(httpOptions.timeout()); + this.httpClient = createHttpClient(httpOptions.timeout(), clientOptions); } private String getApiKeyFromEnv() { @@ -143,15 +155,23 @@ private String getApiKeyFromEnv() { return geminiApiKey; } - private CloseableHttpClient createHttpClient(Optional timeout) { - if (!timeout.isPresent()) { - return HttpClients.createDefault(); - } - RequestConfig config = - RequestConfig.custom() - .setConnectTimeout(timeout.get()) - .build(); - return HttpClientBuilder.create().setDefaultRequestConfig(config).build(); + private CloseableHttpClient createHttpClient( + Optional timeout, Optional clientOptions) { + HttpClientBuilder builder = HttpClients.custom(); + + RequestConfig.Builder requestConfigBuilder = RequestConfig.custom(); + timeout.ifPresent(connectTimeout -> requestConfigBuilder.setConnectTimeout(connectTimeout)); + builder.setDefaultRequestConfig(requestConfigBuilder.build()); + + PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(); + clientOptions.ifPresent( + options -> { + options.maxConnections().ifPresent(connectionManager::setMaxTotal); + options.maxConnectionsPerHost().ifPresent(connectionManager::setDefaultMaxPerRoute); + }); + builder.setConnectionManager(connectionManager); + + return builder.build(); } /** Sends a Http request given the http method, path, and request json string. */ diff --git a/src/main/java/com/google/genai/Client.java b/src/main/java/com/google/genai/Client.java index ed4ae43b122..661a60c41ee 100644 --- a/src/main/java/com/google/genai/Client.java +++ b/src/main/java/com/google/genai/Client.java @@ -19,7 +19,9 @@ import static com.google.common.base.Preconditions.checkNotNull; import com.google.auth.oauth2.GoogleCredentials; +import com.google.errorprone.annotations.CanIgnoreReturnValue; import com.google.genai.errors.GenAiIOException; +import com.google.genai.types.ClientOptions; import com.google.genai.types.HttpOptions; import java.io.IOException; import java.util.HashMap; @@ -85,6 +87,7 @@ public static class Builder { private Optional project = Optional.empty(); private Optional location = Optional.empty(); private Optional credentials = Optional.empty(); + private Optional clientOptions = Optional.empty(); private Optional httpOptions = Optional.empty(); private Optional vertexAI = Optional.empty(); private Optional debugConfig = Optional.empty(); @@ -98,12 +101,14 @@ public Client build() { location, credentials, httpOptions, + clientOptions, vertexAI, debugConfig, environmentVariables); } /** Sets the API key for Gemini API. */ + @CanIgnoreReturnValue public Builder apiKey(String apiKey) { checkNotNull(apiKey, "apiKey cannot be null"); this.apiKey = Optional.of(apiKey); @@ -111,6 +116,7 @@ public Builder apiKey(String apiKey) { } /** Sets the project ID for Vertex AI APIs. */ + @CanIgnoreReturnValue public Builder project(String project) { checkNotNull(project, "project cannot be null"); this.project = Optional.of(project); @@ -118,6 +124,7 @@ public Builder project(String project) { } /** Sets the location for Vertex AI APIs. */ + @CanIgnoreReturnValue public Builder location(String location) { checkNotNull(location, "location cannot be null"); this.location = Optional.of(location); @@ -125,13 +132,23 @@ public Builder location(String location) { } /** Sets the {@link GoogleCredentials} for Vertex AI APIs. */ + @CanIgnoreReturnValue public Builder credentials(GoogleCredentials credentials) { checkNotNull(credentials, "credentials cannot be null"); this.credentials = Optional.of(credentials); return this; } + /** Sets the {@link ClientOptions} for the API client. */ + @CanIgnoreReturnValue + public Builder clientOptions(ClientOptions clientOptions) { + checkNotNull(clientOptions, "clientOptions cannot be null"); + this.clientOptions = Optional.of(clientOptions); + return this; + } + /** Sets the {@link HttpOptions} for the API client. */ + @CanIgnoreReturnValue public Builder httpOptions(HttpOptions httpOptions) { checkNotNull(httpOptions, "httpOptions cannot be null"); this.httpOptions = Optional.of(httpOptions); @@ -139,6 +156,7 @@ public Builder httpOptions(HttpOptions httpOptions) { } /** Sets whether to use Vertex AI APIs. */ + @CanIgnoreReturnValue public Builder vertexAI(boolean vertexAI) { this.vertexAI = Optional.of(vertexAI); return this; @@ -148,6 +166,7 @@ public Builder vertexAI(boolean vertexAI) { * Sets the {@link DebugConfig} for debugging or testing the Client. This is for internal use * only. */ + @CanIgnoreReturnValue Builder debugConfig(DebugConfig debugConfig) { checkNotNull(debugConfig, "debugConfig cannot be null"); this.debugConfig = Optional.of(debugConfig); @@ -155,6 +174,7 @@ Builder debugConfig(DebugConfig debugConfig) { } /** Sets the environment variables for the API client. This is for internal use only. */ + @CanIgnoreReturnValue Builder environmentVariables(Map environmentVariables) { this.environmentVariables = Optional.of(environmentVariables); return this; @@ -174,6 +194,7 @@ public Client() { /* location= */ Optional.empty(), /* credentials= */ Optional.empty(), /* httpOptions= */ Optional.empty(), + /* clientOptions= */ Optional.empty(), /* vertexAI= */ Optional.empty(), /* debugConfig= */ Optional.empty(), /* environmentVariables= */ Optional.empty()); @@ -182,14 +203,17 @@ public Client() { /** * Constructs a Client instance with the given parameters. * - * @param apiKey Optional String for the API key. - * Gemini API only. - * @param project Optional String for the project ID. Vertex AI APIs only. - * Find your project ID - * @param location Optional String for the location. + * @param apiKey Optional String for the API key. Gemini API only. + * @param project Optional String for the project ID. Vertex AI APIs only. Find your project + * ID + * @param location Optional String for the location. * Vertex AI APIs only. * @param credentials Optional {@link GoogleCredentials}. Vertex AI APIs only. * @param httpOptions Optional {@link HttpOptions} for sending HTTP requests. + * @param clientOptions Optional {@link ClientOptions} for the API client. * @param vertexAI Optional Boolean for whether to use Vertex AI APIs. If not specified here nor * in the environment variable, default to false. * @param debugConfig Optional {@link DebugConfig} for debugging or testing the Client. @@ -202,6 +226,7 @@ private Client( Optional location, Optional credentials, Optional httpOptions, + Optional clientOptions, Optional vertexAI, Optional debugConfig, Optional> environmentVariables) { @@ -253,6 +278,7 @@ private Client( new ReplayApiClient( /* apiKey= */ apiKey, /* httpOptions= */ httpOptions, + /* clientOptions= */ clientOptions, this.debugConfig.replaysDirectory(), this.debugConfig.replayId(), this.debugConfig.clientMode()); @@ -264,20 +290,26 @@ private Client( /* location= */ location, /* credentials= */ credentials, /* httpOptions= */ httpOptions, + /* clientOptions= */ clientOptions, this.debugConfig.replaysDirectory(), this.debugConfig.replayId(), this.debugConfig.clientMode()); } } else { if (!useVertexAI) { - this.apiClient = new HttpApiClient(/* apiKey= */ apiKey, /* httpOptions= */ httpOptions); + this.apiClient = + new HttpApiClient( + /* apiKey= */ apiKey, + /* httpOptions= */ httpOptions, + /* clientOptions= */ clientOptions); } else { this.apiClient = new HttpApiClient( /* project= */ project, /* location= */ location, /* credentials= */ credentials, - /* httpOptions= */ httpOptions); + /* httpOptions= */ httpOptions, + /* clientOptions= */ clientOptions); } } diff --git a/src/main/java/com/google/genai/HttpApiClient.java b/src/main/java/com/google/genai/HttpApiClient.java index d7375d20704..701d09a2cb3 100644 --- a/src/main/java/com/google/genai/HttpApiClient.java +++ b/src/main/java/com/google/genai/HttpApiClient.java @@ -20,6 +20,7 @@ import com.google.auth.oauth2.GoogleCredentials; import com.google.common.collect.ImmutableMap; import com.google.genai.errors.GenAiIOException; +import com.google.genai.types.ClientOptions; import com.google.genai.types.HttpOptions; import java.io.IOException; import java.util.Map; @@ -38,8 +39,11 @@ public class HttpApiClient extends ApiClient { /** Constructs an ApiClient for Google AI APIs. */ - HttpApiClient(Optional apiKey, Optional httpOptions) { - super(apiKey, httpOptions); + HttpApiClient( + Optional apiKey, + Optional httpOptions, + Optional clientOptions) { + super(apiKey, httpOptions, clientOptions); } /** Constructs an ApiClient for Vertex AI APIs. */ @@ -47,8 +51,9 @@ public class HttpApiClient extends ApiClient { Optional project, Optional location, Optional credentials, - Optional httpOptions) { - super(project, location, credentials, httpOptions); + Optional httpOptions, + Optional clientOptions) { + super(project, location, credentials, httpOptions, clientOptions); } /** Sends a Http request given the http method, path, request json string, and http options. */ diff --git a/src/main/java/com/google/genai/ReplayApiClient.java b/src/main/java/com/google/genai/ReplayApiClient.java index 0b77174624b..37708ce4c11 100644 --- a/src/main/java/com/google/genai/ReplayApiClient.java +++ b/src/main/java/com/google/genai/ReplayApiClient.java @@ -23,6 +23,7 @@ import com.google.auth.oauth2.GoogleCredentials; import com.google.genai.errors.GenAiIOException; import com.google.genai.types.HttpOptions; +import com.google.genai.types.ClientOptions; import java.io.ByteArrayInputStream; import java.io.IOException; import java.nio.charset.StandardCharsets; @@ -59,10 +60,11 @@ final class ReplayApiClient extends ApiClient { ReplayApiClient( Optional apiKey, Optional httpOptions, + Optional clientOptions, String replaysDirectory, String replayId, String clientMode) { - super(apiKey, httpOptions); + super(apiKey, httpOptions, clientOptions); checkNotNull(replaysDirectory, "replaysDirectory cannot be null"); checkNotNull(replayId, "replayId cannot be null"); checkNotNull(clientMode, "clientMode cannot be null"); @@ -78,10 +80,11 @@ final class ReplayApiClient extends ApiClient { Optional location, Optional credentials, Optional httpOptions, + Optional clientOptions, String replaysDirectory, String replayId, String clientMode) { - super(project, location, credentials, httpOptions); + super(project, location, credentials, httpOptions, clientOptions); checkNotNull(replaysDirectory, "replaysDirectory cannot be null"); checkNotNull(replayId, "replayId cannot be null"); checkNotNull(clientMode, "clientMode cannot be null"); diff --git a/src/main/java/com/google/genai/types/ClientOptions.java b/src/main/java/com/google/genai/types/ClientOptions.java new file mode 100644 index 00000000000..8157b162225 --- /dev/null +++ b/src/main/java/com/google/genai/types/ClientOptions.java @@ -0,0 +1,80 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Auto-generated code. Do not edit. + +package com.google.genai.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.google.auto.value.AutoValue; +import com.google.genai.JsonSerializable; +import java.util.Optional; + +/** Client options to be used in the client instantiation. */ +@AutoValue +@JsonDeserialize(builder = ClientOptions.Builder.class) +public abstract class ClientOptions extends JsonSerializable { + /** The maximum number of connections allowed in the pool. */ + @JsonProperty("maxConnections") + public abstract Optional maxConnections(); + + /** The maximum number of connections allowed per host. */ + @JsonProperty("maxConnectionsPerHost") + public abstract Optional maxConnectionsPerHost(); + + /** Instantiates a builder for ClientOptions. */ + public static Builder builder() { + return new AutoValue_ClientOptions.Builder(); + } + + /** Creates a builder with the same values as this instance. */ + public abstract Builder toBuilder(); + + /** Builder for ClientOptions. */ + @AutoValue.Builder + public abstract static class Builder { + /** For internal usage. Please use `ClientOptions.builder()` for instantiation. */ + @JsonCreator + private static Builder create() { + return new AutoValue_ClientOptions.Builder(); + } + + /** + * Setter for maxConnections. + * + *

maxConnections: The maximum number of connections allowed in the pool. + */ + @JsonProperty("maxConnections") + public abstract Builder maxConnections(Integer maxConnections); + + /** + * Setter for maxConnectionsPerHost. + * + *

maxConnectionsPerHost: The maximum number of connections allowed per host. + */ + @JsonProperty("maxConnectionsPerHost") + public abstract Builder maxConnectionsPerHost(Integer maxConnectionsPerHost); + + public abstract ClientOptions build(); + } + + /** Deserializes a JSON string to a ClientOptions object. */ + public static ClientOptions fromJson(String jsonString) { + return JsonSerializable.fromJsonString(jsonString, ClientOptions.class); + } +} diff --git a/src/test/java/com/google/genai/FakeUploadApiClient.java b/src/test/java/com/google/genai/FakeUploadApiClient.java index edacdee13b0..12c1a9278ee 100644 --- a/src/test/java/com/google/genai/FakeUploadApiClient.java +++ b/src/test/java/com/google/genai/FakeUploadApiClient.java @@ -16,6 +16,7 @@ package com.google.genai; +import com.google.genai.types.ClientOptions; import com.google.genai.types.HttpOptions; import java.util.ArrayList; import java.util.HashMap; @@ -32,7 +33,10 @@ public final class FakeUploadApiClient extends ApiClient { private final Map fileUploadFailureCount; public FakeUploadApiClient() { - super(Optional.of("fake-api-key"), Optional.empty()); + super( + Optional.of("fake-api-key"), + Optional.empty(), + Optional.empty()); fileUploadFailureCount = new HashMap<>(); this.files = new HashMap<>(); } diff --git a/src/test/java/com/google/genai/HttpApiClientTest.java b/src/test/java/com/google/genai/HttpApiClientTest.java index fbd890965ef..7a0091ba156 100644 --- a/src/test/java/com/google/genai/HttpApiClientTest.java +++ b/src/test/java/com/google/genai/HttpApiClientTest.java @@ -26,6 +26,7 @@ import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.fail; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -35,6 +36,7 @@ import com.google.auth.oauth2.GoogleCredentials; import com.google.common.collect.ImmutableMap; import com.google.genai.types.Candidate; +import com.google.genai.types.ClientOptions; import com.google.genai.types.Content; import com.google.genai.types.GenerateContentResponse; import com.google.genai.types.HttpOptions; @@ -49,8 +51,10 @@ import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.apache.http.client.methods.HttpRequestBase; +import org.apache.http.conn.ClientConnectionManager; import org.apache.http.entity.ContentType; import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; import org.apache.http.util.EntityUtils; import org.junit.jupiter.api.Test; import org.mockito.ArgumentCaptor; @@ -96,7 +100,11 @@ public void testRequestPostMethodWithVertexAI() throws Exception { // Arrange HttpApiClient client = new HttpApiClient( - Optional.of(PROJECT), Optional.of(LOCATION), Optional.empty(), Optional.empty()); + Optional.of(PROJECT), + Optional.of(LOCATION), + Optional.empty(), + Optional.empty(), + Optional.empty()); setMockClient(client); // Act @@ -129,7 +137,8 @@ public void testRequestPostMethodWithVertexAI() throws Exception { @Test public void testRequestGetMethodWithMldev() throws Exception { // Arrange - HttpApiClient client = new HttpApiClient(Optional.of(API_KEY), Optional.empty()); + HttpApiClient client = + new HttpApiClient(Optional.of(API_KEY), Optional.empty(), Optional.empty()); setMockClient(client); // Act @@ -154,7 +163,8 @@ public void testRequestGetMethodWithMldev() throws Exception { @Test public void testRequestDeleteMethodWithMldev() throws Exception { // Arrange - HttpApiClient client = new HttpApiClient(Optional.of(API_KEY), Optional.empty()); + HttpApiClient client = + new HttpApiClient(Optional.of(API_KEY), Optional.empty(), Optional.empty()); setMockClient(client); // Act @@ -179,7 +189,8 @@ public void testRequestDeleteMethodWithMldev() throws Exception { @Test public void testRequestWithHttpOptions() throws Exception { // Arrange - HttpApiClient client = new HttpApiClient(Optional.of(API_KEY), Optional.empty()); + HttpApiClient client = + new HttpApiClient(Optional.of(API_KEY), Optional.empty(), Optional.empty()); setMockClient(client); // Act @@ -208,7 +219,8 @@ public void testInitHttpClientMldev() throws Exception { .headers(ImmutableMap.of("test", "application/json")) .timeout(5000) .build(); - HttpApiClient client = new HttpApiClient(Optional.of(API_KEY), Optional.of(httpOptions)); + HttpApiClient client = + new HttpApiClient(Optional.of(API_KEY), Optional.of(httpOptions), Optional.empty()); assertEquals(API_KEY, client.apiKey()); assertFalse(client.vertexAI()); @@ -239,7 +251,8 @@ public void testInitHttpClientVertex() throws Exception { Optional.of(PROJECT), Optional.of(LOCATION), Optional.empty(), - Optional.of(httpOptions)); + Optional.of(httpOptions), + Optional.empty()); assertEquals(PROJECT, client.project()); assertEquals(LOCATION, client.location()); @@ -261,7 +274,8 @@ public void testInitHttpClientVertex() throws Exception { @Test public void testInitHttpClientMldevWithPartialHttpOptions() throws Exception { HttpOptions httpOptions = HttpOptions.builder().apiVersion("v100").timeout(5000).build(); - HttpApiClient client = new HttpApiClient(Optional.of("api-key"), Optional.of(httpOptions)); + HttpApiClient client = + new HttpApiClient(Optional.of("api-key"), Optional.of(httpOptions), Optional.empty()); assertEquals(httpOptions.apiVersion(), client.httpOptions.apiVersion()); assertEquals(httpOptions.timeout(), client.httpOptions.timeout()); @@ -280,7 +294,8 @@ public void testInitHttpClientVertexWithPartialHttpOptions() throws Exception { Optional.of(PROJECT), Optional.of(LOCATION), Optional.empty(), - Optional.of(httpOptions)); + Optional.of(httpOptions), + Optional.empty()); assertEquals(httpOptions.apiVersion(), client.httpOptions.apiVersion()); assertEquals(httpOptions.timeout(), client.httpOptions.timeout()); @@ -294,7 +309,8 @@ public void testInitHttpClientVertexWithPartialHttpOptions() throws Exception { @Test public void testHttpClientMLDevTimeout() throws Exception { HttpOptions httpOptions = HttpOptions.builder().timeout(5000).build(); - HttpApiClient client = new HttpApiClient(Optional.of("api-key"), Optional.of(httpOptions)); + HttpApiClient client = + new HttpApiClient(Optional.of("api-key"), Optional.of(httpOptions), Optional.empty()); CloseableHttpClient httpClient = client.httpClient(); assertNotNull(httpClient); @@ -314,7 +330,8 @@ public void testHttpClientVertexTimeout() throws Exception { Optional credentials = Optional.of(GoogleCredentials.getApplicationDefault()); HttpApiClient client = - new HttpApiClient(project, location, credentials, Optional.of(httpOptions)); + new HttpApiClient( + project, location, credentials, Optional.of(httpOptions), Optional.empty()); CloseableHttpClient httpClient = client.httpClient(); assertNotNull(httpClient); @@ -330,7 +347,8 @@ public void testHttpClientVertexTimeout() throws Exception { @Test public void testHttpClientNoTimeout() throws Exception { HttpOptions httpOptions = HttpOptions.builder().build(); - HttpApiClient client = new HttpApiClient(Optional.of("api-key"), Optional.of(httpOptions)); + HttpApiClient client = + new HttpApiClient(Optional.of("api-key"), Optional.of(httpOptions), Optional.empty()); CloseableHttpClient httpClient = client.httpClient(); assertNotNull(httpClient); @@ -350,7 +368,8 @@ public void testHttpClientVertexNoTimeout() throws Exception { Optional credentials = Optional.of(GoogleCredentials.getApplicationDefault()); HttpApiClient client = - new HttpApiClient(project, location, credentials, Optional.of(httpOptions)); + new HttpApiClient( + project, location, credentials, Optional.of(httpOptions), Optional.empty()); CloseableHttpClient httpClient = client.httpClient(); assertNotNull(httpClient); @@ -364,12 +383,73 @@ public void testHttpClientVertexNoTimeout() throws Exception { assertFalse(client.httpOptions.headers().get().containsKey("X-Server-Timeout")); } + @Test + public void testHttpClientMldevCustomClientOptions() throws Exception { + ClientOptions clientOptions = + ClientOptions.builder().maxConnections(64).maxConnectionsPerHost(16).build(); + HttpApiClient client = + new HttpApiClient(Optional.of("api-key"), Optional.empty(), Optional.of(clientOptions)); + + PoolingHttpClientConnectionManager connectionManager = + getConnectionManager(client.httpClient()); + + assertEquals("api-key", client.apiKey()); + assertFalse(client.vertexAI()); + assertEquals(64, connectionManager.getMaxTotal()); + assertEquals(16, connectionManager.getDefaultMaxPerRoute()); + } + + @Test + public void testHttpClientVertexCustomClientOptions() throws Exception { + ClientOptions clientOptions = + ClientOptions.builder().maxConnections(64).maxConnectionsPerHost(16).build(); + HttpApiClient client = + new HttpApiClient( + Optional.of("project"), + Optional.of("location"), + Optional.empty(), + Optional.empty(), + Optional.of(clientOptions)); + + PoolingHttpClientConnectionManager connectionManager = + getConnectionManager(client.httpClient()); + + assertEquals("project", client.project()); + assertEquals("location", client.location()); + assertTrue(client.vertexAI()); + assertEquals(64, connectionManager.getMaxTotal()); + assertEquals(16, connectionManager.getDefaultMaxPerRoute()); + } + + @Test + public void testHttpClientMldevDefaultClientOptions() throws Exception { + HttpApiClient client = + new HttpApiClient(Optional.of("api-key"), Optional.empty(), Optional.empty()); + + PoolingHttpClientConnectionManager connectionManager = + getConnectionManager(client.httpClient()); + + // Default values for max connections and max connections per host are 20 and 2 respectively + // (set by the Apache HttpClient). + assertEquals(20, connectionManager.getMaxTotal()); + assertEquals(2, connectionManager.getDefaultMaxPerRoute()); + assertEquals("api-key", client.apiKey()); + assertFalse(client.vertexAI()); + } + private RequestConfig getRequestConfig(CloseableHttpClient client) throws Exception { Field configField = client.getClass().getDeclaredField("defaultConfig"); configField.setAccessible(true); return (RequestConfig) configField.get(client); } + private PoolingHttpClientConnectionManager getConnectionManager(CloseableHttpClient client) + throws Exception { + Field connectionManagerField = client.getClass().getDeclaredField("connManager"); + connectionManagerField.setAccessible(true); + return (PoolingHttpClientConnectionManager) connectionManagerField.get(client); + } + @Test public void testHttpClientWithCustomCredentials() throws Exception { GoogleCredentials credentials = Mockito.mock(GoogleCredentials.class); @@ -379,7 +459,8 @@ public void testHttpClientWithCustomCredentials() throws Exception { Optional.of("project"), Optional.of("us-central1"), Optional.of(credentials), - Optional.of(httpOptions)); + Optional.of(httpOptions), + Optional.empty()); assertEquals(credentials, client.credentials.get()); } @@ -391,7 +472,8 @@ public void testHttpClientVertexWithGlobalEndpoint() throws Exception { Optional.of(PROJECT), Optional.of("global"), Optional.empty(), - Optional.of(httpOptions)); + Optional.of(httpOptions), + Optional.empty()); assertEquals("global", client.location()); assertTrue(client.vertexAI()); @@ -402,7 +484,11 @@ public void testHttpClientVertexWithGlobalEndpoint() throws Exception { public void testHttpClientVertexWithNoHttpOptions() throws Exception { HttpApiClient client = new HttpApiClient( - Optional.of(PROJECT), Optional.of("global"), Optional.empty(), Optional.empty()); + Optional.of(PROJECT), + Optional.of("global"), + Optional.empty(), + Optional.empty(), + Optional.empty()); assertEquals("global", client.location()); assertTrue(client.vertexAI()); @@ -412,7 +498,8 @@ public void testHttpClientVertexWithNoHttpOptions() throws Exception { @Test public void testHttpClientMLDevWithNoHttpOptions() throws Exception { - HttpApiClient client = new HttpApiClient(Optional.of("api-key"), Optional.empty()); + HttpApiClient client = + new HttpApiClient(Optional.of("api-key"), Optional.empty(), Optional.empty()); assertEquals(API_KEY, client.apiKey()); assertFalse(client.vertexAI()); From cd63fd0bdb124d8d2bebabc68f29a504ae1f3e7e Mon Sep 17 00:00:00 2001 From: Jaycee Li Date: Wed, 11 Jun 2025 12:06:49 -0700 Subject: [PATCH 003/602] feat: Support varargs in Enum setter methods PiperOrigin-RevId: 770260431 --- .../examples/LiveAudioConversationAsync.java | 3 +- ...LiveTextContextWindowCompressionAsync.java | 2 +- .../examples/LiveTextConversationAsync.java | 3 +- .../LiveTextConversationResumptionAsync.java | 3 +- .../LiveTextToAudioTranscriptionAsync.java | 2 +- .../LiveTextToTextGenerationAsync.java | 4 +- .../com/google/genai/types/AuthConfig.java | 12 ++++- .../types/AutomaticActivityDetection.java | 24 +++++++++- .../com/google/genai/types/Candidate.java | 14 +++++- .../genai/types/CodeExecutionResult.java | 12 ++++- .../genai/types/ControlReferenceConfig.java | 12 ++++- .../genai/types/DynamicRetrievalConfig.java | 12 ++++- .../google/genai/types/EditImageConfig.java | 48 +++++++++++++++++-- .../google/genai/types/ExecutableCode.java | 10 ++++ .../java/com/google/genai/types/File.java | 24 +++++++++- .../genai/types/FunctionCallingConfig.java | 12 ++++- .../genai/types/FunctionDeclaration.java | 12 ++++- .../google/genai/types/FunctionResponse.java | 14 +++++- .../genai/types/GenerateContentConfig.java | 12 ++++- ...GenerateContentResponsePromptFeedback.java | 12 ++++- .../GenerateContentResponseUsageMetadata.java | 12 +++++ .../genai/types/GenerateImagesConfig.java | 36 ++++++++++++-- .../google/genai/types/GenerationConfig.java | 44 ++++++++++++++++- ...ionConfigRoutingConfigAutoRoutingMode.java | 10 ++++ .../google/genai/types/LiveConnectConfig.java | 48 ++++++++++++++++++- .../genai/types/MaskReferenceConfig.java | 14 +++++- .../genai/types/ModalityTokenCount.java | 12 ++++- .../genai/types/ModelSelectionConfig.java | 10 ++++ .../genai/types/RealtimeInputConfig.java | 22 ++++++++- .../com/google/genai/types/SafetyRating.java | 36 ++++++++++++-- .../com/google/genai/types/SafetySetting.java | 36 +++++++++++++- .../java/com/google/genai/types/Schema.java | 10 ++++ .../genai/types/SubjectReferenceConfig.java | 12 ++++- .../com/google/genai/types/UrlMetadata.java | 10 ++++ .../com/google/genai/types/UsageMetadata.java | 12 +++++ 35 files changed, 526 insertions(+), 45 deletions(-) diff --git a/examples/src/main/java/com/google/genai/examples/LiveAudioConversationAsync.java b/examples/src/main/java/com/google/genai/examples/LiveAudioConversationAsync.java index 619f84f4291..be5533f2963 100644 --- a/examples/src/main/java/com/google/genai/examples/LiveAudioConversationAsync.java +++ b/examples/src/main/java/com/google/genai/examples/LiveAudioConversationAsync.java @@ -46,7 +46,6 @@ */ package com.google.genai.examples; -import com.google.common.collect.ImmutableList; import com.google.genai.AsyncSession; import com.google.genai.Client; import com.google.genai.types.Blob; @@ -161,7 +160,7 @@ public static void main(String[] args) throws LineUnavailableException { String voiceName = "Aoede"; LiveConnectConfig config = LiveConnectConfig.builder() - .responseModalitiesFromKnown(ImmutableList.of(Modality.Known.AUDIO)) + .responseModalities(Modality.Known.AUDIO) .speechConfig( SpeechConfig.builder() .voiceConfig( diff --git a/examples/src/main/java/com/google/genai/examples/LiveTextContextWindowCompressionAsync.java b/examples/src/main/java/com/google/genai/examples/LiveTextContextWindowCompressionAsync.java index 38390a22abe..793f5720dee 100644 --- a/examples/src/main/java/com/google/genai/examples/LiveTextContextWindowCompressionAsync.java +++ b/examples/src/main/java/com/google/genai/examples/LiveTextContextWindowCompressionAsync.java @@ -78,7 +78,7 @@ public static void main(String[] args) { LiveConnectConfig config = LiveConnectConfig.builder() - .responseModalitiesFromKnown(ImmutableList.of(Modality.Known.TEXT)) + .responseModalities(Modality.Known.TEXT) .contextWindowCompression( ContextWindowCompressionConfig.builder() .triggerTokens(1000L) diff --git a/examples/src/main/java/com/google/genai/examples/LiveTextConversationAsync.java b/examples/src/main/java/com/google/genai/examples/LiveTextConversationAsync.java index a059ca7057f..a266d46ba3c 100644 --- a/examples/src/main/java/com/google/genai/examples/LiveTextConversationAsync.java +++ b/examples/src/main/java/com/google/genai/examples/LiveTextConversationAsync.java @@ -41,7 +41,6 @@ */ package com.google.genai.examples; -import com.google.common.collect.ImmutableList; import com.google.genai.AsyncSession; import com.google.genai.Client; import com.google.genai.types.Content; @@ -77,7 +76,7 @@ public static void main(String[] args) { LiveConnectConfig config = LiveConnectConfig.builder() - .responseModalitiesFromKnown(ImmutableList.of(Modality.Known.TEXT)) + .responseModalities(Modality.Known.TEXT) .topP(0.8f) .seed(1234) .build(); diff --git a/examples/src/main/java/com/google/genai/examples/LiveTextConversationResumptionAsync.java b/examples/src/main/java/com/google/genai/examples/LiveTextConversationResumptionAsync.java index b176512b0d0..755af1453e3 100644 --- a/examples/src/main/java/com/google/genai/examples/LiveTextConversationResumptionAsync.java +++ b/examples/src/main/java/com/google/genai/examples/LiveTextConversationResumptionAsync.java @@ -49,7 +49,6 @@ */ package com.google.genai.examples; -import com.google.common.collect.ImmutableList; import com.google.genai.AsyncSession; import com.google.genai.Client; import com.google.genai.types.Content; @@ -110,7 +109,7 @@ public static void main(String[] args) { LiveConnectConfig config = LiveConnectConfig.builder() - .responseModalitiesFromKnown(ImmutableList.of(Modality.Known.TEXT)) + .responseModalities(Modality.Known.TEXT) .sessionResumption(sessionResumptionConfig) .topP(0.8f) .seed(1234) diff --git a/examples/src/main/java/com/google/genai/examples/LiveTextToAudioTranscriptionAsync.java b/examples/src/main/java/com/google/genai/examples/LiveTextToAudioTranscriptionAsync.java index 7bdd86c50ae..2ca5ffb7a2d 100644 --- a/examples/src/main/java/com/google/genai/examples/LiveTextToAudioTranscriptionAsync.java +++ b/examples/src/main/java/com/google/genai/examples/LiveTextToAudioTranscriptionAsync.java @@ -90,7 +90,7 @@ public static void main(String[] args) { LiveConnectConfig config = LiveConnectConfig.builder() - .responseModalitiesFromKnown(ImmutableList.of(Modality.Known.AUDIO)) + .responseModalities(Modality.Known.AUDIO) .outputAudioTranscription(AudioTranscriptionConfig.builder()) .systemInstruction(systemInstruction) .speechConfig(SpeechConfig.builder().languageCode("ja-JP")) diff --git a/examples/src/main/java/com/google/genai/examples/LiveTextToTextGenerationAsync.java b/examples/src/main/java/com/google/genai/examples/LiveTextToTextGenerationAsync.java index 203e126b5e7..924d00d302c 100644 --- a/examples/src/main/java/com/google/genai/examples/LiveTextToTextGenerationAsync.java +++ b/examples/src/main/java/com/google/genai/examples/LiveTextToTextGenerationAsync.java @@ -74,9 +74,7 @@ public static void main(String[] args) { } LiveConnectConfig config = - LiveConnectConfig.builder() - .responseModalitiesFromKnown(ImmutableList.of(Modality.Known.TEXT)) - .build(); + LiveConnectConfig.builder().responseModalities(Modality.Known.TEXT).build(); CompletableFuture allDone = new CompletableFuture<>(); diff --git a/src/main/java/com/google/genai/types/AuthConfig.java b/src/main/java/com/google/genai/types/AuthConfig.java index e3c371b34a5..eec5deb5f22 100644 --- a/src/main/java/com/google/genai/types/AuthConfig.java +++ b/src/main/java/com/google/genai/types/AuthConfig.java @@ -96,21 +96,31 @@ public Builder apiKeyConfig(ApiKeyConfig.Builder apiKeyConfigBuilder) { @JsonProperty("authType") public abstract Builder authType(AuthType authType); + /** + * Setter for authType given a known enum. + * + *

authType: Type of auth scheme. + */ @CanIgnoreReturnValue public Builder authType(AuthType.Known knownType) { return authType(new AuthType(knownType)); } + /** + * Setter for authType given a string. + * + *

authType: Type of auth scheme. + */ @CanIgnoreReturnValue public Builder authType(String authType) { return authType(new AuthType(authType)); } + /** * Setter for googleServiceAccountConfig. * *

googleServiceAccountConfig: Config for Google Service Account auth. */ - @JsonProperty("googleServiceAccountConfig") public abstract Builder googleServiceAccountConfig( AuthConfigGoogleServiceAccountConfig googleServiceAccountConfig); diff --git a/src/main/java/com/google/genai/types/AutomaticActivityDetection.java b/src/main/java/com/google/genai/types/AutomaticActivityDetection.java index 62a06907b4e..17f587ea59b 100644 --- a/src/main/java/com/google/genai/types/AutomaticActivityDetection.java +++ b/src/main/java/com/google/genai/types/AutomaticActivityDetection.java @@ -95,33 +95,54 @@ private static Builder create() { @JsonProperty("startOfSpeechSensitivity") public abstract Builder startOfSpeechSensitivity(StartSensitivity startOfSpeechSensitivity); + /** + * Setter for startOfSpeechSensitivity given a known enum. + * + *

startOfSpeechSensitivity: Determines how likely speech is to be detected. + */ @CanIgnoreReturnValue public Builder startOfSpeechSensitivity(StartSensitivity.Known knownType) { return startOfSpeechSensitivity(new StartSensitivity(knownType)); } + /** + * Setter for startOfSpeechSensitivity given a string. + * + *

startOfSpeechSensitivity: Determines how likely speech is to be detected. + */ @CanIgnoreReturnValue public Builder startOfSpeechSensitivity(String startOfSpeechSensitivity) { return startOfSpeechSensitivity(new StartSensitivity(startOfSpeechSensitivity)); } + /** * Setter for endOfSpeechSensitivity. * *

endOfSpeechSensitivity: Determines how likely detected speech is ended. */ - @JsonProperty("endOfSpeechSensitivity") public abstract Builder endOfSpeechSensitivity(EndSensitivity endOfSpeechSensitivity); + /** + * Setter for endOfSpeechSensitivity given a known enum. + * + *

endOfSpeechSensitivity: Determines how likely detected speech is ended. + */ @CanIgnoreReturnValue public Builder endOfSpeechSensitivity(EndSensitivity.Known knownType) { return endOfSpeechSensitivity(new EndSensitivity(knownType)); } + /** + * Setter for endOfSpeechSensitivity given a string. + * + *

endOfSpeechSensitivity: Determines how likely detected speech is ended. + */ @CanIgnoreReturnValue public Builder endOfSpeechSensitivity(String endOfSpeechSensitivity) { return endOfSpeechSensitivity(new EndSensitivity(endOfSpeechSensitivity)); } + /** * Setter for prefixPaddingMs. * @@ -130,7 +151,6 @@ public Builder endOfSpeechSensitivity(String endOfSpeechSensitivity) { * shorter speech can be recognized. However, this also increases the probability of false * positives. */ - @JsonProperty("prefixPaddingMs") public abstract Builder prefixPaddingMs(Integer prefixPaddingMs); diff --git a/src/main/java/com/google/genai/types/Candidate.java b/src/main/java/com/google/genai/types/Candidate.java index 362ce25d9e5..22d7e83006b 100644 --- a/src/main/java/com/google/genai/types/Candidate.java +++ b/src/main/java/com/google/genai/types/Candidate.java @@ -160,21 +160,33 @@ public Builder citationMetadata(CitationMetadata.Builder citationMetadataBuilder @JsonProperty("finishReason") public abstract Builder finishReason(FinishReason finishReason); + /** + * Setter for finishReason given a known enum. + * + *

finishReason: The reason why the model stopped generating tokens. If empty, the model has + * not stopped generating the tokens. + */ @CanIgnoreReturnValue public Builder finishReason(FinishReason.Known knownType) { return finishReason(new FinishReason(knownType)); } + /** + * Setter for finishReason given a string. + * + *

finishReason: The reason why the model stopped generating tokens. If empty, the model has + * not stopped generating the tokens. + */ @CanIgnoreReturnValue public Builder finishReason(String finishReason) { return finishReason(new FinishReason(finishReason)); } + /** * Setter for urlContextMetadata. * *

urlContextMetadata: Metadata related to url context retrieval tool. */ - @JsonProperty("urlContextMetadata") public abstract Builder urlContextMetadata(UrlContextMetadata urlContextMetadata); diff --git a/src/main/java/com/google/genai/types/CodeExecutionResult.java b/src/main/java/com/google/genai/types/CodeExecutionResult.java index 53c5199571f..df53b356b82 100644 --- a/src/main/java/com/google/genai/types/CodeExecutionResult.java +++ b/src/main/java/com/google/genai/types/CodeExecutionResult.java @@ -69,22 +69,32 @@ private static Builder create() { @JsonProperty("outcome") public abstract Builder outcome(Outcome outcome); + /** + * Setter for outcome given a known enum. + * + *

outcome: Required. Outcome of the code execution. + */ @CanIgnoreReturnValue public Builder outcome(Outcome.Known knownType) { return outcome(new Outcome(knownType)); } + /** + * Setter for outcome given a string. + * + *

outcome: Required. Outcome of the code execution. + */ @CanIgnoreReturnValue public Builder outcome(String outcome) { return outcome(new Outcome(outcome)); } + /** * Setter for output. * *

output: Optional. Contains stdout when code execution is successful, stderr or other * description otherwise. */ - @JsonProperty("output") public abstract Builder output(String output); diff --git a/src/main/java/com/google/genai/types/ControlReferenceConfig.java b/src/main/java/com/google/genai/types/ControlReferenceConfig.java index 90b773612d6..698999ca7c7 100644 --- a/src/main/java/com/google/genai/types/ControlReferenceConfig.java +++ b/src/main/java/com/google/genai/types/ControlReferenceConfig.java @@ -66,15 +66,26 @@ private static Builder create() { @JsonProperty("controlType") public abstract Builder controlType(ControlReferenceType controlType); + /** + * Setter for controlType given a known enum. + * + *

controlType: The type of control reference image to use. + */ @CanIgnoreReturnValue public Builder controlType(ControlReferenceType.Known knownType) { return controlType(new ControlReferenceType(knownType)); } + /** + * Setter for controlType given a string. + * + *

controlType: The type of control reference image to use. + */ @CanIgnoreReturnValue public Builder controlType(String controlType) { return controlType(new ControlReferenceType(controlType)); } + /** * Setter for enableControlImageComputation. * @@ -82,7 +93,6 @@ public Builder controlType(String controlType) { * be computed by the model based on the control type. When set to False, the control image must * be provided by the user. */ - @JsonProperty("enableControlImageComputation") public abstract Builder enableControlImageComputation(boolean enableControlImageComputation); diff --git a/src/main/java/com/google/genai/types/DynamicRetrievalConfig.java b/src/main/java/com/google/genai/types/DynamicRetrievalConfig.java index d30de309374..efc4f87949d 100644 --- a/src/main/java/com/google/genai/types/DynamicRetrievalConfig.java +++ b/src/main/java/com/google/genai/types/DynamicRetrievalConfig.java @@ -66,22 +66,32 @@ private static Builder create() { @JsonProperty("mode") public abstract Builder mode(DynamicRetrievalConfigMode mode); + /** + * Setter for mode given a known enum. + * + *

mode: The mode of the predictor to be used in dynamic retrieval. + */ @CanIgnoreReturnValue public Builder mode(DynamicRetrievalConfigMode.Known knownType) { return mode(new DynamicRetrievalConfigMode(knownType)); } + /** + * Setter for mode given a string. + * + *

mode: The mode of the predictor to be used in dynamic retrieval. + */ @CanIgnoreReturnValue public Builder mode(String mode) { return mode(new DynamicRetrievalConfigMode(mode)); } + /** * Setter for dynamicThreshold. * *

dynamicThreshold: Optional. The threshold to be used in dynamic retrieval. If not set, a * system default value is used. */ - @JsonProperty("dynamicThreshold") public abstract Builder dynamicThreshold(Float dynamicThreshold); diff --git a/src/main/java/com/google/genai/types/EditImageConfig.java b/src/main/java/com/google/genai/types/EditImageConfig.java index 223b3084f4c..3b78f330274 100644 --- a/src/main/java/com/google/genai/types/EditImageConfig.java +++ b/src/main/java/com/google/genai/types/EditImageConfig.java @@ -200,40 +200,60 @@ public Builder httpOptions(HttpOptions.Builder httpOptionsBuilder) { @JsonProperty("safetyFilterLevel") public abstract Builder safetyFilterLevel(SafetyFilterLevel safetyFilterLevel); + /** + * Setter for safetyFilterLevel given a known enum. + * + *

safetyFilterLevel: Filter level for safety filtering. + */ @CanIgnoreReturnValue public Builder safetyFilterLevel(SafetyFilterLevel.Known knownType) { return safetyFilterLevel(new SafetyFilterLevel(knownType)); } + /** + * Setter for safetyFilterLevel given a string. + * + *

safetyFilterLevel: Filter level for safety filtering. + */ @CanIgnoreReturnValue public Builder safetyFilterLevel(String safetyFilterLevel) { return safetyFilterLevel(new SafetyFilterLevel(safetyFilterLevel)); } + /** * Setter for personGeneration. * *

personGeneration: Allows generation of people by the model. */ - @JsonProperty("personGeneration") public abstract Builder personGeneration(PersonGeneration personGeneration); + /** + * Setter for personGeneration given a known enum. + * + *

personGeneration: Allows generation of people by the model. + */ @CanIgnoreReturnValue public Builder personGeneration(PersonGeneration.Known knownType) { return personGeneration(new PersonGeneration(knownType)); } + /** + * Setter for personGeneration given a string. + * + *

personGeneration: Allows generation of people by the model. + */ @CanIgnoreReturnValue public Builder personGeneration(String personGeneration) { return personGeneration(new PersonGeneration(personGeneration)); } + /** * Setter for includeSafetyAttributes. * *

includeSafetyAttributes: Whether to report the safety scores of each generated image and * the positive prompt in the response. */ - @JsonProperty("includeSafetyAttributes") public abstract Builder includeSafetyAttributes(boolean includeSafetyAttributes); @@ -254,21 +274,31 @@ public Builder personGeneration(String personGeneration) { @JsonProperty("language") public abstract Builder language(ImagePromptLanguage language); + /** + * Setter for language given a known enum. + * + *

language: Language of the text in the prompt. + */ @CanIgnoreReturnValue public Builder language(ImagePromptLanguage.Known knownType) { return language(new ImagePromptLanguage(knownType)); } + /** + * Setter for language given a string. + * + *

language: Language of the text in the prompt. + */ @CanIgnoreReturnValue public Builder language(String language) { return language(new ImagePromptLanguage(language)); } + /** * Setter for outputMimeType. * *

outputMimeType: MIME type of the generated image. */ - @JsonProperty("outputMimeType") public abstract Builder outputMimeType(String outputMimeType); @@ -289,22 +319,32 @@ public Builder language(String language) { @JsonProperty("editMode") public abstract Builder editMode(EditMode editMode); + /** + * Setter for editMode given a known enum. + * + *

editMode: Describes the editing mode for the request. + */ @CanIgnoreReturnValue public Builder editMode(EditMode.Known knownType) { return editMode(new EditMode(knownType)); } + /** + * Setter for editMode given a string. + * + *

editMode: Describes the editing mode for the request. + */ @CanIgnoreReturnValue public Builder editMode(String editMode) { return editMode(new EditMode(editMode)); } + /** * Setter for baseSteps. * *

baseSteps: The number of sampling steps. A higher value has better image quality, while a * lower value has better latency. */ - @JsonProperty("baseSteps") public abstract Builder baseSteps(Integer baseSteps); diff --git a/src/main/java/com/google/genai/types/ExecutableCode.java b/src/main/java/com/google/genai/types/ExecutableCode.java index f3a8181d0e6..da42fe5ed12 100644 --- a/src/main/java/com/google/genai/types/ExecutableCode.java +++ b/src/main/java/com/google/genai/types/ExecutableCode.java @@ -75,11 +75,21 @@ private static Builder create() { @JsonProperty("language") public abstract Builder language(Language language); + /** + * Setter for language given a known enum. + * + *

language: Required. Programming language of the `code`. + */ @CanIgnoreReturnValue public Builder language(Language.Known knownType) { return language(new Language(knownType)); } + /** + * Setter for language given a string. + * + *

language: Required. Programming language of the `code`. + */ @CanIgnoreReturnValue public Builder language(String language) { return language(new Language(language)); diff --git a/src/main/java/com/google/genai/types/File.java b/src/main/java/com/google/genai/types/File.java index 5216b6fb2d6..34ecb1e76d9 100644 --- a/src/main/java/com/google/genai/types/File.java +++ b/src/main/java/com/google/genai/types/File.java @@ -212,39 +212,59 @@ private static Builder create() { @JsonProperty("state") public abstract Builder state(FileState state); + /** + * Setter for state given a known enum. + * + *

state: Output only. Processing state of the File. + */ @CanIgnoreReturnValue public Builder state(FileState.Known knownType) { return state(new FileState(knownType)); } + /** + * Setter for state given a string. + * + *

state: Output only. Processing state of the File. + */ @CanIgnoreReturnValue public Builder state(String state) { return state(new FileState(state)); } + /** * Setter for source. * *

source: Output only. The source of the `File`. */ - @JsonProperty("source") public abstract Builder source(FileSource source); + /** + * Setter for source given a known enum. + * + *

source: Output only. The source of the `File`. + */ @CanIgnoreReturnValue public Builder source(FileSource.Known knownType) { return source(new FileSource(knownType)); } + /** + * Setter for source given a string. + * + *

source: Output only. The source of the `File`. + */ @CanIgnoreReturnValue public Builder source(String source) { return source(new FileSource(source)); } + /** * Setter for videoMetadata. * *

videoMetadata: Output only. Metadata for a video. */ - @JsonProperty("videoMetadata") public abstract Builder videoMetadata(Map videoMetadata); diff --git a/src/main/java/com/google/genai/types/FunctionCallingConfig.java b/src/main/java/com/google/genai/types/FunctionCallingConfig.java index 8fc1775ed18..cd64b08f89d 100644 --- a/src/main/java/com/google/genai/types/FunctionCallingConfig.java +++ b/src/main/java/com/google/genai/types/FunctionCallingConfig.java @@ -69,15 +69,26 @@ private static Builder create() { @JsonProperty("mode") public abstract Builder mode(FunctionCallingConfigMode mode); + /** + * Setter for mode given a known enum. + * + *

mode: Optional. Function calling mode. + */ @CanIgnoreReturnValue public Builder mode(FunctionCallingConfigMode.Known knownType) { return mode(new FunctionCallingConfigMode(knownType)); } + /** + * Setter for mode given a string. + * + *

mode: Optional. Function calling mode. + */ @CanIgnoreReturnValue public Builder mode(String mode) { return mode(new FunctionCallingConfigMode(mode)); } + /** * Setter for allowedFunctionNames. * @@ -85,7 +96,6 @@ public Builder mode(String mode) { * Function names should match [FunctionDeclaration.name]. With mode set to ANY, model will * predict a function call from the set of function names provided. */ - @JsonProperty("allowedFunctionNames") public abstract Builder allowedFunctionNames(List allowedFunctionNames); diff --git a/src/main/java/com/google/genai/types/FunctionDeclaration.java b/src/main/java/com/google/genai/types/FunctionDeclaration.java index 65ad4ffcc10..2e85affa285 100644 --- a/src/main/java/com/google/genai/types/FunctionDeclaration.java +++ b/src/main/java/com/google/genai/types/FunctionDeclaration.java @@ -103,22 +103,32 @@ private static Builder create() { @JsonProperty("behavior") public abstract Builder behavior(Behavior behavior); + /** + * Setter for behavior given a known enum. + * + *

behavior: Defines the function behavior. + */ @CanIgnoreReturnValue public Builder behavior(Behavior.Known knownType) { return behavior(new Behavior(knownType)); } + /** + * Setter for behavior given a string. + * + *

behavior: Defines the function behavior. + */ @CanIgnoreReturnValue public Builder behavior(String behavior) { return behavior(new Behavior(behavior)); } + /** * Setter for description. * *

description: Optional. Description and purpose of the function. Model uses it to decide * how and whether to call the function. */ - @JsonProperty("description") public abstract Builder description(String description); diff --git a/src/main/java/com/google/genai/types/FunctionResponse.java b/src/main/java/com/google/genai/types/FunctionResponse.java index 6cbe6aafc14..a3cdc1ecdea 100644 --- a/src/main/java/com/google/genai/types/FunctionResponse.java +++ b/src/main/java/com/google/genai/types/FunctionResponse.java @@ -111,22 +111,34 @@ private static Builder create() { @JsonProperty("scheduling") public abstract Builder scheduling(FunctionResponseScheduling scheduling); + /** + * Setter for scheduling given a known enum. + * + *

scheduling: Specifies how the response should be scheduled in the conversation. Only + * applicable to NON_BLOCKING function calls, is ignored otherwise. Defaults to WHEN_IDLE. + */ @CanIgnoreReturnValue public Builder scheduling(FunctionResponseScheduling.Known knownType) { return scheduling(new FunctionResponseScheduling(knownType)); } + /** + * Setter for scheduling given a string. + * + *

scheduling: Specifies how the response should be scheduled in the conversation. Only + * applicable to NON_BLOCKING function calls, is ignored otherwise. Defaults to WHEN_IDLE. + */ @CanIgnoreReturnValue public Builder scheduling(String scheduling) { return scheduling(new FunctionResponseScheduling(scheduling)); } + /** * Setter for id. * *

id: Optional. The id of the function call this response is for. Populated by the client to * match the corresponding function call `id`. */ - @JsonProperty("id") public abstract Builder id(String id); diff --git a/src/main/java/com/google/genai/types/GenerateContentConfig.java b/src/main/java/com/google/genai/types/GenerateContentConfig.java index 18201beb2f5..6e5574a647d 100644 --- a/src/main/java/com/google/genai/types/GenerateContentConfig.java +++ b/src/main/java/com/google/genai/types/GenerateContentConfig.java @@ -554,21 +554,31 @@ public Builder responseModalities(String... responseModalities) { @JsonProperty("mediaResolution") public abstract Builder mediaResolution(MediaResolution mediaResolution); + /** + * Setter for mediaResolution given a known enum. + * + *

mediaResolution: If specified, the media resolution specified will be used. + */ @CanIgnoreReturnValue public Builder mediaResolution(MediaResolution.Known knownType) { return mediaResolution(new MediaResolution(knownType)); } + /** + * Setter for mediaResolution given a string. + * + *

mediaResolution: If specified, the media resolution specified will be used. + */ @CanIgnoreReturnValue public Builder mediaResolution(String mediaResolution) { return mediaResolution(new MediaResolution(mediaResolution)); } + /** * Setter for speechConfig. * *

speechConfig: The speech generation configuration. */ - @JsonProperty("speechConfig") public abstract Builder speechConfig(SpeechConfig speechConfig); diff --git a/src/main/java/com/google/genai/types/GenerateContentResponsePromptFeedback.java b/src/main/java/com/google/genai/types/GenerateContentResponsePromptFeedback.java index 5bb67c1aba0..08be365950f 100644 --- a/src/main/java/com/google/genai/types/GenerateContentResponsePromptFeedback.java +++ b/src/main/java/com/google/genai/types/GenerateContentResponsePromptFeedback.java @@ -74,21 +74,31 @@ private static Builder create() { @JsonProperty("blockReason") public abstract Builder blockReason(BlockedReason blockReason); + /** + * Setter for blockReason given a known enum. + * + *

blockReason: Output only. Blocked reason. + */ @CanIgnoreReturnValue public Builder blockReason(BlockedReason.Known knownType) { return blockReason(new BlockedReason(knownType)); } + /** + * Setter for blockReason given a string. + * + *

blockReason: Output only. Blocked reason. + */ @CanIgnoreReturnValue public Builder blockReason(String blockReason) { return blockReason(new BlockedReason(blockReason)); } + /** * Setter for blockReasonMessage. * *

blockReasonMessage: Output only. A readable block reason message. */ - @JsonProperty("blockReasonMessage") public abstract Builder blockReasonMessage(String blockReasonMessage); diff --git a/src/main/java/com/google/genai/types/GenerateContentResponseUsageMetadata.java b/src/main/java/com/google/genai/types/GenerateContentResponseUsageMetadata.java index 5bb3605ac25..a268283e132 100644 --- a/src/main/java/com/google/genai/types/GenerateContentResponseUsageMetadata.java +++ b/src/main/java/com/google/genai/types/GenerateContentResponseUsageMetadata.java @@ -297,11 +297,23 @@ public Builder toolUsePromptTokensDetails( @JsonProperty("trafficType") public abstract Builder trafficType(TrafficType trafficType); + /** + * Setter for trafficType given a known enum. + * + *

trafficType: Output only. Traffic type. This shows whether a request consumes + * Pay-As-You-Go or Provisioned Throughput quota. + */ @CanIgnoreReturnValue public Builder trafficType(TrafficType.Known knownType) { return trafficType(new TrafficType(knownType)); } + /** + * Setter for trafficType given a string. + * + *

trafficType: Output only. Traffic type. This shows whether a request consumes + * Pay-As-You-Go or Provisioned Throughput quota. + */ @CanIgnoreReturnValue public Builder trafficType(String trafficType) { return trafficType(new TrafficType(trafficType)); diff --git a/src/main/java/com/google/genai/types/GenerateImagesConfig.java b/src/main/java/com/google/genai/types/GenerateImagesConfig.java index f51d2a76400..513b2f949fb 100644 --- a/src/main/java/com/google/genai/types/GenerateImagesConfig.java +++ b/src/main/java/com/google/genai/types/GenerateImagesConfig.java @@ -197,40 +197,60 @@ public Builder httpOptions(HttpOptions.Builder httpOptionsBuilder) { @JsonProperty("safetyFilterLevel") public abstract Builder safetyFilterLevel(SafetyFilterLevel safetyFilterLevel); + /** + * Setter for safetyFilterLevel given a known enum. + * + *

safetyFilterLevel: Filter level for safety filtering. + */ @CanIgnoreReturnValue public Builder safetyFilterLevel(SafetyFilterLevel.Known knownType) { return safetyFilterLevel(new SafetyFilterLevel(knownType)); } + /** + * Setter for safetyFilterLevel given a string. + * + *

safetyFilterLevel: Filter level for safety filtering. + */ @CanIgnoreReturnValue public Builder safetyFilterLevel(String safetyFilterLevel) { return safetyFilterLevel(new SafetyFilterLevel(safetyFilterLevel)); } + /** * Setter for personGeneration. * *

personGeneration: Allows generation of people by the model. */ - @JsonProperty("personGeneration") public abstract Builder personGeneration(PersonGeneration personGeneration); + /** + * Setter for personGeneration given a known enum. + * + *

personGeneration: Allows generation of people by the model. + */ @CanIgnoreReturnValue public Builder personGeneration(PersonGeneration.Known knownType) { return personGeneration(new PersonGeneration(knownType)); } + /** + * Setter for personGeneration given a string. + * + *

personGeneration: Allows generation of people by the model. + */ @CanIgnoreReturnValue public Builder personGeneration(String personGeneration) { return personGeneration(new PersonGeneration(personGeneration)); } + /** * Setter for includeSafetyAttributes. * *

includeSafetyAttributes: Whether to report the safety scores of each generated image and * the positive prompt in the response. */ - @JsonProperty("includeSafetyAttributes") public abstract Builder includeSafetyAttributes(boolean includeSafetyAttributes); @@ -251,21 +271,31 @@ public Builder personGeneration(String personGeneration) { @JsonProperty("language") public abstract Builder language(ImagePromptLanguage language); + /** + * Setter for language given a known enum. + * + *

language: Language of the text in the prompt. + */ @CanIgnoreReturnValue public Builder language(ImagePromptLanguage.Known knownType) { return language(new ImagePromptLanguage(knownType)); } + /** + * Setter for language given a string. + * + *

language: Language of the text in the prompt. + */ @CanIgnoreReturnValue public Builder language(String language) { return language(new ImagePromptLanguage(language)); } + /** * Setter for outputMimeType. * *

outputMimeType: MIME type of the generated image. */ - @JsonProperty("outputMimeType") public abstract Builder outputMimeType(String outputMimeType); diff --git a/src/main/java/com/google/genai/types/GenerationConfig.java b/src/main/java/com/google/genai/types/GenerationConfig.java index ed11b8a16d7..352cbfdee41 100644 --- a/src/main/java/com/google/genai/types/GenerationConfig.java +++ b/src/main/java/com/google/genai/types/GenerationConfig.java @@ -212,21 +212,31 @@ public Builder modelSelectionConfig(ModelSelectionConfig.Builder modelSelectionC @JsonProperty("mediaResolution") public abstract Builder mediaResolution(MediaResolution mediaResolution); + /** + * Setter for mediaResolution given a known enum. + * + *

mediaResolution: Optional. If specified, the media resolution specified will be used. + */ @CanIgnoreReturnValue public Builder mediaResolution(MediaResolution.Known knownType) { return mediaResolution(new MediaResolution(knownType)); } + /** + * Setter for mediaResolution given a string. + * + *

mediaResolution: Optional. If specified, the media resolution specified will be used. + */ @CanIgnoreReturnValue public Builder mediaResolution(String mediaResolution) { return mediaResolution(new MediaResolution(mediaResolution)); } + /** * Setter for presencePenalty. * *

presencePenalty: Optional. Positive penalties. */ - @JsonProperty("presencePenalty") public abstract Builder presencePenalty(Float presencePenalty); @@ -266,6 +276,31 @@ public Builder responseModalities(Modality... responseModalities) { return responseModalities(Arrays.asList(responseModalities)); } + /** + * Setter for responseModalities given a varargs of strings. + * + *

responseModalities: Optional. The modalities of the response. + */ + @CanIgnoreReturnValue + public Builder responseModalities(String... responseModalities) { + return responseModalitiesFromString(Arrays.asList(responseModalities)); + } + + /** + * Setter for responseModalities given a varargs of known enums. + * + *

responseModalities: Optional. The modalities of the response. + */ + @CanIgnoreReturnValue + public Builder responseModalities(Modality.Known... knownTypes) { + return responseModalitiesFromKnown(Arrays.asList(knownTypes)); + } + + /** + * Setter for responseModalities given a list of known enums. + * + *

responseModalities: Optional. The modalities of the response. + */ @CanIgnoreReturnValue public Builder responseModalitiesFromKnown(List knownTypes) { ImmutableList listItems = @@ -273,12 +308,18 @@ public Builder responseModalitiesFromKnown(List knownTypes) { return responseModalities(listItems); } + /** + * Setter for responseModalities given a list of strings. + * + *

responseModalities: Optional. The modalities of the response. + */ @CanIgnoreReturnValue public Builder responseModalitiesFromString(List responseModalities) { ImmutableList listItems = responseModalities.stream().map(Modality::new).collect(toImmutableList()); return responseModalities(listItems); } + /** * Setter for responseSchema. * @@ -288,7 +329,6 @@ public Builder responseModalitiesFromString(List responseModalities) { * set, a compatible response_mime_type must also be set. Compatible mimetypes: * `application/json`: Schema for JSON response. */ - @JsonProperty("responseSchema") public abstract Builder responseSchema(Schema responseSchema); diff --git a/src/main/java/com/google/genai/types/GenerationConfigRoutingConfigAutoRoutingMode.java b/src/main/java/com/google/genai/types/GenerationConfigRoutingConfigAutoRoutingMode.java index e9ea143ddb7..8031269346e 100644 --- a/src/main/java/com/google/genai/types/GenerationConfigRoutingConfigAutoRoutingMode.java +++ b/src/main/java/com/google/genai/types/GenerationConfigRoutingConfigAutoRoutingMode.java @@ -65,11 +65,21 @@ private static Builder create() { @JsonProperty("modelRoutingPreference") public abstract Builder modelRoutingPreference(ModelRoutingPreference modelRoutingPreference); + /** + * Setter for modelRoutingPreference given a known enum. + * + *

modelRoutingPreference: The model routing preference. + */ @CanIgnoreReturnValue public Builder modelRoutingPreference(ModelRoutingPreference.Known knownType) { return modelRoutingPreference(new ModelRoutingPreference(knownType)); } + /** + * Setter for modelRoutingPreference given a string. + * + *

modelRoutingPreference: The model routing preference. + */ @CanIgnoreReturnValue public Builder modelRoutingPreference(String modelRoutingPreference) { return modelRoutingPreference(new ModelRoutingPreference(modelRoutingPreference)); diff --git a/src/main/java/com/google/genai/types/LiveConnectConfig.java b/src/main/java/com/google/genai/types/LiveConnectConfig.java index 8c40f31747e..b345e177f68 100644 --- a/src/main/java/com/google/genai/types/LiveConnectConfig.java +++ b/src/main/java/com/google/genai/types/LiveConnectConfig.java @@ -200,6 +200,34 @@ public Builder responseModalities(Modality... responseModalities) { return responseModalities(Arrays.asList(responseModalities)); } + /** + * Setter for responseModalities given a varargs of strings. + * + *

responseModalities: The requested modalities of the response. Represents the set of + * modalities that the model can return. Defaults to AUDIO if not specified. + */ + @CanIgnoreReturnValue + public Builder responseModalities(String... responseModalities) { + return responseModalitiesFromString(Arrays.asList(responseModalities)); + } + + /** + * Setter for responseModalities given a varargs of known enums. + * + *

responseModalities: The requested modalities of the response. Represents the set of + * modalities that the model can return. Defaults to AUDIO if not specified. + */ + @CanIgnoreReturnValue + public Builder responseModalities(Modality.Known... knownTypes) { + return responseModalitiesFromKnown(Arrays.asList(knownTypes)); + } + + /** + * Setter for responseModalities given a list of known enums. + * + *

responseModalities: The requested modalities of the response. Represents the set of + * modalities that the model can return. Defaults to AUDIO if not specified. + */ @CanIgnoreReturnValue public Builder responseModalitiesFromKnown(List knownTypes) { ImmutableList listItems = @@ -207,12 +235,19 @@ public Builder responseModalitiesFromKnown(List knownTypes) { return responseModalities(listItems); } + /** + * Setter for responseModalities given a list of strings. + * + *

responseModalities: The requested modalities of the response. Represents the set of + * modalities that the model can return. Defaults to AUDIO if not specified. + */ @CanIgnoreReturnValue public Builder responseModalitiesFromString(List responseModalities) { ImmutableList listItems = responseModalities.stream().map(Modality::new).collect(toImmutableList()); return responseModalities(listItems); } + /** * Setter for temperature. * @@ -220,7 +255,6 @@ public Builder responseModalitiesFromString(List responseModalities) { * temperatures are good for prompts that require a less open-ended or creative response, while * higher temperatures can lead to more diverse or creative results. */ - @JsonProperty("temperature") public abstract Builder temperature(Float temperature); @@ -261,22 +295,32 @@ public Builder responseModalitiesFromString(List responseModalities) { @JsonProperty("mediaResolution") public abstract Builder mediaResolution(MediaResolution mediaResolution); + /** + * Setter for mediaResolution given a known enum. + * + *

mediaResolution: If specified, the media resolution specified will be used. + */ @CanIgnoreReturnValue public Builder mediaResolution(MediaResolution.Known knownType) { return mediaResolution(new MediaResolution(knownType)); } + /** + * Setter for mediaResolution given a string. + * + *

mediaResolution: If specified, the media resolution specified will be used. + */ @CanIgnoreReturnValue public Builder mediaResolution(String mediaResolution) { return mediaResolution(new MediaResolution(mediaResolution)); } + /** * Setter for seed. * *

seed: When ``seed`` is fixed to a specific number, the model makes a best effort to * provide the same response for repeated requests. By default, a random number is used. */ - @JsonProperty("seed") public abstract Builder seed(Integer seed); diff --git a/src/main/java/com/google/genai/types/MaskReferenceConfig.java b/src/main/java/com/google/genai/types/MaskReferenceConfig.java index 0860d247163..ac484ca90d2 100644 --- a/src/main/java/com/google/genai/types/MaskReferenceConfig.java +++ b/src/main/java/com/google/genai/types/MaskReferenceConfig.java @@ -76,22 +76,34 @@ private static Builder create() { @JsonProperty("maskMode") public abstract Builder maskMode(MaskReferenceMode maskMode); + /** + * Setter for maskMode given a known enum. + * + *

maskMode: Prompts the model to generate a mask instead of you needing to provide one + * (unless MASK_MODE_USER_PROVIDED is used). + */ @CanIgnoreReturnValue public Builder maskMode(MaskReferenceMode.Known knownType) { return maskMode(new MaskReferenceMode(knownType)); } + /** + * Setter for maskMode given a string. + * + *

maskMode: Prompts the model to generate a mask instead of you needing to provide one + * (unless MASK_MODE_USER_PROVIDED is used). + */ @CanIgnoreReturnValue public Builder maskMode(String maskMode) { return maskMode(new MaskReferenceMode(maskMode)); } + /** * Setter for segmentationClasses. * *

segmentationClasses: A list of up to 5 class ids to use for semantic segmentation. * Automatically creates an image mask based on specific objects. */ - @JsonProperty("segmentationClasses") public abstract Builder segmentationClasses(List segmentationClasses); diff --git a/src/main/java/com/google/genai/types/ModalityTokenCount.java b/src/main/java/com/google/genai/types/ModalityTokenCount.java index f91a1fe3f03..985366b09f7 100644 --- a/src/main/java/com/google/genai/types/ModalityTokenCount.java +++ b/src/main/java/com/google/genai/types/ModalityTokenCount.java @@ -63,21 +63,31 @@ private static Builder create() { @JsonProperty("modality") public abstract Builder modality(MediaModality modality); + /** + * Setter for modality given a known enum. + * + *

modality: The modality associated with this token count. + */ @CanIgnoreReturnValue public Builder modality(MediaModality.Known knownType) { return modality(new MediaModality(knownType)); } + /** + * Setter for modality given a string. + * + *

modality: The modality associated with this token count. + */ @CanIgnoreReturnValue public Builder modality(String modality) { return modality(new MediaModality(modality)); } + /** * Setter for tokenCount. * *

tokenCount: Number of tokens. */ - @JsonProperty("tokenCount") public abstract Builder tokenCount(Integer tokenCount); diff --git a/src/main/java/com/google/genai/types/ModelSelectionConfig.java b/src/main/java/com/google/genai/types/ModelSelectionConfig.java index dad49007c2c..0d2a30b591d 100644 --- a/src/main/java/com/google/genai/types/ModelSelectionConfig.java +++ b/src/main/java/com/google/genai/types/ModelSelectionConfig.java @@ -60,11 +60,21 @@ private static Builder create() { public abstract Builder featureSelectionPreference( FeatureSelectionPreference featureSelectionPreference); + /** + * Setter for featureSelectionPreference given a known enum. + * + *

featureSelectionPreference: Options for feature selection preference. + */ @CanIgnoreReturnValue public Builder featureSelectionPreference(FeatureSelectionPreference.Known knownType) { return featureSelectionPreference(new FeatureSelectionPreference(knownType)); } + /** + * Setter for featureSelectionPreference given a string. + * + *

featureSelectionPreference: Options for feature selection preference. + */ @CanIgnoreReturnValue public Builder featureSelectionPreference(String featureSelectionPreference) { return featureSelectionPreference(new FeatureSelectionPreference(featureSelectionPreference)); diff --git a/src/main/java/com/google/genai/types/RealtimeInputConfig.java b/src/main/java/com/google/genai/types/RealtimeInputConfig.java index 7464c09f2ae..745ea404704 100644 --- a/src/main/java/com/google/genai/types/RealtimeInputConfig.java +++ b/src/main/java/com/google/genai/types/RealtimeInputConfig.java @@ -95,29 +95,49 @@ public Builder automaticActivityDetection( @JsonProperty("activityHandling") public abstract Builder activityHandling(ActivityHandling activityHandling); + /** + * Setter for activityHandling given a known enum. + * + *

activityHandling: Defines what effect activity has. + */ @CanIgnoreReturnValue public Builder activityHandling(ActivityHandling.Known knownType) { return activityHandling(new ActivityHandling(knownType)); } + /** + * Setter for activityHandling given a string. + * + *

activityHandling: Defines what effect activity has. + */ @CanIgnoreReturnValue public Builder activityHandling(String activityHandling) { return activityHandling(new ActivityHandling(activityHandling)); } + /** * Setter for turnCoverage. * *

turnCoverage: Defines which input is included in the user's turn. */ - @JsonProperty("turnCoverage") public abstract Builder turnCoverage(TurnCoverage turnCoverage); + /** + * Setter for turnCoverage given a known enum. + * + *

turnCoverage: Defines which input is included in the user's turn. + */ @CanIgnoreReturnValue public Builder turnCoverage(TurnCoverage.Known knownType) { return turnCoverage(new TurnCoverage(knownType)); } + /** + * Setter for turnCoverage given a string. + * + *

turnCoverage: Defines which input is included in the user's turn. + */ @CanIgnoreReturnValue public Builder turnCoverage(String turnCoverage) { return turnCoverage(new TurnCoverage(turnCoverage)); diff --git a/src/main/java/com/google/genai/types/SafetyRating.java b/src/main/java/com/google/genai/types/SafetyRating.java index e7deddd05be..c5ca95faa1e 100644 --- a/src/main/java/com/google/genai/types/SafetyRating.java +++ b/src/main/java/com/google/genai/types/SafetyRating.java @@ -88,39 +88,59 @@ private static Builder create() { @JsonProperty("category") public abstract Builder category(HarmCategory category); + /** + * Setter for category given a known enum. + * + *

category: Output only. Harm category. + */ @CanIgnoreReturnValue public Builder category(HarmCategory.Known knownType) { return category(new HarmCategory(knownType)); } + /** + * Setter for category given a string. + * + *

category: Output only. Harm category. + */ @CanIgnoreReturnValue public Builder category(String category) { return category(new HarmCategory(category)); } + /** * Setter for probability. * *

probability: Output only. Harm probability levels in the content. */ - @JsonProperty("probability") public abstract Builder probability(HarmProbability probability); + /** + * Setter for probability given a known enum. + * + *

probability: Output only. Harm probability levels in the content. + */ @CanIgnoreReturnValue public Builder probability(HarmProbability.Known knownType) { return probability(new HarmProbability(knownType)); } + /** + * Setter for probability given a string. + * + *

probability: Output only. Harm probability levels in the content. + */ @CanIgnoreReturnValue public Builder probability(String probability) { return probability(new HarmProbability(probability)); } + /** * Setter for probabilityScore. * *

probabilityScore: Output only. Harm probability score. */ - @JsonProperty("probabilityScore") public abstract Builder probabilityScore(Float probabilityScore); @@ -132,21 +152,31 @@ public Builder probability(String probability) { @JsonProperty("severity") public abstract Builder severity(HarmSeverity severity); + /** + * Setter for severity given a known enum. + * + *

severity: Output only. Harm severity levels in the content. + */ @CanIgnoreReturnValue public Builder severity(HarmSeverity.Known knownType) { return severity(new HarmSeverity(knownType)); } + /** + * Setter for severity given a string. + * + *

severity: Output only. Harm severity levels in the content. + */ @CanIgnoreReturnValue public Builder severity(String severity) { return severity(new HarmSeverity(severity)); } + /** * Setter for severityScore. * *

severityScore: Output only. Harm severity score. */ - @JsonProperty("severityScore") public abstract Builder severityScore(Float severityScore); diff --git a/src/main/java/com/google/genai/types/SafetySetting.java b/src/main/java/com/google/genai/types/SafetySetting.java index 05a95051893..d9612db5a2c 100644 --- a/src/main/java/com/google/genai/types/SafetySetting.java +++ b/src/main/java/com/google/genai/types/SafetySetting.java @@ -68,47 +68,79 @@ private static Builder create() { @JsonProperty("method") public abstract Builder method(HarmBlockMethod method); + /** + * Setter for method given a known enum. + * + *

method: Determines if the harm block method uses probability or probability and severity + * scores. + */ @CanIgnoreReturnValue public Builder method(HarmBlockMethod.Known knownType) { return method(new HarmBlockMethod(knownType)); } + /** + * Setter for method given a string. + * + *

method: Determines if the harm block method uses probability or probability and severity + * scores. + */ @CanIgnoreReturnValue public Builder method(String method) { return method(new HarmBlockMethod(method)); } + /** * Setter for category. * *

category: Required. Harm category. */ - @JsonProperty("category") public abstract Builder category(HarmCategory category); + /** + * Setter for category given a known enum. + * + *

category: Required. Harm category. + */ @CanIgnoreReturnValue public Builder category(HarmCategory.Known knownType) { return category(new HarmCategory(knownType)); } + /** + * Setter for category given a string. + * + *

category: Required. Harm category. + */ @CanIgnoreReturnValue public Builder category(String category) { return category(new HarmCategory(category)); } + /** * Setter for threshold. * *

threshold: Required. The harm block threshold. */ - @JsonProperty("threshold") public abstract Builder threshold(HarmBlockThreshold threshold); + /** + * Setter for threshold given a known enum. + * + *

threshold: Required. The harm block threshold. + */ @CanIgnoreReturnValue public Builder threshold(HarmBlockThreshold.Known knownType) { return threshold(new HarmBlockThreshold(knownType)); } + /** + * Setter for threshold given a string. + * + *

threshold: Required. The harm block threshold. + */ @CanIgnoreReturnValue public Builder threshold(String threshold) { return threshold(new HarmBlockThreshold(threshold)); diff --git a/src/main/java/com/google/genai/types/Schema.java b/src/main/java/com/google/genai/types/Schema.java index 702e05e81eb..e87186890f0 100644 --- a/src/main/java/com/google/genai/types/Schema.java +++ b/src/main/java/com/google/genai/types/Schema.java @@ -409,11 +409,21 @@ public Builder required(String... required) { @JsonProperty("type") public abstract Builder type(Type type); + /** + * Setter for type given a known enum. + * + *

type: Optional. The type of the data. + */ @CanIgnoreReturnValue public Builder type(Type.Known knownType) { return type(new Type(knownType)); } + /** + * Setter for type given a string. + * + *

type: Optional. The type of the data. + */ @CanIgnoreReturnValue public Builder type(String type) { return type(new Type(type)); diff --git a/src/main/java/com/google/genai/types/SubjectReferenceConfig.java b/src/main/java/com/google/genai/types/SubjectReferenceConfig.java index 1c9417eac12..0b6dac72ada 100644 --- a/src/main/java/com/google/genai/types/SubjectReferenceConfig.java +++ b/src/main/java/com/google/genai/types/SubjectReferenceConfig.java @@ -63,21 +63,31 @@ private static Builder create() { @JsonProperty("subjectType") public abstract Builder subjectType(SubjectReferenceType subjectType); + /** + * Setter for subjectType given a known enum. + * + *

subjectType: The subject type of a subject reference image. + */ @CanIgnoreReturnValue public Builder subjectType(SubjectReferenceType.Known knownType) { return subjectType(new SubjectReferenceType(knownType)); } + /** + * Setter for subjectType given a string. + * + *

subjectType: The subject type of a subject reference image. + */ @CanIgnoreReturnValue public Builder subjectType(String subjectType) { return subjectType(new SubjectReferenceType(subjectType)); } + /** * Setter for subjectDescription. * *

subjectDescription: Subject description for the image. */ - @JsonProperty("subjectDescription") public abstract Builder subjectDescription(String subjectDescription); diff --git a/src/main/java/com/google/genai/types/UrlMetadata.java b/src/main/java/com/google/genai/types/UrlMetadata.java index a11db41bc03..f4316fbcf23 100644 --- a/src/main/java/com/google/genai/types/UrlMetadata.java +++ b/src/main/java/com/google/genai/types/UrlMetadata.java @@ -71,11 +71,21 @@ private static Builder create() { @JsonProperty("urlRetrievalStatus") public abstract Builder urlRetrievalStatus(UrlRetrievalStatus urlRetrievalStatus); + /** + * Setter for urlRetrievalStatus given a known enum. + * + *

urlRetrievalStatus: Status of the url retrieval. + */ @CanIgnoreReturnValue public Builder urlRetrievalStatus(UrlRetrievalStatus.Known knownType) { return urlRetrievalStatus(new UrlRetrievalStatus(knownType)); } + /** + * Setter for urlRetrievalStatus given a string. + * + *

urlRetrievalStatus: Status of the url retrieval. + */ @CanIgnoreReturnValue public Builder urlRetrievalStatus(String urlRetrievalStatus) { return urlRetrievalStatus(new UrlRetrievalStatus(urlRetrievalStatus)); diff --git a/src/main/java/com/google/genai/types/UsageMetadata.java b/src/main/java/com/google/genai/types/UsageMetadata.java index e2d15267e55..c1931eada88 100644 --- a/src/main/java/com/google/genai/types/UsageMetadata.java +++ b/src/main/java/com/google/genai/types/UsageMetadata.java @@ -281,11 +281,23 @@ public Builder toolUsePromptTokensDetails( @JsonProperty("trafficType") public abstract Builder trafficType(TrafficType trafficType); + /** + * Setter for trafficType given a known enum. + * + *

trafficType: Traffic type. This shows whether a request consumes Pay-As-You-Go or + * Provisioned Throughput quota. + */ @CanIgnoreReturnValue public Builder trafficType(TrafficType.Known knownType) { return trafficType(new TrafficType(knownType)); } + /** + * Setter for trafficType given a string. + * + *

trafficType: Traffic type. This shows whether a request consumes Pay-As-You-Go or + * Provisioned Throughput quota. + */ @CanIgnoreReturnValue public Builder trafficType(String trafficType) { return trafficType(new TrafficType(trafficType)); From 8c8b47a79cbf9014325aeeab156f99db6181a265 Mon Sep 17 00:00:00 2001 From: Matthew Tang Date: Wed, 11 Jun 2025 14:57:27 -0700 Subject: [PATCH 004/602] feat: Add datastore_spec field for VertexAISearch PiperOrigin-RevId: 770333468 --- .../google/genai/types/VertexAISearch.java | 47 ++++++++++ .../types/VertexAISearchDataStoreSpec.java | 94 +++++++++++++++++++ 2 files changed, 141 insertions(+) create mode 100644 src/main/java/com/google/genai/types/VertexAISearchDataStoreSpec.java diff --git a/src/main/java/com/google/genai/types/VertexAISearch.java b/src/main/java/com/google/genai/types/VertexAISearch.java index 161d7afdc18..f1c8bf213dc 100644 --- a/src/main/java/com/google/genai/types/VertexAISearch.java +++ b/src/main/java/com/google/genai/types/VertexAISearch.java @@ -18,11 +18,15 @@ package com.google.genai.types; +import static com.google.common.collect.ImmutableList.toImmutableList; + import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.google.auto.value.AutoValue; import com.google.genai.JsonSerializable; +import java.util.Arrays; +import java.util.List; import java.util.Optional; /** @@ -32,6 +36,14 @@ @AutoValue @JsonDeserialize(builder = VertexAISearch.Builder.class) public abstract class VertexAISearch extends JsonSerializable { + /** + * Specifications that define the specific DataStores to be searched, along with configurations + * for those data stores. This is only considered for Engines with multiple data stores. It should + * only be set if engine is used. + */ + @JsonProperty("dataStoreSpecs") + public abstract Optional> dataStoreSpecs(); + /** * Optional. Fully-qualified Vertex AI Search data store resource ID. Format: * `projects/{project}/locations/{location}/collections/{collection}/dataStores/{dataStore}` @@ -74,6 +86,41 @@ private static Builder create() { return new AutoValue_VertexAISearch.Builder(); } + /** + * Setter for dataStoreSpecs. + * + *

dataStoreSpecs: Specifications that define the specific DataStores to be searched, along + * with configurations for those data stores. This is only considered for Engines with multiple + * data stores. It should only be set if engine is used. + */ + @JsonProperty("dataStoreSpecs") + public abstract Builder dataStoreSpecs(List dataStoreSpecs); + + /** + * Setter for dataStoreSpecs. + * + *

dataStoreSpecs: Specifications that define the specific DataStores to be searched, along + * with configurations for those data stores. This is only considered for Engines with multiple + * data stores. It should only be set if engine is used. + */ + public Builder dataStoreSpecs(VertexAISearchDataStoreSpec... dataStoreSpecs) { + return dataStoreSpecs(Arrays.asList(dataStoreSpecs)); + } + + /** + * Setter for dataStoreSpecs builder. + * + *

dataStoreSpecs: Specifications that define the specific DataStores to be searched, along + * with configurations for those data stores. This is only considered for Engines with multiple + * data stores. It should only be set if engine is used. + */ + public Builder dataStoreSpecs(VertexAISearchDataStoreSpec.Builder... dataStoreSpecsBuilders) { + return dataStoreSpecs( + Arrays.asList(dataStoreSpecsBuilders).stream() + .map(VertexAISearchDataStoreSpec.Builder::build) + .collect(toImmutableList())); + } + /** * Setter for datastore. * diff --git a/src/main/java/com/google/genai/types/VertexAISearchDataStoreSpec.java b/src/main/java/com/google/genai/types/VertexAISearchDataStoreSpec.java new file mode 100644 index 00000000000..900a3027d14 --- /dev/null +++ b/src/main/java/com/google/genai/types/VertexAISearchDataStoreSpec.java @@ -0,0 +1,94 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Auto-generated code. Do not edit. + +package com.google.genai.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.google.auto.value.AutoValue; +import com.google.genai.JsonSerializable; +import java.util.Optional; + +/** + * Define data stores within engine to filter on in a search call and configurations for those data + * stores. For more information, see + * https://cloud.google.com/generative-ai-app-builder/docs/reference/rpc/google.cloud.discoveryengine.v1#datastorespec + */ +@AutoValue +@JsonDeserialize(builder = VertexAISearchDataStoreSpec.Builder.class) +public abstract class VertexAISearchDataStoreSpec extends JsonSerializable { + /** + * Full resource name of DataStore, such as Format: + * `projects/{project}/locations/{location}/collections/{collection}/dataStores/{dataStore}` + */ + @JsonProperty("dataStore") + public abstract Optional dataStore(); + + /** + * Optional. Filter specification to filter documents in the data store specified by data_store + * field. For more information on filtering, see + * [Filtering](https://cloud.google.com/generative-ai-app-builder/docs/filter-search-metadata) + */ + @JsonProperty("filter") + public abstract Optional filter(); + + /** Instantiates a builder for VertexAISearchDataStoreSpec. */ + public static Builder builder() { + return new AutoValue_VertexAISearchDataStoreSpec.Builder(); + } + + /** Creates a builder with the same values as this instance. */ + public abstract Builder toBuilder(); + + /** Builder for VertexAISearchDataStoreSpec. */ + @AutoValue.Builder + public abstract static class Builder { + /** For internal usage. Please use `VertexAISearchDataStoreSpec.builder()` for instantiation. */ + @JsonCreator + private static Builder create() { + return new AutoValue_VertexAISearchDataStoreSpec.Builder(); + } + + /** + * Setter for dataStore. + * + *

dataStore: Full resource name of DataStore, such as Format: + * `projects/{project}/locations/{location}/collections/{collection}/dataStores/{dataStore}` + */ + @JsonProperty("dataStore") + public abstract Builder dataStore(String dataStore); + + /** + * Setter for filter. + * + *

filter: Optional. Filter specification to filter documents in the data store specified by + * data_store field. For more information on filtering, see + * [Filtering](https://cloud.google.com/generative-ai-app-builder/docs/filter-search-metadata) + */ + @JsonProperty("filter") + public abstract Builder filter(String filter); + + public abstract VertexAISearchDataStoreSpec build(); + } + + /** Deserializes a JSON string to a VertexAISearchDataStoreSpec object. */ + public static VertexAISearchDataStoreSpec fromJson(String jsonString) { + return JsonSerializable.fromJsonString(jsonString, VertexAISearchDataStoreSpec.class); + } +} From 16289c16fff617f12b30f1bce6cebd3c7e68c8fa Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Wed, 11 Jun 2025 18:23:03 -0700 Subject: [PATCH 005/602] chore(main): release 1.4.0 (#320) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- .release-please-manifest.json | 2 +- CHANGELOG.md | 19 +++++++++++++++++++ examples/pom.xml | 2 +- pom.xml | 2 +- 4 files changed, 22 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 2a8f4ffddf0..3e9af1b3ae2 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "1.3.0" + ".": "1.4.0" } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 104a782e62a..5afd2377087 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,24 @@ # Changelog +## [1.4.0](https://github.com/googleapis/java-genai/compare/v1.3.0...v1.4.0) (2025-06-11) + + +### Features + +* Add datastore_spec field for VertexAISearch ([8c8b47a](https://github.com/googleapis/java-genai/commit/8c8b47a79cbf9014325aeeab156f99db6181a265)) +* Add support for Veo frame interpolation and video extension ([94f5e41](https://github.com/googleapis/java-genai/commit/94f5e41da83de8caa24c27b32d430f8ea5e6d0d8)) +* RAG - Introducing context storing for Gemini Live API. ([d63d625](https://github.com/googleapis/java-genai/commit/d63d62583f554aca88062dfbf3c77cc65da812dd)) +* Support maxConnections and maxConnectionsPerHost in Client instantiation ([7a4a8ac](https://github.com/googleapis/java-genai/commit/7a4a8ac093adba2f0fb7b2558b41274da450010c)) +* Support passing builder classes to setter methods ([996c994](https://github.com/googleapis/java-genai/commit/996c994d6a2697b8b79dd48a7460eed49a408884)) +* Support passing builder varargs to setter methods ([0b08524](https://github.com/googleapis/java-genai/commit/0b08524b002b656c9c8a7a7f667a9efabb69dcfb)) +* Support varargs in Enum setter methods ([cd63fd0](https://github.com/googleapis/java-genai/commit/cd63fd0bdb124d8d2bebabc68f29a504ae1f3e7e)) +* Support varargs in setter methods ([0b08524](https://github.com/googleapis/java-genai/commit/0b08524b002b656c9c8a7a7f667a9efabb69dcfb)) + + +### Documentation + +* Add javadoc for setter methods in types classes ([996c994](https://github.com/googleapis/java-genai/commit/996c994d6a2697b8b79dd48a7460eed49a408884)) + ## [1.3.0](https://github.com/googleapis/java-genai/compare/v1.2.0...v1.3.0) (2025-06-04) diff --git a/examples/pom.xml b/examples/pom.xml index 57d2a56ccb5..b348f9ebc00 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -5,7 +5,7 @@ com.google.genai.examples google-genai-examples - 1.4.0-SNAPSHOT + 1.4.0 google-genai-examples diff --git a/pom.xml b/pom.xml index bfdf0548ae1..f1993b9830e 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ com.google.genai google-genai google-genai - 1.4.0-SNAPSHOT + 1.4.0 jar Java idiomatic SDK for the Gemini Developer APIs and Vertex AI APIs. From ea168ec7c9b7ada04c18e34846fb701425bf9262 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Wed, 11 Jun 2025 18:35:20 -0700 Subject: [PATCH 006/602] chore(main): release 1.5.0-SNAPSHOT (#328) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- examples/pom.xml | 2 +- pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/pom.xml b/examples/pom.xml index b348f9ebc00..187d08b69f0 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -5,7 +5,7 @@ com.google.genai.examples google-genai-examples - 1.4.0 + 1.5.0-SNAPSHOT google-genai-examples diff --git a/pom.xml b/pom.xml index f1993b9830e..ea44cb843a1 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ com.google.genai google-genai google-genai - 1.4.0 + 1.5.0-SNAPSHOT jar Java idiomatic SDK for the Gemini Developer APIs and Vertex AI APIs. From e02e7ddc740820be0f9b124c2813bb02b484a69b Mon Sep 17 00:00:00 2001 From: jaycee-li Date: Thu, 12 Jun 2025 13:48:46 -0700 Subject: [PATCH 007/602] Revert "chore(main): release 1.4.0" This reverts commit 1fbd5662b981c78510c029899535c1cefa6ab60f. --- .release-please-manifest.json | 2 +- CHANGELOG.md | 19 ------------------- examples/pom.xml | 2 +- pom.xml | 2 +- 4 files changed, 3 insertions(+), 22 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 3e9af1b3ae2..2a8f4ffddf0 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "1.4.0" + ".": "1.3.0" } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 5afd2377087..104a782e62a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,24 +1,5 @@ # Changelog -## [1.4.0](https://github.com/googleapis/java-genai/compare/v1.3.0...v1.4.0) (2025-06-11) - - -### Features - -* Add datastore_spec field for VertexAISearch ([8c8b47a](https://github.com/googleapis/java-genai/commit/8c8b47a79cbf9014325aeeab156f99db6181a265)) -* Add support for Veo frame interpolation and video extension ([94f5e41](https://github.com/googleapis/java-genai/commit/94f5e41da83de8caa24c27b32d430f8ea5e6d0d8)) -* RAG - Introducing context storing for Gemini Live API. ([d63d625](https://github.com/googleapis/java-genai/commit/d63d62583f554aca88062dfbf3c77cc65da812dd)) -* Support maxConnections and maxConnectionsPerHost in Client instantiation ([7a4a8ac](https://github.com/googleapis/java-genai/commit/7a4a8ac093adba2f0fb7b2558b41274da450010c)) -* Support passing builder classes to setter methods ([996c994](https://github.com/googleapis/java-genai/commit/996c994d6a2697b8b79dd48a7460eed49a408884)) -* Support passing builder varargs to setter methods ([0b08524](https://github.com/googleapis/java-genai/commit/0b08524b002b656c9c8a7a7f667a9efabb69dcfb)) -* Support varargs in Enum setter methods ([cd63fd0](https://github.com/googleapis/java-genai/commit/cd63fd0bdb124d8d2bebabc68f29a504ae1f3e7e)) -* Support varargs in setter methods ([0b08524](https://github.com/googleapis/java-genai/commit/0b08524b002b656c9c8a7a7f667a9efabb69dcfb)) - - -### Documentation - -* Add javadoc for setter methods in types classes ([996c994](https://github.com/googleapis/java-genai/commit/996c994d6a2697b8b79dd48a7460eed49a408884)) - ## [1.3.0](https://github.com/googleapis/java-genai/compare/v1.2.0...v1.3.0) (2025-06-04) diff --git a/examples/pom.xml b/examples/pom.xml index 187d08b69f0..57d2a56ccb5 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -5,7 +5,7 @@ com.google.genai.examples google-genai-examples - 1.5.0-SNAPSHOT + 1.4.0-SNAPSHOT google-genai-examples diff --git a/pom.xml b/pom.xml index ea44cb843a1..bfdf0548ae1 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ com.google.genai google-genai google-genai - 1.5.0-SNAPSHOT + 1.4.0-SNAPSHOT jar Java idiomatic SDK for the Gemini Developer APIs and Vertex AI APIs. From 888b47d63fe328ae242472ada1b0ae7431752c05 Mon Sep 17 00:00:00 2001 From: jaycee-li Date: Thu, 12 Jun 2025 14:13:36 -0700 Subject: [PATCH 008/602] Recover 1.4.0 release --- .release-please-manifest.json | 2 +- CHANGELOG.md | 19 +++++++++++++++++++ examples/pom.xml | 2 +- pom.xml | 2 +- 4 files changed, 22 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 2a8f4ffddf0..3e9af1b3ae2 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "1.3.0" + ".": "1.4.0" } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 104a782e62a..5afd2377087 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,24 @@ # Changelog +## [1.4.0](https://github.com/googleapis/java-genai/compare/v1.3.0...v1.4.0) (2025-06-11) + + +### Features + +* Add datastore_spec field for VertexAISearch ([8c8b47a](https://github.com/googleapis/java-genai/commit/8c8b47a79cbf9014325aeeab156f99db6181a265)) +* Add support for Veo frame interpolation and video extension ([94f5e41](https://github.com/googleapis/java-genai/commit/94f5e41da83de8caa24c27b32d430f8ea5e6d0d8)) +* RAG - Introducing context storing for Gemini Live API. ([d63d625](https://github.com/googleapis/java-genai/commit/d63d62583f554aca88062dfbf3c77cc65da812dd)) +* Support maxConnections and maxConnectionsPerHost in Client instantiation ([7a4a8ac](https://github.com/googleapis/java-genai/commit/7a4a8ac093adba2f0fb7b2558b41274da450010c)) +* Support passing builder classes to setter methods ([996c994](https://github.com/googleapis/java-genai/commit/996c994d6a2697b8b79dd48a7460eed49a408884)) +* Support passing builder varargs to setter methods ([0b08524](https://github.com/googleapis/java-genai/commit/0b08524b002b656c9c8a7a7f667a9efabb69dcfb)) +* Support varargs in Enum setter methods ([cd63fd0](https://github.com/googleapis/java-genai/commit/cd63fd0bdb124d8d2bebabc68f29a504ae1f3e7e)) +* Support varargs in setter methods ([0b08524](https://github.com/googleapis/java-genai/commit/0b08524b002b656c9c8a7a7f667a9efabb69dcfb)) + + +### Documentation + +* Add javadoc for setter methods in types classes ([996c994](https://github.com/googleapis/java-genai/commit/996c994d6a2697b8b79dd48a7460eed49a408884)) + ## [1.3.0](https://github.com/googleapis/java-genai/compare/v1.2.0...v1.3.0) (2025-06-04) diff --git a/examples/pom.xml b/examples/pom.xml index 57d2a56ccb5..187d08b69f0 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -5,7 +5,7 @@ com.google.genai.examples google-genai-examples - 1.4.0-SNAPSHOT + 1.5.0-SNAPSHOT google-genai-examples diff --git a/pom.xml b/pom.xml index bfdf0548ae1..ea44cb843a1 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ com.google.genai google-genai google-genai - 1.4.0-SNAPSHOT + 1.5.0-SNAPSHOT jar Java idiomatic SDK for the Gemini Developer APIs and Vertex AI APIs. From 9978c8ccb048da47df871571301efcf44045762e Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Wed, 11 Jun 2025 18:30:08 -0700 Subject: [PATCH 009/602] Copybara import of the project: -- 1fbd5662b981c78510c029899535c1cefa6ab60f by release-please[bot] <55107282+release-please[bot]@users.noreply.github.com>: chore(main): release 1.4.0 COPYBARA_INTEGRATE_REVIEW=https://github.com/googleapis/java-genai/pull/320 from googleapis:release-please--branches--main 1fbd5662b981c78510c029899535c1cefa6ab60f PiperOrigin-RevId: 770407702 --- examples/pom.xml | 2 +- pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/pom.xml b/examples/pom.xml index 187d08b69f0..b348f9ebc00 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -5,7 +5,7 @@ com.google.genai.examples google-genai-examples - 1.5.0-SNAPSHOT + 1.4.0 google-genai-examples diff --git a/pom.xml b/pom.xml index ea44cb843a1..f1993b9830e 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ com.google.genai google-genai google-genai - 1.5.0-SNAPSHOT + 1.4.0 jar Java idiomatic SDK for the Gemini Developer APIs and Vertex AI APIs. From c4ad320da5cb04b4e0125f635da5a8d726e13e70 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Thu, 12 Jun 2025 14:37:23 -0700 Subject: [PATCH 010/602] Copybara import of the project: -- 16289c16fff617f12b30f1bce6cebd3c7e68c8fa by release-please[bot] <55107282+release-please[bot]@users.noreply.github.com>: chore(main): release 1.4.0 (#320) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> -- 99fe95c66833a309dd61d09be00a38d2cfe1c039 by release-please[bot] <55107282+release-please[bot]@users.noreply.github.com>: chore(main): release 1.5.0-SNAPSHOT COPYBARA_INTEGRATE_REVIEW=https://github.com/googleapis/java-genai/pull/328 from googleapis:release-please--branches--main 99fe95c66833a309dd61d09be00a38d2cfe1c039 PiperOrigin-RevId: 770799415 --- examples/pom.xml | 2 +- pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/pom.xml b/examples/pom.xml index b348f9ebc00..187d08b69f0 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -5,7 +5,7 @@ com.google.genai.examples google-genai-examples - 1.4.0 + 1.5.0-SNAPSHOT google-genai-examples diff --git a/pom.xml b/pom.xml index f1993b9830e..ea44cb843a1 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ com.google.genai google-genai google-genai - 1.4.0 + 1.5.0-SNAPSHOT jar Java idiomatic SDK for the Gemini Developer APIs and Vertex AI APIs. From 504984ad8bc30636e47a6838d89fe097766e9484 Mon Sep 17 00:00:00 2001 From: Matthew Tang Date: Thu, 12 Jun 2025 14:45:26 -0700 Subject: [PATCH 011/602] fix: Add backwards compatibility for generateVideos in Java SDK PiperOrigin-RevId: 770802286 --- .../google/genai/examples/GenerateVideos.java | 14 ++++++++------ .../genai/examples/GenerateVideosAsync.java | 1 - .../java/com/google/genai/AsyncModels.java | 19 +++++++++++++++++++ src/main/java/com/google/genai/Models.java | 18 ++++++++++++++++++ 4 files changed, 45 insertions(+), 7 deletions(-) diff --git a/examples/src/main/java/com/google/genai/examples/GenerateVideos.java b/examples/src/main/java/com/google/genai/examples/GenerateVideos.java index 9aea0a414e0..4228f4eff6c 100644 --- a/examples/src/main/java/com/google/genai/examples/GenerateVideos.java +++ b/examples/src/main/java/com/google/genai/examples/GenerateVideos.java @@ -77,7 +77,6 @@ public static void main(String[] args) { "veo-2.0-generate-001", "A neon hologram of a cat driving at top speed", null, - null, generateVideosConfig); // GenerateVideosOperation.done() is empty if the operation is not done. @@ -99,11 +98,14 @@ public static void main(String[] args) { Video generatedVideo = generateVideosOperation.response().get().generatedVideos().get().get(0).video().get(); - try { - client.files.download(generatedVideo, "video.mp4", null); - System.out.println("Downloaded video to video.mp4"); - } catch (GenAiIOException e) { - System.out.println("An error occurred while downloading the video: " + e.getMessage()); + + if (!client.vertexAI()) { + try { + client.files.download(generatedVideo, "video.mp4", null); + System.out.println("Downloaded video to video.mp4"); + } catch (GenAiIOException e) { + System.out.println("An error occurred while downloading the video: " + e.getMessage()); + } } } diff --git a/examples/src/main/java/com/google/genai/examples/GenerateVideosAsync.java b/examples/src/main/java/com/google/genai/examples/GenerateVideosAsync.java index a31e6b34bf9..4897db41b92 100644 --- a/examples/src/main/java/com/google/genai/examples/GenerateVideosAsync.java +++ b/examples/src/main/java/com/google/genai/examples/GenerateVideosAsync.java @@ -78,7 +78,6 @@ public static void main(String[] args) { "veo-2.0-generate-001", "A neon hologram of a cat driving at top speed", null, - null, generateVideosConfig); generateVideosOperationFuture diff --git a/src/main/java/com/google/genai/AsyncModels.java b/src/main/java/com/google/genai/AsyncModels.java index 93400028306..a2045a2bd4d 100644 --- a/src/main/java/com/google/genai/AsyncModels.java +++ b/src/main/java/com/google/genai/AsyncModels.java @@ -322,6 +322,25 @@ public CompletableFuture upscaleImage( () -> models.upscaleImage(model, image, upscaleFactor, config)); } + /** + * Asynchronously generates videos given a GenAI model, and an input (text, image). + * + *

This method is experimental, and kept for backward compatibility. + * + * @param model the name of the GenAI model to use for generating videos + * @param prompt the text prompt for generating the videos. Optional for image to video use cases. + * @param image the input image for generating the videos. Optional if prompt is provided. + * @param config a {@link com.google.genai.types.GenerateVideosConfig} instance that specifies the + * optional configurations + * @return a {@link com.google.genai.types.GenerateVideosOperation} instance that contains the + * generated videos. + */ + public CompletableFuture generateVideos( + String model, String prompt, Image image, GenerateVideosConfig config) { + return CompletableFuture.supplyAsync( + () -> models.generateVideos(model, prompt, image, null, config)); + } + /** * Asynchronously embeds content given a GenAI model and a text string. * diff --git a/src/main/java/com/google/genai/Models.java b/src/main/java/com/google/genai/Models.java index 7d1bb8ad9a2..47d89fde231 100644 --- a/src/main/java/com/google/genai/Models.java +++ b/src/main/java/com/google/genai/Models.java @@ -7163,6 +7163,24 @@ public UpscaleImageResponse upscaleImage( return privateUpscaleImage(model, image, upscaleFactor, apiConfig); } + /** + * Generates videos given a GenAI model, and an input (text, image). + * + *

This method is experimental, and kept for backward compatibility. + * + * @param model the name of the GenAI model to use for generating videos + * @param prompt the text prompt for generating the videos. Optional for image to video use cases. + * @param image the input image for generating the videos. Optional if prompt is provided. + * @param config a {@link com.google.genai.types.GenerateVideosConfig} instance that specifies the + * optional configurations + * @return a {@link com.google.genai.types.GenerateVideosOperation} instance that contains the + * generated videos. + */ + public GenerateVideosOperation generateVideos( + String model, String prompt, Image image, GenerateVideosConfig config) { + return generateVideos(model, prompt, image, null, config); + } + /** * Embeds content given a GenAI model and a text string. * From 49a57d878379729a14ccd4846af67c67bbaf2419 Mon Sep 17 00:00:00 2001 From: Jaycee Li Date: Thu, 12 Jun 2025 14:54:27 -0700 Subject: [PATCH 012/602] chore: release 1.4.1 Release-As: 1.4.1 PiperOrigin-RevId: 770805256 --- releases.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/releases.txt b/releases.txt index a52927e3d87..7b9de251a8c 100644 --- a/releases.txt +++ b/releases.txt @@ -1,4 +1,4 @@ Use this file when you need to force a patch release with release-please. Edit line 4 below with the version for the release. -1.0.0 +1.4.1 From de4a053b4a03d197404d19bf2c9288de3025ef49 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Thu, 12 Jun 2025 15:27:19 -0700 Subject: [PATCH 013/602] chore(main): release 1.4.1 (#329) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- .release-please-manifest.json | 2 +- CHANGELOG.md | 12 ++++++++++++ examples/pom.xml | 2 +- pom.xml | 2 +- 4 files changed, 15 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 3e9af1b3ae2..73257989c9b 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "1.4.0" + ".": "1.4.1" } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 5afd2377087..56ebe82b80e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,17 @@ # Changelog +## [1.4.1](https://github.com/googleapis/java-genai/compare/v1.4.0...v1.4.1) (2025-06-12) + + +### Bug Fixes + +* Add backwards compatibility for generateVideos in Java SDK ([504984a](https://github.com/googleapis/java-genai/commit/504984ad8bc30636e47a6838d89fe097766e9484)) + + +### Miscellaneous Chores + +* release 1.4.1 ([49a57d8](https://github.com/googleapis/java-genai/commit/49a57d878379729a14ccd4846af67c67bbaf2419)) + ## [1.4.0](https://github.com/googleapis/java-genai/compare/v1.3.0...v1.4.0) (2025-06-11) diff --git a/examples/pom.xml b/examples/pom.xml index 187d08b69f0..388b7ef246c 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -5,7 +5,7 @@ com.google.genai.examples google-genai-examples - 1.5.0-SNAPSHOT + 1.4.1 google-genai-examples diff --git a/pom.xml b/pom.xml index ea44cb843a1..0b0962cff3a 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ com.google.genai google-genai google-genai - 1.5.0-SNAPSHOT + 1.4.1 jar Java idiomatic SDK for the Gemini Developer APIs and Vertex AI APIs. From 9c4b43b41bf52d0c3f9cf6c63d1c492a6e35c79f Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Thu, 12 Jun 2025 15:42:03 -0700 Subject: [PATCH 014/602] chore(main): release 1.5.0-SNAPSHOT (#332) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- examples/pom.xml | 2 +- pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/pom.xml b/examples/pom.xml index 388b7ef246c..187d08b69f0 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -5,7 +5,7 @@ com.google.genai.examples google-genai-examples - 1.4.1 + 1.5.0-SNAPSHOT google-genai-examples diff --git a/pom.xml b/pom.xml index 0b0962cff3a..ea44cb843a1 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ com.google.genai google-genai google-genai - 1.4.1 + 1.5.0-SNAPSHOT jar Java idiomatic SDK for the Gemini Developer APIs and Vertex AI APIs. From da9e37057365e9feb9e7f68f0e563204cd8876da Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Thu, 12 Jun 2025 15:35:01 -0700 Subject: [PATCH 015/602] Copybara import of the project: -- 703ef40d1fb87942ef31480dfc9f9349501cf760 by release-please[bot] <55107282+release-please[bot]@users.noreply.github.com>: chore(main): release 1.4.1 COPYBARA_INTEGRATE_REVIEW=https://github.com/googleapis/java-genai/pull/329 from googleapis:release-please--branches--main 703ef40d1fb87942ef31480dfc9f9349501cf760 PiperOrigin-RevId: 770820152 --- examples/pom.xml | 2 +- pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/pom.xml b/examples/pom.xml index 187d08b69f0..388b7ef246c 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -5,7 +5,7 @@ com.google.genai.examples google-genai-examples - 1.5.0-SNAPSHOT + 1.4.1 google-genai-examples diff --git a/pom.xml b/pom.xml index ea44cb843a1..0b0962cff3a 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ com.google.genai google-genai google-genai - 1.5.0-SNAPSHOT + 1.4.1 jar Java idiomatic SDK for the Gemini Developer APIs and Vertex AI APIs. From 489d7805de2eb20140947f5e10b5a1b44ad9a753 Mon Sep 17 00:00:00 2001 From: Jaycee Li Date: Thu, 12 Jun 2025 17:07:53 -0700 Subject: [PATCH 016/602] No public description PiperOrigin-RevId: 770852356 --- examples/pom.xml | 2 +- pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/pom.xml b/examples/pom.xml index 388b7ef246c..187d08b69f0 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -5,7 +5,7 @@ com.google.genai.examples google-genai-examples - 1.4.1 + 1.5.0-SNAPSHOT google-genai-examples diff --git a/pom.xml b/pom.xml index 0b0962cff3a..ea44cb843a1 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ com.google.genai google-genai google-genai - 1.4.1 + 1.5.0-SNAPSHOT jar Java idiomatic SDK for the Gemini Developer APIs and Vertex AI APIs. From 71cafea565cbda4f78b8879d134a69ec840670fd Mon Sep 17 00:00:00 2001 From: Wanlin Du Date: Thu, 12 Jun 2025 17:31:23 -0700 Subject: [PATCH 017/602] chore: Update package version in README and ApiClient to 1.4.1 PiperOrigin-RevId: 770858844 --- README.md | 2 +- examples/pom.xml | 2 +- src/main/java/com/google/genai/ApiClient.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 4dd54a8b4d2..7a0cc041e1a 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ If you're using Maven, add the following to your dependencies: com.google.genai google-genai - 1.3.0 + 1.4.1 ``` diff --git a/examples/pom.xml b/examples/pom.xml index 187d08b69f0..a51998b7d50 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -12,7 +12,7 @@ UTF-8 1.8 1.8 - 1.4.0-SNAPSHOT + 1.5.0-SNAPSHOT diff --git a/src/main/java/com/google/genai/ApiClient.java b/src/main/java/com/google/genai/ApiClient.java index 82fdf4e2a19..d28b640cb07 100644 --- a/src/main/java/com/google/genai/ApiClient.java +++ b/src/main/java/com/google/genai/ApiClient.java @@ -39,7 +39,7 @@ /** Interface for an API client which issues HTTP requests to the GenAI APIs. */ abstract class ApiClient { - private static final String SDK_VERSION = "1.3.0"; // x-version-update:google-genai:released + private static final String SDK_VERSION = "1.4.1"; // x-version-update:google-genai:released private static final Logger logger = Logger.getLogger(ApiClient.class.getName()); CloseableHttpClient httpClient; From 35d93d84a349cf1032d2cc61bf4e3128386759d6 Mon Sep 17 00:00:00 2001 From: Yvonne Yu Date: Fri, 13 Jun 2025 15:48:21 -0700 Subject: [PATCH 018/602] feat: enable json schema for controlled output and function declaration. PiperOrigin-RevId: 771251820 --- src/main/java/com/google/genai/Caches.java | 28 +++++++++++++ .../java/com/google/genai/LiveConverters.java | 28 +++++++++++++ src/main/java/com/google/genai/Models.java | 28 +++++++++++++ .../com/google/genai/TokensConverters.java | 28 +++++++++++++ .../genai/types/FunctionDeclaration.java | 40 +++++++++++++++++++ .../google/genai/types/GenerationConfig.java | 35 ++++++++++++++++ 6 files changed, 187 insertions(+) diff --git a/src/main/java/com/google/genai/Caches.java b/src/main/java/com/google/genai/Caches.java index fc0bca692ec..3ec89511c37 100644 --- a/src/main/java/com/google/genai/Caches.java +++ b/src/main/java/com/google/genai/Caches.java @@ -270,6 +270,13 @@ ObjectNode functionDeclarationToMldev( Common.getValueByPath(fromObject, new String[] {"parameters"})); } + if (Common.getValueByPath(fromObject, new String[] {"parametersJsonSchema"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"parametersJsonSchema"}, + Common.getValueByPath(fromObject, new String[] {"parametersJsonSchema"})); + } + if (Common.getValueByPath(fromObject, new String[] {"response"}) != null) { Common.setValueByPath( toObject, @@ -277,6 +284,13 @@ ObjectNode functionDeclarationToMldev( Common.getValueByPath(fromObject, new String[] {"response"})); } + if (Common.getValueByPath(fromObject, new String[] {"responseJsonSchema"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"responseJsonSchema"}, + Common.getValueByPath(fromObject, new String[] {"responseJsonSchema"})); + } + return toObject; } @@ -1017,6 +1031,13 @@ ObjectNode functionDeclarationToVertex( Common.getValueByPath(fromObject, new String[] {"parameters"})); } + if (Common.getValueByPath(fromObject, new String[] {"parametersJsonSchema"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"parametersJsonSchema"}, + Common.getValueByPath(fromObject, new String[] {"parametersJsonSchema"})); + } + if (Common.getValueByPath(fromObject, new String[] {"response"}) != null) { Common.setValueByPath( toObject, @@ -1024,6 +1045,13 @@ ObjectNode functionDeclarationToVertex( Common.getValueByPath(fromObject, new String[] {"response"})); } + if (Common.getValueByPath(fromObject, new String[] {"responseJsonSchema"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"responseJsonSchema"}, + Common.getValueByPath(fromObject, new String[] {"responseJsonSchema"})); + } + return toObject; } diff --git a/src/main/java/com/google/genai/LiveConverters.java b/src/main/java/com/google/genai/LiveConverters.java index f28cdc12689..5472a1a377c 100644 --- a/src/main/java/com/google/genai/LiveConverters.java +++ b/src/main/java/com/google/genai/LiveConverters.java @@ -642,6 +642,13 @@ ObjectNode functionDeclarationToMldev( Common.getValueByPath(fromObject, new String[] {"parameters"})); } + if (Common.getValueByPath(fromObject, new String[] {"parametersJsonSchema"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"parametersJsonSchema"}, + Common.getValueByPath(fromObject, new String[] {"parametersJsonSchema"})); + } + if (Common.getValueByPath(fromObject, new String[] {"response"}) != null) { Common.setValueByPath( toObject, @@ -649,6 +656,13 @@ ObjectNode functionDeclarationToMldev( Common.getValueByPath(fromObject, new String[] {"response"})); } + if (Common.getValueByPath(fromObject, new String[] {"responseJsonSchema"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"responseJsonSchema"}, + Common.getValueByPath(fromObject, new String[] {"responseJsonSchema"})); + } + return toObject; } @@ -681,6 +695,13 @@ ObjectNode functionDeclarationToVertex( Common.getValueByPath(fromObject, new String[] {"parameters"})); } + if (Common.getValueByPath(fromObject, new String[] {"parametersJsonSchema"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"parametersJsonSchema"}, + Common.getValueByPath(fromObject, new String[] {"parametersJsonSchema"})); + } + if (Common.getValueByPath(fromObject, new String[] {"response"}) != null) { Common.setValueByPath( toObject, @@ -688,6 +709,13 @@ ObjectNode functionDeclarationToVertex( Common.getValueByPath(fromObject, new String[] {"response"})); } + if (Common.getValueByPath(fromObject, new String[] {"responseJsonSchema"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"responseJsonSchema"}, + Common.getValueByPath(fromObject, new String[] {"responseJsonSchema"})); + } + return toObject; } diff --git a/src/main/java/com/google/genai/Models.java b/src/main/java/com/google/genai/Models.java index 47d89fde231..ed195e735fc 100644 --- a/src/main/java/com/google/genai/Models.java +++ b/src/main/java/com/google/genai/Models.java @@ -509,6 +509,13 @@ ObjectNode functionDeclarationToMldev( Common.getValueByPath(fromObject, new String[] {"parameters"})); } + if (Common.getValueByPath(fromObject, new String[] {"parametersJsonSchema"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"parametersJsonSchema"}, + Common.getValueByPath(fromObject, new String[] {"parametersJsonSchema"})); + } + if (Common.getValueByPath(fromObject, new String[] {"response"}) != null) { Common.setValueByPath( toObject, @@ -516,6 +523,13 @@ ObjectNode functionDeclarationToMldev( Common.getValueByPath(fromObject, new String[] {"response"})); } + if (Common.getValueByPath(fromObject, new String[] {"responseJsonSchema"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"responseJsonSchema"}, + Common.getValueByPath(fromObject, new String[] {"responseJsonSchema"})); + } + return toObject; } @@ -2266,6 +2280,13 @@ ObjectNode functionDeclarationToVertex( Common.getValueByPath(fromObject, new String[] {"parameters"})); } + if (Common.getValueByPath(fromObject, new String[] {"parametersJsonSchema"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"parametersJsonSchema"}, + Common.getValueByPath(fromObject, new String[] {"parametersJsonSchema"})); + } + if (Common.getValueByPath(fromObject, new String[] {"response"}) != null) { Common.setValueByPath( toObject, @@ -2273,6 +2294,13 @@ ObjectNode functionDeclarationToVertex( Common.getValueByPath(fromObject, new String[] {"response"})); } + if (Common.getValueByPath(fromObject, new String[] {"responseJsonSchema"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"responseJsonSchema"}, + Common.getValueByPath(fromObject, new String[] {"responseJsonSchema"})); + } + return toObject; } diff --git a/src/main/java/com/google/genai/TokensConverters.java b/src/main/java/com/google/genai/TokensConverters.java index 9c5cc5dfd10..47a69e9ae4b 100644 --- a/src/main/java/com/google/genai/TokensConverters.java +++ b/src/main/java/com/google/genai/TokensConverters.java @@ -642,6 +642,13 @@ ObjectNode functionDeclarationToMldev( Common.getValueByPath(fromObject, new String[] {"parameters"})); } + if (Common.getValueByPath(fromObject, new String[] {"parametersJsonSchema"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"parametersJsonSchema"}, + Common.getValueByPath(fromObject, new String[] {"parametersJsonSchema"})); + } + if (Common.getValueByPath(fromObject, new String[] {"response"}) != null) { Common.setValueByPath( toObject, @@ -649,6 +656,13 @@ ObjectNode functionDeclarationToMldev( Common.getValueByPath(fromObject, new String[] {"response"})); } + if (Common.getValueByPath(fromObject, new String[] {"responseJsonSchema"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"responseJsonSchema"}, + Common.getValueByPath(fromObject, new String[] {"responseJsonSchema"})); + } + return toObject; } @@ -681,6 +695,13 @@ ObjectNode functionDeclarationToVertex( Common.getValueByPath(fromObject, new String[] {"parameters"})); } + if (Common.getValueByPath(fromObject, new String[] {"parametersJsonSchema"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"parametersJsonSchema"}, + Common.getValueByPath(fromObject, new String[] {"parametersJsonSchema"})); + } + if (Common.getValueByPath(fromObject, new String[] {"response"}) != null) { Common.setValueByPath( toObject, @@ -688,6 +709,13 @@ ObjectNode functionDeclarationToVertex( Common.getValueByPath(fromObject, new String[] {"response"})); } + if (Common.getValueByPath(fromObject, new String[] {"responseJsonSchema"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"responseJsonSchema"}, + Common.getValueByPath(fromObject, new String[] {"responseJsonSchema"})); + } + return toObject; } diff --git a/src/main/java/com/google/genai/types/FunctionDeclaration.java b/src/main/java/com/google/genai/types/FunctionDeclaration.java index 2e85affa285..7e02cc508ea 100644 --- a/src/main/java/com/google/genai/types/FunctionDeclaration.java +++ b/src/main/java/com/google/genai/types/FunctionDeclaration.java @@ -71,6 +71,16 @@ public abstract class FunctionDeclaration extends JsonSerializable { @JsonProperty("parameters") public abstract Optional parameters(); + /** + * Optional. Describes the parameters to the function in JSON Schema format. The schema must + * describe an object where the properties are the parameters to the function. For example: ``` { + * "type": "object", "properties": { "name": { "type": "string" }, "age": { "type": "integer" } }, + * "additionalProperties": false, "required": ["name", "age"], "propertyOrdering": ["name", "age"] + * } ``` This field is mutually exclusive with `parameters`. + */ + @JsonProperty("parametersJsonSchema") + public abstract Optional parametersJsonSchema(); + /** * Optional. Describes the output from this function in JSON Schema format. Reflects the Open API * 3.03 Response Object. The Schema defines the type used for the response value of the function. @@ -78,6 +88,14 @@ public abstract class FunctionDeclaration extends JsonSerializable { @JsonProperty("response") public abstract Optional response(); + /** + * Optional. Describes the output from this function in JSON Schema format. The value specified by + * the schema is the response value of the function. This field is mutually exclusive with + * `response`. + */ + @JsonProperty("responseJsonSchema") + public abstract Optional responseJsonSchema(); + /** Instantiates a builder for FunctionDeclaration. */ public static Builder builder() { return new AutoValue_FunctionDeclaration.Builder(); @@ -171,6 +189,18 @@ public Builder parameters(Schema.Builder parametersBuilder) { return parameters(parametersBuilder.build()); } + /** + * Setter for parametersJsonSchema. + * + *

parametersJsonSchema: Optional. Describes the parameters to the function in JSON Schema + * format. The schema must describe an object where the properties are the parameters to the + * function. For example: ``` { "type": "object", "properties": { "name": { "type": "string" }, + * "age": { "type": "integer" } }, "additionalProperties": false, "required": ["name", "age"], + * "propertyOrdering": ["name", "age"] } ``` This field is mutually exclusive with `parameters`. + */ + @JsonProperty("parametersJsonSchema") + public abstract Builder parametersJsonSchema(Object parametersJsonSchema); + /** * Setter for response. * @@ -192,6 +222,16 @@ public Builder response(Schema.Builder responseBuilder) { return response(responseBuilder.build()); } + /** + * Setter for responseJsonSchema. + * + *

responseJsonSchema: Optional. Describes the output from this function in JSON Schema + * format. The value specified by the schema is the response value of the function. This field + * is mutually exclusive with `response`. + */ + @JsonProperty("responseJsonSchema") + public abstract Builder responseJsonSchema(Object responseJsonSchema); + public abstract FunctionDeclaration build(); } diff --git a/src/main/java/com/google/genai/types/GenerationConfig.java b/src/main/java/com/google/genai/types/GenerationConfig.java index 352cbfdee41..513ae3254b9 100644 --- a/src/main/java/com/google/genai/types/GenerationConfig.java +++ b/src/main/java/com/google/genai/types/GenerationConfig.java @@ -94,6 +94,22 @@ public abstract class GenerationConfig extends JsonSerializable { @JsonProperty("responseSchema") public abstract Optional responseSchema(); + /** + * Optional. Output schema of the generated response. This is an alternative to `response_schema` + * that accepts [JSON Schema](https://json-schema.org/). If set, `response_schema` must be + * omitted, but `response_mime_type` is required. While the full JSON Schema may be sent, not all + * features are supported. Specifically, only the following properties are supported: - `$id` - + * `$defs` - `$ref` - `$anchor` - `type` - `format` - `title` - `description` - `enum` (for + * strings and numbers) - `items` - `prefixItems` - `minItems` - `maxItems` - `minimum` - + * `maximum` - `anyOf` - `oneOf` (interpreted the same as `anyOf`) - `properties` - + * `additionalProperties` - `required` The non-standard `propertyOrdering` property may also be + * set. Cyclic references are unrolled to a limited degree and, as such, may only be used within + * non-required properties. (Nullable properties are not sufficient.) If `$ref` is set on a + * sub-schema, no other properties, except for than those starting as a `$`, may be set. + */ + @JsonProperty("responseJsonSchema") + public abstract Optional responseJsonSchema(); + /** Optional. Routing configuration. */ @JsonProperty("routingConfig") public abstract Optional routingConfig(); @@ -345,6 +361,25 @@ public Builder responseSchema(Schema.Builder responseSchemaBuilder) { return responseSchema(responseSchemaBuilder.build()); } + /** + * Setter for responseJsonSchema. + * + *

responseJsonSchema: Optional. Output schema of the generated response. This is an + * alternative to `response_schema` that accepts [JSON Schema](https://json-schema.org/). If + * set, `response_schema` must be omitted, but `response_mime_type` is required. While the full + * JSON Schema may be sent, not all features are supported. Specifically, only the following + * properties are supported: - `$id` - `$defs` - `$ref` - `$anchor` - `type` - `format` - + * `title` - `description` - `enum` (for strings and numbers) - `items` - `prefixItems` - + * `minItems` - `maxItems` - `minimum` - `maximum` - `anyOf` - `oneOf` (interpreted the same as + * `anyOf`) - `properties` - `additionalProperties` - `required` The non-standard + * `propertyOrdering` property may also be set. Cyclic references are unrolled to a limited + * degree and, as such, may only be used within non-required properties. (Nullable properties + * are not sufficient.) If `$ref` is set on a sub-schema, no other properties, except for than + * those starting as a `$`, may be set. + */ + @JsonProperty("responseJsonSchema") + public abstract Builder responseJsonSchema(Object responseJsonSchema); + /** * Setter for routingConfig. * From d80d23b7a8cb440410f9dd9556ee1259352285ef Mon Sep 17 00:00:00 2001 From: Ivan Lopez Hernandez Date: Mon, 16 Jun 2025 10:02:55 -0700 Subject: [PATCH 019/602] feat: Add a default 5 minutes timeout to the Java SDK. PiperOrigin-RevId: 772071436 --- src/main/java/com/google/genai/ApiClient.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/com/google/genai/ApiClient.java b/src/main/java/com/google/genai/ApiClient.java index d28b640cb07..bcb122efb5b 100644 --- a/src/main/java/com/google/genai/ApiClient.java +++ b/src/main/java/com/google/genai/ApiClient.java @@ -25,6 +25,7 @@ import com.google.genai.types.ClientOptions; import com.google.genai.types.HttpOptions; import java.io.IOException; +import java.time.Duration; import java.util.Map; import java.util.Optional; import java.util.logging.Logger; @@ -285,6 +286,9 @@ static HttpOptions defaultHttpOptions(boolean vertexAI, Optional locatio .baseUrl("https://generativelanguage.googleapis.com") .apiVersion("v1beta"); } + + defaultHttpOptionsBuilder.timeout(Math.toIntExact(Duration.ofMinutes(5).toMillis())); + return defaultHttpOptionsBuilder.build(); } From c1b0948af51bc746cbf350e4b6a60b6199d3ffe2 Mon Sep 17 00:00:00 2001 From: Ayush Agrawal Date: Tue, 17 Jun 2025 16:28:34 -0700 Subject: [PATCH 020/602] feat: Parametrize model ID in Java genai samples and set hardcoded model IDs as default values if model ID not passed in by user. PiperOrigin-RevId: 772668628 --- .../examples/CachedContentOperations.java | 8 +++- .../CachedContentOperationsAsync.java | 10 ++++- .../genai/examples/ChatWithFunctionCall.java | 8 +++- .../genai/examples/ChatWithHistory.java | 8 +++- .../genai/examples/ChatWithHistoryAsync.java | 8 +++- .../ChatWithHistoryAsyncStreaming.java | 8 +++- .../examples/ChatWithHistoryStreaming.java | 8 +++- .../google/genai/examples/ComputeTokens.java | 8 +++- .../google/genai/examples/CountTokens.java | 8 +++- .../examples/CountTokensWithConfigs.java | 8 +++- .../google/genai/examples/EditImageAsync.java | 11 ++++-- .../examples/EditImageControlReference.java | 8 +++- .../examples/EditImageMaskReference.java | 11 ++++-- .../examples/EditImageStyleTransfer.java | 8 +++- .../examples/EditImageSubjectReference.java | 8 +++- .../google/genai/examples/EmbedContent.java | 8 +++- .../genai/examples/EmbedContentAsync.java | 8 +++- .../examples/EmbedContentWithConfig.java | 10 +++-- .../genai/examples/GenerateContent.java | 8 +++- .../genai/examples/GenerateContentAsync.java | 9 ++++- .../genai/examples/GenerateContentStream.java | 9 ++++- .../examples/GenerateContentWithConfigs.java | 8 +++- .../GenerateContentWithFunctionCall.java | 10 +++-- .../GenerateContentWithImageInput.java | 9 ++++- .../GenerateContentWithResponseModality.java | 11 ++++-- .../GenerateContentWithResponseSchema.java | 9 ++++- .../google/genai/examples/GenerateImages.java | 8 +++- .../genai/examples/GenerateImagesAsync.java | 8 +++- .../google/genai/examples/GenerateVideos.java | 11 ++++-- .../genai/examples/GenerateVideosAsync.java | 11 ++++-- .../examples/LiveAudioConversationAsync.java | 18 ++++++--- ...LiveTextContextWindowCompressionAsync.java | 21 +++++----- .../examples/LiveTextConversationAsync.java | 17 ++++++--- .../LiveTextConversationResumptionAsync.java | 38 ++++++++++++++----- .../LiveTextToAudioTranscriptionAsync.java | 20 ++++++---- .../LiveTextToTextGenerationAsync.java | 20 ++++++---- .../examples/RequestLevelHttpOptions.java | 8 +++- .../google/genai/examples/UpscaleImage.java | 8 +++- .../genai/examples/UpscaleImageAsync.java | 8 +++- 39 files changed, 322 insertions(+), 101 deletions(-) diff --git a/examples/src/main/java/com/google/genai/examples/CachedContentOperations.java b/examples/src/main/java/com/google/genai/examples/CachedContentOperations.java index 3120b5ace83..ceec0eb0579 100644 --- a/examples/src/main/java/com/google/genai/examples/CachedContentOperations.java +++ b/examples/src/main/java/com/google/genai/examples/CachedContentOperations.java @@ -38,6 +38,7 @@ *

mvn clean compile * *

mvn exec:java -Dexec.mainClass="com.google.genai.examples.CachedContentOperations" + * -Dexec.args="YOUR_MODEL_ID" */ package com.google.genai.examples; @@ -60,6 +61,11 @@ public final class CachedContentOperations { public static void main(String[] args) { + String modelId = "gemini-2.0-flash-001"; + if (args.length != 0) { + modelId = args[0]; + } + // Instantiate the client. The client by default uses the Gemini Developer API. It gets the API // key from the environment variable `GOOGLE_API_KEY`. Vertex AI API can be used by setting the // environment variables `GOOGLE_CLOUD_LOCATION` and `GOOGLE_CLOUD_PROJECT`, as well as setting @@ -89,7 +95,7 @@ public static void main(String[] args) { .contents(content) .build(); - CachedContent cachedContent1 = client.caches.create("gemini-2.0-flash-001", config); + CachedContent cachedContent1 = client.caches.create(modelId, config); System.out.println("Created cached content: " + cachedContent1); // Get the cached content by name. diff --git a/examples/src/main/java/com/google/genai/examples/CachedContentOperationsAsync.java b/examples/src/main/java/com/google/genai/examples/CachedContentOperationsAsync.java index 7db6a2c6a1b..6e5f12e801f 100644 --- a/examples/src/main/java/com/google/genai/examples/CachedContentOperationsAsync.java +++ b/examples/src/main/java/com/google/genai/examples/CachedContentOperationsAsync.java @@ -38,6 +38,7 @@ *

mvn clean compile * *

mvn exec:java -Dexec.mainClass="com.google.genai.examples.CachedContentOperationsAsync" + * -Dexec.args="YOUR_MODEL_ID" */ package com.google.genai.examples; @@ -65,6 +66,13 @@ public final class CachedContentOperationsAsync { public static void main(String[] args) { + String modelId; + if (args.length != 0) { + modelId = args[0]; + } else { + modelId = "gemini-2.0-flash-001"; + } + // Instantiate the client. The client by default uses the Gemini Developer API. It gets the API // key from the environment variable `GOOGLE_API_KEY`. Vertex AI API can be used by setting the // environment variables `GOOGLE_CLOUD_LOCATION` and `GOOGLE_CLOUD_PROJECT`, as well as setting @@ -98,7 +106,7 @@ public static void main(String[] args) { contentFuture.thenCompose( content -> client.async.caches.create( - "gemini-2.0-flash-001", + modelId, CreateCachedContentConfig.builder() .systemInstruction(Content.fromParts(Part.fromText("summarize the pdf"))) .expireTime(Instant.now().plus(Duration.ofHours(1))) diff --git a/examples/src/main/java/com/google/genai/examples/ChatWithFunctionCall.java b/examples/src/main/java/com/google/genai/examples/ChatWithFunctionCall.java index c43b72897b4..19cf8980c79 100644 --- a/examples/src/main/java/com/google/genai/examples/ChatWithFunctionCall.java +++ b/examples/src/main/java/com/google/genai/examples/ChatWithFunctionCall.java @@ -36,6 +36,7 @@ *

2. Compile the java package and run the sample code. * *

mvn clean compile exec:java -Dexec.mainClass="com.google.genai.examples.ChatWithFunctionCall" + * -Dexec.args="YOUR_MODEL_ID" */ package com.google.genai.examples; @@ -59,6 +60,11 @@ public static Integer divideTwoIntegers(int numerator, int denominator) { } public static void main(String[] args) throws NoSuchMethodException { + String modelId = "gemini-2.0-flash-001"; + if (args.length != 0) { + modelId = args[0]; + } + // Instantiate the client. The client by default uses the Gemini Developer API. It gets the API // key from the environment variable `GOOGLE_API_KEY`. Vertex AI API can be used by setting the // environment variables `GOOGLE_CLOUD_LOCATION` and `GOOGLE_CLOUD_PROJECT`, as well as setting @@ -85,7 +91,7 @@ public static void main(String[] args) throws NoSuchMethodException { GenerateContentConfig.builder().tools(Tool.builder().functions(method1, method2)).build(); // Create a chat session. - Chat chatSession = client.chats.create("gemini-2.0-flash-001", config); + Chat chatSession = client.chats.create(modelId, config); GenerateContentResponse response1 = chatSession.sendMessage("what is the weather in San Francisco?"); diff --git a/examples/src/main/java/com/google/genai/examples/ChatWithHistory.java b/examples/src/main/java/com/google/genai/examples/ChatWithHistory.java index de3f94a0223..0d009e72ea8 100644 --- a/examples/src/main/java/com/google/genai/examples/ChatWithHistory.java +++ b/examples/src/main/java/com/google/genai/examples/ChatWithHistory.java @@ -36,6 +36,7 @@ *

2. Compile the java package and run the sample code. * *

mvn clean compile exec:java -Dexec.mainClass="com.google.genai.examples.ChatWithHistory" + * -Dexec.args="YOUR_MODEL_ID" */ package com.google.genai.examples; @@ -48,6 +49,11 @@ /** An example of using the Unified Gen AI Java SDK to create a chat session with history. */ public final class ChatWithHistory { public static void main(String[] args) { + String modelId = "gemini-2.0-flash-001"; + if (args.length != 0) { + modelId = args[0]; + } + // Instantiate the client. The client by default uses the Gemini Developer API. It gets the API // key from the environment variable `GOOGLE_API_KEY`. Vertex AI API can be used by setting the // environment variables `GOOGLE_CLOUD_LOCATION` and `GOOGLE_CLOUD_PROJECT`, as well as setting @@ -65,7 +71,7 @@ public static void main(String[] args) { } // Create a chat session. - Chat chatSession = client.chats.create("gemini-2.0-flash-001"); + Chat chatSession = client.chats.create(modelId); GenerateContentResponse response = chatSession.sendMessage("Can you tell me a story about cheese in 100 words?"); diff --git a/examples/src/main/java/com/google/genai/examples/ChatWithHistoryAsync.java b/examples/src/main/java/com/google/genai/examples/ChatWithHistoryAsync.java index 24901087bfa..d86ad512351 100644 --- a/examples/src/main/java/com/google/genai/examples/ChatWithHistoryAsync.java +++ b/examples/src/main/java/com/google/genai/examples/ChatWithHistoryAsync.java @@ -36,6 +36,7 @@ *

2. Compile the java package and run the sample code. * *

mvn clean compile exec:java -Dexec.mainClass="com.google.genai.examples.ChatWithHistoryAsync" + * -Dexec.args="YOUR_MODEL_ID" */ package com.google.genai.examples; @@ -49,6 +50,11 @@ /** An example of using the Unified Gen AI Java SDK to create an async chat session with history. */ public final class ChatWithHistoryAsync { public static void main(String[] args) { + String modelId = "gemini-2.0-flash-001"; + if (args.length != 0) { + modelId = args[0]; + } + // Instantiate the client. The client by default uses the Gemini Developer API. It gets the API // key from the environment variable `GOOGLE_API_KEY`. Vertex AI API can be used by setting the // environment variables `GOOGLE_CLOUD_LOCATION` and `GOOGLE_CLOUD_PROJECT`, as well as setting @@ -66,7 +72,7 @@ public static void main(String[] args) { } // Create an async chat session. - AsyncChat chatSession = client.async.chats.create("gemini-2.0-flash-001"); + AsyncChat chatSession = client.async.chats.create(modelId); CompletableFuture chatResponseFuture = chatSession.sendMessage("Can you tell me a story about cheese in 100 words?"); diff --git a/examples/src/main/java/com/google/genai/examples/ChatWithHistoryAsyncStreaming.java b/examples/src/main/java/com/google/genai/examples/ChatWithHistoryAsyncStreaming.java index b974dd7ae37..0a541b2164b 100644 --- a/examples/src/main/java/com/google/genai/examples/ChatWithHistoryAsyncStreaming.java +++ b/examples/src/main/java/com/google/genai/examples/ChatWithHistoryAsyncStreaming.java @@ -38,6 +38,7 @@ *

mvn clean compile * *

mvn exec:java -Dexec.mainClass="com.google.genai.examples.ChatWithHistoryAsyncStreaming" + * -Dexec.args="YOUR_MODEL_ID" */ package com.google.genai.examples; @@ -53,6 +54,11 @@ */ public final class ChatWithHistoryAsyncStreaming { public static void main(String[] args) { + String modelId = "gemini-2.0-flash-001"; + if (args.length != 0) { + modelId = args[0]; + } + // Instantiate the client. The client by default uses the Gemini Developer API. It gets the API // key from the environment variable `GOOGLE_API_KEY`. Vertex AI API can be used by setting the // environment variables `GOOGLE_CLOUD_LOCATION` and `GOOGLE_CLOUD_PROJECT`, as well as setting @@ -70,7 +76,7 @@ public static void main(String[] args) { } // Create an async chat session. - AsyncChat chatSession = client.async.chats.create("gemini-2.0-flash-001"); + AsyncChat chatSession = client.async.chats.create(modelId); CompletableFuture> chatResponseFuture = chatSession.sendMessageStream("Can you tell me a story about cheese in 100 words?"); diff --git a/examples/src/main/java/com/google/genai/examples/ChatWithHistoryStreaming.java b/examples/src/main/java/com/google/genai/examples/ChatWithHistoryStreaming.java index b3bacb37e63..4ede79a155d 100644 --- a/examples/src/main/java/com/google/genai/examples/ChatWithHistoryStreaming.java +++ b/examples/src/main/java/com/google/genai/examples/ChatWithHistoryStreaming.java @@ -38,6 +38,7 @@ *

mvn clean compile * *

mvn exec:java -Dexec.mainClass="com.google.genai.examples.ChatWithHistoryStreaming" + * -Dexec.args="YOUR_MODEL_ID" */ package com.google.genai.examples; @@ -51,6 +52,11 @@ */ public final class ChatWithHistoryStreaming { public static void main(String[] args) { + String modelId = "gemini-2.0-flash-001"; + if (args.length != 0) { + modelId = args[0]; + } + // Instantiate the client. The client by default uses the Gemini Developer API. It gets the API // key from the environment variable `GOOGLE_API_KEY`. Vertex AI API can be used by setting the // environment variables `GOOGLE_CLOUD_LOCATION` and `GOOGLE_CLOUD_PROJECT`, as well as setting @@ -68,7 +74,7 @@ public static void main(String[] args) { } // Create a chat session. - Chat chatSession = client.chats.create("gemini-2.0-flash-001"); + Chat chatSession = client.chats.create(modelId); ResponseStream responseStream = chatSession.sendMessageStream("Can you tell me a story about cheese in 100 words?", null); diff --git a/examples/src/main/java/com/google/genai/examples/ComputeTokens.java b/examples/src/main/java/com/google/genai/examples/ComputeTokens.java index 2652394a06d..e049b1147aa 100644 --- a/examples/src/main/java/com/google/genai/examples/ComputeTokens.java +++ b/examples/src/main/java/com/google/genai/examples/ComputeTokens.java @@ -36,6 +36,7 @@ *

2. Compile the java package and run the sample code. * *

mvn clean compile exec:java -Dexec.mainClass="com.google.genai.examples.ComputeTokens" + * -Dexec.args="YOUR_MODEL_ID" */ package com.google.genai.examples; @@ -45,6 +46,11 @@ /** An example of using the Unified Gen AI Java SDK to compute tokens for simple text input. */ public final class ComputeTokens { public static void main(String[] args) { + String modelId = "gemini-2.0-flash-001"; + if (args.length != 0) { + modelId = args[0]; + } + // Instantiate the client. The client by default uses the Gemini Developer API. It gets the API // key from the environment variable `GOOGLE_API_KEY`. Vertex AI API can be used by setting the // environment variables `GOOGLE_CLOUD_LOCATION` and `GOOGLE_CLOUD_PROJECT`, as well as setting @@ -62,7 +68,7 @@ public static void main(String[] args) { } ComputeTokensResponse response = - client.models.computeTokens("gemini-2.0-flash-001", "What is your name?", null); + client.models.computeTokens(modelId, "What is your name?", null); System.out.println("Compute tokens response: " + response); } diff --git a/examples/src/main/java/com/google/genai/examples/CountTokens.java b/examples/src/main/java/com/google/genai/examples/CountTokens.java index 9ea06ce150b..3ae834f6ed0 100644 --- a/examples/src/main/java/com/google/genai/examples/CountTokens.java +++ b/examples/src/main/java/com/google/genai/examples/CountTokens.java @@ -36,6 +36,7 @@ *

2. Compile the java package and run the sample code. * *

mvn clean compile exec:java -Dexec.mainClass="com.google.genai.examples.CountTokens" + * -Dexec.args="YOUR_MODEL_ID" */ package com.google.genai.examples; @@ -45,6 +46,11 @@ /** An example of using the Unified Gen AI Java SDK to count tokens for simple text input. */ public final class CountTokens { public static void main(String[] args) { + String modelId = "gemini-2.0-flash-001"; + if (args.length != 0) { + modelId = args[0]; + } + // Instantiate the client. The client by default uses the Gemini Developer API. It gets the API // key from the environment variable `GOOGLE_API_KEY`. Vertex AI API can be used by setting the // environment variables `GOOGLE_CLOUD_LOCATION` and `GOOGLE_CLOUD_PROJECT`, as well as setting @@ -62,7 +68,7 @@ public static void main(String[] args) { } CountTokensResponse response = - client.models.countTokens("gemini-2.0-flash-001", "What is your name?", null); + client.models.countTokens(modelId, "What is your name?", null); System.out.println("Count tokens response: " + response); } diff --git a/examples/src/main/java/com/google/genai/examples/CountTokensWithConfigs.java b/examples/src/main/java/com/google/genai/examples/CountTokensWithConfigs.java index e43cc9399b9..f0724eb5fdb 100644 --- a/examples/src/main/java/com/google/genai/examples/CountTokensWithConfigs.java +++ b/examples/src/main/java/com/google/genai/examples/CountTokensWithConfigs.java @@ -38,6 +38,7 @@ *

mvn clean compile * *

mvn exec:java -Dexec.mainClass="com.google.genai.examples.CountTokensWithConfigs" + * -Dexec.args="YOUR_MODEL_ID" */ package com.google.genai.examples; @@ -53,6 +54,11 @@ */ public final class CountTokensWithConfigs { public static void main(String[] args) { + String modelId = "gemini-2.0-flash-001"; + if (args.length != 0) { + modelId = args[0]; + } + // Instantiate the client. The client by default uses the Gemini Developer API. It gets the API // key from the environment variable `GOOGLE_API_KEY`. Vertex AI API can be used by setting the // environment variables `GOOGLE_CLOUD_LOCATION` and `GOOGLE_CLOUD_PROJECT`, as well as setting @@ -78,7 +84,7 @@ public static void main(String[] args) { .build(); CountTokensResponse response = - client.models.countTokens("gemini-2.0-flash-001", "Tell me the history of LLM", config); + client.models.countTokens(modelId, "Tell me the history of LLM", config); System.out.println("Response: " + response); } diff --git a/examples/src/main/java/com/google/genai/examples/EditImageAsync.java b/examples/src/main/java/com/google/genai/examples/EditImageAsync.java index 9391e0d8fba..7b0343409ee 100644 --- a/examples/src/main/java/com/google/genai/examples/EditImageAsync.java +++ b/examples/src/main/java/com/google/genai/examples/EditImageAsync.java @@ -36,6 +36,7 @@ *

2. Compile the java package and run the sample code. * *

mvn clean compile exec:java -Dexec.mainClass="com.google.genai.examples.EditImageAsync" + * -Dexec.args="YOUR_MODEL_ID" */ package com.google.genai.examples; @@ -57,6 +58,11 @@ /** An example of using the Unified Gen AI Java SDK to edit an image asynchronously. */ public final class EditImageAsync { public static void main(String[] args) throws IOException, HttpException { + String modelId = "imagen-3.0-capability-001"; + if (args.length != 0) { + modelId = args[0]; + } + // Instantiate the client. The client by default uses the Gemini Developer API. It gets the API // key from the environment variable `GOOGLE_API_KEY`. Vertex AI API can be used by setting the // environment variables `GOOGLE_CLOUD_LOCATION` and `GOOGLE_CLOUD_PROJECT`, as well as setting @@ -102,10 +108,7 @@ public static void main(String[] args) throws IOException, HttpException { CompletableFuture editImageResponseFuture = client.async.models.editImage( - "imagen-3.0-capability-001", - "Sunlight and clear sky", - referenceImages, - editImageConfig); + modelId, "Sunlight and clear sky", referenceImages, editImageConfig); editImageResponseFuture .thenAccept( diff --git a/examples/src/main/java/com/google/genai/examples/EditImageControlReference.java b/examples/src/main/java/com/google/genai/examples/EditImageControlReference.java index 2f6f79d9fb5..e1b0757460b 100644 --- a/examples/src/main/java/com/google/genai/examples/EditImageControlReference.java +++ b/examples/src/main/java/com/google/genai/examples/EditImageControlReference.java @@ -38,6 +38,7 @@ *

mvn clean compile * *

mvn exec:java -Dexec.mainClass="com.google.genai.examples.EditImageControlReference" + * -Dexec.args="YOUR_MODEL_ID" */ package com.google.genai.examples; @@ -54,6 +55,11 @@ /** An example of using the Unified Gen AI Java SDK to edit an image (Control reference). */ public final class EditImageControlReference { public static void main(String[] args) { + String modelId = "imagen-3.0-capability-001"; + if (args.length != 0) { + modelId = args[0]; + } + // Instantiate the client. The client by default uses the Gemini Developer API. It gets the API // key from the environment variable `GOOGLE_API_KEY`. Vertex AI API can be used by setting the // environment variables `GOOGLE_CLOUD_LOCATION` and `GOOGLE_CLOUD_PROJECT`, as well as setting @@ -93,7 +99,7 @@ public static void main(String[] args) { EditImageResponse editImageResponse = client.models.editImage( - "imagen-3.0-capability-001", + modelId, "Change the colors aligning with the scribble map [1].", referenceImages, editImageConfig); diff --git a/examples/src/main/java/com/google/genai/examples/EditImageMaskReference.java b/examples/src/main/java/com/google/genai/examples/EditImageMaskReference.java index d7d64d12caf..1403b7af180 100644 --- a/examples/src/main/java/com/google/genai/examples/EditImageMaskReference.java +++ b/examples/src/main/java/com/google/genai/examples/EditImageMaskReference.java @@ -38,6 +38,7 @@ *

mvn clean compile * *

mvn exec:java -Dexec.mainClass="com.google.genai.examples.EditImageMaskReference" + * -Dexec.args="YOUR_MODEL_ID" */ package com.google.genai.examples; @@ -56,6 +57,11 @@ /** An example of using the Unified Gen AI Java SDK to edit an image (Mask reference). */ public final class EditImageMaskReference { public static void main(String[] args) { + String modelId = "imagen-3.0-capability-001"; + if (args.length != 0) { + modelId = args[0]; + } + // Instantiate the client. The client by default uses the Gemini Developer API. It gets the API // key from the environment variable `GOOGLE_API_KEY`. Vertex AI API can be used by setting the // environment variables `GOOGLE_CLOUD_LOCATION` and `GOOGLE_CLOUD_PROJECT`, as well as setting @@ -101,10 +107,7 @@ public static void main(String[] args) { EditImageResponse editImageResponse = client.models.editImage( - "imagen-3.0-capability-001", - "Sunlight and clear sky", - referenceImages, - editImageConfig); + modelId, "Sunlight and clear sky", referenceImages, editImageConfig); Image editedImage = editImageResponse.generatedImages().get().get(0).image().get(); // Do something with editedImage. diff --git a/examples/src/main/java/com/google/genai/examples/EditImageStyleTransfer.java b/examples/src/main/java/com/google/genai/examples/EditImageStyleTransfer.java index e89667a36dc..98ca3d2b49f 100644 --- a/examples/src/main/java/com/google/genai/examples/EditImageStyleTransfer.java +++ b/examples/src/main/java/com/google/genai/examples/EditImageStyleTransfer.java @@ -38,6 +38,7 @@ *

mvn clean compile * *

mvn exec:java -Dexec.mainClass="com.google.genai.examples.EditImageStyleTransfer" + * -Dexec.args="YOUR_MODEL_ID" */ package com.google.genai.examples; @@ -53,6 +54,11 @@ /** An example of using the Unified Gen AI Java SDK to edit an image (Style transfer). */ public final class EditImageStyleTransfer { public static void main(String[] args) { + String modelId = "imagen-3.0-capability-001"; + if (args.length != 0) { + modelId = args[0]; + } + // Instantiate the client. The client by default uses the Gemini Developer API. It gets the API // key from the environment variable `GOOGLE_API_KEY`. Vertex AI API can be used by setting the // environment variables `GOOGLE_CLOUD_LOCATION` and `GOOGLE_CLOUD_PROJECT`, as well as setting @@ -88,7 +94,7 @@ public static void main(String[] args) { EditImageResponse editImageResponse = client.models.editImage( - "imagen-3.0-capability-001", + modelId, "Generate an image in the style of [1] based on the following caption: A church in the" + " mountain.", referenceImages, diff --git a/examples/src/main/java/com/google/genai/examples/EditImageSubjectReference.java b/examples/src/main/java/com/google/genai/examples/EditImageSubjectReference.java index 1ef36675738..d6e074b5cdf 100644 --- a/examples/src/main/java/com/google/genai/examples/EditImageSubjectReference.java +++ b/examples/src/main/java/com/google/genai/examples/EditImageSubjectReference.java @@ -38,6 +38,7 @@ *

mvn clean compile * *

mvn exec:java -Dexec.mainClass="com.google.genai.examples.EditImageSubjectReference" + * -Dexec.args="YOUR_MODEL_ID" */ package com.google.genai.examples; @@ -54,6 +55,11 @@ /** An example of using the Unified Gen AI Java SDK to edit an image (Subject reference). */ public final class EditImageSubjectReference { public static void main(String[] args) { + String modelId = "imagen-3.0-capability-001"; + if (args.length != 0) { + modelId = args[0]; + } + // Instantiate the client. The client by default uses the Gemini Developer API. It gets the API // key from the environment variable `GOOGLE_API_KEY`. Vertex AI API can be used by setting the // environment variables `GOOGLE_CLOUD_LOCATION` and `GOOGLE_CLOUD_PROJECT`, as well as setting @@ -92,7 +98,7 @@ public static void main(String[] args) { EditImageResponse editImageResponse = client.models.editImage( - "imagen-3.0-capability-001", + modelId, "Generate an image containing a mug with the product logo [1] visible on the side of" + " the mug.", referenceImages, diff --git a/examples/src/main/java/com/google/genai/examples/EmbedContent.java b/examples/src/main/java/com/google/genai/examples/EmbedContent.java index 7f5e621a55c..f8ba861ca1e 100644 --- a/examples/src/main/java/com/google/genai/examples/EmbedContent.java +++ b/examples/src/main/java/com/google/genai/examples/EmbedContent.java @@ -36,6 +36,7 @@ *

2. Compile the java package and run the sample code. * *

mvn clean compile exec:java -Dexec.mainClass="com.google.genai.examples.EmbedContent" + * -Dexec.args="YOUR_MODEL_ID" */ package com.google.genai.examples; @@ -45,6 +46,11 @@ /** An example of using the Unified Gen AI Java SDK to embed content. */ public final class EmbedContent { public static void main(String[] args) { + String modelId = "text-embedding-004"; + if (args.length != 0) { + modelId = args[0]; + } + // Instantiate the client. The client by default uses the Gemini Developer API. It gets the API // key from the environment variable `GOOGLE_API_KEY`. Vertex AI API can be used by setting the // environment variables `GOOGLE_CLOUD_LOCATION` and `GOOGLE_CLOUD_PROJECT`, as well as setting @@ -62,7 +68,7 @@ public static void main(String[] args) { } EmbedContentResponse response = - client.models.embedContent("text-embedding-004", "why is the sky blue?", null); + client.models.embedContent(modelId, "why is the sky blue?", null); System.out.println("Embedding response: " + response); } diff --git a/examples/src/main/java/com/google/genai/examples/EmbedContentAsync.java b/examples/src/main/java/com/google/genai/examples/EmbedContentAsync.java index b8fe0dbb1e4..4a54506569f 100644 --- a/examples/src/main/java/com/google/genai/examples/EmbedContentAsync.java +++ b/examples/src/main/java/com/google/genai/examples/EmbedContentAsync.java @@ -36,6 +36,7 @@ *

2. Compile the java package and run the sample code. * *

mvn clean compile exec:java -Dexec.mainClass="com.google.genai.examples.EmbedContentAsync" + * -Dexec.args="YOUR_MODEL_ID" */ package com.google.genai.examples; @@ -46,6 +47,11 @@ /** An example of using the Unified Gen AI Java SDK to embed content asynchronously. */ public final class EmbedContentAsync { public static void main(String[] args) { + String modelId = "text-embedding-004"; + if (args.length != 0) { + modelId = args[0]; + } + // Instantiate the client. The client by default uses the Gemini Developer API. It gets the API // key from the environment variable `GOOGLE_API_KEY`. Vertex AI API can be used by setting the // environment variables `GOOGLE_CLOUD_LOCATION` and `GOOGLE_CLOUD_PROJECT`, as well as setting @@ -63,7 +69,7 @@ public static void main(String[] args) { } CompletableFuture responseFuture = - client.async.models.embedContent("text-embedding-004", "Why is the sky blue?", null); + client.async.models.embedContent(modelId, "Why is the sky blue?", null); responseFuture .thenAccept( diff --git a/examples/src/main/java/com/google/genai/examples/EmbedContentWithConfig.java b/examples/src/main/java/com/google/genai/examples/EmbedContentWithConfig.java index 797eae0502b..7adbc9e42f4 100644 --- a/examples/src/main/java/com/google/genai/examples/EmbedContentWithConfig.java +++ b/examples/src/main/java/com/google/genai/examples/EmbedContentWithConfig.java @@ -38,6 +38,7 @@ *

mvn clean compile * *

mvn exec:java -Dexec.mainClass="com.google.genai.examples.EmbedContentWithConfig" + * -Dexec.args="YOUR_MODEL_ID" */ package com.google.genai.examples; @@ -49,6 +50,11 @@ /** An example of using the Unified Gen AI Java SDK to embed content with extra config. */ public final class EmbedContentWithConfig { public static void main(String[] args) { + String modelId = "text-embedding-004"; + if (args.length != 0) { + modelId = args[0]; + } + // Instantiate the client. The client by default uses the Gemini Developer API. It gets the API // key from the environment variable `GOOGLE_API_KEY`. Vertex AI API can be used by setting the // environment variables `GOOGLE_CLOUD_LOCATION` and `GOOGLE_CLOUD_PROJECT`, as well as setting @@ -69,9 +75,7 @@ public static void main(String[] args) { EmbedContentResponse response = client.models.embedContent( - "text-embedding-004", - ImmutableList.of("why is the sky blue?", "What is your age?"), - config); + modelId, ImmutableList.of("why is the sky blue?", "What is your age?"), config); System.out.println("Embedding response: " + response); } diff --git a/examples/src/main/java/com/google/genai/examples/GenerateContent.java b/examples/src/main/java/com/google/genai/examples/GenerateContent.java index 6459b407710..b2408e1f533 100644 --- a/examples/src/main/java/com/google/genai/examples/GenerateContent.java +++ b/examples/src/main/java/com/google/genai/examples/GenerateContent.java @@ -36,6 +36,7 @@ *

2. Compile the java package and run the sample code. * *

mvn clean compile exec:java -Dexec.mainClass="com.google.genai.examples.GenerateContent" + * -Dexec.args="YOUR_MODEL_ID" */ package com.google.genai.examples; @@ -45,6 +46,11 @@ /** An example of using the Unified Gen AI Java SDK to generate content. */ public final class GenerateContent { public static void main(String[] args) { + String modelId = "gemini-2.0-flash-001"; + if (args.length != 0) { + modelId = args[0]; + } + // Instantiate the client. The client by default uses the Gemini Developer API. It gets the API // key from the environment variable `GOOGLE_API_KEY`. Vertex AI API can be used by setting the // environment variables `GOOGLE_CLOUD_LOCATION` and `GOOGLE_CLOUD_PROJECT`, as well as setting @@ -62,7 +68,7 @@ public static void main(String[] args) { } GenerateContentResponse response = - client.models.generateContent("gemini-2.0-flash-001", "What is your name?", null); + client.models.generateContent(modelId, "What is your name?", null); // Gets the text string from the response by the quick accessor method `text()`. System.out.println("Unary response: " + response.text()); diff --git a/examples/src/main/java/com/google/genai/examples/GenerateContentAsync.java b/examples/src/main/java/com/google/genai/examples/GenerateContentAsync.java index f50354da19b..49db5cd6e78 100644 --- a/examples/src/main/java/com/google/genai/examples/GenerateContentAsync.java +++ b/examples/src/main/java/com/google/genai/examples/GenerateContentAsync.java @@ -36,6 +36,7 @@ *

2. Compile the java package and run the sample code. * *

mvn clean compile exec:java -Dexec.mainClass="com.google.genai.examples.GenerateContentAsync" + * -Dexec.args="YOUR_MODEL_ID" */ package com.google.genai.examples; @@ -46,6 +47,11 @@ /** An example of using the Unified Gen AI Java SDK to generate content asynchronously. */ public final class GenerateContentAsync { public static void main(String[] args) { + String modelId = "gemini-2.0-flash-001"; + if (args.length != 0) { + modelId = args[0]; + } + // Instantiate the client. The client by default uses the Gemini Developer API. It gets the API // key from the environment variable `GOOGLE_API_KEY`. Vertex AI API can be used by setting the // environment variables `GOOGLE_CLOUD_LOCATION` and `GOOGLE_CLOUD_PROJECT`, as well as setting @@ -63,8 +69,7 @@ public static void main(String[] args) { } CompletableFuture responseFuture = - client.async.models.generateContent( - "gemini-2.0-flash-001", "Introduce Google AI Studio.", null); + client.async.models.generateContent(modelId, "Introduce Google AI Studio.", null); responseFuture .thenAccept( diff --git a/examples/src/main/java/com/google/genai/examples/GenerateContentStream.java b/examples/src/main/java/com/google/genai/examples/GenerateContentStream.java index a226663c4d8..e17c8cbedf1 100644 --- a/examples/src/main/java/com/google/genai/examples/GenerateContentStream.java +++ b/examples/src/main/java/com/google/genai/examples/GenerateContentStream.java @@ -36,6 +36,7 @@ *

2. Compile the java package and run the sample code. * *

mvn clean compile exec:java -Dexec.mainClass="com.google.genai.examples.GenerateContentStream" + * -Dexec.args="YOUR_MODEL_ID" */ package com.google.genai.examples; @@ -46,6 +47,11 @@ /** An example of using the Unified GenAI Java SDK to generate stream of content. */ public final class GenerateContentStream { public static void main(String[] args) { + String modelId = "gemini-2.0-flash-001"; + if (args.length != 0) { + modelId = args[0]; + } + // Instantiate the client. The client by default uses the Gemini Developer API. It gets the API // key from the environment variable `GOOGLE_API_KEY`. Vertex AI API can be used by setting the // environment variables `GOOGLE_CLOUD_LOCATION` and `GOOGLE_CLOUD_PROJECT`, as well as setting @@ -63,8 +69,7 @@ public static void main(String[] args) { } ResponseStream responseStream = - client.models.generateContentStream( - "gemini-2.0-flash-001", "Tell me a story in 300 words.", null); + client.models.generateContentStream(modelId, "Tell me a story in 300 words.", null); System.out.println("Streaming response: "); for (GenerateContentResponse res : responseStream) { diff --git a/examples/src/main/java/com/google/genai/examples/GenerateContentWithConfigs.java b/examples/src/main/java/com/google/genai/examples/GenerateContentWithConfigs.java index dd7c123121e..1366cfeb44a 100644 --- a/examples/src/main/java/com/google/genai/examples/GenerateContentWithConfigs.java +++ b/examples/src/main/java/com/google/genai/examples/GenerateContentWithConfigs.java @@ -38,6 +38,7 @@ *

mvn clean compile * *

mvn exec:java -Dexec.mainClass="com.google.genai.examples.GenerateContentWithConfigs" + * -Dexec.args="YOUR_MODEL_ID" */ package com.google.genai.examples; @@ -56,6 +57,11 @@ /** An example of using the Unified Gen AI Java SDK to generate content with extra configs. */ public final class GenerateContentWithConfigs { public static void main(String[] args) { + String modelId = "gemini-2.0-flash-001"; + if (args.length != 0) { + modelId = args[0]; + } + // Instantiate the client. The client by default uses the Gemini Developer API. It gets the API // key from the environment variable `GOOGLE_API_KEY`. Vertex AI API can be used by setting the // environment variables `GOOGLE_CLOUD_LOCATION` and `GOOGLE_CLOUD_PROJECT`, as well as setting @@ -100,7 +106,7 @@ public static void main(String[] args) { .build(); GenerateContentResponse response = - client.models.generateContent("gemini-2.0-flash-001", "Tell me the history of LLM", config); + client.models.generateContent(modelId, "Tell me the history of LLM", config); System.out.println("Response: " + response.text()); } diff --git a/examples/src/main/java/com/google/genai/examples/GenerateContentWithFunctionCall.java b/examples/src/main/java/com/google/genai/examples/GenerateContentWithFunctionCall.java index 5e532ef4607..bd4b5f5aaf9 100644 --- a/examples/src/main/java/com/google/genai/examples/GenerateContentWithFunctionCall.java +++ b/examples/src/main/java/com/google/genai/examples/GenerateContentWithFunctionCall.java @@ -38,6 +38,7 @@ *

mvn clean compile * *

mvn exec:java -Dexec.mainClass="com.google.genai.examples.GenerateContentWithFunctionCall" + * -Dexec.args="YOUR_MODEL_ID" */ package com.google.genai.examples; @@ -60,6 +61,11 @@ public static Integer divideTwoIntegers(Integer numerator, Integer denominator) } public static void main(String[] args) throws NoSuchMethodException { + String modelId = "gemini-2.0-flash-001"; + if (args.length != 0) { + modelId = args[0]; + } + // Instantiate the client. The client by default uses the Gemini Developer API. It gets the API // key from the environment variable `GOOGLE_API_KEY`. Vertex AI API can be used by setting the // environment variables `GOOGLE_CLOUD_LOCATION` and `GOOGLE_CLOUD_PROJECT`, as well as setting @@ -89,9 +95,7 @@ public static void main(String[] args) throws NoSuchMethodException { GenerateContentResponse response = client.models.generateContent( - "gemini-2.0-flash-001", - "What is the weather in Vancouver? And can you divide 10 by 0?", - config); + modelId, "What is the weather in Vancouver? And can you divide 10 by 0?", config); System.out.println("The response is: " + response.text()); System.out.println( diff --git a/examples/src/main/java/com/google/genai/examples/GenerateContentWithImageInput.java b/examples/src/main/java/com/google/genai/examples/GenerateContentWithImageInput.java index a8cd337da8d..cba08750659 100644 --- a/examples/src/main/java/com/google/genai/examples/GenerateContentWithImageInput.java +++ b/examples/src/main/java/com/google/genai/examples/GenerateContentWithImageInput.java @@ -38,6 +38,7 @@ *

mvn clean compile * *

mvn exec:java -Dexec.mainClass="com.google.genai.examples.GenerateContentWithImageInput" + * -Dexec.args="YOUR_MODEL_ID" */ package com.google.genai.examples; @@ -49,6 +50,11 @@ /** An example of using the Unified Gen AI Java SDK to generate content with image input. */ public final class GenerateContentWithImageInput { public static void main(String[] args) { + String modelId = "gemini-2.0-flash-001"; + if (args.length != 0) { + modelId = args[0]; + } + // Instantiate the client. The client by default uses the Gemini Developer API. It gets the API // key from the environment variable `GOOGLE_API_KEY`. Vertex AI API can be used by setting the // environment variables `GOOGLE_CLOUD_LOCATION` and `GOOGLE_CLOUD_PROJECT`, as well as setting @@ -72,8 +78,7 @@ public static void main(String[] args) { Part.fromText("describe the image"), Part.fromUri("gs://cloud-samples-data/generative-ai/image/scones.jpg", "image/jpeg")); - GenerateContentResponse response = - client.models.generateContent("gemini-2.0-flash-001", content, null); + GenerateContentResponse response = client.models.generateContent(modelId, content, null); System.out.println("Response: " + response.text()); } diff --git a/examples/src/main/java/com/google/genai/examples/GenerateContentWithResponseModality.java b/examples/src/main/java/com/google/genai/examples/GenerateContentWithResponseModality.java index 89b65325a64..2a7c0c37d48 100644 --- a/examples/src/main/java/com/google/genai/examples/GenerateContentWithResponseModality.java +++ b/examples/src/main/java/com/google/genai/examples/GenerateContentWithResponseModality.java @@ -38,6 +38,7 @@ *

mvn clean compile * *

mvn exec:java -Dexec.mainClass="com.google.genai.examples.GenerateContentWithResponseModality" + * -Dexec.args="YOUR_MODEL_ID" */ package com.google.genai.examples; @@ -48,6 +49,11 @@ /** An example of using the Unified Gen AI Java SDK to generate content with response modality. */ public final class GenerateContentWithResponseModality { public static void main(String[] args) { + String modelId = "gemini-2.0-flash-preview-image-generation"; + if (args.length != 0) { + modelId = args[0]; + } + // Instantiate the client. The client by default uses the Gemini Developer API. It gets the API // key from the environment variable `GOOGLE_API_KEY`. Vertex AI API can be used by setting the // environment variables `GOOGLE_CLOUD_LOCATION` and `GOOGLE_CLOUD_PROJECT`, as well as setting @@ -68,10 +74,7 @@ public static void main(String[] args) { GenerateContentConfig.builder().responseModalities("TEXT", "IMAGE").build(); GenerateContentResponse response = - client.models.generateContent( - "gemini-2.0-flash-preview-image-generation", - "Generate a cat image and describe it.", - config); + client.models.generateContent(modelId, "Generate a cat image and describe it.", config); System.out.println("Response: " + response.toJson()); } diff --git a/examples/src/main/java/com/google/genai/examples/GenerateContentWithResponseSchema.java b/examples/src/main/java/com/google/genai/examples/GenerateContentWithResponseSchema.java index 10a1ed807fd..0407244cc25 100644 --- a/examples/src/main/java/com/google/genai/examples/GenerateContentWithResponseSchema.java +++ b/examples/src/main/java/com/google/genai/examples/GenerateContentWithResponseSchema.java @@ -38,6 +38,7 @@ *

mvn clean compile * *

mvn exec:java -Dexec.mainClass="com.google.genai.examples.GenerateContentWithResponseSchema" + * -Dexec.args="YOUR_MODEL_ID" */ package com.google.genai.examples; @@ -54,6 +55,11 @@ */ public final class GenerateContentWithResponseSchema { public static void main(String[] args) { + String modelId = "gemini-2.0-flash-001"; + if (args.length != 0) { + modelId = args[0]; + } + // Instantiate the client. The client by default uses the Gemini Developer API. It gets the API // key from the environment variable `GOOGLE_API_KEY`. Vertex AI API can be used by setting the // environment variables `GOOGLE_CLOUD_LOCATION` and `GOOGLE_CLOUD_PROJECT`, as well as setting @@ -95,8 +101,7 @@ public static void main(String[] args) { .build(); GenerateContentResponse response = - client.models.generateContent( - "gemini-2.0-flash-001", "List a few popular cookie recipes.", config); + client.models.generateContent(modelId, "List a few popular cookie recipes.", config); System.out.println("Response: " + response.text()); } diff --git a/examples/src/main/java/com/google/genai/examples/GenerateImages.java b/examples/src/main/java/com/google/genai/examples/GenerateImages.java index b050211ab68..4b6cfb2230b 100644 --- a/examples/src/main/java/com/google/genai/examples/GenerateImages.java +++ b/examples/src/main/java/com/google/genai/examples/GenerateImages.java @@ -36,6 +36,7 @@ *

2. Compile the java package and run the sample code. * *

mvn clean compile exec:java -Dexec.mainClass="com.google.genai.examples.GenerateImages" + * -Dexec.args="YOUR_MODEL_ID" */ package com.google.genai.examples; @@ -47,6 +48,11 @@ /** An example of using the Unified Gen AI Java SDK to generate images. */ public final class GenerateImages { public static void main(String[] args) { + String modelId = "imagen-3.0-generate-002"; + if (args.length != 0) { + modelId = args[0]; + } + // Instantiate the client. The client by default uses the Gemini Developer API. It gets the API // key from the environment variable `GOOGLE_API_KEY`. Vertex AI API can be used by setting the // environment variables `GOOGLE_CLOUD_LOCATION` and `GOOGLE_CLOUD_PROJECT`, as well as setting @@ -72,7 +78,7 @@ public static void main(String[] args) { GenerateImagesResponse generatedImagesResponse = client.models.generateImages( - "imagen-3.0-generate-002", "Robot holding a red skateboard", generateImagesConfig); + modelId, "Robot holding a red skateboard", generateImagesConfig); System.out.println( "Generated " + generatedImagesResponse.generatedImages().get().size() + " images."); diff --git a/examples/src/main/java/com/google/genai/examples/GenerateImagesAsync.java b/examples/src/main/java/com/google/genai/examples/GenerateImagesAsync.java index 4320bda8c6d..94f9d570a8e 100644 --- a/examples/src/main/java/com/google/genai/examples/GenerateImagesAsync.java +++ b/examples/src/main/java/com/google/genai/examples/GenerateImagesAsync.java @@ -36,6 +36,7 @@ *

2. Compile the java package and run the sample code. * *

mvn clean compile exec:java -Dexec.mainClass="com.google.genai.examples.GenerateImagesAsync" + * -Dexec.args="YOUR_MODEL_ID" */ package com.google.genai.examples; @@ -48,6 +49,11 @@ /** An example of using the Unified Gen AI Java SDK to generate images asynchronously. */ public final class GenerateImagesAsync { public static void main(String[] args) { + String modelId = "imagen-3.0-generate-002"; + if (args.length != 0) { + modelId = args[0]; + } + // Instantiate the client. The client by default uses the Gemini Developer API. It gets the API // key from the environment variable `GOOGLE_API_KEY`. Vertex AI API can be used by setting the // environment variables `GOOGLE_CLOUD_LOCATION` and `GOOGLE_CLOUD_PROJECT`, as well as setting @@ -73,7 +79,7 @@ public static void main(String[] args) { CompletableFuture generateImagesResponseFuture = client.async.models.generateImages( - "imagen-3.0-generate-002", "Robot holding a red skateboard", generateImagesConfig); + modelId, "Robot holding a red skateboard", generateImagesConfig); generateImagesResponseFuture .thenAccept( diff --git a/examples/src/main/java/com/google/genai/examples/GenerateVideos.java b/examples/src/main/java/com/google/genai/examples/GenerateVideos.java index 4228f4eff6c..95b1933f9af 100644 --- a/examples/src/main/java/com/google/genai/examples/GenerateVideos.java +++ b/examples/src/main/java/com/google/genai/examples/GenerateVideos.java @@ -36,6 +36,7 @@ *

2. Compile the java package and run the sample code. * *

mvn clean compile exec:java -Dexec.mainClass="com.google.genai.examples.GenerateVideos" + * -Dexec.args="YOUR_MODEL_ID" */ package com.google.genai.examples; @@ -48,6 +49,11 @@ /** An example of using the Unified Gen AI Java SDK to generate videos. */ public final class GenerateVideos { public static void main(String[] args) { + String modelId = "veo-2.0-generate-001"; + if (args.length != 0) { + modelId = args[0]; + } + // Instantiate the client. The client by default uses the Gemini Developer API. It gets the API // key from the environment variable `GOOGLE_API_KEY`. Vertex AI API can be used by setting the // environment variables `GOOGLE_CLOUD_LOCATION` and `GOOGLE_CLOUD_PROJECT`, as well as setting @@ -74,10 +80,7 @@ public static void main(String[] args) { GenerateVideosOperation generateVideosOperation = client.models.generateVideos( - "veo-2.0-generate-001", - "A neon hologram of a cat driving at top speed", - null, - generateVideosConfig); + modelId, "A neon hologram of a cat driving at top speed", null, generateVideosConfig); // GenerateVideosOperation.done() is empty if the operation is not done. while (!generateVideosOperation.done().filter(Boolean::booleanValue).isPresent()) { diff --git a/examples/src/main/java/com/google/genai/examples/GenerateVideosAsync.java b/examples/src/main/java/com/google/genai/examples/GenerateVideosAsync.java index 4897db41b92..03a9e7d8687 100644 --- a/examples/src/main/java/com/google/genai/examples/GenerateVideosAsync.java +++ b/examples/src/main/java/com/google/genai/examples/GenerateVideosAsync.java @@ -36,6 +36,7 @@ *

2. Compile the java package and run the sample code. * *

mvn clean compile exec:java -Dexec.mainClass="com.google.genai.examples.GenerateVideosAsync" + * -Dexec.args="YOUR_MODEL_ID" */ package com.google.genai.examples; @@ -49,6 +50,11 @@ /** An example of using the Unified Gen AI Java SDK to generate images asynchronously. */ public final class GenerateVideosAsync { public static void main(String[] args) { + String modelId = "veo-2.0-generate-001"; + if (args.length != 0) { + modelId = args[0]; + } + // Instantiate the client. The client by default uses the Gemini Developer API. It gets the API // key from the environment variable `GOOGLE_API_KEY`. Vertex AI API can be used by setting the // environment variables `GOOGLE_CLOUD_LOCATION` and `GOOGLE_CLOUD_PROJECT`, as well as setting @@ -75,10 +81,7 @@ public static void main(String[] args) { CompletableFuture generateVideosOperationFuture = client.async.models.generateVideos( - "veo-2.0-generate-001", - "A neon hologram of a cat driving at top speed", - null, - generateVideosConfig); + modelId, "A neon hologram of a cat driving at top speed", null, generateVideosConfig); generateVideosOperationFuture .thenAccept( diff --git a/examples/src/main/java/com/google/genai/examples/LiveAudioConversationAsync.java b/examples/src/main/java/com/google/genai/examples/LiveAudioConversationAsync.java index be5533f2963..2ee11b79691 100644 --- a/examples/src/main/java/com/google/genai/examples/LiveAudioConversationAsync.java +++ b/examples/src/main/java/com/google/genai/examples/LiveAudioConversationAsync.java @@ -39,6 +39,7 @@ *

mvn clean * *

mvn compile exec:java -Dexec.mainClass="com.google.genai.examples.LiveAudioConversationAsync" + * -Dexec.args="YOUR_MODEL_ID" * *

3. Speak into the microphone. Press Ctrl+C to exit. Important: This example uses the system * default audio input and output, which often won't include echo cancellation. So to prevent the @@ -134,7 +135,6 @@ private static void sendMicrophoneAudio() { } public static void main(String[] args) throws LineUnavailableException { - // Instantiate the client. The client by default uses the Gemini Developer API. It gets the API // key from the environment variable `GOOGLE_API_KEY`. Vertex AI API can be used by setting the // environment variables `GOOGLE_CLOUD_LOCATION` and `GOOGLE_CLOUD_PROJECT`, as well as setting @@ -151,6 +151,16 @@ public static void main(String[] args) throws LineUnavailableException { System.out.println("Using Gemini Developer API"); } + String modelId; + if (client.vertexAI()) { + modelId = "gemini-2.0-flash-live-preview-04-09"; + } else { + modelId = "gemini-2.0-flash-live-001"; + } + if (args.length != 0) { + modelId = args[0]; + } + // --- Audio Line Setup --- microphoneLine = getMicrophoneLine(); speakerLine = getSpeakerLine(); @@ -208,11 +218,7 @@ public static void main(String[] args) throws LineUnavailableException { // --- Connect to Gemini Live API --- System.out.println("Connecting to Gemini Live API..."); - if (client.vertexAI()) { - session = client.async.live.connect("gemini-2.0-flash-live-preview-04-09", config).get(); - } else { - session = client.async.live.connect("gemini-2.0-flash-live-001", config).get(); - } + session = client.async.live.connect(modelId, config).get(); System.out.println("Connected."); // --- Start Audio Lines --- diff --git a/examples/src/main/java/com/google/genai/examples/LiveTextContextWindowCompressionAsync.java b/examples/src/main/java/com/google/genai/examples/LiveTextContextWindowCompressionAsync.java index 793f5720dee..fa7f13f02e6 100644 --- a/examples/src/main/java/com/google/genai/examples/LiveTextContextWindowCompressionAsync.java +++ b/examples/src/main/java/com/google/genai/examples/LiveTextContextWindowCompressionAsync.java @@ -39,6 +39,7 @@ * *

mvn exec:java * -Dexec.mainClass="com.google.genai.examples.LiveTextContextWindowCompressionAsync" + * -Dexec.args="YOUR_MODEL_ID" */ package com.google.genai.examples; @@ -76,6 +77,16 @@ public static void main(String[] args) { System.out.println("Using Gemini Developer API"); } + String modelId; + if (client.vertexAI()) { + modelId = "gemini-2.0-flash-live-preview-04-09"; + } else { + modelId = "gemini-2.0-flash-live-001"; + } + if (args.length != 0) { + modelId = args[0]; + } + LiveConnectConfig config = LiveConnectConfig.builder() .responseModalities(Modality.Known.TEXT) @@ -87,15 +98,7 @@ public static void main(String[] args) { CompletableFuture allDone = new CompletableFuture<>(); - String modelName; - if (client.vertexAI()) { - modelName = "gemini-2.0-flash-live-preview-04-09"; - } else { - modelName = "gemini-2.0-flash-live-001"; - } - - CompletableFuture futureSession = client.async.live.connect(modelName, config); - + CompletableFuture futureSession = client.async.live.connect(modelId, config); futureSession .thenCompose( session -> { diff --git a/examples/src/main/java/com/google/genai/examples/LiveTextConversationAsync.java b/examples/src/main/java/com/google/genai/examples/LiveTextConversationAsync.java index a266d46ba3c..5fa3dd3cb81 100644 --- a/examples/src/main/java/com/google/genai/examples/LiveTextConversationAsync.java +++ b/examples/src/main/java/com/google/genai/examples/LiveTextConversationAsync.java @@ -38,6 +38,7 @@ *

mvn clean compile * *

mvn exec:java -Dexec.mainClass="com.google.genai.examples.LiveTextConversationAsync" + * -Dexec.args="YOUR_MODEL_ID" */ package com.google.genai.examples; @@ -74,6 +75,16 @@ public static void main(String[] args) { System.out.println("Using Gemini Developer API"); } + String modelId; + if (client.vertexAI()) { + modelId = "gemini-2.0-flash-live-preview-04-09"; + } else { + modelId = "gemini-2.0-flash-live-001"; + } + if (args.length != 0) { + modelId = args[0]; + } + LiveConnectConfig config = LiveConnectConfig.builder() .responseModalities(Modality.Known.TEXT) @@ -86,11 +97,7 @@ public static void main(String[] args) { AsyncSession session; try { - if (client.vertexAI()) { - session = client.async.live.connect("gemini-2.0-flash-live-preview-04-09", config).get(); - } else { - session = client.async.live.connect("gemini-2.0-flash-live-001", config).get(); - } + session = client.async.live.connect(modelId, config).get(); // Start receiving messages. CompletableFuture receiveFuture = session.receive(message -> printLiveServerMessage(message, allDone)); diff --git a/examples/src/main/java/com/google/genai/examples/LiveTextConversationResumptionAsync.java b/examples/src/main/java/com/google/genai/examples/LiveTextConversationResumptionAsync.java index 755af1453e3..eb22da47ea6 100644 --- a/examples/src/main/java/com/google/genai/examples/LiveTextConversationResumptionAsync.java +++ b/examples/src/main/java/com/google/genai/examples/LiveTextConversationResumptionAsync.java @@ -38,6 +38,7 @@ *

mvn clean compile * *

mvn exec:java -Dexec.mainClass="com.google.genai.examples.LiveTextConversationResumptionAsync" + * -Dexec.args="YOUR_MODEL_ID" * *

to resume a session, you can use the --session_handle argument to provide the session handle * returned in the session resumption update from the server. @@ -45,7 +46,7 @@ *

mvn clean compile * *

mvn exec:java -Dexec.mainClass="com.google.genai.examples.LiveTextConversationResumptionAsync" - * -Dexec.args="--session_handle=..." + * -Dexec.args="YOUR_MODEL_ID --session_handle=..." */ package com.google.genai.examples; @@ -68,9 +69,22 @@ public final class LiveTextConversationResumptionAsync { public static void main(String[] args) { + boolean containsModelId = false; // Get the session handle from the command line, if provided String sessionHandle = null; - if (args.length > 0) { + if (args.length > 1) { + containsModelId = true; + if (args[1].startsWith("--session_handle")) { + String[] parts = args[1].split("=", 2); + if (parts.length == 2) { + sessionHandle = parts[1]; + } else if (parts.length == 1) { + System.err.println("Error: --session_handle requires a value."); + System.err.println("Usage: mvn ... --session_handle="); + System.exit(1); + } + } + } else if (args.length == 1) { if (args[0].startsWith("--session_handle")) { String[] parts = args[0].split("=", 2); if (parts.length == 2) { @@ -80,6 +94,8 @@ public static void main(String[] args) { System.err.println("Usage: mvn ... --session_handle="); System.exit(1); } + } else { + containsModelId = true; } } @@ -99,6 +115,16 @@ public static void main(String[] args) { System.out.println("Using Gemini Developer API"); } + String modelId; + if (client.vertexAI()) { + modelId = "gemini-2.0-flash-live-preview-04-09"; + } else { + modelId = "gemini-2.0-flash-live-001"; + } + if (containsModelId) { + modelId = args[0]; + } + SessionResumptionConfig.Builder sessionResumptionConfigBuilder = SessionResumptionConfig.builder(); if (sessionHandle != null) { @@ -120,13 +146,7 @@ public static void main(String[] args) { AsyncSession session; try { - if (client.vertexAI()) { - System.out.println("vertex"); - session = client.async.live.connect("gemini-2.0-flash-live-preview-04-09", config).get(); - } else { - System.out.println("mldev"); - session = client.async.live.connect("gemini-2.0-flash-live-001", config).get(); - } + session = client.async.live.connect(modelId, config).get(); // Start receiving messages. CompletableFuture receiveFuture = session.receive(message -> printLiveServerMessage(message, allDone)); diff --git a/examples/src/main/java/com/google/genai/examples/LiveTextToAudioTranscriptionAsync.java b/examples/src/main/java/com/google/genai/examples/LiveTextToAudioTranscriptionAsync.java index 2ca5ffb7a2d..9fa79bb7dda 100644 --- a/examples/src/main/java/com/google/genai/examples/LiveTextToAudioTranscriptionAsync.java +++ b/examples/src/main/java/com/google/genai/examples/LiveTextToAudioTranscriptionAsync.java @@ -38,6 +38,7 @@ *

mvn clean compile * *

mvn exec:java -Dexec.mainClass="com.google.genai.examples.LiveTextToAudioTranscriptionAsync" + * -Dexec.args="YOUR_MODEL_ID" */ package com.google.genai.examples; @@ -83,6 +84,16 @@ public static void main(String[] args) { System.out.println("Using Gemini Developer API"); } + String modelId; + if (client.vertexAI()) { + modelId = "gemini-2.0-flash-live-preview-04-09"; + } else { + modelId = "gemini-2.0-flash-live-001"; + } + if (args.length != 0) { + modelId = args[0]; + } + // Sets the system instruction in the config. Content systemInstruction = Content.fromParts(Part.fromText("Answer in Japanese.")); // Sets the Google Search tool in the config. @@ -99,14 +110,7 @@ public static void main(String[] args) { CompletableFuture allDone = new CompletableFuture<>(); - String modelName; - if (client.vertexAI()) { - modelName = "gemini-2.0-flash-live-preview-04-09"; - } else { - modelName = "gemini-2.0-flash-live-001"; - } - - CompletableFuture futureSession = client.async.live.connect(modelName, config); + CompletableFuture futureSession = client.async.live.connect(modelId, config); futureSession .thenCompose( diff --git a/examples/src/main/java/com/google/genai/examples/LiveTextToTextGenerationAsync.java b/examples/src/main/java/com/google/genai/examples/LiveTextToTextGenerationAsync.java index 924d00d302c..46bb125210e 100644 --- a/examples/src/main/java/com/google/genai/examples/LiveTextToTextGenerationAsync.java +++ b/examples/src/main/java/com/google/genai/examples/LiveTextToTextGenerationAsync.java @@ -38,6 +38,7 @@ *

mvn clean compile * *

mvn exec:java -Dexec.mainClass="com.google.genai.examples.LiveTextToTextGenerationAsync" + * -Dexec.args="YOUR_MODEL_ID" */ package com.google.genai.examples; @@ -73,19 +74,22 @@ public static void main(String[] args) { System.out.println("Using Gemini Developer API"); } + String modelId; + if (client.vertexAI()) { + modelId = "gemini-2.0-flash-live-preview-04-09"; + } else { + modelId = "gemini-2.0-flash-live-001"; + } + if (args.length != 0) { + modelId = args[0]; + } + LiveConnectConfig config = LiveConnectConfig.builder().responseModalities(Modality.Known.TEXT).build(); CompletableFuture allDone = new CompletableFuture<>(); - String modelName; - if (client.vertexAI()) { - modelName = "gemini-2.0-flash-live-preview-04-09"; - } else { - modelName = "gemini-2.0-flash-live-001"; - } - - CompletableFuture futureSession = client.async.live.connect(modelName, config); + CompletableFuture futureSession = client.async.live.connect(modelId, config); futureSession .thenCompose( diff --git a/examples/src/main/java/com/google/genai/examples/RequestLevelHttpOptions.java b/examples/src/main/java/com/google/genai/examples/RequestLevelHttpOptions.java index f4310e976cb..99b3a4f3dca 100644 --- a/examples/src/main/java/com/google/genai/examples/RequestLevelHttpOptions.java +++ b/examples/src/main/java/com/google/genai/examples/RequestLevelHttpOptions.java @@ -38,6 +38,7 @@ *

mvn clean compile * *

mvn exec:java -Dexec.mainClass="com.google.genai.examples.RequestLevelHttpOptions" + * -Dexec.args="YOUR_MODEL_ID" */ package com.google.genai.examples; @@ -50,6 +51,11 @@ /** An example of setting http options at request level. */ public final class RequestLevelHttpOptions { public static void main(String[] args) { + String modelId = "gemini-2.0-flash-001"; + if (args.length != 0) { + modelId = args[0]; + } + // Instantiate the client. The client by default uses the Gemini Developer API. It gets the API // key from the environment variable `GOOGLE_API_KEY`. Vertex AI API can be used by setting the // environment variables `GOOGLE_CLOUD_LOCATION` and `GOOGLE_CLOUD_PROJECT`, as well as setting @@ -73,7 +79,7 @@ public static void main(String[] args) { .build(); GenerateContentResponse response = - client.models.generateContent("gemini-2.0-flash-001", "Tell me the history of LLM", config); + client.models.generateContent(modelId, "Tell me the history of LLM", config); System.out.println("Response: " + response.text()); } diff --git a/examples/src/main/java/com/google/genai/examples/UpscaleImage.java b/examples/src/main/java/com/google/genai/examples/UpscaleImage.java index 96e9eea2c76..73a8f404021 100644 --- a/examples/src/main/java/com/google/genai/examples/UpscaleImage.java +++ b/examples/src/main/java/com/google/genai/examples/UpscaleImage.java @@ -36,6 +36,7 @@ *

2. Compile the java package and run the sample code. * *

mvn clean compile exec:java -Dexec.mainClass="com.google.genai.examples.UpscaleImage" + * -Dexec.args="YOUR_MODEL_ID" */ package com.google.genai.examples; @@ -47,6 +48,11 @@ /** An example of using the Unified Gen AI Java SDK to upscale an image. */ public final class UpscaleImage { public static void main(String[] args) { + String modelId = "imagen-3.0-generate-001"; + if (args.length != 0) { + modelId = args[0]; + } + // Instantiate the client. The client by default uses the Gemini Developer API. It gets the API // key from the environment variable `GOOGLE_API_KEY`. Vertex AI API can be used by setting the // environment variables `GOOGLE_CLOUD_LOCATION` and `GOOGLE_CLOUD_PROJECT`, as well as setting @@ -69,7 +75,7 @@ public static void main(String[] args) { UpscaleImageResponse upscaleImageResponse = client.models.upscaleImage( - "imagen-3.0-generate-001", + modelId, image, "x2", UpscaleImageConfig.builder().outputMimeType("image/jpeg").build()); diff --git a/examples/src/main/java/com/google/genai/examples/UpscaleImageAsync.java b/examples/src/main/java/com/google/genai/examples/UpscaleImageAsync.java index b71f4d69ab3..bd516658c96 100644 --- a/examples/src/main/java/com/google/genai/examples/UpscaleImageAsync.java +++ b/examples/src/main/java/com/google/genai/examples/UpscaleImageAsync.java @@ -36,6 +36,7 @@ *

2. Compile the java package and run the sample code. * *

mvn clean compile exec:java -Dexec.mainClass="com.google.genai.examples.UpscaleImageAsync" + * -Dexec.args="YOUR_MODEL_ID" */ package com.google.genai.examples; @@ -48,6 +49,11 @@ /** An example of using the Unified Gen AI Java SDK to upscale an image asynchronously. */ public final class UpscaleImageAsync { public static void main(String[] args) { + String modelId = "imagen-3.0-generate-001"; + if (args.length != 0) { + modelId = args[0]; + } + // Instantiate the client. The client by default uses the Gemini Developer API. It gets the API // key from the environment variable `GOOGLE_API_KEY`. Vertex AI API can be used by setting the // environment variables `GOOGLE_CLOUD_LOCATION` and `GOOGLE_CLOUD_PROJECT`, as well as setting @@ -70,7 +76,7 @@ public static void main(String[] args) { CompletableFuture upscaleImageResponseFuture = client.async.models.upscaleImage( - "imagen-3.0-generate-001", + modelId, image, "x2", UpscaleImageConfig.builder().outputMimeType("image/jpeg").build()); From a6bfe36843bed1575a03c86a092a17b35e48fd9f Mon Sep 17 00:00:00 2001 From: Ayush Agrawal Date: Wed, 18 Jun 2025 14:17:14 -0700 Subject: [PATCH 021/602] docs: fix small typo in comments PiperOrigin-RevId: 773060196 --- .../java/com/google/genai/examples/CachedContentOperations.java | 2 +- .../com/google/genai/examples/CachedContentOperationsAsync.java | 2 +- .../java/com/google/genai/examples/ChatWithFunctionCall.java | 2 +- .../main/java/com/google/genai/examples/ChatWithHistory.java | 2 +- .../java/com/google/genai/examples/ChatWithHistoryAsync.java | 2 +- .../google/genai/examples/ChatWithHistoryAsyncStreaming.java | 2 +- .../com/google/genai/examples/ChatWithHistoryStreaming.java | 2 +- .../src/main/java/com/google/genai/examples/ComputeTokens.java | 2 +- .../src/main/java/com/google/genai/examples/CountTokens.java | 2 +- .../java/com/google/genai/examples/CountTokensWithConfigs.java | 2 +- .../src/main/java/com/google/genai/examples/EditImageAsync.java | 2 +- .../com/google/genai/examples/EditImageControlReference.java | 2 +- .../java/com/google/genai/examples/EditImageMaskReference.java | 2 +- .../java/com/google/genai/examples/EditImageStyleTransfer.java | 2 +- .../com/google/genai/examples/EditImageSubjectReference.java | 2 +- .../src/main/java/com/google/genai/examples/EmbedContent.java | 2 +- .../main/java/com/google/genai/examples/EmbedContentAsync.java | 2 +- .../java/com/google/genai/examples/EmbedContentWithConfig.java | 2 +- .../src/main/java/com/google/genai/examples/FileOperations.java | 2 +- .../java/com/google/genai/examples/FileOperationsAsync.java | 2 +- .../main/java/com/google/genai/examples/GenerateContent.java | 2 +- .../java/com/google/genai/examples/GenerateContentAsync.java | 2 +- .../java/com/google/genai/examples/GenerateContentStream.java | 2 +- .../com/google/genai/examples/GenerateContentWithConfigs.java | 2 +- .../google/genai/examples/GenerateContentWithFunctionCall.java | 2 +- .../google/genai/examples/GenerateContentWithImageInput.java | 2 +- .../genai/examples/GenerateContentWithResponseModality.java | 2 +- .../genai/examples/GenerateContentWithResponseSchema.java | 2 +- .../src/main/java/com/google/genai/examples/GenerateImages.java | 2 +- .../java/com/google/genai/examples/GenerateImagesAsync.java | 2 +- .../src/main/java/com/google/genai/examples/GenerateVideos.java | 2 +- .../java/com/google/genai/examples/GenerateVideosAsync.java | 2 +- .../com/google/genai/examples/LiveAudioConversationAsync.java | 2 +- .../genai/examples/LiveTextContextWindowCompressionAsync.java | 2 +- .../com/google/genai/examples/LiveTextConversationAsync.java | 2 +- .../genai/examples/LiveTextConversationResumptionAsync.java | 2 +- .../genai/examples/LiveTextToAudioTranscriptionAsync.java | 2 +- .../google/genai/examples/LiveTextToTextGenerationAsync.java | 2 +- .../main/java/com/google/genai/examples/ModelManagement.java | 2 +- .../java/com/google/genai/examples/ModelManagementAsync.java | 2 +- .../java/com/google/genai/examples/RequestLevelHttpOptions.java | 2 +- .../src/main/java/com/google/genai/examples/UpscaleImage.java | 2 +- .../main/java/com/google/genai/examples/UpscaleImageAsync.java | 2 +- 43 files changed, 43 insertions(+), 43 deletions(-) diff --git a/examples/src/main/java/com/google/genai/examples/CachedContentOperations.java b/examples/src/main/java/com/google/genai/examples/CachedContentOperations.java index ceec0eb0579..f5711c6f105 100644 --- a/examples/src/main/java/com/google/genai/examples/CachedContentOperations.java +++ b/examples/src/main/java/com/google/genai/examples/CachedContentOperations.java @@ -28,7 +28,7 @@ * *

export GOOGLE_GENAI_USE_VERTEXAI=true * - *

1b. If you are using Gemini Developer AI, set an API key environment variable. You can find a + *

1b. If you are using Gemini Developer API, set an API key environment variable. You can find a * list of available API keys here: https://aistudio.google.com/app/apikey * *

export GOOGLE_API_KEY=YOUR_API_KEY diff --git a/examples/src/main/java/com/google/genai/examples/CachedContentOperationsAsync.java b/examples/src/main/java/com/google/genai/examples/CachedContentOperationsAsync.java index 6e5f12e801f..223c927a64a 100644 --- a/examples/src/main/java/com/google/genai/examples/CachedContentOperationsAsync.java +++ b/examples/src/main/java/com/google/genai/examples/CachedContentOperationsAsync.java @@ -28,7 +28,7 @@ * *

export GOOGLE_GENAI_USE_VERTEXAI=true * - *

1b. If you are using Gemini Developer AI, set an API key environment variable. You can find a + *

1b. If you are using Gemini Developer API, set an API key environment variable. You can find a * list of available API keys here: https://aistudio.google.com/app/apikey * *

export GOOGLE_API_KEY=YOUR_API_KEY diff --git a/examples/src/main/java/com/google/genai/examples/ChatWithFunctionCall.java b/examples/src/main/java/com/google/genai/examples/ChatWithFunctionCall.java index 19cf8980c79..584a4c1e76a 100644 --- a/examples/src/main/java/com/google/genai/examples/ChatWithFunctionCall.java +++ b/examples/src/main/java/com/google/genai/examples/ChatWithFunctionCall.java @@ -28,7 +28,7 @@ * *

export GOOGLE_GENAI_USE_VERTEXAI=true * - *

1b. If you are using Gemini Developer AI, set an API key environment variable. You can find a + *

1b. If you are using Gemini Developer API, set an API key environment variable. You can find a * list of available API keys here: https://aistudio.google.com/app/apikey * *

export GOOGLE_API_KEY=YOUR_API_KEY diff --git a/examples/src/main/java/com/google/genai/examples/ChatWithHistory.java b/examples/src/main/java/com/google/genai/examples/ChatWithHistory.java index 0d009e72ea8..83a2b4b8af0 100644 --- a/examples/src/main/java/com/google/genai/examples/ChatWithHistory.java +++ b/examples/src/main/java/com/google/genai/examples/ChatWithHistory.java @@ -28,7 +28,7 @@ * *

export GOOGLE_GENAI_USE_VERTEXAI=true * - *

1b. If you are using Gemini Developer AI, set an API key environment variable. You can find a + *

1b. If you are using Gemini Developer API, set an API key environment variable. You can find a * list of available API keys here: https://aistudio.google.com/app/apikey * *

export GOOGLE_API_KEY=YOUR_API_KEY diff --git a/examples/src/main/java/com/google/genai/examples/ChatWithHistoryAsync.java b/examples/src/main/java/com/google/genai/examples/ChatWithHistoryAsync.java index d86ad512351..aa9da312e55 100644 --- a/examples/src/main/java/com/google/genai/examples/ChatWithHistoryAsync.java +++ b/examples/src/main/java/com/google/genai/examples/ChatWithHistoryAsync.java @@ -28,7 +28,7 @@ * *

export GOOGLE_GENAI_USE_VERTEXAI=true * - *

1b. If you are using Gemini Developer AI, set an API key environment variable. You can find a + *

1b. If you are using Gemini Developer API, set an API key environment variable. You can find a * list of available API keys here: https://aistudio.google.com/app/apikey * *

export GOOGLE_API_KEY=YOUR_API_KEY diff --git a/examples/src/main/java/com/google/genai/examples/ChatWithHistoryAsyncStreaming.java b/examples/src/main/java/com/google/genai/examples/ChatWithHistoryAsyncStreaming.java index 0a541b2164b..89112f774fb 100644 --- a/examples/src/main/java/com/google/genai/examples/ChatWithHistoryAsyncStreaming.java +++ b/examples/src/main/java/com/google/genai/examples/ChatWithHistoryAsyncStreaming.java @@ -28,7 +28,7 @@ * *

export GOOGLE_GENAI_USE_VERTEXAI=true * - *

1b. If you are using Gemini Developer AI, set an API key environment variable. You can find a + *

1b. If you are using Gemini Developer API, set an API key environment variable. You can find a * list of available API keys here: https://aistudio.google.com/app/apikey * *

export GOOGLE_API_KEY=YOUR_API_KEY diff --git a/examples/src/main/java/com/google/genai/examples/ChatWithHistoryStreaming.java b/examples/src/main/java/com/google/genai/examples/ChatWithHistoryStreaming.java index 4ede79a155d..c7c69e7c40b 100644 --- a/examples/src/main/java/com/google/genai/examples/ChatWithHistoryStreaming.java +++ b/examples/src/main/java/com/google/genai/examples/ChatWithHistoryStreaming.java @@ -28,7 +28,7 @@ * *

export GOOGLE_GENAI_USE_VERTEXAI=true * - *

1b. If you are using Gemini Developer AI, set an API key environment variable. You can find a + *

1b. If you are using Gemini Developer API, set an API key environment variable. You can find a * list of available API keys here: https://aistudio.google.com/app/apikey * *

export GOOGLE_API_KEY=YOUR_API_KEY diff --git a/examples/src/main/java/com/google/genai/examples/ComputeTokens.java b/examples/src/main/java/com/google/genai/examples/ComputeTokens.java index e049b1147aa..38b2d373026 100644 --- a/examples/src/main/java/com/google/genai/examples/ComputeTokens.java +++ b/examples/src/main/java/com/google/genai/examples/ComputeTokens.java @@ -28,7 +28,7 @@ * *

export GOOGLE_GENAI_USE_VERTEXAI=true * - *

1b. If you are using Gemini Developer AI, set an API key environment variable. You can find a + *

1b. If you are using Gemini Developer API, set an API key environment variable. You can find a * list of available API keys here: https://aistudio.google.com/app/apikey * *

export GOOGLE_API_KEY=YOUR_API_KEY diff --git a/examples/src/main/java/com/google/genai/examples/CountTokens.java b/examples/src/main/java/com/google/genai/examples/CountTokens.java index 3ae834f6ed0..5a6cfa28bb5 100644 --- a/examples/src/main/java/com/google/genai/examples/CountTokens.java +++ b/examples/src/main/java/com/google/genai/examples/CountTokens.java @@ -28,7 +28,7 @@ * *

export GOOGLE_GENAI_USE_VERTEXAI=true * - *

1b. If you are using Gemini Developer AI, set an API key environment variable. You can find a + *

1b. If you are using Gemini Developer API, set an API key environment variable. You can find a * list of available API keys here: https://aistudio.google.com/app/apikey * *

export GOOGLE_API_KEY=YOUR_API_KEY diff --git a/examples/src/main/java/com/google/genai/examples/CountTokensWithConfigs.java b/examples/src/main/java/com/google/genai/examples/CountTokensWithConfigs.java index f0724eb5fdb..770dbcbcbcd 100644 --- a/examples/src/main/java/com/google/genai/examples/CountTokensWithConfigs.java +++ b/examples/src/main/java/com/google/genai/examples/CountTokensWithConfigs.java @@ -28,7 +28,7 @@ * *

export GOOGLE_GENAI_USE_VERTEXAI=true * - *

1b. If you are using Gemini Developer AI, set an API key environment variable. You can find a + *

1b. If you are using Gemini Developer API, set an API key environment variable. You can find a * list of available API keys here: https://aistudio.google.com/app/apikey * *

export GOOGLE_API_KEY=YOUR_API_KEY diff --git a/examples/src/main/java/com/google/genai/examples/EditImageAsync.java b/examples/src/main/java/com/google/genai/examples/EditImageAsync.java index 7b0343409ee..81163a3937c 100644 --- a/examples/src/main/java/com/google/genai/examples/EditImageAsync.java +++ b/examples/src/main/java/com/google/genai/examples/EditImageAsync.java @@ -28,7 +28,7 @@ * *

export GOOGLE_GENAI_USE_VERTEXAI=true * - *

1b. If you are using Gemini Developer AI, set an API key environment variable. You can find a + *

1b. If you are using Gemini Developer API, set an API key environment variable. You can find a * list of available API keys here: https://aistudio.google.com/app/apikey * *

export GOOGLE_API_KEY=YOUR_API_KEY diff --git a/examples/src/main/java/com/google/genai/examples/EditImageControlReference.java b/examples/src/main/java/com/google/genai/examples/EditImageControlReference.java index e1b0757460b..7955580d4c4 100644 --- a/examples/src/main/java/com/google/genai/examples/EditImageControlReference.java +++ b/examples/src/main/java/com/google/genai/examples/EditImageControlReference.java @@ -28,7 +28,7 @@ * *

export GOOGLE_GENAI_USE_VERTEXAI=true * - *

1b. If you are using Gemini Developer AI, set an API key environment variable. You can find a + *

1b. If you are using Gemini Developer API, set an API key environment variable. You can find a * list of available API keys here: https://aistudio.google.com/app/apikey * *

export GOOGLE_API_KEY=YOUR_API_KEY diff --git a/examples/src/main/java/com/google/genai/examples/EditImageMaskReference.java b/examples/src/main/java/com/google/genai/examples/EditImageMaskReference.java index 1403b7af180..3b832a4ff60 100644 --- a/examples/src/main/java/com/google/genai/examples/EditImageMaskReference.java +++ b/examples/src/main/java/com/google/genai/examples/EditImageMaskReference.java @@ -28,7 +28,7 @@ * *

export GOOGLE_GENAI_USE_VERTEXAI=true * - *

1b. If you are using Gemini Developer AI, set an API key environment variable. You can find a + *

1b. If you are using Gemini Developer API, set an API key environment variable. You can find a * list of available API keys here: https://aistudio.google.com/app/apikey * *

export GOOGLE_API_KEY=YOUR_API_KEY diff --git a/examples/src/main/java/com/google/genai/examples/EditImageStyleTransfer.java b/examples/src/main/java/com/google/genai/examples/EditImageStyleTransfer.java index 98ca3d2b49f..021e5702495 100644 --- a/examples/src/main/java/com/google/genai/examples/EditImageStyleTransfer.java +++ b/examples/src/main/java/com/google/genai/examples/EditImageStyleTransfer.java @@ -28,7 +28,7 @@ * *

export GOOGLE_GENAI_USE_VERTEXAI=true * - *

1b. If you are using Gemini Developer AI, set an API key environment variable. You can find a + *

1b. If you are using Gemini Developer API, set an API key environment variable. You can find a * list of available API keys here: https://aistudio.google.com/app/apikey * *

export GOOGLE_API_KEY=YOUR_API_KEY diff --git a/examples/src/main/java/com/google/genai/examples/EditImageSubjectReference.java b/examples/src/main/java/com/google/genai/examples/EditImageSubjectReference.java index d6e074b5cdf..897dcc85635 100644 --- a/examples/src/main/java/com/google/genai/examples/EditImageSubjectReference.java +++ b/examples/src/main/java/com/google/genai/examples/EditImageSubjectReference.java @@ -28,7 +28,7 @@ * *

export GOOGLE_GENAI_USE_VERTEXAI=true * - *

1b. If you are using Gemini Developer AI, set an API key environment variable. You can find a + *

1b. If you are using Gemini Developer API, set an API key environment variable. You can find a * list of available API keys here: https://aistudio.google.com/app/apikey * *

export GOOGLE_API_KEY=YOUR_API_KEY diff --git a/examples/src/main/java/com/google/genai/examples/EmbedContent.java b/examples/src/main/java/com/google/genai/examples/EmbedContent.java index f8ba861ca1e..2886f90929a 100644 --- a/examples/src/main/java/com/google/genai/examples/EmbedContent.java +++ b/examples/src/main/java/com/google/genai/examples/EmbedContent.java @@ -28,7 +28,7 @@ * *

export GOOGLE_GENAI_USE_VERTEXAI=true * - *

1b. If you are using Gemini Developer AI, set an API key environment variable. You can find a + *

1b. If you are using Gemini Developer API, set an API key environment variable. You can find a * list of available API keys here: https://aistudio.google.com/app/apikey * *

export GOOGLE_API_KEY=YOUR_API_KEY diff --git a/examples/src/main/java/com/google/genai/examples/EmbedContentAsync.java b/examples/src/main/java/com/google/genai/examples/EmbedContentAsync.java index 4a54506569f..538f017c19a 100644 --- a/examples/src/main/java/com/google/genai/examples/EmbedContentAsync.java +++ b/examples/src/main/java/com/google/genai/examples/EmbedContentAsync.java @@ -28,7 +28,7 @@ * *

export GOOGLE_GENAI_USE_VERTEXAI=true * - *

1b. If you are using Gemini Developer AI, set an API key environment variable. You can find a + *

1b. If you are using Gemini Developer API, set an API key environment variable. You can find a * list of available API keys here: https://aistudio.google.com/app/apikey * *

export GOOGLE_API_KEY=YOUR_API_KEY diff --git a/examples/src/main/java/com/google/genai/examples/EmbedContentWithConfig.java b/examples/src/main/java/com/google/genai/examples/EmbedContentWithConfig.java index 7adbc9e42f4..1ffbd18f123 100644 --- a/examples/src/main/java/com/google/genai/examples/EmbedContentWithConfig.java +++ b/examples/src/main/java/com/google/genai/examples/EmbedContentWithConfig.java @@ -28,7 +28,7 @@ * *

export GOOGLE_GENAI_USE_VERTEXAI=true * - *

1b. If you are using Gemini Developer AI, set an API key environment variable. You can find a + *

1b. If you are using Gemini Developer API, set an API key environment variable. You can find a * list of available API keys here: https://aistudio.google.com/app/apikey * *

export GOOGLE_API_KEY=YOUR_API_KEY diff --git a/examples/src/main/java/com/google/genai/examples/FileOperations.java b/examples/src/main/java/com/google/genai/examples/FileOperations.java index 4d1dd4c5f06..3dc7eae5771 100644 --- a/examples/src/main/java/com/google/genai/examples/FileOperations.java +++ b/examples/src/main/java/com/google/genai/examples/FileOperations.java @@ -28,7 +28,7 @@ * *

export GOOGLE_GENAI_USE_VERTEXAI=true * - *

1b. If you are using Gemini Developer AI, set an API key environment variable. You can find a + *

1b. If you are using Gemini Developer API, set an API key environment variable. You can find a * list of available API keys here: https://aistudio.google.com/app/apikey * *

export GOOGLE_API_KEY=YOUR_API_KEY diff --git a/examples/src/main/java/com/google/genai/examples/FileOperationsAsync.java b/examples/src/main/java/com/google/genai/examples/FileOperationsAsync.java index 9d0384c1861..6fc53aba435 100644 --- a/examples/src/main/java/com/google/genai/examples/FileOperationsAsync.java +++ b/examples/src/main/java/com/google/genai/examples/FileOperationsAsync.java @@ -28,7 +28,7 @@ * *

export GOOGLE_GENAI_USE_VERTEXAI=true * - *

1b. If you are using Gemini Developer AI, set an API key environment variable. You can find a + *

1b. If you are using Gemini Developer API, set an API key environment variable. You can find a * list of available API keys here: https://aistudio.google.com/app/apikey * *

export GOOGLE_API_KEY=YOUR_API_KEY diff --git a/examples/src/main/java/com/google/genai/examples/GenerateContent.java b/examples/src/main/java/com/google/genai/examples/GenerateContent.java index b2408e1f533..6bc8f357c87 100644 --- a/examples/src/main/java/com/google/genai/examples/GenerateContent.java +++ b/examples/src/main/java/com/google/genai/examples/GenerateContent.java @@ -28,7 +28,7 @@ * *

export GOOGLE_GENAI_USE_VERTEXAI=true * - *

1b. If you are using Gemini Developer AI, set an API key environment variable. You can find a + *

1b. If you are using Gemini Developer API, set an API key environment variable. You can find a * list of available API keys here: https://aistudio.google.com/app/apikey * *

export GOOGLE_API_KEY=YOUR_API_KEY diff --git a/examples/src/main/java/com/google/genai/examples/GenerateContentAsync.java b/examples/src/main/java/com/google/genai/examples/GenerateContentAsync.java index 49db5cd6e78..3915a3cf4d2 100644 --- a/examples/src/main/java/com/google/genai/examples/GenerateContentAsync.java +++ b/examples/src/main/java/com/google/genai/examples/GenerateContentAsync.java @@ -28,7 +28,7 @@ * *

export GOOGLE_GENAI_USE_VERTEXAI=true * - *

1b. If you are using Gemini Developer AI, set an API key environment variable. You can find a + *

1b. If you are using Gemini Developer API, set an API key environment variable. You can find a * list of available API keys here: https://aistudio.google.com/app/apikey * *

export GOOGLE_API_KEY=YOUR_API_KEY diff --git a/examples/src/main/java/com/google/genai/examples/GenerateContentStream.java b/examples/src/main/java/com/google/genai/examples/GenerateContentStream.java index e17c8cbedf1..da242a2924a 100644 --- a/examples/src/main/java/com/google/genai/examples/GenerateContentStream.java +++ b/examples/src/main/java/com/google/genai/examples/GenerateContentStream.java @@ -28,7 +28,7 @@ * *

export GOOGLE_GENAI_USE_VERTEXAI=true * - *

1b. If you are using Gemini Developer AI, set an API key environment variable. You can find a + *

1b. If you are using Gemini Developer API, set an API key environment variable. You can find a * list of available API keys here: https://aistudio.google.com/app/apikey * *

export GOOGLE_API_KEY=YOUR_API_KEY diff --git a/examples/src/main/java/com/google/genai/examples/GenerateContentWithConfigs.java b/examples/src/main/java/com/google/genai/examples/GenerateContentWithConfigs.java index 1366cfeb44a..38833c0de22 100644 --- a/examples/src/main/java/com/google/genai/examples/GenerateContentWithConfigs.java +++ b/examples/src/main/java/com/google/genai/examples/GenerateContentWithConfigs.java @@ -28,7 +28,7 @@ * *

export GOOGLE_GENAI_USE_VERTEXAI=true * - *

1b. If you are using Gemini Developer AI, set an API key environment variable. You can find a + *

1b. If you are using Gemini Developer API, set an API key environment variable. You can find a * list of available API keys here: https://aistudio.google.com/app/apikey * *

export GOOGLE_API_KEY=YOUR_API_KEY diff --git a/examples/src/main/java/com/google/genai/examples/GenerateContentWithFunctionCall.java b/examples/src/main/java/com/google/genai/examples/GenerateContentWithFunctionCall.java index bd4b5f5aaf9..dc6d4b3e7d4 100644 --- a/examples/src/main/java/com/google/genai/examples/GenerateContentWithFunctionCall.java +++ b/examples/src/main/java/com/google/genai/examples/GenerateContentWithFunctionCall.java @@ -28,7 +28,7 @@ * *

export GOOGLE_GENAI_USE_VERTEXAI=true * - *

1b. If you are using Gemini Developer AI, set an API key environment variable. You can find a + *

1b. If you are using Gemini Developer API, set an API key environment variable. You can find a * list of available API keys here: https://aistudio.google.com/app/apikey * *

export GOOGLE_API_KEY=YOUR_API_KEY diff --git a/examples/src/main/java/com/google/genai/examples/GenerateContentWithImageInput.java b/examples/src/main/java/com/google/genai/examples/GenerateContentWithImageInput.java index cba08750659..997737cb60d 100644 --- a/examples/src/main/java/com/google/genai/examples/GenerateContentWithImageInput.java +++ b/examples/src/main/java/com/google/genai/examples/GenerateContentWithImageInput.java @@ -28,7 +28,7 @@ * *

export GOOGLE_GENAI_USE_VERTEXAI=true * - *

1b. If you are using Gemini Developer AI, set an API key environment variable. You can find a + *

1b. If you are using Gemini Developer API, set an API key environment variable. You can find a * list of available API keys here: https://aistudio.google.com/app/apikey * *

export GOOGLE_API_KEY=YOUR_API_KEY diff --git a/examples/src/main/java/com/google/genai/examples/GenerateContentWithResponseModality.java b/examples/src/main/java/com/google/genai/examples/GenerateContentWithResponseModality.java index 2a7c0c37d48..c6422966202 100644 --- a/examples/src/main/java/com/google/genai/examples/GenerateContentWithResponseModality.java +++ b/examples/src/main/java/com/google/genai/examples/GenerateContentWithResponseModality.java @@ -28,7 +28,7 @@ * *

export GOOGLE_GENAI_USE_VERTEXAI=true * - *

1b. If you are using Gemini Developer AI, set an API key environment variable. You can find a + *

1b. If you are using Gemini Developer API, set an API key environment variable. You can find a * list of available API keys here: https://aistudio.google.com/app/apikey * *

export GOOGLE_API_KEY=YOUR_API_KEY diff --git a/examples/src/main/java/com/google/genai/examples/GenerateContentWithResponseSchema.java b/examples/src/main/java/com/google/genai/examples/GenerateContentWithResponseSchema.java index 0407244cc25..ce9e53e41e4 100644 --- a/examples/src/main/java/com/google/genai/examples/GenerateContentWithResponseSchema.java +++ b/examples/src/main/java/com/google/genai/examples/GenerateContentWithResponseSchema.java @@ -28,7 +28,7 @@ * *

export GOOGLE_GENAI_USE_VERTEXAI=true * - *

1b. If you are using Gemini Developer AI, set an API key environment variable. You can find a + *

1b. If you are using Gemini Developer API, set an API key environment variable. You can find a * list of available API keys here: https://aistudio.google.com/app/apikey * *

export GOOGLE_API_KEY=YOUR_API_KEY diff --git a/examples/src/main/java/com/google/genai/examples/GenerateImages.java b/examples/src/main/java/com/google/genai/examples/GenerateImages.java index 4b6cfb2230b..c146985827e 100644 --- a/examples/src/main/java/com/google/genai/examples/GenerateImages.java +++ b/examples/src/main/java/com/google/genai/examples/GenerateImages.java @@ -28,7 +28,7 @@ * *

export GOOGLE_GENAI_USE_VERTEXAI=true * - *

1b. If you are using Gemini Developer AI, set an API key environment variable. You can find a + *

1b. If you are using Gemini Developer API, set an API key environment variable. You can find a * list of available API keys here: https://aistudio.google.com/app/apikey * *

export GOOGLE_API_KEY=YOUR_API_KEY diff --git a/examples/src/main/java/com/google/genai/examples/GenerateImagesAsync.java b/examples/src/main/java/com/google/genai/examples/GenerateImagesAsync.java index 94f9d570a8e..b9ceb3bcc43 100644 --- a/examples/src/main/java/com/google/genai/examples/GenerateImagesAsync.java +++ b/examples/src/main/java/com/google/genai/examples/GenerateImagesAsync.java @@ -28,7 +28,7 @@ * *

export GOOGLE_GENAI_USE_VERTEXAI=true * - *

1b. If you are using Gemini Developer AI, set an API key environment variable. You can find a + *

1b. If you are using Gemini Developer API, set an API key environment variable. You can find a * list of available API keys here: https://aistudio.google.com/app/apikey * *

export GOOGLE_API_KEY=YOUR_API_KEY diff --git a/examples/src/main/java/com/google/genai/examples/GenerateVideos.java b/examples/src/main/java/com/google/genai/examples/GenerateVideos.java index 95b1933f9af..690ee862abd 100644 --- a/examples/src/main/java/com/google/genai/examples/GenerateVideos.java +++ b/examples/src/main/java/com/google/genai/examples/GenerateVideos.java @@ -28,7 +28,7 @@ * *

export GOOGLE_GENAI_USE_VERTEXAI=true * - *

1b. If you are using Gemini Developer AI, set an API key environment variable. You can find a + *

1b. If you are using Gemini Developer API, set an API key environment variable. You can find a * list of available API keys here: https://aistudio.google.com/app/apikey * *

export GOOGLE_API_KEY=YOUR_API_KEY diff --git a/examples/src/main/java/com/google/genai/examples/GenerateVideosAsync.java b/examples/src/main/java/com/google/genai/examples/GenerateVideosAsync.java index 03a9e7d8687..5f97af5c0d3 100644 --- a/examples/src/main/java/com/google/genai/examples/GenerateVideosAsync.java +++ b/examples/src/main/java/com/google/genai/examples/GenerateVideosAsync.java @@ -28,7 +28,7 @@ * *

export GOOGLE_GENAI_USE_VERTEXAI=true * - *

1b. If you are using Gemini Developer AI, set an API key environment variable. You can find a + *

1b. If you are using Gemini Developer API, set an API key environment variable. You can find a * list of available API keys here: https://aistudio.google.com/app/apikey * *

export GOOGLE_API_KEY=YOUR_API_KEY diff --git a/examples/src/main/java/com/google/genai/examples/LiveAudioConversationAsync.java b/examples/src/main/java/com/google/genai/examples/LiveAudioConversationAsync.java index 2ee11b79691..53c4fb4fab1 100644 --- a/examples/src/main/java/com/google/genai/examples/LiveAudioConversationAsync.java +++ b/examples/src/main/java/com/google/genai/examples/LiveAudioConversationAsync.java @@ -28,7 +28,7 @@ * *

export GOOGLE_GENAI_USE_VERTEXAI=true * - *

1b. If you are using Gemini Developer AI, set an API key environment variable. You can find a + *

1b. If you are using Gemini Developer API, set an API key environment variable. You can find a * list of available API keys here: https://aistudio.google.com/app/apikey * *

export GOOGLE_API_KEY=YOUR_API_KEY diff --git a/examples/src/main/java/com/google/genai/examples/LiveTextContextWindowCompressionAsync.java b/examples/src/main/java/com/google/genai/examples/LiveTextContextWindowCompressionAsync.java index fa7f13f02e6..bb6db83ecfa 100644 --- a/examples/src/main/java/com/google/genai/examples/LiveTextContextWindowCompressionAsync.java +++ b/examples/src/main/java/com/google/genai/examples/LiveTextContextWindowCompressionAsync.java @@ -28,7 +28,7 @@ * *

export GOOGLE_GENAI_USE_VERTEXAI=true * - *

1b. If you are using Gemini Developer AI, set an API key environment variable. You can find a + *

1b. If you are using Gemini Developer API, set an API key environment variable. You can find a * list of available API keys here: https://aistudio.google.com/app/apikey * *

export GOOGLE_API_KEY=YOUR_API_KEY diff --git a/examples/src/main/java/com/google/genai/examples/LiveTextConversationAsync.java b/examples/src/main/java/com/google/genai/examples/LiveTextConversationAsync.java index 5fa3dd3cb81..d3c57c75af5 100644 --- a/examples/src/main/java/com/google/genai/examples/LiveTextConversationAsync.java +++ b/examples/src/main/java/com/google/genai/examples/LiveTextConversationAsync.java @@ -28,7 +28,7 @@ * *

export GOOGLE_GENAI_USE_VERTEXAI=true * - *

1b. If you are using Gemini Developer AI, set an API key environment variable. You can find a + *

1b. If you are using Gemini Developer API, set an API key environment variable. You can find a * list of available API keys here: https://aistudio.google.com/app/apikey * *

export GOOGLE_API_KEY=YOUR_API_KEY diff --git a/examples/src/main/java/com/google/genai/examples/LiveTextConversationResumptionAsync.java b/examples/src/main/java/com/google/genai/examples/LiveTextConversationResumptionAsync.java index eb22da47ea6..ad706e0fb67 100644 --- a/examples/src/main/java/com/google/genai/examples/LiveTextConversationResumptionAsync.java +++ b/examples/src/main/java/com/google/genai/examples/LiveTextConversationResumptionAsync.java @@ -28,7 +28,7 @@ * *

export GOOGLE_GENAI_USE_VERTEXAI=true * - *

1b. If you are using Gemini Developer AI, set an API key environment variable. You can find a + *

1b. If you are using Gemini Developer API, set an API key environment variable. You can find a * list of available API keys here: https://aistudio.google.com/app/apikey * *

export GOOGLE_API_KEY=YOUR_API_KEY diff --git a/examples/src/main/java/com/google/genai/examples/LiveTextToAudioTranscriptionAsync.java b/examples/src/main/java/com/google/genai/examples/LiveTextToAudioTranscriptionAsync.java index 9fa79bb7dda..b9fb9360bc0 100644 --- a/examples/src/main/java/com/google/genai/examples/LiveTextToAudioTranscriptionAsync.java +++ b/examples/src/main/java/com/google/genai/examples/LiveTextToAudioTranscriptionAsync.java @@ -28,7 +28,7 @@ * *

export GOOGLE_GENAI_USE_VERTEXAI=true * - *

1b. If you are using Gemini Developer AI, set an API key environment variable. You can find a + *

1b. If you are using Gemini Developer API, set an API key environment variable. You can find a * list of available API keys here: https://aistudio.google.com/app/apikey * *

export GOOGLE_API_KEY=YOUR_API_KEY diff --git a/examples/src/main/java/com/google/genai/examples/LiveTextToTextGenerationAsync.java b/examples/src/main/java/com/google/genai/examples/LiveTextToTextGenerationAsync.java index 46bb125210e..bc0a84676e8 100644 --- a/examples/src/main/java/com/google/genai/examples/LiveTextToTextGenerationAsync.java +++ b/examples/src/main/java/com/google/genai/examples/LiveTextToTextGenerationAsync.java @@ -28,7 +28,7 @@ * *

export GOOGLE_GENAI_USE_VERTEXAI=true * - *

1b. If you are using Gemini Developer AI, set an API key environment variable. You can find a + *

1b. If you are using Gemini Developer API, set an API key environment variable. You can find a * list of available API keys here: https://aistudio.google.com/app/apikey * *

export GOOGLE_API_KEY=YOUR_API_KEY diff --git a/examples/src/main/java/com/google/genai/examples/ModelManagement.java b/examples/src/main/java/com/google/genai/examples/ModelManagement.java index d10595fd45c..f6652492d88 100644 --- a/examples/src/main/java/com/google/genai/examples/ModelManagement.java +++ b/examples/src/main/java/com/google/genai/examples/ModelManagement.java @@ -28,7 +28,7 @@ * *

export GOOGLE_GENAI_USE_VERTEXAI=true * - *

1b. If you are using Gemini Developer AI, set an API key environment variable. You can find a + *

1b. If you are using Gemini Developer API, set an API key environment variable. You can find a * list of available API keys here: https://aistudio.google.com/app/apikey * *

export GOOGLE_API_KEY=YOUR_API_KEY diff --git a/examples/src/main/java/com/google/genai/examples/ModelManagementAsync.java b/examples/src/main/java/com/google/genai/examples/ModelManagementAsync.java index 08965e3cdd9..58829301c54 100644 --- a/examples/src/main/java/com/google/genai/examples/ModelManagementAsync.java +++ b/examples/src/main/java/com/google/genai/examples/ModelManagementAsync.java @@ -28,7 +28,7 @@ * *

export GOOGLE_GENAI_USE_VERTEXAI=true * - *

1b. If you are using Gemini Developer AI, set an API key environment variable. You can find a + *

1b. If you are using Gemini Developer API, set an API key environment variable. You can find a * list of available API keys here: https://aistudio.google.com/app/apikey * *

export GOOGLE_API_KEY=YOUR_API_KEY diff --git a/examples/src/main/java/com/google/genai/examples/RequestLevelHttpOptions.java b/examples/src/main/java/com/google/genai/examples/RequestLevelHttpOptions.java index 99b3a4f3dca..5ba7dd1e712 100644 --- a/examples/src/main/java/com/google/genai/examples/RequestLevelHttpOptions.java +++ b/examples/src/main/java/com/google/genai/examples/RequestLevelHttpOptions.java @@ -28,7 +28,7 @@ * *

export GOOGLE_GENAI_USE_VERTEXAI=true * - *

1b. If you are using Gemini Developer AI, set an API key environment variable. You can find a + *

1b. If you are using Gemini Developer API, set an API key environment variable. You can find a * list of available API keys here: https://aistudio.google.com/app/apikey * *

export GOOGLE_API_KEY=YOUR_API_KEY diff --git a/examples/src/main/java/com/google/genai/examples/UpscaleImage.java b/examples/src/main/java/com/google/genai/examples/UpscaleImage.java index 73a8f404021..4df5e6f3206 100644 --- a/examples/src/main/java/com/google/genai/examples/UpscaleImage.java +++ b/examples/src/main/java/com/google/genai/examples/UpscaleImage.java @@ -28,7 +28,7 @@ * *

export GOOGLE_GENAI_USE_VERTEXAI=true * - *

1b. If you are using Gemini Developer AI, set an API key environment variable. You can find a + *

1b. If you are using Gemini Developer API, set an API key environment variable. You can find a * list of available API keys here: https://aistudio.google.com/app/apikey * *

export GOOGLE_API_KEY=YOUR_API_KEY diff --git a/examples/src/main/java/com/google/genai/examples/UpscaleImageAsync.java b/examples/src/main/java/com/google/genai/examples/UpscaleImageAsync.java index bd516658c96..0f7e136bf3b 100644 --- a/examples/src/main/java/com/google/genai/examples/UpscaleImageAsync.java +++ b/examples/src/main/java/com/google/genai/examples/UpscaleImageAsync.java @@ -28,7 +28,7 @@ * *

export GOOGLE_GENAI_USE_VERTEXAI=true * - *

1b. If you are using Gemini Developer AI, set an API key environment variable. You can find a + *

1b. If you are using Gemini Developer API, set an API key environment variable. You can find a * list of available API keys here: https://aistudio.google.com/app/apikey * *

export GOOGLE_API_KEY=YOUR_API_KEY From aa718657f53f4bd9132a9b00816e7f5581108dec Mon Sep 17 00:00:00 2001 From: Ayush Agrawal Date: Wed, 18 Jun 2025 17:11:56 -0700 Subject: [PATCH 022/602] feat: resolve deep conditional nesting in Live API examples for better readability. PiperOrigin-RevId: 773120186 --- .../examples/LiveAudioConversationAsync.java | 34 ++++++------ ...LiveTextContextWindowCompressionAsync.java | 33 ++++++----- .../examples/LiveTextConversationAsync.java | 24 +++----- .../LiveTextConversationResumptionAsync.java | 13 ++--- .../LiveTextToAudioTranscriptionAsync.java | 55 ++++++++----------- .../LiveTextToTextGenerationAsync.java | 23 +++----- 6 files changed, 77 insertions(+), 105 deletions(-) diff --git a/examples/src/main/java/com/google/genai/examples/LiveAudioConversationAsync.java b/examples/src/main/java/com/google/genai/examples/LiveAudioConversationAsync.java index 53c4fb4fab1..f54f9ef7390 100644 --- a/examples/src/main/java/com/google/genai/examples/LiveAudioConversationAsync.java +++ b/examples/src/main/java/com/google/genai/examples/LiveAudioConversationAsync.java @@ -57,6 +57,8 @@ import com.google.genai.types.PrebuiltVoiceConfig; import com.google.genai.types.SpeechConfig; import com.google.genai.types.VoiceConfig; +import java.util.Collection; +import java.util.Optional; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; @@ -301,28 +303,24 @@ public static void handleAudioResponse(LiveServerMessage message) { .ifPresent( content -> { if (content.turnComplete().orElse(false)) { - // when interrupted, Gemini sends a turn_compete with - // Stop the speaker if the turn is complete + // When interrupted, Gemini sends a turn_complete. + // Stop the speaker if the turn is complete. if (speakerLine != null && speakerLine.isOpen()) { speakerLine.flush(); } } else { - content - .modelTurn() - .flatMap(modelTurn -> modelTurn.parts()) - .ifPresent( - parts -> - parts.forEach( - part -> - part.inlineData() - .flatMap(Blob::data) - .ifPresent( - audioBytes -> { - if (speakerLine != null && speakerLine.isOpen()) { - // Write audio data to the speaker - speakerLine.write(audioBytes, 0, audioBytes.length); - } - }))); + content.modelTurn().stream() + .flatMap(modelTurn -> modelTurn.parts().stream()) + .flatMap(Collection::stream) + .map(part -> part.inlineData().flatMap(Blob::data)) + .flatMap(Optional::stream) + .forEach( + audioBytes -> { + if (speakerLine != null && speakerLine.isOpen()) { + // Write audio data to the speaker + speakerLine.write(audioBytes, 0, audioBytes.length); + } + }); } }); } diff --git a/examples/src/main/java/com/google/genai/examples/LiveTextContextWindowCompressionAsync.java b/examples/src/main/java/com/google/genai/examples/LiveTextContextWindowCompressionAsync.java index bb6db83ecfa..23c6afafcff 100644 --- a/examples/src/main/java/com/google/genai/examples/LiveTextContextWindowCompressionAsync.java +++ b/examples/src/main/java/com/google/genai/examples/LiveTextContextWindowCompressionAsync.java @@ -129,23 +129,26 @@ public static LiveSendClientContentParameters clientContentFromText(String text) public static void printLiveServerMessage( LiveServerMessage message, CompletableFuture allDone) { - if (message.serverContent().isPresent()) { - LiveServerContent content = message.serverContent().get(); - if (content.modelTurn().isPresent()) { - Content modelTurn = content.modelTurn().get(); - for (Part part : modelTurn.parts().orElse(ImmutableList.of())) { - if (part.inlineData().isPresent()) { - // Print some text to indicate that audio is returned. - System.out.print("Some audio bytes in inline_data..."); - } else if (part.text().isPresent()) { - System.out.print(part.text().get()); - } + LiveServerContent content = message.serverContent().orElse(null); + if (content == null) { + return; + } + + Content modelTurn = content.modelTurn().orElse(null); + if (modelTurn != null) { + for (Part part : modelTurn.parts().orElse(ImmutableList.of())) { + if (part.inlineData().isPresent()) { + // Print some text to indicate that audio is returned. + System.out.print("Some audio bytes in inline_data..."); + } else if (part.text().isPresent()) { + System.out.print(part.text().get()); } } - if (content.turnComplete().orElse(false)) { - System.out.println(); - allDone.complete(null); - } + } + + if (content.turnComplete().orElse(false)) { + System.out.println(); + allDone.complete(null); } } diff --git a/examples/src/main/java/com/google/genai/examples/LiveTextConversationAsync.java b/examples/src/main/java/com/google/genai/examples/LiveTextConversationAsync.java index d3c57c75af5..b1a76eaa06d 100644 --- a/examples/src/main/java/com/google/genai/examples/LiveTextConversationAsync.java +++ b/examples/src/main/java/com/google/genai/examples/LiveTextConversationAsync.java @@ -129,22 +129,14 @@ public static LiveSendClientContentParameters clientContentFromText(String text) public static void printLiveServerMessage( LiveServerMessage message, CompletableFuture allDone) { - if (message.serverContent().isPresent()) { - LiveServerContent content = message.serverContent().get(); - content - .modelTurn() - .ifPresent( - modelTurn -> - modelTurn - .parts() - .ifPresent( - parts -> - parts.forEach(part -> part.text().ifPresent(System.out::print)))); - - if (content.turnComplete().orElse(false)) { - System.out.print("\nYour Turn >> "); - allDone.complete(null); - } + message.serverContent() + .flatMap(LiveServerContent::modelTurn) + .flatMap(Content::parts) + .ifPresent(parts -> parts.forEach(part -> part.text().ifPresent(System.out::print))); + + if (message.serverContent().flatMap(LiveServerContent::turnComplete).orElse(false)) { + System.out.print("\nYour Turn >> "); + allDone.complete(null); } } diff --git a/examples/src/main/java/com/google/genai/examples/LiveTextConversationResumptionAsync.java b/examples/src/main/java/com/google/genai/examples/LiveTextConversationResumptionAsync.java index ad706e0fb67..38ebab82db3 100644 --- a/examples/src/main/java/com/google/genai/examples/LiveTextConversationResumptionAsync.java +++ b/examples/src/main/java/com/google/genai/examples/LiveTextConversationResumptionAsync.java @@ -62,6 +62,7 @@ import com.google.genai.types.Part; import com.google.genai.types.SessionResumptionConfig; import java.io.Console; +import java.util.Collection; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; @@ -187,14 +188,10 @@ public static LiveSendClientContentParameters clientContentFromText(String text) private static void printServerContent( LiveServerContent content, CompletableFuture allDone) { - content - .modelTurn() - .ifPresent( - modelTurn -> - modelTurn - .parts() - .ifPresent( - parts -> parts.forEach(part -> part.text().ifPresent(System.out::print)))); + content.modelTurn().flatMap(Content::parts).stream() + .flatMap(Collection::stream) + .map(Part::text) + .forEach(text -> text.ifPresent(System.out::print)); if (content.turnComplete().orElse(false)) { System.out.println("Your Turn >> "); diff --git a/examples/src/main/java/com/google/genai/examples/LiveTextToAudioTranscriptionAsync.java b/examples/src/main/java/com/google/genai/examples/LiveTextToAudioTranscriptionAsync.java index b9fb9360bc0..832f3ae8243 100644 --- a/examples/src/main/java/com/google/genai/examples/LiveTextToAudioTranscriptionAsync.java +++ b/examples/src/main/java/com/google/genai/examples/LiveTextToAudioTranscriptionAsync.java @@ -42,15 +42,11 @@ */ package com.google.genai.examples; -import com.google.common.collect.ImmutableList; import com.google.genai.AsyncSession; import com.google.genai.Client; import com.google.genai.types.AudioTranscriptionConfig; import com.google.genai.types.Content; import com.google.genai.types.GoogleSearch; -import com.google.genai.types.GroundingChunk; -import com.google.genai.types.GroundingChunkWeb; -import com.google.genai.types.GroundingMetadata; import com.google.genai.types.LiveConnectConfig; import com.google.genai.types.LiveSendClientContentParameters; import com.google.genai.types.LiveServerContent; @@ -60,7 +56,7 @@ import com.google.genai.types.SpeechConfig; import com.google.genai.types.Tool; import com.google.genai.types.Transcription; -import java.util.List; +import java.util.Collection; import java.util.Optional; import java.util.concurrent.CompletableFuture; @@ -144,34 +140,8 @@ public static void printLiveServerMessage( LiveServerMessage message, CompletableFuture allDone) { if (message.serverContent().isPresent()) { LiveServerContent content = message.serverContent().get(); - if (content.modelTurn().isPresent()) { - Content modelTurn = content.modelTurn().get(); - for (Part part : modelTurn.parts().orElse(ImmutableList.of())) { - if (part.inlineData().isPresent()) { - // Print some text to indicate that audio is returned. - System.out.print("Some audio bytes in inline_data..."); - } - } - } - if (content.groundingMetadata().isPresent()) { - GroundingMetadata groundingMetadata = content.groundingMetadata().get(); - - Optional> groundingChunksOptional = - groundingMetadata.groundingChunks(); - - if (groundingChunksOptional.isPresent()) { - List groundingChunks = groundingChunksOptional.get(); - for (GroundingChunk chunk : groundingChunks) { - if (chunk.web().isPresent()) { - GroundingChunkWeb web = chunk.web().get(); - if (web.uri().isPresent()) { - String uri = web.uri().get(); - System.out.println("\n\nGrounding URI: " + uri); - } - } - } - } - } + processModelTurn(content); + processGroundingMetadata(content); // Print audio transcription. if (content.outputTranscription().isPresent()) { @@ -187,5 +157,24 @@ public static void printLiveServerMessage( } } + private static void processModelTurn(LiveServerContent content) { + content.modelTurn().flatMap(Content::parts).stream() + .flatMap(Collection::stream) + .map(Part::inlineData) + .filter(Optional::isPresent) + .forEach(inlineData -> System.out.print("Some audio bytes in inline_data...")); + } + + private static void processGroundingMetadata(LiveServerContent content) { + content.groundingMetadata().stream() + .flatMap(metadata -> metadata.groundingChunks().stream()) + .flatMap(Collection::stream) + .map(chunk -> chunk.web()) + .filter(Optional::isPresent) + .map(web -> web.get().uri()) + .filter(Optional::isPresent) + .forEach(uri -> System.out.println("\n\nGrounding URI: " + uri.get())); + } + private LiveTextToAudioTranscriptionAsync() {} } diff --git a/examples/src/main/java/com/google/genai/examples/LiveTextToTextGenerationAsync.java b/examples/src/main/java/com/google/genai/examples/LiveTextToTextGenerationAsync.java index bc0a84676e8..18062532605 100644 --- a/examples/src/main/java/com/google/genai/examples/LiveTextToTextGenerationAsync.java +++ b/examples/src/main/java/com/google/genai/examples/LiveTextToTextGenerationAsync.java @@ -42,7 +42,6 @@ */ package com.google.genai.examples; -import com.google.common.collect.ImmutableList; import com.google.genai.AsyncSession; import com.google.genai.Client; import com.google.genai.types.Content; @@ -121,20 +120,14 @@ public static LiveSendClientContentParameters clientContentFromText(String text) public static void printLiveServerMessage( LiveServerMessage message, CompletableFuture allDone) { - if (message.serverContent().isPresent()) { - LiveServerContent content = message.serverContent().get(); - if (content.modelTurn().isPresent()) { - Content modelTurn = content.modelTurn().get(); - for (Part part : modelTurn.parts().orElse(ImmutableList.of())) { - if (part.text().isPresent()) { - System.out.print(part.text().get()); - } - } - } - if (content.turnComplete().orElse(false)) { - System.out.println(); - allDone.complete(null); - } + message.serverContent() + .flatMap(LiveServerContent::modelTurn) + .flatMap(Content::parts) + .ifPresent(parts -> parts.forEach(part -> part.text().ifPresent(System.out::print))); + + if (message.serverContent().flatMap(LiveServerContent::turnComplete).orElse(false)) { + System.out.println(); + allDone.complete(null); } } From 1833758d5eb695baf6c94d8ce626e802e550014d Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Wed, 18 Jun 2025 17:14:58 -0700 Subject: [PATCH 023/602] chore(main): release 1.5.0 (#337) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- .release-please-manifest.json | 2 +- CHANGELOG.md | 15 +++++++++++++++ examples/pom.xml | 2 +- pom.xml | 2 +- 4 files changed, 18 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 73257989c9b..fbd9082d716 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "1.4.1" + ".": "1.5.0" } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 56ebe82b80e..0dc8aaed03a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,20 @@ # Changelog +## [1.5.0](https://github.com/googleapis/java-genai/compare/v1.4.1...v1.5.0) (2025-06-19) + + +### Features + +* Add a default 5 minutes timeout to the Java SDK. ([d80d23b](https://github.com/googleapis/java-genai/commit/d80d23b7a8cb440410f9dd9556ee1259352285ef)) +* enable json schema for controlled output and function declaration. ([35d93d8](https://github.com/googleapis/java-genai/commit/35d93d84a349cf1032d2cc61bf4e3128386759d6)) +* Parametrize model ID in Java genai samples and set hardcoded model IDs as default values if model ID not passed in by user. ([c1b0948](https://github.com/googleapis/java-genai/commit/c1b0948af51bc746cbf350e4b6a60b6199d3ffe2)) +* resolve deep conditional nesting in Live API examples for better readability. ([aa71865](https://github.com/googleapis/java-genai/commit/aa718657f53f4bd9132a9b00816e7f5581108dec)) + + +### Documentation + +* fix small typo in comments ([a6bfe36](https://github.com/googleapis/java-genai/commit/a6bfe36843bed1575a03c86a092a17b35e48fd9f)) + ## [1.4.1](https://github.com/googleapis/java-genai/compare/v1.4.0...v1.4.1) (2025-06-12) diff --git a/examples/pom.xml b/examples/pom.xml index a51998b7d50..dc67f14e6a2 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -5,7 +5,7 @@ com.google.genai.examples google-genai-examples - 1.5.0-SNAPSHOT + 1.5.0 google-genai-examples diff --git a/pom.xml b/pom.xml index ea44cb843a1..6276a38f3dc 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ com.google.genai google-genai google-genai - 1.5.0-SNAPSHOT + 1.5.0 jar Java idiomatic SDK for the Gemini Developer APIs and Vertex AI APIs. From b25b3034416327c9115b56ddadb19d1892404eb0 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Wed, 18 Jun 2025 17:40:18 -0700 Subject: [PATCH 024/602] chore(main): release 1.6.0-SNAPSHOT (#346) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- examples/pom.xml | 2 +- pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/pom.xml b/examples/pom.xml index dc67f14e6a2..8333d2adcb4 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -5,7 +5,7 @@ com.google.genai.examples google-genai-examples - 1.5.0 + 1.6.0-SNAPSHOT google-genai-examples diff --git a/pom.xml b/pom.xml index 6276a38f3dc..3de1d844970 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ com.google.genai google-genai google-genai - 1.5.0 + 1.6.0-SNAPSHOT jar Java idiomatic SDK for the Gemini Developer APIs and Vertex AI APIs. From f7def2e058c241fe7978d71cd20b2355db32bede Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Wed, 18 Jun 2025 17:37:25 -0700 Subject: [PATCH 025/602] Copybara import of the project: -- 6c5d250186826d97830bcfedba92b05b94d54278 by release-please[bot] <55107282+release-please[bot]@users.noreply.github.com>: chore(main): release 1.5.0 COPYBARA_INTEGRATE_REVIEW=https://github.com/googleapis/java-genai/pull/337 from googleapis:release-please--branches--main 6c5d250186826d97830bcfedba92b05b94d54278 PiperOrigin-RevId: 773127592 --- examples/pom.xml | 2 +- pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/pom.xml b/examples/pom.xml index 8333d2adcb4..dc67f14e6a2 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -5,7 +5,7 @@ com.google.genai.examples google-genai-examples - 1.6.0-SNAPSHOT + 1.5.0 google-genai-examples diff --git a/pom.xml b/pom.xml index 3de1d844970..6276a38f3dc 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ com.google.genai google-genai google-genai - 1.6.0-SNAPSHOT + 1.5.0 jar Java idiomatic SDK for the Gemini Developer APIs and Vertex AI APIs. From 83d615c1abff7f2058d81ac94e34e633508847cf Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Wed, 18 Jun 2025 17:44:45 -0700 Subject: [PATCH 026/602] Copybara import of the project: -- 1833758d5eb695baf6c94d8ce626e802e550014d by release-please[bot] <55107282+release-please[bot]@users.noreply.github.com>: chore(main): release 1.5.0 (#337) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> -- 2dc10166860e6904f015216b9eb1f3439d52ecbe by release-please[bot] <55107282+release-please[bot]@users.noreply.github.com>: chore(main): release 1.6.0-SNAPSHOT COPYBARA_INTEGRATE_REVIEW=https://github.com/googleapis/java-genai/pull/346 from googleapis:release-please--branches--main 2dc10166860e6904f015216b9eb1f3439d52ecbe PiperOrigin-RevId: 773129122 --- examples/pom.xml | 2 +- pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/pom.xml b/examples/pom.xml index dc67f14e6a2..8333d2adcb4 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -5,7 +5,7 @@ com.google.genai.examples google-genai-examples - 1.5.0 + 1.6.0-SNAPSHOT google-genai-examples diff --git a/pom.xml b/pom.xml index 6276a38f3dc..3de1d844970 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ com.google.genai google-genai google-genai - 1.5.0 + 1.6.0-SNAPSHOT jar Java idiomatic SDK for the Gemini Developer APIs and Vertex AI APIs. From 7923fe472902d3ccc4eaf3dcaa9f5e2b35041d66 Mon Sep 17 00:00:00 2001 From: Annie Luc Date: Wed, 18 Jun 2025 18:55:50 -0700 Subject: [PATCH 027/602] refactor: Remove ApiClient parameter from converter functions that don't need it. PiperOrigin-RevId: 773145422 --- src/main/java/com/google/genai/AfcUtil.java | 7 +- .../java/com/google/genai/AsyncSession.java | 4 +- src/main/java/com/google/genai/Caches.java | 218 ++---- src/main/java/com/google/genai/Files.java | 71 +- .../java/com/google/genai/LiveConverters.java | 524 ++++---------- src/main/java/com/google/genai/Models.java | 652 ++++++------------ .../java/com/google/genai/Operations.java | 54 +- .../java/com/google/genai/ResponseStream.java | 6 +- .../com/google/genai/TokensConverters.java | 254 ++----- .../java/com/google/genai/Transformers.java | 39 +- .../java/com/google/genai/AfcUtilTest.java | 26 +- .../com/google/genai/LiveConvertersTest.java | 20 +- .../com/google/genai/TransformersTest.java | 69 +- 13 files changed, 618 insertions(+), 1326 deletions(-) diff --git a/src/main/java/com/google/genai/AfcUtil.java b/src/main/java/com/google/genai/AfcUtil.java index 9c888abe842..bd278753aff 100644 --- a/src/main/java/com/google/genai/AfcUtil.java +++ b/src/main/java/com/google/genai/AfcUtil.java @@ -38,7 +38,7 @@ final class AfcUtil { private static final Logger logger = Logger.getLogger(AfcUtil.class.getName()); private static final int DEFAULT_MAX_REMOTE_CALLS_AFC = 10; - static boolean hasCallableTool(ApiClient apiClient, GenerateContentConfig config) { + static boolean hasCallableTool(GenerateContentConfig config) { if (config == null) { return false; } @@ -53,13 +53,12 @@ static boolean hasCallableTool(ApiClient apiClient, GenerateContentConfig config return false; } - static GenerateContentConfig transformGenerateContentConfig( - ApiClient apiClient, GenerateContentConfig config) { + static GenerateContentConfig transformGenerateContentConfig(GenerateContentConfig config) { GenerateContentConfig transformedConfig; if (config != null && config.tools().isPresent() && !config.tools().get().isEmpty()) { ImmutableList transformedTools = config.tools().get().stream() - .map(tool -> Transformers.tTool(apiClient, tool)) + .map(tool -> Transformers.tTool(tool)) .collect(toImmutableList()); ObjectNode configNode = JsonSerializable.objectMapper.valueToTree(config); configNode.set("tools", JsonSerializable.objectMapper.valueToTree(transformedTools)); diff --git a/src/main/java/com/google/genai/AsyncSession.java b/src/main/java/com/google/genai/AsyncSession.java index d5214c201b1..0d84c8763bd 100644 --- a/src/main/java/com/google/genai/AsyncSession.java +++ b/src/main/java/com/google/genai/AsyncSession.java @@ -100,9 +100,9 @@ private CompletableFuture send(LiveClientMessage input) { ObjectNode body; if (this.apiClient.vertexAI()) { - body = liveConverters.liveClientMessageToVertex(this.apiClient, parameterNode, null); + body = liveConverters.liveClientMessageToVertex(parameterNode, null); } else { - body = liveConverters.liveClientMessageToMldev(this.apiClient, parameterNode, null); + body = liveConverters.liveClientMessageToMldev(parameterNode, null); } return CompletableFuture.runAsync(() -> websocket.send(JsonSerializable.toJsonString(body))); diff --git a/src/main/java/com/google/genai/Caches.java b/src/main/java/com/google/genai/Caches.java index 3ec89511c37..e0b6e8152ad 100644 --- a/src/main/java/com/google/genai/Caches.java +++ b/src/main/java/com/google/genai/Caches.java @@ -53,8 +53,7 @@ public Caches(ApiClient apiClient) { } @ExcludeFromGeneratedCoverageReport - ObjectNode videoMetadataToMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode videoMetadataToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"fps"}) != null) { Common.setValueByPath( @@ -79,7 +78,7 @@ ObjectNode videoMetadataToMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode blobToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode blobToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"displayName"}))) { throw new IllegalArgumentException("displayName parameter is not supported in Gemini API."); @@ -103,7 +102,7 @@ ObjectNode blobToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode pare } @ExcludeFromGeneratedCoverageReport - ObjectNode fileDataToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode fileDataToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"displayName"}))) { throw new IllegalArgumentException("displayName parameter is not supported in Gemini API."); @@ -127,14 +126,13 @@ ObjectNode fileDataToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode } @ExcludeFromGeneratedCoverageReport - ObjectNode partToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode partToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"videoMetadata"}) != null) { Common.setValueByPath( toObject, new String[] {"videoMetadata"}, videoMetadataToMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"videoMetadata"})), toObject)); @@ -152,7 +150,6 @@ ObjectNode partToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode pare toObject, new String[] {"inlineData"}, blobToMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"inlineData"})), toObject)); @@ -163,7 +160,6 @@ ObjectNode partToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode pare toObject, new String[] {"fileData"}, fileDataToMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"fileData"})), toObject)); @@ -215,7 +211,7 @@ ObjectNode partToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode pare } @ExcludeFromGeneratedCoverageReport - ObjectNode contentToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode contentToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"parts"}) != null) { ArrayNode keyArray = (ArrayNode) Common.getValueByPath(fromObject, new String[] {"parts"}); @@ -223,7 +219,7 @@ ObjectNode contentToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode p ArrayNode result = objectMapper.createArrayNode(); for (JsonNode item : keyArray) { - result.add(partToMldev(apiClient, JsonSerializable.toJsonNode(item), toObject)); + result.add(partToMldev(JsonSerializable.toJsonNode(item), toObject)); } Common.setValueByPath(toObject, new String[] {"parts"}, result); } @@ -239,8 +235,7 @@ ObjectNode contentToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode p } @ExcludeFromGeneratedCoverageReport - ObjectNode functionDeclarationToMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode functionDeclarationToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"behavior"}) != null) { Common.setValueByPath( @@ -295,7 +290,7 @@ ObjectNode functionDeclarationToMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode intervalToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode intervalToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"startTime"}) != null) { Common.setValueByPath( @@ -315,15 +310,13 @@ ObjectNode intervalToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode } @ExcludeFromGeneratedCoverageReport - ObjectNode googleSearchToMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode googleSearchToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"timeRangeFilter"}) != null) { Common.setValueByPath( toObject, new String[] {"timeRangeFilter"}, intervalToMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"timeRangeFilter"})), toObject)); @@ -333,8 +326,7 @@ ObjectNode googleSearchToMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode dynamicRetrievalConfigToMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode dynamicRetrievalConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"mode"}) != null) { Common.setValueByPath( @@ -354,15 +346,13 @@ ObjectNode dynamicRetrievalConfigToMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode googleSearchRetrievalToMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode googleSearchRetrievalToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"dynamicRetrievalConfig"}) != null) { Common.setValueByPath( toObject, new String[] {"dynamicRetrievalConfig"}, dynamicRetrievalConfigToMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"dynamicRetrievalConfig"})), toObject)); @@ -372,16 +362,14 @@ ObjectNode googleSearchRetrievalToMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode enterpriseWebSearchToMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode enterpriseWebSearchToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); return toObject; } @ExcludeFromGeneratedCoverageReport - ObjectNode apiKeyConfigToMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode apiKeyConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"apiKeyString"}))) { throw new IllegalArgumentException("apiKeyString parameter is not supported in Gemini API."); @@ -391,7 +379,7 @@ ObjectNode apiKeyConfigToMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode authConfigToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode authConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"apiKeyConfig"}))) { throw new IllegalArgumentException("apiKeyConfig parameter is not supported in Gemini API."); @@ -436,7 +424,7 @@ ObjectNode authConfigToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNod } @ExcludeFromGeneratedCoverageReport - ObjectNode googleMapsToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode googleMapsToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"authConfig"}))) { throw new IllegalArgumentException("authConfig parameter is not supported in Gemini API."); @@ -446,14 +434,14 @@ ObjectNode googleMapsToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNod } @ExcludeFromGeneratedCoverageReport - ObjectNode urlContextToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode urlContextToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); return toObject; } @ExcludeFromGeneratedCoverageReport - ObjectNode toolToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toolToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"functionDeclarations"}) != null) { ArrayNode keyArray = @@ -462,8 +450,7 @@ ObjectNode toolToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode pare ArrayNode result = objectMapper.createArrayNode(); for (JsonNode item : keyArray) { - result.add( - functionDeclarationToMldev(apiClient, JsonSerializable.toJsonNode(item), toObject)); + result.add(functionDeclarationToMldev(JsonSerializable.toJsonNode(item), toObject)); } Common.setValueByPath(toObject, new String[] {"functionDeclarations"}, result); } @@ -477,7 +464,6 @@ ObjectNode toolToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode pare toObject, new String[] {"googleSearch"}, googleSearchToMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"googleSearch"})), toObject)); @@ -488,7 +474,6 @@ ObjectNode toolToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode pare toObject, new String[] {"googleSearchRetrieval"}, googleSearchRetrievalToMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"googleSearchRetrieval"})), toObject)); @@ -508,7 +493,6 @@ ObjectNode toolToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode pare toObject, new String[] {"urlContext"}, urlContextToMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"urlContext"})), toObject)); @@ -525,8 +509,7 @@ ObjectNode toolToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode pare } @ExcludeFromGeneratedCoverageReport - ObjectNode functionCallingConfigToMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode functionCallingConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"mode"}) != null) { Common.setValueByPath( @@ -546,7 +529,7 @@ ObjectNode functionCallingConfigToMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode latLngToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode latLngToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"latitude"}) != null) { Common.setValueByPath( @@ -566,15 +549,13 @@ ObjectNode latLngToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode pa } @ExcludeFromGeneratedCoverageReport - ObjectNode retrievalConfigToMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode retrievalConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"latLng"}) != null) { Common.setValueByPath( toObject, new String[] {"latLng"}, latLngToMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"latLng"})), toObject)); @@ -591,14 +572,13 @@ ObjectNode retrievalConfigToMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode toolConfigToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toolConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"functionCallingConfig"}) != null) { Common.setValueByPath( toObject, new String[] {"functionCallingConfig"}, functionCallingConfigToMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"functionCallingConfig"})), toObject)); @@ -609,7 +589,6 @@ ObjectNode toolConfigToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNod toObject, new String[] {"retrievalConfig"}, retrievalConfigToMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"retrievalConfig"})), toObject)); @@ -619,8 +598,7 @@ ObjectNode toolConfigToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNod } @ExcludeFromGeneratedCoverageReport - ObjectNode createCachedContentConfigToMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode createCachedContentConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"ttl"}) != null) { @@ -647,13 +625,12 @@ ObjectNode createCachedContentConfigToMldev( if (Common.getValueByPath(fromObject, new String[] {"contents"}) != null) { ArrayNode keyArray = (ArrayNode) - Transformers.tContents( - this.apiClient, Common.getValueByPath(fromObject, new String[] {"contents"})); + Transformers.tContents(Common.getValueByPath(fromObject, new String[] {"contents"})); ObjectMapper objectMapper = new ObjectMapper(); ArrayNode result = objectMapper.createArrayNode(); for (JsonNode item : keyArray) { - result.add(contentToMldev(apiClient, JsonSerializable.toJsonNode(item), toObject)); + result.add(contentToMldev(JsonSerializable.toJsonNode(item), toObject)); } Common.setValueByPath(parentObject, new String[] {"contents"}, result); } @@ -663,10 +640,8 @@ ObjectNode createCachedContentConfigToMldev( parentObject, new String[] {"systemInstruction"}, contentToMldev( - apiClient, JsonSerializable.toJsonNode( Transformers.tContent( - this.apiClient, Common.getValueByPath(fromObject, new String[] {"systemInstruction"}))), toObject)); } @@ -677,7 +652,7 @@ ObjectNode createCachedContentConfigToMldev( ArrayNode result = objectMapper.createArrayNode(); for (JsonNode item : keyArray) { - result.add(toolToMldev(apiClient, JsonSerializable.toJsonNode(item), toObject)); + result.add(toolToMldev(JsonSerializable.toJsonNode(item), toObject)); } Common.setValueByPath(parentObject, new String[] {"tools"}, result); } @@ -687,7 +662,6 @@ ObjectNode createCachedContentConfigToMldev( parentObject, new String[] {"toolConfig"}, toolConfigToMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"toolConfig"})), toObject)); @@ -717,7 +691,6 @@ ObjectNode createCachedContentParametersToMldev( toObject, new String[] {"config"}, createCachedContentConfigToMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"config"})), toObject)); @@ -771,8 +744,7 @@ ObjectNode deleteCachedContentParametersToMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode listCachedContentsConfigToMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode listCachedContentsConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"pageSize"}) != null) { @@ -793,15 +765,13 @@ ObjectNode listCachedContentsConfigToMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode listCachedContentsParametersToMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode listCachedContentsParametersToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"config"}) != null) { Common.setValueByPath( toObject, new String[] {"config"}, listCachedContentsConfigToMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"config"})), toObject)); @@ -811,8 +781,7 @@ ObjectNode listCachedContentsParametersToMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode videoMetadataToVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode videoMetadataToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"fps"}) != null) { Common.setValueByPath( @@ -837,7 +806,7 @@ ObjectNode videoMetadataToVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode blobToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode blobToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"displayName"}) != null) { Common.setValueByPath( @@ -864,7 +833,7 @@ ObjectNode blobToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode par } @ExcludeFromGeneratedCoverageReport - ObjectNode fileDataToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode fileDataToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"displayName"}) != null) { Common.setValueByPath( @@ -891,14 +860,13 @@ ObjectNode fileDataToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode } @ExcludeFromGeneratedCoverageReport - ObjectNode partToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode partToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"videoMetadata"}) != null) { Common.setValueByPath( toObject, new String[] {"videoMetadata"}, videoMetadataToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"videoMetadata"})), toObject)); @@ -916,7 +884,6 @@ ObjectNode partToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode par toObject, new String[] {"inlineData"}, blobToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"inlineData"})), toObject)); @@ -927,7 +894,6 @@ ObjectNode partToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode par toObject, new String[] {"fileData"}, fileDataToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"fileData"})), toObject)); @@ -979,7 +945,7 @@ ObjectNode partToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode par } @ExcludeFromGeneratedCoverageReport - ObjectNode contentToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode contentToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"parts"}) != null) { ArrayNode keyArray = (ArrayNode) Common.getValueByPath(fromObject, new String[] {"parts"}); @@ -987,7 +953,7 @@ ObjectNode contentToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode ArrayNode result = objectMapper.createArrayNode(); for (JsonNode item : keyArray) { - result.add(partToVertex(apiClient, JsonSerializable.toJsonNode(item), toObject)); + result.add(partToVertex(JsonSerializable.toJsonNode(item), toObject)); } Common.setValueByPath(toObject, new String[] {"parts"}, result); } @@ -1003,8 +969,7 @@ ObjectNode contentToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode } @ExcludeFromGeneratedCoverageReport - ObjectNode functionDeclarationToVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode functionDeclarationToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"behavior"}))) { throw new IllegalArgumentException("behavior parameter is not supported in Vertex AI."); @@ -1056,7 +1021,7 @@ ObjectNode functionDeclarationToVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode intervalToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode intervalToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"startTime"}) != null) { Common.setValueByPath( @@ -1076,15 +1041,13 @@ ObjectNode intervalToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode } @ExcludeFromGeneratedCoverageReport - ObjectNode googleSearchToVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode googleSearchToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"timeRangeFilter"}) != null) { Common.setValueByPath( toObject, new String[] {"timeRangeFilter"}, intervalToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"timeRangeFilter"})), toObject)); @@ -1094,8 +1057,7 @@ ObjectNode googleSearchToVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode dynamicRetrievalConfigToVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode dynamicRetrievalConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"mode"}) != null) { Common.setValueByPath( @@ -1115,15 +1077,13 @@ ObjectNode dynamicRetrievalConfigToVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode googleSearchRetrievalToVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode googleSearchRetrievalToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"dynamicRetrievalConfig"}) != null) { Common.setValueByPath( toObject, new String[] {"dynamicRetrievalConfig"}, dynamicRetrievalConfigToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"dynamicRetrievalConfig"})), toObject)); @@ -1133,16 +1093,14 @@ ObjectNode googleSearchRetrievalToVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode enterpriseWebSearchToVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode enterpriseWebSearchToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); return toObject; } @ExcludeFromGeneratedCoverageReport - ObjectNode apiKeyConfigToVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode apiKeyConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"apiKeyString"}) != null) { Common.setValueByPath( @@ -1155,14 +1113,13 @@ ObjectNode apiKeyConfigToVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode authConfigToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode authConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"apiKeyConfig"}) != null) { Common.setValueByPath( toObject, new String[] {"apiKeyConfig"}, apiKeyConfigToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"apiKeyConfig"})), toObject)); @@ -1207,14 +1164,13 @@ ObjectNode authConfigToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNo } @ExcludeFromGeneratedCoverageReport - ObjectNode googleMapsToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode googleMapsToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"authConfig"}) != null) { Common.setValueByPath( toObject, new String[] {"authConfig"}, authConfigToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"authConfig"})), toObject)); @@ -1224,14 +1180,14 @@ ObjectNode googleMapsToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNo } @ExcludeFromGeneratedCoverageReport - ObjectNode urlContextToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode urlContextToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); return toObject; } @ExcludeFromGeneratedCoverageReport - ObjectNode toolToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toolToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"functionDeclarations"}) != null) { ArrayNode keyArray = @@ -1240,8 +1196,7 @@ ObjectNode toolToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode par ArrayNode result = objectMapper.createArrayNode(); for (JsonNode item : keyArray) { - result.add( - functionDeclarationToVertex(apiClient, JsonSerializable.toJsonNode(item), toObject)); + result.add(functionDeclarationToVertex(JsonSerializable.toJsonNode(item), toObject)); } Common.setValueByPath(toObject, new String[] {"functionDeclarations"}, result); } @@ -1258,7 +1213,6 @@ ObjectNode toolToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode par toObject, new String[] {"googleSearch"}, googleSearchToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"googleSearch"})), toObject)); @@ -1269,7 +1223,6 @@ ObjectNode toolToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode par toObject, new String[] {"googleSearchRetrieval"}, googleSearchRetrievalToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"googleSearchRetrieval"})), toObject)); @@ -1280,7 +1233,6 @@ ObjectNode toolToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode par toObject, new String[] {"enterpriseWebSearch"}, enterpriseWebSearchToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"enterpriseWebSearch"})), toObject)); @@ -1291,7 +1243,6 @@ ObjectNode toolToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode par toObject, new String[] {"googleMaps"}, googleMapsToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"googleMaps"})), toObject)); @@ -1302,7 +1253,6 @@ ObjectNode toolToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode par toObject, new String[] {"urlContext"}, urlContextToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"urlContext"})), toObject)); @@ -1319,8 +1269,7 @@ ObjectNode toolToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode par } @ExcludeFromGeneratedCoverageReport - ObjectNode functionCallingConfigToVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode functionCallingConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"mode"}) != null) { Common.setValueByPath( @@ -1340,7 +1289,7 @@ ObjectNode functionCallingConfigToVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode latLngToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode latLngToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"latitude"}) != null) { Common.setValueByPath( @@ -1360,15 +1309,13 @@ ObjectNode latLngToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode p } @ExcludeFromGeneratedCoverageReport - ObjectNode retrievalConfigToVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode retrievalConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"latLng"}) != null) { Common.setValueByPath( toObject, new String[] {"latLng"}, latLngToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"latLng"})), toObject)); @@ -1385,14 +1332,13 @@ ObjectNode retrievalConfigToVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode toolConfigToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toolConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"functionCallingConfig"}) != null) { Common.setValueByPath( toObject, new String[] {"functionCallingConfig"}, functionCallingConfigToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"functionCallingConfig"})), toObject)); @@ -1403,7 +1349,6 @@ ObjectNode toolConfigToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNo toObject, new String[] {"retrievalConfig"}, retrievalConfigToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"retrievalConfig"})), toObject)); @@ -1413,8 +1358,7 @@ ObjectNode toolConfigToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNo } @ExcludeFromGeneratedCoverageReport - ObjectNode createCachedContentConfigToVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode createCachedContentConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"ttl"}) != null) { @@ -1441,13 +1385,12 @@ ObjectNode createCachedContentConfigToVertex( if (Common.getValueByPath(fromObject, new String[] {"contents"}) != null) { ArrayNode keyArray = (ArrayNode) - Transformers.tContents( - this.apiClient, Common.getValueByPath(fromObject, new String[] {"contents"})); + Transformers.tContents(Common.getValueByPath(fromObject, new String[] {"contents"})); ObjectMapper objectMapper = new ObjectMapper(); ArrayNode result = objectMapper.createArrayNode(); for (JsonNode item : keyArray) { - result.add(contentToVertex(apiClient, JsonSerializable.toJsonNode(item), toObject)); + result.add(contentToVertex(JsonSerializable.toJsonNode(item), toObject)); } Common.setValueByPath(parentObject, new String[] {"contents"}, result); } @@ -1457,10 +1400,8 @@ ObjectNode createCachedContentConfigToVertex( parentObject, new String[] {"systemInstruction"}, contentToVertex( - apiClient, JsonSerializable.toJsonNode( Transformers.tContent( - this.apiClient, Common.getValueByPath(fromObject, new String[] {"systemInstruction"}))), toObject)); } @@ -1471,7 +1412,7 @@ ObjectNode createCachedContentConfigToVertex( ArrayNode result = objectMapper.createArrayNode(); for (JsonNode item : keyArray) { - result.add(toolToVertex(apiClient, JsonSerializable.toJsonNode(item), toObject)); + result.add(toolToVertex(JsonSerializable.toJsonNode(item), toObject)); } Common.setValueByPath(parentObject, new String[] {"tools"}, result); } @@ -1481,7 +1422,6 @@ ObjectNode createCachedContentConfigToVertex( parentObject, new String[] {"toolConfig"}, toolConfigToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"toolConfig"})), toObject)); @@ -1514,7 +1454,6 @@ ObjectNode createCachedContentParametersToVertex( toObject, new String[] {"config"}, createCachedContentConfigToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"config"})), toObject)); @@ -1568,8 +1507,7 @@ ObjectNode deleteCachedContentParametersToVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode listCachedContentsConfigToVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode listCachedContentsConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"pageSize"}) != null) { @@ -1590,15 +1528,13 @@ ObjectNode listCachedContentsConfigToVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode listCachedContentsParametersToVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode listCachedContentsParametersToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"config"}) != null) { Common.setValueByPath( toObject, new String[] {"config"}, listCachedContentsConfigToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"config"})), toObject)); @@ -1608,8 +1544,7 @@ ObjectNode listCachedContentsParametersToVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode cachedContentFromMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode cachedContentFromMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"name"}) != null) { Common.setValueByPath( @@ -1664,16 +1599,14 @@ ObjectNode cachedContentFromMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode deleteCachedContentResponseFromMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode deleteCachedContentResponseFromMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); return toObject; } @ExcludeFromGeneratedCoverageReport - ObjectNode listCachedContentsResponseFromMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode listCachedContentsResponseFromMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"nextPageToken"}) != null) { Common.setValueByPath( @@ -1689,7 +1622,7 @@ ObjectNode listCachedContentsResponseFromMldev( ArrayNode result = objectMapper.createArrayNode(); for (JsonNode item : keyArray) { - result.add(cachedContentFromMldev(apiClient, JsonSerializable.toJsonNode(item), toObject)); + result.add(cachedContentFromMldev(JsonSerializable.toJsonNode(item), toObject)); } Common.setValueByPath(toObject, new String[] {"cachedContents"}, result); } @@ -1698,8 +1631,7 @@ ObjectNode listCachedContentsResponseFromMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode cachedContentFromVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode cachedContentFromVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"name"}) != null) { Common.setValueByPath( @@ -1754,16 +1686,14 @@ ObjectNode cachedContentFromVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode deleteCachedContentResponseFromVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode deleteCachedContentResponseFromVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); return toObject; } @ExcludeFromGeneratedCoverageReport - ObjectNode listCachedContentsResponseFromVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode listCachedContentsResponseFromVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"nextPageToken"}) != null) { Common.setValueByPath( @@ -1779,7 +1709,7 @@ ObjectNode listCachedContentsResponseFromVertex( ArrayNode result = objectMapper.createArrayNode(); for (JsonNode item : keyArray) { - result.add(cachedContentFromVertex(apiClient, JsonSerializable.toJsonNode(item), toObject)); + result.add(cachedContentFromVertex(JsonSerializable.toJsonNode(item), toObject)); } Common.setValueByPath(toObject, new String[] {"cachedContents"}, result); } @@ -1849,9 +1779,9 @@ public CachedContent create(String model, CreateCachedContentConfig config) { JsonNode responseNode = JsonSerializable.stringToJsonNode(responseString); if (this.apiClient.vertexAI()) { - responseNode = cachedContentFromVertex(this.apiClient, responseNode, null); + responseNode = cachedContentFromVertex(responseNode, null); } else { - responseNode = cachedContentFromMldev(this.apiClient, responseNode, null); + responseNode = cachedContentFromMldev(responseNode, null); } return JsonSerializable.fromJsonNode(responseNode, CachedContent.class); } @@ -1918,9 +1848,9 @@ public CachedContent get(String name, GetCachedContentConfig config) { JsonNode responseNode = JsonSerializable.stringToJsonNode(responseString); if (this.apiClient.vertexAI()) { - responseNode = cachedContentFromVertex(this.apiClient, responseNode, null); + responseNode = cachedContentFromVertex(responseNode, null); } else { - responseNode = cachedContentFromMldev(this.apiClient, responseNode, null); + responseNode = cachedContentFromMldev(responseNode, null); } return JsonSerializable.fromJsonNode(responseNode, CachedContent.class); } @@ -1987,9 +1917,9 @@ public DeleteCachedContentResponse delete(String name, DeleteCachedContentConfig JsonNode responseNode = JsonSerializable.stringToJsonNode(responseString); if (this.apiClient.vertexAI()) { - responseNode = deleteCachedContentResponseFromVertex(this.apiClient, responseNode, null); + responseNode = deleteCachedContentResponseFromVertex(responseNode, null); } else { - responseNode = deleteCachedContentResponseFromMldev(this.apiClient, responseNode, null); + responseNode = deleteCachedContentResponseFromMldev(responseNode, null); } return JsonSerializable.fromJsonNode(responseNode, DeleteCachedContentResponse.class); } @@ -2007,10 +1937,10 @@ ListCachedContentsResponse privateList(ListCachedContentsConfig config) { ObjectNode body; String path; if (this.apiClient.vertexAI()) { - body = listCachedContentsParametersToVertex(this.apiClient, parameterNode, null); + body = listCachedContentsParametersToVertex(parameterNode, null); path = Common.formatMap("cachedContents", body.get("_url")); } else { - body = listCachedContentsParametersToMldev(this.apiClient, parameterNode, null); + body = listCachedContentsParametersToMldev(parameterNode, null); if (body.get("_url") != null) { path = Common.formatMap("cachedContents", body.get("_url")); } else { @@ -2046,9 +1976,9 @@ ListCachedContentsResponse privateList(ListCachedContentsConfig config) { JsonNode responseNode = JsonSerializable.stringToJsonNode(responseString); if (this.apiClient.vertexAI()) { - responseNode = listCachedContentsResponseFromVertex(this.apiClient, responseNode, null); + responseNode = listCachedContentsResponseFromVertex(responseNode, null); } else { - responseNode = listCachedContentsResponseFromMldev(this.apiClient, responseNode, null); + responseNode = listCachedContentsResponseFromMldev(responseNode, null); } return JsonSerializable.fromJsonNode(responseNode, ListCachedContentsResponse.class); } diff --git a/src/main/java/com/google/genai/Files.java b/src/main/java/com/google/genai/Files.java index 07c2b2f23a4..9c477c3957a 100644 --- a/src/main/java/com/google/genai/Files.java +++ b/src/main/java/com/google/genai/Files.java @@ -71,8 +71,7 @@ public Files(ApiClient apiClient) { } @ExcludeFromGeneratedCoverageReport - ObjectNode listFilesConfigToMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode listFilesConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"pageSize"}) != null) { @@ -93,15 +92,13 @@ ObjectNode listFilesConfigToMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode listFilesParametersToMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode listFilesParametersToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"config"}) != null) { Common.setValueByPath( toObject, new String[] {"config"}, listFilesConfigToMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"config"})), toObject)); @@ -111,7 +108,7 @@ ObjectNode listFilesParametersToMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode fileStatusToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode fileStatusToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"details"}) != null) { Common.setValueByPath( @@ -138,7 +135,7 @@ ObjectNode fileStatusToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNod } @ExcludeFromGeneratedCoverageReport - ObjectNode fileToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode fileToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"name"}) != null) { Common.setValueByPath( @@ -234,7 +231,6 @@ ObjectNode fileToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode pare toObject, new String[] {"error"}, fileStatusToMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"error"})), toObject)); @@ -244,15 +240,13 @@ ObjectNode fileToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode pare } @ExcludeFromGeneratedCoverageReport - ObjectNode createFileParametersToMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode createFileParametersToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"file"}) != null) { Common.setValueByPath( toObject, new String[] {"file"}, fileToMldev( - apiClient, JsonSerializable.toJsonNode(Common.getValueByPath(fromObject, new String[] {"file"})), toObject)); } @@ -268,15 +262,13 @@ ObjectNode createFileParametersToMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode getFileParametersToMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode getFileParametersToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"name"}) != null) { Common.setValueByPath( toObject, new String[] {"_url", "file"}, - Transformers.tFileName( - this.apiClient, Common.getValueByPath(fromObject, new String[] {"name"}))); + Transformers.tFileName(Common.getValueByPath(fromObject, new String[] {"name"}))); } if (Common.getValueByPath(fromObject, new String[] {"config"}) != null) { @@ -290,15 +282,13 @@ ObjectNode getFileParametersToMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode deleteFileParametersToMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode deleteFileParametersToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"name"}) != null) { Common.setValueByPath( toObject, new String[] {"_url", "file"}, - Transformers.tFileName( - this.apiClient, Common.getValueByPath(fromObject, new String[] {"name"}))); + Transformers.tFileName(Common.getValueByPath(fromObject, new String[] {"name"}))); } if (Common.getValueByPath(fromObject, new String[] {"config"}) != null) { @@ -312,8 +302,7 @@ ObjectNode deleteFileParametersToMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode fileStatusFromMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode fileStatusFromMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"details"}) != null) { Common.setValueByPath( @@ -340,7 +329,7 @@ ObjectNode fileStatusFromMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode fileFromMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode fileFromMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"name"}) != null) { Common.setValueByPath( @@ -436,7 +425,6 @@ ObjectNode fileFromMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode pa toObject, new String[] {"error"}, fileStatusFromMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"error"})), toObject)); @@ -446,8 +434,7 @@ ObjectNode fileFromMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode pa } @ExcludeFromGeneratedCoverageReport - ObjectNode listFilesResponseFromMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode listFilesResponseFromMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"nextPageToken"}) != null) { Common.setValueByPath( @@ -462,7 +449,7 @@ ObjectNode listFilesResponseFromMldev( ArrayNode result = objectMapper.createArrayNode(); for (JsonNode item : keyArray) { - result.add(fileFromMldev(apiClient, JsonSerializable.toJsonNode(item), toObject)); + result.add(fileFromMldev(JsonSerializable.toJsonNode(item), toObject)); } Common.setValueByPath(toObject, new String[] {"files"}, result); } @@ -471,16 +458,14 @@ ObjectNode listFilesResponseFromMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode createFileResponseFromMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode createFileResponseFromMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); return toObject; } @ExcludeFromGeneratedCoverageReport - ObjectNode deleteFileResponseFromMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode deleteFileResponseFromMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); return toObject; @@ -506,7 +491,7 @@ ListFilesResponse privateList(ListFilesConfig config) { if (this.apiClient.vertexAI()) { throw new UnsupportedOperationException("This method is not supported by the Vertex AI."); } else { - body = listFilesParametersToMldev(this.apiClient, parameterNode, null); + body = listFilesParametersToMldev(parameterNode, null); if (body.get("_url") != null) { path = Common.formatMap("files", body.get("_url")); } else { @@ -544,7 +529,7 @@ ListFilesResponse privateList(ListFilesConfig config) { if (this.apiClient.vertexAI()) { throw new UnsupportedOperationException("This method is not supported by the Vertex AI."); } else { - responseNode = listFilesResponseFromMldev(this.apiClient, responseNode, null); + responseNode = listFilesResponseFromMldev(responseNode, null); } return JsonSerializable.fromJsonNode(responseNode, ListFilesResponse.class); } @@ -567,7 +552,7 @@ CreateFileResponse privateCreate(File file, CreateFileConfig config) { if (this.apiClient.vertexAI()) { throw new UnsupportedOperationException("This method is not supported by the Vertex AI."); } else { - body = createFileParametersToMldev(this.apiClient, parameterNode, null); + body = createFileParametersToMldev(parameterNode, null); if (body.get("_url") != null) { path = Common.formatMap("upload/v1beta/files", body.get("_url")); } else { @@ -615,7 +600,7 @@ CreateFileResponse privateCreate(File file, CreateFileConfig config) { if (this.apiClient.vertexAI()) { throw new UnsupportedOperationException("This method is not supported by the Vertex AI."); } else { - responseNode = createFileResponseFromMldev(this.apiClient, responseNode, null); + responseNode = createFileResponseFromMldev(responseNode, null); } return JsonSerializable.fromJsonNode(responseNode, CreateFileResponse.class); } @@ -645,7 +630,7 @@ public File get(String name, GetFileConfig config) { if (this.apiClient.vertexAI()) { throw new UnsupportedOperationException("This method is not supported by the Vertex AI."); } else { - body = getFileParametersToMldev(this.apiClient, parameterNode, null); + body = getFileParametersToMldev(parameterNode, null); if (body.get("_url") != null) { path = Common.formatMap("files/{file}", body.get("_url")); } else { @@ -683,7 +668,7 @@ public File get(String name, GetFileConfig config) { if (this.apiClient.vertexAI()) { throw new UnsupportedOperationException("This method is not supported by the Vertex AI."); } else { - responseNode = fileFromMldev(this.apiClient, responseNode, null); + responseNode = fileFromMldev(responseNode, null); } return JsonSerializable.fromJsonNode(responseNode, File.class); } @@ -713,7 +698,7 @@ public DeleteFileResponse delete(String name, DeleteFileConfig config) { if (this.apiClient.vertexAI()) { throw new UnsupportedOperationException("This method is not supported by the Vertex AI."); } else { - body = deleteFileParametersToMldev(this.apiClient, parameterNode, null); + body = deleteFileParametersToMldev(parameterNode, null); if (body.get("_url") != null) { path = Common.formatMap("files/{file}", body.get("_url")); } else { @@ -751,7 +736,7 @@ public DeleteFileResponse delete(String name, DeleteFileConfig config) { if (this.apiClient.vertexAI()) { throw new UnsupportedOperationException("This method is not supported by the Vertex AI."); } else { - responseNode = deleteFileResponseFromMldev(this.apiClient, responseNode, null); + responseNode = deleteFileResponseFromMldev(responseNode, null); } return JsonSerializable.fromJsonNode(responseNode, DeleteFileResponse.class); } @@ -830,7 +815,7 @@ private File fileFromUploadHttpEntity(HttpEntity entity) { } JsonNode responseNode = JsonSerializable.stringToJsonNode(responseString); responseNode = responseNode.get("file"); - responseNode = fileFromMldev(this.apiClient, responseNode, null); + responseNode = fileFromMldev(responseNode, null); return JsonSerializable.fromJsonNode(responseNode, File.class); } @@ -908,7 +893,7 @@ private String createFileInApi(UploadFileConfig config, Optional mimeTyp public void download(String fileName, String downloadPath, DownloadFileConfig config) { checkNotNull(fileName); checkNotNull(downloadPath); - String extractedFileName = Transformers.tFileName(apiClient, fileName); + String extractedFileName = Transformers.tFileName(fileName); downloadTo(extractedFileName, downloadPath, config); } @@ -922,7 +907,7 @@ public void download(String fileName, String downloadPath, DownloadFileConfig co public void download(Video video, String downloadPath, DownloadFileConfig config) { checkNotNull(video); checkNotNull(downloadPath); - String extractedFileName = Transformers.tFileName(apiClient, video); + String extractedFileName = Transformers.tFileName(video); if (extractedFileName != null) { downloadTo(extractedFileName, downloadPath, config); } else { @@ -944,7 +929,7 @@ public void download(Video video, String downloadPath, DownloadFileConfig config public void download(File file, String downloadPath, DownloadFileConfig config) { checkNotNull(file); checkNotNull(downloadPath); - String extractedFileName = Transformers.tFileName(apiClient, file); + String extractedFileName = Transformers.tFileName(file); downloadTo(extractedFileName, downloadPath, config); } @@ -959,7 +944,7 @@ public void download( GeneratedVideo generatedVideo, String downloadPath, DownloadFileConfig config) { checkNotNull(generatedVideo); checkNotNull(downloadPath); - String extractedFileName = Transformers.tFileName(apiClient, generatedVideo); + String extractedFileName = Transformers.tFileName(generatedVideo); if (extractedFileName != null) { downloadTo(extractedFileName, downloadPath, config); } else { diff --git a/src/main/java/com/google/genai/LiveConverters.java b/src/main/java/com/google/genai/LiveConverters.java index 5472a1a377c..b3db3a4b784 100644 --- a/src/main/java/com/google/genai/LiveConverters.java +++ b/src/main/java/com/google/genai/LiveConverters.java @@ -31,8 +31,7 @@ public LiveConverters(ApiClient apiClient) { } @ExcludeFromGeneratedCoverageReport - ObjectNode prebuiltVoiceConfigToMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode prebuiltVoiceConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"voiceName"}) != null) { Common.setValueByPath( @@ -45,8 +44,7 @@ ObjectNode prebuiltVoiceConfigToMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode prebuiltVoiceConfigToVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode prebuiltVoiceConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"voiceName"}) != null) { Common.setValueByPath( @@ -59,14 +57,13 @@ ObjectNode prebuiltVoiceConfigToVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode voiceConfigToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode voiceConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"prebuiltVoiceConfig"}) != null) { Common.setValueByPath( toObject, new String[] {"prebuiltVoiceConfig"}, prebuiltVoiceConfigToMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"prebuiltVoiceConfig"})), toObject)); @@ -76,15 +73,13 @@ ObjectNode voiceConfigToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNo } @ExcludeFromGeneratedCoverageReport - ObjectNode voiceConfigToVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode voiceConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"prebuiltVoiceConfig"}) != null) { Common.setValueByPath( toObject, new String[] {"prebuiltVoiceConfig"}, prebuiltVoiceConfigToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"prebuiltVoiceConfig"})), toObject)); @@ -94,8 +89,7 @@ ObjectNode voiceConfigToVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode speakerVoiceConfigToMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode speakerVoiceConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"speaker"}) != null) { Common.setValueByPath( @@ -109,7 +103,6 @@ ObjectNode speakerVoiceConfigToMldev( toObject, new String[] {"voiceConfig"}, voiceConfigToMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"voiceConfig"})), toObject)); @@ -119,8 +112,7 @@ ObjectNode speakerVoiceConfigToMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode speakerVoiceConfigToVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode speakerVoiceConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"speaker"}))) { throw new IllegalArgumentException("speaker parameter is not supported in Vertex AI."); @@ -134,8 +126,7 @@ ObjectNode speakerVoiceConfigToVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode multiSpeakerVoiceConfigToMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode multiSpeakerVoiceConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"speakerVoiceConfigs"}) != null) { ArrayNode keyArray = @@ -144,8 +135,7 @@ ObjectNode multiSpeakerVoiceConfigToMldev( ArrayNode result = objectMapper.createArrayNode(); for (JsonNode item : keyArray) { - result.add( - speakerVoiceConfigToMldev(apiClient, JsonSerializable.toJsonNode(item), toObject)); + result.add(speakerVoiceConfigToMldev(JsonSerializable.toJsonNode(item), toObject)); } Common.setValueByPath(toObject, new String[] {"speakerVoiceConfigs"}, result); } @@ -154,8 +144,7 @@ ObjectNode multiSpeakerVoiceConfigToMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode multiSpeakerVoiceConfigToVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode multiSpeakerVoiceConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"speakerVoiceConfigs"}))) { throw new IllegalArgumentException( @@ -166,15 +155,13 @@ ObjectNode multiSpeakerVoiceConfigToVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode speechConfigToMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode speechConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"voiceConfig"}) != null) { Common.setValueByPath( toObject, new String[] {"voiceConfig"}, voiceConfigToMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"voiceConfig"})), toObject)); @@ -185,7 +172,6 @@ ObjectNode speechConfigToMldev( toObject, new String[] {"multiSpeakerVoiceConfig"}, multiSpeakerVoiceConfigToMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"multiSpeakerVoiceConfig"})), toObject)); @@ -202,15 +188,13 @@ ObjectNode speechConfigToMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode speechConfigToVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode speechConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"voiceConfig"}) != null) { Common.setValueByPath( toObject, new String[] {"voiceConfig"}, voiceConfigToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"voiceConfig"})), toObject)); @@ -233,8 +217,7 @@ ObjectNode speechConfigToVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode videoMetadataToMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode videoMetadataToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"fps"}) != null) { Common.setValueByPath( @@ -259,8 +242,7 @@ ObjectNode videoMetadataToMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode videoMetadataToVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode videoMetadataToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"fps"}) != null) { Common.setValueByPath( @@ -285,7 +267,7 @@ ObjectNode videoMetadataToVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode blobToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode blobToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"displayName"}))) { throw new IllegalArgumentException("displayName parameter is not supported in Gemini API."); @@ -309,7 +291,7 @@ ObjectNode blobToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode pare } @ExcludeFromGeneratedCoverageReport - ObjectNode blobToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode blobToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"displayName"}) != null) { Common.setValueByPath( @@ -336,7 +318,7 @@ ObjectNode blobToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode par } @ExcludeFromGeneratedCoverageReport - ObjectNode fileDataToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode fileDataToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"displayName"}))) { throw new IllegalArgumentException("displayName parameter is not supported in Gemini API."); @@ -360,7 +342,7 @@ ObjectNode fileDataToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode } @ExcludeFromGeneratedCoverageReport - ObjectNode fileDataToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode fileDataToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"displayName"}) != null) { Common.setValueByPath( @@ -387,14 +369,13 @@ ObjectNode fileDataToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode } @ExcludeFromGeneratedCoverageReport - ObjectNode partToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode partToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"videoMetadata"}) != null) { Common.setValueByPath( toObject, new String[] {"videoMetadata"}, videoMetadataToMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"videoMetadata"})), toObject)); @@ -412,7 +393,6 @@ ObjectNode partToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode pare toObject, new String[] {"inlineData"}, blobToMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"inlineData"})), toObject)); @@ -423,7 +403,6 @@ ObjectNode partToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode pare toObject, new String[] {"fileData"}, fileDataToMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"fileData"})), toObject)); @@ -475,14 +454,13 @@ ObjectNode partToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode pare } @ExcludeFromGeneratedCoverageReport - ObjectNode partToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode partToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"videoMetadata"}) != null) { Common.setValueByPath( toObject, new String[] {"videoMetadata"}, videoMetadataToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"videoMetadata"})), toObject)); @@ -500,7 +478,6 @@ ObjectNode partToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode par toObject, new String[] {"inlineData"}, blobToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"inlineData"})), toObject)); @@ -511,7 +488,6 @@ ObjectNode partToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode par toObject, new String[] {"fileData"}, fileDataToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"fileData"})), toObject)); @@ -563,7 +539,7 @@ ObjectNode partToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode par } @ExcludeFromGeneratedCoverageReport - ObjectNode contentToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode contentToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"parts"}) != null) { ArrayNode keyArray = (ArrayNode) Common.getValueByPath(fromObject, new String[] {"parts"}); @@ -571,7 +547,7 @@ ObjectNode contentToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode p ArrayNode result = objectMapper.createArrayNode(); for (JsonNode item : keyArray) { - result.add(partToMldev(apiClient, JsonSerializable.toJsonNode(item), toObject)); + result.add(partToMldev(JsonSerializable.toJsonNode(item), toObject)); } Common.setValueByPath(toObject, new String[] {"parts"}, result); } @@ -587,7 +563,7 @@ ObjectNode contentToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode p } @ExcludeFromGeneratedCoverageReport - ObjectNode contentToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode contentToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"parts"}) != null) { ArrayNode keyArray = (ArrayNode) Common.getValueByPath(fromObject, new String[] {"parts"}); @@ -595,7 +571,7 @@ ObjectNode contentToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode ArrayNode result = objectMapper.createArrayNode(); for (JsonNode item : keyArray) { - result.add(partToVertex(apiClient, JsonSerializable.toJsonNode(item), toObject)); + result.add(partToVertex(JsonSerializable.toJsonNode(item), toObject)); } Common.setValueByPath(toObject, new String[] {"parts"}, result); } @@ -611,8 +587,7 @@ ObjectNode contentToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode } @ExcludeFromGeneratedCoverageReport - ObjectNode functionDeclarationToMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode functionDeclarationToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"behavior"}) != null) { Common.setValueByPath( @@ -667,8 +642,7 @@ ObjectNode functionDeclarationToMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode functionDeclarationToVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode functionDeclarationToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"behavior"}))) { throw new IllegalArgumentException("behavior parameter is not supported in Vertex AI."); @@ -720,7 +694,7 @@ ObjectNode functionDeclarationToVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode intervalToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode intervalToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"startTime"}) != null) { Common.setValueByPath( @@ -740,7 +714,7 @@ ObjectNode intervalToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode } @ExcludeFromGeneratedCoverageReport - ObjectNode intervalToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode intervalToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"startTime"}) != null) { Common.setValueByPath( @@ -760,15 +734,13 @@ ObjectNode intervalToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode } @ExcludeFromGeneratedCoverageReport - ObjectNode googleSearchToMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode googleSearchToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"timeRangeFilter"}) != null) { Common.setValueByPath( toObject, new String[] {"timeRangeFilter"}, intervalToMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"timeRangeFilter"})), toObject)); @@ -778,15 +750,13 @@ ObjectNode googleSearchToMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode googleSearchToVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode googleSearchToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"timeRangeFilter"}) != null) { Common.setValueByPath( toObject, new String[] {"timeRangeFilter"}, intervalToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"timeRangeFilter"})), toObject)); @@ -796,8 +766,7 @@ ObjectNode googleSearchToVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode dynamicRetrievalConfigToMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode dynamicRetrievalConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"mode"}) != null) { Common.setValueByPath( @@ -817,8 +786,7 @@ ObjectNode dynamicRetrievalConfigToMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode dynamicRetrievalConfigToVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode dynamicRetrievalConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"mode"}) != null) { Common.setValueByPath( @@ -838,15 +806,13 @@ ObjectNode dynamicRetrievalConfigToVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode googleSearchRetrievalToMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode googleSearchRetrievalToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"dynamicRetrievalConfig"}) != null) { Common.setValueByPath( toObject, new String[] {"dynamicRetrievalConfig"}, dynamicRetrievalConfigToMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"dynamicRetrievalConfig"})), toObject)); @@ -856,15 +822,13 @@ ObjectNode googleSearchRetrievalToMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode googleSearchRetrievalToVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode googleSearchRetrievalToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"dynamicRetrievalConfig"}) != null) { Common.setValueByPath( toObject, new String[] {"dynamicRetrievalConfig"}, dynamicRetrievalConfigToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"dynamicRetrievalConfig"})), toObject)); @@ -874,24 +838,21 @@ ObjectNode googleSearchRetrievalToVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode enterpriseWebSearchToMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode enterpriseWebSearchToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); return toObject; } @ExcludeFromGeneratedCoverageReport - ObjectNode enterpriseWebSearchToVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode enterpriseWebSearchToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); return toObject; } @ExcludeFromGeneratedCoverageReport - ObjectNode apiKeyConfigToMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode apiKeyConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"apiKeyString"}))) { throw new IllegalArgumentException("apiKeyString parameter is not supported in Gemini API."); @@ -901,8 +862,7 @@ ObjectNode apiKeyConfigToMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode apiKeyConfigToVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode apiKeyConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"apiKeyString"}) != null) { Common.setValueByPath( @@ -915,7 +875,7 @@ ObjectNode apiKeyConfigToVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode authConfigToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode authConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"apiKeyConfig"}))) { throw new IllegalArgumentException("apiKeyConfig parameter is not supported in Gemini API."); @@ -960,14 +920,13 @@ ObjectNode authConfigToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNod } @ExcludeFromGeneratedCoverageReport - ObjectNode authConfigToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode authConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"apiKeyConfig"}) != null) { Common.setValueByPath( toObject, new String[] {"apiKeyConfig"}, apiKeyConfigToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"apiKeyConfig"})), toObject)); @@ -1012,7 +971,7 @@ ObjectNode authConfigToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNo } @ExcludeFromGeneratedCoverageReport - ObjectNode googleMapsToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode googleMapsToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"authConfig"}))) { throw new IllegalArgumentException("authConfig parameter is not supported in Gemini API."); @@ -1022,14 +981,13 @@ ObjectNode googleMapsToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNod } @ExcludeFromGeneratedCoverageReport - ObjectNode googleMapsToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode googleMapsToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"authConfig"}) != null) { Common.setValueByPath( toObject, new String[] {"authConfig"}, authConfigToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"authConfig"})), toObject)); @@ -1039,21 +997,21 @@ ObjectNode googleMapsToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNo } @ExcludeFromGeneratedCoverageReport - ObjectNode urlContextToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode urlContextToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); return toObject; } @ExcludeFromGeneratedCoverageReport - ObjectNode urlContextToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode urlContextToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); return toObject; } @ExcludeFromGeneratedCoverageReport - ObjectNode toolToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toolToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"functionDeclarations"}) != null) { ArrayNode keyArray = @@ -1062,8 +1020,7 @@ ObjectNode toolToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode pare ArrayNode result = objectMapper.createArrayNode(); for (JsonNode item : keyArray) { - result.add( - functionDeclarationToMldev(apiClient, JsonSerializable.toJsonNode(item), toObject)); + result.add(functionDeclarationToMldev(JsonSerializable.toJsonNode(item), toObject)); } Common.setValueByPath(toObject, new String[] {"functionDeclarations"}, result); } @@ -1077,7 +1034,6 @@ ObjectNode toolToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode pare toObject, new String[] {"googleSearch"}, googleSearchToMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"googleSearch"})), toObject)); @@ -1088,7 +1044,6 @@ ObjectNode toolToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode pare toObject, new String[] {"googleSearchRetrieval"}, googleSearchRetrievalToMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"googleSearchRetrieval"})), toObject)); @@ -1108,7 +1063,6 @@ ObjectNode toolToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode pare toObject, new String[] {"urlContext"}, urlContextToMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"urlContext"})), toObject)); @@ -1125,7 +1079,7 @@ ObjectNode toolToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode pare } @ExcludeFromGeneratedCoverageReport - ObjectNode toolToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toolToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"functionDeclarations"}) != null) { ArrayNode keyArray = @@ -1134,8 +1088,7 @@ ObjectNode toolToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode par ArrayNode result = objectMapper.createArrayNode(); for (JsonNode item : keyArray) { - result.add( - functionDeclarationToVertex(apiClient, JsonSerializable.toJsonNode(item), toObject)); + result.add(functionDeclarationToVertex(JsonSerializable.toJsonNode(item), toObject)); } Common.setValueByPath(toObject, new String[] {"functionDeclarations"}, result); } @@ -1152,7 +1105,6 @@ ObjectNode toolToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode par toObject, new String[] {"googleSearch"}, googleSearchToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"googleSearch"})), toObject)); @@ -1163,7 +1115,6 @@ ObjectNode toolToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode par toObject, new String[] {"googleSearchRetrieval"}, googleSearchRetrievalToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"googleSearchRetrieval"})), toObject)); @@ -1174,7 +1125,6 @@ ObjectNode toolToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode par toObject, new String[] {"enterpriseWebSearch"}, enterpriseWebSearchToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"enterpriseWebSearch"})), toObject)); @@ -1185,7 +1135,6 @@ ObjectNode toolToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode par toObject, new String[] {"googleMaps"}, googleMapsToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"googleMaps"})), toObject)); @@ -1196,7 +1145,6 @@ ObjectNode toolToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode par toObject, new String[] {"urlContext"}, urlContextToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"urlContext"})), toObject)); @@ -1213,8 +1161,7 @@ ObjectNode toolToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode par } @ExcludeFromGeneratedCoverageReport - ObjectNode sessionResumptionConfigToMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode sessionResumptionConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"handle"}) != null) { Common.setValueByPath( @@ -1231,8 +1178,7 @@ ObjectNode sessionResumptionConfigToMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode sessionResumptionConfigToVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode sessionResumptionConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"handle"}) != null) { Common.setValueByPath( @@ -1252,24 +1198,21 @@ ObjectNode sessionResumptionConfigToVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode audioTranscriptionConfigToMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode audioTranscriptionConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); return toObject; } @ExcludeFromGeneratedCoverageReport - ObjectNode audioTranscriptionConfigToVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode audioTranscriptionConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); return toObject; } @ExcludeFromGeneratedCoverageReport - ObjectNode automaticActivityDetectionToMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode automaticActivityDetectionToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"disabled"}) != null) { Common.setValueByPath( @@ -1310,8 +1253,7 @@ ObjectNode automaticActivityDetectionToMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode automaticActivityDetectionToVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode automaticActivityDetectionToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"disabled"}) != null) { Common.setValueByPath( @@ -1352,15 +1294,13 @@ ObjectNode automaticActivityDetectionToVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode realtimeInputConfigToMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode realtimeInputConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"automaticActivityDetection"}) != null) { Common.setValueByPath( toObject, new String[] {"automaticActivityDetection"}, automaticActivityDetectionToMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"automaticActivityDetection"})), toObject)); @@ -1384,15 +1324,13 @@ ObjectNode realtimeInputConfigToMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode realtimeInputConfigToVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode realtimeInputConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"automaticActivityDetection"}) != null) { Common.setValueByPath( toObject, new String[] {"automaticActivityDetection"}, automaticActivityDetectionToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"automaticActivityDetection"})), toObject)); @@ -1416,8 +1354,7 @@ ObjectNode realtimeInputConfigToVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode slidingWindowToMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode slidingWindowToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"targetTokens"}) != null) { Common.setValueByPath( @@ -1430,8 +1367,7 @@ ObjectNode slidingWindowToMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode slidingWindowToVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode slidingWindowToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"targetTokens"}) != null) { Common.setValueByPath( @@ -1444,8 +1380,7 @@ ObjectNode slidingWindowToVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode contextWindowCompressionConfigToMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode contextWindowCompressionConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"triggerTokens"}) != null) { Common.setValueByPath( @@ -1459,7 +1394,6 @@ ObjectNode contextWindowCompressionConfigToMldev( toObject, new String[] {"slidingWindow"}, slidingWindowToMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"slidingWindow"})), toObject)); @@ -1469,8 +1403,7 @@ ObjectNode contextWindowCompressionConfigToMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode contextWindowCompressionConfigToVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode contextWindowCompressionConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"triggerTokens"}) != null) { Common.setValueByPath( @@ -1484,7 +1417,6 @@ ObjectNode contextWindowCompressionConfigToVertex( toObject, new String[] {"slidingWindow"}, slidingWindowToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"slidingWindow"})), toObject)); @@ -1494,8 +1426,7 @@ ObjectNode contextWindowCompressionConfigToVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode proactivityConfigToMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode proactivityConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"proactiveAudio"}) != null) { Common.setValueByPath( @@ -1508,8 +1439,7 @@ ObjectNode proactivityConfigToMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode proactivityConfigToVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode proactivityConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"proactiveAudio"}) != null) { Common.setValueByPath( @@ -1522,8 +1452,7 @@ ObjectNode proactivityConfigToVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode liveConnectConfigToMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode liveConnectConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"responseModalities"}) != null) { @@ -1580,10 +1509,8 @@ ObjectNode liveConnectConfigToMldev( parentObject, new String[] {"setup", "generationConfig", "speechConfig"}, speechConfigToMldev( - apiClient, JsonSerializable.toJsonNode( Transformers.tLiveSpeechConfig( - this.apiClient, Common.getValueByPath(fromObject, new String[] {"speechConfig"}))), toObject)); } @@ -1600,10 +1527,8 @@ ObjectNode liveConnectConfigToMldev( parentObject, new String[] {"setup", "systemInstruction"}, contentToMldev( - apiClient, JsonSerializable.toJsonNode( Transformers.tContent( - this.apiClient, Common.getValueByPath(fromObject, new String[] {"systemInstruction"}))), toObject)); } @@ -1611,17 +1536,12 @@ ObjectNode liveConnectConfigToMldev( if (Common.getValueByPath(fromObject, new String[] {"tools"}) != null) { ArrayNode keyArray = (ArrayNode) - Transformers.tTools( - this.apiClient, Common.getValueByPath(fromObject, new String[] {"tools"})); + Transformers.tTools(Common.getValueByPath(fromObject, new String[] {"tools"})); ObjectMapper objectMapper = new ObjectMapper(); ArrayNode result = objectMapper.createArrayNode(); for (JsonNode item : keyArray) { - result.add( - toolToMldev( - apiClient, - JsonSerializable.toJsonNode(Transformers.tTool(this.apiClient, item)), - toObject)); + result.add(toolToMldev(JsonSerializable.toJsonNode(Transformers.tTool(item)), toObject)); } Common.setValueByPath(parentObject, new String[] {"setup", "tools"}, result); } @@ -1631,7 +1551,6 @@ ObjectNode liveConnectConfigToMldev( parentObject, new String[] {"setup", "sessionResumption"}, sessionResumptionConfigToMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"sessionResumption"})), toObject)); @@ -1642,7 +1561,6 @@ ObjectNode liveConnectConfigToMldev( parentObject, new String[] {"setup", "inputAudioTranscription"}, audioTranscriptionConfigToMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"inputAudioTranscription"})), toObject)); @@ -1653,7 +1571,6 @@ ObjectNode liveConnectConfigToMldev( parentObject, new String[] {"setup", "outputAudioTranscription"}, audioTranscriptionConfigToMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"outputAudioTranscription"})), toObject)); @@ -1664,7 +1581,6 @@ ObjectNode liveConnectConfigToMldev( parentObject, new String[] {"setup", "realtimeInputConfig"}, realtimeInputConfigToMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"realtimeInputConfig"})), toObject)); @@ -1675,7 +1591,6 @@ ObjectNode liveConnectConfigToMldev( parentObject, new String[] {"setup", "contextWindowCompression"}, contextWindowCompressionConfigToMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"contextWindowCompression"})), toObject)); @@ -1686,7 +1601,6 @@ ObjectNode liveConnectConfigToMldev( parentObject, new String[] {"setup", "proactivity"}, proactivityConfigToMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"proactivity"})), toObject)); @@ -1696,8 +1610,7 @@ ObjectNode liveConnectConfigToMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode liveConnectConfigToVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode liveConnectConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"responseModalities"}) != null) { @@ -1754,10 +1667,8 @@ ObjectNode liveConnectConfigToVertex( parentObject, new String[] {"setup", "generationConfig", "speechConfig"}, speechConfigToVertex( - apiClient, JsonSerializable.toJsonNode( Transformers.tLiveSpeechConfig( - this.apiClient, Common.getValueByPath(fromObject, new String[] {"speechConfig"}))), toObject)); } @@ -1774,10 +1685,8 @@ ObjectNode liveConnectConfigToVertex( parentObject, new String[] {"setup", "systemInstruction"}, contentToVertex( - apiClient, JsonSerializable.toJsonNode( Transformers.tContent( - this.apiClient, Common.getValueByPath(fromObject, new String[] {"systemInstruction"}))), toObject)); } @@ -1785,17 +1694,12 @@ ObjectNode liveConnectConfigToVertex( if (Common.getValueByPath(fromObject, new String[] {"tools"}) != null) { ArrayNode keyArray = (ArrayNode) - Transformers.tTools( - this.apiClient, Common.getValueByPath(fromObject, new String[] {"tools"})); + Transformers.tTools(Common.getValueByPath(fromObject, new String[] {"tools"})); ObjectMapper objectMapper = new ObjectMapper(); ArrayNode result = objectMapper.createArrayNode(); for (JsonNode item : keyArray) { - result.add( - toolToVertex( - apiClient, - JsonSerializable.toJsonNode(Transformers.tTool(this.apiClient, item)), - toObject)); + result.add(toolToVertex(JsonSerializable.toJsonNode(Transformers.tTool(item)), toObject)); } Common.setValueByPath(parentObject, new String[] {"setup", "tools"}, result); } @@ -1805,7 +1709,6 @@ ObjectNode liveConnectConfigToVertex( parentObject, new String[] {"setup", "sessionResumption"}, sessionResumptionConfigToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"sessionResumption"})), toObject)); @@ -1816,7 +1719,6 @@ ObjectNode liveConnectConfigToVertex( parentObject, new String[] {"setup", "inputAudioTranscription"}, audioTranscriptionConfigToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"inputAudioTranscription"})), toObject)); @@ -1827,7 +1729,6 @@ ObjectNode liveConnectConfigToVertex( parentObject, new String[] {"setup", "outputAudioTranscription"}, audioTranscriptionConfigToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"outputAudioTranscription"})), toObject)); @@ -1838,7 +1739,6 @@ ObjectNode liveConnectConfigToVertex( parentObject, new String[] {"setup", "realtimeInputConfig"}, realtimeInputConfigToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"realtimeInputConfig"})), toObject)); @@ -1849,7 +1749,6 @@ ObjectNode liveConnectConfigToVertex( parentObject, new String[] {"setup", "contextWindowCompression"}, contextWindowCompressionConfigToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"contextWindowCompression"})), toObject)); @@ -1860,7 +1759,6 @@ ObjectNode liveConnectConfigToVertex( parentObject, new String[] {"setup", "proactivity"}, proactivityConfigToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"proactivity"})), toObject)); @@ -1886,7 +1784,6 @@ ObjectNode liveConnectParametersToMldev( toObject, new String[] {"config"}, liveConnectConfigToMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"config"})), toObject)); @@ -1912,7 +1809,6 @@ ObjectNode liveConnectParametersToVertex( toObject, new String[] {"config"}, liveConnectConfigToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"config"})), toObject)); @@ -1922,54 +1818,48 @@ ObjectNode liveConnectParametersToVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode activityStartToMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode activityStartToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); return toObject; } @ExcludeFromGeneratedCoverageReport - ObjectNode activityStartToVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode activityStartToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); return toObject; } @ExcludeFromGeneratedCoverageReport - ObjectNode activityEndToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode activityEndToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); return toObject; } @ExcludeFromGeneratedCoverageReport - ObjectNode activityEndToVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode activityEndToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); return toObject; } @ExcludeFromGeneratedCoverageReport - ObjectNode liveSendRealtimeInputParametersToMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode liveSendRealtimeInputParametersToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"media"}) != null) { Common.setValueByPath( toObject, new String[] {"mediaChunks"}, - Transformers.tBlobs( - this.apiClient, Common.getValueByPath(fromObject, new String[] {"media"}))); + Transformers.tBlobs(Common.getValueByPath(fromObject, new String[] {"media"}))); } if (Common.getValueByPath(fromObject, new String[] {"audio"}) != null) { Common.setValueByPath( toObject, new String[] {"audio"}, - Transformers.tAudioBlob( - this.apiClient, Common.getValueByPath(fromObject, new String[] {"audio"}))); + Transformers.tAudioBlob(Common.getValueByPath(fromObject, new String[] {"audio"}))); } if (Common.getValueByPath(fromObject, new String[] {"audioStreamEnd"}) != null) { @@ -1983,8 +1873,7 @@ ObjectNode liveSendRealtimeInputParametersToMldev( Common.setValueByPath( toObject, new String[] {"video"}, - Transformers.tImageBlob( - this.apiClient, Common.getValueByPath(fromObject, new String[] {"video"}))); + Transformers.tImageBlob(Common.getValueByPath(fromObject, new String[] {"video"}))); } if (Common.getValueByPath(fromObject, new String[] {"text"}) != null) { @@ -1999,7 +1888,6 @@ ObjectNode liveSendRealtimeInputParametersToMldev( toObject, new String[] {"activityStart"}, activityStartToMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"activityStart"})), toObject)); @@ -2010,7 +1898,6 @@ ObjectNode liveSendRealtimeInputParametersToMldev( toObject, new String[] {"activityEnd"}, activityEndToMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"activityEnd"})), toObject)); @@ -2020,15 +1907,13 @@ ObjectNode liveSendRealtimeInputParametersToMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode liveSendRealtimeInputParametersToVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode liveSendRealtimeInputParametersToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"media"}) != null) { Common.setValueByPath( toObject, new String[] {"mediaChunks"}, - Transformers.tBlobs( - this.apiClient, Common.getValueByPath(fromObject, new String[] {"media"}))); + Transformers.tBlobs(Common.getValueByPath(fromObject, new String[] {"media"}))); } if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"audio"}))) { @@ -2055,7 +1940,6 @@ ObjectNode liveSendRealtimeInputParametersToVertex( toObject, new String[] {"activityStart"}, activityStartToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"activityStart"})), toObject)); @@ -2066,7 +1950,6 @@ ObjectNode liveSendRealtimeInputParametersToVertex( toObject, new String[] {"activityEnd"}, activityEndToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"activityEnd"})), toObject)); @@ -2076,8 +1959,7 @@ ObjectNode liveSendRealtimeInputParametersToVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode liveClientSetupToMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode liveClientSetupToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"model"}) != null) { Common.setValueByPath( @@ -2098,10 +1980,8 @@ ObjectNode liveClientSetupToMldev( toObject, new String[] {"systemInstruction"}, contentToMldev( - apiClient, JsonSerializable.toJsonNode( Transformers.tContent( - this.apiClient, Common.getValueByPath(fromObject, new String[] {"systemInstruction"}))), toObject)); } @@ -2109,17 +1989,12 @@ ObjectNode liveClientSetupToMldev( if (Common.getValueByPath(fromObject, new String[] {"tools"}) != null) { ArrayNode keyArray = (ArrayNode) - Transformers.tTools( - this.apiClient, Common.getValueByPath(fromObject, new String[] {"tools"})); + Transformers.tTools(Common.getValueByPath(fromObject, new String[] {"tools"})); ObjectMapper objectMapper = new ObjectMapper(); ArrayNode result = objectMapper.createArrayNode(); for (JsonNode item : keyArray) { - result.add( - toolToMldev( - apiClient, - JsonSerializable.toJsonNode(Transformers.tTool(this.apiClient, item)), - toObject)); + result.add(toolToMldev(JsonSerializable.toJsonNode(Transformers.tTool(item)), toObject)); } Common.setValueByPath(toObject, new String[] {"tools"}, result); } @@ -2129,7 +2004,6 @@ ObjectNode liveClientSetupToMldev( toObject, new String[] {"realtimeInputConfig"}, realtimeInputConfigToMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"realtimeInputConfig"})), toObject)); @@ -2140,7 +2014,6 @@ ObjectNode liveClientSetupToMldev( toObject, new String[] {"sessionResumption"}, sessionResumptionConfigToMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"sessionResumption"})), toObject)); @@ -2151,7 +2024,6 @@ ObjectNode liveClientSetupToMldev( toObject, new String[] {"contextWindowCompression"}, contextWindowCompressionConfigToMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"contextWindowCompression"})), toObject)); @@ -2162,7 +2034,6 @@ ObjectNode liveClientSetupToMldev( toObject, new String[] {"inputAudioTranscription"}, audioTranscriptionConfigToMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"inputAudioTranscription"})), toObject)); @@ -2173,7 +2044,6 @@ ObjectNode liveClientSetupToMldev( toObject, new String[] {"outputAudioTranscription"}, audioTranscriptionConfigToMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"outputAudioTranscription"})), toObject)); @@ -2184,7 +2054,6 @@ ObjectNode liveClientSetupToMldev( toObject, new String[] {"proactivity"}, proactivityConfigToMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"proactivity"})), toObject)); @@ -2194,8 +2063,7 @@ ObjectNode liveClientSetupToMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode liveClientSetupToVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode liveClientSetupToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"model"}) != null) { Common.setValueByPath( @@ -2216,10 +2084,8 @@ ObjectNode liveClientSetupToVertex( toObject, new String[] {"systemInstruction"}, contentToVertex( - apiClient, JsonSerializable.toJsonNode( Transformers.tContent( - this.apiClient, Common.getValueByPath(fromObject, new String[] {"systemInstruction"}))), toObject)); } @@ -2227,17 +2093,12 @@ ObjectNode liveClientSetupToVertex( if (Common.getValueByPath(fromObject, new String[] {"tools"}) != null) { ArrayNode keyArray = (ArrayNode) - Transformers.tTools( - this.apiClient, Common.getValueByPath(fromObject, new String[] {"tools"})); + Transformers.tTools(Common.getValueByPath(fromObject, new String[] {"tools"})); ObjectMapper objectMapper = new ObjectMapper(); ArrayNode result = objectMapper.createArrayNode(); for (JsonNode item : keyArray) { - result.add( - toolToVertex( - apiClient, - JsonSerializable.toJsonNode(Transformers.tTool(this.apiClient, item)), - toObject)); + result.add(toolToVertex(JsonSerializable.toJsonNode(Transformers.tTool(item)), toObject)); } Common.setValueByPath(toObject, new String[] {"tools"}, result); } @@ -2247,7 +2108,6 @@ ObjectNode liveClientSetupToVertex( toObject, new String[] {"realtimeInputConfig"}, realtimeInputConfigToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"realtimeInputConfig"})), toObject)); @@ -2258,7 +2118,6 @@ ObjectNode liveClientSetupToVertex( toObject, new String[] {"sessionResumption"}, sessionResumptionConfigToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"sessionResumption"})), toObject)); @@ -2269,7 +2128,6 @@ ObjectNode liveClientSetupToVertex( toObject, new String[] {"contextWindowCompression"}, contextWindowCompressionConfigToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"contextWindowCompression"})), toObject)); @@ -2280,7 +2138,6 @@ ObjectNode liveClientSetupToVertex( toObject, new String[] {"inputAudioTranscription"}, audioTranscriptionConfigToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"inputAudioTranscription"})), toObject)); @@ -2291,7 +2148,6 @@ ObjectNode liveClientSetupToVertex( toObject, new String[] {"outputAudioTranscription"}, audioTranscriptionConfigToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"outputAudioTranscription"})), toObject)); @@ -2302,7 +2158,6 @@ ObjectNode liveClientSetupToVertex( toObject, new String[] {"proactivity"}, proactivityConfigToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"proactivity"})), toObject)); @@ -2312,8 +2167,7 @@ ObjectNode liveClientSetupToVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode liveClientContentToMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode liveClientContentToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"turns"}) != null) { ArrayNode keyArray = (ArrayNode) Common.getValueByPath(fromObject, new String[] {"turns"}); @@ -2321,7 +2175,7 @@ ObjectNode liveClientContentToMldev( ArrayNode result = objectMapper.createArrayNode(); for (JsonNode item : keyArray) { - result.add(contentToMldev(apiClient, JsonSerializable.toJsonNode(item), toObject)); + result.add(contentToMldev(JsonSerializable.toJsonNode(item), toObject)); } Common.setValueByPath(toObject, new String[] {"turns"}, result); } @@ -2337,8 +2191,7 @@ ObjectNode liveClientContentToMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode liveClientContentToVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode liveClientContentToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"turns"}) != null) { ArrayNode keyArray = (ArrayNode) Common.getValueByPath(fromObject, new String[] {"turns"}); @@ -2346,7 +2199,7 @@ ObjectNode liveClientContentToVertex( ArrayNode result = objectMapper.createArrayNode(); for (JsonNode item : keyArray) { - result.add(contentToVertex(apiClient, JsonSerializable.toJsonNode(item), toObject)); + result.add(contentToVertex(JsonSerializable.toJsonNode(item), toObject)); } Common.setValueByPath(toObject, new String[] {"turns"}, result); } @@ -2362,8 +2215,7 @@ ObjectNode liveClientContentToVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode liveClientRealtimeInputToMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode liveClientRealtimeInputToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"mediaChunks"}) != null) { Common.setValueByPath( @@ -2405,7 +2257,6 @@ ObjectNode liveClientRealtimeInputToMldev( toObject, new String[] {"activityStart"}, activityStartToMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"activityStart"})), toObject)); @@ -2416,7 +2267,6 @@ ObjectNode liveClientRealtimeInputToMldev( toObject, new String[] {"activityEnd"}, activityEndToMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"activityEnd"})), toObject)); @@ -2426,8 +2276,7 @@ ObjectNode liveClientRealtimeInputToMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode liveClientRealtimeInputToVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode liveClientRealtimeInputToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"mediaChunks"}) != null) { Common.setValueByPath( @@ -2457,7 +2306,6 @@ ObjectNode liveClientRealtimeInputToVertex( toObject, new String[] {"activityStart"}, activityStartToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"activityStart"})), toObject)); @@ -2468,7 +2316,6 @@ ObjectNode liveClientRealtimeInputToVertex( toObject, new String[] {"activityEnd"}, activityEndToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"activityEnd"})), toObject)); @@ -2478,8 +2325,7 @@ ObjectNode liveClientRealtimeInputToVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode functionResponseToMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode functionResponseToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"willContinue"}) != null) { Common.setValueByPath( @@ -2518,8 +2364,7 @@ ObjectNode functionResponseToMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode functionResponseToVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode functionResponseToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"willContinue"}))) { throw new IllegalArgumentException("willContinue parameter is not supported in Vertex AI."); @@ -2552,8 +2397,7 @@ ObjectNode functionResponseToVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode liveClientToolResponseToMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode liveClientToolResponseToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"functionResponses"}) != null) { ArrayNode keyArray = @@ -2562,7 +2406,7 @@ ObjectNode liveClientToolResponseToMldev( ArrayNode result = objectMapper.createArrayNode(); for (JsonNode item : keyArray) { - result.add(functionResponseToMldev(apiClient, JsonSerializable.toJsonNode(item), toObject)); + result.add(functionResponseToMldev(JsonSerializable.toJsonNode(item), toObject)); } Common.setValueByPath(toObject, new String[] {"functionResponses"}, result); } @@ -2571,8 +2415,7 @@ ObjectNode liveClientToolResponseToMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode liveClientToolResponseToVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode liveClientToolResponseToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"functionResponses"}) != null) { ArrayNode keyArray = @@ -2581,8 +2424,7 @@ ObjectNode liveClientToolResponseToVertex( ArrayNode result = objectMapper.createArrayNode(); for (JsonNode item : keyArray) { - result.add( - functionResponseToVertex(apiClient, JsonSerializable.toJsonNode(item), toObject)); + result.add(functionResponseToVertex(JsonSerializable.toJsonNode(item), toObject)); } Common.setValueByPath(toObject, new String[] {"functionResponses"}, result); } @@ -2591,15 +2433,13 @@ ObjectNode liveClientToolResponseToVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode liveClientMessageToMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode liveClientMessageToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"setup"}) != null) { Common.setValueByPath( toObject, new String[] {"setup"}, liveClientSetupToMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"setup"})), toObject)); @@ -2610,7 +2450,6 @@ ObjectNode liveClientMessageToMldev( toObject, new String[] {"clientContent"}, liveClientContentToMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"clientContent"})), toObject)); @@ -2621,7 +2460,6 @@ ObjectNode liveClientMessageToMldev( toObject, new String[] {"realtimeInput"}, liveClientRealtimeInputToMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"realtimeInput"})), toObject)); @@ -2632,7 +2470,6 @@ ObjectNode liveClientMessageToMldev( toObject, new String[] {"realtime_input"}, liveSendRealtimeInputParametersToMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"realtimeInputParameters"})), toObject)); @@ -2643,7 +2480,6 @@ ObjectNode liveClientMessageToMldev( toObject, new String[] {"toolResponse"}, liveClientToolResponseToMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"toolResponse"})), toObject)); @@ -2653,15 +2489,13 @@ ObjectNode liveClientMessageToMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode liveClientMessageToVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode liveClientMessageToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"setup"}) != null) { Common.setValueByPath( toObject, new String[] {"setup"}, liveClientSetupToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"setup"})), toObject)); @@ -2672,7 +2506,6 @@ ObjectNode liveClientMessageToVertex( toObject, new String[] {"clientContent"}, liveClientContentToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"clientContent"})), toObject)); @@ -2683,7 +2516,6 @@ ObjectNode liveClientMessageToVertex( toObject, new String[] {"realtimeInput"}, liveClientRealtimeInputToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"realtimeInput"})), toObject)); @@ -2694,7 +2526,6 @@ ObjectNode liveClientMessageToVertex( toObject, new String[] {"realtime_input"}, liveSendRealtimeInputParametersToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"realtimeInputParameters"})), toObject)); @@ -2705,7 +2536,6 @@ ObjectNode liveClientMessageToVertex( toObject, new String[] {"toolResponse"}, liveClientToolResponseToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"toolResponse"})), toObject)); @@ -2715,24 +2545,21 @@ ObjectNode liveClientMessageToVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode liveServerSetupCompleteFromMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode liveServerSetupCompleteFromMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); return toObject; } @ExcludeFromGeneratedCoverageReport - ObjectNode liveServerSetupCompleteFromVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode liveServerSetupCompleteFromVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); return toObject; } @ExcludeFromGeneratedCoverageReport - ObjectNode videoMetadataFromMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode videoMetadataFromMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"fps"}) != null) { Common.setValueByPath( @@ -2757,8 +2584,7 @@ ObjectNode videoMetadataFromMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode videoMetadataFromVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode videoMetadataFromVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"fps"}) != null) { Common.setValueByPath( @@ -2783,7 +2609,7 @@ ObjectNode videoMetadataFromVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode blobFromMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode blobFromMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"data"}) != null) { @@ -2804,7 +2630,7 @@ ObjectNode blobFromMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode pa } @ExcludeFromGeneratedCoverageReport - ObjectNode blobFromVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode blobFromVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"displayName"}) != null) { Common.setValueByPath( @@ -2831,7 +2657,7 @@ ObjectNode blobFromVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode p } @ExcludeFromGeneratedCoverageReport - ObjectNode fileDataFromMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode fileDataFromMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"fileUri"}) != null) { @@ -2852,7 +2678,7 @@ ObjectNode fileDataFromMldev(ApiClient apiClient, JsonNode fromObject, ObjectNod } @ExcludeFromGeneratedCoverageReport - ObjectNode fileDataFromVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode fileDataFromVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"displayName"}) != null) { Common.setValueByPath( @@ -2879,14 +2705,13 @@ ObjectNode fileDataFromVertex(ApiClient apiClient, JsonNode fromObject, ObjectNo } @ExcludeFromGeneratedCoverageReport - ObjectNode partFromMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode partFromMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"videoMetadata"}) != null) { Common.setValueByPath( toObject, new String[] {"videoMetadata"}, videoMetadataFromMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"videoMetadata"})), toObject)); @@ -2904,7 +2729,6 @@ ObjectNode partFromMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode pa toObject, new String[] {"inlineData"}, blobFromMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"inlineData"})), toObject)); @@ -2915,7 +2739,6 @@ ObjectNode partFromMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode pa toObject, new String[] {"fileData"}, fileDataFromMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"fileData"})), toObject)); @@ -2967,14 +2790,13 @@ ObjectNode partFromMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode pa } @ExcludeFromGeneratedCoverageReport - ObjectNode partFromVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode partFromVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"videoMetadata"}) != null) { Common.setValueByPath( toObject, new String[] {"videoMetadata"}, videoMetadataFromVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"videoMetadata"})), toObject)); @@ -2992,7 +2814,6 @@ ObjectNode partFromVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode p toObject, new String[] {"inlineData"}, blobFromVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"inlineData"})), toObject)); @@ -3003,7 +2824,6 @@ ObjectNode partFromVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode p toObject, new String[] {"fileData"}, fileDataFromVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"fileData"})), toObject)); @@ -3055,7 +2875,7 @@ ObjectNode partFromVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode p } @ExcludeFromGeneratedCoverageReport - ObjectNode contentFromMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode contentFromMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"parts"}) != null) { ArrayNode keyArray = (ArrayNode) Common.getValueByPath(fromObject, new String[] {"parts"}); @@ -3063,7 +2883,7 @@ ObjectNode contentFromMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode ArrayNode result = objectMapper.createArrayNode(); for (JsonNode item : keyArray) { - result.add(partFromMldev(apiClient, JsonSerializable.toJsonNode(item), toObject)); + result.add(partFromMldev(JsonSerializable.toJsonNode(item), toObject)); } Common.setValueByPath(toObject, new String[] {"parts"}, result); } @@ -3079,7 +2899,7 @@ ObjectNode contentFromMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode } @ExcludeFromGeneratedCoverageReport - ObjectNode contentFromVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode contentFromVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"parts"}) != null) { ArrayNode keyArray = (ArrayNode) Common.getValueByPath(fromObject, new String[] {"parts"}); @@ -3087,7 +2907,7 @@ ObjectNode contentFromVertex(ApiClient apiClient, JsonNode fromObject, ObjectNod ArrayNode result = objectMapper.createArrayNode(); for (JsonNode item : keyArray) { - result.add(partFromVertex(apiClient, JsonSerializable.toJsonNode(item), toObject)); + result.add(partFromVertex(JsonSerializable.toJsonNode(item), toObject)); } Common.setValueByPath(toObject, new String[] {"parts"}, result); } @@ -3103,8 +2923,7 @@ ObjectNode contentFromVertex(ApiClient apiClient, JsonNode fromObject, ObjectNod } @ExcludeFromGeneratedCoverageReport - ObjectNode transcriptionFromMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode transcriptionFromMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"text"}) != null) { Common.setValueByPath( @@ -3124,8 +2943,7 @@ ObjectNode transcriptionFromMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode transcriptionFromVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode transcriptionFromVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"text"}) != null) { Common.setValueByPath( @@ -3145,8 +2963,7 @@ ObjectNode transcriptionFromVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode urlMetadataFromMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode urlMetadataFromMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"retrievedUrl"}) != null) { Common.setValueByPath( @@ -3166,8 +2983,7 @@ ObjectNode urlMetadataFromMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode urlMetadataFromVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode urlMetadataFromVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"retrievedUrl"}) != null) { Common.setValueByPath( @@ -3187,8 +3003,7 @@ ObjectNode urlMetadataFromVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode urlContextMetadataFromMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode urlContextMetadataFromMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"urlMetadata"}) != null) { ArrayNode keyArray = @@ -3197,7 +3012,7 @@ ObjectNode urlContextMetadataFromMldev( ArrayNode result = objectMapper.createArrayNode(); for (JsonNode item : keyArray) { - result.add(urlMetadataFromMldev(apiClient, JsonSerializable.toJsonNode(item), toObject)); + result.add(urlMetadataFromMldev(JsonSerializable.toJsonNode(item), toObject)); } Common.setValueByPath(toObject, new String[] {"urlMetadata"}, result); } @@ -3206,8 +3021,7 @@ ObjectNode urlContextMetadataFromMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode urlContextMetadataFromVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode urlContextMetadataFromVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"urlMetadata"}) != null) { ArrayNode keyArray = @@ -3216,7 +3030,7 @@ ObjectNode urlContextMetadataFromVertex( ArrayNode result = objectMapper.createArrayNode(); for (JsonNode item : keyArray) { - result.add(urlMetadataFromVertex(apiClient, JsonSerializable.toJsonNode(item), toObject)); + result.add(urlMetadataFromVertex(JsonSerializable.toJsonNode(item), toObject)); } Common.setValueByPath(toObject, new String[] {"urlMetadata"}, result); } @@ -3225,15 +3039,13 @@ ObjectNode urlContextMetadataFromVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode liveServerContentFromMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode liveServerContentFromMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"modelTurn"}) != null) { Common.setValueByPath( toObject, new String[] {"modelTurn"}, contentFromMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"modelTurn"})), toObject)); @@ -3272,7 +3084,6 @@ ObjectNode liveServerContentFromMldev( toObject, new String[] {"inputTranscription"}, transcriptionFromMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"inputTranscription"})), toObject)); @@ -3283,7 +3094,6 @@ ObjectNode liveServerContentFromMldev( toObject, new String[] {"outputTranscription"}, transcriptionFromMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"outputTranscription"})), toObject)); @@ -3294,7 +3104,6 @@ ObjectNode liveServerContentFromMldev( toObject, new String[] {"urlContextMetadata"}, urlContextMetadataFromMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"urlContextMetadata"})), toObject)); @@ -3304,15 +3113,13 @@ ObjectNode liveServerContentFromMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode liveServerContentFromVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode liveServerContentFromVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"modelTurn"}) != null) { Common.setValueByPath( toObject, new String[] {"modelTurn"}, contentFromVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"modelTurn"})), toObject)); @@ -3351,7 +3158,6 @@ ObjectNode liveServerContentFromVertex( toObject, new String[] {"inputTranscription"}, transcriptionFromVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"inputTranscription"})), toObject)); @@ -3362,7 +3168,6 @@ ObjectNode liveServerContentFromVertex( toObject, new String[] {"outputTranscription"}, transcriptionFromVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"outputTranscription"})), toObject)); @@ -3372,8 +3177,7 @@ ObjectNode liveServerContentFromVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode functionCallFromMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode functionCallFromMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"id"}) != null) { Common.setValueByPath( @@ -3398,8 +3202,7 @@ ObjectNode functionCallFromMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode functionCallFromVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode functionCallFromVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"args"}) != null) { @@ -3420,8 +3223,7 @@ ObjectNode functionCallFromVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode liveServerToolCallFromMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode liveServerToolCallFromMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"functionCalls"}) != null) { ArrayNode keyArray = @@ -3430,7 +3232,7 @@ ObjectNode liveServerToolCallFromMldev( ArrayNode result = objectMapper.createArrayNode(); for (JsonNode item : keyArray) { - result.add(functionCallFromMldev(apiClient, JsonSerializable.toJsonNode(item), toObject)); + result.add(functionCallFromMldev(JsonSerializable.toJsonNode(item), toObject)); } Common.setValueByPath(toObject, new String[] {"functionCalls"}, result); } @@ -3439,8 +3241,7 @@ ObjectNode liveServerToolCallFromMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode liveServerToolCallFromVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode liveServerToolCallFromVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"functionCalls"}) != null) { ArrayNode keyArray = @@ -3449,7 +3250,7 @@ ObjectNode liveServerToolCallFromVertex( ArrayNode result = objectMapper.createArrayNode(); for (JsonNode item : keyArray) { - result.add(functionCallFromVertex(apiClient, JsonSerializable.toJsonNode(item), toObject)); + result.add(functionCallFromVertex(JsonSerializable.toJsonNode(item), toObject)); } Common.setValueByPath(toObject, new String[] {"functionCalls"}, result); } @@ -3458,8 +3259,7 @@ ObjectNode liveServerToolCallFromVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode liveServerToolCallCancellationFromMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode liveServerToolCallCancellationFromMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"ids"}) != null) { Common.setValueByPath( @@ -3471,7 +3271,7 @@ ObjectNode liveServerToolCallCancellationFromMldev( @ExcludeFromGeneratedCoverageReport ObjectNode liveServerToolCallCancellationFromVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"ids"}) != null) { Common.setValueByPath( @@ -3482,8 +3282,7 @@ ObjectNode liveServerToolCallCancellationFromVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode modalityTokenCountFromMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode modalityTokenCountFromMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"modality"}) != null) { Common.setValueByPath( @@ -3503,8 +3302,7 @@ ObjectNode modalityTokenCountFromMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode modalityTokenCountFromVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode modalityTokenCountFromVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"modality"}) != null) { Common.setValueByPath( @@ -3524,8 +3322,7 @@ ObjectNode modalityTokenCountFromVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode usageMetadataFromMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode usageMetadataFromMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"promptTokenCount"}) != null) { Common.setValueByPath( @@ -3576,8 +3373,7 @@ ObjectNode usageMetadataFromMldev( ArrayNode result = objectMapper.createArrayNode(); for (JsonNode item : keyArray) { - result.add( - modalityTokenCountFromMldev(apiClient, JsonSerializable.toJsonNode(item), toObject)); + result.add(modalityTokenCountFromMldev(JsonSerializable.toJsonNode(item), toObject)); } Common.setValueByPath(toObject, new String[] {"promptTokensDetails"}, result); } @@ -3589,8 +3385,7 @@ ObjectNode usageMetadataFromMldev( ArrayNode result = objectMapper.createArrayNode(); for (JsonNode item : keyArray) { - result.add( - modalityTokenCountFromMldev(apiClient, JsonSerializable.toJsonNode(item), toObject)); + result.add(modalityTokenCountFromMldev(JsonSerializable.toJsonNode(item), toObject)); } Common.setValueByPath(toObject, new String[] {"cacheTokensDetails"}, result); } @@ -3602,8 +3397,7 @@ ObjectNode usageMetadataFromMldev( ArrayNode result = objectMapper.createArrayNode(); for (JsonNode item : keyArray) { - result.add( - modalityTokenCountFromMldev(apiClient, JsonSerializable.toJsonNode(item), toObject)); + result.add(modalityTokenCountFromMldev(JsonSerializable.toJsonNode(item), toObject)); } Common.setValueByPath(toObject, new String[] {"responseTokensDetails"}, result); } @@ -3616,8 +3410,7 @@ ObjectNode usageMetadataFromMldev( ArrayNode result = objectMapper.createArrayNode(); for (JsonNode item : keyArray) { - result.add( - modalityTokenCountFromMldev(apiClient, JsonSerializable.toJsonNode(item), toObject)); + result.add(modalityTokenCountFromMldev(JsonSerializable.toJsonNode(item), toObject)); } Common.setValueByPath(toObject, new String[] {"toolUsePromptTokensDetails"}, result); } @@ -3626,8 +3419,7 @@ ObjectNode usageMetadataFromMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode usageMetadataFromVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode usageMetadataFromVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"promptTokenCount"}) != null) { Common.setValueByPath( @@ -3678,8 +3470,7 @@ ObjectNode usageMetadataFromVertex( ArrayNode result = objectMapper.createArrayNode(); for (JsonNode item : keyArray) { - result.add( - modalityTokenCountFromVertex(apiClient, JsonSerializable.toJsonNode(item), toObject)); + result.add(modalityTokenCountFromVertex(JsonSerializable.toJsonNode(item), toObject)); } Common.setValueByPath(toObject, new String[] {"promptTokensDetails"}, result); } @@ -3691,8 +3482,7 @@ ObjectNode usageMetadataFromVertex( ArrayNode result = objectMapper.createArrayNode(); for (JsonNode item : keyArray) { - result.add( - modalityTokenCountFromVertex(apiClient, JsonSerializable.toJsonNode(item), toObject)); + result.add(modalityTokenCountFromVertex(JsonSerializable.toJsonNode(item), toObject)); } Common.setValueByPath(toObject, new String[] {"cacheTokensDetails"}, result); } @@ -3704,8 +3494,7 @@ ObjectNode usageMetadataFromVertex( ArrayNode result = objectMapper.createArrayNode(); for (JsonNode item : keyArray) { - result.add( - modalityTokenCountFromVertex(apiClient, JsonSerializable.toJsonNode(item), toObject)); + result.add(modalityTokenCountFromVertex(JsonSerializable.toJsonNode(item), toObject)); } Common.setValueByPath(toObject, new String[] {"responseTokensDetails"}, result); } @@ -3718,8 +3507,7 @@ ObjectNode usageMetadataFromVertex( ArrayNode result = objectMapper.createArrayNode(); for (JsonNode item : keyArray) { - result.add( - modalityTokenCountFromVertex(apiClient, JsonSerializable.toJsonNode(item), toObject)); + result.add(modalityTokenCountFromVertex(JsonSerializable.toJsonNode(item), toObject)); } Common.setValueByPath(toObject, new String[] {"toolUsePromptTokensDetails"}, result); } @@ -3735,8 +3523,7 @@ ObjectNode usageMetadataFromVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode liveServerGoAwayFromMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode liveServerGoAwayFromMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"timeLeft"}) != null) { Common.setValueByPath( @@ -3749,8 +3536,7 @@ ObjectNode liveServerGoAwayFromMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode liveServerGoAwayFromVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode liveServerGoAwayFromVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"timeLeft"}) != null) { Common.setValueByPath( @@ -3764,7 +3550,7 @@ ObjectNode liveServerGoAwayFromVertex( @ExcludeFromGeneratedCoverageReport ObjectNode liveServerSessionResumptionUpdateFromMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"newHandle"}) != null) { Common.setValueByPath( @@ -3793,7 +3579,7 @@ ObjectNode liveServerSessionResumptionUpdateFromMldev( @ExcludeFromGeneratedCoverageReport ObjectNode liveServerSessionResumptionUpdateFromVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"newHandle"}) != null) { Common.setValueByPath( @@ -3821,15 +3607,13 @@ ObjectNode liveServerSessionResumptionUpdateFromVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode liveServerMessageFromMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode liveServerMessageFromMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"setupComplete"}) != null) { Common.setValueByPath( toObject, new String[] {"setupComplete"}, liveServerSetupCompleteFromMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"setupComplete"})), toObject)); @@ -3840,7 +3624,6 @@ ObjectNode liveServerMessageFromMldev( toObject, new String[] {"serverContent"}, liveServerContentFromMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"serverContent"})), toObject)); @@ -3851,7 +3634,6 @@ ObjectNode liveServerMessageFromMldev( toObject, new String[] {"toolCall"}, liveServerToolCallFromMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"toolCall"})), toObject)); @@ -3862,7 +3644,6 @@ ObjectNode liveServerMessageFromMldev( toObject, new String[] {"toolCallCancellation"}, liveServerToolCallCancellationFromMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"toolCallCancellation"})), toObject)); @@ -3873,7 +3654,6 @@ ObjectNode liveServerMessageFromMldev( toObject, new String[] {"usageMetadata"}, usageMetadataFromMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"usageMetadata"})), toObject)); @@ -3884,7 +3664,6 @@ ObjectNode liveServerMessageFromMldev( toObject, new String[] {"goAway"}, liveServerGoAwayFromMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"goAway"})), toObject)); @@ -3895,7 +3674,6 @@ ObjectNode liveServerMessageFromMldev( toObject, new String[] {"sessionResumptionUpdate"}, liveServerSessionResumptionUpdateFromMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"sessionResumptionUpdate"})), toObject)); @@ -3905,15 +3683,13 @@ ObjectNode liveServerMessageFromMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode liveServerMessageFromVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode liveServerMessageFromVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"setupComplete"}) != null) { Common.setValueByPath( toObject, new String[] {"setupComplete"}, liveServerSetupCompleteFromVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"setupComplete"})), toObject)); @@ -3924,7 +3700,6 @@ ObjectNode liveServerMessageFromVertex( toObject, new String[] {"serverContent"}, liveServerContentFromVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"serverContent"})), toObject)); @@ -3935,7 +3710,6 @@ ObjectNode liveServerMessageFromVertex( toObject, new String[] {"toolCall"}, liveServerToolCallFromVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"toolCall"})), toObject)); @@ -3946,7 +3720,6 @@ ObjectNode liveServerMessageFromVertex( toObject, new String[] {"toolCallCancellation"}, liveServerToolCallCancellationFromVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"toolCallCancellation"})), toObject)); @@ -3957,7 +3730,6 @@ ObjectNode liveServerMessageFromVertex( toObject, new String[] {"usageMetadata"}, usageMetadataFromVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"usageMetadata"})), toObject)); @@ -3968,7 +3740,6 @@ ObjectNode liveServerMessageFromVertex( toObject, new String[] {"goAway"}, liveServerGoAwayFromVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"goAway"})), toObject)); @@ -3979,7 +3750,6 @@ ObjectNode liveServerMessageFromVertex( toObject, new String[] {"sessionResumptionUpdate"}, liveServerSessionResumptionUpdateFromVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"sessionResumptionUpdate"})), toObject)); diff --git a/src/main/java/com/google/genai/Models.java b/src/main/java/com/google/genai/Models.java index ed195e735fc..a1f643d432c 100644 --- a/src/main/java/com/google/genai/Models.java +++ b/src/main/java/com/google/genai/Models.java @@ -93,8 +93,7 @@ public Models(ApiClient apiClient) { } @ExcludeFromGeneratedCoverageReport - ObjectNode videoMetadataToMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode videoMetadataToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"fps"}) != null) { Common.setValueByPath( @@ -119,7 +118,7 @@ ObjectNode videoMetadataToMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode blobToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode blobToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"displayName"}))) { throw new IllegalArgumentException("displayName parameter is not supported in Gemini API."); @@ -143,7 +142,7 @@ ObjectNode blobToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode pare } @ExcludeFromGeneratedCoverageReport - ObjectNode fileDataToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode fileDataToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"displayName"}))) { throw new IllegalArgumentException("displayName parameter is not supported in Gemini API."); @@ -167,14 +166,13 @@ ObjectNode fileDataToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode } @ExcludeFromGeneratedCoverageReport - ObjectNode partToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode partToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"videoMetadata"}) != null) { Common.setValueByPath( toObject, new String[] {"videoMetadata"}, videoMetadataToMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"videoMetadata"})), toObject)); @@ -192,7 +190,6 @@ ObjectNode partToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode pare toObject, new String[] {"inlineData"}, blobToMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"inlineData"})), toObject)); @@ -203,7 +200,6 @@ ObjectNode partToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode pare toObject, new String[] {"fileData"}, fileDataToMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"fileData"})), toObject)); @@ -255,7 +251,7 @@ ObjectNode partToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode pare } @ExcludeFromGeneratedCoverageReport - ObjectNode contentToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode contentToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"parts"}) != null) { ArrayNode keyArray = (ArrayNode) Common.getValueByPath(fromObject, new String[] {"parts"}); @@ -263,7 +259,7 @@ ObjectNode contentToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode p ArrayNode result = objectMapper.createArrayNode(); for (JsonNode item : keyArray) { - result.add(partToMldev(apiClient, JsonSerializable.toJsonNode(item), toObject)); + result.add(partToMldev(JsonSerializable.toJsonNode(item), toObject)); } Common.setValueByPath(toObject, new String[] {"parts"}, result); } @@ -279,7 +275,7 @@ ObjectNode contentToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode p } @ExcludeFromGeneratedCoverageReport - ObjectNode schemaToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode schemaToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"anyOf"}) != null) { @@ -440,8 +436,7 @@ ObjectNode schemaToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode pa } @ExcludeFromGeneratedCoverageReport - ObjectNode modelSelectionConfigToMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode modelSelectionConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (!Common.isZero( Common.getValueByPath(fromObject, new String[] {"featureSelectionPreference"}))) { @@ -453,8 +448,7 @@ ObjectNode modelSelectionConfigToMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode safetySettingToMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode safetySettingToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"method"}))) { throw new IllegalArgumentException("method parameter is not supported in Gemini API."); @@ -478,8 +472,7 @@ ObjectNode safetySettingToMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode functionDeclarationToMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode functionDeclarationToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"behavior"}) != null) { Common.setValueByPath( @@ -534,7 +527,7 @@ ObjectNode functionDeclarationToMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode intervalToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode intervalToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"startTime"}) != null) { Common.setValueByPath( @@ -554,15 +547,13 @@ ObjectNode intervalToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode } @ExcludeFromGeneratedCoverageReport - ObjectNode googleSearchToMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode googleSearchToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"timeRangeFilter"}) != null) { Common.setValueByPath( toObject, new String[] {"timeRangeFilter"}, intervalToMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"timeRangeFilter"})), toObject)); @@ -572,8 +563,7 @@ ObjectNode googleSearchToMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode dynamicRetrievalConfigToMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode dynamicRetrievalConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"mode"}) != null) { Common.setValueByPath( @@ -593,15 +583,13 @@ ObjectNode dynamicRetrievalConfigToMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode googleSearchRetrievalToMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode googleSearchRetrievalToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"dynamicRetrievalConfig"}) != null) { Common.setValueByPath( toObject, new String[] {"dynamicRetrievalConfig"}, dynamicRetrievalConfigToMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"dynamicRetrievalConfig"})), toObject)); @@ -611,16 +599,14 @@ ObjectNode googleSearchRetrievalToMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode enterpriseWebSearchToMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode enterpriseWebSearchToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); return toObject; } @ExcludeFromGeneratedCoverageReport - ObjectNode apiKeyConfigToMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode apiKeyConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"apiKeyString"}))) { throw new IllegalArgumentException("apiKeyString parameter is not supported in Gemini API."); @@ -630,7 +616,7 @@ ObjectNode apiKeyConfigToMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode authConfigToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode authConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"apiKeyConfig"}))) { throw new IllegalArgumentException("apiKeyConfig parameter is not supported in Gemini API."); @@ -675,7 +661,7 @@ ObjectNode authConfigToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNod } @ExcludeFromGeneratedCoverageReport - ObjectNode googleMapsToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode googleMapsToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"authConfig"}))) { throw new IllegalArgumentException("authConfig parameter is not supported in Gemini API."); @@ -685,14 +671,14 @@ ObjectNode googleMapsToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNod } @ExcludeFromGeneratedCoverageReport - ObjectNode urlContextToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode urlContextToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); return toObject; } @ExcludeFromGeneratedCoverageReport - ObjectNode toolToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toolToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"functionDeclarations"}) != null) { ArrayNode keyArray = @@ -701,8 +687,7 @@ ObjectNode toolToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode pare ArrayNode result = objectMapper.createArrayNode(); for (JsonNode item : keyArray) { - result.add( - functionDeclarationToMldev(apiClient, JsonSerializable.toJsonNode(item), toObject)); + result.add(functionDeclarationToMldev(JsonSerializable.toJsonNode(item), toObject)); } Common.setValueByPath(toObject, new String[] {"functionDeclarations"}, result); } @@ -716,7 +701,6 @@ ObjectNode toolToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode pare toObject, new String[] {"googleSearch"}, googleSearchToMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"googleSearch"})), toObject)); @@ -727,7 +711,6 @@ ObjectNode toolToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode pare toObject, new String[] {"googleSearchRetrieval"}, googleSearchRetrievalToMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"googleSearchRetrieval"})), toObject)); @@ -747,7 +730,6 @@ ObjectNode toolToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode pare toObject, new String[] {"urlContext"}, urlContextToMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"urlContext"})), toObject)); @@ -764,8 +746,7 @@ ObjectNode toolToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode pare } @ExcludeFromGeneratedCoverageReport - ObjectNode functionCallingConfigToMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode functionCallingConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"mode"}) != null) { Common.setValueByPath( @@ -785,7 +766,7 @@ ObjectNode functionCallingConfigToMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode latLngToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode latLngToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"latitude"}) != null) { Common.setValueByPath( @@ -805,15 +786,13 @@ ObjectNode latLngToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode pa } @ExcludeFromGeneratedCoverageReport - ObjectNode retrievalConfigToMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode retrievalConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"latLng"}) != null) { Common.setValueByPath( toObject, new String[] {"latLng"}, latLngToMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"latLng"})), toObject)); @@ -830,14 +809,13 @@ ObjectNode retrievalConfigToMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode toolConfigToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toolConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"functionCallingConfig"}) != null) { Common.setValueByPath( toObject, new String[] {"functionCallingConfig"}, functionCallingConfigToMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"functionCallingConfig"})), toObject)); @@ -848,7 +826,6 @@ ObjectNode toolConfigToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNod toObject, new String[] {"retrievalConfig"}, retrievalConfigToMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"retrievalConfig"})), toObject)); @@ -858,8 +835,7 @@ ObjectNode toolConfigToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNod } @ExcludeFromGeneratedCoverageReport - ObjectNode prebuiltVoiceConfigToMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode prebuiltVoiceConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"voiceName"}) != null) { Common.setValueByPath( @@ -872,14 +848,13 @@ ObjectNode prebuiltVoiceConfigToMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode voiceConfigToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode voiceConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"prebuiltVoiceConfig"}) != null) { Common.setValueByPath( toObject, new String[] {"prebuiltVoiceConfig"}, prebuiltVoiceConfigToMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"prebuiltVoiceConfig"})), toObject)); @@ -889,8 +864,7 @@ ObjectNode voiceConfigToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNo } @ExcludeFromGeneratedCoverageReport - ObjectNode speakerVoiceConfigToMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode speakerVoiceConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"speaker"}) != null) { Common.setValueByPath( @@ -904,7 +878,6 @@ ObjectNode speakerVoiceConfigToMldev( toObject, new String[] {"voiceConfig"}, voiceConfigToMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"voiceConfig"})), toObject)); @@ -914,8 +887,7 @@ ObjectNode speakerVoiceConfigToMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode multiSpeakerVoiceConfigToMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode multiSpeakerVoiceConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"speakerVoiceConfigs"}) != null) { ArrayNode keyArray = @@ -924,8 +896,7 @@ ObjectNode multiSpeakerVoiceConfigToMldev( ArrayNode result = objectMapper.createArrayNode(); for (JsonNode item : keyArray) { - result.add( - speakerVoiceConfigToMldev(apiClient, JsonSerializable.toJsonNode(item), toObject)); + result.add(speakerVoiceConfigToMldev(JsonSerializable.toJsonNode(item), toObject)); } Common.setValueByPath(toObject, new String[] {"speakerVoiceConfigs"}, result); } @@ -934,15 +905,13 @@ ObjectNode multiSpeakerVoiceConfigToMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode speechConfigToMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode speechConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"voiceConfig"}) != null) { Common.setValueByPath( toObject, new String[] {"voiceConfig"}, voiceConfigToMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"voiceConfig"})), toObject)); @@ -953,7 +922,6 @@ ObjectNode speechConfigToMldev( toObject, new String[] {"multiSpeakerVoiceConfig"}, multiSpeakerVoiceConfigToMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"multiSpeakerVoiceConfig"})), toObject)); @@ -970,8 +938,7 @@ ObjectNode speechConfigToMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode thinkingConfigToMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode thinkingConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"includeThoughts"}) != null) { Common.setValueByPath( @@ -1000,10 +967,8 @@ ObjectNode generateContentConfigToMldev( parentObject, new String[] {"systemInstruction"}, contentToMldev( - apiClient, JsonSerializable.toJsonNode( Transformers.tContent( - this.apiClient, Common.getValueByPath(fromObject, new String[] {"systemInstruction"}))), toObject)); } @@ -1097,10 +1062,8 @@ ObjectNode generateContentConfigToMldev( toObject, new String[] {"responseSchema"}, schemaToMldev( - apiClient, JsonSerializable.toJsonNode( Transformers.tSchema( - this.apiClient, Common.getValueByPath(fromObject, new String[] {"responseSchema"}))), toObject)); } @@ -1121,7 +1084,7 @@ ObjectNode generateContentConfigToMldev( ArrayNode result = objectMapper.createArrayNode(); for (JsonNode item : keyArray) { - result.add(safetySettingToMldev(apiClient, JsonSerializable.toJsonNode(item), toObject)); + result.add(safetySettingToMldev(JsonSerializable.toJsonNode(item), toObject)); } Common.setValueByPath(parentObject, new String[] {"safetySettings"}, result); } @@ -1129,17 +1092,12 @@ ObjectNode generateContentConfigToMldev( if (Common.getValueByPath(fromObject, new String[] {"tools"}) != null) { ArrayNode keyArray = (ArrayNode) - Transformers.tTools( - this.apiClient, Common.getValueByPath(fromObject, new String[] {"tools"})); + Transformers.tTools(Common.getValueByPath(fromObject, new String[] {"tools"})); ObjectMapper objectMapper = new ObjectMapper(); ArrayNode result = objectMapper.createArrayNode(); for (JsonNode item : keyArray) { - result.add( - toolToMldev( - apiClient, - JsonSerializable.toJsonNode(Transformers.tTool(this.apiClient, item)), - toObject)); + result.add(toolToMldev(JsonSerializable.toJsonNode(Transformers.tTool(item)), toObject)); } Common.setValueByPath(parentObject, new String[] {"tools"}, result); } @@ -1149,7 +1107,6 @@ ObjectNode generateContentConfigToMldev( parentObject, new String[] {"toolConfig"}, toolConfigToMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"toolConfig"})), toObject)); @@ -1186,10 +1143,8 @@ ObjectNode generateContentConfigToMldev( toObject, new String[] {"speechConfig"}, speechConfigToMldev( - apiClient, JsonSerializable.toJsonNode( Transformers.tSpeechConfig( - this.apiClient, Common.getValueByPath(fromObject, new String[] {"speechConfig"}))), toObject)); } @@ -1204,7 +1159,6 @@ ObjectNode generateContentConfigToMldev( toObject, new String[] {"thinkingConfig"}, thinkingConfigToMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"thinkingConfig"})), toObject)); @@ -1228,13 +1182,12 @@ ObjectNode generateContentParametersToMldev( if (Common.getValueByPath(fromObject, new String[] {"contents"}) != null) { ArrayNode keyArray = (ArrayNode) - Transformers.tContents( - this.apiClient, Common.getValueByPath(fromObject, new String[] {"contents"})); + Transformers.tContents(Common.getValueByPath(fromObject, new String[] {"contents"})); ObjectMapper objectMapper = new ObjectMapper(); ArrayNode result = objectMapper.createArrayNode(); for (JsonNode item : keyArray) { - result.add(contentToMldev(apiClient, JsonSerializable.toJsonNode(item), toObject)); + result.add(contentToMldev(JsonSerializable.toJsonNode(item), toObject)); } Common.setValueByPath(toObject, new String[] {"contents"}, result); } @@ -1254,8 +1207,7 @@ ObjectNode generateContentParametersToMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode embedContentConfigToMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode embedContentConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"taskType"}) != null) { @@ -1315,7 +1267,6 @@ ObjectNode embedContentParametersToMldev( toObject, new String[] {"config"}, embedContentConfigToMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"config"})), toObject)); @@ -1330,8 +1281,7 @@ ObjectNode embedContentParametersToMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode generateImagesConfigToMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode generateImagesConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"outputGcsUri"}))) { @@ -1452,7 +1402,6 @@ ObjectNode generateImagesParametersToMldev( toObject, new String[] {"config"}, generateImagesConfigToMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"config"})), toObject)); @@ -1539,8 +1488,7 @@ ObjectNode listModelsParametersToMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode updateModelConfigToMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode updateModelConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"displayName"}) != null) { @@ -1584,7 +1532,6 @@ ObjectNode updateModelParametersToMldev( toObject, new String[] {"config"}, updateModelConfigToMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"config"})), toObject)); @@ -1616,8 +1563,7 @@ ObjectNode deleteModelParametersToMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode countTokensConfigToMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode countTokensConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"systemInstruction"}))) { @@ -1652,13 +1598,12 @@ ObjectNode countTokensParametersToMldev( if (Common.getValueByPath(fromObject, new String[] {"contents"}) != null) { ArrayNode keyArray = (ArrayNode) - Transformers.tContents( - this.apiClient, Common.getValueByPath(fromObject, new String[] {"contents"})); + Transformers.tContents(Common.getValueByPath(fromObject, new String[] {"contents"})); ObjectMapper objectMapper = new ObjectMapper(); ArrayNode result = objectMapper.createArrayNode(); for (JsonNode item : keyArray) { - result.add(contentToMldev(apiClient, JsonSerializable.toJsonNode(item), toObject)); + result.add(contentToMldev(JsonSerializable.toJsonNode(item), toObject)); } Common.setValueByPath(toObject, new String[] {"contents"}, result); } @@ -1668,7 +1613,6 @@ ObjectNode countTokensParametersToMldev( toObject, new String[] {"config"}, countTokensConfigToMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"config"})), toObject)); @@ -1678,7 +1622,7 @@ ObjectNode countTokensParametersToMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode imageToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode imageToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"gcsUri"}))) { throw new IllegalArgumentException("gcsUri parameter is not supported in Gemini API."); @@ -1688,8 +1632,7 @@ ObjectNode imageToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode par Common.setValueByPath( toObject, new String[] {"bytesBase64Encoded"}, - Transformers.tBytes( - this.apiClient, Common.getValueByPath(fromObject, new String[] {"imageBytes"}))); + Transformers.tBytes(Common.getValueByPath(fromObject, new String[] {"imageBytes"}))); } if (Common.getValueByPath(fromObject, new String[] {"mimeType"}) != null) { @@ -1703,7 +1646,7 @@ ObjectNode imageToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode par } @ExcludeFromGeneratedCoverageReport - ObjectNode videoToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode videoToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"uri"}) != null) { Common.setValueByPath( @@ -1716,8 +1659,7 @@ ObjectNode videoToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode par Common.setValueByPath( toObject, new String[] {"video", "encodedVideo"}, - Transformers.tBytes( - this.apiClient, Common.getValueByPath(fromObject, new String[] {"videoBytes"}))); + Transformers.tBytes(Common.getValueByPath(fromObject, new String[] {"videoBytes"}))); } if (Common.getValueByPath(fromObject, new String[] {"mimeType"}) != null) { @@ -1731,8 +1673,7 @@ ObjectNode videoToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode par } @ExcludeFromGeneratedCoverageReport - ObjectNode generateVideosConfigToMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode generateVideosConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"numberOfVideos"}) != null) { @@ -1832,7 +1773,6 @@ ObjectNode generateVideosParametersToMldev( toObject, new String[] {"instances[0]", "image"}, imageToMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"image"})), toObject)); @@ -1847,7 +1787,6 @@ ObjectNode generateVideosParametersToMldev( toObject, new String[] {"config"}, generateVideosConfigToMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"config"})), toObject)); @@ -1857,8 +1796,7 @@ ObjectNode generateVideosParametersToMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode videoMetadataToVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode videoMetadataToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"fps"}) != null) { Common.setValueByPath( @@ -1883,7 +1821,7 @@ ObjectNode videoMetadataToVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode blobToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode blobToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"displayName"}) != null) { Common.setValueByPath( @@ -1910,7 +1848,7 @@ ObjectNode blobToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode par } @ExcludeFromGeneratedCoverageReport - ObjectNode fileDataToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode fileDataToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"displayName"}) != null) { Common.setValueByPath( @@ -1937,14 +1875,13 @@ ObjectNode fileDataToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode } @ExcludeFromGeneratedCoverageReport - ObjectNode partToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode partToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"videoMetadata"}) != null) { Common.setValueByPath( toObject, new String[] {"videoMetadata"}, videoMetadataToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"videoMetadata"})), toObject)); @@ -1962,7 +1899,6 @@ ObjectNode partToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode par toObject, new String[] {"inlineData"}, blobToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"inlineData"})), toObject)); @@ -1973,7 +1909,6 @@ ObjectNode partToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode par toObject, new String[] {"fileData"}, fileDataToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"fileData"})), toObject)); @@ -2025,7 +1960,7 @@ ObjectNode partToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode par } @ExcludeFromGeneratedCoverageReport - ObjectNode contentToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode contentToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"parts"}) != null) { ArrayNode keyArray = (ArrayNode) Common.getValueByPath(fromObject, new String[] {"parts"}); @@ -2033,7 +1968,7 @@ ObjectNode contentToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode ArrayNode result = objectMapper.createArrayNode(); for (JsonNode item : keyArray) { - result.add(partToVertex(apiClient, JsonSerializable.toJsonNode(item), toObject)); + result.add(partToVertex(JsonSerializable.toJsonNode(item), toObject)); } Common.setValueByPath(toObject, new String[] {"parts"}, result); } @@ -2049,7 +1984,7 @@ ObjectNode contentToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode } @ExcludeFromGeneratedCoverageReport - ObjectNode schemaToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode schemaToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"anyOf"}) != null) { @@ -2210,8 +2145,7 @@ ObjectNode schemaToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode p } @ExcludeFromGeneratedCoverageReport - ObjectNode modelSelectionConfigToVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode modelSelectionConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"featureSelectionPreference"}) != null) { Common.setValueByPath( @@ -2224,8 +2158,7 @@ ObjectNode modelSelectionConfigToVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode safetySettingToVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode safetySettingToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"method"}) != null) { Common.setValueByPath( @@ -2252,8 +2185,7 @@ ObjectNode safetySettingToVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode functionDeclarationToVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode functionDeclarationToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"behavior"}))) { throw new IllegalArgumentException("behavior parameter is not supported in Vertex AI."); @@ -2305,7 +2237,7 @@ ObjectNode functionDeclarationToVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode intervalToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode intervalToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"startTime"}) != null) { Common.setValueByPath( @@ -2325,15 +2257,13 @@ ObjectNode intervalToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode } @ExcludeFromGeneratedCoverageReport - ObjectNode googleSearchToVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode googleSearchToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"timeRangeFilter"}) != null) { Common.setValueByPath( toObject, new String[] {"timeRangeFilter"}, intervalToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"timeRangeFilter"})), toObject)); @@ -2343,8 +2273,7 @@ ObjectNode googleSearchToVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode dynamicRetrievalConfigToVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode dynamicRetrievalConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"mode"}) != null) { Common.setValueByPath( @@ -2364,15 +2293,13 @@ ObjectNode dynamicRetrievalConfigToVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode googleSearchRetrievalToVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode googleSearchRetrievalToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"dynamicRetrievalConfig"}) != null) { Common.setValueByPath( toObject, new String[] {"dynamicRetrievalConfig"}, dynamicRetrievalConfigToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"dynamicRetrievalConfig"})), toObject)); @@ -2382,16 +2309,14 @@ ObjectNode googleSearchRetrievalToVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode enterpriseWebSearchToVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode enterpriseWebSearchToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); return toObject; } @ExcludeFromGeneratedCoverageReport - ObjectNode apiKeyConfigToVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode apiKeyConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"apiKeyString"}) != null) { Common.setValueByPath( @@ -2404,14 +2329,13 @@ ObjectNode apiKeyConfigToVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode authConfigToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode authConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"apiKeyConfig"}) != null) { Common.setValueByPath( toObject, new String[] {"apiKeyConfig"}, apiKeyConfigToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"apiKeyConfig"})), toObject)); @@ -2456,14 +2380,13 @@ ObjectNode authConfigToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNo } @ExcludeFromGeneratedCoverageReport - ObjectNode googleMapsToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode googleMapsToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"authConfig"}) != null) { Common.setValueByPath( toObject, new String[] {"authConfig"}, authConfigToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"authConfig"})), toObject)); @@ -2473,14 +2396,14 @@ ObjectNode googleMapsToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNo } @ExcludeFromGeneratedCoverageReport - ObjectNode urlContextToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode urlContextToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); return toObject; } @ExcludeFromGeneratedCoverageReport - ObjectNode toolToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toolToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"functionDeclarations"}) != null) { ArrayNode keyArray = @@ -2489,8 +2412,7 @@ ObjectNode toolToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode par ArrayNode result = objectMapper.createArrayNode(); for (JsonNode item : keyArray) { - result.add( - functionDeclarationToVertex(apiClient, JsonSerializable.toJsonNode(item), toObject)); + result.add(functionDeclarationToVertex(JsonSerializable.toJsonNode(item), toObject)); } Common.setValueByPath(toObject, new String[] {"functionDeclarations"}, result); } @@ -2507,7 +2429,6 @@ ObjectNode toolToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode par toObject, new String[] {"googleSearch"}, googleSearchToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"googleSearch"})), toObject)); @@ -2518,7 +2439,6 @@ ObjectNode toolToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode par toObject, new String[] {"googleSearchRetrieval"}, googleSearchRetrievalToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"googleSearchRetrieval"})), toObject)); @@ -2529,7 +2449,6 @@ ObjectNode toolToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode par toObject, new String[] {"enterpriseWebSearch"}, enterpriseWebSearchToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"enterpriseWebSearch"})), toObject)); @@ -2540,7 +2459,6 @@ ObjectNode toolToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode par toObject, new String[] {"googleMaps"}, googleMapsToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"googleMaps"})), toObject)); @@ -2551,7 +2469,6 @@ ObjectNode toolToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode par toObject, new String[] {"urlContext"}, urlContextToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"urlContext"})), toObject)); @@ -2568,8 +2485,7 @@ ObjectNode toolToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode par } @ExcludeFromGeneratedCoverageReport - ObjectNode functionCallingConfigToVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode functionCallingConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"mode"}) != null) { Common.setValueByPath( @@ -2589,7 +2505,7 @@ ObjectNode functionCallingConfigToVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode latLngToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode latLngToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"latitude"}) != null) { Common.setValueByPath( @@ -2609,15 +2525,13 @@ ObjectNode latLngToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode p } @ExcludeFromGeneratedCoverageReport - ObjectNode retrievalConfigToVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode retrievalConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"latLng"}) != null) { Common.setValueByPath( toObject, new String[] {"latLng"}, latLngToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"latLng"})), toObject)); @@ -2634,14 +2548,13 @@ ObjectNode retrievalConfigToVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode toolConfigToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toolConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"functionCallingConfig"}) != null) { Common.setValueByPath( toObject, new String[] {"functionCallingConfig"}, functionCallingConfigToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"functionCallingConfig"})), toObject)); @@ -2652,7 +2565,6 @@ ObjectNode toolConfigToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNo toObject, new String[] {"retrievalConfig"}, retrievalConfigToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"retrievalConfig"})), toObject)); @@ -2662,8 +2574,7 @@ ObjectNode toolConfigToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNo } @ExcludeFromGeneratedCoverageReport - ObjectNode prebuiltVoiceConfigToVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode prebuiltVoiceConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"voiceName"}) != null) { Common.setValueByPath( @@ -2676,15 +2587,13 @@ ObjectNode prebuiltVoiceConfigToVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode voiceConfigToVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode voiceConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"prebuiltVoiceConfig"}) != null) { Common.setValueByPath( toObject, new String[] {"prebuiltVoiceConfig"}, prebuiltVoiceConfigToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"prebuiltVoiceConfig"})), toObject)); @@ -2694,8 +2603,7 @@ ObjectNode voiceConfigToVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode speakerVoiceConfigToVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode speakerVoiceConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"speaker"}))) { throw new IllegalArgumentException("speaker parameter is not supported in Vertex AI."); @@ -2709,8 +2617,7 @@ ObjectNode speakerVoiceConfigToVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode multiSpeakerVoiceConfigToVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode multiSpeakerVoiceConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"speakerVoiceConfigs"}))) { throw new IllegalArgumentException( @@ -2721,15 +2628,13 @@ ObjectNode multiSpeakerVoiceConfigToVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode speechConfigToVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode speechConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"voiceConfig"}) != null) { Common.setValueByPath( toObject, new String[] {"voiceConfig"}, voiceConfigToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"voiceConfig"})), toObject)); @@ -2752,8 +2657,7 @@ ObjectNode speechConfigToVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode thinkingConfigToVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode thinkingConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"includeThoughts"}) != null) { Common.setValueByPath( @@ -2782,10 +2686,8 @@ ObjectNode generateContentConfigToVertex( parentObject, new String[] {"systemInstruction"}, contentToVertex( - apiClient, JsonSerializable.toJsonNode( Transformers.tContent( - this.apiClient, Common.getValueByPath(fromObject, new String[] {"systemInstruction"}))), toObject)); } @@ -2879,10 +2781,8 @@ ObjectNode generateContentConfigToVertex( toObject, new String[] {"responseSchema"}, schemaToVertex( - apiClient, JsonSerializable.toJsonNode( Transformers.tSchema( - this.apiClient, Common.getValueByPath(fromObject, new String[] {"responseSchema"}))), toObject)); } @@ -2899,7 +2799,6 @@ ObjectNode generateContentConfigToVertex( toObject, new String[] {"modelConfig"}, modelSelectionConfigToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"modelSelectionConfig"})), toObject)); @@ -2912,7 +2811,7 @@ ObjectNode generateContentConfigToVertex( ArrayNode result = objectMapper.createArrayNode(); for (JsonNode item : keyArray) { - result.add(safetySettingToVertex(apiClient, JsonSerializable.toJsonNode(item), toObject)); + result.add(safetySettingToVertex(JsonSerializable.toJsonNode(item), toObject)); } Common.setValueByPath(parentObject, new String[] {"safetySettings"}, result); } @@ -2920,17 +2819,12 @@ ObjectNode generateContentConfigToVertex( if (Common.getValueByPath(fromObject, new String[] {"tools"}) != null) { ArrayNode keyArray = (ArrayNode) - Transformers.tTools( - this.apiClient, Common.getValueByPath(fromObject, new String[] {"tools"})); + Transformers.tTools(Common.getValueByPath(fromObject, new String[] {"tools"})); ObjectMapper objectMapper = new ObjectMapper(); ArrayNode result = objectMapper.createArrayNode(); for (JsonNode item : keyArray) { - result.add( - toolToVertex( - apiClient, - JsonSerializable.toJsonNode(Transformers.tTool(this.apiClient, item)), - toObject)); + result.add(toolToVertex(JsonSerializable.toJsonNode(Transformers.tTool(item)), toObject)); } Common.setValueByPath(parentObject, new String[] {"tools"}, result); } @@ -2940,7 +2834,6 @@ ObjectNode generateContentConfigToVertex( parentObject, new String[] {"toolConfig"}, toolConfigToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"toolConfig"})), toObject)); @@ -2980,10 +2873,8 @@ ObjectNode generateContentConfigToVertex( toObject, new String[] {"speechConfig"}, speechConfigToVertex( - apiClient, JsonSerializable.toJsonNode( Transformers.tSpeechConfig( - this.apiClient, Common.getValueByPath(fromObject, new String[] {"speechConfig"}))), toObject)); } @@ -3000,7 +2891,6 @@ ObjectNode generateContentConfigToVertex( toObject, new String[] {"thinkingConfig"}, thinkingConfigToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"thinkingConfig"})), toObject)); @@ -3024,13 +2914,12 @@ ObjectNode generateContentParametersToVertex( if (Common.getValueByPath(fromObject, new String[] {"contents"}) != null) { ArrayNode keyArray = (ArrayNode) - Transformers.tContents( - this.apiClient, Common.getValueByPath(fromObject, new String[] {"contents"})); + Transformers.tContents(Common.getValueByPath(fromObject, new String[] {"contents"})); ObjectMapper objectMapper = new ObjectMapper(); ArrayNode result = objectMapper.createArrayNode(); for (JsonNode item : keyArray) { - result.add(contentToVertex(apiClient, JsonSerializable.toJsonNode(item), toObject)); + result.add(contentToVertex(JsonSerializable.toJsonNode(item), toObject)); } Common.setValueByPath(toObject, new String[] {"contents"}, result); } @@ -3050,8 +2939,7 @@ ObjectNode generateContentParametersToVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode embedContentConfigToVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode embedContentConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"taskType"}) != null) { @@ -3117,7 +3005,6 @@ ObjectNode embedContentParametersToVertex( toObject, new String[] {"config"}, embedContentConfigToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"config"})), toObject)); @@ -3127,8 +3014,7 @@ ObjectNode embedContentParametersToVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode generateImagesConfigToVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode generateImagesConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"outputGcsUri"}) != null) { @@ -3263,7 +3149,6 @@ ObjectNode generateImagesParametersToVertex( toObject, new String[] {"config"}, generateImagesConfigToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"config"})), toObject)); @@ -3273,7 +3158,7 @@ ObjectNode generateImagesParametersToVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode imageToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode imageToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"gcsUri"}) != null) { Common.setValueByPath( @@ -3286,8 +3171,7 @@ ObjectNode imageToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode pa Common.setValueByPath( toObject, new String[] {"bytesBase64Encoded"}, - Transformers.tBytes( - this.apiClient, Common.getValueByPath(fromObject, new String[] {"imageBytes"}))); + Transformers.tBytes(Common.getValueByPath(fromObject, new String[] {"imageBytes"}))); } if (Common.getValueByPath(fromObject, new String[] {"mimeType"}) != null) { @@ -3301,8 +3185,7 @@ ObjectNode imageToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode pa } @ExcludeFromGeneratedCoverageReport - ObjectNode maskReferenceConfigToVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode maskReferenceConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"maskMode"}) != null) { Common.setValueByPath( @@ -3329,8 +3212,7 @@ ObjectNode maskReferenceConfigToVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode controlReferenceConfigToVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode controlReferenceConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"controlType"}) != null) { Common.setValueByPath( @@ -3350,8 +3232,7 @@ ObjectNode controlReferenceConfigToVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode styleReferenceConfigToVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode styleReferenceConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"styleDescription"}) != null) { Common.setValueByPath( @@ -3364,8 +3245,7 @@ ObjectNode styleReferenceConfigToVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode subjectReferenceConfigToVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode subjectReferenceConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"subjectType"}) != null) { Common.setValueByPath( @@ -3385,15 +3265,13 @@ ObjectNode subjectReferenceConfigToVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode referenceImageAPIToVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode referenceImageAPIToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"referenceImage"}) != null) { Common.setValueByPath( toObject, new String[] {"referenceImage"}, imageToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"referenceImage"})), toObject)); @@ -3418,7 +3296,6 @@ ObjectNode referenceImageAPIToVertex( toObject, new String[] {"maskImageConfig"}, maskReferenceConfigToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"maskImageConfig"})), toObject)); @@ -3429,7 +3306,6 @@ ObjectNode referenceImageAPIToVertex( toObject, new String[] {"controlImageConfig"}, controlReferenceConfigToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"controlImageConfig"})), toObject)); @@ -3440,7 +3316,6 @@ ObjectNode referenceImageAPIToVertex( toObject, new String[] {"styleImageConfig"}, styleReferenceConfigToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"styleImageConfig"})), toObject)); @@ -3451,7 +3326,6 @@ ObjectNode referenceImageAPIToVertex( toObject, new String[] {"subjectImageConfig"}, subjectReferenceConfigToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"subjectImageConfig"})), toObject)); @@ -3461,8 +3335,7 @@ ObjectNode referenceImageAPIToVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode editImageConfigToVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode editImageConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"outputGcsUri"}) != null) { @@ -3599,8 +3472,7 @@ ObjectNode editImageParametersToVertex( ArrayNode result = objectMapper.createArrayNode(); for (JsonNode item : keyArray) { - result.add( - referenceImageAPIToVertex(apiClient, JsonSerializable.toJsonNode(item), toObject)); + result.add(referenceImageAPIToVertex(JsonSerializable.toJsonNode(item), toObject)); } Common.setValueByPath(toObject, new String[] {"instances[0]", "referenceImages"}, result); } @@ -3610,7 +3482,6 @@ ObjectNode editImageParametersToVertex( toObject, new String[] {"config"}, editImageConfigToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"config"})), toObject)); @@ -3620,8 +3491,7 @@ ObjectNode editImageParametersToVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode upscaleImageAPIConfigToVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode upscaleImageAPIConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"includeRaiReason"}) != null) { @@ -3679,7 +3549,6 @@ ObjectNode upscaleImageAPIParametersToVertex( toObject, new String[] {"instances[0]", "image"}, imageToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"image"})), toObject)); @@ -3697,7 +3566,6 @@ ObjectNode upscaleImageAPIParametersToVertex( toObject, new String[] {"config"}, upscaleImageAPIConfigToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"config"})), toObject)); @@ -3784,8 +3652,7 @@ ObjectNode listModelsParametersToVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode updateModelConfigToVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode updateModelConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"displayName"}) != null) { @@ -3829,7 +3696,6 @@ ObjectNode updateModelParametersToVertex( toObject, new String[] {"config"}, updateModelConfigToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"config"})), toObject)); @@ -3861,8 +3727,7 @@ ObjectNode deleteModelParametersToVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode countTokensConfigToVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode countTokensConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"systemInstruction"}) != null) { @@ -3870,10 +3735,8 @@ ObjectNode countTokensConfigToVertex( parentObject, new String[] {"systemInstruction"}, contentToVertex( - apiClient, JsonSerializable.toJsonNode( Transformers.tContent( - this.apiClient, Common.getValueByPath(fromObject, new String[] {"systemInstruction"}))), toObject)); } @@ -3884,7 +3747,7 @@ ObjectNode countTokensConfigToVertex( ArrayNode result = objectMapper.createArrayNode(); for (JsonNode item : keyArray) { - result.add(toolToVertex(apiClient, JsonSerializable.toJsonNode(item), toObject)); + result.add(toolToVertex(JsonSerializable.toJsonNode(item), toObject)); } Common.setValueByPath(parentObject, new String[] {"tools"}, result); } @@ -3914,13 +3777,12 @@ ObjectNode countTokensParametersToVertex( if (Common.getValueByPath(fromObject, new String[] {"contents"}) != null) { ArrayNode keyArray = (ArrayNode) - Transformers.tContents( - this.apiClient, Common.getValueByPath(fromObject, new String[] {"contents"})); + Transformers.tContents(Common.getValueByPath(fromObject, new String[] {"contents"})); ObjectMapper objectMapper = new ObjectMapper(); ArrayNode result = objectMapper.createArrayNode(); for (JsonNode item : keyArray) { - result.add(contentToVertex(apiClient, JsonSerializable.toJsonNode(item), toObject)); + result.add(contentToVertex(JsonSerializable.toJsonNode(item), toObject)); } Common.setValueByPath(toObject, new String[] {"contents"}, result); } @@ -3930,7 +3792,6 @@ ObjectNode countTokensParametersToVertex( toObject, new String[] {"config"}, countTokensConfigToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"config"})), toObject)); @@ -3954,13 +3815,12 @@ ObjectNode computeTokensParametersToVertex( if (Common.getValueByPath(fromObject, new String[] {"contents"}) != null) { ArrayNode keyArray = (ArrayNode) - Transformers.tContents( - this.apiClient, Common.getValueByPath(fromObject, new String[] {"contents"})); + Transformers.tContents(Common.getValueByPath(fromObject, new String[] {"contents"})); ObjectMapper objectMapper = new ObjectMapper(); ArrayNode result = objectMapper.createArrayNode(); for (JsonNode item : keyArray) { - result.add(contentToVertex(apiClient, JsonSerializable.toJsonNode(item), toObject)); + result.add(contentToVertex(JsonSerializable.toJsonNode(item), toObject)); } Common.setValueByPath(toObject, new String[] {"contents"}, result); } @@ -3976,7 +3836,7 @@ ObjectNode computeTokensParametersToVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode videoToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode videoToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"uri"}) != null) { Common.setValueByPath( @@ -3989,8 +3849,7 @@ ObjectNode videoToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode pa Common.setValueByPath( toObject, new String[] {"bytesBase64Encoded"}, - Transformers.tBytes( - this.apiClient, Common.getValueByPath(fromObject, new String[] {"videoBytes"}))); + Transformers.tBytes(Common.getValueByPath(fromObject, new String[] {"videoBytes"}))); } if (Common.getValueByPath(fromObject, new String[] {"mimeType"}) != null) { @@ -4004,8 +3863,7 @@ ObjectNode videoToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode pa } @ExcludeFromGeneratedCoverageReport - ObjectNode generateVideosConfigToVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode generateVideosConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"numberOfVideos"}) != null) { @@ -4097,7 +3955,6 @@ ObjectNode generateVideosConfigToVertex( parentObject, new String[] {"instances[0]", "lastFrame"}, imageToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"lastFrame"})), toObject)); @@ -4130,7 +3987,6 @@ ObjectNode generateVideosParametersToVertex( toObject, new String[] {"instances[0]", "image"}, imageToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"image"})), toObject)); @@ -4141,7 +3997,6 @@ ObjectNode generateVideosParametersToVertex( toObject, new String[] {"instances[0]", "video"}, videoToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"video"})), toObject)); @@ -4152,7 +4007,6 @@ ObjectNode generateVideosParametersToVertex( toObject, new String[] {"config"}, generateVideosConfigToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"config"})), toObject)); @@ -4162,8 +4016,7 @@ ObjectNode generateVideosParametersToVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode videoMetadataFromMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode videoMetadataFromMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"fps"}) != null) { Common.setValueByPath( @@ -4188,7 +4041,7 @@ ObjectNode videoMetadataFromMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode blobFromMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode blobFromMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"data"}) != null) { @@ -4209,7 +4062,7 @@ ObjectNode blobFromMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode pa } @ExcludeFromGeneratedCoverageReport - ObjectNode fileDataFromMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode fileDataFromMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"fileUri"}) != null) { @@ -4230,14 +4083,13 @@ ObjectNode fileDataFromMldev(ApiClient apiClient, JsonNode fromObject, ObjectNod } @ExcludeFromGeneratedCoverageReport - ObjectNode partFromMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode partFromMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"videoMetadata"}) != null) { Common.setValueByPath( toObject, new String[] {"videoMetadata"}, videoMetadataFromMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"videoMetadata"})), toObject)); @@ -4255,7 +4107,6 @@ ObjectNode partFromMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode pa toObject, new String[] {"inlineData"}, blobFromMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"inlineData"})), toObject)); @@ -4266,7 +4117,6 @@ ObjectNode partFromMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode pa toObject, new String[] {"fileData"}, fileDataFromMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"fileData"})), toObject)); @@ -4318,7 +4168,7 @@ ObjectNode partFromMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode pa } @ExcludeFromGeneratedCoverageReport - ObjectNode contentFromMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode contentFromMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"parts"}) != null) { ArrayNode keyArray = (ArrayNode) Common.getValueByPath(fromObject, new String[] {"parts"}); @@ -4326,7 +4176,7 @@ ObjectNode contentFromMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode ArrayNode result = objectMapper.createArrayNode(); for (JsonNode item : keyArray) { - result.add(partFromMldev(apiClient, JsonSerializable.toJsonNode(item), toObject)); + result.add(partFromMldev(JsonSerializable.toJsonNode(item), toObject)); } Common.setValueByPath(toObject, new String[] {"parts"}, result); } @@ -4342,8 +4192,7 @@ ObjectNode contentFromMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode } @ExcludeFromGeneratedCoverageReport - ObjectNode citationMetadataFromMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode citationMetadataFromMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"citationSources"}) != null) { Common.setValueByPath( @@ -4356,8 +4205,7 @@ ObjectNode citationMetadataFromMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode urlMetadataFromMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode urlMetadataFromMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"retrievedUrl"}) != null) { Common.setValueByPath( @@ -4377,8 +4225,7 @@ ObjectNode urlMetadataFromMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode urlContextMetadataFromMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode urlContextMetadataFromMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"urlMetadata"}) != null) { ArrayNode keyArray = @@ -4387,7 +4234,7 @@ ObjectNode urlContextMetadataFromMldev( ArrayNode result = objectMapper.createArrayNode(); for (JsonNode item : keyArray) { - result.add(urlMetadataFromMldev(apiClient, JsonSerializable.toJsonNode(item), toObject)); + result.add(urlMetadataFromMldev(JsonSerializable.toJsonNode(item), toObject)); } Common.setValueByPath(toObject, new String[] {"urlMetadata"}, result); } @@ -4396,14 +4243,13 @@ ObjectNode urlContextMetadataFromMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode candidateFromMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode candidateFromMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"content"}) != null) { Common.setValueByPath( toObject, new String[] {"content"}, contentFromMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"content"})), toObject)); @@ -4414,7 +4260,6 @@ ObjectNode candidateFromMldev(ApiClient apiClient, JsonNode fromObject, ObjectNo toObject, new String[] {"citationMetadata"}, citationMetadataFromMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"citationMetadata"})), toObject)); @@ -4439,7 +4284,6 @@ ObjectNode candidateFromMldev(ApiClient apiClient, JsonNode fromObject, ObjectNo toObject, new String[] {"urlContextMetadata"}, urlContextMetadataFromMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"urlContextMetadata"})), toObject)); @@ -4484,8 +4328,7 @@ ObjectNode candidateFromMldev(ApiClient apiClient, JsonNode fromObject, ObjectNo } @ExcludeFromGeneratedCoverageReport - ObjectNode generateContentResponseFromMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode generateContentResponseFromMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"candidates"}) != null) { ArrayNode keyArray = @@ -4494,7 +4337,7 @@ ObjectNode generateContentResponseFromMldev( ArrayNode result = objectMapper.createArrayNode(); for (JsonNode item : keyArray) { - result.add(candidateFromMldev(apiClient, JsonSerializable.toJsonNode(item), toObject)); + result.add(candidateFromMldev(JsonSerializable.toJsonNode(item), toObject)); } Common.setValueByPath(toObject, new String[] {"candidates"}, result); } @@ -4524,16 +4367,14 @@ ObjectNode generateContentResponseFromMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode contentEmbeddingStatisticsFromMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode contentEmbeddingStatisticsFromMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); return toObject; } @ExcludeFromGeneratedCoverageReport - ObjectNode contentEmbeddingFromMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode contentEmbeddingFromMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"values"}) != null) { Common.setValueByPath( @@ -4546,16 +4387,14 @@ ObjectNode contentEmbeddingFromMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode embedContentMetadataFromMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode embedContentMetadataFromMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); return toObject; } @ExcludeFromGeneratedCoverageReport - ObjectNode embedContentResponseFromMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode embedContentResponseFromMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"embeddings"}) != null) { ArrayNode keyArray = @@ -4564,8 +4403,7 @@ ObjectNode embedContentResponseFromMldev( ArrayNode result = objectMapper.createArrayNode(); for (JsonNode item : keyArray) { - result.add( - contentEmbeddingFromMldev(apiClient, JsonSerializable.toJsonNode(item), toObject)); + result.add(contentEmbeddingFromMldev(JsonSerializable.toJsonNode(item), toObject)); } Common.setValueByPath(toObject, new String[] {"embeddings"}, result); } @@ -4575,7 +4413,6 @@ ObjectNode embedContentResponseFromMldev( toObject, new String[] {"metadata"}, embedContentMetadataFromMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"metadata"})), toObject)); @@ -4585,7 +4422,7 @@ ObjectNode embedContentResponseFromMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode imageFromMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode imageFromMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"bytesBase64Encoded"}) != null) { @@ -4593,7 +4430,6 @@ ObjectNode imageFromMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode p toObject, new String[] {"imageBytes"}, Transformers.tBytes( - this.apiClient, Common.getValueByPath(fromObject, new String[] {"bytesBase64Encoded"}))); } @@ -4608,8 +4444,7 @@ ObjectNode imageFromMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode p } @ExcludeFromGeneratedCoverageReport - ObjectNode safetyAttributesFromMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode safetyAttributesFromMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"safetyAttributes", "categories"}) != null) { @@ -4637,15 +4472,13 @@ ObjectNode safetyAttributesFromMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode generatedImageFromMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode generatedImageFromMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"_self"}) != null) { Common.setValueByPath( toObject, new String[] {"image"}, imageFromMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"_self"})), toObject)); @@ -4663,7 +4496,6 @@ ObjectNode generatedImageFromMldev( toObject, new String[] {"safetyAttributes"}, safetyAttributesFromMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"_self"})), toObject)); @@ -4673,8 +4505,7 @@ ObjectNode generatedImageFromMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode generateImagesResponseFromMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode generateImagesResponseFromMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"predictions"}) != null) { ArrayNode keyArray = @@ -4683,7 +4514,7 @@ ObjectNode generateImagesResponseFromMldev( ArrayNode result = objectMapper.createArrayNode(); for (JsonNode item : keyArray) { - result.add(generatedImageFromMldev(apiClient, JsonSerializable.toJsonNode(item), toObject)); + result.add(generatedImageFromMldev(JsonSerializable.toJsonNode(item), toObject)); } Common.setValueByPath(toObject, new String[] {"generatedImages"}, result); } @@ -4694,7 +4525,6 @@ ObjectNode generateImagesResponseFromMldev( toObject, new String[] {"positivePromptSafetyAttributes"}, safetyAttributesFromMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath( fromObject, new String[] {"positivePromptSafetyAttributes"})), @@ -4705,15 +4535,14 @@ ObjectNode generateImagesResponseFromMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode endpointFromMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode endpointFromMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); return toObject; } @ExcludeFromGeneratedCoverageReport - ObjectNode tunedModelInfoFromMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode tunedModelInfoFromMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"baseModel"}) != null) { Common.setValueByPath( @@ -4740,15 +4569,14 @@ ObjectNode tunedModelInfoFromMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode checkpointFromMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode checkpointFromMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); return toObject; } @ExcludeFromGeneratedCoverageReport - ObjectNode modelFromMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode modelFromMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"name"}) != null) { Common.setValueByPath( @@ -4783,7 +4611,6 @@ ObjectNode modelFromMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode p toObject, new String[] {"tunedModelInfo"}, tunedModelInfoFromMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"_self"})), toObject)); @@ -4814,8 +4641,7 @@ ObjectNode modelFromMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode p } @ExcludeFromGeneratedCoverageReport - ObjectNode listModelsResponseFromMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode listModelsResponseFromMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"nextPageToken"}) != null) { Common.setValueByPath( @@ -4828,12 +4654,12 @@ ObjectNode listModelsResponseFromMldev( ArrayNode keyArray = (ArrayNode) Transformers.tExtractModels( - this.apiClient, Common.getValueByPath(fromObject, new String[] {"_self"})); + Common.getValueByPath(fromObject, new String[] {"_self"})); ObjectMapper objectMapper = new ObjectMapper(); ArrayNode result = objectMapper.createArrayNode(); for (JsonNode item : keyArray) { - result.add(modelFromMldev(apiClient, JsonSerializable.toJsonNode(item), toObject)); + result.add(modelFromMldev(JsonSerializable.toJsonNode(item), toObject)); } Common.setValueByPath(toObject, new String[] {"models"}, result); } @@ -4842,16 +4668,14 @@ ObjectNode listModelsResponseFromMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode deleteModelResponseFromMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode deleteModelResponseFromMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); return toObject; } @ExcludeFromGeneratedCoverageReport - ObjectNode countTokensResponseFromMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode countTokensResponseFromMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"totalTokens"}) != null) { Common.setValueByPath( @@ -4871,7 +4695,7 @@ ObjectNode countTokensResponseFromMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode videoFromMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode videoFromMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"video", "uri"}) != null) { Common.setValueByPath( @@ -4885,7 +4709,6 @@ ObjectNode videoFromMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode p toObject, new String[] {"videoBytes"}, Transformers.tBytes( - this.apiClient, Common.getValueByPath(fromObject, new String[] {"video", "encodedVideo"}))); } @@ -4900,15 +4723,13 @@ ObjectNode videoFromMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode p } @ExcludeFromGeneratedCoverageReport - ObjectNode generatedVideoFromMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode generatedVideoFromMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"_self"}) != null) { Common.setValueByPath( toObject, new String[] {"video"}, videoFromMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"_self"})), toObject)); @@ -4918,8 +4739,7 @@ ObjectNode generatedVideoFromMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode generateVideosResponseFromMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode generateVideosResponseFromMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"generatedSamples"}) != null) { ArrayNode keyArray = @@ -4928,7 +4748,7 @@ ObjectNode generateVideosResponseFromMldev( ArrayNode result = objectMapper.createArrayNode(); for (JsonNode item : keyArray) { - result.add(generatedVideoFromMldev(apiClient, JsonSerializable.toJsonNode(item), toObject)); + result.add(generatedVideoFromMldev(JsonSerializable.toJsonNode(item), toObject)); } Common.setValueByPath(toObject, new String[] {"generatedVideos"}, result); } @@ -4951,8 +4771,7 @@ ObjectNode generateVideosResponseFromMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode generateVideosOperationFromMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode generateVideosOperationFromMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"name"}) != null) { Common.setValueByPath( @@ -4988,7 +4807,6 @@ ObjectNode generateVideosOperationFromMldev( toObject, new String[] {"response"}, generateVideosResponseFromMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath( fromObject, new String[] {"response", "generateVideoResponse"})), @@ -4999,8 +4817,7 @@ ObjectNode generateVideosOperationFromMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode videoMetadataFromVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode videoMetadataFromVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"fps"}) != null) { Common.setValueByPath( @@ -5025,7 +4842,7 @@ ObjectNode videoMetadataFromVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode blobFromVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode blobFromVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"displayName"}) != null) { Common.setValueByPath( @@ -5052,7 +4869,7 @@ ObjectNode blobFromVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode p } @ExcludeFromGeneratedCoverageReport - ObjectNode fileDataFromVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode fileDataFromVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"displayName"}) != null) { Common.setValueByPath( @@ -5079,14 +4896,13 @@ ObjectNode fileDataFromVertex(ApiClient apiClient, JsonNode fromObject, ObjectNo } @ExcludeFromGeneratedCoverageReport - ObjectNode partFromVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode partFromVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"videoMetadata"}) != null) { Common.setValueByPath( toObject, new String[] {"videoMetadata"}, videoMetadataFromVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"videoMetadata"})), toObject)); @@ -5104,7 +4920,6 @@ ObjectNode partFromVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode p toObject, new String[] {"inlineData"}, blobFromVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"inlineData"})), toObject)); @@ -5115,7 +4930,6 @@ ObjectNode partFromVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode p toObject, new String[] {"fileData"}, fileDataFromVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"fileData"})), toObject)); @@ -5167,7 +4981,7 @@ ObjectNode partFromVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode p } @ExcludeFromGeneratedCoverageReport - ObjectNode contentFromVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode contentFromVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"parts"}) != null) { ArrayNode keyArray = (ArrayNode) Common.getValueByPath(fromObject, new String[] {"parts"}); @@ -5175,7 +4989,7 @@ ObjectNode contentFromVertex(ApiClient apiClient, JsonNode fromObject, ObjectNod ArrayNode result = objectMapper.createArrayNode(); for (JsonNode item : keyArray) { - result.add(partFromVertex(apiClient, JsonSerializable.toJsonNode(item), toObject)); + result.add(partFromVertex(JsonSerializable.toJsonNode(item), toObject)); } Common.setValueByPath(toObject, new String[] {"parts"}, result); } @@ -5191,8 +5005,7 @@ ObjectNode contentFromVertex(ApiClient apiClient, JsonNode fromObject, ObjectNod } @ExcludeFromGeneratedCoverageReport - ObjectNode citationMetadataFromVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode citationMetadataFromVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"citations"}) != null) { Common.setValueByPath( @@ -5205,8 +5018,7 @@ ObjectNode citationMetadataFromVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode urlMetadataFromVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode urlMetadataFromVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"retrievedUrl"}) != null) { Common.setValueByPath( @@ -5226,8 +5038,7 @@ ObjectNode urlMetadataFromVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode urlContextMetadataFromVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode urlContextMetadataFromVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"urlMetadata"}) != null) { ArrayNode keyArray = @@ -5236,7 +5047,7 @@ ObjectNode urlContextMetadataFromVertex( ArrayNode result = objectMapper.createArrayNode(); for (JsonNode item : keyArray) { - result.add(urlMetadataFromVertex(apiClient, JsonSerializable.toJsonNode(item), toObject)); + result.add(urlMetadataFromVertex(JsonSerializable.toJsonNode(item), toObject)); } Common.setValueByPath(toObject, new String[] {"urlMetadata"}, result); } @@ -5245,15 +5056,13 @@ ObjectNode urlContextMetadataFromVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode candidateFromVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode candidateFromVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"content"}) != null) { Common.setValueByPath( toObject, new String[] {"content"}, contentFromVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"content"})), toObject)); @@ -5264,7 +5073,6 @@ ObjectNode candidateFromVertex( toObject, new String[] {"citationMetadata"}, citationMetadataFromVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"citationMetadata"})), toObject)); @@ -5289,7 +5097,6 @@ ObjectNode candidateFromVertex( toObject, new String[] {"urlContextMetadata"}, urlContextMetadataFromVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"urlContextMetadata"})), toObject)); @@ -5334,8 +5141,7 @@ ObjectNode candidateFromVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode generateContentResponseFromVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode generateContentResponseFromVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"candidates"}) != null) { ArrayNode keyArray = @@ -5344,7 +5150,7 @@ ObjectNode generateContentResponseFromVertex( ArrayNode result = objectMapper.createArrayNode(); for (JsonNode item : keyArray) { - result.add(candidateFromVertex(apiClient, JsonSerializable.toJsonNode(item), toObject)); + result.add(candidateFromVertex(JsonSerializable.toJsonNode(item), toObject)); } Common.setValueByPath(toObject, new String[] {"candidates"}, result); } @@ -5388,8 +5194,7 @@ ObjectNode generateContentResponseFromVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode contentEmbeddingStatisticsFromVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode contentEmbeddingStatisticsFromVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"truncated"}) != null) { Common.setValueByPath( @@ -5409,8 +5214,7 @@ ObjectNode contentEmbeddingStatisticsFromVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode contentEmbeddingFromVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode contentEmbeddingFromVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"values"}) != null) { Common.setValueByPath( @@ -5424,7 +5228,6 @@ ObjectNode contentEmbeddingFromVertex( toObject, new String[] {"statistics"}, contentEmbeddingStatisticsFromVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"statistics"})), toObject)); @@ -5434,8 +5237,7 @@ ObjectNode contentEmbeddingFromVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode embedContentMetadataFromVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode embedContentMetadataFromVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"billableCharacterCount"}) != null) { Common.setValueByPath( @@ -5448,8 +5250,7 @@ ObjectNode embedContentMetadataFromVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode embedContentResponseFromVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode embedContentResponseFromVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"predictions[]", "embeddings"}) != null) { ArrayNode keyArray = @@ -5459,8 +5260,7 @@ ObjectNode embedContentResponseFromVertex( ArrayNode result = objectMapper.createArrayNode(); for (JsonNode item : keyArray) { - result.add( - contentEmbeddingFromVertex(apiClient, JsonSerializable.toJsonNode(item), toObject)); + result.add(contentEmbeddingFromVertex(JsonSerializable.toJsonNode(item), toObject)); } Common.setValueByPath(toObject, new String[] {"embeddings"}, result); } @@ -5470,7 +5270,6 @@ ObjectNode embedContentResponseFromVertex( toObject, new String[] {"metadata"}, embedContentMetadataFromVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"metadata"})), toObject)); @@ -5480,7 +5279,7 @@ ObjectNode embedContentResponseFromVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode imageFromVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode imageFromVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"gcsUri"}) != null) { Common.setValueByPath( @@ -5494,7 +5293,6 @@ ObjectNode imageFromVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode toObject, new String[] {"imageBytes"}, Transformers.tBytes( - this.apiClient, Common.getValueByPath(fromObject, new String[] {"bytesBase64Encoded"}))); } @@ -5509,8 +5307,7 @@ ObjectNode imageFromVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode } @ExcludeFromGeneratedCoverageReport - ObjectNode safetyAttributesFromVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode safetyAttributesFromVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"safetyAttributes", "categories"}) != null) { @@ -5538,15 +5335,13 @@ ObjectNode safetyAttributesFromVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode generatedImageFromVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode generatedImageFromVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"_self"}) != null) { Common.setValueByPath( toObject, new String[] {"image"}, imageFromVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"_self"})), toObject)); @@ -5564,7 +5359,6 @@ ObjectNode generatedImageFromVertex( toObject, new String[] {"safetyAttributes"}, safetyAttributesFromVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"_self"})), toObject)); @@ -5581,8 +5375,7 @@ ObjectNode generatedImageFromVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode generateImagesResponseFromVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode generateImagesResponseFromVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"predictions"}) != null) { ArrayNode keyArray = @@ -5591,8 +5384,7 @@ ObjectNode generateImagesResponseFromVertex( ArrayNode result = objectMapper.createArrayNode(); for (JsonNode item : keyArray) { - result.add( - generatedImageFromVertex(apiClient, JsonSerializable.toJsonNode(item), toObject)); + result.add(generatedImageFromVertex(JsonSerializable.toJsonNode(item), toObject)); } Common.setValueByPath(toObject, new String[] {"generatedImages"}, result); } @@ -5603,7 +5395,6 @@ ObjectNode generateImagesResponseFromVertex( toObject, new String[] {"positivePromptSafetyAttributes"}, safetyAttributesFromVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath( fromObject, new String[] {"positivePromptSafetyAttributes"})), @@ -5614,8 +5405,7 @@ ObjectNode generateImagesResponseFromVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode editImageResponseFromVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode editImageResponseFromVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"predictions"}) != null) { ArrayNode keyArray = @@ -5624,8 +5414,7 @@ ObjectNode editImageResponseFromVertex( ArrayNode result = objectMapper.createArrayNode(); for (JsonNode item : keyArray) { - result.add( - generatedImageFromVertex(apiClient, JsonSerializable.toJsonNode(item), toObject)); + result.add(generatedImageFromVertex(JsonSerializable.toJsonNode(item), toObject)); } Common.setValueByPath(toObject, new String[] {"generatedImages"}, result); } @@ -5634,8 +5423,7 @@ ObjectNode editImageResponseFromVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode upscaleImageResponseFromVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode upscaleImageResponseFromVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"predictions"}) != null) { ArrayNode keyArray = @@ -5644,8 +5432,7 @@ ObjectNode upscaleImageResponseFromVertex( ArrayNode result = objectMapper.createArrayNode(); for (JsonNode item : keyArray) { - result.add( - generatedImageFromVertex(apiClient, JsonSerializable.toJsonNode(item), toObject)); + result.add(generatedImageFromVertex(JsonSerializable.toJsonNode(item), toObject)); } Common.setValueByPath(toObject, new String[] {"generatedImages"}, result); } @@ -5654,7 +5441,7 @@ ObjectNode upscaleImageResponseFromVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode endpointFromVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode endpointFromVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"endpoint"}) != null) { Common.setValueByPath( @@ -5674,8 +5461,7 @@ ObjectNode endpointFromVertex(ApiClient apiClient, JsonNode fromObject, ObjectNo } @ExcludeFromGeneratedCoverageReport - ObjectNode tunedModelInfoFromVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode tunedModelInfoFromVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath( fromObject, new String[] {"labels", "google-vertex-llm-tuning-base-model-id"}) @@ -5705,8 +5491,7 @@ ObjectNode tunedModelInfoFromVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode checkpointFromVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode checkpointFromVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"checkpointId"}) != null) { Common.setValueByPath( @@ -5733,7 +5518,7 @@ ObjectNode checkpointFromVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode modelFromVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode modelFromVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"name"}) != null) { Common.setValueByPath( @@ -5770,7 +5555,7 @@ ObjectNode modelFromVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode ArrayNode result = objectMapper.createArrayNode(); for (JsonNode item : keyArray) { - result.add(endpointFromVertex(apiClient, JsonSerializable.toJsonNode(item), toObject)); + result.add(endpointFromVertex(JsonSerializable.toJsonNode(item), toObject)); } Common.setValueByPath(toObject, new String[] {"endpoints"}, result); } @@ -5787,7 +5572,6 @@ ObjectNode modelFromVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode toObject, new String[] {"tunedModelInfo"}, tunedModelInfoFromVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"_self"})), toObject)); @@ -5807,7 +5591,7 @@ ObjectNode modelFromVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode ArrayNode result = objectMapper.createArrayNode(); for (JsonNode item : keyArray) { - result.add(checkpointFromVertex(apiClient, JsonSerializable.toJsonNode(item), toObject)); + result.add(checkpointFromVertex(JsonSerializable.toJsonNode(item), toObject)); } Common.setValueByPath(toObject, new String[] {"checkpoints"}, result); } @@ -5816,8 +5600,7 @@ ObjectNode modelFromVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode } @ExcludeFromGeneratedCoverageReport - ObjectNode listModelsResponseFromVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode listModelsResponseFromVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"nextPageToken"}) != null) { Common.setValueByPath( @@ -5830,12 +5613,12 @@ ObjectNode listModelsResponseFromVertex( ArrayNode keyArray = (ArrayNode) Transformers.tExtractModels( - this.apiClient, Common.getValueByPath(fromObject, new String[] {"_self"})); + Common.getValueByPath(fromObject, new String[] {"_self"})); ObjectMapper objectMapper = new ObjectMapper(); ArrayNode result = objectMapper.createArrayNode(); for (JsonNode item : keyArray) { - result.add(modelFromVertex(apiClient, JsonSerializable.toJsonNode(item), toObject)); + result.add(modelFromVertex(JsonSerializable.toJsonNode(item), toObject)); } Common.setValueByPath(toObject, new String[] {"models"}, result); } @@ -5844,16 +5627,14 @@ ObjectNode listModelsResponseFromVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode deleteModelResponseFromVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode deleteModelResponseFromVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); return toObject; } @ExcludeFromGeneratedCoverageReport - ObjectNode countTokensResponseFromVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode countTokensResponseFromVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"totalTokens"}) != null) { Common.setValueByPath( @@ -5866,8 +5647,7 @@ ObjectNode countTokensResponseFromVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode computeTokensResponseFromVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode computeTokensResponseFromVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"tokensInfo"}) != null) { Common.setValueByPath( @@ -5880,7 +5660,7 @@ ObjectNode computeTokensResponseFromVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode videoFromVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode videoFromVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"gcsUri"}) != null) { Common.setValueByPath( @@ -5894,7 +5674,6 @@ ObjectNode videoFromVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode toObject, new String[] {"videoBytes"}, Transformers.tBytes( - this.apiClient, Common.getValueByPath(fromObject, new String[] {"bytesBase64Encoded"}))); } @@ -5909,15 +5688,13 @@ ObjectNode videoFromVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode } @ExcludeFromGeneratedCoverageReport - ObjectNode generatedVideoFromVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode generatedVideoFromVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"_self"}) != null) { Common.setValueByPath( toObject, new String[] {"video"}, videoFromVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"_self"})), toObject)); @@ -5927,8 +5704,7 @@ ObjectNode generatedVideoFromVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode generateVideosResponseFromVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode generateVideosResponseFromVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"videos"}) != null) { ArrayNode keyArray = (ArrayNode) Common.getValueByPath(fromObject, new String[] {"videos"}); @@ -5936,8 +5712,7 @@ ObjectNode generateVideosResponseFromVertex( ArrayNode result = objectMapper.createArrayNode(); for (JsonNode item : keyArray) { - result.add( - generatedVideoFromVertex(apiClient, JsonSerializable.toJsonNode(item), toObject)); + result.add(generatedVideoFromVertex(JsonSerializable.toJsonNode(item), toObject)); } Common.setValueByPath(toObject, new String[] {"generatedVideos"}, result); } @@ -5960,8 +5735,7 @@ ObjectNode generateVideosResponseFromVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode generateVideosOperationFromVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode generateVideosOperationFromVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"name"}) != null) { Common.setValueByPath( @@ -5996,7 +5770,6 @@ ObjectNode generateVideosOperationFromVertex( toObject, new String[] {"response"}, generateVideosResponseFromVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"response"})), toObject)); @@ -6063,9 +5836,9 @@ GenerateContentResponse privateGenerateContent( JsonNode responseNode = JsonSerializable.stringToJsonNode(responseString); if (this.apiClient.vertexAI()) { - responseNode = generateContentResponseFromVertex(this.apiClient, responseNode, null); + responseNode = generateContentResponseFromVertex(responseNode, null); } else { - responseNode = generateContentResponseFromMldev(this.apiClient, responseNode, null); + responseNode = generateContentResponseFromMldev(responseNode, null); } return JsonSerializable.fromJsonNode(responseNode, GenerateContentResponse.class); } @@ -6188,9 +5961,9 @@ EmbedContentResponse privateEmbedContent( JsonNode responseNode = JsonSerializable.stringToJsonNode(responseString); if (this.apiClient.vertexAI()) { - responseNode = embedContentResponseFromVertex(this.apiClient, responseNode, null); + responseNode = embedContentResponseFromVertex(responseNode, null); } else { - responseNode = embedContentResponseFromMldev(this.apiClient, responseNode, null); + responseNode = embedContentResponseFromMldev(responseNode, null); } return JsonSerializable.fromJsonNode(responseNode, EmbedContentResponse.class); } @@ -6254,9 +6027,9 @@ GenerateImagesResponse privateGenerateImages( JsonNode responseNode = JsonSerializable.stringToJsonNode(responseString); if (this.apiClient.vertexAI()) { - responseNode = generateImagesResponseFromVertex(this.apiClient, responseNode, null); + responseNode = generateImagesResponseFromVertex(responseNode, null); } else { - responseNode = generateImagesResponseFromMldev(this.apiClient, responseNode, null); + responseNode = generateImagesResponseFromMldev(responseNode, null); } return JsonSerializable.fromJsonNode(responseNode, GenerateImagesResponse.class); } @@ -6322,7 +6095,7 @@ EditImageResponse privateEditImage( JsonNode responseNode = JsonSerializable.stringToJsonNode(responseString); if (this.apiClient.vertexAI()) { - responseNode = editImageResponseFromVertex(this.apiClient, responseNode, null); + responseNode = editImageResponseFromVertex(responseNode, null); } else { throw new UnsupportedOperationException( "This method is not supported by the Gemini Developer API."); @@ -6388,7 +6161,7 @@ UpscaleImageResponse privateUpscaleImage( JsonNode responseNode = JsonSerializable.stringToJsonNode(responseString); if (this.apiClient.vertexAI()) { - responseNode = upscaleImageResponseFromVertex(this.apiClient, responseNode, null); + responseNode = upscaleImageResponseFromVertex(responseNode, null); } else { throw new UnsupportedOperationException( "This method is not supported by the Gemini Developer API."); @@ -6456,9 +6229,9 @@ public Model get(String model, GetModelConfig config) { JsonNode responseNode = JsonSerializable.stringToJsonNode(responseString); if (this.apiClient.vertexAI()) { - responseNode = modelFromVertex(this.apiClient, responseNode, null); + responseNode = modelFromVertex(responseNode, null); } else { - responseNode = modelFromMldev(this.apiClient, responseNode, null); + responseNode = modelFromMldev(responseNode, null); } return JsonSerializable.fromJsonNode(responseNode, Model.class); } @@ -6515,9 +6288,9 @@ ListModelsResponse privateList(ListModelsConfig config) { JsonNode responseNode = JsonSerializable.stringToJsonNode(responseString); if (this.apiClient.vertexAI()) { - responseNode = listModelsResponseFromVertex(this.apiClient, responseNode, null); + responseNode = listModelsResponseFromVertex(responseNode, null); } else { - responseNode = listModelsResponseFromMldev(this.apiClient, responseNode, null); + responseNode = listModelsResponseFromMldev(responseNode, null); } return JsonSerializable.fromJsonNode(responseNode, ListModelsResponse.class); } @@ -6588,9 +6361,9 @@ public Model update(String model, UpdateModelConfig config) { JsonNode responseNode = JsonSerializable.stringToJsonNode(responseString); if (this.apiClient.vertexAI()) { - responseNode = modelFromVertex(this.apiClient, responseNode, null); + responseNode = modelFromVertex(responseNode, null); } else { - responseNode = modelFromMldev(this.apiClient, responseNode, null); + responseNode = modelFromMldev(responseNode, null); } return JsonSerializable.fromJsonNode(responseNode, Model.class); } @@ -6655,9 +6428,9 @@ public DeleteModelResponse delete(String model, DeleteModelConfig config) { JsonNode responseNode = JsonSerializable.stringToJsonNode(responseString); if (this.apiClient.vertexAI()) { - responseNode = deleteModelResponseFromVertex(this.apiClient, responseNode, null); + responseNode = deleteModelResponseFromVertex(responseNode, null); } else { - responseNode = deleteModelResponseFromMldev(this.apiClient, responseNode, null); + responseNode = deleteModelResponseFromMldev(responseNode, null); } return JsonSerializable.fromJsonNode(responseNode, DeleteModelResponse.class); } @@ -6731,9 +6504,9 @@ public CountTokensResponse countTokens( JsonNode responseNode = JsonSerializable.stringToJsonNode(responseString); if (this.apiClient.vertexAI()) { - responseNode = countTokensResponseFromVertex(this.apiClient, responseNode, null); + responseNode = countTokensResponseFromVertex(responseNode, null); } else { - responseNode = countTokensResponseFromMldev(this.apiClient, responseNode, null); + responseNode = countTokensResponseFromMldev(responseNode, null); } return JsonSerializable.fromJsonNode(responseNode, CountTokensResponse.class); } @@ -6803,7 +6576,7 @@ public ComputeTokensResponse computeTokens( JsonNode responseNode = JsonSerializable.stringToJsonNode(responseString); if (this.apiClient.vertexAI()) { - responseNode = computeTokensResponseFromVertex(this.apiClient, responseNode, null); + responseNode = computeTokensResponseFromVertex(responseNode, null); } else { throw new UnsupportedOperationException( "This method is not supported by the Gemini Developer API."); @@ -6891,9 +6664,9 @@ public GenerateVideosOperation generateVideos( JsonNode responseNode = JsonSerializable.stringToJsonNode(responseString); if (this.apiClient.vertexAI()) { - responseNode = generateVideosOperationFromVertex(this.apiClient, responseNode, null); + responseNode = generateVideosOperationFromVertex(responseNode, null); } else { - responseNode = generateVideosOperationFromMldev(this.apiClient, responseNode, null); + responseNode = generateVideosOperationFromMldev(responseNode, null); } return JsonSerializable.fromJsonNode(responseNode, GenerateVideosOperation.class); } @@ -6913,8 +6686,7 @@ public GenerateVideosOperation generateVideos( */ public GenerateContentResponse generateContent( String model, List contents, GenerateContentConfig config) { - GenerateContentConfig transformedConfig = - AfcUtil.transformGenerateContentConfig(apiClient, config); + GenerateContentConfig transformedConfig = AfcUtil.transformGenerateContentConfig(config); if (AfcUtil.shouldDisableAfc(transformedConfig)) { return privateGenerateContent(model, contents, transformedConfig); } @@ -7009,10 +6781,8 @@ public GenerateContentResponse generateContent( */ public ResponseStream generateContentStream( String model, List contents, GenerateContentConfig config) { - GenerateContentConfig transformedConfig = - AfcUtil.transformGenerateContentConfig(apiClient, config); - if (AfcUtil.hasCallableTool(apiClient, config) - && !AfcUtil.shouldDisableAfc(transformedConfig)) { + GenerateContentConfig transformedConfig = AfcUtil.transformGenerateContentConfig(config); + if (AfcUtil.hasCallableTool(config) && !AfcUtil.shouldDisableAfc(transformedConfig)) { logger.warning( "In generateContentStream method, detected that automatic function calling is enabled in" + " the config.AutomaticFunctionCalling(), and callable tool is present in the" diff --git a/src/main/java/com/google/genai/Operations.java b/src/main/java/com/google/genai/Operations.java index 7e077527f80..33b9c1a0acf 100644 --- a/src/main/java/com/google/genai/Operations.java +++ b/src/main/java/com/google/genai/Operations.java @@ -49,8 +49,7 @@ public Operations(ApiClient apiClient) { } @ExcludeFromGeneratedCoverageReport - ObjectNode getOperationParametersToMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode getOperationParametersToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"operationName"}) != null) { Common.setValueByPath( @@ -70,8 +69,7 @@ ObjectNode getOperationParametersToMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode getOperationParametersToVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode getOperationParametersToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"operationName"}) != null) { Common.setValueByPath( @@ -91,8 +89,7 @@ ObjectNode getOperationParametersToVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode fetchPredictOperationParametersToVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode fetchPredictOperationParametersToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"operationName"}) != null) { Common.setValueByPath( @@ -119,7 +116,7 @@ ObjectNode fetchPredictOperationParametersToVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode videoFromMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode videoFromMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"video", "uri"}) != null) { Common.setValueByPath( @@ -133,7 +130,6 @@ ObjectNode videoFromMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode p toObject, new String[] {"videoBytes"}, Transformers.tBytes( - this.apiClient, Common.getValueByPath(fromObject, new String[] {"video", "encodedVideo"}))); } @@ -148,15 +144,13 @@ ObjectNode videoFromMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode p } @ExcludeFromGeneratedCoverageReport - ObjectNode generatedVideoFromMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode generatedVideoFromMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"_self"}) != null) { Common.setValueByPath( toObject, new String[] {"video"}, videoFromMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"_self"})), toObject)); @@ -166,8 +160,7 @@ ObjectNode generatedVideoFromMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode generateVideosResponseFromMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode generateVideosResponseFromMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"generatedSamples"}) != null) { ArrayNode keyArray = @@ -176,7 +169,7 @@ ObjectNode generateVideosResponseFromMldev( ArrayNode result = objectMapper.createArrayNode(); for (JsonNode item : keyArray) { - result.add(generatedVideoFromMldev(apiClient, JsonSerializable.toJsonNode(item), toObject)); + result.add(generatedVideoFromMldev(JsonSerializable.toJsonNode(item), toObject)); } Common.setValueByPath(toObject, new String[] {"generatedVideos"}, result); } @@ -199,8 +192,7 @@ ObjectNode generateVideosResponseFromMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode generateVideosOperationFromMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode generateVideosOperationFromMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"name"}) != null) { Common.setValueByPath( @@ -236,7 +228,6 @@ ObjectNode generateVideosOperationFromMldev( toObject, new String[] {"response"}, generateVideosResponseFromMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath( fromObject, new String[] {"response", "generateVideoResponse"})), @@ -247,7 +238,7 @@ ObjectNode generateVideosOperationFromMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode videoFromVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode videoFromVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"gcsUri"}) != null) { Common.setValueByPath( @@ -261,7 +252,6 @@ ObjectNode videoFromVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode toObject, new String[] {"videoBytes"}, Transformers.tBytes( - this.apiClient, Common.getValueByPath(fromObject, new String[] {"bytesBase64Encoded"}))); } @@ -276,15 +266,13 @@ ObjectNode videoFromVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode } @ExcludeFromGeneratedCoverageReport - ObjectNode generatedVideoFromVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode generatedVideoFromVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"_self"}) != null) { Common.setValueByPath( toObject, new String[] {"video"}, videoFromVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"_self"})), toObject)); @@ -294,8 +282,7 @@ ObjectNode generatedVideoFromVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode generateVideosResponseFromVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode generateVideosResponseFromVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"videos"}) != null) { ArrayNode keyArray = (ArrayNode) Common.getValueByPath(fromObject, new String[] {"videos"}); @@ -303,8 +290,7 @@ ObjectNode generateVideosResponseFromVertex( ArrayNode result = objectMapper.createArrayNode(); for (JsonNode item : keyArray) { - result.add( - generatedVideoFromVertex(apiClient, JsonSerializable.toJsonNode(item), toObject)); + result.add(generatedVideoFromVertex(JsonSerializable.toJsonNode(item), toObject)); } Common.setValueByPath(toObject, new String[] {"generatedVideos"}, result); } @@ -327,8 +313,7 @@ ObjectNode generateVideosResponseFromVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode generateVideosOperationFromVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode generateVideosOperationFromVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"name"}) != null) { Common.setValueByPath( @@ -363,7 +348,6 @@ ObjectNode generateVideosOperationFromVertex( toObject, new String[] {"response"}, generateVideosResponseFromVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"response"})), toObject)); @@ -388,10 +372,10 @@ GenerateVideosOperation privateGetVideosOperation( ObjectNode body; String path; if (this.apiClient.vertexAI()) { - body = getOperationParametersToVertex(this.apiClient, parameterNode, null); + body = getOperationParametersToVertex(parameterNode, null); path = Common.formatMap("{operationName}", body.get("_url")); } else { - body = getOperationParametersToMldev(this.apiClient, parameterNode, null); + body = getOperationParametersToMldev(parameterNode, null); if (body.get("_url") != null) { path = Common.formatMap("{operationName}", body.get("_url")); } else { @@ -427,9 +411,9 @@ GenerateVideosOperation privateGetVideosOperation( JsonNode responseNode = JsonSerializable.stringToJsonNode(responseString); if (this.apiClient.vertexAI()) { - responseNode = generateVideosOperationFromVertex(this.apiClient, responseNode, null); + responseNode = generateVideosOperationFromVertex(responseNode, null); } else { - responseNode = generateVideosOperationFromMldev(this.apiClient, responseNode, null); + responseNode = generateVideosOperationFromMldev(responseNode, null); } return JsonSerializable.fromJsonNode(responseNode, GenerateVideosOperation.class); } @@ -455,7 +439,7 @@ GenerateVideosOperation privateFetchPredictVideosOperation( ObjectNode body; String path; if (this.apiClient.vertexAI()) { - body = fetchPredictOperationParametersToVertex(this.apiClient, parameterNode, null); + body = fetchPredictOperationParametersToVertex(parameterNode, null); path = Common.formatMap("{resourceName}:fetchPredictOperation", body.get("_url")); } else { throw new UnsupportedOperationException( @@ -490,7 +474,7 @@ GenerateVideosOperation privateFetchPredictVideosOperation( JsonNode responseNode = JsonSerializable.stringToJsonNode(responseString); if (this.apiClient.vertexAI()) { - responseNode = generateVideosOperationFromVertex(this.apiClient, responseNode, null); + responseNode = generateVideosOperationFromVertex(responseNode, null); } else { throw new UnsupportedOperationException( "This method is not supported by the Gemini Developer API."); diff --git a/src/main/java/com/google/genai/ResponseStream.java b/src/main/java/com/google/genai/ResponseStream.java index 7edff77c575..95fbde6a9eb 100644 --- a/src/main/java/com/google/genai/ResponseStream.java +++ b/src/main/java/com/google/genai/ResponseStream.java @@ -60,9 +60,7 @@ class ResponseStreamIterator implements Iterator { this.obj = obj; try { this.converter = - obj.getClass() - .getDeclaredMethod( - converterName, ApiClient.class, JsonNode.class, ObjectNode.class); + obj.getClass().getDeclaredMethod(converterName, JsonNode.class, ObjectNode.class); } catch (NoSuchMethodException e) { throw new IllegalStateException("Failed to find converter method " + converterName, e); } @@ -100,7 +98,7 @@ public T next() { nextJson = readNextJson(); try { JsonNode currentJsonNode = JsonSerializable.stringToJsonNode(currentJson); - currentJsonNode = (JsonNode) converter.invoke(obj, null, currentJsonNode, null); + currentJsonNode = (JsonNode) converter.invoke(obj, currentJsonNode, null); if (recordingHistory) { T response = JsonSerializable.fromJsonNode(currentJsonNode, clazz); history.add(response); diff --git a/src/main/java/com/google/genai/TokensConverters.java b/src/main/java/com/google/genai/TokensConverters.java index 47a69e9ae4b..d7d12f41192 100644 --- a/src/main/java/com/google/genai/TokensConverters.java +++ b/src/main/java/com/google/genai/TokensConverters.java @@ -31,8 +31,7 @@ public TokensConverters(ApiClient apiClient) { } @ExcludeFromGeneratedCoverageReport - ObjectNode prebuiltVoiceConfigToMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode prebuiltVoiceConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"voiceName"}) != null) { Common.setValueByPath( @@ -45,8 +44,7 @@ ObjectNode prebuiltVoiceConfigToMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode prebuiltVoiceConfigToVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode prebuiltVoiceConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"voiceName"}) != null) { Common.setValueByPath( @@ -59,14 +57,13 @@ ObjectNode prebuiltVoiceConfigToVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode voiceConfigToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode voiceConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"prebuiltVoiceConfig"}) != null) { Common.setValueByPath( toObject, new String[] {"prebuiltVoiceConfig"}, prebuiltVoiceConfigToMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"prebuiltVoiceConfig"})), toObject)); @@ -76,15 +73,13 @@ ObjectNode voiceConfigToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNo } @ExcludeFromGeneratedCoverageReport - ObjectNode voiceConfigToVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode voiceConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"prebuiltVoiceConfig"}) != null) { Common.setValueByPath( toObject, new String[] {"prebuiltVoiceConfig"}, prebuiltVoiceConfigToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"prebuiltVoiceConfig"})), toObject)); @@ -94,8 +89,7 @@ ObjectNode voiceConfigToVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode speakerVoiceConfigToMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode speakerVoiceConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"speaker"}) != null) { Common.setValueByPath( @@ -109,7 +103,6 @@ ObjectNode speakerVoiceConfigToMldev( toObject, new String[] {"voiceConfig"}, voiceConfigToMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"voiceConfig"})), toObject)); @@ -119,8 +112,7 @@ ObjectNode speakerVoiceConfigToMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode speakerVoiceConfigToVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode speakerVoiceConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"speaker"}))) { throw new IllegalArgumentException("speaker parameter is not supported in Vertex AI."); @@ -134,8 +126,7 @@ ObjectNode speakerVoiceConfigToVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode multiSpeakerVoiceConfigToMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode multiSpeakerVoiceConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"speakerVoiceConfigs"}) != null) { ArrayNode keyArray = @@ -144,8 +135,7 @@ ObjectNode multiSpeakerVoiceConfigToMldev( ArrayNode result = objectMapper.createArrayNode(); for (JsonNode item : keyArray) { - result.add( - speakerVoiceConfigToMldev(apiClient, JsonSerializable.toJsonNode(item), toObject)); + result.add(speakerVoiceConfigToMldev(JsonSerializable.toJsonNode(item), toObject)); } Common.setValueByPath(toObject, new String[] {"speakerVoiceConfigs"}, result); } @@ -154,8 +144,7 @@ ObjectNode multiSpeakerVoiceConfigToMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode multiSpeakerVoiceConfigToVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode multiSpeakerVoiceConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"speakerVoiceConfigs"}))) { throw new IllegalArgumentException( @@ -166,15 +155,13 @@ ObjectNode multiSpeakerVoiceConfigToVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode speechConfigToMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode speechConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"voiceConfig"}) != null) { Common.setValueByPath( toObject, new String[] {"voiceConfig"}, voiceConfigToMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"voiceConfig"})), toObject)); @@ -185,7 +172,6 @@ ObjectNode speechConfigToMldev( toObject, new String[] {"multiSpeakerVoiceConfig"}, multiSpeakerVoiceConfigToMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"multiSpeakerVoiceConfig"})), toObject)); @@ -202,15 +188,13 @@ ObjectNode speechConfigToMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode speechConfigToVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode speechConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"voiceConfig"}) != null) { Common.setValueByPath( toObject, new String[] {"voiceConfig"}, voiceConfigToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"voiceConfig"})), toObject)); @@ -233,8 +217,7 @@ ObjectNode speechConfigToVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode videoMetadataToMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode videoMetadataToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"fps"}) != null) { Common.setValueByPath( @@ -259,8 +242,7 @@ ObjectNode videoMetadataToMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode videoMetadataToVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode videoMetadataToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"fps"}) != null) { Common.setValueByPath( @@ -285,7 +267,7 @@ ObjectNode videoMetadataToVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode blobToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode blobToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"displayName"}))) { throw new IllegalArgumentException("displayName parameter is not supported in Gemini API."); @@ -309,7 +291,7 @@ ObjectNode blobToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode pare } @ExcludeFromGeneratedCoverageReport - ObjectNode blobToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode blobToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"displayName"}) != null) { Common.setValueByPath( @@ -336,7 +318,7 @@ ObjectNode blobToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode par } @ExcludeFromGeneratedCoverageReport - ObjectNode fileDataToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode fileDataToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"displayName"}))) { throw new IllegalArgumentException("displayName parameter is not supported in Gemini API."); @@ -360,7 +342,7 @@ ObjectNode fileDataToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode } @ExcludeFromGeneratedCoverageReport - ObjectNode fileDataToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode fileDataToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"displayName"}) != null) { Common.setValueByPath( @@ -387,14 +369,13 @@ ObjectNode fileDataToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode } @ExcludeFromGeneratedCoverageReport - ObjectNode partToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode partToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"videoMetadata"}) != null) { Common.setValueByPath( toObject, new String[] {"videoMetadata"}, videoMetadataToMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"videoMetadata"})), toObject)); @@ -412,7 +393,6 @@ ObjectNode partToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode pare toObject, new String[] {"inlineData"}, blobToMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"inlineData"})), toObject)); @@ -423,7 +403,6 @@ ObjectNode partToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode pare toObject, new String[] {"fileData"}, fileDataToMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"fileData"})), toObject)); @@ -475,14 +454,13 @@ ObjectNode partToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode pare } @ExcludeFromGeneratedCoverageReport - ObjectNode partToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode partToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"videoMetadata"}) != null) { Common.setValueByPath( toObject, new String[] {"videoMetadata"}, videoMetadataToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"videoMetadata"})), toObject)); @@ -500,7 +478,6 @@ ObjectNode partToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode par toObject, new String[] {"inlineData"}, blobToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"inlineData"})), toObject)); @@ -511,7 +488,6 @@ ObjectNode partToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode par toObject, new String[] {"fileData"}, fileDataToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"fileData"})), toObject)); @@ -563,7 +539,7 @@ ObjectNode partToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode par } @ExcludeFromGeneratedCoverageReport - ObjectNode contentToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode contentToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"parts"}) != null) { ArrayNode keyArray = (ArrayNode) Common.getValueByPath(fromObject, new String[] {"parts"}); @@ -571,7 +547,7 @@ ObjectNode contentToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode p ArrayNode result = objectMapper.createArrayNode(); for (JsonNode item : keyArray) { - result.add(partToMldev(apiClient, JsonSerializable.toJsonNode(item), toObject)); + result.add(partToMldev(JsonSerializable.toJsonNode(item), toObject)); } Common.setValueByPath(toObject, new String[] {"parts"}, result); } @@ -587,7 +563,7 @@ ObjectNode contentToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode p } @ExcludeFromGeneratedCoverageReport - ObjectNode contentToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode contentToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"parts"}) != null) { ArrayNode keyArray = (ArrayNode) Common.getValueByPath(fromObject, new String[] {"parts"}); @@ -595,7 +571,7 @@ ObjectNode contentToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode ArrayNode result = objectMapper.createArrayNode(); for (JsonNode item : keyArray) { - result.add(partToVertex(apiClient, JsonSerializable.toJsonNode(item), toObject)); + result.add(partToVertex(JsonSerializable.toJsonNode(item), toObject)); } Common.setValueByPath(toObject, new String[] {"parts"}, result); } @@ -611,8 +587,7 @@ ObjectNode contentToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode } @ExcludeFromGeneratedCoverageReport - ObjectNode functionDeclarationToMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode functionDeclarationToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"behavior"}) != null) { Common.setValueByPath( @@ -667,8 +642,7 @@ ObjectNode functionDeclarationToMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode functionDeclarationToVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode functionDeclarationToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"behavior"}))) { throw new IllegalArgumentException("behavior parameter is not supported in Vertex AI."); @@ -720,7 +694,7 @@ ObjectNode functionDeclarationToVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode intervalToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode intervalToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"startTime"}) != null) { Common.setValueByPath( @@ -740,7 +714,7 @@ ObjectNode intervalToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode } @ExcludeFromGeneratedCoverageReport - ObjectNode intervalToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode intervalToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"startTime"}) != null) { Common.setValueByPath( @@ -760,15 +734,13 @@ ObjectNode intervalToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode } @ExcludeFromGeneratedCoverageReport - ObjectNode googleSearchToMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode googleSearchToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"timeRangeFilter"}) != null) { Common.setValueByPath( toObject, new String[] {"timeRangeFilter"}, intervalToMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"timeRangeFilter"})), toObject)); @@ -778,15 +750,13 @@ ObjectNode googleSearchToMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode googleSearchToVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode googleSearchToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"timeRangeFilter"}) != null) { Common.setValueByPath( toObject, new String[] {"timeRangeFilter"}, intervalToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"timeRangeFilter"})), toObject)); @@ -796,8 +766,7 @@ ObjectNode googleSearchToVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode dynamicRetrievalConfigToMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode dynamicRetrievalConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"mode"}) != null) { Common.setValueByPath( @@ -817,8 +786,7 @@ ObjectNode dynamicRetrievalConfigToMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode dynamicRetrievalConfigToVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode dynamicRetrievalConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"mode"}) != null) { Common.setValueByPath( @@ -838,15 +806,13 @@ ObjectNode dynamicRetrievalConfigToVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode googleSearchRetrievalToMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode googleSearchRetrievalToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"dynamicRetrievalConfig"}) != null) { Common.setValueByPath( toObject, new String[] {"dynamicRetrievalConfig"}, dynamicRetrievalConfigToMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"dynamicRetrievalConfig"})), toObject)); @@ -856,15 +822,13 @@ ObjectNode googleSearchRetrievalToMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode googleSearchRetrievalToVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode googleSearchRetrievalToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"dynamicRetrievalConfig"}) != null) { Common.setValueByPath( toObject, new String[] {"dynamicRetrievalConfig"}, dynamicRetrievalConfigToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"dynamicRetrievalConfig"})), toObject)); @@ -874,24 +838,21 @@ ObjectNode googleSearchRetrievalToVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode enterpriseWebSearchToMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode enterpriseWebSearchToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); return toObject; } @ExcludeFromGeneratedCoverageReport - ObjectNode enterpriseWebSearchToVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode enterpriseWebSearchToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); return toObject; } @ExcludeFromGeneratedCoverageReport - ObjectNode apiKeyConfigToMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode apiKeyConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"apiKeyString"}))) { throw new IllegalArgumentException("apiKeyString parameter is not supported in Gemini API."); @@ -901,8 +862,7 @@ ObjectNode apiKeyConfigToMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode apiKeyConfigToVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode apiKeyConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"apiKeyString"}) != null) { Common.setValueByPath( @@ -915,7 +875,7 @@ ObjectNode apiKeyConfigToVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode authConfigToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode authConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"apiKeyConfig"}))) { throw new IllegalArgumentException("apiKeyConfig parameter is not supported in Gemini API."); @@ -960,14 +920,13 @@ ObjectNode authConfigToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNod } @ExcludeFromGeneratedCoverageReport - ObjectNode authConfigToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode authConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"apiKeyConfig"}) != null) { Common.setValueByPath( toObject, new String[] {"apiKeyConfig"}, apiKeyConfigToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"apiKeyConfig"})), toObject)); @@ -1012,7 +971,7 @@ ObjectNode authConfigToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNo } @ExcludeFromGeneratedCoverageReport - ObjectNode googleMapsToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode googleMapsToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"authConfig"}))) { throw new IllegalArgumentException("authConfig parameter is not supported in Gemini API."); @@ -1022,14 +981,13 @@ ObjectNode googleMapsToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNod } @ExcludeFromGeneratedCoverageReport - ObjectNode googleMapsToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode googleMapsToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"authConfig"}) != null) { Common.setValueByPath( toObject, new String[] {"authConfig"}, authConfigToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"authConfig"})), toObject)); @@ -1039,21 +997,21 @@ ObjectNode googleMapsToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNo } @ExcludeFromGeneratedCoverageReport - ObjectNode urlContextToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode urlContextToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); return toObject; } @ExcludeFromGeneratedCoverageReport - ObjectNode urlContextToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode urlContextToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); return toObject; } @ExcludeFromGeneratedCoverageReport - ObjectNode toolToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toolToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"functionDeclarations"}) != null) { ArrayNode keyArray = @@ -1062,8 +1020,7 @@ ObjectNode toolToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode pare ArrayNode result = objectMapper.createArrayNode(); for (JsonNode item : keyArray) { - result.add( - functionDeclarationToMldev(apiClient, JsonSerializable.toJsonNode(item), toObject)); + result.add(functionDeclarationToMldev(JsonSerializable.toJsonNode(item), toObject)); } Common.setValueByPath(toObject, new String[] {"functionDeclarations"}, result); } @@ -1077,7 +1034,6 @@ ObjectNode toolToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode pare toObject, new String[] {"googleSearch"}, googleSearchToMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"googleSearch"})), toObject)); @@ -1088,7 +1044,6 @@ ObjectNode toolToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode pare toObject, new String[] {"googleSearchRetrieval"}, googleSearchRetrievalToMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"googleSearchRetrieval"})), toObject)); @@ -1108,7 +1063,6 @@ ObjectNode toolToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode pare toObject, new String[] {"urlContext"}, urlContextToMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"urlContext"})), toObject)); @@ -1125,7 +1079,7 @@ ObjectNode toolToMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode pare } @ExcludeFromGeneratedCoverageReport - ObjectNode toolToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toolToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"functionDeclarations"}) != null) { ArrayNode keyArray = @@ -1134,8 +1088,7 @@ ObjectNode toolToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode par ArrayNode result = objectMapper.createArrayNode(); for (JsonNode item : keyArray) { - result.add( - functionDeclarationToVertex(apiClient, JsonSerializable.toJsonNode(item), toObject)); + result.add(functionDeclarationToVertex(JsonSerializable.toJsonNode(item), toObject)); } Common.setValueByPath(toObject, new String[] {"functionDeclarations"}, result); } @@ -1152,7 +1105,6 @@ ObjectNode toolToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode par toObject, new String[] {"googleSearch"}, googleSearchToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"googleSearch"})), toObject)); @@ -1163,7 +1115,6 @@ ObjectNode toolToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode par toObject, new String[] {"googleSearchRetrieval"}, googleSearchRetrievalToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"googleSearchRetrieval"})), toObject)); @@ -1174,7 +1125,6 @@ ObjectNode toolToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode par toObject, new String[] {"enterpriseWebSearch"}, enterpriseWebSearchToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"enterpriseWebSearch"})), toObject)); @@ -1185,7 +1135,6 @@ ObjectNode toolToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode par toObject, new String[] {"googleMaps"}, googleMapsToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"googleMaps"})), toObject)); @@ -1196,7 +1145,6 @@ ObjectNode toolToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode par toObject, new String[] {"urlContext"}, urlContextToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"urlContext"})), toObject)); @@ -1213,8 +1161,7 @@ ObjectNode toolToVertex(ApiClient apiClient, JsonNode fromObject, ObjectNode par } @ExcludeFromGeneratedCoverageReport - ObjectNode sessionResumptionConfigToMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode sessionResumptionConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"handle"}) != null) { Common.setValueByPath( @@ -1231,8 +1178,7 @@ ObjectNode sessionResumptionConfigToMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode sessionResumptionConfigToVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode sessionResumptionConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"handle"}) != null) { Common.setValueByPath( @@ -1252,24 +1198,21 @@ ObjectNode sessionResumptionConfigToVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode audioTranscriptionConfigToMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode audioTranscriptionConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); return toObject; } @ExcludeFromGeneratedCoverageReport - ObjectNode audioTranscriptionConfigToVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode audioTranscriptionConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); return toObject; } @ExcludeFromGeneratedCoverageReport - ObjectNode automaticActivityDetectionToMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode automaticActivityDetectionToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"disabled"}) != null) { Common.setValueByPath( @@ -1310,8 +1253,7 @@ ObjectNode automaticActivityDetectionToMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode automaticActivityDetectionToVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode automaticActivityDetectionToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"disabled"}) != null) { Common.setValueByPath( @@ -1352,15 +1294,13 @@ ObjectNode automaticActivityDetectionToVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode realtimeInputConfigToMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode realtimeInputConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"automaticActivityDetection"}) != null) { Common.setValueByPath( toObject, new String[] {"automaticActivityDetection"}, automaticActivityDetectionToMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"automaticActivityDetection"})), toObject)); @@ -1384,15 +1324,13 @@ ObjectNode realtimeInputConfigToMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode realtimeInputConfigToVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode realtimeInputConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"automaticActivityDetection"}) != null) { Common.setValueByPath( toObject, new String[] {"automaticActivityDetection"}, automaticActivityDetectionToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"automaticActivityDetection"})), toObject)); @@ -1416,8 +1354,7 @@ ObjectNode realtimeInputConfigToVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode slidingWindowToMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode slidingWindowToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"targetTokens"}) != null) { Common.setValueByPath( @@ -1430,8 +1367,7 @@ ObjectNode slidingWindowToMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode slidingWindowToVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode slidingWindowToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"targetTokens"}) != null) { Common.setValueByPath( @@ -1444,8 +1380,7 @@ ObjectNode slidingWindowToVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode contextWindowCompressionConfigToMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode contextWindowCompressionConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"triggerTokens"}) != null) { Common.setValueByPath( @@ -1459,7 +1394,6 @@ ObjectNode contextWindowCompressionConfigToMldev( toObject, new String[] {"slidingWindow"}, slidingWindowToMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"slidingWindow"})), toObject)); @@ -1469,8 +1403,7 @@ ObjectNode contextWindowCompressionConfigToMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode contextWindowCompressionConfigToVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode contextWindowCompressionConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"triggerTokens"}) != null) { Common.setValueByPath( @@ -1484,7 +1417,6 @@ ObjectNode contextWindowCompressionConfigToVertex( toObject, new String[] {"slidingWindow"}, slidingWindowToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"slidingWindow"})), toObject)); @@ -1494,8 +1426,7 @@ ObjectNode contextWindowCompressionConfigToVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode proactivityConfigToMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode proactivityConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"proactiveAudio"}) != null) { Common.setValueByPath( @@ -1508,8 +1439,7 @@ ObjectNode proactivityConfigToMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode proactivityConfigToVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode proactivityConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"proactiveAudio"}) != null) { Common.setValueByPath( @@ -1522,8 +1452,7 @@ ObjectNode proactivityConfigToVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode liveConnectConfigToMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode liveConnectConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"responseModalities"}) != null) { @@ -1580,10 +1509,8 @@ ObjectNode liveConnectConfigToMldev( parentObject, new String[] {"setup", "generationConfig", "speechConfig"}, speechConfigToMldev( - apiClient, JsonSerializable.toJsonNode( Transformers.tLiveSpeechConfig( - this.apiClient, Common.getValueByPath(fromObject, new String[] {"speechConfig"}))), toObject)); } @@ -1600,10 +1527,8 @@ ObjectNode liveConnectConfigToMldev( parentObject, new String[] {"setup", "systemInstruction"}, contentToMldev( - apiClient, JsonSerializable.toJsonNode( Transformers.tContent( - this.apiClient, Common.getValueByPath(fromObject, new String[] {"systemInstruction"}))), toObject)); } @@ -1611,17 +1536,12 @@ ObjectNode liveConnectConfigToMldev( if (Common.getValueByPath(fromObject, new String[] {"tools"}) != null) { ArrayNode keyArray = (ArrayNode) - Transformers.tTools( - this.apiClient, Common.getValueByPath(fromObject, new String[] {"tools"})); + Transformers.tTools(Common.getValueByPath(fromObject, new String[] {"tools"})); ObjectMapper objectMapper = new ObjectMapper(); ArrayNode result = objectMapper.createArrayNode(); for (JsonNode item : keyArray) { - result.add( - toolToMldev( - apiClient, - JsonSerializable.toJsonNode(Transformers.tTool(this.apiClient, item)), - toObject)); + result.add(toolToMldev(JsonSerializable.toJsonNode(Transformers.tTool(item)), toObject)); } Common.setValueByPath(parentObject, new String[] {"setup", "tools"}, result); } @@ -1631,7 +1551,6 @@ ObjectNode liveConnectConfigToMldev( parentObject, new String[] {"setup", "sessionResumption"}, sessionResumptionConfigToMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"sessionResumption"})), toObject)); @@ -1642,7 +1561,6 @@ ObjectNode liveConnectConfigToMldev( parentObject, new String[] {"setup", "inputAudioTranscription"}, audioTranscriptionConfigToMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"inputAudioTranscription"})), toObject)); @@ -1653,7 +1571,6 @@ ObjectNode liveConnectConfigToMldev( parentObject, new String[] {"setup", "outputAudioTranscription"}, audioTranscriptionConfigToMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"outputAudioTranscription"})), toObject)); @@ -1664,7 +1581,6 @@ ObjectNode liveConnectConfigToMldev( parentObject, new String[] {"setup", "realtimeInputConfig"}, realtimeInputConfigToMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"realtimeInputConfig"})), toObject)); @@ -1675,7 +1591,6 @@ ObjectNode liveConnectConfigToMldev( parentObject, new String[] {"setup", "contextWindowCompression"}, contextWindowCompressionConfigToMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"contextWindowCompression"})), toObject)); @@ -1686,7 +1601,6 @@ ObjectNode liveConnectConfigToMldev( parentObject, new String[] {"setup", "proactivity"}, proactivityConfigToMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"proactivity"})), toObject)); @@ -1696,8 +1610,7 @@ ObjectNode liveConnectConfigToMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode liveConnectConfigToVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode liveConnectConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"responseModalities"}) != null) { @@ -1754,10 +1667,8 @@ ObjectNode liveConnectConfigToVertex( parentObject, new String[] {"setup", "generationConfig", "speechConfig"}, speechConfigToVertex( - apiClient, JsonSerializable.toJsonNode( Transformers.tLiveSpeechConfig( - this.apiClient, Common.getValueByPath(fromObject, new String[] {"speechConfig"}))), toObject)); } @@ -1774,10 +1685,8 @@ ObjectNode liveConnectConfigToVertex( parentObject, new String[] {"setup", "systemInstruction"}, contentToVertex( - apiClient, JsonSerializable.toJsonNode( Transformers.tContent( - this.apiClient, Common.getValueByPath(fromObject, new String[] {"systemInstruction"}))), toObject)); } @@ -1785,17 +1694,12 @@ ObjectNode liveConnectConfigToVertex( if (Common.getValueByPath(fromObject, new String[] {"tools"}) != null) { ArrayNode keyArray = (ArrayNode) - Transformers.tTools( - this.apiClient, Common.getValueByPath(fromObject, new String[] {"tools"})); + Transformers.tTools(Common.getValueByPath(fromObject, new String[] {"tools"})); ObjectMapper objectMapper = new ObjectMapper(); ArrayNode result = objectMapper.createArrayNode(); for (JsonNode item : keyArray) { - result.add( - toolToVertex( - apiClient, - JsonSerializable.toJsonNode(Transformers.tTool(this.apiClient, item)), - toObject)); + result.add(toolToVertex(JsonSerializable.toJsonNode(Transformers.tTool(item)), toObject)); } Common.setValueByPath(parentObject, new String[] {"setup", "tools"}, result); } @@ -1805,7 +1709,6 @@ ObjectNode liveConnectConfigToVertex( parentObject, new String[] {"setup", "sessionResumption"}, sessionResumptionConfigToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"sessionResumption"})), toObject)); @@ -1816,7 +1719,6 @@ ObjectNode liveConnectConfigToVertex( parentObject, new String[] {"setup", "inputAudioTranscription"}, audioTranscriptionConfigToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"inputAudioTranscription"})), toObject)); @@ -1827,7 +1729,6 @@ ObjectNode liveConnectConfigToVertex( parentObject, new String[] {"setup", "outputAudioTranscription"}, audioTranscriptionConfigToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"outputAudioTranscription"})), toObject)); @@ -1838,7 +1739,6 @@ ObjectNode liveConnectConfigToVertex( parentObject, new String[] {"setup", "realtimeInputConfig"}, realtimeInputConfigToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"realtimeInputConfig"})), toObject)); @@ -1849,7 +1749,6 @@ ObjectNode liveConnectConfigToVertex( parentObject, new String[] {"setup", "contextWindowCompression"}, contextWindowCompressionConfigToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"contextWindowCompression"})), toObject)); @@ -1860,7 +1759,6 @@ ObjectNode liveConnectConfigToVertex( parentObject, new String[] {"setup", "proactivity"}, proactivityConfigToVertex( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"proactivity"})), toObject)); @@ -1886,7 +1784,6 @@ ObjectNode liveConnectConstraintsToMldev( toObject, new String[] {"config"}, liveConnectConfigToMldev( - apiClient, JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"config"})), toObject)); @@ -1896,8 +1793,7 @@ ObjectNode liveConnectConstraintsToMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode liveConnectConstraintsToVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode liveConnectConstraintsToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"model"}))) { throw new IllegalArgumentException("model parameter is not supported in Vertex AI."); @@ -1958,8 +1854,7 @@ ObjectNode createAuthTokenConfigToMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode createAuthTokenConfigToVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode createAuthTokenConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"expireTime"}))) { @@ -1990,31 +1885,28 @@ ObjectNode createAuthTokenConfigToVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode createAuthTokenParametersToMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode createAuthTokenParametersToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); return toObject; } @ExcludeFromGeneratedCoverageReport - ObjectNode createAuthTokenParametersToVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode createAuthTokenParametersToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); return toObject; } @ExcludeFromGeneratedCoverageReport - ObjectNode authTokenFromMldev(ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode authTokenFromMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); return toObject; } @ExcludeFromGeneratedCoverageReport - ObjectNode authTokenFromVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode authTokenFromVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); return toObject; diff --git a/src/main/java/com/google/genai/Transformers.java b/src/main/java/com/google/genai/Transformers.java index f2521ab7b62..8a96ef82bd3 100644 --- a/src/main/java/com/google/genai/Transformers.java +++ b/src/main/java/com/google/genai/Transformers.java @@ -120,7 +120,7 @@ public static String tModelsUrl(ApiClient apiClient, @Nullable Object baseModels *

This is used in the converters. */ @SuppressWarnings("PatternMatchingInstanceof") - public static @Nullable JsonNode tExtractModels(ApiClient apiClient, Object origin) { + public static @Nullable JsonNode tExtractModels(Object origin) { if (origin == null) { return null; } @@ -153,7 +153,7 @@ public static String tModelsUrl(ApiClient apiClient, @Nullable Object baseModels * *

This is used in the converters. */ - public static Object tContents(ApiClient apiClient, Object origin) { + public static Object tContents(Object origin) { return origin; } @@ -186,12 +186,11 @@ public static ImmutableList tContents(Content content) { /** * Transforms an object to a Content for the API. * - * @param apiClient the API client to use for transformation * @param content the object to transform, can be a string or Content * @return the transformed Content * @throws IllegalArgumentException if the object is not a supported type */ - public static Content tContent(ApiClient apiClient, Object content) { + public static Content tContent(Object content) { if (content == null) { return null; } else if (content instanceof String) { @@ -206,7 +205,7 @@ public static Content tContent(ApiClient apiClient, Object content) { } /** Transforms an object to a Schema for the API. */ - public static Schema tSchema(ApiClient apiClient, Object origin) { + public static Schema tSchema(Object origin) { if (origin == null) { return null; } else if (origin instanceof Schema) { @@ -217,7 +216,7 @@ public static Schema tSchema(ApiClient apiClient, Object origin) { throw new IllegalArgumentException("Unsupported schema type: " + origin.getClass()); } - public static SpeechConfig tSpeechConfig(ApiClient apiClient, Object speechConfig) { + public static SpeechConfig tSpeechConfig(Object speechConfig) { if (speechConfig == null) { return null; } else if (speechConfig instanceof String) { @@ -240,13 +239,12 @@ public static SpeechConfig tSpeechConfig(ApiClient apiClient, Object speechConfi /** * Transforms a SpeechConfig object for the live API, validating it. * - * @param apiClient the API client to use for transformation * @param origin the object to transform, can be a SpeechConfig or a JsonNode * @return the transformed SpeechConfig * @throws IllegalArgumentException if the object is not a supported type or if * multiSpeakerVoiceConfig is present. */ - public static @Nullable SpeechConfig tLiveSpeechConfig(ApiClient apiClient, Object origin) { + public static @Nullable SpeechConfig tLiveSpeechConfig(Object origin) { SpeechConfig speechConfig; if (origin == null) { return null; @@ -272,12 +270,12 @@ public static SpeechConfig tSpeechConfig(ApiClient apiClient, Object speechConfi * *

This is used in the converters. */ - public static Object tTools(ApiClient apiClient, Object origin) { + public static Object tTools(Object origin) { return origin; } /** Transforms an object to a Tool for the API. */ - public static Tool tTool(ApiClient apiClient, Object origin) { + public static Tool tTool(Object origin) { if (origin == null) { return null; } else if (origin instanceof Tool) { @@ -302,7 +300,6 @@ public static Tool tTool(ApiClient apiClient, Object origin) { // in case reflectMethods is present in the json node, call tTool to parse it and remove it // from the json node. return tTool( - apiClient, JsonSerializable.objectMapper.convertValue( (JsonNode) origin, new TypeReference() {})); } @@ -311,7 +308,7 @@ public static Tool tTool(ApiClient apiClient, Object origin) { } /** Dummy Blobs transformer. */ - public static ArrayNode tBlobs(ApiClient apiClient, Object origin) { + public static ArrayNode tBlobs(Object origin) { // 1. Check if the origin is a JsonNode if (!(origin instanceof JsonNode)) { // If origin is not a JsonNode, we create one from the object. @@ -327,11 +324,11 @@ public static ArrayNode tBlobs(ApiClient apiClient, Object origin) { // 2. If it's not an array, create a new array and add the input to it. ArrayNode arrayNode = JsonNodeFactory.instance.arrayNode(); - arrayNode.add(JsonSerializable.toJsonNode(tBlob(apiClient, origin))); + arrayNode.add(JsonSerializable.toJsonNode(tBlob(origin))); return arrayNode; } - public static Blob tBlob(ApiClient apiClient, Object blob) { + public static Blob tBlob(Object blob) { if (blob instanceof JsonNode) { blob = JsonSerializable.objectMapper.convertValue((JsonNode) blob, new TypeReference() {}); @@ -347,13 +344,12 @@ public static Blob tBlob(ApiClient apiClient, Object blob) { /** * Transforms a blob to an image blob, validating its mime type. * - * @param apiClient the API client to use for transformation * @param blob the object to transform, can be a Blob or a dictionary. * @return the transformed Blob if it is an image. * @throws IllegalArgumentException if the blob is not an image. */ - public static Blob tImageBlob(ApiClient apiClient, Object blob) { - Blob transformedBlob = tBlob(apiClient, blob); + public static Blob tImageBlob(Object blob) { + Blob transformedBlob = tBlob(blob); if (transformedBlob.mimeType().isPresent() && transformedBlob.mimeType().get().startsWith("image/")) { return transformedBlob; @@ -365,13 +361,12 @@ public static Blob tImageBlob(ApiClient apiClient, Object blob) { /** * Transforms a blob to an audio blob, validating its mime type. * - * @param apiClient the API client to use for transformation * @param blob the object to transform, can be a Blob or a dictionary. * @return the transformed Blob if it is an audio. * @throws IllegalArgumentException if the blob is not an audio. */ - public static Blob tAudioBlob(ApiClient apiClient, Object blob) { - Blob transformedBlob = tBlob(apiClient, blob); + public static Blob tAudioBlob(Object blob) { + Blob transformedBlob = tBlob(blob); if (transformedBlob.mimeType().isPresent() && transformedBlob.mimeType().get().startsWith("audio/")) { return transformedBlob; @@ -381,7 +376,7 @@ public static Blob tAudioBlob(ApiClient apiClient, Object blob) { } /** Dummy bytes transformer. */ - public static Object tBytes(ApiClient apiClient, Object origin) { + public static Object tBytes(Object origin) { // TODO(b/389133914): Remove dummy bytes converter. return origin; } @@ -461,7 +456,7 @@ public static String tCachedContentName(ApiClient apiClient, Object origin) { return model; } - public static @Nullable String tFileName(ApiClient apiClient, Object origin) { + public static @Nullable String tFileName(Object origin) { String name = null; if (origin instanceof String) { diff --git a/src/test/java/com/google/genai/AfcUtilTest.java b/src/test/java/com/google/genai/AfcUtilTest.java index 4b8e6fb0ce8..ab0c226dfdc 100644 --- a/src/test/java/com/google/genai/AfcUtilTest.java +++ b/src/test/java/com/google/genai/AfcUtilTest.java @@ -32,13 +32,9 @@ import com.google.genai.types.Tool; import com.google.genai.types.Type; import java.lang.reflect.Method; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.mockito.Mockito; public final class AfcUtilTest { - private static ApiClient mockApiClient; - public static String testFunction1(String input) { return input + "testFunction1"; } @@ -73,16 +69,10 @@ public static Integer testFunction2(Integer a, Integer b) { .required("input2")) .build(); - @BeforeEach - void setUp() { - mockApiClient = Mockito.mock(ApiClient.class); - } - @Test public void transformGenerateContentConfig_emptyConfig_returnsTransformedConfig() { GenerateContentConfig config = GenerateContentConfig.builder().build(); - GenerateContentConfig transformedConfig = - AfcUtil.transformGenerateContentConfig(mockApiClient, config); + GenerateContentConfig transformedConfig = AfcUtil.transformGenerateContentConfig(config); assertEquals(config, transformedConfig); } @@ -92,8 +82,7 @@ public void transformGenerateContentConfig_functionDeclaration_returnsTransforme GenerateContentConfig.builder() .tools(Tool.builder().functionDeclarations(testFunctionDeclaration1)) .build(); - GenerateContentConfig transformedConfig = - AfcUtil.transformGenerateContentConfig(mockApiClient, config); + GenerateContentConfig transformedConfig = AfcUtil.transformGenerateContentConfig(config); assertEquals(config.toString(), transformedConfig.toString()); } @@ -114,8 +103,7 @@ public void transformGenerateContentConfig_functionDeclarationAndMethod_returnsT Tool.builder() .functionDeclarations(testFunctionDeclaration1, testFunctionDeclaration2)) .build(); - GenerateContentConfig transformedConfig = - AfcUtil.transformGenerateContentConfig(mockApiClient, config); + GenerateContentConfig transformedConfig = AfcUtil.transformGenerateContentConfig(config); assertEquals(expectedConfig.toString(), transformedConfig.toString()); } @@ -327,14 +315,14 @@ public void getFunctionResponseParts_exceptionThrown_returnsFunctionResponsePart @Test public void hasCallableTool_nullConfig_returnsFalse() { - boolean hasCallableTool = AfcUtil.hasCallableTool(mockApiClient, null); + boolean hasCallableTool = AfcUtil.hasCallableTool(null); assertEquals(false, hasCallableTool); } @Test public void hasCallableTool_emptyTools_returnsFalse() { GenerateContentConfig config = GenerateContentConfig.builder().build(); - boolean hasCallableTool = AfcUtil.hasCallableTool(mockApiClient, config); + boolean hasCallableTool = AfcUtil.hasCallableTool(config); assertEquals(false, hasCallableTool); } @@ -344,7 +332,7 @@ public void hasCallableTool_noFunctions_returnsFalse() { GenerateContentConfig.builder() .tools(Tool.builder().functionDeclarations(testFunctionDeclaration1)) .build(); - boolean hasCallableTool = AfcUtil.hasCallableTool(mockApiClient, config); + boolean hasCallableTool = AfcUtil.hasCallableTool(config); assertEquals(false, hasCallableTool); } @@ -358,7 +346,7 @@ public void hasCallableTool_returnsTrue() throws NoSuchMethodException { .functionDeclarations(testFunctionDeclaration2) .functions(testMethod1)) .build(); - boolean hasCallableTool = AfcUtil.hasCallableTool(mockApiClient, config); + boolean hasCallableTool = AfcUtil.hasCallableTool(config); assertEquals(true, hasCallableTool); } } diff --git a/src/test/java/com/google/genai/LiveConvertersTest.java b/src/test/java/com/google/genai/LiveConvertersTest.java index 06f97637eea..121b2b2a3e0 100644 --- a/src/test/java/com/google/genai/LiveConvertersTest.java +++ b/src/test/java/com/google/genai/LiveConvertersTest.java @@ -55,9 +55,7 @@ public void testLiveSendRealtimeInputParameters_Media_wrapped() { final LiveConverters mldevLiveConverters = new LiveConverters(GEMINI_API_CLIENT); ObjectNode transformed = mldevLiveConverters.liveClientMessageToMldev( - GEMINI_API_CLIENT, - JsonSerializable.toJsonNode(message), - JsonSerializable.objectMapper.createObjectNode()); + JsonSerializable.toJsonNode(message), JsonSerializable.objectMapper.createObjectNode()); assertEquals( transformed.get("realtime_input").get("mediaChunks").get(0).get("mimeType").asText(), @@ -67,9 +65,7 @@ public void testLiveSendRealtimeInputParameters_Media_wrapped() { transformed = vertexLiveConverters.liveClientMessageToMldev( - GEMINI_API_CLIENT, - JsonSerializable.toJsonNode(message), - JsonSerializable.objectMapper.createObjectNode()); + JsonSerializable.toJsonNode(message), JsonSerializable.objectMapper.createObjectNode()); assertEquals( transformed.get("realtime_input").get("mediaChunks").get(0).get("mimeType").asText(), @@ -87,9 +83,7 @@ public void testLiveSendRealtimeInputParameters_Text_okay() { final LiveConverters mldevLiveConverters = new LiveConverters(GEMINI_API_CLIENT); ObjectNode transformed = mldevLiveConverters.liveClientMessageToMldev( - GEMINI_API_CLIENT, - JsonSerializable.toJsonNode(message), - JsonSerializable.objectMapper.createObjectNode()); + JsonSerializable.toJsonNode(message), JsonSerializable.objectMapper.createObjectNode()); assertEquals(transformed.get("realtime_input").get("text").asText(), "test"); @@ -99,7 +93,6 @@ public void testLiveSendRealtimeInputParameters_Text_okay() { IllegalArgumentException.class, // Expected exception type () -> vertexLiveConverters.liveClientMessageToVertex( - VERTEX_AI_CLIENT, JsonSerializable.toJsonNode(message), JsonSerializable.objectMapper .createObjectNode()) // Code that should throw the exception @@ -122,9 +115,7 @@ public void testLiveSendRealtimeInputParameters_Audio_okay() { final LiveConverters mldevLiveConverters = new LiveConverters(GEMINI_API_CLIENT); ObjectNode transformed = mldevLiveConverters.liveClientMessageToMldev( - GEMINI_API_CLIENT, - JsonSerializable.toJsonNode(message), - JsonSerializable.objectMapper.createObjectNode()); + JsonSerializable.toJsonNode(message), JsonSerializable.objectMapper.createObjectNode()); assertEquals( transformed.get("realtime_input").get("audio").get("mimeType").asText(), "audio/mp3"); @@ -135,7 +126,6 @@ public void testLiveSendRealtimeInputParameters_Audio_okay() { IllegalArgumentException.class, // Expected exception type () -> vertexLiveConverters.liveClientMessageToVertex( - VERTEX_AI_CLIENT, JsonSerializable.toJsonNode(message), JsonSerializable.objectMapper .createObjectNode()) // Code that should throw the exception @@ -161,7 +151,6 @@ public void testLiveSendRealtimeInputParameters_BadBlob_throws() { IllegalArgumentException.class, // Expected exception type () -> mldevLiveConverters.liveClientMessageToMldev( - GEMINI_API_CLIENT, JsonSerializable.toJsonNode(message), JsonSerializable.objectMapper .createObjectNode()) // Code that should throw the exception @@ -200,7 +189,6 @@ public void testMultiSpeakerVoiceConfig_throws() { IllegalArgumentException.class, // Expected exception type () -> mldevLiveConverters.liveConnectConfigToMldev( - GEMINI_API_CLIENT, JsonSerializable.toJsonNode(message), JsonSerializable.objectMapper .createObjectNode()) // Code that should throw the exception diff --git a/src/test/java/com/google/genai/TransformersTest.java b/src/test/java/com/google/genai/TransformersTest.java index 176eea6df5a..fde14fc8f83 100644 --- a/src/test/java/com/google/genai/TransformersTest.java +++ b/src/test/java/com/google/genai/TransformersTest.java @@ -19,7 +19,6 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.mockito.Mockito.mock; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ArrayNode; @@ -42,9 +41,6 @@ public class TransformersTest { private static final String FILE_NAME = "12tsygtx2"; - ApiClient GEMINI_API_CLIENT = mock(ApiClient.class); - ApiClient VERTEX_AI_CLIENT = mock(ApiClient.class); - private class UnsupportedType {} /** A function (static method) to test fromMethod functionalities. */ @@ -63,7 +59,7 @@ public void testTSchema_GeminiAPI_defaultValue_noChange() { Schema.builder() .properties(ImmutableMap.of("test", Schema.builder().default_(1).build())) .build(); - Schema transformedSchema = Transformers.tSchema(GEMINI_API_CLIENT, schema); + Schema transformedSchema = Transformers.tSchema(schema); assertEquals(schema, transformedSchema); } @@ -73,14 +69,14 @@ public void testTSchema_VertexAI_defaultValue_noChange() { Schema.builder() .properties(ImmutableMap.of("test", Schema.builder().default_(1).build())) .build(); - Schema transformedSchema = Transformers.tSchema(VERTEX_AI_CLIENT, schema); + Schema transformedSchema = Transformers.tSchema(schema); assertEquals(schema, transformedSchema); } @Test public void testTSchema_GeminiAPI_title_success() { Schema schema = Schema.builder().title("test").build(); - Schema transformedSchema = Transformers.tSchema(GEMINI_API_CLIENT, schema); + Schema transformedSchema = Transformers.tSchema(schema); assertEquals(true, transformedSchema.title().isPresent()); } @@ -91,7 +87,7 @@ public void testTSchema_AnyOf_success() { .type("OBJECT") .anyOf(Schema.builder().type("STRING"), Schema.builder().type("NUMBER")) .build(); - Schema transformedSchema = Transformers.tSchema(VERTEX_AI_CLIENT, schema); + Schema transformedSchema = Transformers.tSchema(schema); assertEquals(2, transformedSchema.anyOf().get().size()); assertEquals("STRING", transformedSchema.anyOf().get().get(0).type().get().toString()); assertEquals("NUMBER", transformedSchema.anyOf().get().get(1).type().get().toString()); @@ -101,7 +97,7 @@ public void testTSchema_AnyOf_success() { @Test public void testTSchema_Items_success() { Schema schema = Schema.builder().type("ARRAY").items(Schema.builder().type("STRING")).build(); - Schema transformedSchema = Transformers.tSchema(GEMINI_API_CLIENT, schema); + Schema transformedSchema = Transformers.tSchema(schema); assertEquals("STRING", transformedSchema.items().get().type().get().toString()); assertEquals("ARRAY", transformedSchema.type().get().toString()); } @@ -125,7 +121,7 @@ public void testTSchema_Required_success() { .build())) .required("recipe_name", "ingredients")) .build(); - Schema transformedSchema = Transformers.tSchema(GEMINI_API_CLIENT, schema); + Schema transformedSchema = Transformers.tSchema(schema); assertEquals(schema, transformedSchema); } @@ -152,16 +148,17 @@ public void testTTool_noFunctions_success() { .required("recipeName", "ingredients"))) .googleSearch(GoogleSearch.builder()) .build(); - Tool geminiTransformedTool = Transformers.tTool(GEMINI_API_CLIENT, tool); - Tool vertexTransformedTool = Transformers.tTool(VERTEX_AI_CLIENT, tool); + Tool geminiTransformedTool = Transformers.tTool(tool); + Tool vertexTransformedTool = Transformers.tTool(tool); assertEquals(tool, geminiTransformedTool); assertEquals(tool, vertexTransformedTool); } @Test public void testTTool_Functions_success() throws NoSuchMethodException { - Method method = TransformersTest.class.getMethod( - "functionUnderTest", String.class, int.class, double.class, float.class, boolean.class); + Method method = + TransformersTest.class.getMethod( + "functionUnderTest", String.class, int.class, double.class, float.class, boolean.class); Map properties = new HashMap<>(); properties.put("stringParam", Schema.builder().type("STRING").title("stringParam").build()); properties.put("integerParam", Schema.builder().type("INTEGER").title("integerParam").build()); @@ -190,8 +187,8 @@ public void testTTool_Functions_success() throws NoSuchMethodException { .googleSearch(GoogleSearch.builder()) .functions(method) .build(); - Tool geminiTransformedTool = Transformers.tTool(GEMINI_API_CLIENT, originalTool); - Tool vertexTransformedTool = Transformers.tTool(VERTEX_AI_CLIENT, originalTool); + Tool geminiTransformedTool = Transformers.tTool(originalTool); + Tool vertexTransformedTool = Transformers.tTool(originalTool); Tool expectedTool = Tool.builder() .functionDeclarations( @@ -254,8 +251,8 @@ public void testTTool_functionsEmpty_success() { .googleSearch(GoogleSearch.builder()) .functions() .build(); - Tool geminiTransformedTool = Transformers.tTool(GEMINI_API_CLIENT, originalTool); - Tool vertexTransformedTool = Transformers.tTool(VERTEX_AI_CLIENT, originalTool); + Tool geminiTransformedTool = Transformers.tTool(originalTool); + Tool vertexTransformedTool = Transformers.tTool(originalTool); Tool expectedTool = Tool.builder() .functionDeclarations( @@ -283,14 +280,14 @@ public void testTTool_functionsEmpty_success() { @Test public void tFileName_string_success() { - String transformedFileName = Transformers.tFileName(GEMINI_API_CLIENT, FILE_NAME); + String transformedFileName = Transformers.tFileName(FILE_NAME); assertEquals(FILE_NAME, transformedFileName); } @Test public void tFileName_string_file_success() { String fileName = "files/" + FILE_NAME; - String transformedFileName = Transformers.tFileName(GEMINI_API_CLIENT, FILE_NAME); + String transformedFileName = Transformers.tFileName(FILE_NAME); assertEquals(FILE_NAME, transformedFileName); } @@ -298,7 +295,7 @@ public void tFileName_string_file_success() { public void tFileName_textNode_file_success() { String fileName = "files/" + FILE_NAME; TextNode textNode = JsonNodeFactory.instance.textNode(fileName); - String transformedFileName = Transformers.tFileName(GEMINI_API_CLIENT, FILE_NAME); + String transformedFileName = Transformers.tFileName(FILE_NAME); assertEquals(FILE_NAME, transformedFileName); } @@ -311,7 +308,7 @@ public void tFileName_video_success() { + FILE_NAME + ":download?alt=media") .build(); - String transformedFileName = Transformers.tFileName(GEMINI_API_CLIENT, video); + String transformedFileName = Transformers.tFileName(video); assertEquals(FILE_NAME, transformedFileName); } @@ -326,49 +323,45 @@ public void tFileName_generatedVideo_success() { + FILE_NAME + ":download?alt=media")) .build(); - String transformedFileName = Transformers.tFileName(GEMINI_API_CLIENT, generatedVideo); + String transformedFileName = Transformers.tFileName(generatedVideo); assertEquals(FILE_NAME, transformedFileName); } @Test public void tFileName_generatedVideo_noUri_returnNull() { GeneratedVideo generatedVideo = GeneratedVideo.builder().video(Video.builder()).build(); - String transformedFileName = Transformers.tFileName(GEMINI_API_CLIENT, generatedVideo); + String transformedFileName = Transformers.tFileName(generatedVideo); assertEquals(null, transformedFileName); } @Test public void tFileName_video_noUri_returnNull() { Video video = Video.builder().build(); - String transformedFileName = Transformers.tFileName(GEMINI_API_CLIENT, video); + String transformedFileName = Transformers.tFileName(video); assertEquals(null, transformedFileName); } @Test public void tFileName_file_noName_throwsException() { File file = File.builder().build(); - assertThrows( - IllegalArgumentException.class, () -> Transformers.tFileName(GEMINI_API_CLIENT, file)); + assertThrows(IllegalArgumentException.class, () -> Transformers.tFileName(file)); } @Test public void tFileName_generatedVideo_noVideo_throwsException() { GeneratedVideo generatedVideo = GeneratedVideo.builder().build(); - assertThrows( - IllegalArgumentException.class, - () -> Transformers.tFileName(GEMINI_API_CLIENT, generatedVideo)); + assertThrows(IllegalArgumentException.class, () -> Transformers.tFileName(generatedVideo)); } @Test public void tFileName_unsupportedType_throwsException() { assertThrows( - IllegalArgumentException.class, - () -> Transformers.tFileName(GEMINI_API_CLIENT, new UnsupportedType())); + IllegalArgumentException.class, () -> Transformers.tFileName(new UnsupportedType())); } @Test public void tExtractModels_nullResponse_returnNull() { - assertTrue(Transformers.tExtractModels(GEMINI_API_CLIENT, null) == null); + assertTrue(Transformers.tExtractModels(null) == null); } @Test @@ -376,7 +369,7 @@ public void tExtractModels_unsupportedType_throwsException() { IllegalArgumentException exception = assertThrows( IllegalArgumentException.class, - () -> Transformers.tExtractModels(GEMINI_API_CLIENT, new UnsupportedType())); + () -> Transformers.tExtractModels(new UnsupportedType())); assertTrue(exception.getMessage().contains("Unsupported response type")); } @@ -385,7 +378,7 @@ public void tExtractModels_unsupportedType_throwsException() { public void tExtractModels_noModels_returnEmptyArrayNode() { ObjectNode origin = JsonSerializable.objectMapper.createObjectNode(); - JsonNode models = Transformers.tExtractModels(GEMINI_API_CLIENT, origin); + JsonNode models = Transformers.tExtractModels(origin); assertTrue(models.isEmpty()); } @@ -395,7 +388,7 @@ public void tExtractModels_responseWithModels() { origin.put( "models", JsonSerializable.objectMapper.createArrayNode().add("model-1").add("model-2")); - JsonNode models = Transformers.tExtractModels(GEMINI_API_CLIENT, origin); + JsonNode models = Transformers.tExtractModels(origin); assertTrue(models instanceof ArrayNode); assertEquals(2, models.size()); } @@ -405,7 +398,7 @@ public void tExtractModels_responseWithTunedModels() { ObjectNode origin = JsonSerializable.objectMapper.createObjectNode(); origin.put("tunedModels", JsonSerializable.objectMapper.createArrayNode().add("tuned-model-1")); - JsonNode models = Transformers.tExtractModels(GEMINI_API_CLIENT, origin); + JsonNode models = Transformers.tExtractModels(origin); assertTrue(models instanceof ArrayNode); assertEquals(1, models.size()); } @@ -417,7 +410,7 @@ public void tExtractModels_responseWithPublisherModels() { "publisherModels", JsonSerializable.objectMapper.createArrayNode().add("publisher-model-1")); - JsonNode models = Transformers.tExtractModels(GEMINI_API_CLIENT, origin); + JsonNode models = Transformers.tExtractModels(origin); assertTrue(models instanceof ArrayNode); assertEquals(1, models.size()); } From 265f20addd9e9e76c249e6042d653c8cec9f27a4 Mon Sep 17 00:00:00 2001 From: Mark Daoust Date: Fri, 20 Jun 2025 09:08:01 -0700 Subject: [PATCH 028/602] docs: Update description of thinking_budget. PiperOrigin-RevId: 773726493 --- src/main/java/com/google/genai/types/ThinkingConfig.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/google/genai/types/ThinkingConfig.java b/src/main/java/com/google/genai/types/ThinkingConfig.java index d0dd841a653..144de51f19c 100644 --- a/src/main/java/com/google/genai/types/ThinkingConfig.java +++ b/src/main/java/com/google/genai/types/ThinkingConfig.java @@ -36,7 +36,10 @@ public abstract class ThinkingConfig extends JsonSerializable { @JsonProperty("includeThoughts") public abstract Optional includeThoughts(); - /** Indicates the thinking budget in tokens. */ + /** + * Indicates the thinking budget in tokens. 0 is DISABLED. -1 is AUTOMATIC. The default values and + * allowed ranges are model dependent. + */ @JsonProperty("thinkingBudget") public abstract Optional thinkingBudget(); @@ -69,7 +72,8 @@ private static Builder create() { /** * Setter for thinkingBudget. * - *

thinkingBudget: Indicates the thinking budget in tokens. + *

thinkingBudget: Indicates the thinking budget in tokens. 0 is DISABLED. -1 is AUTOMATIC. + * The default values and allowed ranges are model dependent. */ @JsonProperty("thinkingBudget") public abstract Builder thinkingBudget(Integer thinkingBudget); From 22d4ca8cd90be97ae25666a219d5777d81171a4b Mon Sep 17 00:00:00 2001 From: Wanlin Du Date: Fri, 20 Jun 2025 09:58:27 -0700 Subject: [PATCH 029/602] chore: Update package version in README and ApiClient PiperOrigin-RevId: 773743688 --- README.md | 2 +- examples/pom.xml | 2 +- src/main/java/com/google/genai/ApiClient.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 7a0cc041e1a..f212e0e940e 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ If you're using Maven, add the following to your dependencies: com.google.genai google-genai - 1.4.1 + 1.5.0 ``` diff --git a/examples/pom.xml b/examples/pom.xml index 8333d2adcb4..59a433522d2 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -12,7 +12,7 @@ UTF-8 1.8 1.8 - 1.5.0-SNAPSHOT + 1.6.0-SNAPSHOT diff --git a/src/main/java/com/google/genai/ApiClient.java b/src/main/java/com/google/genai/ApiClient.java index bcb122efb5b..bd129e99a9b 100644 --- a/src/main/java/com/google/genai/ApiClient.java +++ b/src/main/java/com/google/genai/ApiClient.java @@ -40,7 +40,7 @@ /** Interface for an API client which issues HTTP requests to the GenAI APIs. */ abstract class ApiClient { - private static final String SDK_VERSION = "1.4.1"; // x-version-update:google-genai:released + private static final String SDK_VERSION = "1.5.0"; // x-version-update:google-genai:released private static final Logger logger = Logger.getLogger(ApiClient.class.getName()); CloseableHttpClient httpClient; From 345c2b93789913d6d84cdde9c30f86ec4041bd24 Mon Sep 17 00:00:00 2001 From: Qiao Wang Date: Fri, 20 Jun 2025 10:14:37 -0700 Subject: [PATCH 030/602] feat: support client.caches.update method PiperOrigin-RevId: 773749915 --- .../examples/CachedContentOperations.java | 10 +- .../java/com/google/genai/AsyncCaches.java | 12 ++ src/main/java/com/google/genai/Caches.java | 164 ++++++++++++++++++ .../types/UpdateCachedContentConfig.java | 111 ++++++++++++ .../types/UpdateCachedContentParameters.java | 93 ++++++++++ 5 files changed, 389 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/google/genai/types/UpdateCachedContentConfig.java create mode 100644 src/main/java/com/google/genai/types/UpdateCachedContentParameters.java diff --git a/examples/src/main/java/com/google/genai/examples/CachedContentOperations.java b/examples/src/main/java/com/google/genai/examples/CachedContentOperations.java index f5711c6f105..bcd6d30b997 100644 --- a/examples/src/main/java/com/google/genai/examples/CachedContentOperations.java +++ b/examples/src/main/java/com/google/genai/examples/CachedContentOperations.java @@ -49,6 +49,8 @@ import com.google.genai.types.DeleteCachedContentResponse; import com.google.genai.types.ListCachedContentsConfig; import com.google.genai.types.Part; +import com.google.genai.types.UpdateCachedContentConfig; + import java.io.IOException; import java.io.InputStream; import java.net.URL; @@ -100,7 +102,13 @@ public static void main(String[] args) { // Get the cached content by name. CachedContent cachedContent2 = client.caches.get(cachedContent1.name().get(), null); - System.out.println("get cached content: " + cachedContent2); + System.out.println("Get cached content: " + cachedContent2); + + CachedContent cachedContent3 = + client.caches.update( + cachedContent1.name().get(), + UpdateCachedContentConfig.builder().ttl(Duration.ofMinutes(10)).build()); + System.out.println("Update cached content: " + cachedContent3); // List all cached contents. System.out.println("List cached contents resrouce names: "); diff --git a/src/main/java/com/google/genai/AsyncCaches.java b/src/main/java/com/google/genai/AsyncCaches.java index 6061214bff9..575822e8723 100644 --- a/src/main/java/com/google/genai/AsyncCaches.java +++ b/src/main/java/com/google/genai/AsyncCaches.java @@ -27,6 +27,7 @@ import com.google.genai.types.DeleteCachedContentResponse; import com.google.genai.types.GetCachedContentConfig; import com.google.genai.types.ListCachedContentsConfig; +import com.google.genai.types.UpdateCachedContentConfig; import java.util.concurrent.CompletableFuture; import java.util.function.Function; @@ -71,6 +72,17 @@ public CompletableFuture delete( return CompletableFuture.supplyAsync(() -> caches.delete(name, config)); } + /** + * Asynchronously updates a cached content resource. + * + * @param name The name(resource id) of the cached content to update. + * @param config A {@link UpdateCachedContentConfig} for configuring the update request. + * @return A {@link CachedContent} object that contains the info of the updated resource. + */ + public CompletableFuture update(String name, UpdateCachedContentConfig config) { + return CompletableFuture.supplyAsync(() -> caches.update(name, config)); + } + /** * Asynchronously makes an API request to list the available cached contents. * diff --git a/src/main/java/com/google/genai/Caches.java b/src/main/java/com/google/genai/Caches.java index e0b6e8152ad..e1a3d77d6de 100644 --- a/src/main/java/com/google/genai/Caches.java +++ b/src/main/java/com/google/genai/Caches.java @@ -35,6 +35,8 @@ import com.google.genai.types.ListCachedContentsConfig; import com.google.genai.types.ListCachedContentsParameters; import com.google.genai.types.ListCachedContentsResponse; +import com.google.genai.types.UpdateCachedContentConfig; +import com.google.genai.types.UpdateCachedContentParameters; import java.io.IOException; import java.util.Optional; import java.util.function.Function; @@ -743,6 +745,52 @@ ObjectNode deleteCachedContentParametersToMldev( return toObject; } + @ExcludeFromGeneratedCoverageReport + ObjectNode updateCachedContentConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + + if (Common.getValueByPath(fromObject, new String[] {"ttl"}) != null) { + Common.setValueByPath( + parentObject, + new String[] {"ttl"}, + Common.getValueByPath(fromObject, new String[] {"ttl"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"expireTime"}) != null) { + Common.setValueByPath( + parentObject, + new String[] {"expireTime"}, + Common.getValueByPath(fromObject, new String[] {"expireTime"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode updateCachedContentParametersToMldev( + ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"name"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"_url", "name"}, + Transformers.tCachedContentName( + this.apiClient, Common.getValueByPath(fromObject, new String[] {"name"}))); + } + + if (Common.getValueByPath(fromObject, new String[] {"config"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"config"}, + updateCachedContentConfigToMldev( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"config"})), + toObject)); + } + + return toObject; + } + @ExcludeFromGeneratedCoverageReport ObjectNode listCachedContentsConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); @@ -1506,6 +1554,52 @@ ObjectNode deleteCachedContentParametersToVertex( return toObject; } + @ExcludeFromGeneratedCoverageReport + ObjectNode updateCachedContentConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + + if (Common.getValueByPath(fromObject, new String[] {"ttl"}) != null) { + Common.setValueByPath( + parentObject, + new String[] {"ttl"}, + Common.getValueByPath(fromObject, new String[] {"ttl"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"expireTime"}) != null) { + Common.setValueByPath( + parentObject, + new String[] {"expireTime"}, + Common.getValueByPath(fromObject, new String[] {"expireTime"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode updateCachedContentParametersToVertex( + ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"name"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"_url", "name"}, + Transformers.tCachedContentName( + this.apiClient, Common.getValueByPath(fromObject, new String[] {"name"}))); + } + + if (Common.getValueByPath(fromObject, new String[] {"config"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"config"}, + updateCachedContentConfigToVertex( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"config"})), + toObject)); + } + + return toObject; + } + @ExcludeFromGeneratedCoverageReport ObjectNode listCachedContentsConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); @@ -1925,6 +2019,76 @@ public DeleteCachedContentResponse delete(String name, DeleteCachedContentConfig } } + /** + * Updates a cached content resource. + * + * @param name The name(resource id) of the cached content to update. + * @param config A {@link UpdateCachedContentConfig} for configuring the update request. + * @return A {@link CachedContent} object that contains the info of the updated resource. + */ + public CachedContent update(String name, UpdateCachedContentConfig config) { + + UpdateCachedContentParameters.Builder parameterBuilder = + UpdateCachedContentParameters.builder(); + + if (!Common.isZero(name)) { + parameterBuilder.name(name); + } + if (!Common.isZero(config)) { + parameterBuilder.config(config); + } + JsonNode parameterNode = JsonSerializable.toJsonNode(parameterBuilder.build()); + + ObjectNode body; + String path; + if (this.apiClient.vertexAI()) { + body = updateCachedContentParametersToVertex(this.apiClient, parameterNode, null); + path = Common.formatMap("{name}", body.get("_url")); + } else { + body = updateCachedContentParametersToMldev(this.apiClient, parameterNode, null); + if (body.get("_url") != null) { + path = Common.formatMap("{name}", body.get("_url")); + } else { + path = "{name}"; + } + } + body.remove("_url"); + + JsonNode queryParams = body.get("_query"); + if (queryParams != null) { + body.remove("_query"); + path = String.format("%s?%s", path, Common.urlEncode((ObjectNode) queryParams)); + } + + // TODO: Remove the hack that removes config. + body.remove("config"); + + Optional requestHttpOptions = Optional.empty(); + if (config != null) { + requestHttpOptions = config.httpOptions(); + } + + try (ApiResponse response = + this.apiClient.request( + "patch", path, JsonSerializable.toJsonString(body), requestHttpOptions)) { + HttpEntity entity = response.getEntity(); + String responseString; + try { + responseString = EntityUtils.toString(entity); + } catch (IOException e) { + throw new GenAiIOException("Failed to read HTTP response.", e); + } + + JsonNode responseNode = JsonSerializable.stringToJsonNode(responseString); + if (this.apiClient.vertexAI()) { + responseNode = cachedContentFromVertex(responseNode, null); + } else { + responseNode = cachedContentFromMldev(responseNode, null); + } + return JsonSerializable.fromJsonNode(responseNode, CachedContent.class); + } + } + ListCachedContentsResponse privateList(ListCachedContentsConfig config) { ListCachedContentsParameters.Builder parameterBuilder = ListCachedContentsParameters.builder(); diff --git a/src/main/java/com/google/genai/types/UpdateCachedContentConfig.java b/src/main/java/com/google/genai/types/UpdateCachedContentConfig.java new file mode 100644 index 00000000000..cc9df5955d5 --- /dev/null +++ b/src/main/java/com/google/genai/types/UpdateCachedContentConfig.java @@ -0,0 +1,111 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Auto-generated code. Do not edit. + +package com.google.genai.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.google.auto.value.AutoValue; +import com.google.genai.JsonSerializable; +import java.time.Duration; +import java.time.Instant; +import java.util.Optional; + +/** Optional parameters for caches.update method. */ +@AutoValue +@JsonDeserialize(builder = UpdateCachedContentConfig.Builder.class) +public abstract class UpdateCachedContentConfig extends JsonSerializable { + /** Used to override HTTP request options. */ + @JsonProperty("httpOptions") + public abstract Optional httpOptions(); + + /** + * The TTL for this resource. The expiration time is computed: now + TTL. It is a duration string, + * with up to nine fractional digits, terminated by 's'. Example: "3.5s". + */ + @JsonProperty("ttl") + public abstract Optional ttl(); + + /** + * Timestamp of when this resource is considered expired. Uses RFC 3339 format, Example: + * 2014-10-02T15:01:23Z. + */ + @JsonProperty("expireTime") + public abstract Optional expireTime(); + + /** Instantiates a builder for UpdateCachedContentConfig. */ + public static Builder builder() { + return new AutoValue_UpdateCachedContentConfig.Builder(); + } + + /** Creates a builder with the same values as this instance. */ + public abstract Builder toBuilder(); + + /** Builder for UpdateCachedContentConfig. */ + @AutoValue.Builder + public abstract static class Builder { + /** For internal usage. Please use `UpdateCachedContentConfig.builder()` for instantiation. */ + @JsonCreator + private static Builder create() { + return new AutoValue_UpdateCachedContentConfig.Builder(); + } + + /** + * Setter for httpOptions. + * + *

httpOptions: Used to override HTTP request options. + */ + @JsonProperty("httpOptions") + public abstract Builder httpOptions(HttpOptions httpOptions); + + /** + * Setter for httpOptions builder. + * + *

httpOptions: Used to override HTTP request options. + */ + public Builder httpOptions(HttpOptions.Builder httpOptionsBuilder) { + return httpOptions(httpOptionsBuilder.build()); + } + + /** + * Setter for ttl. + * + *

ttl: The TTL for this resource. The expiration time is computed: now + TTL. It is a + * duration string, with up to nine fractional digits, terminated by 's'. Example: "3.5s". + */ + @JsonProperty("ttl") + public abstract Builder ttl(Duration ttl); + + /** + * Setter for expireTime. + * + *

expireTime: Timestamp of when this resource is considered expired. Uses RFC 3339 format, + * Example: 2014-10-02T15:01:23Z. + */ + @JsonProperty("expireTime") + public abstract Builder expireTime(Instant expireTime); + + public abstract UpdateCachedContentConfig build(); + } + + /** Deserializes a JSON string to a UpdateCachedContentConfig object. */ + public static UpdateCachedContentConfig fromJson(String jsonString) { + return JsonSerializable.fromJsonString(jsonString, UpdateCachedContentConfig.class); + } +} diff --git a/src/main/java/com/google/genai/types/UpdateCachedContentParameters.java b/src/main/java/com/google/genai/types/UpdateCachedContentParameters.java new file mode 100644 index 00000000000..c5f9d8b85ae --- /dev/null +++ b/src/main/java/com/google/genai/types/UpdateCachedContentParameters.java @@ -0,0 +1,93 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Auto-generated code. Do not edit. + +package com.google.genai.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.google.api.core.InternalApi; +import com.google.auto.value.AutoValue; +import com.google.genai.JsonSerializable; +import java.util.Optional; + +/** None */ +@AutoValue +@InternalApi +@JsonDeserialize(builder = UpdateCachedContentParameters.Builder.class) +public abstract class UpdateCachedContentParameters extends JsonSerializable { + /** The server-generated resource name of the cached content. */ + @JsonProperty("name") + public abstract Optional name(); + + /** Configuration that contains optional parameters. */ + @JsonProperty("config") + public abstract Optional config(); + + /** Instantiates a builder for UpdateCachedContentParameters. */ + public static Builder builder() { + return new AutoValue_UpdateCachedContentParameters.Builder(); + } + + /** Creates a builder with the same values as this instance. */ + public abstract Builder toBuilder(); + + /** Builder for UpdateCachedContentParameters. */ + @AutoValue.Builder + public abstract static class Builder { + /** + * For internal usage. Please use `UpdateCachedContentParameters.builder()` for instantiation. + */ + @JsonCreator + private static Builder create() { + return new AutoValue_UpdateCachedContentParameters.Builder(); + } + + /** + * Setter for name. + * + *

name: The server-generated resource name of the cached content. + */ + @JsonProperty("name") + public abstract Builder name(String name); + + /** + * Setter for config. + * + *

config: Configuration that contains optional parameters. + */ + @JsonProperty("config") + public abstract Builder config(UpdateCachedContentConfig config); + + /** + * Setter for config builder. + * + *

config: Configuration that contains optional parameters. + */ + public Builder config(UpdateCachedContentConfig.Builder configBuilder) { + return config(configBuilder.build()); + } + + public abstract UpdateCachedContentParameters build(); + } + + /** Deserializes a JSON string to a UpdateCachedContentParameters object. */ + public static UpdateCachedContentParameters fromJson(String jsonString) { + return JsonSerializable.fromJsonString(jsonString, UpdateCachedContentParameters.class); + } +} From 03153578ea64f0c34836ac62395aa867f44eac07 Mon Sep 17 00:00:00 2001 From: Wanlin Du Date: Fri, 20 Jun 2025 13:45:07 -0700 Subject: [PATCH 031/602] feat: allow users to access headers for generateContent method and generateContentStream PiperOrigin-RevId: 773828659 --- src/main/java/com/google/genai/Models.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/com/google/genai/Models.java b/src/main/java/com/google/genai/Models.java index a1f643d432c..b9a4f7818ee 100644 --- a/src/main/java/com/google/genai/Models.java +++ b/src/main/java/com/google/genai/Models.java @@ -4330,6 +4330,7 @@ ObjectNode candidateFromMldev(JsonNode fromObject, ObjectNode parentObject) { @ExcludeFromGeneratedCoverageReport ObjectNode generateContentResponseFromMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"candidates"}) != null) { ArrayNode keyArray = (ArrayNode) Common.getValueByPath(fromObject, new String[] {"candidates"}); @@ -5143,6 +5144,7 @@ ObjectNode candidateFromVertex(JsonNode fromObject, ObjectNode parentObject) { @ExcludeFromGeneratedCoverageReport ObjectNode generateContentResponseFromVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"candidates"}) != null) { ArrayNode keyArray = (ArrayNode) Common.getValueByPath(fromObject, new String[] {"candidates"}); From 96c792c3aa84f632e0b46bb986de403ecbf4edc1 Mon Sep 17 00:00:00 2001 From: Ayush Agrawal Date: Fri, 20 Jun 2025 14:18:02 -0700 Subject: [PATCH 032/602] docs: add more comments to make it easier to follow live api code, and to explain the usage of new concepts like thenCompose. PiperOrigin-RevId: 773840049 --- .../examples/LiveTextContextWindowCompressionAsync.java | 7 +++++++ .../google/genai/examples/LiveTextConversationAsync.java | 5 ++++- .../examples/LiveTextConversationResumptionAsync.java | 4 ++++ .../examples/LiveTextToAudioTranscriptionAsync.java | 9 +++++++++ .../genai/examples/LiveTextToTextGenerationAsync.java | 9 ++++++++- 5 files changed, 32 insertions(+), 2 deletions(-) diff --git a/examples/src/main/java/com/google/genai/examples/LiveTextContextWindowCompressionAsync.java b/examples/src/main/java/com/google/genai/examples/LiveTextContextWindowCompressionAsync.java index 23c6afafcff..3844fe389fb 100644 --- a/examples/src/main/java/com/google/genai/examples/LiveTextContextWindowCompressionAsync.java +++ b/examples/src/main/java/com/google/genai/examples/LiveTextContextWindowCompressionAsync.java @@ -87,6 +87,7 @@ public static void main(String[] args) { modelId = args[0]; } + // Configures live session and context window compression. LiveConnectConfig config = LiveConnectConfig.builder() .responseModalities(Modality.Known.TEXT) @@ -114,12 +115,16 @@ public static void main(String[] args) { // Receive messages from the live session. return session.receive(message -> printLiveServerMessage(message, allDone)); }) + // Wait for the allDone future to complete, which is signaled in + // printLiveServerMessage when the server is done sending messages. .thenCompose(unused -> allDone) + // Close the session. .thenCompose(unused -> session.close()); }) .join(); } + /** Wraps client message text. */ public static LiveSendClientContentParameters clientContentFromText(String text) { return LiveSendClientContentParameters.builder() .turnComplete(true) @@ -134,6 +139,7 @@ public static void printLiveServerMessage( return; } + // Print the content sent by the model. Content modelTurn = content.modelTurn().orElse(null); if (modelTurn != null) { for (Part part : modelTurn.parts().orElse(ImmutableList.of())) { @@ -146,6 +152,7 @@ public static void printLiveServerMessage( } } + // Check if the server's turn is complete and signal the allDone future if so. if (content.turnComplete().orElse(false)) { System.out.println(); allDone.complete(null); diff --git a/examples/src/main/java/com/google/genai/examples/LiveTextConversationAsync.java b/examples/src/main/java/com/google/genai/examples/LiveTextConversationAsync.java index b1a76eaa06d..9f7a3d500d1 100644 --- a/examples/src/main/java/com/google/genai/examples/LiveTextConversationAsync.java +++ b/examples/src/main/java/com/google/genai/examples/LiveTextConversationAsync.java @@ -120,6 +120,7 @@ public static void main(String[] args) { } } + /** Wraps client message text. */ public static LiveSendClientContentParameters clientContentFromText(String text) { return LiveSendClientContentParameters.builder() .turnComplete(true) @@ -129,7 +130,9 @@ public static LiveSendClientContentParameters clientContentFromText(String text) public static void printLiveServerMessage( LiveServerMessage message, CompletableFuture allDone) { - message.serverContent() + // Extract and print text from the model. + message + .serverContent() .flatMap(LiveServerContent::modelTurn) .flatMap(Content::parts) .ifPresent(parts -> parts.forEach(part -> part.text().ifPresent(System.out::print))); diff --git a/examples/src/main/java/com/google/genai/examples/LiveTextConversationResumptionAsync.java b/examples/src/main/java/com/google/genai/examples/LiveTextConversationResumptionAsync.java index 38ebab82db3..67a9a92caa3 100644 --- a/examples/src/main/java/com/google/genai/examples/LiveTextConversationResumptionAsync.java +++ b/examples/src/main/java/com/google/genai/examples/LiveTextConversationResumptionAsync.java @@ -128,12 +128,14 @@ public static void main(String[] args) { SessionResumptionConfig.Builder sessionResumptionConfigBuilder = SessionResumptionConfig.builder(); + // Set the session handle if provided. if (sessionHandle != null) { System.out.println("Resuming session handle: " + sessionHandle); sessionResumptionConfigBuilder.handle(sessionHandle); } SessionResumptionConfig sessionResumptionConfig = sessionResumptionConfigBuilder.build(); + // Configures live session and session resumption. LiveConnectConfig config = LiveConnectConfig.builder() .responseModalities(Modality.Known.TEXT) @@ -179,6 +181,7 @@ public static void printLiveServerMessage( } } + /** Wraps client message text. */ public static LiveSendClientContentParameters clientContentFromText(String text) { return LiveSendClientContentParameters.builder() .turnComplete(true) @@ -188,6 +191,7 @@ public static LiveSendClientContentParameters clientContentFromText(String text) private static void printServerContent( LiveServerContent content, CompletableFuture allDone) { + // Extract and print text from the model. content.modelTurn().flatMap(Content::parts).stream() .flatMap(Collection::stream) .map(Part::text) diff --git a/examples/src/main/java/com/google/genai/examples/LiveTextToAudioTranscriptionAsync.java b/examples/src/main/java/com/google/genai/examples/LiveTextToAudioTranscriptionAsync.java index 832f3ae8243..10dd6345833 100644 --- a/examples/src/main/java/com/google/genai/examples/LiveTextToAudioTranscriptionAsync.java +++ b/examples/src/main/java/com/google/genai/examples/LiveTextToAudioTranscriptionAsync.java @@ -95,6 +95,7 @@ public static void main(String[] args) { // Sets the Google Search tool in the config. Tool googleSearchTool = Tool.builder().googleSearch(GoogleSearch.builder()).build(); + // Configures live session and audio transcription. LiveConnectConfig config = LiveConnectConfig.builder() .responseModalities(Modality.Known.AUDIO) @@ -123,12 +124,16 @@ public static void main(String[] args) { // Receive messages from the live session. return session.receive(message -> printLiveServerMessage(message, allDone)); }) + // Wait for the allDone future to complete, which is signaled in + // printLiveServerMessage when the server is done sending messages. .thenCompose(unused -> allDone) + // Close the session. .thenCompose(unused -> session.close()); }) .join(); } + /** Wraps client message text. */ public static LiveSendClientContentParameters clientContentFromText(String text) { return LiveSendClientContentParameters.builder() .turnComplete(true) @@ -150,6 +155,8 @@ public static void printLiveServerMessage( System.out.print(transcription.text().get()); } } + + // Check if the server's turn is complete and signal the allDone future if so. if (content.turnComplete().orElse(false)) { System.out.println(); allDone.complete(null); @@ -162,10 +169,12 @@ private static void processModelTurn(LiveServerContent content) { .flatMap(Collection::stream) .map(Part::inlineData) .filter(Optional::isPresent) + // Print some text to indicate that audio is returned. .forEach(inlineData -> System.out.print("Some audio bytes in inline_data...")); } private static void processGroundingMetadata(LiveServerContent content) { + // Print grounding metadata if present. content.groundingMetadata().stream() .flatMap(metadata -> metadata.groundingChunks().stream()) .flatMap(Collection::stream) diff --git a/examples/src/main/java/com/google/genai/examples/LiveTextToTextGenerationAsync.java b/examples/src/main/java/com/google/genai/examples/LiveTextToTextGenerationAsync.java index 18062532605..adccf9b58e1 100644 --- a/examples/src/main/java/com/google/genai/examples/LiveTextToTextGenerationAsync.java +++ b/examples/src/main/java/com/google/genai/examples/LiveTextToTextGenerationAsync.java @@ -105,12 +105,16 @@ public static void main(String[] args) { // Receive messages from the live session. return session.receive(message -> printLiveServerMessage(message, allDone)); }) + // Wait for the allDone future to complete, which is signaled in + // printLiveServerMessage when the server is done sending messages. .thenCompose(unused -> allDone) + // Close the session. .thenCompose(unused -> session.close()); }) .join(); } + /** Wraps client message text. */ public static LiveSendClientContentParameters clientContentFromText(String text) { return LiveSendClientContentParameters.builder() .turnComplete(true) @@ -120,11 +124,14 @@ public static LiveSendClientContentParameters clientContentFromText(String text) public static void printLiveServerMessage( LiveServerMessage message, CompletableFuture allDone) { - message.serverContent() + // Extract and print text from the model. + message + .serverContent() .flatMap(LiveServerContent::modelTurn) .flatMap(Content::parts) .ifPresent(parts -> parts.forEach(part -> part.text().ifPresent(System.out::print))); + // Check if the server's turn is complete and signal the allDone future if so. if (message.serverContent().flatMap(LiveServerContent::turnComplete).orElse(false)) { System.out.println(); allDone.complete(null); From 9131ac24fde477afb25deb516c7ace51530ed8d9 Mon Sep 17 00:00:00 2001 From: Ayush Agrawal Date: Fri, 20 Jun 2025 14:34:36 -0700 Subject: [PATCH 033/602] feat: configure release-please to automatically update package version across all files during releases. PiperOrigin-RevId: 773845803 --- README.md | 4 ++-- examples/pom.xml | 4 +++- src/main/java/com/google/genai/ApiClient.java | 4 +++- versions.txt | 4 ++++ 4 files changed, 12 insertions(+), 4 deletions(-) create mode 100644 versions.txt diff --git a/README.md b/README.md index f212e0e940e..cf62d054f5f 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ Java idiomatic SDK for the If you're using Maven, add the following to your dependencies: - + ```xml @@ -22,7 +22,7 @@ If you're using Maven, add the following to your dependencies: ``` - + ## Getting Started diff --git a/examples/pom.xml b/examples/pom.xml index 59a433522d2..95ba06f36db 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -12,7 +12,9 @@ UTF-8 1.8 1.8 - 1.6.0-SNAPSHOT + + 1.6.0-SNAPSHOT + diff --git a/src/main/java/com/google/genai/ApiClient.java b/src/main/java/com/google/genai/ApiClient.java index bd129e99a9b..9693526fe33 100644 --- a/src/main/java/com/google/genai/ApiClient.java +++ b/src/main/java/com/google/genai/ApiClient.java @@ -40,7 +40,9 @@ /** Interface for an API client which issues HTTP requests to the GenAI APIs. */ abstract class ApiClient { - private static final String SDK_VERSION = "1.5.0"; // x-version-update:google-genai:released + // {x-version-update-start:google-genai:released} + private static final String SDK_VERSION = "1.5.0"; + // {x-version-update-end:google-genai:released} private static final Logger logger = Logger.getLogger(ApiClient.class.getName()); CloseableHttpClient httpClient; diff --git a/versions.txt b/versions.txt new file mode 100644 index 00000000000..1ffa75a976a --- /dev/null +++ b/versions.txt @@ -0,0 +1,4 @@ +# Format: +# module:released-version:current-version + +google-genai:1.5.0:1.6.0-SNAPSHOT From 9d9acdb494358155cbb3c2ce3acbe55209bbdb7e Mon Sep 17 00:00:00 2001 From: Wanlin Du Date: Mon, 23 Jun 2025 11:29:58 -0700 Subject: [PATCH 034/602] feat: expose the responseJsonSchema in GenerateContentConfig PiperOrigin-RevId: 774859088 --- src/main/java/com/google/genai/Models.java | 14 ++++++++ .../genai/types/GenerateContentConfig.java | 35 +++++++++++++++++++ 2 files changed, 49 insertions(+) diff --git a/src/main/java/com/google/genai/Models.java b/src/main/java/com/google/genai/Models.java index b9a4f7818ee..3daf8996dc5 100644 --- a/src/main/java/com/google/genai/Models.java +++ b/src/main/java/com/google/genai/Models.java @@ -1068,6 +1068,13 @@ ObjectNode generateContentConfigToMldev( toObject)); } + if (Common.getValueByPath(fromObject, new String[] {"responseJsonSchema"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"responseJsonSchema"}, + Common.getValueByPath(fromObject, new String[] {"responseJsonSchema"})); + } + if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"routingConfig"}))) { throw new IllegalArgumentException("routingConfig parameter is not supported in Gemini API."); } @@ -2787,6 +2794,13 @@ ObjectNode generateContentConfigToVertex( toObject)); } + if (Common.getValueByPath(fromObject, new String[] {"responseJsonSchema"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"responseJsonSchema"}, + Common.getValueByPath(fromObject, new String[] {"responseJsonSchema"})); + } + if (Common.getValueByPath(fromObject, new String[] {"routingConfig"}) != null) { Common.setValueByPath( toObject, diff --git a/src/main/java/com/google/genai/types/GenerateContentConfig.java b/src/main/java/com/google/genai/types/GenerateContentConfig.java index 6e5574a647d..ed28f450e84 100644 --- a/src/main/java/com/google/genai/types/GenerateContentConfig.java +++ b/src/main/java/com/google/genai/types/GenerateContentConfig.java @@ -141,6 +141,22 @@ public abstract class GenerateContentConfig extends JsonSerializable { @JsonProperty("responseSchema") public abstract Optional responseSchema(); + /** + * Optional. Output schema of the generated response. This is an alternative to `response_schema` + * that accepts [JSON Schema](https://json-schema.org/). If set, `response_schema` must be + * omitted, but `response_mime_type` is required. While the full JSON Schema may be sent, not all + * features are supported. Specifically, only the following properties are supported: - `$id` - + * `$defs` - `$ref` - `$anchor` - `type` - `format` - `title` - `description` - `enum` (for + * strings and numbers) - `items` - `prefixItems` - `minItems` - `maxItems` - `minimum` - + * `maximum` - `anyOf` - `oneOf` (interpreted the same as `anyOf`) - `properties` - + * `additionalProperties` - `required` The non-standard `propertyOrdering` property may also be + * set. Cyclic references are unrolled to a limited degree and, as such, may only be used within + * non-required properties. (Nullable properties are not sufficient.) If `$ref` is set on a + * sub-schema, no other properties, except for than those starting as a `$`, may be set. + */ + @JsonProperty("responseJsonSchema") + public abstract Optional responseJsonSchema(); + /** Configuration for model router requests. */ @JsonProperty("routingConfig") public abstract Optional routingConfig(); @@ -399,6 +415,25 @@ public Builder responseSchema(Schema.Builder responseSchemaBuilder) { return responseSchema(responseSchemaBuilder.build()); } + /** + * Setter for responseJsonSchema. + * + *

responseJsonSchema: Optional. Output schema of the generated response. This is an + * alternative to `response_schema` that accepts [JSON Schema](https://json-schema.org/). If + * set, `response_schema` must be omitted, but `response_mime_type` is required. While the full + * JSON Schema may be sent, not all features are supported. Specifically, only the following + * properties are supported: - `$id` - `$defs` - `$ref` - `$anchor` - `type` - `format` - + * `title` - `description` - `enum` (for strings and numbers) - `items` - `prefixItems` - + * `minItems` - `maxItems` - `minimum` - `maximum` - `anyOf` - `oneOf` (interpreted the same as + * `anyOf`) - `properties` - `additionalProperties` - `required` The non-standard + * `propertyOrdering` property may also be set. Cyclic references are unrolled to a limited + * degree and, as such, may only be used within non-required properties. (Nullable properties + * are not sufficient.) If `$ref` is set on a sub-schema, no other properties, except for than + * those starting as a `$`, may be set. + */ + @JsonProperty("responseJsonSchema") + public abstract Builder responseJsonSchema(Object responseJsonSchema); + /** * Setter for routingConfig. * From 44c21dd78e0d0be0e681e991b15d3dae3be360f2 Mon Sep 17 00:00:00 2001 From: Kaituo Huang Date: Tue, 24 Jun 2025 13:07:11 -0700 Subject: [PATCH 035/602] docs: improve generate images documentation * add docs for person generation config * add aspect ratio supported values PiperOrigin-RevId: 775352393 --- src/main/java/com/google/genai/types/EditImageConfig.java | 8 ++++++-- .../java/com/google/genai/types/GenerateImagesConfig.java | 8 ++++++-- .../java/com/google/genai/types/PersonGeneration.java | 3 +++ 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/google/genai/types/EditImageConfig.java b/src/main/java/com/google/genai/types/EditImageConfig.java index 3b78f330274..1159b679999 100644 --- a/src/main/java/com/google/genai/types/EditImageConfig.java +++ b/src/main/java/com/google/genai/types/EditImageConfig.java @@ -46,7 +46,10 @@ public abstract class EditImageConfig extends JsonSerializable { @JsonProperty("numberOfImages") public abstract Optional numberOfImages(); - /** Aspect ratio of the generated images. */ + /** + * Aspect ratio of the generated images. Supported values are "1:1", "3:4", "4:3", "9:16", and + * "16:9". + */ @JsonProperty("aspectRatio") public abstract Optional aspectRatio(); @@ -169,7 +172,8 @@ public Builder httpOptions(HttpOptions.Builder httpOptionsBuilder) { /** * Setter for aspectRatio. * - *

aspectRatio: Aspect ratio of the generated images. + *

aspectRatio: Aspect ratio of the generated images. Supported values are "1:1", "3:4", + * "4:3", "9:16", and "16:9". */ @JsonProperty("aspectRatio") public abstract Builder aspectRatio(String aspectRatio); diff --git a/src/main/java/com/google/genai/types/GenerateImagesConfig.java b/src/main/java/com/google/genai/types/GenerateImagesConfig.java index 513b2f949fb..0a672e02ecd 100644 --- a/src/main/java/com/google/genai/types/GenerateImagesConfig.java +++ b/src/main/java/com/google/genai/types/GenerateImagesConfig.java @@ -46,7 +46,10 @@ public abstract class GenerateImagesConfig extends JsonSerializable { @JsonProperty("numberOfImages") public abstract Optional numberOfImages(); - /** Aspect ratio of the generated images. */ + /** + * Aspect ratio of the generated images. Supported values are "1:1", "3:4", "4:3", "9:16", and + * "16:9". + */ @JsonProperty("aspectRatio") public abstract Optional aspectRatio(); @@ -166,7 +169,8 @@ public Builder httpOptions(HttpOptions.Builder httpOptionsBuilder) { /** * Setter for aspectRatio. * - *

aspectRatio: Aspect ratio of the generated images. + *

aspectRatio: Aspect ratio of the generated images. Supported values are "1:1", "3:4", + * "4:3", "9:16", and "16:9". */ @JsonProperty("aspectRatio") public abstract Builder aspectRatio(String aspectRatio); diff --git a/src/main/java/com/google/genai/types/PersonGeneration.java b/src/main/java/com/google/genai/types/PersonGeneration.java index 96e71026a07..8023702e92f 100644 --- a/src/main/java/com/google/genai/types/PersonGeneration.java +++ b/src/main/java/com/google/genai/types/PersonGeneration.java @@ -28,10 +28,13 @@ public class PersonGeneration { /** Enum representing the known values for PersonGeneration. */ public enum Known { + /** Block generation of images of people. */ DONT_ALLOW, + /** Generate images of adults, but not children. */ ALLOW_ADULT, + /** Generate images that include adults and children. */ ALLOW_ALL, PERSON_GENERATION_UNSPECIFIED From 94a329abcd3c668065abfae511b55766ed051668 Mon Sep 17 00:00:00 2001 From: Matthew Tang Date: Tue, 24 Jun 2025 16:59:40 -0700 Subject: [PATCH 036/602] feat: Add enhance_input_image and image_preservation_factor fields for upscale_image PiperOrigin-RevId: 775438709 --- .../google/genai/examples/UpscaleImage.java | 6 +++- src/main/java/com/google/genai/Models.java | 20 +++++++++++ .../genai/types/UpscaleImageAPIConfig.java | 34 +++++++++++++++++++ .../genai/types/UpscaleImageConfig.java | 34 +++++++++++++++++++ 4 files changed, 93 insertions(+), 1 deletion(-) diff --git a/examples/src/main/java/com/google/genai/examples/UpscaleImage.java b/examples/src/main/java/com/google/genai/examples/UpscaleImage.java index 4df5e6f3206..ef726d4c105 100644 --- a/examples/src/main/java/com/google/genai/examples/UpscaleImage.java +++ b/examples/src/main/java/com/google/genai/examples/UpscaleImage.java @@ -78,7 +78,11 @@ public static void main(String[] args) { modelId, image, "x2", - UpscaleImageConfig.builder().outputMimeType("image/jpeg").build()); + UpscaleImageConfig.builder() + .outputMimeType("image/jpeg") + .enhanceInputImage(true) + .imagePreservationFactor(0.6f) + .build()); Image upscaledImage = upscaleImageResponse.generatedImages().get().get(0).image().get(); // Do something with upscaledImage. diff --git a/src/main/java/com/google/genai/Models.java b/src/main/java/com/google/genai/Models.java index 3daf8996dc5..dfe439683ee 100644 --- a/src/main/java/com/google/genai/Models.java +++ b/src/main/java/com/google/genai/Models.java @@ -3529,6 +3529,20 @@ ObjectNode upscaleImageAPIConfigToVertex(JsonNode fromObject, ObjectNode parentO Common.getValueByPath(fromObject, new String[] {"outputCompressionQuality"})); } + if (Common.getValueByPath(fromObject, new String[] {"enhanceInputImage"}) != null) { + Common.setValueByPath( + parentObject, + new String[] {"parameters", "upscaleConfig", "enhanceInputImage"}, + Common.getValueByPath(fromObject, new String[] {"enhanceInputImage"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"imagePreservationFactor"}) != null) { + Common.setValueByPath( + parentObject, + new String[] {"parameters", "upscaleConfig", "imagePreservationFactor"}, + Common.getValueByPath(fromObject, new String[] {"imagePreservationFactor"})); + } + if (Common.getValueByPath(fromObject, new String[] {"numberOfImages"}) != null) { Common.setValueByPath( parentObject, @@ -6967,6 +6981,12 @@ public UpscaleImageResponse upscaleImage( if (config.includeRaiReason().isPresent()) { builder = builder.includeRaiReason(config.includeRaiReason().get()); } + if (config.enhanceInputImage().isPresent()) { + builder = builder.enhanceInputImage(config.enhanceInputImage().get()); + } + if (config.imagePreservationFactor().isPresent()) { + builder = builder.imagePreservationFactor(config.imagePreservationFactor().get()); + } } builder = builder.mode("upscale"); diff --git a/src/main/java/com/google/genai/types/UpscaleImageAPIConfig.java b/src/main/java/com/google/genai/types/UpscaleImageAPIConfig.java index 5923f5fae7e..78d294bd7e4 100644 --- a/src/main/java/com/google/genai/types/UpscaleImageAPIConfig.java +++ b/src/main/java/com/google/genai/types/UpscaleImageAPIConfig.java @@ -52,6 +52,21 @@ public abstract class UpscaleImageAPIConfig extends JsonSerializable { @JsonProperty("outputCompressionQuality") public abstract Optional outputCompressionQuality(); + /** + * Whether to add an image enhancing step before upscaling. It is expected to suppress the noise + * and JPEG compression artifacts from the input image. + */ + @JsonProperty("enhanceInputImage") + public abstract Optional enhanceInputImage(); + + /** + * With a higher image preservation factor, the original image pixels are more respected. With a + * lower image preservation factor, the output image will have be more different from the input + * image, but with finer details and less noise. + */ + @JsonProperty("imagePreservationFactor") + public abstract Optional imagePreservationFactor(); + /** */ @JsonProperty("numberOfImages") public abstract Optional numberOfImages(); @@ -119,6 +134,25 @@ public Builder httpOptions(HttpOptions.Builder httpOptionsBuilder) { @JsonProperty("outputCompressionQuality") public abstract Builder outputCompressionQuality(Integer outputCompressionQuality); + /** + * Setter for enhanceInputImage. + * + *

enhanceInputImage: Whether to add an image enhancing step before upscaling. It is expected + * to suppress the noise and JPEG compression artifacts from the input image. + */ + @JsonProperty("enhanceInputImage") + public abstract Builder enhanceInputImage(boolean enhanceInputImage); + + /** + * Setter for imagePreservationFactor. + * + *

imagePreservationFactor: With a higher image preservation factor, the original image + * pixels are more respected. With a lower image preservation factor, the output image will have + * be more different from the input image, but with finer details and less noise. + */ + @JsonProperty("imagePreservationFactor") + public abstract Builder imagePreservationFactor(Float imagePreservationFactor); + /** * Setter for numberOfImages. * diff --git a/src/main/java/com/google/genai/types/UpscaleImageConfig.java b/src/main/java/com/google/genai/types/UpscaleImageConfig.java index a913b1d7022..f9cc1e0c894 100644 --- a/src/main/java/com/google/genai/types/UpscaleImageConfig.java +++ b/src/main/java/com/google/genai/types/UpscaleImageConfig.java @@ -50,6 +50,21 @@ public abstract class UpscaleImageConfig extends JsonSerializable { @JsonProperty("outputCompressionQuality") public abstract Optional outputCompressionQuality(); + /** + * Whether to add an image enhancing step before upscaling. It is expected to suppress the noise + * and JPEG compression artifacts from the input image. + */ + @JsonProperty("enhanceInputImage") + public abstract Optional enhanceInputImage(); + + /** + * With a higher image preservation factor, the original image pixels are more respected. With a + * lower image preservation factor, the output image will have be more different from the input + * image, but with finer details and less noise. + */ + @JsonProperty("imagePreservationFactor") + public abstract Optional imagePreservationFactor(); + /** Instantiates a builder for UpscaleImageConfig. */ public static Builder builder() { return new AutoValue_UpscaleImageConfig.Builder(); @@ -109,6 +124,25 @@ public Builder httpOptions(HttpOptions.Builder httpOptionsBuilder) { @JsonProperty("outputCompressionQuality") public abstract Builder outputCompressionQuality(Integer outputCompressionQuality); + /** + * Setter for enhanceInputImage. + * + *

enhanceInputImage: Whether to add an image enhancing step before upscaling. It is expected + * to suppress the noise and JPEG compression artifacts from the input image. + */ + @JsonProperty("enhanceInputImage") + public abstract Builder enhanceInputImage(boolean enhanceInputImage); + + /** + * Setter for imagePreservationFactor. + * + *

imagePreservationFactor: With a higher image preservation factor, the original image + * pixels are more respected. With a lower image preservation factor, the output image will have + * be more different from the input image, but with finer details and less noise. + */ + @JsonProperty("imagePreservationFactor") + public abstract Builder imagePreservationFactor(Float imagePreservationFactor); + public abstract UpscaleImageConfig build(); } From b0e665bf6ae09dc2146e49714a4855443a270776 Mon Sep 17 00:00:00 2001 From: Matthew Tang Date: Wed, 25 Jun 2025 11:25:47 -0700 Subject: [PATCH 037/602] feat: Add compressionQuality enum for generate_videos PiperOrigin-RevId: 775769513 --- src/main/java/com/google/genai/Models.java | 12 ++ .../genai/types/GenerateVideosConfig.java | 33 ++++++ .../genai/types/VideoCompressionQuality.java | 109 ++++++++++++++++++ 3 files changed, 154 insertions(+) create mode 100644 src/main/java/com/google/genai/types/VideoCompressionQuality.java diff --git a/src/main/java/com/google/genai/Models.java b/src/main/java/com/google/genai/Models.java index dfe439683ee..0f59255f36f 100644 --- a/src/main/java/com/google/genai/Models.java +++ b/src/main/java/com/google/genai/Models.java @@ -1753,6 +1753,11 @@ ObjectNode generateVideosConfigToMldev(JsonNode fromObject, ObjectNode parentObj throw new IllegalArgumentException("lastFrame parameter is not supported in Gemini API."); } + if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"compressionQuality"}))) { + throw new IllegalArgumentException( + "compressionQuality parameter is not supported in Gemini API."); + } + return toObject; } @@ -3988,6 +3993,13 @@ ObjectNode generateVideosConfigToVertex(JsonNode fromObject, ObjectNode parentOb toObject)); } + if (Common.getValueByPath(fromObject, new String[] {"compressionQuality"}) != null) { + Common.setValueByPath( + parentObject, + new String[] {"parameters", "compressionQuality"}, + Common.getValueByPath(fromObject, new String[] {"compressionQuality"})); + } + return toObject; } diff --git a/src/main/java/com/google/genai/types/GenerateVideosConfig.java b/src/main/java/com/google/genai/types/GenerateVideosConfig.java index 1ff013293f6..b5f22250882 100644 --- a/src/main/java/com/google/genai/types/GenerateVideosConfig.java +++ b/src/main/java/com/google/genai/types/GenerateVideosConfig.java @@ -22,6 +22,7 @@ import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.google.auto.value.AutoValue; +import com.google.errorprone.annotations.CanIgnoreReturnValue; import com.google.genai.JsonSerializable; import java.util.Optional; @@ -100,6 +101,10 @@ public abstract class GenerateVideosConfig extends JsonSerializable { @JsonProperty("lastFrame") public abstract Optional lastFrame(); + /** Compression quality of the generated videos. */ + @JsonProperty("compressionQuality") + public abstract Optional compressionQuality(); + /** Instantiates a builder for GenerateVideosConfig. */ public static Builder builder() { return new AutoValue_GenerateVideosConfig.Builder(); @@ -254,6 +259,34 @@ public Builder lastFrame(Image.Builder lastFrameBuilder) { return lastFrame(lastFrameBuilder.build()); } + /** + * Setter for compressionQuality. + * + *

compressionQuality: Compression quality of the generated videos. + */ + @JsonProperty("compressionQuality") + public abstract Builder compressionQuality(VideoCompressionQuality compressionQuality); + + /** + * Setter for compressionQuality given a known enum. + * + *

compressionQuality: Compression quality of the generated videos. + */ + @CanIgnoreReturnValue + public Builder compressionQuality(VideoCompressionQuality.Known knownType) { + return compressionQuality(new VideoCompressionQuality(knownType)); + } + + /** + * Setter for compressionQuality given a string. + * + *

compressionQuality: Compression quality of the generated videos. + */ + @CanIgnoreReturnValue + public Builder compressionQuality(String compressionQuality) { + return compressionQuality(new VideoCompressionQuality(compressionQuality)); + } + public abstract GenerateVideosConfig build(); } diff --git a/src/main/java/com/google/genai/types/VideoCompressionQuality.java b/src/main/java/com/google/genai/types/VideoCompressionQuality.java new file mode 100644 index 00000000000..b3d9926eccd --- /dev/null +++ b/src/main/java/com/google/genai/types/VideoCompressionQuality.java @@ -0,0 +1,109 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Auto-generated code. Do not edit. + +package com.google.genai.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; +import com.google.common.base.Ascii; +import java.util.Objects; + +/** Enum that controls the compression quality of the generated videos. */ +public class VideoCompressionQuality { + + /** Enum representing the known values for VideoCompressionQuality. */ + public enum Known { + /** + * Optimized video compression quality. This will produce videos with a compressed, smaller file + * size. + */ + OPTIMIZED, + + /** Lossless video compression quality. This will produce videos with a larger file size. */ + LOSSLESS, + + VIDEO_COMPRESSION_QUALITY_UNSPECIFIED + } + + private Known videoCompressionQualityEnum; + private final String value; + + @JsonCreator + public VideoCompressionQuality(String value) { + this.value = value; + for (Known videoCompressionQualityEnum : Known.values()) { + if (Ascii.equalsIgnoreCase(videoCompressionQualityEnum.toString(), value)) { + this.videoCompressionQualityEnum = videoCompressionQualityEnum; + break; + } + } + if (this.videoCompressionQualityEnum == null) { + this.videoCompressionQualityEnum = Known.VIDEO_COMPRESSION_QUALITY_UNSPECIFIED; + } + } + + public VideoCompressionQuality(Known knownValue) { + this.videoCompressionQualityEnum = knownValue; + this.value = knownValue.toString(); + } + + @Override + @JsonValue + public String toString() { + return this.value; + } + + @SuppressWarnings("PatternMatchingInstanceof") + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null) { + return false; + } + + if (!(o instanceof VideoCompressionQuality)) { + return false; + } + + VideoCompressionQuality other = (VideoCompressionQuality) o; + + if (this.videoCompressionQualityEnum != Known.VIDEO_COMPRESSION_QUALITY_UNSPECIFIED + && other.videoCompressionQualityEnum != Known.VIDEO_COMPRESSION_QUALITY_UNSPECIFIED) { + return this.videoCompressionQualityEnum == other.videoCompressionQualityEnum; + } else if (this.videoCompressionQualityEnum == Known.VIDEO_COMPRESSION_QUALITY_UNSPECIFIED + && other.videoCompressionQualityEnum == Known.VIDEO_COMPRESSION_QUALITY_UNSPECIFIED) { + return this.value.equals(other.value); + } + return false; + } + + @Override + public int hashCode() { + if (this.videoCompressionQualityEnum != Known.VIDEO_COMPRESSION_QUALITY_UNSPECIFIED) { + return this.videoCompressionQualityEnum.hashCode(); + } else { + return Objects.hashCode(this.value); + } + } + + public Known knownEnum() { + return this.videoCompressionQualityEnum; + } +} From 74d0e2f77bb038f786ee82ffde7739ecca9f6c13 Mon Sep 17 00:00:00 2001 From: Jaycee Li Date: Wed, 25 Jun 2025 13:47:26 -0700 Subject: [PATCH 038/602] chore: Consolidate unit tests for external environment PiperOrigin-RevId: 775822914 --- .../java/com/google/genai/ClientTest.java | 14 +++++++------ .../com/google/genai/HttpApiClientTest.java | 16 ++++++++------ .../java/com/google/genai/ModelsTest.java | 4 ++++ .../java/com/google/genai/OperationsTest.java | 4 ++++ src/test/java/com/google/genai/TableTest.java | 21 ++++++++++--------- 5 files changed, 37 insertions(+), 22 deletions(-) diff --git a/src/test/java/com/google/genai/ClientTest.java b/src/test/java/com/google/genai/ClientTest.java index ee53b917cdf..5892d65789c 100644 --- a/src/test/java/com/google/genai/ClientTest.java +++ b/src/test/java/com/google/genai/ClientTest.java @@ -46,7 +46,7 @@ public class ClientTest { @Test public void testInitClientFromBuilder_mldev() { // Act - Client client = Client.builder().apiKey(API_KEY).build(); + Client client = Client.builder().apiKey(API_KEY).vertexAI(false).build(); // Assert assertEquals(API_KEY, client.apiKey()); @@ -94,7 +94,8 @@ public void testInitClientFromBuilder_withCredentialsAndHttpOptions() { @Test public void testReplayClient_mldev() { // Act - Client client = Client.builder().apiKey(API_KEY).debugConfig(DEBUG_CONFIG).build(); + Client client = + Client.builder().apiKey(API_KEY).vertexAI(false).debugConfig(DEBUG_CONFIG).build(); // Assert assertEquals(API_KEY, client.apiKey()); @@ -141,7 +142,8 @@ public void testInitClientFromBuilder_setProjectInMldev_throwsException() { // Act IllegalArgumentException exception = assertThrows( - IllegalArgumentException.class, () -> Client.builder().project(PROJECT).build()); + IllegalArgumentException.class, + () -> Client.builder().vertexAI(false).project(PROJECT).build()); // Assert assertEquals("Gemini API do not support project/location.", exception.getMessage()); @@ -167,7 +169,7 @@ public void testSetDefaultBaseUrls() { Client.setDefaultBaseUrls(Optional.of("gemini-base-url"), Optional.of("vertex-base-url")); Client vertexClient = Client.builder().project(PROJECT).location(LOCATION).vertexAI(true).build(); - Client mldevClient = Client.builder().apiKey(API_KEY).build(); + Client mldevClient = Client.builder().apiKey(API_KEY).vertexAI(false).build(); assertEquals("gemini-base-url", mldevClient.baseUrl().orElse(null)); assertEquals("vertex-base-url", vertexClient.baseUrl().orElse(null)); @@ -183,7 +185,7 @@ public void testCloseClient() throws Exception { CloseableHttpClient httpClient = mock(CloseableHttpClient.class); when(apiClient.httpClient()).thenReturn(httpClient); - Client client = Client.builder().apiKey(API_KEY).build(); + Client client = Client.builder().apiKey(API_KEY).vertexAI(false).build(); Field apiClientField = Client.class.getDeclaredField("apiClient"); apiClientField.setAccessible(true); apiClientField.set(client, apiClient); @@ -203,7 +205,7 @@ public void testCloseClient_throwsException() throws Exception { when(apiClient.httpClient()).thenReturn(httpClient); doThrow(new IOException("Failed to close HTTP client.")).when(httpClient).close(); - Client client = Client.builder().apiKey(API_KEY).build(); + Client client = Client.builder().apiKey(API_KEY).vertexAI(false).build(); Field apiClientField = Client.class.getDeclaredField("apiClient"); apiClientField.setAccessible(true); apiClientField.set(client, apiClient); diff --git a/src/test/java/com/google/genai/HttpApiClientTest.java b/src/test/java/com/google/genai/HttpApiClientTest.java index 7a0091ba156..2dc5c61b149 100644 --- a/src/test/java/com/google/genai/HttpApiClientTest.java +++ b/src/test/java/com/google/genai/HttpApiClientTest.java @@ -355,7 +355,8 @@ public void testHttpClientNoTimeout() throws Exception { RequestConfig config = getRequestConfig(httpClient); - assertEquals(-1, config.getConnectTimeout()); + // Default timeout is 5 minutes (300000 milliseconds). + assertEquals(300000, config.getConnectTimeout()); assertEquals("api-key", client.apiKey()); assertFalse(client.httpOptions.headers().get().containsKey("X-Server-Timeout")); } @@ -376,7 +377,8 @@ public void testHttpClientVertexNoTimeout() throws Exception { RequestConfig config = getRequestConfig(httpClient); - assertEquals(-1, config.getConnectTimeout()); + // Default timeout is 5 minutes (300000 milliseconds). + assertEquals(300000, config.getConnectTimeout()); assertEquals("project", client.project()); assertEquals("location", client.location()); assertTrue(client.vertexAI()); @@ -534,7 +536,7 @@ public void testProxySetup() throws Exception { .baseUrl("http://localhost:" + wireMockServer.port()) .apiVersion("v1beta") .build(); - Client client = Client.builder().httpOptions(httpOptions).build(); + Client client = Client.builder().vertexAI(false).httpOptions(httpOptions).build(); GenerateContentResponse response = client.models.generateContent("gemini-2.0-flash", "What is your name?", null); @@ -549,7 +551,7 @@ public void testProxySetup() throws Exception { public void testClientInitializationWithBaseUrlFromHttpOptions() throws Exception { HttpOptions httpOptions = HttpOptions.builder().baseUrl("https://custom-base-url.googleapis.com/").build(); - Client client = Client.builder().httpOptions(httpOptions).build(); + Client client = Client.builder().vertexAI(false).httpOptions(httpOptions).build(); assertTrue(client.baseUrl().isPresent()); assertEquals(client.baseUrl().get(), "https://custom-base-url.googleapis.com/"); @@ -562,7 +564,7 @@ public void testClientInitializationWithBaseUrlFromHttpOptionsOverridesSetDefaul HttpOptions.builder().baseUrl("https://custom-base-url.googleapis.com/").build(); Client.setDefaultBaseUrls( Optional.of("https://gemini-base-url.googleapis.com/"), Optional.empty()); - Client client = Client.builder().httpOptions(httpOptions).build(); + Client client = Client.builder().vertexAI(false).httpOptions(httpOptions).build(); assertTrue(client.baseUrl().isPresent()); assertEquals(client.baseUrl().get(), "https://custom-base-url.googleapis.com/"); @@ -572,7 +574,7 @@ public void testClientInitializationWithBaseUrlFromHttpOptionsOverridesSetDefaul public void testClientInitializationWithBaseUrlFromSetBaseUrls() throws Exception { Client.setDefaultBaseUrls( Optional.of("https://custom-base-url.googleapis.com/"), Optional.empty()); - Client client = Client.builder().build(); + Client client = Client.builder().vertexAI(false).build(); assertTrue(client.baseUrl().isPresent()); assertEquals(client.baseUrl().get(), "https://custom-base-url.googleapis.com/"); @@ -587,6 +589,7 @@ public void testClientInitializationWithBaseUrlFromSetBaseUrlsOverridesEnvironme Optional.of("https://custom-base-url.googleapis.com/"), Optional.empty()); Client client = Client.builder() + .vertexAI(false) .environmentVariables( ImmutableMap.of( "GOOGLE_GEMINI_BASE_URL", "https://gemini-base-url.googleapis.com/")) @@ -602,6 +605,7 @@ public void testClientInitializationWithBaseUrlFromSetBaseUrlsOverridesEnvironme public void testClientInitializationWithBaseUrlFromEnvironment() throws Exception { Client client = Client.builder() + .vertexAI(false) .environmentVariables( ImmutableMap.of( "GOOGLE_GEMINI_BASE_URL", "https://custom-base-url.googleapis.com/")) diff --git a/src/test/java/com/google/genai/ModelsTest.java b/src/test/java/com/google/genai/ModelsTest.java index 1e189f136c4..5f2b2568d91 100644 --- a/src/test/java/com/google/genai/ModelsTest.java +++ b/src/test/java/com/google/genai/ModelsTest.java @@ -52,10 +52,14 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; +import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.CsvSource; import org.junit.jupiter.params.provider.ValueSource; +@EnabledIfEnvironmentVariable( + named = "GOOGLE_GENAI_REPLAYS_DIRECTORY", + matches = ".*genai/replays.*") public class ModelsTest { private Client createClient(boolean vertexAI, String replayId) { // Use the API mode until the replay mode is complete. diff --git a/src/test/java/com/google/genai/OperationsTest.java b/src/test/java/com/google/genai/OperationsTest.java index 4cd1a6b763e..0fb32bd3773 100644 --- a/src/test/java/com/google/genai/OperationsTest.java +++ b/src/test/java/com/google/genai/OperationsTest.java @@ -21,9 +21,13 @@ import com.google.genai.types.GenerateVideosConfig; import com.google.genai.types.GenerateVideosOperation; +import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; +@EnabledIfEnvironmentVariable( + named = "GOOGLE_GENAI_REPLAYS_DIRECTORY", + matches = ".*genai/replays.*") public class OperationsTest { private Client createClient(boolean vertexAI, String replayId) { // Use the API mode until the replay mode is complete. diff --git a/src/test/java/com/google/genai/TableTest.java b/src/test/java/com/google/genai/TableTest.java index 7ef3429b9d5..8ccd64a43e6 100644 --- a/src/test/java/com/google/genai/TableTest.java +++ b/src/test/java/com/google/genai/TableTest.java @@ -17,12 +17,17 @@ /** Runs the test table. */ package com.google.genai; -import static com.github.tomakehurst.wiremock.client.WireMock.*; +import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; +import static com.github.tomakehurst.wiremock.client.WireMock.any; +import static com.github.tomakehurst.wiremock.client.WireMock.anyUrl; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.fail; import static org.junit.jupiter.api.Assumptions.assumeTrue; import com.fasterxml.jackson.core.type.TypeReference; +import com.github.tomakehurst.wiremock.WireMockServer; +import com.github.tomakehurst.wiremock.client.WireMock; +import com.github.tomakehurst.wiremock.core.WireMockConfiguration; import com.google.common.collect.ImmutableSet; import com.google.genai.types.HttpOptions; import com.google.genai.types.TestTableFile; @@ -36,18 +41,14 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Collections; +import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.HashMap; import java.util.Optional; - import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.DynamicTest; import org.junit.jupiter.api.TestFactory; - -import com.github.tomakehurst.wiremock.client.WireMock; -import com.github.tomakehurst.wiremock.core.WireMockConfiguration; -import com.github.tomakehurst.wiremock.WireMockServer; +import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable; /** Sample class to prototype GenAI SDK functionalities. */ public final class TableTest { @@ -351,11 +352,11 @@ private static String getReplayFilePath(String testName) { @TestFactory @DisplayName("TableTest") + @EnabledIfEnvironmentVariable( + named = "GOOGLE_GENAI_REPLAYS_DIRECTORY", + matches = ".*genai/replays.*") Collection createTests() throws IOException { String replaysPath = System.getenv("GOOGLE_GENAI_REPLAYS_DIRECTORY"); - if (replaysPath == null) { - throw new RuntimeException("GOOGLE_GENAI_REPLAYS_DIRECTORY is not set"); - } String testsReplaysPath = replaysPath + "/tests"; Collection dynamicTests = new ArrayList<>(); Files.walk(Paths.get(testsReplaysPath)) From 1f66ce13d239563469f2430e5c0e0a987497da0f Mon Sep 17 00:00:00 2001 From: Jaycee Li Date: Wed, 25 Jun 2025 14:31:39 -0700 Subject: [PATCH 039/602] chore: Fix VideoMetadataTest PiperOrigin-RevId: 775839493 --- src/test/java/com/google/genai/types/VideoMetadataTest.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/test/java/com/google/genai/types/VideoMetadataTest.java b/src/test/java/com/google/genai/types/VideoMetadataTest.java index f98e33ba4b9..f3afd572d6d 100644 --- a/src/test/java/com/google/genai/types/VideoMetadataTest.java +++ b/src/test/java/com/google/genai/types/VideoMetadataTest.java @@ -14,13 +14,12 @@ * limitations under the License. */ -package com.google.genai; +package com.google.genai.types; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; -import com.google.genai.types.VideoMetadata; import java.time.Duration; import org.junit.jupiter.api.Test; From 5ce13e9c79c4791d405b1dfa71c1d9358dc5a08d Mon Sep 17 00:00:00 2001 From: Amy Wu Date: Wed, 25 Jun 2025 14:50:07 -0700 Subject: [PATCH 040/602] feat: Batches support in Java PiperOrigin-RevId: 775846485 --- .../genai/examples/BatchManagement.java | 134 + .../genai/examples/BatchManagementAsync.java | 184 + src/main/java/com/google/genai/ApiClient.java | 2 + .../java/com/google/genai/AsyncBatches.java | 109 + src/main/java/com/google/genai/BasePager.java | 5 +- src/main/java/com/google/genai/Batches.java | 6427 +++++++++++++++++ src/main/java/com/google/genai/Client.java | 4 + .../java/com/google/genai/Transformers.java | 88 + .../java/com/google/genai/types/BatchJob.java | 242 + .../genai/types/BatchJobDestination.java | 155 + .../google/genai/types/BatchJobSource.java | 151 + .../genai/types/CancelBatchJobConfig.java | 77 + .../genai/types/CancelBatchJobParameters.java | 97 + .../genai/types/CreateBatchJobConfig.java | 115 + .../genai/types/CreateBatchJobParameters.java | 117 + .../google/genai/types/GetBatchJobConfig.java | 77 + .../genai/types/GetBatchJobParameters.java | 97 + .../google/genai/types/InlinedRequest.java | 130 + .../google/genai/types/InlinedResponse.java | 98 + .../java/com/google/genai/types/JobError.java | 112 + .../java/com/google/genai/types/JobState.java | 140 + .../genai/types/ListBatchJobsConfig.java | 113 + .../genai/types/ListBatchJobsParameters.java | 79 + .../genai/types/ListBatchJobsResponse.java | 105 + src/test/java/com/google/genai/TableTest.java | 1 + 25 files changed, 8858 insertions(+), 1 deletion(-) create mode 100644 examples/src/main/java/com/google/genai/examples/BatchManagement.java create mode 100644 examples/src/main/java/com/google/genai/examples/BatchManagementAsync.java create mode 100644 src/main/java/com/google/genai/AsyncBatches.java create mode 100644 src/main/java/com/google/genai/Batches.java create mode 100644 src/main/java/com/google/genai/types/BatchJob.java create mode 100644 src/main/java/com/google/genai/types/BatchJobDestination.java create mode 100644 src/main/java/com/google/genai/types/BatchJobSource.java create mode 100644 src/main/java/com/google/genai/types/CancelBatchJobConfig.java create mode 100644 src/main/java/com/google/genai/types/CancelBatchJobParameters.java create mode 100644 src/main/java/com/google/genai/types/CreateBatchJobConfig.java create mode 100644 src/main/java/com/google/genai/types/CreateBatchJobParameters.java create mode 100644 src/main/java/com/google/genai/types/GetBatchJobConfig.java create mode 100644 src/main/java/com/google/genai/types/GetBatchJobParameters.java create mode 100644 src/main/java/com/google/genai/types/InlinedRequest.java create mode 100644 src/main/java/com/google/genai/types/InlinedResponse.java create mode 100644 src/main/java/com/google/genai/types/JobError.java create mode 100644 src/main/java/com/google/genai/types/JobState.java create mode 100644 src/main/java/com/google/genai/types/ListBatchJobsConfig.java create mode 100644 src/main/java/com/google/genai/types/ListBatchJobsParameters.java create mode 100644 src/main/java/com/google/genai/types/ListBatchJobsResponse.java diff --git a/examples/src/main/java/com/google/genai/examples/BatchManagement.java b/examples/src/main/java/com/google/genai/examples/BatchManagement.java new file mode 100644 index 00000000000..d0050df6712 --- /dev/null +++ b/examples/src/main/java/com/google/genai/examples/BatchManagement.java @@ -0,0 +1,134 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Usage: + * + *

1a. If you are using Vertex AI, setup ADC to get credentials: + * https://cloud.google.com/docs/authentication/provide-credentials-adc#google-idp + * + *

Then set Project, Location, and USE_VERTEXAI flag as environment variables: + * + *

export GOOGLE_CLOUD_PROJECT=YOUR_PROJECT + * + *

export GOOGLE_CLOUD_LOCATION=YOUR_LOCATION + * + *

export GOOGLE_GENAI_USE_VERTEXAI=true + * + *

1b. If you are using Gemini Developer API, set an API key environment variable. You can find a + * list of available API keys here: https://aistudio.google.com/app/apikey + * + *

export GOOGLE_API_KEY=YOUR_API_KEY + * + *

2. Compile the java package and run the sample code. + * + *

mvn clean compile + * + *

mvn exec:java -Dexec.mainClass="com.google.genai.examples.BatchManagement" + * -Dexec.args="YOUR_MODEL_ID" + */ +package com.google.genai.examples; + +import com.google.genai.Client; +import com.google.genai.types.BatchJob; +import com.google.genai.types.BatchJobDestination; +import com.google.genai.types.BatchJobSource; +import com.google.genai.types.Content; +import com.google.genai.types.CreateBatchJobConfig; +import com.google.genai.types.InlinedRequest; +import com.google.genai.types.ListBatchJobsConfig; +import com.google.genai.types.Part; + +/** An example of using the Unified Gen AI Java SDK to do operations on batch jobs. */ +public final class BatchManagement { + + public static void main(String[] args) { + + // Instantiate the client. The client by default uses the Gemini Developer API. It gets the API + // key from the environment variable `GOOGLE_API_KEY`. Vertex AI API can be used by setting the + // environment variables `GOOGLE_CLOUD_LOCATION` and `GOOGLE_CLOUD_PROJECT`, as well as setting + // `GOOGLE_GENAI_USE_VERTEXAI` to "true". + // + // Note: Some services are only available in a specific API backend (Gemini or Vertex), you will + // get a `UnsupportedOperationException` if you try to use a service that is not available in + // the backend you are using. + Client client = new Client(); + + if (client.vertexAI()) { + String modelId = "gemini-1.5-flash-002"; + if (args.length != 0) { + modelId = args[0]; + } + System.out.println("Using Vertex AI"); + // Create a batch job. + BatchJobSource batchJobSource = + BatchJobSource.builder() + .gcsUri("gs://unified-genai-tests/batches/input/generate_content_requests.jsonl") + .format("jsonl") + .build(); + CreateBatchJobConfig config = + CreateBatchJobConfig.builder() + .displayName("summarize the pdf") + .dest( + BatchJobDestination.builder() + .gcsUri("gs://unified-genai-tests/batches/output") + .format("jsonl")) + .build(); + BatchJob batchJob1 = client.batches.create(modelId, batchJobSource, config); + System.out.println("Created batch job: " + batchJob1); + // Get the batch job by name. + BatchJob batchJob2 = client.batches.get(batchJob1.name().get(), null); + System.out.println("Get batch job: " + batchJob2); + // Cancel the batch job. + client.batches.cancel(batchJob1.name().get(), null); + System.out.println("Cancelled batch job: " + batchJob1.name().get()); + } else { + System.out.println("Using Gemini Developer API"); + String modelId = "gemini-2.0-flash"; + if (args.length != 0) { + modelId = args[0]; + } + // Create a batch job. + BatchJobSource batchJobSource = + BatchJobSource.builder() + .inlinedRequests( + InlinedRequest.builder() + .contents(Content.builder().parts(Part.fromText("Hello!")))) + .build(); + CreateBatchJobConfig config = + CreateBatchJobConfig.builder().displayName("test-batch-job-java").build(); + BatchJob batchJob1 = client.batches.create(modelId, batchJobSource, config); + System.out.println("Created batch job: " + batchJob1); + // Get the batch job by name. + BatchJob batchJob2 = client.batches.get(batchJob1.name().get(), null); + System.out.println("Get batch job: " + batchJob2); + // Cancel the batch job. + client.batches.cancel(batchJob1.name().get(), null); + System.out.println("Cancelled batch job: " + batchJob1.name().get()); + } + + // List all batch jobs. + System.out.println("List batch jobs resource names: "); + for (BatchJob b : + client.batches.list(ListBatchJobsConfig.builder().pageSize(5).build()).page()) { + System.out.println(b.name().get()); + System.out.println(b.state().get()); + } + + } + + private BatchManagement() {} +} diff --git a/examples/src/main/java/com/google/genai/examples/BatchManagementAsync.java b/examples/src/main/java/com/google/genai/examples/BatchManagementAsync.java new file mode 100644 index 00000000000..c1fcca542c5 --- /dev/null +++ b/examples/src/main/java/com/google/genai/examples/BatchManagementAsync.java @@ -0,0 +1,184 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Usage: + * + *

1a. If you are using Vertex AI, setup ADC to get credentials: + * https://cloud.google.com/docs/authentication/provide-credentials-adc#google-idp + * + *

Then set Project, Location, and USE_VERTEXAI flag as environment variables: + * + *

export GOOGLE_CLOUD_PROJECT=YOUR_PROJECT + * + *

export GOOGLE_CLOUD_LOCATION=YOUR_LOCATION + * + *

export GOOGLE_GENAI_USE_VERTEXAI=true + * + *

1b. If you are using Gemini Developer API, set an API key environment variable. You can find a + * list of available API keys here: https://aistudio.google.com/app/apikey + * + *

export GOOGLE_API_KEY=YOUR_API_KEY + * + *

2. Compile the java package and run the sample code. + * + *

mvn clean compile + * + *

mvn exec:java -Dexec.mainClass="com.google.genai.examples.BatchManagementAsync" + * -Dexec.args="YOUR_MODEL_ID" + */ +package com.google.genai.examples; + +import com.google.genai.AsyncPager; +import com.google.genai.Client; +import com.google.genai.types.BatchJob; +import com.google.genai.types.BatchJobDestination; +import com.google.genai.types.BatchJobSource; +import com.google.genai.types.Content; +import com.google.genai.types.CreateBatchJobConfig; +import com.google.genai.types.InlinedRequest; +import com.google.genai.types.ListBatchJobsConfig; +import com.google.genai.types.Part; +import java.util.concurrent.CompletableFuture; + +/** An example of using the Unified Gen AI Java SDK to do async operations on batch jobs. */ +public final class BatchManagementAsync { + + public static void main(String[] args) { + + // Instantiate the client. The client by default uses the Gemini Developer API. It gets the API + // key from the environment variable `GOOGLE_API_KEY`. Vertex AI API can be used by setting the + // environment variables `GOOGLE_CLOUD_LOCATION` and `GOOGLE_CLOUD_PROJECT`, as well as setting + // `GOOGLE_GENAI_USE_VERTEXAI` to "true". + // + // Note: Some services are only available in a specific API backend (Gemini or Vertex), you will + // get a `UnsupportedOperationException` if you try to use a service that is not available in + // the backend you are using. + Client client = new Client(); + + if (client.vertexAI()) { + String modelId = "gemini-1.5-flash-002"; + if (args.length != 0) { + modelId = args[0]; + } + System.out.println("Using Vertex AI"); + // Create a batch job. + BatchJobSource batchJobSource = + BatchJobSource.builder() + .bigqueryUri( + "bq://vertex-sdk-dev.unified_genai_tests_batches.generate_content_requests") + .format("bigquery") + .build(); + CreateBatchJobConfig config = + CreateBatchJobConfig.builder() + .displayName("test batch") + .dest( + BatchJobDestination.builder() + .bigqueryUri( + "bq://vertex-sdk-dev.unified_genai_tests_batches.generate_content_output") + .format("bigquery")) + .build(); + CompletableFuture finalFuture = + client + .async + .batches + .create(modelId, batchJobSource, config) + .thenCompose( + batchJob1 -> { + System.out.println("Created batch job: " + batchJob1.name()); + CompletableFuture batchJob2Future = + client.async.batches.get(batchJob1.name().get(), null); + + return batchJob2Future.thenCompose( + batchJob2 -> { + System.out.println("Get batch job: " + batchJob2.name()); + // Cancel the batch job. This is now nested, so it happens after get + // completes. + return client + .async + .batches + .cancel(batchJob1.name().get(), null) + .thenAccept( + cancelResponse -> { + System.out.println( + "Successfully initiated cancellation for batch job: " + + batchJob1.name()); + }); + }); + }); + finalFuture.join(); + System.out.println("All batch job operations completed."); + } else { + System.out.println("Using Gemini Developer API"); + String modelId = "gemini-2.0-flash"; + if (args.length != 0) { + modelId = args[0]; + } + // Create a batch job. + BatchJobSource batchJobSource = + BatchJobSource.builder() + .inlinedRequests( + InlinedRequest.builder() + .contents(Content.builder().parts(Part.fromText("Hello!")))) + .build(); + CreateBatchJobConfig config = + CreateBatchJobConfig.builder().displayName("test-batch-job-java").build(); + CompletableFuture finalFuture = + client + .async + .batches + .create(modelId, batchJobSource, config) + .thenCompose( + batchJob1 -> { + System.out.println("Created batch job: " + batchJob1.name()); + CompletableFuture batchJob2Future = + client.async.batches.get(batchJob1.name().get(), null); + + return batchJob2Future.thenCompose( + batchJob2 -> { + System.out.println("Get batch job: " + batchJob2.name()); + // Cancel the batch job. This is now nested, so it happens after get + // completes. + return client + .async + .batches + .cancel(batchJob1.name().get(), null) + .thenAccept( + cancelResponse -> { + System.out.println( + "Successfully initiated cancellation for batch job: " + + batchJob1.name()); + }); + }); + }); + finalFuture.join(); + System.out.println("All batch job operations completed."); + } + // List all batch jobs. + CompletableFuture> asyncPagerFuture = + client.async.batches.list(ListBatchJobsConfig.builder().pageSize(10).build()); + asyncPagerFuture + .thenCompose( + asyncPager -> { + System.out.println("List all batch job names: "); + return asyncPager.forEach( + item -> System.out.println("Batch job name: " + item.name().get())); + }) + .join(); + } + + private BatchManagementAsync() {} +} diff --git a/src/main/java/com/google/genai/ApiClient.java b/src/main/java/com/google/genai/ApiClient.java index 9693526fe33..cc8e1c26f89 100644 --- a/src/main/java/com/google/genai/ApiClient.java +++ b/src/main/java/com/google/genai/ApiClient.java @@ -21,6 +21,7 @@ import com.google.auth.oauth2.GoogleCredentials; import com.google.common.collect.ImmutableMap; +import com.google.errorprone.annotations.CanIgnoreReturnValue; import com.google.genai.errors.GenAiIOException; import com.google.genai.types.ClientOptions; import com.google.genai.types.HttpOptions; @@ -178,6 +179,7 @@ private CloseableHttpClient createHttpClient( } /** Sends a Http request given the http method, path, and request json string. */ + @CanIgnoreReturnValue public abstract ApiResponse request( String httpMethod, String path, String requestJson, Optional httpOptions); diff --git a/src/main/java/com/google/genai/AsyncBatches.java b/src/main/java/com/google/genai/AsyncBatches.java new file mode 100644 index 00000000000..84b21b6c549 --- /dev/null +++ b/src/main/java/com/google/genai/AsyncBatches.java @@ -0,0 +1,109 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Auto-generated code. Do not edit. + +package com.google.genai; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ObjectNode; +import com.google.genai.errors.GenAiIOException; +import com.google.genai.types.BatchJob; +import com.google.genai.types.BatchJobSource; +import com.google.genai.types.CancelBatchJobConfig; +import com.google.genai.types.CreateBatchJobConfig; +import com.google.genai.types.GetBatchJobConfig; +import com.google.genai.types.ListBatchJobsConfig; +import java.util.concurrent.CompletableFuture; +import java.util.function.Function; + +/** Async module of {@link Batches} */ +public final class AsyncBatches { + Batches batches; + + public AsyncBatches(ApiClient apiClient) { + this.batches = new Batches(apiClient); + } + + /** + * Asynchronously gets a batch job resource. + * + * @param name A fully-qualified BatchJob resource name or ID. Example: + * "projects/.../locations/.../batchPredictionJobs/456" or "456" when project and location are + * initialized in the Vertex AI client. Or "files/abc" using the Gemini Developer AI client. + * @param config A {@link GetBatchJobConfig} for configuring the get request. + * @return A {@link BatchJob} object that contains the info of the batch job. + */ + public CompletableFuture get(String name, GetBatchJobConfig config) { + return CompletableFuture.supplyAsync(() -> batches.get(name, config)); + } + + /** + * Asynchronously cancels a batch job resource. + * + * @param name A fully-qualified BatchJob resource name or ID. Example: + * "projects/.../locations/.../batchPredictionJobs/456" or "456" when project and location are + * initialized in the Vertex AI client. Or "files/abc" using the Gemini Developer AI client. + * @param config A {@link CancelBatchJobConfig} for configuring the cancel request. + */ + public CompletableFuture cancel(String name, CancelBatchJobConfig config) { + return CompletableFuture.runAsync(() -> batches.cancel(name, config)); + } + + /** + * Asynchronously creates a batch job. + * + * @param model the name of the GenAI model to use for batch generation. + * @param src The {@link BatchJobSource} of the batch job. + * @param config The configuration {@link CreateBatchJobConfig} for the batch job. + * @return A future that resolves to the batch job. + */ + public CompletableFuture create( + String model, BatchJobSource src, CreateBatchJobConfig config) { + return CompletableFuture.supplyAsync(() -> batches.create(model, src, config)); + } + + /** + * Asynchronously makes an API request to list the available batch jobs. + * + * @param config A {@link ListBatchJobsConfig} for configuring the list request. + * @return A CompletableFuture that resolves to a {@link AsyncPager}. The AsyncPager has a + * `forEach` method that can be used to asynchronously process items in the page and + * automatically query the next page once the current page is exhausted. + */ + @SuppressWarnings("PatternMatchingInstanceof") + public CompletableFuture> list(ListBatchJobsConfig config) { + Function> request = + requestConfig -> { + if (!(requestConfig instanceof ListBatchJobsConfig)) { + throw new GenAiIOException( + "Internal error: Pager expected ListBatchJobsConfig but received " + + requestConfig.getClass().getName()); + } + return CompletableFuture.supplyAsync( + () -> + JsonSerializable.toJsonNode( + batches.privateList((ListBatchJobsConfig) requestConfig))); + }; + return CompletableFuture.supplyAsync( + () -> + new AsyncPager<>( + Pager.PagedItem.BATCH_JOBS, + request, + (ObjectNode) JsonSerializable.toJsonNode(config), + request.apply(config))); + } +} diff --git a/src/main/java/com/google/genai/BasePager.java b/src/main/java/com/google/genai/BasePager.java index e342d0e5b34..d8e7dabe6ac 100644 --- a/src/main/java/com/google/genai/BasePager.java +++ b/src/main/java/com/google/genai/BasePager.java @@ -20,8 +20,10 @@ import com.fasterxml.jackson.databind.node.ObjectNode; import com.google.common.collect.ImmutableList; import com.google.genai.errors.GenAiIOException; +import com.google.genai.types.BatchJob; import com.google.genai.types.CachedContent; import com.google.genai.types.File; +import com.google.genai.types.ListBatchJobsConfig; import com.google.genai.types.ListCachedContentsConfig; import com.google.genai.types.ListFilesConfig; import com.google.genai.types.ListModelsConfig; @@ -36,7 +38,8 @@ abstract class BasePager { static enum PagedItem { MODELS("models", Model.class, ListModelsConfig.class), CACHED_CONTENTS("cachedContents", CachedContent.class, ListCachedContentsConfig.class), - FILES("files", File.class, ListFilesConfig.class); + FILES("files", File.class, ListFilesConfig.class), + BATCH_JOBS("batchJobs", BatchJob.class, ListBatchJobsConfig.class); private final String fieldName; private final Class itemClass; diff --git a/src/main/java/com/google/genai/Batches.java b/src/main/java/com/google/genai/Batches.java new file mode 100644 index 00000000000..80c0997c3e9 --- /dev/null +++ b/src/main/java/com/google/genai/Batches.java @@ -0,0 +1,6427 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Auto-generated code. Do not edit. + +package com.google.genai; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; +import com.google.genai.errors.GenAiIOException; +import com.google.genai.types.BatchJob; +import com.google.genai.types.BatchJobSource; +import com.google.genai.types.CancelBatchJobConfig; +import com.google.genai.types.CancelBatchJobParameters; +import com.google.genai.types.CreateBatchJobConfig; +import com.google.genai.types.CreateBatchJobParameters; +import com.google.genai.types.GetBatchJobConfig; +import com.google.genai.types.GetBatchJobParameters; +import com.google.genai.types.HttpOptions; +import com.google.genai.types.ListBatchJobsConfig; +import com.google.genai.types.ListBatchJobsParameters; +import com.google.genai.types.ListBatchJobsResponse; +import java.io.IOException; +import java.util.Optional; +import java.util.function.Function; +import org.apache.http.HttpEntity; +import org.apache.http.util.EntityUtils; + +/** + * Provides methods for managing the batch jobs. Instantiating this class is not required. After + * instantiating a {@link Client}, access methods through `client.batches.methodName(...)` directly. + */ +public final class Batches { + final ApiClient apiClient; + + public Batches(ApiClient apiClient) { + this.apiClient = apiClient; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode videoMetadataToMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"fps"}) != null) { + Common.setValueByPath( + toObject, new String[] {"fps"}, Common.getValueByPath(fromObject, new String[] {"fps"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"endOffset"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"endOffset"}, + Common.getValueByPath(fromObject, new String[] {"endOffset"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"startOffset"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"startOffset"}, + Common.getValueByPath(fromObject, new String[] {"startOffset"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode blobToMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"displayName"}))) { + throw new IllegalArgumentException("displayName parameter is not supported in Gemini API."); + } + + if (Common.getValueByPath(fromObject, new String[] {"data"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"data"}, + Common.getValueByPath(fromObject, new String[] {"data"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"mimeType"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"mimeType"}, + Common.getValueByPath(fromObject, new String[] {"mimeType"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode fileDataToMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"displayName"}))) { + throw new IllegalArgumentException("displayName parameter is not supported in Gemini API."); + } + + if (Common.getValueByPath(fromObject, new String[] {"fileUri"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"fileUri"}, + Common.getValueByPath(fromObject, new String[] {"fileUri"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"mimeType"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"mimeType"}, + Common.getValueByPath(fromObject, new String[] {"mimeType"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode partToMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"videoMetadata"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"videoMetadata"}, + videoMetadataToMldev( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"videoMetadata"})), + toObject)); + } + + if (Common.getValueByPath(fromObject, new String[] {"thought"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"thought"}, + Common.getValueByPath(fromObject, new String[] {"thought"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"inlineData"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"inlineData"}, + blobToMldev( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"inlineData"})), + toObject)); + } + + if (Common.getValueByPath(fromObject, new String[] {"fileData"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"fileData"}, + fileDataToMldev( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"fileData"})), + toObject)); + } + + if (Common.getValueByPath(fromObject, new String[] {"thoughtSignature"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"thoughtSignature"}, + Common.getValueByPath(fromObject, new String[] {"thoughtSignature"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"codeExecutionResult"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"codeExecutionResult"}, + Common.getValueByPath(fromObject, new String[] {"codeExecutionResult"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"executableCode"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"executableCode"}, + Common.getValueByPath(fromObject, new String[] {"executableCode"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"functionCall"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"functionCall"}, + Common.getValueByPath(fromObject, new String[] {"functionCall"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"functionResponse"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"functionResponse"}, + Common.getValueByPath(fromObject, new String[] {"functionResponse"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"text"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"text"}, + Common.getValueByPath(fromObject, new String[] {"text"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode contentToMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"parts"}) != null) { + ArrayNode keyArray = (ArrayNode) Common.getValueByPath(fromObject, new String[] {"parts"}); + ObjectMapper objectMapper = new ObjectMapper(); + ArrayNode result = objectMapper.createArrayNode(); + + for (JsonNode item : keyArray) { + result.add(partToMldev(JsonSerializable.toJsonNode(item), toObject)); + } + Common.setValueByPath(toObject, new String[] {"parts"}, result); + } + + if (Common.getValueByPath(fromObject, new String[] {"role"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"role"}, + Common.getValueByPath(fromObject, new String[] {"role"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode schemaToMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + + if (Common.getValueByPath(fromObject, new String[] {"anyOf"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"anyOf"}, + Common.getValueByPath(fromObject, new String[] {"anyOf"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"default"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"default"}, + Common.getValueByPath(fromObject, new String[] {"default"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"description"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"description"}, + Common.getValueByPath(fromObject, new String[] {"description"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"enum"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"enum"}, + Common.getValueByPath(fromObject, new String[] {"enum"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"example"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"example"}, + Common.getValueByPath(fromObject, new String[] {"example"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"format"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"format"}, + Common.getValueByPath(fromObject, new String[] {"format"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"items"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"items"}, + Common.getValueByPath(fromObject, new String[] {"items"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"maxItems"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"maxItems"}, + Common.getValueByPath(fromObject, new String[] {"maxItems"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"maxLength"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"maxLength"}, + Common.getValueByPath(fromObject, new String[] {"maxLength"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"maxProperties"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"maxProperties"}, + Common.getValueByPath(fromObject, new String[] {"maxProperties"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"maximum"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"maximum"}, + Common.getValueByPath(fromObject, new String[] {"maximum"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"minItems"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"minItems"}, + Common.getValueByPath(fromObject, new String[] {"minItems"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"minLength"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"minLength"}, + Common.getValueByPath(fromObject, new String[] {"minLength"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"minProperties"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"minProperties"}, + Common.getValueByPath(fromObject, new String[] {"minProperties"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"minimum"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"minimum"}, + Common.getValueByPath(fromObject, new String[] {"minimum"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"nullable"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"nullable"}, + Common.getValueByPath(fromObject, new String[] {"nullable"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"pattern"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"pattern"}, + Common.getValueByPath(fromObject, new String[] {"pattern"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"properties"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"properties"}, + Common.getValueByPath(fromObject, new String[] {"properties"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"propertyOrdering"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"propertyOrdering"}, + Common.getValueByPath(fromObject, new String[] {"propertyOrdering"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"required"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"required"}, + Common.getValueByPath(fromObject, new String[] {"required"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"title"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"title"}, + Common.getValueByPath(fromObject, new String[] {"title"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"type"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"type"}, + Common.getValueByPath(fromObject, new String[] {"type"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode modelSelectionConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (!Common.isZero( + Common.getValueByPath(fromObject, new String[] {"featureSelectionPreference"}))) { + throw new IllegalArgumentException( + "featureSelectionPreference parameter is not supported in Gemini API."); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode safetySettingToMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"method"}))) { + throw new IllegalArgumentException("method parameter is not supported in Gemini API."); + } + + if (Common.getValueByPath(fromObject, new String[] {"category"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"category"}, + Common.getValueByPath(fromObject, new String[] {"category"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"threshold"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"threshold"}, + Common.getValueByPath(fromObject, new String[] {"threshold"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode functionDeclarationToMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"behavior"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"behavior"}, + Common.getValueByPath(fromObject, new String[] {"behavior"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"description"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"description"}, + Common.getValueByPath(fromObject, new String[] {"description"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"name"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"name"}, + Common.getValueByPath(fromObject, new String[] {"name"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"parameters"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"parameters"}, + Common.getValueByPath(fromObject, new String[] {"parameters"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"parametersJsonSchema"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"parametersJsonSchema"}, + Common.getValueByPath(fromObject, new String[] {"parametersJsonSchema"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"response"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"response"}, + Common.getValueByPath(fromObject, new String[] {"response"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"responseJsonSchema"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"responseJsonSchema"}, + Common.getValueByPath(fromObject, new String[] {"responseJsonSchema"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode intervalToMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"startTime"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"startTime"}, + Common.getValueByPath(fromObject, new String[] {"startTime"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"endTime"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"endTime"}, + Common.getValueByPath(fromObject, new String[] {"endTime"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode googleSearchToMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"timeRangeFilter"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"timeRangeFilter"}, + intervalToMldev( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"timeRangeFilter"})), + toObject)); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode dynamicRetrievalConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"mode"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"mode"}, + Common.getValueByPath(fromObject, new String[] {"mode"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"dynamicThreshold"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"dynamicThreshold"}, + Common.getValueByPath(fromObject, new String[] {"dynamicThreshold"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode googleSearchRetrievalToMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"dynamicRetrievalConfig"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"dynamicRetrievalConfig"}, + dynamicRetrievalConfigToMldev( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"dynamicRetrievalConfig"})), + toObject)); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode enterpriseWebSearchToMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode apiKeyConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"apiKeyString"}))) { + throw new IllegalArgumentException("apiKeyString parameter is not supported in Gemini API."); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode authConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"apiKeyConfig"}))) { + throw new IllegalArgumentException("apiKeyConfig parameter is not supported in Gemini API."); + } + + if (Common.getValueByPath(fromObject, new String[] {"authType"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"authType"}, + Common.getValueByPath(fromObject, new String[] {"authType"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"googleServiceAccountConfig"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"googleServiceAccountConfig"}, + Common.getValueByPath(fromObject, new String[] {"googleServiceAccountConfig"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"httpBasicAuthConfig"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"httpBasicAuthConfig"}, + Common.getValueByPath(fromObject, new String[] {"httpBasicAuthConfig"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"oauthConfig"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"oauthConfig"}, + Common.getValueByPath(fromObject, new String[] {"oauthConfig"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"oidcConfig"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"oidcConfig"}, + Common.getValueByPath(fromObject, new String[] {"oidcConfig"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode googleMapsToMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"authConfig"}))) { + throw new IllegalArgumentException("authConfig parameter is not supported in Gemini API."); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode urlContextToMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode toolToMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"functionDeclarations"}) != null) { + ArrayNode keyArray = + (ArrayNode) Common.getValueByPath(fromObject, new String[] {"functionDeclarations"}); + ObjectMapper objectMapper = new ObjectMapper(); + ArrayNode result = objectMapper.createArrayNode(); + + for (JsonNode item : keyArray) { + result.add(functionDeclarationToMldev(JsonSerializable.toJsonNode(item), toObject)); + } + Common.setValueByPath(toObject, new String[] {"functionDeclarations"}, result); + } + + if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"retrieval"}))) { + throw new IllegalArgumentException("retrieval parameter is not supported in Gemini API."); + } + + if (Common.getValueByPath(fromObject, new String[] {"googleSearch"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"googleSearch"}, + googleSearchToMldev( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"googleSearch"})), + toObject)); + } + + if (Common.getValueByPath(fromObject, new String[] {"googleSearchRetrieval"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"googleSearchRetrieval"}, + googleSearchRetrievalToMldev( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"googleSearchRetrieval"})), + toObject)); + } + + if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"enterpriseWebSearch"}))) { + throw new IllegalArgumentException( + "enterpriseWebSearch parameter is not supported in Gemini API."); + } + + if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"googleMaps"}))) { + throw new IllegalArgumentException("googleMaps parameter is not supported in Gemini API."); + } + + if (Common.getValueByPath(fromObject, new String[] {"urlContext"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"urlContext"}, + urlContextToMldev( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"urlContext"})), + toObject)); + } + + if (Common.getValueByPath(fromObject, new String[] {"codeExecution"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"codeExecution"}, + Common.getValueByPath(fromObject, new String[] {"codeExecution"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode functionCallingConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"mode"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"mode"}, + Common.getValueByPath(fromObject, new String[] {"mode"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"allowedFunctionNames"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"allowedFunctionNames"}, + Common.getValueByPath(fromObject, new String[] {"allowedFunctionNames"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode latLngToMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"latitude"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"latitude"}, + Common.getValueByPath(fromObject, new String[] {"latitude"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"longitude"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"longitude"}, + Common.getValueByPath(fromObject, new String[] {"longitude"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode retrievalConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"latLng"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"latLng"}, + latLngToMldev( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"latLng"})), + toObject)); + } + + if (Common.getValueByPath(fromObject, new String[] {"languageCode"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"languageCode"}, + Common.getValueByPath(fromObject, new String[] {"languageCode"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode toolConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"functionCallingConfig"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"functionCallingConfig"}, + functionCallingConfigToMldev( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"functionCallingConfig"})), + toObject)); + } + + if (Common.getValueByPath(fromObject, new String[] {"retrievalConfig"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"retrievalConfig"}, + retrievalConfigToMldev( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"retrievalConfig"})), + toObject)); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode prebuiltVoiceConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"voiceName"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"voiceName"}, + Common.getValueByPath(fromObject, new String[] {"voiceName"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode voiceConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"prebuiltVoiceConfig"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"prebuiltVoiceConfig"}, + prebuiltVoiceConfigToMldev( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"prebuiltVoiceConfig"})), + toObject)); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode speakerVoiceConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"speaker"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"speaker"}, + Common.getValueByPath(fromObject, new String[] {"speaker"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"voiceConfig"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"voiceConfig"}, + voiceConfigToMldev( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"voiceConfig"})), + toObject)); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode multiSpeakerVoiceConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"speakerVoiceConfigs"}) != null) { + ArrayNode keyArray = + (ArrayNode) Common.getValueByPath(fromObject, new String[] {"speakerVoiceConfigs"}); + ObjectMapper objectMapper = new ObjectMapper(); + ArrayNode result = objectMapper.createArrayNode(); + + for (JsonNode item : keyArray) { + result.add(speakerVoiceConfigToMldev(JsonSerializable.toJsonNode(item), toObject)); + } + Common.setValueByPath(toObject, new String[] {"speakerVoiceConfigs"}, result); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode speechConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"voiceConfig"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"voiceConfig"}, + voiceConfigToMldev( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"voiceConfig"})), + toObject)); + } + + if (Common.getValueByPath(fromObject, new String[] {"multiSpeakerVoiceConfig"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"multiSpeakerVoiceConfig"}, + multiSpeakerVoiceConfigToMldev( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"multiSpeakerVoiceConfig"})), + toObject)); + } + + if (Common.getValueByPath(fromObject, new String[] {"languageCode"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"languageCode"}, + Common.getValueByPath(fromObject, new String[] {"languageCode"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode thinkingConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"includeThoughts"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"includeThoughts"}, + Common.getValueByPath(fromObject, new String[] {"includeThoughts"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"thinkingBudget"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"thinkingBudget"}, + Common.getValueByPath(fromObject, new String[] {"thinkingBudget"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode generateContentConfigToMldev( + ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + + if (Common.getValueByPath(fromObject, new String[] {"systemInstruction"}) != null) { + Common.setValueByPath( + parentObject, + new String[] {"systemInstruction"}, + contentToMldev( + JsonSerializable.toJsonNode( + Transformers.tContent( + Common.getValueByPath(fromObject, new String[] {"systemInstruction"}))), + toObject)); + } + + if (Common.getValueByPath(fromObject, new String[] {"temperature"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"temperature"}, + Common.getValueByPath(fromObject, new String[] {"temperature"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"topP"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"topP"}, + Common.getValueByPath(fromObject, new String[] {"topP"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"topK"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"topK"}, + Common.getValueByPath(fromObject, new String[] {"topK"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"candidateCount"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"candidateCount"}, + Common.getValueByPath(fromObject, new String[] {"candidateCount"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"maxOutputTokens"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"maxOutputTokens"}, + Common.getValueByPath(fromObject, new String[] {"maxOutputTokens"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"stopSequences"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"stopSequences"}, + Common.getValueByPath(fromObject, new String[] {"stopSequences"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"responseLogprobs"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"responseLogprobs"}, + Common.getValueByPath(fromObject, new String[] {"responseLogprobs"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"logprobs"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"logprobs"}, + Common.getValueByPath(fromObject, new String[] {"logprobs"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"presencePenalty"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"presencePenalty"}, + Common.getValueByPath(fromObject, new String[] {"presencePenalty"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"frequencyPenalty"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"frequencyPenalty"}, + Common.getValueByPath(fromObject, new String[] {"frequencyPenalty"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"seed"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"seed"}, + Common.getValueByPath(fromObject, new String[] {"seed"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"responseMimeType"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"responseMimeType"}, + Common.getValueByPath(fromObject, new String[] {"responseMimeType"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"responseSchema"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"responseSchema"}, + schemaToMldev( + JsonSerializable.toJsonNode( + Transformers.tSchema( + Common.getValueByPath(fromObject, new String[] {"responseSchema"}))), + toObject)); + } + + if (Common.getValueByPath(fromObject, new String[] {"responseJsonSchema"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"responseJsonSchema"}, + Common.getValueByPath(fromObject, new String[] {"responseJsonSchema"})); + } + + if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"routingConfig"}))) { + throw new IllegalArgumentException("routingConfig parameter is not supported in Gemini API."); + } + + if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"modelSelectionConfig"}))) { + throw new IllegalArgumentException( + "modelSelectionConfig parameter is not supported in Gemini API."); + } + + if (Common.getValueByPath(fromObject, new String[] {"safetySettings"}) != null) { + ArrayNode keyArray = + (ArrayNode) Common.getValueByPath(fromObject, new String[] {"safetySettings"}); + ObjectMapper objectMapper = new ObjectMapper(); + ArrayNode result = objectMapper.createArrayNode(); + + for (JsonNode item : keyArray) { + result.add(safetySettingToMldev(JsonSerializable.toJsonNode(item), toObject)); + } + Common.setValueByPath(parentObject, new String[] {"safetySettings"}, result); + } + + if (Common.getValueByPath(fromObject, new String[] {"tools"}) != null) { + ArrayNode keyArray = + (ArrayNode) + Transformers.tTools(Common.getValueByPath(fromObject, new String[] {"tools"})); + ObjectMapper objectMapper = new ObjectMapper(); + ArrayNode result = objectMapper.createArrayNode(); + + for (JsonNode item : keyArray) { + result.add(toolToMldev(JsonSerializable.toJsonNode(Transformers.tTool(item)), toObject)); + } + Common.setValueByPath(parentObject, new String[] {"tools"}, result); + } + + if (Common.getValueByPath(fromObject, new String[] {"toolConfig"}) != null) { + Common.setValueByPath( + parentObject, + new String[] {"toolConfig"}, + toolConfigToMldev( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"toolConfig"})), + toObject)); + } + + if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"labels"}))) { + throw new IllegalArgumentException("labels parameter is not supported in Gemini API."); + } + + if (Common.getValueByPath(fromObject, new String[] {"cachedContent"}) != null) { + Common.setValueByPath( + parentObject, + new String[] {"cachedContent"}, + Transformers.tCachedContentName( + this.apiClient, Common.getValueByPath(fromObject, new String[] {"cachedContent"}))); + } + + if (Common.getValueByPath(fromObject, new String[] {"responseModalities"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"responseModalities"}, + Common.getValueByPath(fromObject, new String[] {"responseModalities"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"mediaResolution"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"mediaResolution"}, + Common.getValueByPath(fromObject, new String[] {"mediaResolution"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"speechConfig"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"speechConfig"}, + speechConfigToMldev( + JsonSerializable.toJsonNode( + Transformers.tSpeechConfig( + Common.getValueByPath(fromObject, new String[] {"speechConfig"}))), + toObject)); + } + + if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"audioTimestamp"}))) { + throw new IllegalArgumentException( + "audioTimestamp parameter is not supported in Gemini API."); + } + + if (Common.getValueByPath(fromObject, new String[] {"thinkingConfig"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"thinkingConfig"}, + thinkingConfigToMldev( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"thinkingConfig"})), + toObject)); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode inlinedRequestToMldev( + ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"model"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"request", "model"}, + Transformers.tModel( + this.apiClient, Common.getValueByPath(fromObject, new String[] {"model"}))); + } + + if (Common.getValueByPath(fromObject, new String[] {"contents"}) != null) { + ArrayNode keyArray = + (ArrayNode) + Transformers.tContents(Common.getValueByPath(fromObject, new String[] {"contents"})); + ObjectMapper objectMapper = new ObjectMapper(); + ArrayNode result = objectMapper.createArrayNode(); + + for (JsonNode item : keyArray) { + result.add(contentToMldev(JsonSerializable.toJsonNode(item), toObject)); + } + Common.setValueByPath(toObject, new String[] {"request", "contents"}, result); + } + + if (Common.getValueByPath(fromObject, new String[] {"config"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"request", "generationConfig"}, + generateContentConfigToMldev( + apiClient, + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"config"})), + toObject)); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode batchJobSourceToMldev( + ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"format"}))) { + throw new IllegalArgumentException("format parameter is not supported in Gemini API."); + } + + if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"gcsUri"}))) { + throw new IllegalArgumentException("gcsUri parameter is not supported in Gemini API."); + } + + if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"bigqueryUri"}))) { + throw new IllegalArgumentException("bigqueryUri parameter is not supported in Gemini API."); + } + + if (Common.getValueByPath(fromObject, new String[] {"fileName"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"fileName"}, + Common.getValueByPath(fromObject, new String[] {"fileName"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"inlinedRequests"}) != null) { + ArrayNode keyArray = + (ArrayNode) Common.getValueByPath(fromObject, new String[] {"inlinedRequests"}); + ObjectMapper objectMapper = new ObjectMapper(); + ArrayNode result = objectMapper.createArrayNode(); + + for (JsonNode item : keyArray) { + result.add(inlinedRequestToMldev(apiClient, JsonSerializable.toJsonNode(item), toObject)); + } + Common.setValueByPath(toObject, new String[] {"requests", "requests"}, result); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode citationMetadataToMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"citations"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"citationSources"}, + Common.getValueByPath(fromObject, new String[] {"citations"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode urlMetadataToMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"retrievedUrl"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"retrievedUrl"}, + Common.getValueByPath(fromObject, new String[] {"retrievedUrl"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"urlRetrievalStatus"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"urlRetrievalStatus"}, + Common.getValueByPath(fromObject, new String[] {"urlRetrievalStatus"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode urlContextMetadataToMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"urlMetadata"}) != null) { + ArrayNode keyArray = + (ArrayNode) Common.getValueByPath(fromObject, new String[] {"urlMetadata"}); + ObjectMapper objectMapper = new ObjectMapper(); + ArrayNode result = objectMapper.createArrayNode(); + + for (JsonNode item : keyArray) { + result.add(urlMetadataToMldev(JsonSerializable.toJsonNode(item), toObject)); + } + Common.setValueByPath(toObject, new String[] {"urlMetadata"}, result); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode candidateToMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"content"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"content"}, + contentToMldev( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"content"})), + toObject)); + } + + if (Common.getValueByPath(fromObject, new String[] {"citationMetadata"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"citationMetadata"}, + citationMetadataToMldev( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"citationMetadata"})), + toObject)); + } + + if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"finishMessage"}))) { + throw new IllegalArgumentException("finishMessage parameter is not supported in Gemini API."); + } + + if (Common.getValueByPath(fromObject, new String[] {"tokenCount"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"tokenCount"}, + Common.getValueByPath(fromObject, new String[] {"tokenCount"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"finishReason"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"finishReason"}, + Common.getValueByPath(fromObject, new String[] {"finishReason"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"urlContextMetadata"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"urlContextMetadata"}, + urlContextMetadataToMldev( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"urlContextMetadata"})), + toObject)); + } + + if (Common.getValueByPath(fromObject, new String[] {"avgLogprobs"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"avgLogprobs"}, + Common.getValueByPath(fromObject, new String[] {"avgLogprobs"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"groundingMetadata"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"groundingMetadata"}, + Common.getValueByPath(fromObject, new String[] {"groundingMetadata"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"index"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"index"}, + Common.getValueByPath(fromObject, new String[] {"index"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"logprobsResult"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"logprobsResult"}, + Common.getValueByPath(fromObject, new String[] {"logprobsResult"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"safetyRatings"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"safetyRatings"}, + Common.getValueByPath(fromObject, new String[] {"safetyRatings"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode generateContentResponseToMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + + if (Common.getValueByPath(fromObject, new String[] {"candidates"}) != null) { + ArrayNode keyArray = + (ArrayNode) Common.getValueByPath(fromObject, new String[] {"candidates"}); + ObjectMapper objectMapper = new ObjectMapper(); + ArrayNode result = objectMapper.createArrayNode(); + + for (JsonNode item : keyArray) { + result.add(candidateToMldev(JsonSerializable.toJsonNode(item), toObject)); + } + Common.setValueByPath(toObject, new String[] {"candidates"}, result); + } + + if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"createTime"}))) { + throw new IllegalArgumentException("createTime parameter is not supported in Gemini API."); + } + + if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"responseId"}))) { + throw new IllegalArgumentException("responseId parameter is not supported in Gemini API."); + } + + if (Common.getValueByPath(fromObject, new String[] {"modelVersion"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"modelVersion"}, + Common.getValueByPath(fromObject, new String[] {"modelVersion"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"promptFeedback"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"promptFeedback"}, + Common.getValueByPath(fromObject, new String[] {"promptFeedback"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"usageMetadata"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"usageMetadata"}, + Common.getValueByPath(fromObject, new String[] {"usageMetadata"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode jobErrorToMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"details"}))) { + throw new IllegalArgumentException("details parameter is not supported in Gemini API."); + } + + if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"code"}))) { + throw new IllegalArgumentException("code parameter is not supported in Gemini API."); + } + + if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"message"}))) { + throw new IllegalArgumentException("message parameter is not supported in Gemini API."); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode inlinedResponseToMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"response"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"response"}, + generateContentResponseToMldev( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"response"})), + toObject)); + } + + if (Common.getValueByPath(fromObject, new String[] {"error"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"error"}, + jobErrorToMldev( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"error"})), + toObject)); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode batchJobDestinationToMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"format"}))) { + throw new IllegalArgumentException("format parameter is not supported in Gemini API."); + } + + if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"gcsUri"}))) { + throw new IllegalArgumentException("gcsUri parameter is not supported in Gemini API."); + } + + if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"bigqueryUri"}))) { + throw new IllegalArgumentException("bigqueryUri parameter is not supported in Gemini API."); + } + + if (Common.getValueByPath(fromObject, new String[] {"fileName"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"responsesFile"}, + Common.getValueByPath(fromObject, new String[] {"fileName"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"inlinedResponses"}) != null) { + ArrayNode keyArray = + (ArrayNode) Common.getValueByPath(fromObject, new String[] {"inlinedResponses"}); + ObjectMapper objectMapper = new ObjectMapper(); + ArrayNode result = objectMapper.createArrayNode(); + + for (JsonNode item : keyArray) { + result.add(inlinedResponseToMldev(JsonSerializable.toJsonNode(item), toObject)); + } + Common.setValueByPath( + toObject, new String[] {"inlinedResponses", "inlinedResponses"}, result); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode createBatchJobConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + + if (Common.getValueByPath(fromObject, new String[] {"displayName"}) != null) { + Common.setValueByPath( + parentObject, + new String[] {"batch", "displayName"}, + Common.getValueByPath(fromObject, new String[] {"displayName"})); + } + + if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"dest"}))) { + throw new IllegalArgumentException("dest parameter is not supported in Gemini API."); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode createBatchJobParametersToMldev( + ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"model"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"_url", "model"}, + Transformers.tModel( + this.apiClient, Common.getValueByPath(fromObject, new String[] {"model"}))); + } + + if (Common.getValueByPath(fromObject, new String[] {"src"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"batch", "inputConfig"}, + batchJobSourceToMldev( + apiClient, + JsonSerializable.toJsonNode( + Transformers.tBatchJobSource( + Common.getValueByPath(fromObject, new String[] {"src"}))), + toObject)); + } + + if (Common.getValueByPath(fromObject, new String[] {"config"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"config"}, + createBatchJobConfigToMldev( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"config"})), + toObject)); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode getBatchJobParametersToMldev( + ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"name"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"_url", "name"}, + Transformers.tBatchJobName( + this.apiClient, Common.getValueByPath(fromObject, new String[] {"name"}))); + } + + if (Common.getValueByPath(fromObject, new String[] {"config"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"config"}, + Common.getValueByPath(fromObject, new String[] {"config"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode cancelBatchJobParametersToMldev( + ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"name"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"_url", "name"}, + Transformers.tBatchJobName( + this.apiClient, Common.getValueByPath(fromObject, new String[] {"name"}))); + } + + if (Common.getValueByPath(fromObject, new String[] {"config"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"config"}, + Common.getValueByPath(fromObject, new String[] {"config"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode listBatchJobsConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + + if (Common.getValueByPath(fromObject, new String[] {"pageSize"}) != null) { + Common.setValueByPath( + parentObject, + new String[] {"_query", "pageSize"}, + Common.getValueByPath(fromObject, new String[] {"pageSize"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"pageToken"}) != null) { + Common.setValueByPath( + parentObject, + new String[] {"_query", "pageToken"}, + Common.getValueByPath(fromObject, new String[] {"pageToken"})); + } + + if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"filter"}))) { + throw new IllegalArgumentException("filter parameter is not supported in Gemini API."); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode listBatchJobsParametersToMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"config"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"config"}, + listBatchJobsConfigToMldev( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"config"})), + toObject)); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode videoMetadataToVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"fps"}) != null) { + Common.setValueByPath( + toObject, new String[] {"fps"}, Common.getValueByPath(fromObject, new String[] {"fps"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"endOffset"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"endOffset"}, + Common.getValueByPath(fromObject, new String[] {"endOffset"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"startOffset"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"startOffset"}, + Common.getValueByPath(fromObject, new String[] {"startOffset"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode blobToVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"displayName"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"displayName"}, + Common.getValueByPath(fromObject, new String[] {"displayName"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"data"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"data"}, + Common.getValueByPath(fromObject, new String[] {"data"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"mimeType"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"mimeType"}, + Common.getValueByPath(fromObject, new String[] {"mimeType"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode fileDataToVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"displayName"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"displayName"}, + Common.getValueByPath(fromObject, new String[] {"displayName"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"fileUri"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"fileUri"}, + Common.getValueByPath(fromObject, new String[] {"fileUri"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"mimeType"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"mimeType"}, + Common.getValueByPath(fromObject, new String[] {"mimeType"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode partToVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"videoMetadata"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"videoMetadata"}, + videoMetadataToVertex( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"videoMetadata"})), + toObject)); + } + + if (Common.getValueByPath(fromObject, new String[] {"thought"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"thought"}, + Common.getValueByPath(fromObject, new String[] {"thought"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"inlineData"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"inlineData"}, + blobToVertex( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"inlineData"})), + toObject)); + } + + if (Common.getValueByPath(fromObject, new String[] {"fileData"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"fileData"}, + fileDataToVertex( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"fileData"})), + toObject)); + } + + if (Common.getValueByPath(fromObject, new String[] {"thoughtSignature"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"thoughtSignature"}, + Common.getValueByPath(fromObject, new String[] {"thoughtSignature"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"codeExecutionResult"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"codeExecutionResult"}, + Common.getValueByPath(fromObject, new String[] {"codeExecutionResult"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"executableCode"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"executableCode"}, + Common.getValueByPath(fromObject, new String[] {"executableCode"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"functionCall"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"functionCall"}, + Common.getValueByPath(fromObject, new String[] {"functionCall"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"functionResponse"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"functionResponse"}, + Common.getValueByPath(fromObject, new String[] {"functionResponse"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"text"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"text"}, + Common.getValueByPath(fromObject, new String[] {"text"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode contentToVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"parts"}) != null) { + ArrayNode keyArray = (ArrayNode) Common.getValueByPath(fromObject, new String[] {"parts"}); + ObjectMapper objectMapper = new ObjectMapper(); + ArrayNode result = objectMapper.createArrayNode(); + + for (JsonNode item : keyArray) { + result.add(partToVertex(JsonSerializable.toJsonNode(item), toObject)); + } + Common.setValueByPath(toObject, new String[] {"parts"}, result); + } + + if (Common.getValueByPath(fromObject, new String[] {"role"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"role"}, + Common.getValueByPath(fromObject, new String[] {"role"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode schemaToVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + + if (Common.getValueByPath(fromObject, new String[] {"anyOf"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"anyOf"}, + Common.getValueByPath(fromObject, new String[] {"anyOf"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"default"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"default"}, + Common.getValueByPath(fromObject, new String[] {"default"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"description"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"description"}, + Common.getValueByPath(fromObject, new String[] {"description"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"enum"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"enum"}, + Common.getValueByPath(fromObject, new String[] {"enum"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"example"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"example"}, + Common.getValueByPath(fromObject, new String[] {"example"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"format"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"format"}, + Common.getValueByPath(fromObject, new String[] {"format"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"items"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"items"}, + Common.getValueByPath(fromObject, new String[] {"items"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"maxItems"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"maxItems"}, + Common.getValueByPath(fromObject, new String[] {"maxItems"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"maxLength"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"maxLength"}, + Common.getValueByPath(fromObject, new String[] {"maxLength"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"maxProperties"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"maxProperties"}, + Common.getValueByPath(fromObject, new String[] {"maxProperties"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"maximum"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"maximum"}, + Common.getValueByPath(fromObject, new String[] {"maximum"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"minItems"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"minItems"}, + Common.getValueByPath(fromObject, new String[] {"minItems"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"minLength"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"minLength"}, + Common.getValueByPath(fromObject, new String[] {"minLength"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"minProperties"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"minProperties"}, + Common.getValueByPath(fromObject, new String[] {"minProperties"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"minimum"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"minimum"}, + Common.getValueByPath(fromObject, new String[] {"minimum"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"nullable"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"nullable"}, + Common.getValueByPath(fromObject, new String[] {"nullable"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"pattern"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"pattern"}, + Common.getValueByPath(fromObject, new String[] {"pattern"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"properties"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"properties"}, + Common.getValueByPath(fromObject, new String[] {"properties"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"propertyOrdering"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"propertyOrdering"}, + Common.getValueByPath(fromObject, new String[] {"propertyOrdering"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"required"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"required"}, + Common.getValueByPath(fromObject, new String[] {"required"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"title"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"title"}, + Common.getValueByPath(fromObject, new String[] {"title"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"type"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"type"}, + Common.getValueByPath(fromObject, new String[] {"type"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode modelSelectionConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"featureSelectionPreference"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"featureSelectionPreference"}, + Common.getValueByPath(fromObject, new String[] {"featureSelectionPreference"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode safetySettingToVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"method"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"method"}, + Common.getValueByPath(fromObject, new String[] {"method"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"category"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"category"}, + Common.getValueByPath(fromObject, new String[] {"category"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"threshold"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"threshold"}, + Common.getValueByPath(fromObject, new String[] {"threshold"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode functionDeclarationToVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"behavior"}))) { + throw new IllegalArgumentException("behavior parameter is not supported in Vertex AI."); + } + + if (Common.getValueByPath(fromObject, new String[] {"description"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"description"}, + Common.getValueByPath(fromObject, new String[] {"description"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"name"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"name"}, + Common.getValueByPath(fromObject, new String[] {"name"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"parameters"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"parameters"}, + Common.getValueByPath(fromObject, new String[] {"parameters"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"parametersJsonSchema"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"parametersJsonSchema"}, + Common.getValueByPath(fromObject, new String[] {"parametersJsonSchema"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"response"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"response"}, + Common.getValueByPath(fromObject, new String[] {"response"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"responseJsonSchema"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"responseJsonSchema"}, + Common.getValueByPath(fromObject, new String[] {"responseJsonSchema"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode intervalToVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"startTime"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"startTime"}, + Common.getValueByPath(fromObject, new String[] {"startTime"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"endTime"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"endTime"}, + Common.getValueByPath(fromObject, new String[] {"endTime"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode googleSearchToVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"timeRangeFilter"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"timeRangeFilter"}, + intervalToVertex( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"timeRangeFilter"})), + toObject)); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode dynamicRetrievalConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"mode"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"mode"}, + Common.getValueByPath(fromObject, new String[] {"mode"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"dynamicThreshold"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"dynamicThreshold"}, + Common.getValueByPath(fromObject, new String[] {"dynamicThreshold"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode googleSearchRetrievalToVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"dynamicRetrievalConfig"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"dynamicRetrievalConfig"}, + dynamicRetrievalConfigToVertex( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"dynamicRetrievalConfig"})), + toObject)); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode enterpriseWebSearchToVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode apiKeyConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"apiKeyString"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"apiKeyString"}, + Common.getValueByPath(fromObject, new String[] {"apiKeyString"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode authConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"apiKeyConfig"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"apiKeyConfig"}, + apiKeyConfigToVertex( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"apiKeyConfig"})), + toObject)); + } + + if (Common.getValueByPath(fromObject, new String[] {"authType"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"authType"}, + Common.getValueByPath(fromObject, new String[] {"authType"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"googleServiceAccountConfig"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"googleServiceAccountConfig"}, + Common.getValueByPath(fromObject, new String[] {"googleServiceAccountConfig"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"httpBasicAuthConfig"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"httpBasicAuthConfig"}, + Common.getValueByPath(fromObject, new String[] {"httpBasicAuthConfig"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"oauthConfig"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"oauthConfig"}, + Common.getValueByPath(fromObject, new String[] {"oauthConfig"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"oidcConfig"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"oidcConfig"}, + Common.getValueByPath(fromObject, new String[] {"oidcConfig"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode googleMapsToVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"authConfig"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"authConfig"}, + authConfigToVertex( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"authConfig"})), + toObject)); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode urlContextToVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode toolToVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"functionDeclarations"}) != null) { + ArrayNode keyArray = + (ArrayNode) Common.getValueByPath(fromObject, new String[] {"functionDeclarations"}); + ObjectMapper objectMapper = new ObjectMapper(); + ArrayNode result = objectMapper.createArrayNode(); + + for (JsonNode item : keyArray) { + result.add(functionDeclarationToVertex(JsonSerializable.toJsonNode(item), toObject)); + } + Common.setValueByPath(toObject, new String[] {"functionDeclarations"}, result); + } + + if (Common.getValueByPath(fromObject, new String[] {"retrieval"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"retrieval"}, + Common.getValueByPath(fromObject, new String[] {"retrieval"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"googleSearch"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"googleSearch"}, + googleSearchToVertex( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"googleSearch"})), + toObject)); + } + + if (Common.getValueByPath(fromObject, new String[] {"googleSearchRetrieval"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"googleSearchRetrieval"}, + googleSearchRetrievalToVertex( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"googleSearchRetrieval"})), + toObject)); + } + + if (Common.getValueByPath(fromObject, new String[] {"enterpriseWebSearch"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"enterpriseWebSearch"}, + enterpriseWebSearchToVertex( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"enterpriseWebSearch"})), + toObject)); + } + + if (Common.getValueByPath(fromObject, new String[] {"googleMaps"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"googleMaps"}, + googleMapsToVertex( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"googleMaps"})), + toObject)); + } + + if (Common.getValueByPath(fromObject, new String[] {"urlContext"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"urlContext"}, + urlContextToVertex( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"urlContext"})), + toObject)); + } + + if (Common.getValueByPath(fromObject, new String[] {"codeExecution"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"codeExecution"}, + Common.getValueByPath(fromObject, new String[] {"codeExecution"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode functionCallingConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"mode"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"mode"}, + Common.getValueByPath(fromObject, new String[] {"mode"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"allowedFunctionNames"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"allowedFunctionNames"}, + Common.getValueByPath(fromObject, new String[] {"allowedFunctionNames"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode latLngToVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"latitude"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"latitude"}, + Common.getValueByPath(fromObject, new String[] {"latitude"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"longitude"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"longitude"}, + Common.getValueByPath(fromObject, new String[] {"longitude"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode retrievalConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"latLng"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"latLng"}, + latLngToVertex( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"latLng"})), + toObject)); + } + + if (Common.getValueByPath(fromObject, new String[] {"languageCode"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"languageCode"}, + Common.getValueByPath(fromObject, new String[] {"languageCode"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode toolConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"functionCallingConfig"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"functionCallingConfig"}, + functionCallingConfigToVertex( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"functionCallingConfig"})), + toObject)); + } + + if (Common.getValueByPath(fromObject, new String[] {"retrievalConfig"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"retrievalConfig"}, + retrievalConfigToVertex( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"retrievalConfig"})), + toObject)); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode prebuiltVoiceConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"voiceName"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"voiceName"}, + Common.getValueByPath(fromObject, new String[] {"voiceName"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode voiceConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"prebuiltVoiceConfig"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"prebuiltVoiceConfig"}, + prebuiltVoiceConfigToVertex( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"prebuiltVoiceConfig"})), + toObject)); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode speakerVoiceConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"speaker"}))) { + throw new IllegalArgumentException("speaker parameter is not supported in Vertex AI."); + } + + if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"voiceConfig"}))) { + throw new IllegalArgumentException("voiceConfig parameter is not supported in Vertex AI."); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode multiSpeakerVoiceConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"speakerVoiceConfigs"}))) { + throw new IllegalArgumentException( + "speakerVoiceConfigs parameter is not supported in Vertex AI."); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode speechConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"voiceConfig"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"voiceConfig"}, + voiceConfigToVertex( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"voiceConfig"})), + toObject)); + } + + if (!Common.isZero( + Common.getValueByPath(fromObject, new String[] {"multiSpeakerVoiceConfig"}))) { + throw new IllegalArgumentException( + "multiSpeakerVoiceConfig parameter is not supported in Vertex AI."); + } + + if (Common.getValueByPath(fromObject, new String[] {"languageCode"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"languageCode"}, + Common.getValueByPath(fromObject, new String[] {"languageCode"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode thinkingConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"includeThoughts"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"includeThoughts"}, + Common.getValueByPath(fromObject, new String[] {"includeThoughts"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"thinkingBudget"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"thinkingBudget"}, + Common.getValueByPath(fromObject, new String[] {"thinkingBudget"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode generateContentConfigToVertex( + ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + + if (Common.getValueByPath(fromObject, new String[] {"systemInstruction"}) != null) { + Common.setValueByPath( + parentObject, + new String[] {"systemInstruction"}, + contentToVertex( + JsonSerializable.toJsonNode( + Transformers.tContent( + Common.getValueByPath(fromObject, new String[] {"systemInstruction"}))), + toObject)); + } + + if (Common.getValueByPath(fromObject, new String[] {"temperature"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"temperature"}, + Common.getValueByPath(fromObject, new String[] {"temperature"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"topP"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"topP"}, + Common.getValueByPath(fromObject, new String[] {"topP"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"topK"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"topK"}, + Common.getValueByPath(fromObject, new String[] {"topK"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"candidateCount"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"candidateCount"}, + Common.getValueByPath(fromObject, new String[] {"candidateCount"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"maxOutputTokens"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"maxOutputTokens"}, + Common.getValueByPath(fromObject, new String[] {"maxOutputTokens"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"stopSequences"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"stopSequences"}, + Common.getValueByPath(fromObject, new String[] {"stopSequences"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"responseLogprobs"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"responseLogprobs"}, + Common.getValueByPath(fromObject, new String[] {"responseLogprobs"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"logprobs"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"logprobs"}, + Common.getValueByPath(fromObject, new String[] {"logprobs"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"presencePenalty"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"presencePenalty"}, + Common.getValueByPath(fromObject, new String[] {"presencePenalty"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"frequencyPenalty"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"frequencyPenalty"}, + Common.getValueByPath(fromObject, new String[] {"frequencyPenalty"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"seed"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"seed"}, + Common.getValueByPath(fromObject, new String[] {"seed"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"responseMimeType"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"responseMimeType"}, + Common.getValueByPath(fromObject, new String[] {"responseMimeType"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"responseSchema"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"responseSchema"}, + schemaToVertex( + JsonSerializable.toJsonNode( + Transformers.tSchema( + Common.getValueByPath(fromObject, new String[] {"responseSchema"}))), + toObject)); + } + + if (Common.getValueByPath(fromObject, new String[] {"responseJsonSchema"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"responseJsonSchema"}, + Common.getValueByPath(fromObject, new String[] {"responseJsonSchema"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"routingConfig"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"routingConfig"}, + Common.getValueByPath(fromObject, new String[] {"routingConfig"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"modelSelectionConfig"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"modelConfig"}, + modelSelectionConfigToVertex( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"modelSelectionConfig"})), + toObject)); + } + + if (Common.getValueByPath(fromObject, new String[] {"safetySettings"}) != null) { + ArrayNode keyArray = + (ArrayNode) Common.getValueByPath(fromObject, new String[] {"safetySettings"}); + ObjectMapper objectMapper = new ObjectMapper(); + ArrayNode result = objectMapper.createArrayNode(); + + for (JsonNode item : keyArray) { + result.add(safetySettingToVertex(JsonSerializable.toJsonNode(item), toObject)); + } + Common.setValueByPath(parentObject, new String[] {"safetySettings"}, result); + } + + if (Common.getValueByPath(fromObject, new String[] {"tools"}) != null) { + ArrayNode keyArray = + (ArrayNode) + Transformers.tTools(Common.getValueByPath(fromObject, new String[] {"tools"})); + ObjectMapper objectMapper = new ObjectMapper(); + ArrayNode result = objectMapper.createArrayNode(); + + for (JsonNode item : keyArray) { + result.add(toolToVertex(JsonSerializable.toJsonNode(Transformers.tTool(item)), toObject)); + } + Common.setValueByPath(parentObject, new String[] {"tools"}, result); + } + + if (Common.getValueByPath(fromObject, new String[] {"toolConfig"}) != null) { + Common.setValueByPath( + parentObject, + new String[] {"toolConfig"}, + toolConfigToVertex( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"toolConfig"})), + toObject)); + } + + if (Common.getValueByPath(fromObject, new String[] {"labels"}) != null) { + Common.setValueByPath( + parentObject, + new String[] {"labels"}, + Common.getValueByPath(fromObject, new String[] {"labels"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"cachedContent"}) != null) { + Common.setValueByPath( + parentObject, + new String[] {"cachedContent"}, + Transformers.tCachedContentName( + this.apiClient, Common.getValueByPath(fromObject, new String[] {"cachedContent"}))); + } + + if (Common.getValueByPath(fromObject, new String[] {"responseModalities"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"responseModalities"}, + Common.getValueByPath(fromObject, new String[] {"responseModalities"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"mediaResolution"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"mediaResolution"}, + Common.getValueByPath(fromObject, new String[] {"mediaResolution"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"speechConfig"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"speechConfig"}, + speechConfigToVertex( + JsonSerializable.toJsonNode( + Transformers.tSpeechConfig( + Common.getValueByPath(fromObject, new String[] {"speechConfig"}))), + toObject)); + } + + if (Common.getValueByPath(fromObject, new String[] {"audioTimestamp"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"audioTimestamp"}, + Common.getValueByPath(fromObject, new String[] {"audioTimestamp"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"thinkingConfig"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"thinkingConfig"}, + thinkingConfigToVertex( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"thinkingConfig"})), + toObject)); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode inlinedRequestToVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"model"}))) { + throw new IllegalArgumentException("model parameter is not supported in Vertex AI."); + } + + if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"contents"}))) { + throw new IllegalArgumentException("contents parameter is not supported in Vertex AI."); + } + + if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"config"}))) { + throw new IllegalArgumentException("config parameter is not supported in Vertex AI."); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode batchJobSourceToVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"format"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"instancesFormat"}, + Common.getValueByPath(fromObject, new String[] {"format"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"gcsUri"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"gcsSource", "uris"}, + Common.getValueByPath(fromObject, new String[] {"gcsUri"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"bigqueryUri"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"bigquerySource", "inputUri"}, + Common.getValueByPath(fromObject, new String[] {"bigqueryUri"})); + } + + if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"fileName"}))) { + throw new IllegalArgumentException("fileName parameter is not supported in Vertex AI."); + } + + if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"inlinedRequests"}))) { + throw new IllegalArgumentException( + "inlinedRequests parameter is not supported in Vertex AI."); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode citationMetadataToVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"citations"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"citations"}, + Common.getValueByPath(fromObject, new String[] {"citations"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode urlMetadataToVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"retrievedUrl"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"retrievedUrl"}, + Common.getValueByPath(fromObject, new String[] {"retrievedUrl"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"urlRetrievalStatus"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"urlRetrievalStatus"}, + Common.getValueByPath(fromObject, new String[] {"urlRetrievalStatus"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode urlContextMetadataToVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"urlMetadata"}) != null) { + ArrayNode keyArray = + (ArrayNode) Common.getValueByPath(fromObject, new String[] {"urlMetadata"}); + ObjectMapper objectMapper = new ObjectMapper(); + ArrayNode result = objectMapper.createArrayNode(); + + for (JsonNode item : keyArray) { + result.add(urlMetadataToVertex(JsonSerializable.toJsonNode(item), toObject)); + } + Common.setValueByPath(toObject, new String[] {"urlMetadata"}, result); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode candidateToVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"content"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"content"}, + contentToVertex( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"content"})), + toObject)); + } + + if (Common.getValueByPath(fromObject, new String[] {"citationMetadata"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"citationMetadata"}, + citationMetadataToVertex( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"citationMetadata"})), + toObject)); + } + + if (Common.getValueByPath(fromObject, new String[] {"finishMessage"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"finishMessage"}, + Common.getValueByPath(fromObject, new String[] {"finishMessage"})); + } + + if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"tokenCount"}))) { + throw new IllegalArgumentException("tokenCount parameter is not supported in Vertex AI."); + } + + if (Common.getValueByPath(fromObject, new String[] {"finishReason"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"finishReason"}, + Common.getValueByPath(fromObject, new String[] {"finishReason"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"urlContextMetadata"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"urlContextMetadata"}, + urlContextMetadataToVertex( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"urlContextMetadata"})), + toObject)); + } + + if (Common.getValueByPath(fromObject, new String[] {"avgLogprobs"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"avgLogprobs"}, + Common.getValueByPath(fromObject, new String[] {"avgLogprobs"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"groundingMetadata"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"groundingMetadata"}, + Common.getValueByPath(fromObject, new String[] {"groundingMetadata"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"index"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"index"}, + Common.getValueByPath(fromObject, new String[] {"index"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"logprobsResult"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"logprobsResult"}, + Common.getValueByPath(fromObject, new String[] {"logprobsResult"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"safetyRatings"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"safetyRatings"}, + Common.getValueByPath(fromObject, new String[] {"safetyRatings"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode generateContentResponseToVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + + if (Common.getValueByPath(fromObject, new String[] {"candidates"}) != null) { + ArrayNode keyArray = + (ArrayNode) Common.getValueByPath(fromObject, new String[] {"candidates"}); + ObjectMapper objectMapper = new ObjectMapper(); + ArrayNode result = objectMapper.createArrayNode(); + + for (JsonNode item : keyArray) { + result.add(candidateToVertex(JsonSerializable.toJsonNode(item), toObject)); + } + Common.setValueByPath(toObject, new String[] {"candidates"}, result); + } + + if (Common.getValueByPath(fromObject, new String[] {"createTime"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"createTime"}, + Common.getValueByPath(fromObject, new String[] {"createTime"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"responseId"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"responseId"}, + Common.getValueByPath(fromObject, new String[] {"responseId"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"modelVersion"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"modelVersion"}, + Common.getValueByPath(fromObject, new String[] {"modelVersion"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"promptFeedback"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"promptFeedback"}, + Common.getValueByPath(fromObject, new String[] {"promptFeedback"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"usageMetadata"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"usageMetadata"}, + Common.getValueByPath(fromObject, new String[] {"usageMetadata"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode jobErrorToVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"details"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"details"}, + Common.getValueByPath(fromObject, new String[] {"details"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"code"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"code"}, + Common.getValueByPath(fromObject, new String[] {"code"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"message"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"message"}, + Common.getValueByPath(fromObject, new String[] {"message"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode inlinedResponseToVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"response"}))) { + throw new IllegalArgumentException("response parameter is not supported in Vertex AI."); + } + + if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"error"}))) { + throw new IllegalArgumentException("error parameter is not supported in Vertex AI."); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode batchJobDestinationToVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"format"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"predictionsFormat"}, + Common.getValueByPath(fromObject, new String[] {"format"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"gcsUri"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"gcsDestination", "outputUriPrefix"}, + Common.getValueByPath(fromObject, new String[] {"gcsUri"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"bigqueryUri"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"bigqueryDestination", "outputUri"}, + Common.getValueByPath(fromObject, new String[] {"bigqueryUri"})); + } + + if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"fileName"}))) { + throw new IllegalArgumentException("fileName parameter is not supported in Vertex AI."); + } + + if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"inlinedResponses"}))) { + throw new IllegalArgumentException( + "inlinedResponses parameter is not supported in Vertex AI."); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode createBatchJobConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + + if (Common.getValueByPath(fromObject, new String[] {"displayName"}) != null) { + Common.setValueByPath( + parentObject, + new String[] {"displayName"}, + Common.getValueByPath(fromObject, new String[] {"displayName"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"dest"}) != null) { + Common.setValueByPath( + parentObject, + new String[] {"outputConfig"}, + batchJobDestinationToVertex( + JsonSerializable.toJsonNode( + Transformers.tBatchJobDestination( + Common.getValueByPath(fromObject, new String[] {"dest"}))), + toObject)); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode createBatchJobParametersToVertex( + ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"model"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"model"}, + Transformers.tModel( + this.apiClient, Common.getValueByPath(fromObject, new String[] {"model"}))); + } + + if (Common.getValueByPath(fromObject, new String[] {"src"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"inputConfig"}, + batchJobSourceToVertex( + JsonSerializable.toJsonNode( + Transformers.tBatchJobSource( + Common.getValueByPath(fromObject, new String[] {"src"}))), + toObject)); + } + + if (Common.getValueByPath(fromObject, new String[] {"config"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"config"}, + createBatchJobConfigToVertex( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"config"})), + toObject)); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode getBatchJobParametersToVertex( + ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"name"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"_url", "name"}, + Transformers.tBatchJobName( + this.apiClient, Common.getValueByPath(fromObject, new String[] {"name"}))); + } + + if (Common.getValueByPath(fromObject, new String[] {"config"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"config"}, + Common.getValueByPath(fromObject, new String[] {"config"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode cancelBatchJobParametersToVertex( + ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"name"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"_url", "name"}, + Transformers.tBatchJobName( + this.apiClient, Common.getValueByPath(fromObject, new String[] {"name"}))); + } + + if (Common.getValueByPath(fromObject, new String[] {"config"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"config"}, + Common.getValueByPath(fromObject, new String[] {"config"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode listBatchJobsConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + + if (Common.getValueByPath(fromObject, new String[] {"pageSize"}) != null) { + Common.setValueByPath( + parentObject, + new String[] {"_query", "pageSize"}, + Common.getValueByPath(fromObject, new String[] {"pageSize"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"pageToken"}) != null) { + Common.setValueByPath( + parentObject, + new String[] {"_query", "pageToken"}, + Common.getValueByPath(fromObject, new String[] {"pageToken"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"filter"}) != null) { + Common.setValueByPath( + parentObject, + new String[] {"_query", "filter"}, + Common.getValueByPath(fromObject, new String[] {"filter"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode listBatchJobsParametersToVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"config"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"config"}, + listBatchJobsConfigToVertex( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"config"})), + toObject)); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode jobErrorFromMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode videoMetadataFromMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"fps"}) != null) { + Common.setValueByPath( + toObject, new String[] {"fps"}, Common.getValueByPath(fromObject, new String[] {"fps"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"endOffset"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"endOffset"}, + Common.getValueByPath(fromObject, new String[] {"endOffset"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"startOffset"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"startOffset"}, + Common.getValueByPath(fromObject, new String[] {"startOffset"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode blobFromMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + + if (Common.getValueByPath(fromObject, new String[] {"data"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"data"}, + Common.getValueByPath(fromObject, new String[] {"data"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"mimeType"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"mimeType"}, + Common.getValueByPath(fromObject, new String[] {"mimeType"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode fileDataFromMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + + if (Common.getValueByPath(fromObject, new String[] {"fileUri"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"fileUri"}, + Common.getValueByPath(fromObject, new String[] {"fileUri"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"mimeType"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"mimeType"}, + Common.getValueByPath(fromObject, new String[] {"mimeType"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode partFromMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"videoMetadata"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"videoMetadata"}, + videoMetadataFromMldev( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"videoMetadata"})), + toObject)); + } + + if (Common.getValueByPath(fromObject, new String[] {"thought"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"thought"}, + Common.getValueByPath(fromObject, new String[] {"thought"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"inlineData"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"inlineData"}, + blobFromMldev( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"inlineData"})), + toObject)); + } + + if (Common.getValueByPath(fromObject, new String[] {"fileData"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"fileData"}, + fileDataFromMldev( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"fileData"})), + toObject)); + } + + if (Common.getValueByPath(fromObject, new String[] {"thoughtSignature"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"thoughtSignature"}, + Common.getValueByPath(fromObject, new String[] {"thoughtSignature"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"codeExecutionResult"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"codeExecutionResult"}, + Common.getValueByPath(fromObject, new String[] {"codeExecutionResult"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"executableCode"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"executableCode"}, + Common.getValueByPath(fromObject, new String[] {"executableCode"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"functionCall"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"functionCall"}, + Common.getValueByPath(fromObject, new String[] {"functionCall"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"functionResponse"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"functionResponse"}, + Common.getValueByPath(fromObject, new String[] {"functionResponse"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"text"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"text"}, + Common.getValueByPath(fromObject, new String[] {"text"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode contentFromMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"parts"}) != null) { + ArrayNode keyArray = (ArrayNode) Common.getValueByPath(fromObject, new String[] {"parts"}); + ObjectMapper objectMapper = new ObjectMapper(); + ArrayNode result = objectMapper.createArrayNode(); + + for (JsonNode item : keyArray) { + result.add(partFromMldev(JsonSerializable.toJsonNode(item), toObject)); + } + Common.setValueByPath(toObject, new String[] {"parts"}, result); + } + + if (Common.getValueByPath(fromObject, new String[] {"role"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"role"}, + Common.getValueByPath(fromObject, new String[] {"role"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode schemaFromMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + + if (Common.getValueByPath(fromObject, new String[] {"anyOf"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"anyOf"}, + Common.getValueByPath(fromObject, new String[] {"anyOf"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"default"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"default"}, + Common.getValueByPath(fromObject, new String[] {"default"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"description"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"description"}, + Common.getValueByPath(fromObject, new String[] {"description"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"enum"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"enum"}, + Common.getValueByPath(fromObject, new String[] {"enum"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"example"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"example"}, + Common.getValueByPath(fromObject, new String[] {"example"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"format"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"format"}, + Common.getValueByPath(fromObject, new String[] {"format"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"items"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"items"}, + Common.getValueByPath(fromObject, new String[] {"items"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"maxItems"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"maxItems"}, + Common.getValueByPath(fromObject, new String[] {"maxItems"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"maxLength"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"maxLength"}, + Common.getValueByPath(fromObject, new String[] {"maxLength"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"maxProperties"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"maxProperties"}, + Common.getValueByPath(fromObject, new String[] {"maxProperties"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"maximum"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"maximum"}, + Common.getValueByPath(fromObject, new String[] {"maximum"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"minItems"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"minItems"}, + Common.getValueByPath(fromObject, new String[] {"minItems"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"minLength"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"minLength"}, + Common.getValueByPath(fromObject, new String[] {"minLength"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"minProperties"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"minProperties"}, + Common.getValueByPath(fromObject, new String[] {"minProperties"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"minimum"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"minimum"}, + Common.getValueByPath(fromObject, new String[] {"minimum"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"nullable"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"nullable"}, + Common.getValueByPath(fromObject, new String[] {"nullable"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"pattern"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"pattern"}, + Common.getValueByPath(fromObject, new String[] {"pattern"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"properties"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"properties"}, + Common.getValueByPath(fromObject, new String[] {"properties"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"propertyOrdering"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"propertyOrdering"}, + Common.getValueByPath(fromObject, new String[] {"propertyOrdering"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"required"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"required"}, + Common.getValueByPath(fromObject, new String[] {"required"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"title"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"title"}, + Common.getValueByPath(fromObject, new String[] {"title"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"type"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"type"}, + Common.getValueByPath(fromObject, new String[] {"type"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode modelSelectionConfigFromMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode safetySettingFromMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + + if (Common.getValueByPath(fromObject, new String[] {"category"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"category"}, + Common.getValueByPath(fromObject, new String[] {"category"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"threshold"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"threshold"}, + Common.getValueByPath(fromObject, new String[] {"threshold"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode functionDeclarationFromMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"behavior"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"behavior"}, + Common.getValueByPath(fromObject, new String[] {"behavior"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"description"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"description"}, + Common.getValueByPath(fromObject, new String[] {"description"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"name"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"name"}, + Common.getValueByPath(fromObject, new String[] {"name"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"parameters"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"parameters"}, + Common.getValueByPath(fromObject, new String[] {"parameters"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"parametersJsonSchema"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"parametersJsonSchema"}, + Common.getValueByPath(fromObject, new String[] {"parametersJsonSchema"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"response"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"response"}, + Common.getValueByPath(fromObject, new String[] {"response"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"responseJsonSchema"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"responseJsonSchema"}, + Common.getValueByPath(fromObject, new String[] {"responseJsonSchema"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode intervalFromMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"startTime"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"startTime"}, + Common.getValueByPath(fromObject, new String[] {"startTime"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"endTime"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"endTime"}, + Common.getValueByPath(fromObject, new String[] {"endTime"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode googleSearchFromMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"timeRangeFilter"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"timeRangeFilter"}, + intervalFromMldev( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"timeRangeFilter"})), + toObject)); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode dynamicRetrievalConfigFromMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"mode"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"mode"}, + Common.getValueByPath(fromObject, new String[] {"mode"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"dynamicThreshold"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"dynamicThreshold"}, + Common.getValueByPath(fromObject, new String[] {"dynamicThreshold"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode googleSearchRetrievalFromMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"dynamicRetrievalConfig"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"dynamicRetrievalConfig"}, + dynamicRetrievalConfigFromMldev( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"dynamicRetrievalConfig"})), + toObject)); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode enterpriseWebSearchFromMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode apiKeyConfigFromMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode authConfigFromMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + + if (Common.getValueByPath(fromObject, new String[] {"authType"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"authType"}, + Common.getValueByPath(fromObject, new String[] {"authType"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"googleServiceAccountConfig"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"googleServiceAccountConfig"}, + Common.getValueByPath(fromObject, new String[] {"googleServiceAccountConfig"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"httpBasicAuthConfig"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"httpBasicAuthConfig"}, + Common.getValueByPath(fromObject, new String[] {"httpBasicAuthConfig"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"oauthConfig"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"oauthConfig"}, + Common.getValueByPath(fromObject, new String[] {"oauthConfig"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"oidcConfig"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"oidcConfig"}, + Common.getValueByPath(fromObject, new String[] {"oidcConfig"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode googleMapsFromMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode urlContextFromMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode toolFromMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"functionDeclarations"}) != null) { + ArrayNode keyArray = + (ArrayNode) Common.getValueByPath(fromObject, new String[] {"functionDeclarations"}); + ObjectMapper objectMapper = new ObjectMapper(); + ArrayNode result = objectMapper.createArrayNode(); + + for (JsonNode item : keyArray) { + result.add(functionDeclarationFromMldev(JsonSerializable.toJsonNode(item), toObject)); + } + Common.setValueByPath(toObject, new String[] {"functionDeclarations"}, result); + } + + if (Common.getValueByPath(fromObject, new String[] {"googleSearch"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"googleSearch"}, + googleSearchFromMldev( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"googleSearch"})), + toObject)); + } + + if (Common.getValueByPath(fromObject, new String[] {"googleSearchRetrieval"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"googleSearchRetrieval"}, + googleSearchRetrievalFromMldev( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"googleSearchRetrieval"})), + toObject)); + } + + if (Common.getValueByPath(fromObject, new String[] {"urlContext"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"urlContext"}, + urlContextFromMldev( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"urlContext"})), + toObject)); + } + + if (Common.getValueByPath(fromObject, new String[] {"codeExecution"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"codeExecution"}, + Common.getValueByPath(fromObject, new String[] {"codeExecution"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode functionCallingConfigFromMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"mode"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"mode"}, + Common.getValueByPath(fromObject, new String[] {"mode"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"allowedFunctionNames"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"allowedFunctionNames"}, + Common.getValueByPath(fromObject, new String[] {"allowedFunctionNames"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode latLngFromMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"latitude"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"latitude"}, + Common.getValueByPath(fromObject, new String[] {"latitude"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"longitude"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"longitude"}, + Common.getValueByPath(fromObject, new String[] {"longitude"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode retrievalConfigFromMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"latLng"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"latLng"}, + latLngFromMldev( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"latLng"})), + toObject)); + } + + if (Common.getValueByPath(fromObject, new String[] {"languageCode"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"languageCode"}, + Common.getValueByPath(fromObject, new String[] {"languageCode"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode toolConfigFromMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"functionCallingConfig"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"functionCallingConfig"}, + functionCallingConfigFromMldev( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"functionCallingConfig"})), + toObject)); + } + + if (Common.getValueByPath(fromObject, new String[] {"retrievalConfig"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"retrievalConfig"}, + retrievalConfigFromMldev( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"retrievalConfig"})), + toObject)); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode prebuiltVoiceConfigFromMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"voiceName"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"voiceName"}, + Common.getValueByPath(fromObject, new String[] {"voiceName"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode voiceConfigFromMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"prebuiltVoiceConfig"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"prebuiltVoiceConfig"}, + prebuiltVoiceConfigFromMldev( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"prebuiltVoiceConfig"})), + toObject)); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode speakerVoiceConfigFromMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"speaker"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"speaker"}, + Common.getValueByPath(fromObject, new String[] {"speaker"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"voiceConfig"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"voiceConfig"}, + voiceConfigFromMldev( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"voiceConfig"})), + toObject)); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode multiSpeakerVoiceConfigFromMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"speakerVoiceConfigs"}) != null) { + ArrayNode keyArray = + (ArrayNode) Common.getValueByPath(fromObject, new String[] {"speakerVoiceConfigs"}); + ObjectMapper objectMapper = new ObjectMapper(); + ArrayNode result = objectMapper.createArrayNode(); + + for (JsonNode item : keyArray) { + result.add(speakerVoiceConfigFromMldev(JsonSerializable.toJsonNode(item), toObject)); + } + Common.setValueByPath(toObject, new String[] {"speakerVoiceConfigs"}, result); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode speechConfigFromMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"voiceConfig"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"voiceConfig"}, + voiceConfigFromMldev( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"voiceConfig"})), + toObject)); + } + + if (Common.getValueByPath(fromObject, new String[] {"multiSpeakerVoiceConfig"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"multiSpeakerVoiceConfig"}, + multiSpeakerVoiceConfigFromMldev( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"multiSpeakerVoiceConfig"})), + toObject)); + } + + if (Common.getValueByPath(fromObject, new String[] {"languageCode"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"languageCode"}, + Common.getValueByPath(fromObject, new String[] {"languageCode"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode thinkingConfigFromMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"includeThoughts"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"includeThoughts"}, + Common.getValueByPath(fromObject, new String[] {"includeThoughts"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"thinkingBudget"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"thinkingBudget"}, + Common.getValueByPath(fromObject, new String[] {"thinkingBudget"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode generateContentConfigFromMldev( + ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + + if (Common.getValueByPath(parentObject, new String[] {"systemInstruction"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"systemInstruction"}, + contentFromMldev( + JsonSerializable.toJsonNode( + Transformers.tContent( + Common.getValueByPath(parentObject, new String[] {"systemInstruction"}))), + toObject)); + } + + if (Common.getValueByPath(fromObject, new String[] {"temperature"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"temperature"}, + Common.getValueByPath(fromObject, new String[] {"temperature"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"topP"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"topP"}, + Common.getValueByPath(fromObject, new String[] {"topP"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"topK"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"topK"}, + Common.getValueByPath(fromObject, new String[] {"topK"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"candidateCount"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"candidateCount"}, + Common.getValueByPath(fromObject, new String[] {"candidateCount"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"maxOutputTokens"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"maxOutputTokens"}, + Common.getValueByPath(fromObject, new String[] {"maxOutputTokens"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"stopSequences"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"stopSequences"}, + Common.getValueByPath(fromObject, new String[] {"stopSequences"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"responseLogprobs"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"responseLogprobs"}, + Common.getValueByPath(fromObject, new String[] {"responseLogprobs"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"logprobs"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"logprobs"}, + Common.getValueByPath(fromObject, new String[] {"logprobs"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"presencePenalty"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"presencePenalty"}, + Common.getValueByPath(fromObject, new String[] {"presencePenalty"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"frequencyPenalty"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"frequencyPenalty"}, + Common.getValueByPath(fromObject, new String[] {"frequencyPenalty"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"seed"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"seed"}, + Common.getValueByPath(fromObject, new String[] {"seed"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"responseMimeType"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"responseMimeType"}, + Common.getValueByPath(fromObject, new String[] {"responseMimeType"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"responseSchema"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"responseSchema"}, + schemaFromMldev( + JsonSerializable.toJsonNode( + Transformers.tSchema( + Common.getValueByPath(fromObject, new String[] {"responseSchema"}))), + toObject)); + } + + if (Common.getValueByPath(fromObject, new String[] {"responseJsonSchema"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"responseJsonSchema"}, + Common.getValueByPath(fromObject, new String[] {"responseJsonSchema"})); + } + + if (Common.getValueByPath(parentObject, new String[] {"safetySettings"}) != null) { + ArrayNode keyArray = + (ArrayNode) Common.getValueByPath(parentObject, new String[] {"safetySettings"}); + ObjectMapper objectMapper = new ObjectMapper(); + ArrayNode result = objectMapper.createArrayNode(); + + for (JsonNode item : keyArray) { + result.add(safetySettingFromMldev(JsonSerializable.toJsonNode(item), toObject)); + } + Common.setValueByPath(toObject, new String[] {"safetySettings"}, result); + } + + if (Common.getValueByPath(parentObject, new String[] {"tools"}) != null) { + ArrayNode keyArray = + (ArrayNode) + Transformers.tTools(Common.getValueByPath(parentObject, new String[] {"tools"})); + ObjectMapper objectMapper = new ObjectMapper(); + ArrayNode result = objectMapper.createArrayNode(); + + for (JsonNode item : keyArray) { + result.add(toolFromMldev(JsonSerializable.toJsonNode(Transformers.tTool(item)), toObject)); + } + Common.setValueByPath(toObject, new String[] {"tools"}, result); + } + + if (Common.getValueByPath(parentObject, new String[] {"toolConfig"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"toolConfig"}, + toolConfigFromMldev( + JsonSerializable.toJsonNode( + Common.getValueByPath(parentObject, new String[] {"toolConfig"})), + toObject)); + } + + if (Common.getValueByPath(parentObject, new String[] {"cachedContent"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"cachedContent"}, + Transformers.tCachedContentName( + this.apiClient, Common.getValueByPath(parentObject, new String[] {"cachedContent"}))); + } + + if (Common.getValueByPath(fromObject, new String[] {"responseModalities"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"responseModalities"}, + Common.getValueByPath(fromObject, new String[] {"responseModalities"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"mediaResolution"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"mediaResolution"}, + Common.getValueByPath(fromObject, new String[] {"mediaResolution"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"speechConfig"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"speechConfig"}, + speechConfigFromMldev( + JsonSerializable.toJsonNode( + Transformers.tSpeechConfig( + Common.getValueByPath(fromObject, new String[] {"speechConfig"}))), + toObject)); + } + + if (Common.getValueByPath(fromObject, new String[] {"thinkingConfig"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"thinkingConfig"}, + thinkingConfigFromMldev( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"thinkingConfig"})), + toObject)); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode inlinedRequestFromMldev( + ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"request", "model"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"model"}, + Transformers.tModel( + this.apiClient, + Common.getValueByPath(fromObject, new String[] {"request", "model"}))); + } + + if (Common.getValueByPath(fromObject, new String[] {"request", "contents"}) != null) { + ArrayNode keyArray = + (ArrayNode) + Transformers.tContents( + Common.getValueByPath(fromObject, new String[] {"request", "contents"})); + ObjectMapper objectMapper = new ObjectMapper(); + ArrayNode result = objectMapper.createArrayNode(); + + for (JsonNode item : keyArray) { + result.add(contentFromMldev(JsonSerializable.toJsonNode(item), toObject)); + } + Common.setValueByPath(toObject, new String[] {"contents"}, result); + } + + if (Common.getValueByPath(fromObject, new String[] {"request", "generationConfig"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"config"}, + generateContentConfigFromMldev( + apiClient, + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"request", "generationConfig"})), + toObject)); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode batchJobSourceFromMldev( + ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + + if (Common.getValueByPath(fromObject, new String[] {"fileName"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"fileName"}, + Common.getValueByPath(fromObject, new String[] {"fileName"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"requests", "requests"}) != null) { + ArrayNode keyArray = + (ArrayNode) Common.getValueByPath(fromObject, new String[] {"requests", "requests"}); + ObjectMapper objectMapper = new ObjectMapper(); + ArrayNode result = objectMapper.createArrayNode(); + + for (JsonNode item : keyArray) { + result.add(inlinedRequestFromMldev(apiClient, JsonSerializable.toJsonNode(item), toObject)); + } + Common.setValueByPath(toObject, new String[] {"inlinedRequests"}, result); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode citationMetadataFromMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"citationSources"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"citations"}, + Common.getValueByPath(fromObject, new String[] {"citationSources"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode urlMetadataFromMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"retrievedUrl"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"retrievedUrl"}, + Common.getValueByPath(fromObject, new String[] {"retrievedUrl"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"urlRetrievalStatus"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"urlRetrievalStatus"}, + Common.getValueByPath(fromObject, new String[] {"urlRetrievalStatus"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode urlContextMetadataFromMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"urlMetadata"}) != null) { + ArrayNode keyArray = + (ArrayNode) Common.getValueByPath(fromObject, new String[] {"urlMetadata"}); + ObjectMapper objectMapper = new ObjectMapper(); + ArrayNode result = objectMapper.createArrayNode(); + + for (JsonNode item : keyArray) { + result.add(urlMetadataFromMldev(JsonSerializable.toJsonNode(item), toObject)); + } + Common.setValueByPath(toObject, new String[] {"urlMetadata"}, result); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode candidateFromMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"content"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"content"}, + contentFromMldev( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"content"})), + toObject)); + } + + if (Common.getValueByPath(fromObject, new String[] {"citationMetadata"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"citationMetadata"}, + citationMetadataFromMldev( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"citationMetadata"})), + toObject)); + } + + if (Common.getValueByPath(fromObject, new String[] {"tokenCount"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"tokenCount"}, + Common.getValueByPath(fromObject, new String[] {"tokenCount"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"finishReason"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"finishReason"}, + Common.getValueByPath(fromObject, new String[] {"finishReason"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"urlContextMetadata"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"urlContextMetadata"}, + urlContextMetadataFromMldev( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"urlContextMetadata"})), + toObject)); + } + + if (Common.getValueByPath(fromObject, new String[] {"avgLogprobs"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"avgLogprobs"}, + Common.getValueByPath(fromObject, new String[] {"avgLogprobs"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"groundingMetadata"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"groundingMetadata"}, + Common.getValueByPath(fromObject, new String[] {"groundingMetadata"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"index"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"index"}, + Common.getValueByPath(fromObject, new String[] {"index"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"logprobsResult"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"logprobsResult"}, + Common.getValueByPath(fromObject, new String[] {"logprobsResult"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"safetyRatings"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"safetyRatings"}, + Common.getValueByPath(fromObject, new String[] {"safetyRatings"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode generateContentResponseFromMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + + if (Common.getValueByPath(fromObject, new String[] {"candidates"}) != null) { + ArrayNode keyArray = + (ArrayNode) Common.getValueByPath(fromObject, new String[] {"candidates"}); + ObjectMapper objectMapper = new ObjectMapper(); + ArrayNode result = objectMapper.createArrayNode(); + + for (JsonNode item : keyArray) { + result.add(candidateFromMldev(JsonSerializable.toJsonNode(item), toObject)); + } + Common.setValueByPath(toObject, new String[] {"candidates"}, result); + } + + if (Common.getValueByPath(fromObject, new String[] {"modelVersion"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"modelVersion"}, + Common.getValueByPath(fromObject, new String[] {"modelVersion"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"promptFeedback"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"promptFeedback"}, + Common.getValueByPath(fromObject, new String[] {"promptFeedback"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"usageMetadata"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"usageMetadata"}, + Common.getValueByPath(fromObject, new String[] {"usageMetadata"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode inlinedResponseFromMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"response"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"response"}, + generateContentResponseFromMldev( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"response"})), + toObject)); + } + + if (Common.getValueByPath(fromObject, new String[] {"error"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"error"}, + jobErrorFromMldev( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"error"})), + toObject)); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode batchJobDestinationFromMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + + if (Common.getValueByPath(fromObject, new String[] {"responsesFile"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"fileName"}, + Common.getValueByPath(fromObject, new String[] {"responsesFile"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"inlinedResponses", "inlinedResponses"}) + != null) { + ArrayNode keyArray = + (ArrayNode) + Common.getValueByPath( + fromObject, new String[] {"inlinedResponses", "inlinedResponses"}); + ObjectMapper objectMapper = new ObjectMapper(); + ArrayNode result = objectMapper.createArrayNode(); + + for (JsonNode item : keyArray) { + result.add(inlinedResponseFromMldev(JsonSerializable.toJsonNode(item), toObject)); + } + Common.setValueByPath(toObject, new String[] {"inlinedResponses"}, result); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode batchJobFromMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"name"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"name"}, + Common.getValueByPath(fromObject, new String[] {"name"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"metadata", "displayName"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"displayName"}, + Common.getValueByPath(fromObject, new String[] {"metadata", "displayName"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"metadata", "state"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"state"}, + Transformers.tJobState( + Common.getValueByPath(fromObject, new String[] {"metadata", "state"}))); + } + + if (Common.getValueByPath(fromObject, new String[] {"metadata", "createTime"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"createTime"}, + Common.getValueByPath(fromObject, new String[] {"metadata", "createTime"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"metadata", "endTime"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"endTime"}, + Common.getValueByPath(fromObject, new String[] {"metadata", "endTime"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"metadata", "updateTime"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"updateTime"}, + Common.getValueByPath(fromObject, new String[] {"metadata", "updateTime"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"metadata", "model"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"model"}, + Common.getValueByPath(fromObject, new String[] {"metadata", "model"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"metadata", "output"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"dest"}, + batchJobDestinationFromMldev( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"metadata", "output"})), + toObject)); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode listBatchJobsResponseFromMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"nextPageToken"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"nextPageToken"}, + Common.getValueByPath(fromObject, new String[] {"nextPageToken"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"operations"}) != null) { + ArrayNode keyArray = + (ArrayNode) Common.getValueByPath(fromObject, new String[] {"operations"}); + ObjectMapper objectMapper = new ObjectMapper(); + ArrayNode result = objectMapper.createArrayNode(); + + for (JsonNode item : keyArray) { + result.add(batchJobFromMldev(JsonSerializable.toJsonNode(item), toObject)); + } + Common.setValueByPath(toObject, new String[] {"batchJobs"}, result); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode jobErrorFromVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"details"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"details"}, + Common.getValueByPath(fromObject, new String[] {"details"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"code"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"code"}, + Common.getValueByPath(fromObject, new String[] {"code"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"message"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"message"}, + Common.getValueByPath(fromObject, new String[] {"message"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode videoMetadataFromVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"fps"}) != null) { + Common.setValueByPath( + toObject, new String[] {"fps"}, Common.getValueByPath(fromObject, new String[] {"fps"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"endOffset"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"endOffset"}, + Common.getValueByPath(fromObject, new String[] {"endOffset"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"startOffset"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"startOffset"}, + Common.getValueByPath(fromObject, new String[] {"startOffset"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode blobFromVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"displayName"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"displayName"}, + Common.getValueByPath(fromObject, new String[] {"displayName"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"data"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"data"}, + Common.getValueByPath(fromObject, new String[] {"data"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"mimeType"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"mimeType"}, + Common.getValueByPath(fromObject, new String[] {"mimeType"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode fileDataFromVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"displayName"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"displayName"}, + Common.getValueByPath(fromObject, new String[] {"displayName"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"fileUri"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"fileUri"}, + Common.getValueByPath(fromObject, new String[] {"fileUri"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"mimeType"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"mimeType"}, + Common.getValueByPath(fromObject, new String[] {"mimeType"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode partFromVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"videoMetadata"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"videoMetadata"}, + videoMetadataFromVertex( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"videoMetadata"})), + toObject)); + } + + if (Common.getValueByPath(fromObject, new String[] {"thought"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"thought"}, + Common.getValueByPath(fromObject, new String[] {"thought"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"inlineData"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"inlineData"}, + blobFromVertex( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"inlineData"})), + toObject)); + } + + if (Common.getValueByPath(fromObject, new String[] {"fileData"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"fileData"}, + fileDataFromVertex( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"fileData"})), + toObject)); + } + + if (Common.getValueByPath(fromObject, new String[] {"thoughtSignature"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"thoughtSignature"}, + Common.getValueByPath(fromObject, new String[] {"thoughtSignature"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"codeExecutionResult"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"codeExecutionResult"}, + Common.getValueByPath(fromObject, new String[] {"codeExecutionResult"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"executableCode"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"executableCode"}, + Common.getValueByPath(fromObject, new String[] {"executableCode"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"functionCall"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"functionCall"}, + Common.getValueByPath(fromObject, new String[] {"functionCall"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"functionResponse"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"functionResponse"}, + Common.getValueByPath(fromObject, new String[] {"functionResponse"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"text"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"text"}, + Common.getValueByPath(fromObject, new String[] {"text"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode contentFromVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"parts"}) != null) { + ArrayNode keyArray = (ArrayNode) Common.getValueByPath(fromObject, new String[] {"parts"}); + ObjectMapper objectMapper = new ObjectMapper(); + ArrayNode result = objectMapper.createArrayNode(); + + for (JsonNode item : keyArray) { + result.add(partFromVertex(JsonSerializable.toJsonNode(item), toObject)); + } + Common.setValueByPath(toObject, new String[] {"parts"}, result); + } + + if (Common.getValueByPath(fromObject, new String[] {"role"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"role"}, + Common.getValueByPath(fromObject, new String[] {"role"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode schemaFromVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + + if (Common.getValueByPath(fromObject, new String[] {"anyOf"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"anyOf"}, + Common.getValueByPath(fromObject, new String[] {"anyOf"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"default"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"default"}, + Common.getValueByPath(fromObject, new String[] {"default"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"description"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"description"}, + Common.getValueByPath(fromObject, new String[] {"description"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"enum"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"enum"}, + Common.getValueByPath(fromObject, new String[] {"enum"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"example"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"example"}, + Common.getValueByPath(fromObject, new String[] {"example"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"format"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"format"}, + Common.getValueByPath(fromObject, new String[] {"format"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"items"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"items"}, + Common.getValueByPath(fromObject, new String[] {"items"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"maxItems"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"maxItems"}, + Common.getValueByPath(fromObject, new String[] {"maxItems"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"maxLength"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"maxLength"}, + Common.getValueByPath(fromObject, new String[] {"maxLength"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"maxProperties"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"maxProperties"}, + Common.getValueByPath(fromObject, new String[] {"maxProperties"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"maximum"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"maximum"}, + Common.getValueByPath(fromObject, new String[] {"maximum"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"minItems"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"minItems"}, + Common.getValueByPath(fromObject, new String[] {"minItems"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"minLength"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"minLength"}, + Common.getValueByPath(fromObject, new String[] {"minLength"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"minProperties"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"minProperties"}, + Common.getValueByPath(fromObject, new String[] {"minProperties"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"minimum"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"minimum"}, + Common.getValueByPath(fromObject, new String[] {"minimum"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"nullable"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"nullable"}, + Common.getValueByPath(fromObject, new String[] {"nullable"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"pattern"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"pattern"}, + Common.getValueByPath(fromObject, new String[] {"pattern"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"properties"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"properties"}, + Common.getValueByPath(fromObject, new String[] {"properties"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"propertyOrdering"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"propertyOrdering"}, + Common.getValueByPath(fromObject, new String[] {"propertyOrdering"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"required"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"required"}, + Common.getValueByPath(fromObject, new String[] {"required"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"title"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"title"}, + Common.getValueByPath(fromObject, new String[] {"title"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"type"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"type"}, + Common.getValueByPath(fromObject, new String[] {"type"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode modelSelectionConfigFromVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"featureSelectionPreference"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"featureSelectionPreference"}, + Common.getValueByPath(fromObject, new String[] {"featureSelectionPreference"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode safetySettingFromVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"method"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"method"}, + Common.getValueByPath(fromObject, new String[] {"method"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"category"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"category"}, + Common.getValueByPath(fromObject, new String[] {"category"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"threshold"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"threshold"}, + Common.getValueByPath(fromObject, new String[] {"threshold"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode functionDeclarationFromVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + + if (Common.getValueByPath(fromObject, new String[] {"description"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"description"}, + Common.getValueByPath(fromObject, new String[] {"description"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"name"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"name"}, + Common.getValueByPath(fromObject, new String[] {"name"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"parameters"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"parameters"}, + Common.getValueByPath(fromObject, new String[] {"parameters"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"parametersJsonSchema"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"parametersJsonSchema"}, + Common.getValueByPath(fromObject, new String[] {"parametersJsonSchema"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"response"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"response"}, + Common.getValueByPath(fromObject, new String[] {"response"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"responseJsonSchema"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"responseJsonSchema"}, + Common.getValueByPath(fromObject, new String[] {"responseJsonSchema"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode intervalFromVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"startTime"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"startTime"}, + Common.getValueByPath(fromObject, new String[] {"startTime"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"endTime"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"endTime"}, + Common.getValueByPath(fromObject, new String[] {"endTime"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode googleSearchFromVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"timeRangeFilter"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"timeRangeFilter"}, + intervalFromVertex( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"timeRangeFilter"})), + toObject)); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode dynamicRetrievalConfigFromVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"mode"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"mode"}, + Common.getValueByPath(fromObject, new String[] {"mode"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"dynamicThreshold"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"dynamicThreshold"}, + Common.getValueByPath(fromObject, new String[] {"dynamicThreshold"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode googleSearchRetrievalFromVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"dynamicRetrievalConfig"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"dynamicRetrievalConfig"}, + dynamicRetrievalConfigFromVertex( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"dynamicRetrievalConfig"})), + toObject)); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode enterpriseWebSearchFromVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode apiKeyConfigFromVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"apiKeyString"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"apiKeyString"}, + Common.getValueByPath(fromObject, new String[] {"apiKeyString"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode authConfigFromVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"apiKeyConfig"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"apiKeyConfig"}, + apiKeyConfigFromVertex( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"apiKeyConfig"})), + toObject)); + } + + if (Common.getValueByPath(fromObject, new String[] {"authType"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"authType"}, + Common.getValueByPath(fromObject, new String[] {"authType"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"googleServiceAccountConfig"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"googleServiceAccountConfig"}, + Common.getValueByPath(fromObject, new String[] {"googleServiceAccountConfig"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"httpBasicAuthConfig"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"httpBasicAuthConfig"}, + Common.getValueByPath(fromObject, new String[] {"httpBasicAuthConfig"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"oauthConfig"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"oauthConfig"}, + Common.getValueByPath(fromObject, new String[] {"oauthConfig"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"oidcConfig"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"oidcConfig"}, + Common.getValueByPath(fromObject, new String[] {"oidcConfig"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode googleMapsFromVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"authConfig"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"authConfig"}, + authConfigFromVertex( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"authConfig"})), + toObject)); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode urlContextFromVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode toolFromVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"functionDeclarations"}) != null) { + ArrayNode keyArray = + (ArrayNode) Common.getValueByPath(fromObject, new String[] {"functionDeclarations"}); + ObjectMapper objectMapper = new ObjectMapper(); + ArrayNode result = objectMapper.createArrayNode(); + + for (JsonNode item : keyArray) { + result.add(functionDeclarationFromVertex(JsonSerializable.toJsonNode(item), toObject)); + } + Common.setValueByPath(toObject, new String[] {"functionDeclarations"}, result); + } + + if (Common.getValueByPath(fromObject, new String[] {"retrieval"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"retrieval"}, + Common.getValueByPath(fromObject, new String[] {"retrieval"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"googleSearch"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"googleSearch"}, + googleSearchFromVertex( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"googleSearch"})), + toObject)); + } + + if (Common.getValueByPath(fromObject, new String[] {"googleSearchRetrieval"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"googleSearchRetrieval"}, + googleSearchRetrievalFromVertex( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"googleSearchRetrieval"})), + toObject)); + } + + if (Common.getValueByPath(fromObject, new String[] {"enterpriseWebSearch"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"enterpriseWebSearch"}, + enterpriseWebSearchFromVertex( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"enterpriseWebSearch"})), + toObject)); + } + + if (Common.getValueByPath(fromObject, new String[] {"googleMaps"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"googleMaps"}, + googleMapsFromVertex( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"googleMaps"})), + toObject)); + } + + if (Common.getValueByPath(fromObject, new String[] {"urlContext"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"urlContext"}, + urlContextFromVertex( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"urlContext"})), + toObject)); + } + + if (Common.getValueByPath(fromObject, new String[] {"codeExecution"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"codeExecution"}, + Common.getValueByPath(fromObject, new String[] {"codeExecution"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode functionCallingConfigFromVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"mode"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"mode"}, + Common.getValueByPath(fromObject, new String[] {"mode"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"allowedFunctionNames"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"allowedFunctionNames"}, + Common.getValueByPath(fromObject, new String[] {"allowedFunctionNames"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode latLngFromVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"latitude"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"latitude"}, + Common.getValueByPath(fromObject, new String[] {"latitude"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"longitude"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"longitude"}, + Common.getValueByPath(fromObject, new String[] {"longitude"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode retrievalConfigFromVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"latLng"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"latLng"}, + latLngFromVertex( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"latLng"})), + toObject)); + } + + if (Common.getValueByPath(fromObject, new String[] {"languageCode"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"languageCode"}, + Common.getValueByPath(fromObject, new String[] {"languageCode"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode toolConfigFromVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"functionCallingConfig"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"functionCallingConfig"}, + functionCallingConfigFromVertex( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"functionCallingConfig"})), + toObject)); + } + + if (Common.getValueByPath(fromObject, new String[] {"retrievalConfig"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"retrievalConfig"}, + retrievalConfigFromVertex( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"retrievalConfig"})), + toObject)); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode prebuiltVoiceConfigFromVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"voiceName"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"voiceName"}, + Common.getValueByPath(fromObject, new String[] {"voiceName"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode voiceConfigFromVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"prebuiltVoiceConfig"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"prebuiltVoiceConfig"}, + prebuiltVoiceConfigFromVertex( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"prebuiltVoiceConfig"})), + toObject)); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode speakerVoiceConfigFromVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode multiSpeakerVoiceConfigFromVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode speechConfigFromVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"voiceConfig"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"voiceConfig"}, + voiceConfigFromVertex( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"voiceConfig"})), + toObject)); + } + + if (Common.getValueByPath(fromObject, new String[] {"languageCode"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"languageCode"}, + Common.getValueByPath(fromObject, new String[] {"languageCode"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode thinkingConfigFromVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"includeThoughts"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"includeThoughts"}, + Common.getValueByPath(fromObject, new String[] {"includeThoughts"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"thinkingBudget"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"thinkingBudget"}, + Common.getValueByPath(fromObject, new String[] {"thinkingBudget"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode generateContentConfigFromVertex( + ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + + if (Common.getValueByPath(parentObject, new String[] {"systemInstruction"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"systemInstruction"}, + contentFromVertex( + JsonSerializable.toJsonNode( + Transformers.tContent( + Common.getValueByPath(parentObject, new String[] {"systemInstruction"}))), + toObject)); + } + + if (Common.getValueByPath(fromObject, new String[] {"temperature"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"temperature"}, + Common.getValueByPath(fromObject, new String[] {"temperature"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"topP"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"topP"}, + Common.getValueByPath(fromObject, new String[] {"topP"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"topK"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"topK"}, + Common.getValueByPath(fromObject, new String[] {"topK"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"candidateCount"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"candidateCount"}, + Common.getValueByPath(fromObject, new String[] {"candidateCount"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"maxOutputTokens"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"maxOutputTokens"}, + Common.getValueByPath(fromObject, new String[] {"maxOutputTokens"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"stopSequences"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"stopSequences"}, + Common.getValueByPath(fromObject, new String[] {"stopSequences"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"responseLogprobs"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"responseLogprobs"}, + Common.getValueByPath(fromObject, new String[] {"responseLogprobs"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"logprobs"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"logprobs"}, + Common.getValueByPath(fromObject, new String[] {"logprobs"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"presencePenalty"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"presencePenalty"}, + Common.getValueByPath(fromObject, new String[] {"presencePenalty"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"frequencyPenalty"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"frequencyPenalty"}, + Common.getValueByPath(fromObject, new String[] {"frequencyPenalty"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"seed"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"seed"}, + Common.getValueByPath(fromObject, new String[] {"seed"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"responseMimeType"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"responseMimeType"}, + Common.getValueByPath(fromObject, new String[] {"responseMimeType"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"responseSchema"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"responseSchema"}, + schemaFromVertex( + JsonSerializable.toJsonNode( + Transformers.tSchema( + Common.getValueByPath(fromObject, new String[] {"responseSchema"}))), + toObject)); + } + + if (Common.getValueByPath(fromObject, new String[] {"responseJsonSchema"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"responseJsonSchema"}, + Common.getValueByPath(fromObject, new String[] {"responseJsonSchema"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"routingConfig"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"routingConfig"}, + Common.getValueByPath(fromObject, new String[] {"routingConfig"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"modelConfig"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"modelSelectionConfig"}, + modelSelectionConfigFromVertex( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"modelConfig"})), + toObject)); + } + + if (Common.getValueByPath(parentObject, new String[] {"safetySettings"}) != null) { + ArrayNode keyArray = + (ArrayNode) Common.getValueByPath(parentObject, new String[] {"safetySettings"}); + ObjectMapper objectMapper = new ObjectMapper(); + ArrayNode result = objectMapper.createArrayNode(); + + for (JsonNode item : keyArray) { + result.add(safetySettingFromVertex(JsonSerializable.toJsonNode(item), toObject)); + } + Common.setValueByPath(toObject, new String[] {"safetySettings"}, result); + } + + if (Common.getValueByPath(parentObject, new String[] {"tools"}) != null) { + ArrayNode keyArray = + (ArrayNode) + Transformers.tTools(Common.getValueByPath(parentObject, new String[] {"tools"})); + ObjectMapper objectMapper = new ObjectMapper(); + ArrayNode result = objectMapper.createArrayNode(); + + for (JsonNode item : keyArray) { + result.add(toolFromVertex(JsonSerializable.toJsonNode(Transformers.tTool(item)), toObject)); + } + Common.setValueByPath(toObject, new String[] {"tools"}, result); + } + + if (Common.getValueByPath(parentObject, new String[] {"toolConfig"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"toolConfig"}, + toolConfigFromVertex( + JsonSerializable.toJsonNode( + Common.getValueByPath(parentObject, new String[] {"toolConfig"})), + toObject)); + } + + if (Common.getValueByPath(parentObject, new String[] {"labels"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"labels"}, + Common.getValueByPath(parentObject, new String[] {"labels"})); + } + + if (Common.getValueByPath(parentObject, new String[] {"cachedContent"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"cachedContent"}, + Transformers.tCachedContentName( + this.apiClient, Common.getValueByPath(parentObject, new String[] {"cachedContent"}))); + } + + if (Common.getValueByPath(fromObject, new String[] {"responseModalities"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"responseModalities"}, + Common.getValueByPath(fromObject, new String[] {"responseModalities"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"mediaResolution"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"mediaResolution"}, + Common.getValueByPath(fromObject, new String[] {"mediaResolution"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"speechConfig"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"speechConfig"}, + speechConfigFromVertex( + JsonSerializable.toJsonNode( + Transformers.tSpeechConfig( + Common.getValueByPath(fromObject, new String[] {"speechConfig"}))), + toObject)); + } + + if (Common.getValueByPath(fromObject, new String[] {"audioTimestamp"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"audioTimestamp"}, + Common.getValueByPath(fromObject, new String[] {"audioTimestamp"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"thinkingConfig"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"thinkingConfig"}, + thinkingConfigFromVertex( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"thinkingConfig"})), + toObject)); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode inlinedRequestFromVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode batchJobSourceFromVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"instancesFormat"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"format"}, + Common.getValueByPath(fromObject, new String[] {"instancesFormat"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"gcsSource", "uris"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"gcsUri"}, + Common.getValueByPath(fromObject, new String[] {"gcsSource", "uris"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"bigquerySource", "inputUri"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"bigqueryUri"}, + Common.getValueByPath(fromObject, new String[] {"bigquerySource", "inputUri"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode citationMetadataFromVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"citations"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"citations"}, + Common.getValueByPath(fromObject, new String[] {"citations"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode urlMetadataFromVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"retrievedUrl"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"retrievedUrl"}, + Common.getValueByPath(fromObject, new String[] {"retrievedUrl"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"urlRetrievalStatus"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"urlRetrievalStatus"}, + Common.getValueByPath(fromObject, new String[] {"urlRetrievalStatus"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode urlContextMetadataFromVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"urlMetadata"}) != null) { + ArrayNode keyArray = + (ArrayNode) Common.getValueByPath(fromObject, new String[] {"urlMetadata"}); + ObjectMapper objectMapper = new ObjectMapper(); + ArrayNode result = objectMapper.createArrayNode(); + + for (JsonNode item : keyArray) { + result.add(urlMetadataFromVertex(JsonSerializable.toJsonNode(item), toObject)); + } + Common.setValueByPath(toObject, new String[] {"urlMetadata"}, result); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode candidateFromVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"content"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"content"}, + contentFromVertex( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"content"})), + toObject)); + } + + if (Common.getValueByPath(fromObject, new String[] {"citationMetadata"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"citationMetadata"}, + citationMetadataFromVertex( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"citationMetadata"})), + toObject)); + } + + if (Common.getValueByPath(fromObject, new String[] {"finishMessage"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"finishMessage"}, + Common.getValueByPath(fromObject, new String[] {"finishMessage"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"finishReason"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"finishReason"}, + Common.getValueByPath(fromObject, new String[] {"finishReason"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"urlContextMetadata"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"urlContextMetadata"}, + urlContextMetadataFromVertex( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"urlContextMetadata"})), + toObject)); + } + + if (Common.getValueByPath(fromObject, new String[] {"avgLogprobs"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"avgLogprobs"}, + Common.getValueByPath(fromObject, new String[] {"avgLogprobs"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"groundingMetadata"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"groundingMetadata"}, + Common.getValueByPath(fromObject, new String[] {"groundingMetadata"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"index"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"index"}, + Common.getValueByPath(fromObject, new String[] {"index"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"logprobsResult"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"logprobsResult"}, + Common.getValueByPath(fromObject, new String[] {"logprobsResult"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"safetyRatings"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"safetyRatings"}, + Common.getValueByPath(fromObject, new String[] {"safetyRatings"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode generateContentResponseFromVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + + if (Common.getValueByPath(fromObject, new String[] {"candidates"}) != null) { + ArrayNode keyArray = + (ArrayNode) Common.getValueByPath(fromObject, new String[] {"candidates"}); + ObjectMapper objectMapper = new ObjectMapper(); + ArrayNode result = objectMapper.createArrayNode(); + + for (JsonNode item : keyArray) { + result.add(candidateFromVertex(JsonSerializable.toJsonNode(item), toObject)); + } + Common.setValueByPath(toObject, new String[] {"candidates"}, result); + } + + if (Common.getValueByPath(fromObject, new String[] {"createTime"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"createTime"}, + Common.getValueByPath(fromObject, new String[] {"createTime"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"responseId"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"responseId"}, + Common.getValueByPath(fromObject, new String[] {"responseId"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"modelVersion"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"modelVersion"}, + Common.getValueByPath(fromObject, new String[] {"modelVersion"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"promptFeedback"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"promptFeedback"}, + Common.getValueByPath(fromObject, new String[] {"promptFeedback"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"usageMetadata"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"usageMetadata"}, + Common.getValueByPath(fromObject, new String[] {"usageMetadata"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode inlinedResponseFromVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode batchJobDestinationFromVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"predictionsFormat"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"format"}, + Common.getValueByPath(fromObject, new String[] {"predictionsFormat"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"gcsDestination", "outputUriPrefix"}) + != null) { + Common.setValueByPath( + toObject, + new String[] {"gcsUri"}, + Common.getValueByPath(fromObject, new String[] {"gcsDestination", "outputUriPrefix"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"bigqueryDestination", "outputUri"}) + != null) { + Common.setValueByPath( + toObject, + new String[] {"bigqueryUri"}, + Common.getValueByPath(fromObject, new String[] {"bigqueryDestination", "outputUri"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode batchJobFromVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"name"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"name"}, + Common.getValueByPath(fromObject, new String[] {"name"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"displayName"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"displayName"}, + Common.getValueByPath(fromObject, new String[] {"displayName"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"state"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"state"}, + Transformers.tJobState(Common.getValueByPath(fromObject, new String[] {"state"}))); + } + + if (Common.getValueByPath(fromObject, new String[] {"error"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"error"}, + jobErrorFromVertex( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"error"})), + toObject)); + } + + if (Common.getValueByPath(fromObject, new String[] {"createTime"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"createTime"}, + Common.getValueByPath(fromObject, new String[] {"createTime"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"startTime"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"startTime"}, + Common.getValueByPath(fromObject, new String[] {"startTime"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"endTime"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"endTime"}, + Common.getValueByPath(fromObject, new String[] {"endTime"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"updateTime"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"updateTime"}, + Common.getValueByPath(fromObject, new String[] {"updateTime"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"model"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"model"}, + Common.getValueByPath(fromObject, new String[] {"model"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"inputConfig"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"src"}, + batchJobSourceFromVertex( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"inputConfig"})), + toObject)); + } + + if (Common.getValueByPath(fromObject, new String[] {"outputConfig"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"dest"}, + batchJobDestinationFromVertex( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"outputConfig"})), + toObject)); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode listBatchJobsResponseFromVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"nextPageToken"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"nextPageToken"}, + Common.getValueByPath(fromObject, new String[] {"nextPageToken"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"batchPredictionJobs"}) != null) { + ArrayNode keyArray = + (ArrayNode) Common.getValueByPath(fromObject, new String[] {"batchPredictionJobs"}); + ObjectMapper objectMapper = new ObjectMapper(); + ArrayNode result = objectMapper.createArrayNode(); + + for (JsonNode item : keyArray) { + result.add(batchJobFromVertex(JsonSerializable.toJsonNode(item), toObject)); + } + Common.setValueByPath(toObject, new String[] {"batchJobs"}, result); + } + + return toObject; + } + + BatchJob privateCreate(String model, BatchJobSource src, CreateBatchJobConfig config) { + + CreateBatchJobParameters.Builder parameterBuilder = CreateBatchJobParameters.builder(); + + if (!Common.isZero(model)) { + parameterBuilder.model(model); + } + if (!Common.isZero(src)) { + parameterBuilder.src(src); + } + if (!Common.isZero(config)) { + parameterBuilder.config(config); + } + JsonNode parameterNode = JsonSerializable.toJsonNode(parameterBuilder.build()); + + ObjectNode body; + String path; + if (this.apiClient.vertexAI()) { + body = createBatchJobParametersToVertex(this.apiClient, parameterNode, null); + path = Common.formatMap("batchPredictionJobs", body.get("_url")); + } else { + body = createBatchJobParametersToMldev(this.apiClient, parameterNode, null); + if (body.get("_url") != null) { + path = Common.formatMap("{model}:batchGenerateContent", body.get("_url")); + } else { + path = "{model}:batchGenerateContent"; + } + } + body.remove("_url"); + + JsonNode queryParams = body.get("_query"); + if (queryParams != null) { + body.remove("_query"); + path = String.format("%s?%s", path, Common.urlEncode((ObjectNode) queryParams)); + } + + // TODO: Remove the hack that removes config. + body.remove("config"); + + Optional requestHttpOptions = Optional.empty(); + if (config != null) { + requestHttpOptions = config.httpOptions(); + } + + try (ApiResponse response = + this.apiClient.request( + "post", path, JsonSerializable.toJsonString(body), requestHttpOptions)) { + HttpEntity entity = response.getEntity(); + String responseString; + try { + responseString = EntityUtils.toString(entity); + } catch (IOException e) { + throw new GenAiIOException("Failed to read HTTP response.", e); + } + + JsonNode responseNode = JsonSerializable.stringToJsonNode(responseString); + if (this.apiClient.vertexAI()) { + responseNode = batchJobFromVertex(responseNode, null); + } else { + responseNode = batchJobFromMldev(responseNode, null); + } + return JsonSerializable.fromJsonNode(responseNode, BatchJob.class); + } + } + + /** + * Gets a batch job resource. + * + * @param name A fully-qualified BatchJob resource name or ID. Example: + * "projects/.../locations/.../batchPredictionJobs/456" or "456" when project and location are + * initialized in the Vertex AI client. Or "files/abc" using the Gemini Developer AI client. + * @param config A {@link GetBatchJobConfig} for configuring the get request. + * @return A {@link BatchJob} object that contains the info of the batch job. + */ + public BatchJob get(String name, GetBatchJobConfig config) { + + GetBatchJobParameters.Builder parameterBuilder = GetBatchJobParameters.builder(); + + if (!Common.isZero(name)) { + parameterBuilder.name(name); + } + if (!Common.isZero(config)) { + parameterBuilder.config(config); + } + JsonNode parameterNode = JsonSerializable.toJsonNode(parameterBuilder.build()); + + ObjectNode body; + String path; + if (this.apiClient.vertexAI()) { + body = getBatchJobParametersToVertex(this.apiClient, parameterNode, null); + path = Common.formatMap("batchPredictionJobs/{name}", body.get("_url")); + } else { + body = getBatchJobParametersToMldev(this.apiClient, parameterNode, null); + if (body.get("_url") != null) { + path = Common.formatMap("batches/{name}", body.get("_url")); + } else { + path = "batches/{name}"; + } + } + body.remove("_url"); + + JsonNode queryParams = body.get("_query"); + if (queryParams != null) { + body.remove("_query"); + path = String.format("%s?%s", path, Common.urlEncode((ObjectNode) queryParams)); + } + + // TODO: Remove the hack that removes config. + body.remove("config"); + + Optional requestHttpOptions = Optional.empty(); + if (config != null) { + requestHttpOptions = config.httpOptions(); + } + + try (ApiResponse response = + this.apiClient.request( + "get", path, JsonSerializable.toJsonString(body), requestHttpOptions)) { + HttpEntity entity = response.getEntity(); + String responseString; + try { + responseString = EntityUtils.toString(entity); + } catch (IOException e) { + throw new GenAiIOException("Failed to read HTTP response.", e); + } + + JsonNode responseNode = JsonSerializable.stringToJsonNode(responseString); + if (this.apiClient.vertexAI()) { + responseNode = batchJobFromVertex(responseNode, null); + } else { + responseNode = batchJobFromMldev(responseNode, null); + } + return JsonSerializable.fromJsonNode(responseNode, BatchJob.class); + } + } + + /** + * Cancels a batch job resource. + * + * @param name A fully-qualified BatchJob resource name or ID. Example: + * "projects/.../locations/.../batchPredictionJobs/456" or "456" when project and location are + * initialized in the Vertex AI client. Or "files/abc" using the Gemini Developer AI client. + * @param config A {@link CancelBatchJobConfig} for configuring the cancel request. + */ + public void cancel(String name, CancelBatchJobConfig config) { + + CancelBatchJobParameters.Builder parameterBuilder = CancelBatchJobParameters.builder(); + + if (!Common.isZero(name)) { + parameterBuilder.name(name); + } + if (!Common.isZero(config)) { + parameterBuilder.config(config); + } + JsonNode parameterNode = JsonSerializable.toJsonNode(parameterBuilder.build()); + + ObjectNode body; + String path; + if (this.apiClient.vertexAI()) { + body = cancelBatchJobParametersToVertex(this.apiClient, parameterNode, null); + path = Common.formatMap("batchPredictionJobs/{name}:cancel", body.get("_url")); + } else { + body = cancelBatchJobParametersToMldev(this.apiClient, parameterNode, null); + if (body.get("_url") != null) { + path = Common.formatMap("batches/{name}:cancel", body.get("_url")); + } else { + path = "batches/{name}:cancel"; + } + } + body.remove("_url"); + + JsonNode queryParams = body.get("_query"); + if (queryParams != null) { + body.remove("_query"); + path = String.format("%s?%s", path, Common.urlEncode((ObjectNode) queryParams)); + } + + // TODO: Remove the hack that removes config. + body.remove("config"); + + Optional requestHttpOptions = Optional.empty(); + if (config != null) { + requestHttpOptions = config.httpOptions(); + } + + this.apiClient.request("post", path, JsonSerializable.toJsonString(body), requestHttpOptions); + } + + ListBatchJobsResponse privateList(ListBatchJobsConfig config) { + + ListBatchJobsParameters.Builder parameterBuilder = ListBatchJobsParameters.builder(); + + if (!Common.isZero(config)) { + parameterBuilder.config(config); + } + JsonNode parameterNode = JsonSerializable.toJsonNode(parameterBuilder.build()); + + ObjectNode body; + String path; + if (this.apiClient.vertexAI()) { + body = listBatchJobsParametersToVertex(parameterNode, null); + path = Common.formatMap("batchPredictionJobs", body.get("_url")); + } else { + body = listBatchJobsParametersToMldev(parameterNode, null); + if (body.get("_url") != null) { + path = Common.formatMap("batches", body.get("_url")); + } else { + path = "batches"; + } + } + body.remove("_url"); + + JsonNode queryParams = body.get("_query"); + if (queryParams != null) { + body.remove("_query"); + path = String.format("%s?%s", path, Common.urlEncode((ObjectNode) queryParams)); + } + + // TODO: Remove the hack that removes config. + body.remove("config"); + + Optional requestHttpOptions = Optional.empty(); + if (config != null) { + requestHttpOptions = config.httpOptions(); + } + + try (ApiResponse response = + this.apiClient.request( + "get", path, JsonSerializable.toJsonString(body), requestHttpOptions)) { + HttpEntity entity = response.getEntity(); + String responseString; + try { + responseString = EntityUtils.toString(entity); + } catch (IOException e) { + throw new GenAiIOException("Failed to read HTTP response.", e); + } + + JsonNode responseNode = JsonSerializable.stringToJsonNode(responseString); + if (this.apiClient.vertexAI()) { + responseNode = listBatchJobsResponseFromVertex(responseNode, null); + } else { + responseNode = listBatchJobsResponseFromMldev(responseNode, null); + } + return JsonSerializable.fromJsonNode(responseNode, ListBatchJobsResponse.class); + } + } + + /** + * Makes an API request to create the batch job. + * + * @param model the name of the GenAI model to use for generation + * @param src The {@link BatchJobSource} of the batch job. + * @param config The configuration {@link CreateBatchJobConfig} for the batch job. + * @return A BatchJob. + */ + public BatchJob create(String model, BatchJobSource src, CreateBatchJobConfig config) { + if (this.apiClient.vertexAI()) { + if (src.gcsUri().isPresent() && src.bigqueryUri().isPresent()) { + throw new GenAiIOException("Only one of gcsUri and bigqueryUri can be set."); + } + if (!src.gcsUri().isPresent() && !src.bigqueryUri().isPresent()) { + throw new GenAiIOException("One of gcsUri and bigqueryUri must be set."); + } + } else { + if (src.fileName().isPresent() && src.inlinedRequests().isPresent()) { + throw new GenAiIOException("Only one of fileName and InlinedRequests can be set."); + } + if (!src.fileName().isPresent() && !src.inlinedRequests().isPresent()) { + throw new GenAiIOException("One of fileName and InlinedRequests must be set."); + } + } + return this.privateCreate(model, src, config); + } + + /** + * Makes an API request to list the available batch jobs. + * + * @param config A {@link ListBatchJobsConfig} for configuring the list request. + * @return A {@link Pager} object that contains the list of batch jobs. The pager is an iterable + * and automatically queries the next page once the current page is exhausted. + */ + @SuppressWarnings("PatternMatchingInstanceof") + public Pager list(ListBatchJobsConfig config) { + Function request = + requestConfig -> { + if (!(requestConfig instanceof ListBatchJobsConfig)) { + throw new GenAiIOException( + "Internal error: Pager expected ListBatchJobsConfig but received " + + requestConfig.getClass().getName()); + } + return this.privateList((ListBatchJobsConfig) requestConfig); + }; + return new Pager<>( + Pager.PagedItem.BATCH_JOBS, + request, + (ObjectNode) JsonSerializable.toJsonNode(config), + JsonSerializable.toJsonNode(privateList(config))); + } +} diff --git a/src/main/java/com/google/genai/Client.java b/src/main/java/com/google/genai/Client.java index 661a60c41ee..6ef74287961 100644 --- a/src/main/java/com/google/genai/Client.java +++ b/src/main/java/com/google/genai/Client.java @@ -56,6 +56,7 @@ static Map defaultEnvironmentVariables() { /** Async class for GenAI. */ public final class Async { public final AsyncModels models; + public final AsyncBatches batches; public final AsyncCaches caches; public final AsyncOperations operations; public final AsyncLive live; @@ -64,6 +65,7 @@ public final class Async { public Async(ApiClient apiClient) { this.models = new AsyncModels(apiClient); + this.batches = new AsyncBatches(apiClient); this.caches = new AsyncCaches(apiClient); this.operations = new AsyncOperations(apiClient); this.live = new AsyncLive(apiClient); @@ -75,6 +77,7 @@ public Async(ApiClient apiClient) { private final DebugConfig debugConfig; private final ApiClient apiClient; public final Models models; + public final Batches batches; public final Caches caches; public final Operations operations; public final Chats chats; @@ -314,6 +317,7 @@ private Client( } models = new Models(this.apiClient); + batches = new Batches(this.apiClient); caches = new Caches(apiClient); operations = new Operations(this.apiClient); chats = new Chats(this.apiClient); diff --git a/src/main/java/com/google/genai/Transformers.java b/src/main/java/com/google/genai/Transformers.java index 8a96ef82bd3..3db7e80df2d 100644 --- a/src/main/java/com/google/genai/Transformers.java +++ b/src/main/java/com/google/genai/Transformers.java @@ -30,6 +30,7 @@ import com.google.genai.types.File; import com.google.genai.types.FunctionDeclaration; import com.google.genai.types.GeneratedVideo; +import com.google.genai.types.JobState; import com.google.genai.types.Part; import com.google.genai.types.PrebuiltVoiceConfig; import com.google.genai.types.Schema; @@ -526,4 +527,91 @@ private static String getResourceName( } } } + + public static Object tBatchJobSource(Object src) { + return src; + } + + public static Object tBatchJobDestination(Object dest) { + return dest; + } + + /** + * It validates and extracts the batch job name based on the backend (Vertex AI or MLDev). + * + * @param apiClient The ApiClient instance, used to determine the backend. + * @param name The batch job name as an Object, expected to be a String. + * @return The extracted name (e.g., job ID). + * @throws IllegalArgumentException If the input name is not a String or does not match expected + * patterns. + */ + public static String tBatchJobName(ApiClient apiClient, Object name) { + String nameStr; + if (name instanceof String) { + nameStr = (String) name; + } else if (name instanceof JsonNode) { + nameStr = JsonSerializable.toJsonString((JsonNode) name); + nameStr = nameStr.replace("\"", ""); + } else { + throw new IllegalArgumentException("Unsupported batch job name type: " + name.getClass()); + } + + if (apiClient.vertexAI()) { + String fullBatchName = getResourceName(apiClient, nameStr, "batchPredictionJobs"); + if (fullBatchName != null) { + String[] parts = fullBatchName.split("/"); + String jobId = parts[parts.length - 1]; + Pattern pattern = Pattern.compile("[0-9]+"); + Matcher matcher = pattern.matcher(jobId); + if (matcher.find() && parts.length == 6) { + return jobId; + } + } + throw new IllegalArgumentException( + String.format( + "Invalid batch job name: %s. Expected format like" + + " 'projects/123/locations/us-central1/batchPredictionJobs/456' or '456'.", + nameStr)); + } else { + nameStr = nameStr.replace("\"", ""); + if (nameStr.startsWith("batches/")) { + return nameStr.split("/")[1]; + } + throw new IllegalArgumentException( + String.format("Invalid batch job name: %s. Expected format like 'batches/id'", nameStr)); + } + } + + /** + * Maps specific batch states to job states, otherwise returns the state as is. + * + * @param state The input state as an Object, expected to be a String. + * @return The mapped or original state string. + * @throws IllegalArgumentException If the input state is not a String. + */ + public static Object tJobState(Object state) { + String stateStr; + if (state instanceof String) { + stateStr = (String) state; + } else if (state instanceof JsonNode) { + stateStr = JsonSerializable.toJsonString(state); + stateStr = stateStr.replace("\"", ""); + } else { + throw new IllegalArgumentException("Unsupported job state type: " + state.getClass()); + } + switch (stateStr) { + case "BATCH_STATE_UNSPECIFIED": + return JobState.Known.JOB_STATE_UNSPECIFIED; + case "BATCH_STATE_PENDING": + return JobState.Known.JOB_STATE_PENDING; + case "BATCH_STATE_SUCCEEDED": + return JobState.Known.JOB_STATE_SUCCEEDED; + case "BATCH_STATE_FAILED": + return JobState.Known.JOB_STATE_FAILED; + case "BATCH_STATE_CANCELLED": + return JobState.Known.JOB_STATE_CANCELLED; + default: + return state; + } + } } diff --git a/src/main/java/com/google/genai/types/BatchJob.java b/src/main/java/com/google/genai/types/BatchJob.java new file mode 100644 index 00000000000..87f829a4d70 --- /dev/null +++ b/src/main/java/com/google/genai/types/BatchJob.java @@ -0,0 +1,242 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Auto-generated code. Do not edit. + +package com.google.genai.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.google.auto.value.AutoValue; +import com.google.errorprone.annotations.CanIgnoreReturnValue; +import com.google.genai.JsonSerializable; +import java.time.Instant; +import java.util.Optional; + +/** Config for batches.create return value. */ +@AutoValue +@JsonDeserialize(builder = BatchJob.Builder.class) +public abstract class BatchJob extends JsonSerializable { + /** The resource name of the BatchJob. Output only.". */ + @JsonProperty("name") + public abstract Optional name(); + + /** The display name of the BatchJob. */ + @JsonProperty("displayName") + public abstract Optional displayName(); + + /** The state of the BatchJob. */ + @JsonProperty("state") + public abstract Optional state(); + + /** + * Output only. Only populated when the job's state is JOB_STATE_FAILED or JOB_STATE_CANCELLED. + */ + @JsonProperty("error") + public abstract Optional error(); + + /** The time when the BatchJob was created. */ + @JsonProperty("createTime") + public abstract Optional createTime(); + + /** Output only. Time when the Job for the first time entered the `JOB_STATE_RUNNING` state. */ + @JsonProperty("startTime") + public abstract Optional startTime(); + + /** The time when the BatchJob was completed. */ + @JsonProperty("endTime") + public abstract Optional endTime(); + + /** The time when the BatchJob was last updated. */ + @JsonProperty("updateTime") + public abstract Optional updateTime(); + + /** The name of the model that produces the predictions via the BatchJob. */ + @JsonProperty("model") + public abstract Optional model(); + + /** Configuration for the input data. */ + @JsonProperty("src") + public abstract Optional src(); + + /** Configuration for the output data. */ + @JsonProperty("dest") + public abstract Optional dest(); + + /** Instantiates a builder for BatchJob. */ + public static Builder builder() { + return new AutoValue_BatchJob.Builder(); + } + + /** Creates a builder with the same values as this instance. */ + public abstract Builder toBuilder(); + + /** Builder for BatchJob. */ + @AutoValue.Builder + public abstract static class Builder { + /** For internal usage. Please use `BatchJob.builder()` for instantiation. */ + @JsonCreator + private static Builder create() { + return new AutoValue_BatchJob.Builder(); + } + + /** + * Setter for name. + * + *

name: The resource name of the BatchJob. Output only.". + */ + @JsonProperty("name") + public abstract Builder name(String name); + + /** + * Setter for displayName. + * + *

displayName: The display name of the BatchJob. + */ + @JsonProperty("displayName") + public abstract Builder displayName(String displayName); + + /** + * Setter for state. + * + *

state: The state of the BatchJob. + */ + @JsonProperty("state") + public abstract Builder state(JobState state); + + /** + * Setter for state given a known enum. + * + *

state: The state of the BatchJob. + */ + @CanIgnoreReturnValue + public Builder state(JobState.Known knownType) { + return state(new JobState(knownType)); + } + + /** + * Setter for state given a string. + * + *

state: The state of the BatchJob. + */ + @CanIgnoreReturnValue + public Builder state(String state) { + return state(new JobState(state)); + } + + /** + * Setter for error. + * + *

error: Output only. Only populated when the job's state is JOB_STATE_FAILED or + * JOB_STATE_CANCELLED. + */ + @JsonProperty("error") + public abstract Builder error(JobError error); + + /** + * Setter for error builder. + * + *

error: Output only. Only populated when the job's state is JOB_STATE_FAILED or + * JOB_STATE_CANCELLED. + */ + public Builder error(JobError.Builder errorBuilder) { + return error(errorBuilder.build()); + } + + /** + * Setter for createTime. + * + *

createTime: The time when the BatchJob was created. + */ + @JsonProperty("createTime") + public abstract Builder createTime(Instant createTime); + + /** + * Setter for startTime. + * + *

startTime: Output only. Time when the Job for the first time entered the + * `JOB_STATE_RUNNING` state. + */ + @JsonProperty("startTime") + public abstract Builder startTime(Instant startTime); + + /** + * Setter for endTime. + * + *

endTime: The time when the BatchJob was completed. + */ + @JsonProperty("endTime") + public abstract Builder endTime(Instant endTime); + + /** + * Setter for updateTime. + * + *

updateTime: The time when the BatchJob was last updated. + */ + @JsonProperty("updateTime") + public abstract Builder updateTime(Instant updateTime); + + /** + * Setter for model. + * + *

model: The name of the model that produces the predictions via the BatchJob. + */ + @JsonProperty("model") + public abstract Builder model(String model); + + /** + * Setter for src. + * + *

src: Configuration for the input data. + */ + @JsonProperty("src") + public abstract Builder src(BatchJobSource src); + + /** + * Setter for src builder. + * + *

src: Configuration for the input data. + */ + public Builder src(BatchJobSource.Builder srcBuilder) { + return src(srcBuilder.build()); + } + + /** + * Setter for dest. + * + *

dest: Configuration for the output data. + */ + @JsonProperty("dest") + public abstract Builder dest(BatchJobDestination dest); + + /** + * Setter for dest builder. + * + *

dest: Configuration for the output data. + */ + public Builder dest(BatchJobDestination.Builder destBuilder) { + return dest(destBuilder.build()); + } + + public abstract BatchJob build(); + } + + /** Deserializes a JSON string to a BatchJob object. */ + public static BatchJob fromJson(String jsonString) { + return JsonSerializable.fromJsonString(jsonString, BatchJob.class); + } +} diff --git a/src/main/java/com/google/genai/types/BatchJobDestination.java b/src/main/java/com/google/genai/types/BatchJobDestination.java new file mode 100644 index 00000000000..49c7f2933df --- /dev/null +++ b/src/main/java/com/google/genai/types/BatchJobDestination.java @@ -0,0 +1,155 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Auto-generated code. Do not edit. + +package com.google.genai.types; + +import static com.google.common.collect.ImmutableList.toImmutableList; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.google.auto.value.AutoValue; +import com.google.genai.JsonSerializable; +import java.util.Arrays; +import java.util.List; +import java.util.Optional; + +/** Config for `des` parameter. */ +@AutoValue +@JsonDeserialize(builder = BatchJobDestination.Builder.class) +public abstract class BatchJobDestination extends JsonSerializable { + /** Storage format of the output files. Must be one of: 'jsonl', 'bigquery'. */ + @JsonProperty("format") + public abstract Optional format(); + + /** The Google Cloud Storage URI to the output file. */ + @JsonProperty("gcsUri") + public abstract Optional gcsUri(); + + /** The BigQuery URI to the output table. */ + @JsonProperty("bigqueryUri") + public abstract Optional bigqueryUri(); + + /** + * The Gemini Developer API's file resource name of the output data (e.g. "files/12345"). The file + * will be a JSONL file with a single response per line. The responses will be + * GenerateContentResponse messages formatted as JSON. The responses will be written in the same + * order as the input requests. + */ + @JsonProperty("fileName") + public abstract Optional fileName(); + + /** + * The responses to the requests in the batch. Returned when the batch was built using inlined + * requests. The responses will be in the same order as the input requests. + */ + @JsonProperty("inlinedResponses") + public abstract Optional> inlinedResponses(); + + /** Instantiates a builder for BatchJobDestination. */ + public static Builder builder() { + return new AutoValue_BatchJobDestination.Builder(); + } + + /** Creates a builder with the same values as this instance. */ + public abstract Builder toBuilder(); + + /** Builder for BatchJobDestination. */ + @AutoValue.Builder + public abstract static class Builder { + /** For internal usage. Please use `BatchJobDestination.builder()` for instantiation. */ + @JsonCreator + private static Builder create() { + return new AutoValue_BatchJobDestination.Builder(); + } + + /** + * Setter for format. + * + *

format: Storage format of the output files. Must be one of: 'jsonl', 'bigquery'. + */ + @JsonProperty("format") + public abstract Builder format(String format); + + /** + * Setter for gcsUri. + * + *

gcsUri: The Google Cloud Storage URI to the output file. + */ + @JsonProperty("gcsUri") + public abstract Builder gcsUri(String gcsUri); + + /** + * Setter for bigqueryUri. + * + *

bigqueryUri: The BigQuery URI to the output table. + */ + @JsonProperty("bigqueryUri") + public abstract Builder bigqueryUri(String bigqueryUri); + + /** + * Setter for fileName. + * + *

fileName: The Gemini Developer API's file resource name of the output data (e.g. + * "files/12345"). The file will be a JSONL file with a single response per line. The responses + * will be GenerateContentResponse messages formatted as JSON. The responses will be written in + * the same order as the input requests. + */ + @JsonProperty("fileName") + public abstract Builder fileName(String fileName); + + /** + * Setter for inlinedResponses. + * + *

inlinedResponses: The responses to the requests in the batch. Returned when the batch was + * built using inlined requests. The responses will be in the same order as the input requests. + */ + @JsonProperty("inlinedResponses") + public abstract Builder inlinedResponses(List inlinedResponses); + + /** + * Setter for inlinedResponses. + * + *

inlinedResponses: The responses to the requests in the batch. Returned when the batch was + * built using inlined requests. The responses will be in the same order as the input requests. + */ + public Builder inlinedResponses(InlinedResponse... inlinedResponses) { + return inlinedResponses(Arrays.asList(inlinedResponses)); + } + + /** + * Setter for inlinedResponses builder. + * + *

inlinedResponses: The responses to the requests in the batch. Returned when the batch was + * built using inlined requests. The responses will be in the same order as the input requests. + */ + public Builder inlinedResponses(InlinedResponse.Builder... inlinedResponsesBuilders) { + return inlinedResponses( + Arrays.asList(inlinedResponsesBuilders).stream() + .map(InlinedResponse.Builder::build) + .collect(toImmutableList())); + } + + public abstract BatchJobDestination build(); + } + + /** Deserializes a JSON string to a BatchJobDestination object. */ + public static BatchJobDestination fromJson(String jsonString) { + return JsonSerializable.fromJsonString(jsonString, BatchJobDestination.class); + } +} diff --git a/src/main/java/com/google/genai/types/BatchJobSource.java b/src/main/java/com/google/genai/types/BatchJobSource.java new file mode 100644 index 00000000000..d56d3f69011 --- /dev/null +++ b/src/main/java/com/google/genai/types/BatchJobSource.java @@ -0,0 +1,151 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Auto-generated code. Do not edit. + +package com.google.genai.types; + +import static com.google.common.collect.ImmutableList.toImmutableList; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.google.auto.value.AutoValue; +import com.google.genai.JsonSerializable; +import java.util.Arrays; +import java.util.List; +import java.util.Optional; + +/** Config for `src` parameter. */ +@AutoValue +@JsonDeserialize(builder = BatchJobSource.Builder.class) +public abstract class BatchJobSource extends JsonSerializable { + /** Storage format of the input files. Must be one of: 'jsonl', 'bigquery'. */ + @JsonProperty("format") + public abstract Optional format(); + + /** The Google Cloud Storage URIs to input files. */ + @JsonProperty("gcsUri") + public abstract Optional> gcsUri(); + + /** The BigQuery URI to input table. */ + @JsonProperty("bigqueryUri") + public abstract Optional bigqueryUri(); + + /** The Gemini Developer API's file resource name of the input data (e.g. "files/12345"). */ + @JsonProperty("fileName") + public abstract Optional fileName(); + + /** The Gemini Developer API's inlined input data to run batch job. */ + @JsonProperty("inlinedRequests") + public abstract Optional> inlinedRequests(); + + /** Instantiates a builder for BatchJobSource. */ + public static Builder builder() { + return new AutoValue_BatchJobSource.Builder(); + } + + /** Creates a builder with the same values as this instance. */ + public abstract Builder toBuilder(); + + /** Builder for BatchJobSource. */ + @AutoValue.Builder + public abstract static class Builder { + /** For internal usage. Please use `BatchJobSource.builder()` for instantiation. */ + @JsonCreator + private static Builder create() { + return new AutoValue_BatchJobSource.Builder(); + } + + /** + * Setter for format. + * + *

format: Storage format of the input files. Must be one of: 'jsonl', 'bigquery'. + */ + @JsonProperty("format") + public abstract Builder format(String format); + + /** + * Setter for gcsUri. + * + *

gcsUri: The Google Cloud Storage URIs to input files. + */ + @JsonProperty("gcsUri") + public abstract Builder gcsUri(List gcsUri); + + /** + * Setter for gcsUri. + * + *

gcsUri: The Google Cloud Storage URIs to input files. + */ + public Builder gcsUri(String... gcsUri) { + return gcsUri(Arrays.asList(gcsUri)); + } + + /** + * Setter for bigqueryUri. + * + *

bigqueryUri: The BigQuery URI to input table. + */ + @JsonProperty("bigqueryUri") + public abstract Builder bigqueryUri(String bigqueryUri); + + /** + * Setter for fileName. + * + *

fileName: The Gemini Developer API's file resource name of the input data (e.g. + * "files/12345"). + */ + @JsonProperty("fileName") + public abstract Builder fileName(String fileName); + + /** + * Setter for inlinedRequests. + * + *

inlinedRequests: The Gemini Developer API's inlined input data to run batch job. + */ + @JsonProperty("inlinedRequests") + public abstract Builder inlinedRequests(List inlinedRequests); + + /** + * Setter for inlinedRequests. + * + *

inlinedRequests: The Gemini Developer API's inlined input data to run batch job. + */ + public Builder inlinedRequests(InlinedRequest... inlinedRequests) { + return inlinedRequests(Arrays.asList(inlinedRequests)); + } + + /** + * Setter for inlinedRequests builder. + * + *

inlinedRequests: The Gemini Developer API's inlined input data to run batch job. + */ + public Builder inlinedRequests(InlinedRequest.Builder... inlinedRequestsBuilders) { + return inlinedRequests( + Arrays.asList(inlinedRequestsBuilders).stream() + .map(InlinedRequest.Builder::build) + .collect(toImmutableList())); + } + + public abstract BatchJobSource build(); + } + + /** Deserializes a JSON string to a BatchJobSource object. */ + public static BatchJobSource fromJson(String jsonString) { + return JsonSerializable.fromJsonString(jsonString, BatchJobSource.class); + } +} diff --git a/src/main/java/com/google/genai/types/CancelBatchJobConfig.java b/src/main/java/com/google/genai/types/CancelBatchJobConfig.java new file mode 100644 index 00000000000..5a06b0cf176 --- /dev/null +++ b/src/main/java/com/google/genai/types/CancelBatchJobConfig.java @@ -0,0 +1,77 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Auto-generated code. Do not edit. + +package com.google.genai.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.google.auto.value.AutoValue; +import com.google.genai.JsonSerializable; +import java.util.Optional; + +/** Optional parameters. */ +@AutoValue +@JsonDeserialize(builder = CancelBatchJobConfig.Builder.class) +public abstract class CancelBatchJobConfig extends JsonSerializable { + /** Used to override HTTP request options. */ + @JsonProperty("httpOptions") + public abstract Optional httpOptions(); + + /** Instantiates a builder for CancelBatchJobConfig. */ + public static Builder builder() { + return new AutoValue_CancelBatchJobConfig.Builder(); + } + + /** Creates a builder with the same values as this instance. */ + public abstract Builder toBuilder(); + + /** Builder for CancelBatchJobConfig. */ + @AutoValue.Builder + public abstract static class Builder { + /** For internal usage. Please use `CancelBatchJobConfig.builder()` for instantiation. */ + @JsonCreator + private static Builder create() { + return new AutoValue_CancelBatchJobConfig.Builder(); + } + + /** + * Setter for httpOptions. + * + *

httpOptions: Used to override HTTP request options. + */ + @JsonProperty("httpOptions") + public abstract Builder httpOptions(HttpOptions httpOptions); + + /** + * Setter for httpOptions builder. + * + *

httpOptions: Used to override HTTP request options. + */ + public Builder httpOptions(HttpOptions.Builder httpOptionsBuilder) { + return httpOptions(httpOptionsBuilder.build()); + } + + public abstract CancelBatchJobConfig build(); + } + + /** Deserializes a JSON string to a CancelBatchJobConfig object. */ + public static CancelBatchJobConfig fromJson(String jsonString) { + return JsonSerializable.fromJsonString(jsonString, CancelBatchJobConfig.class); + } +} diff --git a/src/main/java/com/google/genai/types/CancelBatchJobParameters.java b/src/main/java/com/google/genai/types/CancelBatchJobParameters.java new file mode 100644 index 00000000000..83201a43cdd --- /dev/null +++ b/src/main/java/com/google/genai/types/CancelBatchJobParameters.java @@ -0,0 +1,97 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Auto-generated code. Do not edit. + +package com.google.genai.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.google.api.core.InternalApi; +import com.google.auto.value.AutoValue; +import com.google.genai.JsonSerializable; +import java.util.Optional; + +/** Config for batches.cancel parameters. */ +@AutoValue +@InternalApi +@JsonDeserialize(builder = CancelBatchJobParameters.Builder.class) +public abstract class CancelBatchJobParameters extends JsonSerializable { + /** + * A fully-qualified BatchJob resource name or ID. Example: + * "projects/.../locations/.../batchPredictionJobs/456" or "456" when project and location are + * initialized in the client. + */ + @JsonProperty("name") + public abstract Optional name(); + + /** Optional parameters for the request. */ + @JsonProperty("config") + public abstract Optional config(); + + /** Instantiates a builder for CancelBatchJobParameters. */ + public static Builder builder() { + return new AutoValue_CancelBatchJobParameters.Builder(); + } + + /** Creates a builder with the same values as this instance. */ + public abstract Builder toBuilder(); + + /** Builder for CancelBatchJobParameters. */ + @AutoValue.Builder + public abstract static class Builder { + /** For internal usage. Please use `CancelBatchJobParameters.builder()` for instantiation. */ + @JsonCreator + private static Builder create() { + return new AutoValue_CancelBatchJobParameters.Builder(); + } + + /** + * Setter for name. + * + *

name: A fully-qualified BatchJob resource name or ID. Example: + * "projects/.../locations/.../batchPredictionJobs/456" or "456" when project and location are + * initialized in the client. + */ + @JsonProperty("name") + public abstract Builder name(String name); + + /** + * Setter for config. + * + *

config: Optional parameters for the request. + */ + @JsonProperty("config") + public abstract Builder config(CancelBatchJobConfig config); + + /** + * Setter for config builder. + * + *

config: Optional parameters for the request. + */ + public Builder config(CancelBatchJobConfig.Builder configBuilder) { + return config(configBuilder.build()); + } + + public abstract CancelBatchJobParameters build(); + } + + /** Deserializes a JSON string to a CancelBatchJobParameters object. */ + public static CancelBatchJobParameters fromJson(String jsonString) { + return JsonSerializable.fromJsonString(jsonString, CancelBatchJobParameters.class); + } +} diff --git a/src/main/java/com/google/genai/types/CreateBatchJobConfig.java b/src/main/java/com/google/genai/types/CreateBatchJobConfig.java new file mode 100644 index 00000000000..505ecda5e47 --- /dev/null +++ b/src/main/java/com/google/genai/types/CreateBatchJobConfig.java @@ -0,0 +1,115 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Auto-generated code. Do not edit. + +package com.google.genai.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.google.auto.value.AutoValue; +import com.google.genai.JsonSerializable; +import java.util.Optional; + +/** Config for optional parameters. */ +@AutoValue +@JsonDeserialize(builder = CreateBatchJobConfig.Builder.class) +public abstract class CreateBatchJobConfig extends JsonSerializable { + /** Used to override HTTP request options. */ + @JsonProperty("httpOptions") + public abstract Optional httpOptions(); + + /** The user-defined name of this BatchJob. */ + @JsonProperty("displayName") + public abstract Optional displayName(); + + /** + * GCS or BigQuery URI prefix for the output predictions. Example: "gs://path/to/output/data" or + * "bq://projectId.bqDatasetId.bqTableId". + */ + @JsonProperty("dest") + public abstract Optional dest(); + + /** Instantiates a builder for CreateBatchJobConfig. */ + public static Builder builder() { + return new AutoValue_CreateBatchJobConfig.Builder(); + } + + /** Creates a builder with the same values as this instance. */ + public abstract Builder toBuilder(); + + /** Builder for CreateBatchJobConfig. */ + @AutoValue.Builder + public abstract static class Builder { + /** For internal usage. Please use `CreateBatchJobConfig.builder()` for instantiation. */ + @JsonCreator + private static Builder create() { + return new AutoValue_CreateBatchJobConfig.Builder(); + } + + /** + * Setter for httpOptions. + * + *

httpOptions: Used to override HTTP request options. + */ + @JsonProperty("httpOptions") + public abstract Builder httpOptions(HttpOptions httpOptions); + + /** + * Setter for httpOptions builder. + * + *

httpOptions: Used to override HTTP request options. + */ + public Builder httpOptions(HttpOptions.Builder httpOptionsBuilder) { + return httpOptions(httpOptionsBuilder.build()); + } + + /** + * Setter for displayName. + * + *

displayName: The user-defined name of this BatchJob. + */ + @JsonProperty("displayName") + public abstract Builder displayName(String displayName); + + /** + * Setter for dest. + * + *

dest: GCS or BigQuery URI prefix for the output predictions. Example: + * "gs://path/to/output/data" or "bq://projectId.bqDatasetId.bqTableId". + */ + @JsonProperty("dest") + public abstract Builder dest(BatchJobDestination dest); + + /** + * Setter for dest builder. + * + *

dest: GCS or BigQuery URI prefix for the output predictions. Example: + * "gs://path/to/output/data" or "bq://projectId.bqDatasetId.bqTableId". + */ + public Builder dest(BatchJobDestination.Builder destBuilder) { + return dest(destBuilder.build()); + } + + public abstract CreateBatchJobConfig build(); + } + + /** Deserializes a JSON string to a CreateBatchJobConfig object. */ + public static CreateBatchJobConfig fromJson(String jsonString) { + return JsonSerializable.fromJsonString(jsonString, CreateBatchJobConfig.class); + } +} diff --git a/src/main/java/com/google/genai/types/CreateBatchJobParameters.java b/src/main/java/com/google/genai/types/CreateBatchJobParameters.java new file mode 100644 index 00000000000..e5348a0a460 --- /dev/null +++ b/src/main/java/com/google/genai/types/CreateBatchJobParameters.java @@ -0,0 +1,117 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Auto-generated code. Do not edit. + +package com.google.genai.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.google.api.core.InternalApi; +import com.google.auto.value.AutoValue; +import com.google.genai.JsonSerializable; +import java.util.Optional; + +/** Config for batches.create parameters. */ +@AutoValue +@InternalApi +@JsonDeserialize(builder = CreateBatchJobParameters.Builder.class) +public abstract class CreateBatchJobParameters extends JsonSerializable { + /** The name of the model to produces the predictions via the BatchJob. */ + @JsonProperty("model") + public abstract Optional model(); + + /** + * GCS URI(-s) or BigQuery URI to your input data to run batch job. Example: + * "gs://path/to/input/data" or "bq://projectId.bqDatasetId.bqTableId". + */ + @JsonProperty("src") + public abstract Optional src(); + + /** Optional parameters for creating a BatchJob. */ + @JsonProperty("config") + public abstract Optional config(); + + /** Instantiates a builder for CreateBatchJobParameters. */ + public static Builder builder() { + return new AutoValue_CreateBatchJobParameters.Builder(); + } + + /** Creates a builder with the same values as this instance. */ + public abstract Builder toBuilder(); + + /** Builder for CreateBatchJobParameters. */ + @AutoValue.Builder + public abstract static class Builder { + /** For internal usage. Please use `CreateBatchJobParameters.builder()` for instantiation. */ + @JsonCreator + private static Builder create() { + return new AutoValue_CreateBatchJobParameters.Builder(); + } + + /** + * Setter for model. + * + *

model: The name of the model to produces the predictions via the BatchJob. + */ + @JsonProperty("model") + public abstract Builder model(String model); + + /** + * Setter for src. + * + *

src: GCS URI(-s) or BigQuery URI to your input data to run batch job. Example: + * "gs://path/to/input/data" or "bq://projectId.bqDatasetId.bqTableId". + */ + @JsonProperty("src") + public abstract Builder src(BatchJobSource src); + + /** + * Setter for src builder. + * + *

src: GCS URI(-s) or BigQuery URI to your input data to run batch job. Example: + * "gs://path/to/input/data" or "bq://projectId.bqDatasetId.bqTableId". + */ + public Builder src(BatchJobSource.Builder srcBuilder) { + return src(srcBuilder.build()); + } + + /** + * Setter for config. + * + *

config: Optional parameters for creating a BatchJob. + */ + @JsonProperty("config") + public abstract Builder config(CreateBatchJobConfig config); + + /** + * Setter for config builder. + * + *

config: Optional parameters for creating a BatchJob. + */ + public Builder config(CreateBatchJobConfig.Builder configBuilder) { + return config(configBuilder.build()); + } + + public abstract CreateBatchJobParameters build(); + } + + /** Deserializes a JSON string to a CreateBatchJobParameters object. */ + public static CreateBatchJobParameters fromJson(String jsonString) { + return JsonSerializable.fromJsonString(jsonString, CreateBatchJobParameters.class); + } +} diff --git a/src/main/java/com/google/genai/types/GetBatchJobConfig.java b/src/main/java/com/google/genai/types/GetBatchJobConfig.java new file mode 100644 index 00000000000..22245c5b2b3 --- /dev/null +++ b/src/main/java/com/google/genai/types/GetBatchJobConfig.java @@ -0,0 +1,77 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Auto-generated code. Do not edit. + +package com.google.genai.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.google.auto.value.AutoValue; +import com.google.genai.JsonSerializable; +import java.util.Optional; + +/** Optional parameters. */ +@AutoValue +@JsonDeserialize(builder = GetBatchJobConfig.Builder.class) +public abstract class GetBatchJobConfig extends JsonSerializable { + /** Used to override HTTP request options. */ + @JsonProperty("httpOptions") + public abstract Optional httpOptions(); + + /** Instantiates a builder for GetBatchJobConfig. */ + public static Builder builder() { + return new AutoValue_GetBatchJobConfig.Builder(); + } + + /** Creates a builder with the same values as this instance. */ + public abstract Builder toBuilder(); + + /** Builder for GetBatchJobConfig. */ + @AutoValue.Builder + public abstract static class Builder { + /** For internal usage. Please use `GetBatchJobConfig.builder()` for instantiation. */ + @JsonCreator + private static Builder create() { + return new AutoValue_GetBatchJobConfig.Builder(); + } + + /** + * Setter for httpOptions. + * + *

httpOptions: Used to override HTTP request options. + */ + @JsonProperty("httpOptions") + public abstract Builder httpOptions(HttpOptions httpOptions); + + /** + * Setter for httpOptions builder. + * + *

httpOptions: Used to override HTTP request options. + */ + public Builder httpOptions(HttpOptions.Builder httpOptionsBuilder) { + return httpOptions(httpOptionsBuilder.build()); + } + + public abstract GetBatchJobConfig build(); + } + + /** Deserializes a JSON string to a GetBatchJobConfig object. */ + public static GetBatchJobConfig fromJson(String jsonString) { + return JsonSerializable.fromJsonString(jsonString, GetBatchJobConfig.class); + } +} diff --git a/src/main/java/com/google/genai/types/GetBatchJobParameters.java b/src/main/java/com/google/genai/types/GetBatchJobParameters.java new file mode 100644 index 00000000000..5da46bf67a9 --- /dev/null +++ b/src/main/java/com/google/genai/types/GetBatchJobParameters.java @@ -0,0 +1,97 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Auto-generated code. Do not edit. + +package com.google.genai.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.google.api.core.InternalApi; +import com.google.auto.value.AutoValue; +import com.google.genai.JsonSerializable; +import java.util.Optional; + +/** Config for batches.get parameters. */ +@AutoValue +@InternalApi +@JsonDeserialize(builder = GetBatchJobParameters.Builder.class) +public abstract class GetBatchJobParameters extends JsonSerializable { + /** + * A fully-qualified BatchJob resource name or ID. Example: + * "projects/.../locations/.../batchPredictionJobs/456" or "456" when project and location are + * initialized in the client. + */ + @JsonProperty("name") + public abstract Optional name(); + + /** Optional parameters for the request. */ + @JsonProperty("config") + public abstract Optional config(); + + /** Instantiates a builder for GetBatchJobParameters. */ + public static Builder builder() { + return new AutoValue_GetBatchJobParameters.Builder(); + } + + /** Creates a builder with the same values as this instance. */ + public abstract Builder toBuilder(); + + /** Builder for GetBatchJobParameters. */ + @AutoValue.Builder + public abstract static class Builder { + /** For internal usage. Please use `GetBatchJobParameters.builder()` for instantiation. */ + @JsonCreator + private static Builder create() { + return new AutoValue_GetBatchJobParameters.Builder(); + } + + /** + * Setter for name. + * + *

name: A fully-qualified BatchJob resource name or ID. Example: + * "projects/.../locations/.../batchPredictionJobs/456" or "456" when project and location are + * initialized in the client. + */ + @JsonProperty("name") + public abstract Builder name(String name); + + /** + * Setter for config. + * + *

config: Optional parameters for the request. + */ + @JsonProperty("config") + public abstract Builder config(GetBatchJobConfig config); + + /** + * Setter for config builder. + * + *

config: Optional parameters for the request. + */ + public Builder config(GetBatchJobConfig.Builder configBuilder) { + return config(configBuilder.build()); + } + + public abstract GetBatchJobParameters build(); + } + + /** Deserializes a JSON string to a GetBatchJobParameters object. */ + public static GetBatchJobParameters fromJson(String jsonString) { + return JsonSerializable.fromJsonString(jsonString, GetBatchJobParameters.class); + } +} diff --git a/src/main/java/com/google/genai/types/InlinedRequest.java b/src/main/java/com/google/genai/types/InlinedRequest.java new file mode 100644 index 00000000000..33c2aee7141 --- /dev/null +++ b/src/main/java/com/google/genai/types/InlinedRequest.java @@ -0,0 +1,130 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Auto-generated code. Do not edit. + +package com.google.genai.types; + +import static com.google.common.collect.ImmutableList.toImmutableList; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.google.auto.value.AutoValue; +import com.google.genai.JsonSerializable; +import java.util.Arrays; +import java.util.List; +import java.util.Optional; + +/** Config for inlined request. */ +@AutoValue +@JsonDeserialize(builder = InlinedRequest.Builder.class) +public abstract class InlinedRequest extends JsonSerializable { + /** + * ID of the model to use. For a list of models, see `Google models + * `_. + */ + @JsonProperty("model") + public abstract Optional model(); + + /** Content of the request. */ + @JsonProperty("contents") + public abstract Optional> contents(); + + /** Configuration that contains optional model parameters. */ + @JsonProperty("config") + public abstract Optional config(); + + /** Instantiates a builder for InlinedRequest. */ + public static Builder builder() { + return new AutoValue_InlinedRequest.Builder(); + } + + /** Creates a builder with the same values as this instance. */ + public abstract Builder toBuilder(); + + /** Builder for InlinedRequest. */ + @AutoValue.Builder + public abstract static class Builder { + /** For internal usage. Please use `InlinedRequest.builder()` for instantiation. */ + @JsonCreator + private static Builder create() { + return new AutoValue_InlinedRequest.Builder(); + } + + /** + * Setter for model. + * + *

model: ID of the model to use. For a list of models, see `Google models + * `_. + */ + @JsonProperty("model") + public abstract Builder model(String model); + + /** + * Setter for contents. + * + *

contents: Content of the request. + */ + @JsonProperty("contents") + public abstract Builder contents(List contents); + + /** + * Setter for contents. + * + *

contents: Content of the request. + */ + public Builder contents(Content... contents) { + return contents(Arrays.asList(contents)); + } + + /** + * Setter for contents builder. + * + *

contents: Content of the request. + */ + public Builder contents(Content.Builder... contentsBuilders) { + return contents( + Arrays.asList(contentsBuilders).stream() + .map(Content.Builder::build) + .collect(toImmutableList())); + } + + /** + * Setter for config. + * + *

config: Configuration that contains optional model parameters. + */ + @JsonProperty("config") + public abstract Builder config(GenerateContentConfig config); + + /** + * Setter for config builder. + * + *

config: Configuration that contains optional model parameters. + */ + public Builder config(GenerateContentConfig.Builder configBuilder) { + return config(configBuilder.build()); + } + + public abstract InlinedRequest build(); + } + + /** Deserializes a JSON string to a InlinedRequest object. */ + public static InlinedRequest fromJson(String jsonString) { + return JsonSerializable.fromJsonString(jsonString, InlinedRequest.class); + } +} diff --git a/src/main/java/com/google/genai/types/InlinedResponse.java b/src/main/java/com/google/genai/types/InlinedResponse.java new file mode 100644 index 00000000000..ae0e13ad674 --- /dev/null +++ b/src/main/java/com/google/genai/types/InlinedResponse.java @@ -0,0 +1,98 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Auto-generated code. Do not edit. + +package com.google.genai.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.google.auto.value.AutoValue; +import com.google.genai.JsonSerializable; +import java.util.Optional; + +/** Config for `inlined_responses` parameter. */ +@AutoValue +@JsonDeserialize(builder = InlinedResponse.Builder.class) +public abstract class InlinedResponse extends JsonSerializable { + /** The response to the request. */ + @JsonProperty("response") + public abstract Optional response(); + + /** The error encountered while processing the request. */ + @JsonProperty("error") + public abstract Optional error(); + + /** Instantiates a builder for InlinedResponse. */ + public static Builder builder() { + return new AutoValue_InlinedResponse.Builder(); + } + + /** Creates a builder with the same values as this instance. */ + public abstract Builder toBuilder(); + + /** Builder for InlinedResponse. */ + @AutoValue.Builder + public abstract static class Builder { + /** For internal usage. Please use `InlinedResponse.builder()` for instantiation. */ + @JsonCreator + private static Builder create() { + return new AutoValue_InlinedResponse.Builder(); + } + + /** + * Setter for response. + * + *

response: The response to the request. + */ + @JsonProperty("response") + public abstract Builder response(GenerateContentResponse response); + + /** + * Setter for response builder. + * + *

response: The response to the request. + */ + public Builder response(GenerateContentResponse.Builder responseBuilder) { + return response(responseBuilder.build()); + } + + /** + * Setter for error. + * + *

error: The error encountered while processing the request. + */ + @JsonProperty("error") + public abstract Builder error(JobError error); + + /** + * Setter for error builder. + * + *

error: The error encountered while processing the request. + */ + public Builder error(JobError.Builder errorBuilder) { + return error(errorBuilder.build()); + } + + public abstract InlinedResponse build(); + } + + /** Deserializes a JSON string to a InlinedResponse object. */ + public static InlinedResponse fromJson(String jsonString) { + return JsonSerializable.fromJsonString(jsonString, InlinedResponse.class); + } +} diff --git a/src/main/java/com/google/genai/types/JobError.java b/src/main/java/com/google/genai/types/JobError.java new file mode 100644 index 00000000000..5f2983b912f --- /dev/null +++ b/src/main/java/com/google/genai/types/JobError.java @@ -0,0 +1,112 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Auto-generated code. Do not edit. + +package com.google.genai.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.google.auto.value.AutoValue; +import com.google.genai.JsonSerializable; +import java.util.Arrays; +import java.util.List; +import java.util.Optional; + +/** Job error. */ +@AutoValue +@JsonDeserialize(builder = JobError.Builder.class) +public abstract class JobError extends JsonSerializable { + /** + * A list of messages that carry the error details. There is a common set of message types for + * APIs to use. + */ + @JsonProperty("details") + public abstract Optional> details(); + + /** The status code. */ + @JsonProperty("code") + public abstract Optional code(); + + /** + * A developer-facing error message, which should be in English. Any user-facing error message + * should be localized and sent in the `details` field. + */ + @JsonProperty("message") + public abstract Optional message(); + + /** Instantiates a builder for JobError. */ + public static Builder builder() { + return new AutoValue_JobError.Builder(); + } + + /** Creates a builder with the same values as this instance. */ + public abstract Builder toBuilder(); + + /** Builder for JobError. */ + @AutoValue.Builder + public abstract static class Builder { + /** For internal usage. Please use `JobError.builder()` for instantiation. */ + @JsonCreator + private static Builder create() { + return new AutoValue_JobError.Builder(); + } + + /** + * Setter for details. + * + *

details: A list of messages that carry the error details. There is a common set of message + * types for APIs to use. + */ + @JsonProperty("details") + public abstract Builder details(List details); + + /** + * Setter for details. + * + *

details: A list of messages that carry the error details. There is a common set of message + * types for APIs to use. + */ + public Builder details(String... details) { + return details(Arrays.asList(details)); + } + + /** + * Setter for code. + * + *

code: The status code. + */ + @JsonProperty("code") + public abstract Builder code(Integer code); + + /** + * Setter for message. + * + *

message: A developer-facing error message, which should be in English. Any user-facing + * error message should be localized and sent in the `details` field. + */ + @JsonProperty("message") + public abstract Builder message(String message); + + public abstract JobError build(); + } + + /** Deserializes a JSON string to a JobError object. */ + public static JobError fromJson(String jsonString) { + return JsonSerializable.fromJsonString(jsonString, JobError.class); + } +} diff --git a/src/main/java/com/google/genai/types/JobState.java b/src/main/java/com/google/genai/types/JobState.java new file mode 100644 index 00000000000..8c0038e47b4 --- /dev/null +++ b/src/main/java/com/google/genai/types/JobState.java @@ -0,0 +1,140 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Auto-generated code. Do not edit. + +package com.google.genai.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; +import com.google.common.base.Ascii; +import java.util.Objects; + +/** Job state. */ +public class JobState { + + /** Enum representing the known values for JobState. */ + public enum Known { + /** The job state is unspecified. */ + JOB_STATE_UNSPECIFIED, + + /** The job has been just created or resumed and processing has not yet begun. */ + JOB_STATE_QUEUED, + + /** The service is preparing to run the job. */ + JOB_STATE_PENDING, + + /** The job is in progress. */ + JOB_STATE_RUNNING, + + /** The job completed successfully. */ + JOB_STATE_SUCCEEDED, + + /** The job failed. */ + JOB_STATE_FAILED, + + /** + * The job is being cancelled. From this state the job may only go to either + * `JOB_STATE_SUCCEEDED`, `JOB_STATE_FAILED` or `JOB_STATE_CANCELLED`. + */ + JOB_STATE_CANCELLING, + + /** The job has been cancelled. */ + JOB_STATE_CANCELLED, + + /** The job has been stopped, and can be resumed. */ + JOB_STATE_PAUSED, + + /** The job has expired. */ + JOB_STATE_EXPIRED, + + /** + * The job is being updated. Only jobs in the `JOB_STATE_RUNNING` state can be updated. After + * updating, the job goes back to the `JOB_STATE_RUNNING` state. + */ + JOB_STATE_UPDATING, + + /** The job is partially succeeded, some results may be missing due to errors. */ + JOB_STATE_PARTIALLY_SUCCEEDED + } + + private Known jobStateEnum; + private final String value; + + @JsonCreator + public JobState(String value) { + this.value = value; + for (Known jobStateEnum : Known.values()) { + if (Ascii.equalsIgnoreCase(jobStateEnum.toString(), value)) { + this.jobStateEnum = jobStateEnum; + break; + } + } + if (this.jobStateEnum == null) { + this.jobStateEnum = Known.JOB_STATE_UNSPECIFIED; + } + } + + public JobState(Known knownValue) { + this.jobStateEnum = knownValue; + this.value = knownValue.toString(); + } + + @Override + @JsonValue + public String toString() { + return this.value; + } + + @SuppressWarnings("PatternMatchingInstanceof") + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null) { + return false; + } + + if (!(o instanceof JobState)) { + return false; + } + + JobState other = (JobState) o; + + if (this.jobStateEnum != Known.JOB_STATE_UNSPECIFIED + && other.jobStateEnum != Known.JOB_STATE_UNSPECIFIED) { + return this.jobStateEnum == other.jobStateEnum; + } else if (this.jobStateEnum == Known.JOB_STATE_UNSPECIFIED + && other.jobStateEnum == Known.JOB_STATE_UNSPECIFIED) { + return this.value.equals(other.value); + } + return false; + } + + @Override + public int hashCode() { + if (this.jobStateEnum != Known.JOB_STATE_UNSPECIFIED) { + return this.jobStateEnum.hashCode(); + } else { + return Objects.hashCode(this.value); + } + } + + public Known knownEnum() { + return this.jobStateEnum; + } +} diff --git a/src/main/java/com/google/genai/types/ListBatchJobsConfig.java b/src/main/java/com/google/genai/types/ListBatchJobsConfig.java new file mode 100644 index 00000000000..30923c639d2 --- /dev/null +++ b/src/main/java/com/google/genai/types/ListBatchJobsConfig.java @@ -0,0 +1,113 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Auto-generated code. Do not edit. + +package com.google.genai.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.google.auto.value.AutoValue; +import com.google.genai.JsonSerializable; +import java.util.Optional; + +/** Config for optional parameters. */ +@AutoValue +@JsonDeserialize(builder = ListBatchJobsConfig.Builder.class) +public abstract class ListBatchJobsConfig extends JsonSerializable { + /** Used to override HTTP request options. */ + @JsonProperty("httpOptions") + public abstract Optional httpOptions(); + + /** */ + @JsonProperty("pageSize") + public abstract Optional pageSize(); + + /** */ + @JsonProperty("pageToken") + public abstract Optional pageToken(); + + /** */ + @JsonProperty("filter") + public abstract Optional filter(); + + /** Instantiates a builder for ListBatchJobsConfig. */ + public static Builder builder() { + return new AutoValue_ListBatchJobsConfig.Builder(); + } + + /** Creates a builder with the same values as this instance. */ + public abstract Builder toBuilder(); + + /** Builder for ListBatchJobsConfig. */ + @AutoValue.Builder + public abstract static class Builder { + /** For internal usage. Please use `ListBatchJobsConfig.builder()` for instantiation. */ + @JsonCreator + private static Builder create() { + return new AutoValue_ListBatchJobsConfig.Builder(); + } + + /** + * Setter for httpOptions. + * + *

httpOptions: Used to override HTTP request options. + */ + @JsonProperty("httpOptions") + public abstract Builder httpOptions(HttpOptions httpOptions); + + /** + * Setter for httpOptions builder. + * + *

httpOptions: Used to override HTTP request options. + */ + public Builder httpOptions(HttpOptions.Builder httpOptionsBuilder) { + return httpOptions(httpOptionsBuilder.build()); + } + + /** + * Setter for pageSize. + * + *

pageSize: + */ + @JsonProperty("pageSize") + public abstract Builder pageSize(Integer pageSize); + + /** + * Setter for pageToken. + * + *

pageToken: + */ + @JsonProperty("pageToken") + public abstract Builder pageToken(String pageToken); + + /** + * Setter for filter. + * + *

filter: + */ + @JsonProperty("filter") + public abstract Builder filter(String filter); + + public abstract ListBatchJobsConfig build(); + } + + /** Deserializes a JSON string to a ListBatchJobsConfig object. */ + public static ListBatchJobsConfig fromJson(String jsonString) { + return JsonSerializable.fromJsonString(jsonString, ListBatchJobsConfig.class); + } +} diff --git a/src/main/java/com/google/genai/types/ListBatchJobsParameters.java b/src/main/java/com/google/genai/types/ListBatchJobsParameters.java new file mode 100644 index 00000000000..3be2d047235 --- /dev/null +++ b/src/main/java/com/google/genai/types/ListBatchJobsParameters.java @@ -0,0 +1,79 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Auto-generated code. Do not edit. + +package com.google.genai.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.google.api.core.InternalApi; +import com.google.auto.value.AutoValue; +import com.google.genai.JsonSerializable; +import java.util.Optional; + +/** Config for batches.list parameters. */ +@AutoValue +@InternalApi +@JsonDeserialize(builder = ListBatchJobsParameters.Builder.class) +public abstract class ListBatchJobsParameters extends JsonSerializable { + /** */ + @JsonProperty("config") + public abstract Optional config(); + + /** Instantiates a builder for ListBatchJobsParameters. */ + public static Builder builder() { + return new AutoValue_ListBatchJobsParameters.Builder(); + } + + /** Creates a builder with the same values as this instance. */ + public abstract Builder toBuilder(); + + /** Builder for ListBatchJobsParameters. */ + @AutoValue.Builder + public abstract static class Builder { + /** For internal usage. Please use `ListBatchJobsParameters.builder()` for instantiation. */ + @JsonCreator + private static Builder create() { + return new AutoValue_ListBatchJobsParameters.Builder(); + } + + /** + * Setter for config. + * + *

config: + */ + @JsonProperty("config") + public abstract Builder config(ListBatchJobsConfig config); + + /** + * Setter for config builder. + * + *

config: + */ + public Builder config(ListBatchJobsConfig.Builder configBuilder) { + return config(configBuilder.build()); + } + + public abstract ListBatchJobsParameters build(); + } + + /** Deserializes a JSON string to a ListBatchJobsParameters object. */ + public static ListBatchJobsParameters fromJson(String jsonString) { + return JsonSerializable.fromJsonString(jsonString, ListBatchJobsParameters.class); + } +} diff --git a/src/main/java/com/google/genai/types/ListBatchJobsResponse.java b/src/main/java/com/google/genai/types/ListBatchJobsResponse.java new file mode 100644 index 00000000000..b57695adb9d --- /dev/null +++ b/src/main/java/com/google/genai/types/ListBatchJobsResponse.java @@ -0,0 +1,105 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Auto-generated code. Do not edit. + +package com.google.genai.types; + +import static com.google.common.collect.ImmutableList.toImmutableList; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.google.auto.value.AutoValue; +import com.google.genai.JsonSerializable; +import java.util.Arrays; +import java.util.List; +import java.util.Optional; + +/** Config for batches.list return value. */ +@AutoValue +@JsonDeserialize(builder = ListBatchJobsResponse.Builder.class) +public abstract class ListBatchJobsResponse extends JsonSerializable { + /** */ + @JsonProperty("nextPageToken") + public abstract Optional nextPageToken(); + + /** */ + @JsonProperty("batchJobs") + public abstract Optional> batchJobs(); + + /** Instantiates a builder for ListBatchJobsResponse. */ + public static Builder builder() { + return new AutoValue_ListBatchJobsResponse.Builder(); + } + + /** Creates a builder with the same values as this instance. */ + public abstract Builder toBuilder(); + + /** Builder for ListBatchJobsResponse. */ + @AutoValue.Builder + public abstract static class Builder { + /** For internal usage. Please use `ListBatchJobsResponse.builder()` for instantiation. */ + @JsonCreator + private static Builder create() { + return new AutoValue_ListBatchJobsResponse.Builder(); + } + + /** + * Setter for nextPageToken. + * + *

nextPageToken: + */ + @JsonProperty("nextPageToken") + public abstract Builder nextPageToken(String nextPageToken); + + /** + * Setter for batchJobs. + * + *

batchJobs: + */ + @JsonProperty("batchJobs") + public abstract Builder batchJobs(List batchJobs); + + /** + * Setter for batchJobs. + * + *

batchJobs: + */ + public Builder batchJobs(BatchJob... batchJobs) { + return batchJobs(Arrays.asList(batchJobs)); + } + + /** + * Setter for batchJobs builder. + * + *

batchJobs: + */ + public Builder batchJobs(BatchJob.Builder... batchJobsBuilders) { + return batchJobs( + Arrays.asList(batchJobsBuilders).stream() + .map(BatchJob.Builder::build) + .collect(toImmutableList())); + } + + public abstract ListBatchJobsResponse build(); + } + + /** Deserializes a JSON string to a ListBatchJobsResponse object. */ + public static ListBatchJobsResponse fromJson(String jsonString) { + return JsonSerializable.fromJsonString(jsonString, ListBatchJobsResponse.class); + } +} diff --git a/src/test/java/com/google/genai/TableTest.java b/src/test/java/com/google/genai/TableTest.java index 8ccd64a43e6..281578e70b0 100644 --- a/src/test/java/com/google/genai/TableTest.java +++ b/src/test/java/com/google/genai/TableTest.java @@ -196,6 +196,7 @@ private static Collection createTestCases( } // Edit image ReferenceImages are not correctly deserialized for replay tests if (testName.contains("models.edit_image") + || testName.contains("batches.test_list_batch_jobs") // TODO(b/427478981) Remove this. || testName.contains("models.generate_content.test_speech_with_config") || testName.contains( "models.generate_content.test_logprobs_zero_with_response_logprobs_true")) { From 357b88917e9785e22e767f0f49c2d8b81d83b53e Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Wed, 25 Jun 2025 15:35:55 -0700 Subject: [PATCH 041/602] chore(main): release 1.6.0 (#350) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- .release-please-manifest.json | 2 +- CHANGELOG.md | 20 ++++++++++++++++++++ examples/pom.xml | 2 +- pom.xml | 2 +- 4 files changed, 23 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index fbd9082d716..7deae33804b 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "1.5.0" + ".": "1.6.0" } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 0dc8aaed03a..15347abbbd1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,25 @@ # Changelog +## [1.6.0](https://github.com/googleapis/java-genai/compare/v1.5.0...v1.6.0) (2025-06-25) + + +### Features + +* Add compressionQuality enum for generate_videos ([b0e665b](https://github.com/googleapis/java-genai/commit/b0e665bf6ae09dc2146e49714a4855443a270776)) +* Add enhance_input_image and image_preservation_factor fields for upscale_image ([94a329a](https://github.com/googleapis/java-genai/commit/94a329abcd3c668065abfae511b55766ed051668)) +* allow users to access headers for generateContent method and generateContentStream ([0315357](https://github.com/googleapis/java-genai/commit/03153578ea64f0c34836ac62395aa867f44eac07)) +* Batches support in Java ([5ce13e9](https://github.com/googleapis/java-genai/commit/5ce13e9c79c4791d405b1dfa71c1d9358dc5a08d)) +* configure release-please to automatically update package version across all files during releases. ([9131ac2](https://github.com/googleapis/java-genai/commit/9131ac24fde477afb25deb516c7ace51530ed8d9)) +* expose the responseJsonSchema in GenerateContentConfig ([9d9acdb](https://github.com/googleapis/java-genai/commit/9d9acdb494358155cbb3c2ce3acbe55209bbdb7e)) +* support client.caches.update method ([345c2b9](https://github.com/googleapis/java-genai/commit/345c2b93789913d6d84cdde9c30f86ec4041bd24)) + + +### Documentation + +* add more comments to make it easier to follow live api code, and to explain the usage of new concepts like thenCompose. ([96c792c](https://github.com/googleapis/java-genai/commit/96c792c3aa84f632e0b46bb986de403ecbf4edc1)) +* improve generate images documentation ([44c21dd](https://github.com/googleapis/java-genai/commit/44c21dd78e0d0be0e681e991b15d3dae3be360f2)) +* Update description of thinking_budget. ([265f20a](https://github.com/googleapis/java-genai/commit/265f20addd9e9e76c249e6042d653c8cec9f27a4)) + ## [1.5.0](https://github.com/googleapis/java-genai/compare/v1.4.1...v1.5.0) (2025-06-19) diff --git a/examples/pom.xml b/examples/pom.xml index 95ba06f36db..e6dc3899bc0 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -5,7 +5,7 @@ com.google.genai.examples google-genai-examples - 1.6.0-SNAPSHOT + 1.6.0 google-genai-examples diff --git a/pom.xml b/pom.xml index 3de1d844970..d8f27defa1f 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ com.google.genai google-genai google-genai - 1.6.0-SNAPSHOT + 1.6.0 jar Java idiomatic SDK for the Gemini Developer APIs and Vertex AI APIs. From 828b1d6eb95330affee953e5be09be9c0b064e69 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Wed, 25 Jun 2025 15:46:25 -0700 Subject: [PATCH 042/602] chore(main): release 1.7.0-SNAPSHOT (#363) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- examples/pom.xml | 2 +- pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/pom.xml b/examples/pom.xml index e6dc3899bc0..e1f9385563a 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -5,7 +5,7 @@ com.google.genai.examples google-genai-examples - 1.6.0 + 1.7.0-SNAPSHOT google-genai-examples diff --git a/pom.xml b/pom.xml index d8f27defa1f..a3c2899b88c 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ com.google.genai google-genai google-genai - 1.6.0 + 1.7.0-SNAPSHOT jar Java idiomatic SDK for the Gemini Developer APIs and Vertex AI APIs. From 9a508aecd401fca04d8407c4693c9d9af7139f12 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Wed, 25 Jun 2025 15:40:00 -0700 Subject: [PATCH 043/602] Copybara import of the project: -- 638d0c6e190b19ae6c3579f31ddff8724671231f by release-please[bot] <55107282+release-please[bot]@users.noreply.github.com>: chore(main): release 1.6.0 COPYBARA_INTEGRATE_REVIEW=https://github.com/googleapis/java-genai/pull/350 from googleapis:release-please--branches--main 638d0c6e190b19ae6c3579f31ddff8724671231f PiperOrigin-RevId: 775863685 --- examples/pom.xml | 2 +- pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/pom.xml b/examples/pom.xml index e1f9385563a..e6dc3899bc0 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -5,7 +5,7 @@ com.google.genai.examples google-genai-examples - 1.7.0-SNAPSHOT + 1.6.0 google-genai-examples diff --git a/pom.xml b/pom.xml index a3c2899b88c..d8f27defa1f 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ com.google.genai google-genai google-genai - 1.7.0-SNAPSHOT + 1.6.0 jar Java idiomatic SDK for the Gemini Developer APIs and Vertex AI APIs. From 18e02ef51603e2f7d005d6dd2243e3c712307cfd Mon Sep 17 00:00:00 2001 From: Annie Luc Date: Wed, 25 Jun 2025 15:58:23 -0700 Subject: [PATCH 044/602] Copybara import of the project: -- 357b88917e9785e22e767f0f49c2d8b81d83b53e by release-please[bot] <55107282+release-please[bot]@users.noreply.github.com>: chore(main): release 1.6.0 (#350) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> -- 5dfcc1d3e493f109f690d028e3b00c40e726508b by release-please[bot] <55107282+release-please[bot]@users.noreply.github.com>: chore(main): release 1.7.0-SNAPSHOT COPYBARA_INTEGRATE_REVIEW=https://github.com/googleapis/java-genai/pull/363 from googleapis:release-please--branches--main 5dfcc1d3e493f109f690d028e3b00c40e726508b PiperOrigin-RevId: 775870580 --- examples/pom.xml | 2 +- pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/pom.xml b/examples/pom.xml index e6dc3899bc0..e1f9385563a 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -5,7 +5,7 @@ com.google.genai.examples google-genai-examples - 1.6.0 + 1.7.0-SNAPSHOT google-genai-examples diff --git a/pom.xml b/pom.xml index d8f27defa1f..a3c2899b88c 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ com.google.genai google-genai google-genai - 1.6.0 + 1.7.0-SNAPSHOT jar Java idiomatic SDK for the Gemini Developer APIs and Vertex AI APIs. From 5d898f8dd04f373a1970035c21a71b772b51720f Mon Sep 17 00:00:00 2001 From: Annie Luc Date: Wed, 25 Jun 2025 16:12:55 -0700 Subject: [PATCH 045/602] chore: Update package version in README and ApiClient PiperOrigin-RevId: 775876322 --- README.md | 2 +- examples/pom.xml | 2 +- src/main/java/com/google/genai/ApiClient.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index cf62d054f5f..425e53a5e4b 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ If you're using Maven, add the following to your dependencies: com.google.genai google-genai - 1.5.0 + 1.6.0 ``` diff --git a/examples/pom.xml b/examples/pom.xml index e1f9385563a..7391b5e960a 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -13,7 +13,7 @@ 1.8 1.8 - 1.6.0-SNAPSHOT + 1.7.0-SNAPSHOT diff --git a/src/main/java/com/google/genai/ApiClient.java b/src/main/java/com/google/genai/ApiClient.java index cc8e1c26f89..a4328210fad 100644 --- a/src/main/java/com/google/genai/ApiClient.java +++ b/src/main/java/com/google/genai/ApiClient.java @@ -42,7 +42,7 @@ abstract class ApiClient { // {x-version-update-start:google-genai:released} - private static final String SDK_VERSION = "1.5.0"; + private static final String SDK_VERSION = "1.6.0"; // {x-version-update-end:google-genai:released} private static final Logger logger = Logger.getLogger(ApiClient.class.getName()); From d1f6201892de9f37b913044dd494c68b81bcc13a Mon Sep 17 00:00:00 2001 From: Ivan Lopez Hernandez Date: Thu, 26 Jun 2025 15:39:25 -0700 Subject: [PATCH 046/602] fix: Remove default timeout PiperOrigin-RevId: 776308733 --- src/main/java/com/google/genai/ApiClient.java | 2 -- src/test/java/com/google/genai/HttpApiClientTest.java | 6 ++---- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/google/genai/ApiClient.java b/src/main/java/com/google/genai/ApiClient.java index a4328210fad..65aed598139 100644 --- a/src/main/java/com/google/genai/ApiClient.java +++ b/src/main/java/com/google/genai/ApiClient.java @@ -291,8 +291,6 @@ static HttpOptions defaultHttpOptions(boolean vertexAI, Optional locatio .apiVersion("v1beta"); } - defaultHttpOptionsBuilder.timeout(Math.toIntExact(Duration.ofMinutes(5).toMillis())); - return defaultHttpOptionsBuilder.build(); } diff --git a/src/test/java/com/google/genai/HttpApiClientTest.java b/src/test/java/com/google/genai/HttpApiClientTest.java index 2dc5c61b149..0a4b20a8c50 100644 --- a/src/test/java/com/google/genai/HttpApiClientTest.java +++ b/src/test/java/com/google/genai/HttpApiClientTest.java @@ -355,8 +355,7 @@ public void testHttpClientNoTimeout() throws Exception { RequestConfig config = getRequestConfig(httpClient); - // Default timeout is 5 minutes (300000 milliseconds). - assertEquals(300000, config.getConnectTimeout()); + assertEquals(-1, config.getConnectTimeout()); assertEquals("api-key", client.apiKey()); assertFalse(client.httpOptions.headers().get().containsKey("X-Server-Timeout")); } @@ -377,8 +376,7 @@ public void testHttpClientVertexNoTimeout() throws Exception { RequestConfig config = getRequestConfig(httpClient); - // Default timeout is 5 minutes (300000 milliseconds). - assertEquals(300000, config.getConnectTimeout()); + assertEquals(-1, config.getConnectTimeout()); assertEquals("project", client.project()); assertEquals("location", client.location()); assertTrue(client.vertexAI()); From 7e6488746d5c041af829d59644fa76384eca3884 Mon Sep 17 00:00:00 2001 From: Sara Robinson Date: Mon, 30 Jun 2025 10:38:33 -0700 Subject: [PATCH 047/602] chore: add new types from discovery doc PiperOrigin-RevId: 777630866 --- src/main/java/com/google/genai/Batches.java | 28 +++ src/main/java/com/google/genai/Caches.java | 14 ++ .../java/com/google/genai/LiveConverters.java | 14 ++ src/main/java/com/google/genai/Models.java | 14 ++ .../com/google/genai/TokensConverters.java | 14 ++ .../java/com/google/genai/types/ApiAuth.java | 80 +++++++ .../genai/types/ApiAuthApiKeyConfig.java | 84 ++++++++ .../java/com/google/genai/types/ApiSpec.java | 107 ++++++++++ .../com/google/genai/types/BlockedReason.java | 5 +- .../genai/types/CodeExecutionResult.java | 4 +- .../com/google/genai/types/Environment.java | 104 ++++++++++ .../google/genai/types/ExecutableCode.java | 4 +- .../com/google/genai/types/ExternalApi.java | 196 ++++++++++++++++++ .../types/ExternalApiElasticSearchParams.java | 98 +++++++++ .../types/ExternalApiSimpleSearchParams.java | 56 +++++ .../google/genai/types/GenerationConfig.java | 83 ++++---- .../google/genai/types/GroundingSupport.java | 13 +- .../com/google/genai/types/HarmCategory.java | 14 +- .../com/google/genai/types/Retrieval.java | 21 ++ .../com/google/genai/types/SafetyRating.java | 42 ++++ .../java/com/google/genai/types/Tool.java | 26 +++ .../google/genai/types/ToolComputerUse.java | 89 ++++++++ 22 files changed, 1065 insertions(+), 45 deletions(-) create mode 100644 src/main/java/com/google/genai/types/ApiAuth.java create mode 100644 src/main/java/com/google/genai/types/ApiAuthApiKeyConfig.java create mode 100644 src/main/java/com/google/genai/types/ApiSpec.java create mode 100644 src/main/java/com/google/genai/types/Environment.java create mode 100644 src/main/java/com/google/genai/types/ExternalApi.java create mode 100644 src/main/java/com/google/genai/types/ExternalApiElasticSearchParams.java create mode 100644 src/main/java/com/google/genai/types/ExternalApiSimpleSearchParams.java create mode 100644 src/main/java/com/google/genai/types/ToolComputerUse.java diff --git a/src/main/java/com/google/genai/Batches.java b/src/main/java/com/google/genai/Batches.java index 80c0997c3e9..02953f0f679 100644 --- a/src/main/java/com/google/genai/Batches.java +++ b/src/main/java/com/google/genai/Batches.java @@ -702,6 +702,13 @@ ObjectNode toolToMldev(JsonNode fromObject, ObjectNode parentObject) { Common.getValueByPath(fromObject, new String[] {"codeExecution"})); } + if (Common.getValueByPath(fromObject, new String[] {"computerUse"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"computerUse"}, + Common.getValueByPath(fromObject, new String[] {"computerUse"})); + } + return toObject; } @@ -2307,6 +2314,13 @@ ObjectNode toolToVertex(JsonNode fromObject, ObjectNode parentObject) { Common.getValueByPath(fromObject, new String[] {"codeExecution"})); } + if (Common.getValueByPath(fromObject, new String[] {"computerUse"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"computerUse"}, + Common.getValueByPath(fromObject, new String[] {"computerUse"})); + } + return toObject; } @@ -3827,6 +3841,13 @@ ObjectNode toolFromMldev(JsonNode fromObject, ObjectNode parentObject) { Common.getValueByPath(fromObject, new String[] {"codeExecution"})); } + if (Common.getValueByPath(fromObject, new String[] {"computerUse"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"computerUse"}, + Common.getValueByPath(fromObject, new String[] {"computerUse"})); + } + return toObject; } @@ -5341,6 +5362,13 @@ ObjectNode toolFromVertex(JsonNode fromObject, ObjectNode parentObject) { Common.getValueByPath(fromObject, new String[] {"codeExecution"})); } + if (Common.getValueByPath(fromObject, new String[] {"computerUse"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"computerUse"}, + Common.getValueByPath(fromObject, new String[] {"computerUse"})); + } + return toObject; } diff --git a/src/main/java/com/google/genai/Caches.java b/src/main/java/com/google/genai/Caches.java index e1a3d77d6de..eca65948d92 100644 --- a/src/main/java/com/google/genai/Caches.java +++ b/src/main/java/com/google/genai/Caches.java @@ -507,6 +507,13 @@ ObjectNode toolToMldev(JsonNode fromObject, ObjectNode parentObject) { Common.getValueByPath(fromObject, new String[] {"codeExecution"})); } + if (Common.getValueByPath(fromObject, new String[] {"computerUse"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"computerUse"}, + Common.getValueByPath(fromObject, new String[] {"computerUse"})); + } + return toObject; } @@ -1313,6 +1320,13 @@ ObjectNode toolToVertex(JsonNode fromObject, ObjectNode parentObject) { Common.getValueByPath(fromObject, new String[] {"codeExecution"})); } + if (Common.getValueByPath(fromObject, new String[] {"computerUse"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"computerUse"}, + Common.getValueByPath(fromObject, new String[] {"computerUse"})); + } + return toObject; } diff --git a/src/main/java/com/google/genai/LiveConverters.java b/src/main/java/com/google/genai/LiveConverters.java index b3db3a4b784..d9c0ca79e3e 100644 --- a/src/main/java/com/google/genai/LiveConverters.java +++ b/src/main/java/com/google/genai/LiveConverters.java @@ -1075,6 +1075,13 @@ ObjectNode toolToMldev(JsonNode fromObject, ObjectNode parentObject) { Common.getValueByPath(fromObject, new String[] {"codeExecution"})); } + if (Common.getValueByPath(fromObject, new String[] {"computerUse"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"computerUse"}, + Common.getValueByPath(fromObject, new String[] {"computerUse"})); + } + return toObject; } @@ -1157,6 +1164,13 @@ ObjectNode toolToVertex(JsonNode fromObject, ObjectNode parentObject) { Common.getValueByPath(fromObject, new String[] {"codeExecution"})); } + if (Common.getValueByPath(fromObject, new String[] {"computerUse"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"computerUse"}, + Common.getValueByPath(fromObject, new String[] {"computerUse"})); + } + return toObject; } diff --git a/src/main/java/com/google/genai/Models.java b/src/main/java/com/google/genai/Models.java index 0f59255f36f..e3c44757233 100644 --- a/src/main/java/com/google/genai/Models.java +++ b/src/main/java/com/google/genai/Models.java @@ -742,6 +742,13 @@ ObjectNode toolToMldev(JsonNode fromObject, ObjectNode parentObject) { Common.getValueByPath(fromObject, new String[] {"codeExecution"})); } + if (Common.getValueByPath(fromObject, new String[] {"computerUse"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"computerUse"}, + Common.getValueByPath(fromObject, new String[] {"computerUse"})); + } + return toObject; } @@ -2493,6 +2500,13 @@ ObjectNode toolToVertex(JsonNode fromObject, ObjectNode parentObject) { Common.getValueByPath(fromObject, new String[] {"codeExecution"})); } + if (Common.getValueByPath(fromObject, new String[] {"computerUse"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"computerUse"}, + Common.getValueByPath(fromObject, new String[] {"computerUse"})); + } + return toObject; } diff --git a/src/main/java/com/google/genai/TokensConverters.java b/src/main/java/com/google/genai/TokensConverters.java index d7d12f41192..86638f464b6 100644 --- a/src/main/java/com/google/genai/TokensConverters.java +++ b/src/main/java/com/google/genai/TokensConverters.java @@ -1075,6 +1075,13 @@ ObjectNode toolToMldev(JsonNode fromObject, ObjectNode parentObject) { Common.getValueByPath(fromObject, new String[] {"codeExecution"})); } + if (Common.getValueByPath(fromObject, new String[] {"computerUse"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"computerUse"}, + Common.getValueByPath(fromObject, new String[] {"computerUse"})); + } + return toObject; } @@ -1157,6 +1164,13 @@ ObjectNode toolToVertex(JsonNode fromObject, ObjectNode parentObject) { Common.getValueByPath(fromObject, new String[] {"codeExecution"})); } + if (Common.getValueByPath(fromObject, new String[] {"computerUse"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"computerUse"}, + Common.getValueByPath(fromObject, new String[] {"computerUse"})); + } + return toObject; } diff --git a/src/main/java/com/google/genai/types/ApiAuth.java b/src/main/java/com/google/genai/types/ApiAuth.java new file mode 100644 index 00000000000..2ae9cc777e3 --- /dev/null +++ b/src/main/java/com/google/genai/types/ApiAuth.java @@ -0,0 +1,80 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Auto-generated code. Do not edit. + +package com.google.genai.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.google.auto.value.AutoValue; +import com.google.genai.JsonSerializable; +import java.util.Optional; + +/** + * The generic reusable api auth config. Deprecated. Please use AuthConfig + * (google/cloud/aiplatform/master/auth.proto) instead. + */ +@AutoValue +@JsonDeserialize(builder = ApiAuth.Builder.class) +public abstract class ApiAuth extends JsonSerializable { + /** The API secret. */ + @JsonProperty("apiKeyConfig") + public abstract Optional apiKeyConfig(); + + /** Instantiates a builder for ApiAuth. */ + public static Builder builder() { + return new AutoValue_ApiAuth.Builder(); + } + + /** Creates a builder with the same values as this instance. */ + public abstract Builder toBuilder(); + + /** Builder for ApiAuth. */ + @AutoValue.Builder + public abstract static class Builder { + /** For internal usage. Please use `ApiAuth.builder()` for instantiation. */ + @JsonCreator + private static Builder create() { + return new AutoValue_ApiAuth.Builder(); + } + + /** + * Setter for apiKeyConfig. + * + *

apiKeyConfig: The API secret. + */ + @JsonProperty("apiKeyConfig") + public abstract Builder apiKeyConfig(ApiAuthApiKeyConfig apiKeyConfig); + + /** + * Setter for apiKeyConfig builder. + * + *

apiKeyConfig: The API secret. + */ + public Builder apiKeyConfig(ApiAuthApiKeyConfig.Builder apiKeyConfigBuilder) { + return apiKeyConfig(apiKeyConfigBuilder.build()); + } + + public abstract ApiAuth build(); + } + + /** Deserializes a JSON string to a ApiAuth object. */ + public static ApiAuth fromJson(String jsonString) { + return JsonSerializable.fromJsonString(jsonString, ApiAuth.class); + } +} diff --git a/src/main/java/com/google/genai/types/ApiAuthApiKeyConfig.java b/src/main/java/com/google/genai/types/ApiAuthApiKeyConfig.java new file mode 100644 index 00000000000..2211294f2d8 --- /dev/null +++ b/src/main/java/com/google/genai/types/ApiAuthApiKeyConfig.java @@ -0,0 +1,84 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Auto-generated code. Do not edit. + +package com.google.genai.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.google.auto.value.AutoValue; +import com.google.genai.JsonSerializable; +import java.util.Optional; + +/** The API secret. */ +@AutoValue +@JsonDeserialize(builder = ApiAuthApiKeyConfig.Builder.class) +public abstract class ApiAuthApiKeyConfig extends JsonSerializable { + /** + * Required. The SecretManager secret version resource name storing API key. e.g. + * projects/{project}/secrets/{secret}/versions/{version} + */ + @JsonProperty("apiKeySecretVersion") + public abstract Optional apiKeySecretVersion(); + + /** The API key string. Either this or `api_key_secret_version` must be set. */ + @JsonProperty("apiKeyString") + public abstract Optional apiKeyString(); + + /** Instantiates a builder for ApiAuthApiKeyConfig. */ + public static Builder builder() { + return new AutoValue_ApiAuthApiKeyConfig.Builder(); + } + + /** Creates a builder with the same values as this instance. */ + public abstract Builder toBuilder(); + + /** Builder for ApiAuthApiKeyConfig. */ + @AutoValue.Builder + public abstract static class Builder { + /** For internal usage. Please use `ApiAuthApiKeyConfig.builder()` for instantiation. */ + @JsonCreator + private static Builder create() { + return new AutoValue_ApiAuthApiKeyConfig.Builder(); + } + + /** + * Setter for apiKeySecretVersion. + * + *

apiKeySecretVersion: Required. The SecretManager secret version resource name storing API + * key. e.g. projects/{project}/secrets/{secret}/versions/{version} + */ + @JsonProperty("apiKeySecretVersion") + public abstract Builder apiKeySecretVersion(String apiKeySecretVersion); + + /** + * Setter for apiKeyString. + * + *

apiKeyString: The API key string. Either this or `api_key_secret_version` must be set. + */ + @JsonProperty("apiKeyString") + public abstract Builder apiKeyString(String apiKeyString); + + public abstract ApiAuthApiKeyConfig build(); + } + + /** Deserializes a JSON string to a ApiAuthApiKeyConfig object. */ + public static ApiAuthApiKeyConfig fromJson(String jsonString) { + return JsonSerializable.fromJsonString(jsonString, ApiAuthApiKeyConfig.class); + } +} diff --git a/src/main/java/com/google/genai/types/ApiSpec.java b/src/main/java/com/google/genai/types/ApiSpec.java new file mode 100644 index 00000000000..17283d5724c --- /dev/null +++ b/src/main/java/com/google/genai/types/ApiSpec.java @@ -0,0 +1,107 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Auto-generated code. Do not edit. + +package com.google.genai.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; +import com.google.common.base.Ascii; +import java.util.Objects; + +/** The API spec that the external API implements. */ +public class ApiSpec { + + /** Enum representing the known values for ApiSpec. */ + public enum Known { + /** Unspecified API spec. This value should not be used. */ + API_SPEC_UNSPECIFIED, + + /** Simple search API spec. */ + SIMPLE_SEARCH, + + /** Elastic search API spec. */ + ELASTIC_SEARCH + } + + private Known apiSpecEnum; + private final String value; + + @JsonCreator + public ApiSpec(String value) { + this.value = value; + for (Known apiSpecEnum : Known.values()) { + if (Ascii.equalsIgnoreCase(apiSpecEnum.toString(), value)) { + this.apiSpecEnum = apiSpecEnum; + break; + } + } + if (this.apiSpecEnum == null) { + this.apiSpecEnum = Known.API_SPEC_UNSPECIFIED; + } + } + + public ApiSpec(Known knownValue) { + this.apiSpecEnum = knownValue; + this.value = knownValue.toString(); + } + + @Override + @JsonValue + public String toString() { + return this.value; + } + + @SuppressWarnings("PatternMatchingInstanceof") + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null) { + return false; + } + + if (!(o instanceof ApiSpec)) { + return false; + } + + ApiSpec other = (ApiSpec) o; + + if (this.apiSpecEnum != Known.API_SPEC_UNSPECIFIED + && other.apiSpecEnum != Known.API_SPEC_UNSPECIFIED) { + return this.apiSpecEnum == other.apiSpecEnum; + } else if (this.apiSpecEnum == Known.API_SPEC_UNSPECIFIED + && other.apiSpecEnum == Known.API_SPEC_UNSPECIFIED) { + return this.value.equals(other.value); + } + return false; + } + + @Override + public int hashCode() { + if (this.apiSpecEnum != Known.API_SPEC_UNSPECIFIED) { + return this.apiSpecEnum.hashCode(); + } else { + return Objects.hashCode(this.value); + } + } + + public Known knownEnum() { + return this.apiSpecEnum; + } +} diff --git a/src/main/java/com/google/genai/types/BlockedReason.java b/src/main/java/com/google/genai/types/BlockedReason.java index 790f3633cbc..fc652ee35d9 100644 --- a/src/main/java/com/google/genai/types/BlockedReason.java +++ b/src/main/java/com/google/genai/types/BlockedReason.java @@ -41,7 +41,10 @@ public enum Known { BLOCKLIST, /** Candidates blocked due to prohibited content. */ - PROHIBITED_CONTENT + PROHIBITED_CONTENT, + + /** Candidates blocked due to unsafe image generation content. */ + IMAGE_SAFETY } private Known blockedReasonEnum; diff --git a/src/main/java/com/google/genai/types/CodeExecutionResult.java b/src/main/java/com/google/genai/types/CodeExecutionResult.java index df53b356b82..2907684badd 100644 --- a/src/main/java/com/google/genai/types/CodeExecutionResult.java +++ b/src/main/java/com/google/genai/types/CodeExecutionResult.java @@ -27,8 +27,8 @@ import java.util.Optional; /** - * Result of executing the [ExecutableCode]. Always follows a `part` containing the - * [ExecutableCode]. + * Result of executing the [ExecutableCode]. Only generated when using the [CodeExecution] tool, and + * always follows a `part` containing the [ExecutableCode]. */ @AutoValue @JsonDeserialize(builder = CodeExecutionResult.Builder.class) diff --git a/src/main/java/com/google/genai/types/Environment.java b/src/main/java/com/google/genai/types/Environment.java new file mode 100644 index 00000000000..4347d593cfd --- /dev/null +++ b/src/main/java/com/google/genai/types/Environment.java @@ -0,0 +1,104 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Auto-generated code. Do not edit. + +package com.google.genai.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; +import com.google.common.base.Ascii; +import java.util.Objects; + +/** Required. The environment being operated. */ +public class Environment { + + /** Enum representing the known values for Environment. */ + public enum Known { + /** Defaults to browser. */ + ENVIRONMENT_UNSPECIFIED, + + /** Operates in a web browser. */ + ENVIRONMENT_BROWSER + } + + private Known environmentEnum; + private final String value; + + @JsonCreator + public Environment(String value) { + this.value = value; + for (Known environmentEnum : Known.values()) { + if (Ascii.equalsIgnoreCase(environmentEnum.toString(), value)) { + this.environmentEnum = environmentEnum; + break; + } + } + if (this.environmentEnum == null) { + this.environmentEnum = Known.ENVIRONMENT_UNSPECIFIED; + } + } + + public Environment(Known knownValue) { + this.environmentEnum = knownValue; + this.value = knownValue.toString(); + } + + @Override + @JsonValue + public String toString() { + return this.value; + } + + @SuppressWarnings("PatternMatchingInstanceof") + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null) { + return false; + } + + if (!(o instanceof Environment)) { + return false; + } + + Environment other = (Environment) o; + + if (this.environmentEnum != Known.ENVIRONMENT_UNSPECIFIED + && other.environmentEnum != Known.ENVIRONMENT_UNSPECIFIED) { + return this.environmentEnum == other.environmentEnum; + } else if (this.environmentEnum == Known.ENVIRONMENT_UNSPECIFIED + && other.environmentEnum == Known.ENVIRONMENT_UNSPECIFIED) { + return this.value.equals(other.value); + } + return false; + } + + @Override + public int hashCode() { + if (this.environmentEnum != Known.ENVIRONMENT_UNSPECIFIED) { + return this.environmentEnum.hashCode(); + } else { + return Objects.hashCode(this.value); + } + } + + public Known knownEnum() { + return this.environmentEnum; + } +} diff --git a/src/main/java/com/google/genai/types/ExecutableCode.java b/src/main/java/com/google/genai/types/ExecutableCode.java index da42fe5ed12..96779f55a4b 100644 --- a/src/main/java/com/google/genai/types/ExecutableCode.java +++ b/src/main/java/com/google/genai/types/ExecutableCode.java @@ -28,8 +28,8 @@ /** * Code generated by the model that is meant to be executed, and the result returned to the model. - * Generated when using the [FunctionDeclaration] tool and [FunctionCallingConfig] mode is set to - * [Mode.CODE]. + * Generated when using the [CodeExecution] tool, in which the code will be automatically executed, + * and a corresponding [CodeExecutionResult] will also be generated. */ @AutoValue @JsonDeserialize(builder = ExecutableCode.Builder.class) diff --git a/src/main/java/com/google/genai/types/ExternalApi.java b/src/main/java/com/google/genai/types/ExternalApi.java new file mode 100644 index 00000000000..69a7ecb26e8 --- /dev/null +++ b/src/main/java/com/google/genai/types/ExternalApi.java @@ -0,0 +1,196 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Auto-generated code. Do not edit. + +package com.google.genai.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.google.auto.value.AutoValue; +import com.google.errorprone.annotations.CanIgnoreReturnValue; +import com.google.genai.JsonSerializable; +import java.util.Optional; + +/** + * Retrieve from data source powered by external API for grounding. The external API is not owned by + * Google, but need to follow the pre-defined API spec. + */ +@AutoValue +@JsonDeserialize(builder = ExternalApi.Builder.class) +public abstract class ExternalApi extends JsonSerializable { + /** The authentication config to access the API. Deprecated. Please use auth_config instead. */ + @JsonProperty("apiAuth") + public abstract Optional apiAuth(); + + /** The API spec that the external API implements. */ + @JsonProperty("apiSpec") + public abstract Optional apiSpec(); + + /** The authentication config to access the API. */ + @JsonProperty("authConfig") + public abstract Optional authConfig(); + + /** Parameters for the elastic search API. */ + @JsonProperty("elasticSearchParams") + public abstract Optional elasticSearchParams(); + + /** + * The endpoint of the external API. The system will call the API at this endpoint to retrieve the + * data for grounding. Example: https://acme.com:443/search + */ + @JsonProperty("endpoint") + public abstract Optional endpoint(); + + /** Parameters for the simple search API. */ + @JsonProperty("simpleSearchParams") + public abstract Optional simpleSearchParams(); + + /** Instantiates a builder for ExternalApi. */ + public static Builder builder() { + return new AutoValue_ExternalApi.Builder(); + } + + /** Creates a builder with the same values as this instance. */ + public abstract Builder toBuilder(); + + /** Builder for ExternalApi. */ + @AutoValue.Builder + public abstract static class Builder { + /** For internal usage. Please use `ExternalApi.builder()` for instantiation. */ + @JsonCreator + private static Builder create() { + return new AutoValue_ExternalApi.Builder(); + } + + /** + * Setter for apiAuth. + * + *

apiAuth: The authentication config to access the API. Deprecated. Please use auth_config + * instead. + */ + @JsonProperty("apiAuth") + public abstract Builder apiAuth(ApiAuth apiAuth); + + /** + * Setter for apiAuth builder. + * + *

apiAuth: The authentication config to access the API. Deprecated. Please use auth_config + * instead. + */ + public Builder apiAuth(ApiAuth.Builder apiAuthBuilder) { + return apiAuth(apiAuthBuilder.build()); + } + + /** + * Setter for apiSpec. + * + *

apiSpec: The API spec that the external API implements. + */ + @JsonProperty("apiSpec") + public abstract Builder apiSpec(ApiSpec apiSpec); + + /** + * Setter for apiSpec given a known enum. + * + *

apiSpec: The API spec that the external API implements. + */ + @CanIgnoreReturnValue + public Builder apiSpec(ApiSpec.Known knownType) { + return apiSpec(new ApiSpec(knownType)); + } + + /** + * Setter for apiSpec given a string. + * + *

apiSpec: The API spec that the external API implements. + */ + @CanIgnoreReturnValue + public Builder apiSpec(String apiSpec) { + return apiSpec(new ApiSpec(apiSpec)); + } + + /** + * Setter for authConfig. + * + *

authConfig: The authentication config to access the API. + */ + @JsonProperty("authConfig") + public abstract Builder authConfig(AuthConfig authConfig); + + /** + * Setter for authConfig builder. + * + *

authConfig: The authentication config to access the API. + */ + public Builder authConfig(AuthConfig.Builder authConfigBuilder) { + return authConfig(authConfigBuilder.build()); + } + + /** + * Setter for elasticSearchParams. + * + *

elasticSearchParams: Parameters for the elastic search API. + */ + @JsonProperty("elasticSearchParams") + public abstract Builder elasticSearchParams(ExternalApiElasticSearchParams elasticSearchParams); + + /** + * Setter for elasticSearchParams builder. + * + *

elasticSearchParams: Parameters for the elastic search API. + */ + public Builder elasticSearchParams( + ExternalApiElasticSearchParams.Builder elasticSearchParamsBuilder) { + return elasticSearchParams(elasticSearchParamsBuilder.build()); + } + + /** + * Setter for endpoint. + * + *

endpoint: The endpoint of the external API. The system will call the API at this endpoint + * to retrieve the data for grounding. Example: https://acme.com:443/search + */ + @JsonProperty("endpoint") + public abstract Builder endpoint(String endpoint); + + /** + * Setter for simpleSearchParams. + * + *

simpleSearchParams: Parameters for the simple search API. + */ + @JsonProperty("simpleSearchParams") + public abstract Builder simpleSearchParams(ExternalApiSimpleSearchParams simpleSearchParams); + + /** + * Setter for simpleSearchParams builder. + * + *

simpleSearchParams: Parameters for the simple search API. + */ + public Builder simpleSearchParams( + ExternalApiSimpleSearchParams.Builder simpleSearchParamsBuilder) { + return simpleSearchParams(simpleSearchParamsBuilder.build()); + } + + public abstract ExternalApi build(); + } + + /** Deserializes a JSON string to a ExternalApi object. */ + public static ExternalApi fromJson(String jsonString) { + return JsonSerializable.fromJsonString(jsonString, ExternalApi.class); + } +} diff --git a/src/main/java/com/google/genai/types/ExternalApiElasticSearchParams.java b/src/main/java/com/google/genai/types/ExternalApiElasticSearchParams.java new file mode 100644 index 00000000000..5ec0a623ec5 --- /dev/null +++ b/src/main/java/com/google/genai/types/ExternalApiElasticSearchParams.java @@ -0,0 +1,98 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Auto-generated code. Do not edit. + +package com.google.genai.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.google.auto.value.AutoValue; +import com.google.genai.JsonSerializable; +import java.util.Optional; + +/** The search parameters to use for the ELASTIC_SEARCH spec. */ +@AutoValue +@JsonDeserialize(builder = ExternalApiElasticSearchParams.Builder.class) +public abstract class ExternalApiElasticSearchParams extends JsonSerializable { + /** The ElasticSearch index to use. */ + @JsonProperty("index") + public abstract Optional index(); + + /** + * Optional. Number of hits (chunks) to request. When specified, it is passed to Elasticsearch as + * the `num_hits` param. + */ + @JsonProperty("numHits") + public abstract Optional numHits(); + + /** The ElasticSearch search template to use. */ + @JsonProperty("searchTemplate") + public abstract Optional searchTemplate(); + + /** Instantiates a builder for ExternalApiElasticSearchParams. */ + public static Builder builder() { + return new AutoValue_ExternalApiElasticSearchParams.Builder(); + } + + /** Creates a builder with the same values as this instance. */ + public abstract Builder toBuilder(); + + /** Builder for ExternalApiElasticSearchParams. */ + @AutoValue.Builder + public abstract static class Builder { + /** + * For internal usage. Please use `ExternalApiElasticSearchParams.builder()` for instantiation. + */ + @JsonCreator + private static Builder create() { + return new AutoValue_ExternalApiElasticSearchParams.Builder(); + } + + /** + * Setter for index. + * + *

index: The ElasticSearch index to use. + */ + @JsonProperty("index") + public abstract Builder index(String index); + + /** + * Setter for numHits. + * + *

numHits: Optional. Number of hits (chunks) to request. When specified, it is passed to + * Elasticsearch as the `num_hits` param. + */ + @JsonProperty("numHits") + public abstract Builder numHits(Integer numHits); + + /** + * Setter for searchTemplate. + * + *

searchTemplate: The ElasticSearch search template to use. + */ + @JsonProperty("searchTemplate") + public abstract Builder searchTemplate(String searchTemplate); + + public abstract ExternalApiElasticSearchParams build(); + } + + /** Deserializes a JSON string to a ExternalApiElasticSearchParams object. */ + public static ExternalApiElasticSearchParams fromJson(String jsonString) { + return JsonSerializable.fromJsonString(jsonString, ExternalApiElasticSearchParams.class); + } +} diff --git a/src/main/java/com/google/genai/types/ExternalApiSimpleSearchParams.java b/src/main/java/com/google/genai/types/ExternalApiSimpleSearchParams.java new file mode 100644 index 00000000000..39314fe765f --- /dev/null +++ b/src/main/java/com/google/genai/types/ExternalApiSimpleSearchParams.java @@ -0,0 +1,56 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Auto-generated code. Do not edit. + +package com.google.genai.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.google.auto.value.AutoValue; +import com.google.genai.JsonSerializable; + +/** The search parameters to use for SIMPLE_SEARCH spec. */ +@AutoValue +@JsonDeserialize(builder = ExternalApiSimpleSearchParams.Builder.class) +public abstract class ExternalApiSimpleSearchParams extends JsonSerializable { + /** Instantiates a builder for ExternalApiSimpleSearchParams. */ + public static Builder builder() { + return new AutoValue_ExternalApiSimpleSearchParams.Builder(); + } + + /** Creates a builder with the same values as this instance. */ + public abstract Builder toBuilder(); + + /** Builder for ExternalApiSimpleSearchParams. */ + @AutoValue.Builder + public abstract static class Builder { + /** + * For internal usage. Please use `ExternalApiSimpleSearchParams.builder()` for instantiation. + */ + @JsonCreator + private static Builder create() { + return new AutoValue_ExternalApiSimpleSearchParams.Builder(); + } + + public abstract ExternalApiSimpleSearchParams build(); + } + + /** Deserializes a JSON string to a ExternalApiSimpleSearchParams object. */ + public static ExternalApiSimpleSearchParams fromJson(String jsonString) { + return JsonSerializable.fromJsonString(jsonString, ExternalApiSimpleSearchParams.class); + } +} diff --git a/src/main/java/com/google/genai/types/GenerationConfig.java b/src/main/java/com/google/genai/types/GenerationConfig.java index 513ae3254b9..3b678cc7eab 100644 --- a/src/main/java/com/google/genai/types/GenerationConfig.java +++ b/src/main/java/com/google/genai/types/GenerationConfig.java @@ -47,6 +47,10 @@ public abstract class GenerationConfig extends JsonSerializable { @JsonProperty("candidateCount") public abstract Optional candidateCount(); + /** Optional. If enabled, the model will detect emotions and adapt its responses accordingly. */ + @JsonProperty("enableAffectiveDialog") + public abstract Optional enableAffectiveDialog(); + /** Optional. Frequency penalties. */ @JsonProperty("frequencyPenalty") public abstract Optional frequencyPenalty(); @@ -67,6 +71,22 @@ public abstract class GenerationConfig extends JsonSerializable { @JsonProperty("presencePenalty") public abstract Optional presencePenalty(); + /** + * Optional. Output schema of the generated response. This is an alternative to `response_schema` + * that accepts [JSON Schema](https://json-schema.org/). If set, `response_schema` must be + * omitted, but `response_mime_type` is required. While the full JSON Schema may be sent, not all + * features are supported. Specifically, only the following properties are supported: - `$id` - + * `$defs` - `$ref` - `$anchor` - `type` - `format` - `title` - `description` - `enum` (for + * strings and numbers) - `items` - `prefixItems` - `minItems` - `maxItems` - `minimum` - + * `maximum` - `anyOf` - `oneOf` (interpreted the same as `anyOf`) - `properties` - + * `additionalProperties` - `required` The non-standard `propertyOrdering` property may also be + * set. Cyclic references are unrolled to a limited degree and, as such, may only be used within + * non-required properties. (Nullable properties are not sufficient.) If `$ref` is set on a + * sub-schema, no other properties, except for than those starting as a `$`, may be set. + */ + @JsonProperty("responseJsonSchema") + public abstract Optional responseJsonSchema(); + /** Optional. If true, export the logprobs results in response. */ @JsonProperty("responseLogprobs") public abstract Optional responseLogprobs(); @@ -94,22 +114,6 @@ public abstract class GenerationConfig extends JsonSerializable { @JsonProperty("responseSchema") public abstract Optional responseSchema(); - /** - * Optional. Output schema of the generated response. This is an alternative to `response_schema` - * that accepts [JSON Schema](https://json-schema.org/). If set, `response_schema` must be - * omitted, but `response_mime_type` is required. While the full JSON Schema may be sent, not all - * features are supported. Specifically, only the following properties are supported: - `$id` - - * `$defs` - `$ref` - `$anchor` - `type` - `format` - `title` - `description` - `enum` (for - * strings and numbers) - `items` - `prefixItems` - `minItems` - `maxItems` - `minimum` - - * `maximum` - `anyOf` - `oneOf` (interpreted the same as `anyOf`) - `properties` - - * `additionalProperties` - `required` The non-standard `propertyOrdering` property may also be - * set. Cyclic references are unrolled to a limited degree and, as such, may only be used within - * non-required properties. (Nullable properties are not sufficient.) If `$ref` is set on a - * sub-schema, no other properties, except for than those starting as a `$`, may be set. - */ - @JsonProperty("responseJsonSchema") - public abstract Optional responseJsonSchema(); - /** Optional. Routing configuration. */ @JsonProperty("routingConfig") public abstract Optional routingConfig(); @@ -196,6 +200,15 @@ public Builder modelSelectionConfig(ModelSelectionConfig.Builder modelSelectionC @JsonProperty("candidateCount") public abstract Builder candidateCount(Integer candidateCount); + /** + * Setter for enableAffectiveDialog. + * + *

enableAffectiveDialog: Optional. If enabled, the model will detect emotions and adapt its + * responses accordingly. + */ + @JsonProperty("enableAffectiveDialog") + public abstract Builder enableAffectiveDialog(boolean enableAffectiveDialog); + /** * Setter for frequencyPenalty. * @@ -256,6 +269,25 @@ public Builder mediaResolution(String mediaResolution) { @JsonProperty("presencePenalty") public abstract Builder presencePenalty(Float presencePenalty); + /** + * Setter for responseJsonSchema. + * + *

responseJsonSchema: Optional. Output schema of the generated response. This is an + * alternative to `response_schema` that accepts [JSON Schema](https://json-schema.org/). If + * set, `response_schema` must be omitted, but `response_mime_type` is required. While the full + * JSON Schema may be sent, not all features are supported. Specifically, only the following + * properties are supported: - `$id` - `$defs` - `$ref` - `$anchor` - `type` - `format` - + * `title` - `description` - `enum` (for strings and numbers) - `items` - `prefixItems` - + * `minItems` - `maxItems` - `minimum` - `maximum` - `anyOf` - `oneOf` (interpreted the same as + * `anyOf`) - `properties` - `additionalProperties` - `required` The non-standard + * `propertyOrdering` property may also be set. Cyclic references are unrolled to a limited + * degree and, as such, may only be used within non-required properties. (Nullable properties + * are not sufficient.) If `$ref` is set on a sub-schema, no other properties, except for than + * those starting as a `$`, may be set. + */ + @JsonProperty("responseJsonSchema") + public abstract Builder responseJsonSchema(Object responseJsonSchema); + /** * Setter for responseLogprobs. * @@ -361,25 +393,6 @@ public Builder responseSchema(Schema.Builder responseSchemaBuilder) { return responseSchema(responseSchemaBuilder.build()); } - /** - * Setter for responseJsonSchema. - * - *

responseJsonSchema: Optional. Output schema of the generated response. This is an - * alternative to `response_schema` that accepts [JSON Schema](https://json-schema.org/). If - * set, `response_schema` must be omitted, but `response_mime_type` is required. While the full - * JSON Schema may be sent, not all features are supported. Specifically, only the following - * properties are supported: - `$id` - `$defs` - `$ref` - `$anchor` - `type` - `format` - - * `title` - `description` - `enum` (for strings and numbers) - `items` - `prefixItems` - - * `minItems` - `maxItems` - `minimum` - `maximum` - `anyOf` - `oneOf` (interpreted the same as - * `anyOf`) - `properties` - `additionalProperties` - `required` The non-standard - * `propertyOrdering` property may also be set. Cyclic references are unrolled to a limited - * degree and, as such, may only be used within non-required properties. (Nullable properties - * are not sufficient.) If `$ref` is set on a sub-schema, no other properties, except for than - * those starting as a `$`, may be set. - */ - @JsonProperty("responseJsonSchema") - public abstract Builder responseJsonSchema(Object responseJsonSchema); - /** * Setter for routingConfig. * diff --git a/src/main/java/com/google/genai/types/GroundingSupport.java b/src/main/java/com/google/genai/types/GroundingSupport.java index 0e459303700..4dd2d897560 100644 --- a/src/main/java/com/google/genai/types/GroundingSupport.java +++ b/src/main/java/com/google/genai/types/GroundingSupport.java @@ -32,8 +32,9 @@ @JsonDeserialize(builder = GroundingSupport.Builder.class) public abstract class GroundingSupport extends JsonSerializable { /** - * Confidence score of the support references. Ranges from 0 to 1. 1 is the most confident. This - * list must have the same size as the grounding_chunk_indices. + * Confidence score of the support references. Ranges from 0 to 1. 1 is the most confident. For + * Gemini 2.0 and before, this list must have the same size as the grounding_chunk_indices. For + * Gemini 2.5 and after, this list will be empty and should be ignored. */ @JsonProperty("confidenceScores") public abstract Optional> confidenceScores(); @@ -71,7 +72,9 @@ private static Builder create() { * Setter for confidenceScores. * *

confidenceScores: Confidence score of the support references. Ranges from 0 to 1. 1 is the - * most confident. This list must have the same size as the grounding_chunk_indices. + * most confident. For Gemini 2.0 and before, this list must have the same size as the + * grounding_chunk_indices. For Gemini 2.5 and after, this list will be empty and should be + * ignored. */ @JsonProperty("confidenceScores") public abstract Builder confidenceScores(List confidenceScores); @@ -80,7 +83,9 @@ private static Builder create() { * Setter for confidenceScores. * *

confidenceScores: Confidence score of the support references. Ranges from 0 to 1. 1 is the - * most confident. This list must have the same size as the grounding_chunk_indices. + * most confident. For Gemini 2.0 and before, this list must have the same size as the + * grounding_chunk_indices. For Gemini 2.5 and after, this list will be empty and should be + * ignored. */ public Builder confidenceScores(Float... confidenceScores) { return confidenceScores(Arrays.asList(confidenceScores)); diff --git a/src/main/java/com/google/genai/types/HarmCategory.java b/src/main/java/com/google/genai/types/HarmCategory.java index ae442279c42..290644dcc59 100644 --- a/src/main/java/com/google/genai/types/HarmCategory.java +++ b/src/main/java/com/google/genai/types/HarmCategory.java @@ -46,7 +46,19 @@ public enum Known { /** * Deprecated: Election filter is not longer supported. The harm category is civic integrity. */ - HARM_CATEGORY_CIVIC_INTEGRITY + HARM_CATEGORY_CIVIC_INTEGRITY, + + /** The harm category is image hate. */ + HARM_CATEGORY_IMAGE_HATE, + + /** The harm category is image dangerous content. */ + HARM_CATEGORY_IMAGE_DANGEROUS_CONTENT, + + /** The harm category is image harassment. */ + HARM_CATEGORY_IMAGE_HARASSMENT, + + /** The harm category is image sexually explicit content. */ + HARM_CATEGORY_IMAGE_SEXUALLY_EXPLICIT } private Known harmCategoryEnum; diff --git a/src/main/java/com/google/genai/types/Retrieval.java b/src/main/java/com/google/genai/types/Retrieval.java index c70feb2ec21..d98e2e6ecb1 100644 --- a/src/main/java/com/google/genai/types/Retrieval.java +++ b/src/main/java/com/google/genai/types/Retrieval.java @@ -33,6 +33,10 @@ public abstract class Retrieval extends JsonSerializable { @JsonProperty("disableAttribution") public abstract Optional disableAttribution(); + /** Use data source powered by external API for grounding. */ + @JsonProperty("externalApi") + public abstract Optional externalApi(); + /** Set to use data source powered by Vertex AI Search. */ @JsonProperty("vertexAiSearch") public abstract Optional vertexAiSearch(); @@ -69,6 +73,23 @@ private static Builder create() { @JsonProperty("disableAttribution") public abstract Builder disableAttribution(boolean disableAttribution); + /** + * Setter for externalApi. + * + *

externalApi: Use data source powered by external API for grounding. + */ + @JsonProperty("externalApi") + public abstract Builder externalApi(ExternalApi externalApi); + + /** + * Setter for externalApi builder. + * + *

externalApi: Use data source powered by external API for grounding. + */ + public Builder externalApi(ExternalApi.Builder externalApiBuilder) { + return externalApi(externalApiBuilder.build()); + } + /** * Setter for vertexAiSearch. * diff --git a/src/main/java/com/google/genai/types/SafetyRating.java b/src/main/java/com/google/genai/types/SafetyRating.java index c5ca95faa1e..e215792912a 100644 --- a/src/main/java/com/google/genai/types/SafetyRating.java +++ b/src/main/java/com/google/genai/types/SafetyRating.java @@ -38,6 +38,14 @@ public abstract class SafetyRating extends JsonSerializable { @JsonProperty("category") public abstract Optional category(); + /** + * Output only. The overwritten threshold for the safety category of Gemini 2.0 image out. If + * minors are detected in the output image, the threshold of each safety category will be + * overwritten if user sets a lower threshold. + */ + @JsonProperty("overwrittenThreshold") + public abstract Optional overwrittenThreshold(); + /** Output only. Harm probability levels in the content. */ @JsonProperty("probability") public abstract Optional probability(); @@ -108,6 +116,40 @@ public Builder category(String category) { return category(new HarmCategory(category)); } + /** + * Setter for overwrittenThreshold. + * + *

overwrittenThreshold: Output only. The overwritten threshold for the safety category of + * Gemini 2.0 image out. If minors are detected in the output image, the threshold of each + * safety category will be overwritten if user sets a lower threshold. + */ + @JsonProperty("overwrittenThreshold") + public abstract Builder overwrittenThreshold(HarmBlockThreshold overwrittenThreshold); + + /** + * Setter for overwrittenThreshold given a known enum. + * + *

overwrittenThreshold: Output only. The overwritten threshold for the safety category of + * Gemini 2.0 image out. If minors are detected in the output image, the threshold of each + * safety category will be overwritten if user sets a lower threshold. + */ + @CanIgnoreReturnValue + public Builder overwrittenThreshold(HarmBlockThreshold.Known knownType) { + return overwrittenThreshold(new HarmBlockThreshold(knownType)); + } + + /** + * Setter for overwrittenThreshold given a string. + * + *

overwrittenThreshold: Output only. The overwritten threshold for the safety category of + * Gemini 2.0 image out. If minors are detected in the output image, the threshold of each + * safety category will be overwritten if user sets a lower threshold. + */ + @CanIgnoreReturnValue + public Builder overwrittenThreshold(String overwrittenThreshold) { + return overwrittenThreshold(new HarmBlockThreshold(overwrittenThreshold)); + } + /** * Setter for probability. * diff --git a/src/main/java/com/google/genai/types/Tool.java b/src/main/java/com/google/genai/types/Tool.java index 66ef3f7f063..7c81f57e17d 100644 --- a/src/main/java/com/google/genai/types/Tool.java +++ b/src/main/java/com/google/genai/types/Tool.java @@ -86,6 +86,13 @@ public abstract class Tool extends JsonSerializable { @JsonProperty("codeExecution") public abstract Optional codeExecution(); + /** + * Optional. Tool to support the model interacting directly with the computer. If enabled, it + * automatically populates computer-use specific Function Declarations. + */ + @JsonProperty("computerUse") + public abstract Optional computerUse(); + /** Instantiates a builder for Tool. */ public static Builder builder() { return new AutoValue_Tool.Builder(); @@ -286,6 +293,25 @@ public Builder codeExecution(ToolCodeExecution.Builder codeExecutionBuilder) { return codeExecution(codeExecutionBuilder.build()); } + /** + * Setter for computerUse. + * + *

computerUse: Optional. Tool to support the model interacting directly with the computer. + * If enabled, it automatically populates computer-use specific Function Declarations. + */ + @JsonProperty("computerUse") + public abstract Builder computerUse(ToolComputerUse computerUse); + + /** + * Setter for computerUse builder. + * + *

computerUse: Optional. Tool to support the model interacting directly with the computer. + * If enabled, it automatically populates computer-use specific Function Declarations. + */ + public Builder computerUse(ToolComputerUse.Builder computerUseBuilder) { + return computerUse(computerUseBuilder.build()); + } + public abstract Tool build(); } diff --git a/src/main/java/com/google/genai/types/ToolComputerUse.java b/src/main/java/com/google/genai/types/ToolComputerUse.java new file mode 100644 index 00000000000..45b18fa995e --- /dev/null +++ b/src/main/java/com/google/genai/types/ToolComputerUse.java @@ -0,0 +1,89 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Auto-generated code. Do not edit. + +package com.google.genai.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.google.auto.value.AutoValue; +import com.google.errorprone.annotations.CanIgnoreReturnValue; +import com.google.genai.JsonSerializable; +import java.util.Optional; + +/** Tool to support computer use. */ +@AutoValue +@JsonDeserialize(builder = ToolComputerUse.Builder.class) +public abstract class ToolComputerUse extends JsonSerializable { + /** Required. The environment being operated. */ + @JsonProperty("environment") + public abstract Optional environment(); + + /** Instantiates a builder for ToolComputerUse. */ + public static Builder builder() { + return new AutoValue_ToolComputerUse.Builder(); + } + + /** Creates a builder with the same values as this instance. */ + public abstract Builder toBuilder(); + + /** Builder for ToolComputerUse. */ + @AutoValue.Builder + public abstract static class Builder { + /** For internal usage. Please use `ToolComputerUse.builder()` for instantiation. */ + @JsonCreator + private static Builder create() { + return new AutoValue_ToolComputerUse.Builder(); + } + + /** + * Setter for environment. + * + *

environment: Required. The environment being operated. + */ + @JsonProperty("environment") + public abstract Builder environment(Environment environment); + + /** + * Setter for environment given a known enum. + * + *

environment: Required. The environment being operated. + */ + @CanIgnoreReturnValue + public Builder environment(Environment.Known knownType) { + return environment(new Environment(knownType)); + } + + /** + * Setter for environment given a string. + * + *

environment: Required. The environment being operated. + */ + @CanIgnoreReturnValue + public Builder environment(String environment) { + return environment(new Environment(environment)); + } + + public abstract ToolComputerUse build(); + } + + /** Deserializes a JSON string to a ToolComputerUse object. */ + public static ToolComputerUse fromJson(String jsonString) { + return JsonSerializable.fromJsonString(jsonString, ToolComputerUse.class); + } +} From 7f4c6bf58804764d568bd3412086ead75a388df0 Mon Sep 17 00:00:00 2001 From: Amy Wu Date: Tue, 1 Jul 2025 10:20:15 -0700 Subject: [PATCH 048/602] feat: Support different media input in Vertex Live API PiperOrigin-RevId: 778094801 --- .../java/com/google/genai/LiveConverters.java | 48 ++++++++++++++----- .../genai/types/LiveServerSetupComplete.java | 14 ++++++ .../com/google/genai/LiveConvertersTest.java | 27 +++++------ 3 files changed, 61 insertions(+), 28 deletions(-) diff --git a/src/main/java/com/google/genai/LiveConverters.java b/src/main/java/com/google/genai/LiveConverters.java index d9c0ca79e3e..499689287a5 100644 --- a/src/main/java/com/google/genai/LiveConverters.java +++ b/src/main/java/com/google/genai/LiveConverters.java @@ -1930,8 +1930,11 @@ ObjectNode liveSendRealtimeInputParametersToVertex(JsonNode fromObject, ObjectNo Transformers.tBlobs(Common.getValueByPath(fromObject, new String[] {"media"}))); } - if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"audio"}))) { - throw new IllegalArgumentException("audio parameter is not supported in Vertex AI."); + if (Common.getValueByPath(fromObject, new String[] {"audio"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"audio"}, + Transformers.tAudioBlob(Common.getValueByPath(fromObject, new String[] {"audio"}))); } if (Common.getValueByPath(fromObject, new String[] {"audioStreamEnd"}) != null) { @@ -1941,12 +1944,18 @@ ObjectNode liveSendRealtimeInputParametersToVertex(JsonNode fromObject, ObjectNo Common.getValueByPath(fromObject, new String[] {"audioStreamEnd"})); } - if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"video"}))) { - throw new IllegalArgumentException("video parameter is not supported in Vertex AI."); + if (Common.getValueByPath(fromObject, new String[] {"video"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"video"}, + Transformers.tImageBlob(Common.getValueByPath(fromObject, new String[] {"video"}))); } - if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"text"}))) { - throw new IllegalArgumentException("text parameter is not supported in Vertex AI."); + if (Common.getValueByPath(fromObject, new String[] {"text"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"text"}, + Common.getValueByPath(fromObject, new String[] {"text"})); } if (Common.getValueByPath(fromObject, new String[] {"activityStart"}) != null) { @@ -2299,20 +2308,29 @@ ObjectNode liveClientRealtimeInputToVertex(JsonNode fromObject, ObjectNode paren Common.getValueByPath(fromObject, new String[] {"mediaChunks"})); } - if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"audio"}))) { - throw new IllegalArgumentException("audio parameter is not supported in Vertex AI."); + if (Common.getValueByPath(fromObject, new String[] {"audio"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"audio"}, + Common.getValueByPath(fromObject, new String[] {"audio"})); } if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"audioStreamEnd"}))) { throw new IllegalArgumentException("audioStreamEnd parameter is not supported in Vertex AI."); } - if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"video"}))) { - throw new IllegalArgumentException("video parameter is not supported in Vertex AI."); + if (Common.getValueByPath(fromObject, new String[] {"video"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"video"}, + Common.getValueByPath(fromObject, new String[] {"video"})); } - if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"text"}))) { - throw new IllegalArgumentException("text parameter is not supported in Vertex AI."); + if (Common.getValueByPath(fromObject, new String[] {"text"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"text"}, + Common.getValueByPath(fromObject, new String[] {"text"})); } if (Common.getValueByPath(fromObject, new String[] {"activityStart"}) != null) { @@ -2568,6 +2586,12 @@ ObjectNode liveServerSetupCompleteFromMldev(JsonNode fromObject, ObjectNode pare @ExcludeFromGeneratedCoverageReport ObjectNode liveServerSetupCompleteFromVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"sessionId"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"sessionId"}, + Common.getValueByPath(fromObject, new String[] {"sessionId"})); + } return toObject; } diff --git a/src/main/java/com/google/genai/types/LiveServerSetupComplete.java b/src/main/java/com/google/genai/types/LiveServerSetupComplete.java index f6c6bf37ce1..ebf53b7feee 100644 --- a/src/main/java/com/google/genai/types/LiveServerSetupComplete.java +++ b/src/main/java/com/google/genai/types/LiveServerSetupComplete.java @@ -19,14 +19,20 @@ package com.google.genai.types; import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.google.auto.value.AutoValue; import com.google.genai.JsonSerializable; +import java.util.Optional; /** Sent in response to a `LiveGenerateContentSetup` message from the client. */ @AutoValue @JsonDeserialize(builder = LiveServerSetupComplete.Builder.class) public abstract class LiveServerSetupComplete extends JsonSerializable { + /** The session id of the live session. */ + @JsonProperty("sessionId") + public abstract Optional sessionId(); + /** Instantiates a builder for LiveServerSetupComplete. */ public static Builder builder() { return new AutoValue_LiveServerSetupComplete.Builder(); @@ -44,6 +50,14 @@ private static Builder create() { return new AutoValue_LiveServerSetupComplete.Builder(); } + /** + * Setter for sessionId. + * + *

sessionId: The session id of the live session. + */ + @JsonProperty("sessionId") + public abstract Builder sessionId(String sessionId); + public abstract LiveServerSetupComplete build(); } diff --git a/src/test/java/com/google/genai/LiveConvertersTest.java b/src/test/java/com/google/genai/LiveConvertersTest.java index 121b2b2a3e0..69b473ba1f7 100644 --- a/src/test/java/com/google/genai/LiveConvertersTest.java +++ b/src/test/java/com/google/genai/LiveConvertersTest.java @@ -89,14 +89,11 @@ public void testLiveSendRealtimeInputParameters_Text_okay() { final LiveConverters vertexLiveConverters = new LiveConverters(GEMINI_API_CLIENT); - assertThrows( - IllegalArgumentException.class, // Expected exception type - () -> - vertexLiveConverters.liveClientMessageToVertex( - JsonSerializable.toJsonNode(message), - JsonSerializable.objectMapper - .createObjectNode()) // Code that should throw the exception - ); + ObjectNode transformedVertex = + vertexLiveConverters.liveClientMessageToVertex( + JsonSerializable.toJsonNode(message), JsonSerializable.objectMapper.createObjectNode()); + + assertEquals(transformedVertex.get("realtime_input").get("text").asText(), "test"); } @Test @@ -122,14 +119,12 @@ public void testLiveSendRealtimeInputParameters_Audio_okay() { final LiveConverters vertexLiveConverters = new LiveConverters(GEMINI_API_CLIENT); - assertThrows( - IllegalArgumentException.class, // Expected exception type - () -> - vertexLiveConverters.liveClientMessageToVertex( - JsonSerializable.toJsonNode(message), - JsonSerializable.objectMapper - .createObjectNode()) // Code that should throw the exception - ); + ObjectNode transformedVertex = + vertexLiveConverters.liveClientMessageToVertex( + JsonSerializable.toJsonNode(message), JsonSerializable.objectMapper.createObjectNode()); + + assertEquals( + transformedVertex.get("realtime_input").get("audio").get("mimeType").asText(), "audio/mp3"); } @Test From 782465d9c85c3637586fef490983771c4b4b5df0 Mon Sep 17 00:00:00 2001 From: Amy Wu Date: Tue, 1 Jul 2025 14:23:54 -0700 Subject: [PATCH 049/602] feat: Support Batches delete PiperOrigin-RevId: 778190298 --- .../java/com/google/genai/AsyncBatches.java | 18 +- src/main/java/com/google/genai/Batches.java | 181 +++++++++++++++++- .../genai/types/DeleteBatchJobConfig.java | 77 ++++++++ .../genai/types/DeleteBatchJobParameters.java | 97 ++++++++++ .../google/genai/types/DeleteResourceJob.java | 101 ++++++++++ 5 files changed, 470 insertions(+), 4 deletions(-) create mode 100644 src/main/java/com/google/genai/types/DeleteBatchJobConfig.java create mode 100644 src/main/java/com/google/genai/types/DeleteBatchJobParameters.java create mode 100644 src/main/java/com/google/genai/types/DeleteResourceJob.java diff --git a/src/main/java/com/google/genai/AsyncBatches.java b/src/main/java/com/google/genai/AsyncBatches.java index 84b21b6c549..f5f61ba3a62 100644 --- a/src/main/java/com/google/genai/AsyncBatches.java +++ b/src/main/java/com/google/genai/AsyncBatches.java @@ -25,6 +25,8 @@ import com.google.genai.types.BatchJobSource; import com.google.genai.types.CancelBatchJobConfig; import com.google.genai.types.CreateBatchJobConfig; +import com.google.genai.types.DeleteBatchJobConfig; +import com.google.genai.types.DeleteResourceJob; import com.google.genai.types.GetBatchJobConfig; import com.google.genai.types.ListBatchJobsConfig; import java.util.concurrent.CompletableFuture; @@ -43,7 +45,7 @@ public AsyncBatches(ApiClient apiClient) { * * @param name A fully-qualified BatchJob resource name or ID. Example: * "projects/.../locations/.../batchPredictionJobs/456" or "456" when project and location are - * initialized in the Vertex AI client. Or "files/abc" using the Gemini Developer AI client. + * initialized in the Vertex AI client. Or "batches/abc" using the Gemini Developer AI client. * @param config A {@link GetBatchJobConfig} for configuring the get request. * @return A {@link BatchJob} object that contains the info of the batch job. */ @@ -56,13 +58,25 @@ public CompletableFuture get(String name, GetBatchJobConfig config) { * * @param name A fully-qualified BatchJob resource name or ID. Example: * "projects/.../locations/.../batchPredictionJobs/456" or "456" when project and location are - * initialized in the Vertex AI client. Or "files/abc" using the Gemini Developer AI client. + * initialized in the Vertex AI client. Or "batches/abc" using the Gemini Developer AI client. * @param config A {@link CancelBatchJobConfig} for configuring the cancel request. */ public CompletableFuture cancel(String name, CancelBatchJobConfig config) { return CompletableFuture.runAsync(() -> batches.cancel(name, config)); } + /** + * Asynchronously deletes a batch job resource. + * + * @param name A fully-qualified BatchJob resource name or ID. Example: + * "projects/.../locations/.../batchPredictionJobs/456" or "456" when project and location are + * initialized in the Vertex AI client. Or "batches/abc" using the Gemini Developer AI client. + * @param config A {@link DeleteBatchJobConfig} for configuring the delete request. + */ + public CompletableFuture delete(String name, DeleteBatchJobConfig config) { + return CompletableFuture.supplyAsync(() -> batches.delete(name, config)); + } + /** * Asynchronously creates a batch job. * diff --git a/src/main/java/com/google/genai/Batches.java b/src/main/java/com/google/genai/Batches.java index 02953f0f679..7dd8c7bdfa1 100644 --- a/src/main/java/com/google/genai/Batches.java +++ b/src/main/java/com/google/genai/Batches.java @@ -29,6 +29,9 @@ import com.google.genai.types.CancelBatchJobParameters; import com.google.genai.types.CreateBatchJobConfig; import com.google.genai.types.CreateBatchJobParameters; +import com.google.genai.types.DeleteBatchJobConfig; +import com.google.genai.types.DeleteBatchJobParameters; +import com.google.genai.types.DeleteResourceJob; import com.google.genai.types.GetBatchJobConfig; import com.google.genai.types.GetBatchJobParameters; import com.google.genai.types.HttpOptions; @@ -1628,6 +1631,28 @@ ObjectNode listBatchJobsParametersToMldev(JsonNode fromObject, ObjectNode parent return toObject; } + @ExcludeFromGeneratedCoverageReport + ObjectNode deleteBatchJobParametersToMldev( + ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"name"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"_url", "name"}, + Transformers.tBatchJobName( + this.apiClient, Common.getValueByPath(fromObject, new String[] {"name"}))); + } + + if (Common.getValueByPath(fromObject, new String[] {"config"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"config"}, + Common.getValueByPath(fromObject, new String[] {"config"})); + } + + return toObject; + } + @ExcludeFromGeneratedCoverageReport ObjectNode videoMetadataToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); @@ -3220,6 +3245,28 @@ ObjectNode listBatchJobsParametersToVertex(JsonNode fromObject, ObjectNode paren return toObject; } + @ExcludeFromGeneratedCoverageReport + ObjectNode deleteBatchJobParametersToVertex( + ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"name"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"_url", "name"}, + Transformers.tBatchJobName( + this.apiClient, Common.getValueByPath(fromObject, new String[] {"name"}))); + } + + if (Common.getValueByPath(fromObject, new String[] {"config"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"config"}, + Common.getValueByPath(fromObject, new String[] {"config"})); + } + + return toObject; + } + @ExcludeFromGeneratedCoverageReport ObjectNode jobErrorFromMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); @@ -4652,6 +4699,36 @@ ObjectNode listBatchJobsResponseFromMldev(JsonNode fromObject, ObjectNode parent return toObject; } + @ExcludeFromGeneratedCoverageReport + ObjectNode deleteResourceJobFromMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"name"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"name"}, + Common.getValueByPath(fromObject, new String[] {"name"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"done"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"done"}, + Common.getValueByPath(fromObject, new String[] {"done"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"error"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"error"}, + jobErrorFromMldev( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"error"})), + toObject)); + } + + return toObject; + } + @ExcludeFromGeneratedCoverageReport ObjectNode jobErrorFromVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); @@ -6154,6 +6231,36 @@ ObjectNode listBatchJobsResponseFromVertex(JsonNode fromObject, ObjectNode paren return toObject; } + @ExcludeFromGeneratedCoverageReport + ObjectNode deleteResourceJobFromVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"name"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"name"}, + Common.getValueByPath(fromObject, new String[] {"name"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"done"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"done"}, + Common.getValueByPath(fromObject, new String[] {"done"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"error"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"error"}, + jobErrorFromVertex( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"error"})), + toObject)); + } + + return toObject; + } + BatchJob privateCreate(String model, BatchJobSource src, CreateBatchJobConfig config) { CreateBatchJobParameters.Builder parameterBuilder = CreateBatchJobParameters.builder(); @@ -6224,7 +6331,7 @@ BatchJob privateCreate(String model, BatchJobSource src, CreateBatchJobConfig co * * @param name A fully-qualified BatchJob resource name or ID. Example: * "projects/.../locations/.../batchPredictionJobs/456" or "456" when project and location are - * initialized in the Vertex AI client. Or "files/abc" using the Gemini Developer AI client. + * initialized in the Vertex AI client. Or "batches/abc" using the Gemini Developer AI client. * @param config A {@link GetBatchJobConfig} for configuring the get request. * @return A {@link BatchJob} object that contains the info of the batch job. */ @@ -6295,7 +6402,7 @@ public BatchJob get(String name, GetBatchJobConfig config) { * * @param name A fully-qualified BatchJob resource name or ID. Example: * "projects/.../locations/.../batchPredictionJobs/456" or "456" when project and location are - * initialized in the Vertex AI client. Or "files/abc" using the Gemini Developer AI client. + * initialized in the Vertex AI client. Or "batches/abc" using the Gemini Developer AI client. * @param config A {@link CancelBatchJobConfig} for configuring the cancel request. */ public void cancel(String name, CancelBatchJobConfig config) { @@ -6401,6 +6508,76 @@ ListBatchJobsResponse privateList(ListBatchJobsConfig config) { } } + /** + * Deletes a batch job resource. + * + * @param name A fully-qualified BatchJob resource name or ID. Example: + * "projects/.../locations/.../batchPredictionJobs/456" or "456" when project and location are + * initialized in the Vertex AI client. Or "batches/abc" using the Gemini Developer AI client. + * @param config A {@link DeleteBatchJobConfig} for configuring the delete request. + */ + public DeleteResourceJob delete(String name, DeleteBatchJobConfig config) { + + DeleteBatchJobParameters.Builder parameterBuilder = DeleteBatchJobParameters.builder(); + + if (!Common.isZero(name)) { + parameterBuilder.name(name); + } + if (!Common.isZero(config)) { + parameterBuilder.config(config); + } + JsonNode parameterNode = JsonSerializable.toJsonNode(parameterBuilder.build()); + + ObjectNode body; + String path; + if (this.apiClient.vertexAI()) { + body = deleteBatchJobParametersToVertex(this.apiClient, parameterNode, null); + path = Common.formatMap("batchPredictionJobs/{name}", body.get("_url")); + } else { + body = deleteBatchJobParametersToMldev(this.apiClient, parameterNode, null); + if (body.get("_url") != null) { + path = Common.formatMap("batches/{name}", body.get("_url")); + } else { + path = "batches/{name}"; + } + } + body.remove("_url"); + + JsonNode queryParams = body.get("_query"); + if (queryParams != null) { + body.remove("_query"); + path = String.format("%s?%s", path, Common.urlEncode((ObjectNode) queryParams)); + } + + // TODO: Remove the hack that removes config. + body.remove("config"); + + Optional requestHttpOptions = Optional.empty(); + if (config != null) { + requestHttpOptions = config.httpOptions(); + } + + try (ApiResponse response = + this.apiClient.request( + "delete", path, JsonSerializable.toJsonString(body), requestHttpOptions)) { + HttpEntity entity = response.getEntity(); + String responseString; + try { + responseString = EntityUtils.toString(entity); + } catch (IOException e) { + throw new GenAiIOException("Failed to read HTTP response.", e); + } + + JsonNode responseNode = JsonSerializable.stringToJsonNode(responseString); + if (this.apiClient.vertexAI()) { + responseNode = deleteResourceJobFromVertex(responseNode, null); + } else { + responseNode = deleteResourceJobFromMldev(responseNode, null); + } + return JsonSerializable.fromJsonNode(responseNode, DeleteResourceJob.class); + } + } + /** * Makes an API request to create the batch job. * diff --git a/src/main/java/com/google/genai/types/DeleteBatchJobConfig.java b/src/main/java/com/google/genai/types/DeleteBatchJobConfig.java new file mode 100644 index 00000000000..638197ccef4 --- /dev/null +++ b/src/main/java/com/google/genai/types/DeleteBatchJobConfig.java @@ -0,0 +1,77 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Auto-generated code. Do not edit. + +package com.google.genai.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.google.auto.value.AutoValue; +import com.google.genai.JsonSerializable; +import java.util.Optional; + +/** Optional parameters for models.get method. */ +@AutoValue +@JsonDeserialize(builder = DeleteBatchJobConfig.Builder.class) +public abstract class DeleteBatchJobConfig extends JsonSerializable { + /** Used to override HTTP request options. */ + @JsonProperty("httpOptions") + public abstract Optional httpOptions(); + + /** Instantiates a builder for DeleteBatchJobConfig. */ + public static Builder builder() { + return new AutoValue_DeleteBatchJobConfig.Builder(); + } + + /** Creates a builder with the same values as this instance. */ + public abstract Builder toBuilder(); + + /** Builder for DeleteBatchJobConfig. */ + @AutoValue.Builder + public abstract static class Builder { + /** For internal usage. Please use `DeleteBatchJobConfig.builder()` for instantiation. */ + @JsonCreator + private static Builder create() { + return new AutoValue_DeleteBatchJobConfig.Builder(); + } + + /** + * Setter for httpOptions. + * + *

httpOptions: Used to override HTTP request options. + */ + @JsonProperty("httpOptions") + public abstract Builder httpOptions(HttpOptions httpOptions); + + /** + * Setter for httpOptions builder. + * + *

httpOptions: Used to override HTTP request options. + */ + public Builder httpOptions(HttpOptions.Builder httpOptionsBuilder) { + return httpOptions(httpOptionsBuilder.build()); + } + + public abstract DeleteBatchJobConfig build(); + } + + /** Deserializes a JSON string to a DeleteBatchJobConfig object. */ + public static DeleteBatchJobConfig fromJson(String jsonString) { + return JsonSerializable.fromJsonString(jsonString, DeleteBatchJobConfig.class); + } +} diff --git a/src/main/java/com/google/genai/types/DeleteBatchJobParameters.java b/src/main/java/com/google/genai/types/DeleteBatchJobParameters.java new file mode 100644 index 00000000000..27807fea35a --- /dev/null +++ b/src/main/java/com/google/genai/types/DeleteBatchJobParameters.java @@ -0,0 +1,97 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Auto-generated code. Do not edit. + +package com.google.genai.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.google.api.core.InternalApi; +import com.google.auto.value.AutoValue; +import com.google.genai.JsonSerializable; +import java.util.Optional; + +/** Config for batches.delete parameters. */ +@AutoValue +@InternalApi +@JsonDeserialize(builder = DeleteBatchJobParameters.Builder.class) +public abstract class DeleteBatchJobParameters extends JsonSerializable { + /** + * A fully-qualified BatchJob resource name or ID. Example: + * "projects/.../locations/.../batchPredictionJobs/456" or "456" when project and location are + * initialized in the client. + */ + @JsonProperty("name") + public abstract Optional name(); + + /** Optional parameters for the request. */ + @JsonProperty("config") + public abstract Optional config(); + + /** Instantiates a builder for DeleteBatchJobParameters. */ + public static Builder builder() { + return new AutoValue_DeleteBatchJobParameters.Builder(); + } + + /** Creates a builder with the same values as this instance. */ + public abstract Builder toBuilder(); + + /** Builder for DeleteBatchJobParameters. */ + @AutoValue.Builder + public abstract static class Builder { + /** For internal usage. Please use `DeleteBatchJobParameters.builder()` for instantiation. */ + @JsonCreator + private static Builder create() { + return new AutoValue_DeleteBatchJobParameters.Builder(); + } + + /** + * Setter for name. + * + *

name: A fully-qualified BatchJob resource name or ID. Example: + * "projects/.../locations/.../batchPredictionJobs/456" or "456" when project and location are + * initialized in the client. + */ + @JsonProperty("name") + public abstract Builder name(String name); + + /** + * Setter for config. + * + *

config: Optional parameters for the request. + */ + @JsonProperty("config") + public abstract Builder config(DeleteBatchJobConfig config); + + /** + * Setter for config builder. + * + *

config: Optional parameters for the request. + */ + public Builder config(DeleteBatchJobConfig.Builder configBuilder) { + return config(configBuilder.build()); + } + + public abstract DeleteBatchJobParameters build(); + } + + /** Deserializes a JSON string to a DeleteBatchJobParameters object. */ + public static DeleteBatchJobParameters fromJson(String jsonString) { + return JsonSerializable.fromJsonString(jsonString, DeleteBatchJobParameters.class); + } +} diff --git a/src/main/java/com/google/genai/types/DeleteResourceJob.java b/src/main/java/com/google/genai/types/DeleteResourceJob.java new file mode 100644 index 00000000000..e3bc5e40fc9 --- /dev/null +++ b/src/main/java/com/google/genai/types/DeleteResourceJob.java @@ -0,0 +1,101 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Auto-generated code. Do not edit. + +package com.google.genai.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.google.auto.value.AutoValue; +import com.google.genai.JsonSerializable; +import java.util.Optional; + +/** The return value of delete operation. */ +@AutoValue +@JsonDeserialize(builder = DeleteResourceJob.Builder.class) +public abstract class DeleteResourceJob extends JsonSerializable { + /** */ + @JsonProperty("name") + public abstract Optional name(); + + /** */ + @JsonProperty("done") + public abstract Optional done(); + + /** */ + @JsonProperty("error") + public abstract Optional error(); + + /** Instantiates a builder for DeleteResourceJob. */ + public static Builder builder() { + return new AutoValue_DeleteResourceJob.Builder(); + } + + /** Creates a builder with the same values as this instance. */ + public abstract Builder toBuilder(); + + /** Builder for DeleteResourceJob. */ + @AutoValue.Builder + public abstract static class Builder { + /** For internal usage. Please use `DeleteResourceJob.builder()` for instantiation. */ + @JsonCreator + private static Builder create() { + return new AutoValue_DeleteResourceJob.Builder(); + } + + /** + * Setter for name. + * + *

name: + */ + @JsonProperty("name") + public abstract Builder name(String name); + + /** + * Setter for done. + * + *

done: + */ + @JsonProperty("done") + public abstract Builder done(boolean done); + + /** + * Setter for error. + * + *

error: + */ + @JsonProperty("error") + public abstract Builder error(JobError error); + + /** + * Setter for error builder. + * + *

error: + */ + public Builder error(JobError.Builder errorBuilder) { + return error(errorBuilder.build()); + } + + public abstract DeleteResourceJob build(); + } + + /** Deserializes a JSON string to a DeleteResourceJob object. */ + public static DeleteResourceJob fromJson(String jsonString) { + return JsonSerializable.fromJsonString(jsonString, DeleteResourceJob.class); + } +} From 335822769bc2cb25e94ef1f5c9e075c8dcb67999 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Tue, 1 Jul 2025 15:35:29 -0700 Subject: [PATCH 050/602] chore(main): release 1.7.0 (#369) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- .release-please-manifest.json | 2 +- CHANGELOG.md | 13 +++++++++++++ examples/pom.xml | 2 +- pom.xml | 2 +- 4 files changed, 16 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 7deae33804b..cce9d1c6d3e 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "1.6.0" + ".": "1.7.0" } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 15347abbbd1..fe80fdc6c1e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,18 @@ # Changelog +## [1.7.0](https://github.com/googleapis/java-genai/compare/v1.6.0...v1.7.0) (2025-07-01) + + +### Features + +* Support Batches delete ([782465d](https://github.com/googleapis/java-genai/commit/782465d9c85c3637586fef490983771c4b4b5df0)) +* Support different media input in Vertex Live API ([7f4c6bf](https://github.com/googleapis/java-genai/commit/7f4c6bf58804764d568bd3412086ead75a388df0)) + + +### Bug Fixes + +* Remove default timeout ([d1f6201](https://github.com/googleapis/java-genai/commit/d1f6201892de9f37b913044dd494c68b81bcc13a)) + ## [1.6.0](https://github.com/googleapis/java-genai/compare/v1.5.0...v1.6.0) (2025-06-25) diff --git a/examples/pom.xml b/examples/pom.xml index 7391b5e960a..ddc9794d259 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -5,7 +5,7 @@ com.google.genai.examples google-genai-examples - 1.7.0-SNAPSHOT + 1.7.0 google-genai-examples diff --git a/pom.xml b/pom.xml index a3c2899b88c..96582129674 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ com.google.genai google-genai google-genai - 1.7.0-SNAPSHOT + 1.7.0 jar Java idiomatic SDK for the Gemini Developer APIs and Vertex AI APIs. From 687ced198f73c88dadbc0772e0127d3e08d736f9 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Tue, 1 Jul 2025 15:55:13 -0700 Subject: [PATCH 051/602] chore(main): release 1.8.0-SNAPSHOT (#377) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- examples/pom.xml | 2 +- pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/pom.xml b/examples/pom.xml index ddc9794d259..1430a782abd 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -5,7 +5,7 @@ com.google.genai.examples google-genai-examples - 1.7.0 + 1.8.0-SNAPSHOT google-genai-examples diff --git a/pom.xml b/pom.xml index 96582129674..3dac4a87e24 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ com.google.genai google-genai google-genai - 1.7.0 + 1.8.0-SNAPSHOT jar Java idiomatic SDK for the Gemini Developer APIs and Vertex AI APIs. From c80bf1865274d0f97d29c3104572fef9d144dd7b Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Tue, 1 Jul 2025 15:49:09 -0700 Subject: [PATCH 052/602] Copybara import of the project: -- 99827b59ecc85b140ec4ca1f00aa87bba335257d by release-please[bot] <55107282+release-please[bot]@users.noreply.github.com>: chore(main): release 1.7.0 COPYBARA_INTEGRATE_REVIEW=https://github.com/googleapis/java-genai/pull/369 from googleapis:release-please--branches--main 99827b59ecc85b140ec4ca1f00aa87bba335257d PiperOrigin-RevId: 778221958 --- examples/pom.xml | 2 +- pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/pom.xml b/examples/pom.xml index 1430a782abd..ddc9794d259 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -5,7 +5,7 @@ com.google.genai.examples google-genai-examples - 1.8.0-SNAPSHOT + 1.7.0 google-genai-examples diff --git a/pom.xml b/pom.xml index 3dac4a87e24..96582129674 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ com.google.genai google-genai google-genai - 1.8.0-SNAPSHOT + 1.7.0 jar Java idiomatic SDK for the Gemini Developer APIs and Vertex AI APIs. From 741971e5123f7391141fd39504b812041d314417 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Tue, 1 Jul 2025 16:12:38 -0700 Subject: [PATCH 053/602] Copybara import of the project: -- 335822769bc2cb25e94ef1f5c9e075c8dcb67999 by release-please[bot] <55107282+release-please[bot]@users.noreply.github.com>: chore(main): release 1.7.0 (#369) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> -- 13b6e75ccc90af5f0525853fd44316520af93a7a by release-please[bot] <55107282+release-please[bot]@users.noreply.github.com>: chore(main): release 1.8.0-SNAPSHOT COPYBARA_INTEGRATE_REVIEW=https://github.com/googleapis/java-genai/pull/377 from googleapis:release-please--branches--main 13b6e75ccc90af5f0525853fd44316520af93a7a PiperOrigin-RevId: 778230162 --- examples/pom.xml | 2 +- pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/pom.xml b/examples/pom.xml index ddc9794d259..1430a782abd 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -5,7 +5,7 @@ com.google.genai.examples google-genai-examples - 1.7.0 + 1.8.0-SNAPSHOT google-genai-examples diff --git a/pom.xml b/pom.xml index 96582129674..3dac4a87e24 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ com.google.genai google-genai google-genai - 1.7.0 + 1.8.0-SNAPSHOT jar Java idiomatic SDK for the Gemini Developer APIs and Vertex AI APIs. From 2a6f78c3f01ce3cc8ddd060348c224ef052f29d1 Mon Sep 17 00:00:00 2001 From: Annie Luc Date: Tue, 1 Jul 2025 16:27:10 -0700 Subject: [PATCH 054/602] chore: Update package version in README and ApiClient PiperOrigin-RevId: 778235467 --- README.md | 2 +- examples/pom.xml | 2 +- src/main/java/com/google/genai/ApiClient.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 425e53a5e4b..8df26fc78d8 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ If you're using Maven, add the following to your dependencies: com.google.genai google-genai - 1.6.0 + 1.7.0 ``` diff --git a/examples/pom.xml b/examples/pom.xml index 1430a782abd..3bcd3dcfd6f 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -13,7 +13,7 @@ 1.8 1.8 - 1.7.0-SNAPSHOT + 1.8.0-SNAPSHOT diff --git a/src/main/java/com/google/genai/ApiClient.java b/src/main/java/com/google/genai/ApiClient.java index 65aed598139..69a8fb2423b 100644 --- a/src/main/java/com/google/genai/ApiClient.java +++ b/src/main/java/com/google/genai/ApiClient.java @@ -42,7 +42,7 @@ abstract class ApiClient { // {x-version-update-start:google-genai:released} - private static final String SDK_VERSION = "1.6.0"; + private static final String SDK_VERSION = "1.7.0"; // {x-version-update-end:google-genai:released} private static final Logger logger = Logger.getLogger(ApiClient.class.getName()); From 029751abade6bf327b6c5153ed57224906210a0f Mon Sep 17 00:00:00 2001 From: Alejandro Cruzado-Ruiz Date: Wed, 2 Jul 2025 08:59:27 -0700 Subject: [PATCH 055/602] chore: Refactor GenAI SDK to use OkHttp in place of Apache HttpClient Main gain of this move is to open the door for using the SDK on Android PiperOrigin-RevId: 778525236 --- examples/pom.xml | 10 +- .../google/genai/examples/EditImageAsync.java | 4 +- pom.xml | 18 +- src/main/java/com/google/genai/ApiClient.java | 34 +- .../java/com/google/genai/ApiResponse.java | 11 +- src/main/java/com/google/genai/Batches.java | 19 +- src/main/java/com/google/genai/Caches.java | 23 +- src/main/java/com/google/genai/Client.java | 8 +- src/main/java/com/google/genai/Files.java | 45 ++- .../java/com/google/genai/HttpApiClient.java | 81 ++--- .../com/google/genai/HttpApiResponse.java | 28 +- src/main/java/com/google/genai/Models.java | 51 ++- .../java/com/google/genai/Operations.java | 11 +- .../com/google/genai/ReplayApiClient.java | 59 ++-- .../com/google/genai/ReplayApiResponse.java | 29 +- .../java/com/google/genai/ResponseStream.java | 11 +- .../java/com/google/genai/UploadClient.java | 39 +-- .../com/google/genai/errors/ApiException.java | 57 ++++ .../java/com/google/genai/AsyncChatTest.java | 88 +++-- src/test/java/com/google/genai/ChatTest.java | 163 +++++----- .../java/com/google/genai/ClientTest.java | 29 +- .../com/google/genai/DefaultValuesTest.java | 10 +- .../com/google/genai/FakeApiResponse.java | 18 +- .../com/google/genai/FakeUploadApiClient.java | 23 +- .../genai/ForwardCompatibilityTest.java | 25 +- .../com/google/genai/HttpApiClientTest.java | 202 ++++++------ .../com/google/genai/UploadClientTest.java | 20 +- .../google/genai/errors/ApiExceptionTest.java | 305 ++---------------- 28 files changed, 618 insertions(+), 803 deletions(-) diff --git a/examples/pom.xml b/examples/pom.xml index 3bcd3dcfd6f..591c795df64 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -17,7 +17,6 @@ - org.apache.maven.plugins @@ -29,8 +28,15 @@ + + org.codehaus.mojo + exec-maven-plugin + 3.5.0 + + false + + - diff --git a/examples/src/main/java/com/google/genai/examples/EditImageAsync.java b/examples/src/main/java/com/google/genai/examples/EditImageAsync.java index 81163a3937c..c1d9a0f6168 100644 --- a/examples/src/main/java/com/google/genai/examples/EditImageAsync.java +++ b/examples/src/main/java/com/google/genai/examples/EditImageAsync.java @@ -50,14 +50,12 @@ import com.google.genai.types.MaskReferenceMode; import com.google.genai.types.RawReferenceImage; import com.google.genai.types.ReferenceImage; -import java.io.IOException; import java.util.ArrayList; import java.util.concurrent.CompletableFuture; -import org.apache.http.HttpException; /** An example of using the Unified Gen AI Java SDK to edit an image asynchronously. */ public final class EditImageAsync { - public static void main(String[] args) throws IOException, HttpException { + public static void main(String[] args) { String modelId = "imagen-3.0-capability-001"; if (args.length != 0) { modelId = args[0]; diff --git a/pom.xml b/pom.xml index 3dac4a87e24..e8cb0c6f358 100644 --- a/pom.xml +++ b/pom.xml @@ -49,12 +49,12 @@ 1.33.0 2.47.0 4.5.14 - 4.4.16 1.11.0 2.17.2 5.11.4 3.12.4 1.6.0 + 4.12.0 @@ -91,11 +91,6 @@ httpclient ${apache.httpcomponents.httpclient.version} - - org.apache.httpcomponents - httpcore - ${apache.httpcomponents.httpcore.version} - com.google.auto.value auto-value @@ -131,6 +126,11 @@ Java-WebSocket ${java-websocket.version} + + com.squareup.okhttp3 + okhttp + ${okhttp.version} + org.junit.jupiter @@ -175,6 +175,12 @@ 2.35.0 test + + + org.jetbrains.kotlin + kotlin-stdlib-jdk8 + 1.9.10 + diff --git a/src/main/java/com/google/genai/ApiClient.java b/src/main/java/com/google/genai/ApiClient.java index 69a8fb2423b..172e8c5cc9b 100644 --- a/src/main/java/com/google/genai/ApiClient.java +++ b/src/main/java/com/google/genai/ApiClient.java @@ -31,11 +31,8 @@ import java.util.Optional; import java.util.logging.Logger; import java.util.stream.Stream; -import org.apache.http.client.config.RequestConfig; -import org.apache.http.impl.client.CloseableHttpClient; -import org.apache.http.impl.client.HttpClientBuilder; -import org.apache.http.impl.client.HttpClients; -import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; +import okhttp3.Dispatcher; +import okhttp3.OkHttpClient; import org.jspecify.annotations.Nullable; /** Interface for an API client which issues HTTP requests to the GenAI APIs. */ @@ -46,7 +43,7 @@ abstract class ApiClient { // {x-version-update-end:google-genai:released} private static final Logger logger = Logger.getLogger(ApiClient.class.getName()); - CloseableHttpClient httpClient; + final OkHttpClient httpClient; HttpOptions httpOptions; final boolean vertexAI; final Optional clientOptions; @@ -150,8 +147,7 @@ private String getApiKeyFromEnv() { geminiApiKey = null; } if (googleApiKey != null && geminiApiKey != null) { - logger.warning( - "Both GOOGLE_API_KEY and GEMINI_API_KEY are set. Using GOOGLE_API_KEY."); + logger.warning("Both GOOGLE_API_KEY and GEMINI_API_KEY are set. Using GOOGLE_API_KEY."); } if (googleApiKey != null) { return googleApiKey; @@ -159,21 +155,23 @@ private String getApiKeyFromEnv() { return geminiApiKey; } - private CloseableHttpClient createHttpClient( + private OkHttpClient createHttpClient( Optional timeout, Optional clientOptions) { - HttpClientBuilder builder = HttpClients.custom(); + OkHttpClient.Builder builder = new OkHttpClient.Builder(); + // Remove timeouts by default (OkHttp has a default of 10 seconds) + builder.connectTimeout(Duration.ofMillis(0)); + builder.readTimeout(Duration.ofMillis(0)); + builder.writeTimeout(Duration.ofMillis(0)); - RequestConfig.Builder requestConfigBuilder = RequestConfig.custom(); - timeout.ifPresent(connectTimeout -> requestConfigBuilder.setConnectTimeout(connectTimeout)); - builder.setDefaultRequestConfig(requestConfigBuilder.build()); + timeout.ifPresent(connectTimeout -> builder.connectTimeout(Duration.ofMillis(connectTimeout))); - PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(); clientOptions.ifPresent( options -> { - options.maxConnections().ifPresent(connectionManager::setMaxTotal); - options.maxConnectionsPerHost().ifPresent(connectionManager::setDefaultMaxPerRoute); + Dispatcher dispatcher = new Dispatcher(); + options.maxConnections().ifPresent(dispatcher::setMaxRequests); + options.maxConnectionsPerHost().ifPresent(dispatcher::setMaxRequestsPerHost); + builder.dispatcher(dispatcher); }); - builder.setConnectionManager(connectionManager); return builder.build(); } @@ -216,7 +214,7 @@ public boolean vertexAI() { } /** Returns the HttpClient for API calls. */ - CloseableHttpClient httpClient() { + OkHttpClient httpClient() { return httpClient; } diff --git a/src/main/java/com/google/genai/ApiResponse.java b/src/main/java/com/google/genai/ApiResponse.java index dce8fe06c93..6c46f6c39fc 100644 --- a/src/main/java/com/google/genai/ApiResponse.java +++ b/src/main/java/com/google/genai/ApiResponse.java @@ -16,15 +16,16 @@ package com.google.genai; -import org.apache.http.Header; -import org.apache.http.HttpEntity; +import okhttp3.Headers; +import okhttp3.ResponseBody; /** The API response contains a response to a call to the GenAI APIs. */ abstract class ApiResponse implements AutoCloseable { - /** Gets the HttpEntity. */ - public abstract HttpEntity getEntity(); + /** Gets the ResponseBody. */ + public abstract ResponseBody getBody(); - public abstract Header[] getHeaders(); + /** Returns all of the headers from the response. */ + public abstract Headers getHeaders(); @Override public abstract void close(); diff --git a/src/main/java/com/google/genai/Batches.java b/src/main/java/com/google/genai/Batches.java index 7dd8c7bdfa1..0c51d9e4fc7 100644 --- a/src/main/java/com/google/genai/Batches.java +++ b/src/main/java/com/google/genai/Batches.java @@ -41,8 +41,7 @@ import java.io.IOException; import java.util.Optional; import java.util.function.Function; -import org.apache.http.HttpEntity; -import org.apache.http.util.EntityUtils; +import okhttp3.ResponseBody; /** * Provides methods for managing the batch jobs. Instantiating this class is not required. After @@ -6308,10 +6307,10 @@ BatchJob privateCreate(String model, BatchJobSource src, CreateBatchJobConfig co try (ApiResponse response = this.apiClient.request( "post", path, JsonSerializable.toJsonString(body), requestHttpOptions)) { - HttpEntity entity = response.getEntity(); + ResponseBody responseBody = response.getBody(); String responseString; try { - responseString = EntityUtils.toString(entity); + responseString = responseBody.string(); } catch (IOException e) { throw new GenAiIOException("Failed to read HTTP response.", e); } @@ -6379,10 +6378,10 @@ public BatchJob get(String name, GetBatchJobConfig config) { try (ApiResponse response = this.apiClient.request( "get", path, JsonSerializable.toJsonString(body), requestHttpOptions)) { - HttpEntity entity = response.getEntity(); + ResponseBody responseBody = response.getBody(); String responseString; try { - responseString = EntityUtils.toString(entity); + responseString = responseBody.string(); } catch (IOException e) { throw new GenAiIOException("Failed to read HTTP response.", e); } @@ -6490,10 +6489,10 @@ ListBatchJobsResponse privateList(ListBatchJobsConfig config) { try (ApiResponse response = this.apiClient.request( "get", path, JsonSerializable.toJsonString(body), requestHttpOptions)) { - HttpEntity entity = response.getEntity(); + ResponseBody responseBody = response.getBody(); String responseString; try { - responseString = EntityUtils.toString(entity); + responseString = responseBody.string(); } catch (IOException e) { throw new GenAiIOException("Failed to read HTTP response.", e); } @@ -6560,10 +6559,10 @@ public DeleteResourceJob delete(String name, DeleteBatchJobConfig config) { try (ApiResponse response = this.apiClient.request( "delete", path, JsonSerializable.toJsonString(body), requestHttpOptions)) { - HttpEntity entity = response.getEntity(); + ResponseBody responseBody = response.getBody(); String responseString; try { - responseString = EntityUtils.toString(entity); + responseString = responseBody.string(); } catch (IOException e) { throw new GenAiIOException("Failed to read HTTP response.", e); } diff --git a/src/main/java/com/google/genai/Caches.java b/src/main/java/com/google/genai/Caches.java index eca65948d92..7ee03586c81 100644 --- a/src/main/java/com/google/genai/Caches.java +++ b/src/main/java/com/google/genai/Caches.java @@ -40,8 +40,7 @@ import java.io.IOException; import java.util.Optional; import java.util.function.Function; -import org.apache.http.HttpEntity; -import org.apache.http.util.EntityUtils; +import okhttp3.ResponseBody; /** * Provides methods for managing the cached content. Instantiating this class is not required. After @@ -1877,10 +1876,10 @@ public CachedContent create(String model, CreateCachedContentConfig config) { try (ApiResponse response = this.apiClient.request( "post", path, JsonSerializable.toJsonString(body), requestHttpOptions)) { - HttpEntity entity = response.getEntity(); + ResponseBody responseBody = response.getBody(); String responseString; try { - responseString = EntityUtils.toString(entity); + responseString = responseBody.string(); } catch (IOException e) { throw new GenAiIOException("Failed to read HTTP response.", e); } @@ -1946,10 +1945,10 @@ public CachedContent get(String name, GetCachedContentConfig config) { try (ApiResponse response = this.apiClient.request( "get", path, JsonSerializable.toJsonString(body), requestHttpOptions)) { - HttpEntity entity = response.getEntity(); + ResponseBody responseBody = response.getBody(); String responseString; try { - responseString = EntityUtils.toString(entity); + responseString = responseBody.string(); } catch (IOException e) { throw new GenAiIOException("Failed to read HTTP response.", e); } @@ -2015,10 +2014,10 @@ public DeleteCachedContentResponse delete(String name, DeleteCachedContentConfig try (ApiResponse response = this.apiClient.request( "delete", path, JsonSerializable.toJsonString(body), requestHttpOptions)) { - HttpEntity entity = response.getEntity(); + ResponseBody responseBody = response.getBody(); String responseString; try { - responseString = EntityUtils.toString(entity); + responseString = responseBody.string(); } catch (IOException e) { throw new GenAiIOException("Failed to read HTTP response.", e); } @@ -2085,10 +2084,10 @@ public CachedContent update(String name, UpdateCachedContentConfig config) { try (ApiResponse response = this.apiClient.request( "patch", path, JsonSerializable.toJsonString(body), requestHttpOptions)) { - HttpEntity entity = response.getEntity(); + ResponseBody responseBody = response.getBody(); String responseString; try { - responseString = EntityUtils.toString(entity); + responseString = responseBody.string(); } catch (IOException e) { throw new GenAiIOException("Failed to read HTTP response.", e); } @@ -2144,10 +2143,10 @@ ListCachedContentsResponse privateList(ListCachedContentsConfig config) { try (ApiResponse response = this.apiClient.request( "get", path, JsonSerializable.toJsonString(body), requestHttpOptions)) { - HttpEntity entity = response.getEntity(); + ResponseBody responseBody = response.getBody(); String responseString; try { - responseString = EntityUtils.toString(entity); + responseString = responseBody.string(); } catch (IOException e) { throw new GenAiIOException("Failed to read HTTP response.", e); } diff --git a/src/main/java/com/google/genai/Client.java b/src/main/java/com/google/genai/Client.java index 6ef74287961..e6dffac145d 100644 --- a/src/main/java/com/google/genai/Client.java +++ b/src/main/java/com/google/genai/Client.java @@ -373,9 +373,13 @@ Optional baseUrl() { @Override public void close() { try { - apiClient.httpClient().close(); + apiClient.httpClient().dispatcher().executorService().shutdown(); + apiClient.httpClient().connectionPool().evictAll(); + if (apiClient.httpClient().cache() != null) { + apiClient.httpClient().cache().close(); + } } catch (IOException e) { - throw new GenAiIOException("Failed to close the HTTP client.", e); + throw new GenAiIOException("Failed to close the client.", e); } } diff --git a/src/main/java/com/google/genai/Files.java b/src/main/java/com/google/genai/Files.java index 9c477c3957a..90a49e875ee 100644 --- a/src/main/java/com/google/genai/Files.java +++ b/src/main/java/com/google/genai/Files.java @@ -51,9 +51,8 @@ import java.util.Map; import java.util.Optional; import java.util.function.Function; -import org.apache.http.Header; -import org.apache.http.HttpEntity; -import org.apache.http.util.EntityUtils; +import okhttp3.Headers; +import okhttp3.ResponseBody; /** * Provides methods for interacting with the available GenAI files. Instantiating this class is not @@ -517,10 +516,10 @@ ListFilesResponse privateList(ListFilesConfig config) { try (ApiResponse response = this.apiClient.request( "get", path, JsonSerializable.toJsonString(body), requestHttpOptions)) { - HttpEntity entity = response.getEntity(); + ResponseBody responseBody = response.getBody(); String responseString; try { - responseString = EntityUtils.toString(entity); + responseString = responseBody.string(); } catch (IOException e) { throw new GenAiIOException("Failed to read HTTP response.", e); } @@ -578,18 +577,19 @@ CreateFileResponse privateCreate(File file, CreateFileConfig config) { try (ApiResponse response = this.apiClient.request( "post", path, JsonSerializable.toJsonString(body), requestHttpOptions)) { - HttpEntity entity = response.getEntity(); + ResponseBody responseBody = response.getBody(); String responseString; try { - responseString = EntityUtils.toString(entity); + responseString = responseBody.string(); } catch (IOException e) { throw new GenAiIOException("Failed to read HTTP response.", e); } if (config.shouldReturnHttpResponse().orElse(false)) { Map headers = new HashMap<>(); - for (Header header : response.getHeaders()) { - headers.put(header.getName(), header.getValue()); + Headers responseHeaders = response.getHeaders(); + for (String headerName : responseHeaders.names()) { + headers.put(headerName, responseHeaders.get(headerName)); } return CreateFileResponse.builder() .sdkHttpResponse(HttpResponse.builder().headers(headers).body(responseString).build()) @@ -656,10 +656,10 @@ public File get(String name, GetFileConfig config) { try (ApiResponse response = this.apiClient.request( "get", path, JsonSerializable.toJsonString(body), requestHttpOptions)) { - HttpEntity entity = response.getEntity(); + ResponseBody responseBody = response.getBody(); String responseString; try { - responseString = EntityUtils.toString(entity); + responseString = responseBody.string(); } catch (IOException e) { throw new GenAiIOException("Failed to read HTTP response.", e); } @@ -724,10 +724,10 @@ public DeleteFileResponse delete(String name, DeleteFileConfig config) { try (ApiResponse response = this.apiClient.request( "delete", path, JsonSerializable.toJsonString(body), requestHttpOptions)) { - HttpEntity entity = response.getEntity(); + ResponseBody responseBody = response.getBody(); String responseString; try { - responseString = EntityUtils.toString(entity); + responseString = responseBody.string(); } catch (IOException e) { throw new GenAiIOException("Failed to read HTTP response.", e); } @@ -760,8 +760,8 @@ public File upload(java.io.File file, UploadFileConfig config) { mimeType = Optional.empty(); } String uploadUrl = createFileInApi(config, mimeType, size); - HttpEntity entity = uploadClient.upload(uploadUrl, inputStream, size); - return fileFromUploadHttpEntity(entity); + ResponseBody responseBody = uploadClient.upload(uploadUrl, inputStream, size); + return fileFromUploadResponseBody(responseBody); } catch (IOException e) { throw new GenAiIOException("Failed to upload file.", e); } @@ -776,8 +776,8 @@ public File upload(java.io.File file, UploadFileConfig config) { */ public File upload(byte[] bytes, UploadFileConfig config) { String uploadUrl = createFileInApi(config, Optional.empty(), bytes.length); - HttpEntity entity = uploadClient.upload(uploadUrl, bytes); - return fileFromUploadHttpEntity(entity); + ResponseBody responseBody = uploadClient.upload(uploadUrl, bytes); + return fileFromUploadResponseBody(responseBody); } /** @@ -790,8 +790,8 @@ public File upload(byte[] bytes, UploadFileConfig config) { */ public File upload(InputStream inputStream, long size, UploadFileConfig config) { String uploadUrl = createFileInApi(config, Optional.empty(), size); - HttpEntity entity = uploadClient.upload(uploadUrl, inputStream, size); - return fileFromUploadHttpEntity(entity); + ResponseBody responseBody = uploadClient.upload(uploadUrl, inputStream, size); + return fileFromUploadResponseBody(responseBody); } /** @@ -806,10 +806,10 @@ public File upload(String filePath, UploadFileConfig config) { return upload(file, config); } - private File fileFromUploadHttpEntity(HttpEntity entity) { + private File fileFromUploadResponseBody(ResponseBody responseBody) { String responseString; try { - responseString = EntityUtils.toString(entity); + responseString = responseBody.string(); } catch (IOException e) { throw new GenAiIOException("Failed to read HTTP response.", e); } @@ -967,8 +967,7 @@ private void downloadTo(String fileName, String downloadPath, DownloadFileConfig this.apiClient.request( "get", String.format("files/%s:download?alt=media", fileName), "", httpOptions); try (FileOutputStream outputStream = new FileOutputStream(downloadPath)) { - HttpEntity entity = response.getEntity(); - entity.writeTo(outputStream); + outputStream.write(response.getBody().bytes()); } catch (IOException e) { throw new GenAiIOException("Failed to download file.", e); } diff --git a/src/main/java/com/google/genai/HttpApiClient.java b/src/main/java/com/google/genai/HttpApiClient.java index 701d09a2cb3..e00cbda699d 100644 --- a/src/main/java/com/google/genai/HttpApiClient.java +++ b/src/main/java/com/google/genai/HttpApiClient.java @@ -18,26 +18,29 @@ import com.google.api.core.InternalApi; import com.google.auth.oauth2.GoogleCredentials; +import com.google.common.base.Ascii; import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; import com.google.genai.errors.GenAiIOException; import com.google.genai.types.ClientOptions; import com.google.genai.types.HttpOptions; import java.io.IOException; import java.util.Map; import java.util.Optional; -import org.apache.http.client.methods.HttpDelete; -import org.apache.http.client.methods.HttpGet; -import org.apache.http.client.methods.HttpPatch; -import org.apache.http.client.methods.HttpPost; -import org.apache.http.client.methods.HttpRequestBase; -import org.apache.http.entity.ByteArrayEntity; -import org.apache.http.entity.ContentType; -import org.apache.http.entity.StringEntity; +import okhttp3.MediaType; +import okhttp3.Request; +import okhttp3.RequestBody; /** Base client for the HTTP APIs. This is for internal use only. */ @InternalApi public class HttpApiClient extends ApiClient { + private static final ImmutableSet METHODS_WITH_BODY = + ImmutableSet.of("POST", "PATCH", "PUT"); + + private static final ImmutableSet VALID_HTTP_METHODS = + ImmutableSet.builder().addAll(METHODS_WITH_BODY).add("GET").add("DELETE").build(); + /** Constructs an ApiClient for Google AI APIs. */ HttpApiClient( Optional apiKey, @@ -56,15 +59,19 @@ public class HttpApiClient extends ApiClient { super(project, location, credentials, httpOptions, clientOptions); } - /** Sends a Http request given the http method, path, request json string, and http options. */ + /** + * Sends a Http request given the http method, path, request json string, and http options. + * Request bodies included for non-POST/PUT/PATCH methods will be ignored. + */ @Override public HttpApiResponse request( String httpMethod, String path, String requestJson, Optional requestHttpOptions) { + String capitalizedHttpMethod = Ascii.toUpperCase(httpMethod); boolean queryBaseModel = - httpMethod.equalsIgnoreCase("GET") && path.startsWith("publishers/google/models"); + capitalizedHttpMethod.equals("GET") && path.startsWith("publishers/google/models"); if (this.vertexAI() && !path.startsWith("projects/") && !queryBaseModel) { path = String.format("projects/%s/locations/%s/", this.project.get(), this.location.get()) @@ -83,28 +90,21 @@ public HttpApiResponse request( "%s/%s/%s", mergedHttpOptions.baseUrl().get(), mergedHttpOptions.apiVersion().get(), path); } + if (!VALID_HTTP_METHODS.contains(capitalizedHttpMethod)) { + throw new IllegalArgumentException("Unsupported HTTP method: " + capitalizedHttpMethod); + } - if (httpMethod.equalsIgnoreCase("POST")) { - HttpPost httpPost = new HttpPost(requestUrl); - setHeaders(httpPost, mergedHttpOptions); - httpPost.setEntity(new StringEntity(requestJson, ContentType.APPLICATION_JSON)); - return executeRequest(httpPost); - } else if (httpMethod.equalsIgnoreCase("GET")) { - HttpGet httpGet = new HttpGet(requestUrl); - setHeaders(httpGet, mergedHttpOptions); - return executeRequest(httpGet); - } else if (httpMethod.equalsIgnoreCase("DELETE")) { - HttpDelete httpDelete = new HttpDelete(requestUrl); - setHeaders(httpDelete, mergedHttpOptions); - return executeRequest(httpDelete); - } else if (httpMethod.equalsIgnoreCase("PATCH")) { - HttpPatch httpPatch = new HttpPatch(requestUrl); - setHeaders(httpPatch, mergedHttpOptions); - httpPatch.setEntity(new StringEntity(requestJson, ContentType.APPLICATION_JSON)); - return executeRequest(httpPatch); + RequestBody body; + if (METHODS_WITH_BODY.contains(capitalizedHttpMethod)) { + body = RequestBody.create(requestJson, MediaType.parse("application/json")); } else { - throw new IllegalArgumentException("Unsupported HTTP method: " + httpMethod); + body = null; } + Request.Builder requestBuilder = + new Request.Builder().url(requestUrl).method(capitalizedHttpMethod, body); + + setHeaders(requestBuilder, mergedHttpOptions); + return executeRequest(requestBuilder.build()); } @Override @@ -115,10 +115,11 @@ public ApiResponse request( Optional requestHttpOptions) { HttpOptions mergedHttpOptions = mergeHttpOptions(requestHttpOptions.orElse(null)); if (httpMethod.equalsIgnoreCase("POST")) { - HttpPost httpPost = new HttpPost(url); - setHeaders(httpPost, mergedHttpOptions); - httpPost.setEntity(new ByteArrayEntity(requestBytes)); - return executeRequest(httpPost); + RequestBody body = + RequestBody.create(MediaType.get("application/octet-stream"), requestBytes); + Request.Builder requestBuilder = new Request.Builder().url(url).post(body); + setHeaders(requestBuilder, mergedHttpOptions); + return executeRequest(requestBuilder.build()); } else { throw new IllegalArgumentException( "The request method with bytes is only supported for POST. Unsupported HTTP method: " @@ -127,14 +128,14 @@ public ApiResponse request( } /** Sets the required headers (including auth) on the request object. */ - private void setHeaders(HttpRequestBase request, HttpOptions requestHttpOptions) { + private void setHeaders(Request.Builder requestBuilder, HttpOptions requestHttpOptions) { for (Map.Entry header : requestHttpOptions.headers().orElse(ImmutableMap.of()).entrySet()) { - request.setHeader(header.getKey(), header.getValue()); + requestBuilder.header(header.getKey(), header.getValue()); } if (apiKey.isPresent()) { - request.setHeader("x-goog-api-key", apiKey.get()); + requestBuilder.header("x-goog-api-key", apiKey.get()); } else { GoogleCredentials cred = credentials.orElseThrow(() -> new IllegalStateException("credentials is required")); @@ -157,18 +158,18 @@ private void setHeaders(HttpRequestBase request, HttpOptions requestHttpOptions) throw e; } } - request.setHeader("Authorization", "Bearer " + accessToken); + requestBuilder.header("Authorization", "Bearer " + accessToken); if (cred.getQuotaProjectId() != null) { - request.setHeader("x-goog-user-project", cred.getQuotaProjectId()); + requestBuilder.header("x-goog-user-project", cred.getQuotaProjectId()); } } } /** Executes the given HTTP request. */ - private HttpApiResponse executeRequest(HttpRequestBase request) { + private HttpApiResponse executeRequest(Request request) { try { - return new HttpApiResponse(httpClient.execute(request)); + return new HttpApiResponse(httpClient.newCall(request).execute()); } catch (IOException e) { throw new GenAiIOException("Failed to execute HTTP request.", e); } diff --git a/src/main/java/com/google/genai/HttpApiResponse.java b/src/main/java/com/google/genai/HttpApiResponse.java index 1e7f6fc4250..14938905f09 100644 --- a/src/main/java/com/google/genai/HttpApiResponse.java +++ b/src/main/java/com/google/genai/HttpApiResponse.java @@ -17,42 +17,36 @@ package com.google.genai; import com.google.genai.errors.ApiException; -import com.google.genai.errors.GenAiIOException; -import java.io.IOException; -import org.apache.http.Header; -import org.apache.http.HttpEntity; -import org.apache.http.client.methods.CloseableHttpResponse; +import okhttp3.Headers; +import okhttp3.Response; +import okhttp3.ResponseBody; /** Wraps a real HTTP response to expose the methods needed by the GenAI SDK. */ final class HttpApiResponse extends ApiResponse { - private final CloseableHttpResponse response; + private final Response response; /** Constructs a HttpApiResponse instance with the response. */ - public HttpApiResponse(CloseableHttpResponse response) { + public HttpApiResponse(Response response) { this.response = response; } - /** Returns the HttpEntity from the response. */ + /** Returns the ResponseBody from the response. */ @Override - public HttpEntity getEntity() { + public ResponseBody getBody() { ApiException.throwFromResponse(response); - return response.getEntity(); + return response.body(); } /** Returns all of the headers from the response. */ @Override - public Header[] getHeaders() { - return response.getAllHeaders(); + public Headers getHeaders() { + return response.headers(); } /** Closes the Http response. */ @Override public void close() { - try { - response.close(); - } catch (IOException e) { - throw new GenAiIOException("Failed to close the HTTP response.", e); - } + response.close(); } } diff --git a/src/main/java/com/google/genai/Models.java b/src/main/java/com/google/genai/Models.java index e3c44757233..da7ec3f0486 100644 --- a/src/main/java/com/google/genai/Models.java +++ b/src/main/java/com/google/genai/Models.java @@ -77,8 +77,7 @@ import java.util.Optional; import java.util.function.Function; import java.util.logging.Logger; -import org.apache.http.HttpEntity; -import org.apache.http.util.EntityUtils; +import okhttp3.ResponseBody; /** * Provides methods for interacting with the available GenAI models. Instantiating this class is not @@ -5882,10 +5881,10 @@ GenerateContentResponse privateGenerateContent( try (ApiResponse response = this.apiClient.request( "post", path, JsonSerializable.toJsonString(body), requestHttpOptions)) { - HttpEntity entity = response.getEntity(); + ResponseBody responseBody = response.getBody(); String responseString; try { - responseString = EntityUtils.toString(entity); + responseString = responseBody.string(); } catch (IOException e) { throw new GenAiIOException("Failed to read HTTP response.", e); } @@ -6007,10 +6006,10 @@ EmbedContentResponse privateEmbedContent( try (ApiResponse response = this.apiClient.request( "post", path, JsonSerializable.toJsonString(body), requestHttpOptions)) { - HttpEntity entity = response.getEntity(); + ResponseBody responseBody = response.getBody(); String responseString; try { - responseString = EntityUtils.toString(entity); + responseString = responseBody.string(); } catch (IOException e) { throw new GenAiIOException("Failed to read HTTP response.", e); } @@ -6073,10 +6072,10 @@ GenerateImagesResponse privateGenerateImages( try (ApiResponse response = this.apiClient.request( "post", path, JsonSerializable.toJsonString(body), requestHttpOptions)) { - HttpEntity entity = response.getEntity(); + ResponseBody responseBody = response.getBody(); String responseString; try { - responseString = EntityUtils.toString(entity); + responseString = responseBody.string(); } catch (IOException e) { throw new GenAiIOException("Failed to read HTTP response.", e); } @@ -6141,10 +6140,10 @@ EditImageResponse privateEditImage( try (ApiResponse response = this.apiClient.request( "post", path, JsonSerializable.toJsonString(body), requestHttpOptions)) { - HttpEntity entity = response.getEntity(); + ResponseBody responseBody = response.getBody(); String responseString; try { - responseString = EntityUtils.toString(entity); + responseString = responseBody.string(); } catch (IOException e) { throw new GenAiIOException("Failed to read HTTP response.", e); } @@ -6207,10 +6206,10 @@ UpscaleImageResponse privateUpscaleImage( try (ApiResponse response = this.apiClient.request( "post", path, JsonSerializable.toJsonString(body), requestHttpOptions)) { - HttpEntity entity = response.getEntity(); + ResponseBody responseBody = response.getBody(); String responseString; try { - responseString = EntityUtils.toString(entity); + responseString = responseBody.string(); } catch (IOException e) { throw new GenAiIOException("Failed to read HTTP response.", e); } @@ -6275,10 +6274,10 @@ public Model get(String model, GetModelConfig config) { try (ApiResponse response = this.apiClient.request( "get", path, JsonSerializable.toJsonString(body), requestHttpOptions)) { - HttpEntity entity = response.getEntity(); + ResponseBody responseBody = response.getBody(); String responseString; try { - responseString = EntityUtils.toString(entity); + responseString = responseBody.string(); } catch (IOException e) { throw new GenAiIOException("Failed to read HTTP response.", e); } @@ -6334,10 +6333,10 @@ ListModelsResponse privateList(ListModelsConfig config) { try (ApiResponse response = this.apiClient.request( "get", path, JsonSerializable.toJsonString(body), requestHttpOptions)) { - HttpEntity entity = response.getEntity(); + ResponseBody responseBody = response.getBody(); String responseString; try { - responseString = EntityUtils.toString(entity); + responseString = responseBody.string(); } catch (IOException e) { throw new GenAiIOException("Failed to read HTTP response.", e); } @@ -6407,10 +6406,10 @@ public Model update(String model, UpdateModelConfig config) { try (ApiResponse response = this.apiClient.request( "patch", path, JsonSerializable.toJsonString(body), requestHttpOptions)) { - HttpEntity entity = response.getEntity(); + ResponseBody responseBody = response.getBody(); String responseString; try { - responseString = EntityUtils.toString(entity); + responseString = responseBody.string(); } catch (IOException e) { throw new GenAiIOException("Failed to read HTTP response.", e); } @@ -6474,10 +6473,10 @@ public DeleteModelResponse delete(String model, DeleteModelConfig config) { try (ApiResponse response = this.apiClient.request( "delete", path, JsonSerializable.toJsonString(body), requestHttpOptions)) { - HttpEntity entity = response.getEntity(); + ResponseBody responseBody = response.getBody(); String responseString; try { - responseString = EntityUtils.toString(entity); + responseString = responseBody.string(); } catch (IOException e) { throw new GenAiIOException("Failed to read HTTP response.", e); } @@ -6550,10 +6549,10 @@ public CountTokensResponse countTokens( try (ApiResponse response = this.apiClient.request( "post", path, JsonSerializable.toJsonString(body), requestHttpOptions)) { - HttpEntity entity = response.getEntity(); + ResponseBody responseBody = response.getBody(); String responseString; try { - responseString = EntityUtils.toString(entity); + responseString = responseBody.string(); } catch (IOException e) { throw new GenAiIOException("Failed to read HTTP response.", e); } @@ -6622,10 +6621,10 @@ public ComputeTokensResponse computeTokens( try (ApiResponse response = this.apiClient.request( "post", path, JsonSerializable.toJsonString(body), requestHttpOptions)) { - HttpEntity entity = response.getEntity(); + ResponseBody responseBody = response.getBody(); String responseString; try { - responseString = EntityUtils.toString(entity); + responseString = responseBody.string(); } catch (IOException e) { throw new GenAiIOException("Failed to read HTTP response.", e); } @@ -6710,10 +6709,10 @@ public GenerateVideosOperation generateVideos( try (ApiResponse response = this.apiClient.request( "post", path, JsonSerializable.toJsonString(body), requestHttpOptions)) { - HttpEntity entity = response.getEntity(); + ResponseBody responseBody = response.getBody(); String responseString; try { - responseString = EntityUtils.toString(entity); + responseString = responseBody.string(); } catch (IOException e) { throw new GenAiIOException("Failed to read HTTP response.", e); } diff --git a/src/main/java/com/google/genai/Operations.java b/src/main/java/com/google/genai/Operations.java index 33b9c1a0acf..3bb9dee0979 100644 --- a/src/main/java/com/google/genai/Operations.java +++ b/src/main/java/com/google/genai/Operations.java @@ -31,8 +31,7 @@ import com.google.genai.types.HttpOptions; import java.io.IOException; import java.util.Optional; -import org.apache.http.HttpEntity; -import org.apache.http.util.EntityUtils; +import okhttp3.ResponseBody; /** * Provides methods for managing the long-running operations. Instantiating this class is not @@ -401,10 +400,10 @@ GenerateVideosOperation privateGetVideosOperation( try (ApiResponse response = this.apiClient.request( "get", path, JsonSerializable.toJsonString(body), requestHttpOptions)) { - HttpEntity entity = response.getEntity(); + ResponseBody responseBody = response.getBody(); String responseString; try { - responseString = EntityUtils.toString(entity); + responseString = responseBody.string(); } catch (IOException e) { throw new GenAiIOException("Failed to read HTTP response.", e); } @@ -464,10 +463,10 @@ GenerateVideosOperation privateFetchPredictVideosOperation( try (ApiResponse response = this.apiClient.request( "post", path, JsonSerializable.toJsonString(body), requestHttpOptions)) { - HttpEntity entity = response.getEntity(); + ResponseBody responseBody = response.getBody(); String responseString; try { - responseString = EntityUtils.toString(entity); + responseString = responseBody.string(); } catch (IOException e) { throw new GenAiIOException("Failed to read HTTP response.", e); } diff --git a/src/main/java/com/google/genai/ReplayApiClient.java b/src/main/java/com/google/genai/ReplayApiClient.java index 37708ce4c11..0d4f002bf5e 100644 --- a/src/main/java/com/google/genai/ReplayApiClient.java +++ b/src/main/java/com/google/genai/ReplayApiClient.java @@ -22,11 +22,9 @@ import com.fasterxml.jackson.core.type.TypeReference; import com.google.auth.oauth2.GoogleCredentials; import com.google.genai.errors.GenAiIOException; -import com.google.genai.types.HttpOptions; import com.google.genai.types.ClientOptions; -import java.io.ByteArrayInputStream; +import com.google.genai.types.HttpOptions; import java.io.IOException; -import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; @@ -37,12 +35,12 @@ import java.util.Map; import java.util.Optional; import java.util.stream.Stream; -import org.apache.http.Header; -import org.apache.http.ProtocolVersion; -import org.apache.http.StatusLine; -import org.apache.http.entity.BasicHttpEntity; -import org.apache.http.message.BasicHeader; -import org.apache.http.message.BasicStatusLine; +import okhttp3.Headers; +import okhttp3.MediaType; +import okhttp3.Protocol; +import okhttp3.Request; +import okhttp3.Response; +import okhttp3.ResponseBody; // TODO(b/369384123): Currently the ReplayApiClient mirrors the HttpApiClient. We will refactor the // ReplayApiClient to use the ReplayFile as part of resolving b/369384123. @@ -116,8 +114,8 @@ static Map loadReplayData(String replayId) { // fields like body_segments are not being populated. For now, we will just use basic JSON // parsing and switch to the generated JSON classes once we have the replays working. // convert JSON string to Map - return JsonSerializable.objectMapper.readValue( - replayData, new TypeReference>() {}); + return JsonSerializable.objectMapper.readValue( + replayData, new TypeReference>() {}); } catch (IOException e) { throw new GenAiIOException("Failed to read replay file: " + e, e); } @@ -165,21 +163,32 @@ public ApiResponse request( responseBody.append(bodySegment.toString()); } - Header[] headers = headerMap.entrySet() - .stream() - .map(entry -> new BasicHeader(entry.getKey(), entry.getValue())) - .toArray(Header[]::new); - + // Create a dummy request, which is required by the Response.Builder + Request dummyRequest = + new Request.Builder() + .url("https://replay.googleapis.com" + path) + .method(httpMethod, null) + .build(); + Headers.Builder headersBuilder = new Headers.Builder(); + headerMap.forEach(headersBuilder::add); + Headers okHttpHeaders = headersBuilder.build(); String responseString = responseBody.toString(); - - BasicHttpEntity entity = new BasicHttpEntity(); - entity.setContent(new ByteArrayInputStream(responseString.getBytes(StandardCharsets.UTF_8))); - entity.setContentLength(responseString.length()); - - StatusLine statusLine = - new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), statusCode, "OK"); - - return new ReplayApiResponse(entity, statusLine, headers); + String contentType = okHttpHeaders.get("Content-Type"); + MediaType mediaType = + (contentType != null) + ? MediaType.parse(contentType) + : MediaType.parse("application/json; charset=utf-8"); + ResponseBody okHttpResponseBody = ResponseBody.create(responseString, mediaType); + Response okHttpResponse = + new Response.Builder() + .request(dummyRequest) + .protocol(Protocol.HTTP_1_1) + .code(statusCode) + .message("OK") + .headers(okHttpHeaders) + .body(okHttpResponseBody) + .build(); + return new ReplayApiResponse(okHttpResponse.body(), statusCode, okHttpHeaders); } else { // Note that if the client mode is "api", then the ReplayApiClient will not be used. throw new IllegalArgumentException("Invalid client mode: " + this.clientMode); diff --git a/src/main/java/com/google/genai/ReplayApiResponse.java b/src/main/java/com/google/genai/ReplayApiResponse.java index 99de3628abe..7b596166119 100644 --- a/src/main/java/com/google/genai/ReplayApiResponse.java +++ b/src/main/java/com/google/genai/ReplayApiResponse.java @@ -16,32 +16,37 @@ package com.google.genai; -import org.apache.http.Header; -import org.apache.http.HttpEntity; -import org.apache.http.StatusLine; +import okhttp3.Headers; +import okhttp3.ResponseBody; // TODO(b/369384123): Change the replay API response to use the ReplayFile. /** Provides a simulated HTTP response from a replay file. */ @ExcludeFromGeneratedCoverageReport final class ReplayApiResponse extends ApiResponse { - private final HttpEntity entity; - private final StatusLine statusLine; - private final Header[] headers; + private final ResponseBody body; + private final int statusCode; + private final Headers headers; - public ReplayApiResponse(HttpEntity entity, StatusLine statusLine, Header[] headers) { - this.entity = entity; - this.statusLine = statusLine; + public ReplayApiResponse(ResponseBody body, int statusCode, Headers headers) { + this.body = body; + this.statusCode = statusCode; this.headers = headers; } @Override - public HttpEntity getEntity() { - return this.entity; + public ResponseBody getBody() { + return this.body; } @Override - public Header[] getHeaders() { return this.headers;} + public Headers getHeaders() { + return this.headers; + } + + public int getStatusCode() { + return this.statusCode; + } @Override public void close() {} diff --git a/src/main/java/com/google/genai/ResponseStream.java b/src/main/java/com/google/genai/ResponseStream.java index 95fbde6a9eb..25df64e222b 100644 --- a/src/main/java/com/google/genai/ResponseStream.java +++ b/src/main/java/com/google/genai/ResponseStream.java @@ -29,9 +29,8 @@ import java.util.ArrayList; import java.util.Iterator; import java.util.List; -import java.util.logging.Logger; import java.util.NoSuchElementException; -import org.apache.http.HttpEntity; +import java.util.logging.Logger; /** An iterable of datatype objects. */ public class ResponseStream implements Iterable, AutoCloseable { @@ -137,13 +136,7 @@ private String readNextJson() { private final BufferedReader reader; public ResponseStream(Class clazz, ApiResponse response, Object obj, String converterName) { - HttpEntity entity = response.getEntity(); - InputStream responseStream; - try { - responseStream = entity.getContent(); - } catch (IOException e) { - throw new GenAiIOException("Failed to read HTTP response.", e); - } + InputStream responseStream = response.getBody().byteStream(); this.reader = new BufferedReader(new InputStreamReader(responseStream, StandardCharsets.UTF_8)); this.iterator = new ResponseStreamIterator(clazz, this.reader, obj, converterName); this.response = response; diff --git a/src/main/java/com/google/genai/UploadClient.java b/src/main/java/com/google/genai/UploadClient.java index 0319c291d8b..3d10e2efb46 100644 --- a/src/main/java/com/google/genai/UploadClient.java +++ b/src/main/java/com/google/genai/UploadClient.java @@ -27,8 +27,8 @@ import java.time.Duration; import java.util.Arrays; import java.util.Optional; -import org.apache.http.Header; -import org.apache.http.HttpEntity; +import okhttp3.Headers; +import okhttp3.ResponseBody; /** Client which handles the upload process for files on the SDK. */ final class UploadClient { @@ -50,28 +50,28 @@ public UploadClient(ApiClient apiClient, int chunkSize) { this.chunkSize = chunkSize; } - public HttpEntity upload(String uploadUrl, String filePath) { + public ResponseBody upload(String uploadUrl, String filePath) { File file = new File(filePath); - HttpEntity entity; + ResponseBody responseBody; try (InputStream inputStream = new FileInputStream(file)) { - entity = upload(uploadUrl, inputStream, file.length()); + responseBody = upload(uploadUrl, inputStream, file.length()); } catch (IOException e) { throw new GenAiIOException("Failed to process input stream", e); } - return entity; + return responseBody; } - public HttpEntity upload(String uploadUrl, byte[] bytes) { - HttpEntity entity; + public ResponseBody upload(String uploadUrl, byte[] bytes) { + ResponseBody responseBody; try (InputStream inputStream = new ByteArrayInputStream(bytes)) { - entity = upload(uploadUrl, inputStream, bytes.length); + responseBody = upload(uploadUrl, inputStream, bytes.length); } catch (IOException e) { throw new GenAiIOException("Failed to process input stream", e); } - return entity; + return responseBody; } - public HttpEntity upload(String uploadUrl, InputStream inputStream, long size) { + public ResponseBody upload(String uploadUrl, InputStream inputStream, long size) { String uploadCommand = "upload"; byte[] buffer = new byte[chunkSize]; int bytesRead; @@ -119,11 +119,12 @@ private UploadChunkResponse uploadChunk( ApiResponse response = null; while (retryCount < MAX_RETRY_COUNT) { response = apiClient.request("POST", uploadUrl, chunk, Optional.of(httpOptions)); - Header[] headers = response.getHeaders(); - for (Header header : headers) { - if (header.getName().equals("X-Goog-Upload-Status")) { + Headers headers = response.getHeaders(); + if (headers != null) { + String headerValue = headers.get("X-Goog-Upload-Status"); + if (headerValue != null) { uploadStatusHeaderFound = true; - uploadStatus = header.getValue(); + uploadStatus = headerValue; break; } } @@ -144,14 +145,14 @@ private UploadChunkResponse uploadChunk( if (!uploadStatusHeaderFound) { throw new IllegalStateException("Upload failed. Retries exhausted, please try again."); } - return new UploadChunkResponse(uploadStatus, response.getEntity()); + return new UploadChunkResponse(uploadStatus, response.getBody()); } private static class UploadChunkResponse { private final String uploadStatus; - private final HttpEntity entity; + private final ResponseBody entity; - UploadChunkResponse(String uploadStatus, HttpEntity entity) { + UploadChunkResponse(String uploadStatus, ResponseBody entity) { this.uploadStatus = uploadStatus; this.entity = entity; } @@ -160,7 +161,7 @@ public String getUploadStatus() { return uploadStatus; } - public HttpEntity getEntity() { + public ResponseBody getEntity() { return entity; } } diff --git a/src/main/java/com/google/genai/errors/ApiException.java b/src/main/java/com/google/genai/errors/ApiException.java index 042c9d2e6a0..825c9990fe6 100644 --- a/src/main/java/com/google/genai/errors/ApiException.java +++ b/src/main/java/com/google/genai/errors/ApiException.java @@ -16,9 +16,14 @@ package com.google.genai.errors; +import static com.google.common.base.Strings.isNullOrEmpty; + import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; +import com.google.api.core.InternalApi; import java.io.IOException; +import okhttp3.Response; +import okhttp3.ResponseBody; import org.apache.http.HttpEntity; import org.apache.http.HttpStatus; import org.apache.http.StatusLine; @@ -50,7 +55,9 @@ public ApiException(int code, String status, String message) { * Throws an ApiException from the response if the response is not a OK status. * * @param response The response from the API call. + * @deprecated Use {@link #throwFromResponse(Response)} instead. */ + @Deprecated public static void throwFromResponse(CloseableHttpResponse response) { StatusLine statusLine = response.getStatusLine(); int code = statusLine.getStatusCode(); @@ -68,6 +75,28 @@ public static void throwFromResponse(CloseableHttpResponse response) { } } + /** + * Throws an ApiException from the response if the response is not a OK status. + * + * @param response The response from the API call. + */ + @InternalApi + public static void throwFromResponse(Response response) { + int code = response.code(); + if (code >= 200 && code < 300) { + return; + } + String status = response.message(); + String message = getErrorMessageFromResponse(response); + if (code >= 400 && code < 500) { // Client errors. + throw new ClientException(code, status, message); + } else if (code >= 500 && code < 600) { // Server errors. + throw new ServerException(code, status, message); + } else { + throw new ApiException(code, status, message); + } + } + /** * Returns the error message from the response, if no error or error message is not found, then * returns an empty string. @@ -93,6 +122,34 @@ static String getErrorMessageFromResponse(CloseableHttpResponse response) { } } + /** + * Returns the error message from the response, if no error or error message is not found, then + * returns an empty string. + */ + static String getErrorMessageFromResponse(Response response) { + ResponseBody responseBody = response.body(); + try { + if (responseBody == null) { + return ""; + } + String responseBodyString = responseBody.string(); + if (isNullOrEmpty(responseBodyString)) { + return ""; + } + ObjectMapper mapper = new ObjectMapper(); + JsonNode errorNode = mapper.readTree(responseBodyString).get("error"); + if (errorNode != null && errorNode.isObject()) { + JsonNode messageNode = errorNode.get("message"); + if (messageNode != null && messageNode.isTextual()) { + return messageNode.asText(); + } + } + return ""; + } catch (IOException ignored) { + return ""; + } + } + /** Returns the status code from the API response. */ public int code() { return code; diff --git a/src/test/java/com/google/genai/AsyncChatTest.java b/src/test/java/com/google/genai/AsyncChatTest.java index da994a05894..2eead7e1c66 100644 --- a/src/test/java/com/google/genai/AsyncChatTest.java +++ b/src/test/java/com/google/genai/AsyncChatTest.java @@ -28,16 +28,13 @@ import com.google.genai.types.GenerateContentResponse; import com.google.genai.types.GenerateContentResponseUsageMetadata; import com.google.genai.types.Part; -import java.io.ByteArrayInputStream; -import java.io.InputStream; import java.lang.reflect.Field; -import java.nio.charset.StandardCharsets; import java.util.Iterator; import java.util.List; import java.util.concurrent.CompletableFuture; import java.util.concurrent.atomic.AtomicInteger; -import org.apache.http.HttpEntity; -import org.apache.http.entity.StringEntity; +import okhttp3.MediaType; +import okhttp3.ResponseBody; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mockito.Mockito; @@ -46,20 +43,15 @@ public class AsyncChatTest { ApiClient mockedClient; ApiResponse mockedResponse; - HttpEntity mockedEntity; ApiResponse mockedResponse1; ApiResponse mockedResponse2; ApiResponse mockedResponse3; - HttpEntity mockedEntity1; - HttpEntity mockedEntity2; - HttpEntity mockedEntity3; Client client; private static final String STREAMING_RESPONSE_CHUNK_1 = "Once upon "; private static final String STREAMING_RESPONSE_CHUNK_2 = "a time, in a land"; private static final String STREAMING_RESPONSE_CHUNK_3 = " far, far away..."; private static final String NON_STREAMING_RESPONSE = "This is a non-streaming response."; - private Iterator mockStreamIterator; GenerateContentResponse responseChunk1 = GenerateContentResponse.builder() @@ -122,16 +114,12 @@ void setUp() { mockedResponse = Mockito.mock(ApiResponse.class); when(mockedClient.request(anyString(), anyString(), anyString(), any())) .thenReturn(mockedResponse); - mockedEntity = Mockito.mock(HttpEntity.class); client = Client.builder().build(); mockedResponse1 = Mockito.mock(ApiResponse.class); mockedResponse2 = Mockito.mock(ApiResponse.class); mockedResponse3 = Mockito.mock(ApiResponse.class); - mockedEntity1 = Mockito.mock(HttpEntity.class); - mockedEntity2 = Mockito.mock(HttpEntity.class); - mockedEntity3 = Mockito.mock(HttpEntity.class); } @Test @@ -151,12 +139,21 @@ public void testGetAsyncChatMessage() throws Exception { apiClientField.setAccessible(true); apiClientField.set(client.async.chats, mockedClient); - StringEntity content = - new StringEntity( + ResponseBody content1 = + ResponseBody.create( + MediaType.get("application/json"), "{\"candidates\":[{\"content\":{\"parts\":[{\"text\":\"Once upon a time, there was a" - + " cheese shop\"}], \"role\":\"model\"}}]}}"); + + " cheese shop\"}], \"role\":\"model\"}, \"finishReason\":\"STOP\"}]}"); + ResponseBody content2 = + ResponseBody.create( + MediaType.get("application/json"), + "{\"candidates\":[{\"content\":{\"parts\":[{\"text\":\"Once upon a time, there was a" + + " cheese shop\"}], \"role\":\"model\"}, \"finishReason\":\"STOP\"}]}"); - when(mockedResponse.getEntity()).thenReturn(content); + when(mockedResponse1.getBody()).thenReturn(content1); + when(mockedResponse2.getBody()).thenReturn(content2); + when(mockedClient.request(anyString(), anyString(), anyString(), any())) + .thenReturn(mockedResponse1, mockedResponse2); AsyncChat chat = client.async.chats.create("gemini-2.0-flash-exp", null); @@ -175,12 +172,21 @@ public void testGetHistoryAsync() throws Exception { apiClientField.setAccessible(true); apiClientField.set(client.async.chats, mockedClient); - StringEntity content = - new StringEntity( + ResponseBody content1 = + ResponseBody.create( + MediaType.get("application/json"), "{\"candidates\":[{\"content\":{\"parts\":[{\"text\":\"Once upon a time, there was a" - + " cheese shop\"}], \"role\":\"model\"}}]}}"); + + " cheese shop\"}], \"role\":\"model\"}, \"finishReason\":\"STOP\"}]}"); + ResponseBody content2 = + ResponseBody.create( + MediaType.get("application/json"), + "{\"candidates\":[{\"content\":{\"parts\":[{\"text\":\"Once upon a time, there was a" + + " cheese shop\"}], \"role\":\"model\"}, \"finishReason\":\"STOP\"}]}"); - when(mockedResponse.getEntity()).thenReturn(content); + when(mockedResponse1.getBody()).thenReturn(content1); + when(mockedResponse2.getBody()).thenReturn(content2); + when(mockedClient.request(anyString(), anyString(), anyString(), any())) + .thenReturn(mockedResponse1, mockedResponse2); AsyncChat chat = client.async.chats.create("gemini-2.0-flash-exp", null); @@ -205,24 +211,17 @@ public void testIterateOverAsyncResponseStream() throws Exception { AsyncChat chatSession = client.async.chats.create("gemini-2.0-flash-exp", null); - InputStream inputStream1 = - new ByteArrayInputStream(streamData.getBytes(StandardCharsets.UTF_8)); - InputStream inputStream2 = - new ByteArrayInputStream(streamData2.getBytes(StandardCharsets.UTF_8)); - - InputStream inputStream3 = - new ByteArrayInputStream(nonStreamData.getBytes(StandardCharsets.UTF_8)); + ResponseBody body1 = ResponseBody.create(MediaType.get("application/json"), streamData); + ResponseBody body2 = ResponseBody.create(MediaType.get("application/json"), streamData2); + ResponseBody body3 = ResponseBody.create(MediaType.get("application/json"), nonStreamData); - when(mockedResponse1.getEntity()).thenReturn(mockedEntity1); - when(mockedResponse2.getEntity()).thenReturn(mockedEntity2); - when(mockedResponse3.getEntity()).thenReturn(mockedEntity3); - when(mockedEntity1.getContent()).thenReturn(inputStream1); - when(mockedEntity2.getContent()).thenReturn(inputStream2); - when(mockedEntity3.getContent()).thenReturn(inputStream3); + when(mockedResponse1.getBody()).thenReturn(body1); + when(mockedResponse2.getBody()).thenReturn(body2); + when(mockedResponse3.getBody()).thenReturn(body3); when(mockedClient.request(anyString(), anyString(), anyString(), any())) .thenReturn(mockedResponse1, mockedResponse2, mockedResponse3); - assert chatSession.getHistory(false).size() == 0; + assert chatSession.getHistory(false).isEmpty(); CompletableFuture> responseStreamFuture = chatSession.sendMessageStream("Tell me a story.", null); @@ -292,19 +291,14 @@ public void testThrowsIfAsyncStreamResponseIsNotConsumed() throws Exception { AsyncChat chatSession = client.async.chats.create("gemini-2.0-flash-exp", null); - InputStream inputStream1 = - new ByteArrayInputStream(streamData.getBytes(StandardCharsets.UTF_8)); - InputStream inputStream2 = - new ByteArrayInputStream(streamData2.getBytes(StandardCharsets.UTF_8)); - - when(mockedResponse1.getEntity()).thenReturn(mockedEntity1); - when(mockedResponse2.getEntity()).thenReturn(mockedEntity2); - when(mockedEntity1.getContent()).thenReturn(inputStream1); - when(mockedEntity2.getContent()).thenReturn(inputStream2); + ResponseBody body1 = ResponseBody.create(MediaType.get("application/json"), streamData); + ResponseBody body2 = ResponseBody.create(MediaType.get("application/json"), streamData2); + when(mockedResponse1.getBody()).thenReturn(body1); + when(mockedResponse2.getBody()).thenReturn(body2); when(mockedClient.request(anyString(), anyString(), anyString(), any())) .thenReturn(mockedResponse1, mockedResponse2); - assert chatSession.getHistory(false).size() == 0; + assert chatSession.getHistory(false).isEmpty(); ResponseStream responseStreamFuture = chatSession.sendMessageStream("Tell me a story.", null).join(); @@ -318,5 +312,7 @@ public void testThrowsIfAsyncStreamResponseIsNotConsumed() throws Exception { assertThrows( IllegalStateException.class, () -> chatSession.sendMessageStream("Tell me another story.")); + + assert exception2.getMessage().equals("Response stream is not consumed"); } } diff --git a/src/test/java/com/google/genai/ChatTest.java b/src/test/java/com/google/genai/ChatTest.java index d7ce6b49485..0312b23651a 100644 --- a/src/test/java/com/google/genai/ChatTest.java +++ b/src/test/java/com/google/genai/ChatTest.java @@ -38,10 +38,9 @@ import java.lang.reflect.Method; import java.nio.charset.StandardCharsets; import java.util.ArrayList; -import java.util.Iterator; import java.util.List; -import org.apache.http.HttpEntity; -import org.apache.http.entity.StringEntity; +import okhttp3.MediaType; +import okhttp3.ResponseBody; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mockito.Mockito; @@ -50,13 +49,12 @@ public class ChatTest { ApiClient mockedClient; ApiResponse mockedResponse; - HttpEntity mockedEntity; ApiResponse mockedResponse1; ApiResponse mockedResponse2; ApiResponse mockedResponse3; - HttpEntity mockedEntity1; - HttpEntity mockedEntity2; - HttpEntity mockedEntity3; + ResponseBody mockedBody1; + ResponseBody mockedBody2; + ResponseBody mockedBody3; Client client; Chats chatSession; @@ -64,7 +62,6 @@ public class ChatTest { private static final String STREAMING_RESPONSE_CHUNK_2 = "a time, in a land"; private static final String STREAMING_RESPONSE_CHUNK_3 = " far, far away..."; private static final String NON_STREAMING_RESPONSE = "This is a non-streaming response."; - private Iterator mockStreamIterator; public static String findTheaters(String movie, String location, String time) { return "AMC Metreon 16, AMC Kabuki 8, AMC Theater 11"; @@ -131,18 +128,15 @@ void setUp() { mockedResponse = Mockito.mock(ApiResponse.class); when(mockedClient.request(anyString(), anyString(), anyString(), any())) .thenReturn(mockedResponse); - mockedEntity = Mockito.mock(HttpEntity.class); client = Client.builder().build(); mockedResponse1 = Mockito.mock(ApiResponse.class); mockedResponse2 = Mockito.mock(ApiResponse.class); mockedResponse3 = Mockito.mock(ApiResponse.class); - mockedEntity1 = Mockito.mock(HttpEntity.class); - mockedEntity2 = Mockito.mock(HttpEntity.class); - mockedEntity3 = Mockito.mock(HttpEntity.class); - - mockStreamIterator = Mockito.mock(ResponseStream.ResponseStreamIterator.class); + mockedBody1 = Mockito.mock(ResponseBody.class); + mockedBody2 = Mockito.mock(ResponseBody.class); + mockedBody3 = Mockito.mock(ResponseBody.class); } @Test @@ -162,11 +156,12 @@ public void testCreateChatSession() throws Exception { @Test public void testGetHistory() throws Exception { - StringEntity content = - new StringEntity( + ResponseBody content = + ResponseBody.create( + MediaType.get("application/json"), "{\"candidates\":[{\"content\":{\"parts\":[{\"text\":\"All Too Well, 10 Minute" - + " Version\"}], \"role\":\"model\"}}]}}"); - when(mockedResponse.getEntity()).thenReturn(content); + + " Version\"}], \"role\":\"model\"}, \"finishReason\":\"STOP\"}]}}"); + when(mockedResponse.getBody()).thenReturn(content); // Make the apiClient field public so that it can be spied on in the tests. This is a // workaround for the fact that the ApiClient is a final class and cannot be spied on directly. Field apiClientField = Chats.class.getDeclaredField("apiClient"); @@ -216,10 +211,12 @@ public void testGetHistoryWithAfc() throws Exception { when(mockedClient.request(anyString(), anyString(), anyString(), any())) .thenReturn(mockedResponse1, mockedResponse2); - StringEntity functionResponseStringEntity = new StringEntity(functionResponse.toJson()); - when(mockedResponse1.getEntity()).thenReturn(functionResponseStringEntity); - StringEntity finalResponseStringEntity = new StringEntity(finalResponse.toJson()); - when(mockedResponse2.getEntity()).thenReturn(finalResponseStringEntity); + ResponseBody functionResponseBody = + ResponseBody.create(MediaType.get("application/json"), functionResponse.toJson()); + when(mockedResponse1.getBody()).thenReturn(functionResponseBody); + ResponseBody finalResponseBody = + ResponseBody.create(MediaType.get("application/json"), finalResponse.toJson()); + when(mockedResponse2.getBody()).thenReturn(finalResponseBody); Field apiClientField = Chats.class.getDeclaredField("apiClient"); apiClientField.setAccessible(true); @@ -244,11 +241,20 @@ public void testGetHistoryWithAfc() throws Exception { @Test public void testMultiTurnChat() throws Exception { - StringEntity content = - new StringEntity( - "{\"candidates\":[{\"content\":{\"parts\":[{\"text\":\"I am doing great!\"}]," - + " \"role\":\"model\"}}]}}"); - when(mockedResponse.getEntity()).thenReturn(content); + ResponseBody content1 = + ResponseBody.create( + MediaType.get("application/json"), + "{\"candidates\":[{\"content\":{\"parts\":[{\"text\":\"I am doing" + + " great!\"}],\"role\":\"model\"},\"finishReason\":\"STOP\"}]}}"); + ResponseBody content2 = + ResponseBody.create( + MediaType.get("application/json"), + "{\"candidates\":[{\"content\":{\"parts\":[{\"text\":\"I am doing" + + " great!\"}],\"role\":\"model\"},\"finishReason\":\"STOP\"}]}}"); + when(mockedResponse1.getBody()).thenReturn(content1); + when(mockedResponse2.getBody()).thenReturn(content2); + when(mockedClient.request(anyString(), anyString(), anyString(), any())) + .thenReturn(mockedResponse1, mockedResponse2); // Make the apiClient field public so that it can be spied on in the tests. This is a // workaround for the fact that the ApiClient is a final class and cannot be spied on directly. @@ -270,12 +276,13 @@ public void testMultiTurnChat() throws Exception { @Test public void testChatWithConfig() throws Exception { - StringEntity content = - new StringEntity( + ResponseBody content = + ResponseBody.create( + MediaType.get("application/json"), "{\"candidates\":[{\"content\":{\"parts\":[{\"text\":\"The Gouda Life\"}]," + " \"role\":\"model\"}}, {\"content\": {\"parts\":[{\"text\":\"Something" + " Bleu\"}], \"role\":\"model\"}}]}}"); - when(mockedResponse.getEntity()).thenReturn(content); + when(mockedResponse.getBody()).thenReturn(content); // Make the apiClient field public so that it can be spied on in the tests. This is a // workaround for the fact that the ApiClient is a final class and cannot be spied on directly. @@ -294,12 +301,13 @@ public void testChatWithConfig() throws Exception { @Test public void testInitConfigIsUsedWhenSendMessageConfigIsNull() throws Exception { - StringEntity content = - new StringEntity( + ResponseBody content = + ResponseBody.create( + MediaType.get("application/json"), "{\"candidates\":[{\"content\":{\"parts\":[{\"text\":\"The Gouda Life\"}]," + " \"role\":\"model\"}}, {\"content\": {\"parts\":[{\"text\":\"Something" + " Bleu\"}], \"role\":\"model\"}}]}}"); - when(mockedResponse.getEntity()).thenReturn(content); + when(mockedResponse.getBody()).thenReturn(content); // Make the apiClient field public so that it can be spied on in the tests. This is a // workaround for the fact that the ApiClient is a final class and cannot be spied on directly. @@ -317,11 +325,21 @@ public void testInitConfigIsUsedWhenSendMessageConfigIsNull() throws Exception { @Test public void testSendMessageContent() throws Exception { - StringEntity content = - new StringEntity( + ResponseBody content1 = + ResponseBody.create( + MediaType.get("application/json"), + "{\"candidates\":[{\"content\":{\"parts\":[{\"text\":\"It's better with" + + " cheddar\"}],\"role\":\"model\"},\"finishReason\":\"STOP\"}]}}"); + ResponseBody content2 = + ResponseBody.create( + MediaType.get("application/json"), "{\"candidates\":[{\"content\":{\"parts\":[{\"text\":\"It's better with" - + " cheddar\"}], \"role\":\"model\"}}]}}"); - when(mockedResponse.getEntity()).thenReturn(content); + + " cheddar\"}],\"role\":\"model\"},\"finishReason\":\"STOP\"}]}}"); + + when(mockedResponse1.getBody()).thenReturn(content1); + when(mockedResponse2.getBody()).thenReturn(content2); + when(mockedClient.request(anyString(), anyString(), anyString(), any())) + .thenReturn(mockedResponse1, mockedResponse2); // Make the apiClient field public so that it can be spied on in the tests. This is a // workaround for the fact that the ApiClient is a final class and cannot be spied on directly. Field apiClientField = Chats.class.getDeclaredField("apiClient"); @@ -345,11 +363,21 @@ public void testSendMessageContent() throws Exception { @Test public void testSendMessageContentList() throws Exception { - StringEntity content = - new StringEntity( + ResponseBody content1 = + ResponseBody.create( + MediaType.get("application/json"), "{\"candidates\":[{\"content\":{\"parts\":[{\"text\":\"It's better with" - + " cheddar\"}], \"role\":\"model\"}}]}}"); - when(mockedResponse.getEntity()).thenReturn(content); + + " cheddar\"}],\"role\":\"model\"},\"finishReason\":\"STOP\"}]}}"); + ResponseBody content2 = + ResponseBody.create( + MediaType.get("application/json"), + "{\"candidates\":[{\"content\":{\"parts\":[{\"text\":\"It's better with" + + " cheddar\"}],\"role\":\"model\"},\"finishReason\":\"STOP\"}]}}"); + + when(mockedResponse1.getBody()).thenReturn(content1); + when(mockedResponse2.getBody()).thenReturn(content2); + when(mockedClient.request(anyString(), anyString(), anyString(), any())) + .thenReturn(mockedResponse1, mockedResponse2); // Make the apiClient field public so that it can be spied on in the tests. This is a // workaround for the fact that the ApiClient is a final class and cannot be spied on directly. Field apiClientField = Chats.class.getDeclaredField("apiClient"); @@ -374,11 +402,12 @@ public void testSendMessageContentList() throws Exception { @Test public void testUnexpectedFinishReasonDoesNotAddToCuratedHistory() throws Exception { - StringEntity content = - new StringEntity( + ResponseBody content = + ResponseBody.create( + MediaType.get("application/json"), "{\"candidates\":[{\"content\":{\"parts\":[{\"text\":\"It's better with" + " cheddar\"}], \"role\":\"model\"}, \"finishReason\":\"BLOCKLIST\"}]}"); - when(mockedResponse.getEntity()).thenReturn(content); + when(mockedResponse.getBody()).thenReturn(content); // Make the apiClient field public so that it can be spied on in the tests. This is a // workaround for the fact that the ApiClient is a final class and cannot be spied on directly. @@ -401,12 +430,13 @@ public void testUnexpectedFinishReasonDoesNotAddToCuratedHistory() throws Except @Test public void testInvalidRoleThrows() throws Exception { - StringEntity content = - new StringEntity( + ResponseBody content = + ResponseBody.create( + MediaType.get("application/json"), "{\"candidates\":[{\"content\":{\"parts\":[{\"text\":\"The Gouda Life\"}]," + " \"role\":\"Mr. Cheese\"}}, {\"content\": {\"parts\":[{\"text\":\"Something" + " Bleu\"}], \"role\":\"model\"}}]}}"); - when(mockedResponse.getEntity()).thenReturn(content); + when(mockedResponse.getBody()).thenReturn(content); // Make the apiClient field public so that it can be spied on in the tests. This is a // workaround for the fact that the ApiClient is a final class and cannot be spied on directly. @@ -428,12 +458,13 @@ public void testInvalidRoleThrows() throws Exception { @Test public void testInvalidHistoryThrows() throws Exception { - StringEntity content = - new StringEntity( + ResponseBody content = + ResponseBody.create( + MediaType.get("application/json"), "{\"candidates\":[{\"content\":{\"parts\":[{\"text\":\"The Gouda Life\"}]," + " \"role\":\"model\"}}, {\"content\": {\"parts\":[{\"text\":\"Something" + " Bleu\"}], \"role\":\"model\"}}]}}"); - when(mockedResponse.getEntity()).thenReturn(content); + when(mockedResponse.getBody()).thenReturn(content); // Make the apiClient field public so that it can be spied on in the tests. This is a // workaround for the fact that the ApiClient is a final class and cannot be spied on directly. @@ -464,20 +495,13 @@ public void testIterateOverResponseStream() throws Exception { Chat chatSession = client.chats.create("gemini-2.0-flash-exp", null); - InputStream inputStream1 = - new ByteArrayInputStream(streamData.getBytes(StandardCharsets.UTF_8)); - InputStream inputStream2 = - new ByteArrayInputStream(streamData2.getBytes(StandardCharsets.UTF_8)); - - InputStream inputStream3 = - new ByteArrayInputStream(nonStreamData.getBytes(StandardCharsets.UTF_8)); + ResponseBody body1 = ResponseBody.create(MediaType.get("application/json"), streamData); + ResponseBody body2 = ResponseBody.create(MediaType.get("application/json"), streamData2); + ResponseBody body3 = ResponseBody.create(MediaType.get("application/json"), nonStreamData); - when(mockedResponse1.getEntity()).thenReturn(mockedEntity1); - when(mockedResponse2.getEntity()).thenReturn(mockedEntity2); - when(mockedResponse3.getEntity()).thenReturn(mockedEntity3); - when(mockedEntity1.getContent()).thenReturn(inputStream1); - when(mockedEntity2.getContent()).thenReturn(inputStream2); - when(mockedEntity3.getContent()).thenReturn(inputStream3); + when(mockedResponse1.getBody()).thenReturn(body1); + when(mockedResponse2.getBody()).thenReturn(body2); + when(mockedResponse3.getBody()).thenReturn(body3); when(mockedClient.request(anyString(), anyString(), anyString(), any())) .thenReturn(mockedResponse1, mockedResponse2, mockedResponse3); @@ -555,15 +579,10 @@ public void testThrowsIfStreamResponseIsNotConsumed() throws Exception { Chat chatSession = client.chats.create("gemini-2.0-flash-exp", null); - InputStream inputStream1 = - new ByteArrayInputStream(streamData.getBytes(StandardCharsets.UTF_8)); - InputStream inputStream2 = - new ByteArrayInputStream(streamData2.getBytes(StandardCharsets.UTF_8)); - - when(mockedResponse1.getEntity()).thenReturn(mockedEntity1); - when(mockedResponse2.getEntity()).thenReturn(mockedEntity2); - when(mockedEntity1.getContent()).thenReturn(inputStream1); - when(mockedEntity2.getContent()).thenReturn(inputStream2); + ResponseBody body1 = ResponseBody.create(MediaType.get("application/json"), streamData); + ResponseBody body2 = ResponseBody.create(MediaType.get("application/json"), streamData2); + when(mockedResponse1.getBody()).thenReturn(body1); + when(mockedResponse2.getBody()).thenReturn(body2); when(mockedClient.request(anyString(), anyString(), anyString(), any())) .thenReturn(mockedResponse1, mockedResponse2); diff --git a/src/test/java/com/google/genai/ClientTest.java b/src/test/java/com/google/genai/ClientTest.java index 5892d65789c..d824e426b0e 100644 --- a/src/test/java/com/google/genai/ClientTest.java +++ b/src/test/java/com/google/genai/ClientTest.java @@ -22,8 +22,6 @@ import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import com.google.auth.oauth2.GoogleCredentials; @@ -32,7 +30,7 @@ import java.io.IOException; import java.lang.reflect.Field; import java.util.Optional; -import org.apache.http.impl.client.CloseableHttpClient; +import okhttp3.OkHttpClient; import org.junit.jupiter.api.Test; public class ClientTest { @@ -182,7 +180,7 @@ public void testSetDefaultBaseUrls() { public void testCloseClient() throws Exception { // Arrange ApiClient apiClient = mock(ApiClient.class); - CloseableHttpClient httpClient = mock(CloseableHttpClient.class); + OkHttpClient httpClient = new OkHttpClient(); when(apiClient.httpClient()).thenReturn(httpClient); Client client = Client.builder().apiKey(API_KEY).vertexAI(false).build(); @@ -194,26 +192,7 @@ public void testCloseClient() throws Exception { client.close(); // Assert - verify(httpClient, times(1)).close(); - } - - @Test - public void testCloseClient_throwsException() throws Exception { - // Arrange - ApiClient apiClient = mock(ApiClient.class); - CloseableHttpClient httpClient = mock(CloseableHttpClient.class); - when(apiClient.httpClient()).thenReturn(httpClient); - doThrow(new IOException("Failed to close HTTP client.")).when(httpClient).close(); - - Client client = Client.builder().apiKey(API_KEY).vertexAI(false).build(); - Field apiClientField = Client.class.getDeclaredField("apiClient"); - apiClientField.setAccessible(true); - apiClientField.set(client, apiClient); - - // Act - GenAiIOException exception = assertThrows(GenAiIOException.class, client::close); - - // Assert - assertEquals("Failed to close the HTTP client.", exception.getMessage()); + assertTrue(httpClient.dispatcher().executorService().isShutdown()); + assertEquals(0, httpClient.connectionPool().connectionCount()); } } diff --git a/src/test/java/com/google/genai/DefaultValuesTest.java b/src/test/java/com/google/genai/DefaultValuesTest.java index 7e5a0e7a980..38717352a9e 100644 --- a/src/test/java/com/google/genai/DefaultValuesTest.java +++ b/src/test/java/com/google/genai/DefaultValuesTest.java @@ -26,8 +26,8 @@ import com.google.genai.types.GenerateContentResponse; import java.lang.reflect.Field; import java.util.Optional; -import org.apache.http.HttpEntity; -import org.apache.http.entity.StringEntity; +import okhttp3.MediaType; +import okhttp3.ResponseBody; import org.junit.jupiter.api.Test; import org.mockito.ArgumentCaptor; import org.mockito.Mockito; @@ -40,10 +40,10 @@ public void testDefaultValues() throws Exception { ApiResponse mockedResponse = Mockito.mock(ApiResponse.class); when(httpClientSpy.request(anyString(), anyString(), anyString(), any())) .thenReturn(mockedResponse); - HttpEntity mockedEntity = Mockito.mock(HttpEntity.class); GenerateContentResponse returnResponse = GenerateContentResponse.builder().build(); - StringEntity content = new StringEntity(returnResponse.toJson()); - when(mockedResponse.getEntity()).thenReturn(content); + ResponseBody content = + ResponseBody.create(MediaType.get("application/json"), returnResponse.toJson()); + when(mockedResponse.getBody()).thenReturn(content); Client client = Client.builder().build(); // Make the apiClient field public so that it can be spied on in the tests. This is a diff --git a/src/test/java/com/google/genai/FakeApiResponse.java b/src/test/java/com/google/genai/FakeApiResponse.java index ad66eb45616..7c9c24ea9cc 100644 --- a/src/test/java/com/google/genai/FakeApiResponse.java +++ b/src/test/java/com/google/genai/FakeApiResponse.java @@ -16,28 +16,28 @@ package com.google.genai; -import org.apache.http.Header; -import org.apache.http.HttpEntity; +import okhttp3.Headers; +import okhttp3.ResponseBody; /** */ public final class FakeApiResponse extends ApiResponse { - private final Header[] headers; - private final HttpEntity entity; + private final Headers headers; + private final ResponseBody body; - public FakeApiResponse(Header[] headers, HttpEntity entity) { + public FakeApiResponse(Headers headers, ResponseBody body) { this.headers = headers; - this.entity = entity; + this.body = body; } @Override - public Header[] getHeaders() { + public Headers getHeaders() { return headers; } @Override - public HttpEntity getEntity() { - return entity; + public ResponseBody getBody() { + return body; } @Override diff --git a/src/test/java/com/google/genai/FakeUploadApiClient.java b/src/test/java/com/google/genai/FakeUploadApiClient.java index 12c1a9278ee..d6a6df81ae8 100644 --- a/src/test/java/com/google/genai/FakeUploadApiClient.java +++ b/src/test/java/com/google/genai/FakeUploadApiClient.java @@ -22,9 +22,12 @@ import java.util.HashMap; import java.util.Map; import java.util.Optional; -import org.apache.http.Header; -import org.apache.http.entity.BasicHttpEntity; -import org.apache.http.message.BasicHeader; +import okhttp3.Headers; +import okhttp3.MediaType; +import okhttp3.Protocol; +import okhttp3.Request; +import okhttp3.Response; +import okhttp3.ResponseBody; /** */ public final class FakeUploadApiClient extends ApiClient { @@ -96,7 +99,8 @@ public ApiResponse request( } else { fileUploadFailureCount.remove(path); } - return new FakeApiResponse(new Header[0], new BasicHttpEntity()); + return new FakeApiResponse( + Headers.of(), ResponseBody.create(MediaType.get("text/plain"), "")); } file.uploadedByteCount += requestBytes.length; @@ -104,15 +108,12 @@ public ApiResponse request( file.uploadedBytes.add(b); } - Header[] responseHeaders = new Header[1]; boolean isFinalUpload = headers.get("X-Goog-Upload-Command").equals("upload, finalize"); + String uploadStatus = isFinalUpload ? "final" : "active"; - if (isFinalUpload) { - responseHeaders[0] = new BasicHeader("X-Goog-Upload-Status", "final"); - } else { - responseHeaders[0] = new BasicHeader("X-Goog-Upload-Status", "active"); - } - return new FakeApiResponse(responseHeaders, new BasicHttpEntity()); + return new FakeApiResponse( + Headers.of("X-Goog-Upload-Status", uploadStatus), + ResponseBody.create(MediaType.get("text/plain"), "")); } public class UploadedFile { diff --git a/src/test/java/com/google/genai/ForwardCompatibilityTest.java b/src/test/java/com/google/genai/ForwardCompatibilityTest.java index 681d200f906..15ddaee7edd 100644 --- a/src/test/java/com/google/genai/ForwardCompatibilityTest.java +++ b/src/test/java/com/google/genai/ForwardCompatibilityTest.java @@ -37,8 +37,8 @@ import com.google.genai.types.SafetySetting; import java.lang.reflect.Field; import java.util.Optional; -import org.apache.http.HttpEntity; -import org.apache.http.entity.StringEntity; +import okhttp3.MediaType; +import okhttp3.ResponseBody; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mockito.ArgumentCaptor; @@ -48,10 +48,10 @@ public class ForwardCompatibilityTest { ApiClient mockedClient; ApiResponse mockedResponse; - HttpEntity mockedEntity; Client client; GenerateContentResponse returnResponse; ObjectMapper objectMapper; + private static final MediaType JSON = MediaType.get("application/json; charset=utf-8"); @BeforeEach void setUp() { @@ -59,7 +59,6 @@ void setUp() { mockedResponse = Mockito.mock(ApiResponse.class); when(mockedClient.request(anyString(), anyString(), anyString(), any())) .thenReturn(mockedResponse); - mockedEntity = Mockito.mock(HttpEntity.class); returnResponse = GenerateContentResponse.builder().build(); objectMapper = new ObjectMapper(); @@ -75,8 +74,8 @@ public void testForwardCompatibility() throws Exception { objectNode.put("unknownFieldToTestForwardCompatibility", "Hello World!"); String jsonString = objectMapper.writeValueAsString(objectNode); - StringEntity content = new StringEntity(jsonString); - when(mockedResponse.getEntity()).thenReturn(content); + ResponseBody responseBody = ResponseBody.create(JSON, jsonString); + when(mockedResponse.getBody()).thenReturn(responseBody); // Make the apiClient field public so that it can be spied on in the tests. This is a // workaround for the fact that the ApiClient is a final class and cannot be spied on directly. @@ -108,8 +107,8 @@ public void testEnumForwardCompatibilityFinishReason() throws Exception { rootObjectNode.putArray("candidates").addAll(candidatesArray); String jsonString = objectMapper.writeValueAsString(rootNode); - StringEntity content = new StringEntity(jsonString); - when(mockedResponse.getEntity()).thenReturn(content); + ResponseBody responseBody = ResponseBody.create(JSON, jsonString); + when(mockedResponse.getBody()).thenReturn(responseBody); Client client = Client.builder().build(); // Make the apiClient field public so that it can be spied on in the tests. This is a @@ -148,8 +147,8 @@ public void testFinishReasonEnumReturnsEnum() throws Exception { rootObjectNode.putArray("candidates").addAll(candidatesArray); String jsonString = objectMapper.writeValueAsString(rootNode); - StringEntity content = new StringEntity(jsonString); - when(mockedResponse.getEntity()).thenReturn(content); + ResponseBody responseBody = ResponseBody.create(JSON, jsonString); + when(mockedResponse.getBody()).thenReturn(responseBody); Client client = Client.builder().build(); // Make the apiClient field public so that it can be spied on in the tests. This is a @@ -187,8 +186,8 @@ public void testEnumForwardCompatibilitySafetyFilterLevel() throws Exception { rootObjectNode.putArray("candidates").addAll(candidatesArray); String jsonString = objectMapper.writeValueAsString(rootNode); - StringEntity content = new StringEntity(jsonString); - when(mockedResponse.getEntity()).thenReturn(content); + ResponseBody responseBody = ResponseBody.create(JSON, jsonString); + when(mockedResponse.getBody()).thenReturn(responseBody); Client client = Client.builder().build(); // Make the apiClient field public so that it can be spied on in the tests. This is a @@ -235,7 +234,7 @@ public void testEnumSendingUnknownSafetysettings() throws Exception { Field apiClientField = Models.class.getDeclaredField("apiClient"); apiClientField.setAccessible(true); apiClientField.set(client.models, mockedClient); - when(mockedResponse.getEntity()).thenReturn(new StringEntity("{}")); + when(mockedResponse.getBody()).thenReturn(ResponseBody.create(JSON, "{}")); GenerateContentResponse response = client.models.generateContent("gemini-2.0-flash-exp", "What is your name?", config); diff --git a/src/test/java/com/google/genai/HttpApiClientTest.java b/src/test/java/com/google/genai/HttpApiClientTest.java index 0a4b20a8c50..0ed6005cc3d 100644 --- a/src/test/java/com/google/genai/HttpApiClientTest.java +++ b/src/test/java/com/google/genai/HttpApiClientTest.java @@ -25,8 +25,8 @@ import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.junit.jupiter.api.Assertions.fail; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -43,19 +43,15 @@ import com.google.genai.types.Part; import java.lang.reflect.Field; import java.util.Optional; -import org.apache.http.Header; -import org.apache.http.HttpEntity; -import org.apache.http.client.config.RequestConfig; -import org.apache.http.client.methods.CloseableHttpResponse; -import org.apache.http.client.methods.HttpDelete; -import org.apache.http.client.methods.HttpGet; -import org.apache.http.client.methods.HttpPost; -import org.apache.http.client.methods.HttpRequestBase; -import org.apache.http.conn.ClientConnectionManager; -import org.apache.http.entity.ContentType; -import org.apache.http.impl.client.CloseableHttpClient; -import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; -import org.apache.http.util.EntityUtils; +import okhttp3.Call; +import okhttp3.Dispatcher; +import okhttp3.OkHttpClient; +import okhttp3.Protocol; +import okhttp3.Request; +import okhttp3.RequestBody; +import okhttp3.Response; +import okhttp3.ResponseBody; +import okio.Buffer; import org.junit.jupiter.api.Test; import org.mockito.ArgumentCaptor; import org.mockito.Mock; @@ -73,19 +69,29 @@ public class HttpApiClientTest { private static final Optional REQUEST_HTTP_OPTIONS = Optional.of( HttpOptions.builder() - .baseUrl("test-url") + .baseUrl("http://test-url") .apiVersion("test-api-version") .headers(ImmutableMap.of("test", "header")) .build()); private static final String TEST_PATH = "test-path"; private static final String TEST_REQUEST_JSON = "{\"test\": \"request-json\"}"; - @Mock CloseableHttpClient mockHttpClient; + @Mock OkHttpClient mockHttpClient; + @Mock Call mockCall; private void setMockClient(HttpApiClient client) throws Exception { - mockHttpClient = Mockito.mock(CloseableHttpClient.class); - CloseableHttpResponse mockResponse = Mockito.mock(CloseableHttpResponse.class); - when(mockHttpClient.execute(any())).thenReturn(mockResponse); + mockHttpClient = Mockito.mock(OkHttpClient.class); + mockCall = Mockito.mock(Call.class); + Response mockResponse = + new Response.Builder() + .request(new Request.Builder().url("https://example.com").build()) + .protocol(Protocol.HTTP_1_1) + .code(200) + .message("OK") + .body(ResponseBody.create(null, "{}")) + .build(); + when(mockHttpClient.newCall(any())).thenReturn(mockCall); + when(mockCall.execute()).thenReturn(mockResponse); Field clientField = ApiClient.class.getDeclaredField("httpClient"); clientField.setAccessible(true); clientField.set(client, mockHttpClient); @@ -94,7 +100,7 @@ private void setMockClient(HttpApiClient client) throws Exception { credentialsField.setAccessible(true); credentialsField.set(client, Optional.of(credentials)); } - + @Test public void testRequestPostMethodWithVertexAI() throws Exception { // Arrange @@ -111,27 +117,26 @@ public void testRequestPostMethodWithVertexAI() throws Exception { client.request("POST", TEST_PATH, TEST_REQUEST_JSON, Optional.empty()); // Assert - ArgumentCaptor requestCaptor = ArgumentCaptor.forClass(HttpRequestBase.class); - verify(mockHttpClient).execute(requestCaptor.capture()); - HttpRequestBase capturedRequest = requestCaptor.getValue(); + ArgumentCaptor requestCaptor = ArgumentCaptor.forClass(Request.class); + verify(mockHttpClient).newCall(requestCaptor.capture()); + Request capturedRequest = requestCaptor.getValue(); - assertTrue(capturedRequest instanceof HttpPost); - assertEquals("POST", capturedRequest.getMethod()); + assertEquals("POST", capturedRequest.method()); assertEquals( String.format( "https://%s-aiplatform.googleapis.com/v1beta1/projects/%s/locations/%s/%s", LOCATION, PROJECT, LOCATION, TEST_PATH), - capturedRequest.getURI().toString()); - Header authHeader = capturedRequest.getFirstHeader("Authorization"); - assertNotNull(authHeader); - assertEquals("Bearer ", authHeader.getValue()); - assertNull(capturedRequest.getFirstHeader("x-goog-api-key")); - - HttpEntity entity = ((HttpPost) capturedRequest).getEntity(); - assertNotNull(entity); - assertEquals(TEST_REQUEST_JSON, EntityUtils.toString(entity)); - assertTrue( - entity.getContentType().getValue().contains(ContentType.APPLICATION_JSON.getMimeType())); + capturedRequest.url().toString()); + assertNotNull(capturedRequest.header("Authorization")); + assertEquals("Bearer", capturedRequest.header("Authorization")); + assertNull(capturedRequest.header("x-goog-api-key")); + + RequestBody body = capturedRequest.body(); + assertNotNull(body); + final Buffer buffer = new Buffer(); + body.writeTo(buffer); + assertEquals(TEST_REQUEST_JSON, buffer.readUtf8()); + assertEquals("application/json; charset=utf-8", body.contentType().toString()); } @Test @@ -145,19 +150,17 @@ public void testRequestGetMethodWithMldev() throws Exception { client.request("GET", TEST_PATH, "", Optional.empty()); // Assert - ArgumentCaptor requestCaptor = ArgumentCaptor.forClass(HttpRequestBase.class); - verify(mockHttpClient).execute(requestCaptor.capture()); - HttpRequestBase capturedRequest = requestCaptor.getValue(); + ArgumentCaptor requestCaptor = ArgumentCaptor.forClass(Request.class); + verify(mockHttpClient).newCall(requestCaptor.capture()); + Request capturedRequest = requestCaptor.getValue(); - assertTrue(capturedRequest instanceof HttpGet); - assertEquals("GET", capturedRequest.getMethod()); + assertEquals("GET", capturedRequest.method()); assertEquals( "https://generativelanguage.googleapis.com/v1beta/" + TEST_PATH, - capturedRequest.getURI().toString()); - Header authHeader = capturedRequest.getFirstHeader("x-goog-api-key"); - assertNotNull(authHeader); - assertEquals(API_KEY, authHeader.getValue()); - assertNull(capturedRequest.getFirstHeader("Authorization")); + capturedRequest.url().toString()); + assertNotNull(capturedRequest.header("x-goog-api-key")); + assertEquals(API_KEY, capturedRequest.header("x-goog-api-key")); + assertNull(capturedRequest.header("Authorization")); } @Test @@ -171,19 +174,17 @@ public void testRequestDeleteMethodWithMldev() throws Exception { client.request("DELETE", TEST_PATH, "", Optional.empty()); // Assert - ArgumentCaptor requestCaptor = ArgumentCaptor.forClass(HttpRequestBase.class); - verify(mockHttpClient).execute(requestCaptor.capture()); - HttpRequestBase capturedRequest = requestCaptor.getValue(); + ArgumentCaptor requestCaptor = ArgumentCaptor.forClass(Request.class); + verify(mockHttpClient).newCall(requestCaptor.capture()); + Request capturedRequest = requestCaptor.getValue(); - assertTrue(capturedRequest instanceof HttpDelete); - assertEquals("DELETE", capturedRequest.getMethod()); + assertEquals("DELETE", capturedRequest.method()); assertEquals( "https://generativelanguage.googleapis.com/v1beta/" + TEST_PATH, - capturedRequest.getURI().toString()); - Header authHeader = capturedRequest.getFirstHeader("x-goog-api-key"); - assertNotNull(authHeader); - assertEquals(API_KEY, authHeader.getValue()); - assertNull(capturedRequest.getFirstHeader("Authorization")); + capturedRequest.url().toString()); + assertNotNull(capturedRequest.header("x-goog-api-key")); + assertEquals(API_KEY, capturedRequest.header("x-goog-api-key")); + assertNull(capturedRequest.header("Authorization")); } @Test @@ -197,17 +198,27 @@ public void testRequestWithHttpOptions() throws Exception { client.request("POST", TEST_PATH, TEST_REQUEST_JSON, REQUEST_HTTP_OPTIONS); // Assert - ArgumentCaptor requestCaptor = ArgumentCaptor.forClass(HttpRequestBase.class); - verify(mockHttpClient).execute(requestCaptor.capture()); - HttpRequestBase capturedRequest = requestCaptor.getValue(); + ArgumentCaptor requestCaptor = ArgumentCaptor.forClass(Request.class); + verify(mockHttpClient).newCall(requestCaptor.capture()); + Request capturedRequest = requestCaptor.getValue(); - assertTrue(capturedRequest instanceof HttpPost); - assertEquals("POST", capturedRequest.getMethod()); + assertEquals("POST", capturedRequest.method()); // The request URL is set by the request-level http options. - assertEquals("test-url/test-api-version/" + TEST_PATH, capturedRequest.getURI().toString()); - Header authHeader = capturedRequest.getFirstHeader("Authorization"); + assertEquals("http://test-url/test-api-version/" + TEST_PATH, capturedRequest.url().toString()); // Request should have the header set by the request-level http options. - assertEquals("header", capturedRequest.getFirstHeader("test").getValue()); + assertEquals("header", capturedRequest.header("test")); + } + + @Test + public void testRequestWithInvalidHttpMethod() throws Exception { + // Arrange + HttpApiClient client = + new HttpApiClient(Optional.of(API_KEY), Optional.empty(), Optional.empty()); + + // Act & Assert + assertThrows( + IllegalArgumentException.class, + () -> client.request("INVALID_METHOD", TEST_PATH, TEST_REQUEST_JSON, Optional.empty())); } @Test @@ -312,12 +323,10 @@ public void testHttpClientMLDevTimeout() throws Exception { HttpApiClient client = new HttpApiClient(Optional.of("api-key"), Optional.of(httpOptions), Optional.empty()); - CloseableHttpClient httpClient = client.httpClient(); + OkHttpClient httpClient = client.httpClient(); assertNotNull(httpClient); - RequestConfig config = getRequestConfig(httpClient); - - assertEquals(5000, config.getConnectTimeout()); + assertEquals(5000, httpClient.connectTimeoutMillis()); assertEquals("api-key", client.apiKey()); assertFalse(client.vertexAI()); } @@ -333,12 +342,10 @@ public void testHttpClientVertexTimeout() throws Exception { new HttpApiClient( project, location, credentials, Optional.of(httpOptions), Optional.empty()); - CloseableHttpClient httpClient = client.httpClient(); + OkHttpClient httpClient = client.httpClient(); assertNotNull(httpClient); - RequestConfig config = getRequestConfig(httpClient); - - assertEquals(4999, config.getConnectTimeout()); + assertEquals(4999, httpClient.connectTimeoutMillis()); assertEquals("project", client.project()); assertEquals("location", client.location()); assertTrue(client.vertexAI()); @@ -350,12 +357,10 @@ public void testHttpClientNoTimeout() throws Exception { HttpApiClient client = new HttpApiClient(Optional.of("api-key"), Optional.of(httpOptions), Optional.empty()); - CloseableHttpClient httpClient = client.httpClient(); + OkHttpClient httpClient = client.httpClient(); assertNotNull(httpClient); - RequestConfig config = getRequestConfig(httpClient); - - assertEquals(-1, config.getConnectTimeout()); + assertEquals(0, httpClient.connectTimeoutMillis()); assertEquals("api-key", client.apiKey()); assertFalse(client.httpOptions.headers().get().containsKey("X-Server-Timeout")); } @@ -371,12 +376,10 @@ public void testHttpClientVertexNoTimeout() throws Exception { new HttpApiClient( project, location, credentials, Optional.of(httpOptions), Optional.empty()); - CloseableHttpClient httpClient = client.httpClient(); + OkHttpClient httpClient = client.httpClient(); assertNotNull(httpClient); - RequestConfig config = getRequestConfig(httpClient); - - assertEquals(-1, config.getConnectTimeout()); + assertEquals(0, httpClient.connectTimeoutMillis()); assertEquals("project", client.project()); assertEquals("location", client.location()); assertTrue(client.vertexAI()); @@ -390,13 +393,12 @@ public void testHttpClientMldevCustomClientOptions() throws Exception { HttpApiClient client = new HttpApiClient(Optional.of("api-key"), Optional.empty(), Optional.of(clientOptions)); - PoolingHttpClientConnectionManager connectionManager = - getConnectionManager(client.httpClient()); + Dispatcher dispatcher = client.httpClient().dispatcher(); assertEquals("api-key", client.apiKey()); assertFalse(client.vertexAI()); - assertEquals(64, connectionManager.getMaxTotal()); - assertEquals(16, connectionManager.getDefaultMaxPerRoute()); + assertEquals(64, dispatcher.getMaxRequests()); + assertEquals(16, dispatcher.getMaxRequestsPerHost()); } @Test @@ -411,14 +413,13 @@ public void testHttpClientVertexCustomClientOptions() throws Exception { Optional.empty(), Optional.of(clientOptions)); - PoolingHttpClientConnectionManager connectionManager = - getConnectionManager(client.httpClient()); + Dispatcher dispatcher = client.httpClient().dispatcher(); assertEquals("project", client.project()); assertEquals("location", client.location()); assertTrue(client.vertexAI()); - assertEquals(64, connectionManager.getMaxTotal()); - assertEquals(16, connectionManager.getDefaultMaxPerRoute()); + assertEquals(64, dispatcher.getMaxRequests()); + assertEquals(16, dispatcher.getMaxRequestsPerHost()); } @Test @@ -426,30 +427,17 @@ public void testHttpClientMldevDefaultClientOptions() throws Exception { HttpApiClient client = new HttpApiClient(Optional.of("api-key"), Optional.empty(), Optional.empty()); - PoolingHttpClientConnectionManager connectionManager = - getConnectionManager(client.httpClient()); + Dispatcher dispatcher = client.httpClient().dispatcher(); - // Default values for max connections and max connections per host are 20 and 2 respectively - // (set by the Apache HttpClient). - assertEquals(20, connectionManager.getMaxTotal()); - assertEquals(2, connectionManager.getDefaultMaxPerRoute()); + // Default values for max connections and max connections per host are 64 and 5 respectively + // (set by OkHttp). When maxConnectionsPerHost is not set, the dispatcher's maxRequestsPerHost + // should be equal to 5. + assertEquals(64, dispatcher.getMaxRequests()); + assertEquals(5, dispatcher.getMaxRequestsPerHost()); assertEquals("api-key", client.apiKey()); assertFalse(client.vertexAI()); } - private RequestConfig getRequestConfig(CloseableHttpClient client) throws Exception { - Field configField = client.getClass().getDeclaredField("defaultConfig"); - configField.setAccessible(true); - return (RequestConfig) configField.get(client); - } - - private PoolingHttpClientConnectionManager getConnectionManager(CloseableHttpClient client) - throws Exception { - Field connectionManagerField = client.getClass().getDeclaredField("connManager"); - connectionManagerField.setAccessible(true); - return (PoolingHttpClientConnectionManager) connectionManagerField.get(client); - } - @Test public void testHttpClientWithCustomCredentials() throws Exception { GoogleCredentials credentials = Mockito.mock(GoogleCredentials.class); diff --git a/src/test/java/com/google/genai/UploadClientTest.java b/src/test/java/com/google/genai/UploadClientTest.java index d8c8e0fa7f6..77de9049af8 100644 --- a/src/test/java/com/google/genai/UploadClientTest.java +++ b/src/test/java/com/google/genai/UploadClientTest.java @@ -28,10 +28,10 @@ import java.io.InputStream; import java.util.ArrayList; import java.util.Random; -import org.apache.http.HttpEntity; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import okhttp3.ResponseBody; public class UploadClientTest { @@ -61,37 +61,37 @@ public void setUp() { @Test public void upload_file_success() throws IOException { UploadClient uploadClient = new UploadClient(API_CLIENT, CHUNK_SIZE); - HttpEntity entity = uploadClient.upload(UPLOAD_URL, FILE_PATH); + ResponseBody responseBody = uploadClient.upload(UPLOAD_URL, FILE_PATH); assertBytesEqual(testBytes, API_CLIENT.files.get(UPLOAD_URL).uploadedBytes); - assertNotNull(entity); + assertNotNull(responseBody); } @Test public void upload_bytes_success() throws IOException { UploadClient uploadClient = new UploadClient(API_CLIENT, CHUNK_SIZE); - HttpEntity entity = uploadClient.upload(UPLOAD_URL, testBytes); + ResponseBody responseBody = uploadClient.upload(UPLOAD_URL, testBytes); assertBytesEqual(testBytes, API_CLIENT.files.get(UPLOAD_URL).uploadedBytes); - assertNotNull(entity); + assertNotNull(responseBody); } @Test public void upload_stream_success() throws IOException { UploadClient uploadClient = new UploadClient(API_CLIENT, CHUNK_SIZE); - HttpEntity entity; + ResponseBody responseBody; try (InputStream inputStream = new FileInputStream(FILE_PATH)) { - entity = uploadClient.upload(UPLOAD_URL, inputStream, testBytes.length); + responseBody = uploadClient.upload(UPLOAD_URL, inputStream, testBytes.length); } assertBytesEqual(testBytes, API_CLIENT.files.get(UPLOAD_URL).uploadedBytes); - assertNotNull(entity); + assertNotNull(responseBody); } @Test public void upload_file_with_retriable_error_success() throws IOException { API_CLIENT.makeFileUploadFail(UPLOAD_URL, 1); UploadClient uploadClient = new UploadClient(API_CLIENT, CHUNK_SIZE); - HttpEntity entity = uploadClient.upload(UPLOAD_URL, FILE_PATH); + ResponseBody responseBody = uploadClient.upload(UPLOAD_URL, FILE_PATH); assertBytesEqual(testBytes, API_CLIENT.files.get(UPLOAD_URL).uploadedBytes); - assertNotNull(entity); + assertNotNull(responseBody); } @Test diff --git a/src/test/java/com/google/genai/errors/ApiExceptionTest.java b/src/test/java/com/google/genai/errors/ApiExceptionTest.java index a2a1f3898f9..861231f7b2d 100644 --- a/src/test/java/com/google/genai/errors/ApiExceptionTest.java +++ b/src/test/java/com/google/genai/errors/ApiExceptionTest.java @@ -22,26 +22,18 @@ import static org.junit.jupiter.api.Assertions.assertInstanceOf; import static org.junit.jupiter.api.Assertions.assertThrows; -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.nio.charset.StandardCharsets; -import java.util.Locale; -import org.apache.http.Header; -import org.apache.http.HttpEntity; -import org.apache.http.HttpStatus; -import org.apache.http.HttpVersion; -import org.apache.http.StatusLine; -import org.apache.http.client.methods.CloseableHttpResponse; -import org.apache.http.message.BasicStatusLine; -import org.apache.http.params.HttpParams; +import okhttp3.MediaType; +import okhttp3.Protocol; +import okhttp3.Request; +import okhttp3.Response; +import okhttp3.ResponseBody; import org.junit.jupiter.api.Test; class ApiExceptionTest { @Test - void testThrowFromResponse_OKStatus_DoesNotThrow() { - CloseableHttpResponse response = createFakeResponse(HttpStatus.SC_OK, "OK", ""); + void testThrowFromResponse_200Status_DoesNotThrow() { + Response response = createFakeResponse(200, "OK", ""); assertDoesNotThrow(() -> ApiException.throwFromResponse(response)); } @@ -51,49 +43,42 @@ void testThrowFromResponse_ClientError_ThrowsClientException() { String status = "Bad Request"; String message = "Invalid request"; String jsonBody = String.format("{ \"error\": { \"message\": \"%s\" } }", message); - CloseableHttpResponse response = - createFakeResponse(HttpStatus.SC_BAD_REQUEST, status, jsonBody); + Response response = createFakeResponse(400, status, jsonBody); ClientException thrown = assertThrows(ClientException.class, () -> ApiException.throwFromResponse(response)); assertInstanceOf(ClientException.class, thrown); - assertEquals(HttpStatus.SC_BAD_REQUEST, thrown.code()); + assertEquals(400, thrown.code()); assertEquals(status, thrown.status()); assertEquals(message, thrown.message()); - assertEquals( - String.format("%d %s. %s", HttpStatus.SC_BAD_REQUEST, status, message), - thrown.getMessage()); + assertEquals(String.format("%d %s. %s", 400, status, message), thrown.getMessage()); } @Test - void testThrowFromResponse_ServerError_ThrowsServerException() throws IOException { - String status = "Internal Server Error"; - String message = "Server fault"; + void testThrowFromResponse_ServerError_ThrowsServerException() { + String status = "Internal Server Error"; + String message = "Server fault"; String jsonBody = String.format("{ \"error\": { \"message\": \"%s\" } }", message); - CloseableHttpResponse response = - createFakeResponse(HttpStatus.SC_INTERNAL_SERVER_ERROR, status, jsonBody); + Response response = createFakeResponse(500, status, jsonBody); // Act & Assert ServerException thrown = assertThrows(ServerException.class, () -> ApiException.throwFromResponse(response)); assertInstanceOf(ServerException.class, thrown); - assertEquals(HttpStatus.SC_INTERNAL_SERVER_ERROR, thrown.code()); + assertEquals(500, thrown.code()); assertEquals(status, thrown.status()); assertEquals(message, thrown.message()); - assertEquals( - String.format("%d %s. %s", HttpStatus.SC_INTERNAL_SERVER_ERROR, status, message), - thrown.getMessage()); + assertEquals(String.format("%d %s. %s", 500, status, message), thrown.getMessage()); } @Test - void testThrowFromResponse_OtherError_ThrowsApiException() throws IOException { + void testThrowFromResponse_OtherError_ThrowsApiException() { String status = "Moved Permanently"; - CloseableHttpResponse response = - createFakeResponse(HttpStatus.SC_MOVED_PERMANENTLY, status, ""); + Response response = createFakeResponse(301, status, ""); ApiException thrown = assertThrows(ApiException.class, () -> ApiException.throwFromResponse(response)); @@ -101,49 +86,44 @@ void testThrowFromResponse_OtherError_ThrowsApiException() throws IOException { assertFalse(thrown instanceof ClientException); assertFalse(thrown instanceof ServerException); - assertEquals(HttpStatus.SC_MOVED_PERMANENTLY, thrown.code()); + assertEquals(301, thrown.code()); assertEquals(status, thrown.status()); assertEquals("", thrown.message()); - assertEquals( - String.format("%d %s. ", HttpStatus.SC_MOVED_PERMANENTLY, status), thrown.getMessage()); + assertEquals(String.format("%d %s. ", 301, status), thrown.getMessage()); } @Test void testGetErrorMessage_ValidMessage() { - CloseableHttpResponse response = - createFakeResponse( - HttpStatus.SC_BAD_REQUEST, "Bad", "{ \"error\": { \"message\": \"test message\" } }"); + Response response = + createFakeResponse(400, "Bad", "{ \"error\": { \"message\": \"test message\" } }"); String message = ApiException.getErrorMessageFromResponse(response); assertEquals("test message", message); } @Test void testGetErrorMessage_NoErrorNode() { - CloseableHttpResponse response = createFakeResponse(HttpStatus.SC_BAD_REQUEST, "Bad", "{}"); + Response response = createFakeResponse(400, "Bad", "{}"); String message = ApiException.getErrorMessageFromResponse(response); assertEquals("", message); } @Test void testGetErrorMessage_NoMessageNode() { - CloseableHttpResponse response = - createFakeResponse(HttpStatus.SC_BAD_REQUEST, "Bad", "{ \"error\": {} }"); + Response response = createFakeResponse(400, "Bad", "{ \"error\": {} }"); String message = ApiException.getErrorMessageFromResponse(response); assertEquals("", message); } @Test void testGetErrorMessage_MessageNotText() { - CloseableHttpResponse response = - createFakeResponse(HttpStatus.SC_BAD_REQUEST, "Bad", "{ \"error\": {\"message\": 123} }"); + Response response = createFakeResponse(400, "Bad", "{ \"error\": {\"message\": 123} }"); String message = ApiException.getErrorMessageFromResponse(response); assertEquals("", message); } @Test void testGetErrorMessage_InvalidJson() { - CloseableHttpResponse response = - createFakeResponse(HttpStatus.SC_BAD_REQUEST, "Bad", "not json"); + Response response = createFakeResponse(400, "Bad", "not json"); String message = ApiException.getErrorMessageFromResponse(response); // JsonProcessingException is caught and ignored, returns "" assertEquals("", message); @@ -151,234 +131,19 @@ void testGetErrorMessage_InvalidJson() { @Test void testGetErrorMessage_EmptyBody() { - CloseableHttpResponse response = createFakeResponse(HttpStatus.SC_BAD_REQUEST, "Bad", ""); + Response response = createFakeResponse(400, "Bad", ""); String message = ApiException.getErrorMessageFromResponse(response); assertEquals("", message); } // Helper Methods - private static CloseableHttpResponse createFakeResponse( - int statusCode, String reasonPhrase, String responseBody) { - HttpEntity entity = (responseBody != null) ? new FakeHttpEntity(responseBody) : null; - return createFakeResponse(statusCode, reasonPhrase, entity); - } - - private static CloseableHttpResponse createFakeResponse( - int statusCode, String reasonPhrase, HttpEntity entity) { - StatusLine statusLine = new BasicStatusLine(HttpVersion.HTTP_1_1, statusCode, reasonPhrase); - return new FakeHttpResponse(statusLine, entity); - } - - // Fake/Stub Implementations - static class FakeHttpResponse implements CloseableHttpResponse { - private final StatusLine statusLine; - private final HttpEntity entity; - - FakeHttpResponse(StatusLine statusLine, HttpEntity entity) { - this.statusLine = statusLine; - this.entity = entity; - } - - @Override - public StatusLine getStatusLine() { - return statusLine; - } - - @Override - public HttpEntity getEntity() { - return entity; - } - - @Override - public void close() throws IOException {} - - // --- Minimal implementation of other methods --- - @Override - public Locale getLocale() { - return Locale.getDefault(); - } - - @Override - public void setStatusLine(StatusLine statusline) {} - - @Override - public void setStatusLine(org.apache.http.ProtocolVersion ver, int code) {} - - @Override - public void setStatusLine(org.apache.http.ProtocolVersion ver, int code, String reason) {} - - @Override - public void setStatusCode(int code) throws IllegalStateException {} - - @Override - public void setReasonPhrase(String reason) throws IllegalStateException {} - - @Override - public void setEntity(HttpEntity entity) {} - - @Override - public void setLocale(Locale loc) {} - - @Override - public org.apache.http.ProtocolVersion getProtocolVersion() { - return HttpVersion.HTTP_1_1; - } - - @Override - public boolean containsHeader(String name) { - return false; - } - - @Override - public Header[] getHeaders(String name) { - return new Header[0]; - } - - @Override - public Header getFirstHeader(String name) { - return null; - } - - @Override - public Header getLastHeader(String name) { - return null; - } - - @Override - public Header[] getAllHeaders() { - return new Header[0]; - } - - @Override - public void addHeader(Header header) {} - - @Override - public void addHeader(String name, String value) {} - - @Override - public void setHeader(Header header) {} - - @Override - public void setHeader(String name, String value) {} - - @Override - public void setHeaders(Header[] headers) {} - - @Override - public void removeHeader(Header header) {} - - @Override - public void removeHeaders(String name) {} - - @Override - public org.apache.http.HeaderIterator headerIterator() { - return null; - } - - @Override - public org.apache.http.HeaderIterator headerIterator(String name) { - return null; - } - - @Override - public HttpParams getParams() { - return null; - } - - @Override - public void setParams(HttpParams params) {} - } - - static class FakeHttpEntity implements HttpEntity { - private final InputStream content; - private final long length; - private final boolean repeatable; - - FakeHttpEntity(String contentString) { - if (contentString != null) { - byte[] bytes = contentString.getBytes(StandardCharsets.UTF_8); - this.content = new ByteArrayInputStream(bytes); - this.length = bytes.length; - this.repeatable = true; - } else { - this.content = null; - this.length = 0; - this.repeatable = true; - } - } - - FakeHttpEntity(InputStream inputStream) { - this.content = inputStream; - this.length = -1; - this.repeatable = inputStream.markSupported(); - } - - @Override - public boolean isRepeatable() { - return repeatable; - } - - @Override - public boolean isChunked() { - return false; - } - - @Override - public long getContentLength() { - return length; - } - - @Override - public Header getContentType() { - return null; - } - - @Override - public Header getContentEncoding() { - return null; - } - - @Override - public InputStream getContent() throws IOException, UnsupportedOperationException { - if (content == null) { - return null; // EntityUtils.toString handles null stream input - } - // Reset if repeatable and mark is supported - if (isRepeatable() && content.markSupported()) { - try { - // Ensure mark was called if needed, or assume start for ByteArrayInputStream - if (content instanceof ByteArrayInputStream) { - content.reset(); - } - } catch (IOException e) { - // Should not happen with ByteArrayInputStream that supports mark/reset - throw new RuntimeException("Failed to reset repeatable stream", e); - } - } - return content; - } - - @Override - public void writeTo(java.io.OutputStream outstream) throws IOException {} - - @Override - public boolean isStreaming() { - return !isRepeatable(); - } - - @Override - public void consumeContent() throws IOException {} - } - - static class FaultyInputStream extends InputStream { - @Override - public int read() throws IOException { - throw new IOException("Simulated read error"); - } - - @Override - public int read(byte[] b, int off, int len) throws IOException { - throw new IOException("Simulated read error"); - } + private static Response createFakeResponse(int statusCode, String reasonPhrase, String body) { + return new Response.Builder() + .request(new Request.Builder().url("http://example.com").build()) + .protocol(Protocol.HTTP_1_1) + .code(statusCode) + .message(reasonPhrase) + .body(body != null ? ResponseBody.create(MediaType.get("application/json"), body) : null) + .build(); } } From b3ee3b84cb723c8c161b525350cd73dda177dbdd Mon Sep 17 00:00:00 2001 From: Jaycee Li Date: Wed, 2 Jul 2025 09:47:10 -0700 Subject: [PATCH 056/602] chore: Refactor request match logic in replay tests chore: Support loading response from replay files chore: Implement path redaction in replay tests chore: Enable replay mode in all table tests PiperOrigin-RevId: 778540794 --- src/main/java/com/google/genai/ApiClient.java | 126 +++++++ src/main/java/com/google/genai/Client.java | 3 - src/main/java/com/google/genai/Common.java | 23 +- .../java/com/google/genai/HttpApiClient.java | 102 +---- .../com/google/genai/ReplayApiClient.java | 353 +++++++++++++----- .../com/google/genai/ReplayApiResponse.java | 12 +- .../com/google/genai/errors/ApiException.java | 28 ++ .../com/google/genai/types/ReplayFile.java | 4 +- .../com/google/genai/types/ReplayRequest.java | 4 +- .../google/genai/types/ReplayResponse.java | 12 +- .../java/com/google/genai/ModelsTest.java | 1 - src/test/java/com/google/genai/TableTest.java | 199 +--------- 12 files changed, 474 insertions(+), 393 deletions(-) diff --git a/src/main/java/com/google/genai/ApiClient.java b/src/main/java/com/google/genai/ApiClient.java index 172e8c5cc9b..59abde6fa8c 100644 --- a/src/main/java/com/google/genai/ApiClient.java +++ b/src/main/java/com/google/genai/ApiClient.java @@ -20,7 +20,9 @@ import static com.google.common.collect.ImmutableMap.toImmutableMap; import com.google.auth.oauth2.GoogleCredentials; +import com.google.common.base.Ascii; import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; import com.google.errorprone.annotations.CanIgnoreReturnValue; import com.google.genai.errors.GenAiIOException; import com.google.genai.types.ClientOptions; @@ -32,9 +34,13 @@ import java.util.logging.Logger; import java.util.stream.Stream; import okhttp3.Dispatcher; +import okhttp3.MediaType; import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.RequestBody; import org.jspecify.annotations.Nullable; + /** Interface for an API client which issues HTTP requests to the GenAI APIs. */ abstract class ApiClient { @@ -43,6 +49,12 @@ abstract class ApiClient { // {x-version-update-end:google-genai:released} private static final Logger logger = Logger.getLogger(ApiClient.class.getName()); + private static final ImmutableSet METHODS_WITH_BODY = + ImmutableSet.of("POST", "PATCH", "PUT"); + + private static final ImmutableSet VALID_HTTP_METHODS = + ImmutableSet.builder().addAll(METHODS_WITH_BODY).add("GET").add("DELETE").build(); + final OkHttpClient httpClient; HttpOptions httpOptions; final boolean vertexAI; @@ -176,6 +188,120 @@ private OkHttpClient createHttpClient( return builder.build(); } + /** Builds a HTTP request given the http method, path, and request json string. */ + protected Request buildRequest( + String httpMethod, + String path, + String requestJson, + Optional requestHttpOptions) { + String capitalizedHttpMethod = Ascii.toUpperCase(httpMethod); + boolean queryBaseModel = + capitalizedHttpMethod.equals("GET") && path.startsWith("publishers/google/models"); + if (this.vertexAI() && !path.startsWith("projects/") && !queryBaseModel) { + path = + String.format("projects/%s/locations/%s/", this.project.get(), this.location.get()) + + path; + } + + HttpOptions mergedHttpOptions = mergeHttpOptions(requestHttpOptions.orElse(null)); + + String requestUrl; + + String baseUrl = + mergedHttpOptions + .baseUrl() + .orElseThrow(() -> new IllegalStateException("baseUrl is required.")); + if (baseUrl.endsWith("/")) { + // Sometimes users set the base URL with a trailing slash, so we need to remove it. + baseUrl = baseUrl.substring(0, baseUrl.length() - 1); + } + String apiVersion = + mergedHttpOptions + .apiVersion() + .orElseThrow(() -> new IllegalStateException("apiVersion is required.")); + + if (apiVersion.isEmpty()) { + requestUrl = String.format("%s/%s", baseUrl, path); + } else { + requestUrl = String.format("%s/%s/%s", baseUrl, apiVersion, path); + } + + if (!VALID_HTTP_METHODS.contains(capitalizedHttpMethod)) { + throw new IllegalArgumentException("Unsupported HTTP method: " + capitalizedHttpMethod); + } + + RequestBody body; + if (METHODS_WITH_BODY.contains(capitalizedHttpMethod)) { + body = RequestBody.create(requestJson, MediaType.parse("application/json")); + } else { + body = null; + } + Request.Builder requestBuilder = + new Request.Builder().url(requestUrl).method(capitalizedHttpMethod, body); + + setHeaders(requestBuilder, mergedHttpOptions); + return requestBuilder.build(); + } + + /** Builds a HTTP request given the http method, url, and request bytes. */ + protected Request buildRequest( + String httpMethod, + String url, + byte[] requestBytes, + Optional requestHttpOptions) { + HttpOptions mergedHttpOptions = mergeHttpOptions(requestHttpOptions.orElse(null)); + if (httpMethod.equalsIgnoreCase("POST")) { + RequestBody body = + RequestBody.create(MediaType.get("application/octet-stream"), requestBytes); + Request.Builder requestBuilder = new Request.Builder().url(url).post(body); + setHeaders(requestBuilder, mergedHttpOptions); + return requestBuilder.build(); + } else { + throw new IllegalArgumentException( + "The request method with bytes is only supported for POST. Unsupported HTTP method: " + + httpMethod); + } + } + + /** Sets the required headers (including auth) on the request object. */ + private void setHeaders(Request.Builder request, HttpOptions requestHttpOptions) { + for (Map.Entry header : + requestHttpOptions.headers().orElse(ImmutableMap.of()).entrySet()) { + request.header(header.getKey(), header.getValue()); + } + + if (apiKey.isPresent()) { + request.header("x-goog-api-key", apiKey.get()); + } else { + GoogleCredentials cred = + credentials.orElseThrow(() -> new IllegalStateException("credentials is required")); + try { + cred.refreshIfExpired(); + } catch (IOException e) { + throw new GenAiIOException("Failed to refresh credentials.", e); + } + String accessToken; + try { + accessToken = cred.getAccessToken().getTokenValue(); + } catch (NullPointerException e) { + // For test cases where the access token is not available. + if (e.getMessage() + .contains( + "because the return value of" + + " \"com.google.auth.oauth2.GoogleCredentials.getAccessToken()\" is null")) { + accessToken = ""; + } else { + throw e; + } + } + request.header("Authorization", "Bearer " + accessToken); + + if (cred.getQuotaProjectId() != null) { + request.header("x-goog-user-project", cred.getQuotaProjectId()); + } + } + } + /** Sends a Http request given the http method, path, and request json string. */ @CanIgnoreReturnValue public abstract ApiResponse request( diff --git a/src/main/java/com/google/genai/Client.java b/src/main/java/com/google/genai/Client.java index e6dffac145d..af13a9a258d 100644 --- a/src/main/java/com/google/genai/Client.java +++ b/src/main/java/com/google/genai/Client.java @@ -274,9 +274,7 @@ private Client( this.debugConfig = debugConfig.orElse(new DebugConfig()); if (this.debugConfig.clientMode().equals("replay") || this.debugConfig.clientMode().equals("auto")) { - System.out.println("Instantialing a client that will use Replay mode..."); if (!useVertexAI) { - System.out.println("Instantialing a replay client that will use Gemini API..."); this.apiClient = new ReplayApiClient( /* apiKey= */ apiKey, @@ -286,7 +284,6 @@ private Client( this.debugConfig.replayId(), this.debugConfig.clientMode()); } else { - System.out.println("Instantialing a replay client that will use Vertex AI APIs..."); this.apiClient = new ReplayApiClient( /* project= */ project, diff --git a/src/main/java/com/google/genai/Common.java b/src/main/java/com/google/genai/Common.java index 873e2bb33d5..f2547b25d55 100644 --- a/src/main/java/com/google/genai/Common.java +++ b/src/main/java/com/google/genai/Common.java @@ -231,7 +231,9 @@ public static String urlEncode(ObjectNode paramsNode) { if (valueNode.isNull()) { queryBuilder.add(encodedKey + "="); } else { - String encodedValue = URLEncoder.encode(valueNode.asText(""), utf8); + // In python(and replay files), "*" is encoded as "%2A" although it is not required. + // So we keep the same behavior here. + String encodedValue = URLEncoder.encode(valueNode.asText(""), utf8).replace("*", "%2A"); queryBuilder.add(encodedKey + "=" + encodedValue); } } @@ -240,4 +242,23 @@ public static String urlEncode(ObjectNode paramsNode) { } return queryBuilder.toString(); } + + /** Converts a snake_case string to camelCase. */ + static String snakeToCamel(String str) { + if (str == null || str.isEmpty()) { + return str; + } + + StringBuilder sb = new StringBuilder(); + boolean capitalizeNext = false; + for (char c : str.toCharArray()) { + if (c == '_') { + capitalizeNext = true; + } else { + sb.append(capitalizeNext ? Character.toUpperCase(c) : c); + capitalizeNext = false; + } + } + return sb.toString(); + } } diff --git a/src/main/java/com/google/genai/HttpApiClient.java b/src/main/java/com/google/genai/HttpApiClient.java index e00cbda699d..9297487403d 100644 --- a/src/main/java/com/google/genai/HttpApiClient.java +++ b/src/main/java/com/google/genai/HttpApiClient.java @@ -18,29 +18,17 @@ import com.google.api.core.InternalApi; import com.google.auth.oauth2.GoogleCredentials; -import com.google.common.base.Ascii; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableSet; import com.google.genai.errors.GenAiIOException; import com.google.genai.types.ClientOptions; import com.google.genai.types.HttpOptions; import java.io.IOException; -import java.util.Map; import java.util.Optional; -import okhttp3.MediaType; import okhttp3.Request; -import okhttp3.RequestBody; /** Base client for the HTTP APIs. This is for internal use only. */ @InternalApi public class HttpApiClient extends ApiClient { - private static final ImmutableSet METHODS_WITH_BODY = - ImmutableSet.of("POST", "PATCH", "PUT"); - - private static final ImmutableSet VALID_HTTP_METHODS = - ImmutableSet.builder().addAll(METHODS_WITH_BODY).add("GET").add("DELETE").build(); - /** Constructs an ApiClient for Google AI APIs. */ HttpApiClient( Optional apiKey, @@ -69,101 +57,17 @@ public HttpApiResponse request( String path, String requestJson, Optional requestHttpOptions) { - String capitalizedHttpMethod = Ascii.toUpperCase(httpMethod); - boolean queryBaseModel = - capitalizedHttpMethod.equals("GET") && path.startsWith("publishers/google/models"); - if (this.vertexAI() && !path.startsWith("projects/") && !queryBaseModel) { - path = - String.format("projects/%s/locations/%s/", this.project.get(), this.location.get()) - + path; - } - - HttpOptions mergedHttpOptions = mergeHttpOptions(requestHttpOptions.orElse(null)); - - String requestUrl; - - if (mergedHttpOptions.apiVersion().get().isEmpty()) { - requestUrl = String.format("%s/%s", mergedHttpOptions.baseUrl().get(), path); - } else { - requestUrl = - String.format( - "%s/%s/%s", - mergedHttpOptions.baseUrl().get(), mergedHttpOptions.apiVersion().get(), path); - } - if (!VALID_HTTP_METHODS.contains(capitalizedHttpMethod)) { - throw new IllegalArgumentException("Unsupported HTTP method: " + capitalizedHttpMethod); - } - - RequestBody body; - if (METHODS_WITH_BODY.contains(capitalizedHttpMethod)) { - body = RequestBody.create(requestJson, MediaType.parse("application/json")); - } else { - body = null; - } - Request.Builder requestBuilder = - new Request.Builder().url(requestUrl).method(capitalizedHttpMethod, body); - - setHeaders(requestBuilder, mergedHttpOptions); - return executeRequest(requestBuilder.build()); + return executeRequest(buildRequest(httpMethod, path, requestJson, requestHttpOptions)); } + /** Sends a Http request given the http method, path, request bytes, and http options. */ @Override public ApiResponse request( String httpMethod, String url, byte[] requestBytes, Optional requestHttpOptions) { - HttpOptions mergedHttpOptions = mergeHttpOptions(requestHttpOptions.orElse(null)); - if (httpMethod.equalsIgnoreCase("POST")) { - RequestBody body = - RequestBody.create(MediaType.get("application/octet-stream"), requestBytes); - Request.Builder requestBuilder = new Request.Builder().url(url).post(body); - setHeaders(requestBuilder, mergedHttpOptions); - return executeRequest(requestBuilder.build()); - } else { - throw new IllegalArgumentException( - "The request method with bytes is only supported for POST. Unsupported HTTP method: " - + httpMethod); - } - } - - /** Sets the required headers (including auth) on the request object. */ - private void setHeaders(Request.Builder requestBuilder, HttpOptions requestHttpOptions) { - for (Map.Entry header : - requestHttpOptions.headers().orElse(ImmutableMap.of()).entrySet()) { - requestBuilder.header(header.getKey(), header.getValue()); - } - - if (apiKey.isPresent()) { - requestBuilder.header("x-goog-api-key", apiKey.get()); - } else { - GoogleCredentials cred = - credentials.orElseThrow(() -> new IllegalStateException("credentials is required")); - try { - cred.refreshIfExpired(); - } catch (IOException e) { - throw new GenAiIOException("Failed to refresh credentials.", e); - } - String accessToken; - try { - accessToken = cred.getAccessToken().getTokenValue(); - } catch (NullPointerException e) { - // For test cases where the access token is not available. - if (e.getMessage() - .contains( - "because the return value of" - + " \"com.google.auth.oauth2.GoogleCredentials.getAccessToken()\" is null")) { - accessToken = ""; - } else { - throw e; - } - } - requestBuilder.header("Authorization", "Bearer " + accessToken); - - if (cred.getQuotaProjectId() != null) { - requestBuilder.header("x-goog-user-project", cred.getQuotaProjectId()); - } - } + return executeRequest(buildRequest(httpMethod, url, requestBytes, requestHttpOptions)); } /** Executes the given HTTP request. */ diff --git a/src/main/java/com/google/genai/ReplayApiClient.java b/src/main/java/com/google/genai/ReplayApiClient.java index 0d4f002bf5e..cb9fff41ed0 100644 --- a/src/main/java/com/google/genai/ReplayApiClient.java +++ b/src/main/java/com/google/genai/ReplayApiClient.java @@ -19,40 +19,44 @@ import static com.google.common.base.Preconditions.checkNotNull; import static java.util.stream.Collectors.joining; -import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; import com.google.auth.oauth2.GoogleCredentials; +import com.google.common.collect.ImmutableMap; import com.google.genai.errors.GenAiIOException; import com.google.genai.types.ClientOptions; import com.google.genai.types.HttpOptions; +import com.google.genai.types.ReplayFile; +import com.google.genai.types.ReplayInteraction; +import com.google.genai.types.ReplayRequest; +import com.google.genai.types.ReplayResponse; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; -import java.util.Arrays; -import java.util.LinkedHashMap; +import java.util.HashMap; import java.util.List; +import java.util.Locale; import java.util.Map; +import java.util.Objects; import java.util.Optional; import java.util.stream.Stream; import okhttp3.Headers; import okhttp3.MediaType; -import okhttp3.Protocol; import okhttp3.Request; -import okhttp3.Response; -import okhttp3.ResponseBody; - -// TODO(b/369384123): Currently the ReplayApiClient mirrors the HttpApiClient. We will refactor the -// ReplayApiClient to use the ReplayFile as part of resolving b/369384123. +import okhttp3.RequestBody; +import okio.Buffer; /** Base client for the HTTP APIs. */ @ExcludeFromGeneratedCoverageReport final class ReplayApiClient extends ApiClient { + private final String clientMode; private final String replaysDirectory; private String replayId; - private final String clientMode; - private Map replaySession = null; - private int replayIndex = -1; + private int replayInteractionIndex; + private List replayInteractions; /** Constructs an ApiClient for Google AI APIs. */ ReplayApiClient( @@ -92,6 +96,7 @@ final class ReplayApiClient extends ApiClient { this.clientMode = clientMode; } + /** Reads a string from a file path. */ static String readString(Path path) { try (Stream stream = Files.lines(path)) { return stream.collect(joining(System.lineSeparator())); @@ -100,104 +105,270 @@ static String readString(Path path) { } } - static Map loadReplayData(String replayId) { - String replaysPath = System.getenv("GOOGLE_GENAI_REPLAYS_DIRECTORY"); - if (replaysPath == null) { - throw new RuntimeException("GOOGLE_GENAI_REPLAYS_DIRECTORY is not set"); - } - String testsReplaysPath = replaysPath + "/tests"; - String replayPath = testsReplaysPath + "/" + replayId; - // Open the replay file if it exists. - try { - String replayData = readString(Paths.get(replayPath)); - // TODO(b/369384123): Parsing to a ReplaySession object is not working because snake_case - // fields like body_segments are not being populated. For now, we will just use basic JSON - // parsing and switch to the generated JSON classes once we have the replays working. - // convert JSON string to Map - return JsonSerializable.objectMapper.readValue( - replayData, new TypeReference>() {}); - } catch (IOException e) { - throw new GenAiIOException("Failed to read replay file: " + e, e); - } - } - + /** Initializes the replay session. */ void initializeReplaySession(String replayId) { this.replayId = replayId; String replayPath = this.replaysDirectory + "/" + this.replayId; - // Open the replay file if it exists. - try { - String replayData = readString(Paths.get(replayPath)); - // TODO(b/369384123): Parsing to a ReplaySession object is not working because snake_case - // fields like body_segments are not being populated. For now, we will just use basic JSON - // parsing and switch to the generated JSON classes once we have the replays working. - // convert JSON string to Map - Map map = - JsonSerializable.objectMapper.readValue( - replayData, new TypeReference>() {}); - this.replaySession = map; - this.replayIndex = 0; - } catch (IOException e) { - throw new GenAiIOException("Failed to read replay file: " + e, e); - } + String replayData = readString(Paths.get(replayPath)); + this.replayInteractions = + ReplayFile.fromJson(replayData) + .interactions() + .orElseThrow( + () -> + new GenAiIOException( + String.format( + "The replay file %s does not have interactions.", replayPath))); + this.replayInteractionIndex = 0; } /** Sends a Http Post request given the path and request json string. */ - @SuppressWarnings("unchecked") @Override public ApiResponse request( String httpMethod, String path, String requestJson, Optional httpOptions) { if (this.clientMode.equals("replay") || this.clientMode.equals("auto")) { - System.out.println(" === Using replay for ID: " + this.replayId); - List interactions = Arrays.asList(this.replaySession.get("interactions")); - // TODO(b/369384123): Ensure the replay is correctly loaded by index for multi-turn - // conversations. - Object currentInteraction = Arrays.asList(interactions.get(this.replayIndex)).get(0); - LinkedHashMap currentMember = - ((ArrayList>) currentInteraction).get(0); - Map responseMap = (Map) currentMember.get("response"); - Integer statusCode = (Integer) responseMap.get("status_code"); - List bodySegments = (List) responseMap.get("body_segments"); - Map headerMap = (Map) responseMap.get("headers"); - StringBuilder responseBody = new StringBuilder(); - for (Object bodySegment : bodySegments) { - responseBody.append(bodySegment.toString()); - } - - // Create a dummy request, which is required by the Response.Builder - Request dummyRequest = - new Request.Builder() - .url("https://replay.googleapis.com" + path) - .method(httpMethod, null) - .build(); - Headers.Builder headersBuilder = new Headers.Builder(); - headerMap.forEach(headersBuilder::add); - Headers okHttpHeaders = headersBuilder.build(); - String responseString = responseBody.toString(); - String contentType = okHttpHeaders.get("Content-Type"); - MediaType mediaType = - (contentType != null) - ? MediaType.parse(contentType) - : MediaType.parse("application/json; charset=utf-8"); - ResponseBody okHttpResponseBody = ResponseBody.create(responseString, mediaType); - Response okHttpResponse = - new Response.Builder() - .request(dummyRequest) - .protocol(Protocol.HTTP_1_1) - .code(statusCode) - .message("OK") - .headers(okHttpHeaders) - .body(okHttpResponseBody) - .build(); - return new ReplayApiResponse(okHttpResponse.body(), statusCode, okHttpHeaders); + ReplayInteraction currentInteraction = replayInteractions.get(this.replayInteractionIndex); + this.replayInteractionIndex++; + matchRequest( + currentInteraction.request().orElse(null), + buildRequest(httpMethod, path, requestJson, httpOptions)); + return buildResponseFromReplay(currentInteraction.response().orElse(null)); } else { // Note that if the client mode is "api", then the ReplayApiClient will not be used. throw new IllegalArgumentException("Invalid client mode: " + this.clientMode); } } + /** Sends a Http request given the http method, path, request bytes, and http options. */ @Override public ApiResponse request( String httpMethod, String path, byte[] requestBytes, Optional httpOptions) { throw new UnsupportedOperationException("Not implemented yet."); } + + /** Makes sure the replay request matches the actual request message. */ + private void matchRequest(ReplayRequest replayRequest, Request actualRequest) { + if (replayRequest == null) { + throw new IllegalArgumentException("Replay request is null."); + } + + // Match request method. + String replayMethod = replayRequest.method().orElse("").toLowerCase(Locale.ROOT); + String actualMethod = actualRequest.method().toLowerCase(Locale.ROOT); + if (!equalsIgnoreKeyCase(replayMethod, actualMethod)) { + throw new AssertionError( + String.format( + "Request method mismatch:\nReplay: %s\nActual: %s", replayMethod, actualMethod)); + } + + // Match request url. + String replayPath = replayRequest.url().orElse(""); + String actualPath = redactRequestUrl(actualRequest.url().toString()); + if (!equalsIgnoreKeyCase(replayPath, actualPath)) { + throw new AssertionError( + String.format("Request url mismatch:\nReplay: %s\nActual: %s", replayPath, actualPath)); + } + + // Match request headers. + Map replayHeaders = replayRequest.headers().orElse(ImmutableMap.of()); + Map actualHeaders = new HashMap<>(); + Map> headersMap = actualRequest.headers().toMultimap(); + for (Map.Entry> entry : headersMap.entrySet()) { + actualHeaders.put(entry.getKey(), String.join(" ", entry.getValue())); + } + actualHeaders = redactRequestHeaders(actualHeaders); + if (!equalsIgnoreKeyCase(replayHeaders, actualHeaders)) { + throw new AssertionError( + String.format( + "Request headers mismatch:\nReplay: %s\nActual: %s", replayHeaders, actualHeaders)); + } + + // Match request body. + if (actualMethod.equals("get") || actualMethod.equals("delete")) { + // No body for these request methods. + return; + } + JsonNode actualBody = + redactRequestBody( + JsonSerializable.stringToJsonNode(requestBodyToString(actualRequest.body()))); + JsonNode replayBody = + JsonSerializable.toJsonNode(replayRequest.bodySegments().orElse(new ArrayList<>()).get(0)); + if (!equalsIgnoreKeyCase(replayBody, actualBody)) { + throw new AssertionError( + String.format("Request body mismatch:\nReplay: %s\nActual: %s", replayBody, actualBody)); + } + } + + /** Builds the response from a {@link ReplayResponse}. */ + private ReplayApiResponse buildResponseFromReplay(ReplayResponse replayResponse) { + if (replayResponse == null) { + throw new IllegalArgumentException("Replay response is null."); + } + // Replay response body_segments is a list of JSON objects for streaming support. Here we + // only read the first body segment. + // TODO(jayceeli): Support streaming responses. + JsonNode bodyNode = + JsonSerializable.toJsonNode(replayResponse.bodySegments().orElse(new ArrayList<>()).get(0)); + Headers headers = Headers.of(replayResponse.headers().orElse(ImmutableMap.of())); + return new ReplayApiResponse(bodyNode, replayResponse.statusCode().orElse(0), headers); + } + + /** + * Redact all the url parts before the resource name, so the test can work against any project, + * location, version, or whether it's EasyGCP. + */ + private static String redactRequestUrl(String requestUrl) { + String result = + requestUrl.replaceAll(".*/projects/[^/]+/locations/[^/]+/", "{VERTEX_URL_PREFIX}/"); + + result = result.replaceAll(".*-aiplatform.googleapis.com/[^/]+/", "{VERTEX_URL_PREFIX}/"); + + result = result.replaceAll(".*aiplatform.googleapis.com/[^/]+/", "{VERTEX_URL_PREFIX}/"); + + result = + result.replaceAll("https://generativelanguage.googleapis.com/[^/]+", "{MLDEV_URL_PREFIX}"); + + return result; + } + + /** Redact all the request headers that are not robust to replay files. */ + private static Map redactRequestHeaders(Map headers) { + Map redactedHeaders = new HashMap<>(); + + for (Map.Entry entry : headers.entrySet()) { + String headerName = entry.getKey(); + String headerValue = entry.getValue(); + + switch (headerName.toLowerCase(Locale.ROOT)) { + case "x-goog-api-key": + redactedHeaders.put(headerName, "{REDACTED}"); + break; + + case "user-agent": + case "x-goog-api-client": + String redactedValue = + headerValue + .replaceAll("\\d+\\.\\d+\\.\\d+", "{VERSION_NUMBER}") + .replace("gl-java/", "{LANGUAGE_LABEL}/"); + redactedHeaders.put(headerName, redactedValue); + break; + + case "x-goog-user-project": + case "authorization": + break; + + default: + redactedHeaders.put(headerName, headerValue); + break; + } + } + return redactedHeaders; + } + + /** Redact the request body to make it robust to replay files. */ + private static JsonNode redactRequestBody(JsonNode requestBody) { + ObjectNode redactedNode = JsonSerializable.objectMapper.createObjectNode(); + requestBody + .fields() + .forEachRemaining( + entry -> { + if (entry.getValue().isTextual()) { + redactedNode.set( + entry.getKey(), + JsonSerializable.toJsonNode( + entry + .getValue() + .asText() + .replaceAll( + "projects/[^/]+/locations/[^/]+/", + "{PROJECT_AND_LOCATION_PATH}/"))); + } else { + redactedNode.set(entry.getKey(), entry.getValue()); + } + }); + return redactedNode; + } + + /** + * Normalizes the key casing(snake vs camel) for a given object. + * + *

e.g., {'my_key': 'my_value'} -> {'myKey': 'myValue'} + */ + @SuppressWarnings("PatternMatchingInstanceOf") + private static Object normalizeKeyCase(Object obj) { + if (obj instanceof Map) { + Map originalMap = (Map) obj; + Map normalizedMap = new HashMap<>(); + for (Map.Entry entry : originalMap.entrySet()) { + String key = (String) entry.getKey(); + normalizedMap.put( + Common.snakeToCamel(key).toLowerCase(Locale.ROOT), normalizeKeyCase(entry.getValue())); + } + return normalizedMap; + } else if (obj instanceof List) { + List originalList = (List) obj; + List normalizedList = new ArrayList<>(); + for (Object item : originalList) { + normalizedList.add(normalizeKeyCase(item)); + } + return normalizedList; + } else if (obj instanceof JsonNode) { + JsonNode node = (JsonNode) obj; + if (node.isObject()) { + ObjectNode normalizedNode = JsonSerializable.objectMapper.createObjectNode(); + node.fields() + .forEachRemaining( + entry -> { + String newKey = Common.snakeToCamel(entry.getKey()); + Object normalizedValue = normalizeKeyCase(entry.getValue()); + normalizedNode.set(newKey, JsonSerializable.toJsonNode(normalizedValue)); + }); + return normalizedNode; + } else if (node.isArray()) { + ArrayNode normalizedNode = JsonSerializable.objectMapper.createArrayNode(); + node.elements() + .forEachRemaining( + item -> { + normalizedNode.add(JsonSerializable.toJsonNode(normalizeKeyCase(item))); + }); + return normalizedNode; + } else if (node.isTextual()) { + // In the replay file, the timestamp has +00:00 offset, while in the + // actual request it uses Z to represent the offset. We need to + // replace it to match the replay file. + return JsonSerializable.toJsonNode(node.asText().replaceAll("(?<=00)Z$", "\\+00:00")); + } + } + return obj; + } + + /** + * Compares two objects for equality ignoring key casing(snake vs camel). + * + *

e.g., {'my_key': 'my_value'} and {'myKey': 'my_value'} are considered equal. + */ + private static boolean equalsIgnoreKeyCase(Object replay, Object actual) { + Object normalizedReplay = normalizeKeyCase(replay); + Object normalizedActual = normalizeKeyCase(actual); + + return Objects.equals(normalizedReplay, normalizedActual); + } + + /** Converts a {@link RequestBody} to a string. */ + private static String requestBodyToString(final RequestBody requestBody) { + if (requestBody == null) { + return "No RequestBody"; + } + try { + final Buffer buffer = new Buffer(); + requestBody.writeTo(buffer); + MediaType contentType = requestBody.contentType(); + if (contentType != null && contentType.charset() != null) { + return buffer.readString(contentType.charset()); + } else { + return buffer.readUtf8(); + } + } catch (final IOException e) { + throw new GenAiIOException("Failed to convert request body to string.", e); + } + } } diff --git a/src/main/java/com/google/genai/ReplayApiResponse.java b/src/main/java/com/google/genai/ReplayApiResponse.java index 7b596166119..8b329be903b 100644 --- a/src/main/java/com/google/genai/ReplayApiResponse.java +++ b/src/main/java/com/google/genai/ReplayApiResponse.java @@ -16,19 +16,21 @@ package com.google.genai; +import com.fasterxml.jackson.databind.JsonNode; +import com.google.genai.errors.ApiException; import okhttp3.Headers; +import okhttp3.MediaType; import okhttp3.ResponseBody; -// TODO(b/369384123): Change the replay API response to use the ReplayFile. /** Provides a simulated HTTP response from a replay file. */ @ExcludeFromGeneratedCoverageReport final class ReplayApiResponse extends ApiResponse { - private final ResponseBody body; + private final JsonNode body; private final int statusCode; private final Headers headers; - public ReplayApiResponse(ResponseBody body, int statusCode, Headers headers) { + public ReplayApiResponse(JsonNode body, int statusCode, Headers headers) { this.body = body; this.statusCode = statusCode; this.headers = headers; @@ -36,7 +38,9 @@ public ReplayApiResponse(ResponseBody body, int statusCode, Headers headers) { @Override public ResponseBody getBody() { - return this.body; + ApiException.throwFromErrorNode(body, statusCode); + return ResponseBody.create( + JsonSerializable.toJsonString(body), MediaType.parse("application/json")); } @Override diff --git a/src/main/java/com/google/genai/errors/ApiException.java b/src/main/java/com/google/genai/errors/ApiException.java index 825c9990fe6..b42e4660a5d 100644 --- a/src/main/java/com/google/genai/errors/ApiException.java +++ b/src/main/java/com/google/genai/errors/ApiException.java @@ -150,6 +150,34 @@ static String getErrorMessageFromResponse(Response response) { } } + /** Throws an ApiException from a {@link JsonNode}. This method is for internal use only. */ + @InternalApi + public static void throwFromErrorNode(JsonNode errorNode, int code) { + if (code == 200) { + return; + } + if (errorNode == null || !errorNode.isObject()) { + return; + } + String message = ""; + JsonNode messageNode = errorNode.get("message"); + if (messageNode != null && messageNode.isTextual()) { + message = messageNode.asText(); + } + String status = "UNKNOWN"; + JsonNode statusNode = errorNode.get("status"); + if (statusNode != null && statusNode.isTextual()) { + status = statusNode.asText(); + } + if (code >= 400 && code < 500) { // Client errors. + throw new ClientException(code, status, message); + } else if (code >= 500 && code < 600) { // Server errors. + throw new ServerException(code, status, message); + } else { + throw new ApiException(code, status, message); + } + } + /** Returns the status code from the API response. */ public int code() { return code; diff --git a/src/main/java/com/google/genai/types/ReplayFile.java b/src/main/java/com/google/genai/types/ReplayFile.java index a71465b7f35..0c12d4d142c 100644 --- a/src/main/java/com/google/genai/types/ReplayFile.java +++ b/src/main/java/com/google/genai/types/ReplayFile.java @@ -34,7 +34,7 @@ @JsonDeserialize(builder = ReplayFile.Builder.class) public abstract class ReplayFile extends JsonSerializable { /** */ - @JsonProperty("replayId") + @JsonProperty("replay_id") public abstract Optional replayId(); /** */ @@ -63,7 +63,7 @@ private static Builder create() { * *

replayId: */ - @JsonProperty("replayId") + @JsonProperty("replay_id") public abstract Builder replayId(String replayId); /** diff --git a/src/main/java/com/google/genai/types/ReplayRequest.java b/src/main/java/com/google/genai/types/ReplayRequest.java index bfd97529d19..5da5d149cb6 100644 --- a/src/main/java/com/google/genai/types/ReplayRequest.java +++ b/src/main/java/com/google/genai/types/ReplayRequest.java @@ -45,7 +45,7 @@ public abstract class ReplayRequest extends JsonSerializable { public abstract Optional> headers(); /** */ - @JsonProperty("bodySegments") + @JsonProperty("body_segments") public abstract Optional>> bodySegments(); /** Instantiates a builder for ReplayRequest. */ @@ -94,7 +94,7 @@ private static Builder create() { * *

bodySegments: */ - @JsonProperty("bodySegments") + @JsonProperty("body_segments") public abstract Builder bodySegments(List> bodySegments); /** diff --git a/src/main/java/com/google/genai/types/ReplayResponse.java b/src/main/java/com/google/genai/types/ReplayResponse.java index dbf103d86a4..85de3549581 100644 --- a/src/main/java/com/google/genai/types/ReplayResponse.java +++ b/src/main/java/com/google/genai/types/ReplayResponse.java @@ -33,7 +33,7 @@ @JsonDeserialize(builder = ReplayResponse.Builder.class) public abstract class ReplayResponse extends JsonSerializable { /** */ - @JsonProperty("statusCode") + @JsonProperty("status_code") public abstract Optional statusCode(); /** */ @@ -41,11 +41,11 @@ public abstract class ReplayResponse extends JsonSerializable { public abstract Optional> headers(); /** */ - @JsonProperty("bodySegments") + @JsonProperty("body_segments") public abstract Optional>> bodySegments(); /** */ - @JsonProperty("sdkResponseSegments") + @JsonProperty("sdk_response_segments") public abstract Optional>> sdkResponseSegments(); /** Instantiates a builder for ReplayResponse. */ @@ -70,7 +70,7 @@ private static Builder create() { * *

statusCode: */ - @JsonProperty("statusCode") + @JsonProperty("status_code") public abstract Builder statusCode(Integer statusCode); /** @@ -86,7 +86,7 @@ private static Builder create() { * *

bodySegments: */ - @JsonProperty("bodySegments") + @JsonProperty("body_segments") public abstract Builder bodySegments(List> bodySegments); /** @@ -103,7 +103,7 @@ public Builder bodySegments(Map... bodySegments) { * *

sdkResponseSegments: */ - @JsonProperty("sdkResponseSegments") + @JsonProperty("sdk_response_segments") public abstract Builder sdkResponseSegments(List> sdkResponseSegments); /** diff --git a/src/test/java/com/google/genai/ModelsTest.java b/src/test/java/com/google/genai/ModelsTest.java index 5f2b2568d91..43ca9388077 100644 --- a/src/test/java/com/google/genai/ModelsTest.java +++ b/src/test/java/com/google/genai/ModelsTest.java @@ -62,7 +62,6 @@ matches = ".*genai/replays.*") public class ModelsTest { private Client createClient(boolean vertexAI, String replayId) { - // Use the API mode until the replay mode is complete. DebugConfig debugConfig = new DebugConfig("api", "", System.getenv("GOOGLE_GENAI_REPLAYS_DIRECTORY")); Client client = Client.builder().debugConfig(debugConfig).vertexAI(vertexAI).build(); diff --git a/src/test/java/com/google/genai/TableTest.java b/src/test/java/com/google/genai/TableTest.java index 281578e70b0..e41bfedd221 100644 --- a/src/test/java/com/google/genai/TableTest.java +++ b/src/test/java/com/google/genai/TableTest.java @@ -17,19 +17,9 @@ /** Runs the test table. */ package com.google.genai; -import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; -import static com.github.tomakehurst.wiremock.client.WireMock.any; -import static com.github.tomakehurst.wiremock.client.WireMock.anyUrl; -import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.fail; import static org.junit.jupiter.api.Assumptions.assumeTrue; -import com.fasterxml.jackson.core.type.TypeReference; -import com.github.tomakehurst.wiremock.WireMockServer; -import com.github.tomakehurst.wiremock.client.WireMock; -import com.github.tomakehurst.wiremock.core.WireMockConfiguration; -import com.google.common.collect.ImmutableSet; -import com.google.genai.types.HttpOptions; import com.google.genai.types.TestTableFile; import com.google.genai.types.TestTableItem; import java.io.IOException; @@ -53,36 +43,6 @@ /** Sample class to prototype GenAI SDK functionalities. */ public final class TableTest { - // TODO(b/384946033): Automate url safe parameter names retrieval. - private static final ImmutableSet URL_SAFE_BASE64_PARAMETER_NAMES = - ImmutableSet.of("image.imageBytes"); - - private static String snakeToPascal(String s) { - String[] parts = s.split("_"); - for (int i = 0; i < parts.length; i++) { - parts[i] = parts[i].substring(0, 1).toUpperCase() + parts[i].substring(1); - } - return String.join("", parts); - } - - private static String snakeToCamel(String str) { - if (str == null || str.isEmpty()) { - return str; - } - - StringBuilder sb = new StringBuilder(); - boolean capitalizeNext = false; - for (char c : str.toCharArray()) { - if (c == '_') { - capitalizeNext = true; - } else { - sb.append(capitalizeNext ? Character.toUpperCase(c) : c); - capitalizeNext = false; - } - } - return sb.toString(); - } - private static Collection createTableTests(String path, boolean vertexAI) throws IOException { String suffix = vertexAI ? "vertex" : "mldev"; @@ -98,9 +58,9 @@ private static Collection createTableTests(String path, boolean ver throw new RuntimeException("Invalid test method: " + testMethod); } String originalModuleName = segments[0]; - String moduleName = snakeToCamel(originalModuleName); + String moduleName = Common.snakeToCamel(originalModuleName); String originalMethodName = segments[1]; - String methodName = snakeToCamel(originalMethodName); + String methodName = Common.snakeToCamel(originalMethodName); String[] replayPathSegments = path.split("/"); String replayFilePath = ""; @@ -110,9 +70,6 @@ private static Collection createTableTests(String path, boolean ver } replayFilePath += replayPathSegments[i] + "/"; } - System.out.println("replayFilePath: " + replayFilePath); - - System.out.println("Running test table: " + testMethod); // Finds the module and methods. Field module = null; @@ -134,15 +91,9 @@ private static Collection createTableTests(String path, boolean ver throw new NoSuchMethodException(); } } catch (NoSuchFieldException | NoSuchMethodException e) { - String msg = " === Skipped: method " + testMethod + " is not supported in Java"; + String msg = " => Test skipped: method " + testMethod + " is not supported in Java"; String testName = String.format("%s.%s.%s", originalModuleName, originalMethodName, suffix); - return Collections.singletonList( - DynamicTest.dynamicTest( - testName, - () -> { - System.out.println(msg); - assumeTrue(false, msg); - })); + return Collections.singletonList(DynamicTest.dynamicTest(testName + msg, () -> {})); } List dynamicTests = new ArrayList<>(); @@ -183,16 +134,10 @@ private static Collection createTestCases( List parameterNames, String replayId) { - System.out.printf(" === Calling method: %s\n", testName); + Client client = createClient(vertexAI); if (testTableItem.hasUnion().isPresent() && testTableItem.hasUnion().get()) { - String msg = " === Skipped: parameters contain unsupported union type"; - return Collections.singletonList( - DynamicTest.dynamicTest( - testName, - () -> { - System.out.println(msg); - assumeTrue(false, msg); - })); + String msg = " => Test skipped: parameters contain unsupported union type"; + return Collections.singletonList(DynamicTest.dynamicTest(testName + msg, () -> {})); } // Edit image ReferenceImages are not correctly deserialized for replay tests if (testName.contains("models.edit_image") @@ -200,14 +145,8 @@ private static Collection createTestCases( || testName.contains("models.generate_content.test_speech_with_config") || testName.contains( "models.generate_content.test_logprobs_zero_with_response_logprobs_true")) { - String msg = " === Skipped: replay tests are not supported for edit_image"; - return Collections.singletonList( - DynamicTest.dynamicTest( - testName, - () -> { - System.out.println(msg); - assumeTrue(false, msg); - })); + String msg = " => Test skipped: replay tests are not supported for edit_image"; + return Collections.singletonList(DynamicTest.dynamicTest(testName + msg, () -> {})); } Map fromParameters = (Map) normalizeKeys((Map) testTableItem.parameters().get()); @@ -227,7 +166,7 @@ private static Collection createTestCases( List parameters = new ArrayList<>(); for (int i = 0; i < parameterNames.size(); i++) { // May throw IndexOutOfBoundsException here - String parameterName = snakeToCamel(parameterNames.get(i)); + String parameterName = Common.snakeToCamel(parameterNames.get(i)); Object fromValue = fromParameters.getOrDefault(parameterName, null); // May throw IllegalArgumentException here Object parameter = @@ -241,50 +180,12 @@ private static Collection createTestCases( DynamicTest.dynamicTest( testName, () -> { - final Map[] normalizedReplayData = new Map[1]; - final Map[] normalizedRequestData = new Map[1]; - WireMockServer wireMockServer = createMockServer(vertexAI); - Map replayData = ReplayApiClient.loadReplayData(replayId); - Client client = createClient(vertexAI, wireMockServer); - - // Capture the request and store it to normalizedReplayData and - // normalizedRequestData - // so that we can check it later. - wireMockServer.addMockServiceRequestListener( - (request, response) -> { - try { - Map requestData = - JsonSerializable.objectMapper.readValue( - request.getBodyAsString(), - new TypeReference>() {}); - normalizedReplayData[0] = (Map) normalizeKeys(replayData); - normalizedRequestData[0] = - (Map) normalizeKeys(requestData); - } catch (IOException e) { - throw new RuntimeException(e); - } - }); - try { client.setReplayId(replayId); - // May throw IllegalAccessException or InvocationTargetException here // InvocationTargetException is sometimes expected, when exceptionIfMldev or // exceptionIfVertex is present. Object response = method.invoke(module.get(client), parameters.toArray()); - - Object expectedRequest = - getAtPath( - normalizedReplayData[0], - "interactions", - 0, - "request", - "bodySegments", - 0); - assertEquals( - expectedRequest, - normalizedRequestData[0], - "Normalized request data should match expected data from replay."); } catch (IllegalAccessException | InvocationTargetException e) { // Handle expected exceptions here Optional skipInApiMode = testTableItem.skipInApiMode(); @@ -306,28 +207,14 @@ private static Collection createTestCases( System.out.println( " === Skipped: test case is expected to fail in Vertex AI"); } - e.printStackTrace(); - fail(String.format("'%s' failed: %s", testName, e)); + fail(String.format("'%s' failed: %s", testName, e.getCause())); } finally { - wireMockServer.stop(); client.close(); } })); } catch (IndexOutOfBoundsException | IllegalArgumentException e) { // Method parameters do not match, continue to the next overloading method } - - // TODO(jayceeli): Remove this once replay mode is fully functional. - if (testName.contains( - "models.generate_content.test_logprobs_zero_with_response_logprobs_true.vertex")) { - String msg = " === Skipped: test case is expected to fail in Vertex AI"; - dynamicTests.add( - DynamicTest.dynamicTest( - testName, - () -> { - assumeTrue(false, msg); - })); - } } if (dynamicTests.isEmpty()) { String msg = @@ -375,27 +262,7 @@ Collection createTests() throws IOException { return dynamicTests; } - static WireMockServer createMockServer(boolean vertexAI) { - WireMockServer wireMockServer = - new WireMockServer(WireMockConfiguration.options().dynamicPort()); - wireMockServer.start(); - WireMock.configureFor("localhost", wireMockServer.port()); - - if (vertexAI) { - wireMockServer.stubFor( - any(anyUrl()) - .willReturn(aResponse().proxiedFrom("https://us-central1-aiplatform.googleapis.com")) - .atPriority(1)); - } else { - wireMockServer.stubFor( - any(anyUrl()) - .willReturn(aResponse().proxiedFrom("https://generativelanguage.googleapis.com")) - .atPriority(1)); - } - return wireMockServer; - } - - static Client createClient(boolean vertexAI, WireMockServer wireMockServer) { + static Client createClient(boolean vertexAI) { String replaysPath = System.getenv("GOOGLE_GENAI_REPLAYS_DIRECTORY"); if (replaysPath == null) { throw new RuntimeException("GOOGLE_GENAI_REPLAYS_DIRECTORY is not set"); @@ -403,18 +270,11 @@ static Client createClient(boolean vertexAI, WireMockServer wireMockServer) { String testsReplaysPath = replaysPath + "/tests"; String replayMode = System.getenv("GOOGLE_GENAI_CLIENT_MODE"); if (replayMode == null) { - // TODO(b/369384123): Make the default replay mode or auto once loading replays - // is complete. - replayMode = "api"; + replayMode = "auto"; } DebugConfig debugConfig = new DebugConfig(replayMode, "", testsReplaysPath); - return Client.builder() - .vertexAI(vertexAI) - .debugConfig(debugConfig) - .httpOptions( - HttpOptions.builder().baseUrl("http://localhost:" + wireMockServer.port()).build()) - .build(); + return Client.builder().vertexAI(vertexAI).debugConfig(debugConfig).build(); } private static Object normalizeKeys(Object data) { @@ -423,7 +283,7 @@ private static Object normalizeKeys(Object data) { Map originalMap = (Map) data; Map newNormalizedMap = new HashMap<>(); for (Map.Entry entry : originalMap.entrySet()) { - String normalizedKey = snakeToCamel(entry.getKey()); + String normalizedKey = Common.snakeToCamel(entry.getKey()); Object normalizedValue = normalizeKeys(entry.getValue()); newNormalizedMap.put(normalizedKey, normalizedValue); } @@ -440,33 +300,4 @@ private static Object normalizeKeys(Object data) { return data; // Return as is for non-map/non-list types } } - - private static Object getAtPath(Object root, Object... pathComponents) { - Object current = root; - for (Object component : pathComponents) { - if (current == null) { - return null; - } - - if (component instanceof String) { - String key = (String) component; - if (current instanceof Map) { - current = ((Map) current).get(key); - } else { - return null; - } - } else if (component instanceof Integer) { - Integer index = (Integer) component; - if (current instanceof List && index >= 0 && index < ((List) current).size()) { - current = ((List) current).get(index); - } else { - return null; - } - } else { - return null; - } - } - return current; - } - } From 2628105ef83cccb20b059bb93503f4fe19e84a0d Mon Sep 17 00:00:00 2001 From: Jaycee Li Date: Mon, 7 Jul 2025 10:43:11 -0700 Subject: [PATCH 057/602] chore: Support streaming responses in ReplayApiClient chore: Enable replay mode in OperationsTest and ModelsTest PiperOrigin-RevId: 780171787 --- src/main/java/com/google/genai/Client.java | 5 +- .../com/google/genai/ReplayApiClient.java | 12 +- .../com/google/genai/ReplayApiResponse.java | 40 +- .../java/com/google/genai/ResponseStream.java | 4 +- .../com/google/genai/errors/ApiException.java | 9 +- .../java/com/google/genai/ModelsTest.java | 421 +++++++++++------- .../java/com/google/genai/OperationsTest.java | 36 +- src/test/java/com/google/genai/TableTest.java | 4 +- src/test/resources/checkerboard.png | Bin 0 -> 387 bytes src/test/resources/google.png | Bin 0 -> 5969 bytes 10 files changed, 326 insertions(+), 205 deletions(-) create mode 100644 src/test/resources/checkerboard.png create mode 100644 src/test/resources/google.png diff --git a/src/main/java/com/google/genai/Client.java b/src/main/java/com/google/genai/Client.java index af13a9a258d..5767ce49784 100644 --- a/src/main/java/com/google/genai/Client.java +++ b/src/main/java/com/google/genai/Client.java @@ -272,8 +272,7 @@ private Client( } this.debugConfig = debugConfig.orElse(new DebugConfig()); - if (this.debugConfig.clientMode().equals("replay") - || this.debugConfig.clientMode().equals("auto")) { + if (this.debugConfig.clientMode().equals("replay")) { if (!useVertexAI) { this.apiClient = new ReplayApiClient( @@ -353,7 +352,7 @@ DebugConfig debugConfig() { return debugConfig; } - /** Returns the client mode. If it's "replay" or "auto", then the client is in testing mode. */ + /** Returns the client mode. If it's "replay", then the client is in testing mode. */ String clientMode() { return debugConfig.clientMode(); } diff --git a/src/main/java/com/google/genai/ReplayApiClient.java b/src/main/java/com/google/genai/ReplayApiClient.java index cb9fff41ed0..c5e5a01f6a4 100644 --- a/src/main/java/com/google/genai/ReplayApiClient.java +++ b/src/main/java/com/google/genai/ReplayApiClient.java @@ -101,7 +101,7 @@ static String readString(Path path) { try (Stream stream = Files.lines(path)) { return stream.collect(joining(System.lineSeparator())); } catch (IOException e) { - throw new GenAiIOException("Failed to read replay file. ", e); + throw new GenAiIOException("Failed to read replay file from path: " + path.toString(), e); } } @@ -125,7 +125,7 @@ void initializeReplaySession(String replayId) { @Override public ApiResponse request( String httpMethod, String path, String requestJson, Optional httpOptions) { - if (this.clientMode.equals("replay") || this.clientMode.equals("auto")) { + if (this.clientMode.equals("replay")) { ReplayInteraction currentInteraction = replayInteractions.get(this.replayInteractionIndex); this.replayInteractionIndex++; matchRequest( @@ -203,13 +203,11 @@ private ReplayApiResponse buildResponseFromReplay(ReplayResponse replayResponse) if (replayResponse == null) { throw new IllegalArgumentException("Replay response is null."); } - // Replay response body_segments is a list of JSON objects for streaming support. Here we - // only read the first body segment. - // TODO(jayceeli): Support streaming responses. JsonNode bodyNode = - JsonSerializable.toJsonNode(replayResponse.bodySegments().orElse(new ArrayList<>()).get(0)); + JsonSerializable.toJsonNode(replayResponse.bodySegments().orElse(new ArrayList<>())); Headers headers = Headers.of(replayResponse.headers().orElse(ImmutableMap.of())); - return new ReplayApiResponse(bodyNode, replayResponse.statusCode().orElse(0), headers); + return new ReplayApiResponse( + (ArrayNode) bodyNode, replayResponse.statusCode().orElse(0), headers); } /** diff --git a/src/main/java/com/google/genai/ReplayApiResponse.java b/src/main/java/com/google/genai/ReplayApiResponse.java index 8b329be903b..e7a0749bd37 100644 --- a/src/main/java/com/google/genai/ReplayApiResponse.java +++ b/src/main/java/com/google/genai/ReplayApiResponse.java @@ -17,7 +17,12 @@ package com.google.genai; import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ArrayNode; import com.google.genai.errors.ApiException; +import com.google.genai.errors.GenAiIOException; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.nio.charset.StandardCharsets; import okhttp3.Headers; import okhttp3.MediaType; import okhttp3.ResponseBody; @@ -26,21 +31,44 @@ @ExcludeFromGeneratedCoverageReport final class ReplayApiResponse extends ApiResponse { - private final JsonNode body; + private final ResponseBody body; private final int statusCode; private final Headers headers; + private final ArrayNode bodySegments; - public ReplayApiResponse(JsonNode body, int statusCode, Headers headers) { - this.body = body; + public ReplayApiResponse(ArrayNode bodySegments, int statusCode, Headers headers) { + this.bodySegments = bodySegments; this.statusCode = statusCode; this.headers = headers; + if (bodySegments.size() == 0) { + this.body = ResponseBody.create(MediaType.parse("application/json"), ""); + } else if (bodySegments.size() == 1) { + // For unary response + this.body = + ResponseBody.create( + MediaType.parse("application/json"), + JsonSerializable.toJsonString(bodySegments.get(0))); + } else { + // For streaming response + try { + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + byte[] newline = "\n".getBytes(StandardCharsets.UTF_8); + for (JsonNode segment : bodySegments) { + outputStream.write(JsonSerializable.objectMapper.writeValueAsBytes(segment)); + outputStream.write(newline); + } + this.body = + ResponseBody.create(outputStream.toByteArray(), MediaType.parse("application/json")); + } catch (IOException e) { + throw new GenAiIOException("Failed to convert body segments to a JSON string.", e); + } + } } @Override public ResponseBody getBody() { - ApiException.throwFromErrorNode(body, statusCode); - return ResponseBody.create( - JsonSerializable.toJsonString(body), MediaType.parse("application/json")); + ApiException.throwFromErrorNode(bodySegments, statusCode); + return this.body; } @Override diff --git a/src/main/java/com/google/genai/ResponseStream.java b/src/main/java/com/google/genai/ResponseStream.java index 25df64e222b..d8619d053fa 100644 --- a/src/main/java/com/google/genai/ResponseStream.java +++ b/src/main/java/com/google/genai/ResponseStream.java @@ -122,8 +122,10 @@ private String readNextJson() { return null; } else if (line.length() == 0) { return readNextJson(); - } else { + } else if (line.startsWith("data: ")) { return line.substring("data: ".length()); + } else { + return line; } } catch (IOException e) { throw new GenAiIOException("Failed to read next JSON object from the stream", e); diff --git a/src/main/java/com/google/genai/errors/ApiException.java b/src/main/java/com/google/genai/errors/ApiException.java index b42e4660a5d..fb4c81ef4b5 100644 --- a/src/main/java/com/google/genai/errors/ApiException.java +++ b/src/main/java/com/google/genai/errors/ApiException.java @@ -20,6 +20,7 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ArrayNode; import com.google.api.core.InternalApi; import java.io.IOException; import okhttp3.Response; @@ -150,17 +151,17 @@ static String getErrorMessageFromResponse(Response response) { } } - /** Throws an ApiException from a {@link JsonNode}. This method is for internal use only. */ + /** Throws an ApiException from a {@link ArrayNode}. This method is for internal use only. */ @InternalApi - public static void throwFromErrorNode(JsonNode errorNode, int code) { + public static void throwFromErrorNode(ArrayNode errorNode, int code) { if (code == 200) { return; } - if (errorNode == null || !errorNode.isObject()) { + if (errorNode == null || errorNode.size() == 0) { return; } String message = ""; - JsonNode messageNode = errorNode.get("message"); + JsonNode messageNode = errorNode.get(0).get("message"); if (messageNode != null && messageNode.isTextual()) { message = messageNode.asText(); } diff --git a/src/test/java/com/google/genai/ModelsTest.java b/src/test/java/com/google/genai/ModelsTest.java index 43ca9388077..71fb024cdf6 100644 --- a/src/test/java/com/google/genai/ModelsTest.java +++ b/src/test/java/com/google/genai/ModelsTest.java @@ -22,60 +22,120 @@ import static org.junit.jupiter.api.Assertions.assertTrue; import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; import com.google.genai.types.ComputeTokensResponse; import com.google.genai.types.Content; import com.google.genai.types.ControlReferenceConfig; import com.google.genai.types.ControlReferenceImage; -import com.google.genai.types.ControlReferenceType; import com.google.genai.types.CountTokensResponse; import com.google.genai.types.EditImageConfig; import com.google.genai.types.EditImageResponse; import com.google.genai.types.EditMode; +import com.google.genai.types.EmbedContentConfig; import com.google.genai.types.EmbedContentResponse; import com.google.genai.types.GenerateContentConfig; import com.google.genai.types.GenerateContentResponse; +import com.google.genai.types.HttpOptions; import com.google.genai.types.Image; import com.google.genai.types.ListModelsConfig; import com.google.genai.types.MaskReferenceConfig; import com.google.genai.types.MaskReferenceImage; -import com.google.genai.types.MaskReferenceMode; import com.google.genai.types.Model; import com.google.genai.types.Part; import com.google.genai.types.RawReferenceImage; -import com.google.genai.types.ReferenceImage; import com.google.genai.types.StyleReferenceConfig; import com.google.genai.types.StyleReferenceImage; import com.google.genai.types.SubjectReferenceConfig; import com.google.genai.types.SubjectReferenceImage; -import com.google.genai.types.SubjectReferenceType; import java.net.URL; import java.nio.file.Path; import java.nio.file.Paths; -import java.util.ArrayList; +import java.util.Arrays; import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable; import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.CsvSource; import org.junit.jupiter.params.provider.ValueSource; @EnabledIfEnvironmentVariable( named = "GOOGLE_GENAI_REPLAYS_DIRECTORY", matches = ".*genai/replays.*") public class ModelsTest { + + private static final String GEMINI_MODEL_NAME = "gemini-1.5-flash"; + private static final String EMBEDDING_MODEL_NAME = "text-embedding-004"; + private static final String IMAGEN_CAPABILITY_MODEL_NAME = "imagen-3.0-capability-001"; + + /** Creates a client for the given Vertex AI flag and replay ID. */ private Client createClient(boolean vertexAI, String replayId) { + String clientMode = System.getenv("GOOGLE_GENAI_CLIENT_MODE"); DebugConfig debugConfig = - new DebugConfig("api", "", System.getenv("GOOGLE_GENAI_REPLAYS_DIRECTORY")); + new DebugConfig( + clientMode == null ? "replay" : clientMode, + "", + System.getenv("GOOGLE_GENAI_REPLAYS_DIRECTORY")); Client client = Client.builder().debugConfig(debugConfig).vertexAI(vertexAI).build(); - if (client.clientMode().equals("replay") || client.clientMode().equals("auto")) { + if (client.clientMode().equals("replay")) { client.setReplayId(replayId); } return client; } - private static final String GEMINI_MODEL_NAME = "gemini-2.0-flash-001"; - private static final String EMBEDDING_MODEL_NAME = "text-embedding-004"; - private static final String PROMPT_TEXT = "Tell me a story in 300 words."; - private static final String PROMPT_TEXT_2 = "What is your name?"; - private static final String PROMPT_TEXT_3 = "What is your age?"; + /** Creates a raw reference image for edit image tests. */ + private RawReferenceImage createRawReferenceImage() throws Exception { + URL resourceUrl = getClass().getClassLoader().getResource("google.png"); + Path filePath = Paths.get(resourceUrl.toURI()); + Image image = Image.fromFile(filePath.toAbsolutePath().toString()); + return RawReferenceImage.builder().referenceImage(image).referenceId(1).build(); + } + + /** Creates a mask reference image for edit image tests. */ + private MaskReferenceImage createMaskReferenceImage() { + return MaskReferenceImage.builder() + .referenceId(2) + .config(MaskReferenceConfig.builder().maskMode("MASK_MODE_BACKGROUND").maskDilation(0.06f)) + .build(); + } + + /** Creates a control reference image for edit image tests. */ + private ControlReferenceImage createControlReferenceImage() throws Exception { + URL resourceUrl = getClass().getClassLoader().getResource("checkerboard.png"); + Path filePath = Paths.get(resourceUrl.toURI()); + Image image = Image.fromFile(filePath.toAbsolutePath().toString()); + return ControlReferenceImage.builder() + .referenceId(2) + .referenceImage(image) + .config( + ControlReferenceConfig.builder() + .controlType("CONTROL_TYPE_SCRIBBLE") + .enableControlImageComputation(false)) + .build(); + } + + /** Creates a subject reference image for edit image tests. */ + private SubjectReferenceImage createSubjectReferenceImage() throws Exception { + URL resourceUrl = getClass().getClassLoader().getResource("google.png"); + Path filePath = Paths.get(resourceUrl.toURI()); + Image image = Image.fromFile(filePath.toAbsolutePath().toString()); + return SubjectReferenceImage.builder() + .referenceId(1) + .referenceImage(image) + .config( + SubjectReferenceConfig.builder() + .subjectType("SUBJECT_TYPE_PRODUCT") + .subjectDescription("A product logo that is a multi-colored letter G")) + .build(); + } + + /** Creates a style reference image for edit image tests. */ + private StyleReferenceImage createStyleReferenceImage() throws Exception { + URL resourceUrl = getClass().getClassLoader().getResource("google.png"); + Path filePath = Paths.get(resourceUrl.toURI()); + Image image = Image.fromFile(filePath.toAbsolutePath().toString()); + return StyleReferenceImage.builder() + .referenceId(1) + .referenceImage(image) + .config(StyleReferenceConfig.builder().styleDescription("glowing style")) + .build(); + } @ParameterizedTest @ValueSource(booleans = {false, true}) @@ -83,13 +143,14 @@ public void testGenerateContent_withContent(boolean vertexAI) throws Exception { // Arrange String suffix = vertexAI ? "vertex" : "mldev"; Client client = - createClient( - vertexAI, "tests/models/generate_content/test_sync_stream." + suffix + ".json"); + createClient(vertexAI, "tests/models/generate_content/test_sync." + suffix + ".json"); // Act GenerateContentResponse response = client.models.generateContent( - GEMINI_MODEL_NAME, Content.fromParts(Part.fromText(PROMPT_TEXT)), null); + GEMINI_MODEL_NAME, + Content.fromParts(Part.fromText("Tell me a story in 300 words.")), + null); // Assert assertNotNull(response.text()); @@ -105,8 +166,13 @@ public void testGenerateContentStream_withText(boolean vertexAI) throws Exceptio vertexAI, "tests/models/generate_content/test_sync_stream." + suffix + ".json"); // Act + GenerateContentConfig config = + GenerateContentConfig.builder() + .httpOptions(HttpOptions.builder().headers(ImmutableMap.of("test", "headers"))) + .build(); ResponseStream responseStream = - client.models.generateContentStream(GEMINI_MODEL_NAME, PROMPT_TEXT, null); + client.models.generateContentStream( + GEMINI_MODEL_NAME, "Tell me a story in 300 words.", config); // Assert int chunks = 0; @@ -125,14 +191,27 @@ public void testGenerateContentStream_withContentAndConfig(boolean vertexAI) thr String suffix = vertexAI ? "vertex" : "mldev"; Client client = createClient( - vertexAI, "tests/models/generate_content/test_sync_stream." + suffix + ".json"); + vertexAI, + "tests/models/generate_content/test_simple_shared_generation_config_stream." + + suffix + + ".json"); // Act + GenerateContentConfig config = + GenerateContentConfig.builder() + .maxOutputTokens(400) + .topK(2f) + .temperature(0.5f) + .topP(0.5f) + .responseMimeType("application/json") + .stopSequences("\n") + .seed(42) + .build(); ResponseStream responseStream = client.models.generateContentStream( GEMINI_MODEL_NAME, - Content.fromParts(Part.fromText(PROMPT_TEXT)), - GenerateContentConfig.builder().maxOutputTokens(300).build()); + Content.fromParts(Part.fromText("tell me a story in 300 words")), + config); // Assert int chunks = 0; @@ -154,7 +233,7 @@ public void testEmbedContent_withText(boolean vertexAI) throws Exception { // Act EmbedContentResponse response = - client.models.embedContent(EMBEDDING_MODEL_NAME, PROMPT_TEXT_2, null); + client.models.embedContent(EMBEDDING_MODEL_NAME, "What is your name?", null); // Assert assertTrue(response.embeddings().isPresent()); @@ -172,9 +251,16 @@ public void testEmbedContent_withListOfTexts(boolean vertexAI) throws Exception "tests/models/embed_content/test_multi_texts_with_config." + suffix + ".json"); // Act + EmbedContentConfig config = + EmbedContentConfig.builder() + .outputDimensionality(10) + .title("test_title") + .taskType("RETRIEVAL_DOCUMENT") + .httpOptions(HttpOptions.builder().headers(ImmutableMap.of("test", "headers"))) + .build(); EmbedContentResponse response = client.models.embedContent( - EMBEDDING_MODEL_NAME, ImmutableList.of(PROMPT_TEXT_2, PROMPT_TEXT_3), null); + EMBEDDING_MODEL_NAME, ImmutableList.of("What is your name?", "I am a model."), config); // Assert assertTrue(response.embeddings().isPresent()); @@ -191,7 +277,7 @@ public void testCountTokens_withText(boolean vertexAI) throws Exception { // Act CountTokensResponse response = - client.models.countTokens(GEMINI_MODEL_NAME, PROMPT_TEXT, null); + client.models.countTokens(GEMINI_MODEL_NAME, "Tell me a story in 300 words.", null); // Assert assertTrue(response.totalTokens().isPresent()); @@ -212,15 +298,15 @@ public void testComputeTokens_withText(boolean vertexAI) throws Exception { // Act ComputeTokensResponse response = - client.models.computeTokens(GEMINI_MODEL_NAME, PROMPT_TEXT, null); + client.models.computeTokens(GEMINI_MODEL_NAME, "Tell me a story in 300 words.", null); // Assert assertTrue(response.tokensInfo().isPresent()); } @ParameterizedTest - @CsvSource({"false, false", "false, true", "true, false", "true, true"}) - public void testListModels(boolean vertexAI, boolean queryBase) throws Exception { + @ValueSource(booleans = {false, true}) + public void testListModels(boolean vertexAI) throws Exception { // Arrange String suffix = vertexAI ? "vertex" : "mldev"; Client client = @@ -228,11 +314,11 @@ public void testListModels(boolean vertexAI, boolean queryBase) throws Exception // Act Pager pager = - client.models.list(ListModelsConfig.builder().pageSize(5).queryBase(queryBase).build()); + client.models.list(ListModelsConfig.builder().pageSize(10).queryBase(true).build()); // Assert - assertEquals(5, pager.size()); - assertTrue(pager.size() <= 5); + assertEquals(10, pager.size()); + assertTrue(pager.size() <= 10); for (Model model : pager) { assertTrue(model.name().isPresent()); } @@ -246,7 +332,8 @@ public void testListModels(boolean vertexAI, boolean queryBase) throws Exception public void testListModel_filterThrowException(boolean vertexAI) throws Exception { // Arrange String suffix = vertexAI ? "vertex" : "mldev"; - Client client = createClient(vertexAI, "tests/models/get/test_list_model." + suffix + ".json"); + Client client = + createClient(vertexAI, "tests/models/list/test_base_models_pager." + suffix + ".json"); // Act IllegalArgumentException exception = @@ -271,181 +358,183 @@ public void testEditImage_withMaskReference(boolean vertexAI) throws Exception { createClient( vertexAI, "tests/models/edit_image/test_edit_mask_inpaint_insert." + suffix + ".json"); - // Act - // Base image created using generateImages with prompt: - // "An umbrella in the foreground, and a rainy night sky in the background" - URL resourceUrl = getClass().getClassLoader().getResource("umbrella.jpg"); - Path filePath = Paths.get(resourceUrl.toURI()); - Image image = Image.fromFile(filePath.toAbsolutePath().toString()); - - EditImageConfig editImageConfig = + EditImageConfig config = EditImageConfig.builder() .editMode(EditMode.Known.EDIT_MODE_INPAINT_INSERTION) .numberOfImages(1) + .negativePrompt("human") + .guidanceScale(15.0f) + .safetyFilterLevel("BLOCK_MEDIUM_AND_ABOVE") + .personGeneration("DONT_ALLOW") + .includeSafetyAttributes(false) + .includeRaiReason(true) .outputMimeType("image/jpeg") + .outputCompressionQuality(80) + .baseSteps(32) .build(); - ArrayList referenceImages = new ArrayList<>(); - RawReferenceImage rawReferenceImage = - RawReferenceImage.builder().referenceImage(image).referenceId(1).build(); - referenceImages.add(rawReferenceImage); - - MaskReferenceImage maskReferenceImage = - MaskReferenceImage.builder() - .referenceId(2) - .config( - MaskReferenceConfig.builder() - .maskMode(MaskReferenceMode.Known.MASK_MODE_BACKGROUND) - .maskDilation(0.0f)) - .build(); - referenceImages.add(maskReferenceImage); - EditImageResponse response = - client.models.editImage( - "imagen-3.0-capability-001", - "Sunlight and clear sky", - referenceImages, - editImageConfig); - - // Assert - assertTrue(response.generatedImages().get().get(0).image().isPresent()); + // Act + if (vertexAI) { + EditImageResponse response = + client.models.editImage( + IMAGEN_CAPABILITY_MODEL_NAME, + "Sunlight and clear weather", + Arrays.asList(createRawReferenceImage(), createMaskReferenceImage()), + config); + + // Assert + assertTrue(response.generatedImages().get().get(0).image().isPresent()); + } else { + UnsupportedOperationException exception = + assertThrows( + UnsupportedOperationException.class, + () -> + client.models.editImage( + IMAGEN_CAPABILITY_MODEL_NAME, + "Sunlight and clear weather", + Arrays.asList(createRawReferenceImage(), createMaskReferenceImage()), + config)); + // Assert + assertEquals( + "This method is not supported by the Gemini Developer API.", exception.getMessage()); + } } @ParameterizedTest @ValueSource(booleans = {false, true}) public void testEditImage_withControlReference(boolean vertexAI) throws Exception { - if (!vertexAI) { - // EditImage is not supported in MLDev. - return; - } // Arrange String suffix = vertexAI ? "vertex" : "mldev"; Client client = - createClient(vertexAI, "tests/models/edit_image/test_edit_control." + suffix + ".json"); - - // Act - // Base image created using generateImages with prompt: - // "A square, circle, and triangle with a white background" - URL resourceUrl = getClass().getClassLoader().getResource("shapes.jpg"); - Path filePath = Paths.get(resourceUrl.toURI()); - Image image = Image.fromFile(filePath.toAbsolutePath().toString()); - - // Control reference. - EditImageConfig editImageConfig = - EditImageConfig.builder().numberOfImages(1).outputMimeType("image/jpeg").build(); - - ArrayList referenceImages = new ArrayList<>(); + createClient( + vertexAI, + "tests/models/edit_image/test_edit_control_user_provided." + suffix + ".json"); - ControlReferenceImage controlReferenceImage = - ControlReferenceImage.builder() - .referenceId(1) - .referenceImage(image) - .config( - ControlReferenceConfig.builder() - .controlType(ControlReferenceType.Known.CONTROL_TYPE_SCRIBBLE) - .enableControlImageComputation(true)) + EditImageConfig config = + EditImageConfig.builder() + .numberOfImages(1) + .aspectRatio("9:16") + .includeRaiReason(true) .build(); - referenceImages.add(controlReferenceImage); - - EditImageResponse response = - client.models.editImage( - "imagen-3.0-capability-001", - "Change the colors aligning with the scribble map [1].", - referenceImages, - editImageConfig); - // Assert - assertTrue(response.generatedImages().get().get(0).image().isPresent()); + // Act + if (vertexAI) { + EditImageResponse response = + client.models.editImage( + IMAGEN_CAPABILITY_MODEL_NAME, + "Change the colors aligning with the scribble map [2]", + Arrays.asList(createRawReferenceImage(), createControlReferenceImage()), + config); + + // Assert + assertTrue(response.generatedImages().get().get(0).image().isPresent()); + } else { + UnsupportedOperationException exception = + assertThrows( + UnsupportedOperationException.class, + () -> + client.models.editImage( + IMAGEN_CAPABILITY_MODEL_NAME, + "Change the colors aligning with the scribble map [2]", + Arrays.asList(createRawReferenceImage(), createControlReferenceImage()), + config)); + // Assert + assertEquals( + "This method is not supported by the Gemini Developer API.", exception.getMessage()); + } } @ParameterizedTest @ValueSource(booleans = {false, true}) public void testEditImage_withSubjectReference(boolean vertexAI) throws Exception { - if (!vertexAI) { - // EditImage is not supported in MLDev. - return; - } // Arrange String suffix = vertexAI ? "vertex" : "mldev"; Client client = - createClient(vertexAI, "tests/models/edit_image/test_edit_subject." + suffix + ".json"); - - // Act - // Base image created using generateImages with prompt: - // "A logo with the letters 'SERN' in a futuristic font with a white background" - URL resourceUrl = getClass().getClassLoader().getResource("logo.jpg"); - Path filePath = Paths.get(resourceUrl.toURI()); - Image image = Image.fromFile(filePath.toAbsolutePath().toString()); + createClient( + vertexAI, + "tests/models/edit_image/test_edit_subject_image_customization." + suffix + ".json"); - // Subject reference. - EditImageConfig editImageConfig = - EditImageConfig.builder().numberOfImages(1).outputMimeType("image/jpeg").build(); - - ArrayList referenceImages = new ArrayList<>(); - SubjectReferenceImage subjectReferenceImage = - SubjectReferenceImage.builder() - .referenceImage(image) - .referenceId(1) - .config( - SubjectReferenceConfig.builder() - .subjectType(SubjectReferenceType.Known.SUBJECT_TYPE_PRODUCT) - .subjectDescription("Product logo")) + EditImageConfig config = + EditImageConfig.builder() + .numberOfImages(1) + .aspectRatio("9:16") + .includeRaiReason(true) .build(); - referenceImages.add(subjectReferenceImage); - EditImageResponse response = - client.models.editImage( - "imagen-3.0-capability-001", - "Generate an image containing a mug with the product logo [1] visible on the side of" - + " the mug.", - referenceImages, - editImageConfig); - - // Assert - assertTrue(response.generatedImages().get().get(0).image().isPresent()); + // Act + if (vertexAI) { + EditImageResponse response = + client.models.editImage( + IMAGEN_CAPABILITY_MODEL_NAME, + "Generate an image containing a mug with the product logo [1] visible on the side of" + + " the mug.", + Arrays.asList(createSubjectReferenceImage()), + config); + + // Assert + assertTrue(response.generatedImages().get().get(0).image().isPresent()); + } else { + UnsupportedOperationException exception = + assertThrows( + UnsupportedOperationException.class, + () -> + client.models.editImage( + IMAGEN_CAPABILITY_MODEL_NAME, + "Generate an image containing a mug with the product logo [1] visible on the" + + " side of the mug.", + Arrays.asList(createSubjectReferenceImage()), + config)); + // Assert + assertEquals( + "This method is not supported by the Gemini Developer API.", exception.getMessage()); + } } @ParameterizedTest @ValueSource(booleans = {false, true}) public void testEditImage_withStyleTransfer(boolean vertexAI) throws Exception { - if (!vertexAI) { - // EditImage is not supported in MLDev. - return; - } // Arrange String suffix = vertexAI ? "vertex" : "mldev"; Client client = createClient( - vertexAI, "tests/models/edit_image/test_edit_style_transfer." + suffix + ".json"); - - // Act - // Base image created using generateImages with prompt: - // "A starry night sky painted with watercolors" - URL resourceUrl = getClass().getClassLoader().getResource("watercolor_night_sky.jpg"); - Path filePath = Paths.get(resourceUrl.toURI()); - Image image = Image.fromFile(filePath.toAbsolutePath().toString()); - - // Style transfer. - EditImageConfig editImageConfig = - EditImageConfig.builder().numberOfImages(1).outputMimeType("image/jpeg").build(); + vertexAI, + "tests/models/edit_image/test_edit_style_reference_image_customization." + + suffix + + ".json"); - ArrayList referenceImages = new ArrayList<>(); - StyleReferenceImage styleReferenceImage = - StyleReferenceImage.builder() - .referenceImage(image) - .referenceId(1) - .config(StyleReferenceConfig.builder().styleDescription("Watercolor")) + EditImageConfig config = + EditImageConfig.builder() + .numberOfImages(1) + .aspectRatio("9:16") + .includeRaiReason(true) .build(); - referenceImages.add(styleReferenceImage); - - EditImageResponse response = - client.models.editImage( - "imagen-3.0-capability-001", - "Generate an image in the style of [1] based on the following caption: A church in the" - + " mountain.", - referenceImages, - editImageConfig); - // Assert - assertTrue(response.generatedImages().get().get(0).image().isPresent()); + // Act + if (vertexAI) { + EditImageResponse response = + client.models.editImage( + IMAGEN_CAPABILITY_MODEL_NAME, + "Generate an image in glowing style [1] based on the following caption: A church in" + + " the mountain.", + Arrays.asList(createStyleReferenceImage()), + config); + + // Assert + assertTrue(response.generatedImages().get().get(0).image().isPresent()); + } else { + UnsupportedOperationException exception = + assertThrows( + UnsupportedOperationException.class, + () -> + client.models.editImage( + IMAGEN_CAPABILITY_MODEL_NAME, + "Generate an image in glowing style [1] based on the following caption: A" + + " church in the mountain.", + Arrays.asList(createStyleReferenceImage()), + config)); + // Assert + assertEquals( + "This method is not supported by the Gemini Developer API.", exception.getMessage()); + } } } diff --git a/src/test/java/com/google/genai/OperationsTest.java b/src/test/java/com/google/genai/OperationsTest.java index 0fb32bd3773..868f4b9646e 100644 --- a/src/test/java/com/google/genai/OperationsTest.java +++ b/src/test/java/com/google/genai/OperationsTest.java @@ -19,7 +19,6 @@ import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; -import com.google.genai.types.GenerateVideosConfig; import com.google.genai.types.GenerateVideosOperation; import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable; import org.junit.jupiter.params.ParameterizedTest; @@ -30,11 +29,14 @@ matches = ".*genai/replays.*") public class OperationsTest { private Client createClient(boolean vertexAI, String replayId) { - // Use the API mode until the replay mode is complete. + String clientMode = System.getenv("GOOGLE_GENAI_CLIENT_MODE"); DebugConfig debugConfig = - new DebugConfig("api", "", System.getenv("GOOGLE_GENAI_REPLAYS_DIRECTORY")); + new DebugConfig( + clientMode == null ? "replay" : clientMode, + "", + System.getenv("GOOGLE_GENAI_REPLAYS_DIRECTORY")); Client client = Client.builder().debugConfig(debugConfig).vertexAI(vertexAI).build(); - if (client.clientMode().equals("replay") || client.clientMode().equals("auto")) { + if (client.clientMode().equals("replay")) { client.setReplayId(replayId); } return client; @@ -46,27 +48,29 @@ public void testGetVideosOperation(boolean vertexAI) throws Exception { // Arrange String suffix = vertexAI ? "vertex" : "mldev"; Client client = - createClient(vertexAI, "tests/operations/test_get_videos_operation." + suffix + ".json"); + createClient( + vertexAI, + "tests/models/generate_videos/test_create_operation_to_poll." + suffix + ".json"); - // Act - GenerateVideosConfig generateVideosConfig = - GenerateVideosConfig.builder().numberOfVideos(1).build(); + String operationName = + vertexAI + ? "projects//locations//publishers/google/models/veo-2.0-generate-001/operations/ddb46542-07ed-4000-958d-655fbffb05a4" + : "models/veo-2.0-generate-001/operations/ren0ubieaocs"; + // Act GenerateVideosOperation generateVideosOperation = - client.models.generateVideos( - "veo-2.0-generate-001", - "A neon hologram of a cat driving at top speed", - null, - null, - generateVideosConfig); + client.operations.getVideosOperation( + GenerateVideosOperation.builder().name(operationName).build(), null); // GenerateVideosOperation.done() is empty if the operation is not done. while (!generateVideosOperation.done().filter(Boolean::booleanValue).isPresent()) { try { - Thread.sleep(10000); // Sleep for 10 seconds. + if (!client.clientMode().equals("replay")) { + Thread.sleep(10000); // Sleep for 10 seconds. + System.out.println("Waiting for operation to complete..."); + } generateVideosOperation = client.operations.getVideosOperation(generateVideosOperation, null); - System.out.println("Waiting for operation to complete..."); } catch (InterruptedException e) { System.out.println("Thread was interrupted while sleeping."); Thread.currentThread().interrupt(); diff --git a/src/test/java/com/google/genai/TableTest.java b/src/test/java/com/google/genai/TableTest.java index e41bfedd221..ea19623fbc7 100644 --- a/src/test/java/com/google/genai/TableTest.java +++ b/src/test/java/com/google/genai/TableTest.java @@ -269,8 +269,8 @@ static Client createClient(boolean vertexAI) { } String testsReplaysPath = replaysPath + "/tests"; String replayMode = System.getenv("GOOGLE_GENAI_CLIENT_MODE"); - if (replayMode == null) { - replayMode = "auto"; + if (replayMode == null || replayMode == "auto") { + replayMode = "replay"; } DebugConfig debugConfig = new DebugConfig(replayMode, "", testsReplaysPath); diff --git a/src/test/resources/checkerboard.png b/src/test/resources/checkerboard.png new file mode 100644 index 0000000000000000000000000000000000000000..0e85ff5cd360e591b00f90edea168da90809a0d1 GIT binary patch literal 387 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�U0N z3m6JPKp0sW8@)7ef#2ByzNjH_8IB}mH>f&eAXG;q!hPy}p-9g4)~36>eW@M_@Y*0J zu()+zMC5S+-TB@6)yQVYsmCP7Eu0(m(S@+;dYRA#Wi`_Spy`oEjm1TS`wRsw9sEbOIWFBIc zOd}Gyb8#`kUPSRe7fBA8nmI}&FiV0!hA^gqg#-vodh*@Mwh^D8=m5uFB0s#G;JZlb zhac7*EK7i?GLFx##DnX_Mm%Ytb{3JxEyL+Z&?6&RD5xo?Io|6H%v%{m%Qfs1Q6*s^ zFuSWd4o4O4_&=!KOj66KoEM6j37#A^>vkl=q;2MG>xXjF)UDpp$O<<#Wa5%z9hN{r z8e-D_U6K>(R#HYs2vWFQ@>;L7^P4^_H*a_IN9Yl^dIEu=RmnEiNtAD2M{^yM1e)g% z#ZpKrbTpFg9+<#gZ%qWln+Bo1fcn#Rg0pjZZyJnzU>}Dg38EEy{>G2OVgT*j2w!bC z=%tVb;aGJU3yJa!;|N(BxSg|1FCXp6fNop3ONr=ZgCu!uq5805bb`n;Y?Yiu_m&`% zO9e5Ecoc;pGDK^Fq&7&t|5ki1MgVdlJRiI$m(=$*amQPP2jFN4cuXh2*C%hVly#ybtNS?fMsTH@Ft<4uUv_k~-QFBv8|nMP556&n<;Q8KqwAJD3CEs8Y-t zFNA#0=P)sVg$1PR-0^?XD#U@!VY@zUqY{oXuysqqaBa*v#pjXDPmolh>KDjkDLzjK zVb>RNUEfK=wbA&7Cb+ow9Fn#DogIfn(k5>^!90T1TdXVN1{*U@a1x6UkOvcdLX@ro zH-CntS6FWj_=LnfnSVLv&nWPCX<-5(~Bk~r}GnDnnkOjxmCE1_UNRbW&ERdtdG1bBJogx&BkK}AF@d6+j45~k4; z3Cg9m>%G>jhy&_Flzv&0Q8Ng65z4Aj+s>7;=9Q`&r9?hrFA*Iq!g$L_i39J4r~{M! z6#_G1Y}fx*R1dGeR2uzbm;i-9kf>KeAcQuH0=FKHnm7>Q6m!Nj7AK$tgz(FD{9Cvi zlp`jMZSW!CPH;|c!Fq+8Q@#nQ#I0^bB#lNK#jNSn%;HcE=sm=Z-`!|Lva^A%2l|j^ zcacNSQPVp^UKsy@u_X{KzO5gulXBEiMj(XBU^#1Kkdqr_2t3JC7piN#XX4C_5o#h= zVmrY-Fo1!iT%v}*#&*01ITB}1a3Vp?8Y_^e5a-4mawLVU_0(tsvhn|z?2nnFg`AaD z?eb2_kMy?XkRuUCoTo7QaRB>!ouGHXSrd;~fa(3-qC6$pWPC zf=ni&SE|U3)8JT#2%|qUX)>Z^#gT@Fh6WVO1Oi#bYN4T_p@Ad!Xas^hA8S2mXlNk6 z20^2$_l76y7@HTZp`kIOYv8@y_2**pAj+sJ%J}FACu&AcU>X`4$p<=eIjSqJw|Uo_ z*na>C(PmF4fc7N8iGB?Y4U}c!4Kv!LL3~YQKhvq0h-?V?kDoFP4UOaiz8yrp&}PU2 zSc8CNMJ6A-K%C3_&rCx@Be}@U-*^~Rc!;LXMyB;cqzDH*qR4T>tgh-FOhZE>*~qy5 zjZ&=+Av&@#-A=}F&vty5wFWdabkzkVRmnkTFJd?pqKc7vw&2T)F(l~dmgt)qz-MBu z0SyfeNYTUkdWakTQQPqs+pg~*azI4G9dCKK#yc#34r?uFXlQ@{;x?^9jszkz){4;3 z(8^P9XEwaA&)pjjXRQwn4IPOfm(fH5d5K`s-Ad5V z(7@OZIEkq}wgh)7bH3Bi(1_nKh&#b`Q9HCljS90XHuj;Rp#g_6?gUq(G~37|L!J-% z;95qQ@ITg|p`ih9Q`lk(BDsb;{^KJJX3ylkEl{7@u74XuXE0`F8X6iJZ=Ym`(reoF zkLFIL1OBMo^^W4M|9-9KXf Date: Mon, 7 Jul 2025 11:16:00 -0700 Subject: [PATCH 058/602] feat: Add new languages for Imagen 4 prompt language PiperOrigin-RevId: 780186165 --- .../google/genai/types/ImagePromptLanguage.java | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/main/java/com/google/genai/types/ImagePromptLanguage.java b/src/main/java/com/google/genai/types/ImagePromptLanguage.java index 62a566add33..3bfe8c30b2b 100644 --- a/src/main/java/com/google/genai/types/ImagePromptLanguage.java +++ b/src/main/java/com/google/genai/types/ImagePromptLanguage.java @@ -28,16 +28,30 @@ public class ImagePromptLanguage { /** Enum representing the known values for ImagePromptLanguage. */ public enum Known { + /** Auto-detect the language. */ AUTO, + /** English */ EN, + /** Japanese */ JA, + /** Korean */ KO, + /** Hindi */ HI, + /** Chinese */ + ZH, + + /** Portuguese */ + PT, + + /** Spanish */ + ES, + IMAGE_PROMPT_LANGUAGE_UNSPECIFIED } From 3219fbd7b1527b64f3562b584158ebfe5145dc8b Mon Sep 17 00:00:00 2001 From: Mark Daoust Date: Mon, 7 Jul 2025 13:58:53 -0700 Subject: [PATCH 059/602] chore: Update default live model for MLDev to 2.5 preview. PiperOrigin-RevId: 780248950 --- .../com/google/genai/examples/LiveAudioConversationAsync.java | 2 +- .../genai/examples/LiveTextContextWindowCompressionAsync.java | 2 +- .../com/google/genai/examples/LiveTextConversationAsync.java | 2 +- .../genai/examples/LiveTextConversationResumptionAsync.java | 2 +- .../genai/examples/LiveTextToAudioTranscriptionAsync.java | 2 +- .../google/genai/examples/LiveTextToTextGenerationAsync.java | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/examples/src/main/java/com/google/genai/examples/LiveAudioConversationAsync.java b/examples/src/main/java/com/google/genai/examples/LiveAudioConversationAsync.java index f54f9ef7390..c127d81125e 100644 --- a/examples/src/main/java/com/google/genai/examples/LiveAudioConversationAsync.java +++ b/examples/src/main/java/com/google/genai/examples/LiveAudioConversationAsync.java @@ -157,7 +157,7 @@ public static void main(String[] args) throws LineUnavailableException { if (client.vertexAI()) { modelId = "gemini-2.0-flash-live-preview-04-09"; } else { - modelId = "gemini-2.0-flash-live-001"; + modelId = "gemini-live-2.5-flash-preview"; } if (args.length != 0) { modelId = args[0]; diff --git a/examples/src/main/java/com/google/genai/examples/LiveTextContextWindowCompressionAsync.java b/examples/src/main/java/com/google/genai/examples/LiveTextContextWindowCompressionAsync.java index 3844fe389fb..aa4b7e636dd 100644 --- a/examples/src/main/java/com/google/genai/examples/LiveTextContextWindowCompressionAsync.java +++ b/examples/src/main/java/com/google/genai/examples/LiveTextContextWindowCompressionAsync.java @@ -81,7 +81,7 @@ public static void main(String[] args) { if (client.vertexAI()) { modelId = "gemini-2.0-flash-live-preview-04-09"; } else { - modelId = "gemini-2.0-flash-live-001"; + modelId = "gemini-live-2.5-flash-preview"; } if (args.length != 0) { modelId = args[0]; diff --git a/examples/src/main/java/com/google/genai/examples/LiveTextConversationAsync.java b/examples/src/main/java/com/google/genai/examples/LiveTextConversationAsync.java index 9f7a3d500d1..c0cef47f12e 100644 --- a/examples/src/main/java/com/google/genai/examples/LiveTextConversationAsync.java +++ b/examples/src/main/java/com/google/genai/examples/LiveTextConversationAsync.java @@ -79,7 +79,7 @@ public static void main(String[] args) { if (client.vertexAI()) { modelId = "gemini-2.0-flash-live-preview-04-09"; } else { - modelId = "gemini-2.0-flash-live-001"; + modelId = "gemini-live-2.5-flash-preview"; } if (args.length != 0) { modelId = args[0]; diff --git a/examples/src/main/java/com/google/genai/examples/LiveTextConversationResumptionAsync.java b/examples/src/main/java/com/google/genai/examples/LiveTextConversationResumptionAsync.java index 67a9a92caa3..ea18e0eeeac 100644 --- a/examples/src/main/java/com/google/genai/examples/LiveTextConversationResumptionAsync.java +++ b/examples/src/main/java/com/google/genai/examples/LiveTextConversationResumptionAsync.java @@ -120,7 +120,7 @@ public static void main(String[] args) { if (client.vertexAI()) { modelId = "gemini-2.0-flash-live-preview-04-09"; } else { - modelId = "gemini-2.0-flash-live-001"; + modelId = "gemini-live-2.5-flash-preview"; } if (containsModelId) { modelId = args[0]; diff --git a/examples/src/main/java/com/google/genai/examples/LiveTextToAudioTranscriptionAsync.java b/examples/src/main/java/com/google/genai/examples/LiveTextToAudioTranscriptionAsync.java index 10dd6345833..5690819f880 100644 --- a/examples/src/main/java/com/google/genai/examples/LiveTextToAudioTranscriptionAsync.java +++ b/examples/src/main/java/com/google/genai/examples/LiveTextToAudioTranscriptionAsync.java @@ -84,7 +84,7 @@ public static void main(String[] args) { if (client.vertexAI()) { modelId = "gemini-2.0-flash-live-preview-04-09"; } else { - modelId = "gemini-2.0-flash-live-001"; + modelId = "gemini-live-2.5-flash-preview"; } if (args.length != 0) { modelId = args[0]; diff --git a/examples/src/main/java/com/google/genai/examples/LiveTextToTextGenerationAsync.java b/examples/src/main/java/com/google/genai/examples/LiveTextToTextGenerationAsync.java index adccf9b58e1..8e7541e9c04 100644 --- a/examples/src/main/java/com/google/genai/examples/LiveTextToTextGenerationAsync.java +++ b/examples/src/main/java/com/google/genai/examples/LiveTextToTextGenerationAsync.java @@ -77,7 +77,7 @@ public static void main(String[] args) { if (client.vertexAI()) { modelId = "gemini-2.0-flash-live-preview-04-09"; } else { - modelId = "gemini-2.0-flash-live-001"; + modelId = "gemini-live-2.5-flash-preview"; } if (args.length != 0) { modelId = args[0]; From bf98f0194ebb431825e6cae941742ccb93f69277 Mon Sep 17 00:00:00 2001 From: Jaycee Li Date: Tue, 8 Jul 2025 15:33:22 -0700 Subject: [PATCH 060/602] chore: Align Java error message with Python PiperOrigin-RevId: 780739394 --- src/main/java/com/google/genai/Files.java | 24 ++++++++++++------- src/main/java/com/google/genai/Models.java | 12 +++++----- .../java/com/google/genai/Operations.java | 4 ++-- .../java/com/google/genai/Transformers.java | 5 +++- .../java/com/google/genai/ModelsTest.java | 12 ++++------ 5 files changed, 32 insertions(+), 25 deletions(-) diff --git a/src/main/java/com/google/genai/Files.java b/src/main/java/com/google/genai/Files.java index 90a49e875ee..46210001f4a 100644 --- a/src/main/java/com/google/genai/Files.java +++ b/src/main/java/com/google/genai/Files.java @@ -488,7 +488,8 @@ ListFilesResponse privateList(ListFilesConfig config) { ObjectNode body; String path; if (this.apiClient.vertexAI()) { - throw new UnsupportedOperationException("This method is not supported by the Vertex AI."); + throw new UnsupportedOperationException( + "This method is only supported in the Gemini Developer client."); } else { body = listFilesParametersToMldev(parameterNode, null); if (body.get("_url") != null) { @@ -526,7 +527,8 @@ ListFilesResponse privateList(ListFilesConfig config) { JsonNode responseNode = JsonSerializable.stringToJsonNode(responseString); if (this.apiClient.vertexAI()) { - throw new UnsupportedOperationException("This method is not supported by the Vertex AI."); + throw new UnsupportedOperationException( + "This method is only supported in the Gemini Developer client."); } else { responseNode = listFilesResponseFromMldev(responseNode, null); } @@ -549,7 +551,8 @@ CreateFileResponse privateCreate(File file, CreateFileConfig config) { ObjectNode body; String path; if (this.apiClient.vertexAI()) { - throw new UnsupportedOperationException("This method is not supported by the Vertex AI."); + throw new UnsupportedOperationException( + "This method is only supported in the Gemini Developer client."); } else { body = createFileParametersToMldev(parameterNode, null); if (body.get("_url") != null) { @@ -598,7 +601,8 @@ CreateFileResponse privateCreate(File file, CreateFileConfig config) { JsonNode responseNode = JsonSerializable.stringToJsonNode(responseString); if (this.apiClient.vertexAI()) { - throw new UnsupportedOperationException("This method is not supported by the Vertex AI."); + throw new UnsupportedOperationException( + "This method is only supported in the Gemini Developer client."); } else { responseNode = createFileResponseFromMldev(responseNode, null); } @@ -628,7 +632,8 @@ public File get(String name, GetFileConfig config) { ObjectNode body; String path; if (this.apiClient.vertexAI()) { - throw new UnsupportedOperationException("This method is not supported by the Vertex AI."); + throw new UnsupportedOperationException( + "This method is only supported in the Gemini Developer client."); } else { body = getFileParametersToMldev(parameterNode, null); if (body.get("_url") != null) { @@ -666,7 +671,8 @@ public File get(String name, GetFileConfig config) { JsonNode responseNode = JsonSerializable.stringToJsonNode(responseString); if (this.apiClient.vertexAI()) { - throw new UnsupportedOperationException("This method is not supported by the Vertex AI."); + throw new UnsupportedOperationException( + "This method is only supported in the Gemini Developer client."); } else { responseNode = fileFromMldev(responseNode, null); } @@ -696,7 +702,8 @@ public DeleteFileResponse delete(String name, DeleteFileConfig config) { ObjectNode body; String path; if (this.apiClient.vertexAI()) { - throw new UnsupportedOperationException("This method is not supported by the Vertex AI."); + throw new UnsupportedOperationException( + "This method is only supported in the Gemini Developer client."); } else { body = deleteFileParametersToMldev(parameterNode, null); if (body.get("_url") != null) { @@ -734,7 +741,8 @@ public DeleteFileResponse delete(String name, DeleteFileConfig config) { JsonNode responseNode = JsonSerializable.stringToJsonNode(responseString); if (this.apiClient.vertexAI()) { - throw new UnsupportedOperationException("This method is not supported by the Vertex AI."); + throw new UnsupportedOperationException( + "This method is only supported in the Gemini Developer client."); } else { responseNode = deleteFileResponseFromMldev(responseNode, null); } diff --git a/src/main/java/com/google/genai/Models.java b/src/main/java/com/google/genai/Models.java index da7ec3f0486..8bcdef31f19 100644 --- a/src/main/java/com/google/genai/Models.java +++ b/src/main/java/com/google/genai/Models.java @@ -6119,7 +6119,7 @@ EditImageResponse privateEditImage( path = Common.formatMap("{model}:predict", body.get("_url")); } else { throw new UnsupportedOperationException( - "This method is not supported by the Gemini Developer API."); + "This method is only supported in the Vertex AI client."); } body.remove("_url"); @@ -6153,7 +6153,7 @@ EditImageResponse privateEditImage( responseNode = editImageResponseFromVertex(responseNode, null); } else { throw new UnsupportedOperationException( - "This method is not supported by the Gemini Developer API."); + "This method is only supported in the Vertex AI client."); } return JsonSerializable.fromJsonNode(responseNode, EditImageResponse.class); } @@ -6185,7 +6185,7 @@ UpscaleImageResponse privateUpscaleImage( path = Common.formatMap("{model}:predict", body.get("_url")); } else { throw new UnsupportedOperationException( - "This method is not supported by the Gemini Developer API."); + "This method is only supported in the Vertex AI client."); } body.remove("_url"); @@ -6219,7 +6219,7 @@ UpscaleImageResponse privateUpscaleImage( responseNode = upscaleImageResponseFromVertex(responseNode, null); } else { throw new UnsupportedOperationException( - "This method is not supported by the Gemini Developer API."); + "This method is only supported in the Vertex AI client."); } return JsonSerializable.fromJsonNode(responseNode, UpscaleImageResponse.class); } @@ -6600,7 +6600,7 @@ public ComputeTokensResponse computeTokens( path = Common.formatMap("{model}:computeTokens", body.get("_url")); } else { throw new UnsupportedOperationException( - "This method is not supported by the Gemini Developer API."); + "This method is only supported in the Vertex AI client."); } body.remove("_url"); @@ -6634,7 +6634,7 @@ public ComputeTokensResponse computeTokens( responseNode = computeTokensResponseFromVertex(responseNode, null); } else { throw new UnsupportedOperationException( - "This method is not supported by the Gemini Developer API."); + "This method is only supported in the Vertex AI client."); } return JsonSerializable.fromJsonNode(responseNode, ComputeTokensResponse.class); } diff --git a/src/main/java/com/google/genai/Operations.java b/src/main/java/com/google/genai/Operations.java index 3bb9dee0979..fa69713e752 100644 --- a/src/main/java/com/google/genai/Operations.java +++ b/src/main/java/com/google/genai/Operations.java @@ -442,7 +442,7 @@ GenerateVideosOperation privateFetchPredictVideosOperation( path = Common.formatMap("{resourceName}:fetchPredictOperation", body.get("_url")); } else { throw new UnsupportedOperationException( - "This method is not supported by the Gemini Developer API."); + "This method is only supported in the Vertex AI client."); } body.remove("_url"); @@ -476,7 +476,7 @@ GenerateVideosOperation privateFetchPredictVideosOperation( responseNode = generateVideosOperationFromVertex(responseNode, null); } else { throw new UnsupportedOperationException( - "This method is not supported by the Gemini Developer API."); + "This method is only supported in the Vertex AI client."); } return JsonSerializable.fromJsonNode(responseNode, GenerateVideosOperation.class); } diff --git a/src/main/java/com/google/genai/Transformers.java b/src/main/java/com/google/genai/Transformers.java index 3db7e80df2d..178473a90a9 100644 --- a/src/main/java/com/google/genai/Transformers.java +++ b/src/main/java/com/google/genai/Transformers.java @@ -62,7 +62,7 @@ private Transformers() {} public static String tModel(ApiClient apiClient, Object origin) { String model; if (origin == null) { - return null; + throw new IllegalArgumentException("model is required."); } else if (origin instanceof String) { model = (String) origin; } else if (origin instanceof JsonNode) { @@ -71,6 +71,9 @@ public static String tModel(ApiClient apiClient, Object origin) { } else { throw new IllegalArgumentException("Unsupported model type: " + origin.getClass()); } + if (model.isEmpty()) { + throw new IllegalArgumentException("model is required."); + } if (apiClient.vertexAI()) { if (model.startsWith("publishers/") || model.startsWith("projects/") diff --git a/src/test/java/com/google/genai/ModelsTest.java b/src/test/java/com/google/genai/ModelsTest.java index 71fb024cdf6..76e7ad484c6 100644 --- a/src/test/java/com/google/genai/ModelsTest.java +++ b/src/test/java/com/google/genai/ModelsTest.java @@ -348,10 +348,6 @@ public void testListModel_filterThrowException(boolean vertexAI) throws Exceptio @ParameterizedTest @ValueSource(booleans = {false, true}) public void testEditImage_withMaskReference(boolean vertexAI) throws Exception { - if (!vertexAI) { - // EditImage is not supported in MLDev. - return; - } // Arrange String suffix = vertexAI ? "vertex" : "mldev"; Client client = @@ -396,7 +392,7 @@ public void testEditImage_withMaskReference(boolean vertexAI) throws Exception { config)); // Assert assertEquals( - "This method is not supported by the Gemini Developer API.", exception.getMessage()); + "This method is only supported in the Vertex AI client.", exception.getMessage()); } } @@ -440,7 +436,7 @@ public void testEditImage_withControlReference(boolean vertexAI) throws Exceptio config)); // Assert assertEquals( - "This method is not supported by the Gemini Developer API.", exception.getMessage()); + "This method is only supported in the Vertex AI client.", exception.getMessage()); } } @@ -486,7 +482,7 @@ public void testEditImage_withSubjectReference(boolean vertexAI) throws Exceptio config)); // Assert assertEquals( - "This method is not supported by the Gemini Developer API.", exception.getMessage()); + "This method is only supported in the Vertex AI client.", exception.getMessage()); } } @@ -534,7 +530,7 @@ public void testEditImage_withStyleTransfer(boolean vertexAI) throws Exception { config)); // Assert assertEquals( - "This method is not supported by the Gemini Developer API.", exception.getMessage()); + "This method is only supported in the Vertex AI client.", exception.getMessage()); } } } From d2f3c0e948412973621301f70d6dfde8e25638d1 Mon Sep 17 00:00:00 2001 From: Ayush Agrawal Date: Wed, 9 Jul 2025 12:09:23 -0700 Subject: [PATCH 061/602] feat: update release-please configuration to enable version updating across all files PiperOrigin-RevId: 781156401 --- README.md | 7 ++----- release-please-config.json | 12 +++++------- versions.txt | 2 +- 3 files changed, 8 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 8df26fc78d8..2768338b1f8 100644 --- a/README.md +++ b/README.md @@ -9,9 +9,7 @@ Java idiomatic SDK for the ## Add dependency If you're using Maven, add the following to your dependencies: - - - +[//]: # ({x-version-update-start:google-genai:released}) ```xml @@ -21,8 +19,7 @@ If you're using Maven, add the following to your dependencies: ``` - - +[//]: # ({x-version-update-end}) ## Getting Started diff --git a/release-please-config.json b/release-please-config.json index ce2b1c767ba..176e73c2c6f 100644 --- a/release-please-config.json +++ b/release-please-config.json @@ -1,17 +1,15 @@ { "$schema": "https://raw.githubusercontent.com/googleapis/release-please/main/schemas/config.json", - "release-type": "maven", "versioning": "always-bump-minor", "separate-pull-requests": true, "include-component-in-tag": false, - "initial-version": "0.2.0-SNAPSHOT", - "extra-files": ["README.md", "src/main/java/com/google/genai/ApiClient.java"], + "bump-minor-pre-major": false, + "bump-patch-for-minor-pre-major": false, "packages": { ".": { - "changelog-path": "CHANGELOG.md", - "release-type": "maven", - "bump-minor-pre-major": false, - "bump-patch-for-minor-pre-major": false + "release-type": "java-yoshi", + "extra-files": ["README.md", "src/main/java/com/google/genai/ApiClient.java"], + "changelog-path": "CHANGELOG.md" } } } \ No newline at end of file diff --git a/versions.txt b/versions.txt index 1ffa75a976a..01a9dfdf6e2 100644 --- a/versions.txt +++ b/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-genai:1.5.0:1.6.0-SNAPSHOT +google-genai:1.7.0:1.8.0-SNAPSHOT From f82b356d2f42ce2bf596875aa5ba595754809235 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Wed, 9 Jul 2025 14:28:27 -0700 Subject: [PATCH 062/602] chore(main): release 1.8.0 (#384) * chore(main): release 1.8.0 * Update CHANGELOG.md --------- Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> Co-authored-by: Ivan Lopez Hernandez --- .release-please-manifest.json | 2 +- CHANGELOG.md | 7 +++++++ README.md | 2 +- examples/pom.xml | 4 ++-- pom.xml | 2 +- src/main/java/com/google/genai/ApiClient.java | 2 +- versions.txt | 2 +- 7 files changed, 14 insertions(+), 7 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index cce9d1c6d3e..c523ce19f0b 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "1.7.0" + ".": "1.8.0" } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index fe80fdc6c1e..64bdd0276a3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## [1.8.0](https://github.com/googleapis/java-genai/compare/v1.7.0...v1.8.0) (2025-07-09) + + +### Features + +* Add new languages for Imagen 4 prompt language ([7e1e6d2](https://github.com/googleapis/java-genai/commit/7e1e6d2ead45c7a0737e4a010fce266fb436d2dd)) + ## [1.7.0](https://github.com/googleapis/java-genai/compare/v1.6.0...v1.7.0) (2025-07-01) diff --git a/README.md b/README.md index 2768338b1f8..71f3d23466b 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ If you're using Maven, add the following to your dependencies: com.google.genai google-genai - 1.7.0 + 1.8.0 ``` diff --git a/examples/pom.xml b/examples/pom.xml index 591c795df64..fbdc7deed73 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -5,7 +5,7 @@ com.google.genai.examples google-genai-examples - 1.8.0-SNAPSHOT + 1.8.0 google-genai-examples @@ -13,7 +13,7 @@ 1.8 1.8 - 1.8.0-SNAPSHOT + 1.8.0 diff --git a/pom.xml b/pom.xml index e8cb0c6f358..ad0768840f4 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ com.google.genai google-genai google-genai - 1.8.0-SNAPSHOT + 1.8.0 jar Java idiomatic SDK for the Gemini Developer APIs and Vertex AI APIs. diff --git a/src/main/java/com/google/genai/ApiClient.java b/src/main/java/com/google/genai/ApiClient.java index 59abde6fa8c..85f64e978ea 100644 --- a/src/main/java/com/google/genai/ApiClient.java +++ b/src/main/java/com/google/genai/ApiClient.java @@ -45,7 +45,7 @@ abstract class ApiClient { // {x-version-update-start:google-genai:released} - private static final String SDK_VERSION = "1.7.0"; + private static final String SDK_VERSION = "1.8.0"; // {x-version-update-end:google-genai:released} private static final Logger logger = Logger.getLogger(ApiClient.class.getName()); diff --git a/versions.txt b/versions.txt index 01a9dfdf6e2..1d9a4227282 100644 --- a/versions.txt +++ b/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-genai:1.7.0:1.8.0-SNAPSHOT +google-genai:1.8.0:1.8.0 From 9fc9673cd90d0ed203e89680b2ce287c6c820b69 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Wed, 9 Jul 2025 14:32:46 -0700 Subject: [PATCH 063/602] chore(main): release 1.9.0-SNAPSHOT (#394) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- examples/pom.xml | 4 ++-- pom.xml | 2 +- versions.txt | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/pom.xml b/examples/pom.xml index fbdc7deed73..30c12b197ef 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -5,7 +5,7 @@ com.google.genai.examples google-genai-examples - 1.8.0 + 1.9.0-SNAPSHOT google-genai-examples @@ -13,7 +13,7 @@ 1.8 1.8 - 1.8.0 + 1.9.0-SNAPSHOT diff --git a/pom.xml b/pom.xml index ad0768840f4..5443657093d 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ com.google.genai google-genai google-genai - 1.8.0 + 1.9.0-SNAPSHOT jar Java idiomatic SDK for the Gemini Developer APIs and Vertex AI APIs. diff --git a/versions.txt b/versions.txt index 1d9a4227282..92cc1f726e6 100644 --- a/versions.txt +++ b/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-genai:1.8.0:1.8.0 +google-genai:1.8.0:1.9.0-SNAPSHOT From 21ce8f5a29f56fcb94bad1221a0547530092fcfa Mon Sep 17 00:00:00 2001 From: Ivan Lopez Hernandez Date: Wed, 9 Jul 2025 14:31:53 -0700 Subject: [PATCH 064/602] Copybara import of the project: -- 35dc340997585bd91bad4ed5a13fad3408b98ec0 by release-please[bot] <55107282+release-please[bot]@users.noreply.github.com>: chore(main): release 1.8.0 -- 4be6357ad2c742862d98468b38ac1455965f0fba by Ivan Lopez Hernandez : Update CHANGELOG.md COPYBARA_INTEGRATE_REVIEW=https://github.com/googleapis/java-genai/pull/384 from googleapis:release-please--branches--main 4be6357ad2c742862d98468b38ac1455965f0fba PiperOrigin-RevId: 781213354 --- examples/pom.xml | 4 ++-- pom.xml | 2 +- versions.txt | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/pom.xml b/examples/pom.xml index 30c12b197ef..fbdc7deed73 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -5,7 +5,7 @@ com.google.genai.examples google-genai-examples - 1.9.0-SNAPSHOT + 1.8.0 google-genai-examples @@ -13,7 +13,7 @@ 1.8 1.8 - 1.9.0-SNAPSHOT + 1.8.0 diff --git a/pom.xml b/pom.xml index 5443657093d..ad0768840f4 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ com.google.genai google-genai google-genai - 1.9.0-SNAPSHOT + 1.8.0 jar Java idiomatic SDK for the Gemini Developer APIs and Vertex AI APIs. diff --git a/versions.txt b/versions.txt index 92cc1f726e6..1d9a4227282 100644 --- a/versions.txt +++ b/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-genai:1.8.0:1.9.0-SNAPSHOT +google-genai:1.8.0:1.8.0 From 8b49778acc292bf7d2834fd980a3f1d1e0991c02 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Wed, 9 Jul 2025 14:55:55 -0700 Subject: [PATCH 065/602] Copybara import of the project: -- 6f904348c1cb865377ca8733ab961b16c0dad301 by release-please[bot] <55107282+release-please[bot]@users.noreply.github.com>: chore(main): release 1.9.0-SNAPSHOT COPYBARA_INTEGRATE_REVIEW=https://github.com/googleapis/java-genai/pull/394 from googleapis:release-please--branches--main 6f904348c1cb865377ca8733ab961b16c0dad301 PiperOrigin-RevId: 781223059 --- examples/pom.xml | 4 ++-- pom.xml | 2 +- versions.txt | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/pom.xml b/examples/pom.xml index fbdc7deed73..30c12b197ef 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -5,7 +5,7 @@ com.google.genai.examples google-genai-examples - 1.8.0 + 1.9.0-SNAPSHOT google-genai-examples @@ -13,7 +13,7 @@ 1.8 1.8 - 1.8.0 + 1.9.0-SNAPSHOT diff --git a/pom.xml b/pom.xml index ad0768840f4..5443657093d 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ com.google.genai google-genai google-genai - 1.8.0 + 1.9.0-SNAPSHOT jar Java idiomatic SDK for the Gemini Developer APIs and Vertex AI APIs. diff --git a/versions.txt b/versions.txt index 1d9a4227282..92cc1f726e6 100644 --- a/versions.txt +++ b/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-genai:1.8.0:1.8.0 +google-genai:1.8.0:1.9.0-SNAPSHOT From 7676dbe74afb2495ae7e954f3a498a6a2a1d8afe Mon Sep 17 00:00:00 2001 From: Amy Wu Date: Thu, 10 Jul 2025 11:22:33 -0700 Subject: [PATCH 066/602] chore: remove unused converter functions PiperOrigin-RevId: 781610804 --- src/main/java/com/google/genai/Batches.java | 4838 +++-------------- src/main/java/com/google/genai/Caches.java | 72 - .../java/com/google/genai/LiveConverters.java | 3473 ++++++------ src/main/java/com/google/genai/Models.java | 143 - .../com/google/genai/TokensConverters.java | 1028 +--- src/test/java/com/google/genai/TableTest.java | 1 - 6 files changed, 2346 insertions(+), 7209 deletions(-) diff --git a/src/main/java/com/google/genai/Batches.java b/src/main/java/com/google/genai/Batches.java index 0c51d9e4fc7..5f523be71d3 100644 --- a/src/main/java/com/google/genai/Batches.java +++ b/src/main/java/com/google/genai/Batches.java @@ -397,18 +397,6 @@ ObjectNode schemaToMldev(JsonNode fromObject, ObjectNode parentObject) { return toObject; } - @ExcludeFromGeneratedCoverageReport - ObjectNode modelSelectionConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (!Common.isZero( - Common.getValueByPath(fromObject, new String[] {"featureSelectionPreference"}))) { - throw new IllegalArgumentException( - "featureSelectionPreference parameter is not supported in Gemini API."); - } - - return toObject; - } - @ExcludeFromGeneratedCoverageReport ObjectNode safetySettingToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); @@ -560,78 +548,6 @@ ObjectNode googleSearchRetrievalToMldev(JsonNode fromObject, ObjectNode parentOb return toObject; } - @ExcludeFromGeneratedCoverageReport - ObjectNode enterpriseWebSearchToMldev(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode apiKeyConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"apiKeyString"}))) { - throw new IllegalArgumentException("apiKeyString parameter is not supported in Gemini API."); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode authConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"apiKeyConfig"}))) { - throw new IllegalArgumentException("apiKeyConfig parameter is not supported in Gemini API."); - } - - if (Common.getValueByPath(fromObject, new String[] {"authType"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"authType"}, - Common.getValueByPath(fromObject, new String[] {"authType"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"googleServiceAccountConfig"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"googleServiceAccountConfig"}, - Common.getValueByPath(fromObject, new String[] {"googleServiceAccountConfig"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"httpBasicAuthConfig"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"httpBasicAuthConfig"}, - Common.getValueByPath(fromObject, new String[] {"httpBasicAuthConfig"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"oauthConfig"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"oauthConfig"}, - Common.getValueByPath(fromObject, new String[] {"oauthConfig"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"oidcConfig"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"oidcConfig"}, - Common.getValueByPath(fromObject, new String[] {"oidcConfig"})); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode googleMapsToMldev(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"authConfig"}))) { - throw new IllegalArgumentException("authConfig parameter is not supported in Gemini API."); - } - - return toObject; - } - @ExcludeFromGeneratedCoverageReport ObjectNode urlContextToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); @@ -1221,464 +1137,194 @@ ObjectNode batchJobSourceToMldev( } @ExcludeFromGeneratedCoverageReport - ObjectNode citationMetadataToMldev(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"citations"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"citationSources"}, - Common.getValueByPath(fromObject, new String[] {"citations"})); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode urlMetadataToMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode createBatchJobConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"retrievedUrl"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"retrievedUrl"}, - Common.getValueByPath(fromObject, new String[] {"retrievedUrl"})); - } - if (Common.getValueByPath(fromObject, new String[] {"urlRetrievalStatus"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"displayName"}) != null) { Common.setValueByPath( - toObject, - new String[] {"urlRetrievalStatus"}, - Common.getValueByPath(fromObject, new String[] {"urlRetrievalStatus"})); + parentObject, + new String[] {"batch", "displayName"}, + Common.getValueByPath(fromObject, new String[] {"displayName"})); } - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode urlContextMetadataToMldev(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"urlMetadata"}) != null) { - ArrayNode keyArray = - (ArrayNode) Common.getValueByPath(fromObject, new String[] {"urlMetadata"}); - ObjectMapper objectMapper = new ObjectMapper(); - ArrayNode result = objectMapper.createArrayNode(); - - for (JsonNode item : keyArray) { - result.add(urlMetadataToMldev(JsonSerializable.toJsonNode(item), toObject)); - } - Common.setValueByPath(toObject, new String[] {"urlMetadata"}, result); + if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"dest"}))) { + throw new IllegalArgumentException("dest parameter is not supported in Gemini API."); } return toObject; } @ExcludeFromGeneratedCoverageReport - ObjectNode candidateToMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode createBatchJobParametersToMldev( + ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"content"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"model"}) != null) { Common.setValueByPath( toObject, - new String[] {"content"}, - contentToMldev( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"content"})), - toObject)); + new String[] {"_url", "model"}, + Transformers.tModel( + this.apiClient, Common.getValueByPath(fromObject, new String[] {"model"}))); } - if (Common.getValueByPath(fromObject, new String[] {"citationMetadata"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"src"}) != null) { Common.setValueByPath( toObject, - new String[] {"citationMetadata"}, - citationMetadataToMldev( + new String[] {"batch", "inputConfig"}, + batchJobSourceToMldev( + apiClient, JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"citationMetadata"})), + Transformers.tBatchJobSource( + Common.getValueByPath(fromObject, new String[] {"src"}))), toObject)); } - if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"finishMessage"}))) { - throw new IllegalArgumentException("finishMessage parameter is not supported in Gemini API."); - } - - if (Common.getValueByPath(fromObject, new String[] {"tokenCount"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"tokenCount"}, - Common.getValueByPath(fromObject, new String[] {"tokenCount"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"finishReason"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"finishReason"}, - Common.getValueByPath(fromObject, new String[] {"finishReason"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"urlContextMetadata"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"config"}) != null) { Common.setValueByPath( toObject, - new String[] {"urlContextMetadata"}, - urlContextMetadataToMldev( + new String[] {"config"}, + createBatchJobConfigToMldev( JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"urlContextMetadata"})), + Common.getValueByPath(fromObject, new String[] {"config"})), toObject)); } - if (Common.getValueByPath(fromObject, new String[] {"avgLogprobs"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"avgLogprobs"}, - Common.getValueByPath(fromObject, new String[] {"avgLogprobs"})); - } + return toObject; + } - if (Common.getValueByPath(fromObject, new String[] {"groundingMetadata"}) != null) { + @ExcludeFromGeneratedCoverageReport + ObjectNode getBatchJobParametersToMldev( + ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"name"}) != null) { Common.setValueByPath( toObject, - new String[] {"groundingMetadata"}, - Common.getValueByPath(fromObject, new String[] {"groundingMetadata"})); + new String[] {"_url", "name"}, + Transformers.tBatchJobName( + this.apiClient, Common.getValueByPath(fromObject, new String[] {"name"}))); } - if (Common.getValueByPath(fromObject, new String[] {"index"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"config"}) != null) { Common.setValueByPath( toObject, - new String[] {"index"}, - Common.getValueByPath(fromObject, new String[] {"index"})); + new String[] {"config"}, + Common.getValueByPath(fromObject, new String[] {"config"})); } - if (Common.getValueByPath(fromObject, new String[] {"logprobsResult"}) != null) { + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode cancelBatchJobParametersToMldev( + ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"name"}) != null) { Common.setValueByPath( toObject, - new String[] {"logprobsResult"}, - Common.getValueByPath(fromObject, new String[] {"logprobsResult"})); + new String[] {"_url", "name"}, + Transformers.tBatchJobName( + this.apiClient, Common.getValueByPath(fromObject, new String[] {"name"}))); } - if (Common.getValueByPath(fromObject, new String[] {"safetyRatings"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"config"}) != null) { Common.setValueByPath( toObject, - new String[] {"safetyRatings"}, - Common.getValueByPath(fromObject, new String[] {"safetyRatings"})); + new String[] {"config"}, + Common.getValueByPath(fromObject, new String[] {"config"})); } return toObject; } @ExcludeFromGeneratedCoverageReport - ObjectNode generateContentResponseToMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode listBatchJobsConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"candidates"}) != null) { - ArrayNode keyArray = - (ArrayNode) Common.getValueByPath(fromObject, new String[] {"candidates"}); - ObjectMapper objectMapper = new ObjectMapper(); - ArrayNode result = objectMapper.createArrayNode(); - - for (JsonNode item : keyArray) { - result.add(candidateToMldev(JsonSerializable.toJsonNode(item), toObject)); - } - Common.setValueByPath(toObject, new String[] {"candidates"}, result); + if (Common.getValueByPath(fromObject, new String[] {"pageSize"}) != null) { + Common.setValueByPath( + parentObject, + new String[] {"_query", "pageSize"}, + Common.getValueByPath(fromObject, new String[] {"pageSize"})); } - if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"createTime"}))) { - throw new IllegalArgumentException("createTime parameter is not supported in Gemini API."); + if (Common.getValueByPath(fromObject, new String[] {"pageToken"}) != null) { + Common.setValueByPath( + parentObject, + new String[] {"_query", "pageToken"}, + Common.getValueByPath(fromObject, new String[] {"pageToken"})); } - if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"responseId"}))) { - throw new IllegalArgumentException("responseId parameter is not supported in Gemini API."); + if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"filter"}))) { + throw new IllegalArgumentException("filter parameter is not supported in Gemini API."); } - if (Common.getValueByPath(fromObject, new String[] {"modelVersion"}) != null) { + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode listBatchJobsParametersToMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"config"}) != null) { Common.setValueByPath( toObject, - new String[] {"modelVersion"}, - Common.getValueByPath(fromObject, new String[] {"modelVersion"})); + new String[] {"config"}, + listBatchJobsConfigToMldev( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"config"})), + toObject)); } - if (Common.getValueByPath(fromObject, new String[] {"promptFeedback"}) != null) { + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode deleteBatchJobParametersToMldev( + ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"name"}) != null) { Common.setValueByPath( toObject, - new String[] {"promptFeedback"}, - Common.getValueByPath(fromObject, new String[] {"promptFeedback"})); + new String[] {"_url", "name"}, + Transformers.tBatchJobName( + this.apiClient, Common.getValueByPath(fromObject, new String[] {"name"}))); } - if (Common.getValueByPath(fromObject, new String[] {"usageMetadata"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"config"}) != null) { Common.setValueByPath( toObject, - new String[] {"usageMetadata"}, - Common.getValueByPath(fromObject, new String[] {"usageMetadata"})); + new String[] {"config"}, + Common.getValueByPath(fromObject, new String[] {"config"})); } return toObject; } @ExcludeFromGeneratedCoverageReport - ObjectNode jobErrorToMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode videoMetadataToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"details"}))) { - throw new IllegalArgumentException("details parameter is not supported in Gemini API."); + if (Common.getValueByPath(fromObject, new String[] {"fps"}) != null) { + Common.setValueByPath( + toObject, new String[] {"fps"}, Common.getValueByPath(fromObject, new String[] {"fps"})); } - if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"code"}))) { - throw new IllegalArgumentException("code parameter is not supported in Gemini API."); + if (Common.getValueByPath(fromObject, new String[] {"endOffset"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"endOffset"}, + Common.getValueByPath(fromObject, new String[] {"endOffset"})); } - if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"message"}))) { - throw new IllegalArgumentException("message parameter is not supported in Gemini API."); + if (Common.getValueByPath(fromObject, new String[] {"startOffset"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"startOffset"}, + Common.getValueByPath(fromObject, new String[] {"startOffset"})); } return toObject; } @ExcludeFromGeneratedCoverageReport - ObjectNode inlinedResponseToMldev(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"response"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"response"}, - generateContentResponseToMldev( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"response"})), - toObject)); - } - - if (Common.getValueByPath(fromObject, new String[] {"error"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"error"}, - jobErrorToMldev( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"error"})), - toObject)); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode batchJobDestinationToMldev(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"format"}))) { - throw new IllegalArgumentException("format parameter is not supported in Gemini API."); - } - - if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"gcsUri"}))) { - throw new IllegalArgumentException("gcsUri parameter is not supported in Gemini API."); - } - - if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"bigqueryUri"}))) { - throw new IllegalArgumentException("bigqueryUri parameter is not supported in Gemini API."); - } - - if (Common.getValueByPath(fromObject, new String[] {"fileName"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"responsesFile"}, - Common.getValueByPath(fromObject, new String[] {"fileName"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"inlinedResponses"}) != null) { - ArrayNode keyArray = - (ArrayNode) Common.getValueByPath(fromObject, new String[] {"inlinedResponses"}); - ObjectMapper objectMapper = new ObjectMapper(); - ArrayNode result = objectMapper.createArrayNode(); - - for (JsonNode item : keyArray) { - result.add(inlinedResponseToMldev(JsonSerializable.toJsonNode(item), toObject)); - } - Common.setValueByPath( - toObject, new String[] {"inlinedResponses", "inlinedResponses"}, result); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode createBatchJobConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - - if (Common.getValueByPath(fromObject, new String[] {"displayName"}) != null) { - Common.setValueByPath( - parentObject, - new String[] {"batch", "displayName"}, - Common.getValueByPath(fromObject, new String[] {"displayName"})); - } - - if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"dest"}))) { - throw new IllegalArgumentException("dest parameter is not supported in Gemini API."); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode createBatchJobParametersToMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"model"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"_url", "model"}, - Transformers.tModel( - this.apiClient, Common.getValueByPath(fromObject, new String[] {"model"}))); - } - - if (Common.getValueByPath(fromObject, new String[] {"src"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"batch", "inputConfig"}, - batchJobSourceToMldev( - apiClient, - JsonSerializable.toJsonNode( - Transformers.tBatchJobSource( - Common.getValueByPath(fromObject, new String[] {"src"}))), - toObject)); - } - - if (Common.getValueByPath(fromObject, new String[] {"config"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"config"}, - createBatchJobConfigToMldev( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"config"})), - toObject)); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode getBatchJobParametersToMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"name"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"_url", "name"}, - Transformers.tBatchJobName( - this.apiClient, Common.getValueByPath(fromObject, new String[] {"name"}))); - } - - if (Common.getValueByPath(fromObject, new String[] {"config"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"config"}, - Common.getValueByPath(fromObject, new String[] {"config"})); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode cancelBatchJobParametersToMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"name"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"_url", "name"}, - Transformers.tBatchJobName( - this.apiClient, Common.getValueByPath(fromObject, new String[] {"name"}))); - } - - if (Common.getValueByPath(fromObject, new String[] {"config"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"config"}, - Common.getValueByPath(fromObject, new String[] {"config"})); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode listBatchJobsConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - - if (Common.getValueByPath(fromObject, new String[] {"pageSize"}) != null) { - Common.setValueByPath( - parentObject, - new String[] {"_query", "pageSize"}, - Common.getValueByPath(fromObject, new String[] {"pageSize"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"pageToken"}) != null) { - Common.setValueByPath( - parentObject, - new String[] {"_query", "pageToken"}, - Common.getValueByPath(fromObject, new String[] {"pageToken"})); - } - - if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"filter"}))) { - throw new IllegalArgumentException("filter parameter is not supported in Gemini API."); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode listBatchJobsParametersToMldev(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"config"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"config"}, - listBatchJobsConfigToMldev( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"config"})), - toObject)); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode deleteBatchJobParametersToMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"name"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"_url", "name"}, - Transformers.tBatchJobName( - this.apiClient, Common.getValueByPath(fromObject, new String[] {"name"}))); - } - - if (Common.getValueByPath(fromObject, new String[] {"config"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"config"}, - Common.getValueByPath(fromObject, new String[] {"config"})); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode videoMetadataToVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"fps"}) != null) { - Common.setValueByPath( - toObject, new String[] {"fps"}, Common.getValueByPath(fromObject, new String[] {"fps"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"endOffset"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"endOffset"}, - Common.getValueByPath(fromObject, new String[] {"endOffset"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"startOffset"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"startOffset"}, - Common.getValueByPath(fromObject, new String[] {"startOffset"})); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode blobToVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode blobToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"displayName"}) != null) { Common.setValueByPath( @@ -1841,4237 +1487,1079 @@ ObjectNode contentToVertex(JsonNode fromObject, ObjectNode parentObject) { } @ExcludeFromGeneratedCoverageReport - ObjectNode schemaToVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode inlinedRequestToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"model"}))) { + throw new IllegalArgumentException("model parameter is not supported in Vertex AI."); + } - if (Common.getValueByPath(fromObject, new String[] {"anyOf"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"anyOf"}, - Common.getValueByPath(fromObject, new String[] {"anyOf"})); + if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"contents"}))) { + throw new IllegalArgumentException("contents parameter is not supported in Vertex AI."); } - if (Common.getValueByPath(fromObject, new String[] {"default"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"default"}, - Common.getValueByPath(fromObject, new String[] {"default"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"description"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"description"}, - Common.getValueByPath(fromObject, new String[] {"description"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"enum"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"enum"}, - Common.getValueByPath(fromObject, new String[] {"enum"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"example"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"example"}, - Common.getValueByPath(fromObject, new String[] {"example"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"format"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"format"}, - Common.getValueByPath(fromObject, new String[] {"format"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"items"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"items"}, - Common.getValueByPath(fromObject, new String[] {"items"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"maxItems"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"maxItems"}, - Common.getValueByPath(fromObject, new String[] {"maxItems"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"maxLength"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"maxLength"}, - Common.getValueByPath(fromObject, new String[] {"maxLength"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"maxProperties"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"maxProperties"}, - Common.getValueByPath(fromObject, new String[] {"maxProperties"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"maximum"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"maximum"}, - Common.getValueByPath(fromObject, new String[] {"maximum"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"minItems"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"minItems"}, - Common.getValueByPath(fromObject, new String[] {"minItems"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"minLength"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"minLength"}, - Common.getValueByPath(fromObject, new String[] {"minLength"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"minProperties"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"minProperties"}, - Common.getValueByPath(fromObject, new String[] {"minProperties"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"minimum"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"minimum"}, - Common.getValueByPath(fromObject, new String[] {"minimum"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"nullable"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"nullable"}, - Common.getValueByPath(fromObject, new String[] {"nullable"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"pattern"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"pattern"}, - Common.getValueByPath(fromObject, new String[] {"pattern"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"properties"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"properties"}, - Common.getValueByPath(fromObject, new String[] {"properties"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"propertyOrdering"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"propertyOrdering"}, - Common.getValueByPath(fromObject, new String[] {"propertyOrdering"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"required"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"required"}, - Common.getValueByPath(fromObject, new String[] {"required"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"title"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"title"}, - Common.getValueByPath(fromObject, new String[] {"title"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"type"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"type"}, - Common.getValueByPath(fromObject, new String[] {"type"})); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode modelSelectionConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"featureSelectionPreference"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"featureSelectionPreference"}, - Common.getValueByPath(fromObject, new String[] {"featureSelectionPreference"})); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode safetySettingToVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"method"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"method"}, - Common.getValueByPath(fromObject, new String[] {"method"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"category"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"category"}, - Common.getValueByPath(fromObject, new String[] {"category"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"threshold"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"threshold"}, - Common.getValueByPath(fromObject, new String[] {"threshold"})); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode functionDeclarationToVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"behavior"}))) { - throw new IllegalArgumentException("behavior parameter is not supported in Vertex AI."); - } - - if (Common.getValueByPath(fromObject, new String[] {"description"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"description"}, - Common.getValueByPath(fromObject, new String[] {"description"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"name"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"name"}, - Common.getValueByPath(fromObject, new String[] {"name"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"parameters"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"parameters"}, - Common.getValueByPath(fromObject, new String[] {"parameters"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"parametersJsonSchema"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"parametersJsonSchema"}, - Common.getValueByPath(fromObject, new String[] {"parametersJsonSchema"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"response"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"response"}, - Common.getValueByPath(fromObject, new String[] {"response"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"responseJsonSchema"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"responseJsonSchema"}, - Common.getValueByPath(fromObject, new String[] {"responseJsonSchema"})); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode intervalToVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"startTime"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"startTime"}, - Common.getValueByPath(fromObject, new String[] {"startTime"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"endTime"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"endTime"}, - Common.getValueByPath(fromObject, new String[] {"endTime"})); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode googleSearchToVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"timeRangeFilter"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"timeRangeFilter"}, - intervalToVertex( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"timeRangeFilter"})), - toObject)); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode dynamicRetrievalConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"mode"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"mode"}, - Common.getValueByPath(fromObject, new String[] {"mode"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"dynamicThreshold"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"dynamicThreshold"}, - Common.getValueByPath(fromObject, new String[] {"dynamicThreshold"})); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode googleSearchRetrievalToVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"dynamicRetrievalConfig"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"dynamicRetrievalConfig"}, - dynamicRetrievalConfigToVertex( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"dynamicRetrievalConfig"})), - toObject)); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode enterpriseWebSearchToVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode apiKeyConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"apiKeyString"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"apiKeyString"}, - Common.getValueByPath(fromObject, new String[] {"apiKeyString"})); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode authConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"apiKeyConfig"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"apiKeyConfig"}, - apiKeyConfigToVertex( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"apiKeyConfig"})), - toObject)); - } - - if (Common.getValueByPath(fromObject, new String[] {"authType"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"authType"}, - Common.getValueByPath(fromObject, new String[] {"authType"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"googleServiceAccountConfig"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"googleServiceAccountConfig"}, - Common.getValueByPath(fromObject, new String[] {"googleServiceAccountConfig"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"httpBasicAuthConfig"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"httpBasicAuthConfig"}, - Common.getValueByPath(fromObject, new String[] {"httpBasicAuthConfig"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"oauthConfig"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"oauthConfig"}, - Common.getValueByPath(fromObject, new String[] {"oauthConfig"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"oidcConfig"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"oidcConfig"}, - Common.getValueByPath(fromObject, new String[] {"oidcConfig"})); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode googleMapsToVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"authConfig"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"authConfig"}, - authConfigToVertex( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"authConfig"})), - toObject)); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode urlContextToVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode toolToVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"functionDeclarations"}) != null) { - ArrayNode keyArray = - (ArrayNode) Common.getValueByPath(fromObject, new String[] {"functionDeclarations"}); - ObjectMapper objectMapper = new ObjectMapper(); - ArrayNode result = objectMapper.createArrayNode(); - - for (JsonNode item : keyArray) { - result.add(functionDeclarationToVertex(JsonSerializable.toJsonNode(item), toObject)); - } - Common.setValueByPath(toObject, new String[] {"functionDeclarations"}, result); - } - - if (Common.getValueByPath(fromObject, new String[] {"retrieval"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"retrieval"}, - Common.getValueByPath(fromObject, new String[] {"retrieval"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"googleSearch"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"googleSearch"}, - googleSearchToVertex( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"googleSearch"})), - toObject)); - } - - if (Common.getValueByPath(fromObject, new String[] {"googleSearchRetrieval"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"googleSearchRetrieval"}, - googleSearchRetrievalToVertex( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"googleSearchRetrieval"})), - toObject)); - } - - if (Common.getValueByPath(fromObject, new String[] {"enterpriseWebSearch"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"enterpriseWebSearch"}, - enterpriseWebSearchToVertex( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"enterpriseWebSearch"})), - toObject)); - } - - if (Common.getValueByPath(fromObject, new String[] {"googleMaps"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"googleMaps"}, - googleMapsToVertex( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"googleMaps"})), - toObject)); - } - - if (Common.getValueByPath(fromObject, new String[] {"urlContext"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"urlContext"}, - urlContextToVertex( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"urlContext"})), - toObject)); - } - - if (Common.getValueByPath(fromObject, new String[] {"codeExecution"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"codeExecution"}, - Common.getValueByPath(fromObject, new String[] {"codeExecution"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"computerUse"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"computerUse"}, - Common.getValueByPath(fromObject, new String[] {"computerUse"})); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode functionCallingConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"mode"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"mode"}, - Common.getValueByPath(fromObject, new String[] {"mode"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"allowedFunctionNames"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"allowedFunctionNames"}, - Common.getValueByPath(fromObject, new String[] {"allowedFunctionNames"})); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode latLngToVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"latitude"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"latitude"}, - Common.getValueByPath(fromObject, new String[] {"latitude"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"longitude"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"longitude"}, - Common.getValueByPath(fromObject, new String[] {"longitude"})); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode retrievalConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"latLng"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"latLng"}, - latLngToVertex( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"latLng"})), - toObject)); - } - - if (Common.getValueByPath(fromObject, new String[] {"languageCode"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"languageCode"}, - Common.getValueByPath(fromObject, new String[] {"languageCode"})); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode toolConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"functionCallingConfig"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"functionCallingConfig"}, - functionCallingConfigToVertex( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"functionCallingConfig"})), - toObject)); - } - - if (Common.getValueByPath(fromObject, new String[] {"retrievalConfig"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"retrievalConfig"}, - retrievalConfigToVertex( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"retrievalConfig"})), - toObject)); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode prebuiltVoiceConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"voiceName"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"voiceName"}, - Common.getValueByPath(fromObject, new String[] {"voiceName"})); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode voiceConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"prebuiltVoiceConfig"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"prebuiltVoiceConfig"}, - prebuiltVoiceConfigToVertex( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"prebuiltVoiceConfig"})), - toObject)); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode speakerVoiceConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"speaker"}))) { - throw new IllegalArgumentException("speaker parameter is not supported in Vertex AI."); - } - - if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"voiceConfig"}))) { - throw new IllegalArgumentException("voiceConfig parameter is not supported in Vertex AI."); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode multiSpeakerVoiceConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"speakerVoiceConfigs"}))) { - throw new IllegalArgumentException( - "speakerVoiceConfigs parameter is not supported in Vertex AI."); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode speechConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"voiceConfig"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"voiceConfig"}, - voiceConfigToVertex( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"voiceConfig"})), - toObject)); - } - - if (!Common.isZero( - Common.getValueByPath(fromObject, new String[] {"multiSpeakerVoiceConfig"}))) { - throw new IllegalArgumentException( - "multiSpeakerVoiceConfig parameter is not supported in Vertex AI."); - } - - if (Common.getValueByPath(fromObject, new String[] {"languageCode"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"languageCode"}, - Common.getValueByPath(fromObject, new String[] {"languageCode"})); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode thinkingConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"includeThoughts"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"includeThoughts"}, - Common.getValueByPath(fromObject, new String[] {"includeThoughts"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"thinkingBudget"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"thinkingBudget"}, - Common.getValueByPath(fromObject, new String[] {"thinkingBudget"})); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode generateContentConfigToVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - - if (Common.getValueByPath(fromObject, new String[] {"systemInstruction"}) != null) { - Common.setValueByPath( - parentObject, - new String[] {"systemInstruction"}, - contentToVertex( - JsonSerializable.toJsonNode( - Transformers.tContent( - Common.getValueByPath(fromObject, new String[] {"systemInstruction"}))), - toObject)); - } - - if (Common.getValueByPath(fromObject, new String[] {"temperature"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"temperature"}, - Common.getValueByPath(fromObject, new String[] {"temperature"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"topP"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"topP"}, - Common.getValueByPath(fromObject, new String[] {"topP"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"topK"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"topK"}, - Common.getValueByPath(fromObject, new String[] {"topK"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"candidateCount"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"candidateCount"}, - Common.getValueByPath(fromObject, new String[] {"candidateCount"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"maxOutputTokens"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"maxOutputTokens"}, - Common.getValueByPath(fromObject, new String[] {"maxOutputTokens"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"stopSequences"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"stopSequences"}, - Common.getValueByPath(fromObject, new String[] {"stopSequences"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"responseLogprobs"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"responseLogprobs"}, - Common.getValueByPath(fromObject, new String[] {"responseLogprobs"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"logprobs"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"logprobs"}, - Common.getValueByPath(fromObject, new String[] {"logprobs"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"presencePenalty"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"presencePenalty"}, - Common.getValueByPath(fromObject, new String[] {"presencePenalty"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"frequencyPenalty"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"frequencyPenalty"}, - Common.getValueByPath(fromObject, new String[] {"frequencyPenalty"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"seed"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"seed"}, - Common.getValueByPath(fromObject, new String[] {"seed"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"responseMimeType"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"responseMimeType"}, - Common.getValueByPath(fromObject, new String[] {"responseMimeType"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"responseSchema"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"responseSchema"}, - schemaToVertex( - JsonSerializable.toJsonNode( - Transformers.tSchema( - Common.getValueByPath(fromObject, new String[] {"responseSchema"}))), - toObject)); - } - - if (Common.getValueByPath(fromObject, new String[] {"responseJsonSchema"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"responseJsonSchema"}, - Common.getValueByPath(fromObject, new String[] {"responseJsonSchema"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"routingConfig"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"routingConfig"}, - Common.getValueByPath(fromObject, new String[] {"routingConfig"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"modelSelectionConfig"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"modelConfig"}, - modelSelectionConfigToVertex( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"modelSelectionConfig"})), - toObject)); - } - - if (Common.getValueByPath(fromObject, new String[] {"safetySettings"}) != null) { - ArrayNode keyArray = - (ArrayNode) Common.getValueByPath(fromObject, new String[] {"safetySettings"}); - ObjectMapper objectMapper = new ObjectMapper(); - ArrayNode result = objectMapper.createArrayNode(); - - for (JsonNode item : keyArray) { - result.add(safetySettingToVertex(JsonSerializable.toJsonNode(item), toObject)); - } - Common.setValueByPath(parentObject, new String[] {"safetySettings"}, result); - } - - if (Common.getValueByPath(fromObject, new String[] {"tools"}) != null) { - ArrayNode keyArray = - (ArrayNode) - Transformers.tTools(Common.getValueByPath(fromObject, new String[] {"tools"})); - ObjectMapper objectMapper = new ObjectMapper(); - ArrayNode result = objectMapper.createArrayNode(); - - for (JsonNode item : keyArray) { - result.add(toolToVertex(JsonSerializable.toJsonNode(Transformers.tTool(item)), toObject)); - } - Common.setValueByPath(parentObject, new String[] {"tools"}, result); - } - - if (Common.getValueByPath(fromObject, new String[] {"toolConfig"}) != null) { - Common.setValueByPath( - parentObject, - new String[] {"toolConfig"}, - toolConfigToVertex( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"toolConfig"})), - toObject)); - } - - if (Common.getValueByPath(fromObject, new String[] {"labels"}) != null) { - Common.setValueByPath( - parentObject, - new String[] {"labels"}, - Common.getValueByPath(fromObject, new String[] {"labels"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"cachedContent"}) != null) { - Common.setValueByPath( - parentObject, - new String[] {"cachedContent"}, - Transformers.tCachedContentName( - this.apiClient, Common.getValueByPath(fromObject, new String[] {"cachedContent"}))); - } - - if (Common.getValueByPath(fromObject, new String[] {"responseModalities"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"responseModalities"}, - Common.getValueByPath(fromObject, new String[] {"responseModalities"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"mediaResolution"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"mediaResolution"}, - Common.getValueByPath(fromObject, new String[] {"mediaResolution"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"speechConfig"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"speechConfig"}, - speechConfigToVertex( - JsonSerializable.toJsonNode( - Transformers.tSpeechConfig( - Common.getValueByPath(fromObject, new String[] {"speechConfig"}))), - toObject)); - } - - if (Common.getValueByPath(fromObject, new String[] {"audioTimestamp"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"audioTimestamp"}, - Common.getValueByPath(fromObject, new String[] {"audioTimestamp"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"thinkingConfig"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"thinkingConfig"}, - thinkingConfigToVertex( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"thinkingConfig"})), - toObject)); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode inlinedRequestToVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"model"}))) { - throw new IllegalArgumentException("model parameter is not supported in Vertex AI."); - } - - if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"contents"}))) { - throw new IllegalArgumentException("contents parameter is not supported in Vertex AI."); - } - - if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"config"}))) { - throw new IllegalArgumentException("config parameter is not supported in Vertex AI."); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode batchJobSourceToVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"format"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"instancesFormat"}, - Common.getValueByPath(fromObject, new String[] {"format"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"gcsUri"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"gcsSource", "uris"}, - Common.getValueByPath(fromObject, new String[] {"gcsUri"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"bigqueryUri"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"bigquerySource", "inputUri"}, - Common.getValueByPath(fromObject, new String[] {"bigqueryUri"})); - } - - if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"fileName"}))) { - throw new IllegalArgumentException("fileName parameter is not supported in Vertex AI."); - } - - if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"inlinedRequests"}))) { - throw new IllegalArgumentException( - "inlinedRequests parameter is not supported in Vertex AI."); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode citationMetadataToVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"citations"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"citations"}, - Common.getValueByPath(fromObject, new String[] {"citations"})); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode urlMetadataToVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"retrievedUrl"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"retrievedUrl"}, - Common.getValueByPath(fromObject, new String[] {"retrievedUrl"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"urlRetrievalStatus"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"urlRetrievalStatus"}, - Common.getValueByPath(fromObject, new String[] {"urlRetrievalStatus"})); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode urlContextMetadataToVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"urlMetadata"}) != null) { - ArrayNode keyArray = - (ArrayNode) Common.getValueByPath(fromObject, new String[] {"urlMetadata"}); - ObjectMapper objectMapper = new ObjectMapper(); - ArrayNode result = objectMapper.createArrayNode(); - - for (JsonNode item : keyArray) { - result.add(urlMetadataToVertex(JsonSerializable.toJsonNode(item), toObject)); - } - Common.setValueByPath(toObject, new String[] {"urlMetadata"}, result); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode candidateToVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"content"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"content"}, - contentToVertex( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"content"})), - toObject)); - } - - if (Common.getValueByPath(fromObject, new String[] {"citationMetadata"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"citationMetadata"}, - citationMetadataToVertex( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"citationMetadata"})), - toObject)); - } - - if (Common.getValueByPath(fromObject, new String[] {"finishMessage"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"finishMessage"}, - Common.getValueByPath(fromObject, new String[] {"finishMessage"})); - } - - if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"tokenCount"}))) { - throw new IllegalArgumentException("tokenCount parameter is not supported in Vertex AI."); - } - - if (Common.getValueByPath(fromObject, new String[] {"finishReason"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"finishReason"}, - Common.getValueByPath(fromObject, new String[] {"finishReason"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"urlContextMetadata"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"urlContextMetadata"}, - urlContextMetadataToVertex( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"urlContextMetadata"})), - toObject)); - } - - if (Common.getValueByPath(fromObject, new String[] {"avgLogprobs"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"avgLogprobs"}, - Common.getValueByPath(fromObject, new String[] {"avgLogprobs"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"groundingMetadata"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"groundingMetadata"}, - Common.getValueByPath(fromObject, new String[] {"groundingMetadata"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"index"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"index"}, - Common.getValueByPath(fromObject, new String[] {"index"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"logprobsResult"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"logprobsResult"}, - Common.getValueByPath(fromObject, new String[] {"logprobsResult"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"safetyRatings"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"safetyRatings"}, - Common.getValueByPath(fromObject, new String[] {"safetyRatings"})); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode generateContentResponseToVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - - if (Common.getValueByPath(fromObject, new String[] {"candidates"}) != null) { - ArrayNode keyArray = - (ArrayNode) Common.getValueByPath(fromObject, new String[] {"candidates"}); - ObjectMapper objectMapper = new ObjectMapper(); - ArrayNode result = objectMapper.createArrayNode(); - - for (JsonNode item : keyArray) { - result.add(candidateToVertex(JsonSerializable.toJsonNode(item), toObject)); - } - Common.setValueByPath(toObject, new String[] {"candidates"}, result); - } - - if (Common.getValueByPath(fromObject, new String[] {"createTime"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"createTime"}, - Common.getValueByPath(fromObject, new String[] {"createTime"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"responseId"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"responseId"}, - Common.getValueByPath(fromObject, new String[] {"responseId"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"modelVersion"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"modelVersion"}, - Common.getValueByPath(fromObject, new String[] {"modelVersion"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"promptFeedback"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"promptFeedback"}, - Common.getValueByPath(fromObject, new String[] {"promptFeedback"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"usageMetadata"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"usageMetadata"}, - Common.getValueByPath(fromObject, new String[] {"usageMetadata"})); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode jobErrorToVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"details"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"details"}, - Common.getValueByPath(fromObject, new String[] {"details"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"code"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"code"}, - Common.getValueByPath(fromObject, new String[] {"code"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"message"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"message"}, - Common.getValueByPath(fromObject, new String[] {"message"})); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode inlinedResponseToVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"response"}))) { - throw new IllegalArgumentException("response parameter is not supported in Vertex AI."); - } - - if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"error"}))) { - throw new IllegalArgumentException("error parameter is not supported in Vertex AI."); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode batchJobDestinationToVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"format"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"predictionsFormat"}, - Common.getValueByPath(fromObject, new String[] {"format"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"gcsUri"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"gcsDestination", "outputUriPrefix"}, - Common.getValueByPath(fromObject, new String[] {"gcsUri"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"bigqueryUri"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"bigqueryDestination", "outputUri"}, - Common.getValueByPath(fromObject, new String[] {"bigqueryUri"})); - } - - if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"fileName"}))) { - throw new IllegalArgumentException("fileName parameter is not supported in Vertex AI."); - } - - if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"inlinedResponses"}))) { - throw new IllegalArgumentException( - "inlinedResponses parameter is not supported in Vertex AI."); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode createBatchJobConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - - if (Common.getValueByPath(fromObject, new String[] {"displayName"}) != null) { - Common.setValueByPath( - parentObject, - new String[] {"displayName"}, - Common.getValueByPath(fromObject, new String[] {"displayName"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"dest"}) != null) { - Common.setValueByPath( - parentObject, - new String[] {"outputConfig"}, - batchJobDestinationToVertex( - JsonSerializable.toJsonNode( - Transformers.tBatchJobDestination( - Common.getValueByPath(fromObject, new String[] {"dest"}))), - toObject)); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode createBatchJobParametersToVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"model"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"model"}, - Transformers.tModel( - this.apiClient, Common.getValueByPath(fromObject, new String[] {"model"}))); - } - - if (Common.getValueByPath(fromObject, new String[] {"src"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"inputConfig"}, - batchJobSourceToVertex( - JsonSerializable.toJsonNode( - Transformers.tBatchJobSource( - Common.getValueByPath(fromObject, new String[] {"src"}))), - toObject)); - } - - if (Common.getValueByPath(fromObject, new String[] {"config"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"config"}, - createBatchJobConfigToVertex( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"config"})), - toObject)); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode getBatchJobParametersToVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"name"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"_url", "name"}, - Transformers.tBatchJobName( - this.apiClient, Common.getValueByPath(fromObject, new String[] {"name"}))); - } - - if (Common.getValueByPath(fromObject, new String[] {"config"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"config"}, - Common.getValueByPath(fromObject, new String[] {"config"})); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode cancelBatchJobParametersToVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"name"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"_url", "name"}, - Transformers.tBatchJobName( - this.apiClient, Common.getValueByPath(fromObject, new String[] {"name"}))); - } - - if (Common.getValueByPath(fromObject, new String[] {"config"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"config"}, - Common.getValueByPath(fromObject, new String[] {"config"})); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode listBatchJobsConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - - if (Common.getValueByPath(fromObject, new String[] {"pageSize"}) != null) { - Common.setValueByPath( - parentObject, - new String[] {"_query", "pageSize"}, - Common.getValueByPath(fromObject, new String[] {"pageSize"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"pageToken"}) != null) { - Common.setValueByPath( - parentObject, - new String[] {"_query", "pageToken"}, - Common.getValueByPath(fromObject, new String[] {"pageToken"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"filter"}) != null) { - Common.setValueByPath( - parentObject, - new String[] {"_query", "filter"}, - Common.getValueByPath(fromObject, new String[] {"filter"})); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode listBatchJobsParametersToVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"config"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"config"}, - listBatchJobsConfigToVertex( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"config"})), - toObject)); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode deleteBatchJobParametersToVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"name"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"_url", "name"}, - Transformers.tBatchJobName( - this.apiClient, Common.getValueByPath(fromObject, new String[] {"name"}))); - } - - if (Common.getValueByPath(fromObject, new String[] {"config"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"config"}, - Common.getValueByPath(fromObject, new String[] {"config"})); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode jobErrorFromMldev(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode videoMetadataFromMldev(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"fps"}) != null) { - Common.setValueByPath( - toObject, new String[] {"fps"}, Common.getValueByPath(fromObject, new String[] {"fps"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"endOffset"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"endOffset"}, - Common.getValueByPath(fromObject, new String[] {"endOffset"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"startOffset"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"startOffset"}, - Common.getValueByPath(fromObject, new String[] {"startOffset"})); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode blobFromMldev(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - - if (Common.getValueByPath(fromObject, new String[] {"data"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"data"}, - Common.getValueByPath(fromObject, new String[] {"data"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"mimeType"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"mimeType"}, - Common.getValueByPath(fromObject, new String[] {"mimeType"})); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode fileDataFromMldev(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - - if (Common.getValueByPath(fromObject, new String[] {"fileUri"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"fileUri"}, - Common.getValueByPath(fromObject, new String[] {"fileUri"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"mimeType"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"mimeType"}, - Common.getValueByPath(fromObject, new String[] {"mimeType"})); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode partFromMldev(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"videoMetadata"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"videoMetadata"}, - videoMetadataFromMldev( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"videoMetadata"})), - toObject)); - } - - if (Common.getValueByPath(fromObject, new String[] {"thought"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"thought"}, - Common.getValueByPath(fromObject, new String[] {"thought"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"inlineData"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"inlineData"}, - blobFromMldev( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"inlineData"})), - toObject)); - } - - if (Common.getValueByPath(fromObject, new String[] {"fileData"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"fileData"}, - fileDataFromMldev( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"fileData"})), - toObject)); - } - - if (Common.getValueByPath(fromObject, new String[] {"thoughtSignature"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"thoughtSignature"}, - Common.getValueByPath(fromObject, new String[] {"thoughtSignature"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"codeExecutionResult"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"codeExecutionResult"}, - Common.getValueByPath(fromObject, new String[] {"codeExecutionResult"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"executableCode"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"executableCode"}, - Common.getValueByPath(fromObject, new String[] {"executableCode"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"functionCall"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"functionCall"}, - Common.getValueByPath(fromObject, new String[] {"functionCall"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"functionResponse"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"functionResponse"}, - Common.getValueByPath(fromObject, new String[] {"functionResponse"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"text"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"text"}, - Common.getValueByPath(fromObject, new String[] {"text"})); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode contentFromMldev(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"parts"}) != null) { - ArrayNode keyArray = (ArrayNode) Common.getValueByPath(fromObject, new String[] {"parts"}); - ObjectMapper objectMapper = new ObjectMapper(); - ArrayNode result = objectMapper.createArrayNode(); - - for (JsonNode item : keyArray) { - result.add(partFromMldev(JsonSerializable.toJsonNode(item), toObject)); - } - Common.setValueByPath(toObject, new String[] {"parts"}, result); - } - - if (Common.getValueByPath(fromObject, new String[] {"role"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"role"}, - Common.getValueByPath(fromObject, new String[] {"role"})); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode schemaFromMldev(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - - if (Common.getValueByPath(fromObject, new String[] {"anyOf"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"anyOf"}, - Common.getValueByPath(fromObject, new String[] {"anyOf"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"default"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"default"}, - Common.getValueByPath(fromObject, new String[] {"default"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"description"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"description"}, - Common.getValueByPath(fromObject, new String[] {"description"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"enum"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"enum"}, - Common.getValueByPath(fromObject, new String[] {"enum"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"example"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"example"}, - Common.getValueByPath(fromObject, new String[] {"example"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"format"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"format"}, - Common.getValueByPath(fromObject, new String[] {"format"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"items"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"items"}, - Common.getValueByPath(fromObject, new String[] {"items"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"maxItems"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"maxItems"}, - Common.getValueByPath(fromObject, new String[] {"maxItems"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"maxLength"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"maxLength"}, - Common.getValueByPath(fromObject, new String[] {"maxLength"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"maxProperties"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"maxProperties"}, - Common.getValueByPath(fromObject, new String[] {"maxProperties"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"maximum"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"maximum"}, - Common.getValueByPath(fromObject, new String[] {"maximum"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"minItems"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"minItems"}, - Common.getValueByPath(fromObject, new String[] {"minItems"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"minLength"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"minLength"}, - Common.getValueByPath(fromObject, new String[] {"minLength"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"minProperties"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"minProperties"}, - Common.getValueByPath(fromObject, new String[] {"minProperties"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"minimum"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"minimum"}, - Common.getValueByPath(fromObject, new String[] {"minimum"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"nullable"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"nullable"}, - Common.getValueByPath(fromObject, new String[] {"nullable"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"pattern"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"pattern"}, - Common.getValueByPath(fromObject, new String[] {"pattern"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"properties"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"properties"}, - Common.getValueByPath(fromObject, new String[] {"properties"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"propertyOrdering"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"propertyOrdering"}, - Common.getValueByPath(fromObject, new String[] {"propertyOrdering"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"required"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"required"}, - Common.getValueByPath(fromObject, new String[] {"required"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"title"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"title"}, - Common.getValueByPath(fromObject, new String[] {"title"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"type"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"type"}, - Common.getValueByPath(fromObject, new String[] {"type"})); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode modelSelectionConfigFromMldev(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode safetySettingFromMldev(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - - if (Common.getValueByPath(fromObject, new String[] {"category"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"category"}, - Common.getValueByPath(fromObject, new String[] {"category"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"threshold"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"threshold"}, - Common.getValueByPath(fromObject, new String[] {"threshold"})); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode functionDeclarationFromMldev(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"behavior"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"behavior"}, - Common.getValueByPath(fromObject, new String[] {"behavior"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"description"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"description"}, - Common.getValueByPath(fromObject, new String[] {"description"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"name"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"name"}, - Common.getValueByPath(fromObject, new String[] {"name"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"parameters"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"parameters"}, - Common.getValueByPath(fromObject, new String[] {"parameters"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"parametersJsonSchema"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"parametersJsonSchema"}, - Common.getValueByPath(fromObject, new String[] {"parametersJsonSchema"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"response"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"response"}, - Common.getValueByPath(fromObject, new String[] {"response"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"responseJsonSchema"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"responseJsonSchema"}, - Common.getValueByPath(fromObject, new String[] {"responseJsonSchema"})); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode intervalFromMldev(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"startTime"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"startTime"}, - Common.getValueByPath(fromObject, new String[] {"startTime"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"endTime"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"endTime"}, - Common.getValueByPath(fromObject, new String[] {"endTime"})); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode googleSearchFromMldev(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"timeRangeFilter"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"timeRangeFilter"}, - intervalFromMldev( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"timeRangeFilter"})), - toObject)); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode dynamicRetrievalConfigFromMldev(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"mode"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"mode"}, - Common.getValueByPath(fromObject, new String[] {"mode"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"dynamicThreshold"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"dynamicThreshold"}, - Common.getValueByPath(fromObject, new String[] {"dynamicThreshold"})); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode googleSearchRetrievalFromMldev(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"dynamicRetrievalConfig"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"dynamicRetrievalConfig"}, - dynamicRetrievalConfigFromMldev( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"dynamicRetrievalConfig"})), - toObject)); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode enterpriseWebSearchFromMldev(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode apiKeyConfigFromMldev(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode authConfigFromMldev(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - - if (Common.getValueByPath(fromObject, new String[] {"authType"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"authType"}, - Common.getValueByPath(fromObject, new String[] {"authType"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"googleServiceAccountConfig"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"googleServiceAccountConfig"}, - Common.getValueByPath(fromObject, new String[] {"googleServiceAccountConfig"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"httpBasicAuthConfig"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"httpBasicAuthConfig"}, - Common.getValueByPath(fromObject, new String[] {"httpBasicAuthConfig"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"oauthConfig"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"oauthConfig"}, - Common.getValueByPath(fromObject, new String[] {"oauthConfig"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"oidcConfig"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"oidcConfig"}, - Common.getValueByPath(fromObject, new String[] {"oidcConfig"})); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode googleMapsFromMldev(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode urlContextFromMldev(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode toolFromMldev(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"functionDeclarations"}) != null) { - ArrayNode keyArray = - (ArrayNode) Common.getValueByPath(fromObject, new String[] {"functionDeclarations"}); - ObjectMapper objectMapper = new ObjectMapper(); - ArrayNode result = objectMapper.createArrayNode(); - - for (JsonNode item : keyArray) { - result.add(functionDeclarationFromMldev(JsonSerializable.toJsonNode(item), toObject)); - } - Common.setValueByPath(toObject, new String[] {"functionDeclarations"}, result); - } - - if (Common.getValueByPath(fromObject, new String[] {"googleSearch"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"googleSearch"}, - googleSearchFromMldev( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"googleSearch"})), - toObject)); - } - - if (Common.getValueByPath(fromObject, new String[] {"googleSearchRetrieval"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"googleSearchRetrieval"}, - googleSearchRetrievalFromMldev( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"googleSearchRetrieval"})), - toObject)); - } - - if (Common.getValueByPath(fromObject, new String[] {"urlContext"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"urlContext"}, - urlContextFromMldev( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"urlContext"})), - toObject)); - } - - if (Common.getValueByPath(fromObject, new String[] {"codeExecution"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"codeExecution"}, - Common.getValueByPath(fromObject, new String[] {"codeExecution"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"computerUse"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"computerUse"}, - Common.getValueByPath(fromObject, new String[] {"computerUse"})); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode functionCallingConfigFromMldev(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"mode"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"mode"}, - Common.getValueByPath(fromObject, new String[] {"mode"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"allowedFunctionNames"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"allowedFunctionNames"}, - Common.getValueByPath(fromObject, new String[] {"allowedFunctionNames"})); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode latLngFromMldev(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"latitude"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"latitude"}, - Common.getValueByPath(fromObject, new String[] {"latitude"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"longitude"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"longitude"}, - Common.getValueByPath(fromObject, new String[] {"longitude"})); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode retrievalConfigFromMldev(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"latLng"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"latLng"}, - latLngFromMldev( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"latLng"})), - toObject)); - } - - if (Common.getValueByPath(fromObject, new String[] {"languageCode"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"languageCode"}, - Common.getValueByPath(fromObject, new String[] {"languageCode"})); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode toolConfigFromMldev(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"functionCallingConfig"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"functionCallingConfig"}, - functionCallingConfigFromMldev( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"functionCallingConfig"})), - toObject)); - } - - if (Common.getValueByPath(fromObject, new String[] {"retrievalConfig"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"retrievalConfig"}, - retrievalConfigFromMldev( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"retrievalConfig"})), - toObject)); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode prebuiltVoiceConfigFromMldev(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"voiceName"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"voiceName"}, - Common.getValueByPath(fromObject, new String[] {"voiceName"})); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode voiceConfigFromMldev(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"prebuiltVoiceConfig"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"prebuiltVoiceConfig"}, - prebuiltVoiceConfigFromMldev( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"prebuiltVoiceConfig"})), - toObject)); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode speakerVoiceConfigFromMldev(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"speaker"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"speaker"}, - Common.getValueByPath(fromObject, new String[] {"speaker"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"voiceConfig"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"voiceConfig"}, - voiceConfigFromMldev( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"voiceConfig"})), - toObject)); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode multiSpeakerVoiceConfigFromMldev(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"speakerVoiceConfigs"}) != null) { - ArrayNode keyArray = - (ArrayNode) Common.getValueByPath(fromObject, new String[] {"speakerVoiceConfigs"}); - ObjectMapper objectMapper = new ObjectMapper(); - ArrayNode result = objectMapper.createArrayNode(); - - for (JsonNode item : keyArray) { - result.add(speakerVoiceConfigFromMldev(JsonSerializable.toJsonNode(item), toObject)); - } - Common.setValueByPath(toObject, new String[] {"speakerVoiceConfigs"}, result); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode speechConfigFromMldev(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"voiceConfig"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"voiceConfig"}, - voiceConfigFromMldev( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"voiceConfig"})), - toObject)); - } - - if (Common.getValueByPath(fromObject, new String[] {"multiSpeakerVoiceConfig"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"multiSpeakerVoiceConfig"}, - multiSpeakerVoiceConfigFromMldev( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"multiSpeakerVoiceConfig"})), - toObject)); - } - - if (Common.getValueByPath(fromObject, new String[] {"languageCode"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"languageCode"}, - Common.getValueByPath(fromObject, new String[] {"languageCode"})); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode thinkingConfigFromMldev(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"includeThoughts"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"includeThoughts"}, - Common.getValueByPath(fromObject, new String[] {"includeThoughts"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"thinkingBudget"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"thinkingBudget"}, - Common.getValueByPath(fromObject, new String[] {"thinkingBudget"})); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode generateContentConfigFromMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - - if (Common.getValueByPath(parentObject, new String[] {"systemInstruction"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"systemInstruction"}, - contentFromMldev( - JsonSerializable.toJsonNode( - Transformers.tContent( - Common.getValueByPath(parentObject, new String[] {"systemInstruction"}))), - toObject)); - } - - if (Common.getValueByPath(fromObject, new String[] {"temperature"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"temperature"}, - Common.getValueByPath(fromObject, new String[] {"temperature"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"topP"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"topP"}, - Common.getValueByPath(fromObject, new String[] {"topP"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"topK"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"topK"}, - Common.getValueByPath(fromObject, new String[] {"topK"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"candidateCount"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"candidateCount"}, - Common.getValueByPath(fromObject, new String[] {"candidateCount"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"maxOutputTokens"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"maxOutputTokens"}, - Common.getValueByPath(fromObject, new String[] {"maxOutputTokens"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"stopSequences"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"stopSequences"}, - Common.getValueByPath(fromObject, new String[] {"stopSequences"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"responseLogprobs"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"responseLogprobs"}, - Common.getValueByPath(fromObject, new String[] {"responseLogprobs"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"logprobs"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"logprobs"}, - Common.getValueByPath(fromObject, new String[] {"logprobs"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"presencePenalty"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"presencePenalty"}, - Common.getValueByPath(fromObject, new String[] {"presencePenalty"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"frequencyPenalty"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"frequencyPenalty"}, - Common.getValueByPath(fromObject, new String[] {"frequencyPenalty"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"seed"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"seed"}, - Common.getValueByPath(fromObject, new String[] {"seed"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"responseMimeType"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"responseMimeType"}, - Common.getValueByPath(fromObject, new String[] {"responseMimeType"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"responseSchema"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"responseSchema"}, - schemaFromMldev( - JsonSerializable.toJsonNode( - Transformers.tSchema( - Common.getValueByPath(fromObject, new String[] {"responseSchema"}))), - toObject)); - } - - if (Common.getValueByPath(fromObject, new String[] {"responseJsonSchema"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"responseJsonSchema"}, - Common.getValueByPath(fromObject, new String[] {"responseJsonSchema"})); - } - - if (Common.getValueByPath(parentObject, new String[] {"safetySettings"}) != null) { - ArrayNode keyArray = - (ArrayNode) Common.getValueByPath(parentObject, new String[] {"safetySettings"}); - ObjectMapper objectMapper = new ObjectMapper(); - ArrayNode result = objectMapper.createArrayNode(); - - for (JsonNode item : keyArray) { - result.add(safetySettingFromMldev(JsonSerializable.toJsonNode(item), toObject)); - } - Common.setValueByPath(toObject, new String[] {"safetySettings"}, result); - } - - if (Common.getValueByPath(parentObject, new String[] {"tools"}) != null) { - ArrayNode keyArray = - (ArrayNode) - Transformers.tTools(Common.getValueByPath(parentObject, new String[] {"tools"})); - ObjectMapper objectMapper = new ObjectMapper(); - ArrayNode result = objectMapper.createArrayNode(); - - for (JsonNode item : keyArray) { - result.add(toolFromMldev(JsonSerializable.toJsonNode(Transformers.tTool(item)), toObject)); - } - Common.setValueByPath(toObject, new String[] {"tools"}, result); - } - - if (Common.getValueByPath(parentObject, new String[] {"toolConfig"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"toolConfig"}, - toolConfigFromMldev( - JsonSerializable.toJsonNode( - Common.getValueByPath(parentObject, new String[] {"toolConfig"})), - toObject)); - } - - if (Common.getValueByPath(parentObject, new String[] {"cachedContent"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"cachedContent"}, - Transformers.tCachedContentName( - this.apiClient, Common.getValueByPath(parentObject, new String[] {"cachedContent"}))); - } - - if (Common.getValueByPath(fromObject, new String[] {"responseModalities"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"responseModalities"}, - Common.getValueByPath(fromObject, new String[] {"responseModalities"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"mediaResolution"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"mediaResolution"}, - Common.getValueByPath(fromObject, new String[] {"mediaResolution"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"speechConfig"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"speechConfig"}, - speechConfigFromMldev( - JsonSerializable.toJsonNode( - Transformers.tSpeechConfig( - Common.getValueByPath(fromObject, new String[] {"speechConfig"}))), - toObject)); - } - - if (Common.getValueByPath(fromObject, new String[] {"thinkingConfig"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"thinkingConfig"}, - thinkingConfigFromMldev( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"thinkingConfig"})), - toObject)); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode inlinedRequestFromMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"request", "model"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"model"}, - Transformers.tModel( - this.apiClient, - Common.getValueByPath(fromObject, new String[] {"request", "model"}))); - } - - if (Common.getValueByPath(fromObject, new String[] {"request", "contents"}) != null) { - ArrayNode keyArray = - (ArrayNode) - Transformers.tContents( - Common.getValueByPath(fromObject, new String[] {"request", "contents"})); - ObjectMapper objectMapper = new ObjectMapper(); - ArrayNode result = objectMapper.createArrayNode(); - - for (JsonNode item : keyArray) { - result.add(contentFromMldev(JsonSerializable.toJsonNode(item), toObject)); - } - Common.setValueByPath(toObject, new String[] {"contents"}, result); - } - - if (Common.getValueByPath(fromObject, new String[] {"request", "generationConfig"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"config"}, - generateContentConfigFromMldev( - apiClient, - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"request", "generationConfig"})), - toObject)); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode batchJobSourceFromMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - - if (Common.getValueByPath(fromObject, new String[] {"fileName"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"fileName"}, - Common.getValueByPath(fromObject, new String[] {"fileName"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"requests", "requests"}) != null) { - ArrayNode keyArray = - (ArrayNode) Common.getValueByPath(fromObject, new String[] {"requests", "requests"}); - ObjectMapper objectMapper = new ObjectMapper(); - ArrayNode result = objectMapper.createArrayNode(); - - for (JsonNode item : keyArray) { - result.add(inlinedRequestFromMldev(apiClient, JsonSerializable.toJsonNode(item), toObject)); - } - Common.setValueByPath(toObject, new String[] {"inlinedRequests"}, result); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode citationMetadataFromMldev(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"citationSources"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"citations"}, - Common.getValueByPath(fromObject, new String[] {"citationSources"})); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode urlMetadataFromMldev(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"retrievedUrl"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"retrievedUrl"}, - Common.getValueByPath(fromObject, new String[] {"retrievedUrl"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"urlRetrievalStatus"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"urlRetrievalStatus"}, - Common.getValueByPath(fromObject, new String[] {"urlRetrievalStatus"})); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode urlContextMetadataFromMldev(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"urlMetadata"}) != null) { - ArrayNode keyArray = - (ArrayNode) Common.getValueByPath(fromObject, new String[] {"urlMetadata"}); - ObjectMapper objectMapper = new ObjectMapper(); - ArrayNode result = objectMapper.createArrayNode(); - - for (JsonNode item : keyArray) { - result.add(urlMetadataFromMldev(JsonSerializable.toJsonNode(item), toObject)); - } - Common.setValueByPath(toObject, new String[] {"urlMetadata"}, result); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode candidateFromMldev(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"content"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"content"}, - contentFromMldev( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"content"})), - toObject)); - } - - if (Common.getValueByPath(fromObject, new String[] {"citationMetadata"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"citationMetadata"}, - citationMetadataFromMldev( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"citationMetadata"})), - toObject)); - } - - if (Common.getValueByPath(fromObject, new String[] {"tokenCount"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"tokenCount"}, - Common.getValueByPath(fromObject, new String[] {"tokenCount"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"finishReason"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"finishReason"}, - Common.getValueByPath(fromObject, new String[] {"finishReason"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"urlContextMetadata"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"urlContextMetadata"}, - urlContextMetadataFromMldev( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"urlContextMetadata"})), - toObject)); - } - - if (Common.getValueByPath(fromObject, new String[] {"avgLogprobs"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"avgLogprobs"}, - Common.getValueByPath(fromObject, new String[] {"avgLogprobs"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"groundingMetadata"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"groundingMetadata"}, - Common.getValueByPath(fromObject, new String[] {"groundingMetadata"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"index"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"index"}, - Common.getValueByPath(fromObject, new String[] {"index"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"logprobsResult"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"logprobsResult"}, - Common.getValueByPath(fromObject, new String[] {"logprobsResult"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"safetyRatings"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"safetyRatings"}, - Common.getValueByPath(fromObject, new String[] {"safetyRatings"})); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode generateContentResponseFromMldev(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - - if (Common.getValueByPath(fromObject, new String[] {"candidates"}) != null) { - ArrayNode keyArray = - (ArrayNode) Common.getValueByPath(fromObject, new String[] {"candidates"}); - ObjectMapper objectMapper = new ObjectMapper(); - ArrayNode result = objectMapper.createArrayNode(); - - for (JsonNode item : keyArray) { - result.add(candidateFromMldev(JsonSerializable.toJsonNode(item), toObject)); - } - Common.setValueByPath(toObject, new String[] {"candidates"}, result); - } - - if (Common.getValueByPath(fromObject, new String[] {"modelVersion"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"modelVersion"}, - Common.getValueByPath(fromObject, new String[] {"modelVersion"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"promptFeedback"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"promptFeedback"}, - Common.getValueByPath(fromObject, new String[] {"promptFeedback"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"usageMetadata"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"usageMetadata"}, - Common.getValueByPath(fromObject, new String[] {"usageMetadata"})); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode inlinedResponseFromMldev(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"response"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"response"}, - generateContentResponseFromMldev( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"response"})), - toObject)); - } - - if (Common.getValueByPath(fromObject, new String[] {"error"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"error"}, - jobErrorFromMldev( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"error"})), - toObject)); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode batchJobDestinationFromMldev(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - - if (Common.getValueByPath(fromObject, new String[] {"responsesFile"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"fileName"}, - Common.getValueByPath(fromObject, new String[] {"responsesFile"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"inlinedResponses", "inlinedResponses"}) - != null) { - ArrayNode keyArray = - (ArrayNode) - Common.getValueByPath( - fromObject, new String[] {"inlinedResponses", "inlinedResponses"}); - ObjectMapper objectMapper = new ObjectMapper(); - ArrayNode result = objectMapper.createArrayNode(); - - for (JsonNode item : keyArray) { - result.add(inlinedResponseFromMldev(JsonSerializable.toJsonNode(item), toObject)); - } - Common.setValueByPath(toObject, new String[] {"inlinedResponses"}, result); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode batchJobFromMldev(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"name"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"name"}, - Common.getValueByPath(fromObject, new String[] {"name"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"metadata", "displayName"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"displayName"}, - Common.getValueByPath(fromObject, new String[] {"metadata", "displayName"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"metadata", "state"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"state"}, - Transformers.tJobState( - Common.getValueByPath(fromObject, new String[] {"metadata", "state"}))); - } - - if (Common.getValueByPath(fromObject, new String[] {"metadata", "createTime"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"createTime"}, - Common.getValueByPath(fromObject, new String[] {"metadata", "createTime"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"metadata", "endTime"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"endTime"}, - Common.getValueByPath(fromObject, new String[] {"metadata", "endTime"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"metadata", "updateTime"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"updateTime"}, - Common.getValueByPath(fromObject, new String[] {"metadata", "updateTime"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"metadata", "model"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"model"}, - Common.getValueByPath(fromObject, new String[] {"metadata", "model"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"metadata", "output"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"dest"}, - batchJobDestinationFromMldev( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"metadata", "output"})), - toObject)); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode listBatchJobsResponseFromMldev(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"nextPageToken"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"nextPageToken"}, - Common.getValueByPath(fromObject, new String[] {"nextPageToken"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"operations"}) != null) { - ArrayNode keyArray = - (ArrayNode) Common.getValueByPath(fromObject, new String[] {"operations"}); - ObjectMapper objectMapper = new ObjectMapper(); - ArrayNode result = objectMapper.createArrayNode(); - - for (JsonNode item : keyArray) { - result.add(batchJobFromMldev(JsonSerializable.toJsonNode(item), toObject)); - } - Common.setValueByPath(toObject, new String[] {"batchJobs"}, result); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode deleteResourceJobFromMldev(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"name"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"name"}, - Common.getValueByPath(fromObject, new String[] {"name"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"done"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"done"}, - Common.getValueByPath(fromObject, new String[] {"done"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"error"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"error"}, - jobErrorFromMldev( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"error"})), - toObject)); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode jobErrorFromVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"details"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"details"}, - Common.getValueByPath(fromObject, new String[] {"details"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"code"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"code"}, - Common.getValueByPath(fromObject, new String[] {"code"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"message"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"message"}, - Common.getValueByPath(fromObject, new String[] {"message"})); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode videoMetadataFromVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"fps"}) != null) { - Common.setValueByPath( - toObject, new String[] {"fps"}, Common.getValueByPath(fromObject, new String[] {"fps"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"endOffset"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"endOffset"}, - Common.getValueByPath(fromObject, new String[] {"endOffset"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"startOffset"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"startOffset"}, - Common.getValueByPath(fromObject, new String[] {"startOffset"})); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode blobFromVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"displayName"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"displayName"}, - Common.getValueByPath(fromObject, new String[] {"displayName"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"data"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"data"}, - Common.getValueByPath(fromObject, new String[] {"data"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"mimeType"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"mimeType"}, - Common.getValueByPath(fromObject, new String[] {"mimeType"})); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode fileDataFromVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"displayName"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"displayName"}, - Common.getValueByPath(fromObject, new String[] {"displayName"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"fileUri"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"fileUri"}, - Common.getValueByPath(fromObject, new String[] {"fileUri"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"mimeType"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"mimeType"}, - Common.getValueByPath(fromObject, new String[] {"mimeType"})); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode partFromVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"videoMetadata"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"videoMetadata"}, - videoMetadataFromVertex( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"videoMetadata"})), - toObject)); - } - - if (Common.getValueByPath(fromObject, new String[] {"thought"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"thought"}, - Common.getValueByPath(fromObject, new String[] {"thought"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"inlineData"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"inlineData"}, - blobFromVertex( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"inlineData"})), - toObject)); - } - - if (Common.getValueByPath(fromObject, new String[] {"fileData"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"fileData"}, - fileDataFromVertex( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"fileData"})), - toObject)); - } - - if (Common.getValueByPath(fromObject, new String[] {"thoughtSignature"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"thoughtSignature"}, - Common.getValueByPath(fromObject, new String[] {"thoughtSignature"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"codeExecutionResult"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"codeExecutionResult"}, - Common.getValueByPath(fromObject, new String[] {"codeExecutionResult"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"executableCode"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"executableCode"}, - Common.getValueByPath(fromObject, new String[] {"executableCode"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"functionCall"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"functionCall"}, - Common.getValueByPath(fromObject, new String[] {"functionCall"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"functionResponse"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"functionResponse"}, - Common.getValueByPath(fromObject, new String[] {"functionResponse"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"text"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"text"}, - Common.getValueByPath(fromObject, new String[] {"text"})); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode contentFromVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"parts"}) != null) { - ArrayNode keyArray = (ArrayNode) Common.getValueByPath(fromObject, new String[] {"parts"}); - ObjectMapper objectMapper = new ObjectMapper(); - ArrayNode result = objectMapper.createArrayNode(); - - for (JsonNode item : keyArray) { - result.add(partFromVertex(JsonSerializable.toJsonNode(item), toObject)); - } - Common.setValueByPath(toObject, new String[] {"parts"}, result); - } - - if (Common.getValueByPath(fromObject, new String[] {"role"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"role"}, - Common.getValueByPath(fromObject, new String[] {"role"})); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode schemaFromVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - - if (Common.getValueByPath(fromObject, new String[] {"anyOf"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"anyOf"}, - Common.getValueByPath(fromObject, new String[] {"anyOf"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"default"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"default"}, - Common.getValueByPath(fromObject, new String[] {"default"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"description"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"description"}, - Common.getValueByPath(fromObject, new String[] {"description"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"enum"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"enum"}, - Common.getValueByPath(fromObject, new String[] {"enum"})); + if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"config"}))) { + throw new IllegalArgumentException("config parameter is not supported in Vertex AI."); } - if (Common.getValueByPath(fromObject, new String[] {"example"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"example"}, - Common.getValueByPath(fromObject, new String[] {"example"})); - } + return toObject; + } + @ExcludeFromGeneratedCoverageReport + ObjectNode batchJobSourceToVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"format"}) != null) { Common.setValueByPath( toObject, - new String[] {"format"}, + new String[] {"instancesFormat"}, Common.getValueByPath(fromObject, new String[] {"format"})); } - if (Common.getValueByPath(fromObject, new String[] {"items"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"gcsUri"}) != null) { Common.setValueByPath( toObject, - new String[] {"items"}, - Common.getValueByPath(fromObject, new String[] {"items"})); + new String[] {"gcsSource", "uris"}, + Common.getValueByPath(fromObject, new String[] {"gcsUri"})); } - if (Common.getValueByPath(fromObject, new String[] {"maxItems"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"bigqueryUri"}) != null) { Common.setValueByPath( toObject, - new String[] {"maxItems"}, - Common.getValueByPath(fromObject, new String[] {"maxItems"})); + new String[] {"bigquerySource", "inputUri"}, + Common.getValueByPath(fromObject, new String[] {"bigqueryUri"})); } - if (Common.getValueByPath(fromObject, new String[] {"maxLength"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"maxLength"}, - Common.getValueByPath(fromObject, new String[] {"maxLength"})); + if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"fileName"}))) { + throw new IllegalArgumentException("fileName parameter is not supported in Vertex AI."); } - if (Common.getValueByPath(fromObject, new String[] {"maxProperties"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"maxProperties"}, - Common.getValueByPath(fromObject, new String[] {"maxProperties"})); + if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"inlinedRequests"}))) { + throw new IllegalArgumentException( + "inlinedRequests parameter is not supported in Vertex AI."); } - if (Common.getValueByPath(fromObject, new String[] {"maximum"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"maximum"}, - Common.getValueByPath(fromObject, new String[] {"maximum"})); + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode inlinedResponseToVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"response"}))) { + throw new IllegalArgumentException("response parameter is not supported in Vertex AI."); } - if (Common.getValueByPath(fromObject, new String[] {"minItems"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"minItems"}, - Common.getValueByPath(fromObject, new String[] {"minItems"})); + if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"error"}))) { + throw new IllegalArgumentException("error parameter is not supported in Vertex AI."); } - if (Common.getValueByPath(fromObject, new String[] {"minLength"}) != null) { + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode batchJobDestinationToVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"format"}) != null) { Common.setValueByPath( toObject, - new String[] {"minLength"}, - Common.getValueByPath(fromObject, new String[] {"minLength"})); + new String[] {"predictionsFormat"}, + Common.getValueByPath(fromObject, new String[] {"format"})); } - if (Common.getValueByPath(fromObject, new String[] {"minProperties"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"gcsUri"}) != null) { Common.setValueByPath( toObject, - new String[] {"minProperties"}, - Common.getValueByPath(fromObject, new String[] {"minProperties"})); + new String[] {"gcsDestination", "outputUriPrefix"}, + Common.getValueByPath(fromObject, new String[] {"gcsUri"})); } - if (Common.getValueByPath(fromObject, new String[] {"minimum"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"bigqueryUri"}) != null) { Common.setValueByPath( toObject, - new String[] {"minimum"}, - Common.getValueByPath(fromObject, new String[] {"minimum"})); + new String[] {"bigqueryDestination", "outputUri"}, + Common.getValueByPath(fromObject, new String[] {"bigqueryUri"})); } - if (Common.getValueByPath(fromObject, new String[] {"nullable"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"nullable"}, - Common.getValueByPath(fromObject, new String[] {"nullable"})); + if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"fileName"}))) { + throw new IllegalArgumentException("fileName parameter is not supported in Vertex AI."); } - if (Common.getValueByPath(fromObject, new String[] {"pattern"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"pattern"}, - Common.getValueByPath(fromObject, new String[] {"pattern"})); + if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"inlinedResponses"}))) { + throw new IllegalArgumentException( + "inlinedResponses parameter is not supported in Vertex AI."); } - if (Common.getValueByPath(fromObject, new String[] {"properties"}) != null) { + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode createBatchJobConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + + if (Common.getValueByPath(fromObject, new String[] {"displayName"}) != null) { Common.setValueByPath( - toObject, - new String[] {"properties"}, - Common.getValueByPath(fromObject, new String[] {"properties"})); + parentObject, + new String[] {"displayName"}, + Common.getValueByPath(fromObject, new String[] {"displayName"})); } - if (Common.getValueByPath(fromObject, new String[] {"propertyOrdering"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"dest"}) != null) { Common.setValueByPath( - toObject, - new String[] {"propertyOrdering"}, - Common.getValueByPath(fromObject, new String[] {"propertyOrdering"})); + parentObject, + new String[] {"outputConfig"}, + batchJobDestinationToVertex( + JsonSerializable.toJsonNode( + Transformers.tBatchJobDestination( + Common.getValueByPath(fromObject, new String[] {"dest"}))), + toObject)); } - if (Common.getValueByPath(fromObject, new String[] {"required"}) != null) { + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode createBatchJobParametersToVertex( + ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"model"}) != null) { Common.setValueByPath( toObject, - new String[] {"required"}, - Common.getValueByPath(fromObject, new String[] {"required"})); + new String[] {"model"}, + Transformers.tModel( + this.apiClient, Common.getValueByPath(fromObject, new String[] {"model"}))); } - if (Common.getValueByPath(fromObject, new String[] {"title"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"src"}) != null) { Common.setValueByPath( toObject, - new String[] {"title"}, - Common.getValueByPath(fromObject, new String[] {"title"})); + new String[] {"inputConfig"}, + batchJobSourceToVertex( + JsonSerializable.toJsonNode( + Transformers.tBatchJobSource( + Common.getValueByPath(fromObject, new String[] {"src"}))), + toObject)); } - if (Common.getValueByPath(fromObject, new String[] {"type"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"config"}) != null) { Common.setValueByPath( toObject, - new String[] {"type"}, - Common.getValueByPath(fromObject, new String[] {"type"})); + new String[] {"config"}, + createBatchJobConfigToVertex( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"config"})), + toObject)); } return toObject; } @ExcludeFromGeneratedCoverageReport - ObjectNode modelSelectionConfigFromVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode getBatchJobParametersToVertex( + ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"featureSelectionPreference"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"name"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"_url", "name"}, + Transformers.tBatchJobName( + this.apiClient, Common.getValueByPath(fromObject, new String[] {"name"}))); + } + + if (Common.getValueByPath(fromObject, new String[] {"config"}) != null) { Common.setValueByPath( toObject, - new String[] {"featureSelectionPreference"}, - Common.getValueByPath(fromObject, new String[] {"featureSelectionPreference"})); + new String[] {"config"}, + Common.getValueByPath(fromObject, new String[] {"config"})); } return toObject; } @ExcludeFromGeneratedCoverageReport - ObjectNode safetySettingFromVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode cancelBatchJobParametersToVertex( + ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"method"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"method"}, - Common.getValueByPath(fromObject, new String[] {"method"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"category"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"name"}) != null) { Common.setValueByPath( toObject, - new String[] {"category"}, - Common.getValueByPath(fromObject, new String[] {"category"})); + new String[] {"_url", "name"}, + Transformers.tBatchJobName( + this.apiClient, Common.getValueByPath(fromObject, new String[] {"name"}))); } - if (Common.getValueByPath(fromObject, new String[] {"threshold"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"config"}) != null) { Common.setValueByPath( toObject, - new String[] {"threshold"}, - Common.getValueByPath(fromObject, new String[] {"threshold"})); + new String[] {"config"}, + Common.getValueByPath(fromObject, new String[] {"config"})); } return toObject; } @ExcludeFromGeneratedCoverageReport - ObjectNode functionDeclarationFromVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode listBatchJobsConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"description"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"pageSize"}) != null) { Common.setValueByPath( - toObject, - new String[] {"description"}, - Common.getValueByPath(fromObject, new String[] {"description"})); + parentObject, + new String[] {"_query", "pageSize"}, + Common.getValueByPath(fromObject, new String[] {"pageSize"})); } - if (Common.getValueByPath(fromObject, new String[] {"name"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"pageToken"}) != null) { Common.setValueByPath( - toObject, - new String[] {"name"}, - Common.getValueByPath(fromObject, new String[] {"name"})); + parentObject, + new String[] {"_query", "pageToken"}, + Common.getValueByPath(fromObject, new String[] {"pageToken"})); } - if (Common.getValueByPath(fromObject, new String[] {"parameters"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"filter"}) != null) { Common.setValueByPath( - toObject, - new String[] {"parameters"}, - Common.getValueByPath(fromObject, new String[] {"parameters"})); + parentObject, + new String[] {"_query", "filter"}, + Common.getValueByPath(fromObject, new String[] {"filter"})); } - if (Common.getValueByPath(fromObject, new String[] {"parametersJsonSchema"}) != null) { + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode listBatchJobsParametersToVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"config"}) != null) { Common.setValueByPath( toObject, - new String[] {"parametersJsonSchema"}, - Common.getValueByPath(fromObject, new String[] {"parametersJsonSchema"})); + new String[] {"config"}, + listBatchJobsConfigToVertex( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"config"})), + toObject)); } - if (Common.getValueByPath(fromObject, new String[] {"response"}) != null) { + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode deleteBatchJobParametersToVertex( + ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"name"}) != null) { Common.setValueByPath( toObject, - new String[] {"response"}, - Common.getValueByPath(fromObject, new String[] {"response"})); + new String[] {"_url", "name"}, + Transformers.tBatchJobName( + this.apiClient, Common.getValueByPath(fromObject, new String[] {"name"}))); } - if (Common.getValueByPath(fromObject, new String[] {"responseJsonSchema"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"config"}) != null) { Common.setValueByPath( toObject, - new String[] {"responseJsonSchema"}, - Common.getValueByPath(fromObject, new String[] {"responseJsonSchema"})); + new String[] {"config"}, + Common.getValueByPath(fromObject, new String[] {"config"})); } return toObject; } @ExcludeFromGeneratedCoverageReport - ObjectNode intervalFromVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode videoMetadataFromMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"startTime"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"fps"}) != null) { + Common.setValueByPath( + toObject, new String[] {"fps"}, Common.getValueByPath(fromObject, new String[] {"fps"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"endOffset"}) != null) { Common.setValueByPath( toObject, - new String[] {"startTime"}, - Common.getValueByPath(fromObject, new String[] {"startTime"})); + new String[] {"endOffset"}, + Common.getValueByPath(fromObject, new String[] {"endOffset"})); } - if (Common.getValueByPath(fromObject, new String[] {"endTime"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"startOffset"}) != null) { Common.setValueByPath( toObject, - new String[] {"endTime"}, - Common.getValueByPath(fromObject, new String[] {"endTime"})); + new String[] {"startOffset"}, + Common.getValueByPath(fromObject, new String[] {"startOffset"})); } return toObject; } @ExcludeFromGeneratedCoverageReport - ObjectNode googleSearchFromVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode blobFromMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"timeRangeFilter"}) != null) { + + if (Common.getValueByPath(fromObject, new String[] {"data"}) != null) { Common.setValueByPath( toObject, - new String[] {"timeRangeFilter"}, - intervalFromVertex( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"timeRangeFilter"})), - toObject)); + new String[] {"data"}, + Common.getValueByPath(fromObject, new String[] {"data"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"mimeType"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"mimeType"}, + Common.getValueByPath(fromObject, new String[] {"mimeType"})); } return toObject; } @ExcludeFromGeneratedCoverageReport - ObjectNode dynamicRetrievalConfigFromVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode fileDataFromMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"mode"}) != null) { + + if (Common.getValueByPath(fromObject, new String[] {"fileUri"}) != null) { Common.setValueByPath( toObject, - new String[] {"mode"}, - Common.getValueByPath(fromObject, new String[] {"mode"})); + new String[] {"fileUri"}, + Common.getValueByPath(fromObject, new String[] {"fileUri"})); } - if (Common.getValueByPath(fromObject, new String[] {"dynamicThreshold"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"mimeType"}) != null) { Common.setValueByPath( toObject, - new String[] {"dynamicThreshold"}, - Common.getValueByPath(fromObject, new String[] {"dynamicThreshold"})); + new String[] {"mimeType"}, + Common.getValueByPath(fromObject, new String[] {"mimeType"})); } return toObject; } @ExcludeFromGeneratedCoverageReport - ObjectNode googleSearchRetrievalFromVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode partFromMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"dynamicRetrievalConfig"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"videoMetadata"}) != null) { Common.setValueByPath( toObject, - new String[] {"dynamicRetrievalConfig"}, - dynamicRetrievalConfigFromVertex( + new String[] {"videoMetadata"}, + videoMetadataFromMldev( JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"dynamicRetrievalConfig"})), + Common.getValueByPath(fromObject, new String[] {"videoMetadata"})), toObject)); } - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode enterpriseWebSearchFromVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode apiKeyConfigFromVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"apiKeyString"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"thought"}) != null) { Common.setValueByPath( toObject, - new String[] {"apiKeyString"}, - Common.getValueByPath(fromObject, new String[] {"apiKeyString"})); + new String[] {"thought"}, + Common.getValueByPath(fromObject, new String[] {"thought"})); } - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode authConfigFromVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"apiKeyConfig"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"inlineData"}) != null) { Common.setValueByPath( toObject, - new String[] {"apiKeyConfig"}, - apiKeyConfigFromVertex( + new String[] {"inlineData"}, + blobFromMldev( JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"apiKeyConfig"})), + Common.getValueByPath(fromObject, new String[] {"inlineData"})), toObject)); } - if (Common.getValueByPath(fromObject, new String[] {"authType"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"fileData"}) != null) { Common.setValueByPath( toObject, - new String[] {"authType"}, - Common.getValueByPath(fromObject, new String[] {"authType"})); + new String[] {"fileData"}, + fileDataFromMldev( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"fileData"})), + toObject)); } - if (Common.getValueByPath(fromObject, new String[] {"googleServiceAccountConfig"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"thoughtSignature"}) != null) { Common.setValueByPath( toObject, - new String[] {"googleServiceAccountConfig"}, - Common.getValueByPath(fromObject, new String[] {"googleServiceAccountConfig"})); + new String[] {"thoughtSignature"}, + Common.getValueByPath(fromObject, new String[] {"thoughtSignature"})); } - if (Common.getValueByPath(fromObject, new String[] {"httpBasicAuthConfig"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"codeExecutionResult"}) != null) { Common.setValueByPath( toObject, - new String[] {"httpBasicAuthConfig"}, - Common.getValueByPath(fromObject, new String[] {"httpBasicAuthConfig"})); + new String[] {"codeExecutionResult"}, + Common.getValueByPath(fromObject, new String[] {"codeExecutionResult"})); } - if (Common.getValueByPath(fromObject, new String[] {"oauthConfig"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"executableCode"}) != null) { Common.setValueByPath( toObject, - new String[] {"oauthConfig"}, - Common.getValueByPath(fromObject, new String[] {"oauthConfig"})); + new String[] {"executableCode"}, + Common.getValueByPath(fromObject, new String[] {"executableCode"})); } - if (Common.getValueByPath(fromObject, new String[] {"oidcConfig"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"functionCall"}) != null) { Common.setValueByPath( toObject, - new String[] {"oidcConfig"}, - Common.getValueByPath(fromObject, new String[] {"oidcConfig"})); + new String[] {"functionCall"}, + Common.getValueByPath(fromObject, new String[] {"functionCall"})); } - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode googleMapsFromVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"authConfig"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"functionResponse"}) != null) { Common.setValueByPath( toObject, - new String[] {"authConfig"}, - authConfigFromVertex( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"authConfig"})), - toObject)); + new String[] {"functionResponse"}, + Common.getValueByPath(fromObject, new String[] {"functionResponse"})); } - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode urlContextFromVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"text"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"text"}, + Common.getValueByPath(fromObject, new String[] {"text"})); + } return toObject; } @ExcludeFromGeneratedCoverageReport - ObjectNode toolFromVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode contentFromMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"functionDeclarations"}) != null) { - ArrayNode keyArray = - (ArrayNode) Common.getValueByPath(fromObject, new String[] {"functionDeclarations"}); + if (Common.getValueByPath(fromObject, new String[] {"parts"}) != null) { + ArrayNode keyArray = (ArrayNode) Common.getValueByPath(fromObject, new String[] {"parts"}); ObjectMapper objectMapper = new ObjectMapper(); ArrayNode result = objectMapper.createArrayNode(); for (JsonNode item : keyArray) { - result.add(functionDeclarationFromVertex(JsonSerializable.toJsonNode(item), toObject)); + result.add(partFromMldev(JsonSerializable.toJsonNode(item), toObject)); } - Common.setValueByPath(toObject, new String[] {"functionDeclarations"}, result); + Common.setValueByPath(toObject, new String[] {"parts"}, result); } - if (Common.getValueByPath(fromObject, new String[] {"retrieval"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"role"}) != null) { Common.setValueByPath( toObject, - new String[] {"retrieval"}, - Common.getValueByPath(fromObject, new String[] {"retrieval"})); + new String[] {"role"}, + Common.getValueByPath(fromObject, new String[] {"role"})); } - if (Common.getValueByPath(fromObject, new String[] {"googleSearch"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"googleSearch"}, - googleSearchFromVertex( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"googleSearch"})), - toObject)); - } + return toObject; + } - if (Common.getValueByPath(fromObject, new String[] {"googleSearchRetrieval"}) != null) { + @ExcludeFromGeneratedCoverageReport + ObjectNode citationMetadataFromMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"citationSources"}) != null) { Common.setValueByPath( toObject, - new String[] {"googleSearchRetrieval"}, - googleSearchRetrievalFromVertex( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"googleSearchRetrieval"})), - toObject)); + new String[] {"citations"}, + Common.getValueByPath(fromObject, new String[] {"citationSources"})); } - if (Common.getValueByPath(fromObject, new String[] {"enterpriseWebSearch"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"enterpriseWebSearch"}, - enterpriseWebSearchFromVertex( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"enterpriseWebSearch"})), - toObject)); - } + return toObject; + } - if (Common.getValueByPath(fromObject, new String[] {"googleMaps"}) != null) { + @ExcludeFromGeneratedCoverageReport + ObjectNode urlMetadataFromMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"retrievedUrl"}) != null) { Common.setValueByPath( toObject, - new String[] {"googleMaps"}, - googleMapsFromVertex( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"googleMaps"})), - toObject)); + new String[] {"retrievedUrl"}, + Common.getValueByPath(fromObject, new String[] {"retrievedUrl"})); } - if (Common.getValueByPath(fromObject, new String[] {"urlContext"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"urlRetrievalStatus"}) != null) { Common.setValueByPath( toObject, - new String[] {"urlContext"}, - urlContextFromVertex( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"urlContext"})), - toObject)); + new String[] {"urlRetrievalStatus"}, + Common.getValueByPath(fromObject, new String[] {"urlRetrievalStatus"})); } - if (Common.getValueByPath(fromObject, new String[] {"codeExecution"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"codeExecution"}, - Common.getValueByPath(fromObject, new String[] {"codeExecution"})); - } + return toObject; + } - if (Common.getValueByPath(fromObject, new String[] {"computerUse"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"computerUse"}, - Common.getValueByPath(fromObject, new String[] {"computerUse"})); + @ExcludeFromGeneratedCoverageReport + ObjectNode urlContextMetadataFromMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"urlMetadata"}) != null) { + ArrayNode keyArray = + (ArrayNode) Common.getValueByPath(fromObject, new String[] {"urlMetadata"}); + ObjectMapper objectMapper = new ObjectMapper(); + ArrayNode result = objectMapper.createArrayNode(); + + for (JsonNode item : keyArray) { + result.add(urlMetadataFromMldev(JsonSerializable.toJsonNode(item), toObject)); + } + Common.setValueByPath(toObject, new String[] {"urlMetadata"}, result); } return toObject; } @ExcludeFromGeneratedCoverageReport - ObjectNode functionCallingConfigFromVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode candidateFromMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"mode"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"content"}) != null) { Common.setValueByPath( toObject, - new String[] {"mode"}, - Common.getValueByPath(fromObject, new String[] {"mode"})); + new String[] {"content"}, + contentFromMldev( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"content"})), + toObject)); } - if (Common.getValueByPath(fromObject, new String[] {"allowedFunctionNames"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"citationMetadata"}) != null) { Common.setValueByPath( toObject, - new String[] {"allowedFunctionNames"}, - Common.getValueByPath(fromObject, new String[] {"allowedFunctionNames"})); + new String[] {"citationMetadata"}, + citationMetadataFromMldev( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"citationMetadata"})), + toObject)); } - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode latLngFromVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"latitude"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"tokenCount"}) != null) { Common.setValueByPath( toObject, - new String[] {"latitude"}, - Common.getValueByPath(fromObject, new String[] {"latitude"})); + new String[] {"tokenCount"}, + Common.getValueByPath(fromObject, new String[] {"tokenCount"})); } - if (Common.getValueByPath(fromObject, new String[] {"longitude"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"finishReason"}) != null) { Common.setValueByPath( toObject, - new String[] {"longitude"}, - Common.getValueByPath(fromObject, new String[] {"longitude"})); + new String[] {"finishReason"}, + Common.getValueByPath(fromObject, new String[] {"finishReason"})); } - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode retrievalConfigFromVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"latLng"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"urlContextMetadata"}) != null) { Common.setValueByPath( toObject, - new String[] {"latLng"}, - latLngFromVertex( + new String[] {"urlContextMetadata"}, + urlContextMetadataFromMldev( JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"latLng"})), + Common.getValueByPath(fromObject, new String[] {"urlContextMetadata"})), toObject)); } - if (Common.getValueByPath(fromObject, new String[] {"languageCode"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"avgLogprobs"}) != null) { Common.setValueByPath( toObject, - new String[] {"languageCode"}, - Common.getValueByPath(fromObject, new String[] {"languageCode"})); + new String[] {"avgLogprobs"}, + Common.getValueByPath(fromObject, new String[] {"avgLogprobs"})); } - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode toolConfigFromVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"functionCallingConfig"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"groundingMetadata"}) != null) { Common.setValueByPath( toObject, - new String[] {"functionCallingConfig"}, - functionCallingConfigFromVertex( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"functionCallingConfig"})), - toObject)); + new String[] {"groundingMetadata"}, + Common.getValueByPath(fromObject, new String[] {"groundingMetadata"})); } - if (Common.getValueByPath(fromObject, new String[] {"retrievalConfig"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"index"}) != null) { Common.setValueByPath( toObject, - new String[] {"retrievalConfig"}, - retrievalConfigFromVertex( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"retrievalConfig"})), - toObject)); + new String[] {"index"}, + Common.getValueByPath(fromObject, new String[] {"index"})); } - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode prebuiltVoiceConfigFromVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"voiceName"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"logprobsResult"}) != null) { Common.setValueByPath( toObject, - new String[] {"voiceName"}, - Common.getValueByPath(fromObject, new String[] {"voiceName"})); + new String[] {"logprobsResult"}, + Common.getValueByPath(fromObject, new String[] {"logprobsResult"})); } - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode voiceConfigFromVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"prebuiltVoiceConfig"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"safetyRatings"}) != null) { Common.setValueByPath( toObject, - new String[] {"prebuiltVoiceConfig"}, - prebuiltVoiceConfigFromVertex( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"prebuiltVoiceConfig"})), - toObject)); + new String[] {"safetyRatings"}, + Common.getValueByPath(fromObject, new String[] {"safetyRatings"})); } return toObject; } @ExcludeFromGeneratedCoverageReport - ObjectNode speakerVoiceConfigFromVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode generateContentResponseFromMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - return toObject; - } + if (Common.getValueByPath(fromObject, new String[] {"candidates"}) != null) { + ArrayNode keyArray = + (ArrayNode) Common.getValueByPath(fromObject, new String[] {"candidates"}); + ObjectMapper objectMapper = new ObjectMapper(); + ArrayNode result = objectMapper.createArrayNode(); - @ExcludeFromGeneratedCoverageReport - ObjectNode multiSpeakerVoiceConfigFromVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + for (JsonNode item : keyArray) { + result.add(candidateFromMldev(JsonSerializable.toJsonNode(item), toObject)); + } + Common.setValueByPath(toObject, new String[] {"candidates"}, result); + } - return toObject; - } + if (Common.getValueByPath(fromObject, new String[] {"modelVersion"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"modelVersion"}, + Common.getValueByPath(fromObject, new String[] {"modelVersion"})); + } - @ExcludeFromGeneratedCoverageReport - ObjectNode speechConfigFromVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"voiceConfig"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"promptFeedback"}) != null) { Common.setValueByPath( toObject, - new String[] {"voiceConfig"}, - voiceConfigFromVertex( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"voiceConfig"})), - toObject)); + new String[] {"promptFeedback"}, + Common.getValueByPath(fromObject, new String[] {"promptFeedback"})); } - if (Common.getValueByPath(fromObject, new String[] {"languageCode"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"usageMetadata"}) != null) { Common.setValueByPath( toObject, - new String[] {"languageCode"}, - Common.getValueByPath(fromObject, new String[] {"languageCode"})); + new String[] {"usageMetadata"}, + Common.getValueByPath(fromObject, new String[] {"usageMetadata"})); } return toObject; } @ExcludeFromGeneratedCoverageReport - ObjectNode thinkingConfigFromVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode jobErrorFromMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"includeThoughts"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"details"}) != null) { Common.setValueByPath( toObject, - new String[] {"includeThoughts"}, - Common.getValueByPath(fromObject, new String[] {"includeThoughts"})); + new String[] {"details"}, + Common.getValueByPath(fromObject, new String[] {"details"})); } - if (Common.getValueByPath(fromObject, new String[] {"thinkingBudget"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"code"}) != null) { Common.setValueByPath( toObject, - new String[] {"thinkingBudget"}, - Common.getValueByPath(fromObject, new String[] {"thinkingBudget"})); + new String[] {"code"}, + Common.getValueByPath(fromObject, new String[] {"code"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"message"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"message"}, + Common.getValueByPath(fromObject, new String[] {"message"})); } return toObject; } @ExcludeFromGeneratedCoverageReport - ObjectNode generateContentConfigFromVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode inlinedResponseFromMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - - if (Common.getValueByPath(parentObject, new String[] {"systemInstruction"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"response"}) != null) { Common.setValueByPath( toObject, - new String[] {"systemInstruction"}, - contentFromVertex( + new String[] {"response"}, + generateContentResponseFromMldev( JsonSerializable.toJsonNode( - Transformers.tContent( - Common.getValueByPath(parentObject, new String[] {"systemInstruction"}))), + Common.getValueByPath(fromObject, new String[] {"response"})), toObject)); } - if (Common.getValueByPath(fromObject, new String[] {"temperature"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"temperature"}, - Common.getValueByPath(fromObject, new String[] {"temperature"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"topP"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"error"}) != null) { Common.setValueByPath( toObject, - new String[] {"topP"}, - Common.getValueByPath(fromObject, new String[] {"topP"})); + new String[] {"error"}, + jobErrorFromMldev( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"error"})), + toObject)); } - if (Common.getValueByPath(fromObject, new String[] {"topK"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"topK"}, - Common.getValueByPath(fromObject, new String[] {"topK"})); - } + return toObject; + } - if (Common.getValueByPath(fromObject, new String[] {"candidateCount"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"candidateCount"}, - Common.getValueByPath(fromObject, new String[] {"candidateCount"})); - } + @ExcludeFromGeneratedCoverageReport + ObjectNode batchJobDestinationFromMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"maxOutputTokens"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"responsesFile"}) != null) { Common.setValueByPath( toObject, - new String[] {"maxOutputTokens"}, - Common.getValueByPath(fromObject, new String[] {"maxOutputTokens"})); + new String[] {"fileName"}, + Common.getValueByPath(fromObject, new String[] {"responsesFile"})); } - if (Common.getValueByPath(fromObject, new String[] {"stopSequences"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"stopSequences"}, - Common.getValueByPath(fromObject, new String[] {"stopSequences"})); - } + if (Common.getValueByPath(fromObject, new String[] {"inlinedResponses", "inlinedResponses"}) + != null) { + ArrayNode keyArray = + (ArrayNode) + Common.getValueByPath( + fromObject, new String[] {"inlinedResponses", "inlinedResponses"}); + ObjectMapper objectMapper = new ObjectMapper(); + ArrayNode result = objectMapper.createArrayNode(); - if (Common.getValueByPath(fromObject, new String[] {"responseLogprobs"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"responseLogprobs"}, - Common.getValueByPath(fromObject, new String[] {"responseLogprobs"})); + for (JsonNode item : keyArray) { + result.add(inlinedResponseFromMldev(JsonSerializable.toJsonNode(item), toObject)); + } + Common.setValueByPath(toObject, new String[] {"inlinedResponses"}, result); } - if (Common.getValueByPath(fromObject, new String[] {"logprobs"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"logprobs"}, - Common.getValueByPath(fromObject, new String[] {"logprobs"})); - } + return toObject; + } - if (Common.getValueByPath(fromObject, new String[] {"presencePenalty"}) != null) { + @ExcludeFromGeneratedCoverageReport + ObjectNode batchJobFromMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"name"}) != null) { Common.setValueByPath( toObject, - new String[] {"presencePenalty"}, - Common.getValueByPath(fromObject, new String[] {"presencePenalty"})); + new String[] {"name"}, + Common.getValueByPath(fromObject, new String[] {"name"})); } - if (Common.getValueByPath(fromObject, new String[] {"frequencyPenalty"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"metadata", "displayName"}) != null) { Common.setValueByPath( toObject, - new String[] {"frequencyPenalty"}, - Common.getValueByPath(fromObject, new String[] {"frequencyPenalty"})); + new String[] {"displayName"}, + Common.getValueByPath(fromObject, new String[] {"metadata", "displayName"})); } - if (Common.getValueByPath(fromObject, new String[] {"seed"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"metadata", "state"}) != null) { Common.setValueByPath( toObject, - new String[] {"seed"}, - Common.getValueByPath(fromObject, new String[] {"seed"})); + new String[] {"state"}, + Transformers.tJobState( + Common.getValueByPath(fromObject, new String[] {"metadata", "state"}))); } - if (Common.getValueByPath(fromObject, new String[] {"responseMimeType"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"metadata", "createTime"}) != null) { Common.setValueByPath( toObject, - new String[] {"responseMimeType"}, - Common.getValueByPath(fromObject, new String[] {"responseMimeType"})); + new String[] {"createTime"}, + Common.getValueByPath(fromObject, new String[] {"metadata", "createTime"})); } - if (Common.getValueByPath(fromObject, new String[] {"responseSchema"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"metadata", "endTime"}) != null) { Common.setValueByPath( toObject, - new String[] {"responseSchema"}, - schemaFromVertex( - JsonSerializable.toJsonNode( - Transformers.tSchema( - Common.getValueByPath(fromObject, new String[] {"responseSchema"}))), - toObject)); + new String[] {"endTime"}, + Common.getValueByPath(fromObject, new String[] {"metadata", "endTime"})); } - if (Common.getValueByPath(fromObject, new String[] {"responseJsonSchema"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"metadata", "updateTime"}) != null) { Common.setValueByPath( toObject, - new String[] {"responseJsonSchema"}, - Common.getValueByPath(fromObject, new String[] {"responseJsonSchema"})); + new String[] {"updateTime"}, + Common.getValueByPath(fromObject, new String[] {"metadata", "updateTime"})); } - if (Common.getValueByPath(fromObject, new String[] {"routingConfig"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"metadata", "model"}) != null) { Common.setValueByPath( toObject, - new String[] {"routingConfig"}, - Common.getValueByPath(fromObject, new String[] {"routingConfig"})); + new String[] {"model"}, + Common.getValueByPath(fromObject, new String[] {"metadata", "model"})); } - if (Common.getValueByPath(fromObject, new String[] {"modelConfig"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"metadata", "output"}) != null) { Common.setValueByPath( toObject, - new String[] {"modelSelectionConfig"}, - modelSelectionConfigFromVertex( + new String[] {"dest"}, + batchJobDestinationFromMldev( JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"modelConfig"})), + Common.getValueByPath(fromObject, new String[] {"metadata", "output"})), toObject)); } - if (Common.getValueByPath(parentObject, new String[] {"safetySettings"}) != null) { - ArrayNode keyArray = - (ArrayNode) Common.getValueByPath(parentObject, new String[] {"safetySettings"}); - ObjectMapper objectMapper = new ObjectMapper(); - ArrayNode result = objectMapper.createArrayNode(); + return toObject; + } - for (JsonNode item : keyArray) { - result.add(safetySettingFromVertex(JsonSerializable.toJsonNode(item), toObject)); - } - Common.setValueByPath(toObject, new String[] {"safetySettings"}, result); + @ExcludeFromGeneratedCoverageReport + ObjectNode listBatchJobsResponseFromMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"nextPageToken"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"nextPageToken"}, + Common.getValueByPath(fromObject, new String[] {"nextPageToken"})); } - if (Common.getValueByPath(parentObject, new String[] {"tools"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"operations"}) != null) { ArrayNode keyArray = - (ArrayNode) - Transformers.tTools(Common.getValueByPath(parentObject, new String[] {"tools"})); + (ArrayNode) Common.getValueByPath(fromObject, new String[] {"operations"}); ObjectMapper objectMapper = new ObjectMapper(); ArrayNode result = objectMapper.createArrayNode(); for (JsonNode item : keyArray) { - result.add(toolFromVertex(JsonSerializable.toJsonNode(Transformers.tTool(item)), toObject)); + result.add(batchJobFromMldev(JsonSerializable.toJsonNode(item), toObject)); } - Common.setValueByPath(toObject, new String[] {"tools"}, result); + Common.setValueByPath(toObject, new String[] {"batchJobs"}, result); } - if (Common.getValueByPath(parentObject, new String[] {"toolConfig"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"toolConfig"}, - toolConfigFromVertex( - JsonSerializable.toJsonNode( - Common.getValueByPath(parentObject, new String[] {"toolConfig"})), - toObject)); - } + return toObject; + } - if (Common.getValueByPath(parentObject, new String[] {"labels"}) != null) { + @ExcludeFromGeneratedCoverageReport + ObjectNode deleteResourceJobFromMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"name"}) != null) { Common.setValueByPath( toObject, - new String[] {"labels"}, - Common.getValueByPath(parentObject, new String[] {"labels"})); + new String[] {"name"}, + Common.getValueByPath(fromObject, new String[] {"name"})); } - if (Common.getValueByPath(parentObject, new String[] {"cachedContent"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"done"}) != null) { Common.setValueByPath( toObject, - new String[] {"cachedContent"}, - Transformers.tCachedContentName( - this.apiClient, Common.getValueByPath(parentObject, new String[] {"cachedContent"}))); + new String[] {"done"}, + Common.getValueByPath(fromObject, new String[] {"done"})); } - if (Common.getValueByPath(fromObject, new String[] {"responseModalities"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"error"}) != null) { Common.setValueByPath( toObject, - new String[] {"responseModalities"}, - Common.getValueByPath(fromObject, new String[] {"responseModalities"})); + new String[] {"error"}, + jobErrorFromMldev( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"error"})), + toObject)); } - if (Common.getValueByPath(fromObject, new String[] {"mediaResolution"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"mediaResolution"}, - Common.getValueByPath(fromObject, new String[] {"mediaResolution"})); - } + return toObject; + } - if (Common.getValueByPath(fromObject, new String[] {"speechConfig"}) != null) { + @ExcludeFromGeneratedCoverageReport + ObjectNode jobErrorFromVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"details"}) != null) { Common.setValueByPath( toObject, - new String[] {"speechConfig"}, - speechConfigFromVertex( - JsonSerializable.toJsonNode( - Transformers.tSpeechConfig( - Common.getValueByPath(fromObject, new String[] {"speechConfig"}))), - toObject)); + new String[] {"details"}, + Common.getValueByPath(fromObject, new String[] {"details"})); } - if (Common.getValueByPath(fromObject, new String[] {"audioTimestamp"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"code"}) != null) { Common.setValueByPath( toObject, - new String[] {"audioTimestamp"}, - Common.getValueByPath(fromObject, new String[] {"audioTimestamp"})); + new String[] {"code"}, + Common.getValueByPath(fromObject, new String[] {"code"})); } - if (Common.getValueByPath(fromObject, new String[] {"thinkingConfig"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"message"}) != null) { Common.setValueByPath( toObject, - new String[] {"thinkingConfig"}, - thinkingConfigFromVertex( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"thinkingConfig"})), - toObject)); + new String[] {"message"}, + Common.getValueByPath(fromObject, new String[] {"message"})); } return toObject; } @ExcludeFromGeneratedCoverageReport - ObjectNode inlinedRequestFromVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode batchJobSourceFromVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode videoMetadataFromVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"instancesFormat"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"fps"}) != null) { Common.setValueByPath( - toObject, - new String[] {"format"}, - Common.getValueByPath(fromObject, new String[] {"instancesFormat"})); + toObject, new String[] {"fps"}, Common.getValueByPath(fromObject, new String[] {"fps"})); } - if (Common.getValueByPath(fromObject, new String[] {"gcsSource", "uris"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"endOffset"}) != null) { Common.setValueByPath( toObject, - new String[] {"gcsUri"}, - Common.getValueByPath(fromObject, new String[] {"gcsSource", "uris"})); + new String[] {"endOffset"}, + Common.getValueByPath(fromObject, new String[] {"endOffset"})); } - if (Common.getValueByPath(fromObject, new String[] {"bigquerySource", "inputUri"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"startOffset"}) != null) { Common.setValueByPath( toObject, - new String[] {"bigqueryUri"}, - Common.getValueByPath(fromObject, new String[] {"bigquerySource", "inputUri"})); + new String[] {"startOffset"}, + Common.getValueByPath(fromObject, new String[] {"startOffset"})); } return toObject; } @ExcludeFromGeneratedCoverageReport - ObjectNode citationMetadataFromVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode blobFromVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"citations"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"displayName"}) != null) { Common.setValueByPath( toObject, - new String[] {"citations"}, - Common.getValueByPath(fromObject, new String[] {"citations"})); + new String[] {"displayName"}, + Common.getValueByPath(fromObject, new String[] {"displayName"})); } - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode urlMetadataFromVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"retrievedUrl"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"data"}) != null) { Common.setValueByPath( toObject, - new String[] {"retrievedUrl"}, - Common.getValueByPath(fromObject, new String[] {"retrievedUrl"})); + new String[] {"data"}, + Common.getValueByPath(fromObject, new String[] {"data"})); } - if (Common.getValueByPath(fromObject, new String[] {"urlRetrievalStatus"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"mimeType"}) != null) { Common.setValueByPath( toObject, - new String[] {"urlRetrievalStatus"}, - Common.getValueByPath(fromObject, new String[] {"urlRetrievalStatus"})); + new String[] {"mimeType"}, + Common.getValueByPath(fromObject, new String[] {"mimeType"})); } return toObject; } @ExcludeFromGeneratedCoverageReport - ObjectNode urlContextMetadataFromVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode fileDataFromVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"urlMetadata"}) != null) { - ArrayNode keyArray = - (ArrayNode) Common.getValueByPath(fromObject, new String[] {"urlMetadata"}); - ObjectMapper objectMapper = new ObjectMapper(); - ArrayNode result = objectMapper.createArrayNode(); + if (Common.getValueByPath(fromObject, new String[] {"displayName"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"displayName"}, + Common.getValueByPath(fromObject, new String[] {"displayName"})); + } - for (JsonNode item : keyArray) { - result.add(urlMetadataFromVertex(JsonSerializable.toJsonNode(item), toObject)); - } - Common.setValueByPath(toObject, new String[] {"urlMetadata"}, result); + if (Common.getValueByPath(fromObject, new String[] {"fileUri"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"fileUri"}, + Common.getValueByPath(fromObject, new String[] {"fileUri"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"mimeType"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"mimeType"}, + Common.getValueByPath(fromObject, new String[] {"mimeType"})); } return toObject; } @ExcludeFromGeneratedCoverageReport - ObjectNode candidateFromVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode partFromVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"content"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"videoMetadata"}) != null) { Common.setValueByPath( toObject, - new String[] {"content"}, - contentFromVertex( + new String[] {"videoMetadata"}, + videoMetadataFromVertex( JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"content"})), + Common.getValueByPath(fromObject, new String[] {"videoMetadata"})), toObject)); } - if (Common.getValueByPath(fromObject, new String[] {"citationMetadata"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"thought"}) != null) { Common.setValueByPath( toObject, - new String[] {"citationMetadata"}, - citationMetadataFromVertex( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"citationMetadata"})), - toObject)); + new String[] {"thought"}, + Common.getValueByPath(fromObject, new String[] {"thought"})); } - if (Common.getValueByPath(fromObject, new String[] {"finishMessage"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"inlineData"}) != null) { Common.setValueByPath( toObject, - new String[] {"finishMessage"}, - Common.getValueByPath(fromObject, new String[] {"finishMessage"})); + new String[] {"inlineData"}, + blobFromVertex( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"inlineData"})), + toObject)); } - if (Common.getValueByPath(fromObject, new String[] {"finishReason"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"fileData"}) != null) { Common.setValueByPath( toObject, - new String[] {"finishReason"}, - Common.getValueByPath(fromObject, new String[] {"finishReason"})); + new String[] {"fileData"}, + fileDataFromVertex( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"fileData"})), + toObject)); } - if (Common.getValueByPath(fromObject, new String[] {"urlContextMetadata"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"thoughtSignature"}) != null) { Common.setValueByPath( toObject, - new String[] {"urlContextMetadata"}, - urlContextMetadataFromVertex( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"urlContextMetadata"})), - toObject)); + new String[] {"thoughtSignature"}, + Common.getValueByPath(fromObject, new String[] {"thoughtSignature"})); } - if (Common.getValueByPath(fromObject, new String[] {"avgLogprobs"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"codeExecutionResult"}) != null) { Common.setValueByPath( toObject, - new String[] {"avgLogprobs"}, - Common.getValueByPath(fromObject, new String[] {"avgLogprobs"})); + new String[] {"codeExecutionResult"}, + Common.getValueByPath(fromObject, new String[] {"codeExecutionResult"})); } - if (Common.getValueByPath(fromObject, new String[] {"groundingMetadata"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"executableCode"}) != null) { Common.setValueByPath( toObject, - new String[] {"groundingMetadata"}, - Common.getValueByPath(fromObject, new String[] {"groundingMetadata"})); + new String[] {"executableCode"}, + Common.getValueByPath(fromObject, new String[] {"executableCode"})); } - if (Common.getValueByPath(fromObject, new String[] {"index"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"functionCall"}) != null) { Common.setValueByPath( toObject, - new String[] {"index"}, - Common.getValueByPath(fromObject, new String[] {"index"})); + new String[] {"functionCall"}, + Common.getValueByPath(fromObject, new String[] {"functionCall"})); } - if (Common.getValueByPath(fromObject, new String[] {"logprobsResult"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"functionResponse"}) != null) { Common.setValueByPath( toObject, - new String[] {"logprobsResult"}, - Common.getValueByPath(fromObject, new String[] {"logprobsResult"})); + new String[] {"functionResponse"}, + Common.getValueByPath(fromObject, new String[] {"functionResponse"})); } - if (Common.getValueByPath(fromObject, new String[] {"safetyRatings"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"text"}) != null) { Common.setValueByPath( toObject, - new String[] {"safetyRatings"}, - Common.getValueByPath(fromObject, new String[] {"safetyRatings"})); + new String[] {"text"}, + Common.getValueByPath(fromObject, new String[] {"text"})); } return toObject; } @ExcludeFromGeneratedCoverageReport - ObjectNode generateContentResponseFromVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode contentFromVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - - if (Common.getValueByPath(fromObject, new String[] {"candidates"}) != null) { - ArrayNode keyArray = - (ArrayNode) Common.getValueByPath(fromObject, new String[] {"candidates"}); + if (Common.getValueByPath(fromObject, new String[] {"parts"}) != null) { + ArrayNode keyArray = (ArrayNode) Common.getValueByPath(fromObject, new String[] {"parts"}); ObjectMapper objectMapper = new ObjectMapper(); ArrayNode result = objectMapper.createArrayNode(); for (JsonNode item : keyArray) { - result.add(candidateFromVertex(JsonSerializable.toJsonNode(item), toObject)); + result.add(partFromVertex(JsonSerializable.toJsonNode(item), toObject)); } - Common.setValueByPath(toObject, new String[] {"candidates"}, result); + Common.setValueByPath(toObject, new String[] {"parts"}, result); } - if (Common.getValueByPath(fromObject, new String[] {"createTime"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"role"}) != null) { Common.setValueByPath( toObject, - new String[] {"createTime"}, - Common.getValueByPath(fromObject, new String[] {"createTime"})); + new String[] {"role"}, + Common.getValueByPath(fromObject, new String[] {"role"})); } - if (Common.getValueByPath(fromObject, new String[] {"responseId"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"responseId"}, - Common.getValueByPath(fromObject, new String[] {"responseId"})); - } + return toObject; + } - if (Common.getValueByPath(fromObject, new String[] {"modelVersion"}) != null) { + @ExcludeFromGeneratedCoverageReport + ObjectNode inlinedRequestFromVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode batchJobSourceFromVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"instancesFormat"}) != null) { Common.setValueByPath( toObject, - new String[] {"modelVersion"}, - Common.getValueByPath(fromObject, new String[] {"modelVersion"})); + new String[] {"format"}, + Common.getValueByPath(fromObject, new String[] {"instancesFormat"})); } - if (Common.getValueByPath(fromObject, new String[] {"promptFeedback"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"gcsSource", "uris"}) != null) { Common.setValueByPath( toObject, - new String[] {"promptFeedback"}, - Common.getValueByPath(fromObject, new String[] {"promptFeedback"})); + new String[] {"gcsUri"}, + Common.getValueByPath(fromObject, new String[] {"gcsSource", "uris"})); } - if (Common.getValueByPath(fromObject, new String[] {"usageMetadata"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"bigquerySource", "inputUri"}) != null) { Common.setValueByPath( toObject, - new String[] {"usageMetadata"}, - Common.getValueByPath(fromObject, new String[] {"usageMetadata"})); + new String[] {"bigqueryUri"}, + Common.getValueByPath(fromObject, new String[] {"bigquerySource", "inputUri"})); } return toObject; diff --git a/src/main/java/com/google/genai/Caches.java b/src/main/java/com/google/genai/Caches.java index 7ee03586c81..c8cac25d6f9 100644 --- a/src/main/java/com/google/genai/Caches.java +++ b/src/main/java/com/google/genai/Caches.java @@ -362,78 +362,6 @@ ObjectNode googleSearchRetrievalToMldev(JsonNode fromObject, ObjectNode parentOb return toObject; } - @ExcludeFromGeneratedCoverageReport - ObjectNode enterpriseWebSearchToMldev(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode apiKeyConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"apiKeyString"}))) { - throw new IllegalArgumentException("apiKeyString parameter is not supported in Gemini API."); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode authConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"apiKeyConfig"}))) { - throw new IllegalArgumentException("apiKeyConfig parameter is not supported in Gemini API."); - } - - if (Common.getValueByPath(fromObject, new String[] {"authType"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"authType"}, - Common.getValueByPath(fromObject, new String[] {"authType"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"googleServiceAccountConfig"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"googleServiceAccountConfig"}, - Common.getValueByPath(fromObject, new String[] {"googleServiceAccountConfig"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"httpBasicAuthConfig"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"httpBasicAuthConfig"}, - Common.getValueByPath(fromObject, new String[] {"httpBasicAuthConfig"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"oauthConfig"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"oauthConfig"}, - Common.getValueByPath(fromObject, new String[] {"oauthConfig"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"oidcConfig"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"oidcConfig"}, - Common.getValueByPath(fromObject, new String[] {"oidcConfig"})); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode googleMapsToMldev(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"authConfig"}))) { - throw new IllegalArgumentException("authConfig parameter is not supported in Gemini API."); - } - - return toObject; - } - @ExcludeFromGeneratedCoverageReport ObjectNode urlContextToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); diff --git a/src/main/java/com/google/genai/LiveConverters.java b/src/main/java/com/google/genai/LiveConverters.java index 499689287a5..2979be9fd8c 100644 --- a/src/main/java/com/google/genai/LiveConverters.java +++ b/src/main/java/com/google/genai/LiveConverters.java @@ -43,19 +43,6 @@ ObjectNode prebuiltVoiceConfigToMldev(JsonNode fromObject, ObjectNode parentObje return toObject; } - @ExcludeFromGeneratedCoverageReport - ObjectNode prebuiltVoiceConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"voiceName"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"voiceName"}, - Common.getValueByPath(fromObject, new String[] {"voiceName"})); - } - - return toObject; - } - @ExcludeFromGeneratedCoverageReport ObjectNode voiceConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); @@ -72,22 +59,6 @@ ObjectNode voiceConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { return toObject; } - @ExcludeFromGeneratedCoverageReport - ObjectNode voiceConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"prebuiltVoiceConfig"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"prebuiltVoiceConfig"}, - prebuiltVoiceConfigToVertex( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"prebuiltVoiceConfig"})), - toObject)); - } - - return toObject; - } - @ExcludeFromGeneratedCoverageReport ObjectNode speakerVoiceConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); @@ -111,20 +82,6 @@ ObjectNode speakerVoiceConfigToMldev(JsonNode fromObject, ObjectNode parentObjec return toObject; } - @ExcludeFromGeneratedCoverageReport - ObjectNode speakerVoiceConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"speaker"}))) { - throw new IllegalArgumentException("speaker parameter is not supported in Vertex AI."); - } - - if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"voiceConfig"}))) { - throw new IllegalArgumentException("voiceConfig parameter is not supported in Vertex AI."); - } - - return toObject; - } - @ExcludeFromGeneratedCoverageReport ObjectNode multiSpeakerVoiceConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); @@ -143,17 +100,6 @@ ObjectNode multiSpeakerVoiceConfigToMldev(JsonNode fromObject, ObjectNode parent return toObject; } - @ExcludeFromGeneratedCoverageReport - ObjectNode multiSpeakerVoiceConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"speakerVoiceConfigs"}))) { - throw new IllegalArgumentException( - "speakerVoiceConfigs parameter is not supported in Vertex AI."); - } - - return toObject; - } - @ExcludeFromGeneratedCoverageReport ObjectNode speechConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); @@ -187,35 +133,6 @@ ObjectNode speechConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { return toObject; } - @ExcludeFromGeneratedCoverageReport - ObjectNode speechConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"voiceConfig"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"voiceConfig"}, - voiceConfigToVertex( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"voiceConfig"})), - toObject)); - } - - if (!Common.isZero( - Common.getValueByPath(fromObject, new String[] {"multiSpeakerVoiceConfig"}))) { - throw new IllegalArgumentException( - "multiSpeakerVoiceConfig parameter is not supported in Vertex AI."); - } - - if (Common.getValueByPath(fromObject, new String[] {"languageCode"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"languageCode"}, - Common.getValueByPath(fromObject, new String[] {"languageCode"})); - } - - return toObject; - } - @ExcludeFromGeneratedCoverageReport ObjectNode videoMetadataToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); @@ -241,31 +158,6 @@ ObjectNode videoMetadataToMldev(JsonNode fromObject, ObjectNode parentObject) { return toObject; } - @ExcludeFromGeneratedCoverageReport - ObjectNode videoMetadataToVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"fps"}) != null) { - Common.setValueByPath( - toObject, new String[] {"fps"}, Common.getValueByPath(fromObject, new String[] {"fps"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"endOffset"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"endOffset"}, - Common.getValueByPath(fromObject, new String[] {"endOffset"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"startOffset"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"startOffset"}, - Common.getValueByPath(fromObject, new String[] {"startOffset"})); - } - - return toObject; - } - @ExcludeFromGeneratedCoverageReport ObjectNode blobToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); @@ -290,33 +182,6 @@ ObjectNode blobToMldev(JsonNode fromObject, ObjectNode parentObject) { return toObject; } - @ExcludeFromGeneratedCoverageReport - ObjectNode blobToVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"displayName"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"displayName"}, - Common.getValueByPath(fromObject, new String[] {"displayName"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"data"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"data"}, - Common.getValueByPath(fromObject, new String[] {"data"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"mimeType"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"mimeType"}, - Common.getValueByPath(fromObject, new String[] {"mimeType"})); - } - - return toObject; - } - @ExcludeFromGeneratedCoverageReport ObjectNode fileDataToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); @@ -341,33 +206,6 @@ ObjectNode fileDataToMldev(JsonNode fromObject, ObjectNode parentObject) { return toObject; } - @ExcludeFromGeneratedCoverageReport - ObjectNode fileDataToVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"displayName"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"displayName"}, - Common.getValueByPath(fromObject, new String[] {"displayName"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"fileUri"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"fileUri"}, - Common.getValueByPath(fromObject, new String[] {"fileUri"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"mimeType"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"mimeType"}, - Common.getValueByPath(fromObject, new String[] {"mimeType"})); - } - - return toObject; - } - @ExcludeFromGeneratedCoverageReport ObjectNode partToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); @@ -454,295 +292,363 @@ ObjectNode partToMldev(JsonNode fromObject, ObjectNode parentObject) { } @ExcludeFromGeneratedCoverageReport - ObjectNode partToVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode contentToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"videoMetadata"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"parts"}) != null) { + ArrayNode keyArray = (ArrayNode) Common.getValueByPath(fromObject, new String[] {"parts"}); + ObjectMapper objectMapper = new ObjectMapper(); + ArrayNode result = objectMapper.createArrayNode(); + + for (JsonNode item : keyArray) { + result.add(partToMldev(JsonSerializable.toJsonNode(item), toObject)); + } + Common.setValueByPath(toObject, new String[] {"parts"}, result); + } + + if (Common.getValueByPath(fromObject, new String[] {"role"}) != null) { Common.setValueByPath( toObject, - new String[] {"videoMetadata"}, - videoMetadataToVertex( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"videoMetadata"})), - toObject)); + new String[] {"role"}, + Common.getValueByPath(fromObject, new String[] {"role"})); } - if (Common.getValueByPath(fromObject, new String[] {"thought"}) != null) { + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode functionDeclarationToMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"behavior"}) != null) { Common.setValueByPath( toObject, - new String[] {"thought"}, - Common.getValueByPath(fromObject, new String[] {"thought"})); + new String[] {"behavior"}, + Common.getValueByPath(fromObject, new String[] {"behavior"})); } - if (Common.getValueByPath(fromObject, new String[] {"inlineData"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"description"}) != null) { Common.setValueByPath( toObject, - new String[] {"inlineData"}, - blobToVertex( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"inlineData"})), - toObject)); + new String[] {"description"}, + Common.getValueByPath(fromObject, new String[] {"description"})); } - if (Common.getValueByPath(fromObject, new String[] {"fileData"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"name"}) != null) { Common.setValueByPath( toObject, - new String[] {"fileData"}, - fileDataToVertex( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"fileData"})), - toObject)); + new String[] {"name"}, + Common.getValueByPath(fromObject, new String[] {"name"})); } - if (Common.getValueByPath(fromObject, new String[] {"thoughtSignature"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"parameters"}) != null) { Common.setValueByPath( toObject, - new String[] {"thoughtSignature"}, - Common.getValueByPath(fromObject, new String[] {"thoughtSignature"})); + new String[] {"parameters"}, + Common.getValueByPath(fromObject, new String[] {"parameters"})); } - if (Common.getValueByPath(fromObject, new String[] {"codeExecutionResult"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"parametersJsonSchema"}) != null) { Common.setValueByPath( toObject, - new String[] {"codeExecutionResult"}, - Common.getValueByPath(fromObject, new String[] {"codeExecutionResult"})); + new String[] {"parametersJsonSchema"}, + Common.getValueByPath(fromObject, new String[] {"parametersJsonSchema"})); } - if (Common.getValueByPath(fromObject, new String[] {"executableCode"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"response"}) != null) { Common.setValueByPath( toObject, - new String[] {"executableCode"}, - Common.getValueByPath(fromObject, new String[] {"executableCode"})); + new String[] {"response"}, + Common.getValueByPath(fromObject, new String[] {"response"})); } - if (Common.getValueByPath(fromObject, new String[] {"functionCall"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"responseJsonSchema"}) != null) { Common.setValueByPath( toObject, - new String[] {"functionCall"}, - Common.getValueByPath(fromObject, new String[] {"functionCall"})); + new String[] {"responseJsonSchema"}, + Common.getValueByPath(fromObject, new String[] {"responseJsonSchema"})); } - if (Common.getValueByPath(fromObject, new String[] {"functionResponse"}) != null) { + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode intervalToMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"startTime"}) != null) { Common.setValueByPath( toObject, - new String[] {"functionResponse"}, - Common.getValueByPath(fromObject, new String[] {"functionResponse"})); + new String[] {"startTime"}, + Common.getValueByPath(fromObject, new String[] {"startTime"})); } - if (Common.getValueByPath(fromObject, new String[] {"text"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"endTime"}) != null) { Common.setValueByPath( toObject, - new String[] {"text"}, - Common.getValueByPath(fromObject, new String[] {"text"})); + new String[] {"endTime"}, + Common.getValueByPath(fromObject, new String[] {"endTime"})); } return toObject; } @ExcludeFromGeneratedCoverageReport - ObjectNode contentToMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode googleSearchToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"parts"}) != null) { - ArrayNode keyArray = (ArrayNode) Common.getValueByPath(fromObject, new String[] {"parts"}); - ObjectMapper objectMapper = new ObjectMapper(); - ArrayNode result = objectMapper.createArrayNode(); - - for (JsonNode item : keyArray) { - result.add(partToMldev(JsonSerializable.toJsonNode(item), toObject)); - } - Common.setValueByPath(toObject, new String[] {"parts"}, result); - } - - if (Common.getValueByPath(fromObject, new String[] {"role"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"timeRangeFilter"}) != null) { Common.setValueByPath( toObject, - new String[] {"role"}, - Common.getValueByPath(fromObject, new String[] {"role"})); + new String[] {"timeRangeFilter"}, + intervalToMldev( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"timeRangeFilter"})), + toObject)); } return toObject; } @ExcludeFromGeneratedCoverageReport - ObjectNode contentToVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode dynamicRetrievalConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"parts"}) != null) { - ArrayNode keyArray = (ArrayNode) Common.getValueByPath(fromObject, new String[] {"parts"}); - ObjectMapper objectMapper = new ObjectMapper(); - ArrayNode result = objectMapper.createArrayNode(); - - for (JsonNode item : keyArray) { - result.add(partToVertex(JsonSerializable.toJsonNode(item), toObject)); - } - Common.setValueByPath(toObject, new String[] {"parts"}, result); + if (Common.getValueByPath(fromObject, new String[] {"mode"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"mode"}, + Common.getValueByPath(fromObject, new String[] {"mode"})); } - if (Common.getValueByPath(fromObject, new String[] {"role"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"dynamicThreshold"}) != null) { Common.setValueByPath( toObject, - new String[] {"role"}, - Common.getValueByPath(fromObject, new String[] {"role"})); + new String[] {"dynamicThreshold"}, + Common.getValueByPath(fromObject, new String[] {"dynamicThreshold"})); } return toObject; } @ExcludeFromGeneratedCoverageReport - ObjectNode functionDeclarationToMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode googleSearchRetrievalToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"behavior"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"dynamicRetrievalConfig"}) != null) { Common.setValueByPath( toObject, - new String[] {"behavior"}, - Common.getValueByPath(fromObject, new String[] {"behavior"})); + new String[] {"dynamicRetrievalConfig"}, + dynamicRetrievalConfigToMldev( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"dynamicRetrievalConfig"})), + toObject)); } - if (Common.getValueByPath(fromObject, new String[] {"description"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"description"}, - Common.getValueByPath(fromObject, new String[] {"description"})); + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode urlContextToMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode toolToMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"functionDeclarations"}) != null) { + ArrayNode keyArray = + (ArrayNode) Common.getValueByPath(fromObject, new String[] {"functionDeclarations"}); + ObjectMapper objectMapper = new ObjectMapper(); + ArrayNode result = objectMapper.createArrayNode(); + + for (JsonNode item : keyArray) { + result.add(functionDeclarationToMldev(JsonSerializable.toJsonNode(item), toObject)); + } + Common.setValueByPath(toObject, new String[] {"functionDeclarations"}, result); } - if (Common.getValueByPath(fromObject, new String[] {"name"}) != null) { + if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"retrieval"}))) { + throw new IllegalArgumentException("retrieval parameter is not supported in Gemini API."); + } + + if (Common.getValueByPath(fromObject, new String[] {"googleSearch"}) != null) { Common.setValueByPath( toObject, - new String[] {"name"}, - Common.getValueByPath(fromObject, new String[] {"name"})); + new String[] {"googleSearch"}, + googleSearchToMldev( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"googleSearch"})), + toObject)); } - if (Common.getValueByPath(fromObject, new String[] {"parameters"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"googleSearchRetrieval"}) != null) { Common.setValueByPath( toObject, - new String[] {"parameters"}, - Common.getValueByPath(fromObject, new String[] {"parameters"})); + new String[] {"googleSearchRetrieval"}, + googleSearchRetrievalToMldev( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"googleSearchRetrieval"})), + toObject)); } - if (Common.getValueByPath(fromObject, new String[] {"parametersJsonSchema"}) != null) { + if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"enterpriseWebSearch"}))) { + throw new IllegalArgumentException( + "enterpriseWebSearch parameter is not supported in Gemini API."); + } + + if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"googleMaps"}))) { + throw new IllegalArgumentException("googleMaps parameter is not supported in Gemini API."); + } + + if (Common.getValueByPath(fromObject, new String[] {"urlContext"}) != null) { Common.setValueByPath( toObject, - new String[] {"parametersJsonSchema"}, - Common.getValueByPath(fromObject, new String[] {"parametersJsonSchema"})); + new String[] {"urlContext"}, + urlContextToMldev( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"urlContext"})), + toObject)); } - if (Common.getValueByPath(fromObject, new String[] {"response"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"codeExecution"}) != null) { Common.setValueByPath( toObject, - new String[] {"response"}, - Common.getValueByPath(fromObject, new String[] {"response"})); + new String[] {"codeExecution"}, + Common.getValueByPath(fromObject, new String[] {"codeExecution"})); } - if (Common.getValueByPath(fromObject, new String[] {"responseJsonSchema"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"computerUse"}) != null) { Common.setValueByPath( toObject, - new String[] {"responseJsonSchema"}, - Common.getValueByPath(fromObject, new String[] {"responseJsonSchema"})); + new String[] {"computerUse"}, + Common.getValueByPath(fromObject, new String[] {"computerUse"})); } return toObject; } @ExcludeFromGeneratedCoverageReport - ObjectNode functionDeclarationToVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode sessionResumptionConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"behavior"}))) { - throw new IllegalArgumentException("behavior parameter is not supported in Vertex AI."); - } - - if (Common.getValueByPath(fromObject, new String[] {"description"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"handle"}) != null) { Common.setValueByPath( toObject, - new String[] {"description"}, - Common.getValueByPath(fromObject, new String[] {"description"})); + new String[] {"handle"}, + Common.getValueByPath(fromObject, new String[] {"handle"})); } - if (Common.getValueByPath(fromObject, new String[] {"name"}) != null) { + if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"transparent"}))) { + throw new IllegalArgumentException("transparent parameter is not supported in Gemini API."); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode audioTranscriptionConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode automaticActivityDetectionToMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"disabled"}) != null) { Common.setValueByPath( toObject, - new String[] {"name"}, - Common.getValueByPath(fromObject, new String[] {"name"})); + new String[] {"disabled"}, + Common.getValueByPath(fromObject, new String[] {"disabled"})); } - if (Common.getValueByPath(fromObject, new String[] {"parameters"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"startOfSpeechSensitivity"}) != null) { Common.setValueByPath( toObject, - new String[] {"parameters"}, - Common.getValueByPath(fromObject, new String[] {"parameters"})); + new String[] {"startOfSpeechSensitivity"}, + Common.getValueByPath(fromObject, new String[] {"startOfSpeechSensitivity"})); } - if (Common.getValueByPath(fromObject, new String[] {"parametersJsonSchema"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"endOfSpeechSensitivity"}) != null) { Common.setValueByPath( toObject, - new String[] {"parametersJsonSchema"}, - Common.getValueByPath(fromObject, new String[] {"parametersJsonSchema"})); + new String[] {"endOfSpeechSensitivity"}, + Common.getValueByPath(fromObject, new String[] {"endOfSpeechSensitivity"})); } - if (Common.getValueByPath(fromObject, new String[] {"response"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"prefixPaddingMs"}) != null) { Common.setValueByPath( toObject, - new String[] {"response"}, - Common.getValueByPath(fromObject, new String[] {"response"})); + new String[] {"prefixPaddingMs"}, + Common.getValueByPath(fromObject, new String[] {"prefixPaddingMs"})); } - if (Common.getValueByPath(fromObject, new String[] {"responseJsonSchema"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"silenceDurationMs"}) != null) { Common.setValueByPath( toObject, - new String[] {"responseJsonSchema"}, - Common.getValueByPath(fromObject, new String[] {"responseJsonSchema"})); + new String[] {"silenceDurationMs"}, + Common.getValueByPath(fromObject, new String[] {"silenceDurationMs"})); } return toObject; } @ExcludeFromGeneratedCoverageReport - ObjectNode intervalToMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode realtimeInputConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"startTime"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"automaticActivityDetection"}) != null) { Common.setValueByPath( toObject, - new String[] {"startTime"}, - Common.getValueByPath(fromObject, new String[] {"startTime"})); + new String[] {"automaticActivityDetection"}, + automaticActivityDetectionToMldev( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"automaticActivityDetection"})), + toObject)); } - if (Common.getValueByPath(fromObject, new String[] {"endTime"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"activityHandling"}) != null) { Common.setValueByPath( toObject, - new String[] {"endTime"}, - Common.getValueByPath(fromObject, new String[] {"endTime"})); + new String[] {"activityHandling"}, + Common.getValueByPath(fromObject, new String[] {"activityHandling"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"turnCoverage"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"turnCoverage"}, + Common.getValueByPath(fromObject, new String[] {"turnCoverage"})); } return toObject; } @ExcludeFromGeneratedCoverageReport - ObjectNode intervalToVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode slidingWindowToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"startTime"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"startTime"}, - Common.getValueByPath(fromObject, new String[] {"startTime"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"endTime"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"targetTokens"}) != null) { Common.setValueByPath( toObject, - new String[] {"endTime"}, - Common.getValueByPath(fromObject, new String[] {"endTime"})); + new String[] {"targetTokens"}, + Common.getValueByPath(fromObject, new String[] {"targetTokens"})); } return toObject; } @ExcludeFromGeneratedCoverageReport - ObjectNode googleSearchToMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode contextWindowCompressionConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"timeRangeFilter"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"triggerTokens"}) != null) { Common.setValueByPath( toObject, - new String[] {"timeRangeFilter"}, - intervalToMldev( + new String[] {"triggerTokens"}, + Common.getValueByPath(fromObject, new String[] {"triggerTokens"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"slidingWindow"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"slidingWindow"}, + slidingWindowToMldev( JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"timeRangeFilter"})), + Common.getValueByPath(fromObject, new String[] {"slidingWindow"})), toObject)); } @@ -750,72 +656,927 @@ ObjectNode googleSearchToMldev(JsonNode fromObject, ObjectNode parentObject) { } @ExcludeFromGeneratedCoverageReport - ObjectNode googleSearchToVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode proactivityConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"timeRangeFilter"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"proactiveAudio"}) != null) { Common.setValueByPath( toObject, - new String[] {"timeRangeFilter"}, - intervalToVertex( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"timeRangeFilter"})), - toObject)); + new String[] {"proactiveAudio"}, + Common.getValueByPath(fromObject, new String[] {"proactiveAudio"})); } return toObject; } @ExcludeFromGeneratedCoverageReport - ObjectNode dynamicRetrievalConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode liveConnectConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"mode"}) != null) { + + if (Common.getValueByPath(fromObject, new String[] {"responseModalities"}) != null) { + Common.setValueByPath( + parentObject, + new String[] {"setup", "generationConfig", "responseModalities"}, + Common.getValueByPath(fromObject, new String[] {"responseModalities"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"temperature"}) != null) { + Common.setValueByPath( + parentObject, + new String[] {"setup", "generationConfig", "temperature"}, + Common.getValueByPath(fromObject, new String[] {"temperature"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"topP"}) != null) { + Common.setValueByPath( + parentObject, + new String[] {"setup", "generationConfig", "topP"}, + Common.getValueByPath(fromObject, new String[] {"topP"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"topK"}) != null) { + Common.setValueByPath( + parentObject, + new String[] {"setup", "generationConfig", "topK"}, + Common.getValueByPath(fromObject, new String[] {"topK"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"maxOutputTokens"}) != null) { + Common.setValueByPath( + parentObject, + new String[] {"setup", "generationConfig", "maxOutputTokens"}, + Common.getValueByPath(fromObject, new String[] {"maxOutputTokens"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"mediaResolution"}) != null) { + Common.setValueByPath( + parentObject, + new String[] {"setup", "generationConfig", "mediaResolution"}, + Common.getValueByPath(fromObject, new String[] {"mediaResolution"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"seed"}) != null) { + Common.setValueByPath( + parentObject, + new String[] {"setup", "generationConfig", "seed"}, + Common.getValueByPath(fromObject, new String[] {"seed"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"speechConfig"}) != null) { + Common.setValueByPath( + parentObject, + new String[] {"setup", "generationConfig", "speechConfig"}, + speechConfigToMldev( + JsonSerializable.toJsonNode( + Transformers.tLiveSpeechConfig( + Common.getValueByPath(fromObject, new String[] {"speechConfig"}))), + toObject)); + } + + if (Common.getValueByPath(fromObject, new String[] {"enableAffectiveDialog"}) != null) { + Common.setValueByPath( + parentObject, + new String[] {"setup", "generationConfig", "enableAffectiveDialog"}, + Common.getValueByPath(fromObject, new String[] {"enableAffectiveDialog"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"systemInstruction"}) != null) { + Common.setValueByPath( + parentObject, + new String[] {"setup", "systemInstruction"}, + contentToMldev( + JsonSerializable.toJsonNode( + Transformers.tContent( + Common.getValueByPath(fromObject, new String[] {"systemInstruction"}))), + toObject)); + } + + if (Common.getValueByPath(fromObject, new String[] {"tools"}) != null) { + ArrayNode keyArray = + (ArrayNode) + Transformers.tTools(Common.getValueByPath(fromObject, new String[] {"tools"})); + ObjectMapper objectMapper = new ObjectMapper(); + ArrayNode result = objectMapper.createArrayNode(); + + for (JsonNode item : keyArray) { + result.add(toolToMldev(JsonSerializable.toJsonNode(Transformers.tTool(item)), toObject)); + } + Common.setValueByPath(parentObject, new String[] {"setup", "tools"}, result); + } + + if (Common.getValueByPath(fromObject, new String[] {"sessionResumption"}) != null) { + Common.setValueByPath( + parentObject, + new String[] {"setup", "sessionResumption"}, + sessionResumptionConfigToMldev( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"sessionResumption"})), + toObject)); + } + + if (Common.getValueByPath(fromObject, new String[] {"inputAudioTranscription"}) != null) { + Common.setValueByPath( + parentObject, + new String[] {"setup", "inputAudioTranscription"}, + audioTranscriptionConfigToMldev( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"inputAudioTranscription"})), + toObject)); + } + + if (Common.getValueByPath(fromObject, new String[] {"outputAudioTranscription"}) != null) { + Common.setValueByPath( + parentObject, + new String[] {"setup", "outputAudioTranscription"}, + audioTranscriptionConfigToMldev( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"outputAudioTranscription"})), + toObject)); + } + + if (Common.getValueByPath(fromObject, new String[] {"realtimeInputConfig"}) != null) { + Common.setValueByPath( + parentObject, + new String[] {"setup", "realtimeInputConfig"}, + realtimeInputConfigToMldev( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"realtimeInputConfig"})), + toObject)); + } + + if (Common.getValueByPath(fromObject, new String[] {"contextWindowCompression"}) != null) { + Common.setValueByPath( + parentObject, + new String[] {"setup", "contextWindowCompression"}, + contextWindowCompressionConfigToMldev( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"contextWindowCompression"})), + toObject)); + } + + if (Common.getValueByPath(fromObject, new String[] {"proactivity"}) != null) { + Common.setValueByPath( + parentObject, + new String[] {"setup", "proactivity"}, + proactivityConfigToMldev( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"proactivity"})), + toObject)); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode liveConnectParametersToMldev( + ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"model"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"setup", "model"}, + Transformers.tModel( + this.apiClient, Common.getValueByPath(fromObject, new String[] {"model"}))); + } + + if (Common.getValueByPath(fromObject, new String[] {"config"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"config"}, + liveConnectConfigToMldev( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"config"})), + toObject)); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode activityStartToMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode activityEndToMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode liveSendRealtimeInputParametersToMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"media"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"mediaChunks"}, + Transformers.tBlobs(Common.getValueByPath(fromObject, new String[] {"media"}))); + } + + if (Common.getValueByPath(fromObject, new String[] {"audio"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"audio"}, + Transformers.tAudioBlob(Common.getValueByPath(fromObject, new String[] {"audio"}))); + } + + if (Common.getValueByPath(fromObject, new String[] {"audioStreamEnd"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"audioStreamEnd"}, + Common.getValueByPath(fromObject, new String[] {"audioStreamEnd"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"video"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"video"}, + Transformers.tImageBlob(Common.getValueByPath(fromObject, new String[] {"video"}))); + } + + if (Common.getValueByPath(fromObject, new String[] {"text"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"text"}, + Common.getValueByPath(fromObject, new String[] {"text"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"activityStart"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"activityStart"}, + activityStartToMldev( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"activityStart"})), + toObject)); + } + + if (Common.getValueByPath(fromObject, new String[] {"activityEnd"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"activityEnd"}, + activityEndToMldev( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"activityEnd"})), + toObject)); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode liveClientSetupToMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"model"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"model"}, + Common.getValueByPath(fromObject, new String[] {"model"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"generationConfig"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"generationConfig"}, + Common.getValueByPath(fromObject, new String[] {"generationConfig"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"systemInstruction"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"systemInstruction"}, + contentToMldev( + JsonSerializable.toJsonNode( + Transformers.tContent( + Common.getValueByPath(fromObject, new String[] {"systemInstruction"}))), + toObject)); + } + + if (Common.getValueByPath(fromObject, new String[] {"tools"}) != null) { + ArrayNode keyArray = + (ArrayNode) + Transformers.tTools(Common.getValueByPath(fromObject, new String[] {"tools"})); + ObjectMapper objectMapper = new ObjectMapper(); + ArrayNode result = objectMapper.createArrayNode(); + + for (JsonNode item : keyArray) { + result.add(toolToMldev(JsonSerializable.toJsonNode(Transformers.tTool(item)), toObject)); + } + Common.setValueByPath(toObject, new String[] {"tools"}, result); + } + + if (Common.getValueByPath(fromObject, new String[] {"realtimeInputConfig"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"realtimeInputConfig"}, + realtimeInputConfigToMldev( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"realtimeInputConfig"})), + toObject)); + } + + if (Common.getValueByPath(fromObject, new String[] {"sessionResumption"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"sessionResumption"}, + sessionResumptionConfigToMldev( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"sessionResumption"})), + toObject)); + } + + if (Common.getValueByPath(fromObject, new String[] {"contextWindowCompression"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"contextWindowCompression"}, + contextWindowCompressionConfigToMldev( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"contextWindowCompression"})), + toObject)); + } + + if (Common.getValueByPath(fromObject, new String[] {"inputAudioTranscription"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"inputAudioTranscription"}, + audioTranscriptionConfigToMldev( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"inputAudioTranscription"})), + toObject)); + } + + if (Common.getValueByPath(fromObject, new String[] {"outputAudioTranscription"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"outputAudioTranscription"}, + audioTranscriptionConfigToMldev( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"outputAudioTranscription"})), + toObject)); + } + + if (Common.getValueByPath(fromObject, new String[] {"proactivity"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"proactivity"}, + proactivityConfigToMldev( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"proactivity"})), + toObject)); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode liveClientContentToMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"turns"}) != null) { + ArrayNode keyArray = (ArrayNode) Common.getValueByPath(fromObject, new String[] {"turns"}); + ObjectMapper objectMapper = new ObjectMapper(); + ArrayNode result = objectMapper.createArrayNode(); + + for (JsonNode item : keyArray) { + result.add(contentToMldev(JsonSerializable.toJsonNode(item), toObject)); + } + Common.setValueByPath(toObject, new String[] {"turns"}, result); + } + + if (Common.getValueByPath(fromObject, new String[] {"turnComplete"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"turnComplete"}, + Common.getValueByPath(fromObject, new String[] {"turnComplete"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode liveClientRealtimeInputToMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"mediaChunks"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"mediaChunks"}, + Common.getValueByPath(fromObject, new String[] {"mediaChunks"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"audio"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"audio"}, + Common.getValueByPath(fromObject, new String[] {"audio"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"audioStreamEnd"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"audioStreamEnd"}, + Common.getValueByPath(fromObject, new String[] {"audioStreamEnd"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"video"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"video"}, + Common.getValueByPath(fromObject, new String[] {"video"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"text"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"text"}, + Common.getValueByPath(fromObject, new String[] {"text"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"activityStart"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"activityStart"}, + activityStartToMldev( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"activityStart"})), + toObject)); + } + + if (Common.getValueByPath(fromObject, new String[] {"activityEnd"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"activityEnd"}, + activityEndToMldev( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"activityEnd"})), + toObject)); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode functionResponseToMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"willContinue"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"willContinue"}, + Common.getValueByPath(fromObject, new String[] {"willContinue"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"scheduling"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"scheduling"}, + Common.getValueByPath(fromObject, new String[] {"scheduling"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"id"}) != null) { + Common.setValueByPath( + toObject, new String[] {"id"}, Common.getValueByPath(fromObject, new String[] {"id"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"name"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"name"}, + Common.getValueByPath(fromObject, new String[] {"name"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"response"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"response"}, + Common.getValueByPath(fromObject, new String[] {"response"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode liveClientToolResponseToMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"functionResponses"}) != null) { + ArrayNode keyArray = + (ArrayNode) Common.getValueByPath(fromObject, new String[] {"functionResponses"}); + ObjectMapper objectMapper = new ObjectMapper(); + ArrayNode result = objectMapper.createArrayNode(); + + for (JsonNode item : keyArray) { + result.add(functionResponseToMldev(JsonSerializable.toJsonNode(item), toObject)); + } + Common.setValueByPath(toObject, new String[] {"functionResponses"}, result); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode liveClientMessageToMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"setup"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"setup"}, + liveClientSetupToMldev( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"setup"})), + toObject)); + } + + if (Common.getValueByPath(fromObject, new String[] {"clientContent"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"clientContent"}, + liveClientContentToMldev( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"clientContent"})), + toObject)); + } + + if (Common.getValueByPath(fromObject, new String[] {"realtimeInput"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"realtimeInput"}, + liveClientRealtimeInputToMldev( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"realtimeInput"})), + toObject)); + } + + if (Common.getValueByPath(fromObject, new String[] {"realtimeInputParameters"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"realtime_input"}, + liveSendRealtimeInputParametersToMldev( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"realtimeInputParameters"})), + toObject)); + } + + if (Common.getValueByPath(fromObject, new String[] {"toolResponse"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"toolResponse"}, + liveClientToolResponseToMldev( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"toolResponse"})), + toObject)); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode prebuiltVoiceConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"voiceName"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"voiceName"}, + Common.getValueByPath(fromObject, new String[] {"voiceName"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode voiceConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"prebuiltVoiceConfig"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"prebuiltVoiceConfig"}, + prebuiltVoiceConfigToVertex( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"prebuiltVoiceConfig"})), + toObject)); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode speechConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"voiceConfig"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"voiceConfig"}, + voiceConfigToVertex( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"voiceConfig"})), + toObject)); + } + + if (!Common.isZero( + Common.getValueByPath(fromObject, new String[] {"multiSpeakerVoiceConfig"}))) { + throw new IllegalArgumentException( + "multiSpeakerVoiceConfig parameter is not supported in Vertex AI."); + } + + if (Common.getValueByPath(fromObject, new String[] {"languageCode"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"languageCode"}, + Common.getValueByPath(fromObject, new String[] {"languageCode"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode videoMetadataToVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"fps"}) != null) { + Common.setValueByPath( + toObject, new String[] {"fps"}, Common.getValueByPath(fromObject, new String[] {"fps"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"endOffset"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"endOffset"}, + Common.getValueByPath(fromObject, new String[] {"endOffset"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"startOffset"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"startOffset"}, + Common.getValueByPath(fromObject, new String[] {"startOffset"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode blobToVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"displayName"}) != null) { Common.setValueByPath( toObject, - new String[] {"mode"}, - Common.getValueByPath(fromObject, new String[] {"mode"})); + new String[] {"displayName"}, + Common.getValueByPath(fromObject, new String[] {"displayName"})); } - if (Common.getValueByPath(fromObject, new String[] {"dynamicThreshold"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"data"}) != null) { Common.setValueByPath( toObject, - new String[] {"dynamicThreshold"}, - Common.getValueByPath(fromObject, new String[] {"dynamicThreshold"})); + new String[] {"data"}, + Common.getValueByPath(fromObject, new String[] {"data"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"mimeType"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"mimeType"}, + Common.getValueByPath(fromObject, new String[] {"mimeType"})); } return toObject; } @ExcludeFromGeneratedCoverageReport - ObjectNode dynamicRetrievalConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode fileDataToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"mode"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"displayName"}) != null) { Common.setValueByPath( toObject, - new String[] {"mode"}, - Common.getValueByPath(fromObject, new String[] {"mode"})); + new String[] {"displayName"}, + Common.getValueByPath(fromObject, new String[] {"displayName"})); } - if (Common.getValueByPath(fromObject, new String[] {"dynamicThreshold"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"fileUri"}) != null) { Common.setValueByPath( toObject, - new String[] {"dynamicThreshold"}, - Common.getValueByPath(fromObject, new String[] {"dynamicThreshold"})); + new String[] {"fileUri"}, + Common.getValueByPath(fromObject, new String[] {"fileUri"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"mimeType"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"mimeType"}, + Common.getValueByPath(fromObject, new String[] {"mimeType"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode partToVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"videoMetadata"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"videoMetadata"}, + videoMetadataToVertex( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"videoMetadata"})), + toObject)); + } + + if (Common.getValueByPath(fromObject, new String[] {"thought"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"thought"}, + Common.getValueByPath(fromObject, new String[] {"thought"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"inlineData"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"inlineData"}, + blobToVertex( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"inlineData"})), + toObject)); + } + + if (Common.getValueByPath(fromObject, new String[] {"fileData"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"fileData"}, + fileDataToVertex( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"fileData"})), + toObject)); + } + + if (Common.getValueByPath(fromObject, new String[] {"thoughtSignature"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"thoughtSignature"}, + Common.getValueByPath(fromObject, new String[] {"thoughtSignature"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"codeExecutionResult"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"codeExecutionResult"}, + Common.getValueByPath(fromObject, new String[] {"codeExecutionResult"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"executableCode"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"executableCode"}, + Common.getValueByPath(fromObject, new String[] {"executableCode"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"functionCall"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"functionCall"}, + Common.getValueByPath(fromObject, new String[] {"functionCall"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"functionResponse"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"functionResponse"}, + Common.getValueByPath(fromObject, new String[] {"functionResponse"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"text"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"text"}, + Common.getValueByPath(fromObject, new String[] {"text"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode contentToVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"parts"}) != null) { + ArrayNode keyArray = (ArrayNode) Common.getValueByPath(fromObject, new String[] {"parts"}); + ObjectMapper objectMapper = new ObjectMapper(); + ArrayNode result = objectMapper.createArrayNode(); + + for (JsonNode item : keyArray) { + result.add(partToVertex(JsonSerializable.toJsonNode(item), toObject)); + } + Common.setValueByPath(toObject, new String[] {"parts"}, result); + } + + if (Common.getValueByPath(fromObject, new String[] {"role"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"role"}, + Common.getValueByPath(fromObject, new String[] {"role"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode functionDeclarationToVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"behavior"}))) { + throw new IllegalArgumentException("behavior parameter is not supported in Vertex AI."); + } + + if (Common.getValueByPath(fromObject, new String[] {"description"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"description"}, + Common.getValueByPath(fromObject, new String[] {"description"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"name"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"name"}, + Common.getValueByPath(fromObject, new String[] {"name"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"parameters"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"parameters"}, + Common.getValueByPath(fromObject, new String[] {"parameters"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"parametersJsonSchema"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"parametersJsonSchema"}, + Common.getValueByPath(fromObject, new String[] {"parametersJsonSchema"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"response"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"response"}, + Common.getValueByPath(fromObject, new String[] {"response"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"responseJsonSchema"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"responseJsonSchema"}, + Common.getValueByPath(fromObject, new String[] {"responseJsonSchema"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode intervalToVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"startTime"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"startTime"}, + Common.getValueByPath(fromObject, new String[] {"startTime"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"endTime"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"endTime"}, + Common.getValueByPath(fromObject, new String[] {"endTime"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode googleSearchToVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"timeRangeFilter"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"timeRangeFilter"}, + intervalToVertex( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"timeRangeFilter"})), + toObject)); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode dynamicRetrievalConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"mode"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"mode"}, + Common.getValueByPath(fromObject, new String[] {"mode"})); } - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode googleSearchRetrievalToMldev(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"dynamicRetrievalConfig"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"dynamicThreshold"}) != null) { Common.setValueByPath( toObject, - new String[] {"dynamicRetrievalConfig"}, - dynamicRetrievalConfigToMldev( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"dynamicRetrievalConfig"})), - toObject)); + new String[] {"dynamicThreshold"}, + Common.getValueByPath(fromObject, new String[] {"dynamicThreshold"})); } return toObject; @@ -837,13 +1598,6 @@ ObjectNode googleSearchRetrievalToVertex(JsonNode fromObject, ObjectNode parentO return toObject; } - @ExcludeFromGeneratedCoverageReport - ObjectNode enterpriseWebSearchToMldev(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - - return toObject; - } - @ExcludeFromGeneratedCoverageReport ObjectNode enterpriseWebSearchToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); @@ -851,16 +1605,6 @@ ObjectNode enterpriseWebSearchToVertex(JsonNode fromObject, ObjectNode parentObj return toObject; } - @ExcludeFromGeneratedCoverageReport - ObjectNode apiKeyConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"apiKeyString"}))) { - throw new IllegalArgumentException("apiKeyString parameter is not supported in Gemini API."); - } - - return toObject; - } - @ExcludeFromGeneratedCoverageReport ObjectNode apiKeyConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); @@ -874,51 +1618,6 @@ ObjectNode apiKeyConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { return toObject; } - @ExcludeFromGeneratedCoverageReport - ObjectNode authConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"apiKeyConfig"}))) { - throw new IllegalArgumentException("apiKeyConfig parameter is not supported in Gemini API."); - } - - if (Common.getValueByPath(fromObject, new String[] {"authType"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"authType"}, - Common.getValueByPath(fromObject, new String[] {"authType"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"googleServiceAccountConfig"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"googleServiceAccountConfig"}, - Common.getValueByPath(fromObject, new String[] {"googleServiceAccountConfig"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"httpBasicAuthConfig"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"httpBasicAuthConfig"}, - Common.getValueByPath(fromObject, new String[] {"httpBasicAuthConfig"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"oauthConfig"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"oauthConfig"}, - Common.getValueByPath(fromObject, new String[] {"oauthConfig"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"oidcConfig"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"oidcConfig"}, - Common.getValueByPath(fromObject, new String[] {"oidcConfig"})); - } - - return toObject; - } - @ExcludeFromGeneratedCoverageReport ObjectNode authConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); @@ -970,16 +1669,6 @@ ObjectNode authConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { return toObject; } - @ExcludeFromGeneratedCoverageReport - ObjectNode googleMapsToMldev(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"authConfig"}))) { - throw new IllegalArgumentException("authConfig parameter is not supported in Gemini API."); - } - - return toObject; - } - @ExcludeFromGeneratedCoverageReport ObjectNode googleMapsToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); @@ -996,13 +1685,6 @@ ObjectNode googleMapsToVertex(JsonNode fromObject, ObjectNode parentObject) { return toObject; } - @ExcludeFromGeneratedCoverageReport - ObjectNode urlContextToMldev(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - - return toObject; - } - @ExcludeFromGeneratedCoverageReport ObjectNode urlContextToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); @@ -1010,81 +1692,6 @@ ObjectNode urlContextToVertex(JsonNode fromObject, ObjectNode parentObject) { return toObject; } - @ExcludeFromGeneratedCoverageReport - ObjectNode toolToMldev(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"functionDeclarations"}) != null) { - ArrayNode keyArray = - (ArrayNode) Common.getValueByPath(fromObject, new String[] {"functionDeclarations"}); - ObjectMapper objectMapper = new ObjectMapper(); - ArrayNode result = objectMapper.createArrayNode(); - - for (JsonNode item : keyArray) { - result.add(functionDeclarationToMldev(JsonSerializable.toJsonNode(item), toObject)); - } - Common.setValueByPath(toObject, new String[] {"functionDeclarations"}, result); - } - - if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"retrieval"}))) { - throw new IllegalArgumentException("retrieval parameter is not supported in Gemini API."); - } - - if (Common.getValueByPath(fromObject, new String[] {"googleSearch"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"googleSearch"}, - googleSearchToMldev( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"googleSearch"})), - toObject)); - } - - if (Common.getValueByPath(fromObject, new String[] {"googleSearchRetrieval"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"googleSearchRetrieval"}, - googleSearchRetrievalToMldev( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"googleSearchRetrieval"})), - toObject)); - } - - if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"enterpriseWebSearch"}))) { - throw new IllegalArgumentException( - "enterpriseWebSearch parameter is not supported in Gemini API."); - } - - if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"googleMaps"}))) { - throw new IllegalArgumentException("googleMaps parameter is not supported in Gemini API."); - } - - if (Common.getValueByPath(fromObject, new String[] {"urlContext"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"urlContext"}, - urlContextToMldev( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"urlContext"})), - toObject)); - } - - if (Common.getValueByPath(fromObject, new String[] {"codeExecution"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"codeExecution"}, - Common.getValueByPath(fromObject, new String[] {"codeExecution"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"computerUse"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"computerUse"}, - Common.getValueByPath(fromObject, new String[] {"computerUse"})); - } - - return toObject; - } - @ExcludeFromGeneratedCoverageReport ObjectNode toolToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); @@ -1174,23 +1781,6 @@ ObjectNode toolToVertex(JsonNode fromObject, ObjectNode parentObject) { return toObject; } - @ExcludeFromGeneratedCoverageReport - ObjectNode sessionResumptionConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"handle"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"handle"}, - Common.getValueByPath(fromObject, new String[] {"handle"})); - } - - if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"transparent"}))) { - throw new IllegalArgumentException("transparent parameter is not supported in Gemini API."); - } - - return toObject; - } - @ExcludeFromGeneratedCoverageReport ObjectNode sessionResumptionConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); @@ -1211,13 +1801,6 @@ ObjectNode sessionResumptionConfigToVertex(JsonNode fromObject, ObjectNode paren return toObject; } - @ExcludeFromGeneratedCoverageReport - ObjectNode audioTranscriptionConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - - return toObject; - } - @ExcludeFromGeneratedCoverageReport ObjectNode audioTranscriptionConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); @@ -1225,47 +1808,6 @@ ObjectNode audioTranscriptionConfigToVertex(JsonNode fromObject, ObjectNode pare return toObject; } - @ExcludeFromGeneratedCoverageReport - ObjectNode automaticActivityDetectionToMldev(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"disabled"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"disabled"}, - Common.getValueByPath(fromObject, new String[] {"disabled"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"startOfSpeechSensitivity"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"startOfSpeechSensitivity"}, - Common.getValueByPath(fromObject, new String[] {"startOfSpeechSensitivity"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"endOfSpeechSensitivity"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"endOfSpeechSensitivity"}, - Common.getValueByPath(fromObject, new String[] {"endOfSpeechSensitivity"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"prefixPaddingMs"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"prefixPaddingMs"}, - Common.getValueByPath(fromObject, new String[] {"prefixPaddingMs"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"silenceDurationMs"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"silenceDurationMs"}, - Common.getValueByPath(fromObject, new String[] {"silenceDurationMs"})); - } - - return toObject; - } - @ExcludeFromGeneratedCoverageReport ObjectNode automaticActivityDetectionToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); @@ -1293,45 +1835,15 @@ ObjectNode automaticActivityDetectionToVertex(JsonNode fromObject, ObjectNode pa if (Common.getValueByPath(fromObject, new String[] {"prefixPaddingMs"}) != null) { Common.setValueByPath( toObject, - new String[] {"prefixPaddingMs"}, - Common.getValueByPath(fromObject, new String[] {"prefixPaddingMs"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"silenceDurationMs"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"silenceDurationMs"}, - Common.getValueByPath(fromObject, new String[] {"silenceDurationMs"})); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode realtimeInputConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"automaticActivityDetection"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"automaticActivityDetection"}, - automaticActivityDetectionToMldev( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"automaticActivityDetection"})), - toObject)); - } - - if (Common.getValueByPath(fromObject, new String[] {"activityHandling"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"activityHandling"}, - Common.getValueByPath(fromObject, new String[] {"activityHandling"})); + new String[] {"prefixPaddingMs"}, + Common.getValueByPath(fromObject, new String[] {"prefixPaddingMs"})); } - if (Common.getValueByPath(fromObject, new String[] {"turnCoverage"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"silenceDurationMs"}) != null) { Common.setValueByPath( toObject, - new String[] {"turnCoverage"}, - Common.getValueByPath(fromObject, new String[] {"turnCoverage"})); + new String[] {"silenceDurationMs"}, + Common.getValueByPath(fromObject, new String[] {"silenceDurationMs"})); } return toObject; @@ -1367,19 +1879,6 @@ ObjectNode realtimeInputConfigToVertex(JsonNode fromObject, ObjectNode parentObj return toObject; } - @ExcludeFromGeneratedCoverageReport - ObjectNode slidingWindowToMldev(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"targetTokens"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"targetTokens"}, - Common.getValueByPath(fromObject, new String[] {"targetTokens"})); - } - - return toObject; - } - @ExcludeFromGeneratedCoverageReport ObjectNode slidingWindowToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); @@ -1393,29 +1892,6 @@ ObjectNode slidingWindowToVertex(JsonNode fromObject, ObjectNode parentObject) { return toObject; } - @ExcludeFromGeneratedCoverageReport - ObjectNode contextWindowCompressionConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"triggerTokens"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"triggerTokens"}, - Common.getValueByPath(fromObject, new String[] {"triggerTokens"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"slidingWindow"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"slidingWindow"}, - slidingWindowToMldev( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"slidingWindow"})), - toObject)); - } - - return toObject; - } - @ExcludeFromGeneratedCoverageReport ObjectNode contextWindowCompressionConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); @@ -1439,19 +1915,6 @@ ObjectNode contextWindowCompressionConfigToVertex(JsonNode fromObject, ObjectNod return toObject; } - @ExcludeFromGeneratedCoverageReport - ObjectNode proactivityConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"proactiveAudio"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"proactiveAudio"}, - Common.getValueByPath(fromObject, new String[] {"proactiveAudio"})); - } - - return toObject; - } - @ExcludeFromGeneratedCoverageReport ObjectNode proactivityConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); @@ -1466,7 +1929,7 @@ ObjectNode proactivityConfigToVertex(JsonNode fromObject, ObjectNode parentObjec } @ExcludeFromGeneratedCoverageReport - ObjectNode liveConnectConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode liveConnectConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"responseModalities"}) != null) { @@ -1522,7 +1985,7 @@ ObjectNode liveConnectConfigToMldev(JsonNode fromObject, ObjectNode parentObject Common.setValueByPath( parentObject, new String[] {"setup", "generationConfig", "speechConfig"}, - speechConfigToMldev( + speechConfigToVertex( JsonSerializable.toJsonNode( Transformers.tLiveSpeechConfig( Common.getValueByPath(fromObject, new String[] {"speechConfig"}))), @@ -1540,7 +2003,7 @@ ObjectNode liveConnectConfigToMldev(JsonNode fromObject, ObjectNode parentObject Common.setValueByPath( parentObject, new String[] {"setup", "systemInstruction"}, - contentToMldev( + contentToVertex( JsonSerializable.toJsonNode( Transformers.tContent( Common.getValueByPath(fromObject, new String[] {"systemInstruction"}))), @@ -1555,7 +2018,7 @@ ObjectNode liveConnectConfigToMldev(JsonNode fromObject, ObjectNode parentObject ArrayNode result = objectMapper.createArrayNode(); for (JsonNode item : keyArray) { - result.add(toolToMldev(JsonSerializable.toJsonNode(Transformers.tTool(item)), toObject)); + result.add(toolToVertex(JsonSerializable.toJsonNode(Transformers.tTool(item)), toObject)); } Common.setValueByPath(parentObject, new String[] {"setup", "tools"}, result); } @@ -1564,7 +2027,7 @@ ObjectNode liveConnectConfigToMldev(JsonNode fromObject, ObjectNode parentObject Common.setValueByPath( parentObject, new String[] {"setup", "sessionResumption"}, - sessionResumptionConfigToMldev( + sessionResumptionConfigToVertex( JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"sessionResumption"})), toObject)); @@ -1574,7 +2037,7 @@ ObjectNode liveConnectConfigToMldev(JsonNode fromObject, ObjectNode parentObject Common.setValueByPath( parentObject, new String[] {"setup", "inputAudioTranscription"}, - audioTranscriptionConfigToMldev( + audioTranscriptionConfigToVertex( JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"inputAudioTranscription"})), toObject)); @@ -1584,7 +2047,7 @@ ObjectNode liveConnectConfigToMldev(JsonNode fromObject, ObjectNode parentObject Common.setValueByPath( parentObject, new String[] {"setup", "outputAudioTranscription"}, - audioTranscriptionConfigToMldev( + audioTranscriptionConfigToVertex( JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"outputAudioTranscription"})), toObject)); @@ -1594,7 +2057,7 @@ ObjectNode liveConnectConfigToMldev(JsonNode fromObject, ObjectNode parentObject Common.setValueByPath( parentObject, new String[] {"setup", "realtimeInputConfig"}, - realtimeInputConfigToMldev( + realtimeInputConfigToVertex( JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"realtimeInputConfig"})), toObject)); @@ -1604,7 +2067,7 @@ ObjectNode liveConnectConfigToMldev(JsonNode fromObject, ObjectNode parentObject Common.setValueByPath( parentObject, new String[] {"setup", "contextWindowCompression"}, - contextWindowCompressionConfigToMldev( + contextWindowCompressionConfigToVertex( JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"contextWindowCompression"})), toObject)); @@ -1614,7 +2077,7 @@ ObjectNode liveConnectConfigToMldev(JsonNode fromObject, ObjectNode parentObject Common.setValueByPath( parentObject, new String[] {"setup", "proactivity"}, - proactivityConfigToMldev( + proactivityConfigToVertex( JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"proactivity"})), toObject)); @@ -1624,80 +2087,126 @@ ObjectNode liveConnectConfigToMldev(JsonNode fromObject, ObjectNode parentObject } @ExcludeFromGeneratedCoverageReport - ObjectNode liveConnectConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode liveConnectParametersToVertex( + ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"model"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"setup", "model"}, + Transformers.tModel( + this.apiClient, Common.getValueByPath(fromObject, new String[] {"model"}))); + } - if (Common.getValueByPath(fromObject, new String[] {"responseModalities"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"config"}) != null) { Common.setValueByPath( - parentObject, - new String[] {"setup", "generationConfig", "responseModalities"}, - Common.getValueByPath(fromObject, new String[] {"responseModalities"})); + toObject, + new String[] {"config"}, + liveConnectConfigToVertex( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"config"})), + toObject)); } - if (Common.getValueByPath(fromObject, new String[] {"temperature"}) != null) { + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode activityStartToVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode activityEndToVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode liveSendRealtimeInputParametersToVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"media"}) != null) { Common.setValueByPath( - parentObject, - new String[] {"setup", "generationConfig", "temperature"}, - Common.getValueByPath(fromObject, new String[] {"temperature"})); + toObject, + new String[] {"mediaChunks"}, + Transformers.tBlobs(Common.getValueByPath(fromObject, new String[] {"media"}))); } - if (Common.getValueByPath(fromObject, new String[] {"topP"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"audio"}) != null) { Common.setValueByPath( - parentObject, - new String[] {"setup", "generationConfig", "topP"}, - Common.getValueByPath(fromObject, new String[] {"topP"})); + toObject, + new String[] {"audio"}, + Transformers.tAudioBlob(Common.getValueByPath(fromObject, new String[] {"audio"}))); } - if (Common.getValueByPath(fromObject, new String[] {"topK"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"audioStreamEnd"}) != null) { Common.setValueByPath( - parentObject, - new String[] {"setup", "generationConfig", "topK"}, - Common.getValueByPath(fromObject, new String[] {"topK"})); + toObject, + new String[] {"audioStreamEnd"}, + Common.getValueByPath(fromObject, new String[] {"audioStreamEnd"})); } - if (Common.getValueByPath(fromObject, new String[] {"maxOutputTokens"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"video"}) != null) { Common.setValueByPath( - parentObject, - new String[] {"setup", "generationConfig", "maxOutputTokens"}, - Common.getValueByPath(fromObject, new String[] {"maxOutputTokens"})); + toObject, + new String[] {"video"}, + Transformers.tImageBlob(Common.getValueByPath(fromObject, new String[] {"video"}))); } - if (Common.getValueByPath(fromObject, new String[] {"mediaResolution"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"text"}) != null) { Common.setValueByPath( - parentObject, - new String[] {"setup", "generationConfig", "mediaResolution"}, - Common.getValueByPath(fromObject, new String[] {"mediaResolution"})); + toObject, + new String[] {"text"}, + Common.getValueByPath(fromObject, new String[] {"text"})); } - if (Common.getValueByPath(fromObject, new String[] {"seed"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"activityStart"}) != null) { Common.setValueByPath( - parentObject, - new String[] {"setup", "generationConfig", "seed"}, - Common.getValueByPath(fromObject, new String[] {"seed"})); + toObject, + new String[] {"activityStart"}, + activityStartToVertex( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"activityStart"})), + toObject)); } - if (Common.getValueByPath(fromObject, new String[] {"speechConfig"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"activityEnd"}) != null) { Common.setValueByPath( - parentObject, - new String[] {"setup", "generationConfig", "speechConfig"}, - speechConfigToVertex( + toObject, + new String[] {"activityEnd"}, + activityEndToVertex( JsonSerializable.toJsonNode( - Transformers.tLiveSpeechConfig( - Common.getValueByPath(fromObject, new String[] {"speechConfig"}))), + Common.getValueByPath(fromObject, new String[] {"activityEnd"})), toObject)); } - if (Common.getValueByPath(fromObject, new String[] {"enableAffectiveDialog"}) != null) { + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode liveClientSetupToVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"model"}) != null) { Common.setValueByPath( - parentObject, - new String[] {"setup", "generationConfig", "enableAffectiveDialog"}, - Common.getValueByPath(fromObject, new String[] {"enableAffectiveDialog"})); + toObject, + new String[] {"model"}, + Common.getValueByPath(fromObject, new String[] {"model"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"generationConfig"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"generationConfig"}, + Common.getValueByPath(fromObject, new String[] {"generationConfig"})); } if (Common.getValueByPath(fromObject, new String[] {"systemInstruction"}) != null) { Common.setValueByPath( - parentObject, - new String[] {"setup", "systemInstruction"}, + toObject, + new String[] {"systemInstruction"}, contentToVertex( JsonSerializable.toJsonNode( Transformers.tContent( @@ -1715,116 +2224,66 @@ ObjectNode liveConnectConfigToVertex(JsonNode fromObject, ObjectNode parentObjec for (JsonNode item : keyArray) { result.add(toolToVertex(JsonSerializable.toJsonNode(Transformers.tTool(item)), toObject)); } - Common.setValueByPath(parentObject, new String[] {"setup", "tools"}, result); - } - - if (Common.getValueByPath(fromObject, new String[] {"sessionResumption"}) != null) { - Common.setValueByPath( - parentObject, - new String[] {"setup", "sessionResumption"}, - sessionResumptionConfigToVertex( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"sessionResumption"})), - toObject)); - } - - if (Common.getValueByPath(fromObject, new String[] {"inputAudioTranscription"}) != null) { - Common.setValueByPath( - parentObject, - new String[] {"setup", "inputAudioTranscription"}, - audioTranscriptionConfigToVertex( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"inputAudioTranscription"})), - toObject)); - } - - if (Common.getValueByPath(fromObject, new String[] {"outputAudioTranscription"}) != null) { - Common.setValueByPath( - parentObject, - new String[] {"setup", "outputAudioTranscription"}, - audioTranscriptionConfigToVertex( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"outputAudioTranscription"})), - toObject)); + Common.setValueByPath(toObject, new String[] {"tools"}, result); } if (Common.getValueByPath(fromObject, new String[] {"realtimeInputConfig"}) != null) { Common.setValueByPath( - parentObject, - new String[] {"setup", "realtimeInputConfig"}, + toObject, + new String[] {"realtimeInputConfig"}, realtimeInputConfigToVertex( JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"realtimeInputConfig"})), toObject)); } - if (Common.getValueByPath(fromObject, new String[] {"contextWindowCompression"}) != null) { - Common.setValueByPath( - parentObject, - new String[] {"setup", "contextWindowCompression"}, - contextWindowCompressionConfigToVertex( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"contextWindowCompression"})), - toObject)); - } - - if (Common.getValueByPath(fromObject, new String[] {"proactivity"}) != null) { - Common.setValueByPath( - parentObject, - new String[] {"setup", "proactivity"}, - proactivityConfigToVertex( + if (Common.getValueByPath(fromObject, new String[] {"sessionResumption"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"sessionResumption"}, + sessionResumptionConfigToVertex( JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"proactivity"})), + Common.getValueByPath(fromObject, new String[] {"sessionResumption"})), toObject)); } - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode liveConnectParametersToMldev( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"model"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"contextWindowCompression"}) != null) { Common.setValueByPath( toObject, - new String[] {"setup", "model"}, - Transformers.tModel( - this.apiClient, Common.getValueByPath(fromObject, new String[] {"model"}))); + new String[] {"contextWindowCompression"}, + contextWindowCompressionConfigToVertex( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"contextWindowCompression"})), + toObject)); } - if (Common.getValueByPath(fromObject, new String[] {"config"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"inputAudioTranscription"}) != null) { Common.setValueByPath( toObject, - new String[] {"config"}, - liveConnectConfigToMldev( + new String[] {"inputAudioTranscription"}, + audioTranscriptionConfigToVertex( JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"config"})), + Common.getValueByPath(fromObject, new String[] {"inputAudioTranscription"})), toObject)); } - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode liveConnectParametersToVertex( - ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"model"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"outputAudioTranscription"}) != null) { Common.setValueByPath( toObject, - new String[] {"setup", "model"}, - Transformers.tModel( - this.apiClient, Common.getValueByPath(fromObject, new String[] {"model"}))); + new String[] {"outputAudioTranscription"}, + audioTranscriptionConfigToVertex( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"outputAudioTranscription"})), + toObject)); } - if (Common.getValueByPath(fromObject, new String[] {"config"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"proactivity"}) != null) { Common.setValueByPath( toObject, - new String[] {"config"}, - liveConnectConfigToVertex( + new String[] {"proactivity"}, + proactivityConfigToVertex( JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"config"})), + Common.getValueByPath(fromObject, new String[] {"proactivity"})), toObject)); } @@ -1832,62 +2291,55 @@ ObjectNode liveConnectParametersToVertex( } @ExcludeFromGeneratedCoverageReport - ObjectNode activityStartToMldev(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode activityStartToVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode activityEndToMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode liveClientContentToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"turns"}) != null) { + ArrayNode keyArray = (ArrayNode) Common.getValueByPath(fromObject, new String[] {"turns"}); + ObjectMapper objectMapper = new ObjectMapper(); + ArrayNode result = objectMapper.createArrayNode(); - return toObject; - } + for (JsonNode item : keyArray) { + result.add(contentToVertex(JsonSerializable.toJsonNode(item), toObject)); + } + Common.setValueByPath(toObject, new String[] {"turns"}, result); + } - @ExcludeFromGeneratedCoverageReport - ObjectNode activityEndToVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"turnComplete"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"turnComplete"}, + Common.getValueByPath(fromObject, new String[] {"turnComplete"})); + } return toObject; } @ExcludeFromGeneratedCoverageReport - ObjectNode liveSendRealtimeInputParametersToMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode liveClientRealtimeInputToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"media"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"mediaChunks"}) != null) { Common.setValueByPath( toObject, new String[] {"mediaChunks"}, - Transformers.tBlobs(Common.getValueByPath(fromObject, new String[] {"media"}))); + Common.getValueByPath(fromObject, new String[] {"mediaChunks"})); } if (Common.getValueByPath(fromObject, new String[] {"audio"}) != null) { Common.setValueByPath( toObject, new String[] {"audio"}, - Transformers.tAudioBlob(Common.getValueByPath(fromObject, new String[] {"audio"}))); + Common.getValueByPath(fromObject, new String[] {"audio"})); } - if (Common.getValueByPath(fromObject, new String[] {"audioStreamEnd"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"audioStreamEnd"}, - Common.getValueByPath(fromObject, new String[] {"audioStreamEnd"})); + if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"audioStreamEnd"}))) { + throw new IllegalArgumentException("audioStreamEnd parameter is not supported in Vertex AI."); } if (Common.getValueByPath(fromObject, new String[] {"video"}) != null) { Common.setValueByPath( toObject, new String[] {"video"}, - Transformers.tImageBlob(Common.getValueByPath(fromObject, new String[] {"video"}))); + Common.getValueByPath(fromObject, new String[] {"video"})); } if (Common.getValueByPath(fromObject, new String[] {"text"}) != null) { @@ -1901,7 +2353,7 @@ ObjectNode liveSendRealtimeInputParametersToMldev(JsonNode fromObject, ObjectNod Common.setValueByPath( toObject, new String[] {"activityStart"}, - activityStartToMldev( + activityStartToVertex( JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"activityStart"})), toObject)); @@ -1911,7 +2363,7 @@ ObjectNode liveSendRealtimeInputParametersToMldev(JsonNode fromObject, ObjectNod Common.setValueByPath( toObject, new String[] {"activityEnd"}, - activityEndToMldev( + activityEndToVertex( JsonSerializable.toJsonNode( Common.getValueByPath(fromObject, new String[] {"activityEnd"})), toObject)); @@ -1921,60 +2373,106 @@ ObjectNode liveSendRealtimeInputParametersToMldev(JsonNode fromObject, ObjectNod } @ExcludeFromGeneratedCoverageReport - ObjectNode liveSendRealtimeInputParametersToVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode functionResponseToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"media"}) != null) { + if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"willContinue"}))) { + throw new IllegalArgumentException("willContinue parameter is not supported in Vertex AI."); + } + + if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"scheduling"}))) { + throw new IllegalArgumentException("scheduling parameter is not supported in Vertex AI."); + } + + if (Common.getValueByPath(fromObject, new String[] {"id"}) != null) { + Common.setValueByPath( + toObject, new String[] {"id"}, Common.getValueByPath(fromObject, new String[] {"id"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"name"}) != null) { Common.setValueByPath( toObject, - new String[] {"mediaChunks"}, - Transformers.tBlobs(Common.getValueByPath(fromObject, new String[] {"media"}))); + new String[] {"name"}, + Common.getValueByPath(fromObject, new String[] {"name"})); } - if (Common.getValueByPath(fromObject, new String[] {"audio"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"response"}) != null) { Common.setValueByPath( toObject, - new String[] {"audio"}, - Transformers.tAudioBlob(Common.getValueByPath(fromObject, new String[] {"audio"}))); + new String[] {"response"}, + Common.getValueByPath(fromObject, new String[] {"response"})); } - if (Common.getValueByPath(fromObject, new String[] {"audioStreamEnd"}) != null) { + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode liveClientToolResponseToVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"functionResponses"}) != null) { + ArrayNode keyArray = + (ArrayNode) Common.getValueByPath(fromObject, new String[] {"functionResponses"}); + ObjectMapper objectMapper = new ObjectMapper(); + ArrayNode result = objectMapper.createArrayNode(); + + for (JsonNode item : keyArray) { + result.add(functionResponseToVertex(JsonSerializable.toJsonNode(item), toObject)); + } + Common.setValueByPath(toObject, new String[] {"functionResponses"}, result); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode liveClientMessageToVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"setup"}) != null) { Common.setValueByPath( toObject, - new String[] {"audioStreamEnd"}, - Common.getValueByPath(fromObject, new String[] {"audioStreamEnd"})); + new String[] {"setup"}, + liveClientSetupToVertex( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"setup"})), + toObject)); } - if (Common.getValueByPath(fromObject, new String[] {"video"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"clientContent"}) != null) { Common.setValueByPath( toObject, - new String[] {"video"}, - Transformers.tImageBlob(Common.getValueByPath(fromObject, new String[] {"video"}))); + new String[] {"clientContent"}, + liveClientContentToVertex( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"clientContent"})), + toObject)); } - if (Common.getValueByPath(fromObject, new String[] {"text"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"realtimeInput"}) != null) { Common.setValueByPath( toObject, - new String[] {"text"}, - Common.getValueByPath(fromObject, new String[] {"text"})); + new String[] {"realtimeInput"}, + liveClientRealtimeInputToVertex( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"realtimeInput"})), + toObject)); } - if (Common.getValueByPath(fromObject, new String[] {"activityStart"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"realtimeInputParameters"}) != null) { Common.setValueByPath( toObject, - new String[] {"activityStart"}, - activityStartToVertex( + new String[] {"realtime_input"}, + liveSendRealtimeInputParametersToVertex( JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"activityStart"})), + Common.getValueByPath(fromObject, new String[] {"realtimeInputParameters"})), toObject)); } - if (Common.getValueByPath(fromObject, new String[] {"activityEnd"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"toolResponse"}) != null) { Common.setValueByPath( toObject, - new String[] {"activityEnd"}, - activityEndToVertex( + new String[] {"toolResponse"}, + liveClientToolResponseToVertex( JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"activityEnd"})), + Common.getValueByPath(fromObject, new String[] {"toolResponse"})), toObject)); } @@ -1982,316 +2480,314 @@ ObjectNode liveSendRealtimeInputParametersToVertex(JsonNode fromObject, ObjectNo } @ExcludeFromGeneratedCoverageReport - ObjectNode liveClientSetupToMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode liveServerSetupCompleteFromMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode videoMetadataFromMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"fps"}) != null) { + Common.setValueByPath( + toObject, new String[] {"fps"}, Common.getValueByPath(fromObject, new String[] {"fps"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"endOffset"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"endOffset"}, + Common.getValueByPath(fromObject, new String[] {"endOffset"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"startOffset"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"startOffset"}, + Common.getValueByPath(fromObject, new String[] {"startOffset"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode blobFromMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + + if (Common.getValueByPath(fromObject, new String[] {"data"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"data"}, + Common.getValueByPath(fromObject, new String[] {"data"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"mimeType"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"mimeType"}, + Common.getValueByPath(fromObject, new String[] {"mimeType"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode fileDataFromMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"model"}) != null) { + + if (Common.getValueByPath(fromObject, new String[] {"fileUri"}) != null) { Common.setValueByPath( toObject, - new String[] {"model"}, - Common.getValueByPath(fromObject, new String[] {"model"})); + new String[] {"fileUri"}, + Common.getValueByPath(fromObject, new String[] {"fileUri"})); } - if (Common.getValueByPath(fromObject, new String[] {"generationConfig"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"mimeType"}) != null) { Common.setValueByPath( toObject, - new String[] {"generationConfig"}, - Common.getValueByPath(fromObject, new String[] {"generationConfig"})); + new String[] {"mimeType"}, + Common.getValueByPath(fromObject, new String[] {"mimeType"})); } - if (Common.getValueByPath(fromObject, new String[] {"systemInstruction"}) != null) { + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode partFromMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"videoMetadata"}) != null) { Common.setValueByPath( toObject, - new String[] {"systemInstruction"}, - contentToMldev( + new String[] {"videoMetadata"}, + videoMetadataFromMldev( JsonSerializable.toJsonNode( - Transformers.tContent( - Common.getValueByPath(fromObject, new String[] {"systemInstruction"}))), + Common.getValueByPath(fromObject, new String[] {"videoMetadata"})), toObject)); } - if (Common.getValueByPath(fromObject, new String[] {"tools"}) != null) { - ArrayNode keyArray = - (ArrayNode) - Transformers.tTools(Common.getValueByPath(fromObject, new String[] {"tools"})); - ObjectMapper objectMapper = new ObjectMapper(); - ArrayNode result = objectMapper.createArrayNode(); - - for (JsonNode item : keyArray) { - result.add(toolToMldev(JsonSerializable.toJsonNode(Transformers.tTool(item)), toObject)); - } - Common.setValueByPath(toObject, new String[] {"tools"}, result); - } - - if (Common.getValueByPath(fromObject, new String[] {"realtimeInputConfig"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"thought"}) != null) { Common.setValueByPath( toObject, - new String[] {"realtimeInputConfig"}, - realtimeInputConfigToMldev( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"realtimeInputConfig"})), - toObject)); + new String[] {"thought"}, + Common.getValueByPath(fromObject, new String[] {"thought"})); } - if (Common.getValueByPath(fromObject, new String[] {"sessionResumption"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"inlineData"}) != null) { Common.setValueByPath( toObject, - new String[] {"sessionResumption"}, - sessionResumptionConfigToMldev( + new String[] {"inlineData"}, + blobFromMldev( JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"sessionResumption"})), + Common.getValueByPath(fromObject, new String[] {"inlineData"})), toObject)); } - if (Common.getValueByPath(fromObject, new String[] {"contextWindowCompression"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"fileData"}) != null) { Common.setValueByPath( toObject, - new String[] {"contextWindowCompression"}, - contextWindowCompressionConfigToMldev( + new String[] {"fileData"}, + fileDataFromMldev( JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"contextWindowCompression"})), + Common.getValueByPath(fromObject, new String[] {"fileData"})), toObject)); } - if (Common.getValueByPath(fromObject, new String[] {"inputAudioTranscription"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"thoughtSignature"}) != null) { Common.setValueByPath( toObject, - new String[] {"inputAudioTranscription"}, - audioTranscriptionConfigToMldev( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"inputAudioTranscription"})), - toObject)); + new String[] {"thoughtSignature"}, + Common.getValueByPath(fromObject, new String[] {"thoughtSignature"})); } - if (Common.getValueByPath(fromObject, new String[] {"outputAudioTranscription"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"codeExecutionResult"}) != null) { Common.setValueByPath( toObject, - new String[] {"outputAudioTranscription"}, - audioTranscriptionConfigToMldev( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"outputAudioTranscription"})), - toObject)); + new String[] {"codeExecutionResult"}, + Common.getValueByPath(fromObject, new String[] {"codeExecutionResult"})); } - if (Common.getValueByPath(fromObject, new String[] {"proactivity"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"executableCode"}) != null) { Common.setValueByPath( toObject, - new String[] {"proactivity"}, - proactivityConfigToMldev( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"proactivity"})), - toObject)); + new String[] {"executableCode"}, + Common.getValueByPath(fromObject, new String[] {"executableCode"})); } - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode liveClientSetupToVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"model"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"functionCall"}) != null) { Common.setValueByPath( toObject, - new String[] {"model"}, - Common.getValueByPath(fromObject, new String[] {"model"})); + new String[] {"functionCall"}, + Common.getValueByPath(fromObject, new String[] {"functionCall"})); } - if (Common.getValueByPath(fromObject, new String[] {"generationConfig"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"functionResponse"}) != null) { Common.setValueByPath( toObject, - new String[] {"generationConfig"}, - Common.getValueByPath(fromObject, new String[] {"generationConfig"})); + new String[] {"functionResponse"}, + Common.getValueByPath(fromObject, new String[] {"functionResponse"})); } - if (Common.getValueByPath(fromObject, new String[] {"systemInstruction"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"text"}) != null) { Common.setValueByPath( toObject, - new String[] {"systemInstruction"}, - contentToVertex( - JsonSerializable.toJsonNode( - Transformers.tContent( - Common.getValueByPath(fromObject, new String[] {"systemInstruction"}))), - toObject)); + new String[] {"text"}, + Common.getValueByPath(fromObject, new String[] {"text"})); } - if (Common.getValueByPath(fromObject, new String[] {"tools"}) != null) { - ArrayNode keyArray = - (ArrayNode) - Transformers.tTools(Common.getValueByPath(fromObject, new String[] {"tools"})); + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode contentFromMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"parts"}) != null) { + ArrayNode keyArray = (ArrayNode) Common.getValueByPath(fromObject, new String[] {"parts"}); ObjectMapper objectMapper = new ObjectMapper(); ArrayNode result = objectMapper.createArrayNode(); for (JsonNode item : keyArray) { - result.add(toolToVertex(JsonSerializable.toJsonNode(Transformers.tTool(item)), toObject)); + result.add(partFromMldev(JsonSerializable.toJsonNode(item), toObject)); } - Common.setValueByPath(toObject, new String[] {"tools"}, result); - } - - if (Common.getValueByPath(fromObject, new String[] {"realtimeInputConfig"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"realtimeInputConfig"}, - realtimeInputConfigToVertex( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"realtimeInputConfig"})), - toObject)); - } - - if (Common.getValueByPath(fromObject, new String[] {"sessionResumption"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"sessionResumption"}, - sessionResumptionConfigToVertex( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"sessionResumption"})), - toObject)); + Common.setValueByPath(toObject, new String[] {"parts"}, result); } - if (Common.getValueByPath(fromObject, new String[] {"contextWindowCompression"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"role"}) != null) { Common.setValueByPath( toObject, - new String[] {"contextWindowCompression"}, - contextWindowCompressionConfigToVertex( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"contextWindowCompression"})), - toObject)); + new String[] {"role"}, + Common.getValueByPath(fromObject, new String[] {"role"})); } - if (Common.getValueByPath(fromObject, new String[] {"inputAudioTranscription"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"inputAudioTranscription"}, - audioTranscriptionConfigToVertex( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"inputAudioTranscription"})), - toObject)); - } + return toObject; + } - if (Common.getValueByPath(fromObject, new String[] {"outputAudioTranscription"}) != null) { + @ExcludeFromGeneratedCoverageReport + ObjectNode transcriptionFromMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"text"}) != null) { Common.setValueByPath( toObject, - new String[] {"outputAudioTranscription"}, - audioTranscriptionConfigToVertex( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"outputAudioTranscription"})), - toObject)); + new String[] {"text"}, + Common.getValueByPath(fromObject, new String[] {"text"})); } - if (Common.getValueByPath(fromObject, new String[] {"proactivity"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"finished"}) != null) { Common.setValueByPath( toObject, - new String[] {"proactivity"}, - proactivityConfigToVertex( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"proactivity"})), - toObject)); + new String[] {"finished"}, + Common.getValueByPath(fromObject, new String[] {"finished"})); } return toObject; } @ExcludeFromGeneratedCoverageReport - ObjectNode liveClientContentToMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode urlMetadataFromMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"turns"}) != null) { - ArrayNode keyArray = (ArrayNode) Common.getValueByPath(fromObject, new String[] {"turns"}); - ObjectMapper objectMapper = new ObjectMapper(); - ArrayNode result = objectMapper.createArrayNode(); - - for (JsonNode item : keyArray) { - result.add(contentToMldev(JsonSerializable.toJsonNode(item), toObject)); - } - Common.setValueByPath(toObject, new String[] {"turns"}, result); + if (Common.getValueByPath(fromObject, new String[] {"retrievedUrl"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"retrievedUrl"}, + Common.getValueByPath(fromObject, new String[] {"retrievedUrl"})); } - if (Common.getValueByPath(fromObject, new String[] {"turnComplete"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"urlRetrievalStatus"}) != null) { Common.setValueByPath( toObject, - new String[] {"turnComplete"}, - Common.getValueByPath(fromObject, new String[] {"turnComplete"})); + new String[] {"urlRetrievalStatus"}, + Common.getValueByPath(fromObject, new String[] {"urlRetrievalStatus"})); } return toObject; } @ExcludeFromGeneratedCoverageReport - ObjectNode liveClientContentToVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode urlContextMetadataFromMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"turns"}) != null) { - ArrayNode keyArray = (ArrayNode) Common.getValueByPath(fromObject, new String[] {"turns"}); + if (Common.getValueByPath(fromObject, new String[] {"urlMetadata"}) != null) { + ArrayNode keyArray = + (ArrayNode) Common.getValueByPath(fromObject, new String[] {"urlMetadata"}); ObjectMapper objectMapper = new ObjectMapper(); ArrayNode result = objectMapper.createArrayNode(); for (JsonNode item : keyArray) { - result.add(contentToVertex(JsonSerializable.toJsonNode(item), toObject)); + result.add(urlMetadataFromMldev(JsonSerializable.toJsonNode(item), toObject)); } - Common.setValueByPath(toObject, new String[] {"turns"}, result); - } - - if (Common.getValueByPath(fromObject, new String[] {"turnComplete"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"turnComplete"}, - Common.getValueByPath(fromObject, new String[] {"turnComplete"})); + Common.setValueByPath(toObject, new String[] {"urlMetadata"}, result); } return toObject; } @ExcludeFromGeneratedCoverageReport - ObjectNode liveClientRealtimeInputToMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode liveServerContentFromMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"mediaChunks"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"modelTurn"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"modelTurn"}, + contentFromMldev( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"modelTurn"})), + toObject)); + } + + if (Common.getValueByPath(fromObject, new String[] {"turnComplete"}) != null) { Common.setValueByPath( toObject, - new String[] {"mediaChunks"}, - Common.getValueByPath(fromObject, new String[] {"mediaChunks"})); + new String[] {"turnComplete"}, + Common.getValueByPath(fromObject, new String[] {"turnComplete"})); } - if (Common.getValueByPath(fromObject, new String[] {"audio"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"interrupted"}) != null) { Common.setValueByPath( toObject, - new String[] {"audio"}, - Common.getValueByPath(fromObject, new String[] {"audio"})); + new String[] {"interrupted"}, + Common.getValueByPath(fromObject, new String[] {"interrupted"})); } - if (Common.getValueByPath(fromObject, new String[] {"audioStreamEnd"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"groundingMetadata"}) != null) { Common.setValueByPath( toObject, - new String[] {"audioStreamEnd"}, - Common.getValueByPath(fromObject, new String[] {"audioStreamEnd"})); + new String[] {"groundingMetadata"}, + Common.getValueByPath(fromObject, new String[] {"groundingMetadata"})); } - if (Common.getValueByPath(fromObject, new String[] {"video"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"generationComplete"}) != null) { Common.setValueByPath( toObject, - new String[] {"video"}, - Common.getValueByPath(fromObject, new String[] {"video"})); + new String[] {"generationComplete"}, + Common.getValueByPath(fromObject, new String[] {"generationComplete"})); } - if (Common.getValueByPath(fromObject, new String[] {"text"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"inputTranscription"}) != null) { Common.setValueByPath( toObject, - new String[] {"text"}, - Common.getValueByPath(fromObject, new String[] {"text"})); + new String[] {"inputTranscription"}, + transcriptionFromMldev( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"inputTranscription"})), + toObject)); } - if (Common.getValueByPath(fromObject, new String[] {"activityStart"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"outputTranscription"}) != null) { Common.setValueByPath( toObject, - new String[] {"activityStart"}, - activityStartToMldev( + new String[] {"outputTranscription"}, + transcriptionFromMldev( JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"activityStart"})), + Common.getValueByPath(fromObject, new String[] {"outputTranscription"})), toObject)); } - if (Common.getValueByPath(fromObject, new String[] {"activityEnd"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"urlContextMetadata"}) != null) { Common.setValueByPath( toObject, - new String[] {"activityEnd"}, - activityEndToMldev( + new String[] {"urlContextMetadata"}, + urlContextMetadataFromMldev( JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"activityEnd"})), + Common.getValueByPath(fromObject, new String[] {"urlContextMetadata"})), toObject)); } @@ -2299,290 +2795,294 @@ ObjectNode liveClientRealtimeInputToMldev(JsonNode fromObject, ObjectNode parent } @ExcludeFromGeneratedCoverageReport - ObjectNode liveClientRealtimeInputToVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode functionCallFromMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"mediaChunks"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"id"}) != null) { Common.setValueByPath( - toObject, - new String[] {"mediaChunks"}, - Common.getValueByPath(fromObject, new String[] {"mediaChunks"})); + toObject, new String[] {"id"}, Common.getValueByPath(fromObject, new String[] {"id"})); } - if (Common.getValueByPath(fromObject, new String[] {"audio"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"args"}) != null) { Common.setValueByPath( toObject, - new String[] {"audio"}, - Common.getValueByPath(fromObject, new String[] {"audio"})); - } - - if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"audioStreamEnd"}))) { - throw new IllegalArgumentException("audioStreamEnd parameter is not supported in Vertex AI."); + new String[] {"args"}, + Common.getValueByPath(fromObject, new String[] {"args"})); } - if (Common.getValueByPath(fromObject, new String[] {"video"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"name"}) != null) { Common.setValueByPath( toObject, - new String[] {"video"}, - Common.getValueByPath(fromObject, new String[] {"video"})); + new String[] {"name"}, + Common.getValueByPath(fromObject, new String[] {"name"})); } - if (Common.getValueByPath(fromObject, new String[] {"text"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"text"}, - Common.getValueByPath(fromObject, new String[] {"text"})); - } + return toObject; + } - if (Common.getValueByPath(fromObject, new String[] {"activityStart"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"activityStart"}, - activityStartToVertex( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"activityStart"})), - toObject)); - } + @ExcludeFromGeneratedCoverageReport + ObjectNode liveServerToolCallFromMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"functionCalls"}) != null) { + ArrayNode keyArray = + (ArrayNode) Common.getValueByPath(fromObject, new String[] {"functionCalls"}); + ObjectMapper objectMapper = new ObjectMapper(); + ArrayNode result = objectMapper.createArrayNode(); - if (Common.getValueByPath(fromObject, new String[] {"activityEnd"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"activityEnd"}, - activityEndToVertex( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"activityEnd"})), - toObject)); + for (JsonNode item : keyArray) { + result.add(functionCallFromMldev(JsonSerializable.toJsonNode(item), toObject)); + } + Common.setValueByPath(toObject, new String[] {"functionCalls"}, result); } return toObject; } @ExcludeFromGeneratedCoverageReport - ObjectNode functionResponseToMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode liveServerToolCallCancellationFromMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"willContinue"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"willContinue"}, - Common.getValueByPath(fromObject, new String[] {"willContinue"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"scheduling"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"ids"}) != null) { Common.setValueByPath( - toObject, - new String[] {"scheduling"}, - Common.getValueByPath(fromObject, new String[] {"scheduling"})); + toObject, new String[] {"ids"}, Common.getValueByPath(fromObject, new String[] {"ids"})); } - if (Common.getValueByPath(fromObject, new String[] {"id"}) != null) { - Common.setValueByPath( - toObject, new String[] {"id"}, Common.getValueByPath(fromObject, new String[] {"id"})); - } + return toObject; + } - if (Common.getValueByPath(fromObject, new String[] {"name"}) != null) { + @ExcludeFromGeneratedCoverageReport + ObjectNode modalityTokenCountFromMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"modality"}) != null) { Common.setValueByPath( toObject, - new String[] {"name"}, - Common.getValueByPath(fromObject, new String[] {"name"})); + new String[] {"modality"}, + Common.getValueByPath(fromObject, new String[] {"modality"})); } - if (Common.getValueByPath(fromObject, new String[] {"response"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"tokenCount"}) != null) { Common.setValueByPath( toObject, - new String[] {"response"}, - Common.getValueByPath(fromObject, new String[] {"response"})); + new String[] {"tokenCount"}, + Common.getValueByPath(fromObject, new String[] {"tokenCount"})); } return toObject; } @ExcludeFromGeneratedCoverageReport - ObjectNode functionResponseToVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode usageMetadataFromMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"willContinue"}))) { - throw new IllegalArgumentException("willContinue parameter is not supported in Vertex AI."); + if (Common.getValueByPath(fromObject, new String[] {"promptTokenCount"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"promptTokenCount"}, + Common.getValueByPath(fromObject, new String[] {"promptTokenCount"})); } - if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"scheduling"}))) { - throw new IllegalArgumentException("scheduling parameter is not supported in Vertex AI."); + if (Common.getValueByPath(fromObject, new String[] {"cachedContentTokenCount"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"cachedContentTokenCount"}, + Common.getValueByPath(fromObject, new String[] {"cachedContentTokenCount"})); } - if (Common.getValueByPath(fromObject, new String[] {"id"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"responseTokenCount"}) != null) { Common.setValueByPath( - toObject, new String[] {"id"}, Common.getValueByPath(fromObject, new String[] {"id"})); + toObject, + new String[] {"responseTokenCount"}, + Common.getValueByPath(fromObject, new String[] {"responseTokenCount"})); } - if (Common.getValueByPath(fromObject, new String[] {"name"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"toolUsePromptTokenCount"}) != null) { Common.setValueByPath( toObject, - new String[] {"name"}, - Common.getValueByPath(fromObject, new String[] {"name"})); + new String[] {"toolUsePromptTokenCount"}, + Common.getValueByPath(fromObject, new String[] {"toolUsePromptTokenCount"})); } - if (Common.getValueByPath(fromObject, new String[] {"response"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"thoughtsTokenCount"}) != null) { Common.setValueByPath( toObject, - new String[] {"response"}, - Common.getValueByPath(fromObject, new String[] {"response"})); + new String[] {"thoughtsTokenCount"}, + Common.getValueByPath(fromObject, new String[] {"thoughtsTokenCount"})); } - return toObject; - } + if (Common.getValueByPath(fromObject, new String[] {"totalTokenCount"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"totalTokenCount"}, + Common.getValueByPath(fromObject, new String[] {"totalTokenCount"})); + } - @ExcludeFromGeneratedCoverageReport - ObjectNode liveClientToolResponseToMldev(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"functionResponses"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"promptTokensDetails"}) != null) { ArrayNode keyArray = - (ArrayNode) Common.getValueByPath(fromObject, new String[] {"functionResponses"}); + (ArrayNode) Common.getValueByPath(fromObject, new String[] {"promptTokensDetails"}); ObjectMapper objectMapper = new ObjectMapper(); ArrayNode result = objectMapper.createArrayNode(); for (JsonNode item : keyArray) { - result.add(functionResponseToMldev(JsonSerializable.toJsonNode(item), toObject)); + result.add(modalityTokenCountFromMldev(JsonSerializable.toJsonNode(item), toObject)); } - Common.setValueByPath(toObject, new String[] {"functionResponses"}, result); + Common.setValueByPath(toObject, new String[] {"promptTokensDetails"}, result); } - return toObject; - } + if (Common.getValueByPath(fromObject, new String[] {"cacheTokensDetails"}) != null) { + ArrayNode keyArray = + (ArrayNode) Common.getValueByPath(fromObject, new String[] {"cacheTokensDetails"}); + ObjectMapper objectMapper = new ObjectMapper(); + ArrayNode result = objectMapper.createArrayNode(); - @ExcludeFromGeneratedCoverageReport - ObjectNode liveClientToolResponseToVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"functionResponses"}) != null) { + for (JsonNode item : keyArray) { + result.add(modalityTokenCountFromMldev(JsonSerializable.toJsonNode(item), toObject)); + } + Common.setValueByPath(toObject, new String[] {"cacheTokensDetails"}, result); + } + + if (Common.getValueByPath(fromObject, new String[] {"responseTokensDetails"}) != null) { ArrayNode keyArray = - (ArrayNode) Common.getValueByPath(fromObject, new String[] {"functionResponses"}); + (ArrayNode) Common.getValueByPath(fromObject, new String[] {"responseTokensDetails"}); ObjectMapper objectMapper = new ObjectMapper(); ArrayNode result = objectMapper.createArrayNode(); for (JsonNode item : keyArray) { - result.add(functionResponseToVertex(JsonSerializable.toJsonNode(item), toObject)); + result.add(modalityTokenCountFromMldev(JsonSerializable.toJsonNode(item), toObject)); } - Common.setValueByPath(toObject, new String[] {"functionResponses"}, result); + Common.setValueByPath(toObject, new String[] {"responseTokensDetails"}, result); + } + + if (Common.getValueByPath(fromObject, new String[] {"toolUsePromptTokensDetails"}) != null) { + ArrayNode keyArray = + (ArrayNode) + Common.getValueByPath(fromObject, new String[] {"toolUsePromptTokensDetails"}); + ObjectMapper objectMapper = new ObjectMapper(); + ArrayNode result = objectMapper.createArrayNode(); + + for (JsonNode item : keyArray) { + result.add(modalityTokenCountFromMldev(JsonSerializable.toJsonNode(item), toObject)); + } + Common.setValueByPath(toObject, new String[] {"toolUsePromptTokensDetails"}, result); } return toObject; } @ExcludeFromGeneratedCoverageReport - ObjectNode liveClientMessageToMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode liveServerGoAwayFromMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"setup"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"timeLeft"}) != null) { Common.setValueByPath( toObject, - new String[] {"setup"}, - liveClientSetupToMldev( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"setup"})), - toObject)); + new String[] {"timeLeft"}, + Common.getValueByPath(fromObject, new String[] {"timeLeft"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode liveServerSessionResumptionUpdateFromMldev( + JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"newHandle"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"newHandle"}, + Common.getValueByPath(fromObject, new String[] {"newHandle"})); } - if (Common.getValueByPath(fromObject, new String[] {"clientContent"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"resumable"}) != null) { Common.setValueByPath( toObject, - new String[] {"clientContent"}, - liveClientContentToMldev( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"clientContent"})), - toObject)); + new String[] {"resumable"}, + Common.getValueByPath(fromObject, new String[] {"resumable"})); } - if (Common.getValueByPath(fromObject, new String[] {"realtimeInput"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"lastConsumedClientMessageIndex"}) + != null) { Common.setValueByPath( toObject, - new String[] {"realtimeInput"}, - liveClientRealtimeInputToMldev( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"realtimeInput"})), - toObject)); + new String[] {"lastConsumedClientMessageIndex"}, + Common.getValueByPath(fromObject, new String[] {"lastConsumedClientMessageIndex"})); } - if (Common.getValueByPath(fromObject, new String[] {"realtimeInputParameters"}) != null) { + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode liveServerMessageFromMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"setupComplete"}) != null) { Common.setValueByPath( toObject, - new String[] {"realtime_input"}, - liveSendRealtimeInputParametersToMldev( + new String[] {"setupComplete"}, + liveServerSetupCompleteFromMldev( JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"realtimeInputParameters"})), + Common.getValueByPath(fromObject, new String[] {"setupComplete"})), toObject)); } - if (Common.getValueByPath(fromObject, new String[] {"toolResponse"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"serverContent"}) != null) { Common.setValueByPath( toObject, - new String[] {"toolResponse"}, - liveClientToolResponseToMldev( + new String[] {"serverContent"}, + liveServerContentFromMldev( JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"toolResponse"})), + Common.getValueByPath(fromObject, new String[] {"serverContent"})), toObject)); } - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode liveClientMessageToVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"setup"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"toolCall"}) != null) { Common.setValueByPath( toObject, - new String[] {"setup"}, - liveClientSetupToVertex( + new String[] {"toolCall"}, + liveServerToolCallFromMldev( JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"setup"})), + Common.getValueByPath(fromObject, new String[] {"toolCall"})), toObject)); } - if (Common.getValueByPath(fromObject, new String[] {"clientContent"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"toolCallCancellation"}) != null) { Common.setValueByPath( toObject, - new String[] {"clientContent"}, - liveClientContentToVertex( + new String[] {"toolCallCancellation"}, + liveServerToolCallCancellationFromMldev( JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"clientContent"})), + Common.getValueByPath(fromObject, new String[] {"toolCallCancellation"})), toObject)); } - if (Common.getValueByPath(fromObject, new String[] {"realtimeInput"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"usageMetadata"}) != null) { Common.setValueByPath( toObject, - new String[] {"realtimeInput"}, - liveClientRealtimeInputToVertex( + new String[] {"usageMetadata"}, + usageMetadataFromMldev( JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"realtimeInput"})), + Common.getValueByPath(fromObject, new String[] {"usageMetadata"})), toObject)); } - if (Common.getValueByPath(fromObject, new String[] {"realtimeInputParameters"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"goAway"}) != null) { Common.setValueByPath( toObject, - new String[] {"realtime_input"}, - liveSendRealtimeInputParametersToVertex( + new String[] {"goAway"}, + liveServerGoAwayFromMldev( JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"realtimeInputParameters"})), + Common.getValueByPath(fromObject, new String[] {"goAway"})), toObject)); } - if (Common.getValueByPath(fromObject, new String[] {"toolResponse"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"sessionResumptionUpdate"}) != null) { Common.setValueByPath( toObject, - new String[] {"toolResponse"}, - liveClientToolResponseToVertex( + new String[] {"sessionResumptionUpdate"}, + liveServerSessionResumptionUpdateFromMldev( JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"toolResponse"})), + Common.getValueByPath(fromObject, new String[] {"sessionResumptionUpdate"})), toObject)); } return toObject; } - @ExcludeFromGeneratedCoverageReport - ObjectNode liveServerSetupCompleteFromMldev(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - - return toObject; - } - @ExcludeFromGeneratedCoverageReport ObjectNode liveServerSetupCompleteFromVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); @@ -2596,31 +3096,6 @@ ObjectNode liveServerSetupCompleteFromVertex(JsonNode fromObject, ObjectNode par return toObject; } - @ExcludeFromGeneratedCoverageReport - ObjectNode videoMetadataFromMldev(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"fps"}) != null) { - Common.setValueByPath( - toObject, new String[] {"fps"}, Common.getValueByPath(fromObject, new String[] {"fps"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"endOffset"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"endOffset"}, - Common.getValueByPath(fromObject, new String[] {"endOffset"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"startOffset"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"startOffset"}, - Common.getValueByPath(fromObject, new String[] {"startOffset"})); - } - - return toObject; - } - @ExcludeFromGeneratedCoverageReport ObjectNode videoMetadataFromVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); @@ -2646,27 +3121,6 @@ ObjectNode videoMetadataFromVertex(JsonNode fromObject, ObjectNode parentObject) return toObject; } - @ExcludeFromGeneratedCoverageReport - ObjectNode blobFromMldev(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - - if (Common.getValueByPath(fromObject, new String[] {"data"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"data"}, - Common.getValueByPath(fromObject, new String[] {"data"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"mimeType"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"mimeType"}, - Common.getValueByPath(fromObject, new String[] {"mimeType"})); - } - - return toObject; - } - @ExcludeFromGeneratedCoverageReport ObjectNode blobFromVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); @@ -2694,134 +3148,28 @@ ObjectNode blobFromVertex(JsonNode fromObject, ObjectNode parentObject) { return toObject; } - @ExcludeFromGeneratedCoverageReport - ObjectNode fileDataFromMldev(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - - if (Common.getValueByPath(fromObject, new String[] {"fileUri"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"fileUri"}, - Common.getValueByPath(fromObject, new String[] {"fileUri"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"mimeType"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"mimeType"}, - Common.getValueByPath(fromObject, new String[] {"mimeType"})); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode fileDataFromVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"displayName"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"displayName"}, - Common.getValueByPath(fromObject, new String[] {"displayName"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"fileUri"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"fileUri"}, - Common.getValueByPath(fromObject, new String[] {"fileUri"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"mimeType"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"mimeType"}, - Common.getValueByPath(fromObject, new String[] {"mimeType"})); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode partFromMldev(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"videoMetadata"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"videoMetadata"}, - videoMetadataFromMldev( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"videoMetadata"})), - toObject)); - } - - if (Common.getValueByPath(fromObject, new String[] {"thought"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"thought"}, - Common.getValueByPath(fromObject, new String[] {"thought"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"inlineData"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"inlineData"}, - blobFromMldev( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"inlineData"})), - toObject)); - } - - if (Common.getValueByPath(fromObject, new String[] {"fileData"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"fileData"}, - fileDataFromMldev( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"fileData"})), - toObject)); - } - - if (Common.getValueByPath(fromObject, new String[] {"thoughtSignature"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"thoughtSignature"}, - Common.getValueByPath(fromObject, new String[] {"thoughtSignature"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"codeExecutionResult"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"codeExecutionResult"}, - Common.getValueByPath(fromObject, new String[] {"codeExecutionResult"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"executableCode"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"executableCode"}, - Common.getValueByPath(fromObject, new String[] {"executableCode"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"functionCall"}) != null) { + @ExcludeFromGeneratedCoverageReport + ObjectNode fileDataFromVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"displayName"}) != null) { Common.setValueByPath( toObject, - new String[] {"functionCall"}, - Common.getValueByPath(fromObject, new String[] {"functionCall"})); + new String[] {"displayName"}, + Common.getValueByPath(fromObject, new String[] {"displayName"})); } - if (Common.getValueByPath(fromObject, new String[] {"functionResponse"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"fileUri"}) != null) { Common.setValueByPath( toObject, - new String[] {"functionResponse"}, - Common.getValueByPath(fromObject, new String[] {"functionResponse"})); + new String[] {"fileUri"}, + Common.getValueByPath(fromObject, new String[] {"fileUri"})); } - if (Common.getValueByPath(fromObject, new String[] {"text"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"mimeType"}) != null) { Common.setValueByPath( toObject, - new String[] {"text"}, - Common.getValueByPath(fromObject, new String[] {"text"})); + new String[] {"mimeType"}, + Common.getValueByPath(fromObject, new String[] {"mimeType"})); } return toObject; @@ -2912,30 +3260,6 @@ ObjectNode partFromVertex(JsonNode fromObject, ObjectNode parentObject) { return toObject; } - @ExcludeFromGeneratedCoverageReport - ObjectNode contentFromMldev(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"parts"}) != null) { - ArrayNode keyArray = (ArrayNode) Common.getValueByPath(fromObject, new String[] {"parts"}); - ObjectMapper objectMapper = new ObjectMapper(); - ArrayNode result = objectMapper.createArrayNode(); - - for (JsonNode item : keyArray) { - result.add(partFromMldev(JsonSerializable.toJsonNode(item), toObject)); - } - Common.setValueByPath(toObject, new String[] {"parts"}, result); - } - - if (Common.getValueByPath(fromObject, new String[] {"role"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"role"}, - Common.getValueByPath(fromObject, new String[] {"role"})); - } - - return toObject; - } - @ExcludeFromGeneratedCoverageReport ObjectNode contentFromVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); @@ -2960,26 +3284,6 @@ ObjectNode contentFromVertex(JsonNode fromObject, ObjectNode parentObject) { return toObject; } - @ExcludeFromGeneratedCoverageReport - ObjectNode transcriptionFromMldev(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"text"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"text"}, - Common.getValueByPath(fromObject, new String[] {"text"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"finished"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"finished"}, - Common.getValueByPath(fromObject, new String[] {"finished"})); - } - - return toObject; - } - @ExcludeFromGeneratedCoverageReport ObjectNode transcriptionFromVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); @@ -3000,156 +3304,6 @@ ObjectNode transcriptionFromVertex(JsonNode fromObject, ObjectNode parentObject) return toObject; } - @ExcludeFromGeneratedCoverageReport - ObjectNode urlMetadataFromMldev(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"retrievedUrl"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"retrievedUrl"}, - Common.getValueByPath(fromObject, new String[] {"retrievedUrl"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"urlRetrievalStatus"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"urlRetrievalStatus"}, - Common.getValueByPath(fromObject, new String[] {"urlRetrievalStatus"})); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode urlMetadataFromVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"retrievedUrl"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"retrievedUrl"}, - Common.getValueByPath(fromObject, new String[] {"retrievedUrl"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"urlRetrievalStatus"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"urlRetrievalStatus"}, - Common.getValueByPath(fromObject, new String[] {"urlRetrievalStatus"})); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode urlContextMetadataFromMldev(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"urlMetadata"}) != null) { - ArrayNode keyArray = - (ArrayNode) Common.getValueByPath(fromObject, new String[] {"urlMetadata"}); - ObjectMapper objectMapper = new ObjectMapper(); - ArrayNode result = objectMapper.createArrayNode(); - - for (JsonNode item : keyArray) { - result.add(urlMetadataFromMldev(JsonSerializable.toJsonNode(item), toObject)); - } - Common.setValueByPath(toObject, new String[] {"urlMetadata"}, result); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode urlContextMetadataFromVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"urlMetadata"}) != null) { - ArrayNode keyArray = - (ArrayNode) Common.getValueByPath(fromObject, new String[] {"urlMetadata"}); - ObjectMapper objectMapper = new ObjectMapper(); - ArrayNode result = objectMapper.createArrayNode(); - - for (JsonNode item : keyArray) { - result.add(urlMetadataFromVertex(JsonSerializable.toJsonNode(item), toObject)); - } - Common.setValueByPath(toObject, new String[] {"urlMetadata"}, result); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode liveServerContentFromMldev(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"modelTurn"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"modelTurn"}, - contentFromMldev( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"modelTurn"})), - toObject)); - } - - if (Common.getValueByPath(fromObject, new String[] {"turnComplete"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"turnComplete"}, - Common.getValueByPath(fromObject, new String[] {"turnComplete"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"interrupted"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"interrupted"}, - Common.getValueByPath(fromObject, new String[] {"interrupted"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"groundingMetadata"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"groundingMetadata"}, - Common.getValueByPath(fromObject, new String[] {"groundingMetadata"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"generationComplete"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"generationComplete"}, - Common.getValueByPath(fromObject, new String[] {"generationComplete"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"inputTranscription"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"inputTranscription"}, - transcriptionFromMldev( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"inputTranscription"})), - toObject)); - } - - if (Common.getValueByPath(fromObject, new String[] {"outputTranscription"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"outputTranscription"}, - transcriptionFromMldev( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"outputTranscription"})), - toObject)); - } - - if (Common.getValueByPath(fromObject, new String[] {"urlContextMetadata"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"urlContextMetadata"}, - urlContextMetadataFromMldev( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"urlContextMetadata"})), - toObject)); - } - - return toObject; - } - @ExcludeFromGeneratedCoverageReport ObjectNode liveServerContentFromVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); @@ -3214,31 +3368,6 @@ ObjectNode liveServerContentFromVertex(JsonNode fromObject, ObjectNode parentObj return toObject; } - @ExcludeFromGeneratedCoverageReport - ObjectNode functionCallFromMldev(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"id"}) != null) { - Common.setValueByPath( - toObject, new String[] {"id"}, Common.getValueByPath(fromObject, new String[] {"id"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"args"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"args"}, - Common.getValueByPath(fromObject, new String[] {"args"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"name"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"name"}, - Common.getValueByPath(fromObject, new String[] {"name"})); - } - - return toObject; - } - @ExcludeFromGeneratedCoverageReport ObjectNode functionCallFromVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); @@ -3248,31 +3377,13 @@ ObjectNode functionCallFromVertex(JsonNode fromObject, ObjectNode parentObject) toObject, new String[] {"args"}, Common.getValueByPath(fromObject, new String[] {"args"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"name"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"name"}, - Common.getValueByPath(fromObject, new String[] {"name"})); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode liveServerToolCallFromMldev(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"functionCalls"}) != null) { - ArrayNode keyArray = - (ArrayNode) Common.getValueByPath(fromObject, new String[] {"functionCalls"}); - ObjectMapper objectMapper = new ObjectMapper(); - ArrayNode result = objectMapper.createArrayNode(); + } - for (JsonNode item : keyArray) { - result.add(functionCallFromMldev(JsonSerializable.toJsonNode(item), toObject)); - } - Common.setValueByPath(toObject, new String[] {"functionCalls"}, result); + if (Common.getValueByPath(fromObject, new String[] {"name"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"name"}, + Common.getValueByPath(fromObject, new String[] {"name"})); } return toObject; @@ -3296,17 +3407,6 @@ ObjectNode liveServerToolCallFromVertex(JsonNode fromObject, ObjectNode parentOb return toObject; } - @ExcludeFromGeneratedCoverageReport - ObjectNode liveServerToolCallCancellationFromMldev(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"ids"}) != null) { - Common.setValueByPath( - toObject, new String[] {"ids"}, Common.getValueByPath(fromObject, new String[] {"ids"})); - } - - return toObject; - } - @ExcludeFromGeneratedCoverageReport ObjectNode liveServerToolCallCancellationFromVertex( JsonNode fromObject, ObjectNode parentObject) { @@ -3319,26 +3419,6 @@ ObjectNode liveServerToolCallCancellationFromVertex( return toObject; } - @ExcludeFromGeneratedCoverageReport - ObjectNode modalityTokenCountFromMldev(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"modality"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"modality"}, - Common.getValueByPath(fromObject, new String[] {"modality"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"tokenCount"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"tokenCount"}, - Common.getValueByPath(fromObject, new String[] {"tokenCount"})); - } - - return toObject; - } - @ExcludeFromGeneratedCoverageReport ObjectNode modalityTokenCountFromVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); @@ -3359,103 +3439,6 @@ ObjectNode modalityTokenCountFromVertex(JsonNode fromObject, ObjectNode parentOb return toObject; } - @ExcludeFromGeneratedCoverageReport - ObjectNode usageMetadataFromMldev(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"promptTokenCount"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"promptTokenCount"}, - Common.getValueByPath(fromObject, new String[] {"promptTokenCount"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"cachedContentTokenCount"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"cachedContentTokenCount"}, - Common.getValueByPath(fromObject, new String[] {"cachedContentTokenCount"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"responseTokenCount"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"responseTokenCount"}, - Common.getValueByPath(fromObject, new String[] {"responseTokenCount"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"toolUsePromptTokenCount"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"toolUsePromptTokenCount"}, - Common.getValueByPath(fromObject, new String[] {"toolUsePromptTokenCount"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"thoughtsTokenCount"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"thoughtsTokenCount"}, - Common.getValueByPath(fromObject, new String[] {"thoughtsTokenCount"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"totalTokenCount"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"totalTokenCount"}, - Common.getValueByPath(fromObject, new String[] {"totalTokenCount"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"promptTokensDetails"}) != null) { - ArrayNode keyArray = - (ArrayNode) Common.getValueByPath(fromObject, new String[] {"promptTokensDetails"}); - ObjectMapper objectMapper = new ObjectMapper(); - ArrayNode result = objectMapper.createArrayNode(); - - for (JsonNode item : keyArray) { - result.add(modalityTokenCountFromMldev(JsonSerializable.toJsonNode(item), toObject)); - } - Common.setValueByPath(toObject, new String[] {"promptTokensDetails"}, result); - } - - if (Common.getValueByPath(fromObject, new String[] {"cacheTokensDetails"}) != null) { - ArrayNode keyArray = - (ArrayNode) Common.getValueByPath(fromObject, new String[] {"cacheTokensDetails"}); - ObjectMapper objectMapper = new ObjectMapper(); - ArrayNode result = objectMapper.createArrayNode(); - - for (JsonNode item : keyArray) { - result.add(modalityTokenCountFromMldev(JsonSerializable.toJsonNode(item), toObject)); - } - Common.setValueByPath(toObject, new String[] {"cacheTokensDetails"}, result); - } - - if (Common.getValueByPath(fromObject, new String[] {"responseTokensDetails"}) != null) { - ArrayNode keyArray = - (ArrayNode) Common.getValueByPath(fromObject, new String[] {"responseTokensDetails"}); - ObjectMapper objectMapper = new ObjectMapper(); - ArrayNode result = objectMapper.createArrayNode(); - - for (JsonNode item : keyArray) { - result.add(modalityTokenCountFromMldev(JsonSerializable.toJsonNode(item), toObject)); - } - Common.setValueByPath(toObject, new String[] {"responseTokensDetails"}, result); - } - - if (Common.getValueByPath(fromObject, new String[] {"toolUsePromptTokensDetails"}) != null) { - ArrayNode keyArray = - (ArrayNode) - Common.getValueByPath(fromObject, new String[] {"toolUsePromptTokensDetails"}); - ObjectMapper objectMapper = new ObjectMapper(); - ArrayNode result = objectMapper.createArrayNode(); - - for (JsonNode item : keyArray) { - result.add(modalityTokenCountFromMldev(JsonSerializable.toJsonNode(item), toObject)); - } - Common.setValueByPath(toObject, new String[] {"toolUsePromptTokensDetails"}, result); - } - - return toObject; - } - @ExcludeFromGeneratedCoverageReport ObjectNode usageMetadataFromVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); @@ -3560,19 +3543,6 @@ ObjectNode usageMetadataFromVertex(JsonNode fromObject, ObjectNode parentObject) return toObject; } - @ExcludeFromGeneratedCoverageReport - ObjectNode liveServerGoAwayFromMldev(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"timeLeft"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"timeLeft"}, - Common.getValueByPath(fromObject, new String[] {"timeLeft"})); - } - - return toObject; - } - @ExcludeFromGeneratedCoverageReport ObjectNode liveServerGoAwayFromVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); @@ -3586,35 +3556,6 @@ ObjectNode liveServerGoAwayFromVertex(JsonNode fromObject, ObjectNode parentObje return toObject; } - @ExcludeFromGeneratedCoverageReport - ObjectNode liveServerSessionResumptionUpdateFromMldev( - JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"newHandle"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"newHandle"}, - Common.getValueByPath(fromObject, new String[] {"newHandle"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"resumable"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"resumable"}, - Common.getValueByPath(fromObject, new String[] {"resumable"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"lastConsumedClientMessageIndex"}) - != null) { - Common.setValueByPath( - toObject, - new String[] {"lastConsumedClientMessageIndex"}, - Common.getValueByPath(fromObject, new String[] {"lastConsumedClientMessageIndex"})); - } - - return toObject; - } - @ExcludeFromGeneratedCoverageReport ObjectNode liveServerSessionResumptionUpdateFromVertex( JsonNode fromObject, ObjectNode parentObject) { @@ -3644,82 +3585,6 @@ ObjectNode liveServerSessionResumptionUpdateFromVertex( return toObject; } - @ExcludeFromGeneratedCoverageReport - ObjectNode liveServerMessageFromMldev(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"setupComplete"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"setupComplete"}, - liveServerSetupCompleteFromMldev( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"setupComplete"})), - toObject)); - } - - if (Common.getValueByPath(fromObject, new String[] {"serverContent"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"serverContent"}, - liveServerContentFromMldev( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"serverContent"})), - toObject)); - } - - if (Common.getValueByPath(fromObject, new String[] {"toolCall"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"toolCall"}, - liveServerToolCallFromMldev( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"toolCall"})), - toObject)); - } - - if (Common.getValueByPath(fromObject, new String[] {"toolCallCancellation"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"toolCallCancellation"}, - liveServerToolCallCancellationFromMldev( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"toolCallCancellation"})), - toObject)); - } - - if (Common.getValueByPath(fromObject, new String[] {"usageMetadata"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"usageMetadata"}, - usageMetadataFromMldev( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"usageMetadata"})), - toObject)); - } - - if (Common.getValueByPath(fromObject, new String[] {"goAway"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"goAway"}, - liveServerGoAwayFromMldev( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"goAway"})), - toObject)); - } - - if (Common.getValueByPath(fromObject, new String[] {"sessionResumptionUpdate"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"sessionResumptionUpdate"}, - liveServerSessionResumptionUpdateFromMldev( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"sessionResumptionUpdate"})), - toObject)); - } - - return toObject; - } - @ExcludeFromGeneratedCoverageReport ObjectNode liveServerMessageFromVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); diff --git a/src/main/java/com/google/genai/Models.java b/src/main/java/com/google/genai/Models.java index 8bcdef31f19..f3bed32ce95 100644 --- a/src/main/java/com/google/genai/Models.java +++ b/src/main/java/com/google/genai/Models.java @@ -434,18 +434,6 @@ ObjectNode schemaToMldev(JsonNode fromObject, ObjectNode parentObject) { return toObject; } - @ExcludeFromGeneratedCoverageReport - ObjectNode modelSelectionConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (!Common.isZero( - Common.getValueByPath(fromObject, new String[] {"featureSelectionPreference"}))) { - throw new IllegalArgumentException( - "featureSelectionPreference parameter is not supported in Gemini API."); - } - - return toObject; - } - @ExcludeFromGeneratedCoverageReport ObjectNode safetySettingToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); @@ -597,78 +585,6 @@ ObjectNode googleSearchRetrievalToMldev(JsonNode fromObject, ObjectNode parentOb return toObject; } - @ExcludeFromGeneratedCoverageReport - ObjectNode enterpriseWebSearchToMldev(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode apiKeyConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"apiKeyString"}))) { - throw new IllegalArgumentException("apiKeyString parameter is not supported in Gemini API."); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode authConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"apiKeyConfig"}))) { - throw new IllegalArgumentException("apiKeyConfig parameter is not supported in Gemini API."); - } - - if (Common.getValueByPath(fromObject, new String[] {"authType"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"authType"}, - Common.getValueByPath(fromObject, new String[] {"authType"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"googleServiceAccountConfig"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"googleServiceAccountConfig"}, - Common.getValueByPath(fromObject, new String[] {"googleServiceAccountConfig"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"httpBasicAuthConfig"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"httpBasicAuthConfig"}, - Common.getValueByPath(fromObject, new String[] {"httpBasicAuthConfig"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"oauthConfig"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"oauthConfig"}, - Common.getValueByPath(fromObject, new String[] {"oauthConfig"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"oidcConfig"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"oidcConfig"}, - Common.getValueByPath(fromObject, new String[] {"oidcConfig"})); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode googleMapsToMldev(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"authConfig"}))) { - throw new IllegalArgumentException("authConfig parameter is not supported in Gemini API."); - } - - return toObject; - } - @ExcludeFromGeneratedCoverageReport ObjectNode urlContextToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); @@ -1658,33 +1574,6 @@ ObjectNode imageToMldev(JsonNode fromObject, ObjectNode parentObject) { return toObject; } - @ExcludeFromGeneratedCoverageReport - ObjectNode videoToMldev(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"uri"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"video", "uri"}, - Common.getValueByPath(fromObject, new String[] {"uri"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"videoBytes"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"video", "encodedVideo"}, - Transformers.tBytes(Common.getValueByPath(fromObject, new String[] {"videoBytes"}))); - } - - if (Common.getValueByPath(fromObject, new String[] {"mimeType"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"encoding"}, - Common.getValueByPath(fromObject, new String[] {"mimeType"})); - } - - return toObject; - } - @ExcludeFromGeneratedCoverageReport ObjectNode generateVideosConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); @@ -2627,31 +2516,6 @@ ObjectNode voiceConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { return toObject; } - @ExcludeFromGeneratedCoverageReport - ObjectNode speakerVoiceConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"speaker"}))) { - throw new IllegalArgumentException("speaker parameter is not supported in Vertex AI."); - } - - if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"voiceConfig"}))) { - throw new IllegalArgumentException("voiceConfig parameter is not supported in Vertex AI."); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode multiSpeakerVoiceConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"speakerVoiceConfigs"}))) { - throw new IllegalArgumentException( - "speakerVoiceConfigs parameter is not supported in Vertex AI."); - } - - return toObject; - } - @ExcludeFromGeneratedCoverageReport ObjectNode speechConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); @@ -4420,13 +4284,6 @@ ObjectNode generateContentResponseFromMldev(JsonNode fromObject, ObjectNode pare return toObject; } - @ExcludeFromGeneratedCoverageReport - ObjectNode contentEmbeddingStatisticsFromMldev(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - - return toObject; - } - @ExcludeFromGeneratedCoverageReport ObjectNode contentEmbeddingFromMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); diff --git a/src/main/java/com/google/genai/TokensConverters.java b/src/main/java/com/google/genai/TokensConverters.java index 86638f464b6..d08f9ed8e5e 100644 --- a/src/main/java/com/google/genai/TokensConverters.java +++ b/src/main/java/com/google/genai/TokensConverters.java @@ -43,19 +43,6 @@ ObjectNode prebuiltVoiceConfigToMldev(JsonNode fromObject, ObjectNode parentObje return toObject; } - @ExcludeFromGeneratedCoverageReport - ObjectNode prebuiltVoiceConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"voiceName"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"voiceName"}, - Common.getValueByPath(fromObject, new String[] {"voiceName"})); - } - - return toObject; - } - @ExcludeFromGeneratedCoverageReport ObjectNode voiceConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); @@ -72,22 +59,6 @@ ObjectNode voiceConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { return toObject; } - @ExcludeFromGeneratedCoverageReport - ObjectNode voiceConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"prebuiltVoiceConfig"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"prebuiltVoiceConfig"}, - prebuiltVoiceConfigToVertex( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"prebuiltVoiceConfig"})), - toObject)); - } - - return toObject; - } - @ExcludeFromGeneratedCoverageReport ObjectNode speakerVoiceConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); @@ -111,20 +82,6 @@ ObjectNode speakerVoiceConfigToMldev(JsonNode fromObject, ObjectNode parentObjec return toObject; } - @ExcludeFromGeneratedCoverageReport - ObjectNode speakerVoiceConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"speaker"}))) { - throw new IllegalArgumentException("speaker parameter is not supported in Vertex AI."); - } - - if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"voiceConfig"}))) { - throw new IllegalArgumentException("voiceConfig parameter is not supported in Vertex AI."); - } - - return toObject; - } - @ExcludeFromGeneratedCoverageReport ObjectNode multiSpeakerVoiceConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); @@ -143,17 +100,6 @@ ObjectNode multiSpeakerVoiceConfigToMldev(JsonNode fromObject, ObjectNode parent return toObject; } - @ExcludeFromGeneratedCoverageReport - ObjectNode multiSpeakerVoiceConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"speakerVoiceConfigs"}))) { - throw new IllegalArgumentException( - "speakerVoiceConfigs parameter is not supported in Vertex AI."); - } - - return toObject; - } - @ExcludeFromGeneratedCoverageReport ObjectNode speechConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); @@ -187,35 +133,6 @@ ObjectNode speechConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { return toObject; } - @ExcludeFromGeneratedCoverageReport - ObjectNode speechConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"voiceConfig"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"voiceConfig"}, - voiceConfigToVertex( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"voiceConfig"})), - toObject)); - } - - if (!Common.isZero( - Common.getValueByPath(fromObject, new String[] {"multiSpeakerVoiceConfig"}))) { - throw new IllegalArgumentException( - "multiSpeakerVoiceConfig parameter is not supported in Vertex AI."); - } - - if (Common.getValueByPath(fromObject, new String[] {"languageCode"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"languageCode"}, - Common.getValueByPath(fromObject, new String[] {"languageCode"})); - } - - return toObject; - } - @ExcludeFromGeneratedCoverageReport ObjectNode videoMetadataToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); @@ -241,31 +158,6 @@ ObjectNode videoMetadataToMldev(JsonNode fromObject, ObjectNode parentObject) { return toObject; } - @ExcludeFromGeneratedCoverageReport - ObjectNode videoMetadataToVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"fps"}) != null) { - Common.setValueByPath( - toObject, new String[] {"fps"}, Common.getValueByPath(fromObject, new String[] {"fps"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"endOffset"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"endOffset"}, - Common.getValueByPath(fromObject, new String[] {"endOffset"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"startOffset"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"startOffset"}, - Common.getValueByPath(fromObject, new String[] {"startOffset"})); - } - - return toObject; - } - @ExcludeFromGeneratedCoverageReport ObjectNode blobToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); @@ -290,33 +182,6 @@ ObjectNode blobToMldev(JsonNode fromObject, ObjectNode parentObject) { return toObject; } - @ExcludeFromGeneratedCoverageReport - ObjectNode blobToVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"displayName"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"displayName"}, - Common.getValueByPath(fromObject, new String[] {"displayName"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"data"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"data"}, - Common.getValueByPath(fromObject, new String[] {"data"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"mimeType"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"mimeType"}, - Common.getValueByPath(fromObject, new String[] {"mimeType"})); - } - - return toObject; - } - @ExcludeFromGeneratedCoverageReport ObjectNode fileDataToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); @@ -341,33 +206,6 @@ ObjectNode fileDataToMldev(JsonNode fromObject, ObjectNode parentObject) { return toObject; } - @ExcludeFromGeneratedCoverageReport - ObjectNode fileDataToVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"displayName"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"displayName"}, - Common.getValueByPath(fromObject, new String[] {"displayName"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"fileUri"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"fileUri"}, - Common.getValueByPath(fromObject, new String[] {"fileUri"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"mimeType"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"mimeType"}, - Common.getValueByPath(fromObject, new String[] {"mimeType"})); - } - - return toObject; - } - @ExcludeFromGeneratedCoverageReport ObjectNode partToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); @@ -453,91 +291,6 @@ ObjectNode partToMldev(JsonNode fromObject, ObjectNode parentObject) { return toObject; } - @ExcludeFromGeneratedCoverageReport - ObjectNode partToVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"videoMetadata"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"videoMetadata"}, - videoMetadataToVertex( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"videoMetadata"})), - toObject)); - } - - if (Common.getValueByPath(fromObject, new String[] {"thought"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"thought"}, - Common.getValueByPath(fromObject, new String[] {"thought"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"inlineData"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"inlineData"}, - blobToVertex( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"inlineData"})), - toObject)); - } - - if (Common.getValueByPath(fromObject, new String[] {"fileData"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"fileData"}, - fileDataToVertex( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"fileData"})), - toObject)); - } - - if (Common.getValueByPath(fromObject, new String[] {"thoughtSignature"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"thoughtSignature"}, - Common.getValueByPath(fromObject, new String[] {"thoughtSignature"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"codeExecutionResult"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"codeExecutionResult"}, - Common.getValueByPath(fromObject, new String[] {"codeExecutionResult"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"executableCode"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"executableCode"}, - Common.getValueByPath(fromObject, new String[] {"executableCode"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"functionCall"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"functionCall"}, - Common.getValueByPath(fromObject, new String[] {"functionCall"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"functionResponse"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"functionResponse"}, - Common.getValueByPath(fromObject, new String[] {"functionResponse"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"text"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"text"}, - Common.getValueByPath(fromObject, new String[] {"text"})); - } - - return toObject; - } - @ExcludeFromGeneratedCoverageReport ObjectNode contentToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); @@ -562,30 +315,6 @@ ObjectNode contentToMldev(JsonNode fromObject, ObjectNode parentObject) { return toObject; } - @ExcludeFromGeneratedCoverageReport - ObjectNode contentToVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"parts"}) != null) { - ArrayNode keyArray = (ArrayNode) Common.getValueByPath(fromObject, new String[] {"parts"}); - ObjectMapper objectMapper = new ObjectMapper(); - ArrayNode result = objectMapper.createArrayNode(); - - for (JsonNode item : keyArray) { - result.add(partToVertex(JsonSerializable.toJsonNode(item), toObject)); - } - Common.setValueByPath(toObject, new String[] {"parts"}, result); - } - - if (Common.getValueByPath(fromObject, new String[] {"role"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"role"}, - Common.getValueByPath(fromObject, new String[] {"role"})); - } - - return toObject; - } - @ExcludeFromGeneratedCoverageReport ObjectNode functionDeclarationToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); @@ -642,92 +371,20 @@ ObjectNode functionDeclarationToMldev(JsonNode fromObject, ObjectNode parentObje } @ExcludeFromGeneratedCoverageReport - ObjectNode functionDeclarationToVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode intervalToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"behavior"}))) { - throw new IllegalArgumentException("behavior parameter is not supported in Vertex AI."); - } - - if (Common.getValueByPath(fromObject, new String[] {"description"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"startTime"}) != null) { Common.setValueByPath( toObject, - new String[] {"description"}, - Common.getValueByPath(fromObject, new String[] {"description"})); + new String[] {"startTime"}, + Common.getValueByPath(fromObject, new String[] {"startTime"})); } - if (Common.getValueByPath(fromObject, new String[] {"name"}) != null) { + if (Common.getValueByPath(fromObject, new String[] {"endTime"}) != null) { Common.setValueByPath( toObject, - new String[] {"name"}, - Common.getValueByPath(fromObject, new String[] {"name"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"parameters"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"parameters"}, - Common.getValueByPath(fromObject, new String[] {"parameters"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"parametersJsonSchema"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"parametersJsonSchema"}, - Common.getValueByPath(fromObject, new String[] {"parametersJsonSchema"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"response"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"response"}, - Common.getValueByPath(fromObject, new String[] {"response"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"responseJsonSchema"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"responseJsonSchema"}, - Common.getValueByPath(fromObject, new String[] {"responseJsonSchema"})); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode intervalToMldev(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"startTime"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"startTime"}, - Common.getValueByPath(fromObject, new String[] {"startTime"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"endTime"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"endTime"}, - Common.getValueByPath(fromObject, new String[] {"endTime"})); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode intervalToVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"startTime"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"startTime"}, - Common.getValueByPath(fromObject, new String[] {"startTime"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"endTime"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"endTime"}, - Common.getValueByPath(fromObject, new String[] {"endTime"})); + new String[] {"endTime"}, + Common.getValueByPath(fromObject, new String[] {"endTime"})); } return toObject; @@ -749,22 +406,6 @@ ObjectNode googleSearchToMldev(JsonNode fromObject, ObjectNode parentObject) { return toObject; } - @ExcludeFromGeneratedCoverageReport - ObjectNode googleSearchToVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"timeRangeFilter"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"timeRangeFilter"}, - intervalToVertex( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"timeRangeFilter"})), - toObject)); - } - - return toObject; - } - @ExcludeFromGeneratedCoverageReport ObjectNode dynamicRetrievalConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); @@ -785,26 +426,6 @@ ObjectNode dynamicRetrievalConfigToMldev(JsonNode fromObject, ObjectNode parentO return toObject; } - @ExcludeFromGeneratedCoverageReport - ObjectNode dynamicRetrievalConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"mode"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"mode"}, - Common.getValueByPath(fromObject, new String[] {"mode"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"dynamicThreshold"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"dynamicThreshold"}, - Common.getValueByPath(fromObject, new String[] {"dynamicThreshold"})); - } - - return toObject; - } - @ExcludeFromGeneratedCoverageReport ObjectNode googleSearchRetrievalToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); @@ -821,181 +442,6 @@ ObjectNode googleSearchRetrievalToMldev(JsonNode fromObject, ObjectNode parentOb return toObject; } - @ExcludeFromGeneratedCoverageReport - ObjectNode googleSearchRetrievalToVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"dynamicRetrievalConfig"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"dynamicRetrievalConfig"}, - dynamicRetrievalConfigToVertex( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"dynamicRetrievalConfig"})), - toObject)); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode enterpriseWebSearchToMldev(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode enterpriseWebSearchToVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode apiKeyConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"apiKeyString"}))) { - throw new IllegalArgumentException("apiKeyString parameter is not supported in Gemini API."); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode apiKeyConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"apiKeyString"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"apiKeyString"}, - Common.getValueByPath(fromObject, new String[] {"apiKeyString"})); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode authConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"apiKeyConfig"}))) { - throw new IllegalArgumentException("apiKeyConfig parameter is not supported in Gemini API."); - } - - if (Common.getValueByPath(fromObject, new String[] {"authType"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"authType"}, - Common.getValueByPath(fromObject, new String[] {"authType"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"googleServiceAccountConfig"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"googleServiceAccountConfig"}, - Common.getValueByPath(fromObject, new String[] {"googleServiceAccountConfig"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"httpBasicAuthConfig"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"httpBasicAuthConfig"}, - Common.getValueByPath(fromObject, new String[] {"httpBasicAuthConfig"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"oauthConfig"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"oauthConfig"}, - Common.getValueByPath(fromObject, new String[] {"oauthConfig"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"oidcConfig"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"oidcConfig"}, - Common.getValueByPath(fromObject, new String[] {"oidcConfig"})); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode authConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"apiKeyConfig"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"apiKeyConfig"}, - apiKeyConfigToVertex( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"apiKeyConfig"})), - toObject)); - } - - if (Common.getValueByPath(fromObject, new String[] {"authType"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"authType"}, - Common.getValueByPath(fromObject, new String[] {"authType"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"googleServiceAccountConfig"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"googleServiceAccountConfig"}, - Common.getValueByPath(fromObject, new String[] {"googleServiceAccountConfig"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"httpBasicAuthConfig"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"httpBasicAuthConfig"}, - Common.getValueByPath(fromObject, new String[] {"httpBasicAuthConfig"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"oauthConfig"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"oauthConfig"}, - Common.getValueByPath(fromObject, new String[] {"oauthConfig"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"oidcConfig"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"oidcConfig"}, - Common.getValueByPath(fromObject, new String[] {"oidcConfig"})); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode googleMapsToMldev(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"authConfig"}))) { - throw new IllegalArgumentException("authConfig parameter is not supported in Gemini API."); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode googleMapsToVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"authConfig"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"authConfig"}, - authConfigToVertex( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"authConfig"})), - toObject)); - } - - return toObject; - } - @ExcludeFromGeneratedCoverageReport ObjectNode urlContextToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); @@ -1003,13 +449,6 @@ ObjectNode urlContextToMldev(JsonNode fromObject, ObjectNode parentObject) { return toObject; } - @ExcludeFromGeneratedCoverageReport - ObjectNode urlContextToVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - - return toObject; - } - @ExcludeFromGeneratedCoverageReport ObjectNode toolToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); @@ -1085,95 +524,6 @@ ObjectNode toolToMldev(JsonNode fromObject, ObjectNode parentObject) { return toObject; } - @ExcludeFromGeneratedCoverageReport - ObjectNode toolToVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"functionDeclarations"}) != null) { - ArrayNode keyArray = - (ArrayNode) Common.getValueByPath(fromObject, new String[] {"functionDeclarations"}); - ObjectMapper objectMapper = new ObjectMapper(); - ArrayNode result = objectMapper.createArrayNode(); - - for (JsonNode item : keyArray) { - result.add(functionDeclarationToVertex(JsonSerializable.toJsonNode(item), toObject)); - } - Common.setValueByPath(toObject, new String[] {"functionDeclarations"}, result); - } - - if (Common.getValueByPath(fromObject, new String[] {"retrieval"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"retrieval"}, - Common.getValueByPath(fromObject, new String[] {"retrieval"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"googleSearch"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"googleSearch"}, - googleSearchToVertex( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"googleSearch"})), - toObject)); - } - - if (Common.getValueByPath(fromObject, new String[] {"googleSearchRetrieval"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"googleSearchRetrieval"}, - googleSearchRetrievalToVertex( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"googleSearchRetrieval"})), - toObject)); - } - - if (Common.getValueByPath(fromObject, new String[] {"enterpriseWebSearch"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"enterpriseWebSearch"}, - enterpriseWebSearchToVertex( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"enterpriseWebSearch"})), - toObject)); - } - - if (Common.getValueByPath(fromObject, new String[] {"googleMaps"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"googleMaps"}, - googleMapsToVertex( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"googleMaps"})), - toObject)); - } - - if (Common.getValueByPath(fromObject, new String[] {"urlContext"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"urlContext"}, - urlContextToVertex( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"urlContext"})), - toObject)); - } - - if (Common.getValueByPath(fromObject, new String[] {"codeExecution"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"codeExecution"}, - Common.getValueByPath(fromObject, new String[] {"codeExecution"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"computerUse"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"computerUse"}, - Common.getValueByPath(fromObject, new String[] {"computerUse"})); - } - - return toObject; - } - @ExcludeFromGeneratedCoverageReport ObjectNode sessionResumptionConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); @@ -1188,86 +538,18 @@ ObjectNode sessionResumptionConfigToMldev(JsonNode fromObject, ObjectNode parent throw new IllegalArgumentException("transparent parameter is not supported in Gemini API."); } - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode sessionResumptionConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"handle"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"handle"}, - Common.getValueByPath(fromObject, new String[] {"handle"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"transparent"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"transparent"}, - Common.getValueByPath(fromObject, new String[] {"transparent"})); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode audioTranscriptionConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode audioTranscriptionConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode automaticActivityDetectionToMldev(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"disabled"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"disabled"}, - Common.getValueByPath(fromObject, new String[] {"disabled"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"startOfSpeechSensitivity"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"startOfSpeechSensitivity"}, - Common.getValueByPath(fromObject, new String[] {"startOfSpeechSensitivity"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"endOfSpeechSensitivity"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"endOfSpeechSensitivity"}, - Common.getValueByPath(fromObject, new String[] {"endOfSpeechSensitivity"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"prefixPaddingMs"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"prefixPaddingMs"}, - Common.getValueByPath(fromObject, new String[] {"prefixPaddingMs"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"silenceDurationMs"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"silenceDurationMs"}, - Common.getValueByPath(fromObject, new String[] {"silenceDurationMs"})); - } + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode audioTranscriptionConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); return toObject; } @ExcludeFromGeneratedCoverageReport - ObjectNode automaticActivityDetectionToVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode automaticActivityDetectionToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"disabled"}) != null) { Common.setValueByPath( @@ -1337,36 +619,6 @@ ObjectNode realtimeInputConfigToMldev(JsonNode fromObject, ObjectNode parentObje return toObject; } - @ExcludeFromGeneratedCoverageReport - ObjectNode realtimeInputConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"automaticActivityDetection"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"automaticActivityDetection"}, - automaticActivityDetectionToVertex( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"automaticActivityDetection"})), - toObject)); - } - - if (Common.getValueByPath(fromObject, new String[] {"activityHandling"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"activityHandling"}, - Common.getValueByPath(fromObject, new String[] {"activityHandling"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"turnCoverage"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"turnCoverage"}, - Common.getValueByPath(fromObject, new String[] {"turnCoverage"})); - } - - return toObject; - } - @ExcludeFromGeneratedCoverageReport ObjectNode slidingWindowToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); @@ -1380,19 +632,6 @@ ObjectNode slidingWindowToMldev(JsonNode fromObject, ObjectNode parentObject) { return toObject; } - @ExcludeFromGeneratedCoverageReport - ObjectNode slidingWindowToVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"targetTokens"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"targetTokens"}, - Common.getValueByPath(fromObject, new String[] {"targetTokens"})); - } - - return toObject; - } - @ExcludeFromGeneratedCoverageReport ObjectNode contextWindowCompressionConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); @@ -1416,29 +655,6 @@ ObjectNode contextWindowCompressionConfigToMldev(JsonNode fromObject, ObjectNode return toObject; } - @ExcludeFromGeneratedCoverageReport - ObjectNode contextWindowCompressionConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"triggerTokens"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"triggerTokens"}, - Common.getValueByPath(fromObject, new String[] {"triggerTokens"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"slidingWindow"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"slidingWindow"}, - slidingWindowToVertex( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"slidingWindow"})), - toObject)); - } - - return toObject; - } - @ExcludeFromGeneratedCoverageReport ObjectNode proactivityConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); @@ -1452,19 +668,6 @@ ObjectNode proactivityConfigToMldev(JsonNode fromObject, ObjectNode parentObject return toObject; } - @ExcludeFromGeneratedCoverageReport - ObjectNode proactivityConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"proactiveAudio"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"proactiveAudio"}, - Common.getValueByPath(fromObject, new String[] {"proactiveAudio"})); - } - - return toObject; - } - @ExcludeFromGeneratedCoverageReport ObjectNode liveConnectConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); @@ -1623,164 +826,6 @@ ObjectNode liveConnectConfigToMldev(JsonNode fromObject, ObjectNode parentObject return toObject; } - @ExcludeFromGeneratedCoverageReport - ObjectNode liveConnectConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - - if (Common.getValueByPath(fromObject, new String[] {"responseModalities"}) != null) { - Common.setValueByPath( - parentObject, - new String[] {"setup", "generationConfig", "responseModalities"}, - Common.getValueByPath(fromObject, new String[] {"responseModalities"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"temperature"}) != null) { - Common.setValueByPath( - parentObject, - new String[] {"setup", "generationConfig", "temperature"}, - Common.getValueByPath(fromObject, new String[] {"temperature"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"topP"}) != null) { - Common.setValueByPath( - parentObject, - new String[] {"setup", "generationConfig", "topP"}, - Common.getValueByPath(fromObject, new String[] {"topP"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"topK"}) != null) { - Common.setValueByPath( - parentObject, - new String[] {"setup", "generationConfig", "topK"}, - Common.getValueByPath(fromObject, new String[] {"topK"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"maxOutputTokens"}) != null) { - Common.setValueByPath( - parentObject, - new String[] {"setup", "generationConfig", "maxOutputTokens"}, - Common.getValueByPath(fromObject, new String[] {"maxOutputTokens"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"mediaResolution"}) != null) { - Common.setValueByPath( - parentObject, - new String[] {"setup", "generationConfig", "mediaResolution"}, - Common.getValueByPath(fromObject, new String[] {"mediaResolution"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"seed"}) != null) { - Common.setValueByPath( - parentObject, - new String[] {"setup", "generationConfig", "seed"}, - Common.getValueByPath(fromObject, new String[] {"seed"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"speechConfig"}) != null) { - Common.setValueByPath( - parentObject, - new String[] {"setup", "generationConfig", "speechConfig"}, - speechConfigToVertex( - JsonSerializable.toJsonNode( - Transformers.tLiveSpeechConfig( - Common.getValueByPath(fromObject, new String[] {"speechConfig"}))), - toObject)); - } - - if (Common.getValueByPath(fromObject, new String[] {"enableAffectiveDialog"}) != null) { - Common.setValueByPath( - parentObject, - new String[] {"setup", "generationConfig", "enableAffectiveDialog"}, - Common.getValueByPath(fromObject, new String[] {"enableAffectiveDialog"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"systemInstruction"}) != null) { - Common.setValueByPath( - parentObject, - new String[] {"setup", "systemInstruction"}, - contentToVertex( - JsonSerializable.toJsonNode( - Transformers.tContent( - Common.getValueByPath(fromObject, new String[] {"systemInstruction"}))), - toObject)); - } - - if (Common.getValueByPath(fromObject, new String[] {"tools"}) != null) { - ArrayNode keyArray = - (ArrayNode) - Transformers.tTools(Common.getValueByPath(fromObject, new String[] {"tools"})); - ObjectMapper objectMapper = new ObjectMapper(); - ArrayNode result = objectMapper.createArrayNode(); - - for (JsonNode item : keyArray) { - result.add(toolToVertex(JsonSerializable.toJsonNode(Transformers.tTool(item)), toObject)); - } - Common.setValueByPath(parentObject, new String[] {"setup", "tools"}, result); - } - - if (Common.getValueByPath(fromObject, new String[] {"sessionResumption"}) != null) { - Common.setValueByPath( - parentObject, - new String[] {"setup", "sessionResumption"}, - sessionResumptionConfigToVertex( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"sessionResumption"})), - toObject)); - } - - if (Common.getValueByPath(fromObject, new String[] {"inputAudioTranscription"}) != null) { - Common.setValueByPath( - parentObject, - new String[] {"setup", "inputAudioTranscription"}, - audioTranscriptionConfigToVertex( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"inputAudioTranscription"})), - toObject)); - } - - if (Common.getValueByPath(fromObject, new String[] {"outputAudioTranscription"}) != null) { - Common.setValueByPath( - parentObject, - new String[] {"setup", "outputAudioTranscription"}, - audioTranscriptionConfigToVertex( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"outputAudioTranscription"})), - toObject)); - } - - if (Common.getValueByPath(fromObject, new String[] {"realtimeInputConfig"}) != null) { - Common.setValueByPath( - parentObject, - new String[] {"setup", "realtimeInputConfig"}, - realtimeInputConfigToVertex( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"realtimeInputConfig"})), - toObject)); - } - - if (Common.getValueByPath(fromObject, new String[] {"contextWindowCompression"}) != null) { - Common.setValueByPath( - parentObject, - new String[] {"setup", "contextWindowCompression"}, - contextWindowCompressionConfigToVertex( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"contextWindowCompression"})), - toObject)); - } - - if (Common.getValueByPath(fromObject, new String[] {"proactivity"}) != null) { - Common.setValueByPath( - parentObject, - new String[] {"setup", "proactivity"}, - proactivityConfigToVertex( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"proactivity"})), - toObject)); - } - - return toObject; - } - @ExcludeFromGeneratedCoverageReport ObjectNode liveConnectConstraintsToMldev( ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { @@ -1806,20 +851,6 @@ ObjectNode liveConnectConstraintsToMldev( return toObject; } - @ExcludeFromGeneratedCoverageReport - ObjectNode liveConnectConstraintsToVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"model"}))) { - throw new IllegalArgumentException("model parameter is not supported in Vertex AI."); - } - - if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"config"}))) { - throw new IllegalArgumentException("config parameter is not supported in Vertex AI."); - } - - return toObject; - } - @ExcludeFromGeneratedCoverageReport ObjectNode createAuthTokenConfigToMldev( ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { @@ -1867,37 +898,6 @@ ObjectNode createAuthTokenConfigToMldev( return toObject; } - @ExcludeFromGeneratedCoverageReport - ObjectNode createAuthTokenConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - - if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"expireTime"}))) { - throw new IllegalArgumentException("expireTime parameter is not supported in Vertex AI."); - } - - if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"newSessionExpireTime"}))) { - throw new IllegalArgumentException( - "newSessionExpireTime parameter is not supported in Vertex AI."); - } - - if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"uses"}))) { - throw new IllegalArgumentException("uses parameter is not supported in Vertex AI."); - } - - if (!Common.isZero( - Common.getValueByPath(fromObject, new String[] {"liveConnectConstraints"}))) { - throw new IllegalArgumentException( - "liveConnectConstraints parameter is not supported in Vertex AI."); - } - - if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"lockAdditionalFields"}))) { - throw new IllegalArgumentException( - "lockAdditionalFields parameter is not supported in Vertex AI."); - } - - return toObject; - } - @ExcludeFromGeneratedCoverageReport ObjectNode createAuthTokenParametersToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); diff --git a/src/test/java/com/google/genai/TableTest.java b/src/test/java/com/google/genai/TableTest.java index ea19623fbc7..58b13da9a26 100644 --- a/src/test/java/com/google/genai/TableTest.java +++ b/src/test/java/com/google/genai/TableTest.java @@ -141,7 +141,6 @@ private static Collection createTestCases( } // Edit image ReferenceImages are not correctly deserialized for replay tests if (testName.contains("models.edit_image") - || testName.contains("batches.test_list_batch_jobs") // TODO(b/427478981) Remove this. || testName.contains("models.generate_content.test_speech_with_config") || testName.contains( "models.generate_content.test_logprobs_zero_with_response_logprobs_true")) { From 2ed15058f9652582bd3c682afc0f9abd4a66e48a Mon Sep 17 00:00:00 2001 From: Jaycee Li Date: Thu, 10 Jul 2025 17:23:57 -0700 Subject: [PATCH 067/602] chore: Validate enum values in converters PiperOrigin-RevId: 781745493 --- src/main/java/com/google/genai/Caches.java | 11 ++++++++ src/main/java/com/google/genai/Models.java | 33 ++++++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/src/main/java/com/google/genai/Caches.java b/src/main/java/com/google/genai/Caches.java index c8cac25d6f9..ead19819ee2 100644 --- a/src/main/java/com/google/genai/Caches.java +++ b/src/main/java/com/google/genai/Caches.java @@ -22,6 +22,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.ObjectNode; +import com.google.common.collect.ImmutableSet; import com.google.genai.errors.GenAiIOException; import com.google.genai.types.CachedContent; import com.google.genai.types.CreateCachedContentConfig; @@ -1578,6 +1579,16 @@ ObjectNode listCachedContentsParametersToVertex(JsonNode fromObject, ObjectNode return toObject; } + @ExcludeFromGeneratedCoverageReport + void behaviorVertexEnumValidate(Object enumValue) { + ImmutableSet invalidEnumValues = + ImmutableSet.of("UNSPECIFIED", "BLOCKING", "NON_BLOCKING"); + if (invalidEnumValues.contains(enumValue.toString().replace("\"", ""))) { + throw new IllegalArgumentException( + String.format("%s enum value is not supported in Vertex AI.", enumValue)); + } + } + @ExcludeFromGeneratedCoverageReport ObjectNode cachedContentFromMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); diff --git a/src/main/java/com/google/genai/Models.java b/src/main/java/com/google/genai/Models.java index f3bed32ce95..70f8921b54f 100644 --- a/src/main/java/com/google/genai/Models.java +++ b/src/main/java/com/google/genai/Models.java @@ -24,6 +24,7 @@ import com.fasterxml.jackson.databind.node.ObjectNode; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; import com.google.genai.errors.GenAiIOException; import com.google.genai.types.ComputeTokensConfig; import com.google.genai.types.ComputeTokensParameters; @@ -1248,6 +1249,8 @@ ObjectNode generateImagesConfigToMldev(JsonNode fromObject, ObjectNode parentObj } if (Common.getValueByPath(fromObject, new String[] {"safetyFilterLevel"}) != null) { + safetyFilterLevelMldevEnumValidate( + Common.getValueByPath(fromObject, new String[] {"safetyFilterLevel"})); Common.setValueByPath( parentObject, new String[] {"parameters", "safetySetting"}, @@ -1255,6 +1258,8 @@ ObjectNode generateImagesConfigToMldev(JsonNode fromObject, ObjectNode parentObj } if (Common.getValueByPath(fromObject, new String[] {"personGeneration"}) != null) { + personGenerationMldevEnumValidate( + Common.getValueByPath(fromObject, new String[] {"personGeneration"})); Common.setValueByPath( parentObject, new String[] {"parameters", "personGeneration"}, @@ -3932,6 +3937,34 @@ ObjectNode generateVideosParametersToVertex( return toObject; } + @ExcludeFromGeneratedCoverageReport + void safetyFilterLevelMldevEnumValidate(Object enumValue) { + ImmutableSet invalidEnumValues = ImmutableSet.of("BLOCK_NONE"); + if (invalidEnumValues.contains(enumValue.toString().replace("\"", ""))) { + throw new IllegalArgumentException( + String.format("%s enum value is not supported in Gemini API.", enumValue)); + } + } + + @ExcludeFromGeneratedCoverageReport + void personGenerationMldevEnumValidate(Object enumValue) { + ImmutableSet invalidEnumValues = ImmutableSet.of("ALLOW_ALL"); + if (invalidEnumValues.contains(enumValue.toString().replace("\"", ""))) { + throw new IllegalArgumentException( + String.format("%s enum value is not supported in Gemini API.", enumValue)); + } + } + + @ExcludeFromGeneratedCoverageReport + void behaviorVertexEnumValidate(Object enumValue) { + ImmutableSet invalidEnumValues = + ImmutableSet.of("UNSPECIFIED", "BLOCKING", "NON_BLOCKING"); + if (invalidEnumValues.contains(enumValue.toString().replace("\"", ""))) { + throw new IllegalArgumentException( + String.format("%s enum value is not supported in Vertex AI.", enumValue)); + } + } + @ExcludeFromGeneratedCoverageReport ObjectNode videoMetadataFromMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); From e57d3f8d03f8c1d2b8ed0ca2d33935c9d88ad85e Mon Sep 17 00:00:00 2001 From: Jaycee Li Date: Thu, 10 Jul 2025 17:28:31 -0700 Subject: [PATCH 068/602] chore: Match error message in replay test PiperOrigin-RevId: 781746941 --- .../java/com/google/genai/Transformers.java | 23 ++++++++-- .../com/google/genai/errors/ApiException.java | 4 +- src/test/java/com/google/genai/TableTest.java | 45 ++++++++++++------- 3 files changed, 49 insertions(+), 23 deletions(-) diff --git a/src/main/java/com/google/genai/Transformers.java b/src/main/java/com/google/genai/Transformers.java index 178473a90a9..5c373897197 100644 --- a/src/main/java/com/google/genai/Transformers.java +++ b/src/main/java/com/google/genai/Transformers.java @@ -509,6 +509,9 @@ public static String tCachedContentName(ApiClient apiClient, Object origin) { /** Formats a resource name given the resource name and resource prefix. */ private static String getResourceName( ApiClient apiClient, String resourceName, String resourcePrefix) { + boolean shouldPrependCollectionIdentifier = + (!resourceName.startsWith(resourcePrefix + "/") + && countCharInAString(String.format("%s/%s", resourcePrefix, resourceName), '/') == 1); if (apiClient.vertexAI()) { if (resourceName.startsWith("projects/")) { return resourceName; @@ -517,18 +520,30 @@ private static String getResourceName( } else if (resourceName.startsWith(resourcePrefix + "/")) { return String.format( "projects/%s/locations/%s/%s", apiClient.project(), apiClient.location(), resourceName); - } else { + } else if (shouldPrependCollectionIdentifier) { return String.format( "projects/%s/locations/%s/%s/%s", apiClient.project(), apiClient.location(), resourcePrefix, resourceName); + } else { + return resourceName; } } else { - if (resourceName.startsWith(resourcePrefix + "/")) { - return resourceName; - } else { + if (shouldPrependCollectionIdentifier) { return String.format("%s/%s", resourcePrefix, resourceName); + } else { + return resourceName; + } + } + } + + private static int countCharInAString(String string, char charToCount) { + int count = 0; + for (char c : string.toCharArray()) { + if (c == charToCount) { + count++; } } + return count; } public static Object tBatchJobSource(Object src) { diff --git a/src/main/java/com/google/genai/errors/ApiException.java b/src/main/java/com/google/genai/errors/ApiException.java index fb4c81ef4b5..a57830f7d76 100644 --- a/src/main/java/com/google/genai/errors/ApiException.java +++ b/src/main/java/com/google/genai/errors/ApiException.java @@ -161,12 +161,12 @@ public static void throwFromErrorNode(ArrayNode errorNode, int code) { return; } String message = ""; - JsonNode messageNode = errorNode.get(0).get("message"); + JsonNode messageNode = errorNode.get(0).get("error").get("message"); if (messageNode != null && messageNode.isTextual()) { message = messageNode.asText(); } String status = "UNKNOWN"; - JsonNode statusNode = errorNode.get("status"); + JsonNode statusNode = errorNode.get(0).get("error").get("status"); if (statusNode != null && statusNode.isTextual()) { status = statusNode.asText(); } diff --git a/src/test/java/com/google/genai/TableTest.java b/src/test/java/com/google/genai/TableTest.java index 58b13da9a26..2ba30d2f808 100644 --- a/src/test/java/com/google/genai/TableTest.java +++ b/src/test/java/com/google/genai/TableTest.java @@ -18,7 +18,6 @@ package com.google.genai; import static org.junit.jupiter.api.Assertions.fail; -import static org.junit.jupiter.api.Assumptions.assumeTrue; import com.google.genai.types.TestTableFile; import com.google.genai.types.TestTableItem; @@ -175,6 +174,13 @@ private static Collection createTestCases( } parameters.add(parameter); } + Optional skipInApiMode = testTableItem.skipInApiMode(); + if (skipInApiMode.isPresent() + && (client.clientMode().equals("api") || client.clientMode().isEmpty())) { + String msg = " => Test skipped: " + skipInApiMode.get(); + dynamicTests.add(DynamicTest.dynamicTest(testName + msg, () -> {})); + continue; + } dynamicTests.add( DynamicTest.dynamicTest( testName, @@ -185,28 +191,33 @@ private static Collection createTestCases( // InvocationTargetException is sometimes expected, when exceptionIfMldev or // exceptionIfVertex is present. Object response = method.invoke(module.get(client), parameters.toArray()); - } catch (IllegalAccessException | InvocationTargetException e) { + } catch (IllegalAccessException + | InvocationTargetException + | IllegalArgumentException e) { // Handle expected exceptions here - Optional skipInApiMode = testTableItem.skipInApiMode(); Optional exceptionIfMldev = testTableItem.exceptionIfMldev(); Optional exceptionIfVertex = testTableItem.exceptionIfVertex(); - if (skipInApiMode.isPresent() - && (client.clientMode().equals("api") || client.clientMode().isEmpty())) { - System.out.printf(" === Skipped: %s\n", skipInApiMode.get()); - assumeTrue(false, String.format("Skipped: %s", skipInApiMode.get())); - } - // TODO(jayceeli): Check if the error message is expected, once we update the - // error - // messages from the ApiClient. if (exceptionIfMldev.isPresent() && !client.vertexAI()) { - assumeTrue(false, "Skipped: test case is expected to fail in MLDev"); - System.out.println(" === Skipped: test case is expected to fail in MLDev"); + if (!e.getCause().getMessage().contains(exceptionIfMldev.get())) { + fail( + String.format( + "'%s' failed to match expected exception:\n" + + "Expected exception: %s\n" + + " Actual exception: %s\n", + testName, exceptionIfMldev.get(), e.getCause().getMessage())); + } } else if (exceptionIfVertex.isPresent() && client.vertexAI()) { - assumeTrue(false, "Skipped: test case is expected to fail in Vertex AI"); - System.out.println( - " === Skipped: test case is expected to fail in Vertex AI"); + if (!e.getCause().getMessage().contains(exceptionIfVertex.get())) { + fail( + String.format( + "'%s' failed to match expected exception:\n" + + "Expected exception: %s\n" + + " Actual exception: %s\n", + testName, exceptionIfVertex.get(), e.getCause().getMessage())); + } + } else { + fail(String.format("'%s' failed: %s", testName, e.getCause())); } - fail(String.format("'%s' failed: %s", testName, e.getCause())); } finally { client.close(); } From c4598da0903d5dacb0c7bb4462aec1226ba259bf Mon Sep 17 00:00:00 2001 From: Annie Luc Date: Fri, 11 Jul 2025 08:32:42 -0700 Subject: [PATCH 069/602] feat: Add `addWatermark` parameter to the edit image configuration. PiperOrigin-RevId: 781992729 --- src/main/java/com/google/genai/Models.java | 7 +++++++ .../java/com/google/genai/types/EditImageConfig.java | 12 ++++++++++++ 2 files changed, 19 insertions(+) diff --git a/src/main/java/com/google/genai/Models.java b/src/main/java/com/google/genai/Models.java index 70f8921b54f..0e2fefa1535 100644 --- a/src/main/java/com/google/genai/Models.java +++ b/src/main/java/com/google/genai/Models.java @@ -3330,6 +3330,13 @@ ObjectNode editImageConfigToVertex(JsonNode fromObject, ObjectNode parentObject) Common.getValueByPath(fromObject, new String[] {"outputCompressionQuality"})); } + if (Common.getValueByPath(fromObject, new String[] {"addWatermark"}) != null) { + Common.setValueByPath( + parentObject, + new String[] {"parameters", "addWatermark"}, + Common.getValueByPath(fromObject, new String[] {"addWatermark"})); + } + if (Common.getValueByPath(fromObject, new String[] {"editMode"}) != null) { Common.setValueByPath( parentObject, diff --git a/src/main/java/com/google/genai/types/EditImageConfig.java b/src/main/java/com/google/genai/types/EditImageConfig.java index 1159b679999..0f0c7f6e539 100644 --- a/src/main/java/com/google/genai/types/EditImageConfig.java +++ b/src/main/java/com/google/genai/types/EditImageConfig.java @@ -100,6 +100,10 @@ public abstract class EditImageConfig extends JsonSerializable { @JsonProperty("outputCompressionQuality") public abstract Optional outputCompressionQuality(); + /** Whether to add a watermark to the generated images. */ + @JsonProperty("addWatermark") + public abstract Optional addWatermark(); + /** Describes the editing mode for the request. */ @JsonProperty("editMode") public abstract Optional editMode(); @@ -315,6 +319,14 @@ public Builder language(String language) { @JsonProperty("outputCompressionQuality") public abstract Builder outputCompressionQuality(Integer outputCompressionQuality); + /** + * Setter for addWatermark. + * + *

addWatermark: Whether to add a watermark to the generated images. + */ + @JsonProperty("addWatermark") + public abstract Builder addWatermark(boolean addWatermark); + /** * Setter for editMode. * From 85be4d154740051ec23cae320e932a0aa3989cec Mon Sep 17 00:00:00 2001 From: Annie Luc Date: Fri, 11 Jul 2025 08:38:24 -0700 Subject: [PATCH 070/602] chore: Throw an error if httpOptions is provided at the request level in Live module PiperOrigin-RevId: 781994492 --- src/main/java/com/google/genai/AsyncLive.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/google/genai/AsyncLive.java b/src/main/java/com/google/genai/AsyncLive.java index 09df8c1babb..a4b91e4b243 100644 --- a/src/main/java/com/google/genai/AsyncLive.java +++ b/src/main/java/com/google/genai/AsyncLive.java @@ -60,6 +60,12 @@ public class AsyncLive { * connection. */ public CompletableFuture connect(String model, LiveConnectConfig config) { + // TODO: b/404946806 - Support per request HTTP options. + if (config != null && config.httpOptions().isPresent()) { + throw new IllegalArgumentException( + "The AsyncLive module does not support httpOptions at request-level in LiveConnectConfig" + + " yet. Please use the client-level httpOptions configuration instead."); + } CompletableFuture future = new CompletableFuture<>(); GenAiWebSocketClient websocket = @@ -249,4 +255,4 @@ private void handleIncomingMessage(String message) { } } } -} \ No newline at end of file +} From 9a2ced8ed3a1896b8170cc9ca117b61cb9eea705 Mon Sep 17 00:00:00 2001 From: Matthew Tang Date: Fri, 11 Jul 2025 10:32:53 -0700 Subject: [PATCH 071/602] docs: Update generated video resolution config docstring PiperOrigin-RevId: 782030857 --- .../java/com/google/genai/types/GenerateVideosConfig.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/google/genai/types/GenerateVideosConfig.java b/src/main/java/com/google/genai/types/GenerateVideosConfig.java index b5f22250882..950d8416889 100644 --- a/src/main/java/com/google/genai/types/GenerateVideosConfig.java +++ b/src/main/java/com/google/genai/types/GenerateVideosConfig.java @@ -64,7 +64,7 @@ public abstract class GenerateVideosConfig extends JsonSerializable { @JsonProperty("aspectRatio") public abstract Optional aspectRatio(); - /** The resolution for the generated video. 1280x720, 1920x1080 are supported. */ + /** The resolution for the generated video. 720p and 1080p are supported. */ @JsonProperty("resolution") public abstract Optional resolution(); @@ -193,7 +193,7 @@ public Builder httpOptions(HttpOptions.Builder httpOptionsBuilder) { /** * Setter for resolution. * - *

resolution: The resolution for the generated video. 1280x720, 1920x1080 are supported. + *

resolution: The resolution for the generated video. 720p and 1080p are supported. */ @JsonProperty("resolution") public abstract Builder resolution(String resolution); From 1ed61d7b54792c246c61568792e8f112db509181 Mon Sep 17 00:00:00 2001 From: Jaycee Li Date: Fri, 11 Jul 2025 14:45:06 -0700 Subject: [PATCH 072/602] chore: Decouple env var settings from unit tests PiperOrigin-RevId: 782115589 --- src/main/java/com/google/genai/ApiClient.java | 2 +- .../java/com/google/genai/AsyncChatTest.java | 4 +++- src/test/java/com/google/genai/ChatTest.java | 8 +++----- src/test/java/com/google/genai/ClientTest.java | 3 --- .../com/google/genai/DefaultValuesTest.java | 3 ++- .../google/genai/ForwardCompatibilityTest.java | 6 ++---- .../com/google/genai/HttpApiClientTest.java | 13 +++++++++---- src/test/java/com/google/genai/ModelsTest.java | 17 ++++++++++++++++- .../java/com/google/genai/OperationsTest.java | 16 +++++++++++++++- src/test/java/com/google/genai/TableTest.java | 13 ++++++++++++- 10 files changed, 63 insertions(+), 22 deletions(-) diff --git a/src/main/java/com/google/genai/ApiClient.java b/src/main/java/com/google/genai/ApiClient.java index 85f64e978ea..eab17d0f35c 100644 --- a/src/main/java/com/google/genai/ApiClient.java +++ b/src/main/java/com/google/genai/ApiClient.java @@ -149,7 +149,7 @@ protected ApiClient( this.httpClient = createHttpClient(httpOptions.timeout(), clientOptions); } - private String getApiKeyFromEnv() { + static String getApiKeyFromEnv() { String googleApiKey = System.getenv("GOOGLE_API_KEY"); if (googleApiKey != null && googleApiKey.isEmpty()) { googleApiKey = null; diff --git a/src/test/java/com/google/genai/AsyncChatTest.java b/src/test/java/com/google/genai/AsyncChatTest.java index 2eead7e1c66..13f21537191 100644 --- a/src/test/java/com/google/genai/AsyncChatTest.java +++ b/src/test/java/com/google/genai/AsyncChatTest.java @@ -31,6 +31,7 @@ import java.lang.reflect.Field; import java.util.Iterator; import java.util.List; +import java.util.Optional; import java.util.concurrent.CompletableFuture; import java.util.concurrent.atomic.AtomicInteger; import okhttp3.MediaType; @@ -115,7 +116,8 @@ void setUp() { when(mockedClient.request(anyString(), anyString(), anyString(), any())) .thenReturn(mockedResponse); - client = Client.builder().build(); + String apiKey = Optional.ofNullable(ApiClient.getApiKeyFromEnv()).orElse("api-key"); + client = Client.builder().apiKey(apiKey).vertexAI(false).build(); mockedResponse1 = Mockito.mock(ApiResponse.class); mockedResponse2 = Mockito.mock(ApiResponse.class); diff --git a/src/test/java/com/google/genai/ChatTest.java b/src/test/java/com/google/genai/ChatTest.java index 0312b23651a..b4112ccf85e 100644 --- a/src/test/java/com/google/genai/ChatTest.java +++ b/src/test/java/com/google/genai/ChatTest.java @@ -26,19 +26,16 @@ import com.google.genai.types.Candidate; import com.google.genai.types.Content; import com.google.genai.types.FinishReason; -import com.google.genai.types.FunctionCall; import com.google.genai.types.GenerateContentConfig; import com.google.genai.types.GenerateContentResponse; import com.google.genai.types.GenerateContentResponseUsageMetadata; import com.google.genai.types.Part; import com.google.genai.types.Tool; -import java.io.ByteArrayInputStream; -import java.io.InputStream; import java.lang.reflect.Field; import java.lang.reflect.Method; -import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; +import java.util.Optional; import okhttp3.MediaType; import okhttp3.ResponseBody; import org.junit.jupiter.api.BeforeEach; @@ -129,7 +126,8 @@ void setUp() { when(mockedClient.request(anyString(), anyString(), anyString(), any())) .thenReturn(mockedResponse); - client = Client.builder().build(); + String apiKey = Optional.ofNullable(ApiClient.getApiKeyFromEnv()).orElse("api-key"); + client = Client.builder().apiKey(apiKey).vertexAI(false).build(); mockedResponse1 = Mockito.mock(ApiResponse.class); mockedResponse2 = Mockito.mock(ApiResponse.class); diff --git a/src/test/java/com/google/genai/ClientTest.java b/src/test/java/com/google/genai/ClientTest.java index d824e426b0e..d7ee1fe8d99 100644 --- a/src/test/java/com/google/genai/ClientTest.java +++ b/src/test/java/com/google/genai/ClientTest.java @@ -20,14 +20,11 @@ import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import com.google.auth.oauth2.GoogleCredentials; -import com.google.genai.errors.GenAiIOException; import com.google.genai.types.HttpOptions; -import java.io.IOException; import java.lang.reflect.Field; import java.util.Optional; import okhttp3.OkHttpClient; diff --git a/src/test/java/com/google/genai/DefaultValuesTest.java b/src/test/java/com/google/genai/DefaultValuesTest.java index 38717352a9e..6f65bdf0d89 100644 --- a/src/test/java/com/google/genai/DefaultValuesTest.java +++ b/src/test/java/com/google/genai/DefaultValuesTest.java @@ -45,7 +45,8 @@ public void testDefaultValues() throws Exception { ResponseBody.create(MediaType.get("application/json"), returnResponse.toJson()); when(mockedResponse.getBody()).thenReturn(content); - Client client = Client.builder().build(); + String apiKey = Optional.ofNullable(ApiClient.getApiKeyFromEnv()).orElse("api-key"); + Client client = Client.builder().apiKey(apiKey).vertexAI(false).build(); // Make the apiClient field public so that it can be spied on in the tests. This is a // workaround for the fact that the ApiClient is a final class and cannot be spied on directly. Field apiClientField = Models.class.getDeclaredField("apiClient"); diff --git a/src/test/java/com/google/genai/ForwardCompatibilityTest.java b/src/test/java/com/google/genai/ForwardCompatibilityTest.java index 15ddaee7edd..82f06687ede 100644 --- a/src/test/java/com/google/genai/ForwardCompatibilityTest.java +++ b/src/test/java/com/google/genai/ForwardCompatibilityTest.java @@ -63,7 +63,8 @@ void setUp() { objectMapper = new ObjectMapper(); - client = Client.builder().build(); + String apiKey = Optional.ofNullable(ApiClient.getApiKeyFromEnv()).orElse("api-key"); + client = Client.builder().apiKey(apiKey).vertexAI(false).build(); } @Test @@ -110,7 +111,6 @@ public void testEnumForwardCompatibilityFinishReason() throws Exception { ResponseBody responseBody = ResponseBody.create(JSON, jsonString); when(mockedResponse.getBody()).thenReturn(responseBody); - Client client = Client.builder().build(); // Make the apiClient field public so that it can be spied on in the tests. This is a // workaround for the fact that the ApiClient is a final class and cannot be spied on directly. Field apiClientField = Models.class.getDeclaredField("apiClient"); @@ -150,7 +150,6 @@ public void testFinishReasonEnumReturnsEnum() throws Exception { ResponseBody responseBody = ResponseBody.create(JSON, jsonString); when(mockedResponse.getBody()).thenReturn(responseBody); - Client client = Client.builder().build(); // Make the apiClient field public so that it can be spied on in the tests. This is a // workaround for the fact that the ApiClient is a final class and cannot be spied on directly. Field apiClientField = Models.class.getDeclaredField("apiClient"); @@ -189,7 +188,6 @@ public void testEnumForwardCompatibilitySafetyFilterLevel() throws Exception { ResponseBody responseBody = ResponseBody.create(JSON, jsonString); when(mockedResponse.getBody()).thenReturn(responseBody); - Client client = Client.builder().build(); // Make the apiClient field public so that it can be spied on in the tests. This is a // workaround for the fact that the ApiClient is a final class and cannot be spied on Field apiClientField = Models.class.getDeclaredField("apiClient"); diff --git a/src/test/java/com/google/genai/HttpApiClientTest.java b/src/test/java/com/google/genai/HttpApiClientTest.java index 0ed6005cc3d..ef507fb4aab 100644 --- a/src/test/java/com/google/genai/HttpApiClientTest.java +++ b/src/test/java/com/google/genai/HttpApiClientTest.java @@ -522,7 +522,8 @@ public void testProxySetup() throws Exception { .baseUrl("http://localhost:" + wireMockServer.port()) .apiVersion("v1beta") .build(); - Client client = Client.builder().vertexAI(false).httpOptions(httpOptions).build(); + Client client = + Client.builder().apiKey(API_KEY).vertexAI(false).httpOptions(httpOptions).build(); GenerateContentResponse response = client.models.generateContent("gemini-2.0-flash", "What is your name?", null); @@ -537,7 +538,8 @@ public void testProxySetup() throws Exception { public void testClientInitializationWithBaseUrlFromHttpOptions() throws Exception { HttpOptions httpOptions = HttpOptions.builder().baseUrl("https://custom-base-url.googleapis.com/").build(); - Client client = Client.builder().vertexAI(false).httpOptions(httpOptions).build(); + Client client = + Client.builder().apiKey(API_KEY).vertexAI(false).httpOptions(httpOptions).build(); assertTrue(client.baseUrl().isPresent()); assertEquals(client.baseUrl().get(), "https://custom-base-url.googleapis.com/"); @@ -550,7 +552,8 @@ public void testClientInitializationWithBaseUrlFromHttpOptionsOverridesSetDefaul HttpOptions.builder().baseUrl("https://custom-base-url.googleapis.com/").build(); Client.setDefaultBaseUrls( Optional.of("https://gemini-base-url.googleapis.com/"), Optional.empty()); - Client client = Client.builder().vertexAI(false).httpOptions(httpOptions).build(); + Client client = + Client.builder().apiKey(API_KEY).vertexAI(false).httpOptions(httpOptions).build(); assertTrue(client.baseUrl().isPresent()); assertEquals(client.baseUrl().get(), "https://custom-base-url.googleapis.com/"); @@ -560,7 +563,7 @@ public void testClientInitializationWithBaseUrlFromHttpOptionsOverridesSetDefaul public void testClientInitializationWithBaseUrlFromSetBaseUrls() throws Exception { Client.setDefaultBaseUrls( Optional.of("https://custom-base-url.googleapis.com/"), Optional.empty()); - Client client = Client.builder().vertexAI(false).build(); + Client client = Client.builder().apiKey(API_KEY).vertexAI(false).build(); assertTrue(client.baseUrl().isPresent()); assertEquals(client.baseUrl().get(), "https://custom-base-url.googleapis.com/"); @@ -575,6 +578,7 @@ public void testClientInitializationWithBaseUrlFromSetBaseUrlsOverridesEnvironme Optional.of("https://custom-base-url.googleapis.com/"), Optional.empty()); Client client = Client.builder() + .apiKey(API_KEY) .vertexAI(false) .environmentVariables( ImmutableMap.of( @@ -591,6 +595,7 @@ public void testClientInitializationWithBaseUrlFromSetBaseUrlsOverridesEnvironme public void testClientInitializationWithBaseUrlFromEnvironment() throws Exception { Client client = Client.builder() + .apiKey(API_KEY) .vertexAI(false) .environmentVariables( ImmutableMap.of( diff --git a/src/test/java/com/google/genai/ModelsTest.java b/src/test/java/com/google/genai/ModelsTest.java index 76e7ad484c6..aa7126c88cd 100644 --- a/src/test/java/com/google/genai/ModelsTest.java +++ b/src/test/java/com/google/genai/ModelsTest.java @@ -51,6 +51,7 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.util.Arrays; +import java.util.Optional; import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; @@ -72,7 +73,20 @@ private Client createClient(boolean vertexAI, String replayId) { clientMode == null ? "replay" : clientMode, "", System.getenv("GOOGLE_GENAI_REPLAYS_DIRECTORY")); - Client client = Client.builder().debugConfig(debugConfig).vertexAI(vertexAI).build(); + String apiKey = Optional.ofNullable(ApiClient.getApiKeyFromEnv()).orElse("api-key"); + String project = Optional.ofNullable(System.getenv("GOOGLE_GENAI_PROJECT")).orElse("project"); + String location = + Optional.ofNullable(System.getenv("GOOGLE_GENAI_LOCATION")).orElse("location"); + + Client.Builder clientBuilder = Client.builder().vertexAI(vertexAI).debugConfig(debugConfig); + + if (vertexAI) { + clientBuilder.project(project).location(location); + } else { + clientBuilder.apiKey(apiKey); + } + Client client = clientBuilder.build(); + if (client.clientMode().equals("replay")) { client.setReplayId(replayId); } @@ -367,6 +381,7 @@ public void testEditImage_withMaskReference(boolean vertexAI) throws Exception { .outputMimeType("image/jpeg") .outputCompressionQuality(80) .baseSteps(32) + .addWatermark(false) .build(); // Act diff --git a/src/test/java/com/google/genai/OperationsTest.java b/src/test/java/com/google/genai/OperationsTest.java index 868f4b9646e..73036c3548c 100644 --- a/src/test/java/com/google/genai/OperationsTest.java +++ b/src/test/java/com/google/genai/OperationsTest.java @@ -20,6 +20,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue; import com.google.genai.types.GenerateVideosOperation; +import java.util.Optional; import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; @@ -35,7 +36,20 @@ private Client createClient(boolean vertexAI, String replayId) { clientMode == null ? "replay" : clientMode, "", System.getenv("GOOGLE_GENAI_REPLAYS_DIRECTORY")); - Client client = Client.builder().debugConfig(debugConfig).vertexAI(vertexAI).build(); + String apiKey = Optional.ofNullable(ApiClient.getApiKeyFromEnv()).orElse("api-key"); + String project = Optional.ofNullable(System.getenv("GOOGLE_GENAI_PROJECT")).orElse("project"); + String location = + Optional.ofNullable(System.getenv("GOOGLE_GENAI_LOCATION")).orElse("location"); + + Client.Builder clientBuilder = Client.builder().vertexAI(vertexAI).debugConfig(debugConfig); + + if (vertexAI) { + clientBuilder.project(project).location(location); + } else { + clientBuilder.apiKey(apiKey); + } + Client client = clientBuilder.build(); + if (client.clientMode().equals("replay")) { client.setReplayId(replayId); } diff --git a/src/test/java/com/google/genai/TableTest.java b/src/test/java/com/google/genai/TableTest.java index 2ba30d2f808..d493d04459a 100644 --- a/src/test/java/com/google/genai/TableTest.java +++ b/src/test/java/com/google/genai/TableTest.java @@ -283,8 +283,19 @@ static Client createClient(boolean vertexAI) { replayMode = "replay"; } DebugConfig debugConfig = new DebugConfig(replayMode, "", testsReplaysPath); + String apiKey = Optional.ofNullable(ApiClient.getApiKeyFromEnv()).orElse("api-key"); + String project = Optional.ofNullable(System.getenv("GOOGLE_GENAI_PROJECT")).orElse("project"); + String location = + Optional.ofNullable(System.getenv("GOOGLE_GENAI_LOCATION")).orElse("location"); - return Client.builder().vertexAI(vertexAI).debugConfig(debugConfig).build(); + Client.Builder clientBuilder = Client.builder().vertexAI(vertexAI).debugConfig(debugConfig); + + if (vertexAI) { + clientBuilder.project(project).location(location); + } else { + clientBuilder.apiKey(apiKey); + } + return clientBuilder.build(); } private static Object normalizeKeys(Object data) { From 52e4a72e2f3bbfa3c469ad44d4267e753a2748e2 Mon Sep 17 00:00:00 2001 From: Jaycee Li Date: Sat, 12 Jul 2025 13:21:15 -0700 Subject: [PATCH 073/602] chore: Refactor ApiClient for Vertex EasyGCP support PiperOrigin-RevId: 782389579 --- src/main/java/com/google/genai/ApiClient.java | 63 ++++---- src/main/java/com/google/genai/Client.java | 2 + .../java/com/google/genai/HttpApiClient.java | 3 +- .../com/google/genai/ReplayApiClient.java | 3 +- .../com/google/genai/HttpApiClientTest.java | 144 +++++++++++++----- 5 files changed, 150 insertions(+), 65 deletions(-) diff --git a/src/main/java/com/google/genai/ApiClient.java b/src/main/java/com/google/genai/ApiClient.java index eab17d0f35c..71b1c601c7b 100644 --- a/src/main/java/com/google/genai/ApiClient.java +++ b/src/main/java/com/google/genai/ApiClient.java @@ -100,42 +100,49 @@ protected ApiClient( } ApiClient( + Optional apiKey, Optional project, Optional location, Optional credentials, Optional customHttpOptions, Optional clientOptions) { + checkNotNull(apiKey, "API Key cannot be null"); checkNotNull(project, "project cannot be null"); checkNotNull(location, "location cannot be null"); checkNotNull(credentials, "credentials cannot be null"); checkNotNull(customHttpOptions, "customHttpOptions cannot be null"); checkNotNull(clientOptions, "clientOptions cannot be null"); - try { - this.project = Optional.of(project.orElse(System.getenv("GOOGLE_CLOUD_PROJECT"))); - } catch (NullPointerException e) { + String apiKeyValue = apiKey.orElseGet(() -> getApiKeyFromEnv()); + String projectValue = project.orElseGet(() -> System.getenv("GOOGLE_CLOUD_PROJECT")); + String locationValue = location.orElseGet(() -> System.getenv("GOOGLE_CLOUD_LOCATION")); + + boolean hasApiKey = apiKeyValue != null && !apiKeyValue.isEmpty(); + boolean hasProjectOrLocation = + (projectValue != null && !projectValue.isEmpty()) + || (locationValue != null && !locationValue.isEmpty()); + + if (!hasApiKey && !hasProjectOrLocation) { throw new IllegalArgumentException( - "Project must either be provided or set in the environment variable" - + " GOOGLE_CLOUD_PROJECT.", - e); - } - if (this.project.get().isEmpty()) { - throw new IllegalArgumentException("Project must not be empty."); + "For Vertex AI APIs, either API key, or project/location must be provided or set in the" + + " environment variable."); } - try { - this.location = Optional.of(location.orElse(System.getenv("GOOGLE_CLOUD_LOCATION"))); - } catch (NullPointerException e) { + if (hasApiKey && hasProjectOrLocation) { throw new IllegalArgumentException( - "Location must either be provided or set in the environment variable" - + " GOOGLE_CLOUD_LOCATION.", - e); - } - if (this.location.get().isEmpty()) { - throw new IllegalArgumentException("Location must not be empty."); + "For Vertex AI APIs, API key cannot be set together with project/location. Please provide" + + " only one of them."); } - this.credentials = Optional.of(credentials.orElseGet(() -> defaultCredentials())); + this.apiKey = Optional.ofNullable(apiKeyValue); + this.project = Optional.ofNullable(projectValue); + this.location = Optional.ofNullable(locationValue); + + // Only set credentials if using project/location. + this.credentials = + projectValue == null + ? Optional.empty() + : Optional.of(credentials.orElseGet(() -> defaultCredentials())); this.clientOptions = clientOptions; @@ -144,7 +151,6 @@ protected ApiClient( if (customHttpOptions.isPresent()) { this.httpOptions = mergeHttpOptions(customHttpOptions.get()); } - this.apiKey = Optional.empty(); this.vertexAI = true; this.httpClient = createHttpClient(httpOptions.timeout(), clientOptions); } @@ -400,15 +406,14 @@ static HttpOptions defaultHttpOptions(boolean vertexAI, Optional locatio HttpOptions.Builder defaultHttpOptionsBuilder = HttpOptions.builder().headers(defaultHeaders.build()); - if (vertexAI && location.isPresent()) { - defaultHttpOptionsBuilder - .baseUrl( - location.get().equalsIgnoreCase("global") - ? "https://aiplatform.googleapis.com" - : String.format("https://%s-aiplatform.googleapis.com", location.get())) - .apiVersion("v1beta1"); - } else if (vertexAI && !location.isPresent()) { - throw new IllegalArgumentException("Location must be provided for Vertex AI APIs."); + if (vertexAI) { + defaultHttpOptionsBuilder.apiVersion("v1beta1"); + if (!location.isPresent() || location.get().equalsIgnoreCase("global")) { + defaultHttpOptionsBuilder.baseUrl("https://aiplatform.googleapis.com"); + } else { + defaultHttpOptionsBuilder.baseUrl( + String.format("https://%s-aiplatform.googleapis.com", location.get())); + } } else { defaultHttpOptionsBuilder .baseUrl("https://generativelanguage.googleapis.com") diff --git a/src/main/java/com/google/genai/Client.java b/src/main/java/com/google/genai/Client.java index 5767ce49784..fa86f6a36a2 100644 --- a/src/main/java/com/google/genai/Client.java +++ b/src/main/java/com/google/genai/Client.java @@ -285,6 +285,7 @@ private Client( } else { this.apiClient = new ReplayApiClient( + /* apiKey= */ apiKey, /* project= */ project, /* location= */ location, /* credentials= */ credentials, @@ -304,6 +305,7 @@ private Client( } else { this.apiClient = new HttpApiClient( + /* apiKey= */ apiKey, /* project= */ project, /* location= */ location, /* credentials= */ credentials, diff --git a/src/main/java/com/google/genai/HttpApiClient.java b/src/main/java/com/google/genai/HttpApiClient.java index 9297487403d..fe6d02d0c06 100644 --- a/src/main/java/com/google/genai/HttpApiClient.java +++ b/src/main/java/com/google/genai/HttpApiClient.java @@ -39,12 +39,13 @@ public class HttpApiClient extends ApiClient { /** Constructs an ApiClient for Vertex AI APIs. */ HttpApiClient( + Optional apiKey, Optional project, Optional location, Optional credentials, Optional httpOptions, Optional clientOptions) { - super(project, location, credentials, httpOptions, clientOptions); + super(apiKey, project, location, credentials, httpOptions, clientOptions); } /** diff --git a/src/main/java/com/google/genai/ReplayApiClient.java b/src/main/java/com/google/genai/ReplayApiClient.java index c5e5a01f6a4..762299f44cd 100644 --- a/src/main/java/com/google/genai/ReplayApiClient.java +++ b/src/main/java/com/google/genai/ReplayApiClient.java @@ -78,6 +78,7 @@ final class ReplayApiClient extends ApiClient { /** Constructs an ApiClient for Vertex AI APIs. */ ReplayApiClient( + Optional apiKey, Optional project, Optional location, Optional credentials, @@ -86,7 +87,7 @@ final class ReplayApiClient extends ApiClient { String replaysDirectory, String replayId, String clientMode) { - super(project, location, credentials, httpOptions, clientOptions); + super(apiKey, project, location, credentials, httpOptions, clientOptions); checkNotNull(replaysDirectory, "replaysDirectory cannot be null"); checkNotNull(replayId, "replayId cannot be null"); checkNotNull(clientMode, "clientMode cannot be null"); diff --git a/src/test/java/com/google/genai/HttpApiClientTest.java b/src/test/java/com/google/genai/HttpApiClientTest.java index ef507fb4aab..f6122f3afa7 100644 --- a/src/test/java/com/google/genai/HttpApiClientTest.java +++ b/src/test/java/com/google/genai/HttpApiClientTest.java @@ -100,12 +100,13 @@ private void setMockClient(HttpApiClient client) throws Exception { credentialsField.setAccessible(true); credentialsField.set(client, Optional.of(credentials)); } - + @Test public void testRequestPostMethodWithVertexAI() throws Exception { // Arrange HttpApiClient client = new HttpApiClient( + Optional.empty(), Optional.of(PROJECT), Optional.of(LOCATION), Optional.empty(), @@ -249,7 +250,20 @@ public void testInitHttpClientMldev() throws Exception { } @Test - public void testInitHttpClientVertex() throws Exception { + public void testInitHttpClientMldevWithNoApiKey_throwsException() throws Exception { + IllegalArgumentException exception = + assertThrows( + IllegalArgumentException.class, + () -> new HttpApiClient(Optional.empty(), Optional.empty(), Optional.empty())); + + assertEquals( + "API key must either be provided or set in the environment variable" + + " GOOGLE_API_KEY or GEMINI_API_KEY. If both are set, GOOGLE_API_KEY will be used.", + exception.getMessage()); + } + + @Test + public void testInitHttpClientVertexWithProjectAndLocation() throws Exception { HttpOptions httpOptions = HttpOptions.builder() .baseUrl("https://aiplatform.googleapis.com") @@ -259,6 +273,7 @@ public void testInitHttpClientVertex() throws Exception { .build(); HttpApiClient client = new HttpApiClient( + Optional.empty(), Optional.of(PROJECT), Optional.of(LOCATION), Optional.empty(), @@ -282,6 +297,63 @@ public void testInitHttpClientVertex() throws Exception { assertEquals("6", client.httpOptions.headers().get().get("X-Server-Timeout")); } + @Test + public void testInitHttpClientVertexWithApiKey() throws Exception { + HttpApiClient client = + new HttpApiClient( + Optional.of(API_KEY), + Optional.empty(), + Optional.empty(), + Optional.empty(), + Optional.empty(), + Optional.empty()); + + assertTrue(client.vertexAI()); + assertEquals(API_KEY, client.apiKey()); + assertNull(client.project()); + assertNull(client.location()); + // Default to global endpoint for easy GCP. + assertEquals(Optional.of("https://aiplatform.googleapis.com"), client.httpOptions.baseUrl()); + } + + @Test + public void testInitHttpClientVertexWithBothApiKeyAndProject_throwsException() throws Exception { + IllegalArgumentException exception = + assertThrows( + IllegalArgumentException.class, + () -> + new HttpApiClient( + Optional.of(API_KEY), + Optional.of(PROJECT), + Optional.empty(), + Optional.empty(), + Optional.empty(), + Optional.empty())); + assertEquals( + "For Vertex AI APIs, API key cannot be set together with project/location. Please provide" + + " only one of them.", + exception.getMessage()); + } + + @Test + public void testHttpClientVertexWithNoApiKeyOrProject_throwsException() throws Exception { + IllegalArgumentException exception = + assertThrows( + IllegalArgumentException.class, + () -> + new HttpApiClient( + Optional.empty(), + Optional.empty(), + Optional.empty(), + Optional.empty(), + Optional.empty(), + Optional.empty())); + assertEquals( + "For Vertex AI APIs, either API key, or project/location must be provided or set in the" + + " environment variable.", + exception.getMessage()); + } + @Test public void testInitHttpClientMldevWithPartialHttpOptions() throws Exception { HttpOptions httpOptions = HttpOptions.builder().apiVersion("v100").timeout(5000).build(); @@ -302,6 +374,7 @@ public void testInitHttpClientVertexWithPartialHttpOptions() throws Exception { HttpOptions httpOptions = HttpOptions.builder().apiVersion("v100").timeout(5000).build(); HttpApiClient client = new HttpApiClient( + Optional.empty(), Optional.of(PROJECT), Optional.of(LOCATION), Optional.empty(), @@ -321,67 +394,67 @@ public void testInitHttpClientVertexWithPartialHttpOptions() throws Exception { public void testHttpClientMLDevTimeout() throws Exception { HttpOptions httpOptions = HttpOptions.builder().timeout(5000).build(); HttpApiClient client = - new HttpApiClient(Optional.of("api-key"), Optional.of(httpOptions), Optional.empty()); + new HttpApiClient(Optional.of(API_KEY), Optional.of(httpOptions), Optional.empty()); OkHttpClient httpClient = client.httpClient(); assertNotNull(httpClient); assertEquals(5000, httpClient.connectTimeoutMillis()); - assertEquals("api-key", client.apiKey()); + assertEquals(API_KEY, client.apiKey()); assertFalse(client.vertexAI()); } @Test public void testHttpClientVertexTimeout() throws Exception { HttpOptions httpOptions = HttpOptions.builder().timeout(4999).build(); - Optional project = Optional.of("project"); - Optional location = Optional.of("location"); - Optional credentials = - Optional.of(GoogleCredentials.getApplicationDefault()); HttpApiClient client = new HttpApiClient( - project, location, credentials, Optional.of(httpOptions), Optional.empty()); + Optional.empty(), + Optional.of(PROJECT), + Optional.of(LOCATION), + Optional.empty(), + Optional.of(httpOptions), + Optional.empty()); OkHttpClient httpClient = client.httpClient(); assertNotNull(httpClient); assertEquals(4999, httpClient.connectTimeoutMillis()); - assertEquals("project", client.project()); - assertEquals("location", client.location()); + assertEquals(PROJECT, client.project()); + assertEquals(LOCATION, client.location()); assertTrue(client.vertexAI()); } @Test public void testHttpClientNoTimeout() throws Exception { - HttpOptions httpOptions = HttpOptions.builder().build(); HttpApiClient client = - new HttpApiClient(Optional.of("api-key"), Optional.of(httpOptions), Optional.empty()); + new HttpApiClient(Optional.of(API_KEY), Optional.empty(), Optional.empty()); OkHttpClient httpClient = client.httpClient(); assertNotNull(httpClient); assertEquals(0, httpClient.connectTimeoutMillis()); - assertEquals("api-key", client.apiKey()); + assertEquals(API_KEY, client.apiKey()); assertFalse(client.httpOptions.headers().get().containsKey("X-Server-Timeout")); } @Test public void testHttpClientVertexNoTimeout() throws Exception { - HttpOptions httpOptions = HttpOptions.builder().build(); - Optional project = Optional.of("project"); - Optional location = Optional.of("location"); - Optional credentials = - Optional.of(GoogleCredentials.getApplicationDefault()); HttpApiClient client = new HttpApiClient( - project, location, credentials, Optional.of(httpOptions), Optional.empty()); + Optional.empty(), + Optional.of(PROJECT), + Optional.of(LOCATION), + Optional.empty(), + Optional.empty(), + Optional.empty()); OkHttpClient httpClient = client.httpClient(); assertNotNull(httpClient); assertEquals(0, httpClient.connectTimeoutMillis()); - assertEquals("project", client.project()); - assertEquals("location", client.location()); + assertEquals(PROJECT, client.project()); + assertEquals(LOCATION, client.location()); assertTrue(client.vertexAI()); assertFalse(client.httpOptions.headers().get().containsKey("X-Server-Timeout")); } @@ -391,11 +464,11 @@ public void testHttpClientMldevCustomClientOptions() throws Exception { ClientOptions clientOptions = ClientOptions.builder().maxConnections(64).maxConnectionsPerHost(16).build(); HttpApiClient client = - new HttpApiClient(Optional.of("api-key"), Optional.empty(), Optional.of(clientOptions)); + new HttpApiClient(Optional.of(API_KEY), Optional.empty(), Optional.of(clientOptions)); Dispatcher dispatcher = client.httpClient().dispatcher(); - assertEquals("api-key", client.apiKey()); + assertEquals(API_KEY, client.apiKey()); assertFalse(client.vertexAI()); assertEquals(64, dispatcher.getMaxRequests()); assertEquals(16, dispatcher.getMaxRequestsPerHost()); @@ -407,16 +480,17 @@ public void testHttpClientVertexCustomClientOptions() throws Exception { ClientOptions.builder().maxConnections(64).maxConnectionsPerHost(16).build(); HttpApiClient client = new HttpApiClient( - Optional.of("project"), - Optional.of("location"), + Optional.empty(), + Optional.of(PROJECT), + Optional.of(LOCATION), Optional.empty(), Optional.empty(), Optional.of(clientOptions)); Dispatcher dispatcher = client.httpClient().dispatcher(); - assertEquals("project", client.project()); - assertEquals("location", client.location()); + assertEquals(PROJECT, client.project()); + assertEquals(LOCATION, client.location()); assertTrue(client.vertexAI()); assertEquals(64, dispatcher.getMaxRequests()); assertEquals(16, dispatcher.getMaxRequestsPerHost()); @@ -425,7 +499,7 @@ public void testHttpClientVertexCustomClientOptions() throws Exception { @Test public void testHttpClientMldevDefaultClientOptions() throws Exception { HttpApiClient client = - new HttpApiClient(Optional.of("api-key"), Optional.empty(), Optional.empty()); + new HttpApiClient(Optional.of(API_KEY), Optional.empty(), Optional.empty()); Dispatcher dispatcher = client.httpClient().dispatcher(); @@ -434,20 +508,20 @@ public void testHttpClientMldevDefaultClientOptions() throws Exception { // should be equal to 5. assertEquals(64, dispatcher.getMaxRequests()); assertEquals(5, dispatcher.getMaxRequestsPerHost()); - assertEquals("api-key", client.apiKey()); + assertEquals(API_KEY, client.apiKey()); assertFalse(client.vertexAI()); } @Test public void testHttpClientWithCustomCredentials() throws Exception { GoogleCredentials credentials = Mockito.mock(GoogleCredentials.class); - HttpOptions httpOptions = HttpOptions.builder().build(); HttpApiClient client = new HttpApiClient( - Optional.of("project"), - Optional.of("us-central1"), + Optional.empty(), + Optional.of(PROJECT), + Optional.of(LOCATION), Optional.of(credentials), - Optional.of(httpOptions), + Optional.empty(), Optional.empty()); assertEquals(credentials, client.credentials.get()); } @@ -457,6 +531,7 @@ public void testHttpClientVertexWithGlobalEndpoint() throws Exception { HttpOptions httpOptions = HttpOptions.builder().build(); HttpApiClient client = new HttpApiClient( + Optional.empty(), Optional.of(PROJECT), Optional.of("global"), Optional.empty(), @@ -472,6 +547,7 @@ public void testHttpClientVertexWithGlobalEndpoint() throws Exception { public void testHttpClientVertexWithNoHttpOptions() throws Exception { HttpApiClient client = new HttpApiClient( + Optional.empty(), Optional.of(PROJECT), Optional.of("global"), Optional.empty(), From bbaf1fd1a5563ac6155e705a73cab933d1a3bfb6 Mon Sep 17 00:00:00 2001 From: Wanlin Du Date: Mon, 14 Jul 2025 09:59:03 -0700 Subject: [PATCH 074/602] chore(java): add samples for *JsonSchema. PiperOrigin-RevId: 782944785 --- .../GenerateContentWithFunctionCallJson.java | 109 ++++++++++++++++++ ...GenerateContentWithResponseJsonSchema.java | 103 +++++++++++++++++ 2 files changed, 212 insertions(+) create mode 100644 examples/src/main/java/com/google/genai/examples/GenerateContentWithFunctionCallJson.java create mode 100644 examples/src/main/java/com/google/genai/examples/GenerateContentWithResponseJsonSchema.java diff --git a/examples/src/main/java/com/google/genai/examples/GenerateContentWithFunctionCallJson.java b/examples/src/main/java/com/google/genai/examples/GenerateContentWithFunctionCallJson.java new file mode 100644 index 00000000000..a162b920fdf --- /dev/null +++ b/examples/src/main/java/com/google/genai/examples/GenerateContentWithFunctionCallJson.java @@ -0,0 +1,109 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Usage: + * + *

1a. If you are using Vertex AI, setup ADC to get credentials: + * https://cloud.google.com/docs/authentication/provide-credentials-adc#google-idp + * + *

Then set Project, Location, and USE_VERTEXAI flag as environment variables: + * + *

export GOOGLE_CLOUD_PROJECT=YOUR_PROJECT + * + *

export GOOGLE_CLOUD_LOCATION=YOUR_LOCATION + * + *

export GOOGLE_GENAI_USE_VERTEXAI=true + * + *

1b. If you are using Gemini Developer API, set an API key environment variable. You can find a + * list of available API keys here: https://aistudio.google.com/app/apikey + * + *

export GOOGLE_API_KEY=YOUR_API_KEY + * + *

2. Compile the java package and run the sample code. + * + *

mvn clean compile + * + *

mvn exec:java -Dexec.mainClass="com.google.genai.examples.GenerateContentWithFunctionCallJson" + * -Dexec.args="YOUR_MODEL_ID" + */ +package com.google.genai.examples; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.genai.Client; +import com.google.genai.types.GenerateContentConfig; +import com.google.genai.types.GenerateContentResponse; +import com.google.genai.types.Tool; +import com.google.genai.types.FunctionDeclaration; + + +/** An example of using the Unified Gen AI Java SDK to generate content with function calling. */ +public final class GenerateContentWithFunctionCallJson { + /** A callable function to get the weather. */ + public static void main(String[] args) { + String modelId = "gemini-2.0-flash-001"; + if (args.length != 0) { + modelId = args[0]; + } + + // Instantiate the client. The client by default uses the Gemini Developer API. It gets the API + // key from the environment variable `GOOGLE_API_KEY`. Vertex AI API can be used by setting the + // environment variables `GOOGLE_CLOUD_LOCATION` and `GOOGLE_CLOUD_PROJECT`, as well as setting + // `GOOGLE_GENAI_USE_VERTEXAI` to "true". + // + // Note: Some services are only available in a specific API backend (Gemini or Vertex), you will + // get a `UnsupportedOperationException` if you try to use a service that is not available in + // the backend you are using. + Client client = new Client(); + + if (client.vertexAI()) { + System.out.println("Using Vertex AI"); + } else { + System.out.println("Using Gemini Developer API"); + } + + ImmutableMap schema = + ImmutableMap.of( + "type", "object", + "properties", ImmutableMap.of("location", ImmutableMap.of("type", "string")), + "required", ImmutableList.of("location")); + + Tool toolWithFunctionDeclarations = + Tool.builder() + .functionDeclarations( + ImmutableList.of( + FunctionDeclaration.builder() + .name("get_weather") + .description("Returns the weather in a given location.") + .parametersJsonSchema(schema) + .build())) + .build(); + + // Add the two methods as callable functions to the list of tools. + GenerateContentConfig config = + GenerateContentConfig.builder() + .tools(ImmutableList.of(toolWithFunctionDeclarations)) + .build(); + + GenerateContentResponse response = + client.models.generateContent(modelId, "What is the weather in Vancouver?", config); + + System.out.println("The response is: " + response.functionCalls()); + } + + private GenerateContentWithFunctionCallJson() {} +} diff --git a/examples/src/main/java/com/google/genai/examples/GenerateContentWithResponseJsonSchema.java b/examples/src/main/java/com/google/genai/examples/GenerateContentWithResponseJsonSchema.java new file mode 100644 index 00000000000..bd3882be126 --- /dev/null +++ b/examples/src/main/java/com/google/genai/examples/GenerateContentWithResponseJsonSchema.java @@ -0,0 +1,103 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Usage: + * + *

1a. If you are using Vertex AI, setup ADC to get credentials: + * https://cloud.google.com/docs/authentication/provide-credentials-adc#google-idp + * + *

Then set Project, Location, and USE_VERTEXAI flag as environment variables: + * + *

export GOOGLE_CLOUD_PROJECT=YOUR_PROJECT + * + *

export GOOGLE_CLOUD_LOCATION=YOUR_LOCATION + * + *

export GOOGLE_GENAI_USE_VERTEXAI=true + * + *

1b. If you are using Gemini Developer API, set an API key environment variable. You can find a + * list of available API keys here: https://aistudio.google.com/app/apikey + * + *

export GOOGLE_API_KEY=YOUR_API_KEY + * + *

2. Compile the java package and run the sample code. + * + *

mvn clean compile + * + *

mvn exec:java -Dexec.mainClass="com.google.genai.examples.GenerateContentWithResponseSchema" + * -Dexec.args="YOUR_MODEL_ID" + */ +package com.google.genai.examples; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.genai.Client; +import com.google.genai.types.GenerateContentConfig; +import com.google.genai.types.GenerateContentResponse; + +/** + * GenerateContentWithResponseJsonSchema generates a content and returns a json object by passing a + * schema. + */ +public final class GenerateContentWithResponseJsonSchema { + public static void main(String[] args) { + String modelId = "gemini-2.0-flash-001"; + if (args.length != 0) { + modelId = args[0]; + } + + // Instantiate the client. The client by default uses the Gemini Developer API. It gets the API + // key from the environment variable `GOOGLE_API_KEY`. Vertex AI API can be used by setting the + // environment variables `GOOGLE_CLOUD_LOCATION` and `GOOGLE_CLOUD_PROJECT`, as well as setting + // `GOOGLE_GENAI_USE_VERTEXAI` to "true". + // + // Note: Some services are only available in a specific API backend (Gemini or Vertex), you will + // get a `UnsupportedOperationException` if you try to use a service that is not available in + // the backend you are using. + Client client = new Client(); + + if (client.vertexAI()) { + System.out.println("Using Vertex AI"); + } else { + System.out.println("Using Gemini Developer API"); + } + + ImmutableMap schema = ImmutableMap.of( + "type", "object", + "properties", ImmutableMap.of( + "recipe_name", ImmutableMap.of("type", "string"), + "ingredients", ImmutableMap.of( + "type", "array", + "items", ImmutableMap.of("type", "string") + ) + ), + "required", ImmutableList.of("recipe_name", "ingredients") + ); + GenerateContentConfig config = + GenerateContentConfig.builder() + .responseMimeType("application/json") + .candidateCount(1) + .responseJsonSchema(schema) + .build(); + + GenerateContentResponse response = + client.models.generateContent(modelId, "List a few popular cookie recipes.", config); + + System.out.println("Response: " + response.text()); + } + + private GenerateContentWithResponseJsonSchema() {} +} From 7755eabbc3dc7289c34db7b97401eddc49032c59 Mon Sep 17 00:00:00 2001 From: Ayush Agrawal Date: Mon, 14 Jul 2025 10:35:54 -0700 Subject: [PATCH 075/602] feat: Migrate Go file.create method to use the sdk_http_response field and remove http_headers PiperOrigin-RevId: 782959386 --- src/main/java/com/google/genai/Files.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/main/java/com/google/genai/Files.java b/src/main/java/com/google/genai/Files.java index 46210001f4a..752222ee32c 100644 --- a/src/main/java/com/google/genai/Files.java +++ b/src/main/java/com/google/genai/Files.java @@ -459,6 +459,12 @@ ObjectNode listFilesResponseFromMldev(JsonNode fromObject, ObjectNode parentObje @ExcludeFromGeneratedCoverageReport ObjectNode createFileResponseFromMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"sdkHttpResponse"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"sdkHttpResponse"}, + Common.getValueByPath(fromObject, new String[] {"sdkHttpResponse"})); + } return toObject; } From d5aadd247db23b707099eb593ce0bfce4d66cd84 Mon Sep 17 00:00:00 2001 From: Amy Wu Date: Mon, 14 Jul 2025 11:51:02 -0700 Subject: [PATCH 076/602] chore: add test coverage to Batches.Cancel and Batches.Create PiperOrigin-RevId: 782987281 --- src/main/java/com/google/genai/Batches.java | 428 +----------------- src/main/java/com/google/genai/Models.java | 14 - src/test/java/com/google/genai/TableTest.java | 3 +- 3 files changed, 8 insertions(+), 437 deletions(-) diff --git a/src/main/java/com/google/genai/Batches.java b/src/main/java/com/google/genai/Batches.java index 5f523be71d3..731ea5d60fe 100644 --- a/src/main/java/com/google/genai/Batches.java +++ b/src/main/java/com/google/genai/Batches.java @@ -1298,212 +1298,6 @@ ObjectNode deleteBatchJobParametersToMldev( return toObject; } - @ExcludeFromGeneratedCoverageReport - ObjectNode videoMetadataToVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"fps"}) != null) { - Common.setValueByPath( - toObject, new String[] {"fps"}, Common.getValueByPath(fromObject, new String[] {"fps"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"endOffset"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"endOffset"}, - Common.getValueByPath(fromObject, new String[] {"endOffset"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"startOffset"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"startOffset"}, - Common.getValueByPath(fromObject, new String[] {"startOffset"})); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode blobToVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"displayName"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"displayName"}, - Common.getValueByPath(fromObject, new String[] {"displayName"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"data"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"data"}, - Common.getValueByPath(fromObject, new String[] {"data"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"mimeType"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"mimeType"}, - Common.getValueByPath(fromObject, new String[] {"mimeType"})); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode fileDataToVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"displayName"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"displayName"}, - Common.getValueByPath(fromObject, new String[] {"displayName"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"fileUri"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"fileUri"}, - Common.getValueByPath(fromObject, new String[] {"fileUri"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"mimeType"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"mimeType"}, - Common.getValueByPath(fromObject, new String[] {"mimeType"})); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode partToVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"videoMetadata"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"videoMetadata"}, - videoMetadataToVertex( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"videoMetadata"})), - toObject)); - } - - if (Common.getValueByPath(fromObject, new String[] {"thought"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"thought"}, - Common.getValueByPath(fromObject, new String[] {"thought"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"inlineData"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"inlineData"}, - blobToVertex( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"inlineData"})), - toObject)); - } - - if (Common.getValueByPath(fromObject, new String[] {"fileData"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"fileData"}, - fileDataToVertex( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"fileData"})), - toObject)); - } - - if (Common.getValueByPath(fromObject, new String[] {"thoughtSignature"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"thoughtSignature"}, - Common.getValueByPath(fromObject, new String[] {"thoughtSignature"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"codeExecutionResult"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"codeExecutionResult"}, - Common.getValueByPath(fromObject, new String[] {"codeExecutionResult"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"executableCode"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"executableCode"}, - Common.getValueByPath(fromObject, new String[] {"executableCode"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"functionCall"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"functionCall"}, - Common.getValueByPath(fromObject, new String[] {"functionCall"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"functionResponse"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"functionResponse"}, - Common.getValueByPath(fromObject, new String[] {"functionResponse"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"text"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"text"}, - Common.getValueByPath(fromObject, new String[] {"text"})); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode contentToVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"parts"}) != null) { - ArrayNode keyArray = (ArrayNode) Common.getValueByPath(fromObject, new String[] {"parts"}); - ObjectMapper objectMapper = new ObjectMapper(); - ArrayNode result = objectMapper.createArrayNode(); - - for (JsonNode item : keyArray) { - result.add(partToVertex(JsonSerializable.toJsonNode(item), toObject)); - } - Common.setValueByPath(toObject, new String[] {"parts"}, result); - } - - if (Common.getValueByPath(fromObject, new String[] {"role"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"role"}, - Common.getValueByPath(fromObject, new String[] {"role"})); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode inlinedRequestToVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"model"}))) { - throw new IllegalArgumentException("model parameter is not supported in Vertex AI."); - } - - if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"contents"}))) { - throw new IllegalArgumentException("contents parameter is not supported in Vertex AI."); - } - - if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"config"}))) { - throw new IllegalArgumentException("config parameter is not supported in Vertex AI."); - } - - return toObject; - } - @ExcludeFromGeneratedCoverageReport ObjectNode batchJobSourceToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); @@ -1540,20 +1334,6 @@ ObjectNode batchJobSourceToVertex(JsonNode fromObject, ObjectNode parentObject) return toObject; } - @ExcludeFromGeneratedCoverageReport - ObjectNode inlinedResponseToVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"response"}))) { - throw new IllegalArgumentException("response parameter is not supported in Vertex AI."); - } - - if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"error"}))) { - throw new IllegalArgumentException("error parameter is not supported in Vertex AI."); - } - - return toObject; - } - @ExcludeFromGeneratedCoverageReport ObjectNode batchJobDestinationToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); @@ -2343,201 +2123,6 @@ ObjectNode jobErrorFromVertex(JsonNode fromObject, ObjectNode parentObject) { return toObject; } - @ExcludeFromGeneratedCoverageReport - ObjectNode videoMetadataFromVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"fps"}) != null) { - Common.setValueByPath( - toObject, new String[] {"fps"}, Common.getValueByPath(fromObject, new String[] {"fps"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"endOffset"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"endOffset"}, - Common.getValueByPath(fromObject, new String[] {"endOffset"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"startOffset"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"startOffset"}, - Common.getValueByPath(fromObject, new String[] {"startOffset"})); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode blobFromVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"displayName"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"displayName"}, - Common.getValueByPath(fromObject, new String[] {"displayName"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"data"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"data"}, - Common.getValueByPath(fromObject, new String[] {"data"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"mimeType"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"mimeType"}, - Common.getValueByPath(fromObject, new String[] {"mimeType"})); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode fileDataFromVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"displayName"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"displayName"}, - Common.getValueByPath(fromObject, new String[] {"displayName"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"fileUri"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"fileUri"}, - Common.getValueByPath(fromObject, new String[] {"fileUri"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"mimeType"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"mimeType"}, - Common.getValueByPath(fromObject, new String[] {"mimeType"})); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode partFromVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"videoMetadata"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"videoMetadata"}, - videoMetadataFromVertex( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"videoMetadata"})), - toObject)); - } - - if (Common.getValueByPath(fromObject, new String[] {"thought"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"thought"}, - Common.getValueByPath(fromObject, new String[] {"thought"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"inlineData"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"inlineData"}, - blobFromVertex( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"inlineData"})), - toObject)); - } - - if (Common.getValueByPath(fromObject, new String[] {"fileData"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"fileData"}, - fileDataFromVertex( - JsonSerializable.toJsonNode( - Common.getValueByPath(fromObject, new String[] {"fileData"})), - toObject)); - } - - if (Common.getValueByPath(fromObject, new String[] {"thoughtSignature"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"thoughtSignature"}, - Common.getValueByPath(fromObject, new String[] {"thoughtSignature"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"codeExecutionResult"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"codeExecutionResult"}, - Common.getValueByPath(fromObject, new String[] {"codeExecutionResult"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"executableCode"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"executableCode"}, - Common.getValueByPath(fromObject, new String[] {"executableCode"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"functionCall"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"functionCall"}, - Common.getValueByPath(fromObject, new String[] {"functionCall"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"functionResponse"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"functionResponse"}, - Common.getValueByPath(fromObject, new String[] {"functionResponse"})); - } - - if (Common.getValueByPath(fromObject, new String[] {"text"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"text"}, - Common.getValueByPath(fromObject, new String[] {"text"})); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode contentFromVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - if (Common.getValueByPath(fromObject, new String[] {"parts"}) != null) { - ArrayNode keyArray = (ArrayNode) Common.getValueByPath(fromObject, new String[] {"parts"}); - ObjectMapper objectMapper = new ObjectMapper(); - ArrayNode result = objectMapper.createArrayNode(); - - for (JsonNode item : keyArray) { - result.add(partFromVertex(JsonSerializable.toJsonNode(item), toObject)); - } - Common.setValueByPath(toObject, new String[] {"parts"}, result); - } - - if (Common.getValueByPath(fromObject, new String[] {"role"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"role"}, - Common.getValueByPath(fromObject, new String[] {"role"})); - } - - return toObject; - } - - @ExcludeFromGeneratedCoverageReport - ObjectNode inlinedRequestFromVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - - return toObject; - } - @ExcludeFromGeneratedCoverageReport ObjectNode batchJobSourceFromVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); @@ -2565,13 +2150,6 @@ ObjectNode batchJobSourceFromVertex(JsonNode fromObject, ObjectNode parentObject return toObject; } - @ExcludeFromGeneratedCoverageReport - ObjectNode inlinedResponseFromVertex(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - - return toObject; - } - @ExcludeFromGeneratedCoverageReport ObjectNode batchJobDestinationFromVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); @@ -3075,6 +2653,12 @@ public DeleteResourceJob delete(String name, DeleteBatchJobConfig config) { */ public BatchJob create(String model, BatchJobSource src, CreateBatchJobConfig config) { if (this.apiClient.vertexAI()) { + if (src.inlinedRequests().isPresent()) { + throw new GenAiIOException("inlinedRequests is not supported for Vertex AI."); + } + if (src.fileName().isPresent()) { + throw new GenAiIOException("fileName is not supported for Vertex AI."); + } if (src.gcsUri().isPresent() && src.bigqueryUri().isPresent()) { throw new GenAiIOException("Only one of gcsUri and bigqueryUri can be set."); } diff --git a/src/main/java/com/google/genai/Models.java b/src/main/java/com/google/genai/Models.java index 0e2fefa1535..c3a5a440d1a 100644 --- a/src/main/java/com/google/genai/Models.java +++ b/src/main/java/com/google/genai/Models.java @@ -4485,13 +4485,6 @@ ObjectNode generateImagesResponseFromMldev(JsonNode fromObject, ObjectNode paren return toObject; } - @ExcludeFromGeneratedCoverageReport - ObjectNode endpointFromMldev(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - - return toObject; - } - @ExcludeFromGeneratedCoverageReport ObjectNode tunedModelInfoFromMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); @@ -4519,13 +4512,6 @@ ObjectNode tunedModelInfoFromMldev(JsonNode fromObject, ObjectNode parentObject) return toObject; } - @ExcludeFromGeneratedCoverageReport - ObjectNode checkpointFromMldev(JsonNode fromObject, ObjectNode parentObject) { - ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); - - return toObject; - } - @ExcludeFromGeneratedCoverageReport ObjectNode modelFromMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); diff --git a/src/test/java/com/google/genai/TableTest.java b/src/test/java/com/google/genai/TableTest.java index d493d04459a..757605dca92 100644 --- a/src/test/java/com/google/genai/TableTest.java +++ b/src/test/java/com/google/genai/TableTest.java @@ -142,7 +142,8 @@ private static Collection createTestCases( if (testName.contains("models.edit_image") || testName.contains("models.generate_content.test_speech_with_config") || testName.contains( - "models.generate_content.test_logprobs_zero_with_response_logprobs_true")) { + "models.generate_content.test_logprobs_zero_with_response_logprobs_true") + || testName.contains("batches.create.test_with_image_blob")) { // TODO(b/431798111) String msg = " => Test skipped: replay tests are not supported for edit_image"; return Collections.singletonList(DynamicTest.dynamicTest(testName + msg, () -> {})); } From 2c07c1310e05b3247d63917c66b2b3f83f509035 Mon Sep 17 00:00:00 2001 From: Wanlin Du Date: Mon, 14 Jul 2025 12:18:09 -0700 Subject: [PATCH 077/602] chore: update existing README.md for using *JsonSchema. PiperOrigin-RevId: 782997445 --- README.md | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 71f3d23466b..dbbf39d6182 100644 --- a/README.md +++ b/README.md @@ -337,6 +337,7 @@ To get a response in JSON by passing in a response schema to the ```java package ; +import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.genai.Client; import com.google.genai.types.GenerateContentConfig; @@ -348,13 +349,18 @@ public class GenerateContentWithSchema { public static void main(String[] args) { Client client = new Client(); - Schema schema = - Schema.builder() - .type("object") - .properties( - ImmutableMap.of( - "name", Schema.builder().type(Type.Known.STRING).description("Your Name").build())) - .build(); + ImmutableMap schema = ImmutableMap.of( + "type", "object", + "properties", ImmutableMap.of( + "recipe_name", ImmutableMap.of("type", "string"), + "ingredients", ImmutableMap.of( + "type", "array", + "items", ImmutableMap.of("type", "string") + ) + ), + "required", ImmutableList.of("recipe_name", "ingredients") + ); + GenerateContentConfig config = GenerateContentConfig.builder() .responseMimeType("application/json") From 12d5dcaa4f8eaf2696d6944e50479e74afb54470 Mon Sep 17 00:00:00 2001 From: Jaycee Li Date: Mon, 14 Jul 2025 14:44:54 -0700 Subject: [PATCH 078/602] chore: Exclude deprecated methods from coverage report PiperOrigin-RevId: 783049762 --- .../com/google/genai/errors/ApiException.java | 29 ++++-- .../ExcludeFromGeneratedCoverageReport.java | 31 +++++++ .../google/genai/errors/ApiExceptionTest.java | 91 +++++++++++++++++++ 3 files changed, 142 insertions(+), 9 deletions(-) create mode 100644 src/main/java/com/google/genai/errors/ExcludeFromGeneratedCoverageReport.java diff --git a/src/main/java/com/google/genai/errors/ApiException.java b/src/main/java/com/google/genai/errors/ApiException.java index a57830f7d76..0d8fa31f77f 100644 --- a/src/main/java/com/google/genai/errors/ApiException.java +++ b/src/main/java/com/google/genai/errors/ApiException.java @@ -58,6 +58,7 @@ public ApiException(int code, String status, String message) { * @param response The response from the API call. * @deprecated Use {@link #throwFromResponse(Response)} instead. */ + @ExcludeFromGeneratedCoverageReport @Deprecated public static void throwFromResponse(CloseableHttpResponse response) { StatusLine statusLine = response.getStatusLine(); @@ -102,6 +103,8 @@ public static void throwFromResponse(Response response) { * Returns the error message from the response, if no error or error message is not found, then * returns an empty string. */ + @ExcludeFromGeneratedCoverageReport + @Deprecated static String getErrorMessageFromResponse(CloseableHttpResponse response) { HttpEntity entity = response.getEntity(); try { @@ -157,19 +160,27 @@ public static void throwFromErrorNode(ArrayNode errorNode, int code) { if (code == 200) { return; } - if (errorNode == null || errorNode.size() == 0) { - return; - } + String message = ""; - JsonNode messageNode = errorNode.get(0).get("error").get("message"); - if (messageNode != null && messageNode.isTextual()) { - message = messageNode.asText(); + try { + JsonNode messageNode = errorNode.get(0).get("error").get("message"); + if (messageNode != null && messageNode.isTextual()) { + message = messageNode.asText(); + } + } catch (NullPointerException | IndexOutOfBoundsException ignored) { + // If message is not found, do nothing and fallback to default message "". } + String status = "UNKNOWN"; - JsonNode statusNode = errorNode.get(0).get("error").get("status"); - if (statusNode != null && statusNode.isTextual()) { - status = statusNode.asText(); + try { + JsonNode statusNode = errorNode.get(0).get("error").get("status"); + if (statusNode != null && statusNode.isTextual()) { + status = statusNode.asText(); + } + } catch (NullPointerException | IndexOutOfBoundsException ignored) { + // If status is not found, do nothing and fallback to default value "UNKNOWN". } + if (code >= 400 && code < 500) { // Client errors. throw new ClientException(code, status, message); } else if (code >= 500 && code < 600) { // Server errors. diff --git a/src/main/java/com/google/genai/errors/ExcludeFromGeneratedCoverageReport.java b/src/main/java/com/google/genai/errors/ExcludeFromGeneratedCoverageReport.java new file mode 100644 index 00000000000..c7e60717c3d --- /dev/null +++ b/src/main/java/com/google/genai/errors/ExcludeFromGeneratedCoverageReport.java @@ -0,0 +1,31 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.genai.errors; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Annotation to exclude a method or constructor from the Jacoco coverage report. + * + *

Jacoco will exclude methods that have an annotation with the word "generated" in it. + */ +@Retention(RetentionPolicy.CLASS) +@Target({ElementType.METHOD, ElementType.CONSTRUCTOR, ElementType.TYPE}) +@interface ExcludeFromGeneratedCoverageReport {} \ No newline at end of file diff --git a/src/test/java/com/google/genai/errors/ApiExceptionTest.java b/src/test/java/com/google/genai/errors/ApiExceptionTest.java index 861231f7b2d..67bca4ed752 100644 --- a/src/test/java/com/google/genai/errors/ApiExceptionTest.java +++ b/src/test/java/com/google/genai/errors/ApiExceptionTest.java @@ -22,6 +22,9 @@ import static org.junit.jupiter.api.Assertions.assertInstanceOf; import static org.junit.jupiter.api.Assertions.assertThrows; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; import okhttp3.MediaType; import okhttp3.Protocol; import okhttp3.Request; @@ -30,6 +33,7 @@ import org.junit.jupiter.api.Test; class ApiExceptionTest { + private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); @Test void testThrowFromResponse_200Status_DoesNotThrow() { @@ -136,6 +140,83 @@ void testGetErrorMessage_EmptyBody() { assertEquals("", message); } + @Test + void testGetErrorMessage_NullBody() { + Response response = createFakeResponse(400, "Bad", null); + String message = ApiException.getErrorMessageFromResponse(response); + assertEquals("", message); + } + + @Test + void testThrowFromErrorNode_OkStatus_DoesNotThrow() { + ArrayNode errorNode = createErrorNode("test message", "OK", 200); + assertDoesNotThrow(() -> ApiException.throwFromErrorNode(errorNode, 200)); + } + + @Test + void testThrowFromErrorNode_ClientError_ThrowsClientException() { + String status = "BAD_REQUEST"; + String message = "Invalid request"; + ArrayNode errorNode = createErrorNode(message, status, 400); + ClientException thrown = + assertThrows(ClientException.class, () -> ApiException.throwFromErrorNode(errorNode, 400)); + assertEquals(400, thrown.code()); + assertEquals(status, thrown.status()); + assertEquals(message, thrown.message()); + } + + @Test + void testThrowFromErrorNode_ServerError_ThrowsServerException() { + String status = "INTERNAL"; + String message = "Server error"; + ArrayNode errorNode = createErrorNode(message, status, 500); + ServerException thrown = + assertThrows(ServerException.class, () -> ApiException.throwFromErrorNode(errorNode, 500)); + assertEquals(500, thrown.code()); + assertEquals(status, thrown.status()); + assertEquals(message, thrown.message()); + } + + @Test + void testThrowFromErrorNode_NullNode_defaultMessageAndStatus() { + ApiException thrown = + assertThrows(ApiException.class, () -> ApiException.throwFromErrorNode(null, 300)); + assertEquals(300, thrown.code()); + assertEquals("UNKNOWN", thrown.status()); + assertEquals("", thrown.message()); + } + + @Test + void testThrowFromErrorNode_EmptyNode_defaultMessageAndStatus() { + ApiException thrown = + assertThrows( + ApiException.class, + () -> ApiException.throwFromErrorNode(OBJECT_MAPPER.createArrayNode(), 300)); + assertEquals(300, thrown.code()); + assertEquals("UNKNOWN", thrown.status()); + assertEquals("", thrown.message()); + } + + @Test + void testThrowFromErrorNode_NoMessageNode_defaultMessage() { + ArrayNode errorNode = createErrorNode(null, "BAD_REQUEST", 400); + ApiException thrown = + assertThrows(ApiException.class, () -> ApiException.throwFromErrorNode(errorNode, 400)); + assertEquals(400, thrown.code()); + assertEquals("BAD_REQUEST", thrown.status()); + assertEquals("", thrown.message()); + } + + @Test + void testThrowFromErrorNode_NoStatusNode_defaultStatus() { + ArrayNode errorNode = createErrorNode("Invalid Request", null, 400); + ApiException thrown = + assertThrows(ApiException.class, () -> ApiException.throwFromErrorNode(errorNode, 400)); + assertEquals(400, thrown.code()); + assertEquals("UNKNOWN", thrown.status()); + assertEquals("Invalid Request", thrown.message()); + } + // Helper Methods private static Response createFakeResponse(int statusCode, String reasonPhrase, String body) { return new Response.Builder() @@ -146,4 +227,14 @@ private static Response createFakeResponse(int statusCode, String reasonPhrase, .body(body != null ? ResponseBody.create(MediaType.get("application/json"), body) : null) .build(); } + + private static ArrayNode createErrorNode(String message, String status, int code) { + ObjectNode node = OBJECT_MAPPER.createObjectNode(); + node.put("message", message); + node.put("status", status); + node.put("code", code); + ObjectNode errorNode = OBJECT_MAPPER.createObjectNode(); + errorNode.put("error", node); + return OBJECT_MAPPER.createArrayNode().add(errorNode); + } } From d63d7809df579165cc2fe14168a0505f039b4eb8 Mon Sep 17 00:00:00 2001 From: Jaycee Li Date: Wed, 16 Jul 2025 00:18:23 -0700 Subject: [PATCH 079/602] chore: Refactor ApiClient for Vertex EasyGCP support PiperOrigin-RevId: 783635581 --- src/main/java/com/google/genai/ApiClient.java | 63 ++++---- src/main/java/com/google/genai/Client.java | 2 - .../java/com/google/genai/HttpApiClient.java | 3 +- .../com/google/genai/ReplayApiClient.java | 3 +- .../com/google/genai/HttpApiClientTest.java | 144 +++++------------- 5 files changed, 65 insertions(+), 150 deletions(-) diff --git a/src/main/java/com/google/genai/ApiClient.java b/src/main/java/com/google/genai/ApiClient.java index 71b1c601c7b..eab17d0f35c 100644 --- a/src/main/java/com/google/genai/ApiClient.java +++ b/src/main/java/com/google/genai/ApiClient.java @@ -100,49 +100,42 @@ protected ApiClient( } ApiClient( - Optional apiKey, Optional project, Optional location, Optional credentials, Optional customHttpOptions, Optional clientOptions) { - checkNotNull(apiKey, "API Key cannot be null"); checkNotNull(project, "project cannot be null"); checkNotNull(location, "location cannot be null"); checkNotNull(credentials, "credentials cannot be null"); checkNotNull(customHttpOptions, "customHttpOptions cannot be null"); checkNotNull(clientOptions, "clientOptions cannot be null"); - String apiKeyValue = apiKey.orElseGet(() -> getApiKeyFromEnv()); - String projectValue = project.orElseGet(() -> System.getenv("GOOGLE_CLOUD_PROJECT")); - String locationValue = location.orElseGet(() -> System.getenv("GOOGLE_CLOUD_LOCATION")); - - boolean hasApiKey = apiKeyValue != null && !apiKeyValue.isEmpty(); - boolean hasProjectOrLocation = - (projectValue != null && !projectValue.isEmpty()) - || (locationValue != null && !locationValue.isEmpty()); - - if (!hasApiKey && !hasProjectOrLocation) { + try { + this.project = Optional.of(project.orElse(System.getenv("GOOGLE_CLOUD_PROJECT"))); + } catch (NullPointerException e) { throw new IllegalArgumentException( - "For Vertex AI APIs, either API key, or project/location must be provided or set in the" - + " environment variable."); + "Project must either be provided or set in the environment variable" + + " GOOGLE_CLOUD_PROJECT.", + e); + } + if (this.project.get().isEmpty()) { + throw new IllegalArgumentException("Project must not be empty."); } - if (hasApiKey && hasProjectOrLocation) { + try { + this.location = Optional.of(location.orElse(System.getenv("GOOGLE_CLOUD_LOCATION"))); + } catch (NullPointerException e) { throw new IllegalArgumentException( - "For Vertex AI APIs, API key cannot be set together with project/location. Please provide" - + " only one of them."); + "Location must either be provided or set in the environment variable" + + " GOOGLE_CLOUD_LOCATION.", + e); + } + if (this.location.get().isEmpty()) { + throw new IllegalArgumentException("Location must not be empty."); } - this.apiKey = Optional.ofNullable(apiKeyValue); - this.project = Optional.ofNullable(projectValue); - this.location = Optional.ofNullable(locationValue); - - // Only set credentials if using project/location. - this.credentials = - projectValue == null - ? Optional.empty() - : Optional.of(credentials.orElseGet(() -> defaultCredentials())); + this.credentials = Optional.of(credentials.orElseGet(() -> defaultCredentials())); this.clientOptions = clientOptions; @@ -151,6 +144,7 @@ protected ApiClient( if (customHttpOptions.isPresent()) { this.httpOptions = mergeHttpOptions(customHttpOptions.get()); } + this.apiKey = Optional.empty(); this.vertexAI = true; this.httpClient = createHttpClient(httpOptions.timeout(), clientOptions); } @@ -406,14 +400,15 @@ static HttpOptions defaultHttpOptions(boolean vertexAI, Optional locatio HttpOptions.Builder defaultHttpOptionsBuilder = HttpOptions.builder().headers(defaultHeaders.build()); - if (vertexAI) { - defaultHttpOptionsBuilder.apiVersion("v1beta1"); - if (!location.isPresent() || location.get().equalsIgnoreCase("global")) { - defaultHttpOptionsBuilder.baseUrl("https://aiplatform.googleapis.com"); - } else { - defaultHttpOptionsBuilder.baseUrl( - String.format("https://%s-aiplatform.googleapis.com", location.get())); - } + if (vertexAI && location.isPresent()) { + defaultHttpOptionsBuilder + .baseUrl( + location.get().equalsIgnoreCase("global") + ? "https://aiplatform.googleapis.com" + : String.format("https://%s-aiplatform.googleapis.com", location.get())) + .apiVersion("v1beta1"); + } else if (vertexAI && !location.isPresent()) { + throw new IllegalArgumentException("Location must be provided for Vertex AI APIs."); } else { defaultHttpOptionsBuilder .baseUrl("https://generativelanguage.googleapis.com") diff --git a/src/main/java/com/google/genai/Client.java b/src/main/java/com/google/genai/Client.java index fa86f6a36a2..5767ce49784 100644 --- a/src/main/java/com/google/genai/Client.java +++ b/src/main/java/com/google/genai/Client.java @@ -285,7 +285,6 @@ private Client( } else { this.apiClient = new ReplayApiClient( - /* apiKey= */ apiKey, /* project= */ project, /* location= */ location, /* credentials= */ credentials, @@ -305,7 +304,6 @@ private Client( } else { this.apiClient = new HttpApiClient( - /* apiKey= */ apiKey, /* project= */ project, /* location= */ location, /* credentials= */ credentials, diff --git a/src/main/java/com/google/genai/HttpApiClient.java b/src/main/java/com/google/genai/HttpApiClient.java index fe6d02d0c06..9297487403d 100644 --- a/src/main/java/com/google/genai/HttpApiClient.java +++ b/src/main/java/com/google/genai/HttpApiClient.java @@ -39,13 +39,12 @@ public class HttpApiClient extends ApiClient { /** Constructs an ApiClient for Vertex AI APIs. */ HttpApiClient( - Optional apiKey, Optional project, Optional location, Optional credentials, Optional httpOptions, Optional clientOptions) { - super(apiKey, project, location, credentials, httpOptions, clientOptions); + super(project, location, credentials, httpOptions, clientOptions); } /** diff --git a/src/main/java/com/google/genai/ReplayApiClient.java b/src/main/java/com/google/genai/ReplayApiClient.java index 762299f44cd..c5e5a01f6a4 100644 --- a/src/main/java/com/google/genai/ReplayApiClient.java +++ b/src/main/java/com/google/genai/ReplayApiClient.java @@ -78,7 +78,6 @@ final class ReplayApiClient extends ApiClient { /** Constructs an ApiClient for Vertex AI APIs. */ ReplayApiClient( - Optional apiKey, Optional project, Optional location, Optional credentials, @@ -87,7 +86,7 @@ final class ReplayApiClient extends ApiClient { String replaysDirectory, String replayId, String clientMode) { - super(apiKey, project, location, credentials, httpOptions, clientOptions); + super(project, location, credentials, httpOptions, clientOptions); checkNotNull(replaysDirectory, "replaysDirectory cannot be null"); checkNotNull(replayId, "replayId cannot be null"); checkNotNull(clientMode, "clientMode cannot be null"); diff --git a/src/test/java/com/google/genai/HttpApiClientTest.java b/src/test/java/com/google/genai/HttpApiClientTest.java index f6122f3afa7..ef507fb4aab 100644 --- a/src/test/java/com/google/genai/HttpApiClientTest.java +++ b/src/test/java/com/google/genai/HttpApiClientTest.java @@ -100,13 +100,12 @@ private void setMockClient(HttpApiClient client) throws Exception { credentialsField.setAccessible(true); credentialsField.set(client, Optional.of(credentials)); } - + @Test public void testRequestPostMethodWithVertexAI() throws Exception { // Arrange HttpApiClient client = new HttpApiClient( - Optional.empty(), Optional.of(PROJECT), Optional.of(LOCATION), Optional.empty(), @@ -250,20 +249,7 @@ public void testInitHttpClientMldev() throws Exception { } @Test - public void testInitHttpClientMldevWithNoApiKey_throwsException() throws Exception { - IllegalArgumentException exception = - assertThrows( - IllegalArgumentException.class, - () -> new HttpApiClient(Optional.empty(), Optional.empty(), Optional.empty())); - - assertEquals( - "API key must either be provided or set in the environment variable" - + " GOOGLE_API_KEY or GEMINI_API_KEY. If both are set, GOOGLE_API_KEY will be used.", - exception.getMessage()); - } - - @Test - public void testInitHttpClientVertexWithProjectAndLocation() throws Exception { + public void testInitHttpClientVertex() throws Exception { HttpOptions httpOptions = HttpOptions.builder() .baseUrl("https://aiplatform.googleapis.com") @@ -273,7 +259,6 @@ public void testInitHttpClientVertexWithProjectAndLocation() throws Exception { .build(); HttpApiClient client = new HttpApiClient( - Optional.empty(), Optional.of(PROJECT), Optional.of(LOCATION), Optional.empty(), @@ -297,63 +282,6 @@ public void testInitHttpClientVertexWithProjectAndLocation() throws Exception { assertEquals("6", client.httpOptions.headers().get().get("X-Server-Timeout")); } - @Test - public void testInitHttpClientVertexWithApiKey() throws Exception { - HttpApiClient client = - new HttpApiClient( - Optional.of(API_KEY), - Optional.empty(), - Optional.empty(), - Optional.empty(), - Optional.empty(), - Optional.empty()); - - assertTrue(client.vertexAI()); - assertEquals(API_KEY, client.apiKey()); - assertNull(client.project()); - assertNull(client.location()); - // Default to global endpoint for easy GCP. - assertEquals(Optional.of("https://aiplatform.googleapis.com"), client.httpOptions.baseUrl()); - } - - @Test - public void testInitHttpClientVertexWithBothApiKeyAndProject_throwsException() throws Exception { - IllegalArgumentException exception = - assertThrows( - IllegalArgumentException.class, - () -> - new HttpApiClient( - Optional.of(API_KEY), - Optional.of(PROJECT), - Optional.empty(), - Optional.empty(), - Optional.empty(), - Optional.empty())); - assertEquals( - "For Vertex AI APIs, API key cannot be set together with project/location. Please provide" - + " only one of them.", - exception.getMessage()); - } - - @Test - public void testHttpClientVertexWithNoApiKeyOrProject_throwsException() throws Exception { - IllegalArgumentException exception = - assertThrows( - IllegalArgumentException.class, - () -> - new HttpApiClient( - Optional.empty(), - Optional.empty(), - Optional.empty(), - Optional.empty(), - Optional.empty(), - Optional.empty())); - assertEquals( - "For Vertex AI APIs, either API key, or project/location must be provided or set in the" - + " environment variable.", - exception.getMessage()); - } - @Test public void testInitHttpClientMldevWithPartialHttpOptions() throws Exception { HttpOptions httpOptions = HttpOptions.builder().apiVersion("v100").timeout(5000).build(); @@ -374,7 +302,6 @@ public void testInitHttpClientVertexWithPartialHttpOptions() throws Exception { HttpOptions httpOptions = HttpOptions.builder().apiVersion("v100").timeout(5000).build(); HttpApiClient client = new HttpApiClient( - Optional.empty(), Optional.of(PROJECT), Optional.of(LOCATION), Optional.empty(), @@ -394,67 +321,67 @@ public void testInitHttpClientVertexWithPartialHttpOptions() throws Exception { public void testHttpClientMLDevTimeout() throws Exception { HttpOptions httpOptions = HttpOptions.builder().timeout(5000).build(); HttpApiClient client = - new HttpApiClient(Optional.of(API_KEY), Optional.of(httpOptions), Optional.empty()); + new HttpApiClient(Optional.of("api-key"), Optional.of(httpOptions), Optional.empty()); OkHttpClient httpClient = client.httpClient(); assertNotNull(httpClient); assertEquals(5000, httpClient.connectTimeoutMillis()); - assertEquals(API_KEY, client.apiKey()); + assertEquals("api-key", client.apiKey()); assertFalse(client.vertexAI()); } @Test public void testHttpClientVertexTimeout() throws Exception { HttpOptions httpOptions = HttpOptions.builder().timeout(4999).build(); + Optional project = Optional.of("project"); + Optional location = Optional.of("location"); + Optional credentials = + Optional.of(GoogleCredentials.getApplicationDefault()); HttpApiClient client = new HttpApiClient( - Optional.empty(), - Optional.of(PROJECT), - Optional.of(LOCATION), - Optional.empty(), - Optional.of(httpOptions), - Optional.empty()); + project, location, credentials, Optional.of(httpOptions), Optional.empty()); OkHttpClient httpClient = client.httpClient(); assertNotNull(httpClient); assertEquals(4999, httpClient.connectTimeoutMillis()); - assertEquals(PROJECT, client.project()); - assertEquals(LOCATION, client.location()); + assertEquals("project", client.project()); + assertEquals("location", client.location()); assertTrue(client.vertexAI()); } @Test public void testHttpClientNoTimeout() throws Exception { + HttpOptions httpOptions = HttpOptions.builder().build(); HttpApiClient client = - new HttpApiClient(Optional.of(API_KEY), Optional.empty(), Optional.empty()); + new HttpApiClient(Optional.of("api-key"), Optional.of(httpOptions), Optional.empty()); OkHttpClient httpClient = client.httpClient(); assertNotNull(httpClient); assertEquals(0, httpClient.connectTimeoutMillis()); - assertEquals(API_KEY, client.apiKey()); + assertEquals("api-key", client.apiKey()); assertFalse(client.httpOptions.headers().get().containsKey("X-Server-Timeout")); } @Test public void testHttpClientVertexNoTimeout() throws Exception { + HttpOptions httpOptions = HttpOptions.builder().build(); + Optional project = Optional.of("project"); + Optional location = Optional.of("location"); + Optional credentials = + Optional.of(GoogleCredentials.getApplicationDefault()); HttpApiClient client = new HttpApiClient( - Optional.empty(), - Optional.of(PROJECT), - Optional.of(LOCATION), - Optional.empty(), - Optional.empty(), - Optional.empty()); + project, location, credentials, Optional.of(httpOptions), Optional.empty()); OkHttpClient httpClient = client.httpClient(); assertNotNull(httpClient); assertEquals(0, httpClient.connectTimeoutMillis()); - assertEquals(PROJECT, client.project()); - assertEquals(LOCATION, client.location()); + assertEquals("project", client.project()); + assertEquals("location", client.location()); assertTrue(client.vertexAI()); assertFalse(client.httpOptions.headers().get().containsKey("X-Server-Timeout")); } @@ -464,11 +391,11 @@ public void testHttpClientMldevCustomClientOptions() throws Exception { ClientOptions clientOptions = ClientOptions.builder().maxConnections(64).maxConnectionsPerHost(16).build(); HttpApiClient client = - new HttpApiClient(Optional.of(API_KEY), Optional.empty(), Optional.of(clientOptions)); + new HttpApiClient(Optional.of("api-key"), Optional.empty(), Optional.of(clientOptions)); Dispatcher dispatcher = client.httpClient().dispatcher(); - assertEquals(API_KEY, client.apiKey()); + assertEquals("api-key", client.apiKey()); assertFalse(client.vertexAI()); assertEquals(64, dispatcher.getMaxRequests()); assertEquals(16, dispatcher.getMaxRequestsPerHost()); @@ -480,17 +407,16 @@ public void testHttpClientVertexCustomClientOptions() throws Exception { ClientOptions.builder().maxConnections(64).maxConnectionsPerHost(16).build(); HttpApiClient client = new HttpApiClient( - Optional.empty(), - Optional.of(PROJECT), - Optional.of(LOCATION), + Optional.of("project"), + Optional.of("location"), Optional.empty(), Optional.empty(), Optional.of(clientOptions)); Dispatcher dispatcher = client.httpClient().dispatcher(); - assertEquals(PROJECT, client.project()); - assertEquals(LOCATION, client.location()); + assertEquals("project", client.project()); + assertEquals("location", client.location()); assertTrue(client.vertexAI()); assertEquals(64, dispatcher.getMaxRequests()); assertEquals(16, dispatcher.getMaxRequestsPerHost()); @@ -499,7 +425,7 @@ public void testHttpClientVertexCustomClientOptions() throws Exception { @Test public void testHttpClientMldevDefaultClientOptions() throws Exception { HttpApiClient client = - new HttpApiClient(Optional.of(API_KEY), Optional.empty(), Optional.empty()); + new HttpApiClient(Optional.of("api-key"), Optional.empty(), Optional.empty()); Dispatcher dispatcher = client.httpClient().dispatcher(); @@ -508,20 +434,20 @@ public void testHttpClientMldevDefaultClientOptions() throws Exception { // should be equal to 5. assertEquals(64, dispatcher.getMaxRequests()); assertEquals(5, dispatcher.getMaxRequestsPerHost()); - assertEquals(API_KEY, client.apiKey()); + assertEquals("api-key", client.apiKey()); assertFalse(client.vertexAI()); } @Test public void testHttpClientWithCustomCredentials() throws Exception { GoogleCredentials credentials = Mockito.mock(GoogleCredentials.class); + HttpOptions httpOptions = HttpOptions.builder().build(); HttpApiClient client = new HttpApiClient( - Optional.empty(), - Optional.of(PROJECT), - Optional.of(LOCATION), + Optional.of("project"), + Optional.of("us-central1"), Optional.of(credentials), - Optional.empty(), + Optional.of(httpOptions), Optional.empty()); assertEquals(credentials, client.credentials.get()); } @@ -531,7 +457,6 @@ public void testHttpClientVertexWithGlobalEndpoint() throws Exception { HttpOptions httpOptions = HttpOptions.builder().build(); HttpApiClient client = new HttpApiClient( - Optional.empty(), Optional.of(PROJECT), Optional.of("global"), Optional.empty(), @@ -547,7 +472,6 @@ public void testHttpClientVertexWithGlobalEndpoint() throws Exception { public void testHttpClientVertexWithNoHttpOptions() throws Exception { HttpApiClient client = new HttpApiClient( - Optional.empty(), Optional.of(PROJECT), Optional.of("global"), Optional.empty(), From 14c008a8fc40f712f922526dc00e2596705dc134 Mon Sep 17 00:00:00 2001 From: Ayush Agrawal Date: Wed, 16 Jul 2025 12:26:09 -0700 Subject: [PATCH 080/602] feat: add tests for the async Operations module PiperOrigin-RevId: 783852739 --- .../com/google/genai/AsyncOperationsTest.java | 160 ++++++++++++++++++ 1 file changed, 160 insertions(+) create mode 100644 src/test/java/com/google/genai/AsyncOperationsTest.java diff --git a/src/test/java/com/google/genai/AsyncOperationsTest.java b/src/test/java/com/google/genai/AsyncOperationsTest.java new file mode 100644 index 00000000000..93041881b23 --- /dev/null +++ b/src/test/java/com/google/genai/AsyncOperationsTest.java @@ -0,0 +1,160 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.genai; + +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import com.google.genai.types.GenerateVideosConfig; +import com.google.genai.types.GenerateVideosOperation; +import java.util.Optional; +import java.util.concurrent.ExecutionException; +import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; + +@EnabledIfEnvironmentVariable( + named = "GOOGLE_GENAI_REPLAYS_DIRECTORY", + matches = ".*genai/replays.*") +public class AsyncOperationsTest { + private Client createClient(boolean vertexAI, String replayId) { + String clientMode = System.getenv("GOOGLE_GENAI_CLIENT_MODE"); + DebugConfig debugConfig = + new DebugConfig( + clientMode == null ? "replay" : clientMode, + "", + System.getenv("GOOGLE_GENAI_REPLAYS_DIRECTORY")); + String apiKey = Optional.ofNullable(ApiClient.getApiKeyFromEnv()).orElse("api-key"); + String project = Optional.ofNullable(System.getenv("GOOGLE_GENAI_PROJECT")).orElse("project"); + String location = + Optional.ofNullable(System.getenv("GOOGLE_GENAI_LOCATION")).orElse("location"); + + Client.Builder clientBuilder = Client.builder().vertexAI(vertexAI).debugConfig(debugConfig); + + if (vertexAI) { + clientBuilder.project(project).location(location); + } else { + clientBuilder.apiKey(apiKey); + } + Client client = clientBuilder.build(); + + if (client.clientMode().equals("replay")) { + client.setReplayId(replayId); + } + return client; + } + + @ParameterizedTest + @ValueSource(booleans = {false, true}) + public void testAsyncGetVideosOperation(boolean vertexAI) + throws ExecutionException, InterruptedException { + // Arrange + String suffix = vertexAI ? "vertex" : "mldev"; + Client client = + createClient( + vertexAI, + "tests/models/generate_videos/test_create_operation_to_poll." + suffix + ".json"); + + String operationName = + vertexAI + ? "projects//locations//publishers/google/models/veo-2.0-generate-001/operations/ddb46542-07ed-4000-958d-655fbffb05a4" + : "models/veo-2.0-generate-001/operations/ren0ubieaocs"; + + // Act + GenerateVideosOperation generateVideosOperation = + client + .async + .operations + .getVideosOperation(GenerateVideosOperation.builder().name(operationName).build(), null) + .get(); + + // GenerateVideosOperation.done() is empty if the operation is not done. + while (!generateVideosOperation.done().filter(Boolean::booleanValue).isPresent()) { + try { + if (!client.clientMode().equals("replay")) { + Thread.sleep(10000); // Sleep for 10 seconds. + System.out.println("Waiting for operation to complete..."); + } + generateVideosOperation = + client.async.operations.getVideosOperation(generateVideosOperation, null).get(); + } catch (InterruptedException e) { + System.out.println("Thread was interrupted while sleeping."); + Thread.currentThread().interrupt(); + } + } + + // Assert + assertTrue(generateVideosOperation.done().get()); + assertNotNull( + generateVideosOperation.response().get().generatedVideos().get().get(0).video().get()); + } + + @ParameterizedTest + @ValueSource(booleans = {false, true}) + public void testTextToVideoPollAsync(boolean vertexAI) + throws ExecutionException, InterruptedException { + // Arrange + String suffix = vertexAI ? "vertex" : "mldev"; + Client client = + createClient( + vertexAI, + "tests/models/generate_videos/test_text_to_video_poll_async." + suffix + ".json"); + + String model = "veo-2.0-generate-001"; + String prompt = "A neon hologram of a cat driving at top speed"; + GenerateVideosConfig.Builder configBuilder = GenerateVideosConfig.builder(); + if (vertexAI) { + configBuilder.outputGcsUri("gs://unified-genai-tests/tmp/genai/video/outputs"); + } + GenerateVideosConfig config = configBuilder.build(); + + // Act + GenerateVideosOperation generateVideosOperation = + client.async.models.generateVideos(model, prompt, null, null, config).get(); + + // GenerateVideosOperation.done() is empty if the operation is not done. + while (!generateVideosOperation.done().filter(Boolean::booleanValue).isPresent()) { + try { + if (!client.clientMode().equals("replay")) { + Thread.sleep(10000); // Sleep for 10 seconds. + System.out.println("Waiting for operation to complete..."); + } + generateVideosOperation = + client.async.operations.getVideosOperation(generateVideosOperation, null).get(); + } catch (InterruptedException e) { + System.out.println("Thread was interrupted while sleeping."); + Thread.currentThread().interrupt(); + } + } + + // Assert + assertTrue(generateVideosOperation.done().get()); + assertNotNull( + generateVideosOperation.response().get().generatedVideos().get().get(0).video().get()); + assertTrue( + generateVideosOperation + .response() + .get() + .generatedVideos() + .get() + .get(0) + .video() + .get() + .uri() + .isPresent()); + } +} From 0ab209db99bf98b58f7273fb12843984c42cb910 Mon Sep 17 00:00:00 2001 From: Ayush Agrawal Date: Wed, 16 Jul 2025 12:32:34 -0700 Subject: [PATCH 081/602] feat: add Tuning support for Java PiperOrigin-RevId: 783854856 --- .../com/google/genai/examples/TuningJobs.java | 116 ++ .../genai/examples/TuningJobsAsync.java | 161 +++ .../java/com/google/genai/AsyncTunings.java | 120 ++ src/main/java/com/google/genai/BasePager.java | 5 +- src/main/java/com/google/genai/Client.java | 4 + src/main/java/com/google/genai/Common.java | 4 +- .../java/com/google/genai/Transformers.java | 88 ++ src/main/java/com/google/genai/Tunings.java | 1245 +++++++++++++++++ .../com/google/genai/types/AdapterSize.java | 119 ++ .../genai/types/CreateTuningJobConfig.java | 238 ++++ .../types/CreateTuningJobParameters.java | 117 ++ .../genai/types/DatasetDistribution.java | 177 +++ ...DatasetDistributionDistributionBucket.java | 95 ++ .../com/google/genai/types/DatasetStats.java | 215 +++ .../genai/types/DistillationDataStats.java | 77 + .../types/DistillationHyperParameters.java | 119 ++ .../google/genai/types/DistillationSpec.java | 175 +++ .../google/genai/types/EncryptionSpec.java | 78 ++ .../genai/types/GetTuningJobConfig.java | 77 + .../genai/types/GetTuningJobParameters.java | 91 ++ .../google/genai/types/GoogleRpcStatus.java | 121 ++ .../genai/types/ListTuningJobsConfig.java | 113 ++ .../genai/types/ListTuningJobsParameters.java | 79 ++ .../genai/types/ListTuningJobsResponse.java | 109 ++ .../com/google/genai/types/Operation.java | 123 ++ .../genai/types/PartnerModelTuningSpec.java | 105 ++ .../types/SupervisedHyperParameters.java | 123 ++ .../types/SupervisedTuningDataStats.java | 294 ++++ .../SupervisedTuningDatasetDistribution.java | 193 +++ ...uningDatasetDistributionDatasetBucket.java | 96 ++ .../genai/types/SupervisedTuningSpec.java | 128 ++ .../com/google/genai/types/TunedModel.java | 131 ++ .../genai/types/TunedModelCheckpoint.java | 108 ++ .../google/genai/types/TuningDataStats.java | 101 ++ .../com/google/genai/types/TuningDataset.java | 122 ++ .../com/google/genai/types/TuningExample.java | 80 ++ .../com/google/genai/types/TuningJob.java | 461 ++++++ .../google/genai/types/TuningOperation.java | 123 ++ .../genai/types/TuningValidationDataset.java | 85 ++ src/test/java/com/google/genai/TableTest.java | 35 +- .../com/google/genai/TransformersTest.java | 115 ++ 41 files changed, 6162 insertions(+), 4 deletions(-) create mode 100644 examples/src/main/java/com/google/genai/examples/TuningJobs.java create mode 100644 examples/src/main/java/com/google/genai/examples/TuningJobsAsync.java create mode 100644 src/main/java/com/google/genai/AsyncTunings.java create mode 100644 src/main/java/com/google/genai/Tunings.java create mode 100644 src/main/java/com/google/genai/types/AdapterSize.java create mode 100644 src/main/java/com/google/genai/types/CreateTuningJobConfig.java create mode 100644 src/main/java/com/google/genai/types/CreateTuningJobParameters.java create mode 100644 src/main/java/com/google/genai/types/DatasetDistribution.java create mode 100644 src/main/java/com/google/genai/types/DatasetDistributionDistributionBucket.java create mode 100644 src/main/java/com/google/genai/types/DatasetStats.java create mode 100644 src/main/java/com/google/genai/types/DistillationDataStats.java create mode 100644 src/main/java/com/google/genai/types/DistillationHyperParameters.java create mode 100644 src/main/java/com/google/genai/types/DistillationSpec.java create mode 100644 src/main/java/com/google/genai/types/EncryptionSpec.java create mode 100644 src/main/java/com/google/genai/types/GetTuningJobConfig.java create mode 100644 src/main/java/com/google/genai/types/GetTuningJobParameters.java create mode 100644 src/main/java/com/google/genai/types/GoogleRpcStatus.java create mode 100644 src/main/java/com/google/genai/types/ListTuningJobsConfig.java create mode 100644 src/main/java/com/google/genai/types/ListTuningJobsParameters.java create mode 100644 src/main/java/com/google/genai/types/ListTuningJobsResponse.java create mode 100644 src/main/java/com/google/genai/types/Operation.java create mode 100644 src/main/java/com/google/genai/types/PartnerModelTuningSpec.java create mode 100644 src/main/java/com/google/genai/types/SupervisedHyperParameters.java create mode 100644 src/main/java/com/google/genai/types/SupervisedTuningDataStats.java create mode 100644 src/main/java/com/google/genai/types/SupervisedTuningDatasetDistribution.java create mode 100644 src/main/java/com/google/genai/types/SupervisedTuningDatasetDistributionDatasetBucket.java create mode 100644 src/main/java/com/google/genai/types/SupervisedTuningSpec.java create mode 100644 src/main/java/com/google/genai/types/TunedModel.java create mode 100644 src/main/java/com/google/genai/types/TunedModelCheckpoint.java create mode 100644 src/main/java/com/google/genai/types/TuningDataStats.java create mode 100644 src/main/java/com/google/genai/types/TuningDataset.java create mode 100644 src/main/java/com/google/genai/types/TuningExample.java create mode 100644 src/main/java/com/google/genai/types/TuningJob.java create mode 100644 src/main/java/com/google/genai/types/TuningOperation.java create mode 100644 src/main/java/com/google/genai/types/TuningValidationDataset.java diff --git a/examples/src/main/java/com/google/genai/examples/TuningJobs.java b/examples/src/main/java/com/google/genai/examples/TuningJobs.java new file mode 100644 index 00000000000..67765fcdde0 --- /dev/null +++ b/examples/src/main/java/com/google/genai/examples/TuningJobs.java @@ -0,0 +1,116 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Usage: + * + *

1a. If you are using Vertex AI, setup ADC to get credentials: + * https://cloud.google.com/docs/authentication/provide-credentials-adc#google-idp + * + *

Then set Project, Location, and USE_VERTEXAI flag as environment variables: + * + *

export GOOGLE_CLOUD_PROJECT=YOUR_PROJECT + * + *

export GOOGLE_CLOUD_LOCATION=YOUR_LOCATION + * + *

export GOOGLE_GENAI_USE_VERTEXAI=true + * + *

1b. If you are using Gemini Developer API, set an API key environment variable. You can find a + * list of available API keys here: https://aistudio.google.com/app/apikey + * + *

export GOOGLE_API_KEY=YOUR_API_KEY + * + *

2. Compile the java package and run the sample code. + * + *

mvn clean compile + * + *

mvn exec:java -Dexec.mainClass="com.google.genai.examples.TuningJobs" + * -Dexec.args="YOUR_MODEL_ID" + */ +package com.google.genai.examples; + +import com.google.genai.Client; +import com.google.genai.types.ListTuningJobsConfig; +import com.google.genai.types.TuningDataset; +import com.google.genai.types.TuningJob; + +/** An example of using the Unified Gen AI Java SDK to do operations on tuning jobs. */ +public final class TuningJobs { + + public static void main(String[] args) { + String modelId = "gemini-2.0-flash-001"; + if (args.length != 0) { + modelId = args[0]; + } + + // Instantiate the client. The client by default uses the Gemini Developer API. It gets the API + // key from the environment variable `GOOGLE_API_KEY`. Vertex AI API can be used by setting the + // environment variables `GOOGLE_CLOUD_LOCATION` and `GOOGLE_CLOUD_PROJECT`, as well as setting + // `GOOGLE_GENAI_USE_VERTEXAI` to "true". + // + // Note: Some services are only available in a specific API backend (Gemini or Vertex), you will + // get a `UnsupportedOperationException` if you try to use a service that is not available in + // the backend you are using. + Client client = new Client(); + + if (client.vertexAI()) { + System.out.println("Using Vertex AI"); + // Create a tuning job. + TuningDataset tuningDataset = + TuningDataset.builder() + .gcsUri( + "gs://cloud-samples-data/ai-platform/generative_ai/gemini-1_5/text/sft_train_data.jsonl") + .build(); + TuningJob tuningJob1 = client.tunings.tune(modelId, tuningDataset, null); + System.out.println("Created tuning job: " + tuningJob1); + // Get the tuning job by name. + TuningJob tuningJob2 = client.tunings.get(tuningJob1.name().get(), null); + System.out.println("Get tuning job: " + tuningJob2); + + // Wait for the tuned model to be available. + String tunedModel = ""; + while (tunedModel.isEmpty()) { + System.out.println("Waiting for tuned model to be available"); + try { + Thread.sleep(10000); // Sleep for 10 seconds. + } catch (InterruptedException e) { + System.out.println("Thread was interrupted while sleeping."); + Thread.currentThread().interrupt(); + } + // Get the tuning job. + TuningJob fetchedTuningJob = client.tunings.get(tuningJob1.name().get(), null); + if (fetchedTuningJob.tunedModel().isPresent() + && fetchedTuningJob.tunedModel().get().model().isPresent()) { + tunedModel = fetchedTuningJob.tunedModel().get().model().get(); + } + } + System.out.println("Tuned model: " + tunedModel); + System.out.println(); + } else { + System.out.println("Using Gemini Developer API"); + } + + // List tuning jobs. + System.out.println("List tuning jobs resource names: "); + for (TuningJob t : + client.tunings.list(ListTuningJobsConfig.builder().pageSize(5).build()).page()) { + System.out.println(t.name().get()); + System.out.println(t.state().get()); + } + } + + private TuningJobs() {} +} diff --git a/examples/src/main/java/com/google/genai/examples/TuningJobsAsync.java b/examples/src/main/java/com/google/genai/examples/TuningJobsAsync.java new file mode 100644 index 00000000000..b76235894fb --- /dev/null +++ b/examples/src/main/java/com/google/genai/examples/TuningJobsAsync.java @@ -0,0 +1,161 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Usage: + * + *

1a. If you are using Vertex AI, setup ADC to get credentials: + * https://cloud.google.com/docs/authentication/provide-credentials-adc#google-idp + * + *

Then set Project, Location, and USE_VERTEXAI flag as environment variables: + * + *

export GOOGLE_CLOUD_PROJECT=YOUR_PROJECT + * + *

export GOOGLE_CLOUD_LOCATION=YOUR_LOCATION + * + *

export GOOGLE_GENAI_USE_VERTEXAI=true + * + *

1b. If you are using Gemini Developer API, set an API key environment variable. You can find a + * list of available API keys here: https://aistudio.google.com/app/apikey + * + *

export GOOGLE_API_KEY=YOUR_API_KEY + * + *

2. Compile the java package and run the sample code. + * + *

mvn clean compile + * + *

mvn exec:java -Dexec.mainClass="com.google.genai.examples.TuningJobsAsync" + * -Dexec.args="YOUR_MODEL_ID" + */ +package com.google.genai.examples; + +import com.google.genai.AsyncPager; +import com.google.genai.Client; +import com.google.genai.types.ListTuningJobsConfig; +import com.google.genai.types.TuningDataset; +import com.google.genai.types.TuningJob; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; + +/** An example of using the Unified Gen AI Java SDK to do async operations on tuning jobs. */ +public final class TuningJobsAsync { + + public static void main(String[] args) { + String modelId = "gemini-2.0-flash-001"; + if (args.length != 0) { + modelId = args[0]; + } + + // Instantiate the client. The client by default uses the Gemini Developer API. It gets the API + // key from the environment variable `GOOGLE_API_KEY`. Vertex AI API can be used by setting the + // environment variables `GOOGLE_CLOUD_LOCATION` and `GOOGLE_CLOUD_PROJECT`, as well as setting + // `GOOGLE_GENAI_USE_VERTEXAI` to "true". + // + // Note: Some services are only available in a specific API backend (Gemini or Vertex), you will + // get a `UnsupportedOperationException` if you try to use a service that is not available in + // the backend you are using. + Client client = new Client(); + ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(); + + try { + if (client.vertexAI()) { + System.out.println("Using Vertex AI"); + // Create a tuning job. + TuningDataset tuningDataset = + TuningDataset.builder() + .gcsUri( + "gs://cloud-samples-data/ai-platform/generative_ai/gemini-1_5/text/sft_train_data.jsonl") + .build(); + CompletableFuture tuningJob1Future = + client.async.tunings.tune(modelId, tuningDataset, null); + tuningJob1Future + .thenCompose( + tuningJob -> { + System.out.println("Created tuning job: " + tuningJob.name().get()); + return pollUntilComplete(tuningJob.name().get(), client, scheduler); + }) + .thenAccept( + finalJob -> { + String tunedModel = finalJob.tunedModel().get().model().get(); + System.out.println("Tuned model: " + tunedModel); + }) + .join(); + System.out.println(); + } else { + System.out.println("Using Gemini Developer API"); + } + + // List tuning jobs. + CompletableFuture> asyncPagerFuture = + client.async.tunings.list(ListTuningJobsConfig.builder().pageSize(5).build()); + asyncPagerFuture + .thenCompose( + asyncPager -> { + System.out.println("List tuning jobs resource names: "); + return asyncPager.page(); + }) + .thenAccept( + page -> { + page.forEach( + job -> System.out.println(job.name().get() + "\n" + job.state().get())); + }) + .join(); + } finally { + scheduler.shutdown(); + } + } + + @SuppressWarnings("FutureReturnValueIgnored") + // Polls the tuning job status asynchronously until it is complete. + private static CompletableFuture pollUntilComplete( + String jobName, Client client, ScheduledExecutorService scheduler) { + + return client + .async + .tunings + .get(jobName, null) + .thenCompose( + job -> { + // Check if the model is ready. + if (job.tunedModel().isPresent() && job.tunedModel().get().model().isPresent()) { + return CompletableFuture.completedFuture(job); + } else { + // The job is not done. Schedule the next poll. + System.out.println( + "Waiting for tuned model to be available... Current state: " + + job.state().get()); + CompletableFuture result = new CompletableFuture<>(); + // Schedule the next call to this same method after a 10-second delay. + scheduler.schedule( + () -> + pollUntilComplete(jobName, client, scheduler) + .thenAccept(result::complete) + .exceptionally( + ex -> { + result.completeExceptionally(ex); + return null; + }), + 10, + TimeUnit.SECONDS); + return result; + } + }); + } + + private TuningJobsAsync() {} +} diff --git a/src/main/java/com/google/genai/AsyncTunings.java b/src/main/java/com/google/genai/AsyncTunings.java new file mode 100644 index 00000000000..239a822346e --- /dev/null +++ b/src/main/java/com/google/genai/AsyncTunings.java @@ -0,0 +1,120 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Auto-generated code. Do not edit. + +package com.google.genai; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ObjectNode; +import com.google.genai.errors.GenAiIOException; +import com.google.genai.types.CreateTuningJobConfig; +import com.google.genai.types.GetTuningJobConfig; +import com.google.genai.types.JobState; +import com.google.genai.types.ListTuningJobsConfig; +import com.google.genai.types.TuningDataset; +import com.google.genai.types.TuningJob; +import com.google.genai.types.TuningOperation; +import java.util.concurrent.CompletableFuture; +import java.util.function.Function; + +/** Async module of {@link Tunings} */ +public final class AsyncTunings { + Tunings tunings; + + public AsyncTunings(ApiClient apiClient) { + this.tunings = new Tunings(apiClient); + } + + /** + * Asynchronously makes an API request to get a tuning job. + * + * @param name The resource name of the tuning job. + * @param config A {@link GetTuningJobConfig} for configuring the get request. + * @return A CompletableFuture that resolves to a {@link TuningJob} object. + */ + public CompletableFuture get(String name, GetTuningJobConfig config) { + return CompletableFuture.supplyAsync(() -> tunings.privateGet(name, config)); + } + + /** + * Asynchronously makes an API request to list the available tuning jobs. + * + * @param config A {@link ListTuningJobsConfig} for configuring the list request. + * @return A CompletableFuture that resolves to a {@link AsyncPager}. The AsyncPager has a + * `forEach` method that can be used to asynchronously process items in the page and + * automatically query the next page once the current page is exhausted. + */ + @SuppressWarnings("PatternMatchingInstanceof") + public CompletableFuture> list(ListTuningJobsConfig config) { + Function> request = + requestConfig -> { + if (!(requestConfig instanceof ListTuningJobsConfig)) { + throw new GenAiIOException( + "Internal error: Pager expected ListTuningJobsConfig but received " + + requestConfig.getClass().getName()); + } + return CompletableFuture.supplyAsync( + () -> + JsonSerializable.toJsonNode( + tunings.privateList((ListTuningJobsConfig) requestConfig))); + }; + return CompletableFuture.supplyAsync( + () -> + new AsyncPager<>( + Pager.PagedItem.TUNING_JOBS, + request, + (ObjectNode) JsonSerializable.toJsonNode(config), + request.apply(config))); + } + + /** + * Asynchronously makes an API request to create a supervised fine-tuning job. + * + *

This method is experimental. + * + * @param baseModel The base model to tune. + * @param trainingDataset The training dataset to use for tuning. + * @param config A {@link CreateTuningJobConfig} for configuring the create request. + * @return A CompletableFuture that resolves to a {@link TuningJob} object. + */ + public CompletableFuture tune( + String baseModel, TuningDataset trainingDataset, CreateTuningJobConfig config) { + return CompletableFuture.supplyAsync( + () -> { + if (tunings.apiClient.vertexAI()) { + return tunings.privateTune(baseModel, trainingDataset, config); + } else { + TuningOperation operation = + tunings.privateTuneMldev(baseModel, trainingDataset, config); + String tunedModelName = ""; + if (operation.metadata().isPresent() + && operation.metadata().get().containsKey("tunedModel")) { + tunedModelName = (String) operation.metadata().get().get("tunedModel"); + } else { + if (!operation.name().isPresent()) { + throw new IllegalArgumentException("Operation name is required."); + } + tunedModelName = operation.name().get().split("/operations/")[0]; + } + return TuningJob.builder() + .name(tunedModelName) + .state(JobState.Known.JOB_STATE_QUEUED) + .build(); + } + }); + } +} diff --git a/src/main/java/com/google/genai/BasePager.java b/src/main/java/com/google/genai/BasePager.java index d8e7dabe6ac..33d026b540f 100644 --- a/src/main/java/com/google/genai/BasePager.java +++ b/src/main/java/com/google/genai/BasePager.java @@ -27,7 +27,9 @@ import com.google.genai.types.ListCachedContentsConfig; import com.google.genai.types.ListFilesConfig; import com.google.genai.types.ListModelsConfig; +import com.google.genai.types.ListTuningJobsConfig; import com.google.genai.types.Model; +import com.google.genai.types.TuningJob; import java.util.ArrayList; import java.util.List; @@ -39,7 +41,8 @@ static enum PagedItem { MODELS("models", Model.class, ListModelsConfig.class), CACHED_CONTENTS("cachedContents", CachedContent.class, ListCachedContentsConfig.class), FILES("files", File.class, ListFilesConfig.class), - BATCH_JOBS("batchJobs", BatchJob.class, ListBatchJobsConfig.class); + BATCH_JOBS("batchJobs", BatchJob.class, ListBatchJobsConfig.class), + TUNING_JOBS("tuningJobs", TuningJob.class, ListTuningJobsConfig.class); private final String fieldName; private final Class itemClass; diff --git a/src/main/java/com/google/genai/Client.java b/src/main/java/com/google/genai/Client.java index 5767ce49784..6ab95cf1aa0 100644 --- a/src/main/java/com/google/genai/Client.java +++ b/src/main/java/com/google/genai/Client.java @@ -62,6 +62,7 @@ public final class Async { public final AsyncLive live; public final AsyncChats chats; public final AsyncFiles files; + public final AsyncTunings tunings; public Async(ApiClient apiClient) { this.models = new AsyncModels(apiClient); @@ -71,6 +72,7 @@ public Async(ApiClient apiClient) { this.live = new AsyncLive(apiClient); this.files = new AsyncFiles(apiClient); this.chats = new AsyncChats(apiClient); + this.tunings = new AsyncTunings(apiClient); } } @@ -83,6 +85,7 @@ public Async(ApiClient apiClient) { public final Chats chats; public final Files files; public final Async async; + public final Tunings tunings; /** Builder for {@link Client}. */ public static class Builder { @@ -319,6 +322,7 @@ private Client( chats = new Chats(this.apiClient); async = new Async(this.apiClient); files = new Files(this.apiClient); + tunings = new Tunings(this.apiClient); } /** Returns whether the client is using Vertex AI APIs. */ diff --git a/src/main/java/com/google/genai/Common.java b/src/main/java/com/google/genai/Common.java index f2547b25d55..a97bd39e4e1 100644 --- a/src/main/java/com/google/genai/Common.java +++ b/src/main/java/com/google/genai/Common.java @@ -101,7 +101,9 @@ static void setValueByPath(ObjectNode jsonObject, String[] path, Object value) { } } - currentObject.put(path[path.length - 1], JsonSerializable.toJsonNode(value)); + String keyToSet = path[path.length - 1]; + JsonNode valueNode = JsonSerializable.toJsonNode(value); + Transformers.updateJsonNode(currentObject, keyToSet, valueNode); } /** diff --git a/src/main/java/com/google/genai/Transformers.java b/src/main/java/com/google/genai/Transformers.java index 5c373897197..159efc4c8ae 100644 --- a/src/main/java/com/google/genai/Transformers.java +++ b/src/main/java/com/google/genai/Transformers.java @@ -506,6 +506,30 @@ public static String tCachedContentName(ApiClient apiClient, Object origin) { return name; } + public static JobState tTuningJobStatus(Object origin) { + String status; + if (origin instanceof String) { + status = (String) origin; + } else if (origin instanceof TextNode) { + status = ((TextNode) origin).textValue(); + } else { + throw new IllegalArgumentException("Unsupported status type: " + origin.getClass()); + } + + switch (status) { + case "STATE_UNSPECIFIED": + return new JobState(JobState.Known.JOB_STATE_UNSPECIFIED); + case "CREATING": + return new JobState(JobState.Known.JOB_STATE_RUNNING); + case "ACTIVE": + return new JobState(JobState.Known.JOB_STATE_SUCCEEDED); + case "FAILED": + return new JobState(JobState.Known.JOB_STATE_FAILED); + default: + return new JobState(status); + } + } + /** Formats a resource name given the resource name and resource prefix. */ private static String getResourceName( ApiClient apiClient, String resourceName, String resourcePrefix) { @@ -632,4 +656,68 @@ public static Object tJobState(Object state) { return state; } } + + /** + * Updates a JSON node with a new value, handling potential conflicts. + * + * @param currentObject The ObjectNode to update. + * @param keyToSet The key to set in the ObjectNode. + * @param valueNode The new JsonNode value. + * @throws IllegalArgumentException if a value cannot be set for an existing key. + */ + public static void updateJsonNode(ObjectNode currentObject, String keyToSet, JsonNode valueNode) { + JsonNode existingData = currentObject.get(keyToSet); + + if (existingData != null) { + // Don't overwrite existing non-empty value with new empty value. + if (valueNode == null || valueNode.isNull() || valueNode.isEmpty()) { + return; + } + + // Don't fail when overwriting value with same value + if (valueNode.equals(existingData)) { + return; + } + + // Instead of overwriting dictionary with another dictionary, merge them. + if (existingData.isObject() && valueNode.isObject()) { + ((ObjectNode) existingData).setAll((ObjectNode) valueNode); + } else { + throw new IllegalArgumentException( + "Cannot set value for an existing key. Key: " + + keyToSet + + "; Existing value: " + + existingData + + "; New value: " + + valueNode); + } + } else { + currentObject.set(keyToSet, valueNode); + } + } + + /** + * Converts a camelCase string to snake_case. + * + * @param str The input string to convert. + * @return The converted string in snake_case. + */ + public static String camelToSnake(String str) { + if (str == null || str.isEmpty()) { + return str; + } + + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < str.length(); i++) { + char c = str.charAt(i); + if (Character.isUpperCase(c)) { + if (i > 0) { + sb.append('_'); + } + } + sb.append(Character.toLowerCase(c)); + } + + return sb.toString(); + } } diff --git a/src/main/java/com/google/genai/Tunings.java b/src/main/java/com/google/genai/Tunings.java new file mode 100644 index 00000000000..55b29ac79de --- /dev/null +++ b/src/main/java/com/google/genai/Tunings.java @@ -0,0 +1,1245 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Auto-generated code. Do not edit. + +package com.google.genai; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; +import com.google.genai.errors.GenAiIOException; +import com.google.genai.types.CreateTuningJobConfig; +import com.google.genai.types.CreateTuningJobParameters; +import com.google.genai.types.GetTuningJobConfig; +import com.google.genai.types.GetTuningJobParameters; +import com.google.genai.types.HttpOptions; +import com.google.genai.types.JobState; +import com.google.genai.types.ListTuningJobsConfig; +import com.google.genai.types.ListTuningJobsParameters; +import com.google.genai.types.ListTuningJobsResponse; +import com.google.genai.types.TuningDataset; +import com.google.genai.types.TuningJob; +import com.google.genai.types.TuningOperation; +import java.io.IOException; +import java.util.Optional; +import java.util.function.Function; +import okhttp3.ResponseBody; + +public final class Tunings { + final ApiClient apiClient; + + public Tunings(ApiClient apiClient) { + this.apiClient = apiClient; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode getTuningJobParametersToMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"name"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"_url", "name"}, + Common.getValueByPath(fromObject, new String[] {"name"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"config"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"config"}, + Common.getValueByPath(fromObject, new String[] {"config"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode listTuningJobsConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + + if (Common.getValueByPath(fromObject, new String[] {"pageSize"}) != null) { + Common.setValueByPath( + parentObject, + new String[] {"_query", "pageSize"}, + Common.getValueByPath(fromObject, new String[] {"pageSize"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"pageToken"}) != null) { + Common.setValueByPath( + parentObject, + new String[] {"_query", "pageToken"}, + Common.getValueByPath(fromObject, new String[] {"pageToken"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"filter"}) != null) { + Common.setValueByPath( + parentObject, + new String[] {"_query", "filter"}, + Common.getValueByPath(fromObject, new String[] {"filter"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode listTuningJobsParametersToMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"config"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"config"}, + listTuningJobsConfigToMldev( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"config"})), + toObject)); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode tuningExampleToMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"textInput"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"textInput"}, + Common.getValueByPath(fromObject, new String[] {"textInput"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"output"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"output"}, + Common.getValueByPath(fromObject, new String[] {"output"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode tuningDatasetToMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"gcsUri"}))) { + throw new IllegalArgumentException("gcsUri parameter is not supported in Gemini API."); + } + + if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"vertexDatasetResource"}))) { + throw new IllegalArgumentException( + "vertexDatasetResource parameter is not supported in Gemini API."); + } + + if (Common.getValueByPath(fromObject, new String[] {"examples"}) != null) { + ArrayNode keyArray = (ArrayNode) Common.getValueByPath(fromObject, new String[] {"examples"}); + ObjectMapper objectMapper = new ObjectMapper(); + ArrayNode result = objectMapper.createArrayNode(); + + for (JsonNode item : keyArray) { + result.add(tuningExampleToMldev(JsonSerializable.toJsonNode(item), toObject)); + } + Common.setValueByPath(toObject, new String[] {"examples", "examples"}, result); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode createTuningJobConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + + if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"validationDataset"}))) { + throw new IllegalArgumentException( + "validationDataset parameter is not supported in Gemini API."); + } + + if (Common.getValueByPath(fromObject, new String[] {"tunedModelDisplayName"}) != null) { + Common.setValueByPath( + parentObject, + new String[] {"displayName"}, + Common.getValueByPath(fromObject, new String[] {"tunedModelDisplayName"})); + } + + if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"description"}))) { + throw new IllegalArgumentException("description parameter is not supported in Gemini API."); + } + + if (Common.getValueByPath(fromObject, new String[] {"epochCount"}) != null) { + Common.setValueByPath( + parentObject, + new String[] {"tuningTask", "hyperparameters", "epochCount"}, + Common.getValueByPath(fromObject, new String[] {"epochCount"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"learningRateMultiplier"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"tuningTask", "hyperparameters", "learningRateMultiplier"}, + Common.getValueByPath(fromObject, new String[] {"learningRateMultiplier"})); + } + + if (!Common.isZero( + Common.getValueByPath(fromObject, new String[] {"exportLastCheckpointOnly"}))) { + throw new IllegalArgumentException( + "exportLastCheckpointOnly parameter is not supported in Gemini API."); + } + + if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"adapterSize"}))) { + throw new IllegalArgumentException("adapterSize parameter is not supported in Gemini API."); + } + + if (Common.getValueByPath(fromObject, new String[] {"batchSize"}) != null) { + Common.setValueByPath( + parentObject, + new String[] {"tuningTask", "hyperparameters", "batchSize"}, + Common.getValueByPath(fromObject, new String[] {"batchSize"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"learningRate"}) != null) { + Common.setValueByPath( + parentObject, + new String[] {"tuningTask", "hyperparameters", "learningRate"}, + Common.getValueByPath(fromObject, new String[] {"learningRate"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode createTuningJobParametersToMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"baseModel"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"baseModel"}, + Common.getValueByPath(fromObject, new String[] {"baseModel"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"trainingDataset"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"tuningTask", "trainingData"}, + tuningDatasetToMldev( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"trainingDataset"})), + toObject)); + } + + if (Common.getValueByPath(fromObject, new String[] {"config"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"config"}, + createTuningJobConfigToMldev( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"config"})), + toObject)); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode getTuningJobParametersToVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"name"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"_url", "name"}, + Common.getValueByPath(fromObject, new String[] {"name"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"config"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"config"}, + Common.getValueByPath(fromObject, new String[] {"config"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode listTuningJobsConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + + if (Common.getValueByPath(fromObject, new String[] {"pageSize"}) != null) { + Common.setValueByPath( + parentObject, + new String[] {"_query", "pageSize"}, + Common.getValueByPath(fromObject, new String[] {"pageSize"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"pageToken"}) != null) { + Common.setValueByPath( + parentObject, + new String[] {"_query", "pageToken"}, + Common.getValueByPath(fromObject, new String[] {"pageToken"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"filter"}) != null) { + Common.setValueByPath( + parentObject, + new String[] {"_query", "filter"}, + Common.getValueByPath(fromObject, new String[] {"filter"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode listTuningJobsParametersToVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"config"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"config"}, + listTuningJobsConfigToVertex( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"config"})), + toObject)); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode tuningDatasetToVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"gcsUri"}) != null) { + Common.setValueByPath( + parentObject, + new String[] {"supervisedTuningSpec", "trainingDatasetUri"}, + Common.getValueByPath(fromObject, new String[] {"gcsUri"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"vertexDatasetResource"}) != null) { + Common.setValueByPath( + parentObject, + new String[] {"supervisedTuningSpec", "trainingDatasetUri"}, + Common.getValueByPath(fromObject, new String[] {"vertexDatasetResource"})); + } + + if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"examples"}))) { + throw new IllegalArgumentException("examples parameter is not supported in Vertex AI."); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode tuningValidationDatasetToVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"gcsUri"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"validationDatasetUri"}, + Common.getValueByPath(fromObject, new String[] {"gcsUri"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"vertexDatasetResource"}) != null) { + Common.setValueByPath( + parentObject, + new String[] {"supervisedTuningSpec", "trainingDatasetUri"}, + Common.getValueByPath(fromObject, new String[] {"vertexDatasetResource"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode createTuningJobConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + + if (Common.getValueByPath(fromObject, new String[] {"validationDataset"}) != null) { + Common.setValueByPath( + parentObject, + new String[] {"supervisedTuningSpec"}, + tuningValidationDatasetToVertex( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"validationDataset"})), + toObject)); + } + + if (Common.getValueByPath(fromObject, new String[] {"tunedModelDisplayName"}) != null) { + Common.setValueByPath( + parentObject, + new String[] {"tunedModelDisplayName"}, + Common.getValueByPath(fromObject, new String[] {"tunedModelDisplayName"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"description"}) != null) { + Common.setValueByPath( + parentObject, + new String[] {"description"}, + Common.getValueByPath(fromObject, new String[] {"description"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"epochCount"}) != null) { + Common.setValueByPath( + parentObject, + new String[] {"supervisedTuningSpec", "hyperParameters", "epochCount"}, + Common.getValueByPath(fromObject, new String[] {"epochCount"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"learningRateMultiplier"}) != null) { + Common.setValueByPath( + parentObject, + new String[] {"supervisedTuningSpec", "hyperParameters", "learningRateMultiplier"}, + Common.getValueByPath(fromObject, new String[] {"learningRateMultiplier"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"exportLastCheckpointOnly"}) != null) { + Common.setValueByPath( + parentObject, + new String[] {"supervisedTuningSpec", "exportLastCheckpointOnly"}, + Common.getValueByPath(fromObject, new String[] {"exportLastCheckpointOnly"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"adapterSize"}) != null) { + Common.setValueByPath( + parentObject, + new String[] {"supervisedTuningSpec", "hyperParameters", "adapterSize"}, + Common.getValueByPath(fromObject, new String[] {"adapterSize"})); + } + + if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"batchSize"}))) { + throw new IllegalArgumentException("batchSize parameter is not supported in Vertex AI."); + } + + if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"learningRate"}))) { + throw new IllegalArgumentException("learningRate parameter is not supported in Vertex AI."); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode createTuningJobParametersToVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"baseModel"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"baseModel"}, + Common.getValueByPath(fromObject, new String[] {"baseModel"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"trainingDataset"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"supervisedTuningSpec", "trainingDatasetUri"}, + tuningDatasetToVertex( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"trainingDataset"})), + toObject)); + } + + if (Common.getValueByPath(fromObject, new String[] {"config"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"config"}, + createTuningJobConfigToVertex( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"config"})), + toObject)); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode tunedModelFromMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"name"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"model"}, + Common.getValueByPath(fromObject, new String[] {"name"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"name"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"endpoint"}, + Common.getValueByPath(fromObject, new String[] {"name"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode tuningJobFromMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"name"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"name"}, + Common.getValueByPath(fromObject, new String[] {"name"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"state"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"state"}, + Transformers.tTuningJobStatus(Common.getValueByPath(fromObject, new String[] {"state"}))); + } + + if (Common.getValueByPath(fromObject, new String[] {"createTime"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"createTime"}, + Common.getValueByPath(fromObject, new String[] {"createTime"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"tuningTask", "startTime"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"startTime"}, + Common.getValueByPath(fromObject, new String[] {"tuningTask", "startTime"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"tuningTask", "completeTime"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"endTime"}, + Common.getValueByPath(fromObject, new String[] {"tuningTask", "completeTime"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"updateTime"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"updateTime"}, + Common.getValueByPath(fromObject, new String[] {"updateTime"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"description"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"description"}, + Common.getValueByPath(fromObject, new String[] {"description"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"baseModel"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"baseModel"}, + Common.getValueByPath(fromObject, new String[] {"baseModel"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"_self"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"tunedModel"}, + tunedModelFromMldev( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"_self"})), + toObject)); + } + + if (Common.getValueByPath(fromObject, new String[] {"distillationSpec"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"distillationSpec"}, + Common.getValueByPath(fromObject, new String[] {"distillationSpec"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"experiment"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"experiment"}, + Common.getValueByPath(fromObject, new String[] {"experiment"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"labels"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"labels"}, + Common.getValueByPath(fromObject, new String[] {"labels"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"pipelineJob"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"pipelineJob"}, + Common.getValueByPath(fromObject, new String[] {"pipelineJob"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"satisfiesPzi"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"satisfiesPzi"}, + Common.getValueByPath(fromObject, new String[] {"satisfiesPzi"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"satisfiesPzs"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"satisfiesPzs"}, + Common.getValueByPath(fromObject, new String[] {"satisfiesPzs"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"serviceAccount"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"serviceAccount"}, + Common.getValueByPath(fromObject, new String[] {"serviceAccount"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"tunedModelDisplayName"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"tunedModelDisplayName"}, + Common.getValueByPath(fromObject, new String[] {"tunedModelDisplayName"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode listTuningJobsResponseFromMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"nextPageToken"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"nextPageToken"}, + Common.getValueByPath(fromObject, new String[] {"nextPageToken"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"tunedModels"}) != null) { + ArrayNode keyArray = + (ArrayNode) Common.getValueByPath(fromObject, new String[] {"tunedModels"}); + ObjectMapper objectMapper = new ObjectMapper(); + ArrayNode result = objectMapper.createArrayNode(); + + for (JsonNode item : keyArray) { + result.add(tuningJobFromMldev(JsonSerializable.toJsonNode(item), toObject)); + } + Common.setValueByPath(toObject, new String[] {"tuningJobs"}, result); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode tuningOperationFromMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"name"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"name"}, + Common.getValueByPath(fromObject, new String[] {"name"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"metadata"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"metadata"}, + Common.getValueByPath(fromObject, new String[] {"metadata"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"done"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"done"}, + Common.getValueByPath(fromObject, new String[] {"done"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"error"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"error"}, + Common.getValueByPath(fromObject, new String[] {"error"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode tunedModelCheckpointFromVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"checkpointId"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"checkpointId"}, + Common.getValueByPath(fromObject, new String[] {"checkpointId"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"epoch"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"epoch"}, + Common.getValueByPath(fromObject, new String[] {"epoch"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"step"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"step"}, + Common.getValueByPath(fromObject, new String[] {"step"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"endpoint"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"endpoint"}, + Common.getValueByPath(fromObject, new String[] {"endpoint"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode tunedModelFromVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"model"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"model"}, + Common.getValueByPath(fromObject, new String[] {"model"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"endpoint"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"endpoint"}, + Common.getValueByPath(fromObject, new String[] {"endpoint"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"checkpoints"}) != null) { + ArrayNode keyArray = + (ArrayNode) Common.getValueByPath(fromObject, new String[] {"checkpoints"}); + ObjectMapper objectMapper = new ObjectMapper(); + ArrayNode result = objectMapper.createArrayNode(); + + for (JsonNode item : keyArray) { + result.add(tunedModelCheckpointFromVertex(JsonSerializable.toJsonNode(item), toObject)); + } + Common.setValueByPath(toObject, new String[] {"checkpoints"}, result); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode tuningJobFromVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"name"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"name"}, + Common.getValueByPath(fromObject, new String[] {"name"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"state"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"state"}, + Transformers.tTuningJobStatus(Common.getValueByPath(fromObject, new String[] {"state"}))); + } + + if (Common.getValueByPath(fromObject, new String[] {"createTime"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"createTime"}, + Common.getValueByPath(fromObject, new String[] {"createTime"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"startTime"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"startTime"}, + Common.getValueByPath(fromObject, new String[] {"startTime"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"endTime"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"endTime"}, + Common.getValueByPath(fromObject, new String[] {"endTime"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"updateTime"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"updateTime"}, + Common.getValueByPath(fromObject, new String[] {"updateTime"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"error"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"error"}, + Common.getValueByPath(fromObject, new String[] {"error"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"description"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"description"}, + Common.getValueByPath(fromObject, new String[] {"description"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"baseModel"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"baseModel"}, + Common.getValueByPath(fromObject, new String[] {"baseModel"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"tunedModel"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"tunedModel"}, + tunedModelFromVertex( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"tunedModel"})), + toObject)); + } + + if (Common.getValueByPath(fromObject, new String[] {"supervisedTuningSpec"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"supervisedTuningSpec"}, + Common.getValueByPath(fromObject, new String[] {"supervisedTuningSpec"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"tuningDataStats"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"tuningDataStats"}, + Common.getValueByPath(fromObject, new String[] {"tuningDataStats"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"encryptionSpec"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"encryptionSpec"}, + Common.getValueByPath(fromObject, new String[] {"encryptionSpec"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"partnerModelTuningSpec"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"partnerModelTuningSpec"}, + Common.getValueByPath(fromObject, new String[] {"partnerModelTuningSpec"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"distillationSpec"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"distillationSpec"}, + Common.getValueByPath(fromObject, new String[] {"distillationSpec"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"experiment"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"experiment"}, + Common.getValueByPath(fromObject, new String[] {"experiment"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"labels"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"labels"}, + Common.getValueByPath(fromObject, new String[] {"labels"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"pipelineJob"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"pipelineJob"}, + Common.getValueByPath(fromObject, new String[] {"pipelineJob"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"satisfiesPzi"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"satisfiesPzi"}, + Common.getValueByPath(fromObject, new String[] {"satisfiesPzi"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"satisfiesPzs"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"satisfiesPzs"}, + Common.getValueByPath(fromObject, new String[] {"satisfiesPzs"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"serviceAccount"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"serviceAccount"}, + Common.getValueByPath(fromObject, new String[] {"serviceAccount"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"tunedModelDisplayName"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"tunedModelDisplayName"}, + Common.getValueByPath(fromObject, new String[] {"tunedModelDisplayName"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode listTuningJobsResponseFromVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"nextPageToken"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"nextPageToken"}, + Common.getValueByPath(fromObject, new String[] {"nextPageToken"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"tuningJobs"}) != null) { + ArrayNode keyArray = + (ArrayNode) Common.getValueByPath(fromObject, new String[] {"tuningJobs"}); + ObjectMapper objectMapper = new ObjectMapper(); + ArrayNode result = objectMapper.createArrayNode(); + + for (JsonNode item : keyArray) { + result.add(tuningJobFromVertex(JsonSerializable.toJsonNode(item), toObject)); + } + Common.setValueByPath(toObject, new String[] {"tuningJobs"}, result); + } + + return toObject; + } + + TuningJob privateGet(String name, GetTuningJobConfig config) { + + GetTuningJobParameters.Builder parameterBuilder = GetTuningJobParameters.builder(); + + if (!Common.isZero(name)) { + parameterBuilder.name(name); + } + if (!Common.isZero(config)) { + parameterBuilder.config(config); + } + JsonNode parameterNode = JsonSerializable.toJsonNode(parameterBuilder.build()); + + ObjectNode body; + String path; + if (this.apiClient.vertexAI()) { + body = getTuningJobParametersToVertex(parameterNode, null); + path = Common.formatMap("{name}", body.get("_url")); + } else { + body = getTuningJobParametersToMldev(parameterNode, null); + if (body.get("_url") != null) { + path = Common.formatMap("{name}", body.get("_url")); + } else { + path = "{name}"; + } + } + body.remove("_url"); + + JsonNode queryParams = body.get("_query"); + if (queryParams != null) { + body.remove("_query"); + path = String.format("%s?%s", path, Common.urlEncode((ObjectNode) queryParams)); + } + + // TODO: Remove the hack that removes config. + body.remove("config"); + + Optional requestHttpOptions = Optional.empty(); + if (config != null) { + requestHttpOptions = config.httpOptions(); + } + + try (ApiResponse response = + this.apiClient.request( + "get", path, JsonSerializable.toJsonString(body), requestHttpOptions)) { + ResponseBody responseBody = response.getBody(); + String responseString; + try { + responseString = responseBody.string(); + } catch (IOException e) { + throw new GenAiIOException("Failed to read HTTP response.", e); + } + + JsonNode responseNode = JsonSerializable.stringToJsonNode(responseString); + if (this.apiClient.vertexAI()) { + responseNode = tuningJobFromVertex(responseNode, null); + } else { + responseNode = tuningJobFromMldev(responseNode, null); + } + return JsonSerializable.fromJsonNode(responseNode, TuningJob.class); + } + } + + ListTuningJobsResponse privateList(ListTuningJobsConfig config) { + + ListTuningJobsParameters.Builder parameterBuilder = ListTuningJobsParameters.builder(); + + if (!Common.isZero(config)) { + parameterBuilder.config(config); + } + JsonNode parameterNode = JsonSerializable.toJsonNode(parameterBuilder.build()); + + ObjectNode body; + String path; + if (this.apiClient.vertexAI()) { + body = listTuningJobsParametersToVertex(parameterNode, null); + path = Common.formatMap("tuningJobs", body.get("_url")); + } else { + body = listTuningJobsParametersToMldev(parameterNode, null); + if (body.get("_url") != null) { + path = Common.formatMap("tunedModels", body.get("_url")); + } else { + path = "tunedModels"; + } + } + body.remove("_url"); + + JsonNode queryParams = body.get("_query"); + if (queryParams != null) { + body.remove("_query"); + path = String.format("%s?%s", path, Common.urlEncode((ObjectNode) queryParams)); + } + + // TODO: Remove the hack that removes config. + body.remove("config"); + + Optional requestHttpOptions = Optional.empty(); + if (config != null) { + requestHttpOptions = config.httpOptions(); + } + + try (ApiResponse response = + this.apiClient.request( + "get", path, JsonSerializable.toJsonString(body), requestHttpOptions)) { + ResponseBody responseBody = response.getBody(); + String responseString; + try { + responseString = responseBody.string(); + } catch (IOException e) { + throw new GenAiIOException("Failed to read HTTP response.", e); + } + + JsonNode responseNode = JsonSerializable.stringToJsonNode(responseString); + if (this.apiClient.vertexAI()) { + responseNode = listTuningJobsResponseFromVertex(responseNode, null); + } else { + responseNode = listTuningJobsResponseFromMldev(responseNode, null); + } + return JsonSerializable.fromJsonNode(responseNode, ListTuningJobsResponse.class); + } + } + + TuningJob privateTune( + String baseModel, TuningDataset trainingDataset, CreateTuningJobConfig config) { + + CreateTuningJobParameters.Builder parameterBuilder = CreateTuningJobParameters.builder(); + + if (!Common.isZero(baseModel)) { + parameterBuilder.baseModel(baseModel); + } + if (!Common.isZero(trainingDataset)) { + parameterBuilder.trainingDataset(trainingDataset); + } + if (!Common.isZero(config)) { + parameterBuilder.config(config); + } + JsonNode parameterNode = JsonSerializable.toJsonNode(parameterBuilder.build()); + + ObjectNode body; + String path; + if (this.apiClient.vertexAI()) { + body = createTuningJobParametersToVertex(parameterNode, null); + path = Common.formatMap("tuningJobs", body.get("_url")); + } else { + throw new UnsupportedOperationException( + "This method is only supported in the Vertex AI client."); + } + body.remove("_url"); + + JsonNode queryParams = body.get("_query"); + if (queryParams != null) { + body.remove("_query"); + path = String.format("%s?%s", path, Common.urlEncode((ObjectNode) queryParams)); + } + + // TODO: Remove the hack that removes config. + body.remove("config"); + + Optional requestHttpOptions = Optional.empty(); + if (config != null) { + requestHttpOptions = config.httpOptions(); + } + + try (ApiResponse response = + this.apiClient.request( + "post", path, JsonSerializable.toJsonString(body), requestHttpOptions)) { + ResponseBody responseBody = response.getBody(); + String responseString; + try { + responseString = responseBody.string(); + } catch (IOException e) { + throw new GenAiIOException("Failed to read HTTP response.", e); + } + + JsonNode responseNode = JsonSerializable.stringToJsonNode(responseString); + if (this.apiClient.vertexAI()) { + responseNode = tuningJobFromVertex(responseNode, null); + } else { + throw new UnsupportedOperationException( + "This method is only supported in the Vertex AI client."); + } + return JsonSerializable.fromJsonNode(responseNode, TuningJob.class); + } + } + + TuningOperation privateTuneMldev( + String baseModel, TuningDataset trainingDataset, CreateTuningJobConfig config) { + + CreateTuningJobParameters.Builder parameterBuilder = CreateTuningJobParameters.builder(); + + if (!Common.isZero(baseModel)) { + parameterBuilder.baseModel(baseModel); + } + if (!Common.isZero(trainingDataset)) { + parameterBuilder.trainingDataset(trainingDataset); + } + if (!Common.isZero(config)) { + parameterBuilder.config(config); + } + JsonNode parameterNode = JsonSerializable.toJsonNode(parameterBuilder.build()); + + ObjectNode body; + String path; + if (this.apiClient.vertexAI()) { + throw new UnsupportedOperationException( + "This method is only supported in the Gemini Developer client."); + } else { + body = createTuningJobParametersToMldev(parameterNode, null); + if (body.get("_url") != null) { + path = Common.formatMap("tunedModels", body.get("_url")); + } else { + path = "tunedModels"; + } + } + body.remove("_url"); + + JsonNode queryParams = body.get("_query"); + if (queryParams != null) { + body.remove("_query"); + path = String.format("%s?%s", path, Common.urlEncode((ObjectNode) queryParams)); + } + + // TODO: Remove the hack that removes config. + body.remove("config"); + + Optional requestHttpOptions = Optional.empty(); + if (config != null) { + requestHttpOptions = config.httpOptions(); + } + + try (ApiResponse response = + this.apiClient.request( + "post", path, JsonSerializable.toJsonString(body), requestHttpOptions)) { + ResponseBody responseBody = response.getBody(); + String responseString; + try { + responseString = responseBody.string(); + } catch (IOException e) { + throw new GenAiIOException("Failed to read HTTP response.", e); + } + + JsonNode responseNode = JsonSerializable.stringToJsonNode(responseString); + if (this.apiClient.vertexAI()) { + throw new UnsupportedOperationException( + "This method is only supported in the Gemini Developer client."); + } else { + responseNode = tuningOperationFromMldev(responseNode, null); + } + return JsonSerializable.fromJsonNode(responseNode, TuningOperation.class); + } + } + + /** + * Makes an API request to get a tuning job. + * + * @param name The resource name of the tuning job. + * @param config A {@link GetTuningJobConfig} for configuring the get request. + * @return A {@link TuningJob} object. + */ + public TuningJob get(String name, GetTuningJobConfig config) { + return this.privateGet(name, config); + } + + /** + * Makes an API request to list the available tuning jobs. + * + * @param config A {@link ListTuningJobsConfig} for configuring the list request. + * @return A {@link Pager} object that contains the list of tuning jobs. The pager is an iterable + * and automatically queries the next page once the current page is exhausted. + */ + @SuppressWarnings("PatternMatchingInstanceof") + public Pager list(ListTuningJobsConfig config) { + Function request = + requestConfig -> { + if (!(requestConfig instanceof ListTuningJobsConfig)) { + throw new GenAiIOException( + "Internal error: Pager expected ListTuningJobsConfig but received " + + requestConfig.getClass().getName()); + } + return this.privateList((ListTuningJobsConfig) requestConfig); + }; + if (config == null) { + config = ListTuningJobsConfig.builder().build(); + } + return new Pager<>( + Pager.PagedItem.TUNING_JOBS, + request, + (ObjectNode) JsonSerializable.toJsonNode(config), + JsonSerializable.toJsonNode(privateList(config))); + } + + /** + * Makes an API request to create a supervised fine-tuning job. + * + *

This method is experimental. + * + * @param baseModel The base model to tune. + * @param trainingDataset The training dataset to use for tuning. + * @param config A {@link CreateTuningJobConfig} for configuring the create request. + * @return A {@link TuningJob} object. + */ + public TuningJob tune( + String baseModel, TuningDataset trainingDataset, CreateTuningJobConfig config) { + if (this.apiClient.vertexAI()) { + return this.privateTune(baseModel, trainingDataset, config); + } else { + TuningOperation operation = this.privateTuneMldev(baseModel, trainingDataset, config); + String tunedModelName = ""; + if (operation.metadata().isPresent() + && operation.metadata().get().containsKey("tunedModel")) { + tunedModelName = (String) operation.metadata().get().get("tunedModel"); + } else { + if (!operation.name().isPresent()) { + throw new IllegalArgumentException("Operation name is required."); + } + tunedModelName = operation.name().get().split("/operations/")[0]; + } + return TuningJob.builder() + .name(tunedModelName) + .state(JobState.Known.JOB_STATE_QUEUED) + .build(); + } + } +} diff --git a/src/main/java/com/google/genai/types/AdapterSize.java b/src/main/java/com/google/genai/types/AdapterSize.java new file mode 100644 index 00000000000..fa47b3d31e6 --- /dev/null +++ b/src/main/java/com/google/genai/types/AdapterSize.java @@ -0,0 +1,119 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Auto-generated code. Do not edit. + +package com.google.genai.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; +import com.google.common.base.Ascii; +import java.util.Objects; + +/** Optional. Adapter size for tuning. */ +public class AdapterSize { + + /** Enum representing the known values for AdapterSize. */ + public enum Known { + /** Adapter size is unspecified. */ + ADAPTER_SIZE_UNSPECIFIED, + + /** Adapter size 1. */ + ADAPTER_SIZE_ONE, + + /** Adapter size 2. */ + ADAPTER_SIZE_TWO, + + /** Adapter size 4. */ + ADAPTER_SIZE_FOUR, + + /** Adapter size 8. */ + ADAPTER_SIZE_EIGHT, + + /** Adapter size 16. */ + ADAPTER_SIZE_SIXTEEN, + + /** Adapter size 32. */ + ADAPTER_SIZE_THIRTY_TWO + } + + private Known adapterSizeEnum; + private final String value; + + @JsonCreator + public AdapterSize(String value) { + this.value = value; + for (Known adapterSizeEnum : Known.values()) { + if (Ascii.equalsIgnoreCase(adapterSizeEnum.toString(), value)) { + this.adapterSizeEnum = adapterSizeEnum; + break; + } + } + if (this.adapterSizeEnum == null) { + this.adapterSizeEnum = Known.ADAPTER_SIZE_UNSPECIFIED; + } + } + + public AdapterSize(Known knownValue) { + this.adapterSizeEnum = knownValue; + this.value = knownValue.toString(); + } + + @Override + @JsonValue + public String toString() { + return this.value; + } + + @SuppressWarnings("PatternMatchingInstanceof") + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null) { + return false; + } + + if (!(o instanceof AdapterSize)) { + return false; + } + + AdapterSize other = (AdapterSize) o; + + if (this.adapterSizeEnum != Known.ADAPTER_SIZE_UNSPECIFIED + && other.adapterSizeEnum != Known.ADAPTER_SIZE_UNSPECIFIED) { + return this.adapterSizeEnum == other.adapterSizeEnum; + } else if (this.adapterSizeEnum == Known.ADAPTER_SIZE_UNSPECIFIED + && other.adapterSizeEnum == Known.ADAPTER_SIZE_UNSPECIFIED) { + return this.value.equals(other.value); + } + return false; + } + + @Override + public int hashCode() { + if (this.adapterSizeEnum != Known.ADAPTER_SIZE_UNSPECIFIED) { + return this.adapterSizeEnum.hashCode(); + } else { + return Objects.hashCode(this.value); + } + } + + public Known knownEnum() { + return this.adapterSizeEnum; + } +} diff --git a/src/main/java/com/google/genai/types/CreateTuningJobConfig.java b/src/main/java/com/google/genai/types/CreateTuningJobConfig.java new file mode 100644 index 00000000000..151fcfd4a35 --- /dev/null +++ b/src/main/java/com/google/genai/types/CreateTuningJobConfig.java @@ -0,0 +1,238 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Auto-generated code. Do not edit. + +package com.google.genai.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.google.auto.value.AutoValue; +import com.google.errorprone.annotations.CanIgnoreReturnValue; +import com.google.genai.JsonSerializable; +import java.util.Optional; + +/** Supervised fine-tuning job creation request - optional fields. */ +@AutoValue +@JsonDeserialize(builder = CreateTuningJobConfig.Builder.class) +public abstract class CreateTuningJobConfig extends JsonSerializable { + /** Used to override HTTP request options. */ + @JsonProperty("httpOptions") + public abstract Optional httpOptions(); + + /** + * Cloud Storage path to file containing training dataset for tuning. The dataset must be + * formatted as a JSONL file. + */ + @JsonProperty("validationDataset") + public abstract Optional validationDataset(); + + /** + * The display name of the tuned Model. The name can be up to 128 characters long and can consist + * of any UTF-8 characters. + */ + @JsonProperty("tunedModelDisplayName") + public abstract Optional tunedModelDisplayName(); + + /** The description of the TuningJob */ + @JsonProperty("description") + public abstract Optional description(); + + /** Number of complete passes the model makes over the entire training dataset during training. */ + @JsonProperty("epochCount") + public abstract Optional epochCount(); + + /** Multiplier for adjusting the default learning rate. */ + @JsonProperty("learningRateMultiplier") + public abstract Optional learningRateMultiplier(); + + /** + * If set to true, disable intermediate checkpoints for SFT and only the last checkpoint will be + * exported. Otherwise, enable intermediate checkpoints for SFT. + */ + @JsonProperty("exportLastCheckpointOnly") + public abstract Optional exportLastCheckpointOnly(); + + /** Adapter size for tuning. */ + @JsonProperty("adapterSize") + public abstract Optional adapterSize(); + + /** + * The batch size hyperparameter for tuning. If not set, a default of 4 or 16 will be used based + * on the number of training examples. + */ + @JsonProperty("batchSize") + public abstract Optional batchSize(); + + /** + * The learning rate hyperparameter for tuning. If not set, a default of 0.001 or 0.0002 will be + * calculated based on the number of training examples. + */ + @JsonProperty("learningRate") + public abstract Optional learningRate(); + + /** Instantiates a builder for CreateTuningJobConfig. */ + public static Builder builder() { + return new AutoValue_CreateTuningJobConfig.Builder(); + } + + /** Creates a builder with the same values as this instance. */ + public abstract Builder toBuilder(); + + /** Builder for CreateTuningJobConfig. */ + @AutoValue.Builder + public abstract static class Builder { + /** For internal usage. Please use `CreateTuningJobConfig.builder()` for instantiation. */ + @JsonCreator + private static Builder create() { + return new AutoValue_CreateTuningJobConfig.Builder(); + } + + /** + * Setter for httpOptions. + * + *

httpOptions: Used to override HTTP request options. + */ + @JsonProperty("httpOptions") + public abstract Builder httpOptions(HttpOptions httpOptions); + + /** + * Setter for httpOptions builder. + * + *

httpOptions: Used to override HTTP request options. + */ + public Builder httpOptions(HttpOptions.Builder httpOptionsBuilder) { + return httpOptions(httpOptionsBuilder.build()); + } + + /** + * Setter for validationDataset. + * + *

validationDataset: Cloud Storage path to file containing training dataset for tuning. The + * dataset must be formatted as a JSONL file. + */ + @JsonProperty("validationDataset") + public abstract Builder validationDataset(TuningValidationDataset validationDataset); + + /** + * Setter for validationDataset builder. + * + *

validationDataset: Cloud Storage path to file containing training dataset for tuning. The + * dataset must be formatted as a JSONL file. + */ + public Builder validationDataset(TuningValidationDataset.Builder validationDatasetBuilder) { + return validationDataset(validationDatasetBuilder.build()); + } + + /** + * Setter for tunedModelDisplayName. + * + *

tunedModelDisplayName: The display name of the tuned Model. The name can be up to 128 + * characters long and can consist of any UTF-8 characters. + */ + @JsonProperty("tunedModelDisplayName") + public abstract Builder tunedModelDisplayName(String tunedModelDisplayName); + + /** + * Setter for description. + * + *

description: The description of the TuningJob + */ + @JsonProperty("description") + public abstract Builder description(String description); + + /** + * Setter for epochCount. + * + *

epochCount: Number of complete passes the model makes over the entire training dataset + * during training. + */ + @JsonProperty("epochCount") + public abstract Builder epochCount(Integer epochCount); + + /** + * Setter for learningRateMultiplier. + * + *

learningRateMultiplier: Multiplier for adjusting the default learning rate. + */ + @JsonProperty("learningRateMultiplier") + public abstract Builder learningRateMultiplier(Float learningRateMultiplier); + + /** + * Setter for exportLastCheckpointOnly. + * + *

exportLastCheckpointOnly: If set to true, disable intermediate checkpoints for SFT and + * only the last checkpoint will be exported. Otherwise, enable intermediate checkpoints for + * SFT. + */ + @JsonProperty("exportLastCheckpointOnly") + public abstract Builder exportLastCheckpointOnly(boolean exportLastCheckpointOnly); + + /** + * Setter for adapterSize. + * + *

adapterSize: Adapter size for tuning. + */ + @JsonProperty("adapterSize") + public abstract Builder adapterSize(AdapterSize adapterSize); + + /** + * Setter for adapterSize given a known enum. + * + *

adapterSize: Adapter size for tuning. + */ + @CanIgnoreReturnValue + public Builder adapterSize(AdapterSize.Known knownType) { + return adapterSize(new AdapterSize(knownType)); + } + + /** + * Setter for adapterSize given a string. + * + *

adapterSize: Adapter size for tuning. + */ + @CanIgnoreReturnValue + public Builder adapterSize(String adapterSize) { + return adapterSize(new AdapterSize(adapterSize)); + } + + /** + * Setter for batchSize. + * + *

batchSize: The batch size hyperparameter for tuning. If not set, a default of 4 or 16 will + * be used based on the number of training examples. + */ + @JsonProperty("batchSize") + public abstract Builder batchSize(Integer batchSize); + + /** + * Setter for learningRate. + * + *

learningRate: The learning rate hyperparameter for tuning. If not set, a default of 0.001 + * or 0.0002 will be calculated based on the number of training examples. + */ + @JsonProperty("learningRate") + public abstract Builder learningRate(Float learningRate); + + public abstract CreateTuningJobConfig build(); + } + + /** Deserializes a JSON string to a CreateTuningJobConfig object. */ + public static CreateTuningJobConfig fromJson(String jsonString) { + return JsonSerializable.fromJsonString(jsonString, CreateTuningJobConfig.class); + } +} diff --git a/src/main/java/com/google/genai/types/CreateTuningJobParameters.java b/src/main/java/com/google/genai/types/CreateTuningJobParameters.java new file mode 100644 index 00000000000..30683c0ae15 --- /dev/null +++ b/src/main/java/com/google/genai/types/CreateTuningJobParameters.java @@ -0,0 +1,117 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Auto-generated code. Do not edit. + +package com.google.genai.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.google.api.core.InternalApi; +import com.google.auto.value.AutoValue; +import com.google.genai.JsonSerializable; +import java.util.Optional; + +/** Supervised fine-tuning job creation parameters - optional fields. */ +@AutoValue +@InternalApi +@JsonDeserialize(builder = CreateTuningJobParameters.Builder.class) +public abstract class CreateTuningJobParameters extends JsonSerializable { + /** The base model that is being tuned, e.g., "gemini-1.0-pro-002". */ + @JsonProperty("baseModel") + public abstract Optional baseModel(); + + /** + * Cloud Storage path to file containing training dataset for tuning. The dataset must be + * formatted as a JSONL file. + */ + @JsonProperty("trainingDataset") + public abstract Optional trainingDataset(); + + /** Configuration for the tuning job. */ + @JsonProperty("config") + public abstract Optional config(); + + /** Instantiates a builder for CreateTuningJobParameters. */ + public static Builder builder() { + return new AutoValue_CreateTuningJobParameters.Builder(); + } + + /** Creates a builder with the same values as this instance. */ + public abstract Builder toBuilder(); + + /** Builder for CreateTuningJobParameters. */ + @AutoValue.Builder + public abstract static class Builder { + /** For internal usage. Please use `CreateTuningJobParameters.builder()` for instantiation. */ + @JsonCreator + private static Builder create() { + return new AutoValue_CreateTuningJobParameters.Builder(); + } + + /** + * Setter for baseModel. + * + *

baseModel: The base model that is being tuned, e.g., "gemini-1.0-pro-002". + */ + @JsonProperty("baseModel") + public abstract Builder baseModel(String baseModel); + + /** + * Setter for trainingDataset. + * + *

trainingDataset: Cloud Storage path to file containing training dataset for tuning. The + * dataset must be formatted as a JSONL file. + */ + @JsonProperty("trainingDataset") + public abstract Builder trainingDataset(TuningDataset trainingDataset); + + /** + * Setter for trainingDataset builder. + * + *

trainingDataset: Cloud Storage path to file containing training dataset for tuning. The + * dataset must be formatted as a JSONL file. + */ + public Builder trainingDataset(TuningDataset.Builder trainingDatasetBuilder) { + return trainingDataset(trainingDatasetBuilder.build()); + } + + /** + * Setter for config. + * + *

config: Configuration for the tuning job. + */ + @JsonProperty("config") + public abstract Builder config(CreateTuningJobConfig config); + + /** + * Setter for config builder. + * + *

config: Configuration for the tuning job. + */ + public Builder config(CreateTuningJobConfig.Builder configBuilder) { + return config(configBuilder.build()); + } + + public abstract CreateTuningJobParameters build(); + } + + /** Deserializes a JSON string to a CreateTuningJobParameters object. */ + public static CreateTuningJobParameters fromJson(String jsonString) { + return JsonSerializable.fromJsonString(jsonString, CreateTuningJobParameters.class); + } +} diff --git a/src/main/java/com/google/genai/types/DatasetDistribution.java b/src/main/java/com/google/genai/types/DatasetDistribution.java new file mode 100644 index 00000000000..f70b89330ee --- /dev/null +++ b/src/main/java/com/google/genai/types/DatasetDistribution.java @@ -0,0 +1,177 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Auto-generated code. Do not edit. + +package com.google.genai.types; + +import static com.google.common.collect.ImmutableList.toImmutableList; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.google.auto.value.AutoValue; +import com.google.genai.JsonSerializable; +import java.util.Arrays; +import java.util.List; +import java.util.Optional; + +/** Distribution computed over a tuning dataset. */ +@AutoValue +@JsonDeserialize(builder = DatasetDistribution.Builder.class) +public abstract class DatasetDistribution extends JsonSerializable { + /** Output only. Defines the histogram bucket. */ + @JsonProperty("buckets") + public abstract Optional> buckets(); + + /** Output only. The maximum of the population values. */ + @JsonProperty("max") + public abstract Optional max(); + + /** Output only. The arithmetic mean of the values in the population. */ + @JsonProperty("mean") + public abstract Optional mean(); + + /** Output only. The median of the values in the population. */ + @JsonProperty("median") + public abstract Optional median(); + + /** Output only. The minimum of the population values. */ + @JsonProperty("min") + public abstract Optional min(); + + /** Output only. The 5th percentile of the values in the population. */ + @JsonProperty("p5") + public abstract Optional p5(); + + /** Output only. The 95th percentile of the values in the population. */ + @JsonProperty("p95") + public abstract Optional p95(); + + /** Output only. Sum of a given population of values. */ + @JsonProperty("sum") + public abstract Optional sum(); + + /** Instantiates a builder for DatasetDistribution. */ + public static Builder builder() { + return new AutoValue_DatasetDistribution.Builder(); + } + + /** Creates a builder with the same values as this instance. */ + public abstract Builder toBuilder(); + + /** Builder for DatasetDistribution. */ + @AutoValue.Builder + public abstract static class Builder { + /** For internal usage. Please use `DatasetDistribution.builder()` for instantiation. */ + @JsonCreator + private static Builder create() { + return new AutoValue_DatasetDistribution.Builder(); + } + + /** + * Setter for buckets. + * + *

buckets: Output only. Defines the histogram bucket. + */ + @JsonProperty("buckets") + public abstract Builder buckets(List buckets); + + /** + * Setter for buckets. + * + *

buckets: Output only. Defines the histogram bucket. + */ + public Builder buckets(DatasetDistributionDistributionBucket... buckets) { + return buckets(Arrays.asList(buckets)); + } + + /** + * Setter for buckets builder. + * + *

buckets: Output only. Defines the histogram bucket. + */ + public Builder buckets(DatasetDistributionDistributionBucket.Builder... bucketsBuilders) { + return buckets( + Arrays.asList(bucketsBuilders).stream() + .map(DatasetDistributionDistributionBucket.Builder::build) + .collect(toImmutableList())); + } + + /** + * Setter for max. + * + *

max: Output only. The maximum of the population values. + */ + @JsonProperty("max") + public abstract Builder max(Double max); + + /** + * Setter for mean. + * + *

mean: Output only. The arithmetic mean of the values in the population. + */ + @JsonProperty("mean") + public abstract Builder mean(Double mean); + + /** + * Setter for median. + * + *

median: Output only. The median of the values in the population. + */ + @JsonProperty("median") + public abstract Builder median(Double median); + + /** + * Setter for min. + * + *

min: Output only. The minimum of the population values. + */ + @JsonProperty("min") + public abstract Builder min(Double min); + + /** + * Setter for p5. + * + *

p5: Output only. The 5th percentile of the values in the population. + */ + @JsonProperty("p5") + public abstract Builder p5(Double p5); + + /** + * Setter for p95. + * + *

p95: Output only. The 95th percentile of the values in the population. + */ + @JsonProperty("p95") + public abstract Builder p95(Double p95); + + /** + * Setter for sum. + * + *

sum: Output only. Sum of a given population of values. + */ + @JsonProperty("sum") + public abstract Builder sum(Double sum); + + public abstract DatasetDistribution build(); + } + + /** Deserializes a JSON string to a DatasetDistribution object. */ + public static DatasetDistribution fromJson(String jsonString) { + return JsonSerializable.fromJsonString(jsonString, DatasetDistribution.class); + } +} diff --git a/src/main/java/com/google/genai/types/DatasetDistributionDistributionBucket.java b/src/main/java/com/google/genai/types/DatasetDistributionDistributionBucket.java new file mode 100644 index 00000000000..adf61aa69ce --- /dev/null +++ b/src/main/java/com/google/genai/types/DatasetDistributionDistributionBucket.java @@ -0,0 +1,95 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Auto-generated code. Do not edit. + +package com.google.genai.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.google.auto.value.AutoValue; +import com.google.genai.JsonSerializable; +import java.util.Optional; + +/** Dataset bucket used to create a histogram for the distribution given a population of values. */ +@AutoValue +@JsonDeserialize(builder = DatasetDistributionDistributionBucket.Builder.class) +public abstract class DatasetDistributionDistributionBucket extends JsonSerializable { + /** Output only. Number of values in the bucket. */ + @JsonProperty("count") + public abstract Optional count(); + + /** Output only. Left bound of the bucket. */ + @JsonProperty("left") + public abstract Optional left(); + + /** Output only. Right bound of the bucket. */ + @JsonProperty("right") + public abstract Optional right(); + + /** Instantiates a builder for DatasetDistributionDistributionBucket. */ + public static Builder builder() { + return new AutoValue_DatasetDistributionDistributionBucket.Builder(); + } + + /** Creates a builder with the same values as this instance. */ + public abstract Builder toBuilder(); + + /** Builder for DatasetDistributionDistributionBucket. */ + @AutoValue.Builder + public abstract static class Builder { + /** + * For internal usage. Please use `DatasetDistributionDistributionBucket.builder()` for + * instantiation. + */ + @JsonCreator + private static Builder create() { + return new AutoValue_DatasetDistributionDistributionBucket.Builder(); + } + + /** + * Setter for count. + * + *

count: Output only. Number of values in the bucket. + */ + @JsonProperty("count") + public abstract Builder count(Long count); + + /** + * Setter for left. + * + *

left: Output only. Left bound of the bucket. + */ + @JsonProperty("left") + public abstract Builder left(Double left); + + /** + * Setter for right. + * + *

right: Output only. Right bound of the bucket. + */ + @JsonProperty("right") + public abstract Builder right(Double right); + + public abstract DatasetDistributionDistributionBucket build(); + } + + /** Deserializes a JSON string to a DatasetDistributionDistributionBucket object. */ + public static DatasetDistributionDistributionBucket fromJson(String jsonString) { + return JsonSerializable.fromJsonString(jsonString, DatasetDistributionDistributionBucket.class); + } +} diff --git a/src/main/java/com/google/genai/types/DatasetStats.java b/src/main/java/com/google/genai/types/DatasetStats.java new file mode 100644 index 00000000000..dcc839becb7 --- /dev/null +++ b/src/main/java/com/google/genai/types/DatasetStats.java @@ -0,0 +1,215 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Auto-generated code. Do not edit. + +package com.google.genai.types; + +import static com.google.common.collect.ImmutableList.toImmutableList; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.google.auto.value.AutoValue; +import com.google.genai.JsonSerializable; +import java.util.Arrays; +import java.util.List; +import java.util.Optional; + +/** Statistics computed over a tuning dataset. */ +@AutoValue +@JsonDeserialize(builder = DatasetStats.Builder.class) +public abstract class DatasetStats extends JsonSerializable { + /** Output only. Number of billable characters in the tuning dataset. */ + @JsonProperty("totalBillableCharacterCount") + public abstract Optional totalBillableCharacterCount(); + + /** Output only. Number of tuning characters in the tuning dataset. */ + @JsonProperty("totalTuningCharacterCount") + public abstract Optional totalTuningCharacterCount(); + + /** Output only. Number of examples in the tuning dataset. */ + @JsonProperty("tuningDatasetExampleCount") + public abstract Optional tuningDatasetExampleCount(); + + /** Output only. Number of tuning steps for this Tuning Job. */ + @JsonProperty("tuningStepCount") + public abstract Optional tuningStepCount(); + + /** Output only. Sample user messages in the training dataset uri. */ + @JsonProperty("userDatasetExamples") + public abstract Optional> userDatasetExamples(); + + /** Output only. Dataset distributions for the user input tokens. */ + @JsonProperty("userInputTokenDistribution") + public abstract Optional userInputTokenDistribution(); + + /** Output only. Dataset distributions for the messages per example. */ + @JsonProperty("userMessagePerExampleDistribution") + public abstract Optional userMessagePerExampleDistribution(); + + /** Output only. Dataset distributions for the user output tokens. */ + @JsonProperty("userOutputTokenDistribution") + public abstract Optional userOutputTokenDistribution(); + + /** Instantiates a builder for DatasetStats. */ + public static Builder builder() { + return new AutoValue_DatasetStats.Builder(); + } + + /** Creates a builder with the same values as this instance. */ + public abstract Builder toBuilder(); + + /** Builder for DatasetStats. */ + @AutoValue.Builder + public abstract static class Builder { + /** For internal usage. Please use `DatasetStats.builder()` for instantiation. */ + @JsonCreator + private static Builder create() { + return new AutoValue_DatasetStats.Builder(); + } + + /** + * Setter for totalBillableCharacterCount. + * + *

totalBillableCharacterCount: Output only. Number of billable characters in the tuning + * dataset. + */ + @JsonProperty("totalBillableCharacterCount") + public abstract Builder totalBillableCharacterCount(Long totalBillableCharacterCount); + + /** + * Setter for totalTuningCharacterCount. + * + *

totalTuningCharacterCount: Output only. Number of tuning characters in the tuning dataset. + */ + @JsonProperty("totalTuningCharacterCount") + public abstract Builder totalTuningCharacterCount(Long totalTuningCharacterCount); + + /** + * Setter for tuningDatasetExampleCount. + * + *

tuningDatasetExampleCount: Output only. Number of examples in the tuning dataset. + */ + @JsonProperty("tuningDatasetExampleCount") + public abstract Builder tuningDatasetExampleCount(Long tuningDatasetExampleCount); + + /** + * Setter for tuningStepCount. + * + *

tuningStepCount: Output only. Number of tuning steps for this Tuning Job. + */ + @JsonProperty("tuningStepCount") + public abstract Builder tuningStepCount(Long tuningStepCount); + + /** + * Setter for userDatasetExamples. + * + *

userDatasetExamples: Output only. Sample user messages in the training dataset uri. + */ + @JsonProperty("userDatasetExamples") + public abstract Builder userDatasetExamples(List userDatasetExamples); + + /** + * Setter for userDatasetExamples. + * + *

userDatasetExamples: Output only. Sample user messages in the training dataset uri. + */ + public Builder userDatasetExamples(Content... userDatasetExamples) { + return userDatasetExamples(Arrays.asList(userDatasetExamples)); + } + + /** + * Setter for userDatasetExamples builder. + * + *

userDatasetExamples: Output only. Sample user messages in the training dataset uri. + */ + public Builder userDatasetExamples(Content.Builder... userDatasetExamplesBuilders) { + return userDatasetExamples( + Arrays.asList(userDatasetExamplesBuilders).stream() + .map(Content.Builder::build) + .collect(toImmutableList())); + } + + /** + * Setter for userInputTokenDistribution. + * + *

userInputTokenDistribution: Output only. Dataset distributions for the user input tokens. + */ + @JsonProperty("userInputTokenDistribution") + public abstract Builder userInputTokenDistribution( + DatasetDistribution userInputTokenDistribution); + + /** + * Setter for userInputTokenDistribution builder. + * + *

userInputTokenDistribution: Output only. Dataset distributions for the user input tokens. + */ + public Builder userInputTokenDistribution( + DatasetDistribution.Builder userInputTokenDistributionBuilder) { + return userInputTokenDistribution(userInputTokenDistributionBuilder.build()); + } + + /** + * Setter for userMessagePerExampleDistribution. + * + *

userMessagePerExampleDistribution: Output only. Dataset distributions for the messages per + * example. + */ + @JsonProperty("userMessagePerExampleDistribution") + public abstract Builder userMessagePerExampleDistribution( + DatasetDistribution userMessagePerExampleDistribution); + + /** + * Setter for userMessagePerExampleDistribution builder. + * + *

userMessagePerExampleDistribution: Output only. Dataset distributions for the messages per + * example. + */ + public Builder userMessagePerExampleDistribution( + DatasetDistribution.Builder userMessagePerExampleDistributionBuilder) { + return userMessagePerExampleDistribution(userMessagePerExampleDistributionBuilder.build()); + } + + /** + * Setter for userOutputTokenDistribution. + * + *

userOutputTokenDistribution: Output only. Dataset distributions for the user output + * tokens. + */ + @JsonProperty("userOutputTokenDistribution") + public abstract Builder userOutputTokenDistribution( + DatasetDistribution userOutputTokenDistribution); + + /** + * Setter for userOutputTokenDistribution builder. + * + *

userOutputTokenDistribution: Output only. Dataset distributions for the user output + * tokens. + */ + public Builder userOutputTokenDistribution( + DatasetDistribution.Builder userOutputTokenDistributionBuilder) { + return userOutputTokenDistribution(userOutputTokenDistributionBuilder.build()); + } + + public abstract DatasetStats build(); + } + + /** Deserializes a JSON string to a DatasetStats object. */ + public static DatasetStats fromJson(String jsonString) { + return JsonSerializable.fromJsonString(jsonString, DatasetStats.class); + } +} diff --git a/src/main/java/com/google/genai/types/DistillationDataStats.java b/src/main/java/com/google/genai/types/DistillationDataStats.java new file mode 100644 index 00000000000..68c608529f5 --- /dev/null +++ b/src/main/java/com/google/genai/types/DistillationDataStats.java @@ -0,0 +1,77 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Auto-generated code. Do not edit. + +package com.google.genai.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.google.auto.value.AutoValue; +import com.google.genai.JsonSerializable; +import java.util.Optional; + +/** Statistics computed for datasets used for distillation. */ +@AutoValue +@JsonDeserialize(builder = DistillationDataStats.Builder.class) +public abstract class DistillationDataStats extends JsonSerializable { + /** Output only. Statistics computed for the training dataset. */ + @JsonProperty("trainingDatasetStats") + public abstract Optional trainingDatasetStats(); + + /** Instantiates a builder for DistillationDataStats. */ + public static Builder builder() { + return new AutoValue_DistillationDataStats.Builder(); + } + + /** Creates a builder with the same values as this instance. */ + public abstract Builder toBuilder(); + + /** Builder for DistillationDataStats. */ + @AutoValue.Builder + public abstract static class Builder { + /** For internal usage. Please use `DistillationDataStats.builder()` for instantiation. */ + @JsonCreator + private static Builder create() { + return new AutoValue_DistillationDataStats.Builder(); + } + + /** + * Setter for trainingDatasetStats. + * + *

trainingDatasetStats: Output only. Statistics computed for the training dataset. + */ + @JsonProperty("trainingDatasetStats") + public abstract Builder trainingDatasetStats(DatasetStats trainingDatasetStats); + + /** + * Setter for trainingDatasetStats builder. + * + *

trainingDatasetStats: Output only. Statistics computed for the training dataset. + */ + public Builder trainingDatasetStats(DatasetStats.Builder trainingDatasetStatsBuilder) { + return trainingDatasetStats(trainingDatasetStatsBuilder.build()); + } + + public abstract DistillationDataStats build(); + } + + /** Deserializes a JSON string to a DistillationDataStats object. */ + public static DistillationDataStats fromJson(String jsonString) { + return JsonSerializable.fromJsonString(jsonString, DistillationDataStats.class); + } +} diff --git a/src/main/java/com/google/genai/types/DistillationHyperParameters.java b/src/main/java/com/google/genai/types/DistillationHyperParameters.java new file mode 100644 index 00000000000..be717feef84 --- /dev/null +++ b/src/main/java/com/google/genai/types/DistillationHyperParameters.java @@ -0,0 +1,119 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Auto-generated code. Do not edit. + +package com.google.genai.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.google.api.core.InternalApi; +import com.google.auto.value.AutoValue; +import com.google.errorprone.annotations.CanIgnoreReturnValue; +import com.google.genai.JsonSerializable; +import java.util.Optional; + +/** Hyperparameters for Distillation. */ +@AutoValue +@InternalApi +@JsonDeserialize(builder = DistillationHyperParameters.Builder.class) +public abstract class DistillationHyperParameters extends JsonSerializable { + /** Optional. Adapter size for distillation. */ + @JsonProperty("adapterSize") + public abstract Optional adapterSize(); + + /** + * Optional. Number of complete passes the model makes over the entire training dataset during + * training. + */ + @JsonProperty("epochCount") + public abstract Optional epochCount(); + + /** Optional. Multiplier for adjusting the default learning rate. */ + @JsonProperty("learningRateMultiplier") + public abstract Optional learningRateMultiplier(); + + /** Instantiates a builder for DistillationHyperParameters. */ + public static Builder builder() { + return new AutoValue_DistillationHyperParameters.Builder(); + } + + /** Creates a builder with the same values as this instance. */ + public abstract Builder toBuilder(); + + /** Builder for DistillationHyperParameters. */ + @AutoValue.Builder + public abstract static class Builder { + /** For internal usage. Please use `DistillationHyperParameters.builder()` for instantiation. */ + @JsonCreator + private static Builder create() { + return new AutoValue_DistillationHyperParameters.Builder(); + } + + /** + * Setter for adapterSize. + * + *

adapterSize: Optional. Adapter size for distillation. + */ + @JsonProperty("adapterSize") + public abstract Builder adapterSize(AdapterSize adapterSize); + + /** + * Setter for adapterSize given a known enum. + * + *

adapterSize: Optional. Adapter size for distillation. + */ + @CanIgnoreReturnValue + public Builder adapterSize(AdapterSize.Known knownType) { + return adapterSize(new AdapterSize(knownType)); + } + + /** + * Setter for adapterSize given a string. + * + *

adapterSize: Optional. Adapter size for distillation. + */ + @CanIgnoreReturnValue + public Builder adapterSize(String adapterSize) { + return adapterSize(new AdapterSize(adapterSize)); + } + + /** + * Setter for epochCount. + * + *

epochCount: Optional. Number of complete passes the model makes over the entire training + * dataset during training. + */ + @JsonProperty("epochCount") + public abstract Builder epochCount(Long epochCount); + + /** + * Setter for learningRateMultiplier. + * + *

learningRateMultiplier: Optional. Multiplier for adjusting the default learning rate. + */ + @JsonProperty("learningRateMultiplier") + public abstract Builder learningRateMultiplier(Double learningRateMultiplier); + + public abstract DistillationHyperParameters build(); + } + + /** Deserializes a JSON string to a DistillationHyperParameters object. */ + public static DistillationHyperParameters fromJson(String jsonString) { + return JsonSerializable.fromJsonString(jsonString, DistillationHyperParameters.class); + } +} diff --git a/src/main/java/com/google/genai/types/DistillationSpec.java b/src/main/java/com/google/genai/types/DistillationSpec.java new file mode 100644 index 00000000000..638b6450620 --- /dev/null +++ b/src/main/java/com/google/genai/types/DistillationSpec.java @@ -0,0 +1,175 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Auto-generated code. Do not edit. + +package com.google.genai.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.google.auto.value.AutoValue; +import com.google.genai.JsonSerializable; +import java.util.Optional; + +/** Tuning Spec for Distillation. */ +@AutoValue +@JsonDeserialize(builder = DistillationSpec.Builder.class) +public abstract class DistillationSpec extends JsonSerializable { + /** + * The base teacher model that is being distilled. See [Supported + * models](https://cloud.google.com/vertex-ai/generative-ai/docs/model-reference/tuning#supported_models). + */ + @JsonProperty("baseTeacherModel") + public abstract Optional baseTeacherModel(); + + /** Optional. Hyperparameters for Distillation. */ + @JsonProperty("hyperParameters") + public abstract Optional hyperParameters(); + + /** + * Deprecated. A path in a Cloud Storage bucket, which will be treated as the root output + * directory of the distillation pipeline. It is used by the system to generate the paths of + * output artifacts. + */ + @JsonProperty("pipelineRootDirectory") + public abstract Optional pipelineRootDirectory(); + + /** + * The student model that is being tuned, e.g., "google/gemma-2b-1.1-it". Deprecated. Use + * base_model instead. + */ + @JsonProperty("studentModel") + public abstract Optional studentModel(); + + /** + * Deprecated. Cloud Storage path to file containing training dataset for tuning. The dataset must + * be formatted as a JSONL file. + */ + @JsonProperty("trainingDatasetUri") + public abstract Optional trainingDatasetUri(); + + /** + * The resource name of the Tuned teacher model. Format: + * `projects/{project}/locations/{location}/models/{model}`. + */ + @JsonProperty("tunedTeacherModelSource") + public abstract Optional tunedTeacherModelSource(); + + /** + * Optional. Cloud Storage path to file containing validation dataset for tuning. The dataset must + * be formatted as a JSONL file. + */ + @JsonProperty("validationDatasetUri") + public abstract Optional validationDatasetUri(); + + /** Instantiates a builder for DistillationSpec. */ + public static Builder builder() { + return new AutoValue_DistillationSpec.Builder(); + } + + /** Creates a builder with the same values as this instance. */ + public abstract Builder toBuilder(); + + /** Builder for DistillationSpec. */ + @AutoValue.Builder + public abstract static class Builder { + /** For internal usage. Please use `DistillationSpec.builder()` for instantiation. */ + @JsonCreator + private static Builder create() { + return new AutoValue_DistillationSpec.Builder(); + } + + /** + * Setter for baseTeacherModel. + * + *

baseTeacherModel: The base teacher model that is being distilled. See [Supported + * models](https://cloud.google.com/vertex-ai/generative-ai/docs/model-reference/tuning#supported_models). + */ + @JsonProperty("baseTeacherModel") + public abstract Builder baseTeacherModel(String baseTeacherModel); + + /** + * Setter for hyperParameters. + * + *

hyperParameters: Optional. Hyperparameters for Distillation. + */ + @JsonProperty("hyperParameters") + public abstract Builder hyperParameters(DistillationHyperParameters hyperParameters); + + /** + * Setter for hyperParameters builder. + * + *

hyperParameters: Optional. Hyperparameters for Distillation. + */ + public Builder hyperParameters(DistillationHyperParameters.Builder hyperParametersBuilder) { + return hyperParameters(hyperParametersBuilder.build()); + } + + /** + * Setter for pipelineRootDirectory. + * + *

pipelineRootDirectory: Deprecated. A path in a Cloud Storage bucket, which will be treated + * as the root output directory of the distillation pipeline. It is used by the system to + * generate the paths of output artifacts. + */ + @JsonProperty("pipelineRootDirectory") + public abstract Builder pipelineRootDirectory(String pipelineRootDirectory); + + /** + * Setter for studentModel. + * + *

studentModel: The student model that is being tuned, e.g., "google/gemma-2b-1.1-it". + * Deprecated. Use base_model instead. + */ + @JsonProperty("studentModel") + public abstract Builder studentModel(String studentModel); + + /** + * Setter for trainingDatasetUri. + * + *

trainingDatasetUri: Deprecated. Cloud Storage path to file containing training dataset for + * tuning. The dataset must be formatted as a JSONL file. + */ + @JsonProperty("trainingDatasetUri") + public abstract Builder trainingDatasetUri(String trainingDatasetUri); + + /** + * Setter for tunedTeacherModelSource. + * + *

tunedTeacherModelSource: The resource name of the Tuned teacher model. Format: + * `projects/{project}/locations/{location}/models/{model}`. + */ + @JsonProperty("tunedTeacherModelSource") + public abstract Builder tunedTeacherModelSource(String tunedTeacherModelSource); + + /** + * Setter for validationDatasetUri. + * + *

validationDatasetUri: Optional. Cloud Storage path to file containing validation dataset + * for tuning. The dataset must be formatted as a JSONL file. + */ + @JsonProperty("validationDatasetUri") + public abstract Builder validationDatasetUri(String validationDatasetUri); + + public abstract DistillationSpec build(); + } + + /** Deserializes a JSON string to a DistillationSpec object. */ + public static DistillationSpec fromJson(String jsonString) { + return JsonSerializable.fromJsonString(jsonString, DistillationSpec.class); + } +} diff --git a/src/main/java/com/google/genai/types/EncryptionSpec.java b/src/main/java/com/google/genai/types/EncryptionSpec.java new file mode 100644 index 00000000000..ea39c7c341a --- /dev/null +++ b/src/main/java/com/google/genai/types/EncryptionSpec.java @@ -0,0 +1,78 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Auto-generated code. Do not edit. + +package com.google.genai.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.google.auto.value.AutoValue; +import com.google.genai.JsonSerializable; +import java.util.Optional; + +/** + * Represents a customer-managed encryption key spec that can be applied to a top-level resource. + */ +@AutoValue +@JsonDeserialize(builder = EncryptionSpec.Builder.class) +public abstract class EncryptionSpec extends JsonSerializable { + /** + * Required. The Cloud KMS resource identifier of the customer managed encryption key used to + * protect a resource. Has the form: + * `projects/my-project/locations/my-region/keyRings/my-kr/cryptoKeys/my-key`. The key needs to be + * in the same region as where the compute resource is created. + */ + @JsonProperty("kmsKeyName") + public abstract Optional kmsKeyName(); + + /** Instantiates a builder for EncryptionSpec. */ + public static Builder builder() { + return new AutoValue_EncryptionSpec.Builder(); + } + + /** Creates a builder with the same values as this instance. */ + public abstract Builder toBuilder(); + + /** Builder for EncryptionSpec. */ + @AutoValue.Builder + public abstract static class Builder { + /** For internal usage. Please use `EncryptionSpec.builder()` for instantiation. */ + @JsonCreator + private static Builder create() { + return new AutoValue_EncryptionSpec.Builder(); + } + + /** + * Setter for kmsKeyName. + * + *

kmsKeyName: Required. The Cloud KMS resource identifier of the customer managed encryption + * key used to protect a resource. Has the form: + * `projects/my-project/locations/my-region/keyRings/my-kr/cryptoKeys/my-key`. The key needs to + * be in the same region as where the compute resource is created. + */ + @JsonProperty("kmsKeyName") + public abstract Builder kmsKeyName(String kmsKeyName); + + public abstract EncryptionSpec build(); + } + + /** Deserializes a JSON string to a EncryptionSpec object. */ + public static EncryptionSpec fromJson(String jsonString) { + return JsonSerializable.fromJsonString(jsonString, EncryptionSpec.class); + } +} diff --git a/src/main/java/com/google/genai/types/GetTuningJobConfig.java b/src/main/java/com/google/genai/types/GetTuningJobConfig.java new file mode 100644 index 00000000000..03981c4c9c3 --- /dev/null +++ b/src/main/java/com/google/genai/types/GetTuningJobConfig.java @@ -0,0 +1,77 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Auto-generated code. Do not edit. + +package com.google.genai.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.google.auto.value.AutoValue; +import com.google.genai.JsonSerializable; +import java.util.Optional; + +/** Optional parameters for tunings.get method. */ +@AutoValue +@JsonDeserialize(builder = GetTuningJobConfig.Builder.class) +public abstract class GetTuningJobConfig extends JsonSerializable { + /** Used to override HTTP request options. */ + @JsonProperty("httpOptions") + public abstract Optional httpOptions(); + + /** Instantiates a builder for GetTuningJobConfig. */ + public static Builder builder() { + return new AutoValue_GetTuningJobConfig.Builder(); + } + + /** Creates a builder with the same values as this instance. */ + public abstract Builder toBuilder(); + + /** Builder for GetTuningJobConfig. */ + @AutoValue.Builder + public abstract static class Builder { + /** For internal usage. Please use `GetTuningJobConfig.builder()` for instantiation. */ + @JsonCreator + private static Builder create() { + return new AutoValue_GetTuningJobConfig.Builder(); + } + + /** + * Setter for httpOptions. + * + *

httpOptions: Used to override HTTP request options. + */ + @JsonProperty("httpOptions") + public abstract Builder httpOptions(HttpOptions httpOptions); + + /** + * Setter for httpOptions builder. + * + *

httpOptions: Used to override HTTP request options. + */ + public Builder httpOptions(HttpOptions.Builder httpOptionsBuilder) { + return httpOptions(httpOptionsBuilder.build()); + } + + public abstract GetTuningJobConfig build(); + } + + /** Deserializes a JSON string to a GetTuningJobConfig object. */ + public static GetTuningJobConfig fromJson(String jsonString) { + return JsonSerializable.fromJsonString(jsonString, GetTuningJobConfig.class); + } +} diff --git a/src/main/java/com/google/genai/types/GetTuningJobParameters.java b/src/main/java/com/google/genai/types/GetTuningJobParameters.java new file mode 100644 index 00000000000..9890b40ccda --- /dev/null +++ b/src/main/java/com/google/genai/types/GetTuningJobParameters.java @@ -0,0 +1,91 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Auto-generated code. Do not edit. + +package com.google.genai.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.google.api.core.InternalApi; +import com.google.auto.value.AutoValue; +import com.google.genai.JsonSerializable; +import java.util.Optional; + +/** Parameters for the get method. */ +@AutoValue +@InternalApi +@JsonDeserialize(builder = GetTuningJobParameters.Builder.class) +public abstract class GetTuningJobParameters extends JsonSerializable { + /** */ + @JsonProperty("name") + public abstract Optional name(); + + /** Optional parameters for the request. */ + @JsonProperty("config") + public abstract Optional config(); + + /** Instantiates a builder for GetTuningJobParameters. */ + public static Builder builder() { + return new AutoValue_GetTuningJobParameters.Builder(); + } + + /** Creates a builder with the same values as this instance. */ + public abstract Builder toBuilder(); + + /** Builder for GetTuningJobParameters. */ + @AutoValue.Builder + public abstract static class Builder { + /** For internal usage. Please use `GetTuningJobParameters.builder()` for instantiation. */ + @JsonCreator + private static Builder create() { + return new AutoValue_GetTuningJobParameters.Builder(); + } + + /** + * Setter for name. + * + *

name: + */ + @JsonProperty("name") + public abstract Builder name(String name); + + /** + * Setter for config. + * + *

config: Optional parameters for the request. + */ + @JsonProperty("config") + public abstract Builder config(GetTuningJobConfig config); + + /** + * Setter for config builder. + * + *

config: Optional parameters for the request. + */ + public Builder config(GetTuningJobConfig.Builder configBuilder) { + return config(configBuilder.build()); + } + + public abstract GetTuningJobParameters build(); + } + + /** Deserializes a JSON string to a GetTuningJobParameters object. */ + public static GetTuningJobParameters fromJson(String jsonString) { + return JsonSerializable.fromJsonString(jsonString, GetTuningJobParameters.class); + } +} diff --git a/src/main/java/com/google/genai/types/GoogleRpcStatus.java b/src/main/java/com/google/genai/types/GoogleRpcStatus.java new file mode 100644 index 00000000000..6672f496f51 --- /dev/null +++ b/src/main/java/com/google/genai/types/GoogleRpcStatus.java @@ -0,0 +1,121 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Auto-generated code. Do not edit. + +package com.google.genai.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.google.auto.value.AutoValue; +import com.google.genai.JsonSerializable; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +/** + * The `Status` type defines a logical error model that is suitable for different programming + * environments, including REST APIs and RPC APIs. It is used by [gRPC](https://github.com/grpc). + * Each `Status` message contains three pieces of data: error code, error message, and error + * details. You can find out more about this error model and how to work with it in the [API Design + * Guide](https://cloud.google.com/apis/design/errors). + */ +@AutoValue +@JsonDeserialize(builder = GoogleRpcStatus.Builder.class) +public abstract class GoogleRpcStatus extends JsonSerializable { + /** The status code, which should be an enum value of google.rpc.Code. */ + @JsonProperty("code") + public abstract Optional code(); + + /** + * A list of messages that carry the error details. There is a common set of message types for + * APIs to use. + */ + @JsonProperty("details") + public abstract Optional>> details(); + + /** + * A developer-facing error message, which should be in English. Any user-facing error message + * should be localized and sent in the google.rpc.Status.details field, or localized by the + * client. + */ + @JsonProperty("message") + public abstract Optional message(); + + /** Instantiates a builder for GoogleRpcStatus. */ + public static Builder builder() { + return new AutoValue_GoogleRpcStatus.Builder(); + } + + /** Creates a builder with the same values as this instance. */ + public abstract Builder toBuilder(); + + /** Builder for GoogleRpcStatus. */ + @AutoValue.Builder + public abstract static class Builder { + /** For internal usage. Please use `GoogleRpcStatus.builder()` for instantiation. */ + @JsonCreator + private static Builder create() { + return new AutoValue_GoogleRpcStatus.Builder(); + } + + /** + * Setter for code. + * + *

code: The status code, which should be an enum value of google.rpc.Code. + */ + @JsonProperty("code") + public abstract Builder code(Integer code); + + /** + * Setter for details. + * + *

details: A list of messages that carry the error details. There is a common set of message + * types for APIs to use. + */ + @JsonProperty("details") + public abstract Builder details(List> details); + + /** + * Setter for details. + * + *

details: A list of messages that carry the error details. There is a common set of message + * types for APIs to use. + */ + public Builder details(Map... details) { + return details(Arrays.asList(details)); + } + + /** + * Setter for message. + * + *

message: A developer-facing error message, which should be in English. Any user-facing + * error message should be localized and sent in the google.rpc.Status.details field, or + * localized by the client. + */ + @JsonProperty("message") + public abstract Builder message(String message); + + public abstract GoogleRpcStatus build(); + } + + /** Deserializes a JSON string to a GoogleRpcStatus object. */ + public static GoogleRpcStatus fromJson(String jsonString) { + return JsonSerializable.fromJsonString(jsonString, GoogleRpcStatus.class); + } +} diff --git a/src/main/java/com/google/genai/types/ListTuningJobsConfig.java b/src/main/java/com/google/genai/types/ListTuningJobsConfig.java new file mode 100644 index 00000000000..3e5cac6644b --- /dev/null +++ b/src/main/java/com/google/genai/types/ListTuningJobsConfig.java @@ -0,0 +1,113 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Auto-generated code. Do not edit. + +package com.google.genai.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.google.auto.value.AutoValue; +import com.google.genai.JsonSerializable; +import java.util.Optional; + +/** Configuration for the list tuning jobs method. */ +@AutoValue +@JsonDeserialize(builder = ListTuningJobsConfig.Builder.class) +public abstract class ListTuningJobsConfig extends JsonSerializable { + /** Used to override HTTP request options. */ + @JsonProperty("httpOptions") + public abstract Optional httpOptions(); + + /** */ + @JsonProperty("pageSize") + public abstract Optional pageSize(); + + /** */ + @JsonProperty("pageToken") + public abstract Optional pageToken(); + + /** */ + @JsonProperty("filter") + public abstract Optional filter(); + + /** Instantiates a builder for ListTuningJobsConfig. */ + public static Builder builder() { + return new AutoValue_ListTuningJobsConfig.Builder(); + } + + /** Creates a builder with the same values as this instance. */ + public abstract Builder toBuilder(); + + /** Builder for ListTuningJobsConfig. */ + @AutoValue.Builder + public abstract static class Builder { + /** For internal usage. Please use `ListTuningJobsConfig.builder()` for instantiation. */ + @JsonCreator + private static Builder create() { + return new AutoValue_ListTuningJobsConfig.Builder(); + } + + /** + * Setter for httpOptions. + * + *

httpOptions: Used to override HTTP request options. + */ + @JsonProperty("httpOptions") + public abstract Builder httpOptions(HttpOptions httpOptions); + + /** + * Setter for httpOptions builder. + * + *

httpOptions: Used to override HTTP request options. + */ + public Builder httpOptions(HttpOptions.Builder httpOptionsBuilder) { + return httpOptions(httpOptionsBuilder.build()); + } + + /** + * Setter for pageSize. + * + *

pageSize: + */ + @JsonProperty("pageSize") + public abstract Builder pageSize(Integer pageSize); + + /** + * Setter for pageToken. + * + *

pageToken: + */ + @JsonProperty("pageToken") + public abstract Builder pageToken(String pageToken); + + /** + * Setter for filter. + * + *

filter: + */ + @JsonProperty("filter") + public abstract Builder filter(String filter); + + public abstract ListTuningJobsConfig build(); + } + + /** Deserializes a JSON string to a ListTuningJobsConfig object. */ + public static ListTuningJobsConfig fromJson(String jsonString) { + return JsonSerializable.fromJsonString(jsonString, ListTuningJobsConfig.class); + } +} diff --git a/src/main/java/com/google/genai/types/ListTuningJobsParameters.java b/src/main/java/com/google/genai/types/ListTuningJobsParameters.java new file mode 100644 index 00000000000..26765a4eb27 --- /dev/null +++ b/src/main/java/com/google/genai/types/ListTuningJobsParameters.java @@ -0,0 +1,79 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Auto-generated code. Do not edit. + +package com.google.genai.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.google.api.core.InternalApi; +import com.google.auto.value.AutoValue; +import com.google.genai.JsonSerializable; +import java.util.Optional; + +/** Parameters for the list tuning jobs method. */ +@AutoValue +@InternalApi +@JsonDeserialize(builder = ListTuningJobsParameters.Builder.class) +public abstract class ListTuningJobsParameters extends JsonSerializable { + /** */ + @JsonProperty("config") + public abstract Optional config(); + + /** Instantiates a builder for ListTuningJobsParameters. */ + public static Builder builder() { + return new AutoValue_ListTuningJobsParameters.Builder(); + } + + /** Creates a builder with the same values as this instance. */ + public abstract Builder toBuilder(); + + /** Builder for ListTuningJobsParameters. */ + @AutoValue.Builder + public abstract static class Builder { + /** For internal usage. Please use `ListTuningJobsParameters.builder()` for instantiation. */ + @JsonCreator + private static Builder create() { + return new AutoValue_ListTuningJobsParameters.Builder(); + } + + /** + * Setter for config. + * + *

config: + */ + @JsonProperty("config") + public abstract Builder config(ListTuningJobsConfig config); + + /** + * Setter for config builder. + * + *

config: + */ + public Builder config(ListTuningJobsConfig.Builder configBuilder) { + return config(configBuilder.build()); + } + + public abstract ListTuningJobsParameters build(); + } + + /** Deserializes a JSON string to a ListTuningJobsParameters object. */ + public static ListTuningJobsParameters fromJson(String jsonString) { + return JsonSerializable.fromJsonString(jsonString, ListTuningJobsParameters.class); + } +} diff --git a/src/main/java/com/google/genai/types/ListTuningJobsResponse.java b/src/main/java/com/google/genai/types/ListTuningJobsResponse.java new file mode 100644 index 00000000000..635484714e3 --- /dev/null +++ b/src/main/java/com/google/genai/types/ListTuningJobsResponse.java @@ -0,0 +1,109 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Auto-generated code. Do not edit. + +package com.google.genai.types; + +import static com.google.common.collect.ImmutableList.toImmutableList; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.google.auto.value.AutoValue; +import com.google.genai.JsonSerializable; +import java.util.Arrays; +import java.util.List; +import java.util.Optional; + +/** Response for the list tuning jobs method. */ +@AutoValue +@JsonDeserialize(builder = ListTuningJobsResponse.Builder.class) +public abstract class ListTuningJobsResponse extends JsonSerializable { + /** + * A token to retrieve the next page of results. Pass to ListTuningJobsRequest.page_token to + * obtain that page. + */ + @JsonProperty("nextPageToken") + public abstract Optional nextPageToken(); + + /** List of TuningJobs in the requested page. */ + @JsonProperty("tuningJobs") + public abstract Optional> tuningJobs(); + + /** Instantiates a builder for ListTuningJobsResponse. */ + public static Builder builder() { + return new AutoValue_ListTuningJobsResponse.Builder(); + } + + /** Creates a builder with the same values as this instance. */ + public abstract Builder toBuilder(); + + /** Builder for ListTuningJobsResponse. */ + @AutoValue.Builder + public abstract static class Builder { + /** For internal usage. Please use `ListTuningJobsResponse.builder()` for instantiation. */ + @JsonCreator + private static Builder create() { + return new AutoValue_ListTuningJobsResponse.Builder(); + } + + /** + * Setter for nextPageToken. + * + *

nextPageToken: A token to retrieve the next page of results. Pass to + * ListTuningJobsRequest.page_token to obtain that page. + */ + @JsonProperty("nextPageToken") + public abstract Builder nextPageToken(String nextPageToken); + + /** + * Setter for tuningJobs. + * + *

tuningJobs: List of TuningJobs in the requested page. + */ + @JsonProperty("tuningJobs") + public abstract Builder tuningJobs(List tuningJobs); + + /** + * Setter for tuningJobs. + * + *

tuningJobs: List of TuningJobs in the requested page. + */ + public Builder tuningJobs(TuningJob... tuningJobs) { + return tuningJobs(Arrays.asList(tuningJobs)); + } + + /** + * Setter for tuningJobs builder. + * + *

tuningJobs: List of TuningJobs in the requested page. + */ + public Builder tuningJobs(TuningJob.Builder... tuningJobsBuilders) { + return tuningJobs( + Arrays.asList(tuningJobsBuilders).stream() + .map(TuningJob.Builder::build) + .collect(toImmutableList())); + } + + public abstract ListTuningJobsResponse build(); + } + + /** Deserializes a JSON string to a ListTuningJobsResponse object. */ + public static ListTuningJobsResponse fromJson(String jsonString) { + return JsonSerializable.fromJsonString(jsonString, ListTuningJobsResponse.class); + } +} diff --git a/src/main/java/com/google/genai/types/Operation.java b/src/main/java/com/google/genai/types/Operation.java new file mode 100644 index 00000000000..297d338f24f --- /dev/null +++ b/src/main/java/com/google/genai/types/Operation.java @@ -0,0 +1,123 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Auto-generated code. Do not edit. + +package com.google.genai.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.google.auto.value.AutoValue; +import com.google.genai.JsonSerializable; +import java.util.Map; +import java.util.Optional; + +/** A long-running operation. */ +@AutoValue +@JsonDeserialize(builder = Operation.Builder.class) +public abstract class Operation extends JsonSerializable { + /** + * The server-assigned name, which is only unique within the same service that originally returns + * it. If you use the default HTTP mapping, the `name` should be a resource name ending with + * `operations/{unique_id}`. + */ + @JsonProperty("name") + public abstract Optional name(); + + /** + * Service-specific metadata associated with the operation. It typically contains progress + * information and common metadata such as create time. Some services might not provide such + * metadata. Any method that returns a long-running operation should document the metadata type, + * if any. + */ + @JsonProperty("metadata") + public abstract Optional> metadata(); + + /** + * If the value is `false`, it means the operation is still in progress. If `true`, the operation + * is completed, and either `error` or `response` is available. + */ + @JsonProperty("done") + public abstract Optional done(); + + /** The error result of the operation in case of failure or cancellation. */ + @JsonProperty("error") + public abstract Optional> error(); + + /** Instantiates a builder for Operation. */ + public static Builder builder() { + return new AutoValue_Operation.Builder(); + } + + /** Creates a builder with the same values as this instance. */ + public abstract Builder toBuilder(); + + /** Builder for Operation. */ + @AutoValue.Builder + public abstract static class Builder { + /** For internal usage. Please use `Operation.builder()` for instantiation. */ + @JsonCreator + private static Builder create() { + return new AutoValue_Operation.Builder(); + } + + /** + * Setter for name. + * + *

name: The server-assigned name, which is only unique within the same service that + * originally returns it. If you use the default HTTP mapping, the `name` should be a resource + * name ending with `operations/{unique_id}`. + */ + @JsonProperty("name") + public abstract Builder name(String name); + + /** + * Setter for metadata. + * + *

metadata: Service-specific metadata associated with the operation. It typically contains + * progress information and common metadata such as create time. Some services might not provide + * such metadata. Any method that returns a long-running operation should document the metadata + * type, if any. + */ + @JsonProperty("metadata") + public abstract Builder metadata(Map metadata); + + /** + * Setter for done. + * + *

done: If the value is `false`, it means the operation is still in progress. If `true`, the + * operation is completed, and either `error` or `response` is available. + */ + @JsonProperty("done") + public abstract Builder done(boolean done); + + /** + * Setter for error. + * + *

error: The error result of the operation in case of failure or cancellation. + */ + @JsonProperty("error") + public abstract Builder error(Map error); + + public abstract Operation build(); + } + + /** Deserializes a JSON string to a Operation object. */ + public static Operation fromJson(String jsonString) { + return JsonSerializable.fromJsonString(jsonString, Operation.class); + } +} diff --git a/src/main/java/com/google/genai/types/PartnerModelTuningSpec.java b/src/main/java/com/google/genai/types/PartnerModelTuningSpec.java new file mode 100644 index 00000000000..8d8a70e12b3 --- /dev/null +++ b/src/main/java/com/google/genai/types/PartnerModelTuningSpec.java @@ -0,0 +1,105 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Auto-generated code. Do not edit. + +package com.google.genai.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.google.auto.value.AutoValue; +import com.google.genai.JsonSerializable; +import java.util.Map; +import java.util.Optional; + +/** Tuning spec for Partner models. */ +@AutoValue +@JsonDeserialize(builder = PartnerModelTuningSpec.Builder.class) +public abstract class PartnerModelTuningSpec extends JsonSerializable { + /** + * Hyperparameters for tuning. The accepted hyper_parameters and their valid range of values will + * differ depending on the base model. + */ + @JsonProperty("hyperParameters") + public abstract Optional> hyperParameters(); + + /** + * Required. Cloud Storage path to file containing training dataset for tuning. The dataset must + * be formatted as a JSONL file. + */ + @JsonProperty("trainingDatasetUri") + public abstract Optional trainingDatasetUri(); + + /** + * Optional. Cloud Storage path to file containing validation dataset for tuning. The dataset must + * be formatted as a JSONL file. + */ + @JsonProperty("validationDatasetUri") + public abstract Optional validationDatasetUri(); + + /** Instantiates a builder for PartnerModelTuningSpec. */ + public static Builder builder() { + return new AutoValue_PartnerModelTuningSpec.Builder(); + } + + /** Creates a builder with the same values as this instance. */ + public abstract Builder toBuilder(); + + /** Builder for PartnerModelTuningSpec. */ + @AutoValue.Builder + public abstract static class Builder { + /** For internal usage. Please use `PartnerModelTuningSpec.builder()` for instantiation. */ + @JsonCreator + private static Builder create() { + return new AutoValue_PartnerModelTuningSpec.Builder(); + } + + /** + * Setter for hyperParameters. + * + *

hyperParameters: Hyperparameters for tuning. The accepted hyper_parameters and their valid + * range of values will differ depending on the base model. + */ + @JsonProperty("hyperParameters") + public abstract Builder hyperParameters(Map hyperParameters); + + /** + * Setter for trainingDatasetUri. + * + *

trainingDatasetUri: Required. Cloud Storage path to file containing training dataset for + * tuning. The dataset must be formatted as a JSONL file. + */ + @JsonProperty("trainingDatasetUri") + public abstract Builder trainingDatasetUri(String trainingDatasetUri); + + /** + * Setter for validationDatasetUri. + * + *

validationDatasetUri: Optional. Cloud Storage path to file containing validation dataset + * for tuning. The dataset must be formatted as a JSONL file. + */ + @JsonProperty("validationDatasetUri") + public abstract Builder validationDatasetUri(String validationDatasetUri); + + public abstract PartnerModelTuningSpec build(); + } + + /** Deserializes a JSON string to a PartnerModelTuningSpec object. */ + public static PartnerModelTuningSpec fromJson(String jsonString) { + return JsonSerializable.fromJsonString(jsonString, PartnerModelTuningSpec.class); + } +} diff --git a/src/main/java/com/google/genai/types/SupervisedHyperParameters.java b/src/main/java/com/google/genai/types/SupervisedHyperParameters.java new file mode 100644 index 00000000000..18ee356bc4a --- /dev/null +++ b/src/main/java/com/google/genai/types/SupervisedHyperParameters.java @@ -0,0 +1,123 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Auto-generated code. Do not edit. + +package com.google.genai.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.google.api.core.InternalApi; +import com.google.auto.value.AutoValue; +import com.google.errorprone.annotations.CanIgnoreReturnValue; +import com.google.genai.JsonSerializable; +import java.util.Optional; + +/** Hyperparameters for SFT. */ +@AutoValue +@InternalApi +@JsonDeserialize(builder = SupervisedHyperParameters.Builder.class) +public abstract class SupervisedHyperParameters extends JsonSerializable { + /** Optional. Adapter size for tuning. */ + @JsonProperty("adapterSize") + public abstract Optional adapterSize(); + + /** + * Optional. Number of complete passes the model makes over the entire training dataset during + * training. + */ + @JsonProperty("epochCount") + public abstract Optional epochCount(); + + /** + * Optional. Multiplier for adjusting the default learning rate. Mutually exclusive with + * `learning_rate`. + */ + @JsonProperty("learningRateMultiplier") + public abstract Optional learningRateMultiplier(); + + /** Instantiates a builder for SupervisedHyperParameters. */ + public static Builder builder() { + return new AutoValue_SupervisedHyperParameters.Builder(); + } + + /** Creates a builder with the same values as this instance. */ + public abstract Builder toBuilder(); + + /** Builder for SupervisedHyperParameters. */ + @AutoValue.Builder + public abstract static class Builder { + /** For internal usage. Please use `SupervisedHyperParameters.builder()` for instantiation. */ + @JsonCreator + private static Builder create() { + return new AutoValue_SupervisedHyperParameters.Builder(); + } + + /** + * Setter for adapterSize. + * + *

adapterSize: Optional. Adapter size for tuning. + */ + @JsonProperty("adapterSize") + public abstract Builder adapterSize(AdapterSize adapterSize); + + /** + * Setter for adapterSize given a known enum. + * + *

adapterSize: Optional. Adapter size for tuning. + */ + @CanIgnoreReturnValue + public Builder adapterSize(AdapterSize.Known knownType) { + return adapterSize(new AdapterSize(knownType)); + } + + /** + * Setter for adapterSize given a string. + * + *

adapterSize: Optional. Adapter size for tuning. + */ + @CanIgnoreReturnValue + public Builder adapterSize(String adapterSize) { + return adapterSize(new AdapterSize(adapterSize)); + } + + /** + * Setter for epochCount. + * + *

epochCount: Optional. Number of complete passes the model makes over the entire training + * dataset during training. + */ + @JsonProperty("epochCount") + public abstract Builder epochCount(Long epochCount); + + /** + * Setter for learningRateMultiplier. + * + *

learningRateMultiplier: Optional. Multiplier for adjusting the default learning rate. + * Mutually exclusive with `learning_rate`. + */ + @JsonProperty("learningRateMultiplier") + public abstract Builder learningRateMultiplier(Double learningRateMultiplier); + + public abstract SupervisedHyperParameters build(); + } + + /** Deserializes a JSON string to a SupervisedHyperParameters object. */ + public static SupervisedHyperParameters fromJson(String jsonString) { + return JsonSerializable.fromJsonString(jsonString, SupervisedHyperParameters.class); + } +} diff --git a/src/main/java/com/google/genai/types/SupervisedTuningDataStats.java b/src/main/java/com/google/genai/types/SupervisedTuningDataStats.java new file mode 100644 index 00000000000..888301e5534 --- /dev/null +++ b/src/main/java/com/google/genai/types/SupervisedTuningDataStats.java @@ -0,0 +1,294 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Auto-generated code. Do not edit. + +package com.google.genai.types; + +import static com.google.common.collect.ImmutableList.toImmutableList; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.google.auto.value.AutoValue; +import com.google.genai.JsonSerializable; +import java.util.Arrays; +import java.util.List; +import java.util.Optional; + +/** Tuning data statistics for Supervised Tuning. */ +@AutoValue +@JsonDeserialize(builder = SupervisedTuningDataStats.Builder.class) +public abstract class SupervisedTuningDataStats extends JsonSerializable { + /** + * Output only. For each index in `truncated_example_indices`, the user-facing reason why the + * example was dropped. + */ + @JsonProperty("droppedExampleReasons") + public abstract Optional> droppedExampleReasons(); + + /** Output only. Number of billable characters in the tuning dataset. */ + @JsonProperty("totalBillableCharacterCount") + public abstract Optional totalBillableCharacterCount(); + + /** Output only. Number of billable tokens in the tuning dataset. */ + @JsonProperty("totalBillableTokenCount") + public abstract Optional totalBillableTokenCount(); + + /** + * Output only. The number of examples in the dataset that have been dropped. An example can be + * dropped for reasons including: too many tokens, contains an invalid image, contains too many + * images, etc. + */ + @JsonProperty("totalTruncatedExampleCount") + public abstract Optional totalTruncatedExampleCount(); + + /** Output only. Number of tuning characters in the tuning dataset. */ + @JsonProperty("totalTuningCharacterCount") + public abstract Optional totalTuningCharacterCount(); + + /** Output only. A partial sample of the indices (starting from 1) of the dropped examples. */ + @JsonProperty("truncatedExampleIndices") + public abstract Optional> truncatedExampleIndices(); + + /** Output only. Number of examples in the tuning dataset. */ + @JsonProperty("tuningDatasetExampleCount") + public abstract Optional tuningDatasetExampleCount(); + + /** Output only. Number of tuning steps for this Tuning Job. */ + @JsonProperty("tuningStepCount") + public abstract Optional tuningStepCount(); + + /** Output only. Sample user messages in the training dataset uri. */ + @JsonProperty("userDatasetExamples") + public abstract Optional> userDatasetExamples(); + + /** Output only. Dataset distributions for the user input tokens. */ + @JsonProperty("userInputTokenDistribution") + public abstract Optional userInputTokenDistribution(); + + /** Output only. Dataset distributions for the messages per example. */ + @JsonProperty("userMessagePerExampleDistribution") + public abstract Optional userMessagePerExampleDistribution(); + + /** Output only. Dataset distributions for the user output tokens. */ + @JsonProperty("userOutputTokenDistribution") + public abstract Optional userOutputTokenDistribution(); + + /** Instantiates a builder for SupervisedTuningDataStats. */ + public static Builder builder() { + return new AutoValue_SupervisedTuningDataStats.Builder(); + } + + /** Creates a builder with the same values as this instance. */ + public abstract Builder toBuilder(); + + /** Builder for SupervisedTuningDataStats. */ + @AutoValue.Builder + public abstract static class Builder { + /** For internal usage. Please use `SupervisedTuningDataStats.builder()` for instantiation. */ + @JsonCreator + private static Builder create() { + return new AutoValue_SupervisedTuningDataStats.Builder(); + } + + /** + * Setter for droppedExampleReasons. + * + *

droppedExampleReasons: Output only. For each index in `truncated_example_indices`, the + * user-facing reason why the example was dropped. + */ + @JsonProperty("droppedExampleReasons") + public abstract Builder droppedExampleReasons(List droppedExampleReasons); + + /** + * Setter for droppedExampleReasons. + * + *

droppedExampleReasons: Output only. For each index in `truncated_example_indices`, the + * user-facing reason why the example was dropped. + */ + public Builder droppedExampleReasons(String... droppedExampleReasons) { + return droppedExampleReasons(Arrays.asList(droppedExampleReasons)); + } + + /** + * Setter for totalBillableCharacterCount. + * + *

totalBillableCharacterCount: Output only. Number of billable characters in the tuning + * dataset. + */ + @JsonProperty("totalBillableCharacterCount") + public abstract Builder totalBillableCharacterCount(Long totalBillableCharacterCount); + + /** + * Setter for totalBillableTokenCount. + * + *

totalBillableTokenCount: Output only. Number of billable tokens in the tuning dataset. + */ + @JsonProperty("totalBillableTokenCount") + public abstract Builder totalBillableTokenCount(Long totalBillableTokenCount); + + /** + * Setter for totalTruncatedExampleCount. + * + *

totalTruncatedExampleCount: Output only. The number of examples in the dataset that have + * been dropped. An example can be dropped for reasons including: too many tokens, contains an + * invalid image, contains too many images, etc. + */ + @JsonProperty("totalTruncatedExampleCount") + public abstract Builder totalTruncatedExampleCount(Long totalTruncatedExampleCount); + + /** + * Setter for totalTuningCharacterCount. + * + *

totalTuningCharacterCount: Output only. Number of tuning characters in the tuning dataset. + */ + @JsonProperty("totalTuningCharacterCount") + public abstract Builder totalTuningCharacterCount(Long totalTuningCharacterCount); + + /** + * Setter for truncatedExampleIndices. + * + *

truncatedExampleIndices: Output only. A partial sample of the indices (starting from 1) of + * the dropped examples. + */ + @JsonProperty("truncatedExampleIndices") + public abstract Builder truncatedExampleIndices(List truncatedExampleIndices); + + /** + * Setter for truncatedExampleIndices. + * + *

truncatedExampleIndices: Output only. A partial sample of the indices (starting from 1) of + * the dropped examples. + */ + public Builder truncatedExampleIndices(Long... truncatedExampleIndices) { + return truncatedExampleIndices(Arrays.asList(truncatedExampleIndices)); + } + + /** + * Setter for tuningDatasetExampleCount. + * + *

tuningDatasetExampleCount: Output only. Number of examples in the tuning dataset. + */ + @JsonProperty("tuningDatasetExampleCount") + public abstract Builder tuningDatasetExampleCount(Long tuningDatasetExampleCount); + + /** + * Setter for tuningStepCount. + * + *

tuningStepCount: Output only. Number of tuning steps for this Tuning Job. + */ + @JsonProperty("tuningStepCount") + public abstract Builder tuningStepCount(Long tuningStepCount); + + /** + * Setter for userDatasetExamples. + * + *

userDatasetExamples: Output only. Sample user messages in the training dataset uri. + */ + @JsonProperty("userDatasetExamples") + public abstract Builder userDatasetExamples(List userDatasetExamples); + + /** + * Setter for userDatasetExamples. + * + *

userDatasetExamples: Output only. Sample user messages in the training dataset uri. + */ + public Builder userDatasetExamples(Content... userDatasetExamples) { + return userDatasetExamples(Arrays.asList(userDatasetExamples)); + } + + /** + * Setter for userDatasetExamples builder. + * + *

userDatasetExamples: Output only. Sample user messages in the training dataset uri. + */ + public Builder userDatasetExamples(Content.Builder... userDatasetExamplesBuilders) { + return userDatasetExamples( + Arrays.asList(userDatasetExamplesBuilders).stream() + .map(Content.Builder::build) + .collect(toImmutableList())); + } + + /** + * Setter for userInputTokenDistribution. + * + *

userInputTokenDistribution: Output only. Dataset distributions for the user input tokens. + */ + @JsonProperty("userInputTokenDistribution") + public abstract Builder userInputTokenDistribution( + SupervisedTuningDatasetDistribution userInputTokenDistribution); + + /** + * Setter for userInputTokenDistribution builder. + * + *

userInputTokenDistribution: Output only. Dataset distributions for the user input tokens. + */ + public Builder userInputTokenDistribution( + SupervisedTuningDatasetDistribution.Builder userInputTokenDistributionBuilder) { + return userInputTokenDistribution(userInputTokenDistributionBuilder.build()); + } + + /** + * Setter for userMessagePerExampleDistribution. + * + *

userMessagePerExampleDistribution: Output only. Dataset distributions for the messages per + * example. + */ + @JsonProperty("userMessagePerExampleDistribution") + public abstract Builder userMessagePerExampleDistribution( + SupervisedTuningDatasetDistribution userMessagePerExampleDistribution); + + /** + * Setter for userMessagePerExampleDistribution builder. + * + *

userMessagePerExampleDistribution: Output only. Dataset distributions for the messages per + * example. + */ + public Builder userMessagePerExampleDistribution( + SupervisedTuningDatasetDistribution.Builder userMessagePerExampleDistributionBuilder) { + return userMessagePerExampleDistribution(userMessagePerExampleDistributionBuilder.build()); + } + + /** + * Setter for userOutputTokenDistribution. + * + *

userOutputTokenDistribution: Output only. Dataset distributions for the user output + * tokens. + */ + @JsonProperty("userOutputTokenDistribution") + public abstract Builder userOutputTokenDistribution( + SupervisedTuningDatasetDistribution userOutputTokenDistribution); + + /** + * Setter for userOutputTokenDistribution builder. + * + *

userOutputTokenDistribution: Output only. Dataset distributions for the user output + * tokens. + */ + public Builder userOutputTokenDistribution( + SupervisedTuningDatasetDistribution.Builder userOutputTokenDistributionBuilder) { + return userOutputTokenDistribution(userOutputTokenDistributionBuilder.build()); + } + + public abstract SupervisedTuningDataStats build(); + } + + /** Deserializes a JSON string to a SupervisedTuningDataStats object. */ + public static SupervisedTuningDataStats fromJson(String jsonString) { + return JsonSerializable.fromJsonString(jsonString, SupervisedTuningDataStats.class); + } +} diff --git a/src/main/java/com/google/genai/types/SupervisedTuningDatasetDistribution.java b/src/main/java/com/google/genai/types/SupervisedTuningDatasetDistribution.java new file mode 100644 index 00000000000..89702f52955 --- /dev/null +++ b/src/main/java/com/google/genai/types/SupervisedTuningDatasetDistribution.java @@ -0,0 +1,193 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Auto-generated code. Do not edit. + +package com.google.genai.types; + +import static com.google.common.collect.ImmutableList.toImmutableList; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.google.auto.value.AutoValue; +import com.google.genai.JsonSerializable; +import java.util.Arrays; +import java.util.List; +import java.util.Optional; + +/** Dataset distribution for Supervised Tuning. */ +@AutoValue +@JsonDeserialize(builder = SupervisedTuningDatasetDistribution.Builder.class) +public abstract class SupervisedTuningDatasetDistribution extends JsonSerializable { + /** Output only. Sum of a given population of values that are billable. */ + @JsonProperty("billableSum") + public abstract Optional billableSum(); + + /** Output only. Defines the histogram bucket. */ + @JsonProperty("buckets") + public abstract Optional> buckets(); + + /** Output only. The maximum of the population values. */ + @JsonProperty("max") + public abstract Optional max(); + + /** Output only. The arithmetic mean of the values in the population. */ + @JsonProperty("mean") + public abstract Optional mean(); + + /** Output only. The median of the values in the population. */ + @JsonProperty("median") + public abstract Optional median(); + + /** Output only. The minimum of the population values. */ + @JsonProperty("min") + public abstract Optional min(); + + /** Output only. The 5th percentile of the values in the population. */ + @JsonProperty("p5") + public abstract Optional p5(); + + /** Output only. The 95th percentile of the values in the population. */ + @JsonProperty("p95") + public abstract Optional p95(); + + /** Output only. Sum of a given population of values. */ + @JsonProperty("sum") + public abstract Optional sum(); + + /** Instantiates a builder for SupervisedTuningDatasetDistribution. */ + public static Builder builder() { + return new AutoValue_SupervisedTuningDatasetDistribution.Builder(); + } + + /** Creates a builder with the same values as this instance. */ + public abstract Builder toBuilder(); + + /** Builder for SupervisedTuningDatasetDistribution. */ + @AutoValue.Builder + public abstract static class Builder { + /** + * For internal usage. Please use `SupervisedTuningDatasetDistribution.builder()` for + * instantiation. + */ + @JsonCreator + private static Builder create() { + return new AutoValue_SupervisedTuningDatasetDistribution.Builder(); + } + + /** + * Setter for billableSum. + * + *

billableSum: Output only. Sum of a given population of values that are billable. + */ + @JsonProperty("billableSum") + public abstract Builder billableSum(Long billableSum); + + /** + * Setter for buckets. + * + *

buckets: Output only. Defines the histogram bucket. + */ + @JsonProperty("buckets") + public abstract Builder buckets(List buckets); + + /** + * Setter for buckets. + * + *

buckets: Output only. Defines the histogram bucket. + */ + public Builder buckets(SupervisedTuningDatasetDistributionDatasetBucket... buckets) { + return buckets(Arrays.asList(buckets)); + } + + /** + * Setter for buckets builder. + * + *

buckets: Output only. Defines the histogram bucket. + */ + public Builder buckets( + SupervisedTuningDatasetDistributionDatasetBucket.Builder... bucketsBuilders) { + return buckets( + Arrays.asList(bucketsBuilders).stream() + .map(SupervisedTuningDatasetDistributionDatasetBucket.Builder::build) + .collect(toImmutableList())); + } + + /** + * Setter for max. + * + *

max: Output only. The maximum of the population values. + */ + @JsonProperty("max") + public abstract Builder max(Double max); + + /** + * Setter for mean. + * + *

mean: Output only. The arithmetic mean of the values in the population. + */ + @JsonProperty("mean") + public abstract Builder mean(Double mean); + + /** + * Setter for median. + * + *

median: Output only. The median of the values in the population. + */ + @JsonProperty("median") + public abstract Builder median(Double median); + + /** + * Setter for min. + * + *

min: Output only. The minimum of the population values. + */ + @JsonProperty("min") + public abstract Builder min(Double min); + + /** + * Setter for p5. + * + *

p5: Output only. The 5th percentile of the values in the population. + */ + @JsonProperty("p5") + public abstract Builder p5(Double p5); + + /** + * Setter for p95. + * + *

p95: Output only. The 95th percentile of the values in the population. + */ + @JsonProperty("p95") + public abstract Builder p95(Double p95); + + /** + * Setter for sum. + * + *

sum: Output only. Sum of a given population of values. + */ + @JsonProperty("sum") + public abstract Builder sum(Long sum); + + public abstract SupervisedTuningDatasetDistribution build(); + } + + /** Deserializes a JSON string to a SupervisedTuningDatasetDistribution object. */ + public static SupervisedTuningDatasetDistribution fromJson(String jsonString) { + return JsonSerializable.fromJsonString(jsonString, SupervisedTuningDatasetDistribution.class); + } +} diff --git a/src/main/java/com/google/genai/types/SupervisedTuningDatasetDistributionDatasetBucket.java b/src/main/java/com/google/genai/types/SupervisedTuningDatasetDistributionDatasetBucket.java new file mode 100644 index 00000000000..a12f8e23a01 --- /dev/null +++ b/src/main/java/com/google/genai/types/SupervisedTuningDatasetDistributionDatasetBucket.java @@ -0,0 +1,96 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Auto-generated code. Do not edit. + +package com.google.genai.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.google.auto.value.AutoValue; +import com.google.genai.JsonSerializable; +import java.util.Optional; + +/** Dataset bucket used to create a histogram for the distribution given a population of values. */ +@AutoValue +@JsonDeserialize(builder = SupervisedTuningDatasetDistributionDatasetBucket.Builder.class) +public abstract class SupervisedTuningDatasetDistributionDatasetBucket extends JsonSerializable { + /** Output only. Number of values in the bucket. */ + @JsonProperty("count") + public abstract Optional count(); + + /** Output only. Left bound of the bucket. */ + @JsonProperty("left") + public abstract Optional left(); + + /** Output only. Right bound of the bucket. */ + @JsonProperty("right") + public abstract Optional right(); + + /** Instantiates a builder for SupervisedTuningDatasetDistributionDatasetBucket. */ + public static Builder builder() { + return new AutoValue_SupervisedTuningDatasetDistributionDatasetBucket.Builder(); + } + + /** Creates a builder with the same values as this instance. */ + public abstract Builder toBuilder(); + + /** Builder for SupervisedTuningDatasetDistributionDatasetBucket. */ + @AutoValue.Builder + public abstract static class Builder { + /** + * For internal usage. Please use `SupervisedTuningDatasetDistributionDatasetBucket.builder()` + * for instantiation. + */ + @JsonCreator + private static Builder create() { + return new AutoValue_SupervisedTuningDatasetDistributionDatasetBucket.Builder(); + } + + /** + * Setter for count. + * + *

count: Output only. Number of values in the bucket. + */ + @JsonProperty("count") + public abstract Builder count(Double count); + + /** + * Setter for left. + * + *

left: Output only. Left bound of the bucket. + */ + @JsonProperty("left") + public abstract Builder left(Double left); + + /** + * Setter for right. + * + *

right: Output only. Right bound of the bucket. + */ + @JsonProperty("right") + public abstract Builder right(Double right); + + public abstract SupervisedTuningDatasetDistributionDatasetBucket build(); + } + + /** Deserializes a JSON string to a SupervisedTuningDatasetDistributionDatasetBucket object. */ + public static SupervisedTuningDatasetDistributionDatasetBucket fromJson(String jsonString) { + return JsonSerializable.fromJsonString( + jsonString, SupervisedTuningDatasetDistributionDatasetBucket.class); + } +} diff --git a/src/main/java/com/google/genai/types/SupervisedTuningSpec.java b/src/main/java/com/google/genai/types/SupervisedTuningSpec.java new file mode 100644 index 00000000000..5ddf6550fc8 --- /dev/null +++ b/src/main/java/com/google/genai/types/SupervisedTuningSpec.java @@ -0,0 +1,128 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Auto-generated code. Do not edit. + +package com.google.genai.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.google.auto.value.AutoValue; +import com.google.genai.JsonSerializable; +import java.util.Optional; + +/** Tuning Spec for Supervised Tuning for first party models. */ +@AutoValue +@JsonDeserialize(builder = SupervisedTuningSpec.Builder.class) +public abstract class SupervisedTuningSpec extends JsonSerializable { + /** + * Optional. If set to true, disable intermediate checkpoints for SFT and only the last checkpoint + * will be exported. Otherwise, enable intermediate checkpoints for SFT. Default is false. + */ + @JsonProperty("exportLastCheckpointOnly") + public abstract Optional exportLastCheckpointOnly(); + + /** Optional. Hyperparameters for SFT. */ + @JsonProperty("hyperParameters") + public abstract Optional hyperParameters(); + + /** + * Required. Training dataset used for tuning. The dataset can be specified as either a Cloud + * Storage path to a JSONL file or as the resource name of a Vertex Multimodal Dataset. + */ + @JsonProperty("trainingDatasetUri") + public abstract Optional trainingDatasetUri(); + + /** + * Optional. Validation dataset used for tuning. The dataset can be specified as either a Cloud + * Storage path to a JSONL file or as the resource name of a Vertex Multimodal Dataset. + */ + @JsonProperty("validationDatasetUri") + public abstract Optional validationDatasetUri(); + + /** Instantiates a builder for SupervisedTuningSpec. */ + public static Builder builder() { + return new AutoValue_SupervisedTuningSpec.Builder(); + } + + /** Creates a builder with the same values as this instance. */ + public abstract Builder toBuilder(); + + /** Builder for SupervisedTuningSpec. */ + @AutoValue.Builder + public abstract static class Builder { + /** For internal usage. Please use `SupervisedTuningSpec.builder()` for instantiation. */ + @JsonCreator + private static Builder create() { + return new AutoValue_SupervisedTuningSpec.Builder(); + } + + /** + * Setter for exportLastCheckpointOnly. + * + *

exportLastCheckpointOnly: Optional. If set to true, disable intermediate checkpoints for + * SFT and only the last checkpoint will be exported. Otherwise, enable intermediate checkpoints + * for SFT. Default is false. + */ + @JsonProperty("exportLastCheckpointOnly") + public abstract Builder exportLastCheckpointOnly(boolean exportLastCheckpointOnly); + + /** + * Setter for hyperParameters. + * + *

hyperParameters: Optional. Hyperparameters for SFT. + */ + @JsonProperty("hyperParameters") + public abstract Builder hyperParameters(SupervisedHyperParameters hyperParameters); + + /** + * Setter for hyperParameters builder. + * + *

hyperParameters: Optional. Hyperparameters for SFT. + */ + public Builder hyperParameters(SupervisedHyperParameters.Builder hyperParametersBuilder) { + return hyperParameters(hyperParametersBuilder.build()); + } + + /** + * Setter for trainingDatasetUri. + * + *

trainingDatasetUri: Required. Training dataset used for tuning. The dataset can be + * specified as either a Cloud Storage path to a JSONL file or as the resource name of a Vertex + * Multimodal Dataset. + */ + @JsonProperty("trainingDatasetUri") + public abstract Builder trainingDatasetUri(String trainingDatasetUri); + + /** + * Setter for validationDatasetUri. + * + *

validationDatasetUri: Optional. Validation dataset used for tuning. The dataset can be + * specified as either a Cloud Storage path to a JSONL file or as the resource name of a Vertex + * Multimodal Dataset. + */ + @JsonProperty("validationDatasetUri") + public abstract Builder validationDatasetUri(String validationDatasetUri); + + public abstract SupervisedTuningSpec build(); + } + + /** Deserializes a JSON string to a SupervisedTuningSpec object. */ + public static SupervisedTuningSpec fromJson(String jsonString) { + return JsonSerializable.fromJsonString(jsonString, SupervisedTuningSpec.class); + } +} diff --git a/src/main/java/com/google/genai/types/TunedModel.java b/src/main/java/com/google/genai/types/TunedModel.java new file mode 100644 index 00000000000..605fe5e6760 --- /dev/null +++ b/src/main/java/com/google/genai/types/TunedModel.java @@ -0,0 +1,131 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Auto-generated code. Do not edit. + +package com.google.genai.types; + +import static com.google.common.collect.ImmutableList.toImmutableList; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.google.auto.value.AutoValue; +import com.google.genai.JsonSerializable; +import java.util.Arrays; +import java.util.List; +import java.util.Optional; + +/** None */ +@AutoValue +@JsonDeserialize(builder = TunedModel.Builder.class) +public abstract class TunedModel extends JsonSerializable { + /** + * Output only. The resource name of the TunedModel. Format: + * `projects/{project}/locations/{location}/models/{model}`. + */ + @JsonProperty("model") + public abstract Optional model(); + + /** + * Output only. A resource name of an Endpoint. Format: + * `projects/{project}/locations/{location}/endpoints/{endpoint}`. + */ + @JsonProperty("endpoint") + public abstract Optional endpoint(); + + /** + * The checkpoints associated with this TunedModel. This field is only populated for tuning jobs + * that enable intermediate checkpoints. + */ + @JsonProperty("checkpoints") + public abstract Optional> checkpoints(); + + /** Instantiates a builder for TunedModel. */ + public static Builder builder() { + return new AutoValue_TunedModel.Builder(); + } + + /** Creates a builder with the same values as this instance. */ + public abstract Builder toBuilder(); + + /** Builder for TunedModel. */ + @AutoValue.Builder + public abstract static class Builder { + /** For internal usage. Please use `TunedModel.builder()` for instantiation. */ + @JsonCreator + private static Builder create() { + return new AutoValue_TunedModel.Builder(); + } + + /** + * Setter for model. + * + *

model: Output only. The resource name of the TunedModel. Format: + * `projects/{project}/locations/{location}/models/{model}`. + */ + @JsonProperty("model") + public abstract Builder model(String model); + + /** + * Setter for endpoint. + * + *

endpoint: Output only. A resource name of an Endpoint. Format: + * `projects/{project}/locations/{location}/endpoints/{endpoint}`. + */ + @JsonProperty("endpoint") + public abstract Builder endpoint(String endpoint); + + /** + * Setter for checkpoints. + * + *

checkpoints: The checkpoints associated with this TunedModel. This field is only populated + * for tuning jobs that enable intermediate checkpoints. + */ + @JsonProperty("checkpoints") + public abstract Builder checkpoints(List checkpoints); + + /** + * Setter for checkpoints. + * + *

checkpoints: The checkpoints associated with this TunedModel. This field is only populated + * for tuning jobs that enable intermediate checkpoints. + */ + public Builder checkpoints(TunedModelCheckpoint... checkpoints) { + return checkpoints(Arrays.asList(checkpoints)); + } + + /** + * Setter for checkpoints builder. + * + *

checkpoints: The checkpoints associated with this TunedModel. This field is only populated + * for tuning jobs that enable intermediate checkpoints. + */ + public Builder checkpoints(TunedModelCheckpoint.Builder... checkpointsBuilders) { + return checkpoints( + Arrays.asList(checkpointsBuilders).stream() + .map(TunedModelCheckpoint.Builder::build) + .collect(toImmutableList())); + } + + public abstract TunedModel build(); + } + + /** Deserializes a JSON string to a TunedModel object. */ + public static TunedModel fromJson(String jsonString) { + return JsonSerializable.fromJsonString(jsonString, TunedModel.class); + } +} diff --git a/src/main/java/com/google/genai/types/TunedModelCheckpoint.java b/src/main/java/com/google/genai/types/TunedModelCheckpoint.java new file mode 100644 index 00000000000..bdacc9a9090 --- /dev/null +++ b/src/main/java/com/google/genai/types/TunedModelCheckpoint.java @@ -0,0 +1,108 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Auto-generated code. Do not edit. + +package com.google.genai.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.google.auto.value.AutoValue; +import com.google.genai.JsonSerializable; +import java.util.Optional; + +/** TunedModelCheckpoint for the Tuned Model of a Tuning Job. */ +@AutoValue +@JsonDeserialize(builder = TunedModelCheckpoint.Builder.class) +public abstract class TunedModelCheckpoint extends JsonSerializable { + /** The ID of the checkpoint. */ + @JsonProperty("checkpointId") + public abstract Optional checkpointId(); + + /** The epoch of the checkpoint. */ + @JsonProperty("epoch") + public abstract Optional epoch(); + + /** The step of the checkpoint. */ + @JsonProperty("step") + public abstract Optional step(); + + /** + * The Endpoint resource name that the checkpoint is deployed to. Format: + * `projects/{project}/locations/{location}/endpoints/{endpoint}`. + */ + @JsonProperty("endpoint") + public abstract Optional endpoint(); + + /** Instantiates a builder for TunedModelCheckpoint. */ + public static Builder builder() { + return new AutoValue_TunedModelCheckpoint.Builder(); + } + + /** Creates a builder with the same values as this instance. */ + public abstract Builder toBuilder(); + + /** Builder for TunedModelCheckpoint. */ + @AutoValue.Builder + public abstract static class Builder { + /** For internal usage. Please use `TunedModelCheckpoint.builder()` for instantiation. */ + @JsonCreator + private static Builder create() { + return new AutoValue_TunedModelCheckpoint.Builder(); + } + + /** + * Setter for checkpointId. + * + *

checkpointId: The ID of the checkpoint. + */ + @JsonProperty("checkpointId") + public abstract Builder checkpointId(String checkpointId); + + /** + * Setter for epoch. + * + *

epoch: The epoch of the checkpoint. + */ + @JsonProperty("epoch") + public abstract Builder epoch(Long epoch); + + /** + * Setter for step. + * + *

step: The step of the checkpoint. + */ + @JsonProperty("step") + public abstract Builder step(Long step); + + /** + * Setter for endpoint. + * + *

endpoint: The Endpoint resource name that the checkpoint is deployed to. Format: + * `projects/{project}/locations/{location}/endpoints/{endpoint}`. + */ + @JsonProperty("endpoint") + public abstract Builder endpoint(String endpoint); + + public abstract TunedModelCheckpoint build(); + } + + /** Deserializes a JSON string to a TunedModelCheckpoint object. */ + public static TunedModelCheckpoint fromJson(String jsonString) { + return JsonSerializable.fromJsonString(jsonString, TunedModelCheckpoint.class); + } +} diff --git a/src/main/java/com/google/genai/types/TuningDataStats.java b/src/main/java/com/google/genai/types/TuningDataStats.java new file mode 100644 index 00000000000..32e3111bd88 --- /dev/null +++ b/src/main/java/com/google/genai/types/TuningDataStats.java @@ -0,0 +1,101 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Auto-generated code. Do not edit. + +package com.google.genai.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.google.auto.value.AutoValue; +import com.google.genai.JsonSerializable; +import java.util.Optional; + +/** The tuning data statistic values for TuningJob. */ +@AutoValue +@JsonDeserialize(builder = TuningDataStats.Builder.class) +public abstract class TuningDataStats extends JsonSerializable { + /** Output only. Statistics for distillation. */ + @JsonProperty("distillationDataStats") + public abstract Optional distillationDataStats(); + + /** The SFT Tuning data stats. */ + @JsonProperty("supervisedTuningDataStats") + public abstract Optional supervisedTuningDataStats(); + + /** Instantiates a builder for TuningDataStats. */ + public static Builder builder() { + return new AutoValue_TuningDataStats.Builder(); + } + + /** Creates a builder with the same values as this instance. */ + public abstract Builder toBuilder(); + + /** Builder for TuningDataStats. */ + @AutoValue.Builder + public abstract static class Builder { + /** For internal usage. Please use `TuningDataStats.builder()` for instantiation. */ + @JsonCreator + private static Builder create() { + return new AutoValue_TuningDataStats.Builder(); + } + + /** + * Setter for distillationDataStats. + * + *

distillationDataStats: Output only. Statistics for distillation. + */ + @JsonProperty("distillationDataStats") + public abstract Builder distillationDataStats(DistillationDataStats distillationDataStats); + + /** + * Setter for distillationDataStats builder. + * + *

distillationDataStats: Output only. Statistics for distillation. + */ + public Builder distillationDataStats( + DistillationDataStats.Builder distillationDataStatsBuilder) { + return distillationDataStats(distillationDataStatsBuilder.build()); + } + + /** + * Setter for supervisedTuningDataStats. + * + *

supervisedTuningDataStats: The SFT Tuning data stats. + */ + @JsonProperty("supervisedTuningDataStats") + public abstract Builder supervisedTuningDataStats( + SupervisedTuningDataStats supervisedTuningDataStats); + + /** + * Setter for supervisedTuningDataStats builder. + * + *

supervisedTuningDataStats: The SFT Tuning data stats. + */ + public Builder supervisedTuningDataStats( + SupervisedTuningDataStats.Builder supervisedTuningDataStatsBuilder) { + return supervisedTuningDataStats(supervisedTuningDataStatsBuilder.build()); + } + + public abstract TuningDataStats build(); + } + + /** Deserializes a JSON string to a TuningDataStats object. */ + public static TuningDataStats fromJson(String jsonString) { + return JsonSerializable.fromJsonString(jsonString, TuningDataStats.class); + } +} diff --git a/src/main/java/com/google/genai/types/TuningDataset.java b/src/main/java/com/google/genai/types/TuningDataset.java new file mode 100644 index 00000000000..2af07425ddd --- /dev/null +++ b/src/main/java/com/google/genai/types/TuningDataset.java @@ -0,0 +1,122 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Auto-generated code. Do not edit. + +package com.google.genai.types; + +import static com.google.common.collect.ImmutableList.toImmutableList; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.google.auto.value.AutoValue; +import com.google.genai.JsonSerializable; +import java.util.Arrays; +import java.util.List; +import java.util.Optional; + +/** Supervised fine-tuning training dataset. */ +@AutoValue +@JsonDeserialize(builder = TuningDataset.Builder.class) +public abstract class TuningDataset extends JsonSerializable { + /** GCS URI of the file containing training dataset in JSONL format. */ + @JsonProperty("gcsUri") + public abstract Optional gcsUri(); + + /** + * The resource name of the Vertex Multimodal Dataset that is used as training dataset. Example: + * 'projects/my-project-id-or-number/locations/my-location/datasets/my-dataset-id'. + */ + @JsonProperty("vertexDatasetResource") + public abstract Optional vertexDatasetResource(); + + /** Inline examples with simple input/output text. */ + @JsonProperty("examples") + public abstract Optional> examples(); + + /** Instantiates a builder for TuningDataset. */ + public static Builder builder() { + return new AutoValue_TuningDataset.Builder(); + } + + /** Creates a builder with the same values as this instance. */ + public abstract Builder toBuilder(); + + /** Builder for TuningDataset. */ + @AutoValue.Builder + public abstract static class Builder { + /** For internal usage. Please use `TuningDataset.builder()` for instantiation. */ + @JsonCreator + private static Builder create() { + return new AutoValue_TuningDataset.Builder(); + } + + /** + * Setter for gcsUri. + * + *

gcsUri: GCS URI of the file containing training dataset in JSONL format. + */ + @JsonProperty("gcsUri") + public abstract Builder gcsUri(String gcsUri); + + /** + * Setter for vertexDatasetResource. + * + *

vertexDatasetResource: The resource name of the Vertex Multimodal Dataset that is used as + * training dataset. Example: + * 'projects/my-project-id-or-number/locations/my-location/datasets/my-dataset-id'. + */ + @JsonProperty("vertexDatasetResource") + public abstract Builder vertexDatasetResource(String vertexDatasetResource); + + /** + * Setter for examples. + * + *

examples: Inline examples with simple input/output text. + */ + @JsonProperty("examples") + public abstract Builder examples(List examples); + + /** + * Setter for examples. + * + *

examples: Inline examples with simple input/output text. + */ + public Builder examples(TuningExample... examples) { + return examples(Arrays.asList(examples)); + } + + /** + * Setter for examples builder. + * + *

examples: Inline examples with simple input/output text. + */ + public Builder examples(TuningExample.Builder... examplesBuilders) { + return examples( + Arrays.asList(examplesBuilders).stream() + .map(TuningExample.Builder::build) + .collect(toImmutableList())); + } + + public abstract TuningDataset build(); + } + + /** Deserializes a JSON string to a TuningDataset object. */ + public static TuningDataset fromJson(String jsonString) { + return JsonSerializable.fromJsonString(jsonString, TuningDataset.class); + } +} diff --git a/src/main/java/com/google/genai/types/TuningExample.java b/src/main/java/com/google/genai/types/TuningExample.java new file mode 100644 index 00000000000..c4b5265f0e2 --- /dev/null +++ b/src/main/java/com/google/genai/types/TuningExample.java @@ -0,0 +1,80 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Auto-generated code. Do not edit. + +package com.google.genai.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.google.auto.value.AutoValue; +import com.google.genai.JsonSerializable; +import java.util.Optional; + +/** None */ +@AutoValue +@JsonDeserialize(builder = TuningExample.Builder.class) +public abstract class TuningExample extends JsonSerializable { + /** Text model input. */ + @JsonProperty("textInput") + public abstract Optional textInput(); + + /** The expected model output. */ + @JsonProperty("output") + public abstract Optional output(); + + /** Instantiates a builder for TuningExample. */ + public static Builder builder() { + return new AutoValue_TuningExample.Builder(); + } + + /** Creates a builder with the same values as this instance. */ + public abstract Builder toBuilder(); + + /** Builder for TuningExample. */ + @AutoValue.Builder + public abstract static class Builder { + /** For internal usage. Please use `TuningExample.builder()` for instantiation. */ + @JsonCreator + private static Builder create() { + return new AutoValue_TuningExample.Builder(); + } + + /** + * Setter for textInput. + * + *

textInput: Text model input. + */ + @JsonProperty("textInput") + public abstract Builder textInput(String textInput); + + /** + * Setter for output. + * + *

output: The expected model output. + */ + @JsonProperty("output") + public abstract Builder output(String output); + + public abstract TuningExample build(); + } + + /** Deserializes a JSON string to a TuningExample object. */ + public static TuningExample fromJson(String jsonString) { + return JsonSerializable.fromJsonString(jsonString, TuningExample.class); + } +} diff --git a/src/main/java/com/google/genai/types/TuningJob.java b/src/main/java/com/google/genai/types/TuningJob.java new file mode 100644 index 00000000000..5a3668fb8bd --- /dev/null +++ b/src/main/java/com/google/genai/types/TuningJob.java @@ -0,0 +1,461 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Auto-generated code. Do not edit. + +package com.google.genai.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.google.auto.value.AutoValue; +import com.google.errorprone.annotations.CanIgnoreReturnValue; +import com.google.genai.JsonSerializable; +import java.time.Instant; +import java.util.Map; +import java.util.Optional; + +/** A tuning job. */ +@AutoValue +@JsonDeserialize(builder = TuningJob.Builder.class) +public abstract class TuningJob extends JsonSerializable { + /** + * Output only. Identifier. Resource name of a TuningJob. Format: + * `projects/{project}/locations/{location}/tuningJobs/{tuning_job}` + */ + @JsonProperty("name") + public abstract Optional name(); + + /** Output only. The detailed state of the job. */ + @JsonProperty("state") + public abstract Optional state(); + + /** Output only. Time when the TuningJob was created. */ + @JsonProperty("createTime") + public abstract Optional createTime(); + + /** + * Output only. Time when the TuningJob for the first time entered the `JOB_STATE_RUNNING` state. + */ + @JsonProperty("startTime") + public abstract Optional startTime(); + + /** + * Output only. Time when the TuningJob entered any of the following JobStates: + * `JOB_STATE_SUCCEEDED`, `JOB_STATE_FAILED`, `JOB_STATE_CANCELLED`, `JOB_STATE_EXPIRED`. + */ + @JsonProperty("endTime") + public abstract Optional endTime(); + + /** Output only. Time when the TuningJob was most recently updated. */ + @JsonProperty("updateTime") + public abstract Optional updateTime(); + + /** + * Output only. Only populated when job's state is `JOB_STATE_FAILED` or `JOB_STATE_CANCELLED`. + */ + @JsonProperty("error") + public abstract Optional error(); + + /** Optional. The description of the TuningJob. */ + @JsonProperty("description") + public abstract Optional description(); + + /** + * The base model that is being tuned. See [Supported + * models](https://cloud.google.com/vertex-ai/generative-ai/docs/model-reference/tuning#supported_models). + */ + @JsonProperty("baseModel") + public abstract Optional baseModel(); + + /** Output only. The tuned model resources associated with this TuningJob. */ + @JsonProperty("tunedModel") + public abstract Optional tunedModel(); + + /** Tuning Spec for Supervised Fine Tuning. */ + @JsonProperty("supervisedTuningSpec") + public abstract Optional supervisedTuningSpec(); + + /** Output only. The tuning data statistics associated with this TuningJob. */ + @JsonProperty("tuningDataStats") + public abstract Optional tuningDataStats(); + + /** + * Customer-managed encryption key options for a TuningJob. If this is set, then all resources + * created by the TuningJob will be encrypted with the provided encryption key. + */ + @JsonProperty("encryptionSpec") + public abstract Optional encryptionSpec(); + + /** Tuning Spec for open sourced and third party Partner models. */ + @JsonProperty("partnerModelTuningSpec") + public abstract Optional partnerModelTuningSpec(); + + /** Tuning Spec for Distillation. */ + @JsonProperty("distillationSpec") + public abstract Optional distillationSpec(); + + /** Output only. The Experiment associated with this TuningJob. */ + @JsonProperty("experiment") + public abstract Optional experiment(); + + /** + * Optional. The labels with user-defined metadata to organize TuningJob and generated resources + * such as Model and Endpoint. Label keys and values can be no longer than 64 characters (Unicode + * codepoints), can only contain lowercase letters, numeric characters, underscores and dashes. + * International characters are allowed. See https://goo.gl/xmQnxf for more information and + * examples of labels. + */ + @JsonProperty("labels") + public abstract Optional> labels(); + + /** + * Output only. The resource name of the PipelineJob associated with the TuningJob. Format: + * `projects/{project}/locations/{location}/pipelineJobs/{pipeline_job}`. + */ + @JsonProperty("pipelineJob") + public abstract Optional pipelineJob(); + + /** Output only. Reserved for future use. */ + @JsonProperty("satisfiesPzi") + public abstract Optional satisfiesPzi(); + + /** Output only. Reserved for future use. */ + @JsonProperty("satisfiesPzs") + public abstract Optional satisfiesPzs(); + + /** + * The service account that the tuningJob workload runs as. If not specified, the Vertex AI Secure + * Fine-Tuned Service Agent in the project will be used. See + * https://cloud.google.com/iam/docs/service-agents#vertex-ai-secure-fine-tuning-service-agent + * Users starting the pipeline must have the `iam.serviceAccounts.actAs` permission on this + * service account. + */ + @JsonProperty("serviceAccount") + public abstract Optional serviceAccount(); + + /** + * Optional. The display name of the TunedModel. The name can be up to 128 characters long and can + * consist of any UTF-8 characters. + */ + @JsonProperty("tunedModelDisplayName") + public abstract Optional tunedModelDisplayName(); + + /** Instantiates a builder for TuningJob. */ + public static Builder builder() { + return new AutoValue_TuningJob.Builder(); + } + + /** Creates a builder with the same values as this instance. */ + public abstract Builder toBuilder(); + + /** Builder for TuningJob. */ + @AutoValue.Builder + public abstract static class Builder { + /** For internal usage. Please use `TuningJob.builder()` for instantiation. */ + @JsonCreator + private static Builder create() { + return new AutoValue_TuningJob.Builder(); + } + + /** + * Setter for name. + * + *

name: Output only. Identifier. Resource name of a TuningJob. Format: + * `projects/{project}/locations/{location}/tuningJobs/{tuning_job}` + */ + @JsonProperty("name") + public abstract Builder name(String name); + + /** + * Setter for state. + * + *

state: Output only. The detailed state of the job. + */ + @JsonProperty("state") + public abstract Builder state(JobState state); + + /** + * Setter for state given a known enum. + * + *

state: Output only. The detailed state of the job. + */ + @CanIgnoreReturnValue + public Builder state(JobState.Known knownType) { + return state(new JobState(knownType)); + } + + /** + * Setter for state given a string. + * + *

state: Output only. The detailed state of the job. + */ + @CanIgnoreReturnValue + public Builder state(String state) { + return state(new JobState(state)); + } + + /** + * Setter for createTime. + * + *

createTime: Output only. Time when the TuningJob was created. + */ + @JsonProperty("createTime") + public abstract Builder createTime(Instant createTime); + + /** + * Setter for startTime. + * + *

startTime: Output only. Time when the TuningJob for the first time entered the + * `JOB_STATE_RUNNING` state. + */ + @JsonProperty("startTime") + public abstract Builder startTime(Instant startTime); + + /** + * Setter for endTime. + * + *

endTime: Output only. Time when the TuningJob entered any of the following JobStates: + * `JOB_STATE_SUCCEEDED`, `JOB_STATE_FAILED`, `JOB_STATE_CANCELLED`, `JOB_STATE_EXPIRED`. + */ + @JsonProperty("endTime") + public abstract Builder endTime(Instant endTime); + + /** + * Setter for updateTime. + * + *

updateTime: Output only. Time when the TuningJob was most recently updated. + */ + @JsonProperty("updateTime") + public abstract Builder updateTime(Instant updateTime); + + /** + * Setter for error. + * + *

error: Output only. Only populated when job's state is `JOB_STATE_FAILED` or + * `JOB_STATE_CANCELLED`. + */ + @JsonProperty("error") + public abstract Builder error(GoogleRpcStatus error); + + /** + * Setter for error builder. + * + *

error: Output only. Only populated when job's state is `JOB_STATE_FAILED` or + * `JOB_STATE_CANCELLED`. + */ + public Builder error(GoogleRpcStatus.Builder errorBuilder) { + return error(errorBuilder.build()); + } + + /** + * Setter for description. + * + *

description: Optional. The description of the TuningJob. + */ + @JsonProperty("description") + public abstract Builder description(String description); + + /** + * Setter for baseModel. + * + *

baseModel: The base model that is being tuned. See [Supported + * models](https://cloud.google.com/vertex-ai/generative-ai/docs/model-reference/tuning#supported_models). + */ + @JsonProperty("baseModel") + public abstract Builder baseModel(String baseModel); + + /** + * Setter for tunedModel. + * + *

tunedModel: Output only. The tuned model resources associated with this TuningJob. + */ + @JsonProperty("tunedModel") + public abstract Builder tunedModel(TunedModel tunedModel); + + /** + * Setter for tunedModel builder. + * + *

tunedModel: Output only. The tuned model resources associated with this TuningJob. + */ + public Builder tunedModel(TunedModel.Builder tunedModelBuilder) { + return tunedModel(tunedModelBuilder.build()); + } + + /** + * Setter for supervisedTuningSpec. + * + *

supervisedTuningSpec: Tuning Spec for Supervised Fine Tuning. + */ + @JsonProperty("supervisedTuningSpec") + public abstract Builder supervisedTuningSpec(SupervisedTuningSpec supervisedTuningSpec); + + /** + * Setter for supervisedTuningSpec builder. + * + *

supervisedTuningSpec: Tuning Spec for Supervised Fine Tuning. + */ + public Builder supervisedTuningSpec(SupervisedTuningSpec.Builder supervisedTuningSpecBuilder) { + return supervisedTuningSpec(supervisedTuningSpecBuilder.build()); + } + + /** + * Setter for tuningDataStats. + * + *

tuningDataStats: Output only. The tuning data statistics associated with this TuningJob. + */ + @JsonProperty("tuningDataStats") + public abstract Builder tuningDataStats(TuningDataStats tuningDataStats); + + /** + * Setter for tuningDataStats builder. + * + *

tuningDataStats: Output only. The tuning data statistics associated with this TuningJob. + */ + public Builder tuningDataStats(TuningDataStats.Builder tuningDataStatsBuilder) { + return tuningDataStats(tuningDataStatsBuilder.build()); + } + + /** + * Setter for encryptionSpec. + * + *

encryptionSpec: Customer-managed encryption key options for a TuningJob. If this is set, + * then all resources created by the TuningJob will be encrypted with the provided encryption + * key. + */ + @JsonProperty("encryptionSpec") + public abstract Builder encryptionSpec(EncryptionSpec encryptionSpec); + + /** + * Setter for encryptionSpec builder. + * + *

encryptionSpec: Customer-managed encryption key options for a TuningJob. If this is set, + * then all resources created by the TuningJob will be encrypted with the provided encryption + * key. + */ + public Builder encryptionSpec(EncryptionSpec.Builder encryptionSpecBuilder) { + return encryptionSpec(encryptionSpecBuilder.build()); + } + + /** + * Setter for partnerModelTuningSpec. + * + *

partnerModelTuningSpec: Tuning Spec for open sourced and third party Partner models. + */ + @JsonProperty("partnerModelTuningSpec") + public abstract Builder partnerModelTuningSpec(PartnerModelTuningSpec partnerModelTuningSpec); + + /** + * Setter for partnerModelTuningSpec builder. + * + *

partnerModelTuningSpec: Tuning Spec for open sourced and third party Partner models. + */ + public Builder partnerModelTuningSpec( + PartnerModelTuningSpec.Builder partnerModelTuningSpecBuilder) { + return partnerModelTuningSpec(partnerModelTuningSpecBuilder.build()); + } + + /** + * Setter for distillationSpec. + * + *

distillationSpec: Tuning Spec for Distillation. + */ + @JsonProperty("distillationSpec") + public abstract Builder distillationSpec(DistillationSpec distillationSpec); + + /** + * Setter for distillationSpec builder. + * + *

distillationSpec: Tuning Spec for Distillation. + */ + public Builder distillationSpec(DistillationSpec.Builder distillationSpecBuilder) { + return distillationSpec(distillationSpecBuilder.build()); + } + + /** + * Setter for experiment. + * + *

experiment: Output only. The Experiment associated with this TuningJob. + */ + @JsonProperty("experiment") + public abstract Builder experiment(String experiment); + + /** + * Setter for labels. + * + *

labels: Optional. The labels with user-defined metadata to organize TuningJob and + * generated resources such as Model and Endpoint. Label keys and values can be no longer than + * 64 characters (Unicode codepoints), can only contain lowercase letters, numeric characters, + * underscores and dashes. International characters are allowed. See https://goo.gl/xmQnxf for + * more information and examples of labels. + */ + @JsonProperty("labels") + public abstract Builder labels(Map labels); + + /** + * Setter for pipelineJob. + * + *

pipelineJob: Output only. The resource name of the PipelineJob associated with the + * TuningJob. Format: `projects/{project}/locations/{location}/pipelineJobs/{pipeline_job}`. + */ + @JsonProperty("pipelineJob") + public abstract Builder pipelineJob(String pipelineJob); + + /** + * Setter for satisfiesPzi. + * + *

satisfiesPzi: Output only. Reserved for future use. + */ + @JsonProperty("satisfiesPzi") + public abstract Builder satisfiesPzi(boolean satisfiesPzi); + + /** + * Setter for satisfiesPzs. + * + *

satisfiesPzs: Output only. Reserved for future use. + */ + @JsonProperty("satisfiesPzs") + public abstract Builder satisfiesPzs(boolean satisfiesPzs); + + /** + * Setter for serviceAccount. + * + *

serviceAccount: The service account that the tuningJob workload runs as. If not specified, + * the Vertex AI Secure Fine-Tuned Service Agent in the project will be used. See + * https://cloud.google.com/iam/docs/service-agents#vertex-ai-secure-fine-tuning-service-agent + * Users starting the pipeline must have the `iam.serviceAccounts.actAs` permission on this + * service account. + */ + @JsonProperty("serviceAccount") + public abstract Builder serviceAccount(String serviceAccount); + + /** + * Setter for tunedModelDisplayName. + * + *

tunedModelDisplayName: Optional. The display name of the TunedModel. The name can be up to + * 128 characters long and can consist of any UTF-8 characters. + */ + @JsonProperty("tunedModelDisplayName") + public abstract Builder tunedModelDisplayName(String tunedModelDisplayName); + + public abstract TuningJob build(); + } + + /** Deserializes a JSON string to a TuningJob object. */ + public static TuningJob fromJson(String jsonString) { + return JsonSerializable.fromJsonString(jsonString, TuningJob.class); + } +} diff --git a/src/main/java/com/google/genai/types/TuningOperation.java b/src/main/java/com/google/genai/types/TuningOperation.java new file mode 100644 index 00000000000..71dbdcca844 --- /dev/null +++ b/src/main/java/com/google/genai/types/TuningOperation.java @@ -0,0 +1,123 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Auto-generated code. Do not edit. + +package com.google.genai.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.google.auto.value.AutoValue; +import com.google.genai.JsonSerializable; +import java.util.Map; +import java.util.Optional; + +/** A long-running operation. */ +@AutoValue +@JsonDeserialize(builder = TuningOperation.Builder.class) +public abstract class TuningOperation extends JsonSerializable { + /** + * The server-assigned name, which is only unique within the same service that originally returns + * it. If you use the default HTTP mapping, the `name` should be a resource name ending with + * `operations/{unique_id}`. + */ + @JsonProperty("name") + public abstract Optional name(); + + /** + * Service-specific metadata associated with the operation. It typically contains progress + * information and common metadata such as create time. Some services might not provide such + * metadata. Any method that returns a long-running operation should document the metadata type, + * if any. + */ + @JsonProperty("metadata") + public abstract Optional> metadata(); + + /** + * If the value is `false`, it means the operation is still in progress. If `true`, the operation + * is completed, and either `error` or `response` is available. + */ + @JsonProperty("done") + public abstract Optional done(); + + /** The error result of the operation in case of failure or cancellation. */ + @JsonProperty("error") + public abstract Optional> error(); + + /** Instantiates a builder for TuningOperation. */ + public static Builder builder() { + return new AutoValue_TuningOperation.Builder(); + } + + /** Creates a builder with the same values as this instance. */ + public abstract Builder toBuilder(); + + /** Builder for TuningOperation. */ + @AutoValue.Builder + public abstract static class Builder { + /** For internal usage. Please use `TuningOperation.builder()` for instantiation. */ + @JsonCreator + private static Builder create() { + return new AutoValue_TuningOperation.Builder(); + } + + /** + * Setter for name. + * + *

name: The server-assigned name, which is only unique within the same service that + * originally returns it. If you use the default HTTP mapping, the `name` should be a resource + * name ending with `operations/{unique_id}`. + */ + @JsonProperty("name") + public abstract Builder name(String name); + + /** + * Setter for metadata. + * + *

metadata: Service-specific metadata associated with the operation. It typically contains + * progress information and common metadata such as create time. Some services might not provide + * such metadata. Any method that returns a long-running operation should document the metadata + * type, if any. + */ + @JsonProperty("metadata") + public abstract Builder metadata(Map metadata); + + /** + * Setter for done. + * + *

done: If the value is `false`, it means the operation is still in progress. If `true`, the + * operation is completed, and either `error` or `response` is available. + */ + @JsonProperty("done") + public abstract Builder done(boolean done); + + /** + * Setter for error. + * + *

error: The error result of the operation in case of failure or cancellation. + */ + @JsonProperty("error") + public abstract Builder error(Map error); + + public abstract TuningOperation build(); + } + + /** Deserializes a JSON string to a TuningOperation object. */ + public static TuningOperation fromJson(String jsonString) { + return JsonSerializable.fromJsonString(jsonString, TuningOperation.class); + } +} diff --git a/src/main/java/com/google/genai/types/TuningValidationDataset.java b/src/main/java/com/google/genai/types/TuningValidationDataset.java new file mode 100644 index 00000000000..8211756d9e1 --- /dev/null +++ b/src/main/java/com/google/genai/types/TuningValidationDataset.java @@ -0,0 +1,85 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Auto-generated code. Do not edit. + +package com.google.genai.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.google.auto.value.AutoValue; +import com.google.genai.JsonSerializable; +import java.util.Optional; + +/** None */ +@AutoValue +@JsonDeserialize(builder = TuningValidationDataset.Builder.class) +public abstract class TuningValidationDataset extends JsonSerializable { + /** GCS URI of the file containing validation dataset in JSONL format. */ + @JsonProperty("gcsUri") + public abstract Optional gcsUri(); + + /** + * The resource name of the Vertex Multimodal Dataset that is used as training dataset. Example: + * 'projects/my-project-id-or-number/locations/my-location/datasets/my-dataset-id'. + */ + @JsonProperty("vertexDatasetResource") + public abstract Optional vertexDatasetResource(); + + /** Instantiates a builder for TuningValidationDataset. */ + public static Builder builder() { + return new AutoValue_TuningValidationDataset.Builder(); + } + + /** Creates a builder with the same values as this instance. */ + public abstract Builder toBuilder(); + + /** Builder for TuningValidationDataset. */ + @AutoValue.Builder + public abstract static class Builder { + /** For internal usage. Please use `TuningValidationDataset.builder()` for instantiation. */ + @JsonCreator + private static Builder create() { + return new AutoValue_TuningValidationDataset.Builder(); + } + + /** + * Setter for gcsUri. + * + *

gcsUri: GCS URI of the file containing validation dataset in JSONL format. + */ + @JsonProperty("gcsUri") + public abstract Builder gcsUri(String gcsUri); + + /** + * Setter for vertexDatasetResource. + * + *

vertexDatasetResource: The resource name of the Vertex Multimodal Dataset that is used as + * training dataset. Example: + * 'projects/my-project-id-or-number/locations/my-location/datasets/my-dataset-id'. + */ + @JsonProperty("vertexDatasetResource") + public abstract Builder vertexDatasetResource(String vertexDatasetResource); + + public abstract TuningValidationDataset build(); + } + + /** Deserializes a JSON string to a TuningValidationDataset object. */ + public static TuningValidationDataset fromJson(String jsonString) { + return JsonSerializable.fromJsonString(jsonString, TuningValidationDataset.class); + } +} diff --git a/src/test/java/com/google/genai/TableTest.java b/src/test/java/com/google/genai/TableTest.java index 757605dca92..48b144de895 100644 --- a/src/test/java/com/google/genai/TableTest.java +++ b/src/test/java/com/google/genai/TableTest.java @@ -61,6 +61,10 @@ private static Collection createTableTests(String path, boolean ver String originalMethodName = segments[1]; String methodName = Common.snakeToCamel(originalMethodName); + if (methodName.equals("privateTune") && !vertexAI) { + methodName = "privateTuneMldev"; + } + String[] replayPathSegments = path.split("/"); String replayFilePath = ""; for (int i = 0; i < replayPathSegments.length; i++) { @@ -199,7 +203,21 @@ private static Collection createTestCases( Optional exceptionIfMldev = testTableItem.exceptionIfMldev(); Optional exceptionIfVertex = testTableItem.exceptionIfVertex(); if (exceptionIfMldev.isPresent() && !client.vertexAI()) { - if (!e.getCause().getMessage().contains(exceptionIfMldev.get())) { + String exceptionMessage = e.getCause().getMessage(); + + // TODO(fix in future): hack for camelCase variable name mismatch with + // expected snake_case name in exception messages. + String geminiParameterException = + " parameter is not supported in Gemini API."; + if (exceptionMessage.endsWith(geminiParameterException)) { + // camel to snake case the variable name in the exception message. + String camelCaseVariable = exceptionMessage.split(" ")[0]; + String snakeCaseVariable = Transformers.camelToSnake(camelCaseVariable); + exceptionMessage = + exceptionMessage.replace(camelCaseVariable, snakeCaseVariable); + } + + if (!exceptionMessage.contains(exceptionIfMldev.get())) { fail( String.format( "'%s' failed to match expected exception:\n" @@ -208,7 +226,20 @@ private static Collection createTestCases( testName, exceptionIfMldev.get(), e.getCause().getMessage())); } } else if (exceptionIfVertex.isPresent() && client.vertexAI()) { - if (!e.getCause().getMessage().contains(exceptionIfVertex.get())) { + String exceptionMessage = e.getCause().getMessage(); + + // TODO(fix in future): hack for camelCase variable name mismatch with + // expected snake_case name in exception messages. + String vertexParameterException = " parameter is not supported in Vertex AI."; + if (exceptionMessage.endsWith(vertexParameterException)) { + // camel to snake case the variable name in the exception message. + String camelCaseVariable = exceptionMessage.split(" ")[0]; + String snakeCaseVariable = Transformers.camelToSnake(camelCaseVariable); + exceptionMessage = + exceptionMessage.replace(camelCaseVariable, snakeCaseVariable); + } + + if (!exceptionMessage.contains(exceptionIfVertex.get())) { fail( String.format( "'%s' failed to match expected exception:\n" diff --git a/src/test/java/com/google/genai/TransformersTest.java b/src/test/java/com/google/genai/TransformersTest.java index fde14fc8f83..dcad8cf75b9 100644 --- a/src/test/java/com/google/genai/TransformersTest.java +++ b/src/test/java/com/google/genai/TransformersTest.java @@ -30,6 +30,7 @@ import com.google.genai.types.FunctionDeclaration; import com.google.genai.types.GeneratedVideo; import com.google.genai.types.GoogleSearch; +import com.google.genai.types.JobState; import com.google.genai.types.Schema; import com.google.genai.types.Tool; import com.google.genai.types.Video; @@ -414,4 +415,118 @@ public void tExtractModels_responseWithPublisherModels() { assertTrue(models instanceof ArrayNode); assertEquals(1, models.size()); } + + @Test + public void tTuningJobStatus_stringInput() { + assertEquals( + JobState.Known.JOB_STATE_UNSPECIFIED, + Transformers.tTuningJobStatus("STATE_UNSPECIFIED").knownEnum()); + assertEquals( + JobState.Known.JOB_STATE_RUNNING, Transformers.tTuningJobStatus("CREATING").knownEnum()); + assertEquals( + JobState.Known.JOB_STATE_SUCCEEDED, Transformers.tTuningJobStatus("ACTIVE").knownEnum()); + assertEquals( + JobState.Known.JOB_STATE_FAILED, Transformers.tTuningJobStatus("FAILED").knownEnum()); + } + + @Test + public void tTuningJobStatus_textNodeInput() { + assertEquals( + JobState.Known.JOB_STATE_UNSPECIFIED, + Transformers.tTuningJobStatus(JsonNodeFactory.instance.textNode("STATE_UNSPECIFIED")) + .knownEnum()); + assertEquals( + JobState.Known.JOB_STATE_RUNNING, + Transformers.tTuningJobStatus(JsonNodeFactory.instance.textNode("CREATING")).knownEnum()); + assertEquals( + JobState.Known.JOB_STATE_SUCCEEDED, + Transformers.tTuningJobStatus(JsonNodeFactory.instance.textNode("ACTIVE")).knownEnum()); + assertEquals( + JobState.Known.JOB_STATE_FAILED, + Transformers.tTuningJobStatus(JsonNodeFactory.instance.textNode("FAILED")).knownEnum()); + } + + @Test + public void tTuningJobStatus_unsupportedType_throwsException() { + assertThrows( + IllegalArgumentException.class, () -> Transformers.tTuningJobStatus(new UnsupportedType())); + } + + @Test + public void updateJsonNode_addNewKey() { + ObjectNode node = JsonNodeFactory.instance.objectNode(); + TextNode value = JsonNodeFactory.instance.textNode("testValue"); + Transformers.updateJsonNode(node, "newKey", value); + assertEquals(value, node.get("newKey")); + } + + @Test + public void updateJsonNode_overwriteWithNull_noChange() { + ObjectNode node = JsonNodeFactory.instance.objectNode(); + TextNode initialValue = JsonNodeFactory.instance.textNode("initialValue"); + node.set("existingKey", initialValue); + Transformers.updateJsonNode(node, "existingKey", null); + assertEquals(initialValue, node.get("existingKey")); + } + + @Test + public void updateJsonNode_overwriteWithSameValue_noChange() { + ObjectNode node = JsonNodeFactory.instance.objectNode(); + TextNode value = JsonNodeFactory.instance.textNode("sameValue"); + node.set("existingKey", value); + Transformers.updateJsonNode( + node, "existingKey", JsonNodeFactory.instance.textNode("sameValue")); + assertEquals(value, node.get("existingKey")); + } + + @Test + public void updateJsonNode_mergeObjects() { + ObjectNode node = JsonNodeFactory.instance.objectNode(); + ObjectNode initialObj = JsonNodeFactory.instance.objectNode(); + initialObj.put("a", "1"); + node.set("objectKey", initialObj); + + ObjectNode newObj = JsonNodeFactory.instance.objectNode(); + newObj.put("b", "2"); + Transformers.updateJsonNode(node, "objectKey", newObj); + + ObjectNode expectedObj = JsonNodeFactory.instance.objectNode(); + expectedObj.put("a", "1"); + expectedObj.put("b", "2"); + assertEquals(expectedObj, node.get("objectKey")); + } + + @Test + public void updateJsonNode_overwriteWithEmptyNode_noChange() { + ObjectNode node = JsonNodeFactory.instance.objectNode(); + TextNode initialValue = JsonNodeFactory.instance.textNode("initial"); + node.set("key", initialValue); + Transformers.updateJsonNode(node, "key", JsonNodeFactory.instance.objectNode()); + assertEquals(initialValue, node.get("key")); + } + + @Test + public void camelToSnake_emptyString() { + assertEquals("", Transformers.camelToSnake("")); + } + + @Test + public void camelToSnake_nullString() { + assertEquals(null, Transformers.camelToSnake(null)); + } + + @Test + public void camelToSnake_singleWord() { + assertEquals("test", Transformers.camelToSnake("test")); + } + + @Test + public void camelToSnake_camelCase() { + assertEquals("test_four_word_string", Transformers.camelToSnake("testFourWordString")); + } + + @Test + public void camelToSnake_withNumbers() { + assertEquals("test_string123", Transformers.camelToSnake("testString123")); + } } From 40e7e07a4acd03b14c19dc1f163d4dea43b62b9b Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Wed, 16 Jul 2025 15:22:43 -0700 Subject: [PATCH 082/602] chore(main): release 1.9.0 (#395) * chore(main): release 1.9.0 * Update CHANGELOG.md --------- Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> Co-authored-by: Ivan Lopez Hernandez --- .release-please-manifest.json | 2 +- CHANGELOG.md | 14 ++++++++++++++ README.md | 2 +- examples/pom.xml | 4 ++-- pom.xml | 2 +- src/main/java/com/google/genai/ApiClient.java | 2 +- versions.txt | 2 +- 7 files changed, 21 insertions(+), 7 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index c523ce19f0b..c3c95522a63 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "1.8.0" + ".": "1.9.0" } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 64bdd0276a3..98f606543e2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,19 @@ # Changelog +## [1.9.0](https://github.com/googleapis/java-genai/compare/v1.8.0...v1.9.0) (2025-07-16) + + +### Features + +* Add `addWatermark` parameter to the edit image configuration. ([c4598da](https://github.com/googleapis/java-genai/commit/c4598da0903d5dacb0c7bb4462aec1226ba259bf)) +* add tests for the async Operations module ([14c008a](https://github.com/googleapis/java-genai/commit/14c008a8fc40f712f922526dc00e2596705dc134)) +* add Tuning support for Java ([0ab209d](https://github.com/googleapis/java-genai/commit/0ab209db99bf98b58f7273fb12843984c42cb910)) + + +### Documentation + +* Update generated video resolution config docstring ([9a2ced8](https://github.com/googleapis/java-genai/commit/9a2ced8ed3a1896b8170cc9ca117b61cb9eea705)) + ## [1.8.0](https://github.com/googleapis/java-genai/compare/v1.7.0...v1.8.0) (2025-07-09) diff --git a/README.md b/README.md index dbbf39d6182..bfc29b7fc97 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ If you're using Maven, add the following to your dependencies: com.google.genai google-genai - 1.8.0 + 1.9.0 ``` diff --git a/examples/pom.xml b/examples/pom.xml index 30c12b197ef..5edfef0d5a9 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -5,7 +5,7 @@ com.google.genai.examples google-genai-examples - 1.9.0-SNAPSHOT + 1.9.0 google-genai-examples @@ -13,7 +13,7 @@ 1.8 1.8 - 1.9.0-SNAPSHOT + 1.9.0 diff --git a/pom.xml b/pom.xml index 5443657093d..5b5d48e1ac9 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ com.google.genai google-genai google-genai - 1.9.0-SNAPSHOT + 1.9.0 jar Java idiomatic SDK for the Gemini Developer APIs and Vertex AI APIs. diff --git a/src/main/java/com/google/genai/ApiClient.java b/src/main/java/com/google/genai/ApiClient.java index eab17d0f35c..e01d0fd4a1e 100644 --- a/src/main/java/com/google/genai/ApiClient.java +++ b/src/main/java/com/google/genai/ApiClient.java @@ -45,7 +45,7 @@ abstract class ApiClient { // {x-version-update-start:google-genai:released} - private static final String SDK_VERSION = "1.8.0"; + private static final String SDK_VERSION = "1.9.0"; // {x-version-update-end:google-genai:released} private static final Logger logger = Logger.getLogger(ApiClient.class.getName()); diff --git a/versions.txt b/versions.txt index 92cc1f726e6..4188367ca84 100644 --- a/versions.txt +++ b/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-genai:1.8.0:1.9.0-SNAPSHOT +google-genai:1.9.0:1.9.0 From 4cce245a9d9ea0b4789d61a697cb586175528fd6 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Wed, 16 Jul 2025 15:39:46 -0700 Subject: [PATCH 083/602] chore(main): release 1.10.0-SNAPSHOT (#415) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- examples/pom.xml | 4 ++-- pom.xml | 2 +- versions.txt | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/pom.xml b/examples/pom.xml index 5edfef0d5a9..3088a81fefa 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -5,7 +5,7 @@ com.google.genai.examples google-genai-examples - 1.9.0 + 1.10.0-SNAPSHOT google-genai-examples @@ -13,7 +13,7 @@ 1.8 1.8 - 1.9.0 + 1.10.0-SNAPSHOT diff --git a/pom.xml b/pom.xml index 5b5d48e1ac9..8e59d53dd3b 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ com.google.genai google-genai google-genai - 1.9.0 + 1.10.0-SNAPSHOT jar Java idiomatic SDK for the Gemini Developer APIs and Vertex AI APIs. diff --git a/versions.txt b/versions.txt index 4188367ca84..39faa71c483 100644 --- a/versions.txt +++ b/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-genai:1.9.0:1.9.0 +google-genai:1.9.0:1.10.0-SNAPSHOT From fdea885c229102aed6925c330f90e4858ba82bf5 Mon Sep 17 00:00:00 2001 From: Ivan Lopez Hernandez Date: Wed, 16 Jul 2025 15:37:28 -0700 Subject: [PATCH 084/602] Copybara import of the project: -- 4b7ec68a63c3fc3d18328eff6f66694f401d8dfa by release-please[bot] <55107282+release-please[bot]@users.noreply.github.com>: chore(main): release 1.9.0 -- fb911656a77d1cd793234e4bbe365858ee39cfdc by Ivan Lopez Hernandez : Update CHANGELOG.md COPYBARA_INTEGRATE_REVIEW=https://github.com/googleapis/java-genai/pull/395 from googleapis:release-please--branches--main fb911656a77d1cd793234e4bbe365858ee39cfdc PiperOrigin-RevId: 783920954 --- examples/pom.xml | 4 ++-- pom.xml | 2 +- versions.txt | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/pom.xml b/examples/pom.xml index 3088a81fefa..5edfef0d5a9 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -5,7 +5,7 @@ com.google.genai.examples google-genai-examples - 1.10.0-SNAPSHOT + 1.9.0 google-genai-examples @@ -13,7 +13,7 @@ 1.8 1.8 - 1.10.0-SNAPSHOT + 1.9.0 diff --git a/pom.xml b/pom.xml index 8e59d53dd3b..5b5d48e1ac9 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ com.google.genai google-genai google-genai - 1.10.0-SNAPSHOT + 1.9.0 jar Java idiomatic SDK for the Gemini Developer APIs and Vertex AI APIs. diff --git a/versions.txt b/versions.txt index 39faa71c483..4188367ca84 100644 --- a/versions.txt +++ b/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-genai:1.9.0:1.10.0-SNAPSHOT +google-genai:1.9.0:1.9.0 From f3c80d6726971163ddaa539a16949aaa3ba479d9 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Wed, 16 Jul 2025 16:55:52 -0700 Subject: [PATCH 085/602] Copybara import of the project: -- 40e7e07a4acd03b14c19dc1f163d4dea43b62b9b by release-please[bot] <55107282+release-please[bot]@users.noreply.github.com>: chore(main): release 1.9.0 (#395) * chore(main): release 1.9.0 * Update CHANGELOG.md --------- Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> Co-authored-by: Ivan Lopez Hernandez -- 3a5c5c91ab14acf42c7db6c5ce6c4e05544be74b by release-please[bot] <55107282+release-please[bot]@users.noreply.github.com>: chore(main): release 1.10.0-SNAPSHOT COPYBARA_INTEGRATE_REVIEW=https://github.com/googleapis/java-genai/pull/415 from googleapis:release-please--branches--main 3a5c5c91ab14acf42c7db6c5ce6c4e05544be74b PiperOrigin-RevId: 783946809 --- examples/pom.xml | 4 ++-- pom.xml | 2 +- versions.txt | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/pom.xml b/examples/pom.xml index 5edfef0d5a9..3088a81fefa 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -5,7 +5,7 @@ com.google.genai.examples google-genai-examples - 1.9.0 + 1.10.0-SNAPSHOT google-genai-examples @@ -13,7 +13,7 @@ 1.8 1.8 - 1.9.0 + 1.10.0-SNAPSHOT diff --git a/pom.xml b/pom.xml index 5b5d48e1ac9..8e59d53dd3b 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ com.google.genai google-genai google-genai - 1.9.0 + 1.10.0-SNAPSHOT jar Java idiomatic SDK for the Gemini Developer APIs and Vertex AI APIs. diff --git a/versions.txt b/versions.txt index 4188367ca84..39faa71c483 100644 --- a/versions.txt +++ b/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-genai:1.9.0:1.9.0 +google-genai:1.9.0:1.10.0-SNAPSHOT From 4ad4b56b2d309b96aa5e811e663cf0ec6daab389 Mon Sep 17 00:00:00 2001 From: Jaycee Li Date: Wed, 16 Jul 2025 18:18:35 -0700 Subject: [PATCH 086/602] chore: Remove test change from CHANGELOG - Features PiperOrigin-RevId: 783970421 --- CHANGELOG.md | 1 - 1 file changed, 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 98f606543e2..49b665051ce 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,6 @@ ### Features * Add `addWatermark` parameter to the edit image configuration. ([c4598da](https://github.com/googleapis/java-genai/commit/c4598da0903d5dacb0c7bb4462aec1226ba259bf)) -* add tests for the async Operations module ([14c008a](https://github.com/googleapis/java-genai/commit/14c008a8fc40f712f922526dc00e2596705dc134)) * add Tuning support for Java ([0ab209d](https://github.com/googleapis/java-genai/commit/0ab209db99bf98b58f7273fb12843984c42cb910)) From c683835593e74673e44f981ab8b0e0c7dbb105cd Mon Sep 17 00:00:00 2001 From: Matthew Tang Date: Thu, 17 Jul 2025 10:24:30 -0700 Subject: [PATCH 087/602] feat: Add generateVideosFromSource in Go, refactor private generateVideos PiperOrigin-RevId: 784229894 --- .../java/com/google/genai/AsyncModels.java | 45 ++++++++++--------- src/main/java/com/google/genai/Models.java | 40 ++++++++++++++++- 2 files changed, 61 insertions(+), 24 deletions(-) diff --git a/src/main/java/com/google/genai/AsyncModels.java b/src/main/java/com/google/genai/AsyncModels.java index a2045a2bd4d..8502b25b5d3 100644 --- a/src/main/java/com/google/genai/AsyncModels.java +++ b/src/main/java/com/google/genai/AsyncModels.java @@ -122,27 +122,6 @@ public CompletableFuture computeTokens( return CompletableFuture.supplyAsync(() -> models.computeTokens(model, contents, config)); } - /** - * Asynchronously generates videos given a GenAI model, and an input (text, image, or video). - * - *

This method is experimental. - * - * @param model the name of the GenAI model to use for generating videos - * @param prompt the text prompt for generating the videos. Optional for image to video use cases. - * @param image the input image for generating the videos. Optional if prompt is provided. - * @param video the input video for video extension use cases. Optional if prompt or image is - * provided. - * @param config a {@link com.google.genai.types.GenerateVideosConfig} instance that specifies the - * optional configurations - * @return a {@link com.google.genai.types.GenerateVideosOperation} instance that contains the - * generated videos. - */ - public CompletableFuture generateVideos( - String model, String prompt, Image image, Video video, GenerateVideosConfig config) { - return CompletableFuture.supplyAsync( - () -> models.generateVideos(model, prompt, image, video, config)); - } - /** * Asynchronously counts tokens given a GenAI model and a text string. * @@ -322,6 +301,28 @@ public CompletableFuture upscaleImage( () -> models.upscaleImage(model, image, upscaleFactor, config)); } + /** + * Asynchronously generates videos given a GenAI model, and an input (text, image, or video). + * + *

This method is experimental. + * + * @param model the name of the GenAI model to use for generating videos + * @param prompt the text prompt for generating the videos. Optional for image to video and video + * extension use cases. + * @param image the input image for generating the videos. Optional if prompt is provided. + * @param video the input video for video extension use cases. Optional if prompt or image is + * provided. + * @param config a {@link com.google.genai.types.GenerateVideosConfig} instance that specifies the + * optional configurations + * @return a {@link com.google.genai.types.GenerateVideosOperation} instance that contains the + * generated videos. + */ + public CompletableFuture generateVideos( + String model, String prompt, Image image, Video video, GenerateVideosConfig config) { + return CompletableFuture.supplyAsync( + () -> models.privateGenerateVideos(model, prompt, image, video, config)); + } + /** * Asynchronously generates videos given a GenAI model, and an input (text, image). * @@ -338,7 +339,7 @@ public CompletableFuture upscaleImage( public CompletableFuture generateVideos( String model, String prompt, Image image, GenerateVideosConfig config) { return CompletableFuture.supplyAsync( - () -> models.generateVideos(model, prompt, image, null, config)); + () -> models.privateGenerateVideos(model, prompt, image, null, config)); } /** diff --git a/src/main/java/com/google/genai/Models.java b/src/main/java/com/google/genai/Models.java index c3a5a440d1a..8ad1d38337f 100644 --- a/src/main/java/com/google/genai/Models.java +++ b/src/main/java/com/google/genai/Models.java @@ -1579,6 +1579,13 @@ ObjectNode imageToMldev(JsonNode fromObject, ObjectNode parentObject) { return toObject; } + @ExcludeFromGeneratedCoverageReport + ObjectNode generateVideosSourceToMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + + return toObject; + } + @ExcludeFromGeneratedCoverageReport ObjectNode generateVideosConfigToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); @@ -3784,6 +3791,13 @@ ObjectNode videoToVertex(JsonNode fromObject, ObjectNode parentObject) { return toObject; } + @ExcludeFromGeneratedCoverageReport + ObjectNode generateVideosSourceToVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + + return toObject; + } + @ExcludeFromGeneratedCoverageReport ObjectNode generateVideosConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); @@ -6529,7 +6543,8 @@ public ComputeTokensResponse computeTokens( *

This method is experimental. * * @param model the name of the GenAI model to use for generating videos - * @param prompt the text prompt for generating the videos. Optional for image to video use cases. + * @param prompt the text prompt for generating the videos. Optional for image to video and video + * extension use cases. * @param image the input image for generating the videos. Optional if prompt is provided. * @param video the input video for video extension use cases. Optional if prompt or image is * provided. @@ -6538,7 +6553,7 @@ public ComputeTokensResponse computeTokens( * @return a {@link com.google.genai.types.GenerateVideosOperation} instance that contains the * generated videos. */ - public GenerateVideosOperation generateVideos( + GenerateVideosOperation privateGenerateVideos( String model, String prompt, Image image, Video video, GenerateVideosConfig config) { GenerateVideosParameters.Builder parameterBuilder = GenerateVideosParameters.builder(); @@ -6905,6 +6920,27 @@ public UpscaleImageResponse upscaleImage( return privateUpscaleImage(model, image, upscaleFactor, apiConfig); } + /** + * Generates videos given a GenAI model, and an input (text, image, or video). + * + *

This method is experimental. + * + * @param model the name of the GenAI model to use for generating videos + * @param prompt the text prompt for generating the videos. Optional for image to video and video + * extension use cases. + * @param image the input image for generating the videos. Optional if prompt is provided. + * @param video the input video for video extension use cases. Optional if prompt or image is + * provided. + * @param config a {@link com.google.genai.types.GenerateVideosConfig} instance that specifies the + * optional configurations + * @return a {@link com.google.genai.types.GenerateVideosOperation} instance that contains the + * generated videos. + */ + public GenerateVideosOperation generateVideos( + String model, String prompt, Image image, Video video, GenerateVideosConfig config) { + return privateGenerateVideos(model, prompt, image, video, config); + } + /** * Generates videos given a GenAI model, and an input (text, image). * From 950c0c657f786039e3a301bf1237a57ae324ff62 Mon Sep 17 00:00:00 2001 From: Matthew Tang Date: Thu, 17 Jul 2025 11:32:25 -0700 Subject: [PATCH 088/602] feat: Add image_size field for Vertex Imagen 4 generation PiperOrigin-RevId: 784254398 --- src/main/java/com/google/genai/Models.java | 11 +++++++++++ .../google/genai/types/GenerateImagesConfig.java | 16 ++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/src/main/java/com/google/genai/Models.java b/src/main/java/com/google/genai/Models.java index 8ad1d38337f..a652b0eec7b 100644 --- a/src/main/java/com/google/genai/Models.java +++ b/src/main/java/com/google/genai/Models.java @@ -1305,6 +1305,10 @@ ObjectNode generateImagesConfigToMldev(JsonNode fromObject, ObjectNode parentObj throw new IllegalArgumentException("addWatermark parameter is not supported in Gemini API."); } + if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"imageSize"}))) { + throw new IllegalArgumentException("imageSize parameter is not supported in Gemini API."); + } + if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"enhancePrompt"}))) { throw new IllegalArgumentException("enhancePrompt parameter is not supported in Gemini API."); } @@ -3023,6 +3027,13 @@ ObjectNode generateImagesConfigToVertex(JsonNode fromObject, ObjectNode parentOb Common.getValueByPath(fromObject, new String[] {"addWatermark"})); } + if (Common.getValueByPath(fromObject, new String[] {"imageSize"}) != null) { + Common.setValueByPath( + parentObject, + new String[] {"parameters", "sampleImageSize"}, + Common.getValueByPath(fromObject, new String[] {"imageSize"})); + } + if (Common.getValueByPath(fromObject, new String[] {"enhancePrompt"}) != null) { Common.setValueByPath( parentObject, diff --git a/src/main/java/com/google/genai/types/GenerateImagesConfig.java b/src/main/java/com/google/genai/types/GenerateImagesConfig.java index 0a672e02ecd..eda36d1880c 100644 --- a/src/main/java/com/google/genai/types/GenerateImagesConfig.java +++ b/src/main/java/com/google/genai/types/GenerateImagesConfig.java @@ -104,6 +104,13 @@ public abstract class GenerateImagesConfig extends JsonSerializable { @JsonProperty("addWatermark") public abstract Optional addWatermark(); + /** + * The size of the largest dimension of the generated image. Supported sizes are 1K and 2K (not + * supported for Imagen 3 models). + */ + @JsonProperty("imageSize") + public abstract Optional imageSize(); + /** Whether to use the prompt rewriting logic. */ @JsonProperty("enhancePrompt") public abstract Optional enhancePrompt(); @@ -320,6 +327,15 @@ public Builder language(String language) { @JsonProperty("addWatermark") public abstract Builder addWatermark(boolean addWatermark); + /** + * Setter for imageSize. + * + *

imageSize: The size of the largest dimension of the generated image. Supported sizes are + * 1K and 2K (not supported for Imagen 3 models). + */ + @JsonProperty("imageSize") + public abstract Builder imageSize(String imageSize); + /** * Setter for enhancePrompt. * From e48c7f1e73dadf5c5198f9b58cea322deb7a4ed0 Mon Sep 17 00:00:00 2001 From: Kaituo Huang Date: Thu, 17 Jul 2025 14:39:45 -0700 Subject: [PATCH 089/602] fix(live): Enhance security by moving api key from query parameters to header PiperOrigin-RevId: 784321443 --- src/main/java/com/google/genai/AsyncLive.java | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/google/genai/AsyncLive.java b/src/main/java/com/google/genai/AsyncLive.java index a4b91e4b243..f256530e649 100644 --- a/src/main/java/com/google/genai/AsyncLive.java +++ b/src/main/java/com/google/genai/AsyncLive.java @@ -101,10 +101,8 @@ private URI getWebSocketUri() { if (!apiClient.vertexAI()) { return new URI( String.format( - "%s/ws/google.ai.generativelanguage.%s.GenerativeService.BidiGenerateContent?key=%s", - wsBaseUrl, - apiClient.httpOptions.apiVersion().orElse("v1beta"), - apiClient.apiKey())); + "%s/ws/google.ai.generativelanguage.%s.GenerativeService.BidiGenerateContent", + wsBaseUrl, apiClient.httpOptions.apiVersion().orElse("v1beta"))); } else { return new URI( String.format( @@ -130,6 +128,12 @@ private Map getWebSocketHeaders() { } catch (IOException e) { throw new GenAiIOException("Failed to refresh credentials for Vertex AI.", e); } + } else { + String apiKey = apiClient.apiKey(); + if (apiKey == null || apiKey.isEmpty()) { + throw new IllegalArgumentException("Missing API key in the client."); + } + headers.put("x-goog-api-key", apiKey); } return headers; } From d151a25f64c250c4464f8ac9b5c3b48efe41b9fe Mon Sep 17 00:00:00 2001 From: Jaycee Li Date: Fri, 18 Jul 2025 11:02:52 -0700 Subject: [PATCH 090/602] chore: Refactor ApiClient for Vertex EasyGCP support PiperOrigin-RevId: 784637176 --- src/main/java/com/google/genai/ApiClient.java | 68 ++++---- src/main/java/com/google/genai/Client.java | 2 + .../java/com/google/genai/HttpApiClient.java | 3 +- .../com/google/genai/ReplayApiClient.java | 3 +- .../com/google/genai/HttpApiClientTest.java | 148 +++++++++++++----- 5 files changed, 152 insertions(+), 72 deletions(-) diff --git a/src/main/java/com/google/genai/ApiClient.java b/src/main/java/com/google/genai/ApiClient.java index e01d0fd4a1e..73d78cac5dd 100644 --- a/src/main/java/com/google/genai/ApiClient.java +++ b/src/main/java/com/google/genai/ApiClient.java @@ -90,7 +90,7 @@ protected ApiClient( this.vertexAI = false; this.clientOptions = clientOptions; - this.httpOptions = defaultHttpOptions(/* vertexAI= */ false, this.location); + this.httpOptions = defaultHttpOptions(/* vertexAI= */ false, this.location, this.apiKey); if (customHttpOptions.isPresent()) { this.httpOptions = mergeHttpOptions(customHttpOptions.get()); @@ -100,51 +100,51 @@ protected ApiClient( } ApiClient( + Optional apiKey, Optional project, Optional location, Optional credentials, Optional customHttpOptions, Optional clientOptions) { + checkNotNull(apiKey, "API Key cannot be null"); checkNotNull(project, "project cannot be null"); checkNotNull(location, "location cannot be null"); checkNotNull(credentials, "credentials cannot be null"); checkNotNull(customHttpOptions, "customHttpOptions cannot be null"); checkNotNull(clientOptions, "clientOptions cannot be null"); - try { - this.project = Optional.of(project.orElse(System.getenv("GOOGLE_CLOUD_PROJECT"))); - } catch (NullPointerException e) { - throw new IllegalArgumentException( - "Project must either be provided or set in the environment variable" - + " GOOGLE_CLOUD_PROJECT.", - e); - } - if (this.project.get().isEmpty()) { - throw new IllegalArgumentException("Project must not be empty."); - } + String apiKeyValue = apiKey.orElseGet(() -> getApiKeyFromEnv()); + String projectValue = project.orElseGet(() -> System.getenv("GOOGLE_CLOUD_PROJECT")); + String locationValue = location.orElseGet(() -> System.getenv("GOOGLE_CLOUD_LOCATION")); - try { - this.location = Optional.of(location.orElse(System.getenv("GOOGLE_CLOUD_LOCATION"))); - } catch (NullPointerException e) { + boolean hasApiKey = apiKeyValue != null && !apiKeyValue.isEmpty(); + boolean hasProjectAndLocation = + (projectValue != null && !projectValue.isEmpty()) + && (locationValue != null && !locationValue.isEmpty()); + + if (!hasApiKey && !hasProjectAndLocation) { throw new IllegalArgumentException( - "Location must either be provided or set in the environment variable" - + " GOOGLE_CLOUD_LOCATION.", - e); - } - if (this.location.get().isEmpty()) { - throw new IllegalArgumentException("Location must not be empty."); + "For Vertex AI APIs, either API key, or project/location must be provided or set in the" + + " environment variable."); } - this.credentials = Optional.of(credentials.orElseGet(() -> defaultCredentials())); + this.apiKey = Optional.ofNullable(apiKeyValue); + this.project = Optional.ofNullable(projectValue); + this.location = Optional.ofNullable(locationValue); + + // Only set credentials if using project/location. + this.credentials = + projectValue == null + ? Optional.empty() + : Optional.of(credentials.orElseGet(() -> defaultCredentials())); this.clientOptions = clientOptions; - this.httpOptions = defaultHttpOptions(/* vertexAI= */ true, this.location); + this.httpOptions = defaultHttpOptions(/* vertexAI= */ true, this.location, this.apiKey); if (customHttpOptions.isPresent()) { this.httpOptions = mergeHttpOptions(customHttpOptions.get()); } - this.apiKey = Optional.empty(); this.vertexAI = true; this.httpClient = createHttpClient(httpOptions.timeout(), clientOptions); } @@ -391,7 +391,8 @@ HttpOptions mergeHttpOptions(HttpOptions httpOptionsToApply) { return mergedHttpOptionsBuilder.build(); } - static HttpOptions defaultHttpOptions(boolean vertexAI, Optional location) { + static HttpOptions defaultHttpOptions( + boolean vertexAI, Optional location, Optional apiKey) { ImmutableMap.Builder defaultHeaders = ImmutableMap.builder(); defaultHeaders.put("Content-Type", "application/json"); defaultHeaders.put("user-agent", libraryVersion()); @@ -400,15 +401,14 @@ static HttpOptions defaultHttpOptions(boolean vertexAI, Optional locatio HttpOptions.Builder defaultHttpOptionsBuilder = HttpOptions.builder().headers(defaultHeaders.build()); - if (vertexAI && location.isPresent()) { - defaultHttpOptionsBuilder - .baseUrl( - location.get().equalsIgnoreCase("global") - ? "https://aiplatform.googleapis.com" - : String.format("https://%s-aiplatform.googleapis.com", location.get())) - .apiVersion("v1beta1"); - } else if (vertexAI && !location.isPresent()) { - throw new IllegalArgumentException("Location must be provided for Vertex AI APIs."); + if (vertexAI) { + defaultHttpOptionsBuilder.apiVersion("v1beta1"); + if (apiKey.isPresent() || location.get().equalsIgnoreCase("global")) { + defaultHttpOptionsBuilder.baseUrl("https://aiplatform.googleapis.com"); + } else { + defaultHttpOptionsBuilder.baseUrl( + String.format("https://%s-aiplatform.googleapis.com", location.get())); + } } else { defaultHttpOptionsBuilder .baseUrl("https://generativelanguage.googleapis.com") diff --git a/src/main/java/com/google/genai/Client.java b/src/main/java/com/google/genai/Client.java index 6ab95cf1aa0..d35850c3d14 100644 --- a/src/main/java/com/google/genai/Client.java +++ b/src/main/java/com/google/genai/Client.java @@ -288,6 +288,7 @@ private Client( } else { this.apiClient = new ReplayApiClient( + /* apiKey= */ apiKey, /* project= */ project, /* location= */ location, /* credentials= */ credentials, @@ -307,6 +308,7 @@ private Client( } else { this.apiClient = new HttpApiClient( + /* apiKey= */ apiKey, /* project= */ project, /* location= */ location, /* credentials= */ credentials, diff --git a/src/main/java/com/google/genai/HttpApiClient.java b/src/main/java/com/google/genai/HttpApiClient.java index 9297487403d..fe6d02d0c06 100644 --- a/src/main/java/com/google/genai/HttpApiClient.java +++ b/src/main/java/com/google/genai/HttpApiClient.java @@ -39,12 +39,13 @@ public class HttpApiClient extends ApiClient { /** Constructs an ApiClient for Vertex AI APIs. */ HttpApiClient( + Optional apiKey, Optional project, Optional location, Optional credentials, Optional httpOptions, Optional clientOptions) { - super(project, location, credentials, httpOptions, clientOptions); + super(apiKey, project, location, credentials, httpOptions, clientOptions); } /** diff --git a/src/main/java/com/google/genai/ReplayApiClient.java b/src/main/java/com/google/genai/ReplayApiClient.java index c5e5a01f6a4..762299f44cd 100644 --- a/src/main/java/com/google/genai/ReplayApiClient.java +++ b/src/main/java/com/google/genai/ReplayApiClient.java @@ -78,6 +78,7 @@ final class ReplayApiClient extends ApiClient { /** Constructs an ApiClient for Vertex AI APIs. */ ReplayApiClient( + Optional apiKey, Optional project, Optional location, Optional credentials, @@ -86,7 +87,7 @@ final class ReplayApiClient extends ApiClient { String replaysDirectory, String replayId, String clientMode) { - super(project, location, credentials, httpOptions, clientOptions); + super(apiKey, project, location, credentials, httpOptions, clientOptions); checkNotNull(replaysDirectory, "replaysDirectory cannot be null"); checkNotNull(replayId, "replayId cannot be null"); checkNotNull(clientMode, "clientMode cannot be null"); diff --git a/src/test/java/com/google/genai/HttpApiClientTest.java b/src/test/java/com/google/genai/HttpApiClientTest.java index ef507fb4aab..fb973905f58 100644 --- a/src/test/java/com/google/genai/HttpApiClientTest.java +++ b/src/test/java/com/google/genai/HttpApiClientTest.java @@ -63,9 +63,9 @@ public class HttpApiClientTest { private static final String PROJECT = "project"; private static final String LOCATION = "location"; private static final HttpOptions defaultHttpOptionsMLDev = - HttpApiClient.defaultHttpOptions(false, Optional.empty()); + HttpApiClient.defaultHttpOptions(false, Optional.empty(), Optional.of(API_KEY)); private static final HttpOptions defaultHttpOptionsVertex = - HttpApiClient.defaultHttpOptions(true, Optional.of(LOCATION)); + HttpApiClient.defaultHttpOptions(true, Optional.of(LOCATION), Optional.empty()); private static final Optional REQUEST_HTTP_OPTIONS = Optional.of( HttpOptions.builder() @@ -100,12 +100,13 @@ private void setMockClient(HttpApiClient client) throws Exception { credentialsField.setAccessible(true); credentialsField.set(client, Optional.of(credentials)); } - + @Test public void testRequestPostMethodWithVertexAI() throws Exception { // Arrange HttpApiClient client = new HttpApiClient( + Optional.empty(), Optional.of(PROJECT), Optional.of(LOCATION), Optional.empty(), @@ -249,7 +250,20 @@ public void testInitHttpClientMldev() throws Exception { } @Test - public void testInitHttpClientVertex() throws Exception { + public void testInitHttpClientMldevWithNoApiKey_throwsException() throws Exception { + IllegalArgumentException exception = + assertThrows( + IllegalArgumentException.class, + () -> new HttpApiClient(Optional.empty(), Optional.empty(), Optional.empty())); + + assertEquals( + "API key must either be provided or set in the environment variable" + + " GOOGLE_API_KEY or GEMINI_API_KEY. If both are set, GOOGLE_API_KEY will be used.", + exception.getMessage()); + } + + @Test + public void testInitHttpClientVertexWithProjectAndLocation() throws Exception { HttpOptions httpOptions = HttpOptions.builder() .baseUrl("https://aiplatform.googleapis.com") @@ -259,6 +273,7 @@ public void testInitHttpClientVertex() throws Exception { .build(); HttpApiClient client = new HttpApiClient( + Optional.empty(), Optional.of(PROJECT), Optional.of(LOCATION), Optional.empty(), @@ -282,6 +297,63 @@ public void testInitHttpClientVertex() throws Exception { assertEquals("6", client.httpOptions.headers().get().get("X-Server-Timeout")); } + @Test + public void testInitHttpClientVertexWithApiKey() throws Exception { + HttpApiClient client = + new HttpApiClient( + Optional.of(API_KEY), + Optional.empty(), + Optional.empty(), + Optional.empty(), + Optional.empty(), + Optional.empty()); + + assertTrue(client.vertexAI()); + assertEquals(API_KEY, client.apiKey()); + assertNull(client.project()); + assertNull(client.location()); + // Default to global endpoint for easy GCP. + assertEquals(Optional.of("https://aiplatform.googleapis.com"), client.httpOptions.baseUrl()); + } + + @Test + public void testInitHttpClientVertexWithNoApiKeyAndNoProject_throwsException() throws Exception { + IllegalArgumentException exception = + assertThrows( + IllegalArgumentException.class, + () -> + new HttpApiClient( + Optional.empty(), + Optional.empty(), + Optional.of(LOCATION), + Optional.empty(), + Optional.empty(), + Optional.empty())); + assertEquals( + "For Vertex AI APIs, either API key, or project/location must be provided or set in the" + + " environment variable.", + exception.getMessage()); + } + + @Test + public void testHttpClientVertexWithNoApiKeyAndNoLocation_throwsException() throws Exception { + IllegalArgumentException exception = + assertThrows( + IllegalArgumentException.class, + () -> + new HttpApiClient( + Optional.empty(), + Optional.of(PROJECT), + Optional.empty(), + Optional.empty(), + Optional.empty(), + Optional.empty())); + assertEquals( + "For Vertex AI APIs, either API key, or project/location must be provided or set in the" + + " environment variable.", + exception.getMessage()); + } + @Test public void testInitHttpClientMldevWithPartialHttpOptions() throws Exception { HttpOptions httpOptions = HttpOptions.builder().apiVersion("v100").timeout(5000).build(); @@ -302,6 +374,7 @@ public void testInitHttpClientVertexWithPartialHttpOptions() throws Exception { HttpOptions httpOptions = HttpOptions.builder().apiVersion("v100").timeout(5000).build(); HttpApiClient client = new HttpApiClient( + Optional.empty(), Optional.of(PROJECT), Optional.of(LOCATION), Optional.empty(), @@ -321,67 +394,67 @@ public void testInitHttpClientVertexWithPartialHttpOptions() throws Exception { public void testHttpClientMLDevTimeout() throws Exception { HttpOptions httpOptions = HttpOptions.builder().timeout(5000).build(); HttpApiClient client = - new HttpApiClient(Optional.of("api-key"), Optional.of(httpOptions), Optional.empty()); + new HttpApiClient(Optional.of(API_KEY), Optional.of(httpOptions), Optional.empty()); OkHttpClient httpClient = client.httpClient(); assertNotNull(httpClient); assertEquals(5000, httpClient.connectTimeoutMillis()); - assertEquals("api-key", client.apiKey()); + assertEquals(API_KEY, client.apiKey()); assertFalse(client.vertexAI()); } @Test public void testHttpClientVertexTimeout() throws Exception { HttpOptions httpOptions = HttpOptions.builder().timeout(4999).build(); - Optional project = Optional.of("project"); - Optional location = Optional.of("location"); - Optional credentials = - Optional.of(GoogleCredentials.getApplicationDefault()); HttpApiClient client = new HttpApiClient( - project, location, credentials, Optional.of(httpOptions), Optional.empty()); + Optional.empty(), + Optional.of(PROJECT), + Optional.of(LOCATION), + Optional.empty(), + Optional.of(httpOptions), + Optional.empty()); OkHttpClient httpClient = client.httpClient(); assertNotNull(httpClient); assertEquals(4999, httpClient.connectTimeoutMillis()); - assertEquals("project", client.project()); - assertEquals("location", client.location()); + assertEquals(PROJECT, client.project()); + assertEquals(LOCATION, client.location()); assertTrue(client.vertexAI()); } @Test public void testHttpClientNoTimeout() throws Exception { - HttpOptions httpOptions = HttpOptions.builder().build(); HttpApiClient client = - new HttpApiClient(Optional.of("api-key"), Optional.of(httpOptions), Optional.empty()); + new HttpApiClient(Optional.of(API_KEY), Optional.empty(), Optional.empty()); OkHttpClient httpClient = client.httpClient(); assertNotNull(httpClient); assertEquals(0, httpClient.connectTimeoutMillis()); - assertEquals("api-key", client.apiKey()); + assertEquals(API_KEY, client.apiKey()); assertFalse(client.httpOptions.headers().get().containsKey("X-Server-Timeout")); } @Test public void testHttpClientVertexNoTimeout() throws Exception { - HttpOptions httpOptions = HttpOptions.builder().build(); - Optional project = Optional.of("project"); - Optional location = Optional.of("location"); - Optional credentials = - Optional.of(GoogleCredentials.getApplicationDefault()); HttpApiClient client = new HttpApiClient( - project, location, credentials, Optional.of(httpOptions), Optional.empty()); + Optional.empty(), + Optional.of(PROJECT), + Optional.of(LOCATION), + Optional.empty(), + Optional.empty(), + Optional.empty()); OkHttpClient httpClient = client.httpClient(); assertNotNull(httpClient); assertEquals(0, httpClient.connectTimeoutMillis()); - assertEquals("project", client.project()); - assertEquals("location", client.location()); + assertEquals(PROJECT, client.project()); + assertEquals(LOCATION, client.location()); assertTrue(client.vertexAI()); assertFalse(client.httpOptions.headers().get().containsKey("X-Server-Timeout")); } @@ -391,11 +464,11 @@ public void testHttpClientMldevCustomClientOptions() throws Exception { ClientOptions clientOptions = ClientOptions.builder().maxConnections(64).maxConnectionsPerHost(16).build(); HttpApiClient client = - new HttpApiClient(Optional.of("api-key"), Optional.empty(), Optional.of(clientOptions)); + new HttpApiClient(Optional.of(API_KEY), Optional.empty(), Optional.of(clientOptions)); Dispatcher dispatcher = client.httpClient().dispatcher(); - assertEquals("api-key", client.apiKey()); + assertEquals(API_KEY, client.apiKey()); assertFalse(client.vertexAI()); assertEquals(64, dispatcher.getMaxRequests()); assertEquals(16, dispatcher.getMaxRequestsPerHost()); @@ -407,16 +480,17 @@ public void testHttpClientVertexCustomClientOptions() throws Exception { ClientOptions.builder().maxConnections(64).maxConnectionsPerHost(16).build(); HttpApiClient client = new HttpApiClient( - Optional.of("project"), - Optional.of("location"), + Optional.empty(), + Optional.of(PROJECT), + Optional.of(LOCATION), Optional.empty(), Optional.empty(), Optional.of(clientOptions)); Dispatcher dispatcher = client.httpClient().dispatcher(); - assertEquals("project", client.project()); - assertEquals("location", client.location()); + assertEquals(PROJECT, client.project()); + assertEquals(LOCATION, client.location()); assertTrue(client.vertexAI()); assertEquals(64, dispatcher.getMaxRequests()); assertEquals(16, dispatcher.getMaxRequestsPerHost()); @@ -425,7 +499,7 @@ public void testHttpClientVertexCustomClientOptions() throws Exception { @Test public void testHttpClientMldevDefaultClientOptions() throws Exception { HttpApiClient client = - new HttpApiClient(Optional.of("api-key"), Optional.empty(), Optional.empty()); + new HttpApiClient(Optional.of(API_KEY), Optional.empty(), Optional.empty()); Dispatcher dispatcher = client.httpClient().dispatcher(); @@ -434,20 +508,20 @@ public void testHttpClientMldevDefaultClientOptions() throws Exception { // should be equal to 5. assertEquals(64, dispatcher.getMaxRequests()); assertEquals(5, dispatcher.getMaxRequestsPerHost()); - assertEquals("api-key", client.apiKey()); + assertEquals(API_KEY, client.apiKey()); assertFalse(client.vertexAI()); } @Test public void testHttpClientWithCustomCredentials() throws Exception { GoogleCredentials credentials = Mockito.mock(GoogleCredentials.class); - HttpOptions httpOptions = HttpOptions.builder().build(); HttpApiClient client = new HttpApiClient( - Optional.of("project"), - Optional.of("us-central1"), + Optional.empty(), + Optional.of(PROJECT), + Optional.of(LOCATION), Optional.of(credentials), - Optional.of(httpOptions), + Optional.empty(), Optional.empty()); assertEquals(credentials, client.credentials.get()); } @@ -457,6 +531,7 @@ public void testHttpClientVertexWithGlobalEndpoint() throws Exception { HttpOptions httpOptions = HttpOptions.builder().build(); HttpApiClient client = new HttpApiClient( + Optional.empty(), Optional.of(PROJECT), Optional.of("global"), Optional.empty(), @@ -472,6 +547,7 @@ public void testHttpClientVertexWithGlobalEndpoint() throws Exception { public void testHttpClientVertexWithNoHttpOptions() throws Exception { HttpApiClient client = new HttpApiClient( + Optional.empty(), Optional.of(PROJECT), Optional.of("global"), Optional.empty(), From 2cbf1e8f7f616f12d95c0e8620bbaa4ffbb3ce56 Mon Sep 17 00:00:00 2001 From: Jaycee Li Date: Fri, 18 Jul 2025 11:08:42 -0700 Subject: [PATCH 091/602] chore: Centralize the environment variables management into ApiClient chore: Make unit tests robust against environment variables PiperOrigin-RevId: 784639242 --- pom.xml | 39 ++++-- src/main/java/com/google/genai/ApiClient.java | 120 ++++++++++++++---- src/main/java/com/google/genai/Client.java | 100 ++------------- .../com/google/genai/AsyncOperationsTest.java | 48 +++++-- .../java/com/google/genai/ClientTest.java | 21 +++ .../com/google/genai/DefaultValuesTest.java | 91 ------------- .../com/google/genai/HttpApiClientTest.java | 74 ++++++++--- .../java/com/google/genai/ModelsTest.java | 47 +++++-- .../java/com/google/genai/OperationsTest.java | 48 +++++-- src/test/java/com/google/genai/TableTest.java | 35 +++-- 10 files changed, 339 insertions(+), 284 deletions(-) delete mode 100644 src/test/java/com/google/genai/DefaultValuesTest.java diff --git a/pom.xml b/pom.xml index 8e59d53dd3b..41637c1a6da 100644 --- a/pom.xml +++ b/pom.xml @@ -52,7 +52,6 @@ 1.11.0 2.17.2 5.11.4 - 3.12.4 1.6.0 4.12.0 @@ -156,13 +155,6 @@ ${junit.version} test - - - org.mockito - mockito-core - ${mockito.version} - test - org.jspecify @@ -341,4 +333,35 @@ + + + jdk8-build + + [1.8,1.9) + + + + org.mockito + mockito-inline + 3.12.4 + test + + + + + + modern-jdk-build + + [11,) + + + + org.mockito + mockito-core + 5.12.0 + test + + + + \ No newline at end of file diff --git a/src/main/java/com/google/genai/ApiClient.java b/src/main/java/com/google/genai/ApiClient.java index 73d78cac5dd..ab5f0996df4 100644 --- a/src/main/java/com/google/genai/ApiClient.java +++ b/src/main/java/com/google/genai/ApiClient.java @@ -55,6 +55,9 @@ abstract class ApiClient { private static final ImmutableSet VALID_HTTP_METHODS = ImmutableSet.builder().addAll(METHODS_WITH_BODY).add("GET").add("DELETE").build(); + private static Optional geminiBaseUrl = Optional.empty(); + private static Optional vertexBaseUrl = Optional.empty(); + final OkHttpClient httpClient; HttpOptions httpOptions; final boolean vertexAI; @@ -75,8 +78,10 @@ protected ApiClient( checkNotNull(customHttpOptions, "customHttpOptions cannot be null"); checkNotNull(clientOptions, "clientOptions cannot be null"); + ImmutableMap environmentVariables = defaultEnvironmentVariables(); + try { - this.apiKey = Optional.of(apiKey.orElse(getApiKeyFromEnv())); + this.apiKey = Optional.of(apiKey.orElse(environmentVariables.get("apiKey"))); } catch (NullPointerException e) { throw new IllegalArgumentException( "API key must either be provided or set in the environment variable" @@ -113,9 +118,11 @@ protected ApiClient( checkNotNull(customHttpOptions, "customHttpOptions cannot be null"); checkNotNull(clientOptions, "clientOptions cannot be null"); - String apiKeyValue = apiKey.orElseGet(() -> getApiKeyFromEnv()); - String projectValue = project.orElseGet(() -> System.getenv("GOOGLE_CLOUD_PROJECT")); - String locationValue = location.orElseGet(() -> System.getenv("GOOGLE_CLOUD_LOCATION")); + ImmutableMap environmentVariables = defaultEnvironmentVariables(); + + String apiKeyValue = apiKey.orElseGet(() -> environmentVariables.get("apiKey")); + String projectValue = project.orElseGet(() -> environmentVariables.get("project")); + String locationValue = location.orElseGet(() -> environmentVariables.get("location")); boolean hasApiKey = apiKeyValue != null && !apiKeyValue.isEmpty(); boolean hasProjectAndLocation = @@ -128,7 +135,7 @@ protected ApiClient( + " environment variable."); } - this.apiKey = Optional.ofNullable(apiKeyValue); + this.apiKey = Optional.ofNullable(projectValue == null ? apiKeyValue : null); this.project = Optional.ofNullable(projectValue); this.location = Optional.ofNullable(locationValue); @@ -149,24 +156,6 @@ protected ApiClient( this.httpClient = createHttpClient(httpOptions.timeout(), clientOptions); } - static String getApiKeyFromEnv() { - String googleApiKey = System.getenv("GOOGLE_API_KEY"); - if (googleApiKey != null && googleApiKey.isEmpty()) { - googleApiKey = null; - } - String geminiApiKey = System.getenv("GEMINI_API_KEY"); - if (geminiApiKey != null && geminiApiKey.isEmpty()) { - geminiApiKey = null; - } - if (googleApiKey != null && geminiApiKey != null) { - logger.warning("Both GOOGLE_API_KEY and GEMINI_API_KEY are set. Using GOOGLE_API_KEY."); - } - if (googleApiKey != null) { - return googleApiKey; - } - return geminiApiKey; - } - private OkHttpClient createHttpClient( Optional timeout, Optional clientOptions) { OkHttpClient.Builder builder = new OkHttpClient.Builder(); @@ -401,18 +390,28 @@ static HttpOptions defaultHttpOptions( HttpOptions.Builder defaultHttpOptionsBuilder = HttpOptions.builder().headers(defaultHeaders.build()); + ImmutableMap defaultEnvironmentVariables = defaultEnvironmentVariables(); if (vertexAI) { defaultHttpOptionsBuilder.apiVersion("v1beta1"); - if (apiKey.isPresent() || location.get().equalsIgnoreCase("global")) { + String defaultBaseUrl = + vertexBaseUrl.orElseGet(() -> defaultEnvironmentVariables.get("vertexBaseUrl")); + if (defaultBaseUrl != null) { + defaultHttpOptionsBuilder.baseUrl(defaultBaseUrl); + } else if (apiKey.isPresent() || location.get().equalsIgnoreCase("global")) { defaultHttpOptionsBuilder.baseUrl("https://aiplatform.googleapis.com"); } else { defaultHttpOptionsBuilder.baseUrl( String.format("https://%s-aiplatform.googleapis.com", location.get())); } } else { - defaultHttpOptionsBuilder - .baseUrl("https://generativelanguage.googleapis.com") - .apiVersion("v1beta"); + defaultHttpOptionsBuilder.apiVersion("v1beta"); + String defaultBaseUrl = + geminiBaseUrl.orElseGet(() -> defaultEnvironmentVariables.get("geminiBaseUrl")); + if (defaultBaseUrl != null) { + defaultHttpOptionsBuilder.baseUrl(defaultBaseUrl); + } else { + defaultHttpOptionsBuilder.baseUrl("https://generativelanguage.googleapis.com"); + } } return defaultHttpOptionsBuilder.build(); @@ -428,4 +427,71 @@ GoogleCredentials defaultCredentials() { e); } } + + /** Returns the API key from the environment variables. */ + static String getApiKeyFromEnv() { + String googleApiKey = System.getenv("GOOGLE_API_KEY"); + if (googleApiKey != null && googleApiKey.isEmpty()) { + googleApiKey = null; + } + String geminiApiKey = System.getenv("GEMINI_API_KEY"); + if (geminiApiKey != null && geminiApiKey.isEmpty()) { + geminiApiKey = null; + } + if (googleApiKey != null && geminiApiKey != null) { + logger.warning("Both GOOGLE_API_KEY and GEMINI_API_KEY are set. Using GOOGLE_API_KEY."); + } + if (googleApiKey != null) { + return googleApiKey; + } + return geminiApiKey; + } + + /** + * Returns the default environment variables for the client. Supported environment variables: + * + *

    + *
  • apiKey -> GOOGLE_API_KEY or GEMINI_API_KEY: API key for Gemini APIs or Vertex AI APIs. + *
  • project -> GOOGLE_CLOUD_PROJECT: Project ID for Vertex AI APIs. + *
  • location -> GOOGLE_CLOUD_LOCATION: Location for Vertex AI APIs. + *
  • vertexAI -> GOOGLE_GENAI_USE_VERTEXAI: Whether to use Vertex AI APIs(true or false). + *
  • geminiBaseUrl -> GOOGLE_GEMINI_BASE_URL: Base URL for Gemini APIs. + *
  • vertexBaseUrl -> GOOGLE_VERTEX_BASE_URL: Base URL for Vertex AI APIs. + *
+ */ + static ImmutableMap defaultEnvironmentVariables() { + ImmutableMap.Builder mapBuilder = ImmutableMap.builder(); + String value; + value = getApiKeyFromEnv(); + if (value != null && !value.isEmpty()) { + mapBuilder.put("apiKey", value); + } + value = System.getenv("GOOGLE_CLOUD_PROJECT"); + if (value != null && !value.isEmpty()) { + mapBuilder.put("project", value); + } + value = System.getenv("GOOGLE_CLOUD_LOCATION"); + if (value != null && !value.isEmpty()) { + mapBuilder.put("location", value); + } + value = System.getenv("GOOGLE_GENAI_USE_VERTEXAI"); + if (value != null && !value.isEmpty()) { + mapBuilder.put("vertexAI", value); + } + value = System.getenv("GOOGLE_GEMINI_BASE_URL"); + if (value != null && !value.isEmpty()) { + mapBuilder.put("geminiBaseUrl", value); + } + value = System.getenv("GOOGLE_VERTEX_BASE_URL"); + if (value != null && !value.isEmpty()) { + mapBuilder.put("vertexBaseUrl", value); + } + return mapBuilder.buildOrThrow(); + } + + /** Overrides the base URLs for the Gemini API and/or Vertex AI API. */ + static void setDefaultBaseUrls(Optional geminiBaseUrl, Optional vertexBaseUrl) { + ApiClient.geminiBaseUrl = geminiBaseUrl; + ApiClient.vertexBaseUrl = vertexBaseUrl; + } } diff --git a/src/main/java/com/google/genai/Client.java b/src/main/java/com/google/genai/Client.java index d35850c3d14..bd9d57a47d9 100644 --- a/src/main/java/com/google/genai/Client.java +++ b/src/main/java/com/google/genai/Client.java @@ -24,34 +24,10 @@ import com.google.genai.types.ClientOptions; import com.google.genai.types.HttpOptions; import java.io.IOException; -import java.util.HashMap; -import java.util.Map; import java.util.Optional; /** Client class for GenAI. */ public final class Client implements AutoCloseable { - private static Optional geminiBaseUrl = Optional.empty(); - private static Optional vertexBaseUrl = Optional.empty(); - - /** Returns the default environment variables for the client. */ - static Map defaultEnvironmentVariables() { - Map variables = new HashMap<>(); - String value; - value = System.getenv("GOOGLE_GENAI_USE_VERTEXAI"); - if (value != null) { - variables.put("GOOGLE_GENAI_USE_VERTEXAI", value); - } - value = System.getenv("GOOGLE_GEMINI_BASE_URL"); - if (value != null) { - variables.put("GOOGLE_GEMINI_BASE_URL", value); - } - value = System.getenv("GOOGLE_VERTEX_BASE_URL"); - if (value != null) { - variables.put("GOOGLE_VERTEX_BASE_URL", value); - } - - return variables; - } /** Async class for GenAI. */ public final class Async { @@ -97,7 +73,6 @@ public static class Builder { private Optional httpOptions = Optional.empty(); private Optional vertexAI = Optional.empty(); private Optional debugConfig = Optional.empty(); - private Optional> environmentVariables = Optional.empty(); /** Builds the {@link Client} instance. */ public Client build() { @@ -109,8 +84,7 @@ public Client build() { httpOptions, clientOptions, vertexAI, - debugConfig, - environmentVariables); + debugConfig); } /** Sets the API key for Gemini API. */ @@ -178,13 +152,6 @@ Builder debugConfig(DebugConfig debugConfig) { this.debugConfig = Optional.of(debugConfig); return this; } - - /** Sets the environment variables for the API client. This is for internal use only. */ - @CanIgnoreReturnValue - Builder environmentVariables(Map environmentVariables) { - this.environmentVariables = Optional.of(environmentVariables); - return this; - } } /** Returns a {@link Builder} for {@link Client}. */ @@ -202,8 +169,7 @@ public Client() { /* httpOptions= */ Optional.empty(), /* clientOptions= */ Optional.empty(), /* vertexAI= */ Optional.empty(), - /* debugConfig= */ Optional.empty(), - /* environmentVariables= */ Optional.empty()); + /* debugConfig= */ Optional.empty()); } /** @@ -223,7 +189,6 @@ public Client() { * @param vertexAI Optional Boolean for whether to use Vertex AI APIs. If not specified here nor * in the environment variable, default to false. * @param debugConfig Optional {@link DebugConfig} for debugging or testing the Client. - * @param environmentVariables Optional Map of environment variables. * @throws IllegalArgumentException if the project/location and API key are set together. */ private Client( @@ -234,19 +199,15 @@ private Client( Optional httpOptions, Optional clientOptions, Optional vertexAI, - Optional debugConfig, - Optional> environmentVariables) { + Optional debugConfig) { checkNotNull(vertexAI, "vertexAI cannot be null"); checkNotNull(debugConfig, "debugConfig cannot be null"); - if (!environmentVariables.isPresent()) { - environmentVariables = Optional.of(defaultEnvironmentVariables()); - } boolean useVertexAI; if (vertexAI.isPresent()) { useVertexAI = vertexAI.get(); } else { - String envVar = environmentVariables.get().get("GOOGLE_GENAI_USE_VERTEXAI"); + String envVar = ApiClient.defaultEnvironmentVariables().get("GOOGLE_GENAI_USE_VERTEXAI"); useVertexAI = envVar != null && envVar.equalsIgnoreCase("true"); } @@ -265,15 +226,6 @@ private Client( throw new IllegalArgumentException("Vertex AI APIs do not support API key."); } - Optional baseUrl = Client.inferBaseUrl(useVertexAI, httpOptions, environmentVariables); - if (baseUrl.isPresent()) { - if (httpOptions.isPresent()) { - httpOptions = Optional.of(httpOptions.get().toBuilder().baseUrl(baseUrl.get()).build()); - } else { - httpOptions = Optional.of(HttpOptions.builder().baseUrl(baseUrl.get()).build()); - } - } - this.debugConfig = debugConfig.orElse(new DebugConfig()); if (this.debugConfig.clientMode().equals("replay")) { if (!useVertexAI) { @@ -347,7 +299,8 @@ public String apiKey() { return apiClient.apiKey(); } - protected void setReplayId(String replayId) { + /** Sets the replay ID for the replay client. For internal testing only. */ + void setReplayId(String replayId) { if (this.apiClient instanceof ReplayApiClient) { ((ReplayApiClient) this.apiClient).initializeReplaySession(replayId); } @@ -386,48 +339,21 @@ public void close() { } /** - * Overrides the base URLs for the Gemini API and Vertex AI API. + * Overrides the base URLs for the Gemini API and/or Vertex AI API. * *

Note: This function should be called before initializing the SDK. If the base URLs are set * after initializing the SDK, the base URLs will not be updated. - */ - public static void setDefaultBaseUrls( - Optional geminiBaseUrl, Optional vertexBaseUrl) { - Client.geminiBaseUrl = geminiBaseUrl; - Client.vertexBaseUrl = vertexBaseUrl; - } - - /** - * Returns the base URL for the Gemini API or Vertex AI API based on the following priority. + * + *

Precedence rule for base URL: * *

1. Base URL set via HttpOptions. * *

2. Base URL set via the latest call to setDefaultBaseUrls. * - *

3. Base URL set via environment variables. + *

3. Base URL set via environment variables GOOGLE_GEMINI_BASE_URL or GOOGLE_VERTEX_BASE_URL. */ - static Optional inferBaseUrl( - boolean vertexAI, - Optional httpOptions, - Optional> environmentVariables) { - if (httpOptions.isPresent() && httpOptions.get().baseUrl().isPresent()) { - return httpOptions.get().baseUrl(); - } - - if (vertexAI) { - if (Client.vertexBaseUrl.isPresent()) { - return Client.vertexBaseUrl; - } else if (environmentVariables.isPresent()) { - return Optional.ofNullable(environmentVariables.get().get("GOOGLE_VERTEX_BASE_URL")); - } - } else { - if (Client.geminiBaseUrl.isPresent()) { - return Client.geminiBaseUrl; - } else if (environmentVariables.isPresent()) { - return Optional.ofNullable(environmentVariables.get().get("GOOGLE_GEMINI_BASE_URL")); - } - } - - return Optional.empty(); + public static void setDefaultBaseUrls( + Optional geminiBaseUrl, Optional vertexBaseUrl) { + ApiClient.setDefaultBaseUrls(geminiBaseUrl, vertexBaseUrl); } } diff --git a/src/test/java/com/google/genai/AsyncOperationsTest.java b/src/test/java/com/google/genai/AsyncOperationsTest.java index 93041881b23..6db2f34b1c6 100644 --- a/src/test/java/com/google/genai/AsyncOperationsTest.java +++ b/src/test/java/com/google/genai/AsyncOperationsTest.java @@ -19,18 +19,25 @@ import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; +import com.google.common.collect.ImmutableMap; import com.google.genai.types.GenerateVideosConfig; import com.google.genai.types.GenerateVideosOperation; -import java.util.Optional; import java.util.concurrent.ExecutionException; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; +import org.mockito.MockedStatic; +import org.mockito.Mockito; @EnabledIfEnvironmentVariable( named = "GOOGLE_GENAI_REPLAYS_DIRECTORY", matches = ".*genai/replays.*") public class AsyncOperationsTest { + + private MockedStatic mockedStaticApiClient; + private Client createClient(boolean vertexAI, String replayId) { String clientMode = System.getenv("GOOGLE_GENAI_CLIENT_MODE"); DebugConfig debugConfig = @@ -38,19 +45,8 @@ private Client createClient(boolean vertexAI, String replayId) { clientMode == null ? "replay" : clientMode, "", System.getenv("GOOGLE_GENAI_REPLAYS_DIRECTORY")); - String apiKey = Optional.ofNullable(ApiClient.getApiKeyFromEnv()).orElse("api-key"); - String project = Optional.ofNullable(System.getenv("GOOGLE_GENAI_PROJECT")).orElse("project"); - String location = - Optional.ofNullable(System.getenv("GOOGLE_GENAI_LOCATION")).orElse("location"); - - Client.Builder clientBuilder = Client.builder().vertexAI(vertexAI).debugConfig(debugConfig); - if (vertexAI) { - clientBuilder.project(project).location(location); - } else { - clientBuilder.apiKey(apiKey); - } - Client client = clientBuilder.build(); + Client client = Client.builder().vertexAI(vertexAI).debugConfig(debugConfig).build(); if (client.clientMode().equals("replay")) { client.setReplayId(replayId); @@ -58,6 +54,32 @@ private Client createClient(boolean vertexAI, String replayId) { return client; } + @BeforeEach + public void setUp() { + String clientMode = System.getenv("GOOGLE_GENAI_CLIENT_MODE"); + if (clientMode != null && clientMode.equals("api")) { + // Don't mock the environment variables for the API test. + return; + } + mockedStaticApiClient = Mockito.mockStatic(ApiClient.class, Mockito.CALLS_REAL_METHODS); + // Mock the default environment variables to avoid reading the actual environment variables. + mockedStaticApiClient + .when(ApiClient::defaultEnvironmentVariables) + .thenReturn( + ImmutableMap.builder() + .put("apiKey", "api-key") + .put("project", "project") + .put("location", "location") + .build()); + } + + @AfterEach + public void tearDown() { + if (mockedStaticApiClient != null) { + mockedStaticApiClient.close(); + } + } + @ParameterizedTest @ValueSource(booleans = {false, true}) public void testAsyncGetVideosOperation(boolean vertexAI) diff --git a/src/test/java/com/google/genai/ClientTest.java b/src/test/java/com/google/genai/ClientTest.java index d7ee1fe8d99..552c6a8a85c 100644 --- a/src/test/java/com/google/genai/ClientTest.java +++ b/src/test/java/com/google/genai/ClientTest.java @@ -24,11 +24,16 @@ import static org.mockito.Mockito.when; import com.google.auth.oauth2.GoogleCredentials; +import com.google.common.collect.ImmutableMap; import com.google.genai.types.HttpOptions; import java.lang.reflect.Field; import java.util.Optional; import okhttp3.OkHttpClient; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.mockito.MockedStatic; +import org.mockito.Mockito; public class ClientTest { private static final String API_KEY = "api-key"; @@ -38,6 +43,22 @@ public class ClientTest { private static final DebugConfig DEBUG_CONFIG = new DebugConfig("replay", "replay-id", "replay-dir"); + private MockedStatic mockedStaticApiClient; + + @BeforeEach + public void setUp() { + mockedStaticApiClient = Mockito.mockStatic(ApiClient.class, Mockito.CALLS_REAL_METHODS); + // Mock the default environment variables to avoid reading the environment variables. + mockedStaticApiClient + .when(ApiClient::defaultEnvironmentVariables) + .thenReturn(ImmutableMap.of()); + } + + @AfterEach + public void tearDown() { + mockedStaticApiClient.close(); + } + @Test public void testInitClientFromBuilder_mldev() { // Act diff --git a/src/test/java/com/google/genai/DefaultValuesTest.java b/src/test/java/com/google/genai/DefaultValuesTest.java deleted file mode 100644 index 6f65bdf0d89..00000000000 --- a/src/test/java/com/google/genai/DefaultValuesTest.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright 2025 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.genai; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import com.google.genai.types.GenerateContentConfig; -import com.google.genai.types.GenerateContentResponse; -import java.lang.reflect.Field; -import java.util.Optional; -import okhttp3.MediaType; -import okhttp3.ResponseBody; -import org.junit.jupiter.api.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.Mockito; - -public class DefaultValuesTest { - @Test - public void testDefaultValues() throws Exception { - // Mocks and test setup. - ApiClient httpClientSpy = Mockito.spy(Mockito.mock(ApiClient.class)); - ApiResponse mockedResponse = Mockito.mock(ApiResponse.class); - when(httpClientSpy.request(anyString(), anyString(), anyString(), any())) - .thenReturn(mockedResponse); - GenerateContentResponse returnResponse = GenerateContentResponse.builder().build(); - ResponseBody content = - ResponseBody.create(MediaType.get("application/json"), returnResponse.toJson()); - when(mockedResponse.getBody()).thenReturn(content); - - String apiKey = Optional.ofNullable(ApiClient.getApiKeyFromEnv()).orElse("api-key"); - Client client = Client.builder().apiKey(apiKey).vertexAI(false).build(); - // Make the apiClient field public so that it can be spied on in the tests. This is a - // workaround for the fact that the ApiClient is a final class and cannot be spied on directly. - Field apiClientField = Models.class.getDeclaredField("apiClient"); - apiClientField.setAccessible(true); - apiClientField.set(client.models, httpClientSpy); - - GenerateContentResponse response = - client.models.generateContent("gemini-2.0-flash", "What is your name?", null); - - ArgumentCaptor argumentCaptor = ArgumentCaptor.forClass(String.class); - verify(httpClientSpy) - .request( - argumentCaptor.capture(), argumentCaptor.capture(), argumentCaptor.capture(), any()); - GenerateContentConfig spiedConfig = - GenerateContentConfig.fromJson(argumentCaptor.getAllValues().get(2)); - - // Assert that the temperature and candidateCount fields are not set when not passed via config. - assertEquals(spiedConfig.audioTimestamp(), Optional.empty()); - assertEquals(spiedConfig.cachedContent(), Optional.empty()); - assertEquals(spiedConfig.candidateCount(), Optional.empty()); - assertEquals(spiedConfig.frequencyPenalty(), Optional.empty()); - assertEquals(spiedConfig.logprobs(), Optional.empty()); - assertEquals(spiedConfig.maxOutputTokens(), Optional.empty()); - assertEquals(spiedConfig.mediaResolution(), Optional.empty()); - assertEquals(spiedConfig.presencePenalty(), Optional.empty()); - assertEquals(spiedConfig.responseLogprobs(), Optional.empty()); - assertEquals(spiedConfig.responseModalities(), Optional.empty()); - assertEquals(spiedConfig.responseMimeType(), Optional.empty()); - assertEquals(spiedConfig.responseSchema(), Optional.empty()); - assertEquals(spiedConfig.routingConfig(), Optional.empty()); - assertEquals(spiedConfig.safetySettings(), Optional.empty()); - assertEquals(spiedConfig.seed(), Optional.empty()); - assertEquals(spiedConfig.stopSequences(), Optional.empty()); - assertEquals(spiedConfig.speechConfig(), Optional.empty()); - assertEquals(spiedConfig.temperature(), Optional.empty()); - assertEquals(spiedConfig.thinkingConfig(), Optional.empty()); - assertEquals(spiedConfig.tools(), Optional.empty()); - assertEquals(spiedConfig.toolConfig(), Optional.empty()); - assertEquals(spiedConfig.topK(), Optional.empty()); - assertEquals(spiedConfig.topP(), Optional.empty()); - } -} diff --git a/src/test/java/com/google/genai/HttpApiClientTest.java b/src/test/java/com/google/genai/HttpApiClientTest.java index fb973905f58..a8e6eadd69a 100644 --- a/src/test/java/com/google/genai/HttpApiClientTest.java +++ b/src/test/java/com/google/genai/HttpApiClientTest.java @@ -52,9 +52,12 @@ import okhttp3.Response; import okhttp3.ResponseBody; import okio.Buffer; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mockito.ArgumentCaptor; import org.mockito.Mock; +import org.mockito.MockedStatic; import org.mockito.Mockito; public class HttpApiClientTest { @@ -76,9 +79,25 @@ public class HttpApiClientTest { private static final String TEST_PATH = "test-path"; private static final String TEST_REQUEST_JSON = "{\"test\": \"request-json\"}"; + private MockedStatic mockedStaticApiClient; + @Mock OkHttpClient mockHttpClient; @Mock Call mockCall; + @BeforeEach + public void setUp() { + mockedStaticApiClient = Mockito.mockStatic(ApiClient.class, Mockito.CALLS_REAL_METHODS); + // Mock the default environment variables to avoid reading the environment variables. + mockedStaticApiClient + .when(ApiClient::defaultEnvironmentVariables) + .thenReturn(ImmutableMap.of()); + } + + @AfterEach + public void tearDown() { + mockedStaticApiClient.close(); + } + private void setMockClient(HttpApiClient client) throws Exception { mockHttpClient = Mockito.mock(OkHttpClient.class); mockCall = Mockito.mock(Call.class); @@ -648,18 +667,14 @@ public void testClientInitializationWithBaseUrlFromSetBaseUrls() throws Exceptio } @Test - public void testClientInitializationWithBaseUrlFromSetBaseUrlsOverridesEnvironment() + public void testGeminiClientInitializationWithBaseUrlFromSetBaseUrlsOverridesEnvironment() throws Exception { + mockedStaticApiClient + .when(ApiClient::defaultEnvironmentVariables) + .thenReturn(ImmutableMap.of("geminiBaseUrl", "https://gemini-base-url.googleapis.com/")); Client.setDefaultBaseUrls( Optional.of("https://custom-base-url.googleapis.com/"), Optional.empty()); - Client client = - Client.builder() - .apiKey(API_KEY) - .vertexAI(false) - .environmentVariables( - ImmutableMap.of( - "GOOGLE_GEMINI_BASE_URL", "https://gemini-base-url.googleapis.com/")) - .build(); + Client client = Client.builder().apiKey(API_KEY).vertexAI(false).build(); assertTrue(client.baseUrl().isPresent()); assertEquals(client.baseUrl().get(), "https://custom-base-url.googleapis.com/"); @@ -668,15 +683,38 @@ public void testClientInitializationWithBaseUrlFromSetBaseUrlsOverridesEnvironme } @Test - public void testClientInitializationWithBaseUrlFromEnvironment() throws Exception { - Client client = - Client.builder() - .apiKey(API_KEY) - .vertexAI(false) - .environmentVariables( - ImmutableMap.of( - "GOOGLE_GEMINI_BASE_URL", "https://custom-base-url.googleapis.com/")) - .build(); + public void testVertexClientInitializationWithBaseUrlFromSetBaseUrlsOverridesEnvironment() + throws Exception { + mockedStaticApiClient + .when(ApiClient::defaultEnvironmentVariables) + .thenReturn(ImmutableMap.of("vertexBaseUrl", "https://vertex-base-url.googleapis.com/")); + Client.setDefaultBaseUrls( + Optional.empty(), Optional.of("https://custom-base-url.googleapis.com/")); + Client client = Client.builder().project(PROJECT).location(LOCATION).vertexAI(true).build(); + + assertTrue(client.baseUrl().isPresent()); + assertEquals(client.baseUrl().get(), "https://custom-base-url.googleapis.com/"); + + Client.setDefaultBaseUrls(Optional.empty(), Optional.empty()); + } + + @Test + public void testGeminiClientInitializationWithBaseUrlFromEnvironment() throws Exception { + mockedStaticApiClient + .when(ApiClient::defaultEnvironmentVariables) + .thenReturn(ImmutableMap.of("geminiBaseUrl", "https://custom-base-url.googleapis.com/")); + Client client = Client.builder().apiKey(API_KEY).vertexAI(false).build(); + + assertTrue(client.baseUrl().isPresent()); + assertEquals(client.baseUrl().get(), "https://custom-base-url.googleapis.com/"); + } + + @Test + public void testVertexClientInitializationWithBaseUrlFromEnvironment() throws Exception { + mockedStaticApiClient + .when(ApiClient::defaultEnvironmentVariables) + .thenReturn(ImmutableMap.of("vertexBaseUrl", "https://custom-base-url.googleapis.com/")); + Client client = Client.builder().project(PROJECT).location(LOCATION).vertexAI(true).build(); assertTrue(client.baseUrl().isPresent()); assertEquals(client.baseUrl().get(), "https://custom-base-url.googleapis.com/"); diff --git a/src/test/java/com/google/genai/ModelsTest.java b/src/test/java/com/google/genai/ModelsTest.java index aa7126c88cd..0049c7e0ef9 100644 --- a/src/test/java/com/google/genai/ModelsTest.java +++ b/src/test/java/com/google/genai/ModelsTest.java @@ -51,10 +51,13 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.util.Arrays; -import java.util.Optional; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; +import org.mockito.MockedStatic; +import org.mockito.Mockito; @EnabledIfEnvironmentVariable( named = "GOOGLE_GENAI_REPLAYS_DIRECTORY", @@ -65,7 +68,8 @@ public class ModelsTest { private static final String EMBEDDING_MODEL_NAME = "text-embedding-004"; private static final String IMAGEN_CAPABILITY_MODEL_NAME = "imagen-3.0-capability-001"; - /** Creates a client for the given Vertex AI flag and replay ID. */ + private MockedStatic mockedStaticApiClient; + private Client createClient(boolean vertexAI, String replayId) { String clientMode = System.getenv("GOOGLE_GENAI_CLIENT_MODE"); DebugConfig debugConfig = @@ -73,19 +77,8 @@ private Client createClient(boolean vertexAI, String replayId) { clientMode == null ? "replay" : clientMode, "", System.getenv("GOOGLE_GENAI_REPLAYS_DIRECTORY")); - String apiKey = Optional.ofNullable(ApiClient.getApiKeyFromEnv()).orElse("api-key"); - String project = Optional.ofNullable(System.getenv("GOOGLE_GENAI_PROJECT")).orElse("project"); - String location = - Optional.ofNullable(System.getenv("GOOGLE_GENAI_LOCATION")).orElse("location"); - Client.Builder clientBuilder = Client.builder().vertexAI(vertexAI).debugConfig(debugConfig); - - if (vertexAI) { - clientBuilder.project(project).location(location); - } else { - clientBuilder.apiKey(apiKey); - } - Client client = clientBuilder.build(); + Client client = Client.builder().vertexAI(vertexAI).debugConfig(debugConfig).build(); if (client.clientMode().equals("replay")) { client.setReplayId(replayId); @@ -93,6 +86,32 @@ private Client createClient(boolean vertexAI, String replayId) { return client; } + @BeforeEach + public void setUp() { + String clientMode = System.getenv("GOOGLE_GENAI_CLIENT_MODE"); + if (clientMode != null && clientMode.equals("api")) { + // Don't mock the environment variables for the API test. + return; + } + mockedStaticApiClient = Mockito.mockStatic(ApiClient.class, Mockito.CALLS_REAL_METHODS); + // Mock the default environment variables to avoid reading the actual environment variables. + mockedStaticApiClient + .when(ApiClient::defaultEnvironmentVariables) + .thenReturn( + ImmutableMap.builder() + .put("apiKey", "api-key") + .put("project", "project") + .put("location", "location") + .build()); + } + + @AfterEach + public void tearDown() { + if (mockedStaticApiClient != null) { + mockedStaticApiClient.close(); + } + } + /** Creates a raw reference image for edit image tests. */ private RawReferenceImage createRawReferenceImage() throws Exception { URL resourceUrl = getClass().getClassLoader().getResource("google.png"); diff --git a/src/test/java/com/google/genai/OperationsTest.java b/src/test/java/com/google/genai/OperationsTest.java index 73036c3548c..1b250a452ba 100644 --- a/src/test/java/com/google/genai/OperationsTest.java +++ b/src/test/java/com/google/genai/OperationsTest.java @@ -19,16 +19,23 @@ import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; +import com.google.common.collect.ImmutableMap; import com.google.genai.types.GenerateVideosOperation; -import java.util.Optional; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; +import org.mockito.MockedStatic; +import org.mockito.Mockito; @EnabledIfEnvironmentVariable( named = "GOOGLE_GENAI_REPLAYS_DIRECTORY", matches = ".*genai/replays.*") public class OperationsTest { + + private MockedStatic mockedStaticApiClient; + private Client createClient(boolean vertexAI, String replayId) { String clientMode = System.getenv("GOOGLE_GENAI_CLIENT_MODE"); DebugConfig debugConfig = @@ -36,19 +43,8 @@ private Client createClient(boolean vertexAI, String replayId) { clientMode == null ? "replay" : clientMode, "", System.getenv("GOOGLE_GENAI_REPLAYS_DIRECTORY")); - String apiKey = Optional.ofNullable(ApiClient.getApiKeyFromEnv()).orElse("api-key"); - String project = Optional.ofNullable(System.getenv("GOOGLE_GENAI_PROJECT")).orElse("project"); - String location = - Optional.ofNullable(System.getenv("GOOGLE_GENAI_LOCATION")).orElse("location"); - - Client.Builder clientBuilder = Client.builder().vertexAI(vertexAI).debugConfig(debugConfig); - if (vertexAI) { - clientBuilder.project(project).location(location); - } else { - clientBuilder.apiKey(apiKey); - } - Client client = clientBuilder.build(); + Client client = Client.builder().vertexAI(vertexAI).debugConfig(debugConfig).build(); if (client.clientMode().equals("replay")) { client.setReplayId(replayId); @@ -56,6 +52,32 @@ private Client createClient(boolean vertexAI, String replayId) { return client; } + @BeforeEach + public void setUp() { + String clientMode = System.getenv("GOOGLE_GENAI_CLIENT_MODE"); + if (clientMode != null && clientMode.equals("api")) { + // Don't mock the environment variables for the API test. + return; + } + mockedStaticApiClient = Mockito.mockStatic(ApiClient.class, Mockito.CALLS_REAL_METHODS); + // Mock the default environment variables to avoid reading the actual environment variables. + mockedStaticApiClient + .when(ApiClient::defaultEnvironmentVariables) + .thenReturn( + ImmutableMap.builder() + .put("apiKey", "api-key") + .put("project", "project") + .put("location", "location") + .build()); + } + + @AfterEach + public void tearDown() { + if (mockedStaticApiClient != null) { + mockedStaticApiClient.close(); + } + } + @ParameterizedTest @ValueSource(booleans = {false, true}) public void testGetVideosOperation(boolean vertexAI) throws Exception { diff --git a/src/test/java/com/google/genai/TableTest.java b/src/test/java/com/google/genai/TableTest.java index 48b144de895..63e0fc689b9 100644 --- a/src/test/java/com/google/genai/TableTest.java +++ b/src/test/java/com/google/genai/TableTest.java @@ -19,6 +19,7 @@ import static org.junit.jupiter.api.Assertions.fail; +import com.google.common.collect.ImmutableMap; import com.google.genai.types.TestTableFile; import com.google.genai.types.TestTableItem; import java.io.IOException; @@ -38,6 +39,8 @@ import org.junit.jupiter.api.DynamicTest; import org.junit.jupiter.api.TestFactory; import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable; +import org.mockito.MockedStatic; +import org.mockito.Mockito; /** Sample class to prototype GenAI SDK functionalities. */ public final class TableTest { @@ -144,9 +147,6 @@ private static Collection createTestCases( } // Edit image ReferenceImages are not correctly deserialized for replay tests if (testName.contains("models.edit_image") - || testName.contains("models.generate_content.test_speech_with_config") - || testName.contains( - "models.generate_content.test_logprobs_zero_with_response_logprobs_true") || testName.contains("batches.create.test_with_image_blob")) { // TODO(b/431798111) String msg = " => Test skipped: replay tests are not supported for edit_image"; return Collections.singletonList(DynamicTest.dynamicTest(testName + msg, () -> {})); @@ -315,19 +315,28 @@ static Client createClient(boolean vertexAI) { replayMode = "replay"; } DebugConfig debugConfig = new DebugConfig(replayMode, "", testsReplaysPath); - String apiKey = Optional.ofNullable(ApiClient.getApiKeyFromEnv()).orElse("api-key"); - String project = Optional.ofNullable(System.getenv("GOOGLE_GENAI_PROJECT")).orElse("project"); - String location = - Optional.ofNullable(System.getenv("GOOGLE_GENAI_LOCATION")).orElse("location"); - Client.Builder clientBuilder = Client.builder().vertexAI(vertexAI).debugConfig(debugConfig); + if (replayMode.equals("replay")) { + // Mock the default environment variables to avoid reading the actual environment variables in + // replay mode. + MockedStatic mockedStaticApiClient = + Mockito.mockStatic(ApiClient.class, Mockito.CALLS_REAL_METHODS); + // Mock the default environment variables to avoid reading the actual environment variables. + mockedStaticApiClient + .when(ApiClient::defaultEnvironmentVariables) + .thenReturn( + ImmutableMap.builder() + .put("apiKey", "api-key") + .put("project", "project") + .put("location", "location") + .build()); - if (vertexAI) { - clientBuilder.project(project).location(location); - } else { - clientBuilder.apiKey(apiKey); + Client client = Client.builder().vertexAI(vertexAI).debugConfig(debugConfig).build(); + mockedStaticApiClient.close(); + return client; } - return clientBuilder.build(); + + return Client.builder().vertexAI(vertexAI).debugConfig(debugConfig).build(); } private static Object normalizeKeys(Object data) { From 1a8ce81b4dd8c0ad03101eab4aed3a426a1c2a37 Mon Sep 17 00:00:00 2001 From: Jaycee Li Date: Fri, 18 Jul 2025 11:13:41 -0700 Subject: [PATCH 092/602] chore: Reuse methods and mocks in tests PiperOrigin-RevId: 784641220 --- .../com/google/genai/AsyncOperationsTest.java | 55 +------------ .../java/com/google/genai/ClientTest.java | 23 +----- .../EnvironmentVariablesMockingExtension.java | 81 +++++++++++++++++++ .../com/google/genai/HttpApiClientTest.java | 34 +++----- .../java/com/google/genai/ModelsTest.java | 81 +++++-------------- .../java/com/google/genai/OperationsTest.java | 53 +----------- src/test/java/com/google/genai/TestUtils.java | 49 +++++++++++ 7 files changed, 169 insertions(+), 207 deletions(-) create mode 100644 src/test/java/com/google/genai/EnvironmentVariablesMockingExtension.java create mode 100644 src/test/java/com/google/genai/TestUtils.java diff --git a/src/test/java/com/google/genai/AsyncOperationsTest.java b/src/test/java/com/google/genai/AsyncOperationsTest.java index 6db2f34b1c6..65ef52139b1 100644 --- a/src/test/java/com/google/genai/AsyncOperationsTest.java +++ b/src/test/java/com/google/genai/AsyncOperationsTest.java @@ -19,67 +19,20 @@ import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; -import com.google.common.collect.ImmutableMap; import com.google.genai.types.GenerateVideosConfig; import com.google.genai.types.GenerateVideosOperation; import java.util.concurrent.ExecutionException; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable; +import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; -import org.mockito.MockedStatic; -import org.mockito.Mockito; @EnabledIfEnvironmentVariable( named = "GOOGLE_GENAI_REPLAYS_DIRECTORY", matches = ".*genai/replays.*") +@ExtendWith(EnvironmentVariablesMockingExtension.class) public class AsyncOperationsTest { - private MockedStatic mockedStaticApiClient; - - private Client createClient(boolean vertexAI, String replayId) { - String clientMode = System.getenv("GOOGLE_GENAI_CLIENT_MODE"); - DebugConfig debugConfig = - new DebugConfig( - clientMode == null ? "replay" : clientMode, - "", - System.getenv("GOOGLE_GENAI_REPLAYS_DIRECTORY")); - - Client client = Client.builder().vertexAI(vertexAI).debugConfig(debugConfig).build(); - - if (client.clientMode().equals("replay")) { - client.setReplayId(replayId); - } - return client; - } - - @BeforeEach - public void setUp() { - String clientMode = System.getenv("GOOGLE_GENAI_CLIENT_MODE"); - if (clientMode != null && clientMode.equals("api")) { - // Don't mock the environment variables for the API test. - return; - } - mockedStaticApiClient = Mockito.mockStatic(ApiClient.class, Mockito.CALLS_REAL_METHODS); - // Mock the default environment variables to avoid reading the actual environment variables. - mockedStaticApiClient - .when(ApiClient::defaultEnvironmentVariables) - .thenReturn( - ImmutableMap.builder() - .put("apiKey", "api-key") - .put("project", "project") - .put("location", "location") - .build()); - } - - @AfterEach - public void tearDown() { - if (mockedStaticApiClient != null) { - mockedStaticApiClient.close(); - } - } - @ParameterizedTest @ValueSource(booleans = {false, true}) public void testAsyncGetVideosOperation(boolean vertexAI) @@ -87,7 +40,7 @@ public void testAsyncGetVideosOperation(boolean vertexAI) // Arrange String suffix = vertexAI ? "vertex" : "mldev"; Client client = - createClient( + TestUtils.createClient( vertexAI, "tests/models/generate_videos/test_create_operation_to_poll." + suffix + ".json"); @@ -132,7 +85,7 @@ public void testTextToVideoPollAsync(boolean vertexAI) // Arrange String suffix = vertexAI ? "vertex" : "mldev"; Client client = - createClient( + TestUtils.createClient( vertexAI, "tests/models/generate_videos/test_text_to_video_poll_async." + suffix + ".json"); diff --git a/src/test/java/com/google/genai/ClientTest.java b/src/test/java/com/google/genai/ClientTest.java index 552c6a8a85c..5fe333dbd58 100644 --- a/src/test/java/com/google/genai/ClientTest.java +++ b/src/test/java/com/google/genai/ClientTest.java @@ -24,17 +24,14 @@ import static org.mockito.Mockito.when; import com.google.auth.oauth2.GoogleCredentials; -import com.google.common.collect.ImmutableMap; import com.google.genai.types.HttpOptions; import java.lang.reflect.Field; import java.util.Optional; import okhttp3.OkHttpClient; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.mockito.MockedStatic; -import org.mockito.Mockito; +import org.junit.jupiter.api.extension.ExtendWith; +@ExtendWith(EnvironmentVariablesMockingExtension.class) public class ClientTest { private static final String API_KEY = "api-key"; private static final String PROJECT = "project"; @@ -43,22 +40,6 @@ public class ClientTest { private static final DebugConfig DEBUG_CONFIG = new DebugConfig("replay", "replay-id", "replay-dir"); - private MockedStatic mockedStaticApiClient; - - @BeforeEach - public void setUp() { - mockedStaticApiClient = Mockito.mockStatic(ApiClient.class, Mockito.CALLS_REAL_METHODS); - // Mock the default environment variables to avoid reading the environment variables. - mockedStaticApiClient - .when(ApiClient::defaultEnvironmentVariables) - .thenReturn(ImmutableMap.of()); - } - - @AfterEach - public void tearDown() { - mockedStaticApiClient.close(); - } - @Test public void testInitClientFromBuilder_mldev() { // Act diff --git a/src/test/java/com/google/genai/EnvironmentVariablesMockingExtension.java b/src/test/java/com/google/genai/EnvironmentVariablesMockingExtension.java new file mode 100644 index 00000000000..2bf9c904070 --- /dev/null +++ b/src/test/java/com/google/genai/EnvironmentVariablesMockingExtension.java @@ -0,0 +1,81 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.genai; + +import com.google.common.collect.ImmutableMap; +import org.junit.jupiter.api.extension.AfterEachCallback; +import org.junit.jupiter.api.extension.BeforeEachCallback; +import org.junit.jupiter.api.extension.ExtensionContext; +import org.junit.jupiter.api.extension.ExtensionContext.Namespace; +import org.junit.jupiter.api.extension.ExtensionContext.Store; +import org.junit.jupiter.api.extension.ParameterContext; +import org.junit.jupiter.api.extension.ParameterResolver; +import org.mockito.MockedStatic; +import org.mockito.Mockito; + +/** + * Extension that mocks the default environment variables in the ApiClient class. + * + *

This extension is used to mock the default environment variables in the ApiClient class in + * order to avoid reading the actual environment variables in replay mode. + */ +public class EnvironmentVariablesMockingExtension + implements BeforeEachCallback, AfterEachCallback, ParameterResolver { + + private static final Namespace NAMESPACE = + Namespace.create(EnvironmentVariablesMockingExtension.class); + private static final String MOCKED_STATIC_KEY = "mockedStaticApiClient"; + + @Override + public void beforeEach(ExtensionContext context) throws Exception { + String clientMode = System.getenv("GOOGLE_GENAI_CLIENT_MODE"); + if (clientMode != null && clientMode.equals("api")) { + return; + } + + MockedStatic mockedStatic = + Mockito.mockStatic(ApiClient.class, Mockito.CALLS_REAL_METHODS); + + mockedStatic.when(ApiClient::defaultEnvironmentVariables).thenReturn(ImmutableMap.of()); + + getStore(context).put(MOCKED_STATIC_KEY, mockedStatic); + } + + @Override + public void afterEach(ExtensionContext context) throws Exception { + MockedStatic mockedStatic = getStore(context).remove(MOCKED_STATIC_KEY, MockedStatic.class); + if (mockedStatic != null) { + mockedStatic.close(); + } + } + + @Override + public boolean supportsParameter( + ParameterContext parameterContext, ExtensionContext extensionContext) { + return parameterContext.getParameter().getType() == MockedStatic.class; + } + + @Override + public Object resolveParameter( + ParameterContext parameterContext, ExtensionContext extensionContext) { + return getStore(extensionContext).get(MOCKED_STATIC_KEY, MockedStatic.class); + } + + private Store getStore(ExtensionContext context) { + return context.getStore(Namespace.create(context.getRequiredTestMethod())); + } +} diff --git a/src/test/java/com/google/genai/HttpApiClientTest.java b/src/test/java/com/google/genai/HttpApiClientTest.java index a8e6eadd69a..cd7a973c13f 100644 --- a/src/test/java/com/google/genai/HttpApiClientTest.java +++ b/src/test/java/com/google/genai/HttpApiClientTest.java @@ -52,14 +52,14 @@ import okhttp3.Response; import okhttp3.ResponseBody; import okio.Buffer; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.MockedStatic; import org.mockito.Mockito; +@ExtendWith(EnvironmentVariablesMockingExtension.class) public class HttpApiClientTest { private static final String API_KEY = "api-key"; @@ -79,25 +79,9 @@ public class HttpApiClientTest { private static final String TEST_PATH = "test-path"; private static final String TEST_REQUEST_JSON = "{\"test\": \"request-json\"}"; - private MockedStatic mockedStaticApiClient; - @Mock OkHttpClient mockHttpClient; @Mock Call mockCall; - @BeforeEach - public void setUp() { - mockedStaticApiClient = Mockito.mockStatic(ApiClient.class, Mockito.CALLS_REAL_METHODS); - // Mock the default environment variables to avoid reading the environment variables. - mockedStaticApiClient - .when(ApiClient::defaultEnvironmentVariables) - .thenReturn(ImmutableMap.of()); - } - - @AfterEach - public void tearDown() { - mockedStaticApiClient.close(); - } - private void setMockClient(HttpApiClient client) throws Exception { mockHttpClient = Mockito.mock(OkHttpClient.class); mockCall = Mockito.mock(Call.class); @@ -667,8 +651,8 @@ public void testClientInitializationWithBaseUrlFromSetBaseUrls() throws Exceptio } @Test - public void testGeminiClientInitializationWithBaseUrlFromSetBaseUrlsOverridesEnvironment() - throws Exception { + public void testGeminiClientInitializationWithBaseUrlFromSetBaseUrlsOverridesEnvironment( + MockedStatic mockedStaticApiClient) throws Exception { mockedStaticApiClient .when(ApiClient::defaultEnvironmentVariables) .thenReturn(ImmutableMap.of("geminiBaseUrl", "https://gemini-base-url.googleapis.com/")); @@ -683,8 +667,8 @@ public void testGeminiClientInitializationWithBaseUrlFromSetBaseUrlsOverridesEnv } @Test - public void testVertexClientInitializationWithBaseUrlFromSetBaseUrlsOverridesEnvironment() - throws Exception { + public void testVertexClientInitializationWithBaseUrlFromSetBaseUrlsOverridesEnvironment( + MockedStatic mockedStaticApiClient) throws Exception { mockedStaticApiClient .when(ApiClient::defaultEnvironmentVariables) .thenReturn(ImmutableMap.of("vertexBaseUrl", "https://vertex-base-url.googleapis.com/")); @@ -699,7 +683,8 @@ public void testVertexClientInitializationWithBaseUrlFromSetBaseUrlsOverridesEnv } @Test - public void testGeminiClientInitializationWithBaseUrlFromEnvironment() throws Exception { + public void testGeminiClientInitializationWithBaseUrlFromEnvironment( + MockedStatic mockedStaticApiClient) throws Exception { mockedStaticApiClient .when(ApiClient::defaultEnvironmentVariables) .thenReturn(ImmutableMap.of("geminiBaseUrl", "https://custom-base-url.googleapis.com/")); @@ -710,7 +695,8 @@ public void testGeminiClientInitializationWithBaseUrlFromEnvironment() throws Ex } @Test - public void testVertexClientInitializationWithBaseUrlFromEnvironment() throws Exception { + public void testVertexClientInitializationWithBaseUrlFromEnvironment( + MockedStatic mockedStaticApiClient) throws Exception { mockedStaticApiClient .when(ApiClient::defaultEnvironmentVariables) .thenReturn(ImmutableMap.of("vertexBaseUrl", "https://custom-base-url.googleapis.com/")); diff --git a/src/test/java/com/google/genai/ModelsTest.java b/src/test/java/com/google/genai/ModelsTest.java index 0049c7e0ef9..ecae6a390c5 100644 --- a/src/test/java/com/google/genai/ModelsTest.java +++ b/src/test/java/com/google/genai/ModelsTest.java @@ -51,67 +51,21 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.util.Arrays; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable; +import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; -import org.mockito.MockedStatic; -import org.mockito.Mockito; @EnabledIfEnvironmentVariable( named = "GOOGLE_GENAI_REPLAYS_DIRECTORY", matches = ".*genai/replays.*") +@ExtendWith(EnvironmentVariablesMockingExtension.class) public class ModelsTest { private static final String GEMINI_MODEL_NAME = "gemini-1.5-flash"; private static final String EMBEDDING_MODEL_NAME = "text-embedding-004"; private static final String IMAGEN_CAPABILITY_MODEL_NAME = "imagen-3.0-capability-001"; - private MockedStatic mockedStaticApiClient; - - private Client createClient(boolean vertexAI, String replayId) { - String clientMode = System.getenv("GOOGLE_GENAI_CLIENT_MODE"); - DebugConfig debugConfig = - new DebugConfig( - clientMode == null ? "replay" : clientMode, - "", - System.getenv("GOOGLE_GENAI_REPLAYS_DIRECTORY")); - - Client client = Client.builder().vertexAI(vertexAI).debugConfig(debugConfig).build(); - - if (client.clientMode().equals("replay")) { - client.setReplayId(replayId); - } - return client; - } - - @BeforeEach - public void setUp() { - String clientMode = System.getenv("GOOGLE_GENAI_CLIENT_MODE"); - if (clientMode != null && clientMode.equals("api")) { - // Don't mock the environment variables for the API test. - return; - } - mockedStaticApiClient = Mockito.mockStatic(ApiClient.class, Mockito.CALLS_REAL_METHODS); - // Mock the default environment variables to avoid reading the actual environment variables. - mockedStaticApiClient - .when(ApiClient::defaultEnvironmentVariables) - .thenReturn( - ImmutableMap.builder() - .put("apiKey", "api-key") - .put("project", "project") - .put("location", "location") - .build()); - } - - @AfterEach - public void tearDown() { - if (mockedStaticApiClient != null) { - mockedStaticApiClient.close(); - } - } - /** Creates a raw reference image for edit image tests. */ private RawReferenceImage createRawReferenceImage() throws Exception { URL resourceUrl = getClass().getClassLoader().getResource("google.png"); @@ -176,7 +130,8 @@ public void testGenerateContent_withContent(boolean vertexAI) throws Exception { // Arrange String suffix = vertexAI ? "vertex" : "mldev"; Client client = - createClient(vertexAI, "tests/models/generate_content/test_sync." + suffix + ".json"); + TestUtils.createClient( + vertexAI, "tests/models/generate_content/test_sync." + suffix + ".json"); // Act GenerateContentResponse response = @@ -195,7 +150,7 @@ public void testGenerateContentStream_withText(boolean vertexAI) throws Exceptio // Arrange String suffix = vertexAI ? "vertex" : "mldev"; Client client = - createClient( + TestUtils.createClient( vertexAI, "tests/models/generate_content/test_sync_stream." + suffix + ".json"); // Act @@ -223,7 +178,7 @@ public void testGenerateContentStream_withContentAndConfig(boolean vertexAI) thr // Arrange String suffix = vertexAI ? "vertex" : "mldev"; Client client = - createClient( + TestUtils.createClient( vertexAI, "tests/models/generate_content/test_simple_shared_generation_config_stream." + suffix @@ -262,7 +217,8 @@ public void testEmbedContent_withText(boolean vertexAI) throws Exception { // Arrange String suffix = vertexAI ? "vertex" : "mldev"; Client client = - createClient(vertexAI, "tests/models/embed_content/test_single_text." + suffix + ".json"); + TestUtils.createClient( + vertexAI, "tests/models/embed_content/test_single_text." + suffix + ".json"); // Act EmbedContentResponse response = @@ -279,7 +235,7 @@ public void testEmbedContent_withListOfTexts(boolean vertexAI) throws Exception // Arrange String suffix = vertexAI ? "vertex" : "mldev"; Client client = - createClient( + TestUtils.createClient( vertexAI, "tests/models/embed_content/test_multi_texts_with_config." + suffix + ".json"); @@ -306,7 +262,8 @@ public void testCountTokens_withText(boolean vertexAI) throws Exception { // Arrange String suffix = vertexAI ? "vertex" : "mldev"; Client client = - createClient(vertexAI, "tests/models/count_tokens/test_count_tokens." + suffix + ".json"); + TestUtils.createClient( + vertexAI, "tests/models/count_tokens/test_count_tokens." + suffix + ".json"); // Act CountTokensResponse response = @@ -326,7 +283,7 @@ public void testComputeTokens_withText(boolean vertexAI) throws Exception { // Arrange String suffix = vertexAI ? "vertex" : "mldev"; Client client = - createClient( + TestUtils.createClient( vertexAI, "tests/models/compute_tokens/test_compute_tokens." + suffix + ".json"); // Act @@ -343,7 +300,8 @@ public void testListModels(boolean vertexAI) throws Exception { // Arrange String suffix = vertexAI ? "vertex" : "mldev"; Client client = - createClient(vertexAI, "tests/models/list/test_base_models_pager." + suffix + ".json"); + TestUtils.createClient( + vertexAI, "tests/models/list/test_base_models_pager." + suffix + ".json"); // Act Pager pager = @@ -366,7 +324,8 @@ public void testListModel_filterThrowException(boolean vertexAI) throws Exceptio // Arrange String suffix = vertexAI ? "vertex" : "mldev"; Client client = - createClient(vertexAI, "tests/models/list/test_base_models_pager." + suffix + ".json"); + TestUtils.createClient( + vertexAI, "tests/models/list/test_base_models_pager." + suffix + ".json"); // Act IllegalArgumentException exception = @@ -384,7 +343,7 @@ public void testEditImage_withMaskReference(boolean vertexAI) throws Exception { // Arrange String suffix = vertexAI ? "vertex" : "mldev"; Client client = - createClient( + TestUtils.createClient( vertexAI, "tests/models/edit_image/test_edit_mask_inpaint_insert." + suffix + ".json"); EditImageConfig config = @@ -436,7 +395,7 @@ public void testEditImage_withControlReference(boolean vertexAI) throws Exceptio // Arrange String suffix = vertexAI ? "vertex" : "mldev"; Client client = - createClient( + TestUtils.createClient( vertexAI, "tests/models/edit_image/test_edit_control_user_provided." + suffix + ".json"); @@ -480,7 +439,7 @@ public void testEditImage_withSubjectReference(boolean vertexAI) throws Exceptio // Arrange String suffix = vertexAI ? "vertex" : "mldev"; Client client = - createClient( + TestUtils.createClient( vertexAI, "tests/models/edit_image/test_edit_subject_image_customization." + suffix + ".json"); @@ -526,7 +485,7 @@ public void testEditImage_withStyleTransfer(boolean vertexAI) throws Exception { // Arrange String suffix = vertexAI ? "vertex" : "mldev"; Client client = - createClient( + TestUtils.createClient( vertexAI, "tests/models/edit_image/test_edit_style_reference_image_customization." + suffix diff --git a/src/test/java/com/google/genai/OperationsTest.java b/src/test/java/com/google/genai/OperationsTest.java index 1b250a452ba..bdcb054a9cf 100644 --- a/src/test/java/com/google/genai/OperationsTest.java +++ b/src/test/java/com/google/genai/OperationsTest.java @@ -19,72 +19,25 @@ import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; -import com.google.common.collect.ImmutableMap; import com.google.genai.types.GenerateVideosOperation; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable; +import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; -import org.mockito.MockedStatic; -import org.mockito.Mockito; @EnabledIfEnvironmentVariable( named = "GOOGLE_GENAI_REPLAYS_DIRECTORY", matches = ".*genai/replays.*") +@ExtendWith(EnvironmentVariablesMockingExtension.class) public class OperationsTest { - private MockedStatic mockedStaticApiClient; - - private Client createClient(boolean vertexAI, String replayId) { - String clientMode = System.getenv("GOOGLE_GENAI_CLIENT_MODE"); - DebugConfig debugConfig = - new DebugConfig( - clientMode == null ? "replay" : clientMode, - "", - System.getenv("GOOGLE_GENAI_REPLAYS_DIRECTORY")); - - Client client = Client.builder().vertexAI(vertexAI).debugConfig(debugConfig).build(); - - if (client.clientMode().equals("replay")) { - client.setReplayId(replayId); - } - return client; - } - - @BeforeEach - public void setUp() { - String clientMode = System.getenv("GOOGLE_GENAI_CLIENT_MODE"); - if (clientMode != null && clientMode.equals("api")) { - // Don't mock the environment variables for the API test. - return; - } - mockedStaticApiClient = Mockito.mockStatic(ApiClient.class, Mockito.CALLS_REAL_METHODS); - // Mock the default environment variables to avoid reading the actual environment variables. - mockedStaticApiClient - .when(ApiClient::defaultEnvironmentVariables) - .thenReturn( - ImmutableMap.builder() - .put("apiKey", "api-key") - .put("project", "project") - .put("location", "location") - .build()); - } - - @AfterEach - public void tearDown() { - if (mockedStaticApiClient != null) { - mockedStaticApiClient.close(); - } - } - @ParameterizedTest @ValueSource(booleans = {false, true}) public void testGetVideosOperation(boolean vertexAI) throws Exception { // Arrange String suffix = vertexAI ? "vertex" : "mldev"; Client client = - createClient( + TestUtils.createClient( vertexAI, "tests/models/generate_videos/test_create_operation_to_poll." + suffix + ".json"); diff --git a/src/test/java/com/google/genai/TestUtils.java b/src/test/java/com/google/genai/TestUtils.java new file mode 100644 index 00000000000..9e2313db3c2 --- /dev/null +++ b/src/test/java/com/google/genai/TestUtils.java @@ -0,0 +1,49 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.genai; + +public final class TestUtils { + static final String API_KEY = "api-key"; + static final String PROJECT = "project"; + static final String LOCATION = "location"; + + private TestUtils() {} + + /** Creates a client given the vertexAI and replayId. Can be used in replay tests. */ + public static Client createClient(boolean vertexAI, String replayId) { + String clientMode = System.getenv("GOOGLE_GENAI_CLIENT_MODE"); + DebugConfig debugConfig = + new DebugConfig( + clientMode == null ? "replay" : clientMode, + "", + System.getenv("GOOGLE_GENAI_REPLAYS_DIRECTORY")); + + Client.Builder clientBuilder = Client.builder().vertexAI(vertexAI).debugConfig(debugConfig); + + if (vertexAI) { + clientBuilder.project(PROJECT).location(LOCATION); + } else { + clientBuilder.apiKey(API_KEY); + } + Client client = clientBuilder.build(); + + if (client.clientMode().equals("replay")) { + client.setReplayId(replayId); + } + return client; + } +} From 2fbf0c91b152f9f159cbe729aeded5f4351307c6 Mon Sep 17 00:00:00 2001 From: Ayush Agrawal Date: Fri, 18 Jul 2025 17:27:17 -0700 Subject: [PATCH 093/602] chore: Add replay tests for Java async files module PiperOrigin-RevId: 784751536 --- .../java/com/google/genai/AsyncFilesTest.java | 134 ++++++++++++++++++ 1 file changed, 134 insertions(+) create mode 100644 src/test/java/com/google/genai/AsyncFilesTest.java diff --git a/src/test/java/com/google/genai/AsyncFilesTest.java b/src/test/java/com/google/genai/AsyncFilesTest.java new file mode 100644 index 00000000000..cd68023d9ad --- /dev/null +++ b/src/test/java/com/google/genai/AsyncFilesTest.java @@ -0,0 +1,134 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.genai; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import com.google.genai.errors.GenAiIOException; +import com.google.genai.types.File; +import com.google.genai.types.ListFilesConfig; +import java.util.concurrent.ExecutionException; +import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable; +import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; + +@EnabledIfEnvironmentVariable( + named = "GOOGLE_GENAI_REPLAYS_DIRECTORY", + matches = ".*genai/replays.*") +@ExtendWith(EnvironmentVariablesMockingExtension.class) +public class AsyncFilesTest { + @ParameterizedTest + @ValueSource(booleans = {false, true}) + public void testAsyncGetFile(boolean vertexAI) throws ExecutionException, InterruptedException { + // Arrange + String suffix = vertexAI ? "vertex" : "mldev"; + Client client = + TestUtils.createClient(vertexAI, "tests/files/get/test_async." + suffix + ".json"); + String fileName = "files/vjvu9fwk2qj8"; + + // Act + if (vertexAI) { + ExecutionException exception = + assertThrows( + ExecutionException.class, () -> client.async.files.get(fileName, null).get()); + + // Assert + assertEquals( + "This method is only supported in the Gemini Developer client.", + exception.getCause().getMessage()); + assertTrue(exception.getCause() instanceof UnsupportedOperationException); + } else { + File file = client.async.files.get(fileName, null).get(); + + // Assert + assertNotNull(file); + assertEquals(fileName, file.name().get()); + } + } + + @ParameterizedTest + @ValueSource(booleans = {false, true}) + public void testAsyncListFiles(boolean vertexAI) throws ExecutionException, InterruptedException { + // Arrange + String suffix = vertexAI ? "vertex" : "mldev"; + Client client = + TestUtils.createClient(vertexAI, "tests/files/list/test_async_pager." + suffix + ".json"); + ListFilesConfig config = ListFilesConfig.builder().pageSize(2).build(); + + // Act + if (vertexAI) { + AsyncPager pager = client.async.files.list(config).get(); + + // Assert + final int[] count = {0}; + ExecutionException exception = + assertThrows( + ExecutionException.class, + () -> + pager + .forEach( + file -> { + assertNotNull(file); + count[0]++; + }) + .get()); + assertTrue(exception.getCause() instanceof GenAiIOException); + assertTrue( + exception + .getCause() + .getMessage() + .contains("This method is only supported in the Gemini Developer client.")); + } else { + AsyncPager pager = client.async.files.list(config).get(); + + // Assert + assertNotNull(pager); + final int[] count = {0}; + pager + .forEach( + file -> { + assertNotNull(file); + count[0]++; + }) + .get(); + assertTrue(count[0] > 0); + } + } + + @ParameterizedTest + @ValueSource(booleans = {false, true}) + public void testAsyncUploadUnknownPath(boolean vertexAI) throws ExecutionException { + // Arrange + String suffix = vertexAI ? "vertex" : "mldev"; + Client client = + TestUtils.createClient( + vertexAI, "tests/files/upload/test_unknown_path_upload_async." + suffix + ".json"); + String filePath = "unknown_path"; + + // Act & Assert + ExecutionException exception = + assertThrows( + ExecutionException.class, () -> client.async.files.upload(filePath, null).get()); + assertTrue(exception.getCause() instanceof GenAiIOException); + assertTrue(exception.getCause().getMessage().contains("Failed to upload file.")); + assertTrue(exception.getCause().getCause() instanceof java.io.FileNotFoundException); + } +} From ed85d1598e8f84392ad1353876fb57c7bc318657 Mon Sep 17 00:00:00 2001 From: Jaycee Li Date: Mon, 21 Jul 2025 12:23:44 -0700 Subject: [PATCH 094/602] chore: enable all tests in Github checks(replay tests will be automatically skipped) PiperOrigin-RevId: 785531352 --- .github/workflows/unit-tests.yml | 10 ++-- src/main/java/com/google/genai/ApiClient.java | 15 +----- .../java/com/google/genai/ClientTest.java | 19 ++++++-- .../com/google/genai/HttpApiClientTest.java | 46 ++++++++++++------- 4 files changed, 49 insertions(+), 41 deletions(-) diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml index 7ffb0c9a55c..72e3eec72d4 100644 --- a/.github/workflows/unit-tests.yml +++ b/.github/workflows/unit-tests.yml @@ -14,10 +14,8 @@ jobs: strategy: matrix: java: [8, 11, 17, 21] - testgroup: [ - # Includes everything in tests/ except the ones listed here - '**/*,!com.google.genai.ClientTest,!com.google.genai.TableTest,!com.google.genai.HttpApiClientTest,!com.google.genai.ModelsTest,!com.google.genai.OperationsTest' - ] + testgroup: ['**/*'] + fail-fast: false name: unit-test (${{matrix.java}}) steps: - uses: actions/checkout@v4 @@ -27,6 +25,4 @@ jobs: java-version: ${{matrix.java}} cache: 'maven' - name: Java Unit Tests - run: mvn clean test -Dtest=${{matrix.testgroup}} - env: - GOOGLE_API_KEY: testkey + run: mvn clean test -Dtest=${{matrix.testgroup}} \ No newline at end of file diff --git a/src/main/java/com/google/genai/ApiClient.java b/src/main/java/com/google/genai/ApiClient.java index ab5f0996df4..482e38b074c 100644 --- a/src/main/java/com/google/genai/ApiClient.java +++ b/src/main/java/com/google/genai/ApiClient.java @@ -269,20 +269,7 @@ private void setHeaders(Request.Builder request, HttpOptions requestHttpOptions) } catch (IOException e) { throw new GenAiIOException("Failed to refresh credentials.", e); } - String accessToken; - try { - accessToken = cred.getAccessToken().getTokenValue(); - } catch (NullPointerException e) { - // For test cases where the access token is not available. - if (e.getMessage() - .contains( - "because the return value of" - + " \"com.google.auth.oauth2.GoogleCredentials.getAccessToken()\" is null")) { - accessToken = ""; - } else { - throw e; - } - } + String accessToken = cred.getAccessToken().getTokenValue(); request.header("Authorization", "Bearer " + accessToken); if (cred.getQuotaProjectId() != null) { diff --git a/src/test/java/com/google/genai/ClientTest.java b/src/test/java/com/google/genai/ClientTest.java index 5fe333dbd58..550d39534f5 100644 --- a/src/test/java/com/google/genai/ClientTest.java +++ b/src/test/java/com/google/genai/ClientTest.java @@ -39,6 +39,7 @@ public class ClientTest { private static final HttpOptions HTTP_OPTIONS = HttpOptions.builder().baseUrl("test-url").build(); private static final DebugConfig DEBUG_CONFIG = new DebugConfig("replay", "replay-id", "replay-dir"); + private static final GoogleCredentials CREDENTIALS = GoogleCredentials.newBuilder().build(); @Test public void testInitClientFromBuilder_mldev() { @@ -56,7 +57,13 @@ public void testInitClientFromBuilder_mldev() { @Test public void testInitClientFromBuilder_vertex() { // Act - Client client = Client.builder().project(PROJECT).location(LOCATION).vertexAI(true).build(); + Client client = + Client.builder() + .project(PROJECT) + .location(LOCATION) + .credentials(CREDENTIALS) + .vertexAI(true) + .build(); // Assert assertEquals(null, client.apiKey()); @@ -75,8 +82,8 @@ public void testInitClientFromBuilder_withCredentialsAndHttpOptions() { Client.builder() .project(PROJECT) .location(LOCATION) + .credentials(CREDENTIALS) .vertexAI(true) - .credentials(mock(GoogleCredentials.class)) .httpOptions(HTTP_OPTIONS) .build(); @@ -109,6 +116,7 @@ public void testReplayClient_vertex() { Client.builder() .project(PROJECT) .location(LOCATION) + .credentials(CREDENTIALS) .vertexAI(true) .debugConfig(DEBUG_CONFIG) .build(); @@ -165,7 +173,12 @@ public void testSetDefaultBaseUrls() { // Act Client.setDefaultBaseUrls(Optional.of("gemini-base-url"), Optional.of("vertex-base-url")); Client vertexClient = - Client.builder().project(PROJECT).location(LOCATION).vertexAI(true).build(); + Client.builder() + .project(PROJECT) + .location(LOCATION) + .credentials(CREDENTIALS) + .vertexAI(true) + .build(); Client mldevClient = Client.builder().apiKey(API_KEY).vertexAI(false).build(); assertEquals("gemini-base-url", mldevClient.baseUrl().orElse(null)); diff --git a/src/test/java/com/google/genai/HttpApiClientTest.java b/src/test/java/com/google/genai/HttpApiClientTest.java index cd7a973c13f..3f5787a425b 100644 --- a/src/test/java/com/google/genai/HttpApiClientTest.java +++ b/src/test/java/com/google/genai/HttpApiClientTest.java @@ -33,6 +33,7 @@ import com.github.tomakehurst.wiremock.WireMockServer; import com.github.tomakehurst.wiremock.client.WireMock; +import com.google.auth.oauth2.AccessToken; import com.google.auth.oauth2.GoogleCredentials; import com.google.common.collect.ImmutableMap; import com.google.genai.types.Candidate; @@ -78,6 +79,10 @@ public class HttpApiClientTest { .build()); private static final String TEST_PATH = "test-path"; private static final String TEST_REQUEST_JSON = "{\"test\": \"request-json\"}"; + private static final GoogleCredentials CREDENTIALS = + GoogleCredentials.newBuilder() + .setAccessToken(AccessToken.newBuilder().setTokenValue("").build()) + .build(); @Mock OkHttpClient mockHttpClient; @Mock Call mockCall; @@ -98,10 +103,6 @@ private void setMockClient(HttpApiClient client) throws Exception { Field clientField = ApiClient.class.getDeclaredField("httpClient"); clientField.setAccessible(true); clientField.set(client, mockHttpClient); - GoogleCredentials credentials = Mockito.mock(GoogleCredentials.class); - Field credentialsField = ApiClient.class.getDeclaredField("credentials"); - credentialsField.setAccessible(true); - credentialsField.set(client, Optional.of(credentials)); } @Test @@ -112,7 +113,7 @@ public void testRequestPostMethodWithVertexAI() throws Exception { Optional.empty(), Optional.of(PROJECT), Optional.of(LOCATION), - Optional.empty(), + Optional.of(CREDENTIALS), Optional.empty(), Optional.empty()); setMockClient(client); @@ -279,7 +280,7 @@ public void testInitHttpClientVertexWithProjectAndLocation() throws Exception { Optional.empty(), Optional.of(PROJECT), Optional.of(LOCATION), - Optional.empty(), + Optional.of(CREDENTIALS), Optional.of(httpOptions), Optional.empty()); @@ -380,7 +381,7 @@ public void testInitHttpClientVertexWithPartialHttpOptions() throws Exception { Optional.empty(), Optional.of(PROJECT), Optional.of(LOCATION), - Optional.empty(), + Optional.of(CREDENTIALS), Optional.of(httpOptions), Optional.empty()); @@ -415,7 +416,7 @@ public void testHttpClientVertexTimeout() throws Exception { Optional.empty(), Optional.of(PROJECT), Optional.of(LOCATION), - Optional.empty(), + Optional.of(CREDENTIALS), Optional.of(httpOptions), Optional.empty()); @@ -448,7 +449,7 @@ public void testHttpClientVertexNoTimeout() throws Exception { Optional.empty(), Optional.of(PROJECT), Optional.of(LOCATION), - Optional.empty(), + Optional.of(CREDENTIALS), Optional.empty(), Optional.empty()); @@ -486,7 +487,7 @@ public void testHttpClientVertexCustomClientOptions() throws Exception { Optional.empty(), Optional.of(PROJECT), Optional.of(LOCATION), - Optional.empty(), + Optional.of(CREDENTIALS), Optional.empty(), Optional.of(clientOptions)); @@ -517,16 +518,15 @@ public void testHttpClientMldevDefaultClientOptions() throws Exception { @Test public void testHttpClientWithCustomCredentials() throws Exception { - GoogleCredentials credentials = Mockito.mock(GoogleCredentials.class); HttpApiClient client = new HttpApiClient( Optional.empty(), Optional.of(PROJECT), Optional.of(LOCATION), - Optional.of(credentials), + Optional.of(CREDENTIALS), Optional.empty(), Optional.empty()); - assertEquals(credentials, client.credentials.get()); + assertEquals(CREDENTIALS, client.credentials.get()); } @Test @@ -537,7 +537,7 @@ public void testHttpClientVertexWithGlobalEndpoint() throws Exception { Optional.empty(), Optional.of(PROJECT), Optional.of("global"), - Optional.empty(), + Optional.of(CREDENTIALS), Optional.of(httpOptions), Optional.empty()); @@ -553,7 +553,7 @@ public void testHttpClientVertexWithNoHttpOptions() throws Exception { Optional.empty(), Optional.of(PROJECT), Optional.of("global"), - Optional.empty(), + Optional.of(CREDENTIALS), Optional.empty(), Optional.empty()); @@ -674,7 +674,13 @@ public void testVertexClientInitializationWithBaseUrlFromSetBaseUrlsOverridesEnv .thenReturn(ImmutableMap.of("vertexBaseUrl", "https://vertex-base-url.googleapis.com/")); Client.setDefaultBaseUrls( Optional.empty(), Optional.of("https://custom-base-url.googleapis.com/")); - Client client = Client.builder().project(PROJECT).location(LOCATION).vertexAI(true).build(); + Client client = + Client.builder() + .project(PROJECT) + .location(LOCATION) + .credentials(CREDENTIALS) + .vertexAI(true) + .build(); assertTrue(client.baseUrl().isPresent()); assertEquals(client.baseUrl().get(), "https://custom-base-url.googleapis.com/"); @@ -700,7 +706,13 @@ public void testVertexClientInitializationWithBaseUrlFromEnvironment( mockedStaticApiClient .when(ApiClient::defaultEnvironmentVariables) .thenReturn(ImmutableMap.of("vertexBaseUrl", "https://custom-base-url.googleapis.com/")); - Client client = Client.builder().project(PROJECT).location(LOCATION).vertexAI(true).build(); + Client client = + Client.builder() + .project(PROJECT) + .location(LOCATION) + .credentials(CREDENTIALS) + .vertexAI(true) + .build(); assertTrue(client.baseUrl().isPresent()); assertEquals(client.baseUrl().get(), "https://custom-base-url.googleapis.com/"); From a5406140aeaf9774265a5bcce79dae0707ed9287 Mon Sep 17 00:00:00 2001 From: Jaycee Li Date: Mon, 21 Jul 2025 15:15:35 -0700 Subject: [PATCH 095/602] fix: Defer loading ADC when credentials is provided explicitly in Live API PiperOrigin-RevId: 785593568 --- src/main/java/com/google/genai/AsyncLive.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/google/genai/AsyncLive.java b/src/main/java/com/google/genai/AsyncLive.java index f256530e649..bb04bd85f0c 100644 --- a/src/main/java/com/google/genai/AsyncLive.java +++ b/src/main/java/com/google/genai/AsyncLive.java @@ -122,7 +122,7 @@ private Map getWebSocketHeaders() { if (apiClient.vertexAI()) { try { GoogleCredentials credentials = - apiClient.credentials.orElse(apiClient.defaultCredentials()); + apiClient.credentials.orElseGet(() -> apiClient.defaultCredentials()); credentials.refreshIfExpired(); headers.put("Authorization", "Bearer " + credentials.getAccessToken().getTokenValue()); } catch (IOException e) { From 0b477837b7f4cf269d7c72ae445e6743e1467e9a Mon Sep 17 00:00:00 2001 From: Ayush Agrawal Date: Mon, 21 Jul 2025 15:16:48 -0700 Subject: [PATCH 096/602] chore: Enable replay tests for non-async and async Java Tunings module PiperOrigin-RevId: 785593969 --- .../com/google/genai/AsyncTuningsTest.java | 135 +++++++++++++++++ .../java/com/google/genai/TuningsTest.java | 139 ++++++++++++++++++ 2 files changed, 274 insertions(+) create mode 100644 src/test/java/com/google/genai/AsyncTuningsTest.java create mode 100644 src/test/java/com/google/genai/TuningsTest.java diff --git a/src/test/java/com/google/genai/AsyncTuningsTest.java b/src/test/java/com/google/genai/AsyncTuningsTest.java new file mode 100644 index 00000000000..2f1b03b439e --- /dev/null +++ b/src/test/java/com/google/genai/AsyncTuningsTest.java @@ -0,0 +1,135 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.genai; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import com.google.genai.types.CreateTuningJobConfig; +import com.google.genai.types.JobState; +import com.google.genai.types.ListTuningJobsConfig; +import com.google.genai.types.TuningDataset; +import com.google.genai.types.TuningExample; +import com.google.genai.types.TuningJob; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ExecutionException; +import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable; +import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; + +@EnabledIfEnvironmentVariable( + named = "GOOGLE_GENAI_REPLAYS_DIRECTORY", + matches = ".*genai/replays.*") +@ExtendWith(EnvironmentVariablesMockingExtension.class) +public class AsyncTuningsTest { + @ParameterizedTest + @ValueSource(booleans = {false, true}) + public void testAsyncPager(boolean vertexAI) throws ExecutionException, InterruptedException { + // Arrange + String suffix = vertexAI ? "vertex" : "mldev"; + Client client = + TestUtils.createClient(vertexAI, "tests/tunings/list/test_async_pager." + suffix + ".json"); + ListTuningJobsConfig config = ListTuningJobsConfig.builder().pageSize(2).build(); + + // Act + AsyncPager pager = client.async.tunings.list(config).get(); + + // Assert + assertNotNull(pager); + assertEquals(pager.pageSize().get(), 2); + pager.forEach(item -> assertNotNull(item)); + } + + @ParameterizedTest + @ValueSource(booleans = {false, true}) + public void testHelperProperties(boolean vertexAI) + throws ExecutionException, InterruptedException { + // Arrange + String suffix = vertexAI ? "vertex" : "mldev"; + Client client = + TestUtils.createClient( + vertexAI, "tests/tunings/get/test_helper_properties." + suffix + ".json"); + + String vertexJob = "projects/801452371447/locations/us-central1/tuningJobs/4303478340632707072"; + String mldevJob = "tunedModels/testdatasetexamples-model-j0fpgpaksvri"; + String jobName = vertexAI ? vertexJob : mldevJob; + + // Act + TuningJob job = client.async.tunings.get(jobName, null).get(); + + // Assert + assertNotNull(job); + assertTrue(job.state().get().knownEnum() == JobState.Known.JOB_STATE_SUCCEEDED); + } + + @ParameterizedTest + @ValueSource(booleans = {false, true}) + public void testTuneUntilSuccess(boolean vertexAI) + throws ExecutionException, InterruptedException { + // Arrange + String suffix = vertexAI ? "vertex" : "mldev"; + Client client = + TestUtils.createClient( + vertexAI, "tests/tunings/end_to_end/test_tune_until_success." + suffix + ".json"); + + TuningJob job; + if (vertexAI) { + TuningDataset tuningDataset = + TuningDataset.builder() + .gcsUri( + "gs://cloud-samples-data/ai-platform/generative_ai/gemini-2_0/text/sft_train_data.jsonl") + .build(); + job = client.async.tunings.tune("gemini-2.0-flash-001", tuningDataset, null).get(); + } else { + // Technically not supported anymore (via API) but the replay test only verifies logic + List examples = new ArrayList<>(); + for (int i = 0; i < 5; i++) { + examples.add( + TuningExample.builder() + .textInput(String.format("Input text %d", i)) + .output(String.format("Output text %d", i)) + .build()); + } + + TuningDataset tuningDataset = TuningDataset.builder().examples(examples).build(); + CreateTuningJobConfig config = + CreateTuningJobConfig.builder() + .tunedModelDisplayName("test_dataset_examples model") + .build(); + job = client.async.tunings.tune("models/gemini-1.0-pro-001", tuningDataset, config).get(); + } + + // Act + TuningJob currentJob = job; + JobState.Known state = job.state().get().knownEnum(); + + // Needed to go through the running + pending tuning job states. + while (state != JobState.Known.JOB_STATE_SUCCEEDED + && state != JobState.Known.JOB_STATE_FAILED + && state != JobState.Known.JOB_STATE_CANCELLED) { + currentJob = client.async.tunings.get(currentJob.name().get(), null).get(); + state = currentJob.state().get().knownEnum(); + } + + // Assert + assertNotNull(currentJob); + assertTrue(currentJob.state().get().knownEnum() == JobState.Known.JOB_STATE_SUCCEEDED); + } +} diff --git a/src/test/java/com/google/genai/TuningsTest.java b/src/test/java/com/google/genai/TuningsTest.java new file mode 100644 index 00000000000..d2775fca3ff --- /dev/null +++ b/src/test/java/com/google/genai/TuningsTest.java @@ -0,0 +1,139 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.genai; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import com.google.genai.types.CreateTuningJobConfig; +import com.google.genai.types.JobState; +import com.google.genai.types.ListTuningJobsConfig; +import com.google.genai.types.TuningDataset; +import com.google.genai.types.TuningExample; +import com.google.genai.types.TuningJob; +import java.util.ArrayList; +import java.util.List; +import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable; +import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; + +@EnabledIfEnvironmentVariable( + named = "GOOGLE_GENAI_REPLAYS_DIRECTORY", + matches = ".*genai/replays.*") +@ExtendWith(EnvironmentVariablesMockingExtension.class) +public class TuningsTest { + @ParameterizedTest + @ValueSource(booleans = {false, true}) + public void testPager(boolean vertexAI) { + // Arrange + String suffix = vertexAI ? "vertex" : "mldev"; + Client client = + TestUtils.createClient(vertexAI, "tests/tunings/list/test_pager." + suffix + ".json"); + ListTuningJobsConfig config = ListTuningJobsConfig.builder().pageSize(2).build(); + + // Act + Pager pager = client.tunings.list(config); + + // Assert + assertNotNull(pager); + assertEquals(2, pager.pageSize()); + for (TuningJob job : pager) { + assertTrue(job.name().isPresent()); + } + + IndexOutOfBoundsException exception = + assertThrows(IndexOutOfBoundsException.class, () -> pager.nextPage()); + assertEquals("No more page in the pager.", exception.getMessage()); + } + + @ParameterizedTest + @ValueSource(booleans = {false, true}) + public void testHelperProperties(boolean vertexAI) { + // Arrange + String suffix = vertexAI ? "vertex" : "mldev"; + Client client = + TestUtils.createClient( + vertexAI, "tests/tunings/get/test_helper_properties." + suffix + ".json"); + + String vertexJob = "projects/801452371447/locations/us-central1/tuningJobs/4303478340632707072"; + String mldevJob = "tunedModels/testdatasetexamples-model-j0fpgpaksvri"; + String jobName = vertexAI ? vertexJob : mldevJob; + + // Act + TuningJob job = client.tunings.get(jobName, null); + + // Assert + assertNotNull(job); + assertTrue(job.state().get().knownEnum() == JobState.Known.JOB_STATE_SUCCEEDED); + } + + @ParameterizedTest + @ValueSource(booleans = {false, true}) + public void testTuneUntilSuccess(boolean vertexAI) { + // Arrange + String suffix = vertexAI ? "vertex" : "mldev"; + Client client = + TestUtils.createClient( + vertexAI, "tests/tunings/end_to_end/test_tune_until_success." + suffix + ".json"); + + TuningJob job; + if (vertexAI) { + TuningDataset tuningDataset = + TuningDataset.builder() + .gcsUri( + "gs://cloud-samples-data/ai-platform/generative_ai/gemini-2_0/text/sft_train_data.jsonl") + .build(); + job = client.tunings.tune("gemini-2.0-flash-001", tuningDataset, null); + } else { + // Technically not supported anymore (via API) but the replay test only verifies logic + List examples = new ArrayList<>(); + for (int i = 0; i < 5; i++) { + examples.add( + TuningExample.builder() + .textInput(String.format("Input text %d", i)) + .output(String.format("Output text %d", i)) + .build()); + } + + TuningDataset tuningDataset = TuningDataset.builder().examples(examples).build(); + CreateTuningJobConfig config = + CreateTuningJobConfig.builder() + .tunedModelDisplayName("test_dataset_examples model") + .build(); + job = client.tunings.tune("models/gemini-1.0-pro-001", tuningDataset, config); + } + + // Act + TuningJob currentJob = job; + JobState.Known state = job.state().get().knownEnum(); + + // Needed to go through the running + pending tuning job states. + while (state != JobState.Known.JOB_STATE_SUCCEEDED + && state != JobState.Known.JOB_STATE_FAILED + && state != JobState.Known.JOB_STATE_CANCELLED) { + currentJob = client.tunings.get(currentJob.name().get(), null); + state = currentJob.state().get().knownEnum(); + } + + // Assert + assertNotNull(currentJob); + assertTrue(currentJob.state().get().knownEnum() == JobState.Known.JOB_STATE_SUCCEEDED); + } +} From 7c9d23106cb06a32cba7f4650edf34065a14bb5f Mon Sep 17 00:00:00 2001 From: Ayush Agrawal Date: Mon, 21 Jul 2025 16:13:43 -0700 Subject: [PATCH 097/602] chore: Enable replay tests for Async Java caches module PiperOrigin-RevId: 785612480 --- .../com/google/genai/AsyncCachesTest.java | 163 ++++++++++++++++++ 1 file changed, 163 insertions(+) create mode 100644 src/test/java/com/google/genai/AsyncCachesTest.java diff --git a/src/test/java/com/google/genai/AsyncCachesTest.java b/src/test/java/com/google/genai/AsyncCachesTest.java new file mode 100644 index 00000000000..0daf92a56b4 --- /dev/null +++ b/src/test/java/com/google/genai/AsyncCachesTest.java @@ -0,0 +1,163 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.genai; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import com.google.genai.errors.ServerException; +import com.google.genai.types.CachedContent; +import com.google.genai.types.Content; +import com.google.genai.types.CreateCachedContentConfig; +import com.google.genai.types.DeleteCachedContentResponse; +import com.google.genai.types.ListCachedContentsConfig; +import com.google.genai.types.Part; +import com.google.genai.types.UpdateCachedContentConfig; +import java.time.Duration; +import java.util.concurrent.ExecutionException; +import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable; +import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; + +@EnabledIfEnvironmentVariable( + named = "GOOGLE_GENAI_REPLAYS_DIRECTORY", + matches = ".*genai/replays.*") +@ExtendWith(EnvironmentVariablesMockingExtension.class) +public class AsyncCachesTest { + private static final String CACHED_CONTENT_NAME_MLDEV = "cachedContents/op47f693jk6b"; + private static final String CACHED_CONTENT_NAME_VERTEX = + "projects/801452371447/locations/us-central1/cachedContents/1899938500610883584"; + + @ParameterizedTest + @ValueSource(booleans = {false, true}) + public void testAsyncCreateCachedContent(boolean vertexAI) + throws ExecutionException, InterruptedException { + // Arrange + String suffix = vertexAI ? "vertex" : "mldev"; + Client client = + TestUtils.createClient( + vertexAI, "tests/caches/create/test_async_googleai_file_create." + suffix + ".json"); + + String model = "gemini-1.5-pro-001"; + CreateCachedContentConfig config = + CreateCachedContentConfig.builder() + .contents( + Content.fromParts( + Part.fromUri( + "https://generativelanguage.googleapis.com/v1beta/files/v200dhvn15h7", + "video/mp4"))) + .displayName("test cache") + .ttl(Duration.ofSeconds(86400)) + .systemInstruction(Transformers.tContent("What is the sum of the two pdfs?")) + .build(); + + // Act + if (vertexAI) { + ExecutionException exception = + assertThrows( + ExecutionException.class, () -> client.async.caches.create(model, config).get()); + + // Assert + assertTrue(exception.getCause() instanceof ServerException); + assertEquals(exception.getCause().getMessage(), "500 INTERNAL. Internal error encountered."); + } else { + CachedContent response = client.async.caches.create(model, config).get(); + + // Assert + assertNotNull(response); + } + } + + @ParameterizedTest + @ValueSource(booleans = {false, true}) + public void testAsyncDeleteCachedContent(boolean vertexAI) + throws ExecutionException, InterruptedException { + // Arrange + String suffix = vertexAI ? "vertex" : "mldev"; + Client client = + TestUtils.createClient( + vertexAI, "tests/caches/delete/test_async_delete." + suffix + ".json"); + String cacheName = vertexAI ? CACHED_CONTENT_NAME_VERTEX : CACHED_CONTENT_NAME_MLDEV; + + // Act + DeleteCachedContentResponse response = client.async.caches.delete(cacheName, null).get(); + + // Assert + assertNotNull(response); + } + + @ParameterizedTest + @ValueSource(booleans = {false, true}) + public void testAsyncGetCachedContent(boolean vertexAI) + throws ExecutionException, InterruptedException { + // Arrange + String suffix = vertexAI ? "vertex" : "mldev"; + Client client = + TestUtils.createClient(vertexAI, "tests/caches/get/test_async_get." + suffix + ".json"); + String cacheName = vertexAI ? CACHED_CONTENT_NAME_VERTEX : CACHED_CONTENT_NAME_MLDEV; + + // Act + CachedContent response = client.async.caches.get(cacheName, null).get(); + + // Assert + assertNotNull(response); + } + + @ParameterizedTest + @ValueSource(booleans = {false, true}) + public void testAsyncListCachedContents(boolean vertexAI) + throws ExecutionException, InterruptedException { + // Arrange + String suffix = vertexAI ? "vertex" : "mldev"; + Client client = + TestUtils.createClient(vertexAI, "tests/caches/list/test_async_pager." + suffix + ".json"); + ListCachedContentsConfig config = ListCachedContentsConfig.builder().pageSize(2).build(); + + // Act + AsyncPager pager = client.async.caches.list(config).get(); + + // Assert + assertNotNull(pager); + assertEquals(pager.pageSize().get(), 2); + assertTrue(pager.size().get() > 0); + pager.forEach(item -> assertNotNull(item)).get(); + } + + @ParameterizedTest + @ValueSource(booleans = {false, true}) + public void testAsyncUpdateCachedContent(boolean vertexAI) + throws ExecutionException, InterruptedException { + // Arrange + String suffix = vertexAI ? "vertex" : "mldev"; + Client client = + TestUtils.createClient( + vertexAI, "tests/caches/update/test_async_update." + suffix + ".json"); + String cacheName = vertexAI ? CACHED_CONTENT_NAME_VERTEX : CACHED_CONTENT_NAME_MLDEV; + + UpdateCachedContentConfig config = + UpdateCachedContentConfig.builder().ttl(Duration.ofSeconds(7600)).build(); + + // Act + CachedContent response = client.async.caches.update(cacheName, config).get(); + + // Assert + assertNotNull(response); + } +} From 0abd2e5721fd664bda0a70941fa67edc2b7f8fd8 Mon Sep 17 00:00:00 2001 From: Ayush Agrawal Date: Mon, 21 Jul 2025 16:19:00 -0700 Subject: [PATCH 098/602] chore: update Async files tests usage of pager PiperOrigin-RevId: 785614029 --- .../java/com/google/genai/AsyncFilesTest.java | 23 ++++--------------- .../com/google/genai/AsyncTuningsTest.java | 2 +- 2 files changed, 5 insertions(+), 20 deletions(-) diff --git a/src/test/java/com/google/genai/AsyncFilesTest.java b/src/test/java/com/google/genai/AsyncFilesTest.java index cd68023d9ad..ed8117a1c2d 100644 --- a/src/test/java/com/google/genai/AsyncFilesTest.java +++ b/src/test/java/com/google/genai/AsyncFilesTest.java @@ -78,18 +78,9 @@ public void testAsyncListFiles(boolean vertexAI) throws ExecutionException, Inte AsyncPager pager = client.async.files.list(config).get(); // Assert - final int[] count = {0}; ExecutionException exception = assertThrows( - ExecutionException.class, - () -> - pager - .forEach( - file -> { - assertNotNull(file); - count[0]++; - }) - .get()); + ExecutionException.class, () -> pager.forEach(file -> assertNotNull(file)).get()); assertTrue(exception.getCause() instanceof GenAiIOException); assertTrue( exception @@ -101,15 +92,9 @@ public void testAsyncListFiles(boolean vertexAI) throws ExecutionException, Inte // Assert assertNotNull(pager); - final int[] count = {0}; - pager - .forEach( - file -> { - assertNotNull(file); - count[0]++; - }) - .get(); - assertTrue(count[0] > 0); + assertEquals(pager.pageSize().get(), 2); + assertTrue(pager.size().get() > 0); + pager.forEach(item -> assertNotNull(item)).get(); } } diff --git a/src/test/java/com/google/genai/AsyncTuningsTest.java b/src/test/java/com/google/genai/AsyncTuningsTest.java index 2f1b03b439e..c50c840dde2 100644 --- a/src/test/java/com/google/genai/AsyncTuningsTest.java +++ b/src/test/java/com/google/genai/AsyncTuningsTest.java @@ -54,7 +54,7 @@ public void testAsyncPager(boolean vertexAI) throws ExecutionException, Interrup // Assert assertNotNull(pager); assertEquals(pager.pageSize().get(), 2); - pager.forEach(item -> assertNotNull(item)); + pager.forEach(item -> assertNotNull(item)).get(); } @ParameterizedTest From 2c16c2b9919612691253fbd36977d9554412d1b1 Mon Sep 17 00:00:00 2001 From: Ayush Agrawal Date: Mon, 21 Jul 2025 16:19:51 -0700 Subject: [PATCH 099/602] chore: Enable replay tests for Async Java batches module PiperOrigin-RevId: 785614297 --- pom.xml | 6 - src/main/java/com/google/genai/ApiClient.java | 2 +- .../com/google/genai/ReplayApiResponse.java | 4 +- .../com/google/genai/AsyncBatchesTest.java | 282 ++++++++++++++++++ .../java/com/google/genai/AsyncChatTest.java | 26 +- src/test/java/com/google/genai/ChatTest.java | 62 ++-- .../com/google/genai/FakeUploadApiClient.java | 4 +- .../genai/ForwardCompatibilityTest.java | 12 +- .../com/google/genai/HttpApiClientTest.java | 2 +- .../com/google/genai/TransformersTest.java | 6 +- .../google/genai/errors/ApiExceptionTest.java | 4 +- 11 files changed, 343 insertions(+), 67 deletions(-) create mode 100644 src/test/java/com/google/genai/AsyncBatchesTest.java diff --git a/pom.xml b/pom.xml index 41637c1a6da..60b4b082e6d 100644 --- a/pom.xml +++ b/pom.xml @@ -149,12 +149,6 @@ ${junit.version} test - - org.junit.jupiter - junit-jupiter-params - ${junit.version} - test - org.jspecify diff --git a/src/main/java/com/google/genai/ApiClient.java b/src/main/java/com/google/genai/ApiClient.java index 482e38b074c..13c694eafdf 100644 --- a/src/main/java/com/google/genai/ApiClient.java +++ b/src/main/java/com/google/genai/ApiClient.java @@ -241,7 +241,7 @@ protected Request buildRequest( HttpOptions mergedHttpOptions = mergeHttpOptions(requestHttpOptions.orElse(null)); if (httpMethod.equalsIgnoreCase("POST")) { RequestBody body = - RequestBody.create(MediaType.get("application/octet-stream"), requestBytes); + RequestBody.create(requestBytes, MediaType.get("application/octet-stream")); Request.Builder requestBuilder = new Request.Builder().url(url).post(body); setHeaders(requestBuilder, mergedHttpOptions); return requestBuilder.build(); diff --git a/src/main/java/com/google/genai/ReplayApiResponse.java b/src/main/java/com/google/genai/ReplayApiResponse.java index e7a0749bd37..dea8ce15bd6 100644 --- a/src/main/java/com/google/genai/ReplayApiResponse.java +++ b/src/main/java/com/google/genai/ReplayApiResponse.java @@ -46,8 +46,8 @@ public ReplayApiResponse(ArrayNode bodySegments, int statusCode, Headers headers // For unary response this.body = ResponseBody.create( - MediaType.parse("application/json"), - JsonSerializable.toJsonString(bodySegments.get(0))); + JsonSerializable.toJsonString(bodySegments.get(0)), + MediaType.parse("application/json")); } else { // For streaming response try { diff --git a/src/test/java/com/google/genai/AsyncBatchesTest.java b/src/test/java/com/google/genai/AsyncBatchesTest.java new file mode 100644 index 00000000000..4b92c61cb07 --- /dev/null +++ b/src/test/java/com/google/genai/AsyncBatchesTest.java @@ -0,0 +1,282 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.genai; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import com.google.genai.errors.GenAiIOException; +import com.google.genai.types.BatchJob; +import com.google.genai.types.BatchJobDestination; +import com.google.genai.types.BatchJobSource; +import com.google.genai.types.Content; +import com.google.genai.types.CreateBatchJobConfig; +import com.google.genai.types.DeleteResourceJob; +import com.google.genai.types.InlinedRequest; +import com.google.genai.types.ListBatchJobsConfig; +import com.google.genai.types.Part; +import java.util.concurrent.ExecutionException; +import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable; +import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; + +@EnabledIfEnvironmentVariable( + named = "GOOGLE_GENAI_REPLAYS_DIRECTORY", + matches = ".*genai/replays.*") +@ExtendWith(EnvironmentVariablesMockingExtension.class) +public class AsyncBatchesTest { + @ParameterizedTest + @ValueSource(booleans = {false, true}) + public void testAsyncCancel(boolean vertexAI) throws ExecutionException, InterruptedException { + // Arrange + String suffix = vertexAI ? "vertex" : "mldev"; + Client client = + TestUtils.createClient( + vertexAI, "tests/batches/cancel/test_async_cancel." + suffix + ".json"); + + String vertexJob = "2803006536245313536"; + String mldevJob = "batches/coqrz7leaeit8g83thvdrkzdulz1bxgi8s74"; + String name = vertexAI ? vertexJob : mldevJob; + + // Act + client.async.batches.cancel(name, null).get(); + } + + @ParameterizedTest + @ValueSource(booleans = {false, true}) + public void testAsyncCreateWithBigquery(boolean vertexAI) + throws ExecutionException, InterruptedException { + // Arrange + String suffix = vertexAI ? "vertex" : "mldev"; + Client client = + TestUtils.createClient( + vertexAI, "tests/batches/create_with_bigquery/test_async_create." + suffix + ".json"); + + BatchJobSource bqInput = + BatchJobSource.builder() + .bigqueryUri( + "bq://vertex-sdk-dev.unified_genai_tests_batches.generate_content_requests") + .format("bigquery") + .build(); + + CreateBatchJobConfig config = + CreateBatchJobConfig.builder() + .displayName("genai_batch_job_20240101000000_bd656") + .dest( + BatchJobDestination.builder() + .bigqueryUri( + "bq://vertex-sdk-dev.unified_genai_tests_batches." + + "generate_content_requests_dest_20240101000000_bd656") + .format("bigquery")) + .build(); + + // Act + if (vertexAI) { + BatchJob batchJob = + client.async.batches.create("gemini-1.5-flash-002", bqInput, config).get(); + + // Assert + assertNotNull(batchJob); + assertTrue(batchJob.name().get().startsWith("projects/")); + } else { + ExecutionException exception = + assertThrows( + ExecutionException.class, + () -> client.async.batches.create("gemini-1.5-flash-002", bqInput, config).get()); + + // Assert + assertTrue(exception.getCause() instanceof GenAiIOException); + assertEquals( + exception.getCause().getMessage(), "One of fileName and InlinedRequests must be set."); + } + } + + @ParameterizedTest + @ValueSource(booleans = {false, true}) + public void testAsyncCreateWithFile(boolean vertexAI) + throws ExecutionException, InterruptedException { + // Arrange + String suffix = vertexAI ? "vertex" : "mldev"; + Client client = + TestUtils.createClient( + vertexAI, "tests/batches/create_with_file/test_async_create." + suffix + ".json"); + BatchJobSource src = BatchJobSource.builder().fileName("files/76eifkmq7uxd").build(); + CreateBatchJobConfig config = CreateBatchJobConfig.builder().displayName("test_batch").build(); + + // Act + if (vertexAI) { + ExecutionException exception = + assertThrows( + ExecutionException.class, + () -> client.async.batches.create("gemini-2.0-flash", src, config).get()); + + // Assert + assertTrue(exception.getCause() instanceof GenAiIOException); + assertEquals(exception.getCause().getMessage(), "fileName is not supported for Vertex AI."); + } else { + BatchJob batchJob = client.async.batches.create("gemini-2.0-flash", src, config).get(); + + // Assert + assertNotNull(batchJob); + assertTrue(batchJob.name().get().startsWith("batches/")); + } + } + + @ParameterizedTest + @ValueSource(booleans = {false, true}) + public void testAsyncCreateWithGcs(boolean vertexAI) + throws ExecutionException, InterruptedException { + // Arrange + String suffix = vertexAI ? "vertex" : "mldev"; + Client client = + TestUtils.createClient( + vertexAI, "tests/batches/create_with_gcs/test_async_create." + suffix + ".json"); + + BatchJobSource src = + BatchJobSource.builder() + .gcsUri("gs://unified-genai-tests/batches/input/generate_content_requests.jsonl") + .format("jsonl") + .build(); + + CreateBatchJobConfig config = + CreateBatchJobConfig.builder() + .displayName("genai_batch_job_20240101000000_bd656") + .dest( + BatchJobDestination.builder() + .gcsUri("gs://unified-genai-tests/batches/input/generate_content_requests/dest") + .format("jsonl")) + .build(); + + // Act + if (vertexAI) { + BatchJob batchJob = client.async.batches.create("gemini-1.5-flash-002", src, config).get(); + + // Assert + assertNotNull(batchJob); + assertTrue(batchJob.name().get().startsWith("projects/")); + } else { + ExecutionException exception = + assertThrows( + ExecutionException.class, + () -> client.async.batches.create("gemini-1.5-flash-002", src, config).get()); + + // Assert + assertTrue(exception.getCause() instanceof GenAiIOException); + assertEquals( + exception.getCause().getMessage(), "One of fileName and InlinedRequests must be set."); + } + } + + @ParameterizedTest + @ValueSource(booleans = {false, true}) + public void testAsyncCreateWithInlinedRequests(boolean vertexAI) + throws ExecutionException, InterruptedException { + // Arrange + String suffix = vertexAI ? "vertex" : "mldev"; + Client client = + TestUtils.createClient( + vertexAI, + "tests/batches/create_with_inlined_requests/test_async_create." + suffix + ".json"); + + BatchJobSource src = + BatchJobSource.builder() + .inlinedRequests( + InlinedRequest.builder() + .contents(Content.builder().parts(Part.fromText("Hello!")).role("user"))) + .build(); + + // Act + if (vertexAI) { + ExecutionException exception = + assertThrows( + ExecutionException.class, + () -> client.async.batches.create("gemini-1.5-flash-002", src, null).get()); + + // Assert + assertTrue(exception.getCause() instanceof GenAiIOException); + assertTrue( + exception + .getCause() + .getMessage() + .equals("inlinedRequests is not supported for Vertex AI.")); + } else { + BatchJob batchJob = client.async.batches.create("gemini-1.5-flash-002", src, null).get(); + + // Assert + assertNotNull(batchJob); + assertTrue(batchJob.name().get().startsWith("batches/")); + } + } + + @ParameterizedTest + @ValueSource(booleans = {false, true}) + public void testAsyncDelete(boolean vertexAI) throws ExecutionException, InterruptedException { + // Arrange + String suffix = vertexAI ? "vertex" : "mldev"; + Client client = + TestUtils.createClient( + vertexAI, "tests/batches/delete/test_async_delete." + suffix + ".json"); + + String vertexJob = "7085929781874655232"; + String mldevJob = "batches/70h2jo0ic2t1zejyl0p4jgi8mk1gj0wvjusv"; + String name = vertexAI ? vertexJob : mldevJob; + + // Act + DeleteResourceJob job = client.async.batches.delete(name, null).get(); + assertNotNull(job); + } + + @ParameterizedTest + @ValueSource(booleans = {false, true}) + public void testAsyncGet(boolean vertexAI) throws ExecutionException, InterruptedException { + // Arrange + String suffix = vertexAI ? "vertex" : "mldev"; + Client client = + TestUtils.createClient(vertexAI, "tests/batches/get/test_async_get." + suffix + ".json"); + + String vertexJob = "5798522612028014592"; + String mldevJob = "batches/2uqn2xn58tohxdg0qnypy4dujme2mvs90gp1"; + String name = vertexAI ? vertexJob : mldevJob; + + // Act + BatchJob batchJob = client.async.batches.get(name, null).get(); + + // Assert + assertNotNull(batchJob); + } + + @ParameterizedTest + @ValueSource(booleans = {false, true}) + public void testAsyncList(boolean vertexAI) throws ExecutionException, InterruptedException { + // Arrange + String suffix = vertexAI ? "vertex" : "mldev"; + Client client = + TestUtils.createClient(vertexAI, "tests/batches/list/test_async_pager." + suffix + ".json"); + ListBatchJobsConfig config = ListBatchJobsConfig.builder().pageSize(10).build(); + + // Act + AsyncPager pager = client.async.batches.list(config).get(); + + // Assert + assertNotNull(pager); + assertEquals(pager.pageSize().get(), 10); + pager.page().get().forEach(item -> assertNotNull(item)); + } +} diff --git a/src/test/java/com/google/genai/AsyncChatTest.java b/src/test/java/com/google/genai/AsyncChatTest.java index 13f21537191..40163a1b46d 100644 --- a/src/test/java/com/google/genai/AsyncChatTest.java +++ b/src/test/java/com/google/genai/AsyncChatTest.java @@ -143,14 +143,14 @@ public void testGetAsyncChatMessage() throws Exception { ResponseBody content1 = ResponseBody.create( - MediaType.get("application/json"), "{\"candidates\":[{\"content\":{\"parts\":[{\"text\":\"Once upon a time, there was a" - + " cheese shop\"}], \"role\":\"model\"}, \"finishReason\":\"STOP\"}]}"); + + " cheese shop\"}], \"role\":\"model\"}, \"finishReason\":\"STOP\"}]}", + MediaType.get("application/json")); ResponseBody content2 = ResponseBody.create( - MediaType.get("application/json"), "{\"candidates\":[{\"content\":{\"parts\":[{\"text\":\"Once upon a time, there was a" - + " cheese shop\"}], \"role\":\"model\"}, \"finishReason\":\"STOP\"}]}"); + + " cheese shop\"}], \"role\":\"model\"}, \"finishReason\":\"STOP\"}]}", + MediaType.get("application/json")); when(mockedResponse1.getBody()).thenReturn(content1); when(mockedResponse2.getBody()).thenReturn(content2); @@ -176,14 +176,14 @@ public void testGetHistoryAsync() throws Exception { ResponseBody content1 = ResponseBody.create( - MediaType.get("application/json"), "{\"candidates\":[{\"content\":{\"parts\":[{\"text\":\"Once upon a time, there was a" - + " cheese shop\"}], \"role\":\"model\"}, \"finishReason\":\"STOP\"}]}"); + + " cheese shop\"}], \"role\":\"model\"}, \"finishReason\":\"STOP\"}]}", + MediaType.get("application/json")); ResponseBody content2 = ResponseBody.create( - MediaType.get("application/json"), "{\"candidates\":[{\"content\":{\"parts\":[{\"text\":\"Once upon a time, there was a" - + " cheese shop\"}], \"role\":\"model\"}, \"finishReason\":\"STOP\"}]}"); + + " cheese shop\"}], \"role\":\"model\"}, \"finishReason\":\"STOP\"}]}", + MediaType.get("application/json")); when(mockedResponse1.getBody()).thenReturn(content1); when(mockedResponse2.getBody()).thenReturn(content2); @@ -213,9 +213,9 @@ public void testIterateOverAsyncResponseStream() throws Exception { AsyncChat chatSession = client.async.chats.create("gemini-2.0-flash-exp", null); - ResponseBody body1 = ResponseBody.create(MediaType.get("application/json"), streamData); - ResponseBody body2 = ResponseBody.create(MediaType.get("application/json"), streamData2); - ResponseBody body3 = ResponseBody.create(MediaType.get("application/json"), nonStreamData); + ResponseBody body1 = ResponseBody.create(streamData, MediaType.get("application/json")); + ResponseBody body2 = ResponseBody.create(streamData2, MediaType.get("application/json")); + ResponseBody body3 = ResponseBody.create(nonStreamData, MediaType.get("application/json")); when(mockedResponse1.getBody()).thenReturn(body1); when(mockedResponse2.getBody()).thenReturn(body2); @@ -293,8 +293,8 @@ public void testThrowsIfAsyncStreamResponseIsNotConsumed() throws Exception { AsyncChat chatSession = client.async.chats.create("gemini-2.0-flash-exp", null); - ResponseBody body1 = ResponseBody.create(MediaType.get("application/json"), streamData); - ResponseBody body2 = ResponseBody.create(MediaType.get("application/json"), streamData2); + ResponseBody body1 = ResponseBody.create(streamData, MediaType.get("application/json")); + ResponseBody body2 = ResponseBody.create(streamData2, MediaType.get("application/json")); when(mockedResponse1.getBody()).thenReturn(body1); when(mockedResponse2.getBody()).thenReturn(body2); when(mockedClient.request(anyString(), anyString(), anyString(), any())) diff --git a/src/test/java/com/google/genai/ChatTest.java b/src/test/java/com/google/genai/ChatTest.java index b4112ccf85e..17da32efdee 100644 --- a/src/test/java/com/google/genai/ChatTest.java +++ b/src/test/java/com/google/genai/ChatTest.java @@ -156,9 +156,9 @@ public void testGetHistory() throws Exception { ResponseBody content = ResponseBody.create( - MediaType.get("application/json"), "{\"candidates\":[{\"content\":{\"parts\":[{\"text\":\"All Too Well, 10 Minute" - + " Version\"}], \"role\":\"model\"}, \"finishReason\":\"STOP\"}]}}"); + + " Version\"}], \"role\":\"model\"}, \"finishReason\":\"STOP\"}]}}", + MediaType.get("application/json")); when(mockedResponse.getBody()).thenReturn(content); // Make the apiClient field public so that it can be spied on in the tests. This is a // workaround for the fact that the ApiClient is a final class and cannot be spied on directly. @@ -210,10 +210,10 @@ public void testGetHistoryWithAfc() throws Exception { when(mockedClient.request(anyString(), anyString(), anyString(), any())) .thenReturn(mockedResponse1, mockedResponse2); ResponseBody functionResponseBody = - ResponseBody.create(MediaType.get("application/json"), functionResponse.toJson()); + ResponseBody.create(functionResponse.toJson(), MediaType.get("application/json")); when(mockedResponse1.getBody()).thenReturn(functionResponseBody); ResponseBody finalResponseBody = - ResponseBody.create(MediaType.get("application/json"), finalResponse.toJson()); + ResponseBody.create(finalResponse.toJson(), MediaType.get("application/json")); when(mockedResponse2.getBody()).thenReturn(finalResponseBody); Field apiClientField = Chats.class.getDeclaredField("apiClient"); @@ -241,14 +241,14 @@ public void testMultiTurnChat() throws Exception { ResponseBody content1 = ResponseBody.create( - MediaType.get("application/json"), "{\"candidates\":[{\"content\":{\"parts\":[{\"text\":\"I am doing" - + " great!\"}],\"role\":\"model\"},\"finishReason\":\"STOP\"}]}}"); + + " great!\"}],\"role\":\"model\"},\"finishReason\":\"STOP\"}]}}", + MediaType.get("application/json")); ResponseBody content2 = ResponseBody.create( - MediaType.get("application/json"), "{\"candidates\":[{\"content\":{\"parts\":[{\"text\":\"I am doing" - + " great!\"}],\"role\":\"model\"},\"finishReason\":\"STOP\"}]}}"); + + " great!\"}],\"role\":\"model\"},\"finishReason\":\"STOP\"}]}}", + MediaType.get("application/json")); when(mockedResponse1.getBody()).thenReturn(content1); when(mockedResponse2.getBody()).thenReturn(content2); when(mockedClient.request(anyString(), anyString(), anyString(), any())) @@ -276,10 +276,10 @@ public void testChatWithConfig() throws Exception { ResponseBody content = ResponseBody.create( - MediaType.get("application/json"), "{\"candidates\":[{\"content\":{\"parts\":[{\"text\":\"The Gouda Life\"}]," + " \"role\":\"model\"}}, {\"content\": {\"parts\":[{\"text\":\"Something" - + " Bleu\"}], \"role\":\"model\"}}]}}"); + + " Bleu\"}], \"role\":\"model\"}}]}}", + MediaType.get("application/json")); when(mockedResponse.getBody()).thenReturn(content); // Make the apiClient field public so that it can be spied on in the tests. This is a @@ -301,10 +301,10 @@ public void testInitConfigIsUsedWhenSendMessageConfigIsNull() throws Exception { ResponseBody content = ResponseBody.create( - MediaType.get("application/json"), "{\"candidates\":[{\"content\":{\"parts\":[{\"text\":\"The Gouda Life\"}]," + " \"role\":\"model\"}}, {\"content\": {\"parts\":[{\"text\":\"Something" - + " Bleu\"}], \"role\":\"model\"}}]}}"); + + " Bleu\"}], \"role\":\"model\"}}]}}", + MediaType.get("application/json")); when(mockedResponse.getBody()).thenReturn(content); // Make the apiClient field public so that it can be spied on in the tests. This is a @@ -325,14 +325,14 @@ public void testSendMessageContent() throws Exception { ResponseBody content1 = ResponseBody.create( - MediaType.get("application/json"), "{\"candidates\":[{\"content\":{\"parts\":[{\"text\":\"It's better with" - + " cheddar\"}],\"role\":\"model\"},\"finishReason\":\"STOP\"}]}}"); + + " cheddar\"}],\"role\":\"model\"},\"finishReason\":\"STOP\"}]}}", + MediaType.get("application/json")); ResponseBody content2 = ResponseBody.create( - MediaType.get("application/json"), "{\"candidates\":[{\"content\":{\"parts\":[{\"text\":\"It's better with" - + " cheddar\"}],\"role\":\"model\"},\"finishReason\":\"STOP\"}]}}"); + + " cheddar\"}],\"role\":\"model\"},\"finishReason\":\"STOP\"}]}}", + MediaType.get("application/json")); when(mockedResponse1.getBody()).thenReturn(content1); when(mockedResponse2.getBody()).thenReturn(content2); @@ -363,14 +363,14 @@ public void testSendMessageContentList() throws Exception { ResponseBody content1 = ResponseBody.create( - MediaType.get("application/json"), "{\"candidates\":[{\"content\":{\"parts\":[{\"text\":\"It's better with" - + " cheddar\"}],\"role\":\"model\"},\"finishReason\":\"STOP\"}]}}"); + + " cheddar\"}],\"role\":\"model\"},\"finishReason\":\"STOP\"}]}}", + MediaType.get("application/json")); ResponseBody content2 = ResponseBody.create( - MediaType.get("application/json"), "{\"candidates\":[{\"content\":{\"parts\":[{\"text\":\"It's better with" - + " cheddar\"}],\"role\":\"model\"},\"finishReason\":\"STOP\"}]}}"); + + " cheddar\"}],\"role\":\"model\"},\"finishReason\":\"STOP\"}]}}", + MediaType.get("application/json")); when(mockedResponse1.getBody()).thenReturn(content1); when(mockedResponse2.getBody()).thenReturn(content2); @@ -402,9 +402,9 @@ public void testSendMessageContentList() throws Exception { public void testUnexpectedFinishReasonDoesNotAddToCuratedHistory() throws Exception { ResponseBody content = ResponseBody.create( - MediaType.get("application/json"), "{\"candidates\":[{\"content\":{\"parts\":[{\"text\":\"It's better with" - + " cheddar\"}], \"role\":\"model\"}, \"finishReason\":\"BLOCKLIST\"}]}"); + + " cheddar\"}], \"role\":\"model\"}, \"finishReason\":\"BLOCKLIST\"}]}", + MediaType.get("application/json")); when(mockedResponse.getBody()).thenReturn(content); // Make the apiClient field public so that it can be spied on in the tests. This is a @@ -430,10 +430,10 @@ public void testInvalidRoleThrows() throws Exception { ResponseBody content = ResponseBody.create( - MediaType.get("application/json"), "{\"candidates\":[{\"content\":{\"parts\":[{\"text\":\"The Gouda Life\"}]," + " \"role\":\"Mr. Cheese\"}}, {\"content\": {\"parts\":[{\"text\":\"Something" - + " Bleu\"}], \"role\":\"model\"}}]}}"); + + " Bleu\"}], \"role\":\"model\"}}]}}", + MediaType.get("application/json")); when(mockedResponse.getBody()).thenReturn(content); // Make the apiClient field public so that it can be spied on in the tests. This is a @@ -458,10 +458,10 @@ public void testInvalidHistoryThrows() throws Exception { ResponseBody content = ResponseBody.create( - MediaType.get("application/json"), "{\"candidates\":[{\"content\":{\"parts\":[{\"text\":\"The Gouda Life\"}]," + " \"role\":\"model\"}}, {\"content\": {\"parts\":[{\"text\":\"Something" - + " Bleu\"}], \"role\":\"model\"}}]}}"); + + " Bleu\"}], \"role\":\"model\"}}]}}", + MediaType.get("application/json")); when(mockedResponse.getBody()).thenReturn(content); // Make the apiClient field public so that it can be spied on in the tests. This is a @@ -493,9 +493,9 @@ public void testIterateOverResponseStream() throws Exception { Chat chatSession = client.chats.create("gemini-2.0-flash-exp", null); - ResponseBody body1 = ResponseBody.create(MediaType.get("application/json"), streamData); - ResponseBody body2 = ResponseBody.create(MediaType.get("application/json"), streamData2); - ResponseBody body3 = ResponseBody.create(MediaType.get("application/json"), nonStreamData); + ResponseBody body1 = ResponseBody.create(streamData, MediaType.get("application/json")); + ResponseBody body2 = ResponseBody.create(streamData2, MediaType.get("application/json")); + ResponseBody body3 = ResponseBody.create(nonStreamData, MediaType.get("application/json")); when(mockedResponse1.getBody()).thenReturn(body1); when(mockedResponse2.getBody()).thenReturn(body2); @@ -577,8 +577,8 @@ public void testThrowsIfStreamResponseIsNotConsumed() throws Exception { Chat chatSession = client.chats.create("gemini-2.0-flash-exp", null); - ResponseBody body1 = ResponseBody.create(MediaType.get("application/json"), streamData); - ResponseBody body2 = ResponseBody.create(MediaType.get("application/json"), streamData2); + ResponseBody body1 = ResponseBody.create(streamData, MediaType.get("application/json")); + ResponseBody body2 = ResponseBody.create(streamData2, MediaType.get("application/json")); when(mockedResponse1.getBody()).thenReturn(body1); when(mockedResponse2.getBody()).thenReturn(body2); when(mockedClient.request(anyString(), anyString(), anyString(), any())) diff --git a/src/test/java/com/google/genai/FakeUploadApiClient.java b/src/test/java/com/google/genai/FakeUploadApiClient.java index d6a6df81ae8..7956eb2fbe0 100644 --- a/src/test/java/com/google/genai/FakeUploadApiClient.java +++ b/src/test/java/com/google/genai/FakeUploadApiClient.java @@ -100,7 +100,7 @@ public ApiResponse request( fileUploadFailureCount.remove(path); } return new FakeApiResponse( - Headers.of(), ResponseBody.create(MediaType.get("text/plain"), "")); + Headers.of(), ResponseBody.create("", MediaType.get("text/plain"))); } file.uploadedByteCount += requestBytes.length; @@ -113,7 +113,7 @@ public ApiResponse request( return new FakeApiResponse( Headers.of("X-Goog-Upload-Status", uploadStatus), - ResponseBody.create(MediaType.get("text/plain"), "")); + ResponseBody.create("", MediaType.get("text/plain"))); } public class UploadedFile { diff --git a/src/test/java/com/google/genai/ForwardCompatibilityTest.java b/src/test/java/com/google/genai/ForwardCompatibilityTest.java index 82f06687ede..cbc6025334c 100644 --- a/src/test/java/com/google/genai/ForwardCompatibilityTest.java +++ b/src/test/java/com/google/genai/ForwardCompatibilityTest.java @@ -75,7 +75,7 @@ public void testForwardCompatibility() throws Exception { objectNode.put("unknownFieldToTestForwardCompatibility", "Hello World!"); String jsonString = objectMapper.writeValueAsString(objectNode); - ResponseBody responseBody = ResponseBody.create(JSON, jsonString); + ResponseBody responseBody = ResponseBody.create(jsonString, JSON); when(mockedResponse.getBody()).thenReturn(responseBody); // Make the apiClient field public so that it can be spied on in the tests. This is a @@ -108,7 +108,7 @@ public void testEnumForwardCompatibilityFinishReason() throws Exception { rootObjectNode.putArray("candidates").addAll(candidatesArray); String jsonString = objectMapper.writeValueAsString(rootNode); - ResponseBody responseBody = ResponseBody.create(JSON, jsonString); + ResponseBody responseBody = ResponseBody.create(jsonString, JSON); when(mockedResponse.getBody()).thenReturn(responseBody); // Make the apiClient field public so that it can be spied on in the tests. This is a @@ -147,7 +147,7 @@ public void testFinishReasonEnumReturnsEnum() throws Exception { rootObjectNode.putArray("candidates").addAll(candidatesArray); String jsonString = objectMapper.writeValueAsString(rootNode); - ResponseBody responseBody = ResponseBody.create(JSON, jsonString); + ResponseBody responseBody = ResponseBody.create(jsonString, JSON); when(mockedResponse.getBody()).thenReturn(responseBody); // Make the apiClient field public so that it can be spied on in the tests. This is a @@ -180,12 +180,12 @@ public void testEnumForwardCompatibilitySafetyFilterLevel() throws Exception { safetyRatingsObjectNode.put("category", "UNKNOWN_SAFETY_RATING_VALUE"); safetyRatingsArray.add(safetyRatingsObjectNode); - candidateObject.put("safetyRatings", safetyRatingsArray); + candidateObject.set("safetyRatings", safetyRatingsArray); candidatesArray.add(candidateObject); rootObjectNode.putArray("candidates").addAll(candidatesArray); String jsonString = objectMapper.writeValueAsString(rootNode); - ResponseBody responseBody = ResponseBody.create(JSON, jsonString); + ResponseBody responseBody = ResponseBody.create(jsonString, JSON); when(mockedResponse.getBody()).thenReturn(responseBody); // Make the apiClient field public so that it can be spied on in the tests. This is a @@ -232,7 +232,7 @@ public void testEnumSendingUnknownSafetysettings() throws Exception { Field apiClientField = Models.class.getDeclaredField("apiClient"); apiClientField.setAccessible(true); apiClientField.set(client.models, mockedClient); - when(mockedResponse.getBody()).thenReturn(ResponseBody.create(JSON, "{}")); + when(mockedResponse.getBody()).thenReturn(ResponseBody.create("{}", JSON)); GenerateContentResponse response = client.models.generateContent("gemini-2.0-flash-exp", "What is your name?", config); diff --git a/src/test/java/com/google/genai/HttpApiClientTest.java b/src/test/java/com/google/genai/HttpApiClientTest.java index 3f5787a425b..74babac0558 100644 --- a/src/test/java/com/google/genai/HttpApiClientTest.java +++ b/src/test/java/com/google/genai/HttpApiClientTest.java @@ -96,7 +96,7 @@ private void setMockClient(HttpApiClient client) throws Exception { .protocol(Protocol.HTTP_1_1) .code(200) .message("OK") - .body(ResponseBody.create(null, "{}")) + .body(ResponseBody.create("{}", null)) .build(); when(mockHttpClient.newCall(any())).thenReturn(mockCall); when(mockCall.execute()).thenReturn(mockResponse); diff --git a/src/test/java/com/google/genai/TransformersTest.java b/src/test/java/com/google/genai/TransformersTest.java index dcad8cf75b9..85f2305eda8 100644 --- a/src/test/java/com/google/genai/TransformersTest.java +++ b/src/test/java/com/google/genai/TransformersTest.java @@ -386,7 +386,7 @@ public void tExtractModels_noModels_returnEmptyArrayNode() { @Test public void tExtractModels_responseWithModels() { ObjectNode origin = JsonSerializable.objectMapper.createObjectNode(); - origin.put( + origin.set( "models", JsonSerializable.objectMapper.createArrayNode().add("model-1").add("model-2")); JsonNode models = Transformers.tExtractModels(origin); @@ -397,7 +397,7 @@ public void tExtractModels_responseWithModels() { @Test public void tExtractModels_responseWithTunedModels() { ObjectNode origin = JsonSerializable.objectMapper.createObjectNode(); - origin.put("tunedModels", JsonSerializable.objectMapper.createArrayNode().add("tuned-model-1")); + origin.set("tunedModels", JsonSerializable.objectMapper.createArrayNode().add("tuned-model-1")); JsonNode models = Transformers.tExtractModels(origin); assertTrue(models instanceof ArrayNode); @@ -407,7 +407,7 @@ public void tExtractModels_responseWithTunedModels() { @Test public void tExtractModels_responseWithPublisherModels() { ObjectNode origin = JsonSerializable.objectMapper.createObjectNode(); - origin.put( + origin.set( "publisherModels", JsonSerializable.objectMapper.createArrayNode().add("publisher-model-1")); diff --git a/src/test/java/com/google/genai/errors/ApiExceptionTest.java b/src/test/java/com/google/genai/errors/ApiExceptionTest.java index 67bca4ed752..92c99196bb0 100644 --- a/src/test/java/com/google/genai/errors/ApiExceptionTest.java +++ b/src/test/java/com/google/genai/errors/ApiExceptionTest.java @@ -224,7 +224,7 @@ private static Response createFakeResponse(int statusCode, String reasonPhrase, .protocol(Protocol.HTTP_1_1) .code(statusCode) .message(reasonPhrase) - .body(body != null ? ResponseBody.create(MediaType.get("application/json"), body) : null) + .body(body != null ? ResponseBody.create(body, MediaType.get("application/json")) : null) .build(); } @@ -234,7 +234,7 @@ private static ArrayNode createErrorNode(String message, String status, int code node.put("status", status); node.put("code", code); ObjectNode errorNode = OBJECT_MAPPER.createObjectNode(); - errorNode.put("error", node); + errorNode.set("error", node); return OBJECT_MAPPER.createArrayNode().add(errorNode); } } From 826c0dca02e06fcb6c7980259b23e955db176ec6 Mon Sep 17 00:00:00 2001 From: Matthew Tang Date: Tue, 22 Jul 2025 10:57:13 -0700 Subject: [PATCH 100/602] feat: Support API keys for VertexAI mode for Java SDK PiperOrigin-RevId: 785918572 --- src/main/java/com/google/genai/ApiClient.java | 90 +++++++++-- src/main/java/com/google/genai/Client.java | 7 +- .../com/google/genai/ReplayApiClient.java | 2 +- .../java/com/google/genai/ClientTest.java | 13 +- .../com/google/genai/HttpApiClientTest.java | 145 +++++++++++++++++- 5 files changed, 226 insertions(+), 31 deletions(-) diff --git a/src/main/java/com/google/genai/ApiClient.java b/src/main/java/com/google/genai/ApiClient.java index 13c694eafdf..07a6720b00a 100644 --- a/src/main/java/com/google/genai/ApiClient.java +++ b/src/main/java/com/google/genai/ApiClient.java @@ -120,28 +120,88 @@ protected ApiClient( ImmutableMap environmentVariables = defaultEnvironmentVariables(); - String apiKeyValue = apiKey.orElseGet(() -> environmentVariables.get("apiKey")); - String projectValue = project.orElseGet(() -> environmentVariables.get("project")); - String locationValue = location.orElseGet(() -> environmentVariables.get("location")); + // Retrieve implicitly set values from the environment. + String envApiKeyValue = environmentVariables.get("apiKey"); + String envProjectValue = environmentVariables.get("project"); + String envLocationValue = environmentVariables.get("location"); + + // Constructor arguments take priority over environment variables. + String apiKeyValue = apiKey.orElse(envApiKeyValue); + String projectValue = project.orElse(envProjectValue); + String locationValue = location.orElse(envLocationValue); + + // Has environment variable values. + boolean hasEnvApiKeyValue = envApiKeyValue != null && !envApiKeyValue.isEmpty(); + boolean hasEnvProjectValue = envProjectValue != null && !envProjectValue.isEmpty(); + boolean hasEnvLocationValue = envLocationValue != null && !envLocationValue.isEmpty(); + + // Constructor arguments. + boolean hasApiKey = apiKey != null && apiKey.isPresent(); + boolean hasCredentials = credentials != null && credentials.isPresent(); + boolean hasProject = project != null && project.isPresent(); + boolean hasLocation = location != null && location.isPresent(); + + // Validate constructor arguments combinations. + if (hasProject && hasApiKey) { + throw new IllegalArgumentException( + "For Vertex AI APIs, project and API key are mutually exclusive in the client" + + " initializer. Please provide only one of them."); + } - boolean hasApiKey = apiKeyValue != null && !apiKeyValue.isEmpty(); - boolean hasProjectAndLocation = - (projectValue != null && !projectValue.isEmpty()) - && (locationValue != null && !locationValue.isEmpty()); + if (hasLocation && hasApiKey) { + throw new IllegalArgumentException( + "For Vertex AI APIs, location and API key are mutually exclusive in the client" + + " initializer. Please provide only one of them."); + } - if (!hasApiKey && !hasProjectAndLocation) { + if (hasCredentials && hasApiKey) { throw new IllegalArgumentException( - "For Vertex AI APIs, either API key, or project/location must be provided or set in the" - + " environment variable."); + "For Vertex AI APIs, API key cannot be set together with credentials. Please provide" + + " only one of them."); + } + + // Handle when to use Vertex AI in express mode (api key). + // Explicit initializer arguments are already validated above. + if (hasCredentials && hasEnvApiKeyValue) { + logger.warning( + "Warning: The user provided Google Cloud credentials will take precedence over the API" + + " key from the environment variable."); + apiKeyValue = null; + } + if (hasApiKey && (hasEnvProjectValue || hasEnvLocationValue)) { + // Explicit API key takes precedence over implicit project/location. + logger.warning( + "Warning: The user provided Vertex AI API key will take precedence over the" + + " project/location from the environment variables."); + projectValue = null; + locationValue = null; + } else if ((hasProject || hasLocation) && hasEnvApiKeyValue) { + // Explicit project/location takes precedence over implicit API key. + logger.warning( + "Warning: The user provided project/location will take precedence over the API key from" + + " the environment variable."); + apiKeyValue = null; + } else if ((hasEnvProjectValue || hasEnvLocationValue) && hasEnvApiKeyValue) { + // Implicit project/location takes precedence over implicit API key. + logger.warning( + "Warning: The project/location from the environment variables will take precedence over" + + " the API key from the environment variable."); + apiKeyValue = null; } - this.apiKey = Optional.ofNullable(projectValue == null ? apiKeyValue : null); + this.apiKey = Optional.ofNullable(apiKeyValue); this.project = Optional.ofNullable(projectValue); this.location = Optional.ofNullable(locationValue); + // Validate that either project and location or API key is set. + if (!((this.project.isPresent() && this.location.isPresent()) || this.apiKey.isPresent())) { + throw new IllegalArgumentException( + "For Vertex AI APIs, either project/location or API key must be set."); + } + // Only set credentials if using project/location. this.credentials = - projectValue == null + !this.project.isPresent() ? Optional.empty() : Optional.of(credentials.orElseGet(() -> defaultCredentials())); @@ -186,7 +246,10 @@ protected Request buildRequest( String capitalizedHttpMethod = Ascii.toUpperCase(httpMethod); boolean queryBaseModel = capitalizedHttpMethod.equals("GET") && path.startsWith("publishers/google/models"); - if (this.vertexAI() && !path.startsWith("projects/") && !queryBaseModel) { + if (this.vertexAI() + && !this.apiKey.isPresent() + && !path.startsWith("projects/") + && !queryBaseModel) { path = String.format("projects/%s/locations/%s/", this.project.get(), this.location.get()) + path; @@ -260,6 +323,7 @@ private void setHeaders(Request.Builder request, HttpOptions requestHttpOptions) } if (apiKey.isPresent()) { + // Sets API key for Gemini Developer API or Vertex AI Express mode request.header("x-goog-api-key", apiKey.get()); } else { GoogleCredentials cred = diff --git a/src/main/java/com/google/genai/Client.java b/src/main/java/com/google/genai/Client.java index bd9d57a47d9..c033cd01fd5 100644 --- a/src/main/java/com/google/genai/Client.java +++ b/src/main/java/com/google/genai/Client.java @@ -207,7 +207,7 @@ private Client( if (vertexAI.isPresent()) { useVertexAI = vertexAI.get(); } else { - String envVar = ApiClient.defaultEnvironmentVariables().get("GOOGLE_GENAI_USE_VERTEXAI"); + String envVar = ApiClient.defaultEnvironmentVariables().get("vertexAI"); useVertexAI = envVar != null && envVar.equalsIgnoreCase("true"); } @@ -221,11 +221,6 @@ private Client( } } - // TODO(jayceeli): Remove this check once we support EasyGCP. - if (apiKey.isPresent() && useVertexAI) { - throw new IllegalArgumentException("Vertex AI APIs do not support API key."); - } - this.debugConfig = debugConfig.orElse(new DebugConfig()); if (this.debugConfig.clientMode().equals("replay")) { if (!useVertexAI) { diff --git a/src/main/java/com/google/genai/ReplayApiClient.java b/src/main/java/com/google/genai/ReplayApiClient.java index 762299f44cd..31f16a14a33 100644 --- a/src/main/java/com/google/genai/ReplayApiClient.java +++ b/src/main/java/com/google/genai/ReplayApiClient.java @@ -213,7 +213,7 @@ private ReplayApiResponse buildResponseFromReplay(ReplayResponse replayResponse) /** * Redact all the url parts before the resource name, so the test can work against any project, - * location, version, or whether it's EasyGCP. + * location, version, or whether it's GCP Express (API keys on Vertex AI). */ private static String redactRequestUrl(String requestUrl) { String result = diff --git a/src/test/java/com/google/genai/ClientTest.java b/src/test/java/com/google/genai/ClientTest.java index 550d39534f5..ee48cb33793 100644 --- a/src/test/java/com/google/genai/ClientTest.java +++ b/src/test/java/com/google/genai/ClientTest.java @@ -131,15 +131,16 @@ public void testReplayClient_vertex() { } @Test - public void testInitClientFromBuilder_setApiKeyInVertex_throwsException() { + public void testInitClientFromBuilder_setApiKeyInVertex() { // Act - IllegalArgumentException exception = - assertThrows( - IllegalArgumentException.class, - () -> Client.builder().apiKey(API_KEY).vertexAI(true).build()); + Client client = Client.builder().apiKey(API_KEY).vertexAI(true).build(); // Assert - assertEquals("Vertex AI APIs do not support API key.", exception.getMessage()); + assertEquals(API_KEY, client.apiKey()); + assertEquals(null, client.project()); + assertEquals(null, client.location()); + assertTrue(client.vertexAI()); + assertEquals("https://aiplatform.googleapis.com", client.baseUrl().orElse(null)); } @Test diff --git a/src/test/java/com/google/genai/HttpApiClientTest.java b/src/test/java/com/google/genai/HttpApiClientTest.java index 74babac0558..96a6aaba3b1 100644 --- a/src/test/java/com/google/genai/HttpApiClientTest.java +++ b/src/test/java/com/google/genai/HttpApiClientTest.java @@ -316,7 +316,7 @@ public void testInitHttpClientVertexWithApiKey() throws Exception { assertEquals(API_KEY, client.apiKey()); assertNull(client.project()); assertNull(client.location()); - // Default to global endpoint for easy GCP. + // GCP Express mode uses global endpoint. assertEquals(Optional.of("https://aiplatform.googleapis.com"), client.httpOptions.baseUrl()); } @@ -334,11 +334,147 @@ public void testInitHttpClientVertexWithNoApiKeyAndNoProject_throwsException() t Optional.empty(), Optional.empty())); assertEquals( - "For Vertex AI APIs, either API key, or project/location must be provided or set in the" - + " environment variable.", + "For Vertex AI APIs, either project/location or API key must be set.", exception.getMessage()); } + @Test + public void testInitHttpClientWithCustomCredentialsAndApiKey_throwsException() throws Exception { + GoogleCredentials credentials = Mockito.mock(GoogleCredentials.class); + IllegalArgumentException exception = + assertThrows( + IllegalArgumentException.class, + () -> + new HttpApiClient( + Optional.of(API_KEY), + Optional.empty(), + Optional.empty(), + Optional.of(credentials), + Optional.empty(), + Optional.empty())); + assertEquals( + "For Vertex AI APIs, API key cannot be set together with credentials. Please provide" + + " only one of them.", + exception.getMessage()); + } + + @Test + public void testInitHttpClientVertexWithProjectLocationAndApiKey_throwsException() + throws Exception { + // Explicit proj/location and API key are not allowed. + IllegalArgumentException exception = + assertThrows( + IllegalArgumentException.class, + () -> + new HttpApiClient( + Optional.of(API_KEY), + Optional.of(PROJECT), + Optional.of(LOCATION), + Optional.empty(), + Optional.empty(), + Optional.empty())); + assertEquals( + "For Vertex AI APIs, project and API key are mutually exclusive in the client initializer." + + " Please provide only one of them.", + exception.getMessage()); + } + + @Test + public void testInitHttpClientVertexExplicitArgPrecedence1( + MockedStatic mockedStaticApiClient) throws Exception { + // Explicit Vertex project and location takes precedence over project and location from + // environment + mockedStaticApiClient + .when(ApiClient::defaultEnvironmentVariables) + .thenReturn(ImmutableMap.of("project", "env-project-id", "location", "env-location")); + HttpApiClient client = + new HttpApiClient( + Optional.empty(), + Optional.of(PROJECT), + Optional.of(LOCATION), + Optional.of(CREDENTIALS), + Optional.empty(), + Optional.empty()); + + assertEquals(PROJECT, client.project()); + assertEquals(LOCATION, client.location()); + assertNull(client.apiKey()); + assertTrue(client.vertexAI()); + assertEquals("https://location-aiplatform.googleapis.com", client.httpOptions.baseUrl().get()); + } + + @Test + public void testInitHttpClientVertexApiKeyCombo1(MockedStatic mockedStaticApiClient) + throws Exception { + // API key from constructor takes precedence over project/location from environment + mockedStaticApiClient + .when(ApiClient::defaultEnvironmentVariables) + .thenReturn(ImmutableMap.of("project", "env-project-id", "location", "env-location")); + HttpApiClient client = + new HttpApiClient( + Optional.of(API_KEY), + Optional.empty(), + Optional.empty(), + Optional.empty(), + Optional.empty(), + Optional.empty()); + + assertNull(client.project()); + assertNull(client.location()); + assertEquals(API_KEY, client.apiKey()); + assertTrue(client.vertexAI()); + assertEquals("https://aiplatform.googleapis.com", client.httpOptions.baseUrl().get()); + } + + @Test + public void testInitHttpClientVertexApiKeyCombo2(MockedStatic mockedStaticApiClient) + throws Exception { + // Proj/location from constructor takes precedence over API key from environment + mockedStaticApiClient + .when(ApiClient::defaultEnvironmentVariables) + .thenReturn(ImmutableMap.of("apiKey", "env-api-key")); + HttpApiClient client = + new HttpApiClient( + Optional.empty(), + Optional.of(PROJECT), + Optional.of(LOCATION), + Optional.of(CREDENTIALS), + Optional.empty(), + Optional.empty()); + + assertEquals(PROJECT, client.project()); + assertEquals(LOCATION, client.location()); + assertNull(client.apiKey()); + assertTrue(client.vertexAI()); + assertEquals("https://location-aiplatform.googleapis.com", client.httpOptions.baseUrl().get()); + } + + @Test + public void testInitHttpClientVertexApiKeyCombo3(MockedStatic mockedStaticApiClient) + throws Exception { + // Proj/location from environment takes precedence over API key from environment + mockedStaticApiClient + .when(ApiClient::defaultEnvironmentVariables) + .thenReturn( + ImmutableMap.of( + "project", "env-project-id", "location", "env-location", "apiKey", "env-api-key")); + HttpApiClient client = + new HttpApiClient( + Optional.empty(), + Optional.empty(), + Optional.empty(), + Optional.of(CREDENTIALS), + Optional.empty(), + Optional.empty()); + + assertEquals("env-project-id", client.project()); + assertEquals("env-location", client.location()); + assertNull(client.apiKey()); + assertTrue(client.vertexAI()); + assertEquals( + "https://env-location-aiplatform.googleapis.com", client.httpOptions.baseUrl().get()); + } + @Test public void testHttpClientVertexWithNoApiKeyAndNoLocation_throwsException() throws Exception { IllegalArgumentException exception = @@ -353,8 +489,7 @@ public void testHttpClientVertexWithNoApiKeyAndNoLocation_throwsException() thro Optional.empty(), Optional.empty())); assertEquals( - "For Vertex AI APIs, either API key, or project/location must be provided or set in the" - + " environment variable.", + "For Vertex AI APIs, either project/location or API key must be set.", exception.getMessage()); } From 45a027b2d0aef1219ec05ac9874f6493180abf94 Mon Sep 17 00:00:00 2001 From: Wanlin Du Date: Tue, 22 Jul 2025 12:06:30 -0700 Subject: [PATCH 101/602] feat: return headers for list method in all modules. PiperOrigin-RevId: 785947079 --- src/main/java/com/google/genai/Batches.java | 2 ++ src/main/java/com/google/genai/Caches.java | 2 ++ src/main/java/com/google/genai/Files.java | 1 + src/main/java/com/google/genai/Models.java | 2 ++ src/main/java/com/google/genai/Tunings.java | 2 ++ 5 files changed, 9 insertions(+) diff --git a/src/main/java/com/google/genai/Batches.java b/src/main/java/com/google/genai/Batches.java index 731ea5d60fe..265e508011c 100644 --- a/src/main/java/com/google/genai/Batches.java +++ b/src/main/java/com/google/genai/Batches.java @@ -2044,6 +2044,7 @@ ObjectNode batchJobFromMldev(JsonNode fromObject, ObjectNode parentObject) { @ExcludeFromGeneratedCoverageReport ObjectNode listBatchJobsResponseFromMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"nextPageToken"}) != null) { Common.setValueByPath( toObject, @@ -2274,6 +2275,7 @@ ObjectNode batchJobFromVertex(JsonNode fromObject, ObjectNode parentObject) { @ExcludeFromGeneratedCoverageReport ObjectNode listBatchJobsResponseFromVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"nextPageToken"}) != null) { Common.setValueByPath( toObject, diff --git a/src/main/java/com/google/genai/Caches.java b/src/main/java/com/google/genai/Caches.java index ead19819ee2..f7e807b750a 100644 --- a/src/main/java/com/google/genai/Caches.java +++ b/src/main/java/com/google/genai/Caches.java @@ -1654,6 +1654,7 @@ ObjectNode deleteCachedContentResponseFromMldev(JsonNode fromObject, ObjectNode @ExcludeFromGeneratedCoverageReport ObjectNode listCachedContentsResponseFromMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"nextPageToken"}) != null) { Common.setValueByPath( toObject, @@ -1741,6 +1742,7 @@ ObjectNode deleteCachedContentResponseFromVertex(JsonNode fromObject, ObjectNode @ExcludeFromGeneratedCoverageReport ObjectNode listCachedContentsResponseFromVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"nextPageToken"}) != null) { Common.setValueByPath( toObject, diff --git a/src/main/java/com/google/genai/Files.java b/src/main/java/com/google/genai/Files.java index 752222ee32c..a2ccc92cd1b 100644 --- a/src/main/java/com/google/genai/Files.java +++ b/src/main/java/com/google/genai/Files.java @@ -435,6 +435,7 @@ ObjectNode fileFromMldev(JsonNode fromObject, ObjectNode parentObject) { @ExcludeFromGeneratedCoverageReport ObjectNode listFilesResponseFromMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"nextPageToken"}) != null) { Common.setValueByPath( toObject, diff --git a/src/main/java/com/google/genai/Models.java b/src/main/java/com/google/genai/Models.java index a652b0eec7b..8c6f1454e40 100644 --- a/src/main/java/com/google/genai/Models.java +++ b/src/main/java/com/google/genai/Models.java @@ -4605,6 +4605,7 @@ ObjectNode modelFromMldev(JsonNode fromObject, ObjectNode parentObject) { @ExcludeFromGeneratedCoverageReport ObjectNode listModelsResponseFromMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"nextPageToken"}) != null) { Common.setValueByPath( toObject, @@ -5565,6 +5566,7 @@ ObjectNode modelFromVertex(JsonNode fromObject, ObjectNode parentObject) { @ExcludeFromGeneratedCoverageReport ObjectNode listModelsResponseFromVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"nextPageToken"}) != null) { Common.setValueByPath( toObject, diff --git a/src/main/java/com/google/genai/Tunings.java b/src/main/java/com/google/genai/Tunings.java index 55b29ac79de..37b417927cf 100644 --- a/src/main/java/com/google/genai/Tunings.java +++ b/src/main/java/com/google/genai/Tunings.java @@ -610,6 +610,7 @@ ObjectNode tuningJobFromMldev(JsonNode fromObject, ObjectNode parentObject) { @ExcludeFromGeneratedCoverageReport ObjectNode listTuningJobsResponseFromMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"nextPageToken"}) != null) { Common.setValueByPath( toObject, @@ -898,6 +899,7 @@ ObjectNode tuningJobFromVertex(JsonNode fromObject, ObjectNode parentObject) { @ExcludeFromGeneratedCoverageReport ObjectNode listTuningJobsResponseFromVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"nextPageToken"}) != null) { Common.setValueByPath( toObject, From dcf70cc64a93355cdc6a2eedf172399dd332750e Mon Sep 17 00:00:00 2001 From: Jaycee Li Date: Tue, 22 Jul 2025 12:28:24 -0700 Subject: [PATCH 102/602] docs: Update README with latest features in Client PiperOrigin-RevId: 785954620 --- README.md | 100 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 98 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index bfc29b7fc97..fed4ebfc65a 100644 --- a/README.md +++ b/README.md @@ -42,6 +42,9 @@ Client client = Client.builder().apiKey("your-api-key").build(); ``` #### Instantiate a client that uses Vertex AI API + +##### Using project and location + ```java import com.google.genai.Client; @@ -54,33 +57,126 @@ Client client = Client.builder() .build(); ``` +##### Using API key on Vertex AI (GCP Express Mode) + +```java +import com.google.genai.Client; + +// Explicitly set the `apiKey` and `vertexAI(true)` to use Vertex AI backend +// in express mode. +Client client = Client.builder() + .apiKey("your-api-key") + .vertexAI(true) + .build(); +``` + #### (Optional) Using environment variables: You can create a client by configuring the necessary environment variables. Configuration setup instructions depends on whether you're using the Gemini Developer API or the Gemini API in Vertex AI. -**Gemini Developer API:** Set `GOOGLE_API_KEY` as shown below: +**Gemini Developer API:** Set the `GOOGLE_API_KEY`. It will automatically be +picked up by the client. Note that `GEMINI_API_KEY` is a legacy environment +variable, it's recommended to use `GOOGLE_API_KEY` only. But if both are set, +`GOOGLE_API_KEY` takes precedence. ```bash export GOOGLE_API_KEY='your-api-key' ``` **Gemini API on Vertex AI:** Set `GOOGLE_GENAI_USE_VERTEXAI`, -`GOOGLE_CLOUD_PROJECT` and `GOOGLE_CLOUD_LOCATION`, as shown below: +`GOOGLE_CLOUD_PROJECT` and `GOOGLE_CLOUD_LOCATION`, or `GOOGLE_API_KEY` for +Vertex AI express mode. It's recommended that you set only project & location, +or API key. But if both are set, project & location takes precedence. ```bash export GOOGLE_GENAI_USE_VERTEXAI=true + +// Set project and location for Vertex AI authentication export GOOGLE_CLOUD_PROJECT='your-project-id' export GOOGLE_CLOUD_LOCATION='us-central1' +// or API key for express mode +export GOOGLE_API_KEY='your-api-key' ``` +After configuring the environment variables, you can instantiate a client +without passing any variables. + ```java import com.google.genai.Client; Client client = new Client(); ``` +### API Selection + +By default, the SDK uses the beta API endpoints provided by Google to support +preview features in the APIs. The stable API endpoints can be selected by +setting the API version to `v1`. + +To set the API version use `HttpOptions`. For example, to set the API version to +`v1` for Vertex AI: + +```java +import com.google.genai.Client; +import com.google.genai.types.HttpOptions; + +Client client = Client.builder() + .project("your-project") + .location("your-location") + .vertexAI(true) + .httpOptions(HttpOptions.builder().apiVersion("v1")) + .build(); +``` + +To set the API version to `v1alpha` for the Gemini Developer API: + +```java +import com.google.genai.Client; +import com.google.genai.types.HttpOptions; + +Client client = Client.builder() + .apiKey("your-api-key") + .httpOptions(HttpOptions.builder().apiVersion("v1alpha")) + .build(); +``` + +### HttpOptions + +Besides `apiVersion`, [HttpOptions](https://github.com/googleapis/java-genai/blob/main/src/main/java/com/google/genai/types/HttpOptions.java) +also allows for flexible customization of HTTP request parameters such as +`baseUrl`, `headers`, and `timeout`: + +```java +HttpOptions httpOptions = HttpOptions.builder() + .baseUrl("your-own-endpoint.com") + .headers(ImmutableMap.of("key", "value")) + .timeout(600) + .build(); +``` + +Beyond client-level configuration, `HttpOptions` can also be set on a +per-request basis, providing maximum flexibility for diverse API call settings. +See [this example](https://github.com/googleapis/java-genai/blob/main/examples/src/main/java/com/google/genai/examples/RequestLevelHttpOptions.java) +for more details. + +### ClientOptions +[ClientOptions](https://github.com/googleapis/java-genai/blob/main/src/main/java/com/google/genai/types/ClientOptions.java) +enables you to customize the behavior of the HTTP client. It currently supports +configuring the connection pool via `maxConnections` (total maximum connections) +and `maxConnectionsPerHost` (maximum connections to a single host). + +```java +import com.google.genai.Client; +import com.google.genai.types.ClientOptions; + +Client client = Client.builder() + .apiKey("your-api-key") + .clientOptions(ClientOptions.builder().maxConnections(64).maxConnectionsPerHost(16)) + .build(); +``` + ### Interact with models The Gen AI Java SDK allows you to access the service programmatically. The following code snippets are some basic usages of model inferencing. From 30e71eca143c18cfb6f6e77bebc4e37164a43f3f Mon Sep 17 00:00:00 2001 From: Ayush Agrawal Date: Tue, 22 Jul 2025 15:47:50 -0700 Subject: [PATCH 103/602] chore: Add replay tests for Java async Models module PiperOrigin-RevId: 786025609 --- .../com/google/genai/AsyncModelsTest.java | 876 ++++++++++++++++++ src/test/resources/bridge1.png | Bin 0 -> 793056 bytes 2 files changed, 876 insertions(+) create mode 100644 src/test/java/com/google/genai/AsyncModelsTest.java create mode 100644 src/test/resources/bridge1.png diff --git a/src/test/java/com/google/genai/AsyncModelsTest.java b/src/test/java/com/google/genai/AsyncModelsTest.java new file mode 100644 index 00000000000..861da83f539 --- /dev/null +++ b/src/test/java/com/google/genai/AsyncModelsTest.java @@ -0,0 +1,876 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.genai; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import com.google.common.collect.ImmutableMap; +import com.google.genai.types.ComputeTokensResponse; +import com.google.genai.types.Content; +import com.google.genai.types.CountTokensResponse; +import com.google.genai.types.DeleteModelConfig; +import com.google.genai.types.DeleteModelResponse; +import com.google.genai.types.EditImageConfig; +import com.google.genai.types.EditImageResponse; +import com.google.genai.types.EditMode; +import com.google.genai.types.EmbedContentConfig; +import com.google.genai.types.EmbedContentResponse; +import com.google.genai.types.GenerateContentConfig; +import com.google.genai.types.GenerateContentResponse; +import com.google.genai.types.GenerateImagesConfig; +import com.google.genai.types.GenerateImagesResponse; +import com.google.genai.types.GenerateVideosConfig; +import com.google.genai.types.GenerateVideosOperation; +import com.google.genai.types.GetModelConfig; +import com.google.genai.types.GoogleSearchRetrieval; +import com.google.genai.types.HttpOptions; +import com.google.genai.types.Image; +import com.google.genai.types.ListModelsConfig; +import com.google.genai.types.MaskReferenceConfig; +import com.google.genai.types.MaskReferenceImage; +import com.google.genai.types.Model; +import com.google.genai.types.Part; +import com.google.genai.types.RagRetrievalConfig; +import com.google.genai.types.RagRetrievalConfigFilter; +import com.google.genai.types.RawReferenceImage; +import com.google.genai.types.Retrieval; +import com.google.genai.types.Tool; +import com.google.genai.types.ToolCodeExecution; +import com.google.genai.types.UpdateModelConfig; +import com.google.genai.types.UpscaleImageConfig; +import com.google.genai.types.UpscaleImageResponse; +import com.google.genai.types.VertexAISearch; +import com.google.genai.types.VertexRagStore; +import com.google.genai.types.VertexRagStoreRagResource; +import java.net.URL; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Arrays; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionException; +import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable; +import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; + +@EnabledIfEnvironmentVariable( + named = "GOOGLE_GENAI_REPLAYS_DIRECTORY", + matches = ".*genai/replays.*") +@ExtendWith(EnvironmentVariablesMockingExtension.class) +public class AsyncModelsTest { + /** Creates a raw reference image for edit image tests. */ + private RawReferenceImage createRawReferenceImage() throws Exception { + URL resourceUrl = getClass().getClassLoader().getResource("google.png"); + Path filePath = Paths.get(resourceUrl.toURI()); + Image image = Image.fromFile(filePath.toAbsolutePath().toString()); + return RawReferenceImage.builder().referenceImage(image).referenceId(1).build(); + } + + /** Creates a mask reference image for edit image tests. */ + private MaskReferenceImage createMaskReferenceImage() { + return MaskReferenceImage.builder() + .referenceId(2) + .config(MaskReferenceConfig.builder().maskMode("MASK_MODE_BACKGROUND").maskDilation(0.06f)) + .build(); + } + + @ParameterizedTest + @ValueSource(booleans = {false, true}) + public void testGenerateContent_withContentAsync(boolean vertexAI) throws Exception { + // Arrange + String suffix = vertexAI ? "vertex" : "mldev"; + Client client = + TestUtils.createClient( + vertexAI, "tests/models/generate_content/test_async." + suffix + ".json"); + + GenerateContentConfig config = + GenerateContentConfig.builder() + .httpOptions(HttpOptions.builder().headers(ImmutableMap.of("test", "headers"))) + .build(); + + // Act + CompletableFuture responseFuture = + client.async.models.generateContent( + "gemini-1.5-flash", + Content.fromParts(Part.fromText("Tell me a story in 300 words.")), + config); + GenerateContentResponse response = responseFuture.join(); + + // Assert + assertNotNull(response.text()); + } + + @ParameterizedTest + @ValueSource(booleans = {false, true}) + public void testListModelsAsync(boolean vertexAI) throws Exception { + // Arrange + String suffix = vertexAI ? "vertex" : "mldev"; + Client client = + TestUtils.createClient( + vertexAI, "tests/models/list/test_base_models_async_pager." + suffix + ".json"); + + // Act + AsyncPager pager = + client + .async + .models + .list(ListModelsConfig.builder().pageSize(10).queryBase(true).build()) + .get(); + + // Assert + assertEquals(10, pager.size().get()); + pager.forEach(item -> assertNotNull(item)).get(); + } + + @ParameterizedTest + @ValueSource(booleans = {false, true}) + public void testListTunedModelsAsync(boolean vertexAI) throws Exception { + // Arrange + String suffix = vertexAI ? "vertex" : "mldev"; + Client client = + TestUtils.createClient( + vertexAI, "tests/models/list/test_tuned_models_async_pager." + suffix + ".json"); + + // Act + AsyncPager pager = + client + .async + .models + .list(ListModelsConfig.builder().pageSize(10).queryBase(false).build()) + .get(); + + // Assert + assertEquals(10, pager.size().get()); + pager.forEach(item -> assertNotNull(item)).get(); + } + + @ParameterizedTest + @ValueSource(booleans = {false, true}) + public void testGenerateContent_withHeadersAsync(boolean vertexAI) throws Exception { + // Arrange + String suffix = vertexAI ? "vertex" : "mldev"; + Client client = + TestUtils.createClient( + vertexAI, "tests/models/generate_content/test_async_with_headers." + suffix + ".json"); + + // Act + CompletableFuture responseFuture = + client.async.models.generateContent( + "gemini-1.5-flash", + Content.fromParts(Part.fromText("Tell me a story in 300 words.")), + null); + GenerateContentResponse response = responseFuture.join(); + + // Assert + assertNotNull(response.text()); + } + + @ParameterizedTest + @ValueSource(booleans = {false, true}) + public void testGenerateContentStream_withContentAsync(boolean vertexAI) throws Exception { + // Arrange + String suffix = vertexAI ? "vertex" : "mldev"; + Client client = + TestUtils.createClient( + vertexAI, "tests/models/generate_content/test_async_stream." + suffix + ".json"); + + // Act + GenerateContentConfig config = + GenerateContentConfig.builder() + .httpOptions(HttpOptions.builder().headers(ImmutableMap.of("test", "headers"))) + .build(); + CompletableFuture> responseStreamFuture = + client.async.models.generateContentStream( + "gemini-1.5-flash", "Tell me a story in 300 words.", config); + ResponseStream responseStream = responseStreamFuture.join(); + + // Assert + int chunks = 0; + for (GenerateContentResponse response : responseStream) { + chunks++; + assertNotNull(response.text()); + } + assertTrue(chunks > 2); + assertTrue(responseStream.isConsumed()); + } + + @ParameterizedTest + @ValueSource(booleans = {false, true}) + public void testGenerateContentStream_withHeadersAsync(boolean vertexAI) throws Exception { + // Arrange + String suffix = vertexAI ? "vertex" : "mldev"; + Client client = + TestUtils.createClient( + vertexAI, + "tests/models/generate_content/test_async_stream_with_headers." + suffix + ".json"); + + // Act + GenerateContentConfig config = + GenerateContentConfig.builder() + .httpOptions(HttpOptions.builder().headers(ImmutableMap.of("test", "headers"))) + .build(); + CompletableFuture> responseStreamFuture = + client.async.models.generateContentStream( + "gemini-1.5-flash", "Tell me a story in 300 words.", config); + + ResponseStream responseStream = responseStreamFuture.join(); + + // Assert + int chunks = 0; + for (GenerateContentResponse response : responseStream) { + chunks++; + assertNotNull(response.text()); + } + assertTrue(chunks > 2); + assertTrue(responseStream.isConsumed()); + } + + @ParameterizedTest + @ValueSource(booleans = {false, true}) + public void testGenerateContent_withContentAndConfigAsync(boolean vertexAI) throws Exception { + // Arrange + String suffix = vertexAI ? "vertex" : "mldev"; + Client client = + TestUtils.createClient( + vertexAI, + "tests/models/generate_content/test_simple_shared_generation_config_async." + + suffix + + ".json"); + + // Act + GenerateContentConfig config = + GenerateContentConfig.builder() + .maxOutputTokens(400) + .topK(2f) + .temperature(0.5f) + .topP(0.5f) + .responseMimeType("application/json") + .stopSequences("\n") + .seed(42) + .build(); + CompletableFuture responseFuture = + client.async.models.generateContent( + "gemini-1.5-flash", + Content.fromParts(Part.fromText("tell me a story in 300 words")), + config); + GenerateContentResponse response = responseFuture.join(); + + // Assert + assertNotNull(response.text()); + } + + @ParameterizedTest + @ValueSource(booleans = {false, true}) + public void testGenerateContentStream_withContentAndConfig(boolean vertexAI) throws Exception { + // Arrange + String suffix = vertexAI ? "vertex" : "mldev"; + Client client = + TestUtils.createClient( + vertexAI, + "tests/models/generate_content/test_simple_shared_generation_config_stream." + + suffix + + ".json"); + + // Act + GenerateContentConfig config = + GenerateContentConfig.builder() + .maxOutputTokens(400) + .topK(2f) + .temperature(0.5f) + .topP(0.5f) + .responseMimeType("application/json") + .stopSequences("\n") + .seed(42) + .build(); + CompletableFuture> responseStreamFuture = + client.async.models.generateContentStream( + "gemini-1.5-flash", + Content.fromParts(Part.fromText("tell me a story in 300 words")), + config); + ResponseStream responseStream = responseStreamFuture.join(); + + // Assert + int chunks = 0; + for (GenerateContentResponse response : responseStream) { + chunks++; + assertNotNull(response.text()); + } + assertTrue(chunks > 2); + assertTrue(responseStream.isConsumed()); + } + + @ParameterizedTest + @ValueSource(booleans = {false, true}) + public void testEmbedContentAsync(boolean vertexAI) throws Exception { + // Arrange + String suffix = vertexAI ? "vertex" : "mldev"; + Client client = + TestUtils.createClient( + vertexAI, "tests/models/embed_content/test_async." + suffix + ".json"); + + EmbedContentConfig config = EmbedContentConfig.builder().outputDimensionality(10).build(); + + // Act + CompletableFuture responseFuture = + client.async.models.embedContent("text-embedding-004", "What is your name?", config); + EmbedContentResponse response = responseFuture.join(); + + // Assert + assertTrue(response.embeddings().isPresent()); + assertEquals(1, response.embeddings().get().size()); + } + + @ParameterizedTest + @ValueSource(booleans = {false, true}) + public void testCountTokensAsync(boolean vertexAI) throws Exception { + // Arrange + String suffix = vertexAI ? "vertex" : "mldev"; + Client client = + TestUtils.createClient( + vertexAI, "tests/models/count_tokens/test_async." + suffix + ".json"); + + // Act + CompletableFuture responseFuture = + client.async.models.countTokens("gemini-1.5-flash", "Tell me a story in 300 words.", null); + CountTokensResponse response = responseFuture.join(); + + // Assert + assertTrue(response.totalTokens().isPresent()); + } + + @ParameterizedTest + @ValueSource(booleans = {false, true}) + public void testComputeTokensAsync(boolean vertexAI) throws Exception { + if (!vertexAI) { + return; + } + + // Arrange + String suffix = vertexAI ? "vertex" : "mldev"; + Client client = + TestUtils.createClient( + vertexAI, "tests/models/compute_tokens/test_async." + suffix + ".json"); + + // Act + CompletableFuture responseFuture = + client.async.models.computeTokens( + "gemini-1.5-flash", "Tell me a story in 300 words.", null); + ComputeTokensResponse response = responseFuture.join(); + + // Assert + assertTrue(response.tokensInfo().isPresent()); + } + + @ParameterizedTest + @ValueSource(booleans = {false, true}) + public void testEditImage_withMaskReferenceAsync(boolean vertexAI) throws Exception { + // Arrange + String suffix = vertexAI ? "vertex" : "mldev"; + Client client = + TestUtils.createClient( + vertexAI, "tests/models/edit_image/test_edit_mask_inpaint_insert." + suffix + ".json"); + + EditImageConfig config = + EditImageConfig.builder() + .editMode(EditMode.Known.EDIT_MODE_INPAINT_INSERTION) + .numberOfImages(1) + .negativePrompt("human") + .guidanceScale(15.0f) + .safetyFilterLevel("BLOCK_MEDIUM_AND_ABOVE") + .personGeneration("DONT_ALLOW") + .includeSafetyAttributes(false) + .includeRaiReason(true) + .outputMimeType("image/jpeg") + .outputCompressionQuality(80) + .baseSteps(32) + .addWatermark(false) + .build(); + + // Act + if (vertexAI) { + CompletableFuture responseFuture = + client.async.models.editImage( + "imagen-3.0-capability-001", + "Sunlight and clear weather", + Arrays.asList(createRawReferenceImage(), createMaskReferenceImage()), + config); + EditImageResponse response = responseFuture.join(); + + // Assert + assertTrue(response.generatedImages().get().get(0).image().isPresent()); + } else { + CompletionException exception = + assertThrows( + CompletionException.class, + () -> + client + .async + .models + .editImage( + "imagen-3.0-capability-001", + "Sunlight and clear weather", + Arrays.asList(createRawReferenceImage(), createMaskReferenceImage()), + config) + .join()); + // Assert + assertEquals( + "This method is only supported in the Vertex AI client.", + exception.getCause().getMessage()); + } + } + + @ParameterizedTest + @ValueSource(booleans = {false, true}) + public void testGoogleSearchRetrievalAsync(boolean vertexAI) throws Exception { + // Arrange + String suffix = vertexAI ? "vertex" : "mldev"; + Client client = + TestUtils.createClient( + vertexAI, + "tests/models/generate_content_tools/test_google_search_retrieval." + suffix + ".json"); + + Tool tool = Tool.builder().googleSearchRetrieval(GoogleSearchRetrieval.builder()).build(); + GenerateContentConfig config = GenerateContentConfig.builder().tools(tool).build(); + + // Act + CompletableFuture responseFuture = + client.async.models.generateContent("gemini-1.5-flash", "Why is the sky blue?", config); + GenerateContentResponse response = responseFuture.join(); + + // Assert + assertNotNull(response.text()); + } + + @ParameterizedTest + @ValueSource(booleans = {true}) // Only for Vertex + public void testVaiSearchAsync(boolean vertexAI) throws Exception { + // Arrange + String suffix = vertexAI ? "vertex" : "mldev"; + Client client = + TestUtils.createClient( + vertexAI, "tests/models/generate_content_tools/test_vai_search." + suffix + ".json"); + + Tool tool = + Tool.builder() + .retrieval( + Retrieval.builder() + .vertexAiSearch( + VertexAISearch.builder() + .datastore( + "projects/vertex-sdk-dev/locations/global/collections/default_collection/dataStores/yvonne_1728691676574"))) + .build(); + GenerateContentConfig config = GenerateContentConfig.builder().tools(tool).build(); + + // Act + CompletableFuture responseFuture = + client.async.models.generateContent( + "gemini-1.5-flash", "what is vertex ai search?", config); + GenerateContentResponse response = responseFuture.join(); + + // Assert + assertNotNull(response.text()); + } + + @ParameterizedTest + @ValueSource(booleans = {false, true}) + public void testCodeExecutionAsync(boolean vertexAI) throws Exception { + // Arrange + String suffix = vertexAI ? "vertex" : "mldev"; + Client client = + TestUtils.createClient( + vertexAI, + "tests/models/generate_content_tools/test_code_execution." + suffix + ".json"); + + Tool tool = Tool.builder().codeExecution(ToolCodeExecution.builder()).build(); + GenerateContentConfig config = GenerateContentConfig.builder().tools(tool).build(); + + // Act + CompletableFuture responseFuture = + client.async.models.generateContent( + "gemini-1.5-flash", + "What is the sum of the first 50 prime numbers? Generate and run code for the" + + " calculation, and make sure you get all 50.", + config); + GenerateContentResponse response = responseFuture.join(); + + // Assert + assertNotNull(response.text()); + } + + @ParameterizedTest + @ValueSource(booleans = {true}) // Only for Vertex + public void testRagModelGaAsync(boolean vertexAI) throws Exception { + // Arrange + String suffix = vertexAI ? "vertex" : "mldev"; + Client client = + TestUtils.createClient( + vertexAI, "tests/models/generate_content_tools/test_rag_model_ga." + suffix + ".json"); + + Tool tool = + Tool.builder() + .retrieval( + Retrieval.builder() + .vertexRagStore( + VertexRagStore.builder() + .ragResources( + VertexRagStoreRagResource.builder() + .ragCorpus( + "projects/964831358985/locations/us-central1/ragCorpora/3379951520341557248")) + .ragRetrievalConfig( + RagRetrievalConfig.builder() + .topK(3) + .filter( + RagRetrievalConfigFilter.builder() + .vectorSimilarityThreshold(0.5))))) + .build(); + GenerateContentConfig config = GenerateContentConfig.builder().tools(tool).build(); + + // Act + CompletableFuture responseFuture = + client.async.models.generateContent( + "gemini-2.0-flash-001", + "How much gain or loss did Google get in the Motorola Mobile deal in 2014?", + config); + GenerateContentResponse response = responseFuture.join(); + + // Assert + assertNotNull(response.text()); + } + + @ParameterizedTest + @ValueSource(booleans = {false, true}) + public void testGenerateImagesAsync(boolean vertexAI) throws Exception { + // Arrange + String suffix = vertexAI ? "vertex" : "mldev"; + Client client = + TestUtils.createClient( + vertexAI, "tests/models/generate_images/test_simple_prompt." + suffix + ".json"); + + GenerateImagesConfig config = + GenerateImagesConfig.builder().numberOfImages(1).outputMimeType("image/jpeg").build(); + + // Act + CompletableFuture responseFuture = + client.async.models.generateImages("imagen-3.0-generate-002", "Red skateboard", config); + GenerateImagesResponse response = responseFuture.join(); + + // Assert + assertTrue(response.generatedImages().get().get(0).image().isPresent()); + assertEquals(1, response.generatedImages().get().size()); + } + + @ParameterizedTest + @ValueSource(booleans = {false, true}) + public void testUpscaleImageAsync(boolean vertexAI) throws Exception { + // Arrange + String suffix = vertexAI ? "vertex" : "mldev"; + Client client = + TestUtils.createClient( + vertexAI, "tests/models/upscale_image/test_upscale." + suffix + ".json"); + + URL resourceUrl = getClass().getClassLoader().getResource("bridge1.png"); + Path filePath = Paths.get(resourceUrl.toURI()); + Image image = Image.fromFile(filePath.toAbsolutePath().toString()); + + UpscaleImageConfig config = + UpscaleImageConfig.builder() + .includeRaiReason(true) + .outputMimeType("image/jpeg") + .outputCompressionQuality(80) + .enhanceInputImage(true) + .imagePreservationFactor(0.6f) + .build(); + + // Act + if (vertexAI) { + CompletableFuture responseFuture = + client.async.models.upscaleImage("imagen-3.0-generate-001", image, "x2", config); + UpscaleImageResponse response = responseFuture.join(); + + // Assert + assertTrue(response.generatedImages().get().get(0).image().isPresent()); + } else { + CompletionException exception = + assertThrows( + CompletionException.class, + () -> + client + .async + .models + .upscaleImage("imagen-3.0-generate-001", image, "x2", config) + .join()); + // Assert + assertEquals( + "This method is only supported in the Vertex AI client.", + exception.getCause().getMessage()); + } + } + + @ParameterizedTest + @ValueSource(booleans = {false, true}) + public void testGenerateVideosAsync(boolean vertexAI) throws Exception { + // Arrange + String suffix = vertexAI ? "vertex" : "mldev"; + Client client = + TestUtils.createClient( + vertexAI, "tests/models/generate_videos/test_text_to_video_poll." + suffix + ".json"); + + GenerateVideosConfig.Builder configBuilder = GenerateVideosConfig.builder(); + if (vertexAI) { + configBuilder.outputGcsUri("gs://unified-genai-tests/tmp/genai/video/outputs"); + } + GenerateVideosConfig config = configBuilder.build(); + + // Act + CompletableFuture responseFuture = + client.async.models.generateVideos( + "veo-2.0-generate-001", "A neon hologram of a cat driving at top speed", null, config); + GenerateVideosOperation operation = responseFuture.join(); + + // Assert + assertNotNull(operation.name()); + } + + @ParameterizedTest + @ValueSource(booleans = {false, true}) + public void testUpdateTunedModelAsync(boolean vertexAI) throws Exception { + // Arrange + String suffix = vertexAI ? "vertex" : "mldev"; + Client client = + TestUtils.createClient( + vertexAI, "tests/models/update/test_async_update_tuned_model." + suffix + ".json"); + + // Act + if (vertexAI) { + UpdateModelConfig config = + UpdateModelConfig.builder() + .description("My tuned gemini-1.0") + .httpOptions(HttpOptions.builder().headers(ImmutableMap.of("test", "headers"))) + .build(); + CompletionException exception = + assertThrows( + CompletionException.class, + () -> + client + .async + .models + .update("tunedModels/generatenum5443-ekrw7ie9wis23zbeogbw6jq8", config) + .join()); + // Assert + assertTrue(exception.getCause().getMessage().contains("404")); + } else { + UpdateModelConfig config = + UpdateModelConfig.builder() + .description("My tuned gemini-1.5") + .httpOptions(HttpOptions.builder().headers(ImmutableMap.of("test", "headers"))) + .build(); + CompletableFuture responseFuture = + client.async.models.update( + "tunedModels/generatenum5443-ekrw7ie9wis23zbeogbw6jq8", config); + Model response = responseFuture.join(); + // Assert + assertNotNull(response); + } + } + + @ParameterizedTest + @ValueSource(booleans = {false, true}) + public void testUpdateModelAsync(boolean vertexAI) throws Exception { + // Arrange + String suffix = vertexAI ? "vertex" : "mldev"; + Client client = + TestUtils.createClient( + vertexAI, "tests/models/update/test_async_update_model." + suffix + ".json"); + + UpdateModelConfig config = + UpdateModelConfig.builder() + .displayName("My tuned gemini-1.5") + .httpOptions(HttpOptions.builder().headers(ImmutableMap.of("test", "headers"))) + .build(); + + // Act + if (vertexAI) { + CompletableFuture responseFuture = + client.async.models.update("models/2171259487439028224", config); + Model response = responseFuture.join(); + // Assert + assertNotNull(response); + } else { + CompletionException exception = + assertThrows( + CompletionException.class, + () -> client.async.models.update("models/2171259487439028224", config).join()); + // Assert + assertTrue(exception.getCause().getMessage().contains("404")); + } + } + + @ParameterizedTest + @ValueSource(booleans = {false, true}) + public void testGetTunedModelAsync(boolean vertexAI) throws Exception { + // Arrange + String suffix = vertexAI ? "vertex" : "mldev"; + Client client = + TestUtils.createClient( + vertexAI, "tests/models/get/test_async_get_tuned_model." + suffix + ".json"); + + // Act + if (vertexAI) { + CompletionException exception = + assertThrows( + CompletionException.class, + () -> client.async.models.get("tunedModels/generate-num-1896", null).join()); + // Assert + assertTrue(exception.getCause().getMessage().contains("404")); + } else { + CompletableFuture responseFuture = + client.async.models.get("tunedModels/generate-num-1896", null); + Model response = responseFuture.join(); + // Assert + assertNotNull(response); + } + } + + @ParameterizedTest + @ValueSource(booleans = {false, true}) + public void testGetModelAsync(boolean vertexAI) throws Exception { + // Arrange + String suffix = vertexAI ? "vertex" : "mldev"; + Client client = + TestUtils.createClient( + vertexAI, "tests/models/get/test_async_get_model." + suffix + ".json"); + + // Act + if (vertexAI) { + CompletableFuture responseFuture = + client.async.models.get( + "models/7687416965014487040", + GetModelConfig.builder() + .httpOptions(HttpOptions.builder().headers(ImmutableMap.of("test", "headers"))) + .build()); + Model response = responseFuture.join(); + // Assert + assertNotNull(response); + } else { + CompletionException exception = + assertThrows( + CompletionException.class, + () -> + client + .async + .models + .get( + "models/7687416965014487040", + GetModelConfig.builder() + .httpOptions( + HttpOptions.builder().headers(ImmutableMap.of("test", "headers"))) + .build()) + .join()); + // Assert + assertTrue(exception.getCause().getMessage().contains("404")); + } + } + + @ParameterizedTest + @ValueSource(booleans = {false, true}) + public void testDeleteModelWithHttpOptionsAsync(boolean vertexAI) throws Exception { + // Arrange + String suffix = vertexAI ? "vertex" : "mldev"; + Client client = + TestUtils.createClient( + vertexAI, + "tests/models/delete/test_async_delete_model_with_http_options_in_method." + + suffix + + ".json"); + + // Act + CompletionException exception = + assertThrows( + CompletionException.class, + () -> + client + .async + .models + .delete( + "tunedModels/generate-num-888", + DeleteModelConfig.builder() + .httpOptions( + HttpOptions.builder() + .apiVersion("test_api_version") + .headers(ImmutableMap.of("test", "headers"))) + .build()) + .join()); + + // Assert + if (vertexAI) { + assertTrue(exception.getCause().getMessage().contains("test_api_version")); + } else { + assertTrue(exception.getCause().getMessage().contains("404")); + } + } + + @ParameterizedTest + @ValueSource(booleans = {false, true}) + public void testDeleteTunedModelAsync(boolean vertexAI) throws Exception { + // Arrange + String suffix = vertexAI ? "vertex" : "mldev"; + Client client = + TestUtils.createClient( + vertexAI, "tests/models/delete/test_async_delete_tuned_model." + suffix + ".json"); + + // Act + if (vertexAI) { + CompletionException exception = + assertThrows( + CompletionException.class, + () -> client.async.models.delete("tunedModels/generate-num-888", null).join()); + // Assert + assertTrue(exception.getCause().getMessage().contains("404")); + } else { + CompletableFuture responseFuture = + client.async.models.delete("tunedModels/generate-num-888", null); + responseFuture.join(); + } + } + + @ParameterizedTest + @ValueSource(booleans = {false, true}) + public void testDeleteModelAsync(boolean vertexAI) throws Exception { + // Arrange + String suffix = vertexAI ? "vertex" : "mldev"; + Client client = + TestUtils.createClient( + vertexAI, "tests/models/delete/test_async_delete_model." + suffix + ".json"); + + // Act + if (vertexAI) { + CompletableFuture responseFuture = + client.async.models.delete("models/1071206899942162432", null); + responseFuture.join(); + } else { + CompletionException exception = + assertThrows( + CompletionException.class, + () -> client.async.models.delete("models/1071206899942162432", null).join()); + // Assert + assertTrue(exception.getCause().getMessage().contains("404")); + } + } +} diff --git a/src/test/resources/bridge1.png b/src/test/resources/bridge1.png new file mode 100644 index 0000000000000000000000000000000000000000..06ea04ab63b2570287bc4b6753a33fa992281a8b GIT binary patch literal 793056 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%0Dmrp~#;y1tkFZcW1 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%0DRR&rV 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

;z=2uQW!& zqg4(>S22gF*m8cF-kOgmv%Bf|ey=~@lN!F^X26wXy(p^Y}K+dW%%a{EZze{VrxQ+p>z=h5C6!7C71EEhMb0CRIO_s3_H?u zS^xDbc};5(gt&*&j1*RB=Uj&i z5jp@3c0`ROC7G?Q`7JTYpX_puwTi`mTGtU^RM0lHw)#<&CCgrCl}#-z5WQ4TyIa}? z-~7~l0T$6kuuaNP%XF%(#5nI4=pxnLUnhq zMbmmxEG}1;Q2+oS07*naR73~0nVK*QD=P9~84)6;CaA$-9C}R6IbG0UqF2{UX~)wAB}=i2;&! z-0w2#u)B?O;+)@4otSdhaopbD-cLPVHQ&?hxNCYZq8%0{hNQ-v{6x#%au|chF-8Xe zS$0ZtqC$xl8@@mcyq?iAg+}9z96S!YkA#S&=Fo);$kJjLXy!i69mkFINlf{$+q-vP z+-~o`ng8s5QWhIvm=Qag3bIo+V;@QsE=HV@ z7k6~2PLwc~^rX1uu<~3*0G|1DjhlgXYLZ49Q%-W&eZIb&=O;mC$AB_&9_h(*!gPG` z?liX(046jJlMAFB!%aS9!~B#}(@_JLgyVjHX%9`_6jlnb0uYh@&+w|o?!io13%&jK-AMwOL2 zq7!CE^whMB7$Q5s>mf|m>Kxv+578R2p{5_42kD8_DiKF@yXbwHI_2>77t&mYk~TjxTRS(DB5v-;RCe4p{mOn$@t#(qp^R@WYQTgTXt87dZvlV`LKlci z7N%=LmIVPp(l@ce^*Y|X6DDQZzfJ}s%Wna%AzfW&oq^2B`G=->GFlo??oK#6< zB(|N{_~z*`jFsV@o>k9)WF=%8GqTsBlB-2|qTIWFiVBRSb|@oXzMFLi=K@k`UAj=G zu~iOCizY3x&EPP)i^B&kD2M%gZB5rh=Q&?qrM0%kVs=CG+V z8Wi{W>O7T-0da^&m5!hgy+D{x zMU3y9G7;kI<9v6!lVhGDEbK!kjw^A2ne0rth(V2c`uTWxY-FAo2hPXo^OQgiMlE3q zU6lbylCKObcEPpMot44JAL`s&abSKJxu>Xb&Sco8gIKCsR+kd?pH;E?o~u8BEyo^`ZC=DN*i41(?=WE@j2;pNi{ z06T{JX-3duB=Lyz^+B4%$Lj;Y>408i_&#;mh^AJIESJl5y1ToE-On>}?&I~-|RQ{;PsF?ZeTmLV+8$Q2t-F$2Nod zsz`NP#a^m1Z=}mPGMwl0;qElThd9+XFc?Er)XgFK1WzF+XpBbK*a}DMIc3jtFwbF? z+}f7k@um72D4=;b5mn)kW&PJ9|AGnGx%Bc;fBh-m{h5mv{)+e7_kH`N^z#d|ZI`sk z=HZGS-m6l|5F0E? z0S{(SE@5rRET5^m02TuL+%f?A8~}R0w(v=XptOa+ija-(3bphNn4c<#Tcmh?+=5+g zj<8}ItGj#ILu~uYO7HcZaxFTRT8-|W2$A+7Ig0z78+vg2I}`vTxDaloSp>{?u?d|Y z!)8ZTF3@ND;|&;N5%O|rXtjPX?z|B{5pQPB1!j=2o)qlDYSK!gwm25=*UhvKiiwaq z?*c6F$3&^aENXa3_z5!u<#7UK#2_g6v~i=)$%mN@4!8`%qNms*05QuC+f+zp?bg=u zRM8TkVHN?F9wlMKa0W0+dsZ4Oe`Zvt5p%F83IrxMc!se^m%IBR*tp&9_c>o7Ob6&w z=Ku~Kr+-2m6F~X!<37d_XK)x`9H^7crv%-`eIADfIqbl=@qQd;7L^K&F8nFlYx2r6;ye8xiV%V;DovJ`Bek-l6*q$=>3WgWy=NIea6NhlO`)~s{AqJp-7 zP$lM;zRDnSM6qwj?Ra;SPTClDL`4Z{PRE?%P9B3A)O5J1V4RKP-57_N9Txo-a{lg9 zhaGnCxY=#o?zeZZ<9zqUal0QbA2y6UM)cV~HO#+!cYCor?(!+0xBELnb3OvA9mim7 zo~57@W*oY|AEx2+)WH2Xj@yvCOE-=K=JIj3`#cVkFtg*}phtZ=CC^u*#^-w73_@$0J@GKF4Q#=kk4#2Iu zq(n364v0dCI>F!;)q(fyFhk;;!q+|jw)+jrQJ|(x7fKxzv>TSGK>466~~tWhBD@ZaSbNYyHrbH(cOy z<pkH!IAc*IiSQNxvFE>FO?Ykb09qW_Rl$h( zr0eOp-=#5imA7pa-Jstj;iZ!Wj#q<=QO)eI9s$8+7m(Yg1y5 zOihgHE0Q8z$%8~TRYSUzLMGHQ(h$s6*`#*eYcOq5fYhz)em+IRu)$-5*Z9Y8{_yp8 z-y=&4;Xa+39{Tw9>W}Y!`pNtNKZ}muFygasLt^FTRaz|cX4DTj1*2th zRwbcKTc0$K<9iA}#)Pw%c*c(E5FlKXQ)b>|;5_xsAOH06)6b_*#~c_RUp^Kva|r%v ze&Wli)6IXz568GoYW0^^Xb=H>Jzrj5Uq);ICWalax1T|XvFXox!pwyXG#RRZbDl3R zpD3Txea?^Phi~Q|vL7GKy2+4ABMGH67Dyjs#!og5 z_X+r%0^##~eSE?x+3`9*%*P~5tdrGU^YIWQI6Y1uD&g;?;6~4lF~0cX7vmng*f_v> z`p+Lfz%koaszTC*ho1C#wpXl-Gu3Dn1SJ~qfW!Fi-8&oxxx4=1pZ@S)|MaKxoa{pY zGRYHs>{)v*Li+VDzx=nq|7*xhDZMGzT_wRh_pO1>nsuA*{4;;i(>o297UwO~bkR_0 zQCd;<-Pe;phn+&LS657KPeP^VFNkH2SnnQknY9?0p5z5eeSZOe%f`ozSTSBMBcPsh zgng?@x$_NWhORm7wECjq7)KnEvj;b@0iO7#yQiBifKeowcZ_`ufnJ9S3olceb;#9O zBq~s0Hu8Ycx@Ol-J3m|i5I_5C02pk~3?$;Va7&(BhTeHrB=yS*US1VfXxS^3*MeE} z-|F6a5MosnG9N zqM*VoiHqWZoMRsb8)}1noO!B{mBzd1xBgD?LKPqwz`@9~&42iZ|A=GQi0<5@5_P62 z=jrZ0{`iA1MSi0{F_YD(SXh%itKN*+0VOOS5?OF_p0?HPxOSz)hzyCi{F|@;n3e-X zbWl#mXtPie9S&v>Y1cVAS4 z4kn)nuxf+R4;?hXCMF;=bJuYgL`EOQkUVun0q$Ppk6|2%^gnX#Dqo z{d+{>%lbiUX4H-o`la>nhNstOxy@^ZFp9_Cj0;u*QL10_H6yXgG+5DzU{{wQ=fHS( zT$v3@TwC#bQqa($3ApFxot{o;^0JND_L}8EtpNElS>e3g$8C%Vd{nK>v)RqpUrd4Z z@>J%(iLCv>rBtgzA)`S}lWhf`Sy3BU+E(Ryp=uEMdogSB>B6ryxVj%B(weLwW*-!~ ze2f0n6gD{tVl$nI%$x-0xu$VMD2}12$wY^gjS*Ghnbuj92Rr$&h}ax|0YzNz00+PpC?Z8UO zHkLh(KCL;!isPx)s$>wEojV5QbJzfnSkOd(kryofEB~F4U{$sXhHWOz90v}GFFu`a zqGJ}~3bl8E+1Plf+>yi*$xlMLhr5Gw6@$`tabQmCzRvEqep?*cCLC%Ws6f=}D?$P= z%Yw|~Hf|}Y(b}icMKZEw+$Y+1hhG6j(|XYRSt)riAoeX1!eMnr65Ogg7s`JU^3W*~ zaq`x%tPGFX8nQi2^s|Wm09iay|KxHz1ee2OKcNl76lFdh=Q%?YN57@btahnZq875{ z3vJ*~hhzARaHzYvf83D2f zusycB``)TNu@?{fBjRLL&p>+Iw<;?$PQ;G=vGzyofZ0<{LZiKfRt!n6Yait|Q|!;T zKHe-(e~)S0_mLLLs2^ft`_~`U{r3b(bnJ-w=AV^Sm;8dM} zi^_*YuC)zo1pzoy^K7^%U=Sia2N;ccvw|e=6HzQ-jjf#(YYJ6WO=M&?nk01}xvCKn zLut5Iap4vzf~w&{IU&njB{|C-DorKIOoi^^D{nVGUpoM5?1B`M1*`T!l9IhKff&ZB zU$+*BEho0eCyMsiLGk`aKK$O)xQtf+pSg^!UMj7I)nTmEW=&YO5>3k0;#9#30eK}D z7&Z(@Ps~VZnhgn+p)UUI|FtoW#aZZ+~X}&9)lW_1wsk4G9`4d&$H(M+s(?`a(v@QiDWbm@dzVk(WY279y56 z)t(mPYz@u2i>P}yiJ)jk8gDOOen{<>sPRJcWErlIb^g5bN=J9Ic?!3+TcXZoddo1U z!_sA%Y80js7~jaR#@0(=SXyF!k-zfTYcEbeU0|xLDGDHp<{GGoHoW=e#4k8 zAW00`oRc7jxuUUkwFg(slx0Fy&C*8r0tto)n)#d{#<&%{D3lcnJx(?XS7;Z*n8DMRmnCfpOE@}2yA16)O!$7F5N)LNe;dSFv*%heU)MKh@mZ z+N;*QfC)RIyeZYoPg+A@jU47u(B6zTj^06KhPw2j>22GzS`GKx0oT~v8y_{TjCgNa zF1P|-WkGv&iN6AqV8SI0W(GO5nmS;al^2vmgK0SC)XZxD=4M)&4=TFt9=F+sE?i1H zM{~rHHAb|X8Q=@MUBpNn5?xw`nY%VvykOH#e>^lo-2bkHvZ{*=SdWR7@6xlhUYOaE zp^~kZ!6N(42+0^M2&OK8dSd{Ugb^Y}yKPvFSUjxg(P}YK3Ic8aE>g^? zPJ)sgf;(K)I7SwafUe27cvCa1o%1f;(5T3k3aYh-2<|AUnx)i#1yNP8xS9Hj4WuvJ z(ptWFkj$XDcOqal0tTTt5Se(WSt-0b_D}1fIR{y8m9_W^LS8O8hmE*xD-gWM=*o7C zW4gnqd%BV|pZMaFA*WeZp5b}1tUoI&4G5~bfKHBwd>9L+vJO-OmJJ%xP(dlk3s%IK zMd|7s&f?_F6Ug8nl~-FiqYJ{Y(tptryewTyLbW_p16xmDCmZB?TqdPV=s0Ah#cL~R zQ9WEisvPp+)~}Qli~8WrbkGnDnOcRXL~3!1Y3W4G({-pKpA_Pvh-$K)h(tw}Adnb> z=x{*BBk@+HVI>`mzNxA4bA^$L+Gu1sr#b?^Qg;F@nm^UHY;n-#I50z`xmx9&Vw7|O zgM`Bk7PlaYh;vg8n5HV37*UjHHxL3P-%uBicb%CX>kOgF4QW$l=dx-jH$6B zA|jjV{EE!Ql@!@@lFBpRin{c4g7Ri6*XcSfsuI(pWHh0IH6=?ZO^eEf4*5nm+)2PSZ2C#luP;h5zvj~Xi5w{9&Mv}c{@`BQtLYXhGwBE98tyR&Cim0Ekw2fspnx?(o4~Vap z!g3dvS<=BlU+P0`73%TwElvv;<-lYW1 z7PkVj<=_>`Qik20?DqU5Yv{q&Rt&|zgx8|Ps9m5%zRp;fCCXZnkWEVmt<2(5is#$S zo@{m2X@Gip5zz7Q`+DlexhPr`7O$X7`ej8=ZDW-B?>*i>azSGP>h8x@-bLI?3!45k zOVTdl#{K{=W7965d87gs)UK_sm8SKbQZ&_YIp7D6Pvb*&G9}FTe0!E)kOh% z0TVoqI=VY}zu!Oq@ZCRf+(fuf2u6#OMAC_3@9w=QU@94%nu>Eyb#EB|_>aH+{)fN!)Nu9XfElG{6QU4Lw-0us z%Qq?zDRGqT!E?X2o<52#3ZG&dN5BZ-leZ5 z7bOw34+KcfJfzk^UlofrBY1_GQaQ&XvIJvem%`IAxE@@|lnIfXey2xhYNhv!r8ib) z@AJ~M#aQd|@0XX)=e$P^-(drj6=qHZQ@Z6si+5igyIZV7M28dzkY2ugNng~=>^wD* zoxB}t-eCR!0d%;}dB49ZE(eLDC}LhfP$b`8t=qLvT-(pJ5Veny8&F1Y2W?HL?IWFN z*zM+8cV8EM)V z)ncI1m{~)tt&S{>aKSfL4NQ8IgiC$^ABK%Vq<6y>Ndu$imM*QbOn-8xb5#!MD^b*BeKxR4u2k> z`1p2K2dEBhTQymw_%}&zCoXq(hlBBfoL2nie%_~EYwJpx zr~Zg~Y2;YE`ctOtA0%5sb7m);li zDvNEqSzNH#L>(6+D2r-~d2;aSs}C@d1|uf%eI8Wa6~ZDg3Ok7+>^8>JAly#9UmzGqGJ|n_XyJiJT5m@$^C8;?1|eHYtKcP* z5#`j>mpc#_sHcC*hi~JqO{C@VmZ~dS$SG3~@f`E&Gtexsa#l;jv_`5x1krn4eU>!O zS3mD@Q}x6YqS&9&3B01EJ2iF^?ZzYRbWOn#hu@R8%;yO|OADH#8Z>s(^Dvi^xQZ4X za?NUg%M4J)+V+AOmVzxay2!eHX4`ZvR!Yd1fyos~OV_e@=Mmy)m03K9T{$u3L@E_a zKT~Ey#%STCXd)N71TBLB6Neom#2~wW)I@r#xm~ARSerFpZr@mv(@Ut2WYHmk4nl~n zHrMB|*fqUU0$Hm@$1txI_fDW$xwd{L}_muX6OK(Tyfoo)v^ z*Iv}O1wPybhV{873QOB5Gm8X?c7WHnxngOH11{x38mSR$_gYo3>E+ zMOQ`hsL(>gx7ddT51wlGc7wBlFRREaC_pBn$wPL?D%V_(S4bkR2}%yhe0nXZ9Lt!K znpKKZnxb#ZKyfRRk zBPm?>UJeB^TYy z%nsM2Xv6Z@If1^k6Q~0PMKDP+MQSfIDpgz)dvFPyhNyb!LZGE_wO|wCJVl6k1z%Hj z)XHL{G!MvNReY2H;t~`Uz^jjDAgF7hfjw-R@8xfc*NLVZmiArJlI46!5|sy);Y)53 znB`%qtEkvOg@;H4!Clj%9joBy9A*i?Gpb*HEjxaM@^uNor9sk1wrSV}BGY}r?sexJ zkuIS!dE$(N=O}N6BnQkXx~!m77{nBY?WAf)9K!}+DutDjmB`MFs;)aU zX8kLHRVG?dp@8m!F1|^8A|Q=dH9$lGGKAKI8(>yWXTUH#Oadmyu+WO9$qZrtonV~< zD=1n~f(DE`PT9j2c(9D?-~r+qK-HBgEv=>7(bl9NQKaaPhv0=h7VCOHY<>UYS*d5q zNU{SM(Mc?YEi6gmkzq!o^7MBJRM?)_mO2WUA;T5MLdNe(h?^(NG^CD<f)fxN7;)q8u9wzkSZ3l`3c+OoUp9qR6?q1Xx&#uF;l_9g{Z49Z;5`d@;8O3rmtn-h&c-@eCuZhLSPv-|ypSSJa zApe3c4*^jEEgtY0;$She$PC&TW898$7%jRvM}Iay zzi`56amDXRg^nXaofV_A;Y0}r5_lK3U~X;%S*yl|2D9P7IZv~^t%-t>${RVni~I6I zfI`gaV&*fukfPSQxMbUnmbFk#yE5JP=z(S-xag=ra!sG$U18BpAzinoM_-cF6J2iE z;`beWa}$D%`Kz>{M_(YTVsHy?T^`zdQ#L(rCIQG>^bpGK-m(aCdHd^F(Y{UB#9gBX z8q7C$-D-EDYG)!KZL}h3j~~Qpyk3bcE#b8Y{ztwFVAeZ>9Zz40v>iK2H2tOk|n!iKU^-()l6+z=aYAV)`$?VH)b)`swgdke2Br*Wps&+3mCE=Xds^>$f z1XV0hrL`pQ8qRbdnSQXJ6Ug|_Iu$}#TsSU98@B1f{SJ=oH!FcvYj4SnDQ3(y00FXU zk-h4TFKhXQNYGoO1s3!m5~WniIWp$eeh~|uKHbG}?ZOig_ktB6ZjZJrbp*4U9m{5i zY~~^QokyPB)N-sn3P8jYTbJsgXw7V9! zTr-M!$syOo>F3Fbz!az7pT}_<2ViignZYn;VWkj!jMcvWB&6UTvutr31~ocKTkG}&9@^&4z7)l&Xw2(9S14MVMO zzx#Tyko!*$yYx5)_bKRcI@=t}3ay#175wNc9~sozhZbI5KHJTJA&Q#kJOL@PAJIFk z%|RADFIk-DE3Ib|MzW2xFSXtJqT@)|kn+kOs)Ci}l(w19Tt)4&-lflvzjkfDi2M%p zd5?6ihu)=2qpc*;y*4kb9oisK~mx3tk%xFWZzEx-1$2}A_w zT{XM&iU5(KffED|g5@tr@aSM+q2{$75&jnSK)kE|xV-A4Z#B|_G;R7*aX;#?(sXOY zN~*vs(-EM)E{snrJ29u+>chFmV%h%`EC{FzJ_)+~^b?9+{xb6U_7oSzGn-cswPo85 zHxDkA#ch#&iM=YX$qNx!#LM9vb>~!bdY%7KvP5i`S=_3lwgf<(i{Eg;Zf2WjQ2`Ql zQB7(q%T_73qY-t>+#hW`KR?kR zRq;TjHDE^PmzOVbmpaY<;17TK>6@QUcSvJ!zTE%%fByIT{iTvL_VMXCZkd>#=CIYU zpXck#3)EMdH=ot=uU=ExXU_KyP{(q^mG7p>3EaqCN;47=LcqvB=N7IbM#*~9b*f-z)!Sja?1RZYV{qvX4pTA2l zmgy+~+2tm}G@&ks-9CN#$?=q}jEp$X^Zxqk1<~T9EK|#RN0lE_8LJW@m$?)^_r2KS zfRE%3-SB9lJG$26=Qr8{*P`0ORfrI^TW`kPK6CjSFSL*7!__El(z+Opy6kBL8Zx`q zLHpzOBxo#F7nuYl&F7rc&1qvm`1tXw@qC+eLKtSBfB63M58o|iF~-yLbAqBMe%$o1 zre5!_nX0vQoN4iST3nV$3eW)Mf+^B+VZ(pmevJ}PHWMka!X zyT&e}Y=~l`j+U73e|XsG%LjZJ=8Y5d=83)Qj{ZjrfSnjITRnX-5>aTzQw>3Q|Lg{#;*^mY{ zvn-jpj+T(1ySqPseEOqbe0$zszxw!*pk`irM%v_D8=Bm)A)=jx1utqJHhWb#3=p&T z76IS@Z*}*BmpaV?DXuT8&uJ|y$U?-9y;wf}TIixuIk6bMQ6LW+T*|zWy+GsVyH1a@ z2oAR!%}miSDf7I0!UK!f@rGq~lBjLLMd9sQssP`W18g|F%CtUw>pg0EFnj9nh$v+Kq_jY z>FNJi#a5#@j(w+y+25lg(#|X?g-OVvwKH>rvL52`n`q5D(L*qzD;AemnxrsuHh$DX+1nJT9US+rA0$A-P#em%gx5653IIG znW_0D({_2vrk^j*E%xP(Yj#%8XI!4ko(i!%(2Ew`o+NBh#*MLR_@GM1>kz?hk6NE- zi5z23N8mbx<_wVucfwU+h=wF^CKW$i?c@+6zd*XKeA z@|Oyn$4V{=s>^2HsHul7c@rM0_u2aUI!5E3-wS;%&s=cnB8?Zb!|NaY@q@uq7EP!H zIm~HBk+fA6$F6Z9qi|SbB>rwVIbGTntc!wAi~N z<&7j$=V6B->R8>(=KW=!_uCi;4pOo)z^T0Lxb*!J%Cw)mPyW`*MCYtEgHo5pD+Kdm z;)RRLCU;Q1w>4JZrv;*~xDujlxJE!Xu?qDAq5Rm(W+&J8*OF|dJ_yiB6V1d5^og1? zdTc7Sbu8;$0<`hdrg_qIlr*R{bkCs;n${PtuRuF1{*lW{?H8R&RHsVT`Munz3Zqsp z>{PJyJt}n30r6q045;P5OWyb}&Di4xK)pb&p_}ZX6jiIJUbd?L%O1(BH_OIuwtml$ zzJ(%hY|VAAw!bcE&zUie8A_kWb9qCOV%tUv{;_keluGS5kaJWNp%2E?? zI4B+GTvl>u)C5(jZ*RiR?6vXRMkF{0y7{)S0vSY!7p{)o61P+idwjO^cC82(C$RNU z{TtSAvC1+J`3dEfF68=};&4>zo?H*FKGjN#^}Y&G$3q0zB%(X4+%*XS=Hb!B4P>GQ zoq4C8%*-|X#Qi>X_fxMR&M9Zy%*7^g)IQYFRu-aCb^x&;edxPK=%{{kHS?9z<7#@> z90xH8+HrdtoN{NJ0*qeXMy`8zl~NWC)W-EoZ1<2sLJ_dBOttlk$W5@$b_v53lPJq{ zNM=C<%47hrXj*NXn^!*iI;or6($CN8=L?OR(Kg|)lKZq+Qr#LV(4#Ff+ZA+bHZCR6zk7Uaxz$@6;^lRXry4+1kxftdkv_i>ElILr*uCQ1Fh9I|gIO#@d~2}HezB+F!Dh`DF{oOb%@ za}FM`fxJ<5$WJhf01Gz8{t0F@hWlE<*~LEcTzabSp!gR5D>+z3C~e`A&lS(mwmr+d zR#_<2O8>zlsW#Z#c5lL;`^uWxHuj}hb8TMyN(T{TlE~BK@H7y?sg`;?znRajOJ4Fk z<25Q&-c7ViM)YtAmW?J6Q-B?VR`w__LSt4eLPg{3lBIC0Xf7FP9BnkP)4QTaC|$N; zLxyX)Yrc9+C0^F?YL&6kRb}PK`$kq!rP@lS;VeuRwvvg0geuO=5nS!HOXx$1s&7B! zC(D8x@D!C9z7W2*lZ8GMtq>=cMVFcmI;p zrVCR(Ww*4*ilCA^1h|b`G=dKy%p_JDor`^mFNYLX$^)Q9M{@ygkoz>+`Fh@8&p{k^ z9LJEysZzvUu*Fwvy*V_n722a4>%~s?q*^`FAWuVAERbfc0791`<{0rXElDL21;|l? zVo-@(LaWGzWdOE~akI4<*9o(Cu}VytKoKp3G<6^}!x`D;+2cHb^R*92i2fV3|Fh*D z3X9clvW9&ev0+ckQ6^X7P##0r4L<$gQQ}d+Xs!1$t@U1S2$)yIP+@VxP(Yx&RYQtB z5q8aP^C1HCNE;@N*)P@diWE_qjw`hv;nX{$>-vfJH~aVgP9hEmD81`_p)C`I!ml%W z9CSBr!C<9|LUonn<~V)obRy13fU=SI5J)yZ-#;5T zN^yutXAPz};HqtWq1v#9%}B>6TD(>yfFLaUgbZOYZtZlP_t(!aFP{P9prCW!v%zkd zTt*WUx-qKCGw`9}?8x!Pjdr2ZEB|d9LBf34un>vzs?*NJ%}y0HRIjU5RD+i|V?tHP z0Qtd)=EvSK^d)`Gmxaz~u(-ROWr`p$F6cnjbLEK{rT}kBBZ*hSaCsAnSua`Ch@}SkX)yPB zpQm9Eh^xoUhDSQ6#J%v3maHOiQ|kNb0?@8%Y;PEC$>`6GXedoee$MmN{osf|Y|qy)%sFwM@_|E~hsM*mDP_C7HfHbtm`Cd1 zrJy!SHO18RL_pkAL*Kr_j3X!%8XC94{h(T#hL?0 zc^G_m16+7{{eGTtQzm=+v;r-UH4OW*cM`Xe6^tunUN3&9V*9Dpj;qfwEOE9effbh$;YsteEd3E zgO=;KU651HQwl60oqlf6xz$tjmNW&Z;*d*IeuA(YZUE=JEARhKNS?&!ei)S1ii&2# zGpgBvh-4lBae|fb2|sSPrw^axXYlK|9X0a0lQvg2C(R5;(HLo~(aI>~&R8m>1W~Za zLXUyrexKsEKmX=W|LLE6`TqMGhvCq9LOSRD_56Yi(uBpwLBfoOmFqybd}a^iPB?|3 zEQTr==w%XwjLCZQ1SQ}UaH3LG*#nc1-m_jAmKuJ+EO)7Lsj>C?x^0Ib=Bx!al-&)=F@Ai6^>mNU&{g(|T1#4A) zqdRhM{g5)z7)YNiu9Dm< zZl%H;%Bx8izT<{yl@yYccYjGR$=&UAdPamO*15nL4HcK?&g$4`SyvFStdE6fWYHpG z=5xlqR3InL=qwf^xqM<~lXqYOlQWv@n5>!;XZNHC%3Jp4&3hy~5^7GL9@pu{97;TQUGlIR zwW*2#XPd276|L}#FKEy_Uog+Ose2-BE}H>9T{3CTbNYP-sr^v08Y)bL}Wqn{R4pWB)4z*k+r=o{TZ*&b%V6FykAlXJT%u6V3 z0dbE_Ta}6t8LIzGuPoK3yO~v!$@XxGH%gzK=?o5z&7mui)euUX;LsnoiIWP<<3cJOW>Ut;uT|7}X-=#R`TUV6C_8Cl#C(0v|R1VGtAQMpDcW%`saEsQ+_W@`8IMbiIka$O32eCHB`?>g+ml z4s^-C)5xiA%bsx~Pniz?hIJv-E_4e6l^iXrhzb}45)vS|4fB`t^wV89Pt56(MLoEg ze0KC=IbA&Yf!zCZw`9Av}$%GD_bu?M=GCDsx!? zx_(U6${Md^R;4q51kcGo<%vjH|OtW2$3jX<(8DarsR^&qezcU`u#avf=@!Ah?rd%HsiH z$U#{^aBWw;ZW?2&zbqhjLHw0`DPamOKpr9{+(oB(^uwRrwV^(is4=PIrHYcr$qt1Ipf%WWa@Qa_4uvvJKXuK$7!10>)s*Yb-l;#muVGF%tCr=(U%kVHoR(5)sF9Ns6^%sVvgBsG z9gehe>SfhP1m#l_M(D<%E3PC3IH~V&&}O%twdMS;#uNo3guU zWEq3i=ox=hb=k@;r7lMncNWe|w3An`Eb$b)8m=p6pW2(b^O91lm9^cszZTe3$Wvf% zlQ)_Ol4qw?Xq)23dyCxfJ>)W{H*aj_D*;Zia`VKZR6nS5WLyhfy0X=r zG9lGq%SlBj+iaxTW|hlCyuz{2%W&r5p^Q%IL@jNN3diKOB1{$iIYE!kSnTf4YpxYEW@l+5-`{(Q5k!RbuRAN>eH1j3wy(C(JQTRnMDMQ?g*6xI45B;iXDoRd7NNQ z{)*joxyb~WwfCDUHBgIp&_BIofs*>B2}&~|O*;gNJ@o2qt~C1rfwti3#?3^ALK)>l z0Jp}?3%mBJ%Tu}xV+o?j6k|Rr{k$oog5wcdlMqFxxdG;o2Hh|*X~uT0vEuUaA7|sz zU14OgIIL?t=&~(?Nw26uGp$N3PfpQAZ~&yo;jN1%EWxReU<#0#&O$v<1+{ZwR1~-6 zV^7`Zka^sQmHwJ$9`4)J71|`X{Dg$q24-0{$t!db{Uea{70VI?XHwabf<0Swt1gyO zOH;=}I7)Mf!p#6cle^5uFw1UoPCuunlQw-4B8C8u!%f`q0kyyld+@eCRCO&3qE`d| zbW@owYb-jiLX&9_1w~u@WNG!eDb$$QQm8_E3@I!W2GL^AJS&p2Jm9CNvUOkXEx-v)vm_vH=&cLP$%+};CaN6OqS@0AAa zGHPlLp*jbm>J5TQ?D0jIjs3>H5*mX%q`H(kBK=53k*RZV+y;-jX9yQNTYXR!82woD zxC9sK1IX;07Fm{u5Z|z29u1U>ME$rmaROT-ntTKvf9d_}IdVY^Y*40D+D2mRet@t! zGP*vizao$>kFda;^PEvgg$bAO#2g&#m|7vL)TmK*SQiGT48Yb# zNMh{kO}<-Q4mtp;MUqlusPNx1y9=Q-XzpPPL+!??_Ob20dYpRd1q-Z=>*=H&0$KQh zBSNKF*-vF0w`|Ezt3MN! zJI)#Awni;YmMg=>QBW#^MrN^}(eLQE9nc7cT%9$BfeP|g9W zP}E{W0ddm}h8;9IWHv|~w_7~d0h)1`^5AWi^woU);99U{q&okeKiid9XE4)`-`7D?|FcQ7#MLUM;XX& zELhR6rmB)ESRsox7RXbFrD0?sIffl^zX6B{{WMx8Q%u>X9`fxp>!$#zTCVyOma15G zGj&Anr)I|82*Hdb$L;uV9Cej%gUdoH%5=gDyZ1G_F>h*;?Sf$DB9jF!om70sADHRfoG#OXWDAwT4fpHrVDsNXT z=DX)Jgqm8?*(@$YrNK?5f5kIV%wB`U zNwrG?k~^`sx3~E$G!!t-RKbG`en*)^8~%-1dneoPN4oalYD&$8p=Lo1^5r zaRQe_Wr%m*1bjH2>k4HbaY#XPgRz&D?oJCzV2RcLHZ;OOxzxN8O5W^U5ycunCd@}?HL327V{dCdnFpfcUxLljkR!apd z%d=U4T=qQg(##y78SR-ivSO|(RSP=G0A=cU*6qE~p`s*E#lIWFR9(onP?eeONy=R? z(V*%0*-yXz*Z=Zg{qXYT`T2u?@#7YUn(KS%ZK7qT6+=}VL+f^FPejscGPuSw2L&4b?8HaE=PdJP=XC%NV%{ZMW&kD9>my!-ju*Nlslo$6n_6rGl_iK2bB{R&k zmx>;52s(s0t88@vDJX#<7g_=~6&qFYrxvKRvQUK({>c{ zi%|?^^U9qK;`B+Lsb*%ea0*+#GviPiG3~$ByC6upw_?m}cW`MkSj!Y>aRd8ePxQj; zpv2BM>FDit7QT*_la$O?3FLby{g`WT>_By^31yQV%f|XCG({3mJYO z7!9ZeWSWXw+_drxV%;T)HY{b=GgV%P07r!tu}o3^;v!7pN7?4bw~taXlX@NH0_3h| z#>)$BuD(%m%+NWbs>+On=5!(x#L?n`U5C1Yw1&ZlxN)p$F-? zRv?Ks%!#hwn(p3R&=$04<=eh78u}$yWs`+06pMW^#Uj`99}I2nQSZ&lCq_1#H20ab zWh&O#x>Cp&OF%@KeyotiM(eLCiRoBYq$5ma>9zEM%hM=o zAny%O9`-A0XWdcymzDzrnpyr$ZRwisVoQ}@+c~)!yM#UsM`42H{VnBELK+5i;FKFk6tm0RMeY}U|FpW&KB2I z{zX+GmE3RL;6l-n$4fWL?5MgNT$NbA+OUSRvI~5IzDT3dqN2s*0;fyz(~R!rf1}(m z74pT>=KTby-RntkJs`ZJDiI^`R6~Z^>>EH^EG9$U2S)@wWLd4<-3HtS|)iz0V;c zp-8OLMDHL60$FeVa0+Y_(G>8tga~-BGJ7BuHy*%Nuhhp;e#dLm^Qb}D)GLyy9(@^p zO{@GuTxJ??xR*n+L!q{3JzCxNQYU=O%q))EB-W9{hy`O;k>Y*{Lhr66cSb+d;`0>S z)K-hknG3j3Y{}M|@eJB$BM2EW-5R5%zl9Q&3ip0U z#Wy2^12WqJfiQ$>4whqOVs*0}{uP&x$b@16e0Wa0*o5a;%zP&@X0Uotkeda>n2+a%1=TD67y zR_|Y=nU$T7i&;3M-dT!MZCUQ9D2F9EbNiec5#|pt^Uhq$juIJVS?_VpwtR{;NGYYn zK9Dia%7*@D8@5G+z+UCuF)@g$;j02kU%tZj1d+P9ZF~i9Rx^#QsN+F>T-t?JXd$iO z;->l%%j-p@gLCk3h4%pPZg2XRrQn+FRVe@~wZ%S5KkNXfTxLtj04*bdsF%Fv+Jo|` zFjv8AOCSM6Xh%+r5UIn4$2CDiV+^0}6XZZ4J)hG?9P7&+Bx<8lm|Hn+VTQCJGz{@% zH1dhFKvB>eC&DB6xAMQ(Y<4mucQL7@R1=`Jse$1da-^zH&7a5tjk_Pksww#(5pS{G zWrNE!t?(;~{_c~sD8A0ir8dr@^^sL{m0loO zQ8EI=KojL+G2d#iH(KbeW?Jl7^43H4Zr03@wV@$wtyDK^2M2|iZdB${bn21?F)a=<3=OjTKW zA+2MMy2fvBCso#tl~THu*IMW9RMH}YB)QBHjHb)nKCzdTSE4KMEan;SQ6W@JLNfSsLm)BU;?=- z;Id50y(j<~N6RW!)U*!}x*|BiULp+4;}#@v`kAT~05Qf5>liF*IvtN|<%Ckc_1wjp z{mizS#3MsJ%HB4f2#hg8t1&NGtMUK|up4g2F)R70A_fTQ2j+xAm}rZRf0R;V~PxJbpFCL7ATp zBYj3^$d)J$W)5Z*h*rcUA7Bh*b?Kd-4-TqC>t_hx{q}FMZt{|i@vA@k^V{thCY^xK zzyIyuN@tWVC0MCI=Su%B8SfoTa~%txn#p{s_oB!s(QElnY&bd@z|bCvHFzo-&JOveG?B^oVUuYw>T8Lf13wzg)_ zK2;GpwLx(jNJNEtdoaAzr7Sa<)N2jXfm)WyTm()LZW6prgjWweeSeOrA8hw-W$1U6e(Btl^4JsG+s<=lP;y~2QRC*-G*}{*p z*nJBwMA4fE=Q}RRF`?|X+_)=DJ9~&LeNxZaawu~F>d*7~D8_*8gDNiupo~TuoR+70 z_cTeB4X}t(!wX1mHf}Sztd{jZ2QxL0-NUkrfnVuU13kv5d)3hpvwb_DJJtZ{?om!9 zbhJ|Elr%_}=Vj}17RjaPydlc6cn8+!(xX~!(8C}_ufGVBBhUYY3__SjGlN;i^8sbC z+XDD&f8dEH1A<1goajR2T`G$L;BMd(Ns{NYcyeXLUq~MjmD{vkDmjc}I;p^B3IX?Z>bffB;r) z<>sGmD5#?AY^z=$Upi&jao|bNfK5LqPNij*k;m~=Hz64ur|xr3$jt@-8%JJ10t!BT z>RbS}H8e3SdNh-Hnvrqcp`31c8A)FJyMl-5n`l_%e?Fp@= z4OHijLw4je^X`-v+)r*&wev=6Z9UMhgBZC!t2qORl9Q!?l3y`6U=cHJdtR4m@`8PK zwNO*vWI7>3+_mQb56iYgB21hitOYC65>!Xp!E6!H0KZLSJG04OrCk_pkySN;`TEUY z{q=AD`ZrT*d>shZ^e)#Cct<&|zxz#=YI z%s$?0Jg0qK`BksBSw?v1A>P@{FkD(?{G&tF!ry${HX+(#+^C zDkJa^)K)P;?Pl$cn&0DEb7o0==w7hegaitdPe7tCTN&|@;zANMDh|gk&dj2#Vrdqb zDHi6o!7CQEDDpNtouB8v(!>U_mNmrc?Gs8sT=pdjM`g0i`c-45G_mC-#KvhxI52dl zkXag%0W8I;A1)6_47o^p#YIlYiVqu^y^CsdghIYaLNYkeonZb_g9ywgND~HFYaY9rI-#Y zMB#BZVQt67`HU|`uLqbo7`=Rf8Hu<&-Pc~jmaNg@s7!2?CND~P2C7S?FCy<}b{CNt zq2`RwCVpQ$vtqbE!XL!dOcvp{#&CS$ZM7^fHzs=nn>>Faq$1h&M zz#jdhmf=9OnB%^4C}UZ_w}!h;Z-3gRVtbOFJCbdbF$Sx&1S zP}CON!0+^1Pkj#nv4%=XVW-hco>E$@Pt(@6)Tb^2|6^Q3Tq)4+!Ek?t<2YOzx5J{%9T5FjYF;#}LK^oB zyYoPFbskpv#I<2jOuHTuv%Fl#rv9gcVF>l7yX)DS;{hSCd+0ngS>?WN8_rXw*_JY^qIA@W|+> zYa+HyTbJQrQ^NEk_VQp2LA!F^5_$B4eh!;a}ElwpzXu%ZSi5ik<(enJOnW~t)>&zwFwL3vovwy&#R!Z7~ze6zib$}PbdE8`#6P&I+DM>`)11$ zRc+l%`op$LEm^DXD{piE&{YFl$bF&vQnINYR22@zoRx;FZ{#LZt;gIc*l}RSwRd)B zoM{N*kBdPlM1Sh&#pTML=9y0c zs`AOM*=*5798-yj4>S5aBO>T=UFoK~ycJJZr>y1Fq@vG$sjs=0w{r}`aK&v)1XxXB zBNPBg9D`$Ux@B1``#jxRPsntF!8jATNh9DmF)goUa>rfgU3TzvpZ6K3aUx3v!9;i; zi5-DsJUN+Zl9URTNUzT$wGqvHwH(_dt&4z}O-&+bWeI{A1nNkel<E3RR!5uQM z8(^Z5p7kx1Ml(QkalW2+xzF<)b{jULbc~h;dqgK4qr2b^cQcHqaXdc*Ci-DxypAyr zi|P)i#~l>QB&@Y7Q)yfW`wB}0hs(1qrJ97hV%(5-{j(xTn={@(35%}F2*wBF8aA}W z$;qVRSg@<-z{k0yy31!IZ?X4rGb-`K)TvP|K}GZFV%Z{xQk9KT=A}Z?`(uZ3QX~`s zHM-{OIVa|Ma>8HkuMlA7(PrE%x?x4j5SwNkPR9UEHiudCzNIcIu z;DjdowoQ#!>S62sHf?LvE^^qW9-%_U#0|U7=mlKg>E||sB}a7l{lRS?d2_4)R5P~t zkoP=tbFzYHe^?{lSp8+2wmEKFTOcp=(J~BMSK9_g#Z?iA2!*0*&%w+1R|@cWXCg&Y zZsRYJLhdM6(1Jk3h~lsxvyS5JYYFT-f6B3z@<%3c)@C!kwG?bLZexFym(e7>QFkr; z`NNiGYef^kcm}#)XMJb`Dus&M%rLIG!hKFU+#Q&=<2dZ-X6K!D%lV?GzbLF)t@2%= zj+kti=em*kZE~$^{cGd+yTAGEU;ev)d!Og){T$IjINdH_Wj7R2>!_LNPOD+ZjTTXj zI2%veAYJq0$LD|c&;R+?U;n~#V+_RYu&9iO=$agajE39oHpWp3%c9aUrM6;SyFuyy z#i{k%H}y&mJ~5B|w7MIN{3F~-x!Pd|MA9%mF5PCrl2is@{#t}M&w1a8nju0V>8 zq$Ad91T@l`5vUXW(Lg)U?HCrN7;zhOnMZ?QW-!Xi*4g`cjteWQ*<#nXZFhC~*5!{6 zEKn@e>INvsWJM|nAo@lYQm7#d!AZkRFqlSQ7G>S+q~GzS%F{=koD8Ms9QNs_KeO9S zan$TS|K>KvlMUWNDKM`A5gFr>*>W1-@ylQT+0*k^k}x>L|Ni|8@!P`=Ai{@tf>l(p z1VKwtSe8piGloHO#PR&3ZB8xqn$35Cd*enDdx9;L^^73bv z(ySRS&E{$NQZ@DeaQSF#CpN{vNKl4nz-Zsov87Jo)qF+T5o$0TiZPzX^MoJApkY2A z$A{YuAKd-4dAoghdiv1U8e_Z?gYfE%vjGkOKl|x7ulE)&)mt)3T_dvTgxt1g{)aNB&f8-$i7vxWp?Dr0QRE;9X`YpF3v{qVh)&;MF+_ zq4!Zr5am#8v7Oydvew2AQ+aC>T8Z}oNL7ID5nMF{L4l-H30vU&&Gsv8{BCie)nE|8 zdvs(CWq>KP3vO+ZOC@cn=NFaHH3;!du*n5Fu)#6&VgT~>EljGBd_?lO+&M49@huRi_B zpZw|9->{U6h&VT%{bmdYvUwrnKIzz+3eT3N4SEF5rvdOp9zl=@-MQQeJI^_u>`(vM zzj*ra6C2|;o__fLw}1V={+nJY>h=B^xZme%**yX-%w_jLv*_;^PO}st{^XtwaIWxA zepAG4+-zi_tLsFjXer2{F%AMSW7!)l1X66(JdljNM>UpQaCJc1cn9zNQlH`D8|$&? zUp;MQaae4B__GrIwnpVql1#iVT|AGC>f0jRP6SFEO__DnsI5A z^`~;TAGFcKe!dy5eyDnuG6hwt_3pHG^P-ILg_uWC8smn&r8`+Ik>iUwooq)Tv*UJq zitU2ISeJ9h*o;k&!wsQYvKVf-4GtSY^0+l|JbnDhvkn0hcQDmg+675*!&Uf(sjIl0 z$!LQxeH>#99=8E|imS#)CqAuITlX{p&>@13kS>z%60?BJkBH7?=eUNs=-R7T{`eSI zkwjyfHy_=lJ$8Mi61MRlQ13pmZQM=}*01VOq<0zdVX!u2Yf7IOr~gMT&D2Bm#D2<&m2chGDd+83-;4tTPx>Tdr0D%P178 zM_iJep9(dt>G$)TfDeI~HhmoA7&p4+M?AmYfoO$ZjrUxt#(*Krh%;T~&6sBo-t5HA zw3-eWJQ`?|aaaXWw9B}IBaSPQqwaR7O^qR<&p>TT@=C@}S$DSAnMy64kV;=!uoFUN zE4kLPb>#)1kY#n0Z}*>ErF<&8sHK6^!Ej5x<}PF186VAe(9CIB@Z`ZAVbsWQjiLt5 z<60igJb~qavAv59TM$*ZCHMIJgj>eZ6BN69^fe*iK1bYm)EXn!6JLmNa8TxbnLy;h z_U5(8;ybEY@mUrr-?5;n?M)?=_2JqOET3)Z_p%`cc@kA^>D8;|e9yY(07}f1eu45T zwDg|(kerr!%n}`x&@u1nVDXYxY;e)X%U3}c($(!~+Vlee03ZNKL_t(`%xT17EjyF` zMv&q}G+d5{XK6sy)TcubGk2e~8}gE@;nU0LAY(nTZ#_%azsc!cdzX9JpNvi4tV5wM zypK(Dqk5B&N6_5NUI+oKY01k%T=#a zhx>=uTrNPX@Ls=D^h!kwW1wHjT{07&4&-juL=m>5jyoin8fzsRkv3pn3SdJ*yez3? z#xL);+9*-YeP-%7gNx(nA!-IIZ&qm55 zc`N9O;g!y)M&rA2$(@Mrg%_m-A8J;YX_d8La(Gz8|I63AElH9jS7PU=d1O{sPtOcy z0791JVg-EQKJD_I4;23YH;^lWm03V`t~)d6uFMEGJ^P>+Gmor70Fzx2;o)wkrkA4^ zQ)AC0;g+&WWFP;>C}QZbmAeR*_AIjzz&Noy5A>s+=Xqg<3rR|=)>yw%0`xSH{M#JA zL>Z9a&~$|`r4&kWtS93D>r&<+Lx{M>stQ4suP(d8h@;sUc0~8Yn;oZ4Fj5>b^4ttU z+OR=m#NFHYtdtb2k6+9Pgn&@PY zV!$s7wR0mV9i__D;4m05diz08H_nHptus>x%ZrJAeF#&CbXw)0NgAN{szqf^xH0NX zeDY`ddZj&TI@`YJC9|#fE{b}8Z6w;{v_55qMq2MKhTs;%*_U%scZJ&l!bln5ii1Bk z?XU*ASn9GJQ1s+Jb|G$42FUIONe?OC)m4`0D^B~dJ&~a(-ARX^wId@BP^xHROuXnE zqL&ueRgvH#Tp(*)S@}wpuhKtdur7JBPyO#_VaqY$>#vLoJUvw(-mWU|c0kJc2)^4( zJ)VZYPp-VcZ(ZFNt*5OpMDxnC?P8Dra?kd}JK`Aw_ktXjjnz^?Bjfh!U-siJYGQ|y z{`AOgM9<&G0#?jt8Q2IfCMIMeoAQQM0%xD>j%5LC*!A1n;4e{+qGfEE+$dC#WSjce zUK=|TADC_}U$1=eXJHdn1#9EtjZA%u3Tv5biSr^Q_I$KBH4eSfVVhu|v=~&q(vToViQ6HGFhPvp6teqj~07 z03p;~#uj1<69ufJ_m9Of4M_x2(N_k7Fld7`>5QY@+%*Nys-Ey+qDU*65ur6I^SmlE zR9vdeOfh%Z$g~IB{+#MGn(?!W)6|`VLoT)~NV59mHI7;G_%++vU*$sEuAVox`6zp; zpOwFq5ZoC1bD~CFZF8bpH2|<9y2@nCOh6XzSR$ExEYr9$8qk|D&r%{Crz{$QQyBtC z924Xt2{U43Dqn_KAqosAlKCJocr!d)6CgDzP|LVBZlCq_gecg4(pM0`FLq#Iww9~5 zB~Qj{?J!LYvTKCC&$A^(oiLS`vETHS*LNr=nFx1Nh(+wOO8^79P!ki1%I6NkgZpS= z3h~2qb0TOPLFWwGCP@*Nt`7U^Gu22kdYLMurbg1;r;h!QaqJ;PSbq?cmL4~N;+v`KiKAF%;WHHdd z-~F%u?*IOO{$IGe`@{Wle`tF4uyJoRA1;{S?vga;45DT1N0>h6jKiBSY!EzNZm-{e z_rPhg0i4zP4np+HC-Y2i!QH2OVxa5}$Uz8sO)QK=!A1C&FF*2~%#17Kn&)&*IXQ1C z-f#z8tgY)dI5-HCp9vF%$K!pT2df8&jM4GkX!9{yZQ5E}W}X{xxapKKMdk4Gd|)o- zFWVCMqErSq=+TUtWKQ7oWJJHZWiz=aSWc*8cUejB5|iR_)qSoQsRSl#E^y9=Ji|cn z(i;+Oz&U+NKBu3_-3G|aJhYX^`LAk|vOJ4GnxBjiUB(~SKyEf>xGUJI zGZDnz_F76H44n7-yGNf{nT>gS$%Es=m-YvsOspoZDzK7)+fY50ksHQ&rpefk$HY8O z%!78GcdauATeEd2umDNkSE^#Vjo8(4t8b7Azv@zEPaAFm%XiW!b2V-5H#@#F!qS`D zTKbc*zC7l``!%_bUw%xx@rg06w_fV~$tn}6&z|S7Y*WDz09DBKk;~&&-E4aE$n*O& zm@0{CZMU#v4KA9yrLjfXtRm#4>(Wk<>%%UdiG(Z|UWRQ=uok8De->PH#3mHNC56;e z-|qo{$5OD*<4o1&xe%EP$ie2r6D%aXc5J<^+tWQSquQvjeUe23S!vZ|$i-5?g^L^3 zPtMl*Oqv?p(A;m2>BmIpMTx<7`s5A^1z`}914N;0eFeWB=`JA}xmpq58| z&WEPzU`C&Q79vcRsH9ZMZmw8^gJRM>iM*w;3IKgnwPo~B1B*;=-fZ1?+fj?%af{@` z3QVPCYPPlodZz1> zsw#kzbSI^kNG%-IDY&%?`Oz`XT-}Zyt*1;gmli`R8pw(!g`yE9FNESJnwKGxM`jO z7%fFgvudf+&{$_o%;!wq5N%c#hbbZMqS9tDJHMg^69uc`jhE}@+sHPy z%?*?wFMOR*+8ku}!fA_>BX6sX3g-d1tV0XkGFNM0T31|%u~UJYxs1kp0CWF#T>YF8 zyS{j|FOAtQbbj(@I0GsbkC%Hf_YCvX`-jrUx6E_Au-Cu+XkpbeAQq< zWakeseT&7CD6STwIyvk=;z1qrS*Y&A>;U!#JP53aOPK*);^exlEB1kCTUTw@?El^< z#>@LfF4jm>_7Qnm&srY(DSu3urc0U-;^2irXi$!^hfhVE^f-l^qzyWOIJ1TmZZNZ1 z-NtDl<>=nRaLy&Xk_Um-x`jNR9EbJ=^CW-^w33WL}k+H>xE{9}B zhsTeiS>p65pD`4Y(Q!2;xVi^7%M{})%@;GXoyB3E)by$?7AJ`hB|tdBFt{raPWYH6a<> zE`nKYa$0r>2z8fgJ0?_%TxXq^`$qzZ15XT;sh~n!*U=aOxo@;c5_#%qiXpI$aUn58 zkH~J++ksgteYI!G-2syrP{H3KiJ&-!CyzA38dt4F6LIY==>5|QfLN%By&mKag*S`4 ztxp+nq|jQ=JK3fT(lURS1>S)eON7^l&zw@O`sLFV;>-6n+Fao_cx4k&6&8!PHd7n_ zw6yEZCO!X4=(+4@d>YNyi_{@-YVxQ8_jxPtsL&HpchWqYwf(>TM5m>l^Rg#vyo8l0 zD;djHVIcd;8gCCdw8VqYmnO?JN81>F+>s@!1@a3O%)NmBl+Eyh_7-X31F>(Cpx zbQ%{ux&JOXG^IE_i0EDcFoL=Ulu+eRqffNFPUBM+b>*gE=FF$T|UMELME?nEuc=!n8tA&^7+7N2IDayAPR+OHo6U^GzSMT%q*(sBF*nU zmma1`Q#I))*>eH=!)Hv%?Aj*qfYBZHt5=&rrr&+p8UT1QW zY#5W^DferYSy=2SfU50+JF-yPdF3*WvfLbn3t-1H_Nn@6uv!nHvs-m1&A-8vx zh8u!%XJq34=8<3$q1rEXW@Do9|~CUOOZPzdR3rn<1Z`hc4hbbSb~JX`Rk z&+{RRN1h(kR*TC_UU~KiENCZ1-X^a0oJ=H;glLDnF`_%BwffEfbYwko-I5}r z0qJFOmxM{$q%zA-D~6SlBqdJBeWum4a=V7oL4n^7Qa)(!oW zO-;2nWs-OGJ+FOnwMcvXWyk+2oUEnA>(Qah(l~Y?e_o zi%xvZhbuF%%gCfe5SC5*(&wN&cV)+pq1a1JGNL;cVynDcB(L3=51r`y=dHs3tU4+QjbfGt);%C0}DZ{Z9qx>wN$;;Wx-kiLUdos zLGGC6qV{71PIMc%B)M^9;5Qgi1$|O?<+6FZ=mGqDu*w!_nXX7SV&q6|7$G?Z%*G); z3?kc_4mlkDI3MRc=X6a>O=lcuO^cE{Myqvav1wG*5t7gI{{C>E=L2&<{@v#>ZdRP? zp%Xd}P&|^W-skHoC$`j}l~l50`%TK);(lnJe+`q-;=S|qf3?Gc>^}Vj&6p3>Q zb7|F*ydu+$p~`Y$u}&JUoXv{#wyk05pPqKkZygd}H&f-UP@9{TCNch38y7-Nl^d6I zFGmlZuH0k?*ARDUyX~6vEc+c>d3W@6Rnb4;%|?njIEstS@o&AhU0}jK#9p6Ls*OJL zK!8ZSv&U%60A#5-tippT%~nz63U}(EH3HS+doZoqOS`u{xKLR|fa-FK>QI+(LG3F0 zmcs&|Vb!h};4ri3)Z!%FJ?jjjc%cr5A|;E~GJPTxPC>vhgD}8hV;xhS;p)OT%;6!Y z$ZsVqwR6)`t!%T#VtFC4`{rdN@v@++xgz0gni}(Uj5!#aW?W`5<7!7`%ofg&8I0rQ z<;Jjch&lquCs|v~VB!GaI_G)DX$B>b+;s>r%mfNEF!Sgl-uIB1Lp42XQImB?TX(3pvYkf?!)95$`L4ph4PbY zuOf=IBEEEC)5Yn{<@sUh=@yF)g{fg@O_?8mxO8}OyBKW`>mmE|2vKxQ2y#z762ets zo7Kpy~dC&(5_&KZRM0haT zwMKfrD;M_RrG8H8F?L+za!HP?K3x>7{XN@dxfS0ndVm?oi7D>Cyi9zd$74CICFKn~ zif&6oH1}>ajz7}O;97aiB9LVSUeEr(g{?{R3EcHm7h^;ysMn;hd9KI@>yktE)-TzB zpH*5P2&f7;L~!tSyhLxeK^TXbWtf))$J7)e91?1r!v^By%RJ*Vo+>zaoO2c`)2H!jM)?F~xJ~(-4+3U@EJ7(WdO(vlj*XhIu_6$e)Gfi>q*z=n>6X0xTd%fn>Ew|t zq`hRapj#X85QFZ@$J#BH4FDJXYsIJ%?ucr;ggGDbP+TY(rhA#&w=eU2L>ePIB2;7{ z;dU3PR5O9lM*|qQ+v}%Kl!dZ1QaDoU5jy2l)AP)>22U{bCNrZ+ljQAq#Yr=B&8Yl{ zp3w-wUP34rKY#u_Znr|YsxZCEOe78Do{^`Kn@+eXDD7`R7Fbyy+x9g|zW3)`6#IVT zRmUhnm>}nj>~TFV*EG&o-x8r-o`njHhsi+wUeE+>Be%U}QSi=XS1 z8E?n<g|E?6ZO6JhU>!4St=!$Kgeu#!;X&XZg}P5Fl-1Q#ax(xV~)cdhoYwbE0gQhp!UO1 zuNNe798vjS;iUis%E(x%*GN!Up~4!j0FQnm8wDz~hBWQ#N2mm$gc0qvr=I$mstdI(t?G3h=f+|OGk<*tLYJ0daVI_ zs>2bR)tTLZlIEzIScl+Zm^`_2hTd`aVMZ~IWoSRk(sK%~Ew`7*wiMaqJ61(eC`rk9 zE2QXqIN-Wuq0faUtFcT^>pgADu;HzB!)j_Bf?a_CNz>=BG6mg%sTnmtM6ze79cn-{ zI=ovhr;RFu#|&wd<}j0iguz@6Q}iatoLJ;d5~@T&&IE6yNj&Tzcr!*}APo~!B1JzR z=lPJpVIBv^!-WYP7%b9qSq?_e4Q0=fV}N+*;pT%QKwA_i8v{%x56F}j@@pA1SC$%@3X5p0L1!T4{#K#i%Z>Yy&B2M{;Or?PGp>DLAH_t%ri?Lp%P zLl%9H>(N+s^o4qqv;aJrFjmsw4{oS-5% zGoPhpKcy-|2tXOpHC1#M9+@07SP(Ufdpt5+1gkVAVj<1^mg1z=zjU9}LBh{D#w`E@ zUCH2q4_Xks&b-$&8>nzrYMpN^+4{U>e)%&?6>k*}UjaZM_7fjdcli{uuGf;wl6k?4 zTO1FiBJL7~b2?!aj5c7pCZh)h$_my5l~=F1)z+D z<%&s&!=8<#EdmqhBaOK1N`4pqqGngV#!yt}8PrljP)1Z1oaT~Mf)!fNHO%NoCOHT& zPGT%jXL+A0k`*H}Ai6=51(b>gITc4H{+tp#x((B#6_CTNu!L$9g?CUay89XYY;QXO}z=@0h$$I zt4=z_^5sS-x@_Uu(3_P&mypF?W;QWlntCwOurd1Lft^}c0_Rm#ZCGK3x*$E{fC05n zri^2(V+JC#cZP8sHWgjD=4Pxy=zVDb03ZNKL_t&otj(IA)XH80U^HX&BDB0`?MzXP zwE$w-P%b^{H~|-@)PWI4#yvzHLRTgLc_&TwDLHU$%f6 z3$L+kQ!jof$0gBa>?@EOH^8o|tK-08qs#)7hy+h((O38ns-nR*>d7d5(_(5U_$*$7 zJ9~Caa?5*d40?H6rns$9vvE9F{nl$Bb>p^NOV#Dj0AxGE*eoTFA``28blJk>WER8% zktJ&lCBkf{pzSQZ#v5Jc-TgQY3-xscddsA4==oUeQ@U%rKJnL@FG-pQ_6gHKm<_w- zeq(g-z#xxeQ_WLRx|n4*U0cu=tl~xNX7<%2qxo=%|FM=mS+t8T;PC zlGTBQ3mm{%?sf$}0&xbYlK=4i=f~gtGW?M9^vC@kE9r&$qjn}!f#Vc z$J=>3ZpLAsUVf>+qXsoWL@kNj$x((vX?cw9MMifw$E40^}CR@%9Mf~ zJuF#!0B}H$zd)%yV^dtotrAD4g)IxU;79on*tAAcy)5`zu2d&JPgI#FlQs#n$PO;8 z8|aAv0Ic9$e7};Tg$6V+l|YqUz1h`(0C8@H(_P-(Hxv$EE0EZs z%?!c>4Gng{c!1_24^DsJez;G-$FzAqavmu_B{Hhg8z%V(+xkl}7tqT!Xharn&oy*q zJb$K&n0pM4(SaSVcQU%tG(e=+a2Q0Ym8f&1IP z{rms)fBom5e)@~qF!KA)ucfwFtO~jGaOB?qC3U?*i@s^E%wn%ZJI)K7s7@|wD_`=u zbuzm!0V~wgD;u_?caxDeEGssO&C40gxNx#zb{AuIGcbv=K~|#{UHqRi_+Dr$pSQwt zImpeDAT&^I>Dxu-V(0s-xyhDwjKAqjoS?HZI0H0BS-$xJddrPs?n) znYH7tU6>ZVvD}r!gxSxs-HpJC`M{0GFYJ;_+=9D**(~NQ5|?z#rrYC@Swj;9lw9yQ z44kTMI3*D6GKWK+A)j2EDnD}fC{w`qKm20iRYtkK{PnN%e!9-pDy_i<3A3P{r~`1~ z@%H}y=P;=$et@byG z-gcWB{!DA^l*tVT$ZXthFB}kuyiOOL9v)5^!ibZ4Idi=hWUj=3U?!5TNn(tHW3Y+5P;cW zb_?kcXs_b-pXJG3$XWDMFXsLaT;5)v&$Y;xyAgn887wMv*>n^EpEI;xWf@3#i=Qjn zUmb*88g>i}g1`xq5A$;pwOTk8XU7Nv-}MD?T;8^DlExSTSu-xyft3Ph6FOc$eg5GW zVVptx@vndW@|Qo`xEb)61o7|w_kX`Bg6l03}Yxln$?IZ(>(yV3uhyf;K|s!ojx`b76AY&-Iw)F;SfsRsU+40 zr^OaYw1z>+0d4n$=#I3!1F}wO$gM5m8^or`*w{}?p*RLPO3M@5aS*9m67enmtJqUpY2aQ1$x7LM4PI@(Z&Q=>Oc_=UGv9D<9Ji`Q zjH=r$ZnOD|X@$%14NQ{bcJQ#)WBee z1-gs9+pewu?8Idz{^I=0NCUEMHMjzi3tZM)Mj|vzyF!hoUg7pAQOq{L@#_pnGw5yv zB!Bq(up5jHpL&oik1$7B*}`S=B1vOoAnIim9=x|nobxgLL7ybD?j*ED=17Z3g7F|u zxGdT`raNL4Vpx%=lh7={RG1i2 zn5K2t52|M=iBP6!Y?hZszvo!l=!VX^hD7abM@ORLGr2>|$XC@-S^F96@g|UMhHP|; zYC#b$I1#CpAOHHV#+QR8hZ!xSPL(joU#A`OI#ygQN=904H*4qZGW3ceF6#V#`kMEWF>imM2F9;$Uho-s6B5wsTqqsuIGxdUM zp^GauQzkFDo6W+V;HavT2E+n+h!l zCi$g7QY~+fB~|VgM*>SvEx$elv=sjqN$7_pi}aagO80@m+I>urmr+m!a!Y_)pppPj zIK4Qv56Rhxxb)k~l78!@(pCinGxj7hn&c%_J5tx-hCL;mkKrP1#byi}IYZ|Xfh7zY znc{0H-A29SG<1pTjwCELIi^%|G16vflT>MhyDm z;ba8^Nu2-6^TwrQ24eR$LTwk7Nq7ql{+(_{KwMrLf7m%Hp)|5Q6B8cHQ0?vx65-_O3=n7ZIH;B%o`Hl0-3^vgWt2CVQ%oIg2~}7Z zlF=AdqUfz-EX|_i^K=gd;e>JGxV@a`L%b0qEQlF}8Osq%=aGcfobE14G-GAlQ~+01 z0h&CNd5E=YCFG0oDT|(wNs4G@p@l{|6BpZD@U5v+AF43G`rF#NuMf4O z4PB)tRqScBxy4qv#!!k#)u0-vHCwkzHOHoS{vMlHwHsSy)p2SnmVe)Xbui zh(&=G;jIxOF4vSfL3Eg1 z$zrOVGgfp72@(vP&BJNXlLwK(iIUc|;$TKWz&h~&gnSzL^73+@4?7g4Rcq%`N{Dhj z36RFn_pwp-7?G}$hK+HA#t>nHiyyk4dQ*=%A_1}75#1;~M2D=V)Ey8JepyIu?7}XL zm@NTv<#t9cHz4m8bID7V$Fjr(O~bXWxjL%2!U_k~k75klB5zOGWqq0Rwu>cgd8|hn zKft2}WeFV;+LCfiKFp4R;WA<}&o^LMi_#8?h+23=k&CQYYiYlbn~+jv4Br8p=bY!M zVGe)H^T?i^m21crdb$uY!fXZiRj60+h&+dRWtG^IFvEm|lhxZZjd-OyfSUM*a~8(B zzLu?RAz0FwqP&rO{pxb_{6{W(r&fEpqpwc@j7{TsEi3Y93~riOs>7HkB9w+%YHGhb zBv};QRsg6#cLDmwQwAaFTRch6F{A}`D^nEJUIQE$xVcXe)24F{8A?hsrC>UJruQ^* zbD9}6-A24yMzE4TG0@gUK--j(lJdcUE@X^0W+ivM$bog*`X*t5$HLJ_C9)QLQK^d~ zW4$9yUGzQcQ;}@3m|k5q18vO&R)Hc0IqbxZoe0T!dGAV@b{umS|9BI zXa6Q*6V>@*zp=LaDC2J^Ropz*Unh_0`fbKAQ9T%IBpZ!l*&3r#tO(&)isKt{ThBih zy)ScElOj28HyZZj4#?C0F(|gWqz_;uI3PvA$n7}9+>XRNq(+boHht<5 z-uNUjY`ly&LFn$sydZ_M|yHV-Wr5aoo75OcF%hBR_!iRYWKOzDG-^JXf6cA*k(jC@8|p5 zmoIP|cGCmM-ZQNz67fnFgha|gp0ycORkEzO^!p?F55?)$1)-2zu~N;5c1f&)urVS~ zA6<9NqK{GY{RT~>c|Nj3P642JiZYYl^M~!OcCeD=dKc|-cW+x7q#>+`2U#(h zI#&!C3=3#dy8N1l#5Z2LeADOl%H`*o^>cu9W+2u@8ffm4!!^%{wrUy&v)3X$D#x$7 z#`9o>ipG?!D706RT`~B=ecoPPfB2hUnjP_zoALMOD2Usn+_P35wz?ma@&H($)+=>Mzs02d_ES^T}a0Zb+4iGW4Okt)WJcUeJuN zD@K@Yrd|ey3@}-=S`{RtG0uGRlV@n4R866`ZU#n=t=DmUI^Q%!av0>VLLAFSW;{tN z^0DaLS``gnSXu8V)dZoHK9vFe;vAL@x!7gv3FN&8nDj8FGO zNs|mrhMU9Mz>9XpO8H;z9KR($enVss6T8bBBpVg&U^IEP8rz=6>VYAn&5SyjZ|TCX zlHjQOY~QksXle7??RGm}PM`2;WE?53QWRVJvtVo#%g7-!33_50usd#SWS||^>bu8xDaK6%JM`x?1+rh7{@%N;fMpqi^%2%>F)Qb z8A&$Ue6ibYd?wRj@8V|DPxray9;hr+Q!4g!@ALV6?ij#7{^@tW z{oU_}-5Bk*eVU^GGEnD_q3@pK>##=E;X-? z3dZ&qk}!Vy^m*t2@VI}Oeo7vvO(C^OWqt(+Z|`4Hy=}&+yAhT~F4{>TLV=BcO$~#J&j`@$=fC>Z@$$lHu6c~(FMs^gQWR80wIe!1 zNy0fJAc5EEo^(R3)hTUMys> zuShOv5?}d7l>{rk2q?_jq`e(h8@>GNm!Ne+eZMSHOvMr;7!)nF7H zDzS^+NVOU{3szz}Ulme_uv%oplfm=Y?6T8x80>bm*v2U(mYhU+b*(I@S(YcY^jdnO zG;NRq$AEOu08Dp_RGqtVXsL4mU?1$-BqvhZovN5tM^HAtZJe;|`jxGpSbPub6i4Nm zkWy_F%`Oy$pm_ap-LcVQsAP+7$0EjYV6++JitMmL7Tc{Z(({!;ZwtDxT3_`|2|hkZ zX8*=o5+h&&<*w&s!KlcKNX4p83ieZa06`3^%aGLt8HX&dUJ#?GqeGR?G_1Jrrj+_| z2}O`0keE&=#Ec79_pPK2W52XPs8dTEcCI^?8$m>Mi=ra4GLu}~r5?`aQP!8Ez`L%q zc_K6x7W&#@U@T)=7&$%f3xlVJ+@XVO95Ox&4VZ_{FizWUWU>Wcapm0=DeL9+5v)9+gJhjCu&*C6mI6*Edfg^;(z&YeriIOHyf1?S3YK%O_-w7#ru_2rjOi}e&?{7t@r*vWNGtK&LVJBTpJ;Uez&d1^RerhqR8A+S z%q(g!a+UimNp9=>G}$NUvM$I#mvYrVT-|Bkoq!i^-`)g8wkVb{0``qmR^*!{?_))GIJ1**US>yCvHK4PG!PSBT`Gs}(4JqO~B zVR7zhGN41la*x23yrrmf-l1g_uPi05CqCK;R{j4=nq`BGvQ?Fix zeU{ef2o*s$gH6q7Y8`u7D#TK`wbYgYAiSQa&GLc!^odP*e@lPv!J7J+)?`X?#Y&{y zaV5O5%Vr*R#{Ny`T+0AgL?v}$1LUgO?%3HH-m=!Y3#*a7nVoY6%U#2tszlhP%Nd)W zHN+}MNL?iDi+KqhhligKmN`NM&T~2@%y=9G#(<`b8Z>V+uUNgxTmhv98F3&p8b=)k z+Rjs3k)BS{AeADT#*7%zUK~<^wT{q1uxRdE_J7^EBsizLY!cUJISnN;iHD?8UM!XO zTo$tldbyy5WU(7+lQ=7K5hdSVNI&nmpvBUrc}60jXd;~gTnHSoO@XB;o35%BIi8qI zxl2cqPg!k7PUo71tsKroi#LOy-BGZ-Gzapf(kaX9(^(wp4 zthGz?^ZlO{Y+ta;Sy|tr{63%lDxA8|_(`j}S%;iZyAR`Cl(_3MrtFX%RtdRXBfsjH zUvOkb6bmcJEVAmJv#z*b1j!@+935c=(Kt^MntmEE1ouaxGao+Zgq+Uta=U#8_>s z_0BA72r(5Nc!w}Q5Htz!(aPo5k+AR@G~}@rq-xPr3aiLpj&Ko7hBnlztx1~`rO_;Q zx=89Kk*bC-T0cYv0%GI0jW~sLjp=zd7Z9|`>eey0!CHUG54ZVfoOJyM*GEeG9dk=@ z>l+lOF5+!BD{C4#YJxJ?obKt8mT3{o4Hl%T_}+%aUgZ+ntAS-|DXxuEUtx#sH^=rN z+GeLFiLqK9u>;V|lpD!I8rZGYO9`kCfn?P?#I|bz3H?%SShl;Xh!G%VyH;j$r!0)F z%T%LGucP8V1#iM$kj$gGQO(iRc!og4n~Wo~+r`qH)wC=fZ&b`ffKQhVIp#oSm{{P7 zh4NDO3Pc@W)2p-UJHTy^;y!+K=nN}*s${l0CMJ%L=xyw&g{(+&v5;}EVVpIthHhHM zI(jLnBFiYnml&jEg@b__mTN)9)~cChnaI&+q?vBH4;fH(2S{_8jjX*h@w~0K%w;GH@yzNj8$psuZTrk}TthXOhesXBO60@_4y>fM9T~ z$gI{C|0=lB9ykXP}@ zdNNVqyOWIS(eyB}j7nr{GZ$ZkONvQ)PIOsOu75G+~Z1xmWV+Qa@qj!OG>E9)HhHhkRTxf~f z$leboMMHTH~AY@}m(Xww`#!!$rEV>#(adKat?G&)n0Ys&Cm?OIK%!g>62dC`9 zhC(I8^iA6Lt2wG^U6R_~pJdh-2x+O*m)AU5w7rBruaAo+X;F?Y2ji&IOsaL~B?Sud zbhX*MlF_#no#R#~%0!!SW=3IlwMtah#886V0pvMfkqPzeX)MBMx8ucbBUIJx<@Pw= z0CS%JD80OVI(~i#ex7IOB&Yisuvwt+9my8`hTUm{^PR=4Gq4uK^Wl`+}Gke~o-qy~8p#jPw zwzVx0+1c+auk`rQl9rEuA_XsN{*eoMNMC)a6pCdrOtnXJj{xCQlByIM%Pgk*6IWcp zJ9^N0aUSTRIQuwMaut#$jI|>x-gf<_5-Nz>JoXv#>Ay#ls1$$Mxc#REs&k3Ph$Azj z$I6N!l@cRh8MUViC3{j*S9){JA*l!>8M#MXaJ& zWQDF$ECmp8x=J1klj;4b001BWNkl$s&9@!-_>UFv`0`yal4^Eqtz)R&)rI{lQpNT1VQ`TY++ zhjC(>-6;L}&wupXQ3M+t$MNa&XDPP6kH`IO&ik;D$61YIK*NHCIA~zk0*xSw(cl_# zamqsVjc zX9^^H^h-WZL@g)Esy4V=hBQ=j^f3zUU`d^5$7sfk6|s}7aW5k5~^dhH>S-CBZhnfXiId2NI5Mh9+}UhHQ-|Ha?_>hDQHKJ50#-~IMCzxk&) z`@>y7|JBd`;UE6DhkJmj`}@4VeF5@_mA0lJrhDbmcY9qbXJ5xf%53Du!2oH&`$qV5 z%!hnWt)<*m;IJb+f&4t_Vi1`Eo;$WB6(>sweCmd3<+D(&WPl#Za9KdIVPWWLwKt)} zYFp;7z@SJ=6(ee!GV9O z+8CnPFTpOl!(63k<7X>jigaR_5Drq+!$RfB6`1KkR7Tb z90g*{9F7uML#5tiv^4+8!ekycTVYHP)JXdtF`_>C66IHjKuM!eW8WAMxN^iZZ>dNX z64qK7K=zdD3$2ereyX%Q3!<@_jxll*$7L{TL z$COmb*R?^X5`0CnRu-x)g|Yatp@bEkW=o1d8+mQ$T$B)M`C80~eWhvpON@;xug;3H zJSWTXm_Rdj`a}wV(dMTNXlMWzvpt?>oR$-ui#WkF3}dOLJiju>XNiHzy11s32aJ;* ztiQFxx2yop{*8J5VAdZdVLQGQv`xIYh4o6IG}GsbUj(x<*l7bx)pV$*<#zPH%YLp} zdNMi_cb|iTS-Jk%FD6qWWgKg$A$`_@29U{Tm3&!W#pBW^5tQ=Nv;tZ&*TgrTXIk0X zDn(vqTAzfkQdT?o0 zTJ}O@Uycftp|Vm*i@8P6rD(Qi@gT zVh$DqblD<`S5sY+g;?3an2!WXj@II~wPuMOCDBZbTH4tPZ>yvs1EV#^vQsU^kwip+ z3S*IJGede2K0I0slH(HO#B=h{sMzpTN>WgC=zxbk3*eQJ64KlwVIdlZ4#lDE(NQy> z6def@yBNpRBMxA9$OeHaciKU-;~4HvfrBvVbW2Ado?w*%4W&=6wcD9;IsRbc*iKH> zsCI;1hAq%11y--KdKJ-F`=NqJW*h)KtI@WAZPIc{f65wCXB2goUfGl&i+iG_OzP6) zqU;vEjBQ1ixgODSSXwqtWphh%bjBVMy(g3SJ=BsPFI zpilWNNs+5V2-in9>_-8J`mogzGv-6CQo7of+3|$p`o_1-9LSk#liT|4YLvAxM=@fH zG_EF`Im`w{rHq!V8$gngw(d|n>kQ(iB5MOI8pOEh+8L-g-L< z0;>L*+r5JJNr;6rp&E@;etD&ZwYGu6R~zMq7m#Kt*9-->x5WKM7p3xHzP$WreN2}2 zD0tIe<$nE@!*@C_c~s6lP_10Bik~GGtKF$Nxw2TRNk{Uy;IQ02NjYKqAg292|;Z z1C+b&V?E8_*~2iJ5f|AqogTz!BaRDsT$h#Tg}5wnS<8}e%k54Gcp8K{-G*f}rn=o^ z0HHK=m&rw)TPp38j1bcZ8dPh~io;{WDccC^_7x7@HGfC`V(400k^2pv;vO9>T!IhC z;(V8Aq@$gT#kC|y>}wbNoYTf|j|z6G4p9j$)O*7X(fBI_GwtgAexD#{ljkvx=2BG5 zqd*H0Em*wg9TL*;GWAPtCEQoIbWQq287=OE>$=#1zW!H+REX=BU~!ItZNB|uY_c&wK7>PMd${UtylWbl8#P- z6rUypw=_=Sy{am#W1UL(rGkh7_iC+SZVZ5giUli5_m-xq@YXfXqwCmPF9>KOeWf8g z&BUCXT2w+xbb;(Z>P&|Tl$q7pI2*qDxKxr@3G^JU1nUdmX0AF44y=|--ZUE@F{ zHvn=M7_T4ZIxcUkyy{J>stDb0pJuRG^E8wo0_hGbKg5Nwv^kIeULw_qZe zwgt5*QuV}+ANI7|q0x`C45)O8B{SHFyWioYY#b4tve@kpLzm^RUQ5ZXB8Z6dFDsLa z-Wo?mx~D`gOE0Z>TznU(&7rZdYX%eukF7P9J2EmpVRWFtv9JWJLCji#vePE(NyAUg(W8FD%(Z~5_h%FbI!%x};Mv+riocFJvbjw&YUTLgq;} zo^i%z+R{qNjRVoUD7-;p0*n|(E)-Dpe$klGM9*TGY`Liv>GB$Fl+|QvEqKc4r<(OOOQXXl><}>QaCi5a#WE|B5r(EGoffeyVS)@yuTEdNQKCxNwvfm=F=I`<{*lK*=LNoY z^QN9?WFTrqT-V4dNzMV zO1jiZC2k|Q6I{8O^krbPQod$mSr1QQW@J6w0Lo}%L~8@pOga=-gDFB8?KW`4HoYi+ zJOEK9%B?~-*|Mrv9>or)OkUMcWvQ9b=4< z4g@Lbyx-F>Wb8FhpzbGyBZ!r=LFtO(j}+B#mxF_&CzmO*2tdh&0ZdA6 zM!Vgp@Y4-dACc#T1jc6+P0|3<@%^Wt9mgPVG8|*PzrCOLd+>>=?t` z0QV_Tt{Fj*fkPKC*9=(3-U!#qNHwi4vQWX9r8Y>|?KqIV`mz#KQ)TrzjvF9yBv#1Y zp^4RVpS@6R)GJGyq45nGH?zacM#;!3h$&jzoRW(+EcYoIB+V(G z(&=u)63aFei0< zy^P6OG;qx#JO%X-(9mRq$J1@BOfMVHM{=3*_4AA5ki*7O4g1<%=dd6{I+uR!T? zb`cL4(0VB~HqlXX(bh1FJO5jtb*N?OYz zNa74RBY*=pd&(0^yBk%2MgObqjtha*@i`S>z4|QHgX>$zKAvES^ncY=X%w+xRc$J{ z%n}sK?R(Wkx0Jrhr(IGtc;5x)fr2Ko$o!W|Fzj^~u!1r>B#W_S-hx~M$kM4?$B>%P zbIH0js%61*48p1hZ4HvOL6_$-mjP5cfw@sjs?J^Sv?9ghtL^n|D!InD0h-x}>{d%qqvXNZOu7u1{`US%EE$vA$`-X7Ga;#zbCi&lT1}E!%_Y}W?26u* z;=1UA64Z%IThpZ=xMSSxAb{wT>NsELs|A)-^sV*SrpN>uJZzZc@+m;>A`*nTwD4T7 zM7r_RZf_LWT>Hv4_m&XL$w_oo)oXy+aWdW06VaA6D%LMy;Ke;fwXASM%P(fPm^fG& zm2W)af2q_H0+hA1u|Obmv)KJyTK2ya9MIVgRIL8NWDP#uIW>K&jW3~O!3c$`Qosi> zFlvJZ4baRil(B)}hzA)NXSLAY|C|MkHZh|bg(Di0$c!^UeDH6&)>B=zMP2MsDWEuR)U8TIieJSuoC|rD! z-%r5C;Qc)BpI_(QDf)zKp6C63e}yK&8*heD{)BvVdae-#o+Ncr8-&!cG?S)GvWy1C z9=XrKBZ|ze0q<+Pb9IH3az3e`372bTyR@F@w%z5c&78|jSjzQ;pb~KfVXKZpNt#k2 z9YvEDM6QF}6~KkdE1z*eA7LNb2QS|YUZ`b=@Iixt+MPE#eJx}mymd`}gG4wp%6}7NVuIJP&niWgO1etH ztHirdd7W(y*09#r`f75N0g;-q#0F~$xnyEs)B+TgU zR%Z?JFh{LlodT|AUB&MYTa`EtRcIivgWt#~JQzoR;qqbG)zy|}MQi@$pA5iiQ3og% zN!ewv)`_(*!Q7b)Uaq%P>4dhOLm6la80;@ z;K?z}=c!7$F*7M#pm4Zz&OBV6`i?6ThHS7EdPYelp{G&iL&Y9;%CA@OtV(kP&DAwo zVyGNTtwab$PAFher$(r9Lx@;ota8Q{J$)zL{THG82}2%lFXFFqgq=oH!&G{*s#9LQ zEiHvs#jR*1E;<>x{}HmbPmy-*QLb@&8cNpX@>MNVk?zyy$vKwWNU-`6g|aJZPN613 zXhvYn6=6kpo#!dZS~4y%+=6Zus!QQnhHixVa+|9&No&C5iQ9}K$ep%F9mB@J>uO@4x&%y zXNAd(M1_z`uWJQM3vCCg3t8umDf$@Cl$t-C<#v&Xy^Ex}i#|h8@l@8duM+J$_SfpP1+ zry7*%6+h z^Uhkd)YdN9RCj~dMI<;qjG&LI5Zfvh`_g!^MvQNHh zw}R_8!A`FbY@9f%qAcw_!Ww3gT@yJFwS8#x@}6~)V->=RBU-+!Gufce6bnqRp;JuD zLz}AG!DWu94=Yy|Aw{!XmrVFos@|ghb-r(HUK46L_(Ftbr5$9dqU2MVqSQGJ9vzhg z)Y<1$(qZijyL(UsJWY6@#ii>bs^7CflXw#n-*< z#gbvk^1I-u9nbCVzYC2|kF#LLSa~+^A~IvYSOT4u1$k9)5uh=B1~5QLg|Z|2x76Ad zBP#0Y9c0zPQ=J$}t=LqJf_o_2G(}6O8;NOA23KY^fDmL1auYP8ovb{XmYcOqUGA>* zBPD@E@!iroD!--sh|=DIoEp%SV@BFnZ%!u?Zmty+fLMO!QefIXZkS?)@(h@$GT*hh zwur*(d|saqD^=P|%VqFKDUG@;wrI9kZl_xN2sTy^wy4Qyc>}=OeL<@jad&cPVhtom zCd36Yg`zu2FOOK#iqXu5yO$5E>TJg5X1Y{l9eTL<)(S`6W{PI!2Y^8HRd&SUXo4Wp zr^gWom>}2v_0@fb%yF;S@DlQkA_FO8z0zh{mk3Rt0tQFb8$?lfD3?ve*K#0pEHb|= z>S!juS$2JIOzG5iKDj{7Ji(JgEzNQT4ULCXS~%%1vrCor{mRaYN@|wDan*w0;nqr3 zS=CO%=^Zjh7QMzoCwW>y7al1DmA5RJnEIWR!$6GnVJ=08r4*_Kn>K7xPSrD4ub8nb zik*IrV%+-rzTQEe=x_}aBV0(fJaTP{FUYg(gfdQBo3+BeEChI{w8JLs_mxrIFt;dn zq`XcnLb`kl#k*J06y{ko8OpM+cz#d7q5xRNGMfZTdg)=DOANAHW3g9^M2*hwT}!}n zGB$y^cEwFj3sWP=Jv@V=vThAqE&<9W_D(rwNE@FS1y__SNwKR^V}(@M%U_d;Nh$+Q zh!n3{$HYOs($yTe!9?kn)XcOJgYicNu3Xbf9aln!YWZ2dMW$^GL2%Ee?PMPO0NZh2 z<=V8(BTgQ>I^!otu#RCfFk=4^t#)R3X*fxkjbj`}J2b}A(~p1pySL|OcRz;B*ZHe& zehHU>uJgI`p*V6E z543_cp@fPPilbt!%`AfWwWmk>nJ9Jc zGIbY)P;w<*QmiD1Y8Hw?dkib^ibjRk#xQyq_hMBI$Pp&hhi*vwnS@;PoXNbVr!PK! zMKN$L@a->ubKdWkZnU;GYwyTN5zjSt`RP>(y16YKN=B=|9p#fink(TTF)N{+pf|Sm zQFta*6z?n|l8O#V*kMFB{4KLxo0lOYQ$dpLFQ^CP1mnEI5`F?4C%yYMl$>vL3+4Gs z<=M%WHm!Jy{GwP|z!o^B&YX$+l=09JR{QBwlxehGLC2xvgzKcq5RImlF7!}QUH0X? zp9HdG6wliiw;%t`Pe#a&V?2F$3ZyCbD2QvvU`SgyXa&3lxea^z@SL7cO_F1btk+7! zfopkUt*H2>)zZM-J##w(-lYIbHIbD_oBQ+h2eXQPM>N|^C8RQtRM>XGv2=Nq_EU*| ziIjAh4M7&gC1tR7#CFUDYd|HbVoV;JM$5))p|i4|UljvmX@-{1DRj~%zu;^{tD~wg zR(#7s6)gHo4KB1ps62(C5<}Q1B(05vrc3`{kzFZ|!oMot%0=DpT!D>MSWA^7%$Ut1 z{CRk>JwT-csmE)x=*zM(VzaF^pm~pzloG)EPjD{Dy+{Tb5ouEDOsic3_nL|bh%2cnKCM>qtJralzN!n*ZxEst0 zn@|$nj7Pu=Mx{TP+JSGGsS*}CXo2Elb{4YCW2=`_rd)dh>^#qTp5#4pRGx1ij%XEB zA(bMcM4AS7%BO*M6X+H;7fb#YAd#yxwajpUA*$NLpko|^2gIk3U;ga(|HK9bnAyvB zpTGI^jlqVEiM!8Fjwx5zANP4b$0!qe#I3A)!yV(v%p^}UXX%eiYl_^c4b@*rE+t*Z zw*X}pISBbFO0+Rq*t}PIDGY^!s60HANXaAg8Hs2j z;;f7Vo-HlIH5zgx>&LL9dJvj}z+pTcAjTNK^W&e{?}Q)8r|WNC{`~&kC$DI1Vu%Ej zYHSfJaX(*Yxde9?8c^=Kkj@my=i~W!eoooP@M|IiU?tLn9Bb=Z8G)$VwKPtDpG3&) zX3tCav~TU|dkb=NpA#oGQClcE)F#1>H>P`la22j5@{Dpyrp)KlFq86RN#&-o06he{ z{O%_K!;rfG`3Z;|l56nb5orlP9(qliLg%MX-@Lqhl9@}G;O$5Ec@m7eKshx;svL~C zjhi3?-TbFN{d+(A=^rJUFn;{<3yaeyk;piBOPQ7~3AS#bI55U2+aQx64I}&paEQ`5 z=@#XcZHyFVqz^YmEir>a`ey=0<;K;Xq>OIG7glwHouY))HO1shp6ue}@{@^&tY8s< zC<{SVZv6UsJud#P5{X5w5Xr-C*Z^0mz<5CF#3HLba(|)29RAc9RFHaTgYyf9lyB{# z%OfFLG{`KQUMIWma+Fx5Zq^$1l6A2|ypMj+;)!4h%?;$VUo~87<-NV^YX7;{0gBaq z@QbH_XSt~fMkB0H4SXCOw|{Hyj~6U7x=?N9J=HK(7!?(`W;%Wg>Fj{7zqJ-9DWqav zZ&sj=LFLvmI=$vbWzWSVW|Xf*RAM}?&y;A@kbNAJ+H%cmENEXtElv$QG)+SwEVLPS zt~~B?iJB4JvpZ903C7-J^gfcMq!~gqsD#Gpl1{(_xf-&JU{rQJdO2(5nQ6Vu3LS_5 zW0tT`p6fw7#5F6Ipf@{Zb7G}ARi1q-@(}2fi#N!lZAHb%BQQ2eJN+&>?b!rXZB9uJ zx4_2&R0j?!bB-W5*+{clbyJF^f_4(weVhyQs0{w7_Er9t@QlPI*$v4PK9#B~C&W5b zf)dv<001BWNklLt*hw^;DrK@$L17;I7(EGMIu&KSx8838 zE?_)eGb6K=rn<0IRL}0UNOPCz_X@rZqR=!myBS5NZ15O|yXQfJPANf(uoeTU$p{(; zLo%NlWAY?yM0jMVx`yr*LKtKM&%QySOTwT=`%H4Fk{Obh6D4Mw-s0EIth`9*SdCR> zXDLCHBxsgS3Mv^_vu-7$Jrc!Q0~O3+?G<~wGOtawH7q#P*XMHr0_2pkzabFWU!7T! zkZs8*BHQPs(+Df%yW%Y>V3p6K<2+vln{%3RPQRZ&NZxWpv7c~rAe>tO$cW!VF4NSD z9YfOK;4KSsARPCObR(giDaDA(KTIt8(0-P1El5@G(??HHA%)9rt&O_7YPB{_Ei>&sN6? zkl-T~U~7ODJ7T#WB^$vEchsnpl=7E+uGSDxLqOJ$YGx~kg_=@}&^upe$)7dHB<$Rn z5)f#>Rt~G8l8PLvuv&3nD#|i5q|LO=2O$~ju@K@?fcbNY;Ur%z+H0Nu&TGAIS5Xp{)o8li{oJ2w&~rh-pd12-;=^qR%lAY5%d2$5H`X?E%$QL^=$cYC(u{`QU-< z0!4@zf^EfTt;$#p2u`zLeE@=+9V=9X#%z~G_XWfdReghq^Q1L|s;&!BamFfyTcrNE z&Uv~#9k&Fd`+711Aq$7cz;L)IrI+6$N}MMBri@D}uXP0jl`v!bO!^}iQ3+HS@{rkZ zxfVk?FsM3i!}_AuktEmYJ_m0gBmjRvfWMCjW&#~YoCPxrzmEHy`6NwN_DEI$Z;UyX zQrc)EavEY-n@ZTK#q`7%<;H%10NiI3DlPcd5=kjeSw+Xll+i-Q{9^<$jFL!PkLx_z zq+RBz)l9+r76z23ffdSH|2-p}(@em?9VQbvM zdvD{E7?;M$OMbHk2Vln#te*ZO#)zb9!M&fSBjq=iU8;jX3tLxHlxTVZ#O`I%X4`n(h|G zv>5Nz2=&+fC?Z$2>_z}_bRc-g>P;mKDWp+bqrx7=pQW`q*_YxCrVB)*VNo2Dp4hF;E&zJ(x5^B5{;8%z_`TQKjDV2DNbaXi1U0yEND=+Jtx zb4<&MXiW+f{V(GX`wBG^DgJ!g{~b<-S511hjAj}#jOP6%?5=I(W- zZ-3%tS}EBx604?=pypknbNe0;=7~qcK?m4wCV`a~xw#OFh+~XVX-EKQ={kz4#9nk+ zo4rvq_g^YmG^Lr)q!#65fV2=8b)+UB84t6=0pR2qUw--Zu$$qAj5LJ~#K4ejaNItA zxW9h>;`lJ#rwguGk&R>AT&HP<5HG_slf>O4tRDiyyvu5bnDt$=CkBw27DL3%QfsC` zB6g6*-4N&WdS*WMn~*e}&>Et^6%}{Vz^WLD0GOod0;;|-gDfQE5jzrcL(7CXA#aO3`y4DSrBgdG zR4l`Qw~LmZbF7k+^p3wrAr;;2BsUBa5v-c{=pyp?%(_U z^L!QgbbI=b|LU=2D7q*rr#H5j)OQBMW%x-gqVG|jo(9Xk;D5YNVIGUqy zX`2+Hsg+x=ymgwluO)L_RzJK{B}wuT7)pmPm#pZ!u{1@(+WwI3B`A>ypaO(37cWb( zk%v1u!sW*7^{c4lWtL}oz~Ft6X48Gj5dJzJr0b-yo8mz5yMxq-1}f7y1VUzX7>*vmzY7p4FTQXp6jii4r+bT3j4ayt&R-~n^%V{CaC zvI40^Da}M{)}<3w_$@sP@mW^++}xrBn-m*~@2sE#l51J9mCV?5e)-~xT3gK!&8z*L z`hp%cKM5W+s{X<v$Y0cxQ8SZYBo`(JZf&dOfMC6aR{m9WXM(na7P z5ocsFd0z#|Hy=d1Kx%buK(jZFXiF%#I{XFz;uwMuxGv@#^4cSyaiGu{S*L76TiJRC zppiGb+2GVUvb?oeKBzXMuvz359aVBAoT=w@r!;kY zI)3qYzcC)5Xoq}~qz#V~4&!+F{P{2c{4bn3Ki@yUeERaMFMjv;e$VGLk%uG=a02bN z+z8Daq}dn;34+hZ6V0NzRiqR#57i-9#SV)T`j*qPNWLjZo`>=$^zjE@e)ZMYg65p? zQ=kpgRHdHSoM%?{K`@#+XfWDqLmZIb(SOOQCG6 zxI|Hl%a8%l$i~CUh%h@iSSim=C*TH78pg!LiPlcVN)|A#3Q`ulCL-Du+(UF)a>;#_ z`rMp~i~YE04j zQ(5ULxU=?B8p9gncHC|yQBtr4g{1WqOe@jMMiD`5f#7~-v5ZEya%84lN~!ReJ{`~F zI70BJz3U*&F-hv2=XpmNW1a=Pa$DH=EF@B>ip{?&9m8 z{r|#7SehUP;KE5Tx(*ZUlM&&(^LgeDQN}?IP!Z;J`A{@;m-`9$JcV=8Wy;`lbV_k? z&UxNXch5ZEo59?I>!l-#?+1a%rPiT~k~7^tmjyto15?#Bj0$1pu3%YCtRn&>b-MC| zsb|IAf||J=b<4`chLHaw&4c5jgofF5Gq@TyAl z-@x@qixxmZpf==HK7W+d*u2PSU(G@c__=ZkY6F?1p^&=ccm`~%2#wCbE+<)cY8hl-Q#_Ogs@~-$!_jd z=Pfebcze3VClL~!=RL#ZH41GD^Eh@?2$$@=E1hQPA&+L{p3$TZQ7%b><(pgX%{uq2 z_LzIkbMST?W*Bi0Sl5g;AOKM%fv)&R?NVYSDbEekag1n+;U1y&DTzP->;Le-{ICD> z%eS8mLnhkL2^3_Ldz@<%VK)Bb-~9Z4`XB#?^Nd8-`H%kTKlyL|)qgvp;;uV%mL!#2 zi2w^t8+jbZ?KnttpR5A*Dv;ZY9^5rR8_f^OB-klJ;s60^n7#7+aQpb>$1g?r)G+fo zT@udensWj;&lz~g%v|n7c`P~a=gaxs>*wzn6~uWM!`ljg!;ahSrqUl#p(h}(%N;)F z98p_6`==Jf2)13QB9QW+F{^J2<7f+*AjcSE-16iIRib%tP{29AyU!PL?5DnA6dc5D zd>k7Es79P?x}d<8V0)1Y&>*vs!gn z`Y1{!xcmL(v)s(#Iynw^kr*@@rbNX-tKgG4H8XryjweV{F6iff{g+8LHbnlxAOFc0 zKl+Kh5+;=}EJU-13p!lg#(^7`B%I^vxZR$1k)XUqHKq?t91P9!wF!{ibD@kMx^Uc{K78@9cML$(_KWj?=j-b^&(O=rk`OI_TNR}|vytUYle9uamL4r&l$moJ z@VgHYmVNOeUQZQ``ONWVM#UTP+-jqaXBq~En?O72s0GjYDr))!;f`ChaF5EDuKVlD z%d2xRAlff}{_~g5-%a=F^BBkLH{Wy>WI(_9&9BbC{Im1*vqZsv{NtZ~_2Zu&b{^xf zLvwmG?{Pl`C{8JmkdveHIne(93{wPEO+U{B7G4JdfJ&}V^vnoS(K+YLYC{|ZX*a9F z>}wxWdz2Tp_(pGjsqcJ`D%B%QDKxPzS$PC_d-a>wdzvoqlgf!4V?bh6UY9$JnVf@Q z{)e;MtN22)cp`}gC*o3aed(szTXhmCgA(cO!_+ppTCWWnvi12Qe!ZdF+MYIA+nuz4 zYHh{)kYv3MzJ0*DNCh;OZ4udccAZweS_I*`lbeXIPZmWrxdqAz>08}XqR*7FPS5mm zWY+5Sv8Bze6ylBBo}&8>JeEWV8SIq%92j(P3`M`K1+)SswHpnQYaDBmRa?lCW8qcG zV!r87$()xR@>M0x@(%5+w1$?-DP%VUxC1n&z}xxRHIa@4SSVQuJ||1T7~ye%~aN=O3VvPt@*ZGeXcA3A@>Posnx>}1X$g)ui zP(*w+S8Cf>6~N8n`UU;Ud(x7K1!apJ7gUMI=czV;0iHsIn4(BlYPc}50`cbPJG#YK zg~jy^Q4u%2D#F~%EQ6#dNIXalA{wm0;TDz8vXX?Btl#AAS`I?dhFz58oKr5&gHOY5 z(Mf^i(9O-`g!u@CW+9Gf8ki1EOa={~_xsB?p8&~qw-YWKLq4Miq@Q^G_5~8)Fb)`{ z>8C+DaB_lf;}(-Wf}`VJlDoUh)DECpG>W24GCX3DNbF&^WWXyVOCnj4&Y@9|*bt7b zN{UZcSFvKb2KR+rp+oE+UIIkezH(7ay%*c(YR+ZS^E-I;@tzN_)Y!@Z?f|oBDv7A_ z5UM9ML$xhr6$lQn0wi7(@`PGq050-mn{iqUBygwfP4BDAhV|st>z4f3>5zqd63tvz zl#7_x6N<|_ZXxto*D`P3B3&0x*$lOr|DAL2-jjR$xmUw2> zxk!+O^s(nnJPd*;!H115w>7uzueH>jSWnA}-B}a@jJ$W0-!GEqeaKWNMc~%cuAqeX z{PGu9#oIyDK?X6}VwB$4%+8$g{%0>HQ__hu%GD%IQl3XO2Zx^%#xb5fst$8Rf93F? zOW`6Q5pB4P76&lk@`*Dx<0;!c+SKGqtq3}@wm38Bvfy=*ZDzFCdTUJ~b#hKLZnExX zMjCk=H)5m%f>N{$8;0rOXP9v`>^$vw3ShywI_wZ-cTSTo(d5|&t;=mWgpyN zY@~4=YHEkuNhF9exe)b{H` z3@r?s!PSHo>OOZNYSJwuE;Vg}wgRy6zlKFwqmqOZN*53WkBWeq4O!!rR9#Z?YfT1i zd4+pbGDRvJYQi2xC5Q?Y#c_J%-y+(EpgTmtl*b1cdMRq#CGuV@Qh=`uHq>${!!&U! z!OL#A@E4Ki2o=na^H?mdq;Q3%X{MBQ1AsC|N#cO{mzt;Czw z7bV8uz6x#yg&WPIa=l0Vr+!c2mbZ6CtP0(dgVuQmD zl~8ahlBiTN;ke!GHsl(I4IAHm`#B^peEmADgR5fLNS=^*y78kBFh zuXt`fv$aHmhDwku|K&c5bYuv-BWVLY+vpyqx?y-W@KU3W+}q^J4QIUf%Yo9yr9iMh zP)qTzDdj4z+f<;rQyIQ*yz9X`ZYuElAgm%kAl85Yv-l7yuQhR1BK8P4E|iwL6}?%a zHdifJ?0BYBq?f2mWqBp0TgOo&Er{tb-&i4k7W=UyFe?n%70_yeTz?hZLoa_4O9mqH znb`c=c>$)+`}tXL-QC9lyb6ODbc}Hz6SqARCLAPAcb!v;6I2r-h77|>;HUd$-~Y-1 zDXAF_X%*Zj(8y-n>LOq^uIP6O*Q6O}PseSH8x*csO4g$Dn0KtA(eY#f5z=UNAFx-*Xrx>=p@>?2OC zI+|8CZ;evj#(YOvS-EPv1gLi}C+2}&V%1J;%b&dIeSN0ih6>I3i2=gG`~?)Pq-vw1 z$5I6zLWEI}5p(mT>OpwAX6roxw|Zjp{^SAfX@zn2Fmd3OwpR#W5==2!dvG zPWo{ix8rGQYED5e=#0}K77YOBIbl9*42@xj@i1j!)u{2{n&<4|9V46U!rq89bHCX|yrVv8!Yf;-qOdM7rC}pPJ4?4W-R`c%xQ}+-|DW?}O}VMei^%Dy zgaGa`6W8xtfBT+i6=VrT6au3BTJMaiygp$qGfPL4oN`2UJ6ErIepThrP*e?#)!_9C z7PYQXU$D#t2(WK)kzv1eiB(GYa+5VXmY96_(k>KmynV{%rM-YKW{A8fte#x9>3`;H zf7&|>vd?>m+iS8tDeiZvkQDnuNT{O4$mNP=fme^15jMtg90bj0l%WG=CuuS92y3?C zF0>SjmW*Q=?kRDHr5$RxYrE1oPUsjw);9PiC~^W3qzNJ7TkfLa0KWRchyUVF{`k9Z zUOs&B;U_=)oln1f`L}=ZXRog_IZ6=VbWlF$Pk#2ZfA%l_t8c&g<-E`DzWweG{{A1x zvc$EOio?ZAwee-CVD$8BjwF2@EVyiQdmuyfw&`}he0u%vyTfjN+|Kj$2S5A@plccp z;LGc$^Yt8d({v0o*%?+eaL_d6Q}djl=Id$M&ckI5JKC4aguYAJFlj&=un2-$pAsvY z8A!{J-AD3EIUUkC2ni-&`UI@b+Ljc{;h5P7XLC?dcDNCpop>K$r3q)PbqClGvnsDu}lzB7DOSqoFBHp6G@~1T&;rd%n zvI?*eb$YqFF*I4Jo^VAFNs7w4CQJI$_vbXG%tLlNFxuA?Al$@3DC%uB=%~`8>AxY( z+(jE+hVnX?*HS#fUlCHr+gCrkS7>>MaQS7^$}EGW=T1Tu=8sd*!{Sidi25?Zj6&iC z6kDdol3HS53_D!02SG;KSlOyT16?2Sh4$5QB0jw_fC3XD-A5$1SkQT%<@LbKhB&*)a8?YfD?~v^zI)a zdv*l$_RDWq_IPizE<$uMq(!sD(3|;LiK4e8!4ig#JN2%ccgL4(b+A}Gg>c53tZ8(+ zX1i+zmn&jsVwz5~;a)~|@}M)bC0XCMD>IXmk@BY<)FBgorFP?w?7k~Zd|L)&J zBRznfxFfixfBmDc|K)%EFF$?$ZfMB$I$u+s8ZdX0FjZtMK>M+ZVe-aU$GErEUY9P` zlVnkq3+Z~9pYOl<#owlP@A>xe`A^5whg7rT%l+l^r|%9ux%A=V7eD#Q&rVDUHV%Tn z{`KGCH@~=_r|ABA`aCUKl(CpHvoXS*g^R2Jib@irP%&ndX>QdefMy5Baon&`jc26>x=-V<%#RJWN-3KTBJbi%aU!u~qZX=I zG`yez_xG#Ep67`krFrJFb)Za@BPTB4;NW1D3J3}<>MjAg%sVPw25cw=mIq?z^m30c zbq<8}u!t>GZUl8VbBx=x9;8howZ5SMZ0(uY8_-f>Nvy?p`DF4qo_a}Z)D<`L=E?dU7vhV+aRY>?D9#x*haxf49WZwh(#60V=4OW=IfVT8S;(F-U;RM!G=|K zvV8jv-}_Q4vbv}VoOzXWR5FdqRfevnJ7^)sRx~>^2Y8_&y5^yW-xj(vKa-kEKRUQqo zB9j68!|ATf8fec#tNe9h_8L>&NaJCxa~I1?!R2yE|4s5_IdsIZi(QgWm~l)Q2)(?{ zSAWTqw|SB@5A8%o$DDq?ym}lBGfkfav*^6-{dJp`x7FJ9M8ePt$b8Q$*R`UFVb)3E zewc=7G(?!+Mp{~=ISe*nQR3c)eeu-~Pn?5e*zNV@_4VbGW}aY}_d99I?pUE7OwkQ0 zW6Plvsa3+TCsgdlO+u-Wc>>lbx09zzNJ_`Jp>$+zBNKH+)>qykj^xHUp@E$YpwUpK zlBbKylMqa(fO`dcJE0|@0h30ItlpDtjIcs7J1SD!)a96lSybhARGLnbXsrMfTj~wk zNKL*h2efUSkP7)Euk417!K{5K5LJJM4WMXu*WcRss0466g(Z<{Cyuu(NW{G z)=Y%Jk=0SrJ?E2r6h|}GDu$$nBh12t1+z}-tGv`+&XXu$!LlI(7-#n~Frr1_H;vHb ze4TfXd&pnTdH1_8i2(HceDIW6{Lgz6Rwz?hA$~A^Z4R(C3jL-@UAXO|fKt zRXy0kDY=}LITULUs5(kdQ7TgFN7wE{SgjEov4rK={-UZOm8UA=s$w?OhGJu!mE{s5 zqSrSyR6(C@4^--l)vh4C|62R8mgvH3Z(3n&|L!Vd?RGB3X8T<^Fnf5u0bna0U;3Wc z!K`05^-@AIZ^-o_H_l%VtZ%2~siJJvxUbBTWZs>na}q1VF4%sj{v0?`ttXO+Q(uaf z%gP5Az9C0Vhp%ruuG|DX?z zlvP(u9f&JZuYwTzv4zWW8#AFG2Vljs?N7*BW>x;DlC;7-QgR%MvSSq(vwdo8G14v< zBEa1Y`ihd?n$C=BZT;PX0IM)i^H-FA$_)5mqR5;P5~k;*ZSxCh1z9hsCm-5{idzzt z9f9posuzH5-J^FU_!d(&mo#l(6}P8 z0x9@PHA|$75bw*|53GH}ntw^H%|E+nIcaDWn`mk;C25dT74Hn{qG|(zUt*h$q&(*x z8=7h{azo;qso!F!lA6|Zfh;B-HMxqp=|097V+16d_dA#sBh6(nxjQ%rj-8E+`v3qS z07*naRO7fkDV&UhaY|uW6g{dz`|=t_#4FWE`*zp5C7~{2x?E8!Qj5L7PfD{`nL?1- zHl}q}E3%DXck<%?R{9Apgba!yu|8A*lQFYRoG-%0nMa6t;<5K-CIU% zU|4myuL6J%%X!q4>U*2`sV9|ZIqfNNv#2jTyGEAGv=1}>R0z-nmGA6kr{N08;LYfs zPA+fxyot(Sii;r1;`9a%GZ>XsU(FgrF-`Bxk_|;_sf8=FV#)AeDs=4CJd&JOjG$8t zKw4(?sw5ptn#Sj>#vhOYG#f@chLe~Y*=}M9N-quLFiI8&yvs=8M&7Yr-9%P^D~?e` zY)wXU%vz=JB9s8X{PX4&3*lWQptoXi_LldV&W&(PadN&+-8pW@>v`t@Et)?CrFyC) z2%rt)pkV~S95N20W5zjS$-ootVCD^6hqJ8eLLB+>$2U+L)`|zkj*%f|BhpQya-soQ zJvfLgor|hNSqTiHU|?uVcgUi{b-HI`ve~$@mOJZEClZd<+NcE4A~Zrqc;-CFr8@L& zS@Ecq9O6VwDK7$QkmaPp34{uU=ESKinN1+bvcY_ld}QT&1D5sz1;}%7B$X8E>%%B) zv0KQgHYsSPK~F7+YUu2bYI9ls^r53p2%CHL89S z6055=?2)r7rMyFgi=w-b(S@YSEZUXl-Vo{nlP<6AgZHt}Z~10>cHg_SC*2$x9McFk zrdEKkh#5wA6^XJ$bAG>yuY0XP$bbi%o?1_b$}z#R8(X_o(703D*PYeQlwxg_IAIB% zdcZzyZNF^OU+)v(@&HL!q9_W;JuH5?7)5BK`SQe&#@fB(`?#9#Nl2 zg-h12G@;M?8x0&BWEE=k(lEM^cG;szNy<|nt=KmWFG_hEg8pxSVIUWCGB z&-RVT!;S0?t~*ON6|q!9*}5dhf#3hb-}~aLFK)*H@MX&V#A|j%7mc!k!6QTQkYceKl3IT_ij zlDo7#zX9^SQDqzpM<0v|LJ1h@QkAcS5a|&BY@W`Wd3l>VQW-eW=dA9DAk%SzQW2022$Z7wa3bu=2pum_I3AlH- z0Mr?UvjJBWJ@phDX$7~TD#@p(Egj|fvIieg4Ck4iRa?_iGm#J%xh`cDtf+D+wQNif znM&AmHxjMvU#>$`0OuLqzq^H{l~0Ay+%S&>Mx5G^RUsP8R;zgdFRw3w*>8Sxhk?g2 z#(-cNg(R4`^YznrFY^;bbKqP3`+xt#U;OeHFZa8dQU3MUAAkR6KQjR1dCED+VE_&o zfYafxF86VmHxZJ!oT9oIgcta`D?9doS)w5bH%=x{nI+kWOi@)swpWV)_N{pRK>L*s z()IE6+dqD*T#&@wU#@sVgOR*cg&4YzUSgWmu&fn}Dhiw=D9e~sTD;|Pt7X%2CUPm) zuz86rMg%TJm@HP*o+QigaG+emz#{CL*p4$;Q!S;PzWdyDQ3zjsxy+l@FM8on-|AtR zFPcr;_*>arQ1U)b0GexrYo{)IS5Mi#m0Ni|K3q0j<^?BsWVx6Mowbde&e`Bw_zZ@w zLNQmmM1kM>8G5S`T{=Kr**Al!3_{pS;f0UpTE-D;T+exNIKEJd$oB=1enPt!PBLXkVvR!zt$keRv)(_UANWR zUAAJ0`HNt+W);bQ`p^GG6p=L>fA(kp?*IC~|4-WOKAl;~QH+9aum02g ze0N}&*}&8DEroV>s7@`q2y9=cE9G5?KK*l<{FS5?#>j;G{d26?$@5A++ZHw}Z&w6P zMY=)63Jk^-<%q&RO-p~8X=TD(9!$~Q)XPba@-guUOO_v(itx8bvLapWR z>E9X|=gEr*OL&}kwc4r@GPRVkOh#$y?zls=!B|6~v=?P|9ODMS%~x-=^aBCFbcZ_x zm%jV-?FR|ei+u)c+z)q19HeLACq|mF`}vDs{q3n!lgBtX@bQZ;zWm`=Hq1z$PV(>n z{u)@a}p^7u0eE5<; z^J(X#__06Tg>*3{D#laV07KKbSuX( zxQtA+)&L?qGX33HmEPFGw!J(pP78aa*Q5)orrfC5dxaLZnO@{KuSxIdm`i_$S~W;6 z-+S{q3YjdRSf<{RE)If`6G&{Q34)<_wSHmLi;nN7$M%%zsumb!5oUa>PAkXUDvzgW zu~Zh?KUL3&@QCQnF+h_~ugeiR7>kh%cYbd`eLQgnU4NaM4?1rW-xcxFf(}^wADB`G@&^ym^o^y<+_FL z4Y(F*Wp42^TqRD5W`}E*Vk<4&UEwW3U$R5nyxYDrxveYA3hDDq{f=aIGSp%FVHZU# z%ICUq=|L13Xszuol~fu_ZsrbEX%h?cWr1iC6<#Am%&hc7WGAeGTILy=FQRF2f8G6J z;YPg6JtR#8w8{BMB9@~dYXg*-lyTfV*XVNd@R5fTVFNKpgDl7N)|f8Haxv6Gc-PS+ zb*1CSp0G=Hs}`#k(Dp~PLLe*)VeasC;SVaJJ_c12ve<%204L6ekR5H(eQvqz zL=kHceh^i3xLcSsstdC8W~6ZmGy`a?oIlAYa7_1CKXYzIMuAxm$Junb;U>Zj6X&o) z0!N%U6Mz{!eq@UPi!MX4L|(NC!1iyn;IlV=DoBF*LF=OnkF^oux~%N1;2Yh{qG{G%tx0+j^4t?0uRgmKs&@-#TNIc}SBeYes8*Mcu^&894_KsttBe#rHvdL`U*ZY7ih z9jy>63`BH(F^aSSGqb@snOPE3IX4zJ=l-^24vI;qc9%A+gTDdSqH13%OiMmg%F}X) zWARA9gIp9x!92j_hCFF%AdEi4f$e4^XD9E9e)}T23)#f5P$S%&$kC<*c<;dU~yONM5e?*|EZ9O~E0)P-dE%2$HJg zq&e2gCG{vpt6AhO8Zk8e_2nMDP^Wox#zhs$%c9ygf=t|}`vfVAPeB_HEfNeMN0oF) z$R#7qY|f~d`Eb_r5}8k8YpQ*-n8owq_E{1Wxjjmfj!jm7QhSDSpVw_3o?Pp7k<9-; zy}sv$ixB$b=9b;>*+Xr12oGAl&&-+FJv%$vSQ%GMt}BR8rYv^gw?-7U4D&3=ioMiw zE~aX_UDCYyHKo|X9zgn1`+>SlwSE;2>{l%wtPuu7v+U#T22k5^`NWz!_cuz(T)tTk z-F;4rd9!-*Wm{F6so{IwBUf00qMNY;!zjQbZ-ca9U|4!adHPUlXieN&JG_XY+8AUo z!_$1T3?_xeLo3X&V)y8MsTqT45StjQglZg>mPd07cQ~u@9Hc0&D-nn&o2hJ`jSO3G zlYl*#v@W4~P=-9uWn2I26bPg~ywv7fJMp+P{adTF2<30v#^#*7cN}BoXyH(Tfu>VC77A} zWUXz|ruJ#$`d8gQ*OJ+yXrY3RHs&Rf2qGct=F&jj>Y{PwlP zN&Km(lLSQ-rTR=>LRvMD5Y0XF(%X5&Y$N5K9_q0Eqax{FC3%!n2pMgXhr45&mK&|` zjA$lL5Kx%F7*%?plyBbDSE2HaGLf{pNa|6`2|%`y%kL1g|z#N86Bv0bTO^h4Ipr&EWU^tAdGuVacYKE5S%7%J9i z0h0aFWZfzQwyDd-z?UaId{j2t1I$|aiFkaUxxsbyz(|`I zWmfdmELm&OVrh1%inJ)3^_t?S(vp)cs6xCeJ^c>UA;}ocglNWtHU>owle>+BJ{^>K zoZMOS-V`1((PMs1Un?8>*5@DoJ2^(Muq0P}; zz*eByal5%q2QdN!gfy9+t|7%K?A{|~cr0(P%pX@e;81E%DfgnkE?uBvpmx{vBDmv$#DrFqQqGmw3ND4p;EgW&VadUL-R6M}S zPf}X&dUt}5=}Q>dbOk^O5mAF_^bpj<93e3B?K>Q%BxK@q7!s+&V89VJo6s51;9GO|pJ zrYIMTIw2-h6~*APborT?9b7MOh*9mEG7w^d+?~MSVLt3`7{eet!UAh% zHw7@IlLthf^Ek!;hVeFTbp72g{?163ru*}UlPFZj1|>RlI)>QpiggS^Z_gd{OE~dd0TgSdyq*NrO(F^+r!oG zPv-4K9hYAW(KF?Gu=bCGQ7^oW1^!aN7WFLsw!$pTe2+jt-by7Nmyopw)t{BNtmRX3 zMvk_3wD>nvFSqR_G96~2-*?vS*uYNuKsE(kzo^npw3KG~4`2uRJXEV&=x9S-QBh9m zUqo4_ou5Y{>NVr;uBtwf8aPtZJdy~_Mj#4F*@T4Vm;{dJ+wJ3rFp9l2k|cK>|?|RWyC;4%JG_xTaB83xSkspxq#Q<8U3GkhxmSx9cNNGGY8*~gDROh~xL4A-`{ z_oT#R;V6{XL9Ho}ZWS^MwPeniK-kH9F}J(?e%_&bm>)7bj@zICumPX#r58Z6al3sK zCj^)scCf8#AdY5jYM>Ou@`QW2097bh?NmJHIp;Kvpxmi@^o32<2qnpxW#WNob6}%R zQ!}$~D^TAezdd+$x13KS=ax+(VTX<52-anZ}Wa_=1FZ}e)D_)Hx#xV{%%r*1e3{BE~o`C2a zx`}dN!U-Jq{QTjAcbVPFskxBm?oVzUsZ{c;vFFe`Kr0_go0P7T|%3xIJPrZ5ow zFvoe$z<<^Daa+Vq_g$dH6#!gUUa;=>1hPxFIWxtbK03YTkVhfn8Q0Z!eTp1xAE|6;vpBu96?x4Vu}F z1C%-Kh|0)#F)>Ef^$DDBnY~xCJfQhDe^Q+#98MYY0(_ZK6W+;HPF9E7dz4B14`nC@!a4*lfI=ks)^VxZvfT$Iu7SYQ$RCfI#fds$pbeUqv1oYv4#3%Za*!1 zB1ph7EPM~jB5NXHP7~;v^ygK5ULLogfazzXiPkEhWK1|$G7ymSUAbyOfV)xm_-`R1 zl)BlX1_cXQV8c>C%3b3)+%*QsDC7rO+C>h=dRyh@8wz`7cCM-BI|{v4;KNe_$tF#i+Yxp zYN&n@vHMz+(v-u(x0!eyafER-q1>Ih&d`LYD?|`h-o#be|O$ z_TWmA#-Wf$EaTFFQMFxn-O}Nf&2n$8)9VoJXb8sXc6oWIYdM)kc7v3vm|ZKDRTUa( zlSaIeK-6K&^lTUyjofL5AW)2sA}SO@*8V1yiQfhzaT~|DJ(GIk6YVB^>!U*0b#4*q zRgliR&DSwC-8DbY`<>t&4vH90<0(?|>NJ{Y#!;4clpOcz*31wx+oZWsH+S6fF79~y z<`tim-BAiGze8v$8mA`@V#&?kLM|xF_5S|s3#j_O@jZ-Pm%FvV*(SNdHXEUbYl}-H zm5zM4_w|o=c;wA>?|k)p?iSw8lf=UT?oS%=_gl^WuFDv79}e&2mfiGnvktVf$FX0$*WPZXRE9cDrPNx z+8?NbelA(LYNAVmg`FsfF41h5nGG{a^fZMx;i5?8%ZQw-%38Q0)!E^m9aSCl5It#! z@PQZ1sQ-_!cWJh4Th4>NFUMSa@2Yd|L%OnFmMpMCa@dZ*LBr6XK?Hx57Qt_zM+3qw z;~)ryZLkHh0AJmsbMHA-d#^c1el+qi#@baf>q@7p)?>~wbL8X8$H=6yM#^iLVbH0e zNVJonQ}j*;U|CHXJi9O2Fir`alqQ^)4Z|2D4m%{p8ItId=T|h35uH`Ax$S<};G!Qo z*se0BmSi<6Ag#5oB@&BKDzT#iK8hcCd7FWQWJdXLv`PjG(BqUr$vDG z!j9q^R3LZNExXkSUV-Ax;(d9ZKbCN?Y?+6M(DrQi?vwpUOLK#&R3M+*13U{cU zxw93`0I_-6fm_2EB>|MUNie!(*^7%wuil8>mA2H$AX$%Hq0!dl-KIH!;A82 zL{*k0)E=wSBiUIBLAE>&R-cq^v3bYB+$>G@3G)O=Mey-0{JoAv4Bt z3r&X+%L~0=eBprfzjqMq@3V@5t^ECOrM6405H3-xlh;S+ukz=bi! z%$*Z#wdCwcvsRG!JlWstIxGpY`pfnmypP93@Qaud;6Ne3Du+%1BrBPs#^!3cyW zP?InLHnt>1qfejnQt1yWgQ)=E8pFmBo<+4MqbNqg6x?-QntuIwe?3PgA?5CJUJyvTpMHCK(Wf5)3GP5t zWj2XbXy2kiag+{l0RwJIA#K_w6%S_WL6WM(queXah&K6j9k*K?*cwKFPq$|pkK4_! zIgZ=So~VHsQ%p_w=s5*|uyH$HzWq2gU4F9z2B#xJZG$9_+s!z#WiNDTMyFt)f{5G} z{iy7SOto@#%^+A2nsoL2@+Q?nA7F)IUI9@OOC{@X@FX{F;IDwMhIzEQtCz|9^N zqRmch74zRT_bMu=9|VrhII7~DHO85{`I-EDAA+>YBZj=Qe6`|Hidx{yTZFdMNQUYi;*cOyN!PKIhXn)@82 zE8N!XFlkl2-l2nj?gwkS{<_=f?Qw!v5)W^w!-6R)9*%}>jM-RKd%5joNMM`SFRA^- z>uc|Aw!W`Zn5?CxA1wY;BK07xy;D&Uv02rfGVdVMzUW7X=_{-J8qmVK`_$5vI;vc) z?KVlh9QjhrU&sPUS1z>?(v^u3l`0TXlUjhx=*Nw^2B@xFW}x*L$=mbO?ZbS&*Z~ECZm85wRfx6Z4L<@ejv1LNz zf@z57{XC8cbfMyR%&!I2lJt4B54AIt$msjtA$dSqvGtD4(}a{A2C^$lb9Dyf37_*K z2M61coO=E7^}2qXnD@8y_4DU~zsY~hR&lBA2aLw)9?i6#j;9O*3?nftihgSNLxqHv z2)4dRM`&|(Hr4R}>b9rf6ncHHjLDW6@o{j!UTAIYE3 zpi-FWEfs7+p}QS!VHvAsr?NjSNX7Wu>w3H2-%Nv1g5KjzRGp}#$oazY`u6#L|4gT% zfw0R117*ofhP~sdJWq6T1;V@fBH}UGlSj6xY_ZSfBAp? zZ~yDRjI_FOkRw!MG{P9`VXJ<0Q?S)xNOoQK*-q)ZOH;7_|kXf6+H+knwO+|N3&iSlgz!8UsXEonHL* z-(Y#|I=#|H%^6`k8+q*4_!7|k$CkE{b_bQI2R8hqho4!%URsthw0Y>2sIWmhm@U5* z7~f#j(&6t0Oyn&q0<^)ZjQ66AsCXD}hZ+1R52d2!tZ{kCo1}cQE|dY1z$UJ;4ye2AOUaH{-4S$;&x`Qc~YfNi@%jbaJgS^ zuaRo5jc;28+Bl9IY2*N=Lisf(1imm}B6DPM4WnWjJbVN|O^huW+oey;Nd4YB;!aY5|U&F#G(p1ZE_%a3tG@wv|{wM9;Q%_7?v6j0LE zS+X?9tYWk_s-=^A*RAp-p_;w<3Eb_+B9a(gXu2JJ3q)sFGttCCTZ^6rrt<^U)$zbK>>H+7&#?b@C(H(?9#&N;?(Lu zB0mVzQ`D^m1`YZIcF2)2j>UczZRH#9`T#Xviq1F+x9glUC?{3pEd{>G3hb@iNSlVq z|F9mU=Axw#`ns)p7t`5$42G3M7y_FkTO8HiEL*~}ffs=|#u85{Lk=z7ljd<{cSa00 zm4E7!O4(;uIwH>>M{Fa!s;B@;28%X!;i*~VDlQRbH^SVnEHQ$)dQwA{Wp7Ss5DB>+ zwH*qa5RzjB+ZSC!jk>PEk$QH|{w70KYs|0+mgK6uew!t>P}{z%&3z~}w3wwpL1}Vh z6hUIxA@LXovIZKLF3LY1FHd~BpXdF&AAB|g6%FWRMvvV)7$t6=>C>`UmWwNlC>sZo zT@#jPrDbt>v;SkTH^q>jmN!|wg-*;F%2KZ29f*bhQt44&+W zZe|%GYzc}Z58;HBC?7mMdzV{QS_Lpw%oOtu_?1%01xI8s9=`HkiJTrFLd+is6Yf#N zp?b7ZX=pXvsgZj4GOygcgwS-zx<_o1zMxC~CzOtQMS&r-35U41PQO8J19n)rS=MxrmtsN~^N3ugQ6kI7+nyujjb(D; z-Rv^JvQI+0P|K|^s+9&0OBg+rR|VACIe}e>y;<{zz38h;n;k6_v@umY@RBz(4hv^X zfOLQRbX}(?P4LFgZ=WSicNl%%uj}qH=&i7CbklJV?sPkFT$rFq&S7CGQfr01i1WKp z9!6oG4~Q0O8Cnfy3?V62k7sBQj0f%cVDVSL8ntCT5+s7wn`~`*z0CdBaKxiV()LEY zTmSNhFR#xlAF?f2$z5g5RNw=p^P;_Hebm3r+N`*dzPQm^PU9{BU1ZvC?Z)ZhK~;di zpNb&NF{{~V5jsthmQPvoP#RkukPN1e9uv8BA zSama{HYwK5ctRhl?+_8p6e@kVI}Ua+vv&w*(H9wu=xxf_SV`%FC_PX=O;P zR9CF5S1DL#g?SL8jAPv*&rDR9)m*N1gDHqaBI%AVv;%iA+*1jtBSv; zl1XkT_Nq8j9U4!ObRv34CHOwSyRtZ`YEn?aC3cfampjW0T?T&)0s1_-P@A( z?QG}iHKpC^e!@uq6VbVJQ>=+gByMx&+Rz5iERR$53qf^chS?1jXOxeAnH5IQ=h)-y|wtiz9G-6I3%l#Ju~ z!*hgqB~Ew0X6>oY*Xvim`oCj{s&kP}t-}(b_0ugSxM3k}sW+@mZ^+kViTp~Pmd%Uh z9;fc5*_1S8Ll6gV;`Pn9A75TR%Juy5!*BcF`Q?B3)#aDhmXc=20L958@>^v|+ue<- z1~3D;K|D&w~A0V47Xuy|k(R4I(uISg}`&TX;PY zM`2}ir{q&c!(m~-To&iGqgX8oS}p#OhOk0y8MDhAMm(XHFGrc5Qx44;u?9P0auUOG zCnAu-F(?nBOlGbz;up9WZA@i#s-5fGi<_HKiYgV0;(kUVPEurHv-ZM_1{ZZRDXRI~ zU_aQ6-8}95-Z)KJBjwVxn6Qv*=--95TKXJ-z z)wysv#)utc1_C1`p$HfVh!JlBOpfdF$p6j=>JcNPg^1m%Jrx)y1X9lmYszdU(#lgV zQkWS+7M7FQG13m;kzss-ueR-Ap|%Kgv4735{Si)K-ZHr|e#tCFnDCKD;-VKnV={Gg zDj!B3mH@#t#&Otj`4z#ir`zqDk00;nBwWLEoxl9$FWs+UHbf3QeY~X|Ct;SM0#S~0 zo)=HTG;x@LaA{!p?rt|vX_dU>J1k|^N`AKv>Yo8y5m;haUwBegg&S6Z%iS)2@txn< zuR*r4xBWrJBAW>IEmc7bwRaqM@2$N)JZ+nybLrd51&50Axfdam#3$fmlxuY{56B@k@P7Wq18S6YqLOp zMd^adbDj|{xxc*)*_2DuY}gq2gJL$O9^ZoY)evY4Y-~^4kZF7A-M^PATwmn^0il*1 zq`U6-&-1+Gv;%X_V;lpA*@)Kq18_|DDBka}XGRjyo55!XkmK|`gouE$PmO{Er~9YR zKSW$dAUQsMe7QY6SCia2y+-bb&KD;KE>wD3oWpWBwgEQfer1;|7J}I*7mab^6lL}Q z(nM|;jZZ{j=S)eVp%PZtYN1<+X03i%uFN-Y>4e&}()v2D`+1#_sB+Hdr;o?hh8N%# zR4O182+wtYebseM=4k_hW86meFlt>Njz8Y+pFdx(J~bk#WiXi?ho)R^uu7)~1QLh| z4Wm!HuJihI%A;DwZcl?2RSP(dqp6n~$q^F>S&m~W_68lY(8{5-%R>RP0(y(I6KiMi z?)6}dh2@wMiq6KU8_KGQvh^yE^8%Lqm_4D;ltyL7@ zkvfHqrTrd_&b|@=6$mUxeH_Q_>AB0Y<~2XPeu~=6ijpC1EH^XSe7+N>)|#U~c7CZZ z>G7*yLZ5<;{p}>-@$$^uXvZV(D}nI0^SWjfl5Z>dH&7Y{Hd`H8-z6{AzivK zB)Gxcz1*_$+M*ahT8@9J(L#k>2>zi+=G`l?4-o#Z%499;x7-v42EE{)Ctz-Jzvg)j zGx37-eB55`9_PEl4$FA^@FC8En9IOxp3znbbXWAwjd~S2H2ne&$|SjmU+qS?vLV7! zR;?RCWL0FKLDeaQ?;l(hY1yvuh=2YTQt9!1#yDR1F%DgdsK15mA_5B&h`eG9Yv1%h|JWz!h)jNXeL1xASl zhaFCjo=42VXKBXD$}C}HLXpntFKyVtph8il^ss@zatvadqg434ADh6muWKFiNAG2m zBW+)NloVpDrX&1d;6Rsr%Kah-5FJT^se=0>%W)Dm#+WvU;nU2<)HIFr^L*wL%oT-m zwTkHu!!eHMaU;j{Ny?}E{#jRg17_`BZWihBFWUYe#m4KS{m&w0aWQ}Z-hH65ET0Rb z&+R12?|gQ}UW$~>YJ1Qk^+9&K+E>!n_ltMw)2Ai|EYCpaDX~Hl3zNihvR0-M&by~T zZDX-wnvyC$sYiJH+n0J$`%ehSspwK1m&>5pB$PsuK)MaM*b&Vre@{tJK1Pg<+SdGj z^Y}#(^cRbaK06C}gOKcHG7oCkqQXYGCBzGCzTURp&q(RX7r!WCW>@f9%~d4)xn6f#s!tv{}^4E zs;yE-7t@?Pl!mk9yvL-4^R@6)k)qWL9Axk1t~TTM?l#QNi^Gm_oV+8X+33(gfQZ0q zk~(TvQ=Y;fRw|f|gVH*NQ#+kJ8G9mQHi)EFQ-qipAE6@Lg!h?vj5TzQsh zU9C-|@qe@K2>9C#Ccur(9|(Tz-^;#8N|};kv8}O;Pg9>03i9eLy?`X zSWBwkFaeK6RKbW@8aJuuk?f9>dzHm#XMJ@i04;~=ZqR`Ml63*mSw2#QKqA#V@=GI3E{Q?01p62?{>Jps(q~hD*RlrxrPfHWuyhw9$t&%zJkVzn5Fdg z3vTG6iLVD@sy*Z7BUeBOj43o**n3-YbK2uFZL367mno?VG3z(Y^h|&z)KNUZqAxs0 zjhS`ifRSBkVt#*LXoIt96NdgE5mP5ZZDx#v{-^t40Ad-=vW07O^a4xT?V5sltH};_W%G^T5G2S z(9Q`;i-7rN3~sG3Ua>~cD{0fT_NZdA_35U(J(GIcVQ!)dg^x%;budDup_7M@DnDJ` zgdd*Kj;}oY-~M{H?Dj@W$;6Ex9PN&4#WL#Im`k--i$~XW+K7pl+M4IMH0O0Yp5nnW zJ#W}m<-0XD?GDryKW_ALaU=WB-l?QmL=;NZKjYyJH3dZqjS ze~8c2=*ZZwk#RQ0vT$5{#6YD$0!=<%KY(vXP2$T`rLG%dWnoQXj|{@4V*-FOGmx%1 z{gTY>qD6;6$rVkKKyc7vRKIf5hV z!V7ed*KP`2!b3>Qs0D0z(0}~_%X`y?fFde5La&-nK@*51eFkh?n#c%cY`+16BTQ8& z&>@@ietL|$kh^CNXajC6U&z}GM1ya{AvHiAJ+-DXBoXH_40iccHD)O2(CqfW3vF-f zAF8m-CP}H@+8{(&o9B6-mmgy|CT0!mN@hx7;=`@{ofo>yHOsHwWX97}1qM>7?f6P| zLvYZ2&KalTLBhs>g_be$;r^`iGeT8OqWby(QXF*T*25x~T?RpU7=}6Tiy5)ynpC>7 zC-n)!q)7p9b4Y9|@LbuZxVY^5Zir$%C7v0IGRYl^-YmIMF=e)PP<0aAAx>vbvI;`S zK-?a{k_tZ0@adjQ$#><0Ef;l*bYVf7V0_Iv>qKhlIxLN=?Yi%UL+{_%6nz?0hv#7l;(Wa# zP-{~JkK0Y6Xm&fs@f4%GB8PDK1TK@!^L}2h2GViGS+a16tR^zD0#c0PR2fI;8{R|= zGak1a1N@NceZDLY}PjB#Pt@GbHs=5p7Sq5D|+yb&-0GWivL5fOoG7X69mRqnqAAfoJSNMTQ|Nc48BTix0a49i&7Ls;o*^MFh%jA8(y1Ukydq##a}& zO@U?@|G^H$iPq@DChW3mbD zB5WQ#a>9+#^eMmDfMh=1UH9uXp4L)y3R5<}Sz5NXa}Nv%MpG!DO-h*bGEWUWPzsEY z!>?0Q=XIrvlYT^;^9nzv+=rEa=@4tl2xV30oU#J4`u0YPnwBnARG>6GA>Hq775Em zFhQhb8jQ9W^6A5lEMAF8x;fyftjMm{_I=8xV0b!i;}%!ojBsgMIkqBULLa=oeV*qP zG^2L_j1Xe14ax#BX>yxkbtSnt(1$0)w~P(+jOr z)%&xCdS3+&#A+f`+Lu-OlZtksrqG<3bEF&cFQxzhAOJ~3K~w;jYo2feX@rfzQB7i! z^UFw-_!nYOhG2H}zHJDRSTm~k{^q-1|NFoC=ktEj_;P!3_m3aGz1-~dcfss9 z_`ARR+p#K|{qXDS)9e4~*PGl!X-kS^Vs4j2F|*;Z4s+5dzj#hww=tfcpCw@8?yp`Q z7ZdulR13;*|4#JKl`9)qRwB=Wwr>K z@kVlt(%W%-*rgi_L{u$N*6}FL$Y33}q&WEW@{;%Q*h47}${GFg>+RfO&I9TRUw=h# zDk{FwB)FlOuTB4sE7bl{UZ%AU9AfmpG>Z=aa148TV$GWE4N`OW=uYLyqkI&bR@_0m zh9^hEypHKDI2Srrc`Rk4$a>}lUl3fR^_1HkvGda7t3fjw=xp!wt82b?Xx?9JI-sdr zHcFXT+yfVV0i}bSD5JP;`(kT)`*QJ0a9-LmzuK^@43?A5=mg6tn^`hcW3L!J0*RqU zA{AYWCeSEZNI}EGU>tG8WG!QnW64jE|Tgaf7D^}vA}U*e1BPF2_&EXblyQ9W^DY}HTl2$~}sNn}VS z(hf<&(vM{qfdB=ujit*9c2yj?6b(R%Q!>oFGOF8yWw6OWc~lBENMq!lTBVrC-w4~ z>L)KGMO_FB66}O6Sy;h=N4x_hRhOhBN(P*R=Xw6{-LE;P4SvSwkKcat^!!BQ5jiSM zuQZIHn;n1nvtLZwyru>Y+-ROORu`gMPW443oZxIJ0sZD>z79@&ER-H4@)^3 zDr8z0RVC5*KJ{BG9@SM6+x3HP7Y;Srf)?yp`-UehLkG!#Kpb0%nZcl>tcka|ixN2gYlN0E9RY41|31&&b)w>brIHZ7l~ z5QSxOv})RdGbCn`+B-bDm}q13f;*&7IpjWMSrM~T=N8fkN~z13cMh9N2^C7dNR$~NLjmD+&_I<8b93$!W~4)PxR)_(CSa1ZQU5Z5n(iUnX^ zlf!b9bRa*v84N@2Q*+|7F^uNYbf3CTza%pocb&Yl){n{c(Y_*_ts-FkwGtne$~5QQ_pU0ChYi z;f$%6D8dgtM|;C&58I@NjZ=k?l_?tZrCa4F&gr$;5#oFn<@v*0fa=6T@e;Ebjfq0y znc84@#egzi5Hn5U+z2*iWTyC;PidP&kG!%n-xI*kS?EM@feKMB>OET6E!k0tfcWT>NC5lTWsVt6B4*`ikJkPm=Fm5WT&h>}h2vgppAYcXqM@Q<=&7DfR zOSS@ZLI7Rvu3?q%sIZyU9+avszAU|vrZw&sbv|VW_@Fh4=JjY&)@ zbpWM{9HHziQkb$l1r+*Z3(4lbXD}5$yy8L88k^->0F{c16*WfckBX+{8&v$MxFxd~ z{Rm6|*9po6pa9k=riy)~L>I;DNf4@GLrO}^;4Vcgps6XJ5(W>~G~pnw%P}O6rVR3` zE|t?AaW2pak3@QmXA70?Op|9^v8Kv`IJ37jz+;T~tDP53Z~k`qHIOZrP<{zXcejYm z=BRHKYbN^Hw1QgFmql7~T(m05TFra&4|ZMI)C74ONBZlgY7AFN_rNx}rI~E4L*UV^ zYV0czQ9osIsp`~Q#hpS0tw3k_VV)0y`uw%1p_!hSb-&x&=}L%hO3^#{wTY^;UG6=~jMyAyuM08?yq-Su&ElzSZ7qv1g= zr$xQ#)8L}Z4y!UDwM;G;iq2(()%XkmvOK9}k>9Vw{&561$_~`e(RWN37eHwvrqGBb zlSz%oN)%O5^_5xKcz)aScyK+Cxu2?VgSMw;Mkhpo?$bCl=Q(E&13OQT(8#<_&C8zb zKmFssi!rbBl+AyCy!@L#|BJg`5p+-mc$lhFT0Mm8(R@}JsD zm3mmcpmx2xo2RuCVV?6+%6ceD6)Y_rfqZIJ?Y2@ZbX{(lJJ39*4ZGehxwt z-O2)G$#W8f`R1E%KiD9M`F0)y^Sb8Lh%gAjp=|g` zh%>ZfCR9m4lYBZ-F$$!)b>W(jj}FW{b0SZ zZF+x8enSzo@_V!Zy;Qt=dkbH`yWo4?S(hOwdq^yzZk~28<|aQV7}hh@AtV&HvpNUR zENUmXYwvm{eC^c$NGtF4g`Q{xM1*scSJ%FWq2RW-N|WK8cK?bAXce~6@;&_@-~dZd zdx^D>T3sjW1Fn%rjS%VZF-U6m+Oc1g4{7_xSt!)8sJ4GVjTLsQe8>LUm?-Uc^V;^! zE_Oiz7q%i_%B{j(%;*C4O)p07t41K92!z&*y%Vjw>P_zj>Fd0s#BMPLNX9Yj_Wf_Z z|JC<@5y$4 zalg+ucL9oHArT3`bb%o47)PFhJ9wUFO=m0h-h0a0f$hC_FK$xcbDs0`p4=)#5{Jk! zee8YRo~&=U@mAmj1H?gH^TW%_FMjK{#w{X9$LH6#Uw!w>>zdQ2Wt^$(&62ZV%4NI( zgu4&n{`MK*;BdqV#4%v0&seKn;HG?#68&xAD-O~{DtV^|F%$&(^oLFnThKC@Q+0G* zMD$C9Bo6-KcYpsEf9LmUqHx&w%fI+HfAh=#fQqnvO#y%T?@bjcEj=>Lx34AqPR1d@ ztcgHYg~UE1C+$Vp2&9gun_t(<^UELn@h{%)pFjWjcAxWyAAh*qiNiqGjM9H#pxgTd zJLEK+BZ7oRbIrH=XG}vJDX{VU^kl=7MRnL&GLBQDL+O0b&qlb}+)Xknz?pu8bA|uj z#dbF$rWI&A)&P^+RhJ2i3waJdftN%;7^H!7o+S9BGl)O@gWvh%Kl#JxrBrcNqUtq_8Syx*!bP6ZOMP?=Fh1=kvP6_v~4H-&pItte#~eap6D32L`fy0gRNkWM6`)R5 zD(Vn?U0M!}SlR{?tGqF^SnkE%Dm1T5piVO*ZJ6245X<287PUC9H5C#|IaaAbabWs9 z&k2}gf>Vw$4jAFOu1goMd4|wl_j&p0IHhdtm1JRsXQL7{`lkjQFhxKO4)tiZ)OBjf zl_*@H(WvPDlFN=+izT#>>Q;sS+A;(;qH8S_b~xh0<$~B^!9ZFxn$uve8A&& znnSzo9@6J1rJ3EpfI+*xJWHB(-JXxX`*(l;+iyS4=^XaUUw;4nci&0QaYXNLt7a*c z*6@r}L@t=k%$Y(GeabbWO*rX$y?YEKw$3#pd3I^)tjA?B9d7_PBf`l+P-c-%F zXwK-0*j@S9HGR1R)}ySc^2|PUm__YKbmoZ^1+$QY3qR)=K^2!a(-y&t*K2dReLKHj zr8%)Hv9^#y6>CtLTe-PAE!g|~`17Cs>7V|I`$^gNzq$V}|KeZ%@cJXI^d^fqWVsk* zCL1zaNR#MwaH38rSJSE(2ASdD63=QOSP8C7dMt-DP)-Z@ZoLpaA~u^GTfCW;e(Yt> zO6K>RySAt^SlZ2_+D@c%`b2d!pYyuTbMOXf&}eZINMqQ%asv&50T*oG;20z*qe+|- z|LR};?{BZ?G3=V>jr`+3`h6WSGRG(!!b2GM!p$aZJ6tF0C>&>-lTC*k(71w~~T2#kP44ByI2r zv9nQ!AM>tt$0kJ!QiG!1dtEB|OUU#1`dd3eH;8jZ{Z&y{7|r$>dQwL+Jo^J9yo%U- z>q7>$wo-?Zy6K;#oT`o^$L(3s9`u85i!2M0P9q`#mz{r^wJ%XnS=UISL}Vy!MTmzL zSlURK|K0BzUqbzFc>*Q#nV|F)jimA4cgE3r5U?pFdIf_(5SP>x_Mh|IHsMEYo#CS3)8>LQ3gXSfu z^~{g){|*U1IDCa?Dl}TMtd4+^L)-gJZdU@L+2>pblkM+B4zb-lz?8RR8)5a#q8+fuAl zrXZdbz7AP5FSCjIP6y?$t2atK`ilQmTNi1ffKnQM0Wzaew5SToKq1S4D#*jyh~0p1 zA!hTtZB1DeVbGWn#6F(vZuY(p^b3zJkd|1<=w!nYgT@Q0&KG-e9$u{&NBOgjH70+ zmL_<(ZkxnrUOjxYHkieBrLudUGY;<)>6RWgZoKK5c2N%RUO#_TW}f?OaFML}w6XI?{a!;nkU6Iv^AB+zJwC9EqR_3rf$ z2Wq;kXhrkY!{61}mipzpt2U$Lj{=SY`Ec7W%AwEZu*HGE7b{j@yRv3wbF(#KWC`@p z?~kamp)a5P9ROO|YNv@(g{WA1v#xpakW>t9N*Gbi88&1(!;Hc08bzlftb-@9|;U9C63fFtoVNHk|B98=%6OZwg=^0u1~(A==XmH zZ@1I8wvzQ!$xSQNS|XF9fD>fm{aRFyy5FlRdiHnU11a|J^sw%PP}};MMYI4GCQ9wH zNi&UOjN7<{Idu4`(`eWIGLxC^mqSr6MjDi&K?mHN13W`R#h3Ft+GapcB@x0nYD z+~G!R5V^gy7_*mBIt-|hxr(LsfP04T zV03do+>9FG0Jz6Q;AlX;JdG(%*G1eSL5Atz;hKcG(|EJ+pK@LX*eu3$!U=P_Ya*s$ zgntla@Yz5r0=>!xNpj(r#lBzhpm%IvF5n35$kR-BkCqoY^>qJ$1o z?KLY|kirz3*inY0G0V_|S?OUXkKm&>FE(d2@O

iP`}9`XwO|H`?gp%~DnujT5eLOgsMk&wu^z|FysN@&3>L^5=j1 zd_0|^kLO7~;}w*{9cqezfG3XLzH^g?&;Txb6U|q7x(Wfts?6Z-@TrjzB0@B1MzzBv z?fuPu?07jQz=Ka;+VQ@1!N9@s{g3be=HLE}?k|R8djIbKxS41$Sp(^_%wPo=fSk|; ze#KNv9cPoq_}>*tV{AWu|7V6KI(!=2=Py6s{ga8!ZI1cz;~%04pG0Fsl*~C@>iuXR zelS_&V}y6MnuN+Vs7o-6^hos4^+jaiM3RjWVD%HnNR?rnag`We)-Ga&?4x~ zdB6Ys>EqNHANqQ}{F~qXOOjLGTWhVod-t7Lb2w=^<}2!d%}Dm+b{tRPrI)<1S<6X2 zivzh4If4%adeGSyuWm3p-XGyNGCXuqlQyIODs4p;wSvVye9VFMDDC><%Yti(RT$W6 zG0uk-@Y4CA`yS0gJ+ahDZnIi#BGbH<4hY<@npx)CvVa`jWoxzvYDMwCF~os+6RbN+ z)YI5<9ZqA5ZetBCf^^Y2Lj~nZ#Y%7Z>T(*Ft#Ptl-rd~wvIVu!*hd}O%5RHLCmD@T zdF`v{x+0I4sREr;`WzMG6%mz-Q9c=|1DgHz1f4MTf}x^*)` z!4uK|03ZNKL_t)ey*CHWG1zZm{$r23z1dc`Tnu@tmv-3SkXmf%yW-%upIqFu>{+}n zun$pj^hFTVA!*6LCfe&$B*3M35l|5+nzFD$d0rZ zi(ZDJzEAb%YC3hTuZEP-l zvCttzv_IHJ-)u34avEN|lr2)?A!&)OP#3rY_W{LQh~x62FZO03^Q@9x<^li^Q={o- zhxv#J+BnbGcTe-rethqD^nN@)-9HVV<36E&a6aEZ+cWyT2NsDrj7xwLYFY7(;Hgnc zB_#`$|2h7z;MT=A*y8U%%sgEBEkV6Rc+3lS2L)NoycP^JAR0;}MVeVOu%t!zf{o`d z1regPe1Q)>?nq~uKAX47phWt%>b;8#>(iNvJbu@@ay>BV^}`J#@1o7xN3B!3;;Dg` z1xyWU9<3iww|VP0K2Yvsnsr(iUNgWF$y=H)U1Fa%>b z3SE@KKMhDQL)>0u-F%?QIVMG6Y69+!@F;f}-sJS@)?6;mZlVW(Y2hj^FMttoiL#Pc z<5hzj#It4p0MLkRT~*+YfO)Ao0K#;S`Qw73B$ou7G@~T9^v;x4XPSVttzmsUygSwR zAS$wp&qWJ|sYp(b0uWqWjr0(NS!YEX0h%n}0ugyNAexaa(zem8(;bfRe>U12BW4tN z7aHu=%uJku4r}@GFd#2@S^OwOEh}>=mw8yAv($``W$-(wc>EDS8r3j5gXwdxJ+KX_-&8ldUI}GC2qJ@ zj#9(H1oibL`x3Z3_r)|+_5g_6R55%e6JyL2o+i zPUysR0<`c7I^}dE80+5&eUUQQX$7k_>=72D={L^WPFmE;A0%OTW{AKmzu4? z?YovADs6x29p-(;g;w%hET4K{yAQ;(S9B|tYLP&anT3@~!%izmYI4coE{Ux%y7K$$ z=lhqRo8$Bm23|+wt<7;qYi4MIvAYk48X^Fg8mnwE>i|l*BUhcr2bAM`DKzcitZ>4X zdvKjukSm7ql4$f{VVSIDW?An43J))*7gzS9>H6l)_CGATyP5$orvuLEjTnScJ*358q~=Wl zY9lJ7@bi08AwYsxlx|bZdfY{v_{u}LoI$x{Z`PuJPw%~^lQHBe0heHmIZ-6wnh?yR z1R%ZP6<3Pu|CNDvu|lF7T*kSEj_-$h0dECxl0nWWcq?Ksl&=Fanv*6wbxyi#MkDLP zZsvaKZjJ6!jndQ%*K$-Em`^7guRd_8S}B9oT#%hdH`TTN*}pO|^_MQdE=1WfAUbCD z(O*a+7>tC&Q3FjL%^FlbqEy&W>A{3ZsTP)rif`poHA}>o?!WZRS3B6{ev`n9uO99R zxf&1=db)IMen!HJvW8|NT#A+>c`-Fa*8n42ZUwTKutAIgABB*KiiFn{1}HIBu@Xx2 z;X;~qLa87_m(^s@I=~=$7NZG>0ay#vEOo%rs(f?yk*c~Jwm~Jc2CzztX&@VW>!fMY zTJIU5C&9)ZSg9Q*(R#oEVcdi+f?} zr@V`$7nuchSgPha%MCePHhB9fv%6a&=7gi2RT$A8%qG}A8=Q{Y*`7XIJB>c@q}C^= z41@rEK!U$F!AeSr)$cT+Lb7P2mT_AdD-A98lcW>NOGP16+S-Dz1R6z2RPnl^{H0Er z3!#)TXS7u9aYlh-COBPlPHXLc4$0hGQzz}j7pXOG0Gc&ftijVE66X*LURt8;Ytffi zmRc>c#C5k`D<&9_xjn+aQp#>oY+bXFGf0y%0M@M_9tj{q0u3~}RK@Ab+`8Q1 zQJ6}_i39TC?m)MLqNQ~(wx(iNYXBviX$)F357a|fEj!!2374R*+vJrc0I*jmXTy4d z-Ix=<1voIKI7jfvbUEEBs)Eff@N!vK)PPiDIsORQjG^323Yn#E#b^ee^NjIqp)r@o zV_}*i_X8W1?5gB88CdK2OF^wiQj4e0AxD%B-Qru#<{thJn4*C;8PJ^Iu< zhq70#gRI6*Q(jH3c)TcH*#LoNXyL)`Y)5N745+}~+B>x$ zUWpe6plNsi^6B;SY1ZE9^<~Zo_6b1xnz5U|1%{G8>n^kCmGQ{rZ2;xVvQ(!P$S56G zra0lTEX4<2L2F2%SA$&zk~TExMHTDp$Cz`vqcdhs#t271^NWo?m`4+bqfIbRI6c|n zjH(@!XBzvKQHQuNZ1K!8P?0nMR7wx6itb~pf{6wU$jm(hafz4G)v+7zOZ!zuR?__v zo$IA6Wswg@xGb9La{36+s%YWjik0OQsyMC?FOz&K!g4OEv%#8t#tmrKu!{<%YReOz zxN5^5n~Yr>6agBnStrypv4CQeZ;jgH0|F7HEZIa(%B;aB#aIc4!f6ue7?*IVm<|d+ zl>oIU8WXC@vbgBtv;5z@PCw^)syBa?y%^?zlXv*<$EUye1N73o!v>!XYPo>Qca6pP z;;2%6@ij}Kv8YzZoG7f+VL@YEeHNaco(_9@d3||)nTR%g&7RuR)VROA#^qk-a`+f< z%O*7d*`|AIt&xMXtDEd<*hlO{i`67{O3J2NN43Igyqg>w=)_j2!Yn{PQmP|T0c)nG z-bu1Gw)5rL<(@f{l#BP@BWzkV8o=E5jsW0vWE>TJk zOey@&pFZ{9|0H0#w-$jguW&2Zl_`T(7Z3!A-jCLMv__1ejK-vsFi}sp_pRl?bOU{2 zynM8&i`@0sj)AaL>Lq<8h{|(IlXiLXw0~j&!vGufN+yp}lh6ChD~YMe3;=1F(-=0C zdQ48}{`%!St@J-KhEjomLS?(wykZAIvFh7WmNxSvl0_Ksy_92oOu(h(K3lX$o!yEh zUV~5dRV~z|ptxu(K=7$K<&kB%%DqK2(x3gyPhVcYJdgQonn%B(zx(*d&-2r;W>9PQ z^YveU{PeTyb-a!jn$F|+_-}t2=djj~ew)I~;G%EejuN^;K-Yn9C-`vgi5}|@RrIP} zZB8{w(?^EZ*cbT)xFm}j7bB-um0DiotY%;i2$OxN?v{r-A~ z@w}&d#LSxe1jnnt{xsVC^eCd2VYX#$(nlW@%+t`tfERD=(5Gy9xwtFm4;#kK>#{{{M8)TL9j~Zn)avh^daFyc9(eNWpXK|*dc*F;Uv!a5@F^IX5zo9vX2Gu(DibmB z{P|}A?vspGTZJ($KvWZL1Z^DIv4B+ZyEnJda zVuI9;8=-@kc8WT9WF9M>lS7shk=DRh!e-WT8-lDpePmyzvZE^it5ON!#0>TGG-g>)|D0+AcW(rmX_+mPCj> z$iqgL&p`&0@OnQ9*HRz#`~&&x5U}9IqZM50uoz0^oR2flN^dCArQ(E+Hb;XI?T|W} zsRxO>jzdrGW@uDXCM&fVU#}Gc!ph-Vh_;w%k9gq?ZI^yhz0K=n)$E8XuxG=-mcbaC z?o%`MAdOUuY>fz!rME`bdyhDXF>E`rMeWjmqne`_{Fs;nXfT=<3NsWB8dB6V92<_5%cy4H(sKaIK=>rBm>cU0V zLGY?xNDrMS2|Sm^h5TZ2rI=+qaQT#lE>)Ch(TEkG5-5uXQlb0E%nG`Q!m>R{mfc=m zd~w-Vk`0lglYL^s{`efzMDu3eHN2TXBkjrF#fV@N0N(7@&}pODfoay-O*dl)&N-(r zC$04enMP#7>&&ugOmd;pamuAA$mQ^f#NLH|^9mT3xPXyL( z2df2S8z<5Q&1m~&bj>mD=bcls32W$_HzP>v@|&S+%4CqN8Y>~ecL9Zqe>cOmKe%I{ z{h<=1`fJr}FUC*qOk@;M4H}JTX>B0Er^X3C77X1q*NNh6o`T>i>KT9E0Yfawxacwws7?yL9v;YzFK(&*UoJ_*t8loL$7j*)AMVMEg~hZ2^`3l zOvtuZiVkB~8Y0K8#KJNYLt956Pv4KU<|fCP&1iYYoX`@f4zby#OY^RzrAHQ&W572= zfyE^#JIBUD8)t;8dRfhlOsJErbp}$;fix#*ZM&8WgpkqTAe+1oQJRSR<&%}mps zX5k22)-1*R4X{WGtXojwkb2G`3e%@+!aaDW{4)e9A~;1d<5*IIxxuVK5S2lsu+ktZ zcOD`v`V5KeD$En$ov-0F?;KBxrU-B z@XCHDwPw*>;Q_)bdo8Y0M|oL`jW0}j8B4DCQgUW#L4<^7#iz?Byc@lnHBE=LZazeI z9t3%4l4(RtQB^v8dKNQJk1KtO``%FE0=G+CQEh;B5RlfxNHm%L(rByzo zv^Z`df;YATw?&*;ue~pJrl7cFhP%v2fi7|e1~Y?Z^d}Yovlt4>0&Wr2a+8xepR<%O zDxWSXkP3zg$x5s*kYU7JjaT`|Qyx-aG#O`jKGMIcFaZF4N|T^4vk*)W;GS^KNRI+_ zBf$ozrU-IGB#oJ!1<=e8v)+x&#=muCUCq(nnC2+@g4YkDh`h=})2*kdpI&WdL^L2% zFYL-{Z9q(4#Pn;1+Ho8RZZ*O|qxBv>jBE#RDb9yq`eyMipb%_bZKk48Y7ovs)v$tJ zc_>zS!bsGW;rY;EV%C5MgE4Xv0v;vpY?Fa)ed*v-iRt4GEIjgOo?J!l8J02HZQMm2JQ{flFvfTb>#et=(VWu)Bg*HD zZuc&q=Gg=%6T(u~d4-yDrz=oe-3`l61w+TfVt}B4ByG~&acLQXw z*1CF5T@c)d%^~oF&pF}g7sUn8L%}1XtqWG!fcZ$#IE>GZ-weWnACQ zf!RoAc{sq-`{iCx^gUtmeu9}~I4%|Y$b)a#G`$GrkbO(zybBbUy0x-#y=?AG> zNpen~r@N!IHt)~(*UwV|%#6p=cfb7QpD{hh+qE@uaHbY8>V8s=(xsYVa3PICK2>Q1 zEP@n^#{NCRbW)2{XCftZktZ*;`KyEm(?B!xDR7eJgP5YqWsKzAz0-ThNY8~_k1tAw zER;oo$!C0Z*j%GYPDAgvcenTPc7iXj&vTy0npp=WP9mv5^7ix;C3sUFoxNf=Dk5wP zdSHNp2|EJ5R39H+jW=&Bc?*)-dA@%7{6`M3HJ2Z~JH*a0M{Bp6-QK_d1xyqj?iz^rJr0L3PRR`JXx0Fem(CJ^ zsHlWR`jnBtoMX)bZ)PBS?=c&$S+~|E!r+!XtP@|!3Ku6<1wo+KoVubhXTHFL7oxj= zL=9kvl?#Fd&6*@@mX|C^l51qpe5GO+-uT+yVLAUo3mDC;*Q0eH*=PhYhuF>V$kr3&iWsD0IEo-y6rY~Q*I*T5Bl_uQy%5TI18mzEF|(mka-7nG^(hWoAu*( zvV({UaznG00vH`!$%TPHShs_>a8$UwwMG_rO$!)jxbR^8r9!j`k=9_SjiPd}gOF#F zRRbG4!EA_48CUsUet^U6upfWGCGzU;2*b71-;uxqr3vNde?H3X; z#R09DCnTCC*oX;1Ee5#|#561vy_(}@p=K&9X50P5r4%6Vi#Uz@_PwoH*3(tbQ9z*hQ;1n1 z%cS8&pael@1T3;;bAhNVDhy>AAB~*(N>t}3$M(F9*s^IEgd_GDM^5f>c`y>dDJ1CS z^;6tKsuYmT$IF*5Z8M$5W^LCJtHi)^V4g_nH1Znd)no=>IePOMO$yS??bNuYh?SGS zBx7Eb>=J(|yzo`jF|z`pyL2( z5mN*W>RAC|z+uBP`7RT&E(q4lR$CR(XxmVP(F4FF_C2q&ws&nVv<5HqqZF*56h@=M zZCuVQlK)#ZmXW_)am#eLz?=;F=jol37%tm-#U9JyRx4$yxFEn8;jH!#+cx}2&ngGq z-7Nc(LCpEDe$bvA9jo z&HVZ4cK@=|C>+2Bn86Fqu()S(T6L5!Y8M)4IaPWGj-qfnD5z zsfR0gofk5N1oQ27lZAZTXC~rRD>}%s`K63T)11}f?C~ic7WEd9uiyHa@;~JD%~~-5 zkWooNs%w*k%mm0GDpN?PG{krW=Kc8i`HOow7Jc*E_S~s(iwxKfsNBgYOof$lkRLQM zPz4>r0EeZsDMi+LLRRPSOqa``9DR&bZ-$c9op^`qDW9Y%G*y?tRTivYegufq001BW zNklovzb}D3=Et&tHAR=3==Hm4D3}cUx~X*H8-58EF3gmYwXyo$$>c4 z7xj#d@rsj3YEHyN$jnKniH7t5PzOln0dJnu#gg6st>Xd=Wgv+QpHOmoi+dCMn{Oi-65 zx^Y}Sc(+A4Wj{g8IRPAV@;IC(AQGLXL6QzLw9&Z&QSEm@X$?idJ29DEhTuwTfq_8G zwWrl4ti@Gd^v!k&TyFZ62=%~2y!@>NJyJ5!GEFXygEUNd)zd^3XaJc+lA(H$Ko~2EfMt8tscEVj!c;9Kt}n0v zryE4|Hy@vR$;E|i)~Pi`R-CgWR6bY6@-qv{jUo|okZ@QWb{w(U2FAhp9NY7&-N&?> zy{?-&)~8%VZCBZZ=jlDNasxQkx0l^ZGh=l0s%_84b=jDv5P?!S zk^l_ma2vNFI7UvZC95<0bcXdtB1A}#)!B(V8Eb-kcn7Ui4x_nsy@Q!{ZkRW39K)10-+j}tu?i?Xq`klHQ9l6 ztYa?Rc7i-0+i7K`{w3G_RPjv~mjiCfP%lb&1K3N&HE64GxdoVMmZ4i(*)-@_8Wl2u zG82z}s8D;Jx(0WNyA@$=ZlTT@AO%ZK9wSJL_MYVgTSHh(Mb`CL7^lJ{V}yVR0+A|M z<6yYeY4vWgcHpFUbZQG$OV|cprvvq(;MC6CqPVW-xo-bS9jT+y>Dx`v8X(LfqUMFl zz=$Py$~BF0a4Dycr-c-XWmeH-CJUi5rsvFWM5YIozd@*q;x$%rFVaQ|@U**Xl4cG6 zw8|K%1~nab&EmvhfHF5hiYx(xWEl@-_fc4kiPH?cP$hs4fn9~?`c@Qwb%3+*1}|tS z*~KdRt`EDjJFYOX|9hGy^@;vj<&+X19hGchv^-NMJv_#dFW4uaC%w(9V^M0r<}_Kv zln7ZsGI?0l;wMpA<>WgY)`b|^>O9+sBTL&-)< z-{Cc=n1CpYd*FyAx}rC|{2n-gs7^(85t`SNLo3vWRTi(Pjf&I0mkBWy2V>41$~gl$ zwQjSg=lzgypM%?e`*uDX=Wl*`jZd$VDm}zjl$NCsR}^JChkOyOJ|fww_@w$VWDDpA&Q9a7JL-nkbPD!Ux2O zIvj8b@LtSSIh|={{Q@gkYe2P}VhzJBTZS}`!JRXFJ2adgqGoRvh)ljQR}F73Cth!T zleZR1vP%evXv>zXIz%WuiKop@ak1gI~av_2y+lqf+9> zvaS+swgAdxIYVWWdZ(NitujrJ&YZ?v?M5iyOwhgL;CbJEyW?D^s=T0{euR`Y$DFfD>(wZ%BpK&CZrc{O&5SMr+GD3c6Nu0} zjw6{m+uhl4Gt+8Bd#-9hzb8 zjIbMRfWwvG@pJ{CmiQO0}eGcUzV@1QO%Av6x zfG$TaXUvtN3+NSGTpP3W_;T)oBJanMwQ(@sp2mOlAO3raVdlsD!k3r7x&Qr-ug~uS z`~CB<_-9Wao;(M}faqogT#}i60@poZv%$rWay`G&BW1O`4C~E3pK-berWr$&%0>C zuIvoHRPpIYtD~q47j}Ct6jW|hrt5KW9TzV%RTri)O%IsKpFYpy$GA^3gMT#JWir4J zbIzImundWp;ka@D66e*uau=frxv^nyf6~JG9*H#rx?U?VmqfqN#RG{wp7h(l`UKUg z_j0D~`a6+fmc0bw?ONiwm1j7wvqd^?&E*a$&S`mhCi>*R8Ow_Oen(DPcgB$e&QYDQ zYhviqN9|zjHKrI*I_`2*ZAW3l9q(@*ax-nqTRe#fDU1vx zxQP?)oRazE{65gr%XeWFTwW>)T-$Yi=JXO&t^muAli(uE+_zgt43OC#T>I|^V?^{U zt@!EV_oN$#`55N&J|)hWQUtIc`usXyUOwKoo15Lns0}pFb}lT(dB$C6?un@@eZV-w zNOS5y7n@f(bTtJfG^L4|)kr#rurpD%k#h!-f!l0nKWEG}63MvE_DZ=FVn~m+W(swx zeHL8>-Dkr(rgcejIcP8MJW^_#6sM3tcJ{N2=2_npt{-hFb7htmPD}7KI%a2(F^>7^ z^GDPOwk{s6oS7Kg?Pov#r5IViIFI?$=if(-hQyrv%bYb>1QcQ0X0bu(+ek61_7G!i z8$ET6H)JUU(!G+d{+|Uqu79VtKRcbS4_&_2&VrTgq5UIjJMEez=^_2-EYo@18Va(*_albZe#v%)va`~UfQyTsP6RkAmAbE%xp zqQ0!ID`6%B^h0~A)5P@PyHX_aUYP^D7Sf1d?AHa0$(vmeNd+-V!f9eU_#}96>avlvefHMwhVe`XJ1Wy$&1Qwcug{R z?DO}3`0b3K6a$nYWZ8*Wy#eVyz)4Jn3wiO&6s8i$h}dA`!_(8BeY;`08AjX=i(iKm zaYWdCeyj2CznjxN25i&+JgEt8XJQ!a5J3w$|=N|&*cz*YR!=;QWVaELF)Aw=6Ins$#PQin+lOqxjR zmFoJ{cZ&7?T7$uwQ4<}r$r!6Pb%jU^^5j3=c(KT!-y$n`Xk?|^QplMu=Smo*_+T_e zFoT%Vny{0Q!ioT^%pB-gxmamH$!-W5Z5VQ34FPG+FqurPWed5nvrxXKdnCdr^FYc9 zPKo9H1_)Y)ZK~ELy+G!sINIZf)|0VJ)dW@*#lGD8ipUnCOZ1a)J?+Yb6`FG!BM|r4 z=iu#Ux7&!xeY=f$Xfqp!ho-_Nz@?UUuJHllQ~SVsegQ$M)p!4Das7=|uTcY%vAT8?Bun-YljS^W{~ES4bgr zkXop@rx8XtgT|0&i7w_0jJU{pn`iyPazda?y=0v3 zj{;J$nlMeX>2Tuyq~FG?j_nWe3V}Bda}vXEaNBVVx2fr%vc#Z_{bmPBUDVK73WY+m zB}cowo2(R}$Y$H8s4n4l8lrEh?JE>>eY5bw6_qt^eDl2p7Y!awuaT3Rh@3r=o!(a4 z?*+0_bKBWaC-F4W-GkL9EVYFMV8)@GYNK0vW*TT)%P_dF%VYsH!2yx%@m@+tve#2_;YXsLkyYOu*kre;M|N(%IHLO#fzvC z5Ww$8yzT+VF<&tRcVn<}Dzc@Zrh=0hs?N5^IH8?@E(R-fT83)6lN)T*pfcGb2@smBWsGn|er=E;}g^07eO3wMkR%g$BOM;Zk2>S$s)8iA7hz)FY)^(`D~8 zR$OM$Yd!S>CtCY(ad=*qyF~6=Fm<&I!N|suxqX$EvZ4gCEHszQOqs8gxw+NIXPH-d z8fNW8e87Bld?ZZ*f@{iUM0S@c&0Nl^6^=lw_ETo$0o1(~gs*8+Y*fqv>Vcvudim6gW!(VZfD0Sdz-MqUIEUs!Q z&x!5Esy8aDsXtKU#AOgPt$7%L4StXjvPgFa7;>0z4iDYUIEe9dyX{}5yK%$qMrBq_ z#tphBjJiW`yPmqjs1~BjQC2H}we0o)^^vWUgd}TzDe|xE30@jO@j@jTCd#8-KBzh4 zm;gi@&Upk0QlU8j1fPRGZTMD*Fnq0pXT`sr1d;hgy}L!RQTGm1TY)H$ho#oz3_d9n z9!yZ?!g;=7@NC6s+jcW8ZX^}iq|w|$(~M?zV$fXLYNdek)K?%Jy^H8PpGsu093H`j z04*4c@-EW;K@hGqf@?6LM2THQ&Pj+D0do=IMVP`FYRjW%C!ti>pQW@?^hQRbECsXlK@bMrPC-S*;EHl)Iiue~@t5jL&)G{Z553S%l%5T=lO!fb4oC=|` z>s24EexdA4&L#XheWLEtCE_VJD{9+l=km|VZ%fOc(SZ}~G^DDA1FEc-{#?0;IZt6! z`ydDmniq1(9HjiF`C|C&+>?VvLbB}5Ej0M({F3WtvhG`V&tXUrJe%C$Z4j(+NGXN& zAu`Xnjy#R{Y}{8uAuKbM7-NjcrdtZ7lSeHGdt>`Au2rJ8=@NQ5Pv~+AXk4P=Cy69O zpt;*{xE#W9yFJm&pEh$hnVbyL4a1Dwe1N3;_HKilnZvAS9yM~l3f8PHUE)}mUB05W zrU+$9!2)i*qZvbC6GY@t@rHOMmz14cd5ZfJUOX_$qk&ACaZZBnZX8C(l+#@@dhCY< zeV77p#tzz;v4bAt9V{lkWPSrm6Y+Fx5i1p=9{N(6rppSO1W$j}DKARhg6#*dECw2a zJ~pR0aX`m0&0~Ue3(7a+^e|UA?{Ry6KVdnKnM4nNxo!qawG`X3hpn7CvbeT5=#6QxNQ{aJbjcEu|&DnpSi zyIT5IjY6CR(k6xhG+IcLn9iP-WjUg+i>edlcg_u&;6>&%?38ZrU{67p4}oEuviaU| zn0Z*GRK^5hnm~Zwan9b#_NQtcM(tg3bCkVN?p+b-Iml=mfd?VbxRvMM>qf~vi$Tg; z3bj^$V9&39t~#ZcNK}Fd6_SIQZeJmVQeuDn(mE3bn(qZ&!Rcl)x{omi%xD91hGt|FH=}GAY|JBjtSkh`i#R)_ z8L#cO9SS@Cfc43ZFF1 z&wB;|BSOcF*O13B+vfpzJZXP9`d-2zx;kM2Ct=hMo(7;+VG!0ru4j?$7XjlKR-4~) zKAmcSdT8D{q`t4tGiy3nT5kC)7R9fjLx?#mo&#`FJNK7YG9om#BW8qjdpBM`z3Q%* znf*BLFZb8az~+VxBSd9*CvV<-zlZ`zG}Ad$KmWV```0g@Ul1eHK(FGvktWDk$a869p2t}( z%1kZ?s5)I%2B1dQq?CBs1nCa?w07& z$M*F6yDwk9!~q*56^z%z%#&=7eV@l1HnO9d5pV=MsKMr=HYw4eL^eh&wSDGrqJp&s zM9fJ<5Cb3)bcZ7=Fm&D3;)50it%2U)k|y4Za?t{=r@yY$ZGJRSdTa7EhLxn5t#)Ot zjGD59riSy9ixoQRKgZafZckwopcyf7KlW^c2|=Nk&!6c-%Gi*X6CYXz$*IW7bZi3H zg)dV!hk|>=>tTm9RfChhyuAMK$&MM*LsPG38b}smu|pR;Wf_*4EMS#=*T(arM6VbZ z{cAH$?eW#Y)F(k96q*4t5GH>-&Wsn=YaOMwfFeY|Z=2b0`exg4%r9SF5c9|ZEe6dv z?lWW1KYseSA9o|S?dEV2n|mnJz;UnniKH7NxZE3DPXM*>qXEc zv$ZX9K_Kg#P+eFu^TKRS!8qr9ec9)`m^-sBM+Y&}-(q&B2lqoVVM=@a^zT0YLGp;< zX0WJc0A?35YD=Jj;Q80dmW_3rVv~v%?&wWRTFdTuqUJclV|Upn`hI)54aseHy@YIT zW;gh@TYSg;vn*_W;{4sncv*_YjC7sgSnWZ+O7vx`X)U&Sg3Oq7Ir%Dui|SX!Xv2io zC`l|sh*g#|S0c!X2ACz6kznh?_PKR60fh&Oy6pC z#O_0AWZdXyVLd1?6KEXJ{?7l8kKg_8Km73Gsb`?kHpfizO#dEG%^obIY|s|={MWz# zZZ{Xe0}=7%{xRk>*o;Z){fBRV^~--UV}j6}vYC~3>HLsbrg5?k8vhm0xrBUK1(J~H zHs^eOd7+sE;#Cmbo}S*34#-dmU1)#g${r{yb)6{BgH10#ne;hbW?(T8SfB5e2LK7lk`*Ga& z??p|-yW5BN@4jI-X*CZT#c1!vQpe18xBhC!-+lCB$1(Zj#|-``PHiCWH~S5Ad(j@6 zyz50j2Iy*^Mn`Sb=Gij6mKZ)`eA%F^0r*mSC>>~BVUUVj3LK?HO9U_u0CDu&Ss zPGqG|w%NHjjOzdsfM$4JVLRP^`OTlYZGdPNckTPH_xny{S@it!@^XLOGYawh-~B$< znts=(r|qBq=|BDO{==NRIbZhs)Lof^k|zrzb7T;NmH|sGpZ}J>q`OKy$T=1ykQz>K zxr)|RE?%{ExYWy)u6UA`>d)&>#zx5uODhRA$9I(jHa)RRBB5=BVoCO6oz^+AI_l@@ z3%c zB`au=q^B2k+RP zw_Ov$cHD>&u`_6yq-rHrbHd=M+xwVH0bQS{x3d09`HpK(vj%oTC~B`ySd(HWyM8g0 z?bqwTR~u8DM^+*_A3n8QC@hwtj6fL2%`F>ayJhJnO*RmMn;qGo>&c#;=KI^uaZGok z7~XEk689Hi(>GWdn-2%Iz+3(i4_|3YOJv!s=-lrF2cF+;dLHvhb3_gg_;dtfI(AdBs zGgL!-QgqtPN!>l7GR#W0s52QB#4ORIM=VM}ry)`LLB;pNN)j{}V8e!NIigdWo=W5z zy}z7YQP^U*{&gMU>A35o?~h-gOnKiL6JK1K9CE^|9s&fS94HZU1z8VH zFnTY7;4tg9N-&z+nC`djY4{d%jxibzTzyUHa5p>XU+ACZGTvEV++ zm)Va)LS~fPFgjq;loBUvwIR{Pa%~?-8xN}06HQya0Vh;j>Ix_U0Cep_QDUCwl9dX< zxd2ORlk5SvRBbBn33P9XD+WuVY8BM`z-mvw9CVdThqYQZ0oE|7Ru2uOQlJTI;TPQV za3*=`)$}4u?ZaW_-Z2r@_)~!yawuoNOH$9BsXV3BRa}6kbbo4a7LK{>)=31sJ`+Km z$9krLY6f|u9f%#IxmOuwgux+z17XxKIwB}@4VO6x4ssAG$Wn$Xi`$n8yB2kB(-i@A z0$^K0>wpSlUq1*E)z&*PWNO+HA(ca>Qnlsm(BtiLF$)xBznS_#%(ha<8p4xRf&yk_ zvsy7oQf~I-4vU>&rb#x7T;@A0?V!hpe*mj%RXXM7+Oqc8r;0<(grw1E<7PMKa5=&u z-@u>i*%*Oi1m+P(#PC~ipJE&{rBfo*7EOITr$fHfDNfl%Gzuz5_ql1USAiA!%WK%x z`Z`lFgi2P|vPD{&F31XX#*hg2ZM(hWz8my@`|y7I{j|CHFoDMr44K0L957pDl^w3C zv|g6Ns@wwBjtYQtlj#8TM11occGz|sA~KthnEULqIOcq65IH}*dpBBGR4p(~PQr^~ zB2(i9M1n099wSNw>5Pn?sPKW8R|?2Q39vH5NLFJ%EuB%1UcQ<)LB^uA^LIY5=7K?u zQ!*0whEm(3d?n_!u>K|l*0^wkPNzqIiCB2LJu4Ue2s6ekE@sc|4rPZW)a0p}yavK- zSVXjP3n|k5lWmF$ehMUVpkWk1-AK3(pVPyKZaEx24r7=mJ&bg8-=7QsD9IEp@vd8J zrP9ldvAXYFvXOK-gcAqGa%QZKpzStZs+^P*RgzUrDVB&_7@FlOIQBzEcXw*KXO%c} zYy%|Au|}$PlS*KhUh$N2*;m#8H{Z6X7;Vf@%zTg%&Zd-cwe}wO`bA)y!Ob z(z1iq7>Gbll|iAS-Zr-1s0p@qXlRK`UEey1GyUEIW>mP%B&(xL(p|2&#_FoGCIO1w zTtkgu&f6rVt^$thjZZFHE6c+Yn}A3m`$N_X(fI+&xJ?(&F`^6UGGo7CIZ5PQu2AUo4oR8LU{#umb0?y&nc0ObbY|h0bqC61yYe@H zAt20np&eVAx|bZN{sSj&JNIbmAJz6|%k130D2%zzjXb4Ht-noRl+FVTE>5)jsL?pi zfBRZ!T2HTMNVFPphCpSYk%8F<(5bM+r3#M<0WIgqNrzY=I4=CvaqmV9%UKwgJwfV~ zuK+c13Aln{*1TAlavm8dZn*tw`}tpf`=@t&{y2Yp(Wm=uPATRDq1YAkVo$ObYaO~m z>DBHm(Xo~VgmA`9RPsPVmkuo=t@S_X)r(D-=UO7>YvoL}c<9@N!pvwsoEyi}xb1#y zw`U$9o0@W4{b(xgAO+Q>gT;J{jn>l`1zK*Tn>lQQ+kL{|upw!fhtic%KH5xp5J9=< z>Ku!7ZKXe=5`K%ktEqJ-MST1%FZxI-CS$wLqLuxiz2EE+ku~ zW$|9yQM}adeXYPRe`t|{u5T5>YO?Ob&;K;|XNDHa;nA$!4^y&pE#nMgpYFq^(pq^2 zCQR)>OoLWaB9Vj+gVDG2f520Pm{;i`d$cI&WoSv}h8Zz)j&g)TQ<&5N?UNzIoQ0iF zwOZS|o?zK4>#0r!cu_@Zv(*Wa$QB2sciIGKa^=YcD~6O&Co#=DmHKLPyu^`!#FZf< zD+C4%S$jNu%|H%YFF1L+ zYg-S~%(MGhHvD%lH(mD;a$%mn)IvGgd^^569DlGW;>Uzhrh7fY0qBZT*>izfBkQ5x-P_otp6Yh zOq>;k^bD$G%u;3+*7@PQ9L74#i=3+El&{EB(w6?ADzPlg%t8}{EN0F=OK|G}JAhGU z+CnFbii&I2o9A<1{*4nloZl|`sxMxBEuu^@<(soIoj{|^ogNZ>et5Ty*uK0N1UbzN z6E@|e<}xiOD3-p=g}$ZedZq`#^JcMEe{a**O2~SIpRGW2`F?E>wLYq%1CfeqRf4p3 zt#Ss2J8?Kb=ivr-ofWdBNtSRdM^@$}^bBKlNN5QhGrA8OL&My*X$-|N=N>a8A!t@o zT7g+eoeU_<++fT(r^c8w%2|^q$b`-*%DPnodR33$?9`qY%6(v(%L%2*W6H!6`t-Li zGJ}rmg#Dk$+72X#y^+t##E-d+c<)x$_ zUdapKyLazJ+(N@05yw8`INY|FJ8xO%o|WDtm?OQ+NcZ&U(F_sHoGfNG4dInq!-$&h zgBeth$^wYiy=7=LI3vQ0wDIAa4>St}Vf%j1j-NAj7{CAc!}i$)xs9Jb ze-_}rp=~qu!WBW;jQP61CTKM`aGb*a;iy|0rgl}IHEUNAk1ds4AHI0?uh$yr{&B#= zzb9cK=r(Q}0ap@n*YsBiF$|Xyqs}^EQDR#9X9M>1mgRJt4lnEcX#c4d>O!@}*No$S zG`pkv2e4Aujh1s=Kv0ZhzUXrxjWOHC0Nc^X1D+RW4Ow>&aNkXEd0nj9c4$cDX9f zZ^k_l4Hg%#U+T?X7T=_H=?I?_qHwiKNpcQJzA(JoItfE z6U`KnQ~IPSLWrnr%HmHpAS7>emKD>h1Aqpta2K#S~qGG(qvK3$O|1VbLNo>wIJI%@+&gx|EkZt z3GpEk*VfEsC#>5Q(W|T)5{@H?kVV^Xr{Kxc=+LIt=B1+UyR-;HiIr(N-x#5qfk|Ve z=FE;i5UYbjq6e*qtypd2H#F|J9LSY!>iAmkst!w+ zE)**STsz(j^7YU1FrRyVQY2fd@bXnQ$F_cm2u}=qo@RjrDa^CwRLdLUda+YwT*wbs zddORr0<89x%`gJxw*CD5FJ%(6A7A!)|M>F5zVBI=^9~=}He(w3q7&(nV)QU{6DHF2 zqlj!+WyoLb0H#7m(4u!E)sCup)>k{z0%Ea2nwG7qjEt(|UwG-V-vD69UQ+9_r*1;I zmHTeXLu4%XIs4*Bm)ACKwrzcjC{@tzUK_*b27+@UB(vN0?88Gdf_vPhAU9&fjNkp? zw>dqP95eQaNQ9THpH-1llc0p-*zfzR!-E`ra$C-tqVqRre(qsyAIVAv)#Ve9AHC`o z0T?YLi)S7`qVtPsrrF7GDM3};5letdXpE|%)Ys0!AFQ&6HQk2A2O z$?{4*o&ZbR+JidJ|16P_b9c#z1F|`fC+)Nmq(qWYgK5mB&HtG&r&7o?gwOEFDgQU8@IR<~OZf2ymzz0Sk9-$RrQPjElk19OfKQMax^b?JpfSpBf#DN9(49Q`VTlmt<^$ zYiei&fQB`XUbeT4lW#@M1XcH%sj~5070{To>$lp{KMA#dx78{5)M-n!ps|&Bxoif1 z(%dl=?ykd2o-r9^SJ#0MnK>ws-6+Xy5H$BTVOo_6ou{*i6Bp)PO+n7>Tx_qk`a;>I z(k_=jAO94AUvF_r|2CQ1t6 zR%SC;`%}&zl-D}PvoCjQ5kuK$mkPurtQIWw*neCmpH|D#ll@w2Tz!Rrh?7s(#x4+3 z;?&x1jIWVxuZ@q_yr`J#LfLnC(8c}VvLcF#Qc(1K1f|SK$y13tsHC37+Id0^ejWtt zBD>3NBfAD9G--KJwbxUaVwl@7GnhpbEjZ2Trn6R|5wIt3<#12s$fZ2-QpKR?9ILDN zMY0snr|!^t!pCitpfv$W%fq)GijUVUp?y+JOW)IZxcDhA8I{i~DFe23xU`1UNibqV zBrR13WWT+>RRtV!+pV1okr|K#eWPV7RjcfuJpQcA6A@t4{UQ+2gVnnMB)O37x+yP@ zU3<_9*vd4oB&RC^Sqksm^3lKi5rMX@EHhapUbYE*>K>iv(VFmbR=Nm7BN8NK3aVXf z#GbH7SVaV{-f<~XmCAscQW9yPwlu90!KC@qH2=N;C3Kt zZWkg{c|S{Nms`2w6N#VK(oUL6KbyJ+Dqqg30-BwNnhzNu9cDVpSj>0=tn%whigvw8 zO@S<54@ihPlc)(X9=txeHj;Sgyw?IdZQ*v>a~^^=--f&U7`LG#Fo%hxPaQ0=Xly%>v`qK!sP$4~kM#9+1?bwUEAv^A|=#FNZ9o{Z1$#*@Q0-=2IRFcBDr>DmJ=PDo`za`)st1CH1A zH3=6|s)J}nwBB9rpELATSBk#MN{he>nzi;j)$KyA>kbR|F?WkK+9t|~4AWu9p($eM zxIf>XF>bL>z-$Zwv1`OsfRW&|@LBKSMXPqSC^-iRL^PgDv?wWRxtW)v%laGZ^#(|a z%y3?#!cTeHC0|IHdl5nB<%+pZ{H|-3Nb7Vkz0c!ijH_yDTxDJ31_vq^j7Zwl-n831WP>7DmnlGEO z8FA!j@Zp;cUw1bSxAgJMktrADrKos&xq_{VWS6%lH$^M%$8$A+`dPb7DVe5=w3v>J z(wxy2W5bs!ITl-n*H$iZcRlsqBW2EPpIMFpk(CoLc`Z?h6^LkuK)zL6ng3n%TQ^Se zFlXheg#t#x6y@oUnCXqm-hKv|Z=k>$ZviP7!D((xB*m5fmJfH)UA<}PSmz=QGMjl` z32c#tTELt+9Kh&HJ!))q^r<%yA~ExTu>gD@ZQtr^*DG4eRnS^lsg;g}kWi^)S5WyJ*s*uIMY8@-ldYVl6tMh@lf?+y~vojbDR=-@1@qByt?)ja&5zdL60fflh zXHyR(4vE>2I{SDng|*VKimAJ2LaD5)>#Lwadq1Vp7!CG#O2~3DD1%@A(f7Z-|K{bz zHhUho8|J(3kJs(Mt{1c8)Bf_^$GC5LaZM=F!k{Uq46bGc#T-3GsSdKW-j&~hoF24f zOO1g4vp@bq0%Q zve>P~bsERjbxcwPwHH>%hp)K37QHP!zY6`q)l>CC0Er}8xt{9w{JY!&?K-kbEa5SC zWPfuv&w)0jUMm^+a>cf9Psx!bk^Pxwt|r_DZah8Aj4&Gxzq+v+ZI#!|GxQ@cYjUg4 zNyqZy+BE{J70~sibJ6AO5NR{QhL78zf$rPQsWI<(efbnY*n}w#1@!sz53l!6-@gC$ z{qwJgNoSU*!YD&T05&-%rc6^alDc!mgam6myVlZ%o)H;gx<2v3B@KwmSJx4YBKz_v zFUK;<(nR}{&Vy=`(X4waooAHqNHP0p%5S--@!}W|n!Oq%FWkkn^9u0PH{Hpp^y*mM zX8~^JYjBy4(kW@PZ83s3KZa?DvfIco*~MMBmQNISN^M`J^Y;xANUM#_nLDzN-f%gvJ zpM=@B$K_CpfcQp(mq5Sl$zu23y)aq`qMo+x`RT)i`;t43MBEi{L8py=RMl@Icy%NpiCiDp}i)iH*x7z7|jL1FWv+=L~ z?jQd4`%iXrjU9@=_|t##pZ!<=!JMx*zv;mDKfZi=ef=T{d*BF2W>`F@MfSpSgI&;R z?wxc2odw_uvb7ly$8pTrv-YBEDQZ>;Z^JC(3&l9BV?NypLVB0Z1f&xoCm~zTk`r_6 zLqI;~zxa>;@-Lp>`yPMpr`P&I2|QS=HV75r2Il`DHaoM-9{h}9jZ+&GJW%bApp^M2eG&ucRt1yO4! zUO#d9J)?H;Ul{ zFj)_-MkXnSchKaFxb(U6jAu3Gy)Lorm+J;B|05(~_%ItXCx#hl=5)%A`~5e+`E?w} zaop$e`lOqE%SwTznRRG}77-Iunh|qSoWVnwL1i89gsu;H-4HHOr!uU2iIx76qWf}m zB6Jqfp{>5Y6uW4Q=k<#%fiB2nmDJDRR7eUl##|jcJ3Y5aaFJD!rwX*SWtL}M4vT_N z{ZGXWp_$FuyZ;=G4%abX=j(Uh|9!@Rm0c#`z|10^IP?qu)#gu&cT|Q%XRV=berE9$ zpK5LQWm9Xd4<{iI7+6$trIkf$EYSL(w9jLS_Rlv5TqR{wW|i$;&t@H7WSSv5ikYpb zvY@5lU1dGz(dW|;U-Dyp2!m$q62#5iWmV|nJJ zatDPX;d6?dw+6&=z^sT)EzlH`gp0?%ld>nDuW@kaW+p~tO86img^DK{2}}^?3W0~J zElKGVr1PPW*pe_;hHR2s%%<}d;N7Ts&lfU@I{mVxp zbol=A`F@{!OtE}a<&j{Wdq1cJ}AF#D56o3+6|T)y?ElPcG=>; z-OLxvvrLrwW_I#UUmi&}PDkL_@9*CEw;$xwh2fL0#P4-@kP#O8^Xb;4Qsu0+o)|zi z+NR1kl&S4z$R>&`m+NC}lO5T4&?GvWMbfgpVd;*|5RHmtj8qWS zQE4r#Jjq1*Nm61LV8{{Eg=X7{{V2ck_#sr6J?nX2mAX=Dwguc0kVHOVyYSo3S1pw~ zI+hJs9P-XA6Tp~}13e%{_96)!)lVUhsTf=r8zT88D^JNzR<~68I1T)ybG4_v2UP)p zJ7`8>^P9^KMrHzsBv1Oa4%7x+G)&JJgh?JoY^+crW+qpan!oU8tG4TcPNJ-tv=XYv zUoXqN?b}lwiXXQs>?6M46q-NY^>HloHhKHPnB@t5KWNelxf-8(twPO`(m*757 z6O*Tb2*m3ivLjpZJUM7F=k5LT;D|Xl1vCN8<#JEtTE%Z7l`Vn=ME!1S6O5RWwb!0+ zz=@P?22uQ-as6Vt#eF4F(+gYC!(|H;c3IZI!%qsFir_xL)7G7!#O{NcdQ1k+ta1sO z0f^8xKxS0CY_|q0?cJ(ACb>JMg>ztJL&>O9P5=NP07*naR9)!nuoS=?iA{p>Al;Mt z>7X6tF6_bV=$knsRWV%d$M&!lBDk``3DeQAXvynB=%or1K&J_kJdGJMU4QPLT__8A zg_*f4d(wq?M7h_^;KHGvvoxuxee;`b1Aaa>usk^IQzmoHNo(iy0jdjhGqs@IpKAN2 z2EE04vTV4Z)vxrVi`=XZ=%f;fKFFd@Yhk-g3!*<#q|*0E=)5o`CtNL4LSs1dPJLN4c-R-loWe*rXh;tA>^ z!psHCm=%YN5IQk75oj3>N$&!)(G`$knW6?Q8Pj2DosrMp;gb~lIkmp0$HlI1Wb3Fi zqSo7rH2bncc{PlQ&=E&^MVk;YK%E>2u2!1G+dm2=iQ0(B+= zNpo{|3NNqs{r!E;W4Hl+-w&D%Jb?)Qzl6QZvL#!x9puA(##(!4o;;7L(!D|t1k}~T z3(R$^SI&iH_ z9<09ivW&{olN8SIJ@oLP*i7%kwqwqHe-#ho$P`>`Ik$wY4sV5}Qkm$v5p`RAwK#--1M0T}UsSS$?61vb>`+8~+Iq?CcK64%I6oX8aC`Us@L}8|8JUn5t zVIWL!$W2JI&2*RtU@8dNcwpbD;YT*J?xLeY4mFt~Cj_VNhLCZvy<04SS_e@CJs~GO z%BHzk0mHSJd?V-=(<3<*q8N`Q5$D3RDeWkGpQyLt6X|Q@Q?cqaFJ~gEDm`6y7a6P! zLX=lk@>POR4DrRB@M;{tkd`-sv&{5bCQ1%zN!}iY_wSEwJpJrvciSG4JyVH6c@tj! zLfI}OQ<~xJXM)m+u@$mOxA&AINQo^O(_@rAOmnqmigPBvh0bYCN7(TQ`z()XlcuCk z;{(Tb(}Uu6;q!_Tu}THWt;IELw=@m)BH+EGU;)PZ)5;NB2A$^$yjl1bty8f#mytc> zV4b*sS+xAy3nzkJoVI?&>@1?HuiPhhO$34%LtH&4%QIVSgoILJHqS^%^EspklVi)4 z08TQiYaz^f?`od{?KW2ROi|Y=YrP7i8bnD7|25}hB|)FBx9fLN0bHiO4sl}xC$nE* zor1VtB`FZC)e<{q?E9Xe1Hc*;0caN2WfnKi<5b*V`I7~LSx=;_tPT$$c(!+u^NXdR zL?qL#h?bwmwd*V-lt@A-bN<&7zFn5QXitD^d0neta+Ip4r9Mx%;LY`L0;yzo%ru!= z+e`pe6NahjxP9~8&$g#`e$0o@_aDB3iAeXLESHFBbClWXDt)wS&m&Ya#IovF0=~xs zszMmFv_RCc4KgA`bNpTCwnYT#3jb04SFyi7KHoONj}5$!r;iXf7nrE%W_YiNmHQE0pVqYa%1yzT^R5EXU31goKq-?EdRQ|WW5Ls?ag2RYlH_cGd#XmDbpk}Hg zYlAa4GeNMXyZ9zq6PF`=dCp7jE3Q9hg_gx&0XK*dL>OG)w;^T_Q#v&c5vMq8lOf{N zyYM|7uOf3~I7_wC*C7>!Pp3hxdK@S?AUE+Js)ZIKWF^^&h-4{ilm98oTp5fPHv@<| zbgd_H-TEA9ro`2P8c2srrChUp^9M}{n*vxota=0xZV)< z@*Dpg4-up7`#ZNkdLEA*6LB+I+DTrWs}uOiPi};ny|GXYq;9_L9lL{apT!el%h~I; z-`-F!pFG)vG<+%wC8^LrH|e?@xrXvspL@O0^&nUumA3}!P!$6uBq9jFF&{G+QSNuZ z)P!Ox+T@feMD#IV-6K=Bjfleugi;jQlad}eNya0F5~kfzx>a-23e}@a7XGVaD3|rg zuST1neu~TDLZpYSX0<~IaUEC48n`X)OzK!g>9NdN5*wOruY?eF_x;!rRT~{$Unk-r zJ>lr=c(&xGBG=5EK|oZtZM)rXc@90obU>x2UKHRufmlman#>+fm%KExMX#jEtS}yf z1ieJCMDz3+q}{A8-$Z%9S{UaPse*Oa2!Bd0S~>N>1thAsENDZAZCiv30gi8e_80!$ z|KLv?BE)0v@7{l~p;bR?+2PIvvuyPl{;H0ji4#dC_ZIXSoQ!SUOm2mjyOVPUyKA0B z;&kW?7g81f`1@b~`6oRdpYFro-?nexZC^25H@O=OpxmEtAO6y}TO39)vt##T({01J z-_)!MByieuxi~ZD3t#+~6=q!rvfrvhH@$7Qo0J7WkjbH@dLA6*@uABs&Xw1>@2~N> zu3M7dfzJMj)d;mt8Dt)Ff*$(aFTVNr|H`*BK8`J3Ui2UTqZhzK_}JZT|2zNbpFBU0 z@K7DU`}ODl`G5RBA0M|Zg!cNk|LV_w`O81X@i3J!OuQzxvS2(~b**UTQhiqkZ7o}X z5++cZ4?Zxzm(6dshcLqZn1}n!scfYvQWj#SL`0-z^8%0=G_F&Fw_AjjE{V2vZFY)d zB_vi)g0?QOp+hAT9ou8dTp6;{0Z;m;HF7y5AvGhWtX5vUnLH6e;Xjfw-@n^#x_x*z zFJ&6+(9QJ!DM>lEKd_+Rha}!N`7p1$8T9BNNwfT zGv~kgEzSbjrEF2b&7{zyB{P>~J=#?(Jbi2q>BiR90rL^0rY3e^rD2MJvz3xbD zjO~VE`iij@DU#M>9)6%o2z(n)&>=EIs4}D+^);wm8r;1_V(ZMFE=;kNnL-j2@wh>M z^ZC<%_22(@;i2R9{Ovb#+aPA4w%x0*dLznZ^n|BvTWcaB>bm-~aIIpg%pC9rN=C<1gNA&zj!kZI0J}8pokRciA8B4*SJspU8(` zj4+)26i!~JO&f9A6ZCJ|Nv>H&g^QBvuOgRvR^(zfSBcDf5YI_(HAP8J_D5% z1zDS2bP;&w0I^n1&P^c}56a@}Pz|^rBLx%(dD1*`LR}-0+HAOosm&5nvtM`K0PP9gF zu+?0v!u+#R$`moZ5KooUz{;{w)P9tBSMtYsw;@u~E^G|lY{oR1-#qE-VT8PbrhN6t zbUlef9uM0zj>pt#Cie7%S5<7G#{1xX=k|aF)w4qe1QMOekT+HCzqFcUN%^^at%E3{ z5eo5nfb(YCVICnNG3VqI9Ri7P(#u9j7QP=*q(h|7Q&F#Sxv%Q`vhwR-u+}gaw(L%= zaYAST5#egN+*~_-BA{iKRzR<%M5-A@-@x)x^BY)ysAuY|&)tv5&G=5@S#;aBLCU0v zz-S7=44D*FO2ia7C=cE|wq4UnfRfz`(pqPvtEs{fAtFX-Bnct{RrRW`L@I>dv&8_s z(PL$~TS$vM=b}Q}LN}wyN;NA-@I-?oo)Hx;wEnRpzO zeb{!(w8_hHY{j<1f9wBCa->hu3CTiaAQ$so*@j6esfz3Y4XD{;|2QAV++Sbs_SM*q zA@Z&H#zXw@!{^+ej>jQ7i~ybx+u?VIh-ghO5Quc|sOr;=HbF!;FYS|cE=^ghtLU7I zT)G|0XkH%t3Ov&ibQPE+APH0-^VE}2%K*ltfMAO^d6$#SnW+|u0q7O*|jC7;| zA_jAHkx$M^WA$LGPcb^+!R9;A!@2nCu1^VO0842+Ggf27!0Jl3#e*|nTnjj zIw9$`HXO+yaIY?!AQ~&IaGIMXs{Mn`xq}Vcw%21dH+#`EN3K>pS1_MFU0kv?dny3WlzVqv^ zpKORK#_ef)dI}dpw(X|=P~jHf^^?UV3J=6+&9ts70i-L|z{ea?F4quO9O;hXE#<{i>9zmBcF9+{Y19 z7@Q%<2q6&N!E%*MRD_O8<#+Ucp|!Mh)iYKa0RfjjHH)~&a9G3{w{O^psIW}w6N>2B zHvC-g@=j`9){fv}xE2gudsjDy_R!N>=RknByG zpIdtI%1WH~&z$@mtVxa#flT9M82!83lR<(pFieJ4chP>ty573oa~JY)Pb-7-htd*P z_>OPh3?O^eD@-{Uhd^#RY&?yj0{#4W_>jYtfq=Yn51l(=vrQsgDDV^@;RK?IoQn0< zp5Xj)eLkfZstN^8itdX&7m?Lmf$Qg|*)GY$X$yesHCQ8FgzSb!WtGYmC~Xpw#-BoYpxD%X&k$ zWG2aBBVnVB?GP#Ie&TqU9CCj$r?Ao^ov^C5YfV`9i4r18_h=zaG@!7ca>fBw=VVZa zEm}D_zo4gLW6n4=RYOpme8rUe9X{`4ynp`I#&EcZJ>&V~{QV}`m6~d5fG~^@szP8I z5~Xcxy;t{v6*VlhDUzsuQ34kUu0y%5v(%to)MCDkdw3}0#0FEjD80=uqeu{)XErg%ddg#K}e`-C2-^!tqzR>07_kw)F)lbalZ&y z`6P?40m`+AzK7bxC@fbVLaD+u0-nvYC(aie9UB|{ZprivC0r&N>TtF|r5pp+v-AVD$I$z=`&2|p6w z00L-447DH#s+u6G^;DV}6&lcnj|M+~jjdwCXW9<4|F2W1QrHW90#zXtDQ1}%ngqA|RNKf9=NM+DBCvs`-&+;SQq_%bq-UpdwcAQ< zmH|54Za1DvAt*WF;fj5hSyjyzs%YF^$EWok(TbxD1f^H68(K8g#Og^70qF3fYW-Zp zkJqQ$J9!pWPV#l`pC6x|Z(mVV%6F%wj;u#)<&>tnb!;xz=N~@aCn3hntA>IK8~Z%& zH_aUm4^@p>>lMLmY;pLUhd>AeOemi|9si0S=|7mnkDuiEX)xlpy$AX6_4xVoJ0K7N z4i#~yVH}6UA(4InBdn9t z1Y&;Os4Q(jQmk-4)MQ{2$CKPPM>vj8hdcr^FvBncvJJc4pXEk9ZlWr$aG(2hk9pVU z!^gDS400Y;u69CB33N(-7i6`nz9s=vl3F+&@H|T)61a)J*Dbc&!v>kTz^UI8L=7{j zs%;G2bSQ!_f|{Tyubzj6ZLP{uLXf#^&K z={5|FAI>b_j4^Rd#xB_?&rwAc=~{+RVGw14M^vi;k@`XAm}{+iq&2TN1y?cvdp+BF zqAN6#wvB+Nwn`~#+{Q+5qF3o=#cMix*;cPET>$$O{cs`$Pqh+3>a=vUG?#$B1ms-R zOJpilQ5({V08#2FIyWR${d!ZqjqT~(I6m*sU;X@}+x_YG`FIQ)f6jS0oMB_|5GVn$Y{e-#+A1lP zKvt|2M_Adrxq?mOv6q4;Sj(3d{~f0bvi5dC>~xJzBbW#&2UwroG}(UU5f@G{pWi_A?Y1!~k|?vpMe?hb*31hOuoK3WYnh6G=Z{a1hfn;Q%&ro#`4 zKy~YpbouG2{ZdD#;JE?{&f~~2uY^cYsUda3gW};coc(ac)0T;R6M-F9t02H&=Gap648p_JY_prQsG=OZaoe80 z{`zN*2||I_*Uuk6{Rm2pcN9}>Kxv&&?>^Ce=o@yNM^8k6VYg&BSQ$=YV?5hP3kTI> z?k}&Og-~XCL9PH3ef zSAY38GO%#?vFVKpj0EI4Yym=K&n?z$8Y#CYX~-^Ae!RT?(|`C6T)5rtgpS*NynCmc zQh9KG^Ucq`{`xz@eRomebcom(5LMXRA3y&1`{VUtI-p9#?e=`Xy${_F-#7VFQ>DzI zCh}@A|K8vFPyWgu{{?@Uc6;wUxE~lwio&c?{K!)Z(FU)PHO{?T*yxMbmx6l9M)(2{ ztv@<1)zNL%$Rk#W2E9}5KwLlm1XfXgEPbllcu4&Eb>D72=Xf%E;N5-$_0x25*?9l_ z{Vv-Mk()ior_JUq9xv1|m5+b0&p-ZxLNhAIrkl8zG*$MIG`({Muj_Uo(g|#>IUA;d zkkF0c0uMU`PB7>$rXlJQNgx``pbERohS+<_vy483SKdC49V&V7g!k;5DN!F|(~*Pr zS`?#N2Gz9jPUGMg`+I8qk_HjxpbQmOwjo5SFnqz=_2x#9l<;7HvvTB|GChRGnpPkl zGu$B~kc7xhV9*i%g3_tA7|2g7D@7sb6k96=l9^L3Ql9b!E27Lj`U`o>|4O>g)u~<0 z;9l>fFgTB$bTUNjwCkj*t~}=+)3)Gd2X5cm(DLC!02$j2!xm!BfI<@Sx%}y?r@FfF zzUfmI>`lyJ1I7K6QD4!Kx`7A=SJ`urS}ZL3TrX{zxfR+u3TZd*&r zi&2vFr%L0NroGT#Z(i$AF)8`;uPzW$sROFY*zWhQzW(sFZChY|_{Hs?{`Ob@#eex< zKiy)Caeun+&i!`#@a-?`W^+z=OqcEvo&(NFS+%Kkvf0Q-DwLG>b$ZHpbLS|D=qL$V z{LfI%$$$OiRn$$@W-l|Cd?5PQ5K*X#FvlSSP%TR)LNXC}``1`*WdtLfE=n+DKOTEL z=u$;Q%;*(WHQ+G4Z_hf0nSFe`{`&jhXk@32Y`Vwo=~+}Xk_$R1&WaL&3@CK^{^{ih zkL)K0KySDE7#oY@=!S_E(<@zCqH-ZLKnz?~F5QSTVp!WHWcO*qVm(Srbp=(So&19g zgtv!AR0D*ZV=AW?C6ZqRz1p`#%s7lWc@^sPI$8me31d;z zqYGTbnB{D`ZDt70O>EPf#~~{7$Q48OxpopMg>}gKKqs{YMMy9nuP>rH-2oHmCXtnp z+=(N?_sAmbNlph$6s9UcI{k2;A$mZKD%*CqF+}F3cMTYfG89l6c?fQB&Ts+f0YOCY z5RsuCIi^6rbj*M^8i;Rxd9L&MY!@?gwWMF7oy#>!8(f&WULsi|OVJ*9o3w^wWzqZH znJ9I{KJ@AM-RqA+pA%z*+WW_*w4v&p2jgG=tKYuzb@%zaz2EltAKtxx{!34r={D`F zcS^sH@y-2-+t8Rkbf&(x^4kO7Z-{s)T9Rt2Q^^8 z2;G99niG?-5D)>2tV_=0gjT`I6Sv^Zo1R#IXX8F2z zXo%BDVrl#~zQPJ)8I)=QjA27UEvNc&s51-EVo`kId&V-njIn<ywuv77>L6Ayz#jfRTtcgJPB=1D89Icc4vu5r$5Ft)mf?wlG;JBMQ;LL{Ev540}iu zsjZ=asC<%z@lU-~3sKBlhTby`F#B@Q(|XAYs+A5n{T23UUjj*a>me=Xeud0{sQfR@ z6tK{kbDzHZaC#^qhyLN$pMQYIoCk!&S3mnku`yrky)Buz)&LU%+5 zAwK(NglpLe3GtzWp1@JeEz7+rkrT_a^xf5iE-)(83<6RWIg5gXc*D{__Y*9UM;Y9D zs(^^Ns<*VJuBqUq(64qSmw_vyB}>pm02vobsL^ENCRAY2P|s)~l{kQriOBUg`}%}_R@jGSOkLR5ocV+cGR`!~-|n{G}@m~NQPKnP5z z;W7r>nqIWmd3eh?TVi#B@&EuJ07*naR12NK6)sLzvhnqag&^%-OY6b*Hg(~mXhqSH ziY3RVR$dVPT*yubNts53NHxASlS4RcJiU{+NgQxx;K@uShKp_QAEuvo!xlqbT=$*t z-ao(BXBFYTe|q`tOZa#1e)0PFaUPUipTg8djYOq=x0?r$qT&VayRJw(DpH9XA~_ny z2RsvJQ}|8H%tj7tafm{Vs^Bm+F}0x>Pz`dZsYu3k+Hi1X+LZRJ@j(}R(zISjfaGmZ zCe3v>{*hDuFScu0q_pNJOjX;>$k_ks?4poIh=jldU`F8tLotRu4_C|P&J=+mGDZgF zh76b~7^>XV?_)+x3G4y@8bMO4XeSj#_9+?^2dL1kh9Oj@NzPwM7$P-tdAa*bmf5&R zBpX5oLkS9^`%9IA1fU9#bf9axm-kvjS>;^G#$ma91u++hlZI!>eH%%p?#ZrtJ>>Qh z@64mYjN+IGJqH(1pevVA76`3X5~S{eRVuqK@FB_&emgfs{T5S_Gh1C(Nd&_6kjEG!nwCXsVioDHnHFR5| zv3@Dn-Rfmn_DUM!yxGw_iK*1I0&7fZsWabkjRHA!))Z~=qL;OGWu!0*DJBLp4<|)M zDWRG7o2NM3C_0p?G)Z;{A<#^kDb38x7U{ia%^|52PgR9RmkJ~zFu4ZCCG(AQFfA^N zRFY8C7GxAmK0UFLB%H})1hi8^RVw3HB#%5rbtP01f|^#^Ti9@;3%l}rRf-CoE~+DZ zI>Ieb6}UoVTN4o3O)ak#$)9&}Tl+=Xr@nP=|Lg1y2P~1->ofLZL4axwtd*ev?>`42ASYM$y#-cQ?Ft+rQ;V2)jG^;7sDf-tRKk!iZcDPm2bWz%OB z)zwhx`jAX(-_I3pWAl(>`Z4!-4Hz<=DVnMgmE3@=lMyGVnc}Wy(`o5DifRmr04Wmm z>}Bk7_@?&VAOGds6X#Gc6vCLHF1%X|Ss5#}4A<6nm)CNbYXR%He{tFyXR_3v^k!fF zqJ_A=xLh)M(#RB!-0CJXdj0CnT9TIOXn@)#0*6x>YS4Q!F9sU~qY@f;#HYvSj}MA+ zz8)Ly!^{QKr!t$x6NS8iuHIGqg?mUB9ei0?} z21GQQI87CG&N%qG%a7)tUtWD4v_VCdJIy`xHM0~byJ*PFdIyi1DJwa*VDZ>diZpsT ziE|;we8q9^ak z_S!ND+B0Nuk^zDX{>kO$+HI{r&A28({^XEJ+plcPoiSQ8vDchc>eGIR*6z73IblO6 zHGf%hI3(W42+!y1M_m91E0d{ji*Kd#4K82cjh!q~rdKL|hQWwXRX^tBE{_*H{0~2V zAEFpaj@$FLy&EF%-M;ziuL|COKIUC+X73>%?)rS#Ez;{01GQ?z`W(04bw1Jg-%@K* zPj_(<*HfGb?~9FClE#ZVlQ z@)-(WWy*$(6qD+)QMeXD2|8H8*`&R?+AtgTv)T$UdwKL`_3f@EYHNj%Tf1DT%l_wO z&m`!pSH-3!Gm3j0kNx#EYT`gmPzMB55%`P_9IVYKS6W1_ElW}yDVb^RM2um!ZJZo- zyNzw1hlYfQr59G@6Ufl)T_Ck6MJ7orn~O%QEHXNix$C0THvzuOiQqykUG=_b|MG~M zxEG0YD8xGbT-gX$!`s@t8iSOz6;hy;PJ7km3Xd?ebgWcm&QQ%7JFoqKp1rQ~4udpy zSAixCswMXlY6xk!?c48ucDp@=%j=B$`)3_yo87;vzxFFK%DGeERre`Xi-UtCal3 zC1GMk#{1h-oJ87T=|lY%Yo3C|WKMe)i<)?kW@vh=_-%?8pAY%j38Hn1IgsYQ!J^;@kTepgi5~`?3EI|J&bJ8Jot_ z1Ap`V&;RbX|BlW%rr@Z@@1mRa1U<1C(iMf}G;@hHDh8dEk|1O7*sIMVNkq(-$H(tK zZl7WVL*>(_m;HE50Czx$zb7F2*m+E%?A;lTThEV+mZ?Q-q$5Zglc(A2R#g4Rr5%2{ zjmx$*+LXecr!i>RIAQR4jjo)}c+BzYzx&NAj<_416n~`p7><3?{ULbx49=tzl#b7n zzuh5254ACbfY!vUI#Lj8?17qErr~Bu%GFcVbMiuR@$y)$gVSb!WO~g}ty~+|G!+&R zWKhL2M)6aTFH!GS8VTXGyKF3>L2Kj^4MMB6SUQa=)()z!L34#$q{IwW*IXq_mmNiK zK(E6!HkaxL>o3~RNUgV)>3pz2`@4`el_da^bmgq?;~M*Z{;3x0`Q zW^SE$BnNc~1&lZ#A-=!k@pu2^uN|L$KB(`%`|zi~o&Vr>|MI@wB9xEu`h(7G{MqmS zoD(`8A7AHvYz{oaB|;=Si3G%?J(?OZ(YlCjO0=w7LRf?t*U%=0L)c7I%!5!aK$ z7HEYYFOL`dr;_#rVv5~NUtiwp2{fB*FU`ItwhOxwI4 zb0*+?Y zyIwL+v`SW!^^&B;e1nSmHc(ois$S_u(?HcKUY&&Me|VxuQA05>oUV06#&9o zqs1g=3EsBde)%{4!}s5O9h4(mwK!FCwu;>DcR%K^N>Y|xzWeIKAAR?A9Mc9qzCQlh zzxY%4d4xxBJZ*pRXMgN6C1^6pIZ$0fR5AC*uYUO5fAhco=5_!0iGTR(Kl|=K`&)l| z96x+Ij(Pv;;YUC_!gVfJV(BYj!GhqpY*?P^AaXa0+l-S+Vl|{)nq;+ozA$hnfxAR} zIl)cBYhxu5S%EaBBA9VR_y8#p^O8{C`TXz9B5JOOZp4X$JfC5JN*Hej3D6T$&R#AY}6fg@Bcrk5L$qYDAm+iiTK zhnT220A)asoUEP?n~xBpkO|S)hO5$`T4k#u6lVKhBD=s|=$EBe`_Yf^h+s(0=8k~s zmJgnkaMequtIIgoyIt|CA}eIEK$av9Zh}Q9J>OIq5~G42l-4E7=Rh|jpBil?1H%N3Svv|3)=LMraeH@ckDrBIRDx*;3a-4w|9Vkmur zYp}XNBGA0mGL30a@{dSiFy<5qI{)%lU;pR-(cgJ~Ipk$x+y3|8eEui@(|`N>?|;0# zdy+%``9Jy9AHDp=$M62|^5ctsc>n$9&sj)2LmbK93PcU+XOr}{ZRjL}X7T%XjcIS-wd^=n9LyIw#EB7o(OqjA9(8g(K4FEi2P`r|h|ZyV$eaP`5* z(%B6^IyNblJH;h2jlWZztLq5V)FjIvM9eJeR*Cb8asjpSh=kbzIk7`6urBb5X0}o_ zyNuuvglwBVJcg;7c}xcl*ltg(cK0Dh*u39}kxlOP=`JrXF%*Zm4W~^7ED(MmLL^%t z2$@|O%x&m+XNS-}={&0`PHN@iCcmKA)!Q283Hqhii#M- zAjq0&n#CYo1mZP+A(tuBU6ae9LRT!jZH%_Bu{Hv2rz+SXrAJ!v;-co)+AcMkTeNh} z(iK3%hjsGV^t_04x{69^EUnfXh^#y_S9gVaDP)BK0tuBoZfWW$8Zw}6A^|mFm3da~ z#R4z|tRq2yFf=p=!sUTP);2^by#*MrBD`EILe3n@tn;vxmTVeA8>XtAd&#EV%A$Rt zm1^C{WhSrYuGAO6<3oNw#toF$m)C#s>tFq~_wTnbJbyiH`#k-AyYCoJ!zSqg(;TUWGtg9z z&_4002Z>Bxi_F2g7=fgMzKBO%R=bxKO|hrV>P27A+%V-rr1F#)xh&O15_%t2wpf|5 zRI5k`g|`AyVGuP~OnJn?sSyyEs4XDT;Q?(FqZG01FO@}Vs)0FqOiUYwO&I}!hj%t^ zpHLRx!%kO3Gtmv9OI41w1Fd5ESG_SIqH2nf-Es0FAvDNYURGzWA-tvXUWyylSGf>7 zqG&F7c({Ye(Sh#XBx?apbmq(TM6Oo|Gc8J&R$TXU2{=n(rwr$>Ek=n^tMaCWn?y-? z+e2h7l3MpB7X#F?Tj6R-w%F?x)dGPFghNy_m#Z={ArMsy(PQ6Ja-cfQ$neO1>cR+- z2nlVirK(b`dmEQ!u|z?}TpIz^!zt=9vmq1Jqon2a(Z?~Q2zgSd` zW@GEJx63rAI^k-fnLKNu(I^J#YLJVKmJU|5vRH}=B%ub(WNb+fPP&_^CRt7wmq0kk z>=FZrB8x&ZcTYSX%H2ViS>xv7g+4_XHI9@}w|0D4EToDr*>hBClE|6ax}Gn0sw`J^0Ey`oRa0U1i<6j&|pZO8}+tdr0MYl$&wT-MWG8sX4 z>QKaFgnW7#0zJn2?fH4^&-!fR=HRq=!~^f%`yS9S)ppW`instnt$h;~n{}R`{x@*~ zaY>8{O6Ps!`cz9du4i3m=zXu$qR{%BWS!Xdl1xt%6bXhf2M*_I zt7?!+hOYAXMRY2-IFj^V(qf$v+eJ6AlWNPGzn-p(Ho*CthI(y_mpomSM#7i+#MZHSJNB z+nIjJQZmuqY(#5j5ich^l|wY{u1{{4xBP1)?o5m@>912ZVv5QE$mZnqG0frQL3fqN z(nb*N2y$^j4x&cpc>*SDS$#Ly1XqHO-Ufg zYP*wAuX^SvG|A-znP)l)GIUuy^iOg#RumK2npJZI07*JvFa@xwA={|OX-QNRL?k4Y zbZ)gjrFY`w#4}`uMJ1z{19TeKV%&1M7u(e;F*hnIbtEq@EU)vnz!Qm*!3=#kRJcE`^HvEcCW&CwRSTewT9c#vNLiul_PEwvas)vShWe-NG6q zJ;E3a>ZSpXF$N>%yx+Fl*lgI#{)u-rY@hc1pZ(^~w#VbgA71g*{e?UPQ)7>5CIajJ zkSFFj^RAz5WYc^fA1vUXHP zcEb@<*o-U;)+n(*t5$0{Q&}!AtSCl|?oGT_@VcgJ83CvbWLxdzW6K&aH2L-F+zyWj zI@lCtYDX1RQ)?uphZ4fhvjP+{Y^#PFsOR9qfbws6H5@5pb(y%{w(BRSgy%Qugyf0R zbs3RUaecunE&Ot>)D?uY1AM)R3pF(QEOU$U)?&_x`LIX&JZ`of`{Cjn#+*KR#I`H+ zn0xl;P0^e&W9ZnnJ^VNh161wh(?>QJbTR2|E@}@|IiO|~BFOal1G3r@3Qw3(k!E3T zu;d;C28s$)1S;=u_rLz#FE%|Q4io$S#s8mw{jU#Flt$swGk$qc5iO^L<5=Q&?% zy(}F5Oa78*dRKz4za$=82 zcw6q)Po(G2J*ik$O(4R;nbM1WBI5Qt>0|^$qe_U+mO(99>pW^1{)E4*Yq%p+7&>xJ z06?gnC_Yb$6_vZ%7bloCz};g9EmT` zvd2@?@AZo2<>gp2Bdr&$aJ>lDv#u}e4^`f*OQV}* z@h>-4pA^=mxXE?xyWb+FF~TDb!2ETm2e&!n*z8FhpZ3rH$3OqS%yoa|`0<@@HxBEL zSf!fFJa?kcWg8o@i7fkEYCk&8eLmq@a=cl>=F$53&JfsTFIWP^mS$Yl-{q!C|NJEX z{&YFH>Vu$g59Ui$kX(nXMts-%WVjA}cYD%JgC?)3hD+G{H(zfuyB}YX>YGRj}jg6I13->8PfeIYNrnhao zQ7S)w-}i%#YI(@pc)H#0+2+v1j=8@)UX~WmBydq`r&6Ca_RL-+iTlx_vrv9wVH7OZ zCBK(_VngXuxO@GZy46aRKfAWIsIE2Zg=O7T=FMS&tQA%7Ps~fS<5aSShE1vp6yy5& zhmXJem%lppM=%Jv-@e-JPaZzZ81dr|zn5@C9R8?|1EwytZQP$f+@Igs*gPUQRj_~l zET$-?_d4;Pk;5BkZ@!xCa8+R6ftcK3>B56F>5m~tj5}><%0fO;g9A&>&Q+&USB>T zkW;$alU>+8Ss60Hrg88hCzs{_DT|EC24z_;^+I z0dpM+bqvw%&mQ~V|IMFm(`j^0jcF3f;`B6o2#_T_o`D!aHN|XQw(dn2KFGac|8sKx z%OB|KVPsXl3$urLwAIV?4-u$LhSRfaK7(EP9iW!EuN7D-7>jc#iK9XSIkj0m`~b{g z@1Nf5ZAg&^t6_@z@0r&g4NCw;fFGf2i@R3el>NH`gx zCNkjZ1A7zIc}CO>K)7Z@3J9P?rGBDzydF2jAJTJO+3=@&)GAxtP@rl_QPXIxS`toV zGiP^?m;z47@>AEp=m%wj68%L9ZJ_;_2kV?1J%YlQydg9RW(3VmFJv7 z@1Ji*&a7wt{?o^g{;0e+(HhPtLU3}{@F$^*4;}B`eF%n$ity#}`7w_-DODE|sIqC; z2JOU{*$H$-j@~?H1pr9`G&NOq$tE$P#0<&ly&;+IFncvXIAZBX!BD%|@?Q~}!yB4? zjVzvEg+C*!NLbPLW-=RYT;NY@lQ%-de)t81-#k{GYGi12S$4V1mx&cPx#Fo@KP;42 zQGx1B#=gmJ%2G1HDw$q;qLJDX8Zkq|{doQKX&!s1m#3{Ef+G@{?XNGNG{R-ilWR6Y z!u@HC?bYY~{xl=zJSdb1hgY3yp`SeTXL_OtosLF-1>~YC&Qxj&Ez-+MHllt|+;DUU zk&qxJRc3tl{SUE|^Kd%+58?;G;1QECJw*tnMhuK0O3KWf+e!yGH!PF?FXDIsK?^Xg zjV>RAm?|ORjWR3?he#rG2Bc%^8M5mGoX{hx0~Z>7 zuY1Fr1uHo$g|wblq|`6ea*hr)viSj{3d^L7QB+@+l)o;AD?h0OJC9(-y$T2v5>v5l z=r$_(_H1rfurK=xpJ${=FD6~NyHv+a%W;AdprR{IFWI}*TqHk6MF<@-Q~*!0fH6Gh z*s!O9C1-014D%mk*FK7<_5=)|m@kCXNPya`G%S_=+ySP%Zdau*Wt(baiF84vF4QF{ zq8Cgjm-4M8|Lx8fWnSEu64l5&+4OVk&;6DTye;OwS?sipHIg{haAFT6)Z-;_lHp=V z$5*(D=-zx(nvEjRnrh8YtX~w~2iF_V)16XT+B7PwFR^D~o@T(fO1q=aXWu}>bI7Fw z!-t^kJk=-r6umi{{k(5iyPg?R+BSN8 z$7)%C{v5e9Fg3DFZV^xQ__bfPuFVd29o0v`TEHUiAbd`H~OsBr3D+MGPZl^ zDH;1?NTzT~BvufFN;5ggkS2?i=dyQa)J+Ur22!C%DCLi#vM5iV!o z1Oixj)hAd=lC4vVShskQ!g3!}D+QSn6+v!BNr<$bWH!-JMcMScnR08~H@i_B93FAV zkq;CMfz{{g5K-2g4vo2YDz%b1%v+DSi$aGfbUq$sJ}UUIZXC>gD(R`HMu?-xm^3F^ zQ+At7z-765ds+YhAOJ~3K~zaY;-os$0%v{(Wf0sSGJ^-95fL-yk)0QVDylZ9m=BM; zR2Oqm5s%C^Z7$)8H^BvW-WZUd9AGIwC8LU3+mEy9#j?2#o1h)(P@yLof>R*Y`_2z} zdw|7k1j8A?CJeai{?MD`Fk~tK&0#G!VDpK`ZZl{R5o$WzZ!(VQGMwTWMq#8kH&Nx( zgk|Z+%6ltQD=Go3KnUwlm3dkV)jLOk9v<|l-cv3RMchmP{8|a5vQcAAp(z(*?bib4>r|pEU+bt+YQzpv)UOI)P4zBGS*{O-q*Ah7 zY{sFA91xK>;&4JB9-h;{Jmw5nO&)Giop1-c#dQ?fR;Yji5)2i%l*7iV2@#2|G+_k* z5?tdaq9mRKHl~z0tZLXHY1_MWnbOKS{IHMO0|DP+;ZAw}~jxVjb7zY%YD-!e5Sa8PH0S zD(xGqy)N0aZ##`JiM?tKPfGiwlC_FbnD5*v7Evyl{4J^HLIlo9#^d7DFlRO0(=DnevE%$%#aaNMm$829w5>{Lp4p2-C0#x`G|=7ILCdP>0+R&wzuCK z&B>G-=i$D6Z!pu0eSqy;#h2#WP^68f&G_|pz4tb@ zCiuITr>~y2tNen^!MBZ8{pWm4=RWPe%hWth8tNMU+9RX-AXT$A9W z@7Qm8n|^mW*+fmbNZ0Pu=@X=Dvbl%*AKEY-y3fo^MKKmATYq8YlOH{)Xl!fA4qi3h zpWvwuB7uW*Pya@AG*FRwoy^kO8HRz*EsOWlrw}u8#+dgT=b+6`^Ua;!3217Fkt9nq zz%((u&E0M{gW2pP8IAYmnxs$~KWG%e-8Eet6Vg=W8`sS*y#9bd9sqVZCqeryJFIG_ zh9bfMWUwQjk_#v0x@sZ8koff>DeDKpdPZOCFIX-}k{?h;%d&G%LW=UHG8`V?KU6cJ z9zyF*>qBy4PL=7P&RkerCe|SU&lxPNJI(+Ai0l>|6xNXoR0s77CaNH0t=tmT+K}`1 zsIaad-((<0ew(6D)@+&GqSK-v zSc+($6g=;N%;VS*09`&}{GiL5R^#xM3a+14&7%>lWlRc(#Ynr#ubCpmd&1M!$T;*c?Br$!A$ z2yyh#&N5Uosx9MoUGmUWGwJJNLxS~bt)XQsbUIpv>N6|**yub32jiLd-a~j?gGh%e z%#4zOicVBcnprBRsM=6*12md7wjA5jG6;}5MRJ%Rivl{cCNO9sgFQdLeDnP;G-m@R z)h_+AT^#hW3$X2*?PY6X?`^sOT5B>$-Y-wxI?bY0YVY0Owm-am+NBV2;pE(%A3g)= zw%A`~L3k*B08|V^Q`%fJvz*pzImNX4&Ket>pFYh$jF0qjeR=u#dRKPgll4Bhy*h2S z8|^l@>p7hB=`-To*~~cCy)ei!yQctua%=~_2@%a|b`(-wGY8kzP|{rnG+08$u0&B3 zl@zp=qjNeBS}-W?b@5eH{UskYct|{wRhK-=lhgl zy4~6+4}oUXM!cgi+}$kL4hxZjgeJgL5vI^Qc~2*er0CNZ;9SIz-E?V}r$0V-pVrNr zMDoh(%Y4Rca<|5hWBQn8iU~eu6e&hegD|-ki&Mrgn&&MpA~l9B?Yxo-(xw*>UCt;} zN;-EnVQAERQK5;&^g{@`fiuk-i=;>?$?wUSa6F%y-f?V~*`NI`e|er%Yi?|pEBJJM zYW*IA&AD}5Oz+wpj%S}nckfM-lLj|JGGPi#CX`OeWyBRNbgZ&=uwq}!T-k#tC8A1c zjGoe&{~f+AGC*(4k{BkaDMS;jpCuVUkZiz2!qu8wnt{dqeJ35HJkj}V4m&~h0AfwaoMC)8~74rreIsNO7 z(>AKCNL`!dp*$eZ2kXXye+xv^GBF0S>5LeJIehwTQunr9uFv27;>G-G*U|X(<=cPo z=}%|xY;Avg|4+Yp_sc)~hxbn(?r;08_5bb1AAkG$e)5xGJ7(XW$Zg~%^K=SMs5rfB zK!np>(wtM>3x7mdWLa38fb!Yk9o)m|l=3W#h)yj8TXY^^@hpXP>rkFaqguif&<$lo zsFAHT>%vmYn39{ajyMLVSG{~|tp%CbS_jd4fC^R=7L}?GV?%ajPxdiWX%*+lTFmLvH*(irNd{7Qr5#X8dl`SM9_93y{ z5C9QY6EGa|m?2v(PAppnghX0v9iZG>i{A7t0}~L<+SZE9IuIPq1aA=mw#{gB&epip z$K`tc=DS}Qn+ZdMF@O{kpbr=He0|!?1}3dVro!|gcWV}T(}LN=wrxNB{qKJG!ykxy zLf>Ul3NNOsbs{+9mzfP!=Z2Z(+#(hbE16ZqF}*@^O~G9>_;ml{`yX~{>uuX_zy0Zt zxBYFmtD6M=U;p<1`RD)Z|M>og_ts6=KD`MIVASKt-CMyE;t-_|;opK#5 z4|qaaxdxscd&0GU`0UTT7aitJU*72 zb;0~M&uCyJ5b(COm;SD+BU=5rKEAylb05WZp0p2rF|(Kq2R!521^N~(yA|2<1EzU zF!hisLL$ z+xOie$}|Z`&73wla~7#pQ|-+~hc^j9nz$4V&?kp$2wus4J}F+Li{^CD<-Ub<88Y)M zd%k37H}u1y??Z2gQ|xXe%-KwXHYPEqkFZ%g#+>)3hU+#>GO2k4-8fuhc%B!?K1`rzys$;+Ju4bI_-De|AbHB~~Zu@B5o^09#XK#JS-7RKoxC9#x2{SB^ zre?FgLu|8dvh0K_=1(oT)iS;)a8j}uCM}xyGoelTErrP+(TF2dW|?vVOkSR+)#VYo zVky_mSeD>$pMa3<31aAmL$0bV!o#6U^b;Ep5YDr!#UUNS=^dpc6N|4$jb9foF4hms zf<&4%_b6Jm1Nw1!?JDX@OEY|STF-Z(17TEZ`J?X?FXCzGqL?CsP79IH+_Af(akM#1 zW^ii1f7)*!?i1AJZ?}HC@$FTblCD#Kx@~W-KWV$%_kn)FbZnK!6Q9LAK($!MZ3p^| zu4zT%9}kx|cVxOA*zmLfVOdW`fhRX2@?(%5#*!Q4eLb$}+1#I3HbZ$bWQVubD)69i zcBC;KlJ z2%YB#JRVQWBuF`!cSd~{Q)DX1o6Asz0y^+VPLj*ML(6Rm0=S#FR=Y~ET`R)zVM zJJkT1Kdu2!WDC!}0KXJ5uN>>)*~ zOih69ehedwYk00o|Wv2}-L*34XHWzQ0i6Wzi2w{F%V)XMZXItK`_+#ggZBtXBdP6f6S;kAelk zUDMQK`4)s-Uv~0}5lAaQE77bW0-$C&Aetm;LX7SsVMLFZgS*LF^qvq5));!o;pol{ zM(@!F$jn0Uf$Af2#Oca}Aj_*zL;@KB3+tdJ=^S&;UD#(J{+Pu}P2(`o=WMXcw!wEe zOvd6IY@&fZ8gVQERkf;*&s|2mG^wNY5DwsJ3)o{L=1>v{MEw> zI$+2P#z(Z$YDc=#b?P6b6ipj#Ixl7xgSrv7cCGHs@2p2?}OKaDu%yV-X5dq8@L-{2# z!Dx;U&4SrSyHY2RIijngS7`-2&u=pWDGg#hzygg=&!wGab3TdGt?rz%wE{ z9w|02{&k;0RfiKxFs6dfG4F4>@7m0)n_;uY5Nz(e%zvu~fDP%c+s*~3O3 zU@%Mzjz6rs*C`+A0of5p)MdQ^nf|ikT^Z_dxX>0nJwRoIs>}HZFmz^F3uvMCdudbE zW)>a^n?)ngrqD&8?ep%lhMFc?%`Sxo8Y~8Qxlfb>B}^cj%m&JjOrET153{lg+J%s{ zROrE@R6?jVmNiWESm&Z(3m~9BJmDb~tF}1aL?b5`Lso~etWYtxXP}x!bV;ccdm>kK zok<2wKBKtBJ(j}2=>@>ja(PsaQPpELF6i!%8@k*LsTJjNk31MhhHr|_ha$w=V2+%! zUVUaQ2+--S0t8I2fha7nFnTTjl3`hjj|ZSJfz~qJiv(0bbX(Clc~<)qYPPw2-bZge zq)`s45!N7zH5pR?(TqNw?sSV!F=f-b>LRy*PrxN#m1?;=(-93AGm|kP<p%rPlV)Ykbt8r5#S^(^n1e zNz6m7EJRdXPa#|R?vulV1{2L1$~)ou$P>BF6zoKa-MS^FX1iQrqz~&`%$GH5n!S-| z@>mJFW$4qInrVY@VKbP8$q*Y1y2u-CLa=x+A_|>hi0LU<5|?T(RRMDVjX=)nV6)!l zUHy8Uy92GY#@1w{x>@hIKH2R3X$ZYN(T1Gv4ZOlONJca3HIp+?NMXYzDqM>j0ujVx zBt?evmmb-agQ`MwH&WjW2PRXJQpc3Kk_^1I?dqFe z@5H=5Z-y(#$!UGVTb;c*%x%991GPPkxo_Pa)`1RF44erEMZ>L&Gb~k@3RCa>iR|SC zp7dO-)4a8>fq6>lRhTK9lR@u{(zZ zAI?yHd4=ujq_E6IMDo|el$tNQal)KsBnp}w=eJC2+J>}TEaJZ|At0KcI1Pf@rDLe> zOr?gnq`h=h{(MlowY*1^@ra*dJqk~pM_nnIm}(^cH zp4xn!Z_q|wTl*TfpZaARW>1%Io-bc(v#qt!u5IhmjPWLZp4@UQ@u9EQtseU4AW#np zN|Sr+6N~amfRp-q#my3xo+Y?Y`xIi)L@D}7diA13 z&WJLinKl724vaEm>$Z8)42R6EmB`f8CBzS*f$X>^#vH)o@8{<%K`GgDbsVdI`dW+` z0Lc=4WVbMj;$fBzWbiSEKxcxUg1YDRdUdEVW}!{q-*P`35?X6uwA#q)6#Yb!y>Bp~ z#nh~pjrJi$ZERJ&S~I}u5u28^YOIo`Ro1N)uxMg zSdaLbcUAYZ`uxthn`_+0{(kqTO=`Tz2{nV!MsvyE+@|@YOqg`S_HEMzHyXIj(b6>| z*==n5#|_QUI~tuc(O>W+(OWee@pvNez#En_t{CEFnyycnyxRD*YvA`EK8-OOOj-6% z4c^|5F&mxl_t)1CZy$g9bR#j{#y)(y#EH4j-FHYe{`9cm=VZFrGD@^|xm>rWPPUlg z#6}PB12$`N$tMaSQE^_{>Km7RZoOYYo{h$8gyYIQpxzj*2z@-K!9U2wA zop5jahVjM(UlsJ`NuCLy(iS4^H*%$`zhp&1EIeqz9ExIFW)G&y=u&_#2$BQ0*W0-7 zl3#isZzEb(Mo?Qvx^Q93pZPjF9(=?~ahI(Q4l5P%P=-8_6?#DAI8N}1NUf~O(lj&k zu}c*MF~~7S2eCtA+GUd%=}?usQ3`>2d?eMgVkHVK-FH0w19FI89B4ILl^hF#<5^+R zHDGI(ansu$KYVq$Qq;D6dVQO(w;RUb^y&B8{lic1FTPLL-RyOYt!>lUuFqS)bh`}Y zsG(gqN90MeB7q@0Nir~Pe^qg3FzbwJ&oE})_VNM>S*j9z9&{lecDvx>CiOC9I8GXkwaYoZhdt1 zq&`3QS;9rZGe*3iy^gKK7Y=n#i1+Y(C!4|r*fRTtG!H!lCgYwARh|B2@dNZ*yKK** z6KL#j_DZv+Hsvnw{qohjZ`|DlH2Lm7{P>54#yAqKw|)t`%Sf4u#=Qazt+lOR+O|nD zl09l-O&YZ3KF8c+dd`%$_H?;i>jcFN*{RGsCdjQl8!aYRew;tubQ7y$FwPtTlN}yJ zoHiPb)>}+FqLH64W7G@vIhYkC-YiStKIM$CtYqcUBSLSTIL3 zYrXZ>nW9^NrT~ zKtyT$gmxco0&^mv0W*dw_?YIn-1_aW-)=9{$Igb`#ubuNw8?#-hTT1ANEgE`}p14AOH9N`(OX|X1qLe>ix%$ zAD;iw{ke5s9OL%-)5H{ew5QGHcjXcSvEasHcAuZ$Z7&x|%{IwpQ=%D3^XVTy{&;(P zwU{NiTAP3lN1Ip%KnR0E`V0hj`Ft*wqv)yX#ebS@`5+ z3CiJ27bt~3byh^a>v1YZqDqWI0?zE9orNwa15rSk83y#}`+k?JS&Nn**;t!^>+SW^ zj7hUTFV9b3fA^imxb9@e!l4Z9c?y7OMf$<&(6|12`lg;db#cD;P$!3iNuora{c3ve z?r$d8t3Lkbhs*Wi_nV%#zx(v@)9dT4VRTL3KfQhU@cPHiCD;dl{mqZR=Cw2Zi{7KUsZa>XnfUBx0F%mh*=;W{7yBgX%R3&dVm75FswCq zc}9;xkQR~f&3OcC$~|uDbP8OLZiZwfR1qd;zj@f))?8%Q5x3C zB>hr!QT|gFdsY!Xmq5qPG`8Hc3g1vM9g`+=!q`b=$FRg<5$azPnQ&m{#Xvb+KF0vG zweH60V>+F3-zAtggNYNd-W3c&)+?^i-w}y+3I?BrL=pj)Lr)T%s)-dekTaWLa3Qji zpNz^rFqS|6We+c?JzQ@*Llz`ES)#afOa3-P3apTq&KFwpUpsf!1_Cng)M#uMUEABG z&kHHqCc>II%r5QX(nriUMbbNG+dlM5w>hl4E`5WVOXhP9cj5jCoR@BB6D{N$Bs~a~ zT%yniK?j#}#ME zt4~xKh|-LYUn^`<3YANcJ`?{(3n76HMLA;ngO7hti^wPflPyg~i|Kat1+i`RK{`LL) z{da0}YG`;iH($=H!Wq=j@b|NYJqJ%&d~8^W@;Xmz5jOJd89(4WeYU?`=(vvdNkcE? zcov3b6%d9By0Wq!SsC>GCeN5)|cn6(`#Z-a)6_j2~F8Yo0Z$h zNN$Wy+M08HI)GCTvcf)Tr=@H#$jB};TGU4#w;^{rBHtt%lBAqfM)wkt!r9r7KK!25 zXEzVu5$QY5nH~D(Ft70nE_16-V&fo(YK(oQyhgR}4!FWKr2?l5%cN zvPy+})@N(|uhL(}KG0jUK75ZMXmhwAW1Es?x0e(GrX#ry1`};3QG@W{t7BE%bQ#55 ztA*RES17&uA~?^ob{4-{^pl_+0{QUU6J#nVRN&~W40NLT0}~ab3y`SNChM?2oS)p= z<4z=PZ6gpF$IUK+8)dBpC^a@ygAXG-95Jc0U7J03o8ohO?snbgcI6dfYg?Poe0tI7 zuz^lD8DLu^SlO~Qxwi1rBO2?G$sXN!=5@PG0oI={ZrgQy_{J`3O}dHw#kVJWdAe}U z_Tv4@tw)=&K6c$d?jN7N{l^}}Uw`R*+9T^*GwMdq>lDy6DyU03vui@gycyL*4YnJmr;dQz^X=V}?r9Dhjwu!gOW)sQQTC)o^ph(iUX_^*k>h{%T zd%0f6{oXg@^Si&g|A-HN)YbQB2(%e1gb)RAT=U?Ty zoPK6)r?RxJv?7QslqfV;L@(FjI(qzu6%PoDvYKg?P!^Tc$%!nomMUu5(<%xQ%#N~^ z;}G-oJwO;%iOl&CKR>`H@gxMy+v$?WBVhc#f$ zo{8F8_wx1&UQa|XP84+l2bJDfmR>Cs&B~}I2o|+_L>$8Gprmz`RwAn9SIE0Q9#F7z zWuBFMV`e@9u_T^-d17Uv({zMs+#29&2gotNZtxkHIWuG+ zpMySHCW8SoIJ))c9&zWk3&IY$sa-_42IjnMgN$a-6gKo&^{QQ|tgXnUiZp+%;GgKt zhockC=B2;c{&c-am&@z*yZJPCsgIrGB7oeDcj0a9SFzvb90VtJ_c{C1_x@?W`)E(! zHrt>*cFppTo`5DI6Ddw~cz9w14elNyWHd4Qh~?X=Pg*Ma4Al@3gFXQ(CX^1huTIZ8 zN9h@Q2IyGxRlqDJkwautYjlU(X1Dpak7l@bmo&7$UBKSjx|&)tQoz|=5!Nn1%~ie{wbMY&c$mh>*#u}Ur@;f&$})~_=8045=!J%Hc(epi z^wL#TR+=%}&o2S~ccGw_w7t*)^QY6XUtzVv8woQ?foI3V(zPsaOl2bh05Li{cRXCa zAbiq>$0u5j;tG{uhCqAiewU)~r7c)sVF7@LaMl6TACJE(Y>u;M^SO#R5G-Ks8MBJu zbj+iQV6G!_(cQJf$MoGu*VyN$x4T^1xZV6>;1Fc(0&`$elS<=R7#GoG#FnXF_p^Y ztetcWmP8i}wxV;ZB08lf;f*cy!zcp6ku=J+$ORS2XsTMN!Y;Mt9_BI2iB~g>yVmU) z%n<`+!#9>Wl(WK=(`ra@q~ctYOJc}x;q0|8kx!6wAXC@UkbTwS<(89ya&O}b783!F z`F-p3X~|OA9jb&-5O*bX08v1$zwpXu4TY&l!<0m{ zl&6ez9r&cAEMhra_gw&Ukv7L`3)h?!6@vvkKz0CaOF9ijkt^Wu5kjl*w-vm%f^OgqyD(5f0vxr`0rDLJ=B^##8iy_w z!a*9ogVRi$<8rYn4a^z2`HigMS~SBR`oJ@*A`oX0IRGL)DMD5W7IbJvXMS3qg(Xr1 z75+waJ{jI<>@hU0(+uX8>CdUELwST_lOQPg?mBhKA_GPRdD&5cM5Sw&X)l>RoB4c$ ze9oo2SK)HT^Hh2WWkZri&!Ugqdlf<#5OJ>P3tq=BPFscZ;@(&!MDkm3r;!e)+~*k6 zT6pU2a|TXKRdO;^ETvo?e<_n>lyXYm0tXKmDV5y84=kYP60HUNOR*y;(W?5I!TL!i zr)spcQ!=QLZnOsNbL$qBGQIcKuiUr~QP9{^&1R#$LavGNQvXMKcHztw6lE5a#G>ad z!DpCAq*s~@t1U5zXYm9ww(yQG(5)pj#M&w?sX$T%2Z7h(NSj#lNNjp zJ-ogHYG|E_xTv_YSR^3%^HScdu|g`Pi{k^Aeq{mVq*@|N?+mE9j5I)6Dsj*ICt0Ev zmrYNtWQ(zVwG`+7Gh1RG&$5)^d1cBSB4I_<;P}9VPzN;n_~GOH_}+!qJ816n*0$|( zb<3^+fkVyOBoR&Zb02krrL`o;1*!&h(LKbYdmT&8;0LQ(2MX&yXBfEPPWccjtn(nD zJiSe)3+waO9KYbgUJsXABD3TMT(P&>l~ZQK>4QjsW9*aY>d89Z z{OyvRq;8^Umg@@N%v6f&L>jkILr{17SVaj1zM&9(OviZ4Q8Uunl0z$^r5Ane)b{D9-aQS^v)MQ zJ)*<(!s1^GlA37HAee(43_$cIfuS{G(i^%vT1*Cn5A2dP>y9zN*3DX*m~i#hhwciW zObc`@HY>wGh=HJ`{MQ|?NIF zQ|5;mun7;xjMX9~00Vn#9sRqfuP=rE!0KlR| z*8|oYmmynbHE+J_(Gb)EEx=RBB|Ka1aw((;=H^oi>#&|tOrbHv)TMl;itko*9KjKD zk$ME8nLd=Wh*{KE<_NItq?0XE1lIXS4LevOwziC%ItlqX;93^0oLVyazOmR_W*9IL zj)eng2TYak>m7 zTkG-}75g%g>})%x+yUk6XR^`asf#^IMUV%q{!dDZS+F@E7A{4OyDdNJ@zmr^&3M$a z%$3vo@O9(|o}Q{eN$J(%lu9)mYr1rB`A(T{2OQ6}w&Jrp#c?cHh9Fc@oFd85ngx4z z#3z>2K+!%l+L(t2<~FF&=+Tqs8@v9+yI;MsgWSi!zLtwNzB=8lEl zU-wlsP<@60&MdZx=2KLa9HtIM-CNzmX9oMs4KJLSECDL6fMd3-j+OY*tYekKL1Hx$ zVZ^86JkYE<@KKO$k5L;*- zP{`E7P{T5A?EzNBFLEwJu57fJjWU6hf;hvG$D2N`5(BPzwEZS zbT!txJetzDq`20U-V{cdDy4L&#BuYScG4O=&J3YRua{nCd-v|^uyqE@kD z{;|vzm~E{Ya*AuTyr$)*23?b7@8MTe07QX@OD~hf&Mu%^;#Z;d*s81$iF2Dr8-TR$ zyJ*&)-K4Q=#-|RKxx3V@Upa?3*)Fu`TM97xcMIk+U#m^f>)5aQP7h0CSmS))hcO7% z5o$18a+1jU3Lzk&i6%})0JEZknrZS zV9;9U6RKe?dpV{Nn9RYjmD5o3la=w%MNq|$ksnyLA;q8?3538thTxqHzlH*T#NG_yBv6v~jy39*XqyP*~ZAZG!G z@g<>bypHJcQ8uOk#zB2(9ki3!sG<*tJZGXsMvyXjBS*n7@)IjnrZ}kBPYWV8fz6P_ z-F1s5uz>;Q+}))XKEAtAbDet}v}CS5!d&F-WyAn1vzvEOa&~%*2T;{{2+e0-4;BoI zWm+g`iCTeBz!l@AP_jfQM(M;}u3!2rYmH>BR0Cie;b4ZXQjVujGlL?HaFM4K$3!-9 zj?bM7^dmY)2TWNH62L8XH*(eUk`DO;{*?ltLuT@u)$}Vx?&tLJqe!l|o|Ip} z*W>3!!Jpo@{zIGy1Utpx&oX92%XXxP5YSc^HXbmj;Bv=uMLDut;v15n^|i4GX`GBQz0s8paeYbU4zEtGJO+z(%8}#0ugBGPYZ;L|My2^O4zr(B0>hrboSe=e^^iE=a_t z%Y95xzz*NBZ$5}7$~im|Y~#s{YNjcV(QVdDfW~f-ba$$75FyThGzfayP`=oMOeG3B za0MBBHI3F@&P_WiSq;_0Z$mBTK@ z$fLv2OA^;4^s0jt;cfu()STNEw`plBo2p>+@)U07NdH5TRjYO7~@{3vQ;i=NHH73B=`yx>OB!fUtKSd!D@w%wyi zl$>S+n%My~!g6?26)OmMrD(zmEgt)<^KPb-+|i~_aT+>FpBiI_Sqke(EyV(?ir>;B zhf2}zV}q7Lx0 z&d2)CXL@}7^VvI?36eCkt#xnkHc82+(FDSGk^AsSYLzg3Lbw!3=bBS=&CTW$f!5jD z$Ib3@O!qtbrL`wCZyfy%W2dXN7SS}P!(BE}1YlGT~E-;xI!=WdPB#kJ8pRUI>^=%~~eC zg?vFET5rs2P{EkOys9jxVjvDGRF+LHm>vB-+qvK{G<>G*AknDVKDPe57qN+@MW`$u;`({2pM>JRM*2y5V zd~5|`nbqOe>)8StITXsIsHBCMK9jp--qtb6x}K#uvm)Tps4pV?vorYl$vAz^!z(HP zZDh^jPJ{T0)|XS{IUZG}g1I>hV6 ztUfy@xE8_Gb*<9Yr{!6%T^TlojLZ5JMl2m;k&qCboQP&<)}M9x_WJevx%+&RqQU=t z_tywMaJHs?7>wfG%G#!B{ZDB3EWDbyoQ%;Of49vKTyU zUajow>DFPy;!X})4gdwoVc~>}4ULI7oa9XfVQI4J4Tz zKchOt5RE7HIAnQrlnr7~1x!f88cu$g^(J{`il=CyWayCM2dI1e(3dnHzhk1>`eo89 zC0WW`NF+FhI+xr=udl|%1{;hraYVt_X=%gbGj}now@Hs4uhG-rKn{2J!CU|kziy%(^nqM$BFFpB{ zZDW=rYJeu_*J=(=Twknwef{NnhakGv<}^0TDIaiSeIWG z&$AC9GJzIlt?d zcm3M?lY9Gp=iltF;xy|rI^1`%}Mu&FxRyHybw5uUG&6+js9K-Q;SxUS94k zdalyI&Dx(_`EGNc%KT!53Ig2IRTbC)Z=2fhOV6eYw4^FgQCg6AMt_9nr79BbM`NTQ zxp9av*H|vbm5PgVv7aq?-eP!GA+itt$Ke`1ScB8aIlpclg|OHx3>=(iI&aHw5F%IL zsNFj*7Ppw$O?g%goMDAep^ej%5GbeAPFJh@Jo`q9q=3fi!c|$c2m%}4ESKX{JNy+>A!mPo2HpML8>8pPk_W6^Y!&p z@F1Yw?|W7{g*nc%@*w1CE)J5A00r+0=}D(;$Keo1){dq-+aeuqLii5CjbKiF)Vd#+N9Q*w)#+6Oe3AVm9Gr0K}AKw4y*h%!Z-S4ll zgYIy-8uu{_7Twb$EhgE%tnLGA))ky{>;OUIOkvhRz{rRpK`_Jg70hQ8I43n%(P9E} zXK!*))yTw|8)>_#pJPVD zz{swgniMSNW=6L$$~9aqa&C{^EHhPBLNH^afsLK!gAQ10t*t8eLJ39I*A+74{+KPZ zqG4GOlTbtSs6Hz)*ApsvbhKWeru9`P?z*Ra{V^U_;y77jo(K&bxUoD;Vz z_(Z$dwv(SsG))S0I;Wa@#Q468Z#viT8x-~e4%VS>KMl&?G zA&?$%y69jzr|Uv*o%C*OgAnfUUD#;Nmsw&(Jn@-&Ni6{YZY3!a&}_qSpH6F_bD%8O zsd3iYbkX-|a8Og?#zw1*OH~Ezu|;e5>W-ov1O*PCfBWMf^t-1^->%oq@Zle9-~Zy$ zbiW%wzxOs;-z;)}8oPm%H4;L%{`J$+T;(V8t4t+XaS->l1mD%XS5O(j|o9LlcdW(y?u%#6k`{rBp(x1%Q7)vUq1-5 zS>Lt0?_`sljhvKgzu!1Gqm2xk5EI68+6bcW3zvR^Rs*)^CRr^iBU}~HJArfGeNMuP zPS!r}K77v6tjCr|i=gQCcE8_^W4c=-$lkWzFMBz6YG9=R0w85@z#M3cHvy>J5M^leta=`OFP(JI@k>3ZPE?>i%4u+f+cNfA zDlPA~F8grJh5EE$+3{PPorMx2LlVp8nv8Hu%&7`j(2W-9z?KShx&iVrIUxBY+<;CD zBLHhtZu@tz%!Imr|Q1BTXJEgJT~TKBGLpk&sfll{rqp50_3$<9ji%`Du|RCIc@!4Ft{0=dY% zv7_LLt{Jk%mDEicF+<=2eW5aNPzV7~7LpP03{!7imo`k->!wTdDZj`zQikaPbc7j` z88KV)%7svr<#==_am}1Bh^F{nfUJolrsRP=-zH=78=-*hKnIHGkud~jR*cHHI^|?w zCL&9}yw$p`W|;A`ae z8={+cnpq(#43nKqlr+b@Y?t0PW9#e}v%B``12%`NahvXPw~Q-*s&6gQoH56Y0(e+w zYG=5-HJcDLAYzgkbjZ6WFy_5x+N;qRITd7Z#L+M_s*^I>>VQJ81R#p8ri^H9q@O?{ ztha6YaAhAFPrV(}dex$uGJCK^#LmLe&(;P82xjKf9TVN=m=m z3YH$5ixb|0xL1O{vri+(S6ii^&a^#8#4)PxN`p+Ty0Hg6EIG9YQCv(jDihd?1jSL7 zq!ior#pp|8rJAcdln%Nb$=8VPG-*h#RL7B#Qq(r*a88;^qG`j6m#i27DKyRIkq@H@ zvtJpNlt~0?BwI$$a5^drzU_%*YEG`0Bg?AvTct3ia{)jqC9B5p>@^Ohj+_t`GPrr= zR}F=`M5~%nVgTOh(t%VIts0X6U$bPqDw3lFcB34OK(MeCK(bjeEeJzRWHeeJHt7NB za8(x*RZM~rHxWbVcPw~;V;z=*LzQ)0+Gr)SIXGUZ98q=A42{pJT5>Zylcq3ImH0fR!|~=AIgX=nuGy!An`=1E?~w_jlmW?^i`S%e zYD|tAgJofvw(nh$$w0zwk$cz(Rs3{bT4P(9t-JY0^#ZK!ZgPdpS~l|}f&Z;_{R>2HvY>O|pE@(g`%)D_utrF=qkHFo}-X7rH_vCUiU!4}}jV8p%EW-re7WY`2k?|@h#L?6=&+l=} zMldsO_Sj_uV$YaHcJ#83&3~Vky1m==$2|$uRFV+}D`F zVk$=&fI#yVxHfBnX1@4h@+EbB(Z-WyMr67*)KJ@9W{kQ`nsQD^n(Fk~sv7R`ns*JQ}de4UFASNMjb5?ux3zoz0Mo5_<1_-xHG3XrbuQ z8@-N&!AgPE%rfeBWL5*sCm0g}W+HkKcN>(Jq?yx_v0tz59+@DTEl5-l+{_fIp`JYE z!Hdyk`S)B2Mp{J8oS>fPGRI11na$hqt5H|F#NHVu{Hp0}n zXICbOn)#9$f&v{vM9Q%E(tD>NGDl)YV+5MfiFyf!2epp0hEo#w{q!#iWb*% z%Nz}I=B-A&*826{Zv@Iakf2&krKsh!5JqFdRx^W{x6rOxy8x;aXX2*;KgQkz?!4EG z*G4_3jDw>oRp$!p3K|z;pPCR^|{53!@v!~_ju7At8MgIPP0EV*1A!A z=KJ9|8#t^g258o>e#7wd_JaANfv$MKt&!Bg;O0te_NLxdJ$>+u)E?~Kr9}E_t2-Cy zitZ1|uMJ!0c4c4vWbj4H>g!|d9zNPTWfmv(NA72Av;<;jq7sTw5YF-JQh>>U*_oQe z<6>GZ8w`dCv{~Qc-&q-0K#cKnR})1ytx^UEysx~?h+ojUlt7UaY*U3$A_n{zy6Cx zuBUb1HX(KkS^DDQLt>HAu+W^o7#q>Zgd-DrHK$oFNqTodQbIZCEe_C(jauX63MZ?V zi*pLhm2fE+pZ&83v z9lPj6+drWVCR`5#t;%Cz$RPoCMHgQdo=xnDR3bQ~DDS=(OMCf|) zw%Y3d`02;rzCLq7m+e|`MmRu!71kJrwER0Eh z81>?j4?YI%am26$l}oiPK>?wy3lNnQczMmwdg*a>x5f3k^;A%%fYAx3BM`MTQ}6#K z^kYC&TgM;+Bu4;%@j#9!_HbVMV%fi(1vY-e$-<^!VDG*6y%Lj=y+24x)l1~XQ(;B|Z1`gSl5y)~M< zyPKE7!nW@byVX=l?kaT%fo7M>t0vOaalS{F&4>w%?rwBb%G*gPIxB9Ia&Q^Qna3@8 zy=ifD&(7h2i8uu0ER}(N$;&_f_8(r8J7s=`@VZ^=MOg&kn=ShyV7u8Y&ENeQ8pAM5 z!c56b6M1`!yFdN%m-iofXT)*y3L`?lx3+JupeWixbA$Bq^7`$!zj-+SaD9CS!;IOf z6atLpS=e^G!{aq~Wzh3~`1bGqm*DB7hJI52*YAJ!2kmh#Tw{JiFa6+8eE_?pC z?M+q-*rW`}q<+2r_?zEb$~pxoQYEpHG?ze{OY!+^udn;Ch&J>-ZWyCH z)=`kknR>2&i4n11x6A~0jFY$5UmKXJCbS{?!=Vyb;=`Pe=y)W@p{X~&VZ$%I|NW`^ z5Mgue)50++rR&xKK?$^+p-FHjlA|PGlF~1+_oz^cH1$}%K7x}C~)2&WIgp{ zjR)EHaJT1uzizKIH(K$Kd+bs#=Edk-!PHYXt0X?<+;k-SP%DwVx&kvo#kB29NdM0a!XRx)eG{d&D6Igbhf zhL1V6*$n{kPxi}1PiW0sbC8)e;s=PH(JPD&W$(K(jEu^;#bWN54u-1v$0Dt%_1uP9 z2FbJ&7gYdH%aZ(~6sd@a4O!%oOehz#XrQ!LjA;xr2~l^BAw+Lvh;&BYf>a;846!x^ zRSLbN!6V}~@sv{1S0oj^8%-%Fv-g??PzJw8Co^*ZVGxDl0rc$}2mo$9m1axCo{Y@w z*wNF>OW+YTxk)CZm)!dfuTqhTA*XvI#y7s`tz^G1oe=f_W( zLUlt|Z`%PXG>_$*B=|r!2W^josaLmJ;o)>MfBH2j@H5viQu;Tb^VW3MUc)r9(>>gb z?zBw8p}JNTx~i0igyr=5x_#U&B5Hi*9%5Q1C|#p3;x8Vbx@pV2W_!#@??Zn6C2le- zBB9>*-qm+8J?nJJ_K4DXV9L3+c0S=`h-lD|POdt>Nn+-V(UYZ1qBQ>51(=(UW9-XO z?5sEhKQPM!(QkESNnq2y}2vPL6SuUo~I9P#1(U#ed4Mmp!p_%TKX? z*7YJ%zH8gs`FcLv#1EP!eFcTkVL_g{eIwU~0V86UpeQ0BLNCdoYl;uw~Ce-=cQQ zhxKt?9usuovc2qmv#eglfe%>3MAD3HT_En|&!L_fv8AGGhX`N18yp#A#s$~jdr@#n z>>0d*)+P1U0UF;0MeP~UqZ_R65$en_+X_-BrRbxl+zUI%kbB(1kg;2CxcKlw2LRHY zRk{HoC6qGr)*6T?zDh5yae*O@Lf5dDM78#rf_S}HN@0y){rRo#QU zHG|N%?5|Y$GCK7Q{Ug?&Dl^WNk<6jFpP--W(IdR^FmbjdFb**LuNq83@JqR2y-LU+*#6CRl(%YnN3wZ zp94vt?C;p|g(Oo$w0Tfai(t#ed|^%c^#!09^}D*BagDlPn)?{?KFB}7i{0)<^T%@^ z-v+etfHZfz_%4HW`zh}Z!MujsW_jzKZ(iX@X#h@-*quluPb<7(4`oLTr34{*#?D;Y z@*r-J=XQRv{>SAdxRvhk!_!}Uy}o*UbEw1Gp*wY=NL9E`?l8E4O ziN!FJiKU>?>;$$<`D|LY*1VmNeTmbfo=*7Q^#LsfdBADQ(im)9LTy2Fb0~^vT_P@Z zg6AUHttfMQxVL9F=q7b4hYh~r-23M`e^kuzQK-K`&x18|yV)@v=^(Szn<=LYoT_XQ z;h+f=ySOF5=Cs#z%O}qkO2guE=W6B}!zEkF31{&iXbg=ZU-JU0dYr;yt9PG%fM%lz zc2`j?S5xULT=vALGi5vrmA8W0pZoYpHyLMs{5}7fxaaQUfg(^% zqcS;Aw`3G%GD?P;LOu}00jl)ng$aNXjz(|xc=B{hU;MmXce^Z98k^a=bzGh6yEPKo zPV$A~vNYJKM=HbAZE;j=i_?}{R?AK%4DO|(3}SSom#AV9#Q-n}QVKV3w$L2J(E63` zaqM6s%x5wQRKxnEP;DFu8PVW0XEn{+oIf?XskpZDdRibDEh8JYO5|#=C#ytm0NeTe z%{Sk8Ymwc#Tt8ob`0$5p=!d%}G9M9ZhyX~7Vza}CUYG#fwbI}5-Uo#_sp)P4A zRo=^r|BK0dyH%_yDKgXK1{09zT|1M2iBf`jQzCB7!WT@n+^V=ne=$8C4sCfgz>RWMeEq&55q#NqSq@s7x%S z8yh9^G@8W$(muJ^iQ*Q*^iO@_MKs z5rb+&R%L_@&5C;@(QS{bAsbq==C&-pShFlDzByzxPgPU*Ot_3VXk6EgCd8@uSs;mK zW>TOTMAA``mD7xtVpAn!btIkd?5S>yoHB)n6Vy1#w;<;*e7Z$%N1o*NPH(pKjOyP0 z{6FIu<|hxkqMFg>pXmj~VuE1*Eyg3^^0T|ojr-+M@yMnyH zw(McHx_L^S2xmr%5`Hk*oujD*7&wTxSej;LPF0_)`Qo0*JOoSG(%h`vsEH-vCiK)s zQ^sx?CO9o~pHFh6A8MCQAEAj{Cr%y*a`HxIu3{+H-pq=oJubvb!jJ{%IT9%Io+fQq zlY@!59u-9$2%&7@Bz4t!1C(+$+9HOLJ91eJL>ibhc;o8wDtFVW1wXC6%Q=b148);T zOM@r_y?Ey^6(T9eUcn7SYWxXu^d)o3=W1?6RvxQ5JVdCNfAt(IJi{>Y$dt`+GpZ!6ju=jW?rm-q5VA~Fuh4f{TZ0?_M0*p zIv&-`MBm^Xzj#@VP&_))k7zJwIaO~z0GLU}yKrLWFYdIC0MJ48WGB4&f_7@>);+@@ z3s@JdJ!D&-LUwVknl54=N`UQ^UyZ`6c2htttZP^Jcljl0Q|kGwijNV$ecLGG;z z(;{12t$Ahu1~Js<3&x3)6bfMUyU)`)4wYNes3IWLGcz-*RY?if+0RV&^gRkH0kXWq zz$%AcZ8=pgSk~3dEokPkT6(ZcbrvNjk(rbk*X3l+jF?qZcfVGXc-?eh2hnqfDoR)yelMQyBUF^Zu~)$ATKW^f|kySTQh1O!=KoOnw-yWfUnGGT_P+gSj+7Ko^l zADVe#4=P#OhXqzgY(jvk0D`q16qKV@$pkIY1<8u7qNquq&SKO8G|;?GQx34zJE{{) z8uDKw#+b?R8XR%V>Mt~G?tNbk1B_RJ#SeLh*|r5 zOawp~9#x!wXfqz0-k>O8J(@^?VYiC~r>tRR5GeuCFWe@ zA}d0ml1L~Imu$2|<$FwtlF!Hpr%AGaX^OXusbqtmV9g|<^i+krCw_DAl}npe%cwHT z97@nUkj3qM-cxKi0m_%)gI|0zPU$S4)hiEv7lGM;Fg|5eEbFCGs4~c)P;Rw!WjXYU z=h(Ho=;m!+X9RX*Uljnfkw~m3V7yVu#v3JMbIU>0P;VO`SjefoeODIO$W6`%#M{5` z(G^h%w}kc{pD&k756fI1`iH%LyncS&C0W4^yJ zhUO@}K}wm(!6>P2KU3tMq9U?j(~L_>BCqt?BXaNi+8|iZea{+X;Uf*9D7Mm7mlMto zkKS|mS44&~%qo7an~RpGMXQF0OLl~^x{)w?%Et6DUwq`l3eHf~5;4*WI@VHmr2v}l zOJHx0#askR!prlEU`0QP41f`PCfqDC%s3QuQULbo$dV`KeB{Fu8(j(JxHPFF4ZDp2 z7W7n?Pbh-+GO((MO3YIB=$VRYDU2C~BrA7E zlc0ib5X6jpeR(Y)6g z>4irlN-KZbof0P++jaJs`qBPWhOe@wQk^Bqh{=;VoHc}`(|vIbGL%~jZ2}VU@%iKa z?LRmjrhR)w=Fgx08@~VAh5}p8lQZ=|hSeK4TQ@yAovjfLdZw(Bx0&Ek!5?;-gXhD; zgdJf#-jYb~th61Tb|9+Zi>INiyDqlucnZ@*A0IGny>4mH`I`xl?#{rQz@YLP;-D{} zBqixfYd)fO<4}TcGV6#8d8ZqaW&e{wN!FaZBqSmu7Pxym11pzSm8S$kG=q7zkXTxR zND*H3Qp#k?!dV#L(2T{Gy-}--87d1K7}FDvDA@v#!bgEJc(*GLB(0auUh z`O66W0MnHszJtTZ#l5*w47;pU55>N3D$x*?e)#Yrch0Z&()=)%ie?4TbB6B*;z^L_5)u+p9`EfIoGSZX-ZVs^=*4XvhvOah42w{d`0uBuA zR#gU~Z@I?~+VCh)fhZ-=oiex8%r9}NR3702$dzTAvq>{!3m_>fA+v>6f;Hve`lkNc zU(DI4Z9yP z{N1LZGVi;!;7r6Mo?C+QHUGEJ{?WM8G)f+_2%mL>MWWa_Yt8t)xuf z_LumW2m!{H2oQwXtqH{@l29^>=cv?R$rQOc4_I?mh_|zKR5_8#*q(WK*zpG%CXUmi z*TGQEy)vR300~OlT~hEQnBG19~{ zNMO;YX!=~L;(6mWZ#K+PK&Pj&i?NqD{A zn!Mv(AismnuihewViOo??>xj-3d-tzWIIF8MPy~pFr z>K8j!v79)`w#={$tRnT@0^F9{#?VV(R#%HjQfoTw*bx*@PTRymbL)&y@n}1n>n9u_ zUXm0VGoloVgavydBpEW1Y2j?iPJ^=K25i7IFc~>$;Z|=RNWrqSK;}w_QP9+@Pe%a6 zX3Me|XlSUhXhyR(3g1DYEZ&6qV?S0o47cyc33`hK=7T)|!`(*tGkKN9yFHZTnF0SOuI4o3MZ43`bpfd^Rp3)t9OZq;imt~q zA25;th8j=xObA7YjZ)j`2*R5!Mk`Gdm_EFGZ_W@5mJvb>JbrYxRP|2iTYr7N(6se# zq*)tM?iDawOGWgZ!JhlGJ|-d}LZQ-C=dcfno;@S?5eyW;hGs@z*0Cx_+&9AUN*0(K zdub19hD^{9R~;we*aQO9-t4p6MjU2eh-9N1-OO#EQBs+9OeYw|gd|~U({f2@G_WS< zaHP&CKxPNl7`CiF&FML?)Nqp=s-OVqz-+TL0B|U?vdwh{3?`pFB*UQ2eEBQ|VmRGf zeQ3;{04D4oY(^G04Kj0z$%N+kQ)G$yq%t%2+>yvktJr%u$;xxhh_x8kMarxbR+{)E z2A^I)X(iNakw|bRFl9v(GPe=?9av`|<1#H8X%XQKMld5CFnL7wlPy`jy^t9Vtx)xr z(IXaLs~M$^+z`E*k8hZAR3@P&r#a1ls0qheGn0JmKN=4HBMw<6`Ji^wyi0|-}_vUZzx-tp>4BVQv^U=L#v;D2;t4Q<+L*~+2 z%rS7^?a$Ab-f&vB{_C&)V(q-XTrHVxqXg|4u`G+puq?9G@|xAnz=|@3v`QOIqn}w38B#(B*`seeqVIv+ zbn3YUvWF_eF~w~(pQUDeTzeNnDFuxx(=1`kbt=NlpoEOgdmR6I%sEzj+}RwCG7<;( z1s4FLoO&3mo0pqaF>$hh5+KY)W)&FJm0JPIWRemUj8HHY+C#l(#9;k}G62d^Ob615 z>@~BnHb@OM7~pSYGBQDjxzkM%)!3O?y^MA01yEgMykSYK9+?p$$I!}KEPBAZY14*j zp^ES~hK|jC#RFZ8@b`-_;>)PwZTxZjHIJa`?nqS{>J~8o7{$x_Sew%*>k@_8*Tr$W zI&=^fZ|Yz7`N3O;@OEKk>h7YHnWfR(E8{8(!eej@YAm(JD7LYqY?7-0(&omkP|gl? z1%b-UbOK65E?1uWns&j;tt}A}Ol(TOs&DFxyO}jx+P1a4h@J_fArpc;YLv2wWEjAj z@IKICaW{w00s!hO0Fi_vdBrHD}rHjK=CYPm3}VOu9wkoX=u}A>-K( z*KxcP=O5i4hU2W1u{m%USmK|g5TO8dYHKNgUb(+2c1Gmpr)7OupJMywXAj$T!};Mi z&UltB9NUx#BeX!-Gq&toT(xPxK@G-HGVt+DU@69v26i`uUVrLeXJIzW7iSJ^Qf_E zIw5cv-NGWr7UVbrw;axRm*d^$0^a~_K$5?#P$3u090O*#vo_NF^kULrCS&Fs@i0_% zL9Bw*ATw91tdZU-Py`$>gV!X=N~T6`K=ud#Y;9k+V661JU;2z_j)rM6w?;npwfN8_gIE6j@Uo< z#p9sd!j#)fN4EV9D4E6bJmL&NtmM}1ZwC4pC|Dzw8xZnVAUnR#qs}^RsMM0i{f)aN z5%+&J>Y{nXi-Xj1a|<(`7+E+L!?or-)&ObF%}dg0zkL7ISACIP==O)^{OvzxZXH`@ znlS(oJ-cN@?#L8#N6(ShM|4SadiIf|Rt{OOqI`~gEleYuHWE~0!~sEenF(CDM8?cz zk5tQ%9j&Bhty)SlCDULA@7e(Xrp$wNWUW+|qUCO=hMMdz^A|9ij<+R9vM0!~Si1fj6aJZm7u1Bs!!m_Mz_3RCe@I5yM z2zpU65<_er7<}1^JV#9w0g~pUafV5l%-y8ynKf~={<|oQZtKID zWMt3kbp(s%2C&CgKu5*lN4BMz&0Ja$EJohOGWH0o{A3x3Qo|ifGl(E%lcc*};Ej2! zm7PWGx!7jr&Ckn;){2OenbbKld-PNXeDNm9$iC-x2}O;DC9D={>AaTk-M33>LALSNjxE1R=#^ah75XRp!i!Y0vnmw%NhlkUX@keiMY3C*2Xbz)_ zaOO>BvP!v_nXiwJzII+fe{CmYtLe%KE9;5ri|-=v<5`Y^W2UB<#q>MFIo--t_ZEn^ zy>wfA-7T`lF1g`}GBcN4nSLv0^=X3$j%dp%||je0AU87RdNy_nX}w>|H*S> zX(oO+p7i8ApadstN7~2{dFEfAo}LUQOK=yM+GCfw$r!F^qA@)w(pNhbx)BB1t{&Qv zs{%s%OUlZEl9vmX1)UxkK4=jGZnO7GMYl6Eu4BX6D5dt{Rb~ zoqJ{cAC@PWB6bSfzU})?u?8MBwzVyl4n6r2$WX`33pvbMD@57cmD*xgs*1tBwq;$+ zngGKh@p5?u6%mzGbN9AdWEefOlSHOrbk+BaKv2ERbUS%K5S>tDj6O97?X)h{cVSEuUjZaFT>ow_vfp&?VnYGo~~#9-@C8B`sx>diHroCmVu9-e%!Zf z9W=A{^!Q}0m14-t^XF{~77}!a-I8H4lfPU(?%QT?nn@9n6BCQ>oU)k1mrGDD z5rVd?%d)`C+01S4mzURPuPjmm&A$5j=YDbsX0~tp$De-m*p$_KfYa%TL`Hz1_!0 znXhi8NMSYNI=Yy0uvJRetjOhqDRETL?qN(BqLFUQTTyHlI3^sy3>SG=GQ#T*XVbBc zDD*B${-OHhnQsgxo|op4%_!%rSx zZ-2nsk5&0$VC4TXVONgEBFQ+Tp95$NjH4r(Ki1F8gwE!r*xub0^nOk4a3orKovb9M9BOqhT7pmD?`cynfs zvv44o0cH<8J5SNzVcx#(c0#3pZu!@l{2%*aZh#vp0i%hZnh{B*??=T;aBxnM<~Xwh z5?2pw`S?V&;tmKSDwRHXvZLxaakI)y9y3r84_QoNeoC%9YoM zw9D3?x7cV4Am;x4 zS=@U`Z8^Pr{A$Mzp;_Da?dAG;tk(qpKqamcuC}bzGq16cs8ne&G&?^%y@MwdhUMk? z^YhCGRuPQ+o4@+?&%gQkHD4s0+v)k``P)By>m+FryPw;;hj(cbwRnrGzWd>KG8xU# z9@h82_~kD^MntoAy==d`{3g|_NM^A2?|%09^gh`os3=M`O5QxS?fW0UM7aCB7 zI}{^9Kn)T#Yt~3-^iGQrOw|mO1Wa^WymgHFr3_(RsRc_ljsXcZ2{uT&S;DEDo^6yE ziOSmnQ8Aq|6GTz4DOQ>Yl_MGvTxETV6_BG4ZxR(b%eQ5>SR&oC+A5(F1kDCv!Uhef z_)|2(QZR4Ja#B?pTWLoPYSe@VRVAI)N{4wJPGGD#X-03hET=?}F#0$eAZxB~%9ylP zwEiBt^iE>iQl^fy#kcJO$i2}U2^d>Lz1W-yre%+-o62*VS?}HGsPyn5^~e@TI23WmUrqE>bF6e&F*DT8(tOV4KFgTreDT=$cL}GF85$m&gWxk0uZQ70 zoWUrs6@`IIJ3q)4$d`02`@RGHa=Cosj?==>hieP7r-$=(zwE}H*BzPv<;+6t$jD?@wPnu1_!rtjE^vnh$(At>?rZ(H0?X zXQJ5_d+)LJeGe!j;@SgzlIl|!rPkDAu%(1c6@)}-6_act0E3| zrb-xK7@ZViAcbtr(uj8Ied~yD1(6v-m$CU$s%L@)V`uyyAHMth@Bi?ZkMIAhU;NF# zIDK=yut`bmeS<`)QoaXzC}krlYixyXcW;^{K>$eB6Lw?vj2_Br>#Ne=I0=>78s!>* zw4qZvxgeU`b5bHSkjB6jIrjNM&6y#i}Bx&XlOARiEv_Ro;SL}kEOLNQZwJm2Q7W&y1OE)>9m>}xv-PPbS zbC}!(FguhccPsjTlpA_2apmVDjgUM7 z(oLGYSkIo?_xjAkTyRF`Stv}B^CmVmUd2|o0Qb5Eq4X6pMO!i0ydrF~;zi6*n*|0|s}&;t_+ z<-oxaeej0cVA{_}DG$pv@`y9Ao&e}ggm4Gf1thX(M!D}Igw+7`@-=BdqdIHZd(xsLi4~L#-nbYnMvWy) zZviq5U94M9B$Y;zZe&Tr6;UgT05;5X@fX#G2V~X*kHkSzsr&4Q1_ zS=dBnS4#qM9E)*=he6BC9y<(K0tr5Zs)q&5(H^D)I87&UB!8qMn*z#BE=3?F1RRWR zr)Nz`1tofr3T~f5_7v)ycj0jO}4r&ks*e-~9Z#@&WFA)V7Q47lDGIKdj5UpSOqRvAEmW zX!w76goiO(Y%ToZWsgu?KY!|G@76~u5)iR5UtV@}`gytRXg_-&PfuN~k?=+P<0pLk z({=yF9u}b6L(0@BcFW z>;^`E;2rLRSWpqeh%|Mi&4%C8qz{-gfL>+KfqN#kYd%&U&aRfi?q?DV$33F^ z(cCLABX5o#BV9S2_VnkqR3tNHmh2T#2NNckx!Gb17uw@HKR;r@zVBLq7pHh$PfBAa zzk1wPDoJQ}e#-0bwhteum&?mvFZ{)7CoLh%>@U&NO}mQNnG!U1Z}eVgvYgOVI-TZg z!1@@s9F5?qQ^li*N>8SK12Nr(zS#_{lPdAmECf7i7- z%Ws$-*Q}O@`YO17a=DmnxE@U1;zO^mJ;v10FXH&m2m1bMz zy6Qm~=0r@6F)9+E5GjMJW(FH6OGR-#l|!Ck=uJ(CIvOcQjvVHOCdR010uZBTKf9Yj zk?pi>1}4Mlr}M(1h7c$QI@KA^sy#{XsRF$0Dbt^5jxm3hqa)Q>NRo>j^4NE7ur{jB@-Q6u=niO z?IHsuUzX^5v&G<0ga$GYV9=h|y>G?`r|)^GvJYe|mQJIThBmCOV(iN>Adp2Sw<7Un z-@A5KGq&h^jt+`S4@@R%aWKpcl^4Zi{2eL-gjJ+Hw=?e!AB0;8>~<#j#W&`xIS-M& z1dgjaNK7*#0GOeT+@##(UV0V0@lr_#vSv*<7qQa^@U-D+IH>qFkBY;Svs42Uw8n(N zlD#yeflMr0X)w|2pV8ei_#g+uFBGOC-;5+`%G@%;L?!wqSQ>*4^?Hj;ipkMPQ*8c+Hc|#-8ra7$v$~N4 zRLtv9!^W_=rc9Sx^^{mOWY*-`n1iNniJ&5D91x#{tOm@iy-+Jr`Sw~Z9;bxU({eQ1 zM<(eoZ#yE`e!Rpt3$M@JR)2wij{IT2T>BQW{cL^uxNjd`J}z;xug~9ozI?py-(5c1 z>#51EKmPE?Z~yN{_Fw<h{wfK?Q22o=Jj_flxL5q)a$cu+iaQ<|LK*^89Ig zeI2c~w;rD^`8(hGwkczKTz}ko5!J-X?gz-FPFcd z-o4=Av2D@!^Lg*5v`q8b*Q6n5Q#EITrnsGun_H1IMtTf{5Az@}2TOg}zY*O)nO<(p z21A!s`>o(!C6oz_4mjD7Jej4DnP8jtSU3AVW5T)Bg<~cO=Yk!Knl|ISk~N}PL>{bS zNlMf>$I1g$F|;;|MuvkB>=^A;iii=_aG6^xMq>@2G;0(TB9P+JR--F&Z4cSq(iJdg zkD$`bV1mNjIdTniGLN|Ma&473Q2T#bd$(TMlH*M5i^!^dnxr_Ru`v$@{AL)KU+f>? ze_+55#=th<7eD#I7#PsNu;!wX2t%Yqw#e?Ych$=H{1BInT&wo!mNiB8*;VV3m$+v{ zWaMCYlw092UzDv9qav3=h|3y^Cxk{m9v@$S{5tJ$7b^&IdQ~9mz%d^mUy;dcb3TyO z$pngn&mTVsn>1CiX^eG72#4o9#MBFb(~|~0t3$wJzJGkBOq*0yJEldoK_M_WXd)_R z^Fb3%V;(7Lxx6sfejv5)llHxVASgjZ-O54I56D~a~JMVHOdf@UZ+j~cwK26l%X(l`_@Rx zT!O<3j+p^`J|2hz&Je4y5OwaywddnQqL5nbV>WR!Z5SsY(}cna6XN~-2hJ$l?dJM% z93S>|KAtj62>G)=|Ii=b|M(B@fBfC^@#C2G`1;_$fBOCJKW=l#U586ZjTBlypavmr z$RG$mnBE1EQ8>w|w-MNbnoQ$Nd!Hh>zr9KLA#~_C=98gFNyF`SXQn*6y_x<(0KRU5 zD_Wv_Pad~09Z_N~bT&C6YKnPGxL;hT9_WDjz@C`D`SI`myZ_~X{4c+J_lDbe!=L2& zyRXj=dqDMg9>4wLZ~x6-{aid<&u_C4(Ro%|jj z|N1}u#sB`BznmY(P46nW-M&1GzqR)tjMFfl@;(0kzyIC8fBUfS?)P8ZzMC?>AJ2b~ z`S{?S`n#w7$G`da{CXU|Abh+1QEdGBepAR8hfR(1;h@ln%V>OY|Bah93LT=P9mk;_ zZgvM}9ZKX&q%eTomhyf3V@`|uD~O1XG0HgefY}rk0=N4uHMqfK&I16T8g>q#u;T#n z?|$=_fBDz{cIeyCo4)x$&YW}dc-{^F!~gle{%^d`X%qao>mTIfhv&yJs0Zb7{QhtL z?f?AUKf^&1$4&o$=ifa3;T`kOBa{GT001BWNklCkZ-UMSeN z=*)RoEFbjo@uS>*7lQanWw&vQZO>i|Cij&R@NJr|+#}ArGNnUDBCH;caZ8t|@6nO}Z2z-3J zfB$#CgTf9Qw;RnqzJ8s@^jZG?_rLr8hwnvjyWKqO0mEI?j^q8~kKfyG|N8HL^F?6C z^Vh%nZjSGMXMcL!?CoamTVd?n9lrTo#dA;1z{B@u>k#NoRH!uMkq++X42M0#$|t6Y z+=L=jrG}FA)rF@3r=!QMXg`$H=Esju#nbH)FAC@>NjhORc|0a@z@RcXg*FcoMu`0I z`#=3&{~k9vY~E!2`1SpHJa4y~kS2Pwn|<)$b7J0)JDwCBgLx#-p+A2AgWUf#=TyO* zoX5lLkjMg;$NPua_a=uKT%>s7ws|s)&D?V>G6&w3!#?nU==1UJm9{*aNGJot&j>l( z%j{)7{EP~4+F|DQZUlcCJD-#=xTE+s9zg6`^|P;C)VizCk#Ub7@U*7=JIlAk@x4a03hZx_k}{ja8vPF?6VoA-6GxyR7GNd>rqV=Z}hvp||_E zL6w{;Dk|Y7BNJ;^`-5jEqujWLE>T5bU!^RQ|2dB8K*bll(WUY1itk9i!= zhYnRU9PO$GF{pegB0#Zt~TRceCS00iPewUyrwc z@ykE|v-|k^{_%0lgCBqQ@h3Z`ijJYjJg746cgo;AIOm^#`Sq{#i-_q>zdm>f|MdI; zH~lYu@y~SPcs_^Xb{|lEpT{3RzH+>oLMG*S$Z?E``YaBzZakntU}nehI6e+QymsFhqY_)^G>iRBcE649zWas4%q&vrJhF^*wV^g| zso0!0r<+vc?x%{1sB+E;JLZx3ZDO>W-0t@`h=KD9psfX!d zLw|AqPKl3?AK%_?kNG?vB*w>aJn#6(lW;P4$DxB1ug4?`n-s-;+bTI4^5Z5ikLy4%JqPld5@yA3xrkNGs3aYnUT@TNDa z++-LjN}+mPa@9KoG`Zb}@5eUb{dRx5zZvau9LDJ`B7saEFw+MnCixV-i41*H=xty? z)DM7*G>ZtJhhp^P*9gF<&UvIDio+kxW(Mo2&^hNZp94Y)X{!3=%dbohqbY8aPn*2S z@C0gxquRZyVrFwr(8Cn&0vbbAhaR+>DiqV6AQi)=eLTOajhl|A9Rhe2#0h6ys;KI1 zcu7ApO8AKv1-KE6oD)Bi6IMBAA~%{13|IZ07#Qk}5gw&eeWb#uLR4>JG}!HS1H7E{ z&E~;rdB7Yo;tVWN^?El3k~YTh6LM7e{L}ki{oj9Kj}NGfIK_D_#Nsb!s{_=1K+eX& zF+!VmJfq4sIgiKV`5tBIsBhzKV3a!=qK4@Oabo|!MSxu3Y~#Cx=!PxlLopQUC+hfl z0m$YAqEryM_0bD{I8Az~%GjTn+0(}n%P<@8S7U8IpgOb6svmkv7|eYVE*UiTTt!&P z#mDfRvxxzLO_H2^(x6kKl$_g;DvTYBBz#{XTNIom#C^OfP!Ce8Xj=UT(?s=jN78H_ zQR}D@S)8Rjr`T86?qXpUB`OCuIyMEwoX-pksX$UD!W~^OdR;*w=X}CUAcq{ZIO@p2 zp*oL)m=AJ7hbqP$VwB-wZ`{T-n|2H*cX!;n%Q*vB?%gyyj2_-Ly^Z_eZQQ2$87?$C zJlWla-gMw7gb_BGc5wP}n>$|8IjfaA1j zB*%UDro z5A*TE<8Qya>s`Od?e=`ga}Ia{B*)Vxsgs_PehBf0kFP(-`vC8^HyXbl$JhCx_wlzM z^Gz}BFwAjN$o+B5ua6JG{mYjxD&zThzpJY7>+|ue`wfsEA74%NyK%FL=f`81J@7tc zn8*_k<2^(eR3VcFiz9n%(B(CezV*oMa0`>iF+HKu2+u}^ANJz4Ml@1vjlTXP0h{I# z9*F|>VeU`&>;=Y&n>%vjB(4y)A+vjP>V7P9`^weHtVJdWrP!Q|#moe$sm?t}`!t)tGdYUUpo6|n{U=&qw<4-Jf32d0^jlPljc0cA}^Lg;_Wx8s) z=WD?#lIj$(FwO7`A~GdW%`X&&10=BFW%xLsKmOiZ$TJA!aD+m~xWx`cFcKz(8o?e4 zWk5XjLIF;y$uJFvAZ_pl$ednf(Mz1&Mnpd~vW5ez^MFN7Es;YYLk@Y$TGoWR83K=f zGxq(!123Kyh}gX=Fi}bd0%@>0AMT8t&%Me=}bok8`SIx!+@BV*>FtD5E?|x=Ere7y``^A z2zeeKw5c)#9^1S}8bBJR?%<(J_!jpF25Tj?FrKK4Zh?V*_-usQ(h&u5|GKKEn(8q3 z4Js^ZZ@MeKHV!+lx~F`2uBBIr^pp-G8PZ7(cRkS#drTg84AEipskqsk$DD<=^rojM z2*t)B!-*9FntePzU^whK&0wOc;}*J*z?_H8L+9b!NX!oU;z`0#c7t(-88hu+;V2{3 zO-)ATJ0izN02ulFcpN&sdZ$-$jL>OBy?7iEdhm4yCj`DLP$xObA3i?h`Q)VUOqtUj zkFO%~@t8rCJX8k;+%-PubVtF%?1$q}-$OtgGz#sQDn{Cq4~V;g-blPZKEzB0X+I1Z zI_|_cKJ16*4dQvLYojijvt5UyE~Sr5PW=m#XN30 z@b!31-hc50qQ|sp2M((5{+N?uszW`lKoP*Enfonhs;WatK97h~v+^$aJq*TA|f{J`FtMs6o~3gCC(?m z>6jvacuonD9yIyj`$0nVIS(P8$5+Keh6>)t+nd_$Igf`uj5hTCiwT(g@c7fiooL!K}kb|_^=Ep0h4Q=_?G6u!6A1eowmF>^lX`U}G66q6{R=f?)n zsKbvfLr4UdWAo$ru7~=v)oem2w~$wsX;{SJW}>fD1t2CeD&Q#!kB=upinybN0`V

hkzmefBMhXqU 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

`o+RtBmF~R= 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 Date: Tue, 22 Jul 2025 18:02:11 -0700 Subject: [PATCH 104/602] fix: Pager throws an exception if list request returns nothing(correct behavior is returning a Pager without any items in it) PiperOrigin-RevId: 786068859 --- src/main/java/com/google/genai/BasePager.java | 18 ++++++++---------- .../java/com/google/genai/AsyncCachesTest.java | 2 +- .../java/com/google/genai/AsyncFilesTest.java | 2 +- .../java/com/google/genai/AsyncModelsTest.java | 3 ++- 4 files changed, 12 insertions(+), 13 deletions(-) diff --git a/src/main/java/com/google/genai/BasePager.java b/src/main/java/com/google/genai/BasePager.java index 33d026b540f..6cdf197b7cb 100644 --- a/src/main/java/com/google/genai/BasePager.java +++ b/src/main/java/com/google/genai/BasePager.java @@ -19,7 +19,6 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ObjectNode; import com.google.common.collect.ImmutableList; -import com.google.genai.errors.GenAiIOException; import com.google.genai.types.BatchJob; import com.google.genai.types.CachedContent; import com.google.genai.types.File; @@ -99,17 +98,16 @@ protected void initNewPage(JsonNode response) { throw new IllegalArgumentException("Response cannot be null."); } JsonNode responseList = response.get(pagedItem.fieldName()); - if (responseList == null) { - throw new GenAiIOException( - "Response does not contain the requested item. Raw response: " - + JsonSerializable.toJsonString(response)); - } // Sets the page. - List page = new ArrayList<>(); - for (JsonNode responseItem : responseList) { - page.add((T) JsonSerializable.fromJsonNode(responseItem, pagedItem.itemClass())); + if (responseList == null) { + this.page = ImmutableList.of(); + } else { + List page = new ArrayList<>(); + for (JsonNode responseItem : responseList) { + page.add((T) JsonSerializable.fromJsonNode(responseItem, pagedItem.itemClass())); + } + this.page = ImmutableList.copyOf(page); } - this.page = ImmutableList.copyOf(page); // Sets the page size. if (requestConfig.get("pageSize") != null) { diff --git a/src/test/java/com/google/genai/AsyncCachesTest.java b/src/test/java/com/google/genai/AsyncCachesTest.java index 0daf92a56b4..7fce66c3cb4 100644 --- a/src/test/java/com/google/genai/AsyncCachesTest.java +++ b/src/test/java/com/google/genai/AsyncCachesTest.java @@ -136,7 +136,7 @@ public void testAsyncListCachedContents(boolean vertexAI) // Assert assertNotNull(pager); assertEquals(pager.pageSize().get(), 2); - assertTrue(pager.size().get() > 0); + assertTrue(pager.size().get() <= 2); pager.forEach(item -> assertNotNull(item)).get(); } diff --git a/src/test/java/com/google/genai/AsyncFilesTest.java b/src/test/java/com/google/genai/AsyncFilesTest.java index ed8117a1c2d..f21d1e64e1d 100644 --- a/src/test/java/com/google/genai/AsyncFilesTest.java +++ b/src/test/java/com/google/genai/AsyncFilesTest.java @@ -93,7 +93,7 @@ public void testAsyncListFiles(boolean vertexAI) throws ExecutionException, Inte // Assert assertNotNull(pager); assertEquals(pager.pageSize().get(), 2); - assertTrue(pager.size().get() > 0); + assertTrue(pager.size().get() <= 2); pager.forEach(item -> assertNotNull(item)).get(); } } diff --git a/src/test/java/com/google/genai/AsyncModelsTest.java b/src/test/java/com/google/genai/AsyncModelsTest.java index 861da83f539..1407578a7b4 100644 --- a/src/test/java/com/google/genai/AsyncModelsTest.java +++ b/src/test/java/com/google/genai/AsyncModelsTest.java @@ -135,7 +135,8 @@ public void testListModelsAsync(boolean vertexAI) throws Exception { .get(); // Assert - assertEquals(10, pager.size().get()); + assertEquals(pager.pageSize().get(), 10); + assertTrue(pager.size().get() <= 10); pager.forEach(item -> assertNotNull(item)).get(); } From 528277406279d772c01ac2a48544962408ac235b Mon Sep 17 00:00:00 2001 From: Jaycee Li Date: Tue, 22 Jul 2025 23:01:20 -0700 Subject: [PATCH 105/602] feat: Support http headers in GenerateContentResponse PiperOrigin-RevId: 786144586 --- .../genai/examples/GenerateContent.java | 7 +++++ .../genai/examples/GenerateContentAsync.java | 8 +++++ src/main/java/com/google/genai/Batches.java | 6 ++++ src/main/java/com/google/genai/Files.java | 9 ++++-- src/main/java/com/google/genai/Models.java | 31 ++++++++++++++++++- .../genai/types/GenerateContentResponse.java | 21 +++++++++++++ .../java/com/google/genai/ModelsTest.java | 1 + 7 files changed, 80 insertions(+), 3 deletions(-) diff --git a/examples/src/main/java/com/google/genai/examples/GenerateContent.java b/examples/src/main/java/com/google/genai/examples/GenerateContent.java index 6bc8f357c87..2fd163e0155 100644 --- a/examples/src/main/java/com/google/genai/examples/GenerateContent.java +++ b/examples/src/main/java/com/google/genai/examples/GenerateContent.java @@ -72,6 +72,13 @@ public static void main(String[] args) { // Gets the text string from the response by the quick accessor method `text()`. System.out.println("Unary response: " + response.text()); + + // Gets the http headers from the response. + response + .sdkHttpResponse() + .ifPresent( + httpResponse -> + System.out.println("Response headers: " + httpResponse.headers().orElse(null))); } private GenerateContent() {} diff --git a/examples/src/main/java/com/google/genai/examples/GenerateContentAsync.java b/examples/src/main/java/com/google/genai/examples/GenerateContentAsync.java index 3915a3cf4d2..7f180d9197e 100644 --- a/examples/src/main/java/com/google/genai/examples/GenerateContentAsync.java +++ b/examples/src/main/java/com/google/genai/examples/GenerateContentAsync.java @@ -74,7 +74,15 @@ public static void main(String[] args) { responseFuture .thenAccept( response -> { + // Gets the text string from the response System.out.println("Async response: " + response.text()); + // Gets the http headers from the response. + response + .sdkHttpResponse() + .ifPresent( + httpResponse -> + System.out.println( + "Response headers: " + httpResponse.headers().orElse(null))); }) .join(); } diff --git a/src/main/java/com/google/genai/Batches.java b/src/main/java/com/google/genai/Batches.java index 265e508011c..d0c5aadf02d 100644 --- a/src/main/java/com/google/genai/Batches.java +++ b/src/main/java/com/google/genai/Batches.java @@ -1856,6 +1856,12 @@ ObjectNode candidateFromMldev(JsonNode fromObject, ObjectNode parentObject) { @ExcludeFromGeneratedCoverageReport ObjectNode generateContentResponseFromMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"sdkHttpResponse"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"sdkHttpResponse"}, + Common.getValueByPath(fromObject, new String[] {"sdkHttpResponse"})); + } if (Common.getValueByPath(fromObject, new String[] {"candidates"}) != null) { ArrayNode keyArray = diff --git a/src/main/java/com/google/genai/Files.java b/src/main/java/com/google/genai/Files.java index a2ccc92cd1b..f3f4bd14946 100644 --- a/src/main/java/com/google/genai/Files.java +++ b/src/main/java/com/google/genai/Files.java @@ -596,13 +596,18 @@ CreateFileResponse privateCreate(File file, CreateFileConfig config) { } if (config.shouldReturnHttpResponse().orElse(false)) { - Map headers = new HashMap<>(); Headers responseHeaders = response.getHeaders(); + if (responseHeaders == null) { + return CreateFileResponse.builder() + .sdkHttpResponse(HttpResponse.builder().body(responseString)) + .build(); + } + Map headers = new HashMap<>(); for (String headerName : responseHeaders.names()) { headers.put(headerName, responseHeaders.get(headerName)); } return CreateFileResponse.builder() - .sdkHttpResponse(HttpResponse.builder().headers(headers).body(responseString).build()) + .sdkHttpResponse(HttpResponse.builder().headers(headers).body(responseString)) .build(); } diff --git a/src/main/java/com/google/genai/Models.java b/src/main/java/com/google/genai/Models.java index 8c6f1454e40..914ac3d0d61 100644 --- a/src/main/java/com/google/genai/Models.java +++ b/src/main/java/com/google/genai/Models.java @@ -55,6 +55,7 @@ import com.google.genai.types.GetModelConfig; import com.google.genai.types.GetModelParameters; import com.google.genai.types.HttpOptions; +import com.google.genai.types.HttpResponse; import com.google.genai.types.Image; import com.google.genai.types.ListModelsConfig; import com.google.genai.types.ListModelsParameters; @@ -74,10 +75,13 @@ import java.io.IOException; import java.lang.reflect.Method; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Optional; import java.util.function.Function; import java.util.logging.Logger; +import okhttp3.Headers; import okhttp3.ResponseBody; /** @@ -4312,6 +4316,12 @@ ObjectNode candidateFromMldev(JsonNode fromObject, ObjectNode parentObject) { @ExcludeFromGeneratedCoverageReport ObjectNode generateContentResponseFromMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"sdkHttpResponse"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"sdkHttpResponse"}, + Common.getValueByPath(fromObject, new String[] {"sdkHttpResponse"})); + } if (Common.getValueByPath(fromObject, new String[] {"candidates"}) != null) { ArrayNode keyArray = @@ -5106,6 +5116,12 @@ ObjectNode candidateFromVertex(JsonNode fromObject, ObjectNode parentObject) { @ExcludeFromGeneratedCoverageReport ObjectNode generateContentResponseFromVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"sdkHttpResponse"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"sdkHttpResponse"}, + Common.getValueByPath(fromObject, new String[] {"sdkHttpResponse"})); + } if (Common.getValueByPath(fromObject, new String[] {"candidates"}) != null) { ArrayNode keyArray = @@ -5805,7 +5821,20 @@ GenerateContentResponse privateGenerateContent( } else { responseNode = generateContentResponseFromMldev(responseNode, null); } - return JsonSerializable.fromJsonNode(responseNode, GenerateContentResponse.class); + + GenerateContentResponse sdkResponse = + JsonSerializable.fromJsonNode(responseNode, GenerateContentResponse.class); + Headers responseHeaders = response.getHeaders(); + if (responseHeaders == null) { + return sdkResponse; + } + Map headers = new HashMap<>(); + for (String headerName : responseHeaders.names()) { + headers.put(headerName, responseHeaders.get(headerName)); + } + return sdkResponse.toBuilder() + .sdkHttpResponse(HttpResponse.builder().headers(headers)) + .build(); } } diff --git a/src/main/java/com/google/genai/types/GenerateContentResponse.java b/src/main/java/com/google/genai/types/GenerateContentResponse.java index 4cf2b44b377..c00a72a4b02 100644 --- a/src/main/java/com/google/genai/types/GenerateContentResponse.java +++ b/src/main/java/com/google/genai/types/GenerateContentResponse.java @@ -41,6 +41,10 @@ @AutoValue @JsonDeserialize(builder = GenerateContentResponse.Builder.class) public abstract class GenerateContentResponse extends JsonSerializable { + /** Used to retain the full HTTP response. */ + @JsonProperty("sdkHttpResponse") + public abstract Optional sdkHttpResponse(); + /** Response variations returned by the model. */ @JsonProperty("candidates") public abstract Optional> candidates(); @@ -89,6 +93,23 @@ private static Builder create() { return new AutoValue_GenerateContentResponse.Builder(); } + /** + * Setter for sdkHttpResponse. + * + *

sdkHttpResponse: Used to retain the full HTTP response. + */ + @JsonProperty("sdkHttpResponse") + public abstract Builder sdkHttpResponse(HttpResponse sdkHttpResponse); + + /** + * Setter for sdkHttpResponse builder. + * + *

sdkHttpResponse: Used to retain the full HTTP response. + */ + public Builder sdkHttpResponse(HttpResponse.Builder sdkHttpResponseBuilder) { + return sdkHttpResponse(sdkHttpResponseBuilder.build()); + } + /** * Setter for candidates. * diff --git a/src/test/java/com/google/genai/ModelsTest.java b/src/test/java/com/google/genai/ModelsTest.java index ecae6a390c5..62c2fdc109f 100644 --- a/src/test/java/com/google/genai/ModelsTest.java +++ b/src/test/java/com/google/genai/ModelsTest.java @@ -142,6 +142,7 @@ public void testGenerateContent_withContent(boolean vertexAI) throws Exception { // Assert assertNotNull(response.text()); + assertNotNull(response.sdkHttpResponse().get().headers()); } @ParameterizedTest From e5b769e54bf1cbb026b2fc65f5d46e6fe5c1c561 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Wed, 23 Jul 2025 14:57:55 -0700 Subject: [PATCH 106/602] chore(main): release 1.10.0 (#422) * chore(main): release 1.10.0 * Update CHANGELOG.md --------- Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> Co-authored-by: Jaycee Li <102714969+jaycee-li@users.noreply.github.com> --- .release-please-manifest.json | 2 +- CHANGELOG.md | 21 +++++++++++++++++++ README.md | 2 +- examples/pom.xml | 4 ++-- pom.xml | 2 +- src/main/java/com/google/genai/ApiClient.java | 2 +- versions.txt | 2 +- 7 files changed, 28 insertions(+), 7 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index c3c95522a63..eb4e0dba726 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "1.9.0" + ".": "1.10.0" } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 49b665051ce..a770a7362d1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,26 @@ # Changelog +## [1.10.0](https://github.com/googleapis/java-genai/compare/v1.9.0...v1.10.0) (2025-07-23) + + +### Features + +* Add image_size field for Vertex Imagen 4 generation ([950c0c6](https://github.com/googleapis/java-genai/commit/950c0c657f786039e3a301bf1237a57ae324ff62)) +* Support API keys for VertexAI mode for Java SDK ([826c0dc](https://github.com/googleapis/java-genai/commit/826c0dca02e06fcb6c7980259b23e955db176ec6)) +* Support http headers in GenerateContentResponse ([5282774](https://github.com/googleapis/java-genai/commit/528277406279d772c01ac2a48544962408ac235b)) + + +### Bug Fixes + +* Defer loading ADC when credentials is provided explicitly in Live API ([a540614](https://github.com/googleapis/java-genai/commit/a5406140aeaf9774265a5bcce79dae0707ed9287)) +* **live:** Enhance security by moving api key from query parameters to header ([e48c7f1](https://github.com/googleapis/java-genai/commit/e48c7f1e73dadf5c5198f9b58cea322deb7a4ed0)) +* Pager throws an exception if list request returns nothing(correct behavior is returning a Pager without any items in it) ([0a2301b](https://github.com/googleapis/java-genai/commit/0a2301b19fcd3e4d3694d42780da8f5ffe5f9207)) + + +### Documentation + +* Update README with latest features in Client ([dcf70cc](https://github.com/googleapis/java-genai/commit/dcf70cc64a93355cdc6a2eedf172399dd332750e)) + ## [1.9.0](https://github.com/googleapis/java-genai/compare/v1.8.0...v1.9.0) (2025-07-16) diff --git a/README.md b/README.md index fed4ebfc65a..dbaa7e1a39a 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ If you're using Maven, add the following to your dependencies: com.google.genai google-genai - 1.9.0 + 1.10.0 ``` diff --git a/examples/pom.xml b/examples/pom.xml index 3088a81fefa..e1aaedbf3ac 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -5,7 +5,7 @@ com.google.genai.examples google-genai-examples - 1.10.0-SNAPSHOT + 1.10.0 google-genai-examples @@ -13,7 +13,7 @@ 1.8 1.8 - 1.10.0-SNAPSHOT + 1.10.0 diff --git a/pom.xml b/pom.xml index 60b4b082e6d..b46c3cd1695 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ com.google.genai google-genai google-genai - 1.10.0-SNAPSHOT + 1.10.0 jar Java idiomatic SDK for the Gemini Developer APIs and Vertex AI APIs. diff --git a/src/main/java/com/google/genai/ApiClient.java b/src/main/java/com/google/genai/ApiClient.java index 07a6720b00a..cfb0a40d5f2 100644 --- a/src/main/java/com/google/genai/ApiClient.java +++ b/src/main/java/com/google/genai/ApiClient.java @@ -45,7 +45,7 @@ abstract class ApiClient { // {x-version-update-start:google-genai:released} - private static final String SDK_VERSION = "1.9.0"; + private static final String SDK_VERSION = "1.10.0"; // {x-version-update-end:google-genai:released} private static final Logger logger = Logger.getLogger(ApiClient.class.getName()); diff --git a/versions.txt b/versions.txt index 39faa71c483..05108f6cf71 100644 --- a/versions.txt +++ b/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-genai:1.9.0:1.10.0-SNAPSHOT +google-genai:1.10.0:1.10.0 From 7b52c38e5e6a4ceada8e92d6daf09f8fd1fc8a5d Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Wed, 23 Jul 2025 15:05:25 -0700 Subject: [PATCH 107/602] chore(main): release 1.11.0-SNAPSHOT (#443) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- examples/pom.xml | 4 ++-- pom.xml | 2 +- versions.txt | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/pom.xml b/examples/pom.xml index e1aaedbf3ac..aa3685b77c3 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -5,7 +5,7 @@ com.google.genai.examples google-genai-examples - 1.10.0 + 1.11.0-SNAPSHOT google-genai-examples @@ -13,7 +13,7 @@ 1.8 1.8 - 1.10.0 + 1.11.0-SNAPSHOT diff --git a/pom.xml b/pom.xml index b46c3cd1695..caea5b8c446 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ com.google.genai google-genai google-genai - 1.10.0 + 1.11.0-SNAPSHOT jar Java idiomatic SDK for the Gemini Developer APIs and Vertex AI APIs. diff --git a/versions.txt b/versions.txt index 05108f6cf71..91058d0cec9 100644 --- a/versions.txt +++ b/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-genai:1.10.0:1.10.0 +google-genai:1.10.0:1.11.0-SNAPSHOT From 932dde97fdd3b8816b8d9a750bb0be5000eabaf4 Mon Sep 17 00:00:00 2001 From: Jaycee Li <102714969+jaycee-li@users.noreply.github.com> Date: Wed, 23 Jul 2025 15:04:27 -0700 Subject: [PATCH 108/602] Copybara import of the project: -- d4b9dff38a87a05b96d0248b6b0f0959fdacee54 by release-please[bot] <55107282+release-please[bot]@users.noreply.github.com>: chore(main): release 1.10.0 -- c56d99b23c46cb4b8caa9bc2846a5fe8db3f21f8 by Jaycee Li <102714969+jaycee-li@users.noreply.github.com>: Update CHANGELOG.md COPYBARA_INTEGRATE_REVIEW=https://github.com/googleapis/java-genai/pull/422 from googleapis:release-please--branches--main c56d99b23c46cb4b8caa9bc2846a5fe8db3f21f8 PiperOrigin-RevId: 786438497 --- examples/pom.xml | 4 ++-- pom.xml | 2 +- versions.txt | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/pom.xml b/examples/pom.xml index aa3685b77c3..e1aaedbf3ac 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -5,7 +5,7 @@ com.google.genai.examples google-genai-examples - 1.11.0-SNAPSHOT + 1.10.0 google-genai-examples @@ -13,7 +13,7 @@ 1.8 1.8 - 1.11.0-SNAPSHOT + 1.10.0 diff --git a/pom.xml b/pom.xml index caea5b8c446..b46c3cd1695 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ com.google.genai google-genai google-genai - 1.11.0-SNAPSHOT + 1.10.0 jar Java idiomatic SDK for the Gemini Developer APIs and Vertex AI APIs. diff --git a/versions.txt b/versions.txt index 91058d0cec9..05108f6cf71 100644 --- a/versions.txt +++ b/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-genai:1.10.0:1.11.0-SNAPSHOT +google-genai:1.10.0:1.10.0 From 4b1fa2ea8157ee02fdcc811d48e61bdc862b4c2a Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Wed, 23 Jul 2025 15:12:52 -0700 Subject: [PATCH 109/602] Copybara import of the project: -- e5b769e54bf1cbb026b2fc65f5d46e6fe5c1c561 by release-please[bot] <55107282+release-please[bot]@users.noreply.github.com>: chore(main): release 1.10.0 (#422) * chore(main): release 1.10.0 * Update CHANGELOG.md --------- Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> Co-authored-by: Jaycee Li <102714969+jaycee-li@users.noreply.github.com> -- 84dc288812212ec8a3be10130c3acf0d0236b0f7 by release-please[bot] <55107282+release-please[bot]@users.noreply.github.com>: chore(main): release 1.11.0-SNAPSHOT COPYBARA_INTEGRATE_REVIEW=https://github.com/googleapis/java-genai/pull/443 from googleapis:release-please--branches--main 84dc288812212ec8a3be10130c3acf0d0236b0f7 PiperOrigin-RevId: 786441337 --- examples/pom.xml | 4 ++-- pom.xml | 2 +- versions.txt | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/pom.xml b/examples/pom.xml index e1aaedbf3ac..aa3685b77c3 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -5,7 +5,7 @@ com.google.genai.examples google-genai-examples - 1.10.0 + 1.11.0-SNAPSHOT google-genai-examples @@ -13,7 +13,7 @@ 1.8 1.8 - 1.10.0 + 1.11.0-SNAPSHOT diff --git a/pom.xml b/pom.xml index b46c3cd1695..caea5b8c446 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ com.google.genai google-genai google-genai - 1.10.0 + 1.11.0-SNAPSHOT jar Java idiomatic SDK for the Gemini Developer APIs and Vertex AI APIs. diff --git a/versions.txt b/versions.txt index 05108f6cf71..91058d0cec9 100644 --- a/versions.txt +++ b/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-genai:1.10.0:1.10.0 +google-genai:1.10.0:1.11.0-SNAPSHOT From 7415e88f7520c695afc63f937b8b547c2877f4f6 Mon Sep 17 00:00:00 2001 From: Wanlin Du Date: Thu, 24 Jul 2025 12:25:09 -0700 Subject: [PATCH 110/602] feat: allow methods in models to return headers in sdk_http_response by default. PiperOrigin-RevId: 786795974 --- src/main/java/com/google/genai/Models.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/main/java/com/google/genai/Models.java b/src/main/java/com/google/genai/Models.java index 914ac3d0d61..f12a7a9046d 100644 --- a/src/main/java/com/google/genai/Models.java +++ b/src/main/java/com/google/genai/Models.java @@ -4382,6 +4382,7 @@ ObjectNode embedContentMetadataFromMldev(JsonNode fromObject, ObjectNode parentO @ExcludeFromGeneratedCoverageReport ObjectNode embedContentResponseFromMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"embeddings"}) != null) { ArrayNode keyArray = (ArrayNode) Common.getValueByPath(fromObject, new String[] {"embeddings"}); @@ -4493,6 +4494,7 @@ ObjectNode generatedImageFromMldev(JsonNode fromObject, ObjectNode parentObject) @ExcludeFromGeneratedCoverageReport ObjectNode generateImagesResponseFromMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"predictions"}) != null) { ArrayNode keyArray = (ArrayNode) Common.getValueByPath(fromObject, new String[] {"predictions"}); @@ -4650,6 +4652,7 @@ ObjectNode deleteModelResponseFromMldev(JsonNode fromObject, ObjectNode parentOb @ExcludeFromGeneratedCoverageReport ObjectNode countTokensResponseFromMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"totalTokens"}) != null) { Common.setValueByPath( toObject, @@ -5232,6 +5235,7 @@ ObjectNode embedContentMetadataFromVertex(JsonNode fromObject, ObjectNode parent @ExcludeFromGeneratedCoverageReport ObjectNode embedContentResponseFromVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"predictions[]", "embeddings"}) != null) { ArrayNode keyArray = (ArrayNode) @@ -5357,6 +5361,7 @@ ObjectNode generatedImageFromVertex(JsonNode fromObject, ObjectNode parentObject @ExcludeFromGeneratedCoverageReport ObjectNode generateImagesResponseFromVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"predictions"}) != null) { ArrayNode keyArray = (ArrayNode) Common.getValueByPath(fromObject, new String[] {"predictions"}); @@ -5387,6 +5392,7 @@ ObjectNode generateImagesResponseFromVertex(JsonNode fromObject, ObjectNode pare @ExcludeFromGeneratedCoverageReport ObjectNode editImageResponseFromVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"predictions"}) != null) { ArrayNode keyArray = (ArrayNode) Common.getValueByPath(fromObject, new String[] {"predictions"}); @@ -5405,6 +5411,7 @@ ObjectNode editImageResponseFromVertex(JsonNode fromObject, ObjectNode parentObj @ExcludeFromGeneratedCoverageReport ObjectNode upscaleImageResponseFromVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"predictions"}) != null) { ArrayNode keyArray = (ArrayNode) Common.getValueByPath(fromObject, new String[] {"predictions"}); @@ -5617,6 +5624,7 @@ ObjectNode deleteModelResponseFromVertex(JsonNode fromObject, ObjectNode parentO @ExcludeFromGeneratedCoverageReport ObjectNode countTokensResponseFromVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"totalTokens"}) != null) { Common.setValueByPath( toObject, @@ -5630,6 +5638,7 @@ ObjectNode countTokensResponseFromVertex(JsonNode fromObject, ObjectNode parentO @ExcludeFromGeneratedCoverageReport ObjectNode computeTokensResponseFromVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"tokensInfo"}) != null) { Common.setValueByPath( toObject, From 1b1205b052a6d1d6782c6cdc190afdb48113ee9c Mon Sep 17 00:00:00 2001 From: Wanlin Du Date: Thu, 24 Jul 2025 13:14:56 -0700 Subject: [PATCH 111/602] feat: allow methods in tuning to return headers in sdk_http_response by default PiperOrigin-RevId: 786812268 --- src/main/java/com/google/genai/Tunings.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/com/google/genai/Tunings.java b/src/main/java/com/google/genai/Tunings.java index 37b417927cf..364c77d2a14 100644 --- a/src/main/java/com/google/genai/Tunings.java +++ b/src/main/java/com/google/genai/Tunings.java @@ -482,6 +482,7 @@ ObjectNode tunedModelFromMldev(JsonNode fromObject, ObjectNode parentObject) { @ExcludeFromGeneratedCoverageReport ObjectNode tuningJobFromMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"name"}) != null) { Common.setValueByPath( toObject, @@ -636,6 +637,7 @@ ObjectNode listTuningJobsResponseFromMldev(JsonNode fromObject, ObjectNode paren @ExcludeFromGeneratedCoverageReport ObjectNode tuningOperationFromMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"name"}) != null) { Common.setValueByPath( toObject, @@ -736,6 +738,7 @@ ObjectNode tunedModelFromVertex(JsonNode fromObject, ObjectNode parentObject) { @ExcludeFromGeneratedCoverageReport ObjectNode tuningJobFromVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"name"}) != null) { Common.setValueByPath( toObject, From 9f58fec1463c23d75356299de6410ced6a8b1f82 Mon Sep 17 00:00:00 2001 From: Wanlin Du Date: Fri, 25 Jul 2025 11:05:22 -0700 Subject: [PATCH 112/602] chore: update API key retrieval mechanism for easy testing. PiperOrigin-RevId: 787172850 --- src/main/java/com/google/genai/ApiClient.java | 26 +++--- .../com/google/genai/HttpApiClientTest.java | 89 ++++++++++++++----- src/test/java/com/google/genai/TableTest.java | 2 +- 3 files changed, 83 insertions(+), 34 deletions(-) diff --git a/src/main/java/com/google/genai/ApiClient.java b/src/main/java/com/google/genai/ApiClient.java index cfb0a40d5f2..48d5f3c7878 100644 --- a/src/main/java/com/google/genai/ApiClient.java +++ b/src/main/java/com/google/genai/ApiClient.java @@ -78,10 +78,8 @@ protected ApiClient( checkNotNull(customHttpOptions, "customHttpOptions cannot be null"); checkNotNull(clientOptions, "clientOptions cannot be null"); - ImmutableMap environmentVariables = defaultEnvironmentVariables(); - try { - this.apiKey = Optional.of(apiKey.orElse(environmentVariables.get("apiKey"))); + this.apiKey = Optional.of(apiKey.orElse(getApiKeyFromEnv())); } catch (NullPointerException e) { throw new IllegalArgumentException( "API key must either be provided or set in the environment variable" @@ -121,7 +119,7 @@ protected ApiClient( ImmutableMap environmentVariables = defaultEnvironmentVariables(); // Retrieve implicitly set values from the environment. - String envApiKeyValue = environmentVariables.get("apiKey"); + String envApiKeyValue = getApiKeyFromEnv(); String envProjectValue = environmentVariables.get("project"); String envLocationValue = environmentVariables.get("location"); @@ -479,13 +477,16 @@ GoogleCredentials defaultCredentials() { } } - /** Returns the API key from the environment variables. */ + /** Returns the API key from defaultEnvironmentVariables. */ static String getApiKeyFromEnv() { - String googleApiKey = System.getenv("GOOGLE_API_KEY"); + + ImmutableMap environmentVariables = defaultEnvironmentVariables(); + + String googleApiKey = environmentVariables.get("googleApiKey"); if (googleApiKey != null && googleApiKey.isEmpty()) { googleApiKey = null; } - String geminiApiKey = System.getenv("GEMINI_API_KEY"); + String geminiApiKey = environmentVariables.get("geminiApiKey"); if (geminiApiKey != null && geminiApiKey.isEmpty()) { geminiApiKey = null; } @@ -502,7 +503,8 @@ static String getApiKeyFromEnv() { * Returns the default environment variables for the client. Supported environment variables: * *

    - *
  • apiKey -> GOOGLE_API_KEY or GEMINI_API_KEY: API key for Gemini APIs or Vertex AI APIs. + *
  • googleApiKey -> GOOGLE_API_KEY environment variable. + *
  • geminiApiKey -> GEMINI_API_KEY environment variable. *
  • project -> GOOGLE_CLOUD_PROJECT: Project ID for Vertex AI APIs. *
  • location -> GOOGLE_CLOUD_LOCATION: Location for Vertex AI APIs. *
  • vertexAI -> GOOGLE_GENAI_USE_VERTEXAI: Whether to use Vertex AI APIs(true or false). @@ -513,9 +515,13 @@ static String getApiKeyFromEnv() { static ImmutableMap defaultEnvironmentVariables() { ImmutableMap.Builder mapBuilder = ImmutableMap.builder(); String value; - value = getApiKeyFromEnv(); + value = System.getenv("GOOGLE_API_KEY"); + if (value != null && !value.isEmpty()) { + mapBuilder.put("googleApiKey", value); + } + value = System.getenv("GEMINI_API_KEY"); if (value != null && !value.isEmpty()) { - mapBuilder.put("apiKey", value); + mapBuilder.put("geminiApiKey", value); } value = System.getenv("GOOGLE_CLOUD_PROJECT"); if (value != null && !value.isEmpty()) { diff --git a/src/test/java/com/google/genai/HttpApiClientTest.java b/src/test/java/com/google/genai/HttpApiClientTest.java index 96a6aaba3b1..aa9d3e77859 100644 --- a/src/test/java/com/google/genai/HttpApiClientTest.java +++ b/src/test/java/com/google/genai/HttpApiClientTest.java @@ -379,6 +379,66 @@ public void testInitHttpClientVertexWithProjectLocationAndApiKey_throwsException exception.getMessage()); } + @Test + public void testOnlyGoogleAPIKeyEnvSet(MockedStatic mockedStaticApiClient) + throws Exception { + // Explicit Vertex project and location takes precedence over project and location from + // environment + mockedStaticApiClient + .when(ApiClient::defaultEnvironmentVariables) + .thenReturn(ImmutableMap.of("googleApiKey", "google-api-key")); + HttpApiClient client = + new HttpApiClient( + Optional.empty(), + Optional.empty(), + Optional.empty(), + Optional.empty(), + Optional.empty(), + Optional.empty()); + + assertEquals(client.apiKey(), "google-api-key"); + } + + @Test + public void testOnlyGeminiAPIKeyEnvSet(MockedStatic mockedStaticApiClient) + throws Exception { + // Explicit Vertex project and location takes precedence over project and location from + // environment + mockedStaticApiClient + .when(ApiClient::defaultEnvironmentVariables) + .thenReturn(ImmutableMap.of("geminiApiKey", "gemini-api-key")); + HttpApiClient client = + new HttpApiClient( + Optional.empty(), + Optional.empty(), + Optional.empty(), + Optional.empty(), + Optional.empty(), + Optional.empty()); + + assertEquals(client.apiKey(), "gemini-api-key"); + } + + @Test + public void testBothAPIKeyEnvSet(MockedStatic mockedStaticApiClient) throws Exception { + // Explicit Vertex project and location takes precedence over project and location from + // environment + mockedStaticApiClient + .when(ApiClient::defaultEnvironmentVariables) + .thenReturn( + ImmutableMap.of("geminiApiKey", "gemini-api-key", "googleApiKey", "google-api-key")); + HttpApiClient client = + new HttpApiClient( + Optional.empty(), + Optional.empty(), + Optional.empty(), + Optional.empty(), + Optional.empty(), + Optional.empty()); + + assertEquals(client.apiKey(), "google-api-key"); + } + @Test public void testInitHttpClientVertexExplicitArgPrecedence1( MockedStatic mockedStaticApiClient) throws Exception { @@ -426,28 +486,6 @@ public void testInitHttpClientVertexApiKeyCombo1(MockedStatic mockedS assertEquals("https://aiplatform.googleapis.com", client.httpOptions.baseUrl().get()); } - @Test - public void testInitHttpClientVertexApiKeyCombo2(MockedStatic mockedStaticApiClient) - throws Exception { - // Proj/location from constructor takes precedence over API key from environment - mockedStaticApiClient - .when(ApiClient::defaultEnvironmentVariables) - .thenReturn(ImmutableMap.of("apiKey", "env-api-key")); - HttpApiClient client = - new HttpApiClient( - Optional.empty(), - Optional.of(PROJECT), - Optional.of(LOCATION), - Optional.of(CREDENTIALS), - Optional.empty(), - Optional.empty()); - - assertEquals(PROJECT, client.project()); - assertEquals(LOCATION, client.location()); - assertNull(client.apiKey()); - assertTrue(client.vertexAI()); - assertEquals("https://location-aiplatform.googleapis.com", client.httpOptions.baseUrl().get()); - } @Test public void testInitHttpClientVertexApiKeyCombo3(MockedStatic mockedStaticApiClient) @@ -457,7 +495,12 @@ public void testInitHttpClientVertexApiKeyCombo3(MockedStatic mockedS .when(ApiClient::defaultEnvironmentVariables) .thenReturn( ImmutableMap.of( - "project", "env-project-id", "location", "env-location", "apiKey", "env-api-key")); + "project", + "env-project-id", + "location", + "env-location", + "googleApiKey", + "google-api-key")); HttpApiClient client = new HttpApiClient( Optional.empty(), diff --git a/src/test/java/com/google/genai/TableTest.java b/src/test/java/com/google/genai/TableTest.java index 63e0fc689b9..43b38552a74 100644 --- a/src/test/java/com/google/genai/TableTest.java +++ b/src/test/java/com/google/genai/TableTest.java @@ -326,7 +326,7 @@ static Client createClient(boolean vertexAI) { .when(ApiClient::defaultEnvironmentVariables) .thenReturn( ImmutableMap.builder() - .put("apiKey", "api-key") + .put("googleApiKey", "google-api-key") .put("project", "project") .put("location", "location") .build()); From 1c240cecaec2b4286013b2377ce0029515d5d3cc Mon Sep 17 00:00:00 2001 From: Wanlin Du Date: Fri, 25 Jul 2025 12:59:48 -0700 Subject: [PATCH 113/602] chore: remove the comment for the ENV key test. PiperOrigin-RevId: 787211709 --- src/test/java/com/google/genai/HttpApiClientTest.java | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/test/java/com/google/genai/HttpApiClientTest.java b/src/test/java/com/google/genai/HttpApiClientTest.java index aa9d3e77859..9a065cb909a 100644 --- a/src/test/java/com/google/genai/HttpApiClientTest.java +++ b/src/test/java/com/google/genai/HttpApiClientTest.java @@ -382,8 +382,6 @@ public void testInitHttpClientVertexWithProjectLocationAndApiKey_throwsException @Test public void testOnlyGoogleAPIKeyEnvSet(MockedStatic mockedStaticApiClient) throws Exception { - // Explicit Vertex project and location takes precedence over project and location from - // environment mockedStaticApiClient .when(ApiClient::defaultEnvironmentVariables) .thenReturn(ImmutableMap.of("googleApiKey", "google-api-key")); @@ -402,8 +400,6 @@ public void testOnlyGoogleAPIKeyEnvSet(MockedStatic mockedStaticApiCl @Test public void testOnlyGeminiAPIKeyEnvSet(MockedStatic mockedStaticApiClient) throws Exception { - // Explicit Vertex project and location takes precedence over project and location from - // environment mockedStaticApiClient .when(ApiClient::defaultEnvironmentVariables) .thenReturn(ImmutableMap.of("geminiApiKey", "gemini-api-key")); @@ -421,8 +417,6 @@ public void testOnlyGeminiAPIKeyEnvSet(MockedStatic mockedStaticApiCl @Test public void testBothAPIKeyEnvSet(MockedStatic mockedStaticApiClient) throws Exception { - // Explicit Vertex project and location takes precedence over project and location from - // environment mockedStaticApiClient .when(ApiClient::defaultEnvironmentVariables) .thenReturn( From 83a6c74270be59bc8dc1c33bf5c81a8837b4adaf Mon Sep 17 00:00:00 2001 From: Annie Luc Date: Tue, 29 Jul 2025 09:45:17 -0700 Subject: [PATCH 114/602] test: Add tests for generating content with image modality PiperOrigin-RevId: 788492886 --- .../com/google/genai/AsyncModelsTest.java | 31 +++++++++++++++++ .../java/com/google/genai/ModelsTest.java | 34 +++++++++++++++++++ 2 files changed, 65 insertions(+) diff --git a/src/test/java/com/google/genai/AsyncModelsTest.java b/src/test/java/com/google/genai/AsyncModelsTest.java index 1407578a7b4..75747d2139c 100644 --- a/src/test/java/com/google/genai/AsyncModelsTest.java +++ b/src/test/java/com/google/genai/AsyncModelsTest.java @@ -243,6 +243,37 @@ public void testGenerateContentStream_withHeadersAsync(boolean vertexAI) throws assertTrue(responseStream.isConsumed()); } + @ParameterizedTest + @ValueSource(booleans = {false, true}) + public void testGenerateContentStream_withImageModalityAsync(boolean vertexAI) throws Exception { + // Arrange + String suffix = vertexAI ? "vertex" : "mldev"; + Client client = + TestUtils.createClient( + vertexAI, + "tests/models/generate_content/test_async_stream_with_non_text_modality." + + suffix + + ".json"); + + // Act + GenerateContentConfig config = + GenerateContentConfig.builder().responseModalities("IMAGE", "TEXT").build(); + CompletableFuture> responseStreamFuture = + client.async.models.generateContentStream( + "gemini-2.0-flash-preview-image-generation", + "Generate an image of the Eiffel tower with fireworks in the background.", + config); + ResponseStream responseStream = responseStreamFuture.join(); + + // Assert + int chunks = 0; + for (GenerateContentResponse response : responseStream) { + chunks++; + } + assertTrue(chunks > 2); + assertTrue(responseStream.isConsumed()); + } + @ParameterizedTest @ValueSource(booleans = {false, true}) public void testGenerateContent_withContentAndConfigAsync(boolean vertexAI) throws Exception { diff --git a/src/test/java/com/google/genai/ModelsTest.java b/src/test/java/com/google/genai/ModelsTest.java index 62c2fdc109f..b544843d9f5 100644 --- a/src/test/java/com/google/genai/ModelsTest.java +++ b/src/test/java/com/google/genai/ModelsTest.java @@ -65,6 +65,8 @@ public class ModelsTest { private static final String GEMINI_MODEL_NAME = "gemini-1.5-flash"; private static final String EMBEDDING_MODEL_NAME = "text-embedding-004"; private static final String IMAGEN_CAPABILITY_MODEL_NAME = "imagen-3.0-capability-001"; + private static final String GEMINI_IMAGE_MODALITY_MODEL_NAME = + "gemini-2.0-flash-preview-image-generation"; /** Creates a raw reference image for edit image tests. */ private RawReferenceImage createRawReferenceImage() throws Exception { @@ -212,6 +214,38 @@ public void testGenerateContentStream_withContentAndConfig(boolean vertexAI) thr assertTrue(responseStream.isConsumed()); } + @ParameterizedTest + @ValueSource(booleans = {false, true}) + public void testGenerateContentStream_withImageModality(boolean vertexAI) throws Exception { + // Arrange + String suffix = vertexAI ? "vertex" : "mldev"; + Client client = + TestUtils.createClient( + vertexAI, + "tests/models/generate_content/test_sync_stream_with_non_text_modality." + + suffix + + ".json"); + + // Act + GenerateContentConfig config = + GenerateContentConfig.builder().responseModalities("IMAGE", "TEXT").build(); + ResponseStream responseStream = + client.models.generateContentStream( + GEMINI_IMAGE_MODALITY_MODEL_NAME, + Content.fromParts( + Part.fromText( + "Generate an image of the Eiffel tower with fireworks in the background.")), + config); + + // Assert + int chunks = 0; + for (GenerateContentResponse response : responseStream) { + chunks++; + } + assertTrue(chunks > 2); + assertTrue(responseStream.isConsumed()); + } + @ParameterizedTest @ValueSource(booleans = {false, true}) public void testEmbedContent_withText(boolean vertexAI) throws Exception { From 222b41e196afc13775cc22292a58567d7b4859fa Mon Sep 17 00:00:00 2001 From: Ayush Agrawal Date: Tue, 29 Jul 2025 10:43:59 -0700 Subject: [PATCH 115/602] feat: support response headers in Go for all methods. PiperOrigin-RevId: 788517981 --- .../com/google/genai/AsyncTuningsTest.java | 40 +++++-------------- .../java/com/google/genai/TuningsTest.java | 40 +++++-------------- 2 files changed, 20 insertions(+), 60 deletions(-) diff --git a/src/test/java/com/google/genai/AsyncTuningsTest.java b/src/test/java/com/google/genai/AsyncTuningsTest.java index c50c840dde2..1ea204c169e 100644 --- a/src/test/java/com/google/genai/AsyncTuningsTest.java +++ b/src/test/java/com/google/genai/AsyncTuningsTest.java @@ -20,14 +20,10 @@ import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; -import com.google.genai.types.CreateTuningJobConfig; import com.google.genai.types.JobState; import com.google.genai.types.ListTuningJobsConfig; import com.google.genai.types.TuningDataset; -import com.google.genai.types.TuningExample; import com.google.genai.types.TuningJob; -import java.util.ArrayList; -import java.util.List; import java.util.concurrent.ExecutionException; import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable; import org.junit.jupiter.api.extension.ExtendWith; @@ -83,38 +79,22 @@ public void testHelperProperties(boolean vertexAI) @ValueSource(booleans = {false, true}) public void testTuneUntilSuccess(boolean vertexAI) throws ExecutionException, InterruptedException { + if (!vertexAI) { // MLDev test removed, tune not supported anymore + return; + } + // Arrange String suffix = vertexAI ? "vertex" : "mldev"; Client client = TestUtils.createClient( vertexAI, "tests/tunings/end_to_end/test_tune_until_success." + suffix + ".json"); - TuningJob job; - if (vertexAI) { - TuningDataset tuningDataset = - TuningDataset.builder() - .gcsUri( - "gs://cloud-samples-data/ai-platform/generative_ai/gemini-2_0/text/sft_train_data.jsonl") - .build(); - job = client.async.tunings.tune("gemini-2.0-flash-001", tuningDataset, null).get(); - } else { - // Technically not supported anymore (via API) but the replay test only verifies logic - List examples = new ArrayList<>(); - for (int i = 0; i < 5; i++) { - examples.add( - TuningExample.builder() - .textInput(String.format("Input text %d", i)) - .output(String.format("Output text %d", i)) - .build()); - } - - TuningDataset tuningDataset = TuningDataset.builder().examples(examples).build(); - CreateTuningJobConfig config = - CreateTuningJobConfig.builder() - .tunedModelDisplayName("test_dataset_examples model") - .build(); - job = client.async.tunings.tune("models/gemini-1.0-pro-001", tuningDataset, config).get(); - } + TuningDataset tuningDataset = + TuningDataset.builder() + .gcsUri( + "gs://cloud-samples-data/ai-platform/generative_ai/gemini-2_0/text/sft_train_data.jsonl") + .build(); + TuningJob job = client.async.tunings.tune("gemini-2.0-flash-001", tuningDataset, null).get(); // Act TuningJob currentJob = job; diff --git a/src/test/java/com/google/genai/TuningsTest.java b/src/test/java/com/google/genai/TuningsTest.java index d2775fca3ff..d0ed0b86ff9 100644 --- a/src/test/java/com/google/genai/TuningsTest.java +++ b/src/test/java/com/google/genai/TuningsTest.java @@ -21,14 +21,10 @@ import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; -import com.google.genai.types.CreateTuningJobConfig; import com.google.genai.types.JobState; import com.google.genai.types.ListTuningJobsConfig; import com.google.genai.types.TuningDataset; -import com.google.genai.types.TuningExample; import com.google.genai.types.TuningJob; -import java.util.ArrayList; -import java.util.List; import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable; import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.params.ParameterizedTest; @@ -87,38 +83,22 @@ public void testHelperProperties(boolean vertexAI) { @ParameterizedTest @ValueSource(booleans = {false, true}) public void testTuneUntilSuccess(boolean vertexAI) { + if (!vertexAI) { // MLDev test removed, tune not supported anymore + return; + } + // Arrange String suffix = vertexAI ? "vertex" : "mldev"; Client client = TestUtils.createClient( vertexAI, "tests/tunings/end_to_end/test_tune_until_success." + suffix + ".json"); - TuningJob job; - if (vertexAI) { - TuningDataset tuningDataset = - TuningDataset.builder() - .gcsUri( - "gs://cloud-samples-data/ai-platform/generative_ai/gemini-2_0/text/sft_train_data.jsonl") - .build(); - job = client.tunings.tune("gemini-2.0-flash-001", tuningDataset, null); - } else { - // Technically not supported anymore (via API) but the replay test only verifies logic - List examples = new ArrayList<>(); - for (int i = 0; i < 5; i++) { - examples.add( - TuningExample.builder() - .textInput(String.format("Input text %d", i)) - .output(String.format("Output text %d", i)) - .build()); - } - - TuningDataset tuningDataset = TuningDataset.builder().examples(examples).build(); - CreateTuningJobConfig config = - CreateTuningJobConfig.builder() - .tunedModelDisplayName("test_dataset_examples model") - .build(); - job = client.tunings.tune("models/gemini-1.0-pro-001", tuningDataset, config); - } + TuningDataset tuningDataset = + TuningDataset.builder() + .gcsUri( + "gs://cloud-samples-data/ai-platform/generative_ai/gemini-2_0/text/sft_train_data.jsonl") + .build(); + TuningJob job = client.tunings.tune("gemini-2.0-flash-001", tuningDataset, null); // Act TuningJob currentJob = job; From bde214f777a2c3b8667fde8afd444d17b7e07e97 Mon Sep 17 00:00:00 2001 From: Amir Hardon Date: Wed, 30 Jul 2025 10:12:19 -0700 Subject: [PATCH 116/602] chore: Automate closing of stale issues This commit updates the GitHub Actions workflow to automatically manage and close stale issues that are awaiting a user response. The workflow now performs the following actions: - Marks issues with the "status:awaiting user response" label as stale after 7 days of inactivity. - Posts a comment notifying that the issue will be closed if no further activity occurs. - Closes the issue if there is no activity for an additional 2 days. PiperOrigin-RevId: 788946450 --- .github/workflows/stale.yml | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 .github/workflows/stale.yml diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml new file mode 100644 index 00000000000..a78b673f193 --- /dev/null +++ b/.github/workflows/stale.yml @@ -0,0 +1,31 @@ +# This workflow warns and then closes issues that have had no activity for a specified amount of time. +name: Mark and close stale issues + +on: + schedule: + # Scheduled to run at 1:30 UTC everyday + - cron: '30 1 * * *' + +jobs: + stale: + + runs-on: ubuntu-latest + permissions: + issues: write + + steps: + - uses: actions/stale@v5 + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + days-before-issue-stale: 7 + days-before-issue-close: 2 + stale-issue-label: "status:stale" + close-issue-reason: not_planned + any-of-labels: "status:awaiting user response" + stale-issue-message: > + This issue has been marked as stale because it has been open for 7 days with no activity. It will be closed in 2 days if no further activity occurs. + close-issue-message: > + This issue was closed because it has been inactive for 9 days. + Please post a new issue if you need further assistance. Thanks! + # Label that can be assigned to issues to exclude them from being marked as stale + exempt-issue-labels: 'override-stale' \ No newline at end of file From 2562f09c42ba1cec01932c9056a924f893afd2e7 Mon Sep 17 00:00:00 2001 From: Jaycee Li Date: Wed, 30 Jul 2025 15:07:50 -0700 Subject: [PATCH 117/602] chore: Add test coverage check to unit tests PiperOrigin-RevId: 789060195 --- .github/workflows/unit-tests.yml | 2 +- pom.xml | 44 ++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 1 deletion(-) diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml index 72e3eec72d4..a68a2963436 100644 --- a/.github/workflows/unit-tests.yml +++ b/.github/workflows/unit-tests.yml @@ -25,4 +25,4 @@ jobs: java-version: ${{matrix.java}} cache: 'maven' - name: Java Unit Tests - run: mvn clean test -Dtest=${{matrix.testgroup}} \ No newline at end of file + run: mvn clean test -Dtest=${{matrix.testgroup}} -Djacoco.skip=true \ No newline at end of file diff --git a/pom.xml b/pom.xml index caea5b8c446..84fac6477cd 100644 --- a/pom.xml +++ b/pom.xml @@ -313,6 +313,7 @@ test report + check @@ -321,6 +322,49 @@ com/google/genai/types/AutoValue_*.class + + + PACKAGE + + com.google.genai + + + + INSTRUCTION + COVEREDRATIO + + 0.70 + + + + + PACKAGE + + com.google.genai.errors + + + + INSTRUCTION + COVEREDRATIO + 0.95 + + + + + PACKAGE + + com.google.genai.types + + + + INSTRUCTION + COVEREDRATIO + + 0.30 + + + + From be3e50e4217780329c0636fd7f8a1b743e7f9597 Mon Sep 17 00:00:00 2001 From: Jaycee Li Date: Thu, 31 Jul 2025 10:29:46 -0700 Subject: [PATCH 118/602] docs: mark Client as thread safe and Chat as not thread safe PiperOrigin-RevId: 789388237 --- src/main/java/com/google/genai/Chat.java | 2 ++ src/main/java/com/google/genai/Client.java | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/google/genai/Chat.java b/src/main/java/com/google/genai/Chat.java index 1e8bedf794c..e2e5ae1cf62 100644 --- a/src/main/java/com/google/genai/Chat.java +++ b/src/main/java/com/google/genai/Chat.java @@ -27,6 +27,8 @@ * *

    This class provides a way to interact with a generative model in a multi-turn chat session. It * keeps track of the chat history and uses it to provide context for subsequent messages. + * + *

    Note: this class is NOT thread-safe. */ public class Chat extends ChatBase { private final ApiClient apiClient; diff --git a/src/main/java/com/google/genai/Client.java b/src/main/java/com/google/genai/Client.java index c033cd01fd5..2efca2a4b91 100644 --- a/src/main/java/com/google/genai/Client.java +++ b/src/main/java/com/google/genai/Client.java @@ -26,7 +26,7 @@ import java.io.IOException; import java.util.Optional; -/** Client class for GenAI. */ +/** Client class for GenAI. This class is thread-safe. */ public final class Client implements AutoCloseable { /** Async class for GenAI. */ From f937dd1752e8a774e06d9afc6953211bd569fc35 Mon Sep 17 00:00:00 2001 From: Wanlin Du Date: Thu, 31 Jul 2025 10:41:17 -0700 Subject: [PATCH 119/602] feat: allow methods in batch to return headers in sdk_http_response by default PiperOrigin-RevId: 789392436 --- src/main/java/com/google/genai/Batches.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/com/google/genai/Batches.java b/src/main/java/com/google/genai/Batches.java index d0c5aadf02d..a93e4fbd0ef 100644 --- a/src/main/java/com/google/genai/Batches.java +++ b/src/main/java/com/google/genai/Batches.java @@ -2076,6 +2076,7 @@ ObjectNode listBatchJobsResponseFromMldev(JsonNode fromObject, ObjectNode parent @ExcludeFromGeneratedCoverageReport ObjectNode deleteResourceJobFromMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"name"}) != null) { Common.setValueByPath( toObject, @@ -2307,6 +2308,7 @@ ObjectNode listBatchJobsResponseFromVertex(JsonNode fromObject, ObjectNode paren @ExcludeFromGeneratedCoverageReport ObjectNode deleteResourceJobFromVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"name"}) != null) { Common.setValueByPath( toObject, From a7dbd4c527456f20aa5d154bde14f74f6e66d174 Mon Sep 17 00:00:00 2001 From: Michael Vorburger Date: Thu, 31 Jul 2025 11:24:49 -0700 Subject: [PATCH 120/602] Copybara import of the project: -- f29e93ee10d03b4e4f75cf3267522d3f24a873db by Michael Vorburger : fix: Remove duplicate JavaTimeModule in JsonSerializable COPYBARA_INTEGRATE_REVIEW=https://github.com/googleapis/java-genai/pull/430 from vorburger:patch-1 f29e93ee10d03b4e4f75cf3267522d3f24a873db PiperOrigin-RevId: 789408532 --- src/main/java/com/google/genai/JsonSerializable.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/main/java/com/google/genai/JsonSerializable.java b/src/main/java/com/google/genai/JsonSerializable.java index 57874b9600e..65b1fafc001 100644 --- a/src/main/java/com/google/genai/JsonSerializable.java +++ b/src/main/java/com/google/genai/JsonSerializable.java @@ -83,7 +83,6 @@ public java.time.Duration deserialize(JsonParser p, DeserializationContext ctxt) static { objectMapper.setSerializationInclusion(JsonInclude.Include.NON_ABSENT); objectMapper.registerModule(new Jdk8Module()); - objectMapper.registerModule(new JavaTimeModule()); // Disable writing dates as timestamps to use ISO-8601 string format for Instant objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); @@ -98,7 +97,6 @@ public java.time.Duration deserialize(JsonParser p, DeserializationContext ctxt) // provided by JavaTimeModule. objectMapper.registerModule(new JavaTimeModule()); objectMapper.registerModule(customModule); - } /** Serializes the instance to a Json string. */ From 139a0112097676caf426fc74ce4ef6342d77b3aa Mon Sep 17 00:00:00 2001 From: Johannes Rauber Date: Thu, 31 Jul 2025 14:38:40 -0700 Subject: [PATCH 121/602] Copybara import of the project: -- 10b1050c7cc45601d0762aebdb0a0ccc48f075a0 by jrauber : Add an automatic module name to better support JPMS COPYBARA_INTEGRATE_REVIEW=https://github.com/googleapis/java-genai/pull/399 from jrauber:main 4f175a9d0559ec1e04a7bee16bd37bdb48f58d35 PiperOrigin-RevId: 789476969 --- pom.xml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 84fac6477cd..aef2e2b8d25 100644 --- a/pom.xml +++ b/pom.xml @@ -213,7 +213,14 @@ maven-jar-plugin - 3.0.2 + 3.3.0 + + + + com.google.genai + + + maven-install-plugin From a2eccafae5c6c9b82341a148b572bf9bc80f241b Mon Sep 17 00:00:00 2001 From: Jaycee Li Date: Thu, 31 Jul 2025 14:41:42 -0700 Subject: [PATCH 122/602] docs: Add latest models features in README PiperOrigin-RevId: 789477988 --- README.md | 227 ++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 150 insertions(+), 77 deletions(-) diff --git a/README.md b/README.md index dbaa7e1a39a..41deec6b25c 100644 --- a/README.md +++ b/README.md @@ -178,11 +178,11 @@ Client client = Client.builder() ``` ### Interact with models -The Gen AI Java SDK allows you to access the service programmatically. +The Google Gen AI Java SDK allows you to access the service programmatically. The following code snippets are some basic usages of model inferencing. #### Generate Content -Use `generateContent` method for the most basic text generation. +Use `generateContent` method for the most basic content generation. ##### with text input @@ -199,10 +199,17 @@ public class GenerateContentWithTextInput { Client client = new Client(); GenerateContentResponse response = - client.models.generateContent("gemini-2.0-flash-001", "What is your name?", null); + client.models.generateContent("gemini-2.5-flash", "What is your name?", null); // Gets the text string from the response by the quick accessor method `text()`. System.out.println("Unary response: " + response.text()); + + // Gets the http headers from the response. + response + .sdkHttpResponse() + .ifPresent( + httpResponse -> + System.out.println("Response headers: " + httpResponse.headers().orElse(null))); } } ``` @@ -232,7 +239,68 @@ public class GenerateContentWithImageInput { Part.fromUri("gs://path/to/image.jpg", "image/jpeg")); GenerateContentResponse response = - client.models.generateContent("gemini-2.0-flash-001", content, null); + client.models.generateContent("gemini-2.5-flash", content, null); + + System.out.println("Response: " + response.text()); + } +} +``` + +##### Generate Content with extra configs +To set configurations like System Instructions and Safety Settings, you can pass +a `GenerateContentConfig` to the `GenerateContent` method. + +```java +package ; + +import com.google.common.collect.ImmutableList; +import com.google.genai.Client; +import com.google.genai.types.Content; +import com.google.genai.types.GenerateContentConfig; +import com.google.genai.types.GenerateContentResponse; +import com.google.genai.types.GoogleSearch; +import com.google.genai.types.HarmBlockThreshold; +import com.google.genai.types.HarmCategory; +import com.google.genai.types.Part; +import com.google.genai.types.SafetySetting; +import com.google.genai.types.ThinkingConfig; +import com.google.genai.types.Tool; + +public class GenerateContentWithConfigs { + public static void main(String[] args) { + Client client = new Client(); + + // Sets the safety settings in the config. + ImmutableList safetySettings = + ImmutableList.of( + SafetySetting.builder() + .category(HarmCategory.Known.HARM_CATEGORY_HATE_SPEECH) + .threshold(HarmBlockThreshold.Known.BLOCK_ONLY_HIGH) + .build(), + SafetySetting.builder() + .category(HarmCategory.Known.HARM_CATEGORY_DANGEROUS_CONTENT) + .threshold(HarmBlockThreshold.Known.BLOCK_LOW_AND_ABOVE) + .build()); + + // Sets the system instruction in the config. + Content systemInstruction = Content.fromParts(Part.fromText("You are a history teacher.")); + + // Sets the Google Search tool in the config. + Tool googleSearchTool = Tool.builder().googleSearch(GoogleSearch.builder()).build(); + + GenerateContentConfig config = + GenerateContentConfig.builder() + // Sets the thinking budget to 0 to disable thinking mode + .thinkingConfig(ThinkingConfig.builder().thinkingBudget(0)) + .candidateCount(1) + .maxOutputTokens(1024) + .safetySettings(safetySettings) + .systemInstruction(systemInstruction) + .tools(googleSearchTool) + .build(); + + GenerateContentResponse response = + client.models.generateContent("gemini-2.5-flash", "Tell me the history of LLM", config); System.out.println("Response: " + response.text()); } @@ -287,14 +355,12 @@ public class GenerateContentWithFunctionCall { GenerateContentConfig config = GenerateContentConfig.builder() - .tools( - ImmutableList.of( - Tool.builder().functions(ImmutableList.of(method)).build())) + .tools(Tool.builder().functions(method)) .build(); GenerateContentResponse response = client.models.generateContent( - "gemini-2.0-flash-001", + "gemini-2.5-flash", "What is the weather in Vancouver?", config); @@ -306,7 +372,7 @@ public class GenerateContentWithFunctionCall { } ``` -#### Stream Generated Content +##### Stream Generated Content To get a streamed response, you can use the `generateContentStream` method: ```java @@ -318,13 +384,11 @@ import com.google.genai.types.GenerateContentResponse; public class StreamGeneration { public static void main(String[] args) { - // Instantiate the client using Vertex API. The client gets the project and location from the - // environment variables `GOOGLE_CLOUD_PROJECT` and `GOOGLE_CLOUD_LOCATION`. - Client client = Client.builder().vertexAI(true).build(); + Client client = new Client(); ResponseStream responseStream = client.models.generateContentStream( - "gemini-2.0-flash-001", "Tell me a story in 300 words.", null); + "gemini-2.5-flash", "Tell me a story in 300 words.", null); System.out.println("Streaming response: "); for (GenerateContentResponse res : responseStream) { @@ -338,7 +402,7 @@ public class StreamGeneration { } ``` -#### Async Generate Content +##### Async Generate Content To get a response asynchronously, you can use the `generateContent` method from the `client.async.models` namespace. @@ -351,12 +415,11 @@ import java.util.concurrent.CompletableFuture; public class GenerateContentAsync { public static void main(String[] args) { - // Instantiates the client using Gemini API, and sets the API key in the builder. - Client client = Client.builder().apiKey("your-api-key").build(); + Client client = new Client(); CompletableFuture responseFuture = client.async.models.generateContent( - "gemini-2.0-flash-001", "Introduce Google AI Studio.", null); + "gemini-2.5-flash", "Introduce Google AI Studio.", null); responseFuture .thenAccept( @@ -368,65 +431,7 @@ public class GenerateContentAsync { } ``` -#### Generate Content with extra configs -To set configurations like System Instructions and Safety Settings, you can pass -a `GenerateContentConfig` to the `GenerateContent` method. - -```java -package ; - -import com.google.common.collect.ImmutableList; -import com.google.genai.Client; -import com.google.genai.types.Content; -import com.google.genai.types.GenerateContentConfig; -import com.google.genai.types.GenerateContentResponse; -import com.google.genai.types.GoogleSearch; -import com.google.genai.types.HarmBlockThreshold; -import com.google.genai.types.HarmCategory; -import com.google.genai.types.Part; -import com.google.genai.types.SafetySetting; -import com.google.genai.types.Tool; - -public class GenerateContentWithConfigs { - public static void main(String[] args) { - Client client = new Client(); - - // Sets the safety settings in the config. - ImmutableList safetySettings = - ImmutableList.of( - SafetySetting.builder() - .category(HarmCategory.Known.HARM_CATEGORY_HATE_SPEECH) - .threshold(HarmBlockThreshold.Known.BLOCK_ONLY_HIGH) - .build(), - SafetySetting.builder() - .category(HarmCategory.Known.HARM_CATEGORY_DANGEROUS_CONTENT) - .threshold(HarmBlockThreshold.Known.BLOCK_LOW_AND_ABOVE) - .build()); - - // Sets the system instruction in the config. - Content systemInstruction = Content.fromParts(Part.fromText("You are a history teacher.")); - - // Sets the Google Search tool in the config. - Tool googleSearchTool = Tool.builder().googleSearch(GoogleSearch.builder().build()).build(); - - GenerateContentConfig config = - GenerateContentConfig.builder() - .candidateCount(1) - .maxOutputTokens(1024) - .safetySettings(safetySettings) - .systemInstruction(systemInstruction) - .tools(ImmutableList.of(googleSearchTool)) - .build(); - - GenerateContentResponse response = - client.models.generateContent("gemini-2.0-flash-001", "Tell me the history of LLM", config); - - System.out.println("Response: " + response.text()); - } -} -``` - -#### Generate Content with JSON response schema +##### Generate Content with JSON response schema To get a response in JSON by passing in a response schema to the `GenerateContent` API. @@ -465,13 +470,81 @@ public class GenerateContentWithSchema { .build(); GenerateContentResponse response = - client.models.generateContent("gemini-2.0-flash-001", "Tell me your name", config); + client.models.generateContent("gemini-2.5-flash", "Tell me your name", config); System.out.println("Response: " + response.text()); } } ``` +#### Count Tokens and Compute Tokens + +The `countTokens` method allows you to calculate the number of tokens your +prompt will use before sending it to the model, helping you manage costs and +stay within the context window. + +```java +package ; + +import com.google.genai.Client; +import com.google.genai.types.CountTokensResponse; + +public class CountTokens { + public static void main(String[] args) { + Client client = new Client(); + + CountTokensResponse response = + client.models.countTokens("gemini-2.5-flash", "What is your name?", null); + + System.out.println("Count tokens response: " + response); + } +} +``` + +The `computeTokens` method returns the Tokens Info that contains tokens and +token IDs given your prompt. This method is only supported in Vertex AI. + +```java +package ; + +import com.google.genai.Client; +import com.google.genai.types.ComputeTokensResponse; + +public class ComputeTokens { + public static void main(String[] args) { + Client client = Client.builder().vertexAI(true).build(); + + ComputeTokensResponse response = + client.models.computeTokens("gemini-2.5-flash", "What is your name?", null); + + System.out.println("Compute tokens response: " + response); + } +} +``` + +#### Embed Content + +The `embedContent` method allows you to generate embeddings for words, phrases, +sentences, and code. Note that only text embedding is supported in this method. + +```java +package ; + +import com.google.genai.Client; +import com.google.genai.types.EmbedContentResponse; + +public class EmbedContent { + public static void main(String[] args) { + Client client = new Client(); + + EmbedContentResponse response = + client.models.embedContent("gemini-embedding-001", "why is the sky blue?", null); + + System.out.println("Embedding response: " + response); + } +} +``` + ## Versioning This library follows [Semantic Versioning](http://semver.org/). From e7de8c83bbd2e7e37c2198c3501e2d5bee58c0a2 Mon Sep 17 00:00:00 2001 From: Matthew Tang Date: Thu, 31 Jul 2025 15:20:48 -0700 Subject: [PATCH 123/602] feat: Support image recontext on Vertex PiperOrigin-RevId: 789490902 --- .../genai/examples/RecontextImageAsync.java | 111 ++++++++ .../RecontextImageProductRecontext.java | 103 +++++++ .../examples/RecontextImageVirtualTryOn.java | 104 +++++++ .../java/com/google/genai/AsyncModels.java | 28 ++ src/main/java/com/google/genai/Models.java | 261 ++++++++++++++++++ .../com/google/genai/types/ProductImage.java | 77 ++++++ .../genai/types/RecontextImageConfig.java | 231 ++++++++++++++++ .../genai/types/RecontextImageParameters.java | 116 ++++++++ .../genai/types/RecontextImageResponse.java | 93 +++++++ .../genai/types/RecontextImageSource.java | 130 +++++++++ 10 files changed, 1254 insertions(+) create mode 100644 examples/src/main/java/com/google/genai/examples/RecontextImageAsync.java create mode 100644 examples/src/main/java/com/google/genai/examples/RecontextImageProductRecontext.java create mode 100644 examples/src/main/java/com/google/genai/examples/RecontextImageVirtualTryOn.java create mode 100644 src/main/java/com/google/genai/types/ProductImage.java create mode 100644 src/main/java/com/google/genai/types/RecontextImageConfig.java create mode 100644 src/main/java/com/google/genai/types/RecontextImageParameters.java create mode 100644 src/main/java/com/google/genai/types/RecontextImageResponse.java create mode 100644 src/main/java/com/google/genai/types/RecontextImageSource.java diff --git a/examples/src/main/java/com/google/genai/examples/RecontextImageAsync.java b/examples/src/main/java/com/google/genai/examples/RecontextImageAsync.java new file mode 100644 index 00000000000..092056d5db8 --- /dev/null +++ b/examples/src/main/java/com/google/genai/examples/RecontextImageAsync.java @@ -0,0 +1,111 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Usage: + * + *

    1a. If you are using Vertex AI, setup ADC to get credentials: + * https://cloud.google.com/docs/authentication/provide-credentials-adc#google-idp + * + *

    Then set Project, Location, and USE_VERTEXAI flag as environment variables: + * + *

    export GOOGLE_CLOUD_PROJECT=YOUR_PROJECT + * + *

    export GOOGLE_CLOUD_LOCATION=YOUR_LOCATION + * + *

    export GOOGLE_GENAI_USE_VERTEXAI=true + * + *

    1b. If you are using Gemini Developer API, set an API key environment variable. You can find a + * list of available API keys here: https://aistudio.google.com/app/apikey + * + *

    export GOOGLE_API_KEY=YOUR_API_KEY + * + *

    2. Compile the java package and run the sample code. + * + *

    mvn clean compile + * + *

    mvn exec:java -Dexec.mainClass="com.google.genai.examples.RecontextImageAsync" + * -Dexec.args="YOUR_MODEL_ID" + */ +package com.google.genai.examples; + +import com.google.genai.Client; +import com.google.genai.types.Image; +import com.google.genai.types.ProductImage; +import com.google.genai.types.RecontextImageConfig; +import com.google.genai.types.RecontextImageResponse; +import com.google.genai.types.RecontextImageSource; +import java.util.ArrayList; +import java.util.concurrent.CompletableFuture; + +/** + * An example of using the Unified Gen AI Java SDK to recontextualize an image (product recontext) + * asynchronously. + */ +public final class RecontextImageAsync { + public static void main(String[] args) { + String modelId = "imagen-product-recontext-preview-06-30"; + if (args.length != 0) { + modelId = args[0]; + } + + // Instantiate the client. The client by default uses the Gemini Developer API. It gets the API + // key from the environment variable `GOOGLE_API_KEY`. Vertex AI API can be used by setting the + // environment variables `GOOGLE_CLOUD_LOCATION` and `GOOGLE_CLOUD_PROJECT`, as well as setting + // `GOOGLE_GENAI_USE_VERTEXAI` to "true". + // + // Note: Some services are only available in a specific API backend (Gemini or Vertex), you will + // get a `UnsupportedOperationException` if you try to use a service that is not available in + // the backend you are using. + Client client = new Client(); + + if (client.vertexAI()) { + System.out.println("Using Vertex AI"); + } else { + System.out.println("Using Gemini Developer API"); + } + + Image productImageBackpack = + Image.builder().gcsUri("gs://genai-sdk-tests/inputs/images/backpack1.png").build(); + + RecontextImageConfig recontextImageConfig = + RecontextImageConfig.builder().numberOfImages(1).outputMimeType("image/jpeg").build(); + + ArrayList productImages = new ArrayList<>(); + ProductImage productImage = ProductImage.builder().productImage(productImageBackpack).build(); + productImages.add(productImage); + + RecontextImageSource recontextImageSource = + RecontextImageSource.builder() + .prompt("On a school desk.") + .productImages(productImages) + .build(); + + CompletableFuture recontextImageResponseFuture = + client.async.models.recontextImage(modelId, recontextImageSource, recontextImageConfig); + + recontextImageResponseFuture + .thenAccept( + recontextImageResponse -> { + Image generatedImage = + recontextImageResponse.generatedImages().get().get(0).image().get(); + // Do something with generatedImage. + }) + .join(); + } + + private RecontextImageAsync() {} +} diff --git a/examples/src/main/java/com/google/genai/examples/RecontextImageProductRecontext.java b/examples/src/main/java/com/google/genai/examples/RecontextImageProductRecontext.java new file mode 100644 index 00000000000..ede04de06ff --- /dev/null +++ b/examples/src/main/java/com/google/genai/examples/RecontextImageProductRecontext.java @@ -0,0 +1,103 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Usage: + * + *

    1a. If you are using Vertex AI, setup ADC to get credentials: + * https://cloud.google.com/docs/authentication/provide-credentials-adc#google-idp + * + *

    Then set Project, Location, and USE_VERTEXAI flag as environment variables: + * + *

    export GOOGLE_CLOUD_PROJECT=YOUR_PROJECT + * + *

    export GOOGLE_CLOUD_LOCATION=YOUR_LOCATION + * + *

    export GOOGLE_GENAI_USE_VERTEXAI=true + * + *

    1b. If you are using Gemini Developer API, set an API key environment variable. You can find a + * list of available API keys here: https://aistudio.google.com/app/apikey + * + *

    export GOOGLE_API_KEY=YOUR_API_KEY + * + *

    2. Compile the java package and run the sample code. + * + *

    mvn clean compile + * + *

    mvn exec:java -Dexec.mainClass="com.google.genai.examples.RecontextImageProductRecontext" + * -Dexec.args="YOUR_MODEL_ID" + */ +package com.google.genai.examples; + +import com.google.genai.Client; +import com.google.genai.types.Image; +import com.google.genai.types.ProductImage; +import com.google.genai.types.RecontextImageConfig; +import com.google.genai.types.RecontextImageResponse; +import com.google.genai.types.RecontextImageSource; +import java.util.ArrayList; + +/** + * An example of using the Unified Gen AI Java SDK to recontextualize an image (product recontext). + */ +public final class RecontextImageProductRecontext { + public static void main(String[] args) { + String modelId = "imagen-product-recontext-preview-06-30"; + if (args.length != 0) { + modelId = args[0]; + } + + // Instantiate the client. The client by default uses the Gemini Developer API. It gets the API + // key from the environment variable `GOOGLE_API_KEY`. Vertex AI API can be used by setting the + // environment variables `GOOGLE_CLOUD_LOCATION` and `GOOGLE_CLOUD_PROJECT`, as well as setting + // `GOOGLE_GENAI_USE_VERTEXAI` to "true". + // + // Note: Some services are only available in a specific API backend (Gemini or Vertex), you will + // get a `UnsupportedOperationException` if you try to use a service that is not available in + // the backend you are using. + Client client = new Client(); + + if (client.vertexAI()) { + System.out.println("Using Vertex AI"); + } else { + System.out.println("Using Gemini Developer API"); + } + + Image productImageBackpack = + Image.builder().gcsUri("gs://genai-sdk-tests/inputs/images/backpack1.png").build(); + + RecontextImageConfig recontextImageConfig = + RecontextImageConfig.builder().numberOfImages(1).outputMimeType("image/jpeg").build(); + + ArrayList productImages = new ArrayList<>(); + ProductImage productImage = ProductImage.builder().productImage(productImageBackpack).build(); + productImages.add(productImage); + + RecontextImageSource recontextImageSource = + RecontextImageSource.builder() + .prompt("On a school desk.") + .productImages(productImages) + .build(); + + RecontextImageResponse recontextImageResponse = + client.models.recontextImage(modelId, recontextImageSource, recontextImageConfig); + + Image generatedImage = recontextImageResponse.generatedImages().get().get(0).image().get(); + // Do something with generatedImage. + } + + private RecontextImageProductRecontext() {} +} diff --git a/examples/src/main/java/com/google/genai/examples/RecontextImageVirtualTryOn.java b/examples/src/main/java/com/google/genai/examples/RecontextImageVirtualTryOn.java new file mode 100644 index 00000000000..c945d41c7ad --- /dev/null +++ b/examples/src/main/java/com/google/genai/examples/RecontextImageVirtualTryOn.java @@ -0,0 +1,104 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Usage: + * + *

    1a. If you are using Vertex AI, setup ADC to get credentials: + * https://cloud.google.com/docs/authentication/provide-credentials-adc#google-idp + * + *

    Then set Project, Location, and USE_VERTEXAI flag as environment variables: + * + *

    export GOOGLE_CLOUD_PROJECT=YOUR_PROJECT + * + *

    export GOOGLE_CLOUD_LOCATION=YOUR_LOCATION + * + *

    export GOOGLE_GENAI_USE_VERTEXAI=true + * + *

    1b. If you are using Gemini Developer API, set an API key environment variable. You can find a + * list of available API keys here: https://aistudio.google.com/app/apikey + * + *

    export GOOGLE_API_KEY=YOUR_API_KEY + * + *

    2. Compile the java package and run the sample code. + * + *

    mvn clean compile + * + *

    mvn exec:java -Dexec.mainClass="com.google.genai.examples.RecontextImageVirtualTryOn" + * -Dexec.args="YOUR_MODEL_ID" + */ +package com.google.genai.examples; + +import com.google.genai.Client; +import com.google.genai.types.Image; +import com.google.genai.types.ProductImage; +import com.google.genai.types.RecontextImageConfig; +import com.google.genai.types.RecontextImageResponse; +import com.google.genai.types.RecontextImageSource; +import java.util.ArrayList; + +/** An example of using the Unified Gen AI Java SDK to recontextualize an image (virtual try-on). */ +public final class RecontextImageVirtualTryOn { + public static void main(String[] args) { + String modelId = "virtual-try-on-exp-05-31"; + if (args.length != 0) { + modelId = args[0]; + } + + // Instantiate the client. The client by default uses the Gemini Developer API. It gets the API + // key from the environment variable `GOOGLE_API_KEY`. Vertex AI API can be used by setting the + // environment variables `GOOGLE_CLOUD_LOCATION` and `GOOGLE_CLOUD_PROJECT`, as well as setting + // `GOOGLE_GENAI_USE_VERTEXAI` to "true". + // + // Note: Some services are only available in a specific API backend (Gemini or Vertex), you will + // get a `UnsupportedOperationException` if you try to use a service that is not available in + // the backend you are using. + Client client = new Client(); + + if (client.vertexAI()) { + System.out.println("Using Vertex AI"); + } else { + System.out.println("Using Gemini Developer API"); + } + + Image productImagePants = + Image.builder().gcsUri("gs://genai-sdk-tests/inputs/images/pants.jpg").build(); + + Image personImage = + Image.builder().gcsUri("gs://genai-sdk-tests/inputs/images/man.jpg").build(); + + RecontextImageConfig recontextImageConfig = + RecontextImageConfig.builder().numberOfImages(1).outputMimeType("image/jpeg").build(); + + ArrayList productImages = new ArrayList<>(); + ProductImage productImage = ProductImage.builder().productImage(productImagePants).build(); + productImages.add(productImage); + + RecontextImageSource recontextImageSource = + RecontextImageSource.builder() + .personImage(personImage) + .productImages(productImages) + .build(); + + RecontextImageResponse recontextImageResponse = + client.models.recontextImage(modelId, recontextImageSource, recontextImageConfig); + + Image generatedImage = recontextImageResponse.generatedImages().get().get(0).image().get(); + // Do something with generatedImage. + } + + private RecontextImageVirtualTryOn() {} +} diff --git a/src/main/java/com/google/genai/AsyncModels.java b/src/main/java/com/google/genai/AsyncModels.java index 8502b25b5d3..e405c5f176c 100644 --- a/src/main/java/com/google/genai/AsyncModels.java +++ b/src/main/java/com/google/genai/AsyncModels.java @@ -42,6 +42,9 @@ import com.google.genai.types.Image; import com.google.genai.types.ListModelsConfig; import com.google.genai.types.Model; +import com.google.genai.types.RecontextImageConfig; +import com.google.genai.types.RecontextImageResponse; +import com.google.genai.types.RecontextImageSource; import com.google.genai.types.ReferenceImage; import com.google.genai.types.UpdateModelConfig; import com.google.genai.types.UpscaleImageConfig; @@ -59,6 +62,31 @@ public AsyncModels(ApiClient apiClient) { this.models = new Models(apiClient); } + /** + * Asynchronously recontextualizes an image. + * + *

    There are two types of recontextualization currently supported: 1) Imagen Product Recontext + * - Generate images of products in new scenes and contexts. 2) Virtual Try-On: Generate images of + * persons modeling fashion products. + * + * @param model the name of the GenAI model to use for image recontext + * @param source a {@link com.google.genai.types.RecontextImageSource} An object containing the + * source inputs (prompt, personImage, productImages) for image recontext. prompt is optional + * for product recontext and disallowed for virtual try-on. personImage is required for + * virtual try-on, disallowed for product recontext. productImages is required for both + * product recontext and virtual try-on. Only one product image is supported for virtual + * try-on, and up to 3 product images (different angles of the same product) are supported for + * product recontext. + * @param config a {@link com.google.genai.types.RecontextImageConfig} instance that specifies the + * optional configurations + * @return a {@link com.google.genai.types.RecontextImageResponse} instance that contains the + * generated images. + */ + public CompletableFuture recontextImage( + String model, RecontextImageSource source, RecontextImageConfig config) { + return CompletableFuture.supplyAsync(() -> models.recontextImage(model, source, config)); + } + /** * Asynchronously fetches information about a model by name. * diff --git a/src/main/java/com/google/genai/Models.java b/src/main/java/com/google/genai/Models.java index f12a7a9046d..2081aea0298 100644 --- a/src/main/java/com/google/genai/Models.java +++ b/src/main/java/com/google/genai/Models.java @@ -62,6 +62,10 @@ import com.google.genai.types.ListModelsResponse; import com.google.genai.types.Model; import com.google.genai.types.Part; +import com.google.genai.types.RecontextImageConfig; +import com.google.genai.types.RecontextImageParameters; +import com.google.genai.types.RecontextImageResponse; +import com.google.genai.types.RecontextImageSource; import com.google.genai.types.ReferenceImage; import com.google.genai.types.ReferenceImageAPI; import com.google.genai.types.SafetyAttributes; @@ -3518,6 +3522,162 @@ ObjectNode upscaleImageAPIParametersToVertex( return toObject; } + @ExcludeFromGeneratedCoverageReport + ObjectNode productImageToVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"productImage"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"image"}, + imageToVertex( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"productImage"})), + toObject)); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode recontextImageSourceToVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"prompt"}) != null) { + Common.setValueByPath( + parentObject, + new String[] {"instances[0]", "prompt"}, + Common.getValueByPath(fromObject, new String[] {"prompt"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"personImage"}) != null) { + Common.setValueByPath( + parentObject, + new String[] {"instances[0]", "personImage", "image"}, + imageToVertex( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"personImage"})), + toObject)); + } + + if (Common.getValueByPath(fromObject, new String[] {"productImages"}) != null) { + ArrayNode keyArray = + (ArrayNode) Common.getValueByPath(fromObject, new String[] {"productImages"}); + ObjectMapper objectMapper = new ObjectMapper(); + ArrayNode result = objectMapper.createArrayNode(); + + for (JsonNode item : keyArray) { + result.add(productImageToVertex(JsonSerializable.toJsonNode(item), toObject)); + } + Common.setValueByPath(parentObject, new String[] {"instances[0]", "productImages"}, result); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode recontextImageConfigToVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + + if (Common.getValueByPath(fromObject, new String[] {"numberOfImages"}) != null) { + Common.setValueByPath( + parentObject, + new String[] {"parameters", "sampleCount"}, + Common.getValueByPath(fromObject, new String[] {"numberOfImages"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"baseSteps"}) != null) { + Common.setValueByPath( + parentObject, + new String[] {"parameters", "editConfig", "baseSteps"}, + Common.getValueByPath(fromObject, new String[] {"baseSteps"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"outputGcsUri"}) != null) { + Common.setValueByPath( + parentObject, + new String[] {"parameters", "storageUri"}, + Common.getValueByPath(fromObject, new String[] {"outputGcsUri"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"seed"}) != null) { + Common.setValueByPath( + parentObject, + new String[] {"parameters", "seed"}, + Common.getValueByPath(fromObject, new String[] {"seed"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"safetyFilterLevel"}) != null) { + Common.setValueByPath( + parentObject, + new String[] {"parameters", "safetySetting"}, + Common.getValueByPath(fromObject, new String[] {"safetyFilterLevel"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"personGeneration"}) != null) { + Common.setValueByPath( + parentObject, + new String[] {"parameters", "personGeneration"}, + Common.getValueByPath(fromObject, new String[] {"personGeneration"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"outputMimeType"}) != null) { + Common.setValueByPath( + parentObject, + new String[] {"parameters", "outputOptions", "mimeType"}, + Common.getValueByPath(fromObject, new String[] {"outputMimeType"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"outputCompressionQuality"}) != null) { + Common.setValueByPath( + parentObject, + new String[] {"parameters", "outputOptions", "compressionQuality"}, + Common.getValueByPath(fromObject, new String[] {"outputCompressionQuality"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"enhancePrompt"}) != null) { + Common.setValueByPath( + parentObject, + new String[] {"parameters", "enhancePrompt"}, + Common.getValueByPath(fromObject, new String[] {"enhancePrompt"})); + } + + return toObject; + } + + @ExcludeFromGeneratedCoverageReport + ObjectNode recontextImageParametersToVertex( + ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"model"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"_url", "model"}, + Transformers.tModel( + this.apiClient, Common.getValueByPath(fromObject, new String[] {"model"}))); + } + + if (Common.getValueByPath(fromObject, new String[] {"source"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"config"}, + recontextImageSourceToVertex( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"source"})), + toObject)); + } + + if (Common.getValueByPath(fromObject, new String[] {"config"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"config"}, + recontextImageConfigToVertex( + JsonSerializable.toJsonNode( + Common.getValueByPath(fromObject, new String[] {"config"})), + toObject)); + } + + return toObject; + } + @ExcludeFromGeneratedCoverageReport ObjectNode getModelParametersToVertex( ApiClient apiClient, JsonNode fromObject, ObjectNode parentObject) { @@ -5427,6 +5587,24 @@ ObjectNode upscaleImageResponseFromVertex(JsonNode fromObject, ObjectNode parent return toObject; } + @ExcludeFromGeneratedCoverageReport + ObjectNode recontextImageResponseFromVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); + if (Common.getValueByPath(fromObject, new String[] {"predictions"}) != null) { + ArrayNode keyArray = + (ArrayNode) Common.getValueByPath(fromObject, new String[] {"predictions"}); + ObjectMapper objectMapper = new ObjectMapper(); + ArrayNode result = objectMapper.createArrayNode(); + + for (JsonNode item : keyArray) { + result.add(generatedImageFromVertex(JsonSerializable.toJsonNode(item), toObject)); + } + Common.setValueByPath(toObject, new String[] {"generatedImages"}, result); + } + + return toObject; + } + @ExcludeFromGeneratedCoverageReport ObjectNode endpointFromVertex(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); @@ -6173,6 +6351,89 @@ UpscaleImageResponse privateUpscaleImage( } } + /** + * Recontextualizes an image. + * + *

    There are two types of recontextualization currently supported: 1) Imagen Product Recontext + * - Generate images of products in new scenes and contexts. 2) Virtual Try-On: Generate images of + * persons modeling fashion products. + * + * @param model the name of the GenAI model to use for image recontext + * @param source a {@link com.google.genai.types.RecontextImageSource} An object containing the + * source inputs (prompt, personImage, productImages) for image recontext. prompt is optional + * for product recontext and disallowed for virtual try-on. personImage is required for + * virtual try-on, disallowed for product recontext. productImages is required for both + * product recontext and virtual try-on. Only one product image is supported for virtual + * try-on, and up to 3 product images (different angles of the same product) are supported for + * product recontext. + * @param config a {@link com.google.genai.types.RecontextImageConfig} instance that specifies the + * optional configurations + * @return a {@link com.google.genai.types.RecontextImageResponse} instance that contains the + * generated images. + */ + public RecontextImageResponse recontextImage( + String model, RecontextImageSource source, RecontextImageConfig config) { + + RecontextImageParameters.Builder parameterBuilder = RecontextImageParameters.builder(); + + if (!Common.isZero(model)) { + parameterBuilder.model(model); + } + if (!Common.isZero(source)) { + parameterBuilder.source(source); + } + if (!Common.isZero(config)) { + parameterBuilder.config(config); + } + JsonNode parameterNode = JsonSerializable.toJsonNode(parameterBuilder.build()); + + ObjectNode body; + String path; + if (this.apiClient.vertexAI()) { + body = recontextImageParametersToVertex(this.apiClient, parameterNode, null); + path = Common.formatMap("{model}:predict", body.get("_url")); + } else { + throw new UnsupportedOperationException( + "This method is only supported in the Vertex AI client."); + } + body.remove("_url"); + + JsonNode queryParams = body.get("_query"); + if (queryParams != null) { + body.remove("_query"); + path = String.format("%s?%s", path, Common.urlEncode((ObjectNode) queryParams)); + } + + // TODO: Remove the hack that removes config. + body.remove("config"); + + Optional requestHttpOptions = Optional.empty(); + if (config != null) { + requestHttpOptions = config.httpOptions(); + } + + try (ApiResponse response = + this.apiClient.request( + "post", path, JsonSerializable.toJsonString(body), requestHttpOptions)) { + ResponseBody responseBody = response.getBody(); + String responseString; + try { + responseString = responseBody.string(); + } catch (IOException e) { + throw new GenAiIOException("Failed to read HTTP response.", e); + } + + JsonNode responseNode = JsonSerializable.stringToJsonNode(responseString); + if (this.apiClient.vertexAI()) { + responseNode = recontextImageResponseFromVertex(responseNode, null); + } else { + throw new UnsupportedOperationException( + "This method is only supported in the Vertex AI client."); + } + return JsonSerializable.fromJsonNode(responseNode, RecontextImageResponse.class); + } + } + /** * Fetches information about a model by name. * diff --git a/src/main/java/com/google/genai/types/ProductImage.java b/src/main/java/com/google/genai/types/ProductImage.java new file mode 100644 index 00000000000..de08c89857e --- /dev/null +++ b/src/main/java/com/google/genai/types/ProductImage.java @@ -0,0 +1,77 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Auto-generated code. Do not edit. + +package com.google.genai.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.google.auto.value.AutoValue; +import com.google.genai.JsonSerializable; +import java.util.Optional; + +/** An image of the product. */ +@AutoValue +@JsonDeserialize(builder = ProductImage.Builder.class) +public abstract class ProductImage extends JsonSerializable { + /** An image of the product to be recontextualized. */ + @JsonProperty("productImage") + public abstract Optional productImage(); + + /** Instantiates a builder for ProductImage. */ + public static Builder builder() { + return new AutoValue_ProductImage.Builder(); + } + + /** Creates a builder with the same values as this instance. */ + public abstract Builder toBuilder(); + + /** Builder for ProductImage. */ + @AutoValue.Builder + public abstract static class Builder { + /** For internal usage. Please use `ProductImage.builder()` for instantiation. */ + @JsonCreator + private static Builder create() { + return new AutoValue_ProductImage.Builder(); + } + + /** + * Setter for productImage. + * + *

    productImage: An image of the product to be recontextualized. + */ + @JsonProperty("productImage") + public abstract Builder productImage(Image productImage); + + /** + * Setter for productImage builder. + * + *

    productImage: An image of the product to be recontextualized. + */ + public Builder productImage(Image.Builder productImageBuilder) { + return productImage(productImageBuilder.build()); + } + + public abstract ProductImage build(); + } + + /** Deserializes a JSON string to a ProductImage object. */ + public static ProductImage fromJson(String jsonString) { + return JsonSerializable.fromJsonString(jsonString, ProductImage.class); + } +} diff --git a/src/main/java/com/google/genai/types/RecontextImageConfig.java b/src/main/java/com/google/genai/types/RecontextImageConfig.java new file mode 100644 index 00000000000..d7bd51e0e67 --- /dev/null +++ b/src/main/java/com/google/genai/types/RecontextImageConfig.java @@ -0,0 +1,231 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Auto-generated code. Do not edit. + +package com.google.genai.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.google.auto.value.AutoValue; +import com.google.errorprone.annotations.CanIgnoreReturnValue; +import com.google.genai.JsonSerializable; +import java.util.Optional; + +/** Configuration for recontextualizing an image. */ +@AutoValue +@JsonDeserialize(builder = RecontextImageConfig.Builder.class) +public abstract class RecontextImageConfig extends JsonSerializable { + /** Used to override HTTP request options. */ + @JsonProperty("httpOptions") + public abstract Optional httpOptions(); + + /** Number of images to generate. */ + @JsonProperty("numberOfImages") + public abstract Optional numberOfImages(); + + /** + * The number of sampling steps. A higher value has better image quality, while a lower value has + * better latency. + */ + @JsonProperty("baseSteps") + public abstract Optional baseSteps(); + + /** Cloud Storage URI used to store the generated images. */ + @JsonProperty("outputGcsUri") + public abstract Optional outputGcsUri(); + + /** Random seed for image generation. */ + @JsonProperty("seed") + public abstract Optional seed(); + + /** Filter level for safety filtering. */ + @JsonProperty("safetyFilterLevel") + public abstract Optional safetyFilterLevel(); + + /** Whether allow to generate person images, and restrict to specific ages. */ + @JsonProperty("personGeneration") + public abstract Optional personGeneration(); + + /** MIME type of the generated image. */ + @JsonProperty("outputMimeType") + public abstract Optional outputMimeType(); + + /** Compression quality of the generated image (for ``image/jpeg`` only). */ + @JsonProperty("outputCompressionQuality") + public abstract Optional outputCompressionQuality(); + + /** Whether to use the prompt rewriting logic. */ + @JsonProperty("enhancePrompt") + public abstract Optional enhancePrompt(); + + /** Instantiates a builder for RecontextImageConfig. */ + public static Builder builder() { + return new AutoValue_RecontextImageConfig.Builder(); + } + + /** Creates a builder with the same values as this instance. */ + public abstract Builder toBuilder(); + + /** Builder for RecontextImageConfig. */ + @AutoValue.Builder + public abstract static class Builder { + /** For internal usage. Please use `RecontextImageConfig.builder()` for instantiation. */ + @JsonCreator + private static Builder create() { + return new AutoValue_RecontextImageConfig.Builder(); + } + + /** + * Setter for httpOptions. + * + *

    httpOptions: Used to override HTTP request options. + */ + @JsonProperty("httpOptions") + public abstract Builder httpOptions(HttpOptions httpOptions); + + /** + * Setter for httpOptions builder. + * + *

    httpOptions: Used to override HTTP request options. + */ + public Builder httpOptions(HttpOptions.Builder httpOptionsBuilder) { + return httpOptions(httpOptionsBuilder.build()); + } + + /** + * Setter for numberOfImages. + * + *

    numberOfImages: Number of images to generate. + */ + @JsonProperty("numberOfImages") + public abstract Builder numberOfImages(Integer numberOfImages); + + /** + * Setter for baseSteps. + * + *

    baseSteps: The number of sampling steps. A higher value has better image quality, while a + * lower value has better latency. + */ + @JsonProperty("baseSteps") + public abstract Builder baseSteps(Integer baseSteps); + + /** + * Setter for outputGcsUri. + * + *

    outputGcsUri: Cloud Storage URI used to store the generated images. + */ + @JsonProperty("outputGcsUri") + public abstract Builder outputGcsUri(String outputGcsUri); + + /** + * Setter for seed. + * + *

    seed: Random seed for image generation. + */ + @JsonProperty("seed") + public abstract Builder seed(Integer seed); + + /** + * Setter for safetyFilterLevel. + * + *

    safetyFilterLevel: Filter level for safety filtering. + */ + @JsonProperty("safetyFilterLevel") + public abstract Builder safetyFilterLevel(SafetyFilterLevel safetyFilterLevel); + + /** + * Setter for safetyFilterLevel given a known enum. + * + *

    safetyFilterLevel: Filter level for safety filtering. + */ + @CanIgnoreReturnValue + public Builder safetyFilterLevel(SafetyFilterLevel.Known knownType) { + return safetyFilterLevel(new SafetyFilterLevel(knownType)); + } + + /** + * Setter for safetyFilterLevel given a string. + * + *

    safetyFilterLevel: Filter level for safety filtering. + */ + @CanIgnoreReturnValue + public Builder safetyFilterLevel(String safetyFilterLevel) { + return safetyFilterLevel(new SafetyFilterLevel(safetyFilterLevel)); + } + + /** + * Setter for personGeneration. + * + *

    personGeneration: Whether allow to generate person images, and restrict to specific ages. + */ + @JsonProperty("personGeneration") + public abstract Builder personGeneration(PersonGeneration personGeneration); + + /** + * Setter for personGeneration given a known enum. + * + *

    personGeneration: Whether allow to generate person images, and restrict to specific ages. + */ + @CanIgnoreReturnValue + public Builder personGeneration(PersonGeneration.Known knownType) { + return personGeneration(new PersonGeneration(knownType)); + } + + /** + * Setter for personGeneration given a string. + * + *

    personGeneration: Whether allow to generate person images, and restrict to specific ages. + */ + @CanIgnoreReturnValue + public Builder personGeneration(String personGeneration) { + return personGeneration(new PersonGeneration(personGeneration)); + } + + /** + * Setter for outputMimeType. + * + *

    outputMimeType: MIME type of the generated image. + */ + @JsonProperty("outputMimeType") + public abstract Builder outputMimeType(String outputMimeType); + + /** + * Setter for outputCompressionQuality. + * + *

    outputCompressionQuality: Compression quality of the generated image (for ``image/jpeg`` + * only). + */ + @JsonProperty("outputCompressionQuality") + public abstract Builder outputCompressionQuality(Integer outputCompressionQuality); + + /** + * Setter for enhancePrompt. + * + *

    enhancePrompt: Whether to use the prompt rewriting logic. + */ + @JsonProperty("enhancePrompt") + public abstract Builder enhancePrompt(boolean enhancePrompt); + + public abstract RecontextImageConfig build(); + } + + /** Deserializes a JSON string to a RecontextImageConfig object. */ + public static RecontextImageConfig fromJson(String jsonString) { + return JsonSerializable.fromJsonString(jsonString, RecontextImageConfig.class); + } +} diff --git a/src/main/java/com/google/genai/types/RecontextImageParameters.java b/src/main/java/com/google/genai/types/RecontextImageParameters.java new file mode 100644 index 00000000000..03d8c95f904 --- /dev/null +++ b/src/main/java/com/google/genai/types/RecontextImageParameters.java @@ -0,0 +1,116 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Auto-generated code. Do not edit. + +package com.google.genai.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.google.api.core.InternalApi; +import com.google.auto.value.AutoValue; +import com.google.genai.JsonSerializable; +import java.util.Optional; + +/** The parameters for recontextualizing an image. */ +@AutoValue +@InternalApi +@JsonDeserialize(builder = RecontextImageParameters.Builder.class) +public abstract class RecontextImageParameters extends JsonSerializable { + /** + * ID of the model to use. For a list of models, see `Google models + * `_. + */ + @JsonProperty("model") + public abstract Optional model(); + + /** A set of source input(s) for image recontextualization. */ + @JsonProperty("source") + public abstract Optional source(); + + /** Configuration for image recontextualization. */ + @JsonProperty("config") + public abstract Optional config(); + + /** Instantiates a builder for RecontextImageParameters. */ + public static Builder builder() { + return new AutoValue_RecontextImageParameters.Builder(); + } + + /** Creates a builder with the same values as this instance. */ + public abstract Builder toBuilder(); + + /** Builder for RecontextImageParameters. */ + @AutoValue.Builder + public abstract static class Builder { + /** For internal usage. Please use `RecontextImageParameters.builder()` for instantiation. */ + @JsonCreator + private static Builder create() { + return new AutoValue_RecontextImageParameters.Builder(); + } + + /** + * Setter for model. + * + *

    model: ID of the model to use. For a list of models, see `Google models + * `_. + */ + @JsonProperty("model") + public abstract Builder model(String model); + + /** + * Setter for source. + * + *

    source: A set of source input(s) for image recontextualization. + */ + @JsonProperty("source") + public abstract Builder source(RecontextImageSource source); + + /** + * Setter for source builder. + * + *

    source: A set of source input(s) for image recontextualization. + */ + public Builder source(RecontextImageSource.Builder sourceBuilder) { + return source(sourceBuilder.build()); + } + + /** + * Setter for config. + * + *

    config: Configuration for image recontextualization. + */ + @JsonProperty("config") + public abstract Builder config(RecontextImageConfig config); + + /** + * Setter for config builder. + * + *

    config: Configuration for image recontextualization. + */ + public Builder config(RecontextImageConfig.Builder configBuilder) { + return config(configBuilder.build()); + } + + public abstract RecontextImageParameters build(); + } + + /** Deserializes a JSON string to a RecontextImageParameters object. */ + public static RecontextImageParameters fromJson(String jsonString) { + return JsonSerializable.fromJsonString(jsonString, RecontextImageParameters.class); + } +} diff --git a/src/main/java/com/google/genai/types/RecontextImageResponse.java b/src/main/java/com/google/genai/types/RecontextImageResponse.java new file mode 100644 index 00000000000..dab46d351e2 --- /dev/null +++ b/src/main/java/com/google/genai/types/RecontextImageResponse.java @@ -0,0 +1,93 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Auto-generated code. Do not edit. + +package com.google.genai.types; + +import static com.google.common.collect.ImmutableList.toImmutableList; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.google.auto.value.AutoValue; +import com.google.genai.JsonSerializable; +import java.util.Arrays; +import java.util.List; +import java.util.Optional; + +/** The output images response. */ +@AutoValue +@JsonDeserialize(builder = RecontextImageResponse.Builder.class) +public abstract class RecontextImageResponse extends JsonSerializable { + /** List of generated images. */ + @JsonProperty("generatedImages") + public abstract Optional> generatedImages(); + + /** Instantiates a builder for RecontextImageResponse. */ + public static Builder builder() { + return new AutoValue_RecontextImageResponse.Builder(); + } + + /** Creates a builder with the same values as this instance. */ + public abstract Builder toBuilder(); + + /** Builder for RecontextImageResponse. */ + @AutoValue.Builder + public abstract static class Builder { + /** For internal usage. Please use `RecontextImageResponse.builder()` for instantiation. */ + @JsonCreator + private static Builder create() { + return new AutoValue_RecontextImageResponse.Builder(); + } + + /** + * Setter for generatedImages. + * + *

    generatedImages: List of generated images. + */ + @JsonProperty("generatedImages") + public abstract Builder generatedImages(List generatedImages); + + /** + * Setter for generatedImages. + * + *

    generatedImages: List of generated images. + */ + public Builder generatedImages(GeneratedImage... generatedImages) { + return generatedImages(Arrays.asList(generatedImages)); + } + + /** + * Setter for generatedImages builder. + * + *

    generatedImages: List of generated images. + */ + public Builder generatedImages(GeneratedImage.Builder... generatedImagesBuilders) { + return generatedImages( + Arrays.asList(generatedImagesBuilders).stream() + .map(GeneratedImage.Builder::build) + .collect(toImmutableList())); + } + + public abstract RecontextImageResponse build(); + } + + /** Deserializes a JSON string to a RecontextImageResponse object. */ + public static RecontextImageResponse fromJson(String jsonString) { + return JsonSerializable.fromJsonString(jsonString, RecontextImageResponse.class); + } +} diff --git a/src/main/java/com/google/genai/types/RecontextImageSource.java b/src/main/java/com/google/genai/types/RecontextImageSource.java new file mode 100644 index 00000000000..5e48c4d48b7 --- /dev/null +++ b/src/main/java/com/google/genai/types/RecontextImageSource.java @@ -0,0 +1,130 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Auto-generated code. Do not edit. + +package com.google.genai.types; + +import static com.google.common.collect.ImmutableList.toImmutableList; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.google.auto.value.AutoValue; +import com.google.genai.JsonSerializable; +import java.util.Arrays; +import java.util.List; +import java.util.Optional; + +/** A set of source input(s) for image recontextualization. */ +@AutoValue +@JsonDeserialize(builder = RecontextImageSource.Builder.class) +public abstract class RecontextImageSource extends JsonSerializable { + /** + * A text prompt for guiding the model during image recontextualization. Not supported for Virtual + * Try-On. + */ + @JsonProperty("prompt") + public abstract Optional prompt(); + + /** Image of the person or subject who will be wearing the product(s). */ + @JsonProperty("personImage") + public abstract Optional personImage(); + + /** A list of product images. */ + @JsonProperty("productImages") + public abstract Optional> productImages(); + + /** Instantiates a builder for RecontextImageSource. */ + public static Builder builder() { + return new AutoValue_RecontextImageSource.Builder(); + } + + /** Creates a builder with the same values as this instance. */ + public abstract Builder toBuilder(); + + /** Builder for RecontextImageSource. */ + @AutoValue.Builder + public abstract static class Builder { + /** For internal usage. Please use `RecontextImageSource.builder()` for instantiation. */ + @JsonCreator + private static Builder create() { + return new AutoValue_RecontextImageSource.Builder(); + } + + /** + * Setter for prompt. + * + *

    prompt: A text prompt for guiding the model during image recontextualization. Not + * supported for Virtual Try-On. + */ + @JsonProperty("prompt") + public abstract Builder prompt(String prompt); + + /** + * Setter for personImage. + * + *

    personImage: Image of the person or subject who will be wearing the product(s). + */ + @JsonProperty("personImage") + public abstract Builder personImage(Image personImage); + + /** + * Setter for personImage builder. + * + *

    personImage: Image of the person or subject who will be wearing the product(s). + */ + public Builder personImage(Image.Builder personImageBuilder) { + return personImage(personImageBuilder.build()); + } + + /** + * Setter for productImages. + * + *

    productImages: A list of product images. + */ + @JsonProperty("productImages") + public abstract Builder productImages(List productImages); + + /** + * Setter for productImages. + * + *

    productImages: A list of product images. + */ + public Builder productImages(ProductImage... productImages) { + return productImages(Arrays.asList(productImages)); + } + + /** + * Setter for productImages builder. + * + *

    productImages: A list of product images. + */ + public Builder productImages(ProductImage.Builder... productImagesBuilders) { + return productImages( + Arrays.asList(productImagesBuilders).stream() + .map(ProductImage.Builder::build) + .collect(toImmutableList())); + } + + public abstract RecontextImageSource build(); + } + + /** Deserializes a JSON string to a RecontextImageSource object. */ + public static RecontextImageSource fromJson(String jsonString) { + return JsonSerializable.fromJsonString(jsonString, RecontextImageSource.class); + } +} From 4912ff421d6d3bc40edd70a939f71f5f33f58597 Mon Sep 17 00:00:00 2001 From: Kaituo Huang Date: Thu, 31 Jul 2025 16:30:26 -0700 Subject: [PATCH 124/602] feat: enable responseId for Gemini Developer API remove thinking tests in v1alpha, thinking is GA now PiperOrigin-RevId: 789512508 --- src/main/java/com/google/genai/Batches.java | 7 +++++ src/main/java/com/google/genai/Models.java | 21 ++++++++++----- .../genai/types/GenerateContentResponse.java | 27 ++++++++++--------- 3 files changed, 36 insertions(+), 19 deletions(-) diff --git a/src/main/java/com/google/genai/Batches.java b/src/main/java/com/google/genai/Batches.java index a93e4fbd0ef..5e0183b6f3e 100644 --- a/src/main/java/com/google/genai/Batches.java +++ b/src/main/java/com/google/genai/Batches.java @@ -1889,6 +1889,13 @@ ObjectNode generateContentResponseFromMldev(JsonNode fromObject, ObjectNode pare Common.getValueByPath(fromObject, new String[] {"promptFeedback"})); } + if (Common.getValueByPath(fromObject, new String[] {"responseId"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"responseId"}, + Common.getValueByPath(fromObject, new String[] {"responseId"})); + } + if (Common.getValueByPath(fromObject, new String[] {"usageMetadata"}) != null) { Common.setValueByPath( toObject, diff --git a/src/main/java/com/google/genai/Models.java b/src/main/java/com/google/genai/Models.java index 2081aea0298..962c133a470 100644 --- a/src/main/java/com/google/genai/Models.java +++ b/src/main/java/com/google/genai/Models.java @@ -4509,6 +4509,13 @@ ObjectNode generateContentResponseFromMldev(JsonNode fromObject, ObjectNode pare Common.getValueByPath(fromObject, new String[] {"promptFeedback"})); } + if (Common.getValueByPath(fromObject, new String[] {"responseId"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"responseId"}, + Common.getValueByPath(fromObject, new String[] {"responseId"})); + } + if (Common.getValueByPath(fromObject, new String[] {"usageMetadata"}) != null) { Common.setValueByPath( toObject, @@ -5305,13 +5312,6 @@ ObjectNode generateContentResponseFromVertex(JsonNode fromObject, ObjectNode par Common.getValueByPath(fromObject, new String[] {"createTime"})); } - if (Common.getValueByPath(fromObject, new String[] {"responseId"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"responseId"}, - Common.getValueByPath(fromObject, new String[] {"responseId"})); - } - if (Common.getValueByPath(fromObject, new String[] {"modelVersion"}) != null) { Common.setValueByPath( toObject, @@ -5326,6 +5326,13 @@ ObjectNode generateContentResponseFromVertex(JsonNode fromObject, ObjectNode par Common.getValueByPath(fromObject, new String[] {"promptFeedback"})); } + if (Common.getValueByPath(fromObject, new String[] {"responseId"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"responseId"}, + Common.getValueByPath(fromObject, new String[] {"responseId"})); + } + if (Common.getValueByPath(fromObject, new String[] {"usageMetadata"}) != null) { Common.setValueByPath( toObject, diff --git a/src/main/java/com/google/genai/types/GenerateContentResponse.java b/src/main/java/com/google/genai/types/GenerateContentResponse.java index c00a72a4b02..946fda87597 100644 --- a/src/main/java/com/google/genai/types/GenerateContentResponse.java +++ b/src/main/java/com/google/genai/types/GenerateContentResponse.java @@ -53,10 +53,6 @@ public abstract class GenerateContentResponse extends JsonSerializable { @JsonProperty("createTime") public abstract Optional createTime(); - /** Identifier for each response. */ - @JsonProperty("responseId") - public abstract Optional responseId(); - /** The history of automatic function calling. */ @JsonProperty("automaticFunctionCallingHistory") public abstract Optional> automaticFunctionCallingHistory(); @@ -72,6 +68,12 @@ public abstract class GenerateContentResponse extends JsonSerializable { @JsonProperty("promptFeedback") public abstract Optional promptFeedback(); + /** + * Output only. response_id is used to identify each response. It is the encoding of the event_id. + */ + @JsonProperty("responseId") + public abstract Optional responseId(); + /** Usage metadata about the response(s). */ @JsonProperty("usageMetadata") public abstract Optional usageMetadata(); @@ -147,14 +149,6 @@ public Builder candidates(Candidate.Builder... candidatesBuilders) { @JsonProperty("createTime") public abstract Builder createTime(Instant createTime); - /** - * Setter for responseId. - * - *

    responseId: Identifier for each response. - */ - @JsonProperty("responseId") - public abstract Builder responseId(String responseId); - /** * Setter for automaticFunctionCallingHistory. * @@ -216,6 +210,15 @@ public Builder promptFeedback( return promptFeedback(promptFeedbackBuilder.build()); } + /** + * Setter for responseId. + * + *

    responseId: Output only. response_id is used to identify each response. It is the encoding + * of the event_id. + */ + @JsonProperty("responseId") + public abstract Builder responseId(String responseId); + /** * Setter for usageMetadata. * From cc0a0aa28cae618acf617ab92819df78d80afea5 Mon Sep 17 00:00:00 2001 From: Jaycee Li Date: Fri, 1 Aug 2025 10:17:40 -0700 Subject: [PATCH 125/602] docs: Add Imagen and Veo to README PiperOrigin-RevId: 789807106 --- README.md | 268 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 268 insertions(+) diff --git a/README.md b/README.md index 41deec6b25c..864cb1ded5b 100644 --- a/README.md +++ b/README.md @@ -545,6 +545,274 @@ public class EmbedContent { } ``` +### Imagen + +Imagen is a text-to-image GenAI service. + +#### Generate Images + +The `generateImages` method helps you create high-quality, unique images given a +text prompt. + +```java +package ; + +import com.google.genai.Client; +import com.google.genai.types.GenerateImagesConfig; +import com.google.genai.types.GenerateImagesResponse; +import com.google.genai.types.Image; + +public class GenerateImages { + public static void main(String[] args) { + Client client = new Client(); + + GenerateImagesConfig config = + GenerateImagesConfig.builder() + .numberOfImages(1) + .outputMimeType("image/jpeg") + .includeSafetyAttributes(true) + .build(); + + GenerateImagesResponse response = + client.models.generateImages( + "imagen-3.0-generate-002", "Robot holding a red skateboard", config); + + response.generatedImages().ifPresent( + images -> { + System.out.println("Generated " + images.size() + " images."); + Image image = images.get(0).image().orElse(null); + // Do something with the image. + } + ); + } +} +``` + +#### Upscale Image + +The `upscaleImage` method allows you to upscale an image. This feature is only +supported in Vertex AI. + +```java +package ; + +import com.google.genai.Client; +import com.google.genai.types.Image; +import com.google.genai.types.UpscaleImageConfig; +import com.google.genai.types.UpscaleImageResponse; + +public class UpscaleImage { + public static void main(String[] args) { + Client client = Client.builder().vertexAI(true).build(); + + Image image = Image.fromFile("path/to/your/image"); + + UpscaleImageConfig config = + UpscaleImageConfig.builder() + .outputMimeType("image/jpeg") + .enhanceInputImage(true) + .imagePreservationFactor(0.6f) + .build(); + + UpscaleImageResponse response = + client.models.upscaleImage("imagen-3.0-generate-002", image, "x2", config); + + response.generatedImages().ifPresent( + images -> { + Image upscaledImage = images.get(0).image().orElse(null); + // Do something with the upscaled image. + } + ); + } +} +``` + +#### Edit Image + +The `editImage` method lets you edit an image. You can input reference images +(ex. mask reference for inpainting, or style reference for style transfer) in +addition to a text prompt to guide the editing. + +This feature uses a different model than `generateImages` and `upscaleImage`. It +is only supported in Vertex AI. + +```java +package ; + +import com.google.genai.Client; +import com.google.genai.types.EditImageConfig; +import com.google.genai.types.EditImageResponse; +import com.google.genai.types.EditMode; +import com.google.genai.types.Image; +import com.google.genai.types.MaskReferenceConfig; +import com.google.genai.types.MaskReferenceImage; +import com.google.genai.types.MaskReferenceMode; +import com.google.genai.types.RawReferenceImage; +import com.google.genai.types.ReferenceImage; +import java.util.ArrayList; + +public class EditImage { + public static void main(String[] args) { + Client client = Client.builder().vertexAI(true).build(); + + Image image = Image.fromFile("path/to/your/image"); + + // Edit image with a mask. + EditImageConfig config = + EditImageConfig.builder() + .editMode(EditMode.Known.EDIT_MODE_INPAINT_INSERTION) + .numberOfImages(1) + .outputMimeType("image/jpeg") + .build(); + + ArrayList referenceImages = new ArrayList<>(); + RawReferenceImage rawReferenceImage = + RawReferenceImage.builder().referenceImage(image).referenceId(1).build(); + referenceImages.add(rawReferenceImage); + + MaskReferenceImage maskReferenceImage = + MaskReferenceImage.builder() + .referenceId(2) + .config( + MaskReferenceConfig.builder() + .maskMode(MaskReferenceMode.Known.MASK_MODE_BACKGROUND) + .maskDilation(0.0f)) + .build(); + referenceImages.add(maskReferenceImage); + + EditImageResponse response = + client.models.editImage( + "imagen-3.0-capability-001", "Sunlight and clear sky", referenceImages, config); + + response.generatedImages().ifPresent( + images -> { + Image editedImage = images.get(0).image().orElse(null); + // Do something with the edited image. + } + ); + } +} +``` + +### Veo + +Veo is a video generation GenAI service. + +#### Generate Videos (Text to Video) + +```java +package ; + +import com.google.genai.Client; +import com.google.genai.types.GenerateVideosConfig; +import com.google.genai.types.GenerateVideosOperation; +import com.google.genai.types.Video; + +public class GenerateVideosWithText { + public static void main(String[] args) { + Client client = new Client(); + + GenerateVideosConfig config = + GenerateVideosConfig.builder() + .numberOfVideos(1) + .enhancePrompt(true) + .durationSeconds(5) + .build(); + + // generateVideos returns an operation + GenerateVideosOperation operation = + client.models.generateVideos( + "veo-2.0-generate-001", "A neon hologram of a cat driving at top speed", null, config); + + // When the operation hasn't been finished, operation.done() is empty + while (!operation.done().isPresent()) { + try { + System.out.println("Waiting for operation to complete..."); + Thread.sleep(10000); + // Sleep for 10 seconds and check the operation again + operation = client.operations.getVideosOperation(operation, null); + } catch (InterruptedException e) { + System.out.println("Thread was interrupted while sleeping."); + Thread.currentThread().interrupt(); + } + } + + operation.response().ifPresent( + response -> { + response.generatedVideos().ifPresent( + videos -> { + System.out.println("Generated " + videos.size() + " videos."); + Video video = videos.get(0).video().orElse(null); + // Do something with the generated video + } + ); + } + ); + } +} +``` + +#### Generate Videos (Image to Video) + +```java +package ; + +import com.google.genai.Client; +import com.google.genai.types.GenerateVideosConfig; +import com.google.genai.types.GenerateVideosOperation; +import com.google.genai.types.Image; +import com.google.genai.types.Video; + +public class GenerateVideosWithImage { + public static void main(String[] args) { + Client client = new Client(); + + Image image = Image.fromFile("path/to/your/image"); + + GenerateVideosConfig config = + GenerateVideosConfig.builder() + .numberOfVideos(1) + .enhancePrompt(true) + .durationSeconds(5) + .build(); + + // generateVideos returns an operation + GenerateVideosOperation operation = + client.models.generateVideos( + "veo-2.0-generate-001", + "Night sky", + image, + config); + + // When the operation hasn't been finished, operation.done() is empty + while (!operation.done().isPresent()) { + try { + System.out.println("Waiting for operation to complete..."); + Thread.sleep(10000); + // Sleep for 10 seconds and check the operation again + operation = client.operations.getVideosOperation(operation, null); + } catch (InterruptedException e) { + System.out.println("Thread was interrupted while sleeping."); + Thread.currentThread().interrupt(); + } + } + + operation.response().ifPresent( + response -> { + response.generatedVideos().ifPresent( + videos -> { + System.out.println("Generated " + videos.size() + " videos."); + Video video = videos.get(0).video().orElse(null); + // Do something with the generated video + } + ); + } + ); + } +} +``` + + ## Versioning This library follows [Semantic Versioning](http://semver.org/). From 036bac89fda15022ec4d9c5c73ba81ad0a6cc9be Mon Sep 17 00:00:00 2001 From: Qiao Wang Date: Fri, 1 Aug 2025 11:51:03 -0700 Subject: [PATCH 126/602] feat: support extraBody in HttpOptions class PiperOrigin-RevId: 789841733 --- .../genai/examples/HttpOptionsExtraBody.java | 104 ++++++++ src/main/java/com/google/genai/ApiClient.java | 68 ++++- .../com/google/genai/types/HttpOptions.java | 19 ++ .../com/google/genai/HttpApiClientTest.java | 232 ++++++++++++++++++ 4 files changed, 422 insertions(+), 1 deletion(-) create mode 100644 examples/src/main/java/com/google/genai/examples/HttpOptionsExtraBody.java diff --git a/examples/src/main/java/com/google/genai/examples/HttpOptionsExtraBody.java b/examples/src/main/java/com/google/genai/examples/HttpOptionsExtraBody.java new file mode 100644 index 00000000000..8a531e1b62e --- /dev/null +++ b/examples/src/main/java/com/google/genai/examples/HttpOptionsExtraBody.java @@ -0,0 +1,104 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Usage: + * + *

    1a. If you are using Vertex AI, setup ADC to get credentials: + * https://cloud.google.com/docs/authentication/provide-credentials-adc#google-idp + * + *

    Then set Project, Location, and USE_VERTEXAI flag as environment variables: + * + *

    export GOOGLE_CLOUD_PROJECT=YOUR_PROJECT + * + *

    export GOOGLE_CLOUD_LOCATION=YOUR_LOCATION + * + *

    export GOOGLE_GENAI_USE_VERTEXAI=true + * + *

    1b. If you are using Gemini Developer API, set an API key environment variable. You can find a + * list of available API keys here: https://aistudio.google.com/app/apikey + * + *

    export GOOGLE_API_KEY=YOUR_API_KEY + * + *

    2. Compile the java package and run the sample code. + * + *

    mvn clean compile exec:java -Dexec.mainClass="com.google.genai.examples.HttpOptionsExtraBody" + * -Dexec.args="YOUR_MODEL_ID" + */ +package com.google.genai.examples; + +import com.google.genai.Client; +import com.google.genai.types.HttpOptions; +import com.google.genai.types.GenerateContentConfig; +import com.google.genai.types.GenerateContentResponse; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; + +/** + * An example of using HttpOption extraBody to inject additional parameters to http request body. + */ +public final class HttpOptionsExtraBody { + public static void main(String[] args) { + String modelId = "gemini-2.0-flash-001"; + if (args.length != 0) { + modelId = args[0]; + } + + // Instantiate the client. The client by default uses the Gemini Developer API. + // It gets the API + // key from the environment variable `GOOGLE_API_KEY`. Vertex AI API can be used + // by setting the + // environment variables `GOOGLE_CLOUD_LOCATION` and `GOOGLE_CLOUD_PROJECT`, as + // well as setting + // `GOOGLE_GENAI_USE_VERTEXAI` to "true". + // + // Note: Some services are only available in a specific API backend (Gemini or + // Vertex), you will + // get a `UnsupportedOperationException` if you try to use a service that is not + // available in + // the backend you are using. + Client client = new Client(); + + if (client.vertexAI()) { + System.out.println("Using Vertex AI"); + } else { + System.out.println("Using Gemini Developer API"); + } + + GenerateContentResponse response = + client.models.generateContent( + modelId, + "What is your name?", + GenerateContentConfig.builder() + .httpOptions( + HttpOptions.builder() + .extraBody( + ImmutableMap.of( + "systemInstruction", + ImmutableMap.of( + "parts", + ImmutableList.of( + ImmutableMap.of("text", "You are a chatbot."))))) + .build()) + .build()); + + System.out.println( + "GenerateContent prompt token count: " + response.usageMetadata().get().promptTokenCount()); + } + + private HttpOptionsExtraBody() {} +} diff --git a/src/main/java/com/google/genai/ApiClient.java b/src/main/java/com/google/genai/ApiClient.java index 48d5f3c7878..eb7049d4b62 100644 --- a/src/main/java/com/google/genai/ApiClient.java +++ b/src/main/java/com/google/genai/ApiClient.java @@ -19,6 +19,8 @@ import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.collect.ImmutableMap.toImmutableMap; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; import com.google.auth.oauth2.GoogleCredentials; import com.google.common.base.Ascii; import com.google.common.collect.ImmutableMap; @@ -29,6 +31,7 @@ import com.google.genai.types.HttpOptions; import java.io.IOException; import java.time.Duration; +import java.util.List; import java.util.Map; import java.util.Optional; import java.util.logging.Logger; @@ -40,7 +43,6 @@ import okhttp3.RequestBody; import org.jspecify.annotations.Nullable; - /** Interface for an API client which issues HTTP requests to the GenAI APIs. */ abstract class ApiClient { @@ -236,6 +238,7 @@ private OkHttpClient createHttpClient( } /** Builds a HTTP request given the http method, path, and request json string. */ + @SuppressWarnings("unchecked") protected Request buildRequest( String httpMethod, String path, @@ -280,12 +283,31 @@ protected Request buildRequest( throw new IllegalArgumentException("Unsupported HTTP method: " + capitalizedHttpMethod); } + ObjectMapper objectMapper = new ObjectMapper(); RequestBody body; if (METHODS_WITH_BODY.contains(capitalizedHttpMethod)) { body = RequestBody.create(requestJson, MediaType.parse("application/json")); } else { body = null; } + + if (mergedHttpOptions.extraBody().isPresent() && body != null) { + try { + Map requestBodyMap = objectMapper.readValue(requestJson, Map.class); + mergeMaps(requestBodyMap, mergedHttpOptions.extraBody().get()); + requestJson = objectMapper.writeValueAsString(requestBodyMap); + body = RequestBody.create(requestJson, MediaType.parse("application/json")); + } catch (JsonProcessingException e) { + logger.warning("Failed to merge extraBody into request body: " + e.getMessage()); + // If merging fails, proceed with the original request body + body = RequestBody.create(requestJson, MediaType.parse("application/json")); + } + } else if (mergedHttpOptions.extraBody().isPresent()) { + logger.warning( + "HttpOptions.extraBody is set, but the HTTP method does not support a request body. " + + "The extraBody will be ignored."); + } + Request.Builder requestBuilder = new Request.Builder().url(requestUrl).method(capitalizedHttpMethod, body); @@ -382,6 +404,47 @@ OkHttpClient httpClient() { return httpClient; } + /** + * Merges two maps recursively. If a key exists in both maps, the value from `source` overwrites + * the value in `target`. If the value is a list, then update the whole list. A warning is logged + * if the types of the values for the same key are different. + * + * @param target The target map to merge into. + * @param source The source map to merge from. + */ + @SuppressWarnings("unchecked") + private void mergeMaps(Map target, Map source) { + for (Map.Entry entry : source.entrySet()) { + String key = entry.getKey(); + Object sourceValue = entry.getValue(); + + if (target.containsKey(key)) { + Object targetValue = target.get(key); + + if (targetValue instanceof Map && sourceValue instanceof Map) { + // Both values are maps, recursively merge them + mergeMaps((Map) targetValue, (Map) sourceValue); + } else if (targetValue instanceof List && sourceValue instanceof List) { + // Both values are lists, replace the target list with the source list + target.put(key, sourceValue); + } else { + // Values are not both maps or both lists, check if they have the same type + if (targetValue.getClass() != sourceValue.getClass()) { + logger.warning( + String.format( + "Type mismatch for key '%s'. Original type: %s, new type: %s. Overwriting" + + " with the new value.", + key, targetValue.getClass().getName(), sourceValue.getClass().getName())); + } + target.put(key, sourceValue); + } + } else { + // Key does not exist in target, add it + target.put(key, sourceValue); + } + } + } + private Optional> getTimeoutHeader(HttpOptions httpOptionsToApply) { if (httpOptionsToApply.timeout().isPresent()) { int timeoutInSeconds = (int) Math.ceil((double) httpOptionsToApply.timeout().get() / 1000.0); @@ -426,6 +489,9 @@ HttpOptions mergeHttpOptions(HttpOptions httpOptionsToApply) { toImmutableMap(Map.Entry::getKey, Map.Entry::getValue, (val1, val2) -> val2)); mergedHttpOptionsBuilder.headers(mergedHeaders); } + if (httpOptionsToApply.extraBody().isPresent()) { + mergedHttpOptionsBuilder.extraBody(httpOptionsToApply.extraBody().get()); + } return mergedHttpOptionsBuilder.build(); } diff --git a/src/main/java/com/google/genai/types/HttpOptions.java b/src/main/java/com/google/genai/types/HttpOptions.java index 46326f2778f..ed51e7d7874 100644 --- a/src/main/java/com/google/genai/types/HttpOptions.java +++ b/src/main/java/com/google/genai/types/HttpOptions.java @@ -46,6 +46,14 @@ public abstract class HttpOptions extends JsonSerializable { @JsonProperty("timeout") public abstract Optional timeout(); + /** + * Extra parameters to add to the request body. The structure must match the backend API's request + * structure. - VertexAI backend API docs: https://cloud.google.com/vertex-ai/docs/reference/rest + * - GeminiAPI backend API docs: https://ai.google.dev/api/rest + */ + @JsonProperty("extraBody") + public abstract Optional> extraBody(); + /** Instantiates a builder for HttpOptions. */ public static Builder builder() { return new AutoValue_HttpOptions.Builder(); @@ -95,6 +103,17 @@ private static Builder create() { @JsonProperty("timeout") public abstract Builder timeout(Integer timeout); + /** + * Setter for extraBody. + * + *

    extraBody: Extra parameters to add to the request body. The structure must match the + * backend API's request structure. - VertexAI backend API docs: + * https://cloud.google.com/vertex-ai/docs/reference/rest - GeminiAPI backend API docs: + * https://ai.google.dev/api/rest + */ + @JsonProperty("extraBody") + public abstract Builder extraBody(Map extraBody); + public abstract HttpOptions build(); } diff --git a/src/test/java/com/google/genai/HttpApiClientTest.java b/src/test/java/com/google/genai/HttpApiClientTest.java index 9a065cb909a..e6d974be779 100644 --- a/src/test/java/com/google/genai/HttpApiClientTest.java +++ b/src/test/java/com/google/genai/HttpApiClientTest.java @@ -16,6 +16,7 @@ package com.google.genai; +import com.fasterxml.jackson.core.type.TypeReference; import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; import static com.github.tomakehurst.wiremock.client.WireMock.post; import static com.github.tomakehurst.wiremock.client.WireMock.stubFor; @@ -33,6 +34,8 @@ import com.github.tomakehurst.wiremock.WireMockServer; import com.github.tomakehurst.wiremock.client.WireMock; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; import com.google.auth.oauth2.AccessToken; import com.google.auth.oauth2.GoogleCredentials; import com.google.common.collect.ImmutableMap; @@ -59,6 +62,8 @@ import org.mockito.Mock; import org.mockito.MockedStatic; import org.mockito.Mockito; +import java.io.IOException; +import java.util.Map; @ExtendWith(EnvironmentVariablesMockingExtension.class) public class HttpApiClientTest { @@ -214,6 +219,233 @@ public void testRequestWithHttpOptions() throws Exception { assertEquals("header", capturedRequest.header("test")); } + @Test + public void testRequestWithHttpOptions_extraBody_addNewKey() throws Exception { + // Arrange + HttpApiClient client = + new HttpApiClient(Optional.of(API_KEY), Optional.empty(), Optional.empty()); + setMockClient(client); + HttpOptions httpOptions = + HttpOptions.builder().extraBody(ImmutableMap.of("newKey", "newValue")).build(); + + // Act + client.request("POST", TEST_PATH, TEST_REQUEST_JSON, Optional.of(httpOptions)); + + // Assert + ArgumentCaptor requestCaptor = ArgumentCaptor.forClass(Request.class); + verify(mockHttpClient).newCall(requestCaptor.capture()); + Request capturedRequest = requestCaptor.getValue(); + + RequestBody body = capturedRequest.body(); + assertNotNull(body); + final Buffer buffer = new Buffer(); + body.writeTo(buffer); + String requestBody = buffer.readUtf8(); + + Map expectedMap = + ImmutableMap.of("test", "request-json", "newKey", "newValue"); + ObjectMapper mapper = new ObjectMapper(); + Map actualMap = mapper.readValue(requestBody, new TypeReference>() {}); + + assertEquals(expectedMap, actualMap); + } + + @Test + public void testRequestWithHttpOptions_extraBody_overwriteKey() throws Exception { + // Arrange + HttpApiClient client = + new HttpApiClient(Optional.of(API_KEY), Optional.empty(), Optional.empty()); + setMockClient(client); + HttpOptions httpOptions = + HttpOptions.builder().extraBody(ImmutableMap.of("test", "overwritten")).build(); + + // Act + client.request("POST", TEST_PATH, TEST_REQUEST_JSON, Optional.of(httpOptions)); + + // Assert + ArgumentCaptor requestCaptor = ArgumentCaptor.forClass(Request.class); + verify(mockHttpClient).newCall(requestCaptor.capture()); + Request capturedRequest = requestCaptor.getValue(); + + RequestBody body = capturedRequest.body(); + assertNotNull(body); + final Buffer buffer = new Buffer(); + body.writeTo(buffer); + String requestBody = buffer.readUtf8(); + + Map expectedMap = ImmutableMap.of("test", "overwritten"); + ObjectMapper mapper = new ObjectMapper(); + Map actualMap = mapper.readValue(requestBody, new TypeReference>() {}); + + assertEquals(expectedMap, actualMap); + } + + @Test + public void testRequestWithHttpOptions_extraBody_recursiveMerge() throws Exception { + // Arrange + HttpApiClient client = + new HttpApiClient(Optional.of(API_KEY), Optional.empty(), Optional.empty()); + setMockClient(client); + String initialJson = "{\"nested\": {\"key1\": \"value1\"}, \"key_to_keep\": \"v_keep\"}"; + HttpOptions httpOptions = + HttpOptions.builder() + .extraBody(ImmutableMap.of("nested", ImmutableMap.of("key2", "value2"))) + .build(); + + // Act + client.request("POST", TEST_PATH, initialJson, Optional.of(httpOptions)); + + // Assert + ArgumentCaptor requestCaptor = ArgumentCaptor.forClass(Request.class); + verify(mockHttpClient).newCall(requestCaptor.capture()); + Request capturedRequest = requestCaptor.getValue(); + + RequestBody body = capturedRequest.body(); + assertNotNull(body); + final Buffer buffer = new Buffer(); + body.writeTo(buffer); + String requestBody = buffer.readUtf8(); + + Map expectedMap = + ImmutableMap.of( + "nested", ImmutableMap.of("key1", "value1", "key2", "value2"), + "key_to_keep", + "v_keep"); + ObjectMapper mapper = new ObjectMapper(); + Map actualMap = mapper.readValue(requestBody, new TypeReference>() {}); + assertEquals(expectedMap, actualMap); + } + + @Test + public void testRequestWithHttpOptions_extraBody_overwriteList() throws Exception { + // Arrange + HttpApiClient client = + new HttpApiClient(Optional.of(API_KEY), Optional.empty(), Optional.empty()); + setMockClient(client); + String initialJson = "{\"list\": [1, 2]}"; + HttpOptions httpOptions = + HttpOptions.builder() + .extraBody(ImmutableMap.of("list", com.google.common.collect.ImmutableList.of(3, 4))) + .build(); + + // Act + client.request("POST", TEST_PATH, initialJson, Optional.of(httpOptions)); + + // Assert + ArgumentCaptor requestCaptor = ArgumentCaptor.forClass(Request.class); + verify(mockHttpClient).newCall(requestCaptor.capture()); + Request capturedRequest = requestCaptor.getValue(); + + RequestBody body = capturedRequest.body(); + assertNotNull(body); + final Buffer buffer = new Buffer(); + body.writeTo(buffer); + String requestBody = buffer.readUtf8(); + + Map expectedMap = + ImmutableMap.of("list", com.google.common.collect.ImmutableList.of(3, 4)); + ObjectMapper mapper = new ObjectMapper(); + Map actualMap = mapper.readValue(requestBody, new TypeReference>() {}); + assertEquals(expectedMap, actualMap); + } + + @Test + public void testRequestWithHttpOptions_extraBody_overwriteWithDifferentType() throws Exception { + // Arrange + HttpApiClient client = + new HttpApiClient(Optional.of(API_KEY), Optional.empty(), Optional.empty()); + setMockClient(client); + String initialJson = "{\"key\": \"string_value\"}"; + HttpOptions httpOptions = HttpOptions.builder().extraBody(ImmutableMap.of("key", 123)).build(); + + // Act + client.request("POST", TEST_PATH, initialJson, Optional.of(httpOptions)); + + // Assert + ArgumentCaptor requestCaptor = ArgumentCaptor.forClass(Request.class); + verify(mockHttpClient).newCall(requestCaptor.capture()); + Request capturedRequest = requestCaptor.getValue(); + + RequestBody body = capturedRequest.body(); + assertNotNull(body); + final Buffer buffer = new Buffer(); + body.writeTo(buffer); + String requestBody = buffer.readUtf8(); + + Map expectedMap = ImmutableMap.of("key", 123); + ObjectMapper mapper = new ObjectMapper(); + Map actualMap = mapper.readValue(requestBody, new TypeReference>() {}); + + assertEquals(expectedMap, actualMap); + } + + @Test + public void testRequestWithHttpOptions_extraBody_complexMerge() throws Exception { + // Arrange + HttpApiClient client = + new HttpApiClient(Optional.of(API_KEY), Optional.empty(), Optional.empty()); + setMockClient(client); + String initialJson = + "{\"a\": 1, \"b\": {\"c\": 2, \"d\": [\"x\", \"y\"]}, \"e\": \"original\"}"; + HttpOptions httpOptions = + HttpOptions.builder() + .extraBody( + ImmutableMap.of( + "b", + ImmutableMap.of( + "d", com.google.common.collect.ImmutableList.of("z"), "f", "new_f"), + "e", + "overwritten")) + .build(); + + // Act + client.request("POST", TEST_PATH, initialJson, Optional.of(httpOptions)); + + // Assert + ArgumentCaptor requestCaptor = ArgumentCaptor.forClass(Request.class); + verify(mockHttpClient).newCall(requestCaptor.capture()); + Request capturedRequest = requestCaptor.getValue(); + + RequestBody body = capturedRequest.body(); + assertNotNull(body); + final Buffer buffer = new Buffer(); + body.writeTo(buffer); + String requestBody = buffer.readUtf8(); + + Map expectedMap = + ImmutableMap.of( + "a", + 1, + "b", + ImmutableMap.of( + "c", 2, "d", com.google.common.collect.ImmutableList.of("z"), "f", "new_f"), + "e", + "overwritten"); + ObjectMapper mapper = new ObjectMapper(); + Map actualMap = mapper.readValue(requestBody, new TypeReference>() {}); + assertEquals(expectedMap, actualMap); + } + + @Test + public void testRequestWithHttpOptions_extraBody_getNoBody() throws Exception { + // Arrange + HttpApiClient client = + new HttpApiClient(Optional.of(API_KEY), Optional.empty(), Optional.empty()); + setMockClient(client); + HttpOptions httpOptions = + HttpOptions.builder().extraBody(ImmutableMap.of("newKey", "newValue")).build(); + + // Act + client.request("GET", TEST_PATH, "", Optional.of(httpOptions)); + + // Assert + ArgumentCaptor requestCaptor = ArgumentCaptor.forClass(Request.class); + verify(mockHttpClient).newCall(requestCaptor.capture()); + Request capturedRequest = requestCaptor.getValue(); + + assertNull(capturedRequest.body()); + } + @Test public void testRequestWithInvalidHttpMethod() throws Exception { // Arrange From c50c755c08efbed5a62e1006890b1d0bd9956702 Mon Sep 17 00:00:00 2001 From: Matthew Tang Date: Fri, 1 Aug 2025 16:25:52 -0700 Subject: [PATCH 127/602] feat: Add image_size field for Gemini Developer API Imagen 4 generation PiperOrigin-RevId: 789937547 --- src/main/java/com/google/genai/Models.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/google/genai/Models.java b/src/main/java/com/google/genai/Models.java index 962c133a470..2cc5007c2b7 100644 --- a/src/main/java/com/google/genai/Models.java +++ b/src/main/java/com/google/genai/Models.java @@ -1313,8 +1313,11 @@ ObjectNode generateImagesConfigToMldev(JsonNode fromObject, ObjectNode parentObj throw new IllegalArgumentException("addWatermark parameter is not supported in Gemini API."); } - if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"imageSize"}))) { - throw new IllegalArgumentException("imageSize parameter is not supported in Gemini API."); + if (Common.getValueByPath(fromObject, new String[] {"imageSize"}) != null) { + Common.setValueByPath( + parentObject, + new String[] {"parameters", "sampleImageSize"}, + Common.getValueByPath(fromObject, new String[] {"imageSize"})); } if (!Common.isZero(Common.getValueByPath(fromObject, new String[] {"enhancePrompt"}))) { From cb27222a7f7cdf442a7d6b61496709f7cf084a91 Mon Sep 17 00:00:00 2001 From: Annie Luc Date: Wed, 6 Aug 2025 12:20:17 -0700 Subject: [PATCH 128/602] feat: Support new enum types for UrlRetrievalStatus PiperOrigin-RevId: 791793857 --- .../java/com/google/genai/types/UrlRetrievalStatus.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/google/genai/types/UrlRetrievalStatus.java b/src/main/java/com/google/genai/types/UrlRetrievalStatus.java index 4e59731ae48..0b0a831f476 100644 --- a/src/main/java/com/google/genai/types/UrlRetrievalStatus.java +++ b/src/main/java/com/google/genai/types/UrlRetrievalStatus.java @@ -35,7 +35,13 @@ public enum Known { URL_RETRIEVAL_STATUS_SUCCESS, /** Url retrieval is failed due to error. */ - URL_RETRIEVAL_STATUS_ERROR + URL_RETRIEVAL_STATUS_ERROR, + + /** Url retrieval is failed because the content is behind paywall. */ + URL_RETRIEVAL_STATUS_PAYWALL, + + /** Url retrieval is failed because the content is unsafe. */ + URL_RETRIEVAL_STATUS_UNSAFE } private Known urlRetrievalStatusEnum; From 1c7b26aa7a12ba50d60c288ce95818dc50dcdc6d Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Wed, 6 Aug 2025 16:41:20 -0700 Subject: [PATCH 129/602] chore(main): release 1.11.0 (#444) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- .release-please-manifest.json | 2 +- CHANGELOG.md | 27 +++++++++++++++++++ README.md | 2 +- examples/pom.xml | 4 +-- pom.xml | 2 +- src/main/java/com/google/genai/ApiClient.java | 2 +- versions.txt | 2 +- 7 files changed, 34 insertions(+), 7 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index eb4e0dba726..caf1487126e 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "1.10.0" + ".": "1.11.0" } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index a770a7362d1..d5221c95990 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,32 @@ # Changelog +## [1.11.0](https://github.com/googleapis/java-genai/compare/v1.10.0...v1.11.0) (2025-08-06) + + +### Features + +* Add image_size field for Gemini Developer API Imagen 4 generation ([c50c755](https://github.com/googleapis/java-genai/commit/c50c755c08efbed5a62e1006890b1d0bd9956702)) +* allow methods in batch to return headers in sdk_http_response by default ([f937dd1](https://github.com/googleapis/java-genai/commit/f937dd1752e8a774e06d9afc6953211bd569fc35)) +* allow methods in models to return headers in sdk_http_response by default. ([7415e88](https://github.com/googleapis/java-genai/commit/7415e88f7520c695afc63f937b8b547c2877f4f6)) +* allow methods in tuning to return headers in sdk_http_response by default ([1b1205b](https://github.com/googleapis/java-genai/commit/1b1205b052a6d1d6782c6cdc190afdb48113ee9c)) +* enable responseId for Gemini Developer API ([4912ff4](https://github.com/googleapis/java-genai/commit/4912ff421d6d3bc40edd70a939f71f5f33f58597)) +* support extraBody in HttpOptions class ([036bac8](https://github.com/googleapis/java-genai/commit/036bac89fda15022ec4d9c5c73ba81ad0a6cc9be)) +* Support image recontext on Vertex ([e7de8c8](https://github.com/googleapis/java-genai/commit/e7de8c83bbd2e7e37c2198c3501e2d5bee58c0a2)) +* Support new enum types for UrlRetrievalStatus ([cb27222](https://github.com/googleapis/java-genai/commit/cb27222a7f7cdf442a7d6b61496709f7cf084a91)) +* support response headers in Go for all methods. ([222b41e](https://github.com/googleapis/java-genai/commit/222b41e196afc13775cc22292a58567d7b4859fa)) + + +### Bug Fixes + +* Remove duplicate JavaTimeModule in JsonSerializable ([a7dbd4c](https://github.com/googleapis/java-genai/commit/a7dbd4c527456f20aa5d154bde14f74f6e66d174)) + + +### Documentation + +* Add Imagen and Veo to README ([cc0a0aa](https://github.com/googleapis/java-genai/commit/cc0a0aa28cae618acf617ab92819df78d80afea5)) +* Add latest models features in README ([a2eccaf](https://github.com/googleapis/java-genai/commit/a2eccafae5c6c9b82341a148b572bf9bc80f241b)) +* mark Client as thread safe and Chat as not thread safe ([be3e50e](https://github.com/googleapis/java-genai/commit/be3e50e4217780329c0636fd7f8a1b743e7f9597)) + ## [1.10.0](https://github.com/googleapis/java-genai/compare/v1.9.0...v1.10.0) (2025-07-23) diff --git a/README.md b/README.md index 864cb1ded5b..a6ecd160f19 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ If you're using Maven, add the following to your dependencies: com.google.genai google-genai - 1.10.0 + 1.11.0 ``` diff --git a/examples/pom.xml b/examples/pom.xml index aa3685b77c3..371222548cf 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -5,7 +5,7 @@ com.google.genai.examples google-genai-examples - 1.11.0-SNAPSHOT + 1.11.0 google-genai-examples @@ -13,7 +13,7 @@ 1.8 1.8 - 1.11.0-SNAPSHOT + 1.11.0 diff --git a/pom.xml b/pom.xml index aef2e2b8d25..8a9d4d56566 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ com.google.genai google-genai google-genai - 1.11.0-SNAPSHOT + 1.11.0 jar Java idiomatic SDK for the Gemini Developer APIs and Vertex AI APIs. diff --git a/src/main/java/com/google/genai/ApiClient.java b/src/main/java/com/google/genai/ApiClient.java index eb7049d4b62..b21bbce16d0 100644 --- a/src/main/java/com/google/genai/ApiClient.java +++ b/src/main/java/com/google/genai/ApiClient.java @@ -47,7 +47,7 @@ abstract class ApiClient { // {x-version-update-start:google-genai:released} - private static final String SDK_VERSION = "1.10.0"; + private static final String SDK_VERSION = "1.11.0"; // {x-version-update-end:google-genai:released} private static final Logger logger = Logger.getLogger(ApiClient.class.getName()); diff --git a/versions.txt b/versions.txt index 91058d0cec9..19877f6dca6 100644 --- a/versions.txt +++ b/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-genai:1.10.0:1.11.0-SNAPSHOT +google-genai:1.11.0:1.11.0 From 1b803175fa00f431bad960d969e5b2e76f0f91f4 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Wed, 6 Aug 2025 18:05:05 -0700 Subject: [PATCH 130/602] chore(main): release 1.12.0-SNAPSHOT (#470) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- examples/pom.xml | 4 ++-- pom.xml | 2 +- versions.txt | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/pom.xml b/examples/pom.xml index 371222548cf..668efc7f7f1 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -5,7 +5,7 @@ com.google.genai.examples google-genai-examples - 1.11.0 + 1.12.0-SNAPSHOT google-genai-examples @@ -13,7 +13,7 @@ 1.8 1.8 - 1.11.0 + 1.12.0-SNAPSHOT diff --git a/pom.xml b/pom.xml index 8a9d4d56566..6aec20651eb 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ com.google.genai google-genai google-genai - 1.11.0 + 1.12.0-SNAPSHOT jar Java idiomatic SDK for the Gemini Developer APIs and Vertex AI APIs. diff --git a/versions.txt b/versions.txt index 19877f6dca6..57695e74f99 100644 --- a/versions.txt +++ b/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-genai:1.11.0:1.11.0 +google-genai:1.11.0:1.12.0-SNAPSHOT From 2e180cc829783cca421adf4c8890f10ac3412be9 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Wed, 6 Aug 2025 17:05:59 -0700 Subject: [PATCH 131/602] Copybara import of the project: -- 62786df9b657c538691db3243dcf9f581a9778ad by release-please[bot] <55107282+release-please[bot]@users.noreply.github.com>: chore(main): release 1.11.0 COPYBARA_INTEGRATE_REVIEW=https://github.com/googleapis/java-genai/pull/444 from googleapis:release-please--branches--main 62786df9b657c538691db3243dcf9f581a9778ad PiperOrigin-RevId: 791901761 --- examples/pom.xml | 4 ++-- pom.xml | 2 +- versions.txt | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/pom.xml b/examples/pom.xml index 668efc7f7f1..371222548cf 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -5,7 +5,7 @@ com.google.genai.examples google-genai-examples - 1.12.0-SNAPSHOT + 1.11.0 google-genai-examples @@ -13,7 +13,7 @@ 1.8 1.8 - 1.12.0-SNAPSHOT + 1.11.0 diff --git a/pom.xml b/pom.xml index 6aec20651eb..8a9d4d56566 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ com.google.genai google-genai google-genai - 1.12.0-SNAPSHOT + 1.11.0 jar Java idiomatic SDK for the Gemini Developer APIs and Vertex AI APIs. diff --git a/versions.txt b/versions.txt index 57695e74f99..19877f6dca6 100644 --- a/versions.txt +++ b/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-genai:1.11.0:1.12.0-SNAPSHOT +google-genai:1.11.0:1.11.0 From 393045a986db3c77fbf816ee32ed2de2c24e387f Mon Sep 17 00:00:00 2001 From: Mark Daoust Date: Thu, 7 Aug 2025 09:45:52 -0700 Subject: [PATCH 132/602] No public description PiperOrigin-RevId: 792198742 --- examples/pom.xml | 4 ++-- pom.xml | 2 +- versions.txt | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/pom.xml b/examples/pom.xml index 371222548cf..668efc7f7f1 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -5,7 +5,7 @@ com.google.genai.examples google-genai-examples - 1.11.0 + 1.12.0-SNAPSHOT google-genai-examples @@ -13,7 +13,7 @@ 1.8 1.8 - 1.11.0 + 1.12.0-SNAPSHOT diff --git a/pom.xml b/pom.xml index 8a9d4d56566..6aec20651eb 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ com.google.genai google-genai google-genai - 1.11.0 + 1.12.0-SNAPSHOT jar Java idiomatic SDK for the Gemini Developer APIs and Vertex AI APIs. diff --git a/versions.txt b/versions.txt index 19877f6dca6..57695e74f99 100644 --- a/versions.txt +++ b/versions.txt @@ -1,4 +1,4 @@ # Format: # module:released-version:current-version -google-genai:1.11.0:1.11.0 +google-genai:1.11.0:1.12.0-SNAPSHOT From c498c8b0cb84fa6ba39062493c2bd88b2a06a862 Mon Sep 17 00:00:00 2001 From: Mark Daoust Date: Thu, 7 Aug 2025 10:31:23 -0700 Subject: [PATCH 133/602] docs: Remove no-op PRs from changelog. PiperOrigin-RevId: 792217789 --- CHANGELOG.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d5221c95990..249f16ae153 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,9 +6,6 @@ ### Features * Add image_size field for Gemini Developer API Imagen 4 generation ([c50c755](https://github.com/googleapis/java-genai/commit/c50c755c08efbed5a62e1006890b1d0bd9956702)) -* allow methods in batch to return headers in sdk_http_response by default ([f937dd1](https://github.com/googleapis/java-genai/commit/f937dd1752e8a774e06d9afc6953211bd569fc35)) -* allow methods in models to return headers in sdk_http_response by default. ([7415e88](https://github.com/googleapis/java-genai/commit/7415e88f7520c695afc63f937b8b547c2877f4f6)) -* allow methods in tuning to return headers in sdk_http_response by default ([1b1205b](https://github.com/googleapis/java-genai/commit/1b1205b052a6d1d6782c6cdc190afdb48113ee9c)) * enable responseId for Gemini Developer API ([4912ff4](https://github.com/googleapis/java-genai/commit/4912ff421d6d3bc40edd70a939f71f5f33f58597)) * support extraBody in HttpOptions class ([036bac8](https://github.com/googleapis/java-genai/commit/036bac89fda15022ec4d9c5c73ba81ad0a6cc9be)) * Support image recontext on Vertex ([e7de8c8](https://github.com/googleapis/java-genai/commit/e7de8c83bbd2e7e37c2198c3501e2d5bee58c0a2)) From b2472b3467a171743422072827bf92780b127d42 Mon Sep 17 00:00:00 2001 From: Sara Robinson Date: Thu, 7 Aug 2025 12:57:52 -0700 Subject: [PATCH 134/602] chore: Add new types from discovery doc PiperOrigin-RevId: 792274865 --- src/main/java/com/google/genai/Batches.java | 7 - src/main/java/com/google/genai/Caches.java | 14 -- .../java/com/google/genai/LiveConverters.java | 14 -- src/main/java/com/google/genai/Models.java | 14 -- .../com/google/genai/TokensConverters.java | 7 - src/main/java/com/google/genai/Tunings.java | 70 ++++++ .../genai/types/GeminiPreferenceExample.java | 126 ++++++++++ .../GeminiPreferenceExampleCompletion.java | 92 +++++++ .../types/GenerationConfigThinkingConfig.java | 8 +- .../google/genai/types/GroundingChunk.java | 21 ++ .../genai/types/GroundingChunkMaps.java | 135 +++++++++++ .../GroundingChunkMapsPlaceAnswerSources.java | 112 +++++++++ ...psPlaceAnswerSourcesAuthorAttribution.java | 99 ++++++++ ...nkMapsPlaceAnswerSourcesReviewSnippet.java | 140 +++++++++++ .../google/genai/types/GroundingMetadata.java | 18 ++ .../com/google/genai/types/PreTunedModel.java | 102 ++++++++ .../PreferenceOptimizationDataStats.java | 227 ++++++++++++++++++ ...PreferenceOptimizationHyperParameters.java | 134 +++++++++++ .../types/PreferenceOptimizationSpec.java | 110 +++++++++ .../types/SupervisedHyperParameters.java | 33 ++- .../genai/types/SupervisedTuningSpec.java | 33 +++ .../java/com/google/genai/types/Tool.java | 26 -- .../com/google/genai/types/TunedModel.java | 10 +- .../google/genai/types/TuningDataStats.java | 23 ++ .../com/google/genai/types/TuningJob.java | 103 ++++++++ .../com/google/genai/types/TuningMode.java | 107 +++++++++ .../com/google/genai/types/TuningTask.java | 107 +++++++++ .../genai/types/VeoHyperParameters.java | 119 +++++++++ .../com/google/genai/types/VeoTuningSpec.java | 111 +++++++++ 29 files changed, 2030 insertions(+), 92 deletions(-) create mode 100644 src/main/java/com/google/genai/types/GeminiPreferenceExample.java create mode 100644 src/main/java/com/google/genai/types/GeminiPreferenceExampleCompletion.java create mode 100644 src/main/java/com/google/genai/types/GroundingChunkMaps.java create mode 100644 src/main/java/com/google/genai/types/GroundingChunkMapsPlaceAnswerSources.java create mode 100644 src/main/java/com/google/genai/types/GroundingChunkMapsPlaceAnswerSourcesAuthorAttribution.java create mode 100644 src/main/java/com/google/genai/types/GroundingChunkMapsPlaceAnswerSourcesReviewSnippet.java create mode 100644 src/main/java/com/google/genai/types/PreTunedModel.java create mode 100644 src/main/java/com/google/genai/types/PreferenceOptimizationDataStats.java create mode 100644 src/main/java/com/google/genai/types/PreferenceOptimizationHyperParameters.java create mode 100644 src/main/java/com/google/genai/types/PreferenceOptimizationSpec.java create mode 100644 src/main/java/com/google/genai/types/TuningMode.java create mode 100644 src/main/java/com/google/genai/types/TuningTask.java create mode 100644 src/main/java/com/google/genai/types/VeoHyperParameters.java create mode 100644 src/main/java/com/google/genai/types/VeoTuningSpec.java diff --git a/src/main/java/com/google/genai/Batches.java b/src/main/java/com/google/genai/Batches.java index 5e0183b6f3e..56f01b82df8 100644 --- a/src/main/java/com/google/genai/Batches.java +++ b/src/main/java/com/google/genai/Batches.java @@ -620,13 +620,6 @@ ObjectNode toolToMldev(JsonNode fromObject, ObjectNode parentObject) { Common.getValueByPath(fromObject, new String[] {"codeExecution"})); } - if (Common.getValueByPath(fromObject, new String[] {"computerUse"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"computerUse"}, - Common.getValueByPath(fromObject, new String[] {"computerUse"})); - } - return toObject; } diff --git a/src/main/java/com/google/genai/Caches.java b/src/main/java/com/google/genai/Caches.java index f7e807b750a..f0aca32bf46 100644 --- a/src/main/java/com/google/genai/Caches.java +++ b/src/main/java/com/google/genai/Caches.java @@ -435,13 +435,6 @@ ObjectNode toolToMldev(JsonNode fromObject, ObjectNode parentObject) { Common.getValueByPath(fromObject, new String[] {"codeExecution"})); } - if (Common.getValueByPath(fromObject, new String[] {"computerUse"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"computerUse"}, - Common.getValueByPath(fromObject, new String[] {"computerUse"})); - } - return toObject; } @@ -1248,13 +1241,6 @@ ObjectNode toolToVertex(JsonNode fromObject, ObjectNode parentObject) { Common.getValueByPath(fromObject, new String[] {"codeExecution"})); } - if (Common.getValueByPath(fromObject, new String[] {"computerUse"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"computerUse"}, - Common.getValueByPath(fromObject, new String[] {"computerUse"})); - } - return toObject; } diff --git a/src/main/java/com/google/genai/LiveConverters.java b/src/main/java/com/google/genai/LiveConverters.java index 2979be9fd8c..4874818da82 100644 --- a/src/main/java/com/google/genai/LiveConverters.java +++ b/src/main/java/com/google/genai/LiveConverters.java @@ -514,13 +514,6 @@ ObjectNode toolToMldev(JsonNode fromObject, ObjectNode parentObject) { Common.getValueByPath(fromObject, new String[] {"codeExecution"})); } - if (Common.getValueByPath(fromObject, new String[] {"computerUse"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"computerUse"}, - Common.getValueByPath(fromObject, new String[] {"computerUse"})); - } - return toObject; } @@ -1771,13 +1764,6 @@ ObjectNode toolToVertex(JsonNode fromObject, ObjectNode parentObject) { Common.getValueByPath(fromObject, new String[] {"codeExecution"})); } - if (Common.getValueByPath(fromObject, new String[] {"computerUse"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"computerUse"}, - Common.getValueByPath(fromObject, new String[] {"computerUse"})); - } - return toObject; } diff --git a/src/main/java/com/google/genai/Models.java b/src/main/java/com/google/genai/Models.java index 2cc5007c2b7..436399c72d6 100644 --- a/src/main/java/com/google/genai/Models.java +++ b/src/main/java/com/google/genai/Models.java @@ -666,13 +666,6 @@ ObjectNode toolToMldev(JsonNode fromObject, ObjectNode parentObject) { Common.getValueByPath(fromObject, new String[] {"codeExecution"})); } - if (Common.getValueByPath(fromObject, new String[] {"computerUse"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"computerUse"}, - Common.getValueByPath(fromObject, new String[] {"computerUse"})); - } - return toObject; } @@ -2415,13 +2408,6 @@ ObjectNode toolToVertex(JsonNode fromObject, ObjectNode parentObject) { Common.getValueByPath(fromObject, new String[] {"codeExecution"})); } - if (Common.getValueByPath(fromObject, new String[] {"computerUse"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"computerUse"}, - Common.getValueByPath(fromObject, new String[] {"computerUse"})); - } - return toObject; } diff --git a/src/main/java/com/google/genai/TokensConverters.java b/src/main/java/com/google/genai/TokensConverters.java index d08f9ed8e5e..1396d8a34ad 100644 --- a/src/main/java/com/google/genai/TokensConverters.java +++ b/src/main/java/com/google/genai/TokensConverters.java @@ -514,13 +514,6 @@ ObjectNode toolToMldev(JsonNode fromObject, ObjectNode parentObject) { Common.getValueByPath(fromObject, new String[] {"codeExecution"})); } - if (Common.getValueByPath(fromObject, new String[] {"computerUse"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"computerUse"}, - Common.getValueByPath(fromObject, new String[] {"computerUse"})); - } - return toObject; } diff --git a/src/main/java/com/google/genai/Tunings.java b/src/main/java/com/google/genai/Tunings.java index 364c77d2a14..f86b91f4371 100644 --- a/src/main/java/com/google/genai/Tunings.java +++ b/src/main/java/com/google/genai/Tunings.java @@ -549,6 +549,13 @@ ObjectNode tuningJobFromMldev(JsonNode fromObject, ObjectNode parentObject) { toObject)); } + if (Common.getValueByPath(fromObject, new String[] {"customBaseModel"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"customBaseModel"}, + Common.getValueByPath(fromObject, new String[] {"customBaseModel"})); + } + if (Common.getValueByPath(fromObject, new String[] {"distillationSpec"}) != null) { Common.setValueByPath( toObject, @@ -570,6 +577,13 @@ ObjectNode tuningJobFromMldev(JsonNode fromObject, ObjectNode parentObject) { Common.getValueByPath(fromObject, new String[] {"labels"})); } + if (Common.getValueByPath(fromObject, new String[] {"outputUri"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"outputUri"}, + Common.getValueByPath(fromObject, new String[] {"outputUri"})); + } + if (Common.getValueByPath(fromObject, new String[] {"pipelineJob"}) != null) { Common.setValueByPath( toObject, @@ -577,6 +591,20 @@ ObjectNode tuningJobFromMldev(JsonNode fromObject, ObjectNode parentObject) { Common.getValueByPath(fromObject, new String[] {"pipelineJob"})); } + if (Common.getValueByPath(fromObject, new String[] {"preTunedModel"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"preTunedModel"}, + Common.getValueByPath(fromObject, new String[] {"preTunedModel"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"preferenceOptimizationSpec"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"preferenceOptimizationSpec"}, + Common.getValueByPath(fromObject, new String[] {"preferenceOptimizationSpec"})); + } + if (Common.getValueByPath(fromObject, new String[] {"satisfiesPzi"}) != null) { Common.setValueByPath( toObject, @@ -605,6 +633,13 @@ ObjectNode tuningJobFromMldev(JsonNode fromObject, ObjectNode parentObject) { Common.getValueByPath(fromObject, new String[] {"tunedModelDisplayName"})); } + if (Common.getValueByPath(fromObject, new String[] {"veoTuningSpec"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"veoTuningSpec"}, + Common.getValueByPath(fromObject, new String[] {"veoTuningSpec"})); + } + return toObject; } @@ -840,6 +875,13 @@ ObjectNode tuningJobFromVertex(JsonNode fromObject, ObjectNode parentObject) { Common.getValueByPath(fromObject, new String[] {"partnerModelTuningSpec"})); } + if (Common.getValueByPath(fromObject, new String[] {"customBaseModel"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"customBaseModel"}, + Common.getValueByPath(fromObject, new String[] {"customBaseModel"})); + } + if (Common.getValueByPath(fromObject, new String[] {"distillationSpec"}) != null) { Common.setValueByPath( toObject, @@ -861,6 +903,13 @@ ObjectNode tuningJobFromVertex(JsonNode fromObject, ObjectNode parentObject) { Common.getValueByPath(fromObject, new String[] {"labels"})); } + if (Common.getValueByPath(fromObject, new String[] {"outputUri"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"outputUri"}, + Common.getValueByPath(fromObject, new String[] {"outputUri"})); + } + if (Common.getValueByPath(fromObject, new String[] {"pipelineJob"}) != null) { Common.setValueByPath( toObject, @@ -868,6 +917,20 @@ ObjectNode tuningJobFromVertex(JsonNode fromObject, ObjectNode parentObject) { Common.getValueByPath(fromObject, new String[] {"pipelineJob"})); } + if (Common.getValueByPath(fromObject, new String[] {"preTunedModel"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"preTunedModel"}, + Common.getValueByPath(fromObject, new String[] {"preTunedModel"})); + } + + if (Common.getValueByPath(fromObject, new String[] {"preferenceOptimizationSpec"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"preferenceOptimizationSpec"}, + Common.getValueByPath(fromObject, new String[] {"preferenceOptimizationSpec"})); + } + if (Common.getValueByPath(fromObject, new String[] {"satisfiesPzi"}) != null) { Common.setValueByPath( toObject, @@ -896,6 +959,13 @@ ObjectNode tuningJobFromVertex(JsonNode fromObject, ObjectNode parentObject) { Common.getValueByPath(fromObject, new String[] {"tunedModelDisplayName"})); } + if (Common.getValueByPath(fromObject, new String[] {"veoTuningSpec"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"veoTuningSpec"}, + Common.getValueByPath(fromObject, new String[] {"veoTuningSpec"})); + } + return toObject; } diff --git a/src/main/java/com/google/genai/types/GeminiPreferenceExample.java b/src/main/java/com/google/genai/types/GeminiPreferenceExample.java new file mode 100644 index 00000000000..53d5e2cbd7c --- /dev/null +++ b/src/main/java/com/google/genai/types/GeminiPreferenceExample.java @@ -0,0 +1,126 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Auto-generated code. Do not edit. + +package com.google.genai.types; + +import static com.google.common.collect.ImmutableList.toImmutableList; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.google.auto.value.AutoValue; +import com.google.genai.JsonSerializable; +import java.util.Arrays; +import java.util.List; +import java.util.Optional; + +/** Input example for preference optimization. */ +@AutoValue +@JsonDeserialize(builder = GeminiPreferenceExample.Builder.class) +public abstract class GeminiPreferenceExample extends JsonSerializable { + /** List of completions for a given prompt. */ + @JsonProperty("completions") + public abstract Optional> completions(); + + /** Multi-turn contents that represents the Prompt. */ + @JsonProperty("contents") + public abstract Optional> contents(); + + /** Instantiates a builder for GeminiPreferenceExample. */ + public static Builder builder() { + return new AutoValue_GeminiPreferenceExample.Builder(); + } + + /** Creates a builder with the same values as this instance. */ + public abstract Builder toBuilder(); + + /** Builder for GeminiPreferenceExample. */ + @AutoValue.Builder + public abstract static class Builder { + /** For internal usage. Please use `GeminiPreferenceExample.builder()` for instantiation. */ + @JsonCreator + private static Builder create() { + return new AutoValue_GeminiPreferenceExample.Builder(); + } + + /** + * Setter for completions. + * + *

    completions: List of completions for a given prompt. + */ + @JsonProperty("completions") + public abstract Builder completions(List completions); + + /** + * Setter for completions. + * + *

    completions: List of completions for a given prompt. + */ + public Builder completions(GeminiPreferenceExampleCompletion... completions) { + return completions(Arrays.asList(completions)); + } + + /** + * Setter for completions builder. + * + *

    completions: List of completions for a given prompt. + */ + public Builder completions(GeminiPreferenceExampleCompletion.Builder... completionsBuilders) { + return completions( + Arrays.asList(completionsBuilders).stream() + .map(GeminiPreferenceExampleCompletion.Builder::build) + .collect(toImmutableList())); + } + + /** + * Setter for contents. + * + *

    contents: Multi-turn contents that represents the Prompt. + */ + @JsonProperty("contents") + public abstract Builder contents(List contents); + + /** + * Setter for contents. + * + *

    contents: Multi-turn contents that represents the Prompt. + */ + public Builder contents(Content... contents) { + return contents(Arrays.asList(contents)); + } + + /** + * Setter for contents builder. + * + *

    contents: Multi-turn contents that represents the Prompt. + */ + public Builder contents(Content.Builder... contentsBuilders) { + return contents( + Arrays.asList(contentsBuilders).stream() + .map(Content.Builder::build) + .collect(toImmutableList())); + } + + public abstract GeminiPreferenceExample build(); + } + + /** Deserializes a JSON string to a GeminiPreferenceExample object. */ + public static GeminiPreferenceExample fromJson(String jsonString) { + return JsonSerializable.fromJsonString(jsonString, GeminiPreferenceExample.class); + } +} diff --git a/src/main/java/com/google/genai/types/GeminiPreferenceExampleCompletion.java b/src/main/java/com/google/genai/types/GeminiPreferenceExampleCompletion.java new file mode 100644 index 00000000000..6f3ba60cd4e --- /dev/null +++ b/src/main/java/com/google/genai/types/GeminiPreferenceExampleCompletion.java @@ -0,0 +1,92 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Auto-generated code. Do not edit. + +package com.google.genai.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.google.auto.value.AutoValue; +import com.google.genai.JsonSerializable; +import java.util.Optional; + +/** Completion and its preference score. */ +@AutoValue +@JsonDeserialize(builder = GeminiPreferenceExampleCompletion.Builder.class) +public abstract class GeminiPreferenceExampleCompletion extends JsonSerializable { + /** Single turn completion for the given prompt. */ + @JsonProperty("completion") + public abstract Optional completion(); + + /** The score for the given completion. */ + @JsonProperty("score") + public abstract Optional score(); + + /** Instantiates a builder for GeminiPreferenceExampleCompletion. */ + public static Builder builder() { + return new AutoValue_GeminiPreferenceExampleCompletion.Builder(); + } + + /** Creates a builder with the same values as this instance. */ + public abstract Builder toBuilder(); + + /** Builder for GeminiPreferenceExampleCompletion. */ + @AutoValue.Builder + public abstract static class Builder { + /** + * For internal usage. Please use `GeminiPreferenceExampleCompletion.builder()` for + * instantiation. + */ + @JsonCreator + private static Builder create() { + return new AutoValue_GeminiPreferenceExampleCompletion.Builder(); + } + + /** + * Setter for completion. + * + *

    completion: Single turn completion for the given prompt. + */ + @JsonProperty("completion") + public abstract Builder completion(Content completion); + + /** + * Setter for completion builder. + * + *

    completion: Single turn completion for the given prompt. + */ + public Builder completion(Content.Builder completionBuilder) { + return completion(completionBuilder.build()); + } + + /** + * Setter for score. + * + *

    score: The score for the given completion. + */ + @JsonProperty("score") + public abstract Builder score(Float score); + + public abstract GeminiPreferenceExampleCompletion build(); + } + + /** Deserializes a JSON string to a GeminiPreferenceExampleCompletion object. */ + public static GeminiPreferenceExampleCompletion fromJson(String jsonString) { + return JsonSerializable.fromJsonString(jsonString, GeminiPreferenceExampleCompletion.class); + } +} diff --git a/src/main/java/com/google/genai/types/GenerationConfigThinkingConfig.java b/src/main/java/com/google/genai/types/GenerationConfigThinkingConfig.java index 115bf7cfb76..cd312b0197f 100644 --- a/src/main/java/com/google/genai/types/GenerationConfigThinkingConfig.java +++ b/src/main/java/com/google/genai/types/GenerationConfigThinkingConfig.java @@ -36,10 +36,7 @@ public abstract class GenerationConfigThinkingConfig extends JsonSerializable { @JsonProperty("includeThoughts") public abstract Optional includeThoughts(); - /** - * Optional. Indicates the thinking budget in tokens. This is only applied when enable_thinking is - * true. - */ + /** Optional. Indicates the thinking budget in tokens. */ @JsonProperty("thinkingBudget") public abstract Optional thinkingBudget(); @@ -74,8 +71,7 @@ private static Builder create() { /** * Setter for thinkingBudget. * - *

    thinkingBudget: Optional. Indicates the thinking budget in tokens. This is only applied - * when enable_thinking is true. + *

    thinkingBudget: Optional. Indicates the thinking budget in tokens. */ @JsonProperty("thinkingBudget") public abstract Builder thinkingBudget(Integer thinkingBudget); diff --git a/src/main/java/com/google/genai/types/GroundingChunk.java b/src/main/java/com/google/genai/types/GroundingChunk.java index 2e6a2aa4c41..64b7bd0dbac 100644 --- a/src/main/java/com/google/genai/types/GroundingChunk.java +++ b/src/main/java/com/google/genai/types/GroundingChunk.java @@ -29,6 +29,10 @@ @AutoValue @JsonDeserialize(builder = GroundingChunk.Builder.class) public abstract class GroundingChunk extends JsonSerializable { + /** Grounding chunk from Google Maps. */ + @JsonProperty("maps") + public abstract Optional maps(); + /** Grounding chunk from context retrieved by the retrieval tools. */ @JsonProperty("retrievedContext") public abstract Optional retrievedContext(); @@ -54,6 +58,23 @@ private static Builder create() { return new AutoValue_GroundingChunk.Builder(); } + /** + * Setter for maps. + * + *

    maps: Grounding chunk from Google Maps. + */ + @JsonProperty("maps") + public abstract Builder maps(GroundingChunkMaps maps); + + /** + * Setter for maps builder. + * + *

    maps: Grounding chunk from Google Maps. + */ + public Builder maps(GroundingChunkMaps.Builder mapsBuilder) { + return maps(mapsBuilder.build()); + } + /** * Setter for retrievedContext. * diff --git a/src/main/java/com/google/genai/types/GroundingChunkMaps.java b/src/main/java/com/google/genai/types/GroundingChunkMaps.java new file mode 100644 index 00000000000..57ae2172fc2 --- /dev/null +++ b/src/main/java/com/google/genai/types/GroundingChunkMaps.java @@ -0,0 +1,135 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Auto-generated code. Do not edit. + +package com.google.genai.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.google.auto.value.AutoValue; +import com.google.genai.JsonSerializable; +import java.util.Optional; + +/** Chunk from Google Maps. */ +@AutoValue +@JsonDeserialize(builder = GroundingChunkMaps.Builder.class) +public abstract class GroundingChunkMaps extends JsonSerializable { + /** + * Sources used to generate the place answer. This includes review snippets and photos that were + * used to generate the answer, as well as uris to flag content. + */ + @JsonProperty("placeAnswerSources") + public abstract Optional placeAnswerSources(); + + /** + * This Place's resource name, in `places/{place_id}` format. Can be used to look up the Place. + */ + @JsonProperty("placeId") + public abstract Optional placeId(); + + /** Text of the chunk. */ + @JsonProperty("text") + public abstract Optional text(); + + /** Title of the chunk. */ + @JsonProperty("title") + public abstract Optional title(); + + /** URI reference of the chunk. */ + @JsonProperty("uri") + public abstract Optional uri(); + + /** Instantiates a builder for GroundingChunkMaps. */ + public static Builder builder() { + return new AutoValue_GroundingChunkMaps.Builder(); + } + + /** Creates a builder with the same values as this instance. */ + public abstract Builder toBuilder(); + + /** Builder for GroundingChunkMaps. */ + @AutoValue.Builder + public abstract static class Builder { + /** For internal usage. Please use `GroundingChunkMaps.builder()` for instantiation. */ + @JsonCreator + private static Builder create() { + return new AutoValue_GroundingChunkMaps.Builder(); + } + + /** + * Setter for placeAnswerSources. + * + *

    placeAnswerSources: Sources used to generate the place answer. This includes review + * snippets and photos that were used to generate the answer, as well as uris to flag content. + */ + @JsonProperty("placeAnswerSources") + public abstract Builder placeAnswerSources( + GroundingChunkMapsPlaceAnswerSources placeAnswerSources); + + /** + * Setter for placeAnswerSources builder. + * + *

    placeAnswerSources: Sources used to generate the place answer. This includes review + * snippets and photos that were used to generate the answer, as well as uris to flag content. + */ + public Builder placeAnswerSources( + GroundingChunkMapsPlaceAnswerSources.Builder placeAnswerSourcesBuilder) { + return placeAnswerSources(placeAnswerSourcesBuilder.build()); + } + + /** + * Setter for placeId. + * + *

    placeId: This Place's resource name, in `places/{place_id}` format. Can be used to look up + * the Place. + */ + @JsonProperty("placeId") + public abstract Builder placeId(String placeId); + + /** + * Setter for text. + * + *

    text: Text of the chunk. + */ + @JsonProperty("text") + public abstract Builder text(String text); + + /** + * Setter for title. + * + *

    title: Title of the chunk. + */ + @JsonProperty("title") + public abstract Builder title(String title); + + /** + * Setter for uri. + * + *

    uri: URI reference of the chunk. + */ + @JsonProperty("uri") + public abstract Builder uri(String uri); + + public abstract GroundingChunkMaps build(); + } + + /** Deserializes a JSON string to a GroundingChunkMaps object. */ + public static GroundingChunkMaps fromJson(String jsonString) { + return JsonSerializable.fromJsonString(jsonString, GroundingChunkMaps.class); + } +} diff --git a/src/main/java/com/google/genai/types/GroundingChunkMapsPlaceAnswerSources.java b/src/main/java/com/google/genai/types/GroundingChunkMapsPlaceAnswerSources.java new file mode 100644 index 00000000000..6d08bdc6966 --- /dev/null +++ b/src/main/java/com/google/genai/types/GroundingChunkMapsPlaceAnswerSources.java @@ -0,0 +1,112 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Auto-generated code. Do not edit. + +package com.google.genai.types; + +import static com.google.common.collect.ImmutableList.toImmutableList; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.google.auto.value.AutoValue; +import com.google.genai.JsonSerializable; +import java.util.Arrays; +import java.util.List; +import java.util.Optional; + +/** Sources used to generate the place answer. */ +@AutoValue +@JsonDeserialize(builder = GroundingChunkMapsPlaceAnswerSources.Builder.class) +public abstract class GroundingChunkMapsPlaceAnswerSources extends JsonSerializable { + /** A link where users can flag a problem with the generated answer. */ + @JsonProperty("flagContentUri") + public abstract Optional flagContentUri(); + + /** Snippets of reviews that are used to generate the answer. */ + @JsonProperty("reviewSnippets") + public abstract Optional> + reviewSnippets(); + + /** Instantiates a builder for GroundingChunkMapsPlaceAnswerSources. */ + public static Builder builder() { + return new AutoValue_GroundingChunkMapsPlaceAnswerSources.Builder(); + } + + /** Creates a builder with the same values as this instance. */ + public abstract Builder toBuilder(); + + /** Builder for GroundingChunkMapsPlaceAnswerSources. */ + @AutoValue.Builder + public abstract static class Builder { + /** + * For internal usage. Please use `GroundingChunkMapsPlaceAnswerSources.builder()` for + * instantiation. + */ + @JsonCreator + private static Builder create() { + return new AutoValue_GroundingChunkMapsPlaceAnswerSources.Builder(); + } + + /** + * Setter for flagContentUri. + * + *

    flagContentUri: A link where users can flag a problem with the generated answer. + */ + @JsonProperty("flagContentUri") + public abstract Builder flagContentUri(String flagContentUri); + + /** + * Setter for reviewSnippets. + * + *

    reviewSnippets: Snippets of reviews that are used to generate the answer. + */ + @JsonProperty("reviewSnippets") + public abstract Builder reviewSnippets( + List reviewSnippets); + + /** + * Setter for reviewSnippets. + * + *

    reviewSnippets: Snippets of reviews that are used to generate the answer. + */ + public Builder reviewSnippets( + GroundingChunkMapsPlaceAnswerSourcesReviewSnippet... reviewSnippets) { + return reviewSnippets(Arrays.asList(reviewSnippets)); + } + + /** + * Setter for reviewSnippets builder. + * + *

    reviewSnippets: Snippets of reviews that are used to generate the answer. + */ + public Builder reviewSnippets( + GroundingChunkMapsPlaceAnswerSourcesReviewSnippet.Builder... reviewSnippetsBuilders) { + return reviewSnippets( + Arrays.asList(reviewSnippetsBuilders).stream() + .map(GroundingChunkMapsPlaceAnswerSourcesReviewSnippet.Builder::build) + .collect(toImmutableList())); + } + + public abstract GroundingChunkMapsPlaceAnswerSources build(); + } + + /** Deserializes a JSON string to a GroundingChunkMapsPlaceAnswerSources object. */ + public static GroundingChunkMapsPlaceAnswerSources fromJson(String jsonString) { + return JsonSerializable.fromJsonString(jsonString, GroundingChunkMapsPlaceAnswerSources.class); + } +} diff --git a/src/main/java/com/google/genai/types/GroundingChunkMapsPlaceAnswerSourcesAuthorAttribution.java b/src/main/java/com/google/genai/types/GroundingChunkMapsPlaceAnswerSourcesAuthorAttribution.java new file mode 100644 index 00000000000..de42b25f97e --- /dev/null +++ b/src/main/java/com/google/genai/types/GroundingChunkMapsPlaceAnswerSourcesAuthorAttribution.java @@ -0,0 +1,99 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Auto-generated code. Do not edit. + +package com.google.genai.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.google.auto.value.AutoValue; +import com.google.genai.JsonSerializable; +import java.util.Optional; + +/** Author attribution for a photo or review. */ +@AutoValue +@JsonDeserialize(builder = GroundingChunkMapsPlaceAnswerSourcesAuthorAttribution.Builder.class) +public abstract class GroundingChunkMapsPlaceAnswerSourcesAuthorAttribution + extends JsonSerializable { + /** Name of the author of the Photo or Review. */ + @JsonProperty("displayName") + public abstract Optional displayName(); + + /** Profile photo URI of the author of the Photo or Review. */ + @JsonProperty("photoUri") + public abstract Optional photoUri(); + + /** URI of the author of the Photo or Review. */ + @JsonProperty("uri") + public abstract Optional uri(); + + /** Instantiates a builder for GroundingChunkMapsPlaceAnswerSourcesAuthorAttribution. */ + public static Builder builder() { + return new AutoValue_GroundingChunkMapsPlaceAnswerSourcesAuthorAttribution.Builder(); + } + + /** Creates a builder with the same values as this instance. */ + public abstract Builder toBuilder(); + + /** Builder for GroundingChunkMapsPlaceAnswerSourcesAuthorAttribution. */ + @AutoValue.Builder + public abstract static class Builder { + /** + * For internal usage. Please use + * `GroundingChunkMapsPlaceAnswerSourcesAuthorAttribution.builder()` for instantiation. + */ + @JsonCreator + private static Builder create() { + return new AutoValue_GroundingChunkMapsPlaceAnswerSourcesAuthorAttribution.Builder(); + } + + /** + * Setter for displayName. + * + *

    displayName: Name of the author of the Photo or Review. + */ + @JsonProperty("displayName") + public abstract Builder displayName(String displayName); + + /** + * Setter for photoUri. + * + *

    photoUri: Profile photo URI of the author of the Photo or Review. + */ + @JsonProperty("photoUri") + public abstract Builder photoUri(String photoUri); + + /** + * Setter for uri. + * + *

    uri: URI of the author of the Photo or Review. + */ + @JsonProperty("uri") + public abstract Builder uri(String uri); + + public abstract GroundingChunkMapsPlaceAnswerSourcesAuthorAttribution build(); + } + + /** + * Deserializes a JSON string to a GroundingChunkMapsPlaceAnswerSourcesAuthorAttribution object. + */ + public static GroundingChunkMapsPlaceAnswerSourcesAuthorAttribution fromJson(String jsonString) { + return JsonSerializable.fromJsonString( + jsonString, GroundingChunkMapsPlaceAnswerSourcesAuthorAttribution.class); + } +} diff --git a/src/main/java/com/google/genai/types/GroundingChunkMapsPlaceAnswerSourcesReviewSnippet.java b/src/main/java/com/google/genai/types/GroundingChunkMapsPlaceAnswerSourcesReviewSnippet.java new file mode 100644 index 00000000000..cff6477b8f5 --- /dev/null +++ b/src/main/java/com/google/genai/types/GroundingChunkMapsPlaceAnswerSourcesReviewSnippet.java @@ -0,0 +1,140 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Auto-generated code. Do not edit. + +package com.google.genai.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.google.auto.value.AutoValue; +import com.google.genai.JsonSerializable; +import java.util.Optional; + +/** Encapsulates a review snippet. */ +@AutoValue +@JsonDeserialize(builder = GroundingChunkMapsPlaceAnswerSourcesReviewSnippet.Builder.class) +public abstract class GroundingChunkMapsPlaceAnswerSourcesReviewSnippet extends JsonSerializable { + /** This review's author. */ + @JsonProperty("authorAttribution") + public abstract Optional + authorAttribution(); + + /** A link where users can flag a problem with the review. */ + @JsonProperty("flagContentUri") + public abstract Optional flagContentUri(); + + /** A link to show the review on Google Maps. */ + @JsonProperty("googleMapsUri") + public abstract Optional googleMapsUri(); + + /** + * A string of formatted recent time, expressing the review time relative to the current time in a + * form appropriate for the language and country. + */ + @JsonProperty("relativePublishTimeDescription") + public abstract Optional relativePublishTimeDescription(); + + /** + * A reference representing this place review which may be used to look up this place review + * again. + */ + @JsonProperty("review") + public abstract Optional review(); + + /** Instantiates a builder for GroundingChunkMapsPlaceAnswerSourcesReviewSnippet. */ + public static Builder builder() { + return new AutoValue_GroundingChunkMapsPlaceAnswerSourcesReviewSnippet.Builder(); + } + + /** Creates a builder with the same values as this instance. */ + public abstract Builder toBuilder(); + + /** Builder for GroundingChunkMapsPlaceAnswerSourcesReviewSnippet. */ + @AutoValue.Builder + public abstract static class Builder { + /** + * For internal usage. Please use `GroundingChunkMapsPlaceAnswerSourcesReviewSnippet.builder()` + * for instantiation. + */ + @JsonCreator + private static Builder create() { + return new AutoValue_GroundingChunkMapsPlaceAnswerSourcesReviewSnippet.Builder(); + } + + /** + * Setter for authorAttribution. + * + *

    authorAttribution: This review's author. + */ + @JsonProperty("authorAttribution") + public abstract Builder authorAttribution( + GroundingChunkMapsPlaceAnswerSourcesAuthorAttribution authorAttribution); + + /** + * Setter for authorAttribution builder. + * + *

    authorAttribution: This review's author. + */ + public Builder authorAttribution( + GroundingChunkMapsPlaceAnswerSourcesAuthorAttribution.Builder authorAttributionBuilder) { + return authorAttribution(authorAttributionBuilder.build()); + } + + /** + * Setter for flagContentUri. + * + *

    flagContentUri: A link where users can flag a problem with the review. + */ + @JsonProperty("flagContentUri") + public abstract Builder flagContentUri(String flagContentUri); + + /** + * Setter for googleMapsUri. + * + *

    googleMapsUri: A link to show the review on Google Maps. + */ + @JsonProperty("googleMapsUri") + public abstract Builder googleMapsUri(String googleMapsUri); + + /** + * Setter for relativePublishTimeDescription. + * + *

    relativePublishTimeDescription: A string of formatted recent time, expressing the review + * time relative to the current time in a form appropriate for the language and country. + */ + @JsonProperty("relativePublishTimeDescription") + public abstract Builder relativePublishTimeDescription(String relativePublishTimeDescription); + + /** + * Setter for review. + * + *

    review: A reference representing this place review which may be used to look up this place + * review again. + */ + @JsonProperty("review") + public abstract Builder review(String review); + + public abstract GroundingChunkMapsPlaceAnswerSourcesReviewSnippet build(); + } + + /** Deserializes a JSON string to a GroundingChunkMapsPlaceAnswerSourcesReviewSnippet object. */ + public static GroundingChunkMapsPlaceAnswerSourcesReviewSnippet fromJson(String jsonString) { + return JsonSerializable.fromJsonString( + jsonString, GroundingChunkMapsPlaceAnswerSourcesReviewSnippet.class); + } +} diff --git a/src/main/java/com/google/genai/types/GroundingMetadata.java b/src/main/java/com/google/genai/types/GroundingMetadata.java index 129c8b63523..99c6a1a41c7 100644 --- a/src/main/java/com/google/genai/types/GroundingMetadata.java +++ b/src/main/java/com/google/genai/types/GroundingMetadata.java @@ -33,6 +33,14 @@ @AutoValue @JsonDeserialize(builder = GroundingMetadata.Builder.class) public abstract class GroundingMetadata extends JsonSerializable { + /** + * Optional. Output only. Resource name of the Google Maps widget context token to be used with + * the PlacesContextElement widget to render contextual data. This is populated only for Google + * Maps grounding. + */ + @JsonProperty("googleMapsWidgetContextToken") + public abstract Optional googleMapsWidgetContextToken(); + /** List of supporting references retrieved from specified grounding source. */ @JsonProperty("groundingChunks") public abstract Optional> groundingChunks(); @@ -74,6 +82,16 @@ private static Builder create() { return new AutoValue_GroundingMetadata.Builder(); } + /** + * Setter for googleMapsWidgetContextToken. + * + *

    googleMapsWidgetContextToken: Optional. Output only. Resource name of the Google Maps + * widget context token to be used with the PlacesContextElement widget to render contextual + * data. This is populated only for Google Maps grounding. + */ + @JsonProperty("googleMapsWidgetContextToken") + public abstract Builder googleMapsWidgetContextToken(String googleMapsWidgetContextToken); + /** * Setter for groundingChunks. * diff --git a/src/main/java/com/google/genai/types/PreTunedModel.java b/src/main/java/com/google/genai/types/PreTunedModel.java new file mode 100644 index 00000000000..1b456697c5f --- /dev/null +++ b/src/main/java/com/google/genai/types/PreTunedModel.java @@ -0,0 +1,102 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Auto-generated code. Do not edit. + +package com.google.genai.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.google.auto.value.AutoValue; +import com.google.genai.JsonSerializable; +import java.util.Optional; + +/** A pre-tuned model for continuous tuning. */ +@AutoValue +@JsonDeserialize(builder = PreTunedModel.Builder.class) +public abstract class PreTunedModel extends JsonSerializable { + /** Output only. The name of the base model this PreTunedModel was tuned from. */ + @JsonProperty("baseModel") + public abstract Optional baseModel(); + + /** Optional. The source checkpoint id. If not specified, the default checkpoint will be used. */ + @JsonProperty("checkpointId") + public abstract Optional checkpointId(); + + /** + * The resource name of the Model. E.g., a model resource name with a specified version id or + * alias: `projects/{project}/locations/{location}/models/{model}@{version_id}` + * `projects/{project}/locations/{location}/models/{model}@{alias}` Or, omit the version id to use + * the default version: `projects/{project}/locations/{location}/models/{model}` + */ + @JsonProperty("tunedModelName") + public abstract Optional tunedModelName(); + + /** Instantiates a builder for PreTunedModel. */ + public static Builder builder() { + return new AutoValue_PreTunedModel.Builder(); + } + + /** Creates a builder with the same values as this instance. */ + public abstract Builder toBuilder(); + + /** Builder for PreTunedModel. */ + @AutoValue.Builder + public abstract static class Builder { + /** For internal usage. Please use `PreTunedModel.builder()` for instantiation. */ + @JsonCreator + private static Builder create() { + return new AutoValue_PreTunedModel.Builder(); + } + + /** + * Setter for baseModel. + * + *

    baseModel: Output only. The name of the base model this PreTunedModel was tuned from. + */ + @JsonProperty("baseModel") + public abstract Builder baseModel(String baseModel); + + /** + * Setter for checkpointId. + * + *

    checkpointId: Optional. The source checkpoint id. If not specified, the default checkpoint + * will be used. + */ + @JsonProperty("checkpointId") + public abstract Builder checkpointId(String checkpointId); + + /** + * Setter for tunedModelName. + * + *

    tunedModelName: The resource name of the Model. E.g., a model resource name with a + * specified version id or alias: + * `projects/{project}/locations/{location}/models/{model}@{version_id}` + * `projects/{project}/locations/{location}/models/{model}@{alias}` Or, omit the version id to + * use the default version: `projects/{project}/locations/{location}/models/{model}` + */ + @JsonProperty("tunedModelName") + public abstract Builder tunedModelName(String tunedModelName); + + public abstract PreTunedModel build(); + } + + /** Deserializes a JSON string to a PreTunedModel object. */ + public static PreTunedModel fromJson(String jsonString) { + return JsonSerializable.fromJsonString(jsonString, PreTunedModel.class); + } +} diff --git a/src/main/java/com/google/genai/types/PreferenceOptimizationDataStats.java b/src/main/java/com/google/genai/types/PreferenceOptimizationDataStats.java new file mode 100644 index 00000000000..40472e35fe6 --- /dev/null +++ b/src/main/java/com/google/genai/types/PreferenceOptimizationDataStats.java @@ -0,0 +1,227 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Auto-generated code. Do not edit. + +package com.google.genai.types; + +import static com.google.common.collect.ImmutableList.toImmutableList; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.google.auto.value.AutoValue; +import com.google.genai.JsonSerializable; +import java.util.Arrays; +import java.util.List; +import java.util.Optional; + +/** Statistics computed for datasets used for preference optimization. */ +@AutoValue +@JsonDeserialize(builder = PreferenceOptimizationDataStats.Builder.class) +public abstract class PreferenceOptimizationDataStats extends JsonSerializable { + /** Output only. Dataset distributions for scores variance per example. */ + @JsonProperty("scoreVariancePerExampleDistribution") + public abstract Optional scoreVariancePerExampleDistribution(); + + /** Output only. Dataset distributions for scores. */ + @JsonProperty("scoresDistribution") + public abstract Optional scoresDistribution(); + + /** Output only. Number of billable tokens in the tuning dataset. */ + @JsonProperty("totalBillableTokenCount") + public abstract Optional totalBillableTokenCount(); + + /** Output only. Number of examples in the tuning dataset. */ + @JsonProperty("tuningDatasetExampleCount") + public abstract Optional tuningDatasetExampleCount(); + + /** Output only. Number of tuning steps for this Tuning Job. */ + @JsonProperty("tuningStepCount") + public abstract Optional tuningStepCount(); + + /** Output only. Sample user examples in the training dataset. */ + @JsonProperty("userDatasetExamples") + public abstract Optional> userDatasetExamples(); + + /** Output only. Dataset distributions for the user input tokens. */ + @JsonProperty("userInputTokenDistribution") + public abstract Optional userInputTokenDistribution(); + + /** Output only. Dataset distributions for the user output tokens. */ + @JsonProperty("userOutputTokenDistribution") + public abstract Optional userOutputTokenDistribution(); + + /** Instantiates a builder for PreferenceOptimizationDataStats. */ + public static Builder builder() { + return new AutoValue_PreferenceOptimizationDataStats.Builder(); + } + + /** Creates a builder with the same values as this instance. */ + public abstract Builder toBuilder(); + + /** Builder for PreferenceOptimizationDataStats. */ + @AutoValue.Builder + public abstract static class Builder { + /** + * For internal usage. Please use `PreferenceOptimizationDataStats.builder()` for instantiation. + */ + @JsonCreator + private static Builder create() { + return new AutoValue_PreferenceOptimizationDataStats.Builder(); + } + + /** + * Setter for scoreVariancePerExampleDistribution. + * + *

    scoreVariancePerExampleDistribution: Output only. Dataset distributions for scores + * variance per example. + */ + @JsonProperty("scoreVariancePerExampleDistribution") + public abstract Builder scoreVariancePerExampleDistribution( + DatasetDistribution scoreVariancePerExampleDistribution); + + /** + * Setter for scoreVariancePerExampleDistribution builder. + * + *

    scoreVariancePerExampleDistribution: Output only. Dataset distributions for scores + * variance per example. + */ + public Builder scoreVariancePerExampleDistribution( + DatasetDistribution.Builder scoreVariancePerExampleDistributionBuilder) { + return scoreVariancePerExampleDistribution( + scoreVariancePerExampleDistributionBuilder.build()); + } + + /** + * Setter for scoresDistribution. + * + *

    scoresDistribution: Output only. Dataset distributions for scores. + */ + @JsonProperty("scoresDistribution") + public abstract Builder scoresDistribution(DatasetDistribution scoresDistribution); + + /** + * Setter for scoresDistribution builder. + * + *

    scoresDistribution: Output only. Dataset distributions for scores. + */ + public Builder scoresDistribution(DatasetDistribution.Builder scoresDistributionBuilder) { + return scoresDistribution(scoresDistributionBuilder.build()); + } + + /** + * Setter for totalBillableTokenCount. + * + *

    totalBillableTokenCount: Output only. Number of billable tokens in the tuning dataset. + */ + @JsonProperty("totalBillableTokenCount") + public abstract Builder totalBillableTokenCount(Long totalBillableTokenCount); + + /** + * Setter for tuningDatasetExampleCount. + * + *

    tuningDatasetExampleCount: Output only. Number of examples in the tuning dataset. + */ + @JsonProperty("tuningDatasetExampleCount") + public abstract Builder tuningDatasetExampleCount(Long tuningDatasetExampleCount); + + /** + * Setter for tuningStepCount. + * + *

    tuningStepCount: Output only. Number of tuning steps for this Tuning Job. + */ + @JsonProperty("tuningStepCount") + public abstract Builder tuningStepCount(Long tuningStepCount); + + /** + * Setter for userDatasetExamples. + * + *

    userDatasetExamples: Output only. Sample user examples in the training dataset. + */ + @JsonProperty("userDatasetExamples") + public abstract Builder userDatasetExamples(List userDatasetExamples); + + /** + * Setter for userDatasetExamples. + * + *

    userDatasetExamples: Output only. Sample user examples in the training dataset. + */ + public Builder userDatasetExamples(GeminiPreferenceExample... userDatasetExamples) { + return userDatasetExamples(Arrays.asList(userDatasetExamples)); + } + + /** + * Setter for userDatasetExamples builder. + * + *

    userDatasetExamples: Output only. Sample user examples in the training dataset. + */ + public Builder userDatasetExamples( + GeminiPreferenceExample.Builder... userDatasetExamplesBuilders) { + return userDatasetExamples( + Arrays.asList(userDatasetExamplesBuilders).stream() + .map(GeminiPreferenceExample.Builder::build) + .collect(toImmutableList())); + } + + /** + * Setter for userInputTokenDistribution. + * + *

    userInputTokenDistribution: Output only. Dataset distributions for the user input tokens. + */ + @JsonProperty("userInputTokenDistribution") + public abstract Builder userInputTokenDistribution( + DatasetDistribution userInputTokenDistribution); + + /** + * Setter for userInputTokenDistribution builder. + * + *

    userInputTokenDistribution: Output only. Dataset distributions for the user input tokens. + */ + public Builder userInputTokenDistribution( + DatasetDistribution.Builder userInputTokenDistributionBuilder) { + return userInputTokenDistribution(userInputTokenDistributionBuilder.build()); + } + + /** + * Setter for userOutputTokenDistribution. + * + *

    userOutputTokenDistribution: Output only. Dataset distributions for the user output + * tokens. + */ + @JsonProperty("userOutputTokenDistribution") + public abstract Builder userOutputTokenDistribution( + DatasetDistribution userOutputTokenDistribution); + + /** + * Setter for userOutputTokenDistribution builder. + * + *

    userOutputTokenDistribution: Output only. Dataset distributions for the user output + * tokens. + */ + public Builder userOutputTokenDistribution( + DatasetDistribution.Builder userOutputTokenDistributionBuilder) { + return userOutputTokenDistribution(userOutputTokenDistributionBuilder.build()); + } + + public abstract PreferenceOptimizationDataStats build(); + } + + /** Deserializes a JSON string to a PreferenceOptimizationDataStats object. */ + public static PreferenceOptimizationDataStats fromJson(String jsonString) { + return JsonSerializable.fromJsonString(jsonString, PreferenceOptimizationDataStats.class); + } +} diff --git a/src/main/java/com/google/genai/types/PreferenceOptimizationHyperParameters.java b/src/main/java/com/google/genai/types/PreferenceOptimizationHyperParameters.java new file mode 100644 index 00000000000..d1eddb922a8 --- /dev/null +++ b/src/main/java/com/google/genai/types/PreferenceOptimizationHyperParameters.java @@ -0,0 +1,134 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Auto-generated code. Do not edit. + +package com.google.genai.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.google.api.core.InternalApi; +import com.google.auto.value.AutoValue; +import com.google.errorprone.annotations.CanIgnoreReturnValue; +import com.google.genai.JsonSerializable; +import java.util.Optional; + +/** Hyperparameters for Preference Optimization. */ +@AutoValue +@InternalApi +@JsonDeserialize(builder = PreferenceOptimizationHyperParameters.Builder.class) +public abstract class PreferenceOptimizationHyperParameters extends JsonSerializable { + /** Optional. Adapter size for preference optimization. */ + @JsonProperty("adapterSize") + public abstract Optional adapterSize(); + + /** Optional. Weight for KL Divergence regularization. */ + @JsonProperty("beta") + public abstract Optional beta(); + + /** + * Optional. Number of complete passes the model makes over the entire training dataset during + * training. + */ + @JsonProperty("epochCount") + public abstract Optional epochCount(); + + /** Optional. Multiplier for adjusting the default learning rate. */ + @JsonProperty("learningRateMultiplier") + public abstract Optional learningRateMultiplier(); + + /** Instantiates a builder for PreferenceOptimizationHyperParameters. */ + public static Builder builder() { + return new AutoValue_PreferenceOptimizationHyperParameters.Builder(); + } + + /** Creates a builder with the same values as this instance. */ + public abstract Builder toBuilder(); + + /** Builder for PreferenceOptimizationHyperParameters. */ + @AutoValue.Builder + public abstract static class Builder { + /** + * For internal usage. Please use `PreferenceOptimizationHyperParameters.builder()` for + * instantiation. + */ + @JsonCreator + private static Builder create() { + return new AutoValue_PreferenceOptimizationHyperParameters.Builder(); + } + + /** + * Setter for adapterSize. + * + *

    adapterSize: Optional. Adapter size for preference optimization. + */ + @JsonProperty("adapterSize") + public abstract Builder adapterSize(AdapterSize adapterSize); + + /** + * Setter for adapterSize given a known enum. + * + *

    adapterSize: Optional. Adapter size for preference optimization. + */ + @CanIgnoreReturnValue + public Builder adapterSize(AdapterSize.Known knownType) { + return adapterSize(new AdapterSize(knownType)); + } + + /** + * Setter for adapterSize given a string. + * + *

    adapterSize: Optional. Adapter size for preference optimization. + */ + @CanIgnoreReturnValue + public Builder adapterSize(String adapterSize) { + return adapterSize(new AdapterSize(adapterSize)); + } + + /** + * Setter for beta. + * + *

    beta: Optional. Weight for KL Divergence regularization. + */ + @JsonProperty("beta") + public abstract Builder beta(Double beta); + + /** + * Setter for epochCount. + * + *

    epochCount: Optional. Number of complete passes the model makes over the entire training + * dataset during training. + */ + @JsonProperty("epochCount") + public abstract Builder epochCount(Long epochCount); + + /** + * Setter for learningRateMultiplier. + * + *

    learningRateMultiplier: Optional. Multiplier for adjusting the default learning rate. + */ + @JsonProperty("learningRateMultiplier") + public abstract Builder learningRateMultiplier(Double learningRateMultiplier); + + public abstract PreferenceOptimizationHyperParameters build(); + } + + /** Deserializes a JSON string to a PreferenceOptimizationHyperParameters object. */ + public static PreferenceOptimizationHyperParameters fromJson(String jsonString) { + return JsonSerializable.fromJsonString(jsonString, PreferenceOptimizationHyperParameters.class); + } +} diff --git a/src/main/java/com/google/genai/types/PreferenceOptimizationSpec.java b/src/main/java/com/google/genai/types/PreferenceOptimizationSpec.java new file mode 100644 index 00000000000..8a99e02d75b --- /dev/null +++ b/src/main/java/com/google/genai/types/PreferenceOptimizationSpec.java @@ -0,0 +1,110 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Auto-generated code. Do not edit. + +package com.google.genai.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.google.auto.value.AutoValue; +import com.google.genai.JsonSerializable; +import java.util.Optional; + +/** Tuning Spec for Preference Optimization. */ +@AutoValue +@JsonDeserialize(builder = PreferenceOptimizationSpec.Builder.class) +public abstract class PreferenceOptimizationSpec extends JsonSerializable { + /** Optional. Hyperparameters for Preference Optimization. */ + @JsonProperty("hyperParameters") + public abstract Optional hyperParameters(); + + /** + * Required. Cloud Storage path to file containing training dataset for preference optimization + * tuning. The dataset must be formatted as a JSONL file. + */ + @JsonProperty("trainingDatasetUri") + public abstract Optional trainingDatasetUri(); + + /** + * Optional. Cloud Storage path to file containing validation dataset for preference optimization + * tuning. The dataset must be formatted as a JSONL file. + */ + @JsonProperty("validationDatasetUri") + public abstract Optional validationDatasetUri(); + + /** Instantiates a builder for PreferenceOptimizationSpec. */ + public static Builder builder() { + return new AutoValue_PreferenceOptimizationSpec.Builder(); + } + + /** Creates a builder with the same values as this instance. */ + public abstract Builder toBuilder(); + + /** Builder for PreferenceOptimizationSpec. */ + @AutoValue.Builder + public abstract static class Builder { + /** For internal usage. Please use `PreferenceOptimizationSpec.builder()` for instantiation. */ + @JsonCreator + private static Builder create() { + return new AutoValue_PreferenceOptimizationSpec.Builder(); + } + + /** + * Setter for hyperParameters. + * + *

    hyperParameters: Optional. Hyperparameters for Preference Optimization. + */ + @JsonProperty("hyperParameters") + public abstract Builder hyperParameters(PreferenceOptimizationHyperParameters hyperParameters); + + /** + * Setter for hyperParameters builder. + * + *

    hyperParameters: Optional. Hyperparameters for Preference Optimization. + */ + public Builder hyperParameters( + PreferenceOptimizationHyperParameters.Builder hyperParametersBuilder) { + return hyperParameters(hyperParametersBuilder.build()); + } + + /** + * Setter for trainingDatasetUri. + * + *

    trainingDatasetUri: Required. Cloud Storage path to file containing training dataset for + * preference optimization tuning. The dataset must be formatted as a JSONL file. + */ + @JsonProperty("trainingDatasetUri") + public abstract Builder trainingDatasetUri(String trainingDatasetUri); + + /** + * Setter for validationDatasetUri. + * + *

    validationDatasetUri: Optional. Cloud Storage path to file containing validation dataset + * for preference optimization tuning. The dataset must be formatted as a JSONL file. + */ + @JsonProperty("validationDatasetUri") + public abstract Builder validationDatasetUri(String validationDatasetUri); + + public abstract PreferenceOptimizationSpec build(); + } + + /** Deserializes a JSON string to a PreferenceOptimizationSpec object. */ + public static PreferenceOptimizationSpec fromJson(String jsonString) { + return JsonSerializable.fromJsonString(jsonString, PreferenceOptimizationSpec.class); + } +} diff --git a/src/main/java/com/google/genai/types/SupervisedHyperParameters.java b/src/main/java/com/google/genai/types/SupervisedHyperParameters.java index 18ee356bc4a..7dbbba73b43 100644 --- a/src/main/java/com/google/genai/types/SupervisedHyperParameters.java +++ b/src/main/java/com/google/genai/types/SupervisedHyperParameters.java @@ -36,6 +36,10 @@ public abstract class SupervisedHyperParameters extends JsonSerializable { @JsonProperty("adapterSize") public abstract Optional adapterSize(); + /** Optional. Batch size for tuning. This feature is only available for open source models. */ + @JsonProperty("batchSize") + public abstract Optional batchSize(); + /** * Optional. Number of complete passes the model makes over the entire training dataset during * training. @@ -43,9 +47,16 @@ public abstract class SupervisedHyperParameters extends JsonSerializable { @JsonProperty("epochCount") public abstract Optional epochCount(); + /** + * Optional. Learning rate for tuning. Mutually exclusive with `learning_rate_multiplier`. This + * feature is only available for open source models. + */ + @JsonProperty("learningRate") + public abstract Optional learningRate(); + /** * Optional. Multiplier for adjusting the default learning rate. Mutually exclusive with - * `learning_rate`. + * `learning_rate`. This feature is only available for 1P models. */ @JsonProperty("learningRateMultiplier") public abstract Optional learningRateMultiplier(); @@ -95,6 +106,15 @@ public Builder adapterSize(String adapterSize) { return adapterSize(new AdapterSize(adapterSize)); } + /** + * Setter for batchSize. + * + *

    batchSize: Optional. Batch size for tuning. This feature is only available for open source + * models. + */ + @JsonProperty("batchSize") + public abstract Builder batchSize(Long batchSize); + /** * Setter for epochCount. * @@ -104,11 +124,20 @@ public Builder adapterSize(String adapterSize) { @JsonProperty("epochCount") public abstract Builder epochCount(Long epochCount); + /** + * Setter for learningRate. + * + *

    learningRate: Optional. Learning rate for tuning. Mutually exclusive with + * `learning_rate_multiplier`. This feature is only available for open source models. + */ + @JsonProperty("learningRate") + public abstract Builder learningRate(Double learningRate); + /** * Setter for learningRateMultiplier. * *

    learningRateMultiplier: Optional. Multiplier for adjusting the default learning rate. - * Mutually exclusive with `learning_rate`. + * Mutually exclusive with `learning_rate`. This feature is only available for 1P models. */ @JsonProperty("learningRateMultiplier") public abstract Builder learningRateMultiplier(Double learningRateMultiplier); diff --git a/src/main/java/com/google/genai/types/SupervisedTuningSpec.java b/src/main/java/com/google/genai/types/SupervisedTuningSpec.java index 5ddf6550fc8..59b66a56293 100644 --- a/src/main/java/com/google/genai/types/SupervisedTuningSpec.java +++ b/src/main/java/com/google/genai/types/SupervisedTuningSpec.java @@ -22,6 +22,7 @@ import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.google.auto.value.AutoValue; +import com.google.errorprone.annotations.CanIgnoreReturnValue; import com.google.genai.JsonSerializable; import java.util.Optional; @@ -47,6 +48,10 @@ public abstract class SupervisedTuningSpec extends JsonSerializable { @JsonProperty("trainingDatasetUri") public abstract Optional trainingDatasetUri(); + /** Tuning mode. */ + @JsonProperty("tuningMode") + public abstract Optional tuningMode(); + /** * Optional. Validation dataset used for tuning. The dataset can be specified as either a Cloud * Storage path to a JSONL file or as the resource name of a Vertex Multimodal Dataset. @@ -108,6 +113,34 @@ public Builder hyperParameters(SupervisedHyperParameters.Builder hyperParameters @JsonProperty("trainingDatasetUri") public abstract Builder trainingDatasetUri(String trainingDatasetUri); + /** + * Setter for tuningMode. + * + *

    tuningMode: Tuning mode. + */ + @JsonProperty("tuningMode") + public abstract Builder tuningMode(TuningMode tuningMode); + + /** + * Setter for tuningMode given a known enum. + * + *

    tuningMode: Tuning mode. + */ + @CanIgnoreReturnValue + public Builder tuningMode(TuningMode.Known knownType) { + return tuningMode(new TuningMode(knownType)); + } + + /** + * Setter for tuningMode given a string. + * + *

    tuningMode: Tuning mode. + */ + @CanIgnoreReturnValue + public Builder tuningMode(String tuningMode) { + return tuningMode(new TuningMode(tuningMode)); + } + /** * Setter for validationDatasetUri. * diff --git a/src/main/java/com/google/genai/types/Tool.java b/src/main/java/com/google/genai/types/Tool.java index 7c81f57e17d..66ef3f7f063 100644 --- a/src/main/java/com/google/genai/types/Tool.java +++ b/src/main/java/com/google/genai/types/Tool.java @@ -86,13 +86,6 @@ public abstract class Tool extends JsonSerializable { @JsonProperty("codeExecution") public abstract Optional codeExecution(); - /** - * Optional. Tool to support the model interacting directly with the computer. If enabled, it - * automatically populates computer-use specific Function Declarations. - */ - @JsonProperty("computerUse") - public abstract Optional computerUse(); - /** Instantiates a builder for Tool. */ public static Builder builder() { return new AutoValue_Tool.Builder(); @@ -293,25 +286,6 @@ public Builder codeExecution(ToolCodeExecution.Builder codeExecutionBuilder) { return codeExecution(codeExecutionBuilder.build()); } - /** - * Setter for computerUse. - * - *

    computerUse: Optional. Tool to support the model interacting directly with the computer. - * If enabled, it automatically populates computer-use specific Function Declarations. - */ - @JsonProperty("computerUse") - public abstract Builder computerUse(ToolComputerUse computerUse); - - /** - * Setter for computerUse builder. - * - *

    computerUse: Optional. Tool to support the model interacting directly with the computer. - * If enabled, it automatically populates computer-use specific Function Declarations. - */ - public Builder computerUse(ToolComputerUse.Builder computerUseBuilder) { - return computerUse(computerUseBuilder.build()); - } - public abstract Tool build(); } diff --git a/src/main/java/com/google/genai/types/TunedModel.java b/src/main/java/com/google/genai/types/TunedModel.java index 605fe5e6760..430132c18bb 100644 --- a/src/main/java/com/google/genai/types/TunedModel.java +++ b/src/main/java/com/google/genai/types/TunedModel.java @@ -35,7 +35,10 @@ public abstract class TunedModel extends JsonSerializable { /** * Output only. The resource name of the TunedModel. Format: - * `projects/{project}/locations/{location}/models/{model}`. + * `projects/{project}/locations/{location}/models/{model}@{version_id}` When tuning from a base + * model, the version_id will be 1. For continuous tuning, the version id will be incremented by 1 + * from the last version id in the parent model. E.g., + * `projects/{project}/locations/{location}/models/{model}@{last_version_id + 1}` */ @JsonProperty("model") public abstract Optional model(); @@ -75,7 +78,10 @@ private static Builder create() { * Setter for model. * *

    model: Output only. The resource name of the TunedModel. Format: - * `projects/{project}/locations/{location}/models/{model}`. + * `projects/{project}/locations/{location}/models/{model}@{version_id}` When tuning from a base + * model, the version_id will be 1. For continuous tuning, the version id will be incremented by + * 1 from the last version id in the parent model. E.g., + * `projects/{project}/locations/{location}/models/{model}@{last_version_id + 1}` */ @JsonProperty("model") public abstract Builder model(String model); diff --git a/src/main/java/com/google/genai/types/TuningDataStats.java b/src/main/java/com/google/genai/types/TuningDataStats.java index 32e3111bd88..baaec4d7a67 100644 --- a/src/main/java/com/google/genai/types/TuningDataStats.java +++ b/src/main/java/com/google/genai/types/TuningDataStats.java @@ -33,6 +33,10 @@ public abstract class TuningDataStats extends JsonSerializable { @JsonProperty("distillationDataStats") public abstract Optional distillationDataStats(); + /** Output only. Statistics for preference optimization. */ + @JsonProperty("preferenceOptimizationDataStats") + public abstract Optional preferenceOptimizationDataStats(); + /** The SFT Tuning data stats. */ @JsonProperty("supervisedTuningDataStats") public abstract Optional supervisedTuningDataStats(); @@ -72,6 +76,25 @@ public Builder distillationDataStats( return distillationDataStats(distillationDataStatsBuilder.build()); } + /** + * Setter for preferenceOptimizationDataStats. + * + *

    preferenceOptimizationDataStats: Output only. Statistics for preference optimization. + */ + @JsonProperty("preferenceOptimizationDataStats") + public abstract Builder preferenceOptimizationDataStats( + PreferenceOptimizationDataStats preferenceOptimizationDataStats); + + /** + * Setter for preferenceOptimizationDataStats builder. + * + *

    preferenceOptimizationDataStats: Output only. Statistics for preference optimization. + */ + public Builder preferenceOptimizationDataStats( + PreferenceOptimizationDataStats.Builder preferenceOptimizationDataStatsBuilder) { + return preferenceOptimizationDataStats(preferenceOptimizationDataStatsBuilder.build()); + } + /** * Setter for supervisedTuningDataStats. * diff --git a/src/main/java/com/google/genai/types/TuningJob.java b/src/main/java/com/google/genai/types/TuningJob.java index 5a3668fb8bd..730dd1089b1 100644 --- a/src/main/java/com/google/genai/types/TuningJob.java +++ b/src/main/java/com/google/genai/types/TuningJob.java @@ -104,6 +104,16 @@ public abstract class TuningJob extends JsonSerializable { @JsonProperty("partnerModelTuningSpec") public abstract Optional partnerModelTuningSpec(); + /** + * Optional. The user-provided path to custom model weights. Set this field to tune a custom + * model. The path must be a Cloud Storage directory that contains the model weights in + * .safetensors format along with associated model metadata files. If this field is set, the + * base_model field must still be set to indicate which base model the custom model is derived + * from. This feature is only available for open source models. + */ + @JsonProperty("customBaseModel") + public abstract Optional customBaseModel(); + /** Tuning Spec for Distillation. */ @JsonProperty("distillationSpec") public abstract Optional distillationSpec(); @@ -122,6 +132,13 @@ public abstract class TuningJob extends JsonSerializable { @JsonProperty("labels") public abstract Optional> labels(); + /** + * Optional. Cloud Storage path to the directory where tuning job outputs are written to. This + * field is only available and required for open source models. + */ + @JsonProperty("outputUri") + public abstract Optional outputUri(); + /** * Output only. The resource name of the PipelineJob associated with the TuningJob. Format: * `projects/{project}/locations/{location}/pipelineJobs/{pipeline_job}`. @@ -129,6 +146,14 @@ public abstract class TuningJob extends JsonSerializable { @JsonProperty("pipelineJob") public abstract Optional pipelineJob(); + /** The pre-tuned model for continuous tuning. */ + @JsonProperty("preTunedModel") + public abstract Optional preTunedModel(); + + /** Tuning Spec for Preference Optimization. */ + @JsonProperty("preferenceOptimizationSpec") + public abstract Optional preferenceOptimizationSpec(); + /** Output only. Reserved for future use. */ @JsonProperty("satisfiesPzi") public abstract Optional satisfiesPzi(); @@ -154,6 +179,10 @@ public abstract class TuningJob extends JsonSerializable { @JsonProperty("tunedModelDisplayName") public abstract Optional tunedModelDisplayName(); + /** Tuning Spec for Veo Tuning. */ + @JsonProperty("veoTuningSpec") + public abstract Optional veoTuningSpec(); + /** Instantiates a builder for TuningJob. */ public static Builder builder() { return new AutoValue_TuningJob.Builder(); @@ -368,6 +397,18 @@ public Builder partnerModelTuningSpec( return partnerModelTuningSpec(partnerModelTuningSpecBuilder.build()); } + /** + * Setter for customBaseModel. + * + *

    customBaseModel: Optional. The user-provided path to custom model weights. Set this field + * to tune a custom model. The path must be a Cloud Storage directory that contains the model + * weights in .safetensors format along with associated model metadata files. If this field is + * set, the base_model field must still be set to indicate which base model the custom model is + * derived from. This feature is only available for open source models. + */ + @JsonProperty("customBaseModel") + public abstract Builder customBaseModel(String customBaseModel); + /** * Setter for distillationSpec. * @@ -405,6 +446,15 @@ public Builder distillationSpec(DistillationSpec.Builder distillationSpecBuilder @JsonProperty("labels") public abstract Builder labels(Map labels); + /** + * Setter for outputUri. + * + *

    outputUri: Optional. Cloud Storage path to the directory where tuning job outputs are + * written to. This field is only available and required for open source models. + */ + @JsonProperty("outputUri") + public abstract Builder outputUri(String outputUri); + /** * Setter for pipelineJob. * @@ -414,6 +464,42 @@ public Builder distillationSpec(DistillationSpec.Builder distillationSpecBuilder @JsonProperty("pipelineJob") public abstract Builder pipelineJob(String pipelineJob); + /** + * Setter for preTunedModel. + * + *

    preTunedModel: The pre-tuned model for continuous tuning. + */ + @JsonProperty("preTunedModel") + public abstract Builder preTunedModel(PreTunedModel preTunedModel); + + /** + * Setter for preTunedModel builder. + * + *

    preTunedModel: The pre-tuned model for continuous tuning. + */ + public Builder preTunedModel(PreTunedModel.Builder preTunedModelBuilder) { + return preTunedModel(preTunedModelBuilder.build()); + } + + /** + * Setter for preferenceOptimizationSpec. + * + *

    preferenceOptimizationSpec: Tuning Spec for Preference Optimization. + */ + @JsonProperty("preferenceOptimizationSpec") + public abstract Builder preferenceOptimizationSpec( + PreferenceOptimizationSpec preferenceOptimizationSpec); + + /** + * Setter for preferenceOptimizationSpec builder. + * + *

    preferenceOptimizationSpec: Tuning Spec for Preference Optimization. + */ + public Builder preferenceOptimizationSpec( + PreferenceOptimizationSpec.Builder preferenceOptimizationSpecBuilder) { + return preferenceOptimizationSpec(preferenceOptimizationSpecBuilder.build()); + } + /** * Setter for satisfiesPzi. * @@ -451,6 +537,23 @@ public Builder distillationSpec(DistillationSpec.Builder distillationSpecBuilder @JsonProperty("tunedModelDisplayName") public abstract Builder tunedModelDisplayName(String tunedModelDisplayName); + /** + * Setter for veoTuningSpec. + * + *

    veoTuningSpec: Tuning Spec for Veo Tuning. + */ + @JsonProperty("veoTuningSpec") + public abstract Builder veoTuningSpec(VeoTuningSpec veoTuningSpec); + + /** + * Setter for veoTuningSpec builder. + * + *

    veoTuningSpec: Tuning Spec for Veo Tuning. + */ + public Builder veoTuningSpec(VeoTuningSpec.Builder veoTuningSpecBuilder) { + return veoTuningSpec(veoTuningSpecBuilder.build()); + } + public abstract TuningJob build(); } diff --git a/src/main/java/com/google/genai/types/TuningMode.java b/src/main/java/com/google/genai/types/TuningMode.java new file mode 100644 index 00000000000..53fb16a8ba0 --- /dev/null +++ b/src/main/java/com/google/genai/types/TuningMode.java @@ -0,0 +1,107 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Auto-generated code. Do not edit. + +package com.google.genai.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; +import com.google.common.base.Ascii; +import java.util.Objects; + +/** Tuning mode. */ +public class TuningMode { + + /** Enum representing the known values for TuningMode. */ + public enum Known { + /** Tuning mode is unspecified. */ + TUNING_MODE_UNSPECIFIED, + + /** Full fine-tuning mode. */ + TUNING_MODE_FULL, + + /** PEFT adapter tuning mode. */ + TUNING_MODE_PEFT_ADAPTER + } + + private Known tuningModeEnum; + private final String value; + + @JsonCreator + public TuningMode(String value) { + this.value = value; + for (Known tuningModeEnum : Known.values()) { + if (Ascii.equalsIgnoreCase(tuningModeEnum.toString(), value)) { + this.tuningModeEnum = tuningModeEnum; + break; + } + } + if (this.tuningModeEnum == null) { + this.tuningModeEnum = Known.TUNING_MODE_UNSPECIFIED; + } + } + + public TuningMode(Known knownValue) { + this.tuningModeEnum = knownValue; + this.value = knownValue.toString(); + } + + @Override + @JsonValue + public String toString() { + return this.value; + } + + @SuppressWarnings("PatternMatchingInstanceof") + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null) { + return false; + } + + if (!(o instanceof TuningMode)) { + return false; + } + + TuningMode other = (TuningMode) o; + + if (this.tuningModeEnum != Known.TUNING_MODE_UNSPECIFIED + && other.tuningModeEnum != Known.TUNING_MODE_UNSPECIFIED) { + return this.tuningModeEnum == other.tuningModeEnum; + } else if (this.tuningModeEnum == Known.TUNING_MODE_UNSPECIFIED + && other.tuningModeEnum == Known.TUNING_MODE_UNSPECIFIED) { + return this.value.equals(other.value); + } + return false; + } + + @Override + public int hashCode() { + if (this.tuningModeEnum != Known.TUNING_MODE_UNSPECIFIED) { + return this.tuningModeEnum.hashCode(); + } else { + return Objects.hashCode(this.value); + } + } + + public Known knownEnum() { + return this.tuningModeEnum; + } +} diff --git a/src/main/java/com/google/genai/types/TuningTask.java b/src/main/java/com/google/genai/types/TuningTask.java new file mode 100644 index 00000000000..5373a3e24fa --- /dev/null +++ b/src/main/java/com/google/genai/types/TuningTask.java @@ -0,0 +1,107 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Auto-generated code. Do not edit. + +package com.google.genai.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; +import com.google.common.base.Ascii; +import java.util.Objects; + +/** Optional. The tuning task. Either I2V or T2V. */ +public class TuningTask { + + /** Enum representing the known values for TuningTask. */ + public enum Known { + /** Default value. This value is unused. */ + TUNING_TASK_UNSPECIFIED, + + /** Tuning task for image to video. */ + TUNING_TASK_I2V, + + /** Tuning task for text to video. */ + TUNING_TASK_T2V + } + + private Known tuningTaskEnum; + private final String value; + + @JsonCreator + public TuningTask(String value) { + this.value = value; + for (Known tuningTaskEnum : Known.values()) { + if (Ascii.equalsIgnoreCase(tuningTaskEnum.toString(), value)) { + this.tuningTaskEnum = tuningTaskEnum; + break; + } + } + if (this.tuningTaskEnum == null) { + this.tuningTaskEnum = Known.TUNING_TASK_UNSPECIFIED; + } + } + + public TuningTask(Known knownValue) { + this.tuningTaskEnum = knownValue; + this.value = knownValue.toString(); + } + + @Override + @JsonValue + public String toString() { + return this.value; + } + + @SuppressWarnings("PatternMatchingInstanceof") + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null) { + return false; + } + + if (!(o instanceof TuningTask)) { + return false; + } + + TuningTask other = (TuningTask) o; + + if (this.tuningTaskEnum != Known.TUNING_TASK_UNSPECIFIED + && other.tuningTaskEnum != Known.TUNING_TASK_UNSPECIFIED) { + return this.tuningTaskEnum == other.tuningTaskEnum; + } else if (this.tuningTaskEnum == Known.TUNING_TASK_UNSPECIFIED + && other.tuningTaskEnum == Known.TUNING_TASK_UNSPECIFIED) { + return this.value.equals(other.value); + } + return false; + } + + @Override + public int hashCode() { + if (this.tuningTaskEnum != Known.TUNING_TASK_UNSPECIFIED) { + return this.tuningTaskEnum.hashCode(); + } else { + return Objects.hashCode(this.value); + } + } + + public Known knownEnum() { + return this.tuningTaskEnum; + } +} diff --git a/src/main/java/com/google/genai/types/VeoHyperParameters.java b/src/main/java/com/google/genai/types/VeoHyperParameters.java new file mode 100644 index 00000000000..af65cbc819d --- /dev/null +++ b/src/main/java/com/google/genai/types/VeoHyperParameters.java @@ -0,0 +1,119 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Auto-generated code. Do not edit. + +package com.google.genai.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.google.api.core.InternalApi; +import com.google.auto.value.AutoValue; +import com.google.errorprone.annotations.CanIgnoreReturnValue; +import com.google.genai.JsonSerializable; +import java.util.Optional; + +/** Hyperparameters for Veo. */ +@AutoValue +@InternalApi +@JsonDeserialize(builder = VeoHyperParameters.Builder.class) +public abstract class VeoHyperParameters extends JsonSerializable { + /** + * Optional. Number of complete passes the model makes over the entire training dataset during + * training. + */ + @JsonProperty("epochCount") + public abstract Optional epochCount(); + + /** Optional. Multiplier for adjusting the default learning rate. */ + @JsonProperty("learningRateMultiplier") + public abstract Optional learningRateMultiplier(); + + /** Optional. The tuning task. Either I2V or T2V. */ + @JsonProperty("tuningTask") + public abstract Optional tuningTask(); + + /** Instantiates a builder for VeoHyperParameters. */ + public static Builder builder() { + return new AutoValue_VeoHyperParameters.Builder(); + } + + /** Creates a builder with the same values as this instance. */ + public abstract Builder toBuilder(); + + /** Builder for VeoHyperParameters. */ + @AutoValue.Builder + public abstract static class Builder { + /** For internal usage. Please use `VeoHyperParameters.builder()` for instantiation. */ + @JsonCreator + private static Builder create() { + return new AutoValue_VeoHyperParameters.Builder(); + } + + /** + * Setter for epochCount. + * + *

    epochCount: Optional. Number of complete passes the model makes over the entire training + * dataset during training. + */ + @JsonProperty("epochCount") + public abstract Builder epochCount(Long epochCount); + + /** + * Setter for learningRateMultiplier. + * + *

    learningRateMultiplier: Optional. Multiplier for adjusting the default learning rate. + */ + @JsonProperty("learningRateMultiplier") + public abstract Builder learningRateMultiplier(Double learningRateMultiplier); + + /** + * Setter for tuningTask. + * + *

    tuningTask: Optional. The tuning task. Either I2V or T2V. + */ + @JsonProperty("tuningTask") + public abstract Builder tuningTask(TuningTask tuningTask); + + /** + * Setter for tuningTask given a known enum. + * + *

    tuningTask: Optional. The tuning task. Either I2V or T2V. + */ + @CanIgnoreReturnValue + public Builder tuningTask(TuningTask.Known knownType) { + return tuningTask(new TuningTask(knownType)); + } + + /** + * Setter for tuningTask given a string. + * + *

    tuningTask: Optional. The tuning task. Either I2V or T2V. + */ + @CanIgnoreReturnValue + public Builder tuningTask(String tuningTask) { + return tuningTask(new TuningTask(tuningTask)); + } + + public abstract VeoHyperParameters build(); + } + + /** Deserializes a JSON string to a VeoHyperParameters object. */ + public static VeoHyperParameters fromJson(String jsonString) { + return JsonSerializable.fromJsonString(jsonString, VeoHyperParameters.class); + } +} diff --git a/src/main/java/com/google/genai/types/VeoTuningSpec.java b/src/main/java/com/google/genai/types/VeoTuningSpec.java new file mode 100644 index 00000000000..40b38f3bb79 --- /dev/null +++ b/src/main/java/com/google/genai/types/VeoTuningSpec.java @@ -0,0 +1,111 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Auto-generated code. Do not edit. + +package com.google.genai.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.google.auto.value.AutoValue; +import com.google.genai.JsonSerializable; +import java.util.Optional; + +/** Tuning Spec for Veo Model Tuning. */ +@AutoValue +@JsonDeserialize(builder = VeoTuningSpec.Builder.class) +public abstract class VeoTuningSpec extends JsonSerializable { + /** Optional. Hyperparameters for Veo. */ + @JsonProperty("hyperParameters") + public abstract Optional hyperParameters(); + + /** + * Required. Training dataset used for tuning. The dataset can be specified as either a Cloud + * Storage path to a JSONL file or as the resource name of a Vertex Multimodal Dataset. + */ + @JsonProperty("trainingDatasetUri") + public abstract Optional trainingDatasetUri(); + + /** + * Optional. Validation dataset used for tuning. The dataset can be specified as either a Cloud + * Storage path to a JSONL file or as the resource name of a Vertex Multimodal Dataset. + */ + @JsonProperty("validationDatasetUri") + public abstract Optional validationDatasetUri(); + + /** Instantiates a builder for VeoTuningSpec. */ + public static Builder builder() { + return new AutoValue_VeoTuningSpec.Builder(); + } + + /** Creates a builder with the same values as this instance. */ + public abstract Builder toBuilder(); + + /** Builder for VeoTuningSpec. */ + @AutoValue.Builder + public abstract static class Builder { + /** For internal usage. Please use `VeoTuningSpec.builder()` for instantiation. */ + @JsonCreator + private static Builder create() { + return new AutoValue_VeoTuningSpec.Builder(); + } + + /** + * Setter for hyperParameters. + * + *

    hyperParameters: Optional. Hyperparameters for Veo. + */ + @JsonProperty("hyperParameters") + public abstract Builder hyperParameters(VeoHyperParameters hyperParameters); + + /** + * Setter for hyperParameters builder. + * + *

    hyperParameters: Optional. Hyperparameters for Veo. + */ + public Builder hyperParameters(VeoHyperParameters.Builder hyperParametersBuilder) { + return hyperParameters(hyperParametersBuilder.build()); + } + + /** + * Setter for trainingDatasetUri. + * + *

    trainingDatasetUri: Required. Training dataset used for tuning. The dataset can be + * specified as either a Cloud Storage path to a JSONL file or as the resource name of a Vertex + * Multimodal Dataset. + */ + @JsonProperty("trainingDatasetUri") + public abstract Builder trainingDatasetUri(String trainingDatasetUri); + + /** + * Setter for validationDatasetUri. + * + *

    validationDatasetUri: Optional. Validation dataset used for tuning. The dataset can be + * specified as either a Cloud Storage path to a JSONL file or as the resource name of a Vertex + * Multimodal Dataset. + */ + @JsonProperty("validationDatasetUri") + public abstract Builder validationDatasetUri(String validationDatasetUri); + + public abstract VeoTuningSpec build(); + } + + /** Deserializes a JSON string to a VeoTuningSpec object. */ + public static VeoTuningSpec fromJson(String jsonString) { + return JsonSerializable.fromJsonString(jsonString, VeoTuningSpec.class); + } +} From 255e739290308cb05b95577412afb64ca93dcf44 Mon Sep 17 00:00:00 2001 From: Jaycee Li Date: Thu, 7 Aug 2025 14:27:54 -0700 Subject: [PATCH 135/602] chore: Add more comments to explain function calling and schema examples PiperOrigin-RevId: 792309574 --- README.md | 4 ++++ .../GenerateContentWithFunctionCall.java | 4 +++- .../GenerateContentWithFunctionCallJson.java | 21 ++++++++----------- 3 files changed, 16 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index a6ecd160f19..6a969a6aa8d 100644 --- a/README.md +++ b/README.md @@ -349,6 +349,8 @@ public class GenerateContentWithFunctionCall { public static void main(String[] args) throws NoSuchMethodException { Client client = new Client(); + // Load the method as a reflected Method object so that it can be + // automatically executed on the client side. Method method = GenerateContentWithFunctionCall.class.getMethod( "getCurrentWeather", String.class, String.class); @@ -450,6 +452,7 @@ public class GenerateContentWithSchema { public static void main(String[] args) { Client client = new Client(); + // Define the schema for the response, in Json format. ImmutableMap schema = ImmutableMap.of( "type", "object", "properties", ImmutableMap.of( @@ -462,6 +465,7 @@ public class GenerateContentWithSchema { "required", ImmutableList.of("recipe_name", "ingredients") ); + // Set the response schema in GenerateContentConfig GenerateContentConfig config = GenerateContentConfig.builder() .responseMimeType("application/json") diff --git a/examples/src/main/java/com/google/genai/examples/GenerateContentWithFunctionCall.java b/examples/src/main/java/com/google/genai/examples/GenerateContentWithFunctionCall.java index dc6d4b3e7d4..f44df320415 100644 --- a/examples/src/main/java/com/google/genai/examples/GenerateContentWithFunctionCall.java +++ b/examples/src/main/java/com/google/genai/examples/GenerateContentWithFunctionCall.java @@ -56,7 +56,7 @@ public static String getCurrentWeather(String location, String unit) { } /** A callable function to divide two integers. */ - public static Integer divideTwoIntegers(Integer numerator, Integer denominator) { + public static Integer divideTwoIntegers(int numerator, int denominator) { return numerator / denominator; } @@ -82,6 +82,8 @@ public static void main(String[] args) throws NoSuchMethodException { System.out.println("Using Gemini Developer API"); } + // Load the two methods as reflected Method objects so that they can be automatically executed + // on the client side. Method method1 = GenerateContentWithFunctionCall.class.getMethod( "getCurrentWeather", String.class, String.class); diff --git a/examples/src/main/java/com/google/genai/examples/GenerateContentWithFunctionCallJson.java b/examples/src/main/java/com/google/genai/examples/GenerateContentWithFunctionCallJson.java index a162b920fdf..9c0c9ed930f 100644 --- a/examples/src/main/java/com/google/genai/examples/GenerateContentWithFunctionCallJson.java +++ b/examples/src/main/java/com/google/genai/examples/GenerateContentWithFunctionCallJson.java @@ -45,11 +45,10 @@ import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.genai.Client; +import com.google.genai.types.FunctionDeclaration; import com.google.genai.types.GenerateContentConfig; import com.google.genai.types.GenerateContentResponse; import com.google.genai.types.Tool; -import com.google.genai.types.FunctionDeclaration; - /** An example of using the Unified Gen AI Java SDK to generate content with function calling. */ public final class GenerateContentWithFunctionCallJson { @@ -76,28 +75,26 @@ public static void main(String[] args) { System.out.println("Using Gemini Developer API"); } + // Define the schema for the function declaration, in Json format. ImmutableMap schema = ImmutableMap.of( "type", "object", "properties", ImmutableMap.of("location", ImmutableMap.of("type", "string")), "required", ImmutableList.of("location")); + // Define the tool with the function declaration. Tool toolWithFunctionDeclarations = Tool.builder() .functionDeclarations( - ImmutableList.of( - FunctionDeclaration.builder() - .name("get_weather") - .description("Returns the weather in a given location.") - .parametersJsonSchema(schema) - .build())) + FunctionDeclaration.builder() + .name("get_weather") + .description("Returns the weather in a given location.") + .parametersJsonSchema(schema)) .build(); - // Add the two methods as callable functions to the list of tools. + // Add the tool to the GenerateContentConfig. GenerateContentConfig config = - GenerateContentConfig.builder() - .tools(ImmutableList.of(toolWithFunctionDeclarations)) - .build(); + GenerateContentConfig.builder().tools(toolWithFunctionDeclarations).build(); GenerateContentResponse response = client.models.generateContent(modelId, "What is the weather in Vancouver?", config); From 94ab84d2dcf5b4a6e3380761f6ae5910e774d693 Mon Sep 17 00:00:00 2001 From: Amy Wu Date: Thu, 7 Aug 2025 14:57:27 -0700 Subject: [PATCH 136/602] chore: internal PiperOrigin-RevId: 792320851 --- src/main/java/com/google/genai/Tunings.java | 38 +++--- .../types/CreateTuningJobParameters.java | 4 +- .../CreateTuningJobParametersPrivate.java | 120 ++++++++++++++++++ .../com/google/genai/types/TuningJob.java | 42 +++--- 4 files changed, 160 insertions(+), 44 deletions(-) create mode 100644 src/main/java/com/google/genai/types/CreateTuningJobParametersPrivate.java diff --git a/src/main/java/com/google/genai/Tunings.java b/src/main/java/com/google/genai/Tunings.java index f86b91f4371..f02c1037ed1 100644 --- a/src/main/java/com/google/genai/Tunings.java +++ b/src/main/java/com/google/genai/Tunings.java @@ -24,7 +24,7 @@ import com.fasterxml.jackson.databind.node.ObjectNode; import com.google.genai.errors.GenAiIOException; import com.google.genai.types.CreateTuningJobConfig; -import com.google.genai.types.CreateTuningJobParameters; +import com.google.genai.types.CreateTuningJobParametersPrivate; import com.google.genai.types.GetTuningJobConfig; import com.google.genai.types.GetTuningJobParameters; import com.google.genai.types.HttpOptions; @@ -219,7 +219,7 @@ ObjectNode createTuningJobConfigToMldev(JsonNode fromObject, ObjectNode parentOb } @ExcludeFromGeneratedCoverageReport - ObjectNode createTuningJobParametersToMldev(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode createTuningJobParametersPrivateToMldev(JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"baseModel"}) != null) { Common.setValueByPath( @@ -427,7 +427,8 @@ ObjectNode createTuningJobConfigToVertex(JsonNode fromObject, ObjectNode parentO } @ExcludeFromGeneratedCoverageReport - ObjectNode createTuningJobParametersToVertex(JsonNode fromObject, ObjectNode parentObject) { + ObjectNode createTuningJobParametersPrivateToVertex( + JsonNode fromObject, ObjectNode parentObject) { ObjectNode toObject = JsonSerializable.objectMapper.createObjectNode(); if (Common.getValueByPath(fromObject, new String[] {"baseModel"}) != null) { Common.setValueByPath( @@ -591,13 +592,6 @@ ObjectNode tuningJobFromMldev(JsonNode fromObject, ObjectNode parentObject) { Common.getValueByPath(fromObject, new String[] {"pipelineJob"})); } - if (Common.getValueByPath(fromObject, new String[] {"preTunedModel"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"preTunedModel"}, - Common.getValueByPath(fromObject, new String[] {"preTunedModel"})); - } - if (Common.getValueByPath(fromObject, new String[] {"preferenceOptimizationSpec"}) != null) { Common.setValueByPath( toObject, @@ -847,6 +841,13 @@ ObjectNode tuningJobFromVertex(JsonNode fromObject, ObjectNode parentObject) { toObject)); } + if (Common.getValueByPath(fromObject, new String[] {"preTunedModel"}) != null) { + Common.setValueByPath( + toObject, + new String[] {"preTunedModel"}, + Common.getValueByPath(fromObject, new String[] {"preTunedModel"})); + } + if (Common.getValueByPath(fromObject, new String[] {"supervisedTuningSpec"}) != null) { Common.setValueByPath( toObject, @@ -917,13 +918,6 @@ ObjectNode tuningJobFromVertex(JsonNode fromObject, ObjectNode parentObject) { Common.getValueByPath(fromObject, new String[] {"pipelineJob"})); } - if (Common.getValueByPath(fromObject, new String[] {"preTunedModel"}) != null) { - Common.setValueByPath( - toObject, - new String[] {"preTunedModel"}, - Common.getValueByPath(fromObject, new String[] {"preTunedModel"})); - } - if (Common.getValueByPath(fromObject, new String[] {"preferenceOptimizationSpec"}) != null) { Common.setValueByPath( toObject, @@ -1119,7 +1113,8 @@ ListTuningJobsResponse privateList(ListTuningJobsConfig config) { TuningJob privateTune( String baseModel, TuningDataset trainingDataset, CreateTuningJobConfig config) { - CreateTuningJobParameters.Builder parameterBuilder = CreateTuningJobParameters.builder(); + CreateTuningJobParametersPrivate.Builder parameterBuilder = + CreateTuningJobParametersPrivate.builder(); if (!Common.isZero(baseModel)) { parameterBuilder.baseModel(baseModel); @@ -1135,7 +1130,7 @@ TuningJob privateTune( ObjectNode body; String path; if (this.apiClient.vertexAI()) { - body = createTuningJobParametersToVertex(parameterNode, null); + body = createTuningJobParametersPrivateToVertex(parameterNode, null); path = Common.formatMap("tuningJobs", body.get("_url")); } else { throw new UnsupportedOperationException( @@ -1182,7 +1177,8 @@ TuningJob privateTune( TuningOperation privateTuneMldev( String baseModel, TuningDataset trainingDataset, CreateTuningJobConfig config) { - CreateTuningJobParameters.Builder parameterBuilder = CreateTuningJobParameters.builder(); + CreateTuningJobParametersPrivate.Builder parameterBuilder = + CreateTuningJobParametersPrivate.builder(); if (!Common.isZero(baseModel)) { parameterBuilder.baseModel(baseModel); @@ -1201,7 +1197,7 @@ TuningOperation privateTuneMldev( throw new UnsupportedOperationException( "This method is only supported in the Gemini Developer client."); } else { - body = createTuningJobParametersToMldev(parameterNode, null); + body = createTuningJobParametersPrivateToMldev(parameterNode, null); if (body.get("_url") != null) { path = Common.formatMap("tunedModels", body.get("_url")); } else { diff --git a/src/main/java/com/google/genai/types/CreateTuningJobParameters.java b/src/main/java/com/google/genai/types/CreateTuningJobParameters.java index 30683c0ae15..cf438f7c2de 100644 --- a/src/main/java/com/google/genai/types/CreateTuningJobParameters.java +++ b/src/main/java/com/google/genai/types/CreateTuningJobParameters.java @@ -31,7 +31,7 @@ @InternalApi @JsonDeserialize(builder = CreateTuningJobParameters.Builder.class) public abstract class CreateTuningJobParameters extends JsonSerializable { - /** The base model that is being tuned, e.g., "gemini-1.0-pro-002". */ + /** The base model that is being tuned, e.g., "gemini-2.5-flash". */ @JsonProperty("baseModel") public abstract Optional baseModel(); @@ -66,7 +66,7 @@ private static Builder create() { /** * Setter for baseModel. * - *

    baseModel: The base model that is being tuned, e.g., "gemini-1.0-pro-002". + *

    baseModel: The base model that is being tuned, e.g., "gemini-2.5-flash". */ @JsonProperty("baseModel") public abstract Builder baseModel(String baseModel); diff --git a/src/main/java/com/google/genai/types/CreateTuningJobParametersPrivate.java b/src/main/java/com/google/genai/types/CreateTuningJobParametersPrivate.java new file mode 100644 index 00000000000..8cb8b8275e3 --- /dev/null +++ b/src/main/java/com/google/genai/types/CreateTuningJobParametersPrivate.java @@ -0,0 +1,120 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Auto-generated code. Do not edit. + +package com.google.genai.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.google.api.core.InternalApi; +import com.google.auto.value.AutoValue; +import com.google.genai.JsonSerializable; +import java.util.Optional; + +/** Supervised fine-tuning job creation parameters - optional fields. */ +@AutoValue +@InternalApi +@JsonDeserialize(builder = CreateTuningJobParametersPrivate.Builder.class) +public abstract class CreateTuningJobParametersPrivate extends JsonSerializable { + /** The base model that is being tuned, e.g., "gemini-2.5-flash". */ + @JsonProperty("baseModel") + public abstract Optional baseModel(); + + /** + * Cloud Storage path to file containing training dataset for tuning. The dataset must be + * formatted as a JSONL file. + */ + @JsonProperty("trainingDataset") + public abstract Optional trainingDataset(); + + /** Configuration for the tuning job. */ + @JsonProperty("config") + public abstract Optional config(); + + /** Instantiates a builder for CreateTuningJobParametersPrivate. */ + public static Builder builder() { + return new AutoValue_CreateTuningJobParametersPrivate.Builder(); + } + + /** Creates a builder with the same values as this instance. */ + public abstract Builder toBuilder(); + + /** Builder for CreateTuningJobParametersPrivate. */ + @AutoValue.Builder + public abstract static class Builder { + /** + * For internal usage. Please use `CreateTuningJobParametersPrivate.builder()` for + * instantiation. + */ + @JsonCreator + private static Builder create() { + return new AutoValue_CreateTuningJobParametersPrivate.Builder(); + } + + /** + * Setter for baseModel. + * + *

    baseModel: The base model that is being tuned, e.g., "gemini-2.5-flash". + */ + @JsonProperty("baseModel") + public abstract Builder baseModel(String baseModel); + + /** + * Setter for trainingDataset. + * + *

    trainingDataset: Cloud Storage path to file containing training dataset for tuning. The + * dataset must be formatted as a JSONL file. + */ + @JsonProperty("trainingDataset") + public abstract Builder trainingDataset(TuningDataset trainingDataset); + + /** + * Setter for trainingDataset builder. + * + *

    trainingDataset: Cloud Storage path to file containing training dataset for tuning. The + * dataset must be formatted as a JSONL file. + */ + public Builder trainingDataset(TuningDataset.Builder trainingDatasetBuilder) { + return trainingDataset(trainingDatasetBuilder.build()); + } + + /** + * Setter for config. + * + *

    config: Configuration for the tuning job. + */ + @JsonProperty("config") + public abstract Builder config(CreateTuningJobConfig config); + + /** + * Setter for config builder. + * + *

    config: Configuration for the tuning job. + */ + public Builder config(CreateTuningJobConfig.Builder configBuilder) { + return config(configBuilder.build()); + } + + public abstract CreateTuningJobParametersPrivate build(); + } + + /** Deserializes a JSON string to a CreateTuningJobParametersPrivate object. */ + public static CreateTuningJobParametersPrivate fromJson(String jsonString) { + return JsonSerializable.fromJsonString(jsonString, CreateTuningJobParametersPrivate.class); + } +} diff --git a/src/main/java/com/google/genai/types/TuningJob.java b/src/main/java/com/google/genai/types/TuningJob.java index 730dd1089b1..95165e75172 100644 --- a/src/main/java/com/google/genai/types/TuningJob.java +++ b/src/main/java/com/google/genai/types/TuningJob.java @@ -85,6 +85,10 @@ public abstract class TuningJob extends JsonSerializable { @JsonProperty("tunedModel") public abstract Optional tunedModel(); + /** The pre-tuned model for continuous tuning. */ + @JsonProperty("preTunedModel") + public abstract Optional preTunedModel(); + /** Tuning Spec for Supervised Fine Tuning. */ @JsonProperty("supervisedTuningSpec") public abstract Optional supervisedTuningSpec(); @@ -146,10 +150,6 @@ public abstract class TuningJob extends JsonSerializable { @JsonProperty("pipelineJob") public abstract Optional pipelineJob(); - /** The pre-tuned model for continuous tuning. */ - @JsonProperty("preTunedModel") - public abstract Optional preTunedModel(); - /** Tuning Spec for Preference Optimization. */ @JsonProperty("preferenceOptimizationSpec") public abstract Optional preferenceOptimizationSpec(); @@ -324,6 +324,23 @@ public Builder tunedModel(TunedModel.Builder tunedModelBuilder) { return tunedModel(tunedModelBuilder.build()); } + /** + * Setter for preTunedModel. + * + *

    preTunedModel: The pre-tuned model for continuous tuning. + */ + @JsonProperty("preTunedModel") + public abstract Builder preTunedModel(PreTunedModel preTunedModel); + + /** + * Setter for preTunedModel builder. + * + *

    preTunedModel: The pre-tuned model for continuous tuning. + */ + public Builder preTunedModel(PreTunedModel.Builder preTunedModelBuilder) { + return preTunedModel(preTunedModelBuilder.build()); + } + /** * Setter for supervisedTuningSpec. * @@ -464,23 +481,6 @@ public Builder distillationSpec(DistillationSpec.Builder distillationSpecBuilder @JsonProperty("pipelineJob") public abstract Builder pipelineJob(String pipelineJob); - /** - * Setter for preTunedModel. - * - *

    preTunedModel: The pre-tuned model for continuous tuning. - */ - @JsonProperty("preTunedModel") - public abstract Builder preTunedModel(PreTunedModel preTunedModel); - - /** - * Setter for preTunedModel builder. - * - *

    preTunedModel: The pre-tuned model for continuous tuning. - */ - public Builder preTunedModel(PreTunedModel.Builder preTunedModelBuilder) { - return preTunedModel(preTunedModelBuilder.build()); - } - /** * Setter for preferenceOptimizationSpec. * From 49e1e80f01dda62bb58b6ee426afd52bd0571904 Mon Sep 17 00:00:00 2001 From: Jaycee Li Date: Thu, 7 Aug 2025 15:31:04 -0700 Subject: [PATCH 137/602] chore: Exclude `fromJson` and `builder()` from code coverage report PiperOrigin-RevId: 792333167 --- pom.xml | 4 +-- .../com/google/genai/types/ActivityEnd.java | 2 ++ .../google/genai/types/ActivityHandling.java | 4 +++ .../com/google/genai/types/ActivityStart.java | 2 ++ .../com/google/genai/types/AdapterSize.java | 4 +++ .../java/com/google/genai/types/ApiAuth.java | 2 ++ .../genai/types/ApiAuthApiKeyConfig.java | 2 ++ .../com/google/genai/types/ApiKeyConfig.java | 2 ++ .../java/com/google/genai/types/ApiSpec.java | 4 +++ .../genai/types/AudioTranscriptionConfig.java | 2 ++ .../com/google/genai/types/AuthConfig.java | 2 ++ .../AuthConfigGoogleServiceAccountConfig.java | 2 ++ .../types/AuthConfigHttpBasicAuthConfig.java | 2 ++ .../genai/types/AuthConfigOauthConfig.java | 2 ++ .../genai/types/AuthConfigOidcConfig.java | 2 ++ .../java/com/google/genai/types/AuthType.java | 4 +++ .../types/AutomaticActivityDetection.java | 2 ++ .../types/AutomaticFunctionCallingConfig.java | 2 ++ .../java/com/google/genai/types/BatchJob.java | 2 ++ .../genai/types/BatchJobDestination.java | 2 ++ .../google/genai/types/BatchJobSource.java | 2 ++ .../java/com/google/genai/types/Behavior.java | 4 +++ .../java/com/google/genai/types/Blob.java | 2 ++ .../com/google/genai/types/BlockedReason.java | 4 +++ .../com/google/genai/types/CachedContent.java | 2 ++ .../types/CachedContentUsageMetadata.java | 2 ++ .../genai/types/CancelBatchJobConfig.java | 2 ++ .../genai/types/CancelBatchJobParameters.java | 2 ++ .../com/google/genai/types/Candidate.java | 2 ++ .../com/google/genai/types/Checkpoint.java | 2 ++ .../java/com/google/genai/types/Citation.java | 2 ++ .../google/genai/types/CitationMetadata.java | 2 ++ .../com/google/genai/types/ClientOptions.java | 2 ++ .../genai/types/CodeExecutionResult.java | 2 ++ .../genai/types/ComputeTokensConfig.java | 2 ++ .../genai/types/ComputeTokensParameters.java | 2 ++ .../genai/types/ComputeTokensResponse.java | 2 ++ .../java/com/google/genai/types/Content.java | 2 ++ .../google/genai/types/ContentEmbedding.java | 2 ++ .../types/ContentEmbeddingStatistics.java | 2 ++ .../types/ContextWindowCompressionConfig.java | 2 ++ .../genai/types/ControlReferenceConfig.java | 2 ++ .../genai/types/ControlReferenceImage.java | 2 ++ .../genai/types/ControlReferenceType.java | 4 +++ .../google/genai/types/CountTokensConfig.java | 2 ++ .../genai/types/CountTokensParameters.java | 2 ++ .../genai/types/CountTokensResponse.java | 2 ++ .../genai/types/CreateAuthTokenConfig.java | 2 ++ .../genai/types/CreateBatchJobConfig.java | 2 ++ .../genai/types/CreateBatchJobParameters.java | 2 ++ .../types/CreateCachedContentConfig.java | 2 ++ .../types/CreateCachedContentParameters.java | 2 ++ .../google/genai/types/CreateFileConfig.java | 2 ++ .../genai/types/CreateFileParameters.java | 2 ++ .../genai/types/CreateFileResponse.java | 2 ++ .../genai/types/CreateTuningJobConfig.java | 2 ++ .../types/CreateTuningJobParameters.java | 2 ++ .../CreateTuningJobParametersPrivate.java | 2 ++ .../genai/types/DatasetDistribution.java | 2 ++ ...DatasetDistributionDistributionBucket.java | 2 ++ .../com/google/genai/types/DatasetStats.java | 2 ++ .../genai/types/DeleteBatchJobConfig.java | 2 ++ .../genai/types/DeleteBatchJobParameters.java | 2 ++ .../types/DeleteCachedContentConfig.java | 2 ++ .../types/DeleteCachedContentParameters.java | 2 ++ .../types/DeleteCachedContentResponse.java | 2 ++ .../google/genai/types/DeleteFileConfig.java | 2 ++ .../genai/types/DeleteFileParameters.java | 2 ++ .../genai/types/DeleteFileResponse.java | 2 ++ .../google/genai/types/DeleteModelConfig.java | 2 ++ .../genai/types/DeleteModelParameters.java | 2 ++ .../genai/types/DeleteModelResponse.java | 2 ++ .../google/genai/types/DeleteResourceJob.java | 2 ++ .../genai/types/DistillationDataStats.java | 2 ++ .../types/DistillationHyperParameters.java | 2 ++ .../google/genai/types/DistillationSpec.java | 2 ++ .../genai/types/DownloadFileConfig.java | 2 ++ .../genai/types/DynamicRetrievalConfig.java | 2 ++ .../types/DynamicRetrievalConfigMode.java | 4 +++ .../google/genai/types/EditImageConfig.java | 2 ++ .../genai/types/EditImageParameters.java | 2 ++ .../google/genai/types/EditImageResponse.java | 2 ++ .../java/com/google/genai/types/EditMode.java | 4 +++ .../genai/types/EmbedContentConfig.java | 2 ++ .../genai/types/EmbedContentMetadata.java | 2 ++ .../genai/types/EmbedContentParameters.java | 2 ++ .../genai/types/EmbedContentResponse.java | 2 ++ .../google/genai/types/EncryptionSpec.java | 2 ++ .../google/genai/types/EndSensitivity.java | 4 +++ .../java/com/google/genai/types/Endpoint.java | 2 ++ .../genai/types/EnterpriseWebSearch.java | 2 ++ .../com/google/genai/types/Environment.java | 4 +++ .../ExcludeFromGeneratedCoverageReport.java | 31 +++++++++++++++++++ .../google/genai/types/ExecutableCode.java | 2 ++ .../com/google/genai/types/ExternalApi.java | 2 ++ .../types/ExternalApiElasticSearchParams.java | 2 ++ .../types/ExternalApiSimpleSearchParams.java | 2 ++ .../types/FeatureSelectionPreference.java | 4 +++ .../types/FetchPredictOperationConfig.java | 2 ++ .../FetchPredictOperationParameters.java | 2 ++ .../java/com/google/genai/types/File.java | 2 ++ .../java/com/google/genai/types/FileData.java | 2 ++ .../com/google/genai/types/FileSource.java | 4 +++ .../com/google/genai/types/FileState.java | 4 +++ .../com/google/genai/types/FileStatus.java | 2 ++ .../com/google/genai/types/FinishReason.java | 4 +++ .../com/google/genai/types/FunctionCall.java | 2 ++ .../genai/types/FunctionCallingConfig.java | 2 ++ .../types/FunctionCallingConfigMode.java | 4 +++ .../genai/types/FunctionDeclaration.java | 2 ++ .../google/genai/types/FunctionResponse.java | 2 ++ .../types/FunctionResponseScheduling.java | 4 +++ .../genai/types/GeminiPreferenceExample.java | 2 ++ .../GeminiPreferenceExampleCompletion.java | 2 ++ .../genai/types/GenerateContentConfig.java | 2 ++ .../types/GenerateContentParameters.java | 2 ++ .../genai/types/GenerateContentResponse.java | 2 ++ ...GenerateContentResponsePromptFeedback.java | 2 ++ .../GenerateContentResponseUsageMetadata.java | 2 ++ .../genai/types/GenerateImagesConfig.java | 2 ++ .../genai/types/GenerateImagesParameters.java | 2 ++ .../genai/types/GenerateImagesResponse.java | 2 ++ .../genai/types/GenerateVideosConfig.java | 2 ++ .../genai/types/GenerateVideosOperation.java | 2 ++ .../genai/types/GenerateVideosParameters.java | 2 ++ .../genai/types/GenerateVideosResponse.java | 2 ++ .../google/genai/types/GeneratedImage.java | 2 ++ .../google/genai/types/GeneratedVideo.java | 2 ++ .../google/genai/types/GenerationConfig.java | 2 ++ .../types/GenerationConfigRoutingConfig.java | 2 ++ ...ionConfigRoutingConfigAutoRoutingMode.java | 2 ++ ...nConfigRoutingConfigManualRoutingMode.java | 2 ++ .../types/GenerationConfigThinkingConfig.java | 2 ++ .../google/genai/types/GetBatchJobConfig.java | 2 ++ .../genai/types/GetBatchJobParameters.java | 2 ++ .../genai/types/GetCachedContentConfig.java | 2 ++ .../types/GetCachedContentParameters.java | 2 ++ .../com/google/genai/types/GetFileConfig.java | 2 ++ .../google/genai/types/GetFileParameters.java | 2 ++ .../google/genai/types/GetModelConfig.java | 2 ++ .../genai/types/GetModelParameters.java | 2 ++ .../genai/types/GetOperationConfig.java | 2 ++ .../genai/types/GetOperationParameters.java | 2 ++ .../genai/types/GetTuningJobConfig.java | 2 ++ .../genai/types/GetTuningJobParameters.java | 2 ++ .../com/google/genai/types/GoogleMaps.java | 2 ++ .../google/genai/types/GoogleRpcStatus.java | 2 ++ .../com/google/genai/types/GoogleSearch.java | 2 ++ .../genai/types/GoogleSearchRetrieval.java | 2 ++ .../google/genai/types/GoogleTypeDate.java | 2 ++ .../google/genai/types/GroundingChunk.java | 2 ++ .../genai/types/GroundingChunkMaps.java | 2 ++ .../GroundingChunkMapsPlaceAnswerSources.java | 2 ++ ...psPlaceAnswerSourcesAuthorAttribution.java | 2 ++ ...nkMapsPlaceAnswerSourcesReviewSnippet.java | 2 ++ .../types/GroundingChunkRetrievedContext.java | 2 ++ .../google/genai/types/GroundingChunkWeb.java | 2 ++ .../google/genai/types/GroundingMetadata.java | 2 ++ .../google/genai/types/GroundingSupport.java | 2 ++ .../google/genai/types/HarmBlockMethod.java | 4 +++ .../genai/types/HarmBlockThreshold.java | 4 +++ .../com/google/genai/types/HarmCategory.java | 4 +++ .../google/genai/types/HarmProbability.java | 4 +++ .../com/google/genai/types/HarmSeverity.java | 4 +++ .../com/google/genai/types/HttpOptions.java | 2 ++ .../com/google/genai/types/HttpResponse.java | 2 ++ .../java/com/google/genai/types/Image.java | 2 ++ .../genai/types/ImagePromptLanguage.java | 4 +++ .../google/genai/types/InlinedRequest.java | 2 ++ .../google/genai/types/InlinedResponse.java | 2 ++ .../java/com/google/genai/types/Interval.java | 2 ++ .../java/com/google/genai/types/JobError.java | 2 ++ .../java/com/google/genai/types/JobState.java | 4 +++ .../java/com/google/genai/types/Language.java | 4 +++ .../java/com/google/genai/types/LatLng.java | 2 ++ .../genai/types/ListBatchJobsConfig.java | 2 ++ .../genai/types/ListBatchJobsParameters.java | 2 ++ .../genai/types/ListBatchJobsResponse.java | 2 ++ .../genai/types/ListCachedContentsConfig.java | 2 ++ .../types/ListCachedContentsParameters.java | 2 ++ .../types/ListCachedContentsResponse.java | 2 ++ .../google/genai/types/ListFilesConfig.java | 2 ++ .../genai/types/ListFilesParameters.java | 2 ++ .../google/genai/types/ListFilesResponse.java | 2 ++ .../google/genai/types/ListModelsConfig.java | 2 ++ .../genai/types/ListModelsParameters.java | 2 ++ .../genai/types/ListModelsResponse.java | 2 ++ .../genai/types/ListTuningJobsConfig.java | 2 ++ .../genai/types/ListTuningJobsParameters.java | 2 ++ .../genai/types/ListTuningJobsResponse.java | 2 ++ .../google/genai/types/LiveClientContent.java | 2 ++ .../google/genai/types/LiveClientMessage.java | 2 ++ .../genai/types/LiveClientRealtimeInput.java | 2 ++ .../google/genai/types/LiveClientSetup.java | 2 ++ .../genai/types/LiveClientToolResponse.java | 2 ++ .../google/genai/types/LiveConnectConfig.java | 2 ++ .../genai/types/LiveConnectConstraints.java | 2 ++ .../genai/types/LiveConnectParameters.java | 2 ++ .../LiveSendClientContentParameters.java | 2 ++ .../LiveSendRealtimeInputParameters.java | 2 ++ .../types/LiveSendToolResponseParameters.java | 2 ++ .../google/genai/types/LiveServerContent.java | 2 ++ .../google/genai/types/LiveServerGoAway.java | 2 ++ .../google/genai/types/LiveServerMessage.java | 2 ++ .../LiveServerSessionResumptionUpdate.java | 2 ++ .../genai/types/LiveServerSetupComplete.java | 2 ++ .../genai/types/LiveServerToolCall.java | 2 ++ .../types/LiveServerToolCallCancellation.java | 2 ++ .../google/genai/types/LogprobsResult.java | 2 ++ .../genai/types/LogprobsResultCandidate.java | 2 ++ .../types/LogprobsResultTopCandidates.java | 2 ++ .../genai/types/MaskReferenceConfig.java | 2 ++ .../genai/types/MaskReferenceImage.java | 2 ++ .../google/genai/types/MaskReferenceMode.java | 4 +++ .../com/google/genai/types/MediaModality.java | 4 +++ .../google/genai/types/MediaResolution.java | 4 +++ .../java/com/google/genai/types/Modality.java | 4 +++ .../genai/types/ModalityTokenCount.java | 2 ++ .../java/com/google/genai/types/Mode.java | 4 +++ .../java/com/google/genai/types/Model.java | 2 ++ .../genai/types/ModelRoutingPreference.java | 4 +++ .../genai/types/ModelSelectionConfig.java | 2 ++ .../genai/types/MultiSpeakerVoiceConfig.java | 2 ++ .../java/com/google/genai/types/Outcome.java | 4 +++ .../java/com/google/genai/types/Part.java | 2 ++ .../genai/types/PartnerModelTuningSpec.java | 2 ++ .../google/genai/types/PersonGeneration.java | 4 +++ .../com/google/genai/types/PreTunedModel.java | 2 ++ .../genai/types/PrebuiltVoiceConfig.java | 2 ++ .../PreferenceOptimizationDataStats.java | 2 ++ ...PreferenceOptimizationHyperParameters.java | 2 ++ .../types/PreferenceOptimizationSpec.java | 2 ++ .../google/genai/types/ProactivityConfig.java | 2 ++ .../com/google/genai/types/ProductImage.java | 2 ++ .../java/com/google/genai/types/RagChunk.java | 2 ++ .../google/genai/types/RagChunkPageSpan.java | 2 ++ .../genai/types/RagRetrievalConfig.java | 2 ++ .../genai/types/RagRetrievalConfigFilter.java | 2 ++ .../types/RagRetrievalConfigHybridSearch.java | 2 ++ .../types/RagRetrievalConfigRanking.java | 2 ++ .../RagRetrievalConfigRankingLlmRanker.java | 2 ++ .../RagRetrievalConfigRankingRankService.java | 2 ++ .../google/genai/types/RawReferenceImage.java | 2 ++ .../genai/types/RealtimeInputConfig.java | 2 ++ .../genai/types/RecontextImageConfig.java | 2 ++ .../genai/types/RecontextImageParameters.java | 2 ++ .../genai/types/RecontextImageResponse.java | 2 ++ .../genai/types/RecontextImageSource.java | 2 ++ .../google/genai/types/ReferenceImageAPI.java | 2 ++ .../com/google/genai/types/ReplayFile.java | 2 ++ .../google/genai/types/ReplayInteraction.java | 2 ++ .../com/google/genai/types/ReplayRequest.java | 2 ++ .../google/genai/types/ReplayResponse.java | 2 ++ .../com/google/genai/types/Retrieval.java | 2 ++ .../google/genai/types/RetrievalConfig.java | 2 ++ .../google/genai/types/RetrievalMetadata.java | 2 ++ .../google/genai/types/SafetyAttributes.java | 2 ++ .../google/genai/types/SafetyFilterLevel.java | 4 +++ .../com/google/genai/types/SafetyRating.java | 2 ++ .../com/google/genai/types/SafetySetting.java | 2 ++ .../java/com/google/genai/types/Schema.java | 2 ++ .../google/genai/types/SearchEntryPoint.java | 2 ++ .../java/com/google/genai/types/Segment.java | 2 ++ .../genai/types/SessionResumptionConfig.java | 2 ++ .../com/google/genai/types/SlidingWindow.java | 2 ++ .../genai/types/SpeakerVoiceConfig.java | 2 ++ .../com/google/genai/types/SpeechConfig.java | 2 ++ .../google/genai/types/StartSensitivity.java | 4 +++ .../genai/types/StyleReferenceConfig.java | 2 ++ .../genai/types/StyleReferenceImage.java | 2 ++ .../genai/types/SubjectReferenceConfig.java | 2 ++ .../genai/types/SubjectReferenceImage.java | 2 ++ .../genai/types/SubjectReferenceType.java | 4 +++ .../types/SupervisedHyperParameters.java | 2 ++ .../types/SupervisedTuningDataStats.java | 2 ++ .../SupervisedTuningDatasetDistribution.java | 2 ++ ...uningDatasetDistributionDatasetBucket.java | 2 ++ .../genai/types/SupervisedTuningSpec.java | 2 ++ .../com/google/genai/types/TestTableFile.java | 2 ++ .../com/google/genai/types/TestTableItem.java | 2 ++ .../google/genai/types/ThinkingConfig.java | 2 ++ .../com/google/genai/types/TokensInfo.java | 2 ++ .../java/com/google/genai/types/Tool.java | 2 ++ .../google/genai/types/ToolCodeExecution.java | 2 ++ .../google/genai/types/ToolComputerUse.java | 2 ++ .../com/google/genai/types/ToolConfig.java | 2 ++ .../com/google/genai/types/TrafficType.java | 4 +++ .../com/google/genai/types/Transcription.java | 2 ++ .../com/google/genai/types/TunedModel.java | 2 ++ .../genai/types/TunedModelCheckpoint.java | 2 ++ .../google/genai/types/TunedModelInfo.java | 2 ++ .../google/genai/types/TuningDataStats.java | 2 ++ .../com/google/genai/types/TuningDataset.java | 2 ++ .../com/google/genai/types/TuningExample.java | 2 ++ .../com/google/genai/types/TuningJob.java | 2 ++ .../com/google/genai/types/TuningMode.java | 4 +++ .../google/genai/types/TuningOperation.java | 2 ++ .../com/google/genai/types/TuningTask.java | 4 +++ .../genai/types/TuningValidationDataset.java | 2 ++ .../com/google/genai/types/TurnCoverage.java | 4 +++ .../java/com/google/genai/types/Type.java | 4 +++ .../types/UpdateCachedContentConfig.java | 2 ++ .../types/UpdateCachedContentParameters.java | 2 ++ .../google/genai/types/UpdateModelConfig.java | 2 ++ .../genai/types/UpdateModelParameters.java | 2 ++ .../google/genai/types/UploadFileConfig.java | 2 ++ .../genai/types/UpscaleImageAPIConfig.java | 2 ++ .../types/UpscaleImageAPIParameters.java | 2 ++ .../genai/types/UpscaleImageConfig.java | 2 ++ .../genai/types/UpscaleImageParameters.java | 2 ++ .../genai/types/UpscaleImageResponse.java | 2 ++ .../com/google/genai/types/UrlContext.java | 2 ++ .../genai/types/UrlContextMetadata.java | 2 ++ .../com/google/genai/types/UrlMetadata.java | 2 ++ .../genai/types/UrlRetrievalStatus.java | 4 +++ .../com/google/genai/types/UsageMetadata.java | 2 ++ .../genai/types/VeoHyperParameters.java | 2 ++ .../com/google/genai/types/VeoTuningSpec.java | 2 ++ .../google/genai/types/VertexAISearch.java | 2 ++ .../types/VertexAISearchDataStoreSpec.java | 2 ++ .../google/genai/types/VertexRagStore.java | 2 ++ .../types/VertexRagStoreRagResource.java | 2 ++ .../java/com/google/genai/types/Video.java | 2 ++ .../genai/types/VideoCompressionQuality.java | 4 +++ .../com/google/genai/types/VideoMetadata.java | 2 ++ .../com/google/genai/types/VoiceConfig.java | 2 ++ 326 files changed, 767 insertions(+), 2 deletions(-) create mode 100644 src/main/java/com/google/genai/types/ExcludeFromGeneratedCoverageReport.java diff --git a/pom.xml b/pom.xml index 6aec20651eb..8a9c7eec80d 100644 --- a/pom.xml +++ b/pom.xml @@ -366,8 +366,8 @@ INSTRUCTION COVEREDRATIO - - 0.30 + + 0.40 diff --git a/src/main/java/com/google/genai/types/ActivityEnd.java b/src/main/java/com/google/genai/types/ActivityEnd.java index 98778d34ba4..24446b34a68 100644 --- a/src/main/java/com/google/genai/types/ActivityEnd.java +++ b/src/main/java/com/google/genai/types/ActivityEnd.java @@ -32,6 +32,7 @@ @JsonDeserialize(builder = ActivityEnd.Builder.class) public abstract class ActivityEnd extends JsonSerializable { /** Instantiates a builder for ActivityEnd. */ + @ExcludeFromGeneratedCoverageReport public static Builder builder() { return new AutoValue_ActivityEnd.Builder(); } @@ -52,6 +53,7 @@ private static Builder create() { } /** Deserializes a JSON string to a ActivityEnd object. */ + @ExcludeFromGeneratedCoverageReport public static ActivityEnd fromJson(String jsonString) { return JsonSerializable.fromJsonString(jsonString, ActivityEnd.class); } diff --git a/src/main/java/com/google/genai/types/ActivityHandling.java b/src/main/java/com/google/genai/types/ActivityHandling.java index 1f14255254e..d2c39aacfac 100644 --- a/src/main/java/com/google/genai/types/ActivityHandling.java +++ b/src/main/java/com/google/genai/types/ActivityHandling.java @@ -64,12 +64,14 @@ public ActivityHandling(Known knownValue) { this.value = knownValue.toString(); } + @ExcludeFromGeneratedCoverageReport @Override @JsonValue public String toString() { return this.value; } + @ExcludeFromGeneratedCoverageReport @SuppressWarnings("PatternMatchingInstanceof") @Override public boolean equals(Object o) { @@ -96,6 +98,7 @@ public boolean equals(Object o) { return false; } + @ExcludeFromGeneratedCoverageReport @Override public int hashCode() { if (this.activityHandlingEnum != Known.ACTIVITY_HANDLING_UNSPECIFIED) { @@ -105,6 +108,7 @@ public int hashCode() { } } + @ExcludeFromGeneratedCoverageReport public Known knownEnum() { return this.activityHandlingEnum; } diff --git a/src/main/java/com/google/genai/types/ActivityStart.java b/src/main/java/com/google/genai/types/ActivityStart.java index 7945ad51cdd..1686db78195 100644 --- a/src/main/java/com/google/genai/types/ActivityStart.java +++ b/src/main/java/com/google/genai/types/ActivityStart.java @@ -32,6 +32,7 @@ @JsonDeserialize(builder = ActivityStart.Builder.class) public abstract class ActivityStart extends JsonSerializable { /** Instantiates a builder for ActivityStart. */ + @ExcludeFromGeneratedCoverageReport public static Builder builder() { return new AutoValue_ActivityStart.Builder(); } @@ -52,6 +53,7 @@ private static Builder create() { } /** Deserializes a JSON string to a ActivityStart object. */ + @ExcludeFromGeneratedCoverageReport public static ActivityStart fromJson(String jsonString) { return JsonSerializable.fromJsonString(jsonString, ActivityStart.class); } diff --git a/src/main/java/com/google/genai/types/AdapterSize.java b/src/main/java/com/google/genai/types/AdapterSize.java index fa47b3d31e6..6117aa00336 100644 --- a/src/main/java/com/google/genai/types/AdapterSize.java +++ b/src/main/java/com/google/genai/types/AdapterSize.java @@ -72,12 +72,14 @@ public AdapterSize(Known knownValue) { this.value = knownValue.toString(); } + @ExcludeFromGeneratedCoverageReport @Override @JsonValue public String toString() { return this.value; } + @ExcludeFromGeneratedCoverageReport @SuppressWarnings("PatternMatchingInstanceof") @Override public boolean equals(Object o) { @@ -104,6 +106,7 @@ public boolean equals(Object o) { return false; } + @ExcludeFromGeneratedCoverageReport @Override public int hashCode() { if (this.adapterSizeEnum != Known.ADAPTER_SIZE_UNSPECIFIED) { @@ -113,6 +116,7 @@ public int hashCode() { } } + @ExcludeFromGeneratedCoverageReport public Known knownEnum() { return this.adapterSizeEnum; } diff --git a/src/main/java/com/google/genai/types/ApiAuth.java b/src/main/java/com/google/genai/types/ApiAuth.java index 2ae9cc777e3..e67d1c91d4e 100644 --- a/src/main/java/com/google/genai/types/ApiAuth.java +++ b/src/main/java/com/google/genai/types/ApiAuth.java @@ -37,6 +37,7 @@ public abstract class ApiAuth extends JsonSerializable { public abstract Optional apiKeyConfig(); /** Instantiates a builder for ApiAuth. */ + @ExcludeFromGeneratedCoverageReport public static Builder builder() { return new AutoValue_ApiAuth.Builder(); } @@ -74,6 +75,7 @@ public Builder apiKeyConfig(ApiAuthApiKeyConfig.Builder apiKeyConfigBuilder) { } /** Deserializes a JSON string to a ApiAuth object. */ + @ExcludeFromGeneratedCoverageReport public static ApiAuth fromJson(String jsonString) { return JsonSerializable.fromJsonString(jsonString, ApiAuth.class); } diff --git a/src/main/java/com/google/genai/types/ApiAuthApiKeyConfig.java b/src/main/java/com/google/genai/types/ApiAuthApiKeyConfig.java index 2211294f2d8..4408a0e9910 100644 --- a/src/main/java/com/google/genai/types/ApiAuthApiKeyConfig.java +++ b/src/main/java/com/google/genai/types/ApiAuthApiKeyConfig.java @@ -41,6 +41,7 @@ public abstract class ApiAuthApiKeyConfig extends JsonSerializable { public abstract Optional apiKeyString(); /** Instantiates a builder for ApiAuthApiKeyConfig. */ + @ExcludeFromGeneratedCoverageReport public static Builder builder() { return new AutoValue_ApiAuthApiKeyConfig.Builder(); } @@ -78,6 +79,7 @@ private static Builder create() { } /** Deserializes a JSON string to a ApiAuthApiKeyConfig object. */ + @ExcludeFromGeneratedCoverageReport public static ApiAuthApiKeyConfig fromJson(String jsonString) { return JsonSerializable.fromJsonString(jsonString, ApiAuthApiKeyConfig.class); } diff --git a/src/main/java/com/google/genai/types/ApiKeyConfig.java b/src/main/java/com/google/genai/types/ApiKeyConfig.java index 6ffd2019679..d8c1cb63433 100644 --- a/src/main/java/com/google/genai/types/ApiKeyConfig.java +++ b/src/main/java/com/google/genai/types/ApiKeyConfig.java @@ -34,6 +34,7 @@ public abstract class ApiKeyConfig extends JsonSerializable { public abstract Optional apiKeyString(); /** Instantiates a builder for ApiKeyConfig. */ + @ExcludeFromGeneratedCoverageReport public static Builder builder() { return new AutoValue_ApiKeyConfig.Builder(); } @@ -62,6 +63,7 @@ private static Builder create() { } /** Deserializes a JSON string to a ApiKeyConfig object. */ + @ExcludeFromGeneratedCoverageReport public static ApiKeyConfig fromJson(String jsonString) { return JsonSerializable.fromJsonString(jsonString, ApiKeyConfig.class); } diff --git a/src/main/java/com/google/genai/types/ApiSpec.java b/src/main/java/com/google/genai/types/ApiSpec.java index 17283d5724c..4fd336b8917 100644 --- a/src/main/java/com/google/genai/types/ApiSpec.java +++ b/src/main/java/com/google/genai/types/ApiSpec.java @@ -60,12 +60,14 @@ public ApiSpec(Known knownValue) { this.value = knownValue.toString(); } + @ExcludeFromGeneratedCoverageReport @Override @JsonValue public String toString() { return this.value; } + @ExcludeFromGeneratedCoverageReport @SuppressWarnings("PatternMatchingInstanceof") @Override public boolean equals(Object o) { @@ -92,6 +94,7 @@ public boolean equals(Object o) { return false; } + @ExcludeFromGeneratedCoverageReport @Override public int hashCode() { if (this.apiSpecEnum != Known.API_SPEC_UNSPECIFIED) { @@ -101,6 +104,7 @@ public int hashCode() { } } + @ExcludeFromGeneratedCoverageReport public Known knownEnum() { return this.apiSpecEnum; } diff --git a/src/main/java/com/google/genai/types/AudioTranscriptionConfig.java b/src/main/java/com/google/genai/types/AudioTranscriptionConfig.java index a444bcea7f3..61a54d4c9db 100644 --- a/src/main/java/com/google/genai/types/AudioTranscriptionConfig.java +++ b/src/main/java/com/google/genai/types/AudioTranscriptionConfig.java @@ -28,6 +28,7 @@ @JsonDeserialize(builder = AudioTranscriptionConfig.Builder.class) public abstract class AudioTranscriptionConfig extends JsonSerializable { /** Instantiates a builder for AudioTranscriptionConfig. */ + @ExcludeFromGeneratedCoverageReport public static Builder builder() { return new AutoValue_AudioTranscriptionConfig.Builder(); } @@ -48,6 +49,7 @@ private static Builder create() { } /** Deserializes a JSON string to a AudioTranscriptionConfig object. */ + @ExcludeFromGeneratedCoverageReport public static AudioTranscriptionConfig fromJson(String jsonString) { return JsonSerializable.fromJsonString(jsonString, AudioTranscriptionConfig.class); } diff --git a/src/main/java/com/google/genai/types/AuthConfig.java b/src/main/java/com/google/genai/types/AuthConfig.java index eec5deb5f22..d2cb708191f 100644 --- a/src/main/java/com/google/genai/types/AuthConfig.java +++ b/src/main/java/com/google/genai/types/AuthConfig.java @@ -55,6 +55,7 @@ public abstract class AuthConfig extends JsonSerializable { public abstract Optional oidcConfig(); /** Instantiates a builder for AuthConfig. */ + @ExcludeFromGeneratedCoverageReport public static Builder builder() { return new AutoValue_AuthConfig.Builder(); } @@ -191,6 +192,7 @@ public Builder oidcConfig(AuthConfigOidcConfig.Builder oidcConfigBuilder) { } /** Deserializes a JSON string to a AuthConfig object. */ + @ExcludeFromGeneratedCoverageReport public static AuthConfig fromJson(String jsonString) { return JsonSerializable.fromJsonString(jsonString, AuthConfig.class); } diff --git a/src/main/java/com/google/genai/types/AuthConfigGoogleServiceAccountConfig.java b/src/main/java/com/google/genai/types/AuthConfigGoogleServiceAccountConfig.java index 9bbf124d26f..3785a26ca2b 100644 --- a/src/main/java/com/google/genai/types/AuthConfigGoogleServiceAccountConfig.java +++ b/src/main/java/com/google/genai/types/AuthConfigGoogleServiceAccountConfig.java @@ -41,6 +41,7 @@ public abstract class AuthConfigGoogleServiceAccountConfig extends JsonSerializa public abstract Optional serviceAccount(); /** Instantiates a builder for AuthConfigGoogleServiceAccountConfig. */ + @ExcludeFromGeneratedCoverageReport public static Builder builder() { return new AutoValue_AuthConfigGoogleServiceAccountConfig.Builder(); } @@ -77,6 +78,7 @@ private static Builder create() { } /** Deserializes a JSON string to a AuthConfigGoogleServiceAccountConfig object. */ + @ExcludeFromGeneratedCoverageReport public static AuthConfigGoogleServiceAccountConfig fromJson(String jsonString) { return JsonSerializable.fromJsonString(jsonString, AuthConfigGoogleServiceAccountConfig.class); } diff --git a/src/main/java/com/google/genai/types/AuthConfigHttpBasicAuthConfig.java b/src/main/java/com/google/genai/types/AuthConfigHttpBasicAuthConfig.java index 34e55ddf9d8..900b285a4ea 100644 --- a/src/main/java/com/google/genai/types/AuthConfigHttpBasicAuthConfig.java +++ b/src/main/java/com/google/genai/types/AuthConfigHttpBasicAuthConfig.java @@ -40,6 +40,7 @@ public abstract class AuthConfigHttpBasicAuthConfig extends JsonSerializable { public abstract Optional credentialSecret(); /** Instantiates a builder for AuthConfigHttpBasicAuthConfig. */ + @ExcludeFromGeneratedCoverageReport public static Builder builder() { return new AutoValue_AuthConfigHttpBasicAuthConfig.Builder(); } @@ -75,6 +76,7 @@ private static Builder create() { } /** Deserializes a JSON string to a AuthConfigHttpBasicAuthConfig object. */ + @ExcludeFromGeneratedCoverageReport public static AuthConfigHttpBasicAuthConfig fromJson(String jsonString) { return JsonSerializable.fromJsonString(jsonString, AuthConfigHttpBasicAuthConfig.class); } diff --git a/src/main/java/com/google/genai/types/AuthConfigOauthConfig.java b/src/main/java/com/google/genai/types/AuthConfigOauthConfig.java index 42082cf4bd6..709f5a29b98 100644 --- a/src/main/java/com/google/genai/types/AuthConfigOauthConfig.java +++ b/src/main/java/com/google/genai/types/AuthConfigOauthConfig.java @@ -47,6 +47,7 @@ public abstract class AuthConfigOauthConfig extends JsonSerializable { public abstract Optional serviceAccount(); /** Instantiates a builder for AuthConfigOauthConfig. */ + @ExcludeFromGeneratedCoverageReport public static Builder builder() { return new AutoValue_AuthConfigOauthConfig.Builder(); } @@ -88,6 +89,7 @@ private static Builder create() { } /** Deserializes a JSON string to a AuthConfigOauthConfig object. */ + @ExcludeFromGeneratedCoverageReport public static AuthConfigOauthConfig fromJson(String jsonString) { return JsonSerializable.fromJsonString(jsonString, AuthConfigOauthConfig.class); } diff --git a/src/main/java/com/google/genai/types/AuthConfigOidcConfig.java b/src/main/java/com/google/genai/types/AuthConfigOidcConfig.java index 4f5339f09e6..33ced7433e3 100644 --- a/src/main/java/com/google/genai/types/AuthConfigOidcConfig.java +++ b/src/main/java/com/google/genai/types/AuthConfigOidcConfig.java @@ -49,6 +49,7 @@ public abstract class AuthConfigOidcConfig extends JsonSerializable { public abstract Optional serviceAccount(); /** Instantiates a builder for AuthConfigOidcConfig. */ + @ExcludeFromGeneratedCoverageReport public static Builder builder() { return new AutoValue_AuthConfigOidcConfig.Builder(); } @@ -92,6 +93,7 @@ private static Builder create() { } /** Deserializes a JSON string to a AuthConfigOidcConfig object. */ + @ExcludeFromGeneratedCoverageReport public static AuthConfigOidcConfig fromJson(String jsonString) { return JsonSerializable.fromJsonString(jsonString, AuthConfigOidcConfig.class); } diff --git a/src/main/java/com/google/genai/types/AuthType.java b/src/main/java/com/google/genai/types/AuthType.java index 4ac09d48c8a..7f03715507d 100644 --- a/src/main/java/com/google/genai/types/AuthType.java +++ b/src/main/java/com/google/genai/types/AuthType.java @@ -71,12 +71,14 @@ public AuthType(Known knownValue) { this.value = knownValue.toString(); } + @ExcludeFromGeneratedCoverageReport @Override @JsonValue public String toString() { return this.value; } + @ExcludeFromGeneratedCoverageReport @SuppressWarnings("PatternMatchingInstanceof") @Override public boolean equals(Object o) { @@ -103,6 +105,7 @@ public boolean equals(Object o) { return false; } + @ExcludeFromGeneratedCoverageReport @Override public int hashCode() { if (this.authTypeEnum != Known.AUTH_TYPE_UNSPECIFIED) { @@ -112,6 +115,7 @@ public int hashCode() { } } + @ExcludeFromGeneratedCoverageReport public Known knownEnum() { return this.authTypeEnum; } diff --git a/src/main/java/com/google/genai/types/AutomaticActivityDetection.java b/src/main/java/com/google/genai/types/AutomaticActivityDetection.java index 17f587ea59b..cd381f2aec6 100644 --- a/src/main/java/com/google/genai/types/AutomaticActivityDetection.java +++ b/src/main/java/com/google/genai/types/AutomaticActivityDetection.java @@ -62,6 +62,7 @@ public abstract class AutomaticActivityDetection extends JsonSerializable { public abstract Optional silenceDurationMs(); /** Instantiates a builder for AutomaticActivityDetection. */ + @ExcludeFromGeneratedCoverageReport public static Builder builder() { return new AutoValue_AutomaticActivityDetection.Builder(); } @@ -168,6 +169,7 @@ public Builder endOfSpeechSensitivity(String endOfSpeechSensitivity) { } /** Deserializes a JSON string to a AutomaticActivityDetection object. */ + @ExcludeFromGeneratedCoverageReport public static AutomaticActivityDetection fromJson(String jsonString) { return JsonSerializable.fromJsonString(jsonString, AutomaticActivityDetection.class); } diff --git a/src/main/java/com/google/genai/types/AutomaticFunctionCallingConfig.java b/src/main/java/com/google/genai/types/AutomaticFunctionCallingConfig.java index e161a75f312..252e8df5c31 100644 --- a/src/main/java/com/google/genai/types/AutomaticFunctionCallingConfig.java +++ b/src/main/java/com/google/genai/types/AutomaticFunctionCallingConfig.java @@ -53,6 +53,7 @@ public abstract class AutomaticFunctionCallingConfig extends JsonSerializable { public abstract Optional ignoreCallHistory(); /** Instantiates a builder for AutomaticFunctionCallingConfig. */ + @ExcludeFromGeneratedCoverageReport public static Builder builder() { return new AutoValue_AutomaticFunctionCallingConfig.Builder(); } @@ -104,6 +105,7 @@ private static Builder create() { } /** Deserializes a JSON string to a AutomaticFunctionCallingConfig object. */ + @ExcludeFromGeneratedCoverageReport public static AutomaticFunctionCallingConfig fromJson(String jsonString) { return JsonSerializable.fromJsonString(jsonString, AutomaticFunctionCallingConfig.class); } diff --git a/src/main/java/com/google/genai/types/BatchJob.java b/src/main/java/com/google/genai/types/BatchJob.java index 87f829a4d70..b4394be60fc 100644 --- a/src/main/java/com/google/genai/types/BatchJob.java +++ b/src/main/java/com/google/genai/types/BatchJob.java @@ -78,6 +78,7 @@ public abstract class BatchJob extends JsonSerializable { public abstract Optional dest(); /** Instantiates a builder for BatchJob. */ + @ExcludeFromGeneratedCoverageReport public static Builder builder() { return new AutoValue_BatchJob.Builder(); } @@ -236,6 +237,7 @@ public Builder dest(BatchJobDestination.Builder destBuilder) { } /** Deserializes a JSON string to a BatchJob object. */ + @ExcludeFromGeneratedCoverageReport public static BatchJob fromJson(String jsonString) { return JsonSerializable.fromJsonString(jsonString, BatchJob.class); } diff --git a/src/main/java/com/google/genai/types/BatchJobDestination.java b/src/main/java/com/google/genai/types/BatchJobDestination.java index 49c7f2933df..7ca1aa5f968 100644 --- a/src/main/java/com/google/genai/types/BatchJobDestination.java +++ b/src/main/java/com/google/genai/types/BatchJobDestination.java @@ -62,6 +62,7 @@ public abstract class BatchJobDestination extends JsonSerializable { public abstract Optional> inlinedResponses(); /** Instantiates a builder for BatchJobDestination. */ + @ExcludeFromGeneratedCoverageReport public static Builder builder() { return new AutoValue_BatchJobDestination.Builder(); } @@ -149,6 +150,7 @@ public Builder inlinedResponses(InlinedResponse.Builder... inlinedResponsesBuild } /** Deserializes a JSON string to a BatchJobDestination object. */ + @ExcludeFromGeneratedCoverageReport public static BatchJobDestination fromJson(String jsonString) { return JsonSerializable.fromJsonString(jsonString, BatchJobDestination.class); } diff --git a/src/main/java/com/google/genai/types/BatchJobSource.java b/src/main/java/com/google/genai/types/BatchJobSource.java index d56d3f69011..d45dd9e196b 100644 --- a/src/main/java/com/google/genai/types/BatchJobSource.java +++ b/src/main/java/com/google/genai/types/BatchJobSource.java @@ -54,6 +54,7 @@ public abstract class BatchJobSource extends JsonSerializable { public abstract Optional> inlinedRequests(); /** Instantiates a builder for BatchJobSource. */ + @ExcludeFromGeneratedCoverageReport public static Builder builder() { return new AutoValue_BatchJobSource.Builder(); } @@ -145,6 +146,7 @@ public Builder inlinedRequests(InlinedRequest.Builder... inlinedRequestsBuilders } /** Deserializes a JSON string to a BatchJobSource object. */ + @ExcludeFromGeneratedCoverageReport public static BatchJobSource fromJson(String jsonString) { return JsonSerializable.fromJsonString(jsonString, BatchJobSource.class); } diff --git a/src/main/java/com/google/genai/types/Behavior.java b/src/main/java/com/google/genai/types/Behavior.java index baff1526f3f..4b043a4484e 100644 --- a/src/main/java/com/google/genai/types/Behavior.java +++ b/src/main/java/com/google/genai/types/Behavior.java @@ -69,12 +69,14 @@ public Behavior(Known knownValue) { this.value = knownValue.toString(); } + @ExcludeFromGeneratedCoverageReport @Override @JsonValue public String toString() { return this.value; } + @ExcludeFromGeneratedCoverageReport @SuppressWarnings("PatternMatchingInstanceof") @Override public boolean equals(Object o) { @@ -101,6 +103,7 @@ public boolean equals(Object o) { return false; } + @ExcludeFromGeneratedCoverageReport @Override public int hashCode() { if (this.behaviorEnum != Known.BEHAVIOR_UNSPECIFIED) { @@ -110,6 +113,7 @@ public int hashCode() { } } + @ExcludeFromGeneratedCoverageReport public Known knownEnum() { return this.behaviorEnum; } diff --git a/src/main/java/com/google/genai/types/Blob.java b/src/main/java/com/google/genai/types/Blob.java index 923319396c5..5de616bfb2d 100644 --- a/src/main/java/com/google/genai/types/Blob.java +++ b/src/main/java/com/google/genai/types/Blob.java @@ -45,6 +45,7 @@ public abstract class Blob extends JsonSerializable { public abstract Optional mimeType(); /** Instantiates a builder for Blob. */ + @ExcludeFromGeneratedCoverageReport public static Builder builder() { return new AutoValue_Blob.Builder(); } @@ -90,6 +91,7 @@ private static Builder create() { } /** Deserializes a JSON string to a Blob object. */ + @ExcludeFromGeneratedCoverageReport public static Blob fromJson(String jsonString) { return JsonSerializable.fromJsonString(jsonString, Blob.class); } diff --git a/src/main/java/com/google/genai/types/BlockedReason.java b/src/main/java/com/google/genai/types/BlockedReason.java index fc652ee35d9..cf06e14b5e5 100644 --- a/src/main/java/com/google/genai/types/BlockedReason.java +++ b/src/main/java/com/google/genai/types/BlockedReason.java @@ -69,12 +69,14 @@ public BlockedReason(Known knownValue) { this.value = knownValue.toString(); } + @ExcludeFromGeneratedCoverageReport @Override @JsonValue public String toString() { return this.value; } + @ExcludeFromGeneratedCoverageReport @SuppressWarnings("PatternMatchingInstanceof") @Override public boolean equals(Object o) { @@ -101,6 +103,7 @@ public boolean equals(Object o) { return false; } + @ExcludeFromGeneratedCoverageReport @Override public int hashCode() { if (this.blockedReasonEnum != Known.BLOCKED_REASON_UNSPECIFIED) { @@ -110,6 +113,7 @@ public int hashCode() { } } + @ExcludeFromGeneratedCoverageReport public Known knownEnum() { return this.blockedReasonEnum; } diff --git a/src/main/java/com/google/genai/types/CachedContent.java b/src/main/java/com/google/genai/types/CachedContent.java index dfc6ba16ba6..0072b18ddad 100644 --- a/src/main/java/com/google/genai/types/CachedContent.java +++ b/src/main/java/com/google/genai/types/CachedContent.java @@ -59,6 +59,7 @@ public abstract class CachedContent extends JsonSerializable { public abstract Optional usageMetadata(); /** Instantiates a builder for CachedContent. */ + @ExcludeFromGeneratedCoverageReport public static Builder builder() { return new AutoValue_CachedContent.Builder(); } @@ -144,6 +145,7 @@ public Builder usageMetadata(CachedContentUsageMetadata.Builder usageMetadataBui } /** Deserializes a JSON string to a CachedContent object. */ + @ExcludeFromGeneratedCoverageReport public static CachedContent fromJson(String jsonString) { return JsonSerializable.fromJsonString(jsonString, CachedContent.class); } diff --git a/src/main/java/com/google/genai/types/CachedContentUsageMetadata.java b/src/main/java/com/google/genai/types/CachedContentUsageMetadata.java index d9d19731ec4..a5a6b7a6dbc 100644 --- a/src/main/java/com/google/genai/types/CachedContentUsageMetadata.java +++ b/src/main/java/com/google/genai/types/CachedContentUsageMetadata.java @@ -50,6 +50,7 @@ public abstract class CachedContentUsageMetadata extends JsonSerializable { public abstract Optional videoDurationSeconds(); /** Instantiates a builder for CachedContentUsageMetadata. */ + @ExcludeFromGeneratedCoverageReport public static Builder builder() { return new AutoValue_CachedContentUsageMetadata.Builder(); } @@ -110,6 +111,7 @@ private static Builder create() { } /** Deserializes a JSON string to a CachedContentUsageMetadata object. */ + @ExcludeFromGeneratedCoverageReport public static CachedContentUsageMetadata fromJson(String jsonString) { return JsonSerializable.fromJsonString(jsonString, CachedContentUsageMetadata.class); } diff --git a/src/main/java/com/google/genai/types/CancelBatchJobConfig.java b/src/main/java/com/google/genai/types/CancelBatchJobConfig.java index 5a06b0cf176..fb3f7e4cd57 100644 --- a/src/main/java/com/google/genai/types/CancelBatchJobConfig.java +++ b/src/main/java/com/google/genai/types/CancelBatchJobConfig.java @@ -34,6 +34,7 @@ public abstract class CancelBatchJobConfig extends JsonSerializable { public abstract Optional httpOptions(); /** Instantiates a builder for CancelBatchJobConfig. */ + @ExcludeFromGeneratedCoverageReport public static Builder builder() { return new AutoValue_CancelBatchJobConfig.Builder(); } @@ -71,6 +72,7 @@ public Builder httpOptions(HttpOptions.Builder httpOptionsBuilder) { } /** Deserializes a JSON string to a CancelBatchJobConfig object. */ + @ExcludeFromGeneratedCoverageReport public static CancelBatchJobConfig fromJson(String jsonString) { return JsonSerializable.fromJsonString(jsonString, CancelBatchJobConfig.class); } diff --git a/src/main/java/com/google/genai/types/CancelBatchJobParameters.java b/src/main/java/com/google/genai/types/CancelBatchJobParameters.java index 83201a43cdd..a8300c880c7 100644 --- a/src/main/java/com/google/genai/types/CancelBatchJobParameters.java +++ b/src/main/java/com/google/genai/types/CancelBatchJobParameters.java @@ -44,6 +44,7 @@ public abstract class CancelBatchJobParameters extends JsonSerializable { public abstract Optional config(); /** Instantiates a builder for CancelBatchJobParameters. */ + @ExcludeFromGeneratedCoverageReport public static Builder builder() { return new AutoValue_CancelBatchJobParameters.Builder(); } @@ -91,6 +92,7 @@ public Builder config(CancelBatchJobConfig.Builder configBuilder) { } /** Deserializes a JSON string to a CancelBatchJobParameters object. */ + @ExcludeFromGeneratedCoverageReport public static CancelBatchJobParameters fromJson(String jsonString) { return JsonSerializable.fromJsonString(jsonString, CancelBatchJobParameters.class); } diff --git a/src/main/java/com/google/genai/types/Candidate.java b/src/main/java/com/google/genai/types/Candidate.java index 22d7e83006b..02ccb9c0399 100644 --- a/src/main/java/com/google/genai/types/Candidate.java +++ b/src/main/java/com/google/genai/types/Candidate.java @@ -85,6 +85,7 @@ public abstract class Candidate extends JsonSerializable { public abstract Optional> safetyRatings(); /** Instantiates a builder for Candidate. */ + @ExcludeFromGeneratedCoverageReport public static Builder builder() { return new AutoValue_Candidate.Builder(); } @@ -287,6 +288,7 @@ public Builder safetyRatings(SafetyRating.Builder... safetyRatingsBuilders) { } /** Deserializes a JSON string to a Candidate object. */ + @ExcludeFromGeneratedCoverageReport public static Candidate fromJson(String jsonString) { return JsonSerializable.fromJsonString(jsonString, Candidate.class); } diff --git a/src/main/java/com/google/genai/types/Checkpoint.java b/src/main/java/com/google/genai/types/Checkpoint.java index 41dd53b0256..9cc5bf87d27 100644 --- a/src/main/java/com/google/genai/types/Checkpoint.java +++ b/src/main/java/com/google/genai/types/Checkpoint.java @@ -42,6 +42,7 @@ public abstract class Checkpoint extends JsonSerializable { public abstract Optional step(); /** Instantiates a builder for Checkpoint. */ + @ExcludeFromGeneratedCoverageReport public static Builder builder() { return new AutoValue_Checkpoint.Builder(); } @@ -86,6 +87,7 @@ private static Builder create() { } /** Deserializes a JSON string to a Checkpoint object. */ + @ExcludeFromGeneratedCoverageReport public static Checkpoint fromJson(String jsonString) { return JsonSerializable.fromJsonString(jsonString, Checkpoint.class); } diff --git a/src/main/java/com/google/genai/types/Citation.java b/src/main/java/com/google/genai/types/Citation.java index 63c0fa41c3a..9815094c96d 100644 --- a/src/main/java/com/google/genai/types/Citation.java +++ b/src/main/java/com/google/genai/types/Citation.java @@ -54,6 +54,7 @@ public abstract class Citation extends JsonSerializable { public abstract Optional uri(); /** Instantiates a builder for Citation. */ + @ExcludeFromGeneratedCoverageReport public static Builder builder() { return new AutoValue_Citation.Builder(); } @@ -131,6 +132,7 @@ public Builder publicationDate(GoogleTypeDate.Builder publicationDateBuilder) { } /** Deserializes a JSON string to a Citation object. */ + @ExcludeFromGeneratedCoverageReport public static Citation fromJson(String jsonString) { return JsonSerializable.fromJsonString(jsonString, Citation.class); } diff --git a/src/main/java/com/google/genai/types/CitationMetadata.java b/src/main/java/com/google/genai/types/CitationMetadata.java index 701e9e70554..d0ac71aa954 100644 --- a/src/main/java/com/google/genai/types/CitationMetadata.java +++ b/src/main/java/com/google/genai/types/CitationMetadata.java @@ -41,6 +41,7 @@ public abstract class CitationMetadata extends JsonSerializable { public abstract Optional> citations(); /** Instantiates a builder for CitationMetadata. */ + @ExcludeFromGeneratedCoverageReport public static Builder builder() { return new AutoValue_CitationMetadata.Builder(); } @@ -93,6 +94,7 @@ public Builder citations(Citation.Builder... citationsBuilders) { } /** Deserializes a JSON string to a CitationMetadata object. */ + @ExcludeFromGeneratedCoverageReport public static CitationMetadata fromJson(String jsonString) { return JsonSerializable.fromJsonString(jsonString, CitationMetadata.class); } diff --git a/src/main/java/com/google/genai/types/ClientOptions.java b/src/main/java/com/google/genai/types/ClientOptions.java index 8157b162225..245d93d9d1a 100644 --- a/src/main/java/com/google/genai/types/ClientOptions.java +++ b/src/main/java/com/google/genai/types/ClientOptions.java @@ -38,6 +38,7 @@ public abstract class ClientOptions extends JsonSerializable { public abstract Optional maxConnectionsPerHost(); /** Instantiates a builder for ClientOptions. */ + @ExcludeFromGeneratedCoverageReport public static Builder builder() { return new AutoValue_ClientOptions.Builder(); } @@ -74,6 +75,7 @@ private static Builder create() { } /** Deserializes a JSON string to a ClientOptions object. */ + @ExcludeFromGeneratedCoverageReport public static ClientOptions fromJson(String jsonString) { return JsonSerializable.fromJsonString(jsonString, ClientOptions.class); } diff --git a/src/main/java/com/google/genai/types/CodeExecutionResult.java b/src/main/java/com/google/genai/types/CodeExecutionResult.java index 2907684badd..433267c12e5 100644 --- a/src/main/java/com/google/genai/types/CodeExecutionResult.java +++ b/src/main/java/com/google/genai/types/CodeExecutionResult.java @@ -45,6 +45,7 @@ public abstract class CodeExecutionResult extends JsonSerializable { public abstract Optional output(); /** Instantiates a builder for CodeExecutionResult. */ + @ExcludeFromGeneratedCoverageReport public static Builder builder() { return new AutoValue_CodeExecutionResult.Builder(); } @@ -102,6 +103,7 @@ public Builder outcome(String outcome) { } /** Deserializes a JSON string to a CodeExecutionResult object. */ + @ExcludeFromGeneratedCoverageReport public static CodeExecutionResult fromJson(String jsonString) { return JsonSerializable.fromJsonString(jsonString, CodeExecutionResult.class); } diff --git a/src/main/java/com/google/genai/types/ComputeTokensConfig.java b/src/main/java/com/google/genai/types/ComputeTokensConfig.java index 6db60ccd1d9..b27800d6c77 100644 --- a/src/main/java/com/google/genai/types/ComputeTokensConfig.java +++ b/src/main/java/com/google/genai/types/ComputeTokensConfig.java @@ -34,6 +34,7 @@ public abstract class ComputeTokensConfig extends JsonSerializable { public abstract Optional httpOptions(); /** Instantiates a builder for ComputeTokensConfig. */ + @ExcludeFromGeneratedCoverageReport public static Builder builder() { return new AutoValue_ComputeTokensConfig.Builder(); } @@ -71,6 +72,7 @@ public Builder httpOptions(HttpOptions.Builder httpOptionsBuilder) { } /** Deserializes a JSON string to a ComputeTokensConfig object. */ + @ExcludeFromGeneratedCoverageReport public static ComputeTokensConfig fromJson(String jsonString) { return JsonSerializable.fromJsonString(jsonString, ComputeTokensConfig.class); } diff --git a/src/main/java/com/google/genai/types/ComputeTokensParameters.java b/src/main/java/com/google/genai/types/ComputeTokensParameters.java index b0c02b9970a..ec789b07dc1 100644 --- a/src/main/java/com/google/genai/types/ComputeTokensParameters.java +++ b/src/main/java/com/google/genai/types/ComputeTokensParameters.java @@ -51,6 +51,7 @@ public abstract class ComputeTokensParameters extends JsonSerializable { public abstract Optional config(); /** Instantiates a builder for ComputeTokensParameters. */ + @ExcludeFromGeneratedCoverageReport public static Builder builder() { return new AutoValue_ComputeTokensParameters.Builder(); } @@ -126,6 +127,7 @@ public Builder config(ComputeTokensConfig.Builder configBuilder) { } /** Deserializes a JSON string to a ComputeTokensParameters object. */ + @ExcludeFromGeneratedCoverageReport public static ComputeTokensParameters fromJson(String jsonString) { return JsonSerializable.fromJsonString(jsonString, ComputeTokensParameters.class); } diff --git a/src/main/java/com/google/genai/types/ComputeTokensResponse.java b/src/main/java/com/google/genai/types/ComputeTokensResponse.java index 60caed0e736..12d98eda999 100644 --- a/src/main/java/com/google/genai/types/ComputeTokensResponse.java +++ b/src/main/java/com/google/genai/types/ComputeTokensResponse.java @@ -42,6 +42,7 @@ public abstract class ComputeTokensResponse extends JsonSerializable { public abstract Optional> tokensInfo(); /** Instantiates a builder for ComputeTokensResponse. */ + @ExcludeFromGeneratedCoverageReport public static Builder builder() { return new AutoValue_ComputeTokensResponse.Builder(); } @@ -97,6 +98,7 @@ public Builder tokensInfo(TokensInfo.Builder... tokensInfoBuilders) { } /** Deserializes a JSON string to a ComputeTokensResponse object. */ + @ExcludeFromGeneratedCoverageReport public static ComputeTokensResponse fromJson(String jsonString) { return JsonSerializable.fromJsonString(jsonString, ComputeTokensResponse.class); } diff --git a/src/main/java/com/google/genai/types/Content.java b/src/main/java/com/google/genai/types/Content.java index 3e6229cb1bf..a1148d9591d 100644 --- a/src/main/java/com/google/genai/types/Content.java +++ b/src/main/java/com/google/genai/types/Content.java @@ -51,6 +51,7 @@ public abstract class Content extends JsonSerializable { public abstract Optional role(); /** Instantiates a builder for Content. */ + @ExcludeFromGeneratedCoverageReport public static Builder builder() { return new AutoValue_Content.Builder(); } @@ -113,6 +114,7 @@ public Builder parts(Part.Builder... partsBuilders) { } /** Deserializes a JSON string to a Content object. */ + @ExcludeFromGeneratedCoverageReport public static Content fromJson(String jsonString) { return JsonSerializable.fromJsonString(jsonString, Content.class); } diff --git a/src/main/java/com/google/genai/types/ContentEmbedding.java b/src/main/java/com/google/genai/types/ContentEmbedding.java index 9dc43169795..be2bbd049c9 100644 --- a/src/main/java/com/google/genai/types/ContentEmbedding.java +++ b/src/main/java/com/google/genai/types/ContentEmbedding.java @@ -40,6 +40,7 @@ public abstract class ContentEmbedding extends JsonSerializable { public abstract Optional statistics(); /** Instantiates a builder for ContentEmbedding. */ + @ExcludeFromGeneratedCoverageReport public static Builder builder() { return new AutoValue_ContentEmbedding.Builder(); } @@ -94,6 +95,7 @@ public Builder statistics(ContentEmbeddingStatistics.Builder statisticsBuilder) } /** Deserializes a JSON string to a ContentEmbedding object. */ + @ExcludeFromGeneratedCoverageReport public static ContentEmbedding fromJson(String jsonString) { return JsonSerializable.fromJsonString(jsonString, ContentEmbedding.class); } diff --git a/src/main/java/com/google/genai/types/ContentEmbeddingStatistics.java b/src/main/java/com/google/genai/types/ContentEmbeddingStatistics.java index 32e37344c02..6440a3eb4dc 100644 --- a/src/main/java/com/google/genai/types/ContentEmbeddingStatistics.java +++ b/src/main/java/com/google/genai/types/ContentEmbeddingStatistics.java @@ -41,6 +41,7 @@ public abstract class ContentEmbeddingStatistics extends JsonSerializable { public abstract Optional tokenCount(); /** Instantiates a builder for ContentEmbeddingStatistics. */ + @ExcludeFromGeneratedCoverageReport public static Builder builder() { return new AutoValue_ContentEmbeddingStatistics.Builder(); } @@ -78,6 +79,7 @@ private static Builder create() { } /** Deserializes a JSON string to a ContentEmbeddingStatistics object. */ + @ExcludeFromGeneratedCoverageReport public static ContentEmbeddingStatistics fromJson(String jsonString) { return JsonSerializable.fromJsonString(jsonString, ContentEmbeddingStatistics.class); } diff --git a/src/main/java/com/google/genai/types/ContextWindowCompressionConfig.java b/src/main/java/com/google/genai/types/ContextWindowCompressionConfig.java index 0534b206b5a..594aaf57518 100644 --- a/src/main/java/com/google/genai/types/ContextWindowCompressionConfig.java +++ b/src/main/java/com/google/genai/types/ContextWindowCompressionConfig.java @@ -41,6 +41,7 @@ public abstract class ContextWindowCompressionConfig extends JsonSerializable { public abstract Optional slidingWindow(); /** Instantiates a builder for ContextWindowCompressionConfig. */ + @ExcludeFromGeneratedCoverageReport public static Builder builder() { return new AutoValue_ContextWindowCompressionConfig.Builder(); } @@ -89,6 +90,7 @@ public Builder slidingWindow(SlidingWindow.Builder slidingWindowBuilder) { } /** Deserializes a JSON string to a ContextWindowCompressionConfig object. */ + @ExcludeFromGeneratedCoverageReport public static ContextWindowCompressionConfig fromJson(String jsonString) { return JsonSerializable.fromJsonString(jsonString, ContextWindowCompressionConfig.class); } diff --git a/src/main/java/com/google/genai/types/ControlReferenceConfig.java b/src/main/java/com/google/genai/types/ControlReferenceConfig.java index 698999ca7c7..a8a00f545a7 100644 --- a/src/main/java/com/google/genai/types/ControlReferenceConfig.java +++ b/src/main/java/com/google/genai/types/ControlReferenceConfig.java @@ -42,6 +42,7 @@ public abstract class ControlReferenceConfig extends JsonSerializable { public abstract Optional enableControlImageComputation(); /** Instantiates a builder for ControlReferenceConfig. */ + @ExcludeFromGeneratedCoverageReport public static Builder builder() { return new AutoValue_ControlReferenceConfig.Builder(); } @@ -100,6 +101,7 @@ public Builder controlType(String controlType) { } /** Deserializes a JSON string to a ControlReferenceConfig object. */ + @ExcludeFromGeneratedCoverageReport public static ControlReferenceConfig fromJson(String jsonString) { return JsonSerializable.fromJsonString(jsonString, ControlReferenceConfig.class); } diff --git a/src/main/java/com/google/genai/types/ControlReferenceImage.java b/src/main/java/com/google/genai/types/ControlReferenceImage.java index 9d3cdb920c9..0471d171bf4 100644 --- a/src/main/java/com/google/genai/types/ControlReferenceImage.java +++ b/src/main/java/com/google/genai/types/ControlReferenceImage.java @@ -55,6 +55,7 @@ public abstract class ControlReferenceImage extends JsonSerializable implements public abstract Optional config(); /** Instantiates a builder for ControlReferenceImage. */ + @ExcludeFromGeneratedCoverageReport public static Builder builder() { return new AutoValue_ControlReferenceImage.Builder(); } @@ -125,6 +126,7 @@ public Builder config(ControlReferenceConfig.Builder configBuilder) { } /** Deserializes a JSON string to a ControlReferenceImage object. */ + @ExcludeFromGeneratedCoverageReport public static ControlReferenceImage fromJson(String jsonString) { return JsonSerializable.fromJsonString(jsonString, ControlReferenceImage.class); } diff --git a/src/main/java/com/google/genai/types/ControlReferenceType.java b/src/main/java/com/google/genai/types/ControlReferenceType.java index 6487868075f..ed0c86ebc53 100644 --- a/src/main/java/com/google/genai/types/ControlReferenceType.java +++ b/src/main/java/com/google/genai/types/ControlReferenceType.java @@ -61,12 +61,14 @@ public ControlReferenceType(Known knownValue) { this.value = knownValue.toString(); } + @ExcludeFromGeneratedCoverageReport @Override @JsonValue public String toString() { return this.value; } + @ExcludeFromGeneratedCoverageReport @SuppressWarnings("PatternMatchingInstanceof") @Override public boolean equals(Object o) { @@ -93,6 +95,7 @@ public boolean equals(Object o) { return false; } + @ExcludeFromGeneratedCoverageReport @Override public int hashCode() { if (this.controlReferenceTypeEnum != Known.CONTROL_REFERENCE_TYPE_UNSPECIFIED) { @@ -102,6 +105,7 @@ public int hashCode() { } } + @ExcludeFromGeneratedCoverageReport public Known knownEnum() { return this.controlReferenceTypeEnum; } diff --git a/src/main/java/com/google/genai/types/CountTokensConfig.java b/src/main/java/com/google/genai/types/CountTokensConfig.java index 2d24dce46d9..dab32e0f530 100644 --- a/src/main/java/com/google/genai/types/CountTokensConfig.java +++ b/src/main/java/com/google/genai/types/CountTokensConfig.java @@ -56,6 +56,7 @@ public abstract class CountTokensConfig extends JsonSerializable { public abstract Optional generationConfig(); /** Instantiates a builder for CountTokensConfig. */ + @ExcludeFromGeneratedCoverageReport public static Builder builder() { return new AutoValue_CountTokensConfig.Builder(); } @@ -161,6 +162,7 @@ public Builder generationConfig(GenerationConfig.Builder generationConfigBuilder } /** Deserializes a JSON string to a CountTokensConfig object. */ + @ExcludeFromGeneratedCoverageReport public static CountTokensConfig fromJson(String jsonString) { return JsonSerializable.fromJsonString(jsonString, CountTokensConfig.class); } diff --git a/src/main/java/com/google/genai/types/CountTokensParameters.java b/src/main/java/com/google/genai/types/CountTokensParameters.java index 896796e5718..d21e0591958 100644 --- a/src/main/java/com/google/genai/types/CountTokensParameters.java +++ b/src/main/java/com/google/genai/types/CountTokensParameters.java @@ -51,6 +51,7 @@ public abstract class CountTokensParameters extends JsonSerializable { public abstract Optional config(); /** Instantiates a builder for CountTokensParameters. */ + @ExcludeFromGeneratedCoverageReport public static Builder builder() { return new AutoValue_CountTokensParameters.Builder(); } @@ -126,6 +127,7 @@ public Builder config(CountTokensConfig.Builder configBuilder) { } /** Deserializes a JSON string to a CountTokensParameters object. */ + @ExcludeFromGeneratedCoverageReport public static CountTokensParameters fromJson(String jsonString) { return JsonSerializable.fromJsonString(jsonString, CountTokensParameters.class); } diff --git a/src/main/java/com/google/genai/types/CountTokensResponse.java b/src/main/java/com/google/genai/types/CountTokensResponse.java index 98c8c228844..a3418db99c2 100644 --- a/src/main/java/com/google/genai/types/CountTokensResponse.java +++ b/src/main/java/com/google/genai/types/CountTokensResponse.java @@ -38,6 +38,7 @@ public abstract class CountTokensResponse extends JsonSerializable { public abstract Optional cachedContentTokenCount(); /** Instantiates a builder for CountTokensResponse. */ + @ExcludeFromGeneratedCoverageReport public static Builder builder() { return new AutoValue_CountTokensResponse.Builder(); } @@ -75,6 +76,7 @@ private static Builder create() { } /** Deserializes a JSON string to a CountTokensResponse object. */ + @ExcludeFromGeneratedCoverageReport public static CountTokensResponse fromJson(String jsonString) { return JsonSerializable.fromJsonString(jsonString, CountTokensResponse.class); } diff --git a/src/main/java/com/google/genai/types/CreateAuthTokenConfig.java b/src/main/java/com/google/genai/types/CreateAuthTokenConfig.java index ec3e81c854c..5260501fb62 100644 --- a/src/main/java/com/google/genai/types/CreateAuthTokenConfig.java +++ b/src/main/java/com/google/genai/types/CreateAuthTokenConfig.java @@ -72,6 +72,7 @@ public abstract class CreateAuthTokenConfig extends JsonSerializable { public abstract Optional> lockAdditionalFields(); /** Instantiates a builder for CreateAuthTokenConfig. */ + @ExcludeFromGeneratedCoverageReport public static Builder builder() { return new AutoValue_CreateAuthTokenConfig.Builder(); } @@ -179,6 +180,7 @@ public Builder lockAdditionalFields(String... lockAdditionalFields) { } /** Deserializes a JSON string to a CreateAuthTokenConfig object. */ + @ExcludeFromGeneratedCoverageReport public static CreateAuthTokenConfig fromJson(String jsonString) { return JsonSerializable.fromJsonString(jsonString, CreateAuthTokenConfig.class); } diff --git a/src/main/java/com/google/genai/types/CreateBatchJobConfig.java b/src/main/java/com/google/genai/types/CreateBatchJobConfig.java index 505ecda5e47..5e8a1fcc141 100644 --- a/src/main/java/com/google/genai/types/CreateBatchJobConfig.java +++ b/src/main/java/com/google/genai/types/CreateBatchJobConfig.java @@ -45,6 +45,7 @@ public abstract class CreateBatchJobConfig extends JsonSerializable { public abstract Optional dest(); /** Instantiates a builder for CreateBatchJobConfig. */ + @ExcludeFromGeneratedCoverageReport public static Builder builder() { return new AutoValue_CreateBatchJobConfig.Builder(); } @@ -109,6 +110,7 @@ public Builder dest(BatchJobDestination.Builder destBuilder) { } /** Deserializes a JSON string to a CreateBatchJobConfig object. */ + @ExcludeFromGeneratedCoverageReport public static CreateBatchJobConfig fromJson(String jsonString) { return JsonSerializable.fromJsonString(jsonString, CreateBatchJobConfig.class); } diff --git a/src/main/java/com/google/genai/types/CreateBatchJobParameters.java b/src/main/java/com/google/genai/types/CreateBatchJobParameters.java index e5348a0a460..445213a1715 100644 --- a/src/main/java/com/google/genai/types/CreateBatchJobParameters.java +++ b/src/main/java/com/google/genai/types/CreateBatchJobParameters.java @@ -47,6 +47,7 @@ public abstract class CreateBatchJobParameters extends JsonSerializable { public abstract Optional config(); /** Instantiates a builder for CreateBatchJobParameters. */ + @ExcludeFromGeneratedCoverageReport public static Builder builder() { return new AutoValue_CreateBatchJobParameters.Builder(); } @@ -111,6 +112,7 @@ public Builder config(CreateBatchJobConfig.Builder configBuilder) { } /** Deserializes a JSON string to a CreateBatchJobParameters object. */ + @ExcludeFromGeneratedCoverageReport public static CreateBatchJobParameters fromJson(String jsonString) { return JsonSerializable.fromJsonString(jsonString, CreateBatchJobParameters.class); } diff --git a/src/main/java/com/google/genai/types/CreateCachedContentConfig.java b/src/main/java/com/google/genai/types/CreateCachedContentConfig.java index a161571e3b9..d766c78d906 100644 --- a/src/main/java/com/google/genai/types/CreateCachedContentConfig.java +++ b/src/main/java/com/google/genai/types/CreateCachedContentConfig.java @@ -84,6 +84,7 @@ public abstract class CreateCachedContentConfig extends JsonSerializable { public abstract Optional kmsKeyName(); /** Instantiates a builder for CreateCachedContentConfig. */ + @ExcludeFromGeneratedCoverageReport public static Builder builder() { return new AutoValue_CreateCachedContentConfig.Builder(); } @@ -252,6 +253,7 @@ public Builder toolConfig(ToolConfig.Builder toolConfigBuilder) { } /** Deserializes a JSON string to a CreateCachedContentConfig object. */ + @ExcludeFromGeneratedCoverageReport public static CreateCachedContentConfig fromJson(String jsonString) { return JsonSerializable.fromJsonString(jsonString, CreateCachedContentConfig.class); } diff --git a/src/main/java/com/google/genai/types/CreateCachedContentParameters.java b/src/main/java/com/google/genai/types/CreateCachedContentParameters.java index afa0b4bc86e..70ae0d868f9 100644 --- a/src/main/java/com/google/genai/types/CreateCachedContentParameters.java +++ b/src/main/java/com/google/genai/types/CreateCachedContentParameters.java @@ -40,6 +40,7 @@ public abstract class CreateCachedContentParameters extends JsonSerializable { public abstract Optional config(); /** Instantiates a builder for CreateCachedContentParameters. */ + @ExcludeFromGeneratedCoverageReport public static Builder builder() { return new AutoValue_CreateCachedContentParameters.Builder(); } @@ -87,6 +88,7 @@ public Builder config(CreateCachedContentConfig.Builder configBuilder) { } /** Deserializes a JSON string to a CreateCachedContentParameters object. */ + @ExcludeFromGeneratedCoverageReport public static CreateCachedContentParameters fromJson(String jsonString) { return JsonSerializable.fromJsonString(jsonString, CreateCachedContentParameters.class); } diff --git a/src/main/java/com/google/genai/types/CreateFileConfig.java b/src/main/java/com/google/genai/types/CreateFileConfig.java index 0202c9f4a7b..13b998624fb 100644 --- a/src/main/java/com/google/genai/types/CreateFileConfig.java +++ b/src/main/java/com/google/genai/types/CreateFileConfig.java @@ -38,6 +38,7 @@ public abstract class CreateFileConfig extends JsonSerializable { public abstract Optional shouldReturnHttpResponse(); /** Instantiates a builder for CreateFileConfig. */ + @ExcludeFromGeneratedCoverageReport public static Builder builder() { return new AutoValue_CreateFileConfig.Builder(); } @@ -84,6 +85,7 @@ public Builder httpOptions(HttpOptions.Builder httpOptionsBuilder) { } /** Deserializes a JSON string to a CreateFileConfig object. */ + @ExcludeFromGeneratedCoverageReport public static CreateFileConfig fromJson(String jsonString) { return JsonSerializable.fromJsonString(jsonString, CreateFileConfig.class); } diff --git a/src/main/java/com/google/genai/types/CreateFileParameters.java b/src/main/java/com/google/genai/types/CreateFileParameters.java index 027f2c05596..4e7c0202097 100644 --- a/src/main/java/com/google/genai/types/CreateFileParameters.java +++ b/src/main/java/com/google/genai/types/CreateFileParameters.java @@ -44,6 +44,7 @@ public abstract class CreateFileParameters extends JsonSerializable { public abstract Optional config(); /** Instantiates a builder for CreateFileParameters. */ + @ExcludeFromGeneratedCoverageReport public static Builder builder() { return new AutoValue_CreateFileParameters.Builder(); } @@ -102,6 +103,7 @@ public Builder config(CreateFileConfig.Builder configBuilder) { } /** Deserializes a JSON string to a CreateFileParameters object. */ + @ExcludeFromGeneratedCoverageReport public static CreateFileParameters fromJson(String jsonString) { return JsonSerializable.fromJsonString(jsonString, CreateFileParameters.class); } diff --git a/src/main/java/com/google/genai/types/CreateFileResponse.java b/src/main/java/com/google/genai/types/CreateFileResponse.java index f78b822fcbf..da9305682bd 100644 --- a/src/main/java/com/google/genai/types/CreateFileResponse.java +++ b/src/main/java/com/google/genai/types/CreateFileResponse.java @@ -34,6 +34,7 @@ public abstract class CreateFileResponse extends JsonSerializable { public abstract Optional sdkHttpResponse(); /** Instantiates a builder for CreateFileResponse. */ + @ExcludeFromGeneratedCoverageReport public static Builder builder() { return new AutoValue_CreateFileResponse.Builder(); } @@ -71,6 +72,7 @@ public Builder sdkHttpResponse(HttpResponse.Builder sdkHttpResponseBuilder) { } /** Deserializes a JSON string to a CreateFileResponse object. */ + @ExcludeFromGeneratedCoverageReport public static CreateFileResponse fromJson(String jsonString) { return JsonSerializable.fromJsonString(jsonString, CreateFileResponse.class); } diff --git a/src/main/java/com/google/genai/types/CreateTuningJobConfig.java b/src/main/java/com/google/genai/types/CreateTuningJobConfig.java index 151fcfd4a35..e725faeeecd 100644 --- a/src/main/java/com/google/genai/types/CreateTuningJobConfig.java +++ b/src/main/java/com/google/genai/types/CreateTuningJobConfig.java @@ -86,6 +86,7 @@ public abstract class CreateTuningJobConfig extends JsonSerializable { public abstract Optional learningRate(); /** Instantiates a builder for CreateTuningJobConfig. */ + @ExcludeFromGeneratedCoverageReport public static Builder builder() { return new AutoValue_CreateTuningJobConfig.Builder(); } @@ -232,6 +233,7 @@ public Builder adapterSize(String adapterSize) { } /** Deserializes a JSON string to a CreateTuningJobConfig object. */ + @ExcludeFromGeneratedCoverageReport public static CreateTuningJobConfig fromJson(String jsonString) { return JsonSerializable.fromJsonString(jsonString, CreateTuningJobConfig.class); } diff --git a/src/main/java/com/google/genai/types/CreateTuningJobParameters.java b/src/main/java/com/google/genai/types/CreateTuningJobParameters.java index cf438f7c2de..1e0d044c3ff 100644 --- a/src/main/java/com/google/genai/types/CreateTuningJobParameters.java +++ b/src/main/java/com/google/genai/types/CreateTuningJobParameters.java @@ -47,6 +47,7 @@ public abstract class CreateTuningJobParameters extends JsonSerializable { public abstract Optional config(); /** Instantiates a builder for CreateTuningJobParameters. */ + @ExcludeFromGeneratedCoverageReport public static Builder builder() { return new AutoValue_CreateTuningJobParameters.Builder(); } @@ -111,6 +112,7 @@ public Builder config(CreateTuningJobConfig.Builder configBuilder) { } /** Deserializes a JSON string to a CreateTuningJobParameters object. */ + @ExcludeFromGeneratedCoverageReport public static CreateTuningJobParameters fromJson(String jsonString) { return JsonSerializable.fromJsonString(jsonString, CreateTuningJobParameters.class); } diff --git a/src/main/java/com/google/genai/types/CreateTuningJobParametersPrivate.java b/src/main/java/com/google/genai/types/CreateTuningJobParametersPrivate.java index 8cb8b8275e3..0b7873ddf0f 100644 --- a/src/main/java/com/google/genai/types/CreateTuningJobParametersPrivate.java +++ b/src/main/java/com/google/genai/types/CreateTuningJobParametersPrivate.java @@ -47,6 +47,7 @@ public abstract class CreateTuningJobParametersPrivate extends JsonSerializable public abstract Optional config(); /** Instantiates a builder for CreateTuningJobParametersPrivate. */ + @ExcludeFromGeneratedCoverageReport public static Builder builder() { return new AutoValue_CreateTuningJobParametersPrivate.Builder(); } @@ -114,6 +115,7 @@ public Builder config(CreateTuningJobConfig.Builder configBuilder) { } /** Deserializes a JSON string to a CreateTuningJobParametersPrivate object. */ + @ExcludeFromGeneratedCoverageReport public static CreateTuningJobParametersPrivate fromJson(String jsonString) { return JsonSerializable.fromJsonString(jsonString, CreateTuningJobParametersPrivate.class); } diff --git a/src/main/java/com/google/genai/types/DatasetDistribution.java b/src/main/java/com/google/genai/types/DatasetDistribution.java index f70b89330ee..306a1781d6f 100644 --- a/src/main/java/com/google/genai/types/DatasetDistribution.java +++ b/src/main/java/com/google/genai/types/DatasetDistribution.java @@ -66,6 +66,7 @@ public abstract class DatasetDistribution extends JsonSerializable { public abstract Optional sum(); /** Instantiates a builder for DatasetDistribution. */ + @ExcludeFromGeneratedCoverageReport public static Builder builder() { return new AutoValue_DatasetDistribution.Builder(); } @@ -171,6 +172,7 @@ public Builder buckets(DatasetDistributionDistributionBucket.Builder... bucketsB } /** Deserializes a JSON string to a DatasetDistribution object. */ + @ExcludeFromGeneratedCoverageReport public static DatasetDistribution fromJson(String jsonString) { return JsonSerializable.fromJsonString(jsonString, DatasetDistribution.class); } diff --git a/src/main/java/com/google/genai/types/DatasetDistributionDistributionBucket.java b/src/main/java/com/google/genai/types/DatasetDistributionDistributionBucket.java index adf61aa69ce..2786e3ce05b 100644 --- a/src/main/java/com/google/genai/types/DatasetDistributionDistributionBucket.java +++ b/src/main/java/com/google/genai/types/DatasetDistributionDistributionBucket.java @@ -42,6 +42,7 @@ public abstract class DatasetDistributionDistributionBucket extends JsonSerializ public abstract Optional right(); /** Instantiates a builder for DatasetDistributionDistributionBucket. */ + @ExcludeFromGeneratedCoverageReport public static Builder builder() { return new AutoValue_DatasetDistributionDistributionBucket.Builder(); } @@ -89,6 +90,7 @@ private static Builder create() { } /** Deserializes a JSON string to a DatasetDistributionDistributionBucket object. */ + @ExcludeFromGeneratedCoverageReport public static DatasetDistributionDistributionBucket fromJson(String jsonString) { return JsonSerializable.fromJsonString(jsonString, DatasetDistributionDistributionBucket.class); } diff --git a/src/main/java/com/google/genai/types/DatasetStats.java b/src/main/java/com/google/genai/types/DatasetStats.java index dcc839becb7..e764568bc64 100644 --- a/src/main/java/com/google/genai/types/DatasetStats.java +++ b/src/main/java/com/google/genai/types/DatasetStats.java @@ -66,6 +66,7 @@ public abstract class DatasetStats extends JsonSerializable { public abstract Optional userOutputTokenDistribution(); /** Instantiates a builder for DatasetStats. */ + @ExcludeFromGeneratedCoverageReport public static Builder builder() { return new AutoValue_DatasetStats.Builder(); } @@ -209,6 +210,7 @@ public Builder userOutputTokenDistribution( } /** Deserializes a JSON string to a DatasetStats object. */ + @ExcludeFromGeneratedCoverageReport public static DatasetStats fromJson(String jsonString) { return JsonSerializable.fromJsonString(jsonString, DatasetStats.class); } diff --git a/src/main/java/com/google/genai/types/DeleteBatchJobConfig.java b/src/main/java/com/google/genai/types/DeleteBatchJobConfig.java index 638197ccef4..3717e3d14c6 100644 --- a/src/main/java/com/google/genai/types/DeleteBatchJobConfig.java +++ b/src/main/java/com/google/genai/types/DeleteBatchJobConfig.java @@ -34,6 +34,7 @@ public abstract class DeleteBatchJobConfig extends JsonSerializable { public abstract Optional httpOptions(); /** Instantiates a builder for DeleteBatchJobConfig. */ + @ExcludeFromGeneratedCoverageReport public static Builder builder() { return new AutoValue_DeleteBatchJobConfig.Builder(); } @@ -71,6 +72,7 @@ public Builder httpOptions(HttpOptions.Builder httpOptionsBuilder) { } /** Deserializes a JSON string to a DeleteBatchJobConfig object. */ + @ExcludeFromGeneratedCoverageReport public static DeleteBatchJobConfig fromJson(String jsonString) { return JsonSerializable.fromJsonString(jsonString, DeleteBatchJobConfig.class); } diff --git a/src/main/java/com/google/genai/types/DeleteBatchJobParameters.java b/src/main/java/com/google/genai/types/DeleteBatchJobParameters.java index 27807fea35a..c72c66bc6fd 100644 --- a/src/main/java/com/google/genai/types/DeleteBatchJobParameters.java +++ b/src/main/java/com/google/genai/types/DeleteBatchJobParameters.java @@ -44,6 +44,7 @@ public abstract class DeleteBatchJobParameters extends JsonSerializable { public abstract Optional config(); /** Instantiates a builder for DeleteBatchJobParameters. */ + @ExcludeFromGeneratedCoverageReport public static Builder builder() { return new AutoValue_DeleteBatchJobParameters.Builder(); } @@ -91,6 +92,7 @@ public Builder config(DeleteBatchJobConfig.Builder configBuilder) { } /** Deserializes a JSON string to a DeleteBatchJobParameters object. */ + @ExcludeFromGeneratedCoverageReport public static DeleteBatchJobParameters fromJson(String jsonString) { return JsonSerializable.fromJsonString(jsonString, DeleteBatchJobParameters.class); } diff --git a/src/main/java/com/google/genai/types/DeleteCachedContentConfig.java b/src/main/java/com/google/genai/types/DeleteCachedContentConfig.java index b30bd2724b8..9343df3f57b 100644 --- a/src/main/java/com/google/genai/types/DeleteCachedContentConfig.java +++ b/src/main/java/com/google/genai/types/DeleteCachedContentConfig.java @@ -34,6 +34,7 @@ public abstract class DeleteCachedContentConfig extends JsonSerializable { public abstract Optional httpOptions(); /** Instantiates a builder for DeleteCachedContentConfig. */ + @ExcludeFromGeneratedCoverageReport public static Builder builder() { return new AutoValue_DeleteCachedContentConfig.Builder(); } @@ -71,6 +72,7 @@ public Builder httpOptions(HttpOptions.Builder httpOptionsBuilder) { } /** Deserializes a JSON string to a DeleteCachedContentConfig object. */ + @ExcludeFromGeneratedCoverageReport public static DeleteCachedContentConfig fromJson(String jsonString) { return JsonSerializable.fromJsonString(jsonString, DeleteCachedContentConfig.class); } diff --git a/src/main/java/com/google/genai/types/DeleteCachedContentParameters.java b/src/main/java/com/google/genai/types/DeleteCachedContentParameters.java index ff4794ece9d..536d1ab11a3 100644 --- a/src/main/java/com/google/genai/types/DeleteCachedContentParameters.java +++ b/src/main/java/com/google/genai/types/DeleteCachedContentParameters.java @@ -40,6 +40,7 @@ public abstract class DeleteCachedContentParameters extends JsonSerializable { public abstract Optional config(); /** Instantiates a builder for DeleteCachedContentParameters. */ + @ExcludeFromGeneratedCoverageReport public static Builder builder() { return new AutoValue_DeleteCachedContentParameters.Builder(); } @@ -87,6 +88,7 @@ public Builder config(DeleteCachedContentConfig.Builder configBuilder) { } /** Deserializes a JSON string to a DeleteCachedContentParameters object. */ + @ExcludeFromGeneratedCoverageReport public static DeleteCachedContentParameters fromJson(String jsonString) { return JsonSerializable.fromJsonString(jsonString, DeleteCachedContentParameters.class); } diff --git a/src/main/java/com/google/genai/types/DeleteCachedContentResponse.java b/src/main/java/com/google/genai/types/DeleteCachedContentResponse.java index 339d4b6ef97..0b79785a5b9 100644 --- a/src/main/java/com/google/genai/types/DeleteCachedContentResponse.java +++ b/src/main/java/com/google/genai/types/DeleteCachedContentResponse.java @@ -28,6 +28,7 @@ @JsonDeserialize(builder = DeleteCachedContentResponse.Builder.class) public abstract class DeleteCachedContentResponse extends JsonSerializable { /** Instantiates a builder for DeleteCachedContentResponse. */ + @ExcludeFromGeneratedCoverageReport public static Builder builder() { return new AutoValue_DeleteCachedContentResponse.Builder(); } @@ -48,6 +49,7 @@ private static Builder create() { } /** Deserializes a JSON string to a DeleteCachedContentResponse object. */ + @ExcludeFromGeneratedCoverageReport public static DeleteCachedContentResponse fromJson(String jsonString) { return JsonSerializable.fromJsonString(jsonString, DeleteCachedContentResponse.class); } diff --git a/src/main/java/com/google/genai/types/DeleteFileConfig.java b/src/main/java/com/google/genai/types/DeleteFileConfig.java index 530b22e25ab..1059f2b3715 100644 --- a/src/main/java/com/google/genai/types/DeleteFileConfig.java +++ b/src/main/java/com/google/genai/types/DeleteFileConfig.java @@ -34,6 +34,7 @@ public abstract class DeleteFileConfig extends JsonSerializable { public abstract Optional httpOptions(); /** Instantiates a builder for DeleteFileConfig. */ + @ExcludeFromGeneratedCoverageReport public static Builder builder() { return new AutoValue_DeleteFileConfig.Builder(); } @@ -71,6 +72,7 @@ public Builder httpOptions(HttpOptions.Builder httpOptionsBuilder) { } /** Deserializes a JSON string to a DeleteFileConfig object. */ + @ExcludeFromGeneratedCoverageReport public static DeleteFileConfig fromJson(String jsonString) { return JsonSerializable.fromJsonString(jsonString, DeleteFileConfig.class); } diff --git a/src/main/java/com/google/genai/types/DeleteFileParameters.java b/src/main/java/com/google/genai/types/DeleteFileParameters.java index a4a18770a39..cb4d5ed6707 100644 --- a/src/main/java/com/google/genai/types/DeleteFileParameters.java +++ b/src/main/java/com/google/genai/types/DeleteFileParameters.java @@ -40,6 +40,7 @@ public abstract class DeleteFileParameters extends JsonSerializable { public abstract Optional config(); /** Instantiates a builder for DeleteFileParameters. */ + @ExcludeFromGeneratedCoverageReport public static Builder builder() { return new AutoValue_DeleteFileParameters.Builder(); } @@ -85,6 +86,7 @@ public Builder config(DeleteFileConfig.Builder configBuilder) { } /** Deserializes a JSON string to a DeleteFileParameters object. */ + @ExcludeFromGeneratedCoverageReport public static DeleteFileParameters fromJson(String jsonString) { return JsonSerializable.fromJsonString(jsonString, DeleteFileParameters.class); } diff --git a/src/main/java/com/google/genai/types/DeleteFileResponse.java b/src/main/java/com/google/genai/types/DeleteFileResponse.java index c1b34814310..fa9e59f97a8 100644 --- a/src/main/java/com/google/genai/types/DeleteFileResponse.java +++ b/src/main/java/com/google/genai/types/DeleteFileResponse.java @@ -28,6 +28,7 @@ @JsonDeserialize(builder = DeleteFileResponse.Builder.class) public abstract class DeleteFileResponse extends JsonSerializable { /** Instantiates a builder for DeleteFileResponse. */ + @ExcludeFromGeneratedCoverageReport public static Builder builder() { return new AutoValue_DeleteFileResponse.Builder(); } @@ -48,6 +49,7 @@ private static Builder create() { } /** Deserializes a JSON string to a DeleteFileResponse object. */ + @ExcludeFromGeneratedCoverageReport public static DeleteFileResponse fromJson(String jsonString) { return JsonSerializable.fromJsonString(jsonString, DeleteFileResponse.class); } diff --git a/src/main/java/com/google/genai/types/DeleteModelConfig.java b/src/main/java/com/google/genai/types/DeleteModelConfig.java index cc1b8543833..04f9528dde1 100644 --- a/src/main/java/com/google/genai/types/DeleteModelConfig.java +++ b/src/main/java/com/google/genai/types/DeleteModelConfig.java @@ -34,6 +34,7 @@ public abstract class DeleteModelConfig extends JsonSerializable { public abstract Optional httpOptions(); /** Instantiates a builder for DeleteModelConfig. */ + @ExcludeFromGeneratedCoverageReport public static Builder builder() { return new AutoValue_DeleteModelConfig.Builder(); } @@ -71,6 +72,7 @@ public Builder httpOptions(HttpOptions.Builder httpOptionsBuilder) { } /** Deserializes a JSON string to a DeleteModelConfig object. */ + @ExcludeFromGeneratedCoverageReport public static DeleteModelConfig fromJson(String jsonString) { return JsonSerializable.fromJsonString(jsonString, DeleteModelConfig.class); } diff --git a/src/main/java/com/google/genai/types/DeleteModelParameters.java b/src/main/java/com/google/genai/types/DeleteModelParameters.java index 383e43ea7f5..8e5d9a7e143 100644 --- a/src/main/java/com/google/genai/types/DeleteModelParameters.java +++ b/src/main/java/com/google/genai/types/DeleteModelParameters.java @@ -40,6 +40,7 @@ public abstract class DeleteModelParameters extends JsonSerializable { public abstract Optional config(); /** Instantiates a builder for DeleteModelParameters. */ + @ExcludeFromGeneratedCoverageReport public static Builder builder() { return new AutoValue_DeleteModelParameters.Builder(); } @@ -85,6 +86,7 @@ public Builder config(DeleteModelConfig.Builder configBuilder) { } /** Deserializes a JSON string to a DeleteModelParameters object. */ + @ExcludeFromGeneratedCoverageReport public static DeleteModelParameters fromJson(String jsonString) { return JsonSerializable.fromJsonString(jsonString, DeleteModelParameters.class); } diff --git a/src/main/java/com/google/genai/types/DeleteModelResponse.java b/src/main/java/com/google/genai/types/DeleteModelResponse.java index 5a7d3c90794..24fdacd0eee 100644 --- a/src/main/java/com/google/genai/types/DeleteModelResponse.java +++ b/src/main/java/com/google/genai/types/DeleteModelResponse.java @@ -28,6 +28,7 @@ @JsonDeserialize(builder = DeleteModelResponse.Builder.class) public abstract class DeleteModelResponse extends JsonSerializable { /** Instantiates a builder for DeleteModelResponse. */ + @ExcludeFromGeneratedCoverageReport public static Builder builder() { return new AutoValue_DeleteModelResponse.Builder(); } @@ -48,6 +49,7 @@ private static Builder create() { } /** Deserializes a JSON string to a DeleteModelResponse object. */ + @ExcludeFromGeneratedCoverageReport public static DeleteModelResponse fromJson(String jsonString) { return JsonSerializable.fromJsonString(jsonString, DeleteModelResponse.class); } diff --git a/src/main/java/com/google/genai/types/DeleteResourceJob.java b/src/main/java/com/google/genai/types/DeleteResourceJob.java index e3bc5e40fc9..e2b2989bf16 100644 --- a/src/main/java/com/google/genai/types/DeleteResourceJob.java +++ b/src/main/java/com/google/genai/types/DeleteResourceJob.java @@ -42,6 +42,7 @@ public abstract class DeleteResourceJob extends JsonSerializable { public abstract Optional error(); /** Instantiates a builder for DeleteResourceJob. */ + @ExcludeFromGeneratedCoverageReport public static Builder builder() { return new AutoValue_DeleteResourceJob.Builder(); } @@ -95,6 +96,7 @@ public Builder error(JobError.Builder errorBuilder) { } /** Deserializes a JSON string to a DeleteResourceJob object. */ + @ExcludeFromGeneratedCoverageReport public static DeleteResourceJob fromJson(String jsonString) { return JsonSerializable.fromJsonString(jsonString, DeleteResourceJob.class); } diff --git a/src/main/java/com/google/genai/types/DistillationDataStats.java b/src/main/java/com/google/genai/types/DistillationDataStats.java index 68c608529f5..862afd5be4b 100644 --- a/src/main/java/com/google/genai/types/DistillationDataStats.java +++ b/src/main/java/com/google/genai/types/DistillationDataStats.java @@ -34,6 +34,7 @@ public abstract class DistillationDataStats extends JsonSerializable { public abstract Optional trainingDatasetStats(); /** Instantiates a builder for DistillationDataStats. */ + @ExcludeFromGeneratedCoverageReport public static Builder builder() { return new AutoValue_DistillationDataStats.Builder(); } @@ -71,6 +72,7 @@ public Builder trainingDatasetStats(DatasetStats.Builder trainingDatasetStatsBui } /** Deserializes a JSON string to a DistillationDataStats object. */ + @ExcludeFromGeneratedCoverageReport public static DistillationDataStats fromJson(String jsonString) { return JsonSerializable.fromJsonString(jsonString, DistillationDataStats.class); } diff --git a/src/main/java/com/google/genai/types/DistillationHyperParameters.java b/src/main/java/com/google/genai/types/DistillationHyperParameters.java index be717feef84..d05bc8372ca 100644 --- a/src/main/java/com/google/genai/types/DistillationHyperParameters.java +++ b/src/main/java/com/google/genai/types/DistillationHyperParameters.java @@ -48,6 +48,7 @@ public abstract class DistillationHyperParameters extends JsonSerializable { public abstract Optional learningRateMultiplier(); /** Instantiates a builder for DistillationHyperParameters. */ + @ExcludeFromGeneratedCoverageReport public static Builder builder() { return new AutoValue_DistillationHyperParameters.Builder(); } @@ -113,6 +114,7 @@ public Builder adapterSize(String adapterSize) { } /** Deserializes a JSON string to a DistillationHyperParameters object. */ + @ExcludeFromGeneratedCoverageReport public static DistillationHyperParameters fromJson(String jsonString) { return JsonSerializable.fromJsonString(jsonString, DistillationHyperParameters.class); } diff --git a/src/main/java/com/google/genai/types/DistillationSpec.java b/src/main/java/com/google/genai/types/DistillationSpec.java index 638b6450620..474e61332b1 100644 --- a/src/main/java/com/google/genai/types/DistillationSpec.java +++ b/src/main/java/com/google/genai/types/DistillationSpec.java @@ -77,6 +77,7 @@ public abstract class DistillationSpec extends JsonSerializable { public abstract Optional validationDatasetUri(); /** Instantiates a builder for DistillationSpec. */ + @ExcludeFromGeneratedCoverageReport public static Builder builder() { return new AutoValue_DistillationSpec.Builder(); } @@ -169,6 +170,7 @@ public Builder hyperParameters(DistillationHyperParameters.Builder hyperParamete } /** Deserializes a JSON string to a DistillationSpec object. */ + @ExcludeFromGeneratedCoverageReport public static DistillationSpec fromJson(String jsonString) { return JsonSerializable.fromJsonString(jsonString, DistillationSpec.class); } diff --git a/src/main/java/com/google/genai/types/DownloadFileConfig.java b/src/main/java/com/google/genai/types/DownloadFileConfig.java index ec8e6aa6ccd..2a23c62a0e1 100644 --- a/src/main/java/com/google/genai/types/DownloadFileConfig.java +++ b/src/main/java/com/google/genai/types/DownloadFileConfig.java @@ -34,6 +34,7 @@ public abstract class DownloadFileConfig extends JsonSerializable { public abstract Optional httpOptions(); /** Instantiates a builder for DownloadFileConfig. */ + @ExcludeFromGeneratedCoverageReport public static Builder builder() { return new AutoValue_DownloadFileConfig.Builder(); } @@ -71,6 +72,7 @@ public Builder httpOptions(HttpOptions.Builder httpOptionsBuilder) { } /** Deserializes a JSON string to a DownloadFileConfig object. */ + @ExcludeFromGeneratedCoverageReport public static DownloadFileConfig fromJson(String jsonString) { return JsonSerializable.fromJsonString(jsonString, DownloadFileConfig.class); } diff --git a/src/main/java/com/google/genai/types/DynamicRetrievalConfig.java b/src/main/java/com/google/genai/types/DynamicRetrievalConfig.java index efc4f87949d..97089b82cce 100644 --- a/src/main/java/com/google/genai/types/DynamicRetrievalConfig.java +++ b/src/main/java/com/google/genai/types/DynamicRetrievalConfig.java @@ -42,6 +42,7 @@ public abstract class DynamicRetrievalConfig extends JsonSerializable { public abstract Optional dynamicThreshold(); /** Instantiates a builder for DynamicRetrievalConfig. */ + @ExcludeFromGeneratedCoverageReport public static Builder builder() { return new AutoValue_DynamicRetrievalConfig.Builder(); } @@ -99,6 +100,7 @@ public Builder mode(String mode) { } /** Deserializes a JSON string to a DynamicRetrievalConfig object. */ + @ExcludeFromGeneratedCoverageReport public static DynamicRetrievalConfig fromJson(String jsonString) { return JsonSerializable.fromJsonString(jsonString, DynamicRetrievalConfig.class); } diff --git a/src/main/java/com/google/genai/types/DynamicRetrievalConfigMode.java b/src/main/java/com/google/genai/types/DynamicRetrievalConfigMode.java index 0af252eea2f..515b5ff89af 100644 --- a/src/main/java/com/google/genai/types/DynamicRetrievalConfigMode.java +++ b/src/main/java/com/google/genai/types/DynamicRetrievalConfigMode.java @@ -59,12 +59,14 @@ public DynamicRetrievalConfigMode(Known knownValue) { this.value = knownValue.toString(); } + @ExcludeFromGeneratedCoverageReport @Override @JsonValue public String toString() { return this.value; } + @ExcludeFromGeneratedCoverageReport @SuppressWarnings("PatternMatchingInstanceof") @Override public boolean equals(Object o) { @@ -94,6 +96,7 @@ public boolean equals(Object o) { return false; } + @ExcludeFromGeneratedCoverageReport @Override public int hashCode() { if (this.dynamicRetrievalConfigModeEnum != Known.DYNAMIC_RETRIEVAL_CONFIG_MODE_UNSPECIFIED) { @@ -103,6 +106,7 @@ public int hashCode() { } } + @ExcludeFromGeneratedCoverageReport public Known knownEnum() { return this.dynamicRetrievalConfigModeEnum; } diff --git a/src/main/java/com/google/genai/types/EditImageConfig.java b/src/main/java/com/google/genai/types/EditImageConfig.java index 0f0c7f6e539..35211fd1dd2 100644 --- a/src/main/java/com/google/genai/types/EditImageConfig.java +++ b/src/main/java/com/google/genai/types/EditImageConfig.java @@ -116,6 +116,7 @@ public abstract class EditImageConfig extends JsonSerializable { public abstract Optional baseSteps(); /** Instantiates a builder for EditImageConfig. */ + @ExcludeFromGeneratedCoverageReport public static Builder builder() { return new AutoValue_EditImageConfig.Builder(); } @@ -368,6 +369,7 @@ public Builder editMode(String editMode) { } /** Deserializes a JSON string to a EditImageConfig object. */ + @ExcludeFromGeneratedCoverageReport public static EditImageConfig fromJson(String jsonString) { return JsonSerializable.fromJsonString(jsonString, EditImageConfig.class); } diff --git a/src/main/java/com/google/genai/types/EditImageParameters.java b/src/main/java/com/google/genai/types/EditImageParameters.java index df0568abec0..e47f69e6b56 100644 --- a/src/main/java/com/google/genai/types/EditImageParameters.java +++ b/src/main/java/com/google/genai/types/EditImageParameters.java @@ -50,6 +50,7 @@ public abstract class EditImageParameters extends JsonSerializable { public abstract Optional config(); /** Instantiates a builder for EditImageParameters. */ + @ExcludeFromGeneratedCoverageReport public static Builder builder() { return new AutoValue_EditImageParameters.Builder(); } @@ -120,6 +121,7 @@ public Builder config(EditImageConfig.Builder configBuilder) { } /** Deserializes a JSON string to a EditImageParameters object. */ + @ExcludeFromGeneratedCoverageReport public static EditImageParameters fromJson(String jsonString) { return JsonSerializable.fromJsonString(jsonString, EditImageParameters.class); } diff --git a/src/main/java/com/google/genai/types/EditImageResponse.java b/src/main/java/com/google/genai/types/EditImageResponse.java index 7aee310938b..d39df0a9d53 100644 --- a/src/main/java/com/google/genai/types/EditImageResponse.java +++ b/src/main/java/com/google/genai/types/EditImageResponse.java @@ -38,6 +38,7 @@ public abstract class EditImageResponse extends JsonSerializable { public abstract Optional> generatedImages(); /** Instantiates a builder for EditImageResponse. */ + @ExcludeFromGeneratedCoverageReport public static Builder builder() { return new AutoValue_EditImageResponse.Builder(); } @@ -87,6 +88,7 @@ public Builder generatedImages(GeneratedImage.Builder... generatedImagesBuilders } /** Deserializes a JSON string to a EditImageResponse object. */ + @ExcludeFromGeneratedCoverageReport public static EditImageResponse fromJson(String jsonString) { return JsonSerializable.fromJsonString(jsonString, EditImageResponse.class); } diff --git a/src/main/java/com/google/genai/types/EditMode.java b/src/main/java/com/google/genai/types/EditMode.java index 1e7d6fb70f7..7258c3b4799 100644 --- a/src/main/java/com/google/genai/types/EditMode.java +++ b/src/main/java/com/google/genai/types/EditMode.java @@ -69,12 +69,14 @@ public EditMode(Known knownValue) { this.value = knownValue.toString(); } + @ExcludeFromGeneratedCoverageReport @Override @JsonValue public String toString() { return this.value; } + @ExcludeFromGeneratedCoverageReport @SuppressWarnings("PatternMatchingInstanceof") @Override public boolean equals(Object o) { @@ -101,6 +103,7 @@ public boolean equals(Object o) { return false; } + @ExcludeFromGeneratedCoverageReport @Override public int hashCode() { if (this.editModeEnum != Known.EDIT_MODE_UNSPECIFIED) { @@ -110,6 +113,7 @@ public int hashCode() { } } + @ExcludeFromGeneratedCoverageReport public Known knownEnum() { return this.editModeEnum; } diff --git a/src/main/java/com/google/genai/types/EmbedContentConfig.java b/src/main/java/com/google/genai/types/EmbedContentConfig.java index ccef31e056f..88bc9c824c6 100644 --- a/src/main/java/com/google/genai/types/EmbedContentConfig.java +++ b/src/main/java/com/google/genai/types/EmbedContentConfig.java @@ -62,6 +62,7 @@ public abstract class EmbedContentConfig extends JsonSerializable { public abstract Optional autoTruncate(); /** Instantiates a builder for EmbedContentConfig. */ + @ExcludeFromGeneratedCoverageReport public static Builder builder() { return new AutoValue_EmbedContentConfig.Builder(); } @@ -143,6 +144,7 @@ public Builder httpOptions(HttpOptions.Builder httpOptionsBuilder) { } /** Deserializes a JSON string to a EmbedContentConfig object. */ + @ExcludeFromGeneratedCoverageReport public static EmbedContentConfig fromJson(String jsonString) { return JsonSerializable.fromJsonString(jsonString, EmbedContentConfig.class); } diff --git a/src/main/java/com/google/genai/types/EmbedContentMetadata.java b/src/main/java/com/google/genai/types/EmbedContentMetadata.java index 816bb9d11c4..baadebbdb88 100644 --- a/src/main/java/com/google/genai/types/EmbedContentMetadata.java +++ b/src/main/java/com/google/genai/types/EmbedContentMetadata.java @@ -34,6 +34,7 @@ public abstract class EmbedContentMetadata extends JsonSerializable { public abstract Optional billableCharacterCount(); /** Instantiates a builder for EmbedContentMetadata. */ + @ExcludeFromGeneratedCoverageReport public static Builder builder() { return new AutoValue_EmbedContentMetadata.Builder(); } @@ -63,6 +64,7 @@ private static Builder create() { } /** Deserializes a JSON string to a EmbedContentMetadata object. */ + @ExcludeFromGeneratedCoverageReport public static EmbedContentMetadata fromJson(String jsonString) { return JsonSerializable.fromJsonString(jsonString, EmbedContentMetadata.class); } diff --git a/src/main/java/com/google/genai/types/EmbedContentParameters.java b/src/main/java/com/google/genai/types/EmbedContentParameters.java index 4ae02be1959..6a52239f7dc 100644 --- a/src/main/java/com/google/genai/types/EmbedContentParameters.java +++ b/src/main/java/com/google/genai/types/EmbedContentParameters.java @@ -51,6 +51,7 @@ public abstract class EmbedContentParameters extends JsonSerializable { public abstract Optional config(); /** Instantiates a builder for EmbedContentParameters. */ + @ExcludeFromGeneratedCoverageReport public static Builder builder() { return new AutoValue_EmbedContentParameters.Builder(); } @@ -126,6 +127,7 @@ public Builder config(EmbedContentConfig.Builder configBuilder) { } /** Deserializes a JSON string to a EmbedContentParameters object. */ + @ExcludeFromGeneratedCoverageReport public static EmbedContentParameters fromJson(String jsonString) { return JsonSerializable.fromJsonString(jsonString, EmbedContentParameters.class); } diff --git a/src/main/java/com/google/genai/types/EmbedContentResponse.java b/src/main/java/com/google/genai/types/EmbedContentResponse.java index 2f35dd4a307..7dee6c06ade 100644 --- a/src/main/java/com/google/genai/types/EmbedContentResponse.java +++ b/src/main/java/com/google/genai/types/EmbedContentResponse.java @@ -42,6 +42,7 @@ public abstract class EmbedContentResponse extends JsonSerializable { public abstract Optional metadata(); /** Instantiates a builder for EmbedContentResponse. */ + @ExcludeFromGeneratedCoverageReport public static Builder builder() { return new AutoValue_EmbedContentResponse.Builder(); } @@ -111,6 +112,7 @@ public Builder metadata(EmbedContentMetadata.Builder metadataBuilder) { } /** Deserializes a JSON string to a EmbedContentResponse object. */ + @ExcludeFromGeneratedCoverageReport public static EmbedContentResponse fromJson(String jsonString) { return JsonSerializable.fromJsonString(jsonString, EmbedContentResponse.class); } diff --git a/src/main/java/com/google/genai/types/EncryptionSpec.java b/src/main/java/com/google/genai/types/EncryptionSpec.java index ea39c7c341a..80b5dfd5352 100644 --- a/src/main/java/com/google/genai/types/EncryptionSpec.java +++ b/src/main/java/com/google/genai/types/EncryptionSpec.java @@ -41,6 +41,7 @@ public abstract class EncryptionSpec extends JsonSerializable { public abstract Optional kmsKeyName(); /** Instantiates a builder for EncryptionSpec. */ + @ExcludeFromGeneratedCoverageReport public static Builder builder() { return new AutoValue_EncryptionSpec.Builder(); } @@ -72,6 +73,7 @@ private static Builder create() { } /** Deserializes a JSON string to a EncryptionSpec object. */ + @ExcludeFromGeneratedCoverageReport public static EncryptionSpec fromJson(String jsonString) { return JsonSerializable.fromJsonString(jsonString, EncryptionSpec.class); } diff --git a/src/main/java/com/google/genai/types/EndSensitivity.java b/src/main/java/com/google/genai/types/EndSensitivity.java index 35641b466bb..3cf231dba11 100644 --- a/src/main/java/com/google/genai/types/EndSensitivity.java +++ b/src/main/java/com/google/genai/types/EndSensitivity.java @@ -60,12 +60,14 @@ public EndSensitivity(Known knownValue) { this.value = knownValue.toString(); } + @ExcludeFromGeneratedCoverageReport @Override @JsonValue public String toString() { return this.value; } + @ExcludeFromGeneratedCoverageReport @SuppressWarnings("PatternMatchingInstanceof") @Override public boolean equals(Object o) { @@ -92,6 +94,7 @@ public boolean equals(Object o) { return false; } + @ExcludeFromGeneratedCoverageReport @Override public int hashCode() { if (this.endSensitivityEnum != Known.END_SENSITIVITY_UNSPECIFIED) { @@ -101,6 +104,7 @@ public int hashCode() { } } + @ExcludeFromGeneratedCoverageReport public Known knownEnum() { return this.endSensitivityEnum; } diff --git a/src/main/java/com/google/genai/types/Endpoint.java b/src/main/java/com/google/genai/types/Endpoint.java index 85a19fb8a39..78d1991b5c3 100644 --- a/src/main/java/com/google/genai/types/Endpoint.java +++ b/src/main/java/com/google/genai/types/Endpoint.java @@ -38,6 +38,7 @@ public abstract class Endpoint extends JsonSerializable { public abstract Optional deployedModelId(); /** Instantiates a builder for Endpoint. */ + @ExcludeFromGeneratedCoverageReport public static Builder builder() { return new AutoValue_Endpoint.Builder(); } @@ -74,6 +75,7 @@ private static Builder create() { } /** Deserializes a JSON string to a Endpoint object. */ + @ExcludeFromGeneratedCoverageReport public static Endpoint fromJson(String jsonString) { return JsonSerializable.fromJsonString(jsonString, Endpoint.class); } diff --git a/src/main/java/com/google/genai/types/EnterpriseWebSearch.java b/src/main/java/com/google/genai/types/EnterpriseWebSearch.java index 29543cfc27f..d0f698cba56 100644 --- a/src/main/java/com/google/genai/types/EnterpriseWebSearch.java +++ b/src/main/java/com/google/genai/types/EnterpriseWebSearch.java @@ -28,6 +28,7 @@ @JsonDeserialize(builder = EnterpriseWebSearch.Builder.class) public abstract class EnterpriseWebSearch extends JsonSerializable { /** Instantiates a builder for EnterpriseWebSearch. */ + @ExcludeFromGeneratedCoverageReport public static Builder builder() { return new AutoValue_EnterpriseWebSearch.Builder(); } @@ -48,6 +49,7 @@ private static Builder create() { } /** Deserializes a JSON string to a EnterpriseWebSearch object. */ + @ExcludeFromGeneratedCoverageReport public static EnterpriseWebSearch fromJson(String jsonString) { return JsonSerializable.fromJsonString(jsonString, EnterpriseWebSearch.class); } diff --git a/src/main/java/com/google/genai/types/Environment.java b/src/main/java/com/google/genai/types/Environment.java index 4347d593cfd..6708ae60499 100644 --- a/src/main/java/com/google/genai/types/Environment.java +++ b/src/main/java/com/google/genai/types/Environment.java @@ -57,12 +57,14 @@ public Environment(Known knownValue) { this.value = knownValue.toString(); } + @ExcludeFromGeneratedCoverageReport @Override @JsonValue public String toString() { return this.value; } + @ExcludeFromGeneratedCoverageReport @SuppressWarnings("PatternMatchingInstanceof") @Override public boolean equals(Object o) { @@ -89,6 +91,7 @@ public boolean equals(Object o) { return false; } + @ExcludeFromGeneratedCoverageReport @Override public int hashCode() { if (this.environmentEnum != Known.ENVIRONMENT_UNSPECIFIED) { @@ -98,6 +101,7 @@ public int hashCode() { } } + @ExcludeFromGeneratedCoverageReport public Known knownEnum() { return this.environmentEnum; } diff --git a/src/main/java/com/google/genai/types/ExcludeFromGeneratedCoverageReport.java b/src/main/java/com/google/genai/types/ExcludeFromGeneratedCoverageReport.java new file mode 100644 index 00000000000..73d98f6f869 --- /dev/null +++ b/src/main/java/com/google/genai/types/ExcludeFromGeneratedCoverageReport.java @@ -0,0 +1,31 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.genai.types; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Annotation to exclude a method or constructor from the Jacoco coverage report. + * + *

    Jacoco will exclude methods that have an annotation with the word "generated" in it. + */ +@Retention(RetentionPolicy.CLASS) +@Target({ElementType.METHOD, ElementType.CONSTRUCTOR, ElementType.TYPE}) +@interface ExcludeFromGeneratedCoverageReport {} diff --git a/src/main/java/com/google/genai/types/ExecutableCode.java b/src/main/java/com/google/genai/types/ExecutableCode.java index 96779f55a4b..f017751d847 100644 --- a/src/main/java/com/google/genai/types/ExecutableCode.java +++ b/src/main/java/com/google/genai/types/ExecutableCode.java @@ -43,6 +43,7 @@ public abstract class ExecutableCode extends JsonSerializable { public abstract Optional language(); /** Instantiates a builder for ExecutableCode. */ + @ExcludeFromGeneratedCoverageReport public static Builder builder() { return new AutoValue_ExecutableCode.Builder(); } @@ -99,6 +100,7 @@ public Builder language(String language) { } /** Deserializes a JSON string to a ExecutableCode object. */ + @ExcludeFromGeneratedCoverageReport public static ExecutableCode fromJson(String jsonString) { return JsonSerializable.fromJsonString(jsonString, ExecutableCode.class); } diff --git a/src/main/java/com/google/genai/types/ExternalApi.java b/src/main/java/com/google/genai/types/ExternalApi.java index 69a7ecb26e8..7ff8cbc5104 100644 --- a/src/main/java/com/google/genai/types/ExternalApi.java +++ b/src/main/java/com/google/genai/types/ExternalApi.java @@ -61,6 +61,7 @@ public abstract class ExternalApi extends JsonSerializable { public abstract Optional simpleSearchParams(); /** Instantiates a builder for ExternalApi. */ + @ExcludeFromGeneratedCoverageReport public static Builder builder() { return new AutoValue_ExternalApi.Builder(); } @@ -190,6 +191,7 @@ public Builder simpleSearchParams( } /** Deserializes a JSON string to a ExternalApi object. */ + @ExcludeFromGeneratedCoverageReport public static ExternalApi fromJson(String jsonString) { return JsonSerializable.fromJsonString(jsonString, ExternalApi.class); } diff --git a/src/main/java/com/google/genai/types/ExternalApiElasticSearchParams.java b/src/main/java/com/google/genai/types/ExternalApiElasticSearchParams.java index 5ec0a623ec5..5d04d103b42 100644 --- a/src/main/java/com/google/genai/types/ExternalApiElasticSearchParams.java +++ b/src/main/java/com/google/genai/types/ExternalApiElasticSearchParams.java @@ -45,6 +45,7 @@ public abstract class ExternalApiElasticSearchParams extends JsonSerializable { public abstract Optional searchTemplate(); /** Instantiates a builder for ExternalApiElasticSearchParams. */ + @ExcludeFromGeneratedCoverageReport public static Builder builder() { return new AutoValue_ExternalApiElasticSearchParams.Builder(); } @@ -92,6 +93,7 @@ private static Builder create() { } /** Deserializes a JSON string to a ExternalApiElasticSearchParams object. */ + @ExcludeFromGeneratedCoverageReport public static ExternalApiElasticSearchParams fromJson(String jsonString) { return JsonSerializable.fromJsonString(jsonString, ExternalApiElasticSearchParams.class); } diff --git a/src/main/java/com/google/genai/types/ExternalApiSimpleSearchParams.java b/src/main/java/com/google/genai/types/ExternalApiSimpleSearchParams.java index 39314fe765f..d32068994a3 100644 --- a/src/main/java/com/google/genai/types/ExternalApiSimpleSearchParams.java +++ b/src/main/java/com/google/genai/types/ExternalApiSimpleSearchParams.java @@ -28,6 +28,7 @@ @JsonDeserialize(builder = ExternalApiSimpleSearchParams.Builder.class) public abstract class ExternalApiSimpleSearchParams extends JsonSerializable { /** Instantiates a builder for ExternalApiSimpleSearchParams. */ + @ExcludeFromGeneratedCoverageReport public static Builder builder() { return new AutoValue_ExternalApiSimpleSearchParams.Builder(); } @@ -50,6 +51,7 @@ private static Builder create() { } /** Deserializes a JSON string to a ExternalApiSimpleSearchParams object. */ + @ExcludeFromGeneratedCoverageReport public static ExternalApiSimpleSearchParams fromJson(String jsonString) { return JsonSerializable.fromJsonString(jsonString, ExternalApiSimpleSearchParams.class); } diff --git a/src/main/java/com/google/genai/types/FeatureSelectionPreference.java b/src/main/java/com/google/genai/types/FeatureSelectionPreference.java index 5a1815d0128..7976dff966d 100644 --- a/src/main/java/com/google/genai/types/FeatureSelectionPreference.java +++ b/src/main/java/com/google/genai/types/FeatureSelectionPreference.java @@ -59,12 +59,14 @@ public FeatureSelectionPreference(Known knownValue) { this.value = knownValue.toString(); } + @ExcludeFromGeneratedCoverageReport @Override @JsonValue public String toString() { return this.value; } + @ExcludeFromGeneratedCoverageReport @SuppressWarnings("PatternMatchingInstanceof") @Override public boolean equals(Object o) { @@ -91,6 +93,7 @@ public boolean equals(Object o) { return false; } + @ExcludeFromGeneratedCoverageReport @Override public int hashCode() { if (this.featureSelectionPreferenceEnum != Known.FEATURE_SELECTION_PREFERENCE_UNSPECIFIED) { @@ -100,6 +103,7 @@ public int hashCode() { } } + @ExcludeFromGeneratedCoverageReport public Known knownEnum() { return this.featureSelectionPreferenceEnum; } diff --git a/src/main/java/com/google/genai/types/FetchPredictOperationConfig.java b/src/main/java/com/google/genai/types/FetchPredictOperationConfig.java index 006f2f9489f..f8ea69c8315 100644 --- a/src/main/java/com/google/genai/types/FetchPredictOperationConfig.java +++ b/src/main/java/com/google/genai/types/FetchPredictOperationConfig.java @@ -34,6 +34,7 @@ public abstract class FetchPredictOperationConfig extends JsonSerializable { public abstract Optional httpOptions(); /** Instantiates a builder for FetchPredictOperationConfig. */ + @ExcludeFromGeneratedCoverageReport public static Builder builder() { return new AutoValue_FetchPredictOperationConfig.Builder(); } @@ -71,6 +72,7 @@ public Builder httpOptions(HttpOptions.Builder httpOptionsBuilder) { } /** Deserializes a JSON string to a FetchPredictOperationConfig object. */ + @ExcludeFromGeneratedCoverageReport public static FetchPredictOperationConfig fromJson(String jsonString) { return JsonSerializable.fromJsonString(jsonString, FetchPredictOperationConfig.class); } diff --git a/src/main/java/com/google/genai/types/FetchPredictOperationParameters.java b/src/main/java/com/google/genai/types/FetchPredictOperationParameters.java index 4a3eae13eae..acb9eb36b59 100644 --- a/src/main/java/com/google/genai/types/FetchPredictOperationParameters.java +++ b/src/main/java/com/google/genai/types/FetchPredictOperationParameters.java @@ -44,6 +44,7 @@ public abstract class FetchPredictOperationParameters extends JsonSerializable { public abstract Optional config(); /** Instantiates a builder for FetchPredictOperationParameters. */ + @ExcludeFromGeneratedCoverageReport public static Builder builder() { return new AutoValue_FetchPredictOperationParameters.Builder(); } @@ -99,6 +100,7 @@ public Builder config(FetchPredictOperationConfig.Builder configBuilder) { } /** Deserializes a JSON string to a FetchPredictOperationParameters object. */ + @ExcludeFromGeneratedCoverageReport public static FetchPredictOperationParameters fromJson(String jsonString) { return JsonSerializable.fromJsonString(jsonString, FetchPredictOperationParameters.class); } diff --git a/src/main/java/com/google/genai/types/File.java b/src/main/java/com/google/genai/types/File.java index 34ecb1e76d9..bbf979d72c2 100644 --- a/src/main/java/com/google/genai/types/File.java +++ b/src/main/java/com/google/genai/types/File.java @@ -101,6 +101,7 @@ public abstract class File extends JsonSerializable { public abstract Optional error(); /** Instantiates a builder for File. */ + @ExcludeFromGeneratedCoverageReport public static Builder builder() { return new AutoValue_File.Builder(); } @@ -289,6 +290,7 @@ public Builder error(FileStatus.Builder errorBuilder) { } /** Deserializes a JSON string to a File object. */ + @ExcludeFromGeneratedCoverageReport public static File fromJson(String jsonString) { return JsonSerializable.fromJsonString(jsonString, File.class); } diff --git a/src/main/java/com/google/genai/types/FileData.java b/src/main/java/com/google/genai/types/FileData.java index d36aa3b8157..4f059ef957c 100644 --- a/src/main/java/com/google/genai/types/FileData.java +++ b/src/main/java/com/google/genai/types/FileData.java @@ -45,6 +45,7 @@ public abstract class FileData extends JsonSerializable { public abstract Optional mimeType(); /** Instantiates a builder for FileData. */ + @ExcludeFromGeneratedCoverageReport public static Builder builder() { return new AutoValue_FileData.Builder(); } @@ -90,6 +91,7 @@ private static Builder create() { } /** Deserializes a JSON string to a FileData object. */ + @ExcludeFromGeneratedCoverageReport public static FileData fromJson(String jsonString) { return JsonSerializable.fromJsonString(jsonString, FileData.class); } diff --git a/src/main/java/com/google/genai/types/FileSource.java b/src/main/java/com/google/genai/types/FileSource.java index fa360c5fda9..1763c1c4d78 100644 --- a/src/main/java/com/google/genai/types/FileSource.java +++ b/src/main/java/com/google/genai/types/FileSource.java @@ -59,12 +59,14 @@ public FileSource(Known knownValue) { this.value = knownValue.toString(); } + @ExcludeFromGeneratedCoverageReport @Override @JsonValue public String toString() { return this.value; } + @ExcludeFromGeneratedCoverageReport @SuppressWarnings("PatternMatchingInstanceof") @Override public boolean equals(Object o) { @@ -91,6 +93,7 @@ public boolean equals(Object o) { return false; } + @ExcludeFromGeneratedCoverageReport @Override public int hashCode() { if (this.fileSourceEnum != Known.FILE_SOURCE_UNSPECIFIED) { @@ -100,6 +103,7 @@ public int hashCode() { } } + @ExcludeFromGeneratedCoverageReport public Known knownEnum() { return this.fileSourceEnum; } diff --git a/src/main/java/com/google/genai/types/FileState.java b/src/main/java/com/google/genai/types/FileState.java index a4f74872b85..af9e2ae68f7 100644 --- a/src/main/java/com/google/genai/types/FileState.java +++ b/src/main/java/com/google/genai/types/FileState.java @@ -61,12 +61,14 @@ public FileState(Known knownValue) { this.value = knownValue.toString(); } + @ExcludeFromGeneratedCoverageReport @Override @JsonValue public String toString() { return this.value; } + @ExcludeFromGeneratedCoverageReport @SuppressWarnings("PatternMatchingInstanceof") @Override public boolean equals(Object o) { @@ -93,6 +95,7 @@ public boolean equals(Object o) { return false; } + @ExcludeFromGeneratedCoverageReport @Override public int hashCode() { if (this.fileStateEnum != Known.FILE_STATE_UNSPECIFIED) { @@ -102,6 +105,7 @@ public int hashCode() { } } + @ExcludeFromGeneratedCoverageReport public Known knownEnum() { return this.fileStateEnum; } diff --git a/src/main/java/com/google/genai/types/FileStatus.java b/src/main/java/com/google/genai/types/FileStatus.java index 5c69faa3292..d3c190a2b50 100644 --- a/src/main/java/com/google/genai/types/FileStatus.java +++ b/src/main/java/com/google/genai/types/FileStatus.java @@ -51,6 +51,7 @@ public abstract class FileStatus extends JsonSerializable { public abstract Optional code(); /** Instantiates a builder for FileStatus. */ + @ExcludeFromGeneratedCoverageReport public static Builder builder() { return new AutoValue_FileStatus.Builder(); } @@ -107,6 +108,7 @@ public Builder details(Map... details) { } /** Deserializes a JSON string to a FileStatus object. */ + @ExcludeFromGeneratedCoverageReport public static FileStatus fromJson(String jsonString) { return JsonSerializable.fromJsonString(jsonString, FileStatus.class); } diff --git a/src/main/java/com/google/genai/types/FinishReason.java b/src/main/java/com/google/genai/types/FinishReason.java index 6df7ea34964..219d350c374 100644 --- a/src/main/java/com/google/genai/types/FinishReason.java +++ b/src/main/java/com/google/genai/types/FinishReason.java @@ -100,12 +100,14 @@ public FinishReason(Known knownValue) { this.value = knownValue.toString(); } + @ExcludeFromGeneratedCoverageReport @Override @JsonValue public String toString() { return this.value; } + @ExcludeFromGeneratedCoverageReport @SuppressWarnings("PatternMatchingInstanceof") @Override public boolean equals(Object o) { @@ -132,6 +134,7 @@ public boolean equals(Object o) { return false; } + @ExcludeFromGeneratedCoverageReport @Override public int hashCode() { if (this.finishReasonEnum != Known.FINISH_REASON_UNSPECIFIED) { @@ -141,6 +144,7 @@ public int hashCode() { } } + @ExcludeFromGeneratedCoverageReport public Known knownEnum() { return this.finishReasonEnum; } diff --git a/src/main/java/com/google/genai/types/FunctionCall.java b/src/main/java/com/google/genai/types/FunctionCall.java index ca0a88af924..ebadb56c076 100644 --- a/src/main/java/com/google/genai/types/FunctionCall.java +++ b/src/main/java/com/google/genai/types/FunctionCall.java @@ -49,6 +49,7 @@ public abstract class FunctionCall extends JsonSerializable { public abstract Optional name(); /** Instantiates a builder for FunctionCall. */ + @ExcludeFromGeneratedCoverageReport public static Builder builder() { return new AutoValue_FunctionCall.Builder(); } @@ -95,6 +96,7 @@ private static Builder create() { } /** Deserializes a JSON string to a FunctionCall object. */ + @ExcludeFromGeneratedCoverageReport public static FunctionCall fromJson(String jsonString) { return JsonSerializable.fromJsonString(jsonString, FunctionCall.class); } diff --git a/src/main/java/com/google/genai/types/FunctionCallingConfig.java b/src/main/java/com/google/genai/types/FunctionCallingConfig.java index cd64b08f89d..5d280e4642a 100644 --- a/src/main/java/com/google/genai/types/FunctionCallingConfig.java +++ b/src/main/java/com/google/genai/types/FunctionCallingConfig.java @@ -45,6 +45,7 @@ public abstract class FunctionCallingConfig extends JsonSerializable { public abstract Optional> allowedFunctionNames(); /** Instantiates a builder for FunctionCallingConfig. */ + @ExcludeFromGeneratedCoverageReport public static Builder builder() { return new AutoValue_FunctionCallingConfig.Builder(); } @@ -114,6 +115,7 @@ public Builder allowedFunctionNames(String... allowedFunctionNames) { } /** Deserializes a JSON string to a FunctionCallingConfig object. */ + @ExcludeFromGeneratedCoverageReport public static FunctionCallingConfig fromJson(String jsonString) { return JsonSerializable.fromJsonString(jsonString, FunctionCallingConfig.class); } diff --git a/src/main/java/com/google/genai/types/FunctionCallingConfigMode.java b/src/main/java/com/google/genai/types/FunctionCallingConfigMode.java index 6d6ff9c675d..2ca721a3df3 100644 --- a/src/main/java/com/google/genai/types/FunctionCallingConfigMode.java +++ b/src/main/java/com/google/genai/types/FunctionCallingConfigMode.java @@ -75,12 +75,14 @@ public FunctionCallingConfigMode(Known knownValue) { this.value = knownValue.toString(); } + @ExcludeFromGeneratedCoverageReport @Override @JsonValue public String toString() { return this.value; } + @ExcludeFromGeneratedCoverageReport @SuppressWarnings("PatternMatchingInstanceof") @Override public boolean equals(Object o) { @@ -107,6 +109,7 @@ public boolean equals(Object o) { return false; } + @ExcludeFromGeneratedCoverageReport @Override public int hashCode() { if (this.functionCallingConfigModeEnum != Known.FUNCTION_CALLING_CONFIG_MODE_UNSPECIFIED) { @@ -116,6 +119,7 @@ public int hashCode() { } } + @ExcludeFromGeneratedCoverageReport public Known knownEnum() { return this.functionCallingConfigModeEnum; } diff --git a/src/main/java/com/google/genai/types/FunctionDeclaration.java b/src/main/java/com/google/genai/types/FunctionDeclaration.java index 7e02cc508ea..78801843a0f 100644 --- a/src/main/java/com/google/genai/types/FunctionDeclaration.java +++ b/src/main/java/com/google/genai/types/FunctionDeclaration.java @@ -97,6 +97,7 @@ public abstract class FunctionDeclaration extends JsonSerializable { public abstract Optional responseJsonSchema(); /** Instantiates a builder for FunctionDeclaration. */ + @ExcludeFromGeneratedCoverageReport public static Builder builder() { return new AutoValue_FunctionDeclaration.Builder(); } @@ -236,6 +237,7 @@ public Builder response(Schema.Builder responseBuilder) { } /** Deserializes a JSON string to a FunctionDeclaration object. */ + @ExcludeFromGeneratedCoverageReport public static FunctionDeclaration fromJson(String jsonString) { return JsonSerializable.fromJsonString(jsonString, FunctionDeclaration.class); } diff --git a/src/main/java/com/google/genai/types/FunctionResponse.java b/src/main/java/com/google/genai/types/FunctionResponse.java index a3cdc1ecdea..50d14349d8d 100644 --- a/src/main/java/com/google/genai/types/FunctionResponse.java +++ b/src/main/java/com/google/genai/types/FunctionResponse.java @@ -72,6 +72,7 @@ public abstract class FunctionResponse extends JsonSerializable { public abstract Optional> response(); /** Instantiates a builder for FunctionResponse. */ + @ExcludeFromGeneratedCoverageReport public static Builder builder() { return new AutoValue_FunctionResponse.Builder(); } @@ -165,6 +166,7 @@ public Builder scheduling(String scheduling) { } /** Deserializes a JSON string to a FunctionResponse object. */ + @ExcludeFromGeneratedCoverageReport public static FunctionResponse fromJson(String jsonString) { return JsonSerializable.fromJsonString(jsonString, FunctionResponse.class); } diff --git a/src/main/java/com/google/genai/types/FunctionResponseScheduling.java b/src/main/java/com/google/genai/types/FunctionResponseScheduling.java index 527afa0a418..cd22370f049 100644 --- a/src/main/java/com/google/genai/types/FunctionResponseScheduling.java +++ b/src/main/java/com/google/genai/types/FunctionResponseScheduling.java @@ -71,12 +71,14 @@ public FunctionResponseScheduling(Known knownValue) { this.value = knownValue.toString(); } + @ExcludeFromGeneratedCoverageReport @Override @JsonValue public String toString() { return this.value; } + @ExcludeFromGeneratedCoverageReport @SuppressWarnings("PatternMatchingInstanceof") @Override public boolean equals(Object o) { @@ -103,6 +105,7 @@ public boolean equals(Object o) { return false; } + @ExcludeFromGeneratedCoverageReport @Override public int hashCode() { if (this.functionResponseSchedulingEnum != Known.FUNCTION_RESPONSE_SCHEDULING_UNSPECIFIED) { @@ -112,6 +115,7 @@ public int hashCode() { } } + @ExcludeFromGeneratedCoverageReport public Known knownEnum() { return this.functionResponseSchedulingEnum; } diff --git a/src/main/java/com/google/genai/types/GeminiPreferenceExample.java b/src/main/java/com/google/genai/types/GeminiPreferenceExample.java index 53d5e2cbd7c..9ebec609555 100644 --- a/src/main/java/com/google/genai/types/GeminiPreferenceExample.java +++ b/src/main/java/com/google/genai/types/GeminiPreferenceExample.java @@ -42,6 +42,7 @@ public abstract class GeminiPreferenceExample extends JsonSerializable { public abstract Optional> contents(); /** Instantiates a builder for GeminiPreferenceExample. */ + @ExcludeFromGeneratedCoverageReport public static Builder builder() { return new AutoValue_GeminiPreferenceExample.Builder(); } @@ -120,6 +121,7 @@ public Builder contents(Content.Builder... contentsBuilders) { } /** Deserializes a JSON string to a GeminiPreferenceExample object. */ + @ExcludeFromGeneratedCoverageReport public static GeminiPreferenceExample fromJson(String jsonString) { return JsonSerializable.fromJsonString(jsonString, GeminiPreferenceExample.class); } diff --git a/src/main/java/com/google/genai/types/GeminiPreferenceExampleCompletion.java b/src/main/java/com/google/genai/types/GeminiPreferenceExampleCompletion.java index 6f3ba60cd4e..5039fac18ca 100644 --- a/src/main/java/com/google/genai/types/GeminiPreferenceExampleCompletion.java +++ b/src/main/java/com/google/genai/types/GeminiPreferenceExampleCompletion.java @@ -38,6 +38,7 @@ public abstract class GeminiPreferenceExampleCompletion extends JsonSerializable public abstract Optional score(); /** Instantiates a builder for GeminiPreferenceExampleCompletion. */ + @ExcludeFromGeneratedCoverageReport public static Builder builder() { return new AutoValue_GeminiPreferenceExampleCompletion.Builder(); } @@ -86,6 +87,7 @@ public Builder completion(Content.Builder completionBuilder) { } /** Deserializes a JSON string to a GeminiPreferenceExampleCompletion object. */ + @ExcludeFromGeneratedCoverageReport public static GeminiPreferenceExampleCompletion fromJson(String jsonString) { return JsonSerializable.fromJsonString(jsonString, GeminiPreferenceExampleCompletion.class); } diff --git a/src/main/java/com/google/genai/types/GenerateContentConfig.java b/src/main/java/com/google/genai/types/GenerateContentConfig.java index ed28f450e84..5be0eb0dc16 100644 --- a/src/main/java/com/google/genai/types/GenerateContentConfig.java +++ b/src/main/java/com/google/genai/types/GenerateContentConfig.java @@ -216,6 +216,7 @@ public abstract class GenerateContentConfig extends JsonSerializable { public abstract Optional thinkingConfig(); /** Instantiates a builder for GenerateContentConfig. */ + @ExcludeFromGeneratedCoverageReport public static Builder builder() { return new AutoValue_GenerateContentConfig.Builder(); } @@ -674,6 +675,7 @@ public Builder thinkingConfig(ThinkingConfig.Builder thinkingConfigBuilder) { } /** Deserializes a JSON string to a GenerateContentConfig object. */ + @ExcludeFromGeneratedCoverageReport public static GenerateContentConfig fromJson(String jsonString) { return JsonSerializable.fromJsonString(jsonString, GenerateContentConfig.class); } diff --git a/src/main/java/com/google/genai/types/GenerateContentParameters.java b/src/main/java/com/google/genai/types/GenerateContentParameters.java index 43f2ca07ed5..be550b56b61 100644 --- a/src/main/java/com/google/genai/types/GenerateContentParameters.java +++ b/src/main/java/com/google/genai/types/GenerateContentParameters.java @@ -51,6 +51,7 @@ public abstract class GenerateContentParameters extends JsonSerializable { public abstract Optional config(); /** Instantiates a builder for GenerateContentParameters. */ + @ExcludeFromGeneratedCoverageReport public static Builder builder() { return new AutoValue_GenerateContentParameters.Builder(); } @@ -126,6 +127,7 @@ public Builder config(GenerateContentConfig.Builder configBuilder) { } /** Deserializes a JSON string to a GenerateContentParameters object. */ + @ExcludeFromGeneratedCoverageReport public static GenerateContentParameters fromJson(String jsonString) { return JsonSerializable.fromJsonString(jsonString, GenerateContentParameters.class); } diff --git a/src/main/java/com/google/genai/types/GenerateContentResponse.java b/src/main/java/com/google/genai/types/GenerateContentResponse.java index 946fda87597..33603df317b 100644 --- a/src/main/java/com/google/genai/types/GenerateContentResponse.java +++ b/src/main/java/com/google/genai/types/GenerateContentResponse.java @@ -79,6 +79,7 @@ public abstract class GenerateContentResponse extends JsonSerializable { public abstract Optional usageMetadata(); /** Instantiates a builder for GenerateContentResponse. */ + @ExcludeFromGeneratedCoverageReport public static Builder builder() { return new AutoValue_GenerateContentResponse.Builder(); } @@ -241,6 +242,7 @@ public Builder usageMetadata( } /** Deserializes a JSON string to a GenerateContentResponse object. */ + @ExcludeFromGeneratedCoverageReport public static GenerateContentResponse fromJson(String jsonString) { return JsonSerializable.fromJsonString(jsonString, GenerateContentResponse.class); } diff --git a/src/main/java/com/google/genai/types/GenerateContentResponsePromptFeedback.java b/src/main/java/com/google/genai/types/GenerateContentResponsePromptFeedback.java index 08be365950f..775e6eae374 100644 --- a/src/main/java/com/google/genai/types/GenerateContentResponsePromptFeedback.java +++ b/src/main/java/com/google/genai/types/GenerateContentResponsePromptFeedback.java @@ -47,6 +47,7 @@ public abstract class GenerateContentResponsePromptFeedback extends JsonSerializ public abstract Optional> safetyRatings(); /** Instantiates a builder for GenerateContentResponsePromptFeedback. */ + @ExcludeFromGeneratedCoverageReport public static Builder builder() { return new AutoValue_GenerateContentResponsePromptFeedback.Builder(); } @@ -135,6 +136,7 @@ public Builder safetyRatings(SafetyRating.Builder... safetyRatingsBuilders) { } /** Deserializes a JSON string to a GenerateContentResponsePromptFeedback object. */ + @ExcludeFromGeneratedCoverageReport public static GenerateContentResponsePromptFeedback fromJson(String jsonString) { return JsonSerializable.fromJsonString(jsonString, GenerateContentResponsePromptFeedback.class); } diff --git a/src/main/java/com/google/genai/types/GenerateContentResponseUsageMetadata.java b/src/main/java/com/google/genai/types/GenerateContentResponseUsageMetadata.java index a268283e132..8d6c25a711d 100644 --- a/src/main/java/com/google/genai/types/GenerateContentResponseUsageMetadata.java +++ b/src/main/java/com/google/genai/types/GenerateContentResponseUsageMetadata.java @@ -85,6 +85,7 @@ public abstract class GenerateContentResponseUsageMetadata extends JsonSerializa public abstract Optional trafficType(); /** Instantiates a builder for GenerateContentResponseUsageMetadata. */ + @ExcludeFromGeneratedCoverageReport public static Builder builder() { return new AutoValue_GenerateContentResponseUsageMetadata.Builder(); } @@ -323,6 +324,7 @@ public Builder trafficType(String trafficType) { } /** Deserializes a JSON string to a GenerateContentResponseUsageMetadata object. */ + @ExcludeFromGeneratedCoverageReport public static GenerateContentResponseUsageMetadata fromJson(String jsonString) { return JsonSerializable.fromJsonString(jsonString, GenerateContentResponseUsageMetadata.class); } diff --git a/src/main/java/com/google/genai/types/GenerateImagesConfig.java b/src/main/java/com/google/genai/types/GenerateImagesConfig.java index eda36d1880c..84ea7f680a1 100644 --- a/src/main/java/com/google/genai/types/GenerateImagesConfig.java +++ b/src/main/java/com/google/genai/types/GenerateImagesConfig.java @@ -116,6 +116,7 @@ public abstract class GenerateImagesConfig extends JsonSerializable { public abstract Optional enhancePrompt(); /** Instantiates a builder for GenerateImagesConfig. */ + @ExcludeFromGeneratedCoverageReport public static Builder builder() { return new AutoValue_GenerateImagesConfig.Builder(); } @@ -348,6 +349,7 @@ public Builder language(String language) { } /** Deserializes a JSON string to a GenerateImagesConfig object. */ + @ExcludeFromGeneratedCoverageReport public static GenerateImagesConfig fromJson(String jsonString) { return JsonSerializable.fromJsonString(jsonString, GenerateImagesConfig.class); } diff --git a/src/main/java/com/google/genai/types/GenerateImagesParameters.java b/src/main/java/com/google/genai/types/GenerateImagesParameters.java index 4810d5c730e..80fef944455 100644 --- a/src/main/java/com/google/genai/types/GenerateImagesParameters.java +++ b/src/main/java/com/google/genai/types/GenerateImagesParameters.java @@ -47,6 +47,7 @@ public abstract class GenerateImagesParameters extends JsonSerializable { public abstract Optional config(); /** Instantiates a builder for GenerateImagesParameters. */ + @ExcludeFromGeneratedCoverageReport public static Builder builder() { return new AutoValue_GenerateImagesParameters.Builder(); } @@ -101,6 +102,7 @@ public Builder config(GenerateImagesConfig.Builder configBuilder) { } /** Deserializes a JSON string to a GenerateImagesParameters object. */ + @ExcludeFromGeneratedCoverageReport public static GenerateImagesParameters fromJson(String jsonString) { return JsonSerializable.fromJsonString(jsonString, GenerateImagesParameters.class); } diff --git a/src/main/java/com/google/genai/types/GenerateImagesResponse.java b/src/main/java/com/google/genai/types/GenerateImagesResponse.java index 0cb23e2888e..24a3fa89f98 100644 --- a/src/main/java/com/google/genai/types/GenerateImagesResponse.java +++ b/src/main/java/com/google/genai/types/GenerateImagesResponse.java @@ -45,6 +45,7 @@ public abstract class GenerateImagesResponse extends JsonSerializable { public abstract Optional positivePromptSafetyAttributes(); /** Instantiates a builder for GenerateImagesResponse. */ + @ExcludeFromGeneratedCoverageReport public static Builder builder() { return new AutoValue_GenerateImagesResponse.Builder(); } @@ -115,6 +116,7 @@ public Builder positivePromptSafetyAttributes( } /** Deserializes a JSON string to a GenerateImagesResponse object. */ + @ExcludeFromGeneratedCoverageReport public static GenerateImagesResponse fromJson(String jsonString) { return JsonSerializable.fromJsonString(jsonString, GenerateImagesResponse.class); } diff --git a/src/main/java/com/google/genai/types/GenerateVideosConfig.java b/src/main/java/com/google/genai/types/GenerateVideosConfig.java index 950d8416889..9231c66402d 100644 --- a/src/main/java/com/google/genai/types/GenerateVideosConfig.java +++ b/src/main/java/com/google/genai/types/GenerateVideosConfig.java @@ -106,6 +106,7 @@ public abstract class GenerateVideosConfig extends JsonSerializable { public abstract Optional compressionQuality(); /** Instantiates a builder for GenerateVideosConfig. */ + @ExcludeFromGeneratedCoverageReport public static Builder builder() { return new AutoValue_GenerateVideosConfig.Builder(); } @@ -291,6 +292,7 @@ public Builder compressionQuality(String compressionQuality) { } /** Deserializes a JSON string to a GenerateVideosConfig object. */ + @ExcludeFromGeneratedCoverageReport public static GenerateVideosConfig fromJson(String jsonString) { return JsonSerializable.fromJsonString(jsonString, GenerateVideosConfig.class); } diff --git a/src/main/java/com/google/genai/types/GenerateVideosOperation.java b/src/main/java/com/google/genai/types/GenerateVideosOperation.java index c042c79a6fe..8e8d7980379 100644 --- a/src/main/java/com/google/genai/types/GenerateVideosOperation.java +++ b/src/main/java/com/google/genai/types/GenerateVideosOperation.java @@ -63,6 +63,7 @@ public abstract class GenerateVideosOperation extends JsonSerializable { public abstract Optional response(); /** Instantiates a builder for GenerateVideosOperation. */ + @ExcludeFromGeneratedCoverageReport public static Builder builder() { return new AutoValue_GenerateVideosOperation.Builder(); } @@ -138,6 +139,7 @@ public Builder response(GenerateVideosResponse.Builder responseBuilder) { } /** Deserializes a JSON string to a GenerateVideosOperation object. */ + @ExcludeFromGeneratedCoverageReport public static GenerateVideosOperation fromJson(String jsonString) { return JsonSerializable.fromJsonString(jsonString, GenerateVideosOperation.class); } diff --git a/src/main/java/com/google/genai/types/GenerateVideosParameters.java b/src/main/java/com/google/genai/types/GenerateVideosParameters.java index 3382b826425..e68ed1e6124 100644 --- a/src/main/java/com/google/genai/types/GenerateVideosParameters.java +++ b/src/main/java/com/google/genai/types/GenerateVideosParameters.java @@ -55,6 +55,7 @@ public abstract class GenerateVideosParameters extends JsonSerializable { public abstract Optional config(); /** Instantiates a builder for GenerateVideosParameters. */ + @ExcludeFromGeneratedCoverageReport public static Builder builder() { return new AutoValue_GenerateVideosParameters.Builder(); } @@ -145,6 +146,7 @@ public Builder config(GenerateVideosConfig.Builder configBuilder) { } /** Deserializes a JSON string to a GenerateVideosParameters object. */ + @ExcludeFromGeneratedCoverageReport public static GenerateVideosParameters fromJson(String jsonString) { return JsonSerializable.fromJsonString(jsonString, GenerateVideosParameters.class); } diff --git a/src/main/java/com/google/genai/types/GenerateVideosResponse.java b/src/main/java/com/google/genai/types/GenerateVideosResponse.java index 69027d743da..258ed0a7603 100644 --- a/src/main/java/com/google/genai/types/GenerateVideosResponse.java +++ b/src/main/java/com/google/genai/types/GenerateVideosResponse.java @@ -46,6 +46,7 @@ public abstract class GenerateVideosResponse extends JsonSerializable { public abstract Optional> raiMediaFilteredReasons(); /** Instantiates a builder for GenerateVideosResponse. */ + @ExcludeFromGeneratedCoverageReport public static Builder builder() { return new AutoValue_GenerateVideosResponse.Builder(); } @@ -120,6 +121,7 @@ public Builder raiMediaFilteredReasons(String... raiMediaFilteredReasons) { } /** Deserializes a JSON string to a GenerateVideosResponse object. */ + @ExcludeFromGeneratedCoverageReport public static GenerateVideosResponse fromJson(String jsonString) { return JsonSerializable.fromJsonString(jsonString, GenerateVideosResponse.class); } diff --git a/src/main/java/com/google/genai/types/GeneratedImage.java b/src/main/java/com/google/genai/types/GeneratedImage.java index bef81420d64..07ac595b010 100644 --- a/src/main/java/com/google/genai/types/GeneratedImage.java +++ b/src/main/java/com/google/genai/types/GeneratedImage.java @@ -46,6 +46,7 @@ public abstract class GeneratedImage extends JsonSerializable { public abstract Optional enhancedPrompt(); /** Instantiates a builder for GeneratedImage. */ + @ExcludeFromGeneratedCoverageReport public static Builder builder() { return new AutoValue_GeneratedImage.Builder(); } @@ -120,6 +121,7 @@ public Builder safetyAttributes(SafetyAttributes.Builder safetyAttributesBuilder } /** Deserializes a JSON string to a GeneratedImage object. */ + @ExcludeFromGeneratedCoverageReport public static GeneratedImage fromJson(String jsonString) { return JsonSerializable.fromJsonString(jsonString, GeneratedImage.class); } diff --git a/src/main/java/com/google/genai/types/GeneratedVideo.java b/src/main/java/com/google/genai/types/GeneratedVideo.java index 467d15efc77..ce45662c3d1 100644 --- a/src/main/java/com/google/genai/types/GeneratedVideo.java +++ b/src/main/java/com/google/genai/types/GeneratedVideo.java @@ -34,6 +34,7 @@ public abstract class GeneratedVideo extends JsonSerializable { public abstract Optional

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%0DvjOFjFP!c4#oHhL@cZj>&T1a1 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