* feat: add LoRA utility module for LoraManager integration (#52)
Detection, metadata reading, trigger word cache, and prompt injection
for ComfyUI-Lora-Manager. All functions return empty results when
LoraManager is not installed.
* feat: add IntegrationConfig for opt-in third-party integrations (#52)
* feat(api): add LoraManager integration endpoints (#52)
Detection, enable/disable, scan/import, trigger word lookup,
and cache refresh endpoints under /prompt_manager/lora/*.
* feat: inject LoRA trigger words into prompts at encoding time (#52)
When enabled, scans for <lora:NAME:WEIGHT> tags in prompt text and
appends trigger words from LoraManager metadata. Behind config toggle.
* feat(ui): add LoraManager integration settings and import UI (#52)
Integrations section in settings with auto-detection badge, enable
toggle, trigger word toggle, and Import LoRA Data button.
* fix: detect LoraManager with case-insensitive directory scan (#52)
* fix: simplify LoraManager heuristic to match real install structure (#52)
* fix: find ComfyUI root via folder_paths and handle symlinked installs (#52)
* fix(ui): add pointer-events-none to toggle switch overlays (#52)
The styled div was intercepting clicks meant for the sr-only checkbox
input, preventing toggle switches from being clickable.
* fix: use lora-manager category and tag for imported LoRA data (#52)
* fix: use rglob to find metadata in lora subdirectories (#52)
* feat: discover LoRA dirs from extra_model_paths.yaml and folder_paths (#52)
Only models/loras under the ComfyUI root was checked. Now also parses
extra_model_paths.yaml and uses folder_paths.get_folder_paths('loras')
at runtime to find all configured LoRA directories.
* fix: use example prompts instead of trigger words, serve LoRA preview images (#52)
- Prompt text now uses civitai example prompts (images[].meta.prompt)
when available, falling back to model name instead of trigger words
- Image serving now allows paths within LoRA directories when the
integration is enabled, fixing 403 errors on preview images
* fix: handle null civitai field, link all preview images (#52)
- Guard against civitai: null in metadata (was crashing the scan)
- Link all local preview images per LoRA, not just the first
- Add get_civitai_image_urls() for future remote image support
* feat: reimport clears previous lora-manager data first (#52)
Clicking Import LoRA Data now deletes all existing lora-manager
category prompts before scanning, ensuring a clean reimport.
* feat: download civitai example images during LoRA import (#52)
Images from civitai.images[] are downloaded to data/lora_images/ cache
and linked to prompts alongside local preview files. Cached files are
reused on reimport. Image serving allows the cache directory.
* feat: add CivitAI API key setting for authenticated image downloads (#52)
Most civitai example images (especially NSFW) require authentication.
Adds API key field to the Integrations settings panel, passed as
Bearer token when downloading example images.
* feat(ui): add progress modal for LoRA import (#52)
Closes settings modal and shows a dedicated progress modal with
progress bar, status text, and processed/imported counts during
LoRA import. Auto-closes after completion.
* fix: reduce download timeout to 5s, update progress per LoRA (#52)
5K images at 15s timeout was painfully slow. Reduced to 5s fail-fast.
Progress now updates for every LoRA with image count, not every 5th.
* perf: use 512px thumbnails and parallel downloads for LoRA images (#52)
Full-size civitai images averaged 5.6MB each (27GB total for 5K images).
Now requests /width=512/ thumbnails (~50-100KB) and downloads 8 in
parallel per LoRA. Expected speedup: ~100x smaller + 8x parallel.
* fix: resize downloaded images to 512px thumbnails locally (#52)
Civitai CDN returns 401 for /width=N/ thumbnail URLs with API key auth.
Instead, download the original and resize to 512px via PIL before saving.
Reduces disk usage from ~5MB to ~30-50KB per image.
* docs: update README for v3.2.1 LoRA Manager integration (#52)
- Add LoRA Manager integration section with setup guide and CivitAI key docs
- Add folder filter section with rescan note for existing libraries
- Add v3.2.1 changelog entry, split from v3.2.0
- Add WIP notice for LoRA Manager feature
- Update AutoTag section to include WD14 models
- Fix stale references (KikoTextEncode, outdated file structure)
- Remove dated v2 development note
- Add screenshots for settings, integration, and filtered results
- Fix code review items: remove unused constant, add comments to empty excepts
- Bump version to 3.2.1
* test: add unit tests for LoRA integration and folder filter (#52)
- test_lora_utils.py: 32 tests covering trigger word extraction, example
prompts, image URLs, metadata parsing, cache dir, TriggerWordCache
- test_lora_database.py: 17 tests covering delete_prompts_by_category,
folder filter search, get_prompt_subfolders, LoRA import workflow
- test_config.py: 7 new IntegrationConfig tests for structure, enable,
partial update, reset, and roundtrip
* fix: remove unused MagicMock import in test_lora_utils (#52)
* fix: diagnostics, backup, and restore now respect config.json db path (#132)
* test: add regression tests for config-aware diagnostics and backup (#132)
* fix(test): use fresh event loop to avoid aiohttp test pollution
* fix: don't kill singleton image monitor when node instance is garbage collected
The __del__ method was calling stop_monitoring() on the shared singleton
ImageMonitor, killing it for ALL nodes whenever any single node instance
was garbage collected between workflow runs. This caused the monitor to
restart on every execution and miss image save events due to race conditions.
* test: add regression tests for image monitor singleton lifecycle
Ensures cleanup/del never stops the shared monitor, singleton is
thread-safe, and observer survives across node instance lifecycles.
* style: address PR review — log suppressed exceptions, remove unused imports
* fix: resolve database path from config.json (#119)
PromptDatabase() was hardcoded to "prompts.db" relative to CWD,
ignoring the DEFAULT_DB_PATH setting from config.json. Added
_resolve_db_path() that reads from PromptManagerConfig when available
and resolves relative paths against the extension root directory.
This fixes Docker deployments where the CWD differs from the extension.
* test: add unit tests for database path resolution (#119)
Cover explicit absolute/relative paths, config fallback, relative
config paths resolved to extension root, and PromptDatabase constructor
integration with _resolve_db_path.
* docs: update database path configuration instructions (#119)
Replace outdated advice to edit py/config.py with correct config.json
approach. Add Docker-specific guidance for absolute paths.
* chore: bump version to 3.1.5
* fix: remove unused import and variables from test (#119)
Address code review: remove unused MagicMock import and unused db
local variables in constructor tests.
* fix: initialize extended_tags before conditional block (#123)
extended_tags was only assigned inside the `if storage_text` block,
causing UnboundLocalError when text input is empty or whitespace-only.
Initialize to empty list before the conditional in both PromptManager
and PromptManagerText nodes.
* test: add unit tests for empty text input handling (#123)
Cover empty string, whitespace-only, empty with prepend/append, and
normal text for both PromptManagerText and PromptManager nodes.
* fix: use parts-based join to prevent double space on empty text (#123)
When main text is empty with prepend/append connected, the old string
concatenation produced "before after" (double space). Switch to
building a parts list and joining with single space so empty text is
cleanly skipped.
* test: add concatenation tests for prepend/append with empty text (#123)
Cover double-space regression, all-parts-present case, and
prepend-only with empty text for both node variants.
* fix: preserve connected input values in widget sync and queue hooks (#123)
The queuePrompt interceptor, syncPromptManagerWidgets, and serialize
hook were overwriting connected input link references with the widget's
empty DOM value. When text is connected from another node, ComfyUI puts
a link reference array in the output — these hooks now check for
connections before syncing, so externally connected text flows through.
* test: add connected-input contract tests for text + prepend + append (#123)
Verifies that externally connected text appears in the final output
alongside prepend/append — the exact scenario from the QA screenshot.
Covers both PromptManagerText and PromptManager (CLIP) variants.
* chore: bump version to 3.1.3
ComfyUI's execution engine walks backwards from output nodes. Without
OUTPUT_NODE = True, our nodes could be silently skipped when downstream
nodes are cached — even when IS_CHANGED returns a new value.
Since all three nodes have side effects (database writes, execution
tracking), they must be marked as output nodes so ComfyUI always
includes them in the execution graph.
Adds regression tests for OUTPUT_NODE and IS_CHANGED contracts.
Bumps version to 3.1.2.
- Remove unused `patch` import from test_output_dir.py
- Add debug log message to ImportError handler instead of bare pass
- Invalidate gallery file listing cache alongside output dir cache
when the user changes gallery_root_path in settings
_find_comfyui_output_dir() now checks GalleryConfig.MONITORING_DIRECTORIES
first before falling back to filesystem auto-detection. Also invalidates
the cached directory when the user changes the setting via save_settings().
Closes#108
- Add Google-style docstrings to main node files (prompt_manager.py, prompt_manager_text.py)
- Enhance database module docstrings with detailed parameter and return documentation
- Add comprehensive docstrings to all utils modules with usage examples
- Document API endpoints and configuration classes thoroughly
- Update module-level docstrings in all __init__.py files
- Ensure consistent naming (ComfyUI_PromptManager) across all documentation
- Follow Python best practices for docstring formatting