horde-engine 3.3.2__tar.gz → 3.4.0__tar.gz

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 (239) hide show
  1. {horde_engine-3.3.2 → horde_engine-3.4.0}/PKG-INFO +1 -1
  2. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/_version.py +2 -2
  3. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/comfy_horde.py +10 -0
  4. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/model_manager/civitai_adhoc.py +139 -4
  5. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/model_manager/lora.py +13 -0
  6. {horde_engine-3.3.2 → horde_engine-3.4.0}/.gitignore +0 -0
  7. {horde_engine-3.3.2 → horde_engine-3.4.0}/LICENSE +0 -0
  8. {horde_engine-3.3.2 → horde_engine-3.4.0}/README.md +0 -0
  9. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/__init__.py +0 -0
  10. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/__pyinstaller.py +0 -0
  11. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/api.py +0 -0
  12. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/benchmark.py +0 -0
  13. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/beta_models.py +0 -0
  14. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/config_path.py +0 -0
  15. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/consts.py +0 -0
  16. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/exceptions.py +0 -0
  17. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/execution/__init__.py +0 -0
  18. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/execution/comfy_patches.py +0 -0
  19. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/execution/graph_utils.py +0 -0
  20. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/execution/in_process.py +0 -0
  21. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/execution/interface.py +0 -0
  22. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/execution/phase_timing.py +0 -0
  23. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/execution/progress_hook.py +0 -0
  24. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/execution/sampling_lease.py +0 -0
  25. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/feature_impact.py +0 -0
  26. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/feature_requirements.py +0 -0
  27. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/horde.py +0 -0
  28. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/initialisation.py +0 -0
  29. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/installation/__init__.py +0 -0
  30. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/installation/__main__.py +0 -0
  31. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/installation/installer.py +0 -0
  32. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/installation/manifest.json +0 -0
  33. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/installation/manifest.py +0 -0
  34. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/integrations/__init__.py +0 -0
  35. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/integrations/logfire_comfy_internals.py +0 -0
  36. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/integrations/logfire_setup.py +0 -0
  37. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/metrics.py +0 -0
  38. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/model_database/db_dep.json +0 -0
  39. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/model_database/db_embeds.json +0 -0
  40. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/model_database/diffusers.json +0 -0
  41. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/model_database/med_config.json +0 -0
  42. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/model_manager/__init__.py +0 -0
  43. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/model_manager/base.py +0 -0
  44. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/model_manager/civitai_provider.py +0 -0
  45. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/model_manager/civitai_records.py +0 -0
  46. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/model_manager/codeformer.py +0 -0
  47. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/model_manager/compvis.py +0 -0
  48. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/model_manager/controlnet.py +0 -0
  49. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/model_manager/diffusers.py +0 -0
  50. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/model_manager/esrgan.py +0 -0
  51. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/model_manager/gfpgan.py +0 -0
  52. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/model_manager/hyper.py +0 -0
  53. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/model_manager/miscellaneous.py +0 -0
  54. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/model_manager/safety_checker.py +0 -0
  55. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/model_manager/ti.py +0 -0
  56. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/__init__.py +0 -0
  57. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/comfyui_layerdiffuse/LICENSE +0 -0
  58. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/comfyui_layerdiffuse/README.md +0 -0
  59. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/comfyui_layerdiffuse/__init__.py +0 -0
  60. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/comfyui_layerdiffuse/examples/layer_diffusion_cond_example.json +0 -0
  61. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/comfyui_layerdiffuse/examples/layer_diffusion_cond_fg_all.json +0 -0
  62. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/comfyui_layerdiffuse/examples/layer_diffusion_cond_joint_bg.json +0 -0
  63. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/comfyui_layerdiffuse/examples/layer_diffusion_cond_joint_fg.json +0 -0
  64. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/comfyui_layerdiffuse/examples/layer_diffusion_diff_bg.json +0 -0
  65. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/comfyui_layerdiffuse/examples/layer_diffusion_diff_bg_stop_at.json +0 -0
  66. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/comfyui_layerdiffuse/examples/layer_diffusion_diff_fg.json +0 -0
  67. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/comfyui_layerdiffuse/examples/layer_diffusion_fg_example.json +0 -0
  68. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/comfyui_layerdiffuse/examples/layer_diffusion_fg_example_rgba.json +0 -0
  69. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/comfyui_layerdiffuse/examples/layer_diffusion_joint.json +0 -0
  70. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/comfyui_layerdiffuse/layered_diffusion.py +0 -0
  71. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/comfyui_layerdiffuse/lib_layerdiffusion/__init__.py +0 -0
  72. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/comfyui_layerdiffuse/lib_layerdiffusion/attention_sharing.py +0 -0
  73. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/comfyui_layerdiffuse/lib_layerdiffusion/enums.py +0 -0
  74. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/comfyui_layerdiffuse/lib_layerdiffusion/models.py +0 -0
  75. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/comfyui_layerdiffuse/lib_layerdiffusion/utils.py +0 -0
  76. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/comfyui_layerdiffuse/pyproject.toml +0 -0
  77. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/comfyui_layerdiffuse/requirements.txt +0 -0
  78. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/facerestore_cf/LICENSE +0 -0
  79. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/facerestore_cf/README.md +0 -0
  80. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/facerestore_cf/__init__.py +0 -0
  81. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/facerestore_cf/basicsr/VERSION +0 -0
  82. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/facerestore_cf/basicsr/__init__.py +0 -0
  83. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/facerestore_cf/basicsr/archs/__init__.py +0 -0
  84. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/facerestore_cf/basicsr/archs/arcface_arch.py +0 -0
  85. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/facerestore_cf/basicsr/archs/arch_util.py +0 -0
  86. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/facerestore_cf/basicsr/archs/codeformer_arch.py +0 -0
  87. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/facerestore_cf/basicsr/archs/rrdbnet_arch.py +0 -0
  88. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/facerestore_cf/basicsr/archs/vgg_arch.py +0 -0
  89. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/facerestore_cf/basicsr/archs/vqgan_arch.py +0 -0
  90. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/facerestore_cf/basicsr/data/__init__.py +0 -0
  91. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/facerestore_cf/basicsr/data/data_sampler.py +0 -0
  92. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/facerestore_cf/basicsr/data/data_util.py +0 -0
  93. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/facerestore_cf/basicsr/data/prefetch_dataloader.py +0 -0
  94. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/facerestore_cf/basicsr/data/transforms.py +0 -0
  95. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/facerestore_cf/basicsr/losses/__init__.py +0 -0
  96. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/facerestore_cf/basicsr/losses/loss_util.py +0 -0
  97. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/facerestore_cf/basicsr/losses/losses.py +0 -0
  98. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/facerestore_cf/basicsr/metrics/__init__.py +0 -0
  99. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/facerestore_cf/basicsr/metrics/metric_util.py +0 -0
  100. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/facerestore_cf/basicsr/metrics/psnr_ssim.py +0 -0
  101. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/facerestore_cf/basicsr/models/__init__.py +0 -0
  102. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/facerestore_cf/basicsr/ops/__init__.py +0 -0
  103. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/facerestore_cf/basicsr/ops/dcn/__init__.py +0 -0
  104. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/facerestore_cf/basicsr/ops/dcn/deform_conv.py +0 -0
  105. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/facerestore_cf/basicsr/ops/dcn/src/deform_conv_cuda.cpp +0 -0
  106. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/facerestore_cf/basicsr/ops/dcn/src/deform_conv_cuda_kernel.cu +0 -0
  107. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/facerestore_cf/basicsr/ops/dcn/src/deform_conv_ext.cpp +0 -0
  108. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/facerestore_cf/basicsr/ops/fused_act/__init__.py +0 -0
  109. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/facerestore_cf/basicsr/ops/fused_act/fused_act.py +0 -0
  110. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/facerestore_cf/basicsr/ops/fused_act/src/fused_bias_act.cpp +0 -0
  111. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/facerestore_cf/basicsr/ops/fused_act/src/fused_bias_act_kernel.cu +0 -0
  112. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/facerestore_cf/basicsr/ops/upfirdn2d/__init__.py +0 -0
  113. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/facerestore_cf/basicsr/ops/upfirdn2d/src/upfirdn2d.cpp +0 -0
  114. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/facerestore_cf/basicsr/ops/upfirdn2d/src/upfirdn2d_kernel.cu +0 -0
  115. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/facerestore_cf/basicsr/ops/upfirdn2d/upfirdn2d.py +0 -0
  116. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/facerestore_cf/basicsr/setup.py +0 -0
  117. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/facerestore_cf/basicsr/train.py +0 -0
  118. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/facerestore_cf/basicsr/utils/__init__.py +0 -0
  119. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/facerestore_cf/basicsr/utils/dist_util.py +0 -0
  120. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/facerestore_cf/basicsr/utils/download_util.py +0 -0
  121. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/facerestore_cf/basicsr/utils/file_client.py +0 -0
  122. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/facerestore_cf/basicsr/utils/img_util.py +0 -0
  123. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/facerestore_cf/basicsr/utils/lmdb_util.py +0 -0
  124. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/facerestore_cf/basicsr/utils/logger.py +0 -0
  125. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/facerestore_cf/basicsr/utils/matlab_functions.py +0 -0
  126. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/facerestore_cf/basicsr/utils/misc.py +0 -0
  127. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/facerestore_cf/basicsr/utils/options.py +0 -0
  128. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/facerestore_cf/basicsr/utils/realesrgan_utils.py +0 -0
  129. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/facerestore_cf/basicsr/utils/registry.py +0 -0
  130. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/facerestore_cf/basicsr/version.py +0 -0
  131. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/facerestore_cf/facelib/__init__.py +0 -0
  132. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/facerestore_cf/facelib/detection/__init__.py +0 -0
  133. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/facerestore_cf/facelib/detection/align_trans.py +0 -0
  134. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/facerestore_cf/facelib/detection/matlab_cp2tform.py +0 -0
  135. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/facerestore_cf/facelib/detection/retinaface/retinaface.py +0 -0
  136. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/facerestore_cf/facelib/detection/retinaface/retinaface_net.py +0 -0
  137. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/facerestore_cf/facelib/detection/retinaface/retinaface_utils.py +0 -0
  138. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/facerestore_cf/facelib/detection/yolov5face/__init__.py +0 -0
  139. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/facerestore_cf/facelib/detection/yolov5face/face_detector.py +0 -0
  140. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/facerestore_cf/facelib/detection/yolov5face/models/__init__.py +0 -0
  141. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/facerestore_cf/facelib/detection/yolov5face/models/common.py +0 -0
  142. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/facerestore_cf/facelib/detection/yolov5face/models/experimental.py +0 -0
  143. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/facerestore_cf/facelib/detection/yolov5face/models/yolo.py +0 -0
  144. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/facerestore_cf/facelib/detection/yolov5face/models/yolov5l.yaml +0 -0
  145. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/facerestore_cf/facelib/detection/yolov5face/models/yolov5n.yaml +0 -0
  146. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/facerestore_cf/facelib/detection/yolov5face/utils/__init__.py +0 -0
  147. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/facerestore_cf/facelib/detection/yolov5face/utils/autoanchor.py +0 -0
  148. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/facerestore_cf/facelib/detection/yolov5face/utils/datasets.py +0 -0
  149. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/facerestore_cf/facelib/detection/yolov5face/utils/extract_ckpt.py +0 -0
  150. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/facerestore_cf/facelib/detection/yolov5face/utils/general.py +0 -0
  151. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/facerestore_cf/facelib/detection/yolov5face/utils/torch_utils.py +0 -0
  152. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/facerestore_cf/facelib/parsing/__init__.py +0 -0
  153. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/facerestore_cf/facelib/parsing/bisenet.py +0 -0
  154. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/facerestore_cf/facelib/parsing/parsenet.py +0 -0
  155. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/facerestore_cf/facelib/parsing/resnet.py +0 -0
  156. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/facerestore_cf/facelib/utils/__init__.py +0 -0
  157. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/facerestore_cf/facelib/utils/face_restoration_helper.py +0 -0
  158. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/facerestore_cf/facelib/utils/face_utils.py +0 -0
  159. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/facerestore_cf/facelib/utils/misc.py +0 -0
  160. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/facerestore_cf/r_chainner/README.md +0 -0
  161. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/facerestore_cf/r_chainner/__init__.py +0 -0
  162. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/facerestore_cf/r_chainner/gfpganv1_clean_arch.py +0 -0
  163. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/facerestore_cf/r_chainner/model_loading.py +0 -0
  164. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/facerestore_cf/r_chainner/stylegan2_clean_arch.py +0 -0
  165. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/facerestore_cf/r_chainner/types.py +0 -0
  166. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/node_controlnet_model_loader.py +0 -0
  167. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/node_image_loader.py +0 -0
  168. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/node_image_output.py +0 -0
  169. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/node_lora_loader.py +0 -0
  170. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/node_model_loader.py +0 -0
  171. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/nodes/node_upscale_model_loader.py +0 -0
  172. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/pipeline/__init__.py +0 -0
  173. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/pipeline/constants.py +0 -0
  174. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/pipeline/context.py +0 -0
  175. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/pipeline/families/__init__.py +0 -0
  176. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/pipeline/families/image.py +0 -0
  177. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/pipeline/families/post_processing.py +0 -0
  178. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/pipeline/graph.py +0 -0
  179. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/pipeline/horde_compat.py +0 -0
  180. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/pipeline/patches.py +0 -0
  181. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/pipeline/payload.py +0 -0
  182. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/pipeline/payload_pp.py +0 -0
  183. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/pipeline/registry.py +0 -0
  184. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/pipeline/resolution.py +0 -0
  185. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/pipeline/template.py +0 -0
  186. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/pipeline_designs/pipeline_controlnet.json +0 -0
  187. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/pipeline_designs/pipeline_controlnet_annotator.json +0 -0
  188. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/pipeline_designs/pipeline_controlnet_hires_fix.json +0 -0
  189. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/pipeline_designs/pipeline_flux.json +0 -0
  190. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/pipeline_designs/pipeline_image_facefix.json +0 -0
  191. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/pipeline_designs/pipeline_image_upscale.json +0 -0
  192. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/pipeline_designs/pipeline_qr_code.json +0 -0
  193. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/pipeline_designs/pipeline_qwen.json +0 -0
  194. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/pipeline_designs/pipeline_stable_cascade.json +0 -0
  195. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/pipeline_designs/pipeline_stable_cascade_2pass.json +0 -0
  196. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/pipeline_designs/pipeline_stable_cascade_remix.json +0 -0
  197. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/pipeline_designs/pipeline_stable_diffusion.json +0 -0
  198. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/pipeline_designs/pipeline_stable_diffusion_hires_fix.json +0 -0
  199. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/pipeline_designs/pipeline_stable_diffusion_img2img_mask.json +0 -0
  200. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/pipeline_designs/pipeline_stable_diffusion_paint.json +0 -0
  201. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/pipelines/pipeline_controlnet.json +0 -0
  202. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/pipelines/pipeline_controlnet_annotator.json +0 -0
  203. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/pipelines/pipeline_controlnet_hires_fix.json +0 -0
  204. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/pipelines/pipeline_flux.json +0 -0
  205. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/pipelines/pipeline_image_facefix.json +0 -0
  206. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/pipelines/pipeline_image_upscale.json +0 -0
  207. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/pipelines/pipeline_qr_code.json +0 -0
  208. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/pipelines/pipeline_qwen.json +0 -0
  209. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/pipelines/pipeline_stable_cascade.json +0 -0
  210. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/pipelines/pipeline_stable_cascade_2pass.json +0 -0
  211. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/pipelines/pipeline_stable_cascade_remix.json +0 -0
  212. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/pipelines/pipeline_stable_diffusion.json +0 -0
  213. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/pipelines/pipeline_stable_diffusion_hires_fix.json +0 -0
  214. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/pipelines/pipeline_stable_diffusion_img2img_mask.json +0 -0
  215. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/pipelines/pipeline_stable_diffusion_paint.json +0 -0
  216. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/preload.py +0 -0
  217. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/py.typed +0 -0
  218. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/pyinstaller_hooks/__init__.py +0 -0
  219. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/pyinstaller_hooks/hook-hordelib.horde.py +0 -0
  220. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/safety.py +0 -0
  221. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/safety_checker.py +0 -0
  222. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/settings.py +0 -0
  223. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/shared_model_manager.py +0 -0
  224. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/train.py +0 -0
  225. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/utils/__init__.py +0 -0
  226. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/utils/distance.py +0 -0
  227. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/utils/dynamicprompt.py +0 -0
  228. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/utils/gpuinfo.py +0 -0
  229. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/utils/image_utils.py +0 -0
  230. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/utils/ioredirect.py +0 -0
  231. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/utils/logger.py +0 -0
  232. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/utils/nvml.py +0 -0
  233. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/utils/optional_deps.py +0 -0
  234. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/utils/sanitizer.py +0 -0
  235. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/utils/switch.py +0 -0
  236. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/utils/torch_build.py +0 -0
  237. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/utils/torch_memory.py +0 -0
  238. {horde_engine-3.3.2 → horde_engine-3.4.0}/hordelib/vram_planning.py +0 -0
  239. {horde_engine-3.3.2 → horde_engine-3.4.0}/pyproject.toml +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: horde-engine
3
- Version: 3.3.2
3
+ Version: 3.4.0
4
4
  Summary: A wrapper around ComfyUI to allow use by AI Horde.
5
5
  Project-URL: Homepage, https://github.com/Haidra-Org/hordelib
6
6
  Project-URL: Bug Tracker, https://github.com/Haidra-Org/hordelib/issues
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
18
18
  commit_id: str | None
19
19
  __commit_id__: str | None
20
20
 
21
- __version__ = version = '3.3.2'
22
- __version_tuple__ = version_tuple = (3, 3, 2)
21
+ __version__ = version = '3.4.0'
22
+ __version_tuple__ = version_tuple = (3, 4, 0)
23
23
 
24
24
  __commit_id__ = commit_id = None
@@ -405,6 +405,10 @@ def pin_models_in_vram() -> bool:
405
405
  def unload_all_models_vram():
406
406
  global _comfy_current_loaded_models
407
407
 
408
+ from hordelib.metrics import get_metrics_collector
409
+
410
+ _unload_start = time.perf_counter()
411
+
408
412
  log_free_ram()
409
413
 
410
414
  from hordelib.shared_model_manager import SharedModelManager
@@ -448,6 +452,12 @@ def unload_all_models_vram():
448
452
  clear_gc_and_torch_cache()
449
453
  log_free_ram()
450
454
 
455
+ # Surface the VRAM-eviction cost to the in-process collector so an embedder can attribute the
456
+ # between-jobs reload churn (this is the "unload" half; the reload is already timed as
457
+ # disk_to_ram/ram_to_vram). Recorded under the job in progress when the unload happens, or the
458
+ # next job on this process when it is an idle eviction.
459
+ get_metrics_collector().record_phase("model_unload", time.perf_counter() - _unload_start)
460
+
451
461
 
452
462
  def unload_all_models_ram():
453
463
  global _comfy_current_loaded_models
@@ -18,11 +18,13 @@ is inherited. See :class:`~hordelib.model_manager.lora.LoraModelManager` and
18
18
 
19
19
  from __future__ import annotations
20
20
 
21
+ import errno
21
22
  import glob
22
23
  import hashlib
23
24
  import json
24
25
  import os
25
26
  import re
27
+ import shutil
26
28
  import threading
27
29
  import time
28
30
  import uuid
@@ -51,9 +53,27 @@ TESTS_ONGOING = os.getenv("TESTS_ONGOING", "0") == "1"
51
53
  TIMESTAMP_FORMAT = "%Y-%m-%d %H:%M:%S"
52
54
  """The strftime/strptime format used for all cache timestamps persisted to disk."""
53
55
 
56
+ _TERMINAL_DISK_ERRNOS: frozenset[int] = frozenset(
57
+ e for e in (getattr(errno, name, None) for name in ("ENOSPC", "EDQUOT", "EROFS", "EFBIG")) if e is not None
58
+ )
59
+ """Disk-write failures that retrying cannot fix: full disk, exceeded quota, read-only FS, file too large.
60
+
61
+ Such a write fails identically on every attempt, yet each retry first re-downloads the entire (often
62
+ hundreds-of-MB) weight file, and the worker thread holds the record for the whole retry budget. The
63
+ ad-hoc downloader treats these as terminal so the queue drains promptly instead of thrashing.
64
+ """
65
+
54
66
  A1111_TRIGGER_PATTERN = re.compile(r"<(?:lora|ti):(.*):.*>")
55
67
  """Matches A1111-style inline trigger syntax so it can be reduced to the bare trigger word."""
56
68
 
69
+ DEFAULT_MIN_FREE_DISK_MB = 1024
70
+ """Keep at least this many MB free on the cache volume; ad-hoc downloads evict (then refuse) below it.
71
+
72
+ A full cache disk turns every weight write into an ENOSPC failure (and can take the whole host's
73
+ working volume down with it). Treating a low-free-space floor as a hard constraint on ad-hoc growth
74
+ keeps the cache self-limiting even if the configured byte budget is mis-set or the volume is shared.
75
+ """
76
+
57
77
 
58
78
  def now_timestamp() -> str:
59
79
  """Return the current local time formatted with :data:`TIMESTAMP_FORMAT`."""
@@ -181,6 +201,7 @@ class CivitaiAdhocModelManager[RecordT: GenericModelRecord](
181
201
  reference_backups: bool | None = None,
182
202
  max_top_disk: int,
183
203
  max_adhoc_disk: int,
204
+ min_free_disk_mb: int = DEFAULT_MIN_FREE_DISK_MB,
184
205
  ) -> None:
185
206
  """Create an ad-hoc CivitAI model manager.
186
207
 
@@ -195,9 +216,12 @@ class CivitaiAdhocModelManager[RecordT: GenericModelRecord](
195
216
  backups follow whether a multiprocessing lock was supplied.
196
217
  max_top_disk: The default-set cache budget, in megabytes.
197
218
  max_adhoc_disk: The ad-hoc cache budget, in megabytes.
219
+ min_free_disk_mb: Keep at least this much free space (in megabytes) on the cache volume;
220
+ ad-hoc downloads evict to make room and refuse rather than cross the floor.
198
221
  """
199
222
  self._max_top_disk = max_top_disk
200
223
  self.max_adhoc_disk = max_adhoc_disk
224
+ self.min_free_disk_mb = max(0, min_free_disk_mb)
201
225
 
202
226
  self._data: dict | None = None
203
227
  self._next_page_url: str | None = None
@@ -503,6 +527,28 @@ class CivitaiAdhocModelManager[RecordT: GenericModelRecord](
503
527
  self.save_reference_to_disk()
504
528
  return
505
529
 
530
+ # Refuse to fetch a fresh weight when the volume can't hold it above the floor, even
531
+ # after evicting every ad-hoc entry. Writing anyway risks an ENOSPC that takes the
532
+ # whole cache (and any co-located worker data) down; skipping leaves the worker able to
533
+ # serve the job without this LoRA. Defaults are never evicted, so an over-full default
534
+ # set legitimately yields "no room" here.
535
+ if not self._ensure_room_for_download(target):
536
+ download_logger.warning(
537
+ "adhoc.download_skipped_disk_full",
538
+ filename=target.filename,
539
+ size_mb=target.size_mb,
540
+ free_mb=round(self.disk_free_mb() or -1.0),
541
+ floor_mb=self.min_free_disk_mb,
542
+ )
543
+ self._record_download_event(
544
+ record,
545
+ success=False,
546
+ size_bytes=0,
547
+ duration_seconds=time.perf_counter() - overall_start,
548
+ retries=retries,
549
+ )
550
+ return
551
+
506
552
  download_start = time.perf_counter()
507
553
  download_url = target.url
508
554
  if self._civitai_api_token and self.is_model_url_from_civitai(download_url):
@@ -578,6 +624,25 @@ class CivitaiAdhocModelManager[RecordT: GenericModelRecord](
578
624
  retries=retries,
579
625
  )
580
626
  return
627
+ except OSError as disk_error:
628
+ if disk_error.errno in _TERMINAL_DISK_ERRNOS:
629
+ # A full / read-only / over-quota disk will not heal between attempts, so retrying only
630
+ # re-downloads the whole weight file to fail the write again while pinning this worker
631
+ # thread (and thus the callers blocked in wait_for_downloads/reset_adhoc_cache). Record
632
+ # the terminal failure and move on; the caller proceeds without this model.
633
+ download_logger.error("adhoc.download_disk_error", errno=disk_error.errno, error=str(disk_error))
634
+ self._metric_network_errors.add(1, {"error_type": "disk"})
635
+ self._record_download_event(
636
+ record,
637
+ success=False,
638
+ size_bytes=0,
639
+ duration_seconds=time.perf_counter() - overall_start,
640
+ retries=retries,
641
+ )
642
+ return
643
+ # Any other OS error may be transient; fall through to the shared retry path below.
644
+ self._metric_network_errors.add(1, {"error_type": "fatal"})
645
+ download_logger.error("adhoc.download_fatal_error", error=str(disk_error))
581
646
  except Exception as fatal_error:
582
647
  self._metric_network_errors.add(1, {"error_type": "fatal"})
583
648
  download_logger.error("adhoc.download_fatal_error", error=str(fatal_error))
@@ -617,6 +682,10 @@ class CivitaiAdhocModelManager[RecordT: GenericModelRecord](
617
682
  def wait_for_downloads(self, timeout: float | None = None) -> None:
618
683
  """Block until the download queue drains and all workers are idle.
619
684
 
685
+ ``timeout`` is the budget in seconds: ``None`` waits forever, and any number (including ``0``) is
686
+ honoured. Using a truthiness test here instead would silently turn ``timeout=0`` into "wait
687
+ forever", so a caller that asked for a bounded drain could hang on a wedged background download.
688
+
620
689
  Raises:
621
690
  TimeoutError: If *timeout* seconds elapse before downloads complete.
622
691
  """
@@ -624,7 +693,7 @@ class CivitaiAdhocModelManager[RecordT: GenericModelRecord](
624
693
  while not self.are_downloads_complete():
625
694
  time.sleep(self.THREAD_WAIT_TIME)
626
695
  waited += self.THREAD_WAIT_TIME
627
- if timeout and waited > timeout:
696
+ if timeout is not None and waited > timeout:
628
697
  raise TimeoutError(f"{self.METRIC_PREFIX} downloads exceeded specified timeout ({timeout})")
629
698
 
630
699
  def are_downloads_complete(self) -> bool:
@@ -692,17 +761,17 @@ class CivitaiAdhocModelManager[RecordT: GenericModelRecord](
692
761
 
693
762
  def is_default_cache_full(self) -> bool:
694
763
  """Return whether the default cache has reached its budget."""
695
- return self.calculate_default_cache() >= self._max_top_disk * 1024
764
+ return self.calculate_default_cache() >= self._max_top_disk
696
765
 
697
766
  def is_adhoc_cache_full(self) -> bool:
698
767
  """Return whether the ad-hoc cache has reached its budget."""
699
- return self.calculate_adhoc_cache() >= self.max_adhoc_disk * 1024
768
+ return self.calculate_adhoc_cache() >= self.max_adhoc_disk
700
769
 
701
770
  def amount_of_adhoc_to_delete(self) -> int:
702
771
  """Return how many ad-hoc entries to evict: one, plus one more per 4GB over budget."""
703
772
  if not self.is_adhoc_cache_full():
704
773
  return 0
705
- return 1 + int((self.calculate_adhoc_cache() - self.max_adhoc_disk * 1024) / 4096)
774
+ return 1 + int((self.calculate_adhoc_cache() - self.max_adhoc_disk) / 4096)
706
775
 
707
776
  def find_oldest_adhoc_entry(self) -> CacheEntry | None:
708
777
  """Return the least-recently-used ad-hoc cache entry, or ``None`` if there are none."""
@@ -726,6 +795,72 @@ class CivitaiAdhocModelManager[RecordT: GenericModelRecord](
726
795
  for _eviction in range(self.amount_of_adhoc_to_delete()):
727
796
  self.delete_oldest()
728
797
 
798
+ def enforce_adhoc_budget(self) -> None:
799
+ """Evict ad-hoc entries back within :attr:`max_adhoc_disk` and persist, if over budget.
800
+
801
+ The public entry point for callers (e.g. the worker) that have just lowered
802
+ ``max_adhoc_disk`` to constrain the cache and want the eviction applied immediately.
803
+ """
804
+ if self.is_adhoc_cache_full():
805
+ self._evict_adhoc_over_limit()
806
+ self.save_reference_to_disk()
807
+
808
+ # ------------------------------------------------------------------
809
+ # Disk-space safety floor
810
+ # ------------------------------------------------------------------
811
+
812
+ def disk_free_mb(self) -> float | None:
813
+ """Return free space (in megabytes) on the cache volume, or ``None`` if it can't be read."""
814
+ try:
815
+ return shutil.disk_usage(self.model_folder_path).free / (1024 * 1024)
816
+ except OSError as usage_error:
817
+ logger.bind(manager=self.METRIC_PREFIX).warning("adhoc.disk_usage_failed", error=str(usage_error))
818
+ return None
819
+
820
+ def is_disk_below_floor(self) -> bool:
821
+ """Return whether free space on the cache volume is below :attr:`min_free_disk_mb`."""
822
+ free = self.disk_free_mb()
823
+ return free is not None and free < self.min_free_disk_mb
824
+
825
+ def evict_adhoc_for_free_space(self, *, required_mb: float = 0.0) -> bool:
826
+ """Evict oldest ad-hoc entries until the volume has room for the floor plus *required_mb*.
827
+
828
+ Re-samples free space after each deletion (only the OS knows the true effect of a delete on a
829
+ shared volume). Persists once if anything was evicted.
830
+
831
+ Returns:
832
+ ``True`` once free space meets the target (or the volume can't be sampled), ``False`` if
833
+ the ad-hoc entries are exhausted and the target still isn't met (an "unsolvable" disk).
834
+ """
835
+ target_mb = self.min_free_disk_mb + max(required_mb, 0.0)
836
+ evicted_any = False
837
+ while True:
838
+ free = self.disk_free_mb()
839
+ if free is None or free >= target_mb:
840
+ if evicted_any:
841
+ self.save_reference_to_disk()
842
+ return True
843
+ oldest = self.find_oldest_adhoc_entry()
844
+ if oldest is None:
845
+ if evicted_any:
846
+ self.save_reference_to_disk()
847
+ return False
848
+ self._delete_model_entry(oldest.model_key, oldest.version_key)
849
+ evicted_any = True
850
+
851
+ def _ensure_room_for_download(self, target: DownloadTarget) -> bool:
852
+ """Return whether *target* can be written without crossing the disk floor, evicting if needed.
853
+
854
+ Evicts oldest ad-hoc entries to make room. Returns ``False`` when even an empty ad-hoc cache
855
+ would leave the volume below the floor (a download that must be skipped).
856
+ """
857
+ free = self.disk_free_mb()
858
+ if free is None:
859
+ return True # Can't sample the volume; defer to the normal ENOSPC handling on write.
860
+ if free - target.size_mb >= self.min_free_disk_mb:
861
+ return True
862
+ return self.evict_adhoc_for_free_space(required_mb=target.size_mb)
863
+
729
864
  # ------------------------------------------------------------------
730
865
  # Unused-file cleanup (shared)
731
866
  # ------------------------------------------------------------------
@@ -25,6 +25,7 @@ from loguru import logger
25
25
 
26
26
  import hordelib.exceptions as he
27
27
  from hordelib.model_manager.civitai_adhoc import (
28
+ DEFAULT_MIN_FREE_DISK_MB,
28
29
  TESTS_ONGOING,
29
30
  CacheEntry,
30
31
  CivitaiAdhocModelManager,
@@ -75,6 +76,8 @@ class LoraModelManager(CivitaiAdhocModelManager[HordeLoraModelRecord]):
75
76
  allowed_top_lora_storage: The default-set cache budget, in megabytes.
76
77
  allowed_adhoc_lora_storage: The ad-hoc cache budget, in megabytes. Overridden by the
77
78
  ``AIWORKER_LORA_CACHE_SIZE`` environment variable when set.
79
+ The ``AIWORKER_LORA_MIN_DISK_FREE_MB`` environment variable likewise overrides the
80
+ free-space floor below which ad-hoc downloads evict (then refuse) to spare the disk.
78
81
  download_wait: Whether :meth:`download_default_models` blocks until downloads complete.
79
82
  multiprocessing_lock: Optional cross-process lock guarding on-disk reference writes.
80
83
  civitai_api_token: Optional CivitAI API token.
@@ -93,6 +96,15 @@ class LoraModelManager(CivitaiAdhocModelManager[HordeLoraModelRecord]):
93
96
  logger.bind(manager="lora").warning("lora.env_cache_size_invalid", raw_value=env_cache_size)
94
97
  adhoc_storage = AIWORKER_LORA_CACHE_SIZE_DEFAULT
95
98
 
99
+ min_free_disk_mb = DEFAULT_MIN_FREE_DISK_MB
100
+ env_min_free = os.getenv("AIWORKER_LORA_MIN_DISK_FREE_MB")
101
+ if env_min_free is not None:
102
+ try:
103
+ min_free_disk_mb = int(env_min_free)
104
+ except (ValueError, TypeError):
105
+ logger.bind(manager="lora").warning("lora.env_min_free_invalid", raw_value=env_min_free)
106
+ min_free_disk_mb = DEFAULT_MIN_FREE_DISK_MB
107
+
96
108
  models_db_path = horde_model_reference_paths.legacy_path.joinpath("lora.json").resolve()
97
109
  super().__init__(
98
110
  model_category=MODEL_REFERENCE_CATEGORY.lora,
@@ -103,6 +115,7 @@ class LoraModelManager(CivitaiAdhocModelManager[HordeLoraModelRecord]):
103
115
  reference_backups=reference_backups,
104
116
  max_top_disk=allowed_top_lora_storage,
105
117
  max_adhoc_disk=adhoc_storage,
118
+ min_free_disk_mb=min_free_disk_mb,
106
119
  )
107
120
 
108
121
  def ensure_is_version(self, lora_version: int | str) -> str | None:
File without changes
File without changes
File without changes