model-compose 0.3.0__tar.gz → 0.3.1__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.
- {model_compose-0.3.0/src/model_compose.egg-info → model_compose-0.3.1}/PKG-INFO +158 -23
- {model_compose-0.3.0 → model_compose-0.3.1}/README.md +157 -22
- {model_compose-0.3.0 → model_compose-0.3.1}/pyproject.toml +1 -1
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/controller/webui/gradio.py +5 -5
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/runtime/docker/docker.py +2 -6
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/workflow/job/base.py +5 -1
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/workflow/job/impl/__init__.py +2 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/workflow/job/impl/action.py +2 -2
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/workflow/job/impl/delay.py +13 -5
- model_compose-0.3.1/src/mindor/core/workflow/job/impl/if_.py +57 -0
- model_compose-0.3.1/src/mindor/core/workflow/job/impl/switch.py +21 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/workflow/job/job.py +1 -1
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/workflow/schema.py +9 -7
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/workflow/workflow.py +39 -12
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/compose.py +5 -5
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/job/impl/__init__.py +2 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/job/impl/action.py +2 -2
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/job/impl/common.py +6 -1
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/job/impl/delay.py +3 -3
- model_compose-0.3.1/src/mindor/dsl/schema/job/impl/if_.py +46 -0
- model_compose-0.3.1/src/mindor/dsl/schema/job/impl/switch.py +29 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/job/impl/types.py +2 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/job/job.py +3 -1
- {model_compose-0.3.0 → model_compose-0.3.1/src/model_compose.egg-info}/PKG-INFO +158 -23
- {model_compose-0.3.0 → model_compose-0.3.1}/src/model_compose.egg-info/SOURCES.txt +4 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/LICENSE +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/setup.cfg +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/__init__.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/cli/__init__.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/cli/compose.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/__init__.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/component/__init__.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/component/base.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/component/component.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/component/context.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/component/services/__init__.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/component/services/http_client.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/component/services/http_server.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/component/services/mcp_client.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/component/services/mcp_server.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/component/services/model/__init__.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/component/services/model/base.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/component/services/model/model.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/component/services/model/tasks/__init__.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/component/services/model/tasks/summarization.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/component/services/model/tasks/text_classification.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/component/services/model/tasks/text_embedding.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/component/services/model/tasks/text_generation.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/component/services/model/tasks/translation.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/component/services/shell.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/component/services/workflow.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/compose/__init__.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/compose/compose.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/compose/manager.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/controller/__init__.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/controller/base.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/controller/controller.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/controller/runner/__init__.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/controller/runner/client.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/controller/runner/http_client.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/controller/runner/mcp_client.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/controller/runner/runner.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/controller/runtime/__init__.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/controller/runtime/docker/__init__.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/controller/runtime/docker/context/Dockerfile +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/controller/runtime/docker/docker.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/controller/runtime/specs.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/controller/services/__init__.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/controller/services/http_server.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/controller/services/mcp_server.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/controller/webui/__init__.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/controller/webui/webui.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/gateway/__init__.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/gateway/base.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/gateway/gateway.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/gateway/services/__init__.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/gateway/services/http_tunnel.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/gateway/services/ssh_tunnel.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/listener/__init__.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/listener/base.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/listener/listener.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/listener/services/__init__.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/listener/services/http_callback.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/logger/__init__.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/logger/base.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/logger/logger.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/logger/logging.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/logger/services/__init__.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/logger/services/console.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/logger/services/file.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/runtime/__init__.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/runtime/docker/__init__.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/runtime/env.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/services/__init__.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/services/async_service.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/utils/__init__.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/utils/expiring.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/utils/http_client.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/utils/http_request.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/utils/http_status.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/utils/image.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/utils/mcp_client.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/utils/renderer.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/utils/ssh_client.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/utils/streaming.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/utils/time.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/utils/workqueue.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/workflow/__init__.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/workflow/context.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/workflow/job/__init__.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/__init__.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/loader.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/__init__.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/action/__init__.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/action/action.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/action/impl/__init__.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/action/impl/common.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/action/impl/http_client.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/action/impl/http_server.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/action/impl/mcp_client.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/action/impl/mcp_server.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/action/impl/model/__init__.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/action/impl/model/impl/__init__.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/action/impl/model/impl/common.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/action/impl/model/impl/summarization.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/action/impl/model/impl/text_classification.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/action/impl/model/impl/text_embedding.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/action/impl/model/impl/text_generation.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/action/impl/model/impl/translation.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/action/impl/model/model.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/action/impl/shell.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/action/impl/workflow.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/component/__init__.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/component/component.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/component/impl/__init__.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/component/impl/common.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/component/impl/http_client.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/component/impl/http_server.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/component/impl/mcp_client.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/component/impl/mcp_server.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/component/impl/model/__init__.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/component/impl/model/impl/__init__.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/component/impl/model/impl/common.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/component/impl/model/impl/summarization.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/component/impl/model/impl/text_classification.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/component/impl/model/impl/text_embedding.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/component/impl/model/impl/text_generation.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/component/impl/model/impl/translation.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/component/impl/model/impl/types.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/component/impl/model/model.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/component/impl/shell.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/component/impl/types.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/component/impl/workflow.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/controller/__init__.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/controller/controller.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/controller/impl/__init__.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/controller/impl/common.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/controller/impl/http_server.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/controller/impl/mcp_server.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/controller/impl/types.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/controller/impl/webui.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/gateway/__init__.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/gateway/gateway.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/gateway/impl/__init__.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/gateway/impl/common.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/gateway/impl/http_tunnel.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/gateway/impl/ssh_tunnel.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/gateway/impl/types.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/job/__init__.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/listener/__init__.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/listener/impl/__init__.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/listener/impl/common.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/listener/impl/http_callback.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/listener/impl/types.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/listener/listener.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/logger/__init__.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/logger/impl/__init__.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/logger/impl/common.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/logger/impl/console.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/logger/impl/file.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/logger/impl/types.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/logger/logger.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/runtime/__init__.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/runtime/impl/__init__.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/runtime/impl/common.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/runtime/impl/docker.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/runtime/impl/native.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/runtime/impl/types.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/runtime/runtime.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/workflow.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/utils/__init__.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/utils/annotation.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/utils/enum.py +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/model_compose.egg-info/dependency_links.txt +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/model_compose.egg-info/entry_points.txt +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/model_compose.egg-info/requires.txt +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/src/model_compose.egg-info/top_level.txt +0 -0
- {model_compose-0.3.0 → model_compose-0.3.1}/tests/test_cli.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: model-compose
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.1
|
|
4
4
|
Summary: model-compose: Declarative AI Model and Workflow Orchestrator
|
|
5
5
|
Author-email: Hanyeol Cho <hanyeol.cho@gmail.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -33,22 +33,21 @@ Dynamic: license-file
|
|
|
33
33
|
[](https://opensource.org/licenses/MIT)
|
|
34
34
|
[](http://makeapullrequest.com)
|
|
35
35
|
|
|
36
|
-

|
|
37
|
-
|
|
38
36
|
**model-compose** is an open-source, declarative workflow orchestrator inspired by `docker-compose`. It lets you define and run AI model pipelines using simple YAML files — no custom code required. Effortlessly connect external AI services or run local AI models, all within powerful, composable workflows.
|
|
39
37
|
|
|
40
38
|
---
|
|
41
39
|
|
|
42
40
|
## ✨ Features
|
|
43
41
|
|
|
44
|
-
- **Declarative by Design
|
|
45
|
-
- **Compose Anything
|
|
46
|
-
- **Built for Orchestration
|
|
47
|
-
- **Multi-Workflow Support
|
|
48
|
-
- **Modular Components
|
|
49
|
-
- **Flexible I/O Routing
|
|
50
|
-
- **Run Locally, Serve Remotely
|
|
51
|
-
- **
|
|
42
|
+
- **Declarative by Design**: Define complete AI workflows using simple YAML files—no complex scripting required.
|
|
43
|
+
- **Compose Anything**: Combine multiple AI models, APIs, and tools into a single, unified pipeline.
|
|
44
|
+
- **Built for Orchestration**: Orchestrate multi-step model interactions with ease. Transform individual API calls into maintainable, end-to-end systems.
|
|
45
|
+
- **Multi-Workflow Support**: Define multiple named workflows in one project. Run them by name or set a default for quick execution.
|
|
46
|
+
- **Modular Components**: Break down logic into reusable components and jobs. Easily plug, swap, and extend them across workflows.
|
|
47
|
+
- **Flexible I/O Routing**: Connect inputs and outputs between jobs using clean, scoped variables—no glue code needed.
|
|
48
|
+
- **Run Locally, Serve Remotely**: Execute workflows from the CLI or expose them as HTTP or MCP endpoints with an optional Web UI.
|
|
49
|
+
- **Docker Deployment**: Build and deploy your workflow controller as a Docker container for consistent and portable execution environments.
|
|
50
|
+
- **Environment Variable Support**: Easily inject secrets and configuration via `.env` files or environment variables to keep your YAML clean and secure.
|
|
52
51
|
|
|
53
52
|
---
|
|
54
53
|
|
|
@@ -85,8 +84,8 @@ By default, this command will:
|
|
|
85
84
|
|
|
86
85
|
- Look for a file named `model-compose.yml` in the **current working directory**
|
|
87
86
|
- Automatically load environment variables from a `.env` file in the **same directory**, if it exists
|
|
88
|
-
- Start the workflow controller (default: http://localhost:8080)
|
|
89
|
-
- Optionally launch the Web UI (default: http://localhost:8081
|
|
87
|
+
- Start the workflow controller (default: `http://localhost:8080`)
|
|
88
|
+
- Optionally launch the Web UI (default: `http://localhost:8081`, if configured)
|
|
90
89
|
|
|
91
90
|
To run in the background (detached mode):
|
|
92
91
|
|
|
@@ -114,7 +113,7 @@ model-compose up --env OPENAI_API_KEY=... --env ELEVENLABS_API_KEY=...
|
|
|
114
113
|
|
|
115
114
|
> 💡 Once the controller is running, you can trigger workflows via the REST API or, if using MCP, via JSON-RPC. You can also access them through the Web UI.
|
|
116
115
|
|
|
117
|
-
####
|
|
116
|
+
#### 🔽 Shutting Down the Server (`down`)
|
|
118
117
|
To gracefully stop and remove the workflow controller and all associated services:
|
|
119
118
|
|
|
120
119
|
```
|
|
@@ -140,19 +139,18 @@ This is useful for testing, automation, or scripting.
|
|
|
140
139
|
| `model-compose stop` | Temporarily pause the currently running controller |
|
|
141
140
|
|
|
142
141
|
---
|
|
143
|
-
|
|
144
142
|
## 🧾 `model-compose.yml`
|
|
145
143
|
|
|
146
144
|
The `model-compose.yml` file is the central configuration file that defines how your workflows are composed and executed.
|
|
147
145
|
|
|
148
146
|
It includes:
|
|
149
147
|
|
|
150
|
-
- **Controller
|
|
151
|
-
- **Components
|
|
152
|
-
- **Workflows
|
|
153
|
-
- **Jobs
|
|
154
|
-
- **Listeners
|
|
155
|
-
- **Gateways
|
|
148
|
+
- **Controller**: configures the HTTP/MCP server, API endpoints, and optional Web UI
|
|
149
|
+
- **Components**: reusable definitions for calling APIs, running local AI models, or executing commands
|
|
150
|
+
- **Workflows**: named sets of jobs that define the flow of data
|
|
151
|
+
- **Jobs**: steps that execute specific components, with support for inputs, outputs, and dependencies
|
|
152
|
+
- **Listeners**: optional callback listeners that handle asynchronous responses from external services
|
|
153
|
+
- **Gateways**: optional tunneling services that expose your local controller to the public internet
|
|
156
154
|
|
|
157
155
|
By default, `model-compose` automatically looks for a file named `model-compose.yml` in the current working directory when running commands like `up` or `run`.
|
|
158
156
|
|
|
@@ -162,6 +160,7 @@ By default, `model-compose` automatically looks for a file named `model-compose.
|
|
|
162
160
|
controller:
|
|
163
161
|
type: http-server
|
|
164
162
|
port: 8080
|
|
163
|
+
base_path: /api
|
|
165
164
|
webui:
|
|
166
165
|
port: 8081
|
|
167
166
|
|
|
@@ -214,7 +213,7 @@ listener:
|
|
|
214
213
|
result: ${item.choices[0].message.content}
|
|
215
214
|
```
|
|
216
215
|
|
|
217
|
-
This listener sets up an HTTP callback endpoint at http://localhost:8090/callbacks/chat-ai to handle asynchronous responses from an external service that behaves like ChatGPT but supports delayed or push-based results. This is useful when integrating with services that notify results via webhook-style callbacks.
|
|
216
|
+
This listener sets up an HTTP callback endpoint at `http://localhost:8090/callbacks/chat-ai` to handle asynchronous responses from an external service that behaves like ChatGPT but supports delayed or push-based results. This is useful when integrating with services that notify results via webhook-style callbacks.
|
|
218
217
|
|
|
219
218
|
#### 🌐 Gateway Example
|
|
220
219
|
|
|
@@ -225,10 +224,146 @@ gateway:
|
|
|
225
224
|
port: 8090
|
|
226
225
|
```
|
|
227
226
|
|
|
228
|
-
This gateway configuration exposes the local listener defined above to the public internet using an HTTP tunnel powered by ngrok. It forwards incoming traffic from a secure, public URL (e.g., https://abc123.ngrok.io) directly to your local callback endpoint at http://localhost:8090
|
|
227
|
+
This gateway configuration exposes the local listener defined above to the public internet using an HTTP tunnel powered by ngrok. It forwards incoming traffic from a secure, public URL (e.g., `https://abc123.ngrok.io`) directly to your local callback endpoint at `http://localhost:8090`. This is essential when integrating with third-party services that need to push data back to your workflow via webhooks or asynchronous callbacks.
|
|
229
228
|
|
|
230
229
|
> 📁 For more example model-compose.yml configurations, check the [examples directory](examples) in the source code.
|
|
231
230
|
|
|
231
|
+
---
|
|
232
|
+
## 🖥 Web UI
|
|
233
|
+
**model-compose** optionally provides a lightweight **Web UI** to help you visually trigger workflows, inspect inputs and outputs, and monitor execution logs.
|
|
234
|
+
|
|
235
|
+

|
|
236
|
+
|
|
237
|
+
#### ✅ Enabling the Web UI
|
|
238
|
+
To enable the Web UI, simply add the `webui` section under your `controller` in the `model-compose.yml` file:
|
|
239
|
+
```
|
|
240
|
+
controller:
|
|
241
|
+
type: http-server
|
|
242
|
+
port: 8080
|
|
243
|
+
webui:
|
|
244
|
+
port: 8081
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
Once enabled, the Web UI will be available at:
|
|
248
|
+
```
|
|
249
|
+
http://localhost:8081
|
|
250
|
+
```
|
|
251
|
+
> By default, the Web UI is powered by [Gradio](https://www.gradio.app), but support for other drivers may be added in the future.
|
|
252
|
+
|
|
253
|
+
---
|
|
254
|
+
## 🛰 MCP Server Support
|
|
255
|
+
You can also expose your workflows via the **Model Context Protocol (MCP)** server to enable remote execution, automation, or system integration using a lightweight JSON-RPC interface.
|
|
256
|
+
|
|
257
|
+
#### ✅ Minimal MCP Server Example
|
|
258
|
+
|
|
259
|
+
```
|
|
260
|
+
controller:
|
|
261
|
+
type: mcp-server
|
|
262
|
+
port: 8080
|
|
263
|
+
base_path: /mcp
|
|
264
|
+
|
|
265
|
+
components:
|
|
266
|
+
chatgpt:
|
|
267
|
+
type: http-client
|
|
268
|
+
base_url: https://api.openai.com/v1
|
|
269
|
+
path: /chat/completions
|
|
270
|
+
method: POST
|
|
271
|
+
headers:
|
|
272
|
+
Authorization: Bearer ${env.OPENAI_API_KEY}
|
|
273
|
+
Content-Type: application/json
|
|
274
|
+
body:
|
|
275
|
+
model: gpt-4o
|
|
276
|
+
messages:
|
|
277
|
+
- role: user
|
|
278
|
+
content: "Write an inspiring quote."
|
|
279
|
+
output:
|
|
280
|
+
quote: ${response.choices[0].message.content}
|
|
281
|
+
|
|
282
|
+
workflows:
|
|
283
|
+
generate-quote:
|
|
284
|
+
default: true
|
|
285
|
+
jobs:
|
|
286
|
+
get-quote:
|
|
287
|
+
component: chatgpt
|
|
288
|
+
```
|
|
289
|
+
This configuration launches the controller as an **MCP server**, which listens on port 8080 and exposes your workflows over a **JSON-RPC API**.
|
|
290
|
+
|
|
291
|
+
Once running, you can invoke workflows remotely using a standard MCP request:
|
|
292
|
+
|
|
293
|
+
```
|
|
294
|
+
{
|
|
295
|
+
"jsonrpc": "2.0",
|
|
296
|
+
"id": 1,
|
|
297
|
+
"method": "callTool",
|
|
298
|
+
"params": {
|
|
299
|
+
"name": "generate-quote",
|
|
300
|
+
"arguments": {}
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
You can send this request via any HTTP client to:
|
|
306
|
+
```
|
|
307
|
+
POST http://localhost:8080/mcp
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
---
|
|
311
|
+
## 🐳 Docker Runtime Support
|
|
312
|
+
You can run the workflow controller inside a Docker container by specifying the runtime option in your `model-compose.yml` file.
|
|
313
|
+
|
|
314
|
+
#### ✅ Minimal Docker Runtime Example
|
|
315
|
+
|
|
316
|
+
```
|
|
317
|
+
controller:
|
|
318
|
+
type: http-server
|
|
319
|
+
port: 8080
|
|
320
|
+
runtime: docker
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
This configuration will launch the controller inside a lightweight Docker container automatically managed by **model-compose**. It uses default settings such as container name, image, and volume mappings.
|
|
324
|
+
|
|
325
|
+
#### ⚙️ Advanced Docker Runtime Options
|
|
326
|
+
You can fully configure the Docker runtime by using an object under the `runtime` key:
|
|
327
|
+
|
|
328
|
+
```
|
|
329
|
+
controller:
|
|
330
|
+
type: http-server
|
|
331
|
+
port: 8080
|
|
332
|
+
runtime:
|
|
333
|
+
type: docker
|
|
334
|
+
image: 192.168.0.23/custom-image:latest
|
|
335
|
+
container_name: my-controller
|
|
336
|
+
volumes:
|
|
337
|
+
- ./models:/models
|
|
338
|
+
- ./cache:/cache
|
|
339
|
+
ports:
|
|
340
|
+
- "5000:8080"
|
|
341
|
+
- "5001:8081"
|
|
342
|
+
env:
|
|
343
|
+
MODEL_STORAGE_PATH: /models
|
|
344
|
+
command: [ "python", "-m", "mindor.cli.compose", "up" ]
|
|
345
|
+
...
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
This gives you full control over:
|
|
349
|
+
|
|
350
|
+
- **container_name**: Custom name for the container
|
|
351
|
+
- **image**: Docker image to use
|
|
352
|
+
- **volumes**: Bind mounts for sharing files between host and container
|
|
353
|
+
- **ports**: Port mappings for host ↔ container communication
|
|
354
|
+
- **env**: Environment variables to inject
|
|
355
|
+
- **command**: Override the default entrypoint
|
|
356
|
+
- *and many more*
|
|
357
|
+
|
|
358
|
+
All of these are optional, allowing you to start simple and customize only what you need.
|
|
359
|
+
|
|
360
|
+
#### 🐳 Benefits of Docker Runtime
|
|
361
|
+
|
|
362
|
+
- Run your controller in a clean, isolated environment
|
|
363
|
+
- Avoid dependency conflicts with your host Python setup
|
|
364
|
+
- Easily deploy your project to remote servers or CI pipelines
|
|
365
|
+
- Share reproducible workflows with others
|
|
366
|
+
|
|
232
367
|
---
|
|
233
368
|
## 🏗 Architecture
|
|
234
369
|
|
|
@@ -4,22 +4,21 @@
|
|
|
4
4
|
[](https://opensource.org/licenses/MIT)
|
|
5
5
|
[](http://makeapullrequest.com)
|
|
6
6
|
|
|
7
|
-

|
|
8
|
-
|
|
9
7
|
**model-compose** is an open-source, declarative workflow orchestrator inspired by `docker-compose`. It lets you define and run AI model pipelines using simple YAML files — no custom code required. Effortlessly connect external AI services or run local AI models, all within powerful, composable workflows.
|
|
10
8
|
|
|
11
9
|
---
|
|
12
10
|
|
|
13
11
|
## ✨ Features
|
|
14
12
|
|
|
15
|
-
- **Declarative by Design
|
|
16
|
-
- **Compose Anything
|
|
17
|
-
- **Built for Orchestration
|
|
18
|
-
- **Multi-Workflow Support
|
|
19
|
-
- **Modular Components
|
|
20
|
-
- **Flexible I/O Routing
|
|
21
|
-
- **Run Locally, Serve Remotely
|
|
22
|
-
- **
|
|
13
|
+
- **Declarative by Design**: Define complete AI workflows using simple YAML files—no complex scripting required.
|
|
14
|
+
- **Compose Anything**: Combine multiple AI models, APIs, and tools into a single, unified pipeline.
|
|
15
|
+
- **Built for Orchestration**: Orchestrate multi-step model interactions with ease. Transform individual API calls into maintainable, end-to-end systems.
|
|
16
|
+
- **Multi-Workflow Support**: Define multiple named workflows in one project. Run them by name or set a default for quick execution.
|
|
17
|
+
- **Modular Components**: Break down logic into reusable components and jobs. Easily plug, swap, and extend them across workflows.
|
|
18
|
+
- **Flexible I/O Routing**: Connect inputs and outputs between jobs using clean, scoped variables—no glue code needed.
|
|
19
|
+
- **Run Locally, Serve Remotely**: Execute workflows from the CLI or expose them as HTTP or MCP endpoints with an optional Web UI.
|
|
20
|
+
- **Docker Deployment**: Build and deploy your workflow controller as a Docker container for consistent and portable execution environments.
|
|
21
|
+
- **Environment Variable Support**: Easily inject secrets and configuration via `.env` files or environment variables to keep your YAML clean and secure.
|
|
23
22
|
|
|
24
23
|
---
|
|
25
24
|
|
|
@@ -56,8 +55,8 @@ By default, this command will:
|
|
|
56
55
|
|
|
57
56
|
- Look for a file named `model-compose.yml` in the **current working directory**
|
|
58
57
|
- Automatically load environment variables from a `.env` file in the **same directory**, if it exists
|
|
59
|
-
- Start the workflow controller (default: http://localhost:8080)
|
|
60
|
-
- Optionally launch the Web UI (default: http://localhost:8081
|
|
58
|
+
- Start the workflow controller (default: `http://localhost:8080`)
|
|
59
|
+
- Optionally launch the Web UI (default: `http://localhost:8081`, if configured)
|
|
61
60
|
|
|
62
61
|
To run in the background (detached mode):
|
|
63
62
|
|
|
@@ -85,7 +84,7 @@ model-compose up --env OPENAI_API_KEY=... --env ELEVENLABS_API_KEY=...
|
|
|
85
84
|
|
|
86
85
|
> 💡 Once the controller is running, you can trigger workflows via the REST API or, if using MCP, via JSON-RPC. You can also access them through the Web UI.
|
|
87
86
|
|
|
88
|
-
####
|
|
87
|
+
#### 🔽 Shutting Down the Server (`down`)
|
|
89
88
|
To gracefully stop and remove the workflow controller and all associated services:
|
|
90
89
|
|
|
91
90
|
```
|
|
@@ -111,19 +110,18 @@ This is useful for testing, automation, or scripting.
|
|
|
111
110
|
| `model-compose stop` | Temporarily pause the currently running controller |
|
|
112
111
|
|
|
113
112
|
---
|
|
114
|
-
|
|
115
113
|
## 🧾 `model-compose.yml`
|
|
116
114
|
|
|
117
115
|
The `model-compose.yml` file is the central configuration file that defines how your workflows are composed and executed.
|
|
118
116
|
|
|
119
117
|
It includes:
|
|
120
118
|
|
|
121
|
-
- **Controller
|
|
122
|
-
- **Components
|
|
123
|
-
- **Workflows
|
|
124
|
-
- **Jobs
|
|
125
|
-
- **Listeners
|
|
126
|
-
- **Gateways
|
|
119
|
+
- **Controller**: configures the HTTP/MCP server, API endpoints, and optional Web UI
|
|
120
|
+
- **Components**: reusable definitions for calling APIs, running local AI models, or executing commands
|
|
121
|
+
- **Workflows**: named sets of jobs that define the flow of data
|
|
122
|
+
- **Jobs**: steps that execute specific components, with support for inputs, outputs, and dependencies
|
|
123
|
+
- **Listeners**: optional callback listeners that handle asynchronous responses from external services
|
|
124
|
+
- **Gateways**: optional tunneling services that expose your local controller to the public internet
|
|
127
125
|
|
|
128
126
|
By default, `model-compose` automatically looks for a file named `model-compose.yml` in the current working directory when running commands like `up` or `run`.
|
|
129
127
|
|
|
@@ -133,6 +131,7 @@ By default, `model-compose` automatically looks for a file named `model-compose.
|
|
|
133
131
|
controller:
|
|
134
132
|
type: http-server
|
|
135
133
|
port: 8080
|
|
134
|
+
base_path: /api
|
|
136
135
|
webui:
|
|
137
136
|
port: 8081
|
|
138
137
|
|
|
@@ -185,7 +184,7 @@ listener:
|
|
|
185
184
|
result: ${item.choices[0].message.content}
|
|
186
185
|
```
|
|
187
186
|
|
|
188
|
-
This listener sets up an HTTP callback endpoint at http://localhost:8090/callbacks/chat-ai to handle asynchronous responses from an external service that behaves like ChatGPT but supports delayed or push-based results. This is useful when integrating with services that notify results via webhook-style callbacks.
|
|
187
|
+
This listener sets up an HTTP callback endpoint at `http://localhost:8090/callbacks/chat-ai` to handle asynchronous responses from an external service that behaves like ChatGPT but supports delayed or push-based results. This is useful when integrating with services that notify results via webhook-style callbacks.
|
|
189
188
|
|
|
190
189
|
#### 🌐 Gateway Example
|
|
191
190
|
|
|
@@ -196,10 +195,146 @@ gateway:
|
|
|
196
195
|
port: 8090
|
|
197
196
|
```
|
|
198
197
|
|
|
199
|
-
This gateway configuration exposes the local listener defined above to the public internet using an HTTP tunnel powered by ngrok. It forwards incoming traffic from a secure, public URL (e.g., https://abc123.ngrok.io) directly to your local callback endpoint at http://localhost:8090
|
|
198
|
+
This gateway configuration exposes the local listener defined above to the public internet using an HTTP tunnel powered by ngrok. It forwards incoming traffic from a secure, public URL (e.g., `https://abc123.ngrok.io`) directly to your local callback endpoint at `http://localhost:8090`. This is essential when integrating with third-party services that need to push data back to your workflow via webhooks or asynchronous callbacks.
|
|
200
199
|
|
|
201
200
|
> 📁 For more example model-compose.yml configurations, check the [examples directory](examples) in the source code.
|
|
202
201
|
|
|
202
|
+
---
|
|
203
|
+
## 🖥 Web UI
|
|
204
|
+
**model-compose** optionally provides a lightweight **Web UI** to help you visually trigger workflows, inspect inputs and outputs, and monitor execution logs.
|
|
205
|
+
|
|
206
|
+

|
|
207
|
+
|
|
208
|
+
#### ✅ Enabling the Web UI
|
|
209
|
+
To enable the Web UI, simply add the `webui` section under your `controller` in the `model-compose.yml` file:
|
|
210
|
+
```
|
|
211
|
+
controller:
|
|
212
|
+
type: http-server
|
|
213
|
+
port: 8080
|
|
214
|
+
webui:
|
|
215
|
+
port: 8081
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
Once enabled, the Web UI will be available at:
|
|
219
|
+
```
|
|
220
|
+
http://localhost:8081
|
|
221
|
+
```
|
|
222
|
+
> By default, the Web UI is powered by [Gradio](https://www.gradio.app), but support for other drivers may be added in the future.
|
|
223
|
+
|
|
224
|
+
---
|
|
225
|
+
## 🛰 MCP Server Support
|
|
226
|
+
You can also expose your workflows via the **Model Context Protocol (MCP)** server to enable remote execution, automation, or system integration using a lightweight JSON-RPC interface.
|
|
227
|
+
|
|
228
|
+
#### ✅ Minimal MCP Server Example
|
|
229
|
+
|
|
230
|
+
```
|
|
231
|
+
controller:
|
|
232
|
+
type: mcp-server
|
|
233
|
+
port: 8080
|
|
234
|
+
base_path: /mcp
|
|
235
|
+
|
|
236
|
+
components:
|
|
237
|
+
chatgpt:
|
|
238
|
+
type: http-client
|
|
239
|
+
base_url: https://api.openai.com/v1
|
|
240
|
+
path: /chat/completions
|
|
241
|
+
method: POST
|
|
242
|
+
headers:
|
|
243
|
+
Authorization: Bearer ${env.OPENAI_API_KEY}
|
|
244
|
+
Content-Type: application/json
|
|
245
|
+
body:
|
|
246
|
+
model: gpt-4o
|
|
247
|
+
messages:
|
|
248
|
+
- role: user
|
|
249
|
+
content: "Write an inspiring quote."
|
|
250
|
+
output:
|
|
251
|
+
quote: ${response.choices[0].message.content}
|
|
252
|
+
|
|
253
|
+
workflows:
|
|
254
|
+
generate-quote:
|
|
255
|
+
default: true
|
|
256
|
+
jobs:
|
|
257
|
+
get-quote:
|
|
258
|
+
component: chatgpt
|
|
259
|
+
```
|
|
260
|
+
This configuration launches the controller as an **MCP server**, which listens on port 8080 and exposes your workflows over a **JSON-RPC API**.
|
|
261
|
+
|
|
262
|
+
Once running, you can invoke workflows remotely using a standard MCP request:
|
|
263
|
+
|
|
264
|
+
```
|
|
265
|
+
{
|
|
266
|
+
"jsonrpc": "2.0",
|
|
267
|
+
"id": 1,
|
|
268
|
+
"method": "callTool",
|
|
269
|
+
"params": {
|
|
270
|
+
"name": "generate-quote",
|
|
271
|
+
"arguments": {}
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
You can send this request via any HTTP client to:
|
|
277
|
+
```
|
|
278
|
+
POST http://localhost:8080/mcp
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
---
|
|
282
|
+
## 🐳 Docker Runtime Support
|
|
283
|
+
You can run the workflow controller inside a Docker container by specifying the runtime option in your `model-compose.yml` file.
|
|
284
|
+
|
|
285
|
+
#### ✅ Minimal Docker Runtime Example
|
|
286
|
+
|
|
287
|
+
```
|
|
288
|
+
controller:
|
|
289
|
+
type: http-server
|
|
290
|
+
port: 8080
|
|
291
|
+
runtime: docker
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
This configuration will launch the controller inside a lightweight Docker container automatically managed by **model-compose**. It uses default settings such as container name, image, and volume mappings.
|
|
295
|
+
|
|
296
|
+
#### ⚙️ Advanced Docker Runtime Options
|
|
297
|
+
You can fully configure the Docker runtime by using an object under the `runtime` key:
|
|
298
|
+
|
|
299
|
+
```
|
|
300
|
+
controller:
|
|
301
|
+
type: http-server
|
|
302
|
+
port: 8080
|
|
303
|
+
runtime:
|
|
304
|
+
type: docker
|
|
305
|
+
image: 192.168.0.23/custom-image:latest
|
|
306
|
+
container_name: my-controller
|
|
307
|
+
volumes:
|
|
308
|
+
- ./models:/models
|
|
309
|
+
- ./cache:/cache
|
|
310
|
+
ports:
|
|
311
|
+
- "5000:8080"
|
|
312
|
+
- "5001:8081"
|
|
313
|
+
env:
|
|
314
|
+
MODEL_STORAGE_PATH: /models
|
|
315
|
+
command: [ "python", "-m", "mindor.cli.compose", "up" ]
|
|
316
|
+
...
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
This gives you full control over:
|
|
320
|
+
|
|
321
|
+
- **container_name**: Custom name for the container
|
|
322
|
+
- **image**: Docker image to use
|
|
323
|
+
- **volumes**: Bind mounts for sharing files between host and container
|
|
324
|
+
- **ports**: Port mappings for host ↔ container communication
|
|
325
|
+
- **env**: Environment variables to inject
|
|
326
|
+
- **command**: Override the default entrypoint
|
|
327
|
+
- *and many more*
|
|
328
|
+
|
|
329
|
+
All of these are optional, allowing you to start simple and customize only what you need.
|
|
330
|
+
|
|
331
|
+
#### 🐳 Benefits of Docker Runtime
|
|
332
|
+
|
|
333
|
+
- Run your controller in a clean, isolated environment
|
|
334
|
+
- Avoid dependency conflicts with your host Python setup
|
|
335
|
+
- Easily deploy your project to remote servers or CI pipelines
|
|
336
|
+
- Share reproducible workflows with others
|
|
337
|
+
|
|
203
338
|
---
|
|
204
339
|
## 🏗 Architecture
|
|
205
340
|
|
|
@@ -106,7 +106,7 @@ class GradioWebUIBuilder:
|
|
|
106
106
|
if type in [ WorkflowVariableType.IMAGE, WorkflowVariableType.AUDIO, WorkflowVariableType.VIDEO, WorkflowVariableType.FILE ] and (not internal or not format):
|
|
107
107
|
if internal and format and format != "path":
|
|
108
108
|
value = await self._save_value_to_temporary_file(value, subtype, format)
|
|
109
|
-
return create_upload_file(value, type.value, subtype)
|
|
109
|
+
return create_upload_file(value, type.value, subtype) if value is not None else None
|
|
110
110
|
|
|
111
111
|
return value if value != "" else None
|
|
112
112
|
|
|
@@ -157,17 +157,17 @@ class GradioWebUIBuilder:
|
|
|
157
157
|
flattened = []
|
|
158
158
|
for variable in variables:
|
|
159
159
|
if isinstance(variable, WorkflowVariableGroupConfig):
|
|
160
|
-
group = output[variable.name] if variable.name else output
|
|
161
|
-
for value in group:
|
|
160
|
+
group = output[variable.name] if variable.name in output else None if variable.name else output
|
|
161
|
+
for value in group or ():
|
|
162
162
|
flattened.extend(await self._flatten_output_value(value, variable.variables))
|
|
163
163
|
else:
|
|
164
|
-
value = output[variable.name] if variable.name else output
|
|
164
|
+
value = output[variable.name] if variable.name in output else None if variable.name else output
|
|
165
165
|
flattened.append(await self._convert_output_value(value, variable.type, variable.subtype, variable.format, variable.internal))
|
|
166
166
|
return flattened
|
|
167
167
|
|
|
168
168
|
async def _convert_output_value(self, value: Any, type: WorkflowVariableType, subtype: Optional[str], format: Optional[WorkflowVariableFormat], internal: bool) -> Any:
|
|
169
169
|
if type == WorkflowVariableType.STRING:
|
|
170
|
-
return json.dumps(value) if isinstance(value, (dict, list)) else str(value)
|
|
170
|
+
return json.dumps(value) if isinstance(value, (dict, list)) else str(value) if value is not None else None
|
|
171
171
|
|
|
172
172
|
if type == WorkflowVariableType.IMAGE:
|
|
173
173
|
return await self._load_image_from_value(value, subtype, format)
|
|
@@ -105,9 +105,7 @@ class DockerRuntimeManager:
|
|
|
105
105
|
privileged=self.config.privileged,
|
|
106
106
|
security_opt=self.config.security_opt,
|
|
107
107
|
restart_policy={ "Name": self.config.restart },
|
|
108
|
-
tty=True,
|
|
109
|
-
stdin_open=True,
|
|
110
|
-
detach=True
|
|
108
|
+
tty=True, stdin_open=True, detach=True
|
|
111
109
|
)
|
|
112
110
|
container.start()
|
|
113
111
|
|
|
@@ -163,9 +161,7 @@ class DockerRuntimeManager:
|
|
|
163
161
|
labels=self.config.build.labels or {},
|
|
164
162
|
network_mode=self.config.build.network,
|
|
165
163
|
pull=self.config.build.pull,
|
|
166
|
-
rm=True,
|
|
167
|
-
forcerm=True,
|
|
168
|
-
decode=True
|
|
164
|
+
rm=True, forcerm=True, decode=True
|
|
169
165
|
)
|
|
170
166
|
|
|
171
167
|
for chunk in response:
|
|
@@ -5,6 +5,10 @@ from mindor.dsl.schema.component import ComponentConfig
|
|
|
5
5
|
from mindor.core.component import ComponentGlobalConfigs
|
|
6
6
|
from mindor.core.workflow.context import WorkflowContext
|
|
7
7
|
|
|
8
|
+
class RoutingTarget:
|
|
9
|
+
def __init__(self, job_id):
|
|
10
|
+
self.job_id = job_id
|
|
11
|
+
|
|
8
12
|
class Job(ABC):
|
|
9
13
|
def __init__(self, id: str, config: JobConfig, global_configs: ComponentGlobalConfigs):
|
|
10
14
|
self.id: str = id
|
|
@@ -12,7 +16,7 @@ class Job(ABC):
|
|
|
12
16
|
self.global_configs: ComponentGlobalConfigs = global_configs
|
|
13
17
|
|
|
14
18
|
@abstractmethod
|
|
15
|
-
async def run(self, context: WorkflowContext) -> Any:
|
|
19
|
+
async def run(self, context: WorkflowContext) -> Union[Any, RoutingTarget]:
|
|
16
20
|
pass
|
|
17
21
|
|
|
18
22
|
def register_job(type: JobType):
|
|
@@ -4,7 +4,7 @@ from mindor.dsl.schema.component import ComponentConfig
|
|
|
4
4
|
from mindor.core.component import ComponentService, ComponentGlobalConfigs, ComponentResolver, create_component
|
|
5
5
|
from mindor.core.utils.time import TimeTracker
|
|
6
6
|
from mindor.core.logger import logging
|
|
7
|
-
from ..base import Job, JobType, WorkflowContext, register_job
|
|
7
|
+
from ..base import Job, JobType, WorkflowContext, RoutingTarget, register_job
|
|
8
8
|
from datetime import datetime
|
|
9
9
|
import asyncio, ulid
|
|
10
10
|
|
|
@@ -13,7 +13,7 @@ class ActionJob(Job):
|
|
|
13
13
|
def __init__(self, id: str, config: ActionJobConfig, global_configs: ComponentGlobalConfigs):
|
|
14
14
|
super().__init__(id, config, global_configs)
|
|
15
15
|
|
|
16
|
-
async def run(self, context: WorkflowContext) -> Any:
|
|
16
|
+
async def run(self, context: WorkflowContext) -> Union[Any, RoutingTarget]:
|
|
17
17
|
component: ComponentService = self._create_component(self.id, await context.render_variable(self.config.component))
|
|
18
18
|
|
|
19
19
|
if not component.started:
|
|
@@ -3,7 +3,7 @@ from mindor.dsl.schema.job import DelayJobConfig, DelayJobMode
|
|
|
3
3
|
from mindor.dsl.schema.component import ComponentConfig
|
|
4
4
|
from mindor.core.utils.time import parse_duration, parse_datetime, TimeTracker
|
|
5
5
|
from mindor.core.logger import logging
|
|
6
|
-
from ..base import Job, JobType, WorkflowContext, register_job
|
|
6
|
+
from ..base import Job, JobType, WorkflowContext, RoutingTarget, register_job
|
|
7
7
|
from datetime import datetime, timedelta
|
|
8
8
|
import asyncio
|
|
9
9
|
|
|
@@ -13,13 +13,21 @@ class DelayJob(Job):
|
|
|
13
13
|
super().__init__(id, config, components)
|
|
14
14
|
|
|
15
15
|
async def run(self, context: WorkflowContext) -> Any:
|
|
16
|
-
|
|
16
|
+
output = await self._delay(self.config.mode, context)
|
|
17
|
+
|
|
18
|
+
output = (await context.render_variable(self.config.output, ignore_files=True)) if self.config.output else output
|
|
19
|
+
context.register_source("output", output)
|
|
20
|
+
|
|
21
|
+
return output
|
|
22
|
+
|
|
23
|
+
async def _delay(self, mode: DelayJobMode, context: WorkflowContext) -> Any:
|
|
24
|
+
if mode == DelayJobMode.TIME_INTERVAL:
|
|
17
25
|
return await self._delay_for_time_interval(context)
|
|
18
26
|
|
|
19
|
-
if
|
|
27
|
+
if mode == DelayJobMode.SPECIFIC_TIME:
|
|
20
28
|
return await self._delay_until_specific_time(context)
|
|
21
29
|
|
|
22
|
-
|
|
30
|
+
raise ValueError(f"Unsupported delay mode: {mode}")
|
|
23
31
|
|
|
24
32
|
async def _delay_for_time_interval(self, context: WorkflowContext) -> Any:
|
|
25
33
|
duration = parse_duration((await context.render_variable(self.config.duration)) or 0.0)
|
|
@@ -35,7 +43,7 @@ class DelayJob(Job):
|
|
|
35
43
|
|
|
36
44
|
return None
|
|
37
45
|
|
|
38
|
-
async def _delay_until_specific_time(self, context: WorkflowContext) -> Any:
|
|
46
|
+
async def _delay_until_specific_time(self, context: WorkflowContext) -> Union[Any, RoutingTarget]:
|
|
39
47
|
timezone = await context.render_variable(self.config.timezone)
|
|
40
48
|
time = parse_datetime((await context.render_variable(self.config.time)) or datetime(2000, 1, 1, 0, 0, 0), timezone)
|
|
41
49
|
|