mirror of
https://github.com/willmiao/ComfyUI-Lora-Manager.git
synced 2026-03-21 21:22:11 -03:00
- Document dual UI systems: standalone web UI and ComfyUI custom node widgets - Add ComfyUI widget development guidelines including styling and constraints - Update terminology in LoraRandomizerNode from 'frontend/backend' to 'fixed/always' for clarity - Include UI constraints for ComfyUI widgets: minimize vertical space, avoid dynamic height changes, keep UI simple
193 lines
6.8 KiB
Markdown
193 lines
6.8 KiB
Markdown
# AGENTS.md
|
|
|
|
This file provides guidance for agentic coding assistants working in this repository.
|
|
|
|
## Development Commands
|
|
|
|
### Backend Development
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
# Install frontend dependencies
|
|
npm install
|
|
|
|
# Run frontend tests
|
|
npm test
|
|
|
|
# Run frontend tests in watch mode
|
|
npm run test:watch
|
|
|
|
# Run frontend tests with coverage
|
|
npm run test:coverage
|
|
```
|
|
|
|
## Python Code Style
|
|
|
|
### Imports
|
|
|
|
- Use `from __future__ import annotations` for forward references in type hints
|
|
- Group imports: standard library, third-party, local (separated by blank lines)
|
|
- Use absolute imports within `py/` package: `from ..services import X`
|
|
- Mock ComfyUI dependencies in tests using `tests/conftest.py` patterns
|
|
|
|
### Formatting & Types
|
|
|
|
- PEP 8 with 4-space indentation
|
|
- Type hints required for function signatures and class attributes
|
|
- Use `TYPE_CHECKING` guard for type-checking-only imports
|
|
- Prefer dataclasses for simple data containers
|
|
- Use `Optional[T]` for nullable types, `Union[T, None]` only when necessary
|
|
|
|
### Naming Conventions
|
|
|
|
- Files: `snake_case.py` (e.g., `model_scanner.py`, `lora_service.py`)
|
|
- Classes: `PascalCase` (e.g., `ModelScanner`, `LoraService`)
|
|
- Functions/variables: `snake_case` (e.g., `get_instance`, `model_type`)
|
|
- Constants: `UPPER_SNAKE_CASE` (e.g., `VALID_LORA_TYPES`)
|
|
- Private members: `_single_underscore` (protected), `__double_underscore` (name-mangled)
|
|
|
|
### Error Handling
|
|
|
|
- Use `logging.getLogger(__name__)` for module-level loggers
|
|
- Define custom exceptions in `py/services/errors.py`
|
|
- Use `asyncio.Lock` for thread-safe singleton patterns
|
|
- Raise specific exceptions with descriptive messages
|
|
- Log errors at appropriate levels (DEBUG, INFO, WARNING, ERROR, CRITICAL)
|
|
|
|
### Async Patterns
|
|
|
|
- Use `async def` for I/O-bound operations
|
|
- Mark async tests with `@pytest.mark.asyncio`
|
|
- Use `async with` for context managers
|
|
- Singleton pattern with class-level locks: see `ModelScanner.get_instance()`
|
|
- Use `aiohttp.web.Response` for HTTP responses
|
|
|
|
### Testing Patterns
|
|
|
|
- Use `pytest` with `--import-mode=importlib`
|
|
- Fixtures in `tests/conftest.py` handle ComfyUI mocking
|
|
- Use `@pytest.mark.no_settings_dir_isolation` for tests needing real paths
|
|
- Test files: `tests/test_*.py`
|
|
- Use `tmp_path_factory` for temporary directory isolation
|
|
|
|
## JavaScript Code Style
|
|
|
|
### Imports & Modules
|
|
|
|
- ES modules with `import`/`export`
|
|
- Use `import { app } from "../../scripts/app.js"` for ComfyUI integration
|
|
- Export named functions/classes: `export function foo() {}`
|
|
- Widget files use `*_widget.js` suffix
|
|
|
|
### Naming & Formatting
|
|
|
|
- camelCase for functions, variables, object properties
|
|
- PascalCase for classes/constructors
|
|
- Constants: `UPPER_SNAKE_CASE` (e.g., `CONVERTED_TYPE`)
|
|
- Files: `snake_case.js` or `kebab-case.js`
|
|
- 2-space indentation preferred (follow existing file conventions)
|
|
|
|
### Widget Development
|
|
|
|
- Use `app.registerExtension()` to register ComfyUI extensions
|
|
- Use `node.addDOMWidget(name, type, element, options)` for custom widgets
|
|
- Event handlers attached via `addEventListener` or widget callbacks
|
|
- See `web/comfyui/utils.js` for shared utilities
|
|
|
|
## Architecture Patterns
|
|
|
|
### Service Layer
|
|
|
|
- Use `ServiceRegistry` singleton for dependency injection
|
|
- Services follow singleton pattern via `get_instance()` class method
|
|
- Separate scanners (discovery) from services (business logic)
|
|
- Handlers in `py/routes/handlers/` implement route logic
|
|
|
|
### Model Types
|
|
|
|
- BaseModelService is abstract base for LoRA, Checkpoint, Embedding services
|
|
- ModelScanner provides file discovery and hash-based deduplication
|
|
- Persistent cache in SQLite via `PersistentModelCache`
|
|
- Metadata sync from CivitAI/CivArchive via `MetadataSyncService`
|
|
|
|
### Routes & Handlers
|
|
|
|
- Route registrars organize endpoints by domain: `ModelRouteRegistrar`, etc.
|
|
- Handlers are pure functions taking dependencies as parameters
|
|
- Use `WebSocketManager` for real-time progress updates
|
|
- Return `aiohttp.web.json_response` or `web.Response`
|
|
|
|
### Recipe System
|
|
|
|
- Base metadata in `py/recipes/base.py`
|
|
- Enrichment adds model metadata: `RecipeEnrichmentService`
|
|
- Parsers for different formats in `py/recipes/parsers/`
|
|
|
|
## Important Notes
|
|
|
|
- Always use English for comments (per copilot-instructions.md)
|
|
- Dual mode: ComfyUI plugin (uses folder_paths) vs standalone (reads settings.json)
|
|
- Detection: `os.environ.get("LORA_MANAGER_STANDALONE", "0") == "1"`
|
|
- Settings auto-saved in user directory or portable mode
|
|
- WebSocket broadcasts for real-time updates (downloads, scans)
|
|
- Symlink handling requires normalized paths
|
|
- API endpoints follow `/loras/*`, `/checkpoints/*`, `/embeddings/*` patterns
|
|
- Run `python scripts/sync_translation_keys.py` after UI string updates
|
|
|
|
## Frontend UI Architecture
|
|
|
|
This project has two distinct UI systems:
|
|
|
|
### 1. Standalone Lora Manager Web UI
|
|
- Location: `./static/` and `./templates/`
|
|
- Purpose: Full-featured web application for managing LoRA models
|
|
- Tech stack: Vanilla JS + CSS, served by the standalone server
|
|
- Development: Uses npm for frontend testing (`npm test`, `npm run test:watch`, etc.)
|
|
|
|
### 2. ComfyUI Custom Node Widgets
|
|
- Location: `./web/comfyui/`
|
|
- Purpose: Widgets and UI logic that ComfyUI loads as custom node extensions
|
|
- Tech stack: Vanilla JS + Vue.js widgets (in `./vue-widgets/` and built to `./web/comfyui/vue-widgets/`)
|
|
- Widget styling: Primary styles in `./web/comfyui/lm_styles.css` (NOT `./static/css/`)
|
|
- Development: No npm build step for these widgets (Vue widgets use build system)
|
|
|
|
### Widget Development Guidelines
|
|
- Use `app.registerExtension()` to register ComfyUI extensions (ComfyUI integration layer)
|
|
- Use `node.addDOMWidget()` for custom DOM widgets
|
|
- Widget styles should follow the patterns in `./web/comfyui/lm_styles.css`
|
|
- Selected state: `rgba(66, 153, 225, 0.3)` background, `rgba(66, 153, 225, 0.6)` border
|
|
- Hover state: `rgba(66, 153, 225, 0.2)` background
|
|
- Color palette matches the Lora Manager accent color (blue #4299e1)
|
|
- Use oklch() for color values when possible (defined in `./static/css/base.css`)
|
|
- Vue widget components are in `./vue-widgets/src/components/` and built to `./web/comfyui/vue-widgets/`
|
|
- When modifying widget styles, check `./web/comfyui/lm_styles.css` for consistency with other ComfyUI widgets
|
|
|