Message gains an optional Parts []ContentPart alongside the existing
plain-text Content, so a turn can carry text plus image/video
attachments. Content stays the single source of truth for every
existing text-only caller (sidebar.go, memory_tools.go, etc. are
untouched); Parts only matters to a provider client when non-empty.
openai and llamacpp (both OpenAI-compatible) serialize Parts into the
standard text/image_url content-array shape; llamacpp additionally
passes video through as a best-effort video_url part, since llama.cpp
itself has no video support but the whole point of this client is the
user's own OpenAI-compatible server sitting in front of a
video-capable model — the server decides whether it understands it,
not this client. anthropic converts image parts to its base64 image
content block, and rejects a video part outright with a clear error:
the Messages API has no video block type at all, so sending one would
just produce a confusing 400 instead.
ProviderCapabilities gains SupportsVideo, true only for llamacpp.
Formatting only (struct field alignment, import ordering) across the
files that didn't comply — no semantic changes.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The Stream() path was broken end to end:
- requests always went out with "stream": false, so the SSE parser found
no data lines and every stream ended empty
- Config.Model was discarded at construction, and the agent loop never
sets req.Model, so requests carried an empty model (hard API error)
- tool-call deltas were ignored entirely: the agent never executed tools
over a stream with this provider (which also backs the ollama type)
- usage was neither requested nor parsed, so token tracking stayed at 0
Now mirrors the proven llamacpp client: stream flag + stream_options
.include_usage, per-index tool-call fragment accumulation flushed on
finish_reason, usage passthrough, a 4MB SSE scanner buffer (64KB default
kills the stream on large tool arguments), and an empty-choices guard in
toResponse instead of a panic.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- agent/loop.go: Record assistant message with ToolCalls before tool results,
and set ToolCallID on tool-result messages so follow-up requests have complete
context (prevents models from losing track of already-attempted tools).
- llm/providers/llamacpp/client.go: Buffer fragmented tool call deltas during
streaming, assemble them into complete calls when finish_reason arrives.
Add ToolCalls, ToolCallID, Name fields to request building.
- llm/providers/openai/client.go: Send ToolCalls, ToolCallID, Name when
building chat requests so messages are wire-format correct.
- llm/types.go: Add ToolCalls field to Message struct for serialization
back into conversation history.
- agent/integration_test.go: Move integration test skip from TestMain to a
per-test skipUnlessIntegration() so it doesn't hide other package tests.
- sandbox & tools: Add edge-case tests (relative traversal, array paths,
non-path strings, zero-value guards, sentinel errors).