Full source for the-third-rev: Discord bot (discord.py), FastAPI web UI (React/TS/Vite/Tailwind), ComfyUI integration, generation history DB, preset manager, workflow inspector, and all supporting modules. Excluded from tracking: .env, invite_tokens.json, *.db (SQLite), current-workflow-changes.json, user_settings/, presets/, logs/, web-static/ (build output), frontend/node_modules/. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
9.0 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Project Overview
This is a Discord bot that integrates with ComfyUI to generate AI images and videos. Users interact via Discord commands, which queue generation requests that execute on a ComfyUI server.
Architecture
File Structure
The codebase is organized into focused modules for maintainability:
the-third-rev/
├── config.py # Configuration and constants
├── job_queue.py # Job queue system (SerialJobQueue)
├── workflow_manager.py # Workflow manipulation logic
├── workflow_state.py # Runtime workflow state management
├── discord_utils.py # Discord helpers and decorators
├── commands/ # Command handlers (organized by functionality)
│ ├── __init__.py # Command registration
│ ├── generation.py # generate, workflow-gen commands
│ ├── workflow.py # workflow-load command
│ ├── upload.py # upload command
│ ├── history.py # history, get-history commands
│ └── workflow_changes.py # get/set workflow changes commands
├── bot.py # Main bot entry point (~150 lines)
└── comfy_client.py # ComfyUI API client (~650 lines)
Core Components
- bot.py: Minimal Discord bot entry point. Loads configuration, creates dependencies, and registers commands. No command logic here.
- comfy_client.py: Async client wrapping ComfyUI's REST and WebSocket APIs. Dependencies (WorkflowManager, WorkflowStateManager) are injected via constructor.
- config.py: Centralized configuration with
BotConfig.from_env()for loading environment variables and constants. - job_queue.py:
SerialJobQueueensuring generation requests execute sequentially, preventing ComfyUI server overload. - workflow_manager.py:
WorkflowManagerclass handling workflow template storage and node manipulation (finding/replacing prompts, seeds, etc). - workflow_state.py:
WorkflowStateManagerclass managing runtime workflow changes (prompt, negative_prompt, input_image) in memory with optional file persistence. - discord_utils.py: Reusable Discord utilities including
@require_comfy_clientdecorator, argument parsing, and theUploadViewcomponent. - commands/: Command handlers organized by functionality. Each module exports a
setup_*_commands(bot, config)function.
Key Architectural Patterns
-
Dependency Injection: ComfyClient receives WorkflowManager and WorkflowStateManager as constructor parameters, eliminating tight coupling to file-based state.
-
Job Queue System: All generation requests are queued through
SerialJobQueuein job_queue.py. Jobs execute serially with a worker loop that catches and logs exceptions without crashing the bot. -
Workflow System: The bot uses two modes:
- Prompt mode: Simple prompt + negative_prompt (requires workflow template with KSampler node)
- Workflow mode: Full workflow JSON with dynamic modifications from WorkflowStateManager
-
Workflow Modification Flow:
- Load workflow template via
bot.comfy.set_workflow()orbot.comfy.load_workflow_from_file() - Runtime changes (prompt, negative_prompt, input_image) stored in WorkflowStateManager
- At generation time, WorkflowManager methods locate nodes by class_type and title metadata, then inject values
- Seeds are randomized automatically via
workflow_manager.find_and_replace_seed()
- Load workflow template via
-
Command Registration: Commands are registered via
commands.register_all_commands(bot, config)which calls individualsetup_*_commands()functions from each command module. -
Configuration Management: All configuration loaded via
BotConfig.from_env()in config.py. Constants (command prefixes, error messages, limits) centralized in config.py. -
History Management: ComfyClient maintains a bounded deque of recent generations (configurable via
history_limit) for retrieval viattr!get-history.
Environment Variables
Required in .env:
DISCORD_BOT_TOKEN: Discord bot authentication tokenCOMFY_SERVER: ComfyUI server address (e.g.,localhost:8188orexample.com:8188)
Optional:
WORKFLOW_FILE: Path to JSON workflow file to load at startupCOMFY_HISTORY_LIMIT: Number of generations to keep in history (default: 10)COMFY_OUTPUT_PATH: Path to ComfyUI output directory (default:C:\Users\ktrangia\Documents\ComfyUI\output)
Running the Bot
python bot.py
The bot will:
- Load configuration from environment variables via
BotConfig.from_env() - Create WorkflowStateManager and WorkflowManager instances
- Initialize ComfyClient with injected dependencies
- Load workflow from
WORKFLOW_FILEif specified - Register all commands via
commands.register_all_commands() - Start Discord bot and job queue
- Listen for commands with prefix
ttr!
Development Commands
No build/test/lint commands exist. This is a standalone Python application.
To run: python bot.py
Key Implementation Details
ComfyUI Workflow Node Injection
When generating with workflows, WorkflowManager searches for specific node patterns:
- Prompt: Finds
CLIPTextEncodenodes with_meta.titlecontaining "Positive Prompt" - Negative Prompt: Finds
CLIPTextEncodenodes with_meta.titlecontaining "Negative Prompt" - Input Image: Finds
LoadImagenodes and replaces theimageinput - Seeds: Finds any node with
inputs.seedorinputs.noise_seedand randomizes
This pattern-matching approach means workflows must follow naming conventions in their node titles for dynamic updates to work.
Discord Command Pattern
Commands use a labelled parameter syntax: ttr!generate prompt:<text> negative_prompt:<text>
Parsing is handled by helpers in discord_utils.py (e.g., parse_labeled_args()). The bot splits on keyword markers (prompt:, negative_prompt:, type:, etc.) rather than traditional argparse. Case is preserved for prompts.
Job Queue Mechanics
Jobs are dataclasses with run: Callable[[], Awaitable[None]] and a label for logging. The queue returns position on submit. Jobs capture their context (ctx, prompts) via lambda closures when submitted.
Image/Video Output Handling
The _general_generate method in ComfyClient returns both images and videos. Videos are identified by file extension (mp4, webm, avi) in the history response. For videos, the bot reads the file from disk at the path specified by COMFY_OUTPUT_PATH rather than downloading via the API.
Command Validation
The @require_comfy_client decorator (from discord_utils.py) validates that bot.comfy exists before executing commands. This eliminates repetitive validation code in every command handler.
State Management
WorkflowStateManager maintains runtime workflow changes in memory with optional persistence to current-workflow-changes.json. The file is loaded on initialization if it exists, and saved automatically when changes are made.
Configuration System
Configuration is managed via the BotConfig dataclass in config.py:
from config import BotConfig
# Load from environment
config = BotConfig.from_env()
# Access configuration
server = config.comfy_server
history_limit = config.comfy_history_limit
output_path = config.comfy_output_path
All constants (command prefixes, error messages, defaults) are defined in config.py and imported where needed.
Adding New Commands
To add a new command:
- Create a new module in
commands/(e.g.,commands/my_feature.py) - Define a
setup_my_feature_commands(bot, config=None)function - Use
@bot.command(name="...")decorators to define commands - Use
@require_comfy_clientdecorator if command needs ComfyClient - Import and call your setup function in
commands/__init__.py'sregister_all_commands()
Example:
# commands/my_feature.py
from discord.ext import commands
from discord_utils import require_comfy_client
def setup_my_feature_commands(bot):
@bot.command(name="my-command")
@require_comfy_client
async def my_command(ctx: commands.Context):
await ctx.reply("Hello from my command!")
Dependencies
From imports:
- discord.py
- aiohttp
- websockets
- python-dotenv (optional, for .env loading)
No requirements.txt exists. Install manually: pip install discord.py aiohttp websockets python-dotenv
Code Organization Principles
The refactored codebase follows these principles:
- Single Responsibility: Each module has one clear purpose
- Dependency Injection: Dependencies passed via constructor, not created internally
- Configuration Centralization: All configuration in config.py
- Command Separation: Commands grouped by functionality in separate modules
- No Magic Strings: Constants defined once in config.py
- Type Safety: Modern Python type hints throughout (dict[str, Any] instead of Dict)
- Logging: Using logger methods instead of print() statements