model-compose 0.3.6__tar.gz → 0.3.7__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 (215) hide show
  1. {model_compose-0.3.6/src/model_compose.egg-info → model_compose-0.3.7}/PKG-INFO +1 -1
  2. {model_compose-0.3.6 → model_compose-0.3.7}/pyproject.toml +1 -1
  3. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/cli/compose.py +7 -2
  4. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/core/component/base.py +12 -0
  5. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/core/component/context.py +6 -0
  6. model_compose-0.3.7/src/mindor/core/component/services/http_server.py +133 -0
  7. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/core/component/services/shell.py +5 -14
  8. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/core/controller/base.py +11 -9
  9. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/core/controller/runner/http_client.py +1 -1
  10. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/core/controller/runner/mcp_client.py +1 -1
  11. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/core/controller/services/http_server.py +82 -2
  12. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/core/controller/services/mcp_server.py +2 -4
  13. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/core/controller/webui/gradio.py +8 -8
  14. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/core/controller/webui/webui.py +8 -8
  15. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/core/listener/services/http_callback.py +2 -0
  16. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/core/runtime/env.py +10 -0
  17. model_compose-0.3.7/src/mindor/core/utils/shell.py +70 -0
  18. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/core/workflow/context.py +3 -0
  19. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/core/workflow/schema.py +6 -3
  20. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/dsl/schema/action/impl/http_client.py +18 -18
  21. model_compose-0.3.7/src/mindor/dsl/schema/action/impl/http_server.py +52 -0
  22. model_compose-0.3.7/src/mindor/dsl/schema/component/impl/http_server.py +35 -0
  23. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/dsl/schema/controller/impl/common.py +3 -3
  24. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/dsl/schema/controller/impl/http_server.py +2 -2
  25. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/dsl/schema/controller/impl/mcp_server.py +2 -2
  26. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/dsl/schema/controller/webui/impl/common.py +2 -2
  27. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/dsl/schema/gateway/impl/common.py +1 -1
  28. {model_compose-0.3.6 → model_compose-0.3.7/src/model_compose.egg-info}/PKG-INFO +1 -1
  29. {model_compose-0.3.6 → model_compose-0.3.7}/src/model_compose.egg-info/SOURCES.txt +1 -0
  30. model_compose-0.3.6/src/mindor/core/component/services/http_server.py +0 -26
  31. model_compose-0.3.6/src/mindor/dsl/schema/action/impl/http_server.py +0 -8
  32. model_compose-0.3.6/src/mindor/dsl/schema/component/impl/http_server.py +0 -11
  33. {model_compose-0.3.6 → model_compose-0.3.7}/LICENSE +0 -0
  34. {model_compose-0.3.6 → model_compose-0.3.7}/README.md +0 -0
  35. {model_compose-0.3.6 → model_compose-0.3.7}/setup.cfg +0 -0
  36. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/__init__.py +0 -0
  37. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/cli/__init__.py +0 -0
  38. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/core/__init__.py +0 -0
  39. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/core/component/__init__.py +0 -0
  40. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/core/component/component.py +0 -0
  41. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/core/component/services/__init__.py +0 -0
  42. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/core/component/services/http_client.py +0 -0
  43. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/core/component/services/mcp_client.py +0 -0
  44. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/core/component/services/mcp_server.py +0 -0
  45. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/core/component/services/model/__init__.py +0 -0
  46. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/core/component/services/model/base.py +0 -0
  47. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/core/component/services/model/model.py +0 -0
  48. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/core/component/services/model/tasks/__init__.py +0 -0
  49. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/core/component/services/model/tasks/summarization.py +0 -0
  50. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/core/component/services/model/tasks/text_classification.py +0 -0
  51. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/core/component/services/model/tasks/text_embedding.py +0 -0
  52. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/core/component/services/model/tasks/text_generation.py +0 -0
  53. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/core/component/services/model/tasks/translation.py +0 -0
  54. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/core/component/services/text_splitter.py +0 -0
  55. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/core/component/services/workflow.py +0 -0
  56. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/core/compose/__init__.py +0 -0
  57. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/core/compose/compose.py +0 -0
  58. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/core/compose/manager.py +0 -0
  59. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/core/controller/__init__.py +0 -0
  60. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/core/controller/controller.py +0 -0
  61. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/core/controller/runner/__init__.py +0 -0
  62. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/core/controller/runner/client.py +0 -0
  63. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/core/controller/runner/runner.py +0 -0
  64. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/core/controller/runtime/__init__.py +0 -0
  65. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/core/controller/runtime/docker/__init__.py +0 -0
  66. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/core/controller/runtime/docker/context/Dockerfile +0 -0
  67. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/core/controller/runtime/docker/docker.py +0 -0
  68. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/core/controller/runtime/specs.py +0 -0
  69. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/core/controller/services/__init__.py +0 -0
  70. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/core/controller/webui/__init__.py +0 -0
  71. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/core/gateway/__init__.py +0 -0
  72. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/core/gateway/base.py +0 -0
  73. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/core/gateway/gateway.py +0 -0
  74. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/core/gateway/services/__init__.py +0 -0
  75. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/core/gateway/services/http_tunnel.py +0 -0
  76. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/core/gateway/services/ssh_tunnel.py +0 -0
  77. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/core/listener/__init__.py +0 -0
  78. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/core/listener/base.py +0 -0
  79. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/core/listener/listener.py +0 -0
  80. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/core/listener/services/__init__.py +0 -0
  81. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/core/logger/__init__.py +0 -0
  82. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/core/logger/base.py +0 -0
  83. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/core/logger/logger.py +0 -0
  84. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/core/logger/logging.py +0 -0
  85. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/core/logger/services/__init__.py +0 -0
  86. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/core/logger/services/console.py +0 -0
  87. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/core/logger/services/file.py +0 -0
  88. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/core/runtime/__init__.py +0 -0
  89. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/core/runtime/docker/__init__.py +0 -0
  90. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/core/runtime/docker/docker.py +0 -0
  91. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/core/services/__init__.py +0 -0
  92. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/core/services/async_service.py +0 -0
  93. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/core/utils/__init__.py +0 -0
  94. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/core/utils/caching.py +0 -0
  95. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/core/utils/http_client.py +0 -0
  96. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/core/utils/http_request.py +0 -0
  97. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/core/utils/http_status.py +0 -0
  98. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/core/utils/image.py +0 -0
  99. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/core/utils/mcp_client.py +0 -0
  100. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/core/utils/renderers.py +0 -0
  101. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/core/utils/resolvers.py +0 -0
  102. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/core/utils/ssh_client.py +0 -0
  103. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/core/utils/streamer.py +0 -0
  104. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/core/utils/streaming.py +0 -0
  105. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/core/utils/time.py +0 -0
  106. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/core/utils/workqueue.py +0 -0
  107. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/core/workflow/__init__.py +0 -0
  108. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/core/workflow/job/__init__.py +0 -0
  109. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/core/workflow/job/base.py +0 -0
  110. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/core/workflow/job/impl/__init__.py +0 -0
  111. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/core/workflow/job/impl/action.py +0 -0
  112. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/core/workflow/job/impl/delay.py +0 -0
  113. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/core/workflow/job/impl/if_.py +0 -0
  114. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/core/workflow/job/impl/random_router.py +0 -0
  115. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/core/workflow/job/impl/switch.py +0 -0
  116. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/core/workflow/job/job.py +0 -0
  117. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/core/workflow/workflow.py +0 -0
  118. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/dsl/__init__.py +0 -0
  119. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/dsl/loader.py +0 -0
  120. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/dsl/schema/__init__.py +0 -0
  121. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/dsl/schema/action/__init__.py +0 -0
  122. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/dsl/schema/action/action.py +0 -0
  123. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/dsl/schema/action/impl/__init__.py +0 -0
  124. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/dsl/schema/action/impl/common.py +0 -0
  125. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/dsl/schema/action/impl/mcp_client.py +0 -0
  126. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/dsl/schema/action/impl/mcp_server.py +0 -0
  127. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/dsl/schema/action/impl/model/__init__.py +0 -0
  128. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/dsl/schema/action/impl/model/impl/__init__.py +0 -0
  129. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/dsl/schema/action/impl/model/impl/common.py +0 -0
  130. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/dsl/schema/action/impl/model/impl/summarization.py +0 -0
  131. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/dsl/schema/action/impl/model/impl/text_classification.py +0 -0
  132. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/dsl/schema/action/impl/model/impl/text_embedding.py +0 -0
  133. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/dsl/schema/action/impl/model/impl/text_generation.py +0 -0
  134. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/dsl/schema/action/impl/model/impl/translation.py +0 -0
  135. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/dsl/schema/action/impl/model/model.py +0 -0
  136. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/dsl/schema/action/impl/shell.py +0 -0
  137. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/dsl/schema/action/impl/text_splitter.py +0 -0
  138. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/dsl/schema/action/impl/workflow.py +0 -0
  139. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/dsl/schema/component/__init__.py +0 -0
  140. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/dsl/schema/component/component.py +0 -0
  141. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/dsl/schema/component/impl/__init__.py +0 -0
  142. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/dsl/schema/component/impl/common.py +0 -0
  143. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/dsl/schema/component/impl/http_client.py +0 -0
  144. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/dsl/schema/component/impl/mcp_client.py +0 -0
  145. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/dsl/schema/component/impl/mcp_server.py +0 -0
  146. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/dsl/schema/component/impl/model/__init__.py +0 -0
  147. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/dsl/schema/component/impl/model/impl/__init__.py +0 -0
  148. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/dsl/schema/component/impl/model/impl/common.py +0 -0
  149. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/dsl/schema/component/impl/model/impl/summarization.py +0 -0
  150. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/dsl/schema/component/impl/model/impl/text_classification.py +0 -0
  151. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/dsl/schema/component/impl/model/impl/text_embedding.py +0 -0
  152. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/dsl/schema/component/impl/model/impl/text_generation.py +0 -0
  153. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/dsl/schema/component/impl/model/impl/translation.py +0 -0
  154. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/dsl/schema/component/impl/model/impl/types.py +0 -0
  155. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/dsl/schema/component/impl/model/model.py +0 -0
  156. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/dsl/schema/component/impl/shell.py +0 -0
  157. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/dsl/schema/component/impl/text_splitter.py +0 -0
  158. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/dsl/schema/component/impl/types.py +0 -0
  159. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/dsl/schema/component/impl/workflow.py +0 -0
  160. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/dsl/schema/compose.py +0 -0
  161. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/dsl/schema/controller/__init__.py +0 -0
  162. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/dsl/schema/controller/controller.py +0 -0
  163. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/dsl/schema/controller/impl/__init__.py +0 -0
  164. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/dsl/schema/controller/impl/types.py +0 -0
  165. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/dsl/schema/controller/webui/__init__.py +0 -0
  166. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/dsl/schema/controller/webui/impl/__init__.py +0 -0
  167. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/dsl/schema/controller/webui/impl/dynamic.py +0 -0
  168. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/dsl/schema/controller/webui/impl/gradio.py +0 -0
  169. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/dsl/schema/controller/webui/impl/static.py +0 -0
  170. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/dsl/schema/controller/webui/webui.py +0 -0
  171. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/dsl/schema/gateway/__init__.py +0 -0
  172. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/dsl/schema/gateway/gateway.py +0 -0
  173. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/dsl/schema/gateway/impl/__init__.py +0 -0
  174. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/dsl/schema/gateway/impl/http_tunnel.py +0 -0
  175. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/dsl/schema/gateway/impl/ssh_tunnel.py +0 -0
  176. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/dsl/schema/gateway/impl/types.py +0 -0
  177. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/dsl/schema/job/__init__.py +0 -0
  178. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/dsl/schema/job/impl/__init__.py +0 -0
  179. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/dsl/schema/job/impl/action.py +0 -0
  180. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/dsl/schema/job/impl/common.py +0 -0
  181. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/dsl/schema/job/impl/delay.py +0 -0
  182. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/dsl/schema/job/impl/if_.py +0 -0
  183. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/dsl/schema/job/impl/random_router.py +0 -0
  184. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/dsl/schema/job/impl/switch.py +0 -0
  185. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/dsl/schema/job/impl/types.py +0 -0
  186. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/dsl/schema/job/job.py +0 -0
  187. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/dsl/schema/listener/__init__.py +0 -0
  188. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/dsl/schema/listener/impl/__init__.py +0 -0
  189. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/dsl/schema/listener/impl/common.py +0 -0
  190. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/dsl/schema/listener/impl/http_callback.py +0 -0
  191. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/dsl/schema/listener/impl/types.py +0 -0
  192. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/dsl/schema/listener/listener.py +0 -0
  193. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/dsl/schema/logger/__init__.py +0 -0
  194. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/dsl/schema/logger/impl/__init__.py +0 -0
  195. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/dsl/schema/logger/impl/common.py +0 -0
  196. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/dsl/schema/logger/impl/console.py +0 -0
  197. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/dsl/schema/logger/impl/file.py +0 -0
  198. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/dsl/schema/logger/impl/types.py +0 -0
  199. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/dsl/schema/logger/logger.py +0 -0
  200. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/dsl/schema/runtime/__init__.py +0 -0
  201. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/dsl/schema/runtime/impl/__init__.py +0 -0
  202. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/dsl/schema/runtime/impl/common.py +0 -0
  203. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/dsl/schema/runtime/impl/docker.py +0 -0
  204. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/dsl/schema/runtime/impl/native.py +0 -0
  205. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/dsl/schema/runtime/impl/types.py +0 -0
  206. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/dsl/schema/runtime/runtime.py +0 -0
  207. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/dsl/schema/workflow.py +0 -0
  208. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/dsl/utils/__init__.py +0 -0
  209. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/dsl/utils/annotation.py +0 -0
  210. {model_compose-0.3.6 → model_compose-0.3.7}/src/mindor/dsl/utils/enum.py +0 -0
  211. {model_compose-0.3.6 → model_compose-0.3.7}/src/model_compose.egg-info/dependency_links.txt +0 -0
  212. {model_compose-0.3.6 → model_compose-0.3.7}/src/model_compose.egg-info/entry_points.txt +0 -0
  213. {model_compose-0.3.6 → model_compose-0.3.7}/src/model_compose.egg-info/requires.txt +0 -0
  214. {model_compose-0.3.6 → model_compose-0.3.7}/src/model_compose.egg-info/top_level.txt +0 -0
  215. {model_compose-0.3.6 → model_compose-0.3.7}/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.6
3
+ Version: 0.3.7
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
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "model-compose"
3
- version = "0.3.6"
3
+ version = "0.3.7"
4
4
  description = "model-compose: Declarative AI Model and Workflow Orchestrator"
5
5
  authors = [
6
6
  { name = "Hanyeol Cho", email = "hanyeol.cho@gmail.com" }
@@ -4,14 +4,14 @@ from pathlib import Path
4
4
  import asyncio
5
5
 
6
6
  from mindor.dsl.loader import load_compose_config
7
- from mindor.core.runtime.env import load_env_files
7
+ from mindor.core.runtime.env import load_env_files, merge_env_data
8
8
  from mindor.core.compose import *
9
9
 
10
10
  @click.group()
11
11
  @click.option(
12
12
  "--file", "-f", "config_files", multiple=True,
13
13
  type=click.Path(exists=True, dir_okay=False, path_type=Path),
14
- help="Compose configuration files"
14
+ help="Compose configuration files."
15
15
  )
16
16
  @click.pass_context
17
17
  def compose_command(ctx: click.Context, config_files: List[Path]) -> None:
@@ -44,6 +44,7 @@ def up_command(
44
44
  async def _async_command():
45
45
  try:
46
46
  env = load_env_files(".", env_files or [])
47
+ env = merge_env_data(env, env_data)
47
48
  config = load_compose_config(".", config_files, env)
48
49
  await launch_services(config, detach, verbose)
49
50
  except Exception as e:
@@ -73,6 +74,7 @@ def down_command(
73
74
  async def _async_command():
74
75
  try:
75
76
  env = load_env_files(".", env_files or [])
77
+ env = merge_env_data(env, env_data)
76
78
  config = load_compose_config(".", config_files, env)
77
79
  await terminate_services(config, verbose)
78
80
  except Exception as e:
@@ -102,6 +104,7 @@ def start_command(
102
104
  async def _async_command():
103
105
  try:
104
106
  env = load_env_files(".", env_files or [])
107
+ env = merge_env_data(env, env_data)
105
108
  config = load_compose_config(".", config_files, env)
106
109
  await start_services(config, verbose)
107
110
  except Exception as e:
@@ -131,6 +134,7 @@ def stop_command(
131
134
  async def _async_command():
132
135
  try:
133
136
  env = load_env_files(".", env_files or [])
137
+ env = merge_env_data(env, env_data)
134
138
  config = load_compose_config(".", config_files, env)
135
139
  await stop_services(config, verbose)
136
140
  except Exception as e:
@@ -176,6 +180,7 @@ def run_command(
176
180
  async def _async_command():
177
181
  try:
178
182
  env = load_env_files(".", env_files or [])
183
+ env = merge_env_data(env, env_data)
179
184
  config = load_compose_config(".", config_files, env)
180
185
  input = json.loads(input_json) if input_json else {}
181
186
  state = await run_workflow(config, workflow_id, input, output_path, verbose)
@@ -57,6 +57,12 @@ class ComponentService(AsyncService):
57
57
  if self.config.max_concurrent_count > 0:
58
58
  self.queue = WorkQueue(self.config.max_concurrent_count, self._run)
59
59
 
60
+ async def install(self) -> None:
61
+ await self._install()
62
+
63
+ async def build(self) -> None:
64
+ await self._build()
65
+
60
66
  async def run(self, action_id: Union[str, None], run_id: str, input: Dict[str, Any]) -> Dict[str, Any]:
61
67
  _, action = ActionResolver(self.config.actions).resolve(action_id)
62
68
  context = ComponentActionContext(run_id, input)
@@ -66,6 +72,12 @@ class ComponentService(AsyncService):
66
72
 
67
73
  return await self._run(action, context)
68
74
 
75
+ async def _install(self) -> None:
76
+ pass
77
+
78
+ async def _build(self) -> None:
79
+ pass
80
+
69
81
  async def _start(self) -> None:
70
82
  if self.queue:
71
83
  await self.queue.start()
@@ -19,17 +19,23 @@ class ComponentActionContext:
19
19
  async def _resolve_source(self, key: str, index: Optional[int]) -> Any:
20
20
  if key in self.sources:
21
21
  return self.sources[key][index] if index is not None else self.sources[key]
22
+
22
23
  if key == "input":
23
24
  return self.input
25
+
24
26
  if key == "context":
25
27
  return self.context
28
+
26
29
  if key.startswith("gateway:"):
27
30
  return self._resolve_gateway(key)
31
+
28
32
  raise KeyError(f"Unknown source: {key}")
29
33
 
30
34
  def _resolve_gateway(self, key: str) -> Any:
31
35
  _, port = key.split(":")
32
36
  gateway = find_gateway_by_port(int(port)) if port else None
37
+
33
38
  if gateway:
34
39
  return gateway.get_context()
40
+
35
41
  return None
@@ -0,0 +1,133 @@
1
+ from typing import Type, Union, Literal, Optional, Dict, List, Tuple, Set, Annotated, Callable, Any
2
+ from abc import ABC, abstractmethod
3
+ from mindor.dsl.schema.component import HttpServerComponentConfig
4
+ from mindor.dsl.schema.action import ActionConfig, HttpServerActionConfig, HttpServerCompletionType, HttpServerCompletionConfig
5
+ from mindor.core.listener import HttpCallbackListener
6
+ from mindor.core.utils.http_client import HttpClient
7
+ from mindor.core.utils.http_status import is_status_code_matched
8
+ from mindor.core.utils.time import parse_duration
9
+ from mindor.core.utils.shell import run_command_streaming
10
+ from ..base import ComponentService, ComponentType, ComponentGlobalConfigs, register_component
11
+ from ..context import ComponentActionContext
12
+ from datetime import datetime, timezone
13
+ import asyncio, os
14
+
15
+ class HttpServerCompletion(ABC):
16
+ def __init__(self, config: HttpServerCompletionConfig):
17
+ self.config: HttpServerCompletionConfig = config
18
+
19
+ @abstractmethod
20
+ async def run(self, context: ComponentActionContext, client: HttpClient) -> Any:
21
+ pass
22
+
23
+ class HttpServerPollingCompletion(HttpServerCompletion):
24
+ async def run(self, context: ComponentActionContext, client: HttpClient) -> Any:
25
+ path = await context.render_variable(self.config.path)
26
+ method = await context.render_variable(self.config.method)
27
+ params = await context.render_variable(self.config.params)
28
+ body = await context.render_variable(self.config.body)
29
+ headers = await context.render_variable(self.config.headers)
30
+
31
+ interval = parse_duration((await context.render_variable(self.config.interval)) or 5.0)
32
+ timeout = parse_duration((await context.render_variable(self.config.timeout)) or 300.0)
33
+ deadline = datetime.now(timezone.utc) + timeout
34
+
35
+ await asyncio.sleep(interval.total_seconds())
36
+
37
+ while datetime.now(timezone.utc) < deadline:
38
+ response, status_code = await client.request(path or "", method, params, body, headers, raise_on_error=False)
39
+ context.register_source("result", response)
40
+
41
+ status = (await context.render_variable(self.config.status)) if self.config.status else None
42
+ if status:
43
+ if status in (self.config.success_when or []):
44
+ return response
45
+ if status in (self.config.fail_when or []):
46
+ raise RuntimeError(f"Polling failed: status '{status}' matched a failure condition.")
47
+ else: # use status code
48
+ if is_status_code_matched(status_code, self.config.success_when or []):
49
+ return response
50
+ if is_status_code_matched(status_code, self.config.fail_when or []):
51
+ raise RuntimeError(f"Polling failed: status code '{status_code}' matched a failure condition.")
52
+
53
+ await asyncio.sleep(interval.total_seconds())
54
+
55
+ raise TimeoutError(f"Polling timed out after {timeout}.")
56
+
57
+ class HttpServerCallbackCompletion(HttpServerCompletion):
58
+ async def run(self, context: ComponentActionContext, client: HttpClient) -> Any:
59
+ callback_id = await context.render_variable(self.config.wait_for)
60
+ future: asyncio.Future = asyncio.get_running_loop().create_future()
61
+ HttpCallbackListener.register_pending_future(callback_id, future)
62
+
63
+ return await future
64
+
65
+ class HttpServerAction:
66
+ def __init__(self, config: HttpServerActionConfig):
67
+ self.config: HttpServerActionConfig = config
68
+ self.completion: HttpServerCompletion = None
69
+
70
+ if self.config.completion:
71
+ self._configure_completion()
72
+
73
+ def _configure_completion(self) -> None:
74
+ if self.config.completion.type == HttpServerCompletionType.POLLING:
75
+ self.completion = HttpServerPollingCompletion(self.config.completion)
76
+ return
77
+
78
+ if self.config.completion.type == HttpServerCompletionType.CALLBACK:
79
+ self.completion = HttpServerCallbackCompletion(self.config.completion)
80
+ return
81
+
82
+ raise ValueError(f"Unsupported http completion type: {self.config.completion.type}")
83
+
84
+ async def run(self, context: ComponentActionContext, client: HttpClient) -> Any:
85
+ path = await context.render_variable(self.config.path)
86
+ method = await context.render_variable(self.config.method)
87
+ params = await context.render_variable(self.config.params)
88
+ body = await context.render_variable(self.config.body)
89
+ headers = await context.render_variable(self.config.headers)
90
+
91
+ response, result = await client.request(path or "", method, params, body, headers), None
92
+ context.register_source("response", response)
93
+
94
+ if self.completion:
95
+ result = await self.completion.run(context, client)
96
+ context.register_source("result", result)
97
+
98
+ return (await context.render_variable(self.config.output, ignore_files=True)) if self.config.output else (result or response)
99
+
100
+ @register_component(ComponentType.HTTP_SERVER)
101
+ class HttpServerComponent(ComponentService):
102
+ def __init__(self, id: str, config: HttpServerComponentConfig, global_configs: ComponentGlobalConfigs, daemon: bool):
103
+ super().__init__(id, config, global_configs, daemon)
104
+
105
+ self.client: Optional[HttpClient] = None
106
+
107
+ async def _install(self) -> None:
108
+ if self.config.commands.install:
109
+ await run_command_streaming(self.config.commands.install, self.config.working_dir, self.config.env)
110
+
111
+ async def _build(self) -> None:
112
+ if self.config.commands.build:
113
+ await run_command_streaming(self.config.commands.build, self.config.working_dir, self.config.env)
114
+
115
+ async def _start(self) -> None:
116
+ base_url = f"http://localhost:{self.config.port}" + (self.config.base_path or "")
117
+ self.client = HttpClient(base_url, self.config.headers)
118
+ await super()._start()
119
+
120
+ async def _stop(self) -> None:
121
+ await super()._stop()
122
+ await self.client.close()
123
+ self.client = None
124
+
125
+ async def _serve(self) -> None:
126
+ if self.config.commands.start:
127
+ await run_command_streaming(self.config.commands.start, self.config.working_dir, self.config.env, block=False)
128
+
129
+ async def _shutdown(self) -> None:
130
+ pass
131
+
132
+ async def _run(self, action: ActionConfig, context: ComponentActionContext) -> Any:
133
+ return await HttpServerAction(action).run(context, self.client)
@@ -1,6 +1,7 @@
1
1
  from typing import Type, Union, Literal, Optional, Dict, List, Tuple, Set, Annotated, Any
2
2
  from mindor.dsl.schema.component import ShellComponentConfig
3
3
  from mindor.dsl.schema.action import ActionConfig, ShellActionConfig
4
+ from mindor.core.utils.shell import run_command
4
5
  from ..base import ComponentService, ComponentType, ComponentGlobalConfigs, register_component
5
6
  from ..context import ComponentActionContext
6
7
  from asyncio.subprocess import Process
@@ -22,24 +23,12 @@ class ShellAction:
22
23
  return (await context.render_variable(self.config.output, ignore_files=True)) if self.config.output else result
23
24
 
24
25
  async def _run_command(self, command: List[str], working_dir: str, env: Dict[str, str], timeout: Optional[float]) -> Dict[str, Any]:
25
- process = await asyncio.create_subprocess_exec(
26
- *command,
27
- cwd=working_dir,
28
- env={ **os.environ, **env },
29
- stdout=asyncio.subprocess.PIPE,
30
- stderr=asyncio.subprocess.PIPE
31
- )
32
-
33
- try:
34
- stdout, stderr = await asyncio.wait_for(process.communicate(), timeout=timeout)
35
- except asyncio.TimeoutError:
36
- if await self._kill_process(process):
37
- raise RuntimeError(f"Command timed out: {' '.join(command)}")
26
+ stdout, stderr, exit_code = await run_command(command, working_dir, env, timeout)
38
27
 
39
28
  return {
40
29
  "stdout": stdout.decode().strip(),
41
30
  "stderr": stderr.decode().strip(),
42
- "exit_code": process.returncode
31
+ "exit_code": exit_code
43
32
  }
44
33
 
45
34
  async def _kill_process(self, process: Process) -> bool:
@@ -55,6 +44,7 @@ class ShellAction:
55
44
 
56
45
  async def _resolve_working_directory(self) -> str:
57
46
  working_dir = self.config.working_dir
47
+
58
48
  if working_dir:
59
49
  if self.base_dir:
60
50
  working_dir = os.path.abspath(os.path.join(self.base_dir, working_dir))
@@ -62,6 +52,7 @@ class ShellAction:
62
52
  working_dir = os.path.abspath(working_dir)
63
53
  else:
64
54
  working_dir = self.base_dir or os.getcwd()
55
+
65
56
  return working_dir
66
57
 
67
58
  @register_component(ComponentType.SHELL)
@@ -16,6 +16,7 @@ from mindor.core.gateway import GatewayService, create_gateway
16
16
  from mindor.core.workflow import Workflow, WorkflowResolver, create_workflow
17
17
  from mindor.core.logger import LoggerService, create_logger
18
18
  from mindor.core.controller.webui import ControllerWebUI
19
+ from mindor.core.workflow.schema import WorkflowSchema, create_workflow_schemas
19
20
  from mindor.core.utils.workqueue import WorkQueue
20
21
  from mindor.core.utils.caching import ExpiringDict
21
22
  from .runtime.specs import ControllerRuntimeSpecs
@@ -55,12 +56,13 @@ class ControllerService(AsyncService):
55
56
  self.listeners: List[ListenerConfig] = listeners
56
57
  self.gateways: List[GatewayConfig] = gateways
57
58
  self.loggers: List[LoggerConfig] = loggers
58
- self.queue: Optional[WorkQueue] = None
59
+ self.workflow_schemas: Dict[str, WorkflowSchema] = create_workflow_schemas(self.workflows, self.components)
60
+ self.task_queue: Optional[WorkQueue] = None
59
61
  self.task_states: ExpiringDict[TaskState] = ExpiringDict()
60
62
  self.task_states_lock: Lock = Lock()
61
-
63
+
62
64
  if self.config.max_concurrent_count > 0:
63
- self.queue = WorkQueue(self.config.max_concurrent_count, self._run_workflow)
65
+ self.task_queue = WorkQueue(self.config.max_concurrent_count, self._run_workflow)
64
66
 
65
67
  async def launch(self, detach: bool, verbose: bool) -> None:
66
68
  if self.config.runtime.type == RuntimeType.NATIVE:
@@ -92,8 +94,8 @@ class ControllerService(AsyncService):
92
94
  self.task_states.set(task_id, state)
93
95
 
94
96
  if wait_for_completion:
95
- if self.queue:
96
- state = await (await self.queue.schedule(task_id, workflow_id, input))
97
+ if self.task_queue:
98
+ state = await (await self.task_queue.schedule(task_id, workflow_id, input))
97
99
  else:
98
100
  state = await self._run_workflow(task_id, workflow_id, input)
99
101
  else:
@@ -106,8 +108,8 @@ class ControllerService(AsyncService):
106
108
  return self.task_states.get(task_id)
107
109
 
108
110
  async def _start(self) -> None:
109
- if self.queue:
110
- await self.queue.start()
111
+ if self.task_queue:
112
+ await self.task_queue.start()
111
113
 
112
114
  if self.daemon:
113
115
  await self._start_loggers()
@@ -121,8 +123,8 @@ class ControllerService(AsyncService):
121
123
  await super()._start()
122
124
 
123
125
  async def _stop(self) -> None:
124
- if self.queue:
125
- await self.queue.stop()
126
+ if self.task_queue:
127
+ await self.task_queue.stop()
126
128
 
127
129
  if self.daemon:
128
130
  await self._stop_components()
@@ -34,7 +34,7 @@ class HttpControllerClient(ControllerClient):
34
34
  await self.client.close()
35
35
 
36
36
  def _resolve_controller_url(self) -> str:
37
- return f"http://localhost:{self.config.port}{self.config.base_path or ''}"
37
+ return f"http://localhost:{self.config.port}" + (self.config.base_path or "")
38
38
 
39
39
  def _flatten_for_multipart(self, data: Dict[str, Any], key: str = "") -> List[Tuple[str, Any]]:
40
40
  flattened = []
@@ -23,7 +23,7 @@ class McpControllerClient(ControllerClient):
23
23
  await self.client.close()
24
24
 
25
25
  def _resolve_controller_url(self) -> str:
26
- return f"http://localhost:{self.config.port}{self.config.base_path or ''}"
26
+ return f"http://localhost:{self.config.port}" + (self.config.base_path or "")
27
27
 
28
28
  async def _call_tool(self, name: str, arguments: Optional[Dict[str, Any]], workflow: WorkflowSchema) -> Any:
29
29
  contents = await self.client.call_tool(name, arguments)
@@ -7,11 +7,11 @@ from mindor.dsl.schema.component import ComponentConfig
7
7
  from mindor.dsl.schema.listener import ListenerConfig
8
8
  from mindor.dsl.schema.gateway import GatewayConfig
9
9
  from mindor.dsl.schema.logger import LoggerConfig
10
- from mindor.dsl.schema.workflow import WorkflowConfig
10
+ from mindor.dsl.schema.workflow import WorkflowConfig, WorkflowVariableConfig, WorkflowVariableGroupConfig
11
11
  from mindor.core.utils.http_request import parse_request_body, parse_options_header
12
12
  from mindor.core.utils.http_client import HttpEventStreamResource
13
13
  from mindor.core.utils.streaming import StreamResource
14
- from ..base import ControllerService, ControllerType, TaskState, TaskStatus, register_controller
14
+ from ..base import ControllerService, ControllerType, WorkflowSchema, TaskState, TaskStatus, register_controller
15
15
  from fastapi import FastAPI, APIRouter, Request, Body, HTTPException
16
16
  from fastapi.middleware.cors import CORSMiddleware
17
17
  from fastapi.responses import Response, JSONResponse, StreamingResponse
@@ -39,6 +39,57 @@ class TaskResult(BaseModel):
39
39
  error=instance.error
40
40
  )
41
41
 
42
+ class WorkflowVariableResult(BaseModel):
43
+ name: Optional[str]
44
+ type: str
45
+ subtype: Optional[str]
46
+ format: Optional[str]
47
+ default: Optional[str]
48
+
49
+ @classmethod
50
+ def from_instance(cls, instance: WorkflowVariableConfig) -> Self:
51
+ return cls(
52
+ name=instance.name,
53
+ type=instance.type,
54
+ subtype=instance.subtype,
55
+ format=instance.format,
56
+ default=instance.default
57
+ )
58
+
59
+ class WorkflowVariableGroupResult(BaseModel):
60
+ name: Optional[str]
61
+ variables: List[WorkflowVariableResult]
62
+
63
+ @classmethod
64
+ def from_instance(cls, instance: WorkflowVariableGroupConfig) -> Self:
65
+ return cls(
66
+ name=instance.name,
67
+ variables=[ WorkflowVariableResult.from_instance(variable) for variable in instance.variables ]
68
+ )
69
+
70
+ class WorkflowSchemaResult(BaseModel):
71
+ workflow_id: str
72
+ title: Optional[str] = None
73
+ description: Optional[str] = None
74
+ input: List[WorkflowVariableResult]
75
+ output: List[Union[WorkflowVariableResult, WorkflowVariableGroupResult]]
76
+
77
+ @classmethod
78
+ def from_instance(cls, instance: WorkflowSchema) -> Self:
79
+ return cls(
80
+ workflow_id=instance.workflow_id,
81
+ title=instance.title,
82
+ description=instance.description,
83
+ input=[ cls._to_variable_result(variable) for variable in instance.input ],
84
+ output=[ cls._to_variable_result(variable) for variable in instance.output ],
85
+ )
86
+
87
+ @classmethod
88
+ def _to_variable_result(cls, variable: Union[WorkflowVariableConfig, WorkflowVariableGroupConfig ]) -> Union[WorkflowVariableResult, WorkflowVariableGroupResult]:
89
+ if isinstance(variable, WorkflowVariableGroupConfig):
90
+ return WorkflowVariableGroupResult.from_instance(variable)
91
+ return WorkflowVariableResult.from_instance(variable)
92
+
42
93
  @register_controller(ControllerType.HTTP_SERVER)
43
94
  class HttpServerController(ControllerService):
44
95
  def __init__(
@@ -107,6 +158,27 @@ class HttpServerController(ControllerService):
107
158
 
108
159
  return self._render_task_state(state)
109
160
 
161
+ @self.router.get("/tasks/{task_id}/jobs")
162
+ async def get_task_jobs(
163
+ task_id: str
164
+ ):
165
+ return None
166
+
167
+ @self.router.get("/workflows")
168
+ async def get_workflow_schemas():
169
+ return self._render_workflow_schemas(self.workflow_schemas)
170
+
171
+ @self.router.get("/workflows/{workflow_id}")
172
+ async def get_workflow_schema(
173
+ workflow_id: str,
174
+ ):
175
+ workflow = self.workflow_schemas[workflow_id] if workflow_id in self.workflow_schemas else None
176
+
177
+ if not workflow:
178
+ raise HTTPException(status_code=404, detail="Workflow not found.")
179
+
180
+ return self._render_workflow_schema(workflow)
181
+
110
182
  async def _serve(self) -> None:
111
183
  self.server = uvicorn.Server(uvicorn.Config(
112
184
  self.app,
@@ -203,3 +275,11 @@ class HttpServerController(ControllerService):
203
275
  headers["Content-Disposition"] = f'attachment; filename="{filename}"'
204
276
 
205
277
  return headers
278
+
279
+ def _render_workflow_schemas(self, workflows: Dict[str, WorkflowSchema]) -> Response:
280
+ return JSONResponse(content={
281
+ workflow_id: WorkflowSchemaResult.from_instance(workflow).model_dump(exclude_none=True) for workflow_id, workflow in workflows.items()
282
+ })
283
+
284
+ def _render_workflow_schema(self, workflow: WorkflowSchema) -> Response:
285
+ return JSONResponse(content=WorkflowSchemaResult.from_instance(workflow).model_dump(exclude_none=True))
@@ -5,7 +5,7 @@ from mindor.dsl.schema.listener import ListenerConfig
5
5
  from mindor.dsl.schema.gateway import GatewayConfig
6
6
  from mindor.dsl.schema.logger import LoggerConfig
7
7
  from mindor.dsl.schema.workflow import WorkflowConfig, WorkflowVariableConfig, WorkflowVariableType, WorkflowVariableFormat
8
- from mindor.core.workflow.schema import WorkflowSchema, create_workflow_schema
8
+ from mindor.core.workflow.schema import WorkflowSchema
9
9
  from mindor.core.utils.streaming import StreamResource, Base64StreamResource
10
10
  from mindor.core.utils.streaming import save_stream_to_temporary_file
11
11
  from mindor.core.utils.http_client import create_stream_with_url
@@ -150,9 +150,7 @@ class McpServerController(ControllerService):
150
150
  self._configure_tools()
151
151
 
152
152
  def _configure_tools(self) -> None:
153
- schema = create_workflow_schema(self.workflows, self.components)
154
-
155
- for workflow_id, workflow in schema.items():
153
+ for workflow_id, workflow in self.workflow_schemas.items():
156
154
  fn, description = WorkflowToolGenerator().generate(workflow_id, workflow, self._run_workflow_as_tool)
157
155
  self.app.add_tool(
158
156
  fn=fn,
@@ -20,13 +20,13 @@ class GradioWebUIBuilder:
20
20
  def __init__(self):
21
21
  self.field_resolver: FieldResolver = FieldResolver()
22
22
 
23
- def build(self, schema: Dict[str, WorkflowSchema], runner: Callable[[Optional[str], Any], Awaitable[Any]]) -> gr.Blocks:
23
+ def build(self, workflow_schemas: Dict[str, WorkflowSchema], workflow_runner: Callable[[Optional[str], Any], Awaitable[Any]]) -> gr.Blocks:
24
24
  with gr.Blocks() as blocks:
25
- for workflow_id, workflow in schema.items():
25
+ for workflow_id, workflow in workflow_schemas.items():
26
26
  async def _run_workflow(input: Any, workflow_id=workflow_id) -> Any:
27
- return await runner(workflow_id, input)
27
+ return await workflow_runner(workflow_id, input)
28
28
 
29
- if len(schema) > 1:
29
+ if len(workflow_schemas) > 1:
30
30
  with gr.Tab(label=workflow.name or workflow_id):
31
31
  self._build_workflow_section(workflow, _run_workflow)
32
32
  else:
@@ -37,7 +37,7 @@ class GradioWebUIBuilder:
37
37
  def _build_workflow_section(self, workflow: WorkflowSchema, runner: Callable[[Any], Awaitable[Any]]) -> gr.Column:
38
38
  with gr.Column() as section:
39
39
  gr.Markdown(f"## **{workflow.title or 'Untitled Workflow'}**")
40
-
40
+
41
41
  if workflow.description:
42
42
  gr.Markdown(f"📝 {workflow.description}")
43
43
 
@@ -47,14 +47,14 @@ class GradioWebUIBuilder:
47
47
 
48
48
  gr.Markdown("#### 📤 Output Values")
49
49
  output_components = [ self._build_output_component(variable) for variable in workflow.output ]
50
-
50
+
51
51
  if not output_components:
52
52
  output_components = [ gr.Textbox(label="", lines=10, interactive=False, show_copy_button=True) ]
53
53
 
54
54
  async def _run_workflow(*args):
55
55
  input = await self._build_input_value(args, workflow.input)
56
56
  output = await runner(input)
57
-
57
+
58
58
  if len(workflow.output) == 1 and self._is_streaming_variable(workflow.output[0]):
59
59
  text = ""
60
60
  async for chunk in output:
@@ -81,7 +81,7 @@ class GradioWebUIBuilder:
81
81
  if isinstance(variable, WorkflowVariableConfig):
82
82
  return variable.format in [ WorkflowVariableFormat.SSE_JSON, WorkflowVariableFormat.SSE_TEXT ]
83
83
  return False
84
-
84
+
85
85
  def _build_input_component(self, variable: WorkflowVariableConfig) -> gr.Component:
86
86
  label = (variable.name or "") + (" *" if variable.required else "") + (f" (default: {variable.default})" if variable.default else "")
87
87
  info = variable.get_annotation_value("description") or ""
@@ -4,14 +4,14 @@ from mindor.dsl.schema.controller.webui import ControllerWebUIConfig, Controller
4
4
  from mindor.dsl.schema.component import ComponentConfig
5
5
  from mindor.dsl.schema.workflow import WorkflowConfig
6
6
  from mindor.core.controller.runner import ControllerRunner
7
- from mindor.core.workflow.schema import create_workflow_schema
7
+ from mindor.core.workflow.schema import WorkflowSchema, create_workflow_schemas
8
8
  from mindor.core.services import AsyncService
9
9
  from .gradio import GradioWebUIBuilder
10
10
  from gradio import mount_gradio_app
11
11
  from fastapi import FastAPI
12
12
  from fastapi.staticfiles import StaticFiles
13
13
  from pathlib import Path
14
- import uvicorn, gradio
14
+ import uvicorn
15
15
 
16
16
  class ControllerWebUI(AsyncService):
17
17
  def __init__(
@@ -26,7 +26,7 @@ class ControllerWebUI(AsyncService):
26
26
 
27
27
  self.config: ControllerWebUIConfig = config
28
28
  self.controller: ControllerConfig = controller
29
- self.schema = create_workflow_schema(workflows, components)
29
+ self.workflow_schemas: Dict[str, WorkflowSchema] = create_workflow_schemas(workflows, components)
30
30
 
31
31
  self.server: Optional[uvicorn.Server] = None
32
32
  self.app: FastAPI = FastAPI(openapi_url=None, docs_url=None, redoc_url=None)
@@ -36,13 +36,13 @@ class ControllerWebUI(AsyncService):
36
36
 
37
37
  def _configure_driver(self) -> None:
38
38
  if self.config.driver == ControllerWebUIDriver.GRADIO:
39
- blocks: gradio.Blocks = GradioWebUIBuilder().build(
40
- schema=self.schema,
41
- runner=self._run_workflow
39
+ blocks = GradioWebUIBuilder().build(
40
+ workflow_schemas=self.workflow_schemas,
41
+ workflow_runner=self._run_workflow
42
42
  )
43
43
  self.app = mount_gradio_app(self.app, blocks, path="")
44
44
  return
45
-
45
+
46
46
  if self.config.driver == ControllerWebUIDriver.STATIC:
47
47
  static_files = StaticFiles(
48
48
  directory=Path(self.config.static_dir).resolve(),
@@ -70,5 +70,5 @@ class ControllerWebUI(AsyncService):
70
70
 
71
71
  async def _run_workflow(self, workflow_id: Optional[str], input: Any) -> Any:
72
72
  if self.runner:
73
- return await self.runner.run_workflow(workflow_id, input, self.schema[workflow_id])
73
+ return await self.runner.run_workflow(workflow_id, input, self.workflow_schemas[workflow_id])
74
74
  return None
@@ -41,8 +41,10 @@ class HttpCallbackContext:
41
41
  async def _resolve_source(self, key: str, index: Optional[int]) -> Any:
42
42
  if key == "body" or key == "item":
43
43
  return self.body
44
+
44
45
  if key == "query":
45
46
  return self.query
47
+
46
48
  raise KeyError(f"Unknown source: {key}")
47
49
 
48
50
  @register_listener(ListenerType.HTTP_CALLBACK)
@@ -17,3 +17,13 @@ def load_env_files(work_dir: Union[ str, Path ], env_files: List[Union[ str, Pat
17
17
  merged_env.update({k: v for k, v in env_dict.items() if v is not None})
18
18
 
19
19
  return merged_env
20
+
21
+ def merge_env_data(env: Dict[str, str], env_data: List[str]) -> Dict[str, str]:
22
+ for env_entry in env_data:
23
+ if "=" not in env_entry:
24
+ raise ValueError(f"Invalid env entry: {env_entry}")
25
+
26
+ key, value = env_entry.split("=", 1)
27
+ env[key] = value
28
+
29
+ return env