model-compose 0.0.3__tar.gz → 0.0.5__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.3/src/model_compose.egg-info → model_compose-0.0.5}/PKG-INFO +1 -1
- {model_compose-0.0.3 → model_compose-0.0.5}/pyproject.toml +1 -1
- {model_compose-0.0.3 → model_compose-0.0.5}/src/mindor/core/component/engine/base.py +3 -3
- {model_compose-0.0.3 → model_compose-0.0.5}/src/mindor/core/component/engine/context.py +5 -1
- {model_compose-0.0.3 → model_compose-0.0.5}/src/mindor/core/component/engine/http_client.py +20 -14
- {model_compose-0.0.3 → model_compose-0.0.5}/src/mindor/core/controller/engine/base.py +2 -2
- {model_compose-0.0.3 → model_compose-0.0.5}/src/mindor/core/controller/engine/http_server.py +21 -8
- model_compose-0.0.5/src/mindor/core/listener/__init__.py +1 -0
- model_compose-0.0.5/src/mindor/core/listener/engine/__init__.py +2 -0
- model_compose-0.0.5/src/mindor/core/listener/engine/base.py +13 -0
- model_compose-0.0.5/src/mindor/core/listener/engine/http_callback.py +37 -0
- model_compose-0.0.5/src/mindor/core/listener/listener.py +9 -0
- model_compose-0.0.5/src/mindor/core/utils/http_headers.py +24 -0
- {model_compose-0.0.3 → model_compose-0.0.5}/src/mindor/core/workflow/context.py +5 -1
- {model_compose-0.0.3 → model_compose-0.0.5}/src/mindor/core/workflow/job.py +3 -1
- {model_compose-0.0.3 → model_compose-0.0.5}/src/mindor/core/workflow/workflow.py +2 -2
- {model_compose-0.0.3 → model_compose-0.0.5}/src/mindor/dsl/schema/action/impl/http_client.py +19 -3
- {model_compose-0.0.3 → model_compose-0.0.5}/src/mindor/dsl/schema/component/impl/http_client.py +4 -4
- {model_compose-0.0.3 → model_compose-0.0.5}/src/mindor/dsl/schema/controller/impl/http_server.py +2 -1
- model_compose-0.0.5/src/mindor/dsl/schema/listener/__init__.py +1 -0
- model_compose-0.0.5/src/mindor/dsl/schema/listener/impl/__init__.py +2 -0
- model_compose-0.0.5/src/mindor/dsl/schema/listener/impl/common.py +7 -0
- model_compose-0.0.5/src/mindor/dsl/schema/listener/impl/http_callback.py +25 -0
- model_compose-0.0.5/src/mindor/dsl/schema/listener/impl/types.py +4 -0
- model_compose-0.0.5/src/mindor/dsl/schema/listener/listener.py +10 -0
- {model_compose-0.0.3 → model_compose-0.0.5/src/model_compose.egg-info}/PKG-INFO +1 -1
- {model_compose-0.0.3 → model_compose-0.0.5}/src/model_compose.egg-info/SOURCES.txt +12 -0
- {model_compose-0.0.3 → model_compose-0.0.5}/LICENSE +0 -0
- {model_compose-0.0.3 → model_compose-0.0.5}/README.md +0 -0
- {model_compose-0.0.3 → model_compose-0.0.5}/setup.cfg +0 -0
- {model_compose-0.0.3 → model_compose-0.0.5}/src/mindor/__init__.py +0 -0
- {model_compose-0.0.3 → model_compose-0.0.5}/src/mindor/cli/__init__.py +0 -0
- {model_compose-0.0.3 → model_compose-0.0.5}/src/mindor/cli/compose.py +0 -0
- {model_compose-0.0.3 → model_compose-0.0.5}/src/mindor/core/__init__.py +0 -0
- {model_compose-0.0.3 → model_compose-0.0.5}/src/mindor/core/component/__init__.py +0 -0
- {model_compose-0.0.3 → model_compose-0.0.5}/src/mindor/core/component/component.py +0 -0
- {model_compose-0.0.3 → model_compose-0.0.5}/src/mindor/core/component/engine/__init__.py +0 -0
- {model_compose-0.0.3 → model_compose-0.0.5}/src/mindor/core/component/engine/http_server.py +0 -0
- {model_compose-0.0.3 → model_compose-0.0.5}/src/mindor/core/compose/__init__.py +0 -0
- {model_compose-0.0.3 → model_compose-0.0.5}/src/mindor/core/compose/compose.py +0 -0
- {model_compose-0.0.3 → model_compose-0.0.5}/src/mindor/core/compose/manager.py +0 -0
- {model_compose-0.0.3 → model_compose-0.0.5}/src/mindor/core/controller/__init__.py +0 -0
- {model_compose-0.0.3 → model_compose-0.0.5}/src/mindor/core/controller/controller.py +0 -0
- {model_compose-0.0.3 → model_compose-0.0.5}/src/mindor/core/controller/engine/__init__.py +0 -0
- {model_compose-0.0.3 → model_compose-0.0.5}/src/mindor/core/controller/engine/mcp_server.py +0 -0
- {model_compose-0.0.3 → model_compose-0.0.5}/src/mindor/core/runtime/__init__.py +0 -0
- {model_compose-0.0.3 → model_compose-0.0.5}/src/mindor/core/runtime/env.py +0 -0
- {model_compose-0.0.3 → model_compose-0.0.5}/src/mindor/core/utils/__init__.py +0 -0
- {model_compose-0.0.3 → model_compose-0.0.5}/src/mindor/core/utils/expiring.py +0 -0
- {model_compose-0.0.3 → model_compose-0.0.5}/src/mindor/core/utils/template.py +0 -0
- {model_compose-0.0.3 → model_compose-0.0.5}/src/mindor/core/utils/workqueue.py +0 -0
- {model_compose-0.0.3 → model_compose-0.0.5}/src/mindor/core/workflow/__init__.py +0 -0
- {model_compose-0.0.3 → model_compose-0.0.5}/src/mindor/dsl/__init__.py +0 -0
- {model_compose-0.0.3 → model_compose-0.0.5}/src/mindor/dsl/loader.py +1 -1
- {model_compose-0.0.3 → model_compose-0.0.5}/src/mindor/dsl/schema/__init__.py +0 -0
- {model_compose-0.0.3 → model_compose-0.0.5}/src/mindor/dsl/schema/action/__init__.py +0 -0
- {model_compose-0.0.3 → model_compose-0.0.5}/src/mindor/dsl/schema/action/action.py +1 -1
- {model_compose-0.0.3 → model_compose-0.0.5}/src/mindor/dsl/schema/action/impl/__init__.py +0 -0
- {model_compose-0.0.3 → model_compose-0.0.5}/src/mindor/dsl/schema/action/impl/common.py +1 -1
- {model_compose-0.0.3 → model_compose-0.0.5}/src/mindor/dsl/schema/action/impl/http_server.py +1 -1
- {model_compose-0.0.3 → model_compose-0.0.5}/src/mindor/dsl/schema/action/impl/mcp_client.py +1 -1
- {model_compose-0.0.3 → model_compose-0.0.5}/src/mindor/dsl/schema/action/impl/mcp_server.py +1 -1
- {model_compose-0.0.3 → model_compose-0.0.5}/src/mindor/dsl/schema/component/__init__.py +0 -0
- {model_compose-0.0.3 → model_compose-0.0.5}/src/mindor/dsl/schema/component/component.py +0 -0
- {model_compose-0.0.3 → model_compose-0.0.5}/src/mindor/dsl/schema/component/impl/__init__.py +0 -0
- {model_compose-0.0.3 → model_compose-0.0.5}/src/mindor/dsl/schema/component/impl/common.py +1 -1
- {model_compose-0.0.3 → model_compose-0.0.5}/src/mindor/dsl/schema/component/impl/http_server.py +1 -1
- {model_compose-0.0.3 → model_compose-0.0.5}/src/mindor/dsl/schema/component/impl/mcp_client.py +1 -1
- {model_compose-0.0.3 → model_compose-0.0.5}/src/mindor/dsl/schema/component/impl/mcp_server.py +1 -1
- {model_compose-0.0.3 → model_compose-0.0.5}/src/mindor/dsl/schema/component/impl/types.py +0 -0
- {model_compose-0.0.3 → model_compose-0.0.5}/src/mindor/dsl/schema/compose.py +1 -1
- {model_compose-0.0.3 → model_compose-0.0.5}/src/mindor/dsl/schema/controller/__init__.py +0 -0
- {model_compose-0.0.3 → model_compose-0.0.5}/src/mindor/dsl/schema/controller/controller.py +1 -1
- {model_compose-0.0.3 → model_compose-0.0.5}/src/mindor/dsl/schema/controller/impl/__init__.py +0 -0
- {model_compose-0.0.3 → model_compose-0.0.5}/src/mindor/dsl/schema/controller/impl/common.py +1 -1
- {model_compose-0.0.3 → model_compose-0.0.5}/src/mindor/dsl/schema/controller/impl/mcp_server.py +1 -1
- {model_compose-0.0.3 → model_compose-0.0.5}/src/mindor/dsl/schema/controller/impl/types.py +0 -0
- {model_compose-0.0.3 → model_compose-0.0.5}/src/mindor/dsl/schema/runtime/__init__.py +0 -0
- {model_compose-0.0.3 → model_compose-0.0.5}/src/mindor/dsl/schema/runtime/impl/__init__.py +0 -0
- {model_compose-0.0.3 → model_compose-0.0.5}/src/mindor/dsl/schema/runtime/impl/common.py +1 -1
- {model_compose-0.0.3 → model_compose-0.0.5}/src/mindor/dsl/schema/runtime/impl/docker.py +1 -1
- {model_compose-0.0.3 → model_compose-0.0.5}/src/mindor/dsl/schema/runtime/impl/types.py +0 -0
- {model_compose-0.0.3 → model_compose-0.0.5}/src/mindor/dsl/schema/runtime/runtime.py +1 -1
- {model_compose-0.0.3 → model_compose-0.0.5}/src/mindor/dsl/schema/workflow.py +1 -1
- {model_compose-0.0.3 → model_compose-0.0.5}/src/model_compose.egg-info/dependency_links.txt +0 -0
- {model_compose-0.0.3 → model_compose-0.0.5}/src/model_compose.egg-info/entry_points.txt +0 -0
- {model_compose-0.0.3 → model_compose-0.0.5}/src/model_compose.egg-info/requires.txt +0 -0
- {model_compose-0.0.3 → model_compose-0.0.5}/src/model_compose.egg-info/top_level.txt +0 -0
- {model_compose-0.0.3 → model_compose-0.0.5}/tests/test_cli.py +0 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
from abc import ABC, abstractmethod
|
|
2
1
|
from typing import Type, Union, Literal, Optional, Dict, List, Tuple, Set, Annotated, Callable, Any
|
|
2
|
+
from abc import ABC, abstractmethod
|
|
3
3
|
|
|
4
4
|
from mindor.dsl.schema.component import ComponentConfig, ComponentType
|
|
5
5
|
from mindor.dsl.schema.action import ActionConfig
|
|
@@ -78,9 +78,9 @@ class BaseComponent(ABC):
|
|
|
78
78
|
if self.daemon_task:
|
|
79
79
|
await self.daemon_task
|
|
80
80
|
|
|
81
|
-
async def run(self, action_id: Union[str, None], input: Dict[str, Any]) -> Dict[str, Any]:
|
|
81
|
+
async def run(self, action_id: Union[str, None], call_id: str, input: Dict[str, Any]) -> Dict[str, Any]:
|
|
82
82
|
_, action = ActionResolver(self.config.actions).resolve(action_id)
|
|
83
|
-
context = ComponentContext(input, self.env)
|
|
83
|
+
context = ComponentContext(call_id, input, self.env)
|
|
84
84
|
|
|
85
85
|
if self.queue:
|
|
86
86
|
return await (await self.queue.schedule(action, context))
|
|
@@ -2,9 +2,11 @@ from typing import Type, Union, Literal, Optional, Dict, List, Tuple, Set, Annot
|
|
|
2
2
|
from mindor.core.utils.template import TemplateRenderer
|
|
3
3
|
|
|
4
4
|
class ComponentContext:
|
|
5
|
-
def __init__(self, input: Dict[str, Any], env: Dict[str, str]):
|
|
5
|
+
def __init__(self, call_id: str, input: Dict[str, Any], env: Dict[str, str]):
|
|
6
|
+
self.call_id: str = call_id
|
|
6
7
|
self.input: Dict[str, Any] = input
|
|
7
8
|
self.env: Dict[str, str] = env
|
|
9
|
+
self.context: Dict[str, Any] = { "call_id": call_id }
|
|
8
10
|
self.sources: Dict[str, Any] = {}
|
|
9
11
|
self.renderer: TemplateRenderer = TemplateRenderer(self._resolve_source)
|
|
10
12
|
|
|
@@ -21,4 +23,6 @@ class ComponentContext:
|
|
|
21
23
|
return self.input
|
|
22
24
|
if key == "env":
|
|
23
25
|
return self.env
|
|
26
|
+
if key == "context":
|
|
27
|
+
return self.context
|
|
24
28
|
raise KeyError(f"Unknown source: {key}")
|
|
@@ -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 HttpClientComponentConfig, HttpClientActionConfig, HttpUrl
|
|
3
|
+
from mindor.core.utils.http_headers import parse_options_header, get_header_value
|
|
3
4
|
from .base import BaseComponent, ComponentType, ComponentEngineMap, ActionConfig
|
|
4
5
|
from .context import ComponentContext
|
|
5
6
|
|
|
6
|
-
from
|
|
7
|
-
from urllib.parse import urlencode, urljoin
|
|
7
|
+
from urllib.parse import urlencode
|
|
8
8
|
import aiohttp, json
|
|
9
9
|
|
|
10
10
|
class HttpClientAction:
|
|
@@ -22,14 +22,14 @@ class HttpClientAction:
|
|
|
22
22
|
response = await self._request(url, method, params, body, headers)
|
|
23
23
|
|
|
24
24
|
if not self.config.output:
|
|
25
|
-
return response
|
|
25
|
+
return response
|
|
26
26
|
|
|
27
27
|
if response:
|
|
28
28
|
context.register_source("response", response)
|
|
29
29
|
|
|
30
30
|
return context.render_template(self.config.output)
|
|
31
31
|
|
|
32
|
-
async def _request(self, url: str, method: str, params: Optional[Dict[str, Any]], body: Optional[
|
|
32
|
+
async def _request(self, url: str, method: str, params: Optional[Dict[str, Any]], body: Optional[Any], headers: Optional[Dict[str, str]]) -> Any:
|
|
33
33
|
async with aiohttp.ClientSession() as session:
|
|
34
34
|
async with session.request(
|
|
35
35
|
method,
|
|
@@ -49,19 +49,19 @@ class HttpClientAction:
|
|
|
49
49
|
|
|
50
50
|
return context.render_template(str(self.config.endpoint))
|
|
51
51
|
|
|
52
|
-
def _serialize_request_body(self, body:
|
|
53
|
-
content_type =
|
|
54
|
-
|
|
55
|
-
if content_type == "application/json":
|
|
56
|
-
return json.dumps(body)
|
|
52
|
+
def _serialize_request_body(self, body: Any, headers: Optional[Dict[str, str]]) -> Any:
|
|
53
|
+
content_type, _ = parse_options_header(get_header_value(headers, "Content-Type", ""))
|
|
57
54
|
|
|
58
55
|
if content_type == "application/x-www-form-urlencoded":
|
|
59
56
|
return urlencode(body)
|
|
60
|
-
|
|
61
|
-
|
|
57
|
+
|
|
58
|
+
if isinstance(body, (str, bytes)):
|
|
59
|
+
return body
|
|
60
|
+
|
|
61
|
+
return json.dumps(body)
|
|
62
62
|
|
|
63
|
-
async def _deserialize_response_body(self, response: aiohttp.ClientResponse) ->
|
|
64
|
-
content_type = response.headers.get("Content-Type", "")
|
|
63
|
+
async def _deserialize_response_body(self, response: aiohttp.ClientResponse) -> Any:
|
|
64
|
+
content_type, _ = parse_options_header(response.headers.get("Content-Type", ""))
|
|
65
65
|
|
|
66
66
|
if content_type == "application/json":
|
|
67
67
|
return await response.json()
|
|
@@ -69,7 +69,13 @@ class HttpClientAction:
|
|
|
69
69
|
if content_type.startswith("text/"):
|
|
70
70
|
return await response.text()
|
|
71
71
|
|
|
72
|
-
|
|
72
|
+
_, disposition = parse_options_header(response.headers.get("Content-Disposition"))
|
|
73
|
+
|
|
74
|
+
return {
|
|
75
|
+
"filename": disposition.get("filename"),
|
|
76
|
+
"content_type": content_type,
|
|
77
|
+
"stream": response.content
|
|
78
|
+
}
|
|
73
79
|
|
|
74
80
|
class HttpClientComponent(BaseComponent):
|
|
75
81
|
def __init__(self, id: str, config: HttpClientComponentConfig, env: Dict[str, str], daemon: bool):
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
from typing import Type, Union, Literal, Optional, Dict, List, Tuple, Set, Annotated, Any
|
|
1
2
|
from abc import ABC, abstractmethod
|
|
2
3
|
from dataclasses import dataclass
|
|
3
|
-
from typing import Type, Union, Literal, Optional, Dict, List, Tuple, Set, Annotated, Any
|
|
4
4
|
|
|
5
5
|
from mindor.dsl.schema.controller import ControllerConfig, ControllerType
|
|
6
6
|
from mindor.dsl.schema.component import ComponentConfig
|
|
@@ -125,7 +125,7 @@ class BaseController(ABC):
|
|
|
125
125
|
|
|
126
126
|
try:
|
|
127
127
|
workflow = create_workflow(*WorkflowResolver(self.workflows).resolve(workflow_id), self.components, self.env)
|
|
128
|
-
output = await workflow.run(input)
|
|
128
|
+
output = await workflow.run(task_id, input)
|
|
129
129
|
state = TaskState(task_id=task_id, status="completed", output=output)
|
|
130
130
|
except Exception as e:
|
|
131
131
|
state = TaskState(task_id=task_id, status="failed", error=str(e))
|
{model_compose-0.0.3 → model_compose-0.0.5}/src/mindor/core/controller/engine/http_server.py
RENAMED
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
from pydantic import BaseModel
|
|
2
1
|
from typing import Type, Union, Literal, Optional, Dict, List, Tuple, Set, Annotated, Any
|
|
3
2
|
from typing_extensions import Self
|
|
3
|
+
from pydantic import BaseModel
|
|
4
4
|
|
|
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
8
|
from .base import BaseController, ControllerType, ControllerEngineMap, TaskState
|
|
9
9
|
|
|
10
|
-
from fastapi import FastAPI, Body, HTTPException
|
|
10
|
+
from fastapi import FastAPI, APIRouter, Body, HTTPException
|
|
11
11
|
import uvicorn
|
|
12
12
|
|
|
13
13
|
class WorkflowTaskRequestBody(BaseModel):
|
|
@@ -36,11 +36,13 @@ class HttpServerController(BaseController):
|
|
|
36
36
|
|
|
37
37
|
self.server: Optional[uvicorn.Server] = None
|
|
38
38
|
self.app: FastAPI = FastAPI()
|
|
39
|
-
|
|
39
|
+
self.router: APIRouter = APIRouter()
|
|
40
|
+
|
|
40
41
|
self._configure_routes()
|
|
42
|
+
self.app.include_router(self.router, prefix=self.config.base_path)
|
|
41
43
|
|
|
42
44
|
def _configure_routes(self):
|
|
43
|
-
@self.
|
|
45
|
+
@self.router.post("/workflows", response_model=TaskResult, response_model_exclude_none=True)
|
|
44
46
|
async def run_workflow(
|
|
45
47
|
body: WorkflowTaskRequestBody = Body(...)
|
|
46
48
|
):
|
|
@@ -48,7 +50,7 @@ class HttpServerController(BaseController):
|
|
|
48
50
|
|
|
49
51
|
return TaskResult.from_instance(state)
|
|
50
52
|
|
|
51
|
-
@self.
|
|
53
|
+
@self.router.get("/tasks/{task_id}", response_model=TaskResult, response_model_exclude_none=True)
|
|
52
54
|
async def get_task_state(
|
|
53
55
|
task_id: str
|
|
54
56
|
):
|
|
@@ -59,11 +61,22 @@ class HttpServerController(BaseController):
|
|
|
59
61
|
|
|
60
62
|
return TaskResult.from_instance(state)
|
|
61
63
|
|
|
64
|
+
@self.router.get("/tasks/{task_id}/output")
|
|
65
|
+
async def get_task_output(
|
|
66
|
+
task_id: str
|
|
67
|
+
):
|
|
68
|
+
state = self.get_task_state(task_id)
|
|
69
|
+
|
|
70
|
+
if not state:
|
|
71
|
+
raise HTTPException(status_code=404, detail="Task not found")
|
|
72
|
+
|
|
73
|
+
return state.output
|
|
74
|
+
|
|
62
75
|
async def _serve(self) -> None:
|
|
63
76
|
self.server = uvicorn.Server(uvicorn.Config(
|
|
64
|
-
self.app,
|
|
65
|
-
host=self.config.host,
|
|
66
|
-
port=self.config.port,
|
|
77
|
+
self.app,
|
|
78
|
+
host=self.config.host,
|
|
79
|
+
port=self.config.port,
|
|
67
80
|
log_level="info"
|
|
68
81
|
))
|
|
69
82
|
await self.server.serve()
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from .listener import *
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
from typing import Type, Union, Literal, Optional, Dict, List, Tuple, Set, Annotated, Any
|
|
2
|
+
from abc import ABC, abstractmethod
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
|
|
5
|
+
from mindor.dsl.schema.listener import ListenerConfig, ListenerType
|
|
6
|
+
from mindor.core.listener import BaseListener, create_listener
|
|
7
|
+
|
|
8
|
+
class BaseListener(ABC):
|
|
9
|
+
def __init__(self, config: ListenerConfig, env: Dict[str, str]):
|
|
10
|
+
self.config: ListenerConfig = config
|
|
11
|
+
self.env: Dict[str, str] = env
|
|
12
|
+
|
|
13
|
+
ListenerEngineMap: Dict[ListenerType, Type[BaseListener]] = {}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
from typing import Type, Union, Literal, Optional, Dict, List, Tuple, Set, Annotated, Any
|
|
2
|
+
from typing_extensions import Self
|
|
3
|
+
from pydantic import BaseModel
|
|
4
|
+
|
|
5
|
+
from mindor.dsl.schema.listener import HttpCallbackListenerConfig
|
|
6
|
+
from .base import BaseListener, ListenerType, ListenerEngineMap
|
|
7
|
+
|
|
8
|
+
from fastapi import FastAPI, APIRouter, Body, HTTPException
|
|
9
|
+
import uvicorn
|
|
10
|
+
|
|
11
|
+
class HttpCallbackListener(BaseListener):
|
|
12
|
+
def __init__(self, config: HttpCallbackListenerConfig, env: Dict[str, str]):
|
|
13
|
+
super().__init__(config, env)
|
|
14
|
+
|
|
15
|
+
self.server: Optional[uvicorn.Server] = None
|
|
16
|
+
self.app: FastAPI = FastAPI()
|
|
17
|
+
self.router: APIRouter = APIRouter()
|
|
18
|
+
|
|
19
|
+
self._configure_routes()
|
|
20
|
+
self.app.include_router(self.router, prefix=self.config.base_path)
|
|
21
|
+
|
|
22
|
+
def _configure_routes(self):
|
|
23
|
+
pass
|
|
24
|
+
|
|
25
|
+
async def _serve(self) -> None:
|
|
26
|
+
self.server = uvicorn.Server(uvicorn.Config(
|
|
27
|
+
self.app,
|
|
28
|
+
host=self.config.host,
|
|
29
|
+
port=self.config.port,
|
|
30
|
+
log_level="info"
|
|
31
|
+
))
|
|
32
|
+
await self.server.serve()
|
|
33
|
+
|
|
34
|
+
async def _shutdown(self) -> None:
|
|
35
|
+
self.server.should_exit = True
|
|
36
|
+
|
|
37
|
+
ListenerEngineMap[ListenerType.HTTP_CALLBACK] = HttpCallbackListener
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
from typing import Type, Union, Literal, Optional, Dict, List, Tuple, Set, Annotated, Any
|
|
2
|
+
from mindor.dsl.schema.listener import ListenerConfig
|
|
3
|
+
from .engine import BaseListener, ListenerEngineMap
|
|
4
|
+
|
|
5
|
+
def create_listener(config: ControllerConfig, env: Dict[str, str]) -> BaseListener:
|
|
6
|
+
try:
|
|
7
|
+
return ListenerEngineMap[config.type](config, env)
|
|
8
|
+
except KeyError:
|
|
9
|
+
raise ValueError(f"Unsupported listener type: {config.type}")
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
from typing import Dict, Tuple, Optional
|
|
2
|
+
from requests.structures import CaseInsensitiveDict
|
|
3
|
+
import re
|
|
4
|
+
|
|
5
|
+
_token_pattern = r"([\w!#$%&'*+\-.^_`|~]+)"
|
|
6
|
+
_quoted_pattern = r'"([^"]*)"'
|
|
7
|
+
_option_regex = re.compile(fr";\s*{_token_pattern}=(?:{_token_pattern}|{_quoted_pattern})", re.ASCII)
|
|
8
|
+
_firefox_escape_fix = re.compile(r'\\"(?!; |\s*$)')
|
|
9
|
+
|
|
10
|
+
def parse_options_header(value: str) -> Tuple[str, Dict[str, str]]:
|
|
11
|
+
value = _firefox_escape_fix.sub("%22", value)
|
|
12
|
+
pos = value.find(";")
|
|
13
|
+
if pos >= 0:
|
|
14
|
+
options = {
|
|
15
|
+
m.group(1).lower(): m.group(2) or m.group(3).replace("%22", "") for m in _option_regex.finditer(value[pos:])
|
|
16
|
+
}
|
|
17
|
+
value = value[:pos]
|
|
18
|
+
else:
|
|
19
|
+
options = {}
|
|
20
|
+
|
|
21
|
+
return value.strip().lower(), options
|
|
22
|
+
|
|
23
|
+
def get_header_value(headers: Dict[str, str], header: str, default_value: Optional[str] = None) -> Optional[str]:
|
|
24
|
+
return CaseInsensitiveDict(headers or {}).get(header, default_value)
|
|
@@ -2,9 +2,11 @@ from typing import Type, Union, Literal, Optional, Dict, List, Tuple, Set, Annot
|
|
|
2
2
|
from mindor.core.utils.template import TemplateRenderer
|
|
3
3
|
|
|
4
4
|
class WorkflowContext:
|
|
5
|
-
def __init__(self, input: Dict[str, Any], env: Dict[str, str]):
|
|
5
|
+
def __init__(self, task_id: str, input: Dict[str, Any], env: Dict[str, str]):
|
|
6
|
+
self.task_id: str = task_id
|
|
6
7
|
self.input: Dict[str, Any] = input
|
|
7
8
|
self.env: Dict[str, str] = env
|
|
9
|
+
self.context: Dict[str, Any] = { "task_id": task_id }
|
|
8
10
|
self.sources: Dict[str, Any] = { "jobs": {} }
|
|
9
11
|
self.renderer = TemplateRenderer(self._resolve_source)
|
|
10
12
|
|
|
@@ -24,4 +26,6 @@ class WorkflowContext:
|
|
|
24
26
|
return self.input
|
|
25
27
|
if key == "env":
|
|
26
28
|
return self.env
|
|
29
|
+
if key == "context":
|
|
30
|
+
return self.context
|
|
27
31
|
raise KeyError(f"Unknown source: {key}")
|
|
@@ -3,6 +3,7 @@ from mindor.dsl.schema.workflow import JobConfig
|
|
|
3
3
|
from mindor.dsl.schema.component import ComponentConfig
|
|
4
4
|
from mindor.core.component import BaseComponent
|
|
5
5
|
from .context import WorkflowContext
|
|
6
|
+
import ulid
|
|
6
7
|
|
|
7
8
|
class Job:
|
|
8
9
|
def __init__(self, id: str, config: JobConfig, component_provider: Callable[[Union[ComponentConfig, str]], BaseComponent]):
|
|
@@ -16,8 +17,9 @@ class Job:
|
|
|
16
17
|
if not component.started:
|
|
17
18
|
await component.start()
|
|
18
19
|
|
|
20
|
+
call_id = ulid.ulid()
|
|
19
21
|
input = context.render_template(self.config.input)
|
|
20
|
-
output = await component.run(self.config.action, input)
|
|
22
|
+
output = await component.run(self.config.action, call_id, input)
|
|
21
23
|
|
|
22
24
|
context.register_source("output", output)
|
|
23
25
|
output = context.render_template(self.config.output)
|
|
@@ -129,8 +129,8 @@ class Workflow:
|
|
|
129
129
|
self.components: Dict[str, ComponentConfig] = components
|
|
130
130
|
self.env: Dict[str, str] = env
|
|
131
131
|
|
|
132
|
-
async def run(self, input: Dict[str, Any]) -> Dict[str, Any]:
|
|
133
|
-
context = WorkflowContext(input, self.env)
|
|
132
|
+
async def run(self, task_id: str, input: Dict[str, Any]) -> Dict[str, Any]:
|
|
133
|
+
context = WorkflowContext(task_id, input, self.env)
|
|
134
134
|
runner = WorkflowRunner(self.config.jobs, self._create_component)
|
|
135
135
|
|
|
136
136
|
output = await runner.run(context)
|
{model_compose-0.0.3 → model_compose-0.0.5}/src/mindor/dsl/schema/action/impl/http_client.py
RENAMED
|
@@ -1,9 +1,17 @@
|
|
|
1
|
+
from typing import Type, Union, Literal, Optional, Dict, List, Tuple, Set, Annotated, Any
|
|
1
2
|
from pydantic import BaseModel, Field, HttpUrl
|
|
2
3
|
from pydantic import model_validator
|
|
3
|
-
from typing import Type, Union, Literal, Optional, Dict, List, Tuple, Set, Annotated, Any
|
|
4
4
|
from .common import CommonActionConfig
|
|
5
5
|
|
|
6
|
-
class
|
|
6
|
+
class CommonCompletionConfig(BaseModel):
|
|
7
|
+
type: Literal[ "callback", "polling" ]
|
|
8
|
+
|
|
9
|
+
class CallbackCompletionConfig(CommonCompletionConfig):
|
|
10
|
+
type: Literal["callback"]
|
|
11
|
+
wait_for: str
|
|
12
|
+
|
|
13
|
+
class PollingCompletionConfig(CommonCompletionConfig):
|
|
14
|
+
type: Literal["polling"]
|
|
7
15
|
endpoint: Optional[HttpUrl] = None
|
|
8
16
|
path: Optional[str] = None
|
|
9
17
|
method: Literal[ "GET", "POST", "PUT", "DELETE", "PATCH" ] = "GET"
|
|
@@ -19,6 +27,14 @@ class HttpClientActionCompletionConfig(CommonActionConfig):
|
|
|
19
27
|
raise ValueError("Either 'endpoint' or 'path' must be set, but not both.")
|
|
20
28
|
return values
|
|
21
29
|
|
|
30
|
+
HttpClientCompletionConfig = Annotated[
|
|
31
|
+
Union[
|
|
32
|
+
CallbackCompletionConfig,
|
|
33
|
+
PollingCompletionConfig
|
|
34
|
+
],
|
|
35
|
+
Field(discriminator="type")
|
|
36
|
+
]
|
|
37
|
+
|
|
22
38
|
class HttpClientActionConfig(CommonActionConfig):
|
|
23
39
|
endpoint: Optional[HttpUrl] = None
|
|
24
40
|
path: Optional[str] = None
|
|
@@ -27,7 +43,7 @@ class HttpClientActionConfig(CommonActionConfig):
|
|
|
27
43
|
body: Optional[Dict[str, Any]] = Field(default_factory=dict)
|
|
28
44
|
params: Optional[Dict[str, str]] = Field(default_factory=dict)
|
|
29
45
|
deferred: bool = False
|
|
30
|
-
completion: Optional[
|
|
46
|
+
completion: Optional[HttpClientCompletionConfig] = None
|
|
31
47
|
|
|
32
48
|
@model_validator(mode="before")
|
|
33
49
|
def validate_endpoint_or_path(cls, values):
|
{model_compose-0.0.3 → model_compose-0.0.5}/src/mindor/dsl/schema/component/impl/http_client.py
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
from typing import Type, Union, Literal, Optional, Dict, List, Tuple, Set, Annotated, Any
|
|
1
2
|
from pydantic import BaseModel, Field, HttpUrl
|
|
2
3
|
from pydantic import model_validator
|
|
3
|
-
from typing import Type, Union, Literal, Optional, Dict, List, Tuple, Set, Annotated, Any
|
|
4
4
|
from mindor.dsl.schema.action import HttpClientActionConfig
|
|
5
5
|
from .common import ComponentType, CommonComponentConfig
|
|
6
6
|
|
|
@@ -27,7 +27,7 @@ class HttpClientComponentConfig(CommonComponentConfig):
|
|
|
27
27
|
|
|
28
28
|
@model_validator(mode="after")
|
|
29
29
|
def validate_baseurl_with_completion(self):
|
|
30
|
-
for action_id, action in self.actions.items():
|
|
31
|
-
|
|
32
|
-
|
|
30
|
+
# for action_id, action in self.actions.items():
|
|
31
|
+
# if action.completion and action.completion.path and not self.base_url:
|
|
32
|
+
# raise ValueError(f"Completion for action '{action_id}' uses 'path' but 'base_url' is not set in the component.")
|
|
33
33
|
return self
|
{model_compose-0.0.3 → model_compose-0.0.5}/src/mindor/dsl/schema/controller/impl/http_server.py
RENAMED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
+
from typing import Type, Union, Literal, Optional, Dict, List, Tuple, Set, Annotated, Any
|
|
1
2
|
from pydantic import BaseModel, Field, HttpUrl
|
|
2
3
|
from pydantic import model_validator
|
|
3
|
-
from typing import Type, Union, Literal, Optional, Dict, List, Tuple, Set, Annotated, Any
|
|
4
4
|
from .common import ControllerType, CommonControllerConfig
|
|
5
5
|
|
|
6
6
|
class HttpServerControllerConfig(CommonControllerConfig):
|
|
7
7
|
type: Literal[ControllerType.HTTP_SERVER]
|
|
8
8
|
host: Optional[str] = "0.0.0.0"
|
|
9
9
|
port: Optional[int] = 8080
|
|
10
|
+
base_path: Optional[str] = None
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from .listener import *
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
from typing import Type, Union, Literal, Optional, Dict, List, Tuple, Set, Annotated, Any
|
|
2
|
+
from pydantic import BaseModel, Field
|
|
3
|
+
from .types import ListenerType
|
|
4
|
+
|
|
5
|
+
class CommonListenerConfig(BaseModel):
|
|
6
|
+
type: ListenerType
|
|
7
|
+
runtime: Literal[ "docker", "native" ] = "native"
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
from typing import Type, Union, Literal, Optional, Dict, List, Tuple, Set, Annotated, Any
|
|
2
|
+
from pydantic import BaseModel, Field, HttpUrl
|
|
3
|
+
from pydantic import model_validator
|
|
4
|
+
from .common import ListenerType, CommonListenerConfig
|
|
5
|
+
|
|
6
|
+
class HttpCallbackConfig(BaseModel):
|
|
7
|
+
path: str
|
|
8
|
+
method: Literal[ "GET", "POST", "PUT", "DELETE", "PATCH" ] = "GET"
|
|
9
|
+
bulk: bool = False
|
|
10
|
+
identify_by: str
|
|
11
|
+
|
|
12
|
+
class HttpCallbackListenerConfig(CommonListenerConfig):
|
|
13
|
+
type: Literal[ListenerType.HTTP_CALLBACK]
|
|
14
|
+
host: Optional[str] = "0.0.0.0"
|
|
15
|
+
port: Optional[int] = 8090
|
|
16
|
+
base_path: Optional[str] = None
|
|
17
|
+
callbacks: Optional[List[HttpCallbackConfig]] = Field(default_factory=list)
|
|
18
|
+
|
|
19
|
+
@model_validator(mode="before")
|
|
20
|
+
def inflate_single_callback(cls, values):
|
|
21
|
+
if "callbacks" not in values:
|
|
22
|
+
callback_keys = set(HttpCallbackConfig.model_fields.keys())
|
|
23
|
+
if any(k in values for k in callback_keys):
|
|
24
|
+
values["callbacks"] = [ { k: values.pop(k) for k in callback_keys if k in values } ]
|
|
25
|
+
return values
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
from typing import Type, Union, Literal, Optional, Dict, List, Tuple, Set, Annotated, Any
|
|
2
|
+
from pydantic import BaseModel, Field, HttpUrl
|
|
3
|
+
from .impl import *
|
|
4
|
+
|
|
5
|
+
ListenerConfig = Annotated[
|
|
6
|
+
Union[
|
|
7
|
+
HttpCallbackListenerConfig
|
|
8
|
+
],
|
|
9
|
+
Field(discriminator="type")
|
|
10
|
+
]
|
|
@@ -21,10 +21,16 @@ src/mindor/core/controller/engine/__init__.py
|
|
|
21
21
|
src/mindor/core/controller/engine/base.py
|
|
22
22
|
src/mindor/core/controller/engine/http_server.py
|
|
23
23
|
src/mindor/core/controller/engine/mcp_server.py
|
|
24
|
+
src/mindor/core/listener/__init__.py
|
|
25
|
+
src/mindor/core/listener/listener.py
|
|
26
|
+
src/mindor/core/listener/engine/__init__.py
|
|
27
|
+
src/mindor/core/listener/engine/base.py
|
|
28
|
+
src/mindor/core/listener/engine/http_callback.py
|
|
24
29
|
src/mindor/core/runtime/__init__.py
|
|
25
30
|
src/mindor/core/runtime/env.py
|
|
26
31
|
src/mindor/core/utils/__init__.py
|
|
27
32
|
src/mindor/core/utils/expiring.py
|
|
33
|
+
src/mindor/core/utils/http_headers.py
|
|
28
34
|
src/mindor/core/utils/template.py
|
|
29
35
|
src/mindor/core/utils/workqueue.py
|
|
30
36
|
src/mindor/core/workflow/__init__.py
|
|
@@ -60,6 +66,12 @@ src/mindor/dsl/schema/controller/impl/common.py
|
|
|
60
66
|
src/mindor/dsl/schema/controller/impl/http_server.py
|
|
61
67
|
src/mindor/dsl/schema/controller/impl/mcp_server.py
|
|
62
68
|
src/mindor/dsl/schema/controller/impl/types.py
|
|
69
|
+
src/mindor/dsl/schema/listener/__init__.py
|
|
70
|
+
src/mindor/dsl/schema/listener/listener.py
|
|
71
|
+
src/mindor/dsl/schema/listener/impl/__init__.py
|
|
72
|
+
src/mindor/dsl/schema/listener/impl/common.py
|
|
73
|
+
src/mindor/dsl/schema/listener/impl/http_callback.py
|
|
74
|
+
src/mindor/dsl/schema/listener/impl/types.py
|
|
63
75
|
src/mindor/dsl/schema/runtime/__init__.py
|
|
64
76
|
src/mindor/dsl/schema/runtime/runtime.py
|
|
65
77
|
src/mindor/dsl/schema/runtime/impl/__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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
from pydantic import BaseModel, Field
|
|
2
1
|
from typing import Type, Union, Literal, Optional, Dict, List, Tuple, Set, Annotated, Any
|
|
2
|
+
from pydantic import BaseModel, Field
|
|
3
3
|
|
|
4
4
|
class CommonActionConfig(BaseModel):
|
|
5
5
|
output: Optional[Dict[str, Any]] = Field(default_factory=dict)
|
{model_compose-0.0.3 → model_compose-0.0.5}/src/mindor/dsl/schema/action/impl/http_server.py
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
from typing import Type, Union, Literal, Optional, Dict, List, Tuple, Set, Annotated, Any
|
|
1
2
|
from pydantic import BaseModel, Field, HttpUrl
|
|
2
3
|
from pydantic import model_validator
|
|
3
|
-
from typing import Type, Union, Literal, Optional, Dict, List, Tuple, Set, Annotated, Any
|
|
4
4
|
from .common import CommonActionConfig
|
|
5
5
|
|
|
6
6
|
class HttpServerActionConfig(CommonActionConfig):
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
from typing import Type, Union, Literal, Optional, Dict, List, Tuple, Set, Annotated, Any
|
|
1
2
|
from pydantic import BaseModel, Field, HttpUrl
|
|
2
3
|
from pydantic import model_validator
|
|
3
|
-
from typing import Type, Union, Literal, Optional, Dict, List, Tuple, Set, Annotated, Any
|
|
4
4
|
from .common import CommonActionConfig
|
|
5
5
|
|
|
6
6
|
class McpClientActionConfig(CommonActionConfig):
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
from typing import Type, Union, Literal, Optional, Dict, List, Tuple, Set, Annotated, Any
|
|
1
2
|
from pydantic import BaseModel, Field, HttpUrl
|
|
2
3
|
from pydantic import model_validator
|
|
3
|
-
from typing import Type, Union, Literal, Optional, Dict, List, Tuple, Set, Annotated, Any
|
|
4
4
|
from .common import CommonActionConfig
|
|
5
5
|
|
|
6
6
|
class McpServerActionConfig(CommonActionConfig):
|
|
File without changes
|
|
File without changes
|
{model_compose-0.0.3 → model_compose-0.0.5}/src/mindor/dsl/schema/component/impl/__init__.py
RENAMED
|
File without changes
|
{model_compose-0.0.3 → model_compose-0.0.5}/src/mindor/dsl/schema/component/impl/http_server.py
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
from typing import Type, Union, Literal, Optional, Dict, List, Tuple, Set, Annotated, Any
|
|
1
2
|
from pydantic import BaseModel, Field, HttpUrl
|
|
2
3
|
from pydantic import model_validator
|
|
3
|
-
from typing import Type, Union, Literal, Optional, Dict, List, Tuple, Set, Annotated, Any
|
|
4
4
|
from mindor.dsl.schema.action import HttpServerActionConfig
|
|
5
5
|
from .common import ComponentType, CommonComponentConfig
|
|
6
6
|
|
{model_compose-0.0.3 → model_compose-0.0.5}/src/mindor/dsl/schema/component/impl/mcp_client.py
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
from typing import Type, Union, Literal, Optional, Dict, List, Tuple, Set, Annotated, Any
|
|
1
2
|
from pydantic import BaseModel, Field, HttpUrl
|
|
2
3
|
from pydantic import model_validator
|
|
3
|
-
from typing import Type, Union, Literal, Optional, Dict, List, Tuple, Set, Annotated, Any
|
|
4
4
|
from mindor.dsl.schema.action import McpClientActionConfig
|
|
5
5
|
from .common import ComponentType, CommonComponentConfig
|
|
6
6
|
|
{model_compose-0.0.3 → model_compose-0.0.5}/src/mindor/dsl/schema/component/impl/mcp_server.py
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
from typing import Type, Union, Literal, Optional, Dict, List, Tuple, Set, Annotated, Any
|
|
1
2
|
from pydantic import BaseModel, Field, HttpUrl
|
|
2
3
|
from pydantic import model_validator
|
|
3
|
-
from typing import Type, Union, Literal, Optional, Dict, List, Tuple, Set, Annotated, Any
|
|
4
4
|
from mindor.dsl.schema.action import McpServerActionConfig
|
|
5
5
|
from .common import ComponentType, CommonComponentConfig
|
|
6
6
|
|
|
File without changes
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
from typing import Type, Union, Literal, Optional, Dict, List, Tuple, Set, Annotated, Any
|
|
1
2
|
from pydantic import BaseModel, Field
|
|
2
3
|
from pydantic import model_validator
|
|
3
|
-
from typing import Type, Union, Literal, Optional, Dict, List, Tuple, Set, Annotated, Any
|
|
4
4
|
|
|
5
5
|
from .controller import ControllerConfig
|
|
6
6
|
from .component import ComponentConfig
|
|
File without changes
|
{model_compose-0.0.3 → model_compose-0.0.5}/src/mindor/dsl/schema/controller/impl/__init__.py
RENAMED
|
File without changes
|
{model_compose-0.0.3 → model_compose-0.0.5}/src/mindor/dsl/schema/controller/impl/mcp_server.py
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
from typing import Type, Union, Literal, Optional, Dict, List, Tuple, Set, Annotated, Any
|
|
1
2
|
from pydantic import BaseModel, Field, HttpUrl
|
|
2
3
|
from pydantic import model_validator
|
|
3
|
-
from typing import Type, Union, Literal, Optional, Dict, List, Tuple, Set, Annotated, Any
|
|
4
4
|
from .common import ControllerType, CommonControllerConfig
|
|
5
5
|
|
|
6
6
|
class McpServerControllerConfig(CommonControllerConfig):
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
from typing import Type, Union, Literal, Optional, Dict, List, Tuple, Set, Annotated, Any
|
|
1
2
|
from pydantic import BaseModel, Field, HttpUrl
|
|
2
3
|
from pydantic import model_validator
|
|
3
|
-
from typing import Type, Union, Literal, Optional, Dict, List, Tuple, Set, Annotated, Any
|
|
4
4
|
from .common import RuntimeType, CommonRumtimeConfig
|
|
5
5
|
|
|
6
6
|
class DockerRuntimeConfig(CommonRumtimeConfig):
|
|
File without changes
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
from typing import Type, Union, Literal, Optional, Dict, List, Tuple, Set, Annotated, Any
|
|
1
2
|
from pydantic import BaseModel, Field
|
|
2
3
|
from pydantic import model_validator
|
|
3
|
-
from typing import Type, Union, Literal, Optional, Dict, List, Tuple, Set, Annotated, Any
|
|
4
4
|
from .component import ComponentConfig
|
|
5
5
|
|
|
6
6
|
class JobConfig(BaseModel):
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|