Fixup tool calling

This commit is contained in:
2026-06-04 10:03:36 -05:00
parent a06aa531f6
commit 2cdb06cffe
4 changed files with 45 additions and 35 deletions
+22 -14
View File
@@ -223,10 +223,10 @@ struct HarnessConfig {
DRH_DEFINE_TYPE_OPTIONAL(HarnessConfig, max_tool_iterations, verbose, depth)
struct FunctionCall {
std::string name;
std::string arguments;
std::string name = "";
std::string arguments = "";
};
DRH_DEFINE_TYPE_REQUIRED(FunctionCall, name, arguments)
DRH_DEFINE_TYPE_OPTIONAL(FunctionCall, name, arguments)
// Manual registration for vector<FunctionCall> (cannot be auto-registered via macros)
inline const auto json_register_vector_FunctionCall = []() {
@@ -239,19 +239,20 @@ inline const auto json_register_vector_FunctionCall = []() {
}();
struct ToolCall {
std::string id;
std::string type;
FunctionCall function;
size_t index;
std::string id = "";
std::string type = "";
FunctionCall function = {};
};
DRH_DEFINE_TYPE_REQUIRED(ToolCall, id, type, function)
DRH_DEFINE_TYPE_MIXED(ToolCall, (index), (id, type, function))
struct Message {
std::string role;
std::string content;
std::string reasoning;
std::string reasoning_content;
std::string tool_call_id;
std::vector<ToolCall> tool_calls;
std::string role = "";
std::string content = "";
std::string reasoning = "";
std::string reasoning_content = "";
std::string tool_call_id = "";
std::vector<ToolCall> tool_calls = {};
std::string dump(int indent = -1) const;
};
@@ -361,11 +362,18 @@ struct SkillToolParams {
};
DRH_DEFINE_TYPE_REQUIRED(SkillToolParams, name)
struct NestedMixedTest {
std::string name = "";
std::string arguments = "";
};
DRH_DEFINE_TYPE_REQUIRED(NestedMixedTest, name, arguments)
// Test struct for json_to_field - has both primitive and custom type fields
struct MixedFieldsStruct {
std::string name;
int count;
FunctionCall func;
NestedMixedTest func;
};
DRH_DEFINE_TYPE_MIXED(MixedFieldsStruct, (name, count, func), ())
+22 -2
View File
@@ -138,18 +138,37 @@ std::expected<Message, std::string> OllamaClient::chat(const std::vector<Message
auto partial_message = &chat_response->choices[0].delta;
//std::cerr << new_packet << std::endl;
total.content += partial_message->content;
total.reasoning_content += partial_message->reasoning_content;
total.reasoning += partial_message->reasoning;
total.role += partial_message->role;
total.tool_call_id += partial_message->tool_call_id;
// FIXME:
//total.tool_calls += partial_message->tool_calls;
std::string to_write = partial_message->content
+ partial_message->reasoning_content
+ partial_message->reasoning;
for (auto const& x : partial_message->tool_calls)
{
if (x.index < 100)
{
while (total.tool_calls.size() <= x.index)
{
total.tool_calls.push_back(ToolCall{x.index});
}
to_write += x.function.name;
to_write += x.function.arguments;
total.tool_calls[x.index].function.arguments += x.function.arguments;
total.tool_calls[x.index].function.name += x.function.name;
total.tool_calls[x.index].id += x.id;
total.tool_calls[x.index].type += x.type;
}
}
std::string to_write2 = "";
for (char const& c : to_write)
{
@@ -171,6 +190,7 @@ std::expected<Message, std::string> OllamaClient::chat(const std::vector<Message
if (!response_result) {
return std::unexpected(response_result.error());
}
std::cerr << std::endl;
//std::cerr << "Repsonse: " << response_buf << std::endl;
//std::cerr << "Total Tokens: " << ret.usage.total_tokens << std::endl;
//std::cerr << "Input Tokens: " << ret.usage.prompt_tokens << std::endl;
+1 -1
View File
@@ -64,7 +64,7 @@ function message() {
--arg name "$tool_name" \
--argjson args "$tool_args" \
'. + {
"tool_calls": [{"id": "call_1", "type": "function", "function": {"name": $name, "arguments": $args}}],
"tool_calls": [{"index":0, "id": "call_1", "type": "function", "function": {"name": $name, "arguments": $args}}],
"content": null
}')
else
-18
View File
@@ -107,21 +107,3 @@ fi
echo "All MixedFieldsStruct tests passed!"
# ===== Deeply nested type error propagation test (issue 86) =====
# Test Message → vector<ToolCall> → FunctionCall error propagation
# Verify that missing required field in deeply nested type produces proper error message
OUTPUT=$("${DRHARNESS}" -R Message '{"role": "user", "tool_calls": [{"id": "call_1", "type": "function", "function": {"name": "test"}}]}')
if [ "${OUTPUT}" != "error: field 'tool_calls': element 0: field 'function': missing required field: arguments" ]; then
echo "FAIL: Message deeply nested error - expected 'error: field '\''tool_calls'\'': element 0: field '\''function'\'': missing required field: arguments', got '${OUTPUT}'"
exit 1
fi
# Test Message → vector<ToolCall> → ToolCall missing required field
OUTPUT=$("${DRHARNESS}" -R Message '{"role": "user", "tool_calls": [{"id": "call_1", "function": {"name": "test", "arguments": "{}"}}]}')
if [ "${OUTPUT}" != "error: field 'tool_calls': element 0: missing required field: type" ]; then
echo "FAIL: Message tool_calls missing type - expected 'error: field '\''tool_calls'\'': element 0: missing required field: type', got '${OUTPUT}'"
exit 1
fi
echo "All deeply nested type tests passed (issue 86)!"