@@ -1340,6 +1340,7 @@ static void common_chat_parse_glm_4_5(common_chat_msg_parser & builder) {
13401340 // consume initial spaces
13411341 builder.consume_spaces ();
13421342 builder.try_parse_reasoning (" <think>" , " </think>" );
1343+
13431344 if (!builder.syntax ().parse_tool_calls ) {
13441345 builder.add_content (builder.consume_rest ());
13451346 return ;
@@ -1390,71 +1391,80 @@ static void common_chat_parse_glm_4_5(common_chat_msg_parser & builder) {
13901391 static const common_regex json_tool_calls_start (" \\ {[^}]*\" tool_calls\"\\ s*:\\ s*\\ [" );
13911392
13921393 if (auto res = builder.try_find_regex (json_tool_calls_start)) {
1393- // Move to start of JSON and consume it
13941394 builder.move_to (res->groups [0 ].begin );
1395-
1396- // Define paths for extracting tool call data
1395+
13971396 static const std::vector<std::vector<std::string>> args_paths = {{" tool_calls" , " arguments" }};
13981397 static const std::vector<std::vector<std::string>> content_paths = {{" content" }};
1399-
1398+
14001399 auto json_result = builder.try_consume_json_with_dumped_args (args_paths, content_paths);
1401-
1400+
14021401 if (json_result) {
1403- // if partial skip
14041402 if (json_result->is_partial ) {
1405- throw common_chat_msg_partial_exception (" incomplete tool call" );
1403+ throw common_chat_msg_partial_exception (" incomplete JSON tool call" );
14061404 }
1407-
1405+
14081406 // Handle content field if present
14091407 if (json_result->value .contains (" content" ) && json_result->value .at (" content" ).is_string ()) {
14101408 std::string content = json_result->value .at (" content" );
14111409 builder.add_content (content);
14121410 }
1413-
1411+
14141412 // Handle tool_calls array if present
14151413 if (json_result->value .contains (" tool_calls" ) && json_result->value .at (" tool_calls" ).is_array ()) {
14161414 const auto & tool_calls_array = json_result->value .at (" tool_calls" );
1417-
1415+
14181416 for (size_t i = 0 ; i < tool_calls_array.size (); i++) {
14191417 const auto & tool_call = tool_calls_array[i];
1420-
1418+
14211419 if (!tool_call.is_object ()) {
14221420 continue ;
14231421 }
1424-
1422+
14251423 // Extract tool call fields
1426- std::string name = tool_call.contains (" name" ) && tool_call.at (" name" ).is_string ()
1427- ? tool_call.at (" name" ).get <std::string>()
1428- : " " ;
1429- std::string id = tool_call.contains (" id" ) && tool_call.at (" id" ).is_string ()
1430- ? tool_call.at (" id" ).get <std::string>()
1431- : " " ;
1432- std::string arguments = tool_call.contains (" arguments" )
1433- ? tool_call.at (" arguments" ).dump ()
1434- : " {}" ;
1435-
1424+ std::string name = tool_call.contains (" name" ) && tool_call.at (" name" ).is_string ()
1425+ ? tool_call.at (" name" ).get <std::string>()
1426+ : " " ;
1427+ std::string id = tool_call.contains (" id" ) && tool_call.at (" id" ).is_string ()
1428+ ? tool_call.at (" id" ).get <std::string>()
1429+ : " " ;
1430+
1431+ // Handle arguments intelligently to avoid double-escaping
1432+ std::string arguments;
1433+ if (tool_call.contains (" arguments" )) {
1434+ const auto & args_json = tool_call.at (" arguments" );
1435+ if (args_json.is_string ()) {
1436+ // If already a string, use as-is (model likely pre-stringified)
1437+ arguments = args_json.get <std::string>();
1438+ } else if (args_json.is_object ()) {
1439+ // If object, dump to string
1440+ arguments = args_json.dump ();
1441+ } else {
1442+ continue ;
1443+ }
1444+ } else {
1445+ arguments = " {}" ;
1446+ }
1447+
14361448 if (name.empty ()) {
14371449 continue ;
14381450 }
1439-
1451+
14401452 // Add the tool call
14411453 if (!builder.add_tool_call (name, id, arguments)) {
1442- if (json_result->is_partial ) {
1443- throw common_chat_msg_partial_exception (" incomplete JSON tool call" );
1444- }
1454+ throw common_chat_msg_partial_exception (" incomplete JSON tool call" );
14451455 }
14461456 }
1447-
1457+
14481458 return ; // Exit function after successful JSON parsing
14491459 }
1450-
1460+
14511461 // If partial JSON without complete structure, throw exception
14521462 if (json_result->is_partial ) {
14531463 throw common_chat_msg_partial_exception (" incomplete JSON response" );
14541464 }
14551465 }
14561466 }
1457-
1467+
14581468 builder.add_content (builder.consume_rest ());
14591469}
14601470
0 commit comments