fix(ollama): make agent + tool calls work against Ollama Cloud - #254
Open
craigamcw wants to merge 1 commit into
Open
fix(ollama): make agent + tool calls work against Ollama Cloud#254craigamcw wants to merge 1 commit into
craigamcw wants to merge 1 commit into
Conversation
Two request-serialization incompatibilities caused Ollama Cloud (https://ollama.com/v1) to reject agent requests with "400 invalid message format", even though desktop/local endpoints accept them. 1. User message content was serialized as a content-block array ([{ "type": "text", ... }]) for any image-capable model. Ollama Cloud only accepts a plain string for text. Flatten text-only content to a string in the pi-ai openai-completions provider (patches/@mariozechner+pi-ai+0.60.0.patch). 2. DeepSeek-V4 models get requiresThinkingInContent, which serializes the assistant's thinking as a non-standard { "type": "thinking" } content block. Some custom relays require that, but Ollama Cloud rejects it. Disable it specifically for the ollama.com endpoint (and keep it for local Ollama / other relays) in applyPiModelRuntimeOverrides. Adds tests covering the Ollama-Cloud-vs-relay branch. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Review mode: initial
Findings
- [Minor]
ollama.comendpoint detection could match unintended subdomains (e.g.,https://xollama.com). The checkendpoint.includes('ollama.com')is broad; consider using a more precise pattern likeendpoint.includes('//ollama.com')or a URL hostname parse to reduce false positives.
Suggested fix insrc/main/claude/pi-model-resolution.ts:337:const endpointUrl = new URL(options.customBaseUrl || nextModel.baseUrl || ''); const isOllamaCloud = endpointUrl.hostname === 'ollama.com' || endpointUrl.hostname.endsWith('.ollama.com');
Summary
No blockers or major issues found. The patch and runtime override correctly address the two serialization incompatibilities with Ollama Cloud. The detection logic for ollama.com is adequate for the known endpoints but could be tightened to avoid false matches. Test coverage is good.
Testing
Existing tests pass (vitest suites for pi-model-resolution). Not run (automation).
Open Cowork Bot
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Using Ollama Cloud (
https://ollama.com/v1) with the agent fails with400 invalid message format— but only on the cloud endpoint; local Ollama and other relays accept the same requests. Captured the exact request body Ollama Cloud rejects and traced it to two serialization issues.Fixes
1. User content serialized as an array instead of a string
For any image-capable model, the openai-completions provider emitted
content: [{ "type": "text", "text": "…" }]. Ollama Cloud only accepts a plain string for text content. This flattens text-only content to a string (the standard OpenAI Chat Completions form that OpenAI, OpenRouter, and Ollama all accept), keeping the array form only when there's an actual image.→
patches/@mariozechner+pi-ai+0.60.0.patch2. Non-standard
{ "type": "thinking" }content block on follow-up turnsDeepSeek-V4 models set
requiresThinkingInContent, which serializes the assistant's prior thinking intocontent[]as{ "type": "thinking", … }. Some custom relays require that, but Ollama Cloud rejects it (it's not a valid OpenAI content type), so the second agent turn (after a tool call) 400s. This disables it specifically for theollama.comendpoint while leaving it on for local Ollama and other relays.→
src/main/claude/pi-model-resolution.tsTests
src/tests/claude/pi-model-resolution.test.ts: new cases assertingrequiresThinkingInContentisfalseforollama.comandtruefor other relay endpoints.pi-model-resolution/deepseek-thinking-serialization/claude-sdk-one-shotsuites pass;tsc --noEmitclean.Verified end-to-end: a multi-turn, tool-using agent session with
deepseek-v4-proon Ollama Cloud now completes successfully.🤖 Generated with Claude Code