solana-agent 12.0.0__py3-none-any.whl → 14.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.
- solana_agent/__init__.py +33 -1
- solana_agent/adapters/__init__.py +6 -0
- solana_agent/adapters/llm_adapter.py +123 -0
- solana_agent/adapters/mongodb_adapter.py +69 -0
- solana_agent/client/__init__.py +0 -0
- solana_agent/client/solana_agent.py +75 -0
- solana_agent/domains/__init__.py +6 -0
- solana_agent/domains/agents.py +80 -0
- solana_agent/domains/routing.py +14 -0
- solana_agent/factories/__init__.py +0 -0
- solana_agent/factories/agent_factory.py +148 -0
- solana_agent/interfaces/__init__.py +11 -0
- solana_agent/interfaces/plugins/plugins.py +118 -0
- solana_agent/interfaces/providers/data_storage.py +53 -0
- solana_agent/interfaces/providers/llm.py +34 -0
- solana_agent/interfaces/providers/memory.py +38 -0
- solana_agent/interfaces/repositories/agent.py +33 -0
- solana_agent/interfaces/services/agent.py +41 -0
- solana_agent/interfaces/services/query.py +11 -0
- solana_agent/interfaces/services/routing.py +19 -0
- solana_agent/plugins/__init__.py +6 -0
- solana_agent/plugins/manager.py +147 -0
- solana_agent/plugins/registry.py +64 -0
- solana_agent/plugins/tools/__init__.py +10 -0
- solana_agent/plugins/tools/auto_tool.py +47 -0
- solana_agent/repositories/__init__.py +6 -0
- solana_agent/repositories/agent.py +99 -0
- solana_agent/repositories/memory.py +134 -0
- solana_agent/services/__init__.py +6 -0
- solana_agent/services/agent.py +323 -0
- solana_agent/services/query.py +223 -0
- solana_agent/services/routing.py +149 -0
- solana_agent-14.0.1.dist-info/METADATA +126 -0
- solana_agent-14.0.1.dist-info/RECORD +36 -0
- solana_agent/ai.py +0 -8015
- solana_agent-12.0.0.dist-info/METADATA +0 -395
- solana_agent-12.0.0.dist-info/RECORD +0 -6
- {solana_agent-12.0.0.dist-info → solana_agent-14.0.1.dist-info}/LICENSE +0 -0
- {solana_agent-12.0.0.dist-info → solana_agent-14.0.1.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,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,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")
|