Parse key=value pairs from ` `. Simplified: we parse key="string" and key=number/bool/null pairs.
| 501 | } |
| 502 | saw_declared_key = true; |
| 503 | const auto & prop_schema = (*props)[it.key()]; |
| 504 | if (prop_schema.is_object() && prop_schema.contains("type") && |
| 505 | !value_matches_type_spec(it.value(), prop_schema["type"])) { |
| 506 | return false; |
| 507 | } |
| 508 | } |
| 509 | |
| 510 | return has_required || saw_declared_key || obj.empty() || |
| 511 | props == nullptr || props->empty(); |
| 512 | } |
| 513 | |
| 514 | static bool parse_single_tool_arg_object(const json & obj, const json & tools, |
| 515 | std::string & out_name, json & out_args) { |
| 516 | const json * fn = single_tool_function(tools); |
| 517 | if (!fn || !fn->contains("name") || !(*fn)["name"].is_string()) return false; |
| 518 | const json * schema = tool_input_schema(*fn); |
| 519 | if (!object_matches_tool_schema(obj, schema)) return false; |
| 520 | out_name = (*fn)["name"].get<std::string>(); |
| 521 | out_args = obj; |
| 522 | return true; |
| 523 | } |
| 524 | |
| 525 | // ─── Function signature parser ────────────────────────────────────────── |
| 526 | |
| 527 | // Parse key=value pairs from `<function=name(k="v", k2=123)></function>`. |
| 528 | // Simplified: we parse key="string" and key=number/bool/null pairs. |
| 529 | static bool parse_function_sig_args(const std::string & arg_text, json & out_args) { |
| 530 | out_args = json::object(); |
| 531 | if (arg_text.empty()) return true; |
| 532 | |
| 533 | size_t pos = 0; |
| 534 | while (pos < arg_text.size()) { |
| 535 | // Skip whitespace and commas |
| 536 | while (pos < arg_text.size() && (arg_text[pos] == ' ' || arg_text[pos] == ',' || |
| 537 | arg_text[pos] == '\n' || arg_text[pos] == '\r' || arg_text[pos] == '\t')) |
| 538 | pos++; |
| 539 | if (pos >= arg_text.size()) break; |
| 540 | |
| 541 | // key |
| 542 | size_t eq = arg_text.find('=', pos); |
| 543 | if (eq == std::string::npos) return false; |
| 544 | std::string key = arg_text.substr(pos, eq - pos); |
| 545 | while (!key.empty() && key.back() == ' ') key.pop_back(); |
| 546 | if (key.empty()) return false; |
| 547 | pos = eq + 1; |
| 548 | |
| 549 | // skip whitespace after = |
| 550 | while (pos < arg_text.size() && arg_text[pos] == ' ') pos++; |
| 551 | if (pos >= arg_text.size()) return false; |
| 552 | |
| 553 | // value |
| 554 | if (arg_text[pos] == '"' || arg_text[pos] == '\'') { |
| 555 | char quote = arg_text[pos]; |
| 556 | pos++; |
| 557 | std::string val; |
| 558 | while (pos < arg_text.size() && arg_text[pos] != quote) { |
| 559 | if (arg_text[pos] == '\\' && pos + 1 < arg_text.size()) { |
| 560 | val += arg_text[pos + 1]; |
no test coverage detected