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,307 @@
1
+ """
2
+ AgentConfig - Canonical JSON schema for portable agent definitions.
3
+
4
+ This schema defines the format for agent configurations that can be:
5
+ 1. Stored in Django as JSON revisions
6
+ 2. Loaded from standalone .json files
7
+ 3. Used by agent_runtime_core without Django dependency
8
+
9
+ Example:
10
+ # Load from file
11
+ config = AgentConfig.from_file("my_agent.json")
12
+
13
+ # Create runtime and run
14
+ runtime = JsonAgentRuntime(config, llm_client)
15
+ result = await runtime.run(ctx)
16
+ """
17
+
18
+ from dataclasses import dataclass, field
19
+ from datetime import datetime
20
+ from typing import Any, Optional
21
+ import json
22
+ from pathlib import Path
23
+
24
+
25
+ @dataclass
26
+ class SubAgentToolConfig:
27
+ """
28
+ Configuration for a sub-agent tool (agent-as-tool pattern).
29
+
30
+ This allows an agent to delegate to another agent as if it were a tool.
31
+ The sub-agent can either be referenced by slug (resolved at runtime)
32
+ or embedded inline (for portable standalone configs).
33
+ """
34
+
35
+ name: str # Tool name the parent uses to invoke this agent
36
+ description: str # When to use this agent (shown to parent LLM)
37
+
38
+ # Reference to sub-agent (one of these should be set)
39
+ agent_slug: str = "" # Reference by slug (resolved at runtime from registry)
40
+ agent_config: Optional["AgentConfig"] = None # Embedded config (for standalone)
41
+
42
+ # Invocation settings
43
+ invocation_mode: str = "delegate" # "delegate" or "handoff"
44
+ context_mode: str = "full" # "full", "summary", or "message_only"
45
+ max_turns: Optional[int] = None
46
+
47
+ def to_dict(self) -> dict:
48
+ result = {
49
+ "name": self.name,
50
+ "description": self.description,
51
+ "tool_type": "subagent",
52
+ "invocation_mode": self.invocation_mode,
53
+ "context_mode": self.context_mode,
54
+ }
55
+ if self.agent_slug:
56
+ result["agent_slug"] = self.agent_slug
57
+ if self.agent_config:
58
+ result["agent_config"] = self.agent_config.to_dict()
59
+ if self.max_turns is not None:
60
+ result["max_turns"] = self.max_turns
61
+ return result
62
+
63
+ @classmethod
64
+ def from_dict(cls, data: dict) -> "SubAgentToolConfig":
65
+ agent_config = None
66
+ if "agent_config" in data and data["agent_config"]:
67
+ # Defer import to avoid circular dependency
68
+ agent_config = AgentConfig.from_dict(data["agent_config"])
69
+
70
+ return cls(
71
+ name=data["name"],
72
+ description=data["description"],
73
+ agent_slug=data.get("agent_slug", ""),
74
+ agent_config=agent_config,
75
+ invocation_mode=data.get("invocation_mode", "delegate"),
76
+ context_mode=data.get("context_mode", "full"),
77
+ max_turns=data.get("max_turns"),
78
+ )
79
+
80
+
81
+ @dataclass
82
+ class ToolConfig:
83
+ """Configuration for a single tool."""
84
+
85
+ name: str
86
+ description: str
87
+ parameters: dict # JSON Schema for parameters
88
+ function_path: str # Import path like "myapp.services.orders.lookup_order"
89
+
90
+ # Optional metadata
91
+ requires_confirmation: bool = False
92
+ is_safe: bool = True # No side effects
93
+ timeout_seconds: int = 30
94
+
95
+ def to_dict(self) -> dict:
96
+ return {
97
+ "name": self.name,
98
+ "description": self.description,
99
+ "parameters": self.parameters,
100
+ "function_path": self.function_path,
101
+ "requires_confirmation": self.requires_confirmation,
102
+ "is_safe": self.is_safe,
103
+ "timeout_seconds": self.timeout_seconds,
104
+ }
105
+
106
+ @classmethod
107
+ def from_dict(cls, data: dict) -> "ToolConfig":
108
+ return cls(
109
+ name=data["name"],
110
+ description=data["description"],
111
+ parameters=data.get("parameters", {}),
112
+ function_path=data.get("function_path", ""),
113
+ requires_confirmation=data.get("requires_confirmation", False),
114
+ is_safe=data.get("is_safe", True),
115
+ timeout_seconds=data.get("timeout_seconds", 30),
116
+ )
117
+
118
+
119
+ @dataclass
120
+ class KnowledgeConfig:
121
+ """Configuration for a knowledge source."""
122
+
123
+ name: str
124
+ knowledge_type: str # "text", "file", "url"
125
+ inclusion_mode: str = "always" # "always", "on_demand", "rag"
126
+
127
+ # Content (depends on type)
128
+ content: str = "" # For text type
129
+ file_path: str = "" # For file type
130
+ url: str = "" # For url type
131
+
132
+ def to_dict(self) -> dict:
133
+ return {
134
+ "name": self.name,
135
+ "type": self.knowledge_type,
136
+ "inclusion_mode": self.inclusion_mode,
137
+ "content": self.content,
138
+ "file_path": self.file_path,
139
+ "url": self.url,
140
+ }
141
+
142
+ @classmethod
143
+ def from_dict(cls, data: dict) -> "KnowledgeConfig":
144
+ return cls(
145
+ name=data["name"],
146
+ knowledge_type=data.get("type", "text"),
147
+ inclusion_mode=data.get("inclusion_mode", "always"),
148
+ content=data.get("content", ""),
149
+ file_path=data.get("file_path", ""),
150
+ url=data.get("url", ""),
151
+ )
152
+
153
+
154
+ @dataclass
155
+ class AgentConfig:
156
+ """
157
+ Canonical configuration for an agent.
158
+
159
+ This is the portable format that can be serialized to JSON and
160
+ loaded by any runtime (Django or standalone).
161
+
162
+ For multi-agent systems, sub_agents contains embedded agent configs
163
+ that this agent can delegate to. The sub_agent_tools list defines
164
+ how each sub-agent is exposed as a tool.
165
+ """
166
+
167
+ # Identity
168
+ name: str
169
+ slug: str
170
+ description: str = ""
171
+
172
+ # Core configuration
173
+ system_prompt: str = ""
174
+ model: str = "gpt-4o"
175
+ model_settings: dict = field(default_factory=dict)
176
+
177
+ # Tools and knowledge
178
+ tools: list[ToolConfig] = field(default_factory=list)
179
+ knowledge: list[KnowledgeConfig] = field(default_factory=list)
180
+
181
+ # Sub-agent tools (agent-as-tool pattern)
182
+ # These define other agents this agent can delegate to
183
+ sub_agent_tools: list[SubAgentToolConfig] = field(default_factory=list)
184
+
185
+ # Metadata
186
+ version: str = "1.0"
187
+ schema_version: str = "1" # For future schema migrations
188
+ created_at: Optional[str] = None
189
+ updated_at: Optional[str] = None
190
+
191
+ # Extra config (for extensibility)
192
+ extra: dict = field(default_factory=dict)
193
+
194
+ def to_dict(self) -> dict:
195
+ """Serialize to dictionary (JSON-compatible)."""
196
+ result = {
197
+ "schema_version": self.schema_version,
198
+ "version": self.version,
199
+ "name": self.name,
200
+ "slug": self.slug,
201
+ "description": self.description,
202
+ "system_prompt": self.system_prompt,
203
+ "model": self.model,
204
+ "model_settings": self.model_settings,
205
+ "tools": [t.to_dict() for t in self.tools],
206
+ "knowledge": [k.to_dict() for k in self.knowledge],
207
+ "created_at": self.created_at,
208
+ "updated_at": self.updated_at,
209
+ "extra": self.extra,
210
+ }
211
+ # Only include sub_agent_tools if there are any
212
+ if self.sub_agent_tools:
213
+ result["sub_agent_tools"] = [s.to_dict() for s in self.sub_agent_tools]
214
+ return result
215
+
216
+ def to_json(self, indent: int = 2) -> str:
217
+ """Serialize to JSON string."""
218
+ return json.dumps(self.to_dict(), indent=indent)
219
+
220
+ def save(self, path: str | Path) -> None:
221
+ """Save to a JSON file."""
222
+ path = Path(path)
223
+ path.write_text(self.to_json())
224
+
225
+ @classmethod
226
+ def from_dict(cls, data: dict) -> "AgentConfig":
227
+ """Load from dictionary."""
228
+ # Parse regular tools (skip subagent tools - they're in sub_agent_tools)
229
+ tools = []
230
+ for t in data.get("tools", []):
231
+ if t.get("tool_type") != "subagent":
232
+ tools.append(ToolConfig.from_dict(t))
233
+
234
+ knowledge = [KnowledgeConfig.from_dict(k) for k in data.get("knowledge", [])]
235
+
236
+ # Parse sub-agent tools
237
+ sub_agent_tools = []
238
+ for s in data.get("sub_agent_tools", []):
239
+ sub_agent_tools.append(SubAgentToolConfig.from_dict(s))
240
+ # Also check tools list for subagent type (backwards compat)
241
+ for t in data.get("tools", []):
242
+ if t.get("tool_type") == "subagent":
243
+ sub_agent_tools.append(SubAgentToolConfig.from_dict(t))
244
+
245
+ return cls(
246
+ name=data["name"],
247
+ slug=data["slug"],
248
+ description=data.get("description", ""),
249
+ system_prompt=data.get("system_prompt", ""),
250
+ model=data.get("model", "gpt-4o"),
251
+ model_settings=data.get("model_settings", {}),
252
+ tools=tools,
253
+ knowledge=knowledge,
254
+ sub_agent_tools=sub_agent_tools,
255
+ version=data.get("version", "1.0"),
256
+ schema_version=data.get("schema_version", "1"),
257
+ created_at=data.get("created_at"),
258
+ updated_at=data.get("updated_at"),
259
+ extra=data.get("extra", {}),
260
+ )
261
+
262
+ @classmethod
263
+ def from_json(cls, json_str: str) -> "AgentConfig":
264
+ """Load from JSON string."""
265
+ return cls.from_dict(json.loads(json_str))
266
+
267
+ @classmethod
268
+ def from_file(cls, path: str | Path) -> "AgentConfig":
269
+ """Load from a JSON file."""
270
+ path = Path(path)
271
+ return cls.from_json(path.read_text())
272
+
273
+ def with_timestamp(self) -> "AgentConfig":
274
+ """Return a copy with updated timestamp."""
275
+ now = datetime.utcnow().isoformat() + "Z"
276
+ return AgentConfig(
277
+ name=self.name,
278
+ slug=self.slug,
279
+ description=self.description,
280
+ system_prompt=self.system_prompt,
281
+ model=self.model,
282
+ model_settings=self.model_settings,
283
+ tools=self.tools,
284
+ knowledge=self.knowledge,
285
+ sub_agent_tools=self.sub_agent_tools,
286
+ version=self.version,
287
+ schema_version=self.schema_version,
288
+ created_at=self.created_at or now,
289
+ updated_at=now,
290
+ extra=self.extra,
291
+ )
292
+
293
+ def get_all_embedded_agents(self) -> dict[str, "AgentConfig"]:
294
+ """
295
+ Get all embedded agent configs (for standalone execution).
296
+
297
+ Returns a dict mapping slug -> AgentConfig for all sub-agents
298
+ that have embedded configs (not just slug references).
299
+ """
300
+ agents = {}
301
+ for sub_tool in self.sub_agent_tools:
302
+ if sub_tool.agent_config:
303
+ agents[sub_tool.agent_config.slug] = sub_tool.agent_config
304
+ # Recursively get nested sub-agents
305
+ agents.update(sub_tool.agent_config.get_all_embedded_agents())
306
+ return agents
307
+
@@ -0,0 +1,88 @@
1
+ """
2
+ File processing module for agent_runtime_core.
3
+
4
+ Provides pluggable file processors for reading various file types,
5
+ OCR integration, and AI vision capabilities.
6
+
7
+ Example:
8
+ from agent_runtime_core.files import FileProcessorRegistry, process_file
9
+
10
+ # Register processors
11
+ registry = FileProcessorRegistry()
12
+ registry.auto_register() # Register all available processors
13
+
14
+ # Process a file
15
+ result = await registry.process("document.pdf", file_bytes)
16
+ print(result.text) # Extracted text
17
+ print(result.metadata) # File metadata
18
+ """
19
+
20
+ from .base import (
21
+ FileProcessor,
22
+ FileProcessorRegistry,
23
+ ProcessedFile,
24
+ FileType,
25
+ ProcessingOptions,
26
+ )
27
+ from .processors import (
28
+ TextFileProcessor,
29
+ PDFProcessor,
30
+ ImageProcessor,
31
+ DocxProcessor,
32
+ XlsxProcessor,
33
+ CsvProcessor,
34
+ )
35
+ from .ocr import (
36
+ OCRProvider,
37
+ TesseractOCR,
38
+ GoogleVisionOCR,
39
+ AWSTextractOCR,
40
+ AzureDocumentOCR,
41
+ )
42
+ from .vision import (
43
+ VisionProvider,
44
+ OpenAIVision,
45
+ AnthropicVision,
46
+ GeminiVision,
47
+ )
48
+ from .tools import (
49
+ FileTools,
50
+ FileToolsConfig,
51
+ get_file_read_schema,
52
+ get_file_write_schema,
53
+ get_file_list_schema,
54
+ )
55
+
56
+ __all__ = [
57
+ # Base classes
58
+ "FileProcessor",
59
+ "FileProcessorRegistry",
60
+ "ProcessedFile",
61
+ "FileType",
62
+ "ProcessingOptions",
63
+ # Processors
64
+ "TextFileProcessor",
65
+ "PDFProcessor",
66
+ "ImageProcessor",
67
+ "DocxProcessor",
68
+ "XlsxProcessor",
69
+ "CsvProcessor",
70
+ # OCR
71
+ "OCRProvider",
72
+ "TesseractOCR",
73
+ "GoogleVisionOCR",
74
+ "AWSTextractOCR",
75
+ "AzureDocumentOCR",
76
+ # Vision
77
+ "VisionProvider",
78
+ "OpenAIVision",
79
+ "AnthropicVision",
80
+ "GeminiVision",
81
+ # Tools
82
+ "FileTools",
83
+ "FileToolsConfig",
84
+ "get_file_read_schema",
85
+ "get_file_write_schema",
86
+ "get_file_list_schema",
87
+ ]
88
+