MCPcopy Create free account
hub / github.com/Luce-Org/lucebox-hub / parse_tool_calls

Function parse_tool_calls

server/src/server/tool_parser.cpp:574–782  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

572 int depth = 0;
573 while (end < arg_text.size()) {
574 char c = arg_text[end];
575 if (c == '(' || c == '[' || c == '{') depth++;
576 else if (c == ')' || c == ']' || c == '}') {
577 if (depth == 0) break;
578 depth--;
579 }
580 else if (c == ',' && depth == 0) break;
581 end++;
582 }
583 std::string raw = arg_text.substr(pos, end - pos);
584 while (!raw.empty() && raw.back() == ' ') raw.pop_back();
585 pos = end;
586
587 // Try to parse as JSON literal
588 try {
589 out_args[key] = json::parse(raw);
590 } catch (...) {
591 out_args[key] = raw;
592 }
593 }
594 }
595 return true;
596}
597
598// ─── Main parser ────────────────────────────────────────────────────────
599
600ToolParseResult parse_tool_calls(const std::string & text, const json & tools) {
601 ToolParseResult result;
602 std::vector<Span> removals;
603
604 auto add_call = [&](const std::string & fn_name, const json & args,
605 size_t start, size_t end) {
606 if (!tool_allowed(tools, fn_name)) return;
607 ToolCall tc;
608 tc.id = generate_call_id();
609 tc.name = fn_name;
610 tc.arguments = args.dump();
611 result.tool_calls.push_back(std::move(tc));
612 removals.push_back({start, end});
613 };
614
615 // Pattern 8 (Laguna): <tool_call>NAME\n<arg_key>K</arg_key>\n
616 // <arg_value>V</arg_value>...\n</tool_call>. Values are raw strings or
617 // JSON (the template emits non-strings via tojson); coerce via the
618 // declared tool schema like the other patterns. Checked before pattern 1
619 // so the shared <tool_call> wrapper is not half-consumed by the Qwen
620 // regexes.
621 {
622 size_t pos = 0;
623 while ((pos = text.find("<tool_call>", pos)) != std::string::npos) {
624 const size_t body_start = pos + 11;
625 const size_t close = text.find("</tool_call>", body_start);
626 if (close == std::string::npos) break;
627 const std::string body = text.substr(body_start, close - body_start);
628 const size_t first_key = body.find("<arg_key>");
629 // Only claim bodies in the Laguna shape: bare name then arg tags
630 // (or a bare name alone for zero-arg calls); leave <function=...>
631 // bodies to the Qwen patterns below.

Calls 14

tool_allowedFunction · 0.85
generate_call_idFunction · 0.85
parse_xml_paramsFunction · 0.85
overlapsFunction · 0.85
parse_function_sig_argsFunction · 0.85
parse_json_tool_callFunction · 0.85
balanced_braces_endFunction · 0.85
coerce_relaxed_jsonFunction · 0.85
span_covers_non_wsFunction · 0.85
clearMethod · 0.80