--- title: ComfyUI Extension Development Guide description: >- Learn how to add new models, workflows, and features to LobeHub's ComfyUI integration tags: - ComfyUI - Development Guide - Model Extension - Workflow Development --- # ComfyUI Extension Development Guide This guide is based on actual code implementation and helps developers extend LobeHub's ComfyUI integration functionality. ## Architecture Overview LobeHub ComfyUI integration uses a four-layer service architecture built around the main `LobeComfyUI` class: ```plaintext packages/model-runtime/src/providers/comfyui/ ├── index.ts # LobeComfyUI main class entry ├── services/ # Four core services │ ├── comfyuiClient.ts # ComfyUIClientService - client and auth │ ├── modelResolver.ts # ModelResolverService - model resolution │ ├── workflowBuilder.ts # WorkflowBuilderService - workflow building │ └── imageService.ts # ImageService - image generation ├── config/ # Configuration system │ ├── modelRegistry.ts # Main model registry (222 models) │ ├── fluxModelRegistry.ts # 130 FLUX model configurations │ ├── sdModelRegistry.ts # 92 SD series model configurations │ ├── systemComponents.ts # VAE/CLIP/T5/LoRA/ControlNet components │ └── workflowRegistry.ts # Workflow routing configurations ├── workflows/ # Workflow implementations │ ├── flux-dev.ts # FLUX Dev 20-step workflow │ ├── flux-schnell.ts # FLUX Schnell 4-step fast workflow │ ├── flux-kontext.ts # FLUX Kontext fill workflow │ ├── sd35.ts # SD3.5 external encoder workflow │ ├── simple-sd.ts # Generic SD workflow │ └── index.ts # Workflow exports ├── utils/ # Utility layer │ ├── staticModelLookup.ts # Model lookup functions │ ├── workflowDetector.ts # Model architecture detection │ ├── promptSplitter.ts # FLUX dual prompt splitting │ ├── seedGenerator.ts # Random seed generation │ ├── cacheManager.ts # TTL cache management │ └── workflowUtils.ts # Workflow utility functions └── errors/ # Error handling ├── base.ts # Base error classes ├── modelResolverError.ts # Model resolution errors ├── workflowError.ts # Workflow errors └── servicesError.ts # Service errors src/server/services/comfyui/ # Server-side implementation ├── core/ # Core server services │ ├── comfyUIAuthService.ts # Authentication service │ ├── comfyUIClientService.ts # Client service │ ├── comfyUIConnectionService.ts # Connection service │ ├── errorHandlerService.ts # Error handling service │ ├── imageService.ts # Image generation service │ ├── modelResolverService.ts # Model resolution service │ └── workflowBuilderService.ts # Workflow builder service ├── config/ # Server-side configurations │ ├── constants.ts # Constants and defaults │ ├── modelRegistry.ts # Model registry │ ├── fluxModelRegistry.ts # FLUX models │ ├── sdModelRegistry.ts # SD models │ ├── systemComponents.ts # System components │ └── workflowRegistry.ts # Workflow registry ├── workflows/ # Server-side workflow implementations │ ├── flux-dev.ts # FLUX Dev workflow │ ├── flux-schnell.ts # FLUX Schnell workflow │ ├── flux-kontext.ts # FLUX Kontext workflow │ ├── sd35.ts # SD3.5 workflow │ └── simple-sd.ts # Simple SD workflow ├── utils/ # Server utilities │ ├── cacheManager.ts # Cache management │ ├── componentInfo.ts # Component information │ ├── imageResizer.ts # Image resizing │ ├── promptSplitter.ts # Prompt splitting │ ├── staticModelLookup.ts # Model lookup │ ├── weightDType.ts # Weight dtype utilities │ ├── workflowDetector.ts # Workflow detection │ └── workflowUtils.ts # Workflow utilities └── errors/ # Server error handling ├── base.ts # Base error classes ├── configError.ts # Configuration errors ├── modelResolverError.ts # Model resolver errors ├── servicesError.ts # Service errors ├── utilsError.ts # Utility errors └── workflowError.ts # Workflow errors packages/model-runtime/src/utils/ # Shared utilities └── comfyuiErrorParser.ts # Unified error parser for client/server ``` ### Core Service Architecture The main `LobeComfyUI` class initializes four core services: ```typescript // packages/model-runtime/src/providers/comfyui/index.ts export class LobeComfyUI implements LobeRuntimeAI, AuthenticatedImageRuntime { constructor(options: ComfyUIKeyVault = {}) { // 1. Client Service - handles auth and API calls this.clientService = new ComfyUIClientService(options); // 2. Model Resolver Service - model lookup and component selection const modelResolverService = new ModelResolverService(this.clientService); // 3. Workflow Builder Service - routes and builds workflows const workflowBuilderService = new WorkflowBuilderService({ clientService: this.clientService, modelResolverService: modelResolverService, }); // 4. Image Service - unified image generation entry point this.imageService = new ImageService( this.clientService, modelResolverService, workflowBuilderService, ); } } ``` ## Authentication System ComfyUI integration supports four authentication methods, handled by `AuthManager` within `ComfyUIClientService`: ### Supported Authentication Types ```typescript interface ComfyUIKeyVault { baseURL: string; authType?: 'none' | 'basic' | 'bearer' | 'custom'; // Basic Auth username?: string; password?: string; // Bearer Token apiKey?: string; // Custom Headers customHeaders?: Record; } ``` ### Authentication Configuration Examples ```typescript // No authentication const comfyUI = new LobeComfyUI({ baseURL: 'http://localhost:8000', authType: 'none' }); // Basic authentication const comfyUI = new LobeComfyUI({ baseURL: 'https://your-comfyui-server.com', authType: 'basic', username: 'your-username', password: 'your-password' }); // Bearer Token const comfyUI = new LobeComfyUI({ baseURL: 'https://your-comfyui-server.com', authType: 'bearer', apiKey: 'your-api-key' }); // Custom headers const comfyUI = new LobeComfyUI({ baseURL: 'https://your-comfyui-server.com', authType: 'custom', customHeaders: { 'X-API-Key': 'your-custom-key', 'Authorization': 'Custom your-token' } }); ``` ## WebAPI Routes ComfyUI provides a REST WebAPI route for image generation, supporting both regular authentication and internal service authentication: ### Route Details ```typescript // src/app/(backend)/webapi/create-image/comfyui/route.ts export const runtime = 'nodejs'; export const maxDuration = 300; // 5 minutes max // POST /api/create-image/comfyui { model: string; // Model identifier params: { // Generation parameters prompt: string; width?: number; height?: number; // ... other parameters }; options?: { // Optional generation options // ... additional options }; } ``` ### Authentication Middleware The WebAPI route uses the `checkAuth` middleware for authentication: ```typescript import { checkAuth } from '@/app/(backend)/middleware/auth'; // The route automatically validates JWT tokens // and passes authentication context to the tRPC caller ``` ### Error Handling The WebAPI route provides structured error responses: ```typescript // AgentRuntimeError is extracted from TRPCError's cause if (agentError && 'errorType' in agentError) { // Convert errorType to appropriate HTTP status // 401 for InvalidProviderAPIKey // 403 for PermissionDenied // 404 for NotFound // 500+ for server errors } ``` ## Adding New Models ### 1. Understanding Model Registry Structure Model configurations are stored in configuration files: ```typescript // packages/model-runtime/src/providers/comfyui/config/modelRegistry.ts export interface ModelConfig { modelFamily: 'FLUX' | 'SD1' | 'SDXL' | 'SD3'; priority: number; // 1=Official, 2=Enterprise, 3=Community recommendedDtype?: 'default' | 'fp8_e4m3fn' | 'fp8_e5m2'; variant: string; // Model variant identifier } ``` ### 2. Adding FLUX Models Add new models in `fluxModelRegistry.ts`: ```typescript // packages/model-runtime/src/providers/comfyui/config/fluxModelRegistry.ts export const FLUX_MODEL_REGISTRY: Record = { // Existing models... // Add new FLUX Dev model 'your-custom-flux-dev.safetensors': { modelFamily: 'FLUX', priority: 2, // Enterprise-level model variant: 'dev', recommendedDtype: 'default', }, // Add quantized version 'your-custom-flux-dev-fp8.safetensors': { modelFamily: 'FLUX', priority: 2, variant: 'dev', recommendedDtype: 'fp8_e4m3fn', }, }; ``` ### 3. Adding SD Series Models Add in `sdModelRegistry.ts`: ```typescript // packages/model-runtime/src/providers/comfyui/config/sdModelRegistry.ts export const SD_MODEL_REGISTRY: Record = { // Existing models... // Add new SD3.5 model 'your-custom-sd35.safetensors': { modelFamily: 'SD3', priority: 2, variant: 'sd35', recommendedDtype: 'default', }, }; ``` ### 4. Update Model ID Mapping (Optional) If you need friendly model IDs for frontend, add mapping in `modelRegistry.ts`: ```typescript // packages/model-runtime/src/providers/comfyui/config/modelRegistry.ts export const MODEL_ID_VARIANT_MAP: Record = { // Existing mappings... // Add new model friendly IDs 'my-custom-flux': 'dev', // Maps to dev variant 'my-custom-sd35': 'sd35', // Maps to sd35 variant }; ``` ## Creating New Workflows ### Workflow Creation Principles **Important: Workflow node structures come from native ComfyUI exports** 1. Design workflow in ComfyUI interface 2. Export as JSON using "Export (API Format)" 3. Copy JSON structure to TypeScript file 4. Wrap and parameterize using `PromptBuilder` ### 1. Export Workflow from ComfyUI In the ComfyUI interface: 1. Drag nodes to build desired workflow 2. Connect node inputs and outputs 3. Right-click empty area → "Export (API Format)" 4. Copy the generated JSON structure ### 2. Workflow File Template Create new file `workflows/your-workflow.ts`: ```typescript import { PromptBuilder } from '@saintno/comfyui-sdk'; import type { WorkflowContext } from '../services/workflowBuilder'; import { generateUniqueSeeds } from '../utils/seedGenerator'; import { getWorkflowFilenamePrefix } from '../utils/workflowUtils'; /** * Build custom workflow * @param modelFileName - Model file name * @param params - Generation parameters * @param context - Workflow context */ export async function buildYourCustomWorkflow( modelFileName: string, params: Record, context: WorkflowContext, ): Promise> { // JSON structure from ComfyUI "Export (API Format)" const workflow = { '1': { _meta: { title: 'Load Checkpoint' }, class_type: 'CheckpointLoaderSimple', inputs: { ckpt_name: modelFileName, }, }, '2': { _meta: { title: 'CLIP Text Encode' }, class_type: 'CLIPTextEncode', inputs: { clip: ['1', 1], // Connect to node 1 CLIP output text: params.prompt, }, }, '3': { _meta: { title: 'Empty Latent' }, class_type: 'EmptyLatentImage', inputs: { width: params.width, height: params.height, batch_size: 1, }, }, '4': { _meta: { title: 'KSampler' }, class_type: 'KSampler', inputs: { model: ['1', 0], // Connect to node 1 MODEL output positive: ['2', 0], // Connect to node 2 CONDITIONING output negative: ['2', 0], // Can configure negative prompts latent_image: ['3', 0], seed: params.seed ?? generateUniqueSeeds(1)[0], steps: params.steps, cfg: params.cfg, sampler_name: 'euler', scheduler: 'normal', denoise: 1.0, }, }, '5': { _meta: { title: 'VAE Decode' }, class_type: 'VAEDecode', inputs: { samples: ['4', 0], vae: ['1', 2], // Connect to node 1 VAE output }, }, '6': { _meta: { title: 'Save Image' }, class_type: 'SaveImage', inputs: { filename_prefix: getWorkflowFilenamePrefix('buildYourCustomWorkflow', context.variant), images: ['5', 0], }, }, }; // Wrap static JSON with PromptBuilder const builder = new PromptBuilder( workflow, ['width', 'height', 'steps', 'cfg', 'seed'], // Input parameters ['images'], // Output parameters ); // Set output nodes builder.setOutputNode('images', '6'); // Set input node paths builder.setInputNode('width', '3.inputs.width'); builder.setInputNode('height', '3.inputs.height'); builder.setInputNode('steps', '4.inputs.steps'); builder.setInputNode('cfg', '4.inputs.cfg'); builder.setInputNode('seed', '4.inputs.seed'); // Set parameter values builder .input('width', params.width) .input('height', params.height) .input('steps', params.steps) .input('cfg', params.cfg) .input('seed', params.seed ?? generateUniqueSeeds(1)[0]); return builder; } ``` ### 3. Register New Workflow Add workflow mapping in `workflowRegistry.ts`: ```typescript // packages/model-runtime/src/providers/comfyui/config/workflowRegistry.ts import { buildYourCustomWorkflow } from '../workflows/your-workflow'; export const VARIANT_WORKFLOW_MAP: Record = { // Existing mappings... // Add new workflow 'your-variant': buildYourCustomWorkflow, }; ``` ### 4. Actual Workflow Example Reference the real implementation in `flux-dev.ts`: ```typescript // packages/model-runtime/src/providers/comfyui/workflows/flux-dev.ts (simplified) export async function buildFluxDevWorkflow( modelFileName: string, params: Record, context: WorkflowContext, ): Promise> { // Get required components const selectedT5Model = await context.modelResolverService.getOptimalComponent('t5', 'FLUX'); const selectedVAE = await context.modelResolverService.getOptimalComponent('vae', 'FLUX'); const selectedCLIP = await context.modelResolverService.getOptimalComponent('clip', 'FLUX'); // Handle dual prompt splitting const { t5xxlPrompt, clipLPrompt } = splitPromptForDualCLIP(params.prompt); // Static workflow definition (from ComfyUI export) const workflow = { '1': { class_type: 'DualCLIPLoader', inputs: { clip_name1: selectedT5Model, clip_name2: selectedCLIP, type: 'flux', }, }, // ... more nodes }; // Parameter injection (must be done within workflow file) workflow['5'].inputs.clip_l = clipLPrompt; workflow['5'].inputs.t5xxl = t5xxlPrompt; workflow['4'].inputs.width = params.width; workflow['4'].inputs.height = params.height; // Create and configure PromptBuilder const builder = new PromptBuilder(workflow, inputs, outputs); // Configure input/output mappings... return builder; } ``` ## System Component Management ### Component Configuration Structure All system components (VAE, CLIP, T5, LoRA, ControlNet) are unified in `systemComponents.ts`: ```typescript // packages/model-runtime/src/providers/comfyui/config/systemComponents.ts export interface ComponentConfig { modelFamily: string; // Model family priority: number; // 1=Required, 2=Standard, 3=Optional type: string; // Component type compatibleVariants?: string[]; // Compatible variants (LoRA/ControlNet) controlnetType?: string; // ControlNet type } export const SYSTEM_COMPONENTS: Record = { // VAE components 'ae.safetensors': { modelFamily: 'FLUX', priority: 1, type: 'vae', }, // CLIP components 'clip_l.safetensors': { modelFamily: 'FLUX', priority: 1, type: 'clip', }, // T5 encoders 't5xxl_fp16.safetensors': { modelFamily: 'FLUX', priority: 1, type: 't5', }, // LoRA adapters 'realism_lora.safetensors': { compatibleVariants: ['dev'], modelFamily: 'FLUX', priority: 1, type: 'lora', }, // ControlNet models 'flux-controlnet-canny-v3.safetensors': { compatibleVariants: ['dev'], controlnetType: 'canny', modelFamily: 'FLUX', priority: 1, type: 'controlnet', }, }; ``` ### Adding New Components ```typescript // Add new LoRA 'your-custom-lora.safetensors': { compatibleVariants: ['dev', 'schnell'], modelFamily: 'FLUX', priority: 2, type: 'lora', }, // Add new ControlNet 'your-controlnet-pose.safetensors': { compatibleVariants: ['dev'], controlnetType: 'pose', modelFamily: 'FLUX', priority: 2, type: 'controlnet', }, ``` ### Component Query API ```typescript import { getAllComponentsWithNames, getOptimalComponent } from '../config/systemComponents'; // Get optimal component const bestVAE = getOptimalComponent('vae', 'FLUX'); const bestT5 = getOptimalComponent('t5', 'FLUX'); // Query specific type components const availableLoras = getAllComponentsWithNames({ type: 'lora', modelFamily: 'FLUX', compatibleVariant: 'dev' }); // Query ControlNet const cannyControlNets = getAllComponentsWithNames({ type: 'controlnet', controlnetType: 'canny', modelFamily: 'FLUX' }); ``` ## Model Resolution and Lookup ### ModelResolverService Working Principles ```typescript // packages/model-runtime/src/providers/comfyui/services/modelResolver.ts export class ModelResolverService { async resolveModelFileName(modelId: string): Promise { // 1. Clean model ID const cleanId = modelId.replace(/^comfyui\//, ''); // 2. Check model ID mapping const mappedVariant = MODEL_ID_VARIANT_MAP[cleanId]; if (mappedVariant) { const prioritizedModels = getModelsByVariant(mappedVariant); const serverModels = await this.getAvailableModelFiles(); // Find first available model by priority for (const filename of prioritizedModels) { if (serverModels.includes(filename)) { return filename; } } } // 3. Direct registry lookup if (MODEL_REGISTRY[cleanId]) { return cleanId; } // 4. Check server file existence if (isModelFile(cleanId)) { const serverModels = await this.getAvailableModelFiles(); if (serverModels.includes(cleanId)) { return cleanId; } } return undefined; } } ``` ### Model Lookup Examples ```typescript // Actual usage examples const resolver = new ModelResolverService(clientService); // Friendly ID lookup const fluxDevFile = await resolver.resolveModelFileName('flux-dev'); // Returns: 'flux1-dev.safetensors' (if exists) // Direct filename lookup const directFile = await resolver.resolveModelFileName('my-custom-model.safetensors'); // Returns: 'my-custom-model.safetensors' (if exists) // Variant lookup const devModels = getModelsByVariant('dev'); console.log(devModels.slice(0, 3)); // Output: ['flux1-dev.safetensors', 'flux1-dev-fp8.safetensors', ...] ``` ## Error Handling ### Error Type Hierarchy ```plaintext // packages/model-runtime/src/providers/comfyui/errors/ ComfyUIInternalError // Base error ├── ModelResolverError // Model resolution errors ├── WorkflowError // Workflow errors ├── ServicesError // Service errors └── UtilsError // Utility errors ``` ### Error Handling Examples ```typescript import { ModelResolverError, WorkflowError } from '../errors'; try { const result = await comfyUI.createImage({ model: 'nonexistent-model', params: { prompt: 'test' } }); } catch (error) { if (error instanceof ModelResolverError) { console.log('Model resolution failed:', error.message); console.log('Error reason:', error.reason); console.log('Error details:', error.details); } else if (error instanceof WorkflowError) { console.log('Workflow error:', error.message); } } ``` ### Unified Error Parser A shared error parser is available for both client and server-side error handling: ```typescript // packages/model-runtime/src/utils/comfyuiErrorParser.ts import { parseComfyUIErrorMessage, cleanComfyUIErrorMessage } from '../utils/comfyuiErrorParser'; // Parse error messages and determine error types const { error, errorType } = parseComfyUIErrorMessage(rawError); // Clean error messages from ComfyUI formatting const cleanMessage = cleanComfyUIErrorMessage(errorMessage); ``` The error parser handles: - HTTP status code mapping to error types - Server-side error enhancement - Model file missing detection - Network error identification - Workflow validation errors ## Testing Architecture and Development ### Testing Architecture Overview The ComfyUI integration uses a unified testing architecture that ensures maintainability and customization-friendly tests. This architecture includes: - **Unified Mock System**: Centralized management of all external dependency mocks - **Parameterized Testing**: Automatically adapts to new models without modifying existing tests - **Fixture System**: Retrieves test data from configuration files to ensure accuracy - **Coverage Goals**: ComfyUI module maintains 97%+ coverage ### Test File Structure ```plaintext packages/model-runtime/src/providers/comfyui/__tests__/ ├── setup/ │ └── unifiedMocks.ts # Unified Mock configuration ├── fixtures/ │ ├── parameters.fixture.ts # Parameter test fixtures │ └── workflow.fixture.ts # Workflow test fixtures ├── integration/ │ ├── parameterMapping.test.ts # Parameter mapping integration tests │ └── workflowBuilder.test.ts # Workflow builder tests ├── services/ # Service unit tests └── workflows/ # Workflow unit tests ``` ### Adding Tests for New Models When adding new models, tests will automatically recognize and run appropriate parameter mapping tests. You only need to: #### 1. Add Parameter Schema in Model Configuration ```typescript // packages/model-bank/src/aiModels/comfyui.ts export const myNewModelParamsSchema = { prompt: { type: 'string', required: true }, steps: { type: 'number', default: 20, min: 1, max: 150 }, cfg: { type: 'number', default: 7.0, min: 1.0, max: 30.0 } }; ``` #### 2. Create Workflow Builder ```typescript // packages/model-runtime/src/providers/comfyui/workflows/myNewModel.ts export async function buildMyNewModelWorkflow( modelName: string, params: MyNewModelParams, context: ComfyUIContext ) { const workflow = { /* workflow definition */ }; // Parameter injection workflow['1'].inputs.prompt = params.prompt; workflow['2'].inputs.steps = params.steps; return workflow; } ``` #### 3. Register Model in Fixtures ```typescript // packages/model-runtime/src/providers/comfyui/__tests__/fixtures/parameters.fixture.ts import { myNewModelParamsSchema, // ... other schemas } from '../../../../../model-bank/src/aiModels/comfyui'; export const parametersFixture = { models: { 'my-new-model': { schema: myNewModelParamsSchema, defaults: { steps: myNewModelParamsSchema.steps.default, cfg: myNewModelParamsSchema.cfg.default, }, boundaries: { min: { steps: myNewModelParamsSchema.steps.min }, max: { steps: myNewModelParamsSchema.steps.max } } } } }; ``` ### Testing Best Practices #### Use Unified Mock System ```typescript import { setupAllMocks } from '../setup/unifiedMocks'; describe('MyTest', () => { const mocks = setupAllMocks(); beforeEach(() => { vi.clearAllMocks(); }); }); ``` #### Write Parameter Mapping Tests Parameter mapping tests run automatically, verifying that frontend parameters are correctly injected into workflows: ```typescript // Tests automatically include newly registered models describe.each( Object.entries(models).filter(([name]) => workflowBuilders[name]) )( '%s parameter mapping', (modelName, modelConfig) => { it('should map schema parameters to workflow', async () => { const params = { prompt: 'test prompt', ...modelConfig.defaults, }; const workflow = await builder(`${modelName}.safetensors`, params, mockContext); expect(workflow).toBeDefined(); }); } ); ``` #### Customization-Friendly Testing Principles - **Don't test workflow structure**: Workflows are ComfyUI's official format; only test parameter mapping - **Use configuration-driven data**: Test data comes from model configuration files to ensure consistency - **Avoid brittle assertions**: Don't check specific node IDs or internal structures - **Support extension**: New models should only affect coverage, not break existing tests ### Running Tests ```bash # Run ComfyUI related tests cd packages/model-runtime bunx vitest run --silent='passed-only' 'src/comfyui' # View coverage bunx vitest run --coverage 'src/comfyui' # Run specific test files bunx vitest run 'src/comfyui/__tests__/integration/parameterMapping.test.ts' ``` ### Coverage Targets - **Overall coverage**: ComfyUI module maintains 97%+ coverage - **Core functionality**: 100% branch coverage - **New features**: Maintain or improve existing coverage levels ## Development and Testing ### 1. Local Development Setup ```bash # Start ComfyUI debug mode DEBUG=lobe-image:* pnpm dev ``` ### 2. Testing New Features ```typescript // Create test file import { buildYourCustomWorkflow } from './your-workflow'; describe('Custom Workflow', () => { test('should build workflow correctly', async () => { const mockContext = { clientService: mockClientService, modelResolverService: mockModelResolver, }; const workflow = await buildYourCustomWorkflow( 'test-model.safetensors', { prompt: 'test', width: 512, height: 512 }, mockContext ); expect(workflow).toBeDefined(); // Verify workflow structure... }); }); ``` ### 3. Model Configuration Testing ```typescript import { getModelConfig, getAllModelNames } from '../config/modelRegistry'; describe('Model Registry', () => { test('should find new model', () => { const config = getModelConfig('your-new-model.safetensors'); expect(config).toBeDefined(); expect(config?.variant).toBe('dev'); expect(config?.modelFamily).toBe('FLUX'); }); }); ``` ## Complete Usage Examples ### Basic Image Generation ```typescript import { LobeComfyUI } from '@/libs/model-runtime/comfyui'; const comfyUI = new LobeComfyUI({ baseURL: 'http://localhost:8000', authType: 'none' }); // FLUX Dev model generation const result = await comfyUI.createImage({ model: 'flux-dev', params: { prompt: 'Beautiful landscape painting, high quality, detailed', width: 1024, height: 1024, steps: 20, cfg: 3.5, seed: -1 } }); console.log('Generated image URL:', result.imageUrl); ``` ### SD3.5 Model Usage ```typescript // SD3.5 automatically detects available encoders const sd35Result = await comfyUI.createImage({ model: 'stable-diffusion-35', params: { prompt: 'Futuristic cityscape', width: 1344, height: 768, steps: 28, cfg: 4.5 } }); ``` ### Enterprise Optimized Models ```typescript // System automatically selects best available variant (e.g., FP8 quantized) const optimizedResult = await comfyUI.createImage({ model: 'flux-dev', params: { prompt: 'Professional business portrait', width: 768, height: 1024, steps: 15 // FP8 models can use fewer steps } }); ``` ## Important Notes - Ensure ComfyUI service is running and accessible - Check that all required model files are properly installed - Pay attention to model file naming conventions and path configurations - Regularly check and update workflow configurations to support new features - Be aware of parameter differences and compatibility across model families - When adding new models, follow the testing architecture guidelines to ensure test completeness - Always run relevant tests before committing code to ensure coverage targets are met ## Summary This documentation is based on actual code implementation and includes: 1. **Real Architecture Description**: Four-layer service architecture with clear responsibility separation 2. **Accurate API Calls**: Using `PromptBuilder` instead of fictional classes 3. **Correct Workflow Creation**: Real process of exporting JSON from ComfyUI 4. **Actual Configuration Structure**: Based on real registry files 5. **Working Code Examples**: All examples can be run directly 6. **Comprehensive Testing Guide**: Unified testing architecture with customization-friendly approach Developers can use this accurate documentation to effectively extend ComfyUI integration functionality while maintaining high code quality and test coverage.