11# src/agent_core/agents/actions/action_registry.py
22"""
33Defines the ActionRegistry, a singleton object that discovers and manages
4- all available actions in the simulation.
4+ all available actions in the simulation. This version is designed to be
5+ "override-friendly" for testing purposes.
56"""
67
78import importlib
1314class ActionRegistry :
1415 """
1516 A registry for discovering, storing, and retrieving action classes.
17+
18+ In its default mode (`strict=False`), it allows new actions to override
19+ existing actions with the same `action_id`. This is useful in testing
20+ environments where multiple simulations define their own version of a
21+ common action (e.g., 'move').
22+
23+ In `strict=True` mode, it will raise a ValueError if a duplicate
24+ action_id is registered, which is useful for production to prevent
25+ accidental naming collisions.
1626 """
1727
18- def __init__ (self ) -> None :
28+ def __init__ (self , strict : bool = False ) -> None :
1929 self ._actions : Dict [str , Type [ActionInterface ]] = {}
20- print ("ActionRegistry initialized." )
30+ self .strict = strict
31+ print (
32+ f"ActionRegistry initialized in { 'strict' if self .strict else 'override' } mode."
33+ )
2134
2235 def load_actions_from_paths (self , module_paths : List [str ]) -> None :
2336 """
2437 Dynamically imports Python modules from a list of string paths.
25-
26- This is the core of the plugin system. Importing a module that
27- contains an @action_registry.register decorator will cause that
28- action to be registered.
29-
30- Args:
31- module_paths: A list of module paths, e.g.,
32- ["simulations.soul_sim.actions.move_action"].
3338 """
3439 print (f"Dynamically loading actions from: { module_paths } " )
3540 for path in module_paths :
@@ -64,9 +69,11 @@ def register(self, action_class: Type[ActionInterface]) -> Type[ActionInterface]
6469 f"Action class { action_class .__name__ } has an invalid 'action_id' property."
6570 )
6671
67- if action_id in self ._actions :
72+ # Only raise an error if the registry is in strict mode.
73+ if action_id in self ._actions and self .strict :
6874 raise ValueError (f"Action with ID '{ action_id } ' is already registered." )
6975
76+ # Silently override the existing action if not in strict mode.
7077 self ._actions [action_id ] = action_class
7178 print (f"Action '{ action_name } ' registered with ID '{ action_id } '." )
7279 return action_class
@@ -88,6 +95,5 @@ def action_ids(self) -> List[str]:
8895 return sorted (self ._actions .keys ())
8996
9097
91- # Create a global singleton instance of the registry.
92- # All other parts of the application will import this instance.
93- action_registry = ActionRegistry ()
98+ # Create a global singleton instance of the registry in non-strict mode.
99+ action_registry = ActionRegistry (strict = False )
0 commit comments