diffusers-workflow 0.4.0a10__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.
- {diffusers_workflow-0.4.0a10/diffusers_workflow.egg-info → diffusers_workflow-0.4.0a12}/PKG-INFO +17 -4
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/README.md +16 -3
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12/diffusers_workflow.egg-info}/PKG-INFO +17 -4
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/diffusers_workflow.egg-info/SOURCES.txt +24 -22
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/__init__.py +14 -2
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/events.py +22 -1
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/pipeline_processors/pipeline.py +50 -4
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/repl.py +18 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/run.py +14 -0
- diffusers_workflow-0.4.0a12/dw/schema.py +43 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/security.py +181 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/serve.py +49 -1
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/server/app.py +329 -44
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/server/jobs.py +26 -1
- diffusers_workflow-0.4.0a10/dw/server/ui/assets/cssMode-DBf-T_da.js → diffusers_workflow-0.4.0a12/dw/server/ui/assets/cssMode-CRm5Fmld.js +1 -1
- diffusers_workflow-0.4.0a10/dw/server/ui/assets/editor.api-B0D5Ygq7.js → diffusers_workflow-0.4.0a12/dw/server/ui/assets/editor.api-CArwgKCZ.js +1 -1
- diffusers_workflow-0.4.0a10/dw/server/ui/assets/freemarker2-Br8g4G1T.js → diffusers_workflow-0.4.0a12/dw/server/ui/assets/freemarker2-B42MpbWP.js +1 -1
- diffusers_workflow-0.4.0a10/dw/server/ui/assets/handlebars-BKo1TaOF.js → diffusers_workflow-0.4.0a12/dw/server/ui/assets/handlebars-BhleeD_A.js +1 -1
- diffusers_workflow-0.4.0a10/dw/server/ui/assets/html-Bis1seyM.js → diffusers_workflow-0.4.0a12/dw/server/ui/assets/html-Bi_v7qEe.js +1 -1
- diffusers_workflow-0.4.0a10/dw/server/ui/assets/htmlMode-D2SOD2MF.js → diffusers_workflow-0.4.0a12/dw/server/ui/assets/htmlMode-c39yjrZR.js +1 -1
- diffusers_workflow-0.4.0a12/dw/server/ui/assets/index-CKHZ9ZUD.css +1 -0
- diffusers_workflow-0.4.0a12/dw/server/ui/assets/index-Do_ZJ3yS.js +23 -0
- diffusers_workflow-0.4.0a10/dw/server/ui/assets/javascript-CkEbVb78.js → diffusers_workflow-0.4.0a12/dw/server/ui/assets/javascript-BTuzJzdO.js +1 -1
- diffusers_workflow-0.4.0a10/dw/server/ui/assets/jsonMode-dVJbYwxg.js → diffusers_workflow-0.4.0a12/dw/server/ui/assets/jsonMode-DY2FmMCP.js +1 -1
- diffusers_workflow-0.4.0a10/dw/server/ui/assets/liquid-Btak-6uF.js → diffusers_workflow-0.4.0a12/dw/server/ui/assets/liquid-iXwDEnQP.js +1 -1
- diffusers_workflow-0.4.0a10/dw/server/ui/assets/lspLanguageFeatures-BfeZZQbb.js → diffusers_workflow-0.4.0a12/dw/server/ui/assets/lspLanguageFeatures-CVXyTq9V.js +1 -1
- diffusers_workflow-0.4.0a10/dw/server/ui/assets/mdx-D9KXK7-s.js → diffusers_workflow-0.4.0a12/dw/server/ui/assets/mdx-QE70XlV0.js +1 -1
- diffusers_workflow-0.4.0a10/dw/server/ui/assets/monaco-ZMCk_MWf.js → diffusers_workflow-0.4.0a12/dw/server/ui/assets/monaco-CzCru1EC.js +4 -4
- diffusers_workflow-0.4.0a10/dw/server/ui/assets/python-0FnO4xGM.js → diffusers_workflow-0.4.0a12/dw/server/ui/assets/python-DxHS-kHp.js +1 -1
- diffusers_workflow-0.4.0a10/dw/server/ui/assets/razor-B6PMzeY4.js → diffusers_workflow-0.4.0a12/dw/server/ui/assets/razor-CT5Qrhwg.js +1 -1
- diffusers_workflow-0.4.0a10/dw/server/ui/assets/tsMode-nxyvZH1t.js → diffusers_workflow-0.4.0a12/dw/server/ui/assets/tsMode-qXdDdnF1.js +1 -1
- diffusers_workflow-0.4.0a10/dw/server/ui/assets/typescript-BhBe8aGf.js → diffusers_workflow-0.4.0a12/dw/server/ui/assets/typescript-BWfJagji.js +1 -1
- diffusers_workflow-0.4.0a10/dw/server/ui/assets/workers-ChAf-t8A.js → diffusers_workflow-0.4.0a12/dw/server/ui/assets/workers-C9vxrwoC.js +1 -1
- diffusers_workflow-0.4.0a10/dw/server/ui/assets/xml-z2r9dHSO.js → diffusers_workflow-0.4.0a12/dw/server/ui/assets/xml-DhJEwsDK.js +1 -1
- diffusers_workflow-0.4.0a10/dw/server/ui/assets/yaml-DrcHrz7f.js → diffusers_workflow-0.4.0a12/dw/server/ui/assets/yaml-CiixMxAq.js +1 -1
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/server/ui/index.html +2 -2
- diffusers_workflow-0.4.0a12/dw/server/updater.py +192 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/type_helpers.py +12 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/validate.py +13 -1
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/variables.py +92 -38
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/workflow.py +54 -7
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw_mcp/__main__.py +9 -1
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw_mcp/client.py +14 -2
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw_mcp/diagnose.py +50 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw_mcp/server.py +11 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/pyproject.toml +1 -1
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/tests/test_cli.py +18 -1
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/tests/test_mcp_client.py +39 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/tests/test_mcp_diagnose.py +82 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/tests/test_mcp_server.py +13 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/tests/test_modular_pipeline.py +88 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/tests/test_phase_events.py +77 -1
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/tests/test_security.py +40 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/tests/test_server.py +542 -11
- diffusers_workflow-0.4.0a12/tests/test_updater.py +126 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/tests/test_variables.py +61 -15
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/tests/test_workflow.py +96 -0
- diffusers_workflow-0.4.0a12/tests/test_workflow_trust.py +237 -0
- diffusers_workflow-0.4.0a10/dw/schema.py +0 -24
- diffusers_workflow-0.4.0a10/dw/server/ui/assets/index-D7eWnTCB.css +0 -1
- diffusers_workflow-0.4.0a10/dw/server/ui/assets/index-JyFxgIR9.js +0 -20
- diffusers_workflow-0.4.0a10/dw/server/updater.py +0 -119
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/LICENSE +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/MANIFEST.in +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/diffusers_workflow.egg-info/dependency_links.txt +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/diffusers_workflow.egg-info/entry_points.txt +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/diffusers_workflow.egg-info/requires.txt +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/diffusers_workflow.egg-info/top_level.txt +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/arguments.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/cache_blocks.json +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/cache_blocks.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/community_pipelines/pipeline_flux_rf_inversion.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/hub_cache.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/introspection.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/log_setup.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/pipeline_processors/chain.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/pipeline_processors/config_objects.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/pipeline_processors/remote.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/previous_results.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/prompt_schema.json +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/prompt_weighting.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/prompts.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/repl_commands.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/repl_worker.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/result.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/server/__init__.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/server/enhancers.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/abap-08VXUWAP.js +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/apex-BWPQTe0t.js +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/azcli-Bc_sGQ0U.js +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/bat-i0X4ZdIN.js +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/bicep-B5-_aFwp.js +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/cameligo-DMUM7wLl.js +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/clojure-Cm7r79vr.js +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/codicon-Brq4_Ui5.ttf +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/coffee-Ba7i2nA0.js +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/cpp-C7h46wYY.js +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/csharp-BKxtCVv1.js +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/csp-bTuwJoIa.js +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/css-DIMkf-bt.js +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/css.worker-B3ciXF_0.js +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/cypher-CVaqCwHa.js +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/dart-onAF5SnQ.js +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/dockerfile-DZFCIeNp.js +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/ecl-D05T4iGw.js +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/editor-jjEx9u7D.css +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/editor.worker-q-txB4vs.js +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/elixir-6RTg0lbw.js +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/flow9-C5_-GSwl.js +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/fsharp-C8Ef5oNN.js +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/go-C-y9NEjX.js +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/graphql-fmXr3nnJ.js +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/hcl-CpzslTdj.js +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/html.worker-C93Ht9o9.js +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/ini-sBoK_t0W.js +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/java-BEtHBSE6.js +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/json.worker-B2V3pomh.js +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/julia-Bri6UV-V.js +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/kotlin-BOotOW0E.js +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/less-B9JPFI3C.js +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/lexon-CfSJPG6W.js +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/lua-CsQS60Ue.js +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/m3-D-oSqn_W.js +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/markdown-Cimd5fb3.js +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/mips-CIPQ_RoX.js +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/monaco--ixms01u.css +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/msdax-DauUninz.js +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/mysql-SOo6toE5.js +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/objective-c-FvmIjYaQ.js +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/pascal-DrH0SRf2.js +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/pascaligo-D-ptJ9y-.js +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/perl-oz_6vUea.js +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/pgsql-DTj74zXo.js +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/php-nr791fC2.js +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/pla-CopQ2nXW.js +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/postiats-43DmfD33.js +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/powerquery-D3hlyOfw.js +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/powershell-DmHpPYUd.js +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/protobuf-C531GsRP.js +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/pug-Z5eAx3Zn.js +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/qsharp-DkqhCAOL.js +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/r-BwWrilGY.js +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/redis-ClamHrr6.js +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/redshift-DT7zqm-g.js +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/restructuredtext-BYgofb2h.js +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/ruby-DezsRK8O.js +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/rust-DdL9SqIa.js +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/sb-CcwsVR0C.js +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/scala-DHpiXF5c.js +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/scheme-BeGwcela.js +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/scss-gp-XZpBa.js +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/shell-CC2rA5mh.js +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/solidity-BEEn4gHE.js +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/sophia-CRfGWb83.js +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/sparql-D_Lu-MrJ.js +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/sql-NEE52Syq.js +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/st-DbInun42.js +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/swift-Bxkupp3x.js +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/systemverilog-Bz4Y3fRF.js +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/tcl-DISqw1ZD.js +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/ts.worker-D7T1-Ig5.js +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/twig-De2hgUGE.js +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/typespec-B8J7ngcE.js +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/vb-DV3o63ZY.js +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/server/ui/assets/wgsl-DpFanUEy.js +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/settings.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/step.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/tasks/audio_utils.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/tasks/background_remover.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/tasks/borders.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/tasks/concat_videos.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/tasks/depth_estimator.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/tasks/diffusion_upscale.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/tasks/format_messages.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/tasks/gather.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/tasks/image_to_text.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/tasks/image_utils.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/tasks/interpolate_frames.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/tasks/model_cache.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/tasks/pair_audio.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/tasks/qr_code.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/tasks/restore_faces.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/tasks/rife_model.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/tasks/segment.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/tasks/task.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/tasks/tensor_image.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/tasks/text_generation.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/tasks/text_sections.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/tasks/upscale.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/tasks/video_utils.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/tasks/zoe_depth.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/teacache.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/teacache_models.json +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/test.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/worker.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/workflow_schema.json +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/workflows/augment_prompt.json +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/workflows/describe_image.json +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/workflows/h3_context_ir.json +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/workflows/test.json +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw_mcp/__init__.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw_mcp/authoring.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw_mcp/catalog.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw_mcp/media.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw_mcp/models.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw_mcp/prompts.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/setup.cfg +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/tests/test_argument_updates.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/tests/test_arguments.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/tests/test_audio_utils.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/tests/test_borders.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/tests/test_cache_blocks.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/tests/test_chain.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/tests/test_component_pruning.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/tests/test_concat_videos.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/tests/test_config_objects.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/tests/test_configuration_schema.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/tests/test_depth_estimator.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/tests/test_device.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/tests/test_device_helpers.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/tests/test_device_portability.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/tests/test_diffusion_upscale.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/tests/test_docs_links.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/tests/test_events.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/tests/test_examples.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/tests/test_gather.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/tests/test_hub_cache.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/tests/test_image_to_text.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/tests/test_image_utils.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/tests/test_integration.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/tests/test_interpolate_frames.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/tests/test_introspection.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/tests/test_list_images.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/tests/test_mcp_authoring.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/tests/test_mcp_catalog.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/tests/test_mcp_media.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/tests/test_mcp_models.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/tests/test_mcp_prompts.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/tests/test_model_cache.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/tests/test_offload_placement.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/tests/test_pair_audio.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/tests/test_pipeline_caching.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/tests/test_pipeline_components.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/tests/test_previous_results.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/tests/test_prompt_parser.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/tests/test_prompt_weighting.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/tests/test_prompts.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/tests/test_repl_commands.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/tests/test_repl_ergonomics.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/tests/test_repl_hierarchical.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/tests/test_repl_reorganization.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/tests/test_repl_worker.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/tests/test_resize_bucket.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/tests/test_result.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/tests/test_scheduler_config.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/tests/test_schema.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/tests/test_segment.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/tests/test_step.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/tests/test_strip_exif_and_watermark.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/tests/test_task.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/tests/test_task_discovery.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/tests/test_teacache.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/tests/test_tensor_image.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/tests/test_text_generation.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/tests/test_text_sections.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/tests/test_type_helpers.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/tests/test_video_utils.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/tests/test_worker.py +0 -0
- {diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/tests/test_worker_execute.py +0 -0
{diffusers_workflow-0.4.0a10/diffusers_workflow.egg-info → diffusers_workflow-0.4.0a12}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: diffusers-workflow
|
|
3
|
-
Version: 0.4.
|
|
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
|
|
@@ -79,6 +79,8 @@ Dynamic: license-file
|
|
|
79
79
|
|
|
80
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.
|
|
81
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
|
+
|
|
82
84
|
**Python 3.10-3.14 | CUDA (NVIDIA) | MPS (Apple Silicon) | CPU**
|
|
83
85
|
|
|
84
86
|
<picture>
|
|
@@ -92,7 +94,7 @@ A declarative workflow engine and web UI for the [Hugging Face Diffusers library
|
|
|
92
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).
|
|
93
95
|
- **Declarative JSON workflows** with variable substitution and cross-step data flow
|
|
94
96
|
- **Multi-step pipelines** — chain text-to-image, image-to-video, inpainting, ControlNet
|
|
95
|
-
- **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)
|
|
96
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
|
|
97
99
|
- **Quantization** — BitsAndBytes, TorchAO, GGUF, SDNQ, optimum-quanto
|
|
98
100
|
- **Inference acceleration** — TeaCache, FirstBlockCache, FasterCache, MagCache, TaylorSeerCache
|
|
@@ -153,15 +155,26 @@ Jobs queue, stream progress live (per denoising step), cancel cooperatively, and
|
|
|
153
155
|
|
|
154
156
|
### Run a Workflow
|
|
155
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
|
+
|
|
156
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
|
|
157
169
|
python -m dw.run workflows/flux/FluxDev.json
|
|
158
|
-
python -m dw.run workflows/flux/FluxDev.json prompt="a cat" num_images_per_prompt=4
|
|
159
170
|
```
|
|
160
171
|
|
|
172
|
+
Without this, the run fails partway through with an HTTP 401/403 from the Hub.
|
|
173
|
+
|
|
161
174
|
### Validate a Workflow
|
|
162
175
|
|
|
163
176
|
```bash
|
|
164
|
-
python -m dw.validate workflows/
|
|
177
|
+
python -m dw.validate workflows/sd15.json
|
|
165
178
|
```
|
|
166
179
|
|
|
167
180
|
### Interactive REPL
|
|
@@ -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>
|
|
@@ -17,7 +19,7 @@ A declarative workflow engine and web UI for the [Hugging Face Diffusers library
|
|
|
17
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).
|
|
18
20
|
- **Declarative JSON workflows** with variable substitution and cross-step data flow
|
|
19
21
|
- **Multi-step pipelines** — chain text-to-image, image-to-video, inpainting, ControlNet
|
|
20
|
-
- **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)
|
|
21
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
|
|
22
24
|
- **Quantization** — BitsAndBytes, TorchAO, GGUF, SDNQ, optimum-quanto
|
|
23
25
|
- **Inference acceleration** — TeaCache, FirstBlockCache, FasterCache, MagCache, TaylorSeerCache
|
|
@@ -78,15 +80,26 @@ Jobs queue, stream progress live (per denoising step), cancel cooperatively, and
|
|
|
78
80
|
|
|
79
81
|
### Run a Workflow
|
|
80
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
|
+
|
|
81
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
|
|
82
94
|
python -m dw.run workflows/flux/FluxDev.json
|
|
83
|
-
python -m dw.run workflows/flux/FluxDev.json prompt="a cat" num_images_per_prompt=4
|
|
84
95
|
```
|
|
85
96
|
|
|
97
|
+
Without this, the run fails partway through with an HTTP 401/403 from the Hub.
|
|
98
|
+
|
|
86
99
|
### Validate a Workflow
|
|
87
100
|
|
|
88
101
|
```bash
|
|
89
|
-
python -m dw.validate workflows/
|
|
102
|
+
python -m dw.validate workflows/sd15.json
|
|
90
103
|
```
|
|
91
104
|
|
|
92
105
|
### Interactive REPL
|
{diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12/diffusers_workflow.egg-info}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: diffusers-workflow
|
|
3
|
-
Version: 0.4.
|
|
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
|
|
@@ -79,6 +79,8 @@ Dynamic: license-file
|
|
|
79
79
|
|
|
80
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.
|
|
81
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
|
+
|
|
82
84
|
**Python 3.10-3.14 | CUDA (NVIDIA) | MPS (Apple Silicon) | CPU**
|
|
83
85
|
|
|
84
86
|
<picture>
|
|
@@ -92,7 +94,7 @@ A declarative workflow engine and web UI for the [Hugging Face Diffusers library
|
|
|
92
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).
|
|
93
95
|
- **Declarative JSON workflows** with variable substitution and cross-step data flow
|
|
94
96
|
- **Multi-step pipelines** — chain text-to-image, image-to-video, inpainting, ControlNet
|
|
95
|
-
- **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)
|
|
96
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
|
|
97
99
|
- **Quantization** — BitsAndBytes, TorchAO, GGUF, SDNQ, optimum-quanto
|
|
98
100
|
- **Inference acceleration** — TeaCache, FirstBlockCache, FasterCache, MagCache, TaylorSeerCache
|
|
@@ -153,15 +155,26 @@ Jobs queue, stream progress live (per denoising step), cancel cooperatively, and
|
|
|
153
155
|
|
|
154
156
|
### Run a Workflow
|
|
155
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
|
+
|
|
156
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
|
|
157
169
|
python -m dw.run workflows/flux/FluxDev.json
|
|
158
|
-
python -m dw.run workflows/flux/FluxDev.json prompt="a cat" num_images_per_prompt=4
|
|
159
170
|
```
|
|
160
171
|
|
|
172
|
+
Without this, the run fails partway through with an HTTP 401/403 from the Hub.
|
|
173
|
+
|
|
161
174
|
### Validate a Workflow
|
|
162
175
|
|
|
163
176
|
```bash
|
|
164
|
-
python -m dw.validate workflows/
|
|
177
|
+
python -m dw.validate workflows/sd15.json
|
|
165
178
|
```
|
|
166
179
|
|
|
167
180
|
### Interactive REPL
|
{diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/diffusers_workflow.egg-info/SOURCES.txt
RENAMED
|
@@ -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-
|
|
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-
|
|
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-
|
|
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-
|
|
81
|
+
dw/server/ui/assets/handlebars-BhleeD_A.js
|
|
82
82
|
dw/server/ui/assets/hcl-CpzslTdj.js
|
|
83
|
-
dw/server/ui/assets/html-
|
|
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-
|
|
86
|
-
dw/server/ui/assets/index-
|
|
87
|
-
dw/server/ui/assets/index-
|
|
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-
|
|
90
|
+
dw/server/ui/assets/javascript-BTuzJzdO.js
|
|
91
91
|
dw/server/ui/assets/json.worker-B2V3pomh.js
|
|
92
|
-
dw/server/ui/assets/jsonMode-
|
|
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-
|
|
98
|
-
dw/server/ui/assets/lspLanguageFeatures-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
143
|
+
dw/server/ui/assets/tsMode-qXdDdnF1.js
|
|
144
144
|
dw/server/ui/assets/twig-De2hgUGE.js
|
|
145
|
-
dw/server/ui/assets/typescript-
|
|
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-
|
|
150
|
-
dw/server/ui/assets/xml-
|
|
151
|
-
dw/server/ui/assets/yaml-
|
|
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
|
|
@@ -254,8 +254,10 @@ tests/test_tensor_image.py
|
|
|
254
254
|
tests/test_text_generation.py
|
|
255
255
|
tests/test_text_sections.py
|
|
256
256
|
tests/test_type_helpers.py
|
|
257
|
+
tests/test_updater.py
|
|
257
258
|
tests/test_variables.py
|
|
258
259
|
tests/test_video_utils.py
|
|
259
260
|
tests/test_worker.py
|
|
260
261
|
tests/test_worker_execute.py
|
|
261
|
-
tests/test_workflow.py
|
|
262
|
+
tests/test_workflow.py
|
|
263
|
+
tests/test_workflow_trust.py
|
|
@@ -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
|
-
#
|
|
33
|
-
#
|
|
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
|
|
@@ -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):
|
|
@@ -82,6 +96,11 @@ def deactivate_context(token):
|
|
|
82
96
|
# the run is waiting on, not what any one library is doing internally
|
|
83
97
|
PHASES = ("loading", "cached", "generating", "decoding", "saving", "task")
|
|
84
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
|
+
|
|
85
104
|
|
|
86
105
|
def emit_phase(phase, detail=None):
|
|
87
106
|
"""Report a coarse phase change on the active run.
|
|
@@ -92,4 +111,6 @@ def emit_phase(phase, detail=None):
|
|
|
92
111
|
enough (a handful per step) to carry a free-text detail alongside, which
|
|
93
112
|
is what makes 'loading' readable as 'which model'.
|
|
94
113
|
"""
|
|
95
|
-
|
|
114
|
+
context = get_context()
|
|
115
|
+
context.note_phase(phase)
|
|
116
|
+
context.emit("phase", phase=phase, detail=detail)
|
{diffusers_workflow-0.4.0a10 → diffusers_workflow-0.4.0a12}/dw/pipeline_processors/pipeline.py
RENAMED
|
@@ -16,6 +16,10 @@ from .remote import remote_text_encoder
|
|
|
16
16
|
from ..cache_blocks import register_cache_blocks
|
|
17
17
|
from ..teacache import teacache_context
|
|
18
18
|
from ..type_helpers import has_method
|
|
19
|
+
from ..security import (
|
|
20
|
+
require_trusted_from_pretrained_arguments,
|
|
21
|
+
require_trusted_pre_load_modules,
|
|
22
|
+
)
|
|
19
23
|
from .. import empty_device_cache, get_device_type, resolve_device
|
|
20
24
|
from diffusers import attention_backend
|
|
21
25
|
|
|
@@ -23,6 +27,7 @@ from diffusers import attention_backend
|
|
|
23
27
|
# imported where they are used - at module scope they add seconds to every startup
|
|
24
28
|
|
|
25
29
|
from ..events import WorkflowCancelled, emit_phase, get_context
|
|
30
|
+
from huggingface_hub.errors import HfHubHTTPError
|
|
26
31
|
|
|
27
32
|
logger = logging.getLogger("dw")
|
|
28
33
|
|
|
@@ -224,8 +229,12 @@ class Pipeline:
|
|
|
224
229
|
logger.debug(f"Loading pipeline: {self.name}")
|
|
225
230
|
|
|
226
231
|
# Import modules that need to register with diffusers/transformers before loading
|
|
227
|
-
# (e.g., sdnq registers its quantization method on import)
|
|
228
|
-
|
|
232
|
+
# (e.g., sdnq registers its quantization method on import). This runs
|
|
233
|
+
# arbitrary python at import time, so an untrusted workflow is refused
|
|
234
|
+
# here unless --trust-workflows was passed - see docs/SECURITY.md
|
|
235
|
+
pre_load_modules = self.configuration.get("pre_load_modules", [])
|
|
236
|
+
require_trusted_pre_load_modules(pre_load_modules)
|
|
237
|
+
for module_name in pre_load_modules:
|
|
229
238
|
logger.info(f"Pre-loading module: {module_name}")
|
|
230
239
|
importlib.import_module(module_name)
|
|
231
240
|
|
|
@@ -1509,6 +1518,10 @@ def load_component(
|
|
|
1509
1518
|
component_type = configuration["component_type"]
|
|
1510
1519
|
component = None
|
|
1511
1520
|
|
|
1521
|
+
# Refused before anything reaches the Hub: an untrusted workflow must not
|
|
1522
|
+
# be able to have diffusers fetch and run code on its behalf
|
|
1523
|
+
require_trusted_from_pretrained_arguments(from_pretrained_arguments, component_name)
|
|
1524
|
+
|
|
1512
1525
|
# A standard pipeline takes a component as a constructor argument. A modular one
|
|
1513
1526
|
# cannot: it is built from the component specs in its own index and given the
|
|
1514
1527
|
# objects afterwards, which is also what keeps load_components() from pulling a
|
|
@@ -1537,6 +1550,7 @@ def load_component(
|
|
|
1537
1550
|
f"Consider changing torch_dtype from float16 to float32 for {component_name} "
|
|
1538
1551
|
)
|
|
1539
1552
|
|
|
1553
|
+
model_name = None
|
|
1540
1554
|
try:
|
|
1541
1555
|
with loading_device(configuration):
|
|
1542
1556
|
# Load from model name
|
|
@@ -1600,12 +1614,44 @@ def load_component(
|
|
|
1600
1614
|
)
|
|
1601
1615
|
|
|
1602
1616
|
except Exception as e:
|
|
1603
|
-
#
|
|
1604
|
-
#
|
|
1617
|
+
# 401/403 from the Hub means the account behind whatever token (or
|
|
1618
|
+
# lack of one) HfApi is using cannot read this repo - almost always
|
|
1619
|
+
# a gated model the user has not requested access to, or has not
|
|
1620
|
+
# logged in for. A whole-pipeline load raises the HfHubHTTPError
|
|
1621
|
+
# itself; a per-component load gets it wrapped in an EnvironmentError
|
|
1622
|
+
# by diffusers' _get_model_file / transformers' cached_file, so the
|
|
1623
|
+
# cause chain is searched. Every other error (a real outage, a bad
|
|
1624
|
+
# repo id) is logged once with its traceback and re-raised unchanged
|
|
1625
|
+
if _hub_auth_status(e) is not None:
|
|
1626
|
+
repo = model_name or component_name
|
|
1627
|
+
logger.error(
|
|
1628
|
+
f"Hugging Face authentication required loading {component_name} "
|
|
1629
|
+
f"({repo}): {e}",
|
|
1630
|
+
exc_info=True,
|
|
1631
|
+
)
|
|
1632
|
+
raise RuntimeError(
|
|
1633
|
+
f"Model '{repo}' requires Hugging Face authentication - run "
|
|
1634
|
+
f"'huggingface-cli login', or request access at "
|
|
1635
|
+
f"https://huggingface.co/{repo}"
|
|
1636
|
+
) from e
|
|
1605
1637
|
logger.error(f"{type(e).__name__} loading {component_name}: {e}", exc_info=True)
|
|
1606
1638
|
raise
|
|
1607
1639
|
|
|
1608
1640
|
|
|
1641
|
+
def _hub_auth_status(error):
|
|
1642
|
+
"""The 401/403 status an exception (or anything in its cause/context
|
|
1643
|
+
chain) carries from the Hub, else None."""
|
|
1644
|
+
seen = set()
|
|
1645
|
+
while error is not None and id(error) not in seen:
|
|
1646
|
+
seen.add(id(error))
|
|
1647
|
+
if isinstance(error, HfHubHTTPError):
|
|
1648
|
+
status = getattr(getattr(error, "response", None), "status_code", None)
|
|
1649
|
+
if status in (401, 403):
|
|
1650
|
+
return status
|
|
1651
|
+
error = error.__cause__ or error.__context__
|
|
1652
|
+
return None
|
|
1653
|
+
|
|
1654
|
+
|
|
1609
1655
|
def apply_sdnq_optimizations(pipeline, component_names):
|
|
1610
1656
|
"""Apply SDNQ quantized matmul optimization to pipeline components.
|
|
1611
1657
|
|
|
@@ -278,8 +278,26 @@ def main():
|
|
|
278
278
|
default="INFO",
|
|
279
279
|
help="Set the logging level (DEBUG, INFO, WARNING, ERROR, CRITICAL)",
|
|
280
280
|
)
|
|
281
|
+
parser.add_argument(
|
|
282
|
+
"--trust-workflows",
|
|
283
|
+
action="store_true",
|
|
284
|
+
default=False,
|
|
285
|
+
help="Trust every workflow loaded this session to execute arbitrary "
|
|
286
|
+
"Python: allow pre_load_modules and any dotted "
|
|
287
|
+
"*_type/*_dtype/dtype/config_type value, not just ones inside the "
|
|
288
|
+
"diffusers/torch/transformers/quantization-backend ecosystem the "
|
|
289
|
+
"tool already depends on. Off by default - see docs/SECURITY.md's "
|
|
290
|
+
"Trust model.",
|
|
291
|
+
)
|
|
281
292
|
args = parser.parse_args()
|
|
282
293
|
|
|
294
|
+
# Set before the worker subprocess is ever spawned - 'spawn' launches a
|
|
295
|
+
# fresh interpreter that inherits this environment variable, so
|
|
296
|
+
# 'workflow load/run' in the worker sees the same trust choice
|
|
297
|
+
from .security import set_trust_workflows
|
|
298
|
+
|
|
299
|
+
set_trust_workflows(args.trust_workflows)
|
|
300
|
+
|
|
283
301
|
# Initialize logging
|
|
284
302
|
startup(args.log_level)
|
|
285
303
|
|
|
@@ -7,6 +7,7 @@ from .security import (
|
|
|
7
7
|
validate_output_path,
|
|
8
8
|
validate_variable_name,
|
|
9
9
|
validate_string_input,
|
|
10
|
+
set_trust_workflows,
|
|
10
11
|
SecurityError,
|
|
11
12
|
MAX_VARIABLE_VALUE_LENGTH,
|
|
12
13
|
)
|
|
@@ -44,6 +45,17 @@ def main():
|
|
|
44
45
|
"DW_PROMPT_DIR, else ./prompts if it exists, else the nearest "
|
|
45
46
|
"prompts/ above the workflow file)",
|
|
46
47
|
)
|
|
48
|
+
parser.add_argument(
|
|
49
|
+
"--trust-workflows",
|
|
50
|
+
action="store_true",
|
|
51
|
+
default=False,
|
|
52
|
+
help="Trust this workflow file to execute arbitrary Python: allow "
|
|
53
|
+
"pre_load_modules and any dotted *_type/*_dtype/dtype/config_type "
|
|
54
|
+
"value, not just ones inside the diffusers/torch/transformers/"
|
|
55
|
+
"quantization-backend ecosystem the tool already depends on. Off "
|
|
56
|
+
"by default - see docs/SECURITY.md's Trust model. Only pass this "
|
|
57
|
+
"for a workflow file whose source you trust.",
|
|
58
|
+
)
|
|
47
59
|
# parse_intermixed_args, not parse_args: argparse splits positionals into
|
|
48
60
|
# groups around an option, and with a nargs='*' positional that means
|
|
49
61
|
# 'dw-run wf.json -o outputs prompt=cat' - an option between the file
|
|
@@ -53,6 +65,8 @@ def main():
|
|
|
53
65
|
if args.prompt_dir:
|
|
54
66
|
os.environ["DW_PROMPT_DIR"] = os.path.abspath(args.prompt_dir)
|
|
55
67
|
|
|
68
|
+
set_trust_workflows(args.trust_workflows)
|
|
69
|
+
|
|
56
70
|
# Parse key-value pairs with validation
|
|
57
71
|
variables = {}
|
|
58
72
|
for variable in args.variables:
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import os
|
|
3
|
+
from jsonschema import validate, ValidationError
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def validate_data(data, schema):
|
|
7
|
+
try:
|
|
8
|
+
validate(instance=data, schema=schema)
|
|
9
|
+
return True, "Validation successful"
|
|
10
|
+
|
|
11
|
+
except ValidationError as ve:
|
|
12
|
+
path = json_path(ve.absolute_path)
|
|
13
|
+
location = f" at {path}" if path else ""
|
|
14
|
+
return False, f"Validation error{location}: {ve.message}"
|
|
15
|
+
except json.JSONDecodeError as je:
|
|
16
|
+
return False, f"JSON parsing error: {str(je)}"
|
|
17
|
+
except Exception as e:
|
|
18
|
+
return False, f"Unexpected error: {str(e)}"
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def json_path(absolute_path):
|
|
22
|
+
"""Render a jsonschema ValidationError's absolute_path (a deque of dict
|
|
23
|
+
keys and list indices) as a dotted/bracket path, e.g.
|
|
24
|
+
steps[0].pipeline.arguments.prompt. None if the error is at the root."""
|
|
25
|
+
if not absolute_path:
|
|
26
|
+
return None
|
|
27
|
+
parts = []
|
|
28
|
+
for element in absolute_path:
|
|
29
|
+
if isinstance(element, int):
|
|
30
|
+
parts.append(f"[{element}]")
|
|
31
|
+
elif not parts:
|
|
32
|
+
parts.append(str(element))
|
|
33
|
+
else:
|
|
34
|
+
parts.append(f".{element}")
|
|
35
|
+
return "".join(parts)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def load_schema(schema_name):
|
|
39
|
+
file_spec = os.path.join(
|
|
40
|
+
os.path.dirname(os.path.abspath(__file__)), f"{schema_name}_schema.json"
|
|
41
|
+
)
|
|
42
|
+
with open(file_spec, "r") as file:
|
|
43
|
+
return json.load(file)
|