09fe013ff96dc3eec84da3658f9efa293c110e22
6
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
d90ae98fed |
feat(llm): atomic node cutover — generic ChatCompletion/LLM* nodes (T-CUT-01/04-07/11)
OllamaClient now emits an OllamaProvider via the generic LLM_CLIENT socket (was OllamaClientType/OLLAMA_CLIENT). OllamaChatCompletion, OllamaModelSelector, OllamaLoadModel, OllamaUnloadModel renamed to ChatCompletion, LLMModelSelector, LLMLoadModel, LLMUnloadModel — all delegate to client.* (LLMProvider protocol) instead of building Ollama URLs/payloads inline. Structured output now goes through client.chat_structured() (pydantic-ai), not hand-rolled tool-calling. ollama.py's own duplicate HTTP/cache infra (_post_json, _TTLLRUCache, _MODEL_LIST_CACHE, _CHAT_RESPONSE_CACHE) is gone — single source of truth in comfydv._llm.ollama_provider (plan D1); the combo-widget path (_load_default_models, /dv/ollama/models) imports _fetch_models/_run_async from there instead of duplicating them. _client_headers deleted (dead code once nodes delegate to client.*). Added MIGRATION_MAP (old->new node/socket names, FR-009). NODE_CLASS_MAPPINGS keys changed to match (breaking rename, confirmed acceptable per ADR-007). conftest.py's autouse cache-clearing fixture repointed to the single cache source and ChatCompletion (plan D8). tests/test_ollama.py itself is NOT yet updated (T-CUT-08, next commit) — it will fail to collect until then; this is the expected atomic-cutover intermediate state, not a regression to fix independently. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0132ojafeazQ3ephcBejEWFj |
||
|
|
40e851588d |
feat(ollama): opt-in structured output via tool-calling + pydantic validation
Adds structured_output/output_schema/max_retries inputs to OllamaChatCompletion, fixing three real reliability problems: models prepending commentary, wrapping responses in code fences, and occasionally returning blank output. When enabled, requests go through Ollama's OpenAI-compatible tool-calling endpoint (a single forced tool call matching output_schema) instead of native /api/chat, and each response is validated against a dynamically-built pydantic model — invalid/blank responses retry with fresh network calls, exhausting into a clear RuntimeError rather than silently passing bad data downstream. One additional ComfyUI output socket is exposed per schema property, mirroring FormatString's existing dynamic-output pattern. Fully backward compatible: structured_output defaults off and non-structured behavior is untouched. Ollama's native /api/chat "format" field (JSON-Schema-constrained decoding) was tried first but proved unreliable against a real local model during implementation — see ADR-006 for the full investigation and why tool-calling was chosen over both native format and pydantic-ai (the latter would reintroduce httpx/openai-sdk, reversing ADR-004). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> |
||
|
|
fcb95fadfa |
feat(ollama): per-client auth headers and local response caching
Adds an OLLAMA_HEADERS socket type (Basic Auth, Bearer Token, Custom) that composes onto OllamaClient, so requests to a proxied/authenticated Ollama server carry the right Authorization header through model discovery, load/unload, and chat. Also adds a bounded local cache: a short-TTL LRU for model discovery (avoids duplicate /api/tags round-trips from repeated node creation/refresh) and an unbounded-TTL LRU for chat responses, keyed on the full request signature — needed because OllamaChatCompletion is OUTPUT_NODE=True and so is re-executed by ComfyUI on every queue run even when nothing changed. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> |
||
|
|
4c64e2b6da |
feat(chat): I-commit — model→STRING, OLLAMA_HOST docker support, dynamic test fixtures
- OllamaChatCompletion.model changed from COMBO to plain STRING so it can receive a wired value from OllamaLoadModel without a separate model_name socket (removes dual-input UX confusion and COMBO validation errors) - Removed model_name optional input — model STRING is the single entry point - _load_default_models() tries OLLAMA_HOST env var → host.docker.internal → localhost so COMBO nodes pre-populate on server start inside Docker - docker-compose.dev.yml: OLLAMA_HOST=http://host.docker.internal:11434 so model dropdowns are populated at startup without a manual Refresh click - JS: refreshModelWidget handles both COMBO and STRING widget types; keeps user-typed/wired value when it is already a known model - Tests: first_generative_model fixture dynamically selects the first installed model instead of hardcoding embeddinggemma:latest (which is an embedding-only model that rejects /api/generate with HTTP 400) - Tests: test_multi_turn_receives_context passes think=False to prevent Qwen3 thinking-mode models from returning empty content fields - Screenshots retaken: ollama_chat.png, ollama_lifecycle.png, ollama_workflow.png All 80 unit + 9 integration tests pass. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RWysE6jYn4YjNorLBQ1cXb |
||
|
|
f3574c0202 |
feat(006): Ollama model integration — 14 nodes for LLM inference in ComfyUI workflows (#8)
* fix: eliminate all identified broken windows before Ollama implementation - pyproject.toml: add requires-python>=3.11, real description, remove dead [project.scripts] entry (no main() exists), add system/integration markers - __init__.py: replace pytest-in-sys.modules guard with comfy-in-sys.modules (checks the actual condition; cleaner semantics) - tests/conftest.py: remove duplicate module-level class definitions and the aiohttp mock (real aiohttp is installed; mock blocked integration tests) - circuit_breaker.py: remove copy-pasted INPUT_TYPES boilerplate docstring; logger.debug → logger.warning for ComfyUI-absent branch (degraded state) - random_choice.py: remove copy-pasted INPUT_TYPES boilerplate and dead triple-quoted string literal; fix bare re-raise to log before propagating - format_string.py: print() → logger.warning(); remove # type: ignore on two dict assignments; remove cargo-culted # noqa: F401 (ruff doesn't flag) - scripts/take_screenshots.py: remove unused h_pad and v_pad parameters All 76 tests pass; ruff clean. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RWysE6jYn4YjNorLBQ1cXb * design(006): full DESIGN phase artefacts for Ollama model integration Adds spec, plan, tasks, 6 BDD feature files, ADRs, and epic file for spec 006-ollama-model-integration (14 nodes ported from darth-veitcher/comfyui-ollama-model-manager, Issue #1 fix, logging harmonisation, live-service integration tests). - specs/006-ollama-model-integration/{spec,plan,tasks}.md - specs/006-ollama-model-integration/features/us{1-6}_*.feature - specs/006-ollama-model-integration/{.beacon.toml,checklists/} - project-management/ADRs/ADR-004-aiohttp-over-httpx-for-ollama.md - project-management/ADRs/ADR-005-ollama-host-config-via-client-node.md - project-management/Roadmap/epics/ollama-integration.md Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RWysE6jYn4YjNorLBQ1cXb * chore(006): Phase 1 setup — Ollama fixtures, Justfile recipes, test skeleton - conftest.py: add ollama_host (session), ollama_available (session), skip_if_no_ollama fixtures for @pytest.mark.integration tests - Justfile: add test, test-unit, test-integration, test-system recipes - tests/test_ollama.py: empty skeleton with module docstring and lazy-import block (uncommented phase-by-phase as ollama.py is built) Closes T001 (system marker — done in broken-windows commit), T002, T003, T004. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RWysE6jYn4YjNorLBQ1cXb * feat(006): Phase 3 foundational — ollama.py, ollama.js, __init__ wiring (T011-T014) - src/comfydv/ollama.py: OllamaClientType, _run_async, _fetch_models, _post_json, _DEFAULT_MODELS (populated at import), /dv/ollama/models route, all 14 node classes (US1-US6) with correct ComfyUI contract - src/js/ollama.js: app.registerExtension for OllamaModelSelector/LoadModel/ ChatCompletion — refreshModelDropdown + ⟳ refresh button - src/comfydv/__init__.py: register all 14 Ollama nodes in NODE_CLASS_MAPPINGS and NODE_DISPLAY_NAME_MAPPINGS Closes T011, T012, T013, T014. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RWysE6jYn4YjNorLBQ1cXb * test(006): full Ollama test suite — T015-T031 all US TDD-T commits (T-T032) Add tests/test_ollama.py with 6 test classes covering all 14 nodes: - TestUS1OllamaConnection: client type, custom host, unreachable error - TestUS2ModelSelection: fetch list, selector output, COMBO type, empty fallback - TestUS3ModelLifecycle: COMBO type, empty-model guard, load/unload integration - TestUS4ChatCompletion: COMBO type, single-turn, multi-turn, history growth - TestUS5ComposableOptions: all 7 option nodes + chaining + deterministic - TestUS6HistoryInspection: debug output, length counts - TestNodeContracts: parametrised over all 14 nodes for ComfyUI contract Also remove tests/__init__.py — its presence caused pytest to walk up past the repo root and add the parent directory to sys.path, making the root-level __init__.py win the 'comfydv' namespace over src/comfydv/. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RWysE6jYn4YjNorLBQ1cXb * style: ruff format test_ollama.py Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RWysE6jYn4YjNorLBQ1cXb * feat(006): T032/T034 — extend packaging tests and manager entry for 14 Ollama nodes Update EXPECTED_NODENAMES in test_packaging.py to include all 14 Ollama node display names. Update comfy-manager-entry.json nodename array and description to register all 14 nodes with ComfyUI Manager. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RWysE6jYn4YjNorLBQ1cXb * docs(006): T033 — add Ollama section to README and docs/index.md Add all 14 Ollama nodes to the node reference table and add a dedicated Ollama section covering minimal workflow, option nodes, and multi-turn conversation patterns. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RWysE6jYn4YjNorLBQ1cXb * test(006): T035-T/I — TestLoggingConsistency: no print(), correct log levels Add TestLoggingConsistency class to tests/test_logging.py: - AST scan: assert zero print() calls across all src/comfydv/*.py - circuit_breaker: ComfyUI-absent branch uses logger.warning() not debug - random_choice: exception path calls logger.error() and uses plain raise - ollama: absent-ComfyUI paths emit at least 2 logger.warning() calls All checks pass (fixes were already in Phase 2 broken windows commit). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RWysE6jYn4YjNorLBQ1cXb * docs: add Quickstart section to README — satisfies beacon doctor readme-completeness Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RWysE6jYn4YjNorLBQ1cXb * chore(006): mark all 55 tasks complete in tasks.md — spec fully implemented Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RWysE6jYn4YjNorLBQ1cXb * docs(006): T036/T037 — add Ollama screenshots and docker extra_hosts for host Ollama routing Captures 4 Ollama node screenshots (client, chat, workflow, options) via Playwright against the live dev ComfyUI instance. Adds extra_hosts to docker-compose.dev.yml so the container can reach host-machine Ollama. Updates README and docs/index.md to embed all 8 screenshots. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RWysE6jYn4YjNorLBQ1cXb --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> |
||
|
|
130c57f88b |
Add comprehensive pytest test suite and fix FormatString node issues
- Fixed Jinja2 regex pattern to handle spaces around filters ({{ var | filter }})
- Added null safety in IS_CHANGED method for empty/None templates
- Restored dynamic output functionality for variable chaining
- Created 47 comprehensive tests with 78% coverage on format_string.py
- Set up test infrastructure with ComfyUI dependency mocking
- Used importlib to bypass package imports during testing
- Added conditional imports in root __init__.py for test compatibility
- Configured pytest in pyproject.toml (removed outdated pytest.ini)
- Added pytest and pytest-cov to dev dependencies
- Updated .gitignore for test artifacts
- Removed deprecated model_unload.py
|