- README.md + docs/index.md: fix stale wiring instructions that referenced
model_name optional input (removed); now correctly shows wiring
OllamaLoadModel.model_name → OllamaChatCompletion.model (STRING)
- ChatCompletion description updated to mention inline response display
- Minimal chat workflow prose updated to reflect STRING model input + inline
display (no separate Text Display node needed)
- .github/workflows/docs.yml: auto-deploy docs via mike on push to main;
reads version from pyproject.toml, deploys as <version> + stable alias
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RWysE6jYn4YjNorLBQ1cXb
- 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
OllamaChatCompletion now sets OUTPUT_NODE = True and returns
{"ui": {"text": [...]}, "result": (...)} so ComfyUI renders the
response text directly in the node body after each run.
On first turn, the full response is displayed.
On subsequent turns, the response is shown with a compact history
summary (last 6 messages, 100-char snippets) so multi-turn context
is visible at a glance without a separate display node.
_history_preview() helper added for the summary rendering.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RWysE6jYn4YjNorLBQ1cXb
5 failing unit tests:
- test_chat_is_output_node
- test_chat_returns_ui_result_dict
- test_chat_ui_contains_response_text
- test_chat_result_is_3_tuple
- test_wired_model_name_overrides_combo (updated to unpack from ["result"])
Integration tests updated to unpack from ["result"] for API consistency.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RWysE6jYn4YjNorLBQ1cXb
OllamaChatCompletion grew taller with the new timeout_secs widget.
Nodes repositioned with generous horizontal gaps (60→380→720→1200)
and scale reduced to 0.72 so the full Load→Chat→Unload chain is
visible without overlap.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RWysE6jYn4YjNorLBQ1cXb
9 new tests cover:
- _run_async: event-loop safety when called from a running loop
- _post_json: raises RuntimeError on 4xx/5xx; timeout kwarg forwarded
- LoadModel/UnloadModel: must use /api/generate, keep_alive must be int
- ChatCompletion: must expose timeout_secs widget and forward it
58 pre-existing unit tests remain green. Integration tests excluded.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RWysE6jYn4YjNorLBQ1cXb
OllamaUnloadModel now works as a pass-through node: wire
OllamaChatCompletion.response into the optional `passthrough` input and
OllamaChatCompletion.model_name into `model` — ComfyUI's data-flow graph
then guarantees Load → Chat → Unload execution order.
OllamaChatCompletion gains an optional `model_name` forceInput so
OllamaLoadModel.model_name can wire in (creating Load → Chat ordering) and
overrides the COMBO dropdown. It also returns `model_name` as a 3rd output
so the model can flow downstream to UnloadModel without duplication.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RWysE6jYn4YjNorLBQ1cXb
Fresh Playwright sessions landed on ComfyUI's template gallery (no `workflow`
key in localStorage) instead of the node canvas. Pre-seeding an empty workflow
via Playwright storage_state fixes the capture. Also shows localhost:11434 in
the OllamaClient screenshot (user-facing default) rather than the Docker-internal
routing URL.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RWysE6jYn4YjNorLBQ1cXb
Mirrors the README.md rewrite into the MkDocs site landing page:
- Add Circuit Breaker section with screenshot (assets/circuit_breaker.png)
- Update Format String and Random Choice prose to match README
- Replace stale dependency list (rich/colorama/termcolor removed in spec 001)
- Add ComfyUI Manager install path
- Image paths use assets/ (MkDocs-relative) vs docs/assets/ in README
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RWysE6jYn4YjNorLBQ1cXb
Replace hand-crafted PowerPoint exports with Playwright-generated screenshots
taken from the actual running Docker test harness:
- scripts/take_screenshots.py: headless Chromium via Playwright; creates nodes
programmatically via LiteGraph/window.app, triggers updateNodeConfig() for
FormatString's dynamic socket update, then crops tightly around each node
- docs/assets/: four screenshots (fstring, jinja2, random, circuit_breaker)
replacing the old 1920×1080 PowerPoint exports (90%+ smaller, more accurate)
- Justfile: add `screenshots` recipe (starts harness if needed, waits healthy,
runs the script)
- README.md: rewrite to cover all three nodes including Circuit Breaker;
fix stale dependency list (was listing rich/colorama/termcolor which we
removed in spec 001); add ComfyUI Manager install path
- pyproject.toml + uv.lock: add playwright to [dev] dependencies
Run: just screenshots
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RWysE6jYn4YjNorLBQ1cXb
app/frontend_management.py imports requests but the tag's requirements.txt
omits it. Add explicit pip install so the image build is self-contained.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
just up — mounts local repo into container, streams logs, no rebuild needed
just up-d — same but detached; use `just logs` to follow
just build/rebuild — manage the base image
just open/status/down — day-to-day helpers
just ci-smoke — CI path (COPY-based, --quick-test-for-ci)
docker-compose.dev.yml overrides the COPY+quick-exit CMD with a volume
mount and persistent server so code changes are live immediately.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Removed unused `import sys` from test_logging.py (left over after
stripping MockInterruptProcessingException). Fixed invalid noqa comment
format on format_string.py:31.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
docker-compose.yml + docker/Dockerfile: python:3.11-slim base, ComfyUI
cloned at pinned tag, torch CPU wheel, comfydv mounted into custom_nodes/,
jinja2 installed via requirements.txt, port 8188 exposed. No GPU required.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
5 tests RED: docker-compose.yml and docker/Dockerfile don't exist yet.
Added pyyaml>=6.0.2 to dev deps for YAML parsing in tests.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replaces stale 'model memory management' text with an accurate description
of FormatString, RandomChoice, and CircuitBreaker. Matches the text in
comfy-manager-entry.json exactly.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2 tests RED: @description mentions non-existent 'model memory management'
and omits 'circuit' (CircuitBreaker). One test already passes (no Model
Unloader mention) — correct baseline.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Draft entry ready for PR to ltdrdata/ComfyUI-Manager/custom-node-list.json.
Contains author, title, reference, files, install_type=git-clone,
description (accurate, no non-existent nodes), and all 3 nodenames.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
requirements.txt now lists only jinja2>=3.1.6 per ADR-003.
aiohttp>=3.9.0 moved from [dependency-groups].dev to
[project.dependencies] so pip-only installs get the dep too.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
5 tests RED as expected: jinja2 missing, colorama/termcolor/bare-dot
still present, aiohttp not in [project.dependencies].
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
18 stub tests pass; 4 Gherkin feature files cover US1–US4 acceptance
scenarios verbatim from spec.md. No assertions yet — TDD pairs T010-T
through T041-T will fill these in next.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Parallel subagent audit (2026-06-28) identified four categories of defects:
- requirements.txt broken for ComfyUI Manager install
- FormatString: no debounce, clears connections, ID mismatch, class mutation
- RandomChoice/CircuitBreaker correctness bugs
- Stale metadata and dead code throughout
Epic captures 15 success criteria across installation, UX, and correctness.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* chore: initialise BEACON framework with all bootstrap artefacts
- Problem statement, constitution, architecture doc, roadmap populated
- CHANGELOG.md created (Keep a Changelog); README expanded with
What-is-this, Install, and Quickstart sections
- pyproject.toml gains [project.urls] (repository + documentation)
- beacon doctor: 32 pass, 2 pre-commit warns, 0 failures
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* chore: Phase 1 — add NullHandler to package root, remove hardcoded setLevel
T001: logging.getLogger("comfydv").addHandler(NullHandler()) in __init__.py
T002: remove logger.setLevel(logging.DEBUG) from format_string.py
Also fix pyproject.toml TOML structure (project.urls was inside [project] block)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* test: failing tests for logging modernisation (T010-T through T030-T)
RED phase — 5 tests fail for the correct reasons before implementation:
T010-T: format_string produces stdout (print block)
T011-T: update_widget emits INFO records on hot path
T012-T: random_choice produces stdout (colorama/rich prints)
T020-T: load_node_state uses print() on error instead of logger.error
T021-T: circuit_breaker uses print() instead of logger
T001/T002/T030-T already green: NullHandler registered, setLevel removed.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat: standardise logging across all nodes (T010-I through T044)
GREEN phase — all 11 logging tests pass:
T010-I: Remove 8-line diagnostic print block from format_string()
T011-I: Downgrade all hot-path logger.info() calls to logger.debug();
switch all logger calls to %-style formatting; remove rich import
T012-I: Replace colorama/termcolor/rich print calls in random_choice with
logger.debug(); add logger = logging.getLogger(__name__)
T020-I: Convert print() on load_node_state error to logger.error()
T021-I: Add logger to circuit_breaker; replace print() with logger.debug();
fix logic so status=False triggers the interrupt (per BDD spec)
T040: Remove colorama, rich, termcolor from pyproject.toml dependencies
T042: ruff check + format clean
T044: beacon doctor --strict passes (34/34)
Also adds ADR-001 and ADR-002 capturing the stdlib logging and NullHandler
decisions, linked from the logging-modernisation epic.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* chore: mark all 001-standardise-logging tasks complete in tasks.md
All [x] checkboxes flipped after 11/11 tests pass and beacon doctor --strict
reports 0 failures.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* chore: mark logging-modernisation epic success criteria complete
All success criteria verified: NullHandler added, setLevel removed, print()
calls converted, colorama/rich/termcolor removed from deps, zero stdout in
normal operation, errors surface at ERROR level, all tests pass.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* chore: commit spec artefacts and dependency lock for 001-standardise-logging
Includes spec.md, plan.md, research.md, BDD feature files, contracts, .beacon.toml
backlink, and uv.lock after removing colorama/rich/termcolor.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: James Veitch <darthveitcher@office-mac-mini.local>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
BREAKING CHANGE: Output order changed to put primary outputs first
- formatted_string now always in output position 0 (was dynamic)
- saved_file_path now always in output position 1 (was dynamic)
- Variable pass-through outputs now in positions 2+ (were 0+)
This change ensures primary outputs are in fixed, predictable positions,
resolving ComfyUI output mapping issues when dynamic outputs are present.
Changes:
- Updated format_string() return statement to reverse output order
- Updated update_widget() to set RETURN_TYPES/RETURN_NAMES in new order
- Updated all 47 tests to expect new output positions
- Updated all docstrings and examples in format_string.py
- Added comprehensive "Output Structure" documentation to README.md
- Added same documentation to docs/index.md for consistency
- All tests passing ✅