From cb12d57a6c31acc29e77e4cea25485c85264e59b Mon Sep 17 00:00:00 2001 From: Lennart Austenfeld Date: Fri, 1 Aug 2025 15:28:39 +0200 Subject: [PATCH 1/3] vendor : update vendored copy of google/minja Signed-off-by: Lennart Austenfeld --- vendor/minja/chat-template.hpp | 12 +++++++----- vendor/minja/minja.hpp | 28 +++++++++++++++++++++++----- 2 files changed, 30 insertions(+), 10 deletions(-) diff --git a/vendor/minja/chat-template.hpp b/vendor/minja/chat-template.hpp index ab5b521dd462a..8f617dbfdff96 100644 --- a/vendor/minja/chat-template.hpp +++ b/vendor/minja/chat-template.hpp @@ -162,10 +162,15 @@ class chat_template { }), false); caps_.supports_tools = contains(out, "some_tool"); + auto out_empty = try_raw_render(json::array({dummy_user_msg, {{"role", "assistant"}, {"content", ""}}}), {}, false); + auto out_null = try_raw_render(json::array({dummy_user_msg, {{"role", "assistant"}, {"content", nullptr}}}), {}, false); + caps_.requires_non_null_content = contains(out_empty, user_needle) && !contains(out_null, user_needle); + + json j_null; auto make_tool_calls_msg = [&](const json & tool_calls) { return json { {"role", "assistant"}, - {"content", nullptr}, + {"content", caps_.requires_non_null_content? "" : j_null}, {"tool_calls", tool_calls}, }; }; @@ -195,9 +200,6 @@ class chat_template { caps_.supports_tool_calls = tool_call_renders_str_arguments || tool_call_renders_obj_arguments; caps_.requires_object_arguments = !tool_call_renders_str_arguments && tool_call_renders_obj_arguments; - auto out_empty = try_raw_render(json::array({dummy_user_msg, {{"role", "assistant"}, {"content", ""}}}), {}, false); - auto out_null = try_raw_render(json::array({dummy_user_msg, {{"role", "assistant"}, {"content", nullptr}}}), {}, false); - caps_.requires_non_null_content = contains(out_empty, user_needle) && !contains(out_null, user_needle); if (caps_.supports_tool_calls) { auto dummy_args = caps_.requires_object_arguments ? dummy_args_obj : json(dummy_args_obj.dump()); @@ -234,7 +236,7 @@ class chat_template { }; const json tool_call_msg { {"role", "assistant"}, - {"content", nullptr}, + {"content", caps_.requires_non_null_content ? "" : j_null}, {"tool_calls", json::array({ { // TODO: detect if requires numerical id or fixed length == 6 like Nemo diff --git a/vendor/minja/minja.hpp b/vendor/minja/minja.hpp index f9658ddc0194c..a36e44682f2ba 100644 --- a/vendor/minja/minja.hpp +++ b/vendor/minja/minja.hpp @@ -1246,7 +1246,7 @@ class SubscriptExpr : public Expression { } return result; - } else if (target_value.is_array()) { + } else if (target_value.is_array()) { auto result = Value::array(); for (int64_t i = start; step > 0 ? i < end : i > end; i += step) { result.push_back(target_value.at(i)); @@ -1355,8 +1355,13 @@ class BinaryOpExpr : public Expression { case Op::Gt: return l > r; case Op::Le: return l <= r; case Op::Ge: return l >= r; - case Op::In: return (r.is_array() || r.is_object()) && r.contains(l); - case Op::NotIn: return !(r.is_array() && r.contains(l)); + case Op::In: return (((r.is_array() || r.is_object()) && r.contains(l)) || + (l.is_string() && r.is_string() && + r.to_str().find(l.to_str()) != std::string::npos)); + case Op::NotIn: + return !(((r.is_array() || r.is_object()) && r.contains(l)) || + (l.is_string() && r.is_string() && + r.to_str().find(l.to_str()) != std::string::npos)); default: break; } throw std::runtime_error("Unknown binary operator"); @@ -1552,6 +1557,19 @@ class MethodCallExpr : public Expression { else res[i] = std::tolower(res[i]); } return res; + } else if (method->get_name() == "replace") { + vargs.expectArgs("replace method", {2, 3}, {0, 0}); + auto before = vargs.args[0].get(); + auto after = vargs.args[1].get(); + auto count = vargs.args.size() == 3 ? vargs.args[2].get() + : str.length(); + size_t start_pos = 0; + while ((start_pos = str.find(before, start_pos)) != std::string::npos && + count-- > 0) { + str.replace(start_pos, before.length(), after); + start_pos += after.length(); + } + return str; } } throw std::runtime_error("Unknown method: " + method->get_name()); @@ -2127,8 +2145,8 @@ class Parser { } } } - - if ((has_first_colon || has_second_colon) && (start || end || step)) { + + if ((has_first_colon || has_second_colon)) { index = std::make_shared(slice_loc, std::move(start), std::move(end), std::move(step)); } else { index = std::move(start); From 2f31f4416b3488d80a93a2b2aecc6a011acd354c Mon Sep 17 00:00:00 2001 From: Lennart Austenfeld Date: Fri, 1 Aug 2025 16:07:00 +0200 Subject: [PATCH 2/3] Re-remove trailing whitespace Signed-off-by: Lennart Austenfeld --- vendor/minja/minja.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vendor/minja/minja.hpp b/vendor/minja/minja.hpp index a36e44682f2ba..dd107dccdaf11 100644 --- a/vendor/minja/minja.hpp +++ b/vendor/minja/minja.hpp @@ -1246,7 +1246,7 @@ class SubscriptExpr : public Expression { } return result; - } else if (target_value.is_array()) { + } else if (target_value.is_array()) { auto result = Value::array(); for (int64_t i = start; step > 0 ? i < end : i > end; i += step) { result.push_back(target_value.at(i)); @@ -2145,7 +2145,7 @@ class Parser { } } } - + if ((has_first_colon || has_second_colon)) { index = std::make_shared(slice_loc, std::move(start), std::move(end), std::move(step)); } else { From ecdd861c66ab1af1e8b9aff30de8abff3d4a710d Mon Sep 17 00:00:00 2001 From: Lennart Austenfeld Date: Fri, 1 Aug 2025 16:19:46 +0200 Subject: [PATCH 3/3] Remove another trailing whitespace Signed-off-by: Lennart Austenfeld --- vendor/minja/chat-template.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/minja/chat-template.hpp b/vendor/minja/chat-template.hpp index 8f617dbfdff96..cf113bf2221d2 100644 --- a/vendor/minja/chat-template.hpp +++ b/vendor/minja/chat-template.hpp @@ -165,7 +165,7 @@ class chat_template { auto out_empty = try_raw_render(json::array({dummy_user_msg, {{"role", "assistant"}, {"content", ""}}}), {}, false); auto out_null = try_raw_render(json::array({dummy_user_msg, {{"role", "assistant"}, {"content", nullptr}}}), {}, false); caps_.requires_non_null_content = contains(out_empty, user_needle) && !contains(out_null, user_needle); - + json j_null; auto make_tool_calls_msg = [&](const json & tool_calls) { return json {