quraite 0.1.0__py3-none-any.whl → 0.1.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. quraite/__init__.py +3 -3
  2. quraite/adapters/__init__.py +134 -134
  3. quraite/adapters/agno_adapter.py +157 -159
  4. quraite/adapters/base.py +123 -123
  5. quraite/adapters/bedrock_agents_adapter.py +343 -343
  6. quraite/adapters/flowise_adapter.py +275 -275
  7. quraite/adapters/google_adk_adapter.py +211 -209
  8. quraite/adapters/http_adapter.py +255 -239
  9. quraite/adapters/{langgraph_adapter.py → langchain_adapter.py} +305 -304
  10. quraite/adapters/{langgraph_server_adapter.py → langchain_server_adapter.py} +252 -252
  11. quraite/adapters/langflow_adapter.py +192 -192
  12. quraite/adapters/n8n_adapter.py +220 -220
  13. quraite/adapters/openai_agents_adapter.py +267 -269
  14. quraite/adapters/pydantic_ai_adapter.py +307 -312
  15. quraite/adapters/smolagents_adapter.py +148 -152
  16. quraite/logger.py +61 -61
  17. quraite/schema/message.py +91 -91
  18. quraite/schema/response.py +16 -16
  19. quraite/serve/__init__.py +1 -1
  20. quraite/serve/cloudflared.py +210 -210
  21. quraite/serve/local_agent.py +360 -360
  22. quraite/traces/traces_adk_openinference.json +379 -0
  23. quraite/traces/traces_agno_multi_agent.json +669 -0
  24. quraite/traces/traces_agno_openinference.json +321 -0
  25. quraite/traces/traces_crewai_openinference.json +155 -0
  26. quraite/traces/traces_langgraph_openinference.json +349 -0
  27. quraite/traces/traces_langgraph_openinference_multi_agent.json +2705 -0
  28. quraite/traces/traces_langgraph_traceloop.json +510 -0
  29. quraite/traces/traces_openai_agents_multi_agent_1.json +402 -0
  30. quraite/traces/traces_openai_agents_openinference.json +341 -0
  31. quraite/traces/traces_pydantic_openinference.json +286 -0
  32. quraite/traces/traces_pydantic_openinference_multi_agent_1.json +399 -0
  33. quraite/traces/traces_pydantic_openinference_multi_agent_2.json +398 -0
  34. quraite/traces/traces_smol_agents_openinference.json +397 -0
  35. quraite/traces/traces_smol_agents_tool_calling_openinference.json +704 -0
  36. quraite/tracing/__init__.py +25 -24
  37. quraite/tracing/constants.py +15 -16
  38. quraite/tracing/span_exporter.py +101 -115
  39. quraite/tracing/span_processor.py +47 -49
  40. quraite/tracing/tool_extractors.py +309 -290
  41. quraite/tracing/trace.py +564 -564
  42. quraite/tracing/types.py +179 -179
  43. quraite/tracing/utils.py +170 -170
  44. quraite/utils/json_utils.py +269 -269
  45. quraite-0.1.2.dist-info/METADATA +386 -0
  46. quraite-0.1.2.dist-info/RECORD +49 -0
  47. {quraite-0.1.0.dist-info → quraite-0.1.2.dist-info}/WHEEL +1 -1
  48. quraite-0.1.0.dist-info/METADATA +0 -44
  49. quraite-0.1.0.dist-info/RECORD +0 -35
@@ -1,209 +1,211 @@
1
- import uuid
2
- from typing import List, Union
3
-
4
- from google.adk.agents import Agent
5
- from google.adk.apps.app import App
6
- from google.adk.errors.already_exists_error import AlreadyExistsError
7
- from google.adk.runners import Runner
8
- from google.adk.sessions import BaseSessionService, InMemorySessionService
9
- from google.genai import types
10
- from opentelemetry.trace import TracerProvider
11
-
12
- from quraite.adapters.base import BaseAdapter
13
- from quraite.logger import get_logger
14
- from quraite.schema.message import AgentMessage
15
- from quraite.schema.response import AgentInvocationResponse
16
- from quraite.tracing.constants import QURAITE_ADAPTER_TRACE_PREFIX, Framework
17
- from quraite.tracing.trace import AgentSpan, AgentTrace
18
-
19
- logger = get_logger(__name__)
20
-
21
-
22
- class GoogleADKAdapter(BaseAdapter):
23
- """
24
- Google ADK adapter wrapper that converts any Google ADK agent
25
- to a standardized callable interface (ainvoke) with tracing support.
26
-
27
- This class wraps any Google ADK Agent and provides:
28
- - Asynchronous invocation via ainvoke()
29
- - OpenTelemetry tracing integration
30
- - Session management for multi-turn conversations
31
- """
32
-
33
- def __init__(
34
- self,
35
- agent: Agent,
36
- agent_name: str = "Google ADK Agent",
37
- tracer_provider: TracerProvider = None,
38
- app_name: str = "google_adk_agent",
39
- user_id: str = str(uuid.uuid4()),
40
- session_service: BaseSessionService = InMemorySessionService(),
41
- ):
42
- """
43
- Initialize with a pre-configured Google ADK agent
44
-
45
- Args:
46
- agent: A Google ADK Agent instance
47
- app_name: Application name for ADK runner
48
- agent_name: Name of the agent for trajectory metadata
49
- tracer_provider: TracerProvider for tracing (required)
50
- """
51
- logger.debug(
52
- "Initializing GoogleADKAdapter (agent_name=%s, app_name=%s)",
53
- agent_name,
54
- app_name,
55
- )
56
- self._init_tracing(tracer_provider, required=True)
57
-
58
- self.agent: Agent = agent
59
- self.app_name = app_name
60
- self.agent_name = agent_name
61
- self.session_service = session_service
62
- self.user_id = user_id
63
- self.app = App(
64
- name=app_name,
65
- root_agent=agent,
66
- )
67
- self.runner = Runner(
68
- app=self.app,
69
- session_service=session_service,
70
- )
71
- logger.info("GoogleADKAdapter initialized successfully")
72
-
73
- def _prepare_input(self, input: List[AgentMessage]) -> str:
74
- """
75
- Prepare input for Google ADK agent from List[Message].
76
-
77
- Args:
78
- input: List[Message] containing user_message
79
-
80
- Returns:
81
- str: User message text
82
- """
83
- logger.debug("Preparing Google ADK input from %d messages", len(input))
84
- if not input or input[-1].role != "user":
85
- logger.error("Google ADK input missing user message")
86
- raise ValueError("No user message found in the input")
87
-
88
- last_user_message = input[-1]
89
- # Check if content list is not empty and has text
90
- if not last_user_message.content:
91
- logger.error("Google ADK user message missing content")
92
- raise ValueError("User message has no content")
93
-
94
- # Find the first text content item
95
- text_content = None
96
- for content_item in last_user_message.content:
97
- if content_item.type == "text" and content_item.text:
98
- text_content = content_item.text
99
- break
100
-
101
- if not text_content:
102
- logger.error("Google ADK user message missing text content")
103
- raise ValueError("No text content found in user message")
104
-
105
- logger.debug("Prepared Google ADK input (text_length=%d)", len(text_content))
106
- return text_content
107
-
108
- async def ainvoke(
109
- self,
110
- input: List[AgentMessage],
111
- session_id: Union[str, None] = None,
112
- ) -> AgentInvocationResponse:
113
- """
114
- Asynchronous invocation method - invokes the Google ADK agent with tracing
115
-
116
- Args:
117
- input: List[AgentMessage] containing user_message
118
- session_id: Optional conversation ID for maintaining context
119
-
120
- Returns:
121
- AgentInvocationResponse - response containing agent trace, trajectory, and final response.
122
- """
123
- logger.info(
124
- "Google ADK ainvoke called (session_id=%s, input_messages=%d)",
125
- session_id,
126
- len(input),
127
- )
128
- agent_input = self._prepare_input(input)
129
- session_id = session_id or str(uuid.uuid4())
130
-
131
- try:
132
- return await self._ainvoke_with_tracing(agent_input, session_id)
133
-
134
- except Exception as e:
135
- logger.exception("Error invoking Google ADK agent")
136
- raise RuntimeError(f"Error invoking Google ADK agent: {e}") from e
137
-
138
- async def _ainvoke_with_tracing(
139
- self,
140
- agent_input: str,
141
- session_id: str,
142
- ) -> AgentInvocationResponse:
143
- """Execute ainvoke with tracing enabled."""
144
- adapter_trace_id = f"{QURAITE_ADAPTER_TRACE_PREFIX}-{uuid.uuid4()}"
145
- logger.debug(
146
- "Starting Google ADK traced invocation (trace_id=%s, session_id=%s)",
147
- adapter_trace_id,
148
- session_id,
149
- )
150
-
151
- with self.tracer.start_as_current_span(name=adapter_trace_id):
152
- # Create session if it doesn't exist
153
- try:
154
- await self.session_service.create_session(
155
- app_name=self.app_name,
156
- user_id=self.user_id,
157
- session_id=session_id,
158
- )
159
- except AlreadyExistsError:
160
- logger.info("Session already exists: %s", session_id)
161
- except Exception as e:
162
- logger.exception("Error creating Google ADK session")
163
- raise RuntimeError(f"Error creating session: {e}") from e
164
-
165
- # Create content for ADK
166
- content = types.Content(
167
- role="user",
168
- parts=[types.Part(text=agent_input)],
169
- )
170
-
171
- # Run async and consume events
172
- events = self.runner.run_async(
173
- new_message=content,
174
- user_id=self.user_id,
175
- session_id=session_id,
176
- )
177
-
178
- # Consume all events (tracing captures everything)
179
- async for event in events:
180
- pass # Just consume events, tracing handles capture
181
-
182
- # Get trace spans
183
- trace_readable_spans = self.quraite_span_exporter.get_trace_by_testcase(
184
- adapter_trace_id
185
- )
186
-
187
- if trace_readable_spans:
188
- agent_trace = AgentTrace(
189
- spans=[
190
- AgentSpan.from_readable_oi_span(span)
191
- for span in trace_readable_spans
192
- ],
193
- )
194
- logger.info(
195
- "Google ADK trace collected %d spans for trace_id=%s",
196
- len(trace_readable_spans),
197
- adapter_trace_id,
198
- )
199
- else:
200
- logger.warning(
201
- "No spans exported for Google ADK trace_id=%s", adapter_trace_id
202
- )
203
-
204
- return AgentInvocationResponse(
205
- agent_trace=agent_trace,
206
- agent_trajectory=agent_trace.to_agent_trajectory(
207
- framework=Framework.GOOGLE_ADK
208
- ),
209
- )
1
+ import uuid
2
+ from typing import List, Union
3
+
4
+ from google.adk.agents import Agent
5
+ from google.adk.apps.app import App
6
+ from google.adk.errors.already_exists_error import AlreadyExistsError
7
+ from google.adk.runners import Runner
8
+ from google.adk.sessions import BaseSessionService, InMemorySessionService
9
+ from google.genai import types
10
+ from opentelemetry.trace import TracerProvider
11
+
12
+ from quraite.adapters.base import BaseAdapter
13
+ from quraite.logger import get_logger
14
+ from quraite.schema.message import AgentMessage
15
+ from quraite.schema.response import AgentInvocationResponse
16
+ from quraite.tracing.constants import Framework
17
+ from quraite.tracing.trace import AgentSpan, AgentTrace
18
+
19
+ logger = get_logger(__name__)
20
+
21
+
22
+ class GoogleADKAdapter(BaseAdapter):
23
+ """
24
+ Google ADK adapter wrapper that converts any Google ADK agent
25
+ to a standardized callable interface (ainvoke) with tracing support.
26
+
27
+ This class wraps any Google ADK Agent and provides:
28
+ - Asynchronous invocation via ainvoke()
29
+ - OpenTelemetry tracing integration
30
+ - Session management for multi-turn conversations
31
+ """
32
+
33
+ def __init__(
34
+ self,
35
+ agent: Agent,
36
+ agent_name: str = "Google ADK Agent",
37
+ tracer_provider: TracerProvider = None,
38
+ app_name: str = "google_adk_agent",
39
+ user_id: str = str(uuid.uuid4()),
40
+ session_service: BaseSessionService = InMemorySessionService(),
41
+ ):
42
+ """
43
+ Initialize with a pre-configured Google ADK agent
44
+
45
+ Args:
46
+ agent: A Google ADK Agent instance
47
+ app_name: Application name for ADK runner
48
+ agent_name: Name of the agent for trajectory metadata
49
+ tracer_provider: TracerProvider for tracing (required)
50
+ """
51
+ logger.debug(
52
+ "Initializing GoogleADKAdapter (agent_name=%s, app_name=%s)",
53
+ agent_name,
54
+ app_name,
55
+ )
56
+ self._init_tracing(tracer_provider, required=True)
57
+
58
+ self.agent: Agent = agent
59
+ self.app_name = app_name
60
+ self.agent_name = agent_name
61
+ self.session_service = session_service
62
+ self.user_id = user_id
63
+ self.app = App(
64
+ name=app_name,
65
+ root_agent=agent,
66
+ )
67
+ self.runner = Runner(
68
+ app=self.app,
69
+ session_service=session_service,
70
+ )
71
+ logger.info("GoogleADKAdapter initialized successfully")
72
+
73
+ def _prepare_input(self, input: List[AgentMessage]) -> str:
74
+ """
75
+ Prepare input for Google ADK agent from List[Message].
76
+
77
+ Args:
78
+ input: List[Message] containing user_message
79
+
80
+ Returns:
81
+ str: User message text
82
+ """
83
+ logger.debug("Preparing Google ADK input from %d messages", len(input))
84
+ if not input or input[-1].role != "user":
85
+ logger.error("Google ADK input missing user message")
86
+ raise ValueError("No user message found in the input")
87
+
88
+ last_user_message = input[-1]
89
+ # Check if content list is not empty and has text
90
+ if not last_user_message.content:
91
+ logger.error("Google ADK user message missing content")
92
+ raise ValueError("User message has no content")
93
+
94
+ # Find the first text content item
95
+ text_content = None
96
+ for content_item in last_user_message.content:
97
+ if content_item.type == "text" and content_item.text:
98
+ text_content = content_item.text
99
+ break
100
+
101
+ if not text_content:
102
+ logger.error("Google ADK user message missing text content")
103
+ raise ValueError("No text content found in user message")
104
+
105
+ logger.debug("Prepared Google ADK input (text_length=%d)", len(text_content))
106
+ return text_content
107
+
108
+ async def ainvoke(
109
+ self,
110
+ input: List[AgentMessage],
111
+ session_id: Union[str, None] = None,
112
+ ) -> AgentInvocationResponse:
113
+ """
114
+ Asynchronous invocation method - invokes the Google ADK agent with tracing
115
+
116
+ Args:
117
+ input: List[AgentMessage] containing user_message
118
+ session_id: Optional conversation ID for maintaining context
119
+
120
+ Returns:
121
+ AgentInvocationResponse - response containing agent trace, trajectory, and final response.
122
+ """
123
+ logger.info(
124
+ "Google ADK ainvoke called (session_id=%s, input_messages=%d)",
125
+ session_id,
126
+ len(input),
127
+ )
128
+ agent_input = self._prepare_input(input)
129
+ session_id = session_id or str(uuid.uuid4())
130
+
131
+ try:
132
+ return await self._ainvoke_with_tracing(agent_input, session_id)
133
+
134
+ except Exception as e:
135
+ logger.exception("Error invoking Google ADK agent")
136
+ raise RuntimeError(f"Error invoking Google ADK agent: {e}") from e
137
+
138
+ async def _ainvoke_with_tracing(
139
+ self,
140
+ agent_input: str,
141
+ session_id: str,
142
+ ) -> AgentInvocationResponse:
143
+ """Execute ainvoke with tracing enabled."""
144
+ logger.debug(
145
+ "Starting Google ADK traced invocation (session_id=%s)",
146
+ session_id,
147
+ )
148
+
149
+ with self.tracer.start_as_current_span("google_adk_invocation") as span:
150
+ trace_id = span.get_span_context().trace_id
151
+ logger.debug(
152
+ "Starting Google ADK traced invocation (trace_id=%s, session_id=%s)",
153
+ trace_id,
154
+ session_id,
155
+ )
156
+ # Create session if it doesn't exist
157
+ try:
158
+ await self.session_service.create_session(
159
+ app_name=self.app_name,
160
+ user_id=self.user_id,
161
+ session_id=session_id,
162
+ )
163
+ except AlreadyExistsError:
164
+ logger.info("Session already exists: %s", session_id)
165
+ except Exception as e:
166
+ logger.exception("Error creating Google ADK session")
167
+ raise RuntimeError(f"Error creating session: {e}") from e
168
+
169
+ # Create content for ADK
170
+ content = types.Content(
171
+ role="user",
172
+ parts=[types.Part(text=agent_input)],
173
+ )
174
+
175
+ # Run async and consume events
176
+ events = self.runner.run_async(
177
+ new_message=content,
178
+ user_id=self.user_id,
179
+ session_id=session_id,
180
+ )
181
+
182
+ # Consume all events (tracing captures everything)
183
+ async for event in events:
184
+ pass # Just consume events, tracing handles capture
185
+
186
+ # Get trace spans
187
+ trace_readable_spans = self.quraite_span_exporter.get_spans_by_trace_id(
188
+ trace_id
189
+ )
190
+
191
+ if trace_readable_spans:
192
+ agent_trace = AgentTrace(
193
+ spans=[
194
+ AgentSpan.from_readable_oi_span(span)
195
+ for span in trace_readable_spans
196
+ ],
197
+ )
198
+ logger.info(
199
+ "Google ADK trace collected %d spans for trace_id=%s",
200
+ len(trace_readable_spans),
201
+ trace_id,
202
+ )
203
+ else:
204
+ logger.warning("No spans exported for Google ADK trace_id=%s", trace_id)
205
+
206
+ return AgentInvocationResponse(
207
+ agent_trace=agent_trace,
208
+ agent_trajectory=agent_trace.to_agent_trajectory(
209
+ framework=Framework.GOOGLE_ADK
210
+ ),
211
+ )