mojentic 0.6.0__py3-none-any.whl → 0.6.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.
- _examples/recursive_agent.py +2 -2
- _examples/tracer_demo.py +78 -17
- mojentic/agents/simple_recursive_agent.py +20 -21
- mojentic/llm/gateways/openai.py +2 -2
- mojentic/llm/llm_broker.py +37 -27
- mojentic/llm/tools/llm_tool.py +7 -6
- mojentic/tracer/null_tracer.py +38 -26
- mojentic/tracer/tracer_events.py +27 -25
- mojentic/tracer/tracer_system.py +58 -42
- mojentic/tracer/tracer_system_spec.py +65 -54
- {mojentic-0.6.0.dist-info → mojentic-0.6.2.dist-info}/METADATA +1 -1
- {mojentic-0.6.0.dist-info → mojentic-0.6.2.dist-info}/RECORD +15 -15
- {mojentic-0.6.0.dist-info → mojentic-0.6.2.dist-info}/WHEEL +1 -1
- {mojentic-0.6.0.dist-info → mojentic-0.6.2.dist-info}/licenses/LICENSE.md +0 -0
- {mojentic-0.6.0.dist-info → mojentic-0.6.2.dist-info}/top_level.txt +0 -0
mojentic/tracer/null_tracer.py
CHANGED
|
@@ -12,20 +12,20 @@ from mojentic.tracer.tracer_events import TracerEvent
|
|
|
12
12
|
class NullTracer:
|
|
13
13
|
"""
|
|
14
14
|
A no-op implementation of TracerSystem that silently discards all tracing operations.
|
|
15
|
-
|
|
15
|
+
|
|
16
16
|
This class follows the Null Object Pattern to eliminate conditional checks in client code.
|
|
17
17
|
All record methods are overridden to do nothing, and all query methods return empty results.
|
|
18
18
|
"""
|
|
19
|
-
|
|
19
|
+
|
|
20
20
|
def __init__(self):
|
|
21
21
|
"""Initialize the NullTracer with disabled state."""
|
|
22
22
|
self.enabled = False
|
|
23
23
|
self.event_store = None
|
|
24
|
-
|
|
24
|
+
|
|
25
25
|
def record_event(self, event: TracerEvent) -> None:
|
|
26
26
|
"""
|
|
27
27
|
Do nothing implementation of record_event.
|
|
28
|
-
|
|
28
|
+
|
|
29
29
|
Parameters
|
|
30
30
|
----------
|
|
31
31
|
event : TracerEvent
|
|
@@ -33,16 +33,17 @@ class NullTracer:
|
|
|
33
33
|
"""
|
|
34
34
|
# Do nothing
|
|
35
35
|
pass
|
|
36
|
-
|
|
36
|
+
|
|
37
37
|
def record_llm_call(self,
|
|
38
38
|
model: str,
|
|
39
39
|
messages: List[Dict],
|
|
40
40
|
temperature: float = 1.0,
|
|
41
41
|
tools: Optional[List[Dict]] = None,
|
|
42
|
-
source: Any = None
|
|
42
|
+
source: Any = None,
|
|
43
|
+
correlation_id: str = None) -> None:
|
|
43
44
|
"""
|
|
44
45
|
Do nothing implementation of record_llm_call.
|
|
45
|
-
|
|
46
|
+
|
|
46
47
|
Parameters
|
|
47
48
|
----------
|
|
48
49
|
model : str
|
|
@@ -55,19 +56,22 @@ class NullTracer:
|
|
|
55
56
|
The tools available to the LLM, if any.
|
|
56
57
|
source : Any, optional
|
|
57
58
|
The source of the event.
|
|
59
|
+
correlation_id : str, optional
|
|
60
|
+
UUID string that is copied from cause-to-affect for tracing events.
|
|
58
61
|
"""
|
|
59
62
|
# Do nothing
|
|
60
63
|
pass
|
|
61
|
-
|
|
64
|
+
|
|
62
65
|
def record_llm_response(self,
|
|
63
66
|
model: str,
|
|
64
67
|
content: str,
|
|
65
68
|
tool_calls: Optional[List[Dict]] = None,
|
|
66
69
|
call_duration_ms: Optional[float] = None,
|
|
67
|
-
source: Any = None
|
|
70
|
+
source: Any = None,
|
|
71
|
+
correlation_id: str = None) -> None:
|
|
68
72
|
"""
|
|
69
73
|
Do nothing implementation of record_llm_response.
|
|
70
|
-
|
|
74
|
+
|
|
71
75
|
Parameters
|
|
72
76
|
----------
|
|
73
77
|
model : str
|
|
@@ -80,19 +84,22 @@ class NullTracer:
|
|
|
80
84
|
The duration of the LLM call in milliseconds.
|
|
81
85
|
source : Any, optional
|
|
82
86
|
The source of the event.
|
|
87
|
+
correlation_id : str, optional
|
|
88
|
+
UUID string that is copied from cause-to-affect for tracing events.
|
|
83
89
|
"""
|
|
84
90
|
# Do nothing
|
|
85
91
|
pass
|
|
86
|
-
|
|
92
|
+
|
|
87
93
|
def record_tool_call(self,
|
|
88
94
|
tool_name: str,
|
|
89
95
|
arguments: Dict[str, Any],
|
|
90
96
|
result: Any,
|
|
91
97
|
caller: Optional[str] = None,
|
|
92
|
-
source: Any = None
|
|
98
|
+
source: Any = None,
|
|
99
|
+
correlation_id: str = None) -> None:
|
|
93
100
|
"""
|
|
94
101
|
Do nothing implementation of record_tool_call.
|
|
95
|
-
|
|
102
|
+
|
|
96
103
|
Parameters
|
|
97
104
|
----------
|
|
98
105
|
tool_name : str
|
|
@@ -105,19 +112,22 @@ class NullTracer:
|
|
|
105
112
|
The name of the agent or component calling the tool.
|
|
106
113
|
source : Any, optional
|
|
107
114
|
The source of the event.
|
|
115
|
+
correlation_id : str, optional
|
|
116
|
+
UUID string that is copied from cause-to-affect for tracing events.
|
|
108
117
|
"""
|
|
109
118
|
# Do nothing
|
|
110
119
|
pass
|
|
111
|
-
|
|
120
|
+
|
|
112
121
|
def record_agent_interaction(self,
|
|
113
122
|
from_agent: str,
|
|
114
123
|
to_agent: str,
|
|
115
124
|
event_type: str,
|
|
116
125
|
event_id: Optional[str] = None,
|
|
117
|
-
source: Any = None
|
|
126
|
+
source: Any = None,
|
|
127
|
+
correlation_id: str = None) -> None:
|
|
118
128
|
"""
|
|
119
129
|
Do nothing implementation of record_agent_interaction.
|
|
120
|
-
|
|
130
|
+
|
|
121
131
|
Parameters
|
|
122
132
|
----------
|
|
123
133
|
from_agent : str
|
|
@@ -130,10 +140,12 @@ class NullTracer:
|
|
|
130
140
|
A unique identifier for the event.
|
|
131
141
|
source : Any, optional
|
|
132
142
|
The source of the event.
|
|
143
|
+
correlation_id : str, optional
|
|
144
|
+
UUID string that is copied from cause-to-affect for tracing events.
|
|
133
145
|
"""
|
|
134
146
|
# Do nothing
|
|
135
147
|
pass
|
|
136
|
-
|
|
148
|
+
|
|
137
149
|
def get_events(self,
|
|
138
150
|
event_type: Optional[Type[TracerEvent]] = None,
|
|
139
151
|
start_time: Optional[float] = None,
|
|
@@ -141,7 +153,7 @@ class NullTracer:
|
|
|
141
153
|
filter_func: Optional[Callable[[TracerEvent], bool]] = None) -> List[TracerEvent]:
|
|
142
154
|
"""
|
|
143
155
|
Return an empty list for any get_events request.
|
|
144
|
-
|
|
156
|
+
|
|
145
157
|
Parameters
|
|
146
158
|
----------
|
|
147
159
|
event_type : Type[TracerEvent], optional
|
|
@@ -152,40 +164,40 @@ class NullTracer:
|
|
|
152
164
|
Include events with timestamp <= end_time.
|
|
153
165
|
filter_func : Callable[[TracerEvent], bool], optional
|
|
154
166
|
Custom filter function to apply to events.
|
|
155
|
-
|
|
167
|
+
|
|
156
168
|
Returns
|
|
157
169
|
-------
|
|
158
170
|
List[TracerEvent]
|
|
159
171
|
An empty list.
|
|
160
172
|
"""
|
|
161
173
|
return []
|
|
162
|
-
|
|
174
|
+
|
|
163
175
|
def get_last_n_tracer_events(self, n: int, event_type: Optional[Type[TracerEvent]] = None) -> List[TracerEvent]:
|
|
164
176
|
"""
|
|
165
177
|
Return an empty list for any get_last_n_tracer_events request.
|
|
166
|
-
|
|
178
|
+
|
|
167
179
|
Parameters
|
|
168
180
|
----------
|
|
169
181
|
n : int
|
|
170
182
|
Number of events to return.
|
|
171
183
|
event_type : Type[TracerEvent], optional
|
|
172
184
|
Filter events by this specific tracer event type.
|
|
173
|
-
|
|
185
|
+
|
|
174
186
|
Returns
|
|
175
187
|
-------
|
|
176
188
|
List[TracerEvent]
|
|
177
189
|
An empty list.
|
|
178
190
|
"""
|
|
179
191
|
return []
|
|
180
|
-
|
|
192
|
+
|
|
181
193
|
def clear(self) -> None:
|
|
182
194
|
"""Do nothing implementation of clear method."""
|
|
183
195
|
pass
|
|
184
|
-
|
|
196
|
+
|
|
185
197
|
def enable(self) -> None:
|
|
186
198
|
"""No-op method for interface compatibility."""
|
|
187
199
|
pass
|
|
188
|
-
|
|
200
|
+
|
|
189
201
|
def disable(self) -> None:
|
|
190
202
|
"""No-op method for interface compatibility."""
|
|
191
|
-
pass
|
|
203
|
+
pass
|
mojentic/tracer/tracer_events.py
CHANGED
|
@@ -3,6 +3,7 @@ Defines tracer event types for tracking system interactions.
|
|
|
3
3
|
"""
|
|
4
4
|
from typing import Any, Dict, List, Optional, Type
|
|
5
5
|
from datetime import datetime
|
|
6
|
+
import uuid
|
|
6
7
|
|
|
7
8
|
from pydantic import Field
|
|
8
9
|
|
|
@@ -12,24 +13,25 @@ from mojentic.event import Event
|
|
|
12
13
|
class TracerEvent(Event):
|
|
13
14
|
"""
|
|
14
15
|
Base class for all tracer-specific events.
|
|
15
|
-
|
|
16
|
+
|
|
16
17
|
Tracer events are used to track system interactions for observability purposes.
|
|
17
18
|
They are distinct from regular events which are used for agent communication.
|
|
18
19
|
"""
|
|
19
20
|
timestamp: float = Field(..., description="Timestamp when the event occurred")
|
|
20
|
-
|
|
21
|
+
correlation_id: str = Field(default_factory=lambda: str(uuid.uuid4()), description="UUID string that is copied from cause-to-affect for tracing events")
|
|
22
|
+
|
|
21
23
|
def printable_summary(self) -> str:
|
|
22
24
|
"""
|
|
23
25
|
Return a formatted string summary of the event.
|
|
24
|
-
|
|
26
|
+
|
|
25
27
|
Returns
|
|
26
28
|
-------
|
|
27
29
|
str
|
|
28
30
|
A formatted string with the event information.
|
|
29
31
|
"""
|
|
30
32
|
event_time = datetime.fromtimestamp(self.timestamp).strftime("%H:%M:%S.%f")[:-3]
|
|
31
|
-
return f"[{event_time}] {type(self).__name__}"
|
|
32
|
-
|
|
33
|
+
return f"[{event_time}] {type(self).__name__} (correlation_id: {self.correlation_id})"
|
|
34
|
+
|
|
33
35
|
|
|
34
36
|
class LLMCallTracerEvent(TracerEvent):
|
|
35
37
|
"""
|
|
@@ -39,25 +41,25 @@ class LLMCallTracerEvent(TracerEvent):
|
|
|
39
41
|
messages: List[dict] = Field(..., description="The messages sent to the LLM")
|
|
40
42
|
temperature: float = Field(1.0, description="The temperature setting used for the call")
|
|
41
43
|
tools: Optional[List[Dict]] = Field(None, description="The tools available to the LLM, if any")
|
|
42
|
-
|
|
44
|
+
|
|
43
45
|
def printable_summary(self) -> str:
|
|
44
46
|
"""Return a formatted summary of the LLM call event."""
|
|
45
47
|
base_summary = super().printable_summary()
|
|
46
48
|
summary = f"{base_summary}\n Model: {self.model}"
|
|
47
|
-
|
|
49
|
+
|
|
48
50
|
if self.messages:
|
|
49
51
|
msg_count = len(self.messages)
|
|
50
52
|
summary += f"\n Messages: {msg_count} message{'s' if msg_count != 1 else ''}"
|
|
51
|
-
|
|
53
|
+
|
|
52
54
|
if self.temperature != 1.0:
|
|
53
55
|
summary += f"\n Temperature: {self.temperature}"
|
|
54
|
-
|
|
56
|
+
|
|
55
57
|
if self.tools:
|
|
56
58
|
tool_names = [tool.get('name', 'unknown') for tool in self.tools]
|
|
57
59
|
summary += f"\n Available Tools: {', '.join(tool_names)}"
|
|
58
|
-
|
|
60
|
+
|
|
59
61
|
return summary
|
|
60
|
-
|
|
62
|
+
|
|
61
63
|
|
|
62
64
|
class LLMResponseTracerEvent(TracerEvent):
|
|
63
65
|
"""
|
|
@@ -67,23 +69,23 @@ class LLMResponseTracerEvent(TracerEvent):
|
|
|
67
69
|
content: str = Field(..., description="The content of the LLM response")
|
|
68
70
|
tool_calls: Optional[List[Dict]] = Field(None, description="Any tool calls made by the LLM")
|
|
69
71
|
call_duration_ms: Optional[float] = Field(None, description="Duration of the LLM call in milliseconds")
|
|
70
|
-
|
|
72
|
+
|
|
71
73
|
def printable_summary(self) -> str:
|
|
72
74
|
"""Return a formatted summary of the LLM response event."""
|
|
73
75
|
base_summary = super().printable_summary()
|
|
74
76
|
summary = f"{base_summary}\n Model: {self.model}"
|
|
75
|
-
|
|
77
|
+
|
|
76
78
|
if self.content:
|
|
77
79
|
content_preview = self.content[:100] + "..." if len(self.content) > 100 else self.content
|
|
78
80
|
summary += f"\n Content: {content_preview}"
|
|
79
|
-
|
|
81
|
+
|
|
80
82
|
if self.tool_calls:
|
|
81
83
|
tool_count = len(self.tool_calls)
|
|
82
84
|
summary += f"\n Tool Calls: {tool_count} call{'s' if tool_count != 1 else ''}"
|
|
83
|
-
|
|
85
|
+
|
|
84
86
|
if self.call_duration_ms is not None:
|
|
85
87
|
summary += f"\n Duration: {self.call_duration_ms:.2f}ms"
|
|
86
|
-
|
|
88
|
+
|
|
87
89
|
return summary
|
|
88
90
|
|
|
89
91
|
|
|
@@ -95,23 +97,23 @@ class ToolCallTracerEvent(TracerEvent):
|
|
|
95
97
|
arguments: Dict[str, Any] = Field(..., description="Arguments provided to the tool")
|
|
96
98
|
result: Any = Field(..., description="Result returned by the tool")
|
|
97
99
|
caller: Optional[str] = Field(None, description="Name of the agent or component that called the tool")
|
|
98
|
-
|
|
100
|
+
|
|
99
101
|
def printable_summary(self) -> str:
|
|
100
102
|
"""Return a formatted summary of the tool call event."""
|
|
101
103
|
base_summary = super().printable_summary()
|
|
102
104
|
summary = f"{base_summary}\n Tool: {self.tool_name}"
|
|
103
|
-
|
|
105
|
+
|
|
104
106
|
if self.arguments:
|
|
105
107
|
summary += f"\n Arguments: {self.arguments}"
|
|
106
|
-
|
|
108
|
+
|
|
107
109
|
if self.result is not None:
|
|
108
110
|
result_str = str(self.result)
|
|
109
111
|
result_preview = result_str[:100] + "..." if len(result_str) > 100 else result_str
|
|
110
112
|
summary += f"\n Result: {result_preview}"
|
|
111
|
-
|
|
113
|
+
|
|
112
114
|
if self.caller:
|
|
113
115
|
summary += f"\n Caller: {self.caller}"
|
|
114
|
-
|
|
116
|
+
|
|
115
117
|
return summary
|
|
116
118
|
|
|
117
119
|
|
|
@@ -123,14 +125,14 @@ class AgentInteractionTracerEvent(TracerEvent):
|
|
|
123
125
|
to_agent: str = Field(..., description="Name of the agent receiving the event")
|
|
124
126
|
event_type: str = Field(..., description="Type of event being processed")
|
|
125
127
|
event_id: Optional[str] = Field(None, description="Unique identifier for the event")
|
|
126
|
-
|
|
128
|
+
|
|
127
129
|
def printable_summary(self) -> str:
|
|
128
130
|
"""Return a formatted summary of the agent interaction event."""
|
|
129
131
|
base_summary = super().printable_summary()
|
|
130
132
|
summary = f"{base_summary}\n From: {self.from_agent} → To: {self.to_agent}"
|
|
131
133
|
summary += f"\n Event Type: {self.event_type}"
|
|
132
|
-
|
|
134
|
+
|
|
133
135
|
if self.event_id:
|
|
134
136
|
summary += f"\n Event ID: {self.event_id}"
|
|
135
|
-
|
|
136
|
-
return summary
|
|
137
|
+
|
|
138
|
+
return summary
|
mojentic/tracer/tracer_system.py
CHANGED
|
@@ -24,16 +24,16 @@ logger = structlog.get_logger()
|
|
|
24
24
|
class TracerSystem:
|
|
25
25
|
"""
|
|
26
26
|
Central system for capturing and querying tracer events.
|
|
27
|
-
|
|
27
|
+
|
|
28
28
|
The TracerSystem is responsible for recording events related to LLM calls,
|
|
29
29
|
tool usage, and agent interactions, providing a way to trace through the
|
|
30
30
|
major events of the system.
|
|
31
31
|
"""
|
|
32
|
-
|
|
32
|
+
|
|
33
33
|
def __init__(self, event_store: Optional[EventStore] = None, enabled: bool = True):
|
|
34
34
|
"""
|
|
35
35
|
Initialize the tracer system.
|
|
36
|
-
|
|
36
|
+
|
|
37
37
|
Parameters
|
|
38
38
|
----------
|
|
39
39
|
event_store : EventStore, optional
|
|
@@ -43,11 +43,11 @@ class TracerSystem:
|
|
|
43
43
|
"""
|
|
44
44
|
self.event_store = event_store or EventStore()
|
|
45
45
|
self.enabled = enabled
|
|
46
|
-
|
|
46
|
+
|
|
47
47
|
def record_event(self, event: TracerEvent) -> None:
|
|
48
48
|
"""
|
|
49
49
|
Record a tracer event in the event store.
|
|
50
|
-
|
|
50
|
+
|
|
51
51
|
Parameters
|
|
52
52
|
----------
|
|
53
53
|
event : TracerEvent
|
|
@@ -55,18 +55,19 @@ class TracerSystem:
|
|
|
55
55
|
"""
|
|
56
56
|
if not self.enabled:
|
|
57
57
|
return
|
|
58
|
-
|
|
58
|
+
|
|
59
59
|
self.event_store.store(event)
|
|
60
|
-
|
|
60
|
+
|
|
61
61
|
def record_llm_call(self,
|
|
62
62
|
model: str,
|
|
63
63
|
messages: List[Dict],
|
|
64
64
|
temperature: float = 1.0,
|
|
65
65
|
tools: Optional[List[Dict]] = None,
|
|
66
|
-
source: Any = None
|
|
66
|
+
source: Any = None,
|
|
67
|
+
correlation_id: str = None) -> None:
|
|
67
68
|
"""
|
|
68
69
|
Record an LLM call event.
|
|
69
|
-
|
|
70
|
+
|
|
70
71
|
Parameters
|
|
71
72
|
----------
|
|
72
73
|
model : str
|
|
@@ -79,29 +80,33 @@ class TracerSystem:
|
|
|
79
80
|
The tools available to the LLM, if any.
|
|
80
81
|
source : Any, optional
|
|
81
82
|
The source of the event. If None, the TracerSystem class will be used.
|
|
83
|
+
correlation_id : str, required
|
|
84
|
+
UUID string that is copied from cause-to-affect for tracing events.
|
|
82
85
|
"""
|
|
83
86
|
if not self.enabled:
|
|
84
87
|
return
|
|
85
|
-
|
|
88
|
+
|
|
86
89
|
event = LLMCallTracerEvent(
|
|
87
90
|
source=source or type(self),
|
|
88
91
|
timestamp=time.time(),
|
|
89
92
|
model=model,
|
|
90
93
|
messages=messages,
|
|
91
94
|
temperature=temperature,
|
|
92
|
-
tools=tools
|
|
95
|
+
tools=tools,
|
|
96
|
+
correlation_id=correlation_id
|
|
93
97
|
)
|
|
94
98
|
self.event_store.store(event)
|
|
95
|
-
|
|
99
|
+
|
|
96
100
|
def record_llm_response(self,
|
|
97
101
|
model: str,
|
|
98
102
|
content: str,
|
|
99
103
|
tool_calls: Optional[List[Dict]] = None,
|
|
100
104
|
call_duration_ms: Optional[float] = None,
|
|
101
|
-
source: Any = None
|
|
105
|
+
source: Any = None,
|
|
106
|
+
correlation_id: str = None) -> None:
|
|
102
107
|
"""
|
|
103
108
|
Record an LLM response event.
|
|
104
|
-
|
|
109
|
+
|
|
105
110
|
Parameters
|
|
106
111
|
----------
|
|
107
112
|
model : str
|
|
@@ -114,29 +119,33 @@ class TracerSystem:
|
|
|
114
119
|
The duration of the LLM call in milliseconds.
|
|
115
120
|
source : Any, optional
|
|
116
121
|
The source of the event. If None, the TracerSystem class will be used.
|
|
122
|
+
correlation_id : str, required
|
|
123
|
+
UUID string that is copied from cause-to-affect for tracing events.
|
|
117
124
|
"""
|
|
118
125
|
if not self.enabled:
|
|
119
126
|
return
|
|
120
|
-
|
|
127
|
+
|
|
121
128
|
event = LLMResponseTracerEvent(
|
|
122
129
|
source=source or type(self),
|
|
123
130
|
timestamp=time.time(),
|
|
124
131
|
model=model,
|
|
125
132
|
content=content,
|
|
126
133
|
tool_calls=tool_calls,
|
|
127
|
-
call_duration_ms=call_duration_ms
|
|
134
|
+
call_duration_ms=call_duration_ms,
|
|
135
|
+
correlation_id=correlation_id
|
|
128
136
|
)
|
|
129
137
|
self.event_store.store(event)
|
|
130
|
-
|
|
138
|
+
|
|
131
139
|
def record_tool_call(self,
|
|
132
140
|
tool_name: str,
|
|
133
141
|
arguments: Dict[str, Any],
|
|
134
142
|
result: Any,
|
|
135
143
|
caller: Optional[str] = None,
|
|
136
|
-
source: Any = None
|
|
144
|
+
source: Any = None,
|
|
145
|
+
correlation_id: str = None) -> None:
|
|
137
146
|
"""
|
|
138
147
|
Record a tool call event.
|
|
139
|
-
|
|
148
|
+
|
|
140
149
|
Parameters
|
|
141
150
|
----------
|
|
142
151
|
tool_name : str
|
|
@@ -149,29 +158,33 @@ class TracerSystem:
|
|
|
149
158
|
The name of the agent or component calling the tool.
|
|
150
159
|
source : Any, optional
|
|
151
160
|
The source of the event. If None, the TracerSystem class will be used.
|
|
161
|
+
correlation_id : str, required
|
|
162
|
+
UUID string that is copied from cause-to-affect for tracing events.
|
|
152
163
|
"""
|
|
153
164
|
if not self.enabled:
|
|
154
165
|
return
|
|
155
|
-
|
|
166
|
+
|
|
156
167
|
event = ToolCallTracerEvent(
|
|
157
168
|
source=source or type(self),
|
|
158
169
|
timestamp=time.time(),
|
|
159
170
|
tool_name=tool_name,
|
|
160
171
|
arguments=arguments,
|
|
161
172
|
result=result,
|
|
162
|
-
caller=caller
|
|
173
|
+
caller=caller,
|
|
174
|
+
correlation_id=correlation_id
|
|
163
175
|
)
|
|
164
176
|
self.event_store.store(event)
|
|
165
|
-
|
|
177
|
+
|
|
166
178
|
def record_agent_interaction(self,
|
|
167
179
|
from_agent: str,
|
|
168
180
|
to_agent: str,
|
|
169
181
|
event_type: str,
|
|
170
182
|
event_id: Optional[str] = None,
|
|
171
|
-
source: Any = None
|
|
183
|
+
source: Any = None,
|
|
184
|
+
correlation_id: str = None) -> None:
|
|
172
185
|
"""
|
|
173
186
|
Record an agent interaction event.
|
|
174
|
-
|
|
187
|
+
|
|
175
188
|
Parameters
|
|
176
189
|
----------
|
|
177
190
|
from_agent : str
|
|
@@ -184,20 +197,23 @@ class TracerSystem:
|
|
|
184
197
|
A unique identifier for the event.
|
|
185
198
|
source : Any, optional
|
|
186
199
|
The source of the event. If None, the TracerSystem class will be used.
|
|
200
|
+
correlation_id : str, required
|
|
201
|
+
UUID string that is copied from cause-to-affect for tracing events.
|
|
187
202
|
"""
|
|
188
203
|
if not self.enabled:
|
|
189
204
|
return
|
|
190
|
-
|
|
205
|
+
|
|
191
206
|
event = AgentInteractionTracerEvent(
|
|
192
207
|
source=source or type(self),
|
|
193
208
|
timestamp=time.time(),
|
|
194
209
|
from_agent=from_agent,
|
|
195
210
|
to_agent=to_agent,
|
|
196
211
|
event_type=event_type,
|
|
197
|
-
event_id=event_id
|
|
212
|
+
event_id=event_id,
|
|
213
|
+
correlation_id=correlation_id
|
|
198
214
|
)
|
|
199
215
|
self.event_store.store(event)
|
|
200
|
-
|
|
216
|
+
|
|
201
217
|
def get_events(self,
|
|
202
218
|
event_type: Optional[Type[TracerEvent]] = None,
|
|
203
219
|
start_time: Optional[float] = None,
|
|
@@ -205,10 +221,10 @@ class TracerSystem:
|
|
|
205
221
|
filter_func: Optional[Callable[[TracerEvent], bool]] = None) -> List[TracerEvent]:
|
|
206
222
|
"""
|
|
207
223
|
Get tracer events from the store, optionally filtered.
|
|
208
|
-
|
|
224
|
+
|
|
209
225
|
This is a convenience wrapper around the EventStore's get_events method,
|
|
210
226
|
specifically for tracer events.
|
|
211
|
-
|
|
227
|
+
|
|
212
228
|
Parameters
|
|
213
229
|
----------
|
|
214
230
|
event_type : Type[TracerEvent], optional
|
|
@@ -219,7 +235,7 @@ class TracerSystem:
|
|
|
219
235
|
Include events with timestamp <= end_time.
|
|
220
236
|
filter_func : Callable[[TracerEvent], bool], optional
|
|
221
237
|
Custom filter function to apply to events.
|
|
222
|
-
|
|
238
|
+
|
|
223
239
|
Returns
|
|
224
240
|
-------
|
|
225
241
|
List[TracerEvent]
|
|
@@ -227,33 +243,33 @@ class TracerSystem:
|
|
|
227
243
|
"""
|
|
228
244
|
# First filter to only TracerEvents
|
|
229
245
|
events = self.event_store.get_events(event_type=TracerEvent)
|
|
230
|
-
|
|
246
|
+
|
|
231
247
|
# Then apply additional filters
|
|
232
248
|
if event_type is not None:
|
|
233
249
|
events = [e for e in events if isinstance(e, event_type)]
|
|
234
|
-
|
|
250
|
+
|
|
235
251
|
if start_time is not None:
|
|
236
252
|
events = [e for e in events if e.timestamp >= start_time]
|
|
237
|
-
|
|
253
|
+
|
|
238
254
|
if end_time is not None:
|
|
239
255
|
events = [e for e in events if e.timestamp <= end_time]
|
|
240
|
-
|
|
256
|
+
|
|
241
257
|
if filter_func is not None:
|
|
242
258
|
events = [e for e in events if filter_func(e)]
|
|
243
|
-
|
|
259
|
+
|
|
244
260
|
return events
|
|
245
|
-
|
|
261
|
+
|
|
246
262
|
def get_last_n_tracer_events(self, n: int, event_type: Optional[Type[TracerEvent]] = None) -> List[TracerEvent]:
|
|
247
263
|
"""
|
|
248
264
|
Get the last N tracer events, optionally filtered by type.
|
|
249
|
-
|
|
265
|
+
|
|
250
266
|
Parameters
|
|
251
267
|
----------
|
|
252
268
|
n : int
|
|
253
269
|
Number of events to return.
|
|
254
270
|
event_type : Type[TracerEvent], optional
|
|
255
271
|
Filter events by this specific tracer event type.
|
|
256
|
-
|
|
272
|
+
|
|
257
273
|
Returns
|
|
258
274
|
-------
|
|
259
275
|
List[TracerEvent]
|
|
@@ -261,19 +277,19 @@ class TracerSystem:
|
|
|
261
277
|
"""
|
|
262
278
|
base_type = event_type or TracerEvent
|
|
263
279
|
return self.event_store.get_last_n_events(n, event_type=base_type)
|
|
264
|
-
|
|
280
|
+
|
|
265
281
|
def clear(self) -> None:
|
|
266
282
|
"""
|
|
267
283
|
Clear all events from the event store.
|
|
268
284
|
"""
|
|
269
285
|
self.event_store.clear()
|
|
270
|
-
|
|
286
|
+
|
|
271
287
|
def enable(self) -> None:
|
|
272
288
|
"""
|
|
273
289
|
Enable the tracer system.
|
|
274
290
|
"""
|
|
275
291
|
self.enabled = True
|
|
276
|
-
|
|
292
|
+
|
|
277
293
|
def disable(self) -> None:
|
|
278
294
|
"""
|
|
279
295
|
Disable the tracer system.
|
|
@@ -282,4 +298,4 @@ class TracerSystem:
|
|
|
282
298
|
|
|
283
299
|
|
|
284
300
|
# Import and use the null tracer directly in client code via:
|
|
285
|
-
# from mojentic.tracer import null_tracer
|
|
301
|
+
# from mojentic.tracer import null_tracer
|