toolCallGrammar function
The tool-call grammar: exactly one of {"tool": "<name>", "arguments": <that tool's schema>} or
{"answer": "<text>"} (when allowAnswer).
Implementation
String toolCallGrammar(List<({String name, Map<String, Object?> parameters})> tools, {bool allowAnswer = true}) {
if (tools.isEmpty && !allowAnswer) throw GrammarSchemaException('no tools and no answer allowed');
final g = JsonSchemaGrammar();
final alts = <String>[];
for (final t in tools) {
final args = g.rule(t.parameters.isEmpty ? {'type': 'object'} : t.parameters, 'args-${t.name}');
alts.add('"{" ws "\\"tool\\"" ws ":" ws ${JsonSchemaGrammar._literal(t.name)} ws "," ws "\\"arguments\\"" ws ":" ws $args ws "}"');
}
if (allowAnswer) alts.add('"{" ws "\\"answer\\"" ws ":" ws string ws "}"');
return g.render('root ::= ws (${alts.join(' | ')}) ws');
}