Files

155 lines
4.6 KiB
Python

"""Plugin interface and registry for memory backends."""
from enum import Enum
from typing import Any, Dict, List, Optional, Protocol, runtime_checkable
class Capability(str, Enum):
"""Memory backend capabilities."""
VECTOR_SEARCH = "vector_search"
FULL_TEXT_SEARCH = "full_text_search"
STRUCTURED_QUERY = "structured_query"
PERSISTENCE = "persistence"
EMBEDDINGS = "embeddings"
GRAPH_QUERIES = "graph_queries"
TIME_SERIES = "time_series"
MARKDOWN_IMPORT = "markdown_import"
@runtime_checkable
class MemoryBackendPlugin(Protocol):
"""Interface for memory backend plugins."""
@property
def name(self) -> str:
"""Unique name of the backend."""
...
@property
def capabilities(self) -> List[Capability]:
"""List of capabilities provided by this backend."""
...
async def initialize(self) -> None:
"""Initialize the backend."""
...
async def shutdown(self) -> None:
"""Shutdown the backend."""
...
async def store_memory(
self,
content: str,
metadata: Dict[str, Any],
user_id: str = "default",
project_id: str = "default",
) -> str:
"""Store a memory and return its ID."""
...
async def retrieve_memory(
self,
query: str,
user_id: str = "default",
project_id: str = "default",
limit: int = 10,
) -> List[Dict[str, Any]]:
"""Retrieve memories based on query."""
...
async def search_memory(
self,
query: str,
user_id: str = "default",
project_id: str = "default",
limit: int = 10,
) -> List[Dict[str, Any]]:
"""Search memories based on query with scoring."""
...
async def delete_memory(
self, memory_id: str, user_id: str = "default", project_id: str = "default"
) -> bool:
"""Delete a memory by ID."""
...
class PluginRegistry:
"""Registry for memory backend plugins."""
def __init__(self) -> None:
self._plugins: Dict[str, MemoryBackendPlugin] = {}
self._active_plugins: List[str] = []
self._initialized: bool = False
def register_plugin(self, plugin: MemoryBackendPlugin) -> None:
"""Register a new plugin."""
self._plugins[plugin.name] = plugin
def unregister_plugin(self, name: str) -> bool:
"""Unregister a plugin."""
if name in self._plugins:
del self._plugins[name]
if name in self._active_plugins:
self._active_plugins.remove(name)
return True
return False
def enable_plugin(self, name: str) -> bool:
"""Enable a registered plugin."""
if name in self._plugins and name not in self._active_plugins:
self._active_plugins.append(name)
return True
return False
def disable_plugin(self, name: str) -> bool:
"""Disable an active plugin."""
if name in self._active_plugins:
self._active_plugins.remove(name)
return True
return False
def get_plugin(self, name: str) -> Optional[MemoryBackendPlugin]:
"""Get a specific plugin."""
return self._plugins.get(name)
def get_active_plugins(self) -> List[MemoryBackendPlugin]:
"""Get all active plugins."""
return [self._plugins[name] for name in self._active_plugins]
def get_available_plugins(self) -> List[str]:
"""Get names of all registered plugins."""
return list(self._plugins.keys())
def get_plugin_capabilities(self, name: str) -> List[Capability]:
"""Get capabilities of a specific plugin."""
plugin = self.get_plugin(name)
return plugin.capabilities if plugin else []
def has_capability(self, capability: Capability) -> List[str]:
"""Get all plugins that support a specific capability."""
result = []
for name, plugin in self._plugins.items():
if capability in plugin.capabilities:
result.append(name)
return result
async def initialize_all_active(self) -> None:
"""Initialize all active plugins."""
if not self._initialized:
for plugin in self.get_active_plugins():
await plugin.initialize()
self._initialized = True
async def shutdown_all_active(self) -> None:
"""Shutdown all active plugins."""
for plugin in self.get_active_plugins():
await plugin.shutdown()
self._initialized = False
# Global registry instance
registry = PluginRegistry()