Extends the chat-completions surface so callers can ask any provider
to call named functions and get structured tool_calls back. Wired
through all three provider adapters so the planner and companion can
switch off the fragile JSON-parsing pathway.
- Request: tools[], tool_choice, assistant tool_calls, tool-role
messages with tool_call_id.
- Response: MessageResponse.tool_calls, Choice.finish_reason adds
"tool_calls", DeltaContent streams tool_calls.
- Google provider: Tool(function_declarations=...) build, result
normalised (args dict → JSON string), function_response parts on
a user turn for tool-role messages.
- OpenAI-compat: 1:1 passthrough of the OpenAI spec.
- Ollama: /api/chat passthrough; model-level capability check via a
TOOL_CAPABLE_OLLAMA_PATTERNS whitelist (llama3.1+, qwen2.5+,
mistral, command-r, …) — unsupported models rejected rather than
silently falling back to prose.
- Router: model_supports_tools() check upfront for both streaming
and non-streaming paths; ProviderCapabilityError bubbles as 400.
No silent downgrade. Missing tool support = explicit error.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The first iteration of the Ollama response_format passthrough crashed
with 'ChatCompletionRequest object has no attribute response_format'
because the Pydantic request model didn't declare the field at all —
incoming response_format from OpenAI-compatible clients was being
silently dropped at the parsing layer before the provider could see it.
Fix: declare a typed ResponseFormat sub-model with the two OpenAI shapes
('json_object' and 'json_schema'), add it as an optional field on
ChatCompletionRequest, and let the Ollama provider read it directly
without defensive getattr fallbacks.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Update pnpm-lock.yaml with matrix bot dependencies
- Add environment variables to generate-env.mjs
- Improve mana-llm config and ollama provider
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>