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.

Files changed (130) hide show
  1. flock/cli/execute_flock.py +1 -1
  2. flock/cli/manage_agents.py +6 -6
  3. flock/components/__init__.py +30 -0
  4. flock/components/evaluation/__init__.py +9 -0
  5. flock/components/evaluation/declarative_evaluation_component.py +222 -0
  6. flock/components/routing/__init__.py +15 -0
  7. flock/{routers/conditional/conditional_router.py → components/routing/conditional_routing_component.py} +61 -53
  8. flock/components/routing/default_routing_component.py +103 -0
  9. flock/components/routing/llm_routing_component.py +206 -0
  10. flock/components/utility/__init__.py +15 -0
  11. flock/{modules/enterprise_memory/enterprise_memory_module.py → components/utility/memory_utility_component.py} +195 -173
  12. flock/{modules/performance/metrics_module.py → components/utility/metrics_utility_component.py} +110 -95
  13. flock/{modules/output/output_module.py → components/utility/output_utility_component.py} +47 -45
  14. flock/core/__init__.py +26 -18
  15. flock/core/agent/__init__.py +16 -0
  16. flock/core/agent/flock_agent_components.py +104 -0
  17. flock/core/agent/flock_agent_execution.py +101 -0
  18. flock/core/agent/flock_agent_integration.py +206 -0
  19. flock/core/agent/flock_agent_lifecycle.py +177 -0
  20. flock/core/agent/flock_agent_serialization.py +381 -0
  21. flock/core/api/endpoints.py +2 -2
  22. flock/core/api/service.py +2 -2
  23. flock/core/component/__init__.py +15 -0
  24. flock/core/{flock_module.py → component/agent_component_base.py} +136 -34
  25. flock/core/component/evaluation_component.py +56 -0
  26. flock/core/component/routing_component.py +74 -0
  27. flock/core/component/utility_component.py +69 -0
  28. flock/core/config/flock_agent_config.py +49 -2
  29. flock/core/evaluation/utils.py +3 -2
  30. flock/core/execution/batch_executor.py +1 -1
  31. flock/core/execution/evaluation_executor.py +2 -2
  32. flock/core/execution/opik_executor.py +1 -1
  33. flock/core/flock.py +147 -493
  34. flock/core/flock_agent.py +195 -1032
  35. flock/core/flock_factory.py +114 -90
  36. flock/core/flock_scheduler.py +1 -1
  37. flock/core/flock_server_manager.py +8 -8
  38. flock/core/logging/logging.py +1 -0
  39. flock/core/mcp/flock_mcp_server.py +53 -48
  40. flock/core/mcp/{flock_mcp_tool_base.py → flock_mcp_tool.py} +2 -2
  41. flock/core/mcp/mcp_client.py +9 -9
  42. flock/core/mcp/mcp_client_manager.py +9 -9
  43. flock/core/mcp/mcp_config.py +24 -24
  44. flock/core/mixin/dspy_integration.py +5 -5
  45. flock/core/orchestration/__init__.py +18 -0
  46. flock/core/orchestration/flock_batch_processor.py +94 -0
  47. flock/core/orchestration/flock_evaluator.py +113 -0
  48. flock/core/orchestration/flock_execution.py +288 -0
  49. flock/core/orchestration/flock_initialization.py +125 -0
  50. flock/core/orchestration/flock_server_manager.py +67 -0
  51. flock/core/orchestration/flock_web_server.py +117 -0
  52. flock/core/registry/__init__.py +45 -0
  53. flock/core/registry/agent_registry.py +69 -0
  54. flock/core/registry/callable_registry.py +139 -0
  55. flock/core/registry/component_discovery.py +142 -0
  56. flock/core/registry/component_registry.py +64 -0
  57. flock/core/registry/config_mapping.py +64 -0
  58. flock/core/registry/decorators.py +137 -0
  59. flock/core/registry/registry_hub.py +205 -0
  60. flock/core/registry/server_registry.py +57 -0
  61. flock/core/registry/type_registry.py +86 -0
  62. flock/core/serialization/flock_serializer.py +36 -32
  63. flock/core/serialization/serialization_utils.py +28 -25
  64. flock/core/util/hydrator.py +1 -1
  65. flock/core/util/input_resolver.py +29 -2
  66. flock/mcp/servers/sse/flock_sse_server.py +10 -10
  67. flock/mcp/servers/stdio/flock_stdio_server.py +10 -10
  68. flock/mcp/servers/streamable_http/flock_streamable_http_server.py +10 -10
  69. flock/mcp/servers/websockets/flock_websocket_server.py +10 -10
  70. flock/platform/docker_tools.py +3 -3
  71. flock/webapp/app/chat.py +1 -1
  72. flock/webapp/app/main.py +9 -5
  73. flock/webapp/app/services/flock_service.py +1 -1
  74. flock/webapp/app/services/sharing_store.py +1 -0
  75. flock/workflow/activities.py +67 -92
  76. flock/workflow/agent_execution_activity.py +6 -6
  77. flock/workflow/flock_workflow.py +1 -1
  78. flock_core-0.5.0b0.dist-info/METADATA +272 -0
  79. {flock_core-0.4.528.dist-info → flock_core-0.5.0b0.dist-info}/RECORD +82 -95
  80. flock/core/flock_evaluator.py +0 -60
  81. flock/core/flock_registry.py +0 -702
  82. flock/core/flock_router.py +0 -83
  83. flock/evaluators/__init__.py +0 -1
  84. flock/evaluators/declarative/__init__.py +0 -1
  85. flock/evaluators/declarative/declarative_evaluator.py +0 -217
  86. flock/evaluators/memory/memory_evaluator.py +0 -90
  87. flock/evaluators/test/test_case_evaluator.py +0 -38
  88. flock/evaluators/zep/zep_evaluator.py +0 -59
  89. flock/modules/__init__.py +0 -1
  90. flock/modules/assertion/__init__.py +0 -1
  91. flock/modules/assertion/assertion_module.py +0 -286
  92. flock/modules/callback/__init__.py +0 -1
  93. flock/modules/callback/callback_module.py +0 -91
  94. flock/modules/enterprise_memory/README.md +0 -99
  95. flock/modules/mem0/__init__.py +0 -1
  96. flock/modules/mem0/mem0_module.py +0 -126
  97. flock/modules/mem0_async/__init__.py +0 -1
  98. flock/modules/mem0_async/async_mem0_module.py +0 -126
  99. flock/modules/memory/__init__.py +0 -1
  100. flock/modules/memory/memory_module.py +0 -429
  101. flock/modules/memory/memory_parser.py +0 -125
  102. flock/modules/memory/memory_storage.py +0 -736
  103. flock/modules/output/__init__.py +0 -1
  104. flock/modules/performance/__init__.py +0 -1
  105. flock/modules/zep/__init__.py +0 -1
  106. flock/modules/zep/zep_module.py +0 -192
  107. flock/routers/__init__.py +0 -1
  108. flock/routers/agent/__init__.py +0 -1
  109. flock/routers/agent/agent_router.py +0 -236
  110. flock/routers/agent/handoff_agent.py +0 -58
  111. flock/routers/default/__init__.py +0 -1
  112. flock/routers/default/default_router.py +0 -80
  113. flock/routers/feedback/feedback_router.py +0 -114
  114. flock/routers/list_generator/list_generator_router.py +0 -166
  115. flock/routers/llm/__init__.py +0 -1
  116. flock/routers/llm/llm_router.py +0 -365
  117. flock/tools/__init__.py +0 -0
  118. flock/tools/azure_tools.py +0 -781
  119. flock/tools/code_tools.py +0 -167
  120. flock/tools/file_tools.py +0 -149
  121. flock/tools/github_tools.py +0 -157
  122. flock/tools/markdown_tools.py +0 -205
  123. flock/tools/system_tools.py +0 -9
  124. flock/tools/text_tools.py +0 -810
  125. flock/tools/web_tools.py +0 -90
  126. flock/tools/zendesk_tools.py +0 -147
  127. flock_core-0.4.528.dist-info/METADATA +0 -675
  128. {flock_core-0.4.528.dist-info → flock_core-0.5.0b0.dist-info}/WHEEL +0 -0
  129. {flock_core-0.4.528.dist-info → flock_core-0.5.0b0.dist-info}/entry_points.txt +0 -0
  130. {flock_core-0.4.528.dist-info → flock_core-0.5.0b0.dist-info}/licenses/LICENSE +0 -0
@@ -8,14 +8,21 @@ from typing import Any, Literal
8
8
  import httpx
9
9
  from pydantic import AnyUrl, BaseModel, ConfigDict, Field, FileUrl
10
10
 
11
+ from flock.components.utility.metrics_utility_component import (
12
+ MetricsUtilityComponent,
13
+ MetricsUtilityConfig,
14
+ )
15
+
16
+ # New unified components imported locally to avoid circular imports
17
+ from flock.core.config.flock_agent_config import FlockAgentConfig
11
18
  from flock.core.config.scheduled_agent_config import ScheduledAgentConfig
12
- from flock.core.flock_agent import FlockAgent, SignatureType
19
+ from flock.core.flock_agent import DynamicStr, FlockAgent
13
20
  from flock.core.logging.formatters.themes import OutputTheme
14
- from flock.core.mcp.flock_mcp_server import FlockMCPServerBase
21
+ from flock.core.mcp.flock_mcp_server import FlockMCPServer
15
22
  from flock.core.mcp.mcp_config import (
16
- FlockMCPCachingConfigurationBase,
17
- FlockMCPCallbackConfigurationBase,
18
- FlockMCPFeatureConfigurationBase,
23
+ FlockMCPCachingConfiguration,
24
+ FlockMCPCallbackConfiguration,
25
+ FlockMCPFeatureConfiguration,
19
26
  )
20
27
  from flock.core.mcp.types.types import (
21
28
  FlockListRootsMCPCallback,
@@ -28,10 +35,6 @@ from flock.core.mcp.types.types import (
28
35
  StreamableHttpServerParameters,
29
36
  WebsocketServerParameters,
30
37
  )
31
- from flock.evaluators.declarative.declarative_evaluator import (
32
- DeclarativeEvaluator,
33
- DeclarativeEvaluatorConfig,
34
- )
35
38
  from flock.mcp.servers.sse.flock_sse_server import (
36
39
  FlockSSEConfig,
37
40
  FlockSSEConnectionConfig,
@@ -52,11 +55,6 @@ from flock.mcp.servers.websockets.flock_websocket_server import (
52
55
  FlockWSConnectionConfig,
53
56
  FlockWSServer,
54
57
  )
55
- from flock.modules.output.output_module import OutputModule, OutputModuleConfig
56
- from flock.modules.performance.metrics_module import (
57
- MetricsModule,
58
- MetricsModuleConfig,
59
- )
60
58
  from flock.workflow.temporal_config import TemporalActivityConfig
61
59
 
62
60
  LoggingLevel = Literal[
@@ -111,34 +109,29 @@ class FlockFactory:
111
109
  class StreamableHttpParams(BaseModel):
112
110
  """Factory-Params for Streamable Http Servers."""
113
111
 
114
- url: str | AnyUrl = Field(
115
- ...,
116
- description="Url the server listens at."
117
- )
112
+ url: str | AnyUrl = Field(..., description="Url the server listens at.")
118
113
 
119
114
  headers: dict[str, Any] | None = Field(
120
115
  default=None,
121
- description="Additional Headers to pass to the client."
116
+ description="Additional Headers to pass to the client.",
122
117
  )
123
118
 
124
119
  auth: httpx.Auth | None = Field(
125
- default=None,
126
- description="Httpx Auth Schema."
120
+ default=None, description="Httpx Auth Schema."
127
121
  )
128
122
 
129
123
  timeout_seconds: float | int = Field(
130
- default=5,
131
- description="Http Timeout in Seconds"
124
+ default=5, description="Http Timeout in Seconds"
132
125
  )
133
126
 
134
127
  sse_read_timeout_seconds: float | int = Field(
135
- default=60*5,
136
- description="How many seconds to wait for server-sent events until closing the connection."
128
+ default=60 * 5,
129
+ description="How many seconds to wait for server-sent events until closing the connection.",
137
130
  )
138
131
 
139
132
  terminate_on_close: bool = Field(
140
133
  default=True,
141
- description="Whether or not to terminate the underlying connection on close."
134
+ description="Whether or not to terminate the underlying connection on close.",
142
135
  )
143
136
 
144
137
  model_config = ConfigDict(
@@ -169,8 +162,7 @@ class FlockFactory:
169
162
  )
170
163
 
171
164
  auth: httpx.Auth | None = Field(
172
- default=None,
173
- description="Httpx Auth Scheme."
165
+ default=None, description="Httpx Auth Scheme."
174
166
  )
175
167
 
176
168
  model_config = ConfigDict(
@@ -189,7 +181,10 @@ class FlockFactory:
189
181
  @staticmethod
190
182
  def create_mcp_server(
191
183
  name: str,
192
- connection_params: StreamableHttpParams | SSEParams | StdioParams | WebsocketParams,
184
+ connection_params: StreamableHttpParams
185
+ | SSEParams
186
+ | StdioParams
187
+ | WebsocketParams,
193
188
  max_retries: int = 3,
194
189
  mount_points: list[str | MCPRoot] | None = None,
195
190
  timeout_seconds: int | float = 10,
@@ -212,7 +207,7 @@ class FlockFactory:
212
207
  tool_result_cache_ttl=100,
213
208
  description: str | Callable[..., str] | None = None,
214
209
  alert_latency_threshold_ms: int = 30000,
215
- ) -> FlockMCPServerBase:
210
+ ) -> FlockMCPServer:
216
211
  """Create a default MCP Server with common modules.
217
212
 
218
213
  Allows for creating one of the three default-implementations provided
@@ -251,19 +246,19 @@ class FlockFactory:
251
246
  continue # ignore
252
247
 
253
248
  # build generic configs
254
- feature_config = FlockMCPFeatureConfigurationBase(
249
+ feature_config = FlockMCPFeatureConfiguration(
255
250
  roots_enabled=enable_roots_feature,
256
251
  tools_enabled=enable_tools_feature,
257
252
  prompts_enabled=enable_prompts_feature,
258
253
  sampling_enabled=enable_sampling_feature,
259
254
  )
260
- callback_config = FlockMCPCallbackConfigurationBase(
255
+ callback_config = FlockMCPCallbackConfiguration(
261
256
  sampling_callback=sampling_callback,
262
257
  list_roots_callback=list_roots_callback,
263
258
  logging_callback=logging_callback,
264
259
  message_handler=message_handler,
265
260
  )
266
- caching_config = FlockMCPCachingConfigurationBase(
261
+ caching_config = FlockMCPCachingConfiguration(
267
262
  tool_cache_max_size=tool_cache_size,
268
263
  tool_cache_max_ttl=tool_cache_ttl,
269
264
  resource_contents_cache_max_size=resource_contents_cache_size,
@@ -375,30 +370,30 @@ class FlockFactory:
375
370
 
376
371
  if not server_config:
377
372
  raise ValueError(
378
- f"Unable to create server configuration for passed params."
373
+ "Unable to create server configuration for passed params."
379
374
  )
380
375
 
381
376
  server = concrete_server_cls(config=server_config)
382
377
 
383
- metrics_module_config = MetricsModuleConfig(
378
+ metrics_component_config = MetricsUtilityConfig(
384
379
  latency_threshold_ms=alert_latency_threshold_ms
385
380
  )
386
381
 
387
- metrics_module = MetricsModule("metrics", config=metrics_module_config)
382
+ metrics_component = MetricsUtilityComponent("metrics", config=metrics_component_config)
388
383
 
389
- server.add_module(metrics_module)
384
+ server.add_component(metrics_component)
390
385
 
391
386
  return server
392
387
 
393
388
  @staticmethod
394
389
  def create_default_agent(
395
390
  name: str,
396
- description: str | Callable[..., str] | None = None,
391
+ description: DynamicStr| None = None,
397
392
  model: str | Callable[..., str] | None = None,
398
- input: SignatureType = None,
399
- output: SignatureType = None,
393
+ input: DynamicStr = None,
394
+ output: DynamicStr = None,
400
395
  tools: list[Callable[..., Any] | Any] | None = None,
401
- servers: list[str | FlockMCPServerBase] | None = None,
396
+ servers: list[str | FlockMCPServer] | None = None,
402
397
  use_cache: bool = True,
403
398
  enable_rich_tables: bool = False,
404
399
  output_theme: OutputTheme = OutputTheme.abernathy,
@@ -414,18 +409,34 @@ class FlockFactory:
414
409
  stream: bool = False,
415
410
  include_thought_process: bool = False,
416
411
  include_reasoning: bool = False,
412
+ next_agent: DynamicStr | None = None,
417
413
  temporal_activity_config: TemporalActivityConfig | None = None,
418
414
  ) -> FlockAgent:
419
- """Creates a default FlockAgent.
415
+ """Creates a default FlockAgent using unified component architecture.
420
416
 
421
- The default agent includes the following modules:
422
- - DeclarativeEvaluator
423
- - OutputModule
424
- - MetricsModule
417
+ The default agent includes the following unified components:
418
+ - DeclarativeEvaluationComponent (core LLM evaluation)
419
+ - OutputUtilityComponent (result formatting and display)
420
+ - MetricsUtilityComponent (performance tracking)
425
421
 
426
- It also includes direct acces to the most important configurations.
422
+ This provides a complete, production-ready agent with sensible defaults.
427
423
  """
428
- eval_config = DeclarativeEvaluatorConfig(
424
+ # Import unified components locally to avoid circular imports
425
+ from flock.components.evaluation.declarative_evaluation_component import (
426
+ DeclarativeEvaluationComponent,
427
+ DeclarativeEvaluationConfig,
428
+ )
429
+ from flock.components.utility.metrics_utility_component import (
430
+ MetricsUtilityComponent,
431
+ MetricsUtilityConfig,
432
+ )
433
+ from flock.components.utility.output_utility_component import (
434
+ OutputUtilityComponent,
435
+ OutputUtilityConfig,
436
+ )
437
+
438
+ # Create evaluation component
439
+ eval_config = DeclarativeEvaluationConfig(
429
440
  model=model,
430
441
  use_cache=use_cache,
431
442
  max_tokens=max_tokens,
@@ -436,8 +447,30 @@ class FlockFactory:
436
447
  include_thought_process=include_thought_process,
437
448
  include_reasoning=include_reasoning,
438
449
  )
450
+ evaluator = DeclarativeEvaluationComponent(
451
+ name="default_evaluator", config=eval_config
452
+ )
453
+
454
+ # Create output utility component
455
+ output_config = OutputUtilityConfig(
456
+ render_table=enable_rich_tables,
457
+ theme=output_theme,
458
+ no_output=no_output,
459
+ print_context=print_context,
460
+ )
461
+ output_component = OutputUtilityComponent(
462
+ name="output_formatter", config=output_config
463
+ )
464
+
465
+ # Create metrics utility component
466
+ metrics_config = MetricsUtilityConfig(
467
+ latency_threshold_ms=alert_latency_threshold_ms
468
+ )
469
+ metrics_component = MetricsUtilityComponent(
470
+ name="metrics_tracker", config=metrics_config
471
+ )
439
472
 
440
- evaluator = DeclarativeEvaluator(name="default", config=eval_config)
473
+ # Create agent with unified components
441
474
  agent = FlockAgent(
442
475
  name=name,
443
476
  input=input,
@@ -446,65 +479,56 @@ class FlockFactory:
446
479
  servers=servers,
447
480
  model=model,
448
481
  description=description,
449
- evaluator=evaluator,
450
- write_to_file=write_to_file,
451
- wait_for_input=wait_for_input,
482
+ components=[evaluator, output_component, metrics_component],
483
+ config=FlockAgentConfig(write_to_file=write_to_file,
484
+ wait_for_input=wait_for_input),
485
+ next_agent=next_agent,
452
486
  temporal_activity_config=temporal_activity_config,
453
487
  )
454
- output_config = OutputModuleConfig(
455
- render_table=enable_rich_tables,
456
- theme=output_theme,
457
- no_output=no_output,
458
- print_context=print_context,
459
- )
460
- output_module = OutputModule("output", config=output_config)
461
-
462
- metrics_config = MetricsModuleConfig(
463
- latency_threshold_ms=alert_latency_threshold_ms
464
- )
465
- metrics_module = MetricsModule("metrics", config=metrics_config)
466
488
 
467
- agent.add_module(output_module)
468
- agent.add_module(metrics_module)
469
489
  return agent
470
490
 
471
491
  @staticmethod
472
492
  def create_scheduled_agent(
473
493
  name: str,
474
- schedule_expression: str, # e.g., "every 1h", "0 0 * * *"
475
- description: str | Callable[..., str] | None = None,
476
- model: str | Callable[..., str] | None = None,
477
- output: SignatureType = None, # Input might be implicit or none
494
+ schedule_expression: str, # e.g., "every 1h", "0 0 * * *"
495
+ description: DynamicStr | None = None,
496
+ model: str | None = None,
497
+ output: DynamicStr | None = None, # Input might be implicit or none
478
498
  tools: list[Callable[..., Any] | Any] | None = None,
479
- servers: list[str | FlockMCPServerBase] | None = None,
480
- use_cache: bool = False, # Whether to cache results
481
- temperature: float = 0.7, # Temperature for model responses
499
+ servers: list[str | FlockMCPServer] | None = None,
500
+ use_cache: bool = False, # Whether to cache results
501
+ temperature: float = 0.7, # Temperature for model responses
482
502
  # ... other common agent params from create_default_agent ...
483
- temporal_activity_config: TemporalActivityConfig | None = None, # If you want scheduled tasks to be Temporal activities
484
- **kwargs # Forward other standard agent params
503
+ next_agent: DynamicStr | None = None,
504
+ temporal_activity_config: TemporalActivityConfig
505
+ | None = None, # If you want scheduled tasks to be Temporal activities
506
+ **kwargs, # Forward other standard agent params
485
507
  ) -> FlockAgent:
486
508
  """Creates a FlockAgent configured to run on a schedule."""
487
- agent_config = ScheduledAgentConfig( # Use the new config type
509
+ agent_config = ScheduledAgentConfig( # Use the new config type
488
510
  schedule_expression=schedule_expression,
489
511
  enabled=True,
490
512
  initial_run=True,
491
513
  max_runs=0,
492
- **kwargs
514
+ **kwargs,
493
515
  )
494
516
 
495
-
496
- agent = FlockFactory.create_default_agent( # Reuse your existing factory
497
- name=name,
498
- description=description,
499
- model=model,
500
- input="trigger_time: str | Time of scheduled execution",
501
- output=output,
502
- tools=tools,
503
- servers=servers,
504
- temporal_activity_config=temporal_activity_config,
505
- use_cache=use_cache,
506
- temperature=temperature,
507
- **kwargs
517
+ agent = (
518
+ FlockFactory.create_default_agent( # Reuse your existing factory
519
+ name=name,
520
+ description=description,
521
+ model=model,
522
+ input="trigger_time: str | Time of scheduled execution",
523
+ output=output,
524
+ tools=tools,
525
+ servers=servers,
526
+ temporal_activity_config=temporal_activity_config,
527
+ use_cache=use_cache,
528
+ temperature=temperature,
529
+ next_agent=next_agent,
530
+ **kwargs,
531
+ )
508
532
  )
509
533
  agent.config = agent_config # Assign the scheduled agent config
510
534
 
@@ -76,7 +76,7 @@ class FlockScheduler:
76
76
  logger.info(f"Triggering scheduled agent '{agent.name}' at {trigger_time.isoformat()}")
77
77
  try:
78
78
  # Input for a scheduled agent could include the trigger time
79
- await self.flock.run_async(start_agent=agent.name, input={"trigger_time": trigger_time})
79
+ await self.flock.run_async(agent=agent.name, input={"trigger_time": trigger_time})
80
80
  logger.info(f"Scheduled agent '{agent.name}' finished successfully.")
81
81
  except Exception as e:
82
82
  logger.error(f"Error running scheduled agent '{agent.name}': {e}\n{traceback.format_exc()}")
@@ -6,13 +6,13 @@ from contextlib import AsyncExitStack
6
6
  from anyio import Lock
7
7
  from pydantic import BaseModel, ConfigDict, Field
8
8
 
9
- from flock.core.mcp.flock_mcp_server import FlockMCPServerBase
9
+ from flock.core.mcp.flock_mcp_server import FlockMCPServer
10
10
 
11
11
 
12
12
  class FlockServerManager(BaseModel):
13
13
  """Async-context-manager to start/stop a set of Flock MCP servers."""
14
14
 
15
- servers: list[FlockMCPServerBase] | None = Field(
15
+ servers: list[FlockMCPServer] | None = Field(
16
16
  ..., exclude=True, description="The servers to manage."
17
17
  )
18
18
 
@@ -32,7 +32,7 @@ class FlockServerManager(BaseModel):
32
32
 
33
33
  def __init__(
34
34
  self,
35
- servers: list[FlockMCPServerBase] | None = None,
35
+ servers: list[FlockMCPServer] | None = None,
36
36
  stack: AsyncExitStack | None = None,
37
37
  lock: asyncio.Lock | None = None,
38
38
  ) -> None:
@@ -43,7 +43,7 @@ class FlockServerManager(BaseModel):
43
43
  lock=lock,
44
44
  )
45
45
 
46
- def add_server_sync(self, server: FlockMCPServerBase) -> None:
46
+ def add_server_sync(self, server: FlockMCPServer) -> None:
47
47
  """Add a server to be managed by the ServerManager.
48
48
 
49
49
  Note:
@@ -57,7 +57,7 @@ class FlockServerManager(BaseModel):
57
57
 
58
58
  self.servers.append(server)
59
59
 
60
- def remove_server_sync(self, server: FlockMCPServerBase) -> None:
60
+ def remove_server_sync(self, server: FlockMCPServer) -> None:
61
61
  """Remove a server from the list of managed servers.
62
62
 
63
63
  Note:
@@ -71,7 +71,7 @@ class FlockServerManager(BaseModel):
71
71
 
72
72
  # -- For future use: Allow adding and removal of servers during runtime ---
73
73
  async def add_server_during_runtime(
74
- self, server: FlockMCPServerBase
74
+ self, server: FlockMCPServer
75
75
  ) -> None:
76
76
  """Add a server to the manager and, if already running, start it immediately."""
77
77
  if self.lock is None:
@@ -88,13 +88,13 @@ class FlockServerManager(BaseModel):
88
88
  await self.stack.enter_async_context(server)
89
89
 
90
90
  async def remove_server_during_runtime(
91
- self, server: FlockMCPServerBase
91
+ self, server: FlockMCPServer
92
92
  ) -> None:
93
93
  """Tear down and remove a server from the manager at runtime."""
94
94
  if self.lock is None:
95
95
  self.lock = asyncio.Lock()
96
96
 
97
- retrieved_server: FlockMCPServerBase | None = None
97
+ retrieved_server: FlockMCPServer | None = None
98
98
 
99
99
  async with self.lock:
100
100
  if not self.servers or server not in self.servers:
@@ -154,6 +154,7 @@ def color_for_category(category: str) -> str:
154
154
  if category in COLOR_MAP:
155
155
  return COLOR_MAP[category]
156
156
  parts = category.split(".")
157
+ # Try progressively shorter parent categories
157
158
  for i in range(len(parts) - 1, 0, -1):
158
159
  parent_category = ".".join(parts[:i])
159
160
  if parent_category in COLOR_MAP: