ambivo-agents 1.0.1__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.
@@ -0,0 +1,301 @@
1
+ # ambivo_agents/config/loader.py
2
+ """
3
+ Configuration loader for ambivo_agents.
4
+ All configurations must be sourced from agent_config.yaml - no defaults.
5
+ """
6
+
7
+ import os
8
+ import yaml
9
+ from pathlib import Path
10
+ from typing import Dict, Any
11
+
12
+
13
+ class ConfigurationError(Exception):
14
+ """Raised when configuration is missing or invalid."""
15
+ pass
16
+
17
+
18
+ def load_config(config_path: str = None) -> Dict[str, Any]:
19
+ """
20
+ Load configuration from agent_config.yaml.
21
+
22
+ Args:
23
+ config_path: Optional path to config file. If None, searches for agent_config.yaml
24
+ in current directory and parent directories.
25
+
26
+ Returns:
27
+ Configuration dictionary
28
+
29
+ Raises:
30
+ ConfigurationError: If config file is not found or invalid
31
+ """
32
+ if config_path:
33
+ config_file = Path(config_path)
34
+ else:
35
+ # Search for agent_config.yaml starting from current directory
36
+ config_file = _find_config_file()
37
+
38
+ if not config_file or not config_file.exists():
39
+ raise ConfigurationError(
40
+ "agent_config.yaml not found. This file is required for ambivo_agents to function. "
41
+ "Please create agent_config.yaml in your project root or specify the path explicitly."
42
+ )
43
+
44
+ try:
45
+ with open(config_file, 'r', encoding='utf-8') as f:
46
+ config = yaml.safe_load(f)
47
+
48
+ if not config:
49
+ raise ConfigurationError("agent_config.yaml is empty or contains invalid YAML")
50
+
51
+ # Validate required sections
52
+ _validate_config(config)
53
+
54
+ return config
55
+
56
+ except yaml.YAMLError as e:
57
+ raise ConfigurationError(f"Invalid YAML in agent_config.yaml: {e}")
58
+ except Exception as e:
59
+ raise ConfigurationError(f"Failed to load agent_config.yaml: {e}")
60
+
61
+
62
+ def _find_config_file() -> Path:
63
+ """Find agent_config.yaml in current directory or parent directories."""
64
+ current_dir = Path.cwd()
65
+
66
+ # Check current directory first
67
+ config_file = current_dir / "agent_config.yaml"
68
+ if config_file.exists():
69
+ return config_file
70
+
71
+ # Check parent directories
72
+ for parent in current_dir.parents:
73
+ config_file = parent / "agent_config.yaml"
74
+ if config_file.exists():
75
+ return config_file
76
+
77
+ return None
78
+
79
+
80
+ def _validate_config(config: Dict[str, Any]) -> None:
81
+ """
82
+ Validate that required configuration sections exist.
83
+
84
+ Args:
85
+ config: Configuration dictionary
86
+
87
+ Raises:
88
+ ConfigurationError: If required sections are missing
89
+ """
90
+ required_sections = ['redis', 'llm']
91
+ missing_sections = []
92
+
93
+ for section in required_sections:
94
+ if section not in config:
95
+ missing_sections.append(section)
96
+
97
+ if missing_sections:
98
+ raise ConfigurationError(
99
+ f"Required configuration sections missing: {missing_sections}. "
100
+ "Please check your agent_config.yaml file."
101
+ )
102
+
103
+ # Validate Redis config
104
+ redis_config = config['redis']
105
+ required_redis_fields = ['host', 'port']
106
+ missing_redis_fields = [field for field in required_redis_fields if field not in redis_config]
107
+
108
+ if missing_redis_fields:
109
+ raise ConfigurationError(
110
+ f"Required Redis configuration fields missing: {missing_redis_fields}"
111
+ )
112
+
113
+ # Validate LLM config
114
+ llm_config = config['llm']
115
+ has_api_key = any(key in llm_config for key in [
116
+ 'openai_api_key', 'anthropic_api_key', 'aws_access_key_id'
117
+ ])
118
+
119
+ if not has_api_key:
120
+ raise ConfigurationError(
121
+ "At least one LLM provider API key is required in llm configuration. "
122
+ "Supported providers: openai_api_key, anthropic_api_key, aws_access_key_id"
123
+ )
124
+
125
+
126
+ def get_config_section(section: str, config: Dict[str, Any] = None) -> Dict[str, Any]:
127
+ """
128
+ Get a specific configuration section.
129
+
130
+ Args:
131
+ section: Section name (e.g., 'redis', 'llm', 'web_scraping')
132
+ config: Optional config dict. If None, loads from file.
133
+
134
+ Returns:
135
+ Configuration section dictionary
136
+
137
+ Raises:
138
+ ConfigurationError: If section is not found
139
+ """
140
+ if config is None:
141
+ config = load_config()
142
+
143
+ if section not in config:
144
+ raise ConfigurationError(f"Configuration section '{section}' not found in agent_config.yaml")
145
+
146
+ return config[section]
147
+
148
+
149
+ # Centralized capability and agent type mapping - UPDATED WITH YOUTUBE
150
+ CAPABILITY_TO_AGENT_TYPE = {
151
+ 'assistant': 'assistant',
152
+ 'code_execution': 'code_executor',
153
+ 'proxy': 'proxy',
154
+ 'web_scraping': 'web_scraper',
155
+ 'knowledge_base': 'knowledge_base',
156
+ 'web_search': 'web_search',
157
+ 'media_editor': 'media_editor',
158
+ 'youtube_download': 'youtube_download' # NEW
159
+ }
160
+
161
+ CONFIG_FLAG_TO_CAPABILITY = {
162
+ 'enable_web_scraping': 'web_scraping',
163
+ 'enable_knowledge_base': 'knowledge_base',
164
+ 'enable_web_search': 'web_search',
165
+ 'enable_media_editor': 'media_editor',
166
+ 'enable_youtube_download': 'youtube_download', # NEW
167
+ 'enable_code_execution': 'code_execution',
168
+ 'enable_proxy_mode': 'proxy'
169
+ }
170
+
171
+
172
+ def validate_agent_capabilities(config: Dict[str, Any] = None) -> Dict[str, bool]:
173
+ """
174
+ Validate and return available agent capabilities based on configuration.
175
+
176
+ This is the SINGLE SOURCE OF TRUTH for capability checking.
177
+
178
+ Args:
179
+ config: Optional config dict. If None, loads from file.
180
+
181
+ Returns:
182
+ Dictionary of capability_name -> enabled status
183
+ """
184
+ if config is None:
185
+ config = load_config()
186
+
187
+ # Always available capabilities
188
+ capabilities = {
189
+ 'assistant': True, # Always available
190
+ 'code_execution': True, # Always available with Docker
191
+ 'proxy': True, # Always available
192
+ }
193
+
194
+ # Get agent_capabilities section
195
+ agent_caps = config.get('agent_capabilities', {})
196
+
197
+ # Check optional capabilities based on both flag AND config section existence
198
+ capabilities['web_scraping'] = (
199
+ agent_caps.get('enable_web_scraping', False) and
200
+ 'web_scraping' in config
201
+ )
202
+
203
+ capabilities['knowledge_base'] = (
204
+ agent_caps.get('enable_knowledge_base', False) and
205
+ 'knowledge_base' in config
206
+ )
207
+
208
+ capabilities['web_search'] = (
209
+ agent_caps.get('enable_web_search', False) and
210
+ 'web_search' in config
211
+ )
212
+
213
+ capabilities['media_editor'] = (
214
+ agent_caps.get('enable_media_editor', False) and
215
+ 'media_editor' in config
216
+ )
217
+
218
+ # YouTube download capability
219
+ capabilities['youtube_download'] = (
220
+ agent_caps.get('enable_youtube_download', False) and
221
+ 'youtube_download' in config
222
+ )
223
+
224
+ return capabilities
225
+
226
+
227
+ def get_available_agent_types(config: Dict[str, Any] = None) -> Dict[str, bool]:
228
+ """
229
+ Get available agent types based on capabilities.
230
+
231
+ This maps capabilities to agent type names consistently.
232
+
233
+ Args:
234
+ config: Optional config dict. If None, loads from file.
235
+
236
+ Returns:
237
+ Dictionary of agent_type_name -> available status
238
+ """
239
+ try:
240
+ capabilities = validate_agent_capabilities(config)
241
+
242
+ # Map capabilities to agent types using centralized mapping
243
+ agent_types = {}
244
+ for capability, agent_type in CAPABILITY_TO_AGENT_TYPE.items():
245
+ agent_types[agent_type] = capabilities.get(capability, False)
246
+
247
+ return agent_types
248
+
249
+ except Exception as e:
250
+ import logging
251
+ logging.error(f"Error getting available agent types: {e}")
252
+ # Safe fallback
253
+ return {
254
+ 'assistant': True,
255
+ 'code_executor': True,
256
+ 'proxy': True,
257
+ 'knowledge_base': False,
258
+ 'web_scraper': False,
259
+ 'web_search': False,
260
+ 'media_editor': False,
261
+ 'youtube_download': False
262
+ }
263
+
264
+
265
+ def get_enabled_capabilities(config: Dict[str, Any] = None) -> list[str]:
266
+ """
267
+ Get list of enabled capability names.
268
+
269
+ Args:
270
+ config: Optional config dict. If None, loads from file.
271
+
272
+ Returns:
273
+ List of enabled capability names
274
+ """
275
+ capabilities = validate_agent_capabilities(config)
276
+ return [cap for cap, enabled in capabilities.items() if enabled]
277
+
278
+
279
+ def get_available_agent_type_names(config: Dict[str, Any] = None) -> list[str]:
280
+ """
281
+ Get list of available agent type names.
282
+
283
+ Args:
284
+ config: Optional config dict. If None, loads from file.
285
+
286
+ Returns:
287
+ List of available agent type names
288
+ """
289
+ agent_types = get_available_agent_types(config)
290
+ return [agent_type for agent_type, available in agent_types.items() if available]
291
+
292
+
293
+ def capability_to_agent_type(capability: str) -> str:
294
+ """Convert capability name to agent type name."""
295
+ return CAPABILITY_TO_AGENT_TYPE.get(capability, capability)
296
+
297
+
298
+ def agent_type_to_capability(agent_type: str) -> str:
299
+ """Convert agent type name to capability name."""
300
+ reverse_mapping = {v: k for k, v in CAPABILITY_TO_AGENT_TYPE.items()}
301
+ return reverse_mapping.get(agent_type, agent_type)
@@ -0,0 +1,33 @@
1
+ # ambivo_agents/core/__init__.py
2
+ from .base import (
3
+ AgentRole,
4
+ MessageType,
5
+ AgentMessage,
6
+ AgentTool,
7
+ ExecutionContext,
8
+ BaseAgent,
9
+ ProviderConfig,
10
+ ProviderTracker,
11
+ AgentSession
12
+ )
13
+ from .memory import MemoryManagerInterface, RedisMemoryManager, create_redis_memory_manager
14
+ from .llm import LLMServiceInterface, MultiProviderLLMService, create_multi_provider_llm_service
15
+
16
+ __all__ = [
17
+ "AgentRole",
18
+ "MessageType",
19
+ "AgentMessage",
20
+ "AgentTool",
21
+ "ExecutionContext",
22
+ "BaseAgent",
23
+ "ProviderConfig",
24
+ "ProviderTracker",
25
+ "MemoryManagerInterface",
26
+ "RedisMemoryManager",
27
+ "create_redis_memory_manager",
28
+ "LLMServiceInterface",
29
+ "MultiProviderLLMService",
30
+ "create_multi_provider_llm_service",
31
+ "AgentSession"
32
+ ]
33
+