11 KiB
Architecture
ComfyUI-Doctor is a ComfyUI custom node extension with three main surfaces:
- a Python package that loads inside ComfyUI and registers PromptServer routes
- browser-side JavaScript that renders the Doctor sidebar and panels
- development/test tooling that keeps host compatibility, API contracts, and UI behavior stable
For route-level details, use the machine-readable OpenAPI contract: openapi.json.
Host Startup
ComfyUI loads the package entry point from __init__.py. That file keeps host-facing responsibilities together:
- install or hand off the startup logger
- initialize the full
SmartLogger - configure LLM rate and concurrency limits
- create the API logger
- collect a system snapshot
- register PromptServer routes through
api_routes.py - expose node mappings and
WEB_DIRECTORY
prestartup_script.py runs earlier in the ComfyUI startup lifecycle. It captures early terminal output before the full package import is available. The main package then hands off that logger so startup logs and runtime logs share one path.
Backend Layout
The backend is organized around a small entry point and focused service modules:
| Area | Primary files | Responsibility |
|---|---|---|
| Package entry | __init__.py, nodes.py, prestartup_script.py |
ComfyUI loading, node export, startup logging |
| API routes | api_routes.py, services/routes.py |
PromptServer HTTP route registration and route handlers |
| Analysis | analyzer.py, pattern_loader.py, pipeline/, services/prompt_helpers.py |
Error categorization, pattern matching, prompt construction |
| LLM | llm_client.py, session_manager.py, services/llm_provider_adapters.py, services/llm/ |
Provider requests, retry, proxy policy, rate/concurrency limits |
| Security | security.py, outbound.py, sanitizer.py, services/security/ |
SSRF checks, outbound sanitization, admin guard, error envelopes |
| Storage | services/doctor_paths.py, logger.py, history_store.py, services/secret_store.py |
Canonical data paths, logs, history, encrypted credential storage |
| Diagnostics | services/diagnostics/, services/intent/ |
Workflow, dependency, current host model/media/dataset asset folders and loaders, privacy, performance, and signature-pack checks |
| Community | services/community_feedback.py, pipeline/plugins/ |
Feedback preview/submission and scan-only plugin trust reporting |
| Telemetry | telemetry.py, web/doctor_telemetry.js |
Local-only opt-in event buffer and UI controls |
The domain packages under services/llm/, services/security/, services/infra/, and services/community/ provide stable import entry points for code that should not depend on individual implementation file paths.
API Surface
api_routes.py registers the main Doctor and debugger endpoints. Smaller service-owned handlers live in services/routes.py and are attached by api_routes.py.
The public API groups are:
- debugger status, language, and history
- LLM analysis, chat, provider defaults, key verification, and model listing
- admin-gated server-side credential metadata and storage
- statistics, resolution state, and feedback
- runtime health, diagnostics, and plugin trust reports
- local telemetry controls
- resumable jobs and provider capability status
Write-sensitive routes use the Doctor admin guard. The API error shape is centralized through services/api_response.py, and the public contract is captured in docs/openapi.json.
Doctor-owned docs use canonical /doctor/... route paths. Current ComfyUI hosts may also expose /api/doctor/... aliases through host route duplication, but that global alias behavior belongs to the host.
Data Flows
Startup and Logging
prestartup_script.pycaptures early output.__init__.pyimports the package with ComfyUI-relative imports.SmartLogger.install()takes over logging.- The API logger writes operational events to the Doctor data directory.
- Route registration runs after ComfyUI
serverandaiohttpimports are available.
Error Analysis
- ComfyUI output is captured by
SmartLogger. - The analyzer and pattern pipeline classify the error.
- Node/workflow context is collected and pruned.
- Prompt helpers build a provider-neutral request payload.
- LLM calls go through adapter, retry, rate-limit, proxy, SSRF, and outbound-sanitization layers.
- Results are stored in history and exposed to the frontend.
Chat
- The frontend sends error context, user messages, provider settings, privacy mode, and optional credentials.
- Backend routes resolve credentials from request data, environment variables, local provider behavior, or the server-side store.
- The provider adapter builds the request.
- The route returns JSON or Server-Sent Events for streaming chat.
Diagnostics
- The frontend or caller posts workflow/context data to diagnostics endpoints.
HealthCheckRequestis parsed by the diagnostics runner.- Registered checks inspect workflow lint, dependencies, model assets, privacy/security, runtime performance, and signature packs.
- Reports are saved by the diagnostics store and exposed through report/history endpoints.
Model asset checks use ComfyUI's live folder_names_and_paths registry as the
authoritative source when available, including custom roots and registered
extensions. Older hosts retain a bounded fixed fallback. Workflow traversal
also inspects bounded definitions.subgraphs content and preserves visible
host plus concrete source provenance for nested assets. Positional widget
values remain authoritative and uniquely matched named values are fallback
only. First-party promoted image/video/output/audio loaders retain concrete
source provenance; arbitrary custom upload-loader behavior is not inferred
without authoritative node definitions. Input/dataset folders and every file
candidate are real-path-contained within registered roots before any
filesystem probe, read, or enumeration.
Telemetry
Telemetry is local-only and disabled by default. When enabled, accepted events are validated against an allowlist and written to the local telemetry buffer. The browser UI can view, export, clear, and toggle telemetry through Doctor endpoints. The integration and stress test lanes use the Playwright harness backend for deterministic telemetry endpoint behavior.
Frontend Layout
ComfyUI loads frontend assets from web/.
| Area | Primary files | Responsibility |
|---|---|---|
| Extension registration | web/doctor.js, web/comfyui_frontend_compat.js |
ComfyUI extension setup and host API compatibility |
| State and API | web/doctor_state.js, web/doctor_api.js, web/doctor_actions.js |
UI state, backend requests, user actions |
| Shell UI | web/doctor_ui.js, web/doctor_right_panel.js, web/doctor_rendering.js, web/doctor_selectors.js |
Sidebar shell, right panel, rendering helpers, selectors |
| Chat | web/doctor_chat.js, web/chat-island.js, web/tabs/chat_tab.js, web/llm_provider_quick_switch.js |
Chat UI, Preact island, vanilla fallback, provider switch |
| Statistics and diagnostics | web/statistics-island.js, web/tabs/stats_tab.js, web/doctor_telemetry.js |
Stats dashboard, health/trust, feedback, telemetry |
| Settings | web/tabs/settings_tab.js, web/llm_key_store.js, web/privacy_utils.js |
Provider settings, credential handling, privacy mode |
| Resilience | web/preact-loader.js, web/island_registry.js, web/ErrorBoundary.js, web/global_error_handler.js |
Local Preact loading, island fallback, error boundaries |
Preact islands improve the Chat and Statistics surfaces, but each island has a vanilla fallback so the sidebar remains usable if the island loader fails. Tab activation receives the exact owned pane. Chat island activation and unmount operate on that concrete container, while late async render cleanup is discarded safely after tab-manager destruction rather than acting on detached DOM or an unrelated matching element. Validation-error display is normalized in the frontend so known prompt-validation failures use stable local catalog text and grouping metadata. Public raw errors and graph links can surface eligible input-level errors to a visible subgraph boundary while retaining source provenance; unknown or unproven topology falls back safely without private store access or breaking runtime error reporting.
Security and Storage Boundaries
Security-sensitive behavior is centralized:
- SSRF validation guards provider base URLs.
- Outbound sanitization prevents raw private context from leaving the process;
AuthorizationandX-API-Keyvalues are always redacted in text and structured payloads, regardless of privacy mode. - Privacy modes control how much local context can be sent to remote providers.
- Write-sensitive endpoints use the admin guard.
- Server-side credentials use the secret store and are never exposed through status APIs.
- Community plugins are scanned for trust metadata without importing plugin code.
- Telemetry is local-only and opt-in.
- Doctor-owned frontend settings opt out of the host frontend's independent setting-change telemetry.
- Plain backend and exception status strings are inserted as literal text; intentional rich chat rendering stays on its separate sanitized path.
Storage should go through services/doctor_paths.py so Desktop, portable, and
standard ComfyUI installations resolve Doctor data consistently. Runtime
identity and storage evidence are separate: a managed Desktop interpreter can
remain classified as Desktop while the data directory comes from ComfyUI's
private system-user API.
Testing Architecture
The full local acceptance gate is scripts/run_full_tests_windows.ps1 on Windows or scripts/run_full_tests_linux.sh on Linux/WSL. It covers:
- supply-chain dependency scan
- detect-secrets
- pre-commit hooks
- host-like package/startup validation
- backend unit tests
- default Playwright E2E
Backend test collection leaves the canonical production __init__.py
byte-stable. Host-shaped package loading is validated separately rather than
renaming the entry point or substituting a backup during pytest collection.
Additional focused lanes:
npm run test:integrationruns@integrationtelemetry tests against the harness backend by default, or a live backend whenCOMFYUI_URLis set.npm run test:stressruns opt-in@stresstelemetry burst/state tests against the harness backend.python scripts/focused_gate.pyruns the supplemental focused security/contract/E2E regression lane. It is not a replacement for the full acceptance gate.python scripts/check_host_compatibility.pyevaluates source-linked contracts with separate frontend runtime lanes for the Desktop bundle, ComfyUI package pin, and standalone frontend source.
Compatibility Principles
- Keep package imports compatible with ComfyUI custom-node loading.
- Keep frontend registration compatible with current and deprecated host sidebar APIs where support exists.
- Keep host compatibility checks version-aware and aligned with prompt queue source metadata, execution event payloads, model registries, nested workflow serialization, validation-error state, setting telemetry, Desktop layout, system statistics metadata, job-cancel contracts, and frontend queue/cancel adoption.
- Keep public route changes reflected in
docs/openapi.json. - Keep local harness tests deterministic; live backend tests must be explicit opt-in.