flock-core 0.5.11__py3-none-any.whl → 0.5.21__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 (94) hide show
  1. flock/__init__.py +1 -1
  2. flock/agent/__init__.py +30 -0
  3. flock/agent/builder_helpers.py +192 -0
  4. flock/agent/builder_validator.py +169 -0
  5. flock/agent/component_lifecycle.py +325 -0
  6. flock/agent/context_resolver.py +141 -0
  7. flock/agent/mcp_integration.py +212 -0
  8. flock/agent/output_processor.py +304 -0
  9. flock/api/__init__.py +20 -0
  10. flock/{api_models.py → api/models.py} +0 -2
  11. flock/{service.py → api/service.py} +3 -3
  12. flock/cli.py +2 -2
  13. flock/components/__init__.py +41 -0
  14. flock/components/agent/__init__.py +22 -0
  15. flock/{components.py → components/agent/base.py} +4 -3
  16. flock/{utility/output_utility_component.py → components/agent/output_utility.py} +12 -7
  17. flock/components/orchestrator/__init__.py +22 -0
  18. flock/{orchestrator_component.py → components/orchestrator/base.py} +5 -293
  19. flock/components/orchestrator/circuit_breaker.py +95 -0
  20. flock/components/orchestrator/collection.py +143 -0
  21. flock/components/orchestrator/deduplication.py +78 -0
  22. flock/core/__init__.py +30 -0
  23. flock/core/agent.py +953 -0
  24. flock/{artifacts.py → core/artifacts.py} +1 -1
  25. flock/{context_provider.py → core/context_provider.py} +3 -3
  26. flock/core/orchestrator.py +1102 -0
  27. flock/{store.py → core/store.py} +99 -454
  28. flock/{subscription.py → core/subscription.py} +1 -1
  29. flock/dashboard/collector.py +5 -5
  30. flock/dashboard/events.py +1 -1
  31. flock/dashboard/graph_builder.py +7 -7
  32. flock/dashboard/routes/__init__.py +21 -0
  33. flock/dashboard/routes/control.py +327 -0
  34. flock/dashboard/routes/helpers.py +340 -0
  35. flock/dashboard/routes/themes.py +76 -0
  36. flock/dashboard/routes/traces.py +521 -0
  37. flock/dashboard/routes/websocket.py +108 -0
  38. flock/dashboard/service.py +43 -1316
  39. flock/engines/dspy/__init__.py +20 -0
  40. flock/engines/dspy/artifact_materializer.py +216 -0
  41. flock/engines/dspy/signature_builder.py +474 -0
  42. flock/engines/dspy/streaming_executor.py +812 -0
  43. flock/engines/dspy_engine.py +45 -1330
  44. flock/engines/examples/simple_batch_engine.py +2 -2
  45. flock/engines/streaming/__init__.py +3 -0
  46. flock/engines/streaming/sinks.py +489 -0
  47. flock/examples.py +7 -7
  48. flock/logging/logging.py +1 -16
  49. flock/models/__init__.py +10 -0
  50. flock/orchestrator/__init__.py +45 -0
  51. flock/{artifact_collector.py → orchestrator/artifact_collector.py} +3 -3
  52. flock/orchestrator/artifact_manager.py +168 -0
  53. flock/{batch_accumulator.py → orchestrator/batch_accumulator.py} +2 -2
  54. flock/orchestrator/component_runner.py +389 -0
  55. flock/orchestrator/context_builder.py +167 -0
  56. flock/{correlation_engine.py → orchestrator/correlation_engine.py} +2 -2
  57. flock/orchestrator/event_emitter.py +167 -0
  58. flock/orchestrator/initialization.py +184 -0
  59. flock/orchestrator/lifecycle_manager.py +226 -0
  60. flock/orchestrator/mcp_manager.py +202 -0
  61. flock/orchestrator/scheduler.py +189 -0
  62. flock/orchestrator/server_manager.py +234 -0
  63. flock/orchestrator/tracing.py +147 -0
  64. flock/storage/__init__.py +10 -0
  65. flock/storage/artifact_aggregator.py +158 -0
  66. flock/storage/in_memory/__init__.py +6 -0
  67. flock/storage/in_memory/artifact_filter.py +114 -0
  68. flock/storage/in_memory/history_aggregator.py +115 -0
  69. flock/storage/sqlite/__init__.py +10 -0
  70. flock/storage/sqlite/agent_history_queries.py +154 -0
  71. flock/storage/sqlite/consumption_loader.py +100 -0
  72. flock/storage/sqlite/query_builder.py +112 -0
  73. flock/storage/sqlite/query_params_builder.py +91 -0
  74. flock/storage/sqlite/schema_manager.py +168 -0
  75. flock/storage/sqlite/summary_queries.py +194 -0
  76. flock/utils/__init__.py +14 -0
  77. flock/utils/async_utils.py +67 -0
  78. flock/{runtime.py → utils/runtime.py} +3 -3
  79. flock/utils/time_utils.py +53 -0
  80. flock/utils/type_resolution.py +38 -0
  81. flock/{utilities.py → utils/utilities.py} +2 -2
  82. flock/utils/validation.py +57 -0
  83. flock/utils/visibility.py +79 -0
  84. flock/utils/visibility_utils.py +134 -0
  85. {flock_core-0.5.11.dist-info → flock_core-0.5.21.dist-info}/METADATA +19 -5
  86. {flock_core-0.5.11.dist-info → flock_core-0.5.21.dist-info}/RECORD +92 -34
  87. flock/agent.py +0 -1578
  88. flock/orchestrator.py +0 -1983
  89. /flock/{visibility.py → core/visibility.py} +0 -0
  90. /flock/{system_artifacts.py → models/system_artifacts.py} +0 -0
  91. /flock/{helper → utils}/cli_helper.py +0 -0
  92. {flock_core-0.5.11.dist-info → flock_core-0.5.21.dist-info}/WHEEL +0 -0
  93. {flock_core-0.5.11.dist-info → flock_core-0.5.21.dist-info}/entry_points.txt +0 -0
  94. {flock_core-0.5.11.dist-info → flock_core-0.5.21.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,167 @@
1
+ """Execution context building with security boundary enforcement.
2
+
3
+ Phase 5A: Extracted from orchestrator.py to eliminate code duplication.
4
+
5
+ This module implements the security boundary pattern for context creation,
6
+ consolidating duplicated code from direct_invoke(), invoke(), and _run_agent_task().
7
+
8
+ SECURITY CRITICAL: This module enforces the Phase 8 context provider pattern
9
+ that prevents identity spoofing and READ capability bypass.
10
+ """
11
+
12
+ from __future__ import annotations
13
+
14
+ import logging
15
+ from typing import TYPE_CHECKING, Any
16
+ from uuid import UUID, uuid4
17
+
18
+
19
+ if TYPE_CHECKING:
20
+ from flock.core import Agent
21
+ from flock.core.artifacts import Artifact
22
+ from flock.core.store import BlackboardStore
23
+ from flock.utils.runtime import Context
24
+
25
+
26
+ class ContextBuilder:
27
+ """Builds execution contexts with security boundary enforcement.
28
+
29
+ This module implements the security boundary pattern:
30
+ 1. Resolve provider (agent > global > default)
31
+ 2. Wrap with BoundContextProvider (prevent identity spoofing)
32
+ 3. Evaluate context artifacts (orchestrator controls READ)
33
+ 4. Create Context with data-only (no capabilities)
34
+
35
+ Phase 5A: Extracted to eliminate duplication across 3 methods and
36
+ reduce _run_agent_task complexity from C(11) to B or A.
37
+
38
+ SECURITY NOTICE: Changes to this module affect the security boundary
39
+ between agents and the blackboard. Review carefully.
40
+ """
41
+
42
+ def __init__(
43
+ self,
44
+ *,
45
+ store: BlackboardStore,
46
+ default_context_provider: Any | None = None,
47
+ ):
48
+ """Initialize ContextBuilder with blackboard store and default provider.
49
+
50
+ Args:
51
+ store: BlackboardStore instance for context provider queries
52
+ default_context_provider: Global context provider (Phase 3 security fix).
53
+ If None, agents use DefaultContextProvider. Can be overridden per-agent.
54
+ """
55
+ self._store = store
56
+ self._default_context_provider = default_context_provider
57
+ self._logger = logging.getLogger(__name__)
58
+
59
+ async def build_execution_context(
60
+ self,
61
+ *,
62
+ agent: Agent,
63
+ artifacts: list[Artifact],
64
+ correlation_id: UUID | None = None,
65
+ is_batch: bool = False,
66
+ ) -> Context:
67
+ """Build Context with pre-filtered artifacts (Phase 8 security fix).
68
+
69
+ Implements the security boundary pattern:
70
+ 1. Resolve provider (agent > global > default)
71
+ 2. Wrap with BoundContextProvider (prevent identity spoofing)
72
+ 3. Evaluate context artifacts (orchestrator controls READ)
73
+ 4. Create Context with data-only (no capabilities)
74
+
75
+ SECURITY NOTICE: This method enforces the security boundary between
76
+ agents and the blackboard. Agents receive pre-filtered context data
77
+ and cannot bypass visibility controls.
78
+
79
+ Args:
80
+ agent: Agent instance being executed
81
+ artifacts: Input artifacts that triggered execution
82
+ correlation_id: Optional correlation ID for grouping related work
83
+ is_batch: Whether this is a batch execution (affects context metadata)
84
+
85
+ Returns:
86
+ Context with pre-filtered artifacts and agent identity
87
+
88
+ Examples:
89
+ >>> # Direct invocation
90
+ >>> context = await builder.build_execution_context(
91
+ ... agent=pizza_agent,
92
+ ... artifacts=[input_artifact],
93
+ ... correlation_id=uuid4(),
94
+ ... is_batch=False,
95
+ ... )
96
+ >>> outputs = await agent.execute(context, artifacts)
97
+
98
+ >>> # Batch execution
99
+ >>> context = await builder.build_execution_context(
100
+ ... agent=batch_agent,
101
+ ... artifacts=batch_artifacts,
102
+ ... correlation_id=batch_correlation,
103
+ ... is_batch=True,
104
+ ... )
105
+ """
106
+ # Phase 8: Evaluate context BEFORE creating Context (security fix)
107
+ # Provider resolution: per-agent > global > DefaultContextProvider
108
+ from flock.core.context_provider import (
109
+ BoundContextProvider,
110
+ ContextRequest,
111
+ DefaultContextProvider,
112
+ )
113
+
114
+ # Resolve correlation ID
115
+ resolved_correlation_id = correlation_id or (
116
+ artifacts[0].correlation_id
117
+ if artifacts and artifacts[0].correlation_id
118
+ else uuid4()
119
+ )
120
+
121
+ # Step 1: Resolve provider (agent > global > default)
122
+ inner_provider = (
123
+ getattr(agent, "context_provider", None)
124
+ or self._default_context_provider
125
+ or DefaultContextProvider()
126
+ )
127
+
128
+ # Step 2: SECURITY FIX - Wrap provider with BoundContextProvider
129
+ # This prevents identity spoofing by binding the provider to the agent's identity
130
+ provider = BoundContextProvider(inner_provider, agent.identity)
131
+
132
+ # Step 3: Evaluate context using provider (orchestrator controls READ capability)
133
+ # Engines will receive pre-filtered artifacts via ctx.artifacts
134
+ request = ContextRequest(
135
+ agent=agent,
136
+ correlation_id=resolved_correlation_id,
137
+ store=self._store,
138
+ agent_identity=agent.identity,
139
+ exclude_ids={a.id for a in artifacts}, # Exclude input artifacts
140
+ )
141
+ context_artifacts = await provider(request)
142
+
143
+ # Step 4: Create Context with pre-filtered data (no capabilities!)
144
+ # SECURITY: Context is now just data - engines can't query anything
145
+ from flock.utils.runtime import Context
146
+
147
+ ctx = Context(
148
+ artifacts=context_artifacts, # Pre-filtered conversation context
149
+ agent_identity=agent.identity,
150
+ task_id=str(uuid4()),
151
+ correlation_id=resolved_correlation_id,
152
+ is_batch=is_batch,
153
+ )
154
+
155
+ # Log context creation for debugging
156
+ self._logger.debug(
157
+ f"Context built: agent={agent.name}, "
158
+ f"correlation_id={resolved_correlation_id}, "
159
+ f"is_batch={is_batch}, "
160
+ f"context_artifacts={len(context_artifacts)}, "
161
+ f"input_artifacts={len(artifacts)}"
162
+ )
163
+
164
+ return ctx
165
+
166
+
167
+ __all__ = ["ContextBuilder"]
@@ -16,8 +16,8 @@ from typing import TYPE_CHECKING, Any
16
16
 
17
17
 
18
18
  if TYPE_CHECKING:
19
- from flock.artifacts import Artifact
20
- from flock.subscription import JoinSpec, Subscription
19
+ from flock.core.artifacts import Artifact
20
+ from flock.core.subscription import JoinSpec, Subscription
21
21
 
22
22
 
23
23
  class CorrelationGroup:
@@ -0,0 +1,167 @@
1
+ """Event emission for real-time dashboard updates.
2
+
3
+ Phase 5A: Extracted from orchestrator.py to reduce coupling to dashboard.
4
+
5
+ This module handles WebSocket event emission for dashboard visualization of
6
+ batch and correlation logic operations. Separating this code reduces the
7
+ orchestrator's dependency on dashboard-specific components.
8
+ """
9
+
10
+ from __future__ import annotations
11
+
12
+ from typing import TYPE_CHECKING, Any
13
+
14
+
15
+ if TYPE_CHECKING:
16
+ from flock.core.artifacts import Artifact
17
+ from flock.core.subscription import Subscription
18
+ from flock.orchestrator.batch_accumulator import BatchEngine
19
+ from flock.orchestrator.correlation_engine import CorrelationEngine
20
+
21
+
22
+ class EventEmitter:
23
+ """Manages WebSocket event emission for dashboard updates.
24
+
25
+ This module is responsible for broadcasting real-time events about
26
+ batch accumulation and correlation group status to connected dashboard
27
+ clients via WebSocket.
28
+
29
+ Phase 5A: Extracted to reduce orchestrator coupling to dashboard.
30
+ """
31
+
32
+ def __init__(self, websocket_manager: Any | None = None):
33
+ """Initialize EventEmitter with WebSocket manager.
34
+
35
+ Args:
36
+ websocket_manager: WebSocket manager instance for broadcasting events.
37
+ If None, event emission is disabled (dashboard not active).
38
+ """
39
+ self._websocket_manager = websocket_manager
40
+
41
+ def set_websocket_manager(self, websocket_manager: Any | None) -> None:
42
+ """Update the WebSocket manager (called when dashboard is enabled).
43
+
44
+ Args:
45
+ websocket_manager: WebSocket manager instance for broadcasting
46
+ """
47
+ self._websocket_manager = websocket_manager
48
+
49
+ async def emit_correlation_updated(
50
+ self,
51
+ *,
52
+ correlation_engine: CorrelationEngine,
53
+ agent_name: str,
54
+ subscription_index: int,
55
+ artifact: Artifact,
56
+ ) -> None:
57
+ """Emit CorrelationGroupUpdatedEvent for real-time dashboard updates.
58
+
59
+ Called when an artifact is added to a correlation group that is not yet complete.
60
+
61
+ Args:
62
+ correlation_engine: CorrelationEngine instance with current state
63
+ agent_name: Name of the agent with the JoinSpec subscription
64
+ subscription_index: Index of the subscription in the agent's subscriptions list
65
+ artifact: The artifact that triggered this update
66
+ """
67
+ # Only emit if dashboard is enabled
68
+ if self._websocket_manager is None:
69
+ return
70
+
71
+ # Import _get_correlation_groups helper from dashboard service
72
+ from flock.dashboard.routes.helpers import _get_correlation_groups
73
+
74
+ # Get current correlation groups state from engine
75
+ groups = _get_correlation_groups(
76
+ correlation_engine, agent_name, subscription_index
77
+ )
78
+
79
+ if not groups:
80
+ return # No groups to report (shouldn't happen, but defensive)
81
+
82
+ # Find the group that was just updated (match by last updated time or artifact ID)
83
+ # For now, we'll emit an event for the FIRST group that's still waiting
84
+ # In practice, the artifact we just added should be in one of these groups
85
+ for group_state in groups:
86
+ if not group_state["is_complete"]:
87
+ # Import CorrelationGroupUpdatedEvent
88
+ from flock.dashboard.events import CorrelationGroupUpdatedEvent
89
+
90
+ # Build and emit event
91
+ event = CorrelationGroupUpdatedEvent(
92
+ agent_name=agent_name,
93
+ subscription_index=subscription_index,
94
+ correlation_key=group_state["correlation_key"],
95
+ collected_types=group_state["collected_types"],
96
+ required_types=group_state["required_types"],
97
+ waiting_for=group_state["waiting_for"],
98
+ elapsed_seconds=group_state["elapsed_seconds"],
99
+ expires_in_seconds=group_state["expires_in_seconds"],
100
+ expires_in_artifacts=group_state["expires_in_artifacts"],
101
+ artifact_id=str(artifact.id),
102
+ artifact_type=artifact.type,
103
+ is_complete=group_state["is_complete"],
104
+ )
105
+
106
+ # Broadcast via WebSocket
107
+ await self._websocket_manager.broadcast(event)
108
+ break # Only emit one event per artifact addition
109
+
110
+ async def emit_batch_item_added(
111
+ self,
112
+ *,
113
+ batch_engine: BatchEngine,
114
+ agent_name: str,
115
+ subscription_index: int,
116
+ subscription: Subscription,
117
+ artifact: Artifact,
118
+ ) -> None:
119
+ """Emit BatchItemAddedEvent for real-time dashboard updates.
120
+
121
+ Called when an artifact is added to a batch that hasn't reached flush threshold.
122
+
123
+ Args:
124
+ batch_engine: BatchEngine instance with current state
125
+ agent_name: Name of the agent with the BatchSpec subscription
126
+ subscription_index: Index of the subscription in the agent's subscriptions list
127
+ subscription: The subscription with BatchSpec configuration
128
+ artifact: The artifact that triggered this update
129
+ """
130
+ # Only emit if dashboard is enabled
131
+ if self._websocket_manager is None:
132
+ return
133
+
134
+ # Import _get_batch_state helper from dashboard service
135
+ from flock.dashboard.routes.helpers import _get_batch_state
136
+
137
+ # Get current batch state from engine
138
+ batch_state = _get_batch_state(
139
+ batch_engine, agent_name, subscription_index, subscription.batch
140
+ )
141
+
142
+ if not batch_state:
143
+ return # No batch to report (shouldn't happen, but defensive)
144
+
145
+ # Import BatchItemAddedEvent
146
+ from flock.dashboard.events import BatchItemAddedEvent
147
+
148
+ # Build and emit event
149
+ event = BatchItemAddedEvent(
150
+ agent_name=agent_name,
151
+ subscription_index=subscription_index,
152
+ items_collected=batch_state["items_collected"],
153
+ items_target=batch_state.get("items_target"),
154
+ items_remaining=batch_state.get("items_remaining"),
155
+ elapsed_seconds=batch_state["elapsed_seconds"],
156
+ timeout_seconds=batch_state.get("timeout_seconds"),
157
+ timeout_remaining_seconds=batch_state.get("timeout_remaining_seconds"),
158
+ will_flush=batch_state["will_flush"],
159
+ artifact_id=str(artifact.id),
160
+ artifact_type=artifact.type,
161
+ )
162
+
163
+ # Broadcast via WebSocket
164
+ await self._websocket_manager.broadcast(event)
165
+
166
+
167
+ __all__ = ["EventEmitter"]
@@ -0,0 +1,184 @@
1
+ """Orchestrator initialization helper.
2
+
3
+ Handles component setup and state initialization.
4
+ Extracted from orchestrator.py to reduce __init__ complexity.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ import asyncio
10
+ import logging
11
+ import os
12
+ from typing import TYPE_CHECKING, Any
13
+
14
+ from flock.core.store import InMemoryBlackboardStore
15
+ from flock.orchestrator.artifact_collector import ArtifactCollector
16
+ from flock.orchestrator.batch_accumulator import BatchEngine
17
+ from flock.orchestrator.component_runner import ComponentRunner
18
+ from flock.orchestrator.context_builder import ContextBuilder
19
+ from flock.orchestrator.correlation_engine import CorrelationEngine
20
+ from flock.orchestrator.event_emitter import EventEmitter
21
+ from flock.orchestrator.lifecycle_manager import LifecycleManager
22
+ from flock.orchestrator.mcp_manager import MCPManager
23
+ from flock.orchestrator.tracing import TracingManager
24
+ from flock.utils.cli_helper import init_console
25
+
26
+
27
+ if TYPE_CHECKING:
28
+ from flock.components.orchestrator import OrchestratorComponent
29
+ from flock.core.store import BlackboardStore
30
+
31
+
32
+ class OrchestratorInitializer:
33
+ """Handles orchestrator component initialization.
34
+
35
+ Centralizes the complex setup logic from Flock.__init__ into
36
+ a focused helper class.
37
+ """
38
+
39
+ @staticmethod
40
+ def initialize_components(
41
+ store: BlackboardStore | None,
42
+ context_provider: Any,
43
+ max_agent_iterations: int,
44
+ logger: logging.Logger,
45
+ model: str | None,
46
+ ) -> dict[str, Any]:
47
+ """Initialize all orchestrator components and state.
48
+
49
+ Args:
50
+ store: Blackboard storage backend (or None for default)
51
+ context_provider: Global context provider for agents
52
+ max_agent_iterations: Circuit breaker limit
53
+ logger: Logger instance
54
+ model: Default LLM model
55
+
56
+ Returns:
57
+ Dictionary of initialized components and state
58
+
59
+ Examples:
60
+ >>> logger = logging.getLogger(__name__)
61
+ >>> components = OrchestratorInitializer.initialize_components(
62
+ ... store=None,
63
+ ... context_provider=None,
64
+ ... max_agent_iterations=1000,
65
+ ... logger=logger,
66
+ ... model="openai/gpt-4.1",
67
+ ... )
68
+ >>> orchestrator.store = components["store"]
69
+ >>> orchestrator._scheduler = components["scheduler"]
70
+ """
71
+ # Initialize console (with error handling for encoding issues)
72
+ try:
73
+ init_console(clear_screen=True, show_banner=True, model=model)
74
+ except (UnicodeEncodeError, UnicodeDecodeError):
75
+ # Skip banner on Windows consoles with encoding issues (e.g., tests, CI)
76
+ pass
77
+
78
+ # Basic state
79
+ resolved_store = store or InMemoryBlackboardStore()
80
+ agents: dict[str, Any] = {}
81
+ lock = asyncio.Lock()
82
+ metrics: dict[str, float] = {"artifacts_published": 0, "agent_runs": 0}
83
+ agent_iteration_count: dict[str, int] = {}
84
+
85
+ # Engines
86
+ artifact_collector = ArtifactCollector()
87
+ correlation_engine = CorrelationEngine()
88
+ batch_engine = BatchEngine()
89
+
90
+ # Phase 5A modules
91
+ context_builder = ContextBuilder(
92
+ store=resolved_store,
93
+ default_context_provider=context_provider,
94
+ )
95
+ event_emitter = EventEmitter(websocket_manager=None)
96
+ lifecycle_manager = LifecycleManager(
97
+ correlation_engine=correlation_engine,
98
+ batch_engine=batch_engine,
99
+ cleanup_interval=0.1,
100
+ )
101
+
102
+ # Phase 3 modules
103
+ mcp_manager_instance = MCPManager()
104
+ tracing_manager = TracingManager()
105
+
106
+ # Auto-workflow tracing feature flag
107
+ auto_workflow_enabled = os.getenv(
108
+ "FLOCK_AUTO_WORKFLOW_TRACE", "false"
109
+ ).lower() in {
110
+ "true",
111
+ "1",
112
+ "yes",
113
+ "on",
114
+ }
115
+
116
+ return {
117
+ # Basic state
118
+ "store": resolved_store,
119
+ "agents": agents,
120
+ "lock": lock,
121
+ "metrics": metrics,
122
+ "agent_iteration_count": agent_iteration_count,
123
+ # Engines
124
+ "artifact_collector": artifact_collector,
125
+ "correlation_engine": correlation_engine,
126
+ "batch_engine": batch_engine,
127
+ # Phase 5A modules
128
+ "context_builder": context_builder,
129
+ "event_emitter": event_emitter,
130
+ "lifecycle_manager": lifecycle_manager,
131
+ # Phase 3 modules
132
+ "mcp_manager_instance": mcp_manager_instance,
133
+ "tracing_manager": tracing_manager,
134
+ # Feature flags
135
+ "auto_workflow_enabled": auto_workflow_enabled,
136
+ # Placeholders
137
+ "websocket_manager": None,
138
+ }
139
+
140
+ @staticmethod
141
+ def initialize_components_and_runner(
142
+ components_list: list[OrchestratorComponent],
143
+ max_agent_iterations: int,
144
+ logger: logging.Logger,
145
+ ) -> dict[str, Any]:
146
+ """Initialize built-in components and create ComponentRunner.
147
+
148
+ Args:
149
+ components_list: List to populate with components
150
+ max_agent_iterations: Circuit breaker limit
151
+ logger: Logger instance
152
+
153
+ Returns:
154
+ Dictionary with component_runner and updated components list
155
+
156
+ Examples:
157
+ >>> components = []
158
+ >>> result = OrchestratorInitializer.initialize_components_and_runner(
159
+ ... components, max_agent_iterations=1000, logger=logger
160
+ ... )
161
+ >>> component_runner = result["component_runner"]
162
+ """
163
+ from flock.components.orchestrator import (
164
+ BuiltinCollectionComponent,
165
+ CircuitBreakerComponent,
166
+ DeduplicationComponent,
167
+ )
168
+
169
+ # Add built-in components
170
+ components_list.append(
171
+ CircuitBreakerComponent(max_iterations=max_agent_iterations)
172
+ )
173
+ components_list.append(DeduplicationComponent())
174
+ components_list.append(BuiltinCollectionComponent())
175
+
176
+ # Sort by priority
177
+ components_list.sort(key=lambda c: c.priority)
178
+
179
+ # Create ComponentRunner
180
+ component_runner = ComponentRunner(components_list, logger)
181
+
182
+ return {
183
+ "component_runner": component_runner,
184
+ }