agnt5 0.1.0__cp39-abi3-macosx_11_0_arm64.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. agnt5/__init__.py +307 -0
  2. agnt5/__pycache__/__init__.cpython-311.pyc +0 -0
  3. agnt5/__pycache__/agent.cpython-311.pyc +0 -0
  4. agnt5/__pycache__/context.cpython-311.pyc +0 -0
  5. agnt5/__pycache__/durable.cpython-311.pyc +0 -0
  6. agnt5/__pycache__/extraction.cpython-311.pyc +0 -0
  7. agnt5/__pycache__/memory.cpython-311.pyc +0 -0
  8. agnt5/__pycache__/reflection.cpython-311.pyc +0 -0
  9. agnt5/__pycache__/runtime.cpython-311.pyc +0 -0
  10. agnt5/__pycache__/task.cpython-311.pyc +0 -0
  11. agnt5/__pycache__/tool.cpython-311.pyc +0 -0
  12. agnt5/__pycache__/tracing.cpython-311.pyc +0 -0
  13. agnt5/__pycache__/types.cpython-311.pyc +0 -0
  14. agnt5/__pycache__/workflow.cpython-311.pyc +0 -0
  15. agnt5/_core.abi3.so +0 -0
  16. agnt5/agent.py +1086 -0
  17. agnt5/context.py +406 -0
  18. agnt5/durable.py +1050 -0
  19. agnt5/extraction.py +410 -0
  20. agnt5/llm/__init__.py +179 -0
  21. agnt5/llm/__pycache__/__init__.cpython-311.pyc +0 -0
  22. agnt5/llm/__pycache__/anthropic.cpython-311.pyc +0 -0
  23. agnt5/llm/__pycache__/azure.cpython-311.pyc +0 -0
  24. agnt5/llm/__pycache__/base.cpython-311.pyc +0 -0
  25. agnt5/llm/__pycache__/google.cpython-311.pyc +0 -0
  26. agnt5/llm/__pycache__/mistral.cpython-311.pyc +0 -0
  27. agnt5/llm/__pycache__/openai.cpython-311.pyc +0 -0
  28. agnt5/llm/__pycache__/together.cpython-311.pyc +0 -0
  29. agnt5/llm/anthropic.py +319 -0
  30. agnt5/llm/azure.py +348 -0
  31. agnt5/llm/base.py +315 -0
  32. agnt5/llm/google.py +373 -0
  33. agnt5/llm/mistral.py +330 -0
  34. agnt5/llm/model_registry.py +467 -0
  35. agnt5/llm/models.json +227 -0
  36. agnt5/llm/openai.py +334 -0
  37. agnt5/llm/together.py +377 -0
  38. agnt5/memory.py +746 -0
  39. agnt5/reflection.py +514 -0
  40. agnt5/runtime.py +699 -0
  41. agnt5/task.py +476 -0
  42. agnt5/testing.py +451 -0
  43. agnt5/tool.py +516 -0
  44. agnt5/tracing.py +624 -0
  45. agnt5/types.py +210 -0
  46. agnt5/workflow.py +897 -0
  47. agnt5-0.1.0.dist-info/METADATA +93 -0
  48. agnt5-0.1.0.dist-info/RECORD +49 -0
  49. agnt5-0.1.0.dist-info/WHEEL +4 -0
agnt5/context.py ADDED
@@ -0,0 +1,406 @@
1
+ """
2
+ Context management for the AGNT5 SDK.
3
+
4
+ Provides execution context for agents, tools, and workflows with
5
+ support for distributed tracing, state management, and error handling.
6
+ """
7
+
8
+ from typing import Any, Dict, Optional, List, Union, TypeVar, ContextManager, Generic, Type
9
+ from contextvars import ContextVar
10
+ from contextlib import contextmanager
11
+ import uuid
12
+ from datetime import datetime
13
+ import logging
14
+ from dataclasses import dataclass, field
15
+
16
+ from .types import ExecutionContext, ExecutionState, Message
17
+
18
+
19
+ logger = logging.getLogger(__name__)
20
+
21
+ # Context variable for the current execution context
22
+ _current_context: ContextVar[Optional["Context"]] = ContextVar("agnt5_context", default=None)
23
+
24
+ T = TypeVar('T')
25
+
26
+
27
+ @dataclass
28
+ class Context:
29
+ """
30
+ Execution context for AGNT5 operations with durable primitives integration.
31
+
32
+ Provides access to:
33
+ - Execution metadata (ID, timestamps, state)
34
+ - Distributed tracing information
35
+ - Shared state and variables
36
+ - Error handling and recovery
37
+ - Durable function calls via ctx.call()
38
+ - Durable sleep via ctx.sleep()
39
+ - Durable object access via ctx.get_object()
40
+
41
+ Example:
42
+ ```python
43
+ from agnt5 import Context, get_context
44
+
45
+ # Get current context
46
+ ctx = get_context()
47
+
48
+ # Make durable service calls
49
+ result = await ctx.call("data_service", "process", input_data)
50
+
51
+ # Durable sleep
52
+ await ctx.sleep(30)
53
+
54
+ # Access durable objects
55
+ memory = await ctx.get_object(AgentMemory, "user_123")
56
+
57
+ # Store state
58
+ await ctx.set("user_id", "123")
59
+ user_id = await ctx.get("user_id")
60
+ ```
61
+ """
62
+
63
+ execution_id: str = field(default_factory=lambda: str(uuid.uuid4()))
64
+ parent_id: Optional[str] = None
65
+ name: Optional[str] = None
66
+
67
+ # Execution state
68
+ state: ExecutionState = ExecutionState.PENDING
69
+ started_at: Optional[datetime] = None
70
+ completed_at: Optional[datetime] = None
71
+
72
+ # Metadata
73
+ metadata: Dict[str, Any] = field(default_factory=dict)
74
+
75
+ # State storage
76
+ _state: Dict[str, Any] = field(default_factory=dict, init=False)
77
+
78
+ # Conversation history (for agents)
79
+ _messages: List[Message] = field(default_factory=list, init=False)
80
+
81
+ # Error information
82
+ error: Optional[Exception] = None
83
+ error_count: int = 0
84
+
85
+ def __post_init__(self):
86
+ """Initialize context after creation."""
87
+ if self.state == ExecutionState.RUNNING and not self.started_at:
88
+ self.started_at = datetime.utcnow()
89
+
90
+ async def set(self, key: str, value: Any) -> None:
91
+ """
92
+ Set a value in the context state with durable persistence.
93
+
94
+ Args:
95
+ key: State key
96
+ value: State value
97
+ """
98
+ from .durable import _runtime_client
99
+
100
+ if _runtime_client:
101
+ await _runtime_client.save_state(key, value)
102
+ else:
103
+ self._state[key] = value
104
+
105
+ async def get(self, key: str, default: Any = None) -> Any:
106
+ """
107
+ Get a value from the context state with durable persistence.
108
+
109
+ Args:
110
+ key: State key
111
+ default: Default value if key not found
112
+
113
+ Returns:
114
+ State value or default
115
+ """
116
+ from .durable import _runtime_client
117
+
118
+ if _runtime_client:
119
+ return await _runtime_client.load_state(key, default)
120
+ else:
121
+ return self._state.get(key, default)
122
+
123
+ async def update(self, **kwargs) -> None:
124
+ """Update multiple state values with durable persistence."""
125
+ for key, value in kwargs.items():
126
+ await self.set(key, value)
127
+
128
+ async def clear(self) -> None:
129
+ """Clear all state values with durable persistence."""
130
+ from .durable import _runtime_client
131
+
132
+ if _runtime_client:
133
+ for key in list(self._state.keys()):
134
+ await _runtime_client.delete_state(key)
135
+ else:
136
+ self._state.clear()
137
+
138
+ @property
139
+ def state_dict(self) -> Dict[str, Any]:
140
+ """Get a copy of the state dictionary."""
141
+ return self._state.copy()
142
+
143
+ def add_message(self, message: Message) -> None:
144
+ """Add a message to the conversation history."""
145
+ self._messages.append(message)
146
+
147
+ def get_messages(self) -> List[Message]:
148
+ """Get the conversation history."""
149
+ return self._messages.copy()
150
+
151
+ def clear_messages(self) -> None:
152
+ """Clear the conversation history."""
153
+ self._messages.clear()
154
+
155
+ def create_child(self, name: str) -> "Context":
156
+ """
157
+ Create a child context.
158
+
159
+ Args:
160
+ name: Name for the child context
161
+
162
+ Returns:
163
+ Child context
164
+ """
165
+ child = Context(
166
+ execution_id=str(uuid.uuid4()),
167
+ parent_id=self.execution_id,
168
+ name=name,
169
+ state=ExecutionState.PENDING,
170
+ metadata=self.metadata.copy(),
171
+ )
172
+
173
+ # Copy parent state
174
+ child._state = self._state.copy()
175
+
176
+ return child
177
+
178
+ def record_error(self, error: Exception) -> None:
179
+ """Record an error in the context."""
180
+ self.error = error
181
+ self.error_count += 1
182
+ logger.error(f"Error in context {self.execution_id}: {error}")
183
+
184
+ async def call(self, service: str, method: str, *args, **kwargs) -> Any:
185
+ """
186
+ Make a durable external service call via the runtime.
187
+
188
+ Args:
189
+ service: Service name
190
+ method: Method name
191
+ *args: Method arguments
192
+ **kwargs: Method keyword arguments
193
+
194
+ Returns:
195
+ Service response
196
+ """
197
+ from .durable import _runtime_client
198
+
199
+ if _runtime_client:
200
+ return await _runtime_client.call_service(service, method, *args, **kwargs)
201
+ else:
202
+ # Fallback to mock response for testing
203
+ logger.info(f"Mock service call: {service}.{method}")
204
+ return f"mock_response_from_{service}_{method}"
205
+
206
+ async def sleep(self, seconds: float) -> None:
207
+ """
208
+ Durable sleep that survives restarts.
209
+
210
+ Args:
211
+ seconds: Duration to sleep in seconds
212
+ """
213
+ from .durable import _runtime_client
214
+ import asyncio
215
+
216
+ if _runtime_client:
217
+ await _runtime_client.durable_sleep(seconds)
218
+ else:
219
+ # Fallback for testing
220
+ logger.info(f"Mock durable sleep: {seconds} seconds")
221
+ await asyncio.sleep(seconds)
222
+
223
+ async def get_object(self, object_class: Type[Any], object_id: str) -> Any:
224
+ """
225
+ Get or create a durable object instance.
226
+
227
+ Args:
228
+ object_class: The durable object class
229
+ object_id: Unique identifier for the object instance
230
+
231
+ Returns:
232
+ Durable object instance
233
+ """
234
+ from .durable import _runtime_client
235
+
236
+ if _runtime_client:
237
+ return await _runtime_client.get_object(object_class, object_id)
238
+ else:
239
+ # Fallback: create object directly
240
+ return await object_class.get_or_create(object_id)
241
+
242
+ def mark_completed(self, success: bool = True) -> None:
243
+ """Mark the context as completed."""
244
+ self.completed_at = datetime.utcnow()
245
+ self.state = ExecutionState.COMPLETED if success else ExecutionState.FAILED
246
+
247
+ def to_dict(self) -> Dict[str, Any]:
248
+ """Convert context to dictionary for serialization."""
249
+ return {
250
+ "execution_id": self.execution_id,
251
+ "parent_id": self.parent_id,
252
+ "name": self.name,
253
+ "state": self.state.value,
254
+ "started_at": self.started_at.isoformat() if self.started_at else None,
255
+ "completed_at": self.completed_at.isoformat() if self.completed_at else None,
256
+ "metadata": self.metadata,
257
+ "state_data": self._state,
258
+ "error": str(self.error) if self.error else None,
259
+ "error_count": self.error_count,
260
+ }
261
+
262
+ @classmethod
263
+ def from_dict(cls, data: Dict[str, Any]) -> "Context":
264
+ """Create context from dictionary."""
265
+ ctx = cls(
266
+ execution_id=data["execution_id"],
267
+ parent_id=data.get("parent_id"),
268
+ name=data.get("name"),
269
+ state=ExecutionState(data["state"]),
270
+ metadata=data.get("metadata", {}),
271
+ )
272
+
273
+ # Restore timestamps
274
+ if data.get("started_at"):
275
+ ctx.started_at = datetime.fromisoformat(data["started_at"])
276
+ if data.get("completed_at"):
277
+ ctx.completed_at = datetime.fromisoformat(data["completed_at"])
278
+
279
+ # Restore state
280
+ ctx._state = data.get("state_data", {})
281
+
282
+ # Restore error info
283
+ ctx.error_count = data.get("error_count", 0)
284
+
285
+ return ctx
286
+
287
+
288
+ def get_context() -> Context:
289
+ """
290
+ Get the current execution context.
291
+
292
+ Returns:
293
+ Current context or creates a new one if none exists
294
+ """
295
+ ctx = _current_context.get()
296
+ if ctx is None:
297
+ ctx = Context()
298
+ _current_context.set(ctx)
299
+ return ctx
300
+
301
+
302
+ def set_context(ctx: Context) -> None:
303
+ """
304
+ Set the current execution context.
305
+
306
+ Args:
307
+ ctx: Context to set as current
308
+ """
309
+ _current_context.set(ctx)
310
+
311
+
312
+ @contextmanager
313
+ def use_context(ctx: Context) -> ContextManager[Context]:
314
+ """
315
+ Context manager to temporarily use a specific context.
316
+
317
+ Example:
318
+ ```python
319
+ ctx = Context(name="my-operation")
320
+
321
+ with use_context(ctx):
322
+ # All operations here use ctx
323
+ agent = Agent("my-agent")
324
+ await agent.run("Hello")
325
+ ```
326
+ """
327
+ previous = _current_context.get()
328
+ _current_context.set(ctx)
329
+
330
+ try:
331
+ yield ctx
332
+ finally:
333
+ _current_context.set(previous)
334
+
335
+
336
+ @contextmanager
337
+ def create_context(
338
+ name: Optional[str] = None,
339
+ metadata: Optional[Dict[str, Any]] = None,
340
+ ) -> ContextManager[Context]:
341
+ """
342
+ Create and use a new context.
343
+
344
+ Example:
345
+ ```python
346
+ with create_context("data-processing") as ctx:
347
+ # Operations in this context
348
+ ctx.set("batch_size", 100)
349
+ process_data()
350
+ ```
351
+ """
352
+ ctx = Context(
353
+ name=name,
354
+ metadata=metadata or {},
355
+ state=ExecutionState.RUNNING,
356
+ )
357
+
358
+ with use_context(ctx):
359
+ yield ctx
360
+
361
+
362
+ class ContextualValue(Generic[T]):
363
+ """
364
+ A value that is bound to the current context.
365
+
366
+ Example:
367
+ ```python
368
+ # Define a contextual value
369
+ current_user = ContextualValue[str]("current_user")
370
+
371
+ # Set in context
372
+ with create_context("request") as ctx:
373
+ current_user.set("alice")
374
+
375
+ # Get from anywhere in the call stack
376
+ user = current_user.get() # "alice"
377
+ ```
378
+ """
379
+
380
+ def __init__(self, key: str, default: Optional[T] = None):
381
+ """Initialize a contextual value."""
382
+ self.key = key
383
+ self.default = default
384
+
385
+ def get(self) -> Optional[T]:
386
+ """Get the value from the current context."""
387
+ ctx = get_context()
388
+ return ctx.get(self.key, self.default)
389
+
390
+ def set(self, value: T) -> None:
391
+ """Set the value in the current context."""
392
+ ctx = get_context()
393
+ ctx.set(self.key, value)
394
+
395
+ def clear(self) -> None:
396
+ """Clear the value from the current context."""
397
+ ctx = get_context()
398
+ if self.key in ctx._state:
399
+ del ctx._state[self.key]
400
+
401
+
402
+ # Common contextual values
403
+ current_agent = ContextualValue[str]("current_agent")
404
+ current_workflow = ContextualValue[str]("current_workflow")
405
+ current_user = ContextualValue[str]("current_user")
406
+ current_tenant = ContextualValue[str]("current_tenant")