flock-core 0.4.528__py3-none-any.whl → 0.5.0b0__py3-none-any.whl
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.
Potentially problematic release.
This version of flock-core might be problematic. Click here for more details.
- flock/cli/execute_flock.py +1 -1
- flock/cli/manage_agents.py +6 -6
- flock/components/__init__.py +30 -0
- flock/components/evaluation/__init__.py +9 -0
- flock/components/evaluation/declarative_evaluation_component.py +222 -0
- flock/components/routing/__init__.py +15 -0
- flock/{routers/conditional/conditional_router.py → components/routing/conditional_routing_component.py} +61 -53
- flock/components/routing/default_routing_component.py +103 -0
- flock/components/routing/llm_routing_component.py +206 -0
- flock/components/utility/__init__.py +15 -0
- flock/{modules/enterprise_memory/enterprise_memory_module.py → components/utility/memory_utility_component.py} +195 -173
- flock/{modules/performance/metrics_module.py → components/utility/metrics_utility_component.py} +110 -95
- flock/{modules/output/output_module.py → components/utility/output_utility_component.py} +47 -45
- flock/core/__init__.py +26 -18
- flock/core/agent/__init__.py +16 -0
- flock/core/agent/flock_agent_components.py +104 -0
- flock/core/agent/flock_agent_execution.py +101 -0
- flock/core/agent/flock_agent_integration.py +206 -0
- flock/core/agent/flock_agent_lifecycle.py +177 -0
- flock/core/agent/flock_agent_serialization.py +381 -0
- flock/core/api/endpoints.py +2 -2
- flock/core/api/service.py +2 -2
- flock/core/component/__init__.py +15 -0
- flock/core/{flock_module.py → component/agent_component_base.py} +136 -34
- flock/core/component/evaluation_component.py +56 -0
- flock/core/component/routing_component.py +74 -0
- flock/core/component/utility_component.py +69 -0
- flock/core/config/flock_agent_config.py +49 -2
- flock/core/evaluation/utils.py +3 -2
- flock/core/execution/batch_executor.py +1 -1
- flock/core/execution/evaluation_executor.py +2 -2
- flock/core/execution/opik_executor.py +1 -1
- flock/core/flock.py +147 -493
- flock/core/flock_agent.py +195 -1032
- flock/core/flock_factory.py +114 -90
- flock/core/flock_scheduler.py +1 -1
- flock/core/flock_server_manager.py +8 -8
- flock/core/logging/logging.py +1 -0
- flock/core/mcp/flock_mcp_server.py +53 -48
- flock/core/mcp/{flock_mcp_tool_base.py → flock_mcp_tool.py} +2 -2
- flock/core/mcp/mcp_client.py +9 -9
- flock/core/mcp/mcp_client_manager.py +9 -9
- flock/core/mcp/mcp_config.py +24 -24
- flock/core/mixin/dspy_integration.py +5 -5
- flock/core/orchestration/__init__.py +18 -0
- flock/core/orchestration/flock_batch_processor.py +94 -0
- flock/core/orchestration/flock_evaluator.py +113 -0
- flock/core/orchestration/flock_execution.py +288 -0
- flock/core/orchestration/flock_initialization.py +125 -0
- flock/core/orchestration/flock_server_manager.py +67 -0
- flock/core/orchestration/flock_web_server.py +117 -0
- flock/core/registry/__init__.py +45 -0
- flock/core/registry/agent_registry.py +69 -0
- flock/core/registry/callable_registry.py +139 -0
- flock/core/registry/component_discovery.py +142 -0
- flock/core/registry/component_registry.py +64 -0
- flock/core/registry/config_mapping.py +64 -0
- flock/core/registry/decorators.py +137 -0
- flock/core/registry/registry_hub.py +205 -0
- flock/core/registry/server_registry.py +57 -0
- flock/core/registry/type_registry.py +86 -0
- flock/core/serialization/flock_serializer.py +36 -32
- flock/core/serialization/serialization_utils.py +28 -25
- flock/core/util/hydrator.py +1 -1
- flock/core/util/input_resolver.py +29 -2
- flock/mcp/servers/sse/flock_sse_server.py +10 -10
- flock/mcp/servers/stdio/flock_stdio_server.py +10 -10
- flock/mcp/servers/streamable_http/flock_streamable_http_server.py +10 -10
- flock/mcp/servers/websockets/flock_websocket_server.py +10 -10
- flock/platform/docker_tools.py +3 -3
- flock/webapp/app/chat.py +1 -1
- flock/webapp/app/main.py +9 -5
- flock/webapp/app/services/flock_service.py +1 -1
- flock/webapp/app/services/sharing_store.py +1 -0
- flock/workflow/activities.py +67 -92
- flock/workflow/agent_execution_activity.py +6 -6
- flock/workflow/flock_workflow.py +1 -1
- flock_core-0.5.0b0.dist-info/METADATA +272 -0
- {flock_core-0.4.528.dist-info → flock_core-0.5.0b0.dist-info}/RECORD +82 -95
- flock/core/flock_evaluator.py +0 -60
- flock/core/flock_registry.py +0 -702
- flock/core/flock_router.py +0 -83
- flock/evaluators/__init__.py +0 -1
- flock/evaluators/declarative/__init__.py +0 -1
- flock/evaluators/declarative/declarative_evaluator.py +0 -217
- flock/evaluators/memory/memory_evaluator.py +0 -90
- flock/evaluators/test/test_case_evaluator.py +0 -38
- flock/evaluators/zep/zep_evaluator.py +0 -59
- flock/modules/__init__.py +0 -1
- flock/modules/assertion/__init__.py +0 -1
- flock/modules/assertion/assertion_module.py +0 -286
- flock/modules/callback/__init__.py +0 -1
- flock/modules/callback/callback_module.py +0 -91
- flock/modules/enterprise_memory/README.md +0 -99
- flock/modules/mem0/__init__.py +0 -1
- flock/modules/mem0/mem0_module.py +0 -126
- flock/modules/mem0_async/__init__.py +0 -1
- flock/modules/mem0_async/async_mem0_module.py +0 -126
- flock/modules/memory/__init__.py +0 -1
- flock/modules/memory/memory_module.py +0 -429
- flock/modules/memory/memory_parser.py +0 -125
- flock/modules/memory/memory_storage.py +0 -736
- flock/modules/output/__init__.py +0 -1
- flock/modules/performance/__init__.py +0 -1
- flock/modules/zep/__init__.py +0 -1
- flock/modules/zep/zep_module.py +0 -192
- flock/routers/__init__.py +0 -1
- flock/routers/agent/__init__.py +0 -1
- flock/routers/agent/agent_router.py +0 -236
- flock/routers/agent/handoff_agent.py +0 -58
- flock/routers/default/__init__.py +0 -1
- flock/routers/default/default_router.py +0 -80
- flock/routers/feedback/feedback_router.py +0 -114
- flock/routers/list_generator/list_generator_router.py +0 -166
- flock/routers/llm/__init__.py +0 -1
- flock/routers/llm/llm_router.py +0 -365
- flock/tools/__init__.py +0 -0
- flock/tools/azure_tools.py +0 -781
- flock/tools/code_tools.py +0 -167
- flock/tools/file_tools.py +0 -149
- flock/tools/github_tools.py +0 -157
- flock/tools/markdown_tools.py +0 -205
- flock/tools/system_tools.py +0 -9
- flock/tools/text_tools.py +0 -810
- flock/tools/web_tools.py +0 -90
- flock/tools/zendesk_tools.py +0 -147
- flock_core-0.4.528.dist-info/METADATA +0 -675
- {flock_core-0.4.528.dist-info → flock_core-0.5.0b0.dist-info}/WHEEL +0 -0
- {flock_core-0.4.528.dist-info → flock_core-0.5.0b0.dist-info}/entry_points.txt +0 -0
- {flock_core-0.4.528.dist-info → flock_core-0.5.0b0.dist-info}/licenses/LICENSE +0 -0
|
@@ -15,11 +15,11 @@ from pydantic import (
|
|
|
15
15
|
Field,
|
|
16
16
|
)
|
|
17
17
|
|
|
18
|
-
from flock.core.
|
|
18
|
+
from flock.core.component.agent_component_base import AgentComponent
|
|
19
19
|
from flock.core.logging.logging import get_logger
|
|
20
|
-
from flock.core.mcp.
|
|
21
|
-
from flock.core.mcp.mcp_client_manager import
|
|
22
|
-
from flock.core.mcp.mcp_config import
|
|
20
|
+
from flock.core.mcp.flock_mcp_tool import FlockMCPTool
|
|
21
|
+
from flock.core.mcp.mcp_client_manager import FlockMCPClientManager
|
|
22
|
+
from flock.core.mcp.mcp_config import FlockMCPConfiguration
|
|
23
23
|
from flock.core.serialization.serializable import Serializable
|
|
24
24
|
from flock.core.serialization.serialization_utils import (
|
|
25
25
|
deserialize_component,
|
|
@@ -28,7 +28,7 @@ from flock.core.serialization.serialization_utils import (
|
|
|
28
28
|
|
|
29
29
|
logger = get_logger("mcp.server")
|
|
30
30
|
tracer = trace.get_tracer(__name__)
|
|
31
|
-
T = TypeVar("T", bound="
|
|
31
|
+
T = TypeVar("T", bound="FlockMCPServer")
|
|
32
32
|
|
|
33
33
|
LoggingLevel = Literal[
|
|
34
34
|
"debug",
|
|
@@ -42,7 +42,7 @@ LoggingLevel = Literal[
|
|
|
42
42
|
]
|
|
43
43
|
|
|
44
44
|
|
|
45
|
-
class
|
|
45
|
+
class FlockMCPServer(BaseModel, Serializable, ABC):
|
|
46
46
|
"""Base class for all Flock MCP Server Types.
|
|
47
47
|
|
|
48
48
|
Servers serve as an abstraction-layer between the underlying MCPClientSession
|
|
@@ -64,7 +64,7 @@ class FlockMCPServerBase(BaseModel, Serializable, ABC):
|
|
|
64
64
|
2. Using FlockMCPServerConfig.with_fields() to create a config class.
|
|
65
65
|
"""
|
|
66
66
|
|
|
67
|
-
config:
|
|
67
|
+
config: FlockMCPConfiguration = Field(
|
|
68
68
|
..., description="Config for clients connecting to the server."
|
|
69
69
|
)
|
|
70
70
|
|
|
@@ -74,15 +74,15 @@ class FlockMCPServerBase(BaseModel, Serializable, ABC):
|
|
|
74
74
|
description="Whether or not this Server has already initialized.",
|
|
75
75
|
)
|
|
76
76
|
|
|
77
|
-
|
|
77
|
+
components: dict[str, AgentComponent] = Field(
|
|
78
78
|
default={},
|
|
79
|
-
description="Dictionary of
|
|
79
|
+
description="Dictionary of unified agent components attached to this Server.",
|
|
80
80
|
)
|
|
81
81
|
|
|
82
82
|
# --- Underlying ConnectionManager ---
|
|
83
83
|
# (Manages a pool of ClientConnections and does the actual talking to the MCP Server)
|
|
84
84
|
# (Excluded from Serialization)
|
|
85
|
-
client_manager:
|
|
85
|
+
client_manager: FlockMCPClientManager | None = Field(
|
|
86
86
|
default=None,
|
|
87
87
|
exclude=True,
|
|
88
88
|
description="Underlying Connection Manager. Handles the actual underlying connections to the server.",
|
|
@@ -98,43 +98,43 @@ class FlockMCPServerBase(BaseModel, Serializable, ABC):
|
|
|
98
98
|
arbitrary_types_allowed=True,
|
|
99
99
|
)
|
|
100
100
|
|
|
101
|
-
def
|
|
102
|
-
"""Add a
|
|
103
|
-
if not
|
|
104
|
-
logger.error("
|
|
101
|
+
def add_component(self, component: AgentComponent) -> None:
|
|
102
|
+
"""Add a unified component to this server."""
|
|
103
|
+
if not component.name:
|
|
104
|
+
logger.error("Component must have a name to be added.")
|
|
105
105
|
return
|
|
106
|
-
if self.
|
|
107
|
-
logger.warning(f"Overwriting existing
|
|
106
|
+
if self.components and component.name in self.components:
|
|
107
|
+
logger.warning(f"Overwriting existing component: {component.name}")
|
|
108
108
|
|
|
109
|
-
self.
|
|
109
|
+
self.components[component.name] = component
|
|
110
110
|
logger.debug(
|
|
111
|
-
f"Added
|
|
111
|
+
f"Added component '{component.name}' to server {self.config.name}"
|
|
112
112
|
)
|
|
113
113
|
return
|
|
114
114
|
|
|
115
|
-
def
|
|
116
|
-
"""Remove a
|
|
117
|
-
if
|
|
118
|
-
del self.
|
|
115
|
+
def remove_component(self, component_name: str) -> None:
|
|
116
|
+
"""Remove a component from this server."""
|
|
117
|
+
if component_name in self.components:
|
|
118
|
+
del self.components[component_name]
|
|
119
119
|
logger.debug(
|
|
120
|
-
f"Removed
|
|
120
|
+
f"Removed component '{component_name}' from server '{self.config.name}'"
|
|
121
121
|
)
|
|
122
122
|
else:
|
|
123
123
|
logger.warning(
|
|
124
|
-
f"
|
|
124
|
+
f"Component '{component_name}' not found on server '{self.config.name}'"
|
|
125
125
|
)
|
|
126
126
|
return
|
|
127
127
|
|
|
128
|
-
def
|
|
129
|
-
"""Get a
|
|
130
|
-
return self.
|
|
128
|
+
def get_component(self, component_name: str) -> AgentComponent | None:
|
|
129
|
+
"""Get a component by name."""
|
|
130
|
+
return self.components.get(component_name)
|
|
131
131
|
|
|
132
|
-
def
|
|
133
|
-
"""Get a list of currently enabled
|
|
134
|
-
return [
|
|
132
|
+
def get_enabled_components(self) -> list[AgentComponent]:
|
|
133
|
+
"""Get a list of currently enabled components attached to this server."""
|
|
134
|
+
return [c for c in self.components.values() if c.config.enabled]
|
|
135
135
|
|
|
136
136
|
@abstractmethod
|
|
137
|
-
async def initialize(self) ->
|
|
137
|
+
async def initialize(self) -> FlockMCPClientManager:
|
|
138
138
|
"""Called when initializing the server."""
|
|
139
139
|
pass
|
|
140
140
|
|
|
@@ -211,7 +211,7 @@ class FlockMCPServerBase(BaseModel, Serializable, ABC):
|
|
|
211
211
|
additional_params=additional_params
|
|
212
212
|
)
|
|
213
213
|
result: list[
|
|
214
|
-
|
|
214
|
+
FlockMCPTool
|
|
215
215
|
] = await self.client_manager.get_tools(
|
|
216
216
|
agent_id=agent_id,
|
|
217
217
|
run_id=run_id,
|
|
@@ -244,7 +244,7 @@ class FlockMCPServerBase(BaseModel, Serializable, ABC):
|
|
|
244
244
|
try:
|
|
245
245
|
if not additional_params:
|
|
246
246
|
additional_params = {}
|
|
247
|
-
for module in self.
|
|
247
|
+
for module in self.get_enabled_components():
|
|
248
248
|
additional_params = await module.on_connect(
|
|
249
249
|
server=self, additional_params=additional_params
|
|
250
250
|
)
|
|
@@ -264,7 +264,7 @@ class FlockMCPServerBase(BaseModel, Serializable, ABC):
|
|
|
264
264
|
with tracer.start_as_current_span("server.pre_init") as span:
|
|
265
265
|
span.set_attribute("server.name", self.config.name)
|
|
266
266
|
try:
|
|
267
|
-
for module in self.
|
|
267
|
+
for module in self.get_enabled_components():
|
|
268
268
|
await module.on_pre_server_init(self)
|
|
269
269
|
except Exception as module_error:
|
|
270
270
|
logger.error(
|
|
@@ -282,7 +282,7 @@ class FlockMCPServerBase(BaseModel, Serializable, ABC):
|
|
|
282
282
|
with tracer.start_as_current_span("server.post_init") as span:
|
|
283
283
|
span.set_attribute("server.name", self.config.name)
|
|
284
284
|
try:
|
|
285
|
-
for module in self.
|
|
285
|
+
for module in self.get_enabled_components():
|
|
286
286
|
await module.on_post_server_init(self)
|
|
287
287
|
except Exception as module_error:
|
|
288
288
|
logger.error(
|
|
@@ -300,7 +300,7 @@ class FlockMCPServerBase(BaseModel, Serializable, ABC):
|
|
|
300
300
|
with tracer.start_as_current_span("server.pre_terminate") as span:
|
|
301
301
|
span.set_attribute("server.name", self.config.name)
|
|
302
302
|
try:
|
|
303
|
-
for module in self.
|
|
303
|
+
for module in self.get_enabled_components():
|
|
304
304
|
await module.on_pre_server_terminate(self)
|
|
305
305
|
except Exception as module_error:
|
|
306
306
|
logger.error(
|
|
@@ -318,7 +318,7 @@ class FlockMCPServerBase(BaseModel, Serializable, ABC):
|
|
|
318
318
|
with tracer.start_as_current_span("server.post_terminate") as span:
|
|
319
319
|
span.set_attribute("server.name", self.config.name)
|
|
320
320
|
try:
|
|
321
|
-
for module in self.
|
|
321
|
+
for module in self.get_enabled_components():
|
|
322
322
|
await module.on_post_server_terminate(server=self)
|
|
323
323
|
except Exception as module_error:
|
|
324
324
|
logger.error(
|
|
@@ -336,7 +336,7 @@ class FlockMCPServerBase(BaseModel, Serializable, ABC):
|
|
|
336
336
|
with tracer.start_as_current_span("server.on_error") as span:
|
|
337
337
|
span.set_attribute("server.name", self.config.name)
|
|
338
338
|
try:
|
|
339
|
-
for module in self.
|
|
339
|
+
for module in self.get_enabled_components():
|
|
340
340
|
await module.on_server_error(server=self, error=error)
|
|
341
341
|
except Exception as module_error:
|
|
342
342
|
logger.error(
|
|
@@ -354,7 +354,7 @@ class FlockMCPServerBase(BaseModel, Serializable, ABC):
|
|
|
354
354
|
with tracer.start_as_current_span("server.pre_mcp_call") as span:
|
|
355
355
|
span.set_attribute("server.name", self.config.name)
|
|
356
356
|
try:
|
|
357
|
-
for module in self.
|
|
357
|
+
for module in self.get_enabled_components():
|
|
358
358
|
await module.on_pre_mcp_call(
|
|
359
359
|
server=self, arguments=arguments
|
|
360
360
|
)
|
|
@@ -374,7 +374,7 @@ class FlockMCPServerBase(BaseModel, Serializable, ABC):
|
|
|
374
374
|
with tracer.start_as_current_span("server.post_mcp_call") as span:
|
|
375
375
|
span.set_attribute("server.name", self.config.name)
|
|
376
376
|
try:
|
|
377
|
-
for module in self.
|
|
377
|
+
for module in self.get_enabled_components():
|
|
378
378
|
await module.on_post_mcp_call(server=self, result=result)
|
|
379
379
|
except Exception as module_error:
|
|
380
380
|
logger.error(
|
|
@@ -385,7 +385,7 @@ class FlockMCPServerBase(BaseModel, Serializable, ABC):
|
|
|
385
385
|
span.record_exception(module_error)
|
|
386
386
|
|
|
387
387
|
# --- Async Methods ---
|
|
388
|
-
async def __aenter__(self) -> "
|
|
388
|
+
async def __aenter__(self) -> "FlockMCPServer":
|
|
389
389
|
"""Enter the asynchronous context for the server."""
|
|
390
390
|
# Spin up the client-manager
|
|
391
391
|
with tracer.start_as_current_span("server.__aenter__") as span:
|
|
@@ -432,9 +432,9 @@ class FlockMCPServerBase(BaseModel, Serializable, ABC):
|
|
|
432
432
|
# --- Serialization Implementation ---
|
|
433
433
|
def to_dict(self, path_type: str = "relative") -> dict[str, Any]:
|
|
434
434
|
"""Convert instance to dictionary representation suitable for serialization."""
|
|
435
|
-
from flock.core.
|
|
435
|
+
from flock.core.registry import get_registry
|
|
436
436
|
|
|
437
|
-
|
|
437
|
+
registry = get_registry()
|
|
438
438
|
|
|
439
439
|
exclude = ["modules", "config"]
|
|
440
440
|
|
|
@@ -498,7 +498,7 @@ class FlockMCPServerBase(BaseModel, Serializable, ABC):
|
|
|
498
498
|
def add_serialized_component(component: Any, field_name: str):
|
|
499
499
|
if component:
|
|
500
500
|
comp_type = type(component)
|
|
501
|
-
type_name =
|
|
501
|
+
type_name = registry.get_component_type_name(
|
|
502
502
|
comp_type
|
|
503
503
|
) # Get registered name
|
|
504
504
|
|
|
@@ -614,16 +614,21 @@ class FlockMCPServerBase(BaseModel, Serializable, ABC):
|
|
|
614
614
|
config_cls = config_field.annotation
|
|
615
615
|
except (AttributeError, KeyError):
|
|
616
616
|
# fallback if Pydantic v1 or missing
|
|
617
|
-
config_cls =
|
|
617
|
+
config_cls = FlockMCPConfiguration
|
|
618
618
|
config_object = config_cls.from_dict(config_data)
|
|
619
619
|
data["config"] = config_object
|
|
620
620
|
|
|
621
621
|
# now construct
|
|
622
|
-
server = real_cls(**{k: v for k, v in data.items() if k
|
|
622
|
+
server = real_cls(**{k: v for k, v in data.items() if k not in ["modules", "components"]})
|
|
623
623
|
|
|
624
|
-
# re-hydrate modules
|
|
624
|
+
# re-hydrate components (both legacy modules and new components)
|
|
625
|
+
for cname, cdata in data.get("components", {}).items():
|
|
626
|
+
server.add_component(deserialize_component(cdata, AgentComponent))
|
|
627
|
+
|
|
628
|
+
# Handle legacy modules for backward compatibility during transition
|
|
625
629
|
for mname, mdata in data.get("modules", {}).items():
|
|
626
|
-
|
|
630
|
+
logger.warning(f"Legacy module '{mname}' found during deserialization - consider migrating to unified components")
|
|
631
|
+
# Skip legacy modules during migration
|
|
627
632
|
|
|
628
633
|
# --- Separate Data ---
|
|
629
634
|
component_configs = {}
|
|
@@ -13,7 +13,7 @@ from flock.core.logging.logging import get_logger
|
|
|
13
13
|
logger = get_logger("mcp.tool")
|
|
14
14
|
tracer = trace.get_tracer(__name__)
|
|
15
15
|
|
|
16
|
-
T = TypeVar("T", bound="
|
|
16
|
+
T = TypeVar("T", bound="FlockMCPTool")
|
|
17
17
|
|
|
18
18
|
TYPE_MAPPING = {
|
|
19
19
|
"string": str,
|
|
@@ -25,7 +25,7 @@ TYPE_MAPPING = {
|
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
|
|
28
|
-
class
|
|
28
|
+
class FlockMCPTool(BaseModel):
|
|
29
29
|
"""Base Class for MCP Tools for Flock."""
|
|
30
30
|
|
|
31
31
|
name: str = Field(..., description="Name of the tool")
|
flock/core/mcp/mcp_client.py
CHANGED
|
@@ -37,8 +37,8 @@ from pydantic import (
|
|
|
37
37
|
)
|
|
38
38
|
|
|
39
39
|
from flock.core.logging.logging import get_logger
|
|
40
|
-
from flock.core.mcp.
|
|
41
|
-
from flock.core.mcp.mcp_config import
|
|
40
|
+
from flock.core.mcp.flock_mcp_tool import FlockMCPTool
|
|
41
|
+
from flock.core.mcp.mcp_config import FlockMCPConfiguration
|
|
42
42
|
from flock.core.mcp.types.factories import (
|
|
43
43
|
default_flock_mcp_list_roots_callback_factory,
|
|
44
44
|
default_flock_mcp_logging_callback_factory,
|
|
@@ -61,7 +61,7 @@ tracer = trace.get_tracer(__name__)
|
|
|
61
61
|
GetSessionIdCallback = Callable[[], str | None]
|
|
62
62
|
|
|
63
63
|
|
|
64
|
-
class
|
|
64
|
+
class FlockMCPClient(BaseModel, ABC):
|
|
65
65
|
"""Wrapper for mcp ClientSession.
|
|
66
66
|
|
|
67
67
|
Class will attempt to re-establish connection if possible.
|
|
@@ -71,7 +71,7 @@ class FlockMCPClientBase(BaseModel, ABC):
|
|
|
71
71
|
"""
|
|
72
72
|
|
|
73
73
|
# --- Properties ---
|
|
74
|
-
config:
|
|
74
|
+
config: FlockMCPConfiguration = Field(
|
|
75
75
|
..., description="The config for this client instance."
|
|
76
76
|
)
|
|
77
77
|
|
|
@@ -225,7 +225,7 @@ class FlockMCPClientBase(BaseModel, ABC):
|
|
|
225
225
|
|
|
226
226
|
def __init__(
|
|
227
227
|
self,
|
|
228
|
-
config:
|
|
228
|
+
config: FlockMCPConfiguration,
|
|
229
229
|
lock: Lock | None = None,
|
|
230
230
|
tool_cache: TTLCache | None = None,
|
|
231
231
|
tool_result_cache: TTLCache | None = None,
|
|
@@ -374,24 +374,24 @@ class FlockMCPClientBase(BaseModel, ABC):
|
|
|
374
374
|
self,
|
|
375
375
|
agent_id: str,
|
|
376
376
|
run_id: str,
|
|
377
|
-
) -> list[
|
|
377
|
+
) -> list[FlockMCPTool]:
|
|
378
378
|
"""Gets a list of available tools from the server."""
|
|
379
379
|
|
|
380
380
|
@cached(cache=self.tool_cache, key=cache_key_generator)
|
|
381
381
|
async def _get_tools_cached(
|
|
382
382
|
agent_id: str,
|
|
383
383
|
run_id: str,
|
|
384
|
-
) -> list[
|
|
384
|
+
) -> list[FlockMCPTool]:
|
|
385
385
|
if not self.config.feature_config.tools_enabled:
|
|
386
386
|
return []
|
|
387
387
|
|
|
388
|
-
async def _get_tools_internal() -> list[
|
|
388
|
+
async def _get_tools_internal() -> list[FlockMCPTool]:
|
|
389
389
|
# TODO: Crash
|
|
390
390
|
response: ListToolsResult = await self.session.list_tools()
|
|
391
391
|
flock_tools = []
|
|
392
392
|
|
|
393
393
|
for tool in response.tools:
|
|
394
|
-
converted_tool =
|
|
394
|
+
converted_tool = FlockMCPTool.from_mcp_tool(
|
|
395
395
|
tool,
|
|
396
396
|
agent_id=agent_id,
|
|
397
397
|
run_id=run_id,
|
|
@@ -13,22 +13,22 @@ from pydantic import (
|
|
|
13
13
|
)
|
|
14
14
|
|
|
15
15
|
from flock.core.logging.logging import get_logger
|
|
16
|
-
from flock.core.mcp.
|
|
16
|
+
from flock.core.mcp.flock_mcp_tool import FlockMCPTool
|
|
17
17
|
from flock.core.mcp.mcp_client import (
|
|
18
|
-
|
|
18
|
+
FlockMCPClient,
|
|
19
19
|
)
|
|
20
|
-
from flock.core.mcp.mcp_config import
|
|
20
|
+
from flock.core.mcp.mcp_config import FlockMCPConfiguration
|
|
21
21
|
|
|
22
22
|
logger = get_logger("mcp.client_manager")
|
|
23
23
|
tracer = trace.get_tracer(__name__)
|
|
24
24
|
|
|
25
|
-
TClient = TypeVar("TClient", bound="
|
|
25
|
+
TClient = TypeVar("TClient", bound="FlockMCPClient")
|
|
26
26
|
|
|
27
27
|
|
|
28
|
-
class
|
|
28
|
+
class FlockMCPClientManager(BaseModel, ABC, Generic[TClient]):
|
|
29
29
|
"""Handles a Pool of MCPClients of type TClient."""
|
|
30
30
|
|
|
31
|
-
client_config:
|
|
31
|
+
client_config: FlockMCPConfiguration = Field(
|
|
32
32
|
..., description="Configuration for clients."
|
|
33
33
|
)
|
|
34
34
|
|
|
@@ -38,7 +38,7 @@ class FlockMCPClientManagerBase(BaseModel, ABC, Generic[TClient]):
|
|
|
38
38
|
exclude=True,
|
|
39
39
|
)
|
|
40
40
|
|
|
41
|
-
clients: dict[str, dict[str,
|
|
41
|
+
clients: dict[str, dict[str, FlockMCPClient]] = Field(
|
|
42
42
|
default_factory=dict,
|
|
43
43
|
exclude=True,
|
|
44
44
|
description="Internal Store for the clients.",
|
|
@@ -154,7 +154,7 @@ class FlockMCPClientManagerBase(BaseModel, ABC, Generic[TClient]):
|
|
|
154
154
|
agent_id: str,
|
|
155
155
|
run_id: str,
|
|
156
156
|
additional_params: dict[str, Any] | None = None,
|
|
157
|
-
) -> list[
|
|
157
|
+
) -> list[FlockMCPTool]:
|
|
158
158
|
"""Retrieves a list of tools for the agents to act on."""
|
|
159
159
|
with tracer.start_as_current_span("client_manager.get_tools") as span:
|
|
160
160
|
span.set_attribute("agent_id", agent_id)
|
|
@@ -165,7 +165,7 @@ class FlockMCPClientManagerBase(BaseModel, ABC, Generic[TClient]):
|
|
|
165
165
|
run_id=run_id,
|
|
166
166
|
additional_params=additional_params,
|
|
167
167
|
)
|
|
168
|
-
tools: list[
|
|
168
|
+
tools: list[FlockMCPTool] = await client.get_tools(
|
|
169
169
|
agent_id=agent_id, run_id=run_id
|
|
170
170
|
)
|
|
171
171
|
return tools
|
flock/core/mcp/mcp_config.py
CHANGED
|
@@ -36,14 +36,14 @@ LoggingLevel = Literal[
|
|
|
36
36
|
]
|
|
37
37
|
|
|
38
38
|
|
|
39
|
-
A = TypeVar("A", bound="
|
|
40
|
-
B = TypeVar("B", bound="
|
|
41
|
-
C = TypeVar("C", bound="
|
|
42
|
-
D = TypeVar("D", bound="
|
|
43
|
-
E = TypeVar("E", bound="
|
|
39
|
+
A = TypeVar("A", bound="FlockMCPCallbackConfiguration")
|
|
40
|
+
B = TypeVar("B", bound="FlockMCPConnectionConfiguration")
|
|
41
|
+
C = TypeVar("C", bound="FlockMCPConfiguration")
|
|
42
|
+
D = TypeVar("D", bound="FlockMCPCachingConfiguration")
|
|
43
|
+
E = TypeVar("E", bound="FlockMCPFeatureConfiguration")
|
|
44
44
|
|
|
45
45
|
|
|
46
|
-
class
|
|
46
|
+
class FlockMCPCachingConfiguration(BaseModel, Serializable):
|
|
47
47
|
"""Configuration for Caching in Clients."""
|
|
48
48
|
|
|
49
49
|
tool_cache_max_size: float = Field(
|
|
@@ -110,7 +110,7 @@ class FlockMCPCachingConfigurationBase(BaseModel, Serializable):
|
|
|
110
110
|
)
|
|
111
111
|
|
|
112
112
|
|
|
113
|
-
class
|
|
113
|
+
class FlockMCPCallbackConfiguration(BaseModel, Serializable):
|
|
114
114
|
"""Base Configuration Class for Callbacks for Clients."""
|
|
115
115
|
|
|
116
116
|
sampling_callback: FlockSamplingMCPCallback | None = Field(
|
|
@@ -188,7 +188,7 @@ class FlockMCPCallbackConfigurationBase(BaseModel, Serializable):
|
|
|
188
188
|
)
|
|
189
189
|
|
|
190
190
|
|
|
191
|
-
class
|
|
191
|
+
class FlockMCPConnectionConfiguration(BaseModel, Serializable):
|
|
192
192
|
"""Base Configuration Class for Connection Parameters for a client."""
|
|
193
193
|
|
|
194
194
|
max_retries: int = Field(
|
|
@@ -298,7 +298,7 @@ class FlockMCPConnectionConfigurationBase(BaseModel, Serializable):
|
|
|
298
298
|
)
|
|
299
299
|
|
|
300
300
|
|
|
301
|
-
class
|
|
301
|
+
class FlockMCPFeatureConfiguration(BaseModel, Serializable):
|
|
302
302
|
"""Base Configuration Class for switching MCP Features on and off."""
|
|
303
303
|
|
|
304
304
|
roots_enabled: bool = Field(
|
|
@@ -346,7 +346,7 @@ class FlockMCPFeatureConfigurationBase(BaseModel, Serializable):
|
|
|
346
346
|
)
|
|
347
347
|
|
|
348
348
|
|
|
349
|
-
class
|
|
349
|
+
class FlockMCPConfiguration(BaseModel, Serializable):
|
|
350
350
|
"""Base Configuration Class for MCP Clients.
|
|
351
351
|
|
|
352
352
|
Each Client should implement their own config
|
|
@@ -357,22 +357,22 @@ class FlockMCPConfigurationBase(BaseModel, Serializable):
|
|
|
357
357
|
..., description="Name of the server the client connects to."
|
|
358
358
|
)
|
|
359
359
|
|
|
360
|
-
connection_config:
|
|
360
|
+
connection_config: FlockMCPConnectionConfiguration = Field(
|
|
361
361
|
..., description="MCP Connection Configuration for a client."
|
|
362
362
|
)
|
|
363
363
|
|
|
364
|
-
caching_config:
|
|
365
|
-
default_factory=
|
|
364
|
+
caching_config: FlockMCPCachingConfiguration = Field(
|
|
365
|
+
default_factory=FlockMCPCachingConfiguration,
|
|
366
366
|
description="Configuration for the internal caches of the client.",
|
|
367
367
|
)
|
|
368
368
|
|
|
369
|
-
callback_config:
|
|
370
|
-
default_factory=
|
|
369
|
+
callback_config: FlockMCPCallbackConfiguration = Field(
|
|
370
|
+
default_factory=FlockMCPCallbackConfiguration,
|
|
371
371
|
description="Callback configuration for the client.",
|
|
372
372
|
)
|
|
373
373
|
|
|
374
|
-
feature_config:
|
|
375
|
-
default_factory=
|
|
374
|
+
feature_config: FlockMCPFeatureConfiguration = Field(
|
|
375
|
+
default_factory=FlockMCPFeatureConfiguration,
|
|
376
376
|
description="Feature configuration for the client.",
|
|
377
377
|
)
|
|
378
378
|
|
|
@@ -425,7 +425,7 @@ class FlockMCPConfigurationBase(BaseModel, Serializable):
|
|
|
425
425
|
config_cls = config_field.annotation
|
|
426
426
|
except (AttributeError, KeyError):
|
|
427
427
|
# fallback
|
|
428
|
-
config_cls =
|
|
428
|
+
config_cls = FlockMCPConnectionConfiguration
|
|
429
429
|
instance_data["connection_config"] = config_cls.from_dict(connection_config)
|
|
430
430
|
else:
|
|
431
431
|
raise ValueError(f"connection_config MUST be specified for '{data.get('name', 'unknown_server')}")
|
|
@@ -436,10 +436,10 @@ class FlockMCPConfigurationBase(BaseModel, Serializable):
|
|
|
436
436
|
config_cls = config_field.annotation
|
|
437
437
|
except (AttributeError, KeyError):
|
|
438
438
|
# fallback
|
|
439
|
-
config_cls =
|
|
439
|
+
config_cls = FlockMCPCachingConfiguration
|
|
440
440
|
instance_data["caching_config"] = config_cls.from_dict(caching_config)
|
|
441
441
|
else:
|
|
442
|
-
instance_data["caching_config"] =
|
|
442
|
+
instance_data["caching_config"] = FlockMCPCachingConfiguration()
|
|
443
443
|
|
|
444
444
|
if feature_config:
|
|
445
445
|
try:
|
|
@@ -447,10 +447,10 @@ class FlockMCPConfigurationBase(BaseModel, Serializable):
|
|
|
447
447
|
config_cls = config_field.annotation
|
|
448
448
|
except (AttributeError, KeyError):
|
|
449
449
|
# fallback
|
|
450
|
-
config_cls =
|
|
450
|
+
config_cls = FlockMCPFeatureConfiguration
|
|
451
451
|
instance_data["feature_config"] = config_cls.from_dict(feature_config)
|
|
452
452
|
else:
|
|
453
|
-
instance_data["feature_config"] =
|
|
453
|
+
instance_data["feature_config"] = FlockMCPFeatureConfiguration()
|
|
454
454
|
|
|
455
455
|
if callback_config:
|
|
456
456
|
try:
|
|
@@ -458,10 +458,10 @@ class FlockMCPConfigurationBase(BaseModel, Serializable):
|
|
|
458
458
|
config_cls = config_field.annotation
|
|
459
459
|
except (AttributeError, KeyError):
|
|
460
460
|
# fallback
|
|
461
|
-
config_cls =
|
|
461
|
+
config_cls = FlockMCPCallbackConfiguration
|
|
462
462
|
instance_data["callback_config"] = config_cls.from_dict(callback_config)
|
|
463
463
|
else:
|
|
464
|
-
instance_data["callback_config"] =
|
|
464
|
+
instance_data["callback_config"] = FlockMCPCallbackConfiguration()
|
|
465
465
|
|
|
466
466
|
return cls(**{k: v for k, v in instance_data.items()})
|
|
467
467
|
|
|
@@ -30,9 +30,9 @@ def _resolve_type_string(type_str: str) -> type:
|
|
|
30
30
|
List, Dict, Optional, Union, Literal.
|
|
31
31
|
"""
|
|
32
32
|
# Import registry here to avoid circular imports
|
|
33
|
-
from flock.core.
|
|
33
|
+
from flock.core.registry import get_registry
|
|
34
34
|
|
|
35
|
-
|
|
35
|
+
registry = get_registry()
|
|
36
36
|
|
|
37
37
|
type_str = type_str.strip()
|
|
38
38
|
logger.debug(f"Attempting to resolve type string: '{type_str}'")
|
|
@@ -40,7 +40,7 @@ def _resolve_type_string(type_str: str) -> type:
|
|
|
40
40
|
# 1. Check built-ins and registered types directly
|
|
41
41
|
try:
|
|
42
42
|
# This covers str, int, bool, Any, and types registered by name
|
|
43
|
-
resolved_type =
|
|
43
|
+
resolved_type = registry.get_type(type_str)
|
|
44
44
|
logger.debug(f"Resolved '{type_str}' via registry to: {resolved_type}")
|
|
45
45
|
return resolved_type
|
|
46
46
|
except KeyError:
|
|
@@ -61,7 +61,7 @@ def _resolve_type_string(type_str: str) -> type:
|
|
|
61
61
|
|
|
62
62
|
try:
|
|
63
63
|
# Get the base generic type (e.g., list, dict, Optional) from registry/builtins
|
|
64
|
-
BaseType =
|
|
64
|
+
BaseType = registry.get_type(
|
|
65
65
|
base_name
|
|
66
66
|
) # Expects List, Dict etc. to be registered
|
|
67
67
|
logger.debug(
|
|
@@ -149,7 +149,7 @@ class DSPyIntegrationMixin:
|
|
|
149
149
|
self, agent_name, description_spec, fields_spec
|
|
150
150
|
) -> Any:
|
|
151
151
|
"""Creates a dynamic DSPy Signature class from string specifications,
|
|
152
|
-
resolving types using the
|
|
152
|
+
resolving types using the registry.
|
|
153
153
|
"""
|
|
154
154
|
try:
|
|
155
155
|
import dspy
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# src/flock/core/orchestration/__init__.py
|
|
2
|
+
"""Orchestration components for Flock."""
|
|
3
|
+
|
|
4
|
+
from .flock_batch_processor import FlockBatchProcessor
|
|
5
|
+
from .flock_evaluator import FlockEvaluator
|
|
6
|
+
from .flock_execution import FlockExecution
|
|
7
|
+
from .flock_initialization import FlockInitialization
|
|
8
|
+
from .flock_server_manager import FlockServerManager
|
|
9
|
+
from .flock_web_server import FlockWebServer
|
|
10
|
+
|
|
11
|
+
__all__ = [
|
|
12
|
+
"FlockExecution",
|
|
13
|
+
"FlockServerManager",
|
|
14
|
+
"FlockBatchProcessor",
|
|
15
|
+
"FlockEvaluator",
|
|
16
|
+
"FlockWebServer",
|
|
17
|
+
"FlockInitialization",
|
|
18
|
+
]
|