solana-agent 12.0.0__py3-none-any.whl → 14.0.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 (39) hide show
  1. solana_agent/__init__.py +33 -1
  2. solana_agent/adapters/__init__.py +6 -0
  3. solana_agent/adapters/llm_adapter.py +123 -0
  4. solana_agent/adapters/mongodb_adapter.py +69 -0
  5. solana_agent/client/__init__.py +0 -0
  6. solana_agent/client/solana_agent.py +75 -0
  7. solana_agent/domains/__init__.py +6 -0
  8. solana_agent/domains/agents.py +80 -0
  9. solana_agent/domains/routing.py +14 -0
  10. solana_agent/factories/__init__.py +0 -0
  11. solana_agent/factories/agent_factory.py +148 -0
  12. solana_agent/interfaces/__init__.py +11 -0
  13. solana_agent/interfaces/plugins/plugins.py +118 -0
  14. solana_agent/interfaces/providers/data_storage.py +53 -0
  15. solana_agent/interfaces/providers/llm.py +34 -0
  16. solana_agent/interfaces/providers/memory.py +38 -0
  17. solana_agent/interfaces/repositories/agent.py +33 -0
  18. solana_agent/interfaces/services/agent.py +41 -0
  19. solana_agent/interfaces/services/query.py +11 -0
  20. solana_agent/interfaces/services/routing.py +19 -0
  21. solana_agent/plugins/__init__.py +6 -0
  22. solana_agent/plugins/manager.py +147 -0
  23. solana_agent/plugins/registry.py +64 -0
  24. solana_agent/plugins/tools/__init__.py +10 -0
  25. solana_agent/plugins/tools/auto_tool.py +47 -0
  26. solana_agent/repositories/__init__.py +6 -0
  27. solana_agent/repositories/agent.py +99 -0
  28. solana_agent/repositories/memory.py +134 -0
  29. solana_agent/services/__init__.py +6 -0
  30. solana_agent/services/agent.py +320 -0
  31. solana_agent/services/query.py +223 -0
  32. solana_agent/services/routing.py +149 -0
  33. solana_agent-14.0.0.dist-info/METADATA +121 -0
  34. solana_agent-14.0.0.dist-info/RECORD +36 -0
  35. solana_agent/ai.py +0 -8015
  36. solana_agent-12.0.0.dist-info/METADATA +0 -395
  37. solana_agent-12.0.0.dist-info/RECORD +0 -6
  38. {solana_agent-12.0.0.dist-info → solana_agent-14.0.0.dist-info}/LICENSE +0 -0
  39. {solana_agent-12.0.0.dist-info → solana_agent-14.0.0.dist-info}/WHEEL +0 -0
@@ -0,0 +1,118 @@
1
+ """
2
+ Plugin system interfaces.
3
+
4
+ These interfaces define the contracts for the plugin system,
5
+ enabling extensibility through tools and plugins.
6
+ """
7
+ from abc import ABC, abstractmethod
8
+ from typing import Dict, List, Any, Optional, Callable
9
+
10
+
11
+ class Tool(ABC):
12
+ """Interface for tools that can be used by agents."""
13
+
14
+ @property
15
+ @abstractmethod
16
+ def name(self) -> str:
17
+ """Get the name of the tool."""
18
+ pass
19
+
20
+ @property
21
+ @abstractmethod
22
+ def description(self) -> str:
23
+ """Get the description of the tool."""
24
+ pass
25
+
26
+ @abstractmethod
27
+ def configure(self, config: Dict[str, Any]) -> None:
28
+ """Configure the tool with global configuration."""
29
+ pass
30
+
31
+ @abstractmethod
32
+ def get_schema(self) -> Dict[str, Any]:
33
+ """Get the schema for the tool parameters."""
34
+ pass
35
+
36
+ @abstractmethod
37
+ def execute(self, **params) -> Dict[str, Any]:
38
+ """Execute the tool with the given parameters."""
39
+ pass
40
+
41
+
42
+ class ToolRegistry(ABC):
43
+ """Interface for the tool registry."""
44
+
45
+ @abstractmethod
46
+ def register_tool(self, tool: Tool) -> bool:
47
+ """Register a tool in the registry."""
48
+ pass
49
+
50
+ @abstractmethod
51
+ def get_tool(self, tool_name: str) -> Optional[Tool]:
52
+ """Get a tool by name."""
53
+ pass
54
+
55
+ @abstractmethod
56
+ def assign_tool_to_agent(self, agent_name: str, tool_name: str) -> bool:
57
+ """Give an agent access to a specific tool."""
58
+ pass
59
+
60
+ @abstractmethod
61
+ def get_agent_tools(self, agent_name: str) -> List[Dict[str, Any]]:
62
+ """Get all tools available to an agent."""
63
+ pass
64
+
65
+ @abstractmethod
66
+ def list_all_tools(self) -> List[str]:
67
+ """List all registered tools."""
68
+ pass
69
+
70
+ @abstractmethod
71
+ def configure_all_tools(self, config: Dict[str, Any]) -> None:
72
+ """Configure all registered tools with the same config."""
73
+ pass
74
+
75
+
76
+ class Plugin(ABC):
77
+ """Interface for plugins that can be loaded by the system."""
78
+
79
+ @property
80
+ @abstractmethod
81
+ def name(self) -> str:
82
+ """Get the name of the plugin."""
83
+ pass
84
+
85
+ @property
86
+ @abstractmethod
87
+ def description(self) -> str:
88
+ """Get the description of the plugin."""
89
+ pass
90
+
91
+ @abstractmethod
92
+ def initialize(self, tool_registry: ToolRegistry) -> bool:
93
+ """Initialize the plugin and register its tools."""
94
+ pass
95
+
96
+
97
+ class PluginManager(ABC):
98
+ """Interface for the plugin manager."""
99
+
100
+ @abstractmethod
101
+ def register_plugin(self, plugin: Plugin) -> bool:
102
+ """Register a plugin in the manager."""
103
+ pass
104
+
105
+ @abstractmethod
106
+ def load_plugins(self) -> List[str]:
107
+ """Load all registered plugins."""
108
+ pass
109
+
110
+ @abstractmethod
111
+ def get_plugin(self, name: str) -> Optional[Plugin]:
112
+ """Get a plugin by name."""
113
+ pass
114
+
115
+ @abstractmethod
116
+ def list_plugins(self) -> List[Dict[str, Any]]:
117
+ """List all registered plugins with their details."""
118
+ pass
@@ -0,0 +1,53 @@
1
+ from abc import ABC, abstractmethod
2
+ from typing import Dict, List, Optional
3
+
4
+
5
+ class DataStorageProvider(ABC):
6
+ """Interface for data storage providers."""
7
+
8
+ @abstractmethod
9
+ def create_collection(self, name: str) -> None:
10
+ """Create a new collection."""
11
+ pass
12
+
13
+ @abstractmethod
14
+ def collection_exists(self, name: str) -> bool:
15
+ """Check if collection exists."""
16
+ pass
17
+
18
+ @abstractmethod
19
+ def insert_one(self, collection: str, document: Dict) -> str:
20
+ """Insert a document into a collection."""
21
+ pass
22
+
23
+ @abstractmethod
24
+ def find_one(self, collection: str, query: Dict) -> Optional[Dict]:
25
+ """Find a single document."""
26
+ pass
27
+
28
+ @abstractmethod
29
+ def find(
30
+ self, collection: str, query: Dict, sort: Optional[List] = None, limit: int = 0, skip: int = 0
31
+ ) -> List[Dict]:
32
+ """Find documents matching query."""
33
+ pass
34
+
35
+ @abstractmethod
36
+ def update_one(self, collection: str, query: Dict, update: Dict, upsert: bool = False) -> bool:
37
+ """Update a document."""
38
+ pass
39
+
40
+ @abstractmethod
41
+ def delete_one(self, collection: str, query: Dict) -> bool:
42
+ """Delete a document."""
43
+ pass
44
+
45
+ @abstractmethod
46
+ def create_index(self, collection: str, keys: List, **kwargs) -> None:
47
+ """Create an index."""
48
+ pass
49
+
50
+ @abstractmethod
51
+ def count_documents(self, collection: str, query: Dict) -> int:
52
+ """Count documents matching query."""
53
+ pass
@@ -0,0 +1,34 @@
1
+ from abc import ABC, abstractmethod
2
+ from typing import AsyncGenerator, List, Type, TypeVar
3
+
4
+ from pydantic import BaseModel
5
+
6
+
7
+ T = TypeVar('T', bound=BaseModel)
8
+
9
+
10
+ class LLMProvider(ABC):
11
+ """Interface for language model providers."""
12
+
13
+ @abstractmethod
14
+ async def generate_text(
15
+ self,
16
+ prompt: str,
17
+ system_prompt: str = "",
18
+ needs_search: bool = False,
19
+ **kwargs,
20
+ ) -> AsyncGenerator[str, None]:
21
+ """Generate text from the language model."""
22
+ pass
23
+
24
+ @abstractmethod
25
+ def generate_embedding(self, text: str) -> List[float]:
26
+ """Generate embedding vector for text."""
27
+ pass
28
+
29
+ @abstractmethod
30
+ async def parse_structured_output(
31
+ self, prompt: str, system_prompt: str, model_class: Type[T], **kwargs
32
+ ) -> T:
33
+ """Generate structured output using a specific model class."""
34
+ pass
@@ -0,0 +1,38 @@
1
+ from abc import ABC, abstractmethod
2
+ from typing import Any, Dict, List, Optional, Tuple
3
+
4
+
5
+ class MemoryProvider(ABC):
6
+ """Interface for conversation memory providers."""
7
+
8
+ @abstractmethod
9
+ async def store(self, user_id: str, messages: List[Dict[str, Any]]) -> None:
10
+ """Store messages in memory."""
11
+ pass
12
+
13
+ @abstractmethod
14
+ async def retrieve(self, user_id: str) -> str:
15
+ """Retrieve memory for a user as formatted string."""
16
+ pass
17
+
18
+ @abstractmethod
19
+ async def delete(self, user_id: str) -> None:
20
+ """Delete memory for a user."""
21
+ pass
22
+
23
+ @abstractmethod
24
+ def find(
25
+ self,
26
+ collection: str,
27
+ query: Dict,
28
+ sort: Optional[List[Tuple]] = None,
29
+ limit: int = 0,
30
+ skip: int = 0
31
+ ) -> List[Dict]:
32
+ """Find documents matching query."""
33
+ pass
34
+
35
+ @abstractmethod
36
+ def count_documents(self, collection: str, query: Dict) -> int:
37
+ """Count documents matching query."""
38
+ pass
@@ -0,0 +1,33 @@
1
+ from abc import ABC, abstractmethod
2
+ from typing import List, Optional
3
+
4
+ from solana_agent.domains.agents import AIAgent
5
+
6
+
7
+ class AgentRepository(ABC):
8
+ """Interface for agent data access."""
9
+
10
+ @abstractmethod
11
+ def get_ai_agent_by_name(self, name: str) -> Optional[AIAgent]:
12
+ """Get an AI agent by name."""
13
+ pass
14
+
15
+ @abstractmethod
16
+ def get_ai_agent(self, name: str) -> Optional[AIAgent]:
17
+ """Get an AI agent by name."""
18
+ pass
19
+
20
+ @abstractmethod
21
+ def get_all_ai_agents(self) -> List[AIAgent]:
22
+ """Get all AI agents."""
23
+ pass
24
+
25
+ @abstractmethod
26
+ def save_ai_agent(self, agent: AIAgent) -> bool:
27
+ """Save an AI agent."""
28
+ pass
29
+
30
+ @abstractmethod
31
+ def delete_ai_agent(self, name: str) -> bool:
32
+ """Delete an AI agent."""
33
+ pass
@@ -0,0 +1,41 @@
1
+ from abc import ABC, abstractmethod
2
+ from typing import Any, AsyncGenerator, Dict, List
3
+
4
+
5
+ class AgentService(ABC):
6
+ """Interface for agent management and response generation."""
7
+
8
+ @abstractmethod
9
+ def register_ai_agent(self, name: str, instructions: str, specialization: str, model: str = "gpt-4o-mini") -> None:
10
+ """Register an AI agent with its specialization."""
11
+ pass
12
+
13
+ @abstractmethod
14
+ def get_agent_system_prompt(self, agent_name: str) -> str:
15
+ """Get the system prompt for an agent."""
16
+ pass
17
+
18
+ @abstractmethod
19
+ def get_specializations(self) -> Dict[str, str]:
20
+ """Get all registered specializations."""
21
+ pass
22
+
23
+ @abstractmethod
24
+ async def generate_response(self, agent_name: str, user_id: str, query: str, memory_context: str = "", **kwargs) -> AsyncGenerator[str, None]:
25
+ """Generate a response from an agent."""
26
+ pass
27
+
28
+ @abstractmethod
29
+ def assign_tool_for_agent(self, agent_name: str, tool_name: str) -> bool:
30
+ """Assign a tool to an agent."""
31
+ pass
32
+
33
+ @abstractmethod
34
+ def get_agent_tools(self, agent_name: str) -> List[Dict[str, Any]]:
35
+ """Get tools available to an agent."""
36
+ pass
37
+
38
+ @abstractmethod
39
+ def execute_tool(self, agent_name: str, tool_name: str, parameters: Dict[str, Any]) -> Dict[str, Any]:
40
+ """Execute a tool on behalf of an agent."""
41
+ pass
@@ -0,0 +1,11 @@
1
+ from abc import ABC, abstractmethod
2
+ from typing import AsyncGenerator
3
+
4
+
5
+ class QueryService(ABC):
6
+ """Interface for processing user queries."""
7
+
8
+ @abstractmethod
9
+ async def process(self, user_id: str, query: str) -> AsyncGenerator[str, None]:
10
+ """Process a query from a user."""
11
+ pass
@@ -0,0 +1,19 @@
1
+ from abc import ABC, abstractmethod
2
+ from typing import Any, Tuple
3
+
4
+
5
+ class RoutingService(ABC):
6
+ """Interface for query routing services."""
7
+
8
+ @abstractmethod
9
+ async def route_query(self, user_id: str, query: str) -> Tuple[str, Any]:
10
+ """Route a query to the appropriate agent.
11
+
12
+ Args:
13
+ user_id: User ID
14
+ query: User query
15
+
16
+ Returns:
17
+ Tuple of (agent_name, ticket)
18
+ """
19
+ pass
@@ -0,0 +1,6 @@
1
+ """
2
+ Plugin system for the Solana Agent.
3
+
4
+ This package provides plugin management, tool registration, and plugin discovery
5
+ mechanisms that extend the agent system with custom functionality.
6
+ """
@@ -0,0 +1,147 @@
1
+ """
2
+ Plugin manager for the Solana Agent system.
3
+
4
+ This module implements the concrete PluginManager that discovers,
5
+ loads, and manages plugins.
6
+ """
7
+ import importlib
8
+ from typing import Dict, List, Any, Optional
9
+ import importlib.metadata
10
+
11
+ from solana_agent.interfaces.plugins.plugins import PluginManager as PluginManagerInterface
12
+ from solana_agent.interfaces.plugins.plugins import Plugin
13
+ from solana_agent.plugins.registry import ToolRegistry
14
+
15
+
16
+ class PluginManager(PluginManagerInterface):
17
+ """Manager for discovering and loading plugins."""
18
+
19
+ # Class variable to track loaded entry points
20
+ _loaded_entry_points = set()
21
+
22
+ def __init__(self, config: Optional[Dict[str, Any]] = None, tool_registry: Optional[ToolRegistry] = None):
23
+ """Initialize with optional configuration and tool registry."""
24
+ self.config = config or {}
25
+ self.tool_registry = tool_registry or ToolRegistry()
26
+ self._plugins = {} # Changed to instance variable
27
+
28
+ def register_plugin(self, plugin: Plugin) -> bool:
29
+ """Register a plugin in the manager.
30
+
31
+ Args:
32
+ plugin: The plugin to register
33
+
34
+ Returns:
35
+ True if registration succeeded, False otherwise
36
+ """
37
+ try:
38
+ # Store plugin by name
39
+ self._plugins[plugin.name] = plugin
40
+
41
+ # Initialize the plugin with the tool registry
42
+ plugin.initialize(self.tool_registry)
43
+
44
+ # *** ADD THIS LINE: Configure the plugin with our config ***
45
+ print(f"Configuring plugin {plugin.name} with config")
46
+ plugin.configure(self.config)
47
+
48
+ return True
49
+ except Exception as e:
50
+ print(f"Error registering plugin {plugin.name}: {e}")
51
+ return False
52
+
53
+ def load_plugins(self) -> List[str]:
54
+ """Load all plugins using entry points and apply configuration.
55
+
56
+ Returns:
57
+ List of loaded plugin names
58
+ """
59
+ loaded_plugins = []
60
+
61
+ # Discover plugins through entry points
62
+ try:
63
+ for entry_point in importlib.metadata.entry_points(group='solana_agent.plugins'):
64
+ # Skip if this entry point has already been loaded
65
+ entry_point_id = f"{entry_point.name}:{entry_point.value}"
66
+ if entry_point_id in PluginManager._loaded_entry_points:
67
+ print(
68
+ f"Skipping already loaded plugin: {entry_point.name}")
69
+ continue
70
+
71
+ try:
72
+ print(f"Found plugin entry point: {entry_point.name}")
73
+ PluginManager._loaded_entry_points.add(entry_point_id)
74
+ plugin_factory = entry_point.load()
75
+ plugin = plugin_factory()
76
+
77
+ # Register the plugin
78
+ if self.register_plugin(plugin):
79
+ # Use entry_point.name instead of plugin.name
80
+ loaded_plugins.append(entry_point.name)
81
+
82
+ except Exception as e:
83
+ print(f"Error loading plugin {entry_point.name}: {e}")
84
+ except Exception as e:
85
+ print(f"Error discovering plugins: {e}")
86
+
87
+ return loaded_plugins
88
+
89
+ def get_plugin(self, name: str) -> Optional[Plugin]:
90
+ """Get a plugin by name.
91
+
92
+ Args:
93
+ name: Name of the plugin to retrieve
94
+
95
+ Returns:
96
+ Plugin instance or None if not found
97
+ """
98
+ return self._plugins.get(name)
99
+
100
+ def list_plugins(self) -> List[Dict[str, Any]]:
101
+ """List all registered plugins with their details.
102
+
103
+ Returns:
104
+ List of plugin details dictionaries
105
+ """
106
+ return [
107
+ {
108
+ "name": plugin.name,
109
+ "description": plugin.description
110
+ }
111
+ for plugin in self._plugins.values()
112
+ ]
113
+
114
+ def execute_tool(self, tool_name: str, **kwargs) -> Dict[str, Any]:
115
+ """Execute a tool with the given parameters.
116
+
117
+ Args:
118
+ tool_name: Name of the tool to execute
119
+ **kwargs: Parameters to pass to the tool
120
+
121
+ Returns:
122
+ Dictionary with execution results
123
+ """
124
+ tool = self.tool_registry.get_tool(tool_name)
125
+ if not tool:
126
+ return {"status": "error", "message": f"Tool {tool_name} not found"}
127
+
128
+ try:
129
+ return tool.execute(**kwargs)
130
+ except Exception as e:
131
+ return {"status": "error", "message": str(e)}
132
+
133
+ def configure(self, config: Dict[str, Any]) -> None:
134
+ """Configure the plugin manager and all plugins.
135
+
136
+ Args:
137
+ config: Configuration dictionary
138
+ """
139
+ self.config.update(config)
140
+ self.tool_registry.configure_all_tools(config)
141
+ print("Configuring all plugins with updated config")
142
+ for name, plugin in self._plugins.items():
143
+ try:
144
+ print(f"Configuring plugin: {name}")
145
+ plugin.configure(self.config)
146
+ except Exception as e:
147
+ print(f"Error configuring plugin {name}: {e}")
@@ -0,0 +1,64 @@
1
+ """
2
+ Tool registry for the Solana Agent system.
3
+
4
+ This module implements the concrete ToolRegistry that manages tools
5
+ and their access permissions.
6
+ """
7
+ from typing import Dict, List, Any, Optional
8
+
9
+ from solana_agent.interfaces.plugins.plugins import ToolRegistry as ToolRegistryInterface
10
+ from solana_agent.interfaces.plugins.plugins import Tool
11
+
12
+
13
+ class ToolRegistry(ToolRegistryInterface):
14
+ """Instance-based registry that manages tools and their access permissions."""
15
+
16
+ def __init__(self):
17
+ """Initialize an empty tool registry."""
18
+ self._tools = {} # name -> tool instance
19
+ self._agent_tools = {} # agent_name -> [tool_names]
20
+
21
+ def register_tool(self, tool: Tool) -> bool:
22
+ """Register a tool with this registry."""
23
+ self._tools[tool.name] = tool
24
+ print(f"Registered tool: {tool.name}")
25
+ return True
26
+
27
+ def get_tool(self, tool_name: str) -> Optional[Tool]:
28
+ """Get a tool by name."""
29
+ return self._tools.get(tool_name)
30
+
31
+ def assign_tool_to_agent(self, agent_name: str, tool_name: str) -> bool:
32
+ """Give an agent access to a specific tool."""
33
+ if tool_name not in self._tools:
34
+ print(f"Error: Tool {tool_name} is not registered")
35
+ return False
36
+
37
+ if agent_name not in self._agent_tools:
38
+ self._agent_tools[agent_name] = []
39
+
40
+ if tool_name not in self._agent_tools[agent_name]:
41
+ self._agent_tools[agent_name].append(tool_name)
42
+
43
+ return True
44
+
45
+ def get_agent_tools(self, agent_name: str) -> List[Dict[str, Any]]:
46
+ """Get all tools available to an agent."""
47
+ tool_names = self._agent_tools.get(agent_name, [])
48
+ return [
49
+ {
50
+ "name": name,
51
+ "description": self._tools[name].description,
52
+ "parameters": self._tools[name].get_schema()
53
+ }
54
+ for name in tool_names if name in self._tools
55
+ ]
56
+
57
+ def list_all_tools(self) -> List[str]:
58
+ """List all registered tools."""
59
+ return list(self._tools.keys())
60
+
61
+ def configure_all_tools(self, config: Dict[str, Any]) -> None:
62
+ """Configure all registered tools with the same config."""
63
+ for tool in self._tools.values():
64
+ tool.configure(config)
@@ -0,0 +1,10 @@
1
+ """
2
+ Tools for the Solana Agent system.
3
+
4
+ This package contains the base AutoTool class and built-in tool implementations.
5
+ """
6
+
7
+ from solana_agent.plugins.tools.auto_tool import *
8
+
9
+ # Version of the domain model
10
+ __version__ = '14.0.0'
@@ -0,0 +1,47 @@
1
+ """
2
+ AutoTool implementation for the Solana Agent system.
3
+
4
+ This module provides the base AutoTool class that implements the Tool interface
5
+ and can be extended to create custom tools.
6
+ """
7
+ from typing import Dict, Any
8
+
9
+ from solana_agent.interfaces.plugins.plugins import Tool
10
+
11
+
12
+ class AutoTool(Tool):
13
+ """Base class for tools that automatically register with the system."""
14
+
15
+ def __init__(self, name: str, description: str, registry=None):
16
+ """Initialize the tool with name and description."""
17
+ self._name = name
18
+ self._description = description
19
+ self._config = {}
20
+
21
+ # Register with the provided registry if given
22
+ if registry is not None:
23
+ registry.register_tool(self)
24
+
25
+ @property
26
+ def name(self) -> str:
27
+ """Get the name of the tool."""
28
+ return self._name
29
+
30
+ @property
31
+ def description(self) -> str:
32
+ """Get the description of the tool."""
33
+ return self._description
34
+
35
+ def configure(self, config: Dict[str, Any]) -> None:
36
+ """Configure the tool with settings from config."""
37
+ self._config = config
38
+
39
+ def get_schema(self) -> Dict[str, Any]:
40
+ """Return the JSON schema for this tool's parameters."""
41
+ # Override in subclasses
42
+ return {}
43
+
44
+ def execute(self, **params) -> Dict[str, Any]:
45
+ """Execute the tool with the provided parameters."""
46
+ # Override in subclasses
47
+ raise NotImplementedError("Tool must implement execute method")
@@ -0,0 +1,6 @@
1
+ """
2
+ Repository implementations for data access.
3
+
4
+ This package contains repository implementations that provide
5
+ data access capabilities for the domain models.
6
+ """