feat(009): add optional images carrier to Message (T002-I)

Message.images: list[str] | None = None — base64 payloads per turn, the
provider-neutral carrier ADR-008 defines. Default None keeps text-only
turns text-only. Makes T002-T pass.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UvS9TFMCFYNHC4MMvzJaZS
This commit is contained in:
Claude
2026-07-22 19:01:00 +00:00
parent 7e56f2e5bf
commit 1c72e0b2ea
2 changed files with 14 additions and 3 deletions
+2 -2
View File
@@ -33,8 +33,8 @@ handling lives only in the `comfy`-guarded `ollama.py`.
**Purpose**: the image carrier every path depends on. **⚠️ No user story work can begin until this is complete.**
- [ ] T002-T Write FAILING test: `Message.images` defaults to `None`, round-trips a base64 list, and a text-only message's transport dump **omits** the `images` key (byte-identical to today), in `tests/test_llm_provider.py` (contract T1)
- [ ] T002-I Add `images: list[str] | None = None` to `Message` in `src/comfydv/_llm/provider.py` — makes T002-T pass
- [x] T002-T Write FAILING test: `Message.images` defaults to `None`, round-trips a base64 list, and a text-only message's transport dump **omits** the `images` key (byte-identical to today), in `tests/test_llm_provider.py` (contract T1)
- [x] T002-I Add `images: list[str] | None = None` to `Message` in `src/comfydv/_llm/provider.py` — makes T002-T pass
**Checkpoint**: carrier ready — user stories can begin.
+12 -1
View File
@@ -39,10 +39,21 @@ class ModelInfo(BaseModel):
class Message(BaseModel):
"""One turn in a chat request."""
"""One turn in a chat request.
``images`` carries optional base64-encoded image payloads (no ``data:``
prefix) associated with this turn, for vision-capable models. ``None``
(the default) means a text-only turn that serializes byte-for-byte as
before — providers dump with ``exclude_none=True`` so no ``images`` key
reaches the wire for image-less turns. Each provider translates this
neutral carrier into its own native shape (ADR-008): Ollama's flat
per-message ``images`` array, llama.cpp's OpenAI ``image_url`` content
parts, and pydantic-ai ``BinaryContent`` on the structured path.
"""
role: Literal["system", "user", "assistant"]
content: str
images: list[str] | None = None
class LLMProvider(Protocol):