simbiot-harness/venv/lib/python3.12/site-packages/strands/plugins/registry.py
Simbiot Harness b60439152b Simbiot Harness v0.1: тактовая лестница на Strands + CQRS/ES-спина
- harness/es.py: append-only event store + проекции (образец — кооп-портал)
- harness/levels.py: уровни 1с/1м/1ч/1д, контекст ∝ масштабу
- harness/scheduler.py: уровневые потоки, идемпотентные тики, absorbed-стабы
- harness/isolated_runner.py + _llm_worker.py: LLM-тик в сабпроцессе
  (глобальный asyncio-рантайм Strands не переживает 2+ create_harness)
- cli.py: init/task/tasks/status/events + requeue (написан самим минутным агентом)
- 9router: отдельный ключ sk-simbiot, модель auto (glm-5.3 первым)
2026-09-29 15:28:50 +00:00

133 lines
4.6 KiB
Python

"""Plugin registry for managing plugins attached to an agent.
This module provides the _PluginRegistry class for tracking and managing
plugins that have been initialized with an agent instance.
"""
import logging
import weakref
from typing import TYPE_CHECKING
from ._discovery import call_init_method
from .plugin import Plugin
if TYPE_CHECKING:
from ..agent import Agent
logger = logging.getLogger(__name__)
class _PluginRegistry:
"""Registry for managing plugins attached to an agent.
The _PluginRegistry tracks plugins that have been initialized with an agent,
providing methods to add plugins and invoke their initialization.
The registry handles:
1. Calling the plugin's init_agent() method for custom initialization
2. Auto-registering discovered @hook decorated methods with the agent
3. Auto-registering discovered @tool decorated methods with the agent
Example:
```python
registry = _PluginRegistry(agent)
class MyPlugin(Plugin):
name = "my-plugin"
@hook
def on_event(self, event: BeforeModelCallEvent):
pass # Auto-registered by registry
def init_agent(self, agent: Agent) -> None:
# Custom logic only - no super() needed
pass
plugin = MyPlugin()
registry.add_and_init(plugin)
```
"""
def __init__(self, agent: "Agent") -> None:
"""Initialize a plugin registry with an agent reference.
Args:
agent: The agent instance that plugins will be initialized with.
"""
self._agent_ref = weakref.ref(agent)
self._plugins: dict[str, Plugin] = {}
@property
def _agent(self) -> "Agent":
"""Return the agent, raising ReferenceError if it has been garbage collected."""
agent = self._agent_ref()
if agent is None:
raise ReferenceError("Agent has been garbage collected")
return agent
def add_and_init(self, plugin: Plugin) -> None:
"""Add and initialize a plugin with the agent.
This method:
1. Registers the plugin in the registry
2. Calls the plugin's init_agent method for custom initialization
3. Auto-registers all discovered @hook methods with the agent's hook registry
4. Auto-registers all discovered @tool methods with the agent's tool registry
Handles both sync and async init_agent implementations automatically.
Args:
plugin: The plugin to add and initialize.
Raises:
ValueError: If a plugin with the same name is already registered.
"""
if plugin.name in self._plugins:
raise ValueError(f"plugin_name=<{plugin.name}> | plugin already registered")
logger.debug("plugin_name=<%s> | registering and initializing plugin", plugin.name)
self._plugins[plugin.name] = plugin
# Call user's init_agent for custom initialization
call_init_method(plugin.init_agent, self._agent)
# Auto-register discovered hooks with the agent
self._register_hooks(plugin)
# Auto-register discovered tools with the agent's tool registry
self._register_tools(plugin)
def _register_hooks(self, plugin: Plugin) -> None:
"""Register all discovered hooks from the plugin with the agent.
Uses agent.add_hook() rather than the hook registry directly, so that
the agent can track registrations through its public API.
Args:
plugin: The plugin whose hooks should be registered.
"""
for hook_callback in plugin.hooks:
event_types = getattr(hook_callback, "_hook_event_types", [])
for event_type in event_types:
self._agent.add_hook(hook_callback, event_type)
logger.debug(
"plugin=<%s>, hook=<%s>, event_type=<%s> | registered hook",
plugin.name,
getattr(hook_callback, "__name__", repr(hook_callback)),
event_type.__name__,
)
def _register_tools(self, plugin: Plugin) -> None:
"""Register all discovered tools from the plugin with the agent.
Args:
plugin: The plugin whose tools should be registered.
"""
if plugin.tools:
self._agent.tool_registry.process_tools(list(plugin.tools))
for tool in plugin.tools:
logger.debug(
"plugin=<%s>, tool=<%s> | registered tool",
plugin.name,
tool.tool_name,
)