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.
Files changed (198) hide show
  1. {model_compose-0.3.0/src/model_compose.egg-info → model_compose-0.3.1}/PKG-INFO +158 -23
  2. {model_compose-0.3.0 → model_compose-0.3.1}/README.md +157 -22
  3. {model_compose-0.3.0 → model_compose-0.3.1}/pyproject.toml +1 -1
  4. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/controller/webui/gradio.py +5 -5
  5. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/runtime/docker/docker.py +2 -6
  6. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/workflow/job/base.py +5 -1
  7. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/workflow/job/impl/__init__.py +2 -0
  8. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/workflow/job/impl/action.py +2 -2
  9. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/workflow/job/impl/delay.py +13 -5
  10. model_compose-0.3.1/src/mindor/core/workflow/job/impl/if_.py +57 -0
  11. model_compose-0.3.1/src/mindor/core/workflow/job/impl/switch.py +21 -0
  12. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/workflow/job/job.py +1 -1
  13. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/workflow/schema.py +9 -7
  14. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/workflow/workflow.py +39 -12
  15. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/compose.py +5 -5
  16. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/job/impl/__init__.py +2 -0
  17. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/job/impl/action.py +2 -2
  18. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/job/impl/common.py +6 -1
  19. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/job/impl/delay.py +3 -3
  20. model_compose-0.3.1/src/mindor/dsl/schema/job/impl/if_.py +46 -0
  21. model_compose-0.3.1/src/mindor/dsl/schema/job/impl/switch.py +29 -0
  22. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/job/impl/types.py +2 -0
  23. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/job/job.py +3 -1
  24. {model_compose-0.3.0 → model_compose-0.3.1/src/model_compose.egg-info}/PKG-INFO +158 -23
  25. {model_compose-0.3.0 → model_compose-0.3.1}/src/model_compose.egg-info/SOURCES.txt +4 -0
  26. {model_compose-0.3.0 → model_compose-0.3.1}/LICENSE +0 -0
  27. {model_compose-0.3.0 → model_compose-0.3.1}/setup.cfg +0 -0
  28. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/__init__.py +0 -0
  29. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/cli/__init__.py +0 -0
  30. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/cli/compose.py +0 -0
  31. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/__init__.py +0 -0
  32. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/component/__init__.py +0 -0
  33. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/component/base.py +0 -0
  34. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/component/component.py +0 -0
  35. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/component/context.py +0 -0
  36. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/component/services/__init__.py +0 -0
  37. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/component/services/http_client.py +0 -0
  38. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/component/services/http_server.py +0 -0
  39. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/component/services/mcp_client.py +0 -0
  40. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/component/services/mcp_server.py +0 -0
  41. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/component/services/model/__init__.py +0 -0
  42. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/component/services/model/base.py +0 -0
  43. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/component/services/model/model.py +0 -0
  44. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/component/services/model/tasks/__init__.py +0 -0
  45. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/component/services/model/tasks/summarization.py +0 -0
  46. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/component/services/model/tasks/text_classification.py +0 -0
  47. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/component/services/model/tasks/text_embedding.py +0 -0
  48. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/component/services/model/tasks/text_generation.py +0 -0
  49. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/component/services/model/tasks/translation.py +0 -0
  50. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/component/services/shell.py +0 -0
  51. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/component/services/workflow.py +0 -0
  52. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/compose/__init__.py +0 -0
  53. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/compose/compose.py +0 -0
  54. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/compose/manager.py +0 -0
  55. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/controller/__init__.py +0 -0
  56. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/controller/base.py +0 -0
  57. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/controller/controller.py +0 -0
  58. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/controller/runner/__init__.py +0 -0
  59. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/controller/runner/client.py +0 -0
  60. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/controller/runner/http_client.py +0 -0
  61. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/controller/runner/mcp_client.py +0 -0
  62. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/controller/runner/runner.py +0 -0
  63. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/controller/runtime/__init__.py +0 -0
  64. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/controller/runtime/docker/__init__.py +0 -0
  65. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/controller/runtime/docker/context/Dockerfile +0 -0
  66. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/controller/runtime/docker/docker.py +0 -0
  67. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/controller/runtime/specs.py +0 -0
  68. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/controller/services/__init__.py +0 -0
  69. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/controller/services/http_server.py +0 -0
  70. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/controller/services/mcp_server.py +0 -0
  71. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/controller/webui/__init__.py +0 -0
  72. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/controller/webui/webui.py +0 -0
  73. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/gateway/__init__.py +0 -0
  74. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/gateway/base.py +0 -0
  75. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/gateway/gateway.py +0 -0
  76. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/gateway/services/__init__.py +0 -0
  77. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/gateway/services/http_tunnel.py +0 -0
  78. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/gateway/services/ssh_tunnel.py +0 -0
  79. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/listener/__init__.py +0 -0
  80. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/listener/base.py +0 -0
  81. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/listener/listener.py +0 -0
  82. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/listener/services/__init__.py +0 -0
  83. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/listener/services/http_callback.py +0 -0
  84. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/logger/__init__.py +0 -0
  85. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/logger/base.py +0 -0
  86. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/logger/logger.py +0 -0
  87. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/logger/logging.py +0 -0
  88. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/logger/services/__init__.py +0 -0
  89. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/logger/services/console.py +0 -0
  90. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/logger/services/file.py +0 -0
  91. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/runtime/__init__.py +0 -0
  92. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/runtime/docker/__init__.py +0 -0
  93. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/runtime/env.py +0 -0
  94. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/services/__init__.py +0 -0
  95. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/services/async_service.py +0 -0
  96. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/utils/__init__.py +0 -0
  97. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/utils/expiring.py +0 -0
  98. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/utils/http_client.py +0 -0
  99. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/utils/http_request.py +0 -0
  100. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/utils/http_status.py +0 -0
  101. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/utils/image.py +0 -0
  102. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/utils/mcp_client.py +0 -0
  103. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/utils/renderer.py +0 -0
  104. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/utils/ssh_client.py +0 -0
  105. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/utils/streaming.py +0 -0
  106. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/utils/time.py +0 -0
  107. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/utils/workqueue.py +0 -0
  108. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/workflow/__init__.py +0 -0
  109. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/workflow/context.py +0 -0
  110. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/core/workflow/job/__init__.py +0 -0
  111. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/__init__.py +0 -0
  112. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/loader.py +0 -0
  113. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/__init__.py +0 -0
  114. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/action/__init__.py +0 -0
  115. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/action/action.py +0 -0
  116. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/action/impl/__init__.py +0 -0
  117. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/action/impl/common.py +0 -0
  118. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/action/impl/http_client.py +0 -0
  119. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/action/impl/http_server.py +0 -0
  120. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/action/impl/mcp_client.py +0 -0
  121. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/action/impl/mcp_server.py +0 -0
  122. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/action/impl/model/__init__.py +0 -0
  123. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/action/impl/model/impl/__init__.py +0 -0
  124. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/action/impl/model/impl/common.py +0 -0
  125. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/action/impl/model/impl/summarization.py +0 -0
  126. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/action/impl/model/impl/text_classification.py +0 -0
  127. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/action/impl/model/impl/text_embedding.py +0 -0
  128. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/action/impl/model/impl/text_generation.py +0 -0
  129. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/action/impl/model/impl/translation.py +0 -0
  130. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/action/impl/model/model.py +0 -0
  131. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/action/impl/shell.py +0 -0
  132. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/action/impl/workflow.py +0 -0
  133. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/component/__init__.py +0 -0
  134. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/component/component.py +0 -0
  135. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/component/impl/__init__.py +0 -0
  136. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/component/impl/common.py +0 -0
  137. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/component/impl/http_client.py +0 -0
  138. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/component/impl/http_server.py +0 -0
  139. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/component/impl/mcp_client.py +0 -0
  140. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/component/impl/mcp_server.py +0 -0
  141. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/component/impl/model/__init__.py +0 -0
  142. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/component/impl/model/impl/__init__.py +0 -0
  143. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/component/impl/model/impl/common.py +0 -0
  144. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/component/impl/model/impl/summarization.py +0 -0
  145. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/component/impl/model/impl/text_classification.py +0 -0
  146. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/component/impl/model/impl/text_embedding.py +0 -0
  147. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/component/impl/model/impl/text_generation.py +0 -0
  148. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/component/impl/model/impl/translation.py +0 -0
  149. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/component/impl/model/impl/types.py +0 -0
  150. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/component/impl/model/model.py +0 -0
  151. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/component/impl/shell.py +0 -0
  152. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/component/impl/types.py +0 -0
  153. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/component/impl/workflow.py +0 -0
  154. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/controller/__init__.py +0 -0
  155. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/controller/controller.py +0 -0
  156. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/controller/impl/__init__.py +0 -0
  157. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/controller/impl/common.py +0 -0
  158. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/controller/impl/http_server.py +0 -0
  159. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/controller/impl/mcp_server.py +0 -0
  160. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/controller/impl/types.py +0 -0
  161. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/controller/impl/webui.py +0 -0
  162. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/gateway/__init__.py +0 -0
  163. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/gateway/gateway.py +0 -0
  164. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/gateway/impl/__init__.py +0 -0
  165. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/gateway/impl/common.py +0 -0
  166. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/gateway/impl/http_tunnel.py +0 -0
  167. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/gateway/impl/ssh_tunnel.py +0 -0
  168. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/gateway/impl/types.py +0 -0
  169. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/job/__init__.py +0 -0
  170. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/listener/__init__.py +0 -0
  171. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/listener/impl/__init__.py +0 -0
  172. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/listener/impl/common.py +0 -0
  173. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/listener/impl/http_callback.py +0 -0
  174. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/listener/impl/types.py +0 -0
  175. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/listener/listener.py +0 -0
  176. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/logger/__init__.py +0 -0
  177. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/logger/impl/__init__.py +0 -0
  178. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/logger/impl/common.py +0 -0
  179. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/logger/impl/console.py +0 -0
  180. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/logger/impl/file.py +0 -0
  181. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/logger/impl/types.py +0 -0
  182. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/logger/logger.py +0 -0
  183. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/runtime/__init__.py +0 -0
  184. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/runtime/impl/__init__.py +0 -0
  185. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/runtime/impl/common.py +0 -0
  186. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/runtime/impl/docker.py +0 -0
  187. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/runtime/impl/native.py +0 -0
  188. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/runtime/impl/types.py +0 -0
  189. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/runtime/runtime.py +0 -0
  190. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/schema/workflow.py +0 -0
  191. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/utils/__init__.py +0 -0
  192. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/utils/annotation.py +0 -0
  193. {model_compose-0.3.0 → model_compose-0.3.1}/src/mindor/dsl/utils/enum.py +0 -0
  194. {model_compose-0.3.0 → model_compose-0.3.1}/src/model_compose.egg-info/dependency_links.txt +0 -0
  195. {model_compose-0.3.0 → model_compose-0.3.1}/src/model_compose.egg-info/entry_points.txt +0 -0
  196. {model_compose-0.3.0 → model_compose-0.3.1}/src/model_compose.egg-info/requires.txt +0 -0
  197. {model_compose-0.3.0 → model_compose-0.3.1}/src/model_compose.egg-info/top_level.txt +0 -0
  198. {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.0
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
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
34
34
  [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](http://makeapullrequest.com)
35
35
 
36
- ![Screenshots](docs/images/screenshots.png)
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:** Define complete AI workflows using simple YAML files—no complex scripting required.
45
- - **Compose Anything:** Combine multiple AI models, APIs, and tools into a single, unified pipeline.
46
- - **Built for Orchestration:** Orchestrate multi-step model interactions with ease. Transform individual API calls into maintainable, end-to-end systems.
47
- - **Multi-Workflow Support:** Define multiple named workflows in one project. Run them by name or set a default for quick execution.
48
- - **Modular Components:** Break down logic into reusable components and jobs. Easily plug, swap, and extend them across workflows.
49
- - **Flexible I/O Routing:** Connect inputs and outputs between jobs using clean, scoped variables—no glue code needed.
50
- - **Run Locally, Serve Remotely:** Execute workflows from the CLI or expose them as HTTP or MCP endpoints with an optional Web UI.
51
- - **Environment Variable Support:** Easily inject secrets and configuration via `.env` files or environment variables to keep your YAML clean and secure.
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, if configured)
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
- #### 📉 Shutting Down the Server (`down`)
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** configures the HTTP/MCP server, API endpoints, and optional Web UI
151
- - **Components** reusable definitions for calling APIs, running local AI models, or executing commands
152
- - **Workflows** named sets of jobs that define the flow of data
153
- - **Jobs** steps that execute specific components, with support for inputs, outputs, and dependencies
154
- - **Listeners** optional callback listeners that handle asynchronous responses from external services
155
- - **Gateways** - optional tunneling services that expose your local controller to the public internet
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. This is essential when integrating with third-party services that need to push data back to your workflow via webhooks or asynchronous callbacks.
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
+ ![Screenshots](docs/images/webui.png)
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
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
5
5
  [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](http://makeapullrequest.com)
6
6
 
7
- ![Screenshots](docs/images/screenshots.png)
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:** Define complete AI workflows using simple YAML files—no complex scripting required.
16
- - **Compose Anything:** Combine multiple AI models, APIs, and tools into a single, unified pipeline.
17
- - **Built for Orchestration:** Orchestrate multi-step model interactions with ease. Transform individual API calls into maintainable, end-to-end systems.
18
- - **Multi-Workflow Support:** Define multiple named workflows in one project. Run them by name or set a default for quick execution.
19
- - **Modular Components:** Break down logic into reusable components and jobs. Easily plug, swap, and extend them across workflows.
20
- - **Flexible I/O Routing:** Connect inputs and outputs between jobs using clean, scoped variables—no glue code needed.
21
- - **Run Locally, Serve Remotely:** Execute workflows from the CLI or expose them as HTTP or MCP endpoints with an optional Web UI.
22
- - **Environment Variable Support:** Easily inject secrets and configuration via `.env` files or environment variables to keep your YAML clean and secure.
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, if configured)
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
- #### 📉 Shutting Down the Server (`down`)
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** configures the HTTP/MCP server, API endpoints, and optional Web UI
122
- - **Components** reusable definitions for calling APIs, running local AI models, or executing commands
123
- - **Workflows** named sets of jobs that define the flow of data
124
- - **Jobs** steps that execute specific components, with support for inputs, outputs, and dependencies
125
- - **Listeners** optional callback listeners that handle asynchronous responses from external services
126
- - **Gateways** - optional tunneling services that expose your local controller to the public internet
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. This is essential when integrating with third-party services that need to push data back to your workflow via webhooks or asynchronous callbacks.
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
+ ![Screenshots](docs/images/webui.png)
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
 
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "model-compose"
3
- version = "0.3.0"
3
+ version = "0.3.1"
4
4
  description = "model-compose: Declarative AI Model and Workflow Orchestrator"
5
5
  authors = [
6
6
  { name = "Hanyeol Cho", email = "hanyeol.cho@gmail.com" }
@@ -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):
@@ -1,2 +1,4 @@
1
1
  from .action import *
2
2
  from .delay import *
3
+ from .if_ import *
4
+ from .switch import *
@@ -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
- if self.config.mode == DelayJobMode.TIME_INTERVAL:
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 self.config.mode == DelayJobMode.SPECIFIC_TIME:
27
+ if mode == DelayJobMode.SPECIFIC_TIME:
20
28
  return await self._delay_until_specific_time(context)
21
29
 
22
- return None
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