fix: strip whitespace from ToolCall fields in multiple clients

This commit is contained in:
extio-de
2026-10-18 00:09:05 +02:00
parent 98c5312089
commit 637e00e07c
4 changed files with 15 additions and 8 deletions

View File

@@ -21,7 +21,6 @@ import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.http.HttpMethod; import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatusCode;
import org.springframework.web.client.RestClient; import org.springframework.web.client.RestClient;
import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude;
@@ -621,7 +620,7 @@ public class AnthropicClient implements Client {
} }
break; break;
case "tool_use": case "tool_use":
toolCalls.add(new ToolCall(block.id(), "tool_use", block.name(), this.serializeToolInput(block.input()))); toolCalls.add(new ToolCall(strip(block.id()), "tool_use", strip(block.name()), this.serializeToolInput(block.input())));
break; break;
default: default:
LOGGER.debug("Ignoring unsupported response content block type: {}", block.type()); LOGGER.debug("Ignoring unsupported response content block type: {}", block.type());
@@ -791,6 +790,10 @@ public class AnthropicClient implements Client {
return this.anthropicDialect == null ? DEFAULT_ANTHROPIC_DIALECT : this.anthropicDialect; return this.anthropicDialect == null ? DEFAULT_ANTHROPIC_DIALECT : this.anthropicDialect;
} }
private static String strip(final String text) {
return text == null ? null : text.strip();
}
private static final class StreamBlock { private static final class StreamBlock {
private String type; private String type;

View File

@@ -295,10 +295,14 @@ public class ChatCompletionClient extends AbstractCompletionClient {
} }
return chatToolCalls.stream() return chatToolCalls.stream()
.filter(Objects::nonNull) .filter(Objects::nonNull)
.map(toolCall -> new ToolCall(toolCall.getId(), toolCall.getType(), toolCall.getFunction() != null ? toolCall.getFunction().getName() : null, toolCall.getFunction() != null ? toolCall.getFunction().getArguments() : null)) .map(toolCall -> new ToolCall(strip(toolCall.getId()), strip(toolCall.getType()), toolCall.getFunction() != null ? strip(toolCall.getFunction().getName()) : null, toolCall.getFunction() != null ? strip(toolCall.getFunction().getArguments()) : null))
.toList(); .toList();
} }
private static String strip(final String text) {
return text == null ? null : text.strip();
}
private List<ChatMessage> createChats(final Conversation conversation, final ModelProfile modelProfile) { private List<ChatMessage> createChats(final Conversation conversation, final ModelProfile modelProfile) {
final List<ChatMessage> chat = new ArrayList<>(); final List<ChatMessage> chat = new ArrayList<>();
final AtomicInteger tokens = new AtomicInteger(); final AtomicInteger tokens = new AtomicInteger();

View File

@@ -609,9 +609,9 @@ public class ResponsesApiClient implements Client {
} }
final var callId = this.text(item, "call_id"); final var callId = this.text(item, "call_id");
toolCalls.add(new ToolCall( toolCalls.add(new ToolCall(
callId.isBlank() ? this.text(item, "id") : callId, callId.isBlank() ? this.text(item, "id") : callId.strip(),
"function", "function",
this.text(item, "name"), this.text(item, "name").strip(),
this.text(item, "arguments"))); this.text(item, "arguments")));
} }
return List.copyOf(toolCalls); return List.copyOf(toolCalls);

View File

@@ -352,9 +352,9 @@ public class OllamaClient implements Client {
continue; continue;
} }
toolCalls.add(new ToolCall( toolCalls.add(new ToolCall(
toolCall.getId() != null && !toolCall.getId().isBlank() ? toolCall.getId() : "ollama-tool-call-" + (i + 1), toolCall.getId() != null && !toolCall.getId().isBlank() ? toolCall.getId().strip() : "ollama-tool-call-" + (i + 1),
toolCall.getType() != null && !toolCall.getType().isBlank() ? toolCall.getType() : "function", toolCall.getType() != null && !toolCall.getType().isBlank() ? toolCall.getType().strip() : "function",
toolCall.getFunction().getName(), toolCall.getFunction().getName().strip(),
this.serializeArguments(toolCall.getFunction().getArguments()))); this.serializeArguments(toolCall.getFunction().getArguments())));
} }
return List.copyOf(toolCalls); return List.copyOf(toolCalls);