implemented the missing type: "message" field for user and developer input items in ResponsesApiClient.java, ensuring compliance with the Open Responses specification

This commit is contained in:
extio-de
2026-06-05 00:44:06 +02:00
parent 4453b7c2d1
commit 7969cba37b

View File

@@ -9,9 +9,9 @@ import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.LinkedHashSet;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Consumer;
@@ -27,13 +27,6 @@ import org.springframework.web.client.RestClientResponseException;
import com.fasterxml.jackson.annotation.JsonInclude;
import tools.jackson.core.JacksonException;
import tools.jackson.core.json.JsonReadFeature;
import tools.jackson.databind.DeserializationFeature;
import tools.jackson.databind.JsonNode;
import tools.jackson.databind.ObjectMapper;
import tools.jackson.databind.json.JsonMapper;
import de.extio.lmlib.client.Chunk;
import de.extio.lmlib.client.Client;
import de.extio.lmlib.client.Completion;
@@ -41,16 +34,22 @@ import de.extio.lmlib.client.CompletionFinishReason;
import de.extio.lmlib.client.CompletionStatistics;
import de.extio.lmlib.client.Conversation;
import de.extio.lmlib.client.Conversation.Turn;
import de.extio.lmlib.client.ToolCallData;
import de.extio.lmlib.client.ToolCall;
import de.extio.lmlib.client.ToolCallData;
import de.extio.lmlib.client.ToolDefinition;
import de.extio.lmlib.profile.ModelCategory;
import de.extio.lmlib.profile.ModelProfile;
import de.extio.lmlib.profile.ModelProfile.ModelProvider;
import de.extio.lmlib.profile.ModelProfileService;
import de.extio.lmlib.token.TokenizerResolver;
import tools.jackson.core.JacksonException;
import tools.jackson.core.json.JsonReadFeature;
import tools.jackson.databind.DeserializationFeature;
import tools.jackson.databind.JsonNode;
import tools.jackson.databind.ObjectMapper;
import tools.jackson.databind.json.JsonMapper;
public class ResponsesApiClient implements Client{
public class ResponsesApiClient implements Client {
private static final Logger LOGGER = LoggerFactory.getLogger(ResponsesApiClient.class);
@@ -371,10 +370,19 @@ public class ResponsesApiClient implements Client{
}
final Map<String, Object> item;
if ("assistant".equals(role)) {
item = this.createAssistantMessageInputItem(normalizedText, phase);
final var messageItem = new LinkedHashMap<String, Object>();
messageItem.put("type", "message");
messageItem.put("role", "assistant");
messageItem.put("status", "completed");
messageItem.put("content", List.of(Map.of("type", "output_text", "text", normalizedText)));
if (phase != null && !phase.isBlank()) {
messageItem.put("phase", phase);
}
item = messageItem;
}
else {
final var easyInputMessage = new LinkedHashMap<String, Object>();
easyInputMessage.put("type", "message");
easyInputMessage.put("role", role);
easyInputMessage.put("content", normalizedText);
item = easyInputMessage;
@@ -384,18 +392,6 @@ public class ResponsesApiClient implements Client{
return this.countTokens(inputTextBuilder.toString(), modelProfile) > maxLength && maxLength > 0;
}
private Map<String, Object> createAssistantMessageInputItem(final String normalizedText, final String phase) {
final var messageItem = new LinkedHashMap<String, Object>();
messageItem.put("type", "message");
messageItem.put("role", "assistant");
messageItem.put("status", "completed");
messageItem.put("content", List.of(Map.of("type", "output_text", "text", normalizedText)));
if (phase != null && !phase.isBlank()) {
messageItem.put("phase", phase);
}
return Map.copyOf(messageItem);
}
private boolean addAssistantOutputItems(final List<Map<String, Object>> outputItems, final List<Map<String, Object>> inputItems, final StringBuilder inputTextBuilder, final ModelProfile modelProfile, final int maxLength) {
final var containsFunctionCalls = outputItems.stream().anyMatch(outputItem -> "function_call".equals(outputItem.get("type")));
for (final var outputItem : outputItems) {
@@ -419,7 +415,7 @@ public class ResponsesApiClient implements Client{
if (textTokens <= remainingTokens) {
return text;
}
var tokenized = this.tokenizerResolver.tokenize(text, modelProfile);
final var tokenized = this.tokenizerResolver.tokenize(text, modelProfile);
if (remainingTokens <= 0 || tokenized.isEmpty()) {
return "";
}