@@ -332,58 +332,36 @@ common_peg_parser analyze_tools::build_tool_parser_tag_tagged(parser_build_conte
332332 const auto & inputs = ctx.inputs ;
333333 bool force_tools = inputs.tool_choice == COMMON_CHAT_TOOL_CHOICE_REQUIRED ;
334334
335+ auto until_suffix = p.rule (" until-suffix" , p.until (arguments.value_suffix ));
336+
335337 common_peg_parser tool_choice = p.choice ();
336338
337339 foreach_function (inputs.tools , [&](const json & tool) {
338340 const auto & func = tool.at (" function" );
339341 std::string name = func.at (" name" );
340- const auto & params = func.contains (" parameters" ) ? func.at (" parameters" ) : json::object ();
342+ auto params = func.contains (" parameters" ) ? func.at (" parameters" ) : json::object ();
341343 const auto & properties = params.contains (" properties" ) ? params.at (" properties" ) : json::object ();
344+
342345 std::set<std::string> required;
346+ if (params.contains (" required" )) {
347+ params.at (" required" ).get_to (required);
348+ }
349+
350+ auto schema_info = common_schema_info ();
351+ schema_info.resolve_refs (params);
343352
344353 // Build parser for each argument, separating required and optional
345354 std::vector<common_peg_parser> required_parsers;
346355 std::vector<common_peg_parser> optional_parsers;
347356 for (const auto & [param_name, param_schema] : properties.items ()) {
348- bool is_required = required.find (param_name) != required.end ();
349- std::string type = " object" ;
350- if (param_schema.contains (" type" )) {
351- const auto & type_obj = param_schema.at (" type" );
352- if (type_obj.is_string ()) {
353- type_obj.get_to (type);
354- } else if (type_obj.is_array ()) {
355- // Handle nullable types like ["string", "null"]
356- for (const auto & t : type_obj) {
357- if (t.is_string () && t.get <std::string>() != " null" ) {
358- type = t.get <std::string>();
359- break ;
360- }
361- }
362- } else if (type_obj.is_object ()) {
363- if (type_obj.contains (" type" ) && type_obj.at (" type" ).is_string ()) {
364- type_obj.at (" type" ).get_to (type);
365- }
366- }
367- }
368- // Infer string type from enum values when type is unspecified
369- if (type == " object" && param_schema.contains (" enum" )) {
370- const auto & enum_vals = param_schema.at (" enum" );
371- if (enum_vals.is_array ()) {
372- for (const auto & v : enum_vals) {
373- if (v.is_string ()) {
374- type = " string" ;
375- break ;
376- }
377- }
378- }
379- }
357+ bool is_required = required.find (param_name) != required.end ();
380358
381359 auto arg =
382360 p.tool_arg (p.tool_arg_open (arguments.name_prefix + p.tool_arg_name (p.literal (param_name)) +
383361 arguments.name_suffix ) +
384362 arguments.value_prefix +
385- (type == " string " ?
386- p.tool_arg_string_value (p.schema (p. until (arguments. value_suffix ) ,
363+ (schema_info. resolves_to_string (param_schema) ?
364+ p.tool_arg_string_value (p.schema (until_suffix ,
387365 " tool-" + name + " -arg-" + param_name + " -schema" ,
388366 param_schema, true )) :
389367 p.tool_arg_json_value (p.schema (
@@ -414,7 +392,7 @@ common_peg_parser analyze_tools::build_tool_parser_tag_tagged(parser_build_conte
414392 for (const auto & opt : optional_parsers) {
415393 any_opt |= opt;
416394 }
417- args_seq = args_seq + p.repeat (p.space () + any_opt, 0 , ( int ) optional_parsers. size () );
395+ args_seq = args_seq + p.repeat (p.space () + any_opt, 0 , - 1 );
418396 }
419397
420398 if (!arguments.start .empty ()) {
0 commit comments