Files
darth-veitcher-comfydv/tests/test_llm_provider.py
T
James VeitchandClaude Sonnet 5 736ffd1e77 feat(llm): shared chat_structured() via pydantic-ai (T011-T013)
Provider-layer only — src/comfydv/_llm/chat.py doesn't touch ollama.py, so
it's safe to land ahead of the deferred atomic node cutover (issue #16).
Ports ADR-006's exact retry/validation contract: bounded retries (0-5,
clamped), RuntimeError naming model/attempt-count/truncated-last-response
on exhaustion. Agent's own internal retries disabled so the error contract
is comfydv's, not pydantic-ai's.

Required an API-discovery spike (Agent/OpenAIProvider/OpenAIChatModel
constructors and exception surface aren't reliably knowable from training
data for a fast-moving library) before tests could be written meaningfully
— tests and implementation were validated together rather than strictly
red-first; noted in tasks.md rather than presented as pure TDD.

Also fixes a pre-existing gap in test_packaging.py's requirements.txt/
pyproject.toml consistency check: it stripped `[extras]` on one side of the
comparison but not the other, which this change's pydantic-ai-slim[openai]
entry exposed as the first dependency with an extras marker.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0132ojafeazQ3ephcBejEWFj
2026-07-11 13:37:16 +01:00

44 lines
1.4 KiB
Python

"""
Tests for comfydv._llm — shared LLMProvider protocol and OllamaProvider.
Test layers:
Unit (no marker) — pure Python, no live services
Integration (-m integration) — requires live Ollama at localhost:11434
BDD coverage:
../specs/007-llm-provider-abstraction/features/us1_connect_and_chat.feature
../specs/007-llm-provider-abstraction/features/us2_structured_output.feature
../specs/007-llm-provider-abstraction/features/us3_model_lifecycle.feature
"""
from comfydv._llm.ollama_provider import OllamaProvider
from comfydv._llm.provider import Message, ModelInfo, ModelStatus
def test_ollama_provider_captures_connection_state():
provider = OllamaProvider("http://localhost:11434", headers={"X-Test": "1"})
assert provider.host == "http://localhost:11434"
assert provider.headers == {"X-Test": "1"}
def test_ollama_provider_headers_default_to_none():
provider = OllamaProvider("http://localhost:11434")
assert provider.headers is None
def test_model_status_values():
assert ModelStatus.LOADED == "loaded"
assert ModelStatus.SLEEPING == "sleeping"
assert ModelStatus.DOWNLOADING == "downloading"
def test_model_info_optional_size():
info = ModelInfo(name="llama3", status=ModelStatus.UNLOADED)
assert info.size is None
def test_message_roles():
Message(role="system", content="be terse")
Message(role="user", content="hi")
Message(role="assistant", content="hello")