genxai-framework 0.1.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.
- cli/__init__.py +3 -0
- cli/commands/__init__.py +6 -0
- cli/commands/approval.py +85 -0
- cli/commands/audit.py +127 -0
- cli/commands/metrics.py +25 -0
- cli/commands/tool.py +389 -0
- cli/main.py +32 -0
- genxai/__init__.py +81 -0
- genxai/api/__init__.py +5 -0
- genxai/api/app.py +21 -0
- genxai/config/__init__.py +5 -0
- genxai/config/settings.py +37 -0
- genxai/connectors/__init__.py +19 -0
- genxai/connectors/base.py +122 -0
- genxai/connectors/kafka.py +92 -0
- genxai/connectors/postgres_cdc.py +95 -0
- genxai/connectors/registry.py +44 -0
- genxai/connectors/sqs.py +94 -0
- genxai/connectors/webhook.py +73 -0
- genxai/core/__init__.py +37 -0
- genxai/core/agent/__init__.py +32 -0
- genxai/core/agent/base.py +206 -0
- genxai/core/agent/config_io.py +59 -0
- genxai/core/agent/registry.py +98 -0
- genxai/core/agent/runtime.py +970 -0
- genxai/core/communication/__init__.py +6 -0
- genxai/core/communication/collaboration.py +44 -0
- genxai/core/communication/message_bus.py +192 -0
- genxai/core/communication/protocols.py +35 -0
- genxai/core/execution/__init__.py +22 -0
- genxai/core/execution/metadata.py +181 -0
- genxai/core/execution/queue.py +201 -0
- genxai/core/graph/__init__.py +30 -0
- genxai/core/graph/checkpoints.py +77 -0
- genxai/core/graph/edges.py +131 -0
- genxai/core/graph/engine.py +813 -0
- genxai/core/graph/executor.py +516 -0
- genxai/core/graph/nodes.py +161 -0
- genxai/core/graph/trigger_runner.py +40 -0
- genxai/core/memory/__init__.py +19 -0
- genxai/core/memory/base.py +72 -0
- genxai/core/memory/embedding.py +327 -0
- genxai/core/memory/episodic.py +448 -0
- genxai/core/memory/long_term.py +467 -0
- genxai/core/memory/manager.py +543 -0
- genxai/core/memory/persistence.py +297 -0
- genxai/core/memory/procedural.py +461 -0
- genxai/core/memory/semantic.py +526 -0
- genxai/core/memory/shared.py +62 -0
- genxai/core/memory/short_term.py +303 -0
- genxai/core/memory/vector_store.py +508 -0
- genxai/core/memory/working.py +211 -0
- genxai/core/state/__init__.py +6 -0
- genxai/core/state/manager.py +293 -0
- genxai/core/state/schema.py +115 -0
- genxai/llm/__init__.py +14 -0
- genxai/llm/base.py +150 -0
- genxai/llm/factory.py +329 -0
- genxai/llm/providers/__init__.py +1 -0
- genxai/llm/providers/anthropic.py +249 -0
- genxai/llm/providers/cohere.py +274 -0
- genxai/llm/providers/google.py +334 -0
- genxai/llm/providers/ollama.py +147 -0
- genxai/llm/providers/openai.py +257 -0
- genxai/llm/routing.py +83 -0
- genxai/observability/__init__.py +6 -0
- genxai/observability/logging.py +327 -0
- genxai/observability/metrics.py +494 -0
- genxai/observability/tracing.py +372 -0
- genxai/performance/__init__.py +39 -0
- genxai/performance/cache.py +256 -0
- genxai/performance/pooling.py +289 -0
- genxai/security/audit.py +304 -0
- genxai/security/auth.py +315 -0
- genxai/security/cost_control.py +528 -0
- genxai/security/default_policies.py +44 -0
- genxai/security/jwt.py +142 -0
- genxai/security/oauth.py +226 -0
- genxai/security/pii.py +366 -0
- genxai/security/policy_engine.py +82 -0
- genxai/security/rate_limit.py +341 -0
- genxai/security/rbac.py +247 -0
- genxai/security/validation.py +218 -0
- genxai/tools/__init__.py +21 -0
- genxai/tools/base.py +383 -0
- genxai/tools/builtin/__init__.py +131 -0
- genxai/tools/builtin/communication/__init__.py +15 -0
- genxai/tools/builtin/communication/email_sender.py +159 -0
- genxai/tools/builtin/communication/notification_manager.py +167 -0
- genxai/tools/builtin/communication/slack_notifier.py +118 -0
- genxai/tools/builtin/communication/sms_sender.py +118 -0
- genxai/tools/builtin/communication/webhook_caller.py +136 -0
- genxai/tools/builtin/computation/__init__.py +15 -0
- genxai/tools/builtin/computation/calculator.py +101 -0
- genxai/tools/builtin/computation/code_executor.py +183 -0
- genxai/tools/builtin/computation/data_validator.py +259 -0
- genxai/tools/builtin/computation/hash_generator.py +129 -0
- genxai/tools/builtin/computation/regex_matcher.py +201 -0
- genxai/tools/builtin/data/__init__.py +15 -0
- genxai/tools/builtin/data/csv_processor.py +213 -0
- genxai/tools/builtin/data/data_transformer.py +299 -0
- genxai/tools/builtin/data/json_processor.py +233 -0
- genxai/tools/builtin/data/text_analyzer.py +288 -0
- genxai/tools/builtin/data/xml_processor.py +175 -0
- genxai/tools/builtin/database/__init__.py +15 -0
- genxai/tools/builtin/database/database_inspector.py +157 -0
- genxai/tools/builtin/database/mongodb_query.py +196 -0
- genxai/tools/builtin/database/redis_cache.py +167 -0
- genxai/tools/builtin/database/sql_query.py +145 -0
- genxai/tools/builtin/database/vector_search.py +163 -0
- genxai/tools/builtin/file/__init__.py +17 -0
- genxai/tools/builtin/file/directory_scanner.py +214 -0
- genxai/tools/builtin/file/file_compressor.py +237 -0
- genxai/tools/builtin/file/file_reader.py +102 -0
- genxai/tools/builtin/file/file_writer.py +122 -0
- genxai/tools/builtin/file/image_processor.py +186 -0
- genxai/tools/builtin/file/pdf_parser.py +144 -0
- genxai/tools/builtin/test/__init__.py +15 -0
- genxai/tools/builtin/test/async_simulator.py +62 -0
- genxai/tools/builtin/test/data_transformer.py +99 -0
- genxai/tools/builtin/test/error_generator.py +82 -0
- genxai/tools/builtin/test/simple_math.py +94 -0
- genxai/tools/builtin/test/string_processor.py +72 -0
- genxai/tools/builtin/web/__init__.py +15 -0
- genxai/tools/builtin/web/api_caller.py +161 -0
- genxai/tools/builtin/web/html_parser.py +330 -0
- genxai/tools/builtin/web/http_client.py +187 -0
- genxai/tools/builtin/web/url_validator.py +162 -0
- genxai/tools/builtin/web/web_scraper.py +170 -0
- genxai/tools/custom/my_test_tool_2.py +9 -0
- genxai/tools/dynamic.py +105 -0
- genxai/tools/mcp_server.py +167 -0
- genxai/tools/persistence/__init__.py +6 -0
- genxai/tools/persistence/models.py +55 -0
- genxai/tools/persistence/service.py +322 -0
- genxai/tools/registry.py +227 -0
- genxai/tools/security/__init__.py +11 -0
- genxai/tools/security/limits.py +214 -0
- genxai/tools/security/policy.py +20 -0
- genxai/tools/security/sandbox.py +248 -0
- genxai/tools/templates.py +435 -0
- genxai/triggers/__init__.py +19 -0
- genxai/triggers/base.py +104 -0
- genxai/triggers/file_watcher.py +75 -0
- genxai/triggers/queue.py +68 -0
- genxai/triggers/registry.py +82 -0
- genxai/triggers/schedule.py +66 -0
- genxai/triggers/webhook.py +68 -0
- genxai/utils/__init__.py +1 -0
- genxai/utils/tokens.py +295 -0
- genxai_framework-0.1.0.dist-info/METADATA +495 -0
- genxai_framework-0.1.0.dist-info/RECORD +156 -0
- genxai_framework-0.1.0.dist-info/WHEEL +5 -0
- genxai_framework-0.1.0.dist-info/entry_points.txt +2 -0
- genxai_framework-0.1.0.dist-info/licenses/LICENSE +21 -0
- genxai_framework-0.1.0.dist-info/top_level.txt +2 -0
genxai/core/__init__.py
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"""Core components of GenXAI framework."""
|
|
2
|
+
|
|
3
|
+
from genxai.core.agent import (
|
|
4
|
+
Agent,
|
|
5
|
+
AgentConfig,
|
|
6
|
+
AgentFactory,
|
|
7
|
+
AgentRegistry,
|
|
8
|
+
AgentRuntime,
|
|
9
|
+
AgentType,
|
|
10
|
+
)
|
|
11
|
+
from genxai.core.graph import (
|
|
12
|
+
Edge,
|
|
13
|
+
EnhancedGraph,
|
|
14
|
+
Graph,
|
|
15
|
+
Node,
|
|
16
|
+
NodeType,
|
|
17
|
+
WorkflowExecutor,
|
|
18
|
+
execute_workflow_sync,
|
|
19
|
+
)
|
|
20
|
+
from genxai.core.memory.manager import MemorySystem
|
|
21
|
+
|
|
22
|
+
__all__ = [
|
|
23
|
+
"Agent",
|
|
24
|
+
"AgentConfig",
|
|
25
|
+
"AgentFactory",
|
|
26
|
+
"AgentRegistry",
|
|
27
|
+
"AgentRuntime",
|
|
28
|
+
"AgentType",
|
|
29
|
+
"Graph",
|
|
30
|
+
"EnhancedGraph",
|
|
31
|
+
"WorkflowExecutor",
|
|
32
|
+
"execute_workflow_sync",
|
|
33
|
+
"Node",
|
|
34
|
+
"NodeType",
|
|
35
|
+
"Edge",
|
|
36
|
+
"MemorySystem",
|
|
37
|
+
]
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"""Agent system for GenXAI."""
|
|
2
|
+
|
|
3
|
+
from genxai.core.agent.base import Agent, AgentConfig, AgentType, AgentFactory
|
|
4
|
+
from genxai.core.agent.config_io import (
|
|
5
|
+
agent_config_from_dict,
|
|
6
|
+
agent_config_to_dict,
|
|
7
|
+
agent_from_dict,
|
|
8
|
+
agent_to_dict,
|
|
9
|
+
export_agent_config_yaml,
|
|
10
|
+
export_agents_yaml,
|
|
11
|
+
import_agent_config_yaml,
|
|
12
|
+
import_agents_yaml,
|
|
13
|
+
)
|
|
14
|
+
from genxai.core.agent.runtime import AgentRuntime
|
|
15
|
+
from genxai.core.agent.registry import AgentRegistry
|
|
16
|
+
|
|
17
|
+
__all__ = [
|
|
18
|
+
"Agent",
|
|
19
|
+
"AgentConfig",
|
|
20
|
+
"AgentFactory",
|
|
21
|
+
"AgentType",
|
|
22
|
+
"AgentRuntime",
|
|
23
|
+
"AgentRegistry",
|
|
24
|
+
"agent_config_from_dict",
|
|
25
|
+
"agent_config_to_dict",
|
|
26
|
+
"agent_from_dict",
|
|
27
|
+
"agent_to_dict",
|
|
28
|
+
"export_agent_config_yaml",
|
|
29
|
+
"export_agents_yaml",
|
|
30
|
+
"import_agent_config_yaml",
|
|
31
|
+
"import_agents_yaml",
|
|
32
|
+
]
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
"""Base agent class and configuration."""
|
|
2
|
+
|
|
3
|
+
from typing import Any, Dict, List, Optional
|
|
4
|
+
from pydantic import BaseModel, Field, ConfigDict
|
|
5
|
+
from enum import Enum
|
|
6
|
+
import logging
|
|
7
|
+
|
|
8
|
+
logger = logging.getLogger(__name__)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class AgentType(str, Enum):
|
|
12
|
+
"""Types of agents."""
|
|
13
|
+
|
|
14
|
+
REACTIVE = "reactive"
|
|
15
|
+
DELIBERATIVE = "deliberative"
|
|
16
|
+
LEARNING = "learning"
|
|
17
|
+
COLLABORATIVE = "collaborative"
|
|
18
|
+
AUTONOMOUS = "autonomous"
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class AgentConfig(BaseModel):
|
|
22
|
+
"""Configuration for an agent."""
|
|
23
|
+
|
|
24
|
+
model_config = ConfigDict(use_enum_values=True)
|
|
25
|
+
|
|
26
|
+
role: str = Field(..., description="Role of the agent")
|
|
27
|
+
goal: str = Field(..., description="Goal the agent should achieve")
|
|
28
|
+
backstory: str = Field(default="", description="Background story for the agent")
|
|
29
|
+
|
|
30
|
+
# LLM configuration
|
|
31
|
+
llm_provider: str = Field(default="openai", description="LLM provider to use")
|
|
32
|
+
llm_model: str = Field(default="gpt-4", description="LLM model name")
|
|
33
|
+
llm_temperature: float = Field(default=0.7, ge=0.0, le=2.0)
|
|
34
|
+
llm_max_tokens: Optional[int] = Field(default=None, description="Max tokens for response")
|
|
35
|
+
|
|
36
|
+
# Tools
|
|
37
|
+
tools: List[str] = Field(default_factory=list, description="List of tool names")
|
|
38
|
+
allow_tool_creation: bool = Field(default=False, description="Allow dynamic tool creation")
|
|
39
|
+
|
|
40
|
+
# Memory
|
|
41
|
+
enable_memory: bool = Field(default=True, description="Enable memory system")
|
|
42
|
+
memory_type: str = Field(default="short_term", description="Type of memory to use")
|
|
43
|
+
|
|
44
|
+
# Behavior
|
|
45
|
+
agent_type: AgentType = Field(default=AgentType.REACTIVE)
|
|
46
|
+
max_iterations: int = Field(default=10, description="Max iterations for agent execution")
|
|
47
|
+
verbose: bool = Field(default=False, description="Enable verbose logging")
|
|
48
|
+
|
|
49
|
+
# Guardrails
|
|
50
|
+
max_execution_time: Optional[float] = Field(default=None, description="Max execution time in seconds")
|
|
51
|
+
allowed_domains: List[str] = Field(default_factory=list, description="Allowed domains for web access")
|
|
52
|
+
|
|
53
|
+
# Metadata
|
|
54
|
+
metadata: Dict[str, Any] = Field(default_factory=dict)
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
class Agent(BaseModel):
|
|
59
|
+
"""Base agent class."""
|
|
60
|
+
|
|
61
|
+
model_config = ConfigDict(arbitrary_types_allowed=True, extra="allow")
|
|
62
|
+
|
|
63
|
+
id: str = Field(..., description="Unique agent identifier")
|
|
64
|
+
config: AgentConfig
|
|
65
|
+
|
|
66
|
+
# Runtime state
|
|
67
|
+
_execution_count: int = 0
|
|
68
|
+
_total_tokens: int = 0
|
|
69
|
+
_last_result: Optional[Any] = None
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def __init__(self, id: str, config: AgentConfig, **kwargs: Any) -> None:
|
|
73
|
+
"""Initialize agent.
|
|
74
|
+
|
|
75
|
+
Args:
|
|
76
|
+
id: Agent identifier
|
|
77
|
+
config: Agent configuration
|
|
78
|
+
**kwargs: Additional arguments
|
|
79
|
+
"""
|
|
80
|
+
super().__init__(id=id, config=config, **kwargs)
|
|
81
|
+
logger.info(f"Agent initialized: {self.id} (role: {self.config.role})")
|
|
82
|
+
|
|
83
|
+
async def execute(self, task: str, context: Optional[Dict[str, Any]] = None) -> Dict[str, Any]:
|
|
84
|
+
"""Execute a task.
|
|
85
|
+
|
|
86
|
+
This is a placeholder that will be implemented by AgentRuntime.
|
|
87
|
+
|
|
88
|
+
Args:
|
|
89
|
+
task: Task description
|
|
90
|
+
context: Execution context
|
|
91
|
+
|
|
92
|
+
Returns:
|
|
93
|
+
Execution result
|
|
94
|
+
"""
|
|
95
|
+
self._execution_count += 1
|
|
96
|
+
|
|
97
|
+
logger.info(f"Agent {self.id} executing task: {task}")
|
|
98
|
+
|
|
99
|
+
# Placeholder implementation
|
|
100
|
+
result = {
|
|
101
|
+
"agent_id": self.id,
|
|
102
|
+
"task": task,
|
|
103
|
+
"status": "completed",
|
|
104
|
+
"output": f"Agent {self.config.role} processed: {task}",
|
|
105
|
+
"execution_count": self._execution_count,
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
self._last_result = result
|
|
109
|
+
return result
|
|
110
|
+
|
|
111
|
+
async def reflect(self, result: Dict[str, Any]) -> Dict[str, Any]:
|
|
112
|
+
"""Reflect on execution result.
|
|
113
|
+
|
|
114
|
+
Args:
|
|
115
|
+
result: Execution result to reflect on
|
|
116
|
+
|
|
117
|
+
Returns:
|
|
118
|
+
Reflection insights
|
|
119
|
+
"""
|
|
120
|
+
logger.debug(f"Agent {self.id} reflecting on result")
|
|
121
|
+
|
|
122
|
+
return {
|
|
123
|
+
"agent_id": self.id,
|
|
124
|
+
"reflection": "Reflection placeholder",
|
|
125
|
+
"improvements": [],
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
def get_stats(self) -> Dict[str, Any]:
|
|
129
|
+
"""Get agent statistics.
|
|
130
|
+
|
|
131
|
+
Returns:
|
|
132
|
+
Agent statistics
|
|
133
|
+
"""
|
|
134
|
+
return {
|
|
135
|
+
"id": self.id,
|
|
136
|
+
"role": self.config.role,
|
|
137
|
+
"execution_count": self._execution_count,
|
|
138
|
+
"total_tokens": self._total_tokens,
|
|
139
|
+
"agent_type": self.config.agent_type,
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
def reset_stats(self) -> None:
|
|
143
|
+
"""Reset agent statistics."""
|
|
144
|
+
self._execution_count = 0
|
|
145
|
+
self._total_tokens = 0
|
|
146
|
+
self._last_result = None
|
|
147
|
+
logger.info(f"Agent {self.id} statistics reset")
|
|
148
|
+
|
|
149
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
150
|
+
"""Convert agent to dictionary.
|
|
151
|
+
|
|
152
|
+
Returns:
|
|
153
|
+
Dictionary representation
|
|
154
|
+
"""
|
|
155
|
+
return {
|
|
156
|
+
"id": self.id,
|
|
157
|
+
"config": self.config.dict(),
|
|
158
|
+
"stats": self.get_stats(),
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
def __repr__(self) -> str:
|
|
162
|
+
"""String representation."""
|
|
163
|
+
return f"Agent(id={self.id}, role={self.config.role}, type={self.config.agent_type})"
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
class AgentFactory:
|
|
167
|
+
"""Factory for creating agents."""
|
|
168
|
+
|
|
169
|
+
@staticmethod
|
|
170
|
+
def create_agent(
|
|
171
|
+
id: str,
|
|
172
|
+
role: str,
|
|
173
|
+
goal: str,
|
|
174
|
+
**kwargs: Any,
|
|
175
|
+
) -> Agent:
|
|
176
|
+
"""Create an agent with given configuration.
|
|
177
|
+
|
|
178
|
+
Args:
|
|
179
|
+
id: Agent identifier
|
|
180
|
+
role: Agent role
|
|
181
|
+
goal: Agent goal
|
|
182
|
+
**kwargs: Additional configuration
|
|
183
|
+
|
|
184
|
+
Returns:
|
|
185
|
+
Configured agent
|
|
186
|
+
"""
|
|
187
|
+
config = AgentConfig(
|
|
188
|
+
role=role,
|
|
189
|
+
goal=goal,
|
|
190
|
+
**kwargs,
|
|
191
|
+
)
|
|
192
|
+
|
|
193
|
+
return Agent(id=id, config=config)
|
|
194
|
+
|
|
195
|
+
@staticmethod
|
|
196
|
+
def create_from_dict(data: Dict[str, Any]) -> Agent:
|
|
197
|
+
"""Create agent from dictionary.
|
|
198
|
+
|
|
199
|
+
Args:
|
|
200
|
+
data: Agent data
|
|
201
|
+
|
|
202
|
+
Returns:
|
|
203
|
+
Agent instance
|
|
204
|
+
"""
|
|
205
|
+
config = AgentConfig(**data.get("config", {}))
|
|
206
|
+
return Agent(id=data["id"], config=config)
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"""YAML import/export utilities for agent configuration."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
from typing import Any, Dict, Iterable, List
|
|
7
|
+
import yaml
|
|
8
|
+
|
|
9
|
+
from genxai.core.agent.base import Agent, AgentConfig
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def agent_config_to_dict(config: AgentConfig) -> Dict[str, Any]:
|
|
13
|
+
"""Serialize AgentConfig to a dictionary."""
|
|
14
|
+
return config.model_dump(mode="json")
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def agent_config_from_dict(data: Dict[str, Any]) -> AgentConfig:
|
|
18
|
+
"""Load AgentConfig from a dictionary."""
|
|
19
|
+
return AgentConfig(**data)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def agent_to_dict(agent: Agent) -> Dict[str, Any]:
|
|
23
|
+
"""Serialize Agent to a dictionary."""
|
|
24
|
+
return {"id": agent.id, "config": agent_config_to_dict(agent.config)}
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def agent_from_dict(data: Dict[str, Any]) -> Agent:
|
|
28
|
+
"""Load Agent from a dictionary."""
|
|
29
|
+
return Agent(id=data["id"], config=agent_config_from_dict(data["config"]))
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def export_agent_config_yaml(agent: Agent, path: Path) -> None:
|
|
33
|
+
"""Export an agent configuration to a YAML file."""
|
|
34
|
+
payload = agent_to_dict(agent)
|
|
35
|
+
path.write_text(yaml.safe_dump(payload, sort_keys=False))
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def import_agent_config_yaml(path: Path) -> Agent:
|
|
39
|
+
"""Import an agent configuration from a YAML file."""
|
|
40
|
+
data = yaml.safe_load(path.read_text())
|
|
41
|
+
if not isinstance(data, dict):
|
|
42
|
+
raise ValueError("Invalid YAML format for agent config")
|
|
43
|
+
return agent_from_dict(data)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def export_agents_yaml(agents: Iterable[Agent], path: Path) -> None:
|
|
47
|
+
"""Export a list of agents to YAML."""
|
|
48
|
+
payload = {"agents": [agent_to_dict(agent) for agent in agents]}
|
|
49
|
+
path.write_text(yaml.safe_dump(payload, sort_keys=False))
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def import_agents_yaml(path: Path) -> List[Agent]:
|
|
53
|
+
"""Import a list of agents from YAML."""
|
|
54
|
+
data = yaml.safe_load(path.read_text())
|
|
55
|
+
if not isinstance(data, dict) or "agents" not in data:
|
|
56
|
+
raise ValueError("Invalid YAML format for agents list")
|
|
57
|
+
if not isinstance(data["agents"], list):
|
|
58
|
+
raise ValueError("Invalid YAML format for agents list")
|
|
59
|
+
return [agent_from_dict(item) for item in data["agents"]]
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
"""Agent registry for managing agent instances."""
|
|
2
|
+
|
|
3
|
+
from typing import Dict, Optional, List
|
|
4
|
+
import logging
|
|
5
|
+
|
|
6
|
+
from genxai.core.agent.base import Agent
|
|
7
|
+
|
|
8
|
+
logger = logging.getLogger(__name__)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class AgentRegistry:
|
|
12
|
+
"""Global registry for managing agent instances."""
|
|
13
|
+
|
|
14
|
+
_agents: Dict[str, Agent] = {}
|
|
15
|
+
|
|
16
|
+
@classmethod
|
|
17
|
+
def register(cls, agent: Agent) -> None:
|
|
18
|
+
"""Register an agent.
|
|
19
|
+
|
|
20
|
+
Args:
|
|
21
|
+
agent: Agent instance to register
|
|
22
|
+
|
|
23
|
+
Raises:
|
|
24
|
+
ValueError: If agent with same ID already exists
|
|
25
|
+
"""
|
|
26
|
+
if agent.id in cls._agents:
|
|
27
|
+
logger.warning(f"Agent '{agent.id}' already registered, overwriting")
|
|
28
|
+
|
|
29
|
+
cls._agents[agent.id] = agent
|
|
30
|
+
logger.info(f"Registered agent: {agent.id} (role: {agent.config.role})")
|
|
31
|
+
|
|
32
|
+
@classmethod
|
|
33
|
+
def get(cls, agent_id: str) -> Optional[Agent]:
|
|
34
|
+
"""Get an agent by ID.
|
|
35
|
+
|
|
36
|
+
Args:
|
|
37
|
+
agent_id: Agent identifier
|
|
38
|
+
|
|
39
|
+
Returns:
|
|
40
|
+
Agent instance if found, None otherwise
|
|
41
|
+
"""
|
|
42
|
+
agent = cls._agents.get(agent_id)
|
|
43
|
+
if agent is None:
|
|
44
|
+
logger.warning(f"Agent '{agent_id}' not found in registry")
|
|
45
|
+
return agent
|
|
46
|
+
|
|
47
|
+
@classmethod
|
|
48
|
+
def unregister(cls, agent_id: str) -> bool:
|
|
49
|
+
"""Unregister an agent.
|
|
50
|
+
|
|
51
|
+
Args:
|
|
52
|
+
agent_id: Agent identifier
|
|
53
|
+
|
|
54
|
+
Returns:
|
|
55
|
+
True if agent was unregistered, False if not found
|
|
56
|
+
"""
|
|
57
|
+
if agent_id in cls._agents:
|
|
58
|
+
del cls._agents[agent_id]
|
|
59
|
+
logger.info(f"Unregistered agent: {agent_id}")
|
|
60
|
+
return True
|
|
61
|
+
return False
|
|
62
|
+
|
|
63
|
+
@classmethod
|
|
64
|
+
def list_all(cls) -> List[str]:
|
|
65
|
+
"""List all registered agent IDs.
|
|
66
|
+
|
|
67
|
+
Returns:
|
|
68
|
+
List of agent IDs
|
|
69
|
+
"""
|
|
70
|
+
return list(cls._agents.keys())
|
|
71
|
+
|
|
72
|
+
@classmethod
|
|
73
|
+
def get_all(cls) -> Dict[str, Agent]:
|
|
74
|
+
"""Get all registered agents.
|
|
75
|
+
|
|
76
|
+
Returns:
|
|
77
|
+
Dictionary of agent ID to agent instance
|
|
78
|
+
"""
|
|
79
|
+
return cls._agents.copy()
|
|
80
|
+
|
|
81
|
+
@classmethod
|
|
82
|
+
def clear(cls) -> None:
|
|
83
|
+
"""Clear all registered agents."""
|
|
84
|
+
count = len(cls._agents)
|
|
85
|
+
cls._agents.clear()
|
|
86
|
+
logger.info(f"Cleared {count} agents from registry")
|
|
87
|
+
|
|
88
|
+
@classmethod
|
|
89
|
+
def get_stats(cls) -> Dict[str, int]:
|
|
90
|
+
"""Get registry statistics.
|
|
91
|
+
|
|
92
|
+
Returns:
|
|
93
|
+
Dictionary with registry stats
|
|
94
|
+
"""
|
|
95
|
+
return {
|
|
96
|
+
"total_agents": len(cls._agents),
|
|
97
|
+
"agent_ids": cls.list_all(),
|
|
98
|
+
}
|