mirror of
https://github.com/willmiao/ComfyUI-Lora-Manager.git
synced 2026-08-29 08:51:27 -03:00
1a1be95a64
Audit of all 10 locale files found recipe/checkpoint mistranslations, inverted ko tag logic, stale help texts, placeholder contract deviations, and untranslated feature blocks. Document the conventions (R1-R9), per- language term maps, confusion hot-spots, and the translation workflow so future agents and translators follow the established decisions (e.g. keep 'Recipe' untranslated in French, use 配方 in Chinese).
9.5 KiB
9.5 KiB
AGENTS.md
This file provides guidance for agentic coding assistants working in this repository.
Overview
ComfyUI LoRA Manager is a comprehensive LoRA management system for ComfyUI that combines a Python backend with browser-based widgets. It provides model organization, downloading from CivitAI/CivArchive, recipe management, and one-click workflow integration.
Development Commands
Backend Development
# Install dependencies
pip install -r requirements.txt
pip install -r requirements-dev.txt
# Run standalone server (port 8188 by default)
python standalone.py --port 8188
# Run all backend tests
pytest
# Run specific test file
pytest tests/test_recipes.py
# Run specific test function
pytest tests/test_recipes.py::test_function_name
# Run backend tests with coverage
COVERAGE_FILE=coverage/backend/.coverage pytest \
--cov=py --cov=standalone \
--cov-report=term-missing \
--cov-report=html:coverage/backend/html \
--cov-report=xml:coverage/backend/coverage.xml \
--cov-report=json:coverage/backend/coverage.json
Frontend Development (LoRA Manager Web UI)
# Install dependencies (root and Vue widgets)
npm install
cd vue-widgets && npm install && cd ..
npm test # Run all tests (JS + Vue)
npm run test:js # Run JS tests only
npm run test:vue # Run Vue widget tests only
npm run test:watch # Watch mode (JS tests only)
npm run test:coverage # Generate coverage report
Vue Widget Development
cd vue-widgets
npm install
npm run dev # Build in watch mode
npm run build # Build production bundle
npm run typecheck # Run TypeScript type checking
npm test # Run Vue widget tests
npm run test:watch # Watch mode
npm run test:coverage # Generate coverage report
Localization
# Sync translation keys after UI string updates
python scripts/sync_translation_keys.py
Locale files are in locales/ (en, zh-CN, zh-TW, ja, ko, fr, de, es, ru, he).
Before translating anything, read docs/i18n-translation-guidelines.md — it defines the
term conventions (e.g. "Recipe" stays untranslated in French, 配方 in Chinese; model-type and
brand names are never translated), per-locale preferred renderings, placeholder rules, and
the known confusion hot-spots.
Code Style
Python
Imports & Formatting
- Use
from __future__ import annotationsfor forward references - Group imports: standard library, third-party, local (blank line separated)
- Use
TYPE_CHECKINGguard for type-checking-only imports - Absolute imports within
py/:from ..services import X - PEP 8 with 4-space indentation, type hints required
Naming Conventions
- Files:
snake_case.py, Classes:PascalCase, Functions/vars:snake_case - Constants:
UPPER_SNAKE_CASE, Private:_protected,__mangled
Error Handling & Async
- Use
logging.getLogger(__name__), define custom exceptions inpy/services/errors.py async deffor I/O,@pytest.mark.asynciofor async tests- Singleton with
asyncio.Lock: seeModelScanner.get_instance() - Return
aiohttp.web.json_responseorweb.Response
JavaScript/TypeScript
Imports & Modules
- ES modules:
import { app } from "../../scripts/app.js"for ComfyUI - Vue:
import { ref, computed } from 'vue', type imports:import type { Foo } - Export named functions:
export function foo() {}
Naming & Formatting
- camelCase for functions/vars/props, PascalCase for classes
- Constants:
UPPER_SNAKE_CASE, Files:snake_case.jsorkebab-case.js - 2-space indentation preferred (follow existing file conventions)
- Vue Single File Components:
<script setup lang="ts">preferred
Widget Development
- Prefer vanilla JS for
web/comfyui/widgets; avoid framework dependencies (except the Vue widgets invue-widgets/) - ComfyUI:
app.registerExtension(),node.addDOMWidget(name, type, element, options) - Event handlers via
addEventListeneror widget callbacks - Shared utilities:
web/comfyui/utils.js - Dual-mode rendering patterns (canvas vs Vue): see
docs/comfyui-dual-mode-widgets.md
Vue Composables Pattern
- Use composition API:
useXxxState(widget), return reactive refs and methods - Guard restoration loops with flag:
let isRestoring = false - Build config from state:
const buildConfig = (): Config => { ... }
Architecture
Dual Mode Operation
The system runs in two modes:
- ComfyUI plugin mode: Integrates with ComfyUI's PromptServer, uses
folder_pathsfor model discovery - Standalone mode:
standalone.pymocks ComfyUI dependencies, reads paths fromsettings.json - Detection:
os.environ.get("LORA_MANAGER_STANDALONE", "0") == "1"
Backend Entry Points
__init__.py— ComfyUI plugin entry: registers nodes viaNODE_CLASS_MAPPINGS, setsWEB_DIRECTORY, callsLoraManager.add_routes()standalone.py— Standalone server: mocksfolder_pathsand node modules, starts aiohttp serverpy/lora_manager.py— MainLoraManagerclass that registers all HTTP routes
Service Layer
ServiceRegistrysingleton for DI, services useget_instance()classmethodBaseModelServiceabstract base →LoraService,CheckpointService,EmbeddingServiceModelScannerbase →LoraScanner,CheckpointScanner,EmbeddingScannerfor file discovery with hash-based deduplicationPersistentModelCache(SQLite) for metadata persistenceMetadataSyncService— background sync from CivitAI/CivArchive APIsSettingsManager— settings with schema migration supportWebSocketManager— real-time progress broadcastingModelServiceFactory— creates the right service for each model type- Use cases in
py/services/use_cases/orchestrate complex business logic (auto-organize, bulk refresh, downloads) - Separate scanners (discovery) from services (business logic)
- Handlers in
py/routes/handlers/are pure functions with deps as params
Model Types & Routes
- API endpoints follow
/loras/*,/checkpoints/*,/embeddings/*patterns - Route registrars organize endpoints by domain:
ModelRouteRegistrar,RecipeRouteRegistrar, etc. - Request handlers in
py/routes/handlers/implement route logic - All routes use aiohttp, return
web.json_responseorweb.Response
Recipe System
- Base:
py/recipes/base.py, Enrichment:RecipeEnrichmentServiceinpy/recipes/enrichment.py - Parsers:
py/recipes/parsers/for PNG metadata, JSON, and workflow formats
Custom Nodes
- Location:
py/nodes/, all nodes registered in__init__.py - Each node class has a
NAMEclass attribute used as key inNODE_CLASS_MAPPINGS - Standard ComfyUI node pattern:
INPUT_TYPES()classmethod,RETURN_TYPES,FUNCTION
Configuration
py/config.pymanages folder paths for models and handles symlink mappings- Auto-saves paths to
settings.jsonin ComfyUI mode
Frontend UI Architecture
1. LoRA Manager Web UI
- Location:
./static/(JS/CSS) and./templates/(HTML) - Tech: Vanilla JS + CSS, served by the hosting server (ComfyUI app in plugin mode,
standalone.pyin standalone mode) - Tests:
tests/frontend/**/*.test.js(vitest + jsdom)
2. ComfyUI Custom Node Widgets
- Location:
./web/comfyui/(Vanilla JS) +./vue-widgets/(Vue) - Primary styles:
./web/comfyui/lm_styles.css(NOT./static/css/) - Vue widgets: Vue 3 + TypeScript + PrimeVue + vue-i18n, e.g.
LoraPoolWidget,LoraRandomizerWidget,LoraCyclerWidget,AutocompleteTextWidget - Vue builds to
./web/comfyui/vue-widgets/; auto-built on ComfyUI startup viapy/vue_widget_builder.py, typecheck viavue-tsc - Widget registration:
app.registerExtension()andgetCustomWidgetshooks;node.addDOMWidget(...)embeds HTML in LiteGraph nodes - See
docs/dom_widget_dev_guide.mdfor the DOMWidget development guide
Testing
Backend (pytest)
- Config in
pytest.ini:--import-mode=importlib, testpaths=tests - Fixtures in
tests/conftest.pymock ComfyUI dependencies; usetmp_path_factoryfor isolation - Markers:
@pytest.mark.asyncio,@pytest.mark.no_settings_dir_isolation(tests needing real settings paths)
Frontend (vitest)
- Vanilla JS tests:
tests/frontend/**/*.test.jswith jsdom; setup intests/frontend/setup.js - Vue widget tests:
vue-widgets/tests/**/*.test.tswith jsdom +@vue/test-utils
Key Integration Points
- Settings: Stored in the user config directory (via
platformdirs) or portable mode ("use_portable_settings": true) - CivitAI/CivArchive: API clients for metadata sync and model downloads; CivitAI API key stored in settings
- Symlinks: Config scans symlinks to map virtual→physical paths; fingerprinting prevents redundant rescans
- WebSocket: Broadcasts real-time progress for downloads, scans, and metadata sync
- Model scanning flow: Walk folders → compute hashes → deduplicate → extract safetensors metadata → cache in SQLite → background CivitAI sync → WebSocket broadcast
Important Notes
- ALWAYS use English for comments (per copilot-instructions.md)
- Run
python scripts/sync_translation_keys.pyafter adding UI strings tolocales/en.json - Symlinks require normalized paths.
Business paths vs real paths: All stored paths and operation routing use the
original paths as they appear under configured model roots — symlinks are NOT
resolved.
os.path.realpathis only for scanner dedup and the symlink cache. Any path passed toos.remove/os.rename/shutil.moveor validated by a containment check MUST use the business path (i.e.os.path.abspath, notrealpath).