Models using the harmony parser may output analysis/thinking segments
before JSON arguments in tool calls. For example:
<|channel|>analysis<|message|>I need to list files.{"path": "/tmp"}
Previously this would fail JSON parsing. Now the parser:
- Extracts and strips harmony analysis segments before JSON
- Preserves the thinking content separately
- Uses brace-matching to extract complete JSON objects
This brings the harmony parser in line with Qwen3VL and Cogito parsers
which already handle mixed thinking/tool call content via event-based
parsing.
In #11910 we started sanitizing function names, but we accidentally were
modifying built-ins like `browser.open` to `browser_open`. This was
removing the special prompt rendering for built-ins, but this wasn't
immediately apparent since the models seem to be reasonably good at
remembering the built-ins even when presented with these slightly
renamed version. This fix prevents built-ins from ever being renamed.
Now that we have a built-in parser abstraction, which was introduced in
<https://github.com/ollama/ollama/pull/12248>, we can modify our harmony
parser to match this and then get rid of nearly all of the
harmony-specific logic in routes.go. We do have a small amount of
code that turns the parser on by default if the architecture matches and
no other built-in parser was provided.
The built-in parser interface was modified in order to handle harmony's
prefill and tool name translation requirements.