comfygit-core 0.2.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (93) hide show
  1. comfygit_core/analyzers/custom_node_scanner.py +109 -0
  2. comfygit_core/analyzers/git_change_parser.py +156 -0
  3. comfygit_core/analyzers/model_scanner.py +318 -0
  4. comfygit_core/analyzers/node_classifier.py +58 -0
  5. comfygit_core/analyzers/node_git_analyzer.py +77 -0
  6. comfygit_core/analyzers/status_scanner.py +362 -0
  7. comfygit_core/analyzers/workflow_dependency_parser.py +143 -0
  8. comfygit_core/caching/__init__.py +16 -0
  9. comfygit_core/caching/api_cache.py +210 -0
  10. comfygit_core/caching/base.py +212 -0
  11. comfygit_core/caching/comfyui_cache.py +100 -0
  12. comfygit_core/caching/custom_node_cache.py +320 -0
  13. comfygit_core/caching/workflow_cache.py +797 -0
  14. comfygit_core/clients/__init__.py +4 -0
  15. comfygit_core/clients/civitai_client.py +412 -0
  16. comfygit_core/clients/github_client.py +349 -0
  17. comfygit_core/clients/registry_client.py +230 -0
  18. comfygit_core/configs/comfyui_builtin_nodes.py +1614 -0
  19. comfygit_core/configs/comfyui_models.py +62 -0
  20. comfygit_core/configs/model_config.py +151 -0
  21. comfygit_core/constants.py +82 -0
  22. comfygit_core/core/environment.py +1635 -0
  23. comfygit_core/core/workspace.py +898 -0
  24. comfygit_core/factories/environment_factory.py +419 -0
  25. comfygit_core/factories/uv_factory.py +61 -0
  26. comfygit_core/factories/workspace_factory.py +109 -0
  27. comfygit_core/infrastructure/sqlite_manager.py +156 -0
  28. comfygit_core/integrations/__init__.py +7 -0
  29. comfygit_core/integrations/uv_command.py +318 -0
  30. comfygit_core/logging/logging_config.py +15 -0
  31. comfygit_core/managers/environment_git_orchestrator.py +316 -0
  32. comfygit_core/managers/environment_model_manager.py +296 -0
  33. comfygit_core/managers/export_import_manager.py +116 -0
  34. comfygit_core/managers/git_manager.py +667 -0
  35. comfygit_core/managers/model_download_manager.py +252 -0
  36. comfygit_core/managers/model_symlink_manager.py +166 -0
  37. comfygit_core/managers/node_manager.py +1378 -0
  38. comfygit_core/managers/pyproject_manager.py +1321 -0
  39. comfygit_core/managers/user_content_symlink_manager.py +436 -0
  40. comfygit_core/managers/uv_project_manager.py +569 -0
  41. comfygit_core/managers/workflow_manager.py +1944 -0
  42. comfygit_core/models/civitai.py +432 -0
  43. comfygit_core/models/commit.py +18 -0
  44. comfygit_core/models/environment.py +293 -0
  45. comfygit_core/models/exceptions.py +378 -0
  46. comfygit_core/models/manifest.py +132 -0
  47. comfygit_core/models/node_mapping.py +201 -0
  48. comfygit_core/models/protocols.py +248 -0
  49. comfygit_core/models/registry.py +63 -0
  50. comfygit_core/models/shared.py +356 -0
  51. comfygit_core/models/sync.py +42 -0
  52. comfygit_core/models/system.py +204 -0
  53. comfygit_core/models/workflow.py +914 -0
  54. comfygit_core/models/workspace_config.py +71 -0
  55. comfygit_core/py.typed +0 -0
  56. comfygit_core/repositories/migrate_paths.py +49 -0
  57. comfygit_core/repositories/model_repository.py +958 -0
  58. comfygit_core/repositories/node_mappings_repository.py +246 -0
  59. comfygit_core/repositories/workflow_repository.py +57 -0
  60. comfygit_core/repositories/workspace_config_repository.py +121 -0
  61. comfygit_core/resolvers/global_node_resolver.py +459 -0
  62. comfygit_core/resolvers/model_resolver.py +250 -0
  63. comfygit_core/services/import_analyzer.py +218 -0
  64. comfygit_core/services/model_downloader.py +422 -0
  65. comfygit_core/services/node_lookup_service.py +251 -0
  66. comfygit_core/services/registry_data_manager.py +161 -0
  67. comfygit_core/strategies/__init__.py +4 -0
  68. comfygit_core/strategies/auto.py +72 -0
  69. comfygit_core/strategies/confirmation.py +69 -0
  70. comfygit_core/utils/comfyui_ops.py +125 -0
  71. comfygit_core/utils/common.py +164 -0
  72. comfygit_core/utils/conflict_parser.py +232 -0
  73. comfygit_core/utils/dependency_parser.py +231 -0
  74. comfygit_core/utils/download.py +216 -0
  75. comfygit_core/utils/environment_cleanup.py +111 -0
  76. comfygit_core/utils/filesystem.py +178 -0
  77. comfygit_core/utils/git.py +1184 -0
  78. comfygit_core/utils/input_signature.py +145 -0
  79. comfygit_core/utils/model_categories.py +52 -0
  80. comfygit_core/utils/pytorch.py +71 -0
  81. comfygit_core/utils/requirements.py +211 -0
  82. comfygit_core/utils/retry.py +242 -0
  83. comfygit_core/utils/symlink_utils.py +119 -0
  84. comfygit_core/utils/system_detector.py +258 -0
  85. comfygit_core/utils/uuid.py +28 -0
  86. comfygit_core/utils/uv_error_handler.py +158 -0
  87. comfygit_core/utils/version.py +73 -0
  88. comfygit_core/utils/workflow_hash.py +90 -0
  89. comfygit_core/validation/resolution_tester.py +297 -0
  90. comfygit_core-0.2.0.dist-info/METADATA +939 -0
  91. comfygit_core-0.2.0.dist-info/RECORD +93 -0
  92. comfygit_core-0.2.0.dist-info/WHEEL +4 -0
  93. comfygit_core-0.2.0.dist-info/licenses/LICENSE.txt +661 -0
@@ -0,0 +1,939 @@
1
+ Metadata-Version: 2.4
2
+ Name: comfygit-core
3
+ Version: 0.2.0
4
+ Summary: ComfyGit Core - Git-based ComfyUI environment manager
5
+ License-File: LICENSE.txt
6
+ Requires-Python: >=3.10
7
+ Requires-Dist: aiohttp>=3.9.0
8
+ Requires-Dist: blake3>=1.0.5
9
+ Requires-Dist: packaging>=25.0
10
+ Requires-Dist: psutil>=7.0.0
11
+ Requires-Dist: pyyaml>=6.0
12
+ Requires-Dist: requests>=2.32.4
13
+ Requires-Dist: requirements-parser>=0.13.0
14
+ Requires-Dist: tomlkit>=0.13.3
15
+ Requires-Dist: uv>=0.9.9
16
+ Description-Content-Type: text/markdown
17
+
18
+ # ComfyDock Core
19
+
20
+ Core library for programmatic ComfyUI environment and package management. Build custom tools, GUIs, web interfaces, or CI/CD integrations on top of ComfyDock's architecture.
21
+
22
+ > **⚠️ MVP Status**: This library is under active development. APIs may change between versions. Pin your dependencies to specific versions in production.
23
+
24
+ ## What is ComfyDock Core?
25
+
26
+ ComfyDock Core is the **reusable library** that powers the `cfd` CLI and can power your own tools. It provides:
27
+
28
+ - **Workspace & Environment Management** - Create and manage isolated ComfyUI installations
29
+ - **Custom Node Management** - Install, update, remove nodes with conflict detection
30
+ - **Workflow Tracking** - Track workflows and resolve missing dependencies
31
+ - **Model Management** - Content-addressable model index with automatic resolution
32
+ - **Version Control** - Git-based commit/rollback for environment snapshots
33
+ - **Export/Import** - Package and share complete working environments
34
+ - **Strategy Pattern** - Plug in your own UI logic via callbacks
35
+
36
+ This is a **library, not a CLI**. No `print()` or `input()` statements - all user interaction happens through callbacks you provide.
37
+
38
+ ## Installation
39
+
40
+ Published separately to PyPI as `comfydock-core`:
41
+
42
+ ```bash
43
+ # With pip
44
+ pip install comfydock-core
45
+
46
+ # With uv
47
+ uv add comfydock-core
48
+ ```
49
+
50
+ ## Quick Start
51
+
52
+ ### Basic Workspace and Environment Operations
53
+
54
+ ```python
55
+ from pathlib import Path
56
+ from comfydock_core.factories.workspace_factory import WorkspaceFactory
57
+
58
+ # Create a new workspace
59
+ workspace = WorkspaceFactory.create(Path.home() / "my-comfyui-workspace")
60
+
61
+ # Or find an existing workspace
62
+ workspace = WorkspaceFactory.find(Path.home() / "my-comfyui-workspace")
63
+
64
+ # Create an environment (downloads ComfyUI, sets up Python venv)
65
+ env = workspace.create_environment(
66
+ name="production",
67
+ python_version="3.11",
68
+ comfyui_version="master", # or specific commit hash
69
+ torch_backend="auto" # auto-detect GPU, or "cpu", "cu121", etc.
70
+ )
71
+
72
+ # List all environments
73
+ environments = workspace.list_environments()
74
+ for env in environments:
75
+ print(f"Environment: {env.name} at {env.path}")
76
+
77
+ # Get a specific environment
78
+ env = workspace.get_environment("production")
79
+
80
+ # Set active environment (for CLI convenience, optional for library usage)
81
+ workspace.set_active_environment("production")
82
+ active = workspace.get_active_environment()
83
+
84
+ # Delete an environment
85
+ workspace.delete_environment("production")
86
+ ```
87
+
88
+ **API Reference**: See `src/comfydock_core/core/workspace.py` for full `Workspace` API and `src/comfydock_core/factories/workspace_factory.py` for factory methods.
89
+
90
+ ### Node Management
91
+
92
+ ```python
93
+ # Add a node from ComfyUI registry
94
+ result = env.add_node("comfyui-akatz-nodes")
95
+
96
+ # Add a node from GitHub URL
97
+ result = env.add_node(
98
+ "https://github.com/ltdrdata/ComfyUI-Impact-Pack",
99
+ version="v5.0" # optional: specify branch, tag, or commit
100
+ )
101
+
102
+ # Track a development node (your own node under development)
103
+ result = env.add_node(
104
+ "/path/to/my-custom-node",
105
+ dev=True # marks as development node, preserved on removal
106
+ )
107
+
108
+ # List installed nodes
109
+ nodes = env.list_nodes()
110
+ for node in nodes:
111
+ print(f"{node.name}: {node.source} ({node.version})")
112
+
113
+ # Remove a node
114
+ result = env.remove_node("comfyui-manager")
115
+
116
+ # Update a node to latest version
117
+ update_result = env.update_node("comfyui-impact-pack")
118
+ if update_result.updated:
119
+ print(f"Updated from {update_result.old_version} to {update_result.new_version}")
120
+ ```
121
+
122
+ **Node Sources**: Nodes can come from:
123
+ - `registry` - ComfyUI official registry
124
+ - `git` - GitHub/GitLab repositories
125
+ - `development` - Local nodes under development
126
+
127
+ **API Reference**: See `src/comfydock_core/core/environment.py` for node methods and `src/comfydock_core/managers/node_manager.py` for implementation details.
128
+
129
+ ### Workflow Tracking and Resolution
130
+
131
+ ```python
132
+ from pathlib import Path
133
+
134
+ # Track a workflow (registers it for monitoring)
135
+ env.track_workflow(Path("my-workflow.json"))
136
+
137
+ # List tracked workflows
138
+ workflows = env.list_workflows()
139
+
140
+ # Resolve workflow dependencies (finds missing nodes and models)
141
+ result = env.resolve_workflow(
142
+ "my-workflow.json",
143
+ node_strategy=my_node_strategy, # custom strategy for ambiguous nodes
144
+ model_strategy=my_model_strategy, # custom strategy for missing models
145
+ install_nodes=True # automatically install missing nodes
146
+ )
147
+
148
+ # Check resolution results
149
+ if result.all_nodes_resolved:
150
+ print("All nodes available")
151
+ else:
152
+ print(f"Missing nodes: {result.unresolved_nodes}")
153
+
154
+ if result.all_models_found:
155
+ print("All models found")
156
+ else:
157
+ print(f"Missing models: {result.missing_models}")
158
+
159
+ # Untrack a workflow
160
+ env.untrack_workflow("my-workflow.json")
161
+ ```
162
+
163
+ **Workflow Resolution Process**:
164
+ 1. Parse workflow JSON for node types and model references
165
+ 2. Match node types to installed nodes or registry entries
166
+ 3. Match model references to indexed models by hash
167
+ 4. Return detailed status with resolution results
168
+
169
+ **API Reference**: See `src/comfydock_core/managers/workflow_manager.py` for workflow operations and `src/comfydock_core/models/workflow.py` for data structures.
170
+
171
+ ### Model Management
172
+
173
+ ```python
174
+ # Set global models directory (workspace-wide)
175
+ workspace.set_models_directory(Path.home() / "my-models")
176
+
177
+ # Sync model index (scan directory and update database)
178
+ workspace.sync_model_index()
179
+
180
+ # Find models by hash, filename, or path
181
+ models = workspace.find_model("juggernaut")
182
+ for model in models:
183
+ print(f"{model.filename}: {model.hash_quick}")
184
+
185
+ # Download a model from URL
186
+ download_result = workspace.download_model(
187
+ url="https://civitai.com/api/download/models/12345",
188
+ category="checkpoints", # auto-path to checkpoints/
189
+ filename="my-model.safetensors" # optional override
190
+ )
191
+
192
+ # Add download source to existing model (for sharing)
193
+ workspace.add_model_source(
194
+ model_hash="abc123...",
195
+ url="https://civitai.com/models/..."
196
+ )
197
+
198
+ # Models are symlinked into environments automatically
199
+ # No duplication - all environments share the workspace model index
200
+ ```
201
+
202
+ **Model Index**: Uses Blake3 quick hash (first/middle/last 15MB) for fast identification and full SHA256 hash for verification during export/import.
203
+
204
+ **API Reference**: See `src/comfydock_core/core/workspace.py` for model methods and `src/comfydock_core/repositories/model_repository.py` for database operations.
205
+
206
+ ### Version Control (Commit/Rollback)
207
+
208
+ ```python
209
+ # Commit current state (creates git snapshot in .cec/)
210
+ commit_result = env.commit(
211
+ message="Added Impact Pack and configured workflows"
212
+ )
213
+
214
+ # View commit history
215
+ commits = env.get_commit_history()
216
+ for commit in commits:
217
+ print(f"v{commit.version}: {commit.message} ({commit.timestamp})")
218
+
219
+ # Rollback to previous version
220
+ env.rollback(
221
+ target="v2", # version identifier, or None to discard uncommitted changes
222
+ force=False # if True, discard uncommitted changes without error
223
+ )
224
+
225
+ # Check for uncommitted changes
226
+ status = env.get_status()
227
+ if status.has_uncommitted_changes:
228
+ print("Uncommitted changes detected")
229
+ ```
230
+
231
+ **What Gets Committed**:
232
+ - `pyproject.toml` - Node metadata, model references, Python dependencies
233
+ - `uv.lock` - Locked Python dependency versions
234
+ - `.cec/workflows/` - Tracked workflow files
235
+
236
+ **What Doesn't Get Committed**:
237
+ - Node source code (tracked in metadata, downloaded on demand)
238
+ - Model files (too large, referenced by hash)
239
+ - `.venv/` - Python virtual environment (recreated from lock)
240
+
241
+ **API Reference**: See `src/comfydock_core/core/environment.py` for version control methods and `src/comfydock_core/managers/git_manager.py` for git operations.
242
+
243
+ ### Export and Import
244
+
245
+ ```python
246
+ from comfydock_core.models.protocols import ExportCallbacks, ImportCallbacks
247
+
248
+ # Export environment to tarball
249
+ class MyExportCallbacks(ExportCallbacks):
250
+ def on_progress(self, step: str, current: int, total: int):
251
+ print(f"{step}: {current}/{total}")
252
+
253
+ workspace.export_environment(
254
+ env_name="production",
255
+ output_path="production-env.tar.gz",
256
+ callbacks=MyExportCallbacks()
257
+ )
258
+
259
+ # Import environment from tarball
260
+ class MyImportCallbacks(ImportCallbacks):
261
+ def on_node_download_start(self, node_name: str):
262
+ print(f"Downloading node: {node_name}")
263
+
264
+ def on_model_download_progress(self, filename: str, progress: float):
265
+ print(f"Model {filename}: {progress*100:.1f}%")
266
+
267
+ workspace.import_environment(
268
+ source="production-env.tar.gz",
269
+ name="imported-production",
270
+ callbacks=MyImportCallbacks(),
271
+ torch_backend="auto"
272
+ )
273
+
274
+ # Import from git repository
275
+ workspace.import_environment(
276
+ source="https://github.com/user/my-comfyui-env.git",
277
+ name="team-env",
278
+ branch="main", # optional: branch, tag, or commit
279
+ callbacks=MyImportCallbacks()
280
+ )
281
+ ```
282
+
283
+ **Export Contents**:
284
+ - Environment configuration (pyproject.toml, uv.lock)
285
+ - Tracked workflows
286
+ - Development node source code
287
+ - Node metadata (registry IDs, git URLs + commits)
288
+ - Model download sources (CivitAI/HuggingFace URLs)
289
+
290
+ **Import Process**:
291
+ 1. Extract/clone environment configuration
292
+ 2. Download missing custom nodes
293
+ 3. Download missing models (if sources available)
294
+ 4. Create Python virtual environment
295
+ 5. Install dependencies from lock file
296
+
297
+ **API Reference**: See `src/comfydock_core/models/protocols.py` for callback protocols and `src/comfydock_core/managers/export_import_manager.py` for implementation.
298
+
299
+ ### Git Remote Operations
300
+
301
+ ```python
302
+ # Add a git remote (for environment sharing via git)
303
+ env.add_remote(name="origin", url="https://github.com/user/my-env.git")
304
+
305
+ # List remotes
306
+ remotes = env.list_remotes()
307
+
308
+ # Push to remote
309
+ env.push_to_remote(remote="origin", force=False)
310
+
311
+ # Pull from remote
312
+ env.pull_from_remote(remote="origin", force=False)
313
+
314
+ # Remove a remote
315
+ env.remove_remote(name="origin")
316
+ ```
317
+
318
+ **Remote Collaboration**: Each environment's `.cec/` directory is a git repository. You can push to GitHub/GitLab and others can import from the URL.
319
+
320
+ **API Reference**: See `src/comfydock_core/core/environment.py` for remote methods.
321
+
322
+ ### Python Dependency Management
323
+
324
+ ```python
325
+ # Add Python packages to environment
326
+ env.add_python_dependencies(["opencv-python>=4.5.0", "pillow"])
327
+
328
+ # Add from requirements.txt
329
+ env.add_python_dependencies_from_file(Path("requirements.txt"))
330
+
331
+ # Remove Python packages
332
+ env.remove_python_dependencies(["opencv-python"])
333
+
334
+ # List dependencies
335
+ deps = env.list_python_dependencies()
336
+ ```
337
+
338
+ **Dependency Isolation**: Each custom node gets its own dependency group in `pyproject.toml` to isolate conflicts.
339
+
340
+ **API Reference**: See `src/comfydock_core/core/environment.py` for Python dependency methods.
341
+
342
+ ## Strategy Pattern (Custom UI Integration)
343
+
344
+ ComfyDock Core uses the **strategy pattern** to allow custom frontends to provide their own UI logic. No hardcoded prompts or dialogs.
345
+
346
+ ### Node Resolution Strategy
347
+
348
+ When adding nodes with ambiguous names, provide a strategy to resolve:
349
+
350
+ ```python
351
+ from comfydock_core.models.protocols import NodeResolutionStrategy
352
+ from comfydock_core.models.shared import NodeInfo
353
+
354
+ class CLINodeStrategy(NodeResolutionStrategy):
355
+ """Interactive CLI node resolution."""
356
+
357
+ def resolve_ambiguous(
358
+ self,
359
+ node_identifier: str,
360
+ candidates: list[NodeInfo]
361
+ ) -> NodeInfo:
362
+ """User picks from multiple matches."""
363
+ print(f"Multiple nodes match '{node_identifier}':")
364
+ for i, node in enumerate(candidates, 1):
365
+ print(f" {i}. {node.name} ({node.source})")
366
+
367
+ choice = int(input("Select: ")) - 1
368
+ return candidates[choice]
369
+
370
+ def resolve_optional(
371
+ self,
372
+ node_identifier: str,
373
+ is_required: bool
374
+ ) -> bool:
375
+ """User decides whether to install optional node."""
376
+ if is_required:
377
+ return True
378
+
379
+ response = input(f"Install optional node '{node_identifier}'? (y/N): ")
380
+ return response.lower() == 'y'
381
+
382
+ # Use your strategy
383
+ env.add_node("comfyui", strategy=CLINodeStrategy())
384
+ ```
385
+
386
+ ### Model Resolution Strategy
387
+
388
+ When workflows reference missing models:
389
+
390
+ ```python
391
+ from comfydock_core.models.protocols import ModelResolutionStrategy
392
+ from comfydock_core.models.shared import ModelDetails
393
+
394
+ class CLIModelStrategy(ModelResolutionStrategy):
395
+ """Interactive CLI model resolution."""
396
+
397
+ def resolve_missing_model(
398
+ self,
399
+ model_reference: str,
400
+ candidates: list[ModelDetails]
401
+ ) -> ModelDetails | None:
402
+ """User picks from search results or skips."""
403
+ if not candidates:
404
+ print(f"No models found for '{model_reference}'")
405
+ return None
406
+
407
+ print(f"Found models for '{model_reference}':")
408
+ for i, model in enumerate(candidates, 1):
409
+ print(f" {i}. {model.filename} ({model.size_mb:.1f} MB)")
410
+ print(f" {len(candidates)+1}. Skip")
411
+
412
+ choice = int(input("Select: "))
413
+ if choice == len(candidates) + 1:
414
+ return None
415
+
416
+ return candidates[choice - 1]
417
+
418
+ # Use your strategy
419
+ env.resolve_workflow(
420
+ "my-workflow.json",
421
+ model_strategy=CLIModelStrategy()
422
+ )
423
+ ```
424
+
425
+ ### Confirmation Strategy
426
+
427
+ For destructive operations (node removal, rollback):
428
+
429
+ ```python
430
+ from comfydock_core.strategies.confirmation import ConfirmationStrategy
431
+
432
+ class CLIConfirmationStrategy(ConfirmationStrategy):
433
+ """Interactive CLI confirmations."""
434
+
435
+ def confirm_node_removal(self, node_name: str, is_dev: bool) -> bool:
436
+ """User confirms node removal."""
437
+ msg = f"Remove node '{node_name}'"
438
+ if is_dev:
439
+ msg += " (development node will be disabled, not deleted)"
440
+ response = input(f"{msg}? (y/N): ")
441
+ return response.lower() == 'y'
442
+
443
+ def confirm_rollback(self, target_version: str, has_uncommitted: bool) -> bool:
444
+ """User confirms rollback."""
445
+ msg = f"Rollback to {target_version}"
446
+ if has_uncommitted:
447
+ msg += " (uncommitted changes will be lost)"
448
+ response = input(f"{msg}? (y/N): ")
449
+ return response.lower() == 'y'
450
+ ```
451
+
452
+ ### Auto Strategies (Non-Interactive)
453
+
454
+ For automated/CI environments, use auto-confirm strategies:
455
+
456
+ ```python
457
+ from comfydock_core.strategies.auto import (
458
+ AutoConfirmStrategy,
459
+ AutoNodeStrategy,
460
+ AutoModelStrategy
461
+ )
462
+
463
+ # Auto-confirm all operations
464
+ env.remove_node("some-node", strategy=AutoConfirmStrategy())
465
+
466
+ # Auto-select first match
467
+ env.add_node("ambiguous", strategy=AutoNodeStrategy())
468
+
469
+ # Auto-skip missing models
470
+ result = env.resolve_workflow(
471
+ "workflow.json",
472
+ model_strategy=AutoModelStrategy()
473
+ )
474
+ ```
475
+
476
+ **Available Strategies**:
477
+ - `NodeResolutionStrategy` - Handle ambiguous node names
478
+ - `ModelResolutionStrategy` - Handle missing model resolution
479
+ - `ConfirmationStrategy` - Handle destructive operations
480
+ - `RollbackStrategy` - Handle rollback confirmations
481
+ - `ExportCallbacks` - Progress updates during export
482
+ - `ImportCallbacks` - Progress updates during import
483
+
484
+ **API Reference**: See `src/comfydock_core/models/protocols.py` for all strategy protocols and `src/comfydock_core/strategies/` for built-in implementations.
485
+
486
+ ## Architecture Overview
487
+
488
+ ComfyDock Core uses a **layered architecture** separating concerns:
489
+
490
+ ```
491
+ ┌─────────────────────────────────────────────────────────────┐
492
+ │ API Layer (Workspace, Environment) │
493
+ │ - High-level operations │
494
+ │ - Public API surface │
495
+ └─────────────────────────┬───────────────────────────────────┘
496
+
497
+ ┌─────────────────────────▼───────────────────────────────────┐
498
+ │ Management Layer (Managers) │
499
+ │ - NodeManager: Node installation/removal │
500
+ │ - WorkflowManager: Workflow tracking/resolution │
501
+ │ - ModelSymlinkManager: Model symlinking │
502
+ │ - GitManager: Git operations │
503
+ │ - PyprojectManager: pyproject.toml manipulation │
504
+ │ - UVProjectManager: UV command execution │
505
+ └─────────────────────────┬───────────────────────────────────┘
506
+
507
+ ┌─────────────────────────▼───────────────────────────────────┐
508
+ │ Service Layer (Services) │
509
+ │ - NodeLookupService: Find nodes across sources │
510
+ │ - ModelDownloader: Download models from URLs │
511
+ │ - RegistryDataManager: ComfyUI registry cache │
512
+ │ - ImportAnalyzer: Preview imports │
513
+ └─────────────────────────┬───────────────────────────────────┘
514
+
515
+ ┌─────────────────────────▼───────────────────────────────────┐
516
+ │ Repository Layer (Data Access) │
517
+ │ - ModelRepository: SQLite model index │
518
+ │ - WorkflowRepository: Workflow caching │
519
+ │ - NodeMappingsRepository: Node-to-package mappings │
520
+ │ - WorkspaceConfigRepository: Workspace configuration │
521
+ └─────────────────────────────────────────────────────────────┘
522
+ ```
523
+
524
+ ### Component Organization
525
+
526
+ **Core (`core/`)**
527
+ - `workspace.py` - Multi-environment coordinator
528
+ - `environment.py` - Single environment abstraction
529
+
530
+ **Managers (`managers/`)** - Orchestrate operations, maintain state
531
+ - Depend on services and repositories
532
+ - Handle complex workflows (install node → update pyproject → sync venv)
533
+
534
+ **Services (`services/`)** - Stateless business logic
535
+ - Pure functions or stateless classes
536
+ - Reusable across different managers
537
+
538
+ **Repositories (`repositories/`)** - Data persistence
539
+ - Database access (SQLite)
540
+ - File I/O (JSON, TOML)
541
+ - Caching
542
+
543
+ **Analyzers (`analyzers/`)** - Parse and extract information
544
+ - Workflow dependency parsing
545
+ - Custom node scanning
546
+ - Status analysis
547
+
548
+ **Resolvers (`resolvers/`)** - Determine actions
549
+ - Map workflow nodes to packages
550
+ - Find model download sources
551
+
552
+ **Models (`models/`)** - Data structures
553
+ - Type definitions
554
+ - Dataclasses
555
+ - Protocols (strategy interfaces)
556
+
557
+ **Factories (`factories/`)** - Object construction
558
+ - Handle complex initialization
559
+ - Dependency injection
560
+
561
+ **Strategies (`strategies/`)** - Pluggable behavior
562
+ - Auto-confirm strategies
563
+ - Interactive strategies (in frontend)
564
+
565
+ ## Use Cases
566
+
567
+ ### Use Case 1: Building a GUI
568
+
569
+ ```python
570
+ from PyQt6.QtWidgets import QProgressDialog
571
+ from comfydock_core.models.protocols import ImportCallbacks
572
+
573
+ class QtImportCallbacks(ImportCallbacks):
574
+ """Qt-based progress UI for imports."""
575
+
576
+ def __init__(self, parent):
577
+ self.dialog = QProgressDialog(
578
+ "Importing environment...",
579
+ "Cancel",
580
+ 0, 100,
581
+ parent
582
+ )
583
+ self.dialog.setWindowModality(Qt.WindowModal)
584
+
585
+ def on_node_download_start(self, node_name: str):
586
+ self.dialog.setLabelText(f"Downloading node: {node_name}")
587
+
588
+ def on_model_download_progress(self, filename: str, progress: float):
589
+ self.dialog.setValue(int(progress * 100))
590
+ self.dialog.setLabelText(f"Downloading model: {filename}")
591
+
592
+ def on_python_sync_start(self):
593
+ self.dialog.setLabelText("Installing Python dependencies...")
594
+
595
+ # Use in your Qt application
596
+ workspace.import_environment(
597
+ "shared-env.tar.gz",
598
+ callbacks=QtImportCallbacks(self.mainwindow)
599
+ )
600
+ ```
601
+
602
+ ### Use Case 2: CI/CD Pipeline
603
+
604
+ ```python
605
+ """Validate workflow compatibility in CI pipeline."""
606
+ import sys
607
+ from comfydock_core.factories.workspace_factory import WorkspaceFactory
608
+ from comfydock_core.strategies.auto import AutoModelStrategy, AutoNodeStrategy
609
+
610
+ # Create test workspace
611
+ workspace = WorkspaceFactory.create("/tmp/ci-test-workspace")
612
+ env = workspace.create_environment("ci-test")
613
+
614
+ # Import workflow to test
615
+ env.track_workflow("workflow-to-test.json")
616
+
617
+ # Resolve with auto strategies (non-interactive)
618
+ result = env.resolve_workflow(
619
+ "workflow-to-test.json",
620
+ node_strategy=AutoNodeStrategy(),
621
+ model_strategy=AutoModelStrategy(),
622
+ install_nodes=True
623
+ )
624
+
625
+ # Check results
626
+ if not result.all_nodes_resolved:
627
+ print(f"ERROR: Missing nodes: {result.unresolved_nodes}")
628
+ sys.exit(1)
629
+
630
+ if not result.all_models_found:
631
+ print(f"WARNING: Missing models: {result.missing_models}")
632
+ # Could fail here or continue depending on requirements
633
+
634
+ print("✓ Workflow validation passed")
635
+ ```
636
+
637
+ ### Use Case 3: Batch Environment Creation
638
+
639
+ ```python
640
+ """Create multiple environments from templates."""
641
+ from pathlib import Path
642
+
643
+ workspace = WorkspaceFactory.find()
644
+
645
+ # Define environment templates
646
+ templates = [
647
+ {"name": "video", "nodes": ["comfyui-animatediff", "comfyui-video-helper"]},
648
+ {"name": "upscale", "nodes": ["comfyui-ultimate-upscale"]},
649
+ {"name": "inpaint", "nodes": ["comfyui-inpaint-nodes"]},
650
+ ]
651
+
652
+ for template in templates:
653
+ print(f"Creating {template['name']} environment...")
654
+
655
+ env = workspace.create_environment(
656
+ name=template['name'],
657
+ python_version="3.11"
658
+ )
659
+
660
+ # Add nodes
661
+ for node_id in template['nodes']:
662
+ env.add_node(node_id)
663
+
664
+ # Commit initial setup
665
+ env.commit(f"Initial {template['name']} environment setup")
666
+
667
+ print(f"✓ {template['name']} environment ready")
668
+ ```
669
+
670
+ ### Use Case 4: Environment Replication Tool
671
+
672
+ ```python
673
+ """Clone production environment to staging."""
674
+ from pathlib import Path
675
+ import tempfile
676
+
677
+ workspace = WorkspaceFactory.find()
678
+
679
+ # Export production
680
+ with tempfile.TemporaryDirectory() as tmpdir:
681
+ export_path = Path(tmpdir) / "production-snapshot.tar.gz"
682
+ workspace.export_environment("production", export_path)
683
+
684
+ # Import as staging
685
+ workspace.import_environment(
686
+ export_path,
687
+ name="staging",
688
+ torch_backend="auto"
689
+ )
690
+
691
+ print("✓ Production cloned to staging")
692
+ ```
693
+
694
+ ## Error Handling
695
+
696
+ ComfyDock Core uses a custom exception hierarchy for precise error handling:
697
+
698
+ ```python
699
+ from comfydock_core.models.exceptions import (
700
+ ComfyDockError, # Base exception
701
+ CDWorkspaceError, # Workspace-related errors
702
+ CDEnvironmentError, # Environment-related errors
703
+ CDNodeConflictError, # Node installation conflicts
704
+ CDNodeNotFoundError, # Node not found
705
+ UVCommandError, # UV command failures
706
+ )
707
+
708
+ try:
709
+ env = workspace.create_environment("test")
710
+ except CDEnvironmentError as e:
711
+ print(f"Environment error: {e}")
712
+ # Handle environment-specific error
713
+ except CDWorkspaceError as e:
714
+ print(f"Workspace error: {e}")
715
+ # Handle workspace-specific error
716
+ except ComfyDockError as e:
717
+ print(f"ComfyDock error: {e}")
718
+ # Handle any ComfyDock error
719
+ ```
720
+
721
+ **Exception Hierarchy**:
722
+ ```
723
+ ComfyDockError
724
+ ├── CDWorkspaceError
725
+ │ ├── CDWorkspaceNotFoundError
726
+ │ └── CDWorkspaceExistsError
727
+ ├── CDEnvironmentError
728
+ │ ├── CDEnvironmentNotFoundError
729
+ │ ├── CDEnvironmentExistsError
730
+ │ └── CDNodeConflictError
731
+ ├── CDNodeError
732
+ │ ├── CDNodeNotFoundError
733
+ │ └── CDNodeInstallError
734
+ └── UVCommandError
735
+ ```
736
+
737
+ **API Reference**: See `src/comfydock_core/models/exceptions.py` for all exception types.
738
+
739
+ ## Data Structures
740
+
741
+ Key data structures used throughout the API:
742
+
743
+ ### NodeInfo
744
+ ```python
745
+ from comfydock_core.models.shared import NodeInfo
746
+
747
+ # Returned by list_nodes(), node lookup, etc.
748
+ node = NodeInfo(
749
+ name="comfyui-manager",
750
+ identifier="comfyui-manager",
751
+ source="registry", # or "git", "development"
752
+ version="1.0.0",
753
+ url="https://github.com/...",
754
+ installed=True
755
+ )
756
+ ```
757
+
758
+ ### EnvironmentStatus
759
+ ```python
760
+ from comfydock_core.models.environment import EnvironmentStatus
761
+
762
+ # Returned by env.get_status()
763
+ status = EnvironmentStatus(
764
+ has_uncommitted_changes=True,
765
+ python_version="3.11.5",
766
+ comfyui_version="abc123",
767
+ installed_nodes=["comfyui-manager"],
768
+ tracked_workflows=["workflow.json"],
769
+ sync_issues=[] # list of issues if any
770
+ )
771
+ ```
772
+
773
+ ### ResolutionResult
774
+ ```python
775
+ from comfydock_core.models.workflow import ResolutionResult
776
+
777
+ # Returned by env.resolve_workflow()
778
+ result = ResolutionResult(
779
+ all_nodes_resolved=True,
780
+ all_models_found=False,
781
+ unresolved_nodes=[],
782
+ missing_models=["model.safetensors"],
783
+ resolved_nodes=["node1", "node2"],
784
+ found_models=["other-model.safetensors"]
785
+ )
786
+ ```
787
+
788
+ **API Reference**: See `src/comfydock_core/models/` for all data structures.
789
+
790
+ ## Design Principles
791
+
792
+ ComfyDock Core follows these principles for library design:
793
+
794
+ 1. **No UI Coupling**: Zero `print()` or `input()` statements. All user interaction through callbacks.
795
+
796
+ 2. **Stateless Services**: Services are pure functions or stateless classes. State lives in Managers and Core objects.
797
+
798
+ 3. **Strategy Pattern**: Pluggable behavior via protocol interfaces. Frontends provide their own strategies.
799
+
800
+ 4. **Dependency Injection**: Factories handle complex object construction. No singletons.
801
+
802
+ 5. **Layered Architecture**: Clear separation between API, Management, Service, and Repository layers.
803
+
804
+ 6. **Type Safety**: Full type hints. Use protocols for interfaces, dataclasses for data.
805
+
806
+ 7. **Error Transparency**: Custom exception hierarchy. No silent failures.
807
+
808
+ 8. **Content-Addressable**: Models identified by hash, not path. Enables flexible remapping.
809
+
810
+ ## Development
811
+
812
+ ### Running Tests
813
+
814
+ ```bash
815
+ # All tests
816
+ uv run pytest tests/
817
+
818
+ # Integration tests only
819
+ uv run pytest tests/integration/
820
+
821
+ # Unit tests only
822
+ uv run pytest tests/unit/
823
+
824
+ # Specific test file
825
+ uv run pytest tests/integration/test_environment_basic.py
826
+
827
+ # With coverage
828
+ uv run pytest --cov=comfydock_core tests/
829
+
830
+ # Verbose output
831
+ uv run pytest tests/ -v
832
+ ```
833
+
834
+ ### Project Structure
835
+
836
+ ```
837
+ comfydock-core/
838
+ ├── src/comfydock_core/
839
+ │ ├── core/ # Workspace & Environment
840
+ │ ├── managers/ # Orchestration layer
841
+ │ ├── services/ # Business logic
842
+ │ ├── repositories/ # Data access
843
+ │ ├── analyzers/ # Parsing & extraction
844
+ │ ├── resolvers/ # Action determination
845
+ │ ├── models/ # Data structures
846
+ │ ├── factories/ # Object construction
847
+ │ ├── strategies/ # Built-in strategies
848
+ │ ├── clients/ # External API clients
849
+ │ ├── utils/ # Utilities
850
+ │ ├── caching/ # Caching layer
851
+ │ ├── configs/ # Static configuration
852
+ │ ├── infrastructure/ # SQLite, etc.
853
+ │ ├── validation/ # Testing utilities
854
+ │ └── logging/ # Logging setup
855
+ ├── tests/
856
+ │ ├── integration/ # Integration tests
857
+ │ ├── unit/ # Unit tests
858
+ │ └── conftest.py # Pytest fixtures
859
+ ├── docs/
860
+ │ ├── codebase-map.md # Architecture details
861
+ │ ├── prd.md # Product requirements
862
+ │ └── layer-hierarchy.md # Layer dependencies
863
+ └── pyproject.toml # Package metadata
864
+ ```
865
+
866
+ ### Contributing
867
+
868
+ This is an MVP project maintained by a single developer. APIs may change between versions.
869
+
870
+ - **Issues**: [GitHub Issues](https://github.com/ComfyDock/comfydock/issues)
871
+ - **Discussions**: [GitHub Discussions](https://github.com/ComfyDock/comfydock/discussions)
872
+ - **Pull Requests**: Welcome, but discuss major changes first
873
+
874
+ ## API Documentation
875
+
876
+ For detailed API documentation:
877
+ - **Full API Docs**: [www.comfydock.com/api](https://www.comfydock.com/api) (coming soon)
878
+ - **Architecture Details**: See `docs/codebase-map.md` in this repository
879
+ - **Source Code**: All source is in `src/comfydock_core/` with inline documentation
880
+
881
+ ## Comparison to CLI
882
+
883
+ The CLI (`comfydock-cli` package) is built on top of this core library:
884
+
885
+ | Core Library | CLI Package |
886
+ |--------------|-------------|
887
+ | Programmatic Python API | Command-line interface |
888
+ | Strategy callbacks for UI | Interactive terminal UI |
889
+ | No user interaction | Prompts, progress bars, formatting |
890
+ | `workspace.create_environment()` | `cfd create <name>` |
891
+ | `env.add_node()` | `cfd node add <id>` |
892
+ | Returns data structures | Prints formatted output |
893
+
894
+ **Use the core library when:**
895
+ - Building a custom GUI (Qt, Electron, web UI)
896
+ - CI/CD automation
897
+ - Scripting bulk operations
898
+ - Integrating into larger tools
899
+
900
+ **Use the CLI when:**
901
+ - Interactive terminal usage
902
+ - Quick manual operations
903
+ - You want the pre-built UX
904
+
905
+ ## License
906
+
907
+ ComfyDock Core is **dual-licensed**:
908
+
909
+ - **AGPL-3.0** for open-source use (free forever)
910
+ - **Commercial licenses** available for businesses requiring proprietary use
911
+
912
+ **For open-source projects:** Use freely under AGPL-3.0. Modifications must be open-sourced.
913
+
914
+ **For businesses:** Contact us for commercial licensing if you need to:
915
+ - Build proprietary applications without open-sourcing modifications
916
+ - Offer SaaS without disclosing source code
917
+ - Integrate into closed-source products
918
+
919
+ See [LICENSE.txt](../../LICENSE.txt) for the full AGPL-3.0 license text.
920
+
921
+ ## Version & Stability
922
+
923
+ **Current Version**: 1.0.0
924
+
925
+ **Stability**: MVP - APIs may change between versions. Pin your dependencies:
926
+
927
+ ```toml
928
+ # pyproject.toml
929
+ dependencies = [
930
+ "comfydock-core>=1.0.0,<1.1.0" # Pin to minor version
931
+ ]
932
+ ```
933
+
934
+ **Semantic Versioning**:
935
+ - Major (X.0.0): Breaking API changes
936
+ - Minor (0.X.0): New features, backward compatible
937
+ - Patch (0.0.X): Bug fixes, backward compatible
938
+
939
+ We will stabilize APIs as we approach 2.0.0 release.