flock-core 0.4.519__py3-none-any.whl → 0.5.0b1__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 (103) hide show
  1. flock/cli/manage_agents.py +3 -3
  2. flock/components/__init__.py +28 -0
  3. flock/components/evaluation/__init__.py +9 -0
  4. flock/components/evaluation/declarative_evaluation_component.py +198 -0
  5. flock/components/routing/__init__.py +15 -0
  6. flock/{routers/conditional/conditional_router.py → components/routing/conditional_routing_component.py} +60 -49
  7. flock/components/routing/default_routing_component.py +103 -0
  8. flock/components/routing/llm_routing_component.py +208 -0
  9. flock/components/utility/__init__.py +15 -0
  10. flock/{modules/enterprise_memory/enterprise_memory_module.py → components/utility/memory_utility_component.py} +195 -173
  11. flock/{modules/performance/metrics_module.py → components/utility/metrics_utility_component.py} +101 -86
  12. flock/{modules/output/output_module.py → components/utility/output_utility_component.py} +49 -49
  13. flock/core/__init__.py +2 -8
  14. flock/core/agent/__init__.py +16 -0
  15. flock/core/agent/flock_agent_components.py +104 -0
  16. flock/core/agent/flock_agent_execution.py +101 -0
  17. flock/core/agent/flock_agent_integration.py +147 -0
  18. flock/core/agent/flock_agent_lifecycle.py +177 -0
  19. flock/core/agent/flock_agent_serialization.py +378 -0
  20. flock/core/component/__init__.py +15 -0
  21. flock/core/{flock_module.py → component/agent_component_base.py} +136 -35
  22. flock/core/component/evaluation_component_base.py +56 -0
  23. flock/core/component/routing_component_base.py +75 -0
  24. flock/core/component/utility_component_base.py +69 -0
  25. flock/core/config/flock_agent_config.py +49 -2
  26. flock/core/evaluation/utils.py +1 -1
  27. flock/core/execution/evaluation_executor.py +1 -1
  28. flock/core/flock.py +137 -483
  29. flock/core/flock_agent.py +151 -1018
  30. flock/core/flock_factory.py +94 -73
  31. flock/core/{flock_registry.py → flock_registry.py.backup} +3 -17
  32. flock/core/logging/logging.py +1 -0
  33. flock/core/mcp/flock_mcp_server.py +42 -37
  34. flock/core/mixin/dspy_integration.py +5 -5
  35. flock/core/orchestration/__init__.py +18 -0
  36. flock/core/orchestration/flock_batch_processor.py +94 -0
  37. flock/core/orchestration/flock_evaluator.py +113 -0
  38. flock/core/orchestration/flock_execution.py +288 -0
  39. flock/core/orchestration/flock_initialization.py +125 -0
  40. flock/core/orchestration/flock_server_manager.py +65 -0
  41. flock/core/orchestration/flock_web_server.py +117 -0
  42. flock/core/registry/__init__.py +39 -0
  43. flock/core/registry/agent_registry.py +69 -0
  44. flock/core/registry/callable_registry.py +139 -0
  45. flock/core/registry/component_discovery.py +142 -0
  46. flock/core/registry/component_registry.py +64 -0
  47. flock/core/registry/config_mapping.py +64 -0
  48. flock/core/registry/decorators.py +137 -0
  49. flock/core/registry/registry_hub.py +202 -0
  50. flock/core/registry/server_registry.py +57 -0
  51. flock/core/registry/type_registry.py +86 -0
  52. flock/core/serialization/flock_serializer.py +33 -30
  53. flock/core/serialization/serialization_utils.py +28 -25
  54. flock/core/util/input_resolver.py +29 -2
  55. flock/platform/docker_tools.py +3 -3
  56. flock/tools/markdown_tools.py +1 -2
  57. flock/tools/text_tools.py +1 -2
  58. flock/webapp/app/main.py +9 -5
  59. flock/workflow/activities.py +59 -84
  60. flock/workflow/activities_unified.py +230 -0
  61. flock/workflow/agent_execution_activity.py +6 -6
  62. flock/workflow/flock_workflow.py +1 -1
  63. {flock_core-0.4.519.dist-info → flock_core-0.5.0b1.dist-info}/METADATA +4 -4
  64. {flock_core-0.4.519.dist-info → flock_core-0.5.0b1.dist-info}/RECORD +67 -68
  65. flock/core/flock_evaluator.py +0 -60
  66. flock/core/flock_router.py +0 -83
  67. flock/evaluators/__init__.py +0 -1
  68. flock/evaluators/declarative/__init__.py +0 -1
  69. flock/evaluators/declarative/declarative_evaluator.py +0 -194
  70. flock/evaluators/memory/memory_evaluator.py +0 -90
  71. flock/evaluators/test/test_case_evaluator.py +0 -38
  72. flock/evaluators/zep/zep_evaluator.py +0 -59
  73. flock/modules/__init__.py +0 -1
  74. flock/modules/assertion/__init__.py +0 -1
  75. flock/modules/assertion/assertion_module.py +0 -286
  76. flock/modules/callback/__init__.py +0 -1
  77. flock/modules/callback/callback_module.py +0 -91
  78. flock/modules/enterprise_memory/README.md +0 -99
  79. flock/modules/mem0/__init__.py +0 -1
  80. flock/modules/mem0/mem0_module.py +0 -126
  81. flock/modules/mem0_async/__init__.py +0 -1
  82. flock/modules/mem0_async/async_mem0_module.py +0 -126
  83. flock/modules/memory/__init__.py +0 -1
  84. flock/modules/memory/memory_module.py +0 -429
  85. flock/modules/memory/memory_parser.py +0 -125
  86. flock/modules/memory/memory_storage.py +0 -736
  87. flock/modules/output/__init__.py +0 -1
  88. flock/modules/performance/__init__.py +0 -1
  89. flock/modules/zep/__init__.py +0 -1
  90. flock/modules/zep/zep_module.py +0 -192
  91. flock/routers/__init__.py +0 -1
  92. flock/routers/agent/__init__.py +0 -1
  93. flock/routers/agent/agent_router.py +0 -236
  94. flock/routers/agent/handoff_agent.py +0 -58
  95. flock/routers/default/__init__.py +0 -1
  96. flock/routers/default/default_router.py +0 -80
  97. flock/routers/feedback/feedback_router.py +0 -114
  98. flock/routers/list_generator/list_generator_router.py +0 -166
  99. flock/routers/llm/__init__.py +0 -1
  100. flock/routers/llm/llm_router.py +0 -365
  101. {flock_core-0.4.519.dist-info → flock_core-0.5.0b1.dist-info}/WHEEL +0 -0
  102. {flock_core-0.4.519.dist-info → flock_core-0.5.0b1.dist-info}/entry_points.txt +0 -0
  103. {flock_core-0.4.519.dist-info → flock_core-0.5.0b1.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,137 @@
1
+ # src/flock/core/registry/decorators.py
2
+ """Registry decorators for component, tool, and type registration."""
3
+
4
+ import inspect
5
+ from collections.abc import Callable
6
+ from typing import Any, TypeVar, overload
7
+
8
+ from flock.core.registry.registry_hub import get_registry
9
+
10
+ ClassType = TypeVar("ClassType", bound=type)
11
+ FuncType = TypeVar("FuncType", bound=Callable)
12
+ ConfigType = TypeVar("ConfigType")
13
+
14
+
15
+ # --- Component Registration Decorator ---
16
+
17
+ @overload
18
+ def flock_component(cls: ClassType) -> ClassType: ... # Basic registration
19
+
20
+
21
+ @overload
22
+ def flock_component(
23
+ *, name: str | None = None, config_class: type[ConfigType] | None = None
24
+ ) -> Callable[[ClassType], ClassType]: ... # With options
25
+
26
+
27
+ def flock_component(
28
+ cls: ClassType | None = None,
29
+ *,
30
+ name: str | None = None,
31
+ config_class: type[ConfigType] | None = None,
32
+ ) -> Any:
33
+ """Decorator to register a Flock Component class and optionally link its config class."""
34
+ registry = get_registry()
35
+
36
+ def decorator(inner_cls: ClassType) -> ClassType:
37
+ if not inspect.isclass(inner_cls):
38
+ raise TypeError("@flock_component can only decorate classes.")
39
+
40
+ component_name = name or inner_cls.__name__
41
+ registry.register_component(inner_cls, name=component_name)
42
+
43
+ # If config_class is provided, register the mapping
44
+ if config_class:
45
+ registry.register_config_component_pair(config_class, inner_cls)
46
+
47
+ return inner_cls
48
+
49
+ if cls is None:
50
+ # Called as @flock_component(name="...", config_class=...)
51
+ return decorator
52
+ else:
53
+ # Called as @flock_component
54
+ return decorator(cls)
55
+
56
+
57
+ # --- Tool/Callable Registration Decorator ---
58
+
59
+ @overload
60
+ def flock_tool(func: FuncType) -> FuncType: ...
61
+
62
+
63
+ @overload
64
+ def flock_tool(
65
+ *, name: str | None = None
66
+ ) -> Callable[[FuncType], FuncType]: ...
67
+
68
+
69
+ def flock_tool(func: FuncType | None = None, *, name: str | None = None) -> Any:
70
+ """Decorator to register a callable function/method as a Tool (or general callable).
71
+
72
+ Usage:
73
+ @flock_tool
74
+ def my_web_search(query: str): ...
75
+
76
+ @flock_tool(name="utils.calculate_pi")
77
+ def compute_pi(): ...
78
+ """
79
+ registry = get_registry()
80
+
81
+ def decorator(inner_func: FuncType) -> FuncType:
82
+ if not callable(inner_func):
83
+ raise TypeError("@flock_tool can only decorate callables.")
84
+ # Let registry handle default name generation if None
85
+ registry.register_callable(inner_func, name=name)
86
+ return inner_func
87
+
88
+ if func is None:
89
+ # Called as @flock_tool(name="...")
90
+ return decorator
91
+ else:
92
+ # Called as @flock_tool
93
+ return decorator(func)
94
+
95
+
96
+ # Alias for clarity
97
+ flock_callable = flock_tool
98
+
99
+
100
+ # --- Type Registration Decorator ---
101
+
102
+ @overload
103
+ def flock_type(cls: ClassType) -> ClassType: ...
104
+
105
+
106
+ @overload
107
+ def flock_type(
108
+ *, name: str | None = None
109
+ ) -> Callable[[ClassType], ClassType]: ...
110
+
111
+
112
+ def flock_type(cls: ClassType | None = None, *, name: str | None = None) -> Any:
113
+ """Decorator to register a Type (Pydantic Model, Dataclass) used in signatures.
114
+
115
+ Usage:
116
+ @flock_type
117
+ class MyDataModel(BaseModel): ...
118
+
119
+ @flock_type(name="UserInput")
120
+ @dataclass
121
+ class UserQuery: ...
122
+ """
123
+ registry = get_registry()
124
+
125
+ def decorator(inner_cls: ClassType) -> ClassType:
126
+ if not inspect.isclass(inner_cls):
127
+ raise TypeError("@flock_type can only decorate classes.")
128
+ type_name = name or inner_cls.__name__
129
+ registry.register_type(inner_cls, name=type_name)
130
+ return inner_cls
131
+
132
+ if cls is None:
133
+ # Called as @flock_type(name="...")
134
+ return decorator
135
+ else:
136
+ # Called as @flock_type
137
+ return decorator(cls)
@@ -0,0 +1,202 @@
1
+ # src/flock/core/registry/registry_hub.py
2
+ """Main registry hub using composition pattern with thread safety."""
3
+
4
+ import threading
5
+ from typing import TYPE_CHECKING, Any, TypeVar
6
+
7
+ from flock.core.logging.logging import get_logger
8
+
9
+ if TYPE_CHECKING:
10
+ from collections.abc import Callable
11
+ from flock.core.flock_agent import FlockAgent
12
+ from flock.core.mcp.flock_mcp_server import FlockMCPServerBase
13
+
14
+ logger = get_logger("registry.hub")
15
+
16
+ T = TypeVar("T")
17
+ ConfigType = TypeVar("ConfigType")
18
+ ClassType = TypeVar("ClassType")
19
+
20
+
21
+ class RegistryHub:
22
+ """Thread-safe registry hub using composition pattern.
23
+
24
+ Main coordinator for all registry types following the successful
25
+ pattern from Flock and FlockAgent refactoring.
26
+ """
27
+
28
+ def __init__(self):
29
+ self._lock = threading.RLock()
30
+ logger.debug("RegistryHub initialized with thread safety")
31
+
32
+ # --- Lazy-loaded composition helpers (following Flock pattern) ---
33
+
34
+ @property
35
+ def components(self):
36
+ """Component class registry helper."""
37
+ if not hasattr(self, '_components_helper'):
38
+ from flock.core.registry.component_registry import ComponentRegistry
39
+ self._components_helper = ComponentRegistry(self._lock)
40
+ return self._components_helper
41
+
42
+ @property
43
+ def callables(self):
44
+ """Callable registry helper."""
45
+ if not hasattr(self, '_callables_helper'):
46
+ from flock.core.registry.callable_registry import CallableRegistry
47
+ self._callables_helper = CallableRegistry(self._lock)
48
+ return self._callables_helper
49
+
50
+ @property
51
+ def agents(self):
52
+ """Agent registry helper."""
53
+ if not hasattr(self, '_agents_helper'):
54
+ from flock.core.registry.agent_registry import AgentRegistry
55
+ self._agents_helper = AgentRegistry(self._lock)
56
+ return self._agents_helper
57
+
58
+ @property
59
+ def servers(self):
60
+ """Server registry helper."""
61
+ if not hasattr(self, '_servers_helper'):
62
+ from flock.core.registry.server_registry import ServerRegistry
63
+ self._servers_helper = ServerRegistry(self._lock)
64
+ return self._servers_helper
65
+
66
+ @property
67
+ def types(self):
68
+ """Type registry helper."""
69
+ if not hasattr(self, '_types_helper'):
70
+ from flock.core.registry.type_registry import TypeRegistry
71
+ self._types_helper = TypeRegistry(self._lock)
72
+ return self._types_helper
73
+
74
+ @property
75
+ def config_mapping(self):
76
+ """Config mapping helper."""
77
+ if not hasattr(self, '_config_mapping_helper'):
78
+ from flock.core.registry.config_mapping import ConfigMapping
79
+ self._config_mapping_helper = ConfigMapping(self._lock)
80
+ return self._config_mapping_helper
81
+
82
+ @property
83
+ def discovery(self):
84
+ """Component discovery helper."""
85
+ if not hasattr(self, '_discovery_helper'):
86
+ from flock.core.registry.component_discovery import ComponentDiscovery
87
+ self._discovery_helper = ComponentDiscovery(self)
88
+ return self._discovery_helper
89
+
90
+ # --- High-level registry operations (delegate to helpers) ---
91
+
92
+ def register_agent(self, agent: "FlockAgent", *, force: bool = False) -> None:
93
+ """Register a FlockAgent instance."""
94
+ self.agents.register_agent(agent, force=force)
95
+
96
+ def get_agent(self, name: str) -> "FlockAgent | None":
97
+ """Get a registered FlockAgent instance by name."""
98
+ return self.agents.get_agent(name)
99
+
100
+ def get_all_agent_names(self) -> list[str]:
101
+ """Get all registered agent names."""
102
+ return self.agents.get_all_agent_names()
103
+
104
+ def register_server(self, server: "FlockMCPServerBase") -> None:
105
+ """Register a FlockMCPServer instance."""
106
+ self.servers.register_server(server)
107
+
108
+ def get_server(self, name: str) -> "FlockMCPServerBase | None":
109
+ """Get a registered FlockMCPServer instance by name."""
110
+ return self.servers.get_server(name)
111
+
112
+ def get_all_server_names(self) -> list[str]:
113
+ """Get all registered server names."""
114
+ return self.servers.get_all_server_names()
115
+
116
+ def register_callable(self, func: "Callable", name: str | None = None) -> str | None:
117
+ """Register a callable function/method."""
118
+ return self.callables.register_callable(func, name)
119
+
120
+ def get_callable(self, name_or_path: str) -> "Callable":
121
+ """Get a registered callable by name or path."""
122
+ return self.callables.get_callable(name_or_path)
123
+
124
+ def get_callable_path_string(self, func: "Callable") -> str | None:
125
+ """Get the path string for a callable."""
126
+ return self.callables.get_callable_path_string(func)
127
+
128
+ def register_type(self, type_obj: type, name: str | None = None) -> str | None:
129
+ """Register a type (Pydantic Model, Dataclass, etc.)."""
130
+ return self.types.register_type(type_obj, name)
131
+
132
+ def get_type(self, type_name: str) -> type:
133
+ """Get a registered type by name."""
134
+ return self.types.get_type(type_name)
135
+
136
+ def register_component(self, component_class: type, name: str | None = None) -> str | None:
137
+ """Register a component class."""
138
+ return self.components.register_component(component_class, name)
139
+
140
+ def get_component(self, type_name: str) -> type:
141
+ """Get a registered component class by name."""
142
+ return self.components.get_component(type_name)
143
+
144
+ def get_component_type_name(self, component_class: type) -> str | None:
145
+ """Get the type name for a component class."""
146
+ return self.components.get_component_type_name(component_class)
147
+
148
+ def register_config_component_pair(self, config_cls: type[ConfigType], component_cls: type[ClassType]) -> None:
149
+ """Register a config-to-component mapping."""
150
+ self.config_mapping.register_config_component_pair(config_cls, component_cls)
151
+
152
+ def get_component_class_for_config(self, config_cls: type[ConfigType]) -> type[ClassType] | None:
153
+ """Get the component class for a config class."""
154
+ return self.config_mapping.get_component_class_for_config(config_cls)
155
+
156
+ def discover_and_register_components(self) -> None:
157
+ """Auto-discover and register components from known packages."""
158
+ self.discovery.discover_and_register_components()
159
+
160
+ def register_module_components(self, module_or_path: Any) -> None:
161
+ """Register components from a specific module."""
162
+ self.discovery.register_module_components(module_or_path)
163
+
164
+ # --- Utility methods ---
165
+
166
+ def clear_all(self) -> None:
167
+ """Clear all registries (useful for testing)."""
168
+ with self._lock:
169
+ if hasattr(self, '_agents_helper'):
170
+ self.agents.clear()
171
+ if hasattr(self, '_servers_helper'):
172
+ self.servers.clear()
173
+ if hasattr(self, '_callables_helper'):
174
+ self.callables.clear()
175
+ if hasattr(self, '_types_helper'):
176
+ self.types.clear()
177
+ if hasattr(self, '_components_helper'):
178
+ self.components.clear()
179
+ if hasattr(self, '_config_mapping_helper'):
180
+ self.config_mapping.clear_config_mappings()
181
+ logger.debug("Cleared all registries")
182
+
183
+ def get_registry_summary(self) -> dict[str, int]:
184
+ """Get a summary of all registries."""
185
+ with self._lock:
186
+ return {
187
+ "agents": len(self.agents.get_all_agents()),
188
+ "servers": len(self.servers.get_all_servers()),
189
+ "callables": len(self.callables.get_all_callables()),
190
+ "types": len(self.types.get_all_types()),
191
+ "components": len(self.components.get_all_components()),
192
+ "config_mappings": len(self.config_mapping.get_all_config_mappings()),
193
+ }
194
+
195
+
196
+ # --- Global singleton instance ---
197
+ _default_registry_hub = RegistryHub()
198
+
199
+
200
+ def get_registry() -> RegistryHub:
201
+ """Get the default thread-safe registry hub instance."""
202
+ return _default_registry_hub
@@ -0,0 +1,57 @@
1
+ # src/flock/core/registry/server_registry.py
2
+ """MCP Server registration and lookup functionality."""
3
+
4
+ import threading
5
+ from typing import TYPE_CHECKING
6
+
7
+ from flock.core.logging.logging import get_logger
8
+
9
+ if TYPE_CHECKING:
10
+ from flock.core.mcp.flock_mcp_server import FlockMCPServerBase
11
+
12
+ logger = get_logger("registry.servers")
13
+
14
+
15
+ class ServerRegistry:
16
+ """Manages FlockMCPServerBase registration and lookup with thread safety."""
17
+
18
+ def __init__(self, lock: threading.RLock):
19
+ self._lock = lock
20
+ self._servers: dict[str, "FlockMCPServerBase"] = {}
21
+
22
+ def register_server(self, server: "FlockMCPServerBase") -> None:
23
+ """Register a flock mcp server by its name."""
24
+ if not hasattr(server.config, "name") or not server.config.name:
25
+ logger.error("Attempted to register a server without a valid 'name' attribute.")
26
+ return
27
+
28
+ with self._lock:
29
+ if server.config.name in self._servers and self._servers[server.config.name] != server:
30
+ logger.warning(f"Server '{server.config.name}' already registered. Overwriting.")
31
+
32
+ self._servers[server.config.name] = server
33
+ logger.debug(f"Registered server: {server.config.name}")
34
+
35
+ def get_server(self, name: str) -> "FlockMCPServerBase | None":
36
+ """Retrieve a registered FlockMCPServer instance by name."""
37
+ with self._lock:
38
+ server = self._servers.get(name)
39
+ if not server:
40
+ logger.warning(f"Server '{name}' not found in registry.")
41
+ return server
42
+
43
+ def get_all_server_names(self) -> list[str]:
44
+ """Return a list of names for all registered servers."""
45
+ with self._lock:
46
+ return list(self._servers.keys())
47
+
48
+ def get_all_servers(self) -> dict[str, "FlockMCPServerBase"]:
49
+ """Get all registered servers."""
50
+ with self._lock:
51
+ return self._servers.copy()
52
+
53
+ def clear(self) -> None:
54
+ """Clear all registered servers."""
55
+ with self._lock:
56
+ self._servers.clear()
57
+ logger.debug("Cleared all registered servers")
@@ -0,0 +1,86 @@
1
+ # src/flock/core/registry/type_registry.py
2
+ """Type registration and lookup functionality."""
3
+
4
+ import threading
5
+ from typing import Any, Literal, Mapping, Optional, Sequence, TypeVar, Union
6
+
7
+ from flock.core.logging.logging import get_logger
8
+
9
+ logger = get_logger("registry.types")
10
+
11
+
12
+ class TypeRegistry:
13
+ """Manages type registration and lookup with thread safety."""
14
+
15
+ def __init__(self, lock: threading.RLock):
16
+ self._lock = lock
17
+ self._types: dict[str, type] = {}
18
+ self._register_core_types()
19
+
20
+ def register_type(self, type_obj: type, name: str | None = None) -> str | None:
21
+ """Register a class/type (Pydantic, Dataclass, etc.) used in signatures."""
22
+ type_name = name or type_obj.__name__
23
+ if not type_name:
24
+ logger.error(f"Could not determine name for type: {type_obj}")
25
+ return None
26
+
27
+ with self._lock:
28
+ if type_name in self._types and self._types[type_name] != type_obj:
29
+ logger.warning(f"Type '{type_name}' already registered. Overwriting.")
30
+
31
+ self._types[type_name] = type_obj
32
+ logger.debug(f"Registered type: {type_name}")
33
+ return type_name
34
+
35
+ def get_type(self, type_name: str) -> type:
36
+ """Retrieve a registered type by its name."""
37
+ with self._lock:
38
+ if type_name in self._types:
39
+ return self._types[type_name]
40
+
41
+ # Consider adding dynamic import attempts for types if needed,
42
+ # but explicit registration is generally safer for types.
43
+ logger.warning(f"Type '{type_name}' not found in registry. Will attempt to build it from builtins.")
44
+ raise KeyError(f"Type '{type_name}' not found. Ensure it is registered.")
45
+
46
+ def get_all_types(self) -> dict[str, type]:
47
+ """Get all registered types."""
48
+ with self._lock:
49
+ return self._types.copy()
50
+
51
+ def clear(self) -> None:
52
+ """Clear all registered types (except core types)."""
53
+ with self._lock:
54
+ # Save core types
55
+ core_types = {
56
+ name: type_obj for name, type_obj in self._types.items()
57
+ if type_obj in [str, int, float, bool, list, dict, tuple, set, Any, Mapping, Sequence, TypeVar, Literal, Optional, Union]
58
+ }
59
+ self._types.clear()
60
+ self._types.update(core_types)
61
+ logger.debug("Cleared all registered types (keeping core types)")
62
+
63
+ def _register_core_types(self):
64
+ """Register common built-in and typing types."""
65
+ core_types = [
66
+ str,
67
+ int,
68
+ float,
69
+ bool,
70
+ list,
71
+ dict,
72
+ tuple,
73
+ set,
74
+ Any,
75
+ Mapping,
76
+ Sequence,
77
+ TypeVar,
78
+ Literal,
79
+ Optional,
80
+ Union, # Common typing generics
81
+ ]
82
+ for t in core_types:
83
+ try:
84
+ self.register_type(t)
85
+ except Exception as e:
86
+ logger.error(f"Failed to auto-register core type {t}: {e}")
@@ -1,7 +1,6 @@
1
1
  # src/flock/core/serialization/flock_serializer.py
2
2
  """Handles serialization and deserialization logic for Flock instances."""
3
3
 
4
- import builtins
5
4
  import importlib
6
5
  import importlib.util
7
6
  import inspect
@@ -14,7 +13,7 @@ from typing import TYPE_CHECKING, Any, Literal
14
13
  from pydantic import BaseModel, create_model
15
14
 
16
15
  # Need registry access
17
- from flock.core.flock_registry import get_registry
16
+ from flock.core.registry import get_registry
18
17
  from flock.core.logging.logging import get_logger
19
18
  from flock.core.serialization.serialization_utils import (
20
19
  # Assuming this handles basic serialization needs
@@ -26,7 +25,7 @@ if TYPE_CHECKING:
26
25
 
27
26
 
28
27
  logger = get_logger("serialization.flock")
29
- FlockRegistry = get_registry()
28
+ registry = get_registry()
30
29
 
31
30
 
32
31
  class FlockSerializer:
@@ -186,7 +185,7 @@ class FlockSerializer:
186
185
  "description_callable"
187
186
  ]
188
187
  description_callable = agent_instance.description
189
- path_str = FlockRegistry.get_callable_path_string(
188
+ path_str = registry.get_callable_path_string(
190
189
  description_callable
191
190
  )
192
191
  if path_str:
@@ -205,7 +204,7 @@ class FlockSerializer:
205
204
  )
206
205
  input_callable_name = agent_data["input_callable"]
207
206
  input_callable = agent_instance.input
208
- path_str = FlockRegistry.get_callable_path_string(
207
+ path_str = registry.get_callable_path_string(
209
208
  input_callable
210
209
  )
211
210
  if path_str:
@@ -224,7 +223,7 @@ class FlockSerializer:
224
223
  )
225
224
  output_callable_name = agent_data["output_callable"]
226
225
  output_callable = agent_instance.output
227
- path_str = FlockRegistry.get_callable_path_string(
226
+ path_str = registry.get_callable_path_string(
228
227
  output_callable
229
228
  )
230
229
  if path_str:
@@ -250,7 +249,7 @@ class FlockSerializer:
250
249
  tool = tool_objs[i]
251
250
  if callable(tool) and not isinstance(tool, type):
252
251
  path_str = (
253
- FlockRegistry.get_callable_path_string(tool)
252
+ registry.get_callable_path_string(tool)
254
253
  )
255
254
  if path_str:
256
255
  logger.debug(
@@ -415,7 +414,7 @@ class FlockSerializer:
415
414
  type_definitions = {}
416
415
  for type_name in type_names:
417
416
  try:
418
- type_obj = FlockRegistry.get_type(
417
+ type_obj = registry.get_type(
419
418
  type_name
420
419
  ) # Throws KeyError if not found
421
420
  type_def = FlockSerializer._extract_type_definition(
@@ -490,7 +489,7 @@ class FlockSerializer:
490
489
  "file_path": None,
491
490
  }
492
491
  try:
493
- component_class = FlockRegistry.get_component(
492
+ component_class = registry.get_component(
494
493
  component_type_name
495
494
  ) # Raises KeyError if not found
496
495
  component_def["module_path"] = getattr(
@@ -540,7 +539,7 @@ class FlockSerializer:
540
539
  "file_path": None,
541
540
  }
542
541
  try:
543
- func = FlockRegistry.get_callable(
542
+ func = registry.get_callable(
544
543
  callable_path
545
544
  ) # Raises KeyError if not found
546
545
  callable_def["module_path"] = getattr(func, "__module__", "unknown")
@@ -596,7 +595,7 @@ class FlockSerializer:
596
595
  module = importlib.import_module(module_path)
597
596
  if hasattr(module, type_name):
598
597
  type_obj = getattr(module, type_name)
599
- FlockRegistry.register_type(type_obj, type_name)
598
+ registry.register_type(type_obj, type_name)
600
599
  logger.info(
601
600
  f"Registered type '{type_name}' from module '{module_path}'"
602
601
  )
@@ -629,7 +628,7 @@ class FlockSerializer:
629
628
  type_name: str, type_def: dict[str, Any]
630
629
  ) -> None:
631
630
  """Dynamically create and register a Pydantic model from schema."""
632
- # (Logic remains the same, ensure it uses FlockRegistry.register_type)
631
+ # (Logic remains the same, ensure it uses registry.register_type)
633
632
  schema = type_def.get("schema", {})
634
633
  try:
635
634
  fields = {}
@@ -641,7 +640,7 @@ class FlockSerializer:
641
640
  fields[field_name] = (field_type, default)
642
641
 
643
642
  DynamicModel = create_model(type_name, **fields)
644
- FlockRegistry.register_type(DynamicModel, type_name)
643
+ registry.register_type(DynamicModel, type_name)
645
644
  logger.info(
646
645
  f"Dynamically created and registered Pydantic model: {type_name}"
647
646
  )
@@ -672,27 +671,31 @@ class FlockSerializer:
672
671
  @staticmethod
673
672
  def _create_dataclass(type_name: str, type_def: dict[str, Any]) -> None:
674
673
  """Dynamically create and register a dataclass."""
675
- # (Logic remains the same, ensure it uses FlockRegistry.register_type)
674
+ # (Logic remains the same, ensure it uses registry.register_type)
676
675
  from dataclasses import make_dataclass
677
676
 
678
677
  fields_def = type_def.get("fields", {})
679
678
  try:
680
679
  fields = []
681
680
  for field_name, field_props in fields_def.items():
682
- # Safely evaluate type string - requires care!
681
+ # Safely map type strings to actual types
683
682
  field_type_str = field_props.get("type", "str")
684
- try:
685
- field_type = eval(
686
- field_type_str,
687
- {"__builtins__": builtins.__dict__},
688
- {"List": list, "Dict": dict},
689
- ) # Allow basic types
690
- except Exception:
691
- field_type = Any
683
+ type_mapping = {
684
+ "str": str,
685
+ "int": int,
686
+ "float": float,
687
+ "bool": bool,
688
+ "list": list,
689
+ "dict": dict,
690
+ "List": list,
691
+ "Dict": dict,
692
+ "Any": Any,
693
+ }
694
+ field_type = type_mapping.get(field_type_str, Any)
692
695
  fields.append((field_name, field_type))
693
696
 
694
697
  DynamicDataclass = make_dataclass(type_name, fields)
695
- FlockRegistry.register_type(DynamicDataclass, type_name)
698
+ registry.register_type(DynamicDataclass, type_name)
696
699
  logger.info(
697
700
  f"Dynamically created and registered dataclass: {type_name}"
698
701
  )
@@ -705,7 +708,7 @@ class FlockSerializer:
705
708
  path_type: Literal["absolute", "relative"],
706
709
  ) -> None:
707
710
  """Register component/callable definitions from serialized data."""
708
- # (Logic remains the same, ensure it uses FlockRegistry.register_component/register_callable)
711
+ # (Logic remains the same, ensure it uses registry.register_component/register_callable)
709
712
  # Key change: Ensure file_path is handled correctly based on path_type from metadata
710
713
  for name, comp_def in component_defs.items():
711
714
  logger.debug(
@@ -735,13 +738,13 @@ class FlockSerializer:
735
738
  if hasattr(module, name):
736
739
  obj = getattr(module, name)
737
740
  if kind == "flock_callable" and callable(obj):
738
- FlockRegistry.register_callable(
741
+ registry.register_callable(
739
742
  obj, name
740
743
  ) # Register by simple name
741
744
  # Also register by full path if possible
742
745
  full_path = f"{module_path}.{name}"
743
746
  if full_path != name:
744
- FlockRegistry.register_callable(obj, full_path)
747
+ registry.register_callable(obj, full_path)
745
748
  logger.info(
746
749
  f"Registered callable '{name}' from module '{module_path}'"
747
750
  )
@@ -749,7 +752,7 @@ class FlockSerializer:
749
752
  elif kind == "flock_component" and isinstance(
750
753
  obj, type
751
754
  ):
752
- FlockRegistry.register_component(obj, name)
755
+ registry.register_component(obj, name)
753
756
  logger.info(
754
757
  f"Registered component '{name}' from module '{module_path}'"
755
758
  )
@@ -785,14 +788,14 @@ class FlockSerializer:
785
788
  if hasattr(module, name):
786
789
  obj = getattr(module, name)
787
790
  if kind == "flock_callable" and callable(obj):
788
- FlockRegistry.register_callable(obj, name)
791
+ registry.register_callable(obj, name)
789
792
  logger.info(
790
793
  f"Registered callable '{name}' from file '{file_path}'"
791
794
  )
792
795
  elif kind == "flock_component" and isinstance(
793
796
  obj, type
794
797
  ):
795
- FlockRegistry.register_component(obj, name)
798
+ registry.register_component(obj, name)
796
799
  logger.info(
797
800
  f"Registered component '{name}' from file '{file_path}'"
798
801
  )