1717 from typing import Any , List , Dict
1818 from pydantic_ai .usage import RequestUsage
1919
20+ try :
21+ from pydantic_ai .messages import (
22+ BaseToolCallPart ,
23+ BaseToolReturnPart ,
24+ SystemPromptPart ,
25+ UserPromptPart ,
26+ TextPart ,
27+ ThinkingPart ,
28+ )
29+ except ImportError :
30+ # Fallback if these classes are not available
31+ BaseToolCallPart = None # type: ignore
32+ BaseToolReturnPart = None # type: ignore
33+ SystemPromptPart = None # type: ignore
34+ UserPromptPart = None # type: ignore
35+ TextPart = None # type: ignore
36+ ThinkingPart = None # type: ignore
37+
2038
2139def _set_usage_data (span , usage ):
2240 # type: (sentry_sdk.tracing.Span, RequestUsage) -> None
@@ -63,24 +81,24 @@ def _set_input_messages(span, messages):
6381 if hasattr (msg , "parts" ):
6482 for part in msg .parts :
6583 role = "user"
66- if hasattr ( part , "__class__" ):
67- if "System" in part . __class__ . __name__ :
68- role = "system"
69- elif (
70- "Assistant" in part . __class__ . __name__
71- or "Text" in part . __class__ . __name__
72- or "ToolCall" in part . __class__ . __name__
73- ):
74- role = "assistant"
75- elif "ToolReturn" in part . __class__ . __name__ :
76- role = "tool"
84+ # Use isinstance checks with proper base classes
85+ if SystemPromptPart and isinstance ( part , SystemPromptPart ) :
86+ role = "system"
87+ elif (
88+ ( TextPart and isinstance ( part , TextPart ))
89+ or ( ThinkingPart and isinstance ( part , ThinkingPart ))
90+ or ( BaseToolCallPart and isinstance ( part , BaseToolCallPart ))
91+ ):
92+ role = "assistant"
93+ elif BaseToolReturnPart and isinstance ( part , BaseToolReturnPart ) :
94+ role = "tool"
7795
7896 content = [] # type: List[Dict[str, Any] | str]
7997 tool_calls = None
8098 tool_call_id = None
8199
82100 # Handle ToolCallPart (assistant requesting tool use)
83- if "ToolCall" in part . __class__ . __name__ :
101+ if BaseToolCallPart and isinstance ( part , BaseToolCallPart ) :
84102 tool_call_data = {}
85103 if hasattr (part , "tool_name" ):
86104 tool_call_data ["name" ] = part .tool_name
@@ -89,7 +107,7 @@ def _set_input_messages(span, messages):
89107 if tool_call_data :
90108 tool_calls = [tool_call_data ]
91109 # Handle ToolReturnPart (tool result)
92- elif "ToolReturn" in part . __class__ . __name__ :
110+ elif BaseToolReturnPart and isinstance ( part , BaseToolReturnPart ) :
93111 if hasattr (part , "tool_name" ):
94112 tool_call_id = part .tool_name
95113 if hasattr (part , "content" ):
@@ -144,18 +162,17 @@ def _set_output_data(span, response):
144162 tool_calls = []
145163
146164 for part in response .parts :
147- if hasattr (part , "__class__" ):
148- if "Text" in part .__class__ .__name__ and hasattr (part , "content" ):
149- texts .append (part .content )
150- elif "ToolCall" in part .__class__ .__name__ :
151- tool_call_data = {
152- "type" : "function" ,
153- }
154- if hasattr (part , "tool_name" ):
155- tool_call_data ["name" ] = part .tool_name
156- if hasattr (part , "args" ):
157- tool_call_data ["arguments" ] = safe_serialize (part .args )
158- tool_calls .append (tool_call_data )
165+ if TextPart and isinstance (part , TextPart ) and hasattr (part , "content" ):
166+ texts .append (part .content )
167+ elif BaseToolCallPart and isinstance (part , BaseToolCallPart ):
168+ tool_call_data = {
169+ "type" : "function" ,
170+ }
171+ if hasattr (part , "tool_name" ):
172+ tool_call_data ["name" ] = part .tool_name
173+ if hasattr (part , "args" ):
174+ tool_call_data ["arguments" ] = safe_serialize (part .args )
175+ tool_calls .append (tool_call_data )
159176
160177 if texts :
161178 set_data_normalized (span , SPANDATA .GEN_AI_RESPONSE_TEXT , texts )
0 commit comments