Skip to content

fix(agentic-server): speak ollama's dialect, and name an upstream refusal - #1772

Merged
pyramation merged 1 commit into
mainfrom
fix/ollama-content-parts
Aug 19, 2026
Merged

fix(agentic-server): speak ollama's dialect, and name an upstream refusal#1772
pyramation merged 1 commit into
mainfrom
fix/ollama-content-parts

Conversation

@pyramation

Copy link
Copy Markdown
Contributor

Summary

A real pi run through the gateway against a local ollama died on its first turn. Ollama's chat api takes content as a string, and every harness sends parts:

"content": [{ "type": "text", "text": "" }]
400 json: cannot unmarshal array into Go struct field ChatRequest.messages.content of type string

The gateway is where the dialects meet, so transformChatRequest now flattens for the ollama provider only: text parts joined with \n, image_url parts (base64 data urls) moved to ollama's own images field, and any part it cannot express throws rather than being dropped into a prompt the model never sees. Providers on the OpenAI wire keep passing parts through untouched.

The same failure was also unreadable from the harness side: the reason sat in error.upstream, which nothing reads, while error.message was a bare LLM provider error: 400.

-  message: `LLM provider error: ${upstream.status}`
+  message: upstreamErrorMessage(provider, upstream.status, text)
+  // → "ollama provider error 400: json: cannot unmarshal array into Go struct field …"

upstreamErrorMessage unwraps {error} / {error:{message}} when the body is JSON, falls back to the raw body when it isn't, collapses whitespace and truncates at 300 chars; error.upstream still carries the untruncated body.

Link to Devin session: https://app.devin.ai/sessions/2d292e43fd2e4f34bb84605b5aa2a250
Requested by: @pyramation

…usal

Ollama's chat api takes `content` as a string; every harness sends it as parts,
so a pi turn through the gateway died on `json: cannot unmarshal array into Go
struct field ChatRequest.messages.content of type string`. The gateway is where
the dialects meet, so it flattens text parts and moves image parts to ollama's
own `images` field, failing loudly on a part it cannot express.

That failure also reached the run as a bare `LLM provider error: 400` with the
reason unread in `error.upstream` — harnesses surface `error.message` and
nothing else, so the message now names the provider and its reason.
@pyramation pyramation self-assigned this Aug 19, 2026
@devin-ai-integration

Copy link
Copy Markdown
Contributor

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment, CI, and merge conflict monitoring

@pyramation
pyramation merged commit 53bd390 into main Aug 19, 2026
20 checks passed
@pyramation
pyramation deleted the fix/ollama-content-parts branch August 19, 2026 21:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant