hammad-python 0.0.30__py3-none-any.whl → 0.0.31__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 (137) hide show
  1. ham/__init__.py +10 -0
  2. {hammad_python-0.0.30.dist-info → hammad_python-0.0.31.dist-info}/METADATA +6 -32
  3. hammad_python-0.0.31.dist-info/RECORD +6 -0
  4. hammad/__init__.py +0 -84
  5. hammad/_internal.py +0 -256
  6. hammad/_main.py +0 -226
  7. hammad/cache/__init__.py +0 -40
  8. hammad/cache/base_cache.py +0 -181
  9. hammad/cache/cache.py +0 -169
  10. hammad/cache/decorators.py +0 -261
  11. hammad/cache/file_cache.py +0 -80
  12. hammad/cache/ttl_cache.py +0 -74
  13. hammad/cli/__init__.py +0 -33
  14. hammad/cli/animations.py +0 -573
  15. hammad/cli/plugins.py +0 -867
  16. hammad/cli/styles/__init__.py +0 -55
  17. hammad/cli/styles/settings.py +0 -139
  18. hammad/cli/styles/types.py +0 -358
  19. hammad/cli/styles/utils.py +0 -634
  20. hammad/data/__init__.py +0 -90
  21. hammad/data/collections/__init__.py +0 -49
  22. hammad/data/collections/collection.py +0 -326
  23. hammad/data/collections/indexes/__init__.py +0 -37
  24. hammad/data/collections/indexes/qdrant/__init__.py +0 -1
  25. hammad/data/collections/indexes/qdrant/index.py +0 -723
  26. hammad/data/collections/indexes/qdrant/settings.py +0 -94
  27. hammad/data/collections/indexes/qdrant/utils.py +0 -210
  28. hammad/data/collections/indexes/tantivy/__init__.py +0 -1
  29. hammad/data/collections/indexes/tantivy/index.py +0 -426
  30. hammad/data/collections/indexes/tantivy/settings.py +0 -40
  31. hammad/data/collections/indexes/tantivy/utils.py +0 -176
  32. hammad/data/configurations/__init__.py +0 -35
  33. hammad/data/configurations/configuration.py +0 -564
  34. hammad/data/models/__init__.py +0 -50
  35. hammad/data/models/extensions/__init__.py +0 -4
  36. hammad/data/models/extensions/pydantic/__init__.py +0 -42
  37. hammad/data/models/extensions/pydantic/converters.py +0 -759
  38. hammad/data/models/fields.py +0 -546
  39. hammad/data/models/model.py +0 -1078
  40. hammad/data/models/utils.py +0 -280
  41. hammad/data/sql/__init__.py +0 -24
  42. hammad/data/sql/database.py +0 -576
  43. hammad/data/sql/types.py +0 -127
  44. hammad/data/types/__init__.py +0 -75
  45. hammad/data/types/file.py +0 -431
  46. hammad/data/types/multimodal/__init__.py +0 -36
  47. hammad/data/types/multimodal/audio.py +0 -200
  48. hammad/data/types/multimodal/image.py +0 -182
  49. hammad/data/types/text.py +0 -1308
  50. hammad/formatting/__init__.py +0 -33
  51. hammad/formatting/json/__init__.py +0 -27
  52. hammad/formatting/json/converters.py +0 -158
  53. hammad/formatting/text/__init__.py +0 -63
  54. hammad/formatting/text/converters.py +0 -723
  55. hammad/formatting/text/markdown.py +0 -131
  56. hammad/formatting/yaml/__init__.py +0 -26
  57. hammad/formatting/yaml/converters.py +0 -5
  58. hammad/genai/__init__.py +0 -217
  59. hammad/genai/a2a/__init__.py +0 -32
  60. hammad/genai/a2a/workers.py +0 -552
  61. hammad/genai/agents/__init__.py +0 -59
  62. hammad/genai/agents/agent.py +0 -1973
  63. hammad/genai/agents/run.py +0 -1024
  64. hammad/genai/agents/types/__init__.py +0 -42
  65. hammad/genai/agents/types/agent_context.py +0 -13
  66. hammad/genai/agents/types/agent_event.py +0 -128
  67. hammad/genai/agents/types/agent_hooks.py +0 -220
  68. hammad/genai/agents/types/agent_messages.py +0 -31
  69. hammad/genai/agents/types/agent_response.py +0 -125
  70. hammad/genai/agents/types/agent_stream.py +0 -327
  71. hammad/genai/graphs/__init__.py +0 -125
  72. hammad/genai/graphs/_utils.py +0 -190
  73. hammad/genai/graphs/base.py +0 -1828
  74. hammad/genai/graphs/plugins.py +0 -316
  75. hammad/genai/graphs/types.py +0 -638
  76. hammad/genai/models/__init__.py +0 -1
  77. hammad/genai/models/embeddings/__init__.py +0 -43
  78. hammad/genai/models/embeddings/model.py +0 -226
  79. hammad/genai/models/embeddings/run.py +0 -163
  80. hammad/genai/models/embeddings/types/__init__.py +0 -37
  81. hammad/genai/models/embeddings/types/embedding_model_name.py +0 -75
  82. hammad/genai/models/embeddings/types/embedding_model_response.py +0 -76
  83. hammad/genai/models/embeddings/types/embedding_model_run_params.py +0 -66
  84. hammad/genai/models/embeddings/types/embedding_model_settings.py +0 -47
  85. hammad/genai/models/language/__init__.py +0 -57
  86. hammad/genai/models/language/model.py +0 -1098
  87. hammad/genai/models/language/run.py +0 -878
  88. hammad/genai/models/language/types/__init__.py +0 -40
  89. hammad/genai/models/language/types/language_model_instructor_mode.py +0 -47
  90. hammad/genai/models/language/types/language_model_messages.py +0 -28
  91. hammad/genai/models/language/types/language_model_name.py +0 -239
  92. hammad/genai/models/language/types/language_model_request.py +0 -127
  93. hammad/genai/models/language/types/language_model_response.py +0 -217
  94. hammad/genai/models/language/types/language_model_response_chunk.py +0 -56
  95. hammad/genai/models/language/types/language_model_settings.py +0 -89
  96. hammad/genai/models/language/types/language_model_stream.py +0 -600
  97. hammad/genai/models/language/utils/__init__.py +0 -28
  98. hammad/genai/models/language/utils/requests.py +0 -421
  99. hammad/genai/models/language/utils/structured_outputs.py +0 -135
  100. hammad/genai/models/model_provider.py +0 -4
  101. hammad/genai/models/multimodal.py +0 -47
  102. hammad/genai/models/reranking.py +0 -26
  103. hammad/genai/types/__init__.py +0 -1
  104. hammad/genai/types/base.py +0 -215
  105. hammad/genai/types/history.py +0 -290
  106. hammad/genai/types/tools.py +0 -507
  107. hammad/logging/__init__.py +0 -35
  108. hammad/logging/decorators.py +0 -834
  109. hammad/logging/logger.py +0 -1018
  110. hammad/mcp/__init__.py +0 -53
  111. hammad/mcp/client/__init__.py +0 -35
  112. hammad/mcp/client/client.py +0 -624
  113. hammad/mcp/client/client_service.py +0 -400
  114. hammad/mcp/client/settings.py +0 -178
  115. hammad/mcp/servers/__init__.py +0 -26
  116. hammad/mcp/servers/launcher.py +0 -1161
  117. hammad/runtime/__init__.py +0 -32
  118. hammad/runtime/decorators.py +0 -142
  119. hammad/runtime/run.py +0 -299
  120. hammad/service/__init__.py +0 -49
  121. hammad/service/create.py +0 -527
  122. hammad/service/decorators.py +0 -283
  123. hammad/types.py +0 -288
  124. hammad/typing/__init__.py +0 -435
  125. hammad/web/__init__.py +0 -43
  126. hammad/web/http/__init__.py +0 -1
  127. hammad/web/http/client.py +0 -944
  128. hammad/web/models.py +0 -275
  129. hammad/web/openapi/__init__.py +0 -1
  130. hammad/web/openapi/client.py +0 -740
  131. hammad/web/search/__init__.py +0 -1
  132. hammad/web/search/client.py +0 -1023
  133. hammad/web/utils.py +0 -472
  134. hammad_python-0.0.30.dist-info/RECORD +0 -135
  135. {hammad → ham}/py.typed +0 -0
  136. {hammad_python-0.0.30.dist-info → hammad_python-0.0.31.dist-info}/WHEEL +0 -0
  137. {hammad_python-0.0.30.dist-info → hammad_python-0.0.31.dist-info}/licenses/LICENSE +0 -0
@@ -1,42 +0,0 @@
1
- """hammad.genai.agents.types"""
2
-
3
- from typing import TYPE_CHECKING
4
- from ...._internal import create_getattr_importer
5
-
6
-
7
- if TYPE_CHECKING:
8
- from .agent_event import AgentEvent
9
- from .agent_hooks import HookManager, HookDecorator
10
- from .agent_response import (
11
- AgentResponse,
12
- _create_agent_response_from_language_model_response,
13
- )
14
- from .agent_stream import AgentStream, AgentResponseChunk
15
- from .agent_context import AgentContext
16
- from .agent_messages import AgentMessages
17
-
18
-
19
- __all__ = [
20
- # hammad.genai.agents.types.agent_event
21
- "AgentEvent",
22
- # hammad.genai.agents.types.agent_hooks
23
- "HookManager",
24
- "HookDecorator",
25
- # hammad.genai.agents.types.agent_response
26
- "AgentResponse",
27
- "_create_agent_response_from_language_model_response",
28
- # hammad.genai.agents.types.agent_stream
29
- "AgentStream",
30
- "AgentResponseChunk",
31
- # hammad.genai.agents.types.agent_context
32
- "AgentContext",
33
- # hammad.genai.agents.types.agent_messages
34
- "AgentMessages",
35
- ]
36
-
37
-
38
- __getattr__ = create_getattr_importer(__all__)
39
-
40
-
41
- def __dir__() -> list[str]:
42
- return __all__
@@ -1,13 +0,0 @@
1
- """hammad.genai.agents.types.agent_context"""
2
-
3
- from typing import Dict, Any, TypeVar
4
- from pydantic import BaseModel
5
-
6
-
7
- __all__ = [
8
- "AgentContext",
9
- ]
10
-
11
-
12
- AgentContext = TypeVar("AgentContext", bound=BaseModel | Dict[str, Any])
13
- """A context object that can be used to store information about the agent's state."""
@@ -1,128 +0,0 @@
1
- """hammad.genai.agents.types.agent_event"""
2
-
3
- from typing import Any, Dict, Optional, Literal
4
- from openai.types.chat import ChatCompletionMessageParam, ChatCompletionContentPartParam
5
-
6
- from ...types.base import BaseGenAIModelEvent
7
-
8
-
9
- __all__ = [
10
- "AgentEvent",
11
- ]
12
-
13
-
14
- class AgentEvent(BaseGenAIModelEvent[Any]):
15
- """Base class for all agent events with universal event checking.
16
-
17
- This class extends BaseGenAIModelEvent to provide agent-specific
18
- event handling capabilities.
19
- """
20
-
21
- type: Literal["agent"] = "agent"
22
- """The type of the model. Always 'agent'."""
23
-
24
- model: str = "agent"
25
- """The model that generated this event."""
26
-
27
- output: Any = None
28
- """The event data/output."""
29
-
30
- event_type: str
31
- """The specific type of event (e.g., 'context_update', 'tool_call', etc.)."""
32
-
33
- metadata: Dict[str, Any] = {}
34
- """Additional metadata for the event."""
35
-
36
- def __init__(
37
- self,
38
- event_type: str,
39
- data: Any = None,
40
- metadata: Optional[Dict[str, Any]] = None,
41
- **kwargs: Any,
42
- ):
43
- """Initialize an AgentEvent.
44
-
45
- Args:
46
- event_type: The type of event
47
- data: The event data
48
- metadata: Additional metadata
49
- **kwargs: Additional keyword arguments
50
- """
51
- super().__init__(
52
- output=data, event_type=event_type, metadata=metadata or {}, **kwargs
53
- )
54
-
55
- def is_event(self, event_type: str) -> bool:
56
- """Universal event type checker."""
57
- return self.event_type == event_type
58
-
59
- def is_event_category(self, category: str) -> bool:
60
- """Check if event belongs to a category (e.g., 'tool' matches 'tool_call', 'tool_execution')."""
61
- return self.event_type.startswith(category)
62
-
63
- def has_metadata(self, key: str) -> bool:
64
- """Check if event has specific metadata."""
65
- return key in self.metadata
66
-
67
- def get_metadata(self, key: str, default: Any = None) -> Any:
68
- """Get metadata value."""
69
- return self.metadata.get(key, default)
70
-
71
- # Common event type checks (for convenience)
72
- def is_context_update(self) -> bool:
73
- return self.is_event("context_update")
74
-
75
- def is_tool_call(self) -> bool:
76
- return self.is_event("tool_call")
77
-
78
- def is_tool_execution(self) -> bool:
79
- return self.is_event("tool_execution")
80
-
81
- def is_tool_response(self) -> bool:
82
- return self.is_event("tool_response")
83
-
84
- def is_final_response(self) -> bool:
85
- return self.is_event("final_response")
86
-
87
- def is_step_start(self) -> bool:
88
- return self.is_event("step_start")
89
-
90
- def is_step_end(self) -> bool:
91
- return self.is_event("step_end")
92
-
93
- def is_error(self) -> bool:
94
- return self.is_event("error")
95
-
96
- def is_stream_chunk(self) -> bool:
97
- return self.is_event("stream_chunk")
98
-
99
- # Category checks
100
- def is_tool_event(self) -> bool:
101
- return self.is_event_category("tool")
102
-
103
- def is_context_event(self) -> bool:
104
- return self.is_event_category("context")
105
-
106
- def is_stream_event(self) -> bool:
107
- return self.is_event_category("stream")
108
-
109
- def to_message(self) -> ChatCompletionMessageParam:
110
- """Convert the event to a chat completion message."""
111
- content = f"Event: {self.event_type}"
112
- if self.output:
113
- content += f"\nData: {self.output}"
114
- if self.metadata:
115
- content += f"\nMetadata: {self.metadata}"
116
-
117
- return {"role": "assistant", "content": content}
118
-
119
- def to_content_part(self) -> ChatCompletionContentPartParam:
120
- """Convert the event to a chat completion content part."""
121
- content = f"Event: {self.event_type}"
122
- if self.output:
123
- content += f" - {self.output}"
124
-
125
- return {"type": "text", "text": content}
126
-
127
- def __repr__(self) -> str:
128
- return f"AgentEvent(type='{self.event_type}', data={self.output}, metadata={self.metadata})"
@@ -1,220 +0,0 @@
1
- """hammad.genai.agents.types.agent_hooks"""
2
-
3
- from typing import Any, Dict, List, Callable, Optional
4
- from .agent_event import AgentEvent
5
-
6
-
7
- __all__ = [
8
- "HookManager",
9
- "HookDecorator",
10
- ]
11
-
12
-
13
- class HookManager:
14
- """Manages hooks for agent events."""
15
-
16
- def __init__(self):
17
- self.hooks: Dict[str, List[Callable]] = {}
18
- self.specific_hooks: Dict[str, Dict[str, List[Callable]]] = {}
19
-
20
- def register_hook(
21
- self, event_type: str, callback: Callable, specific_name: Optional[str] = None
22
- ):
23
- """Register a hook for an event type.
24
-
25
- Args:
26
- event_type: The type of event to hook into
27
- callback: The callback function to execute
28
- specific_name: Optional specific name for targeted hooks
29
- """
30
- if specific_name:
31
- if event_type not in self.specific_hooks:
32
- self.specific_hooks[event_type] = {}
33
- if specific_name not in self.specific_hooks[event_type]:
34
- self.specific_hooks[event_type][specific_name] = []
35
- self.specific_hooks[event_type][specific_name].append(callback)
36
- else:
37
- if event_type not in self.hooks:
38
- self.hooks[event_type] = []
39
- self.hooks[event_type].append(callback)
40
-
41
- def trigger_hooks(
42
- self, event_type: str, data: Any, specific_name: Optional[str] = None
43
- ) -> Any:
44
- """Trigger hooks for an event type.
45
-
46
- Args:
47
- event_type: The type of event
48
- data: The event data
49
- specific_name: Optional specific name for targeted hooks
50
-
51
- Returns:
52
- The potentially modified data after running through hooks
53
- """
54
- result = data
55
-
56
- # Trigger general hooks
57
- if event_type in self.hooks:
58
- for hook in self.hooks[event_type]:
59
- hook_result = hook(result)
60
- if hook_result is not None:
61
- result = hook_result
62
-
63
- # Trigger specific hooks
64
- if specific_name and event_type in self.specific_hooks:
65
- if specific_name in self.specific_hooks[event_type]:
66
- for hook in self.specific_hooks[event_type][specific_name]:
67
- hook_result = hook(result)
68
- if hook_result is not None:
69
- result = hook_result
70
-
71
- return result
72
-
73
- def trigger_event(
74
- self, event: AgentEvent, specific_name: Optional[str] = None
75
- ) -> Any:
76
- """Trigger hooks for an AgentEvent.
77
-
78
- Args:
79
- event: The AgentEvent instance
80
- specific_name: Optional specific name for targeted hooks
81
-
82
- Returns:
83
- The potentially modified event data after running through hooks
84
- """
85
- return self.trigger_hooks(event.event_type, event.output, specific_name)
86
-
87
- def clear_hooks(
88
- self, event_type: Optional[str] = None, specific_name: Optional[str] = None
89
- ):
90
- """Clear hooks for a specific event type or all hooks.
91
-
92
- Args:
93
- event_type: Optional event type to clear (clears all if None)
94
- specific_name: Optional specific name to clear
95
- """
96
- if event_type is None:
97
- self.hooks.clear()
98
- self.specific_hooks.clear()
99
- else:
100
- if event_type in self.hooks:
101
- if specific_name is None:
102
- del self.hooks[event_type]
103
-
104
- if event_type in self.specific_hooks:
105
- if specific_name is None:
106
- del self.specific_hooks[event_type]
107
- elif specific_name in self.specific_hooks[event_type]:
108
- del self.specific_hooks[event_type][specific_name]
109
-
110
- def list_hooks(self) -> Dict[str, Any]:
111
- """List all registered hooks.
112
-
113
- Returns:
114
- Dictionary containing all hooks information
115
- """
116
- return {
117
- "general_hooks": {k: len(v) for k, v in self.hooks.items()},
118
- "specific_hooks": {
119
- k: {sk: len(sv) for sk, sv in v.items()}
120
- for k, v in self.specific_hooks.items()
121
- },
122
- }
123
-
124
-
125
- class HookDecorator:
126
- """Provides type-hinted hook decorators with extensible event system."""
127
-
128
- def __init__(self, hook_manager: HookManager):
129
- self.hook_manager = hook_manager
130
- self._event_types = set()
131
-
132
- def __call__(self, event_type: str, specific_name: Optional[str] = None):
133
- """Register a hook for any event type.
134
-
135
- Args:
136
- event_type: The type of event to hook into
137
- specific_name: Optional specific name for targeted hooks
138
-
139
- Returns:
140
- Decorator function
141
- """
142
-
143
- def decorator(func: Callable):
144
- self.hook_manager.register_hook(event_type, func, specific_name)
145
- self._event_types.add(event_type)
146
- return func
147
-
148
- return decorator
149
-
150
- def get_registered_event_types(self) -> set:
151
- """Get all registered event types."""
152
- return self._event_types.copy()
153
-
154
- def supports_event(self, event_type: str) -> bool:
155
- """Check if an event type is supported."""
156
- return event_type in self._event_types
157
-
158
- # Convenience decorators for common events
159
- def on_context_update(self, specific_name: Optional[str] = None):
160
- """Decorator for context update events."""
161
- return self.__call__("context_update", specific_name)
162
-
163
- def on_tool_call(self, specific_name: Optional[str] = None):
164
- """Decorator for tool call events."""
165
- return self.__call__("tool_call", specific_name)
166
-
167
- def on_tool_execution(self, specific_name: Optional[str] = None):
168
- """Decorator for tool execution events."""
169
- return self.__call__("tool_execution", specific_name)
170
-
171
- def on_tool_response(self, specific_name: Optional[str] = None):
172
- """Decorator for tool response events."""
173
- return self.__call__("tool_response", specific_name)
174
-
175
- def on_final_response(self, specific_name: Optional[str] = None):
176
- """Decorator for final response events."""
177
- return self.__call__("final_response", specific_name)
178
-
179
- def on_step_start(self, specific_name: Optional[str] = None):
180
- """Decorator for step start events."""
181
- return self.__call__("step_start", specific_name)
182
-
183
- def on_step_end(self, specific_name: Optional[str] = None):
184
- """Decorator for step end events."""
185
- return self.__call__("step_end", specific_name)
186
-
187
- def on_error(self, specific_name: Optional[str] = None):
188
- """Decorator for error events."""
189
- return self.__call__("error", specific_name)
190
-
191
- def on_stream_chunk(self, specific_name: Optional[str] = None):
192
- """Decorator for stream chunk events."""
193
- return self.__call__("stream_chunk", specific_name)
194
-
195
- # Dynamic event type classes - these are created dynamically
196
- # based on the actual events that occur in the system
197
- def __getattr__(self, name: str):
198
- """Dynamically create event type classes for better type hinting."""
199
- if name.startswith("_"):
200
- raise AttributeError(
201
- f"'{self.__class__.__name__}' object has no attribute '{name}'"
202
- )
203
-
204
- # Create a dynamic class for this event type
205
- class DynamicEventType:
206
- def __init__(
207
- self, event_data: Any = None, metadata: Optional[Dict[str, Any]] = None
208
- ):
209
- self.event_data = event_data
210
- self.metadata = metadata or {}
211
-
212
- def __repr__(self):
213
- return f"{name}(data={self.event_data}, metadata={self.metadata})"
214
-
215
- DynamicEventType.__name__ = name
216
- DynamicEventType.__qualname__ = f"{self.__class__.__name__}.{name}"
217
-
218
- # Cache the class
219
- setattr(self, name, DynamicEventType)
220
- return DynamicEventType
@@ -1,31 +0,0 @@
1
- """hammad.genai.agents.types.agent_messages"""
2
-
3
- from typing import TypeAlias, Union, List, Any, TYPE_CHECKING
4
-
5
- from ...models.language.types import LanguageModelMessages
6
-
7
- if TYPE_CHECKING:
8
- from openai.types.chat import ChatCompletionMessageParam
9
- from ...types.history import History
10
-
11
-
12
- __all__ = [
13
- "AgentMessages",
14
- ]
15
-
16
-
17
- AgentMessages: TypeAlias = Union[
18
- str,
19
- "ChatCompletionMessageParam",
20
- "List[ChatCompletionMessageParam]",
21
- "History",
22
- LanguageModelMessages,
23
- Any,
24
- ]
25
- """Type alias for agent message inputs that extends LanguageModelMessages to include History objects.
26
-
27
- This type alias allows agents to accept:
28
- - All standard LanguageModelMessages types (str, ChatCompletionMessageParam, List[ChatCompletionMessageParam])
29
- - History objects for conversation history management
30
- - Any other type for flexibility
31
- """
@@ -1,125 +0,0 @@
1
- """hammad.genai.agents.types.agent_response"""
2
-
3
- from typing import List, Any, TypeVar, Literal, Generic
4
- from pydantic import Field
5
-
6
- from ....cache import cached
7
- from ....typing import get_type_description
8
- from ...models.language.types import (
9
- LanguageModelResponse,
10
- )
11
-
12
- from .agent_context import AgentContext
13
-
14
- __all__ = [
15
- "AgentResponse",
16
- "_create_agent_response_from_language_model_response",
17
- ]
18
-
19
-
20
- T = TypeVar("T")
21
-
22
-
23
- def _create_agent_response_from_language_model_response(
24
- response: LanguageModelResponse[T],
25
- steps: List[LanguageModelResponse[str]] | None = None,
26
- context: Any = None,
27
- ) -> "AgentResponse[T]":
28
- """Create a AgentResponse from a LanguageModelResponse."""
29
- try:
30
- return AgentResponse(
31
- type="agent",
32
- model=response.model,
33
- output=response.output,
34
- content=response.content,
35
- completion=response.completion,
36
- refusal=response.refusal,
37
- steps=steps or [],
38
- context=context,
39
- )
40
- except Exception as e:
41
- raise ValueError(
42
- "Failed to create AgentResponse from LanguageModelResponse."
43
- ) from e
44
-
45
-
46
- class AgentResponse(LanguageModelResponse[T], Generic[T, AgentContext]):
47
- """A response generated by an agent, that includes the steps and final
48
- output during the agent's execution."""
49
-
50
- type: Literal["agent"] = "agent"
51
- """The type of the response. Always `agent`."""
52
-
53
- steps: List[LanguageModelResponse[str]] = Field(default_factory=list)
54
- """
55
- A list of steps taken by the agent **BEFORE** its final output.
56
-
57
- NOTE: If the final output was also the first step, this will be
58
- empty.
59
- """
60
-
61
- context: AgentContext | None = None
62
- """
63
- The final context object after agent execution.
64
-
65
- This is always the final version of the context after any updates
66
- have been applied during the agent's execution.
67
- """
68
-
69
- @cached
70
- def __str__(self) -> str:
71
- """Pretty prints the response object."""
72
- output = ">>> AgentResponse:"
73
-
74
- if self.output or self.content:
75
- output += f"\n{self.output if self.output else self.content}"
76
- else:
77
- output += f"\n{self.completion}"
78
-
79
- output += f"\n\n>>> Model: {self.model}"
80
- # NOTE:
81
- # added +1 to include final step in the output
82
- output += f"\n>>> Steps: {len(self.steps) + 1}"
83
- output += f"\n>>> Output Type: {get_type_description(type(self.output))}"
84
-
85
- # Calculate total tool calls across all steps
86
- total_tool_calls = 0
87
- for step in self.steps:
88
- if step.has_tool_calls():
89
- total_tool_calls += len(step.tool_calls)
90
-
91
- output += f"\n>>> Total Tool Calls: {total_tool_calls}"
92
-
93
- # Show context if available
94
- if self.context:
95
- output += (
96
- f"\n>>> Final Context: {self._format_context_display(self.context)}"
97
- )
98
-
99
- return output
100
-
101
- def _format_context_display(self, context: AgentContext) -> str:
102
- """Format context for display in string representation."""
103
- if context is None:
104
- return "None"
105
-
106
- try:
107
- # For Pydantic models, show as dict
108
- if hasattr(context, "model_dump"):
109
- context_dict = context.model_dump()
110
- elif isinstance(context, dict):
111
- context_dict = context
112
- else:
113
- return str(context)
114
-
115
- # Format as compact JSON-like string
116
- items = []
117
- for key, value in context_dict.items():
118
- if isinstance(value, str):
119
- items.append(f"{key}='{value}'")
120
- else:
121
- items.append(f"{key}={value}")
122
-
123
- return "{" + ", ".join(items) + "}"
124
- except Exception:
125
- return str(context)