solana-agent 31.2.4__tar.gz → 31.2.6__tar.gz

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 (48) hide show
  1. {solana_agent-31.2.4 → solana_agent-31.2.6}/PKG-INFO +5 -5
  2. {solana_agent-31.2.4 → solana_agent-31.2.6}/pyproject.toml +7 -7
  3. solana_agent-31.2.6/solana_agent/domains/routing.py +24 -0
  4. {solana_agent-31.2.4 → solana_agent-31.2.6}/solana_agent/services/routing.py +32 -21
  5. solana_agent-31.2.4/solana_agent/domains/routing.py +0 -14
  6. {solana_agent-31.2.4 → solana_agent-31.2.6}/LICENSE +0 -0
  7. {solana_agent-31.2.4 → solana_agent-31.2.6}/README.md +0 -0
  8. {solana_agent-31.2.4 → solana_agent-31.2.6}/solana_agent/__init__.py +0 -0
  9. {solana_agent-31.2.4 → solana_agent-31.2.6}/solana_agent/adapters/__init__.py +0 -0
  10. {solana_agent-31.2.4 → solana_agent-31.2.6}/solana_agent/adapters/ffmpeg_transcoder.py +0 -0
  11. {solana_agent-31.2.4 → solana_agent-31.2.6}/solana_agent/adapters/mongodb_adapter.py +0 -0
  12. {solana_agent-31.2.4 → solana_agent-31.2.6}/solana_agent/adapters/openai_adapter.py +0 -0
  13. {solana_agent-31.2.4 → solana_agent-31.2.6}/solana_agent/adapters/openai_realtime_ws.py +0 -0
  14. {solana_agent-31.2.4 → solana_agent-31.2.6}/solana_agent/adapters/pinecone_adapter.py +0 -0
  15. {solana_agent-31.2.4 → solana_agent-31.2.6}/solana_agent/cli.py +0 -0
  16. {solana_agent-31.2.4 → solana_agent-31.2.6}/solana_agent/client/__init__.py +0 -0
  17. {solana_agent-31.2.4 → solana_agent-31.2.6}/solana_agent/client/solana_agent.py +0 -0
  18. {solana_agent-31.2.4 → solana_agent-31.2.6}/solana_agent/domains/__init__.py +0 -0
  19. {solana_agent-31.2.4 → solana_agent-31.2.6}/solana_agent/domains/agent.py +0 -0
  20. {solana_agent-31.2.4 → solana_agent-31.2.6}/solana_agent/factories/__init__.py +0 -0
  21. {solana_agent-31.2.4 → solana_agent-31.2.6}/solana_agent/factories/agent_factory.py +0 -0
  22. {solana_agent-31.2.4 → solana_agent-31.2.6}/solana_agent/guardrails/pii.py +0 -0
  23. {solana_agent-31.2.4 → solana_agent-31.2.6}/solana_agent/interfaces/__init__.py +0 -0
  24. {solana_agent-31.2.4 → solana_agent-31.2.6}/solana_agent/interfaces/client/client.py +0 -0
  25. {solana_agent-31.2.4 → solana_agent-31.2.6}/solana_agent/interfaces/guardrails/guardrails.py +0 -0
  26. {solana_agent-31.2.4 → solana_agent-31.2.6}/solana_agent/interfaces/plugins/plugins.py +0 -0
  27. {solana_agent-31.2.4 → solana_agent-31.2.6}/solana_agent/interfaces/providers/audio.py +0 -0
  28. {solana_agent-31.2.4 → solana_agent-31.2.6}/solana_agent/interfaces/providers/data_storage.py +0 -0
  29. {solana_agent-31.2.4 → solana_agent-31.2.6}/solana_agent/interfaces/providers/llm.py +0 -0
  30. {solana_agent-31.2.4 → solana_agent-31.2.6}/solana_agent/interfaces/providers/memory.py +0 -0
  31. {solana_agent-31.2.4 → solana_agent-31.2.6}/solana_agent/interfaces/providers/realtime.py +0 -0
  32. {solana_agent-31.2.4 → solana_agent-31.2.6}/solana_agent/interfaces/providers/vector_storage.py +0 -0
  33. {solana_agent-31.2.4 → solana_agent-31.2.6}/solana_agent/interfaces/services/agent.py +0 -0
  34. {solana_agent-31.2.4 → solana_agent-31.2.6}/solana_agent/interfaces/services/knowledge_base.py +0 -0
  35. {solana_agent-31.2.4 → solana_agent-31.2.6}/solana_agent/interfaces/services/query.py +0 -0
  36. {solana_agent-31.2.4 → solana_agent-31.2.6}/solana_agent/interfaces/services/routing.py +0 -0
  37. {solana_agent-31.2.4 → solana_agent-31.2.6}/solana_agent/plugins/__init__.py +0 -0
  38. {solana_agent-31.2.4 → solana_agent-31.2.6}/solana_agent/plugins/manager.py +0 -0
  39. {solana_agent-31.2.4 → solana_agent-31.2.6}/solana_agent/plugins/registry.py +0 -0
  40. {solana_agent-31.2.4 → solana_agent-31.2.6}/solana_agent/plugins/tools/__init__.py +0 -0
  41. {solana_agent-31.2.4 → solana_agent-31.2.6}/solana_agent/plugins/tools/auto_tool.py +0 -0
  42. {solana_agent-31.2.4 → solana_agent-31.2.6}/solana_agent/repositories/__init__.py +0 -0
  43. {solana_agent-31.2.4 → solana_agent-31.2.6}/solana_agent/repositories/memory.py +0 -0
  44. {solana_agent-31.2.4 → solana_agent-31.2.6}/solana_agent/services/__init__.py +0 -0
  45. {solana_agent-31.2.4 → solana_agent-31.2.6}/solana_agent/services/agent.py +0 -0
  46. {solana_agent-31.2.4 → solana_agent-31.2.6}/solana_agent/services/knowledge_base.py +0 -0
  47. {solana_agent-31.2.4 → solana_agent-31.2.6}/solana_agent/services/query.py +0 -0
  48. {solana_agent-31.2.4 → solana_agent-31.2.6}/solana_agent/services/realtime.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: solana-agent
3
- Version: 31.2.4
3
+ Version: 31.2.6
4
4
  Summary: AI Agents for Solana
5
5
  License: MIT
6
6
  Keywords: solana,solana ai,solana agent,ai,ai agent,ai agents
@@ -15,14 +15,14 @@ Classifier: Programming Language :: Python :: 3.12
15
15
  Classifier: Programming Language :: Python :: 3.13
16
16
  Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
17
17
  Requires-Dist: instructor (==1.11.3)
18
- Requires-Dist: llama-index-core (==0.14.0)
18
+ Requires-Dist: llama-index-core (==0.14.1)
19
19
  Requires-Dist: llama-index-embeddings-openai (==0.5.1)
20
- Requires-Dist: logfire (==4.5.0)
21
- Requires-Dist: openai (==1.107.0)
20
+ Requires-Dist: logfire (==4.7.0)
21
+ Requires-Dist: openai (==1.107.2)
22
22
  Requires-Dist: pillow (==11.3.0)
23
23
  Requires-Dist: pinecone[asyncio] (==7.3.0)
24
24
  Requires-Dist: pydantic (>=2)
25
- Requires-Dist: pymongo (==4.14.1)
25
+ Requires-Dist: pymongo (==4.15.0)
26
26
  Requires-Dist: pypdf (==6.0.0)
27
27
  Requires-Dist: rich (>=13,<14.0)
28
28
  Requires-Dist: scrubadub (==2.0.1)
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "solana-agent"
3
- version = "31.2.4"
3
+ version = "31.2.6"
4
4
  description = "AI Agents for Solana"
5
5
  authors = ["Bevan Hunt <bevan@bevanhunt.com>"]
6
6
  license = "MIT"
@@ -24,17 +24,17 @@ testpaths = ["tests"]
24
24
 
25
25
  [tool.poetry.dependencies]
26
26
  python = ">=3.12,<4.0"
27
- openai = "1.107.0"
27
+ openai = "1.107.2"
28
28
  pydantic = ">=2"
29
- pymongo = "4.14.1"
29
+ pymongo = "4.15.0"
30
30
  zep-cloud = "3.4.3"
31
31
  instructor = "1.11.3"
32
32
  pinecone = { version = "7.3.0", extras = ["asyncio"] }
33
- llama-index-core = "0.14.0"
33
+ llama-index-core = "0.14.1"
34
34
  llama-index-embeddings-openai = "0.5.1"
35
35
  pypdf = "6.0.0"
36
36
  scrubadub = "2.0.1"
37
- logfire = "4.5.0"
37
+ logfire = "4.7.0"
38
38
  typer = "0.17.4"
39
39
  rich = ">=13,<14.0"
40
40
  pillow = "11.3.0"
@@ -43,7 +43,7 @@ websockets = ">=13,<16"
43
43
  [tool.poetry.group.dev.dependencies]
44
44
  pytest = "^8.4.2"
45
45
  pytest-cov = "^7.0.0"
46
- pytest-asyncio = "^1.1.0"
46
+ pytest-asyncio = "^1.2.0"
47
47
  pytest-mock = "^3.15.0"
48
48
  pytest-github-actions-annotate-failures = "^0.3.0"
49
49
  sphinx = "^8.2.3"
@@ -51,7 +51,7 @@ sphinx-rtd-theme = "^3.0.2"
51
51
  myst-parser = "^4.0.1"
52
52
  sphinx-autobuild = "^2025.08.25"
53
53
  mongomock = "^4.3.0"
54
- ruff = "^0.12.12"
54
+ ruff = "^0.13.0"
55
55
 
56
56
  [tool.poetry.scripts]
57
57
  solana-agent = "solana_agent.cli:app"
@@ -0,0 +1,24 @@
1
+ from typing import List
2
+ from pydantic import BaseModel, Field
3
+
4
+
5
+ class QueryAnalysis(BaseModel):
6
+ """Analysis of a user query for routing purposes."""
7
+
8
+ primary_agent: str = Field(
9
+ ...,
10
+ description="Name of the primary agent that should handle this query (must be one of the available agent names)",
11
+ )
12
+ secondary_agents: List[str] = Field(
13
+ default_factory=list,
14
+ description="Names of secondary agents that might be helpful (must be from the available agent names)",
15
+ )
16
+ complexity_level: int = Field(
17
+ default=1, description="Complexity level (1-5)", ge=1, le=5
18
+ )
19
+ topics: List[str] = Field(
20
+ default_factory=list, description="Key topics in the query"
21
+ )
22
+ confidence: float = Field(
23
+ default=0.5, description="Confidence in the analysis", ge=0.0, le=1.0
24
+ )
@@ -1,11 +1,3 @@
1
- """
2
- Routing service implementation.
3
-
4
- This service manages query routing to appropriate agents using an LLM-based
5
- analysis. It defaults to a small, low-cost model for routing to minimize
6
- overhead while maintaining quality.
7
- """
8
-
9
1
  import logging
10
2
  from typing import Dict, List, Optional, Any
11
3
  from solana_agent.interfaces.services.routing import (
@@ -81,37 +73,48 @@ class RoutingService(RoutingServiceInterface):
81
73
 
82
74
  USER QUERY: {query}
83
75
 
84
- Please determine:
85
- 1. Which agent is the primary best match for this query (must be one of the listed agents)
86
- 2. Any secondary agents that might be helpful (must be from the listed agents)
87
- 3. The complexity level (1-5, where 5 is most complex)
88
- 4. Any key topics or technologies mentioned
76
+ ROUTING RULES:
77
+ - Match the user query to the agent whose specialization best fits the user's intent
78
+ - Return the EXACT agent name that matches best
79
+
80
+ INSTRUCTIONS:
81
+ - primary_agent: The exact name of the best matching agent (e.g., "onboarding", "event_feedback")
82
+ - secondary_agents: Other agents that might help (usually empty)
83
+ - complexity_level: 1-5 (5 being most complex)
84
+ - topics: Key topics mentioned
85
+ - confidence: 0.0-1.0 (how confident you are in this routing decision)
86
+
87
+ For the query "{query}", which agent should handle it?
89
88
  """
90
89
 
91
90
  try:
92
91
  analysis = await self.llm_provider.parse_structured_output(
93
92
  prompt=prompt,
94
- system_prompt="Match user queries to the most appropriate agent based on specializations.",
93
+ system_prompt="You are an expert at routing user queries to the most appropriate AI agent. Always return the exact agent name that best matches the user's needs based on the specializations provided. If the user mentions a specific topic, prioritize agents whose specialization matches that topic.",
95
94
  model_class=QueryAnalysis,
96
95
  api_key=self.api_key,
97
96
  base_url=self.base_url,
98
97
  model=self.model,
99
98
  )
100
99
 
100
+ logger.debug(f"LLM analysis result: {analysis}")
101
+
101
102
  return {
102
- "primary_specialization": analysis.primary_specialization,
103
- "secondary_specializations": analysis.secondary_specializations,
103
+ "primary_specialization": analysis.primary_agent,
104
+ "secondary_specializations": analysis.secondary_agents,
104
105
  "complexity_level": analysis.complexity_level,
105
106
  "topics": analysis.topics,
106
107
  "confidence": analysis.confidence,
107
108
  }
108
109
  except Exception as e:
109
- logger.error(f"Error analyzing query: {e}") # Use logger.error
110
+ logger.error(f"Error analyzing query: {e}")
111
+ logger.debug(f"Query that failed: {query}")
112
+ logger.debug(f"Available agents: {list(agents.keys())}")
110
113
  # Return default analysis on error
114
+ first_agent = list(agents.keys())[0] if agents else "general"
115
+ logger.debug(f"Defaulting to first agent: {first_agent}")
111
116
  return {
112
- "primary_specialization": list(agents.keys())[0]
113
- if agents
114
- else "general",
117
+ "primary_specialization": first_agent,
115
118
  "secondary_specializations": [],
116
119
  "complexity_level": 1,
117
120
  "topics": [],
@@ -143,9 +146,11 @@ class RoutingService(RoutingServiceInterface):
143
146
 
144
147
  # Always analyze with a small model to select the best agent
145
148
  analysis = await self._analyze_query(query)
149
+ logger.debug(f"Routing analysis for query '{query}': {analysis}")
146
150
  best_agent = await self._find_best_ai_agent(
147
151
  analysis["primary_specialization"], analysis["secondary_specializations"]
148
152
  )
153
+ logger.debug(f"Selected agent: {best_agent}")
149
154
  chosen = best_agent or next(iter(agents.keys()))
150
155
  self._last_agent = chosen
151
156
  return chosen
@@ -171,6 +176,7 @@ class RoutingService(RoutingServiceInterface):
171
176
 
172
177
  # First, check if primary_specialization is directly an agent name
173
178
  if primary_specialization in ai_agents:
179
+ logger.debug(f"Direct agent match: {primary_specialization}")
174
180
  return primary_specialization
175
181
 
176
182
  # If not a direct agent name match, use specialization matching
@@ -185,6 +191,9 @@ class RoutingService(RoutingServiceInterface):
185
191
  or primary_specialization.lower() in agent.specialization.lower()
186
192
  ):
187
193
  score += 10
194
+ logger.debug(
195
+ f"Specialization match for {agent_id}: '{agent.specialization}' matches '{primary_specialization}'"
196
+ )
188
197
 
189
198
  # Check secondary specializations
190
199
  for sec_spec in secondary_specializations:
@@ -209,6 +218,8 @@ class RoutingService(RoutingServiceInterface):
209
218
 
210
219
  # If no match found, return first agent as fallback
211
220
  if ai_agents:
212
- return next(iter(ai_agents.keys()))
221
+ fallback_agent = next(iter(ai_agents.keys()))
222
+ logger.debug(f"No match found, using fallback agent: {fallback_agent}")
223
+ return fallback_agent
213
224
 
214
225
  return None
@@ -1,14 +0,0 @@
1
- from typing import List
2
- from pydantic import BaseModel, Field
3
-
4
-
5
- class QueryAnalysis(BaseModel):
6
- """Analysis of a user query for routing purposes."""
7
-
8
- primary_specialization: str = Field(..., description="Main specialization needed")
9
- secondary_specializations: List[str] = Field(
10
- ..., description="Other helpful specializations"
11
- )
12
- complexity_level: int = Field(..., description="Complexity level (1-5)")
13
- topics: List[str] = Field(..., description="Key topics in the query")
14
- confidence: float = Field(..., description="Confidence in the analysis")
File without changes
File without changes