Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions src/main/java/com/google/genai/Client.java
Original file line number Diff line number Diff line change
Expand Up @@ -629,6 +629,15 @@ Optional<String> baseUrl() {
@Override
public void close() {
apiClient.close();
// android:strip_begin
try {
// apiClient.close() already tears down the shared OkHttp dispatcher/pool; gaosClient.close()
// is called for lifecycle completeness in case it manages other internal resources.
gaosClient.close();
} catch (Exception e) {
// ignore
}
// android:strip_end
}

/**
Expand Down
11 changes: 11 additions & 0 deletions src/main/java/com/google/genai/errors/ApiException.java
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,17 @@ public ApiException(int code, String status, String message) {
this.message = message;
}

/**
* Creates a new ApiException carrying the originating cause (e.g. a reparented gaos error). Lets
* translated interaction errors keep their original stack/message.
*/
public ApiException(int code, String status, String message, Throwable cause) {
super(String.format("%d %s. %s", code, status, message), cause);
this.code = code;
this.status = status;
this.message = message;
}


/**
* Throws an ApiException from the response if the response is not a OK status.
Expand Down
7 changes: 6 additions & 1 deletion src/main/java/com/google/genai/errors/ClientException.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,15 @@
package com.google.genai.errors;

/** Client exception raised by the GenAI API. */
public final class ClientException extends ApiException {
public class ClientException extends ApiException {

/** Creates a new ClientException with the specified message. */
public ClientException(int code, String status, String message) {
super(code, status, message);
}

/** Creates a new ClientException carrying the originating cause. */
public ClientException(int code, String status, String message, Throwable cause) {
super(code, status, message, cause);
}
}
7 changes: 6 additions & 1 deletion src/main/java/com/google/genai/errors/ServerException.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,15 @@
package com.google.genai.errors;

/** Server exception raised by the GenAI API. */
public final class ServerException extends ApiException {
public class ServerException extends ApiException {

/** Creates a new ServerException with the specified message. */
public ServerException(int code, String status, String message) {
super(code, status, message);
}

/** Creates a new ServerException carrying the originating cause. */
public ServerException(int code, String status, String message, Throwable cause) {
super(code, status, message, cause);
}
}
13 changes: 12 additions & 1 deletion src/main/java/com/google/genai/gaos/AsyncGenAI.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
* <p>You can use the Gemini API for use cases like reasoning across text and images, content generation,
* dialogue agents, summarization and classification systems, and more.
*/
public class AsyncGenAI {
public class AsyncGenAI implements java.lang.AutoCloseable {
private static final Headers _headers = Headers.EMPTY;

private final AsyncInteractions interactions;
Expand Down Expand Up @@ -84,4 +84,15 @@ public AsyncEnvironments environments() {
public GenAI sync() {
return syncSDK;
}

/**
* Releases the configured HTTP client's owned resources. The sync and
* async SDKs share one client, which is closed at most once.
*
* @throws Exception if the configured client cannot be closed
*/
@Override
public void close() throws Exception {
this.sdkConfiguration.closeClient();
}
}
21 changes: 15 additions & 6 deletions src/main/java/com/google/genai/gaos/GenAI.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@
import java.lang.String;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ScheduledExecutorService;
import java.util.function.Consumer;

/**
Expand All @@ -41,7 +40,7 @@
* cases like reasoning across text and images, content generation, dialogue agents, summarization and
* classification systems, and more.
*/
public class GenAI {
public class GenAI implements java.lang.AutoCloseable {
private static final Headers _headers = Headers.EMPTY;


Expand Down Expand Up @@ -93,7 +92,7 @@ public Triggers triggers() {

public Environments environments() {
return environments;
}
}private SDKConfiguration sdkConfiguration;
private final AsyncGenAI asyncSDK;

/**
Expand Down Expand Up @@ -195,11 +194,10 @@ public Builder retryConfig(RetryConfig retryConfig) {
* @param retryScheduler The ScheduledExecutorService to use.
* @return The builder instance.
*/
public Builder asyncRetryScheduler(ScheduledExecutorService retryScheduler) {
public Builder asyncRetryScheduler(java.util.concurrent.ScheduledExecutorService retryScheduler) {
this.sdkConfiguration.setAsyncRetryScheduler(retryScheduler);
return this;
}

/**
* Enables debug logging for HTTP requests and responses, including JSON body content.
* <p>
Expand Down Expand Up @@ -276,13 +274,14 @@ public static Builder builder() {

private GenAI(SDKConfiguration sdkConfiguration) {
sdkConfiguration.initialize();
sdkConfiguration = sdkConfiguration.hooks().sdkInit(sdkConfiguration);
this.interactions = new Interactions(sdkConfiguration);
this.webhooks = new Webhooks(sdkConfiguration);
this.agents = new Agents(sdkConfiguration);
this.triggers = new Triggers(sdkConfiguration);
this.environments = new Environments(sdkConfiguration);
sdkConfiguration = sdkConfiguration.hooks().sdkInit(sdkConfiguration);
this.asyncSDK = new AsyncGenAI(this, sdkConfiguration);
this.sdkConfiguration = sdkConfiguration;
}

/**
Expand All @@ -294,4 +293,14 @@ public AsyncGenAI async() {
return asyncSDK;
}


/**
* Releases the configured HTTP client's owned resources.
*
* @throws Exception if the configured client cannot be closed
*/
@Override
public void close() throws Exception {
this.sdkConfiguration.closeClient();
}
}
13 changes: 12 additions & 1 deletion src/main/java/com/google/genai/gaos/SDKConfiguration.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public class SDKConfiguration {
private static final String LANGUAGE = "java";
public static final String OPENAPI_DOC_VERSION = "v1beta";
public static final String SDK_VERSION = "0.1.0";
public static final String GEN_VERSION = "2.924.0";
public static final String GEN_VERSION = "2.930.0";
private static final String BASE_PACKAGE = "com.google.genai.gaos";
public static final String USER_AGENT =
String.format("speakeasy-sdk/%s %s %s %s %s",
Expand All @@ -64,6 +64,17 @@ public void setClient(HTTPClient client) {
Utils.checkNotNull(client, "client");
this.client = client;
}

private final java.util.concurrent.atomic.AtomicReference<Object> closedClient =
new java.util.concurrent.atomic.AtomicReference<>();

public void closeClient() throws Exception {
Object client = client();
if (closedClient.getAndSet(client) != client
&& client instanceof java.lang.AutoCloseable) {
((java.lang.AutoCloseable) client).close();
}
}

private String serverUrl;

Expand Down
71 changes: 20 additions & 51 deletions src/main/java/com/google/genai/gaos/hooks/SDKHooks.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,6 @@

package com.google.genai.gaos.hooks;

import com.google.genai.gaos.models.shared.Security;
import com.google.genai.gaos.utils.HasSecurity;
import com.google.genai.gaos.utils.transport.HttpRequest;
import java.util.Map;
import java.util.concurrent.CompletableFuture;

//
// This file is written once by speakeasy code generation and
// thereafter will not be overwritten by speakeasy updates. As a
Expand All @@ -35,55 +29,30 @@ private SDKHooks() {
}

public static void initialize(com.google.genai.gaos.utils.Hooks hooks) {
hooks.registerBeforeRequest(
(context, request) -> {
if (context.securitySource().isPresent()) {
HasSecurity hasSecurity = context.securitySource().get().getSecurity();
if (hasSecurity instanceof Security) {
Security security = (Security) hasSecurity;
HttpRequest.Builder builder = request.toBuilder();
// register synchronous hooks here
// hooks.registerBeforeRequest(...);
// hooks.registerAfterSuccess(...);
// hooks.registerAfterError(...);

if (security.defaultHeaders().isPresent()) {
for (Map.Entry<String, String> entry : security.defaultHeaders().get().entrySet()) {
builder.setHeader(entry.getKey(), entry.getValue());
}
}
if (security.apiKey().isPresent()) {
builder.setHeader("x-goog-api-key", security.apiKey().get());
} else if (security.accessToken().isPresent()) {
builder.setHeader("Authorization", "Bearer " + security.accessToken().get());
}
return builder.build();
}
}
return request;
});
// for more information see
// https://www.speakeasy.com/docs/additional-features/sdk-hooks
}

public static void initialize(com.google.genai.gaos.utils.AsyncHooks asyncHooks) {
asyncHooks.registerBeforeRequest(
(context, request) -> {
if (context.securitySource().isPresent()) {
HasSecurity hasSecurity = context.securitySource().get().getSecurity();
if (hasSecurity instanceof Security) {
Security security = (Security) hasSecurity;
HttpRequest.Builder builder = request.toBuilder();

if (security.defaultHeaders().isPresent()) {
for (Map.Entry<String, String> entry : security.defaultHeaders().get().entrySet()) {
builder.setHeader(entry.getKey(), entry.getValue());
}
}
if (security.apiKey().isPresent()) {
builder.setHeader("x-goog-api-key", security.apiKey().get());
} else if (security.accessToken().isPresent()) {
builder.setHeader("Authorization", "Bearer " + security.accessToken().get());
}
return CompletableFuture.completedFuture(builder.build());
}
}
return CompletableFuture.completedFuture(request);
});
// register async hooks here
// asyncHooks.registerBeforeRequest(...);
// asyncHooks.registerAfterSuccess(...);
// asyncHooks.registerAfterError(...);

// NOTE: If you have existing synchronous hooks, you can adapt them using HookAdapters:
// asyncHooks.registerAfterError(com.google.genai.gaos.utils.HookAdapters.adapt(mySyncHook));

// PERFORMANCE TIP: For better performance, implement async hooks directly using
// non-blocking I/O (NIO) APIs instead of adapting synchronous hooks, as adapters
// offload execution to the ForkJoinPool which can introduce overhead.

// for more information see
// https://www.speakeasy.com/docs/additional-features/sdk-hooks
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
* An exception associated with Authentication or Authorization.
*/
@SuppressWarnings("serial")
public class AuthException extends GenAiException {
public class AuthException extends GaosClientException {

public AuthException(String message, int code, byte[] body, HttpResponse<InputStream> rawResponse) {
super(message, code, body, rawResponse, null);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
import java.util.Optional;

@SuppressWarnings("serial")
public class CancelInteractionByIdClientError extends GenAiException {
public class CancelInteractionByIdClientError extends GaosClientException {

@Nullable
private final Data data;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
import java.util.Optional;

@SuppressWarnings("serial")
public class CancelInteractionByIdServerError extends GenAiException {
public class CancelInteractionByIdServerError extends GaosServerException {

@Nullable
private final Data data;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
import java.util.Optional;

@SuppressWarnings("serial")
public class CreateInteractionClientError extends GenAiException {
public class CreateInteractionClientError extends GaosClientException {

@Nullable
private final Data data;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
import java.util.Optional;

@SuppressWarnings("serial")
public class CreateInteractionServerError extends GenAiException {
public class CreateInteractionServerError extends GaosServerException {

@Nullable
private final Data data;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
import java.util.Optional;

@SuppressWarnings("serial")
public class DeleteInteractionClientError extends GenAiException {
public class DeleteInteractionClientError extends GaosClientException {

@Nullable
private final Data data;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
import java.util.Optional;

@SuppressWarnings("serial")
public class DeleteInteractionServerError extends GenAiException {
public class DeleteInteractionServerError extends GaosServerException {

@Nullable
private final Data data;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@
* Thrown by a service call when an error response occurs. Contains details about the response.
*/
@SuppressWarnings("serial")
public class SDKException extends GenAiException {
public class GaosApiException extends GaosBaseException {

public SDKException(
public GaosApiException(
String message,
int code,
@Nullable byte[] body,
Expand All @@ -41,18 +41,18 @@ public SDKException(
super(message, code, body, rawResponse, cause);
}

public static SDKException from(String message, HttpResponse<InputStream> rawResponse) {
public static GaosApiException from(String message, HttpResponse<InputStream> rawResponse) {
return from(message, rawResponse, null);
}

public static SDKException from(String message, HttpResponse<InputStream> rawResponse, @Nullable Throwable cause) {
public static GaosApiException from(String message, HttpResponse<InputStream> rawResponse, @Nullable Throwable cause) {
try {
return new SDKException(
return new GaosApiException(
message, rawResponse.statusCode(), Utils.extractByteArrayFromBody(rawResponse), rawResponse, cause);
} catch (IOException e) {
// Gracefully handle IOExceptions that occur while reading the body
// by returning an error without a body.
return new SDKException(
return new GaosApiException(
message, rawResponse.statusCode(), null, rawResponse, cause);
}
}
Expand Down
Loading
Loading