tiphys.hooks

Tiphys hooks system.

Provides lifecycle events and hook registration for extensibility.

 1"""
 2Tiphys hooks system.
 3
 4Provides lifecycle events and hook registration for extensibility.
 5"""
 6
 7from tiphys.hooks.base import BaseHook, FunctionHook, Hook, hook
 8from tiphys.hooks.events import (
 9    EVENT_TYPES,
10    AgentRespondEvent,
11    AgentThinkEvent,
12    ErrorEvent,
13    GatewayBootEvent,
14    GatewayShutdownEvent,
15    HookEvent,
16    HookEventType,
17    MessageReceivedEvent,
18    MessageSentEvent,
19    PluginLoadEvent,
20    PluginUnloadEvent,
21    SessionEndEvent,
22    SessionStartEvent,
23    ToolCompleteEvent,
24    ToolExecuteEvent,
25)
26from tiphys.hooks.manager import HookManager, get_hook_manager
27
28__all__ = [
29    # Base
30    "Hook",
31    "BaseHook",
32    "FunctionHook",
33    "hook",
34    # Events
35    "HookEvent",
36    "HookEventType",
37    "EVENT_TYPES",
38    "GatewayBootEvent",
39    "GatewayShutdownEvent",
40    "SessionStartEvent",
41    "SessionEndEvent",
42    "MessageReceivedEvent",
43    "MessageSentEvent",
44    "ToolExecuteEvent",
45    "ToolCompleteEvent",
46    "AgentThinkEvent",
47    "AgentRespondEvent",
48    "PluginLoadEvent",
49    "PluginUnloadEvent",
50    "ErrorEvent",
51    # Manager
52    "HookManager",
53    "get_hook_manager",
54]
@runtime_checkable
class Hook(typing.Protocol):
14@runtime_checkable
15class Hook(Protocol):
16    """Protocol for hook implementations."""
17
18    @property
19    def name(self) -> str:
20        """Unique name for this hook."""
21        ...
22
23    @property
24    def event_types(self) -> list[str]:
25        """List of event types this hook handles."""
26        ...
27
28    @property
29    def priority(self) -> int:
30        """Priority for execution order (lower = earlier)."""
31        ...
32
33    async def execute(self, event: HookEvent) -> None:
34        """Execute the hook with the given event."""
35        ...

Protocol for hook implementations.

Hook(*args, **kwargs)
1771def _no_init_or_replace_init(self, *args, **kwargs):
1772    cls = type(self)
1773
1774    if cls._is_protocol:
1775        raise TypeError('Protocols cannot be instantiated')
1776
1777    # Already using a custom `__init__`. No need to calculate correct
1778    # `__init__` to call. This can lead to RecursionError. See bpo-45121.
1779    if cls.__init__ is not _no_init_or_replace_init:
1780        return
1781
1782    # Initially, `__init__` of a protocol subclass is set to `_no_init_or_replace_init`.
1783    # The first instantiation of the subclass will call `_no_init_or_replace_init` which
1784    # searches for a proper new `__init__` in the MRO. The new `__init__`
1785    # replaces the subclass' old `__init__` (ie `_no_init_or_replace_init`). Subsequent
1786    # instantiation of the protocol subclass will thus use the new
1787    # `__init__` and no longer call `_no_init_or_replace_init`.
1788    for base in cls.__mro__:
1789        init = base.__dict__.get('__init__', _no_init_or_replace_init)
1790        if init is not _no_init_or_replace_init:
1791            cls.__init__ = init
1792            break
1793    else:
1794        # should not happen
1795        cls.__init__ = object.__init__
1796
1797    cls.__init__(self, *args, **kwargs)
name: str
18    @property
19    def name(self) -> str:
20        """Unique name for this hook."""
21        ...

Unique name for this hook.

event_types: list[str]
23    @property
24    def event_types(self) -> list[str]:
25        """List of event types this hook handles."""
26        ...

List of event types this hook handles.

priority: int
28    @property
29    def priority(self) -> int:
30        """Priority for execution order (lower = earlier)."""
31        ...

Priority for execution order (lower = earlier).

async def execute(self, event: HookEvent) -> None:
33    async def execute(self, event: HookEvent) -> None:
34        """Execute the hook with the given event."""
35        ...

Execute the hook with the given event.

class BaseHook:
38class BaseHook:
39    """
40    Base implementation for hooks.
41
42    Subclass this to create custom hooks with common functionality.
43    """
44
45    def __init__(
46        self,
47        name: str,
48        event_types: list[str],
49        priority: int = 100,
50    ) -> None:
51        """
52        Initialize the hook.
53
54        Args:
55            name: Unique name for this hook.
56            event_types: List of event types to handle.
57            priority: Execution priority (lower = earlier).
58        """
59        self._name = name
60        self._event_types = event_types
61        self._priority = priority
62
63    @property
64    def name(self) -> str:
65        """Unique name for this hook."""
66        return self._name
67
68    @property
69    def event_types(self) -> list[str]:
70        """List of event types this hook handles."""
71        return self._event_types
72
73    @property
74    def priority(self) -> int:
75        """Priority for execution order."""
76        return self._priority
77
78    async def execute(self, event: HookEvent) -> None:
79        """Execute the hook. Override in subclasses."""
80        pass

Base implementation for hooks.

Subclass this to create custom hooks with common functionality.

BaseHook(name: str, event_types: list[str], priority: int = 100)
45    def __init__(
46        self,
47        name: str,
48        event_types: list[str],
49        priority: int = 100,
50    ) -> None:
51        """
52        Initialize the hook.
53
54        Args:
55            name: Unique name for this hook.
56            event_types: List of event types to handle.
57            priority: Execution priority (lower = earlier).
58        """
59        self._name = name
60        self._event_types = event_types
61        self._priority = priority

Initialize the hook.

Args: name: Unique name for this hook. event_types: List of event types to handle. priority: Execution priority (lower = earlier).

name: str
63    @property
64    def name(self) -> str:
65        """Unique name for this hook."""
66        return self._name

Unique name for this hook.

event_types: list[str]
68    @property
69    def event_types(self) -> list[str]:
70        """List of event types this hook handles."""
71        return self._event_types

List of event types this hook handles.

priority: int
73    @property
74    def priority(self) -> int:
75        """Priority for execution order."""
76        return self._priority

Priority for execution order.

async def execute(self, event: HookEvent) -> None:
78    async def execute(self, event: HookEvent) -> None:
79        """Execute the hook. Override in subclasses."""
80        pass

Execute the hook. Override in subclasses.

class FunctionHook(tiphys.hooks.BaseHook):
 83class FunctionHook(BaseHook):
 84    """
 85    Hook that wraps a simple async function.
 86
 87    Useful for creating hooks without subclassing.
 88    """
 89
 90    def __init__(
 91        self,
 92        name: str,
 93        event_types: list[str],
 94        handler: Callable[[HookEvent], Awaitable[None]],
 95        priority: int = 100,
 96    ) -> None:
 97        """
 98        Initialize the function hook.
 99
100        Args:
101            name: Unique name for this hook.
102            event_types: List of event types to handle.
103            handler: Async function to call when events fire.
104            priority: Execution priority (lower = earlier).
105        """
106        super().__init__(name, event_types, priority)
107        self._handler = handler
108
109    async def execute(self, event: HookEvent) -> None:
110        """Execute the handler function."""
111        await self._handler(event)

Hook that wraps a simple async function.

Useful for creating hooks without subclassing.

FunctionHook( name: str, event_types: list[str], handler: Callable[[HookEvent], Awaitable[None]], priority: int = 100)
 90    def __init__(
 91        self,
 92        name: str,
 93        event_types: list[str],
 94        handler: Callable[[HookEvent], Awaitable[None]],
 95        priority: int = 100,
 96    ) -> None:
 97        """
 98        Initialize the function hook.
 99
100        Args:
101            name: Unique name for this hook.
102            event_types: List of event types to handle.
103            handler: Async function to call when events fire.
104            priority: Execution priority (lower = earlier).
105        """
106        super().__init__(name, event_types, priority)
107        self._handler = handler

Initialize the function hook.

Args: name: Unique name for this hook. event_types: List of event types to handle. handler: Async function to call when events fire. priority: Execution priority (lower = earlier).

async def execute(self, event: HookEvent) -> None:
109    async def execute(self, event: HookEvent) -> None:
110        """Execute the handler function."""
111        await self._handler(event)

Execute the handler function.

def hook( name: str, event_types: list[str], priority: int = 100) -> Callable[[Callable[[HookEvent], Awaitable[None]]], FunctionHook]:
114def hook(
115    name: str,
116    event_types: list[str],
117    priority: int = 100,
118) -> Callable[[Callable[[HookEvent], Awaitable[None]]], FunctionHook]:
119    """
120    Decorator to create a hook from an async function.
121
122    Usage:
123        @hook("my_hook", ["session:start"])
124        async def on_session_start(event: HookEvent) -> None:
125            print(f"Session started: {event}")
126    """
127
128    def decorator(
129        func: Callable[[HookEvent], Awaitable[None]],
130    ) -> FunctionHook:
131        return FunctionHook(
132            name=name,
133            event_types=event_types,
134            handler=func,
135            priority=priority,
136        )
137
138    return decorator

Decorator to create a hook from an async function.

Usage: @hook("my_hook", ["session:start"]) async def on_session_start(event: HookEvent) -> None: print(f"Session started: {event}")

class HookEvent(pydantic.main.BaseModel):
15class HookEvent(BaseModel):
16    """Base class for all hook events."""
17
18    type: str
19    timestamp: datetime = Field(default_factory=datetime.utcnow)

Base class for all hook events.

type: str = PydanticUndefined
timestamp: datetime.datetime = PydanticUndefined
EVENT_TYPES = ['gateway:boot', 'gateway:shutdown', 'session:start', 'session:end', 'message:received', 'message:sent', 'tool:execute', 'tool:complete', 'agent:think', 'agent:respond', 'plugin:load', 'plugin:unload', 'error']
class GatewayBootEvent(tiphys.hooks.HookEvent):
22class GatewayBootEvent(HookEvent):
23    """Emitted when the gateway starts up."""
24
25    type: Literal["gateway:boot"] = "gateway:boot"
26    config: dict[str, Any] = Field(default_factory=dict)

Emitted when the gateway starts up.

type: Literal['gateway:boot'] = 'gateway:boot'
config: dict[str, typing.Any] = PydanticUndefined
class GatewayShutdownEvent(tiphys.hooks.HookEvent):
29class GatewayShutdownEvent(HookEvent):
30    """Emitted when the gateway is shutting down."""
31
32    type: Literal["gateway:shutdown"] = "gateway:shutdown"

Emitted when the gateway is shutting down.

type: Literal['gateway:shutdown'] = 'gateway:shutdown'
class SessionStartEvent(tiphys.hooks.HookEvent):
35class SessionStartEvent(HookEvent):
36    """Emitted when a new session starts."""
37
38    type: Literal["session:start"] = "session:start"
39    session_key: str
40    agent_id: str
41    channel: str | None = None

Emitted when a new session starts.

type: Literal['session:start'] = 'session:start'
session_key: str = PydanticUndefined
agent_id: str = PydanticUndefined
channel: str | None = None
class SessionEndEvent(tiphys.hooks.HookEvent):
44class SessionEndEvent(HookEvent):
45    """Emitted when a session ends."""
46
47    type: Literal["session:end"] = "session:end"
48    session_key: str
49    duration_ms: int = 0

Emitted when a session ends.

type: Literal['session:end'] = 'session:end'
session_key: str = PydanticUndefined
duration_ms: int = 0
class MessageReceivedEvent(tiphys.hooks.HookEvent):
52class MessageReceivedEvent(HookEvent):
53    """Emitted when a message is received from a channel."""
54
55    type: Literal["message:received"] = "message:received"
56    message_id: str
57    channel: str
58    sender_id: str
59    content: str

Emitted when a message is received from a channel.

type: Literal['message:received'] = 'message:received'
message_id: str = PydanticUndefined
channel: str = PydanticUndefined
sender_id: str = PydanticUndefined
content: str = PydanticUndefined
class MessageSentEvent(tiphys.hooks.HookEvent):
62class MessageSentEvent(HookEvent):
63    """Emitted when a message is sent to a channel."""
64
65    type: Literal["message:sent"] = "message:sent"
66    message_id: str | None = None
67    channel: str
68    content: str

Emitted when a message is sent to a channel.

type: Literal['message:sent'] = 'message:sent'
message_id: str | None = None
channel: str = PydanticUndefined
content: str = PydanticUndefined
class ToolExecuteEvent(tiphys.hooks.HookEvent):
71class ToolExecuteEvent(HookEvent):
72    """Emitted before a tool is executed."""
73
74    type: Literal["tool:execute"] = "tool:execute"
75    tool_name: str
76    arguments: dict[str, Any] = Field(default_factory=dict)
77    agent_id: str

Emitted before a tool is executed.

type: Literal['tool:execute'] = 'tool:execute'
tool_name: str = PydanticUndefined
arguments: dict[str, typing.Any] = PydanticUndefined
agent_id: str = PydanticUndefined
class ToolCompleteEvent(tiphys.hooks.HookEvent):
80class ToolCompleteEvent(HookEvent):
81    """Emitted after a tool completes execution."""
82
83    type: Literal["tool:complete"] = "tool:complete"
84    tool_name: str
85    success: bool
86    result: str
87    duration_ms: int = 0
88    agent_id: str

Emitted after a tool completes execution.

type: Literal['tool:complete'] = 'tool:complete'
tool_name: str = PydanticUndefined
success: bool = PydanticUndefined
result: str = PydanticUndefined
duration_ms: int = 0
agent_id: str = PydanticUndefined
class AgentThinkEvent(tiphys.hooks.HookEvent):
91class AgentThinkEvent(HookEvent):
92    """Emitted when agent produces thinking/reasoning."""
93
94    type: Literal["agent:think"] = "agent:think"
95    agent_id: str
96    content: str

Emitted when agent produces thinking/reasoning.

type: Literal['agent:think'] = 'agent:think'
agent_id: str = PydanticUndefined
content: str = PydanticUndefined
class AgentRespondEvent(tiphys.hooks.HookEvent):
 99class AgentRespondEvent(HookEvent):
100    """Emitted when agent produces a response."""
101
102    type: Literal["agent:respond"] = "agent:respond"
103    agent_id: str
104    content: str
105    is_final: bool = False

Emitted when agent produces a response.

type: Literal['agent:respond'] = 'agent:respond'
agent_id: str = PydanticUndefined
content: str = PydanticUndefined
is_final: bool = False
class PluginLoadEvent(tiphys.hooks.HookEvent):
108class PluginLoadEvent(HookEvent):
109    """Emitted when a plugin is loaded."""
110
111    type: Literal["plugin:load"] = "plugin:load"
112    plugin_name: str
113    plugin_path: str | None = None

Emitted when a plugin is loaded.

type: Literal['plugin:load'] = 'plugin:load'
plugin_name: str = PydanticUndefined
plugin_path: str | None = None
class PluginUnloadEvent(tiphys.hooks.HookEvent):
116class PluginUnloadEvent(HookEvent):
117    """Emitted when a plugin is unloaded."""
118
119    type: Literal["plugin:unload"] = "plugin:unload"
120    plugin_name: str

Emitted when a plugin is unloaded.

type: Literal['plugin:unload'] = 'plugin:unload'
plugin_name: str = PydanticUndefined
class ErrorEvent(tiphys.hooks.HookEvent):
123class ErrorEvent(HookEvent):
124    """Emitted when an error occurs."""
125
126    type: Literal["error"] = "error"
127    message: str
128    error_type: str | None = None
129    context: dict[str, Any] = Field(default_factory=dict)

Emitted when an error occurs.

type: Literal['error'] = 'error'
message: str = PydanticUndefined
error_type: str | None = None
context: dict[str, typing.Any] = PydanticUndefined
class HookManager:
 19class HookManager:
 20    """
 21    Manages lifecycle hooks.
 22
 23    Handles registration, execution, and ordering of hooks.
 24    """
 25
 26    def __init__(self) -> None:
 27        """Initialize the hook manager."""
 28        self._hooks: dict[str, list[Hook]] = defaultdict(list)
 29        self._hook_names: set[str] = set()
 30
 31    def register(self, hook: Hook) -> None:
 32        """
 33        Register a hook.
 34
 35        Args:
 36            hook: The hook to register.
 37
 38        Raises:
 39            ValueError: If a hook with the same name is already registered.
 40        """
 41        if hook.name in self._hook_names:
 42            raise ValueError(f"Hook '{hook.name}' is already registered")
 43
 44        self._hook_names.add(hook.name)
 45
 46        # Register for each event type
 47        for event_type in hook.event_types:
 48            self._hooks[event_type].append(hook)
 49            # Sort by priority
 50            self._hooks[event_type].sort(key=lambda h: h.priority)
 51
 52    def unregister(self, name: str) -> bool:
 53        """
 54        Unregister a hook by name.
 55
 56        Args:
 57            name: Name of the hook to unregister.
 58
 59        Returns:
 60            True if the hook was unregistered, False if not found.
 61        """
 62        if name not in self._hook_names:
 63            return False
 64
 65        self._hook_names.discard(name)
 66
 67        # Remove from all event types
 68        for event_type in list(self._hooks.keys()):
 69            self._hooks[event_type] = [h for h in self._hooks[event_type] if h.name != name]
 70
 71        return True
 72
 73    def get_hooks(self, event_type: str) -> list[Hook]:
 74        """
 75        Get all hooks registered for an event type.
 76
 77        Args:
 78            event_type: The event type to get hooks for.
 79
 80        Returns:
 81            List of hooks sorted by priority.
 82        """
 83        return self._hooks.get(event_type, [])
 84
 85    def list_hooks(self) -> list[str]:
 86        """List all registered hook names."""
 87        return list(self._hook_names)
 88
 89    async def emit(self, event: HookEvent) -> None:
 90        """
 91        Emit an event to all registered hooks.
 92
 93        Hooks are executed in priority order.
 94        Errors in individual hooks are logged but don't stop other hooks.
 95
 96        Args:
 97            event: The event to emit.
 98        """
 99        hooks = self._hooks.get(event.type, [])
100
101        if not hooks:
102            return
103
104        await logger.adebug(
105            "Emitting hook event",
106            event_type=event.type,
107            hook_count=len(hooks),
108        )
109
110        for hook in hooks:
111            try:
112                await hook.execute(event)
113            except Exception as e:
114                await logger.aerror(
115                    "Hook execution failed",
116                    hook=hook.name,
117                    event_type=event.type,
118                    error=str(e),
119                )
120
121    async def emit_parallel(self, event: HookEvent) -> None:
122        """
123        Emit an event to all hooks in parallel.
124
125        Unlike emit(), this runs all hooks concurrently.
126        Use when hook order doesn't matter and you want speed.
127
128        Args:
129            event: The event to emit.
130        """
131        hooks = self._hooks.get(event.type, [])
132
133        if not hooks:
134            return
135
136        async def safe_execute(hook: Hook) -> None:
137            try:
138                await hook.execute(event)
139            except Exception as e:
140                await logger.aerror(
141                    "Hook execution failed",
142                    hook=hook.name,
143                    event_type=event.type,
144                    error=str(e),
145                )
146
147        await asyncio.gather(*[safe_execute(hook) for hook in hooks])
148
149    def clear(self) -> int:
150        """
151        Clear all registered hooks.
152
153        Returns:
154            Number of hooks cleared.
155        """
156        count = len(self._hook_names)
157        self._hooks.clear()
158        self._hook_names.clear()
159        return count

Manages lifecycle hooks.

Handles registration, execution, and ordering of hooks.

HookManager()
26    def __init__(self) -> None:
27        """Initialize the hook manager."""
28        self._hooks: dict[str, list[Hook]] = defaultdict(list)
29        self._hook_names: set[str] = set()

Initialize the hook manager.

def register(self, hook: Hook) -> None:
31    def register(self, hook: Hook) -> None:
32        """
33        Register a hook.
34
35        Args:
36            hook: The hook to register.
37
38        Raises:
39            ValueError: If a hook with the same name is already registered.
40        """
41        if hook.name in self._hook_names:
42            raise ValueError(f"Hook '{hook.name}' is already registered")
43
44        self._hook_names.add(hook.name)
45
46        # Register for each event type
47        for event_type in hook.event_types:
48            self._hooks[event_type].append(hook)
49            # Sort by priority
50            self._hooks[event_type].sort(key=lambda h: h.priority)

Register a hook.

Args: hook: The hook to register.

Raises: ValueError: If a hook with the same name is already registered.

def unregister(self, name: str) -> bool:
52    def unregister(self, name: str) -> bool:
53        """
54        Unregister a hook by name.
55
56        Args:
57            name: Name of the hook to unregister.
58
59        Returns:
60            True if the hook was unregistered, False if not found.
61        """
62        if name not in self._hook_names:
63            return False
64
65        self._hook_names.discard(name)
66
67        # Remove from all event types
68        for event_type in list(self._hooks.keys()):
69            self._hooks[event_type] = [h for h in self._hooks[event_type] if h.name != name]
70
71        return True

Unregister a hook by name.

Args: name: Name of the hook to unregister.

Returns: True if the hook was unregistered, False if not found.

def get_hooks(self, event_type: str) -> list[Hook]:
73    def get_hooks(self, event_type: str) -> list[Hook]:
74        """
75        Get all hooks registered for an event type.
76
77        Args:
78            event_type: The event type to get hooks for.
79
80        Returns:
81            List of hooks sorted by priority.
82        """
83        return self._hooks.get(event_type, [])

Get all hooks registered for an event type.

Args: event_type: The event type to get hooks for.

Returns: List of hooks sorted by priority.

def list_hooks(self) -> list[str]:
85    def list_hooks(self) -> list[str]:
86        """List all registered hook names."""
87        return list(self._hook_names)

List all registered hook names.

async def emit(self, event: HookEvent) -> None:
 89    async def emit(self, event: HookEvent) -> None:
 90        """
 91        Emit an event to all registered hooks.
 92
 93        Hooks are executed in priority order.
 94        Errors in individual hooks are logged but don't stop other hooks.
 95
 96        Args:
 97            event: The event to emit.
 98        """
 99        hooks = self._hooks.get(event.type, [])
100
101        if not hooks:
102            return
103
104        await logger.adebug(
105            "Emitting hook event",
106            event_type=event.type,
107            hook_count=len(hooks),
108        )
109
110        for hook in hooks:
111            try:
112                await hook.execute(event)
113            except Exception as e:
114                await logger.aerror(
115                    "Hook execution failed",
116                    hook=hook.name,
117                    event_type=event.type,
118                    error=str(e),
119                )

Emit an event to all registered hooks.

Hooks are executed in priority order. Errors in individual hooks are logged but don't stop other hooks.

Args: event: The event to emit.

async def emit_parallel(self, event: HookEvent) -> None:
121    async def emit_parallel(self, event: HookEvent) -> None:
122        """
123        Emit an event to all hooks in parallel.
124
125        Unlike emit(), this runs all hooks concurrently.
126        Use when hook order doesn't matter and you want speed.
127
128        Args:
129            event: The event to emit.
130        """
131        hooks = self._hooks.get(event.type, [])
132
133        if not hooks:
134            return
135
136        async def safe_execute(hook: Hook) -> None:
137            try:
138                await hook.execute(event)
139            except Exception as e:
140                await logger.aerror(
141                    "Hook execution failed",
142                    hook=hook.name,
143                    event_type=event.type,
144                    error=str(e),
145                )
146
147        await asyncio.gather(*[safe_execute(hook) for hook in hooks])

Emit an event to all hooks in parallel.

Unlike emit(), this runs all hooks concurrently. Use when hook order doesn't matter and you want speed.

Args: event: The event to emit.

def clear(self) -> int:
149    def clear(self) -> int:
150        """
151        Clear all registered hooks.
152
153        Returns:
154            Number of hooks cleared.
155        """
156        count = len(self._hook_names)
157        self._hooks.clear()
158        self._hook_names.clear()
159        return count

Clear all registered hooks.

Returns: Number of hooks cleared.

def get_hook_manager() -> HookManager:
166def get_hook_manager() -> HookManager:
167    """
168    Get the global hook manager.
169
170    .. deprecated::
171        Use AppContext.hook_manager instead. This function will be removed
172        in a future version.
173
174    Returns:
175        The global HookManager instance.
176    """
177    import warnings
178
179    from tiphys.context import get_context, has_context
180
181    # If AppContext is available, use it (preferred path)
182    if has_context():
183        warnings.warn(
184            "get_hook_manager() is deprecated. Use AppContext.hook_manager instead.",
185            DeprecationWarning,
186            stacklevel=2,
187        )
188        return get_context().hook_manager
189
190    # Fallback to global singleton for backwards compatibility
191    global _hook_manager
192    if _hook_manager is None:
193        _hook_manager = HookManager()
194    return _hook_manager

Get the global hook manager.

Deprecated since version : Use AppContext.hook_manager instead. This function will be removed in a future version.

Returns: The global HookManager instance.