Skip to content
Merged
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
2 changes: 1 addition & 1 deletion .release-please-manifest.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
".": "1.2.0"
".": "1.3.0"
}
17 changes: 17 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,22 @@
# Changelog

## [1.3.0](https://github.com/google/adk-java/compare/v1.2.0...v1.3.0) (2026-05-13)


### Features

* Add ChatCompletionsHTTPClient and support for non-streaming requests ([9529c1a](https://github.com/google/adk-java/commit/9529c1aeecb324e1c00c6bd105df2a0e9f67ed26))
* Add conversion from LlmRequest to ChatCompletionsRequest ([d37f6ee](https://github.com/google/adk-java/commit/d37f6ee6d8ec036154593b734f1a3b080847cfea))
* Add SkillSource interface and implementations for loading skills ([509c4aa](https://github.com/google/adk-java/commit/509c4aa75fdc752c2758a1761cbd8946075b310c))
* Add support for refusal content using "[[REFUSAL]]:" prefix ([e9184c9](https://github.com/google/adk-java/commit/e9184c9846d97f65907667aa2a6bbac1f65fed64))
* Refactor BigQueryAgentAnalyticsPlugin for async in preparation for GCS offloading ([d837ef0](https://github.com/google/adk-java/commit/d837ef0164cedd284af6caee84911569109ab7e3))


### Bug Fixes

* Account for nulls in EventActions and State ([582cf7c](https://github.com/google/adk-java/commit/582cf7c2b6534afaf5edfa501391191478d8d8ea))
* upgrade Mockito and JaCoCo for Java 25 compatibility ([8574fc5](https://github.com/google/adk-java/commit/8574fc5bb6ac7edae99306b06c0a610f7da60048))

## [1.2.0](https://github.com/google/adk-java/compare/v1.1.0...v1.2.0) (2026-04-24)


Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,13 +50,13 @@ If you're using Maven, add the following to your dependencies:
<dependency>
<groupId>com.google.adk</groupId>
<artifactId>google-adk</artifactId>
<version>1.2.0</version>
<version>1.3.0</version>
</dependency>
<!-- Dev UI -->
<dependency>
<groupId>com.google.adk</groupId>
<artifactId>google-adk-dev</artifactId>
<version>1.2.0</version>
<version>1.3.0</version>
</dependency>
```

Expand Down
2 changes: 1 addition & 1 deletion a2a/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<parent>
<groupId>com.google.adk</groupId>
<artifactId>google-adk-parent</artifactId>
<version>1.2.1-SNAPSHOT</version><!-- {x-version-update:google-adk:current} -->
<version>1.3.1-SNAPSHOT</version><!-- {x-version-update:google-adk:current} -->
</parent>

<artifactId>google-adk-a2a</artifactId>
Expand Down
2 changes: 1 addition & 1 deletion contrib/firestore-session-service/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
<parent>
<groupId>com.google.adk</groupId>
<artifactId>google-adk-parent</artifactId>
<version>1.2.1-SNAPSHOT</version><!-- {x-version-update:google-adk:current} -->
<version>1.3.1-SNAPSHOT</version><!-- {x-version-update:google-adk:current} -->
<relativePath>../../pom.xml</relativePath>
</parent>

Expand Down
2 changes: 1 addition & 1 deletion contrib/langchain4j/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
<parent>
<groupId>com.google.adk</groupId>
<artifactId>google-adk-parent</artifactId>
<version>1.2.1-SNAPSHOT</version><!-- {x-version-update:google-adk:current} -->
<version>1.3.1-SNAPSHOT</version><!-- {x-version-update:google-adk:current} -->
<relativePath>../../pom.xml</relativePath>
</parent>

Expand Down
2 changes: 1 addition & 1 deletion contrib/planners/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
<parent>
<groupId>com.google.adk</groupId>
<artifactId>google-adk-parent</artifactId>
<version>1.2.1-SNAPSHOT</version><!-- {x-version-update:google-adk:current} -->
<version>1.3.1-SNAPSHOT</version><!-- {x-version-update:google-adk:current} -->
<relativePath>../../pom.xml</relativePath>
</parent>

Expand Down
2 changes: 1 addition & 1 deletion contrib/samples/a2a_basic/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<parent>
<groupId>com.google.adk</groupId>
<artifactId>google-adk-samples</artifactId>
<version>1.2.1-SNAPSHOT</version><!-- {x-version-update:google-adk:current} -->
<version>1.3.1-SNAPSHOT</version><!-- {x-version-update:google-adk:current} -->
<relativePath>..</relativePath>
</parent>

Expand Down
2 changes: 1 addition & 1 deletion contrib/samples/a2a_server/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<parent>
<groupId>com.google.adk</groupId>
<artifactId>google-adk-samples</artifactId>
<version>1.2.1-SNAPSHOT</version><!-- {x-version-update:google-adk:current} -->
<version>1.3.1-SNAPSHOT</version><!-- {x-version-update:google-adk:current} -->
<relativePath>..</relativePath>
</parent>

Expand Down
2 changes: 1 addition & 1 deletion contrib/samples/configagent/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<parent>
<groupId>com.google.adk</groupId>
<artifactId>google-adk-samples</artifactId>
<version>1.2.1-SNAPSHOT</version><!-- {x-version-update:google-adk:current} -->
<version>1.3.1-SNAPSHOT</version><!-- {x-version-update:google-adk:current} -->
<relativePath>..</relativePath>
</parent>

Expand Down
2 changes: 1 addition & 1 deletion contrib/samples/helloworld/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
<parent>
<groupId>com.google.adk</groupId>
<artifactId>google-adk-samples</artifactId>
<version>1.2.1-SNAPSHOT</version><!-- {x-version-update:google-adk:current} -->
<version>1.3.1-SNAPSHOT</version><!-- {x-version-update:google-adk:current} -->
<relativePath>..</relativePath>
</parent>

Expand Down
2 changes: 1 addition & 1 deletion contrib/samples/mcpfilesystem/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
<parent>
<groupId>com.google.adk</groupId>
<artifactId>google-adk-parent</artifactId>
<version>1.2.1-SNAPSHOT</version><!-- {x-version-update:google-adk:current} -->
<version>1.3.1-SNAPSHOT</version><!-- {x-version-update:google-adk:current} -->
<relativePath>../../..</relativePath>
</parent>

Expand Down
2 changes: 1 addition & 1 deletion contrib/samples/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<parent>
<groupId>com.google.adk</groupId>
<artifactId>google-adk-parent</artifactId>
<version>1.2.1-SNAPSHOT</version><!-- {x-version-update:google-adk:current} -->
<version>1.3.1-SNAPSHOT</version><!-- {x-version-update:google-adk:current} -->
<relativePath>../..</relativePath>
</parent>

Expand Down
2 changes: 1 addition & 1 deletion contrib/spring-ai/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
<parent>
<groupId>com.google.adk</groupId>
<artifactId>google-adk-parent</artifactId>
<version>1.2.1-SNAPSHOT</version><!-- {x-version-update:google-adk:current} -->
<version>1.3.1-SNAPSHOT</version><!-- {x-version-update:google-adk:current} -->
<relativePath>../../pom.xml</relativePath>
</parent>

Expand Down
2 changes: 1 addition & 1 deletion core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
<parent>
<groupId>com.google.adk</groupId>
<artifactId>google-adk-parent</artifactId>
<version>1.2.1-SNAPSHOT</version><!-- {x-version-update:google-adk:current} -->
<version>1.3.1-SNAPSHOT</version><!-- {x-version-update:google-adk:current} -->
</parent>

<artifactId>google-adk</artifactId>
Expand Down
2 changes: 1 addition & 1 deletion core/src/main/java/com/google/adk/Version.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
*/
public final class Version {
// Don't touch this, release-please should keep it up to date.
public static final String JAVA_ADK_VERSION = "1.2.0"; // x-release-please-released-version
public static final String JAVA_ADK_VERSION = "1.3.0"; // x-release-please-released-version

private Version() {}
}
100 changes: 84 additions & 16 deletions core/src/main/java/com/google/adk/models/Gemini.java
Original file line number Diff line number Diff line change
Expand Up @@ -226,21 +226,7 @@ public Flowable<LlmResponse> generateContent(LlmRequest llmRequest, boolean stre
() ->
processRawResponses(
Flowable.fromFuture(streamFuture).flatMapIterable(iterable -> iterable)))
.filter(
llmResponse ->
llmResponse
.content()
.flatMap(Content::parts)
.map(
parts ->
!parts.isEmpty()
&& parts.stream()
.anyMatch(
p ->
p.functionCall().isPresent()
|| p.functionResponse().isPresent()
|| p.text().isPresent()))
.orElse(false));
.filter(Gemini::shouldEmit);
} else {
logger.debug("Sending generateContent request to model {}", effectiveModelName);
return Flowable.fromFuture(
Expand Down Expand Up @@ -298,7 +284,28 @@ static Flowable<LlmResponse> processRawResponses(Flowable<GenerateContentRespons
responsesToEmit.add(aggregatedTextResponse);
accumulatedText.setLength(0);
}
responsesToEmit.add(currentProcessedLlmResponse);
if (isEmptyTextOnlyResponse(currentProcessedLlmResponse)) {
// Strip the empty-text content while preserving any carried metadata
// (`usageMetadata`, `finishReason`, `modelVersion`, etc.) by emitting a
// content-less response marked as `partial`. This handles the trailing
// `{parts:[{text:""}], finishReason:STOP}` chunk emitted by some Gemini
// preview models (e.g. 3.1-flash-lite) after a function call: keeping
// the chunk as-is would propagate it as a non-partial event whose
// Event#finalResponse() returns true and prematurely terminate
// BaseLlmFlow#run before the function response is sent back to the
// model; dropping it entirely would lose the carried metadata. If the
// chunk carries no useful metadata at all, suppress it outright.
LlmResponse metadataOnly =
currentProcessedLlmResponse.toBuilder()
.content((Content) null)
.partial(true)
.build();
if (hasUsefulMetadata(metadataOnly)) {
responsesToEmit.add(metadataOnly);
}
} else {
responsesToEmit.add(currentProcessedLlmResponse);
}
}
logger.debug("Responses to emit: {}", responsesToEmit);
return Flowable.fromIterable(responsesToEmit);
Expand Down Expand Up @@ -358,6 +365,67 @@ private static LlmResponse thinkingResponseFromText(String accumulatedThoughtTex
.build();
}

/**
* Returns true if {@code response} should be emitted downstream by the streaming pipeline.
*
* <p>Drops chunks that carry neither semantic content (i.e. they are an empty-text-only response
* per {@link #isEmptyTextOnlyResponse}) nor any useful metadata (per {@link #hasUsefulMetadata}).
*
* <p>Package-private for testing.
*/
static boolean shouldEmit(LlmResponse response) {
return !isEmptyTextOnlyResponse(response) || hasUsefulMetadata(response);
}

/**
* Returns true if {@code response} carries any non-content metadata that should be propagated
* downstream (e.g. {@code usageMetadata}, {@code finishReason}, transcriptions, grounding or
* error info). Inspects only top-level {@link LlmResponse} fields; the response's content/parts
* are intentionally not considered here.
*/
private static boolean hasUsefulMetadata(LlmResponse response) {
return response.usageMetadata().isPresent()
|| response.finishReason().isPresent()
|| response.errorCode().isPresent()
|| response.groundingMetadata().isPresent()
|| response.inputTranscription().isPresent()
|| response.outputTranscription().isPresent();
}

/**
* Returns true if {@code response} consists of exactly one {@link Part} whose only meaningful
* payload is an empty text string (i.e. {@code parts:[{text:""}]}). Such a chunk can be safely
* dropped from the streaming aggregator because it carries no semantic content for the agent
* pipeline. A part is considered to carry semantic content if any of its non-text payloads
* ({@code functionCall}, {@code functionResponse}, {@code inlineData}, {@code executableCode},
* {@code codeExecutionResult}, {@code fileData}, {@code thoughtSignature}, {@code videoMetadata},
* {@code toolCall}, {@code toolResponse}) is present.
*/
private static boolean isEmptyTextOnlyResponse(LlmResponse response) {
return response
.content()
.flatMap(Content::parts)
.map(
parts -> {
if (parts.size() != 1) {
return false;
}
Part part = parts.get(0);
return part.text().map(String::isEmpty).orElse(false)
&& part.functionCall().isEmpty()
&& part.functionResponse().isEmpty()
&& part.inlineData().isEmpty()
&& part.executableCode().isEmpty()
&& part.codeExecutionResult().isEmpty()
&& part.fileData().isEmpty()
&& part.thoughtSignature().isEmpty()
&& part.videoMetadata().isEmpty()
&& part.toolCall().isEmpty()
&& part.toolResponse().isEmpty();
})
.orElse(false);
}

@Override
public BaseLlmConnection connect(LlmRequest llmRequest) {
if (!apiClient.vertexAI()) {
Expand Down
Loading