REDROOM
PHP 8.2.30
Path:
Logout
Edit File
Size: 2.88 KB
Close
//opt/hc_python/lib/python3.12/site-packages/sentry_sdk/integrations/pydantic_ai/patches/tools.py
Text
Base64
from functools import wraps from sentry_sdk.integrations import DidNotEnable import sentry_sdk from ..spans import execute_tool_span, update_execute_tool_span from ..utils import ( _capture_exception, get_current_agent, ) from typing import TYPE_CHECKING if TYPE_CHECKING: from typing import Any try: from pydantic_ai.mcp import MCPServer # type: ignore HAS_MCP = True except ImportError: HAS_MCP = False try: from pydantic_ai._tool_manager import ToolManager # type: ignore except ImportError: raise DidNotEnable("pydantic-ai not installed") def _patch_tool_execution(): # type: () -> None """ Patch ToolManager._call_tool to create execute_tool spans. This is the single point where ALL tool calls flow through in pydantic_ai, regardless of toolset type (function, MCP, combined, wrapper, etc.). By patching here, we avoid: - Patching multiple toolset classes - Dealing with signature mismatches from instrumented MCP servers - Complex nested toolset handling """ original_call_tool = ToolManager._call_tool @wraps(original_call_tool) async def wrapped_call_tool(self, call, *args, **kwargs): # type: (Any, Any, *Any, **Any) -> Any # Extract tool info before calling original name = call.tool_name tool = self.tools.get(name) if self.tools else None # Determine tool type by checking tool.toolset tool_type = "function" # default if tool and HAS_MCP and isinstance(tool.toolset, MCPServer): tool_type = "mcp" # Get agent from contextvar agent = get_current_agent() if agent and tool: try: args_dict = call.args_as_dict() except Exception: args_dict = call.args if isinstance(call.args, dict) else {} # Create execute_tool span # Nesting is handled by isolation_scope() to ensure proper parent-child relationships with sentry_sdk.isolation_scope(): with execute_tool_span( name, args_dict, agent, tool_type=tool_type, ) as span: try: result = await original_call_tool( self, call, *args, **kwargs, ) update_execute_tool_span(span, result) return result except Exception as exc: _capture_exception(exc) raise exc from None # No span context - just call original return await original_call_tool( self, call, *args, **kwargs, ) ToolManager._call_tool = wrapped_call_tool
Save
Close
Exit & Reset
Text mode: syntax highlighting auto-detects file type.
Directory Contents
Dirs: 1 × Files: 5
Delete Selected
Select All
Select None
Sort:
Name
Size
Modified
Enable drag-to-move
Name
Size
Perms
Modified
Actions
__pycache__
DIR
-
drwxr-xr-x
2025-12-03 08:02:53
Edit
Download
Rename
Chmod
Change Date
Delete
OK
Cancel
recursive
OK
Cancel
recursive
OK
Cancel
agent_run.py
7.27 KB
lrw-r--r--
2025-12-03 08:02:53
Edit
Download
Rename
Chmod
Change Date
Delete
OK
Cancel
recursive
OK
Cancel
recursive
OK
Cancel
graph_nodes.py
3.75 KB
lrw-r--r--
2025-12-03 08:02:53
Edit
Download
Rename
Chmod
Change Date
Delete
OK
Cancel
recursive
OK
Cancel
recursive
OK
Cancel
model_request.py
1.22 KB
lrw-r--r--
2025-12-03 08:02:53
Edit
Download
Rename
Chmod
Change Date
Delete
OK
Cancel
recursive
OK
Cancel
recursive
OK
Cancel
tools.py
2.88 KB
lrw-r--r--
2025-12-03 08:02:53
Edit
Download
Rename
Chmod
Change Date
Delete
OK
Cancel
recursive
OK
Cancel
recursive
OK
Cancel
__init__.py
229 B
lrw-r--r--
2025-12-03 08:02:53
Edit
Download
Rename
Chmod
Change Date
Delete
OK
Cancel
recursive
OK
Cancel
recursive
OK
Cancel
Zip Selected
If ZipArchive is unavailable, a
.tar
will be created (no compression).