parse method
Parses one raw generated model turn into prose plus any tool calls.
generated is the text emitted by LlamaCppFlutter.generate for a single
model turn — with the stop sequence already stripped, so any
<|tool_call>…<tool_call|> blocks are complete. Thinking-channel content
is removed. Synthetic sequential FunctionCallContent.callIds are
assigned so results can be correlated downstream.
Implementation
GemmaTurn parse(String generated) {
final cleaned = _stripThinking(generated);
final calls = <FunctionCallContent>[];
final text = StringBuffer();
var cursor = 0;
while (cursor < cleaned.length) {
final open = cleaned.indexOf(toolCallOpen, cursor);
if (open < 0) {
text.write(cleaned.substring(cursor));
break;
}
text.write(cleaned.substring(cursor, open));
final close = cleaned.indexOf(toolCallClose, open);
final bodyEnd = close < 0 ? cleaned.length : close;
final block = cleaned.substring(open + toolCallOpen.length, bodyEnd);
final call = _parseCall(block, calls.length);
if (call != null) {
calls.add(call);
}
cursor = close < 0 ? cleaned.length : close + toolCallClose.length;
}
return GemmaTurn(text: text.toString().trim(), calls: calls);
}