flock-core 0.5.0b2__py3-none-any.whl → 0.5.0b5__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.

Files changed (55) hide show
  1. flock/cli/execute_flock.py +1 -1
  2. flock/cli/manage_agents.py +3 -3
  3. flock/components/evaluation/declarative_evaluation_component.py +10 -10
  4. flock/components/routing/conditional_routing_component.py +7 -6
  5. flock/components/routing/default_routing_component.py +3 -3
  6. flock/components/routing/llm_routing_component.py +24 -26
  7. flock/components/utility/memory_utility_component.py +3 -3
  8. flock/components/utility/metrics_utility_component.py +11 -11
  9. flock/components/utility/output_utility_component.py +11 -9
  10. flock/core/__init__.py +24 -10
  11. flock/core/agent/flock_agent_components.py +16 -16
  12. flock/core/agent/flock_agent_integration.py +88 -29
  13. flock/core/agent/flock_agent_serialization.py +23 -20
  14. flock/core/api/endpoints.py +2 -2
  15. flock/core/api/service.py +2 -2
  16. flock/core/component/__init__.py +7 -7
  17. flock/core/component/{evaluation_component_base.py → evaluation_component.py} +2 -2
  18. flock/core/component/{routing_component_base.py → routing_component.py} +3 -4
  19. flock/core/component/{utility_component_base.py → utility_component.py} +3 -3
  20. flock/core/evaluation/utils.py +2 -1
  21. flock/core/execution/batch_executor.py +1 -1
  22. flock/core/execution/evaluation_executor.py +1 -1
  23. flock/core/execution/opik_executor.py +1 -1
  24. flock/core/flock.py +12 -12
  25. flock/core/flock_agent.py +68 -38
  26. flock/core/flock_factory.py +21 -18
  27. flock/core/flock_scheduler.py +1 -1
  28. flock/core/flock_server_manager.py +8 -8
  29. flock/core/mcp/flock_mcp_server.py +11 -11
  30. flock/core/mcp/{flock_mcp_tool_base.py → flock_mcp_tool.py} +2 -2
  31. flock/core/mcp/mcp_client.py +9 -9
  32. flock/core/mcp/mcp_client_manager.py +9 -9
  33. flock/core/mcp/mcp_config.py +24 -24
  34. flock/core/orchestration/flock_execution.py +13 -13
  35. flock/core/orchestration/flock_initialization.py +6 -6
  36. flock/core/orchestration/flock_server_manager.py +8 -6
  37. flock/core/registry/__init__.py +16 -10
  38. flock/core/registry/registry_hub.py +7 -4
  39. flock/core/registry/server_registry.py +6 -6
  40. flock/core/serialization/flock_serializer.py +3 -2
  41. flock/core/util/hydrator.py +1 -1
  42. flock/mcp/servers/sse/flock_sse_server.py +10 -10
  43. flock/mcp/servers/stdio/flock_stdio_server.py +10 -10
  44. flock/mcp/servers/streamable_http/flock_streamable_http_server.py +10 -10
  45. flock/mcp/servers/websockets/flock_websocket_server.py +10 -10
  46. flock/webapp/app/chat.py +1 -1
  47. flock/webapp/app/services/flock_service.py +1 -1
  48. flock/workflow/activities.py +10 -10
  49. {flock_core-0.5.0b2.dist-info → flock_core-0.5.0b5.dist-info}/METADATA +1 -1
  50. {flock_core-0.5.0b2.dist-info → flock_core-0.5.0b5.dist-info}/RECORD +53 -55
  51. flock/core/flock_registry.py.backup +0 -688
  52. flock/workflow/activities_unified.py +0 -230
  53. {flock_core-0.5.0b2.dist-info → flock_core-0.5.0b5.dist-info}/WHEEL +0 -0
  54. {flock_core-0.5.0b2.dist-info → flock_core-0.5.0b5.dist-info}/entry_points.txt +0 -0
  55. {flock_core-0.5.0b2.dist-info → flock_core-0.5.0b5.dist-info}/licenses/LICENSE +0 -0
@@ -142,7 +142,7 @@ def execute_flock(flock: Flock):
142
142
 
143
143
  # Run the Flock
144
144
  result = flock.run(
145
- start_agent=start_agent_name,
145
+ agent=start_agent_name,
146
146
  input=input_data,
147
147
  )
148
148
 
@@ -105,7 +105,7 @@ def _list_agents(flock: Flock):
105
105
  model = agent.model or flock.model or "Default"
106
106
 
107
107
  # Format description (truncate if too long)
108
- description = agent.resolved_description
108
+ description = agent.description
109
109
  if description and len(description) > 30:
110
110
  description = description[:27] + "..."
111
111
  elif not description:
@@ -165,7 +165,7 @@ def _view_agent_details(agent: FlockAgent):
165
165
 
166
166
  basic_info.add_row("Name", agent.name)
167
167
  basic_info.add_row("Model", str(agent.model or "Default"))
168
- basic_info.add_row("Description", agent.resolved_description if agent.resolved_description else "N/A")
168
+ basic_info.add_row("Description", agent.description if agent.description else "N/A")
169
169
  basic_info.add_row("Input", str(agent.input))
170
170
  basic_info.add_row("Output", str(agent.output))
171
171
  basic_info.add_row("Write to File", str(agent.config.write_to_file))
@@ -339,7 +339,7 @@ def _edit_agent(flock: Flock):
339
339
  console.print(f"\n[bold underline]Details for Agent: {agent.name}[/]")
340
340
  basic_info = Table(show_header=False, box=Box.ROUNDED, padding=(0, 2))
341
341
  basic_info.add_row("Name", agent.name)
342
- description = agent.resolved_description
342
+ description = agent.description
343
343
  basic_info.add_row("Description", description if description else "N/A")
344
344
  basic_info.add_row("Model", agent.model or "Flock Default")
345
345
  basic_info.add_row("Input Signature", str(agent.input))
@@ -12,12 +12,12 @@ with workflow.unsafe.imports_passed_through():
12
12
  from pydantic import Field, PrivateAttr
13
13
 
14
14
  from flock.core.component.agent_component_base import AgentComponentConfig
15
- from flock.core.component.evaluation_component_base import EvaluationComponentBase
15
+ from flock.core.component.evaluation_component import EvaluationComponent
16
16
  from flock.core.context.context import FlockContext
17
- from flock.core.registry import flock_component
18
17
  from flock.core.logging.logging import get_logger
19
18
  from flock.core.mixin.dspy_integration import DSPyIntegrationMixin
20
19
  from flock.core.mixin.prompt_parser import PromptParserMixin
20
+ from flock.core.registry import flock_component
21
21
 
22
22
  logger = get_logger("components.evaluation.declarative")
23
23
 
@@ -45,7 +45,7 @@ class DeclarativeEvaluationConfig(AgentComponentConfig):
45
45
 
46
46
  @flock_component(config_class=DeclarativeEvaluationConfig)
47
47
  class DeclarativeEvaluationComponent(
48
- EvaluationComponentBase, DSPyIntegrationMixin, PromptParserMixin
48
+ EvaluationComponent, DSPyIntegrationMixin, PromptParserMixin
49
49
  ):
50
50
  """Evaluation component that uses DSPy for generation.
51
51
 
@@ -58,7 +58,7 @@ class DeclarativeEvaluationComponent(
58
58
  default_factory=DeclarativeEvaluationConfig,
59
59
  description="Evaluation configuration",
60
60
  )
61
-
61
+
62
62
  _cost: float = PrivateAttr(default=0.0)
63
63
  _lm_history: list = PrivateAttr(default_factory=list)
64
64
 
@@ -75,7 +75,7 @@ class DeclarativeEvaluationComponent(
75
75
  ) -> dict[str, Any]:
76
76
  """Core evaluation logic using DSPy - migrated from DeclarativeEvaluator."""
77
77
  logger.debug(f"Starting declarative evaluation for component '{self.name}'")
78
-
78
+
79
79
  # Setup DSPy context with LM (directly from original implementation)
80
80
  with dspy.context(
81
81
  lm=dspy.LM(
@@ -89,14 +89,14 @@ class DeclarativeEvaluationComponent(
89
89
  try:
90
90
  from rich.console import Console
91
91
  console = Console()
92
-
92
+
93
93
  # Create DSPy signature from agent definition
94
94
  _dspy_signature = self.create_dspy_signature_class(
95
95
  agent.name,
96
96
  agent.description,
97
97
  f"{agent.input} -> {agent.output}",
98
98
  )
99
-
99
+
100
100
  # Get output field names for streaming
101
101
  output_field_names = list(_dspy_signature.output_fields.keys())
102
102
  if not output_field_names:
@@ -113,7 +113,7 @@ class DeclarativeEvaluationComponent(
113
113
  mcp_tools=mcp_tools or [],
114
114
  kwargs=self.config.kwargs,
115
115
  )
116
-
116
+
117
117
  except Exception as setup_error:
118
118
  logger.error(
119
119
  f"Error setting up DSPy task for agent '{agent.name}': {setup_error}",
@@ -132,7 +132,7 @@ class DeclarativeEvaluationComponent(
132
132
  async def _execute_streaming(self, agent_task, inputs: dict[str, Any], agent: Any, console) -> dict[str, Any]:
133
133
  """Execute DSPy program in streaming mode (from original implementation)."""
134
134
  logger.info(f"Evaluating agent '{agent.name}' with async streaming.")
135
-
135
+
136
136
  if not callable(agent_task):
137
137
  logger.error("agent_task is not callable, cannot stream.")
138
138
  raise TypeError("DSPy task could not be created or is not callable.")
@@ -167,7 +167,7 @@ class DeclarativeEvaluationComponent(
167
167
  async def _execute_standard(self, agent_task, inputs: dict[str, Any], agent: Any) -> dict[str, Any]:
168
168
  """Execute DSPy program in standard mode (from original implementation)."""
169
169
  logger.info(f"Evaluating agent '{agent.name}' without streaming.")
170
-
170
+
171
171
  try:
172
172
  # Ensure the call is awaited if the underlying task is async
173
173
  result_obj = await agent_task.acall(**inputs)
@@ -8,11 +8,12 @@ from typing import TYPE_CHECKING, Any, Literal
8
8
  from pydantic import Field, model_validator
9
9
 
10
10
  from flock.core.component.agent_component_base import AgentComponentConfig
11
- from flock.core.component.routing_component_base import RoutingComponentBase
11
+ from flock.core.component.routing_component import RoutingComponent
12
12
  from flock.core.context.context import FlockContext
13
- from flock.core.registry import flock_component, get_registry
13
+
14
14
  # HandOffRequest removed - using agent.next_agent directly
15
15
  from flock.core.logging.logging import get_logger
16
+ from flock.core.registry import flock_component, get_registry
16
17
 
17
18
  if TYPE_CHECKING:
18
19
  from flock.core.flock_agent import FlockAgent
@@ -148,7 +149,7 @@ class ConditionalRoutingConfig(AgentComponentConfig):
148
149
 
149
150
 
150
151
  @flock_component(config_class=ConditionalRoutingConfig)
151
- class ConditionalRoutingComponent(RoutingComponentBase):
152
+ class ConditionalRoutingComponent(RoutingComponent):
152
153
  """Routes workflow based on evaluating a condition against a value in the FlockContext.
153
154
 
154
155
  Supports various built-in checks (string, number, list, type, bool, existence)
@@ -436,7 +437,7 @@ class ConditionalRoutingComponent(RoutingComponentBase):
436
437
 
437
438
  next_agent = cfg.success_agent or None # Stop chain if None
438
439
  logger.debug(f"Success route target: '{next_agent}'")
439
-
440
+
440
441
  agent.next_agent = next_agent # Set directly on agent
441
442
 
442
443
  else:
@@ -481,7 +482,7 @@ class ConditionalRoutingComponent(RoutingComponentBase):
481
482
  logger.debug(
482
483
  f"Failure route target (after retries): '{next_agent}'"
483
484
  )
484
-
485
+
485
486
  agent.next_agent = next_agent
486
487
  else:
487
488
  # --- No Retry Logic ---
@@ -489,5 +490,5 @@ class ConditionalRoutingComponent(RoutingComponentBase):
489
490
  cfg.failure_agent or None
490
491
  ) # Use failure agent or stop
491
492
  logger.debug(f"Failure route target (no retry): '{next_agent}'")
492
-
493
+
493
494
  agent.next_agent = next_agent
@@ -7,10 +7,10 @@ from typing import TYPE_CHECKING, Any
7
7
  from pydantic import Field
8
8
 
9
9
  from flock.core.component.agent_component_base import AgentComponentConfig
10
- from flock.core.component.routing_component_base import RoutingComponentBase
10
+ from flock.core.component.routing_component import RoutingComponent
11
11
  from flock.core.context.context import FlockContext
12
- from flock.core.registry import flock_component
13
12
  from flock.core.logging.logging import get_logger
13
+ from flock.core.registry import flock_component
14
14
 
15
15
  if TYPE_CHECKING:
16
16
  from flock.core.flock_agent import FlockAgent
@@ -27,7 +27,7 @@ class DefaultRoutingConfig(AgentComponentConfig):
27
27
 
28
28
 
29
29
  @flock_component(config_class=DefaultRoutingConfig)
30
- class DefaultRoutingComponent(RoutingComponentBase):
30
+ class DefaultRoutingComponent(RoutingComponent):
31
31
  """Default routing component implementation.
32
32
 
33
33
  This router simply uses the configured hand_off property to determine the next agent.
@@ -8,11 +8,12 @@ import litellm
8
8
  from pydantic import Field
9
9
 
10
10
  from flock.core.component.agent_component_base import AgentComponentConfig
11
- from flock.core.component.routing_component_base import RoutingComponentBase
11
+ from flock.core.component.routing_component import RoutingComponent
12
12
  from flock.core.context.context import FlockContext
13
- from flock.core.registry import flock_component
13
+
14
14
  # HandOffRequest removed - using agent.next_agent directly
15
15
  from flock.core.logging.logging import get_logger
16
+ from flock.core.registry import flock_component
16
17
 
17
18
  if TYPE_CHECKING:
18
19
  from flock.core.flock_agent import FlockAgent
@@ -53,7 +54,7 @@ If no agent is suitable, use "next_agent": "" to end the workflow.""",
53
54
 
54
55
 
55
56
  @flock_component(config_class=LLMRoutingConfig)
56
- class LLMRoutingComponent(RoutingComponentBase):
57
+ class LLMRoutingComponent(RoutingComponent):
57
58
  """Router that uses an LLM to determine the next agent in a workflow.
58
59
 
59
60
  This component analyzes the current agent's output and uses an LLM to
@@ -79,7 +80,7 @@ class LLMRoutingComponent(RoutingComponentBase):
79
80
  ) -> list[str]:
80
81
  """Get list of available agent names except the current one."""
81
82
  available = []
82
- for agent_name in agent_definitions.keys():
83
+ for agent_name in agent_definitions:
83
84
  if agent_name != current_agent_name:
84
85
  available.append(agent_name)
85
86
  return available
@@ -91,17 +92,16 @@ class LLMRoutingComponent(RoutingComponentBase):
91
92
  available_agents: list[str],
92
93
  ) -> str:
93
94
  """Create the prompt for LLM agent selection."""
94
-
95
95
  # Format available agents
96
96
  agents_list = []
97
97
  for agent_name in available_agents:
98
98
  agents_list.append(f"- {agent_name}")
99
-
99
+
100
100
  available_agents_str = "\n".join(agents_list) if agents_list else "None available"
101
-
102
- # Format current output
101
+
102
+ # Format current output
103
103
  current_output = json.dumps(result, indent=2) if result else "No output"
104
-
104
+
105
105
  return self.config.prompt_template.format(
106
106
  current_agent_name=current_agent.name,
107
107
  current_output=current_output,
@@ -115,14 +115,13 @@ class LLMRoutingComponent(RoutingComponentBase):
115
115
  available_agents: list[str],
116
116
  ) -> tuple[str, float]:
117
117
  """Use an LLM to select the best next agent."""
118
-
119
118
  if not available_agents:
120
119
  logger.warning("No available agents for LLM routing")
121
120
  return "", 0.0
122
121
 
123
122
  # Create the selection prompt
124
123
  prompt = self._create_selection_prompt(current_agent, result, available_agents)
125
-
124
+
126
125
  try:
127
126
  # Call the LLM
128
127
  response = await litellm.acompletion(
@@ -133,30 +132,30 @@ class LLMRoutingComponent(RoutingComponentBase):
133
132
  temperature=self.config.temperature,
134
133
  max_tokens=self.config.max_tokens,
135
134
  )
136
-
135
+
137
136
  response_content = response.choices[0].message.content.strip()
138
137
  logger.debug(f"LLM routing response: {response_content}")
139
-
138
+
140
139
  # Parse the JSON response
141
140
  try:
142
141
  routing_decision = json.loads(response_content)
143
142
  next_agent = routing_decision.get("next_agent", "")
144
143
  confidence = routing_decision.get("confidence", 0.0)
145
144
  reasoning = routing_decision.get("reasoning", "No reasoning provided")
146
-
145
+
147
146
  logger.info(f"LLM routing decision: {next_agent} (confidence: {confidence}) - {reasoning}")
148
-
147
+
149
148
  # Validate the selected agent is available
150
149
  if next_agent and next_agent not in available_agents and next_agent != "":
151
150
  logger.warning(f"LLM selected unavailable agent '{next_agent}', ending workflow")
152
151
  return "", 0.0
153
-
152
+
154
153
  return next_agent, confidence
155
-
154
+
156
155
  except json.JSONDecodeError as e:
157
156
  logger.error(f"Failed to parse LLM response as JSON: {e}")
158
157
  return "", 0.0
159
-
158
+
160
159
  except Exception as e:
161
160
  logger.error(f"Error calling LLM for routing: {e}")
162
161
  return "", 0.0
@@ -168,19 +167,18 @@ class LLMRoutingComponent(RoutingComponentBase):
168
167
  context: FlockContext | None = None,
169
168
  ) -> None:
170
169
  """Use LLM to determine the next agent based on current output."""
171
-
172
170
  if not context:
173
171
  logger.warning("No context provided for LLM routing")
174
172
  return
175
173
 
176
174
  logger.info(f"LLM routing from agent '{agent.name}'")
177
-
175
+
178
176
  # Get available agents from context
179
177
  agent_definitions = getattr(context, 'agent_definitions', {})
180
178
  available_agents = self._get_available_agents(agent_definitions, agent.name)
181
-
179
+
182
180
  logger.debug(f"Available agents for LLM routing: {available_agents}")
183
-
181
+
184
182
  if not available_agents:
185
183
  logger.warning("No available agents for LLM routing")
186
184
  return
@@ -189,20 +187,20 @@ class LLMRoutingComponent(RoutingComponentBase):
189
187
  next_agent_name, confidence = await self._select_next_agent(
190
188
  agent, result, available_agents
191
189
  )
192
-
190
+
193
191
  logger.info(f"LLM routing result: {next_agent_name} (confidence: {confidence})")
194
-
192
+
195
193
  # Check confidence threshold
196
194
  if not next_agent_name or confidence < self.config.confidence_threshold:
197
195
  logger.warning(
198
196
  f"LLM routing confidence {confidence} below threshold {self.config.confidence_threshold}"
199
197
  )
200
198
  return
201
-
199
+
202
200
  # Validate the selected agent exists
203
201
  if next_agent_name not in agent_definitions:
204
202
  logger.error(f"LLM selected non-existent agent '{next_agent_name}'")
205
203
  return
206
-
204
+
207
205
  logger.info(f"Successfully routed to agent '{next_agent_name}' with confidence {confidence}")
208
206
  agent.next_agent = next_agent_name
@@ -30,10 +30,10 @@ from flock.adapter.faiss_adapter import FAISSAdapter
30
30
  from flock.adapter.pinecone_adapter import PineconeAdapter
31
31
  from flock.adapter.vector_base import VectorAdapter
32
32
  from flock.core.component.agent_component_base import AgentComponentConfig
33
- from flock.core.component.utility_component_base import UtilityComponentBase
33
+ from flock.core.component.utility_component import UtilityComponent
34
34
  from flock.core.context.context import FlockContext
35
- from flock.core.registry import flock_component
36
35
  from flock.core.logging.logging import get_logger
36
+ from flock.core.registry import flock_component
37
37
 
38
38
  # Conditional import for MetricsUtilityComponent to avoid circular imports
39
39
  if TYPE_CHECKING:
@@ -423,7 +423,7 @@ class MemoryStore:
423
423
 
424
424
 
425
425
  @flock_component(config_class=MemoryUtilityConfig)
426
- class MemoryUtilityComponent(UtilityComponentBase):
426
+ class MemoryUtilityComponent(UtilityComponent):
427
427
  """Enterprise-ready memory utility component using real datastores."""
428
428
 
429
429
  config: MemoryUtilityConfig = Field(
@@ -13,10 +13,10 @@ import psutil
13
13
  from pydantic import BaseModel, Field, field_validator
14
14
 
15
15
  from flock.core.component.agent_component_base import AgentComponentConfig
16
- from flock.core.component.utility_component_base import UtilityComponentBase
16
+ from flock.core.component.utility_component import UtilityComponent
17
17
  from flock.core.context.context import FlockContext
18
+ from flock.core.mcp.flock_mcp_server import FlockMCPServer
18
19
  from flock.core.registry import flock_component
19
- from flock.core.mcp.flock_mcp_server import FlockMCPServerBase
20
20
 
21
21
  if TYPE_CHECKING:
22
22
  from flock.core.flock_agent import FlockAgent
@@ -79,7 +79,7 @@ class MetricsUtilityConfig(AgentComponentConfig):
79
79
 
80
80
 
81
81
  @flock_component(config_class=MetricsUtilityConfig)
82
- class MetricsUtilityComponent(UtilityComponentBase):
82
+ class MetricsUtilityComponent(UtilityComponent):
83
83
  """Utility component for collecting and analyzing agent performance metrics."""
84
84
 
85
85
  # --- Singleton holder for convenient static access ---
@@ -540,7 +540,7 @@ class MetricsUtilityComponent(UtilityComponentBase):
540
540
 
541
541
  # --- MCP Server Lifecycle Hooks ---
542
542
  async def on_server_error(
543
- self, server: FlockMCPServerBase, error: Exception
543
+ self, server: FlockMCPServer, error: Exception
544
544
  ) -> None:
545
545
  """Record server error metrics."""
546
546
  self._record_metric(
@@ -552,7 +552,7 @@ class MetricsUtilityComponent(UtilityComponentBase):
552
552
  },
553
553
  )
554
554
 
555
- async def on_pre_server_init(self, server: FlockMCPServerBase):
555
+ async def on_pre_server_init(self, server: FlockMCPServer):
556
556
  """Initialize metrics collection for server."""
557
557
  self._server_start_time = time.time()
558
558
 
@@ -564,7 +564,7 @@ class MetricsUtilityComponent(UtilityComponentBase):
564
564
  {"server": server.config.name, "phase": "pre_init"},
565
565
  )
566
566
 
567
- async def on_post_server_init(self, server: FlockMCPServerBase):
567
+ async def on_post_server_init(self, server: FlockMCPServer):
568
568
  """Collect metrics after server starts."""
569
569
  if self.config.collect_memory:
570
570
  checkpoint_memory = psutil.Process().memory_info().rss
@@ -574,7 +574,7 @@ class MetricsUtilityComponent(UtilityComponentBase):
574
574
  {"server": server.config.name, "phase": "post_init"},
575
575
  )
576
576
 
577
- async def on_pre_server_terminate(self, server: FlockMCPServerBase):
577
+ async def on_pre_server_terminate(self, server: FlockMCPServer):
578
578
  """Collect metrics before server terminates."""
579
579
  if self.config.collect_memory:
580
580
  checkpoint_memory = psutil.Process().memory_info().rss
@@ -584,7 +584,7 @@ class MetricsUtilityComponent(UtilityComponentBase):
584
584
  {"server": server.config.name, "phase": "pre_terminate"},
585
585
  )
586
586
 
587
- async def on_post_server_terminate(self, server: FlockMCPServerBase):
587
+ async def on_post_server_terminate(self, server: FlockMCPServer):
588
588
  """Collect metrics after server terminates.
589
589
 
590
590
  Clean up and final metric recording.
@@ -615,7 +615,7 @@ class MetricsUtilityComponent(UtilityComponentBase):
615
615
  json.dump(summary, f, indent=2)
616
616
 
617
617
  async def on_pre_mcp_call(
618
- self, server: FlockMCPServerBase, arguments: Any | None = None
618
+ self, server: FlockMCPServer, arguments: Any | None = None
619
619
  ):
620
620
  """Record pre-call metrics."""
621
621
  if self.config.collect_cpu:
@@ -645,7 +645,7 @@ class MetricsUtilityComponent(UtilityComponentBase):
645
645
  )
646
646
 
647
647
  async def on_post_mcp_call(
648
- self, server: FlockMCPServerBase, result: Any | None = None
648
+ self, server: FlockMCPServer, result: Any | None = None
649
649
  ):
650
650
  """Record post-call metrics."""
651
651
  if self.config.collect_timing and self._server_start_time:
@@ -676,7 +676,7 @@ class MetricsUtilityComponent(UtilityComponentBase):
676
676
  )
677
677
 
678
678
  async def on_connect(
679
- self, server: FlockMCPServerBase, additional_params: dict[str, Any]
679
+ self, server: FlockMCPServer, additional_params: dict[str, Any]
680
680
  ) -> dict[str, Any]:
681
681
  """Collect metrics during connect."""
682
682
  # We should track the refresh rate for clients
@@ -7,13 +7,15 @@ from typing import TYPE_CHECKING, Any
7
7
  from pydantic import Field
8
8
 
9
9
  from flock.core.component.agent_component_base import AgentComponentConfig
10
- from flock.core.component.utility_component_base import UtilityComponentBase
10
+ from flock.core.component.utility_component import UtilityComponent
11
11
  from flock.core.context.context import FlockContext
12
12
  from flock.core.context.context_vars import FLOCK_BATCH_SILENT_MODE
13
- from flock.core.registry import flock_component
14
- from flock.core.logging.formatters.themed_formatter import ThemedAgentResultFormatter
13
+ from flock.core.logging.formatters.themed_formatter import (
14
+ ThemedAgentResultFormatter,
15
+ )
15
16
  from flock.core.logging.formatters.themes import OutputTheme
16
17
  from flock.core.logging.logging import get_logger
18
+ from flock.core.registry import flock_component
17
19
 
18
20
  if TYPE_CHECKING:
19
21
  from flock.core.flock_agent import FlockAgent
@@ -58,7 +60,7 @@ class OutputUtilityConfig(AgentComponentConfig):
58
60
 
59
61
 
60
62
  @flock_component(config_class=OutputUtilityConfig)
61
- class OutputUtilityComponent(UtilityComponentBase):
63
+ class OutputUtilityComponent(UtilityComponent):
62
64
  """Utility component that handles output formatting and display."""
63
65
 
64
66
  config: OutputUtilityConfig = Field(
@@ -97,7 +99,7 @@ class OutputUtilityComponent(UtilityComponentBase):
97
99
  """Format a dictionary with proper indentation."""
98
100
  if not d:
99
101
  return "{}"
100
-
102
+
101
103
  items = []
102
104
  prefix = " " * indent
103
105
  for key, value in d.items():
@@ -105,17 +107,17 @@ class OutputUtilityComponent(UtilityComponentBase):
105
107
  value = value[:97] + "..."
106
108
  formatted_value = self._format_value(value, key)
107
109
  items.append(f"{prefix} {key}: {formatted_value}")
108
-
110
+
109
111
  return "{\n" + "\n".join(items) + f"\n{prefix}}}"
110
112
 
111
113
  def _format_list(self, lst: list[Any]) -> str:
112
114
  """Format a list with proper structure."""
113
115
  if not lst:
114
116
  return "[]"
115
-
117
+
116
118
  if len(lst) <= 3:
117
119
  return str(lst)
118
-
120
+
119
121
  # For longer lists, show first few items and count
120
122
  preview = [str(item) for item in lst[:3]]
121
123
  return f"[{', '.join(preview)}, ... ({len(lst)} total)]"
@@ -127,7 +129,7 @@ class OutputUtilityComponent(UtilityComponentBase):
127
129
  language = match.group(1) or "text"
128
130
  code = match.group(2)
129
131
  return f"[CODE:{language}]\n{code}\n[/CODE]"
130
-
132
+
131
133
  # Replace markdown-style code blocks
132
134
  text = re.sub(
133
135
  r"```(\w+)?\n(.*?)\n```", replace_code_block, text, flags=re.DOTALL
flock/core/__init__.py CHANGED
@@ -1,9 +1,22 @@
1
1
  """This module contains the core classes of the flock package."""
2
2
 
3
+ from flock.core.component import (
4
+ AgentComponent,
5
+ AgentComponentConfig,
6
+ EvaluationComponent,
7
+ RoutingComponent,
8
+ UtilityComponent,
9
+ )
3
10
  from flock.core.context.context import FlockContext
4
11
  from flock.core.flock import Flock
5
12
  from flock.core.flock_agent import FlockAgent
6
13
  from flock.core.flock_factory import FlockFactory
14
+ from flock.core.mcp.flock_mcp_server import (
15
+ FlockMCPServer,
16
+ )
17
+ from flock.core.mcp.flock_mcp_tool import FlockMCPTool
18
+ from flock.core.mcp.mcp_client import FlockMCPClient
19
+ from flock.core.mcp.mcp_client_manager import FlockMCPClientManager
7
20
  from flock.core.registry import (
8
21
  RegistryHub as FlockRegistry, # Keep FlockRegistry name for API compatibility
9
22
  flock_callable,
@@ -12,23 +25,24 @@ from flock.core.registry import (
12
25
  flock_type,
13
26
  get_registry,
14
27
  )
15
- from flock.core.mcp.flock_mcp_server import (
16
- FlockMCPServerBase,
17
- )
18
- from flock.core.mcp.flock_mcp_tool_base import FlockMCPToolBase
19
- from flock.core.mcp.mcp_client import FlockMCPClientBase
20
- from flock.core.mcp.mcp_client_manager import FlockMCPClientManagerBase
21
28
 
22
29
  __all__ = [
23
30
  "Flock",
24
31
  "FlockAgent",
25
32
  "FlockContext",
26
33
  "FlockFactory",
27
- "FlockMCPClientBase",
28
- "FlockMCPClientManagerBase",
29
- "FlockMCPServerBase",
34
+ # Components
35
+ "AgentComponent",
36
+ "AgentComponentConfig",
37
+ "EvaluationComponent",
38
+ "RoutingComponent",
39
+ "UtilityComponent",
40
+
41
+ "FlockMCPClient",
42
+ "FlockMCPClientManager",
43
+ "FlockMCPServer",
30
44
  "FlockMCPServerConfig",
31
- "FlockMCPToolBase",
45
+ "FlockMCPTool",
32
46
  "FlockRegistry",
33
47
  "flock_callable",
34
48
  "flock_component",
@@ -2,14 +2,14 @@
2
2
 
3
3
  from typing import TYPE_CHECKING, Any
4
4
 
5
- from flock.core.component.evaluation_component_base import EvaluationComponentBase
6
- from flock.core.component.routing_component_base import RoutingComponentBase
7
- from flock.core.component.utility_component_base import UtilityComponentBase
5
+ from flock.core.component.evaluation_component import EvaluationComponent
6
+ from flock.core.component.routing_component import RoutingComponent
7
+ from flock.core.component.utility_component import UtilityComponent
8
8
  from flock.core.logging.logging import get_logger
9
9
 
10
10
  if TYPE_CHECKING:
11
- from flock.core.flock_agent import FlockAgent
12
11
  from flock.core.component.agent_component_base import AgentComponent
12
+ from flock.core.flock_agent import FlockAgent
13
13
 
14
14
  logger = get_logger("agent.components")
15
15
 
@@ -25,7 +25,7 @@ class FlockAgentComponents:
25
25
  if not component.name:
26
26
  logger.error("Component must have a name to be added.")
27
27
  return
28
-
28
+
29
29
  # Check if component with same name already exists
30
30
  existing = self.get_component(component.name)
31
31
  if existing:
@@ -54,29 +54,29 @@ class FlockAgentComponents:
54
54
  def get_enabled_components(self) -> list["AgentComponent"]:
55
55
  """Get a list of currently enabled components attached to this agent."""
56
56
  return [c for c in self.agent.components if c.config.enabled]
57
-
57
+
58
58
  def get_components_by_type(self, component_type: type) -> list["AgentComponent"]:
59
59
  """Get all components of a specific type."""
60
60
  return [c for c in self.agent.components if isinstance(c, component_type)]
61
61
 
62
- def get_evaluation_components(self) -> list[EvaluationComponentBase]:
62
+ def get_evaluation_components(self) -> list[EvaluationComponent]:
63
63
  """Get all evaluation components."""
64
- return self.get_components_by_type(EvaluationComponentBase)
64
+ return self.get_components_by_type(EvaluationComponent)
65
65
 
66
- def get_routing_components(self) -> list[RoutingComponentBase]:
66
+ def get_routing_components(self) -> list[RoutingComponent]:
67
67
  """Get all routing components."""
68
- return self.get_components_by_type(RoutingComponentBase)
69
-
70
- def get_utility_components(self) -> list[UtilityComponentBase]:
68
+ return self.get_components_by_type(RoutingComponent)
69
+
70
+ def get_utility_components(self) -> list[UtilityComponent]:
71
71
  """Get all utility components."""
72
- return self.get_components_by_type(UtilityComponentBase)
72
+ return self.get_components_by_type(UtilityComponent)
73
73
 
74
- def get_primary_evaluator(self) -> EvaluationComponentBase | None:
74
+ def get_primary_evaluator(self) -> EvaluationComponent | None:
75
75
  """Get the primary evaluation component (first one found)."""
76
76
  evaluators = self.get_evaluation_components()
77
77
  return evaluators[0] if evaluators else None
78
-
79
- def get_primary_router(self) -> RoutingComponentBase | None:
78
+
79
+ def get_primary_router(self) -> RoutingComponent | None:
80
80
  """Get the primary routing component (first one found)."""
81
81
  routers = self.get_routing_components()
82
82
  return routers[0] if routers else None