diff --git a/api/src/main/java/org/apache/flink/agents/api/agents/ReActAgent.java b/api/src/main/java/org/apache/flink/agents/api/agents/ReActAgent.java
index 10ed457e0..798b453f3 100644
--- a/api/src/main/java/org/apache/flink/agents/api/agents/ReActAgent.java
+++ b/api/src/main/java/org/apache/flink/agents/api/agents/ReActAgent.java
@@ -178,7 +178,7 @@ public static void stopAction(Event event, RunnerContext ctx) {
if (response.getExtraArgs().containsKey(STRUCTURED_OUTPUT)) {
output = response.getExtraArgs().get(STRUCTURED_OUTPUT);
} else {
- output = String.valueOf(response.getContent());
+ output = response.getText();
}
ctx.sendEvent(new OutputEvent(output));
diff --git a/api/src/main/java/org/apache/flink/agents/api/chat/messages/AudioBlock.java b/api/src/main/java/org/apache/flink/agents/api/chat/messages/AudioBlock.java
new file mode 100644
index 000000000..ea82c269e
--- /dev/null
+++ b/api/src/main/java/org/apache/flink/agents/api/chat/messages/AudioBlock.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.apache.flink.agents.api.chat.messages;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+import javax.annotation.Nullable;
+
+/** The audio content of a {@link ChatMessage} — see {@link MediaBlock} for the media shape. */
+public final class AudioBlock extends MediaBlock {
+
+ @JsonCreator
+ public AudioBlock(
+ @JsonProperty("media_type") String mediaType,
+ @JsonProperty("data") @Nullable String data,
+ @JsonProperty("url") @Nullable String url,
+ @JsonProperty("name") @Nullable String name,
+ @JsonProperty("size_bytes") @Nullable Long sizeBytes,
+ @JsonProperty("sha256") @Nullable String sha256) {
+ super(mediaType, data, url, name, sizeBytes, sha256);
+ }
+
+ /** Creates an audio block carrying an inline base64 payload. */
+ public static AudioBlock fromBase64(String mediaType, String data) {
+ return new AudioBlock(mediaType, data, null, null, null, null);
+ }
+
+ /** Creates an audio block referencing an externally managed URL or provider file URI. */
+ public static AudioBlock fromUrl(String mediaType, String url) {
+ return new AudioBlock(mediaType, null, url, null, null, null);
+ }
+
+ @Override
+ public String getType() {
+ return "audio";
+ }
+}
diff --git a/api/src/main/java/org/apache/flink/agents/api/chat/messages/ChatMessage.java b/api/src/main/java/org/apache/flink/agents/api/chat/messages/ChatMessage.java
index a15f220ce..24e009323 100644
--- a/api/src/main/java/org/apache/flink/agents/api/chat/messages/ChatMessage.java
+++ b/api/src/main/java/org/apache/flink/agents/api/chat/messages/ChatMessage.java
@@ -20,21 +20,36 @@
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
+import java.util.stream.Collectors;
/**
* Chat message class that represents all message types (user, system, assistant, tool) with
- * different roles
+ * different roles.
+ *
+ *
Message content is an ordered list of typed {@link ContentBlock}s ({@link TextBlock} plus the
+ * media blocks); a text-only message simply carries one {@link TextBlock}. The string convenience
+ * constructors and factories preserve the text-message experience, and {@link #getText()} is the
+ * ordered concatenation of the text blocks.
+ *
+ *
Blocks are immutable and the message snapshots every block list it is handed, so {@link
+ * #getBlocks()} is an unmodifiable view: the content changes only by replacing it through {@link
+ * #setBlocks(List)} or {@link #setText(String)}.
*/
public class ChatMessage {
+ private static final ObjectMapper MAPPER = new ObjectMapper();
+
private MessageRole role;
- private String content;
+ private List blocks;
@JsonProperty("tool_calls")
private List