solana-agent 10.0.0__py3-none-any.whl → 11.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.
solana_agent/ai.py CHANGED
@@ -13,7 +13,6 @@ This module implements a clean architecture approach with:
13
13
  import asyncio
14
14
  import datetime
15
15
  import json
16
- import os
17
16
  import re
18
17
  import traceback
19
18
  import uuid
@@ -39,10 +38,6 @@ from zep_python.client import AsyncZep
39
38
  from zep_cloud.types import Message
40
39
  from pinecone import Pinecone
41
40
  from abc import ABC, abstractmethod
42
- import sys
43
- import importlib
44
- import subprocess
45
- from pathlib import Path
46
41
 
47
42
 
48
43
  #############################################
@@ -5034,181 +5029,47 @@ class PluginManager:
5034
5029
  """Manages discovery, loading and execution of plugins."""
5035
5030
 
5036
5031
  def __init__(self, plugins_dir: str = "plugins"):
5037
- self.plugins_dir = Path(plugins_dir)
5038
- self.loaded_plugins = {}
5039
- self.plugin_envs = {}
5032
+ self.plugins_dir = plugins_dir
5033
+ self.tools = {}
5040
5034
 
5041
- def discover_plugins(self) -> List[Dict[str, Any]]:
5042
- """Find all plugins in the plugins directory."""
5043
- plugins = []
5044
-
5045
- if not self.plugins_dir.exists():
5046
- return plugins
5047
-
5048
- for plugin_dir in self.plugins_dir.iterdir():
5049
- if not plugin_dir.is_dir():
5050
- continue
5051
-
5052
- metadata_file = plugin_dir / "plugin.json"
5053
-
5054
- if metadata_file.exists():
5055
- try:
5056
- with open(metadata_file, "r") as f:
5057
- metadata = json.load(f)
5058
-
5059
- metadata["path"] = str(plugin_dir)
5060
- plugins.append(metadata)
5061
- except Exception as e:
5062
- print(
5063
- f"Error loading plugin metadata from {metadata_file}: {e}")
5064
-
5065
- return plugins
5066
-
5067
- def setup_plugin_environment(self, plugin_metadata: Dict[str, Any]) -> str:
5068
- """Setup virtual environment for a plugin and install its dependencies.
5069
-
5070
- Args:
5071
- plugin_metadata: Plugin metadata including path
5035
+ def load_all_plugins(self) -> int:
5036
+ """Load all plugins using setuptools entry points.
5072
5037
 
5073
- Returns:
5074
- Path to the plugin's virtual environment
5038
+ Returns the number of plugins loaded for backwards compatibility.
5075
5039
  """
5076
- plugin_name = plugin_metadata["name"]
5077
- plugin_path = Path(plugin_metadata["path"])
5078
-
5079
- # Create virtual environment for plugin
5080
- env_dir = Path(self.plugins_dir) / f"{plugin_name}_env"
5081
-
5082
- # If environment already exists, return its path
5083
- if env_dir.exists():
5084
- return str(env_dir)
5085
-
5086
- print(f"Creating virtual environment for plugin {plugin_name}")
5087
-
5088
- # Check if requirements file exists
5089
- requirements_file = plugin_path / "requirements.txt"
5090
- pyproject_file = plugin_path / "pyproject.toml"
5091
-
5092
- # Create virtual environment
5093
- import venv
5094
- venv.create(env_dir, with_pip=True)
5095
-
5096
- # Determine package installation command (prefer uv if available)
5097
- try:
5098
- # Try to import uv to check if it's installed
5099
- import importlib.util
5100
- uv_spec = importlib.util.find_spec("uv")
5101
- use_uv = uv_spec is not None
5102
- except ImportError:
5103
- use_uv = False
5104
-
5105
- # Install dependencies if requirements file exists
5106
- if requirements_file.exists() or pyproject_file.exists():
5107
- print(f"Installing requirements for plugin {plugin_name}")
5108
-
5109
- # Prepare pip command
5110
- if sys.platform == "win32":
5111
- pip_path = env_dir / "Scripts" / "pip"
5112
- else:
5113
- pip_path = env_dir / "bin" / "pip"
5040
+ import importlib.metadata
5114
5041
 
5115
- # Install dependencies using uv if available
5042
+ count = 0
5043
+ # Discover plugins registered via entry_points
5044
+ for entry_point in importlib.metadata.entry_points(group='solana_agent.plugins'):
5116
5045
  try:
5117
- if use_uv:
5118
- # Use UV for faster dependency installation
5119
- target_file = "pyproject.toml" if pyproject_file.exists() else "requirements.txt"
5120
- subprocess.check_call([
5121
- "uv", "pip", "install",
5122
- "-r" if target_file == "requirements.txt" else ".",
5123
- str(plugin_path / target_file)
5124
- ])
5125
- else:
5126
- # Fall back to regular pip
5127
- if requirements_file.exists():
5128
- subprocess.check_call([
5129
- str(pip_path), "install", "-r",
5130
- str(requirements_file)
5131
- ])
5132
- elif pyproject_file.exists():
5133
- subprocess.check_call([
5134
- str(pip_path), "install",
5135
- str(plugin_path)
5136
- ])
5137
- except subprocess.CalledProcessError as e:
5138
- print(
5139
- f"Failed to install dependencies for plugin {plugin_name}: {e}")
5140
-
5141
- return str(env_dir)
5142
-
5143
- def load_plugin(self, plugin_metadata: Dict[str, Any]) -> bool:
5144
- """Load a plugin and register its tools."""
5145
- plugin_name = plugin_metadata["name"]
5146
- plugin_path = plugin_metadata["path"]
5147
-
5148
- # Setup environment for plugin
5149
- env_dir = self.setup_plugin_environment(plugin_metadata)
5150
- self.plugin_envs[plugin_name] = env_dir
5151
-
5152
- # Add plugin directory to path temporarily (fix for import discovery)
5153
- # We need to add the parent directory, not just the plugin directory itself
5154
- parent_dir = os.path.dirname(str(plugin_path))
5155
- sys.path.insert(0, parent_dir)
5156
-
5157
- try:
5158
- # Import the plugin module
5159
- plugin_module = importlib.import_module(plugin_name)
5160
-
5161
- # Call the plugin's setup function if it exists
5162
- if hasattr(plugin_module, "register_tools"):
5163
- plugin_module.register_tools(tool_registry)
5164
-
5165
- self.loaded_plugins[plugin_name] = plugin_metadata
5166
- return True
5167
-
5168
- except Exception as e:
5169
- print(f"Error loading plugin {plugin_name}: {e}")
5170
- import traceback
5171
- traceback.print_exc() # This will help debug import issues
5172
- return False
5173
-
5174
- finally:
5175
- # Remove the plugin directory from path
5176
- if parent_dir in sys.path:
5177
- sys.path.remove(parent_dir)
5046
+ plugin_class = entry_point.load()
5047
+ plugin = plugin_class()
5048
+
5049
+ # Register all tools from this plugin
5050
+ for tool in plugin.get_tools():
5051
+ self.tools[tool.name] = tool
5052
+ print(f"Registered tool: {tool.name}")
5053
+ count += 1
5054
+ except Exception as e:
5055
+ print(f"Error loading plugin {entry_point.name}: {e}")
5178
5056
 
5179
- def load_all_plugins(self) -> int:
5180
- """Discover and load all available plugins."""
5181
- plugins = self.discover_plugins()
5182
- loaded_count = 0
5057
+ return count
5183
5058
 
5184
- for plugin_metadata in plugins:
5185
- if self.load_plugin(plugin_metadata):
5186
- loaded_count += 1
5059
+ def get_tool(self, name):
5060
+ """Get a tool by name."""
5061
+ return self.tools.get(name)
5187
5062
 
5188
- return loaded_count
5063
+ def list_tools(self):
5064
+ """List all available tools."""
5065
+ return list(self.tools.keys())
5189
5066
 
5190
5067
  def execute_tool(self, tool_name: str, **kwargs) -> Dict[str, Any]:
5191
5068
  """Execute a tool with provided parameters."""
5192
- tool = tool_registry.get_tool(tool_name)
5069
+ tool = self.tools.get(tool_name)
5193
5070
  if not tool:
5194
5071
  raise ValueError(f"Tool {tool_name} not found")
5195
5072
 
5196
- # Get the plugin name for this tool
5197
- plugin_name = None
5198
- for name, metadata in self.loaded_plugins.items():
5199
- tool_list = metadata.get("tools", [])
5200
- if isinstance(tool_list, list) and tool_name in tool_list:
5201
- plugin_name = name
5202
- break
5203
-
5204
- if not plugin_name or plugin_name not in self.plugin_envs:
5205
- # If we can't identify the plugin, execute in the current environment
5206
- try:
5207
- return tool.execute(**kwargs)
5208
- except Exception as e:
5209
- return {"error": str(e), "status": "error"}
5210
-
5211
- # Execute in isolated environment
5212
5073
  try:
5213
5074
  return tool.execute(**kwargs)
5214
5075
  except Exception as e:
@@ -1,30 +1,27 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: solana-agent
3
- Version: 10.0.0
3
+ Version: 11.0.0
4
4
  Summary: The Future of Work
5
5
  License: MIT
6
6
  Keywords: ai,openai,ai agents,agi
7
7
  Author: Bevan Hunt
8
8
  Author-email: bevan@bevanhunt.com
9
- Requires-Python: >=3.9,<4.0
9
+ Requires-Python: >=3.12,<4.0
10
10
  Classifier: License :: OSI Approved :: MIT License
11
11
  Classifier: Programming Language :: Python :: 3
12
- Classifier: Programming Language :: Python :: 3.9
13
- Classifier: Programming Language :: Python :: 3.10
14
- Classifier: Programming Language :: Python :: 3.11
15
12
  Classifier: Programming Language :: Python :: 3.12
16
13
  Classifier: Programming Language :: Python :: 3.13
17
14
  Classifier: Programming Language :: Python :: 3 :: Only
18
15
  Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
19
16
  Requires-Dist: ntplib (>=0.4.0,<0.5.0)
20
- Requires-Dist: openai (>=1.65.5,<2.0.0)
17
+ Requires-Dist: openai (>=1.66.1,<2.0.0)
21
18
  Requires-Dist: pandas (>=2.2.3,<3.0.0)
22
19
  Requires-Dist: pinecone (>=6.0.1,<7.0.0)
23
20
  Requires-Dist: pydantic (>=2.10.6,<3.0.0)
24
21
  Requires-Dist: pymongo (>=4.11.2,<5.0.0)
25
22
  Requires-Dist: qdrant-client (>=1.13.3,<2.0.0)
26
23
  Requires-Dist: requests (>=2.32.3,<3.0.0)
27
- Requires-Dist: zep-cloud (>=2.5.0,<3.0.0)
24
+ Requires-Dist: zep-cloud (>=2.6.1,<3.0.0)
28
25
  Requires-Dist: zep-python (>=2.0.2,<3.0.0)
29
26
  Project-URL: Repository, https://github.com/truemagic-coder/solana-agent
30
27
  Description-Content-Type: text/markdown
@@ -33,7 +30,7 @@ Description-Content-Type: text/markdown
33
30
 
34
31
  [![PyPI - Version](https://img.shields.io/pypi/v/solana-agent)](https://pypi.org/project/solana-agent/)
35
32
  [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](https://opensource.org/licenses/MIT)
36
- [![Python 3.9+](https://img.shields.io/badge/python-3.9+-orange.svg)](https://www.python.org/downloads/)
33
+ [![Python 3.12+](https://img.shields.io/badge/python-3.12+-orange.svg)](https://www.python.org/downloads/)
37
34
  [![codecov](https://img.shields.io/codecov/c/github/truemagic-coder/solana-agent/main.svg)](https://codecov.io/gh/truemagic-coder/solana-agent)
38
35
  [![Build Status](https://img.shields.io/github/actions/workflow/status/truemagic-coder/solana-agent/test.yml?branch=main)](https://github.com/truemagic-coder/solana-agent/actions/workflows/test.yml)
39
36
 
@@ -246,15 +243,15 @@ Solana Agent transforms organizations into living systems that continuously lear
246
243
  Standardized interfaces across all tenants.
247
244
  Efficient multi-tenant scaling with shared infrastructure.
248
245
 
249
- - **🔌 Plugin System:**
250
- Extensible architecture with dynamic tool loading capabilities.
251
- Isolated plugin environments with dependency management.
246
+ - **🔌 Standard Python Plugin System:**
247
+ Extensible architecture using Python's native package ecosystem.
248
+ PyPI-compatible plugin distribution with standard dependency management.
249
+ Entry point registration (`solana_agent.plugins`) for seamless discovery.
252
250
  Tool registry for AI agent capability extension.
253
251
  Permission-based tool access for security and control.
254
- Standard interface for third-party integrations.
252
+ Clean interface for third-party integrations through standard Python APIs.
255
253
  Built-in internet search capabilities via Perplexity API.
256
- Seamless AI agent interaction with external services.
257
- Runtime tool discovery without code modification.
254
+ Runtime tool discovery without service restarts.
258
255
 
259
256
  ## Implementation Technologies
260
257
 
@@ -281,7 +278,7 @@ You can install Solana Agent using pip:
281
278
 
282
279
  Each public method has a docstring for real-time IDE hinting.
283
280
 
284
- ## Example Setup
281
+ ## Example App
285
282
 
286
283
  ```python
287
284
  from solana_agent import SolanaAgent
@@ -356,6 +353,55 @@ async for response in solana_agent.process("user123", "What are the latest AI de
356
353
  print(response, end="")
357
354
  ```
358
355
 
356
+ ## Example Plugin
357
+
358
+ `my_plugin/plugin.py`
359
+
360
+ ```python
361
+ from solana_agent import Tool
362
+
363
+ class MyCustomTool(Tool):
364
+ @property
365
+ def name(self) -> str:
366
+ return "my_custom_tool"
367
+
368
+ @property
369
+ def description(self) -> str:
370
+ return "Does something amazing"
371
+
372
+ @property
373
+ def parameters_schema(self) -> dict:
374
+ return {
375
+ "type": "object",
376
+ "properties": {
377
+ "parameter1": {"type": "string", "description": "First parameter"}
378
+ }
379
+ }
380
+
381
+ def execute(self, **kwargs) -> dict:
382
+ # Tool implementation here
383
+ return {"result": "success", "data": "Something amazing"}
384
+
385
+ class SolanaPlugin:
386
+ def get_tools(self):
387
+ return [MyCustomTool()]
388
+ ```
389
+
390
+ `pyproject.toml`
391
+
392
+ ```toml
393
+ [build-system]
394
+ requires = ["setuptools>=42", "wheel"]
395
+ build-backend = "setuptools.build_meta"
396
+
397
+ [project]
398
+ name = "my-solana-plugin"
399
+ version = "0.1.0"
400
+
401
+ [project.entry-points."solana_agent.plugins"]
402
+ my_plugin = "my_plugin.plugin:SolanaPlugin"
403
+ ```
404
+
359
405
  ## Example App
360
406
 
361
407
  [Solana Agent Example App](https://github.com/truemagic-coder/solana-agent-app)
@@ -0,0 +1,6 @@
1
+ solana_agent/__init__.py,sha256=zpfnWqANd3OHGWm7NCF5Y6m01BWG4NkNk8SK9Ex48nA,18
2
+ solana_agent/ai.py,sha256=XM_bqGz5XLga5SEaKIgSD8_H09DbB6_ir7Tt1tbuJFw,188008
3
+ solana_agent-11.0.0.dist-info/LICENSE,sha256=BnSRc-NSFuyF2s496l_4EyrwAP6YimvxWcjPiJ0J7g4,1057
4
+ solana_agent-11.0.0.dist-info/METADATA,sha256=Ufhql8QGmSGdcQeu5FnFMmnd8qhgVEFDOFb5amIFlQY,17761
5
+ solana_agent-11.0.0.dist-info/WHEEL,sha256=XbeZDeTWKc1w7CSIyre5aMDU_-PohRwTQceYnisIYYY,88
6
+ solana_agent-11.0.0.dist-info/RECORD,,
@@ -1,6 +0,0 @@
1
- solana_agent/__init__.py,sha256=zpfnWqANd3OHGWm7NCF5Y6m01BWG4NkNk8SK9Ex48nA,18
2
- solana_agent/ai.py,sha256=434Wvowzpw48_fGlMWsBUo9oZswwK7DCcsmI_e9bcyI,193201
3
- solana_agent-10.0.0.dist-info/LICENSE,sha256=BnSRc-NSFuyF2s496l_4EyrwAP6YimvxWcjPiJ0J7g4,1057
4
- solana_agent-10.0.0.dist-info/METADATA,sha256=q1dcqNEPYC3wX8dcSoe08z5SWnKkO2qvAIeK1EQC-4E,16816
5
- solana_agent-10.0.0.dist-info/WHEEL,sha256=XbeZDeTWKc1w7CSIyre5aMDU_-PohRwTQceYnisIYYY,88
6
- solana_agent-10.0.0.dist-info/RECORD,,