From dc81846cc58c367dc72dab0f0eb264a8e5b4cdaf Mon Sep 17 00:00:00 2001 From: mhyeon-lee Date: Thu, 2 Apr 2026 03:05:40 +0900 Subject: [PATCH] feat: Binding url citation metadata for event --- .../java/com/google/adk/events/Event.java | 24 +++++++++++++++++++ .../adk/flows/llmflows/BaseLlmFlow.java | 2 ++ .../com/google/adk/models/LlmResponse.java | 12 ++++++++++ 3 files changed, 38 insertions(+) diff --git a/core/src/main/java/com/google/adk/events/Event.java b/core/src/main/java/com/google/adk/events/Event.java index cde4e4452..ce1523454 100644 --- a/core/src/main/java/com/google/adk/events/Event.java +++ b/core/src/main/java/com/google/adk/events/Event.java @@ -26,6 +26,7 @@ import com.google.common.collect.ImmutableList; import com.google.common.collect.Iterables; import com.google.errorprone.annotations.CanIgnoreReturnValue; +import com.google.genai.types.CitationMetadata; import com.google.genai.types.Content; import com.google.genai.types.CustomMetadata; import com.google.genai.types.FinishReason; @@ -61,6 +62,7 @@ public class Event extends JsonBaseModel { private @Nullable Double avgLogprobs; private @Nullable Boolean interrupted; private @Nullable String branch; + private @Nullable CitationMetadata citationMetadata; private @Nullable GroundingMetadata groundingMetadata; private @Nullable List customMetadata; private @Nullable String modelVersion; @@ -236,6 +238,16 @@ public void branch(@Nullable String branch) { this.branch = branch; } + /** The citation metadata of the event. */ + @JsonProperty("citationMetadata") + public Optional citationMetadata() { + return Optional.ofNullable(citationMetadata); + } + + public void setCitationMetadata(@Nullable CitationMetadata citationMetadata) { + this.citationMetadata = citationMetadata; + } + /** The grounding metadata of the event. */ @JsonProperty("groundingMetadata") public Optional groundingMetadata() { @@ -359,6 +371,7 @@ public static class Builder { private @Nullable Double avgLogprobs; private @Nullable Boolean interrupted; private @Nullable String branch; + private @Nullable CitationMetadata citationMetadata; private @Nullable GroundingMetadata groundingMetadata; private @Nullable List customMetadata; private @Nullable String modelVersion; @@ -495,6 +508,13 @@ Optional branch() { return Optional.ofNullable(branch); } + @CanIgnoreReturnValue + @JsonProperty("citationMetadata") + public Builder citationMetadata(@Nullable CitationMetadata value) { + this.citationMetadata = value; + return this; + } + @CanIgnoreReturnValue @JsonProperty("groundingMetadata") public Builder groundingMetadata(@Nullable GroundingMetadata value) { @@ -536,6 +556,7 @@ public Event build() { event.setAvgLogprobs(avgLogprobs); event.setInterrupted(interrupted); event.branch(branch); + event.setCitationMetadata(citationMetadata); event.setGroundingMetadata(groundingMetadata); event.setCustomMetadata(customMetadata); event.setModelVersion(modelVersion); @@ -573,6 +594,7 @@ public Builder toBuilder() { .avgLogprobs(this.avgLogprobs) .interrupted(this.interrupted) .branch(this.branch) + .citationMetadata(this.citationMetadata) .groundingMetadata(this.groundingMetadata) .customMetadata(this.customMetadata) .modelVersion(this.modelVersion); @@ -606,6 +628,7 @@ public boolean equals(Object obj) { && Objects.equals(avgLogprobs, other.avgLogprobs) && Objects.equals(interrupted, other.interrupted) && Objects.equals(branch, other.branch) + && Objects.equals(citationMetadata, other.branch) && Objects.equals(groundingMetadata, other.groundingMetadata) && Objects.equals(customMetadata, other.customMetadata) && Objects.equals(modelVersion, other.modelVersion); @@ -634,6 +657,7 @@ public int hashCode() { avgLogprobs, interrupted, branch, + citationMetadata, groundingMetadata, customMetadata, modelVersion, diff --git a/core/src/main/java/com/google/adk/flows/llmflows/BaseLlmFlow.java b/core/src/main/java/com/google/adk/flows/llmflows/BaseLlmFlow.java index 48d141819..2693df8c1 100644 --- a/core/src/main/java/com/google/adk/flows/llmflows/BaseLlmFlow.java +++ b/core/src/main/java/com/google/adk/flows/llmflows/BaseLlmFlow.java @@ -736,7 +736,9 @@ private Event buildModelResponseEvent( .errorMessage(llmResponse.errorMessage().orElse(null)) .interrupted(llmResponse.interrupted().orElse(null)) .turnComplete(llmResponse.turnComplete().orElse(null)) + .citationMetadata(llmResponse.citationMetadata().orElse(null)) .groundingMetadata(llmResponse.groundingMetadata().orElse(null)) + .customMetadata(llmResponse.customMetadata().orElse(null)) .avgLogprobs(llmResponse.avgLogprobs().orElse(null)) .finishReason(llmResponse.finishReason().orElse(null)) .usageMetadata(llmResponse.usageMetadata().orElse(null)) diff --git a/core/src/main/java/com/google/adk/models/LlmResponse.java b/core/src/main/java/com/google/adk/models/LlmResponse.java index 560e2abcc..892f251d5 100644 --- a/core/src/main/java/com/google/adk/models/LlmResponse.java +++ b/core/src/main/java/com/google/adk/models/LlmResponse.java @@ -52,6 +52,14 @@ public abstract class LlmResponse extends JsonBaseModel { @JsonProperty("content") public abstract Optional content(); + /** + * Returns the citation metadata of the first candidate in the response, if available. + * + * @return An {@link Optional} containing {@link CitationMetadata} or empty. + */ + @JsonProperty("citationMetadata") + public abstract Optional citationMetadata(); + /** * Returns the grounding metadata of the first candidate in the response, if available. * @@ -133,6 +141,9 @@ static LlmResponse.Builder jacksonBuilder() { @JsonProperty("interrupted") public abstract Builder interrupted(@Nullable Boolean interrupted); + @JsonProperty("citationMetadata") + public abstract Builder citationMetadata(@Nullable CitationMetadata citationMetadata); + @JsonProperty("groundingMetadata") public abstract Builder groundingMetadata(@Nullable GroundingMetadata groundingMetadata); @@ -172,6 +183,7 @@ public final Builder response(GenerateContentResponse response) { this.finishReason(candidate.finishReason().orElse(null)); if (candidate.content().isPresent()) { this.content(candidate.content().get()); + this.citationMetadata(candidate.citationMetadata().orElse(null)); this.groundingMetadata(candidate.groundingMetadata().orElse(null)); } else { candidate.finishReason().ifPresent(this::errorCode);