aiecs 1.3.8__py3-none-any.whl → 1.4.0__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.

Potentially problematic release.


This version of aiecs might be problematic. Click here for more details.

Files changed (36) hide show
  1. aiecs/__init__.py +1 -1
  2. aiecs/domain/__init__.py +120 -0
  3. aiecs/domain/agent/__init__.py +184 -0
  4. aiecs/domain/agent/base_agent.py +691 -0
  5. aiecs/domain/agent/exceptions.py +99 -0
  6. aiecs/domain/agent/hybrid_agent.py +495 -0
  7. aiecs/domain/agent/integration/__init__.py +23 -0
  8. aiecs/domain/agent/integration/context_compressor.py +219 -0
  9. aiecs/domain/agent/integration/context_engine_adapter.py +258 -0
  10. aiecs/domain/agent/integration/retry_policy.py +228 -0
  11. aiecs/domain/agent/integration/role_config.py +217 -0
  12. aiecs/domain/agent/lifecycle.py +298 -0
  13. aiecs/domain/agent/llm_agent.py +309 -0
  14. aiecs/domain/agent/memory/__init__.py +13 -0
  15. aiecs/domain/agent/memory/conversation.py +216 -0
  16. aiecs/domain/agent/migration/__init__.py +15 -0
  17. aiecs/domain/agent/migration/conversion.py +171 -0
  18. aiecs/domain/agent/migration/legacy_wrapper.py +97 -0
  19. aiecs/domain/agent/models.py +263 -0
  20. aiecs/domain/agent/observability.py +443 -0
  21. aiecs/domain/agent/persistence.py +287 -0
  22. aiecs/domain/agent/prompts/__init__.py +25 -0
  23. aiecs/domain/agent/prompts/builder.py +164 -0
  24. aiecs/domain/agent/prompts/formatters.py +192 -0
  25. aiecs/domain/agent/prompts/template.py +264 -0
  26. aiecs/domain/agent/registry.py +261 -0
  27. aiecs/domain/agent/tool_agent.py +267 -0
  28. aiecs/domain/agent/tools/__init__.py +13 -0
  29. aiecs/domain/agent/tools/schema_generator.py +222 -0
  30. aiecs/main.py +2 -2
  31. {aiecs-1.3.8.dist-info → aiecs-1.4.0.dist-info}/METADATA +1 -1
  32. {aiecs-1.3.8.dist-info → aiecs-1.4.0.dist-info}/RECORD +36 -9
  33. {aiecs-1.3.8.dist-info → aiecs-1.4.0.dist-info}/WHEEL +0 -0
  34. {aiecs-1.3.8.dist-info → aiecs-1.4.0.dist-info}/entry_points.txt +0 -0
  35. {aiecs-1.3.8.dist-info → aiecs-1.4.0.dist-info}/licenses/LICENSE +0 -0
  36. {aiecs-1.3.8.dist-info → aiecs-1.4.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,443 @@
1
+ """
2
+ Agent Observability
3
+
4
+ Observer pattern and controllers for monitoring agent behavior.
5
+ """
6
+
7
+ import logging
8
+ from typing import Dict, Any, List, Protocol, Optional
9
+ from datetime import datetime
10
+ from abc import ABC, abstractmethod
11
+
12
+ from .base_agent import BaseAIAgent
13
+ from .models import AgentState
14
+
15
+ logger = logging.getLogger(__name__)
16
+
17
+
18
+ class AgentObserver(Protocol):
19
+ """Protocol for observing agent events."""
20
+
21
+ def on_state_changed(
22
+ self,
23
+ agent_id: str,
24
+ old_state: AgentState,
25
+ new_state: AgentState,
26
+ timestamp: datetime
27
+ ) -> None:
28
+ """
29
+ Called when agent state changes.
30
+
31
+ Args:
32
+ agent_id: Agent identifier
33
+ old_state: Previous state
34
+ new_state: New state
35
+ timestamp: Change timestamp
36
+ """
37
+ ...
38
+
39
+ def on_task_started(
40
+ self,
41
+ agent_id: str,
42
+ task_id: str,
43
+ task: Dict[str, Any],
44
+ timestamp: datetime
45
+ ) -> None:
46
+ """
47
+ Called when agent starts a task.
48
+
49
+ Args:
50
+ agent_id: Agent identifier
51
+ task_id: Task identifier
52
+ task: Task specification
53
+ timestamp: Start timestamp
54
+ """
55
+ ...
56
+
57
+ def on_task_completed(
58
+ self,
59
+ agent_id: str,
60
+ task_id: str,
61
+ result: Dict[str, Any],
62
+ timestamp: datetime
63
+ ) -> None:
64
+ """
65
+ Called when agent completes a task.
66
+
67
+ Args:
68
+ agent_id: Agent identifier
69
+ task_id: Task identifier
70
+ result: Task result
71
+ timestamp: Completion timestamp
72
+ """
73
+ ...
74
+
75
+ def on_task_failed(
76
+ self,
77
+ agent_id: str,
78
+ task_id: str,
79
+ error: Exception,
80
+ timestamp: datetime
81
+ ) -> None:
82
+ """
83
+ Called when agent task fails.
84
+
85
+ Args:
86
+ agent_id: Agent identifier
87
+ task_id: Task identifier
88
+ error: Error that occurred
89
+ timestamp: Failure timestamp
90
+ """
91
+ ...
92
+
93
+ def on_tool_called(
94
+ self,
95
+ agent_id: str,
96
+ tool_name: str,
97
+ parameters: Dict[str, Any],
98
+ timestamp: datetime
99
+ ) -> None:
100
+ """
101
+ Called when agent calls a tool.
102
+
103
+ Args:
104
+ agent_id: Agent identifier
105
+ tool_name: Tool name
106
+ parameters: Tool parameters
107
+ timestamp: Call timestamp
108
+ """
109
+ ...
110
+
111
+
112
+ class LoggingObserver:
113
+ """Observer that logs agent events."""
114
+
115
+ def __init__(self, log_level: int = logging.INFO):
116
+ """
117
+ Initialize logging observer.
118
+
119
+ Args:
120
+ log_level: Logging level
121
+ """
122
+ self.logger = logging.getLogger(f"{__name__}.LoggingObserver")
123
+ self.log_level = log_level
124
+
125
+ def on_state_changed(
126
+ self,
127
+ agent_id: str,
128
+ old_state: AgentState,
129
+ new_state: AgentState,
130
+ timestamp: datetime
131
+ ) -> None:
132
+ """Log state change."""
133
+ self.logger.log(
134
+ self.log_level,
135
+ f"Agent {agent_id}: {old_state.value} → {new_state.value}"
136
+ )
137
+
138
+ def on_task_started(
139
+ self,
140
+ agent_id: str,
141
+ task_id: str,
142
+ task: Dict[str, Any],
143
+ timestamp: datetime
144
+ ) -> None:
145
+ """Log task start."""
146
+ self.logger.log(
147
+ self.log_level,
148
+ f"Agent {agent_id}: Task {task_id} started"
149
+ )
150
+
151
+ def on_task_completed(
152
+ self,
153
+ agent_id: str,
154
+ task_id: str,
155
+ result: Dict[str, Any],
156
+ timestamp: datetime
157
+ ) -> None:
158
+ """Log task completion."""
159
+ self.logger.log(
160
+ self.log_level,
161
+ f"Agent {agent_id}: Task {task_id} completed"
162
+ )
163
+
164
+ def on_task_failed(
165
+ self,
166
+ agent_id: str,
167
+ task_id: str,
168
+ error: Exception,
169
+ timestamp: datetime
170
+ ) -> None:
171
+ """Log task failure."""
172
+ self.logger.log(
173
+ self.log_level,
174
+ f"Agent {agent_id}: Task {task_id} failed - {str(error)}"
175
+ )
176
+
177
+ def on_tool_called(
178
+ self,
179
+ agent_id: str,
180
+ tool_name: str,
181
+ parameters: Dict[str, Any],
182
+ timestamp: datetime
183
+ ) -> None:
184
+ """Log tool call."""
185
+ self.logger.log(
186
+ self.log_level,
187
+ f"Agent {agent_id}: Tool '{tool_name}' called"
188
+ )
189
+
190
+
191
+ class MetricsObserver:
192
+ """Observer that collects metrics."""
193
+
194
+ def __init__(self):
195
+ """Initialize metrics observer."""
196
+ self.state_changes: List[Dict[str, Any]] = []
197
+ self.task_events: List[Dict[str, Any]] = []
198
+ self.tool_calls: List[Dict[str, Any]] = []
199
+
200
+ def on_state_changed(
201
+ self,
202
+ agent_id: str,
203
+ old_state: AgentState,
204
+ new_state: AgentState,
205
+ timestamp: datetime
206
+ ) -> None:
207
+ """Record state change."""
208
+ self.state_changes.append({
209
+ "agent_id": agent_id,
210
+ "old_state": old_state.value,
211
+ "new_state": new_state.value,
212
+ "timestamp": timestamp.isoformat(),
213
+ })
214
+
215
+ def on_task_started(
216
+ self,
217
+ agent_id: str,
218
+ task_id: str,
219
+ task: Dict[str, Any],
220
+ timestamp: datetime
221
+ ) -> None:
222
+ """Record task start."""
223
+ self.task_events.append({
224
+ "agent_id": agent_id,
225
+ "task_id": task_id,
226
+ "event": "started",
227
+ "timestamp": timestamp.isoformat(),
228
+ })
229
+
230
+ def on_task_completed(
231
+ self,
232
+ agent_id: str,
233
+ task_id: str,
234
+ result: Dict[str, Any],
235
+ timestamp: datetime
236
+ ) -> None:
237
+ """Record task completion."""
238
+ self.task_events.append({
239
+ "agent_id": agent_id,
240
+ "task_id": task_id,
241
+ "event": "completed",
242
+ "timestamp": timestamp.isoformat(),
243
+ })
244
+
245
+ def on_task_failed(
246
+ self,
247
+ agent_id: str,
248
+ task_id: str,
249
+ error: Exception,
250
+ timestamp: datetime
251
+ ) -> None:
252
+ """Record task failure."""
253
+ self.task_events.append({
254
+ "agent_id": agent_id,
255
+ "task_id": task_id,
256
+ "event": "failed",
257
+ "error": str(error),
258
+ "timestamp": timestamp.isoformat(),
259
+ })
260
+
261
+ def on_tool_called(
262
+ self,
263
+ agent_id: str,
264
+ tool_name: str,
265
+ parameters: Dict[str, Any],
266
+ timestamp: datetime
267
+ ) -> None:
268
+ """Record tool call."""
269
+ self.tool_calls.append({
270
+ "agent_id": agent_id,
271
+ "tool_name": tool_name,
272
+ "timestamp": timestamp.isoformat(),
273
+ })
274
+
275
+ def get_metrics(self) -> Dict[str, Any]:
276
+ """Get collected metrics."""
277
+ return {
278
+ "state_changes": len(self.state_changes),
279
+ "task_events": len(self.task_events),
280
+ "tool_calls": len(self.tool_calls),
281
+ "state_changes_data": self.state_changes,
282
+ "task_events_data": self.task_events,
283
+ "tool_calls_data": self.tool_calls,
284
+ }
285
+
286
+ def clear(self) -> None:
287
+ """Clear all metrics."""
288
+ self.state_changes.clear()
289
+ self.task_events.clear()
290
+ self.tool_calls.clear()
291
+
292
+
293
+ class AgentController:
294
+ """
295
+ Controller for managing agent execution and monitoring.
296
+
297
+ Integrates with observers for event tracking.
298
+ """
299
+
300
+ def __init__(self, agent: BaseAIAgent):
301
+ """
302
+ Initialize agent controller.
303
+
304
+ Args:
305
+ agent: Agent to control
306
+ """
307
+ self.agent = agent
308
+ self.observers: List[AgentObserver] = []
309
+ logger.info(f"AgentController initialized for agent {agent.agent_id}")
310
+
311
+ def add_observer(self, observer: AgentObserver) -> None:
312
+ """
313
+ Add an observer.
314
+
315
+ Args:
316
+ observer: Observer to add
317
+ """
318
+ self.observers.append(observer)
319
+ logger.debug(f"Observer added to agent {self.agent.agent_id}")
320
+
321
+ def remove_observer(self, observer: AgentObserver) -> None:
322
+ """
323
+ Remove an observer.
324
+
325
+ Args:
326
+ observer: Observer to remove
327
+ """
328
+ if observer in self.observers:
329
+ self.observers.remove(observer)
330
+ logger.debug(f"Observer removed from agent {self.agent.agent_id}")
331
+
332
+ def notify_state_changed(
333
+ self,
334
+ old_state: AgentState,
335
+ new_state: AgentState
336
+ ) -> None:
337
+ """Notify observers of state change."""
338
+ timestamp = datetime.utcnow()
339
+ for observer in self.observers:
340
+ try:
341
+ observer.on_state_changed(
342
+ self.agent.agent_id,
343
+ old_state,
344
+ new_state,
345
+ timestamp
346
+ )
347
+ except Exception as e:
348
+ logger.error(f"Observer notification failed: {e}")
349
+
350
+ def notify_task_started(self, task_id: str, task: Dict[str, Any]) -> None:
351
+ """Notify observers of task start."""
352
+ timestamp = datetime.utcnow()
353
+ for observer in self.observers:
354
+ try:
355
+ observer.on_task_started(
356
+ self.agent.agent_id,
357
+ task_id,
358
+ task,
359
+ timestamp
360
+ )
361
+ except Exception as e:
362
+ logger.error(f"Observer notification failed: {e}")
363
+
364
+ def notify_task_completed(self, task_id: str, result: Dict[str, Any]) -> None:
365
+ """Notify observers of task completion."""
366
+ timestamp = datetime.utcnow()
367
+ for observer in self.observers:
368
+ try:
369
+ observer.on_task_completed(
370
+ self.agent.agent_id,
371
+ task_id,
372
+ result,
373
+ timestamp
374
+ )
375
+ except Exception as e:
376
+ logger.error(f"Observer notification failed: {e}")
377
+
378
+ def notify_task_failed(self, task_id: str, error: Exception) -> None:
379
+ """Notify observers of task failure."""
380
+ timestamp = datetime.utcnow()
381
+ for observer in self.observers:
382
+ try:
383
+ observer.on_task_failed(
384
+ self.agent.agent_id,
385
+ task_id,
386
+ error,
387
+ timestamp
388
+ )
389
+ except Exception as e:
390
+ logger.error(f"Observer notification failed: {e}")
391
+
392
+ def notify_tool_called(
393
+ self,
394
+ tool_name: str,
395
+ parameters: Dict[str, Any]
396
+ ) -> None:
397
+ """Notify observers of tool call."""
398
+ timestamp = datetime.utcnow()
399
+ for observer in self.observers:
400
+ try:
401
+ observer.on_tool_called(
402
+ self.agent.agent_id,
403
+ tool_name,
404
+ parameters,
405
+ timestamp
406
+ )
407
+ except Exception as e:
408
+ logger.error(f"Observer notification failed: {e}")
409
+
410
+ async def execute_task_with_observation(
411
+ self,
412
+ task: Dict[str, Any],
413
+ context: Dict[str, Any]
414
+ ) -> Dict[str, Any]:
415
+ """
416
+ Execute task with observer notifications.
417
+
418
+ Args:
419
+ task: Task specification
420
+ context: Execution context
421
+
422
+ Returns:
423
+ Task result
424
+ """
425
+ task_id = task.get('task_id', f"task_{datetime.utcnow().timestamp()}")
426
+
427
+ # Notify start
428
+ self.notify_task_started(task_id, task)
429
+
430
+ try:
431
+ # Execute task
432
+ result = await self.agent.execute_task(task, context)
433
+
434
+ # Notify completion
435
+ self.notify_task_completed(task_id, result)
436
+
437
+ return result
438
+
439
+ except Exception as e:
440
+ # Notify failure
441
+ self.notify_task_failed(task_id, e)
442
+ raise
443
+