diffusers-workflow 0.8.0__tar.gz → 0.9.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {diffusers_workflow-0.8.0/diffusers_workflow.egg-info → diffusers_workflow-0.9.0}/PKG-INFO +1 -1
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0/diffusers_workflow.egg-info}/PKG-INFO +1 -1
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/docs/MCP.md +1 -1
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/docs/RELEASING.md +60 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/docs/REMOTE.md +5 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/plan.py +67 -13
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/routes/jobs.py +7 -5
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/tasks/joins.py +10 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw_mcp/exports.py +15 -12
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw_mcp/tools_jobs.py +10 -11
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/pyproject.toml +1 -1
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_assemble_and_score_target_lufs.py +12 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_concat_videos.py +17 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_mcp_exports.py +11 -4
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_mcp_server.py +8 -7
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_plan.py +81 -4
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_plugin_skills.py +35 -2
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_server_exports.py +15 -6
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/LICENSE +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/MANIFEST.in +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/README.md +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/diffusers_workflow.egg-info/SOURCES.txt +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/diffusers_workflow.egg-info/dependency_links.txt +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/diffusers_workflow.egg-info/entry_points.txt +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/diffusers_workflow.egg-info/requires.txt +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/diffusers_workflow.egg-info/top_level.txt +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/__init__.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/adapter_compatibility.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/argument_media.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/argument_warnings.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/arguments.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/assessment_rules.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/assets.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/audio_qc.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/cache_blocks.json +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/cache_blocks.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/community_pipelines/pipeline_flux_rf_inversion.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/content_types.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/dissolve_frame_errors.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/docs/ACCELERATION.md +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/docs/AGENT_LOOP.md +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/docs/ARCHITECTURE.md +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/docs/DEPENDENCIES.md +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/docs/IP_ADAPTER.md +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/docs/LORAS.md +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/docs/PROMPT_WEIGHTING.md +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/docs/QUANTIZATION.md +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/docs/RECIPES_24GB.md +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/docs/SECURITY.md +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/docs/SECURITY_QUICKREF.md +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/docs/SERVER.md +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/docs/TASKS.md +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/docs/TESTING.md +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/docs/WORKER_GUIDE.md +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/docs/WORKFLOW_GUIDE.md +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/docs/WORKSPACES.md +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/download_watch.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/dsp.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/elision.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/events.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/for_each.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/host_memory.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/host_memory_projection.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/hub_cache.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/introspection.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/kernel_availability.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/library.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/locations.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/log_setup.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/lora_catalog.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/lora_catalog_schema.json +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/lora_hub.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/media.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/media_frames.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/media_types.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/output_extraction.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/path_redaction.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/pipeline_ownership.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/pipeline_processors/adapters.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/pipeline_processors/chain.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/pipeline_processors/components.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/pipeline_processors/config_objects.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/pipeline_processors/pipeline.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/pipeline_processors/placement.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/pipeline_processors/progress.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/pipeline_processors/remote.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/previous_results.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/probe_paths.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/prompt_schema.json +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/prompt_weighting.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/prompts.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/realize.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/reference_limits.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/reference_names.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/references.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/result.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/run.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/runs.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/scalar_result_validation.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/schema.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/security.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/serve.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/__init__.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/admission.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/api_models.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/app.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/assess.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/catalog.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/catalog_shape.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/deps.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/enhancers.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/exports.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/guides.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/http_security.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/inline_media.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/job_history.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/job_record.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/jobs.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/mcp_mount.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/netinfo.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/observed_cost.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/outputs.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/routes/__init__.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/routes/assets.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/routes/files.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/routes/gallery.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/routes/library.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/routes/loras.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/routes/media.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/routes/system.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/sysinfo.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/ui/assets/abap-08VXUWAP.js +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/ui/assets/apex-BWPQTe0t.js +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/ui/assets/azcli-Bc_sGQ0U.js +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/ui/assets/bat-i0X4ZdIN.js +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/ui/assets/bicep-B5-_aFwp.js +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/ui/assets/cameligo-DMUM7wLl.js +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/ui/assets/clojure-Cm7r79vr.js +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/ui/assets/codicon-Brq4_Ui5.ttf +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/ui/assets/coffee-Ba7i2nA0.js +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/ui/assets/cpp-C7h46wYY.js +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/ui/assets/csharp-BKxtCVv1.js +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/ui/assets/csp-bTuwJoIa.js +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/ui/assets/css-DIMkf-bt.js +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/ui/assets/css.worker-B3ciXF_0.js +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/ui/assets/cssMode-C1mrKegs.js +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/ui/assets/cypher-CVaqCwHa.js +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/ui/assets/dart-onAF5SnQ.js +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/ui/assets/dockerfile-DZFCIeNp.js +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/ui/assets/ecl-D05T4iGw.js +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/ui/assets/editor-jjEx9u7D.css +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/ui/assets/editor.api-EZbUgQvM.js +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/ui/assets/editor.worker-q-txB4vs.js +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/ui/assets/elixir-6RTg0lbw.js +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/ui/assets/flow9-C5_-GSwl.js +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/ui/assets/freemarker2-Dth1K2Vy.js +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/ui/assets/fsharp-C8Ef5oNN.js +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/ui/assets/go-C-y9NEjX.js +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/ui/assets/graphql-fmXr3nnJ.js +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/ui/assets/handlebars-8Sswqnxq.js +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/ui/assets/hcl-CpzslTdj.js +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/ui/assets/html-BYtYo7f1.js +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/ui/assets/html.worker-C93Ht9o9.js +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/ui/assets/htmlMode-B_AiWoXc.js +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/ui/assets/index-B6Ujrvuj.js +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/ui/assets/index-BChhQc7I.css +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/ui/assets/ini-sBoK_t0W.js +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/ui/assets/java-BEtHBSE6.js +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/ui/assets/javascript-E4m083D3.js +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/ui/assets/json.worker-B2V3pomh.js +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/ui/assets/jsonMode--h7ZikWy.js +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/ui/assets/julia-Bri6UV-V.js +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/ui/assets/kotlin-BOotOW0E.js +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/ui/assets/less-B9JPFI3C.js +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/ui/assets/lexon-CfSJPG6W.js +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/ui/assets/liquid-BzbKdLRW.js +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/ui/assets/lspLanguageFeatures-CRa0bRFV.js +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/ui/assets/lua-CsQS60Ue.js +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/ui/assets/m3-D-oSqn_W.js +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/ui/assets/markdown-Cimd5fb3.js +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/ui/assets/mdx-BJ4u6XQs.js +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/ui/assets/mips-CIPQ_RoX.js +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/ui/assets/monaco--ixms01u.css +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/ui/assets/monaco-DwaeaVri.js +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/ui/assets/msdax-DauUninz.js +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/ui/assets/mysql-SOo6toE5.js +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/ui/assets/objective-c-FvmIjYaQ.js +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/ui/assets/pascal-DrH0SRf2.js +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/ui/assets/pascaligo-D-ptJ9y-.js +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/ui/assets/perl-oz_6vUea.js +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/ui/assets/pgsql-DTj74zXo.js +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/ui/assets/php-nr791fC2.js +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/ui/assets/pla-CopQ2nXW.js +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/ui/assets/postiats-43DmfD33.js +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/ui/assets/powerquery-D3hlyOfw.js +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/ui/assets/powershell-DmHpPYUd.js +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/ui/assets/protobuf-C531GsRP.js +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/ui/assets/pug-Z5eAx3Zn.js +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/ui/assets/python-CoX_gCAL.js +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/ui/assets/qsharp-DkqhCAOL.js +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/ui/assets/r-BwWrilGY.js +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/ui/assets/razor-BCTdG5SN.js +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/ui/assets/redis-ClamHrr6.js +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/ui/assets/redshift-DT7zqm-g.js +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/ui/assets/restructuredtext-BYgofb2h.js +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/ui/assets/ruby-DezsRK8O.js +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/ui/assets/rust-DdL9SqIa.js +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/ui/assets/sb-CcwsVR0C.js +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/ui/assets/scala-DHpiXF5c.js +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/ui/assets/scheme-BeGwcela.js +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/ui/assets/scss-gp-XZpBa.js +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/ui/assets/shell-CC2rA5mh.js +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/ui/assets/solidity-BEEn4gHE.js +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/ui/assets/sophia-CRfGWb83.js +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/ui/assets/sparql-D_Lu-MrJ.js +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/ui/assets/sql-NEE52Syq.js +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/ui/assets/st-DbInun42.js +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/ui/assets/swift-Bxkupp3x.js +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/ui/assets/systemverilog-Bz4Y3fRF.js +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/ui/assets/tcl-DISqw1ZD.js +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/ui/assets/ts.worker-D7T1-Ig5.js +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/ui/assets/tsMode-B6BV7a76.js +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/ui/assets/twig-De2hgUGE.js +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/ui/assets/typescript-DJe7-fvZ.js +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/ui/assets/typespec-B8J7ngcE.js +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/ui/assets/vb-DV3o63ZY.js +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/ui/assets/wgsl-DpFanUEy.js +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/ui/assets/workers-DCzLJTPE.js +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/ui/assets/xml-CNvWfUrB.js +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/ui/assets/yaml-ByARP6WE.js +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/ui/index.html +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/server/updater.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/settings.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/shot_span_preflight.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/shots.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/slice_preflight.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/step.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/step_cache.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/step_value_checks.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/subfolders.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/task_domains.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/tasks/assess.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/tasks/audio_dynamics.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/tasks/audio_transcription.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/tasks/audio_utils.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/tasks/background_remover.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/tasks/borders.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/tasks/compose_text.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/tasks/concat_videos.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/tasks/depth_estimator.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/tasks/diffusion_upscale.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/tasks/dissolve_videos.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/tasks/format_messages.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/tasks/gather.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/tasks/grade.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/tasks/h3_latent_upscale.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/tasks/h3_latent_upscaler_model.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/tasks/image_to_text.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/tasks/image_utils.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/tasks/interpolate_frames.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/tasks/join_into_song.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/tasks/judge.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/tasks/loop_bed.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/tasks/model_cache.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/tasks/pair_audio.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/tasks/qr_code.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/tasks/restore_faces.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/tasks/rife_model.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/tasks/segment.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/tasks/select.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/tasks/speech_generation.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/tasks/stabilize.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/tasks/task.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/tasks/tensor_image.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/tasks/text_generation.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/tasks/text_sections.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/tasks/upscale.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/tasks/video_utils.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/tasks/voice_attribution.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/tasks/zoe_depth.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/test.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/trust.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/type_helpers.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/type_references.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/validate.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/validation.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/variable_constraints.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/variables.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/video_extensions.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/video_size_errors.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/vram_estimate.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/vram_inheritance.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/worker.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/worker_manager.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/worker_protocol.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/workflow.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/workflow_run.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/workflow_schema.json +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/workflows/h3_context_ir.json +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/workflows/test.json +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/workspace.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw/writers.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw_mcp/__init__.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw_mcp/__main__.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw_mcp/assets.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw_mcp/authoring.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw_mcp/catalog.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw_mcp/client.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw_mcp/confine.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw_mcp/diagnose.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw_mcp/guides.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw_mcp/loras.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw_mcp/media.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw_mcp/models.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw_mcp/prompts.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw_mcp/server.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw_mcp/tools_authoring.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw_mcp/tools_catalog.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw_mcp/tools_media.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/dw_mcp/workspaces.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/setup.cfg +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_admission.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_api_contract.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_arch_metrics.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_arch_report.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_architecture_map.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_argument_updates.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_arguments.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_assess.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_assessment_rules.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_assets.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_attention_slicing.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_audio_utils.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_best_of_n_template.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_borders.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_cache_blocks.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_catalog_shape.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_catalog_structure.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_chain.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_ci_config.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_cli.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_component_name_errors.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_component_pruning.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_component_type_errors.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_compose_text.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_config_objects.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_configuration_schema.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_content_types.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_depth_estimator.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_device.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_device_helpers.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_device_portability.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_dialogue_short_voices.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_diffusion_upscale.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_dissolve_frame_errors.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_dissolve_videos.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_docs_links.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_download_watch.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_dsp.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_elision.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_events.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_examples.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_find_loop_bed.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_for_each.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_gather.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_grade.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_h3_adapters.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_h3_context_ir.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_h3_latent_upscale.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_h3_schedule.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_h3_upscaler_source.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_h3_vram_ceiling.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_hf_placement.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_host_memory.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_host_memory_projection.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_hub_cache.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_image_to_text.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_image_utils.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_integration.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_interpolate_frames.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_introspection.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_job_history_wal.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_job_progress.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_job_warnings.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_jobs_listing.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_jobs_reused.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_join_into_song.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_judge.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_kernel_availability.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_library_path.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_library_sources.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_list_images.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_locations.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_lora_alpha.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_lora_catalog.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_lora_disable.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_lora_hub.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_lora_library.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_ltx2_diffusion_decode.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_ltx2_extend_clip.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_ltx2_ic_loras.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_ltx_prompt_library.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_mcp_assets.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_mcp_authoring.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_mcp_catalog.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_mcp_client.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_mcp_confine.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_mcp_diagnose.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_mcp_guides.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_mcp_loras.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_mcp_main.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_mcp_media.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_mcp_models.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_mcp_prompts.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_mcp_twins.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_mcp_workspaces.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_media_audio.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_media_frames.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_media_info.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_media_layering.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_mix_audio.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_model_cache.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_modular_output_properties.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_modular_pipeline.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_modular_progress.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_mps_fallback_warning.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_mps_rope_precision.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_null_media.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_observed_cost.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_offload_placement.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_output_references.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_pair_audio.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_pair_audio_fit.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_parallel_loading_default.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_path_redaction.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_phase_events.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_pipeline_caching.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_pipeline_components.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_prepare_pipeline.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_previous_result_walker_parity.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_previous_results.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_prompt_library.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_prompt_parser.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_prompt_references.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_prompt_weighting.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_prompts.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_real_models.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_realize.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_recenter_crop.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_reference_limits.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_reference_names.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_reference_skip_sets.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_references.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_rerun_new_seed.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_resize_bucket.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_result.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_result_fps.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_result_output_naming.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_rule_parity.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_runs.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_scalar_result_validation.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_scheduler_config.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_schema.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_security.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_security_auth.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_security_decoder_bombs.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_security_input_caps.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_security_ssrf.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_security_symlinks.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_security_trust_gate.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_security_web_headers.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_segment.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_select.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_select_validation.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_serve_main.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_server.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_server_assess.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_server_downloads.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_server_gallery_image.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_server_guides.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_server_info.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_server_jobs.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_server_library_path.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_server_loras.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_server_mcp.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_server_workspaces.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_shaping_logs.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_shot_span_preflight.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_shots.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_slice_preflight.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_speech_generation.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_stabilize.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_step.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_step_cache.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_strip_exif_and_watermark.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_sub_workflow_resolver.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_subfolders.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_task.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_task_discovery.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_task_domains.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_task_signature_errors.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_template_defaults.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_template_subfolders.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_tensor_image.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_text_generation.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_text_sections.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_transcribe_audio.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_type_helpers.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_ui_twins.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_updater.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_validate_arguments.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_validation.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_variable_constraints.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_variables.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_video_extensions.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_video_size_errors.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_video_utils.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_voice_attribution.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_vram_estimate.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_vram_inheritance.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_worker.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_worker_execute.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_worker_job_peak_rss.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_worker_manager.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_worker_messages.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_workflow.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_workflow_snapshot.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_workflow_step_cache.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_workflow_trust.py +0 -0
- {diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_workspace.py +0 -0
|
@@ -308,7 +308,7 @@ references written in the same session.
|
|
|
308
308
|
| `run_workflow(workflow_path=None, inline_workflow=None, arguments=None, acknowledged_cost=False, workspace=None, wait_seconds=0)` | exactly one of `workflow_path` (a catalog name from `list_workflows`, with or without `.json`, or a path to a workflow file on the server) or `inline_workflow`, optional `arguments`, `acknowledged_cost`, `workspace`, `wait_seconds` | Queue a workflow for generation. Returns as soon as the job is queued - unless `wait_seconds` is above 0, in which case the call then waits on the queued job exactly as `wait_for_job(job_id, timeout_seconds=wait_seconds)` would (same per-call cap, clamped not honoured) and the result carries the queued-job fields plus that wait's (`status`, `still_running`, `waited_seconds`, `timeout_requested_seconds`, `timeout_applied_seconds`, `timeout_capped`, the slim `job`); when the cap covers the job's runtime one call is the run and the wait, and a `still_running: true` result is followed with `wait_for_job` as before. `workspace` names the workspace for this one call without switching the session to it - use it to pin a job whose `output:` or `asset:` references live in a workspace other than the session's - `acknowledged_cost` is `true` or the bound `{fingerprint, minutes, downloads}` from the validate plan; a 409 means the plan changed and the message carries the new estimate, and nothing is waited on |
|
|
309
309
|
| `get_job(job_id)` | `job_id` | Get a job's status, warnings, output manifest, error and traceback; each manifest entry's `subfolder` is the in-run subfolder the step declared - by convention `final` for the deliverable, `intermediate` for scratch, `''` for none. A running job also carries `progress` (below) |
|
|
310
310
|
| `get_job_workflow(job_id)` | `job_id` | The REST equivalent is `GET /api/jobs/{id}/workflow` (see [SERVER.md](SERVER.md#jobs-api)). The workflow the job actually ran. `realized: true` means every mutable input is pinned (arguments, seed, prompts, `output:latest`); `false` means the job predates run tracking and this is the definition as submitted. Pass it to `save_workflow` to keep it under a name |
|
|
311
|
-
| `export_job(job_id, overwrite=False)` | `job_id`, `overwrite` | Gather one finished job into `<workspace>/exports/<job id>/` on the server: the realized workflow, the run's manifest, the job row, a README, and copies of the assets, earlier-run inputs and outputs. Returns the directory, a zip URL, the file list with sizes and the total. The three JSON files are in the zip, not repeated here - get_job_workflow and get_job serve them individually. **The directory is on the machine running the server**, like `download_output`'s destination.
|
|
311
|
+
| `export_job(job_id, overwrite=False)` | `job_id`, `overwrite` | Gather one finished job into `<workspace>/exports/<job id>/` on the server: the realized workflow, the run's manifest, the job row, a README, and copies of the assets, earlier-run inputs and outputs. Returns the directory, a zip URL, the file list with sizes and the total. The three JSON files are in the zip, not repeated here - get_job_workflow and get_job serve them individually. **The directory is on the machine running the server**, like `download_output`'s destination. The zip needs no token (`/exports/*.zip` is ungated like `/outputs`, #592), so `auth_required` is false and the agent fetches `open_url` itself (prefixing a relative one with the server address) and unpacks it into `exports/` under the session's working directory (a deliverable, not a temp file) - the archive already unpacks into one folder named after the job id, so do not create that folder first; only an agent without HTTP gives the user `open_url`. `true` is kept as a forward guard for a gated zip, when `open_url` is handed to the person instead |
|
|
312
312
|
| `get_job_events(job_id, after=-1, limit=200)` | `job_id`, `after`, `limit` | Get a page of a job's progress events |
|
|
313
313
|
| `wait_for_job(job_id, timeout_seconds=20)` | `job_id`, `timeout_seconds` | Block until a job reaches a terminal status, or `timeout_seconds` elapses. **One call blocks for at most the server's cap** — 55 seconds unless the deployment sets `DW_MCP_MAX_WAIT_SECONDS` higher, and the tool's description states the live value; a larger `timeout_seconds` is clamped, not honoured. Ask for the job's `plan.estimate` plus a margin: under the cap that is one call for the whole job, over it one call per cap. A deployment raises the cap only as far as its clients (and anything between them and the server) hold one silent HTTP request open - Claude Code's limit is `MCP_TOOL_TIMEOUT`. Every reply carries `waited_seconds`, `timeout_requested_seconds`, `timeout_applied_seconds` and `timeout_capped`, so a capped return is distinguishable from an elapsed one. Use instead of hand-polling `get_job`/`get_job_events` in a loop; if it returns `still_running: true`, call it again. Returns a slim job - status, warnings, error, `run_id` and `run_version` (the run's `v5`, as the gallery labels it), and the manifest once finished - without the arguments; `get_job` has those. A running job also carries `progress` (below) |
|
|
314
314
|
| `cancel_job(job_id)` | `job_id` | Ask a queued or running job to stop |
|
|
@@ -7,6 +7,63 @@ notes from commits at tag time (see below). This section is a scratch pad
|
|
|
7
7
|
for items a branch's author wants the next release note to name; clear it
|
|
8
8
|
when a release ships.
|
|
9
9
|
|
|
10
|
+
### 0.9.0
|
|
11
|
+
|
|
12
|
+
<!-- Drafted from v0.8.0..dd74e17b (develop). Paste into the GitHub release body once the tag has published: gh release edit v0.9.0 --notes-file ... -->
|
|
13
|
+
|
|
14
|
+
A smaller range than 0.8.0: the LoRA catalog grows to cover three more
|
|
15
|
+
bases, the cost planner is corrected for list-driven and `for_each` steps,
|
|
16
|
+
and `export_job` reports its zip's real auth gating. No upgrade-order
|
|
17
|
+
changes.
|
|
18
|
+
|
|
19
|
+
**LoRA catalog** (docs/LORAS.md)
|
|
20
|
+
|
|
21
|
+
- 11 LTX-2.5 entries added: IC-LoRAs for alpha generation, clean plate,
|
|
22
|
+
colorization, day-to-night, layout-to-render, detail refinement,
|
|
23
|
+
restoration, SDR-to-HDR and water simulation, plus cinemagraph and
|
|
24
|
+
slow-motion control.
|
|
25
|
+
- MiniMax-H3 goes to 13 trial and 3 rejected entries beyond the 0.8.0 set:
|
|
26
|
+
styles, speech, orbits, action and motion, and a diffusers-native 4-step
|
|
27
|
+
turbo. FastVideo FastH3 (`.diff` keys), RAVEN (unrecognised prefix, loads
|
|
28
|
+
nothing silently) and TaoMate (lowercase `lora_a`/`lora_b`) are rejected.
|
|
29
|
+
- New bases: Qwen-Image-2.1 (10 trial, including three few-step distills
|
|
30
|
+
that need their scheduler and sigma overrides, plus edit LoRAs; Fun-Acc
|
|
31
|
+
rejected) and Z-Image-Turbo (13 trial). The Z-Image entries match
|
|
32
|
+
`Tongyi-MAI/Z-Image-Turbo` only; whether they apply to the SDNQ
|
|
33
|
+
checkpoint is untested.
|
|
34
|
+
- Every new entry pins the repo's current sha, and its header was read
|
|
35
|
+
against the installed diffusers converter.
|
|
36
|
+
|
|
37
|
+
**Cost planning**
|
|
38
|
+
|
|
39
|
+
- `other_device` figures are re-priced for `for_each` counts and shifted
|
|
40
|
+
list drivers (#589, #590).
|
|
41
|
+
- A shifted per-entry field in a list driver resets to unknown, and a
|
|
42
|
+
summed child figure takes the children's basis (#593). A numeric string
|
|
43
|
+
in a list-driver entry compares as its number (#593).
|
|
44
|
+
- Measured MPS cost entries for `templates/ltx2/text-to-video` and Music 3
|
|
45
|
+
(#590).
|
|
46
|
+
|
|
47
|
+
**Fixes**
|
|
48
|
+
|
|
49
|
+
- `assemble-and-score` threads `sample_rate` into its edit join, and mixed-rate
|
|
50
|
+
shots resampled to a pinned `sample_rate` no longer draw a warning advising
|
|
51
|
+
you to pass it (#594).
|
|
52
|
+
- `export_job` reports the zip's real gating: `/exports/*.zip` is ungated
|
|
53
|
+
like `/outputs`, so `auth_required` is false whether or not the server has
|
|
54
|
+
a token. The MCP `next` text and the skills now say to fetch `open_url` and
|
|
55
|
+
unpack into `exports/` to bring a project home (#595, #592).
|
|
56
|
+
|
|
57
|
+
**Plugin**
|
|
58
|
+
|
|
59
|
+
- The `ltx-2.5`, `minimax-h3` and `minimax-music3` skills moved
|
|
60
|
+
request-specific detail (the LTX caption spec, H3 checkpoint and LoRA
|
|
61
|
+
combinations and cuts recipes, Music 3 loudness) into `references/`
|
|
62
|
+
beside each `SKILL.md`, which are read when the skill points there. The
|
|
63
|
+
12 KiB cap applies to `SKILL.md` alone; a new test fails on an unlinked
|
|
64
|
+
reference or a dead link.
|
|
65
|
+
- The H3 and LTX skills point at `list_loras`.
|
|
66
|
+
|
|
10
67
|
### 0.8.0
|
|
11
68
|
|
|
12
69
|
<!-- Drafted from v0.7.0..a9e1e72b (develop). Paste into the GitHub release body once the tag has published: gh release edit v0.8.0 --notes-file ... -->
|
|
@@ -38,6 +95,9 @@ upscaler and two security fixes.
|
|
|
38
95
|
- GHSA-crqf-hw9p-r739: `create_workspace`'s MCP result is `name`,
|
|
39
96
|
`default`, `current` and `next` only; `list_workspaces(detail=true)` is
|
|
40
97
|
the opt-in for folder paths. `POST /api/workspaces` is unchanged.
|
|
98
|
+
- `GET /api/loras/recommend` and `recommend_loras`: `hub_error` names the
|
|
99
|
+
exception type, or the HTTP status, never the exception's text, which
|
|
100
|
+
could name the server's HF cache directory. The log keeps the full error.
|
|
41
101
|
- UI lockfile bumps for open Dependabot alerts (devalue, dompurify,
|
|
42
102
|
brace-expansion, undici).
|
|
43
103
|
|
|
@@ -48,6 +48,11 @@ responses add an `absolute_url` / `absolute_zip_url` built from it; nothing
|
|
|
48
48
|
guesses this from request headers, so an unconfigured server omits the
|
|
49
49
|
field rather than composing a wrong origin.
|
|
50
50
|
|
|
51
|
+
The export zip, like `/outputs` and `/inputs` files, needs no token (#592), so
|
|
52
|
+
an agent with HTTP fetches `export_job`'s `open_url` itself, prefixing a
|
|
53
|
+
relative one with the address it reaches the server at; `DW_PUBLIC_URL` is for
|
|
54
|
+
the URLs handed to a person.
|
|
55
|
+
|
|
51
56
|
## Browser
|
|
52
57
|
|
|
53
58
|
Open `http://<box>:8765`. Click the key icon next to the theme toggle,
|
|
@@ -17,6 +17,7 @@ import copy
|
|
|
17
17
|
import hashlib
|
|
18
18
|
import json
|
|
19
19
|
import logging
|
|
20
|
+
import math
|
|
20
21
|
import os
|
|
21
22
|
|
|
22
23
|
from huggingface_hub import model_info
|
|
@@ -340,6 +341,36 @@ def _driver_comparable(value):
|
|
|
340
341
|
return json.dumps(value, sort_keys=True, default=str)
|
|
341
342
|
|
|
342
343
|
|
|
344
|
+
def _numeric_fields(entries):
|
|
345
|
+
"""{field: {values}} over the numeric fields of a list's dict entries. A
|
|
346
|
+
numeric string ("243") counts as its number, as `_driver_comparable` does
|
|
347
|
+
for a scalar driver."""
|
|
348
|
+
fields = {}
|
|
349
|
+
if not isinstance(entries, list):
|
|
350
|
+
return fields
|
|
351
|
+
for entry in entries:
|
|
352
|
+
if not isinstance(entry, dict):
|
|
353
|
+
continue
|
|
354
|
+
for key, value in entry.items():
|
|
355
|
+
number = _driver_comparable(value)
|
|
356
|
+
if isinstance(number, float) and math.isfinite(number):
|
|
357
|
+
fields.setdefault(key, set()).add(number)
|
|
358
|
+
return fields
|
|
359
|
+
|
|
360
|
+
|
|
361
|
+
def _list_entry_field_shifted(default_entries, effective_entries):
|
|
362
|
+
"""Whether a list driver's entries carry a numeric field (a per-shot
|
|
363
|
+
`num_frames`, say) with a value none of the default entries had. The
|
|
364
|
+
curated figure was measured over the default entries' values, so a value
|
|
365
|
+
outside them has no matching bucket - the #267 rule applied inside a
|
|
366
|
+
list driver (#593)."""
|
|
367
|
+
measured = _numeric_fields(default_entries)
|
|
368
|
+
for field, values in _numeric_fields(effective_entries).items():
|
|
369
|
+
if field in measured and not values <= measured[field]:
|
|
370
|
+
return True
|
|
371
|
+
return False
|
|
372
|
+
|
|
373
|
+
|
|
343
374
|
def _scalar_driver_shifted(definition, expanded, list_entries):
|
|
344
375
|
"""Whether a declared, non-list `cost_driver` was overridden away from
|
|
345
376
|
the default value the curated `cost` was measured against (#267).
|
|
@@ -352,10 +383,12 @@ def _scalar_driver_shifted(definition, expanded, list_entries):
|
|
|
352
383
|
defaults = definition.get("variables") or {}
|
|
353
384
|
effective = expanded.get("variables") or {}
|
|
354
385
|
for name in _declared_drivers(definition):
|
|
355
|
-
if name in list_entries:
|
|
356
|
-
continue
|
|
357
386
|
default_value = defaults.get(name)
|
|
358
387
|
if isinstance(default_value, list):
|
|
388
|
+
if _list_entry_field_shifted(default_value, effective.get(name)):
|
|
389
|
+
return True
|
|
390
|
+
continue
|
|
391
|
+
if name in list_entries:
|
|
359
392
|
continue
|
|
360
393
|
if _driver_comparable(effective.get(name)) != _driver_comparable(default_value):
|
|
361
394
|
return True
|
|
@@ -365,7 +398,7 @@ def _scalar_driver_shifted(definition, expanded, list_entries):
|
|
|
365
398
|
def _own_price(definition, expanded, list_entries, device, measured_entries):
|
|
366
399
|
"""The workflow's own price, reset to unknown when a scalar driver moved."""
|
|
367
400
|
own = _price(definition.get("cost"), device, list_entries, measured_entries or {})
|
|
368
|
-
if own["basis"]
|
|
401
|
+
if own["basis"] in (CATALOG, OTHER_DEVICE) and _scalar_driver_shifted(
|
|
369
402
|
definition, expanded, list_entries
|
|
370
403
|
):
|
|
371
404
|
# A scalar cost_driver (H3's num_frames, say) moved away from the
|
|
@@ -434,7 +467,7 @@ def _child_catalog_price(child_definition, child_cost, step_arguments, device):
|
|
|
434
467
|
child_list_entries = _list_entries(child_definition, child_expanded)
|
|
435
468
|
child = _price(child_cost, device, child_list_entries, child_measured_entries)
|
|
436
469
|
if (
|
|
437
|
-
child["basis"]
|
|
470
|
+
child["basis"] in (CATALOG, OTHER_DEVICE)
|
|
438
471
|
and child_definition is not None
|
|
439
472
|
and _scalar_driver_shifted(child_definition, child_expanded, child_list_entries)
|
|
440
473
|
):
|
|
@@ -458,6 +491,7 @@ class _ChildTotals:
|
|
|
458
491
|
self.all_observed = True
|
|
459
492
|
self.runs = []
|
|
460
493
|
self.measured_on = set()
|
|
494
|
+
self.bases = []
|
|
461
495
|
|
|
462
496
|
def add(self, path, child, observed):
|
|
463
497
|
self.had_child = True
|
|
@@ -469,7 +503,9 @@ class _ChildTotals:
|
|
|
469
503
|
if child["minutes"] is None:
|
|
470
504
|
self.partial = True
|
|
471
505
|
self.unpriced.append(path)
|
|
472
|
-
|
|
506
|
+
return
|
|
507
|
+
self.bases.append((child["basis"], child.get("measured_on")))
|
|
508
|
+
if self.minutes is not None:
|
|
473
509
|
self.minutes += child["minutes"]
|
|
474
510
|
else:
|
|
475
511
|
self.minutes = child["minutes"]
|
|
@@ -509,6 +545,20 @@ def _rolled_up_estimate(own, totals, device, cached_steps, total_steps):
|
|
|
509
545
|
top_measured_on = (
|
|
510
546
|
next(iter(totals.measured_on)) if len(totals.measured_on) == 1 else None
|
|
511
547
|
)
|
|
548
|
+
if top_basis == UNKNOWN and minutes is not None and totals.bases:
|
|
549
|
+
# A number must not carry the basis a caller reads as "no number":
|
|
550
|
+
# the parent has no cost of its own, but its priced children do, so
|
|
551
|
+
# the sum takes their basis (#593)
|
|
552
|
+
kinds = {basis for basis, _ in totals.bases}
|
|
553
|
+
if OTHER_DEVICE in kinds:
|
|
554
|
+
top_basis = OTHER_DEVICE
|
|
555
|
+
elif kinds == {CATALOG}:
|
|
556
|
+
top_basis = CATALOG
|
|
557
|
+
else:
|
|
558
|
+
top_basis = DERIVED
|
|
559
|
+
devices = {on for _, on in totals.bases}
|
|
560
|
+
if len(devices) == 1:
|
|
561
|
+
top_measured_on = next(iter(devices))
|
|
512
562
|
rounded = round(minutes, 1) if minutes is not None else None
|
|
513
563
|
result = {
|
|
514
564
|
"minutes": rounded,
|
|
@@ -696,18 +746,22 @@ def _price(cost, device, list_entries, measured_entries):
|
|
|
696
746
|
basis = OTHER_DEVICE
|
|
697
747
|
minutes = float(chosen.get("minutes", 0))
|
|
698
748
|
per = chosen.get("per_entry")
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
):
|
|
749
|
+
# Another device's figure is re-priced for the list length too (#589): it
|
|
750
|
+
# stays `other_device` (still not a measurement here), but a 32-entry
|
|
751
|
+
# for_each must not be quoted at the one-clip figure
|
|
752
|
+
if isinstance(per, dict) and per.get("variable") in list_entries:
|
|
704
753
|
count = list_entries[per["variable"]]
|
|
705
754
|
each = float(per.get("minutes", 0))
|
|
706
755
|
measured_with = int(per.get("entries", 0))
|
|
707
756
|
minutes = max(0.0, (minutes - each * measured_with) + each * count)
|
|
708
|
-
basis
|
|
709
|
-
|
|
710
|
-
|
|
757
|
+
if basis == CATALOG:
|
|
758
|
+
basis = PER_ENTRY
|
|
759
|
+
else:
|
|
760
|
+
minutes, repriced_basis = _repriced(minutes, list_entries, measured_entries)
|
|
761
|
+
if repriced_basis == UNKNOWN:
|
|
762
|
+
return {"minutes": None, "basis": UNKNOWN, "measured_on": None}
|
|
763
|
+
if basis == CATALOG:
|
|
764
|
+
basis = repriced_basis
|
|
711
765
|
return {"minutes": minutes, "basis": basis, "measured_on": chosen.get("name")}
|
|
712
766
|
|
|
713
767
|
|
|
@@ -455,11 +455,13 @@ def export_job_route(
|
|
|
455
455
|
absolute_zip_url = absolute_served_url(zip_path, ws)
|
|
456
456
|
if absolute_zip_url is not None:
|
|
457
457
|
body["absolute_zip_url"] = absolute_zip_url
|
|
458
|
-
#
|
|
459
|
-
#
|
|
460
|
-
#
|
|
461
|
-
#
|
|
462
|
-
|
|
458
|
+
# Whether the zip URL above needs a bearer token (#353, #592) - a
|
|
459
|
+
# property of the route, not of whether this server has a token. The
|
|
460
|
+
# auth middleware covers /api/ and /mcp only, and /exports/*.zip sits
|
|
461
|
+
# with /outputs and /inputs on dw/server/routes/files.py's ungated
|
|
462
|
+
# list, so it is false. export_job's `next` keeps its hand-it-over
|
|
463
|
+
# branch for the day /exports is gated.
|
|
464
|
+
body["auth_required"] = False
|
|
463
465
|
for key, name in (
|
|
464
466
|
("workflow", "workflow.json"),
|
|
465
467
|
("manifest", "manifest.json"),
|
|
@@ -94,6 +94,7 @@ def reconcile_sample_rates(command, videos, names, waveforms, sample_rate=None):
|
|
|
94
94
|
for video, waveform in zip(videos, waveforms)
|
|
95
95
|
if waveform is not None
|
|
96
96
|
]
|
|
97
|
+
pinned = bool(sample_rate)
|
|
97
98
|
sample_rate = sample_rate or (max(set(rates)) if rates else None)
|
|
98
99
|
if rates and len(set(rates)) == 1 and rates[0] != sample_rate:
|
|
99
100
|
# The inputs agree and the caller pinned another rate: converting
|
|
@@ -104,6 +105,15 @@ def reconcile_sample_rates(command, videos, names, waveforms, sample_rate=None):
|
|
|
104
105
|
command=command,
|
|
105
106
|
sample_rate=sample_rate,
|
|
106
107
|
)
|
|
108
|
+
elif rates and pinned and any(rate != sample_rate for rate in rates):
|
|
109
|
+
# Mixed inputs converted to the rate the caller (or the template)
|
|
110
|
+
# pinned: expected, and 'pass sample_rate' advice would be wrong (#594)
|
|
111
|
+
emit_log(
|
|
112
|
+
f"{command}: resampling tracks at {sorted(set(rates))} Hz to the "
|
|
113
|
+
f"requested {sample_rate} Hz",
|
|
114
|
+
command=command,
|
|
115
|
+
sample_rate=sample_rate,
|
|
116
|
+
)
|
|
107
117
|
elif rates and any(rate != sample_rate for rate in rates):
|
|
108
118
|
# emit_warning rather than logger.warning: resampling every track is
|
|
109
119
|
# an audio decision made on the caller's behalf, and a caller reading
|
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
The one thing this module has to keep saying: the directory it makes is on
|
|
4
4
|
the machine running dw.serve, which over a `dw.serve --mcp` endpoint is the
|
|
5
5
|
GPU box and not where the agent is. The zip URL is the way to it from
|
|
6
|
-
anywhere else
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
anywhere else, and it needs no token: /exports/*.zip is ungated like
|
|
7
|
+
/outputs (#592), so `auth_required` is false and the agent fetches it itself.
|
|
8
|
+
The hand-it-to-the-person branch (#353) stays for the day it is gated.
|
|
9
9
|
"""
|
|
10
10
|
|
|
11
11
|
from dw_mcp.client import api_path
|
|
@@ -22,10 +22,10 @@ def export_job(client, job_id, overwrite=False):
|
|
|
22
22
|
here. The directory is on the server machine, not this one.
|
|
23
23
|
|
|
24
24
|
`auth_required` says whether the zip needs this server's bearer token
|
|
25
|
-
to open
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
25
|
+
to open. The server reports false - the zip route is ungated, token or
|
|
26
|
+
not (#592) - and `next` says to fetch `open_url` and unpack it. True
|
|
27
|
+
is a forward guard: a gated zip is for the *person* to open, since
|
|
28
|
+
this agent cannot attach the token to their browser. `open_url` is
|
|
29
29
|
`absolute_zip_url` when the server has one configured (`DW_PUBLIC_URL`
|
|
30
30
|
/ the `public_url` setting), else the relative `zip_url`."""
|
|
31
31
|
body = client.post_json(
|
|
@@ -58,11 +58,14 @@ def export_job(client, job_id, overwrite=False):
|
|
|
58
58
|
open_url = absolute_zip_url or zip_url
|
|
59
59
|
next_text = (
|
|
60
60
|
"The directory is on the server. To give the user the files, "
|
|
61
|
-
"fetch open_url
|
|
62
|
-
"
|
|
63
|
-
"
|
|
64
|
-
"
|
|
65
|
-
"
|
|
61
|
+
"fetch open_url with whatever HTTP you have - it needs no token; "
|
|
62
|
+
"prefix a relative one with the address you reach this server at "
|
|
63
|
+
"- and unpack it into exports/ under the session's working "
|
|
64
|
+
"directory - it is the user's deliverable, not a temporary file, "
|
|
65
|
+
"so not a scratch or temp directory. The archive already unpacks "
|
|
66
|
+
"into one folder named after the job id; do not create that "
|
|
67
|
+
"folder first or the id is doubled in the path. Only if you "
|
|
68
|
+
"cannot make HTTP requests, give the user open_url to open. "
|
|
66
69
|
"workflow.json, manifest.json and job.json are inside it - they "
|
|
67
70
|
"are not repeated here; get_job_workflow and get_job serve them "
|
|
68
71
|
"individually."
|
|
@@ -216,16 +216,15 @@ class JobTools:
|
|
|
216
216
|
repeated here - get_job_workflow and get_job serve them individually.
|
|
217
217
|
THE DIRECTORY IS ON THE MACHINE RUNNING THE SERVER, not on yours.
|
|
218
218
|
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
the
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
way. Refuses a job that is still running; refuses an existing
|
|
219
|
+
open_url is the zip and needs no token: fetch it with any HTTP
|
|
220
|
+
you have (prefix a relative one with the server's address) and
|
|
221
|
+
unpack it into exports/ under the session's working directory -
|
|
222
|
+
the user's deliverable, not a temp file; it already unpacks into
|
|
223
|
+
one folder named after the job id, so do not create that folder first.
|
|
224
|
+
Only without HTTP, give the user open_url to open. If `auth_required`
|
|
225
|
+
is ever true, the zip is gated: hand it over (see `next`).
|
|
226
|
+
Individual results stay reachable inline via
|
|
227
|
+
get_output_image/get_output_audio/get_output_frames
|
|
228
|
+
without the zip. Refuses a job that is still running; refuses an existing
|
|
230
229
|
export unless overwrite=true."""
|
|
231
230
|
return exports.export_job(self.client, job_id, overwrite=overwrite)
|
|
@@ -8,7 +8,7 @@ name = "diffusers-workflow"
|
|
|
8
8
|
# runtime (static in TOML because importing dw at build time would drag
|
|
9
9
|
# torch into the build environment). Release tags must match it - see
|
|
10
10
|
# docs/RELEASING.md
|
|
11
|
-
version = "0.
|
|
11
|
+
version = "0.9.0"
|
|
12
12
|
description = "Declarative workflow engine and web UI for Hugging Face Diffusers"
|
|
13
13
|
readme = "README.md"
|
|
14
14
|
requires-python = ">=3.10"
|
{diffusers_workflow-0.8.0 → diffusers_workflow-0.9.0}/tests/test_assemble_and_score_target_lufs.py
RENAMED
|
@@ -124,3 +124,15 @@ def test_the_description_places_the_limit_ceiling_on_the_mix_not_the_film():
|
|
|
124
124
|
description = load_definition()["description"]
|
|
125
125
|
assert "holds on the mix 'balanced' writes, not on the film" in description
|
|
126
126
|
assert "about 1 dB above it" in description
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
def test_edit_join_gets_template_sample_rate():
|
|
130
|
+
"""#594: the edit join resampled mixed-rate shots to its own 48 kHz default
|
|
131
|
+
and warned the caller to pass sample_rate, which the template never
|
|
132
|
+
threaded through."""
|
|
133
|
+
from dw.variables import replace_variables, resolve_variable_values
|
|
134
|
+
|
|
135
|
+
definition = load_definition()
|
|
136
|
+
merged = resolve_variable_values({**definition["variables"], "sample_rate": 32000})
|
|
137
|
+
edit = steps_by_name(replace_variables(definition, merged))["edit"]
|
|
138
|
+
assert edit["task"]["arguments"]["sample_rate"] == 32000
|
|
@@ -643,6 +643,23 @@ class TestWarningsReachTheCaller:
|
|
|
643
643
|
assert "resampling them all to 200 Hz" in warnings[0]["message"]
|
|
644
644
|
assert "resample_audio" in warnings[0]["message"]
|
|
645
645
|
|
|
646
|
+
def test_mixed_rates_resampled_to_a_pinned_rate_draw_no_warning(self):
|
|
647
|
+
"""#594: a pinned sample_rate is the target; no advice to pass it."""
|
|
648
|
+
from dw.events import RunContext, activate_context, deactivate_context
|
|
649
|
+
|
|
650
|
+
events = []
|
|
651
|
+
token = activate_context(RunContext(on_event=events.append))
|
|
652
|
+
try:
|
|
653
|
+
result = concat_videos(
|
|
654
|
+
[audio_video(8, 0.5), audio_video(8, 0.5, sample_rate=200)],
|
|
655
|
+
sample_rate=150,
|
|
656
|
+
)
|
|
657
|
+
finally:
|
|
658
|
+
deactivate_context(token)
|
|
659
|
+
|
|
660
|
+
assert result.sample_rate == 150
|
|
661
|
+
assert [e for e in events if e.get("event") == "warning"] == []
|
|
662
|
+
|
|
646
663
|
def test_agreeing_rates_resampled_to_a_pinned_rate_draw_no_warning(self):
|
|
647
664
|
"""#453: inputs that agree, converted to the rate the caller pinned,
|
|
648
665
|
are not 'videos at different sample rates'."""
|
|
@@ -106,9 +106,10 @@ def test_the_next_hint_sends_the_zip_to_the_working_directory():
|
|
|
106
106
|
|
|
107
107
|
|
|
108
108
|
def test_auth_required_tells_the_agent_to_hand_the_zip_to_a_person():
|
|
109
|
-
"""#353
|
|
110
|
-
|
|
111
|
-
hint has to say hand
|
|
109
|
+
"""#353, kept as a forward guard by #592: the server reports false
|
|
110
|
+
today, but if the zip is ever gated this agent has no way to attach the
|
|
111
|
+
token to a fetch made on the person's behalf - the hint has to say hand
|
|
112
|
+
it over, not fetch it."""
|
|
112
113
|
client, _ = exporting(body={**SUMMARY, "auth_required": True})
|
|
113
114
|
|
|
114
115
|
result = exports.export_job(client, "job-1")
|
|
@@ -135,7 +136,9 @@ def test_an_absolute_open_url_is_preferred_and_said_to_be_absolute():
|
|
|
135
136
|
assert "already absolute" in result["next"]
|
|
136
137
|
|
|
137
138
|
|
|
138
|
-
def
|
|
139
|
+
def test_no_auth_required_fetches_the_zip_itself():
|
|
140
|
+
"""#592: the zip is ungated, so the server reports false and the hint
|
|
141
|
+
says fetch and unpack - not hand it over, which is the gated branch."""
|
|
139
142
|
client, _ = exporting(body={**SUMMARY, "auth_required": False})
|
|
140
143
|
|
|
141
144
|
result = exports.export_job(client, "job-1")
|
|
@@ -143,6 +146,10 @@ def test_no_auth_required_still_fetches_the_zip_itself():
|
|
|
143
146
|
assert result["auth_required"] is False
|
|
144
147
|
assert result["open_url"] == "/exports/job-1.zip"
|
|
145
148
|
assert "fetch open_url" in result["next"]
|
|
149
|
+
assert "needs no token" in result["next"]
|
|
150
|
+
assert "exports/" in result["next"]
|
|
151
|
+
assert "hand open_url to the person" not in result["next"]
|
|
152
|
+
assert "do not fetch it" not in result["next"]
|
|
146
153
|
|
|
147
154
|
|
|
148
155
|
def test_absolute_zip_url_is_omitted_rather_than_null_when_unconfigured():
|
|
@@ -1056,17 +1056,18 @@ async def test_export_job_sends_the_zip_to_the_working_directory():
|
|
|
1056
1056
|
|
|
1057
1057
|
|
|
1058
1058
|
@pytest.mark.asyncio
|
|
1059
|
-
async def
|
|
1060
|
-
"""#
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1059
|
+
async def test_export_job_description_says_to_fetch_the_ungated_zip():
|
|
1060
|
+
"""#592: the zip route is ungated, so the served description - what the
|
|
1061
|
+
agent plans from before it sees `next` - tells it to fetch open_url,
|
|
1062
|
+
no longer the #353 "do NOT fetch it", and keeps auth_required's hand-over
|
|
1063
|
+
as the forward guard for a gated zip."""
|
|
1064
1064
|
tools = await tools_of(server_over(ok({})))
|
|
1065
1065
|
|
|
1066
1066
|
description = tools["export_job"].description
|
|
1067
|
+
assert "needs no token" in description
|
|
1068
|
+
assert "fetch it with any HTTP" in description
|
|
1069
|
+
assert "do NOT fetch it" not in description
|
|
1067
1070
|
assert "auth_required" in description
|
|
1068
|
-
assert "do NOT fetch it" in description
|
|
1069
|
-
assert "hand open_url to the person" in description
|
|
1070
1071
|
|
|
1071
1072
|
|
|
1072
1073
|
@pytest.mark.asyncio
|
|
@@ -365,14 +365,42 @@ class TestEstimate:
|
|
|
365
365
|
answer = plan(spec, arguments=arguments)["estimate"]
|
|
366
366
|
assert (answer["minutes"], answer["basis"]) == (None, "unknown")
|
|
367
367
|
|
|
368
|
-
def
|
|
369
|
-
"""
|
|
370
|
-
|
|
368
|
+
def test_another_devices_figure_is_re_priced_for_the_list(self, plan):
|
|
369
|
+
"""#589: a 2-shot figure from another backend quoted verbatim for a
|
|
370
|
+
10-shot run was the 1/100 gate. It stays `other_device` - not a
|
|
371
|
+
measurement here - but the entry count multiplies."""
|
|
371
372
|
spec = definition()
|
|
372
373
|
spec["cost"] = [cost("mps", 40, name="M2")]
|
|
373
374
|
shots = [{"name": f"s{n}", "prompt": "x"} for n in range(10)]
|
|
374
375
|
answer = plan(spec, arguments={"shots": shots})["estimate"]
|
|
375
|
-
assert (answer["minutes"], answer["basis"]) == (
|
|
376
|
+
assert (answer["minutes"], answer["basis"]) == (200.0, "other_device")
|
|
377
|
+
|
|
378
|
+
def test_another_devices_per_entry_rate_prices_the_list(self, plan):
|
|
379
|
+
spec = definition()
|
|
380
|
+
spec["cost"] = [
|
|
381
|
+
cost("mps", 10, {"variable": "shots", "minutes": 3, "entries": 2})
|
|
382
|
+
]
|
|
383
|
+
shots = [{"name": f"s{n}", "prompt": "x"} for n in range(5)]
|
|
384
|
+
answer = plan(spec, arguments={"shots": shots})["estimate"]
|
|
385
|
+
assert (answer["minutes"], answer["basis"]) == (19.0, "other_device")
|
|
386
|
+
|
|
387
|
+
def test_another_devices_figure_with_two_changed_lists_is_unknown(self, plan):
|
|
388
|
+
spec = definition()
|
|
389
|
+
spec["cost"] = [cost("mps", 40, name="M2")]
|
|
390
|
+
spec["variables"]["angles"] = [{"name": "wide"}]
|
|
391
|
+
spec["steps"].append(
|
|
392
|
+
{
|
|
393
|
+
"name": "angle",
|
|
394
|
+
"for_each": "variable:angles",
|
|
395
|
+
"task": {"command": "x", "arguments": {"name": "item:name"}},
|
|
396
|
+
}
|
|
397
|
+
)
|
|
398
|
+
arguments = {
|
|
399
|
+
"shots": [{"name": f"s{n}", "prompt": "x"} for n in range(4)],
|
|
400
|
+
"angles": [{"name": "wide"}, {"name": "tight"}],
|
|
401
|
+
}
|
|
402
|
+
answer = plan(spec, arguments=arguments)["estimate"]
|
|
403
|
+
assert (answer["minutes"], answer["basis"]) == (None, "unknown")
|
|
376
404
|
|
|
377
405
|
def test_minutes_is_rounded_to_one_decimal(self, plan):
|
|
378
406
|
spec = definition()
|
|
@@ -389,6 +417,15 @@ class TestEstimate:
|
|
|
389
417
|
answer = plan(spec, arguments={"frames": 9})["estimate"]
|
|
390
418
|
assert (answer["minutes"], answer["basis"]) == (None, "unknown")
|
|
391
419
|
|
|
420
|
+
def test_a_shifted_scalar_driver_is_unknown_on_another_device_too(self, plan):
|
|
421
|
+
"""#589: the other_device branch skipped the #267 check, so a 241-frame
|
|
422
|
+
run was quoted the 121-frame clip's figure."""
|
|
423
|
+
spec = definition()
|
|
424
|
+
spec["cost"] = [cost("mps", 40, name="M2")]
|
|
425
|
+
spec["cost_drivers"] = ["frames"]
|
|
426
|
+
answer = plan(spec, arguments={"frames": 9})["estimate"]
|
|
427
|
+
assert (answer["minutes"], answer["basis"]) == (None, "unknown")
|
|
428
|
+
|
|
392
429
|
def test_an_unshifted_scalar_cost_driver_still_quotes_the_catalog_figure(
|
|
393
430
|
self, plan
|
|
394
431
|
):
|
|
@@ -407,6 +444,35 @@ class TestEstimate:
|
|
|
407
444
|
answer = plan(spec, arguments={"shots": shots})["estimate"]
|
|
408
445
|
assert (answer["minutes"], answer["basis"]) == (50.0, "derived")
|
|
409
446
|
|
|
447
|
+
def test_a_shifted_per_entry_field_in_a_list_driver_is_unknown(self, plan):
|
|
448
|
+
"""#593: a per-shot num_frames outside the values the default entries
|
|
449
|
+
were measured with has no matching bucket, same as a scalar (#267)."""
|
|
450
|
+
spec = definition()
|
|
451
|
+
spec["cost"] = [cost("mps", 40, name="M2")]
|
|
452
|
+
spec["cost_drivers"] = ["shots"]
|
|
453
|
+
spec["variables"]["shots"] = [
|
|
454
|
+
{"name": "a", "prompt": "p", "num_frames": 124},
|
|
455
|
+
{"name": "b", "prompt": "p", "num_frames": 141},
|
|
456
|
+
]
|
|
457
|
+
same = [
|
|
458
|
+
{"name": "x", "prompt": "p", "num_frames": 124},
|
|
459
|
+
{"name": "y", "prompt": "p", "num_frames": 124},
|
|
460
|
+
]
|
|
461
|
+
long = [
|
|
462
|
+
{"name": "x", "prompt": "p", "num_frames": 243},
|
|
463
|
+
{"name": "y", "prompt": "p", "num_frames": 243},
|
|
464
|
+
]
|
|
465
|
+
kept = plan(spec, arguments={"shots": same})["estimate"]
|
|
466
|
+
assert (kept["minutes"], kept["basis"]) == (40.0, "other_device")
|
|
467
|
+
moved = plan(spec, arguments={"shots": long})["estimate"]
|
|
468
|
+
assert (moved["minutes"], moved["basis"]) == (None, "unknown")
|
|
469
|
+
as_text = [dict(entry, num_frames=str(entry["num_frames"])) for entry in long]
|
|
470
|
+
moved = plan(spec, arguments={"shots": as_text})["estimate"]
|
|
471
|
+
assert (moved["minutes"], moved["basis"]) == (None, "unknown")
|
|
472
|
+
same_text = [dict(entry, num_frames="124") for entry in same]
|
|
473
|
+
kept = plan(spec, arguments={"shots": same_text})["estimate"]
|
|
474
|
+
assert (kept["minutes"], kept["basis"]) == (40.0, "other_device")
|
|
475
|
+
|
|
410
476
|
def test_an_undeclared_variable_shift_is_not_a_driver_shift(self, plan):
|
|
411
477
|
"""Only a declared cost_driver triggers the fallback - any other
|
|
412
478
|
variable overridden away from its default is none of this rule's
|
|
@@ -580,6 +646,17 @@ class TestSubWorkflowEstimate:
|
|
|
580
646
|
assert (answer["minutes"], answer["partial"]) == (7.0, False)
|
|
581
647
|
assert answer["unpriced"] == []
|
|
582
648
|
|
|
649
|
+
def test_a_number_never_carries_the_unknown_basis(self, plan, tmp_path):
|
|
650
|
+
"""#593: an uncosted parent that only composes priced children sums
|
|
651
|
+
to a figure, which takes the children's basis rather than `unknown`."""
|
|
652
|
+
child = {"id": "child", "cost": [cost("cuda", 5)], "steps": []}
|
|
653
|
+
(tmp_path / "child.json").write_text(json.dumps(child))
|
|
654
|
+
parent = composing("child.json")
|
|
655
|
+
del parent["cost"]
|
|
656
|
+
parent["steps"] = parent["steps"][1:]
|
|
657
|
+
answer = plan(parent)["estimate"]
|
|
658
|
+
assert (answer["minutes"], answer["basis"]) == (5.0, "catalog")
|
|
659
|
+
|
|
583
660
|
def test_a_child_without_a_cost_makes_the_estimate_partial(self, plan, tmp_path):
|
|
584
661
|
(tmp_path / "child.json").write_text(json.dumps({"id": "child", "steps": []}))
|
|
585
662
|
answer = plan(composing("child.json"))["estimate"]
|