solana-agent 19.0.1__tar.gz → 19.1.0__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 (35) hide show
  1. {solana_agent-19.0.1 → solana_agent-19.1.0}/PKG-INFO +57 -48
  2. {solana_agent-19.0.1 → solana_agent-19.1.0}/README.md +54 -45
  3. {solana_agent-19.0.1 → solana_agent-19.1.0}/pyproject.toml +3 -3
  4. {solana_agent-19.0.1 → solana_agent-19.1.0}/solana_agent/adapters/llm_adapter.py +0 -13
  5. {solana_agent-19.0.1 → solana_agent-19.1.0}/solana_agent/client/solana_agent.py +3 -0
  6. {solana_agent-19.0.1 → solana_agent-19.1.0}/solana_agent/factories/agent_factory.py +28 -6
  7. {solana_agent-19.0.1 → solana_agent-19.1.0}/solana_agent/interfaces/client/client.py +3 -2
  8. {solana_agent-19.0.1 → solana_agent-19.1.0}/solana_agent/interfaces/providers/llm.py +0 -5
  9. {solana_agent-19.0.1 → solana_agent-19.1.0}/solana_agent/interfaces/services/agent.py +3 -7
  10. {solana_agent-19.0.1 → solana_agent-19.1.0}/solana_agent/interfaces/services/query.py +1 -0
  11. {solana_agent-19.0.1 → solana_agent-19.1.0}/solana_agent/repositories/memory.py +42 -31
  12. {solana_agent-19.0.1 → solana_agent-19.1.0}/solana_agent/services/agent.py +5 -15
  13. {solana_agent-19.0.1 → solana_agent-19.1.0}/solana_agent/services/query.py +11 -4
  14. {solana_agent-19.0.1 → solana_agent-19.1.0}/LICENSE +0 -0
  15. {solana_agent-19.0.1 → solana_agent-19.1.0}/solana_agent/__init__.py +0 -0
  16. {solana_agent-19.0.1 → solana_agent-19.1.0}/solana_agent/adapters/__init__.py +0 -0
  17. {solana_agent-19.0.1 → solana_agent-19.1.0}/solana_agent/adapters/mongodb_adapter.py +0 -0
  18. {solana_agent-19.0.1 → solana_agent-19.1.0}/solana_agent/client/__init__.py +0 -0
  19. {solana_agent-19.0.1 → solana_agent-19.1.0}/solana_agent/domains/__init__.py +0 -0
  20. {solana_agent-19.0.1 → solana_agent-19.1.0}/solana_agent/domains/agent.py +0 -0
  21. {solana_agent-19.0.1 → solana_agent-19.1.0}/solana_agent/domains/routing.py +0 -0
  22. {solana_agent-19.0.1 → solana_agent-19.1.0}/solana_agent/factories/__init__.py +0 -0
  23. {solana_agent-19.0.1 → solana_agent-19.1.0}/solana_agent/interfaces/__init__.py +0 -0
  24. {solana_agent-19.0.1 → solana_agent-19.1.0}/solana_agent/interfaces/plugins/plugins.py +0 -0
  25. {solana_agent-19.0.1 → solana_agent-19.1.0}/solana_agent/interfaces/providers/data_storage.py +0 -0
  26. {solana_agent-19.0.1 → solana_agent-19.1.0}/solana_agent/interfaces/providers/memory.py +0 -0
  27. {solana_agent-19.0.1 → solana_agent-19.1.0}/solana_agent/interfaces/services/routing.py +0 -0
  28. {solana_agent-19.0.1 → solana_agent-19.1.0}/solana_agent/plugins/__init__.py +0 -0
  29. {solana_agent-19.0.1 → solana_agent-19.1.0}/solana_agent/plugins/manager.py +0 -0
  30. {solana_agent-19.0.1 → solana_agent-19.1.0}/solana_agent/plugins/registry.py +0 -0
  31. {solana_agent-19.0.1 → solana_agent-19.1.0}/solana_agent/plugins/tools/__init__.py +0 -0
  32. {solana_agent-19.0.1 → solana_agent-19.1.0}/solana_agent/plugins/tools/auto_tool.py +0 -0
  33. {solana_agent-19.0.1 → solana_agent-19.1.0}/solana_agent/repositories/__init__.py +0 -0
  34. {solana_agent-19.0.1 → solana_agent-19.1.0}/solana_agent/services/__init__.py +0 -0
  35. {solana_agent-19.0.1 → solana_agent-19.1.0}/solana_agent/services/routing.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: solana-agent
3
- Version: 19.0.1
3
+ Version: 19.1.0
4
4
  Summary: Agentic IQ
5
5
  License: MIT
6
6
  Keywords: ai,openai,ai agents,agi
@@ -13,8 +13,8 @@ Classifier: Programming Language :: Python :: 3.12
13
13
  Classifier: Programming Language :: Python :: 3.13
14
14
  Classifier: Programming Language :: Python :: 3 :: Only
15
15
  Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
16
- Requires-Dist: openai (>=1.68.2,<2.0.0)
17
- Requires-Dist: pydantic (>=2.10.6,<3.0.0)
16
+ Requires-Dist: openai (>=1.69.0,<2.0.0)
17
+ Requires-Dist: pydantic (>=2.11.0,<3.0.0)
18
18
  Requires-Dist: pymongo (>=4.11.3,<5.0.0)
19
19
  Requires-Dist: zep-cloud (>=2.8.0,<3.0.0)
20
20
  Requires-Dist: zep-python (>=2.0.2,<3.0.0)
@@ -35,41 +35,36 @@ Description-Content-Type: text/markdown
35
35
 
36
36
  ## Agentic IQ
37
37
 
38
- Power your business using Solana Agent!
38
+ Build your AI business in three lines of code!
39
39
 
40
- * **Brand:** AI agents will speak in your brand voice
41
- * **Expert:** The AI agent with the most expertise will answer your users' inquiries
42
- * **Extend:** Assign tools for your AI agents to perform actions
40
+ ## Why?
41
+ * Three lines of code required
42
+ * Multi-Modal Streaming
43
+ * Conversational Memory & History
44
+ * Intelligent Routing
45
+ * Business Alignment
46
+ * Extensible Tooling
47
+ * Simple Business Definition
48
+ * Tested & Secure
49
+ * Built in Python
50
+ * Deployed by [CometHeart](https://cometheart.com) & [WalletBubbles](https://walletbubbles.com)
43
51
 
44
52
  ## Features
45
53
 
46
54
  * Seamless text and audio streaming with real-time multi-modal processing
47
- * Persistent memory that preserves context across all agent interactions (optional)
55
+ * Persistent memory that preserves context across all agent interactions
56
+ * Streamlined message history for all agent interactions
48
57
  * Intelligent query routing to agents with optimal domain expertise
49
58
  * Unified value system ensuring brand-aligned agent responses
50
59
  * Powerful tool integration using standard Python packages and/or inline classes
51
60
  * Assigned tools are utilized by agents automatically and effectively
52
61
  * Simple business definition using JSON
53
62
 
54
- ## Why?
55
- * Multi-Modal Streaming
56
- * Conversational Memory
57
- * Intelligent Routing
58
- * Business Alignment
59
- * Extensible Tooling
60
- * Simple Business Definition
61
- * Built using OOP & SOLID in Python - the language of AI
62
- * Batteries Included
63
- * Small Library: ~2,000 LOC of code & ~1,200 LOC of tests
64
- * Few Dependencies
65
- * Well Tested
66
- * Used in production by [CometHeart](https://cometheart.com) and [WalletBubbles](https://walletbubbles.com)
67
-
68
63
  ## Stack
69
64
 
70
65
  * [Python](https://python.org) - Programming Language
71
66
  * [OpenAI](https://openai.com) - LLMs
72
- * [MongoDB](https://mongodb.com) - Database
67
+ * [MongoDB](https://mongodb.com) - Conversational History (optional)
73
68
  * [Zep](https://getzep.com) - Conversational Memory (optional)
74
69
 
75
70
  ## Installation
@@ -84,7 +79,7 @@ You can install Solana Agent using pip:
84
79
  from solana_agent import SolanaAgent
85
80
 
86
81
  config = {
87
- "business": {
82
+ "business": { # optional
88
83
  "mission": "To provide users with a one-stop shop for their queries.",
89
84
  "values": {
90
85
  "Friendliness": "Users must be treated fairly, openly, and with friendliness.",
@@ -95,17 +90,17 @@ config = {
95
90
  ],
96
91
  "voice": "The voice of the brand is that of a research business."
97
92
  },
98
- "mongo": {
93
+ "mongo": { # optional
99
94
  "connection_string": "mongodb://localhost:27017",
100
95
  "database": "solana_agent"
101
96
  },
102
- "openai": {
103
- "api_key": "your-openai-api-key",
104
- },
105
97
  "zep": { # optional
106
98
  "api_key": "your-zep-api-key",
107
99
  "base_url": "your-zep-base-url", # not applicable if using Zep Cloud
108
100
  },
101
+ "openai": {
102
+ "api_key": "your-openai-api-key",
103
+ },
109
104
  "agents": [
110
105
  {
111
106
  "name": "research_specialist",
@@ -136,7 +131,7 @@ Plugins like Solana Agent Kit (sakit) integrate automatically with Solana Agent.
136
131
  from solana_agent import SolanaAgent
137
132
 
138
133
  config = {
139
- "business": {
134
+ "business": { # optional
140
135
  "mission": "To provide users with a one-stop shop for their queries.",
141
136
  "values": {
142
137
  "Friendliness": "Users must be treated fairly, openly, and with friendliness.",
@@ -147,23 +142,26 @@ config = {
147
142
  ],
148
143
  "voice": "The voice of the brand is that of a research business."
149
144
  },
150
- "mongo": {
145
+ "openai": { # optional
146
+ "api_key": "your-openai-api-key",
147
+ },
148
+ "ollama": { # optional
149
+ "url": "your-ollama-url",
150
+ },
151
+ "mongo": { # optional
151
152
  "connection_string": "mongodb://localhost:27017",
152
153
  "database": "solana_agent"
153
154
  },
154
- "openai": {
155
- "api_key": "your-openai-api-key",
156
- },
157
155
  "zep": { # optional
158
156
  "api_key": "your-zep-api-key",
159
157
  "base_url": "your-zep-base-url", # not applicable if using Zep Cloud
160
158
  },
161
159
  "tools": {
162
- "search_internet": {
163
- "api_key": "your-perplexity-key", # Required
164
- "citations": True, # Optional, defaults to True
165
- "model": "sonar" # Optional, defaults to "sonar"
166
- },
160
+ "search_internet": {
161
+ "api_key": "your-perplexity-key", # Required
162
+ "citations": True, # Optional, defaults to True
163
+ "model": "sonar" # Optional, defaults to "sonar"
164
+ },
167
165
  },
168
166
  "agents": [
169
167
  {
@@ -241,7 +239,7 @@ class TestTool(Tool):
241
239
  }
242
240
 
243
241
  config = {
244
- "business": {
242
+ "business": { # optional
245
243
  "mission": "To provide users with a one-stop shop for their queries.",
246
244
  "values": {
247
245
  "Friendliness": "Users must be treated fairly, openly, and with friendliness.",
@@ -252,13 +250,16 @@ config = {
252
250
  ],
253
251
  "voice": "The voice of the brand is that of a research business."
254
252
  },
255
- "mongo": {
253
+ "openai": { # optional
254
+ "api_key": "your-openai-api-key",
255
+ },
256
+ "ollama": { # optional
257
+ "url": "your-ollama-url",
258
+ },
259
+ "mongo": { # optional
256
260
  "connection_string": "mongodb://localhost:27017",
257
261
  "database": "solana_agent"
258
262
  },
259
- "openai": {
260
- "api_key": "your-openai-api-key",
261
- },
262
263
  "zep": { # optional
263
264
  "api_key": "your-zep-api-key",
264
265
  "base_url": "your-zep-base-url", # not applicable if using Zep Cloud
@@ -287,24 +288,32 @@ async for response in solana_agent.process("user123", "What are the latest AI de
287
288
  print(response, end="")
288
289
  ```
289
290
 
290
- ## Notes on Tools
291
+ ## Notes
291
292
  * Solana Agent agents can only call one tool per response.
292
293
  * Solana Agent agents choose the best tool for the job.
293
294
  * Solana Agent tools do not use OpenAI function calling.
294
295
  * Solana Agent tools are async functions.
296
+ * Solana Agent will use OpenAI for audio and Ollama and for text if both config vars are set
297
+
298
+ ## Local Setup
299
+
300
+ A Docker Compose and Zep Config file is available at the root of this project
295
301
 
296
302
  ## API Documentation
297
- * Available at [Solana Agent Documentation Site](https://docs.solana-agent.com)
298
303
 
299
- ## Solana Agent Kit
304
+ The official up-to-date documentation site
305
+
306
+ [Solana Agent Documentation Site](https://docs.solana-agent.com)
307
+
308
+ ## Official Tools
300
309
 
301
- A collection of Solana Agent tools
310
+ The official collection of tools in one plugin
302
311
 
303
312
  [Solana Agent Kit](https://github.com/truemagic-coder/solana-agent-kit)
304
313
 
305
314
  ## Example App
306
315
 
307
- A Solana Agent example app written in FastAPI and Next.js
316
+ The official example app written in FastAPI and Next.js
308
317
 
309
318
  [Solana Agent Example App](https://github.com/truemagic-coder/solana-agent-app)
310
319
 
@@ -12,41 +12,36 @@
12
12
 
13
13
  ## Agentic IQ
14
14
 
15
- Power your business using Solana Agent!
15
+ Build your AI business in three lines of code!
16
16
 
17
- * **Brand:** AI agents will speak in your brand voice
18
- * **Expert:** The AI agent with the most expertise will answer your users' inquiries
19
- * **Extend:** Assign tools for your AI agents to perform actions
17
+ ## Why?
18
+ * Three lines of code required
19
+ * Multi-Modal Streaming
20
+ * Conversational Memory & History
21
+ * Intelligent Routing
22
+ * Business Alignment
23
+ * Extensible Tooling
24
+ * Simple Business Definition
25
+ * Tested & Secure
26
+ * Built in Python
27
+ * Deployed by [CometHeart](https://cometheart.com) & [WalletBubbles](https://walletbubbles.com)
20
28
 
21
29
  ## Features
22
30
 
23
31
  * Seamless text and audio streaming with real-time multi-modal processing
24
- * Persistent memory that preserves context across all agent interactions (optional)
32
+ * Persistent memory that preserves context across all agent interactions
33
+ * Streamlined message history for all agent interactions
25
34
  * Intelligent query routing to agents with optimal domain expertise
26
35
  * Unified value system ensuring brand-aligned agent responses
27
36
  * Powerful tool integration using standard Python packages and/or inline classes
28
37
  * Assigned tools are utilized by agents automatically and effectively
29
38
  * Simple business definition using JSON
30
39
 
31
- ## Why?
32
- * Multi-Modal Streaming
33
- * Conversational Memory
34
- * Intelligent Routing
35
- * Business Alignment
36
- * Extensible Tooling
37
- * Simple Business Definition
38
- * Built using OOP & SOLID in Python - the language of AI
39
- * Batteries Included
40
- * Small Library: ~2,000 LOC of code & ~1,200 LOC of tests
41
- * Few Dependencies
42
- * Well Tested
43
- * Used in production by [CometHeart](https://cometheart.com) and [WalletBubbles](https://walletbubbles.com)
44
-
45
40
  ## Stack
46
41
 
47
42
  * [Python](https://python.org) - Programming Language
48
43
  * [OpenAI](https://openai.com) - LLMs
49
- * [MongoDB](https://mongodb.com) - Database
44
+ * [MongoDB](https://mongodb.com) - Conversational History (optional)
50
45
  * [Zep](https://getzep.com) - Conversational Memory (optional)
51
46
 
52
47
  ## Installation
@@ -61,7 +56,7 @@ You can install Solana Agent using pip:
61
56
  from solana_agent import SolanaAgent
62
57
 
63
58
  config = {
64
- "business": {
59
+ "business": { # optional
65
60
  "mission": "To provide users with a one-stop shop for their queries.",
66
61
  "values": {
67
62
  "Friendliness": "Users must be treated fairly, openly, and with friendliness.",
@@ -72,17 +67,17 @@ config = {
72
67
  ],
73
68
  "voice": "The voice of the brand is that of a research business."
74
69
  },
75
- "mongo": {
70
+ "mongo": { # optional
76
71
  "connection_string": "mongodb://localhost:27017",
77
72
  "database": "solana_agent"
78
73
  },
79
- "openai": {
80
- "api_key": "your-openai-api-key",
81
- },
82
74
  "zep": { # optional
83
75
  "api_key": "your-zep-api-key",
84
76
  "base_url": "your-zep-base-url", # not applicable if using Zep Cloud
85
77
  },
78
+ "openai": {
79
+ "api_key": "your-openai-api-key",
80
+ },
86
81
  "agents": [
87
82
  {
88
83
  "name": "research_specialist",
@@ -113,7 +108,7 @@ Plugins like Solana Agent Kit (sakit) integrate automatically with Solana Agent.
113
108
  from solana_agent import SolanaAgent
114
109
 
115
110
  config = {
116
- "business": {
111
+ "business": { # optional
117
112
  "mission": "To provide users with a one-stop shop for their queries.",
118
113
  "values": {
119
114
  "Friendliness": "Users must be treated fairly, openly, and with friendliness.",
@@ -124,23 +119,26 @@ config = {
124
119
  ],
125
120
  "voice": "The voice of the brand is that of a research business."
126
121
  },
127
- "mongo": {
122
+ "openai": { # optional
123
+ "api_key": "your-openai-api-key",
124
+ },
125
+ "ollama": { # optional
126
+ "url": "your-ollama-url",
127
+ },
128
+ "mongo": { # optional
128
129
  "connection_string": "mongodb://localhost:27017",
129
130
  "database": "solana_agent"
130
131
  },
131
- "openai": {
132
- "api_key": "your-openai-api-key",
133
- },
134
132
  "zep": { # optional
135
133
  "api_key": "your-zep-api-key",
136
134
  "base_url": "your-zep-base-url", # not applicable if using Zep Cloud
137
135
  },
138
136
  "tools": {
139
- "search_internet": {
140
- "api_key": "your-perplexity-key", # Required
141
- "citations": True, # Optional, defaults to True
142
- "model": "sonar" # Optional, defaults to "sonar"
143
- },
137
+ "search_internet": {
138
+ "api_key": "your-perplexity-key", # Required
139
+ "citations": True, # Optional, defaults to True
140
+ "model": "sonar" # Optional, defaults to "sonar"
141
+ },
144
142
  },
145
143
  "agents": [
146
144
  {
@@ -218,7 +216,7 @@ class TestTool(Tool):
218
216
  }
219
217
 
220
218
  config = {
221
- "business": {
219
+ "business": { # optional
222
220
  "mission": "To provide users with a one-stop shop for their queries.",
223
221
  "values": {
224
222
  "Friendliness": "Users must be treated fairly, openly, and with friendliness.",
@@ -229,13 +227,16 @@ config = {
229
227
  ],
230
228
  "voice": "The voice of the brand is that of a research business."
231
229
  },
232
- "mongo": {
230
+ "openai": { # optional
231
+ "api_key": "your-openai-api-key",
232
+ },
233
+ "ollama": { # optional
234
+ "url": "your-ollama-url",
235
+ },
236
+ "mongo": { # optional
233
237
  "connection_string": "mongodb://localhost:27017",
234
238
  "database": "solana_agent"
235
239
  },
236
- "openai": {
237
- "api_key": "your-openai-api-key",
238
- },
239
240
  "zep": { # optional
240
241
  "api_key": "your-zep-api-key",
241
242
  "base_url": "your-zep-base-url", # not applicable if using Zep Cloud
@@ -264,24 +265,32 @@ async for response in solana_agent.process("user123", "What are the latest AI de
264
265
  print(response, end="")
265
266
  ```
266
267
 
267
- ## Notes on Tools
268
+ ## Notes
268
269
  * Solana Agent agents can only call one tool per response.
269
270
  * Solana Agent agents choose the best tool for the job.
270
271
  * Solana Agent tools do not use OpenAI function calling.
271
272
  * Solana Agent tools are async functions.
273
+ * Solana Agent will use OpenAI for audio and Ollama and for text if both config vars are set
274
+
275
+ ## Local Setup
276
+
277
+ A Docker Compose and Zep Config file is available at the root of this project
272
278
 
273
279
  ## API Documentation
274
- * Available at [Solana Agent Documentation Site](https://docs.solana-agent.com)
275
280
 
276
- ## Solana Agent Kit
281
+ The official up-to-date documentation site
282
+
283
+ [Solana Agent Documentation Site](https://docs.solana-agent.com)
284
+
285
+ ## Official Tools
277
286
 
278
- A collection of Solana Agent tools
287
+ The official collection of tools in one plugin
279
288
 
280
289
  [Solana Agent Kit](https://github.com/truemagic-coder/solana-agent-kit)
281
290
 
282
291
  ## Example App
283
292
 
284
- A Solana Agent example app written in FastAPI and Next.js
293
+ The official example app written in FastAPI and Next.js
285
294
 
286
295
  [Solana Agent Example App](https://github.com/truemagic-coder/solana-agent-app)
287
296
 
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "solana-agent"
3
- version = "19.0.1"
3
+ version = "19.1.0"
4
4
  description = "Agentic IQ"
5
5
  authors = ["Bevan Hunt <bevan@bevanhunt.com>"]
6
6
  license = "MIT"
@@ -18,8 +18,8 @@ python_paths = [".", "tests"]
18
18
 
19
19
  [tool.poetry.dependencies]
20
20
  python = ">=3.12,<4.0"
21
- openai = "^1.68.2"
22
- pydantic = "^2.10.6"
21
+ openai = "^1.69.0"
22
+ pydantic = "^2.11.0"
23
23
  pymongo = "^4.11.3"
24
24
  zep-cloud = "^2.8.0"
25
25
  zep-python = "^2.0.2"
@@ -135,19 +135,6 @@ class OpenAIAdapter(LLMProvider):
135
135
  print(traceback.format_exc())
136
136
  yield f"I apologize, but I encountered an error: {str(e)}"
137
137
 
138
- def generate_embedding(self, text: str) -> List[float]: # pragma: no cover
139
- """Generate embeddings for a given text using OpenAI's embedding model."""
140
- try:
141
- response = self.client.embeddings.create(
142
- model="text-embedding-3-small",
143
- input=text
144
- )
145
- return response.data[0].embedding
146
- except Exception as e:
147
- print(f"Error generating embedding: {e}")
148
- # Return a zero vector as fallback (not ideal but prevents crashing)
149
- return [0.0] * 1536 # Standard size for text-embedding-3-small
150
-
151
138
  async def parse_structured_output(
152
139
  self,
153
140
  prompt: str,
@@ -44,6 +44,7 @@ class SolanaAgent(SolanaAgentInterface):
44
44
  self,
45
45
  user_id: str,
46
46
  message: Union[str, bytes],
47
+ prompt: Optional[str] = None,
47
48
  output_format: Literal["text", "audio"] = "text",
48
49
  audio_voice: Literal["alloy", "ash", "ballad", "coral", "echo",
49
50
  "fable", "onyx", "nova", "sage", "shimmer"] = "nova",
@@ -59,6 +60,7 @@ class SolanaAgent(SolanaAgentInterface):
59
60
  Args:
60
61
  user_id: User ID
61
62
  message: Text message or audio bytes
63
+ prompt: Optional prompt for the agent
62
64
  output_format: Response format ("text" or "audio")
63
65
  audio_voice: Voice to use for audio output
64
66
  audio_instructions: Optional instructions for audio synthesis
@@ -76,6 +78,7 @@ class SolanaAgent(SolanaAgentInterface):
76
78
  audio_instructions=audio_instructions,
77
79
  audio_output_format=audio_output_format,
78
80
  audio_input_format=audio_input_format,
81
+ prompt=prompt,
79
82
  ):
80
83
  yield chunk
81
84
 
@@ -37,10 +37,19 @@ class SolanaAgentFactory:
37
37
  Configured QueryService instance
38
38
  """
39
39
  # Create adapters
40
- db_adapter = MongoDBAdapter(
41
- connection_string=config["mongo"]["connection_string"],
42
- database_name=config["mongo"]["database"],
43
- )
40
+
41
+ if "mongo" in config:
42
+ # MongoDB connection string and database name
43
+ if "connection_string" not in config["mongo"]:
44
+ raise ValueError("MongoDB connection string is required.")
45
+ if "database" not in config["mongo"]:
46
+ raise ValueError("MongoDB database name is required.")
47
+ db_adapter = MongoDBAdapter(
48
+ connection_string=config["mongo"]["connection_string"],
49
+ database_name=config["mongo"]["database"],
50
+ )
51
+ else:
52
+ db_adapter = None
44
53
 
45
54
  llm_adapter = OpenAIAdapter(
46
55
  api_key=config["openai"]["api_key"],
@@ -59,12 +68,25 @@ class SolanaAgentFactory:
59
68
  )
60
69
 
61
70
  # Create repositories
62
- if "zep" in config:
71
+ memory_provider = None
72
+
73
+ if "zep" in config and "mongo" in config:
74
+ if "api_key" not in config["zep"]:
75
+ raise ValueError("Zep API key is required.")
63
76
  memory_provider = MemoryRepository(
64
77
  db_adapter, config["zep"].get("api_key"), config["zep"].get("base_url"))
65
- else:
78
+
79
+ if "mongo" in config and not "zep" in config:
66
80
  memory_provider = MemoryRepository(db_adapter)
67
81
 
82
+ if "zep" in config and not "mongo" in config:
83
+ if "api_key" not in config["zep"]:
84
+ raise ValueError("Zep API key is required.")
85
+ memory_provider = MemoryRepository(
86
+ zep_api_key=config["zep"].get("api_key"),
87
+ zep_base_url=config["zep"].get("base_url")
88
+ )
89
+
68
90
  # Create primary services
69
91
  agent_service = AgentService(
70
92
  llm_provider=llm_adapter,
@@ -1,5 +1,5 @@
1
1
  from abc import ABC, abstractmethod
2
- from typing import Any, AsyncGenerator, Dict, Literal, Union
2
+ from typing import Any, AsyncGenerator, Dict, Literal, Optional, Union
3
3
 
4
4
  from solana_agent.interfaces.plugins.plugins import Tool
5
5
 
@@ -15,12 +15,13 @@ class SolanaAgent(ABC):
15
15
  output_format: Literal["text", "audio"] = "text",
16
16
  audio_voice: Literal["alloy", "ash", "ballad", "coral", "echo",
17
17
  "fable", "onyx", "nova", "sage", "shimmer"] = "nova",
18
- audio_instructions: str = None,
18
+ audio_instructions: Optional[str] = None,
19
19
  audio_output_format: Literal['mp3', 'opus',
20
20
  'aac', 'flac', 'wav', 'pcm'] = "aac",
21
21
  audio_input_format: Literal[
22
22
  "flac", "mp3", "mp4", "mpeg", "mpga", "m4a", "ogg", "wav", "webm"
23
23
  ] = "mp4",
24
+ prompt: Optional[str] = None,
24
25
  ) -> AsyncGenerator[Union[str, bytes], None]:
25
26
  """Process a user message and return the response stream."""
26
27
  pass
@@ -19,11 +19,6 @@ class LLMProvider(ABC):
19
19
  """Generate text from the language model."""
20
20
  pass
21
21
 
22
- @abstractmethod
23
- def generate_embedding(self, text: str) -> List[float]:
24
- """Generate embedding vector for text."""
25
- pass
26
-
27
22
  @abstractmethod
28
23
  async def parse_structured_output(
29
24
  self, prompt: str, system_prompt: str, model_class: Type[T],
@@ -1,5 +1,5 @@
1
1
  from abc import ABC, abstractmethod
2
- from typing import Any, AsyncGenerator, Dict, List, Literal, Union
2
+ from typing import Any, AsyncGenerator, Dict, List, Literal, Optional, Union
3
3
 
4
4
  from solana_agent.domains.agent import AIAgent
5
5
 
@@ -17,11 +17,6 @@ class AgentService(ABC):
17
17
  """Get the system prompt for an agent."""
18
18
  pass
19
19
 
20
- @abstractmethod
21
- def get_specializations(self) -> Dict[str, str]:
22
- """Get all registered specializations."""
23
- pass
24
-
25
20
  @abstractmethod
26
21
  async def generate_response(
27
22
  self,
@@ -32,12 +27,13 @@ class AgentService(ABC):
32
27
  output_format: Literal["text", "audio"] = "text",
33
28
  audio_voice: Literal["alloy", "ash", "ballad", "coral", "echo",
34
29
  "fable", "onyx", "nova", "sage", "shimmer"] = "nova",
35
- audio_instructions: str = None,
30
+ audio_instructions: Optional[str] = None,
36
31
  audio_output_format: Literal['mp3', 'opus',
37
32
  'aac', 'flac', 'wav', 'pcm'] = "aac",
38
33
  audio_input_format: Literal[
39
34
  "flac", "mp3", "mp4", "mpeg", "mpga", "m4a", "ogg", "wav", "webm"
40
35
  ] = "mp4",
36
+ prompt: Optional[str] = None,
41
37
  ) -> AsyncGenerator[Union[str, bytes], None]:
42
38
  """Generate a response from an agent."""
43
39
  pass
@@ -19,6 +19,7 @@ class QueryService(ABC):
19
19
  audio_input_format: Literal[
20
20
  "flac", "mp3", "mp4", "mpeg", "mpga", "m4a", "ogg", "wav", "webm"
21
21
  ] = "mp4",
22
+ prompt: Optional[str] = None,
22
23
  ) -> AsyncGenerator[Union[str, bytes], None]:
23
24
  """Process the user request and generate a response."""
24
25
  pass
@@ -12,19 +12,23 @@ class MemoryRepository(MemoryProvider):
12
12
 
13
13
  def __init__(
14
14
  self,
15
- mongo_adapter: MongoDBAdapter,
15
+ mongo_adapter: Optional[MongoDBAdapter] = None,
16
16
  zep_api_key: Optional[str] = None,
17
17
  zep_base_url: Optional[str] = None
18
18
  ):
19
19
  """Initialize the combined memory provider."""
20
- # Initialize MongoDB
21
- self.mongo = mongo_adapter
22
- self.collection = "conversations"
20
+ if not mongo_adapter:
21
+ self.mongo = None
22
+ self.collection = None
23
+ else:
24
+ # Initialize MongoDB
25
+ self.mongo = mongo_adapter
26
+ self.collection = "conversations"
23
27
 
24
- # Ensure MongoDB collection and indexes
25
- self.mongo.create_collection(self.collection)
26
- self.mongo.create_index(self.collection, [("user_id", 1)])
27
- self.mongo.create_index(self.collection, [("timestamp", 1)])
28
+ # Ensure MongoDB collection and indexes
29
+ self.mongo.create_collection(self.collection)
30
+ self.mongo.create_index(self.collection, [("user_id", 1)])
31
+ self.mongo.create_index(self.collection, [("timestamp", 1)])
28
32
 
29
33
  # Initialize Zep
30
34
  if zep_api_key and not zep_base_url:
@@ -37,22 +41,23 @@ class MemoryRepository(MemoryProvider):
37
41
  async def store(self, user_id: str, messages: List[Dict[str, Any]]) -> None:
38
42
  """Store messages in both Zep and MongoDB."""
39
43
  # Store in MongoDB as single document
40
- try:
41
- # Extract user and assistant messages
42
- user_message = next(msg["content"]
43
- for msg in messages if msg["role"] == "user")
44
- assistant_message = next(
45
- msg["content"] for msg in messages if msg["role"] == "assistant")
46
-
47
- doc = {
48
- "user_id": user_id,
49
- "user_message": user_message,
50
- "assistant_message": assistant_message,
51
- "timestamp": datetime.now(timezone.utc)
52
- }
53
- self.mongo.insert_one(self.collection, doc)
54
- except Exception as e:
55
- print(f"MongoDB storage error: {e}")
44
+ if self.mongo:
45
+ try:
46
+ # Extract user and assistant messages
47
+ user_message = next(msg["content"]
48
+ for msg in messages if msg["role"] == "user")
49
+ assistant_message = next(
50
+ msg["content"] for msg in messages if msg["role"] == "assistant")
51
+
52
+ doc = {
53
+ "user_id": user_id,
54
+ "user_message": user_message,
55
+ "assistant_message": assistant_message,
56
+ "timestamp": datetime.now(timezone.utc)
57
+ }
58
+ self.mongo.insert_one(self.collection, doc)
59
+ except Exception as e:
60
+ print(f"MongoDB storage error: {e}")
56
61
 
57
62
  # Store in Zep with role-based format
58
63
  if not self.zep:
@@ -99,13 +104,14 @@ class MemoryRepository(MemoryProvider):
99
104
 
100
105
  async def delete(self, user_id: str) -> None:
101
106
  """Delete memory from both systems."""
102
- try:
103
- self.mongo.delete_all(
104
- self.collection,
105
- {"user_id": user_id}
106
- )
107
- except Exception as e:
108
- print(f"MongoDB deletion error: {e}")
107
+ if self.mongo:
108
+ try:
109
+ self.mongo.delete_all(
110
+ self.collection,
111
+ {"user_id": user_id}
112
+ )
113
+ except Exception as e:
114
+ print(f"MongoDB deletion error: {e}")
109
115
 
110
116
  if not self.zep:
111
117
  return
@@ -125,9 +131,14 @@ class MemoryRepository(MemoryProvider):
125
131
  skip: int = 0
126
132
  ) -> List[Dict]:
127
133
  """Find documents matching query."""
134
+ if not self.mongo:
135
+ return []
128
136
  return self.mongo.find(collection, query, sort=sort, limit=limit, skip=skip)
129
137
 
130
138
  def count_documents(self, collection: str, query: Dict) -> int:
139
+ """Count documents matching query."""
140
+ if not self.mongo:
141
+ return 0
131
142
  return self.mongo.count_documents(collection, query)
132
143
 
133
144
  def _truncate(self, text: str, limit: int = 2500) -> str:
@@ -108,20 +108,6 @@ class AgentService(AgentServiceInterface):
108
108
  """
109
109
  return {agent.name: agent for agent in self.agents}
110
110
 
111
- def get_specializations(self) -> Dict[str, str]:
112
- """Get all registered specializations.
113
-
114
- Returns:
115
- Dictionary mapping specialization names to descriptions
116
- """
117
- specializations = {}
118
-
119
- for agent in self.agents:
120
- if agent.specialization:
121
- specializations[agent.specialization] = f"AI expertise in {agent.specialization}"
122
-
123
- return specializations
124
-
125
111
  def assign_tool_for_agent(self, agent_name: str, tool_name: str) -> bool:
126
112
  """Assign a tool to an agent.
127
113
 
@@ -187,6 +173,7 @@ class AgentService(AgentServiceInterface):
187
173
  audio_input_format: Literal[
188
174
  "flac", "mp3", "mp4", "mpeg", "mpga", "m4a", "ogg", "wav", "webm"
189
175
  ] = "mp4",
176
+ prompt: Optional[str] = None,
190
177
  ) -> AsyncGenerator[Union[str, bytes], None]: # pragma: no cover
191
178
  """Generate a response with support for text/audio input/output.
192
179
 
@@ -200,6 +187,7 @@ class AgentService(AgentServiceInterface):
200
187
  audio_instructions: Optional instructions for audio synthesis
201
188
  audio_output_format: Audio output format
202
189
  audio_input_format: Audio input format
190
+ prompt: Optional prompt for the agent
203
191
 
204
192
  Yields:
205
193
  Text chunks or audio bytes depending on output_format
@@ -233,7 +221,9 @@ class AgentService(AgentServiceInterface):
233
221
  # Add User ID and memory context
234
222
  system_prompt += f"\n\nUser ID: {user_id}"
235
223
  if memory_context:
236
- system_prompt += f"\n\nMemory Context: {memory_context}"
224
+ system_prompt += f"\n\nMEMORY CONTEXT: {memory_context}"
225
+ if prompt:
226
+ system_prompt += f"\n\nADDITIONAL PROMPT: {prompt}"
237
227
 
238
228
  # Keep track of the complete text response
239
229
  complete_text_response = ""
@@ -46,14 +46,19 @@ class QueryService(QueryServiceInterface):
46
46
  audio_input_format: Literal[
47
47
  "flac", "mp3", "mp4", "mpeg", "mpga", "m4a", "ogg", "wav", "webm"
48
48
  ] = "mp4",
49
+ prompt: Optional[str] = None,
49
50
  ) -> AsyncGenerator[Union[str, bytes], None]: # pragma: no cover
50
51
  """Process the user request with appropriate agent.
51
52
 
52
53
  Args:
53
54
  user_id: User ID
54
55
  query: Text query or audio bytes
55
- output_format: Response format ("text" or "audio")
56
- voice: Voice to use for audio output
56
+ output_format: Response format ("text" or "audio")
57
+ audio_voice: Voice for TTS (text-to-speech)
58
+ audio_instructions: Optional instructions for TTS
59
+ audio_output_format: Audio output format
60
+ audio_input_format: Audio input format
61
+ prompt: Optional prompt for the agent
57
62
 
58
63
  Yields:
59
64
  Response chunks (text strings or audio bytes)
@@ -105,7 +110,8 @@ class QueryService(QueryServiceInterface):
105
110
  audio_voice=audio_voice,
106
111
  audio_input_format=audio_input_format,
107
112
  audio_output_format=audio_output_format,
108
- audio_instructions=audio_instructions
113
+ audio_instructions=audio_instructions,
114
+ prompt=prompt,
109
115
  ):
110
116
  yield audio_chunk
111
117
 
@@ -122,7 +128,8 @@ class QueryService(QueryServiceInterface):
122
128
  user_id=user_id,
123
129
  query=user_text,
124
130
  memory_context=memory_context,
125
- output_format="text"
131
+ output_format="text",
132
+ prompt=prompt,
126
133
  ):
127
134
  yield chunk
128
135
  full_text_response += chunk
File without changes