model-compose 0.0.5__tar.gz → 0.0.6__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {model_compose-0.0.5/src/model_compose.egg-info → model_compose-0.0.6}/PKG-INFO +1 -1
- {model_compose-0.0.5 → model_compose-0.0.6}/pyproject.toml +1 -1
- {model_compose-0.0.5 → model_compose-0.0.6}/src/mindor/core/component/engine/__init__.py +1 -1
- {model_compose-0.0.5 → model_compose-0.0.6}/src/mindor/core/component/engine/base.py +1 -1
- {model_compose-0.0.5 → model_compose-0.0.6}/src/mindor/core/component/engine/http_client.py +55 -25
- {model_compose-0.0.5 → model_compose-0.0.6}/src/mindor/core/component/engine/http_server.py +1 -1
- {model_compose-0.0.5 → model_compose-0.0.6}/src/mindor/core/controller/engine/http_server.py +45 -16
- model_compose-0.0.6/src/mindor/core/utils/resources.py +28 -0
- {model_compose-0.0.5 → model_compose-0.0.6}/src/mindor/core/workflow/job.py +5 -5
- {model_compose-0.0.5 → model_compose-0.0.6}/src/mindor/core/workflow/workflow.py +5 -4
- {model_compose-0.0.5 → model_compose-0.0.6}/src/mindor/dsl/schema/action/impl/http_client.py +3 -3
- {model_compose-0.0.5 → model_compose-0.0.6}/src/mindor/dsl/schema/action/impl/http_server.py +1 -1
- {model_compose-0.0.5 → model_compose-0.0.6}/src/mindor/dsl/schema/action/impl/mcp_client.py +1 -1
- {model_compose-0.0.5 → model_compose-0.0.6}/src/mindor/dsl/schema/action/impl/mcp_server.py +2 -2
- {model_compose-0.0.5 → model_compose-0.0.6}/src/mindor/dsl/schema/component/component.py +1 -1
- {model_compose-0.0.5 → model_compose-0.0.6}/src/mindor/dsl/schema/component/impl/common.py +1 -1
- {model_compose-0.0.5 → model_compose-0.0.6}/src/mindor/dsl/schema/component/impl/http_client.py +2 -2
- {model_compose-0.0.5 → model_compose-0.0.6}/src/mindor/dsl/schema/component/impl/http_server.py +1 -1
- {model_compose-0.0.5 → model_compose-0.0.6}/src/mindor/dsl/schema/component/impl/mcp_client.py +2 -2
- {model_compose-0.0.5 → model_compose-0.0.6}/src/mindor/dsl/schema/component/impl/mcp_server.py +1 -1
- {model_compose-0.0.5 → model_compose-0.0.6}/src/mindor/dsl/schema/controller/controller.py +1 -1
- {model_compose-0.0.5 → model_compose-0.0.6}/src/mindor/dsl/schema/controller/impl/http_server.py +1 -1
- {model_compose-0.0.5 → model_compose-0.0.6}/src/mindor/dsl/schema/controller/impl/mcp_server.py +1 -1
- {model_compose-0.0.5 → model_compose-0.0.6}/src/mindor/dsl/schema/listener/impl/http_callback.py +1 -1
- {model_compose-0.0.5 → model_compose-0.0.6}/src/mindor/dsl/schema/listener/listener.py +1 -1
- {model_compose-0.0.5 → model_compose-0.0.6}/src/mindor/dsl/schema/runtime/impl/docker.py +1 -1
- {model_compose-0.0.5 → model_compose-0.0.6}/src/mindor/dsl/schema/runtime/runtime.py +1 -1
- {model_compose-0.0.5 → model_compose-0.0.6/src/model_compose.egg-info}/PKG-INFO +1 -1
- {model_compose-0.0.5 → model_compose-0.0.6}/src/model_compose.egg-info/SOURCES.txt +1 -0
- {model_compose-0.0.5 → model_compose-0.0.6}/LICENSE +0 -0
- {model_compose-0.0.5 → model_compose-0.0.6}/README.md +0 -0
- {model_compose-0.0.5 → model_compose-0.0.6}/setup.cfg +0 -0
- {model_compose-0.0.5 → model_compose-0.0.6}/src/mindor/__init__.py +0 -0
- {model_compose-0.0.5 → model_compose-0.0.6}/src/mindor/cli/__init__.py +0 -0
- {model_compose-0.0.5 → model_compose-0.0.6}/src/mindor/cli/compose.py +0 -0
- {model_compose-0.0.5 → model_compose-0.0.6}/src/mindor/core/__init__.py +0 -0
- {model_compose-0.0.5 → model_compose-0.0.6}/src/mindor/core/component/__init__.py +0 -0
- {model_compose-0.0.5 → model_compose-0.0.6}/src/mindor/core/component/component.py +0 -0
- {model_compose-0.0.5 → model_compose-0.0.6}/src/mindor/core/component/engine/context.py +0 -0
- {model_compose-0.0.5 → model_compose-0.0.6}/src/mindor/core/compose/__init__.py +0 -0
- {model_compose-0.0.5 → model_compose-0.0.6}/src/mindor/core/compose/compose.py +0 -0
- {model_compose-0.0.5 → model_compose-0.0.6}/src/mindor/core/compose/manager.py +0 -0
- {model_compose-0.0.5 → model_compose-0.0.6}/src/mindor/core/controller/__init__.py +0 -0
- {model_compose-0.0.5 → model_compose-0.0.6}/src/mindor/core/controller/controller.py +0 -0
- {model_compose-0.0.5 → model_compose-0.0.6}/src/mindor/core/controller/engine/__init__.py +0 -0
- {model_compose-0.0.5 → model_compose-0.0.6}/src/mindor/core/controller/engine/base.py +0 -0
- {model_compose-0.0.5 → model_compose-0.0.6}/src/mindor/core/controller/engine/mcp_server.py +0 -0
- {model_compose-0.0.5 → model_compose-0.0.6}/src/mindor/core/listener/__init__.py +0 -0
- {model_compose-0.0.5 → model_compose-0.0.6}/src/mindor/core/listener/engine/__init__.py +0 -0
- {model_compose-0.0.5 → model_compose-0.0.6}/src/mindor/core/listener/engine/base.py +0 -0
- {model_compose-0.0.5 → model_compose-0.0.6}/src/mindor/core/listener/engine/http_callback.py +0 -0
- {model_compose-0.0.5 → model_compose-0.0.6}/src/mindor/core/listener/listener.py +0 -0
- {model_compose-0.0.5 → model_compose-0.0.6}/src/mindor/core/runtime/__init__.py +0 -0
- {model_compose-0.0.5 → model_compose-0.0.6}/src/mindor/core/runtime/env.py +0 -0
- {model_compose-0.0.5 → model_compose-0.0.6}/src/mindor/core/utils/__init__.py +0 -0
- {model_compose-0.0.5 → model_compose-0.0.6}/src/mindor/core/utils/expiring.py +0 -0
- {model_compose-0.0.5 → model_compose-0.0.6}/src/mindor/core/utils/http_headers.py +0 -0
- {model_compose-0.0.5 → model_compose-0.0.6}/src/mindor/core/utils/template.py +0 -0
- {model_compose-0.0.5 → model_compose-0.0.6}/src/mindor/core/utils/workqueue.py +0 -0
- {model_compose-0.0.5 → model_compose-0.0.6}/src/mindor/core/workflow/__init__.py +0 -0
- {model_compose-0.0.5 → model_compose-0.0.6}/src/mindor/core/workflow/context.py +0 -0
- {model_compose-0.0.5 → model_compose-0.0.6}/src/mindor/dsl/__init__.py +0 -0
- {model_compose-0.0.5 → model_compose-0.0.6}/src/mindor/dsl/loader.py +0 -0
- {model_compose-0.0.5 → model_compose-0.0.6}/src/mindor/dsl/schema/__init__.py +0 -0
- {model_compose-0.0.5 → model_compose-0.0.6}/src/mindor/dsl/schema/action/__init__.py +0 -0
- {model_compose-0.0.5 → model_compose-0.0.6}/src/mindor/dsl/schema/action/action.py +0 -0
- {model_compose-0.0.5 → model_compose-0.0.6}/src/mindor/dsl/schema/action/impl/__init__.py +0 -0
- {model_compose-0.0.5 → model_compose-0.0.6}/src/mindor/dsl/schema/action/impl/common.py +0 -0
- {model_compose-0.0.5 → model_compose-0.0.6}/src/mindor/dsl/schema/component/__init__.py +0 -0
- {model_compose-0.0.5 → model_compose-0.0.6}/src/mindor/dsl/schema/component/impl/__init__.py +0 -0
- {model_compose-0.0.5 → model_compose-0.0.6}/src/mindor/dsl/schema/component/impl/types.py +0 -0
- {model_compose-0.0.5 → model_compose-0.0.6}/src/mindor/dsl/schema/compose.py +0 -0
- {model_compose-0.0.5 → model_compose-0.0.6}/src/mindor/dsl/schema/controller/__init__.py +0 -0
- {model_compose-0.0.5 → model_compose-0.0.6}/src/mindor/dsl/schema/controller/impl/__init__.py +0 -0
- {model_compose-0.0.5 → model_compose-0.0.6}/src/mindor/dsl/schema/controller/impl/common.py +0 -0
- {model_compose-0.0.5 → model_compose-0.0.6}/src/mindor/dsl/schema/controller/impl/types.py +0 -0
- {model_compose-0.0.5 → model_compose-0.0.6}/src/mindor/dsl/schema/listener/__init__.py +0 -0
- {model_compose-0.0.5 → model_compose-0.0.6}/src/mindor/dsl/schema/listener/impl/__init__.py +0 -0
- {model_compose-0.0.5 → model_compose-0.0.6}/src/mindor/dsl/schema/listener/impl/common.py +0 -0
- {model_compose-0.0.5 → model_compose-0.0.6}/src/mindor/dsl/schema/listener/impl/types.py +0 -0
- {model_compose-0.0.5 → model_compose-0.0.6}/src/mindor/dsl/schema/runtime/__init__.py +0 -0
- {model_compose-0.0.5 → model_compose-0.0.6}/src/mindor/dsl/schema/runtime/impl/__init__.py +0 -0
- {model_compose-0.0.5 → model_compose-0.0.6}/src/mindor/dsl/schema/runtime/impl/common.py +0 -0
- {model_compose-0.0.5 → model_compose-0.0.6}/src/mindor/dsl/schema/runtime/impl/types.py +0 -0
- {model_compose-0.0.5 → model_compose-0.0.6}/src/mindor/dsl/schema/workflow.py +0 -0
- {model_compose-0.0.5 → model_compose-0.0.6}/src/model_compose.egg-info/dependency_links.txt +0 -0
- {model_compose-0.0.5 → model_compose-0.0.6}/src/model_compose.egg-info/entry_points.txt +0 -0
- {model_compose-0.0.5 → model_compose-0.0.6}/src/model_compose.egg-info/requires.txt +0 -0
- {model_compose-0.0.5 → model_compose-0.0.6}/src/model_compose.egg-info/top_level.txt +0 -0
- {model_compose-0.0.5 → model_compose-0.0.6}/tests/test_cli.py +0 -0
|
@@ -117,7 +117,7 @@ class BaseComponent(ABC):
|
|
|
117
117
|
pass
|
|
118
118
|
|
|
119
119
|
@abstractmethod
|
|
120
|
-
async def _run(self, action: ActionConfig, context: ComponentContext) ->
|
|
120
|
+
async def _run(self, action: ActionConfig, context: ComponentContext) -> Any:
|
|
121
121
|
pass
|
|
122
122
|
|
|
123
123
|
ComponentEngineMap: Dict[ComponentType, Type[BaseComponent]] = {}
|
|
@@ -1,18 +1,42 @@
|
|
|
1
|
-
from typing import Type, Union, Literal, Optional, Dict, List, Tuple, Set, Annotated, Any
|
|
2
|
-
from mindor.dsl.schema.component import HttpClientComponentConfig, HttpClientActionConfig
|
|
1
|
+
from typing import Type, Union, Literal, Optional, Dict, List, Tuple, Set, Annotated, AsyncIterator, Any
|
|
2
|
+
from mindor.dsl.schema.component import HttpClientComponentConfig, HttpClientActionConfig
|
|
3
3
|
from mindor.core.utils.http_headers import parse_options_header, get_header_value
|
|
4
|
+
from mindor.core.utils.resources import StreamResource
|
|
4
5
|
from .base import BaseComponent, ComponentType, ComponentEngineMap, ActionConfig
|
|
5
6
|
from .context import ComponentContext
|
|
6
7
|
|
|
7
8
|
from urllib.parse import urlencode
|
|
8
9
|
import aiohttp, json
|
|
9
10
|
|
|
11
|
+
class HttpStreamResource(StreamResource):
|
|
12
|
+
def __init__(self, session: aiohttp.ClientSession, stream: aiohttp.StreamReader, filename: Optional[str], content_type: Optional[str]):
|
|
13
|
+
super().__init__(content_type, filename)
|
|
14
|
+
|
|
15
|
+
self.session: aiohttp.ClientSession = session
|
|
16
|
+
self.stream: aiohttp.StreamReader = stream
|
|
17
|
+
|
|
18
|
+
def get_stream(self):
|
|
19
|
+
return self.stream
|
|
20
|
+
|
|
21
|
+
async def close(self):
|
|
22
|
+
await self.session.close()
|
|
23
|
+
|
|
24
|
+
async def _iterate_stream(self) -> AsyncIterator[bytes]:
|
|
25
|
+
_, buffer_size = self.stream.get_read_buffer_limits()
|
|
26
|
+
chunk_size = buffer_size or 65536
|
|
27
|
+
|
|
28
|
+
while not self.stream.at_eof():
|
|
29
|
+
chunk = await self.stream.read(chunk_size)
|
|
30
|
+
if not chunk:
|
|
31
|
+
break
|
|
32
|
+
yield chunk
|
|
33
|
+
|
|
10
34
|
class HttpClientAction:
|
|
11
|
-
def __init__(self, base_url:
|
|
12
|
-
self.base_url:
|
|
35
|
+
def __init__(self, base_url: Optional[str], config: HttpClientActionConfig):
|
|
36
|
+
self.base_url: Optional[str] = base_url
|
|
13
37
|
self.config: HttpClientActionConfig = config
|
|
14
38
|
|
|
15
|
-
async def run(self, context: ComponentContext) ->
|
|
39
|
+
async def run(self, context: ComponentContext) -> Any:
|
|
16
40
|
url = self._resolve_request_url(context)
|
|
17
41
|
method = context.render_template(self.config.method)
|
|
18
42
|
params = context.render_template(self.config.params)
|
|
@@ -21,32 +45,41 @@ class HttpClientAction:
|
|
|
21
45
|
|
|
22
46
|
response = await self._request(url, method, params, body, headers)
|
|
23
47
|
|
|
24
|
-
if not self.config.output:
|
|
25
|
-
return response
|
|
26
|
-
|
|
27
48
|
if response:
|
|
28
49
|
context.register_source("response", response)
|
|
29
50
|
|
|
30
|
-
return context.render_template(self.config.output)
|
|
51
|
+
return context.render_template(self.config.output) if self.config.output else response
|
|
31
52
|
|
|
32
53
|
async def _request(self, url: str, method: str, params: Optional[Dict[str, Any]], body: Optional[Any], headers: Optional[Dict[str, str]]) -> Any:
|
|
33
|
-
|
|
34
|
-
|
|
54
|
+
session = aiohttp.ClientSession()
|
|
55
|
+
try:
|
|
56
|
+
response = await session.request(
|
|
35
57
|
method,
|
|
36
58
|
url,
|
|
37
59
|
params=params,
|
|
38
60
|
data=self._serialize_request_body(body, headers) if body is not None else None,
|
|
39
61
|
headers=headers
|
|
40
|
-
)
|
|
41
|
-
|
|
42
|
-
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
if response.status >= 400:
|
|
65
|
+
raise ValueError(f"Request failed with status {response.status}")
|
|
66
|
+
|
|
67
|
+
content = await self._parse_response_content(session, response)
|
|
43
68
|
|
|
44
|
-
|
|
69
|
+
if isinstance(content, HttpStreamResource):
|
|
70
|
+
pass
|
|
71
|
+
else:
|
|
72
|
+
await session.close()
|
|
73
|
+
|
|
74
|
+
return content
|
|
75
|
+
except:
|
|
76
|
+
await session.close()
|
|
77
|
+
raise
|
|
45
78
|
|
|
46
79
|
def _resolve_request_url(self, context: ComponentContext) -> str:
|
|
47
80
|
if self.base_url and self.config.path:
|
|
48
81
|
return context.render_template(str(self.base_url)) + context.render_template(self.config.path)
|
|
49
|
-
|
|
82
|
+
|
|
50
83
|
return context.render_template(str(self.config.endpoint))
|
|
51
84
|
|
|
52
85
|
def _serialize_request_body(self, body: Any, headers: Optional[Dict[str, str]]) -> Any:
|
|
@@ -60,22 +93,19 @@ class HttpClientAction:
|
|
|
60
93
|
|
|
61
94
|
return json.dumps(body)
|
|
62
95
|
|
|
63
|
-
async def
|
|
96
|
+
async def _parse_response_content(self, session: aiohttp.ClientSession, response: aiohttp.ClientResponse) -> Any:
|
|
64
97
|
content_type, _ = parse_options_header(response.headers.get("Content-Type", ""))
|
|
65
98
|
|
|
66
99
|
if content_type == "application/json":
|
|
67
100
|
return await response.json()
|
|
68
|
-
|
|
101
|
+
|
|
69
102
|
if content_type.startswith("text/"):
|
|
70
103
|
return await response.text()
|
|
71
104
|
|
|
72
|
-
_, disposition = parse_options_header(response.headers.get("Content-Disposition"))
|
|
105
|
+
_, disposition = parse_options_header(response.headers.get("Content-Disposition", ""))
|
|
106
|
+
filename = disposition.get("filename")
|
|
73
107
|
|
|
74
|
-
return
|
|
75
|
-
"filename": disposition.get("filename"),
|
|
76
|
-
"content_type": content_type,
|
|
77
|
-
"stream": response.content
|
|
78
|
-
}
|
|
108
|
+
return HttpStreamResource(session, response.content, filename, content_type)
|
|
79
109
|
|
|
80
110
|
class HttpClientComponent(BaseComponent):
|
|
81
111
|
def __init__(self, id: str, config: HttpClientComponentConfig, env: Dict[str, str], daemon: bool):
|
|
@@ -87,7 +117,7 @@ class HttpClientComponent(BaseComponent):
|
|
|
87
117
|
async def _shutdown(self) -> None:
|
|
88
118
|
pass
|
|
89
119
|
|
|
90
|
-
async def _run(self, action: ActionConfig, context: ComponentContext) ->
|
|
120
|
+
async def _run(self, action: ActionConfig, context: ComponentContext) -> Any:
|
|
91
121
|
return await HttpClientAction(self.config.base_url, action).run(context)
|
|
92
122
|
|
|
93
123
|
ComponentEngineMap[ComponentType.HTTP_CLIENT] = HttpClientComponent
|
|
@@ -13,7 +13,7 @@ class HttpServerComponent(BaseComponent):
|
|
|
13
13
|
async def _shutdown(self) -> None:
|
|
14
14
|
pass
|
|
15
15
|
|
|
16
|
-
async def _run(self, action: ActionConfig, context: ComponentContext) ->
|
|
16
|
+
async def _run(self, action: ActionConfig, context: ComponentContext) -> Any:
|
|
17
17
|
return {}
|
|
18
18
|
|
|
19
19
|
ComponentEngineMap[ComponentType.HTTP_SERVER] = HttpServerComponent
|
{model_compose-0.0.5 → model_compose-0.0.6}/src/mindor/core/controller/engine/http_server.py
RENAMED
|
@@ -5,15 +5,19 @@ from pydantic import BaseModel
|
|
|
5
5
|
from mindor.dsl.schema.controller import HttpServerControllerConfig
|
|
6
6
|
from mindor.dsl.schema.component import ComponentConfig
|
|
7
7
|
from mindor.dsl.schema.workflow import WorkflowConfig
|
|
8
|
+
from mindor.core.utils.resources import StreamResource
|
|
8
9
|
from .base import BaseController, ControllerType, ControllerEngineMap, TaskState
|
|
9
10
|
|
|
10
11
|
from fastapi import FastAPI, APIRouter, Body, HTTPException
|
|
11
|
-
import
|
|
12
|
+
from fastapi.responses import JSONResponse, StreamingResponse
|
|
13
|
+
from starlette.background import BackgroundTask
|
|
14
|
+
import asyncio, uvicorn
|
|
12
15
|
|
|
13
16
|
class WorkflowTaskRequestBody(BaseModel):
|
|
14
17
|
workflow_id: Optional[str] = None
|
|
15
18
|
input: Optional[Dict[str, Any]] = None
|
|
16
19
|
wait_for_completion: bool = True
|
|
20
|
+
output_only: bool = False
|
|
17
21
|
|
|
18
22
|
class TaskResult(BaseModel):
|
|
19
23
|
task_id: str
|
|
@@ -42,35 +46,60 @@ class HttpServerController(BaseController):
|
|
|
42
46
|
self.app.include_router(self.router, prefix=self.config.base_path)
|
|
43
47
|
|
|
44
48
|
def _configure_routes(self):
|
|
45
|
-
@self.router.post("/workflows"
|
|
49
|
+
@self.router.post("/workflows")
|
|
46
50
|
async def run_workflow(
|
|
47
51
|
body: WorkflowTaskRequestBody = Body(...)
|
|
48
52
|
):
|
|
49
53
|
state = await self.run_workflow(body.workflow_id, body.input, body.wait_for_completion)
|
|
50
54
|
|
|
51
|
-
|
|
55
|
+
if body.output_only and body.wait_for_completion:
|
|
56
|
+
if state.status == "failed":
|
|
57
|
+
raise HTTPException(status_code=500, detail=str(state.error))
|
|
58
|
+
|
|
59
|
+
if isinstance(state.output, StreamResource):
|
|
60
|
+
return StreamingResponse(
|
|
61
|
+
state.output,
|
|
62
|
+
media_type=state.output.content_type,
|
|
63
|
+
headers = {
|
|
64
|
+
"Content-Disposition": f"attachment; filename={state.output.filename}"
|
|
65
|
+
} if state.output.filename else {},
|
|
66
|
+
#background=BackgroundTask(lambda: asyncio.create_task(state.output.close()))
|
|
67
|
+
)
|
|
52
68
|
|
|
53
|
-
|
|
69
|
+
return state.output
|
|
70
|
+
|
|
71
|
+
return JSONResponse(content=TaskResult.from_instance(state).model_dump(exclude_none=True))
|
|
72
|
+
|
|
73
|
+
@self.router.get("/tasks/{task_id}")
|
|
54
74
|
async def get_task_state(
|
|
55
|
-
task_id: str
|
|
75
|
+
task_id: str,
|
|
76
|
+
output_only: bool = False
|
|
56
77
|
):
|
|
57
78
|
state = self.get_task_state(task_id)
|
|
58
79
|
|
|
59
80
|
if not state:
|
|
60
|
-
raise HTTPException(status_code=404, detail="Task not found")
|
|
81
|
+
raise HTTPException(status_code=404, detail="Task not found.")
|
|
61
82
|
|
|
62
|
-
|
|
83
|
+
if output_only:
|
|
84
|
+
if state.status in [ "pending", "processing" ]:
|
|
85
|
+
raise HTTPException(status_code=202, detail="Task is still in progress.")
|
|
86
|
+
|
|
87
|
+
if state.status == "failed":
|
|
88
|
+
raise HTTPException(status_code=500, detail=str(state.error))
|
|
63
89
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
90
|
+
if isinstance(state.output, StreamResource):
|
|
91
|
+
return StreamingResponse(
|
|
92
|
+
state.output,
|
|
93
|
+
media_type=state.output.content_type,
|
|
94
|
+
headers = {
|
|
95
|
+
"Content-Disposition": f"attachment; filename={state.output.filename}"
|
|
96
|
+
} if state.output.filename else {},
|
|
97
|
+
# background=BackgroundTask(lambda: asyncio.create_task(state.output.close()))
|
|
98
|
+
)
|
|
69
99
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
return state.output
|
|
100
|
+
return state.output
|
|
101
|
+
|
|
102
|
+
return JSONResponse(content=TaskResult.from_instance(state).model_dump(exclude_none=True))
|
|
74
103
|
|
|
75
104
|
async def _serve(self) -> None:
|
|
76
105
|
self.server = uvicorn.Server(uvicorn.Config(
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
from typing import Optional, AsyncIterator
|
|
2
|
+
from abc import ABC, abstractmethod
|
|
3
|
+
|
|
4
|
+
class StreamResource(ABC):
|
|
5
|
+
def __init__(self, content_type: Optional[str], filename: Optional[str]):
|
|
6
|
+
self.content_type = content_type or "application/octet-stream"
|
|
7
|
+
self.filename = filename
|
|
8
|
+
|
|
9
|
+
async def __aenter__(self):
|
|
10
|
+
return self
|
|
11
|
+
|
|
12
|
+
async def __aexit__(self, exc_type, exc_val, exc_tb):
|
|
13
|
+
await self.close()
|
|
14
|
+
|
|
15
|
+
def __aiter__(self):
|
|
16
|
+
return self._iterate_stream()
|
|
17
|
+
|
|
18
|
+
@abstractmethod
|
|
19
|
+
def get_stream(self):
|
|
20
|
+
pass
|
|
21
|
+
|
|
22
|
+
@abstractmethod
|
|
23
|
+
async def close(self):
|
|
24
|
+
pass
|
|
25
|
+
|
|
26
|
+
@abstractmethod
|
|
27
|
+
async def _iterate_stream(self) -> AsyncIterator[bytes]:
|
|
28
|
+
pass
|
|
@@ -11,17 +11,17 @@ class Job:
|
|
|
11
11
|
self.config: JobConfig = config
|
|
12
12
|
self.component_provider: Callable[[Union[ComponentConfig, str]], BaseComponent] = component_provider
|
|
13
13
|
|
|
14
|
-
async def run(self, context: WorkflowContext) ->
|
|
14
|
+
async def run(self, context: WorkflowContext) -> Any:
|
|
15
15
|
component = self.component_provider(self.config.component)
|
|
16
16
|
|
|
17
17
|
if not component.started:
|
|
18
18
|
await component.start()
|
|
19
19
|
|
|
20
20
|
call_id = ulid.ulid()
|
|
21
|
-
input = context.render_template(self.config.input)
|
|
21
|
+
input = context.render_template(self.config.input) if self.config.output else context.input
|
|
22
22
|
output = await component.run(self.config.action, call_id, input)
|
|
23
23
|
|
|
24
|
-
|
|
25
|
-
|
|
24
|
+
if output:
|
|
25
|
+
context.register_source("output", output)
|
|
26
26
|
|
|
27
|
-
return output
|
|
27
|
+
return context.render_template(self.config.output) if self.config.output else output
|
|
@@ -80,12 +80,12 @@ class WorkflowRunner:
|
|
|
80
80
|
self.jobs: Dict[str, JobConfig] = jobs
|
|
81
81
|
self.component_provider: Callable[[Union[ComponentConfig, str]], BaseComponent] = component_provider
|
|
82
82
|
|
|
83
|
-
async def run(self, context: WorkflowContext) ->
|
|
83
|
+
async def run(self, context: WorkflowContext) -> Any:
|
|
84
84
|
pending_jobs: Dict[str, Job] = { job_id: Job(job_id, job, self.component_provider) for job_id, job in self.jobs.items() }
|
|
85
85
|
running_job_ids: Set[str] = set()
|
|
86
86
|
completed_job_ids: Set[str] = set()
|
|
87
87
|
scheduled_job_tasks: Dict[str, asyncio.Task] = {}
|
|
88
|
-
output:
|
|
88
|
+
output: Any = {}
|
|
89
89
|
|
|
90
90
|
while pending_jobs:
|
|
91
91
|
runnable_jobs = [ job for job in pending_jobs.values() if self._can_run_job(job, running_job_ids, completed_job_ids) ]
|
|
@@ -107,7 +107,8 @@ class WorkflowRunner:
|
|
|
107
107
|
context.complete_job(completed_job_id, completed_job_output)
|
|
108
108
|
|
|
109
109
|
if self._is_terminal_job(completed_job_id):
|
|
110
|
-
output
|
|
110
|
+
output = completed_job_output
|
|
111
|
+
# output.update(completed_job_output)
|
|
111
112
|
|
|
112
113
|
running_job_ids.remove(completed_job_id)
|
|
113
114
|
completed_job_ids.add(completed_job_id)
|
|
@@ -129,7 +130,7 @@ class Workflow:
|
|
|
129
130
|
self.components: Dict[str, ComponentConfig] = components
|
|
130
131
|
self.env: Dict[str, str] = env
|
|
131
132
|
|
|
132
|
-
async def run(self, task_id: str, input: Dict[str, Any]) ->
|
|
133
|
+
async def run(self, task_id: str, input: Dict[str, Any]) -> Any:
|
|
133
134
|
context = WorkflowContext(task_id, input, self.env)
|
|
134
135
|
runner = WorkflowRunner(self.config.jobs, self._create_component)
|
|
135
136
|
|
{model_compose-0.0.5 → model_compose-0.0.6}/src/mindor/dsl/schema/action/impl/http_client.py
RENAMED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
from typing import Type, Union, Literal, Optional, Dict, List, Tuple, Set, Annotated, Any
|
|
2
|
-
from pydantic import BaseModel, Field
|
|
2
|
+
from pydantic import BaseModel, Field
|
|
3
3
|
from pydantic import model_validator
|
|
4
4
|
from .common import CommonActionConfig
|
|
5
5
|
|
|
@@ -12,7 +12,7 @@ class CallbackCompletionConfig(CommonCompletionConfig):
|
|
|
12
12
|
|
|
13
13
|
class PollingCompletionConfig(CommonCompletionConfig):
|
|
14
14
|
type: Literal["polling"]
|
|
15
|
-
endpoint: Optional[
|
|
15
|
+
endpoint: Optional[str] = None
|
|
16
16
|
path: Optional[str] = None
|
|
17
17
|
method: Literal[ "GET", "POST", "PUT", "DELETE", "PATCH" ] = "GET"
|
|
18
18
|
headers: Optional[Dict[str, str]] = Field(default_factory=dict)
|
|
@@ -36,7 +36,7 @@ HttpClientCompletionConfig = Annotated[
|
|
|
36
36
|
]
|
|
37
37
|
|
|
38
38
|
class HttpClientActionConfig(CommonActionConfig):
|
|
39
|
-
endpoint: Optional[
|
|
39
|
+
endpoint: Optional[str] = None
|
|
40
40
|
path: Optional[str] = None
|
|
41
41
|
method: Literal[ "GET", "POST", "PUT", "DELETE", "PATCH" ] = "POST"
|
|
42
42
|
headers: Optional[Dict[str, str]] = Field(default_factory=dict)
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
from typing import Type, Union, Literal, Optional, Dict, List, Tuple, Set, Annotated, Any
|
|
2
|
-
from pydantic import BaseModel, Field
|
|
2
|
+
from pydantic import BaseModel, Field
|
|
3
3
|
from pydantic import model_validator
|
|
4
4
|
from .common import CommonActionConfig
|
|
5
5
|
|
|
6
6
|
class McpServerActionConfig(CommonActionConfig):
|
|
7
7
|
def __init__(self):
|
|
8
|
-
super.__init__(
|
|
8
|
+
super().__init__()
|
{model_compose-0.0.5 → model_compose-0.0.6}/src/mindor/dsl/schema/component/impl/http_client.py
RENAMED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
from typing import Type, Union, Literal, Optional, Dict, List, Tuple, Set, Annotated, Any
|
|
2
|
-
from pydantic import BaseModel, Field
|
|
2
|
+
from pydantic import BaseModel, Field
|
|
3
3
|
from pydantic import model_validator
|
|
4
4
|
from mindor.dsl.schema.action import HttpClientActionConfig
|
|
5
5
|
from .common import ComponentType, CommonComponentConfig
|
|
6
6
|
|
|
7
7
|
class HttpClientComponentConfig(CommonComponentConfig):
|
|
8
8
|
type: Literal[ComponentType.HTTP_CLIENT]
|
|
9
|
-
base_url: Optional[
|
|
9
|
+
base_url: Optional[str] = None
|
|
10
10
|
headers: Optional[Dict[str, Any]] = Field(default_factory=dict)
|
|
11
11
|
actions: Optional[Dict[str, HttpClientActionConfig]] = Field(default_factory=dict)
|
|
12
12
|
|
{model_compose-0.0.5 → model_compose-0.0.6}/src/mindor/dsl/schema/component/impl/http_server.py
RENAMED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
from typing import Type, Union, Literal, Optional, Dict, List, Tuple, Set, Annotated, Any
|
|
2
|
-
from pydantic import BaseModel, Field
|
|
2
|
+
from pydantic import BaseModel, Field
|
|
3
3
|
from pydantic import model_validator
|
|
4
4
|
from mindor.dsl.schema.action import HttpServerActionConfig
|
|
5
5
|
from .common import ComponentType, CommonComponentConfig
|
{model_compose-0.0.5 → model_compose-0.0.6}/src/mindor/dsl/schema/component/impl/mcp_client.py
RENAMED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
from typing import Type, Union, Literal, Optional, Dict, List, Tuple, Set, Annotated, Any
|
|
2
|
-
from pydantic import BaseModel, Field
|
|
2
|
+
from pydantic import BaseModel, Field
|
|
3
3
|
from pydantic import model_validator
|
|
4
4
|
from mindor.dsl.schema.action import McpClientActionConfig
|
|
5
5
|
from .common import ComponentType, CommonComponentConfig
|
|
6
6
|
|
|
7
7
|
class McpClientComponentConfig(CommonComponentConfig):
|
|
8
8
|
type: Literal[ComponentType.MCP_CLIENT]
|
|
9
|
-
endpoint:
|
|
9
|
+
endpoint: Optional[str] = None
|
|
10
10
|
actions: Optional[Dict[str, McpClientActionConfig]] = Field(default_factory=dict)
|
{model_compose-0.0.5 → model_compose-0.0.6}/src/mindor/dsl/schema/component/impl/mcp_server.py
RENAMED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
from typing import Type, Union, Literal, Optional, Dict, List, Tuple, Set, Annotated, Any
|
|
2
|
-
from pydantic import BaseModel, Field
|
|
2
|
+
from pydantic import BaseModel, Field
|
|
3
3
|
from pydantic import model_validator
|
|
4
4
|
from mindor.dsl.schema.action import McpServerActionConfig
|
|
5
5
|
from .common import ComponentType, CommonComponentConfig
|
{model_compose-0.0.5 → model_compose-0.0.6}/src/mindor/dsl/schema/controller/impl/http_server.py
RENAMED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
from typing import Type, Union, Literal, Optional, Dict, List, Tuple, Set, Annotated, Any
|
|
2
|
-
from pydantic import BaseModel, Field
|
|
2
|
+
from pydantic import BaseModel, Field
|
|
3
3
|
from pydantic import model_validator
|
|
4
4
|
from .common import ControllerType, CommonControllerConfig
|
|
5
5
|
|
{model_compose-0.0.5 → model_compose-0.0.6}/src/mindor/dsl/schema/controller/impl/mcp_server.py
RENAMED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
from typing import Type, Union, Literal, Optional, Dict, List, Tuple, Set, Annotated, Any
|
|
2
|
-
from pydantic import BaseModel, Field
|
|
2
|
+
from pydantic import BaseModel, Field
|
|
3
3
|
from pydantic import model_validator
|
|
4
4
|
from .common import ControllerType, CommonControllerConfig
|
|
5
5
|
|
{model_compose-0.0.5 → model_compose-0.0.6}/src/mindor/dsl/schema/listener/impl/http_callback.py
RENAMED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
from typing import Type, Union, Literal, Optional, Dict, List, Tuple, Set, Annotated, Any
|
|
2
|
-
from pydantic import BaseModel, Field
|
|
2
|
+
from pydantic import BaseModel, Field
|
|
3
3
|
from pydantic import model_validator
|
|
4
4
|
from .common import ListenerType, CommonListenerConfig
|
|
5
5
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
from typing import Type, Union, Literal, Optional, Dict, List, Tuple, Set, Annotated, Any
|
|
2
|
-
from pydantic import BaseModel, Field
|
|
2
|
+
from pydantic import BaseModel, Field
|
|
3
3
|
from pydantic import model_validator
|
|
4
4
|
from .common import RuntimeType, CommonRumtimeConfig
|
|
5
5
|
|
|
@@ -31,6 +31,7 @@ src/mindor/core/runtime/env.py
|
|
|
31
31
|
src/mindor/core/utils/__init__.py
|
|
32
32
|
src/mindor/core/utils/expiring.py
|
|
33
33
|
src/mindor/core/utils/http_headers.py
|
|
34
|
+
src/mindor/core/utils/resources.py
|
|
34
35
|
src/mindor/core/utils/template.py
|
|
35
36
|
src/mindor/core/utils/workqueue.py
|
|
36
37
|
src/mindor/core/workflow/__init__.py
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{model_compose-0.0.5 → model_compose-0.0.6}/src/mindor/core/listener/engine/http_callback.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{model_compose-0.0.5 → model_compose-0.0.6}/src/mindor/dsl/schema/component/impl/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{model_compose-0.0.5 → model_compose-0.0.6}/src/mindor/dsl/schema/controller/impl/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|