Initialize the memory context manager.
(self, memory_names: Optional[List[str]] = None)
| 70 | self._variables_lock = asyncio.Lock() # Lock for get/set trainable variables |
| 71 | |
| 72 | async def initialize(self, memory_names: Optional[List[str]] = None): |
| 73 | """Initialize the memory context manager.""" |
| 74 | # Register memory-related symbols for auto-injection in dynamic code |
| 75 | dynamic_manager.register_symbol("MEMORY_SYSTEM", MEMORY_SYSTEM) |
| 76 | dynamic_manager.register_symbol("Memory", Memory) |
| 77 | |
| 78 | # Register memory context provider for automatic import injection |
| 79 | def memory_context_provider(): |
| 80 | """Provide memory-related imports for dynamic memory classes.""" |
| 81 | return { |
| 82 | "MEMORY_SYSTEM": MEMORY_SYSTEM, |
| 83 | "Memory": Memory, |
| 84 | } |
| 85 | dynamic_manager.register_context_provider("memory", memory_context_provider) |
| 86 | |
| 87 | # Load memory systems from MEMORY_SYSTEM registry |
| 88 | memory_configs = {} |
| 89 | registry_memory_configs: Dict[str, MemoryConfig] = await self._load_from_registry() |
| 90 | memory_configs.update(registry_memory_configs) |
| 91 | |
| 92 | # Load memory systems from code (JSON file) |
| 93 | code_memory_configs: Dict[str, MemoryConfig] = await self._load_from_code() |
| 94 | |
| 95 | # Merge code configs with registry configs, only override if code version is strictly greater |
| 96 | for memory_name, code_config in code_memory_configs.items(): |
| 97 | if memory_name in memory_configs: |
| 98 | registry_config = memory_configs[memory_name] |
| 99 | # Compare versions: only override if code version is strictly greater |
| 100 | if version_manager.compare_versions(code_config.version, registry_config.version) > 0: |
| 101 | logger.info(f"| 🔄 Overriding memory {memory_name} from registry (v{registry_config.version}) with code version (v{code_config.version})") |
| 102 | memory_configs[memory_name] = code_config |
| 103 | else: |
| 104 | logger.info(f"| 📌 Keeping memory {memory_name} from registry (v{registry_config.version}), code version (v{code_config.version}) is not greater") |
| 105 | # If versions are equal, update the history with registry config (which has real class, not dynamic) |
| 106 | if version_manager.compare_versions(code_config.version, registry_config.version) == 0: |
| 107 | # Replace the code config in history with registry config to preserve real class reference |
| 108 | if memory_name in self._memory_history_versions: |
| 109 | self._memory_history_versions[memory_name][registry_config.version] = registry_config |
| 110 | else: |
| 111 | # New memory from code, add it |
| 112 | memory_configs[memory_name] = code_config |
| 113 | |
| 114 | # Filter memory systems by names if provided |
| 115 | if memory_names is not None: |
| 116 | memory_configs = {name: memory_configs[name] for name in memory_names if name in memory_configs} |
| 117 | |
| 118 | # Build all memory systems concurrently with a concurrency limit |
| 119 | memory_names_list = list(memory_configs.keys()) |
| 120 | tasks = [ |
| 121 | self.build(memory_configs[name]) for name in memory_names_list |
| 122 | ] |
| 123 | results = await gather_with_concurrency(tasks, max_concurrency=10, return_exceptions=True) |
| 124 | |
| 125 | for memory_name, result in zip(memory_names_list, results): |
| 126 | if isinstance(result, Exception): |
| 127 | logger.error(f"| ❌ Failed to initialize memory {memory_name}: {result}") |
| 128 | continue |
| 129 | self._memory_configs[memory_name] = result |
no test coverage detected