Files
darth-veitcher-comfydv/README.md
T
James VeitchandClaude Sonnet 4.6 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>
2026-06-29 00:55:15 +01:00

6.5 KiB

comfydv

A collection of workflow efficiency and quality-of-life nodes built out of necessity for personal ComfyUI use.

What is this?

comfydv fills gaps in ComfyUI's built-in node library: dynamic string formatting, seed-controlled random selection, graceful workflow interruption, and Ollama LLM integration. Install it once and connect the nodes like any other — no Python knowledge required.

Node What it does
Format String Formats a string from a Python f-string or Jinja2 template. Detects variables in the template and automatically adds/removes input sockets.
Random Choice Accepts any number of typed inputs and outputs one at random, with a configurable seed for reproducibility.
Circuit Breaker Halts the current ComfyUI queue run gracefully without crashing the server. Wire the status toggle to a boolean condition to skip the rest of the queue when a condition isn't met.
Ollama Client Configures a connection to an Ollama server (default: http://localhost:11434). Threads the host URL through the graph as an OLLAMA_CLIENT socket.
Ollama Model Selector Fetches the live model list from Ollama and presents it as a dropdown. Outputs the selected model name.
Ollama Load Model Loads a model into Ollama's memory using /api/show with keep_alive=-1.
Ollama Unload Model Evicts a model from Ollama's memory using /api/show with keep_alive=0.
Ollama Chat Completion Sends a prompt (and optional conversation history) to Ollama /api/chat and returns the response text plus the updated history.
Ollama Option — * Seven composable option nodes (Temperature, Seed, Max Tokens, Top P, Top K, Repeat Penalty, Extra Body) that merge into an OLLAMA_OPTIONS dict wired into Chat Completion.
Ollama Debug History Serialises an OLLAMA_HISTORY list to a pretty-printed JSON string for inspection.
Ollama History Length Returns the number of messages in an OLLAMA_HISTORY list as an integer.

Install

Via ComfyUI Manager (recommended): search for comfydv and click Install.

Manual:

cd /path/to/ComfyUI/custom_nodes
git clone https://github.com/darth-veitcher/comfydv.git

Restart ComfyUI. The nodes appear under the dv/ and dv/ollama categories in the node menu. Runtime dependencies (jinja2, aiohttp) are installed automatically via requirements.txt.

For Ollama nodes: install Ollama and pull at least one model (ollama pull qwen2.5:latest) before using the Ollama nodes.

Quickstart

  1. Install via ComfyUI Manager (search comfydv) or clone manually into custom_nodes/.
  2. Right-click the canvas → Add Node → dv/ to find Format String, Random Choice, and Circuit Breaker.
  3. For Ollama nodes: start Ollama (ollama serve), pull a model (ollama pull qwen2.5:latest), then add nodes from dv/ollama/.

Documentation

Full documentation: darth-veitcher.github.io/comfydv


Format String

Formats text from a Python f-string or Jinja2 template. As you type the template, input sockets appear and disappear automatically — one per variable detected.

Python f-strings

Type {variable_name} and a socket appears. Wire it to any string output in your workflow.

Format String — f-string mode

Outputs are always in a stable order:

Output Content
formatted_string The rendered result
saved_file_path Path written to disk (if save_path is set)
<var> … Pass-through of each input value, for easy chaining

Jinja2 templates

Switch template_type to Jinja2 to unlock filters (| upper, | int, …), conditionals ({% if %}…{% endif %}), and loops.

Format String — Jinja2 mode

Variables detected in {{ }} expressions become input sockets exactly as in Simple mode. See the Jinja2 documentation for the full filter/test reference.


Random Choice

Connect any number of inputs of the same type. Each run picks one at random. Set seed for reproducibility.

Random Choice

  • Accepts any ComfyUI type (STRING, IMAGE, CONDITIONING, …)
  • Add as many inputs as you like; unused slots are removed automatically when disconnected
  • seed = 0 randomises on every run; any other value locks the selection

Circuit Breaker

Stops the queue gracefully when a condition isn't met — no crash, no error, just a clean halt.

Circuit Breaker

Wire an image (or any trigger) into trigger and a boolean into status. When status is false the node raises InterruptProcessingException, which tells ComfyUI to stop the current run cleanly. When status is true the image passes through unchanged.

Typical use: skip an expensive upscale step when a quality-check node says the draft is already good enough.


Ollama

14 nodes for integrating a local Ollama LLM into your ComfyUI workflow. The host URL is configured once in Ollama Client and threaded through the graph — all downstream nodes receive it via the OLLAMA_CLIENT socket.

Ollama Client node

Configure the server address once; all downstream Ollama nodes inherit it automatically.

Ollama Client

Minimal chat workflow

  1. Ollama Client → set host (default http://localhost:11434)
  2. Ollama Model Selector → pick a model from the live dropdown
  3. Ollama Chat Completion → wire client + model + prompt → response string

Ollama Chat Completion

Wire multiple nodes together for a complete end-to-end workflow:

Ollama Full Workflow

Option nodes

Chain any combination of Ollama Option — nodes before Chat Completion to override inference parameters:

Option node Ollama param
Temperature temperature
Seed seed
Max Tokens num_predict
Top P top_p
Top K top_k
Repeat Penalty repeat_penalty
Extra Body arbitrary JSON merged into options

Ollama Option Nodes

Multi-turn conversations

OLLAMA_HISTORY flows out of Chat Completion as a list of {"role", "content"} dicts. Wire it back into the next Chat Completion for multi-turn conversations, or inspect it with Ollama Debug History / Ollama History Length.