;
@@ -734,7 +731,7 @@ import java.util.ArrayList;
public class EditImage {
public static void main(String[] args) {
- Client client = Client.builder().enterprise(true).build();
+ Client client = Client.builder().vertexAI(true).build();
Image image = Image.fromFile("path/to/your/image");
@@ -975,57 +972,6 @@ public final class FileOperations {
}
```
-### Interactions (Experimental)
-
-The `interactions` service provides access to experimental features.
-
-> [!WARNING]
-> This service is experimental and subject to change or removal in future releases.
-
-You can access it via the client:
-```java
-client.interactions
-```
-or asynchronously:
-```java
-client.async.interactions
-```
-
-### Example: Create Interaction
-
-This example demonstrates creating a simple model interaction.
-
-```java
-import com.google.genai.Client;
-import com.google.genai.interactions.models.interactions.Content;
-import com.google.genai.interactions.models.interactions.CreateModelInteractionParams;
-import com.google.genai.interactions.models.interactions.Interaction;
-import com.google.genai.interactions.models.interactions.Model;
-
-Client client = new Client();
-
-CreateModelInteractionParams params =
- CreateModelInteractionParams.builder()
- .input("Why is the sky blue?")
- .model(Model.GEMINI_2_5_FLASH)
- .build();
-
-Interaction interaction = client.interactions.create(params);
-
-System.out.println("Interaction ID: " + interaction.id());
-System.out.println("Status: " + interaction.status());
-
-// Print the text outputs from the interaction.
-interaction.outputs().ifPresent(outputs -> {
- for (Content output : outputs) {
- output.text().ifPresent(text -> System.out.println("Output: " + text.text()));
- }
-});
-```
-
-For more examples, see `interactions*` in the [examples directory](https://github.com/googleapis/java-genai/tree/main/examples/).
-
-
## Versioning
@@ -1040,7 +986,7 @@ The Google Gen AI Java SDK will accept contributions in the future.
Apache 2.0 - See [LICENSE][license] for more information.
[gemini-api-doc]: https://ai.google.dev/gemini-api/docs
-[gemini-enterprise-agent-platform-doc]: https://docs.cloud.google.com/gemini-enterprise-agent-platform
+[vertex-api-doc]: https://cloud.google.com/vertex-ai/generative-ai/docs/learn/overview
[maven-version-image]: https://img.shields.io/maven-central/v/com.google.genai/google-genai.svg
[maven-version-link]: https://central.sonatype.com/artifact/com.google.genai/google-genai
[javadoc-image]: https://img.shields.io/badge/JavaDoc-Online-green
diff --git a/examples/src/main/java/com/google/genai/examples/InteractionBasic.java b/examples/src/main/java/com/google/genai/examples/InteractionBasic.java
deleted file mode 100644
index 1cd3d78dcdc..00000000000
--- a/examples/src/main/java/com/google/genai/examples/InteractionBasic.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright 2026 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.InteractionBasic"
- */
-package com.google.genai.examples;
-
-import com.google.genai.Client;
-import com.google.genai.interactions.models.interactions.Content;
-import com.google.genai.interactions.models.interactions.CreateModelInteractionParams;
-import com.google.genai.interactions.models.interactions.Interaction;
-import com.google.genai.interactions.models.interactions.Model;
-import com.google.genai.interactions.models.interactions.Step;
-
-/** An example of using the Unified Gen AI Java SDK to create a basic interaction. */
-public final class InteractionBasic {
- public static void main(String[] args) {
- Client client = new Client();
-
- if (client.vertexAI()) {
- System.out.println("Interactions API is not yet supported on Vertex");
- return;
- }
-
- System.out.println("Using Gemini Developer API");
-
- CreateModelInteractionParams params =
- CreateModelInteractionParams.builder()
- .input("Why is the sky blue?")
- .model(Model.GEMINI_2_5_FLASH)
- .build();
-
- Interaction interaction = client.interactions.create(params);
-
- System.out.println("Interaction ID: " + interaction.id());
- System.out.println("Status: " + interaction.status());
-
- // Print the text outputs from the interaction.
- for (Step step : interaction.steps()) {
- if (step.isModelOutput()) {
- step.asModelOutput()
- .content()
- .ifPresent(
- contents -> {
- for (Content content : contents) {
- content
- .text()
- .ifPresent(text -> System.out.println("Output: " + text.text()));
- }
- });
- }
- }
- }
-
- private InteractionBasic() {}
-}
diff --git a/examples/src/main/java/com/google/genai/examples/InteractionCreate.java b/examples/src/main/java/com/google/genai/examples/InteractionCreate.java
deleted file mode 100644
index 52f4597c5b6..00000000000
--- a/examples/src/main/java/com/google/genai/examples/InteractionCreate.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright 2026 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.InteractionCreate"
- */
-package com.google.genai.examples;
-
-import com.google.genai.Client;
-import com.google.genai.interactions.models.interactions.Content;
-import com.google.genai.interactions.models.interactions.CreateModelInteractionParams;
-import com.google.genai.interactions.models.interactions.Interaction;
-import com.google.genai.interactions.models.interactions.Model;
-import com.google.genai.interactions.models.interactions.Step;
-
-/** An example of using the Unified Gen AI Java SDK to create an interaction. */
-public final class InteractionCreate {
- 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()) {
- System.out.println("Using Vertex AI");
- } else {
- System.out.println("Using Gemini Developer API");
- }
-
- CreateModelInteractionParams params =
- CreateModelInteractionParams.builder()
- .input("What is your name?")
- .model(Model.GEMINI_2_5_FLASH)
- .build();
-
- Interaction interaction = client.interactions.create(params);
-
- System.out.println("Interaction ID: " + interaction.id());
- System.out.println("Status: " + interaction.status());
-
- // Print the text outputs from the interaction.
- for (Step step : interaction.steps()) {
- if (step.isModelOutput()) {
- step.asModelOutput()
- .content()
- .ifPresent(
- contents -> {
- for (Content content : contents) {
- content
- .text()
- .ifPresent(text -> System.out.println("Output: " + text.text()));
- }
- });
- }
- }
- }
-
- private InteractionCreate() {}
-}
diff --git a/examples/src/main/java/com/google/genai/examples/InteractionCreateAsync.java b/examples/src/main/java/com/google/genai/examples/InteractionCreateAsync.java
deleted file mode 100644
index 19b5144a602..00000000000
--- a/examples/src/main/java/com/google/genai/examples/InteractionCreateAsync.java
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright 2026 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.InteractionCreateAsync"
- */
-package com.google.genai.examples;
-
-import com.google.genai.Client;
-import com.google.genai.interactions.models.interactions.Content;
-import com.google.genai.interactions.models.interactions.CreateModelInteractionParams;
-import com.google.genai.interactions.models.interactions.Interaction;
-import com.google.genai.interactions.models.interactions.Model;
-import com.google.genai.interactions.models.interactions.Step;
-import java.util.concurrent.CompletableFuture;
-
-/** An example of using the Unified Gen AI Java SDK to create an interaction asynchronously. */
-public final class InteractionCreateAsync {
- 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()) {
- System.out.println("Using Vertex AI");
- } else {
- System.out.println("Using Gemini Developer API");
- }
-
- CreateModelInteractionParams params =
- CreateModelInteractionParams.builder()
- .input("What is your name?")
- .model(Model.GEMINI_2_5_FLASH)
- .build();
-
- CompletableFuture interactionFuture = client.async.interactions.create(params);
-
- interactionFuture
- .thenAccept(
- interaction -> {
- System.out.println("Interaction ID: " + interaction.id());
- System.out.println("Status: " + interaction.status());
-
- // Print the text outputs from the interaction.
- for (Step step : interaction.steps()) {
- if (step.isModelOutput()) {
- step.asModelOutput()
- .content()
- .ifPresent(
- contents -> {
- for (Content content : contents) {
- content
- .text()
- .ifPresent(
- text -> System.out.println("Output: " + text.text()));
- }
- });
- }
- }
- })
- .join();
- }
-
- private InteractionCreateAsync() {}
-}
diff --git a/examples/src/main/java/com/google/genai/examples/InteractionCreateAsyncStreaming.java b/examples/src/main/java/com/google/genai/examples/InteractionCreateAsyncStreaming.java
deleted file mode 100644
index 254b6c86d0d..00000000000
--- a/examples/src/main/java/com/google/genai/examples/InteractionCreateAsyncStreaming.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright 2026 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.InteractionCreateAsyncStreaming"
- */
-package com.google.genai.examples;
-
-import com.google.genai.Client;
-import com.google.genai.interactions.models.interactions.CreateModelInteractionParams;
-import com.google.genai.interactions.models.interactions.Model;
-
-/**
- * An example of using the Unified Gen AI Java SDK to create a streaming interaction asynchronously.
- */
-public final class InteractionCreateAsyncStreaming {
- 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()) {
- System.out.println("Using Vertex AI");
- } else {
- System.out.println("Using Gemini Developer API");
- }
-
- CreateModelInteractionParams params =
- CreateModelInteractionParams.builder()
- .input("Tell me a story in 300 words.")
- .model(Model.GEMINI_2_5_FLASH)
- .build();
-
- System.out.println("Streaming response:");
- client
- .async
- .interactions
- .createStreaming(params)
- .subscribe(
- event ->
- event
- .stepDelta()
- .map(stepDelta -> stepDelta.delta())
- .flatMap(delta -> delta.text())
- .map(text -> text.text())
- .ifPresent(System.out::print))
- // Wait for the stream to complete.
- .onCompleteFuture()
- .join();
- System.out.println();
-
- client.close();
- }
-
- private InteractionCreateAsyncStreaming() {}
-}
diff --git a/examples/src/main/java/com/google/genai/examples/InteractionCreateStreaming.java b/examples/src/main/java/com/google/genai/examples/InteractionCreateStreaming.java
deleted file mode 100644
index 24e1f175262..00000000000
--- a/examples/src/main/java/com/google/genai/examples/InteractionCreateStreaming.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright 2026 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.InteractionCreateStreaming"
- */
-package com.google.genai.examples;
-
-import com.google.genai.Client;
-import com.google.genai.interactions.core.http.StreamResponse;
-import com.google.genai.interactions.models.interactions.CreateModelInteractionParams;
-import com.google.genai.interactions.models.interactions.InteractionSseEvent;
-import com.google.genai.interactions.models.interactions.Model;
-
-/**
- * An example of using the Unified Gen AI Java SDK to create a streaming interaction synchronously.
- */
-public final class InteractionCreateStreaming {
- 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()) {
- System.out.println("Using Vertex AI");
- } else {
- System.out.println("Using Gemini Developer API");
- }
-
- CreateModelInteractionParams params =
- CreateModelInteractionParams.builder()
- .input("Tell me a story in 300 words.")
- .model(Model.GEMINI_2_5_FLASH)
- .build();
-
- try (StreamResponse streamResponse =
- client.interactions.createStreaming(params)) {
- System.out.println("Streaming response:");
- streamResponse.stream()
- .flatMap(event -> event.stepDelta().stream())
- .map(stepDelta -> stepDelta.delta())
- .flatMap(delta -> delta.text().stream())
- .map(text -> text.text())
- .forEach(System.out::print);
- System.out.println();
- }
- }
-
- private InteractionCreateStreaming() {}
-}
diff --git a/examples/src/main/java/com/google/genai/examples/InteractionDeepResearch.java b/examples/src/main/java/com/google/genai/examples/InteractionDeepResearch.java
deleted file mode 100644
index 8653f287249..00000000000
--- a/examples/src/main/java/com/google/genai/examples/InteractionDeepResearch.java
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- * Copyright 2026 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:
- *
- * Deep Research is currently only available on Vertex AI.
- *
- *
1. Setup ADC to get credentials:
- * https://cloud.google.com/docs/authentication/provide-credentials-adc#google-idp
- *
- *
2. Set Project, Location, and USE_VERTEXAI flag as environment variables:
- *
- *
export GOOGLE_CLOUD_PROJECT=YOUR_PROJECT
- *
- *
export GOOGLE_CLOUD_LOCATION=global
- *
- *
export GOOGLE_GENAI_USE_VERTEXAI=true
- *
- *
3. Compile the java package and run the sample code.
- *
- *
mvn clean compile exec:java
- * -Dexec.mainClass="com.google.genai.examples.InteractionDeepResearch"
- */
-package com.google.genai.examples;
-
-import com.google.genai.Client;
-import com.google.genai.interactions.core.ClientOptions;
-import com.google.genai.interactions.core.RequestOptions;
-import com.google.genai.interactions.core.http.StreamResponse;
-import com.google.genai.interactions.models.interactions.CreateAgentInteractionParams;
-import com.google.genai.interactions.models.interactions.InteractionSseEvent;
-import com.google.genai.interactions.services.blocking.InteractionService;
-import java.time.Duration;
-import java.util.concurrent.atomic.AtomicReference;
-
-/**
- * An example of using the Unified Gen AI Java SDK to run a Deep Research interaction on Vertex AI.
- */
-public final class InteractionDeepResearch {
- public static void main(String[] args) {
- // Instantiate the client. Deep Research requires Vertex AI.
- // Ensure GOOGLE_CLOUD_PROJECT, GOOGLE_CLOUD_LOCATION=global, and
- // GOOGLE_GENAI_USE_VERTEXAI=true are set in your environment.
- Client client = new Client();
-
- if (!client.vertexAI()) {
- System.err.println("Deep Research is only supported on Vertex AI. "
- + "Please set GOOGLE_GENAI_USE_VERTEXAI=true.");
- return;
- }
-
- System.out.println(
- "Using Vertex AI Project: " + (client.project() != null ? client.project() : "unknown"));
-
- CreateAgentInteractionParams params =
- CreateAgentInteractionParams.builder()
- .agent("deep-research-pro-preview-12-2025")
- .input("I want to learn more about the history of Hadrian's Wall")
- .background(true)
- .stream(true)
- .build();
-
- AtomicReference interactionId = new AtomicReference<>();
- RequestOptions options = RequestOptions.builder().timeout(Duration.ofHours(1)).build();
-
- System.out.println("--- Starting Deep Research Interaction ---");
- InteractionService interactions =
- client.interactions.withOptions(
- b -> {
- ClientOptions.Builder unused =
- b.apiVersion("v1beta1");
- });
-
- try (StreamResponse streamResponse =
- interactions.createStreaming(params, options)) {
- // We consume the first few events to capture the Interaction ID and see progress.
- streamResponse.stream()
- .limit(1)
- .forEach(
- event -> {
- if (event.isCreated()) {
- String id = event.asCreated().interaction().id();
- interactionId.set(id);
- System.out.println("Started Interaction ID: " + id);
- }
- String eventType = "unknown";
- if (event.isCreated()) {
- eventType = "interaction.created";
- } else if (event.isCompleted()) {
- eventType = "interaction.completed";
- } else if (event.isStatusUpdate()) {
- eventType = "interaction.status_update";
- } else if (event.isStepStart()) {
- eventType = "step.start";
- } else if (event.isStepDelta()) {
- eventType = "step.delta";
- } else if (event.isStepStop()) {
- eventType = "step.stop";
- } else if (event.isError()) {
- eventType = "error";
- }
-
- System.out.println("Event type: " + eventType);
- });
- }
-
- String id = interactionId.get();
- if (id == null) {
- System.err.println("Failed to capture interaction ID.");
- return;
- }
-
- // Deep research can take a long time. In a real application, you might poll or resume later.
- // Here we resume the stream to wait for more output.
- System.out.println("\n--- Resuming Interaction: " + id + " ---");
- try (StreamResponse getStream =
- interactions.getStreaming(id, options)) {
- getStream.stream()
- .forEach(
- event -> {
- if (event.isStatusUpdate()) {
- System.out.println(
- "\n[Status update: " + event.asStatusUpdate().status().known() + "]");
- }
-
- event
- .stepDelta()
- .ifPresent(
- delta -> {
- delta
- .delta()
- .text()
- .ifPresentOrElse(
- text -> System.out.print(text.text()),
- () -> {
- // If it's a content delta but doesn't have text (e.g. tool call
- // or thought), print it.
- System.out.println(
- "\n[Agent Activity]: "
- + delta
- .delta()
- ._json()
- .map(Object::toString)
- .orElse("Unknown activity"));
- });
- });
- });
- System.out.println();
- }
- }
-
- private InteractionDeepResearch() {}
-}
diff --git a/examples/src/main/java/com/google/genai/examples/InteractionFunctionCallingClientState.java b/examples/src/main/java/com/google/genai/examples/InteractionFunctionCallingClientState.java
deleted file mode 100644
index a3f87d86326..00000000000
--- a/examples/src/main/java/com/google/genai/examples/InteractionFunctionCallingClientState.java
+++ /dev/null
@@ -1,215 +0,0 @@
-/*
- * Copyright 2026 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.InteractionFunctionCallingClientState"
- */
-package com.google.genai.examples;
-
-import com.google.common.collect.ImmutableMap;
-import com.google.genai.Client;
-import com.google.genai.interactions.core.JsonValue;
-import com.google.genai.interactions.models.interactions.Content;
-import com.google.genai.interactions.models.interactions.CreateModelInteractionParams;
-import com.google.genai.interactions.models.interactions.Function;
-import com.google.genai.interactions.models.interactions.FunctionCallStep;
-import com.google.genai.interactions.models.interactions.FunctionResultStep;
-import com.google.genai.interactions.models.interactions.Interaction;
-import com.google.genai.interactions.models.interactions.Model;
-import com.google.genai.interactions.models.interactions.Step;
-import com.google.genai.interactions.models.interactions.TextContent;
-import com.google.genai.interactions.models.interactions.Tool;
-import com.google.genai.interactions.models.interactions.UserInputStep;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * An example of using the Interactions API for multi-turn function calling where the state is
- * managed by the client.
- */
-public final class InteractionFunctionCallingClientState {
- public static void main(String[] args) {
- Client client = new Client();
-
- if (client.vertexAI()) {
- System.out.println("Interactions API is not yet supported on Vertex");
- return;
- }
-
- System.out.println("Using Gemini Developer API");
-
- // 1. Define the function (tool)
- Map attendeesSchema = new HashMap<>();
- attendeesSchema.put("type", "array");
- attendeesSchema.put("items", ImmutableMap.of("type", "string"));
- attendeesSchema.put("description", "List of people attending the meeting.");
-
- Map dateSchema = new HashMap<>();
- dateSchema.put("type", "string");
- dateSchema.put("description", "Date of the meeting (e.g., 2024-07-29)");
-
- Map timeSchema = new HashMap<>();
- timeSchema.put("type", "string");
- timeSchema.put("description", "Time of the meeting (e.g., 15:00)");
-
- Map topicSchema = new HashMap<>();
- topicSchema.put("type", "string");
- topicSchema.put("description", "The subject or topic of the meeting.");
-
- Map properties = new HashMap<>();
- properties.put("attendees", attendeesSchema);
- properties.put("date", dateSchema);
- properties.put("time", timeSchema);
- properties.put("topic", topicSchema);
-
- Map parametersSchema = new HashMap<>();
- parametersSchema.put("type", "object");
- parametersSchema.put("properties", properties);
- parametersSchema.put("required", Arrays.asList("attendees", "date", "time", "topic"));
-
- Function function =
- Function.builder()
- .name("schedule_meeting")
- .description("Schedules a meeting with specified attendees at a given time and date.")
- .parameters(JsonValue.from(parametersSchema))
- .build();
-
- // 2. Initialize conversation history
- List conversationHistory = new ArrayList<>();
- conversationHistory.add(
- Step.ofUserInput(
- UserInputStep.builder()
- .content(
- List.of(
- Content.ofText(
- TextContent.builder()
- .text(
- "Schedule a meeting for 2025-11-01 at 10 am with Peter and Amir"
- + " about the Next Gen API")
- .build())))
- .build()));
-
- // 3. First turn: Model decides to call the function
- CreateModelInteractionParams params =
- CreateModelInteractionParams.builder()
- .model(Model.GEMINI_2_5_FLASH)
- .inputOfStepList(conversationHistory)
- .tools(Arrays.asList(Tool.ofFunction(function)))
- .build();
-
- Interaction response = client.interactions.create(params);
-
- String functionCallId = null;
- String functionName = null;
-
- List steps = response.steps();
- if (steps != null) {
- for (Step step : steps) {
- if (step.isFunctionCall()) {
- FunctionCallStep functionCall = step.asFunctionCall();
- functionCallId = functionCall.id();
- functionName = functionCall.name();
- System.out.println("Model requested function call: " + functionName);
- System.out.println("Arguments: " + functionCall.arguments());
- } else if (step.isModelOutput()) {
- step.asModelOutput()
- .content()
- .ifPresent(
- contents -> {
- for (Content output : contents) {
- output
- .text()
- .ifPresent(text -> System.out.println("Output Text: " + text.text()));
- }
- });
- }
- }
-
- // Add model response back to history
- for (Step step : steps) {
- conversationHistory.add(step);
- }
- }
-
- // 4. Second turn: Send the function result back to the model
- if (functionCallId != null) {
- System.out.println("Sending function result back...");
-
- FunctionResultStep functionResult =
- FunctionResultStep.builder()
- .callId(functionCallId)
- .name(functionName)
- .result(FunctionResultStep.Result.ofString("Meeting scheduled successfully."))
- .build();
-
- // Create a step with function result
- conversationHistory.add(Step.ofFunctionResult(functionResult));
-
- CreateModelInteractionParams followUpParams =
- CreateModelInteractionParams.builder()
- .model(Model.GEMINI_2_5_FLASH)
- .inputOfStepList(conversationHistory)
- .build();
-
- Interaction followUpResponse = client.interactions.create(followUpParams);
-
- System.out.println("Final response status: " + followUpResponse.status());
- for (Step step : followUpResponse.steps()) {
- if (step.isModelOutput()) {
- step.asModelOutput()
- .content()
- .ifPresent(
- contents -> {
- for (Content output : contents) {
- output
- .text()
- .ifPresent(
- text -> System.out.println("Final Output: " + text.text()));
- }
- });
- }
- }
- } else {
- System.out.println("No function call requested by the model.");
- }
- }
-
- private InteractionFunctionCallingClientState() {}
-}
diff --git a/examples/src/main/java/com/google/genai/examples/InteractionFunctionCallingServerState.java b/examples/src/main/java/com/google/genai/examples/InteractionFunctionCallingServerState.java
deleted file mode 100644
index 7652c71270d..00000000000
--- a/examples/src/main/java/com/google/genai/examples/InteractionFunctionCallingServerState.java
+++ /dev/null
@@ -1,194 +0,0 @@
-/*
- * Copyright 2026 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.InteractionFunctionCallingServerState"
- */
-package com.google.genai.examples;
-
-import com.google.common.collect.ImmutableMap;
-import com.google.genai.Client;
-import com.google.genai.interactions.core.JsonValue;
-import com.google.genai.interactions.models.interactions.Content;
-import com.google.genai.interactions.models.interactions.CreateModelInteractionParams;
-import com.google.genai.interactions.models.interactions.Function;
-import com.google.genai.interactions.models.interactions.FunctionCallStep;
-import com.google.genai.interactions.models.interactions.FunctionResultStep;
-import com.google.genai.interactions.models.interactions.Interaction;
-import com.google.genai.interactions.models.interactions.Model;
-import com.google.genai.interactions.models.interactions.Step;
-import com.google.genai.interactions.models.interactions.Tool;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * An example of using the Interactions API for multi-turn function calling where the state is
- * managed by the server.
- */
-public final class InteractionFunctionCallingServerState {
- public static void main(String[] args) {
- Client client = new Client();
-
- if (client.vertexAI()) {
- System.out.println("Interactions API is not yet supported on Vertex");
- return;
- }
-
- System.out.println("Using Gemini Developer API");
-
- // 1. Define the function (tool)
- Map attendeesSchema = new HashMap<>();
- attendeesSchema.put("type", "array");
- attendeesSchema.put("items", ImmutableMap.of("type", "string"));
- attendeesSchema.put("description", "List of people attending the meeting.");
-
- Map dateSchema = new HashMap<>();
- dateSchema.put("type", "string");
- dateSchema.put("description", "Date of the meeting (e.g., 2024-07-29)");
-
- Map timeSchema = new HashMap<>();
- timeSchema.put("type", "string");
- timeSchema.put("description", "Time of the meeting (e.g., 15:00)");
-
- Map topicSchema = new HashMap<>();
- topicSchema.put("type", "string");
- topicSchema.put("description", "The subject or topic of the meeting.");
-
- Map properties = new HashMap<>();
- properties.put("attendees", attendeesSchema);
- properties.put("date", dateSchema);
- properties.put("time", timeSchema);
- properties.put("topic", topicSchema);
-
- Map parametersSchema = new HashMap<>();
- parametersSchema.put("type", "object");
- parametersSchema.put("properties", properties);
- parametersSchema.put("required", Arrays.asList("attendees", "date", "time", "topic"));
-
- Function function =
- Function.builder()
- .name("schedule_meeting")
- .description("Schedules a meeting with specified attendees at a given time and date.")
- .parameters(JsonValue.from(parametersSchema))
- .build();
-
- // 2. First turn: Model decides to call the function
- CreateModelInteractionParams params =
- CreateModelInteractionParams.builder()
- .input(
- "Schedule a meeting for 2025-11-01 at 10 am with Peter and Amir about the Next Gen"
- + " API")
- .model(Model.GEMINI_2_5_FLASH)
- .tools(Arrays.asList(Tool.ofFunction(function)))
- .build();
-
- Interaction response = client.interactions.create(params);
-
- String functionCallId = null;
- String functionName = null;
-
- List steps = response.steps();
- if (steps != null) {
- for (Step step : steps) {
- if (step.isFunctionCall()) {
- FunctionCallStep functionCall = step.asFunctionCall();
- functionCallId = functionCall.id();
- functionName = functionCall.name();
- System.out.println("Model requested function call: " + functionName);
- System.out.println("Arguments: " + functionCall.arguments());
- } else if (step.isModelOutput()) {
- step.asModelOutput()
- .content()
- .ifPresent(
- contents -> {
- for (Content output : contents) {
- output
- .text()
- .ifPresent(text -> System.out.println("Output Text: " + text.text()));
- }
- });
- }
- }
- }
-
- // 3. Second turn: Send the function result back to the model
- if (functionCallId != null) {
- System.out.println("Sending function result back...");
-
- FunctionResultStep functionResult =
- FunctionResultStep.builder()
- .callId(functionCallId)
- .name(functionName)
- .result(FunctionResultStep.Result.ofString("Meeting scheduled successfully."))
- .build();
-
- CreateModelInteractionParams followUpParams =
- CreateModelInteractionParams.builder()
- .model(Model.GEMINI_2_5_FLASH)
- .previousInteractionId(response.id())
- .input(
- CreateModelInteractionParams.Input.ofStepList(
- java.util.Arrays.asList(Step.ofFunctionResult(functionResult))))
- .build();
-
- Interaction followUpResponse = client.interactions.create(followUpParams);
-
- System.out.println("Final response status: " + followUpResponse.status());
- for (Step step : followUpResponse.steps()) {
- if (step.isModelOutput()) {
- step.asModelOutput()
- .content()
- .ifPresent(
- contents -> {
- for (Content output : contents) {
- output
- .text()
- .ifPresent(
- text -> System.out.println("Final Output: " + text.text()));
- }
- });
- }
- }
- } else {
- System.out.println("No function call requested by the model.");
- }
- }
-
- private InteractionFunctionCallingServerState() {}
-}
diff --git a/examples/src/main/java/com/google/genai/examples/InteractionGet.java b/examples/src/main/java/com/google/genai/examples/InteractionGet.java
deleted file mode 100644
index f19f5566741..00000000000
--- a/examples/src/main/java/com/google/genai/examples/InteractionGet.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Copyright 2026 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.InteractionGet"
- */
-package com.google.genai.examples;
-
-import com.google.genai.Client;
-import com.google.genai.interactions.models.interactions.Content;
-import com.google.genai.interactions.models.interactions.CreateModelInteractionParams;
-import com.google.genai.interactions.models.interactions.Interaction;
-import com.google.genai.interactions.models.interactions.Model;
-import com.google.genai.interactions.models.interactions.Step;
-
-/** An example of using the Unified Gen AI Java SDK to retrieve an interaction. */
-public final class InteractionGet {
- public static void main(String[] args) {
- Client client = new Client();
-
- if (client.vertexAI()) {
- System.out.println("Interactions API is not yet supported on Vertex");
- return;
- }
-
- System.out.println("Using Gemini Developer API");
-
- // First, create an interaction to get an ID.
- CreateModelInteractionParams createParams =
- CreateModelInteractionParams.builder()
- .input("Why is the sky blue?")
- .model(Model.GEMINI_2_5_FLASH)
- .build();
-
- Interaction createdInteraction = client.interactions.create(createParams);
- String id = createdInteraction.id();
- System.out.println("Created Interaction ID: " + id);
-
- // Now, retrieve the interaction using the ID.
- Interaction retrievedInteraction = client.interactions.get(id);
- System.out.println("Retrieved Interaction ID: " + retrievedInteraction.id());
- System.out.println("Status: " + retrievedInteraction.status());
-
- // Print the text outputs from the retrieved interaction.
- for (Step step : retrievedInteraction.steps()) {
- if (step.isModelOutput()) {
- step.asModelOutput()
- .content()
- .ifPresent(
- contents -> {
- for (Content content : contents) {
- content
- .text()
- .ifPresent(text -> System.out.println("Output: " + text.text()));
- }
- });
- }
- }
- }
-
- private InteractionGet() {}
-}
diff --git a/examples/src/main/java/com/google/genai/examples/InteractionMultimodalInputTextAndAudio.java b/examples/src/main/java/com/google/genai/examples/InteractionMultimodalInputTextAndAudio.java
deleted file mode 100644
index 1e5b582b0b9..00000000000
--- a/examples/src/main/java/com/google/genai/examples/InteractionMultimodalInputTextAndAudio.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright 2026 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
- *
- * http://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.InteractionMultimodalInputTextAndAudio"
- */
-package com.google.genai.examples;
-
-import com.google.genai.Client;
-import com.google.genai.interactions.models.interactions.AudioContent;
-import com.google.genai.interactions.models.interactions.Content;
-import com.google.genai.interactions.models.interactions.CreateModelInteractionParams;
-import com.google.genai.interactions.models.interactions.Interaction;
-import com.google.genai.interactions.models.interactions.Step;
-import com.google.genai.interactions.models.interactions.TextContent;
-import java.util.Arrays;
-import java.util.List;
-
-/** Example of using the Interactions API with multimodal input (text and audio). */
-public class InteractionMultimodalInputTextAndAudio {
-
- private InteractionMultimodalInputTextAndAudio() {}
-
- private static void createInteractions(Client client) {
- Content textContent =
- Content.ofText(TextContent.builder().text("Summarize this audio clip.").build());
- Content audioContent =
- Content.ofAudio(
- AudioContent.builder()
- .uri("gs://cloud-samples-data/generative-ai/audio/pixel.mp3")
- .mimeType(AudioContent.MimeType.AUDIO_MP3)
- .build());
-
- List contents = Arrays.asList(textContent, audioContent);
-
- CreateModelInteractionParams params =
- CreateModelInteractionParams.builder()
- .model("gemini-2.5-flash")
- .inputOfContentList(contents)
- .build();
-
- Interaction interaction = client.interactions.create(params);
-
- List steps = interaction.steps();
- for (int i = 0; i < steps.size(); i++) {
- System.out.println("Step " + (i + 1) + ": " + steps.get(i));
- }
- }
-
- public static void main(String[] args) {
- Client client = new Client();
- if (client.vertexAI()) {
- System.out.println("Interactions API is not yet supported on Vertex");
- return;
- }
- try {
- createInteractions(client);
- } catch (RuntimeException e) {
- System.err.println("Got error: " + e.getMessage());
- e.printStackTrace();
- }
- }
-}
diff --git a/examples/src/main/java/com/google/genai/examples/InteractionMultimodalInputTextAndImage.java b/examples/src/main/java/com/google/genai/examples/InteractionMultimodalInputTextAndImage.java
deleted file mode 100644
index 68bb9ab5e71..00000000000
--- a/examples/src/main/java/com/google/genai/examples/InteractionMultimodalInputTextAndImage.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright 2026 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
- *
- * http://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.InteractionMultimodalInputTextAndImage"
- */
-package com.google.genai.examples;
-
-import com.google.genai.Client;
-import com.google.genai.interactions.models.interactions.Content;
-import com.google.genai.interactions.models.interactions.CreateModelInteractionParams;
-import com.google.genai.interactions.models.interactions.ImageContent;
-import com.google.genai.interactions.models.interactions.Interaction;
-import com.google.genai.interactions.models.interactions.Step;
-import com.google.genai.interactions.models.interactions.TextContent;
-import java.util.Arrays;
-import java.util.List;
-
-/** Example of using the Interactions API with multimodal input (text and image). */
-public class InteractionMultimodalInputTextAndImage {
-
- private InteractionMultimodalInputTextAndImage() {}
-
- private static void createInteractions(Client client) {
- Content textContent =
- Content.ofText(TextContent.builder().text("What is shown in this image?").build());
- Content imageContent =
- Content.ofImage(
- ImageContent.builder()
- .uri("gs://cloud-samples-data/generative-ai/image/scones.jpg")
- .mimeType(ImageContent.MimeType.IMAGE_JPEG)
- .build());
-
- List contents = Arrays.asList(textContent, imageContent);
-
- CreateModelInteractionParams params =
- CreateModelInteractionParams.builder()
- .model("gemini-2.5-flash")
- .inputOfContentList(contents)
- .build();
-
- Interaction interaction = client.interactions.create(params);
-
- List steps = interaction.steps();
- for (int i = 0; i < steps.size(); i++) {
- System.out.println("Step " + (i + 1) + ": " + steps.get(i));
- }
- }
-
- public static void main(String[] args) {
- Client client = new Client();
- if (client.vertexAI()) {
- System.out.println("Interactions API is not yet supported on Vertex");
- return;
- }
- try {
- createInteractions(client);
- } catch (RuntimeException e) {
- System.err.println("Got error: " + e.getMessage());
- e.printStackTrace();
- }
- }
-}
diff --git a/examples/src/main/java/com/google/genai/examples/InteractionMultimodalResponseAudio.java b/examples/src/main/java/com/google/genai/examples/InteractionMultimodalResponseAudio.java
deleted file mode 100644
index 8083d9735b8..00000000000
--- a/examples/src/main/java/com/google/genai/examples/InteractionMultimodalResponseAudio.java
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright 2026 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
- *
- * http://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.InteractionMultimodalResponseAudio"
- */
-package com.google.genai.examples;
-
-import com.google.genai.Client;
-import com.google.genai.interactions.models.interactions.CreateModelInteractionParams;
-import com.google.genai.interactions.models.interactions.CreateModelInteractionParams.ResponseModality;
-import com.google.genai.interactions.models.interactions.GenerationConfig;
-import com.google.genai.interactions.models.interactions.Interaction;
-import com.google.genai.interactions.models.interactions.SpeechConfig;
-import com.google.genai.interactions.models.interactions.Step;
-import java.util.Arrays;
-
-/** Example of generating audio using the Interactions API. */
-public final class InteractionMultimodalResponseAudio {
-
- private static void createInteractions(Client client) {
-
- SpeechConfig speechConfig = SpeechConfig.builder().voice("achernar").language("en-US").build();
-
- GenerationConfig generationConfig =
- GenerationConfig.builder().speechConfig(Arrays.asList(speechConfig)).build();
-
- CreateModelInteractionParams params =
- CreateModelInteractionParams.builder()
- .model("gemini-2.5-flash-preview-tts")
- .responseModalities(Arrays.asList(ResponseModality.AUDIO))
- .generationConfig(generationConfig)
- .input("Say cheerfully: Have a wonderful day!")
- .build();
-
- Interaction interaction = client.interactions.create(params);
-
- int i = 1;
- for (Step step : interaction.steps()) {
- System.out.println("Output " + i + ": " + step);
- i++;
- }
- }
-
- public static void main(String[] args) {
- Client client = new Client();
- if (client.vertexAI()) {
- System.out.println("Interactions API is not yet supported on Vertex");
- return;
- }
- try {
- createInteractions(client);
- } catch (RuntimeException e) {
- System.err.println("Got error: " + e.getMessage());
- e.printStackTrace();
- }
- }
-
- private InteractionMultimodalResponseAudio() {}
-}
diff --git a/examples/src/main/java/com/google/genai/examples/InteractionMultimodalResponseAudioWithGenerateContent.java b/examples/src/main/java/com/google/genai/examples/InteractionMultimodalResponseAudioWithGenerateContent.java
deleted file mode 100644
index f6a5c2f39c1..00000000000
--- a/examples/src/main/java/com/google/genai/examples/InteractionMultimodalResponseAudioWithGenerateContent.java
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * Copyright 2026 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.InteractionMultimodalResponseAudioWithGenerateContent"
- */
-package com.google.genai.examples;
-
-import com.google.genai.Client;
-import com.google.genai.JsonSerializable;
-import com.google.genai.interactions.models.interactions.Content;
-import com.google.genai.interactions.models.interactions.CreateModelInteractionParams;
-import com.google.genai.interactions.models.interactions.CreateModelInteractionParams.ResponseModality;
-import com.google.genai.interactions.models.interactions.GenerationConfig;
-import com.google.genai.interactions.models.interactions.Interaction;
-import com.google.genai.interactions.models.interactions.Model;
-import com.google.genai.interactions.models.interactions.SpeechConfig;
-import com.google.genai.interactions.models.interactions.Step;
-import com.google.genai.types.GenerateContentConfig;
-import com.google.genai.types.GenerateContentResponse;
-import java.util.Collections;
-
-/**
- * An example of using the Unified Gen AI Java SDK to create an interaction with audio response and
- * generate content with audio response.
- */
-public final class InteractionMultimodalResponseAudioWithGenerateContent {
- public static void main(String[] args) {
- Client client = new Client();
-
- if (client.vertexAI()) {
- System.out.println("Interactions API is not yet supported on Vertex");
- return;
- }
-
- System.out.println("[Interactions] Start interactions multimodal response audio");
-
- SpeechConfig speechConfig = SpeechConfig.builder().voice("achernar").language("en-US").build();
-
- GenerationConfig generationConfig =
- GenerationConfig.builder().speechConfig(Collections.singletonList(speechConfig)).build();
-
- CreateModelInteractionParams params =
- CreateModelInteractionParams.builder()
- .model(Model.GEMINI_2_5_FLASH_PREVIEW_TTS)
- .responseModalities(Collections.singletonList(ResponseModality.AUDIO))
- .generationConfig(generationConfig)
- .input("Say cheerfully: Have a wonderful day!")
- .build();
-
- Interaction interaction = client.interactions.create(params);
-
- System.out.println("Interaction ID: " + interaction.id());
- System.out.println("Status: " + interaction.status());
-
- int i = 1;
- for (Step step : interaction.steps()) {
- System.out.println("Step " + i + ": " + step);
- i++;
- }
-
- System.out.println("[Generate Content] Start generate content");
- GenerateContentConfig config =
- GenerateContentConfig.builder().responseModalities("AUDIO").build();
-
- GenerateContentResponse generateContentResponse =
- client.models.generateContent(
- "gemini-2.5-flash-preview-tts", "Say cheerfully: Have a wonderful day!", config);
-
- System.out.println(
- "Generate Content response: " + JsonSerializable.toJsonString(generateContentResponse));
- }
-
- private InteractionMultimodalResponseAudioWithGenerateContent() {}
-}
diff --git a/examples/src/main/java/com/google/genai/examples/InteractionMultimodalResponseImage.java b/examples/src/main/java/com/google/genai/examples/InteractionMultimodalResponseImage.java
deleted file mode 100644
index 2476809c5ee..00000000000
--- a/examples/src/main/java/com/google/genai/examples/InteractionMultimodalResponseImage.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright 2026 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
- *
- * http://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.InteractionMultimodalResponseImage"
- */
-package com.google.genai.examples;
-
-import com.google.genai.Client;
-import com.google.genai.interactions.models.interactions.CreateModelInteractionParams;
-import com.google.genai.interactions.models.interactions.CreateModelInteractionParams.ResponseModality;
-import com.google.genai.interactions.models.interactions.Interaction;
-import com.google.genai.interactions.models.interactions.Step;
-import java.util.Arrays;
-
-/** Example of generating an image using the Interactions API. */
-public class InteractionMultimodalResponseImage {
-
- private static void createInteractions(Client client) {
-
- CreateModelInteractionParams params =
- CreateModelInteractionParams.builder()
- .model("gemini-2.5-flash-image-preview")
- .responseModalities(Arrays.asList(ResponseModality.IMAGE))
- .input("Generate an image of a futuristic cityscape at sunset.")
- .build();
-
- Interaction interaction = client.interactions.create(params);
-
- int i = 1;
- for (Step step : interaction.steps()) {
- System.out.println("Output " + i + ": " + step);
- i++;
- }
- }
-
- public static void main(String[] args) {
- Client client = new Client();
- if (client.vertexAI()) {
- System.out.println("Interactions API is not yet supported on Vertex");
- return;
- }
- try {
- createInteractions(client);
- } catch (RuntimeException e) {
- System.err.println("Got error: " + e.getMessage());
- e.printStackTrace();
- }
- }
-
- private InteractionMultimodalResponseImage() {}
-}
diff --git a/examples/src/main/java/com/google/genai/examples/InteractionMultimodalResponseImageWithGenerateContent.java b/examples/src/main/java/com/google/genai/examples/InteractionMultimodalResponseImageWithGenerateContent.java
deleted file mode 100644
index 6927477b9ea..00000000000
--- a/examples/src/main/java/com/google/genai/examples/InteractionMultimodalResponseImageWithGenerateContent.java
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * Copyright 2026 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.InteractionMultimodalResponseImageWithGenerateContent"
- */
-package com.google.genai.examples;
-
-import com.google.genai.Client;
-import com.google.genai.JsonSerializable;
-import com.google.genai.interactions.models.interactions.Content;
-import com.google.genai.interactions.models.interactions.CreateModelInteractionParams;
-import com.google.genai.interactions.models.interactions.CreateModelInteractionParams.ResponseModality;
-import com.google.genai.interactions.models.interactions.Interaction;
-import com.google.genai.interactions.models.interactions.Model;
-import com.google.genai.interactions.models.interactions.Step;
-import com.google.genai.types.GenerateContentConfig;
-import com.google.genai.types.GenerateContentResponse;
-import java.util.Collections;
-
-/**
- * An example of using the Unified Gen AI Java SDK to create an interaction with image response and
- * generate content with image response.
- */
-public final class InteractionMultimodalResponseImageWithGenerateContent {
- public static void main(String[] args) {
- Client client = new Client();
-
- if (client.vertexAI()) {
- System.out.println("Interactions API is not yet supported on Vertex");
- return;
- }
-
- System.out.println("[Interactions] Start interactions multimodal response image");
-
- CreateModelInteractionParams params =
- CreateModelInteractionParams.builder()
- .model(Model.GEMINI_2_5_FLASH_IMAGE)
- .responseModalities(Collections.singletonList(ResponseModality.IMAGE))
- .input("Generate an image of a futuristic cityscape at sunset.")
- .build();
-
- Interaction interaction = client.interactions.create(params);
-
- System.out.println("Interaction ID: " + interaction.id());
- System.out.println("Status: " + interaction.status());
-
- int i = 1;
- for (Step step : interaction.steps()) {
- System.out.println("Step " + i + ": " + step);
- i++;
- }
-
- System.out.println("[Generate Content] Start generate content");
- GenerateContentConfig config =
- GenerateContentConfig.builder().responseModalities("TEXT", "IMAGE").build();
-
- GenerateContentResponse generateContentResponse =
- client.models.generateContent(
- "gemini-2.5-flash-image",
- "Generate an image of a futuristic cityscape at sunset.",
- config);
-
- System.out.println(
- "Generate Content response: " + JsonSerializable.toJsonString(generateContentResponse));
- }
-
- private InteractionMultimodalResponseImageWithGenerateContent() {}
-}
diff --git a/examples/src/main/java/com/google/genai/examples/InteractionStateful.java b/examples/src/main/java/com/google/genai/examples/InteractionStateful.java
deleted file mode 100644
index a74def6597d..00000000000
--- a/examples/src/main/java/com/google/genai/examples/InteractionStateful.java
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Copyright 2026 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.InteractionStateful"
- */
-package com.google.genai.examples;
-
-import com.google.genai.Client;
-import com.google.genai.interactions.models.interactions.Content;
-import com.google.genai.interactions.models.interactions.CreateModelInteractionParams;
-import com.google.genai.interactions.models.interactions.Interaction;
-import com.google.genai.interactions.models.interactions.Model;
-import com.google.genai.interactions.models.interactions.Step;
-
-/** An example of using the Unified Gen AI Java SDK to create a stateful interaction. */
-public final class InteractionStateful {
- public static void main(String[] args) {
- Client client = new Client();
-
- if (client.vertexAI()) {
- System.out.println("Interactions API is not yet supported on Vertex AI");
- return;
- }
-
- System.out.println("Using Gemini Developer API");
-
- System.out.println("User: What are the three largest cities in Spain?");
- CreateModelInteractionParams params1 =
- CreateModelInteractionParams.builder()
- .input("What are the three largest cities in Spain?")
- .model(Model.GEMINI_2_5_FLASH)
- .build();
-
- Interaction interaction1 = client.interactions.create(params1);
- System.out.println("Model: ");
- printOutput(interaction1);
-
- System.out.println("\nUser: What is the most famous landmark in the second one?");
- CreateModelInteractionParams params2 =
- CreateModelInteractionParams.builder()
- .input("What is the most famous landmark in the second one?")
- .model(Model.GEMINI_2_5_FLASH)
- .previousInteractionId(interaction1.id())
- .build();
-
- Interaction interaction2 = client.interactions.create(params2);
- System.out.println("Model: ");
- printOutput(interaction2);
- }
-
- private static void printOutput(Interaction interaction) {
- for (Step step : interaction.steps()) {
- if (step.isModelOutput()) {
- step.asModelOutput()
- .content()
- .ifPresent(
- contents -> {
- for (Content content : contents) {
- content.text().ifPresent(text -> System.out.println(text.text()));
- }
- });
- }
- }
- }
-
- private InteractionStateful() {}
-}
diff --git a/examples/src/main/java/com/google/genai/examples/InteractionStateless.java b/examples/src/main/java/com/google/genai/examples/InteractionStateless.java
deleted file mode 100644
index af0037da85f..00000000000
--- a/examples/src/main/java/com/google/genai/examples/InteractionStateless.java
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * Copyright 2026 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.InteractionStateless"
- */
-package com.google.genai.examples;
-
-import com.google.genai.Client;
-import com.google.genai.interactions.models.interactions.Content;
-import com.google.genai.interactions.models.interactions.CreateModelInteractionParams;
-import com.google.genai.interactions.models.interactions.Interaction;
-import com.google.genai.interactions.models.interactions.Model;
-import com.google.genai.interactions.models.interactions.ModelOutputStep;
-import com.google.genai.interactions.models.interactions.Step;
-import com.google.genai.interactions.models.interactions.TextContent;
-import com.google.genai.interactions.models.interactions.UserInputStep;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * An example of using the Unified Gen AI Java SDK to create a stateless interaction (multi-turn
- * chat).
- */
-public final class InteractionStateless {
- public static void main(String[] args) {
- Client client = new Client();
-
- if (client.vertexAI()) {
- System.out.println("Interactions API is not yet supported on Vertex");
- return;
- } else {
- System.out.println("Using Gemini Developer API");
- }
-
- List conversationHistory = new ArrayList<>();
- conversationHistory.add(
- Step.ofUserInput(
- UserInputStep.builder()
- .content(
- List.of(
- Content.ofText(
- TextContent.builder()
- .text("What are the three largest cities in Spain?")
- .build())))
- .build()));
-
- System.out.println("User: What are the three largest cities in Spain?");
-
- CreateModelInteractionParams params1 =
- CreateModelInteractionParams.builder()
- .inputOfStepList(conversationHistory)
- .model(Model.GEMINI_2_5_FLASH)
- .store(false)
- .build();
-
- Interaction response1 = client.interactions.create(params1);
-
- System.out.println("Model: ");
- // Add model response to history
- for (Step step : response1.steps()) {
- if (step.isModelOutput()) {
- step.asModelOutput()
- .content()
- .ifPresent(
- contents -> {
- for (Content output : contents) {
- output.text().ifPresent(text -> System.out.println(text.text()));
- }
- });
- }
- conversationHistory.add(step);
- }
-
- // Add next user message
- conversationHistory.add(
- Step.ofUserInput(
- UserInputStep.builder()
- .content(
- List.of(
- Content.ofText(
- TextContent.builder()
- .text("What is the most famous landmark in the second one?")
- .build())))
- .build()));
-
- System.out.println("\nUser: What is the most famous landmark in the second one?");
-
- CreateModelInteractionParams params2 =
- CreateModelInteractionParams.builder()
- .inputOfStepList(conversationHistory)
- .model(Model.GEMINI_2_5_FLASH)
- .store(false)
- .build();
-
- Interaction response2 = client.interactions.create(params2);
-
- System.out.println("Model: ");
- for (Step step : response2.steps()) {
- if (step.isModelOutput()) {
- step.asModelOutput()
- .content()
- .ifPresent(
- contents -> {
- for (Content output : contents) {
- output.text().ifPresent(text -> System.out.println(text.text()));
- }
- });
- }
- }
- }
-
- private InteractionStateless() {}
-}
diff --git a/examples/src/main/java/com/google/genai/examples/InteractionStreaming.java b/examples/src/main/java/com/google/genai/examples/InteractionStreaming.java
deleted file mode 100644
index efc3079aabe..00000000000
--- a/examples/src/main/java/com/google/genai/examples/InteractionStreaming.java
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Copyright 2026 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.InteractionStreaming"
- */
-package com.google.genai.examples;
-
-import com.google.genai.Client;
-import com.google.genai.interactions.core.http.StreamResponse;
-import com.google.genai.interactions.models.interactions.CreateModelInteractionParams;
-import com.google.genai.interactions.models.interactions.InteractionSseEvent;
-import com.google.genai.interactions.models.interactions.Model;
-
-/** An example of using the Unified Gen AI Java SDK to stream an interaction. */
-public final class InteractionStreaming {
- public static void main(String[] args) {
- Client client = new Client();
-
- if (client.vertexAI()) {
- System.out.println("Interactions API is not yet supported on Vertex AI");
- return;
- }
-
- System.out.println("Using Gemini Developer API");
-
- CreateModelInteractionParams params =
- CreateModelInteractionParams.builder()
- .input("Tell me a story")
- .model(Model.GEMINI_2_5_FLASH)
- .build();
-
- try (StreamResponse response =
- client.interactions.createStreaming(params)) {
- response.stream()
- .forEach(
- event -> {
- if (event.isStepDelta()) {
- event
- .asStepDelta()
- .delta()
- .text()
- .ifPresent(
- t -> {
- System.out.print(t.text());
- System.out.flush();
- });
- }
- });
- System.out.println();
- } catch (RuntimeException e) {
- System.err.println("Error during streaming: " + e.getMessage());
- e.printStackTrace();
- }
- }
-
- private InteractionStreaming() {}
-}
diff --git a/examples/src/main/java/com/google/genai/examples/InteractionStructuredOutputJson.java b/examples/src/main/java/com/google/genai/examples/InteractionStructuredOutputJson.java
deleted file mode 100644
index 5bbc2d606f1..00000000000
--- a/examples/src/main/java/com/google/genai/examples/InteractionStructuredOutputJson.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright 2026 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
- *
- * http://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.InteractionStructuredOutputJson"
- */
-package com.google.genai.examples;
-
-import com.google.genai.Client;
-import com.google.genai.interactions.core.JsonValue;
-import com.google.genai.interactions.models.interactions.CreateModelInteractionParams;
-import com.google.genai.interactions.models.interactions.CreateModelInteractionParams.ResponseFormat;
-import com.google.genai.interactions.models.interactions.Interaction;
-import java.util.HashMap;
-import java.util.Map;
-
-/** Example of requesting structured JSON output using the Interactions API. */
-public class InteractionStructuredOutputJson {
-
- private static void createInteractions(Client client) {
-
- Map format = new HashMap<>();
- format.put("type", "array");
- format.put("description", "A list of colors");
- JsonValue responseFormat = JsonValue.from(format);
-
- CreateModelInteractionParams params =
- CreateModelInteractionParams.builder()
- .model("gemini-2.5-flash")
- .input("Which are the colors of a rainbow")
- .responseMimeType("application/json")
- .responseFormat(ResponseFormat.ofJsonValue(responseFormat))
- .build();
-
- Interaction interaction = client.interactions.create(params);
-
- System.out.println(interaction);
- }
-
- public static void main(String[] args) {
- Client client = new Client();
- if (client.vertexAI()) {
- System.out.println("Interactions API is not yet supported on Vertex");
- return;
- }
- try {
- createInteractions(client);
- } catch (RuntimeException e) {
- System.err.println("Got error: " + e.getMessage());
- e.printStackTrace();
- }
- }
-
- private InteractionStructuredOutputJson() {}
-}
diff --git a/examples/src/main/java/com/google/genai/examples/InteractionToolCallWithCodeExecution.java b/examples/src/main/java/com/google/genai/examples/InteractionToolCallWithCodeExecution.java
deleted file mode 100644
index 79cbffc508a..00000000000
--- a/examples/src/main/java/com/google/genai/examples/InteractionToolCallWithCodeExecution.java
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright 2026 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.InteractionToolCallWithCodeExecution"
- */
-package com.google.genai.examples;
-
-import com.google.genai.Client;
-import com.google.genai.interactions.models.interactions.Content;
-import com.google.genai.interactions.models.interactions.CreateModelInteractionParams;
-import com.google.genai.interactions.models.interactions.Interaction;
-import com.google.genai.interactions.models.interactions.Model;
-import com.google.genai.interactions.models.interactions.Step;
-import com.google.genai.interactions.models.interactions.Tool;
-
-/** An example of using the Interactions API with code execution tool. */
-public final class InteractionToolCallWithCodeExecution {
- public static void main(String[] args) {
- Client client = new Client();
-
- if (client.vertexAI()) {
- System.out.println("Interactions API is not yet supported on Vertex");
- return;
- }
-
- System.out.println("Using Gemini Developer API");
-
- CreateModelInteractionParams params =
- CreateModelInteractionParams.builder()
- .input("What is the sum of the first 100 integers?")
- .model(Model.GEMINI_2_5_FLASH)
- .addTool(Tool.ofCodeExecution())
- .build();
-
- try {
- Interaction interaction = client.interactions.create(params);
-
- System.out.println("Interaction ID: " + interaction.id());
- System.out.println("Status: " + interaction.status());
-
- // Print the text outputs from the interaction.
- for (Step step : interaction.steps()) {
- if (step.isModelOutput()) {
- step.asModelOutput()
- .content()
- .ifPresent(
- contents -> {
- for (Content content : contents) {
- content
- .text()
- .ifPresent(
- text -> System.out.println("Output: " + text.text()));
- }
- });
- }
- }
- } catch (RuntimeException e) {
- System.err.println("Error creating interaction: " + e.getMessage());
- e.printStackTrace();
- }
- }
-
- private InteractionToolCallWithCodeExecution() {}
-}
diff --git a/examples/src/main/java/com/google/genai/examples/InteractionToolCallWithComputerUse.java b/examples/src/main/java/com/google/genai/examples/InteractionToolCallWithComputerUse.java
deleted file mode 100644
index 83c32cb8561..00000000000
--- a/examples/src/main/java/com/google/genai/examples/InteractionToolCallWithComputerUse.java
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Copyright 2026 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.InteractionToolCallWithComputerUse"
- */
-package com.google.genai.examples;
-
-import com.google.genai.Client;
-import com.google.genai.interactions.models.interactions.Content;
-import com.google.genai.interactions.models.interactions.CreateModelInteractionParams;
-import com.google.genai.interactions.models.interactions.Interaction;
-import com.google.genai.interactions.models.interactions.Step;
-import com.google.genai.interactions.models.interactions.Tool;
-
-/**
- * An example of using the Unified Gen AI Java SDK to create an interaction with computer use tool.
- */
-public final class InteractionToolCallWithComputerUse {
- public static void main(String[] args) {
- Client client = new Client();
-
- if (client.vertexAI()) {
- System.out.println("Interactions API is not yet supported on Vertex");
- return;
- } else {
- System.out.println("Using Gemini Developer API");
- }
-
- CreateModelInteractionParams params =
- CreateModelInteractionParams.builder()
- .model("gemini-2.5-computer-use-preview-10-2025")
- .input(
- "Search for highly rated smart fridges with touchscreen, 2 doors, around 25 cu ft,"
- + " priced below 4000 dollars on Google Shopping. Create a bulleted list of the"
- + " 3 cheapest options in the format of name, description, price in an"
- + " easy-to-read layout.")
- .addTool(
- Tool.ComputerUse.builder()
- .environment(Tool.ComputerUse.Environment.BROWSER)
- .build())
- .build();
-
- Interaction interaction = client.interactions.create(params);
-
- System.out.println("Interaction ID: " + interaction.id());
- System.out.println("Status: " + interaction.status());
-
- // Print the text outputs from the interaction.
- for (Step step : interaction.steps()) {
- if (step.isModelOutput()) {
- step.asModelOutput()
- .content()
- .ifPresent(
- contents -> {
- for (Content content : contents) {
- content
- .text()
- .ifPresent(text -> System.out.println("Output: " + text.text()));
- }
- });
- }
- }
- }
-
- private InteractionToolCallWithComputerUse() {}
-}
diff --git a/examples/src/main/java/com/google/genai/examples/InteractionToolCallWithFunctions.java b/examples/src/main/java/com/google/genai/examples/InteractionToolCallWithFunctions.java
deleted file mode 100644
index 9705ca33253..00000000000
--- a/examples/src/main/java/com/google/genai/examples/InteractionToolCallWithFunctions.java
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- * Copyright 2026 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.InteractionToolCallWithFunctions"
- */
-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.interactions.core.JsonValue;
-import com.google.genai.interactions.models.interactions.Content;
-import com.google.genai.interactions.models.interactions.CreateModelInteractionParams;
-import com.google.genai.interactions.models.interactions.Function;
-import com.google.genai.interactions.models.interactions.FunctionCallStep;
-import com.google.genai.interactions.models.interactions.Interaction;
-import com.google.genai.interactions.models.interactions.Model;
-import com.google.genai.interactions.models.interactions.Step;
-import com.google.genai.interactions.models.interactions.Tool;
-
-/** An example of using the Unified Gen AI Java SDK to perform tool calling with functions. */
-public final class InteractionToolCallWithFunctions {
- public static void main(String[] args) {
- Client client = new Client();
-
- if (client.vertexAI()) {
- System.out.println("Interactions API is not yet supported on Vertex AI");
- return;
- }
-
- System.out.println("Using Gemini Developer API");
-
- ImmutableMap attendeesSchema =
- ImmutableMap.of(
- "type",
- "array",
- "items",
- ImmutableMap.of("type", "string"),
- "description",
- "List of people attending the meeting.");
- ImmutableMap dateSchema =
- ImmutableMap.of("type", "string", "description", "Date of the meeting (e.g., 2024-07-29)");
- ImmutableMap timeSchema =
- ImmutableMap.of("type", "string", "description", "Time of the meeting (e.g., 15:00)");
- ImmutableMap topicSchema =
- ImmutableMap.of("type", "string", "description", "The subject or topic of the meeting.");
-
- ImmutableMap properties =
- ImmutableMap.of(
- "attendees",
- attendeesSchema,
- "date",
- dateSchema,
- "time",
- timeSchema,
- "topic",
- topicSchema);
-
- ImmutableMap parametersSchema =
- ImmutableMap.of(
- "type",
- "object",
- "properties",
- properties,
- "required",
- ImmutableList.of("attendees", "date", "time", "topic"));
-
- Function function =
- Function.builder()
- .name("schedule_meeting")
- .description("Schedules a meeting with specified attendees at a given time and date.")
- .parameters(JsonValue.from(parametersSchema))
- .build();
-
- Tool tool = Tool.ofFunction(function);
-
- CreateModelInteractionParams params =
- CreateModelInteractionParams.builder()
- .input(
- "Schedule a meeting for 10/06/2028 at 10 am with Peter and Amir about the Next Gen"
- + " API")
- .model(Model.GEMINI_2_5_FLASH)
- .tools(ImmutableList.of(tool))
- .build();
-
- Interaction interaction = client.interactions.create(params);
-
- System.out.println("Interaction ID: " + interaction.id());
- System.out.println("Status: " + interaction.status());
-
- for (Step step : interaction.steps()) {
- if (step.isFunctionCall()) {
- FunctionCallStep fc = step.asFunctionCall();
- System.out.println("Function Call: " + fc.name());
- System.out.println("Arguments: " + fc.arguments());
- } else if (step.isModelOutput()) {
- step.asModelOutput()
- .content()
- .ifPresent(
- contents -> {
- for (Content output : contents) {
- output
- .text()
- .ifPresent(
- text ->
- System.out.println("Output Text: " + text.text()));
- }
- });
- }
- }
- }
-
- private InteractionToolCallWithFunctions() {}
-}
diff --git a/examples/src/main/java/com/google/genai/examples/InteractionToolCallWithGoogleSearch.java b/examples/src/main/java/com/google/genai/examples/InteractionToolCallWithGoogleSearch.java
deleted file mode 100644
index 4520ee36e63..00000000000
--- a/examples/src/main/java/com/google/genai/examples/InteractionToolCallWithGoogleSearch.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright 2026 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.InteractionToolCallWithGoogleSearch"
- */
-package com.google.genai.examples;
-
-import com.google.common.collect.ImmutableList;
-import com.google.genai.Client;
-import com.google.genai.interactions.models.interactions.Content;
-import com.google.genai.interactions.models.interactions.CreateModelInteractionParams;
-import com.google.genai.interactions.models.interactions.Interaction;
-import com.google.genai.interactions.models.interactions.Model;
-import com.google.genai.interactions.models.interactions.Step;
-import com.google.genai.interactions.models.interactions.Tool;
-
-/** An example of using the Unified Gen AI Java SDK to perform tool calling with Google Search. */
-public final class InteractionToolCallWithGoogleSearch {
- public static void main(String[] args) {
- Client client = new Client();
-
- if (client.vertexAI()) {
- System.out.println("Interactions API is not yet supported on Vertex AI");
- return;
- }
-
- System.out.println("Using Gemini Developer API");
-
- Tool.GoogleSearch googleSearch = Tool.GoogleSearch.builder().build();
- Tool tool = Tool.ofGoogleSearch(googleSearch);
-
- CreateModelInteractionParams params =
- CreateModelInteractionParams.builder()
- .input("Why is the sky blue")
- .model(Model.GEMINI_2_5_FLASH)
- .tools(ImmutableList.of(tool))
- .build();
-
- Interaction interaction = client.interactions.create(params);
-
- System.out.println("Interaction ID: " + interaction.id());
- System.out.println("Status: " + interaction.status());
-
- for (Step step : interaction.steps()) {
- if (step.isModelOutput()) {
- step.asModelOutput()
- .content()
- .ifPresent(
- contents -> {
- for (Content content : contents) {
- content
- .text()
- .ifPresent(
- text -> System.out.println("Output Text: " + text.text()));
- }
- });
- }
- }
- }
-
- private InteractionToolCallWithGoogleSearch() {}
-}
diff --git a/examples/src/main/java/com/google/genai/examples/InteractionToolCallWithMcpServer.java b/examples/src/main/java/com/google/genai/examples/InteractionToolCallWithMcpServer.java
deleted file mode 100644
index e554058a3b8..00000000000
--- a/examples/src/main/java/com/google/genai/examples/InteractionToolCallWithMcpServer.java
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Copyright 2026 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.InteractionToolCallWithMcpServer"
- */
-package com.google.genai.examples;
-
-import com.google.genai.Client;
-import com.google.genai.interactions.models.interactions.Content;
-import com.google.genai.interactions.models.interactions.CreateModelInteractionParams;
-import com.google.genai.interactions.models.interactions.Interaction;
-import com.google.genai.interactions.models.interactions.Model;
-import com.google.genai.interactions.models.interactions.Step;
-import com.google.genai.interactions.models.interactions.Tool;
-
-/** An example of using the Interactions API with an MCP server tool. */
-public final class InteractionToolCallWithMcpServer {
- public static void main(String[] args) {
- Client client = new Client();
-
- if (client.vertexAI()) {
- System.out.println("Interactions API is not yet supported on Vertex");
- return;
- }
-
- System.out.println("Using Gemini Developer API");
-
- Tool.McpServer mcpServer =
- Tool.McpServer.builder()
- .name("weather_service")
- .url("https://gemini-api-demos.uc.r.appspot.com/mcp")
- .build();
-
- CreateModelInteractionParams params =
- CreateModelInteractionParams.builder()
- .input("What is the temperature today in London?")
- .systemInstruction(
- "Today is 9-23-2025. Any dates before this are in the past, and any dates after"
- + " this are in the future.")
- .model(Model.GEMINI_2_5_FLASH)
- .addTool(Tool.ofMcpServer(mcpServer))
- .build();
-
- try {
- Interaction interaction = client.interactions.create(params);
-
- System.out.println("Interaction ID: " + interaction.id());
- System.out.println("Status: " + interaction.status());
-
- // Print the text outputs from the interaction.
- for (Step step : interaction.steps()) {
- if (step.isModelOutput()) {
- step.asModelOutput()
- .content()
- .ifPresent(
- contents -> {
- for (Content content : contents) {
- content
- .text()
- .ifPresent(
- text -> System.out.println("Output: " + text.text()));
- }
- });
- }
- }
- } catch (RuntimeException e) {
- System.err.println("Error creating interaction: " + e.getMessage());
- e.printStackTrace();
- }
- }
-
- private InteractionToolCallWithMcpServer() {}
-}
diff --git a/examples/src/main/java/com/google/genai/examples/InteractionToolCallWithUrlContext.java b/examples/src/main/java/com/google/genai/examples/InteractionToolCallWithUrlContext.java
deleted file mode 100644
index c4b38865ef4..00000000000
--- a/examples/src/main/java/com/google/genai/examples/InteractionToolCallWithUrlContext.java
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright 2026 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.InteractionToolCallWithUrlContext"
- */
-package com.google.genai.examples;
-
-import com.google.genai.Client;
-import com.google.genai.interactions.models.interactions.Content;
-import com.google.genai.interactions.models.interactions.CreateModelInteractionParams;
-import com.google.genai.interactions.models.interactions.Interaction;
-import com.google.genai.interactions.models.interactions.Model;
-import com.google.genai.interactions.models.interactions.Step;
-import com.google.genai.interactions.models.interactions.Tool;
-
-/** An example of using the Interactions API with URL context tool. */
-public final class InteractionToolCallWithUrlContext {
- public static void main(String[] args) {
- Client client = new Client();
-
- if (client.vertexAI()) {
- System.out.println("Interactions API is not yet supported on Vertex");
- return;
- }
-
- System.out.println("Using Gemini Developer API");
-
- CreateModelInteractionParams params =
- CreateModelInteractionParams.builder()
- .input(
- "Compare the ingredients and cooking times from the recipes at"
- + " https://www.foodnetwork.com/recipes/ina-garten/perfect-roast-chicken-recipe-1940592"
- + " and https://www.allrecipes.com/recipe/21151/simple-whole-roast-chicken/")
- .model(Model.GEMINI_2_5_FLASH)
- .addTool(Tool.ofUrlContext())
- .build();
-
- try {
- Interaction interaction = client.interactions.create(params);
-
- System.out.println("Interaction ID: " + interaction.id());
- System.out.println("Status: " + interaction.status());
-
- // Print the text outputs from the interaction.
- for (Step step : interaction.steps()) {
- if (step.isModelOutput()) {
- step.asModelOutput()
- .content()
- .ifPresent(
- contents -> {
- for (Content content : contents) {
- content
- .text()
- .ifPresent(
- text -> System.out.println("Output: " + text.text()));
- }
- });
- }
- }
- } catch (RuntimeException e) {
- System.err.println("Error creating interaction: " + e.getMessage());
- e.printStackTrace();
- }
- }
-
- private InteractionToolCallWithUrlContext() {}
-}
diff --git a/examples/src/main/java/com/google/genai/examples/InteractionWithConfig.java b/examples/src/main/java/com/google/genai/examples/InteractionWithConfig.java
deleted file mode 100644
index 0624c37bf5c..00000000000
--- a/examples/src/main/java/com/google/genai/examples/InteractionWithConfig.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright 2026 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.InteractionWithConfig"
- */
-package com.google.genai.examples;
-
-import com.google.genai.Client;
-import com.google.genai.interactions.models.interactions.Content;
-import com.google.genai.interactions.models.interactions.CreateModelInteractionParams;
-import com.google.genai.interactions.models.interactions.Interaction;
-import com.google.genai.interactions.models.interactions.Model;
-import com.google.genai.interactions.models.interactions.Step;
-
-/** An example of using the Unified Gen AI Java SDK to create an interaction with config. */
-public final class InteractionWithConfig {
- public static void main(String[] args) {
- Client client = new Client();
-
- if (client.vertexAI()) {
- System.out.println("Interactions API is not yet supported on Vertex AI");
- return;
- }
-
- System.out.println("Using Gemini Developer API");
-
- CreateModelInteractionParams params =
- CreateModelInteractionParams.builder()
- .input("Tell me a story")
- .model(Model.GEMINI_2_5_FLASH)
- .systemInstruction("You are a helpful assistant")
- .build();
-
- Interaction interaction = client.interactions.create(params);
-
- System.out.println("Interaction ID: " + interaction.id());
- System.out.println("Status: " + interaction.status());
-
- for (Step step : interaction.steps()) {
- if (step.isModelOutput()) {
- step.asModelOutput()
- .content()
- .ifPresent(
- contents -> {
- for (Content content : contents) {
- content
- .text()
- .ifPresent(text -> System.out.println("Output: " + text.text()));
- }
- });
- }
- }
- }
-
- private InteractionWithConfig() {}
-}
diff --git a/pom.xml b/pom.xml
index 50d08c6c232..676ecb3b48c 100644
--- a/pom.xml
+++ b/pom.xml
@@ -55,7 +55,6 @@
5.11.4
1.6.0
4.12.0
- 1.9.10
src/main/java
src/test/java
@@ -131,11 +130,6 @@
okhttp
${okhttp.version}
-
- com.squareup.okhttp3
- logging-interceptor
- ${okhttp.version}
-
com.google.protobuf
protobuf-java
@@ -166,27 +160,10 @@
jspecify
1.0.0
-
org.jetbrains.kotlin
kotlin-stdlib-jdk8
- ${kotlin.version}
-
-
- org.jetbrains.kotlin
- kotlin-reflect
- ${kotlin.version}
-
-
-
- com.fasterxml.jackson.module
- jackson-module-kotlin
- ${jackson.version}
-
-
- com.google.errorprone
- error_prone_annotations
- 2.36.0
+ 1.9.10
@@ -327,70 +304,6 @@
-
- org.jetbrains.kotlin
- kotlin-maven-plugin
- ${kotlin.version}
-
-
- compile
-
- compile
-
-
-
- ${project.basedir}/${main.java.src.dir}
-
-
-
-
- test-compile
-
- test-compile
-
-
-
- ${project.basedir}/${test.java.src.dir}
-
-
-
-
-
- 1.8
-
- -Xjvm-default=all
-
-
-
-
- maven-compiler-plugin
-
-
-
- default-compile
- none
-
-
-
- default-testCompile
- none
-
-
- java-compile
- compile
-
- compile
-
-
-
- java-test-compile
- test-compile
-
- testCompile
-
-
-
-
org.jacoco
jacoco-maven-plugin
@@ -631,7 +544,6 @@
-
maven-compiler-plugin
diff --git a/src/main/java/com/google/genai/ApiClient.java b/src/main/java/com/google/genai/ApiClient.java
index f763457f626..0e5bbc384df 100644
--- a/src/main/java/com/google/genai/ApiClient.java
+++ b/src/main/java/com/google/genai/ApiClient.java
@@ -26,10 +26,6 @@
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.genai.errors.GenAiIOException;
-// interactions:strip_begin
-import com.google.genai.interactions.core.VertexInfo;
-import com.google.genai.interactions.core.http.HttpClient;
-// interactions:strip_end
import com.google.genai.types.ClientOptions;
import com.google.genai.types.HttpOptions;
import com.google.genai.types.HttpRetryOptions;
@@ -81,9 +77,6 @@ public abstract class ApiClient implements AutoCloseable {
HttpOptions httpOptions;
final boolean vertexAI;
final Optional clientOptions;
- // interactions:strip_begin
- final com.google.genai.interactions.core.ClientOptions interactionsClientOptions;
- // interactions:strip_end
final Optional customBaseUrl;
// For Google AI APIs
final Optional apiKey;
@@ -127,9 +120,6 @@ protected ApiClient(
}
this.httpClient = createHttpClient(httpOptions, clientOptions);
- // interactions:strip_begin
- this.interactionsClientOptions = createInteractionsClientOptions();
- // interactions:strip_end
}
ApiClient(
@@ -284,9 +274,6 @@ protected ApiClient(
}
this.vertexAI = true;
this.httpClient = createHttpClient(httpOptions, clientOptions);
- // interactions:strip_begin
- this.interactionsClientOptions = createInteractionsClientOptions();
- // interactions:strip_end
}
private OkHttpClient createHttpClient(
@@ -377,67 +364,6 @@ private void applyProxyOptions(ProxyOptions proxyOptions, OkHttpClient.Builder b
}
}
- // interactions:strip_begin
- private com.google.genai.interactions.core.ClientOptions createInteractionsClientOptions() {
- HttpClient httpClient =
- // Wrap in a non-closing client so that we can call `.close()` on the client options
- // below without closing twice.
- new NonClosingDelegatingHttpClient(
- new com.google.genai.interactions.client.okhttp.OkHttpClient(this.httpClient));
- if (credentials.isPresent()) {
- httpClient = new GoogleCredentialsHttpClient(httpClient, credentials.get());
- }
-
- // NOTE: We purposefully DO NOT set the following:
- // - `checkJacksonVersionCompatibility`, `jsonMapper`, `sleeper`, `clock`,
- // `responseValidation`, and `queryParams` because the defaults are fine and there are no
- // corresponding fields in
- // the main client.
- // - `timeout` because we override it by passing a custom `OkHttpClient`, which has timeouts
- // configured.
- // - `maxRetries` because we don't wrap in `RetryingHttpClient` because retries are configured
- // on the `OkHttpClient`
- // instead.
- com.google.genai.interactions.core.ClientOptions.Builder builder =
- com.google.genai.interactions.core.ClientOptions.builder()
- .httpClient(httpClient)
- .baseUrl(httpOptions.baseUrl())
- .apiKey(apiKey);
-
- // BEGIN_SDK_PRIVATE_ONLY
- // clientOptions
- // .flatMap(ClientOptions::streamHandlerExecutor)
- // .ifPresent(
- // streamHandlerExecutor -> {
- // com.google.genai.interactions.core.ClientOptions.Builder unused =
- // builder.streamHandlerExecutor(streamHandlerExecutor);
- // });
- // END_SDK_PRIVATE_ONLY
-
- httpOptions
- .apiVersion()
- .ifPresent(
- apiVersion -> {
- com.google.genai.interactions.core.ClientOptions.Builder unused =
- builder.apiVersion(apiVersion);
- });
- if (vertexAI && project.isPresent() && location.isPresent()) {
- com.google.genai.interactions.core.ClientOptions.Builder unused =
- builder.vertexInfo(new VertexInfo(project.get(), location.get()));
- }
- httpOptions
- .headers()
- .ifPresent(
- headers ->
- headers.forEach(
- (name, value) -> {
- com.google.genai.interactions.core.ClientOptions.Builder unused =
- builder.putHeader(name, value);
- }));
- return builder.build();
- }
- // interactions:strip_end
-
/** Builds a HTTP request given the http method, path, and request json string. */
@SuppressWarnings("unchecked")
protected Request buildRequest(
@@ -965,9 +891,6 @@ public void close() {
if (httpClient().cache() != null) {
httpClient().cache().close();
}
- // interactions:strip_begin
- this.interactionsClientOptions.close();
- // interactions:strip_end
} catch (IOException e) {
throw new GenAiIOException("Failed to close the client.", e);
}
diff --git a/src/main/java/com/google/genai/Client.java b/src/main/java/com/google/genai/Client.java
index ad236f80223..763d04507f8 100644
--- a/src/main/java/com/google/genai/Client.java
+++ b/src/main/java/com/google/genai/Client.java
@@ -19,14 +19,8 @@
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.auth.oauth2.GoogleCredentials;
-import com.google.errorprone.annotations.CanIgnoreReturnValue;
-// interactions:strip_begin
-import com.google.genai.interactions.services.async.InteractionServiceAsync;
-import com.google.genai.interactions.services.async.InteractionServiceAsyncImpl;
-import com.google.genai.interactions.services.blocking.InteractionService;
-import com.google.genai.interactions.services.blocking.InteractionServiceImpl;
-// interactions:strip_end
import com.google.common.collect.ImmutableMap;
+import com.google.errorprone.annotations.CanIgnoreReturnValue;
import com.google.genai.types.ClientOptions;
import com.google.genai.types.HttpOptions;
import java.util.Optional;
@@ -50,11 +44,6 @@ public final class Async {
public final AsyncTunings tunings;
public final AsyncFileSearchStores fileSearchStores;
- // interactions:strip_begin
- public final InteractionServiceAsync interactions;
-
- // interactions:strip_end
-
public Async(ApiClient apiClient) {
this.models = new AsyncModels(apiClient);
this.batches = new AsyncBatches(apiClient);
@@ -66,9 +55,6 @@ public Async(ApiClient apiClient) {
this.authTokens = new AsyncTokens(apiClient);
this.tunings = new AsyncTunings(apiClient);
this.fileSearchStores = new AsyncFileSearchStores(apiClient);
- // interactions:strip_begin
- this.interactions = new InteractionServiceAsyncImpl(apiClient.interactionsClientOptions);
- // interactions:strip_end
}
}
@@ -85,11 +71,6 @@ public Async(ApiClient apiClient) {
public final Tunings tunings;
public final FileSearchStores fileSearchStores;
- // interactions:strip_begin
- public final InteractionService interactions;
-
- // interactions:strip_end
-
/** Builder for {@link Client}. */
public static class Builder {
private Optional apiKey = Optional.empty();
@@ -98,8 +79,8 @@ public static class Builder {
private Optional credentials = Optional.empty();
private Optional clientOptions = Optional.empty();
private Optional httpOptions = Optional.empty();
- private Optional enterprise = Optional.empty();
private Optional vertexAI = Optional.empty();
+ private Optional enterprise = Optional.empty();
private Optional debugConfig = Optional.empty();
/** Builds the {@link Client} instance. */
@@ -111,8 +92,8 @@ public Client build() {
credentials,
httpOptions,
clientOptions,
- enterprise,
vertexAI,
+ enterprise,
debugConfig);
}
@@ -173,9 +154,7 @@ public Builder enterprise(boolean enterprise) {
return this;
}
- /** Sets whether to use Vertex AI APIs.
- * When both enterprise and vertexAI are set, and they have different values, an IllegalArgumentException will be thrown.
- */
+ /** Sets whether to use Vertex AI APIs. */
@CanIgnoreReturnValue
public Builder vertexAI(boolean vertexAI) {
this.vertexAI = Optional.of(vertexAI);
@@ -208,8 +187,8 @@ public Client() {
/* credentials= */ Optional.empty(),
/* httpOptions= */ Optional.empty(),
/* clientOptions= */ Optional.empty(),
- /* enterprise= */ Optional.empty(),
/* vertexAI= */ Optional.empty(),
+ /* enterprise= */ Optional.empty(),
/* debugConfig= */ Optional.empty());
}
@@ -239,8 +218,8 @@ private Client(
Optional credentials,
Optional httpOptions,
Optional clientOptions,
- Optional enterprise,
Optional vertexAI,
+ Optional enterprise,
Optional debugConfig) {
checkNotNull(vertexAI, "vertexAI cannot be null");
checkNotNull(enterprise, "enterprise cannot be null");
@@ -341,18 +320,15 @@ private Client(
authTokens = new Tokens(this.apiClient);
tunings = new Tunings(this.apiClient);
fileSearchStores = new FileSearchStores(this.apiClient);
- // interactions:strip_begin
- interactions = new InteractionServiceImpl(this.apiClient.interactionsClientOptions);
- // interactions:strip_end
}
- /** Returns whether the client is using Gemini Enterprise Agent Platform. */
- public boolean enterprise() {
+ /** Returns whether the client is using Vertex AI APIs. */
+ public boolean vertexAI() {
return apiClient.vertexAI();
}
- /** Returns whether the client is using Vertex AI APIs. */
- public boolean vertexAI() {
+ /** Returns whether the client is using Gemini Enterprise Agent Platform. */
+ public boolean enterprise() {
return apiClient.vertexAI();
}
diff --git a/src/main/java/com/google/genai/GoogleCredentialsHttpClient.java b/src/main/java/com/google/genai/GoogleCredentialsHttpClient.java
deleted file mode 100644
index 99e7e6f2e38..00000000000
--- a/src/main/java/com/google/genai/GoogleCredentialsHttpClient.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright 2026 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.auth.oauth2.GoogleCredentials;
-import com.google.genai.errors.GenAiIOException;
-import com.google.genai.interactions.core.RequestOptions;
-import com.google.genai.interactions.core.http.HttpClient;
-import com.google.genai.interactions.core.http.HttpRequest;
-import com.google.genai.interactions.core.http.HttpResponse;
-
-import java.io.IOException;
-import java.util.Set;
-import java.util.concurrent.CompletableFuture;
-
-/** A wrapper {@link HttpClient} that adds request headers from {@link GoogleCredentials}. */
-final class GoogleCredentialsHttpClient implements HttpClient {
- private final HttpClient delegate;
- private final GoogleCredentials credentials;
-
- GoogleCredentialsHttpClient(HttpClient delegate, GoogleCredentials credentials) {
- this.delegate = delegate;
- this.credentials = credentials;
- }
-
- @Override
- public HttpResponse execute(HttpRequest request, RequestOptions requestOptions) {
- return delegate.execute(withGoogleCredentialsHeaders(request), requestOptions);
- }
-
- @Override
- public HttpResponse execute(HttpRequest request) {
- return delegate.execute(withGoogleCredentialsHeaders(request));
- }
-
- @Override
- public CompletableFuture executeAsync(HttpRequest request, RequestOptions requestOptions) {
- return CompletableFuture.supplyAsync(() -> withGoogleCredentialsHeaders(request))
- .thenCompose(newRequest -> delegate.executeAsync(newRequest, requestOptions));
- }
-
- @Override
- public CompletableFuture executeAsync(HttpRequest request) {
- return CompletableFuture.supplyAsync(() -> withGoogleCredentialsHeaders(request))
- .thenCompose(delegate::executeAsync);
- }
-
- private HttpRequest withGoogleCredentialsHeaders(HttpRequest request) {
- Set headerNames = request.headers().names();
- if (headerNames.contains("Authorization") || headerNames.contains("x-goog-api-key")) {
- return request;
- }
-
- try {
- credentials.refreshIfExpired();
- } catch (IOException e) {
- throw new GenAiIOException("Failed to refresh credentials.", e);
- }
-
- String accessToken = credentials.getAccessToken().getTokenValue();
- HttpRequest.Builder builder = request.toBuilder().putHeader("Authorization", "Bearer " + accessToken);
- if (credentials.getQuotaProjectId() != null && !headerNames.contains("x-goog-user-project")) {
- builder = builder.putHeader("x-goog-user-project", credentials.getQuotaProjectId());
- }
- return builder.build();
- }
-
- @Override
- public void close() {
- delegate.close();
- }
-}
-
diff --git a/src/main/java/com/google/genai/NonClosingDelegatingHttpClient.java b/src/main/java/com/google/genai/NonClosingDelegatingHttpClient.java
deleted file mode 100644
index 305e553a8ee..00000000000
--- a/src/main/java/com/google/genai/NonClosingDelegatingHttpClient.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright 2026 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.genai.interactions.core.RequestOptions;
-import com.google.genai.interactions.core.http.HttpClient;
-import com.google.genai.interactions.core.http.HttpRequest;
-import com.google.genai.interactions.core.http.HttpResponse;
-
-import java.util.concurrent.CompletableFuture;
-
-/**
- * A wrapper {@link HttpClient} that does not close its delegate when the wrapper is closed.
- *
- * This is used to pass the client to other classes that may try to close it, but we don't want them to because we
- * want to retain ownership of the client.
- */
-final class NonClosingDelegatingHttpClient implements HttpClient {
- private final HttpClient delegate;
-
- NonClosingDelegatingHttpClient(HttpClient delegate) {
- this.delegate = delegate;
- }
-
- @Override
- public HttpResponse execute(HttpRequest request, RequestOptions requestOptions) {
- return delegate.execute(request, requestOptions);
- }
-
- @Override
- public HttpResponse execute(HttpRequest request) {
- return delegate.execute(request);
- }
-
- @Override
- public CompletableFuture executeAsync(HttpRequest request, RequestOptions requestOptions) {
- return delegate.executeAsync(request, requestOptions);
- }
-
- @Override
- public CompletableFuture executeAsync(HttpRequest request) {
- return delegate.executeAsync(request);
- }
-
- @Override
- public void close() {
- // Purposefully empty.
- }
-}
diff --git a/src/main/java/com/google/genai/interactions/client/GeminiNextGenApiClient.kt b/src/main/java/com/google/genai/interactions/client/GeminiNextGenApiClient.kt
deleted file mode 100644
index 3927f33e594..00000000000
--- a/src/main/java/com/google/genai/interactions/client/GeminiNextGenApiClient.kt
+++ /dev/null
@@ -1,93 +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
-*
-* http://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.
-*/
-
-// File generated from our OpenAPI spec by Stainless.
-
-package com.google.genai.interactions.client
-
-import com.google.genai.interactions.core.ClientOptions
-import com.google.genai.interactions.services.blocking.InteractionService
-import java.util.function.Consumer
-
-/**
- * A client for interacting with the Gemini Next Gen API REST API synchronously. You can also switch
- * to asynchronous execution via the [async] method.
- *
- * This client performs best when you create a single instance and reuse it for all interactions
- * with the REST API. This is because each client holds its own connection pool and thread pools.
- * Reusing connections and threads reduces latency and saves memory. The client also handles rate
- * limiting per client. This means that creating and using multiple instances at the same time will
- * not respect rate limits.
- *
- * The threads and connections that are held will be released automatically if they remain idle. But
- * if you are writing an application that needs to aggressively release unused resources, then you
- * may call [close].
- */
-interface GeminiNextGenApiClient {
-
- /**
- * Returns a version of this client that uses asynchronous execution.
- *
- * The returned client shares its resources, like its connection pool and thread pools, with
- * this client.
- */
- fun async(): GeminiNextGenApiClientAsync
-
- /**
- * Returns a view of this service that provides access to raw HTTP responses for each method.
- */
- fun withRawResponse(): WithRawResponse
-
- /**
- * Returns a view of this service with the given option modifications applied.
- *
- * The original service is not modified.
- */
- fun withOptions(modifier: Consumer): GeminiNextGenApiClient
-
- fun interactions(): InteractionService
-
- /**
- * Closes this client, relinquishing any underlying resources.
- *
- * This is purposefully not inherited from [AutoCloseable] because the client is long-lived and
- * usually should not be synchronously closed via try-with-resources.
- *
- * It's also usually not necessary to call this method at all. the default HTTP client
- * automatically releases threads and connections if they remain idle, but if you are writing an
- * application that needs to aggressively release unused resources, then you may call this
- * method.
- */
- fun close()
-
- /**
- * A view of [GeminiNextGenApiClient] that provides access to raw HTTP responses for each
- * method.
- */
- interface WithRawResponse {
-
- /**
- * Returns a view of this service with the given option modifications applied.
- *
- * The original service is not modified.
- */
- fun withOptions(
- modifier: Consumer
- ): GeminiNextGenApiClient.WithRawResponse
-
- fun interactions(): InteractionService.WithRawResponse
- }
-}
diff --git a/src/main/java/com/google/genai/interactions/client/GeminiNextGenApiClientAsync.kt b/src/main/java/com/google/genai/interactions/client/GeminiNextGenApiClientAsync.kt
deleted file mode 100644
index 458d18e858c..00000000000
--- a/src/main/java/com/google/genai/interactions/client/GeminiNextGenApiClientAsync.kt
+++ /dev/null
@@ -1,93 +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
-*
-* http://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.
-*/
-
-// File generated from our OpenAPI spec by Stainless.
-
-package com.google.genai.interactions.client
-
-import com.google.genai.interactions.core.ClientOptions
-import com.google.genai.interactions.services.async.InteractionServiceAsync
-import java.util.function.Consumer
-
-/**
- * A client for interacting with the Gemini Next Gen API REST API asynchronously. You can also
- * switch to synchronous execution via the [sync] method.
- *
- * This client performs best when you create a single instance and reuse it for all interactions
- * with the REST API. This is because each client holds its own connection pool and thread pools.
- * Reusing connections and threads reduces latency and saves memory. The client also handles rate
- * limiting per client. This means that creating and using multiple instances at the same time will
- * not respect rate limits.
- *
- * The threads and connections that are held will be released automatically if they remain idle. But
- * if you are writing an application that needs to aggressively release unused resources, then you
- * may call [close].
- */
-interface GeminiNextGenApiClientAsync {
-
- /**
- * Returns a version of this client that uses synchronous execution.
- *
- * The returned client shares its resources, like its connection pool and thread pools, with
- * this client.
- */
- fun sync(): GeminiNextGenApiClient
-
- /**
- * Returns a view of this service that provides access to raw HTTP responses for each method.
- */
- fun withRawResponse(): WithRawResponse
-
- /**
- * Returns a view of this service with the given option modifications applied.
- *
- * The original service is not modified.
- */
- fun withOptions(modifier: Consumer): GeminiNextGenApiClientAsync
-
- fun interactions(): InteractionServiceAsync
-
- /**
- * Closes this client, relinquishing any underlying resources.
- *
- * This is purposefully not inherited from [AutoCloseable] because the client is long-lived and
- * usually should not be synchronously closed via try-with-resources.
- *
- * It's also usually not necessary to call this method at all. the default HTTP client
- * automatically releases threads and connections if they remain idle, but if you are writing an
- * application that needs to aggressively release unused resources, then you may call this
- * method.
- */
- fun close()
-
- /**
- * A view of [GeminiNextGenApiClientAsync] that provides access to raw HTTP responses for each
- * method.
- */
- interface WithRawResponse {
-
- /**
- * Returns a view of this service with the given option modifications applied.
- *
- * The original service is not modified.
- */
- fun withOptions(
- modifier: Consumer
- ): GeminiNextGenApiClientAsync.WithRawResponse
-
- fun interactions(): InteractionServiceAsync.WithRawResponse
- }
-}
diff --git a/src/main/java/com/google/genai/interactions/client/GeminiNextGenApiClientAsyncImpl.kt b/src/main/java/com/google/genai/interactions/client/GeminiNextGenApiClientAsyncImpl.kt
deleted file mode 100644
index a82a5d38900..00000000000
--- a/src/main/java/com/google/genai/interactions/client/GeminiNextGenApiClientAsyncImpl.kt
+++ /dev/null
@@ -1,78 +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
-*
-* http://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.
-*/
-
-// File generated from our OpenAPI spec by Stainless.
-
-package com.google.genai.interactions.client
-
-import com.google.genai.interactions.core.ClientOptions
-import com.google.genai.interactions.core.getPackageVersion
-import com.google.genai.interactions.services.async.InteractionServiceAsync
-import com.google.genai.interactions.services.async.InteractionServiceAsyncImpl
-import java.util.function.Consumer
-
-class GeminiNextGenApiClientAsyncImpl(private val clientOptions: ClientOptions) :
- GeminiNextGenApiClientAsync {
-
- private val clientOptionsWithUserAgent =
- if (clientOptions.headers.names().contains("User-Agent")) clientOptions
- else
- clientOptions
- .toBuilder()
- .putHeader("User-Agent", "${javaClass.simpleName}/Java ${getPackageVersion()}")
- .build()
-
- // Pass the original clientOptions so that this client sets its own User-Agent.
- private val sync: GeminiNextGenApiClient by lazy { GeminiNextGenApiClientImpl(clientOptions) }
-
- private val withRawResponse: GeminiNextGenApiClientAsync.WithRawResponse by lazy {
- WithRawResponseImpl(clientOptions)
- }
-
- private val interactions: InteractionServiceAsync by lazy {
- InteractionServiceAsyncImpl(clientOptionsWithUserAgent)
- }
-
- override fun sync(): GeminiNextGenApiClient = sync
-
- override fun withRawResponse(): GeminiNextGenApiClientAsync.WithRawResponse = withRawResponse
-
- override fun withOptions(
- modifier: Consumer
- ): GeminiNextGenApiClientAsync =
- GeminiNextGenApiClientAsyncImpl(clientOptions.toBuilder().apply(modifier::accept).build())
-
- override fun interactions(): InteractionServiceAsync = interactions
-
- override fun close() = clientOptions.close()
-
- class WithRawResponseImpl internal constructor(private val clientOptions: ClientOptions) :
- GeminiNextGenApiClientAsync.WithRawResponse {
-
- private val interactions: InteractionServiceAsync.WithRawResponse by lazy {
- InteractionServiceAsyncImpl.WithRawResponseImpl(clientOptions)
- }
-
- override fun withOptions(
- modifier: Consumer
- ): GeminiNextGenApiClientAsync.WithRawResponse =
- GeminiNextGenApiClientAsyncImpl.WithRawResponseImpl(
- clientOptions.toBuilder().apply(modifier::accept).build()
- )
-
- override fun interactions(): InteractionServiceAsync.WithRawResponse = interactions
- }
-}
diff --git a/src/main/java/com/google/genai/interactions/client/GeminiNextGenApiClientImpl.kt b/src/main/java/com/google/genai/interactions/client/GeminiNextGenApiClientImpl.kt
deleted file mode 100644
index a2c3de26ac5..00000000000
--- a/src/main/java/com/google/genai/interactions/client/GeminiNextGenApiClientImpl.kt
+++ /dev/null
@@ -1,78 +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
-*
-* http://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.
-*/
-
-// File generated from our OpenAPI spec by Stainless.
-
-package com.google.genai.interactions.client
-
-import com.google.genai.interactions.core.ClientOptions
-import com.google.genai.interactions.core.getPackageVersion
-import com.google.genai.interactions.services.blocking.InteractionService
-import com.google.genai.interactions.services.blocking.InteractionServiceImpl
-import java.util.function.Consumer
-
-class GeminiNextGenApiClientImpl(private val clientOptions: ClientOptions) :
- GeminiNextGenApiClient {
-
- private val clientOptionsWithUserAgent =
- if (clientOptions.headers.names().contains("User-Agent")) clientOptions
- else
- clientOptions
- .toBuilder()
- .putHeader("User-Agent", "${javaClass.simpleName}/Java ${getPackageVersion()}")
- .build()
-
- // Pass the original clientOptions so that this client sets its own User-Agent.
- private val async: GeminiNextGenApiClientAsync by lazy {
- GeminiNextGenApiClientAsyncImpl(clientOptions)
- }
-
- private val withRawResponse: GeminiNextGenApiClient.WithRawResponse by lazy {
- WithRawResponseImpl(clientOptions)
- }
-
- private val interactions: InteractionService by lazy {
- InteractionServiceImpl(clientOptionsWithUserAgent)
- }
-
- override fun async(): GeminiNextGenApiClientAsync = async
-
- override fun withRawResponse(): GeminiNextGenApiClient.WithRawResponse = withRawResponse
-
- override fun withOptions(modifier: Consumer): GeminiNextGenApiClient =
- GeminiNextGenApiClientImpl(clientOptions.toBuilder().apply(modifier::accept).build())
-
- override fun interactions(): InteractionService = interactions
-
- override fun close() = clientOptions.close()
-
- class WithRawResponseImpl internal constructor(private val clientOptions: ClientOptions) :
- GeminiNextGenApiClient.WithRawResponse {
-
- private val interactions: InteractionService.WithRawResponse by lazy {
- InteractionServiceImpl.WithRawResponseImpl(clientOptions)
- }
-
- override fun withOptions(
- modifier: Consumer
- ): GeminiNextGenApiClient.WithRawResponse =
- GeminiNextGenApiClientImpl.WithRawResponseImpl(
- clientOptions.toBuilder().apply(modifier::accept).build()
- )
-
- override fun interactions(): InteractionService.WithRawResponse = interactions
- }
-}
diff --git a/src/main/java/com/google/genai/interactions/client/okhttp/GeminiNextGenApiOkHttpClient.kt b/src/main/java/com/google/genai/interactions/client/okhttp/GeminiNextGenApiOkHttpClient.kt
deleted file mode 100644
index 4e879f382d6..00000000000
--- a/src/main/java/com/google/genai/interactions/client/okhttp/GeminiNextGenApiOkHttpClient.kt
+++ /dev/null
@@ -1,408 +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
-*
-* http://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.
-*/
-
-// File generated from our OpenAPI spec by Stainless.
-
-package com.google.genai.interactions.client.okhttp
-
-import com.fasterxml.jackson.databind.json.JsonMapper
-import com.google.genai.interactions.client.GeminiNextGenApiClient
-import com.google.genai.interactions.client.GeminiNextGenApiClientImpl
-import com.google.genai.interactions.core.ClientOptions
-import com.google.genai.interactions.core.Sleeper
-import com.google.genai.interactions.core.Timeout
-import com.google.genai.interactions.core.http.AsyncStreamResponse
-import com.google.genai.interactions.core.http.Headers
-import com.google.genai.interactions.core.http.HttpClient
-import com.google.genai.interactions.core.http.QueryParams
-import com.google.genai.interactions.core.jsonMapper
-import java.net.Proxy
-import java.time.Clock
-import java.time.Duration
-import java.util.Optional
-import java.util.concurrent.Executor
-import java.util.concurrent.ExecutorService
-import javax.net.ssl.HostnameVerifier
-import javax.net.ssl.SSLSocketFactory
-import javax.net.ssl.X509TrustManager
-import kotlin.jvm.optionals.getOrNull
-
-/**
- * A class that allows building an instance of [GeminiNextGenApiClient] with [OkHttpClient] as the
- * underlying [HttpClient].
- */
-class GeminiNextGenApiOkHttpClient private constructor() {
-
- companion object {
-
- /** Returns a mutable builder for constructing an instance of [GeminiNextGenApiClient]. */
- @JvmStatic fun builder() = Builder()
-
- /**
- * Returns a client configured using system properties and environment variables.
- *
- * @see ClientOptions.Builder.fromEnv
- */
- @JvmStatic fun fromEnv(): GeminiNextGenApiClient = builder().fromEnv().build()
- }
-
- /** A builder for [GeminiNextGenApiOkHttpClient]. */
- class Builder internal constructor() {
-
- private var clientOptions: ClientOptions.Builder = ClientOptions.builder()
- private var dispatcherExecutorService: ExecutorService? = null
- private var proxy: Proxy? = null
- private var maxIdleConnections: Int? = null
- private var keepAliveDuration: Duration? = null
- private var sslSocketFactory: SSLSocketFactory? = null
- private var trustManager: X509TrustManager? = null
- private var hostnameVerifier: HostnameVerifier? = null
-
- /**
- * The executor service to use for running HTTP requests.
- *
- * Defaults to OkHttp's
- * [default executor service](https://github.com/square/okhttp/blob/ace792f443b2ffb17974f5c0d1cecdf589309f26/okhttp/src/commonJvmAndroid/kotlin/okhttp3/Dispatcher.kt#L98-L104).
- *
- * This class takes ownership of the executor service and shuts it down when closed.
- */
- fun dispatcherExecutorService(dispatcherExecutorService: ExecutorService?) = apply {
- this.dispatcherExecutorService = dispatcherExecutorService
- }
-
- /**
- * Alias for calling [Builder.dispatcherExecutorService] with
- * `dispatcherExecutorService.orElse(null)`.
- */
- fun dispatcherExecutorService(dispatcherExecutorService: Optional) =
- dispatcherExecutorService(dispatcherExecutorService.getOrNull())
-
- fun proxy(proxy: Proxy?) = apply { this.proxy = proxy }
-
- /** Alias for calling [Builder.proxy] with `proxy.orElse(null)`. */
- fun proxy(proxy: Optional) = proxy(proxy.getOrNull())
-
- /**
- * The maximum number of idle connections kept by the underlying OkHttp connection pool.
- *
- * If this is set, then [keepAliveDuration] must also be set.
- *
- * If unset, then OkHttp's default is used.
- */
- fun maxIdleConnections(maxIdleConnections: Int?) = apply {
- this.maxIdleConnections = maxIdleConnections
- }
-
- /**
- * Alias for [Builder.maxIdleConnections].
- *
- * This unboxed primitive overload exists for backwards compatibility.
- */
- fun maxIdleConnections(maxIdleConnections: Int) =
- maxIdleConnections(maxIdleConnections as Int?)
-
- /**
- * Alias for calling [Builder.maxIdleConnections] with `maxIdleConnections.orElse(null)`.
- */
- fun maxIdleConnections(maxIdleConnections: Optional) =
- maxIdleConnections(maxIdleConnections.getOrNull())
-
- /**
- * The keep-alive duration for idle connections in the underlying OkHttp connection pool.
- *
- * If this is set, then [maxIdleConnections] must also be set.
- *
- * If unset, then OkHttp's default is used.
- */
- fun keepAliveDuration(keepAliveDuration: Duration?) = apply {
- this.keepAliveDuration = keepAliveDuration
- }
-
- /** Alias for calling [Builder.keepAliveDuration] with `keepAliveDuration.orElse(null)`. */
- fun keepAliveDuration(keepAliveDuration: Optional) =
- keepAliveDuration(keepAliveDuration.getOrNull())
-
- /**
- * The socket factory used to secure HTTPS connections.
- *
- * If this is set, then [trustManager] must also be set.
- *
- * If unset, then the system default is used. Most applications should not call this method,
- * and instead use the system default. The default include special optimizations that can be
- * lost if the implementation is modified.
- */
- fun sslSocketFactory(sslSocketFactory: SSLSocketFactory?) = apply {
- this.sslSocketFactory = sslSocketFactory
- }
-
- /** Alias for calling [Builder.sslSocketFactory] with `sslSocketFactory.orElse(null)`. */
- fun sslSocketFactory(sslSocketFactory: Optional) =
- sslSocketFactory(sslSocketFactory.getOrNull())
-
- /**
- * The trust manager used to secure HTTPS connections.
- *
- * If this is set, then [sslSocketFactory] must also be set.
- *
- * If unset, then the system default is used. Most applications should not call this method,
- * and instead use the system default. The default include special optimizations that can be
- * lost if the implementation is modified.
- */
- fun trustManager(trustManager: X509TrustManager?) = apply {
- this.trustManager = trustManager
- }
-
- /** Alias for calling [Builder.trustManager] with `trustManager.orElse(null)`. */
- fun trustManager(trustManager: Optional) =
- trustManager(trustManager.getOrNull())
-
- /**
- * The verifier used to confirm that response certificates apply to requested hostnames for
- * HTTPS connections.
- *
- * If unset, then a default hostname verifier is used.
- */
- fun hostnameVerifier(hostnameVerifier: HostnameVerifier?) = apply {
- this.hostnameVerifier = hostnameVerifier
- }
-
- /** Alias for calling [Builder.hostnameVerifier] with `hostnameVerifier.orElse(null)`. */
- fun hostnameVerifier(hostnameVerifier: Optional) =
- hostnameVerifier(hostnameVerifier.getOrNull())
-
- /**
- * Whether to throw an exception if any of the Jackson versions detected at runtime are
- * incompatible with the SDK's minimum supported Jackson version (2.13.4).
- *
- * Defaults to true. Use extreme caution when disabling this option. There is no guarantee
- * that the SDK will work correctly when using an incompatible Jackson version.
- */
- fun checkJacksonVersionCompatibility(checkJacksonVersionCompatibility: Boolean) = apply {
- clientOptions.checkJacksonVersionCompatibility(checkJacksonVersionCompatibility)
- }
-
- /**
- * The Jackson JSON mapper to use for serializing and deserializing JSON.
- *
- * Defaults to [com.google.genai.interactions.core.jsonMapper]. The default is usually
- * sufficient and rarely needs to be overridden.
- */
- fun jsonMapper(jsonMapper: JsonMapper) = apply { clientOptions.jsonMapper(jsonMapper) }
-
- /**
- * The executor to use for running [AsyncStreamResponse.Handler] callbacks.
- *
- * Defaults to a dedicated cached thread pool.
- *
- * This class takes ownership of the executor and shuts it down, if possible, when closed.
- */
- fun streamHandlerExecutor(streamHandlerExecutor: Executor) = apply {
- clientOptions.streamHandlerExecutor(streamHandlerExecutor)
- }
-
- /**
- * The interface to use for delaying execution, like during retries.
- *
- * This is primarily useful for using fake delays in tests.
- *
- * Defaults to real execution delays.
- *
- * This class takes ownership of the sleeper and closes it when closed.
- */
- fun sleeper(sleeper: Sleeper) = apply { clientOptions.sleeper(sleeper) }
-
- /**
- * The clock to use for operations that require timing, like retries.
- *
- * This is primarily useful for using a fake clock in tests.
- *
- * Defaults to [Clock.systemUTC].
- */
- fun clock(clock: Clock) = apply { clientOptions.clock(clock) }
-
- /**
- * The base URL to use for every request.
- *
- * Defaults to the production environment: `https://generativelanguage.googleapis.com`.
- */
- fun baseUrl(baseUrl: String?) = apply { clientOptions.baseUrl(baseUrl) }
-
- /** Alias for calling [Builder.baseUrl] with `baseUrl.orElse(null)`. */
- fun baseUrl(baseUrl: Optional) = baseUrl(baseUrl.getOrNull())
-
- /**
- * Whether to call `validate` on every response before returning it.
- *
- * Defaults to false, which means the shape of the response will not be validated upfront.
- * Instead, validation will only occur for the parts of the response that are accessed.
- */
- fun responseValidation(responseValidation: Boolean) = apply {
- clientOptions.responseValidation(responseValidation)
- }
-
- /**
- * Sets the maximum time allowed for various parts of an HTTP call's lifecycle, excluding
- * retries.
- *
- * Defaults to [Timeout.default].
- */
- fun timeout(timeout: Timeout) = apply { clientOptions.timeout(timeout) }
-
- /**
- * Sets the maximum time allowed for a complete HTTP call, not including retries.
- *
- * See [Timeout.request] for more details.
- *
- * For fine-grained control, pass a [Timeout] object.
- */
- fun timeout(timeout: Duration) = apply { clientOptions.timeout(timeout) }
-
- /**
- * The maximum number of times to retry failed requests, with a short exponential backoff
- * between requests.
- *
- * Only the following error types are retried:
- * - Connection errors (for example, due to a network connectivity problem)
- * - 408 Request Timeout
- * - 409 Conflict
- * - 429 Rate Limit
- * - 5xx Internal
- *
- * The API may also explicitly instruct the SDK to retry or not retry a request.
- *
- * Defaults to 2.
- */
- fun maxRetries(maxRetries: Int) = apply { clientOptions.maxRetries(maxRetries) }
-
- fun apiKey(apiKey: String?) = apply { clientOptions.apiKey(apiKey) }
-
- /** Alias for calling [Builder.apiKey] with `apiKey.orElse(null)`. */
- fun apiKey(apiKey: Optional) = apiKey(apiKey.getOrNull())
-
- /** Defaults to `"v1beta"`. */
- fun apiVersion(apiVersion: String) = apply { clientOptions.apiVersion(apiVersion) }
-
- fun headers(headers: Headers) = apply { clientOptions.headers(headers) }
-
- fun headers(headers: Map>) = apply {
- clientOptions.headers(headers)
- }
-
- fun putHeader(name: String, value: String) = apply { clientOptions.putHeader(name, value) }
-
- fun putHeaders(name: String, values: Iterable) = apply {
- clientOptions.putHeaders(name, values)
- }
-
- fun putAllHeaders(headers: Headers) = apply { clientOptions.putAllHeaders(headers) }
-
- fun putAllHeaders(headers: Map>) = apply {
- clientOptions.putAllHeaders(headers)
- }
-
- fun replaceHeaders(name: String, value: String) = apply {
- clientOptions.replaceHeaders(name, value)
- }
-
- fun replaceHeaders(name: String, values: Iterable) = apply {
- clientOptions.replaceHeaders(name, values)
- }
-
- fun replaceAllHeaders(headers: Headers) = apply { clientOptions.replaceAllHeaders(headers) }
-
- fun replaceAllHeaders(headers: Map>) = apply {
- clientOptions.replaceAllHeaders(headers)
- }
-
- fun removeHeaders(name: String) = apply { clientOptions.removeHeaders(name) }
-
- fun removeAllHeaders(names: Set) = apply { clientOptions.removeAllHeaders(names) }
-
- fun queryParams(queryParams: QueryParams) = apply { clientOptions.queryParams(queryParams) }
-
- fun queryParams(queryParams: Map>) = apply {
- clientOptions.queryParams(queryParams)
- }
-
- fun putQueryParam(key: String, value: String) = apply {
- clientOptions.putQueryParam(key, value)
- }
-
- fun putQueryParams(key: String, values: Iterable) = apply {
- clientOptions.putQueryParams(key, values)
- }
-
- fun putAllQueryParams(queryParams: QueryParams) = apply {
- clientOptions.putAllQueryParams(queryParams)
- }
-
- fun putAllQueryParams(queryParams: Map>) = apply {
- clientOptions.putAllQueryParams(queryParams)
- }
-
- fun replaceQueryParams(key: String, value: String) = apply {
- clientOptions.replaceQueryParams(key, value)
- }
-
- fun replaceQueryParams(key: String, values: Iterable) = apply {
- clientOptions.replaceQueryParams(key, values)
- }
-
- fun replaceAllQueryParams(queryParams: QueryParams) = apply {
- clientOptions.replaceAllQueryParams(queryParams)
- }
-
- fun replaceAllQueryParams(queryParams: Map>) = apply {
- clientOptions.replaceAllQueryParams(queryParams)
- }
-
- fun removeQueryParams(key: String) = apply { clientOptions.removeQueryParams(key) }
-
- fun removeAllQueryParams(keys: Set) = apply {
- clientOptions.removeAllQueryParams(keys)
- }
-
- /**
- * Updates configuration using system properties and environment variables.
- *
- * @see ClientOptions.Builder.fromEnv
- */
- fun fromEnv() = apply { clientOptions.fromEnv() }
-
- /**
- * Returns an immutable instance of [GeminiNextGenApiClient].
- *
- * Further updates to this [Builder] will not mutate the returned instance.
- */
- fun build(): GeminiNextGenApiClient =
- GeminiNextGenApiClientImpl(
- clientOptions
- .httpClient(
- OkHttpClient.builder()
- .timeout(clientOptions.timeout())
- .proxy(proxy)
- .maxIdleConnections(maxIdleConnections)
- .keepAliveDuration(keepAliveDuration)
- .dispatcherExecutorService(dispatcherExecutorService)
- .sslSocketFactory(sslSocketFactory)
- .trustManager(trustManager)
- .hostnameVerifier(hostnameVerifier)
- .build()
- )
- .build()
- )
- }
-}
diff --git a/src/main/java/com/google/genai/interactions/client/okhttp/GeminiNextGenApiOkHttpClientAsync.kt b/src/main/java/com/google/genai/interactions/client/okhttp/GeminiNextGenApiOkHttpClientAsync.kt
deleted file mode 100644
index 987c035a5c5..00000000000
--- a/src/main/java/com/google/genai/interactions/client/okhttp/GeminiNextGenApiOkHttpClientAsync.kt
+++ /dev/null
@@ -1,410 +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
-*
-* http://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.
-*/
-
-// File generated from our OpenAPI spec by Stainless.
-
-package com.google.genai.interactions.client.okhttp
-
-import com.fasterxml.jackson.databind.json.JsonMapper
-import com.google.genai.interactions.client.GeminiNextGenApiClientAsync
-import com.google.genai.interactions.client.GeminiNextGenApiClientAsyncImpl
-import com.google.genai.interactions.core.ClientOptions
-import com.google.genai.interactions.core.Sleeper
-import com.google.genai.interactions.core.Timeout
-import com.google.genai.interactions.core.http.AsyncStreamResponse
-import com.google.genai.interactions.core.http.Headers
-import com.google.genai.interactions.core.http.HttpClient
-import com.google.genai.interactions.core.http.QueryParams
-import com.google.genai.interactions.core.jsonMapper
-import java.net.Proxy
-import java.time.Clock
-import java.time.Duration
-import java.util.Optional
-import java.util.concurrent.Executor
-import java.util.concurrent.ExecutorService
-import javax.net.ssl.HostnameVerifier
-import javax.net.ssl.SSLSocketFactory
-import javax.net.ssl.X509TrustManager
-import kotlin.jvm.optionals.getOrNull
-
-/**
- * A class that allows building an instance of [GeminiNextGenApiClientAsync] with [OkHttpClient] as
- * the underlying [HttpClient].
- */
-class GeminiNextGenApiOkHttpClientAsync private constructor() {
-
- companion object {
-
- /**
- * Returns a mutable builder for constructing an instance of [GeminiNextGenApiClientAsync].
- */
- @JvmStatic fun builder() = Builder()
-
- /**
- * Returns a client configured using system properties and environment variables.
- *
- * @see ClientOptions.Builder.fromEnv
- */
- @JvmStatic fun fromEnv(): GeminiNextGenApiClientAsync = builder().fromEnv().build()
- }
-
- /** A builder for [GeminiNextGenApiOkHttpClientAsync]. */
- class Builder internal constructor() {
-
- private var clientOptions: ClientOptions.Builder = ClientOptions.builder()
- private var dispatcherExecutorService: ExecutorService? = null
- private var proxy: Proxy? = null
- private var maxIdleConnections: Int? = null
- private var keepAliveDuration: Duration? = null
- private var sslSocketFactory: SSLSocketFactory? = null
- private var trustManager: X509TrustManager? = null
- private var hostnameVerifier: HostnameVerifier? = null
-
- /**
- * The executor service to use for running HTTP requests.
- *
- * Defaults to OkHttp's
- * [default executor service](https://github.com/square/okhttp/blob/ace792f443b2ffb17974f5c0d1cecdf589309f26/okhttp/src/commonJvmAndroid/kotlin/okhttp3/Dispatcher.kt#L98-L104).
- *
- * This class takes ownership of the executor service and shuts it down when closed.
- */
- fun dispatcherExecutorService(dispatcherExecutorService: ExecutorService?) = apply {
- this.dispatcherExecutorService = dispatcherExecutorService
- }
-
- /**
- * Alias for calling [Builder.dispatcherExecutorService] with
- * `dispatcherExecutorService.orElse(null)`.
- */
- fun dispatcherExecutorService(dispatcherExecutorService: Optional) =
- dispatcherExecutorService(dispatcherExecutorService.getOrNull())
-
- fun proxy(proxy: Proxy?) = apply { this.proxy = proxy }
-
- /** Alias for calling [Builder.proxy] with `proxy.orElse(null)`. */
- fun proxy(proxy: Optional) = proxy(proxy.getOrNull())
-
- /**
- * The maximum number of idle connections kept by the underlying OkHttp connection pool.
- *
- * If this is set, then [keepAliveDuration] must also be set.
- *
- * If unset, then OkHttp's default is used.
- */
- fun maxIdleConnections(maxIdleConnections: Int?) = apply {
- this.maxIdleConnections = maxIdleConnections
- }
-
- /**
- * Alias for [Builder.maxIdleConnections].
- *
- * This unboxed primitive overload exists for backwards compatibility.
- */
- fun maxIdleConnections(maxIdleConnections: Int) =
- maxIdleConnections(maxIdleConnections as Int?)
-
- /**
- * Alias for calling [Builder.maxIdleConnections] with `maxIdleConnections.orElse(null)`.
- */
- fun maxIdleConnections(maxIdleConnections: Optional) =
- maxIdleConnections(maxIdleConnections.getOrNull())
-
- /**
- * The keep-alive duration for idle connections in the underlying OkHttp connection pool.
- *
- * If this is set, then [maxIdleConnections] must also be set.
- *
- * If unset, then OkHttp's default is used.
- */
- fun keepAliveDuration(keepAliveDuration: Duration?) = apply {
- this.keepAliveDuration = keepAliveDuration
- }
-
- /** Alias for calling [Builder.keepAliveDuration] with `keepAliveDuration.orElse(null)`. */
- fun keepAliveDuration(keepAliveDuration: Optional) =
- keepAliveDuration(keepAliveDuration.getOrNull())
-
- /**
- * The socket factory used to secure HTTPS connections.
- *
- * If this is set, then [trustManager] must also be set.
- *
- * If unset, then the system default is used. Most applications should not call this method,
- * and instead use the system default. The default include special optimizations that can be
- * lost if the implementation is modified.
- */
- fun sslSocketFactory(sslSocketFactory: SSLSocketFactory?) = apply {
- this.sslSocketFactory = sslSocketFactory
- }
-
- /** Alias for calling [Builder.sslSocketFactory] with `sslSocketFactory.orElse(null)`. */
- fun sslSocketFactory(sslSocketFactory: Optional) =
- sslSocketFactory(sslSocketFactory.getOrNull())
-
- /**
- * The trust manager used to secure HTTPS connections.
- *
- * If this is set, then [sslSocketFactory] must also be set.
- *
- * If unset, then the system default is used. Most applications should not call this method,
- * and instead use the system default. The default include special optimizations that can be
- * lost if the implementation is modified.
- */
- fun trustManager(trustManager: X509TrustManager?) = apply {
- this.trustManager = trustManager
- }
-
- /** Alias for calling [Builder.trustManager] with `trustManager.orElse(null)`. */
- fun trustManager(trustManager: Optional) =
- trustManager(trustManager.getOrNull())
-
- /**
- * The verifier used to confirm that response certificates apply to requested hostnames for
- * HTTPS connections.
- *
- * If unset, then a default hostname verifier is used.
- */
- fun hostnameVerifier(hostnameVerifier: HostnameVerifier?) = apply {
- this.hostnameVerifier = hostnameVerifier
- }
-
- /** Alias for calling [Builder.hostnameVerifier] with `hostnameVerifier.orElse(null)`. */
- fun hostnameVerifier(hostnameVerifier: Optional) =
- hostnameVerifier(hostnameVerifier.getOrNull())
-
- /**
- * Whether to throw an exception if any of the Jackson versions detected at runtime are
- * incompatible with the SDK's minimum supported Jackson version (2.13.4).
- *
- * Defaults to true. Use extreme caution when disabling this option. There is no guarantee
- * that the SDK will work correctly when using an incompatible Jackson version.
- */
- fun checkJacksonVersionCompatibility(checkJacksonVersionCompatibility: Boolean) = apply {
- clientOptions.checkJacksonVersionCompatibility(checkJacksonVersionCompatibility)
- }
-
- /**
- * The Jackson JSON mapper to use for serializing and deserializing JSON.
- *
- * Defaults to [com.google.genai.interactions.core.jsonMapper]. The default is usually
- * sufficient and rarely needs to be overridden.
- */
- fun jsonMapper(jsonMapper: JsonMapper) = apply { clientOptions.jsonMapper(jsonMapper) }
-
- /**
- * The executor to use for running [AsyncStreamResponse.Handler] callbacks.
- *
- * Defaults to a dedicated cached thread pool.
- *
- * This class takes ownership of the executor and shuts it down, if possible, when closed.
- */
- fun streamHandlerExecutor(streamHandlerExecutor: Executor) = apply {
- clientOptions.streamHandlerExecutor(streamHandlerExecutor)
- }
-
- /**
- * The interface to use for delaying execution, like during retries.
- *
- * This is primarily useful for using fake delays in tests.
- *
- * Defaults to real execution delays.
- *
- * This class takes ownership of the sleeper and closes it when closed.
- */
- fun sleeper(sleeper: Sleeper) = apply { clientOptions.sleeper(sleeper) }
-
- /**
- * The clock to use for operations that require timing, like retries.
- *
- * This is primarily useful for using a fake clock in tests.
- *
- * Defaults to [Clock.systemUTC].
- */
- fun clock(clock: Clock) = apply { clientOptions.clock(clock) }
-
- /**
- * The base URL to use for every request.
- *
- * Defaults to the production environment: `https://generativelanguage.googleapis.com`.
- */
- fun baseUrl(baseUrl: String?) = apply { clientOptions.baseUrl(baseUrl) }
-
- /** Alias for calling [Builder.baseUrl] with `baseUrl.orElse(null)`. */
- fun baseUrl(baseUrl: Optional) = baseUrl(baseUrl.getOrNull())
-
- /**
- * Whether to call `validate` on every response before returning it.
- *
- * Defaults to false, which means the shape of the response will not be validated upfront.
- * Instead, validation will only occur for the parts of the response that are accessed.
- */
- fun responseValidation(responseValidation: Boolean) = apply {
- clientOptions.responseValidation(responseValidation)
- }
-
- /**
- * Sets the maximum time allowed for various parts of an HTTP call's lifecycle, excluding
- * retries.
- *
- * Defaults to [Timeout.default].
- */
- fun timeout(timeout: Timeout) = apply { clientOptions.timeout(timeout) }
-
- /**
- * Sets the maximum time allowed for a complete HTTP call, not including retries.
- *
- * See [Timeout.request] for more details.
- *
- * For fine-grained control, pass a [Timeout] object.
- */
- fun timeout(timeout: Duration) = apply { clientOptions.timeout(timeout) }
-
- /**
- * The maximum number of times to retry failed requests, with a short exponential backoff
- * between requests.
- *
- * Only the following error types are retried:
- * - Connection errors (for example, due to a network connectivity problem)
- * - 408 Request Timeout
- * - 409 Conflict
- * - 429 Rate Limit
- * - 5xx Internal
- *
- * The API may also explicitly instruct the SDK to retry or not retry a request.
- *
- * Defaults to 2.
- */
- fun maxRetries(maxRetries: Int) = apply { clientOptions.maxRetries(maxRetries) }
-
- fun apiKey(apiKey: String?) = apply { clientOptions.apiKey(apiKey) }
-
- /** Alias for calling [Builder.apiKey] with `apiKey.orElse(null)`. */
- fun apiKey(apiKey: Optional) = apiKey(apiKey.getOrNull())
-
- /** Defaults to `"v1beta"`. */
- fun apiVersion(apiVersion: String) = apply { clientOptions.apiVersion(apiVersion) }
-
- fun headers(headers: Headers) = apply { clientOptions.headers(headers) }
-
- fun headers(headers: Map>) = apply {
- clientOptions.headers(headers)
- }
-
- fun putHeader(name: String, value: String) = apply { clientOptions.putHeader(name, value) }
-
- fun putHeaders(name: String, values: Iterable) = apply {
- clientOptions.putHeaders(name, values)
- }
-
- fun putAllHeaders(headers: Headers) = apply { clientOptions.putAllHeaders(headers) }
-
- fun putAllHeaders(headers: Map>) = apply {
- clientOptions.putAllHeaders(headers)
- }
-
- fun replaceHeaders(name: String, value: String) = apply {
- clientOptions.replaceHeaders(name, value)
- }
-
- fun replaceHeaders(name: String, values: Iterable) = apply {
- clientOptions.replaceHeaders(name, values)
- }
-
- fun replaceAllHeaders(headers: Headers) = apply { clientOptions.replaceAllHeaders(headers) }
-
- fun replaceAllHeaders(headers: Map>) = apply {
- clientOptions.replaceAllHeaders(headers)
- }
-
- fun removeHeaders(name: String) = apply { clientOptions.removeHeaders(name) }
-
- fun removeAllHeaders(names: Set) = apply { clientOptions.removeAllHeaders(names) }
-
- fun queryParams(queryParams: QueryParams) = apply { clientOptions.queryParams(queryParams) }
-
- fun queryParams(queryParams: Map>) = apply {
- clientOptions.queryParams(queryParams)
- }
-
- fun putQueryParam(key: String, value: String) = apply {
- clientOptions.putQueryParam(key, value)
- }
-
- fun putQueryParams(key: String, values: Iterable) = apply {
- clientOptions.putQueryParams(key, values)
- }
-
- fun putAllQueryParams(queryParams: QueryParams) = apply {
- clientOptions.putAllQueryParams(queryParams)
- }
-
- fun putAllQueryParams(queryParams: Map>) = apply {
- clientOptions.putAllQueryParams(queryParams)
- }
-
- fun replaceQueryParams(key: String, value: String) = apply {
- clientOptions.replaceQueryParams(key, value)
- }
-
- fun replaceQueryParams(key: String, values: Iterable) = apply {
- clientOptions.replaceQueryParams(key, values)
- }
-
- fun replaceAllQueryParams(queryParams: QueryParams) = apply {
- clientOptions.replaceAllQueryParams(queryParams)
- }
-
- fun replaceAllQueryParams(queryParams: Map>) = apply {
- clientOptions.replaceAllQueryParams(queryParams)
- }
-
- fun removeQueryParams(key: String) = apply { clientOptions.removeQueryParams(key) }
-
- fun removeAllQueryParams(keys: Set) = apply {
- clientOptions.removeAllQueryParams(keys)
- }
-
- /**
- * Updates configuration using system properties and environment variables.
- *
- * @see ClientOptions.Builder.fromEnv
- */
- fun fromEnv() = apply { clientOptions.fromEnv() }
-
- /**
- * Returns an immutable instance of [GeminiNextGenApiClientAsync].
- *
- * Further updates to this [Builder] will not mutate the returned instance.
- */
- fun build(): GeminiNextGenApiClientAsync =
- GeminiNextGenApiClientAsyncImpl(
- clientOptions
- .httpClient(
- OkHttpClient.builder()
- .timeout(clientOptions.timeout())
- .proxy(proxy)
- .maxIdleConnections(maxIdleConnections)
- .keepAliveDuration(keepAliveDuration)
- .dispatcherExecutorService(dispatcherExecutorService)
- .sslSocketFactory(sslSocketFactory)
- .trustManager(trustManager)
- .hostnameVerifier(hostnameVerifier)
- .build()
- )
- .build()
- )
- }
-}
diff --git a/src/main/java/com/google/genai/interactions/client/okhttp/OkHttpClient.kt b/src/main/java/com/google/genai/interactions/client/okhttp/OkHttpClient.kt
deleted file mode 100644
index fc046ccaf5c..00000000000
--- a/src/main/java/com/google/genai/interactions/client/okhttp/OkHttpClient.kt
+++ /dev/null
@@ -1,308 +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
-*
-* http://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.interactions.client.okhttp
-
-import com.google.genai.interactions.core.RequestOptions
-import com.google.genai.interactions.core.Timeout
-import com.google.genai.interactions.core.http.Headers
-import com.google.genai.interactions.core.http.HttpClient
-import com.google.genai.interactions.core.http.HttpMethod
-import com.google.genai.interactions.core.http.HttpRequest
-import com.google.genai.interactions.core.http.HttpRequestBody
-import com.google.genai.interactions.core.http.HttpResponse
-import com.google.genai.interactions.errors.GeminiNextGenApiIoException
-import java.io.IOException
-import java.io.InputStream
-import java.net.Proxy
-import java.time.Duration
-import java.util.concurrent.CancellationException
-import java.util.concurrent.CompletableFuture
-import java.util.concurrent.ExecutorService
-import java.util.concurrent.TimeUnit
-import javax.net.ssl.HostnameVerifier
-import javax.net.ssl.SSLSocketFactory
-import javax.net.ssl.X509TrustManager
-import okhttp3.Call
-import okhttp3.Callback
-import okhttp3.ConnectionPool
-import okhttp3.Dispatcher
-import okhttp3.HttpUrl.Companion.toHttpUrl
-import okhttp3.MediaType
-import okhttp3.MediaType.Companion.toMediaType
-import okhttp3.Request
-import okhttp3.RequestBody
-import okhttp3.RequestBody.Companion.toRequestBody
-import okhttp3.Response
-import okhttp3.logging.HttpLoggingInterceptor
-import okio.BufferedSink
-
-class OkHttpClient constructor(@JvmSynthetic internal val okHttpClient: okhttp3.OkHttpClient) :
- HttpClient {
-
- override fun execute(request: HttpRequest, requestOptions: RequestOptions): HttpResponse {
- val call = newCall(request, requestOptions)
-
- return try {
- call.execute().toResponse()
- } catch (e: IOException) {
- throw GeminiNextGenApiIoException("Request failed", e)
- } finally {
- request.body?.close()
- }
- }
-
- override fun executeAsync(
- request: HttpRequest,
- requestOptions: RequestOptions,
- ): CompletableFuture {
- val future = CompletableFuture()
-
- val call = newCall(request, requestOptions)
- call.enqueue(
- object : Callback {
- override fun onResponse(call: Call, response: Response) {
- future.complete(response.toResponse())
- }
-
- override fun onFailure(call: Call, e: IOException) {
- future.completeExceptionally(GeminiNextGenApiIoException("Request failed", e))
- }
- }
- )
-
- future.whenComplete { _, e ->
- if (e is CancellationException) {
- call.cancel()
- }
- request.body?.close()
- }
-
- return future
- }
-
- override fun close() {
- okHttpClient.dispatcher.executorService.shutdown()
- okHttpClient.connectionPool.evictAll()
- okHttpClient.cache?.close()
- }
-
- private fun newCall(request: HttpRequest, requestOptions: RequestOptions): Call {
- val clientBuilder = okHttpClient.newBuilder()
-
- val logLevel =
- when (System.getenv("GEMINI_NEXT_GEN_API_LOG")?.lowercase()) {
- "info" -> HttpLoggingInterceptor.Level.BASIC
- "debug" -> HttpLoggingInterceptor.Level.BODY
- else -> null
- }
- if (logLevel != null) {
- clientBuilder.addNetworkInterceptor(
- HttpLoggingInterceptor().setLevel(logLevel).apply { redactHeader("x-goog-api-key") }
- )
- }
-
- requestOptions.timeout?.let {
- clientBuilder
- .connectTimeout(it.connect())
- .readTimeout(it.read())
- .writeTimeout(it.write())
- .callTimeout(it.request())
- }
-
- val client = clientBuilder.build()
- return client.newCall(request.toRequest(client))
- }
-
- private fun HttpRequest.toRequest(client: okhttp3.OkHttpClient): Request {
- var body: RequestBody? = body?.toRequestBody()
- if (body == null && requiresBody(method)) {
- body = "".toRequestBody()
- }
-
- val builder = Request.Builder().url(toUrl()).method(method.name, body)
- headers.names().forEach { name ->
- headers.values(name).forEach { builder.addHeader(name, it) }
- }
-
- return builder.build()
- }
-
- /** `OkHttpClient` always requires a request body for some methods. */
- private fun requiresBody(method: HttpMethod): Boolean =
- when (method) {
- HttpMethod.POST,
- HttpMethod.PUT,
- HttpMethod.PATCH -> true
- else -> false
- }
-
- private fun HttpRequest.toUrl(): String {
- val builder = baseUrl.toHttpUrl().newBuilder()
- pathSegments.forEach(builder::addPathSegment)
- queryParams.keys().forEach { key ->
- queryParams.values(key).forEach { builder.addQueryParameter(key, it) }
- }
-
- return builder.toString()
- }
-
- private fun HttpRequestBody.toRequestBody(): RequestBody {
- val mediaType = contentType()?.toMediaType()
- val length = contentLength()
-
- return object : RequestBody() {
- override fun contentType(): MediaType? = mediaType
-
- override fun contentLength(): Long = length
-
- override fun isOneShot(): Boolean = !repeatable()
-
- override fun writeTo(sink: BufferedSink) = writeTo(sink.outputStream())
- }
- }
-
- private fun Response.toResponse(): HttpResponse {
- val headers = headers.toHeaders()
-
- return object : HttpResponse {
- override fun statusCode(): Int = code
-
- override fun headers(): Headers = headers
-
- override fun body(): InputStream = body!!.byteStream()
-
- override fun close() = body!!.close()
- }
- }
-
- private fun okhttp3.Headers.toHeaders(): Headers {
- val headersBuilder = Headers.builder()
- for (i in 0 until size) {
- headersBuilder.put(name(i), value(i))
- }
- return headersBuilder.build()
- }
-
- companion object {
- @JvmStatic fun builder() = Builder()
- }
-
- class Builder internal constructor() {
-
- private var timeout: Timeout = Timeout.default()
- private var proxy: Proxy? = null
- private var maxIdleConnections: Int? = null
- private var keepAliveDuration: Duration? = null
- private var dispatcherExecutorService: ExecutorService? = null
- private var sslSocketFactory: SSLSocketFactory? = null
- private var trustManager: X509TrustManager? = null
- private var hostnameVerifier: HostnameVerifier? = null
-
- fun timeout(timeout: Timeout) = apply { this.timeout = timeout }
-
- fun timeout(timeout: Duration) = timeout(Timeout.builder().request(timeout).build())
-
- fun proxy(proxy: Proxy?) = apply { this.proxy = proxy }
-
- /**
- * Sets the maximum number of idle connections kept by the underlying [ConnectionPool].
- *
- * If this is set, then [keepAliveDuration] must also be set.
- *
- * If unset, then OkHttp's default is used.
- */
- fun maxIdleConnections(maxIdleConnections: Int?) = apply {
- this.maxIdleConnections = maxIdleConnections
- }
-
- /**
- * Sets the keep-alive duration for idle connections in the underlying [ConnectionPool].
- *
- * If this is set, then [maxIdleConnections] must also be set.
- *
- * If unset, then OkHttp's default is used.
- */
- fun keepAliveDuration(keepAliveDuration: Duration?) = apply {
- this.keepAliveDuration = keepAliveDuration
- }
-
- fun dispatcherExecutorService(dispatcherExecutorService: ExecutorService?) = apply {
- this.dispatcherExecutorService = dispatcherExecutorService
- }
-
- fun sslSocketFactory(sslSocketFactory: SSLSocketFactory?) = apply {
- this.sslSocketFactory = sslSocketFactory
- }
-
- fun trustManager(trustManager: X509TrustManager?) = apply {
- this.trustManager = trustManager
- }
-
- fun hostnameVerifier(hostnameVerifier: HostnameVerifier?) = apply {
- this.hostnameVerifier = hostnameVerifier
- }
-
- fun build(): OkHttpClient =
- OkHttpClient(
- okhttp3.OkHttpClient.Builder()
- // `RetryingHttpClient` handles retries if the user enabled them.
- .retryOnConnectionFailure(false)
- .connectTimeout(timeout.connect())
- .readTimeout(timeout.read())
- .writeTimeout(timeout.write())
- .callTimeout(timeout.request())
- .proxy(proxy)
- .apply {
- dispatcherExecutorService?.let { dispatcher(Dispatcher(it)) }
-
- val maxIdleConnections = maxIdleConnections
- val keepAliveDuration = keepAliveDuration
- if (maxIdleConnections != null && keepAliveDuration != null) {
- connectionPool(
- ConnectionPool(
- maxIdleConnections,
- keepAliveDuration.toNanos(),
- TimeUnit.NANOSECONDS,
- )
- )
- } else {
- check((maxIdleConnections != null) == (keepAliveDuration != null)) {
- "Both or none of `maxIdleConnections` and `keepAliveDuration` must be set, but only one was set"
- }
- }
-
- val sslSocketFactory = sslSocketFactory
- val trustManager = trustManager
- if (sslSocketFactory != null && trustManager != null) {
- sslSocketFactory(sslSocketFactory, trustManager)
- } else {
- check((sslSocketFactory != null) == (trustManager != null)) {
- "Both or none of `sslSocketFactory` and `trustManager` must be set, but only one was set"
- }
- }
-
- hostnameVerifier?.let(::hostnameVerifier)
- }
- .build()
- .apply {
- // We usually make all our requests to the same host so it makes sense to
- // raise the per-host limit to the overall limit.
- dispatcher.maxRequestsPerHost = dispatcher.maxRequests
- }
- )
- }
-}
diff --git a/src/main/java/com/google/genai/interactions/core/BaseDeserializer.kt b/src/main/java/com/google/genai/interactions/core/BaseDeserializer.kt
deleted file mode 100644
index 24a8adf9430..00000000000
--- a/src/main/java/com/google/genai/interactions/core/BaseDeserializer.kt
+++ /dev/null
@@ -1,60 +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
-*
-* http://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.interactions.core
-
-import com.fasterxml.jackson.core.JsonParser
-import com.fasterxml.jackson.core.ObjectCodec
-import com.fasterxml.jackson.core.type.TypeReference
-import com.fasterxml.jackson.databind.BeanProperty
-import com.fasterxml.jackson.databind.DeserializationContext
-import com.fasterxml.jackson.databind.JavaType
-import com.fasterxml.jackson.databind.JsonDeserializer
-import com.fasterxml.jackson.databind.JsonNode
-import com.fasterxml.jackson.databind.deser.ContextualDeserializer
-import com.fasterxml.jackson.databind.deser.std.StdDeserializer
-import kotlin.reflect.KClass
-
-abstract class BaseDeserializer(type: KClass) :
- StdDeserializer(type.java), ContextualDeserializer {
-
- override fun createContextual(
- context: DeserializationContext,
- property: BeanProperty?,
- ): JsonDeserializer {
- return this
- }
-
- override fun deserialize(parser: JsonParser, context: DeserializationContext): T {
- return parser.codec.deserialize(parser.readValueAsTree())
- }
-
- protected abstract fun ObjectCodec.deserialize(node: JsonNode): T
-
- protected fun ObjectCodec.tryDeserialize(node: JsonNode, type: TypeReference): T? =
- try {
- readValue(treeAsTokens(node), type)
- } catch (e: Exception) {
- null
- }
-
- protected fun ObjectCodec.tryDeserialize(node: JsonNode, type: JavaType): T? =
- try {
- readValue(treeAsTokens(node), type)
- } catch (e: Exception) {
- null
- }
-}
diff --git a/src/main/java/com/google/genai/interactions/core/BaseSerializer.kt b/src/main/java/com/google/genai/interactions/core/BaseSerializer.kt
deleted file mode 100644
index 04ace38a7e6..00000000000
--- a/src/main/java/com/google/genai/interactions/core/BaseSerializer.kt
+++ /dev/null
@@ -1,22 +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
-*
-* http://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.interactions.core
-
-import com.fasterxml.jackson.databind.ser.std.StdSerializer
-import kotlin.reflect.KClass
-
-abstract class BaseSerializer(type: KClass) : StdSerializer(type.java)
diff --git a/src/main/java/com/google/genai/interactions/core/Check.kt b/src/main/java/com/google/genai/interactions/core/Check.kt
deleted file mode 100644
index 2c0ef8fe77a..00000000000
--- a/src/main/java/com/google/genai/interactions/core/Check.kt
+++ /dev/null
@@ -1,112 +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
-*
-* http://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.
-*/
-
-@file:JvmName("Check")
-
-package com.google.genai.interactions.core
-
-import com.fasterxml.jackson.core.Version
-import com.fasterxml.jackson.core.util.VersionUtil
-
-fun checkRequired(name: String, condition: Boolean) =
- check(condition) { "`$name` is required, but was not set" }
-
-fun checkRequired(name: String, value: T?): T =
- checkNotNull(value) { "`$name` is required, but was not set" }
-
-@JvmSynthetic
-internal fun checkKnown(name: String, value: JsonField): T =
- value.asKnown().orElseThrow {
- IllegalStateException("`$name` is not a known type: ${value.javaClass.simpleName}")
- }
-
-@JvmSynthetic
-internal fun checkKnown(name: String, value: MultipartField): T =
- value.value.asKnown().orElseThrow {
- IllegalStateException("`$name` is not a known type: ${value.javaClass.simpleName}")
- }
-
-@JvmSynthetic
-internal fun checkLength(name: String, value: String, length: Int): String =
- value.also {
- check(it.length == length) { "`$name` must have length $length, but was ${it.length}" }
- }
-
-@JvmSynthetic
-internal fun checkMinLength(name: String, value: String, minLength: Int): String =
- value.also {
- check(it.length >= minLength) {
- if (minLength == 1) "`$name` must be non-empty, but was empty"
- else "`$name` must have at least length $minLength, but was ${it.length}"
- }
- }
-
-@JvmSynthetic
-internal fun checkMaxLength(name: String, value: String, maxLength: Int): String =
- value.also {
- check(it.length <= maxLength) {
- "`$name` must have at most length $maxLength, but was ${it.length}"
- }
- }
-
-@JvmSynthetic
-internal fun checkJacksonVersionCompatibility() {
- val incompatibleJacksonVersions =
- RUNTIME_JACKSON_VERSIONS.mapNotNull {
- val badVersionReason = BAD_JACKSON_VERSIONS[it.toString()]
- when {
- it.majorVersion != MINIMUM_JACKSON_VERSION.majorVersion ->
- it to "incompatible major version"
- it.minorVersion < MINIMUM_JACKSON_VERSION.minorVersion ->
- it to "minor version too low"
- it.minorVersion == MINIMUM_JACKSON_VERSION.minorVersion &&
- it.patchLevel < MINIMUM_JACKSON_VERSION.patchLevel ->
- it to "patch version too low"
- badVersionReason != null -> it to badVersionReason
- else -> null
- }
- }
- check(incompatibleJacksonVersions.isEmpty()) {
- """
-This SDK requires a minimum Jackson version of $MINIMUM_JACKSON_VERSION, but the following incompatible Jackson versions were detected at runtime:
-
-${incompatibleJacksonVersions.asSequence().map { (version, incompatibilityReason) ->
- "- `${version.toFullString().replace("/", ":")}` ($incompatibilityReason)"
-}.joinToString("\n")}
-
-This can happen if you are either:
-1. Directly depending on different Jackson versions
-2. Depending on some library that depends on different Jackson versions, potentially transitively
-
-Double-check that you are depending on compatible Jackson versions.
-
-See https://www.github.com/stainless-sdks/gemini-next-gen-api-java#jackson for more information.
- """
- .trimIndent()
- }
-}
-
-private val MINIMUM_JACKSON_VERSION: Version = VersionUtil.parseVersion("2.13.4", null, null)
-private val BAD_JACKSON_VERSIONS: Map =
- mapOf("2.18.1" to "due to https://github.com/FasterXML/jackson-databind/issues/4639")
-private val RUNTIME_JACKSON_VERSIONS: List =
- listOf(
- com.fasterxml.jackson.core.json.PackageVersion.VERSION,
- com.fasterxml.jackson.databind.cfg.PackageVersion.VERSION,
- com.fasterxml.jackson.datatype.jdk8.PackageVersion.VERSION,
- com.fasterxml.jackson.datatype.jsr310.PackageVersion.VERSION,
- com.fasterxml.jackson.module.kotlin.PackageVersion.VERSION,
- )
diff --git a/src/main/java/com/google/genai/interactions/core/ClientOptions.kt b/src/main/java/com/google/genai/interactions/core/ClientOptions.kt
deleted file mode 100644
index 8887c91666e..00000000000
--- a/src/main/java/com/google/genai/interactions/core/ClientOptions.kt
+++ /dev/null
@@ -1,526 +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
-*
-* http://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.
-*/
-
-// File generated from our OpenAPI spec by Stainless.
-
-package com.google.genai.interactions.core
-
-import com.fasterxml.jackson.databind.json.JsonMapper
-import com.google.genai.interactions.core.http.AsyncStreamResponse
-import com.google.genai.interactions.core.http.Headers
-import com.google.genai.interactions.core.http.HttpClient
-import com.google.genai.interactions.core.http.PhantomReachableClosingHttpClient
-import com.google.genai.interactions.core.http.QueryParams
-import com.google.genai.interactions.core.http.RetryingHttpClient
-import java.time.Clock
-import java.time.Duration
-import java.util.Optional
-import java.util.concurrent.Executor
-import java.util.concurrent.ExecutorService
-import java.util.concurrent.Executors
-import java.util.concurrent.ThreadFactory
-import java.util.concurrent.atomic.AtomicLong
-import kotlin.jvm.optionals.getOrNull
-
-/** A class representing the SDK client configuration. */
-class ClientOptions
-private constructor(
- private val originalHttpClient: HttpClient,
- /**
- * The HTTP client to use in the SDK.
- *
- * Use the one published in `gemini-next-gen-api-java-client-okhttp` or implement your own.
- *
- * This class takes ownership of the client and closes it when closed.
- */
- @get:JvmName("httpClient") val httpClient: HttpClient,
- /**
- * Whether to throw an exception if any of the Jackson versions detected at runtime are
- * incompatible with the SDK's minimum supported Jackson version (2.13.4).
- *
- * Defaults to true. Use extreme caution when disabling this option. There is no guarantee that
- * the SDK will work correctly when using an incompatible Jackson version.
- */
- @get:JvmName("checkJacksonVersionCompatibility") val checkJacksonVersionCompatibility: Boolean,
- /**
- * The Jackson JSON mapper to use for serializing and deserializing JSON.
- *
- * Defaults to [com.google.genai.interactions.core.jsonMapper]. The default is usually sufficient
- * and rarely needs to be overridden.
- */
- @get:JvmName("jsonMapper") val jsonMapper: JsonMapper,
- /**
- * The executor to use for running [AsyncStreamResponse.Handler] callbacks.
- *
- * Defaults to a dedicated cached thread pool.
- *
- * This class takes ownership of the executor and shuts it down, if possible, when closed.
- */
- @get:JvmName("streamHandlerExecutor") val streamHandlerExecutor: Executor,
- /**
- * The interface to use for delaying execution, like during retries.
- *
- * This is primarily useful for using fake delays in tests.
- *
- * Defaults to real execution delays.
- *
- * This class takes ownership of the sleeper and closes it when closed.
- */
- @get:JvmName("sleeper") val sleeper: Sleeper,
- /**
- * The clock to use for operations that require timing, like retries.
- *
- * This is primarily useful for using a fake clock in tests.
- *
- * Defaults to [Clock.systemUTC].
- */
- @get:JvmName("clock") val clock: Clock,
- private val baseUrl: String?,
- /** Headers to send with the request. */
- @get:JvmName("headers") val headers: Headers,
- /** Query params to send with the request. */
- @get:JvmName("queryParams") val queryParams: QueryParams,
- /**
- * Whether to call `validate` on every response before returning it.
- *
- * Defaults to false, which means the shape of the response will not be validated upfront.
- * Instead, validation will only occur for the parts of the response that are accessed.
- */
- @get:JvmName("responseValidation") val responseValidation: Boolean,
- /**
- * Sets the maximum time allowed for various parts of an HTTP call's lifecycle, excluding
- * retries.
- *
- * Defaults to [Timeout.default].
- */
- @get:JvmName("timeout") val timeout: Timeout,
- /**
- * The maximum number of times to retry failed requests, with a short exponential backoff
- * between requests.
- *
- * Only the following error types are retried:
- * - Connection errors (for example, due to a network connectivity problem)
- * - 408 Request Timeout
- * - 409 Conflict
- * - 429 Rate Limit
- * - 5xx Internal
- *
- * The API may also explicitly instruct the SDK to retry or not retry a request.
- *
- * Defaults to 2.
- */
- @get:JvmName("maxRetries") val maxRetries: Int,
- private val apiKey: String?,
- /** Defaults to `"v1beta"`. */
- @get:JvmName("apiVersion") val apiVersion: String,
- @JvmSynthetic internal val vertexInfo: VertexInfo?,
-) {
-
- init {
- if (checkJacksonVersionCompatibility) {
- checkJacksonVersionCompatibility()
- }
- }
-
- /**
- * The base URL to use for every request.
- *
- * Defaults to the production environment: `https://generativelanguage.googleapis.com`.
- */
- fun baseUrl(): String = baseUrl ?: PRODUCTION_URL
-
- fun apiKey(): Optional = Optional.ofNullable(apiKey)
-
- fun toBuilder() = Builder().from(this)
-
- companion object {
-
- const val PRODUCTION_URL = "https://generativelanguage.googleapis.com"
-
- /**
- * Returns a mutable builder for constructing an instance of [ClientOptions].
- *
- * The following fields are required:
- * ```java
- * .httpClient()
- * ```
- */
- @JvmStatic fun builder() = Builder()
-
- /**
- * Returns options configured using system properties and environment variables.
- *
- * @see Builder.fromEnv
- */
- @JvmStatic fun fromEnv(): ClientOptions = builder().fromEnv().build()
- }
-
- /** A builder for [ClientOptions]. */
- class Builder internal constructor() {
-
- private var httpClient: HttpClient? = null
- private var checkJacksonVersionCompatibility: Boolean = true
- private var jsonMapper: JsonMapper = jsonMapper()
- private var streamHandlerExecutor: Executor? = null
- private var sleeper: Sleeper? = null
- private var clock: Clock = Clock.systemUTC()
- private var baseUrl: String? = null
- private var headers: Headers.Builder = Headers.builder()
- private var queryParams: QueryParams.Builder = QueryParams.builder()
- private var responseValidation: Boolean = false
- private var timeout: Timeout = Timeout.default()
- private var maxRetries: Int = 2
- private var apiKey: String? = null
- private var apiVersion: String = "v1beta"
- private var vertexInfo: VertexInfo? = null
-
- @JvmSynthetic
- internal fun from(clientOptions: ClientOptions) = apply {
- httpClient = clientOptions.originalHttpClient
- checkJacksonVersionCompatibility = clientOptions.checkJacksonVersionCompatibility
- jsonMapper = clientOptions.jsonMapper
- streamHandlerExecutor = clientOptions.streamHandlerExecutor
- sleeper = clientOptions.sleeper
- clock = clientOptions.clock
- baseUrl = clientOptions.baseUrl
- headers = clientOptions.headers.toBuilder()
- queryParams = clientOptions.queryParams.toBuilder()
- responseValidation = clientOptions.responseValidation
- timeout = clientOptions.timeout
- maxRetries = clientOptions.maxRetries
- apiKey = clientOptions.apiKey
- apiVersion = clientOptions.apiVersion
- vertexInfo = clientOptions.vertexInfo
- }
-
- /**
- * The HTTP client to use in the SDK.
- *
- * Use the one published in `gemini-next-gen-api-java-client-okhttp` or implement your own.
- *
- * This class takes ownership of the client and closes it when closed.
- */
- fun httpClient(httpClient: HttpClient) = apply {
- this.httpClient = PhantomReachableClosingHttpClient(httpClient)
- }
-
- /**
- * Whether to throw an exception if any of the Jackson versions detected at runtime are
- * incompatible with the SDK's minimum supported Jackson version (2.13.4).
- *
- * Defaults to true. Use extreme caution when disabling this option. There is no guarantee
- * that the SDK will work correctly when using an incompatible Jackson version.
- */
- fun checkJacksonVersionCompatibility(checkJacksonVersionCompatibility: Boolean) = apply {
- this.checkJacksonVersionCompatibility = checkJacksonVersionCompatibility
- }
-
- /**
- * The Jackson JSON mapper to use for serializing and deserializing JSON.
- *
- * Defaults to [com.google.genai.interactions.core.jsonMapper]. The default is usually
- * sufficient and rarely needs to be overridden.
- */
- fun jsonMapper(jsonMapper: JsonMapper) = apply { this.jsonMapper = jsonMapper }
-
- /**
- * The executor to use for running [AsyncStreamResponse.Handler] callbacks.
- *
- * Defaults to a dedicated cached thread pool.
- *
- * This class takes ownership of the executor and shuts it down, if possible, when closed.
- */
- fun streamHandlerExecutor(streamHandlerExecutor: Executor) = apply {
- this.streamHandlerExecutor =
- if (streamHandlerExecutor is ExecutorService)
- PhantomReachableExecutorService(streamHandlerExecutor)
- else streamHandlerExecutor
- }
-
- /**
- * The interface to use for delaying execution, like during retries.
- *
- * This is primarily useful for using fake delays in tests.
- *
- * Defaults to real execution delays.
- *
- * This class takes ownership of the sleeper and closes it when closed.
- */
- fun sleeper(sleeper: Sleeper) = apply { this.sleeper = PhantomReachableSleeper(sleeper) }
-
- /**
- * The clock to use for operations that require timing, like retries.
- *
- * This is primarily useful for using a fake clock in tests.
- *
- * Defaults to [Clock.systemUTC].
- */
- fun clock(clock: Clock) = apply { this.clock = clock }
-
- /**
- * The base URL to use for every request.
- *
- * Defaults to the production environment: `https://generativelanguage.googleapis.com`.
- */
- fun baseUrl(baseUrl: String?) = apply { this.baseUrl = baseUrl }
-
- /** Alias for calling [Builder.baseUrl] with `baseUrl.orElse(null)`. */
- fun baseUrl(baseUrl: Optional) = baseUrl(baseUrl.getOrNull())
-
- /**
- * Whether to call `validate` on every response before returning it.
- *
- * Defaults to false, which means the shape of the response will not be validated upfront.
- * Instead, validation will only occur for the parts of the response that are accessed.
- */
- fun responseValidation(responseValidation: Boolean) = apply {
- this.responseValidation = responseValidation
- }
-
- /**
- * Sets the maximum time allowed for various parts of an HTTP call's lifecycle, excluding
- * retries.
- *
- * Defaults to [Timeout.default].
- */
- fun timeout(timeout: Timeout) = apply { this.timeout = timeout }
-
- /**
- * Sets the maximum time allowed for a complete HTTP call, not including retries.
- *
- * See [Timeout.request] for more details.
- *
- * For fine-grained control, pass a [Timeout] object.
- */
- fun timeout(timeout: Duration) = timeout(Timeout.builder().request(timeout).build())
-
- /**
- * The maximum number of times to retry failed requests, with a short exponential backoff
- * between requests.
- *
- * Only the following error types are retried:
- * - Connection errors (for example, due to a network connectivity problem)
- * - 408 Request Timeout
- * - 409 Conflict
- * - 429 Rate Limit
- * - 5xx Internal
- *
- * The API may also explicitly instruct the SDK to retry or not retry a request.
- *
- * Defaults to 2.
- */
- fun maxRetries(maxRetries: Int) = apply { this.maxRetries = maxRetries }
-
- fun apiKey(apiKey: String?) = apply { this.apiKey = apiKey }
-
- /** Alias for calling [Builder.apiKey] with `apiKey.orElse(null)`. */
- fun apiKey(apiKey: Optional) = apiKey(apiKey.getOrNull())
-
- /** Defaults to `"v1beta"`. */
- fun apiVersion(apiVersion: String) = apply { this.apiVersion = apiVersion }
-
- fun vertexInfo(vertexInfo: VertexInfo?) = apply { this.vertexInfo = vertexInfo }
-
- fun headers(headers: Headers) = apply {
- this.headers.clear()
- putAllHeaders(headers)
- }
-
- fun headers(headers: Map>) = apply {
- this.headers.clear()
- putAllHeaders(headers)
- }
-
- fun putHeader(name: String, value: String) = apply { headers.put(name, value) }
-
- fun putHeaders(name: String, values: Iterable) = apply { headers.put(name, values) }
-
- fun putAllHeaders(headers: Headers) = apply { this.headers.putAll(headers) }
-
- fun putAllHeaders(headers: Map>) = apply {
- this.headers.putAll(headers)
- }
-
- fun replaceHeaders(name: String, value: String) = apply { headers.replace(name, value) }
-
- fun replaceHeaders(name: String, values: Iterable) = apply {
- headers.replace(name, values)
- }
-
- fun replaceAllHeaders(headers: Headers) = apply { this.headers.replaceAll(headers) }
-
- fun replaceAllHeaders(headers: Map>) = apply {
- this.headers.replaceAll(headers)
- }
-
- fun removeHeaders(name: String) = apply { headers.remove(name) }
-
- fun removeAllHeaders(names: Set) = apply { headers.removeAll(names) }
-
- fun queryParams(queryParams: QueryParams) = apply {
- this.queryParams.clear()
- putAllQueryParams(queryParams)
- }
-
- fun queryParams(queryParams: Map>) = apply {
- this.queryParams.clear()
- putAllQueryParams(queryParams)
- }
-
- fun putQueryParam(key: String, value: String) = apply { queryParams.put(key, value) }
-
- fun putQueryParams(key: String, values: Iterable) = apply {
- queryParams.put(key, values)
- }
-
- fun putAllQueryParams(queryParams: QueryParams) = apply {
- this.queryParams.putAll(queryParams)
- }
-
- fun putAllQueryParams(queryParams: Map>) = apply {
- this.queryParams.putAll(queryParams)
- }
-
- fun replaceQueryParams(key: String, value: String) = apply {
- queryParams.replace(key, value)
- }
-
- fun replaceQueryParams(key: String, values: Iterable) = apply {
- queryParams.replace(key, values)
- }
-
- fun replaceAllQueryParams(queryParams: QueryParams) = apply {
- this.queryParams.replaceAll(queryParams)
- }
-
- fun replaceAllQueryParams(queryParams: Map>) = apply {
- this.queryParams.replaceAll(queryParams)
- }
-
- fun removeQueryParams(key: String) = apply { queryParams.remove(key) }
-
- fun removeAllQueryParams(keys: Set) = apply { queryParams.removeAll(keys) }
-
- fun timeout(): Timeout = timeout
-
- /**
- * Updates configuration using system properties and environment variables.
- *
- * See this table for the available options:
- *
- * |Setter |System property |Environment variable |Required|Default value |
- * |---------|-------------------------------|------------------------------|--------|---------------------------------------------|
- * |`apiKey` |`gemininextgenapi.geminiApiKey`|`GEMINI_API_KEY` |false |- |
- * |`baseUrl`|`gemininextgenapi.baseUrl` |`GEMINI_NEXT_GEN_API_BASE_URL`|true |`"https://generativelanguage.googleapis.com"`|
- *
- * System properties take precedence over environment variables.
- */
- fun fromEnv() = apply {
- (System.getProperty("gemininextgenapi.baseUrl")
- ?: System.getenv("GEMINI_NEXT_GEN_API_BASE_URL"))
- ?.let { baseUrl(it) }
- (System.getProperty("gemininextgenapi.geminiApiKey") ?: System.getenv("GEMINI_API_KEY"))
- ?.let { apiKey(it) }
- }
-
- /**
- * Returns an immutable instance of [ClientOptions].
- *
- * Further updates to this [Builder] will not mutate the returned instance.
- *
- * The following fields are required:
- * ```java
- * .httpClient()
- * ```
- *
- * @throws IllegalStateException if any required field is unset.
- */
- fun build(): ClientOptions {
- val httpClient = checkRequired("httpClient", httpClient)
- val streamHandlerExecutor =
- streamHandlerExecutor
- ?: PhantomReachableExecutorService(
- Executors.newCachedThreadPool(
- object : ThreadFactory {
-
- private val threadFactory: ThreadFactory =
- Executors.defaultThreadFactory()
- private val count = AtomicLong(0)
-
- override fun newThread(runnable: Runnable): Thread =
- threadFactory.newThread(runnable).also {
- it.name =
- "gemini-next-gen-api-stream-handler-thread-${count.getAndIncrement()}"
- }
- }
- )
- )
- val sleeper = sleeper ?: PhantomReachableSleeper(DefaultSleeper())
-
- val headers = Headers.builder()
- val queryParams = QueryParams.builder()
- headers.put("Api-Revision", "2026-05-20")
- // We replace after all the default headers to allow end-users to overwrite them.
- headers.replaceAll(this.headers.build())
- queryParams.replaceAll(this.queryParams.build())
- apiKey?.let {
- if (!it.isEmpty()) {
- headers.replace("x-goog-api-key", it)
- }
- }
-
- return ClientOptions(
- httpClient,
- RetryingHttpClient.builder()
- .httpClient(httpClient)
- .sleeper(sleeper)
- .clock(clock)
- .maxRetries(maxRetries)
- .build(),
- checkJacksonVersionCompatibility,
- jsonMapper,
- streamHandlerExecutor,
- sleeper,
- clock,
- baseUrl,
- headers.build(),
- queryParams.build(),
- responseValidation,
- timeout,
- maxRetries,
- apiKey,
- apiVersion,
- vertexInfo,
- )
- }
- }
-
- /**
- * Closes these client options, relinquishing any underlying resources.
- *
- * This is purposefully not inherited from [AutoCloseable] because the client options are
- * long-lived and usually should not be synchronously closed via try-with-resources.
- *
- * It's also usually not necessary to call this method at all. the default client automatically
- * releases threads and connections if they remain idle, but if you are writing an application
- * that needs to aggressively release unused resources, then you may call this method.
- */
- fun close() {
- httpClient.close()
- (streamHandlerExecutor as? ExecutorService)?.shutdown()
- sleeper.close()
- }
-}
diff --git a/src/main/java/com/google/genai/interactions/core/DefaultSleeper.kt b/src/main/java/com/google/genai/interactions/core/DefaultSleeper.kt
deleted file mode 100644
index 485c67612db..00000000000
--- a/src/main/java/com/google/genai/interactions/core/DefaultSleeper.kt
+++ /dev/null
@@ -1,44 +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
-*
-* http://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.interactions.core
-
-import java.time.Duration
-import java.util.Timer
-import java.util.TimerTask
-import java.util.concurrent.CompletableFuture
-
-class DefaultSleeper : Sleeper {
-
- private val timer = Timer("DefaultSleeper", true)
-
- override fun sleep(duration: Duration) = Thread.sleep(duration.toMillis())
-
- override fun sleepAsync(duration: Duration): CompletableFuture {
- val future = CompletableFuture()
- timer.schedule(
- object : TimerTask() {
- override fun run() {
- future.complete(null)
- }
- },
- duration.toMillis(),
- )
- return future
- }
-
- override fun close() = timer.cancel()
-}
diff --git a/src/main/java/com/google/genai/interactions/core/ObjectMappers.kt b/src/main/java/com/google/genai/interactions/core/ObjectMappers.kt
deleted file mode 100644
index 3b4c3b54663..00000000000
--- a/src/main/java/com/google/genai/interactions/core/ObjectMappers.kt
+++ /dev/null
@@ -1,194 +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
-*
-* http://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.
-*/
-
-@file:JvmName("ObjectMappers")
-
-package com.google.genai.interactions.core
-
-import com.fasterxml.jackson.annotation.JsonInclude
-import com.fasterxml.jackson.core.JsonGenerator
-import com.fasterxml.jackson.core.JsonParseException
-import com.fasterxml.jackson.core.JsonParser
-import com.fasterxml.jackson.databind.DeserializationContext
-import com.fasterxml.jackson.databind.DeserializationFeature
-import com.fasterxml.jackson.databind.MapperFeature
-import com.fasterxml.jackson.databind.SerializationFeature
-import com.fasterxml.jackson.databind.SerializerProvider
-import com.fasterxml.jackson.databind.cfg.CoercionAction
-import com.fasterxml.jackson.databind.cfg.CoercionInputShape
-import com.fasterxml.jackson.databind.deser.std.StdDeserializer
-import com.fasterxml.jackson.databind.json.JsonMapper
-import com.fasterxml.jackson.databind.module.SimpleModule
-import com.fasterxml.jackson.databind.type.LogicalType
-import com.fasterxml.jackson.datatype.jdk8.Jdk8Module
-import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule
-import com.fasterxml.jackson.module.kotlin.kotlinModule
-import java.io.InputStream
-import java.time.DateTimeException
-import java.time.LocalDate
-import java.time.LocalDateTime
-import java.time.OffsetDateTime
-import java.time.ZoneId
-import java.time.format.DateTimeFormatter
-import java.time.temporal.ChronoField
-
-fun jsonMapper(): JsonMapper =
- JsonMapper.builder()
- .addModule(kotlinModule())
- .addModule(Jdk8Module())
- .addModule(JavaTimeModule())
- .addModule(
- SimpleModule()
- .addSerializer(InputStreamSerializer)
- .addDeserializer(OffsetDateTime::class.java, LenientOffsetDateTimeDeserializer())
- )
- .withCoercionConfig(LogicalType.Boolean) {
- it.setCoercion(CoercionInputShape.Integer, CoercionAction.Fail)
- .setCoercion(CoercionInputShape.Float, CoercionAction.Fail)
- .setCoercion(CoercionInputShape.String, CoercionAction.Fail)
- .setCoercion(CoercionInputShape.Array, CoercionAction.Fail)
- .setCoercion(CoercionInputShape.Object, CoercionAction.Fail)
- }
- .withCoercionConfig(LogicalType.Integer) {
- it.setCoercion(CoercionInputShape.Boolean, CoercionAction.Fail)
- .setCoercion(CoercionInputShape.Float, CoercionAction.Fail)
- .setCoercion(CoercionInputShape.String, CoercionAction.Fail)
- .setCoercion(CoercionInputShape.Array, CoercionAction.Fail)
- .setCoercion(CoercionInputShape.Object, CoercionAction.Fail)
- }
- .withCoercionConfig(LogicalType.Float) {
- it.setCoercion(CoercionInputShape.Boolean, CoercionAction.Fail)
- .setCoercion(CoercionInputShape.String, CoercionAction.Fail)
- .setCoercion(CoercionInputShape.Array, CoercionAction.Fail)
- .setCoercion(CoercionInputShape.Object, CoercionAction.Fail)
- }
- .withCoercionConfig(LogicalType.Textual) {
- it.setCoercion(CoercionInputShape.Boolean, CoercionAction.Fail)
- .setCoercion(CoercionInputShape.Integer, CoercionAction.Fail)
- .setCoercion(CoercionInputShape.Float, CoercionAction.Fail)
- .setCoercion(CoercionInputShape.Array, CoercionAction.Fail)
- .setCoercion(CoercionInputShape.Object, CoercionAction.Fail)
- }
- .withCoercionConfig(LogicalType.DateTime) {
- it.setCoercion(CoercionInputShape.Integer, CoercionAction.Fail)
- .setCoercion(CoercionInputShape.Float, CoercionAction.Fail)
- .setCoercion(CoercionInputShape.Array, CoercionAction.Fail)
- .setCoercion(CoercionInputShape.Object, CoercionAction.Fail)
- }
- .withCoercionConfig(LogicalType.Array) {
- it.setCoercion(CoercionInputShape.Boolean, CoercionAction.Fail)
- .setCoercion(CoercionInputShape.Integer, CoercionAction.Fail)
- .setCoercion(CoercionInputShape.Float, CoercionAction.Fail)
- .setCoercion(CoercionInputShape.String, CoercionAction.Fail)
- .setCoercion(CoercionInputShape.Object, CoercionAction.Fail)
- }
- .withCoercionConfig(LogicalType.Collection) {
- it.setCoercion(CoercionInputShape.Boolean, CoercionAction.Fail)
- .setCoercion(CoercionInputShape.Integer, CoercionAction.Fail)
- .setCoercion(CoercionInputShape.Float, CoercionAction.Fail)
- .setCoercion(CoercionInputShape.String, CoercionAction.Fail)
- .setCoercion(CoercionInputShape.Object, CoercionAction.Fail)
- }
- .withCoercionConfig(LogicalType.Map) {
- it.setCoercion(CoercionInputShape.Boolean, CoercionAction.Fail)
- .setCoercion(CoercionInputShape.Integer, CoercionAction.Fail)
- .setCoercion(CoercionInputShape.Float, CoercionAction.Fail)
- .setCoercion(CoercionInputShape.String, CoercionAction.Fail)
- .setCoercion(CoercionInputShape.Object, CoercionAction.Fail)
- }
- .withCoercionConfig(LogicalType.POJO) {
- it.setCoercion(CoercionInputShape.Boolean, CoercionAction.Fail)
- .setCoercion(CoercionInputShape.Integer, CoercionAction.Fail)
- .setCoercion(CoercionInputShape.Float, CoercionAction.Fail)
- .setCoercion(CoercionInputShape.String, CoercionAction.Fail)
- .setCoercion(CoercionInputShape.Array, CoercionAction.Fail)
- }
- .serializationInclusion(JsonInclude.Include.NON_ABSENT)
- .disable(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE)
- .disable(SerializationFeature.FLUSH_AFTER_WRITE_VALUE)
- .disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
- .disable(SerializationFeature.WRITE_DURATIONS_AS_TIMESTAMPS)
- .disable(MapperFeature.ALLOW_COERCION_OF_SCALARS)
- .disable(MapperFeature.AUTO_DETECT_CREATORS)
- .disable(MapperFeature.AUTO_DETECT_FIELDS)
- .disable(MapperFeature.AUTO_DETECT_GETTERS)
- .disable(MapperFeature.AUTO_DETECT_IS_GETTERS)
- .disable(MapperFeature.AUTO_DETECT_SETTERS)
- .build()
-
-/** A serializer that serializes [InputStream] to bytes. */
-private object InputStreamSerializer : BaseSerializer(InputStream::class) {
-
- private fun readResolve(): Any = InputStreamSerializer
-
- override fun serialize(
- value: InputStream?,
- gen: JsonGenerator?,
- serializers: SerializerProvider?,
- ) {
- if (value == null) {
- gen?.writeNull()
- } else {
- value.use { gen?.writeBinary(it.readBytes()) }
- }
- }
-}
-
-/**
- * A deserializer that can deserialize [OffsetDateTime] from datetimes, dates, and zoned datetimes.
- */
-private class LenientOffsetDateTimeDeserializer :
- StdDeserializer(OffsetDateTime::class.java) {
-
- companion object {
-
- private val DATE_TIME_FORMATTERS =
- listOf(
- DateTimeFormatter.ISO_LOCAL_DATE_TIME,
- DateTimeFormatter.ISO_LOCAL_DATE,
- DateTimeFormatter.ISO_ZONED_DATE_TIME,
- )
- }
-
- override fun logicalType(): LogicalType = LogicalType.DateTime
-
- override fun deserialize(p: JsonParser, context: DeserializationContext): OffsetDateTime {
- val exceptions = mutableListOf()
-
- for (formatter in DATE_TIME_FORMATTERS) {
- try {
- val temporal = formatter.parse(p.text)
-
- return when {
- !temporal.isSupported(ChronoField.HOUR_OF_DAY) ->
- LocalDate.from(temporal)
- .atStartOfDay()
- .atZone(ZoneId.of("UTC"))
- .toOffsetDateTime()
- !temporal.isSupported(ChronoField.OFFSET_SECONDS) ->
- LocalDateTime.from(temporal).atZone(ZoneId.of("UTC")).toOffsetDateTime()
- else -> OffsetDateTime.from(temporal)
- }
- } catch (e: DateTimeException) {
- exceptions.add(e)
- }
- }
-
- throw JsonParseException(p, "Cannot parse `OffsetDateTime` from value: ${p.text}").apply {
- exceptions.forEach { addSuppressed(it) }
- }
- }
-}
diff --git a/src/main/java/com/google/genai/interactions/core/Params.kt b/src/main/java/com/google/genai/interactions/core/Params.kt
deleted file mode 100644
index d9c986c75c9..00000000000
--- a/src/main/java/com/google/genai/interactions/core/Params.kt
+++ /dev/null
@@ -1,32 +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
-*
-* http://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.interactions.core
-
-import com.google.genai.interactions.core.http.Headers
-import com.google.genai.interactions.core.http.QueryParams
-
-/** An interface representing parameters passed to a service method. */
-interface Params {
- /** The full set of headers in the parameters, including both fixed and additional headers. */
- fun _headers(): Headers
-
- /**
- * The full set of query params in the parameters, including both fixed and additional query
- * params.
- */
- fun _queryParams(): QueryParams
-}
diff --git a/src/main/java/com/google/genai/interactions/core/PhantomReachable.kt b/src/main/java/com/google/genai/interactions/core/PhantomReachable.kt
deleted file mode 100644
index e45dd5a4b83..00000000000
--- a/src/main/java/com/google/genai/interactions/core/PhantomReachable.kt
+++ /dev/null
@@ -1,72 +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
-*
-* http://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.
-*/
-
-@file:JvmName("PhantomReachable")
-
-package com.google.genai.interactions.core
-
-import com.google.genai.interactions.errors.GeminiNextGenApiException
-import java.lang.reflect.InvocationTargetException
-
-/**
- * Closes [closeable] when [observed] becomes only phantom reachable.
- *
- * This is a wrapper around a Java 9+ [java.lang.ref.Cleaner], or a no-op in older Java versions.
- */
-@JvmSynthetic
-internal fun closeWhenPhantomReachable(observed: Any, closeable: AutoCloseable) {
- check(observed !== closeable) {
- "`observed` cannot be the same object as `closeable` because it would never become phantom reachable"
- }
- closeWhenPhantomReachable(observed, closeable::close)
-}
-
-/**
- * Calls [close] when [observed] becomes only phantom reachable.
- *
- * This is a wrapper around a Java 9+ [java.lang.ref.Cleaner], or a no-op in older Java versions.
- */
-@JvmSynthetic
-internal fun closeWhenPhantomReachable(observed: Any, close: () -> Unit) {
- closeWhenPhantomReachable?.let { it(observed, close) }
-}
-
-private val closeWhenPhantomReachable: ((Any, () -> Unit) -> Unit)? by lazy {
- try {
- val cleanerClass = Class.forName("java.lang.ref.Cleaner")
- val cleanerCreate = cleanerClass.getMethod("create")
- val cleanerRegister =
- cleanerClass.getMethod("register", Any::class.java, Runnable::class.java)
- val cleanerObject = cleanerCreate.invoke(null);
-
- { observed, close ->
- try {
- cleanerRegister.invoke(cleanerObject, observed, Runnable { close() })
- } catch (e: ReflectiveOperationException) {
- if (e is InvocationTargetException) {
- when (val cause = e.cause) {
- is RuntimeException,
- is Error -> throw cause
- }
- }
- throw GeminiNextGenApiException("Unexpected reflective invocation failure", e)
- }
- }
- } catch (e: ReflectiveOperationException) {
- // We're running Java 8, which has no Cleaner.
- null
- }
-}
diff --git a/src/main/java/com/google/genai/interactions/core/PhantomReachableExecutorService.kt b/src/main/java/com/google/genai/interactions/core/PhantomReachableExecutorService.kt
deleted file mode 100644
index c091e7f4eb3..00000000000
--- a/src/main/java/com/google/genai/interactions/core/PhantomReachableExecutorService.kt
+++ /dev/null
@@ -1,74 +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
-*
-* http://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.interactions.core
-
-import java.util.concurrent.Callable
-import java.util.concurrent.ExecutorService
-import java.util.concurrent.Future
-import java.util.concurrent.TimeUnit
-
-/**
- * A delegating wrapper around an [ExecutorService] that shuts it down once it's only phantom
- * reachable.
- *
- * This class ensures the [ExecutorService] is shut down even if the user forgets to do it.
- */
-internal class PhantomReachableExecutorService(private val executorService: ExecutorService) :
- ExecutorService {
- init {
- closeWhenPhantomReachable(this) { executorService.shutdown() }
- }
-
- override fun execute(command: Runnable) = executorService.execute(command)
-
- override fun shutdown() = executorService.shutdown()
-
- override fun shutdownNow(): MutableList = executorService.shutdownNow()
-
- override fun isShutdown(): Boolean = executorService.isShutdown
-
- override fun isTerminated(): Boolean = executorService.isTerminated
-
- override fun awaitTermination(timeout: Long, unit: TimeUnit): Boolean =
- executorService.awaitTermination(timeout, unit)
-
- override fun submit(task: Callable): Future = executorService.submit(task)
-
- override fun submit(task: Runnable, result: T): Future =
- executorService.submit(task, result)
-
- override fun submit(task: Runnable): Future<*> = executorService.submit(task)
-
- override fun invokeAll(
- tasks: MutableCollection>
- ): MutableList> = executorService.invokeAll(tasks)
-
- override fun invokeAll(
- tasks: MutableCollection>,
- timeout: Long,
- unit: TimeUnit,
- ): MutableList> = executorService.invokeAll(tasks, timeout, unit)
-
- override fun invokeAny(tasks: MutableCollection>): T =
- executorService.invokeAny(tasks)
-
- override fun invokeAny(
- tasks: MutableCollection>,
- timeout: Long,
- unit: TimeUnit,
- ): T = executorService.invokeAny(tasks, timeout, unit)
-}
diff --git a/src/main/java/com/google/genai/interactions/core/PhantomReachableSleeper.kt b/src/main/java/com/google/genai/interactions/core/PhantomReachableSleeper.kt
deleted file mode 100644
index 278ed9af1e2..00000000000
--- a/src/main/java/com/google/genai/interactions/core/PhantomReachableSleeper.kt
+++ /dev/null
@@ -1,39 +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
-*
-* http://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.interactions.core
-
-import java.time.Duration
-import java.util.concurrent.CompletableFuture
-
-/**
- * A delegating wrapper around a [Sleeper] that closes it once it's only phantom reachable.
- *
- * This class ensures the [Sleeper] is closed even if the user forgets to do it.
- */
-internal class PhantomReachableSleeper(private val sleeper: Sleeper) : Sleeper {
-
- init {
- closeWhenPhantomReachable(this, sleeper)
- }
-
- override fun sleep(duration: Duration) = sleeper.sleep(duration)
-
- override fun sleepAsync(duration: Duration): CompletableFuture =
- sleeper.sleepAsync(duration)
-
- override fun close() = sleeper.close()
-}
diff --git a/src/main/java/com/google/genai/interactions/core/PrepareRequest.kt b/src/main/java/com/google/genai/interactions/core/PrepareRequest.kt
deleted file mode 100644
index 2a29fd3bee9..00000000000
--- a/src/main/java/com/google/genai/interactions/core/PrepareRequest.kt
+++ /dev/null
@@ -1,48 +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
- *
- * http://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.
- */
-
-@file:JvmName("PrepareRequest")
-
-package com.google.genai.interactions.core
-
-import com.google.genai.interactions.core.http.HttpRequest
-import java.util.concurrent.CompletableFuture
-
-@JvmSynthetic
-internal fun HttpRequest.prepare(clientOptions: ClientOptions, params: Params): HttpRequest =
- toBuilder()
- .pathSegments(
- clientOptions.vertexInfo?.let { toVertexPathSegments(it, pathSegments) } ?: pathSegments
- )
- .putAllQueryParams(clientOptions.queryParams)
- .replaceAllQueryParams(params._queryParams())
- .putAllHeaders(clientOptions.headers)
- .replaceAllHeaders(params._headers())
- .build()
-
-private fun toVertexPathSegments(vertexInfo: VertexInfo, pathSegments: List): List =
- pathSegments.toMutableList().apply {
- addAll(1, listOf("projects", vertexInfo.project, "locations", vertexInfo.location))
- }
-
-@JvmSynthetic
-internal fun HttpRequest.prepareAsync(
- clientOptions: ClientOptions,
- params: Params,
-): CompletableFuture =
- // This async version exists to make it easier to add async specific preparation logic in the
- // future.
- CompletableFuture.completedFuture(prepare(clientOptions, params))
diff --git a/src/main/java/com/google/genai/interactions/core/Properties.kt b/src/main/java/com/google/genai/interactions/core/Properties.kt
deleted file mode 100644
index dcc5cfee865..00000000000
--- a/src/main/java/com/google/genai/interactions/core/Properties.kt
+++ /dev/null
@@ -1,58 +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
-*
-* http://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.
-*/
-
-@file:JvmName("Properties")
-
-package com.google.genai.interactions.core
-
-import com.google.genai.interactions.client.GeminiNextGenApiClient
-
-fun getOsArch(): String {
- val osArch = System.getProperty("os.arch")
-
- return when (osArch) {
- null -> "unknown"
- "i386",
- "x32",
- "x86" -> "x32"
- "amd64",
- "x86_64" -> "x64"
- "arm" -> "arm"
- "aarch64" -> "arm64"
- else -> "other:$osArch"
- }
-}
-
-fun getOsName(): String {
- val osName = System.getProperty("os.name")
- val vendorUrl = System.getProperty("java.vendor.url")
-
- return when {
- osName == null -> "Unknown"
- osName.startsWith("Linux") && vendorUrl == "http://www.android.com/" -> "Android"
- osName.startsWith("Linux") -> "Linux"
- osName.startsWith("Mac OS") -> "MacOS"
- osName.startsWith("Windows") -> "Windows"
- else -> "Other:$osName"
- }
-}
-
-fun getOsVersion(): String = System.getProperty("os.version", "unknown") ?: "unknown"
-
-fun getPackageVersion(): String =
- GeminiNextGenApiClient::class.java.`package`?.implementationVersion ?: "unknown"
-
-fun getJavaVersion(): String = System.getProperty("java.version", "unknown") ?: "unknown"
diff --git a/src/main/java/com/google/genai/interactions/core/RequestOptions.kt b/src/main/java/com/google/genai/interactions/core/RequestOptions.kt
deleted file mode 100644
index fbc569f2ec8..00000000000
--- a/src/main/java/com/google/genai/interactions/core/RequestOptions.kt
+++ /dev/null
@@ -1,62 +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
-*
-* http://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.interactions.core
-
-import java.time.Duration
-
-class RequestOptions private constructor(val responseValidation: Boolean?, val timeout: Timeout?) {
-
- companion object {
-
- private val NONE = builder().build()
-
- @JvmStatic fun none() = NONE
-
- @JvmSynthetic
- internal fun from(clientOptions: ClientOptions): RequestOptions =
- builder()
- .responseValidation(clientOptions.responseValidation)
- .timeout(clientOptions.timeout)
- .build()
-
- @JvmStatic fun builder() = Builder()
- }
-
- fun applyDefaults(options: RequestOptions): RequestOptions =
- RequestOptions(
- responseValidation = responseValidation ?: options.responseValidation,
- timeout =
- if (options.timeout != null && timeout != null) timeout.assign(options.timeout)
- else timeout ?: options.timeout,
- )
-
- class Builder internal constructor() {
-
- private var responseValidation: Boolean? = null
- private var timeout: Timeout? = null
-
- fun responseValidation(responseValidation: Boolean) = apply {
- this.responseValidation = responseValidation
- }
-
- fun timeout(timeout: Timeout) = apply { this.timeout = timeout }
-
- fun timeout(timeout: Duration) = timeout(Timeout.builder().request(timeout).build())
-
- fun build(): RequestOptions = RequestOptions(responseValidation, timeout)
- }
-}
diff --git a/src/main/java/com/google/genai/interactions/core/Sleeper.kt b/src/main/java/com/google/genai/interactions/core/Sleeper.kt
deleted file mode 100644
index bdda52bd57d..00000000000
--- a/src/main/java/com/google/genai/interactions/core/Sleeper.kt
+++ /dev/null
@@ -1,37 +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
-*
-* http://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.interactions.core
-
-import java.time.Duration
-import java.util.concurrent.CompletableFuture
-
-/**
- * An interface for delaying execution for a specified amount of time.
- *
- * Useful for testing and cleaning up resources.
- */
-interface Sleeper : AutoCloseable {
-
- /** Synchronously pauses execution for the given [duration]. */
- fun sleep(duration: Duration)
-
- /** Asynchronously pauses execution for the given [duration]. */
- fun sleepAsync(duration: Duration): CompletableFuture
-
- /** Overridden from [AutoCloseable] to not have a checked exception in its signature. */
- override fun close()
-}
diff --git a/src/main/java/com/google/genai/interactions/core/Timeout.kt b/src/main/java/com/google/genai/interactions/core/Timeout.kt
deleted file mode 100644
index 0e96f6af764..00000000000
--- a/src/main/java/com/google/genai/interactions/core/Timeout.kt
+++ /dev/null
@@ -1,187 +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
-*
-* http://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.
-*/
-
-// File generated from our OpenAPI spec by Stainless.
-
-package com.google.genai.interactions.core
-
-import java.time.Duration
-import java.util.Objects
-import java.util.Optional
-import kotlin.jvm.optionals.getOrNull
-
-/** A class containing timeouts for various processing phases of a request. */
-class Timeout
-private constructor(
- private val connect: Duration?,
- private val read: Duration?,
- private val write: Duration?,
- private val request: Duration?,
-) {
-
- /**
- * The maximum time allowed to establish a connection with a host.
- *
- * A value of [Duration.ZERO] means there's no timeout.
- *
- * Defaults to `Duration.ofMinutes(1)`.
- */
- fun connect(): Duration = connect ?: Duration.ofMinutes(1)
-
- /**
- * The maximum time allowed between two data packets when waiting for the server’s response.
- *
- * A value of [Duration.ZERO] means there's no timeout.
- *
- * Defaults to `request()`.
- */
- fun read(): Duration = read ?: request()
-
- /**
- * The maximum time allowed between two data packets when sending the request to the server.
- *
- * A value of [Duration.ZERO] means there's no timeout.
- *
- * Defaults to `request()`.
- */
- fun write(): Duration = write ?: request()
-
- /**
- * The maximum time allowed for a complete HTTP call, not including retries.
- *
- * This includes resolving DNS, connecting, writing the request body, server processing, as well
- * as reading the response body.
- *
- * A value of [Duration.ZERO] means there's no timeout.
- *
- * Defaults to `Duration.ofMinutes(1)`.
- */
- fun request(): Duration = request ?: Duration.ofMinutes(1)
-
- fun toBuilder() = Builder().from(this)
-
- companion object {
-
- @JvmStatic fun default() = builder().build()
-
- /** Returns a mutable builder for constructing an instance of [Timeout]. */
- @JvmStatic fun builder() = Builder()
- }
-
- /** A builder for [Timeout]. */
- class Builder internal constructor() {
-
- private var connect: Duration? = null
- private var read: Duration? = null
- private var write: Duration? = null
- private var request: Duration? = null
-
- @JvmSynthetic
- internal fun from(timeout: Timeout) = apply {
- connect = timeout.connect
- read = timeout.read
- write = timeout.write
- request = timeout.request
- }
-
- /**
- * The maximum time allowed to establish a connection with a host.
- *
- * A value of [Duration.ZERO] means there's no timeout.
- *
- * Defaults to `Duration.ofMinutes(1)`.
- */
- fun connect(connect: Duration?) = apply { this.connect = connect }
-
- /** Alias for calling [Builder.connect] with `connect.orElse(null)`. */
- fun connect(connect: Optional) = connect(connect.getOrNull())
-
- /**
- * The maximum time allowed between two data packets when waiting for the server’s response.
- *
- * A value of [Duration.ZERO] means there's no timeout.
- *
- * Defaults to `request()`.
- */
- fun read(read: Duration?) = apply { this.read = read }
-
- /** Alias for calling [Builder.read] with `read.orElse(null)`. */
- fun read(read: Optional) = read(read.getOrNull())
-
- /**
- * The maximum time allowed between two data packets when sending the request to the server.
- *
- * A value of [Duration.ZERO] means there's no timeout.
- *
- * Defaults to `request()`.
- */
- fun write(write: Duration?) = apply { this.write = write }
-
- /** Alias for calling [Builder.write] with `write.orElse(null)`. */
- fun write(write: Optional) = write(write.getOrNull())
-
- /**
- * The maximum time allowed for a complete HTTP call, not including retries.
- *
- * This includes resolving DNS, connecting, writing the request body, server processing, as
- * well as reading the response body.
- *
- * A value of [Duration.ZERO] means there's no timeout.
- *
- * Defaults to `Duration.ofMinutes(1)`.
- */
- fun request(request: Duration?) = apply { this.request = request }
-
- /** Alias for calling [Builder.request] with `request.orElse(null)`. */
- fun request(request: Optional) = request(request.getOrNull())
-
- /**
- * Returns an immutable instance of [Timeout].
- *
- * Further updates to this [Builder] will not mutate the returned instance.
- */
- fun build(): Timeout = Timeout(connect, read, write, request)
- }
-
- @JvmSynthetic
- internal fun assign(target: Timeout): Timeout =
- target
- .toBuilder()
- .apply {
- connect?.let(this::connect)
- read?.let(this::read)
- write?.let(this::write)
- request?.let(this::request)
- }
- .build()
-
- override fun equals(other: Any?): Boolean {
- if (this === other) {
- return true
- }
-
- return other is Timeout &&
- connect == other.connect &&
- read == other.read &&
- write == other.write &&
- request == other.request
- }
-
- override fun hashCode(): Int = Objects.hash(connect, read, write, request)
-
- override fun toString() =
- "Timeout{connect=$connect, read=$read, write=$write, request=$request}"
-}
diff --git a/src/main/java/com/google/genai/interactions/core/Utils.kt b/src/main/java/com/google/genai/interactions/core/Utils.kt
deleted file mode 100644
index 9a9dec8ebdf..00000000000
--- a/src/main/java/com/google/genai/interactions/core/Utils.kt
+++ /dev/null
@@ -1,131 +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
-*
-* http://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.
-*/
-
-@file:JvmName("Utils")
-
-package com.google.genai.interactions.core
-
-import com.google.genai.interactions.errors.GeminiNextGenApiInvalidDataException
-import java.util.Collections
-import java.util.SortedMap
-import java.util.concurrent.CompletableFuture
-import java.util.concurrent.locks.Lock
-
-@JvmSynthetic
-internal fun T?.getOrThrow(name: String): T =
- this ?: throw GeminiNextGenApiInvalidDataException("`${name}` is not present")
-
-@JvmSynthetic
-internal fun List.toImmutable(): List =
- if (isEmpty()) Collections.emptyList() else Collections.unmodifiableList(toList())
-
-@JvmSynthetic
-internal fun Map.toImmutable(): Map =
- if (isEmpty()) immutableEmptyMap() else Collections.unmodifiableMap(toMap())
-
-@JvmSynthetic internal fun immutableEmptyMap(): Map = Collections.emptyMap()
-
-@JvmSynthetic
-internal fun , V> SortedMap.toImmutable(): SortedMap =
- if (isEmpty()) Collections.emptySortedMap()
- else Collections.unmodifiableSortedMap(toSortedMap(comparator()))
-
-/**
- * Returns all elements that yield the largest value for the given function, or an empty list if
- * there are zero elements.
- *
- * This is similar to [Sequence.maxByOrNull] except it returns _all_ elements that yield the largest
- * value; not just the first one.
- */
-@JvmSynthetic
-internal fun > Sequence.allMaxBy(selector: (T) -> R): List {
- var maxValue: R? = null
- val maxElements = mutableListOf()
-
- val iterator = iterator()
- while (iterator.hasNext()) {
- val element = iterator.next()
- val value = selector(element)
- if (maxValue == null || value > maxValue) {
- maxValue = value
- maxElements.clear()
- maxElements.add(element)
- } else if (value == maxValue) {
- maxElements.add(element)
- }
- }
-
- return maxElements
-}
-
-/**
- * Returns whether [this] is equal to [other].
- *
- * This differs from [Object.equals] because it also deeply equates arrays based on their contents,
- * even when there are arrays directly nested within other arrays.
- */
-@JvmSynthetic
-internal infix fun Any?.contentEquals(other: Any?): Boolean =
- arrayOf(this).contentDeepEquals(arrayOf(other))
-
-/**
- * Returns a hash of the given sequence of [values].
- *
- * This differs from [java.util.Objects.hash] because it also deeply hashes arrays based on their
- * contents, even when there are arrays directly nested within other arrays.
- */
-@JvmSynthetic internal fun contentHash(vararg values: Any?): Int = values.contentDeepHashCode()
-
-/**
- * Returns a [String] representation of [this].
- *
- * This differs from [Object.toString] because it also deeply stringifies arrays based on their
- * contents, even when there are arrays directly nested within other arrays.
- */
-@JvmSynthetic
-internal fun Any?.contentToString(): String {
- var string = arrayOf(this).contentDeepToString()
- if (string.startsWith('[')) {
- string = string.substring(1)
- }
- if (string.endsWith(']')) {
- string = string.substring(0, string.length - 1)
- }
- return string
-}
-
-internal interface Enum
-
-/**
- * Executes the given [action] while holding the lock, returning a [CompletableFuture] with the
- * result.
- *
- * @param action The asynchronous action to execute while holding the lock
- * @return A [CompletableFuture] that completes with the result of the action
- */
-@JvmSynthetic
-internal fun Lock.withLockAsync(action: () -> CompletableFuture): CompletableFuture {
- lock()
- val future =
- try {
- action()
- } catch (e: Throwable) {
- unlock()
- throw e
- }
- future.whenComplete { _, _ -> unlock() }
- return future
-}
diff --git a/src/main/java/com/google/genai/interactions/core/Values.kt b/src/main/java/com/google/genai/interactions/core/Values.kt
deleted file mode 100644
index f80ec11fad4..00000000000
--- a/src/main/java/com/google/genai/interactions/core/Values.kt
+++ /dev/null
@@ -1,739 +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
-*
-* http://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.interactions.core
-
-import com.fasterxml.jackson.annotation.JacksonAnnotationsInside
-import com.fasterxml.jackson.annotation.JsonCreator
-import com.fasterxml.jackson.annotation.JsonInclude
-import com.fasterxml.jackson.core.JsonGenerator
-import com.fasterxml.jackson.core.ObjectCodec
-import com.fasterxml.jackson.core.type.TypeReference
-import com.fasterxml.jackson.databind.BeanProperty
-import com.fasterxml.jackson.databind.DeserializationContext
-import com.fasterxml.jackson.databind.JavaType
-import com.fasterxml.jackson.databind.JsonDeserializer
-import com.fasterxml.jackson.databind.JsonNode
-import com.fasterxml.jackson.databind.SerializerProvider
-import com.fasterxml.jackson.databind.annotation.JsonDeserialize
-import com.fasterxml.jackson.databind.annotation.JsonSerialize
-import com.fasterxml.jackson.databind.node.JsonNodeType.ARRAY
-import com.fasterxml.jackson.databind.node.JsonNodeType.BINARY
-import com.fasterxml.jackson.databind.node.JsonNodeType.BOOLEAN
-import com.fasterxml.jackson.databind.node.JsonNodeType.MISSING
-import com.fasterxml.jackson.databind.node.JsonNodeType.NULL
-import com.fasterxml.jackson.databind.node.JsonNodeType.NUMBER
-import com.fasterxml.jackson.databind.node.JsonNodeType.OBJECT
-import com.fasterxml.jackson.databind.node.JsonNodeType.POJO
-import com.fasterxml.jackson.databind.node.JsonNodeType.STRING
-import com.fasterxml.jackson.databind.ser.std.NullSerializer
-import com.google.genai.interactions.errors.GeminiNextGenApiInvalidDataException
-import java.io.InputStream
-import java.util.Objects
-import java.util.Optional
-
-/**
- * A class representing a serializable JSON field.
- *
- * It can either be a [KnownValue] value of type [T], matching the type the SDK expects, or an
- * arbitrary JSON value that bypasses the type system (via [JsonValue]).
- */
-@JsonDeserialize(using = JsonField.Deserializer::class)
-sealed class JsonField {
-
- /**
- * Returns whether this field is missing, which means it will be omitted from the serialized
- * JSON entirely.
- */
- fun isMissing(): Boolean = this is JsonMissing
-
- /** Whether this field is explicitly set to `null`. */
- fun isNull(): Boolean = this is JsonNull
-
- /**
- * Returns an [Optional] containing this field's "known" value, meaning it matches the type the
- * SDK expects, or an empty [Optional] if this field contains an arbitrary [JsonValue].
- *
- * This is the opposite of [asUnknown].
- */
- fun asKnown():
- Optional<
- // Safe because `Optional` is effectively covariant, but Kotlin doesn't know that.
- @UnsafeVariance
- T
- > = Optional.ofNullable((this as? KnownValue)?.value)
-
- /**
- * Returns an [Optional] containing this field's arbitrary [JsonValue], meaning it mismatches
- * the type the SDK expects, or an empty [Optional] if this field contains a "known" value.
- *
- * This is the opposite of [asKnown].
- */
- fun asUnknown(): Optional = Optional.ofNullable(this as? JsonValue)
-
- /**
- * Returns an [Optional] containing this field's boolean value, or an empty [Optional] if it
- * doesn't contain a boolean.
- *
- * This method checks for both a [KnownValue] containing a boolean and for [JsonBoolean].
- */
- fun asBoolean(): Optional =
- when (this) {
- is JsonBoolean -> Optional.of(value)
- is KnownValue -> Optional.ofNullable(value as? Boolean)
- else -> Optional.empty()
- }
-
- /**
- * Returns an [Optional] containing this field's numerical value, or an empty [Optional] if it
- * doesn't contain a number.
- *
- * This method checks for both a [KnownValue] containing a number and for [JsonNumber].
- */
- fun asNumber(): Optional =
- when (this) {
- is JsonNumber -> Optional.of(value)
- is KnownValue -> Optional.ofNullable(value as? Number)
- else -> Optional.empty()
- }
-
- /**
- * Returns an [Optional] containing this field's string value, or an empty [Optional] if it
- * doesn't contain a string.
- *
- * This method checks for both a [KnownValue] containing a string and for [JsonString].
- */
- fun asString(): Optional =
- when (this) {
- is JsonString -> Optional.of(value)
- is KnownValue -> Optional.ofNullable(value as? String)
- else -> Optional.empty()
- }
-
- fun asStringOrThrow(): String =
- asString().orElseThrow { GeminiNextGenApiInvalidDataException("Value is not a string") }
-
- /**
- * Returns an [Optional] containing this field's list value, or an empty [Optional] if it
- * doesn't contain a list.
- *
- * This method checks for both a [KnownValue] containing a list and for [JsonArray].
- */
- fun asArray(): Optional> =
- when (this) {
- is JsonArray -> Optional.of(values)
- is KnownValue ->
- Optional.ofNullable(
- (value as? List<*>)?.map {
- try {
- JsonValue.from(it)
- } catch (e: IllegalArgumentException) {
- // The known value is a list, but not all values are convertible to
- // `JsonValue`.
- return Optional.empty()
- }
- }
- )
- else -> Optional.empty()
- }
-
- /**
- * Returns an [Optional] containing this field's map value, or an empty [Optional] if it doesn't
- * contain a map.
- *
- * This method checks for both a [KnownValue] containing a map and for [JsonObject].
- */
- fun asObject(): Optional