model-compose 0.3.6__tar.gz → 0.3.8__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 (220) hide show
  1. {model_compose-0.3.6/src/model_compose.egg-info → model_compose-0.3.8}/PKG-INFO +1 -1
  2. {model_compose-0.3.6 → model_compose-0.3.8}/pyproject.toml +1 -1
  3. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/cli/compose.py +7 -2
  4. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/core/component/base.py +12 -0
  5. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/core/component/context.py +6 -0
  6. model_compose-0.3.8/src/mindor/core/component/services/http_server.py +137 -0
  7. model_compose-0.3.8/src/mindor/core/component/services/mcp_server.py +68 -0
  8. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/core/component/services/shell.py +8 -29
  9. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/core/compose/compose.py +1 -1
  10. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/core/compose/manager.py +4 -4
  11. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/core/controller/base.py +80 -20
  12. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/core/controller/runner/http_client.py +1 -1
  13. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/core/controller/runner/mcp_client.py +1 -1
  14. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/core/controller/runtime/docker/docker.py +9 -3
  15. model_compose-0.3.8/src/mindor/core/controller/runtime/native/__init__.py +1 -0
  16. model_compose-0.3.8/src/mindor/core/controller/runtime/native/native.py +24 -0
  17. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/core/controller/services/http_server.py +82 -2
  18. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/core/controller/services/mcp_server.py +2 -4
  19. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/core/controller/webui/gradio.py +8 -8
  20. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/core/controller/webui/webui.py +8 -8
  21. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/core/listener/services/http_callback.py +2 -0
  22. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/core/runtime/env.py +10 -0
  23. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/core/services/async_service.py +5 -0
  24. model_compose-0.3.8/src/mindor/core/utils/shell.py +70 -0
  25. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/core/workflow/context.py +3 -0
  26. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/core/workflow/schema.py +6 -3
  27. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/dsl/schema/action/impl/http_client.py +18 -18
  28. model_compose-0.3.8/src/mindor/dsl/schema/action/impl/http_server.py +52 -0
  29. model_compose-0.3.8/src/mindor/dsl/schema/action/impl/mcp_server.py +9 -0
  30. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/dsl/schema/component/impl/http_client.py +1 -1
  31. model_compose-0.3.8/src/mindor/dsl/schema/component/impl/http_server.py +43 -0
  32. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/dsl/schema/component/impl/mcp_client.py +1 -1
  33. model_compose-0.3.8/src/mindor/dsl/schema/component/impl/mcp_server.py +27 -0
  34. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/dsl/schema/component/impl/model/impl/summarization.py +1 -1
  35. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/dsl/schema/component/impl/model/impl/text_classification.py +1 -1
  36. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/dsl/schema/component/impl/model/impl/text_embedding.py +1 -1
  37. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/dsl/schema/component/impl/model/impl/text_generation.py +1 -1
  38. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/dsl/schema/component/impl/model/impl/translation.py +1 -1
  39. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/dsl/schema/controller/impl/common.py +3 -3
  40. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/dsl/schema/controller/impl/http_server.py +2 -2
  41. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/dsl/schema/controller/impl/mcp_server.py +2 -2
  42. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/dsl/schema/controller/webui/impl/common.py +2 -2
  43. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/dsl/schema/gateway/impl/common.py +1 -1
  44. {model_compose-0.3.6 → model_compose-0.3.8/src/model_compose.egg-info}/PKG-INFO +1 -1
  45. {model_compose-0.3.6 → model_compose-0.3.8}/src/model_compose.egg-info/SOURCES.txt +3 -0
  46. model_compose-0.3.6/src/mindor/core/component/services/http_server.py +0 -26
  47. model_compose-0.3.6/src/mindor/core/component/services/mcp_server.py +0 -27
  48. model_compose-0.3.6/src/mindor/dsl/schema/action/impl/http_server.py +0 -8
  49. model_compose-0.3.6/src/mindor/dsl/schema/action/impl/mcp_server.py +0 -7
  50. model_compose-0.3.6/src/mindor/dsl/schema/component/impl/http_server.py +0 -11
  51. model_compose-0.3.6/src/mindor/dsl/schema/component/impl/mcp_server.py +0 -9
  52. {model_compose-0.3.6 → model_compose-0.3.8}/LICENSE +0 -0
  53. {model_compose-0.3.6 → model_compose-0.3.8}/README.md +0 -0
  54. {model_compose-0.3.6 → model_compose-0.3.8}/setup.cfg +0 -0
  55. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/__init__.py +0 -0
  56. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/cli/__init__.py +0 -0
  57. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/core/__init__.py +0 -0
  58. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/core/component/__init__.py +0 -0
  59. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/core/component/component.py +0 -0
  60. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/core/component/services/__init__.py +0 -0
  61. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/core/component/services/http_client.py +0 -0
  62. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/core/component/services/mcp_client.py +0 -0
  63. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/core/component/services/model/__init__.py +0 -0
  64. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/core/component/services/model/base.py +0 -0
  65. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/core/component/services/model/model.py +0 -0
  66. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/core/component/services/model/tasks/__init__.py +0 -0
  67. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/core/component/services/model/tasks/summarization.py +0 -0
  68. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/core/component/services/model/tasks/text_classification.py +0 -0
  69. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/core/component/services/model/tasks/text_embedding.py +0 -0
  70. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/core/component/services/model/tasks/text_generation.py +0 -0
  71. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/core/component/services/model/tasks/translation.py +0 -0
  72. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/core/component/services/text_splitter.py +0 -0
  73. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/core/component/services/workflow.py +0 -0
  74. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/core/compose/__init__.py +0 -0
  75. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/core/controller/__init__.py +0 -0
  76. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/core/controller/controller.py +0 -0
  77. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/core/controller/runner/__init__.py +0 -0
  78. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/core/controller/runner/client.py +0 -0
  79. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/core/controller/runner/runner.py +0 -0
  80. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/core/controller/runtime/__init__.py +0 -0
  81. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/core/controller/runtime/docker/__init__.py +0 -0
  82. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/core/controller/runtime/docker/context/Dockerfile +0 -0
  83. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/core/controller/runtime/specs.py +0 -0
  84. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/core/controller/services/__init__.py +0 -0
  85. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/core/controller/webui/__init__.py +0 -0
  86. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/core/gateway/__init__.py +0 -0
  87. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/core/gateway/base.py +0 -0
  88. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/core/gateway/gateway.py +0 -0
  89. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/core/gateway/services/__init__.py +0 -0
  90. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/core/gateway/services/http_tunnel.py +0 -0
  91. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/core/gateway/services/ssh_tunnel.py +0 -0
  92. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/core/listener/__init__.py +0 -0
  93. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/core/listener/base.py +0 -0
  94. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/core/listener/listener.py +0 -0
  95. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/core/listener/services/__init__.py +0 -0
  96. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/core/logger/__init__.py +0 -0
  97. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/core/logger/base.py +0 -0
  98. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/core/logger/logger.py +0 -0
  99. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/core/logger/logging.py +0 -0
  100. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/core/logger/services/__init__.py +0 -0
  101. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/core/logger/services/console.py +0 -0
  102. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/core/logger/services/file.py +0 -0
  103. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/core/runtime/__init__.py +0 -0
  104. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/core/runtime/docker/__init__.py +0 -0
  105. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/core/runtime/docker/docker.py +0 -0
  106. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/core/services/__init__.py +0 -0
  107. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/core/utils/__init__.py +0 -0
  108. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/core/utils/caching.py +0 -0
  109. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/core/utils/http_client.py +0 -0
  110. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/core/utils/http_request.py +0 -0
  111. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/core/utils/http_status.py +0 -0
  112. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/core/utils/image.py +0 -0
  113. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/core/utils/mcp_client.py +0 -0
  114. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/core/utils/renderers.py +0 -0
  115. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/core/utils/resolvers.py +0 -0
  116. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/core/utils/ssh_client.py +0 -0
  117. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/core/utils/streamer.py +0 -0
  118. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/core/utils/streaming.py +0 -0
  119. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/core/utils/time.py +0 -0
  120. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/core/utils/workqueue.py +0 -0
  121. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/core/workflow/__init__.py +0 -0
  122. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/core/workflow/job/__init__.py +0 -0
  123. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/core/workflow/job/base.py +0 -0
  124. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/core/workflow/job/impl/__init__.py +0 -0
  125. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/core/workflow/job/impl/action.py +0 -0
  126. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/core/workflow/job/impl/delay.py +0 -0
  127. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/core/workflow/job/impl/if_.py +0 -0
  128. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/core/workflow/job/impl/random_router.py +0 -0
  129. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/core/workflow/job/impl/switch.py +0 -0
  130. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/core/workflow/job/job.py +0 -0
  131. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/core/workflow/workflow.py +0 -0
  132. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/dsl/__init__.py +0 -0
  133. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/dsl/loader.py +0 -0
  134. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/dsl/schema/__init__.py +0 -0
  135. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/dsl/schema/action/__init__.py +0 -0
  136. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/dsl/schema/action/action.py +0 -0
  137. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/dsl/schema/action/impl/__init__.py +0 -0
  138. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/dsl/schema/action/impl/common.py +0 -0
  139. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/dsl/schema/action/impl/mcp_client.py +0 -0
  140. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/dsl/schema/action/impl/model/__init__.py +0 -0
  141. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/dsl/schema/action/impl/model/impl/__init__.py +0 -0
  142. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/dsl/schema/action/impl/model/impl/common.py +0 -0
  143. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/dsl/schema/action/impl/model/impl/summarization.py +0 -0
  144. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/dsl/schema/action/impl/model/impl/text_classification.py +0 -0
  145. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/dsl/schema/action/impl/model/impl/text_embedding.py +0 -0
  146. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/dsl/schema/action/impl/model/impl/text_generation.py +0 -0
  147. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/dsl/schema/action/impl/model/impl/translation.py +0 -0
  148. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/dsl/schema/action/impl/model/model.py +0 -0
  149. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/dsl/schema/action/impl/shell.py +0 -0
  150. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/dsl/schema/action/impl/text_splitter.py +0 -0
  151. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/dsl/schema/action/impl/workflow.py +0 -0
  152. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/dsl/schema/component/__init__.py +0 -0
  153. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/dsl/schema/component/component.py +0 -0
  154. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/dsl/schema/component/impl/__init__.py +0 -0
  155. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/dsl/schema/component/impl/common.py +0 -0
  156. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/dsl/schema/component/impl/model/__init__.py +0 -0
  157. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/dsl/schema/component/impl/model/impl/__init__.py +0 -0
  158. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/dsl/schema/component/impl/model/impl/common.py +0 -0
  159. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/dsl/schema/component/impl/model/impl/types.py +0 -0
  160. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/dsl/schema/component/impl/model/model.py +0 -0
  161. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/dsl/schema/component/impl/shell.py +0 -0
  162. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/dsl/schema/component/impl/text_splitter.py +0 -0
  163. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/dsl/schema/component/impl/types.py +0 -0
  164. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/dsl/schema/component/impl/workflow.py +0 -0
  165. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/dsl/schema/compose.py +0 -0
  166. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/dsl/schema/controller/__init__.py +0 -0
  167. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/dsl/schema/controller/controller.py +0 -0
  168. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/dsl/schema/controller/impl/__init__.py +0 -0
  169. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/dsl/schema/controller/impl/types.py +0 -0
  170. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/dsl/schema/controller/webui/__init__.py +0 -0
  171. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/dsl/schema/controller/webui/impl/__init__.py +0 -0
  172. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/dsl/schema/controller/webui/impl/dynamic.py +0 -0
  173. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/dsl/schema/controller/webui/impl/gradio.py +0 -0
  174. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/dsl/schema/controller/webui/impl/static.py +0 -0
  175. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/dsl/schema/controller/webui/webui.py +0 -0
  176. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/dsl/schema/gateway/__init__.py +0 -0
  177. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/dsl/schema/gateway/gateway.py +0 -0
  178. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/dsl/schema/gateway/impl/__init__.py +0 -0
  179. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/dsl/schema/gateway/impl/http_tunnel.py +0 -0
  180. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/dsl/schema/gateway/impl/ssh_tunnel.py +0 -0
  181. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/dsl/schema/gateway/impl/types.py +0 -0
  182. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/dsl/schema/job/__init__.py +0 -0
  183. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/dsl/schema/job/impl/__init__.py +0 -0
  184. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/dsl/schema/job/impl/action.py +0 -0
  185. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/dsl/schema/job/impl/common.py +0 -0
  186. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/dsl/schema/job/impl/delay.py +0 -0
  187. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/dsl/schema/job/impl/if_.py +0 -0
  188. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/dsl/schema/job/impl/random_router.py +0 -0
  189. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/dsl/schema/job/impl/switch.py +0 -0
  190. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/dsl/schema/job/impl/types.py +0 -0
  191. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/dsl/schema/job/job.py +0 -0
  192. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/dsl/schema/listener/__init__.py +0 -0
  193. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/dsl/schema/listener/impl/__init__.py +0 -0
  194. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/dsl/schema/listener/impl/common.py +0 -0
  195. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/dsl/schema/listener/impl/http_callback.py +0 -0
  196. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/dsl/schema/listener/impl/types.py +0 -0
  197. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/dsl/schema/listener/listener.py +0 -0
  198. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/dsl/schema/logger/__init__.py +0 -0
  199. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/dsl/schema/logger/impl/__init__.py +0 -0
  200. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/dsl/schema/logger/impl/common.py +0 -0
  201. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/dsl/schema/logger/impl/console.py +0 -0
  202. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/dsl/schema/logger/impl/file.py +0 -0
  203. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/dsl/schema/logger/impl/types.py +0 -0
  204. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/dsl/schema/logger/logger.py +0 -0
  205. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/dsl/schema/runtime/__init__.py +0 -0
  206. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/dsl/schema/runtime/impl/__init__.py +0 -0
  207. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/dsl/schema/runtime/impl/common.py +0 -0
  208. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/dsl/schema/runtime/impl/docker.py +0 -0
  209. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/dsl/schema/runtime/impl/native.py +0 -0
  210. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/dsl/schema/runtime/impl/types.py +0 -0
  211. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/dsl/schema/runtime/runtime.py +0 -0
  212. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/dsl/schema/workflow.py +0 -0
  213. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/dsl/utils/__init__.py +0 -0
  214. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/dsl/utils/annotation.py +0 -0
  215. {model_compose-0.3.6 → model_compose-0.3.8}/src/mindor/dsl/utils/enum.py +0 -0
  216. {model_compose-0.3.6 → model_compose-0.3.8}/src/model_compose.egg-info/dependency_links.txt +0 -0
  217. {model_compose-0.3.6 → model_compose-0.3.8}/src/model_compose.egg-info/entry_points.txt +0 -0
  218. {model_compose-0.3.6 → model_compose-0.3.8}/src/model_compose.egg-info/requires.txt +0 -0
  219. {model_compose-0.3.6 → model_compose-0.3.8}/src/model_compose.egg-info/top_level.txt +0 -0
  220. {model_compose-0.3.6 → model_compose-0.3.8}/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.8
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.8"
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 setup(self) -> None:
61
+ await self._setup()
62
+
63
+ async def teardown(self) -> None:
64
+ await self._teardown()
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 _setup(self) -> None:
76
+ pass
77
+
78
+ async def _teardown(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,137 @@
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
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 _setup(self) -> None:
108
+ if self.config.commands.install:
109
+ for command in self.config.commands.install:
110
+ await run_command_streaming(command, self.config.working_dir, self.config.env)
111
+
112
+ if self.config.commands.build:
113
+ for command in self.config.commands.build:
114
+ await run_command_streaming(command, self.config.working_dir, self.config.env)
115
+
116
+ async def _teardown(self):
117
+ pass
118
+
119
+ async def _start(self) -> None:
120
+ base_url = f"http://localhost:{self.config.port}" + (self.config.base_path or "")
121
+ self.client = HttpClient(base_url, self.config.headers)
122
+ await super()._start()
123
+
124
+ async def _stop(self) -> None:
125
+ await super()._stop()
126
+ await self.client.close()
127
+ self.client = None
128
+
129
+ async def _serve(self) -> None:
130
+ if self.config.commands.start:
131
+ await run_command_streaming(self.config.commands.start, self.config.working_dir, self.config.env, block=False)
132
+
133
+ async def _shutdown(self) -> None:
134
+ pass
135
+
136
+ async def _run(self, action: ActionConfig, context: ComponentActionContext) -> Any:
137
+ return await HttpServerAction(action).run(context, self.client)
@@ -0,0 +1,68 @@
1
+ from typing import Type, Union, Literal, Optional, Dict, List, Tuple, Set, Annotated, Any
2
+ from mindor.dsl.schema.component import McpServerComponentConfig
3
+ from mindor.dsl.schema.action import ActionConfig, McpServerActionConfig
4
+ from mindor.core.utils.mcp_client import McpClient, ContentBlock, TextContent, ImageContent, AudioContent
5
+ from mindor.core.utils.shell import run_command_streaming
6
+ from ..base import ComponentService, ComponentType, ComponentGlobalConfigs, register_component
7
+ from ..context import ComponentActionContext
8
+
9
+ class McpServerAction:
10
+ def __init__(self, config: McpServerActionConfig):
11
+ self.config: McpServerActionConfig = config
12
+
13
+ async def run(self, context: ComponentActionContext, client: McpClient) -> Any:
14
+ tool = await context.render_variable(self.config.tool)
15
+ arguments = await context.render_variable(self.config.arguments)
16
+
17
+ response = [ await self._convert_output_value(content) for content in await client.call_tool(tool, arguments) ]
18
+ context.register_source("response", response)
19
+
20
+ return (await context.render_variable(self.config.output, ignore_files=True)) if self.config.output else response
21
+
22
+ async def _convert_output_value(self, content: ContentBlock) -> Any:
23
+ if isinstance(content, TextContent):
24
+ return content.text
25
+
26
+ if isinstance(content, (ImageContent, AudioContent)):
27
+ return content.data
28
+
29
+ return None
30
+
31
+ @register_component(ComponentType.MCP_SERVER)
32
+ class McpServerComponent(ComponentService):
33
+ def __init__(self, id: str, config: McpServerComponentConfig, global_configs: ComponentGlobalConfigs, daemon: bool):
34
+ super().__init__(id, config, global_configs, daemon)
35
+
36
+ self.client: Optional[McpClient] = None
37
+
38
+ async def _setup(self) -> None:
39
+ if self.config.commands.install:
40
+ for command in self.config.commands.install:
41
+ await run_command_streaming(command, self.config.working_dir, self.config.env)
42
+
43
+ if self.config.commands.build:
44
+ for command in self.config.commands.build:
45
+ await run_command_streaming(command, self.config.working_dir, self.config.env)
46
+
47
+ async def _teardown(self):
48
+ pass
49
+
50
+ async def _start(self) -> None:
51
+ base_url = f"http://localhost:{self.config.port}" + (self.config.base_path or "")
52
+ self.client = McpClient(base_url, self.config.headers)
53
+ await super()._start()
54
+
55
+ async def _stop(self) -> None:
56
+ await super()._stop()
57
+ await self.client.close()
58
+ self.client = None
59
+
60
+ async def _serve(self) -> None:
61
+ if self.config.commands.start:
62
+ await run_command_streaming(self.config.commands.start, self.config.working_dir, self.config.env, block=False)
63
+
64
+ async def _shutdown(self) -> None:
65
+ pass
66
+
67
+ async def _run(self, action: ActionConfig, context: ComponentActionContext) -> Any:
68
+ return await McpServerAction(action).run(context, self.client)
@@ -1,10 +1,10 @@
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
- from asyncio.subprocess import Process
7
- import asyncio, os
7
+ import os
8
8
 
9
9
  class ShellAction:
10
10
  def __init__(self, config: ShellActionConfig, base_dir: Optional[str], env: Optional[Dict[str, str]]):
@@ -22,39 +22,17 @@ class ShellAction:
22
22
  return (await context.render_variable(self.config.output, ignore_files=True)) if self.config.output else result
23
23
 
24
24
  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
- )
25
+ stdout, stderr, exit_code = await run_command(command, working_dir, env, timeout)
32
26
 
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)}")
38
-
39
- return {
40
- "stdout": stdout.decode().strip(),
27
+ return {
28
+ "stdout": stdout.decode().strip(),
41
29
  "stderr": stderr.decode().strip(),
42
- "exit_code": process.returncode
30
+ "exit_code": exit_code
43
31
  }
44
32
 
45
- async def _kill_process(self, process: Process) -> bool:
46
- if process.returncode is None:
47
- process.kill()
48
- try:
49
- await process.wait()
50
- except Exception as e:
51
- pass
52
- return True
53
- else:
54
- return False
55
-
56
33
  async def _resolve_working_directory(self) -> str:
57
34
  working_dir = self.config.working_dir
35
+
58
36
  if working_dir:
59
37
  if self.base_dir:
60
38
  working_dir = os.path.abspath(os.path.join(self.base_dir, working_dir))
@@ -62,6 +40,7 @@ class ShellAction:
62
40
  working_dir = os.path.abspath(working_dir)
63
41
  else:
64
42
  working_dir = self.base_dir or os.getcwd()
43
+
65
44
  return working_dir
66
45
 
67
46
  @register_component(ComponentType.SHELL)
@@ -9,7 +9,7 @@ async def terminate_services(config: ComposeConfig, verbose: bool):
9
9
  await ComposeManager(config, daemon=False).terminate_services(verbose)
10
10
 
11
11
  async def start_services(config: ComposeConfig, verbose: bool):
12
- await ComposeManager(config, daemon=False).start_services(verbose)
12
+ await ComposeManager(config, daemon=True).start_services(verbose)
13
13
 
14
14
  async def stop_services(config: ComposeConfig, verbose: bool):
15
15
  await ComposeManager(config, daemon=False).stop_services(verbose)
@@ -16,16 +16,16 @@ class ComposeManager:
16
16
  )
17
17
 
18
18
  async def launch_services(self, detach: bool, verbose: bool):
19
- await self.controller.launch(detach, verbose)
19
+ await self.controller.launch_services(detach, verbose)
20
20
 
21
21
  async def terminate_services(self, verbose: bool):
22
- await self.controller.terminate(verbose)
22
+ await self.controller.terminate_services(verbose)
23
23
 
24
24
  async def start_services(self, verbose: bool):
25
- await self.controller.start()
25
+ await self.controller.start_services(verbose)
26
26
 
27
27
  async def stop_services(self, verbose: bool):
28
- await self.controller.stop()
28
+ await self.controller.stop_services(verbose)
29
29
 
30
30
  async def run_workflow(self, workflow_id: Optional[str], input: Dict[str, Any], output_path: Optional[str], verbose: bool) -> TaskState:
31
31
  if not self.controller.started:
@@ -1,13 +1,12 @@
1
1
  from typing import Type, Union, Literal, Optional, Dict, List, Tuple, Set, Annotated, Any
2
2
  from enum import Enum
3
3
  from dataclasses import dataclass
4
- from pydantic import BaseModel
5
4
  from mindor.dsl.schema.controller import ControllerConfig, ControllerType
6
5
  from mindor.dsl.schema.component import ComponentConfig
7
6
  from mindor.dsl.schema.listener import ListenerConfig
8
7
  from mindor.dsl.schema.gateway import GatewayConfig
9
8
  from mindor.dsl.schema.workflow import WorkflowConfig
10
- from mindor.dsl.schema.runtime import RuntimeType, DockerBuildConfig
9
+ from mindor.dsl.schema.runtime import RuntimeType
11
10
  from mindor.dsl.schema.logger import LoggerConfig, LoggerType, ConsoleLoggerConfig
12
11
  from mindor.core.services import AsyncService
13
12
  from mindor.core.component import ComponentService, ComponentGlobalConfigs, create_component
@@ -16,12 +15,15 @@ from mindor.core.gateway import GatewayService, create_gateway
16
15
  from mindor.core.workflow import Workflow, WorkflowResolver, create_workflow
17
16
  from mindor.core.logger import LoggerService, create_logger
18
17
  from mindor.core.controller.webui import ControllerWebUI
18
+ from mindor.core.workflow.schema import WorkflowSchema, create_workflow_schemas
19
19
  from mindor.core.utils.workqueue import WorkQueue
20
20
  from mindor.core.utils.caching import ExpiringDict
21
21
  from .runtime.specs import ControllerRuntimeSpecs
22
+ from .runtime.native import NativeRuntimeLauncher
22
23
  from .runtime.docker import DockerRuntimeLauncher
23
24
  from threading import Lock
24
- import asyncio, ulid
25
+ from pathlib import Path
26
+ import asyncio, ulid, os
25
27
 
26
28
  class TaskStatus(str, Enum):
27
29
  PENDING = "pending"
@@ -55,17 +57,23 @@ class ControllerService(AsyncService):
55
57
  self.listeners: List[ListenerConfig] = listeners
56
58
  self.gateways: List[GatewayConfig] = gateways
57
59
  self.loggers: List[LoggerConfig] = loggers
58
- self.queue: Optional[WorkQueue] = None
60
+ self.workflow_schemas: Dict[str, WorkflowSchema] = create_workflow_schemas(self.workflows, self.components)
61
+ self.task_queue: Optional[WorkQueue] = None
59
62
  self.task_states: ExpiringDict[TaskState] = ExpiringDict()
60
63
  self.task_states_lock: Lock = Lock()
61
-
64
+
62
65
  if self.config.max_concurrent_count > 0:
63
- self.queue = WorkQueue(self.config.max_concurrent_count, self._run_workflow)
66
+ self.task_queue = WorkQueue(self.config.max_concurrent_count, self._run_workflow)
64
67
 
65
- async def launch(self, detach: bool, verbose: bool) -> None:
68
+ async def launch_services(self, detach: bool, verbose: bool) -> None:
66
69
  if self.config.runtime.type == RuntimeType.NATIVE:
67
70
  if detach:
68
- pass
71
+ await self._start_loggers()
72
+ await NativeRuntimeLauncher().launch_detached()
73
+ await self._stop_loggers()
74
+ return
75
+
76
+ await self._setup_components()
69
77
  await self.start()
70
78
  await self.wait_until_stopped()
71
79
  return
@@ -73,16 +81,46 @@ class ControllerService(AsyncService):
73
81
  if self.config.runtime.type == RuntimeType.DOCKER:
74
82
  await self._start_loggers()
75
83
  await DockerRuntimeLauncher(self.config, verbose).launch(self._get_runtime_specs(), detach)
84
+ await self._stop_loggers()
76
85
  return
77
86
 
78
- async def terminate(self, verbose: bool) -> None:
87
+ async def terminate_services(self, verbose: bool) -> None:
79
88
  if self.config.runtime.type == RuntimeType.NATIVE:
80
- await self.stop()
89
+ await self._start_loggers()
90
+ await NativeRuntimeLauncher().stop()
91
+ await self._teardown_components()
92
+ await self._stop_loggers()
81
93
  return
82
-
94
+
83
95
  if self.config.runtime.type == RuntimeType.DOCKER:
84
96
  await self._start_loggers()
85
97
  await DockerRuntimeLauncher(self.config, verbose).terminate()
98
+ await self._stop_loggers()
99
+ return
100
+
101
+ async def start_services(self, verbose: bool) -> None:
102
+ if self.config.runtime.type == RuntimeType.NATIVE:
103
+ await self.start()
104
+ await self.wait_until_stopped()
105
+ return
106
+
107
+ if self.config.runtime.type == RuntimeType.DOCKER:
108
+ await self._start_loggers()
109
+ await DockerRuntimeLauncher(self.config, verbose).start()
110
+ await self._stop_loggers()
111
+ return
112
+
113
+ async def stop_services(self, verbose: bool) -> None:
114
+ if self.config.runtime.type == RuntimeType.NATIVE:
115
+ await self._start_loggers()
116
+ await NativeRuntimeLauncher().stop()
117
+ await self._stop_loggers()
118
+ return
119
+
120
+ if self.config.runtime.type == RuntimeType.DOCKER:
121
+ await self._start_loggers()
122
+ await DockerRuntimeLauncher(self.config, verbose).stop()
123
+ await self._stop_loggers()
86
124
  return
87
125
 
88
126
  async def run_workflow(self, workflow_id: Optional[str], input: Dict[str, Any], wait_for_completion: bool = True) -> TaskState:
@@ -92,8 +130,8 @@ class ControllerService(AsyncService):
92
130
  self.task_states.set(task_id, state)
93
131
 
94
132
  if wait_for_completion:
95
- if self.queue:
96
- state = await (await self.queue.schedule(task_id, workflow_id, input))
133
+ if self.task_queue:
134
+ state = await (await self.task_queue.schedule(task_id, workflow_id, input))
97
135
  else:
98
136
  state = await self._run_workflow(task_id, workflow_id, input)
99
137
  else:
@@ -106,11 +144,12 @@ class ControllerService(AsyncService):
106
144
  return self.task_states.get(task_id)
107
145
 
108
146
  async def _start(self) -> None:
109
- if self.queue:
110
- await self.queue.start()
147
+ if self.task_queue:
148
+ await self.task_queue.start()
149
+
150
+ await self._start_loggers()
111
151
 
112
152
  if self.daemon:
113
- await self._start_loggers()
114
153
  await self._start_gateways()
115
154
  await self._start_listeners()
116
155
  await self._start_components()
@@ -118,23 +157,38 @@ class ControllerService(AsyncService):
118
157
  if self.config.webui:
119
158
  await self._start_webui()
120
159
 
160
+ asyncio.create_task(self._watch_stop_request())
161
+
121
162
  await super()._start()
122
163
 
123
164
  async def _stop(self) -> None:
124
- if self.queue:
125
- await self.queue.stop()
165
+ if self.task_queue:
166
+ await self.task_queue.stop()
126
167
 
127
168
  if self.daemon:
128
169
  await self._stop_components()
129
170
  await self._stop_listeners()
130
171
  await self._stop_gateways()
131
- await self._stop_loggers()
132
172
 
133
173
  if self.config.webui:
134
174
  await self._stop_webui()
135
175
 
136
176
  await super()._stop()
137
177
 
178
+ async def _on_stop(self) -> None:
179
+ await self._stop_loggers()
180
+
181
+ async def _watch_stop_request(self, interval: float = 1.0) -> None:
182
+ stop_file = Path.cwd() / ".stop"
183
+
184
+ while self.started:
185
+ if stop_file.exists():
186
+ await self.stop()
187
+ break
188
+ await asyncio.sleep(interval)
189
+
190
+ os.unlink(stop_file)
191
+
138
192
  async def _start_listeners(self) -> None:
139
193
  await asyncio.gather(*[ listener.start() for listener in self._create_listeners() ])
140
194
 
@@ -147,6 +201,12 @@ class ControllerService(AsyncService):
147
201
  async def _stop_gateways(self) -> None:
148
202
  await asyncio.gather(*[ gateway.stop() for gateway in self._create_gateways() ])
149
203
 
204
+ async def _setup_components(self) -> None:
205
+ await asyncio.gather(*[ component.setup() for component in self._create_components() ])
206
+
207
+ async def _teardown_components(self) -> None:
208
+ await asyncio.gather(*[ component.teardown() for component in self._create_components() ])
209
+
150
210
  async def _start_components(self) -> None:
151
211
  await asyncio.gather(*[ component.start() for component in self._create_components() ])
152
212
 
@@ -198,7 +258,7 @@ class ControllerService(AsyncService):
198
258
  state = TaskState(task_id=task_id, status=TaskStatus.PROCESSING)
199
259
  with self.task_states_lock:
200
260
  self.task_states.set(task_id, state)
201
-
261
+
202
262
  try:
203
263
  workflow = self._create_workflow(workflow_id)
204
264
  output = await workflow.run(task_id, input)
@@ -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)