diffusers-workflow 0.4.0a8__tar.gz → 0.4.0a12__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 (272) hide show
  1. {diffusers_workflow-0.4.0a8/diffusers_workflow.egg-info → diffusers_workflow-0.4.0a12}/PKG-INFO +23 -4
  2. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/README.md +18 -3
  3. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12/diffusers_workflow.egg-info}/PKG-INFO +23 -4
  4. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/diffusers_workflow.egg-info/SOURCES.txt +47 -22
  5. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/diffusers_workflow.egg-info/entry_points.txt +1 -0
  6. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/diffusers_workflow.egg-info/requires.txt +5 -0
  7. diffusers_workflow-0.4.0a12/diffusers_workflow.egg-info/top_level.txt +2 -0
  8. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/__init__.py +89 -2
  9. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/events.py +38 -0
  10. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/hub_cache.py +5 -2
  11. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/introspection.py +76 -15
  12. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/pipeline_processors/chain.py +5 -0
  13. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/pipeline_processors/config_objects.py +4 -2
  14. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/pipeline_processors/pipeline.py +125 -15
  15. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/previous_results.py +13 -8
  16. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/repl.py +18 -0
  17. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/result.py +20 -2
  18. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/run.py +19 -1
  19. diffusers_workflow-0.4.0a12/dw/schema.py +43 -0
  20. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/security.py +187 -4
  21. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/serve.py +49 -1
  22. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/server/app.py +457 -46
  23. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/server/jobs.py +79 -5
  24. diffusers_workflow-0.4.0a8/dw/server/ui/assets/cssMode-4JQhrTTm.js → diffusers_workflow-0.4.0a12/dw/server/ui/assets/cssMode-CRm5Fmld.js +1 -1
  25. diffusers_workflow-0.4.0a8/dw/server/ui/assets/editor.api-B_68laXH.js → diffusers_workflow-0.4.0a12/dw/server/ui/assets/editor.api-CArwgKCZ.js +1 -1
  26. diffusers_workflow-0.4.0a8/dw/server/ui/assets/freemarker2-C4IxK8gs.js → diffusers_workflow-0.4.0a12/dw/server/ui/assets/freemarker2-B42MpbWP.js +1 -1
  27. diffusers_workflow-0.4.0a8/dw/server/ui/assets/handlebars-BArDGhF4.js → diffusers_workflow-0.4.0a12/dw/server/ui/assets/handlebars-BhleeD_A.js +1 -1
  28. diffusers_workflow-0.4.0a8/dw/server/ui/assets/html-8yKFx0-x.js → diffusers_workflow-0.4.0a12/dw/server/ui/assets/html-Bi_v7qEe.js +1 -1
  29. diffusers_workflow-0.4.0a8/dw/server/ui/assets/htmlMode-BwXG6XFP.js → diffusers_workflow-0.4.0a12/dw/server/ui/assets/htmlMode-c39yjrZR.js +1 -1
  30. diffusers_workflow-0.4.0a12/dw/server/ui/assets/index-CKHZ9ZUD.css +1 -0
  31. diffusers_workflow-0.4.0a12/dw/server/ui/assets/index-Do_ZJ3yS.js +23 -0
  32. diffusers_workflow-0.4.0a8/dw/server/ui/assets/javascript-B3mqpFQQ.js → diffusers_workflow-0.4.0a12/dw/server/ui/assets/javascript-BTuzJzdO.js +1 -1
  33. diffusers_workflow-0.4.0a8/dw/server/ui/assets/jsonMode-C1m5Z8Ha.js → diffusers_workflow-0.4.0a12/dw/server/ui/assets/jsonMode-DY2FmMCP.js +1 -1
  34. diffusers_workflow-0.4.0a8/dw/server/ui/assets/liquid-Cs5oVPJ1.js → diffusers_workflow-0.4.0a12/dw/server/ui/assets/liquid-iXwDEnQP.js +1 -1
  35. diffusers_workflow-0.4.0a8/dw/server/ui/assets/lspLanguageFeatures-CnroSKaf.js → diffusers_workflow-0.4.0a12/dw/server/ui/assets/lspLanguageFeatures-CVXyTq9V.js +1 -1
  36. diffusers_workflow-0.4.0a8/dw/server/ui/assets/mdx-BGAIyUWE.js → diffusers_workflow-0.4.0a12/dw/server/ui/assets/mdx-QE70XlV0.js +1 -1
  37. diffusers_workflow-0.4.0a8/dw/server/ui/assets/monaco-ab9gu2Wi.js → diffusers_workflow-0.4.0a12/dw/server/ui/assets/monaco-CzCru1EC.js +4 -4
  38. diffusers_workflow-0.4.0a8/dw/server/ui/assets/python-XsfASqaE.js → diffusers_workflow-0.4.0a12/dw/server/ui/assets/python-DxHS-kHp.js +1 -1
  39. diffusers_workflow-0.4.0a8/dw/server/ui/assets/razor-C-1xVmcy.js → diffusers_workflow-0.4.0a12/dw/server/ui/assets/razor-CT5Qrhwg.js +1 -1
  40. diffusers_workflow-0.4.0a8/dw/server/ui/assets/tsMode-BDa9GeVq.js → diffusers_workflow-0.4.0a12/dw/server/ui/assets/tsMode-qXdDdnF1.js +1 -1
  41. diffusers_workflow-0.4.0a8/dw/server/ui/assets/typescript-VE9GZNZf.js → diffusers_workflow-0.4.0a12/dw/server/ui/assets/typescript-BWfJagji.js +1 -1
  42. diffusers_workflow-0.4.0a8/dw/server/ui/assets/workers-C_2pIPh_.js → diffusers_workflow-0.4.0a12/dw/server/ui/assets/workers-C9vxrwoC.js +1 -1
  43. diffusers_workflow-0.4.0a8/dw/server/ui/assets/xml-BJp06vju.js → diffusers_workflow-0.4.0a12/dw/server/ui/assets/xml-DhJEwsDK.js +1 -1
  44. diffusers_workflow-0.4.0a8/dw/server/ui/assets/yaml-EI9SS79i.js → diffusers_workflow-0.4.0a12/dw/server/ui/assets/yaml-CiixMxAq.js +1 -1
  45. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/server/ui/index.html +2 -2
  46. diffusers_workflow-0.4.0a12/dw/server/updater.py +192 -0
  47. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/step.py +41 -0
  48. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/tasks/task.py +7 -2
  49. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/tasks/text_generation.py +15 -2
  50. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/type_helpers.py +12 -0
  51. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/validate.py +13 -1
  52. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/variables.py +92 -38
  53. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/workflow.py +61 -7
  54. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/workflow_schema.json +2 -2
  55. diffusers_workflow-0.4.0a12/dw_mcp/__init__.py +6 -0
  56. diffusers_workflow-0.4.0a12/dw_mcp/__main__.py +47 -0
  57. diffusers_workflow-0.4.0a12/dw_mcp/authoring.py +37 -0
  58. diffusers_workflow-0.4.0a12/dw_mcp/catalog.py +83 -0
  59. diffusers_workflow-0.4.0a12/dw_mcp/client.py +213 -0
  60. diffusers_workflow-0.4.0a12/dw_mcp/diagnose.py +139 -0
  61. diffusers_workflow-0.4.0a12/dw_mcp/media.py +133 -0
  62. diffusers_workflow-0.4.0a12/dw_mcp/models.py +97 -0
  63. diffusers_workflow-0.4.0a12/dw_mcp/prompts.py +91 -0
  64. diffusers_workflow-0.4.0a12/dw_mcp/server.py +403 -0
  65. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/pyproject.toml +4 -1
  66. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/tests/test_arguments.py +3 -2
  67. diffusers_workflow-0.4.0a12/tests/test_cli.py +198 -0
  68. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/tests/test_config_objects.py +10 -2
  69. diffusers_workflow-0.4.0a12/tests/test_device.py +150 -0
  70. diffusers_workflow-0.4.0a12/tests/test_device_portability.py +116 -0
  71. diffusers_workflow-0.4.0a12/tests/test_mcp_authoring.py +156 -0
  72. diffusers_workflow-0.4.0a12/tests/test_mcp_catalog.py +118 -0
  73. diffusers_workflow-0.4.0a12/tests/test_mcp_client.py +409 -0
  74. diffusers_workflow-0.4.0a12/tests/test_mcp_diagnose.py +334 -0
  75. diffusers_workflow-0.4.0a12/tests/test_mcp_media.py +377 -0
  76. diffusers_workflow-0.4.0a12/tests/test_mcp_models.py +187 -0
  77. diffusers_workflow-0.4.0a12/tests/test_mcp_prompts.py +267 -0
  78. diffusers_workflow-0.4.0a12/tests/test_mcp_server.py +740 -0
  79. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/tests/test_modular_pipeline.py +97 -2
  80. diffusers_workflow-0.4.0a12/tests/test_offload_placement.py +105 -0
  81. diffusers_workflow-0.4.0a12/tests/test_phase_events.py +303 -0
  82. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/tests/test_pipeline_components.py +33 -1
  83. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/tests/test_previous_results.py +48 -0
  84. diffusers_workflow-0.4.0a12/tests/test_repl_worker.py +77 -0
  85. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/tests/test_result.py +35 -0
  86. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/tests/test_security.py +57 -0
  87. diffusers_workflow-0.4.0a12/tests/test_server.py +2284 -0
  88. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/tests/test_step.py +82 -0
  89. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/tests/test_task.py +1 -1
  90. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/tests/test_task_discovery.py +43 -0
  91. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/tests/test_text_generation.py +38 -0
  92. diffusers_workflow-0.4.0a12/tests/test_updater.py +126 -0
  93. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/tests/test_variables.py +61 -15
  94. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/tests/test_workflow.py +96 -0
  95. diffusers_workflow-0.4.0a12/tests/test_workflow_trust.py +237 -0
  96. diffusers_workflow-0.4.0a8/diffusers_workflow.egg-info/top_level.txt +0 -1
  97. diffusers_workflow-0.4.0a8/dw/schema.py +0 -24
  98. diffusers_workflow-0.4.0a8/dw/server/ui/assets/index-BY3Mtj4M.js +0 -17
  99. diffusers_workflow-0.4.0a8/dw/server/ui/assets/index-Bug26k2P.css +0 -1
  100. diffusers_workflow-0.4.0a8/dw/server/updater.py +0 -119
  101. diffusers_workflow-0.4.0a8/tests/test_device.py +0 -59
  102. diffusers_workflow-0.4.0a8/tests/test_server.py +0 -1109
  103. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/LICENSE +0 -0
  104. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/MANIFEST.in +0 -0
  105. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/diffusers_workflow.egg-info/dependency_links.txt +0 -0
  106. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/arguments.py +0 -0
  107. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/cache_blocks.json +0 -0
  108. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/cache_blocks.py +0 -0
  109. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/community_pipelines/pipeline_flux_rf_inversion.py +0 -0
  110. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/log_setup.py +0 -0
  111. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/pipeline_processors/remote.py +0 -0
  112. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/prompt_schema.json +0 -0
  113. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/prompt_weighting.py +0 -0
  114. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/prompts.py +0 -0
  115. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/repl_commands.py +0 -0
  116. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/repl_worker.py +0 -0
  117. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/server/__init__.py +0 -0
  118. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/server/enhancers.py +0 -0
  119. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/abap-08VXUWAP.js +0 -0
  120. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/apex-BWPQTe0t.js +0 -0
  121. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/azcli-Bc_sGQ0U.js +0 -0
  122. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/bat-i0X4ZdIN.js +0 -0
  123. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/bicep-B5-_aFwp.js +0 -0
  124. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/cameligo-DMUM7wLl.js +0 -0
  125. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/clojure-Cm7r79vr.js +0 -0
  126. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/codicon-Brq4_Ui5.ttf +0 -0
  127. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/coffee-Ba7i2nA0.js +0 -0
  128. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/cpp-C7h46wYY.js +0 -0
  129. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/csharp-BKxtCVv1.js +0 -0
  130. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/csp-bTuwJoIa.js +0 -0
  131. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/css-DIMkf-bt.js +0 -0
  132. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/css.worker-B3ciXF_0.js +0 -0
  133. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/cypher-CVaqCwHa.js +0 -0
  134. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/dart-onAF5SnQ.js +0 -0
  135. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/dockerfile-DZFCIeNp.js +0 -0
  136. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/ecl-D05T4iGw.js +0 -0
  137. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/editor-jjEx9u7D.css +0 -0
  138. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/editor.worker-q-txB4vs.js +0 -0
  139. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/elixir-6RTg0lbw.js +0 -0
  140. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/flow9-C5_-GSwl.js +0 -0
  141. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/fsharp-C8Ef5oNN.js +0 -0
  142. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/go-C-y9NEjX.js +0 -0
  143. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/graphql-fmXr3nnJ.js +0 -0
  144. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/hcl-CpzslTdj.js +0 -0
  145. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/html.worker-C93Ht9o9.js +0 -0
  146. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/ini-sBoK_t0W.js +0 -0
  147. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/java-BEtHBSE6.js +0 -0
  148. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/json.worker-B2V3pomh.js +0 -0
  149. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/julia-Bri6UV-V.js +0 -0
  150. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/kotlin-BOotOW0E.js +0 -0
  151. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/less-B9JPFI3C.js +0 -0
  152. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/lexon-CfSJPG6W.js +0 -0
  153. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/lua-CsQS60Ue.js +0 -0
  154. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/m3-D-oSqn_W.js +0 -0
  155. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/markdown-Cimd5fb3.js +0 -0
  156. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/mips-CIPQ_RoX.js +0 -0
  157. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/monaco--ixms01u.css +0 -0
  158. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/msdax-DauUninz.js +0 -0
  159. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/mysql-SOo6toE5.js +0 -0
  160. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/objective-c-FvmIjYaQ.js +0 -0
  161. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/pascal-DrH0SRf2.js +0 -0
  162. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/pascaligo-D-ptJ9y-.js +0 -0
  163. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/perl-oz_6vUea.js +0 -0
  164. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/pgsql-DTj74zXo.js +0 -0
  165. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/php-nr791fC2.js +0 -0
  166. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/pla-CopQ2nXW.js +0 -0
  167. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/postiats-43DmfD33.js +0 -0
  168. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/powerquery-D3hlyOfw.js +0 -0
  169. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/powershell-DmHpPYUd.js +0 -0
  170. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/protobuf-C531GsRP.js +0 -0
  171. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/pug-Z5eAx3Zn.js +0 -0
  172. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/qsharp-DkqhCAOL.js +0 -0
  173. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/r-BwWrilGY.js +0 -0
  174. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/redis-ClamHrr6.js +0 -0
  175. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/redshift-DT7zqm-g.js +0 -0
  176. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/restructuredtext-BYgofb2h.js +0 -0
  177. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/ruby-DezsRK8O.js +0 -0
  178. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/rust-DdL9SqIa.js +0 -0
  179. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/sb-CcwsVR0C.js +0 -0
  180. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/scala-DHpiXF5c.js +0 -0
  181. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/scheme-BeGwcela.js +0 -0
  182. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/scss-gp-XZpBa.js +0 -0
  183. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/shell-CC2rA5mh.js +0 -0
  184. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/solidity-BEEn4gHE.js +0 -0
  185. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/sophia-CRfGWb83.js +0 -0
  186. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/sparql-D_Lu-MrJ.js +0 -0
  187. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/sql-NEE52Syq.js +0 -0
  188. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/st-DbInun42.js +0 -0
  189. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/swift-Bxkupp3x.js +0 -0
  190. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/systemverilog-Bz4Y3fRF.js +0 -0
  191. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/tcl-DISqw1ZD.js +0 -0
  192. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/ts.worker-D7T1-Ig5.js +0 -0
  193. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/twig-De2hgUGE.js +0 -0
  194. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/typespec-B8J7ngcE.js +0 -0
  195. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/vb-DV3o63ZY.js +0 -0
  196. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/wgsl-DpFanUEy.js +0 -0
  197. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/settings.py +0 -0
  198. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/tasks/audio_utils.py +0 -0
  199. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/tasks/background_remover.py +0 -0
  200. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/tasks/borders.py +0 -0
  201. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/tasks/concat_videos.py +0 -0
  202. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/tasks/depth_estimator.py +0 -0
  203. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/tasks/diffusion_upscale.py +0 -0
  204. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/tasks/format_messages.py +0 -0
  205. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/tasks/gather.py +0 -0
  206. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/tasks/image_to_text.py +0 -0
  207. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/tasks/image_utils.py +0 -0
  208. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/tasks/interpolate_frames.py +0 -0
  209. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/tasks/model_cache.py +0 -0
  210. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/tasks/pair_audio.py +0 -0
  211. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/tasks/qr_code.py +0 -0
  212. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/tasks/restore_faces.py +0 -0
  213. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/tasks/rife_model.py +0 -0
  214. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/tasks/segment.py +0 -0
  215. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/tasks/tensor_image.py +0 -0
  216. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/tasks/text_sections.py +0 -0
  217. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/tasks/upscale.py +0 -0
  218. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/tasks/video_utils.py +0 -0
  219. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/tasks/zoe_depth.py +0 -0
  220. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/teacache.py +0 -0
  221. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/teacache_models.json +0 -0
  222. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/test.py +0 -0
  223. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/worker.py +0 -0
  224. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/workflows/augment_prompt.json +0 -0
  225. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/workflows/describe_image.json +0 -0
  226. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/workflows/h3_context_ir.json +0 -0
  227. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/dw/workflows/test.json +0 -0
  228. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/setup.cfg +0 -0
  229. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/tests/test_argument_updates.py +0 -0
  230. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/tests/test_audio_utils.py +0 -0
  231. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/tests/test_borders.py +0 -0
  232. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/tests/test_cache_blocks.py +0 -0
  233. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/tests/test_chain.py +0 -0
  234. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/tests/test_component_pruning.py +0 -0
  235. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/tests/test_concat_videos.py +0 -0
  236. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/tests/test_configuration_schema.py +0 -0
  237. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/tests/test_depth_estimator.py +0 -0
  238. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/tests/test_device_helpers.py +0 -0
  239. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/tests/test_diffusion_upscale.py +0 -0
  240. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/tests/test_docs_links.py +0 -0
  241. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/tests/test_events.py +0 -0
  242. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/tests/test_examples.py +0 -0
  243. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/tests/test_gather.py +0 -0
  244. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/tests/test_hub_cache.py +0 -0
  245. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/tests/test_image_to_text.py +0 -0
  246. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/tests/test_image_utils.py +0 -0
  247. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/tests/test_integration.py +0 -0
  248. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/tests/test_interpolate_frames.py +0 -0
  249. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/tests/test_introspection.py +0 -0
  250. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/tests/test_list_images.py +0 -0
  251. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/tests/test_model_cache.py +0 -0
  252. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/tests/test_pair_audio.py +0 -0
  253. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/tests/test_pipeline_caching.py +0 -0
  254. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/tests/test_prompt_parser.py +0 -0
  255. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/tests/test_prompt_weighting.py +0 -0
  256. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/tests/test_prompts.py +0 -0
  257. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/tests/test_repl_commands.py +0 -0
  258. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/tests/test_repl_ergonomics.py +0 -0
  259. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/tests/test_repl_hierarchical.py +0 -0
  260. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/tests/test_repl_reorganization.py +0 -0
  261. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/tests/test_resize_bucket.py +0 -0
  262. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/tests/test_scheduler_config.py +0 -0
  263. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/tests/test_schema.py +0 -0
  264. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/tests/test_segment.py +0 -0
  265. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/tests/test_strip_exif_and_watermark.py +0 -0
  266. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/tests/test_teacache.py +0 -0
  267. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/tests/test_tensor_image.py +0 -0
  268. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/tests/test_text_sections.py +0 -0
  269. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/tests/test_type_helpers.py +0 -0
  270. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/tests/test_video_utils.py +0 -0
  271. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/tests/test_worker.py +0 -0
  272. {diffusers_workflow-0.4.0a8 → diffusers_workflow-0.4.0a12}/tests/test_worker_execute.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: diffusers-workflow
3
- Version: 0.4.0a8
3
+ Version: 0.4.0a12
4
4
  Summary: Declarative workflow engine and web UI for Hugging Face Diffusers
5
5
  Author: dkackman
6
6
  License: Apache-2.0
@@ -57,6 +57,9 @@ Requires-Dist: packaging>=26.3
57
57
  Provides-Extra: server
58
58
  Requires-Dist: fastapi>=0.141.1; extra == "server"
59
59
  Requires-Dist: uvicorn[standard]>=0.52.4; extra == "server"
60
+ Provides-Extra: mcp
61
+ Requires-Dist: mcp>=2.1.1; extra == "mcp"
62
+ Requires-Dist: httpx>=0.28.1; extra == "mcp"
60
63
  Provides-Extra: dev
61
64
  Requires-Dist: pytest>=9.1.1; extra == "dev"
62
65
  Requires-Dist: pytest-cov>=7.1.0; extra == "dev"
@@ -67,6 +70,7 @@ Requires-Dist: pytest-asyncio>=1.4.0; extra == "dev"
67
70
  Requires-Dist: httpx>=0.28.1; extra == "dev"
68
71
  Requires-Dist: black>=26.5.1; extra == "dev"
69
72
  Requires-Dist: build; extra == "dev"
73
+ Requires-Dist: mcp>=2.1.1; extra == "dev"
70
74
  Dynamic: license-file
71
75
 
72
76
  [![CodeQL](https://github.com/dkackman/diffusers-workflow/actions/workflows/github-code-scanning/codeql/badge.svg)](https://github.com/dkackman/diffusers-workflow/actions/workflows/github-code-scanning/codeql)
@@ -75,6 +79,8 @@ Dynamic: license-file
75
79
 
76
80
  A declarative workflow engine and web UI for the [Hugging Face Diffusers library](https://github.com/huggingface/diffusers). Define image/video generation pipelines in JSON — with full access to the configuration diffusers exposes — and run them from the command line, an interactive REPL, or a browser.
77
81
 
82
+ A workflow JSON file is portable and easy to hand off — but that same flexibility means loading one can execute arbitrary Python (dynamic imports are how it reaches any diffusers pipeline or quantization backend without a bespoke adapter for each). Treat a workflow file from someone else the way you'd treat a `.py` script: see [Trust model](docs/SECURITY.md#trust-model) before running one you didn't write.
83
+
78
84
  **Python 3.10-3.14 | CUDA (NVIDIA) | MPS (Apple Silicon) | CPU**
79
85
 
80
86
  <picture>
@@ -85,9 +91,10 @@ A declarative workflow engine and web UI for the [Hugging Face Diffusers library
85
91
  ## Features
86
92
 
87
93
  - **Web UI** — browse and run workflows, edit them in introspection-driven forms, watch jobs stream live progress, manage generated output and the models on disk. `python -m dw.serve` and open a browser. See [Server & Web UI](docs/SERVER.md).
94
+ - **MCP server** — a stdio server that lets an MCP client (Claude Code first) author, validate, save, run and diagnose workflows against a running `dw.serve`. `dw-mcp`. See [MCP Server](docs/MCP.md).
88
95
  - **Declarative JSON workflows** with variable substitution and cross-step data flow
89
96
  - **Multi-step pipelines** — chain text-to-image, image-to-video, inpainting, ControlNet
90
- - **Reproducible by construction** — outputs embed their full workflow definition and seed; any image in the gallery reopens as the exact workflow that made it
97
+ - **Reproducible by construction** — outputs embed their full workflow definition and seed; any image in the gallery reopens as the exact workflow that made it (see [Trust model](docs/SECURITY.md#trust-model) before reopening one someone else sent you)
91
98
  - **Long-video chaining** — run a video pipeline once per segment and stitch the segments into one clip, with audio-driven length and frame-to-frame continuity
92
99
  - **Quantization** — BitsAndBytes, TorchAO, GGUF, SDNQ, optimum-quanto
93
100
  - **Inference acceleration** — TeaCache, FirstBlockCache, FasterCache, MagCache, TaylorSeerCache
@@ -148,15 +155,26 @@ Jobs queue, stream progress live (per denoising step), cancel cooperatively, and
148
155
 
149
156
  ### Run a Workflow
150
157
 
158
+ `workflows/sd15.json` is the smallest, fastest starting point — a small, ungated model and a literal prompt, so the first run needs no Hugging Face login and downloads only a few GB:
159
+
151
160
  ```bash
161
+ python -m dw.run workflows/sd15.json
162
+ python -m dw.run workflows/sd15.json prompt="a cat" num_images_per_prompt=4
163
+ ```
164
+
165
+ Most of the workflows under `workflows/` (Flux, LTX-2, MiniMax...) use **gated** Hugging Face models — the repo owner has to approve your account before you can download them. Before running one of those, request access on the model's Hugging Face page (e.g. [black-forest-labs/FLUX.1-dev](https://huggingface.co/black-forest-labs/FLUX.1-dev)) and log in locally:
166
+
167
+ ```bash
168
+ huggingface-cli login
152
169
  python -m dw.run workflows/flux/FluxDev.json
153
- python -m dw.run workflows/flux/FluxDev.json prompt="a cat" num_images_per_prompt=4
154
170
  ```
155
171
 
172
+ Without this, the run fails partway through with an HTTP 401/403 from the Hub.
173
+
156
174
  ### Validate a Workflow
157
175
 
158
176
  ```bash
159
- python -m dw.validate workflows/flux/FluxDev.json
177
+ python -m dw.validate workflows/sd15.json
160
178
  ```
161
179
 
162
180
  ### Interactive REPL
@@ -323,6 +341,7 @@ See [workflows/](workflows/) for more workflow files.
323
341
  ### Guides
324
342
 
325
343
  - [Server & Web UI](docs/SERVER.md) — The web UI, jobs API, and introspection service
344
+ - [MCP Server](docs/MCP.md) — Tool surface for MCP clients (Claude Code, Claude Desktop)
326
345
  - [Workflow Guide](docs/WORKFLOW_GUIDE.md) — JSON structure, variables, steps, data flow
327
346
  - [Quantization](docs/QUANTIZATION.md) — BitsAndBytes, TorchAO, GGUF, SDNQ
328
347
  - [Inference Acceleration](docs/ACCELERATION.md) — torch.compile, FirstBlockCache, MagCache, TaylorSeer, TeaCache
@@ -4,6 +4,8 @@
4
4
 
5
5
  A declarative workflow engine and web UI for the [Hugging Face Diffusers library](https://github.com/huggingface/diffusers). Define image/video generation pipelines in JSON — with full access to the configuration diffusers exposes — and run them from the command line, an interactive REPL, or a browser.
6
6
 
7
+ A workflow JSON file is portable and easy to hand off — but that same flexibility means loading one can execute arbitrary Python (dynamic imports are how it reaches any diffusers pipeline or quantization backend without a bespoke adapter for each). Treat a workflow file from someone else the way you'd treat a `.py` script: see [Trust model](docs/SECURITY.md#trust-model) before running one you didn't write.
8
+
7
9
  **Python 3.10-3.14 | CUDA (NVIDIA) | MPS (Apple Silicon) | CPU**
8
10
 
9
11
  <picture>
@@ -14,9 +16,10 @@ A declarative workflow engine and web UI for the [Hugging Face Diffusers library
14
16
  ## Features
15
17
 
16
18
  - **Web UI** — browse and run workflows, edit them in introspection-driven forms, watch jobs stream live progress, manage generated output and the models on disk. `python -m dw.serve` and open a browser. See [Server & Web UI](docs/SERVER.md).
19
+ - **MCP server** — a stdio server that lets an MCP client (Claude Code first) author, validate, save, run and diagnose workflows against a running `dw.serve`. `dw-mcp`. See [MCP Server](docs/MCP.md).
17
20
  - **Declarative JSON workflows** with variable substitution and cross-step data flow
18
21
  - **Multi-step pipelines** — chain text-to-image, image-to-video, inpainting, ControlNet
19
- - **Reproducible by construction** — outputs embed their full workflow definition and seed; any image in the gallery reopens as the exact workflow that made it
22
+ - **Reproducible by construction** — outputs embed their full workflow definition and seed; any image in the gallery reopens as the exact workflow that made it (see [Trust model](docs/SECURITY.md#trust-model) before reopening one someone else sent you)
20
23
  - **Long-video chaining** — run a video pipeline once per segment and stitch the segments into one clip, with audio-driven length and frame-to-frame continuity
21
24
  - **Quantization** — BitsAndBytes, TorchAO, GGUF, SDNQ, optimum-quanto
22
25
  - **Inference acceleration** — TeaCache, FirstBlockCache, FasterCache, MagCache, TaylorSeerCache
@@ -77,15 +80,26 @@ Jobs queue, stream progress live (per denoising step), cancel cooperatively, and
77
80
 
78
81
  ### Run a Workflow
79
82
 
83
+ `workflows/sd15.json` is the smallest, fastest starting point — a small, ungated model and a literal prompt, so the first run needs no Hugging Face login and downloads only a few GB:
84
+
80
85
  ```bash
86
+ python -m dw.run workflows/sd15.json
87
+ python -m dw.run workflows/sd15.json prompt="a cat" num_images_per_prompt=4
88
+ ```
89
+
90
+ Most of the workflows under `workflows/` (Flux, LTX-2, MiniMax...) use **gated** Hugging Face models — the repo owner has to approve your account before you can download them. Before running one of those, request access on the model's Hugging Face page (e.g. [black-forest-labs/FLUX.1-dev](https://huggingface.co/black-forest-labs/FLUX.1-dev)) and log in locally:
91
+
92
+ ```bash
93
+ huggingface-cli login
81
94
  python -m dw.run workflows/flux/FluxDev.json
82
- python -m dw.run workflows/flux/FluxDev.json prompt="a cat" num_images_per_prompt=4
83
95
  ```
84
96
 
97
+ Without this, the run fails partway through with an HTTP 401/403 from the Hub.
98
+
85
99
  ### Validate a Workflow
86
100
 
87
101
  ```bash
88
- python -m dw.validate workflows/flux/FluxDev.json
102
+ python -m dw.validate workflows/sd15.json
89
103
  ```
90
104
 
91
105
  ### Interactive REPL
@@ -252,6 +266,7 @@ See [workflows/](workflows/) for more workflow files.
252
266
  ### Guides
253
267
 
254
268
  - [Server & Web UI](docs/SERVER.md) — The web UI, jobs API, and introspection service
269
+ - [MCP Server](docs/MCP.md) — Tool surface for MCP clients (Claude Code, Claude Desktop)
255
270
  - [Workflow Guide](docs/WORKFLOW_GUIDE.md) — JSON structure, variables, steps, data flow
256
271
  - [Quantization](docs/QUANTIZATION.md) — BitsAndBytes, TorchAO, GGUF, SDNQ
257
272
  - [Inference Acceleration](docs/ACCELERATION.md) — torch.compile, FirstBlockCache, MagCache, TaylorSeer, TeaCache
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: diffusers-workflow
3
- Version: 0.4.0a8
3
+ Version: 0.4.0a12
4
4
  Summary: Declarative workflow engine and web UI for Hugging Face Diffusers
5
5
  Author: dkackman
6
6
  License: Apache-2.0
@@ -57,6 +57,9 @@ Requires-Dist: packaging>=26.3
57
57
  Provides-Extra: server
58
58
  Requires-Dist: fastapi>=0.141.1; extra == "server"
59
59
  Requires-Dist: uvicorn[standard]>=0.52.4; extra == "server"
60
+ Provides-Extra: mcp
61
+ Requires-Dist: mcp>=2.1.1; extra == "mcp"
62
+ Requires-Dist: httpx>=0.28.1; extra == "mcp"
60
63
  Provides-Extra: dev
61
64
  Requires-Dist: pytest>=9.1.1; extra == "dev"
62
65
  Requires-Dist: pytest-cov>=7.1.0; extra == "dev"
@@ -67,6 +70,7 @@ Requires-Dist: pytest-asyncio>=1.4.0; extra == "dev"
67
70
  Requires-Dist: httpx>=0.28.1; extra == "dev"
68
71
  Requires-Dist: black>=26.5.1; extra == "dev"
69
72
  Requires-Dist: build; extra == "dev"
73
+ Requires-Dist: mcp>=2.1.1; extra == "dev"
70
74
  Dynamic: license-file
71
75
 
72
76
  [![CodeQL](https://github.com/dkackman/diffusers-workflow/actions/workflows/github-code-scanning/codeql/badge.svg)](https://github.com/dkackman/diffusers-workflow/actions/workflows/github-code-scanning/codeql)
@@ -75,6 +79,8 @@ Dynamic: license-file
75
79
 
76
80
  A declarative workflow engine and web UI for the [Hugging Face Diffusers library](https://github.com/huggingface/diffusers). Define image/video generation pipelines in JSON — with full access to the configuration diffusers exposes — and run them from the command line, an interactive REPL, or a browser.
77
81
 
82
+ A workflow JSON file is portable and easy to hand off — but that same flexibility means loading one can execute arbitrary Python (dynamic imports are how it reaches any diffusers pipeline or quantization backend without a bespoke adapter for each). Treat a workflow file from someone else the way you'd treat a `.py` script: see [Trust model](docs/SECURITY.md#trust-model) before running one you didn't write.
83
+
78
84
  **Python 3.10-3.14 | CUDA (NVIDIA) | MPS (Apple Silicon) | CPU**
79
85
 
80
86
  <picture>
@@ -85,9 +91,10 @@ A declarative workflow engine and web UI for the [Hugging Face Diffusers library
85
91
  ## Features
86
92
 
87
93
  - **Web UI** — browse and run workflows, edit them in introspection-driven forms, watch jobs stream live progress, manage generated output and the models on disk. `python -m dw.serve` and open a browser. See [Server & Web UI](docs/SERVER.md).
94
+ - **MCP server** — a stdio server that lets an MCP client (Claude Code first) author, validate, save, run and diagnose workflows against a running `dw.serve`. `dw-mcp`. See [MCP Server](docs/MCP.md).
88
95
  - **Declarative JSON workflows** with variable substitution and cross-step data flow
89
96
  - **Multi-step pipelines** — chain text-to-image, image-to-video, inpainting, ControlNet
90
- - **Reproducible by construction** — outputs embed their full workflow definition and seed; any image in the gallery reopens as the exact workflow that made it
97
+ - **Reproducible by construction** — outputs embed their full workflow definition and seed; any image in the gallery reopens as the exact workflow that made it (see [Trust model](docs/SECURITY.md#trust-model) before reopening one someone else sent you)
91
98
  - **Long-video chaining** — run a video pipeline once per segment and stitch the segments into one clip, with audio-driven length and frame-to-frame continuity
92
99
  - **Quantization** — BitsAndBytes, TorchAO, GGUF, SDNQ, optimum-quanto
93
100
  - **Inference acceleration** — TeaCache, FirstBlockCache, FasterCache, MagCache, TaylorSeerCache
@@ -148,15 +155,26 @@ Jobs queue, stream progress live (per denoising step), cancel cooperatively, and
148
155
 
149
156
  ### Run a Workflow
150
157
 
158
+ `workflows/sd15.json` is the smallest, fastest starting point — a small, ungated model and a literal prompt, so the first run needs no Hugging Face login and downloads only a few GB:
159
+
151
160
  ```bash
161
+ python -m dw.run workflows/sd15.json
162
+ python -m dw.run workflows/sd15.json prompt="a cat" num_images_per_prompt=4
163
+ ```
164
+
165
+ Most of the workflows under `workflows/` (Flux, LTX-2, MiniMax...) use **gated** Hugging Face models — the repo owner has to approve your account before you can download them. Before running one of those, request access on the model's Hugging Face page (e.g. [black-forest-labs/FLUX.1-dev](https://huggingface.co/black-forest-labs/FLUX.1-dev)) and log in locally:
166
+
167
+ ```bash
168
+ huggingface-cli login
152
169
  python -m dw.run workflows/flux/FluxDev.json
153
- python -m dw.run workflows/flux/FluxDev.json prompt="a cat" num_images_per_prompt=4
154
170
  ```
155
171
 
172
+ Without this, the run fails partway through with an HTTP 401/403 from the Hub.
173
+
156
174
  ### Validate a Workflow
157
175
 
158
176
  ```bash
159
- python -m dw.validate workflows/flux/FluxDev.json
177
+ python -m dw.validate workflows/sd15.json
160
178
  ```
161
179
 
162
180
  ### Interactive REPL
@@ -323,6 +341,7 @@ See [workflows/](workflows/) for more workflow files.
323
341
  ### Guides
324
342
 
325
343
  - [Server & Web UI](docs/SERVER.md) — The web UI, jobs API, and introspection service
344
+ - [MCP Server](docs/MCP.md) — Tool surface for MCP clients (Claude Code, Claude Desktop)
326
345
  - [Workflow Guide](docs/WORKFLOW_GUIDE.md) — JSON structure, variables, steps, data flow
327
346
  - [Quantization](docs/QUANTIZATION.md) — BitsAndBytes, TorchAO, GGUF, SDNQ
328
347
  - [Inference Acceleration](docs/ACCELERATION.md) — torch.compile, FirstBlockCache, MagCache, TaylorSeer, TeaCache
@@ -64,45 +64,45 @@ dw/server/ui/assets/csharp-BKxtCVv1.js
64
64
  dw/server/ui/assets/csp-bTuwJoIa.js
65
65
  dw/server/ui/assets/css-DIMkf-bt.js
66
66
  dw/server/ui/assets/css.worker-B3ciXF_0.js
67
- dw/server/ui/assets/cssMode-4JQhrTTm.js
67
+ dw/server/ui/assets/cssMode-CRm5Fmld.js
68
68
  dw/server/ui/assets/cypher-CVaqCwHa.js
69
69
  dw/server/ui/assets/dart-onAF5SnQ.js
70
70
  dw/server/ui/assets/dockerfile-DZFCIeNp.js
71
71
  dw/server/ui/assets/ecl-D05T4iGw.js
72
72
  dw/server/ui/assets/editor-jjEx9u7D.css
73
- dw/server/ui/assets/editor.api-B_68laXH.js
73
+ dw/server/ui/assets/editor.api-CArwgKCZ.js
74
74
  dw/server/ui/assets/editor.worker-q-txB4vs.js
75
75
  dw/server/ui/assets/elixir-6RTg0lbw.js
76
76
  dw/server/ui/assets/flow9-C5_-GSwl.js
77
- dw/server/ui/assets/freemarker2-C4IxK8gs.js
77
+ dw/server/ui/assets/freemarker2-B42MpbWP.js
78
78
  dw/server/ui/assets/fsharp-C8Ef5oNN.js
79
79
  dw/server/ui/assets/go-C-y9NEjX.js
80
80
  dw/server/ui/assets/graphql-fmXr3nnJ.js
81
- dw/server/ui/assets/handlebars-BArDGhF4.js
81
+ dw/server/ui/assets/handlebars-BhleeD_A.js
82
82
  dw/server/ui/assets/hcl-CpzslTdj.js
83
- dw/server/ui/assets/html-8yKFx0-x.js
83
+ dw/server/ui/assets/html-Bi_v7qEe.js
84
84
  dw/server/ui/assets/html.worker-C93Ht9o9.js
85
- dw/server/ui/assets/htmlMode-BwXG6XFP.js
86
- dw/server/ui/assets/index-BY3Mtj4M.js
87
- dw/server/ui/assets/index-Bug26k2P.css
85
+ dw/server/ui/assets/htmlMode-c39yjrZR.js
86
+ dw/server/ui/assets/index-CKHZ9ZUD.css
87
+ dw/server/ui/assets/index-Do_ZJ3yS.js
88
88
  dw/server/ui/assets/ini-sBoK_t0W.js
89
89
  dw/server/ui/assets/java-BEtHBSE6.js
90
- dw/server/ui/assets/javascript-B3mqpFQQ.js
90
+ dw/server/ui/assets/javascript-BTuzJzdO.js
91
91
  dw/server/ui/assets/json.worker-B2V3pomh.js
92
- dw/server/ui/assets/jsonMode-C1m5Z8Ha.js
92
+ dw/server/ui/assets/jsonMode-DY2FmMCP.js
93
93
  dw/server/ui/assets/julia-Bri6UV-V.js
94
94
  dw/server/ui/assets/kotlin-BOotOW0E.js
95
95
  dw/server/ui/assets/less-B9JPFI3C.js
96
96
  dw/server/ui/assets/lexon-CfSJPG6W.js
97
- dw/server/ui/assets/liquid-Cs5oVPJ1.js
98
- dw/server/ui/assets/lspLanguageFeatures-CnroSKaf.js
97
+ dw/server/ui/assets/liquid-iXwDEnQP.js
98
+ dw/server/ui/assets/lspLanguageFeatures-CVXyTq9V.js
99
99
  dw/server/ui/assets/lua-CsQS60Ue.js
100
100
  dw/server/ui/assets/m3-D-oSqn_W.js
101
101
  dw/server/ui/assets/markdown-Cimd5fb3.js
102
- dw/server/ui/assets/mdx-BGAIyUWE.js
102
+ dw/server/ui/assets/mdx-QE70XlV0.js
103
103
  dw/server/ui/assets/mips-CIPQ_RoX.js
104
104
  dw/server/ui/assets/monaco--ixms01u.css
105
- dw/server/ui/assets/monaco-ab9gu2Wi.js
105
+ dw/server/ui/assets/monaco-CzCru1EC.js
106
106
  dw/server/ui/assets/msdax-DauUninz.js
107
107
  dw/server/ui/assets/mysql-SOo6toE5.js
108
108
  dw/server/ui/assets/objective-c-FvmIjYaQ.js
@@ -117,10 +117,10 @@ dw/server/ui/assets/powerquery-D3hlyOfw.js
117
117
  dw/server/ui/assets/powershell-DmHpPYUd.js
118
118
  dw/server/ui/assets/protobuf-C531GsRP.js
119
119
  dw/server/ui/assets/pug-Z5eAx3Zn.js
120
- dw/server/ui/assets/python-XsfASqaE.js
120
+ dw/server/ui/assets/python-DxHS-kHp.js
121
121
  dw/server/ui/assets/qsharp-DkqhCAOL.js
122
122
  dw/server/ui/assets/r-BwWrilGY.js
123
- dw/server/ui/assets/razor-C-1xVmcy.js
123
+ dw/server/ui/assets/razor-CT5Qrhwg.js
124
124
  dw/server/ui/assets/redis-ClamHrr6.js
125
125
  dw/server/ui/assets/redshift-DT7zqm-g.js
126
126
  dw/server/ui/assets/restructuredtext-BYgofb2h.js
@@ -140,15 +140,15 @@ dw/server/ui/assets/swift-Bxkupp3x.js
140
140
  dw/server/ui/assets/systemverilog-Bz4Y3fRF.js
141
141
  dw/server/ui/assets/tcl-DISqw1ZD.js
142
142
  dw/server/ui/assets/ts.worker-D7T1-Ig5.js
143
- dw/server/ui/assets/tsMode-BDa9GeVq.js
143
+ dw/server/ui/assets/tsMode-qXdDdnF1.js
144
144
  dw/server/ui/assets/twig-De2hgUGE.js
145
- dw/server/ui/assets/typescript-VE9GZNZf.js
145
+ dw/server/ui/assets/typescript-BWfJagji.js
146
146
  dw/server/ui/assets/typespec-B8J7ngcE.js
147
147
  dw/server/ui/assets/vb-DV3o63ZY.js
148
148
  dw/server/ui/assets/wgsl-DpFanUEy.js
149
- dw/server/ui/assets/workers-C_2pIPh_.js
150
- dw/server/ui/assets/xml-BJp06vju.js
151
- dw/server/ui/assets/yaml-EI9SS79i.js
149
+ dw/server/ui/assets/workers-C9vxrwoC.js
150
+ dw/server/ui/assets/xml-DhJEwsDK.js
151
+ dw/server/ui/assets/yaml-CiixMxAq.js
152
152
  dw/tasks/audio_utils.py
153
153
  dw/tasks/background_remover.py
154
154
  dw/tasks/borders.py
@@ -177,12 +177,23 @@ dw/workflows/augment_prompt.json
177
177
  dw/workflows/describe_image.json
178
178
  dw/workflows/h3_context_ir.json
179
179
  dw/workflows/test.json
180
+ dw_mcp/__init__.py
181
+ dw_mcp/__main__.py
182
+ dw_mcp/authoring.py
183
+ dw_mcp/catalog.py
184
+ dw_mcp/client.py
185
+ dw_mcp/diagnose.py
186
+ dw_mcp/media.py
187
+ dw_mcp/models.py
188
+ dw_mcp/prompts.py
189
+ dw_mcp/server.py
180
190
  tests/test_argument_updates.py
181
191
  tests/test_arguments.py
182
192
  tests/test_audio_utils.py
183
193
  tests/test_borders.py
184
194
  tests/test_cache_blocks.py
185
195
  tests/test_chain.py
196
+ tests/test_cli.py
186
197
  tests/test_component_pruning.py
187
198
  tests/test_concat_videos.py
188
199
  tests/test_config_objects.py
@@ -190,6 +201,7 @@ tests/test_configuration_schema.py
190
201
  tests/test_depth_estimator.py
191
202
  tests/test_device.py
192
203
  tests/test_device_helpers.py
204
+ tests/test_device_portability.py
193
205
  tests/test_diffusion_upscale.py
194
206
  tests/test_docs_links.py
195
207
  tests/test_events.py
@@ -202,9 +214,19 @@ tests/test_integration.py
202
214
  tests/test_interpolate_frames.py
203
215
  tests/test_introspection.py
204
216
  tests/test_list_images.py
217
+ tests/test_mcp_authoring.py
218
+ tests/test_mcp_catalog.py
219
+ tests/test_mcp_client.py
220
+ tests/test_mcp_diagnose.py
221
+ tests/test_mcp_media.py
222
+ tests/test_mcp_models.py
223
+ tests/test_mcp_prompts.py
224
+ tests/test_mcp_server.py
205
225
  tests/test_model_cache.py
206
226
  tests/test_modular_pipeline.py
227
+ tests/test_offload_placement.py
207
228
  tests/test_pair_audio.py
229
+ tests/test_phase_events.py
208
230
  tests/test_pipeline_caching.py
209
231
  tests/test_pipeline_components.py
210
232
  tests/test_previous_results.py
@@ -215,6 +237,7 @@ tests/test_repl_commands.py
215
237
  tests/test_repl_ergonomics.py
216
238
  tests/test_repl_hierarchical.py
217
239
  tests/test_repl_reorganization.py
240
+ tests/test_repl_worker.py
218
241
  tests/test_resize_bucket.py
219
242
  tests/test_result.py
220
243
  tests/test_scheduler_config.py
@@ -231,8 +254,10 @@ tests/test_tensor_image.py
231
254
  tests/test_text_generation.py
232
255
  tests/test_text_sections.py
233
256
  tests/test_type_helpers.py
257
+ tests/test_updater.py
234
258
  tests/test_variables.py
235
259
  tests/test_video_utils.py
236
260
  tests/test_worker.py
237
261
  tests/test_worker_execute.py
238
- tests/test_workflow.py
262
+ tests/test_workflow.py
263
+ tests/test_workflow_trust.py
@@ -1,4 +1,5 @@
1
1
  [console_scripts]
2
+ dw-mcp = dw_mcp.__main__:main
2
3
  dw-repl = dw.repl:main
3
4
  dw-run = dw.run:main
4
5
  dw-serve = dw.serve:main
@@ -49,6 +49,11 @@ pytest-asyncio>=1.4.0
49
49
  httpx>=0.28.1
50
50
  black>=26.5.1
51
51
  build
52
+ mcp>=2.1.1
53
+
54
+ [mcp]
55
+ mcp>=2.1.1
56
+ httpx>=0.28.1
52
57
 
53
58
  [server]
54
59
  fastapi>=0.141.1
@@ -29,8 +29,20 @@ warnings.filterwarnings("ignore", category=FutureWarning)
29
29
  warnings.filterwarnings("ignore", category=UserWarning)
30
30
  warnings.filterwarnings("ignore", category=DeprecationWarning)
31
31
 
32
- # Lazy import torch to avoid import errors when torch isn't available
33
- # (e.g., when using system Python instead of venv)
32
+ # Eager (but guarded) import of torch. This module's own top-level code needs
33
+ # torch's exceptions/types unconditionally to detect its absence gracefully
34
+ # (see _TORCH_AVAILABLE below) rather than deferring the try/except to first
35
+ # use everywhere torch is touched. It would be nice for a torch-free path like
36
+ # `python -m dw.validate` (pure JSON schema validation) to skip this multi-
37
+ # second import, but that isn't achievable by changing dw/__init__.py alone:
38
+ # dw/validate.py imports dw/workflow.py, which does its own unconditional
39
+ # `import torch` at module scope (Workflow.run() uses torch.Generator() for
40
+ # seeding) - so torch loads regardless of what this module does. Making the
41
+ # import here lazy without also restructuring dw/workflow.py's random-seed
42
+ # handling would just move the cost around, not remove it, and touching
43
+ # dw/workflow.py's import structure is a larger, riskier change than this
44
+ # fix pass is meant to make. Left eager on purpose; see the audit notes for
45
+ # why a real fix needs to start in dw/workflow.py, not here.
34
46
  try:
35
47
  import torch
36
48
  import diffusers
@@ -138,6 +150,81 @@ def get_device_type(device=None):
138
150
  return torch.device(device if device is not None else get_device()).type
139
151
 
140
152
 
153
+ def backend_available(device_type):
154
+ """
155
+ Whether this machine can actually run on a backend.
156
+
157
+ Only the backends dw knows how to probe get an answer. An unrecognized one is
158
+ reported available rather than guessed at, so a device torch understands and dw
159
+ does not is left alone instead of being rewritten.
160
+
161
+ Args:
162
+ device_type: Backend name ('cuda', 'mps', 'cpu', ...)
163
+
164
+ Returns:
165
+ bool: Whether the backend is usable here
166
+ """
167
+ if not _TORCH_AVAILABLE:
168
+ return device_type == "cpu"
169
+
170
+ if device_type == "cpu":
171
+ return True
172
+
173
+ if device_type == "cuda":
174
+ return torch.cuda.is_available()
175
+
176
+ if device_type == "mps":
177
+ return hasattr(torch.backends, "mps") and torch.backends.mps.is_available()
178
+
179
+ is_available = getattr(getattr(torch, device_type, None), "is_available", None)
180
+ return bool(is_available()) if callable(is_available) else True
181
+
182
+
183
+ def resolve_device(requested):
184
+ """
185
+ Translate a device a workflow asked for into one this machine has.
186
+
187
+ A device named in a workflow is nearly always the author saying 'the accelerator'
188
+ rather than 'specifically NVIDIA', so a workflow written on a CUDA box runs on a
189
+ Mac and back again. The backend is what gets translated - an index is left alone
190
+ when the backend matches, since 'cuda:1' on a single-GPU CUDA box is a genuine
191
+ mistake and not a portability problem. A CPU device is never rewritten: pinning a
192
+ step to the CPU is how a GPU-specific problem gets ruled out.
193
+
194
+ Args:
195
+ requested: Device identifier from a workflow, or None for no override
196
+
197
+ Returns:
198
+ The device to use, or None if None was passed
199
+ """
200
+ if requested is None or not _TORCH_AVAILABLE:
201
+ return requested
202
+
203
+ try:
204
+ device = torch.device(requested)
205
+ except (RuntimeError, TypeError, ValueError):
206
+ # Not a device torch understands - let the failure surface where it is used
207
+ return requested
208
+
209
+ if device.type == "cpu" or backend_available(device.type):
210
+ return requested
211
+
212
+ target = get_device()
213
+ if device.index is not None:
214
+ logging.warning(
215
+ f"Workflow asks for '{requested}', which this machine has no {device.type} "
216
+ f"backend for - running on {target}. The device index is dropped, so a "
217
+ "workflow that meant to spread work across accelerators will not."
218
+ )
219
+ else:
220
+ logging.warning(
221
+ f"Workflow asks for '{requested}', which this machine has no {device.type} "
222
+ f"backend for - running on {target}"
223
+ )
224
+
225
+ return target
226
+
227
+
141
228
  def get_autocast_device_type():
142
229
  """
143
230
  Get the device type to use for torch.autocast.
@@ -27,6 +27,10 @@ class RunContext:
27
27
  def __init__(self, on_event=None):
28
28
  self._on_event = on_event
29
29
  self._cancel = threading.Event()
30
+ # The most recent phase this run reported (see emit_phase/PHASES) -
31
+ # cancel() reads it to tell a client whether the cancel takes effect
32
+ # right away or has to wait out an in-flight, non-interruptible phase
33
+ self._current_phase = None
30
34
  # Pipeline cache keys this run resolved - the worker evicts entries a
31
35
  # run no longer touches, so an edited workflow drops stale models
32
36
  self.touched_pipelines = set()
@@ -40,8 +44,18 @@ class RunContext:
40
44
  # A broken sink must not kill a run that is otherwise fine
41
45
  logger.warning(f"Progress event sink failed on '{event_type}': {e}")
42
46
 
47
+ def note_phase(self, phase):
48
+ """Record the run's latest phase - called by emit_phase, read by
49
+ cancel() to judge whether the current phase can be interrupted."""
50
+ self._current_phase = phase
51
+
43
52
  def cancel(self):
44
53
  self._cancel.set()
54
+ if self._current_phase in NON_INTERRUPTIBLE_PHASES:
55
+ # A model load or a task step has no checkpoint to catch this
56
+ # flag until it finishes - say so, or the client sees the cancel
57
+ # request go silent for however long that takes
58
+ self.emit("cancel_pending", phase=self._current_phase)
45
59
 
46
60
  @property
47
61
  def cancelled(self):
@@ -76,3 +90,27 @@ def activate_context(context):
76
90
 
77
91
  def deactivate_context(token):
78
92
  _active_context.reset(token)
93
+
94
+
95
+ # The coarse states a run passes through. Small on purpose: a phase says what
96
+ # the run is waiting on, not what any one library is doing internally
97
+ PHASES = ("loading", "cached", "generating", "decoding", "saving", "task")
98
+
99
+ # Phases with no checkpoint of their own: nothing inside a from_pretrained()
100
+ # call or a task handler consults the cancel flag, so a cancel requested
101
+ # during one of these can only take effect once the phase finishes on its own
102
+ NON_INTERRUPTIBLE_PHASES = ("loading", "task")
103
+
104
+
105
+ def emit_phase(phase, detail=None):
106
+ """Report a coarse phase change on the active run.
107
+
108
+ A step spends most of its wall clock outside the denoise loop - pulling
109
+ weights, decoding latents, encoding video - and a step counter says
110
+ nothing about any of that. These are the rest of the story. They are rare
111
+ enough (a handful per step) to carry a free-text detail alongside, which
112
+ is what makes 'loading' readable as 'which model'.
113
+ """
114
+ context = get_context()
115
+ context.note_phase(phase)
116
+ context.emit("phase", phase=phase, detail=detail)
@@ -150,6 +150,7 @@ class DownloadManager:
150
150
  except HFValidationError as e:
151
151
  raise ValueError(str(e))
152
152
 
153
+ cancel_event = threading.Event()
153
154
  with self._lock:
154
155
  for entry in self._downloads.values():
155
156
  if entry["repo_id"] == repo_id and entry["status"] == "downloading":
@@ -163,12 +164,14 @@ class DownloadManager:
163
164
  "error": None,
164
165
  "started_at": time.time(),
165
166
  "finished_at": None,
167
+ # Set before the entry is published: cancel() reaches for this
168
+ # the moment the id is visible, and assigning it after the
169
+ # lock left a window where cancelling raised KeyError
170
+ "_cancel": cancel_event,
166
171
  }
167
172
  self._downloads[entry["id"]] = entry
168
173
  self._prune()
169
174
 
170
- cancel_event = threading.Event()
171
- entry["_cancel"] = cancel_event
172
175
  thread = threading.Thread(
173
176
  target=self._run, args=(entry, cancel_event), daemon=True
174
177
  )