Commit 5202104b5 for llama.cpp
commit 5202104b59ada9005db079eea43882a2b7bf5802
Author: Sigbjørn Skjæret <sigbjorn.skjaeret@huggingface.co>
Date: Mon Sep 7 09:14:32 2026 +0200
caps : recheck typed content if template checks for string (#28511)
diff --git a/common/jinja/caps.cpp b/common/jinja/caps.cpp
index 9971c021e..c5962ab77 100644
--- a/common/jinja/caps.cpp
+++ b/common/jinja/caps.cpp
@@ -117,6 +117,7 @@ caps caps_get(jinja::program & prog) {
JJ_DEBUG("%s\n", ">>> Running capability check: typed content");
+ bool checks_for_string = false;
static const std::string content_marker = "STRING_MARKER";
// case: typed content support
@@ -136,6 +137,10 @@ caps caps_get(jinja::program & prog) {
[&](context &, bool success, value & messages, value &, const std::string & rendered) {
auto & content = messages->at(0)->at("content");
caps_print_stats(content, "messages[0].content");
+ if (has_op(content, "test_is_string")) {
+ // checked if content is string
+ checks_for_string = true;
+ }
bool used_as_array = has_op(content, "selectattr") || has_op(content, "array_access");
if (used_as_array) {
// accessed as an array
@@ -151,6 +156,33 @@ caps caps_get(jinja::program & prog) {
}
);
+ if (checks_for_string) {
+ caps_try_execute(
+ prog,
+ [&]() {
+ // messages
+ return json::array({
+ {
+ {"role", "user"},
+ {"content", json::array({
+ })}
+ }
+ });
+ },
+ nullptr, // ctx_fn
+ nullptr, // tools_fn
+ [&](context &, bool success, value & messages, value &, const std::string &) {
+ auto & content = messages->at(0)->at("content");
+ caps_print_stats(content, "messages[0].content");
+ bool used_as_array = has_op(content, "selectattr") || has_op(content, "array_access");
+ if (used_as_array && success) {
+ // accessed as an array
+ result.supports_typed_content = true;
+ }
+ }
+ );
+ }
+
JJ_DEBUG("%s\n", ">>> Running capability check: system prompt");
// case: system prompt support
diff --git a/common/jinja/runtime.cpp b/common/jinja/runtime.cpp
index 4ce79e32a..b02992529 100644
--- a/common/jinja/runtime.cpp
+++ b/common/jinja/runtime.cpp
@@ -412,12 +412,18 @@ value test_expression::execute_impl(context & ctx) {
throw std::runtime_error("Invalid test expression");
}
- auto it = builtins.find("test_is_" + test_id);
- JJ_DEBUG("Test expression %s '%s' %s (using function 'test_is_%s')", operand->type().c_str(), test_id.c_str(), negate ? "(negate)" : "", test_id.c_str());
+ const std::string test_name = "test_is_" + test_id;
+ auto it = builtins.find(test_name);
+ JJ_DEBUG("Test expression %s '%s' %s (using function '%s')", operand->type().c_str(), test_id.c_str(), negate ? "(negate)" : "", test_name.c_str());
if (it == builtins.end()) {
throw std::runtime_error("Unknown test '" + test_id + "'");
}
+ if (ctx.is_get_stats) {
+ value_t::stats_t::mark_used(input);
+ input->stats.ops.insert(test_name);
+ }
+
auto res = it->second(args);
if (negate) {