agent-runtime-core 0.7.0__py3-none-any.whl → 0.8.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.
Files changed (38) hide show
  1. agent_runtime_core/__init__.py +109 -2
  2. agent_runtime_core/agentic_loop.py +254 -0
  3. agent_runtime_core/config.py +54 -4
  4. agent_runtime_core/config_schema.py +307 -0
  5. agent_runtime_core/files/__init__.py +88 -0
  6. agent_runtime_core/files/base.py +343 -0
  7. agent_runtime_core/files/ocr.py +406 -0
  8. agent_runtime_core/files/processors.py +508 -0
  9. agent_runtime_core/files/tools.py +317 -0
  10. agent_runtime_core/files/vision.py +360 -0
  11. agent_runtime_core/interfaces.py +106 -0
  12. agent_runtime_core/json_runtime.py +509 -0
  13. agent_runtime_core/llm/__init__.py +80 -7
  14. agent_runtime_core/llm/anthropic.py +133 -12
  15. agent_runtime_core/llm/models_config.py +180 -0
  16. agent_runtime_core/memory/__init__.py +70 -0
  17. agent_runtime_core/memory/manager.py +554 -0
  18. agent_runtime_core/memory/mixin.py +294 -0
  19. agent_runtime_core/multi_agent.py +569 -0
  20. agent_runtime_core/persistence/__init__.py +2 -0
  21. agent_runtime_core/persistence/file.py +277 -0
  22. agent_runtime_core/rag/__init__.py +65 -0
  23. agent_runtime_core/rag/chunking.py +224 -0
  24. agent_runtime_core/rag/indexer.py +253 -0
  25. agent_runtime_core/rag/retriever.py +261 -0
  26. agent_runtime_core/runner.py +193 -15
  27. agent_runtime_core/tool_calling_agent.py +88 -130
  28. agent_runtime_core/tools.py +179 -0
  29. agent_runtime_core/vectorstore/__init__.py +193 -0
  30. agent_runtime_core/vectorstore/base.py +138 -0
  31. agent_runtime_core/vectorstore/embeddings.py +242 -0
  32. agent_runtime_core/vectorstore/sqlite_vec.py +328 -0
  33. agent_runtime_core/vectorstore/vertex.py +295 -0
  34. {agent_runtime_core-0.7.0.dist-info → agent_runtime_core-0.8.0.dist-info}/METADATA +236 -1
  35. agent_runtime_core-0.8.0.dist-info/RECORD +63 -0
  36. agent_runtime_core-0.7.0.dist-info/RECORD +0 -39
  37. {agent_runtime_core-0.7.0.dist-info → agent_runtime_core-0.8.0.dist-info}/WHEEL +0 -0
  38. {agent_runtime_core-0.7.0.dist-info → agent_runtime_core-0.8.0.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,294 @@
1
+ """
2
+ Memory mixin for adding cross-conversation memory to agents.
3
+
4
+ This mixin can be combined with ToolCallingAgent or any AgentRuntime
5
+ to add automatic memory extraction and recall.
6
+ """
7
+
8
+ import logging
9
+ from typing import Any, Optional
10
+
11
+ from agent_runtime_core.interfaces import LLMClient, RunContext, RunResult
12
+ from agent_runtime_core.persistence.base import KnowledgeStore, FactType
13
+ from agent_runtime_core.memory.manager import (
14
+ MemoryManager,
15
+ MemoryConfig,
16
+ RecalledMemory,
17
+ )
18
+
19
+ logger = logging.getLogger(__name__)
20
+
21
+
22
+ class MemoryEnabledAgent:
23
+ """
24
+ Mixin that adds cross-conversation memory to agents.
25
+
26
+ Add this mixin to your agent class to enable automatic memory
27
+ extraction and recall. The mixin hooks into the agent lifecycle
28
+ to:
29
+
30
+ 1. Recall relevant memories before each run
31
+ 2. Inject memories into the system prompt
32
+ 3. Extract new memories after each run
33
+
34
+ Example:
35
+ from agent_runtime_core import ToolCallingAgent, ToolRegistry
36
+ from agent_runtime_core.memory import MemoryEnabledAgent
37
+
38
+ class MyAgent(MemoryEnabledAgent, ToolCallingAgent):
39
+ memory_enabled = True
40
+
41
+ @property
42
+ def key(self) -> str:
43
+ return "my-agent"
44
+
45
+ @property
46
+ def system_prompt(self) -> str:
47
+ return "You are a helpful assistant."
48
+
49
+ @property
50
+ def tools(self) -> ToolRegistry:
51
+ return ToolRegistry()
52
+
53
+ Configuration:
54
+ - memory_enabled: Set to True to enable memory (default: False)
55
+ - memory_config: Optional MemoryConfig instance
56
+ - memory_prompt_style: How to format memories ("list", "prose", "structured")
57
+ """
58
+
59
+ # Class-level configuration (can be overridden in subclasses)
60
+ memory_enabled: bool = False
61
+ memory_config: Optional[MemoryConfig] = None
62
+ memory_prompt_style: str = "list"
63
+
64
+ # Instance state (set during initialization)
65
+ _memory_manager: Optional[MemoryManager] = None
66
+ _recalled_memories: list[RecalledMemory] = []
67
+
68
+ def configure_memory(
69
+ self,
70
+ knowledge_store: KnowledgeStore,
71
+ llm_client: Optional[LLMClient] = None,
72
+ config: Optional[MemoryConfig] = None,
73
+ ) -> None:
74
+ """
75
+ Configure the memory system for this agent.
76
+
77
+ Call this before running the agent if memory_enabled is True.
78
+
79
+ Args:
80
+ knowledge_store: Store for persisting memories
81
+ llm_client: LLM client for extraction (uses agent's client if not provided)
82
+ config: Memory configuration
83
+ """
84
+ if llm_client is None:
85
+ # Try to get from agent's get_llm_client method
86
+ if hasattr(self, 'get_llm_client'):
87
+ llm_client = self.get_llm_client()
88
+ else:
89
+ raise ValueError("llm_client required when agent doesn't have get_llm_client")
90
+
91
+ self._memory_manager = MemoryManager(
92
+ knowledge_store=knowledge_store,
93
+ llm_client=llm_client,
94
+ config=config or self.memory_config or MemoryConfig(),
95
+ )
96
+
97
+ def get_memory_manager(self) -> Optional[MemoryManager]:
98
+ """Get the memory manager instance."""
99
+ return self._memory_manager
100
+
101
+ async def recall_memories_for_context(
102
+ self,
103
+ ctx: RunContext,
104
+ ) -> list[RecalledMemory]:
105
+ """
106
+ Recall relevant memories for the current context.
107
+
108
+ Override this method to customize memory recall logic.
109
+
110
+ Args:
111
+ ctx: The run context
112
+
113
+ Returns:
114
+ List of relevant memories
115
+ """
116
+ if not self._memory_manager:
117
+ return []
118
+
119
+ # Get user_id from context metadata if available
120
+ user_id = ctx.metadata.get("user_id") or ctx.metadata.get("user")
121
+
122
+ # Recall memories based on input messages
123
+ return await self._memory_manager.recall_memories(
124
+ messages=ctx.input_messages,
125
+ user_id=str(user_id) if user_id else None,
126
+ )
127
+
128
+ def format_memories_for_prompt(
129
+ self,
130
+ memories: list[RecalledMemory],
131
+ ) -> str:
132
+ """
133
+ Format memories for inclusion in the system prompt.
134
+
135
+ Override this method to customize memory formatting.
136
+
137
+ Args:
138
+ memories: List of recalled memories
139
+
140
+ Returns:
141
+ Formatted string to append to system prompt
142
+ """
143
+ if not self._memory_manager or not memories:
144
+ return ""
145
+
146
+ return self._memory_manager.format_memories_for_prompt(
147
+ memories,
148
+ format_style=self.memory_prompt_style,
149
+ )
150
+
151
+ async def extract_memories_from_run(
152
+ self,
153
+ ctx: RunContext,
154
+ result: RunResult,
155
+ ) -> None:
156
+ """
157
+ Extract memories from a completed run.
158
+
159
+ Override this method to customize memory extraction logic.
160
+
161
+ Args:
162
+ ctx: The run context
163
+ result: The run result
164
+ """
165
+ if not self._memory_manager:
166
+ return
167
+
168
+ # Get user_id from context metadata
169
+ user_id = ctx.metadata.get("user_id") or ctx.metadata.get("user")
170
+
171
+ # Combine input messages with result messages for extraction
172
+ all_messages = list(ctx.input_messages)
173
+ if result.final_messages:
174
+ all_messages.extend(result.final_messages)
175
+
176
+ # Extract memories
177
+ await self._memory_manager.extract_memories(
178
+ messages=all_messages,
179
+ user_id=str(user_id) if user_id else None,
180
+ )
181
+
182
+ # ==========================================================================
183
+ # Hooks for ToolCallingAgent integration
184
+ # ==========================================================================
185
+
186
+ async def before_run(self, ctx: RunContext) -> None:
187
+ """
188
+ Hook called before the agent run starts.
189
+
190
+ Recalls relevant memories and stores them for prompt injection.
191
+ """
192
+ # Call parent's before_run if it exists
193
+ if hasattr(super(), 'before_run'):
194
+ await super().before_run(ctx)
195
+
196
+ if self.memory_enabled and self._memory_manager:
197
+ self._recalled_memories = await self.recall_memories_for_context(ctx)
198
+ if self._recalled_memories:
199
+ logger.info(f"Recalled {len(self._recalled_memories)} memories for run")
200
+
201
+ async def after_run(self, ctx: RunContext, result: RunResult) -> RunResult:
202
+ """
203
+ Hook called after the agent run completes.
204
+
205
+ Extracts memories from the conversation.
206
+ """
207
+ # Call parent's after_run if it exists
208
+ if hasattr(super(), 'after_run'):
209
+ result = await super().after_run(ctx, result)
210
+
211
+ if self.memory_enabled and self._memory_manager:
212
+ await self.extract_memories_from_run(ctx, result)
213
+
214
+ return result
215
+
216
+ @property
217
+ def system_prompt_with_memory(self) -> str:
218
+ """
219
+ Get the system prompt with memories injected.
220
+
221
+ This is used internally by the mixin. Override system_prompt
222
+ in your agent class, not this property.
223
+ """
224
+ base_prompt = self.system_prompt if hasattr(self, 'system_prompt') else ""
225
+
226
+ if not self.memory_enabled or not self._recalled_memories:
227
+ return base_prompt
228
+
229
+ memory_text = self.format_memories_for_prompt(self._recalled_memories)
230
+ if memory_text:
231
+ return f"{base_prompt}\n\n{memory_text}"
232
+
233
+ return base_prompt
234
+
235
+
236
+ # =============================================================================
237
+ # Convenience function for creating memory-enabled agents
238
+ # =============================================================================
239
+
240
+
241
+ def with_memory(
242
+ agent_class: type,
243
+ knowledge_store: KnowledgeStore,
244
+ llm_client: Optional[LLMClient] = None,
245
+ config: Optional[MemoryConfig] = None,
246
+ ) -> type:
247
+ """
248
+ Create a memory-enabled version of an agent class.
249
+
250
+ This is a convenience function for adding memory to existing agents
251
+ without modifying their class definition.
252
+
253
+ Example:
254
+ from agent_runtime_core import ToolCallingAgent
255
+ from agent_runtime_core.memory import with_memory
256
+
257
+ # Original agent
258
+ class MyAgent(ToolCallingAgent):
259
+ ...
260
+
261
+ # Memory-enabled version
262
+ MemoryMyAgent = with_memory(
263
+ MyAgent,
264
+ knowledge_store=FileKnowledgeStore(),
265
+ )
266
+
267
+ agent = MemoryMyAgent()
268
+
269
+ Args:
270
+ agent_class: The agent class to enhance
271
+ knowledge_store: Store for persisting memories
272
+ llm_client: Optional LLM client for extraction
273
+ config: Optional memory configuration
274
+
275
+ Returns:
276
+ A new class with memory capabilities
277
+ """
278
+ class MemoryEnabledVersion(MemoryEnabledAgent, agent_class):
279
+ memory_enabled = True
280
+ memory_config = config
281
+
282
+ def __init__(self, *args, **kwargs):
283
+ super().__init__(*args, **kwargs)
284
+ self.configure_memory(
285
+ knowledge_store=knowledge_store,
286
+ llm_client=llm_client,
287
+ config=config,
288
+ )
289
+
290
+ MemoryEnabledVersion.__name__ = f"MemoryEnabled{agent_class.__name__}"
291
+ MemoryEnabledVersion.__qualname__ = f"MemoryEnabled{agent_class.__qualname__}"
292
+
293
+ return MemoryEnabledVersion
294
+